Skip to content

feat(functional): backfill for the native port - #389

Merged
Veradictus merged 29 commits into
masterfrom
port/backfill
Nov 2, 2026
Merged

Veradictus merged 29 commits into
masterfrom
port/backfill

Conversation

@Veradictus

@Veradictus Veradictus commented Nov 1, 2026 •

Copy link
Copy Markdown
Member

Functional C for USA v1.01's remaining assembly, for the native port in OpenRAC. OpenRAC's native port (#191) is pinned to this branch's tip.

No matches here, 0 functions added to the report. progress/, the README table and docs/VERSIONS.md are untouched. Nothing in nonmatching/functional/ is compiled into the matching build.

What's in it

  • 357 rows in nonmatching/functional.tsv, up from 29. 12 are per-level copies, each SAME on its own level's captures.
  • Gate result: 342 SAME, 0 differ, 2 not checked. func_002BA0E0 can't place in level 02, whose table holds its own routine (func_L02_0033C8B8) where the row names func_002BEE70. func_002A0558 is never called in the capture runs.
  • func_002F2758 is out: it's a piece of hand-written code with register inputs, and its row made hostgen call the wrong thing. func_L09_00410200 is out too: feat(src): match func_00292078 and retain near misses #388 matched it.
  • tools/fcheck.py: $RAC2_FCHECK_OPT and far branches, for gating a whole kernel in hostgen's console form. Capture scripts for every level, by holding the next-level word through New Game. Levels 1-20 and 22-26 are reached. Level 30 crashes on that load.
  • tests/check_repository.py: now allows ASM_FUNC rows in functional.tsv.
  • A branch coverage check (tools/fcheck.py cover): captured calls ran only 53% of the rows' retail bytes, so every row with unrun blocks was read against retail's disassembly. That found 31 real slips (wrong offsets, inverted tests, a misplaced store from a delay slot, wrong globals), all fixed. Most fixed lines still aren't reached by the captures, so treat them as read from the code, not proven by a run.
  • The gate applies the port's per-level call table, so a level copy's own callee is what gets compared.
  • func_L00_00420C38, the hero camera: two slips fixed (+0x44 and the blend rate), checked against retail with scripted hyper strike and double jump captures.
  • func_002F7320, the key table lookup, from the assembly. Not gated yet.
  • func_00131D98 split at 0x131DE8.
  • Master merged in, with fix(nonmatching): repair five large actor and loader reconstructions #390. func_L11_00420C88 takes that PR's repaired draft (retail's float compare sense in the selector 10 clamp) and keeps our 0x56c fix for case 23, which the draft still reads as 0x54c. SAME on 4 calls; those calls reach neither changed spot.
  • func_002E8368's loading scene phase end: both retail paths return 1. SAME on 4 calls.

Checked

  • tools/build.py all on USA v1.01: 28 of 28 programs byte-identical, one row removal behind this tip. Functional C isn't linked, so that can't change the bytes.
  • tests/check_repository.py passes.
  • SAME means the function agreed with retail on the captured states, at most 3 levels per function. It isn't a proof for paths those captures didn't reach.
  • tools/fcheck_gate.py calibrate hasn't been rerun on the new levels; the full-row gate ran instead.

Still to come

Collision needed no C here: CollLine, CollSphere and func_00277F48 translate, and hostgen's console form of each gates SAME (32, 32 and 6 calls; OpenRAC keeps those verdicts). func_00274D90 is the moby draw side, which the port replaces. What's left is the functions the port's translator refuses and that have callers, then the near-miss drafts as the gate proves them.

@bytematchdev

bytematchdev Bot commented Nov 1, 2026 •

Copy link
Copy Markdown

ByteMatch progress report

SCUS_972.68_v2

Code matched 81.01% · 4.52 MB of 5.58 MB
Fuzzy match 81.01%
Functions 7,595 / 8,634
Data matched 0.00%
Units complete 973 / 1,156

No function changes.

SCES_516.07

Code matched 54.15% · 3.09 MB of 5.70 MB
Fuzzy match 54.15%
Functions 6,996 / 8,672
Data matched 0.00%
Units complete 958 / 1,196

No function changes.

SCUS_972.68

Code matched 84.74% · 4.68 MB of 5.53 MB
Fuzzy match 84.74%
Functions 7,760 / 8,579
Data matched 0.00%
Units complete 924 / 1,018

No function changes.

Commit 578bc4c · Ratchet & Clank: Going Commando on ByteMatch

…ort branches

$RAC2_FCHECK_OPT replaces the unit's -O for the test copy, and a branch the assembler finds out of
range goes through a jump of its own. hostgen's console form of a whole hand-written kernel needs both.
Retail reaches it by jal from hand-written code with its inputs in v1, s5 and a1, on a stack of its own
in the scratchpad. The row's C took a0-a3, and it won over the translation, so those callers passed it
the wrong values. With no row they run it in place. func_002BA0E0's table names func_002BEE70: the
catalogue's name for the routine at 0x002BEE78.
func_L00_002A4928, func_L01_00394240, func_L00_00424F98, func_L04_003A21F8, func_L06_00443A38,
func_L06_003E5D30. One declaration of D_001A79F0 each, retail addresses in place of ref_ names, the
angle's exact bits, three settings read as one array, and the frame retail has, so an unset w
left on the stack matches.
…8 on

D_L00_0023A6F0 has no value in any level's build, so outside level 0 the name
kept level 0's address and the second half of the table was written elsewhere.
Found by reading retail's unrun blocks against the C: wrong offsets and a
wrong table name, missed conditions, extra or missing calls. All SAME at the
gate, which does not reach the fixed lines.
… captures caught

func_002B0C28 wrote its slot state to 0x1A8FB0 and fell through to return 1
where retail writes 0x1A8C60 and returns 2; func_002B0CE0 the same global.
func_003384C0 restored the field of view after its last camera update, where
retail restores it in that call's delay slot, before it. The rest came from
reading retail's unrun blocks against the C.
…E8 at +0x50

The row held an 80-byte loop driver and, after it, a second function with a
frame of its own. tools/build.py all: every program OK as before.
…solve as the port's

call_copies.tsv lists the jals of a folded function that target another
function in some levels' copies; the port calls what the running copy's jal
calls (openrac_call_in_copy). The gate now does the same for a level build:
the address at the same offset of that level's copy. func_L00_003603C0's
level 9 state differed for want of it.
…is SAME, addresses moved

Each has the same instructions as a gated sibling but for addresses; the
sibling's C with its addresses read off the two retail codes. Each SAME in its
own level on box2's captures (4 calls each, func_L22_0040F1C0 1).
# Conflicts:
#	nonmatching/functional.tsv
Rebase the functional row on the retained draft of #390. Selector 10's angle
clamp now uses retail's strict compares (c.lt.s on both bounds), so an
unordered angle is stored unchanged where the earlier C stored +pi/2. The
other changes of the draft (hero globals as one object, separate projectile
arms in cases 38/39, selector 0's branch order) do the same as before.

Case 23 keeps this row's WORD(state, 0x56c) for the func_002B6228 path,
which retail reads at 0x4231B8 and 0x4231E0; the draft still has 0x54c.

Gate: fcheck SAME on 4 calls; fcheck cover runs 171 of 3,958 retail
instructions, and neither selector 10 nor case 23 is among them, so both
changes rest on reading retail.
@Veradictus Veradictus changed the title [WIP] feat(functional): backfill for the native port feat(functional): backfill for the native port Nov 2, 2026
@Veradictus
Veradictus marked this pull request as ready for review November 2, 2026 07:54
@Veradictus
Veradictus merged commit 296d8db into master Nov 2, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant