Author Topic: [WIP] FF9 Save editor. Memory card and save offset stuff.  (Read 32402 times)

gjoerulv

  • *
  • Posts: 1214
  • me
    • View Profile
    • My Youtube
I'm working on a FF9 savegame editor (anyone got a good idea for a name  :P). 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 HEADERS

When I open a .mcr file with a hex-editor, the header -0x80 bytes- looks like this:

Code: [Select]
?? ?? ?? ?? ?? ?? .... ?? ?? ?? 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:
Code: [Select]
?? ?? ?? ?? ?? ?? ?? ?? ?? ?? [<---           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:

Code: [Select]
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.

Code: [Select]
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.  :-D


PART 2. SAVE MAP OFFSETS

Here 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.  :roll: 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.

Code: [Select]
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.

Aali

  • *
  • Posts: 1196
    • View Profile
Re: [WIP] FF9 Save editor. Memory card and save offset stuff.
« Reply #1 on: 2010-09-14 00:51:59 »
May I suggest Freya as the name for this program? Assuming its not already taken by some other tool.

gjoerulv

  • *
  • Posts: 1214
  • me
    • View Profile
    • My Youtube
Re: [WIP] FF9 Save editor. Memory card and save offset stuff.
« Reply #2 on: 2010-09-14 00:59:42 »
Ye, that might work. Freya is one smexy rat!

Senti

  • *
  • Posts: 79
  • There's a fine line between insanity and ingenius
    • View Profile
    • Psychopathic Studios
Re: [WIP] FF9 Save editor. Memory card and save offset stuff.
« Reply #3 on: 2010-09-14 04:36:30 »
I would personally recommend Blank as the name of the editor, not a main character, but he is the first to truly save Zidane, Steiner and Garnet by sacrificing himself to keep them alive.

Bosola

  • Fire hazard!
  • *
  • Posts: 1748
    • View Profile
    • My YouTube Channel
Re: [WIP] FF9 Save editor. Memory card and save offset stuff.
« Reply #4 on: 2010-09-14 19:57:55 »
Dibs on calling the FF9 Enemy Editor Garland.

Covarr

  • Covarr-Let
  • Administrator
  • *
  • Posts: 3941
  • Just Covarr. No "n".
    • View Profile
Re: [WIP] FF9 Save editor. Memory card and save offset stuff.
« Reply #5 on: 2010-09-14 20:28:24 »
Obviously, you should call it Kefka_Leonhart37. Just sayin'.

gjoerulv

  • *
  • Posts: 1214
  • me
    • View Profile
    • My Youtube
Re: [WIP] FF9 Save editor. Memory card and save offset stuff.
« Reply #6 on: 2010-09-14 22:40:04 »
I would personally recommend Blank as the name of the editor, not a main character, but he is the first to truly save Zidane, Steiner and Garnet by sacrificing himself to keep them alive.

Actually that's not a bad idea.

Dibs on calling the FF9 Enemy Editor Garland.

As a long term plan I was planing on making one myself. Are you making one? Anyway, Garland would be THE perfect name for one.  :-D

Obviously, you should call it Kefka_Leonhart37. Just sayin'.

Consider it done!  ;D

EDIT:

Actually I found out each slot header has a game ID and a product code. And, yay, I revealed the NTCS codes.

Code: [Select]
PAL disc 1 = BESLES-02965
PAL disc 2 = BESLES-12965
PAL disc 3 = BESLES-22965
PAL disc 4 = BESLES-32965

NTSC disc 1 = BASLUS-01251
NTSC disc 2 = BASLUS-01295
NTSC disc 3 = BASLUS-01296
NTSC disc 4 = BASLUS-01297

Game ID = 00000-[saveNr on memcard]

If someone has any info. on the psx memcard structure I would be glad.
« Last Edit: 2010-09-19 18:57:03 by gjoerulv »

Zande

  • *
  • Posts: 55
  • 友情は武器よりも強し
    • View Profile
Re: [WIP] FF9 Save editor. Memory card and save offset stuff.
« Reply #7 on: 2010-09-20 17:22:46 »
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.  :-D
There's seven different versions of the game, here's the disc ID's for them all:

Code: [Select]
Japanese      SLPS_020.00, SLPS_020.01, SLPS_020.02, SLPS_020.03
English (USA) SLUS_012.51, SLUS_012.95, SLUS_012.96, SLUS_012.97
English (EU)  SLES_029.65, SLES_129.65, SLES_229.65, SLES_329.65
French        SLES_029.66, SLES_129.66, SLES_229.66, SLES_329.66
German        SLES_029.67, SLES_129.67, SLES_229.67, SLES_329.67
Italian       SLES_029.68, SLES_129.68, SLES_229.68, SLES_329.68
Spanish       SLES_029.69, SLES_129.69, SLES_229.69, SLES_329.69

For the savefiles, the first 2 characters (region code?) in the ID is BE for all european discs (eg. BESLES-02965), BA for the USA ones (eg. BASLUS-01251), and BI for the japanese ones (eg. BISLPS-02000). And they all use the same save file format structure (but the japanese version uses a different character table for strings of course), which is probably also the reason サラマンダー wasn't called Salamander (but Amarant) outside of Japan as it doesn't fit the 8 byte character name limit.

gjoerulv

  • *
  • Posts: 1214
  • me
    • View Profile
    • My Youtube
Re: [WIP] FF9 Save editor. Memory card and save offset stuff.
« Reply #8 on: 2010-09-20 22:48:43 »
Thanks Zande, this'll help. I figured those BEs and BAs where regional stuff. The stuff you listed are the product codes, while the rest of the header info (I know of) are the game-IDs (the end is not slot# as I typed in the opening post, but part of the game id).

EDIT:

ok, so I've compared some saves and figured out the bitmap at the end of the character data. Each ability equipped has a flag, and it looks like this (must not be read as memory, but like you would see it in an hex editor):

Code: [Select]
Auto-Potion     00 00 00 00 00 00 00 01
Locomotion      00 00 00 00 00 00 00 02
Clear Headed    00 00 00 00 00 00 00 04
Boost           00 00 00 00 00 00 00 08
Odin's Sword    00 00 00 00 00 00 00 10
Mug             00 00 00 00 00 00 00 20
Bandit          00 00 00 00 00 00 00 40
??????          00 00 00 00 00 00 00 80
Insomniac       00 00 00 00 00 00 01 00
Antibody        00 00 00 00 00 00 02 00
Bright Eyes     00 00 00 00 00 00 04 00
Loudmouth       00 00 00 00 00 00 08 00
Restore HP      00 00 00 00 00 00 10 00
Jelly           00 00 00 00 00 00 20 00
Return Magic    00 00 00 00 00 00 40 00
Absorb MP       00 00 00 00 00 00 80 00
Body Temp       00 00 00 00 00 01 00 00
Alert           00 00 00 00 00 02 00 00
Initiative      00 00 00 00 00 04 00 00
Level Up        00 00 00 00 00 08 00 00
Ability Up      00 00 00 00 00 10 00 00
Millionaire     00 00 00 00 00 20 00 00
Flee-Gil        00 00 00 00 00 40 00 00
Guardian Mog    00 00 00 00 00 80 00 00
Mag Elem Null   00 00 00 00 01 00 00 00
Concentrate     00 00 00 00 02 00 00 00
Half MP         00 00 00 00 04 00 00 00
High Tide       00 00 00 00 08 00 00 00
Counter         00 00 00 00 10 00 00 00
Cover           00 00 00 00 20 00 00 00
Protect Girls   00 00 00 00 40 00 00 00
Eye 4 Eye       00 00 00 00 80 00 00 00
Healer          00 00 00 01 00 00 00 00
Add Status      00 00 00 02 00 00 00 00
Gamble Defence  00 00 00 04 00 00 00 00
??????          00 00 00 08 00 00 00 00
Power Throw     00 00 00 10 00 00 00 00
Power Up        00 00 00 20 00 00 00 00
Reflect-Null    00 00 00 40 00 00 00 00
Reflectx2       00 00 00 80 00 00 00 00
Undead Killer   00 00 01 00 00 00 00 00
Dragon Killer   00 00 02 00 00 00 00 00
Devil Killer    00 00 04 00 00 00 00 00
Beast killer    00 00 08 00 00 00 00 00
Man Eater       00 00 10 00 00 00 00 00
High Jump       00 00 20 00 00 00 00 00
Master Thief    00 00 40 00 00 00 00 00
Steal Gil       00 00 80 00 00 00 00 00
MP+20%          00 01 00 00 00 00 00 00
Accuracy+       00 02 00 00 00 00 00 00
Distract        00 04 00 00 00 00 00 00
Long Reach      00 08 00 00 00 00 00 00
MP Attack       00 10 00 00 00 00 00 00
Bird Killer     00 20 00 00 00 00 00 00
Bug Killer      00 40 00 00 00 00 00 00
Stone Killer    00 80 00 00 00 00 00 00
Auto-Reflect    01 00 00 00 00 00 00 00
Auto-Float      02 00 00 00 00 00 00 00
Auto-Haste      04 00 00 00 00 00 00 00
Auto-Regen      08 00 00 00 00 00 00 00
Auto-Life       10 00 00 00 00 00 00 00
HP+10%          20 00 00 00 00 00 00 00
HP+20%          40 00 00 00 00 00 00 00
MP+10%          80 00 00 00 00 00 00 00

??????          00 00 00 00 00 00 00 80
??????          00 00 00 08 00 00 00 00

Can someone see what abilities I've might forgotten (the ? ?? ?? ?, 2 of 'em). Or maybe they're dummied out? I can't check 'em be setting these flags 'cause then I get a bad checksum. sigh, I gotta figure out that checksum out too. As I see it, it's not a crc, but a 2 byte checksum at offset 0x13FE. As far as I'm concerned, FF9 doesn't use any space from 0x1400 and out.
« Last Edit: 2010-09-28 12:12:49 by gjoerulv »

