Monday, January 23, 2017

Spyro, MGS and CTR save format

I documented this when I was making plugins for MemcardRex. If anyone needs this info for some reason, here it is.
Offsets are for .mcs single save format.

Spyro the Dragon:
Level name Gems, Dragons, Eggs
Artisans Home 100, 4, 0
Stone Hill 200, 4, 1
Dark Hollow 100, 3, 0
Town Square 200, 4, 1
Toasty 100, 1, 0
Sunny Flight 300, 0, 0
Peace Keepers Home 200, 3, 1
Dry Canyon 400, 4, 1
Cliff Town 400, 3, 1
Ice Cavern 400, 5, 0
Doctor Shemp 300, 1, 0
Night Flight 300, 0, 0
Magic Crafters Home 300, 3, 2
Alpine Ridge 500, 4, 1
High Caves 500, 3, 2
Wizard Peak 500, 3, 2
BlowHard 400, 1, 0
Crystal Flight 300, 0, 0
Beast Makers Home 300, 2, 0
Terrace Villiage 400 2, 0
Misty Bog 500 4 0
Tree Tops 500 3 0
MetalHead 500 1 0
Wild Flight 300 0 0
Dream Weavers Home 300 3 0
Dark Passage 500 5 0
Lofty Castle 400 3 0
Haunted Towers 500 3 0
Jaques 500 2 0
Icy Flight 300 0 0
Gnorc Gnexus 200 2 0
Gnorc Cove 400 2 0
Twilight Harbor 400 2 0
Gnasty Gnorc 500 0 0
Gnasty's Loot 2000 0 0

Save structure information:
Values are stored in the little endian byte order

0x000 - 128 bytes (Save header)
0x080 - 512 bytes (Save title + icon)
0x280 - 1536 bytes (Slot 1)
0x880 - 1536 bytes (Slot 2)
0xE80 - 1536 bytes (Slot 3)

Slot structure:
0x280 - 8 bit (Start location. Read as decimal: World x 10 + Stage)
0x281 - 8 bit (SFX volume) - Values range from 0 to 10
0x282 - 8 bit (Music volume) - Values range from 0 to 10
0x284 - 8 bit (Passive/Active flag) - Passive is 82 and Active is 2. Probably used for something else too
0x288 - 8 bit (Stereo/Mono flag) - Stereo is 0 and Mono is 1
0x28B - 8 bit (Lives) - Maximum is 255 but only 2 digits will be visible ingame
0x2C0 - 8 bit (Unlocked level flags) - Values range from 0 to 1
0x308 - 35 x 8 bit (Saved dragons)
0x32C - 35 x 16 bit (Gems)
0x374 - 16 x 8 bit (Eggs)
0x38C - 32 x 8 bit (Flags for collected items)
0x80C - 32 bit (Checksum) - Sum of all previous bytes from beginning of the slot

Additional information:
Each slot offsets by 0x600 from the previous one.

Game progress percentage (120 % max):
70% - Number of gems (14000 max)
40% - Number of saved dragons (80 max)
10% - Unknown


Crash Team Racing:
Character indexes:
0x0 - Crash Bandicoot
0x1 - Dr. Neo Cortex
0x2 - Tiny Tiger
0x3 - Coco Bandicoot
0x4 - N. Gin
0x5 - Dingodile
0x6 - Polar
0x7 - Pura
0x8 - Pinstripe
0x9 - Papu Papu
0xA - Ripper Roo
0xB - Komodo Joe
0xC - Dr. N. Tropy
0xD - Penta Penguin
0xE - Fake Crash
0xF - Nitrous Oxide (game locks up)

Unsupported indexes (0xF and up) lead to game crashing.
If the index is 0xFFFF save is not active.

Save structure information:
Values are stored in the little endian byte order.

0x0000 - 128 bytes (Save Header)
0x0080 - 256 bytes (Save title + icon)
0x0180 - 80 bytes (1st save slot)
0x01D0 - 80 bytes (2nd save slot)
0x0220 - 80 bytes (3rd save slot)
0x0270 - 80 bytes (4th save slot)

0x0184 - 8 bit (Colectables flags 1)
bit 1 - Unknown
bit 2 - Unknown
bit 3 - Unknown
bit 4 - Unknown
bit 5 - Unknown
bit 6 - Unknown
bit 7 - Dingo Canyon (trophy)
bit 8 - Dragon Mines (trophy)

0x0185 - 8 bit (Colectables flags 2)
bit 1 - Blizzard Bluff (trophy)
bit 2 - Crash Cove (trophy)
bit 3 - Tiger Temple (trophy)
bit 4 - Papu's Pyramid (trophy)
bit 5 - Roo's Tubes (trophy)
bit 6 - Hot Air Skyway (trophy)
bit 7 - Sewer Speedway (trophy)
bit 8 - Mystery Caves (trophy)

