Changes

Jump to navigation Jump to search

Splatoon 2/Save

5,988 bytes added, 20:11, 26 June 2019
m
SaveDataCmn
{{WIP}}
 
Splatoon 2 saves its data in '''<code>save.dat</code>'''.
* '''[https://leanny.github.io/SplatHeX.html SplatHeX]''': a full fledged save editor for Windows.
* '''[https://github.com/3096/effective-spoon/releases/tag/rewrite Splatsave]''': an open source program that decrypts and re-encrypts <code>save.dat</code>.
== Revisions ==
Since release, there has been '''57''' revisions to this file:
{| class="wikitable" border="1"
|-
! VerVersion
! Added On
! Save Size
| 4.0.0
| 0x88D90
| Introduced save body shuffleand 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 key look-up tableand now shuffles twice, before and after encryption. Content is presumably still the same as Ver 3.|-| 8| 4.3.1| 0x88D90| Introduced additional encryption for each shuffle blocks. Shuffling now uses bit reversed/flipped CRC32 checksum as seed. Content is still the same as Ver 3.
|}
The encryption used on the save body is '''AES-128 CBC'''. The key is generated
using a <code>[[Sead/Pseudorandom Number Generator‎|sead::Random</code> ]] 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
<code>sead::Random</code> object after the encryption key. The key is generated by <code>Cmn::SaveDataFactory::Impl::IEncodedAllAccessor::createKey</code>.
The For version 4, a shuffling process for save body takes was added to take place after it the save body gets encrypted. This shuffling is not present in version five, but is encrypteddone twice in version 7 and onward, with a shuffle before the body encryption as well. In save version 8, the shuffling doubles as an added layer of encryption. The For determining the block sizes to shuffle, the game constructs constructs a new <code>sead::Random</code> object . In version 4 and 7, this <code>sead::Random</code> object is initialized simply with the CRC32 checksum from the save header; in version 8, rather, the checksum is bit-reversed before being used for the after-encryption shuffle, and bit-reversed, plus bit-flipped for the before-encryption shuffle. It The game then uses this the <code>sead::Random</code> object 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 body size for version 8, despite following the same general principal, goes an extra step to make sure that all the generated block sizes are multiple of 0x10, for the added "shuffle encryption" purpose. The game then uses <code>sead::PtrArrayImpl::shuffle</code> with the same previous <code>sead::Random</code> object to complete the shuffle. While in version 4 and 7, the shuffling is done by simply copying over the block buffers, the version 8 save creates more <code>sead::Random</code> objects for each block, initialized with the respective block size. The game uses these <code>sead::Random</code> objects to generate the IV used for block encryption, and then chains the object into <code>Cmn::SaveDataFactory::Impl::IEncodedAllAccessor::createKey</code>, the same key generation function used in "whole-body" encryption, to create the encryption key. Lastly, all the blocks are encrypted into their shuffled position with the existing AES-128 CBC algorithm.
== save.dat file structure File Structure =='''Save === Header:'''===
{| class="wikitable" border="1"
|-
| 0
|}
----'''Save === Body Structure'''===
{| class="wikitable" border="1"
|-
| SaveDataMsnOcta
|}
----'''=== SaveDataCmn(0x10):'''===
{| class="wikitable" border="1"
|-
|}
SkillChip (Ability ChuncksChunks) Inventory part:
{| class="wikitable" border="1"
|-
| 0x8
| 0x200
| (SkillChip (a.k.a. Ability ChuncksChunks) Inventory)
|}
| 0x258F5
| 0x1
| Cococnut Coconut Post Display
| 1 for enabled
|-
| 1 if yes
|-
| 0x284F80x284E8
| 0x284F8
| 0x2D2C
| unk (Haven't looked into yet)
|}
 === SaveDataVss ==={| class="wikitable"! 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|-'''SaveDataVss| 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):{| class="wikitable"! 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 (0x2B220PlayerSystemInfo):'''{| class="wikitable" border! Offset !! Size !! Description !! Value|-| 0x8 || 0x14 || In-game name || UTF-16LE|} Structure of Entry (PlayerInfo):{| class="1wikitable"! 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
|-
! Offset! Absolute Offset! Size! Description! Value| 0xA4 || 0x20 || ??? || Gear
|-
| 0x00xC4 | 0x2B220| 4| PlayerRank (Not rank, but level| Tank || See Mush/TankInfo. They call it rank in the code.)| Looks like level 1 is `0` and level 2 is `1`, etc)byml
|-
| 0x40xC8 | 0x2B224| 4| Experience| To be filled inPlayerBottomId || See Mush/BottomInfo.byml
|-
| 0x80xDC | 0x2B228| 4| StarRank| To be filled inLevel || Looks like level 1 is 0 and level 2 is 1, etc
|-
| 0x140xE0 | 0x2B234| 4| (TicketBoostRemaining)| 20Stars ||
|-
| 0x87680xE4 | 0x33988| 4| (X Power | Rainmaker)rank || 2770.0 = C-, 1 = C, 2 (Float)= C+, etc
|-
| 0x87B00xE8 | 0x339D0| 4| (X Power Splatzone)| 2809.7 (Float)Splat Zones rank || See above
|-
| 0x87F80xEC | 0x33A18| 4| (X Power | Tower Control)rank | 2801.4 (Float)| See above
|-
| 0x88400xF0 | 0x33A60| 4| (X Power | Clam Blitz)rank || 2797.1 (Float)See above
|}
----'''=== SaveDataLocal(0x37970):'''===----'''=== SaveDataMsn(0x3AD58):'''===
{| class="wikitable" border="1"
|-
| 0x3CBC8
| 4
| (MechanicalFishSardinium)
| 69
|}
----'''=== SaveDataShop(0x40BD0):'''===----=== SaveDataCoop ==='''SaveDataCoop(0x438D0?):'''=== SaveDataFest ===----=== SaveDataStats ===More to be added here...=== SaveDataMsnOcta ===----'''Save === Footer:'''<br />===
Used for save crypto (as of ver 4)
{| class="wikitable" border="1"
| AES-CMAC
|}
 
[[Category:Splatoon 2]]
4
edits

Navigation menu