kruci

  • *
  • Posts: 105
    • View Profile
Re: [WIP] FF9 Save editor. Memory card and save offset stuff.
« Reply #9 on: 2010-09-30 19:44:56 »
Those are all abilities in file 08_04a.txt.... (dont ask what the hell that name means!)
this is how they are sorted in data file
Code: [Select]
Ability Up
Absorb MP
Accuracy+
Add Status
Alert
Antibody
Auto-Float
Auto-Haste
Auto-Life
Auto-Potion
Auto-Reflect
Auto-Regen
Bandit
Beast Killer
Bird Killer
Body Temp
Boost
Bright Eyes
Bug Killer
Chemist
Clear Headed
Concentrate
Counter
Cover
Devil Killer
Distract
Dragon Killer
Eye 4 Eye
Flee-Gil
Gamble Defense
Guardian Mog
HP+10%
HP+20%
Half MP
Healer
High Jump
High Tide
Initiative
Insomniac
Jelly
Level Up
Locomotion
Long Reach
Loudmouth
MP Attack
MP+10%
MP+20%
Mag Elem Null
Man Eater
Master Thief
Millionaire
Mug
Odin’s Sword
Power Throw
Power Up
Protect Girls
Reflect-Null
Reflectx2
Restore HP
Return Magic
Steal Gil
Stone Killer
Undead Killer
Void