0x0186 - 8 bit (Colectables flags 3)
bit 1 - Cortex Castle (trophy)
bit 2 - N. Gin Labs (trophy)
bit 3 - Polar Pass (trophy)
bit 4 - Oxide Station (trophy)
bit 5 - Coco Park (trophy)
bit 6 - Tiny Arena (trophy)
bit 7 - Dingo Canyon (blue relic)
bit 8 - Dragon Mines (blue relic)

0x0187 - 8 bit (Colectables flags 4)
bit 1 - Blizzard Bluff (blue relic)
bit 2 - Crash Cove (blue relic)
bit 3 - Tiger Temple (blue relic)
bit 4 - Papu's Pyramid (blue relic)
bit 5 - Roo's Tubes (blue relic)
bit 6 - Hot Air Skyway (blue relic)
bit 7 - Sewer Speedway (blue relic)
bit 8 - Mystery Caves (blue relic)

0x0188 - 8 bit (Colectables flags 5)
bit 1 - Cortex Castle (blue relic)
bit 2 - N. Gin Labs (blue relic)
bit 3 - Polar Pass (blue relic)
bit 4 - Oxide Station (blue relic)
bit 5 - Coco Park (blue relic)
bit 6 - Tiny Arena (blue relic)
bit 7 - Slide Coliseum (blue relic)
bit 8 - Turbo Track (blue relic)

0x0189 - 8 bit (Colectables flags 6)
bit 1 - Dingo Canyon (gold relic)
bit 2 - Dragon Mines (gold relic)
bit 3 - Blizzard Bluff (gold relic)
bit 4 - Crash Cove (gold relic)
bit 5 - Tiger Temple (gold relic)
bit 6 - Papu's Pyramid (gold relic)
bit 7 - Roo's Tubes (gold relic)
bit 8 - Hot Air Skyway (gold relic)

0x018A - 8 bit (Colectables flags 7)
bit 1 - Sewer Speedway (gold relic)
bit 2 - Mystery Caves (gold relic)
bit 3 - Cortex Castle (gold relic)
bit 4 - N. Gin Labs (gold relic)
bit 5 - Polar Pass (gold relic)
bit 6 - Oxide Station (gold relic)
bit 7 - Coco Park (gold relic)
bit 8 - Tiny Arena (gold relic)

0x018B - 8 bit (Colectables flags 8)
bit 1 - Slide Coliseum (gold relic)
bit 2 - Turbo Track (gold relic)
bit 3 - Dingo Canyon (platinum relic)
bit 4 - Dragon Mines (platinum relic)
bit 5 - Blizzard Bluff (platinum relic)
bit 6 - Crash Cove (platinum relic)
bit 7 - Tiger Temple (platinum relic)
bit 8 - Papu's Pyramid (platinum relic)

0x018C - 8 bit (Colectables flags 9)
bit 1 - Roo's Tubes (platinum relic)
bit 2 - Hot Air Skyway (platinum relic)
bit 3 - Sewer Speedway (platinum relic)
bit 4 - Mystery Caves (platinum relic)
bit 5 - Cortex Castle (platinum relic)
bit 6 - N. Gin Labs (platinum relic)
bit 7 - Polar Pass (platinum relic)
bit 8 - Oxide Station (platinum relic)

0x018D - 8 bit (Colectables flags 10)
bit 1 - Coco Park (platinum relic)
bit 2 - Tiny Arena (platinum relic)
bit 3 - Slide Coliseum (platinum relic)
bit 4 - Turbo Track (platinum relic)
bit 5 - Dingo Canyon (CTR token)
bit 6 - Dragon Mines (CTR token)
bit 7 - Blizzard Bluff (CTR token)
bit 8 - Crash Cove (CTR token)

0x018E - 8 bit (Colectables flags 11)
bit 1 - Tiger Temple (CTR token)
bit 2 - Papu's Pyramid (CTR token)
bit 3 - Roo's Tubes (CTR token)
bit 4 - Hot Air Skyway (CTR token)
bit 5 - Sewer Speedway (CTR token)
bit 6 - Mystery Caves (CTR token)
bit 7 - Cortex Castle (CTR token)
bit 8 - N. Gin Labs (CTR token)

0x018F - 8 bit (Colectables flags 12)
bit 1 - Polar Pass (CTR token)
bit 2 - Oxide Station (CTR token)
bit 3 - Coco Park (CTR token)
bit 4 - Tiny Arena (CTR token)
bit 5 - Unknown
bit 6 - Unknown
bit 7 - Ripper Roo (boss)
bit 8 - Papu Papu (boss)

0x019C - 9 bytes (User name, standard ASCII, 8 letters + null char)
0x01AE - 16 bit (Game character)

0x02C8 - 8 bit (Character unlockables 1)
bit 1 - Unknown
bit 2 - Unknown
bit 3 - Parking Lot (Battle arena)
bit 4 - The North Bowl (Battle arena)
bit 5 - Lab Basement (Battle arena)
bit 6 - Dr. N. Tropy
bit 7 - Penta Penguin
bit 8 - Ripper Roo

0x02C9 - 8 bit (Character unlockables 2)
bit 1 - Papu Papu
bit 2 - Komodo Joe
bit 3 - Pinstripe
bit 4 - Fake Crash
bit 5 - Unknown
bit 6 - Unknown
bit 7 - Unknown
bit 8 - Unknown

