Contributing
The code repo's own CONTRIBUTING.md, STYLE.md and REVIEW.md are the rules; this page is a
summary of how the work goes.
Ways to help
- Bank mapping: identifying what lives where in ROM, even roughly, before anything is matched.
- Function matching: draft, make readable, gate, review (below).
- Review: checking routines someone else matched, so they reach
verified. - Tooling: diffing, cross-references, progress tracking, CI.
- Data and graphics cataloguing: identifying compressed blobs, tile data and their formats (separate from code matching, but needed eventually).
Ground rules
- No ROM data, headers or extracted assets in commits. Ever. Tools and source only.
- Matched, readable and reviewed, or not on
main. A literal transcription of the disassembly is fine on a work branch, never onmain. - Byte-exact means byte-exact. A routine that "looks equivalent" but doesn't reassemble identically isn't matched.
- Say how you know. A name or meaning that is inferred says so, and from what ("inferred:
only written by the revive path"); an unknown one stays an
Unkname or is hedged ("probably"). Community documents and other disassemblies are leads, not evidence. - Keep the original's quirks. Dead code, a redundant instruction, an apparent bug: kept, named and documented, never "fixed".
- No generated numbers in docs. Counts and percentages come from
tools/progress.py; never type one by hand, and never commitsymbols/functions.csvorsymbols/progress.json. - One pull request per logical unit: a cluster of routines, a tooling change. Bring a branch
up to date by merging
main, never by rebasing.
The workflow
- Pick the next target from the code repo's
NEXT.md. - Draft it:
make draft ADDR=C1:3714(tools/draft.py) disassembles the routine, tracking M/X, DP and DB, and writes asar source with a header skeleton and every operand the project already has a name for, then checks it assembles to the original bytes.make xref ADDR=...(tools/xref.py) lists every call or jump to an address. - Make it readable (
STYLE.md): named RAM (asm/include/ram_*.inc), structs, calls and constants; explicit.b/.w/.lwidths (see asar Quirks); no hand-encoded opcodes; a header with what the routine is for and its CPU state on entry and exit (M, X, DP, DB). Calls into unmatched code go through label-only stubs inasm/include/unmatched*.asm. - Generate the Callers blocks:
python3 tools/callers.py --updaterewrites the; Callersblock of every header fromtools/xref.py's confirmed call sites. The block is generated, not reviewed, and left out of the source hash; run it after matching code and after mergingmain. Hand-written remarks about callers go on a; Callers note:line. - Gate:
make gaterunsmake diff(byte-exact),make verify(every byte the source claims is really emitted by it) andmake lint(tools/lint_readability.py, including the header rulesHEADER,CALLERS,SIZE,UNMATCHEDandDPDB). - Review: someone who did not write the routine checks a whole cluster against the ROM:
every claim true, the CPU state right, names that don't mislead, unknowns hedged. The verdict is
one row per routine in a new round file,
symbols/reviews/rNNN.csv(address,name,date,reviewer,verdict,source_hash,notes), with the routine'ssource_hashfromsymbols/functions.csv. Any later edit to the routine changes its hash and sends it back for review.tools/progress.py --updatethen marks itverified. - Session end:
tools/end_session.sh.
A change to STYLE.md or to the lint's rules is its own commit, approved by the maintainer and
logged under "Decisions" in STATUS.md, so no routine is judged by a rule its own author just
wrote.
Getting started
python3 tools/check_env.pyto confirm your toolchain (asar 1.91, Python 3.10+,make).- Drop your own legally dumped ROM in
roms/chrono_trigger.sfc(never committed; see Target ROM). make diffshould report a 100% match.- Read
STATUS.mdfor where things stand andNEXT.mdfor the queue.