Changes

50 bytes removed ,  21:49, 31 March 2019
m
no edit summary
Line 1: Line 1:  
This page describes the format of save files contained in NAND. These files are stored as completely unencrypted, plaintext data. Save files are not cleared upon creation, resulting in possible garbage data in unused portions of the container.
 
This page describes the format of save files contained in NAND. These files are stored as completely unencrypted, plaintext data. Save files are not cleared upon creation, resulting in possible garbage data in unused portions of the container.
   −
== Main header ==
+
= Main header =
    
The header is 0x4000 bytes long.
 
The header is 0x4000 bytes long.
Line 66: Line 66:  
The additional storage at the end of the header is used to store any extra header data. This data's structure is determined by offsets stored in the main part of the header.
 
The additional storage at the end of the header is used to store any extra header data. This data's structure is determined by offsets stored in the main part of the header.
   −
=== AES CMAC header ===
+
== AES CMAC header ==
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 84: Line 84:  
The final CMAC key used for this is generated using GenerateAesKek with a kek source and the device key, along with and LoadAesKey and a set key seed.
 
The final CMAC key used for this is generated using GenerateAesKek with a kek source and the device key, along with and LoadAesKey and a set key seed.
   −
=== DISF ===
+
== DISF ==
    
This section contains information about the structure of the save file.
 
This section contains information about the structure of the save file.
Line 291: Line 291:  
|}
 
|}
   −
=== Integrity verification header ===
+
== Integrity verification header ==
    
* Offsets for levels 1-3 come from the metadata remap storage
 
* Offsets for levels 1-3 come from the metadata remap storage
Line 329: Line 329:  
|}
 
|}
   −
==== Level information ====
+
=== Level information ===
    
* 0x18 bytes long
 
* 0x18 bytes long
Line 358: Line 358:  
|}
 
|}
   −
=== Journal header ===
+
== Journal header ==
    
{| class="wikitable"
 
{| class="wikitable"
Line 396: Line 396:  
|}
 
|}
   −
==== Journal map header ====
+
=== Journal map header ===
    
{| class="wikitable"
 
{| class="wikitable"
Line 422: Line 422:  
|}
 
|}
   −
=== Extra data ===
+
== Extra data ==
    
{| class="wikitable"
 
{| class="wikitable"
Line 467: Line 467:  
|}
 
|}
   −
== Remap Storage ==
+
= Remap Storage =
    
Remap Storage is used to remap segments of data from virtual offsets to physical offsets. This allows extending the save file without having to relocate existing data.
 
Remap Storage is used to remap segments of data from virtual offsets to physical offsets. This allows extending the save file without having to relocate existing data.
Line 483: Line 483:  
Segment index: 0x3 Offset: 0x000000000000100
 
Segment index: 0x3 Offset: 0x000000000000100
   −
=== Remap storage header ===
+
== Remap storage header ==
    
{| class="wikitable"
 
{| class="wikitable"
Line 516: Line 516:  
|}
 
|}
   −
=== Remapping Entry ===
+
== Remapping Entry ==
    
{| class="wikitable"
 
{| class="wikitable"
Line 546: Line 546:  
|}
 
|}
   −
== Duplex Storage ==
+
= Duplex Storage =
    