0x02CC - 8 bit (General unlockables)
bit 1 - Unknown
bit 2 - Unknown
bit 3 - Unknown
bit 4 - Unknown
bit 5 - Scrapbook mode
bit 6 - Unknown
bit 7 - Unknown
bit 8 - Unknown

0x17FE - 16 bit (Checksum, big endian)

Checksum calculation:

private uint GetChecksumCTR(byte[] InputData)
{
//Simulated PS1 registers
uint r2 = 0;
uint r3 = 0;
uint r4 = 0;
uint r5 = 0;
uint r6 = 0;
uint r7 = 0;

//Checksum calculation
for (uint i = 0; i < 5760; i++)
{
r5 = InputData[i + 0x180];
r3 = 0x7;
r7 = 0x10000;
r6 = r7;
r6 = r6 | 0x1021;

//Erase old checksum
InputData[0x17FE] = 0x00;
InputData[0x17FF] = 0x00;

while (r3 < 0xFFFF)
{
r4 = r4 << 0x1;
r2 = r5 >> (int)r3;
r2 = r2 & 0x1;
r4 = r4 | r2;
r2 = r4 & r7;

if (r2 != 0) r4 = r4 ^ r6;

r3 = (r3 + 0xFFFF) & 0xFFFF;
}
}
return r4;
}


Metal Gear Solid:
Weapon order:
Socom
FA-MAS
Grenades
Nikita
Stinger
Claymore
C4
Stun grenades
Chaff grenades
PSG-1

Item order:
Cigarettes
Magnifying scope
Cardboard box A
Cardboard box B
Cardboard box C
Night-vision goggles
Thermal goggles
Gas mask
Body armor
Ketchup
Stealth
Bandana
Camera
Ration
Cold medicine
Diazepam
PAL card key
ID card
Timer bomb
Mine detector
MO disc
Rope
Handkerchief
Suppressor

Location order:
Dock
Heliport
Tank Hangar
Cell
Medi room
Armory
Armory Sth
Canyon
Nuke Bldg 1
Nuke Bldg. B1
Cmnder room
Nuke Bldg. B2
Lab
Cave
U.Grnd Pssge
Comm Twr A
Roof/Comm Twr
Comm Twr B
Twr Wall A
Walkway
Snowfield
Blast Furnance
Cargo Elev.
Warehouse
Warehouse Nth
U.Grnd Base 1
U.Grnd Base 2
U.Grnd Base 3
Cmnd room
Spply Rte.
Esc Route

Save identifier:
GHHMMCLI

G - Magic letter (G - game, V - training data, C - photo)
HH - Hours
MM - Minutes (EZ starts with 0, NM with q)
C - New or cleared game (Starts with @ - New game, H - Disc 2)
L - Location (Starts with A - Dock)
I - Identifier between similar saves (Starts with A)

This is just for info when loading game. Identifier data is not used in game.

Save structure information:
Values are stored in the little endian byte order.

0x0000 - 128 bytes (Save Header)
0x0080 - 512 bytes (Save title + icon)
0x0280 - 2560 bytes (Save data)
0x0C80 - 2560 bytes (Save data mirror, not used when loading)
0x1680 - 2560 bytes (Save data mirror, not used when loading)

0x0184 - 32 bit (Checksum) - CRC32
0x0190 - 32 bit (Game time) - Counted in frames (NTSC - 60 fps, PAL - 50 fps)
0x01BC - 32 bit (Generic flags, unknown at this time)
0x01C2 - 16 bit (Game difficulty) - 0-Easy, 1-Normal, 2-Hard, 3-Extreme
0x01C4 - 16 bit (Option flags) - ????R??? ???????? - (When R is active radar is invisible)
0x01D6 - 16 bit (Current health) - Anything above 1400 causes issues
0x01D8 - 16 bit (Maximum health) - Anything above 1400 causes issues
0x01E2 - 10 x 16 bit (Current weapon units) - If the value is positive weapon is in stock
0x01F6 - 10 x 16 bit (Maximum weapon units)
0x020A - 23 x 16 bit (Current item units) - If the value is greater then 0 item is in stock
0x023A - 16 bit (Maximum Rations)
0x023C - 16 bit (Maximum Cold medicines)
0x023E - 16 bit (Maximum Diazepams)
0x0270 - 8 bit (Number of saves)
0x02DA - 8 bit (Torture flags) ????O??? - (When O is activated Meryl dies)

2 comments:

  1. Mr Doshen. It's your old friend rainmotorsports. I have been trying to get ahold of you for a bit. I dont suppose you still use your old gmail? I still have that one. Mine is the same, my user name obviously. If you see this give me a shout I would like to catch up. NGEMU is quite dead and I can't get past the anti spam to send a PM.

    ReplyDelete
    Replies
    1. Hi, Rain.

      I've sent you a mail, hope you got it.
      Yeah, I still use my old gmail account for the "scene".

      Delete