Skip to content

feat(src): six Joba functions in C, notes for the near misses - #394

Merged
Veradictus merged 16 commits into
OpenRAC:masterfrom
DrLegitamate:match/drlegitamate-joba-00434580
Nov 2, 2026
Merged

Veradictus merged 16 commits into
OpenRAC:masterfrom
DrLegitamate:match/drlegitamate-joba-00434580

Conversation

@DrLegitamate

@DrLegitamate DrLegitamate commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

Six Joba (level 11) functions matched from their retained near misses, plus measured notes for the ones that stay assembly.

Matched

Function Bytes What closed it
func_L11_00434580 1,144 Two control-flow fixes in the draft: a hit with a true predicate only removes the object (retail skips func_L00_003294F0), and a stopped projectile in frames 25-33 returns without expiring. Each arm writes out its own hit tail, which jump2 cross-jumps after allocation (object stays in $s2). func_002C2210's last two parameters are declared float-then-int (same $t2/$f14; other callers already use that interleaving). The distance call is func_00282E80, not func_00282E48.
func_L11_00472E10 896 The eight-child loop as a plain index loop over the state words swaps the sentinel and state into retail's $s4/$s3.
func_L11_00461308 1,236 The random bounds are one two-float block at D_L11_001B2388: the upper is read as D_L11_001B2388_block[1] (existing _block sda alias pattern), a two-instruction absolute load that stays out of the call's delay slot; the lower keeps its $gp view. Forming the linked moby's pointer before reading its state byte fixes the predicate's registers.
func_L11_003DCEB0 436 The state flag takes the switch variable only once the frame count reaches 0x79, giving retail's movn; the count is incremented in place and re-read (unmasked store, masked compare). The effect table uses the char D_L11_001A8F20[] __attribute__((sda)) declaration most callers already have, so its address is one macro load and the 0x810001 stack argument takes $a2 (diagnosed from the allocation dump). Prototypes added for three helpers it called undeclared.
func_L11_00437FD0 628 The direction flag and pass count carry next-state values set in each arm and copied back at the end of each pass, reproducing retail's $a1/$v1 values with stores after each definition and reloads before the shared copy and the pass test (the allocation dump showed a single pseudo crossing 14 calls could never be caller-saved). The lengths are indexed by the loop counter, length is block-local and next is formed after the floor clamp. -O2 -G0 -g in its own unit (-g supplies the line-label nop before div.s).
func_L11_00438880 1,108 Both flag scans as while (next < 13) { int j = next - 1; if (!flags[j]) break; next++; }. Written as flags[next-1], the front end folds the address to (flags+next)-1 and loop.c finds the address giv not worth reducing (0 vs 7 in the loop dump); the separate j keeps the next-1 giv, so the summed benefit makes loop.c strength-reduce it into retail's pointer cursor, including the pre-loop test through the computed address and the copy into the cursor.

Each lives in its own unit; the nonmatching/ copies are retired, and the two functions that had port-only C in nonmatching/functional.tsv lose those rows and files (as in 588f8f0).

Notes only (still assembly)

  • func_L11_00452450: all 956 bytes match if func_002B60B0 is declared void in this caller. Not used, because the callee returns its pointer and COMPILER-NOTES forbids an invented void return; most existing callers in src/ already declare it void. A maintainer ruling would settle it.
  • func_L11_00443D78: negative result appended to its notes (inline conversions do not serialize).
  • func_L11_00443940: improved body and findings in its notes. With the MenuRecord/SDATA table shapes from the matched sibling and -fno-rerun-loop-opt, the selection loop matches retail; 20 bytes remain, mainly retail keeping each label pointer in its own register before the four draw calls.

Validation

  • tools/check.py: each matched function 1 of 1 USA v1.01 place. PAL's catalogue has none of them; US2 not checked (no US2 dump on this machine).
  • tools/build.py all --strict: 28 programs OK, zero C fallbacks (e.g. 11_joba: OK: 2363208 loaded bytes equal).
  • python3 -m unittest discover -s tests: 339 tests OK.
  • tests/check_repository.py: repository checks passed.
  • Compiler rebuilt from this master before measuring. Progress report not regenerated.

🤖 Generated with Claude Code

https://claude.ai/code/session_017f7s8MnhdrdEynhYhxkLs6

DrLegitamate and others added 8 commits November 2, 2026 18:11
Joba's projectile update, 1,144 bytes at its one USA place, from the retained
near miss. Two control-flow corrections and two source shapes close it:

- A hit with a true predicate only removes the object: retail's branch skips
  func_L00_003294F0, which belongs to the burst path.
- A projectile that has stopped moving in frames 25-33 returns without expiring.
- Each arm writes out its own hit tail; jump2 cross-jumps them after allocation,
  which keeps the object in $s2 and the impact load in the branch slot.
- func_002C2210's last two arguments are declared float-then-int (same $t2/$f14
  registers, an interleaving other callers already use), putting the $t2 zero in
  the delay slot.
- The distance call is func_00282E80, not func_00282E48.