Missing
Code: [Select]
Chemist
Void
Supposing that Void is not ability, but void place..... (played only start of FF9)
In mine NTSC version is 'Gamble Defense'  (you have CE in end:P)


header file  in SLUS_012.51
0x5D92A  0x5DB2A, format 2B pointer 6B other chaos, maybe useful for something...
data file in file 0008  (9th file in first folder....:P)  0x8640 0x88D4


gjoerulv

  • *
  • Posts: 1214
  • me
    • View Profile
    • My Youtube
Re: [WIP] FF9 Save editor. Memory card and save offset stuff.
« Reply #10 on: 2010-10-01 14:35:34 »
Missing
Code: [Select]
Chemist
Void
Supposing that Void is not ability, but void place..... (played only start of FF9)
In mine NTSC version is 'Gamble Defense'  (you have CE in end:P)

Thanks! I thought I had chemist... Must've forgotten. And, yes, it's defenCE in the PAL version. British English vs US English.

header file  in SLUS_012.51
0x5D92A  0x5DB2A, format 2B pointer 6B other chaos, maybe useful for something...
data file in file 0008  (9th file in first folder....:P)  0x8640 0x88D4

I'm not sure what you mean here. Inside the .img file on that disc?

oh, and anyone got any intel (lol) on how the checksum/crc?

