Hello! I originally posted this months ago on reddit.com/r/3dshacks
I'm hoping to get some more helpful eyes to look at this.
There is a 48 byte header appended to SNES virtual console saves extracted from 3DS and WiiU.
An extracted SNES virtual console save contains 4 files. .cfg, .vea, .ves and .vew
.cfg is a configuration file.
.vea is a resume point for the emulator to load.
.ves is a file that contains the actual save data.
.vew is the save state (if any)
If you open up a .ves file in a HEX editor, you can see that Nintendo appends 48 hex bytes before the actual save file. I've dumped a bunch of virtual console saves and tried to make sense of the 48 bytes...
START SIZE DESCRIPTION
0x00 0x2 Always 0x0100
0x02 0x2 checksum-16 little endian, decrease first byte down a single hex value
0x04 0x2 game preset ID
0x06 0x2 Always 0x0000
0x08 0x5 Always 00's on 3DS. Different for each WiiU vc game? [why though?!?]
0x0d 0x3 Always 0x000000
0x10 0x8 Always 0xC13586A565CB942C [why though?!?]
0x18 0x2 save size kb little endian
0x1a 0x2 Always 0x0000
0x1c 0x4 changes 0x???????? [why though?!?]
0x20 0x10 Always 0x00000000000000000000000000000000
I'm stumped for bytes 28-31 (start 0x1c). Perhaps more encryption? A timestamp?
If any of my research is unclear, or if anyone has a question, let me know and I can try to explain/elaborate.
EDIT: Did some testing. Here's how to add the correct 48-byte header to an SNES save to get it working on a N3DS.
1. Append a 48 byte header (all 0's) to the beginning of your save file.
2. Change the 1st byte of the header to 0x01
3. Change the 5th and 6th bytes to the game's preset id. (ex. EarthBound = 6E10, Super Metroid = 4010, etc)
4. Change bytes 17-24 to 0xC13586A565CB942C
5. Generate a Checksum-16 for the entire save file. Reverse the byte order and decrease the first byte down a single hex value. Add to the save file as 3rd and 4th byte.
6. Make sure your save file is named properly. The name is based off the serial/product code. So for Earthbound, my save file would be named 'KTR-UAEE.ves'
7. Import your save (a folder containing ONLY a .ves) using JKSM and it should properly appear when you boot the game.
Here are some examples for altering the checksum-16 to be correct,
if the checksum is 470F, the value we add to the save file would be 0E47.
checksum-16 '470F' -> '0E47' new value
checksum-16 'B1D5' -> 'D4B1' new value
checksum-16 '6120' -> '1F61' new value
Notes: still confused about the following
START SIZE DESCRIPTION
I'm hoping to get some more helpful eyes to look at this.
There is a 48 byte header appended to SNES virtual console saves extracted from 3DS and WiiU.
An extracted SNES virtual console save contains 4 files. .cfg, .vea, .ves and .vew
.cfg is a configuration file.
.vea is a resume point for the emulator to load.
.ves is a file that contains the actual save data.
.vew is the save state (if any)
If you open up a .ves file in a HEX editor, you can see that Nintendo appends 48 hex bytes before the actual save file. I've dumped a bunch of virtual console saves and tried to make sense of the 48 bytes...
START SIZE DESCRIPTION
0x00 0x2 Always 0x0100
0x02 0x2 checksum-16 little endian, decrease first byte down a single hex value
0x04 0x2 game preset ID
0x06 0x2 Always 0x0000
0x08 0x5 Always 00's on 3DS. Different for each WiiU vc game? [why though?!?]
0x0d 0x3 Always 0x000000
0x10 0x8 Always 0xC13586A565CB942C [why though?!?]
0x18 0x2 save size kb little endian
0x1a 0x2 Always 0x0000
0x1c 0x4 changes 0x???????? [why though?!?]
0x20 0x10 Always 0x00000000000000000000000000000000
I'm stumped for bytes 28-31 (start 0x1c). Perhaps more encryption? A timestamp?
If any of my research is unclear, or if anyone has a question, let me know and I can try to explain/elaborate.
EDIT: Did some testing. Here's how to add the correct 48-byte header to an SNES save to get it working on a N3DS.
1. Append a 48 byte header (all 0's) to the beginning of your save file.
2. Change the 1st byte of the header to 0x01
3. Change the 5th and 6th bytes to the game's preset id. (ex. EarthBound = 6E10, Super Metroid = 4010, etc)
4. Change bytes 17-24 to 0xC13586A565CB942C
5. Generate a Checksum-16 for the entire save file. Reverse the byte order and decrease the first byte down a single hex value. Add to the save file as 3rd and 4th byte.
6. Make sure your save file is named properly. The name is based off the serial/product code. So for Earthbound, my save file would be named 'KTR-UAEE.ves'
7. Import your save (a folder containing ONLY a .ves) using JKSM and it should properly appear when you boot the game.
Here are some examples for altering the checksum-16 to be correct,
if the checksum is 470F, the value we add to the save file would be 0E47.
checksum-16 '470F' -> '0E47' new value
checksum-16 'B1D5' -> 'D4B1' new value
checksum-16 '6120' -> '1F61' new value
Notes: still confused about the following
START SIZE DESCRIPTION
0x08 0x5 Always 00's on 3DS. Different for each WiiU vc game? [why though?!?]
0x10 0x8 Always 0xC13586A565CB942C [why though?!?]
0x18 0x2 save size kb little endian
0x1c 0x4 changes 0x???????? [why though?!?]
I don't currently have my WiiU set-up so I haven't been able to do any testing regarding Start 0x08, Size 0x5. Perhaps someone can do some testing?
Not entirely sure what 0xC13586A565CB942C does, but it is absolutely needed.
The save size isn't needed. I've been able to get my saves working without setting it.
Start 0x1c, Size 0x4. Always changing when a save is made. However, doesn't seem to be needed. Can be turned to 00's.
0x10 0x8 Always 0xC13586A565CB942C [why though?!?]
0x18 0x2 save size kb little endian
0x1c 0x4 changes 0x???????? [why though?!?]
I don't currently have my WiiU set-up so I haven't been able to do any testing regarding Start 0x08, Size 0x5. Perhaps someone can do some testing?
Not entirely sure what 0xC13586A565CB942C does, but it is absolutely needed.
The save size isn't needed. I've been able to get my saves working without setting it.
Start 0x1c, Size 0x4. Always changing when a save is made. However, doesn't seem to be needed. Can be turned to 00's.
Last edited by k1r92,