• Welcome to Final Fantasy Hacktics. Please login or sign up.

Code Documentation Thread

Started by formerdeathcorps, March 10, 2014, 03:25:07 am


March 10, 2014, 03:25:07 am Last Edit: March 10, 2014, 07:36:15 am by formerdeathcorps

The main code for WotL is located in BOOT.BIN.  This thread is dedicated to its documentation.

Rafa / Malak New Hardcoding (found in 0xCF8CC in BOOT.BIN)

088d3878: 3c0408a7 lui r4,0x08a7
088d387c: 248464c0 addiu r4,r4,0x64c0
088d3880: 00853021 addu r6,r4,r5           //r6 = Ability Offset
088d3884: 90c50003 lbu r5,0x0003(r6)     //r5 = Ability Flags 1
088d3888: 90d10009 lbu r17,0x0009(r6)    //r17 = Ability X
088d388c: 3c04092f lui r4,0x092f
088d3890: 90d20008 lbu r18,0x0008(r6)    //r18 = Ability Formula
088d3894: a085975c sb r5,-0x68a4(r4)     //Store r5 in ability RAM.
088d3898: 324500ff andi r5,r18,0x00ff
088d389c: 24a4ffe2 addiu r4,r5,-0x001e
088d38a0: 2c810002 sltiu r1,r4,0x0002
088d38a4: 50200027 beql r1,r0,0x088d3944    //If not Rafa / Malak formulas, check for Formula 5E (Triple Thunder / Flame)
088d38a8: 2404005e addiu r4,r0,0x005e
088d38ac: 3c04092e lui r4,0x092e
088d38b0: 8c845b9c lw r4,0x5b9c(r4)
088d38b4: 14800022 bne r4,r0,0x088d3940      //If not during combat phase, check for Formula 5E
088d38b8: 00000000 nop
088d38bc: 3c1008a8 lui r16,0x08a8
088d38c0: 00002021 addu r4,r0,r0
088d38c4: 0e288700 jal 0x08a21c00               //Stores 0 (r4) into 0x097a7514
088d38c8: 2610b1f0 addiu r16,r16,-0x4e10      //r16 = Chance of N Hits Table Offset (see below)
088d38cc: 3c0408a8 lui r4,0x08a8
088d38d0: 2484b1fc addiu r4,r4,-0x4e04
088d38d4: 0e2886c0 jal 0x08a21b00            //Input r4 = 0x08a7b1fc, r5 = 0x155e into routine, but these values (which seem to be an offset containing a special RNG seed / multiplier) are not used
088d38d8: 2405155e addiu r5,r0,0x155e

088d38dc: 00021880 sll r3,r2,0x02
088d38e0: 00622021 addu r4,r3,r2
088d38e4: 00041880 sll r3,r4,0x02
088d38e8: 00831821 addu r3,r4,r3
088d38ec: 00031880 sll r3,r3,0x02                     //r3 = RN{0...7FFF} * 100
088d38f0: 04610003 bgez r3,0x088d3900            //This is guaranteed, GOTO 0x88d3900 and r5 = RN{0...99}
088d38f4: 00032bc3 sra r5,r3,0x0f
088d38f8: 24637fff addiu r3,r3,0x7fff                 //Ensures positivity, but this isn't necessary.
088d38fc: 00032bc3 sra r5,r3,0x0f
088d3900: 3c0308a8 lui r3,0x08a8
088d3904: 9064b1f0 lbu r4,-0x4e10(r3)              //Starting at 0x08a7b1f0 (or BOOT.BIN 0x277244) is a table listing the probability of for getting N hits on Rafa / Malak formulas.  There are 10 entries; thus, the maximum # of hits is hard-coded as 10.
Hit 1    5%
Hit 2    5%
Hit 3    10%
HIt 4   10%
Hit 5    20%
HIt 6    20%
HIt 7    10%
Hit 8    10%
Hit 9     5%
Hit 10    5%
088d3908: 0085082a slt r1,r4,r5
088d390c: 10200009 beq r1,r0,0x088d3934          //GOTO 0x88d3934 if failed on the first attempt
088d3910: 24110001 addiu r17,r0,0x0001             //r17 = 1
088d3914: 00a42823 subu r5,r5,r4                     //ELSE (on success), reduce RN by the probability of the previous table entry
088d3918: 26100001 addiu r16,r16,0x0001           //Increment one slot on the failure table
088d391c: 26230001 addiu r3,r17,0x0001
088d3920: 92040000 lbu r4,0x0000(r16)
088d3924: 307100ff andi r17,r3,0x00ff               //r17++
088d3928: 0085182a slt r3,r4,r5
088d392c: 5460fffa bnel r3,r0,0x088d3918         //Keep going until number of hits is determined
088d3930: 00a42823 subu r5,r5,r4
088d3934: 3c03092e lui r3,0x092e
088d3938: 10000048 beq r0,r0,0x088d3a5c       //GOTO OTHER CHECKS, store r17 as the number of hits
088d393c: a0715c4e sb r17,0x5c4e(r3)
The destruction of the will is the rape of the mind.
The dogmas of every era are nothing but the fantasies of those in power; their dreams are our waking nightmares.


