Difference between revisions of "Splatoon 2/Save"

From Deep Sea Knowledge
Jump to navigation Jump to search
(Updated octoling struct)
(save.dat file structure)
Line 652: Line 652:
 
| 4
 
| 4
 
| Octoling PlayerModelType (Gender, basically)
 
| Octoling PlayerModelType (Gender, basically)
| 2: Female Veemo| 2: Male Veemo
+
| |2: Female Veemo| 3: Male Veemo
 
|-
 
|-
 
| 0x284D4
 
| 0x284D4

Revision as of 04:56, 27 October 2018

Splatoon 2 saves its data in save.dat.

Tools

  • SplatHeX: a full fledged save editor for Windows.
  • Splatsave: an open source program that decrypts and re-encrypts save.dat.

Revisions

Since release, there has been 5 revisions to this file:

Ver Added On Save Size Description
0 1.0.0 0x483B0 Original shipped version, saves in plain text.
1 1.1.0 0x483E0 Introduced encryption. Added in day 1 patch.
2 2.3.0 0x86840 Added Stats Data (SaveDataStats)
3 3.0.0 0x88D90 Added Octo Expansion Data (SaveDataMsnOcta). Introduced new key look-up table.
4 4.0.0 0x88D90 Introduced save body shuffle. Introduced new key look-up table. Content is the same as Ver 3

Encoding

The encoding process takes place in Cmn::SaveDataFactory::encode. The decoding process takes place in Cmn::SaveDataFactory::decode.

The encryption used on the save body is AES-128 CBC. The key is generated using a sead::Random object initialized from a 16 byte seed stored in the save footer, in which also stores the initialization vector and the CMAC for authentication. The CMAC key is generated from the same sead::Random object after the encryption key.

The shuffling for save body takes place after it is encrypted. The game constructs a new sead::Random object initialized with the CRC32 from the save header. It then uses this to generate block sizes larger than 1/16 of body size and smaller than 1/8 of body size (or total remaining size, in case the remaining size is smaller than 1/8 of body size). When the remaining size is smaller than 1/16 of body size, it is added as the size of the last block. The game then uses sead::PtrArrayImpl::shuffle with the same sead::Random object to complete the shuffle.

save.dat file structure

Save Header:

Offset Size Description Value
0x0 4 (Save Version) 0, 1, 2, 3 or 4, etc
0x4 4 (Dev Save Version?)
0x8 4 crc32 of save body (everything between header and footer) DEADBEAF
0xC 4 (Padding) 0

Save Body Structure

Offset Absolute Offset Size Description
0x0 0x10 0x2B210 SaveDataCmn
0x2B210 0x2B220 0xC750 SaveDataVss
0x37960 0x37970 0x33E8 SaveDataLocal
0x3AD48 0x3AD58 0x5E78 SaveDataMsn
0x40BC0 0x40BD0 0x2D00 SaveDataShop
0x438C0 0x438D0 0x49C0 SaveDataCoop
0x48280 0x48290 0x11C SaveDataFest
0x4839C 0x483AC 0x3E460 SaveDataStats
0x867FC 0x8680C 0x2544 SaveDataMsnOcta

SaveDataCmn(0x10):

Offset Absolute Offset Size Description Value
0x0 0x10 4 Inkling PlayerModelType (Gender, basically) 0: Woomy | 1: Ngyes | 6: Story Octoling (Rev 0 and 1 only)
0x4 0x14 4 Inkling PlayerHairId See Mush/HairInfo.byml
0x8 0x18 4 Inkling PlayerBottomId See Mush/BottomInfo.byml
0xC 0x1C 4 Inkling PlayerSkinColorId 0 to 6, 0 being lightest and 6 darkest
0x10 0x20 4 Inkling PlayerEyeColorId 0 to 13, each value represents a color
0x14 0x24 4 Weapon (Equipped Main Weapon Id) See Mush/WeaponInfo_Main.byml
0x18 0x28 4 Weapon (Equipped Sub Weapon Id) See Mush/WeaponInfo_Sub.byml
0x1C 0x2C 4 Weapon (Equipped Special Weapon Id) See Mush/WeaponInfo_Special.byml
0x20 0x30 4 Weapon (Equipped Weapon Turf inked) 1234567
0x24 0x34 4 unk (padding?) 0?

