Skip to content

feat(src): two Oozla functions in C, closer near miss for func_L11_00420C88 - #396

Merged
Veradictus merged 6 commits into
OpenRAC:masterfrom
DrLegitamate:match/drlegitamate-joba-oozla
Nov 3, 2026
Merged

Veradictus merged 6 commits into
OpenRAC:masterfrom
DrLegitamate:match/drlegitamate-joba-oozla

Conversation

@DrLegitamate

@DrLegitamate DrLegitamate commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

Follow-up to #394: two Oozla (level 01) functions matched from their retained near misses, and an improved near miss for Joba's largest remaining function.

Matched

Function Bytes What closed it
func_L01_003D1A48 1,268 The RGB mask is a block-local int rgb = 0xFFFFFF; at the top of the inner loop body. As an inline constant its lifetime was 1, so loop.c's first pass (threshold already lowered by two float hoists) left it for the rerun, after five pointer preparations; as a local its set is the first movable insn and is hoisted first, giving retail's preheader order. -O2 -G8 -g in its own unit.
func_L01_003D8358 1,108 Two source corrections. step = speed*step swapped the mul.s operands (expand_binop swaps them when the target is an operand); the height now adds speed*step directly. Reusing scale for both the constant and the product tied the scale multiply with an argument move in sched2 (equal priority, decided by dependent count); holding the constant in its own k gives retail's order. Default -G8 profile; its port-only C row and file are removed (as in 588f8f0).

Notes only

  • func_L11_00420C88 (15,832 bytes): the retained body is now 15,832/15,832 bytes with 18 register-only rows left. Earlier drafts' counts hid 47 alignment nops from a do/while(0) macro. Recovered: per-branch call tails, retail branch order, nested call arguments, strict float compares, case-local variables, the case 5 partner loop in the shape of matched sibling func_L11_00424A60 (its D_L11_001B359C load now lands in the branch slot as retail's one-word $gp form), and a real index error in case 19 (0x54c where retail uses 0x56c).

Question for maintainers: func_002B60B0's declaration in Joba callers

Two independent Joba functions match completely only if this caller declares func_002B60B0 as returning void:

  • func_L11_00420C88: with the retained body, a void declaration closes all 18 remaining rows (verified: 1 of 1 places match). With the true void * return, sched1 ranks the post-call index load above the lui and local-alloc sees $v0 as still in use, so index and base swap $v0/$v1 at three call sites.
  • func_L11_00452450: a void declaration closes its seven rows (see its note).

src/game/002B60B0.c returns its pointer, and COMPILER-NOTES forbids an invented void return, so neither is used here. Most existing callers in src/ already declare it void. If maintainers accept that these callers' original declaration was void (retail leaving $v0 free after the call at every site is consistent with that), both functions can land as matches; otherwise the notes stand.

Validation

  • tools/check.py: each matched function 1 of 1 USA v1.01 place. func_L01_003D8358 also has a USA v2.00 place, not checked here (no US2 dump on this machine); PAL has neither.
  • tools/build.py all --strict: 28 programs OK, zero C fallbacks (01_oozla: OK: 2062852 loaded bytes equal).
  • python3 -m unittest discover -s tests: 339 tests OK.
  • tests/check_repository.py: repository checks passed.
  • Progress report not regenerated.

🤖 Generated with Claude Code

https://claude.ai/code/session_017f7s8MnhdrdEynhYhxkLs6

DrLegitamate and others added 3 commits November 2, 2026 22:58
Every block now aligns with retail; about 120 instructions differ, mostly
register names. Per-branch call tails, retail branch order, nested call
arguments, strict float compares and case-local variables recover the control
flow and the object/state/path allocation; case 19's table index was 0x54c
where retail uses 0x56c. The remaining eight bytes are the D_L11_001B359C load
in the second switch's case 5 partner loop. The draft's earlier counts included
47 alignment nops from a do/while(0) macro.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017f7s8MnhdrdEynhYhxkLs6
From the nonmatching draft (1268/1268 bytes, four preheader instructions
reordered). Declaring the RGB mask as a constant local inside the inner
loop gives its set a long lifetime, so loop.c hoists it on the first pass
ahead of the pointer preparations, as retail does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017f7s8MnhdrdEynhYhxkLs6
Oozla state handler (1108 bytes, -G8 unit). The draft was one sched2
tie away: holding the scale constant in its own variable (k) for -k*y
and k*x, instead of overwriting it with the product, makes sched2 issue
k*x before the zero direction argument as retail does. Writing the
height update as one speed*step product fixes the other multiply's
operand order. Removes the nonmatching draft and the functional port
stand-in.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017f7s8MnhdrdEynhYhxkLs6
@bytematchdev

bytematchdev Bot commented Nov 2, 2026

Copy link
Copy Markdown

ByteMatch progress report

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_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.

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 50a05a1 · Ratchet & Clank: Going Commando on ByteMatch

DrLegitamate and others added 3 commits November 2, 2026 23:44
… left

Second attempt: the case 5 partner loop takes the matched sibling
func_L11_00424A60's for(;;) shape with its inline moby helpers, so the
D_L11_001B359C load stays last before the loop entry and reorg moves it into the
branch slot as retail's one-word $gp form; case 28 and case 40 get their own
locals. 15,832/15,832 bytes; the remaining 18 rows are index/base register
swaps after the value-returning func_002B60B0 call in cases 14, 15 and 22. A
void declaration of func_002B60B0 closes all of them, as it does for
func_L11_00452450; not used, the callee returns its pointer.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017f7s8MnhdrdEynhYhxkLs6
@Veradictus
Veradictus merged commit 86a6d30 into OpenRAC:master Nov 3, 2026
2 checks passed
Veradictus added a commit that referenced this pull request Nov 3, 2026
Veradictus added a commit that referenced this pull request Nov 3, 2026
…now matched

func_00293F98, func_002EC408 and func_L00_002B30E8 have matched C in src/
since #396-#399; their functional files had no functional.tsv row left
and nothing reads them.
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.

2 participants