Changes to Unit Tables:

089b8fe8: 00161100 sll r2,r22,0x04
089b8fec: 00561023 subu r2,r2,r22
089b8ff0: 00021080 sll r2,r2,0x02
089b8ff4: 00561021 addu r2,r2,r22
089b8ff8: 000218c0 sll r3,r2,0x03           //r3 = Unit ID * 0x1e8
089b8ffc: 3c02092e lui r2,0x092e
089b9000: 24425cb4 addiu r2,r2,0x5cb4
089b9004: 00438821 addu r17,r2,r3          //r17 = 0x92e5cb4 + unit ID * 0x1e8

In other words, each unit's basic data is 0x1e8 long (0x28 longer than vanilla).  It starts at 0x92e5cb4.  For reference, this is vanilla's unit RAM table:

At the most conservative, the following changes are necessary:

This accounts for 0x15 out of 0x28 new bytes.

Half of MP Check:
089b9084: 9222009a lbu r2,0x009a(r17)
089b9088: 30420080 andi r2,r2,0x0080
089b908c: 10400006 beq r2,r0,0x089b90a8                     //If not Half of MP, GOTO MP Check
089b9090: 9064000d lbu r4,0x000d(r3)
089b9094: 04810003 bgez r4,0x089b90a4                        //ELSE, halve the MP cost of the spell
089b9098: 00041043 sra r2,r4,0x01
089b909c: 24820001 addiu r2,r4,0x0001                         //An impossible branch
089b90a0: 00021043 sra r2,r2,0x01
089b90a4: 00402021 addu r4,r2,r0
089b90a8: 96220036 lhu r2,0x0036(r17)
089b90ac: 0044082a slt r1,r2,r4
089b90b0: 14200051 bne r1,r0,0x089b91f8                      //If CurMP < MP Cost, GOTO END
089b90b4: 00000000 nop

We see that there are 8 additional bytes between vanilla's current MP (0x2e) vs. WotL's (0x36).  Assuming the same order as vanilla, 7 of the 8 bytes are accounted for with the changes to equip IDs, leaving 1 mystery byte.
WE see that there are 10 additional bytes between vanilla's Half of MP (0x90) vs. WotL's (0x9a).  Assuming the same order as vanilla, 8 of the 10 bytes are accounted for with the changes to equip IDs and types, leaving 2 mystery bytes.
Assuming the number of crystals eaten per character is stored somewhere before current MP, that leaves one extra byte in WotL from curMP to Half of MP that doesn't exist in vanilla.