Weapon Inventory part:

Offset Absolute Offset Size of Each Entry (HaveWeapon) Total Size Description
0x28 0x38 0x130 0x13000 (Weapon Inventory)

Structure of Entry (HaveWeapon)

Offset Size Description Value
0x0 4 Weapon (WeaponMain id) See Mush/WeaponInfo_Main.byml
0x4 4 Weapon (WeaponSub id) See Mush/WeaponInfo_Sub.byml
0x8 4 Weapon (WeaponSp id) See Mush/WeaponInfo_Special.byml
0xC 4 Weapon (Turf inked) 1234567
0x10 0x8 Last Time Equipped UNIX Epoch time
0x18 0x4 Freshness Level 3
0x1C 0x4 Flag Color
0x20 0x108 unk (Some weird block, likely represents various flags) A buncha 0x55555555, bit flipped to 0xAAAAAAAA at some places
0x128 4 (New or not) 0 = new, 1 = not new
0x12C 4 unk (padding?) 0?

SaveDataCmn (Cont'd):

Offset Absolute Offset Size Description Value
0x13028 0x13038 4 Equipped Shoe Id See Mush/GearInfo_Shoes.byml
0x1302C 0x1303C 4 Equipped Clothes Id See Mush/GearInfo_Clothes.byml
0x13030 0x13040 4 Equipped HeadGear Id See Mush/GearInfo_Head.byml
0x13034 0x13044 4 unk (padding?) 0?

Gear Inventory part:

Offset Absolute Offset Size of Each Entry (HaveGear) Total Size Description
0x13038 0x13048 0x30 0x6000 (Shoe Inventory)
0x19038 0x19048 0x30 0x6000 (Clothes Inventory)
0x1F038 0x1F048 0x30 0x6000 (HeadGearInventory)

Structure of Entry (HaveGear):

Offset Size Description Value
0x0 4 (Gear id) See GearInfo_XXXX.byml
0x4 4 Gear Level (Total # of unlocked abilities - including main slot) 1, 2, 3, or 4
0x8 4 Gear Slots Unlocked (Total # of ability slots - including main slot) 1, 2, 3, or 4
0xC 4 Main slot ability id See SkillInfo.byml
0x10 4 Sub slot#1 ability id See SkillInfo.byml
0x14 4 Sub slot#2 ability id See SkillInfo.byml
0x18 4 Sub slot#3 ability id See SkillInfo.byml
0x1C 4 Current Experience Value between 0 and [maxexp -1]
0x20 0x8 Last Time Equipped UNIX Epoch time
0x28 4 (New or not) 0 = new, 1 = not new
0x2C 4 unk (padding?) 0?

SkillChip (Ability Chuncks) Inventory part:

Offset Absolute Offset Size of Each Entry (HaveSkillChip) Total Size Description
0x25038 0x25048 0x8 0x200 (SkillChip (a.k.a. Ability Chuncks) Inventory)

Structure of Entry (HaveSkillChip):

Offset Size Description Value
0x0 4 Skill ID See SkillInfo.byml
0x4 4 Skill chip amount 696

BoostTicket (Crusty Sean) Inventory part:

Offset Absolute Offset Size of Each Entry (HaveBoostTicket) Total Size Description
0x25238 0x25248 0xC 0x300 (BoostTicket Inventory)

Structure of Entry (HaveBoostTicket):

Offset Size Description Value
0x0 4 Type ID 0 = +50% Exp, 1 = +100% Exp, 2 = +50% Money, 3 = +100% Money, 4 = Skill Drink, 5 = +150% Exp, 6 = +150% Money
0x4 4 Boosted skill id for drinks (-1 for food tickets) See SkillInfo.byml
0xC 4 Ticket amount 69

SaveDataCmn (Cont'd):

Offset Absolute Offset Size Description Value
0x25538 0x25548 4 TutorialResult 0 for not seen tutorial, > 0 for seen tutorial?
0x2553C 0x2554C 0x4 CtrlOption (Handheld Stick) Float, 1.0 for +5, -1.0 for -5
0x25540 0x25550 0x4 CtrlOption (Handheld Motion) Float, 1.0 for +5, -1.0 for -5
0x25544 0x25554 0x1 CtrlOption (Handheld motion ctrl flag) 1 for enabled
0x25545 0x25555 0x1 CtrlOption (Handheld motion invert Y-axis) 1 for enabled
0x25546 0x25556 0x1 CtrlOption (Handheld motion invert X-axis) 1 for enabled
0x25547 0x25557 0x41 CtrlOption (unk) A buncha 0s?
0x25588 0x25598 0x4 CtrlOption (TV/Tabletop Stick) Float, 1.0 for +5, -1.0 for -5
0x2558C 0x2559C 0x4 CtrlOption (TV/Tabletop Motion) Float, 1.0 for +5, -1.0 for -5
0x25590 0x255A0 0x1 CtrlOption (TV/Tabletop motion ctrl flag) 1 for enabled
0x25591 0x255A1 0x1 CtrlOption (TV/Tabletop invert Y-axis) 1 for enabled
0x25592 0x255A2 0x1 CtrlOption (TV/Tabletop invert X-axis) 1 for enabled
0x25593 0x255A3 0x41 CtrlOption (unk) A buncha 0s?
0x255D4 0x255E4 0x10 OnlinePlayPenalty (4 values) Haven't looked into yet
0x255E8 0x255F8 0x8 OnlinePlayPenalty Time (penalty end time) UNIX Epoch time
0x255F0 0x25600 0x188 unk (Haven't looked into yet)
0x25778 0x25788 4 HaveMoney 9696969
0x2577C 0x2578C 4 HaveTurbanShell (Sea snails) 969
0x25780 0x25790 0x108 unk (Haven't looked into yet)
0x25888 0x25898 8 Time (time of save?) UNIX Epoch time
0x25890 0x258A0 0x54 unk (Haven't looked into yet)
0x258E4 0x258F4 0x1 Color Lock 1 for enabled
0x258E5 0x258F5 0x1 Cococnut Post Display 1 for enabled
0x258E6 0x258F6 0x2BEA unk (Haven't looked into yet)
0x284D0 0x284E0 4 Octoling PlayerModelType (Gender, basically) 2: Female Veemo| 3: Male Veemo
0x284D4 0x284E4 4 Octoling PlayerHairId See Mush/HairInfo.byml
0x284D8 0x284E8 4 Octoling PlayerBottomId See Mush/BottomInfo.byml
0x284DC 0x284EC 4 Octoling PlayerSkinColorId 0 to 6, 0 being lightest and 6 darkest
0x284E0 0x284F0 4 Octoling PlayerEyeColorId 0 to 13, each value represents a color
0x284E4 0x284F4 4 Is Octoling 1 if yes
0x258E6 0x258F6 0x2D2C unk (Haven't looked into yet)

SaveDataVss(0x2B220):

Offset Absolute Offset Size Description Value
0x0 0x2B220 4 PlayerRank (Not rank, but level. They call it rank in the code.) Looks like level 1 is `0` and level 2 is `1`, etc)
0x4 0x2B224 4 Experience To be filled in
0x8 0x2B228 4 StarRank To be filled in
0x14 0x2B234 4 (TicketBoostRemaining) 20
0x8768 0x33988 4 (X Power Rainmaker) 2770.2 (Float)
0x87B0 0x339D0 4 (X Power Splatzone) 2809.7 (Float)
0x87F8 0x33A18 4 (X Power Tower Control) 2801.4 (Float)
0x8840 0x33A60 4 (X Power Clam Blitz) 2797.1 (Float)

SaveDataLocal(0x37970):


SaveDataMsn(0x3AD58):

Offset Absolute Offset Size Description Value
0x1E6C 0x3CBC4 4 (HeroModePowerOrb) 6969
0x1E70 0x3CBC8 4 (MechanicalFish) 69

SaveDataShop(0x40BD0):


SaveDataCoop(0x438D0?):


More to be added here...


Save Footer:
Used for save crypto (as of ver 4)

Offset Size Description
EOF-0x30 0x10 IV (initialization vector)
EOF-0x20 0x10 Key Seed
EOF-0x10 0x10 AES-CMAC