Armorvil

  • *
  • Posts: 621
  • Working on : FFVII Total Grudge
    • View Profile
Re: [WIP] FF9 Save editor. Memory card and save offset stuff.
« Reply #11 on: 2010-10-01 20:43:16 »
Great, great stuff ! And might I suggest 'Memoria' for its name ? I think it'd be fitting for a FFIX save editor.

Bosola

  • Fire hazard!
  • *
  • Posts: 1748
    • View Profile
    • My YouTube Channel
Re: [WIP] FF9 Save editor. Memory card and save offset stuff.
« Reply #12 on: 2010-10-02 13:42:31 »
So, the save wasn't compressed / encrypted? I just assuned it'd be a complete arseache to decode.

I may be able to help with this.

gjoerulv

  • *
  • Posts: 1214
  • me
    • View Profile
    • My Youtube
Re: [WIP] FF9 Save editor. Memory card and save offset stuff.
« Reply #13 on: 2010-10-04 14:47:04 »
Great, great stuff ! And might I suggest 'Memoria' for its name ? I think it'd be fitting for a FFIX save editor.

Best suggestion so far imo. Using an app called memoria sounds epic in some way...

So, the save wasn't compressed / encrypted? I just assuned it'd be a complete arseache to decode.

I may be able to help with this.

No, as far as I'm concerned there's no compression. At least not the parts I've figured out. Besides, FF9 don't use any space after offset 0x13FF. I have downloaded some saves that have some data after this point, but when I erase this data (zero it to hell), the save is still 100% usable with no difference in-game, no error message when loading the game etc.
I dunno how anybody got data here, 'cause when I play with these saves, and overwrite 'em, I only get zeroes after 0x13FF.
Even when you slightly alter the block's title you get an error (not the header, but the title inside the actual save data), thus I highly doubt FF9 use any space after 0x13FF. Which leads to my conclusion that there is no reason for compression.

I must admit the card-section of the savemap seems encrypted. Either that or the cards are stored in a different order in the savemap. I'm yet to figure it out, but it would help to get the checksum right first. Then It'll be way easier to see differences when I save with my editor and play the game.

Bosola

  • Fire hazard!
  • *
  • Posts: 1748
    • View Profile
    • My YouTube Channel
Re: [WIP] FF9 Save editor. Memory card and save offset stuff.
« Reply #14 on: 2010-10-07 18:02:33 »
Hunch? I'd guess there were a set of "Seen card?" flags and then data for the quantities.

I'd like to see how that data changes when you pick up and lose cards.

kruci

  • *
  • Posts: 105
    • View Profile
Re: [WIP] FF9 Save editor. Memory card and save offset stuff.
« Reply #15 on: 2010-10-09 18:40:02 »
header file  in SLUS_012.51
0x5D92A  0x5DB2A, format 2B pointer 6B other chaos, maybe useful for something...
data file in file 0008  (9th file in first folder....:P)  0x8640 0x88D4

I'm not sure what you mean here. Inside the .img file on that disc?

Yeah, that's inside .img file.
I thought that .img file structure is 'common' knowledge since it was long time ago posted here by someone (maybe in wiki too).
Its structure is something like 'folders and files' - that's why I refer to '9th file in first folder'.
There was some extractor of .img file posted here, seen in q-gears svn if I am not wrong.
(But it lack import, which I needed, so I made one myself:P)

