I'm working on a FF9 savegame editor (anyone got a good idea for a name
). I need some help understanding how the psx memorycard works and where the data is. I've tried some searching with
some luck. But lets see if I've gotten the gist of things. I've worked on a .mcr file.
PART 1. MEMORY CARD HEADERSWhen I open a .mcr file with a hex-editor, the header -0x80 bytes- looks like this:
?? ?? ?? ?? ?? ?? .... ?? ?? ?? CS
4D 43 00 00 00 00 .... 00 00 00 0E
Question1: What do the "??" represent? Are they even important when making a save editor (pointers etc)?
The last one being a checksum, the bytes are XORed 'til the end of the header.
Then the header for each slot follows, 0x80 bytes each (if I got it down right). The checksum is on the last byte and is calculated the same way. Here are the 1st FF9 saveslot header on my card:
?? ?? ?? ?? ?? ?? ?? ?? ?? ?? [<--- Region/DiscNr code --->] [SlotNr]
51 00 00 00 00 20 00 00 FF FF 42 45 53 4C 45 53 2D 30 32 39 36 35 30 30 30 30 30 2D 30 30 00 00
?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ??
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ??
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? CS
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 77
Question2: What are the "??" here? Specially the ones before Region/DiscNr code. Nuber of slots to use?
Region/DiscNr code + SlotNr are read like this as a string:
BESLES-0296500000-00
I'm guessing this means PAL disc1 code stuff, and that it is slot nr 1 (read as 0. The 3 last bytes here are slot nr, so no need to include 'em further).
Below is what I've read testing saves from all discs. And I'm pretty sure I'm correct.
PAL disc 1 = BESLES-0296500000
PAL disc 2 = BESLES-1296500000
PAL disc 3 = BESLES-2296500000
PAL disc 4 = BESLES-3296500000
Question 3: How do the NTSC codes look like, and are there other versions (Spanish, German, etc)?
It would be great if there only were 2 versions of this: NTSC and PAL.
PART 2. SAVE MAP OFFSETSHere I could use much help. I dunno what the stuff from after the last slot 'til the beginning of save-data is (offset 0x800 - 0x1FFF). Before the 1st save-data, starting at 0x2000, there seems to be another header equal to the 1st one in the file. I guess it doesn't matter much though, as it's mostly just 0x00 bytes.
I'm guessing it might be something to do with games which use multiple slots. Or not...
Anyway, here are the data I've found by searching the web and analyzing saves. Each save block are 2000h bytes long.
0x0105: BYTE Level; // Party leader level
0x0106: BYTE Name[8]; // Party leader name
0x010E: BYTE Unknown; // ???
0x010F: BYTE Unknown; // ???
0x0106: BYTE Location[28]; // Name of current location
0x012C: BYTE Gametime; // Gametime (expressed in tenth of a second)
0x0130: BYTE Gil; // Total amount of Gil
0x0ee8 | 00 00 00 00 = 0 // Number of Gil
// ============================================================================
// Final Fantasy IX | Savegame | Character Stats
// Start Pointer: 0x09d0
// End Pointer: 0x0EDF
// Block Count: 9
// Block Size: 144 bytes
// Total Size: 1296 bytes
// ============================================================================
0x0000: BYTE Name[8]; // Character name
0x0008: BYTE Unknown; // ???
0x0009: BYTE Unknown; // ???
0x000A: BYTE Unknown; // ???
0x000B: BYTE Level; // Character level
0x000C: DWORD Experience; // Total amount of experience ?
0x0010: WORD CurrentHP; // Current amount of HP
0x0012: WORD CurrentMP; // Current amount of MP
0x0014: BYTE Unknown; // ???
0x0015: BYTE Unknown; // ???
0x0016: BYTE Unknown; // ???
0x0017: BYTE CurrentMS; // Current amount of magical stones
0x0018: BYTE MaxHP; // Max amount of HP
0x001A: BYTE MaxMP; // Max amount of MP
0x001C: BYTE Unknown; // ???
0x001D: BYTE Unknown; // ???
0x001E: BYTE Unknown; // ???
0x001F: BYTE MaxMS; // Max amount of magical stones
0x0020: BYTE TranceLevel; // Trance Level
0x0021: BYTE Unknown; // ???
0x0022: BYTE Unknown; // ???
0x0023: BYTE Unknown; // ???
0x0024: BYTE Speed; // Speed (total value incl. gear bonuses)
0x0025: BYTE Strength; // Strength (total value incl. gear bonuses)
0x0026: BYTE Magic; // Magic (total value incl. gear bonuses)
0x0027: BYTE Spirit; // Spirit (total value incl. gear bonuses)
0x0028: BYTE Defence; // Defence
0x0029: BYTE Evade; // Evade
0x002A: BYTE MagicDefence; // Magic defence
0x002B: BYTE MagicEvade; // Magic evade
0x002C: WORD 2nd HP max; // Max HP with Bonus
0x002E: WORD 2nd MP max; // Max MP with Bonus
0x0030: BYTE BaseSpeed; // Base speed (excl. gear bonuses)
0x0031: BYTE BaseStrength; // Base strength (excl. gear bonuses)
0x0032: BYTE BaseMagic; // Base magic (excl. gear bonuses)
0x0033: BYTE BaseSpirit; // Base spirit (excl. gear bonuses)
0x0034: BYTE Unknown; // ???
0x0035: BYTE Unknown; // ???
0x0036: BYTE Unknown; // ???
0x0037: BYTE Unknown; // ???
0x0038: BYTE Status; // Status bits.
0x0039: BYTE Weapon; // Equiped weapon
0x003A: BYTE Headgear; // Equiped head gear
0x003B: BYTE Armgear; // Equiped arm gear
0x003C: BYTE Armor; // Equiped armor
0x003D: BYTE Addon; // Equiped add-on
0x003E: BYTE Unknown; // ???
0x003F: BYTE Unknown; // ???
0x0040: BYTE Unknown; // ???
0x0041: BYTE Unknown; // ???
0x0042: BYTE Unknown; // ???
0x0043: BYTE Unknown; // ???
0x0044: BYTE Unknown; // ???
0x0045: BYTE Unknown; // ???
0x0046: BYTE Unknown; // ???
0x0047: BYTE Unknown; // ???
0x0048: BYTE Unknown; // ???
0x0049: BYTE Unknown; // ???
0x004A: BYTE Unknown; // ???
0x004B: BYTE Unknown; // ???
0x004C: BYTE Unknown; // ???
0x004D: BYTE Unknown; // ???
0x004E: BYTE Unknown; // ???
0x004F: BYTE Unknown; // ???
0x0050: BYTE Unknown; // ???
0x0051: BYTE Unknown; // ???
0x0052: BYTE Unknown; // ???
0x0053: BYTE Unknown; // ???
0x0054: BYTE Unknown; // ???
0x0055: BYTE Unknown; // ???
0x0056: BYTE Unknown; // ???
0x0057: BYTE Unknown; // ???
0x0058: BYTE Unknown; // ???
0x0058: BYTE AbilityAP[48]; // AP for action/support abilities
0x0088: BYTE Support[8]; // Support abilities equiped
// ============================================================================
// Final Fantasy IX | Savegame | Item List
// Start Pointer: 0x0F20
// End Pointer: 0x111F
// Block Count: 256
// Block Size: 2 bytes
// Total Size: 512 bytes
// ============================================================================
0x0000: BYTE ID; // Item ID
0x0001: BYTE Count; // Item Count
CARDS:
0x1178: WORD WINS?
0x117A: WORD LOSSES?
0x117C: WORD DRAWS?
0x119A: BYTE Card Count? // Number of cards in stock
0x119B: BYTE Type Count? // Number of card types
// ============================================================================
// Final Fantasy IX | Savegame | Cards
// Start Pointer: 0x119C
// End Pointer: 0x13F3
// Block Count: 100
// Block Size: 6 bytes
// Total Size: 600 bytes
// ============================================================================
0x0000: BYTE ID? ; // Type ID (FFh = empty block)?
0x0001: BYTE Arrow bits?; // Bitmap representing arrows?
0x0002: BYTE Attack type?; // Type of attack (physical, magical etch.)?
0x0003: BYTE Attack?; // Atack Power?
0x0004: BYTE P.Def?; // Physical defence power?
0x0005: BYTE M.Def?; // Magical defence power?
I see there are some errors here (BYTE instead of WORD etc), but I'm too lazy to correct 'em. The bit length should be obvious in most cases.