data/claims/chrono-trigger.yamlChrono Trigger's battle rules and New Game+ (dscotton's ct_disassembly, USA ROM)
Game: Chrono Trigger.
The load screen offers New Game+ only when one byte of the battery save, kept outside the three save slots, is set. In Mesen, with a staged save in slot 0 and that byte set, the screen drew a "New Game +" label beside the plain "New Game"; with the cursor on New Game, Right flipped a menu byte from $08 to $78, the value the confirm code tests, and A then opened the screen's slot prompt. A without Right started a plain new game, and with the byte cleared the screen drew no "New Game +" label. The plus is font character $EC, whose tile on that screen is a plus sign. chrono-trigger/new-game-plus-gate
About: Chrono Trigger New Game+
Value: label New Game + · selected 78 · prompt state 2
VerifiedChrono Trigger (USA) ·0x2e5d3-0x2e922 — $C2:E5D3-$C2:E922, the load screen, run by the probe: three runs in MesenCE 2.2.1 from power-on. The probe writes slot 0 (its checksum and the magic word $E41B) and $30:7FE2 = $FF (or 0) on the first frame, resets, presses Start every 120 frames until menu screen $0E opens, waits 120 frames, then taps Up, Right (or not), A, Down and A, 16 frames apart. Labels are read from video RAM, where the screen's tile numbers are the font's character codes, and the glyph from the font tiles at $E000.ct_disassembly: Chrono Trigger (US v1.0) disassembly · bank_C2.asm#L24431-L24445+ LDA.L $307FE2 ;C2E75D|AFE27F30|307FE2;
BEQ + ;C2E761|F017 |C2E77A;
LDA.B $54 ;C2E763|
CMP.B #$03 ;C2E765|
BNE _LE77A ;C2E767|
LDA.B $5A ;C2E769|
AND.B #$03 ;C2E76B|
BEQ _LE77A ;C2E76D|
LDA.W $9392 ;C2E76F|
EOR.B #$70 ;C2E772|
STA.W $9392 ;C2E774|
JSR.W Menu_PlayCursorSfx ;C2E777|
…Our readingonly when the save byte at $30:7FE2 is set24431–24432and the cursor is on New Game (position 3)24433–24435and Left or Right is pressed24436–24438flip the byte at $9392 between $08 and $7824439–24442ct_disassembly: Chrono Trigger (US v1.0) disassembly · bank_C2.asm#L24294-L24318+ JSR.W Menu_PlayCursorSfx ;C2E647|20C2EA |C2EAC2;
SEP #$30 ;C2E64A|E230 | ;
LDA.B $54 ;C2E64C|A554 |000054;
CMP.B #$03 ;C2E64E|C903 | ;
BCS LoadSaveMenuPossiblyOther_E65D ;C2E650|B00B |C2E65D;
STA.B $79 ;C2E652|8579 |000079;
STA.W !LastSlotSavedCopied ;C2E654|8D1404 |7E0414;
JSL.L SaveSlot_LoadRegions ;C2E657|22A3FAFF|FFFAA3;
BRA + ;C2E65B|8037 |C2E694;
; | | ;
LoadSaveMenuPossiblyOther_E65D:
JSR.W NewGame_SeedCharStatsAndTechs ;C2E65D|
…Our readingA on a slot (cursor below 3) loads that slot24296–24301A on New Game: set up a new game24305–24307if the save byte is set and $9392 holds $78, draw the slot prompt and go to the next state24310–24318ct_disassembly: Chrono Trigger (US v1.0) disassembly · bank_C2.asm#L24497-L24500LDA.L $307FE2 ;C2E7F9|AFE27F30|307FE2;
BEQ + ;C2E7FD|F006 |C2E805;
LDX.W #$C36B ;C2E7FF|
JSR.W Menu_RunFFUiCommandList ;C2E802|Our readingwhen the save byte is set, run the screen's extra drawing list at $FF:C36B24497–24500New Game+ starts from a new game's records and copies three things from the chosen slot: the first 1,408 bytes of its main block (the inventory, the seven characters' records and what follows them, up to the active party), the 51 bytes of names and gold, and one event-flag byte whose bits let each character learn magic techniques. It then dresses each character in the four pieces of equipment from its starting record, Ayla's weapon excepted, putting the saved gear in the inventory; recomputes HP and refills MP; removes every item whose record carries flag bit $10; and sets another event-flag byte to $10. In Mesen, from a save staged in slot 0 and started through the load screen, the copied bytes held the save's values, and every other byte of work RAM at $7E:2000-$7E:2FFF and $7F:0000-$7F:01FF stayed as the new game had set it; five bytes at $7E:2857-$7E:285B, which changed during the run, were left out of the check. Verified — the slots: $30:6000, $6A00 and $7400, $A00 bytes each, so $30:7FE2 lies outside themChecked by claude, 2026-11-08 — ran probes/chrono-trigger/new-game-plus.mjs (three runs from power-on with a staged SRAM: byte set with and without Right, byte cleared); read the load screen's cursor routine (bank_C2.asm L24431-L24445), the confirm branch (L24294-L24318) and the build step that runs the extra drawing list (L24497-L24500)Revised after a check by a second AI model, 2026-11-08.Probe: probes/chrono-trigger/new-game-plus.mjsCited by: New Game+
Choosing New Game+ draws the prompt "Start using which data?" and waits for input: confirming on one of the three save slots carries that slot into the new game and starts it, confirming on New Game starts a plain new game, and the other input puts the cursor back on New Game and returns to the slot list. chrono-trigger/new-game-plus-prompt
About: Chrono Trigger New Game+
Codect_disassembly: Chrono Trigger (US v1.0) disassembly ·bank_C2.asm#L24525-L24537PHP ;C2E841|
REP #$30 ;C2E842|
SEP #$20 ;C2E844|
INC.W $0D84 ;C2E846|
LDA.B #$03 ;C2E849|
STA.W $020C ;C2E84B|
LDX.W #$5E00 ;C2E84E|
STX.W $0DC5 ;C2E851|
LDX.W #$CF3B ;C2E854|
STX.W $020D ;C2E857|
LDA.B #$FF ;C2E85A|
STA.W $020F ;C2E85C|
…Our readingdraw string 3 of the description table at $FF:CF3B24529–24537Chrono Trigger (USA) · 0x3fcfd9-0x3fcff0 — $FF:CFD9, string 3 of the table at $FF:CF3B: "Start using" / "which data?"ct_disassembly: Chrono Trigger (US v1.0) disassembly · bank_C2.asm#L24341-L24376PointersUsed_C2E6AE:
JSR.W Menu_UpdateSelectionInput ;C2E6AE|
BIT.W $0D1D ;C2E6B1|
BMI _C2LE6C5 ;C2E6B4|
BVS _C2LE6DF ;C2E6B6|
JSR.W Menu_SaveSlotCursorMove ;C2E6B8|
LDA.B $81 ;C2E6BB|
CMP.B $54 ;C2E6BD|
BEQ _C2LE6C4 ;C2E6BF|
JSR.W Menu_PlayCursorSfx ;C2E6C1|
_C2LE6C4:
RTS ;C2E6C4|
…Our readingconfirm or cancel24342–24345confirm on New Game (cursor 3 or more): the plain new game path24356–24359confirm on a slot: carry it over ($FF:FAED), then start the game24360–24364the other input: cursor to New Game (3), back to the slot list24365–24376The load screen offers New Game+ only when one byte of the battery save, kept outside the three save slots, is set. In Mesen, with a staged save in slot 0 and that byte set, the screen drew a "New Game +" label beside the plain "New Game"; with the cursor on New Game, Right flipped a menu byte from $08 to $78, the value the confirm code tests, and A then opened the screen's slot prompt. A without Right started a plain new game, and with the byte cleared the screen drew no "New Game +" label. The plus is font character $EC, whose tile on that screen is a plus sign. Verified — the character codes, read from the screenct_disassembly: Chrono Trigger (US v1.0) disassembly · bank_C2.asm#L24319-L24340_LE683:
LDX.B #$00 ;C2E683|
_LE685:
LDA.W $0D49,X ;C2E685|
BEQ _LE691 ;C2E688|
INX ;C2E68A|
CPX.B #$03 ;C2E68B|
BCC _LE685 ;C2E68D|
LDX.B #$00 ;C2E68F|
_LE691:
STX.W $0414 ;C2E691|
; | | ;
…Our readingthe plain new game: note the first slot whose valid mark is 0, or slot 024319–24329leave the menu for the game24331–24340Checked by claude, 2026-11-08 — read the prompt's drawing (bank_C2.asm L24525-L24537: string 3 of the table at $FF:CF3B) and the prompt state (L24341-L24368); decoded the string's bytes at $FF:CFD9 with the font's letter order, which the gate probe's labels bear out ($A0 A, $BA a, $EF space); the probe renders $B2 as an S and $DF as a hook over a stem, a question mark; the confirm on a slot is the probe's ARevised after a check by a second AI model, 2026-11-08.Cited by: New Game+
New Game+ starts from a new game's records and copies three things from the chosen slot: the first 1,408 bytes of its main block (the inventory, the seven characters' records and what follows them, up to the active party), the 51 bytes of names and gold, and one event-flag byte whose bits let each character learn magic techniques. It then dresses each character in the four pieces of equipment from its starting record, Ayla's weapon excepted, putting the saved gear in the inventory; recomputes HP and refills MP; removes every item whose record carries flag bit $10; and sets another event-flag byte to $10. In Mesen, from a save staged in slot 0 and started through the load screen, the copied bytes held the save's values, and every other byte of work RAM at $7E:2000-$7E:2FFF and $7F:0000-$7F:01FF stayed as the new game had set it; five bytes at $7E:2857-$7E:285B, which changed during the run, were left out of the check. chrono-trigger/new-game-plus-carry
About: Chrono Trigger New Game+
Value: copied 7e2400-7e297f, 7e2c23-7e2c55 · flag copied 7f01e0 · flag set 7f01cf=10 · rock bytes 7e2857-7e285b
VerifiedChrono Trigger (USA) ·0x3ffaed-0x3ffbd2 — $FF:FAED-$FF:FBD2, an incbin in the disassembly. Our reading: two copies from the slot (records at $FF:FBC1); the byte at slot offset $7E3 ($7F:01E0) copied; for characters 6 down to 0, the starting record's bytes $29, $2A, $28 and $27 (at $FF:FBCF) passed to party operation $0A, the weapon skipped for the record at $190 (Ayla); party operations 6 and 7; for the 242 inventory slots, an item whose $7E:7700 entry has bit $10 cleared with its count; $10 stored to $7F:01CF.ct_disassembly: Chrono Trigger (US v1.0) disassembly · bank_FF.asm#L1184-L1188 — The save layout, the disassembly's comment; the copy records give the same offsets.; (SaveSlot_GetBase: slot bases $306000/$306A00/$307400, $0A00 bytes each). Regions: $7E2400+$5B0
; (main save block: inventory/char records/learned techs/gold), $7E2C23+$33 (character names),
; $7E0400+$10 (config), $00:0100+$10, $7F0000+$200 (event flags), $00:027E+2, $00:0290+$11,
; $7E2C7C+$1E. Because region 1 ($7E2400) is copied first, it lands at slot offset 0:
; inventory item ids at slot+$000..$0FF, quantities at slot+$100..$1FF. After the regionct_disassembly: Chrono Trigger (US v1.0) disassembly · bank_C2.asm#L24305-L24305 — The new game's records are set up before the prompt, so the carry-over writes over them.JSR.W NewGame_SeedCharStatsAndTechs ;C2E65D|ct_disassembly: Chrono Trigger (US v1.0) disassembly · bank_C1.asm#L31184-L31200LDA.L CharTechIdTables,X ;C1F482|BFEB1BCC|CC1BEB;
AND.B #$80 ;C1F486|2980 | ;
BEQ + ;C1F488|F018 |C1F4A2;
TDC ;C1F48A|7B | ;
LDA.W $B2D1 ;C1F48B|ADD1B2 |7EB2D1;
TAY ;C1F48E|A8 | ;
LDA.B #$01 ;C1F48F|A901 | ;
; | | ;
- CPY.W #$0000 ;C1F491|C00000 | ;
BEQ ++ ;C1F494|F004 |C1F49A;
ASL A ;C1F496|0A | ;
DEY ;C1F497|88 | ;
…Our readinga magic technique (id bit $80)31184–31186is learned only if the character's bit is set in $7F:01E031187–31200ct_disassembly: Chrono Trigger (US v1.0) disassembly · bank_C2.asm#L13577-L13614; Y = char record: recomputes effective HP field +$03 = base max HP +$05 plus 25%/50% bonus when accessory +$2A is item $A0/$A1, clamped to 999.
Party_RecalcCharHpBonus: LDA.W $002A,Y ;C28D1C|B92A00 |7E002A;
AND.W #$00FF ;C28D1F|29FF00 | ;
TAX ;C28D22|AA | ;
LDA.W $0005,Y ;C28D23|B90500 |7E0005;
CPX.W #$00A1 ;C28D26|E0A100 | ;
BEQ + ;C28D29|F009 |C28D34;
CPX.W #$00A0 ;C28D2B|E0A000 | ;
BEQ ++ ;C28D2E|F003 |C28D33;
LDA.W #$0000 ;C28D30|A90000 | ;
; | | ;
++ LSR A ;C28D33|4A | ;
…Our readingHP field +3 = base maximum +5, plus half for accessory $A1 or a quarter for $A0, at most 99913578–13594MP byte +7 = byte +9, for the seven records13600–13612ct_disassembly: Chrono Trigger (US v1.0) disassembly · bank_C2.asm#L14994-L15002+ STZ.B $00 ;C298B5|6400 |000000;
; | | ;
- SEP #$20 ;C298B7|E220 | ;
LDA.B $00 ;C298B9|A500 |000000;
JSR.W Item_GetStatsPtr ;C298BB|20AD88 |C288AD;
LDY.B $00 ;C298BE|A400 |000000;
LDA.L CharInitData,X ;C298C0|BF0000CC|CC0000;
AND.B #$1E ;C298C4|291E | ;
STA.W $7700,Y ;C298C6|990077 |7E7700;Our reading$7E:7700 + item = the item record's first byte, bits $1E14994–15002ct_disassembly: Chrono Trigger (US v1.0) disassembly · bank_C2.asm#L12297-L12297JSL.L Menu_CheckRockTriples ;C2837B|2258F9FF|FFF958;ct_disassembly: Chrono Trigger (US v1.0) disassembly · bank_C2.asm#L13463-L13465JSR.W (PartyOp_JumpTable,X) ;C28C4A|FC5B8C |C28C5B;
STA.B $C1 ;C28C4D|85C1 |0004C1;
JSR.W Menu_LoadPartyD1Recs ;C28C4F|204D83 |C2834D;Our readingafter every party operation, reload the party records (whose routine makes the call above)13463–13465ct_disassembly: Chrono Trigger (US v1.0) disassembly · bank_C2.asm#L12215-L12215 — The disassembly's account of the five bytes, not traced here.; Clears $2857-2859 then scans all 7 char records: if the equipped accessory (+$2A) is a rock item ($AE-$B2) and its $03F6+id gate is set, writes $80 to $27A9+id (=$2857+); paired with Menu_CheckRockTriples on menu exit.Checked by claude, 2026-11-08 — disassembled $FF:FAED-$FF:FBC0 and its two copy records at $FF:FBC1 (slot offset $000 to $7E:2400, $580 bytes; slot offset $5B0 to $7E:2C23, $33 bytes), the starting-record offsets at $FF:FBCF, and the equip operation it calls (party operation $0A at $C2:8D8F); read the HP and MP operations (bank_C2.asm L13577-L13614), the item flag table it tests (L14994-L15002), the magic gate on the copied byte (bank_C1.asm L31184-L31200), and the save layout (bank_FF.asm L1184-L1188); ran the probe, which checks each copied byte against the staged save and each equip and inventory count against the routine's orderRevised after a check by a second AI model, 2026-11-08.Probe: probes/chrono-trigger/new-game-plus.mjsCited by: New Game+
The items New Game+ removes are those whose record's first byte has bit $10 set: every key item from the Seed to Toma's Pop but the Race Log, and the Slasher, Slasher 2, the three Masamune entries, the Bent Sword and Bent Hilt, the Taban Vest, Taban Suit and Taban Helm, OzziePants, the GreenDream, the Hero Medal and the Flea Vest, as the item tables list them. Gear a character still wears is put in the inventory first, so it goes too. chrono-trigger/new-game-plus-purge
About: Chrono Trigger New Game+
CodeChrono Trigger (USA) ·0x3ffb9c-0x3ffbb8 — $FF:FB9C-$FF:FBB8: for each of 242 inventory slots, clear the item and its count when $7E:7700 + item has bit $10.ct_disassembly: Chrono Trigger (US v1.0) disassembly · bank_C2.asm#L14994-L15002+ STZ.B $00 ;C298B5|6400 |000000;
; | | ;
- SEP #$20 ;C298B7|E220 | ;
LDA.B $00 ;C298B9|A500 |000000;
JSR.W Item_GetStatsPtr ;C298BB|20AD88 |C288AD;
LDY.B $00 ;C298BE|A400 |000000;
LDA.L CharInitData,X ;C298C0|BF0000CC|CC0000;
AND.B #$1E ;C298C4|291E | ;
STA.W $7700,Y ;C298C6|990077 |7E7700;The 89 weapon slots ($01-$59) each have a six-byte record (flags, price, who may equip it, a stat bonus, and an element bonus) and a five-byte one whose first byte is the weapon's attack; the menu takes the equipped weapon's as the weapon attack it works the character's attack from. CodeThe 32 armor slots ($5B-$7A) each have a six-byte record (flags, price, who may equip it, a stat bonus, and an element bonus) and a three-byte one whose first byte is its defense; the menu adds the equipped armor's and helmet's to the defense it totals. CodeThe 24 helmet slots ($7C-$93) each have a six-byte record (flags, price, who may equip it, a stat bonus, and an element bonus) and a three-byte one whose first byte is its defense; the menu adds the equipped armor's and helmet's to the defense it totals. CodeThe 39 accessory slots ($95-$BB) each have a four-byte record (flags, price, and who may equip it) and a four-byte one; when the second byte of that has bit 6 set, its third byte is a stat bonus, as a weapon's is. CodeThe 53 slots from $BD to $F1 hold the consumables and key items, each with a three-byte record (flags and price) and a four-byte one that the item-use code reads for its effect. CodeNew Game+ starts from a new game's records and copies three things from the chosen slot: the first 1,408 bytes of its main block (the inventory, the seven characters' records and what follows them, up to the active party), the 51 bytes of names and gold, and one event-flag byte whose bits let each character learn magic techniques. It then dresses each character in the four pieces of equipment from its starting record, Ayla's weapon excepted, putting the saved gear in the inventory; recomputes HP and refills MP; removes every item whose record carries flag bit $10; and sets another event-flag byte to $10. In Mesen, from a save staged in slot 0 and started through the load screen, the copied bytes held the save's values, and every other byte of work RAM at $7E:2000-$7E:2FFF and $7F:0000-$7F:01FF stayed as the new game had set it; five bytes at $7E:2857-$7E:285B, which changed during the run, were left out of the check. Verified — the probe's check that no flagged item is leftChecked by claude, 2026-11-08 — listed the rows of the five item tables whose flags have bit $10; read the table the purge tests (bank_C2.asm L14994-L15002) and the purge loop in our disassembly of $FF:FB9C-$FF:FBB8; the New Game+ probe saw the Masamune, Taban Helm, Taban Vest, Hero Medal, Gate Key, Pendant and Moon Stone goChecked by a second AI model, 2026-11-08.Cited by: New Game+
The save byte that unlocks New Game+ is set to $FF by one entry of the party-operation table; no call to that entry was found, since every long call into the party operations passes another operation number. The byte is cleared in one branch of the menu launcher, taken when it is called for menu 0 while a flag at $7F:0061 is still 0. The save check (party operation 9) leaves that flag at 0 when no slot passes validation and sets it to 2 otherwise, and the load screen's New Game sets it to 1. In Mesen, power-on with the byte set and no valid slot ran the clear once and left the byte at 0; with a valid slot the clear never ran, and a plain new game started from the load screen left the byte at $FF. Erasing a slot from the load screen also clears the byte when no valid slot is left. chrono-trigger/new-game-plus-unlock
About: Chrono Trigger New Game+
Value: no slot clears true · no slot byte 00 · plain byte ff
VerifiedChrono Trigger (USA) ·0x28042-0x2805a — $C2:8042-$C2:805A, the launcher's start-up branch, run by the probe in MesenCE 2.2.1: the staged SRAM without a valid slot, Start pressed every 120 frames for 1,800 frames from power-on; an execution callback at $C2:8053 (the store that clears the byte) counted its runs, and the byte was read from save RAM after each run.ct_disassembly: Chrono Trigger (US v1.0) disassembly · bank_C2.asm#L13615-L13617LDA.B #$FF ;C28D63|
STA.L $307FE2 ;C28D65|
RTS ;C28D69|Chrono Trigger (USA) · 0x28c5b-0x28c74 — $C2:8C5B, the party-operation table: entry 8 is $8D63.ct_disassembly: Chrono Trigger (US v1.0) disassembly · bank_C2.asm#L11873-L11882LDA.W !HoldsIndexMenuLoad ;C2803D|AD000A |7E0A00;
BNE + ;C28040|D022 |C28064;
LDA.L !StatusByteUsedBy_0061 ;C28042|AF61007F|7F0061;
BNE + ;C28046|D01C |C28064;
JSR.W NewGame_SeedCharStatsAndTechs ;C28048|206E95 |C2956E;
LDA.B #$01 ;C2804B|A901 | ;
STA.L !StatusByteUsedBy_0061 ;C2804D|8F61007F|7F0061;
LDA.B #$00 ;C28051|A900 | ;
STA.L $307FE2 ;C28053|8FE27F30|307FE2;
STA.L $307FE1 ;C28057|8FE17F30|307FE1;Our readingcalled for menu 0 while the start-up flag at $7F:0061 is still 011873–11876seed the starting party, set the flag to 111877–11879clear the byte11880–11881ct_disassembly: Chrono Trigger (US v1.0) disassembly · bank_C2.asm#L13618-L13636SEP #$30 ;C28D6A|E230 | ;
STZ.B $79 ;C28D6C|6479 |000479;
; | | ;
- JSL.L SaveSlot_Validate ;C28D6E|22C4F9FF|FFF9C4;
ORA.B #$00 ;C28D72|0900 | ;
BEQ + ;C28D74|F00F |C28D85;
INC.B $79 ;C28D76|E679 |000479;
LDA.B $79 ;C28D78|A579 |000479;
CMP.B #$03 ;C28D7A|C903 | ;
BCC - ;C28D7C|90F0 |C28D6E;
JSR.W NewGame_SeedCharStatsAndTechs ;C28D7E|206E95 |C2956E;
LDA.B #$00 ;C28D81|A900 | ;
…Our readingvalidate slots 0 to 2 in turn13621–13627none valid: seed the starting party, flag 013628–13630a valid slot: flag 213632–13635ct_disassembly: Chrono Trigger (US v1.0) disassembly · bank_C2.asm#L24573-L24590PHP ;C2E8B7|
SEP #$30 ;C2E8B8|
LDX.B $79 ;C2E8BA|
STZ.W $0D49,X ;C2E8BC|
STZ.W $0D79,X ;C2E8BF|
LDA.B $79 ;C2E8C2|
ASL ;C2E8C4|
TAX ;C2E8C5|
STA.L $307FF8,X ;C2E8C6|
LDA.B #$7E ;C2E8CA|
STA.W $9894 ;C2E8CC|
LDA.W $0D49 ;C2E8CF|
…Our readinginvalidate the slot24575–24581if no valid slot is left, clear the byte24584–24588Checked by claude, 2026-11-08 — ran probes/chrono-trigger/new-game-plus.mjs (a fourth run boots with the byte set and slot 0's magic word cleared; every run ends by reading the byte and counting runs of the clear); read the entry (bank_C2.asm L13615-L13617), the table (ROM $C2:8C5B, entry 8), the launcher's branch (L11873-L11882), the save check (L13618-L13636) and the erase step (L24573-L24590); searched the ROM for JSL $C2:8004 (15 sites, operations 0-7 and 9-12, each loaded as an immediate just before), for jumps and branches to $C2:8D63, and for other stores to $7FE2Revised after a check by a second AI model, 2026-11-08.Probe: probes/chrono-trigger/new-game-plus.mjsCited by: New Game+
The disassembly calls the event-flag byte New Game+ sets "New Game+ right telepod active to warp to Lavos"; the event script that reads it is not traced. chrono-trigger/new-game-plus-telepod
About: Chrono Trigger New Game+
Code notesct_disassembly: Chrono Trigger (US v1.0) disassembly ·ramvars.asm#L260-L260!NewGameRightTelepod = $7F01CF ; New Game+ right telepod active to warp to LavosChecked by a second AI model, 2026-11-08.New Game+ becomes available once Lavos has been beaten in one of the normal endings, reached by fighting through the Black Omen or by the Bucket at the End of Time; until then the load screen doesn't offer it. In the USA cartridge the offer waits on one save byte, and the code that sets that byte has not been found. chrono-trigger/new-game-plus-condition
About: Chrono Trigger New Game+
PublisherNintendo Player's Guide: Chrono Trigger ·p. 129 (scan image 77), Altered DestiniesThe "New Game +" option won't appear on the file save screen until you defeat Lavos for the first time.Nintendo Player's Guide: Chrono Trigger · p. 129 (scan image 77), Normal EndingsAll the normal endings are found by beating Lavos when your party battles through the Black Omen Fortress or warps in the Bucket at the End of Time. You need to beat Lavos in this manner to select the "New Game +" mode.The load screen offers New Game+ only when one byte of the battery save, kept outside the three save slots, is set. In Mesen, with a staged save in slot 0 and that byte set, the screen drew a "New Game +" label beside the plain "New Game"; with the cursor on New Game, Right flipped a menu byte from $08 to $78, the value the confirm code tests, and A then opened the screen's slot prompt. A without Right started a plain new game, and with the byte cleared the screen drew no "New Game +" label. The plus is font character $EC, whose tile on that screen is a plus sign. Verified — the save byte the load screen tests before it draws the optionThe save byte that unlocks New Game+ is set to $FF by one entry of the party-operation table; no call to that entry was found, since every long call into the party operations passes another operation number. The byte is cleared in one branch of the menu launcher, taken when it is called for menu 0 while a flag at $7F:0061 is still 0. The save check (party operation 9) leaves that flag at 0 when no slot passes validation and sets it to 2 otherwise, and the load screen's New Game sets it to 1. In Mesen, power-on with the byte set and no valid slot ran the clear once and left the byte at 0; with a valid slot the clear never ran, and a plain new game started from the load screen left the byte at $FF. Erasing a slot from the load screen also clears the byte when no valid slot is left. Verified — no call to the operation that sets the byte was foundChecked by claude, 2026-11-08 — read p. 129 on the scan's page image (page/n76.jpg) and matched each quote to the OCRChecked by a second AI model, 2026-11-08.Cited by: New Game+
Most of the game's endings are reached only on a New Game+ file. A gate in the right telepod at Leene Square leads straight to Lavos, and which ending plays depends on the quests done before that fight. chrono-trigger/new-game-plus-endings
About: Chrono Trigger New Game+
PublisherNintendo Player's Guide: Chrono Trigger ·p. 129 (scan image 77), Altered DestiniesThere are many endings in Chrono Trigger, but you can only see most of them if you finish the game a second time using the "New Game +" mode.Nintendo Player's Guide: Chrono Trigger · p. 129 (scan image 77), The Lavos GateLook for the new gate in the right teleportation station in Leene Square. This is your direct link to LavosNintendo Player's Guide: Chrono Trigger · p. 129 (scan image 77), Multi EndingsThe Lavos Gate appears in Leene Square. You can choose between playing the game or defeating Lavos. Endings depend on which quests you undertake.Checked by claude, 2026-11-08 — read p. 129 on the scan's page image (page/n76.jpg) and matched each quote to the OCRChecked by a second AI model, 2026-11-08.The disassembly names the event-flag byte New Game+ sets after this telepod (new-game-plus-telepod), and the event script that reads it, like the one that picks the ending (ending-choice), is not traced.
Cited by: New Game+
The earliest known English print uses of the mode's name date from 1995: Nintendo of America's Player's Guide for the game, © 1995, calls it "New Game +" and also "New Game Plus". "New Game +" is the label the USA release's load screen draws. chrono-trigger/new-game-plus-name
About: Chrono Trigger New Game+
Value: en New Game + · en alt New Game Plus
PublisherNintendo Player's Guide: Chrono Trigger ·p. 129 (scan image 77), How to Find a Plus EndingUse the "New Game Plus" file to return to the past and find some of the best endings in Chrono Trigger.Nintendo Player's Guide: Chrono Trigger · p. 129 (scan image 77), Select the "New Game +"The "New Game +" mode is not available until you finish Chrono Trigger for the first time.Nintendo Player's Guide: Chrono Trigger · imprint (scan image 3) — the staff page's imprint, which the OCR misses; read on the page image (page/n2.jpg)©1995 by Nintendo of America Inc.The load screen offers New Game+ only when one byte of the battery save, kept outside the three save slots, is set. In Mesen, with a staged save in slot 0 and that byte set, the screen drew a "New Game +" label beside the plain "New Game"; with the cursor on New Game, Right flipped a menu byte from $08 to $78, the value the confirm code tests, and A then opened the screen's slot prompt. A without Right started a plain new game, and with the byte cleared the screen drew no "New Game +" label. The plus is font character $EC, whose tile on that screen is a plus sign. Verified — the load screen's "New Game +" label, read from video RAM in MesenChecked by claude, 2026-11-08 — read the guide's p. 129 and imprint on the page images (page/n76.jpg, page/n2.jpg); the Internet Archive's OCR misses the imprintRevised after a check by a second AI model, 2026-11-08.Earliest known: no earlier English print use turned up in full-text searches of the Internet Archive. The Japanese name's earliest known print use is new-game-plus-name-ja.
Cited by: New Game+
The earliest known print use of the mode's Japanese name is in the June 1995 issue of Micom Basic Magazine, which calls Chrono Trigger's mode 強くてニューゲーム (Tsuyokute New Game, "strong new game"). chrono-trigger/new-game-plus-name-ja
About: Chrono Trigger New Game+
Value: ja 強くてニューゲーム
MagazineマイコンBASICマガジン, June 1995 ·p. 149 (scan image 153), Final Stage, heading — by 板場利光 (Itaba Toshimitsu), in the writers' column "Final Stage"; the OCR misses the column, so the quotes are from the page image (page/n152.jpg)「強くてニューゲーム」で遊ぼうOur translationLet's play "Tsuyokute New Game"マイコンBASICマガジン, June 1995 · p. 149 (scan image 153), Final Stage, first paragraph知っている人も多いと思うが,『クロノ・トリガー』には「強くてニューゲーム」というモードがある。Our translationMany will know this, but Chrono Trigger has a mode called "Tsuyokute New Game".Checked by claude, 2026-11-08 — read p. 149 on the page image (page/n152.jpg); the Internet Archive's OCR misses the columnRevised after a check by a second AI model, 2026-11-08.Earliest known: no earlier print use turned up in full-text searches of the Internet Archive, the 1995 issues of Micom Basic Magazine and the September to December 1995 issues of Weekly Famitsu held there. The Japanese guidebooks of the time, which could be earlier, have not been found as scans (new-game-plus-name-japan).
Cited by: New Game+
The Japanese release's own label for New Game+, and the name the Japanese guidebooks of the time print, haven't been read: only the USA cartridge has been run, and no Japanese guidebook of the time has been found as a scan. chrono-trigger/new-game-plus-name-japan
About: Chrono Trigger New Game+
UnsourcedRevised after a check by a second AI model, 2026-11-08.Which ending plays is decided in the event scripts, which the disassembly leaves as data; no code that branches on an ending was found in the disassembled banks. chrono-trigger/ending-choice
A damaging technique runs in four steps: the battle loads the technique's formula and defense-selector bytes, computes a magnitude by that formula, resolves the target's defense value, and applies it. Formulas 1, 2 and 4 first wake the target: if the target's status byte +$1E has bit $02 or $04 set, both are cleared and its turn counter restarts from its reload value. The defense step clears the same two bits for every formula, without the restart. chrono-trigger/damage-steps
About: Chrono Trigger Damage formula
Codect_disassembly: Chrono Trigger (US v1.0) disassembly ·bank_C1.asm#L26881-L26884+ JSR.W Battle_LoadFormulaDefStat ;C1D32C|20A4D1 |C1D1A4;
JSR.W Battle_DamageMagnitude ;C1D32F|20F5E0 |C1E0F5;
JSR.W Battle_ResolveStatOperand ;C1D332|205FE6 |C1E65F;
JSR.W Battle_ApplyDefenseReduction ;C1D335|20ADDC |C1DCAD;ct_disassembly: Chrono Trigger (US v1.0) disassembly · bank_C1.asm#L26680-L26688Battle_LoadFormulaDefStat: TDC ;C1D1A4|7B | ;
TAX ;C1D1A5|AA | ;
STX.B $16 ;C1D1A6|8616 |000016;
STX.B $18 ;C1D1A8|8618 |000018;
LDA.W ActTech_Formula ;C1D1AA|ADEBAE |7EAEEB;
STA.B $16 ;C1D1AD|8516 |000016;
LDA.W ActTech_DefStat ;C1D1AF|ADECAE |7EAEEC;
STA.B $18 ;C1D1B2|8518 |000018;
RTS ;C1D1B4|60 | ;Our readingthe technique's formula and defense-selector bytes26684–26687ct_disassembly: Chrono Trigger (US v1.0) disassembly · bank_C1.asm#L29266-L29282Battle_WakeTargetOnDamage: TDC ;C1E63B|7B | ;
LDX.W $B1F6 ;C1E63C|AEF6B1 |7EB1F6;
LDA.W BatWork_StatusCur1,X ;C1E63F|BD4B5E |7E5E4B;
BIT.B #$06 ;C1E642|8906 | ;
BEQ + ;C1E644|F018 |C1E65E;
AND.B #$F9 ;C1E646|
STA.W $5E4B,X ;C1E648|
TDC ;C1E64B|
LDA.W $B1FD ;C1E64C|
TAX ;C1E64F|
LDA.B #$01 ;C1E650|
STA.W $B03A,X ;C1E652|
…Our readingif the target's byte +$1E has bit $02 or $0429267–29270clear them and reload the turn counter29271–29279The defense value is one of two target bytes, as the technique's defense selector picks: $3E reads byte +$3E as is, $3C reads byte +$3C × 5 / 2 (the disassembly labels them Defense and Magic Defense). The target's statuses lower it: bit $02 or $80 of its byte +$1E multiplies it by 16/20 and skips the next three; otherwise each of bit $40, bits $05 and bit $20 multiplies it by 18/20. The low two bits n of the technique's property byte 8, when not 0, then scale it by n/4 (the disassembly's comment says only two property records set them and no player technique uses either), and the value is capped at 255. Damage is then magnitude × (256 − defense) / 256 plus the formula's bonus, and a result of 0 becomes 1. Code — the defense step's clear of the two bitsChecked by claude, 2026-11-08 — read the four calls (bank_C1.asm L26881-L26884), the loader (L26680-L26688) and the wake step (L29266-L29282)Revised after a check by a second AI model, 2026-11-08.Formula 1 sets the magnitude to power × (12 × the attacker's byte +$36 + 5 × its byte +$43) / 18, where power is the technique's power byte, and draws a random bonus from 0 to a third of byte +$36 (rounded down). The disassembly labels +$36 the live Power and +$43 a value computed when the battle loads. The bonus is added after the defense step, so defense does not reduce it. chrono-trigger/damage-physical
About: Chrono Trigger Damage formula
Codect_disassembly: Chrono Trigger (US v1.0) disassembly ·bank_C1.asm#L28591-L28660Battle_DamageMagnitude: TDC ;C1E0F5|7B | ; Compute base damage magnitude; dispatches on $16 = byte5 (a FORMULA SELECTOR, not raw power). Selector 1: magnitude = power(byte9 ActTech_Power) * (5*atkStat$5E70 + 12*atkStat$5E63) / 0x12, and a variance factor $B2BE = Battle_RandRange(atkStat$5E63/3 + 1). Selector 2 ($C1E184): magnitude from atkStat$5E67*8 + atkStat$5E70*8. Selector 3 = Battle_MagicDamage ($C1E203): power*(Level+Magic)*12/15. Selector 4 ($C1E276) = ENEMY PHYSICAL ATTACK: power*CurAttack*2/0x12 (see comment there). Selector 5+ -> $C1E2D3. Result magnitude -> $2C/$30, then JMP $C1E575 (applies the $B2BE variance) -> Battle_ApplyDefenseReduction.
LDA.B $16 ;C1E0F6|A516 |000016;
CMP.B #$01 ;C1E0F8|C901 | ;
BEQ + ;C1E0FA|F003 |C1E0FF;
JMP.W Battle_DmgMag_TrySel2 ;C1E0FC|4C84E1 |C1E184;
; | | ;
+ JSR.W Battle_WakeTargetOnDamage ;C1E0FF|203BE6 |C1E63B;
LDX.W $B1F4 ;C1E102|AEF4B1 |7EB1F4;
TDC ;C1E105|7B | ;
LDA.W BatWork_CurPower,X ;C1E106|BD635E |7E5E63;
TAX ;C1E109|AA | ;
STX.B $28 ;C1E10A|8628 |000028;
…Our readingformula 1 only28592–2859512 × byte +$3628600–28608plus 5 × byte +$4328610–28621times the technique's power28624–28635over 1828638–28642bonus: random 0 to (byte +$36 / 3)28645–28657keep the magnitude and go to the status step28658–28660ct_disassembly: Chrono Trigger (US v1.0) disassembly · battle_work.asm#L38-L48 — The disassembly's labels for the record bytes the statement names.BatWork_Calc43 = $5E70 ; +0x43 computed-on-load value used in the damage magnitude
; (x5 sel.1 / x8 sel.2 w/ currentPower); exact stat TBD
BatWork_CurPower = $5E63 ; +0x36 live Power
BatWork_CurStamina = $5E64 ; +0x37 live Stamina
BatWork_CurSpeed = $5E65 ; +0x38 live Speed
BatWork_CurMagic = $5E66 ; +0x39 live Magic
BatWork_CurHit = $5E67 ; +0x3A live Hit (accuracy)
BatWork_CurEvade = $5E68 ; +0x3B live Evade
BatWork_CurMagDef = $5E69 ; +0x3C live Magic Defense
BatWork_CurAttack = $5E6A ; +0x3D live Attack
BatWork_CurDefense = $5E6B ; +0x3E live DefenseChecked by claude, 2026-11-08 — read formula 1 (bank_C1.asm L28591-L28660) and the random-range routine it calls (L22060-L22105): with a low of 0 and a high of n + 1 it returns a table byte mod (n + 1)Revised after a check by a second AI model, 2026-11-08.Cited by: Damage formula
Formula 2 sets the magnitude to power × (8 × the attacker's byte +$3A + 8 × its byte +$43) / 18 and draws a random bonus from 0 to ⌊77 × byte +$3A / 256⌋, about 30% of it. The disassembly labels +$3A the live Hit. chrono-trigger/damage-hit-formula
About: Chrono Trigger Damage formula
Codect_disassembly: Chrono Trigger (US v1.0) disassembly ·bank_C1.asm#L28663-L28719Battle_DmgMag_TrySel2: CMP.B #$02 ;C1E184|C902 | ;
BNE + ;C1E186|D074 |C1E1FC;
JSR.W Battle_WakeTargetOnDamage ;C1E188|203BE6 |C1E63B;
LDX.W $B1F4 ;C1E18B|AEF4B1 |7EB1F4;
TDC ;C1E18E|7B | ;
LDA.W BatWork_CurHit,X ;C1E18F|BD675E |7E5E67;
TAX ;C1E192|AA | ;
STX.B $28 ;C1E193|8628 |000028;
LDA.B #$08 ;C1E195|A908 | ;
TAX ;C1E197|AA | ;
STX.B $2A ;C1E198|862A |00002A;
JSR.W Battle_Mul16 ;C1E19A|200BC9 |C1C90B;
…Our reading8 × byte +$3A plus 8 × byte +$4328668–28689times power, over 1828692–28708bonus: random 0 to 30% of byte +$3A28710–28718ct_disassembly: Chrono Trigger (US v1.0) disassembly · bank_C1.asm#L24221-L24259Battle_Mul30Percent: REP #$20 ;C1C063|C220 | ;
XBA ;C1C065|EB | ;
LSR A ;C1C066|4A | ;
TAY ;C1C067|A8 | ;
LSR A ;C1C068|4A | ;
LSR A ;C1C069|4A | ;
STA.B $08 ;C1C06A|8508 |000008;
TYA ;C1C06C|98 | ;
SEC ;C1C06D|38 | ;
SBC.B $08 ;C1C06E|E508 |000008;
TAY ;C1C070|A8 | ;
LDA.B $08 ;C1C071|A508 |000008;
…ct_disassembly: Chrono Trigger (US v1.0) disassembly · battle_work.asm#L38-L48 — The disassembly's labels for the record bytes the statement names.BatWork_Calc43 = $5E70 ; +0x43 computed-on-load value used in the damage magnitude
; (x5 sel.1 / x8 sel.2 w/ currentPower); exact stat TBD
BatWork_CurPower = $5E63 ; +0x36 live Power
BatWork_CurStamina = $5E64 ; +0x37 live Stamina
BatWork_CurSpeed = $5E65 ; +0x38 live Speed
BatWork_CurMagic = $5E66 ; +0x39 live Magic
BatWork_CurHit = $5E67 ; +0x3A live Hit (accuracy)
BatWork_CurEvade = $5E68 ; +0x3B live Evade
BatWork_CurMagDef = $5E69 ; +0x3C live Magic Defense
BatWork_CurAttack = $5E6A ; +0x3D live Attack
BatWork_CurDefense = $5E6B ; +0x3E live DefenseChecked by claude, 2026-11-08 — read formula 2 (bank_C1.asm L28663-L28719) and the 30% step (L24221-L24259): from the stat s it subtracts s·256/8, /16, /128 and /256 from s·256/2, all exact, so 77s/256, and keeps the high byteRevised after a check by a second AI model, 2026-11-08.Formula 3 sets the magnitude to power × (12 × the attacker's byte +$12 + 12 × its byte +$39) / 15 and draws a random bonus from 0 to ⌊77 × byte +$39 / 256⌋. The disassembly labels +$12 the level and +$39 the live Magic. Unlike formulas 1, 2 and 4 it does not restart the target's turn counter. chrono-trigger/damage-magic
About: Chrono Trigger Damage formula
Codect_disassembly: Chrono Trigger (US v1.0) disassembly ·bank_C1.asm#L28721-L28780+ CMP.B #$03 ;C1E1FC|C903 | ;
BEQ Battle_MagicDamage ;C1E1FE|F003 |C1E203;
JMP.W Battle_DmgMag_TrySel4 ;C1E200|4C76E2 |C1E276;
; | | ;
Battle_MagicDamage: TDC ;C1E203|7B | ; Single-target magic damage (effect type 3): dmg = magicPower($7EAEEF) * (stat $7E5E3F + stat $7E5E66) * 0x0C / 0x0F, via Battle_Mul16/Battle_Div16; defense applied via $C1C063. Multi-target variant at $C1E276.
LDX.W $B1F4 ;C1E204|AEF4B1 |7EB1F4;
LDA.W BatWork_Level,X ;C1E207|BD3F5E |7E5E3F;
TAX ;C1E20A|AA | ;
STX.B $28 ;C1E20B|8628 |000028;
LDA.B #$0C ;C1E20D|A90C | ;
TAX ;C1E20F|AA | ;
STX.B $2A ;C1E210|862A |00002A;
…Our readingformula 328721–2872212 × byte +$12 plus 12 × byte +$3928726–28749times power, over 1528752–28768bonus: random 0 to 30% of byte +$3928770–28779ct_disassembly: Chrono Trigger (US v1.0) disassembly · battle_work.asm#L38-L48 — The disassembly's labels for the record bytes the statement names.BatWork_Calc43 = $5E70 ; +0x43 computed-on-load value used in the damage magnitude
; (x5 sel.1 / x8 sel.2 w/ currentPower); exact stat TBD
BatWork_CurPower = $5E63 ; +0x36 live Power
BatWork_CurStamina = $5E64 ; +0x37 live Stamina
BatWork_CurSpeed = $5E65 ; +0x38 live Speed
BatWork_CurMagic = $5E66 ; +0x39 live Magic
BatWork_CurHit = $5E67 ; +0x3A live Hit (accuracy)
BatWork_CurEvade = $5E68 ; +0x3B live Evade
BatWork_CurMagDef = $5E69 ; +0x3C live Magic Defense
BatWork_CurAttack = $5E6A ; +0x3D live Attack
BatWork_CurDefense = $5E6B ; +0x3E live Defensect_disassembly: Chrono Trigger (US v1.0) disassembly · battle_work.asm#L15-L15BatWork_Level = $5E3F ; +0x12 levelChecked by claude, 2026-11-08 — read the selector branch and formula 3 (bank_C1.asm L28721-L28780); it has no call to the wake step, the one that restarts the counterRevised after a check by a second AI model, 2026-11-08.Formula 4 sets the magnitude to power × 2 × the attacker's byte +$3D / 18 and draws a random bonus from 0 to one more than about a fifth of byte +$3D: (52s − ⌊s/2⌋ − ⌊s/4⌋) / 256, rounded down, for a stat s. The disassembly labels +$3D the live Attack and calls formula 4 the enemies' physical attack. chrono-trigger/damage-enemy
About: Chrono Trigger Damage formula
Codect_disassembly: Chrono Trigger (US v1.0) disassembly ·bank_C1.asm#L28787-L28830Battle_DmgMag_TrySel4: CMP.B #$04 ;C1E276|C904 | ;
BNE + ;C1E278|D059 |C1E2D3;
JSR.W Battle_WakeTargetOnDamage ;C1E27A|203BE6 |C1E63B;
TDC ;C1E27D|7B | ;
LDX.W $B1F4 ;C1E27E|AEF4B1 |7EB1F4;
LDA.W BatWork_CurAttack,X ;C1E281|BD6A5E |7E5E6A;
TAX ;C1E284|AA | ;
STX.B $28 ;C1E285|8628 |000028;
LDA.B #$02 ;C1E287|A902 | ;
TAX ;C1E289|AA | ;
STX.B $2A ;C1E28A|862A |00002A;
JSR.W Battle_Mul16 ;C1E28C|200BC9 |C1C90B;
…Our readingformula 428787–287882 × byte +$3D, times power, over 1828792–28818bonus: random 0 to (20% of byte +$3D) + 128820–28829ct_disassembly: Chrono Trigger (US v1.0) disassembly · bank_C1.asm#L24178-L24215Battle_Mul20Percent: REP #$20 ;C1C02A|C220 | ;
XBA ;C1C02C|EB | ;
LSR A ;C1C02D|4A | ;
LSR A ;C1C02E|4A | ;
TAY ;C1C02F|A8 | ;
LSR A ;C1C030|4A | ;
LSR A ;C1C031|4A | ;
LSR A ;C1C032|4A | ;
STA.B $08 ;C1C033|8508 |000008;
TYA ;C1C035|98 | ;
SEC ;C1C036|38 | ;
SBC.B $08 ;C1C037|E508 |000008;
…ct_disassembly: Chrono Trigger (US v1.0) disassembly · battle_work.asm#L38-L48 — The disassembly's labels for the record bytes the statement names.BatWork_Calc43 = $5E70 ; +0x43 computed-on-load value used in the damage magnitude
; (x5 sel.1 / x8 sel.2 w/ currentPower); exact stat TBD
BatWork_CurPower = $5E63 ; +0x36 live Power
BatWork_CurStamina = $5E64 ; +0x37 live Stamina
BatWork_CurSpeed = $5E65 ; +0x38 live Speed
BatWork_CurMagic = $5E66 ; +0x39 live Magic
BatWork_CurHit = $5E67 ; +0x3A live Hit (accuracy)
BatWork_CurEvade = $5E68 ; +0x3B live Evade
BatWork_CurMagDef = $5E69 ; +0x3C live Magic Defense
BatWork_CurAttack = $5E6A ; +0x3D live Attack
BatWork_CurDefense = $5E6B ; +0x3E live DefenseChecked by claude, 2026-11-08 — read formula 4 (bank_C1.asm L28787-L28830) and the 20% step (L24178-L24215): from s·256/4 it subtracts s·256/32 and /64 (exact) and ⌊s/2⌋ and ⌊s/4⌋ (the shifts drop bits), then keeps the high byte; the range is RandRange(0, that + 2)Revised after a check by a second AI model, 2026-11-08.After the formula, the attacker's statuses scale the magnitude. Bits of its bytes +$21 and +$26 (ORed) are tested in order and only the first that is set applies: $80 multiplies by 1.5 and skips everything else, $08 halves and then triples, $02 quarters and then multiplies by 5. Then each set bit of its byte +$1E applies in turn: $40 multiplies by 8/10, $20 by 8/10, and $04 divides by 4. The bonus drawn by the formula is not scaled. chrono-trigger/damage-attacker-status
About: Chrono Trigger Damage formula
Codect_disassembly: Chrono Trigger (US v1.0) disassembly ·bank_C1.asm#L29170-L29263Battle_ApplyAttackerStatusDmgMods: LDX.W $B1F4 ;C1E575|AEF4B1 |7EB1F4;
LDA.W !PC1HasProtectStatus,X ;C1E578|BD4E5E |7E5E4E;
ORA.W !PC1HasProtectShield,X ;C1E57B|1D535E |7E5E53;
BIT.B #$80 ;C1E57E|8980 | ;
BEQ + ;C1E580|F010 |C1E592;
REP #$20 ;C1E582|
LDA.B $2C ;C1E584|
LSR ;C1E586|
CLC ;C1E587|
ADC.B $2C ;C1E588|
STA.B $2C ;C1E58A|
TDC ;C1E58C|
…Our readingbit $80 of +$21|+$26: × 1.5, then straight to the end29171–29183else bit $08: ÷ 2 × 329185–29199else bit $02: ÷ 4 × 529201–29214+$1E bit $40: × 8 ÷ 1029217–29230+$1E bit $20: × 8 ÷ 1029232–29245+$1E bit $04: ÷ 429247–29255pass the magnitude on29257–29263Checked by claude, 2026-11-08 — read the status step (bank_C1.asm L29170-L29263), which scales only the magnitudeChecked by a second AI model, 2026-11-08.The defense value is one of two target bytes, as the technique's defense selector picks: $3E reads byte +$3E as is, $3C reads byte +$3C × 5 / 2 (the disassembly labels them Defense and Magic Defense). The target's statuses lower it: bit $02 or $80 of its byte +$1E multiplies it by 16/20 and skips the next three; otherwise each of bit $40, bits $05 and bit $20 multiplies it by 18/20. The low two bits n of the technique's property byte 8, when not 0, then scale it by n/4 (the disassembly's comment says only two property records set them and no player technique uses either), and the value is capped at 255. Damage is then magnitude × (256 − defense) / 256 plus the formula's bonus, and a result of 0 becomes 1. chrono-trigger/damage-defense
About: Chrono Trigger Damage formula
Value: defense from 256 · defense cap 255 · minimum 1
Codect_disassembly: Chrono Trigger (US v1.0) disassembly ·bank_C1.asm#L29284-L29319Battle_ResolveStatOperand: LDA.B $18 ;C1E65F|A518 |000018; Resolve + modify the TARGET DEFENSE operand $18. (1) If $18 (TechProperty byte6) is a stat-index sentinel 0x3E/0x3C, replace it with the target's actual stat at $5E2D + $B1F6 + $18 (byte6 selects which defense stat); else literal. (2) Apply TARGET-STATUS defense modifiers from StatusCur1 ($5E4B): bits 0x80/0x02 (Stop/Sleep) -> def x16/20 (0.8); bit 0x40 (Poison) / bits 0x04+0x01 (Confused+Blind) / bit 0x20 -> def x18/20 (0.9) -- i.e. ailing targets defend worse. (3) byte8 DEFENSE-PIERCE (C1E748): if ActTech_Byte8 & 3 != 0 -> def = def*(byte8&3)/4; only property records 0x45/0x47 set this and NO player tech references them, so it is dormant for player techs (likely enemy-attack records). (4) Clamp def to 0xFF. Result $18 feeds Battle_ApplyDefenseReduction (dmg = magnitude*(256-def)/256).
CMP.B #$3E ;C1E661|C93E | ;
BNE + ;C1E663|D013 |C1E678;
REP #$20 ;C1E665|C220 | ;
LDA.B $18 ;C1E667|A518 |000018;
CLC ;C1E669|18 | ;
ADC.W $B1F6 ;C1E66A|6DF6B1 |7EB1F6;
TAX ;C1E66D|AA | ;
TDC ;C1E66E|7B | ;
SEP #$20 ;C1E66F|E220 | ;
LDA.W !PC1Portrait,X ;C1E671|BD2D5E |7E5E2D;
STA.B $18 ;C1E674|8518 |000018;
…Our readingselector $3E: the target's byte +$3E29285–29296selector $3C: the target's byte +$3C × 5 ÷ 229297–29319ct_disassembly: Chrono Trigger (US v1.0) disassembly · bank_C1.asm#L29320-L29339STX.B $18 ;C1E6A7|8618 |000018;
; | | ;
++ LDX.W $B1F6 ;C1E6A9|AEF6B1 |7EB1F6;
LDA.W BatWork_StatusCur1,X ;C1E6AC|BD4B5E |7E5E4B;
STA.B $0E ;C1E6AF|850E |00000E;
AND.B #$82 ;C1E6B1|2982 | ;
BEQ + ;C1E6B3|F020 |C1E6D5;
TDC ;C1E6B5|7B | ; status Stop/Sleep (0x82): $18(def) = def * 16/20 (x0.8)
LDA.B $18 ;C1E6B6|A518 |000018;
TAX ;C1E6B8|AA | ;
STX.B $28 ;C1E6B9|8628 |000028;
LDX.W #$0010 ;C1E6BB|A21000 | ;
…Our readingtarget +$1E bits $82: × 16 ÷ 20, skip the next checks29321–29339ct_disassembly: Chrono Trigger (US v1.0) disassembly · bank_C1.asm#L29343-L29423+ LDA.B $0E ;C1E6D5|A50E |00000E;
AND.B #$40 ;C1E6D7|2940 | ;
BEQ + ;C1E6D9|F01E |C1E6F9;
TDC ;C1E6DB|7B | ; status Poison (0x40): $18(def) = def * 18/20 (x0.9)
LDA.B $18 ;C1E6DC|A518 |000018;
TAX ;C1E6DE|AA | ;
STX.B $28 ;C1E6DF|8628 |000028;
LDX.W #$0012 ;C1E6E1|A21200 | ;
STX.B $2A ;C1E6E4|862A |00002A;
JSR.W Battle_Mul16 ;C1E6E6|200BC9 |C1C90B;
LDX.B $2C ;C1E6E9|A62C |00002C;
STX.B $28 ;C1E6EB|8628 |000028;
…Our readingbit $40: × 18 ÷ 2029343–29359bits $05: × 18 ÷ 2029361–29377bit $20: × 18 ÷ 2029379–29395low two bits n of property byte 8: × n ÷ 429398–29411cap at 25529415–29421ct_disassembly: Chrono Trigger (US v1.0) disassembly · bank_C1.asm#L28032-L28065Battle_ApplyDefenseReduction: TDC ;C1DCAD|7B | ; Final damage step: $AD89 = $16 * (256 - $18) / 256, i.e. base magnitude $16 reduced by the defense fraction $18 (0-255). Also clears target status bits 0x06 ($5E4B[tgt] &= 0xF9).
LDX.W $B1F6 ;C1DCAE|AEF6B1 |7EB1F6;
LDA.W BatWork_StatusCur1,X ;C1DCB1|BD4B5E |7E5E4B;
AND.B #$F9 ;C1DCB4|29F9 | ;
STA.W BatWork_StatusCur1,X ;C1DCB6|9D4B5E |7E5E4B;
REP #$20 ;C1DCB9|C220 | ;
LDA.W #$0100 ;C1DCBB|A90001 | ;
SEC ;C1DCBE|38 | ;
SBC.B $18 ;C1DCBF|E518 |000018;
SEP #$20 ;C1DCC1|E220 | ;
TAX ;C1DCC3|AA | ;
STX.B $28 ;C1DCC4|8628 |000028;
…Our readingclear the target's +$1E bits $02 and $0428033–28036magnitude × (256 − defense) ÷ 25628037–28054plus the bonus28055–280590 becomes 128062–28065ct_disassembly: Chrono Trigger (US v1.0) disassembly · battle_work.asm#L38-L48 — The disassembly's labels for the record bytes the statement names.BatWork_Calc43 = $5E70 ; +0x43 computed-on-load value used in the damage magnitude
; (x5 sel.1 / x8 sel.2 w/ currentPower); exact stat TBD
BatWork_CurPower = $5E63 ; +0x36 live Power
BatWork_CurStamina = $5E64 ; +0x37 live Stamina
BatWork_CurSpeed = $5E65 ; +0x38 live Speed
BatWork_CurMagic = $5E66 ; +0x39 live Magic
BatWork_CurHit = $5E67 ; +0x3A live Hit (accuracy)
BatWork_CurEvade = $5E68 ; +0x3B live Evade
BatWork_CurMagDef = $5E69 ; +0x3C live Magic Defense
BatWork_CurAttack = $5E6A ; +0x3D live Attack
BatWork_CurDefense = $5E6B ; +0x3E live Defensect_disassembly: Chrono Trigger (US v1.0) disassembly · battle_work.asm#L71-L75 — The disassembly's comment on property byte 8, latched to $7E:AE4E.ActTech_Byte8 = $AEEE ; byte8 -> $AE4E (via Battle_LatchTechBytes7and8). LOW 2 BITS = a DEFENSE-PIERCE
; multiplier: in Battle_ResolveStatOperand (C1E741) if byte8&3 != 0
; the target defense $18 = def*(byte8&3)/4. Only property records
; 0x45/0x47 set it ($3E=x0.5, $01=x0.25) and NO player tech uses
; those records -> dormant for players (enemy-attack records).Checked by claude, 2026-11-08 — read the resolver (bank_C1.asm L29284-L29423) and the defense step (L28032-L28065); the bonus byte is added after the multiply and divideRevised after a check by a second AI model, 2026-11-08.Cited by: Damage formula
The battle's random draws come from a table read in sequence, by an index that wraps after 256: a draw from low to high returns low + the next table byte mod (high − low), then moves the index on. It returns high unchanged when low is $FF, high is 0, or high equals low, and the raw table byte, without moving on, when high − low is $FF. When bit $20 of the battle-settings byte that the start-battle event command writes is set, every draw returns low, except when low is $FF, so the formulas add no bonus. chrono-trigger/battle-random-range
About: Chrono Trigger Damage formula
Codect_disassembly: Chrono Trigger (US v1.0) disassembly ·bank_C1.asm#L22060-L22105Battle_RandRange: SEP #$10 ;C1AF22|E210 | ; Battle RNG: A = range -> returns a pseudo-random sample for that range (from the $2989 battle seed; bit 0x20 selects a mode). The shared roll for hit checks (vs 100), damage variance, heal variance, status chance, etc. (24 callers).
STX.B $25 ;C1AF24|8625 |000025;
REP #$10 ;C1AF26|C210 | ;
LDX.B $2C ;C1AF28|A62C |00002C;
PHX ;C1AF2A|DA | ;
SEP #$10 ;C1AF2B|E210 | ;
LDX.B $25 ;C1AF2D|A625 |000025;
CPX.B #$FF ;C1AF2F|E0FF | ;
BNE + ;C1AF31|D002 |C1AF35;
BRA _LAF73 ;C1AF33|
; | | ;
+ STA.W !CriticalHitChance ;C1AF35|8D1EB3 |7EB31E;
…Our readinglow is $FF: return high22066–22069settings bit $20: return low22072–22076high is 0 or equals low: return high22078–22082range $FF: the raw table byte22083–22089else low + table byte mod range, next index22091–22101ct_disassembly: Chrono Trigger (US v1.0) disassembly · bank_C1.asm#L25503-L25533Battle_Div16: PHP ;C1C92A|08 | ; 16-bit divide: $28 / $2A -> quotient $2C, remainder $32 (shift-subtract, 32 iters).
REP #$30 ;C1C92B|C230 | ;
STZ.B $2C ;C1C92D|642C |00002C;
STZ.B $32 ;C1C92F|6432 |000032;
LDA.B $28 ;C1C931|A528 |000028;
BEQ + ;C1C933|F022 |C1C957;
LDA.B $2A ;C1C935|A52A |00002A;
BEQ + ;C1C937|F01E |C1C957;
LDX.W #$0020 ;C1C939|A22000 | ;
; | | ;
- ROL.B $28 ;C1C93C|2628 |000028;
ROL.B $2E ;C1C93E|262E |00002E;
…Our readingthe remainder ends in $3225506–25523A battle starts from an event script: command $D8 takes two bytes, stores them as the battle's two settings bytes and raises the field's battle request. The script stays on the command until the field marks the battle done, then clears that mark and moves past the command's three bytes. Code — the command writes the settings byteChecked by claude, 2026-11-08 — read the routine (bank_C1.asm L22060-L22105) and the divide it calls (L25503-L25533), whose remainder is the value added to low; the settings byte is the one the start-battle command stores (bank_C0.asm L7713-L7714)Revised after a check by a second AI model, 2026-11-08.When its damage modification runs (a flag can skip it) and the attack doesn't ignore defense, Final Fantasy VI multiplies damage by a random 224–255 (computed: a random byte ORed with $E0) over 256, adding 1, and then by 255 minus the target's Defense or Magic Defense over 256, adding 1, so defense also scales the random part; on one path the second factor is a fixed $3F (computed) in place of the defense. Chrono Trigger multiplies its magnitude by 256 minus the defense over 256 and adds a separately drawn bonus afterwards, which defense does not reduce. chrono-trigger/damage-changes-ff6
About: Chrono Trigger Damage formula
CodeFinal Fantasy VI Disassembly ·src/battle/calc_dmg.asm#L153-L193; [ calculate damage modification ]
; random variance, defense stat, shell/safe, defending, row, morph, friendly fire
CalcDmgMod:
@0c9e: php
longa
lda $11b0 ; damage
sta $f0
shorta
lda near w7e3414
jeq @0d3b
jsr Rand
ora #$e0 ; random variance (240..255)
…Our readingskipped when the flag is 0163–164random byte ORed with $E0, multiply165–168an attack flag skips the defense multiply174–176Defense or Magic Defense: 255 − it, or $3F on one path177–193Final Fantasy VI Disassembly · src/battle/calc_dmg.asm#L239-L248; [ multiply damage by fraction ($e8 / 255) ]
MultDmg:
@0d3d: php
longa
lda $f0
jsr Mult24
inc
sta $f0
plpOur readingmultiply, then add 1243–247Final Fantasy VI Disassembly · src/battle/math.asm#L41-L45; [ +a *= $e8 / 256 ]
; ++$e8 = +a * $e8
Mult24:ct_disassembly: Chrono Trigger (US v1.0) disassembly · bank_C1.asm#L28037-L28059REP #$20 ;C1DCB9|C220 | ;
LDA.W #$0100 ;C1DCBB|A90001 | ;
SEC ;C1DCBE|38 | ;
SBC.B $18 ;C1DCBF|E518 |000018;
SEP #$20 ;C1DCC1|E220 | ;
TAX ;C1DCC3|AA | ;
STX.B $28 ;C1DCC4|8628 |000028;
LDX.B $16 ;C1DCC6|A616 |000016;
STX.B $2A ;C1DCC8|862A |00002A;
JSR.W Battle_Mul16 ;C1DCCA|200BC9 |C1C90B;
LDX.B $2C ;C1DCCD|A62C |00002C;
STX.B $28 ;C1DCCF|8628 |000028;
…Our readingmagnitude × (256 − defense) ÷ 25628037–28054plus the bonus28055–28059Checked by claude, 2026-11-08 — read FF6's damage modification and its multiply (calc_dmg.asm L153-L193, L239-L248; math.asm L41-L45) and Chrono Trigger's defense step (bank_C1.asm L28037-L28059)Revised after a check by a second AI model, 2026-11-08.Cited by: Damage formula
At the start of a battle each party member's and enemy's turn counter is set to 105 − 6s plus an entry of a 128-byte table in 8-bit arithmetic, where s is its byte +$38 (capped at 16, and the cap written back) and the battle-speed setting's index k, 0 to 7, picks a row of 16 entries. Computed over all 128 entries, that is (k + 2) × (25 − s): from 216 at index 7 and speed 1 down to 18 at index 0 and speed 16. The same value is kept as the unit's reload value. An enemy whose counter is 0 acts when a per-unit status byte is 0, 4, 6 or $0A to $10 (any other value needs a flag at $9826 set, which acting clears) and a flag at $B247 is clear; its counter is then set back to the reload value and adjusted for status. The disassembly labels byte +$38 the live Speed. chrono-trigger/atb-start-counter
About: Chrono Trigger Active Time Battle
Value: min 18 · max 216 · speed cap 16
Codect_disassembly: Chrono Trigger (US v1.0) disassembly ·bank_FD.asm#L2161-L2213- LDX.B $02 ;FDB7EF|A602 |000002;
LDA.W !PC1IndexDeadIf,X ;FDB7F1|BDFFAE |7EAEFF;
CMP.B #$FF ;FDB7F4|C9FF | ;
BEQ + ;FDB7F6|F063 |FDB85B;
REP #$20 ;FDB7F8|C220 | ;
TXA ;FDB7FA|8A | ;
ASL A ;FDB7FB|0A | ;
TAX ;FDB7FC|AA | ;
LDA.L PointersStartAddressesRAMCopy,X ;FDB7FD|BF0BA8FD|FDA80B;
TAX ;FDB801|AA | ;
STX.B $04 ;FDB802|8604 |000004;
TDC ;FDB804|7B | ;
…Our readingfor each party member present2161–2164cap byte +$38 at 162174–2178table entry (setting index & 7) × 16 + speed − 12181–2195$69 − 6 × speed + entry: start and reload value2196–2211ct_disassembly: Chrono Trigger (US v1.0) disassembly · bank_FD.asm#L2236-L2282LDA.W $0038,X ;FDB87F|BD3800 |7E0038;
CMP.B #$10 ;FDB882|C910 | ;
BCC ++ ;FDB884|9005 |FDB88B;
LDA.B #$10 ;FDB886|A910 | ;
STA.W $0038,X ;FDB888|9D3800 |7E0038;
; | | ;
++ TDC ;FDB88B|7B | ;
LDA.W !BattleSpeedIndex1 ;FDB88C|AD9029 |7E2990;
AND.B #$07 ;FDB88F|2907 | ;
TAX ;FDB891|AA | ;
STX.B $28 ;FDB892|8628 |000028;
LDX.W #$0010 ;FDB894|A21000 | ;
…Our readingthe same for each enemy2236–2282Chrono Trigger (USA) · 0xc2e31-0xc2eb0 — $CC:2E31, the 128-byte start-counter table: 8 settings × 16 speeds.ct_disassembly: Chrono Trigger (US v1.0) disassembly · bank_C1.asm#L16583-L16626LDA.W $B163,X ;C1848B|BD63B1 |7EB163;
TAX ;C1848E|AA | ;
STX.B $22 ;C1848F|8622 |000022;
CMP.B #$03 ;C18491|C903 | ;
BCC + ;C18493|907C |C18511;
LDX.B $22 ;C18495|A622 |000022;
LDA.W !PC1IndexDeadIf,X ;C18497|BDFFAE |7EAEFF;
CMP.B #$FF ;C1849A|C9FF | ;
BEQ ++ ;C1849C|F04E |C184EC;
LDA.W !Character1AttackBar,X ;C1849E|BDABAF |7EAFAB;
BNE ++ ;C184A1|D049 |C184EC;
LDA.W !PC1HasStopStatus,X ;C184A3|BD0A5E |7E5E0A;
…Our readingan enemy unit (index 3 or more) that is alive16583–16591whose counter is 016592–16593and whose status byte is 0, 4, 6 or $0A-$10, or the flag at $9826 is set16594–16608and the flag at $B247 is clear16609–16610acts16615–16619and its counter is set back to the reload value16620–16622and adjusted for status16623ct_disassembly: Chrono Trigger (US v1.0) disassembly · battle_work.asm#L38-L48 — The disassembly's labels for the record bytes the statement names.BatWork_Calc43 = $5E70 ; +0x43 computed-on-load value used in the damage magnitude
; (x5 sel.1 / x8 sel.2 w/ currentPower); exact stat TBD
BatWork_CurPower = $5E63 ; +0x36 live Power
BatWork_CurStamina = $5E64 ; +0x37 live Stamina
BatWork_CurSpeed = $5E65 ; +0x38 live Speed
BatWork_CurMagic = $5E66 ; +0x39 live Magic
BatWork_CurHit = $5E67 ; +0x3A live Hit (accuracy)
BatWork_CurEvade = $5E68 ; +0x3B live Evade
BatWork_CurMagDef = $5E69 ; +0x3C live Magic Defense
BatWork_CurAttack = $5E6A ; +0x3D live Attack
BatWork_CurDefense = $5E6B ; +0x3E live DefenseTwo statuses change a unit's turn counter when it is reloaded after an action and when the unit is woken by damage: bit $80 of its byte +$20 or +$25 halves the counter, and bit $20 of its byte +$1E doubles it, to at most 255. A counter left at 0 becomes 1. Code — the status adjustment after the reloadChecked by claude, 2026-11-08 — read the start-of-battle routine (bank_FD.asm L2157-L2290) and the enemy turn check (bank_C1.asm L16583-L16626); a script checked that (105 − 6s + table[16k + s − 1]) mod 256 equals (k + 2)(25 − s) for all 128 entries of ROM $CC:2E31, with the minimum 18 and maximum 216Revised after a check by a second AI model, 2026-11-08.Two statuses change a unit's turn counter when it is reloaded after an action and when the unit is woken by damage: bit $80 of its byte +$20 or +$25 halves the counter, and bit $20 of its byte +$1E doubles it, to at most 255. A counter left at 0 becomes 1. chrono-trigger/atb-status-rate
About: Chrono Trigger Active Time Battle
Codect_disassembly: Chrono Trigger (US v1.0) disassembly ·bank_C1.asm#L23825-L23861Battle_AdjustAtbRateForStatus: REP #$20 ;C1BD6F|C220 | ;
TXA ;C1BD71|8A | ;
XBA ;C1BD72|EB | ;
LSR A ;C1BD73|4A | ;
TAY ;C1BD74|A8 | ;
TDC ;C1BD75|7B | ;
SEP #$20 ;C1BD76|E220 | ;
LDA.W BatWork_StatusCur3,Y ;C1BD78|B94D5E |7E5E4D;
ORA.W BatWork_StatusPerm3,Y ;C1BD7B|19525E |7E5E52;
BIT.B #$80 ;C1BD7E|8980 | ;
BEQ + ;C1BD80|F007 |C1BD89;
LDA.W $AFAB,X ;C1BD82|
…Our reading+$20|+$25 bit $80: halve the counter23832–23838+$1E bit $20: double it, at most 25523840–238480 becomes 123850–23853Checked by claude, 2026-11-08 — read the adjustment (bank_C1.asm L23825-L23861) and its calls after the enemy reload (L16623) and the wake step (L29280)Checked by a second AI model, 2026-11-08.How the Wait and Active settings differ is not traced: the code that counts the turn counters down was not found. chrono-trigger/atb-wait-active
About: Chrono Trigger Active Time Battle
UnsourcedChecked by a second AI model, 2026-11-08.A battle starts from an event script: command $D8 takes two bytes, stores them as the battle's two settings bytes and raises the field's battle request. The script stays on the command until the field marks the battle done, then clears that mark and moves past the command's three bytes. chrono-trigger/battle-start-command
bank_C0.asm#L12693-L12693dw EventCmd_StartBattle,EventCmd_OpD9,EventCmd_OpDA,EventCmd_Nop ;C05F1E| | opcodes D8-DB;Our readingopcode $D8 is the start-battle command12693ct_disassembly: Chrono Trigger (US v1.0) disassembly · bank_C0.asm#L7704-L7734EventCmd_StartBattle:
LDA.B $17 ;C03A83|A517 |000117;
BIT.B #$01 ;C03A85|8901 | ;
BNE + ;C03A87|D021 |C03AAA;
LDA.B $18 ;C03A89|A518 |000118;
BIT.B #$01 ;C03A8B|8901 | ;
BNE ++ ;C03A8D|D01E |C03AAD;
TYX ;C03A8F|BB | ;
INX ;C03A90|E8 | ;
LDA.L $7F2001,X ;C03A91|BF01207F|7F2001;
STA.L !EventCommandD8Settings ;C03A95|8F89297E|7E2989;
INX ;C03A99|E8 | ;
…Our readinga request already raised: stay on the command7705–7707the battle done: go to the end7708–7710store the two bytes7711–7717raise the request7718–7720clear the done mark, move past three bytes7727–7734Checked by claude, 2026-11-08 — read the command (bank_C0.asm L7704-L7734) and its entry in the event command table (L12693)Revised after a check by a second AI model, 2026-11-08.Whether any map rolls battles at random is not traced; the battles found start from event scripts. chrono-trigger/random-encounters
About: Chrono Trigger Visible encounter
UnsourcedChecked by a second AI model, 2026-11-08.Cited by: Random encounter, Visible encounter
The rules for running from a battle are not traced. chrono-trigger/escape
About: Chrono Trigger Fleeing
UnsourcedChecked by a second AI model, 2026-11-08.How a technique's area of effect picks its targets is not traced. chrono-trigger/technique-area
The critical-hit rule is not traced. chrono-trigger/critical-hit
About: Chrono Trigger Critical hit
UnsourcedChecked by a second AI model, 2026-11-08.How the battle decides that an attack hits or misses is not traced. chrono-trigger/hit-evade
About: Chrono Trigger Hit chance
UnsourcedChecked by a second AI model, 2026-11-08.For attacks whose effect runs the element step, an attack has at most one element: the first of bits $80, $40, $20 and $10 set in its element byte picks one of four (the disassembly calls them Lightning, Shadow, Water and Fire), and with none set the damage is left alone. The target's resistance byte for that element, at +$3F to +$42 of its record, sets the damage to damage × 4 / d, where d is the byte's low six bits, less 2 when bit $40 is set; so 4 leaves damage as it is, 2 doubles it, 8 halves it, and 0 makes it 0 (the divide returns 0 for a divisor of 0). Bit $80 of the byte sets a flag whose use is not traced. chrono-trigger/elements
About: Chrono Trigger Elemental weakness
Codect_disassembly: Chrono Trigger (US v1.0) disassembly ·bank_C1.asm#L30487-L30556TechFx_ElemResistOnly: TDC ;C1EF39|7B | ;
; | | ;
Battle_ApplyElemResist: LDA.W $B190 ;C1EF3A|AD90B1 |7EB190; Elemental resistance. ENTRY: reached ONLY via the byte8 TechFxHandler dispatch -- handler 10 (C1EF39 = TDC + fall-through here) or handler 11 (C1EFBC, after the damage multiplier). No direct callers, so a tech gets elemental resistance ONLY if its byte8 selects handler 10/11 (elemental techs); physical combos (handler 2) skip it. A = attack element $7EB190. Despite looking like a bitmask, the consumer is a PRIORITY CASCADE, not a multi-bit test: BIT #$80 Lightning(idx0) / #$40 Shadow(idx1) / #$20 Water(idx2) / #$10 Fire(idx3), and the FIRST set bit branches straight out -- only the HIGHEST set bit is honored, lower bits are ignored. So an attack has exactly ONE element (the field is effectively a priority-encoded enum Lightning>Shadow>Water>Fire; a multi-element value like $30 = Water|Fire resolves to Water only). Only the high nibble selects element. The low nibble is an attack-CLASS tag (0x00 support/no-damage incl. heals, 0x02 magical/elemental damage, 0x04 physical damage -- mutually exclusive; e.g. Antipode $42 = Shadow + magical). It is maintained consistently across the whole table but is INERT at runtime: byte3's ONLY consumer in the ROM is this load -> $B190, and the cascade tests only the high nibble (0x02/0x04/0x00 are all "no element" to it). Actual physical-vs-magical behavior comes from the property record, not this nibble. The chosen index reads target per-element defense $7E5E6C,x (x = target base $7EB1F6 + index) and scales damage once. Absorb/immune flag pass at $C1E575 (target flags $7E5E4E/$7E5E53).
STA.B $2C ;C1EF3D|852C |00002C;
BIT.B #$80 ;C1EF3F|8980 | ;
BEQ + ;C1EF41|F003 |C1EF46;
TDC ;C1EF43|7B | ;
BRA ++ ;C1EF44|8016 |C1EF5C;
; | | ;
+ BIT.B #$40 ;C1EF46|8940 | ;
BEQ + ;C1EF48|F004 |C1EF4E;
LDA.B #$01 ;C1EF4A|A901 | ;
…Our readingthe first set bit of $80, $40, $20, $10 picks element 0-330489–30508no bit: return unchanged30506–30507multiplier 4; the target's byte +$3F + element30510–30521bit $80: set a flag30522–30526low six bits, less 2 if bit $4030528–30537damage × 4 ÷ that30539–30552the step reached after a damage multiplier30555–30556ct_disassembly: Chrono Trigger (US v1.0) disassembly · bank_C1.asm#L25503-L25510Battle_Div16: PHP ;C1C92A|08 | ; 16-bit divide: $28 / $2A -> quotient $2C, remainder $32 (shift-subtract, 32 iters).
REP #$30 ;C1C92B|C230 | ;
STZ.B $2C ;C1C92D|642C |00002C;
STZ.B $32 ;C1C92F|6432 |000032;
LDA.B $28 ;C1C931|A528 |000028;
BEQ + ;C1C933|F022 |C1C957;
LDA.B $2A ;C1C935|A52A |00002A;
BEQ + ;C1C937|F01E |C1C957;Our readinga zero operand leaves the quotient 025505–25510Checked by claude, 2026-11-08 — read the element step (bank_C1.asm L30487-L30556) and the divide (L25503-L25533), which leaves the quotient at 0 when either operand is 0; the step's only direct call is after a damage multiplier (L30555-L30556)Revised after a check by a second AI model, 2026-11-08.