keyosuke

  • Guest
Re: [WIP] FF9 Save editor. Memory card and save offset stuff.
« Reply #16 on: 2010-12-18 02:29:31 »
I just wanted to say good luck on the save file editor.  If you get far enough that it can change an attribute and save back to a useable save file, maybe we can get an alpha/beta to play with? I think the hardest part of these type of editors is always checksum related.  Some other game I was reading about stored the checksum twice, and it was a checksum of only part of the save file.  I think 90% of the developement time was checksum related.

gjoerulv

  • *
  • Posts: 1214
  • me
    • View Profile
    • My Youtube
Re: [WIP] FF9 Save editor. Memory card and save offset stuff.
« Reply #17 on: 2011-01-26 15:28:36 »


Ok, a small update as I've started working on it again.
I implemented a "CRC16 assuming checksum finder" (lol). As you can see on the status strip on the form it goes through every polynomial, starting at offset 0 - 256, with every possible initial values on 2 different savegames (block 11 and 12). No need to say it's gonna take hours. And even if I find enough matches it's based on certain assumptions. May very well be a waste of time.  :-\

Timber

  • *
  • Posts: 386
    • View Profile
Re: [WIP] FF9 Save editor. Memory card and save offset stuff.
« Reply #18 on: 2011-01-28 12:21:32 »
Looking really nice gjoerulv :)
Would it be possible to make a 'hard mode' by modding the save files in any way?
I ask because I did this with FFX, by lowing the stats you earn as you progress.
Obviously FFIX has a totally different system, but I would so love to make it more difficult!
Any ideas?

gjoerulv

  • *
  • Posts: 1214
  • me
    • View Profile
    • My Youtube
Re: [WIP] FF9 Save editor. Memory card and save offset stuff.
« Reply #19 on: 2011-01-28 15:12:40 »
The savemap (parts of it) is basically the only knowledge I have 'bout the "inner workings of FF9" lol, so besides lowering stats, level, etch, nothing else pops out from the top of my head.

I would love to have a hard mod for FF9. Any FF needs a hard mode. If I am to make a FF9 enemy editor it's name will certainly be Garland.  :evil:

Micky

  • *
  • Posts: 300
    • View Profile
Re: [WIP] FF9 Save editor. Memory card and save offset stuff.
« Reply #20 on: 2011-01-28 20:57:09 »
I implemented a "CRC16 assuming checksum finder" (lol). As you can see on the status strip on the form it goes through every polynomial, starting at offset 0 - 256, with every possible initial values on 2 different savegames (block 11 and 12). No need to say it's gonna take hours. And even if I find enough matches it's based on certain assumptions. May very well be a waste of time.  :-\
I did the same for the CRC16 checksum in F-Zero FX emblem files, and it didn't take particularly long.

nfitc1

  • *
  • Posts: 2981
  • I just don't know what went wrong.
    • View Profile
    • WM/PrC Blog
Re: [WIP] FF9 Save editor. Memory card and save offset stuff.
« Reply #21 on: 2011-01-29 19:18:16 »
I implemented a "CRC16 assuming checksum finder" (lol). As you can see on the status strip on the form it goes through every polynomial, starting at offset 0 - 256, with every possible initial values on 2 different savegames (block 11 and 12). No need to say it's gonna take hours. And even if I find enough matches it's based on certain assumptions. May very well be a waste of time.  :-\

Not to steal Micky's thunder, but if you're moderately skilled at debugging you could find out where the game checks the CRC and figures out how it's calculated. One thing I've seen that kind of check do is generate a CRC based on the data as it loads then checks the CRC that's saved in the file. There's bound to be a place where it generates the test case so you could check that out.
Alternately, you could find where it writes the save file and see where it pulls the CRC from and how THAT'S generated. If I had a good PSX debugger/emulator I'd help you look. Can you recommend one?

Micky

  • *
  • Posts: 300
    • View Profile