A Duplex Storage contains four separate elements: [[#Duplex header|a header]], a bitmap, and two identically-sized chunks of data.
 
A Duplex Storage contains four separate elements: [[#Duplex header|a header]], a bitmap, and two identically-sized chunks of data.
Line 552: Line 552:  
As hinted by the name, a Duplex Storage contains two main chunks of data. To store X bytes, two chunks of data each with size X are required.
 
As hinted by the name, a Duplex Storage contains two main chunks of data. To store X bytes, two chunks of data each with size X are required.
   −
=== Bitmap ===
+
== Bitmap ==
    
This main data storage is split into blocks of the size indicated in the duplex header. The bitmap contains as many bits as the main data has blocks. If the main data is 0x40000 bytes long with a block size of 0x4000 bytes, the bitmap would contain 0x10 bits.
 
This main data storage is split into blocks of the size indicated in the duplex header. The bitmap contains as many bits as the main data has blocks. If the main data is 0x40000 bytes long with a block size of 0x4000 bytes, the bitmap would contain 0x10 bits.
Line 558: Line 558:  
The bitmap controls which data chunk is active for each block. e.g. If bit 3 of the bitmap is a 0 then block 3 of data chunk 0 is active and block 3 of data chunk 1 is inactive. This means that when data from block 3 is read, the data from chunk 0 will be returned and the data from chunk 1 will be completely ignored.
 
The bitmap controls which data chunk is active for each block. e.g. If bit 3 of the bitmap is a 0 then block 3 of data chunk 0 is active and block 3 of data chunk 1 is inactive. This means that when data from block 3 is read, the data from chunk 0 will be returned and the data from chunk 1 will be completely ignored.
   −
=== Hierarchical Duplex Storage ===
+
== Hierarchical Duplex Storage ==
    
Multiple Duplex Storages can be chained together to gain various benefits. With a Hierarchical Duplex Storage, the bitmap for the main data is stored inside another Duplex Storage.
 
Multiple Duplex Storages can be chained together to gain various benefits. With a Hierarchical Duplex Storage, the bitmap for the main data is stored inside another Duplex Storage.
Line 566: Line 566:  
This allows for atomic operations on the Hierarchical Duplex Storage. When writing to the storage, data will be written to the inactive blocks and inactive bitmaps. When the data is committed the bit in the save file header is flipped, changing which master bitmap is active.
 
This allows for atomic operations on the Hierarchical Duplex Storage. When writing to the storage, data will be written to the inactive blocks and inactive bitmaps. When the data is committed the bit in the save file header is flipped, changing which master bitmap is active.
   −
=== Duplex header ===
+
== Duplex header ==
    
* Block sizes are stored as powers of 2
 
* Block sizes are stored as powers of 2
Line 622: Line 622:  
|}
 
|}
   −
== Save FS ==
+
= Save FS =
   −
=== Save FS header ===
+
== Save FS header ==
    
* Structure is different than 3DS.
 
* Structure is different than 3DS.
Line 656: Line 656:  
|}
 
|}
   −
=== File allocation table header ===
+
== File allocation table header ==
    
{| class="wikitable"
 
{| class="wikitable"
Line 702: Line 702:  
|}
 
|}
   −
=== Save File Table ===
+
== Save File Table ==
    
The save file table is similar to the RomFS file table, except the save file table uses linked lists instead of dictionaries.
 
The save file table is similar to the RomFS file table, except the save file table uses linked lists instead of dictionaries.
Line 710: Line 710:  
'''SaveFsList<SaveFileTableEntry<SaveFileInfo>>'''
 
'''SaveFsList<SaveFileTableEntry<SaveFileInfo>>'''
   −
==== Save File Table Entry ====
+
=== Save File Table Entry ===
    
SaveFileTableEntry<class T>
 
SaveFileTableEntry<class T>
Line 730: Line 730:  
|}
 
|}
   −
==== Save File Info ====
+
=== Save File Info ===
    
Holds the information of a single file.
 
Holds the information of a single file.
Line 754: Line 754:  
|}
 
|}
   −
==== Save Directory Info ====
+
=== Save Directory Info ===
    
Holds the information of a single directory.
 
Holds the information of a single directory.
Line 778: Line 778:  
|}
 
|}
   −
=== Save FS List ===
+
== Save FS List ==
    
SaveFsList<class T>
 
SaveFsList<class T>
Line 806: Line 806:  
|}
 
|}
   −
==== Save FS List Key ====
+
=== Save FS List Key ===
    
{| class="wikitable"
 
{| class="wikitable"
Line 824: Line 824:  
|}
 
|}
   −
==== Save FS List Entry ====
+
=== Save FS List Entry ===
    
{| class="wikitable"
 
{| class="wikitable"
74

edits