Commit Graph

734 Commits

Author SHA1 Message Date
csaldiasdev
746e0dd4c2 docs: rename-plan — linker-script propagation rule
Fixes the wrong 'do not edit symbol_addrs*.txt' rule caught during
the D_80070F84 → gSpeciesBaseStats rename. Adds a new section
explaining that symbol_addrs.txt and undefined_syms.ld contain full
symbol declarations (not just address pins), the rename must
propagate to them, and which linker scripts are NOT declarations.

Updates:
- Out-of-scope section: removes the wrong rule, points to the new section
- Function workflow: adds step 5 (linker-script check) + renumbers
- Global-variable workflow: corrects the 'leave linker alone' line
- ps-rename-check: now checks linker-script consistency as part of
  the exit-0 contract (covers both <old> removed and <new> added)

Still matching: md5 ed1378bc… (docs-only change, build unaffected)
2026-07-05 20:33:32 -04:00
csaldiasdev
e2f23dd1fb rename: D_80070F84 → gSpeciesBaseStats[] + unk_D_80070F84 → PokemonStatsExtended
The per-species base-stats table (HP/Attack/Defense/Speed/Special)
and its sibling all-unk_NN struct. Used in CalculateStatValue
(src/22630.c), func_88600020 (src/fragments/27/fragment27.c),
and battle code (src/fragments/62/*).

Note: also updates linker_scripts/us/symbol_addrs.txt and
undefined_syms.ld — the original 'do not edit linker scripts'
rule from the rename plan was incomplete: when a symbol is
declared by name in symbol_addrs.txt or undefined_syms.ld, the
rename MUST propagate to the linker script, otherwise the new
symbol is undefined and the link fails. The address (0x80070F84)
is preserved.

D_80070FA0[] stays as-is (different table, different layout, kept
on the renamed PokemonStatsExtended type via the extern decl).

Still matching: md5 ed1378bc… (verified by `make`)
2026-07-05 20:28:56 -04:00
csaldiasdev
2b0a7ef13e rename: D_80079070 → gSpeciesBattleAnimConfig[] in 4F410.c
The per-species battle animation / effect configuration table.
Indexed by species ID (decremented to 0-based) in the func_80048060-
area dispatcher. Fields unk_03/unk_04 are sound/animation parameters
returned via var_a3 / sp24.

The struct typedef (unk_D_80079070) and its fields (unk_00..unk_04)
are left untouched per the rename plan — table-level only.

Still matching: md5 ed1378bc… (verified by `make`)
2026-07-05 20:27:08 -04:00
csaldiasdev
67480deb29 rename: D_80077970 → gSpeciesSoundVariant[] in 373A0.c
The per-species sound/SE variant table. Indexed by species ID
(decremented to 0-based) in func_800367A0's cases 0x33 and 0x32.
The struct typedef (unk_D_80077970) and its fields (unk_00..unk_04)
are left untouched per the rename plan — table-level only.

Still matching: md5 ed1378bc… (verified by `make`)
2026-07-05 20:26:46 -04:00
csaldiasdev
1a100c47b7 rename: literal 151 → NATIONAL_DEX_COUNT in fragments/28/fragment28_214920.c
Nine sites where 151 is the Gen-1 species count:

- L239, L246: mem_pool_alloc size for D_8006FF00 pointer arrays
- L240, L247: for loops over D_8006FF00[] (species metadata)
- L244, L251: func_8002CBB0 calls with species count + size args
- L6260: reverse for loop (i = 151 down to 1) over species

Introduces #include "pokemon.h" in this file.

Still matching: md5 ed1378bc… (verified by `make`)
2026-07-05 20:25:22 -04:00
csaldiasdev
606eff9a41 rename: literal 151 → NATIONAL_DEX_COUNT (loop bounds + array size)
Four sites in src/20470.c and src/fragments/50/fragment50.c where
151 is used as the Gen-1 species count:

- src/20470.c:514 — for loop over D_8006FF00[] (species metadata)
- src/fragments/50/fragment50.c:69 — D_82608568 array size
- src/fragments/50/fragment50.c:1679 — for loop counting owned species
- src/fragments/50/fragment50.c:2613 — for loop loading portrait textures

Introduces #include "pokemon.h" in both files.

Other 151 occurrences in fragments/50/fragment50.c (lines 2574,
2630, 2632) are explicit Mew species IDs, not species counts —
left untouched (would need a separate MEW = 151 constant if
named, but that's out of scope for the count-sentinels pass).

Still matching: md5 ed1378bc… (verified by `make`)
2026-07-05 20:24:38 -04:00
csaldiasdev
cef5b58562 rename: literal 0x98 → SPECIES_BLANK in 4F410.c
Three sites where arg0 (species ID) is compared/assigned/switched:
- L1089: range check ((arg0 == 0) || (arg0 >= SPECIES_BLANK))
- L1179: default species assignment in case 1
- L1214: switch case fallthrough to default handler

Introduces #include "pokemon.h" in this file.

Other 0x98 occurrences (L86, L276, L570) are D_80079070[] data
table entries (per-species animation/sound parameter values), not
species IDs — left untouched. Other 0x9C/0x9D/0x9E/etc. cases in
the same switch are Stadium-specific species IDs beyond the
national dex range, distinct from SPECIES_BLANK — left as-is.

Callers: func_80048060-area (src/3D140.c)
Still matching: md5 ed1378bc… (verified by `make`)
2026-07-05 20:21:10 -04:00
csaldiasdev
c274fd455d rename: literal 0x98 → SPECIES_BLANK in 373A0.c
Four sites in func_800367A0 (case 0x33 and case 0x32) where
arg1 (a species ID) is checked against the upper-bound sentinel
before decrementing to a 0-indexed array. Introduces
#include "pokemon.h" in this file.

Other 0x98 occurrences in 373A0.c (lines 24, 31, 41) are
D_80077970[] data table entries (per-species animation/sound
parameter values), not species IDs — left untouched.

Callers: func_80048408-area (src/3D140.c:857, etc.)
Still matching: md5 ed1378bc… (verified by `make`)
2026-07-05 20:20:39 -04:00
csaldiasdev
5c958f2892 rename: literal 190 → SPECIES_EXTENDED_MAX in func_80022A60
Upper bound of the wider species ID range accepted by func_80022A60
(maps to D_800732FF). Returns SPECIES_BLANK (already named) on
out-of-range.

Callers: func_80021D9C, func_800228F0 (src/232C0.c:121, others)
Still matching: md5 ed1378bc… (verified by `make`)
2026-07-05 20:18:39 -04:00
csaldiasdev
f66751412f rename: literal 151 → NATIONAL_DEX_COUNT in func_80022A38
The canonical Gen-1 species range check. Used as the upper bound
of the lookup in D_80073267.

Callers: func_80021F04, func_80026268 (src/232C0.c:155, others)
Still matching: md5 ed1378bc… (verified by `make`)
2026-07-05 20:18:27 -04:00
csaldiasdev
05dbdd0393 rename: literal 152 → SPECIES_BLANK in func_80022A60
The out-of-range return value in the wider species ID lookup
function. Introduces #include "pokemon.h" in this file.

Callers: func_80021D9C, func_800228F0 (src/232C0.c:121, others)
Still matching: md5 ed1378bc… (verified by `make`)
2026-07-05 20:18:14 -04:00
csaldiasdev
780c9949d3 add: include/pokemon.h with species ID constants
Defines:
- SPECIES_NONE         = 0
- NATIONAL_DEX_COUNT   = 151
- SPECIES_BLANK        = 152  (out-of-range sentinel)
- SPECIES_EXTENDED_MAX = 190  (Stadium-internal species ID range)

Still matching: md5 ed1378bc… (verified by `make`, header currently unused)
2026-07-05 20:17:53 -04:00
csaldiasdev
0cbb693399 minimax joins the show 2026-07-05 20:01:28 -04:00
cristian
501dc4da9f Decompile func_8120241C (score panel compose) to C behind NON_MATCHING
Graphics cluster: draws the score/counter panel (layout by D_8122C4E2), then
lays out the value's digit run right-to-left via the D_8120E580 glyph-width
table (u8[], two-level lookup at +0x80). Same composer pattern as func_81202210;
strides (var_s4-0x266 bytes, u16 dst step, D_8120D7F3 u8[]) verified vs asm.
Bare GLOBAL_ASM: 34 -> 33.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 16:56:25 -04:00
cristian
57d716f5af Decompile func_81202210 (GB screen frame compose) to C behind NON_MATCHING
Graphics cluster: clears the GB screen buffer, draws the border glyphs, then
lays out the digit run using a two-level glyph-width lookup in D_8120E480
(width index at +0x43, then advance). Reverse-engineered the three glyph tables
from the asm: D_8120E480 (u8[]), D_8120E680 (u16[]), D_8122AD50 (u8[]).
Bare GLOBAL_ASM: 35 -> 34.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 16:36:27 -04:00
cristian
cc7fa7890f Decompile func_812018C0 (tint-modulated blit) to C behind NON_MATCHING
Graphics cluster: scales each source pixel's luminance (blue channel, 0-31) by
the arg2 RGB565 tint and writes it to the render target. IDO 4x-unrolled loop
rewritten as a simple double loop (all 4 unrolled pixels verified identical).
Bare GLOBAL_ASM: 36 -> 35.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 16:27:15 -04:00
cristian
b4e221c9aa Decompile func_812016DC (render-target frame draw) to C behind NON_MATCHING
Graphics cluster: blits corner/edge glyphs from D_8122C748 into the render
target, then paints the 0xC14 grid lines. m2c mistyped every pointer stride as
a u16 element count; verified against the asm that they are all byte offsets
(u8* base + byte offsets, cast to u16* at each access). Bare GLOBAL_ASM: 37 -> 36.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 16:25:07 -04:00
cristian
19ce69a2aa Decompile func_812020C0 (tile->framebuffer blit) to C behind NON_MATCHING
Graphics cluster: copies a tile's set (odd) pixels from D_8122C748's plane data
into the render target at +0x5B4, 4 pixels per step over an 0xB x 0xC region;
arg1 selects source plane and scan direction. Multiplier (arg2*0x108), source
step (+/-1 u16) and framebuffer offset verified vs asm. Bare GLOBAL_ASM: 38 -> 37.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 16:11:29 -04:00
cristian
f5062afcbc Decompile func_80048060 (sound event dispatcher) to C behind NON_MATCHING
Play-sound path: search the 3-slot cache for the sound id, evicting+DMA-loading
the file, player object and wave data on a miss, then dispatch by event type to
start/stop a voice via the slot's command table. Built on reverse-engineered
audio types: File2SubHeader2.files[] table, ALSeqFile seqArray (D_800FC700 wave
entries), and the 6-byte command record at D_800FC6C0[slot]+0x10 (all strides/
offsets verified vs asm). Includes 373A0.h for the audio globals (match-safe).
Bare GLOBAL_ASM: 40 -> 39... crosses 80% C-first.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 16:01:33 -04:00
cristian
5e7a7bdf4a Add trailing files[] array to File2SubHeader2
373A0.c allocates D_800FC6F0/D_800FC6FC as a File2SubHeader2 header followed by
num_files u32 file offsets; the event/sound dispatchers index that array. Add it
as files[ENTRY_SIZE] (flexible array) so sizeof stays 0xC and the matching build
is unaffected (verified md5). Documents the real audio file-table layout.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 15:44:19 -04:00
cristian
d39b7013d8 Decompile func_80033B2C to C behind NON_MATCHING; 33FE0 fully C
Model initializer: copies the header block into the model's 0x138 sub-struct,
records the matrix's per-axis scale into position, runs the base transform and
rebuilds the joint command list. This clears the last bare function in 33FE0.c,
which is now entirely C (build-free). Bare GLOBAL_ASM: 40 -> 39.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 15:08:15 -04:00
cristian
99e3449ef9 docs: update C-first progress (21 functions, 79%, 33FE0 cluster complete)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 15:03:32 -04:00
cristian
373cb11759 Decompile func_80035B20 and func_800357F4; func_80035434/538 return f32
The leftover-$f0 pair: both used a distance value returned via $f0 by
func_80035434 / func_80035538, which were declared void ending in a bare
sqrtf(...). Changed those to return f32 (verified still byte-matching), then:
- func_80035B20: spring-blends target vertices toward sources by scaled distance
- func_800357F4: builds the transform-command list from the joint adjacency graph
This completes the 33FE0 model cluster. Bare GLOBAL_ASM: 42 -> 40.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 15:02:59 -04:00
cristian
fbc18d1fae Decompile func_80033D44 (append transform frame) to C behind NON_MATCHING
Builds an orthonormal frame from the p0->p1 direction (picking an up-vector via
D_8007C5B4, two cross products), stores a new StadiumTransform with its four
control points and matrix, then computes each vertex's projection weights.
Largest 33FE0 function (0x510). Bare GLOBAL_ASM: 43 -> 42.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 10:53:12 -04:00
cristian
fffa9a8a05 Decompile func_80034348 (smooth vertex normals) to C behind NON_MATCHING
Clears per-vertex accumulators, adds each triangle's length-120 face normal
(cross product) to its three vertices, then stores the per-vertex average as
the vertex color. m2c's 4x-unrolled clear/average loops rewritten as simple
loops; triangle index stride (3x s16) and (s32)len>0 guard verified vs asm.
Bare GLOBAL_ASM: 44 -> 43.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 10:49:04 -04:00
cristian
4e14464d55 Decompile func_80034BD4 (projected vertex deform) to C behind NON_MATCHING
Same barycentric deform as func_80034824, gated on func_80033568 projecting the
vertex onto the transform's p0->p1 edge within (0, maxDist); clears the bit
otherwise. arg0 is the segment forwarded to Memmap (as func_800361C4 passes it).
Bare GLOBAL_ASM: 45 -> 44.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 10:42:07 -04:00
cristian
21c1015e80 Decompile func_80034824 (barycentric vertex deform) to C behind NON_MATCHING
Transforms a StadiumTransform's four corners by its matrix (guMtxXFMF), then
sets each flagged vertex's offset to the weight-interpolated corner minus base.
Offsets verified against the asm: nextIndex (0x92), disabled (0x8E), and the
per-transform weights at vtx + arg2*0x10 + 0x14. Bare GLOBAL_ASM: 46 -> 45.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 10:36:24 -04:00
cristian
a54c8b835a docs: update C-first progress (15 functions, 75.8%)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 10:31:33 -04:00
cristian
560cae02df Decompile func_80035FA8 (vertex offset settle) to C behind NON_MATCHING
Zeros sub-threshold offsets, folds the drawGroup-averaged offset into base,
and decays the offset by stiffness. m2c read the count via the position
pointer at +0x2C (= ModelVertex.drawGroup, 0x90); resolved against the struct.
Bare GLOBAL_ASM: 47 -> 46.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 10:31:00 -04:00
cristian
eb38c225c3 Decompile func_80035E2C (per-vertex Y nudge) to C behind NON_MATCHING
Adjusts flagged vertices' Y position by mode; retyped m2c's void* args to
ModelSegment*/ModelVertex*. Defining it before func_800361C4 lets that
function's forward-decl be dropped. Bare GLOBAL_ASM: 48 -> 47.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 10:22:21 -04:00
cristian
6b86efc0ce Decompile func_800361C4 (model dispatcher) to C behind NON_MATCHING
Jump-table dispatch on model type calling per-type transform sequences, then
a vertex remap loop copying the 0x30-byte pos/color/tex tail. Offsets and the
inline copy verified against the asm; Memmap_GetSegmentVaddr returns uintptr_t
so results are cast. Bare GLOBAL_ASM: 49 -> 48.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 10:18:08 -04:00
cristian
39e1ae7edf Decompile 2 jump-table functions to C behind NON_MATCHING
func_81207698 (threshold lookup switch, hand-decompiled from asm since m2c
gave a degenerate draft) and func_81208C08 (message-dispatch switch, m2c via
the rodata jtbl input) in fragment1_86CB0. Bare GLOBAL_ASM: 51 -> 49.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 10:02:34 -04:00
cristian
40a5253f5a Decompile func_81202758 to C behind NON_MATCHING
Tile-grid draw routine sourcing glyph data from D_8122C748->unk0000; each
m2c "D_8122C748 + offset" maps to &D_8122C748->unk0000[offset]. Bare
GLOBAL_ASM: 52 -> 51.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 09:55:40 -04:00
cristian
c764224f64 docs: record m2c jump-table workflow (pass rodata .s)
m2c resolves switch jump tables when the rodata .s defining jtbl_* is passed
as an extra input. Unblocks the 14 remaining jump-table functions.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 09:51:13 -04:00
cristian
acba8cbf02 Fix func_81202758 forward-decl signature in func_81202FCC
Correct the prototype to (u16*, s32) to match the actual function, avoiding
a future conflict when func_81202758 is decompiled.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 09:47:29 -04:00
cristian
0182e1383d Decompile 2 more functions to C behind NON_MATCHING
func_81202FCC (timer-driven counter update) and func_812006AC (GB-pak ROM
read with checksum, mirrors sibling func_812008C8) in fragment1_7F9A0.
Bare GLOBAL_ASM: 54 -> 52.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 09:45:59 -04:00
cristian
ee756f49ca docs: update C-first progress (7 functions, 71.6%)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 09:38:09 -04:00
cristian
c4ad1bb9e6 Decompile 2 more functions to C behind NON_MATCHING
func_812004B8 (GB-pak write/verify retry loop, mirrors sibling func_81200358)
and func_81202EA8 (saturating additive RGB565 blend) in fragment1_7F9A0.
Bare GLOBAL_ASM: 56 -> 54.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 09:37:30 -04:00
cristian
541dfa4c1b Decompile 5 functions to C behind NON_MATCHING
C-first: wrap func_80033D1C, func_800414B8, func_8003F4C0 (3D140/33FE0) and
func_812075C0, func_81209690 (fragment1_86CB0) in #ifdef NON_MATCHING. The
matching build still uses GLOBAL_ASM and stays byte-exact; NON_MATCHING now
compiles these from C. Bare GLOBAL_ASM: 61 -> 56.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 09:33:07 -04:00
cristian
fab939a784 docs: C-first plan, Rust/Python tool equivalence, dev deps
Add docs/c-first-plan.md (campaign to write C for every function before
matching), document the macOS build gotchas and Rust matching toolkit in
README/CLAUDE, and record m2c as an optional dev dependency.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 09:33:07 -04:00
cristian
fc4b527fd9 Rust tools: add ps-status --c-coverage and ps-fdiff --file
Support the C-first campaign: globalasm now detects whether each GLOBAL_ASM
is behind a NON_MATCHING guard; ps-status --c-coverage reports guarded vs
bare counts (the "bare -> 0" metric) with --list/--json; ps-fdiff --file
summarizes every function in a source object, ranked closest-first.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 09:32:55 -04:00
cristian
49c07fe999 ps-core: match mapfile_parser .text symbol table exactly
The map parser dropped symbol-less contributions and vram==0 archive
members, undercounting progress by 6980 bytes vs progress.py. Skip
unallocated (vram==0) contributions and synthesize a $_static_symbol for
the leading gap before a contribution's first named symbol, matching
mapfile_parser symbol-for-symbol (8240 symbols / 2204464 bytes).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 09:32:55 -04:00
cristian
f0b540b4b5 macOS: auto-detect GNU libiconv for EUC-JP encoding
macOS's BSD iconv mis-encodes an ASCII backslash as the EUC-JP fullwidth
backslash (0xA1C0) after a multibyte character, corrupting \n escapes in
Japanese string literals and breaking the byte-match (~293-byte divergence
in fragment62). Prefer GNU libiconv from Homebrew when present, warn otherwise.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-05 09:32:43 -04:00
cristian
91cd790c86 Add Rust matching tools (ps-status, ps-firstdiff, ps-fdiff)
Introduce a cargo workspace under tools/rust/ with a shared ps-core
library and three binaries for the byte-for-byte matching effort:

- ps-status: status of functions pending decompilation. Build-free mode
  scans GLOBAL_ASM in src/ (validated: 190 funcs across 68 files, matching
  grep); build-aware mode reports byte progress per folder from the linker
  .map, porting the progress.py metric.
- ps-firstdiff: first difference(s) between built and expected ROM, with
  function naming and jal-target resolution (like tools/first_diff.py).
- ps-fdiff: non-interactive per-function asm diff of built ROM vs baserom
  (like ./diff.py -mwo <func>).

ps-core provides parsers for GLOBAL_ASM, symbol_addrs, and GNU ld .map
files (with vram/vrom lookups), a .z64 reader with md5 verification, and a
rabbitizer wrapper for disassembly. All parsers are unit-tested.

Wired into tools/Makefile (cargo build, skipped with a warning if cargo is
absent), target/ gitignored, and documented in README.md and
tools/rust/README.md.

The Python scripts (progress.py, tools/first_diff.py, diff.py) are kept in
place: only the build-free ps-status path can be validated without a ROM
and toolchain. Parity of the build-dependent tools must be confirmed in a
full build environment before removing the Python equivalents.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 23:52:13 -04:00
csaldiasdev
33c207cdca starting point. 2026-06-28 17:30:52 -04:00
Revo
a4011d1146 Merge pull request #225 from zanderyk/func_800328E4
Some checks failed
C/C++ CI / build (push) Has been cancelled
Match `func_800328E4` and `func_80032940` and `func_80032990`
2026-06-10 12:07:18 -04:00
Revo
7baf18daff Merge pull request #229 from dplewis/macos-archiver
Fix ultralib build on macOS
2026-06-10 12:07:01 -04:00
Diamond Lewis
35badf1d48 Fix ultralib build on macOS 2026-06-10 10:51:35 -05:00
Revo
756f7e332e Merge pull request #228 from zanderyk/jpeg-utils-match
Some checks failed
C/C++ CI / build (push) Has been cancelled
Jpeg utils match
2026-02-27 22:01:32 -05:00
alexanderkarlis
0379a7b95e rename C970 -> jpegutils 2026-02-27 15:28:46 -05:00