Final Fantasy VI
Square's 1994 Super Famicom game, read through everything8215's disassembly, which builds the Japanese and North American releases.
On this page
Final Fantasy VI is Square’s third Final Fantasy for the Super Famicom; North America got it as Final Fantasy III. The code read here is everything8215’s ff6 disassembly, which builds the Japanese and North American ROMs.
Its ATB fills a gauge rather than counting a timer down: every 2 frames each combatant’s gauge gains a constant built from its speed, and a full gauge is a turn1. The battle speed setting enters only the monsters’ constant2. A critical is a flat 1 in 323, and encounters keep Final Fantasy V’s counter at half the normal rate4.
#The evade bug
The hit check scales the attack’s hit rate by the target’s evade. The branch meant to choose Evade for a physical attack reads a flag that the check before it has already cleared, so every attack that reaches the evade roll is checked against magic evade (MBlock) instead5. The disassembly keeps the shipped code and offers a fix, credited to Terii Senshi, as a build option5.
Mechanics
| Mechanic | Kind | How |
|---|---|---|
| Turn order | Active time | each combatant's gauge fills in real time by its speed |
| Active Time Battle | Gauge | (speed + 20) × 1.5 × 64 ÷ 16 added every 2 frames, paused only when wait mode and the time-stop flag are both set; the speed setting slows only monsters |
| Hit chance | Hit times evade | hit rate scaled by the target's evade, and by a bug every attack reads magic evade; a physical attack on a target with Image rolls against the Image instead |
| Damage formula | Defense as a fraction | a random 224–255 over 256, then 255 − defense over 256 |
| Critical hit | Fixed | 1 in 32 for any attack that can crit, doubling the damage |
| Elemental weakness | Multiplier with absorb | absorb heals, then nullify, halve, and weak doubles |
| Fleeing | Hold to run | a run counter per character, raised by a roll each status tick, against 2 per monster |
| Random encounter | Danger counter | Final Fantasy V's counter at half the normal rate, $70 per step |
Every claim about this game, by concept (11)
References
- ^Final Fantasy V counts each combatant's ATB timer down by one per tick from 120 + weight ÷ 8 − agility; Final Fantasy VI instead adds a constant built from speed to a gauge every 2 frames and gives the turn when the gauge overflows.Codeeverything8215, FF5 disassembly · everything8215, FF6 disassembly
How we know
5409 adc #$78 ;+120 5410 sec 5411 sbc Agility ;-agi
src/battle/battle-main.asm lines 5405–5416 at 997c87d · upstream ↗ 4740 lda CurrentTimer,X ⋮ 4742 dec CurrentTimer,X 4743 lda CurrentTimer,X 4744 bne TimerActive 4745FlagTimer: ;flag EnableTimer when CurrentTimer hits 0
src/battle/battle-main.asm lines 4740–4745 at 997c87d · upstream ↗ 91; [ increment atb gauge counter ] ⋮ 98 adc near wTargetProp2::w7e3ac8,x ; add atb constant 99 sta near wTargetProp1::w7e3218,x 100 shorta 101 bcc _11ba ; return if it didn't overflow
src/battle/atb.asm lines 91–104 at 8130132 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-21.
Checked by a second AI model, 2026-10-21.
- ^Each combatant's ATB gauge constant is (speed + 20) times 1.5 times a haste, normal, or slow constant of 84, 64, or 32, over 16; for monsters the speed term is first scaled by 255 − 24 × the battle speed setting, over 255, so the setting slows only the monsters. Every 2 frames
UpdateBattleTimeadds each present combatant's constant to its gauge, and a gauge that overflows gives that combatant a turn. It skips the update only when wait mode is on and the battle-time-stopped flag is also set, since it ANDs the two.Codeeverything8215, FF6 disassemblyrevisedHow we know
1437; [ update atb gauge constant ] ⋮ 1439CalcSpeed: 1440@09d2: php 1441 ldy #$20 1442 lda near wTargetProp3::w7e3ef8,x 1443 bit #STATUS3::SLOW 1444 bne @09e4 1445 ldy #$40 ; y = haste/normal/slow constant (32/64/82) 1446 bit #STATUS3::HASTE 1447 beq @09e4 1448 ldy #$54 ⋮ 1454 lsr ⋮
src/battle/action_1.asm lines 1435–1470 at 8130132 · upstream ↗ 4; [ update battle time ] ⋮ 6UpdateBattleTime: ⋮ 10 lda near w7e2f41 ; check if battle time is stopped by battle program 11 and near w7e3a8f ; wait mode 12 bne @118b 13 lda near w7e3a6c ; previous frame counter value 14 ldx #2 15@112e: cmp $0e ; current frame counter value 16 beq @1190 ; return if less than 2 frames have elapsed
src/battle/atb.asm lines 4–16 at 8130132 · upstream ↗ 91; [ increment atb gauge counter ] ⋮ 97 lda near wTargetProp1::w7e3218,x ; atb gauge % 98 adc near wTargetProp2::w7e3ac8,x ; add atb constant 99 sta near wTargetProp1::w7e3218,x 100 shorta 101 bcc _11ba ; return if it didn't overflow ⋮ 105@11d1: stz near wTargetProp1::w7e3218_H,x ; clear atb gauge % ⋮ 116 jsr SetFlag0 ; set $3aa0.7 (allow battle menu to open) ⋮ 121; [ open battle menu (character) or add action to advance wait queue (monster) ] ⋮ 149_120e: jmp _c24e66 ; add action to advance wait queue
src/battle/atb.asm lines 91–149 at 8130132 · upstream ↗ 75@2481: and #$07 ; battle speed 76 asl3 77 sta $ee 78 asl 79 adc $ee 80 not_a 81 sta near w7e3a90 ; set battle speed constant
src/battle/init.asm lines 75–81 at 8130132 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-21.
Revised after a check by a second AI model, 2026-10-21.
- ^Unless an attack is set to always crit, it is critical when a random byte is under 8, a 1-in-32 chance, and a critical adds 2 to the damage multiplier, which the code comments as damage ×2.Codeeverything8215, FF6 disassembly
How we know
333@33f2: lda #$02 334 bit zb3 335 beq @340c ; auto-crit 336 bit zb2 337 bne @3414 338 bit zba 339 beq @3414 340 jsr Rand 341 cmp #$08 342 bcs @3414 ; 31/32 chance to branch 343 lda near w7e3eb0 + 25 344 beq @3414 ; branch if there are no targets ⋮
src/battle/attack.asm lines 332–348 at 8130132 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-21.
Checked by a second AI model, 2026-10-21.
- ^Final Fantasy VI keeps Final Fantasy V's random-battle counter, which each step raises by the map's rate and which a byte from the random table, offset each time its pointer wraps, is tested against; it halves the normal rate from $E0 to $70 per step and changes the high one from $180 to $160.Codeeverything8215, FF5 disassembly · everything8215, FF6 disassembly
How we know
21700_c0cb09: 21701 .word $00e0, $0040, $0180, $0200
src/field/field-main.asm lines 21700–21701 at 997c87d · upstream ↗ 21658 lda $16a8 ; random battle counter 21659 clc 21660 adc f:_c0cb09,x ; add probability value ⋮ 21666 jsr _c0cc52 ; update random number for random battles 21667 cmp $16a9
src/field/field-main.asm lines 21658–21670 at 997c87d · upstream ↗ 264; normal map random battle rates 265; 8 bytes each (normal, low, high, very high) 266SubBattleRateTbl: 267 .word $0070,$0040,$0160,$0200 ; normal
src/field/battle.asm lines 264–267 at 8130132 · upstream ↗ 386 lda $1f6e ; random battle counter 387 adc f:SubBattleRateTbl,x ; add random battle rate (max #$ff00) ⋮ 392 jsr UpdateBattleRng 393 cmp $1f6f
src/field/battle.asm lines 386–393 at 8130132 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-21.
Checked by a second AI model, 2026-10-21.
- ^ abUnless the target has Image, which a physical attack instead tests with a random byte under $40 (a miss that may remove the Image), an attack that can miss hits when a roll of 0–99 is under its hit rate times the target's stored evade, over 256, where the stored value is 256 − 2 × the evade % (255 for 0). The branch meant to pick Evade for a physical attack tests a carry flag that the check before it has cleared, so every such attack is checked against the target's magic evade (MBlock) and skips the Blind and status adjustments; the disassembly carries a
BUGFIX_EVADEoption, credited to Terii Senshi, that restores Evade.Codeeverything8215, FF6 disassemblyrevisedHow we know
138 lda $11a2 139 lsr 140 bcc @233f ; branch if a magic attack 141 lda near wTargetProp2::RetalFlags,y ; RETAL_FLAGS::RETORT 142 lsr 143 bcs @22e8 ; branch if $3e4c.0 is set (retort) 144 lda near wTargetProp3::w7e3ee5,y 145 bit #STATUS2::IMAGE 146.if BUGFIX_EVADE 147 beq @2346 148.else 149 beq @233f ⋮
src/battle/check_hit.asm lines 138–210 at 8130132 · upstream ↗ 121; [ invert evade/mblock ] ⋮ 123_evasionconv: 124InvertEvade: 125@2861: .a8 126 asl 127 bcc @2866 128 lda #$ff 129@2866: neg_a 130 bne @286c 131 dec
src/battle/init_attacker.asm lines 121–132 at 8130132 · upstream ↗ 41; evade bugfix by Terii Senshi 42def_config BUGFIX_EVADE, 0
src/common/const.inc lines 41–42 at 8130132 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-21.
Revised after a check by a second AI model, 2026-10-21.
Sources
Code
- everything8215. 2026. “Final Fantasy V Disassembly.” Commit 997c87d. everything8215/ff5 @ 997c87d · licence, all uses
- everything8215. 2026. “Final Fantasy VI Disassembly.” Commit 8130132. everything8215/ff6 @ 8130132 · licence, all uses