Built -O2 -G8 -g in its own unit. The nonmatching copy is retired.

Validation:
- tools/check.py: 1 of 1 USA place; absent from the PAL catalogue; US2 not
  checked (no US2 dump here).
- tools/build.py level 11 --strict: OK, zero C fallbacks.
- python3 -m unittest discover -s tests: 339 tests passed.
- tests/check_repository.py passed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017f7s8MnhdrdEynhYhxkLs6
Twenty-odd source shapes and per-file options for the two flag scans, none
closer than the retained body; the second scan's pointer copy points at loop
strength reduction.

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

Record that a void func_002B60B0 declaration closes all seven rows, and why it is
not used, for a maintainer to rule on.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017f7s8MnhdrdEynhYhxkLs6
The retained near miss was 896/896 bytes with the state pointer and the child
loop's -1 sentinel in each other's saved registers. Writing the eight-child loop
as a plain index loop over the state words, rather than a walking pointer with
a down-counter, gives the sentinel $s4 and the state $s3 as in retail. Built
-O2 -G8 in its own unit; the nonmatching copy is retired.

Validation:
- tools/check.py: 1 of 1 USA place.
- tools/build.py level 11 --strict: OK, zero C fallbacks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017f7s8MnhdrdEynhYhxkLs6
The retained near miss was four bytes short: its upper random bound, read as a
bare one-word symbol, was moved into a call's delay slot and became a $gp load.
The bounds are one two-float block at D_L11_001B2388; reading the upper as the
block's second word (an existing `_block` sda alias pattern) gives the
two-instruction absolute load that stays before the call, and the lower keeps
its $gp view. Forming the linked moby's pointer before reading its state byte
fixes the predicate's registers. Built with the default -O2 -G0 profile in its
own unit; the nonmatching copy is retired.

Validation:
- tools/check.py: 1 of 1 USA place.
- tools/build.py level 11 --strict: OK, zero C fallbacks.

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

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

DrLegitamate and others added 5 commits November 2, 2026 18:40
Second attempt: the state-flag movn and counter store now match; the retained
body is 436/436 bytes with 14 rows left in the final call's argument setup.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017f7s8MnhdrdEynhYhxkLs6
Three changes over the retained near miss. The state flag takes the switch
variable only once the frame count reaches 0x79 (`flag` stays 0 otherwise),
which gives retail's movn; the count is incremented in place and re-read, so
the store is unmasked and the compare masked. The effect table is declared as
the sda incomplete array most callers already use, so its address is one
macro load among the argument moves and the 0x810001 stack argument takes a2
as in retail (found with the allocation dump: the split lui was being hoisted).
The three helpers it called undeclared now have their usual prototypes. Built
-O2 -G8 in its own unit; the nonmatching copy is retired.

Validation:
- tools/check.py: 1 of 1 USA place.
- tools/build.py level 11 --strict: OK, zero C fallbacks.
- tests/check_repository.py passed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017f7s8MnhdrdEynhYhxkLs6
@DrLegitamate DrLegitamate changed the title feat(src): three Joba functions in C, notes for five near misses feat(src): four Joba functions in C, notes for the near misses Nov 2, 2026
Joba's rope solver, 628 bytes at its one USA place, from the retained near miss.
The direction flag and pass count carry next-state values set in each arm and
copied back at the end of each pass, which reproduces retail's $a1/$v1 values
with stores after each definition and reloads before the shared copy and the
pass test (the allocation dump showed a single pseudo crossing 14 calls could
never be caller-saved). The lengths are indexed by the loop counter, `length`
is block-local and `next` is formed after the floor clamp. Built -O2 -G0 -g in
its own unit (-g supplies the line-label nop before div.s); the nonmatching
copy is retired.

Validation:
- tools/check.py: 1 of 1 USA place.
- tools/build.py level 11 --strict: OK, zero C fallbacks.
- tests/check_repository.py passed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017f7s8MnhdrdEynhYhxkLs6
@DrLegitamate DrLegitamate changed the title feat(src): four Joba functions in C, notes for the near misses feat(src): five Joba functions in C, notes for the near misses Nov 2, 2026
The flag scans index flags with a block-local j = next-1. Kept as a
separate variable, the front end does not fold flags+(next-1) into
(flags+next)-1, so loop.c strength-reduces the address giv into a
pointer register, giving retail's cursor, pre-loop test and copy.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017f7s8MnhdrdEynhYhxkLs6
@DrLegitamate DrLegitamate changed the title feat(src): five Joba functions in C, notes for the near misses feat(src): six Joba functions in C, notes for the near misses Nov 2, 2026
Update the retained draft with the sibling MenuRecord and SDATA table
shapes and record why the selection loop is strength-reduced (rerun loop
pass hoists the table la), the -fno-rerun-loop-opt measurement (904 bytes,
loop matches) and the remaining label-copy and entry-allocation differences.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017f7s8MnhdrdEynhYhxkLs6
@Veradictus
Veradictus merged commit 37c78fb into OpenRAC: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.

2 participants