• Welcome to Final Fantasy Hacktics. Please login or sign up.
 
June 18, 2024, 03:40:54 pm

News:

Please use .png instead of .bmp when uploading unfinished sprites to the forum!


ASM Collective BATTLE.BIN Map

Started by formerdeathcorps, January 06, 2011, 05:09:33 am

Glain

I talked to fdc a while back about looking at some of the evasion routines, and one thing we talked about was that there were several routines for different kinds of evasion... three called from formulas (physical, charge, and magic). And looking into that, there's another routine that finds the various evasion numbers (A-EV, S-EV, C-EV) within the physical/magic sections that's nearly duplicated, just that it grabs magic evade instead of physical evade for the magic sections. It also turns out that those routines are next to each other in BATTLE.BIN... which means, if we wrote one big routine, we could save some space... or if we decided to change one, we'd only have to change it in one place, in theory.

I came up with this as a combined routine for finding either physical or magic evade numbers (This was the test case I was using for my app, by the way). Here I'm using r4 ($a0) as the parameter (0=physical, 1=magic):



COMBINED EVASION NUMBERS ROUTINE
PARAMETERS: r4 = TYPE (0 = physical, 1 = magical)

# SETUP (r16 = TYPE)
addiu r29,r29,0xffe8
sw r31, 0x0010(r29)
sw r16, 0x0014(r29)
addu r16,r4,r0                              # r16 = r4
lui r4,0x8019
lw r4,0x2d98(r4)                           # r4 = [Target unit]         
bne r16,r0,(SECTION3)                        # Skip next section if Type==MAGIC
addu r7,r0,r0                              # r7 (Can use weapon guard) = 0 (false)

(SECTION2):                        # CHECK FOR WEAPON GUARD (PHYSICAL)
lbu r2,0x008e(r4)                              
nop
andi r2,r2,0x0040                           # r2 = [Reaction is Weapon Guard]   
beq r2,r0,(SECTION3)                           
nop            
jal 0x0018130c                              # CALL: Weapon Guard usability            
nop
sltiu r7,r2,0x0001                           # r7 = !r2                              

(SECTION3):                        # INITIALIZE
ori r2,r0,0x0064
lui r1,0x8019
sb r2,0x38dc(r1)                           # Hit rate = 100
lui r1,0x8019
sb r0,0x38de(r1)                           # A-EV = 0
lui r1,0x8019
sb r0,0x38df(r1)                           # R-EV = 0
lui r1,0x8019
sb r0,0x38e0(r1)                           # L-EV = 0
bne r16,r0,(SECTION3p1)                        
addu r2,r0,r0                               
lbu r2,0x0043(r4)                           

(SECTION3p1):                     # C-EV
lui r1,0x8019
sb r2,0x38e1(r1)                           # C-EV = (Type==MAGIC) ? 0 : [C-EV]
lbu r2,0x0006(r4)                                                   
nop
andi r2,r2,0x0020
bne r2,r0,(RETURN)                           # If target is monster, RETURN
nop

(SECTION4):                        # A-EV
lbu r2,0x001c(r4)
lui r5,0x8006
addiu r5,r5,0x2eb8
sll r3,r2,0x01
addu r3,r3,r2
sll r3,r3,0x02
addu r3,r3,r5
lbu r2,0x0003(r3)            
nop
andi r2,r2,0x0008
beq r2,r0,(SECTION5)                        # Skip A-EV if Accessory isn't actually an accessory
nop
lbu r2,0x0004(r3)
nop
sll r2,r2,0x01
lui r1,0x8006
addu r1,r1,r2
addu r1,r1,r16                              # Use magic evade (1 offset higher) if Type==MAGIC
lbu r2,0x3f58(r1)                           # r2 = [Accessory A-EV]
lui r1,0x8019
sb r2,0x38de(r1)                           # Save [A-EV]

(SECTION5):                        # R-EV (Right hand)
lbu r3,0x001d(r4)                           # r3 = [Right hand weapon of target unit]
nop
sll r2,r3,0x01
addu r2,r2,r3
sll r2,r2,0x02               
lui r1,0x8006
addu r1,r1,r2               
lbu r5,0x2ebb(r1)            
lbu r3,0x001e(r4)                           # r3 = [Right hand shield of target unit]
lbu r8,0x2ebc(r1)            
sll r2,r3,0x01
addu r2,r2,r3
sll r2,r2,0x02               
lui r1,0x8006
addu r1,r1,r2               
lbu r3,0x2ebb(r1)            
lbu r6,0x2ebc(r1)            
andi r2,r5,0x0080            
beq r2,r0,(SECTION5p1)                        # IF [Right hand weapon] not a weapon, skip to shield section
nop
beq r7,r0,(SECTION5p1)                        # IF [No weapon guard], skip to shield section
sll r2,r8,0x03
lui r1,0x8006
addu r1,r1,r2            
addu r1,r1,r16                              # Use magic evade if Type==MAGIC
lbu r2,0x3abd(r1)                           # r2 = [Right-hand weapon evade]
j (SECTION5p2)                              # Skip to save
nop

(SECTION5p1):                           # Shield section
andi r2,r3,0x0040            
beq r2,r0,(SECTION6)                        # IF [Right hand shield] not a shield, skip
sll r2,r6,0x01
lui r1,0x8006
addu r1,r1,r2
addu r1,r1,r16                              # Use magic evade if Type==MAGIC
lbu r2,0x3eb8(r1)                           # r2 = [Right-hand shield S-EV]

(SECTION5p2):                           # Save R-EV
lui r1,0x8019
sb r2,0x38df(r1)                           # Save [R-EV] (Right hand evade)

(SECTION6):                        # L-EV (Left hand)
lbu r3,0x001f(r4)                           # r3 = [Left hand weapon of target unit]
nop
sll r2,r3,0x01
addu r2,r2,r3
sll r2,r2,0x02               
lui r1,0x8006
addu r1,r1,r2               
lbu r5,0x2ebb(r1)            
lbu r3,0x0020(r4)                           # r3 = [Left hand shield of target unit]
lbu r8,0x2ebc(r1)            
sll r2,r3,0x01
addu r2,r2,r3
sll r2,r2,0x02               
lui r1,0x8006
addu r1,r1,r2               
lbu r3,0x2ebb(r1)                        
lbu r6,0x2ebc(r1)            
andi r2,r5,0x0080            
beq r2,r0,(SECTION6p1)                        # IF [Left hand weapon] not a weapon, skip to shield section
nop
beq r7,r0,(SECTION6p1)                        # IF [No weapon guard], skip to shield section
sll r2,r8,0x03
lui r1,0x8006
addu r1,r1,r2
addu r1,r1,r16                              # Use magic evade if Type==MAGIC
lbu r2,0x3abd(r1)                           # r2 = [Left-hand weapon evade]
j (SECTION6p2)                              # Skip to save
nop

(SECTION6p1):                           # Shield section   
andi r2,r3,0x0040            
beq r2,r0,(RETURN)                           # IF [Left hand shield] not a shield, skip
sll r2,r6,0x01
lui r1,0x8006
addu r1,r1,r2
addu r1,r1,r16                              # Use magic evade if Type==MAGIC
lbu r2,0x3eb8(r1)                           # r2 = [Left-hand shield S-EV]

(SECTION6p2):                           # Save L-EV
lui r1,0x8019
sb r2,0x38e0(r1)                           # Save [L-EV] (Left hand evade)

(RETURN):
lw r31,0x0010(r29)
lw r16,0x0014(r29)
addiu r29,r29,0x0018
jr r31                                    # RETURN
nop


That one is probably just about as big as the routine for physical evade was, so there'd be a decent chunk of space gained here (maybe 50-75 lines?), if we wanted to expand the routine.

Then there'd be the main evasion routine to combine:


COMBINED
PARAMETERS: (r4=TYPE (0=physical, 1=charge(physical), 2=magic))

addiu r29,r29,0xffe8
sw r31,0x0010(r29)
sw r16,0x0014(r29)
sw r17,0x000c(r29)
addu r16,r4,r0               # r16 = r4 (0=physical, 1=charge, 2=magic)
slti r17,r16,0x0002
slti r17,r17,0x0001            # r17 = (0=physical/charge, 1=magic)
jal 0x00184f9c               # Equipment Evasion Setting
addu r4,r17,r0               # (r4 == TYPE)
bne r17,r0,(SECTION2)            # IF (TYPE == MAGIC), skip
nop
jal 0x001852e4               # Concentrate Calculation (Attacker)
nop
jal 0x00185328               # Dark/Confuse/Transparent Calculation (Attacker)
nop

(SECTION2):
jal 0x0018537c               # Abandon Calculation (Defender)
nop
jal 0x001853f4               # Evasion Changes due to Status (Defender)
nop
bne r16,r0,(SECTION3)            # If (TYPE != PHYSICAL), skip
nop
jal 0x00185738               # Weather Effects on Bows/Crossbows
nop

(SECTION3):
bne r17,r0,(SECTION4)            # If (TYPE == MAGIC), skip
nop
jal 0x001854fc               # Facing Evade Calculation
nop

(SECTION4):
jal 0x00185814               # Combined Evasion Roll (Calculates Hit %)
nop
lw r31,0x0010(r29)
lw r16,0x0014(r29)
lw r17,0x000c(r29)
addiu r29,r29,0x0018
jr r31
nop


I also replaced the call to a function that did nothing but delegate to another function (which I mentioned earlier in the thread). This is basically a bunch of function calls, so I was just selecting which ones were needed. Here r4 ($a0) is the type parameter, but now is (0=physical, 1=charge, 2=magic).

Of course, that means all the formulas would have to specify r4's value before calling the combined evasion routine (0x188510). That's annoying but luckily there is a nop after each call to the evasion functions, so you could replace the nop with:

Physical: addu r4,r0,r0
Charge: addiu r4,r0,1
Magic: addiu r4,r0,2

A one-time patch could change them, but it's still annoying because new formulas would have to remember to follow that format. Anyhow, this is just an idea for how to consolidate these routines.
  • Modding version: Other/Unknown

formerdeathcorps

May 24, 2011, 05:07:43 pm #81 Last Edit: June 02, 2011, 01:34:06 am by formerdeathcorps
Next routine:


lbu r4, 0x018C (r3) r4 = Target Hit Flag
lbu r5, 0x38F3 (r1) r5 = Ability Flag 1
beq r4, r0, (E) If attack doesn't hit/is negated, GOTO (E)
ori r6, r0, 0x0002
beq r4, r6, (UseAccuracy) If r4 =2 (if formula is % hit to cast status), GOTO (UseAccuracy)
andi r5, r5, 0x0040
bne r5, r0, (ProcCheck) ELSE, if the blank flag directly above Ranged Weapon is flagged, r8 = 100 and GOTO (ProcCheck)
ori r8, r0, 0x0064
j (ProcCheck) ELSE (if blank flag isn't flagged), r8 = 25 and GOTO (ProcCheck)
ori r8, r0, 0x0019
(UseAccuracy) j (ProcCheck) r8 = Attack Accuracy and GOTO (ProcCheck)
lbu r8, 0x01B6 (r3)
(ProcCheck) addu r9, r31, r0 r9 = r31 because r31 will be modified by the following routine.
jal (RNG) To get the random hit%, GOTO (RNG)
addiu r7, r0, 0x0064
lbu r4, 0x38F4 (r1) r4 = Ability Flags 2
slt r6, r7, r8
andi r4, r4, 0x0020
bne r6, r0, (Status/Spell) If RN < Chance, GOTO (Status/Spell)
lbu r5, 0x018C (r3) r6 = Target Hit Flag
ori r6, r0, 0x0002
lbu r7, 0x3906 (r1) r7 = Status Infliction Type Byte
beq r6, r5, (SetZero) If RN > Chance and hit type = 2 (variable hit rate), GOTO (SetZero)
nop
bne r4, r0, (E) If RN > Chance, hit type = 1 (already hit), and proc is spell, GOTO (E)
andi r7, r7, 0x0001
bne r7, r0, (SetZero) If RN > Chance, hit type = 1 (already hit), proc is status, and the 4th blank flag on inflict status is checked, GOTO (SetZero)
nop
j (E) If RN > Chance, hit type = 1 (already hit), proc is status and the 4th blank flag on inflict status isn't checked, GOTO (E)
(Status/Spell) ori r6, r0, 0x0001
bne r4, r0, (Spell) If RN < Chance, hit type = 1 (already hit), and if proc is spell, GOTO (Spell)
sb r6, 0x018C (r3)
j (Status) If RN < Chance, hit type = 1, and if proc is status, GOTO (Status)
nop


(RNG) lui r4, 0xA001
lw r5, -0x6FF0 (r4) Load random word.
lui r6, 0x41C6
addiu r6, r6, 0x4E6D
multu r5, r6
mflo r5
nop
addiu r5, r5, 0x3039
sw r5, -0x6FF0 (r4) Store new Random Word.
multu r7, r5
mfhi r7 r7 = {0...value(r7)-1}
jr 31 Return to Proc Status/Spell Routine
nop

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.

formerdeathcorps

May 25, 2011, 05:09:24 am #82 Last Edit: May 26, 2011, 01:24:02 am by formerdeathcorps
All right, here's an interesting routine, with some hard-coded stuff many of us here would love to delete.


0017d4a0: 27bdffe8 addiu r29,r29,0xffe8
0017d4a4: 3c038019 lui r3,0x8019
0017d4a8: 8c63f5f0 lw r3,-0x0a10(r3)
0017d4ac: 34020001 ori r2,r0,0x0001
0017d4b0: afbf0014 sw r31,0x0014(r29)
0017d4b4: afb00010 sw r16,0x0010(r29)
0017d4b8: 3c018019 lui r1,0x8019
0017d4bc: a02238c2 sb r2,0x38c2(r1) Hit is normal hits, not multi-hit.
0017d4c0: 3c018019 lui r1,0x8019
0017d4c4: a02038c3 sb r0,0x38c3(r1) ???
0017d4c8: 3c018019 lui r1,0x8019
0017d4cc: a42038c8 sh r0,0x38c8(r1) No Spell Procs.
0017d4d0: 3c018019 lui r1,0x8019
0017d4d4: a02038ed sb r0,0x38ed(r1) Attack is not evaded?
0017d4d8: 14600009 bne r3,r0,0x0017d500 If RAM 0x18F5F0 isn't 0, GOTO RAM 0x17D500.
0017d4dc: 00002821 addu r5,r0,r0
0017d4e0: 3c018019 lui r1,0x8019
0017d4e4: a02038e8 sb r0,0x38e8(r1) ELSE, No Spell Procs (again).
0017d4e8: 3c018019 lui r1,0x8019
0017d4ec: a02038e7 sb r0,0x38e7(r1) No EXP bonus.
0017d4f0: 3c018019 lui r1,0x8019
0017d4f4: a020390c sb r0,0x390c(r1) ???
0017d4f8: 3c018019 lui r1,0x8019
0017d4fc: a020390d sb r0,0x390d(r1) ???
0017d500: 9082016f lbu r2,0x016f(r4) Load attack's Skillset ID.
0017d504: 3c018006 lui r1,0x8006
0017d508: 00220821 addu r1,r1,r2
0017d50c: 90265cb4 lbu r6,0x5cb4(r1) Load attack's menu type from SCUS.
0017d510: 3c018019 lui r1,0x8019
0017d514: a020f7ec sb r0,-0x0814(r1) Clear byte where Ability Flags are copied (one of many places).
0017d518: 9082001d lbu r2,0x001d(r4)
0017d51c: 3c018019 lui r1,0x8019
0017d520: a02238c4 sb r2,0x38c4(r1) RH Weapon is stored.
0017d524: 9082001f lbu r2,0x001f(r4)
0017d528: 3c038019 lui r3,0x8019
0017d52c: 906338c4 lbu r3,0x38c4(r3)
0017d530: 3c018019 lui r1,0x8019
0017d534: a02238c5 sb r2,0x38c5(r1) LH Weapon is stored.
0017d538: 340200ff ori r2,r0,0x00ff
0017d53c: 14620008 bne r3,r2,0x0017d560 If RH weapon exists, GOTO RAM 0x17D560.  This is what allows a RH Scorpion Tail and a LH iron sword to always count for 23 WP on holy explosion, even though it's really the WP of the sword that should count.
0017d540: 30c300ff andi r3,r6,0x00ff
0017d544: 9083001f lbu r3,0x001f(r4)
0017d548: 340200ff ori r2,r0,0x00ff
0017d54c: 3c018019 lui r1,0x8019
0017d550: a02238c5 sb r2,0x38c5(r1)
0017d554: 3c018019 lui r1,0x8019
0017d558: a02338c4 sb r3,0x38c4(r1) ELSE, LH weapon is set as primary weapon, and LH weapon byte = none.
0017d55c: 30c300ff andi r3,r6,0x00ff
0017d560: 34020002 ori r2,r0,0x0002
0017d564: 14620006 bne r3,r2,0x0017d580 If attack type isn't THROW, GOTO RAM 0x17D580
0017d568: 00000000 nop
0017d56c: 90820176 lbu r2,0x0176(r4)
0017d570: 3c018019 lui r1,0x8019
0017d574: a02238c4 sb r2,0x38c4(r1) If attack type is THROW, store thrown item and GOTO END.
0017d578: 0805f5bd j 0x0017d6f4
0017d57c: 00000000 nop
0017d580: 10600003 beq r3,r0,0x0017d590 If attack type is <Default>, GOTO RAM 0x17D590
0017d584: 34020006 ori r2,r0,0x0006
0017d588: 1462002b bne r3,r2,0x0017d638 If attack type isn't Monster, GOTO RAM 0x17D638
0017d58c: 30c300ff andi r3,r6,0x00ff
0017d590: 84830170 lh r3,0x0170(r4) If Attack type is <Default> or Monster, load attack ID.
0017d594: 00000000 nop
0017d598: 04610004 bgez r3,0x0017d5ac
0017d59c: 000310c0 sll r2,r3,0x03
0017d5a0: 28620170 slti r2,r3,0x0170
0017d5a4: 1040000b beq r2,r0,0x0017d5d4 If attack is after Potion, GOTO RAM 0x17D5D4
0017d5a8: 000310c0 sll r2,r3,0x03
0017d5ac: 00431023 subu r2,r2,r3
0017d5b0: 00021040 sll r2,r2,0x01
0017d5b4: 3c038006 lui r3,0x8006
0017d5b8: 2463fbf0 addiu r3,r3,0xfbf0
0017d5bc: 00431021 addu r2,r2,r3
0017d5c0: 90430003 lbu r3,0x0003(r2)
0017d5c4: 3c018019 lui r1,0x8019
0017d5c8: a023f7ec sb r3,-0x0814(r1) Store Ability Flags Byte 1
0017d5cc: 90500009 lbu r16,0x0009(r2) Load X
0017d5d0: 90450008 lbu r5,0x0008(r2) Load Formula
0017d5d4: 00000000 nop
0017d5d8: 24a2ffe2 addiu r2,r5,0xffe2
0017d5dc: 2c420002 sltiu r2,r2,0x0002
0017d5e0: 10400010 beq r2,r0,0x0017d624 If Formula is not Rafa's or Malak's, GOTO RAM 0x17D624.  This is the hard-coding of multi-hit for Rafa/Malak.
0017d5e4: 30a300ff andi r3,r5,0x00ff
0017d5e8: 3c028019 lui r2,0x8019
0017d5ec: 8c42f5fc lw r2,-0x0a04(r2)
0017d5f0: 00000000 nop
0017d5f4: 1440000c bne r2,r0,0x0017d628 ELSE if attack hits no one, GOTO RAM 0x17D628.  Because this is only checked once, multi-hit formulas will continue attacking even if all targets in range, including the caster, were killed.
0017d5f8: 3402005e ori r2,r0,0x005e
0017d5fc: 0c0088c3 jal 0x0002230c
0017d600: 00000000 nop
0017d604: 02020018 mult r16,r2
0017d608: 00001012 mflo r2
0017d60c: 04410002 bgez r2,0x0017d618
0017d610: 00000000 nop
0017d614: 24427fff addiu r2,r2,0x7fff
0017d618: 000213c3 sra r2,r2,0x0f
0017d61c: 0805f5bb j 0x0017d6ec ELSE (if Rafa/Malak formula hits), GOTO RAM 0x17D6EC and store r2 = RN{1...X+1}, the amount of hits.
0017d620: 24420001 addiu r2,r2,0x0001
0017d624: 3402005e ori r2,r0,0x005e
0017d628: 14620003 bne r3,r2,0x0017d638 If Formula is not Triple Thunder/Flame's, GOTO RAM 0x17D638.  This is the hard-coding of multi-hit for Triple Flame/Thunder.
0017d62c: 30c300ff andi r3,r6,0x00ff
0017d630: 0805f5bb j 0x0017d6ec  If it is, GOTO RAM 0x17D6EC and store X+1, the amount of hits.  Because there is no corresponding check (like Rafa/Malak) to see if you actually hit anything in the AoE, it is possible to have the animation appear even if nothing is in the AoE.
0017d634: 26020001 addiu r2,r16,0x0001
0017d638: 34020009 ori r2,r0,0x0009
0017d63c: 1062002d beq r3,r2,0x0017d6f4 If attack type is Jump, GOTO END.
0017d640: 34020008 ori r2,r0,0x0008
0017d644: 10620009 beq r3,r2,0x0017d66c
0017d648: 3402000a ori r2,r0,0x000a
0017d64c: 10620007 beq r3,r2,0x0017d66c If attack type is Attack or Charge, GOTO RAM 0x17D66C
0017d650: 00000000 nop
0017d654: 3c028019 lui r2,0x8019
0017d658: 9042f7ec lbu r2,-0x0814(r2)
0017d65c: 00000000 nop
0017d660: 30420020 andi r2,r2,0x0020
0017d664: 10400023 beq r2,r0,0x0017d6f4
0017d668: 00000000 nop
0017d66c: 9082005a lbu r2,0x005a(r4) Attack type here is Attack, Charge, or has Ranged Weapon.
0017d670: 90850091 lbu r5,0x0091(r4)
0017d674: 30420002 andi r2,r2,0x0002
0017d678: 14400006 bne r2,r0,0x0017d694 If attacker is frogged, GOTO RAM 0x17D694
0017d67c: 340200ff ori r2,r0,0x00ff
0017d680: 90820006 lbu r2,0x0006(r4)
0017d684: 00000000 nop
0017d688: 30420020 andi r2,r2,0x0020
0017d68c: 10400005 beq r2,r0,0x0017d6a4 If attacker is not a monster, GOTO RAM 0x17D6A4
0017d690: 340200ff ori r2,r0,0x00ff
0017d694: 3c018019 lui r1,0x8019
0017d698: a02238c4 sb r2,0x38c4(r1) If attacker is frogged or is a monster, RH Weapon = none.
0017d69c: 3c018019 lui r1,0x8019
0017d6a0: a02238c5 sb r2,0x38c5(r1) If attacker is frogged or is a monster, LH Weapon = none.
0017d6a4: 3c048019 lui r4,0x8019
0017d6a8: 248438c4 addiu r4,r4,0x38c4
0017d6ac: 94830000 lhu r3,0x0000(r4)
0017d6b0: 3402ffff ori r2,r0,0xffff
0017d6b4: 1062000a beq r3,r2,0x0017d6e0
0017d6b8: 340300ff ori r3,r0,0x00ff
0017d6bc: 90820000 lbu r2,0x0000(r4)
0017d6c0: 00000000 nop
0017d6c4: 1043000b beq r2,r3,0x0017d6f4
0017d6c8: 00000000 nop
0017d6cc: 3c028019 lui r2,0x8019
0017d6d0: 904238c5 lbu r2,0x38c5(r2)
0017d6d4: 00000000 nop
0017d6d8: 10430006 beq r2,r3,0x0017d6f4
0017d6dc: 00000000 nop
0017d6e0: 30a20001 andi r2,r5,0x0001
0017d6e4: 10400003 beq r2,r0,0x0017d6f4
0017d6e8: 34020002 ori r2,r0,0x0002
0017d6ec: 3c018019 lui r1,0x8019
0017d6f0: a02238c2 sb r2,0x38c2(r1) Store number of hits from multi-hit or two swords.
0017d6f4: 8fbf0014 lw r31,0x0014(r29)
0017d6f8: 8fb00010 lw r16,0x0010(r29)
0017d6fc: 27bd0018 addiu r29,r29,0x0018
0017d700: 03e00008 jr r31
0017d704: 00000000 nop

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.

Pride

Ramza causes game over?


00180b2c: 27bdffe0 addiu r29,r29,0xffe0      
00180b30: 2c820080 sltiu r2,r4,0x0080      
00180b34: afbf001c sw r31,0x001c(r29)      
00180b38: afb20018 sw r18,0x0018(r29)      
00180b3c: afb10014 sw r17,0x0014(r29)      
00180b40: 14400005 bne r2,r0,0x00180b58      
00180b44: afb00010 sw r16,0x0010(r29)      
00180b48: 0806031d j 0x00180c74         
00180b4c: 2402ffff addiu r2,r0,0xffff      
00180b50: 0806031d j 0x00180c74         
00180b54: 2402fffe addiu r2,r0,0xfffe      
00180b58: 00008021 addu r16,r0,r0      
00180b5c: 340600ff ori r6,r0,0x00ff      R6 = FF
00180b60: 308500ff andi r5,r4,0x00ff      
00180b64: 3c038019 lui r3,0x8019      
00180b68: 246308cc addiu r3,r3,0x08cc      Load Unit Data
00180b6c: 90620001 lbu r2,0x0001(r3)      Unit ID
00180b70: 00000000 nop            
00180b74: 10460011 beq r2,r6,0x00180bbc      Branch if unit ID is FF (doesn't exist)?
00180b78: 00000000 nop            
00180b7c: 90620000 lbu r2,0x0000(r3)      Load Sprite Set
00180b80: 00000000 nop            
00180b84: 1445000d bne r2,r5,0x00180bbc      Branch if Sprite set isn't Ramza (01 - 03)?
00180b88: 00000000 nop            
00180b8c: 90620058 lbu r2,0x0058(r3)      Load 1st Set of Current Status
00180b90: 00000000 nop            
00180b94: 30420040 andi r2,r2,0x0040      
00180b98: 14400006 bne r2,r0,0x00180bb4      Branch if in Crystal Status
00180b9c: 00000000 nop            
00180ba0: 90630059 lbu r3,0x0059(r3)      Load 2nd Set of Current Status
00180ba4: 00000000 nop            
00180ba8: 30630001 andi r3,r3,0x0001      
00180bac: 10600031 beq r3,r0,0x00180c74      Branch to end if not in Treasure Status
00180bb0: 02001021 addu r2,r16,r0      
00180bb4: 0806031d j 0x00180c74         
00180bb8: 2402fffd addiu r2,r0,0xfffd      
00180bbc: 26100001 addiu r16,r16,0x0001      
00180bc0: 2a020015 slti r2,r16,0x0015      
00180bc4: 1440ffe9 bne r2,r0,0x00180b6c      
00180bc8: 246301c0 addiu r3,r3,0x01c0      
00180bcc: 00008021 addu r16,r0,r0      
00180bd0: 340800ff ori r8,r0,0x00ff      R8 = FF
00180bd4: 308600ff andi r6,r4,0x00ff      
00180bd8: 34070080 ori r7,r0,0x0080      
00180bdc: 3c038019 lui r3,0x8019      
00180be0: 246308cc addiu r3,r3,0x08cc      Load Unit Data
00180be4: 90650001 lbu r5,0x0001(r3)      Load Unit ID
00180be8: 00000000 nop            
00180bec: 14a8000d bne r5,r8,0x00180c24      
00180bf0: 26100001 addiu r16,r16,0x0001      
00180bf4: 90620000 lbu r2,0x0000(r3)      Load Sprite Set
00180bf8: 00000000 nop            
00180bfc: 1446000a bne r2,r6,0x00180c28      
00180c00: 2a020015 slti r2,r16,0x0015      
00180c04: 90620183 lbu r2,0x0183(r3)      
00180c08: 00000000 nop            
00180c0c: 10450005 beq r2,r5,0x00180c24      
00180c10: 00000000 nop            
00180c14: 1040ffce beq r2,r0,0x00180b50      
00180c18: 00000000 nop            
00180c1c: 10470015 beq r2,r7,0x00180c74      
00180c20: 2402fffd addiu r2,r0,0xfffd      
00180c24: 2a020015 slti r2,r16,0x0015      
00180c28: 1440ffee bne r2,r0,0x00180be4      
00180c2c: 246301c0 addiu r3,r3,0x01c0      
00180c30: 00008021 addu r16,r0,r0      
00180c34: 341200ff ori r18,r0,0x00ff      
00180c38: 309100ff andi r17,r4,0x00ff      
00180c3c: 0c0166bc jal 0x00059af0      
00180c40: 02002021 addu r4,r16,r0      
00180c44: 00401821 addu r3,r2,r0      
00180c48: 90620001 lbu r2,0x0001(r3)      Load Unit ID
00180c4c: 00000000 nop            
00180c50: 10520005 beq r2,r18,0x00180c68      
00180c54: 26100001 addiu r16,r16,0x0001      
00180c58: 90620000 lbu r2,0x0000(r3)      Load Sprite Set
00180c5c: 00000000 nop            
00180c60: 10510004 beq r2,r17,0x00180c74   
00180c64: 2402fffc addiu r2,r0,0xfffc      
00180c68: 2a020014 slti r2,r16,0x0014      
00180c6c: 1440fff3 bne r2,r0,0x00180c3c      
00180c70: 2402fffb addiu r2,r0,0xfffb      
00180c74: 8fbf001c lw r31,0x001c(r29)      
00180c78: 8fb20018 lw r18,0x0018(r29)      
00180c7c: 8fb10014 lw r17,0x0014(r29)      
00180c80: 8fb00010 lw r16,0x0010(r29)      
00180c84: 27bd0020 addiu r29,r29,0x0020      
00180c88: 03e00008 jr r31         
00180c8c: 00000000 nop            
  • Modding version: PSX
Check out my ASM thread. Who doesn't like hax?

LastingDawn

Looks to be. Is that looking at a range, of 1-3 or is it saying 01,02,03? If it is digit based I would really like to change one to 022 (for Rad)
"Moment's anger can revert to joy,
sadness can be turned to delight.
A nation destroyed cannot be restored,
the dead brought back to life."

Art of War

Beta & Gretchen Forever!!!!

formerdeathcorps

May 25, 2011, 07:32:43 pm #85 Last Edit: May 26, 2011, 03:17:58 am by formerdeathcorps
OK, here's another interesting routine.


00187ca0: 3c068019 lui r6,0x8019
00187ca4: 8cc62d90 lw r6,0x2d90(r6)
00187ca8: 27bdffe8 addiu r29,r29,0xffe8
00187cac: afbf0010 sw r31,0x0010(r29)
00187cb0: 90c20025 lbu r2,0x0025(r6)
00187cb4: 00000000 nop
00187cb8: 30420080 andi r2,r2,0x0080
00187cbc: 10400079 beq r2,r0,0x00187ea4 If not HP Damage, GOTO END.
00187cc0: 00000000 nop
00187cc4: 3c058019 lui r5,0x8019
00187cc8: 8ca52d98 lw r5,0x2d98(r5)
00187ccc: 84c20004 lh r2,0x0004(r6)
00187cd0: 94a30028 lhu r3,0x0028(r5)
00187cd4: 84c40006 lh r4,0x0006(r6)
00187cd8: 00621823 subu r3,r3,r2 r3 = Target HP - HP Damage
00187cdc: 90a20006 lbu r2,0x0006(r5)
00187ce0: 00000000 nop
00187ce4: 304200c0 andi r2,r2,0x00c0
00187ce8: 1440006e bne r2,r0,0x00187ea4 GOTO END if target is not monster.
00187cec: 00642021 addu r4,r3,r4 r4 = Target HP - HP Damage + HP Healing
00187cf0: 90a201ba lbu r2,0x01ba(r5)
00187cf4: 00000000 nop
00187cf8: 30420030 andi r2,r2,0x0030
00187cfc: 000210c2 srl r2,r2,0x03
00187d00: 3c018019 lui r1,0x8019
00187d04: 00220821 addu r1,r1,r2
00187d08: 9422f5f4 lhu r2,-0x0a0c(r1)
00187d0c: 00000000 nop
00187d10: 10400007 beq r2,r0,0x00187d30 ELSE, if r2 = 0, skip Normal Attack Check.
00187d14: 00000000 nop
00187d18: 3c028019 lui r2,0x8019
00187d1c: 904238f5 lbu r2,0x38f5(r2)
00187d20: 00000000 nop
00187d24: 30420008 andi r2,r2,0x0008
00187d28: 1440005e bne r2,r0,0x00187ea4 If r2 = ??? (has something to do with if the monster is always there, randomly there, or both) and normal attack, GOTO END.
00187d2c: 00000000 nop
00187d30: 94a20058 lhu r2,0x0058(r5)
00187d34: 00000000 nop
00187d38: 30428020 andi r2,r2,0x8020
00187d3c: 14400059 bne r2,r0,0x00187ea4 If target is petrified or dead, GOTO END....(you would think this was included in the weapon formulas themselves).
00187d40: 00000000 nop
00187d44: 90a2005b lbu r2,0x005b(r5)
00187d48: 00000000 nop
00187d4c: 30420001 andi r2,r2,0x0001
00187d50: 14400054 bne r2,r0,0x00187ea4 If target has wall, GOTO END.
00187d54: 00000000 nop
00187d58: 18800006 blez r4,0x00187d74 If enemy HP is 0 or less, GOTO RAM 0x187D74
00187d5c: 00000000 nop
00187d60: 90c2001b lbu r2,0x001b(r6)
00187d64: 00000000 nop
00187d68: 30420020 andi r2,r2,0x0020
00187d6c: 10400021 beq r2,r0,0x00187df4 If dead isn't being added, GOTO RAM 0x187DF4
00187d70: 00000000 nop
00187d74: 3c028019 lui r2,0x8019
00187d78: 8c422d94 lw r2,0x2d94(r2)
00187d7c: 00000000 nop
00187d80: 90420091 lbu r2,0x0091(r2)
00187d84: 00000000 nop
00187d88: 30420040 andi r2,r2,0x0040
00187d8c: 10400019 beq r2,r0,0x00187df4 If monster is killed, but attacker doesn't have secret hunt, GOTO RAM 0x187DF4
00187d90: 00000000 nop
00187d94: 90a20005 lbu r2,0x0005(r5)
00187d98: 00000000 nop
00187d9c: 30420004 andi r2,r2,0x0004
00187da0: 14400014 bne r2,r0,0x00187df4 If monster is killed, but monster has immortal, GOTO RAM 0x187DF4
00187da4: 00000000 nop
00187da8: 90a20003 lbu r2,0x0003(r5)
00187dac: 00000000 nop
00187db0: 2442ffa2 addiu r2,r2,0xffa2
00187db4: 2c420030 sltiu r2,r2,0x0030
00187db8: 1040003a beq r2,r0,0x00187ea4 If monster is killed, but monster is not poachable, GOTO END.
00187dbc: 00000000 nop
00187dc0: 0c062f4d jal 0x0018bd34 Disable second attack?
00187dc4: 00000000 nop
00187dc8: 0c062f3c jal 0x0018bcf0 Disable spell proc.
00187dcc: 00000000 nop
00187dd0: 3c028019 lui r2,0x8019
00187dd4: 8c422d90 lw r2,0x2d90(r2)
00187dd8: 00000000 nop
00187ddc: 94430010 lhu r3,0x0010(r2)
00187de0: 00000000 nop
00187de4: 34630020 ori r3,r3,0x0020
00187de8: a4430010 sh r3,0x0010(r2) Store attack type as poaching.
00187dec: 08061fa7 j 0x00187e9c GOTO END and end of turn effect is poach.
00187df0: 34020006 ori r2,r0,0x0006
00187df4: 1880002b blez r4,0x00187ea4 Check (again) if target has 0 or less HP and GOTO END if true.
00187df8: 3c03cccc lui r3,0xcccc
00187dfc: 3c028019 lui r2,0x8019
00187e00: 8c422d98 lw r2,0x2d98(r2)
00187e04: 00000000 nop
00187e08: 9442002a lhu r2,0x002a(r2)
00187e0c: 3463cccd ori r3,r3,0xcccd
00187e10: 00430019 multu r2,r3
00187e14: 00001010 mfhi r2
00187e18: 00021082 srl r2,r2,0x02
00187e1c: 3042ffff andi r2,r2,0xffff
00187e20: 0044102a slt r2,r2,r4
00187e24: 1440001f bne r2,r0,0x00187ea4 GOTO END if monster's HP > 20% of maxHP.
00187e28: 00000000 nop
00187e2c: 3c028019 lui r2,0x8019
00187e30: 8c422d94 lw r2,0x2d94(r2)
00187e34: 00000000 nop
00187e38: 90420091 lbu r2,0x0091(r2)
00187e3c: 00000000 nop
00187e40: 30420080 andi r2,r2,0x0080
00187e44: 10400017 beq r2,r0,0x00187ea4 ELSE, GOTO END if the attacker doesn't have train.
00187e48: 00002021 addu r4,r0,r0
00187e4c: 3c038019 lui r3,0x8019
00187e50: 8c632d90 lw r3,0x2d90(r3)
00187e54: 00000000 nop
00187e58: 9062001c lbu r2,0x001c(r3)
00187e5c: 00000000 nop
00187e60: 34420040 ori r2,r2,0x0040
00187e64: 0c0612c9 jal 0x00184b24 ELSE, +Invite to monster, but also run routine to make sure it's not nullified (shouldn't this be done earlier)?
00187e68: a062001c sb r2,0x001c(r3)
00187e6c: 1040000d beq r2,r0,0x00187ea4 If nullified, GOTO END.
00187e70: 00000000 nop
00187e74: 3c048019 lui r4,0x8019
00187e78: 8c842d90 lw r4,0x2d90(r4)
00187e7c: 00000000 nop
00187e80: 94820010 lhu r2,0x0010(r4)
00187e84: 90830025 lbu r3,0x0025(r4)
00187e88: 34420040 ori r2,r2,0x0040
00187e8c: 34630008 ori r3,r3,0x0008
00187e90: a4820010 sh r2,0x0010(r4) Attack type is add status.
00187e94: 34020009 ori r2,r0,0x0009
00187e98: a0830025 sb r3,0x0025(r4) Attack type is add status.
00187e9c: 3c018019 lui r1,0x8019
00187ea0: a022390e sb r2,0x390e(r1) End of turn effect is whatever r2 is (6 is poach, 9 is tame).
00187ea4: 8fbf0010 lw r31,0x0010(r29)
00187ea8: 27bd0018 addiu r29,r29,0x0018
00187eac: 03e00008 jr r31
00187eb0: 00000000 nop
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.

RandMuadDib

So I was thinking about new abilities and was looking at infamous (#2 came out today) and shockwave caught my attention, being able to fliing multiple opponents. I took a look at your knockback routine, but I'm bad at interpreting code. Will it allow knockback when there are multiple targets?
I will show you the power of SARDIIIIINES!!!!

Celdia

@FDC: I was looking to rewrite formula 5E to replace PA for every instance of MA and found you had the formula flagged as a clone of 1E. Surprise, surprise, I come in here and find out you've got this
0017d628: 14620003 bne r3,r2,0x0017d638 If Formula is not Triple Thunder/Flame's, GOTO RAM 0x17D638.  This is the hard-coding of multi-hit for Triple Flame/Thunder.

already figured out. I just need to make sure that I'm reading everything right and that its not actually calling 1E's code so that I can change 5E without altering 1E.
  • Modding version: PSX
  • Discord username: Celdia#0

Glain

Quote from: Celdia on June 08, 2011, 08:25:07 am
@FDC: I was looking to rewrite formula 5E to replace PA for every instance of MA and found you had the formula flagged as a clone of 1E. Surprise, surprise, I come in here and find out you've got this already figured out. I just need to make sure that I'm reading everything right and that its not actually calling 1E's code so that I can change 5E without altering 1E.


I can probably comment on this as I've done a few formula hacks.

It's not that 1E and 5E necessarily have anything to do with each other, except that they both call a common routine... the one that calculates damage. That is, all the work in calculating damage is done here (in both formulas):

0c062269 jal 0x001889a4   Truth Formula

As far as I can tell, changing 5E without changing 1E would mean you'd either have to create a new routine for 5E to call, or edit the existing one to take a parameter that can tell it whether to use PA or MA.
  • Modding version: Other/Unknown

Pride

Just reaffirming what glain said. I'll write you the new routine if you would like.
  • Modding version: PSX
Check out my ASM thread. Who doesn't like hax?

Pride

Double posting ftw

Very early in the thread fdc offers a formula 07 "fix" to add status and elemental properties (Click here to see his post) but celdia pointed out it was bugged so... here is a semi fixed version of it. Its not a complete fix because if you absorb the element you are healing you'll always miss your target. Other then that though... Its fine. It also assumes you are using his other formula consolidation found in that post.

0x121C50

E8FFBD27
1000BFAF
8E21060C
00000000
D41C060C
00000000
AD1F060C
00000000
1000BF8F
1800BD27
0800E003
00000000

0x12862C

508C

If you aren't using his other formula fixes then put the edit at 0x121d3c and don't change 0x12862c.
  • Modding version: PSX
Check out my ASM thread. Who doesn't like hax?

Mando

Just to clarify, this fix above pride, will miss if you attack someone that can absorb the element of your skill?

(I normally don't apply the formula fix because I change skills that are element involved to another formula)

^ New FFAT website made by St4r!

Pride

  • Modding version: PSX
Check out my ASM thread. Who doesn't like hax?

Celdia

Okay, so I ran into a snag I didn't foresee in my design stages and figured you guys could figure this one out. I think Glain's post at the top of this page actually might have the answer in it technically. Its another one of my simple ideas that I don't think applies so simply behind the code.

I made Platina Shield into an Armlet Type item, making it equipable by everyone in their Hand slots. The equip preview displays correctly but the item won't apply any evasion % to the unit its equipped on. I want it to apply Armlet-type Item Evade % to Shield Evade on the unit. I'm wondering if my problem is something like the notation in (SECTION 4) "# Skip A-EV if Accessory isn't actually an accessory" causing it to ignore the evasion on the item because its claiming to be a shield but isn't.
  • Modding version: PSX
  • Discord username: Celdia#0

Glain

Quote from: Celdia on June 11, 2011, 05:23:25 pm
Okay, so I ran into a snag I didn't foresee in my design stages and figured you guys could figure this one out. I think Glain's post at the top of this page actually might have the answer in it technically. Its another one of my simple ideas that I don't think applies so simply behind the code.

I made Platina Shield into an Armlet Type item, making it equipable by everyone in their Hand slots. The equip preview displays correctly but the item won't apply any evasion % to the unit its equipped on. I want it to apply Armlet-type Item Evade % to Shield Evade on the unit. I'm wondering if my problem is something like the notation in (SECTION 4) "# Skip A-EV if Accessory isn't actually an accessory" causing it to ignore the evasion on the item because its claiming to be a shield but isn't.


It looks like that could happen if Platina Shield no longer had the Shield checkbox selected in FFTPatcher (to the right of item type).
  • Modding version: Other/Unknown

Celdia

What do those checkboxes actually affect in the upper right? I tried a few variations on them and nothing seemed to change anywhere.
  • Modding version: PSX
  • Discord username: Celdia#0

Glain

The checkboxes are what the evade ASM is checking when it does the whole "Skip A-EV if accessory slot isn't an accessory" kind of thing. I thought that might be why the evasion was being skipped, but it seems that's not the case.

There's another funky thing about the left/right hand slots. In battle, it's stored like: ([Right hand weapon], [Right hand shield], [Left hand weapon], [Left hand shield]). All as separate slots. Anything that doesn't apply is just set to [Empty]. So if a character had a weapon and a shield, it would be: ([Equipped Weapon], [Empty], [Empty], [Equipped Shield]).

I set up a quick scenario like this, using Gold Shield as the armlet-type shield and put it on Mustadio, and ran it in the pSX debugger. What I saw in memory for Mustadio's equipment was this:

[Left hand weapon] = [Romanda Gun]
[Left hand shield] = [Empty]
[Right hand weapon] = [Gold Shield]
[Right hand shield] = [Empty]

...Oops. The obvious guess would be that switching the item type made the game believe that the Gold Shield belonged in the weapon slot instead of the shield slot. It's got me a bit curious, so I may look into it later.
  • Modding version: Other/Unknown

formerdeathcorps

OK, considering how crammed I was for register space in writing my Knockback and Elemental routines (both of which have bugs, by the way), as well as my repeated calling of AI flags, I'm going to rewrite my formula hack to save more space by using the Stack Pointer.

Very start of any formula routine:

addiu r29, r29, 0xFFEC
sw r16, 0x0000 (r29)
sw r17, 0x0004 (r29)
sw r18, 0x0008 (r29)
sw r19, 0x000C (r29)
sw r20, 0x0010 (r29)
lui r16, 0x8019 r16 = 0x190000
lw r17, 0x2D94 (r16) r17 = Attacker Offset
lw r18, 0x2D98 (r16) r18 = Defender Offset
lhu r19, 0x38D6 (r16)
lui r20, 0x8006
sll r19, r19, 0x03
addu r19, r20, r19
lbu r19, -0x1410 (r19) r19 = AI flags; r20 will be used as a r31 replacement for complicated mechanics routines that call subroutines
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.

formerdeathcorps

June 18, 2011, 09:13:01 am #98 Last Edit: June 22, 2011, 05:02:59 pm by formerdeathcorps
This will be more than a simple register swap.  I intend to add a new flag that lets you use the foe's stats instead of your own (in the XA1/YA3 position).

NOTE: The following assumes you are using Xifanie's Ability Requirement Hack (latest version).

lbu r3, 0x38F9 (r16) Loads X
lbu r1, 0x38F6 (r16) r1 = Ability Flags Byte 4
addiu r6, r16, 0x38CE r6 = XA1's address
addiu r7, r16, 0x38D0 r7 = XA2's address
andi r3, r3, 0x000F r3 = the last 4 bits of X
andi r1, r1, 0x0008 r1 = 8 if "Require Sword" is checked, ELSE r1 = 0
(LS) addu r2, r17, r0 r2 = Attacker's data address
beq r6, r7 (CS) If r6 = r7, GOTO Calculation Start.
sltiu r4, r3, 0x0004
beq r1, r0, (CS) If blank flag under "Hit Allies" is not checked, GOTO Calculation Start.
nop
addu r2, r18, r0 r2 = Defender's data address
lhu r8, 0x003c (r2) r8 = Defender WP1 and WP2
(CS) bne r4, r0, (*) If r3 < 4, GOTO (*)
lbu r5, 0x0036 (r2) r5 = Attacker/Defender PA
sltiu r4, r3, 0x0008
bne r4, r0, (*) If r3 < 8, GOTO (*)
lbu r5, 0x0037 (r2) r5 = Attacker/Defender MA
sltiu r4, r3, 0x000C
bne r4, r0, (*) If r3 < 12, GOTO (*)
lbu r5, 0x0038 (r2) r5 = Attacker/Defender SP
beq r6, r7 (*) If r6 = r7, GOTO (*).
lbu r5, 0x3902 (r16) r5 = Attacker WP
beq r1, r0, (*) If blank flag under "Hit Allies" is not checked, GOTO (*).
andi r9, r8, 0x00FF r9 = Defender WP1
srl r8, r8, 0x08 r8 = Defender WP2
sltiu r5, r9, r8 r5 = 1 if Defender WP1 < WP2, ELSE, r5 = 0.
bne r5, r0, (*) If Defender WP1 < WP2, GOTO (*).
addu r5, r8, r0 r5 = Defender WP2.
addu r5, r9, r0 ELSE, r5 = Defender WP1.
(*) beq r6, r7, (E) If r6 = r7, GOTO End.
sb r5, 0x0000 (r6) Stores r5 at the address of r6
andi r3, r3, 0x0003
sll r3, r3, 0x0002
addiu r3, r3, 0x0001 The purpose of these r3 manipulations is to put r3 in a form that the previous loop can understand.
j (LS) Jumps back to the Loop's Start.
addiu r6, r6, 0x0002 r6 = r6 + 2 = r7 = XA2's address
(E) jr 31 Returns to the Main Formula Routine.
nop

SCUS
0x4CE24
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000


ori r4, r0, 0x0005
beq r3, r4, (E) NOTE: r3 can only be 1, 5, 9, or 13, which corresponds to PA, MA, SP, WP.  If XA2 is MA, GOTO (E)
lbu r6, 0x005C (r18) Load Status Byte 5.
lbu r7, 0x0058 (r18) Load Status Byte 1.
lbu r5, 0x005A (r18) Load Status Byte 3.
lhu r4, 0x38D0 (r16) Load XA2.
andi r6, r6, 0x0010
bne r6, r0, (Mult) If target is asleep, GOTO (Mult)
andi r7, r7, 0x0008
bne r7, r0, (Mult) If target is charging, GOTO (Mult)
andi r5, r5, 0x0006
beq r5, r0, (E) If target isn't chickened/frogged, GOTO (E)
(Mult) srl r5, r4, 0x01 r5 = [XA2/2]
addu r4, r4, r5 XA2 = XA2 + [XA2/2]
sh r4, 0x38D0 (r16) Store XA2.
(E) jr 31 Return to Main Routine
nop

addu r20, r31, r0 Stores the return address in r20 because it'll be modified by the jal commands below.
ori r4, r0, 0x0005
beq r4, r3, (MA) NOTE: r3 can only be 1, 5, 9, or 13, which corresponds to PA, MA, SP, WP.  If r3 is MA, GOTO (MA)
lhu r7, 0x38D0 (r16) Loads XA2
ori r4, r0, 0x000D
bne r4, r3, (PA/SP) If r3 isn't WP, GOTO (PA/SP)
lbu r5, 0x38D9 (r16)  Loads the "Two Hands" byte.
jal (WP-UP) If WP, GOTO (WP-UP)
lbu r4, 0x38FF (r16) Loads weapon characteristic byte.
(PA/SP) jal (P-UP) If PA/SP, GOTO (P-UP)
lbu r3, 0x38D8 (r16) Loads Weapon Type byte.
j (E1) GOTO (E1)
nop
(MA) jal (M-UP) If MA, GOTO (M-UP)
lbu r3, 0x0090 (r17) Loads Support Byte 4.
(E1) jr 20 Return to Main Routine
nop

(WP-UP)beq r5, r0, (E2) If not using two-hands, GOTO (E2)
andi r3, r4, 0x0001
bne r3, r0, (E2) If weapon is forced two-hands, GOTO (E2)
andi r3, r4, 0x0004
beq r3, r0, (E2) If weapon is not two-handable, GOTO (E2)
sll r6, r7, 0x01
sh r6, 0x38D0 (r16) If 2H is used and XA2 is WP, XA2 = XA2 * 2.
(E2) jr 31
nop
(P-UP) lbu r4, 0x0091 (r17) Loads Support Byte 5.
bne r3, r0, (A-UP)  If equipping a weapon, GOTO (A-UP)
andi r4, r4, 0x0020
beq r4, r0, (A-UP) If Martial Arts isn't used, GOTO (A-UP)
srl r6, r7, 0x01
addu r6, r7, r6
sh r6, 0x38D0 (r16) If Martial Arts is used and XA2 is PA or SP, XA2 = XA2 + [XA2/2].
(A-UP) lbu r3, 0x0090 (r2) Loads Support Byte 4.
lui r4, 0x5555  r4 = 55550000.
andi r5, r3, 0x0010
beq r5, r0, (E3)  If Attack Up isn't used, GOTO (E3)
(Mult) addiu r4, r4, 0x5556 r4 = 55555556 as a multiplier against FFFFFFFF.  In simple terms, this is 1/3.
sll r3, r7, 0x02
mult r4, r3 Term on HI is XA2 * 4 * 1/3.
sra r3, r3, 0x1F r3 = 0.
mfhi r4
subu r4, r4, r3 r4 = r4 - 0.
sh r4, 0x38D0 (r16)  If ATTACK or MAGIC ATTACK UP is flagged, XA2 = XA2 * 4/3.
(E3) jr r31
nop

(M-UP)lui r4, 0x5555  r4 = 55550000.
andi r5, r3, 0x0004
beq r5, r0, (E3) If Magic Attack Up isn't used, GOTO (E3)
nop
j (Mult) GOTO (Mult)
nop


lhu r7, 0x38CE (r1) Loads XA1
lbu r4, 0x38E5 (r1) Loads Formula
lbu r3, 0x38FA (r1) Loads Y
addiu r5, r0, 0x0008
beq r5, r4, (F8) If Formula 8 (I'll change this to some other number later), GOTO (F8).
addiu r6, r0, 0x0009
beq r6, r4, (F9) If Formula 9 (I'll change this to some other number later), GOTO (F9).
addiu r5, r0, 0x000A
beq r5, r4, (FA) If Formula A (I'll change this to some other number later), GOTO (FA).
addiu r6, r0, 0x000B
beq r6, r4, (FB) If Formula B (I'll change this to some other number later), GOTO (FB).
addu r7, r7, r3 r7 = XA1 + Y
lhu r4, 0x38D0 (r1) r4 = XA2
nop
addu r4, r7, r4
jr 31 Return to Main Routine
sb r4, 0x38D0 (r1) XA2 = XA1 + XA2 + Y
(FB) srl r7, r7, 0x01 XA1 = (XA1 + Y) / 2
j (E)
(FA) srl r6, r3, 0x03 r6 = [Y/8]
andi r3, r3, 0x0007 r3 = last 3 bits of Y
beq r3, r0, (Calc)
lbu r5, 0x0036 (r2) r5 = PA if r3 = 0
addiu r4, r0, 0x0001
beq r3, r4, (Calc)
lbu r5, 0x0037 (r2) r5 = MA if r3 = 1
addiu r4, r0, 0x0002
beq r3, r4, (Calc)
lbu r5, 0x0038 (r2) r5 = SP if r3 = 2
addiu r4, r0, 0x0003
beq r3, r4, (Calc)
lbu r5, 0x3902 (r1) r5 = WP if r3 = 3
addiu r4, r0, 0x0004
beq r3, r4, (Div4)
lbu r5, 0x0022 (r2) r5 = LVL if r3 = 4
addiu r4, r0, 0x0005
beq r3, r4, (Check)
addu r5, r2, 0x003E Readies the check where r5 = WEV1 if r3 = 5
addiu r4, r0, 0x0006
beq r3, r4, (Check)
addu r5, r2, 0x0045 Readies the check where r5 = SMEV1 if r3 = 6
addu r5, r2, 0x0041 Readies the check where r5 = SPEV1 if r3 = 7
(Check) lbu r4, 0x0000 (r5) r4 = RH equipment evasion.
bne r4, r0, (DivCheck) Checks RH equipment for evasion.
sltiu r3, r3, 0x0007 r3 = 1 if r3 < 7. r3 = 0 if r3 = 7.
lbu r4, 0x0001 (r5) r4 = LH equipment evasion.
(DivCheck) beq r3, r0 (Div3) If r3 = 0 (original r3 = 7), GOTO (Div3)
addu r5, r4, r0 r5 = r4
j (Calc)
srl r5, r5, 0x01 r5 = r5 / 2...this allows the SM-EV and W-EV used in formulas to cap at 25-30 in vanilla.
(Div3) lui r4, 0x5555
addu r4, r4, 0x5556
mult r5, r4
mfhi r5 r5 = r5 / 3...this allows the SP-EV used in formulas to cap at 25 in vanilla.
j (Calc)
nop
(Div4) j (Calc)
srl r5, r5, 0x02 r5 = r5 / 4...this allows the LVL used in formulas to cap at 25 in vanilla.
(Calc) bne r5, r0 (Nonzero) If r5 is not zero, GOTO (Nonzero)
nop
addiu r5, r0, 0x0001
(Nonzero) addu r7, r7, r5 r7 = XA1 + r5 (which we'll now call YA3)
srl r7, r7, 0x01 r7 = (XA1 + YA3) / 2
j (E)
addu r7, r7, r6 XA1 = (XA1 + YA3) / 2 + [Y/8]
(F9) andi r5, r3, 0x0008 r5 = first bit of Y
beq r5, r0 (Sorter)
srl r6, r3, 0x04 r6 = [Y/16]
lw r2, 0x2D98 (r1) Load the target's stats.
(Sorter) andi r5, r3, 0x0003 r5 = last 2 bits of Y
andi r3, r3, 0x0004 r3 = second bit of Y
beq r5, r0 (Divider1)
addiu r4, r2, 0x0028 Readies the check where r4 = curHP if r5 = 0
addiu r5, r5, 0xFFFF r5 = r5 - 1
beq r5, r0 (Divider1)
addiu r4, r2, 0x002C Readies the check where r4 = curMP if r5 = 0 (original r5 = 1).
addiu r5, r5, 0xFFFF r5 = r5 - 1
beq r5, r0 (Divider2)
lbu r4, 0x0024 (r2) r4 = Br of target or caster if r5 = 0 (original r5 = 2)
lbu r5, 0x005C (r2) r5 = Status Byte 5 on target or caster if r5 = 1 (original r5 = 3)
lbu r4, 0x0026 (r2) r4 = Fa of target or caster if r5 = 1 (original r5 = 3)
andi r5, r5 0x00C0
beq r5, r0 (Divider2) If not Innocent or Faith, GOTO (Divider2)
nop
sltiu r5, r5, 0x0080 r5 = 1 if Innocent.  r5 = 0 if Faith.
beq r5, r0 (Divider2) If Faith, GOTO (Divider2)
addiu r4, r0, 0x0064 r4 = 100
addiu r4, r0, 0x0000 ELSE, r4 = 0
(Divider2) beq r3, r0 (Div100) If r3 = 0 (normal), GOTO (Div100)
addiu r5, r0, 0x0064 r5 = 100
subu r4, r5, r4 If r3 = 1 (reversed stats), r4 = 100 - (BR or Adjusted FA)
(Div100) mult r7, r4
mflo r4 r4 = XA1 * BR/FA/UnBr/UnFa
lui r5, 0x028F
addiu r5, r5, 0x5C29
mult r4, r5
mfhi r5 r5 = XA1 * Br/Fa/UnBr/UnFa / 100
nop
j (E)
addu r7, r5, r6 XA1 = (XA1 * Br/Fa/UnBr/UnFa / 100) + [Y/16]
(Divider1) lhu r5, 0x0000 (r4) r5 = curHP or curMP
beq r3, r0 (OverMax) If r3 = 0 (normal), GOTO (OverMax)
lhu r4, 0x0002 (r4) r4 = maxHP or maxMP
subu r5, r4, r5 If r3 = 1 (reversed stats), r4 = max-cur HP/MP
(OverMax) mult r7, r5
mflo r5 r5 = XA1 * curHP/MP/max-curHP/max-curMP
nop
nop
div r5, r4
mflo r5 r5 = XA1 * curHP/MP/max-curHP/max-curMP / maxHP/MP
nop
j (E)
addu r7, r5, r6 XA1 = (XA1 * curHP/max-curHP/curMP/max-curMP / maxHP/MP) + [Y/16]
(F8) lui r4, 0xA001
lw r5, -0x6FF0 (r4) Load random word.
lui r6, 0x41C6
addiu r6, r6, 0x4E6D
multu r5, r6
mflo r5
nop
addiu r5, r5, 0x3039
sw r5, -0x6FF0 (r4) Store new Random Word.
multu r7, r5
mfhi r7 r7 = {0...XA1-1}
nop
addiu r7, r7, 0x0001 r7 = {1...XA1}
addu r7, r7, r3 XA1 = {1...XA1}+Y
(E) jr 31 Return to Main Routine
sb r7, 0x38CE (r1) Store modified XA1.


lhu r4, 0x38D0 (r1) Loads r4 as XA2
lhu r5, 0x38CE (r1) Loads r5 as XA1
beq r4, r0 (Set1) If XA2 is 0, GOTO (Set1)
nop
(Mult) mult r4, r5
mflo r4 XA2 = XA1 * XA2
nop
jr 31 Return to Main Routine
sh r4, 0x38D0 (r1) Stores new XA2

(Set1) j (Mult) GOTO (Mult)
addiu r4, r0, 0x0001 If XA2 = 0, XA2 is now 1.


lbu r6, 0x3904 (r1) r6 = Weapon Elemental
lbu r4, 0x38F3 (r1) r4 = Ability Flags Byte 1
lbu r5, 0x38F7 (r1) r5 = Ability Elemental
andi r7, r4, 0x0004
beq r7, r0 (E) If Weapon Strike is not flagged, GOTO (E)
nop
or r5, r5, r6 ELSE, Ability Elemental = Weapon Elemental + Ability Elemental
(E) jr 31 Returns to the Main Formula Routine.
sb r5, 0x38F7 (r1) Store new Ability Elemental


lbu r4, 0x38F7 (r1) Loads ability element
lbu r5, 0x0071 (r2) Loads elements strengthened
lhu r6, 0x38D0 (r1) Loads XA2
and r4, r4, r5 Checks ability element against elements strengthened
beq r4, r0, (E) If ability element isn't a boosted element, GOTO (E)
srl r5, r6, 0x02 If ability element is boosted, r5 = [XA2/4]
addu r6, r6, r5 XA2 = XA2 + [XA2/4]
(E)  jr 31 Return to Main Routine
sh r6, 0x38D0 (r1) Stores XA2

addu r2, r31, r0 r2 = Return Address, because r31 will be modified below by the jal commands.
lw r3, 0x2D98 (r1) Load target address.
lhu r5, 0x38D6 (r1) r5 = Used Ability ID
lui r4, 0x8006
sll r5, r5, 0x03 r5 = r5 * 8
addu r4, r4, r5
lbu r5, -0x140A (r4) r5 = AI Byte 4
lbu r6, 0x005B (r3) r6 = Status Byte 4
andi r4, r5, 0x0002
beq r4, r0 (Prot) If AI flag Magic Defense Up is not checked, GOTO (Prot)
andi r7, r6, 0x0010
beq r7, r0 (Prot) If target does not have Shell, GOTO (Prot)
nop
jal (Mult) If target has Shell and skill is blocked by Shell, GOTO (Mult)
nop
(Prot) andi r4, r5, 0x0001
beq r4, r0 (MADEF) If AI flag Defense Up is not checked, GOTO (MADEF)
andi r7, r6, 0x0020
beq r7, r0 (MADEF) If target does not have Protect, GOTO (MADEF)
nop
jal (Mult) If target has Protect and skill is blocked by Protect, GOTO (Mult)
(MADEF) lbu r6, 0x0090 (r3) r6 = Support Byte 2
andi r4, r5, 0x0002
beq r4, r0 (DEFUP) If AI flag Magic Defense Up is not checked, GOTO (DEFUP)
andi r7, r6, 0x0002
beq r7, r0 (DEFUP) If target does not have Magic Defense Up, GOTO (DEFUP)
nop
jal (Mult) If target has Magic Defense Up and skill is blocked by Shell, GOTO (Mult)
(DEFUP) andi r5, r5, 0x0001
beq r5, r0 (E) If AI flag Defense Up is not checked, GOTO (E)
andi r6, r6, 0x0008
beq r6, r0 (E) If target does not have Defense Up, GOTO (E)
nop
jal (Mult) If target has Defense Up and skill is blocked by Protect, GOTO (Mult)
nop
(E) jr r2 Return to Main Routine
nop

(Mult) lui r4, 0xAAAA
lhu r7, 0x38D0 (r1) r7 = XA2
addiu r4, r4, 0xAAAB r4 = AAAAAAAB
multu r7, r4
mfhi r7 r7 = XA2 * 2/3
nop
jr 31 Return to Protect/Shell/MADEF/DEFUP Routine
sh r7, 0x38D0 (r1) XA2 = XA2 * 2/3


lw r2, 0x2D94 (r1) Loads the attacker's stats
lw r3, 0x2D98 (r1) Loads the defender's stats
lui r7, 0x8006
lhu r6, 0x38D6 (r1) r6 = Used Ability ID
lbu r4, 0x0009 (r2) Loads the attacker's Zodiac Sign Byte
sll r6, r6, 0x03 r6 = r6 * 8
addu r7, r7, r6
lbu r7, -0x140D (r7) r7 = AI Byte 1 for attack
addiu r6, r0, 0x000C
andi r7, r7, 0x0010 Checks if the currently unused flag under "Learn on Hit" is flagged.
bne r7, r0, (E) If flagged, GOTO (E)
lbu r5, 0x0009 (r3) Loads the defender's Zodiac Sign Byte
srl r4, r4, 0x04 Gets the attacker byte's upper 4 bits.
beq r4, r6, (E) If Attacker sign is Ophiuchus, GOTO (E)
srl r5, r5, 0x04 Gets the defender byte's upper 4 bits.
beq r5, r6, (E) If Defender sign is Ophiuchus, GOTO (E)
andi r7, r4, 0x0003 r7 = the lower 2 bits of attacker sign
andi r6, r5, 0x0003 r6 = the lower 2 bits of defender sign
beq r6, r7, (Good) If attacker and defender signs differ by 4, GOTO (Good)
lbu r1, 0x38D0 (r1) r1 = XA2
addiu r7, r0, 0x0002
addiu r6, r0, 0x0006
(MOD) div r4, r6
mfhi r4 r4 = r4 MOD r6...MOD means you take the remainder of the division.
nop
nop
div r5, r6
mfhi r5 r5 = r5 MOD r6
nop
beq r4, r5 (Diff) If attacker and defender signs form a square or its diagonal, GOTO (Diff)
addiu r7, r7, 0xFFFF r7 = r7 - 1
bne r7, r0, (MOD) If r7 isn't zero, GOTO (MOD)
addiu r6, r0, 0x0003
(E) jr 31 Return to Main Routine
lui r1, 0x8019 Resets r1 = 0x80190000.
(Diff) beq r7, r0 (Bad) If r7 = 0 (when r6 = 3), GOTO (Bad)
lbu r6, 0x0006 (r2) r6 = attacker gender
lbu r7, 0x0006 (r3) r7 = defender gender
or r4, r6, r7
andi r4, r4, 0x0020
bne r4, r0, (Bad) If either combatant is a monster, GOTO (Bad)
andi r6, r6, 0x00C0
andi r7, r7, 0x00C0
beq r6, r7 (EndBranch) If the genders are the same, GOTO (EndBranch)
srl r4, r1, 0x01 XA2 = [XA2/2]
(+) addu r4, r1, r4 XA2 = XA2 + r4
(EndBranch) lui r7, 0x8019
j (E)
sb r4, 0x38D0 (r7) Store r1 as XA2
(Good) j (+)
(Bad) srl r4, r1, 0x02 r4 = [XA2/4]
j (EndBranch)
subu r4, r1, r4 XA2 = XA2 - [XA2/4]


lbu r4, 0x38F7 (r1) Loads ability element
lbu r5, 0x006F (r3) Loads elements halved
lhu r6, 0x38D0 (r1) Load XA2
and r4, r4, r5 Checks ability element against elements halved
beq r4, r0, (E) If ability element isn't a halved element, GOTO (E)
lw r2, 0x2D94 (r1) Loads attacker address
srl r6, r6, 0x01 If ability element is halved, XA2 = [XA2/2]
(E) jr 31 Return to Main Routine
sh r6, 0x38D0 (r1) Stores XA2


lhu r4, 0x38D6 (r1) r4 = Used Ability ID
lui r5, 0x8006
sll r4, r4, 0x03 r4 = r4 * 8
addu r5, r5, r4
lbu r6, -0x1409 (r5) r6 = AI Byte 5
lbu r7, -0x140A (r5) r7 = AI Byte 4
lbu r5, -0x140B (r5) r5 = AI Byte 3
andi r6, r6, 0x0004
bne r6, r0, (Un) If 3rd blank AI flag under the Third Unknown under Learn on Hit is flagged, GOTO (Un)
(Check) andi r7, r7, 0x0080
bne r7, r0, (Br) If the blank AI flag above Direct Attack is flagged, GOTO (Br)
andi r5, r5, 0x0004
bne r5, r0, (Fa) If the Unknown AI flag under Random Hits is flagged, GOTO (Fa)
nop
jr 31 ELSE, GOTO Main Routine
nop

(Un) addiu r6, r0, 0x0064
j (Check) r6 = 100, r4 = Yes, GOTO (Check)
addiu r4, r0, 0x0001

(Br) bne r4, r0, (UnBr) If UnBrave/UnFaith is flagged, GOTO (UnBr)
lbu r7, 0x0024 (r2) r7 = Attacker Brave
j (Mult) ELSE, GOTO (Mult)
(UnBr) lbu r4, 0x0024 (r3) r4 = Defender Brave
subu r7, r6, r7 r7 = 100 - Attacker Brave if UnBrave/UnFaith is flagged
subu r4, r6, r4 r4 = 100 - Defender Brave if UnBrave/UnFaith is flagged
(Mult) lhu r6, 0x38D0 (r1) r6 = XA2
nop
mult r6, r7
mflo r6 r6 = XA2 * (CaBr/Fa or 100 - CaBr/Fa)
nop
nop
mult r6, r4
mflo r6 r6 = XA2 * (CaBr/Fa or 100 - CaBr/Fa) * (TaBr/Fa or 100 - TaBr/Fa)
lui r4, 0x0006
addu r4, r4, 0x8DB8
mult r6, r4
mfhi r6 XA2 = [XA2 * (CaBr/Fa or 100 - CaBr/Fa) * (TaBr/Fa or 100 - TaBr/Fa) / 10000]
nop
jr 31 GOTO Main Routine
sh r6, 0x38D0 (r1) Stores new XA2
(Fa) lbu r5, 0x005C (r2) r5 = Attacker Status Byte 5
lbu r7, 0x005C (r3) r7 = Defender Status Byte 5
andi r5, r5, 0x00C0
beq r5, r0, (Load-AFa) If attacker does not have innocent or faith, GOTO (Load-AFa)
andi r7, r7, 0x00C0
sltiu r5, r5, 0x0080
beq r5, r0, (A-Inn) If attacker has Innocent, GOTO (A-Inn)
nop
j (CheckTar) If attacker has Faith, r5 = 100 and GOTO (CheckTar)
addiu r5, r0, 0x0064
(A-Inn) j (CheckTar) If attacker has Innocent, r5 = 0 and GOTO (CheckTar)
addiu r5, r0, 0x0000
(Load-AFa) lbu r5, 0x0026 (r2) If attacker has neither, r5 = Attacker Faith
(CheckTar) beq r7, r0, (Load-DFa) If defender does not have innocent or faith, GOTO (Load-DFa)
nop
sltiu r7, r7, 0x0080
beq r7, r0, (D-Inn) If defender has Innocent, GOTO (D-Inn)
nop
j (CheckUn) If defender has Faith, r7 = 100 and GOTO (CheckUn)
addiu r7, r0, 0x0064
(D-Inn) j (CheckUn) If defender has Innocent, r7 = 0 and GOTO (CheckUn)
addiu r7, r0, 0x0000
(Load-DFa) lbu r7, 0x0026 (r3) If defender has neither, r7 = Defender Faith
(CheckUn) beq r4, r0, (Normal) If UnBrave/UnFaith isn't flagged, GOTO (Normal)
nop
subu r5, r6, r5 r5 = 100 - Attacker Faith if UnBrave/UnFaith is flagged
subu r7, r6, r7 r7 = 100 - Defender Faith if UnBrave/UnFaith is flagged
(Normal) addu r4, r7, r0 r4 = r7 = Defender Faith
j (Mult) GOTO (Mult)
addu r7, r5, r0 r7 = r5 = Attacker Faith


lhu r4, 0x38D6 (r1) r4 = Used Ability ID
lui r5, 0x8006
sll r4, r4, 0x03 r4 = r4 * 8
addu r4, r5, r4
lbu r9, -0x1409 (r4) r9 = AI Byte 5
addu r8, r31, r0 Sends r31 into r8 because r31 will be modified by jal commands below.
andi r4, r9, 0x0010
beq r4, r0, (KB Check) If the first blank flag under the Third Unknown in the "Learn on Hit" box is unflagged, GOTO (KB Check)
sb r0, 0x38CC (r1) Reset Higher Tile Flag
jal (RNG) ELSE, GOTO (RNG)
addiu r7, r0, 0x0064
addiu r4, r0, 0x0004
sub r4, r4, r7 r4 = 4 - RN from 0 to 99
bltz r4 (KB check) If RN > 4, GOTO (KB check)
addiu r5, r0, 0x0001
sb r5, 0x018D (r2) Flag attack as critical.
jal (RNG) GOTO (RNG)
lhu r7, 0x38D0 (r1) r7 = Base Damage
lhu r6, 0x38D0 (r1) r6 = Base Damage
addiu r7, r7, 0x0001 r7 = {1...Base Damage}
addu r6, r6, r7 New Damage = Base Damage + {1...Base Damage}
sh r6, 0x38D0 (r1) Store New Damage
(KB check) andi r4, r9, 0x0008
beq r4, r0, (E) If the second blank flag under the Third Unknown in the "Learn on Hit" box is unflagged, GOTO (E)
sb r0, 0x38EE (r1) Reset Knockback Height
jal (RNG) GOTO (RNG)
addiu r7, r0, 0x0064
addiu r4, r0, 0x0031
sub r4, r4, r7 r4 = 49 - RN from 0 to 99
bltz r4 (E) If RN > 49, GOTO (E)
(KB) lbu r5, 0x0182 (r3)
beq r2, r3, (E) If you are targeting yourself with knockback, GOTO (E)
lbu r4, 0x0005 (r3)
lbu r6, 0x0047 (r2) r6 = Attacker X Coordinate
andi r4, r4, 0x0004
bne r4, r0, (E) If target is immortal, GOTO (E)
lbu r7, 0x0047 (r3) r7 = Defender X Coordinate
bne r5, r0, (E) If target is riding a chocobo or in 2h+ water, GOTO (E)
lui r4, 0x800E
lbu r5, 0x4E9C (r4) r5 = Map Maximum X
beq r7, r0 (CheckEdge1) If Defender X Coordinate = 0, GOTO (CheckEdge1)
sb r0, 0x38EC (r1) Reset Knockback Flag
beq r7, r5 (CheckEdge2) If Defender X Coordinate = Map Maximum X, GOTO (CheckEdge2)
nop
sub r5, r6, r7 XA1 Byte 1 = Attacker X - Defender X
j (YChecks) Store Byte 1 of XA1 and GOTO (YChecks)
sb r5, 0x38CE (r1)
(CheckEdge1) beq r6, r0 (YChecks) If Defender and Attacker X Coordinate = 0, GOTO (YChecks)
sb r0, 0x38CE (r1) Store Byte 1 of XA1 as 0.
(E) jr r8 ELSE, unflag knockback and return to Main Routine
sb r0, 0x38EC (r1)
(CheckEdge2) beq r6, r5 (YChecks) If Defender and Attacker X Coordinate = Maximum, GOTO (YChecks)
sb r0, 0x38CE (r1) Store Byte 1 of XA1 as 0.
jr r8 If Defender X Coordinate = Maximum, but Attacker X coordinate is not maximal, unflag knockback and return to Main Routine
sb r0, 0x38EC (r1)
(YChecks) lbu r6, 0x0048 (r2) r6 = Attacker Y Coordinate
lbu r7, 0x0048 (r3) r7 = Defender Y Coordinate
lbu r5, 0x4EA0 (r4) r5 = Map Maximum Y
beq r7, r0, (CheckEdge3) If Defender Y Coordinate = 0, GOTO (CheckEdge3)
nop
beq r7, r5, (CheckEdge4) If Defender Y Coordinate = Maximum Y, GOTO (CheckEdge4)
nop
sub r5, r6, r7 XA1 Byte 1 = Attacker Y - Defender Y
j (NewXY) Store Byte 2 of XA1 and GOTO (NewXY)
sb r5, 0x38CF (r1)
(CheckEdge3) beq r6, r0 (NewXY) If Defender and Attacker Y Coordinate = 0, GOTO (NewXY)
sb r0, 0x38CF (r1) Store Byte 2 of XA1 as 0.
jr r8 If Defender Y Coordinate = 0, while Attacker Y Coordinate isn't, unflag knockback and return to Main Routine
sb r0, 0x38EC (r1)
(CheckEdge4) beq r6, r5 (NewXY) If Defender and Attacker Y Coordinate = Maximum, GOTO (NewXY)
sb r0, 0x38CF (r1) Store Byte 2 of XA1 as 0.
jr r8 If Defender Y Coordinate = Maximum, but Attacker Y coordinate is not maximal, unflag knockback and return to Main Routine
sb r0, 0x38EC (r1)
(NewXY) lb r4, 0x38CE (r1) r4 = Attacker X - Defender X
lb r5, 0x38CF (r1) r5 = Attacker Y - Defender Y
bgez r4 (+X) If r4 is greater than or equal to 0, GOTO (+X)
addiu r7, r0, 0x0100
addiu r6, r0, 0x0001 If r4 < 0, r6 = 1
j (YDiff) Make r4 positive and GOTO (YDiff)
subu r4, r7, r4 If r4 < 0, r4 = 0x100 - r4 (as unsigned byte), essentially the equivalent of multiplying a signed byte by -1.
(+X) bne r4, r0 (YDiff) If r4 > 0, r6 = 2 and GOTO (YDiff)
addiu r6, r0, 0x0002
addiu r6, r0, 0x0000 ELSE, r6 = 0
(YDiff) bgez r5 (+Y) If r5 is greater than or equal to 0, GOTO (+Y)
addiu r7, r0, 0x0100
ori r6, r6, 0x0004 If r5 < 0, r6 = r6 OR 0x4 = r6 + 4 (because r6 = 0, 1, or 2)
j (CoordChange) Make r5 positive and GOTO (CoordChange)
subu r5, r7, r5 If r5 < 0, r5 = 0x100 - r5 (as unsigned byte), essentially the equivalent of multiplying a signed byte by -1.
(+Y) beq r5, r0 (CoordChange) If r5 = 0, r6 = r6 and GOTO (CoordChange)
ori r6, r6, 0x0000
ori r6, r6, 0x0008 ELSE, r6 = r6 OR 0x8 = r6 + 8 (because r6 = 0, 1, or 2)
(CoordChange) jal (RNG) r7 = r4 + r5 = Distance Attacker is from Defender and GOTO (RNG)
addu r7, r4, r5
sub r7, r4, r7 r7 = |Attacker X - Defender X| - {0...|Attacker X - Defender X| + |Attacker Y - Defender Y| - 1}
bgtz r7 (ChangeX) If r7 > 0, GOTO (Change X)
lbu r5, 0x0048 (r3) r5 = Defender Y
andi r6, r6, 0x0008
beq r6, r0, (+1Y) If Attacker Y < Defender Y, GOTO (+1Y)
nop
j (NewCoord) If Attacker Y > Defender Y, Defender Y = Defender Y - 1 and GOTO (NewCoord)
addiu r5, r5, 0xFFFF
(+1Y) j (NewCoord) If Attacker Y < Defender Y, Defender Y = Defender Y + 1 and GOTO (NewCoord)
addiu r5, r5, 0x0001
(ChangeX) lbu r4, 0x0047 (r3) r4 = Defender X
andi r6, r6, 0x0002
beq r6, r0, (+1X) If Attacker X < Defender X, GOTO (+1X)
nop
j (NewCoord) If Attacker X > Defender X, Defender X = Defender X - 1 and GOTO (NewCoord)
addiu r4, r4, -0xFFFF
(+1X) addiu r4, r4, 0x0001 If Attacker X < Defender X, Defender X = Defender X + 1
(NewCoord) lui r6, 0x800E
lbu r6, 0x4E9C (r6) r6 = Map Maximum X
sb r4, 0x38CE (r1) Store Defender X as XA1 Byte 1
sb r5, 0x38CF (r1) Store Defender Y as XA1 Byte 2
lhu r5, 0x0048 (r3) r5 = Pre-Attack Defender Y + Unit Facing
lbu r4, 0x0047 (r3) r4 = Pre-Attack Defender X
andi r7, r5, 0x8000
jal (TileOffset) GOTO (TileOffset)
andi r5, r5, 0x00FF r5 = Pre-Attack Defender Y
bne r7, r0, (HigherTile) If the defender stood on a higher tile, GOTO (HigherTile)
nop
j (NewHeight) ELSE, r7 = Height of Lower Tile and GOTO (NewHeight)
lbu r7, -0x0732 (r4)
(HigherTile) lbu r7, 0x00CE (r4) r7 = Height of Higher Tile
(NewHeight) lbu r5, 0x38CF (r1) r5 = Defender Y (current)
jal (TileOffset) GOTO (TileOffset)
lbu r4, 0x38CE (r1) r4 = Defender X (current)
lbu r9, 0x005A (r3) r9 = Current Status Byte 3
lbu r5, 0x0093 (r3) r5 = Movement Status Byte 1
andi r9, r9. 0x0040
bne r9, r0, (SCheckFail) If target has float status, GOTO (SCheckFail)
lbu r2, 0x0095 (r3) r2 = Movement Status Byte 3
andi r5, r5, 0x0002
bne r5, r0, (SCheckFail) If target has ignore height, GOTO (SCheckFail)
andi r2, r2, 0x000C
beq r2, r0, (SCheckGood) If target doesn't have float/fly, GOTO (SCheckGood)
addu r9, r0, r0 If target doesn't have float/fly/ignore height, r9 = 0
(SCheckFail) addiu r9, r0, 0x0001 ELSE, r9 = 1
(SCheckGood) lbu r5, -0x0732 (r4) r5 = Height of Current Lower Tile
lbu r2, -0x072E (r4) r2 = Byte 7 of Current Lower Tile Data
sltu r4, r7, r5
bne r4, r0 (E) IF r7 < r5, GOTO (E)
andi r2, r2, 0x0001
bne r2, r0, (HigherTile) ELSE IF lower tile is impassable, GOTO (HigherTile)
sub r4, r7, r5 r4 = r7 - r5
bne, r9, r0, (NoFallDamageL) ELSE If target has float/fly/ignore height, GOTO (NoFallDamageL)
nop
sb r4, 0x38EE (r1) ELSE, Store r4 as knockback height
(NoFallDamageL) ori r4, r0, 0x0001 r4 = 1
sb r4, 0x38EC (r1) Flag Knockback
(HigherTile) lbu r5, 0x38CF (r1) r5 = Defender Y (current)
jal (TileOffset) GOTO (TileOffset)
lbu r4, 0x38CE (r1) r4 = Defender X (current)
lbu r5, 0x00CE (r4) r5 = Height of Current Higher Tile
lbu r2, 0x00D2 (r4) r2 = Byte 7 of Current Higher Tile Data
beq r5, r0 (E2) IF r5 = 0, GOTO (E2)
sltu r4, r7, r5
bne r4, r0 (E2) ELSE IF r7 < r5, GOTO (E2)
andi r2, r2, 0x0001
bne r2, r0, (E) ELSE IF higher tile is impassable, GOTO (E)
sub r4, r7, r5 r4 = r7 - r5
bne, r9, r0, (NoFallDamageH) ELSE If target has float/fly/ignore height, GOTO (NoFallDamageH)
addu r6, r0, r0 r6 = 0
sb r4, 0x38EE (r1) ELSE, store r4 as Knockback Height.
(NoFallDamageH) ori r4, r0, 0x0001 r4 = 1
sb r4, 0x38EC (r1) Flag Knockback
(E2) lbu r4, 0x38EC (r1) r4 = Knockback flag.
nop
beq r4, r0, (E) If Knockback is not flagged, GOTO (E)
nop
bne r6, r0, (LowerFlag) ELSE If r6 = Map Maximum X (and not 0), GOTO (LowerFlag)
addiu r7, r0, 0x0001 r7 = 1
sb r7, 0x38CC (r1) ELSE, flag Higher Tile
(LowerFlag) lbu r5, 0x38C1 (r1) r5 = The Xth unit on map (target)
lbu r4, 0x38CE (r1) r4 = Target X (current)
sb r5, 0x38EF (r1) Store r5.
lbu r5, 0x38CF (r1) r5 = Target Y (current)
sb r4, 0x38CA (r1) Store r4.
lbu r4, 0x019D (r3) r4 = Attack Elemental Modifier Flags vs. Target
sb r5, 0x38CB (r1) Store r5.
ori r4, r4, 0x0040 r4 = r4 OR 0x40
jr r8 GOTO Main Routine
sb r4, 0x019D (r3) Store r4, which now has a knockback on attack flag

(TileOffset) mult r5, r6
mflo r5 r5 = Map Maximum X * Defender Y (pre-attack or current)
nop
addiu r5, r5, r4 r5 = Map Maximum X * Defender Y + Defender X (pre-attack or current)
sll r5, r5, 0x03 r5 = r5 * 8
lui r4, 0x8019
jr 31  Return to Critical/Knockback Routine
addu r4, r4, r5

(RNG) lui r4, 0xA001
lw r5, -0x6FF0 (r4) Load random word.
lui r6, 0x41C6
addiu r6, r6, 0x4E6D
multu r5, r6
mflo r5
nop
addiu r5, r5, 0x3039
sw r5, -0x6FF0 (r4) Store new Random Word.
multu r7, r5
mfhi r7 r7 = {0...value(r7)-1}
jr 31 Return to Critical/Knockback Routine
nop

BATTLE.BIN
0x123EB0
00000000

BATTLE.BIN
0x11408C
00000000
00000000

BATTLE.BIN
0x1140FC
00000000
00000000

BATTLE.BIN
0x115FD8
EC

BATTLE.BIN
0x115FE0
01

BATTLE.BIN
0x124420
EC

BATTLE.BIN
0x124428
01

BATTLE.BIN
0x116250
EC

BATTLE.BIN
0x1162AC
EC

BATTLE.BIN
0x1162B4
01

BATTLE.BIN
0x1162C4
EC

BATTLE.BIN
0x123E50
EC

BATTLE.BIN
0x119EB8
lui r18, 0x8019 or 1980123C
0x119EC4
lbu r18, 0x38CC (r18) or CC385292


lw r2, 0x2D94 (r1) r2 = Attacker Offset
lhu r4, 0x38D6 (r1) r4 = Ability ID
lbu r7, 0x38F7 (r1) r7 = Ability Elemental
lui r6, 0x8006
sll r4, r4, 0x03 r4 = Ability ID * 8
addu r6, r6, r4 r6 = r6 + Ability ID * 8
lbu r4, 0x005A (r3) r4 = Target Status Bytes 3
lbu r8, 0x006E (r3) r8 = Target Elemental Nullification Byte
andi r4, r4, 0x0040
beq r4, r0, (NullCompare) If target is does not have float, GOTO (NullCompare)
nop
ori r8, r8, 0x0008 ELSE, Target is now nulls earth.
(NullCompare) andi r8, r8, r7
bne r8, r0, (ENull) If element is Nulled, GOTO (ENull)
lbu r6, -0x140B (r6) r6 = AI Flags Byte 3
lhu r4, 0x0058 (r3) ELSE, r4 = Target Status Bytes 1 and 2
lbu r8, 0x0070 (r3) r8 = Target Elemental Weakness Byte
andi r4, r4, 0x0410
beq r4, r0, (CheckOil) If target is not undead or vampire (has blood suck), GOTO (CheckOil)
addiu r9, r0, 0x0001
ori r8, r8, 0x0002 ELSE, Target is now weak against holy
(CheckOil) lbu r4, 0x005A (r3) r4 = Target Status Bytes 3
sb r9, 0x018C (r3) Flag attack as hit.
andi r4, r4, 0x0080
beq r4, r0 (NoStatusWeak) If target does not have oil, GOTO (NoStatusWeak)
nop
ori r8, r8, 0x0080 ELSE, Target is now weak against fire
(NoStatusWeak) lhu r4, 0x38D0 (r1) r4 = Base Damage
andi r6, r6, 0x0020
beq r6, r0, (EWeak) If AI Undead Reverse Flag is not flagged, r9 = 1 and GOTO (EWeak)
addiu r9, r0, 0x0001
andi r9, r5, 0x0080 ELSE r9 = 0, if the first blank flag under Player Abilities isn't flagged (healing), or 80 if it is (drain)
(EWeak) lbu r5, 0x38D6 (r1) r5 = Ability ID
lui r6, 0x8006
sll r5, r5, 0x03 r5 = Ability ID * 8
addu r6, r6, r5 r6 = r6 + Ability ID * 8
lbu r5, -0x140C (r6) r5 = AI Flags Byte 2
and r8, r8, r7
beq r8, r0, (SetupDMG) If the target is not weak against the spell's element, GOTO (SetupDMG)
addiu r9, r9, 0xFFFF
sll r4, r4, 0x01 ELSE, r4 = r4 * 2
(SetupDMG) andi r5, r5, 0x00A0
beq r5, r0, (EAbsorb) If the AI HP and MP flags are unflagged, GOTO (EAbsorb)
addu r6, r4, r0 r6 = r4
andi r6, r5, 0x0080
beq r6, r0 (-MP) ELSE, r6 = 0 or 0x80 and if AI flag HP is not flagged (r6 = 0), GOTO (-MP)
nop
andi r6, r5, 0x0040
beq r6, r0 (-HP) ELSE, If AI flag MP is not flagged, GOTO (-HP)
sh r4, 0x0190 (r3) Stores HP Damage as 2x Base Damage
srl r4, r4, 0x01
(-MP) sh r4, 0x0194 (r3) Stores r4 as MP Damage
(-HP) lbu r4, 0x019D (r3) r4 = Elemental Resistance Byte
beq r8, r0, (EAbsorb) If the target is not weak against the spell's element, GOTO (EAbsorb)
lbu r6, 0x01B1 (r3) r6 = Attack Type Byte
ori r4, r4, 0x0008 ELSE, r4 includes damage is elemental weakness
ori r6, r6, 0x00A0 r6 includes HP/MP Damage
sb r4, 0x019D (r3) Store r4 as elemental resistance byte
bgtz r9, (DrainFlags) If attack is supposed to drain, GOTO (DrainFlags)
sb r6, 0x01B1 (r3) Store r6 as attack type byte
j (EAbsorb) ELSE, GOTO (EAbsorb)
nop
(DrainFlags) lhu r4, 0x0194 (r3) r4 = MP Damage Dealt
lhu r5, 0x002C (r3) r5 = Target MP
lhu r6, 0x002C (r3) r6 = Target MP
sub r5, r5, r4
bltz r5, (ExcessMPDMG) If target MP < MP Damage Dealt, GOTO (ExcessMPDMG)
nop
j (HPDrain) GOTO (HPDrain)
sh r4, 0x0196 (r2) ELSE, Set MP restored to MP Damage Dealt.
(ExcessMPDMG) sh r6, 0x0196 (r2) If target MP < MP Damage Dealt, set MP restored as target MP.
(HPDrain) lhu r4, 0x0190 (r3) r4 = HP Damage Dealt
lhu r5, 0x0028 (r3) r5 = Target HP
lhu r6, 0x0028 (r3) r6 = Target HP
sub r5, r5, r4
bltz r5, (ExcessHPDMG) If target HP < HP Damage Dealt, GOTO (ExcessMPDMG)
nop
j (SelfFlags) GOTO (SelfFlags)
sh r4, 0x0192 (r2) ELSE, Set HP restored to HP Damage Dealt.
(ExcessHPDMG) sh r6, 0x0192 (r2) If target HP < HP Damage Dealt, set HP restored as target HP.
(SelfFlags) ori r4, r0, 0x0001
lbu r5, 0x01B1 (r2) r5 = Attack Type Byte of caster.
sb r4, 0x018C (r2) Drain will affect caster.
ori r5, r5, 0x0050 r5 includes HP/MP Healing
sb r5, 0x01B1 (r2) r5 is stored as the caster attack type byte.
ori r6, r0, 0x0100 r6 = 0x100
beq r9, r6, (E) If r9 = 0x100 (only possible if drain attack has no elemental modifiers), GOTO (E)
(EAbsorb) lbu r4, 0x0058 (r3) r4 = Target Status Bytes 1
lbu r8, 0x006D (r3) r8 = Target Elemental Absorption Byte
andi r4, r4, 0x0010
beq r4, r0, (NoUndead) If the target isn't undead, GOTO (NoUndead)
nop
ori r8, r8, 0x0001 ELSE, the target absorbs dark attacks.
(NoUndead) and r8, r8, r7
beq r8, r0, (Normal) If the target does not absorb the spell's element, GOTO (Normal)
lhu r4, 0x0190 (r3) r4 = HP Damage
bne r5, r0 (NotStatus) If the attack deals damage, drain, or healing, GOTO (NotStatus)
sll r6, r6, 0x01 Double hit chance of non-damage attack if target absorbs element.
addiu r9, r0, 0x0002
sb r9, 0x018C (r3) ELSE, Store 0x2 into target hit byte.
j (E) GOTO (E)
sh r6, 0x01B6 (r3) r6 = Hit Chance
(NotStatus) lhu r5, 0x0194 (r3) r5 = MP Damage
(HealSetup) sh r0, 0x0190 (r3) HP Damage is 0
bgtz r9, (DrainReversalFlags) If attack is supposed to drain, GOTO (DrainReversalFlags)
sh r0, 0x0194 (r3) MP Damage is 0
sh r4, 0x0192 (r3) r4 = HP Healing
sh r5, 0x0196 (r3) r5 = MP Healing
(EAbsorbFlags) lbu r5, 0x019D (r3) r5 = Elemental Resistance Byte
lbu r6, 0x01B1 (r3) r6 = Attack Type Byte
ori r5, r5, 0x0004 r5 includes healing is elemental absorption
andi r6, r6, 0x005F r6 no longer includes HP/MP damage.
ori r6, r6, 0x0050 r6 includes HP/MP Healing
sb r5, 0x019D (r3) Store r5 as elemental resistance byte
jr 31 Return to Main Formula Routine
sb r6, 0x01B1 (r3) Store r6 as attack type byte
(DrainReversalFlags) sh r4, 0x0190 (r2) r4 = HP Damage on Caster
lbu r6, 0x002C (r2) r6 = Caster MP
sh r5, 0x0194 (r2) r5 = MP Damage on Caster
sub r6, r6, r5
bltz r6, (ExcessMPHeal) If caster MP < MP Damage Dealt, GOTO (ExcessMPHeal)
sh r0, 0x0196 (r2) MP Healing on Caster is 0
j (HPReversal) GOTO (HPReversal)
sh r5, 0x0196 (r3) ELSE, Target MP Healing = Caster MP Damage
(ExcessMPHeal) add r6, r6, r5
sh r6, 0x0196 (r3) If Caster MP < MP Damage Dealt, Target MP Healing = Caster MP
(HPReversal) lbu r6, 0x0028 (r2) r6 = Caster HP
nop
sub r6, r6, r4
bltz r6, (ExcessHPHeal) If caster HP < HP Damage Dealt, GOTO (ExcessHPHeal)
sh r0, 0x0192 (r2) HP Healing on Caster is 0
j (SelfReverseFlags) GOTO (SelfReverseFlags)
sh r4, 0x0192 (r3) ELSE, Target HP Healing = Caster HP Damage
(ExcessMPHeal) add r6, r6, r4
sh r6, 0x0192 (r3) If Caster HP < HP Damage Dealt, Target MP Healing = Caster MP
(SelfReverseFlags) lbu r6, 0x01B1 (r2) r6 = Caster Attack Type Byte
ori r5, r0, 0x0001
andi r6, r6, 0x00AF r6 no longer includes HP/MP healing.
ori r6, r6, 0x00A0 r6 includes HP/MP Damage
sb r5, 0x018C (r2) Caster is affected by drain reversal.
j (EAbsorbFlags) GOTO (EAbsorbFlags)
sb r6, 0x01B1 (r2) Store r6 as attack type byte
(Normal) bne r5, r0 (NotStatus2) If the attack deals damage, drain, or healing, GOTO (NotStatus2)
nop
addiu r9, r0, 0x0002
sb r9, 0x018C (r3) ELSE, Store 0x2 into target hit byte.
j (E) GOTO (E)
sh r6, 0x01B6 (r3) r6 = Hit Chance
(NotStatus2) bltz r9, (Healing) If r9 < 0 (if the AI flags are set as healing), GOTO (Healing)
lhu r5, 0x0194 (r3) r5 = MP Damage
lbu r6, 0x01B1 (r3) ELSE, r6 = Attack Type Byte
nop
ori r6, r6, 0x00A0 r6 includes HP/MP Damage
bgtz r9, (Drain) If r9 > 0 (if the AI flags are set as drain), GOTO (Drain)
sb r6, 0x01B1 (r3) Store r6 as Attack Type Byte
jr 31 ELSE (if attack is not drain/healing), return to Main Formula Routine
nop
(Healing) addu, r7, r31, r0 r7 = Return address
jal (HealSetup) Save offset into r31 and GOTO (HealSetup)
nop
andi r5, r5, 0x00FB r5 no longer includes healing as elemental absorption
jr r7 Return to Main Formula Routine
sb r5, 0x019D (r3) Store r5 as elemental resistance byte
(Drain) j (DrainFlags) GOTO (DrainFlags)
addiu r9, r0, 0x0100 r9 = 0x100 (for comparison purposes above)
(E) jr r31 Return to Main Formula Routine
nop

(ENull) sb r0, 0x018C (r3) Attack will miss.
sh r0, 0x0190 (r3) HP Damage is 0.
sh r0, 0x0192 (r3) MP Damage is 0.
sh r0, 0x0194 (r3) HP Healing is 0.
sh r0, 0x0196 (r3) MP Healing is 0.
sh r0, 0x019C (r3) Set the elemental resistance byte to 0
sb r0, 0x01B1 (r3) Set the attack type byte to 0
sh r0, 0x01B6 (r3) Set the accuracy to 0
ori r4, r0, 0x0005
sb r4, 0x018E (r3) Display on missed attack is "Nullified"
lbu r4, 0x38ED (r1) r4 = Target Terrain Byte
sh r0, 0x38C8 (r1) Spell/Status Flags = 0
sh r0, 0x38C6 (r1) Status/Spell ID = 0
andi r4, r4, 0x0080
beq r4, r0 (E2) If target isn't above the terrain because of fly/float/chicken/frog, GOTO (E2)
nop
sb r0, 0x38ED (r1) ELSE, r4 = 0
(E2) jr r31 Return to Main Formula Routine
nop
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.

LastingDawn

That's some Class A work there FDC, but that Critical/Knockback routine, oy... makes the head spin. You've already your own added fix to that it seems though?
"Moment's anger can revert to joy,
sadness can be turned to delight.
A nation destroyed cannot be restored,
the dead brought back to life."

Art of War

Beta & Gretchen Forever!!!!