Cite as
everything8215, FF6 disassembly
Original
https://github.com/everything8215/ff6
Pinned
everything8215/ff6 @ 813013276c952fdd27edcf7b8b86f17291542cbf
Accessed
2026-10-21
Licence
GPL-3.0 (LICENSE file)
Credit
everything8215 and the repository's contributors, who disassembled and commented the Super Famicom game. Every label and comment quoted in ff6 claims is theirs.
Notes
ca65 source that builds Final Fantasy VI 1.0 (J) and Final Fantasy III 1.0 and 1.1 (U), the North American release (README, with CRC32s; the Japanese build fills unused regions with $FF, so it doesn't match the original byte for byte).

Cited on

Claims (14)

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.src/battle/action_1.asm L1435–1470src/battle/atb.asm L4–16src/battle/atb.asm L91–149src/battle/init.asm L75–81Code
Unless 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.src/battle/check_hit.asm L138–210src/battle/init_attacker.asm L121–132src/common/const.inc L41–42Code
CalcDmgMod 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.src/battle/calc_dmg.asm L153–193src/battle/calc_dmg.asm L239–248src/battle/math.asm L41–45Code
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.src/battle/attack.asm L332–348Code
A 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.src/battle/calc_dmg.asm L40–72src/battle/calc_dmg.asm L125–130Code
While 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.src/battle/timer.asm L293–316src/battle/timer.asm L239–242src/battle/timer.asm L13–41src/battle/gfx_buf.asm L22–73src/battle/init_attacker.asm L182–183Code
Each 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.src/field/battle.asm L264–270src/field/battle.asm L374–396src/field/battle.asm L470–485Code
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.src/field/battle.asm L125–129src/field/battle.asm L130–134src/world/move.asm L884–894Code
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.src/battle/atb.asm L91–104Code
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.src/field/battle.asm L264–267src/field/battle.asm L386–393Code
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.src/battle/attack.asm L339–342Code
In the North American release, BattleSetTmpDmgAsPhysical takes the attacker's physical attack S (physAttack after stat multipliers) and the action's level L (characterLevel) and computes (⌊L·S/32⌋ · ⌊(L + S)/32⌋ + S) × (512 − the target's defense) × the attack's power, over 8,192: a base of S + ⌊L·S/32⌋·⌊(L + S)/32⌋, scaled by power/16 and by (512 − defense)/512 (computed). It then doubles the damage when damageFlags bit $2 is set, the bit a critical sets and that this same function also sets for any attack whose attackFlags bit $2000 is clear (ff7/critical), multiplies it by 1.5 under Berserk, for a short-range attack or an enemy's Attack command halves it once if the target or the attacker is in the back row (other attacks ignore rows), halves it for a defending target, multiplies it by the target's backDamageMult/8 when the unnamed unk234 bit 0 is set, quarters it under Frog, applies the Sadness, multi-target, and Barrier modifiers, and sets it to 0 under Mini. Last, BattleAddRndModifierAndZeroCheck multiplies by 3,841 plus a random byte, over 4,096 (93.8–100%, computed), and raises 0 to 1, so a Mini attacker deals 1. Final Fantasy VI's CalcDmgMod also lets defense remove a share, but as (255 − Defense)/256, with a variance of 224–255 over 256 applied before it.src/battle/calc_dmg.asm L153–193Code
In the North American release, BattleRollPhysicalHit hits when a roll of 1–100 (BattleGetRnd164) is under the hit chance: the attack's hit % (targetAttackPercent) plus a quarter of the attacker's dexterity, plus the attacker's Df%, less the target's Df%, cut by 30% under Fury, and raised to at least 1, which never hits. A party member's Df% is a quarter of its dexterity plus its physical evade and an enemy's is its physical evade alone, so a party attacker's dexterity counts twice. The chance is instead 255 against a target under Death, Sleep, Confusion, Stop, Petrify, Manipulate, or Paralysis, for the Death, Nullify, and Absorb affinities and one unnamed affinity flag, and for two flags the code leaves unnamed (unk234 bit 0, unk218 bit 5). Before the roll, a 0–99 roll under the attacker's luck/4 makes a sure hit; failing that, when an enemy attacks a party member and the same roll is under the target's luck/4, the attack misses, even at 255. BattleGetRnd164 scales a 16-bit random number by 99/65,535 and adds 1, so it gives 100 only for $FFFF, and a chance h of 2–100 hits about (h − 1) times in 99 (computed for evenly spread 16-bit values). Final Fantasy VI instead scales the hit rate by the target's stored evade (magic evade, through a bug) and rolls 0–99 against it.src/battle/check_hit.asm L166–210Code
In the North American release, BattleRollCriticalHit is entry 2 of the hit-formula table, so it runs only for an attack whose hit-formula script includes it, and only if the hit roll didn't mark a miss. Its chance is (the action's level + the attacker's luck − the target's level)/4, plus the weapon's critical % for a party member, or 255 under Lucky Girl; a 1–100 roll at or under the chance sets bit 1 ($2) of damageFlags. BattleSetTmpDmgAsPhysical doubles the damage when that bit is set, and sets it itself for an attack whose attackFlags bit $2000 is clear. So a chance c of 0–99 crits about c times in 99 (computed for evenly spread 16-bit values). Final Fantasy VI crits on a random byte under 8, 1 in 32, whatever the stats, and a critical adds 2 to the damage multiplier, which its code comments as damage ×2.src/battle/attack.asm L332–348Code