Changes

388 bytes removed ,  01:30, 18 October 2011
Line 351: Line 351:  
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.
 
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 SAVE filesystem works with a backup. There are two SAVE blocks inside the partition concatenated. It seems that the second is always the updated one...
+
* The SAVE filesystem works with a backup. There are two SAVE blocks inside the partition concatenated. Which SAVE block is the updated one is unknown yet.. (I'm guessing from experience that (image[0x100B] & 0x20) == 0x20 --> 1st SAVE --[[User:Elisherer|Elisherer]] 01:30, 18 October 2011 (CEST))
   −
Finding the file system file base:
+
'''Finding the folders table:'''
* If there's no DATA partiton the file base will be at the uint32 @ 0x58 into the SAVE header.
+
* If DATA partition exists: At folder table exact offset from the SAVE struct (from the beginning of the struct).
* Otherwise the file base will be at ('active_table' & 0xFFFFFFFE) into the DATA partition.
+
* Otherwise: The 'folder table offset' * 'folder table media' (=0x200) from the 'filestore offset'. (usually 0 from filebase)
   −
Finding the file system table:
+
'''Finding the files table:'''
* If the uint32 @ 0x58 and uint32 @ 0x6C into the SAVE header aren't 0 then the table is at [@0x58] + [@0x6C]*0x200.
+
* If DATA partition exists: At file table exact offset from the SAVE struct (from the beginning of the struct).
* Otherwise, (meaning the files are at another partition) the exact offset into the SAVE is @ 0x68.
+
* Otherwise: The 'file table offset' * 'file table media' (=0x200) from the 'filestore offset'.
   −
File system's entry structure:
+
'''Detemining the filestore base:'''
 +
* If DATA partition exists: At file base from the DATA's DIFI struct into the DATA partition.
 +
* Otherwise: At the 'filestore offset' from the beginning of the SAVE struct.
 +
 
 +
Folder's entry structure:
 
<pre>
 
<pre>
  struct fs_entry {
+
  struct folder_entry {
     u32 node_cnt;
+
     u32 parent_folder_index;
 +
    u8  filename[0x10];
 +
    u32 folder_index;
 +
    u32 unk1;
 +
    u32 unk2; // flags?
 +
    u32 unk3;
 +
    u32 unk4;
 +
}
 +
</pre>
 +
 
 +
File's entry structure:
 +
<pre>
 +
struct file_entry {
 +
    u32 parent_folder_index;
 
     u8  filename[0x10];
 
     u8  filename[0x10];
 
     u32 index;
 
     u32 index;
 
     u32 unk1; // magic?
 
     u32 unk1; // magic?
 
     u32 block_offset;
 
     u32 block_offset;
     u32 file_size;
+
     u64 file_size;
     u32 unk2;
+
     u32 unk2; // flags?
    u32 unk3; // flags and/or date?
+
     u32 unk3;
     u32 unk4;
   
  }
 
  }
 
</pre>
 
</pre>
   −
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 both tables is the count of the table, the parent directory index will be the amount of table rows. The root includes the itself, so there are amount - 1 folders in the root directory. The entries that follow after the root are the actual folders/files.  
 +
 
 +
Reading the files out is as simple as taking the file base offset and adding (block_offset * 0x200) to it.
    
Here's a follow-up example from the Legend of Zelda: Ocarina of Time 3D:
 
Here's a follow-up example from the Legend of Zelda: Ocarina of Time 3D:
Line 394: Line 412:  
</pre>
 
</pre>
   −
Example for a different file with different SAVE structure:
+
{| class="wikitable"
 
+
|-
<pre>
+
! Start
00002400 53415645 00000400 20000000 00000000 SAVE.... ....... //Save from Steel Diver
+
! Length
00002410 28030000 00000000 00020000 00000000 (...............
+
! Description
00002420 00000000 00020000 88000000 00000000 ................
+
|-
00002430 03000000 00020000 94000000 00000000 ................
+
| 0x00
00002440 43000000 00020000 A0010000 00000000 C...............
+
| 4
00002450 28030000 00020000 00000000 00000000 (............... //[0x58] = 0 and
+
| Magic ("SAVE")
00002460 28030000 00020000 E81A0000 00000000 (............... //[0x6C] = 0, but
+
|-
00002470 00000000 00020000 381B0000 00000000 ........8....... //On offset 0x68 There's an exact offset to the FST
+
| 0x04
00002480 40000000 00020000 01000000 00000000 @............... //meaning a uint32_t at 0x68 into the SAVE struct
+
| 4
00002490 00000000 00000000 00000000 02000000 ................
+
| Magic padding
 
+
|-
00003F30 00000000 00000000 04000000 41000000 ............A... // first fs_entry '04 00 00 00'
+
| 0x08
00003F40 00000000 00000000 00000000 00000000 ................ //exectly 0x1B38 from the save header struct
+
| 8
00003F50 00000000 00000000 00000000 00000000 ................
+
| Unknown
00003F60 00000000 00000000 01000000 67686F73 ............ghos
+
|-
00003F70 742E7374 30370000 00000000 00000000 t.st07..........
+
| 0x10
00003F80 D57B1100 00000000 7E290000 00000000 .{......~)......
+
| 8
00003F90 00000000 00000000 01000000 73617665 ............save
+
| Partition Size
00003FA0 2E737562 00000000 00000000 01000000 .sub............
+
|-
00003FB0 D57B1100 15000000 9C090000 00000000 .{..............
+
| 0x18
00003FC0 00000000 00000000 01000000 73617665 ............save
+
| 4
00003FD0 2E706572 69730000 00000000 02000000 .peris..........
+
| Unknown
00003FE0 D57B1100 1A000000 29070000 00000000 .{......).......
+
|-
00003FF0 00000000 00000000 00000000 00000000 ................
+
| 0x1C
</pre>
+
| 8
 
+
| Unknown
known struct until now:
+
|-
 
+
| 0x24
<pre>
+
| 4
struct save_header {
+
| Unknown
        char magic[4];          //'SAVE'
+
|-
        u8 unknown0[0x54];
+
| 0x28
        u32 file_base_offset;
+
| 8
        u8 unknown1[0x10];
+
| Unknown (First table offset)
        u32 fst_block_offset;    //FST is in [file_base_offset] * 0x200 + [fst_block_offset]
+
|-
        u8 unknown2[8];          //or (if no filebase)
+
| 0x30
        uint32 fst_exact_offset; //The exact offset from the header start
+
| 4
}
+
| Unknown (num of u32 in table)
</pre>
+
|-
 +
| 0x34
 +
| 4
 +
| Unknown (size of media)
 +
|-
 +
| 0x38
 +
| 8
 +
| Unknown (Second table offset)
 +
|-
 +
| 0x40
 +
| 4
 +
| Unknown (num of u32 in table)
 +
|-
 +
| 0x44
 +
| 4
 +
| Unknown (size of media)
 +
|-
 +
| 0x48
 +
| 8
 +
| Unknown (Second table offset)
 +
|-
 +
| 0x50
 +
| 4
 +
| Unknown (num of u32 in table)
 +
|-
 +
| 0x54
 +
| 4
 +
| Unknown (size of media)
 +
|-
 +
| 0x58
 +
| 8
 +
| File store offset (from SAVE)
 +
|-
 +
| 0x60
 +
| 4
 +
| File store length (medias)
 +
|-
 +
| 0x64
 +
| 4
 +
| File store media size
 +
|-
 +
| 0x68
 +
| 4/8
 +
| Folders Table offset (8 bytes in DATA)
 +
|-
 +
| 0x6C
 +
| 4
 +
| Folders Table Length (medias) (Only in no DATA)
 +
|-
 +
| 0x70
 +
| 4
 +
| Folders Table unknown
 +
|-
 +
| 0x74
 +
| 4
 +
| Folders Table Media size
 +
|-
 +
| 0x78
 +
| 4/8
 +
| Files Table offset (8 bytes in DATA)
 +
|-
 +
| 0x7C
 +
| 4
 +
| Files Table Length (medias) (Only in no DATA)
 +
|-
 +
| 0x80
 +
| 4
 +
| Files Table unknown
 +
|-
 +
| 0x84
 +
| 4
 +
| Files Table Media size
 +
|-
 +
|}
    
=== Initialization ===
 
=== Initialization ===
399

edits