Re: [WIP] FF9 Save editor. Memory card and save offset stuff.
« Reply #22 on: 2011-01-29 19:57:05 »
Not to steal Micky's thunder, but if you're moderately skilled at debugging you could find out where the game checks the CRC and figures out how it's calculated.
Don't worry, other than saying that it is a valid approach to try all polynomials for a CRC16 I didn't mean to do much thundering.

gjoerulv

  • *
  • Posts: 1214
  • me
    • View Profile
    • My Youtube
Re: [WIP] FF9 Save editor. Memory card and save offset stuff.
« Reply #23 on: 2011-01-30 20:31:34 »
I thought I could go the easy way out to just check every poly, calculating from different start offsets. Didn't work with normal crc16. I tried a few algorithms to no avail. My attempts assume a crc16 stored at 0x13FE, that all the data is raw (which shouldn't matter anyway), and that all the data in one saveblock only are checked in one segment. Since my attempts didn't work I tried a Crc16ccitt algorithm (pic), which... didn't work.

Either my assumptions are wrong or my calculations are wrong. I'm pretty sure it's the latter. If you look through the save data you would agree, at least at first glance. Then again, if it's this easy, why isn't there a FF9 save editor available anywhere?

I haven't put much effort into the crc/checksum, but debugging will help if you know what you're doing. Though I'm kinda new to psx emulation, it shouldn't be too hard finding a good emulator. Any help breaking the code would be great.

I'm kinda busy these days however, so I don't expect too much work from me. I'll get to it when I get to it. :P

EDIT: lol, done some debugging
« Last Edit: 2011-02-06 03:05:46 by gjoerulv »

Zande

  • *
  • Posts: 55
  • 友情は武器よりも強し
    • View Profile
Re: [WIP] FF9 Save editor. Memory card and save offset stuff.
« Reply #24 on: 2011-05-06 16:53:29 »
Ok so I'm going to resurrect this topic abit, don't know whenever you're working on this anymore, but for anyone interested...

So out of boredom I started to dig alittle thru FF9 again yesterday, and I started to look for a checksum rutine in the load/save module, and it didn't take too long to discover what I wanted (though I did have some luck aswell :P). The checksum used for the savegames is a standard CRC-16-CCITT algorithm (x16 + x12 + x5 + 1), and besides the CRC calulation rutine there's also a initation rutine for the lookup table which uses the polynomial 0x8404 for the generation. I wrote two C++ equivalents for the generation and calculation so I could try it with a save file. The calculation is done using all bytes from the beginning of a saveslot and up to (but ofcourse excluding) the checksum value, that's 5118 (0x13FE) bytes for the calculation. I would assume that the game data also use the same CRC, but I haven't tried that so I can't confirm that's the case.

Here's the C++ code I wrote for the checksum, I also included a complete lookup table (which do make the initiation function totally pointless, but still Oo), have fun.

Code: [Select]
unsigned short LookupTable[256] = {
0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF,
0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7,
0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E,
0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876,
0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD,
0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5,
0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C,
0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974,
0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB,
0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3,
0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A,
0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72,
0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9,
0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1,
0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738,
0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70,
0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7,
0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF,
0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036,
0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E,
0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5,
0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD,
0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134,
0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C,
0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3,
0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB,
0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232,
0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A,
0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1,
0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9,
0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330,
0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78
};

void InitiateCRC(void) {
    for(unsigned short Index = 0; Index < 256; Index++) {
        unsigned short Value = Index;

        for(unsigned short Bit = 0; Bit < 8; Bit++) {
            if(Value & 0x0001) {
                Value >>= 1;
                Value ^= 0x8408;
            } else {
                Value >>= 1;
            }

            LookupTable[Index] = Value;
        }
    }
}

unsigned short CalculateCRC(unsigned char *Pointer, unsigned short Size = 0x13FE) {
    unsigned short Checksum = 0xFFFF;

    while(Size--)
        Checksum = (Checksum >> 8) ^ LookupTable[(Checksum ^ *Pointer++) & 0xFF];

   return Checksum;
}