On this page
  1. The evade bug
  2. Related
  3. Mechanics
  4. References
  5. Sources

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

MechanicKindHow
Turn orderActive timeeach combatant's gauge fills in real time by its speed
Active Time BattleGauge(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 chanceHit times evadehit 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 formulaDefense as a fractiona random 224–255 over 256, then 255 − defense over 256
Critical hitFixed1 in 32 for any attack that can crit, doubling the damage
Elemental weaknessMultiplier with absorbabsorb heals, then nullify, halve, and weak doubles
FleeingHold to runa run counter per character, raised by a roll each status tick, against 2 per monster
Random encounterDanger counterFinal Fantasy V's counter at half the normal rate, $70 per step
Every claim about this game, by concept (11)
Active Time BattleEach 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 UpdateBattleTime adds 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.Code
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.Code
Critical hitUnless 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.Code
In Final Fantasy V only three weapon attack types roll for a critical (fists, katanas, and type 36), at the crit % the attack type carries; in Final Fantasy VI an attack that can crit does so on a random byte under 8, 1 in 32, whatever the weapon.Code
Damage formulaCalcDmgMod multiplies the damage by a random variance and then by 255 − the target's Defense (Magic Defense for a magic attack), each over 256 plus 1. The variance is a random byte ORed with $E0, so 224–255; the routine's comment says 240–255.Code
Elemental weaknessA damage element that the target absorbs turns the damage into healing; one it nullifies makes the damage 0; one it halves halves it; one it is weak to doubles it, unless the damage is already 32,768 or more. The checks run in that order and the first match applies.Code
FleeingWhile the characters are trying to run away, each character's run counter gains a random 1 to their run factor each time their status counter overflows, and the character escapes when the counter reaches the run difficulty. The difficulty is 2 for each monster present, or 6 for one marked harder to run from; a monster marked can't-escape, or a pincer attack, forbids running.Code
Hit chanceUnless 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_EVADE option, credited to Terii Senshi, that restores Evade.Code
Random encounterEach step on a town or dungeon map adds the map's rate to a random-battle counter ($70 per step at the normal rate; $40, $160, or $200 at the low, high, and very high ones; the Charm Bangle halves them and the Moogle Charm zeroes them), and a battle starts when a byte from the random table, plus an offset that grows by 17 each time its pointer wraps, is under the counter's high byte. A battle clears the counter, so each step without one makes the next likelier.Code
On the world map, the sector that picks the battle rate and group is read from $1F60 and $1F61. While the player walks, the world map's movement code copies the current position there only in the branch taken after a random battle starts, so the rate and group stay as they were until a battle or another writer (world map start, events, entrances) updates them; the disassembly marks this as a bug.Code
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.Code

References

  1. ^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.

    In the claim ledger

  2. ^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 UpdateBattleTime adds 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 disassemblyrevised
    How 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.

    In the claim ledger

  3. ^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.

    In the claim ledger

  4. ^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.

    In the claim ledger

  5. ^ 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_EVADE option, credited to Terii Senshi, that restores Evade.Codeeverything8215, FF6 disassemblyrevised
    How 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.

    In the claim ledger

Sources

Code