Devlog
Notes on the Chrono Trigger matching decompilation project, one post per working day. Written in plain English — if you don't know 65816 assembly, check the Glossary first.
16 October 2026: the credits, and a future that refused to change
The fifth and sixth batches of the packed $C3 module take it from half to 70%. The module is a block of code the game keeps compressed in the ROM and unpacks into RAM at $7E:3000 when it needs it; the jet-bike race was its first part to be matched. This batch is three of its smaller programs, each a scene of its own.
15 October 2026: how the sound driver reads a score
The third batch of the SPC700 sound driver is the part that plays the music: the pass that walks through every voice's track many times a second. With it the driver stood at two thirds of its 6,543 code bytes. The fourth batch, later the same day, took it the rest of the way: the whole driver is now built from source, and every one of its 177 routines and tables is verified.
14 October 2026: how much of the ROM is code? And bank $C1 is done
Every progress figure on this site divides the code matched so far by the amount of code in the game. Until today that second number, 358,356 bytes, came from a one-off survey done at the start. Now that whole banks are matched, it could be checked, and it was wrong by a third.
9 October 2026: event commands, battle effects, the dial and the menu threads
Two more batches went through review overnight: the second half of the field's event-script commands in $C0, and the part of the battle engine that resolves an action's targets and runs its effects in $C1. Together 10,245 bytes in 143 routines, all independently verified.
8 October 2026: who can you hit? The target modes
The code that answers "who does this action hit?" for the battle menu is matched: a 33-entry table of target modes and the eighteen small routines behind it, plus the routine that puts a character into the ready queue. 1,033 bytes in 26 functions (session 43).
24 September 2026: the cursor that draws itself
One big routine: BattleMenu_UpdateCursorOverlay, 828 bytes, the last stub in the command-menu neighborhood. Every frame, after input is processed, it decides what the pointing hand (or hands) on screen should look like, and where.
22 September 2026: the tech and item lists, and the command menu is closed
The input handling for the tech list and the item list is matched, the last two submenus still holding stubs. Every input handler in the battle command menu is now matched code. 637 bytes in 15 routines, the last two increments of session 41.
19 September 2026: the battle command menu, from dirty flag to committed action
The biggest single day so far: 1,478 bytes in 22 routines, all in bank $C1's battle command menu. It now runs as matched code from the gate that decides whether to redraw the menu, through controller input and confirm, to the 8-byte action record the battle engine executes. This is the first stretch of session 41, worked in eight increments.
14 August 2026: opening bank C1, from the math helpers to the battle windows
Bank $C1, the battle engine, is open. In one day it went from an empty file to 4,085 matched bytes: math and number formatting, the battle status bar and all its callees, the item and tech list renderers, and the per-frame window upkeep. 33 functions over sessions 34 to 40, plus a root-cause fix in the disassembler.
12 August 2026: the sprite-init system closes, and a first look at bank C1
The triple-slot routines, the dispatcher layer above the sprite-slot cluster and the animation queue that drives it are all matched, so the sprite system from $C98A to $E129 is one continuous run of matched code. Then a scouting pass over bank $C1, the battle engine. 3,509 new bytes in 10 functions (sessions 31 to 33).
11 August 2026: the sprite-slot cluster takes shape, and an honest progress number
Five body routines of the sprite-slot init cluster are matched, then the triple-slot dispatch. In between, the progress number gets a real denominator: matched code against the game's code, not against the whole 4 MB ROM. 2,377 new bytes in 7 functions (sessions 29 and 30).
10 August 2026: the animation-frame gate
One routine today, Sub_CB3A (162 bytes), the gate at the start of every sprite-slot init routine. Scoping around it corrected yesterday's picture of the call chain and mapped a new cluster at $CB3A–$D800.
9 August 2026: the Sub_E12A cluster closes, and the slot allocators
All six callees of Sub_E12A are matched in one pass, which completes the sprite init arc. Then the three sprite-slot allocators that sit just before it: 1,169 new bytes in 9 functions (sessions 26 and 27).
7 August 2026: the last mode handler, screen transitions, and the sprite init pass
The $0C76 mode dispatch is closed with the default handler. Then the whole screen-transition path, from fade-out through scene save and restore to fade-in, is matched, two early labels are corrected, and the 1,034-byte sprite init pass Sub_E12A goes in: 2,568 new bytes in 15 functions over sessions 21 to 25.
6 August 2026: the engine spine, the whole sprite system, and the mode handlers
The longest day so far, seventeen sessions (4 to 20) in bank $C0. The game loop and its per-frame reset are matched, then the complete sprite system, from the VBlank handler down to every renderer and init helper, then the head of the per-frame state machine and all five of its named mode handlers: 9,542 new bytes in 32 functions.
31 July 2026: MainInit, the hardware setup
MainInit at $FD:C000 is matched: the 215 bytes the SNES runs right after the reset stub to put the hardware into a known state. The project now stands at 471 matched bytes.
25 July 2026: a disassembler and the first bank sweeps
No new matches today. Instead the project got the tools it needs to scale: a recursive-descent disassembler, sweeps of banks $00, $01 and $02, CI, a pre-commit hook, progress tracking and a hardware register include file.
20 July 2026: setting up, and the last page of bank $00
The project starts. I set up the build, found the reset vector, and matched the whole last page of bank $00: 256 bytes of boot stubs, tables, ROM header and vectors.