Innocent / EQ Sword / EQ Materia Blade Checks:
089b90d0: 9222005c lbu r2,0x005c(r17)
089b90d4: 30420040 andi r2,r2,0x0040
089b90d8: 14400047 bne r2,r0,0x089b91f8                               //If caster is Always: Innocent, GOTO END
089b90dc: 00000000 nop
089b90e0: 90630006 lbu r3,0x0006(r3)
089b90e4: 30620008 andi r2,r3,0x0008
089b90e8: 50400007 beql r2,r0,0x089b9108                              //If ability does not have EQ Sword flagged, GOTO Check Next
089b90ec: 30620004 andi r2,r3,0x0004
089b90f0: 922201a8 lbu r2,0x01a8(r17)
089b90f4: 30420008 andi r2,r2,0x0008
089b90f8: 14400009 bne r2,r0,0x089b9120                              //ELSE IF Sword is equipped, GOTO Success
089b90fc: 00000000 nop
089b9100: 1000003d beq r0,r0,0x089b91f8                              //ELSE, GOTO END
089b9104: 00000000 nop
089b9108: 10400005 beq r2,r0,0x089b9120                              //If ability does not have EQ Materia Blade flagged, GOTO Success
089b910c: 00000000 nop
089b9110: 922201a8 lbu r2,0x01a8(r17)
089b9114: 30420004 andi r2,r2,0x0004
089b9118: 10400037 beq r2,r0,0x089b91f8                             //ELSE IF Materia Blade is not equipped, GOTO END

This passage is also revealing in its own way.  We see that innocent is also transposed 10 bytes (from 0x52 in vanilla to 0x5c here).  This means we can narrow the bounds of the unknown byte mentioned above.  It is located between curMP (0x2e) and innocent (0x5c).
Similarly, the byte that detects if the unit is equipping a materia blade or sword has been transposed 36 bytes (from 0x184 in vanilla to 0x1a8 here).  Out of these 36 bytes, only the 21 bytes given in the "obvious additions" list are accounted for, so there are 15 unknown bytes located between Half of MP (0x9a) and Equipped Items Check Byte (0x1a8).
The destruction of the will is the rape of the mind.
The dogmas of every era are nothing but the fantasies of those in power; their dreams are our waking nightmares.


March 12, 2014, 09:48:53 am #2 Last Edit: March 13, 2014, 07:26:49 am by formerdeathcorps

After a review of how to unlock dark knight, it seems two bytes are needed to track the necessary data.
1) ID of the unit that killed this character.
2) # of kills scored (not the # of crystals eaten).
EDIT: Found 'em!  They were tacked onto the end of the unit RAM table.

092e5c44 - Target's Data Pointer
092e5c48 - Attacker's Data Pointer
With these two pieces of data, WotL battle mechanics are now fully hackable!  Have at it, FFH!
The destruction of the will is the rape of the mind.
The dogmas of every era are nothing but the fantasies of those in power; their dreams are our waking nightmares.


  • Modding version: PSX
<@Angel> Teach a man to fish and he'll open up a fishery to compete against yours.

Journey of the Five Youtube ChannelThe Lion War Current Status
Jot5 Leader :: Eventer :: OtherTLW Leader :: Eventer :: Other


  • Modding version: PSX
Kotetsu Quad Killer!!


February 22, 2018, 03:20:45 am #5 Last Edit: February 27, 2018, 02:49:03 am by Quantumpencil
WeaponXA() location in EBOOT.Bin are as follows:

Formula Pointers are at 0x08A7500C

0x88A54C0 - main routine, branches to all specific weapon type ID's, and includes the formula for fell swords at 0x88A5748

Specific XA calc locations:

PA -> 0x88A559C
PA * Br/100 -> 0x88A5610
SP+PA/2 - > 0x88A55DC
1....PA -> 0x88A56BC
PA*(100-FA)/100 -> 0x88A5748
PA + MA -> 0x88A5714

ElementalModifiers() is located at 0x88A6040
This handles oil, float, and elemental weak/half/null/absorb flag setting

SetStatusChanges() is located at 0x 88A4540
This reads from the status data and handles cancelling statuses, stackable/unstackable statuses, the immortal ENTD flag, and not inflicting statuses that a unit is immune to or already has.

A large damage modifiers function (which I am not totally done decoding yet) begins at 0x88AA180; it handles elemental strengthening, arcane defense, aracane strength, applies damage boosts due to toad and chicken, handles defend, and some more things.  It calls both the elemental/status setting routines. I will update with more info once I have finished parsing it.

EDIT: The above function is the main magic damage formula; I have found/documented many of the formulas real locations in EBOOT.bin. I'll start porting hacks/writing some documentation for all of this in the coming weeks

  • Modding version: WotL
Modding version: WotL


281248: Ramza's starting stats and equipment. Can't find his level nor his Bravery/Faith, though.

EDIT: The offset is for an ISO though.