Difference between revisions of "Splatoon 2/Save"

From Deep Sea Knowledge
Jump to navigation Jump to search
(add additional note about shuffle in rev 7)
Line 72: Line 72:
 
by <code>Cmn::SaveDataFactory::Impl::IEncodedAllAccessor::createKey</code>.
 
by <code>Cmn::SaveDataFactory::Impl::IEncodedAllAccessor::createKey</code>.
  
The shuffling for save body takes place after it is encrypted. The game  
+
The shuffling for save body takes place after it is encrypted. In revision 7, a shuffle is done before encryption as well. The game  
 
constructs a new <code>sead::Random</code> object initialized with the CRC32  
 
constructs a new <code>sead::Random</code> object initialized with the CRC32  
 
from the save header. It then uses this to generate block sizes larger than  
 
from the save header. It then uses this to generate block sizes larger than  

Revision as of 11:46, 5 December 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 7 revisions to this file:

Version 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 and new key look-up table. Content is the same as Ver 3.
5 4.2.0 0x88D90 Same look-up table as Ver 4, but removed shuffling. Content is still the same as Ver 3.
6 4.3.0 0x88D90 Internal version. Does not appear in actual saved files. Mostly likely it's the same encoding as before but converted added abilities.
7 4.3.0 0x88D90 Introduced new look-up table and now shuffles twice, before and after encryption. Content is presumably still 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 key is generated by Cmn::SaveDataFactory::Impl::IEncodedAllAccessor::createKey.

The shuffling for save body takes place after it is encrypted. In revision 7, a shuffle is done before encryption as well. 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.

File Structure

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

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

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 Chunks) Inventory part:

Offset Absolute Offset Size of Each Entry (HaveSkillChip) Total Size Description
0x25038 0x25048 0x8 0x200 (SkillChip (a.k.a. Ability Chunks) 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 Coconut 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
0x284F8 0x284F8 0x2D2C unk (Haven't looked into yet)

SaveDataVss

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
0x18 0x2B238 4 Rainmaker rank 0 = C-, 1 = C, 2 = C+, etc
0x24 0x2B244 4 Splat Zones rank See above
0x30 0x2B250 4 Tower Control rank See above
0x3C 0x2B25C 4 Clam Blitz rank See above
0x60 0x2B280 4 Turf War MMR/Power 1969.6 (Float)
0x64 0x2B284 4 Turf War Glicko2 rating deviation 69.6 (Float)
0x68 0x2B288 4 Turf War Glicko2 volatility 0.06 (Float)
0x6C 0x2B28C 4 Turf War calculation state (?) 1
0x70 0x2B290 4 Rainmaker MMR/Power 1969.6 (Float)
0x74 0x2B294 4 Rainmaker Glicko2 rating deviation 69.6 (Float)
0x78 0x2B298 4 Rainmaker Glicko2 volatility 0.06 (Float)
0x7C 0x2B29C 4 Rainmaker calculation state (?) 1
0x80 0x2B2A0 4 Splat Zones MMR/Power 1969.6 (Float)
0x84 0x2B2A4 4 Splat Zones Glicko2 rating deviation 69.6 (Float)
0x88 0x2B2A8 4 Splat Zones Glicko2 volatility 0.06 (Float)
0x8C 0x2B2AC 4 Splat Zones calculation state (?) 1
0x90 0x2B2B0 4 Tower Control MMR/Power 1969.6 (Float)
0x94 0x2B2B4 4 Tower Control Glicko2 rating deviation 69.6 (Float)
0x98 0x2B2B8 4 Tower Control Glicko2 volatility 0.06 (Float)
0x9C 0x2B2BC 4 Tower Control calculation state (?) 1
0xA0 0x2B2C0 4 Clam Blitz MMR/Power 1969.6 (Float)
0xA4 0x2B2C4 4 Clam Blitz Glicko2 rating deviation 69.6 (Float)
0xA8 0x2B2C8 4 Clam Blitz Glicko2 volatility 0.06 (Float)
0xAC 0x2B2CC 4 Tower Control calculation state (?) 1
0x260 0x2B480 0x2800 Pair League Battle results TagScore Array (32)
0x2A60 0x2DC80 0x2800 Team League Battle results TagScore Array (32)
0x5260 0x30480 0x2C0 ??? LeagueScore Array (8)
0x5520 0x30740 0x2C0 ??? LeagueScore Array (8)
0x57E0 0x30A00 0x2C0 ??? LeagueScore Array (8)
0x5AA0 0x30CC0 0x2C0 ??? LeagueScore Array (8)
0x5EB0 0x310D0 0x28A0 Plaza NPCs (?) PlayerInfo Array (25)
0x8768 0x33988 4 Rainmaker X Power 2270.2 (Float)
0x87B0 0x339D0 4 Splat Zones X Power 2309.7 (Float)
0x87F8 0x33A18 4 Tower Control X Power 2301.4 (Float)
0x8840 0x33A60 4 Clam Blitz X Power 2297.1 (Float)

Structure of Entry (TagPlayers):

Offset Size Description Value
0x0 8 Player 1 NEX Unique ID Needs investigation
0x8 0x28 Player 1 system info PlayerSystemInfo
0x30 8 Player 2 NEX Unique ID Needs investigation
0x38 0x28 Player 2 system info PlayerSystemInfo
0x60 8 Player 3 NEX Unique ID Needs investigation
0x68 0x28 Player 3 system info PlayerSystemInfo
0x90 8 Player 4 NEX Unique ID Needs investigation
0x98 0x28 Player 4 system info PlayerSystemInfo

Structure of Entry (PlayerSystemInfo):

Offset Size Description Value
0x8 0x14 In-game name UTF-16LE

Structure of Entry (PlayerInfo):

Offset Size Description Value
0x16 0x14 In-game name UTF-16LE
0x40 4 PlayerHairId See Mush/HairInfo.byml
0x44 4 PlayerSkinColorId 0 to 6, 0 being lightest and 6 darkest
0x48 4 PlayerEyeColorId 0 to 13, each value represents a color
0x64 0x20 ??? Gear
0x84 0x20 ??? Gear
0xA4 0x20 ??? Gear
0xC4 4 Tank See Mush/TankInfo.byml
0xC8 4 PlayerBottomId See Mush/BottomInfo.byml
0xDC 4 Level Looks like level 1 is 0 and level 2 is 1, etc
0xE0 4 Stars
0xE4 4 Rainmaker rank 0 = C-, 1 = C, 2 = C+, etc
0xE8 4 Splat Zones rank See above
0xEC 4 Tower Control rank See above
0xF0 4 Clam Blitz rank See above

SaveDataLocal

SaveDataMsn

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

SaveDataShop

SaveDataCoop

SaveDataFest

SaveDataStats

SaveDataMsnOcta

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