EarthBound Beginnings
Nintendo's 1989 Famicom role-playing game Mother, read through its English build, released as EarthBound Beginnings, in Nathan-R-Og's disassembly.
On this page
EarthBound Beginnings is the English release of Mother, which Nintendo made for the Famicom. The code read here is Nathan-R-Og’s mother, a cc65 disassembly that builds the Japanese ROM and the English one; the atlas’s Virtual Console ROM has the English build’s hash. The claims describe that build.
A plain attack deals the attacker’s Offense less half the target’s Defense1, and a shared routine then moves the result up or down by 0 to 24 percent, mostly by 10 or less2. The same spread rolls Speed for the turn order, picked again before every action3.
The Fight stat decides both a “SMAAAASH!!” and a dodge. The attacker’s Fight against the target’s sets the critical chance, about 26 in 256 when they match. A SMAAAASH deals the full Offense and comes before the dodge roll4. The target’s Fight against the attacker’s sets the dodge, 27 in 256 when they match5. Running is a coin flip6.
Random encounters roll per step against an area’s rate, 32 in 256 at most. Each fight moves the area down the table for a while, up to two steps7. Damage comes off HP in one subtraction, with no rolling meter8.
Mechanics
| Mechanic | Kind | How |
|---|---|---|
| Turn order | Stat plus a roll | each pick rolls every waiting combatant's Speed through a ±0–24% spread, and the highest acts |
| Damage formula | Attack minus defense | Offense less half the Defense, then a ±0–24% spread weighted toward small changes |
| Critical hit | Stat against stat | "SMAAAASH!!" from the attacker's Fight against the target's, about 26 in 256 when they match; it deals the full Offense |
| Hit chance | Dodge, stat against stat | the target dodges from its Fight against the attacker's, 27 in 256 when they match |
| Fleeing | Fixed chance | 1 time in 2, never in a battle an event started |
| Random encounter | By area | 32 to 5 in 256 per step by area, falling for a while after each fight |
| Rolling HP meter | At once | damage comes off HP at once |
Every claim about this game, by concept (8)
References
- ^In EarthBound Beginnings (English build), a normal attack deals the attacker's Offense less half the target's Defense; when the Offense is below the Defense it deals (3 × Offense − Defense) ÷ 4 instead, at least 1. The damage routine then applies the ±0–24% spread, halves the result for a shielded or guarding target, and deals at least 1.CodeNathan-R-Og/motherrevised
How we know
3399; Normal Attack Damage = AttackerOFF - (DefenderDEF / 2) 3400; If DEF > OFF, Damage = (3 * AttackerOFF - DefenderDEF ) / 4 3401BINST60_SETNUMBASH: ⋮ 3413 sbc battle_wordvar64 ⋮ 3418 sbc battle_wordvar64+1 3419 bcc @SETNUM_WeakBash 3420 lsr battle_wordvar64+1 3421 ror battle_wordvar64 ⋮ 3424 sbc battle_wordvar64 ⋮ 3427 sbc battle_wordvar64+1
src/global/prg/battle.asm lines 3399–3427 at e0b3e3f · upstream ↗ 3445: lda battle_wordvar60 3446 ora battle_wordvar60+1 3447 bne :+ 3448 inc battle_wordvar60 ; min dmg = 1
src/global/prg/battle.asm lines 3444–3448 at e0b3e3f · upstream ↗ 4569DoDamage: 4570 lda target_offset 4571 pha 4572 jsr MOV_input_output
src/global/prg/battle.asm lines 4569–4572 at e0b3e3f · upstream ↗ 5285MOV_input_output: 5286 lda battle_input_num 5287 sta battle_wordvar60 5288 lda battle_input_num+1 5289 sta battle_wordvar60+1 5290 jmp RNG_WORD
src/global/prg/battle.asm lines 5285–5290 at e0b3e3f · upstream ↗ 4593 ; halve damage if shielded ⋮ 4599 ; halve damage if guarding (stacks) ⋮ 4605 ; apply resists if any (stacks) 4606: jsr ApplyResistance 4607 lda battle_wordvar60 4608 ora battle_wordvar60+1 4609 bne :+ 4610 inc battle_wordvar60
src/global/prg/battle.asm lines 4593–4610 at e0b3e3f · 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 EarthBound Beginnings (the English build that the 2015 Virtual Console release uses), a shared routine adds random spread to a value: it moves the value by a weight in percent drawn from a 128-entry table by a random byte, up or down at even odds. The weights run from 0 to 24, and 92 of the 128 entries are 10 or less, so most rolls move the value by a few percent. Damage and the turn-order Speed roll both use it.CodeNathan-R-Og/mother · “EarthBound Beginnings (USA, Europe) (Virtual Console)”
How we know
9867 ldx #6 9868 @B31_130b: 9869 asl UNK_60 9870 rol UNK_60+1 9871 dex 9872 bne @B31_130b ; UNK_60 =<< 6 (multiply by 64) ⋮ 9880 lda #$64 9881 sta UNK_64 9882 jsr B31_113d 9883 jsr RNG_BYTE 9884 lsr a 9885 php ; PUSH SIGN ⋮
src/global/prg/constant.asm lines 9867–9918 at e0b3e3f · upstream ↗ 9943; $F37D - This table is indexed by (rand() >> 1) -- wtf is this layout 9944; WEIGHT 9945B31_137d: 9946 .byte 0, 0, 0, 0, 0 ; 5 9947 .byte 12, 12, 12, 12, 12 ; 5 9948 .byte 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ; 10 ⋮ 9968 .byte 22 ; 1 9969 .byte 23 ; 1 9970 .byte 24 ; 1
src/global/prg/constant.asm lines 9943–9970 at e0b3e3f · upstream ↗ In the cartridge (“EarthBound Beginnings (USA, Europe) (Virtual Console)”): the fixed bank's $F37D, the 128 weights as the ROM has them. We don't reproduce the bytes.
5285MOV_input_output: 5286 lda battle_input_num 5287 sta battle_wordvar60 5288 lda battle_input_num+1 5289 sta battle_wordvar60+1 5290 jmp RNG_WORD
src/global/prg/battle.asm lines 5285–5290 at e0b3e3f · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-21.
Checked by a second AI model, 2026-10-21.
- ^In EarthBound Beginnings (English build), the next combatant to act is picked one at a time: every combatant yet to act this round rolls its Speed through the ±0–24% spread, capped at 255, and the highest goes; the rest roll again for the next pick.CodeNathan-R-Og/mother
How we know
2305BattleTurnEngine: 2306 jsr ConcludeBattle 2307 bcs @TurnEngineReturn 2308 ldx #8 2309@TurnEngineSort_LS: 2310 txa 2311 pha 2312 jsr SortTurnOrder 2313 jsr DoBattlerTurn 2314 lda #$ff 2315 ldy attacker_offset 2316 sta BATTLER_ACTION_ID, y
src/global/prg/battle.asm lines 2305–2316 at e0b3e3f · upstream ↗ 2349SortTurnOrder: ⋮ 2351 sta battle_wordvar60 2352 sta battle_wordvar60+1 ⋮ 2355 lda BATTLER_ACTION_ID, y 2356 cmp #BA_COMPLETE 2357 beq @SortTurnOrder_INC ⋮ 2360 lda BATTLER_SPD, y 2361 jsr RNGifySpeed 2362 cmp battle_wordvar60+1 2363 bcc @SortTurnOrder_INC 2364 sta battle_wordvar60+1 ⋮ 2371 sta battle_wordvar60 ⋮
src/global/prg/battle.asm lines 2349–2376 at e0b3e3f · upstream ↗ 9972; used in Turn Order sorting to randomize speed (theorized effect) 9973; should be +-25% 9974; A should have the Speed value to modify 9975RNGifySpeed: ⋮ 9977 lda UNK_60+1 ⋮ 9979 lda UNK_60 ⋮ 9984 jsr RNG_WORD 9985 lda UNK_60+1 9986 beq @B31_1415 9987 lda #$ff 9988 sta UNK_60
src/global/prg/constant.asm lines 9972–9988 at e0b3e3f · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-21.
Checked by a second AI model, 2026-10-21.
- ^In EarthBound Beginnings (English build), a plain attack is a "SMAAAASH!!" when a random byte is below max(0, ⌊(256 + attacker's Fight − target's Fight) ÷ 2⌋ − 102), about 26 in 256 at equal Fight. It is checked before the dodge roll, so it can't be dodged, and it deals the attacker's Offense, ignoring Defense. There is no SMAAAASH during the invincibility scripts, while the party fires the tank gun instead, or, 1 time in 2, from a blinded attacker.CodeNathan-R-Og/motherrevised
How we know
3135; Same calculation as chance to Dodge. ⋮ 3137BINSTCONDITION2_CRIT: 3138 jsr SEC_IsInvinciblityOn 3139 bcs :+ 3140 ldy attacker_offset 3141 lda BATTLER_CORES, y 3142 sta battle_wordvar60 3143 ldy target_offset 3144 lda BATTLER_CORES, y 3145 sta battle_wordvar62 3146 jsr DoFightEquation 3147 lda battle_wordvar62 ⋮
src/global/prg/battle.asm lines 3135–3149 at e0b3e3f · upstream ↗ 3151; Only runs 50-50 check if attacker_offset is blinded 3152BINSTCONDITION3_BLIND_MISS: 3153 ldy attacker_offset 3154 lda BATTLER_MINOR_STATUS, y 3155 and #BLIND 3156 eor #BLIND 3157 rol a 3158 bcs :+ 3159 jsr RNG_BYTE 3160 and #$80 ; 50-50 3161 rol a 3162: rts
src/global/prg/battle.asm lines 3151–3162 at e0b3e3f · upstream ↗ 3276DoFightEquation: 3277 lda #$01 3278 sta battle_wordvar60+1 3279 sec 3280 lda battle_wordvar60 3281 sbc battle_wordvar62 3282 sta battle_wordvar60 3283 lda battle_wordvar60+1 3284 sbc #$00 3285 lsr a 3286 ror battle_wordvar60 3287 sec ⋮
src/global/prg/battle.asm lines 3276–3295 at e0b3e3f · upstream ↗ 2532 .addr BINST7_IFFALSE ; 7 : Jump If Carry Clear .word ptr 2533 .addr BINST8_IFTRUE ; 8 : Jump If Carry Set .word ptr
src/global/prg/battle.asm lines 2532–2533 at e0b3e3f · upstream ↗ 585BATTLE_ACTION1: 586ba_target BA_TARGET::RETARGET 587ba_jumpifnot BA_CON::BOTHLIVE, BA1_NORMAL 588ba_jumpif BA_CON::IS_BLINDED, BA1_NORMAL 589ba_jumpif BA_CON::IS_TANK, BA1_TANK 590ba_jumpif BA_CON::IS_CRIT, BA1_CRIT ⋮ 596ba_jumpifnot BA_CON::IS_DODGE, BATACT_DODGED_SWIFTLY ⋮ 602 BA1_CRIT: ⋮ 606ba_misc BA_MISC::DISPTEXT, $0B ;SMAAAASH 607ba_misc BA_MISC::DAMAGECALC_CRIT, 0
src/global/battle_data.asm lines 585–608 at e0b3e3f · upstream ↗ 3483; Damage = AttackerOFF 3484; If Teddy Script, setnum to rand(1, 16) 3485BINST61_SETNUMCRIT: 3486 ldy attacker_offset 3487 lda BATTLER_OFF, y 3488 sta battle_input_num
src/global/prg/battle.asm lines 3483–3490 at e0b3e3f · 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 EarthBound Beginnings (English build), the target of a plain attack dodges when a random byte is at most max(0, ⌊(256 + target's Fight − attacker's Fight) ÷ 2⌋ − 102), 27 in 256 at equal Fight; a paralyzed, sleeping, or petrified target can't dodge. The attacker has no accuracy stat of its own.CodeNathan-R-Og/mother
How we know
3106; Used by Normal Attack and all its goons (various semi-clones) to determine if physical missed. 3107; Uses Fight in calculation. "Base chance" to dodge is ~10% (26/256). ⋮ 3110BINSTCONDITION1_DODGED: ⋮ 3112 bne @DodgeFalse ⋮ 3115 and #PETRIFICATION | PARALYSIS | SLEEP 3116 bne @DodgeFalse ⋮ 3119 lda BATTLER_CORES, y 3120 sta battle_wordvar60 3121 ldy attacker_offset 3122 lda BATTLER_CORES, y 3123 sta battle_wordvar62 3124 jsr DoFightEquation ⋮
src/global/prg/battle.asm lines 3106–3133 at e0b3e3f · upstream ↗ 3276DoFightEquation: ⋮ 3282 sta battle_wordvar60 ⋮ 3289 sbc #$66 3290 bcs :+ 3291 lda #$00 3292: sta battle_wordvar60 3293 jsr RNG_BYTE 3294 sta battle_wordvar62
src/global/prg/battle.asm lines 3276–3295 at e0b3e3f · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-21.
Checked by a second AI model, 2026-10-21.
- ^In EarthBound Beginnings (English build), running away works 1 time in 2 (the top bit of a random byte), with no stat in it, and never in a battle an event started.CodeNathan-R-Og/mother
How we know
1474BATACT_RUN_AWAY: 1475ba_target BA_TARGET::OUR_LEADER_REAL 1476ba_misc BA_MISC::DISPTEXT, $43 1477ba_jumpif BA_CON::D2, @fail 1478ba_jumpif BA_CON::SCRIPTED, @fail ⋮ 1487@fail: 1488ba_misc BA_MISC::DISPTEXT, $44
src/global/battle_data.asm lines 1474–1489 at e0b3e3f · upstream ↗ 3219; no requirement 50-50 3220BINSTCONDITION8_50_50: 3221 jsr RNG_BYTE 3222 asl a 3223 rts
src/global/prg/battle.asm lines 3219–3223 at e0b3e3f · upstream ↗ 3243; sees if battle is triggered (not random). 3244; different from battle being scripted 3245BINSTCONDITIONB_NOT_TRIGGERED_BATTLE: 3246 lda is_scripted 3247 bne :+ 3248 sec 3249 rts 3250: clc 3251 rts
src/global/prg/battle.asm lines 3243–3251 at e0b3e3f · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-21.
Checked by a second AI model, 2026-10-21.
- ^In EarthBound Beginnings (English build), each step in an area with encounters starts a fight when a random byte is below a rate from the table 32, 21, 16, 13, 10, 8, 6, 5 (in 256), indexed by the area's frequency class (1–7) plus a counter, capped at the eighth entry. The counter rises by 1 with each encounter, up to 2, so the rate drops after fights; it returns to 0 in areas without encounters and after a fade-out transition.CodeNathan-R-Og/mother · “EarthBound Beginnings (USA, Europe) (Virtual Console)”
How we know
560DoWalkingStep: ⋮ 579 ;get areaEncounterDef based on area 580 ldx map_area 581 lda AREA_ENCOUNTER_LIST, x ⋮ 586 ;else, write 0 587 sta UNK_24
src/global/prg/title.asm lines 560–594 at e0b3e3f · upstream ↗ 615 @EncounterFrequencyExists: 616 clc ⋮ 618 ;if frequency is >= 9, cap it to 8 619 adc UNK_24 620 cmp #9 621 bcc @NoForceCap 622 lda #8 ⋮ 627 ;get a random value 628 jsr RNG_BYTE ⋮ 631 cmp AREA_FREQ_TABLE-1, x 632 ;if random value >= area_freq_table[x], leave 633 bcs @FrequencyFail ⋮
src/global/prg/title.asm lines 614–645 at e0b3e3f · upstream ↗ 694 AREA_FREQ_TABLE: 695 ;lookup table for frequencies 696 .byte 32,21,16,13,10,8,6,5
src/global/prg/title.asm lines 694–696 at e0b3e3f · upstream ↗ In the cartridge (“EarthBound Beginnings (USA, Europe) (Virtual Console)”): bank $14 $B58B, the eight rates as the ROM has them. We don't reproduce the bytes.
2761 ;fade out 2762B30_0b57: 2763 jsr BANKSET_H13 2764 jsr OverworldTransitionIntepreter ⋮ 2770 lda #0 2771 sta UNK_24
src/global/prg/constant.asm lines 2761–2771 at e0b3e3f · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-21.
Checked by a second AI model, 2026-10-21.
- ^In EarthBound Beginnings (English build), damage comes off the target's HP in one subtraction, and the target falls when it reaches 0 or below: there is no rolling meter.CodeNathan-R-Og/mother
How we know
4635; @UpdateHP Effect 4636 ldy target_offset 4637 sec 4638 lda BATTLER_CURR_HP, y 4639 sbc battle_wordvar60 4640 sta BATTLER_CURR_HP, y 4641 lda BATTLER_CURR_HP+1, y 4642 sbc battle_wordvar60+1 4643 sta BATTLER_CURR_HP+1, y 4644 bcc @DeathEffect 4645 ora BATTLER_CURR_HP, y 4646 beq @DeathEffect
src/global/prg/battle.asm lines 4635–4646 at e0b3e3f · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-21.
Checked by a second AI model, 2026-10-21.
Sources
Code
- Nathan-R-Og. 2026. “mother: Disassembly of Mother/Earthbound Zero/Earthbound Beginnings for the NES.” Commit e0b3e3f. Nathan-R-Og/mother @ e0b3e3f · licence, all uses
- n.d. “EarthBound Beginnings (USA, Europe) (Virtual Console).” · licence, all uses