Changes

1,287 bytes added ,  02:16, 19 September 2011
Some confusion on IRC about the savefile filesystem. This should make it a bit clearer. Better explaination, new example and new replacement example.
Line 1: Line 1:  +
This page describes the format, de/encryption, etc. of savegames found in 3DS game cartridges/gamecards. You can find savegames from various 3DS games on the [[Games]] page.
 +
 +
 
=== Encryption ===
 
=== Encryption ===
   Line 69: Line 72:  
=== Filesystem ===
 
=== Filesystem ===
 
   
 
   
Savefiles are stored on the FLASH in a custom filesystem called SAVE. SAVE has a header which describes where the various bits of the filesystem live. The most important is the FST or filesystem table. You can find the FST by first finding the file base offset which is the offset to which all the entries in the FST are relative. The file base offset is a uint16_t at 0x58 from the filesystem start. The FST offset is a uint32_t at 0x6C and is in blocks (which are 0x200 bytes large).
+
Savefiles are stored on the FLASH in a custom filesystem called SAVE. SAVE has a header which describes where the various bits of the filesystem live. The header can be found by searching for the string "SAVE" (minus quotation marks) in the savefile. The address where the 'S' is located is the base address for the SAVE header/filesystem.
 +
 
 +
The most important information in the savefile is the FST or filesystem table. You can find the FST by first finding the file base offset which is the offset to which all the entries in the FST are relative. The file base offset is a uint16_t at 0x58 from the filesystem start. The FST offset is a uint32_t at 0x6C and is in blocks (which are 0x200 bytes large).
 +
 
 +
For example, the Legend of Zelda: Ocarina of Time 3D SAVE header looks like this:
 +
 
 +
<pre>
 +
00001FF0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF  ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
 +
00002000: 53415645 00000400 20000000 00000000  SAVE.... .......  //Start of SAVE header
 +
00002010: 68000000 00000000 00020000 00000000  h...............
 +
00002020: 00000000 00020000 88000000 00000000  ........ˆ.......
 +
00002030: 03000000 00020000 94000000 00000000  ........”.......
 +
00002040: 09000000 00020000 B8000000 00000000  ........¸.......
 +
00002050: 66000000 00020000 00040000 00000000  f...............  //File base offset - 0x0400 (little endian byte ordering)
 +
00002060: 66000000 00020000 00000000 01000000  f...............  //FST offset - 0x00000001 (little endian byte ordering) * 0x200
 +
00002070: 00000000 00020000 01000000 01000000  ................
 +
00002080: 08000000 00020000 01000000 00000000  ................
 +
...
 +
</pre>
    
Once you've found the FST, parsing it is fairly straightforward.
 
Once you've found the FST, parsing it is fairly straightforward.
Line 89: Line 110:  
The first entry is the root directory, easily identifiable by the node_cnt being larger than 1. The node_cnt includes the root directory itself, so there are node_cnt - 1 files in the root directory. The entries that follow after the root directory are the actual files. Reading them out is as simple as taking the file base offset and adding (block_offset * 0x200) to it.
 
The first entry is the root directory, easily identifiable by the node_cnt being larger than 1. The node_cnt includes the root directory itself, so there are node_cnt - 1 files in the root directory. The entries that follow after the root directory are the actual files. Reading them out is as simple as taking the file base offset and adding (block_offset * 0x200) to it.
   −
Example from Super MonkeyBall 3D:
+
Here's a follow-up example from the Legend of Zelda: Ocarina of Time 3D:
 
<pre>
 
<pre>
0003800: 04000000 21000000 00000000 00000000  ....!...........
+
00002600: 03000000 09000000 00000000 00000000  ................  //FST entry = SAVE base + File base + (FST offset * 0x200)
0003810: 00000000 00000000 00000000 00000000  ................
+
00002610: 00000000 00000000 00000000 00000000  ................ //0x2600    = 0x2000    + 0x400    + (0x1        * 0x200)
0003820: 00000000 00000000 00000000 00000000  ................
+
00002620: 00000000 00000000 00000000 00000000  ................
0003830: 01000000 736d6233 64732e64 61740000  ....smb3ds.dat..
+
00002630: 01000000 73797374 656D2E64 61740000  ....system.dat..
0003840: 00000000 00000000 d57b1100 05000000 .........{......
+
00002640: 00000000 00000000 D57B1100 02000000 ........Õ{......
0003850: e4060000 00000000 c8cf0008 00000000  ................
+
00002650: 22000000 00000000 E8121500 00000000  ".......è.......
0003860: 01000000 6d677265 706c6179 30302e64 ....mgreplay00.d
+
00002660: 01000000 73617665 30302E62 696E0000 ....save00.bin..
0003870: 61740000 01000000 d57b1100 09000000  at.......{......
+
00002670: 00000000 01000000 69921100 03000000 ........i’......
0003880: 1c210000 00000000 cd331000 00000000  .!.......3......
+
00002680: DC140000 00000000 04000000 00000000  Ü...............
0003890: 01000000 6d677265 706c6179 30312e64 ....mgreplay01.d
  −
00038a0: 61740000 02000000 d57b1100 1a000000  at.......{......
  −
00038b0: 1c210000 00000000 00000000 00000000  .!..............
   
</pre>
 
</pre>
  
34

edits