fix(phase-30 S6b): MULTI-LINE BLINDNESS in family_remap — 4 faces, 3 fixed; +740 members (R22 140/140)

- ONE root cause, four faces (cookbook §134): extract_unit's preamble scanner reads C
  one line at a time, so every construct that WRAPS was misread.
  D1 the {-guard fired on a documentation comment mentioning a brace -> carry truncated
     mid-comment -> `parse error before 'the'`.
  D2 _def_head_at's "param list continues -> ANSI definition" fallback accepted a WRAPPED
     DECLARATION as a definition head -> a 16-line fragment with no body, closed by a brace
     pair inside a comment -> a silent 0/137 that reads exactly like a compiler wall.
  D5 the backscan met a multi-line typedef's CLOSING line `} T;` first and stopped -> the
     type never travelled -> `T undeclared` across 17 families / 24,332 templatable ins.
     (The code comment claimed they "route through the engine_types.h lift"; measured, they
     routed nowhere.)
  D4 wrapped __asm__("func_...") alias invisible to a single-line regex — MEASURED (1 exemplar,
     3,288 ins, second blocker behind it) and deliberately NOT fixed; it now returns None so the
     sweep reports a VISIBLE skip instead of 137 silent failures (R32).
- Fixes: _def_head_at(ln, idx, more=()) lookahead (no-lookahead keeps the historical answer);
  {-guard exempts comment-only lines + an R32 dangling-comment backstop; forward brace scan
  counts over cdecl._mask (R33, one masking oracle); _typedef_block_start carries whole blocks.
- BLAST RADIUS (R14): extract_unit diffed vs the pre-fix tool over all 181 zero-crack exemplars
  -> 157 byte-IDENTICAL, 24 changed, all in the intended direction.
- PAYOFF: D1+D2 +323 members from families that banked ZERO; D5 +417 incl. func_8012B77C 139/139
  (8,062 ins) and func_80128C98 137/275. S6 total 1,582 members (pre-fix tool scored 842).
- R22 clean-fleet 140/140. Fleet 94.43->94.88% fn-count, 91.4->91.9% instr, 84.0->84.6% distinct.
- TELL worth keeping (§134): bimodal bank rates (57 all / 52 zero / 8 partial) are a TOOLING
  signature, not codegen. Probe one member and read one compiler error before writing a family off.
This commit is contained in:
Drew T
2026-08-01 17:28:06 -06:00
parent 8a519addf7
commit 39558b2991
647 changed files with 40805 additions and 2169 deletions
+1209 -1217
View File
File diff suppressed because it is too large Load Diff
+6 -3
View File
@@ -2,7 +2,7 @@
> **Generated by `tools/cookbook_index.py` — do not hand-edit** (R33). Regenerate after adding a cookbook section.
>
> `docs/matching-cookbook.md` is ~716 KB / 359 sections. Grepping it blind is how three P30 wave-1 agents each "discovered" an idiom that was already written down. **Start here, then read the section.** A section appears under every symptom it addresses.
> `docs/matching-cookbook.md` is ~716 KB / 360 sections. Grepping it blind is how three P30 wave-1 agents each "discovered" an idiom that was already written down. **Start here, then read the section.** A section appears under every symptom it addresses.
**How to use:** name what you SEE in the diff (a stolen delay slot, an extra `la`, a swapped register pair, a `conflicting types` error), find that symptom below, read those sections first. If nothing fits, THEN grind — and add a section when you win.
@@ -262,7 +262,7 @@
- **§127a** — §71 (sibling-first) is the strongest `-O0` lever, and it beats the index <sub>L8370</sub>
- **§132** — The `JR-PAIR-IN-ONE-O0-OBJECT` "wall" was TWO instrument defects: a merged-double span the carve could not see, and a truncated object no rule deleted (P30 S29, `func_8013B83C` + `func_8013BD74`) <sub>L8563</sub>
### family propagation & sweeps (65)
### family propagation & sweeps (66)
- **§8d** — Templating a body INTO a TU must not CHANGE its declaration environment — demote the carried data externs (Phase 26 session 8, byte-proven on `func_8015AE2C` ×133) <sub>L483</sub>
- **§11** — Cross-binary dedup & code-sharing (Phase 11 — "one match unlocks many") <sub>L908</sub>
@@ -329,6 +329,7 @@
- **§123** — PROPAGATE A FAMILY WITH THE TOOL ITS TIER NEEDS: `dedup_propagate` is h_exact-only; its refusals are statements about the TOOL (P30 wave 1, 2026-07-30) <sub>L8109</sub>
- **§124** — A "not matched" verdict can mean the definition is there under a DIFFERENT C NAME: the asm-label alias blind spot (P30 SESSION-28, `func_8016191C` ×137) <sub>L8146</sub>
- **§124a** — a family sweep's `0 matched-exemplar families` may be a FILTER, not a wall <sub>L8191</sub>
- **§134** — MULTI-LINE BLINDNESS: one root cause, four faces, in `family_remap`'s preamble scanner (P30 S6, 190 zero-crack families) <sub>L8704</sub>
### integration / TU plumbing (32)
@@ -365,7 +366,7 @@
- **§112** — A macro-scoped declaration only collides where the macro is INSTANTIATED (Phase 29 T67/T69, `audit_header_sigs.py`) <sub>L7723</sub>
- **§114** — The THIRD decl axis: a CALLEE the draft declares differently from the target TU (Phase 29 T76/T77) <sub>L7801</sub>
### build graph, splat & the harness (89)
### build graph, splat & the harness (90)
- **§4** — Flag/toolchain gotchas <sub>L190</sub>
- **Build** — mechanism — per-file opt override (splat resegmentation) <sub>L288</sub>
@@ -456,6 +457,7 @@
- **§130** — An INCREMENTAL build can report BYTE-IDENTICAL for a change the CLEAN build cannot even LINK (P30 S28, the jr pair) <sub>L8479</sub>
- **§132** — The `JR-PAIR-IN-ONE-O0-OBJECT` "wall" was TWO instrument defects: a merged-double span the carve could not see, and a truncated object no rule deleted (P30 S29, `func_8013B83C` + `func_8013BD74`) <sub>L8563</sub>
- **§133** — The DEFAULT-FILTER class: three times in one session, a tool silently answered a narrower question than the one asked (P30 S1–S3) <sub>L8678</sub>
- **§134** — MULTI-LINE BLINDNESS: one root cause, four faces, in `family_remap`'s preamble scanner (P30 S6, 190 zero-crack families) <sub>L8704</sub>
### process, measurement & doctrine (47)
@@ -971,3 +973,4 @@
- **§132a** — `--like` is for a sibling with NO record; against one that HAS a record it over-derives (P30 S29, `ov_SC07_010`) <sub>L8628</sub>
- **§132b** — When the span's already-matched owner is ITSELF multi-switch: `--span-rel` (P30 S1, `func_8014032C`) <sub>L8653</sub>
- **§133** — The DEFAULT-FILTER class: three times in one session, a tool silently answered a narrower question than the one asked (P30 S1–S3) <sub>L8678</sub>
- **§134** — MULTI-LINE BLINDNESS: one root cause, four faces, in `family_remap`'s preamble scanner (P30 S6, 190 zero-crack families) <sub>L8704</sub>
+54
View File
@@ -8700,3 +8700,57 @@ your own filter, not the world. State the filter out loud in the same breath as
families **with ≥100 members, any size**"), and re-run once with it removed before any conclusion is
allowed to shape a plan. A number that scoped a phase deserves the same instrument-check R35 demands
of a probe.
## §134 — MULTI-LINE BLINDNESS: one root cause, four faces, in `family_remap`'s preamble scanner (P30 S6, 190 zero-crack families)
`extract_unit` builds a templatable unit by walking UP from a definition line, accepting lines that
"look like" preamble (`extern` / `//` / `/*` / `*` / `typedef` / blank). That scanner is **line-at-a-time
over a language whose constructs span lines**, and every construct that wraps was misread. Four faces,
all found in one session by probing eight zero-banked families with ONE build each (`.run/s6_diag.py`
— remap → splice → build that overlay → read the compiler's own error → revert):
| face | the construct | what the scanner concluded | the symptom, in the sibling |
|---|---|---|---|
| **D1** | a block comment containing `{` — e.g. `* => { u16, u16, s32 }` | the `{`-guard (a real T65 fix for `extern void f(int); int g(){…}` on one line) fired on *documentation* | carry stops MID-comment; the draft opens with ` * …` and an unmatched `*/` → **`parse error before 'the'`** |
| **D2** | a wrapped DECLARATION — `extern void func_801466F0(s32 a0, …,`⏎` s32 sp8);` | `_def_head_at`'s fallback: "param list continues past this line ⇒ ANSI definition" | line 457 accepted as a definition head → unit is a **16-line fragment with no body** (a neighbouring `DEFINE_func_*()`, an `#include`, a comment), closed by the `{ u16, … }` *inside that comment* → **0/137, reads as a compiler wall** |
| **D4** | a wrapped asm-label alias — `extern void aF…(…,`⏎` s32 sp8) __asm__("func_801466F0");` | `_alias_decl_for` is a single-line `rx.match` | the definition is invisible → "no matched unit" |
| **D5** | a multi-line `typedef struct {…} T;` | the backscan meets the CLOSING line `} T;` first; `}` is not an accepted prefix, so it stops | the type never travels → **`T undeclared`**, measured at **17 families / 24,332 templatable ins** |
**Why it matters more than four bugs.** D2 and D5 produce a *silent, uniform, whole-family* failure —
exactly the shape a compiler wall produces. The tell is **bimodality**: S6's first sweep banked
842/2,735, and the residue split **57 families all-banked / 52 zero / 8 partial**. Per-member codegen
residuals do not cluster like that; one per-family blocker does. **Bimodal bank rates are a
tooling signature — probe one member before writing the family off** (R35, and the fifth consecutive
"structural wall" in this project to resolve to our own instrument after §53/§124/§126/§132).
**The fixes** (all in `tools/family_remap.py`, all blast-radius-verified against the pre-fix tool by
diffing `extract_unit` output over every affected exemplar — **157 of 181 byte-identical**, the rest
changed only in the intended direction):
- `_def_head_at(ln, paren_idx, more=())` — the caller passes the following lines, so a wrapped list
closes and the same `;`-vs-`{` test answers correctly. With lookahead supplied and no close, it
returns **False** ("unknown" is not "definition"); with no lookahead it keeps the historical answer,
so un-updated callers cannot silently change behaviour.
- the `{`-guard exempts comment-only lines (`*`, `//`, or an unclosed `/*`), plus an **R32 backstop**
that drops-and-announces a preamble that still opens inside a comment.
- the forward body scan counts braces in **`cdecl._mask`ed** text (R33: one masking oracle), so a
brace inside a comment or string can never close a function body.
- `_typedef_block_start()` — on a `} T;` closing line, walk up to the matching `typedef` (both the
`typedef struct {` and brace-on-its-own-line forms) and carry the WHOLE block. Only blocks that
literally begin with `typedef` are carried: a struct VARIABLE (`struct {…} g;`) closes identically
and defining it in the sibling would be a duplicate global. Safe because `harvest_verify` already
strips a typedef the sibling TU provides (`cdecl.strip_provided_typedefs`), so a duplicate cannot
break the sibling — and the whole-binary gate remains the sole arbiter (G3/P9).
**Measured payoff, one command each:** D1+D2 recovered **+323 members** from families that had banked
**zero**; D5 then banked the 139-member `func_8012B77C` family **139/139** (8,062 ins) and took
`func_80128C98` to 137/275. S6 total: **1,582 members** off a population that the pre-fix tool scored
at 842. D4 was measured (1 exemplar / 3,288 ins, with a second blocker behind it) and deliberately left
UNFIXED — but it now returns `None`, so the sweep reports it as `skipped {'no matched unit for func'}`
rather than failing 137 times. **A known gap that announces itself is not the same defect as a silent
one** (R32).
**The general practice.** Any scanner that classifies C by reading one line at a time is wrong on
wrapped declarations, wrapped attributes/asm-labels, multi-line typedefs, and comments containing
braces — and its failures will look like walls, not bugs. Give it lookahead, mask comments/strings
before counting delimiters, and when a family banks 0/N with every member failing identically, **read
one compiler error before believing the compiler.**
+144 -144
View File
@@ -4,157 +4,157 @@
# cross-binary collapsible-byte leverage: docs/duplicates.cross.md.
# THREE progress metrics (all matter — see the labels):
FLEET fn-count byte-ident: 334873 / 353721 = 94.67% (REAL+LINKED+empties; FUNCTION-count, ×134-inflated — one crack counts per overlay)
FLEET instr-weighted : 12039773 / 13141652 = 91.6% (shipped .text across main + resident + 138 overlays; the decomp.dev-DISPLAY number)
FLEET distinct-code(uniq): 4758745 / 5634875 = 84.5% (74401/87459 unique fns; the DISTINCT-RE number)
FLEET fn-count byte-ident: 335613 / 353721 = 94.88% (REAL+LINKED+empties; FUNCTION-count, ×134-inflated — one crack counts per overlay)
FLEET instr-weighted : 12072870 / 13141652 = 91.9% (shipped .text across main + resident + 138 overlays; the decomp.dev-DISPLAY number)
FLEET distinct-code(uniq): 4767563 / 5634875 = 84.6% (74648/87459 unique fns; the DISTINCT-RE number)
MAIN game-code weighted : 436 / 60201 = 0.7% (INCLUDED in the fleet numbers above since 2026-07-22 — roadmap §1 metrics contract; LINKED-excluding Ghidra sig dated 2026-06-14; caveat is R34: no independent second oracle for a PS-X EXE, NOT drift)
(fleet EXCLUDING main, for continuity with pre-2026-07-22 readings: 12039337 / 13081451 = 92.0%)
(fleet EXCLUDING main, for continuity with pre-2026-07-22 readings: 12072434 / 13081451 = 92.3%)
FLEET REAL substantive : 333018 (of which dedup-shared 240422 via 1905 groups / 240496 instances)
FLEET REAL substantive : 333758 (of which dedup-shared 240422 via 1905 groups / 240496 instances)
FLEET LINKED PsyQ objs : 959
FLEET NON_MATCHING : 7 (0 in any default build — G4)
FLEET INCLUDE_ASM stubs : 18841
FLEET INCLUDE_ASM stubs : 18101
FLEET matchable : 353721
| binary | REAL | shared | LINKED | byte-ident | matchable | byte-ident % |
|---|---:|---:|---:|---:|---:|---:|
| main | 54 | 2 | 959 | 1055 | 2096 | 50.3% |
| resident | 129 | 0 | 0 | 131 | 145 | 90.3% |
| ov_SC01_000 | 2370 | 1748 | 0 | 2370 | 2403 | 98.6% |
| ov_SC01_001 | 2377 | 1749 | 0 | 2379 | 2466 | 96.5% |
| ov_SC01_004 | 2368 | 1740 | 0 | 2369 | 2414 | 98.1% |
| ov_SC01_005 | 2399 | 1763 | 0 | 2399 | 2503 | 95.8% |
| ov_SC01_006 | 2399 | 1763 | 0 | 2399 | 2503 | 95.8% |
| ov_SC01_008 | 2368 | 1740 | 0 | 2370 | 2426 | 97.7% |
| ov_SC01_009 | 2393 | 1741 | 0 | 2394 | 2507 | 95.5% |
| ov_SC01_074 | 2374 | 1741 | 0 | 2376 | 2425 | 98.0% |
| ov_SC01_077 | 2535 | 1707 | 0 | 2537 | 2586 | 98.1% |
| ov_SC01_080 | 2408 | 1744 | 0 | 2408 | 2512 | 95.9% |
| ov_SC01_084 | 2429 | 1749 | 0 | 2434 | 2579 | 94.4% |
| ov_SC02_000 | 2490 | 1788 | 0 | 2490 | 2683 | 92.8% |
| ov_SC02_003 | 2489 | 1788 | 0 | 2489 | 2683 | 92.8% |
| ov_SC02_004 | 2373 | 1744 | 0 | 2373 | 2401 | 98.8% |
| ov_SC02_005 | 2510 | 1740 | 0 | 2520 | 2927 | 86.1% |
| ov_SC02_011 | 2526 | 1747 | 0 | 2537 | 2893 | 87.7% |
| ov_SC02_015 | 2379 | 1746 | 0 | 2379 | 2414 | 98.6% |
| ov_SC02_016 | 2428 | 1746 | 0 | 2431 | 2545 | 95.5% |
| ov_SC02_017 | 2490 | 1746 | 0 | 2498 | 2732 | 91.4% |
| ov_SC02_021 | 2383 | 1746 | 0 | 2383 | 2437 | 97.8% |
| ov_SC02_026 | 2411 | 1744 | 0 | 2417 | 2572 | 94.0% |
| ov_SC02_027 | 2449 | 1744 | 0 | 2458 | 2692 | 91.3% |
| ov_SC02_028 | 2449 | 1744 | 0 | 2459 | 2701 | 91.0% |
| ov_SC02_031 | 2429 | 1745 | 0 | 2434 | 2562 | 95.0% |
| ov_SC02_035 | 2400 | 1744 | 0 | 2403 | 2520 | 95.4% |
| ov_SC02_039 | 2372 | 1744 | 0 | 2372 | 2416 | 98.2% |
| ov_SC02_041 | 2426 | 1744 | 0 | 2429 | 2561 | 94.8% |
| ov_SC03_001 | 2533 | 1745 | 0 | 2550 | 2869 | 88.9% |
| ov_SC03_002 | 2439 | 1749 | 0 | 2454 | 2631 | 93.3% |
| ov_SC03_003 | 2380 | 1744 | 0 | 2381 | 2423 | 98.3% |
| ov_SC03_006 | 2480 | 1750 | 0 | 2489 | 2767 | 90.0% |
| ov_SC03_007 | 2437 | 1744 | 0 | 2441 | 2623 | 93.1% |
| ov_SC03_010 | 2391 | 1744 | 0 | 2391 | 2471 | 96.8% |
| ov_SC03_011 | 2396 | 1744 | 0 | 2402 | 2527 | 95.1% |
| ov_SC03_012 | 2370 | 1744 | 0 | 2371 | 2406 | 98.5% |
| ov_SC03_013 | 2397 | 1744 | 0 | 2397 | 2493 | 96.1% |
| ov_SC03_014 | 2490 | 1772 | 0 | 2490 | 2685 | 92.7% |
| ov_SC03_015 | 2484 | 1772 | 0 | 2484 | 2685 | 92.5% |
| ov_SC03_023 | 2381 | 1744 | 0 | 2382 | 2435 | 97.8% |
| ov_SC03_024 | 2447 | 1749 | 0 | 2454 | 2641 | 92.9% |
| ov_SC03_028 | 2419 | 1744 | 0 | 2423 | 2664 | 91.0% |
| ov_SC03_029 | 2440 | 1746 | 0 | 2450 | 2644 | 92.7% |
| ov_SC03_030 | 2398 | 1749 | 0 | 2400 | 2495 | 96.2% |
| ov_SC03_031 | 2398 | 1744 | 0 | 2401 | 2514 | 95.5% |
| ov_SC03_089 | 2426 | 1749 | 0 | 2433 | 2581 | 94.3% |
| ov_SC03_090 | 2430 | 1749 | 0 | 2438 | 2625 | 92.9% |
| ov_SC03_091 | 2432 | 1744 | 0 | 2440 | 2640 | 92.4% |
| ov_SC03_092 | 2445 | 1749 | 0 | 2457 | 2587 | 95.0% |
| ov_SC03_093 | 2418 | 1744 | 0 | 2422 | 2563 | 94.5% |
| ov_SC03_094 | 2408 | 1744 | 0 | 2414 | 2577 | 93.7% |
| ov_SC03_095 | 2391 | 1744 | 0 | 2394 | 2474 | 96.8% |
| ov_SC03_096 | 2391 | 1744 | 0 | 2394 | 2465 | 97.1% |
| ov_SC03_097 | 2439 | 1744 | 0 | 2446 | 2603 | 94.0% |
| ov_SC03_098 | 2409 | 1744 | 0 | 2412 | 2541 | 94.9% |
| ov_SC03_099 | 2399 | 1744 | 0 | 2402 | 2504 | 95.9% |
| ov_SC03_100 | 2416 | 1744 | 0 | 2420 | 2539 | 95.3% |
| ov_SC03_101 | 2418 | 1749 | 0 | 2422 | 2528 | 95.8% |
| ov_SC03_102 | 2394 | 1744 | 0 | 2397 | 2492 | 96.2% |
| ov_SC03_103 | 2404 | 1746 | 0 | 2407 | 2510 | 95.9% |
| ov_SC03_104 | 2432 | 1749 | 0 | 2439 | 2616 | 93.2% |
| ov_SC03_105 | 2413 | 1744 | 0 | 2420 | 2597 | 93.2% |
| ov_SC03_108 | 2375 | 1744 | 0 | 2375 | 2443 | 97.2% |
| ov_SC03_109 | 2378 | 1744 | 0 | 2380 | 2424 | 98.2% |
| ov_SC03_110 | 2392 | 1744 | 0 | 2392 | 2468 | 96.9% |
| ov_SC03_111 | 2405 | 1744 | 0 | 2408 | 2510 | 95.9% |
| ov_SC03_112 | 2400 | 1746 | 0 | 2402 | 2526 | 95.1% |
| ov_SC03_113 | 2386 | 1746 | 0 | 2389 | 2468 | 96.8% |
| ov_SC03_114 | 2368 | 1744 | 0 | 2370 | 2415 | 98.1% |
| ov_SC03_115 | 2399 | 1744 | 0 | 2401 | 2472 | 97.1% |
| ov_SC03_116 | 2376 | 1744 | 0 | 2379 | 2438 | 97.6% |
| ov_SC03_117 | 2420 | 1744 | 0 | 2426 | 2557 | 94.9% |
| ov_SC03_118 | 2467 | 1768 | 0 | 2468 | 2685 | 91.9% |
| ov_SC03_119 | 2463 | 1768 | 0 | 2464 | 2685 | 91.8% |
| ov_SC03_121 | 2386 | 1744 | 0 | 2389 | 2459 | 97.2% |
| ov_SC03_124 | 2480 | 1740 | 0 | 2500 | 2741 | 91.2% |
| ov_SC03_125 | 2425 | 1744 | 0 | 2437 | 2588 | 94.2% |
| ov_SC03_126 | 2381 | 1746 | 0 | 2381 | 2423 | 98.3% |
| ov_SC04_000 | 2417 | 1748 | 0 | 2426 | 2546 | 95.3% |
| ov_SC04_002 | 2444 | 1744 | 0 | 2448 | 2636 | 92.9% |
| ov_SC04_003 | 2398 | 1744 | 0 | 2402 | 2502 | 96.0% |
| ov_SC04_004 | 2420 | 1744 | 0 | 2422 | 2558 | 94.7% |
| ov_SC04_005 | 2430 | 1744 | 0 | 2436 | 2612 | 93.3% |
| ov_SC04_006 | 2389 | 1744 | 0 | 2391 | 2454 | 97.4% |
| ov_SC04_007 | 2423 | 1744 | 0 | 2427 | 2569 | 94.5% |
| ov_SC04_008 | 2377 | 1744 | 0 | 2377 | 2415 | 98.4% |
| ov_SC04_009 | 2391 | 1744 | 0 | 2394 | 2441 | 98.1% |
| ov_SC04_010 | 2379 | 1744 | 0 | 2380 | 2419 | 98.4% |
| ov_SC04_011 | 2461 | 1749 | 0 | 2467 | 2803 | 88.0% |
| ov_SC04_012 | 2378 | 1744 | 0 | 2379 | 2420 | 98.3% |
| ov_SC04_015 | 2449 | 1745 | 0 | 2460 | 2611 | 94.2% |
| ov_SC04_016 | 2377 | 1744 | 0 | 2379 | 2440 | 97.5% |
| ov_SC04_018 | 2536 | 1780 | 0 | 2536 | 2857 | 88.8% |
| ov_SC04_019 | 2536 | 1780 | 0 | 2536 | 2857 | 88.8% |
| ov_SC04_020 | 2413 | 1744 | 0 | 2425 | 2567 | 94.5% |
| ov_SC04_021 | 2381 | 1746 | 0 | 2381 | 2423 | 98.3% |
| ov_SC05_000 | 2379 | 1748 | 0 | 2382 | 2422 | 98.3% |
| ov_SC05_001 | 2422 | 1744 | 0 | 2427 | 2574 | 94.3% |
| ov_SC05_002 | 2390 | 1744 | 0 | 2393 | 2442 | 98.0% |
| ov_SC05_003 | 2387 | 1744 | 0 | 2388 | 2481 | 96.3% |
| ov_SC05_004 | 2380 | 1744 | 0 | 2382 | 2464 | 96.7% |
| ov_SC05_005 | 2395 | 1749 | 0 | 2396 | 2491 | 96.2% |
| ov_SC05_006 | 2384 | 1744 | 0 | 2384 | 2430 | 98.1% |
| ov_SC05_007 | 2397 | 1744 | 0 | 2402 | 2482 | 96.8% |
| ov_SC05_008 | 2407 | 1744 | 0 | 2409 | 2543 | 94.7% |
| ov_SC05_009 | 2383 | 1744 | 0 | 2387 | 2438 | 97.9% |
| ov_SC05_010 | 2418 | 1744 | 0 | 2422 | 2588 | 93.6% |
| ov_SC05_011 | 2376 | 1744 | 0 | 2377 | 2409 | 98.7% |
| ov_SC05_017 | 2518 | 1741 | 0 | 2529 | 2842 | 89.0% |
| ov_SC05_018 | 2444 | 1744 | 0 | 2457 | 2673 | 91.9% |
| ov_SC05_019 | 2381 | 1746 | 0 | 2381 | 2423 | 98.3% |
| ov_SC06_000 | 2473 | 1753 | 0 | 2476 | 2691 | 92.0% |
| ov_SC06_006 | 2402 | 1744 | 0 | 2403 | 2511 | 95.7% |
| ov_SC06_008 | 2427 | 1746 | 0 | 2433 | 2542 | 95.7% |
| ov_SC06_010 | 2408 | 1744 | 0 | 2413 | 2517 | 95.9% |
| ov_SC06_011 | 2385 | 1744 | 0 | 2389 | 2468 | 96.8% |
| ov_SC06_013 | 2379 | 1744 | 0 | 2380 | 2425 | 98.1% |
| ov_SC06_014 | 2388 | 1744 | 0 | 2390 | 2453 | 97.4% |
| ov_SC06_015 | 2384 | 1744 | 0 | 2384 | 2421 | 98.5% |
| ov_SC06_016 | 2404 | 1744 | 0 | 2406 | 2549 | 94.4% |
| ov_SC06_018 | 2432 | 1746 | 0 | 2439 | 2665 | 91.5% |
| ov_SC06_020 | 2401 | 1746 | 0 | 2402 | 2518 | 95.4% |
| ov_SC06_022 | 2429 | 1744 | 0 | 2437 | 2642 | 92.2% |
| ov_SC06_024 | 2440 | 1744 | 0 | 2446 | 2667 | 91.7% |
| ov_SC06_025 | 2414 | 1744 | 0 | 2419 | 2572 | 94.1% |
| ov_SC06_027 | 2371 | 1744 | 0 | 2372 | 2408 | 98.5% |
| ov_SC06_029 | 2438 | 1744 | 0 | 2450 | 2662 | 92.0% |
| ov_SC06_030 | 2384 | 1744 | 0 | 2384 | 2456 | 97.1% |
| ov_SC06_032 | 2424 | 1745 | 0 | 2431 | 2658 | 91.5% |
| ov_SC06_033 | 2425 | 1745 | 0 | 2432 | 2631 | 92.4% |
| ov_SC07_000 | 2398 | 1748 | 0 | 2400 | 2521 | 95.2% |
| ov_SC07_001 | 2384 | 1744 | 0 | 2386 | 2454 | 97.2% |
| ov_SC07_002 | 2412 | 1744 | 0 | 2416 | 2579 | 93.7% |
| ov_SC07_006 | 2276 | 1560 | 0 | 2356 | 2456 | 95.9% |
| ov_SC07_007 | 2303 | 1592 | 0 | 2387 | 2613 | 91.4% |
| ov_SC07_008 | 2365 | 1744 | 0 | 2365 | 2386 | 99.1% |
| ov_SC07_009 | 2376 | 1744 | 0 | 2378 | 2430 | 97.9% |
| ov_SC07_010 | 2286 | 1614 | 0 | 2369 | 2524 | 93.9% |
| ov_SC07_011 | 2297 | 1591 | 0 | 2377 | 2449 | 97.1% |
| ov_SC01_000 | 2375 | 1748 | 0 | 2375 | 2403 | 98.8% |
| ov_SC01_001 | 2382 | 1749 | 0 | 2384 | 2466 | 96.7% |
| ov_SC01_004 | 2372 | 1740 | 0 | 2373 | 2414 | 98.3% |
| ov_SC01_005 | 2403 | 1763 | 0 | 2403 | 2503 | 96.0% |
| ov_SC01_006 | 2403 | 1763 | 0 | 2403 | 2503 | 96.0% |
| ov_SC01_008 | 2372 | 1740 | 0 | 2374 | 2426 | 97.9% |
| ov_SC01_009 | 2397 | 1741 | 0 | 2398 | 2507 | 95.7% |
| ov_SC01_074 | 2378 | 1741 | 0 | 2380 | 2425 | 98.1% |
| ov_SC01_077 | 2536 | 1707 | 0 | 2538 | 2586 | 98.1% |
| ov_SC01_080 | 2412 | 1744 | 0 | 2412 | 2512 | 96.0% |
| ov_SC01_084 | 2433 | 1749 | 0 | 2438 | 2579 | 94.5% |
| ov_SC02_000 | 2496 | 1788 | 0 | 2496 | 2683 | 93.0% |
| ov_SC02_003 | 2496 | 1788 | 0 | 2496 | 2683 | 93.0% |
| ov_SC02_004 | 2377 | 1744 | 0 | 2377 | 2401 | 99.0% |
| ov_SC02_005 | 2514 | 1740 | 0 | 2524 | 2927 | 86.2% |
| ov_SC02_011 | 2535 | 1747 | 0 | 2546 | 2893 | 88.0% |
| ov_SC02_015 | 2383 | 1746 | 0 | 2383 | 2414 | 98.7% |
| ov_SC02_016 | 2434 | 1746 | 0 | 2437 | 2545 | 95.8% |
| ov_SC02_017 | 2496 | 1746 | 0 | 2504 | 2732 | 91.7% |
| ov_SC02_021 | 2387 | 1746 | 0 | 2387 | 2437 | 97.9% |
| ov_SC02_026 | 2415 | 1744 | 0 | 2421 | 2572 | 94.1% |
| ov_SC02_027 | 2455 | 1744 | 0 | 2464 | 2692 | 91.5% |
| ov_SC02_028 | 2457 | 1744 | 0 | 2467 | 2701 | 91.3% |
| ov_SC02_031 | 2435 | 1745 | 0 | 2440 | 2562 | 95.2% |
| ov_SC02_035 | 2404 | 1744 | 0 | 2407 | 2520 | 95.5% |
| ov_SC02_039 | 2376 | 1744 | 0 | 2376 | 2416 | 98.3% |
| ov_SC02_041 | 2431 | 1744 | 0 | 2434 | 2561 | 95.0% |
| ov_SC03_001 | 2537 | 1745 | 0 | 2554 | 2869 | 89.0% |
| ov_SC03_002 | 2443 | 1749 | 0 | 2458 | 2631 | 93.4% |
| ov_SC03_003 | 2384 | 1744 | 0 | 2385 | 2423 | 98.4% |
| ov_SC03_006 | 2486 | 1750 | 0 | 2495 | 2767 | 90.2% |
| ov_SC03_007 | 2441 | 1744 | 0 | 2445 | 2623 | 93.2% |
| ov_SC03_010 | 2395 | 1744 | 0 | 2395 | 2471 | 96.9% |
| ov_SC03_011 | 2400 | 1744 | 0 | 2406 | 2527 | 95.2% |
| ov_SC03_012 | 2374 | 1744 | 0 | 2375 | 2406 | 98.7% |
| ov_SC03_013 | 2401 | 1744 | 0 | 2401 | 2493 | 96.3% |
| ov_SC03_014 | 2496 | 1772 | 0 | 2496 | 2685 | 93.0% |
| ov_SC03_015 | 2498 | 1772 | 0 | 2498 | 2685 | 93.0% |
| ov_SC03_023 | 2385 | 1744 | 0 | 2386 | 2435 | 98.0% |
| ov_SC03_024 | 2456 | 1749 | 0 | 2463 | 2641 | 93.3% |
| ov_SC03_028 | 2423 | 1744 | 0 | 2427 | 2664 | 91.1% |
| ov_SC03_029 | 2446 | 1746 | 0 | 2456 | 2644 | 92.9% |
| ov_SC03_030 | 2402 | 1749 | 0 | 2404 | 2495 | 96.4% |
| ov_SC03_031 | 2404 | 1744 | 0 | 2407 | 2514 | 95.7% |
| ov_SC03_089 | 2432 | 1749 | 0 | 2439 | 2581 | 94.5% |
| ov_SC03_090 | 2436 | 1749 | 0 | 2444 | 2625 | 93.1% |
| ov_SC03_091 | 2438 | 1744 | 0 | 2446 | 2640 | 92.7% |
| ov_SC03_092 | 2451 | 1749 | 0 | 2463 | 2587 | 95.2% |
| ov_SC03_093 | 2426 | 1744 | 0 | 2430 | 2563 | 94.8% |
| ov_SC03_094 | 2415 | 1744 | 0 | 2421 | 2577 | 93.9% |
| ov_SC03_095 | 2396 | 1744 | 0 | 2399 | 2474 | 97.0% |
| ov_SC03_096 | 2395 | 1744 | 0 | 2398 | 2465 | 97.3% |
| ov_SC03_097 | 2447 | 1744 | 0 | 2454 | 2603 | 94.3% |
| ov_SC03_098 | 2417 | 1744 | 0 | 2420 | 2541 | 95.2% |
| ov_SC03_099 | 2405 | 1744 | 0 | 2408 | 2504 | 96.2% |
| ov_SC03_100 | 2423 | 1744 | 0 | 2427 | 2539 | 95.6% |
| ov_SC03_101 | 2427 | 1749 | 0 | 2431 | 2528 | 96.2% |
| ov_SC03_102 | 2398 | 1744 | 0 | 2401 | 2492 | 96.3% |
| ov_SC03_103 | 2411 | 1746 | 0 | 2414 | 2510 | 96.2% |
| ov_SC03_104 | 2440 | 1749 | 0 | 2447 | 2616 | 93.5% |
| ov_SC03_105 | 2417 | 1744 | 0 | 2424 | 2597 | 93.3% |
| ov_SC03_108 | 2379 | 1744 | 0 | 2379 | 2443 | 97.4% |
| ov_SC03_109 | 2382 | 1744 | 0 | 2384 | 2424 | 98.3% |
| ov_SC03_110 | 2398 | 1744 | 0 | 2398 | 2468 | 97.2% |
| ov_SC03_111 | 2411 | 1744 | 0 | 2414 | 2510 | 96.2% |
| ov_SC03_112 | 2404 | 1746 | 0 | 2406 | 2526 | 95.2% |
| ov_SC03_113 | 2391 | 1746 | 0 | 2394 | 2468 | 97.0% |
| ov_SC03_114 | 2373 | 1744 | 0 | 2375 | 2415 | 98.3% |
| ov_SC03_115 | 2403 | 1744 | 0 | 2405 | 2472 | 97.3% |
| ov_SC03_116 | 2381 | 1744 | 0 | 2384 | 2438 | 97.8% |
| ov_SC03_117 | 2424 | 1744 | 0 | 2430 | 2557 | 95.0% |
| ov_SC03_118 | 2474 | 1768 | 0 | 2475 | 2685 | 92.2% |
| ov_SC03_119 | 2470 | 1768 | 0 | 2471 | 2685 | 92.0% |
| ov_SC03_121 | 2390 | 1744 | 0 | 2393 | 2459 | 97.3% |
| ov_SC03_124 | 2484 | 1740 | 0 | 2504 | 2741 | 91.4% |
| ov_SC03_125 | 2429 | 1744 | 0 | 2441 | 2588 | 94.3% |
| ov_SC03_126 | 2385 | 1746 | 0 | 2385 | 2423 | 98.4% |
| ov_SC04_000 | 2424 | 1748 | 0 | 2433 | 2546 | 95.6% |
| ov_SC04_002 | 2453 | 1744 | 0 | 2457 | 2636 | 93.2% |
| ov_SC04_003 | 2405 | 1744 | 0 | 2409 | 2502 | 96.3% |
| ov_SC04_004 | 2429 | 1744 | 0 | 2431 | 2558 | 95.0% |
| ov_SC04_005 | 2440 | 1744 | 0 | 2446 | 2612 | 93.6% |
| ov_SC04_006 | 2395 | 1744 | 0 | 2397 | 2454 | 97.7% |
| ov_SC04_007 | 2433 | 1744 | 0 | 2437 | 2569 | 94.9% |
| ov_SC04_008 | 2382 | 1744 | 0 | 2382 | 2415 | 98.6% |
| ov_SC04_009 | 2396 | 1744 | 0 | 2399 | 2441 | 98.3% |
| ov_SC04_010 | 2384 | 1744 | 0 | 2385 | 2419 | 98.6% |
| ov_SC04_011 | 2470 | 1749 | 0 | 2476 | 2803 | 88.3% |
| ov_SC04_012 | 2383 | 1744 | 0 | 2384 | 2420 | 98.5% |
| ov_SC04_015 | 2453 | 1745 | 0 | 2464 | 2611 | 94.4% |
| ov_SC04_016 | 2382 | 1744 | 0 | 2384 | 2440 | 97.7% |
| ov_SC04_018 | 2540 | 1780 | 0 | 2540 | 2857 | 88.9% |
| ov_SC04_019 | 2540 | 1780 | 0 | 2540 | 2857 | 88.9% |
| ov_SC04_020 | 2417 | 1744 | 0 | 2429 | 2567 | 94.6% |
| ov_SC04_021 | 2385 | 1746 | 0 | 2385 | 2423 | 98.4% |
| ov_SC05_000 | 2383 | 1748 | 0 | 2386 | 2422 | 98.5% |
| ov_SC05_001 | 2428 | 1744 | 0 | 2433 | 2574 | 94.5% |
| ov_SC05_002 | 2395 | 1744 | 0 | 2398 | 2442 | 98.2% |
| ov_SC05_003 | 2391 | 1744 | 0 | 2392 | 2481 | 96.4% |
| ov_SC05_004 | 2384 | 1744 | 0 | 2386 | 2464 | 96.8% |
| ov_SC05_005 | 2401 | 1749 | 0 | 2402 | 2491 | 96.4% |
| ov_SC05_006 | 2390 | 1744 | 0 | 2390 | 2430 | 98.4% |
| ov_SC05_007 | 2401 | 1744 | 0 | 2406 | 2482 | 96.9% |
| ov_SC05_008 | 2411 | 1744 | 0 | 2413 | 2543 | 94.9% |
| ov_SC05_009 | 2390 | 1744 | 0 | 2394 | 2438 | 98.2% |
| ov_SC05_010 | 2423 | 1744 | 0 | 2427 | 2588 | 93.8% |
| ov_SC05_011 | 2381 | 1744 | 0 | 2382 | 2409 | 98.9% |
| ov_SC05_017 | 2522 | 1741 | 0 | 2533 | 2842 | 89.1% |
| ov_SC05_018 | 2448 | 1744 | 0 | 2461 | 2673 | 92.1% |
| ov_SC05_019 | 2385 | 1746 | 0 | 2385 | 2423 | 98.4% |
| ov_SC06_000 | 2483 | 1753 | 0 | 2486 | 2691 | 92.4% |
| ov_SC06_006 | 2407 | 1744 | 0 | 2408 | 2511 | 95.9% |
| ov_SC06_008 | 2431 | 1746 | 0 | 2437 | 2542 | 95.9% |
| ov_SC06_010 | 2412 | 1744 | 0 | 2417 | 2517 | 96.0% |
| ov_SC06_011 | 2394 | 1744 | 0 | 2398 | 2468 | 97.2% |
| ov_SC06_013 | 2385 | 1744 | 0 | 2386 | 2425 | 98.4% |
| ov_SC06_014 | 2394 | 1744 | 0 | 2396 | 2453 | 97.7% |
| ov_SC06_015 | 2389 | 1744 | 0 | 2389 | 2421 | 98.7% |
| ov_SC06_016 | 2411 | 1744 | 0 | 2413 | 2549 | 94.7% |
| ov_SC06_018 | 2437 | 1746 | 0 | 2444 | 2665 | 91.7% |
| ov_SC06_020 | 2406 | 1746 | 0 | 2407 | 2518 | 95.6% |
| ov_SC06_022 | 2434 | 1744 | 0 | 2442 | 2642 | 92.4% |
| ov_SC06_024 | 2445 | 1744 | 0 | 2451 | 2667 | 91.9% |
| ov_SC06_025 | 2418 | 1744 | 0 | 2423 | 2572 | 94.2% |
| ov_SC06_027 | 2375 | 1744 | 0 | 2376 | 2408 | 98.7% |
| ov_SC06_029 | 2442 | 1744 | 0 | 2454 | 2662 | 92.2% |
| ov_SC06_030 | 2388 | 1744 | 0 | 2388 | 2456 | 97.2% |
| ov_SC06_032 | 2430 | 1745 | 0 | 2437 | 2658 | 91.7% |
| ov_SC06_033 | 2430 | 1745 | 0 | 2437 | 2631 | 92.6% |
| ov_SC07_000 | 2404 | 1748 | 0 | 2406 | 2521 | 95.4% |
| ov_SC07_001 | 2388 | 1744 | 0 | 2390 | 2454 | 97.4% |
| ov_SC07_002 | 2418 | 1744 | 0 | 2422 | 2579 | 93.9% |
| ov_SC07_006 | 2280 | 1560 | 0 | 2360 | 2456 | 96.1% |
| ov_SC07_007 | 2308 | 1592 | 0 | 2392 | 2613 | 91.5% |
| ov_SC07_008 | 2370 | 1744 | 0 | 2370 | 2386 | 99.3% |
| ov_SC07_009 | 2380 | 1744 | 0 | 2382 | 2430 | 98.0% |
| ov_SC07_010 | 2292 | 1614 | 0 | 2375 | 2524 | 94.1% |
| ov_SC07_011 | 2303 | 1591 | 0 | 2383 | 2449 | 97.3% |
+35
View File
@@ -559,6 +559,41 @@ one is a genuine byte DIFF.** Two are proven defects in `tools/family_remap.py`,
`_def_head_at('extern void func_801466F0(s32 a0, s32 a1, s32 a2, s32 a3,', idx) -> True`.
This is the §110/R35 class again — a silent 0/137 wearing a compiler wall's clothes.
**S6b — the fix belongs in the TOOL, not in 17 exemplars (R33).** The plan was to hand-move each
MISSING-TYPE exemplar's typedef into its function body (§100, byte-neutral, 17 edits + 17 verifications).
Probing the class first showed it is the SAME root cause as D1/D2 — a multi-line construct read one line
at a time — so it was fixed once, in `family_remap`, for every future family instead:
- **D5 — `_typedef_block_start()`**: on a `} T;` closing line, walk up to the matching `typedef` (both
the `typedef struct {` and brace-on-its-own-line forms) and carry the WHOLE block. Only blocks that
literally begin with `typedef` are carried (a struct VARIABLE closes identically but would be a
duplicate global in the sibling); safe because `harvest_verify` already strips a typedef the sibling
TU provides. The old code comment claimed these functions "route through the engine_types.h lift" —
measured, they routed **nowhere**: 17 families / 24,332 ins were simply dropped.
- **D4 — the wrapped asm-label alias** (`_alias_decl_for` is a single-line `rx.match`) was MEASURED
(1 exemplar, `0x801466f0`, 137 members / 3,288 ins, with a second blocker behind it) and deliberately
**left unfixed**. It now returns `None`, so the sweep reports `skipped {'no matched unit for func'}`
instead of failing 137 times. **A known gap that announces itself is not the same defect as a silent
one** (R32).
- Also hardened: the forward body scan now counts braces in `cdecl._mask`ed text (R33 — one masking
oracle), so a brace inside a comment or string can never close a function body.
**Blast radius verified, not assumed (R14):** `extract_unit` output diffed against the pre-S6 tool over
all 181 zero-crack exemplars — **157 byte-IDENTICAL**, 24 changed, every change in the intended
direction (more preamble carried; one → `None`, the D4 case that previously produced garbage).
**Measured payoff of the repairs, one sweep each:**
· D1+D2 → **+323 members** recovered from families that had banked **zero**.
· D5 → **+417 members**, including `func_8012B77C` **139/139** (8,062 ins — the head prize) and
`func_80128C98` 137/275; `func_80146AFC` 135/137, `func_80176144` 99/137.
· **S6 total: 1,582 member-matches.** The pre-fix tool scored this same population at 842.
**R22 clean-fleet `make clean` + extract-all + check-all → 140 passed, 0 failed of 140.**
Fleet **94.43→94.88% fn-count · 91.4→91.9% instr · 84.0→84.6% distinct**; phase arc from open
(92.00 / 87.5 / 78.0) = **+2.88pp fn · +4.4pp instr · +6.6pp distinct**.
**Family state now: 70 ALL-banked · 17 partial · 94 zero-banked; 64,050 templatable ins still open.**
Distilled to **cookbook §134** (the MULTI-LINE BLINDNESS class + the bimodality tell: 57/52/8 is a
tooling signature, not a codegen one — read ONE compiler error before believing the compiler).
### ✅ S3 — the close=0 stored-draft DIAGNOSTIC pass: measured, classified, and correctly NOT scaled (2026-08-01)
Chartered as "classify, and only build a fix if ≥3 share a named class". Ran exactly that; the answer
is that no cheap shared class exists, so nothing was scaled. **The population is bigger than the plan
+21 -1
View File
@@ -385,7 +385,27 @@ void func_80128AF4(void) {
DEFINE_func_80128C14() /* dedup: shared engine-core @0x80128C14 (src/shared) */
INCLUDE_ASM("asm/ov_SC01_000/nonmatchings/ov_SC01_000", func_80128C98);
typedef struct {
s32 word0;
s32 word4;
} CdFileLoc_80128C98;
extern CdFileLoc_80128C98 cdFileLocTable[];
extern void func_8001ABBC(s32 a0, s32 a1, void *a2, s32 a3, s32 a4);
s32 func_80128C98(s32 arg0) {
extern s16 D_8017EEB8[];
s16 idx = D_8017EEB8[arg0];
if (idx >= 0) {
func_8001ABBC(0, 0, (u8 *)&cdFileLocTable[idx], D_801A3234, 0);
} else {
return 1;
}
}
INCLUDE_ASM("asm/ov_SC01_000/nonmatchings/ov_SC01_000", func_80128CFC);
+78 -1
View File
@@ -479,7 +479,84 @@ INCLUDE_ASM("asm/ov_SC01_000/nonmatchings/ov_SC01_000_after", func_80146A6C);
DEFINE_func_80146AB4() /* dedup: shared engine-core @0x80146AB4 (src/shared) */
INCLUDE_ASM("asm/ov_SC01_000/nonmatchings/ov_SC01_000_after", func_80146AFC);
extern s32 func_80146B9C(void * arg0);
/* func_80146AFC — ASCENDING twin of the byte-proven DEFINE_func_80146B9C()
* in src/shared/engine_core.h (cookbook §71: find the already-matched sibling first).
* Same 0x58-stride slot table (base D_8011D030), same 7-store copy body in the same
* order, same $a2/$a1 giv pair. 80146B9C walks DOWN; this one walks UP, so the guard
* is `p < end`, end = p + 0xA50 (30 slots x 0x58).
*
* DECAY ROOT CAUSE (this redraft): the stored backlog draft had been rewritten to
* `void func_80146AFC(...)`, which drops BOTH `return 0` paths' `addu $v0,$zero,$zero`
* and the hit path's `j .L80146B94` => LENGTH-DRIFT -2 (38 vs 40) plus $v0/$v1 regalloc
* drift on the final lw/sw pair. Restoring the s32 return type (the fleet spelling the
* banked sibling func_80146B9C already uses) restores MATCH at 40/40.
*
* RECONCILE (2026-08-01) — the whole-binary gate failed with
* ov_SC01_077_after.c:592: conflicting types for `D_8011D030' (previous decl :564)
* TWO file-scope collisions were present; both are fixed HERE, with NO edit to
* src/shared/engine_core.h and NO change to the generated code (re-verified MATCH
* after each step):
*
* 1. D_8011D030 (the reported one). DEFINE_func_801469C8() emits
* `extern s32 D_8011D030;` at FILE scope (engine_core.h:10811, above the
* `s32 func_801469C8(...) {` line), and this TU expands that macro at :564 —
extern s32 D_8011D030;
* i.e. before the splice point :570. The draft's `extern u16` therefore
* redeclared it incompatibly at :592. Conformed to the TU's `extern s32`.
* Codegen-neutral: the sole use is `(u8 *)&D_8011D030`, an address-of, so the
* declared object type never reaches a load/store width (cookbook §20).
*
* 2. func_80146AFC ITSELF (latent, would have surfaced next). DEFINE_func_8014C010()
* (:13510) and DEFINE_func_8014AD30() (:13524) each emit a file-scope
* `extern void func_80146AFC(void *a0);`, and this TU expands them at :1386 and
* :1541 — after the splice — so an `s32 func_80146AFC` definition collides on the
* RETURN axis. Fixed with the §37/§124 ASM-LABEL ALIAS: the C identifier is
* aF80146AFC, the emitted label is func_80146AFC, so the canonical void decl and
* this s32 definition never share a namespace. Callers discard the result, so the
* void-typed call sites stay codegen-identical.
*
* Both were reproduced and then cleared against the real cpp+cc1-2.7.2 pair using a
* synthetic copy of this TU's declaration environment (.run/uc2/_recon_probe_80146AFC.c):
* the pre-reconcile spelling emits exactly the gate's error pair; the spelling below
* compiles clean.
*
* ORACLE: tools/match_one.py func_80146AFC --c .run/uc2/func_80146AFC.c
* --asm-subdir asm/ov_SC01_077/nonmatchings/ov_SC01_077_after -> MATCH (40 ins)
*/
s32 aF80146AFC(void *arg0) __asm__("func_80146AFC");
s32 aF80146AFC(void *arg0)
{
register u8 *p __asm__("$6");
register u8 *q __asm__("$5");
u8 *end;
p = (u8 *)&D_8011D030;
end = p + 0xA50;
if ((u32)p < (u32)end) {
q = p + 0x30;
do {
if (*(u16 *)p == 0) {
*(s32 *)(q + 0x4) = *(s32 *)((u8 *)arg0 + 0x8);
*(s16 *)p = *(u16 *)((u8 *)arg0 + 0x0);
*(s16 *)(q - 0x2A) = *(u16 *)((u8 *)arg0 + 0x2);
*(s16 *)(q - 0x26) = *(u16 *)((u8 *)arg0 + 0x4);
*(s16 *)(q - 0x22) = *(u16 *)((u8 *)arg0 + 0x6);
*(s32 *)(q - 0x4) = *(s32 *)((u8 *)arg0 + 0xC);
*(s32 *)(q + 0x0) = *(s32 *)((u8 *)arg0 + 0x10);
return (s32)p;
}
p += 0x58;
q += 0x58;
} while ((u32)p < (u32)end);
}
return 0;
}
DEFINE_func_80146B9C() /* dedup: shared engine-core @0x80146B9C (src/shared) */
+49 -1
View File
@@ -327,7 +327,55 @@ DEFINE_func_8012B70C() /* dedup: shared engine-core @0x8012B70C (src/shared) */
DEFINE_func_8012B744() /* dedup: shared engine-core @0x8012B744 (src/shared) */
INCLUDE_ASM("asm/ov_SC01_000/nonmatchings/ov_SC01_000_jr_8012ACE0", func_8012B77C);
extern s32 ratan2(s32 a0, s32 a1);
extern s32 func_80047948(s32 a0); /* rsin-like: angle (0..0xFFF) -> 1.12 fixed */
extern s32 func_8004787C(s32 a0); /* rcos-like: angle (0..0xFFF) -> 1.12 fixed */
/* The 4-byte destination is a PACKED PAIR of angles held entirely in ONE saved register
* ($s4) across all three calls — that is what produces the target's
* andi $s4,$s4,0xFFFF (read of the still-uninitialized local, hoisted into the prologue)
* ... or $s4,$s4,ang<<16 -> t.hi = yaw
* ... and $s4,$s4,0xFFFF0000 / or $s4,$s4,ang&0xFFFF -> t.lo = pitch
* A `struct { s16 lo, hi; }` has align 2 -> BLKmode-ish handling: gcc spills it to the stack
* and stores it with lwl/lwr + swl/swr (54 ins, 53 mismatched). Two 16-bit BITFIELDS in a
* u32 container give the SImode, align-4 struct gcc keeps in a register. */
typedef struct {
u32 lo : 16;
u32 hi : 16;
} Ang2_8012B77C_8012B77C;
/* a0 = destination packed-angle word, a1 = "from" entity, a2 = "to" entity.
* Both entities carry 16.16 fixed-point x/y/z at +0/+4/+8; the s16 reads at +2/+6/+0xA are
* the integer halves. Returns the destination pointer — the return value is REAL: without it
* gcc stores with `sw $s4,0($s3)` (57 ins) instead of the target's
* addu $v0,$s3,$zero ; sw $s4,0($v0) (the return-value copy that the store's base coalesces onto).
* The flattened `dz` reuse at the end is also load-bearing: making the (dz*sin + dx*cos)>>12
* temp its OWN variable gives it $a1 for the whole chain; reusing `dz` extends that allocno so
* it lands in $s5 exactly as the target does (`sra $s5,$v0,12` / `negu $a1,$s5`), and it also
* demotes dz's priority so the saved-reg order comes out $s3=out, $s4=t, $s5=dz. */
s32 func_8012B77C(s32 out, s32 from, s32 to) {
Ang2_8012B77C_8012B77C t;
s32 dx, dy, dz;
s32 ang;
s32 r1, r2;
dz = *(s16 *)(to + 0xA) - *(s16 *)(from + 0xA);
dx = *(s16 *)(to + 0x2) - *(s16 *)(from + 0x2);
dy = *(s16 *)(to + 0x6) - *(s16 *)(from + 0x6);
ang = (ratan2(-dz, dx) - 0x400) & 0xFFF;
t.hi = ang;
r1 = func_80047948(ang);
r2 = func_8004787C(ang);
dz = (dz * r1 + dx * r2) >> 12;
t.lo = ratan2(dy, -dz);
*(Ang2_8012B77C_8012B77C *)out = t;
return out;
}
DEFINE_func_8012B864() /* dedup: shared engine-core @0x8012B864 (src/shared) */
+74 -1
View File
@@ -3222,7 +3222,80 @@ void func_80175DA8(param_1)
}
INCLUDE_ASM("asm/ov_SC01_000/nonmatchings/ov_SC01_000_jr_801734BC", func_80176144);
/* func_80176144 — RECONCILED variant of .run/uc/func_80176144.c
*
* GATE BLOCKER (whole-binary build, NOT match_one):
* src/ov_SC01_077/ov_SC01_077_jr_801734BC.c:3476: conflicting types for `D_800AF634'
* || previous declaration at :3296
*
* ROOT CAUSE — a HOISTED file-scope typedef, not a bad signature:
* That TU hoists, at FILE scope, for func_80175DA8:
* :3295 typedef struct { s32 g0; s32 pad[2]; } S_AF634_80176144;
* :3296 extern S_AF634_80176144 D_800AF634[];
* :3297 extern S_AF634_80176144 D_800AF638[];
* The stored draft re-declares the SAME struct shape as a BLOCK-scope typedef
* (rule D — it must travel to the 137 sibling overlays, which have no such
* preamble). A block-scope `typedef struct {...} S_AF634_80176144;` is a DISTINCT type
* from the file-scope one (C has no structural typing), so the block-scope
* `extern S_AF634_80176144 D_800AF634[];` re-declares the symbol incompatibly with the
* in-scope file-scope decl -> hard error.
* Note the earlier block-scope copies in the same TU (:3080 func_80175820,
* :3123 func_801759D8) do NOT error: they precede :3296, so no file-scope decl
* of D_800AF634 is in scope there. Anything AFTER :3296 collides. Our
* definition lands at :3476. That is why only this one fired.
*
* FIX — §37/§124 ASM-LABEL ALIAS applied to the DATA symbols (cookbook §2516:
* "asm-label alias for sibling-decl signedness/proto conflicts ... beats
* reconcile's *(u16*)&D_x cast whose address-of PERTURBS regalloc"):
* the two objects are reached through PRIVATE C identifiers aAF634 / aAF638
* carrying __asm__("D_800AF634") / __asm__("D_800AF638"). The emitted
* %hi/%lo relocations are against the same symbols, so codegen is unchanged,
* while the C names can never collide with ANY sibling TU's declaration —
* whether hoisted, block-scope, or absent. No header edit; no src/ edit.
* Strictly better than deleting the local decls (which would bind this
* exemplar to the one TU that happens to hoist them).
*
* The s32 parameter + explicit (s16) narrowing is retained from the stored draft
* (canonical decl in engine_core.h:18985/:4587 is `void func_80176144(s32)`;
* the K&R short param would itself be a conflicting-types error). The (s16)
* narrowing IS the entry `sll $s0,$a0,16 / sra $s0,$s0,16` pair.
*
* Verified: python3 tools/match_one.py func_80176144 --c .run/uc2/func_80176144.c
* --asm-subdir ov_SC01_077/nonmatchings/ov_SC01_077_jr_801734BC -> MATCH (53 ins)
*/
void func_80176144(s32 a0)
{
typedef struct { s32 g0; s32 pad[2]; } S_AF634_80176144; /* size 0x0C */
/* §37 asm-label alias: private C names, canonical relocations. */
extern S_AF634_80176144 aAF634[] __asm__("D_800AF634");
extern S_AF634_80176144 aAF638[] __asm__("D_800AF638");
extern u8 D_8011F7A8;
extern s16 D_8011F7BC;
extern s16 D_8011F7BE;
extern s32 func_80178004(s32 a0, s32 a1, s32 a2);
u32 *slot;
u32 *p;
s16 param_1 = (s16)a0;
p = (u32 *)(aAF638[param_1].g0 + aAF634[param_1].g0 * 4);
slot = (u32 *)(param_1 * 4 + (s32)&D_8011F7A8);
slot[14] = (u32)p;
/* §5a zero-byte sched fence: without it sched1 hoists the two %hi/lhu global
argument loads above the `sw` of slot[14] (16 mismatches, 0 length drift). */
__asm__("");
p = (u32 *)func_80178004((s32)p,
(s16)((*(u16 *)&D_8011F7BC) - 0x17),
(s16)((*(u16 *)&D_8011F7BE) + 0x65));
slot[16] = (u32)p - 0x14;
p += 5;
aAF634[param_1].g0 += ((s32)p - (s32)slot[14]) >> 2;
}
// @class: regalloc-order
+26 -2
View File
@@ -52,7 +52,6 @@ extern s32 func_80165A50(s32);
extern void func_80029514(s32);
extern u8 D_800AF630[];
extern u8 D_80078EC0;
extern s32 D_80126B58;
extern s32 func_80028FBC(void);
extern s32 func_80029000(void);
extern s32 func_80028D9C(void);
@@ -3243,7 +3242,32 @@ void func_8017D1B4(void *a0) {
}
INCLUDE_ASM("asm/ov_SC01_000/nonmatchings/ov_SC01_000_jr_8017BEBC", func_8017D1F0);
/* 8 bytes, align 2 -> lwl/lwr/swl/swr copy (cookbook §48-C2) */
typedef struct {
s16 v[4];
} Blk8_80126940_8017D1F0;
extern u16 func_80148800(s32 *a0);
extern void func_8017D290(s32 param_1, s16 *param_2);
void func_8017D1F0(s32 a0) {
extern s32 D_80126B58;
extern s16 D_801826B0[];
extern Blk8_80126940_8017D1F0 D_80126940;
Blk8_80126940_8017D1F0 sp10;
u8 t;
if (func_80148800(&D_80126B58) & 3) {
t = (*(u8 *)(a0 + 5) + 1) & 1;
*(u8 *)(a0 + 5) = t;
*(s32 *)(a0 + 0x14) = D_801826B0[t];
}
sp10 = D_80126940;
func_8017D290(a0, sp10.v);
}
// @class: schedule
+21 -1
View File
@@ -387,7 +387,27 @@ void func_80128AF4(void) {
DEFINE_func_80128C14() /* dedup: shared engine-core @0x80128C14 (src/shared) */
INCLUDE_ASM("asm/ov_SC01_001/nonmatchings/ov_SC01_001", func_80128C98);
typedef struct {
s32 word0;
s32 word4;
} CdFileLoc_80128C98;
extern CdFileLoc_80128C98 cdFileLocTable[];
extern void func_8001ABBC(s32 a0, s32 a1, void *a2, s32 a3, s32 a4);
s32 func_80128C98(s32 arg0) {
extern s16 D_80183B08[];
s16 idx = D_80183B08[arg0];
if (idx >= 0) {
func_8001ABBC(0, 0, (u8 *)&cdFileLocTable[idx], D_801EB30C, 0);
} else {
return 1;
}
}
INCLUDE_ASM("asm/ov_SC01_001/nonmatchings/ov_SC01_001", func_80128CFC);
+78 -1
View File
@@ -479,7 +479,84 @@ INCLUDE_ASM("asm/ov_SC01_001/nonmatchings/ov_SC01_001_after", func_80146A6C);
DEFINE_func_80146AB4() /* dedup: shared engine-core @0x80146AB4 (src/shared) */
INCLUDE_ASM("asm/ov_SC01_001/nonmatchings/ov_SC01_001_after", func_80146AFC);
extern s32 func_80146B9C(void * arg0);
/* func_80146AFC — ASCENDING twin of the byte-proven DEFINE_func_80146B9C()
* in src/shared/engine_core.h (cookbook §71: find the already-matched sibling first).
* Same 0x58-stride slot table (base D_8011D030), same 7-store copy body in the same
* order, same $a2/$a1 giv pair. 80146B9C walks DOWN; this one walks UP, so the guard
* is `p < end`, end = p + 0xA50 (30 slots x 0x58).
*
* DECAY ROOT CAUSE (this redraft): the stored backlog draft had been rewritten to
* `void func_80146AFC(...)`, which drops BOTH `return 0` paths' `addu $v0,$zero,$zero`
* and the hit path's `j .L80146B94` => LENGTH-DRIFT -2 (38 vs 40) plus $v0/$v1 regalloc
* drift on the final lw/sw pair. Restoring the s32 return type (the fleet spelling the
* banked sibling func_80146B9C already uses) restores MATCH at 40/40.
*
* RECONCILE (2026-08-01) — the whole-binary gate failed with
* ov_SC01_077_after.c:592: conflicting types for `D_8011D030' (previous decl :564)
* TWO file-scope collisions were present; both are fixed HERE, with NO edit to
* src/shared/engine_core.h and NO change to the generated code (re-verified MATCH
* after each step):
*
* 1. D_8011D030 (the reported one). DEFINE_func_801469C8() emits
* `extern s32 D_8011D030;` at FILE scope (engine_core.h:10811, above the
* `s32 func_801469C8(...) {` line), and this TU expands that macro at :564 —
extern s32 D_8011D030;
* i.e. before the splice point :570. The draft's `extern u16` therefore
* redeclared it incompatibly at :592. Conformed to the TU's `extern s32`.
* Codegen-neutral: the sole use is `(u8 *)&D_8011D030`, an address-of, so the
* declared object type never reaches a load/store width (cookbook §20).
*
* 2. func_80146AFC ITSELF (latent, would have surfaced next). DEFINE_func_8014C010()
* (:13510) and DEFINE_func_8014AD30() (:13524) each emit a file-scope
* `extern void func_80146AFC(void *a0);`, and this TU expands them at :1386 and
* :1541 — after the splice — so an `s32 func_80146AFC` definition collides on the
* RETURN axis. Fixed with the §37/§124 ASM-LABEL ALIAS: the C identifier is
* aF80146AFC, the emitted label is func_80146AFC, so the canonical void decl and
* this s32 definition never share a namespace. Callers discard the result, so the
* void-typed call sites stay codegen-identical.
*
* Both were reproduced and then cleared against the real cpp+cc1-2.7.2 pair using a
* synthetic copy of this TU's declaration environment (.run/uc2/_recon_probe_80146AFC.c):
* the pre-reconcile spelling emits exactly the gate's error pair; the spelling below
* compiles clean.
*
* ORACLE: tools/match_one.py func_80146AFC --c .run/uc2/func_80146AFC.c
* --asm-subdir asm/ov_SC01_077/nonmatchings/ov_SC01_077_after -> MATCH (40 ins)
*/
s32 aF80146AFC(void *arg0) __asm__("func_80146AFC");
s32 aF80146AFC(void *arg0)
{
register u8 *p __asm__("$6");
register u8 *q __asm__("$5");
u8 *end;
p = (u8 *)&D_8011D030;
end = p + 0xA50;
if ((u32)p < (u32)end) {
q = p + 0x30;
do {
if (*(u16 *)p == 0) {
*(s32 *)(q + 0x4) = *(s32 *)((u8 *)arg0 + 0x8);
*(s16 *)p = *(u16 *)((u8 *)arg0 + 0x0);
*(s16 *)(q - 0x2A) = *(u16 *)((u8 *)arg0 + 0x2);
*(s16 *)(q - 0x26) = *(u16 *)((u8 *)arg0 + 0x4);
*(s16 *)(q - 0x22) = *(u16 *)((u8 *)arg0 + 0x6);
*(s32 *)(q - 0x4) = *(s32 *)((u8 *)arg0 + 0xC);
*(s32 *)(q + 0x0) = *(s32 *)((u8 *)arg0 + 0x10);
return (s32)p;
}
p += 0x58;
q += 0x58;
} while ((u32)p < (u32)end);
}
return 0;
}
DEFINE_func_80146B9C() /* dedup: shared engine-core @0x80146B9C (src/shared) */
+49 -1
View File
@@ -327,7 +327,55 @@ DEFINE_func_8012B70C() /* dedup: shared engine-core @0x8012B70C (src/shared) */
DEFINE_func_8012B744() /* dedup: shared engine-core @0x8012B744 (src/shared) */
INCLUDE_ASM("asm/ov_SC01_001/nonmatchings/ov_SC01_001_jr_8012ACE0", func_8012B77C);
extern s32 ratan2(s32 a0, s32 a1);
extern s32 func_80047948(s32 a0); /* rsin-like: angle (0..0xFFF) -> 1.12 fixed */
extern s32 func_8004787C(s32 a0); /* rcos-like: angle (0..0xFFF) -> 1.12 fixed */
/* The 4-byte destination is a PACKED PAIR of angles held entirely in ONE saved register
* ($s4) across all three calls — that is what produces the target's
* andi $s4,$s4,0xFFFF (read of the still-uninitialized local, hoisted into the prologue)
* ... or $s4,$s4,ang<<16 -> t.hi = yaw
* ... and $s4,$s4,0xFFFF0000 / or $s4,$s4,ang&0xFFFF -> t.lo = pitch
* A `struct { s16 lo, hi; }` has align 2 -> BLKmode-ish handling: gcc spills it to the stack
* and stores it with lwl/lwr + swl/swr (54 ins, 53 mismatched). Two 16-bit BITFIELDS in a
* u32 container give the SImode, align-4 struct gcc keeps in a register. */
typedef struct {
u32 lo : 16;
u32 hi : 16;
} Ang2_8012B77C_8012B77C;
/* a0 = destination packed-angle word, a1 = "from" entity, a2 = "to" entity.
* Both entities carry 16.16 fixed-point x/y/z at +0/+4/+8; the s16 reads at +2/+6/+0xA are
* the integer halves. Returns the destination pointer — the return value is REAL: without it
* gcc stores with `sw $s4,0($s3)` (57 ins) instead of the target's
* addu $v0,$s3,$zero ; sw $s4,0($v0) (the return-value copy that the store's base coalesces onto).
* The flattened `dz` reuse at the end is also load-bearing: making the (dz*sin + dx*cos)>>12
* temp its OWN variable gives it $a1 for the whole chain; reusing `dz` extends that allocno so
* it lands in $s5 exactly as the target does (`sra $s5,$v0,12` / `negu $a1,$s5`), and it also
* demotes dz's priority so the saved-reg order comes out $s3=out, $s4=t, $s5=dz. */
s32 func_8012B77C(s32 out, s32 from, s32 to) {
Ang2_8012B77C_8012B77C t;
s32 dx, dy, dz;
s32 ang;
s32 r1, r2;
dz = *(s16 *)(to + 0xA) - *(s16 *)(from + 0xA);
dx = *(s16 *)(to + 0x2) - *(s16 *)(from + 0x2);
dy = *(s16 *)(to + 0x6) - *(s16 *)(from + 0x6);
ang = (ratan2(-dz, dx) - 0x400) & 0xFFF;
t.hi = ang;
r1 = func_80047948(ang);
r2 = func_8004787C(ang);
dz = (dz * r1 + dx * r2) >> 12;
t.lo = ratan2(dy, -dz);
*(Ang2_8012B77C_8012B77C *)out = t;
return out;
}
DEFINE_func_8012B864() /* dedup: shared engine-core @0x8012B864 (src/shared) */
+74 -1
View File
@@ -3172,7 +3172,80 @@ void func_80175DA8(param_1)
}
INCLUDE_ASM("asm/ov_SC01_001/nonmatchings/ov_SC01_001_jr_801734BC", func_80176144);
/* func_80176144 — RECONCILED variant of .run/uc/func_80176144.c
*
* GATE BLOCKER (whole-binary build, NOT match_one):
* src/ov_SC01_077/ov_SC01_077_jr_801734BC.c:3476: conflicting types for `D_800AF634'
* || previous declaration at :3296
*
* ROOT CAUSE — a HOISTED file-scope typedef, not a bad signature:
* That TU hoists, at FILE scope, for func_80175DA8:
* :3295 typedef struct { s32 g0; s32 pad[2]; } S_AF634_80176144;
* :3296 extern S_AF634_80176144 D_800AF634[];
* :3297 extern S_AF634_80176144 D_800AF638[];
* The stored draft re-declares the SAME struct shape as a BLOCK-scope typedef
* (rule D — it must travel to the 137 sibling overlays, which have no such
* preamble). A block-scope `typedef struct {...} S_AF634_80176144;` is a DISTINCT type
* from the file-scope one (C has no structural typing), so the block-scope
* `extern S_AF634_80176144 D_800AF634[];` re-declares the symbol incompatibly with the
* in-scope file-scope decl -> hard error.
* Note the earlier block-scope copies in the same TU (:3080 func_80175820,
* :3123 func_801759D8) do NOT error: they precede :3296, so no file-scope decl
* of D_800AF634 is in scope there. Anything AFTER :3296 collides. Our
* definition lands at :3476. That is why only this one fired.
*
* FIX — §37/§124 ASM-LABEL ALIAS applied to the DATA symbols (cookbook §2516:
* "asm-label alias for sibling-decl signedness/proto conflicts ... beats
* reconcile's *(u16*)&D_x cast whose address-of PERTURBS regalloc"):
* the two objects are reached through PRIVATE C identifiers aAF634 / aAF638
* carrying __asm__("D_800AF634") / __asm__("D_800AF638"). The emitted
* %hi/%lo relocations are against the same symbols, so codegen is unchanged,
* while the C names can never collide with ANY sibling TU's declaration —
* whether hoisted, block-scope, or absent. No header edit; no src/ edit.
* Strictly better than deleting the local decls (which would bind this
* exemplar to the one TU that happens to hoist them).
*
* The s32 parameter + explicit (s16) narrowing is retained from the stored draft
* (canonical decl in engine_core.h:18985/:4587 is `void func_80176144(s32)`;
* the K&R short param would itself be a conflicting-types error). The (s16)
* narrowing IS the entry `sll $s0,$a0,16 / sra $s0,$s0,16` pair.
*
* Verified: python3 tools/match_one.py func_80176144 --c .run/uc2/func_80176144.c
* --asm-subdir ov_SC01_077/nonmatchings/ov_SC01_077_jr_801734BC -> MATCH (53 ins)
*/
void func_80176144(s32 a0)
{
typedef struct { s32 g0; s32 pad[2]; } S_AF634_80176144; /* size 0x0C */
/* §37 asm-label alias: private C names, canonical relocations. */
extern S_AF634_80176144 aAF634[] __asm__("D_800AF634");
extern S_AF634_80176144 aAF638[] __asm__("D_800AF638");
extern u8 D_8011F7A8;
extern s16 D_8011F7BC;
extern s16 D_8011F7BE;
extern s32 func_80178004(s32 a0, s32 a1, s32 a2);
u32 *slot;
u32 *p;
s16 param_1 = (s16)a0;
p = (u32 *)(aAF638[param_1].g0 + aAF634[param_1].g0 * 4);
slot = (u32 *)(param_1 * 4 + (s32)&D_8011F7A8);
slot[14] = (u32)p;
/* §5a zero-byte sched fence: without it sched1 hoists the two %hi/lhu global
argument loads above the `sw` of slot[14] (16 mismatches, 0 length drift). */
__asm__("");
p = (u32 *)func_80178004((s32)p,
(s16)((*(u16 *)&D_8011F7BC) - 0x17),
(s16)((*(u16 *)&D_8011F7BE) + 0x65));
slot[16] = (u32)p - 0x14;
p += 5;
aAF634[param_1].g0 += ((s32)p - (s32)slot[14]) >> 2;
}
// @class: regalloc-order
+26 -2
View File
@@ -52,7 +52,6 @@ extern s32 func_80165A50(s32);
extern void func_80029514(s32);
extern u8 D_800AF630[];
extern u8 D_80078EC0;
extern s32 D_80126B58;
extern s32 func_80028FBC(void);
extern s32 func_80029000(void);
extern s32 func_80028D9C(void);
@@ -3223,7 +3222,32 @@ void func_8017D060(void *a0) {
}
INCLUDE_ASM("asm/ov_SC01_001/nonmatchings/ov_SC01_001_jr_8017BEBC", func_8017D09C);
/* 8 bytes, align 2 -> lwl/lwr/swl/swr copy (cookbook §48-C2) */
typedef struct {
s16 v[4];
} Blk8_80126940_8017D09C;
extern u16 func_80148800(s32 *a0);
extern void func_8017D13C(s32 param_1, s16 *param_2);
void func_8017D09C(s32 a0) {
extern s32 D_80126B58;
extern s16 D_801872BC[];
extern Blk8_80126940_8017D09C D_80126940;
Blk8_80126940_8017D09C sp10;
u8 t;
if (func_80148800(&D_80126B58) & 3) {
t = (*(u8 *)(a0 + 5) + 1) & 1;
*(u8 *)(a0 + 5) = t;
*(s32 *)(a0 + 0x14) = D_801872BC[t];
}
sp10 = D_80126940;
func_8017D13C(a0, sp10.v);
}
// @class: schedule
+21 -1
View File
@@ -387,7 +387,27 @@ void func_80128AF4(void) {
DEFINE_func_80128C14() /* dedup: shared engine-core @0x80128C14 (src/shared) */
INCLUDE_ASM("asm/ov_SC01_004/nonmatchings/ov_SC01_004", func_80128C98);
typedef struct {
s32 word0;
s32 word4;
} CdFileLoc_80128C98;
extern CdFileLoc_80128C98 cdFileLocTable[];
extern void func_8001ABBC(s32 a0, s32 a1, void *a2, s32 a3, s32 a4);
s32 func_80128C98(s32 arg0) {
extern s16 D_8017F4CC[];
s16 idx = D_8017F4CC[arg0];
if (idx >= 0) {
func_8001ABBC(0, 0, (u8 *)&cdFileLocTable[idx], D_8018D6EC, 0);
} else {
return 1;
}
}
INCLUDE_ASM("asm/ov_SC01_004/nonmatchings/ov_SC01_004", func_80128CFC);
+78 -1
View File
@@ -481,7 +481,84 @@ INCLUDE_ASM("asm/ov_SC01_004/nonmatchings/ov_SC01_004_after", func_80146A6C);
DEFINE_func_80146AB4() /* dedup: shared engine-core @0x80146AB4 (src/shared) */
INCLUDE_ASM("asm/ov_SC01_004/nonmatchings/ov_SC01_004_after", func_80146AFC);
extern s32 func_80146B9C(void * arg0);
/* func_80146AFC — ASCENDING twin of the byte-proven DEFINE_func_80146B9C()
* in src/shared/engine_core.h (cookbook §71: find the already-matched sibling first).
* Same 0x58-stride slot table (base D_8011D030), same 7-store copy body in the same
* order, same $a2/$a1 giv pair. 80146B9C walks DOWN; this one walks UP, so the guard
* is `p < end`, end = p + 0xA50 (30 slots x 0x58).
*
* DECAY ROOT CAUSE (this redraft): the stored backlog draft had been rewritten to
* `void func_80146AFC(...)`, which drops BOTH `return 0` paths' `addu $v0,$zero,$zero`
* and the hit path's `j .L80146B94` => LENGTH-DRIFT -2 (38 vs 40) plus $v0/$v1 regalloc
* drift on the final lw/sw pair. Restoring the s32 return type (the fleet spelling the
* banked sibling func_80146B9C already uses) restores MATCH at 40/40.
*
* RECONCILE (2026-08-01) — the whole-binary gate failed with
* ov_SC01_077_after.c:592: conflicting types for `D_8011D030' (previous decl :564)
* TWO file-scope collisions were present; both are fixed HERE, with NO edit to
* src/shared/engine_core.h and NO change to the generated code (re-verified MATCH
* after each step):
*
* 1. D_8011D030 (the reported one). DEFINE_func_801469C8() emits
* `extern s32 D_8011D030;` at FILE scope (engine_core.h:10811, above the
* `s32 func_801469C8(...) {` line), and this TU expands that macro at :564 —
extern s32 D_8011D030;
* i.e. before the splice point :570. The draft's `extern u16` therefore
* redeclared it incompatibly at :592. Conformed to the TU's `extern s32`.
* Codegen-neutral: the sole use is `(u8 *)&D_8011D030`, an address-of, so the
* declared object type never reaches a load/store width (cookbook §20).
*
* 2. func_80146AFC ITSELF (latent, would have surfaced next). DEFINE_func_8014C010()
* (:13510) and DEFINE_func_8014AD30() (:13524) each emit a file-scope
* `extern void func_80146AFC(void *a0);`, and this TU expands them at :1386 and
* :1541 — after the splice — so an `s32 func_80146AFC` definition collides on the
* RETURN axis. Fixed with the §37/§124 ASM-LABEL ALIAS: the C identifier is
* aF80146AFC, the emitted label is func_80146AFC, so the canonical void decl and
* this s32 definition never share a namespace. Callers discard the result, so the
* void-typed call sites stay codegen-identical.
*
* Both were reproduced and then cleared against the real cpp+cc1-2.7.2 pair using a
* synthetic copy of this TU's declaration environment (.run/uc2/_recon_probe_80146AFC.c):
* the pre-reconcile spelling emits exactly the gate's error pair; the spelling below
* compiles clean.
*
* ORACLE: tools/match_one.py func_80146AFC --c .run/uc2/func_80146AFC.c
* --asm-subdir asm/ov_SC01_077/nonmatchings/ov_SC01_077_after -> MATCH (40 ins)
*/
s32 aF80146AFC(void *arg0) __asm__("func_80146AFC");
s32 aF80146AFC(void *arg0)
{
register u8 *p __asm__("$6");
register u8 *q __asm__("$5");
u8 *end;
p = (u8 *)&D_8011D030;
end = p + 0xA50;
if ((u32)p < (u32)end) {
q = p + 0x30;
do {
if (*(u16 *)p == 0) {
*(s32 *)(q + 0x4) = *(s32 *)((u8 *)arg0 + 0x8);
*(s16 *)p = *(u16 *)((u8 *)arg0 + 0x0);
*(s16 *)(q - 0x2A) = *(u16 *)((u8 *)arg0 + 0x2);
*(s16 *)(q - 0x26) = *(u16 *)((u8 *)arg0 + 0x4);
*(s16 *)(q - 0x22) = *(u16 *)((u8 *)arg0 + 0x6);
*(s32 *)(q - 0x4) = *(s32 *)((u8 *)arg0 + 0xC);
*(s32 *)(q + 0x0) = *(s32 *)((u8 *)arg0 + 0x10);
return (s32)p;
}
p += 0x58;
q += 0x58;
} while ((u32)p < (u32)end);
}
return 0;
}
DEFINE_func_80146B9C() /* dedup: shared engine-core @0x80146B9C (src/shared) */
+49 -1
View File
@@ -327,7 +327,55 @@ DEFINE_func_8012B70C() /* dedup: shared engine-core @0x8012B70C (src/shared) */
DEFINE_func_8012B744() /* dedup: shared engine-core @0x8012B744 (src/shared) */
INCLUDE_ASM("asm/ov_SC01_004/nonmatchings/ov_SC01_004_jr_8012ACE0", func_8012B77C);
extern s32 ratan2(s32 a0, s32 a1);
extern s32 func_80047948(s32 a0); /* rsin-like: angle (0..0xFFF) -> 1.12 fixed */
extern s32 func_8004787C(s32 a0); /* rcos-like: angle (0..0xFFF) -> 1.12 fixed */
/* The 4-byte destination is a PACKED PAIR of angles held entirely in ONE saved register
* ($s4) across all three calls — that is what produces the target's
* andi $s4,$s4,0xFFFF (read of the still-uninitialized local, hoisted into the prologue)
* ... or $s4,$s4,ang<<16 -> t.hi = yaw
* ... and $s4,$s4,0xFFFF0000 / or $s4,$s4,ang&0xFFFF -> t.lo = pitch
* A `struct { s16 lo, hi; }` has align 2 -> BLKmode-ish handling: gcc spills it to the stack
* and stores it with lwl/lwr + swl/swr (54 ins, 53 mismatched). Two 16-bit BITFIELDS in a
* u32 container give the SImode, align-4 struct gcc keeps in a register. */
typedef struct {
u32 lo : 16;
u32 hi : 16;
} Ang2_8012B77C_8012B77C;
/* a0 = destination packed-angle word, a1 = "from" entity, a2 = "to" entity.
* Both entities carry 16.16 fixed-point x/y/z at +0/+4/+8; the s16 reads at +2/+6/+0xA are
* the integer halves. Returns the destination pointer — the return value is REAL: without it
* gcc stores with `sw $s4,0($s3)` (57 ins) instead of the target's
* addu $v0,$s3,$zero ; sw $s4,0($v0) (the return-value copy that the store's base coalesces onto).
* The flattened `dz` reuse at the end is also load-bearing: making the (dz*sin + dx*cos)>>12
* temp its OWN variable gives it $a1 for the whole chain; reusing `dz` extends that allocno so
* it lands in $s5 exactly as the target does (`sra $s5,$v0,12` / `negu $a1,$s5`), and it also
* demotes dz's priority so the saved-reg order comes out $s3=out, $s4=t, $s5=dz. */
s32 func_8012B77C(s32 out, s32 from, s32 to) {
Ang2_8012B77C_8012B77C t;
s32 dx, dy, dz;
s32 ang;
s32 r1, r2;
dz = *(s16 *)(to + 0xA) - *(s16 *)(from + 0xA);
dx = *(s16 *)(to + 0x2) - *(s16 *)(from + 0x2);
dy = *(s16 *)(to + 0x6) - *(s16 *)(from + 0x6);
ang = (ratan2(-dz, dx) - 0x400) & 0xFFF;
t.hi = ang;
r1 = func_80047948(ang);
r2 = func_8004787C(ang);
dz = (dz * r1 + dx * r2) >> 12;
t.lo = ratan2(dy, -dz);
*(Ang2_8012B77C_8012B77C *)out = t;
return out;
}
DEFINE_func_8012B864() /* dedup: shared engine-core @0x8012B864 (src/shared) */
+74 -1
View File
@@ -3172,7 +3172,80 @@ void func_80175DA8(param_1)
}
INCLUDE_ASM("asm/ov_SC01_004/nonmatchings/ov_SC01_004_jr_801734BC", func_80176144);
/* func_80176144 — RECONCILED variant of .run/uc/func_80176144.c
*
* GATE BLOCKER (whole-binary build, NOT match_one):
* src/ov_SC01_077/ov_SC01_077_jr_801734BC.c:3476: conflicting types for `D_800AF634'
* || previous declaration at :3296
*
* ROOT CAUSE — a HOISTED file-scope typedef, not a bad signature:
* That TU hoists, at FILE scope, for func_80175DA8:
* :3295 typedef struct { s32 g0; s32 pad[2]; } S_AF634_80176144;
* :3296 extern S_AF634_80176144 D_800AF634[];
* :3297 extern S_AF634_80176144 D_800AF638[];
* The stored draft re-declares the SAME struct shape as a BLOCK-scope typedef
* (rule D — it must travel to the 137 sibling overlays, which have no such
* preamble). A block-scope `typedef struct {...} S_AF634_80176144;` is a DISTINCT type
* from the file-scope one (C has no structural typing), so the block-scope
* `extern S_AF634_80176144 D_800AF634[];` re-declares the symbol incompatibly with the
* in-scope file-scope decl -> hard error.
* Note the earlier block-scope copies in the same TU (:3080 func_80175820,
* :3123 func_801759D8) do NOT error: they precede :3296, so no file-scope decl
* of D_800AF634 is in scope there. Anything AFTER :3296 collides. Our
* definition lands at :3476. That is why only this one fired.
*
* FIX — §37/§124 ASM-LABEL ALIAS applied to the DATA symbols (cookbook §2516:
* "asm-label alias for sibling-decl signedness/proto conflicts ... beats
* reconcile's *(u16*)&D_x cast whose address-of PERTURBS regalloc"):
* the two objects are reached through PRIVATE C identifiers aAF634 / aAF638
* carrying __asm__("D_800AF634") / __asm__("D_800AF638"). The emitted
* %hi/%lo relocations are against the same symbols, so codegen is unchanged,
* while the C names can never collide with ANY sibling TU's declaration —
* whether hoisted, block-scope, or absent. No header edit; no src/ edit.
* Strictly better than deleting the local decls (which would bind this
* exemplar to the one TU that happens to hoist them).
*
* The s32 parameter + explicit (s16) narrowing is retained from the stored draft
* (canonical decl in engine_core.h:18985/:4587 is `void func_80176144(s32)`;
* the K&R short param would itself be a conflicting-types error). The (s16)
* narrowing IS the entry `sll $s0,$a0,16 / sra $s0,$s0,16` pair.
*
* Verified: python3 tools/match_one.py func_80176144 --c .run/uc2/func_80176144.c
* --asm-subdir ov_SC01_077/nonmatchings/ov_SC01_077_jr_801734BC -> MATCH (53 ins)
*/
void func_80176144(s32 a0)
{
typedef struct { s32 g0; s32 pad[2]; } S_AF634_80176144; /* size 0x0C */
/* §37 asm-label alias: private C names, canonical relocations. */
extern S_AF634_80176144 aAF634[] __asm__("D_800AF634");
extern S_AF634_80176144 aAF638[] __asm__("D_800AF638");
extern u8 D_8011F7A8;
extern s16 D_8011F7BC;
extern s16 D_8011F7BE;
extern s32 func_80178004(s32 a0, s32 a1, s32 a2);
u32 *slot;
u32 *p;
s16 param_1 = (s16)a0;
p = (u32 *)(aAF638[param_1].g0 + aAF634[param_1].g0 * 4);
slot = (u32 *)(param_1 * 4 + (s32)&D_8011F7A8);
slot[14] = (u32)p;
/* §5a zero-byte sched fence: without it sched1 hoists the two %hi/lhu global
argument loads above the `sw` of slot[14] (16 mismatches, 0 length drift). */
__asm__("");
p = (u32 *)func_80178004((s32)p,
(s16)((*(u16 *)&D_8011F7BC) - 0x17),
(s16)((*(u16 *)&D_8011F7BE) + 0x65));
slot[16] = (u32)p - 0x14;
p += 5;
aAF634[param_1].g0 += ((s32)p - (s32)slot[14]) >> 2;
}
// @class: regalloc-order
+21 -1
View File
@@ -388,7 +388,27 @@ void func_80128AF4(void) {
DEFINE_func_80128C14() /* dedup: shared engine-core @0x80128C14 (src/shared) */
INCLUDE_ASM("asm/ov_SC01_005/nonmatchings/ov_SC01_005", func_80128C98);
typedef struct {
s32 word0;
s32 word4;
} CdFileLoc_80128C98;
extern CdFileLoc_80128C98 cdFileLocTable[];
extern void func_8001ABBC(s32 a0, s32 a1, void *a2, s32 a3, s32 a4);
s32 func_80128C98(s32 arg0) {
extern s16 D_80182660[];
s16 idx = D_80182660[arg0];
if (idx >= 0) {
func_8001ABBC(0, 0, (u8 *)&cdFileLocTable[idx], D_801CAE4C, 0);
} else {
return 1;
}
}
INCLUDE_ASM("asm/ov_SC01_005/nonmatchings/ov_SC01_005", func_80128CFC);
+78 -1
View File
@@ -482,7 +482,84 @@ INCLUDE_ASM("asm/ov_SC01_005/nonmatchings/ov_SC01_005_after", func_80146A6C);
DEFINE_func_80146AB4() /* dedup: shared engine-core @0x80146AB4 (src/shared) */
INCLUDE_ASM("asm/ov_SC01_005/nonmatchings/ov_SC01_005_after", func_80146AFC);
extern s32 func_80146B9C(void * arg0);
/* func_80146AFC — ASCENDING twin of the byte-proven DEFINE_func_80146B9C()
* in src/shared/engine_core.h (cookbook §71: find the already-matched sibling first).
* Same 0x58-stride slot table (base D_8011D030), same 7-store copy body in the same
* order, same $a2/$a1 giv pair. 80146B9C walks DOWN; this one walks UP, so the guard
* is `p < end`, end = p + 0xA50 (30 slots x 0x58).
*
* DECAY ROOT CAUSE (this redraft): the stored backlog draft had been rewritten to
* `void func_80146AFC(...)`, which drops BOTH `return 0` paths' `addu $v0,$zero,$zero`
* and the hit path's `j .L80146B94` => LENGTH-DRIFT -2 (38 vs 40) plus $v0/$v1 regalloc
* drift on the final lw/sw pair. Restoring the s32 return type (the fleet spelling the
* banked sibling func_80146B9C already uses) restores MATCH at 40/40.
*
* RECONCILE (2026-08-01) — the whole-binary gate failed with
* ov_SC01_077_after.c:592: conflicting types for `D_8011D030' (previous decl :564)
* TWO file-scope collisions were present; both are fixed HERE, with NO edit to
* src/shared/engine_core.h and NO change to the generated code (re-verified MATCH
* after each step):
*
* 1. D_8011D030 (the reported one). DEFINE_func_801469C8() emits
* `extern s32 D_8011D030;` at FILE scope (engine_core.h:10811, above the
* `s32 func_801469C8(...) {` line), and this TU expands that macro at :564 —
extern s32 D_8011D030;
* i.e. before the splice point :570. The draft's `extern u16` therefore
* redeclared it incompatibly at :592. Conformed to the TU's `extern s32`.
* Codegen-neutral: the sole use is `(u8 *)&D_8011D030`, an address-of, so the
* declared object type never reaches a load/store width (cookbook §20).
*
* 2. func_80146AFC ITSELF (latent, would have surfaced next). DEFINE_func_8014C010()
* (:13510) and DEFINE_func_8014AD30() (:13524) each emit a file-scope
* `extern void func_80146AFC(void *a0);`, and this TU expands them at :1386 and
* :1541 — after the splice — so an `s32 func_80146AFC` definition collides on the
* RETURN axis. Fixed with the §37/§124 ASM-LABEL ALIAS: the C identifier is
* aF80146AFC, the emitted label is func_80146AFC, so the canonical void decl and
* this s32 definition never share a namespace. Callers discard the result, so the
* void-typed call sites stay codegen-identical.
*
* Both were reproduced and then cleared against the real cpp+cc1-2.7.2 pair using a
* synthetic copy of this TU's declaration environment (.run/uc2/_recon_probe_80146AFC.c):
* the pre-reconcile spelling emits exactly the gate's error pair; the spelling below
* compiles clean.
*
* ORACLE: tools/match_one.py func_80146AFC --c .run/uc2/func_80146AFC.c
* --asm-subdir asm/ov_SC01_077/nonmatchings/ov_SC01_077_after -> MATCH (40 ins)
*/
s32 aF80146AFC(void *arg0) __asm__("func_80146AFC");
s32 aF80146AFC(void *arg0)
{
register u8 *p __asm__("$6");
register u8 *q __asm__("$5");
u8 *end;
p = (u8 *)&D_8011D030;
end = p + 0xA50;
if ((u32)p < (u32)end) {
q = p + 0x30;
do {
if (*(u16 *)p == 0) {
*(s32 *)(q + 0x4) = *(s32 *)((u8 *)arg0 + 0x8);
*(s16 *)p = *(u16 *)((u8 *)arg0 + 0x0);
*(s16 *)(q - 0x2A) = *(u16 *)((u8 *)arg0 + 0x2);
*(s16 *)(q - 0x26) = *(u16 *)((u8 *)arg0 + 0x4);
*(s16 *)(q - 0x22) = *(u16 *)((u8 *)arg0 + 0x6);
*(s32 *)(q - 0x4) = *(s32 *)((u8 *)arg0 + 0xC);
*(s32 *)(q + 0x0) = *(s32 *)((u8 *)arg0 + 0x10);
return (s32)p;
}
p += 0x58;
q += 0x58;
} while ((u32)p < (u32)end);
}
return 0;
}
DEFINE_func_80146B9C() /* dedup: shared engine-core @0x80146B9C (src/shared) */
+49 -1
View File
@@ -325,7 +325,55 @@ DEFINE_func_8012B70C() /* dedup: shared engine-core @0x8012B70C (src/shared) */
DEFINE_func_8012B744() /* dedup: shared engine-core @0x8012B744 (src/shared) */
INCLUDE_ASM("asm/ov_SC01_005/nonmatchings/ov_SC01_005_jr_8012ACE0", func_8012B77C);
extern s32 ratan2(s32 a0, s32 a1);
extern s32 func_80047948(s32 a0); /* rsin-like: angle (0..0xFFF) -> 1.12 fixed */
extern s32 func_8004787C(s32 a0); /* rcos-like: angle (0..0xFFF) -> 1.12 fixed */
/* The 4-byte destination is a PACKED PAIR of angles held entirely in ONE saved register
* ($s4) across all three calls — that is what produces the target's
* andi $s4,$s4,0xFFFF (read of the still-uninitialized local, hoisted into the prologue)
* ... or $s4,$s4,ang<<16 -> t.hi = yaw
* ... and $s4,$s4,0xFFFF0000 / or $s4,$s4,ang&0xFFFF -> t.lo = pitch
* A `struct { s16 lo, hi; }` has align 2 -> BLKmode-ish handling: gcc spills it to the stack
* and stores it with lwl/lwr + swl/swr (54 ins, 53 mismatched). Two 16-bit BITFIELDS in a
* u32 container give the SImode, align-4 struct gcc keeps in a register. */
typedef struct {
u32 lo : 16;
u32 hi : 16;
} Ang2_8012B77C_8012B77C;
/* a0 = destination packed-angle word, a1 = "from" entity, a2 = "to" entity.
* Both entities carry 16.16 fixed-point x/y/z at +0/+4/+8; the s16 reads at +2/+6/+0xA are
* the integer halves. Returns the destination pointer — the return value is REAL: without it
* gcc stores with `sw $s4,0($s3)` (57 ins) instead of the target's
* addu $v0,$s3,$zero ; sw $s4,0($v0) (the return-value copy that the store's base coalesces onto).
* The flattened `dz` reuse at the end is also load-bearing: making the (dz*sin + dx*cos)>>12
* temp its OWN variable gives it $a1 for the whole chain; reusing `dz` extends that allocno so
* it lands in $s5 exactly as the target does (`sra $s5,$v0,12` / `negu $a1,$s5`), and it also
* demotes dz's priority so the saved-reg order comes out $s3=out, $s4=t, $s5=dz. */
s32 func_8012B77C(s32 out, s32 from, s32 to) {
Ang2_8012B77C_8012B77C t;
s32 dx, dy, dz;
s32 ang;
s32 r1, r2;
dz = *(s16 *)(to + 0xA) - *(s16 *)(from + 0xA);
dx = *(s16 *)(to + 0x2) - *(s16 *)(from + 0x2);
dy = *(s16 *)(to + 0x6) - *(s16 *)(from + 0x6);
ang = (ratan2(-dz, dx) - 0x400) & 0xFFF;
t.hi = ang;
r1 = func_80047948(ang);
r2 = func_8004787C(ang);
dz = (dz * r1 + dx * r2) >> 12;
t.lo = ratan2(dy, -dz);
*(Ang2_8012B77C_8012B77C *)out = t;
return out;
}
DEFINE_func_8012B864() /* dedup: shared engine-core @0x8012B864 (src/shared) */
+74 -1
View File
@@ -3173,7 +3173,80 @@ void func_80175DA8(param_1)
}
INCLUDE_ASM("asm/ov_SC01_005/nonmatchings/ov_SC01_005_jr_801734BC", func_80176144);
/* func_80176144 — RECONCILED variant of .run/uc/func_80176144.c
*
* GATE BLOCKER (whole-binary build, NOT match_one):
* src/ov_SC01_077/ov_SC01_077_jr_801734BC.c:3476: conflicting types for `D_800AF634'
* || previous declaration at :3296
*
* ROOT CAUSE — a HOISTED file-scope typedef, not a bad signature:
* That TU hoists, at FILE scope, for func_80175DA8:
* :3295 typedef struct { s32 g0; s32 pad[2]; } S_AF634_80176144;
* :3296 extern S_AF634_80176144 D_800AF634[];
* :3297 extern S_AF634_80176144 D_800AF638[];
* The stored draft re-declares the SAME struct shape as a BLOCK-scope typedef
* (rule D — it must travel to the 137 sibling overlays, which have no such
* preamble). A block-scope `typedef struct {...} S_AF634_80176144;` is a DISTINCT type
* from the file-scope one (C has no structural typing), so the block-scope
* `extern S_AF634_80176144 D_800AF634[];` re-declares the symbol incompatibly with the
* in-scope file-scope decl -> hard error.
* Note the earlier block-scope copies in the same TU (:3080 func_80175820,
* :3123 func_801759D8) do NOT error: they precede :3296, so no file-scope decl
* of D_800AF634 is in scope there. Anything AFTER :3296 collides. Our
* definition lands at :3476. That is why only this one fired.
*
* FIX — §37/§124 ASM-LABEL ALIAS applied to the DATA symbols (cookbook §2516:
* "asm-label alias for sibling-decl signedness/proto conflicts ... beats
* reconcile's *(u16*)&D_x cast whose address-of PERTURBS regalloc"):
* the two objects are reached through PRIVATE C identifiers aAF634 / aAF638
* carrying __asm__("D_800AF634") / __asm__("D_800AF638"). The emitted
* %hi/%lo relocations are against the same symbols, so codegen is unchanged,
* while the C names can never collide with ANY sibling TU's declaration —
* whether hoisted, block-scope, or absent. No header edit; no src/ edit.
* Strictly better than deleting the local decls (which would bind this
* exemplar to the one TU that happens to hoist them).
*
* The s32 parameter + explicit (s16) narrowing is retained from the stored draft
* (canonical decl in engine_core.h:18985/:4587 is `void func_80176144(s32)`;
* the K&R short param would itself be a conflicting-types error). The (s16)
* narrowing IS the entry `sll $s0,$a0,16 / sra $s0,$s0,16` pair.
*
* Verified: python3 tools/match_one.py func_80176144 --c .run/uc2/func_80176144.c
* --asm-subdir ov_SC01_077/nonmatchings/ov_SC01_077_jr_801734BC -> MATCH (53 ins)
*/
void func_80176144(s32 a0)
{
typedef struct { s32 g0; s32 pad[2]; } S_AF634_80176144; /* size 0x0C */
/* §37 asm-label alias: private C names, canonical relocations. */
extern S_AF634_80176144 aAF634[] __asm__("D_800AF634");
extern S_AF634_80176144 aAF638[] __asm__("D_800AF638");
extern u8 D_8011F7A8;
extern s16 D_8011F7BC;
extern s16 D_8011F7BE;
extern s32 func_80178004(s32 a0, s32 a1, s32 a2);
u32 *slot;
u32 *p;
s16 param_1 = (s16)a0;
p = (u32 *)(aAF638[param_1].g0 + aAF634[param_1].g0 * 4);
slot = (u32 *)(param_1 * 4 + (s32)&D_8011F7A8);
slot[14] = (u32)p;
/* §5a zero-byte sched fence: without it sched1 hoists the two %hi/lhu global
argument loads above the `sw` of slot[14] (16 mismatches, 0 length drift). */
__asm__("");
p = (u32 *)func_80178004((s32)p,
(s16)((*(u16 *)&D_8011F7BC) - 0x17),
(s16)((*(u16 *)&D_8011F7BE) + 0x65));
slot[16] = (u32)p - 0x14;
p += 5;
aAF634[param_1].g0 += ((s32)p - (s32)slot[14]) >> 2;
}
// @class: regalloc-order
+21 -1
View File
@@ -388,7 +388,27 @@ void func_80128AF4(void) {
DEFINE_func_80128C14() /* dedup: shared engine-core @0x80128C14 (src/shared) */
INCLUDE_ASM("asm/ov_SC01_006/nonmatchings/ov_SC01_006", func_80128C98);
typedef struct {
s32 word0;
s32 word4;
} CdFileLoc_80128C98;
extern CdFileLoc_80128C98 cdFileLocTable[];
extern void func_8001ABBC(s32 a0, s32 a1, void *a2, s32 a3, s32 a4);
s32 func_80128C98(s32 arg0) {
extern s16 D_80182660[];
s16 idx = D_80182660[arg0];
if (idx >= 0) {
func_8001ABBC(0, 0, (u8 *)&cdFileLocTable[idx], D_801CAE4C, 0);
} else {
return 1;
}
}
INCLUDE_ASM("asm/ov_SC01_006/nonmatchings/ov_SC01_006", func_80128CFC);
+78 -1
View File
@@ -482,7 +482,84 @@ INCLUDE_ASM("asm/ov_SC01_006/nonmatchings/ov_SC01_006_after", func_80146A6C);
DEFINE_func_80146AB4() /* dedup: shared engine-core @0x80146AB4 (src/shared) */
INCLUDE_ASM("asm/ov_SC01_006/nonmatchings/ov_SC01_006_after", func_80146AFC);
extern s32 func_80146B9C(void * arg0);
/* func_80146AFC — ASCENDING twin of the byte-proven DEFINE_func_80146B9C()
* in src/shared/engine_core.h (cookbook §71: find the already-matched sibling first).
* Same 0x58-stride slot table (base D_8011D030), same 7-store copy body in the same
* order, same $a2/$a1 giv pair. 80146B9C walks DOWN; this one walks UP, so the guard
* is `p < end`, end = p + 0xA50 (30 slots x 0x58).
*
* DECAY ROOT CAUSE (this redraft): the stored backlog draft had been rewritten to
* `void func_80146AFC(...)`, which drops BOTH `return 0` paths' `addu $v0,$zero,$zero`
* and the hit path's `j .L80146B94` => LENGTH-DRIFT -2 (38 vs 40) plus $v0/$v1 regalloc
* drift on the final lw/sw pair. Restoring the s32 return type (the fleet spelling the
* banked sibling func_80146B9C already uses) restores MATCH at 40/40.
*
* RECONCILE (2026-08-01) — the whole-binary gate failed with
* ov_SC01_077_after.c:592: conflicting types for `D_8011D030' (previous decl :564)
* TWO file-scope collisions were present; both are fixed HERE, with NO edit to
* src/shared/engine_core.h and NO change to the generated code (re-verified MATCH
* after each step):
*
* 1. D_8011D030 (the reported one). DEFINE_func_801469C8() emits
* `extern s32 D_8011D030;` at FILE scope (engine_core.h:10811, above the
* `s32 func_801469C8(...) {` line), and this TU expands that macro at :564 —
extern s32 D_8011D030;
* i.e. before the splice point :570. The draft's `extern u16` therefore
* redeclared it incompatibly at :592. Conformed to the TU's `extern s32`.
* Codegen-neutral: the sole use is `(u8 *)&D_8011D030`, an address-of, so the
* declared object type never reaches a load/store width (cookbook §20).
*
* 2. func_80146AFC ITSELF (latent, would have surfaced next). DEFINE_func_8014C010()
* (:13510) and DEFINE_func_8014AD30() (:13524) each emit a file-scope
* `extern void func_80146AFC(void *a0);`, and this TU expands them at :1386 and
* :1541 — after the splice — so an `s32 func_80146AFC` definition collides on the
* RETURN axis. Fixed with the §37/§124 ASM-LABEL ALIAS: the C identifier is
* aF80146AFC, the emitted label is func_80146AFC, so the canonical void decl and
* this s32 definition never share a namespace. Callers discard the result, so the
* void-typed call sites stay codegen-identical.
*
* Both were reproduced and then cleared against the real cpp+cc1-2.7.2 pair using a
* synthetic copy of this TU's declaration environment (.run/uc2/_recon_probe_80146AFC.c):
* the pre-reconcile spelling emits exactly the gate's error pair; the spelling below
* compiles clean.
*
* ORACLE: tools/match_one.py func_80146AFC --c .run/uc2/func_80146AFC.c
* --asm-subdir asm/ov_SC01_077/nonmatchings/ov_SC01_077_after -> MATCH (40 ins)
*/
s32 aF80146AFC(void *arg0) __asm__("func_80146AFC");
s32 aF80146AFC(void *arg0)
{
register u8 *p __asm__("$6");
register u8 *q __asm__("$5");
u8 *end;
p = (u8 *)&D_8011D030;
end = p + 0xA50;
if ((u32)p < (u32)end) {
q = p + 0x30;
do {
if (*(u16 *)p == 0) {
*(s32 *)(q + 0x4) = *(s32 *)((u8 *)arg0 + 0x8);
*(s16 *)p = *(u16 *)((u8 *)arg0 + 0x0);
*(s16 *)(q - 0x2A) = *(u16 *)((u8 *)arg0 + 0x2);
*(s16 *)(q - 0x26) = *(u16 *)((u8 *)arg0 + 0x4);
*(s16 *)(q - 0x22) = *(u16 *)((u8 *)arg0 + 0x6);
*(s32 *)(q - 0x4) = *(s32 *)((u8 *)arg0 + 0xC);
*(s32 *)(q + 0x0) = *(s32 *)((u8 *)arg0 + 0x10);
return (s32)p;
}
p += 0x58;
q += 0x58;
} while ((u32)p < (u32)end);
}
return 0;
}
DEFINE_func_80146B9C() /* dedup: shared engine-core @0x80146B9C (src/shared) */
+49 -1
View File
@@ -325,7 +325,55 @@ DEFINE_func_8012B70C() /* dedup: shared engine-core @0x8012B70C (src/shared) */
DEFINE_func_8012B744() /* dedup: shared engine-core @0x8012B744 (src/shared) */
INCLUDE_ASM("asm/ov_SC01_006/nonmatchings/ov_SC01_006_jr_8012ACE0", func_8012B77C);
extern s32 ratan2(s32 a0, s32 a1);
extern s32 func_80047948(s32 a0); /* rsin-like: angle (0..0xFFF) -> 1.12 fixed */
extern s32 func_8004787C(s32 a0); /* rcos-like: angle (0..0xFFF) -> 1.12 fixed */
/* The 4-byte destination is a PACKED PAIR of angles held entirely in ONE saved register
* ($s4) across all three calls — that is what produces the target's
* andi $s4,$s4,0xFFFF (read of the still-uninitialized local, hoisted into the prologue)
* ... or $s4,$s4,ang<<16 -> t.hi = yaw
* ... and $s4,$s4,0xFFFF0000 / or $s4,$s4,ang&0xFFFF -> t.lo = pitch
* A `struct { s16 lo, hi; }` has align 2 -> BLKmode-ish handling: gcc spills it to the stack
* and stores it with lwl/lwr + swl/swr (54 ins, 53 mismatched). Two 16-bit BITFIELDS in a
* u32 container give the SImode, align-4 struct gcc keeps in a register. */
typedef struct {
u32 lo : 16;
u32 hi : 16;
} Ang2_8012B77C_8012B77C;
/* a0 = destination packed-angle word, a1 = "from" entity, a2 = "to" entity.
* Both entities carry 16.16 fixed-point x/y/z at +0/+4/+8; the s16 reads at +2/+6/+0xA are
* the integer halves. Returns the destination pointer — the return value is REAL: without it
* gcc stores with `sw $s4,0($s3)` (57 ins) instead of the target's
* addu $v0,$s3,$zero ; sw $s4,0($v0) (the return-value copy that the store's base coalesces onto).
* The flattened `dz` reuse at the end is also load-bearing: making the (dz*sin + dx*cos)>>12
* temp its OWN variable gives it $a1 for the whole chain; reusing `dz` extends that allocno so
* it lands in $s5 exactly as the target does (`sra $s5,$v0,12` / `negu $a1,$s5`), and it also
* demotes dz's priority so the saved-reg order comes out $s3=out, $s4=t, $s5=dz. */
s32 func_8012B77C(s32 out, s32 from, s32 to) {
Ang2_8012B77C_8012B77C t;
s32 dx, dy, dz;
s32 ang;
s32 r1, r2;
dz = *(s16 *)(to + 0xA) - *(s16 *)(from + 0xA);
dx = *(s16 *)(to + 0x2) - *(s16 *)(from + 0x2);
dy = *(s16 *)(to + 0x6) - *(s16 *)(from + 0x6);
ang = (ratan2(-dz, dx) - 0x400) & 0xFFF;
t.hi = ang;
r1 = func_80047948(ang);
r2 = func_8004787C(ang);
dz = (dz * r1 + dx * r2) >> 12;
t.lo = ratan2(dy, -dz);
*(Ang2_8012B77C_8012B77C *)out = t;
return out;
}
DEFINE_func_8012B864() /* dedup: shared engine-core @0x8012B864 (src/shared) */
+74 -1
View File
@@ -3173,7 +3173,80 @@ void func_80175DA8(param_1)
}
INCLUDE_ASM("asm/ov_SC01_006/nonmatchings/ov_SC01_006_jr_801734BC", func_80176144);
/* func_80176144 — RECONCILED variant of .run/uc/func_80176144.c
*
* GATE BLOCKER (whole-binary build, NOT match_one):
* src/ov_SC01_077/ov_SC01_077_jr_801734BC.c:3476: conflicting types for `D_800AF634'
* || previous declaration at :3296
*
* ROOT CAUSE — a HOISTED file-scope typedef, not a bad signature:
* That TU hoists, at FILE scope, for func_80175DA8:
* :3295 typedef struct { s32 g0; s32 pad[2]; } S_AF634_80176144;
* :3296 extern S_AF634_80176144 D_800AF634[];
* :3297 extern S_AF634_80176144 D_800AF638[];
* The stored draft re-declares the SAME struct shape as a BLOCK-scope typedef
* (rule D — it must travel to the 137 sibling overlays, which have no such
* preamble). A block-scope `typedef struct {...} S_AF634_80176144;` is a DISTINCT type
* from the file-scope one (C has no structural typing), so the block-scope
* `extern S_AF634_80176144 D_800AF634[];` re-declares the symbol incompatibly with the
* in-scope file-scope decl -> hard error.
* Note the earlier block-scope copies in the same TU (:3080 func_80175820,
* :3123 func_801759D8) do NOT error: they precede :3296, so no file-scope decl
* of D_800AF634 is in scope there. Anything AFTER :3296 collides. Our
* definition lands at :3476. That is why only this one fired.
*
* FIX — §37/§124 ASM-LABEL ALIAS applied to the DATA symbols (cookbook §2516:
* "asm-label alias for sibling-decl signedness/proto conflicts ... beats
* reconcile's *(u16*)&D_x cast whose address-of PERTURBS regalloc"):
* the two objects are reached through PRIVATE C identifiers aAF634 / aAF638
* carrying __asm__("D_800AF634") / __asm__("D_800AF638"). The emitted
* %hi/%lo relocations are against the same symbols, so codegen is unchanged,
* while the C names can never collide with ANY sibling TU's declaration —
* whether hoisted, block-scope, or absent. No header edit; no src/ edit.
* Strictly better than deleting the local decls (which would bind this
* exemplar to the one TU that happens to hoist them).
*
* The s32 parameter + explicit (s16) narrowing is retained from the stored draft
* (canonical decl in engine_core.h:18985/:4587 is `void func_80176144(s32)`;
* the K&R short param would itself be a conflicting-types error). The (s16)
* narrowing IS the entry `sll $s0,$a0,16 / sra $s0,$s0,16` pair.
*
* Verified: python3 tools/match_one.py func_80176144 --c .run/uc2/func_80176144.c
* --asm-subdir ov_SC01_077/nonmatchings/ov_SC01_077_jr_801734BC -> MATCH (53 ins)
*/
void func_80176144(s32 a0)
{
typedef struct { s32 g0; s32 pad[2]; } S_AF634_80176144; /* size 0x0C */
/* §37 asm-label alias: private C names, canonical relocations. */
extern S_AF634_80176144 aAF634[] __asm__("D_800AF634");
extern S_AF634_80176144 aAF638[] __asm__("D_800AF638");
extern u8 D_8011F7A8;
extern s16 D_8011F7BC;
extern s16 D_8011F7BE;
extern s32 func_80178004(s32 a0, s32 a1, s32 a2);
u32 *slot;
u32 *p;
s16 param_1 = (s16)a0;
p = (u32 *)(aAF638[param_1].g0 + aAF634[param_1].g0 * 4);
slot = (u32 *)(param_1 * 4 + (s32)&D_8011F7A8);
slot[14] = (u32)p;
/* §5a zero-byte sched fence: without it sched1 hoists the two %hi/lhu global
argument loads above the `sw` of slot[14] (16 mismatches, 0 length drift). */
__asm__("");
p = (u32 *)func_80178004((s32)p,
(s16)((*(u16 *)&D_8011F7BC) - 0x17),
(s16)((*(u16 *)&D_8011F7BE) + 0x65));
slot[16] = (u32)p - 0x14;
p += 5;
aAF634[param_1].g0 += ((s32)p - (s32)slot[14]) >> 2;
}
// @class: regalloc-order
+21 -1
View File
@@ -387,7 +387,27 @@ void func_80128AF4(void) {
DEFINE_func_80128C14() /* dedup: shared engine-core @0x80128C14 (src/shared) */
INCLUDE_ASM("asm/ov_SC01_008/nonmatchings/ov_SC01_008", func_80128C98);
typedef struct {
s32 word0;
s32 word4;
} CdFileLoc_80128C98;
extern CdFileLoc_80128C98 cdFileLocTable[];
extern void func_8001ABBC(s32 a0, s32 a1, void *a2, s32 a3, s32 a4);
s32 func_80128C98(s32 arg0) {
extern s16 D_8017FA40[];
s16 idx = D_8017FA40[arg0];
if (idx >= 0) {
func_8001ABBC(0, 0, (u8 *)&cdFileLocTable[idx], D_801A08FC, 0);
} else {
return 1;
}
}
INCLUDE_ASM("asm/ov_SC01_008/nonmatchings/ov_SC01_008", func_80128CFC);
+78 -1
View File
@@ -481,7 +481,84 @@ INCLUDE_ASM("asm/ov_SC01_008/nonmatchings/ov_SC01_008_after", func_80146A6C);
DEFINE_func_80146AB4() /* dedup: shared engine-core @0x80146AB4 (src/shared) */
INCLUDE_ASM("asm/ov_SC01_008/nonmatchings/ov_SC01_008_after", func_80146AFC);
extern s32 func_80146B9C(void * arg0);
/* func_80146AFC — ASCENDING twin of the byte-proven DEFINE_func_80146B9C()
* in src/shared/engine_core.h (cookbook §71: find the already-matched sibling first).
* Same 0x58-stride slot table (base D_8011D030), same 7-store copy body in the same
* order, same $a2/$a1 giv pair. 80146B9C walks DOWN; this one walks UP, so the guard
* is `p < end`, end = p + 0xA50 (30 slots x 0x58).
*
* DECAY ROOT CAUSE (this redraft): the stored backlog draft had been rewritten to
* `void func_80146AFC(...)`, which drops BOTH `return 0` paths' `addu $v0,$zero,$zero`
* and the hit path's `j .L80146B94` => LENGTH-DRIFT -2 (38 vs 40) plus $v0/$v1 regalloc
* drift on the final lw/sw pair. Restoring the s32 return type (the fleet spelling the
* banked sibling func_80146B9C already uses) restores MATCH at 40/40.
*
* RECONCILE (2026-08-01) — the whole-binary gate failed with
* ov_SC01_077_after.c:592: conflicting types for `D_8011D030' (previous decl :564)
* TWO file-scope collisions were present; both are fixed HERE, with NO edit to
* src/shared/engine_core.h and NO change to the generated code (re-verified MATCH
* after each step):
*
* 1. D_8011D030 (the reported one). DEFINE_func_801469C8() emits
* `extern s32 D_8011D030;` at FILE scope (engine_core.h:10811, above the
* `s32 func_801469C8(...) {` line), and this TU expands that macro at :564 —
extern s32 D_8011D030;
* i.e. before the splice point :570. The draft's `extern u16` therefore
* redeclared it incompatibly at :592. Conformed to the TU's `extern s32`.
* Codegen-neutral: the sole use is `(u8 *)&D_8011D030`, an address-of, so the
* declared object type never reaches a load/store width (cookbook §20).
*
* 2. func_80146AFC ITSELF (latent, would have surfaced next). DEFINE_func_8014C010()
* (:13510) and DEFINE_func_8014AD30() (:13524) each emit a file-scope
* `extern void func_80146AFC(void *a0);`, and this TU expands them at :1386 and
* :1541 — after the splice — so an `s32 func_80146AFC` definition collides on the
* RETURN axis. Fixed with the §37/§124 ASM-LABEL ALIAS: the C identifier is
* aF80146AFC, the emitted label is func_80146AFC, so the canonical void decl and
* this s32 definition never share a namespace. Callers discard the result, so the
* void-typed call sites stay codegen-identical.
*
* Both were reproduced and then cleared against the real cpp+cc1-2.7.2 pair using a
* synthetic copy of this TU's declaration environment (.run/uc2/_recon_probe_80146AFC.c):
* the pre-reconcile spelling emits exactly the gate's error pair; the spelling below
* compiles clean.
*
* ORACLE: tools/match_one.py func_80146AFC --c .run/uc2/func_80146AFC.c
* --asm-subdir asm/ov_SC01_077/nonmatchings/ov_SC01_077_after -> MATCH (40 ins)
*/
s32 aF80146AFC(void *arg0) __asm__("func_80146AFC");
s32 aF80146AFC(void *arg0)
{
register u8 *p __asm__("$6");
register u8 *q __asm__("$5");
u8 *end;
p = (u8 *)&D_8011D030;
end = p + 0xA50;
if ((u32)p < (u32)end) {
q = p + 0x30;
do {
if (*(u16 *)p == 0) {
*(s32 *)(q + 0x4) = *(s32 *)((u8 *)arg0 + 0x8);
*(s16 *)p = *(u16 *)((u8 *)arg0 + 0x0);
*(s16 *)(q - 0x2A) = *(u16 *)((u8 *)arg0 + 0x2);
*(s16 *)(q - 0x26) = *(u16 *)((u8 *)arg0 + 0x4);
*(s16 *)(q - 0x22) = *(u16 *)((u8 *)arg0 + 0x6);
*(s32 *)(q - 0x4) = *(s32 *)((u8 *)arg0 + 0xC);
*(s32 *)(q + 0x0) = *(s32 *)((u8 *)arg0 + 0x10);
return (s32)p;
}
p += 0x58;
q += 0x58;
} while ((u32)p < (u32)end);
}
return 0;
}
DEFINE_func_80146B9C() /* dedup: shared engine-core @0x80146B9C (src/shared) */
+49 -1
View File
@@ -327,7 +327,55 @@ DEFINE_func_8012B70C() /* dedup: shared engine-core @0x8012B70C (src/shared) */
DEFINE_func_8012B744() /* dedup: shared engine-core @0x8012B744 (src/shared) */
INCLUDE_ASM("asm/ov_SC01_008/nonmatchings/ov_SC01_008_jr_8012ACE0", func_8012B77C);
extern s32 ratan2(s32 a0, s32 a1);
extern s32 func_80047948(s32 a0); /* rsin-like: angle (0..0xFFF) -> 1.12 fixed */
extern s32 func_8004787C(s32 a0); /* rcos-like: angle (0..0xFFF) -> 1.12 fixed */
/* The 4-byte destination is a PACKED PAIR of angles held entirely in ONE saved register
* ($s4) across all three calls — that is what produces the target's
* andi $s4,$s4,0xFFFF (read of the still-uninitialized local, hoisted into the prologue)
* ... or $s4,$s4,ang<<16 -> t.hi = yaw
* ... and $s4,$s4,0xFFFF0000 / or $s4,$s4,ang&0xFFFF -> t.lo = pitch
* A `struct { s16 lo, hi; }` has align 2 -> BLKmode-ish handling: gcc spills it to the stack
* and stores it with lwl/lwr + swl/swr (54 ins, 53 mismatched). Two 16-bit BITFIELDS in a
* u32 container give the SImode, align-4 struct gcc keeps in a register. */
typedef struct {
u32 lo : 16;
u32 hi : 16;
} Ang2_8012B77C_8012B77C;
/* a0 = destination packed-angle word, a1 = "from" entity, a2 = "to" entity.
* Both entities carry 16.16 fixed-point x/y/z at +0/+4/+8; the s16 reads at +2/+6/+0xA are
* the integer halves. Returns the destination pointer — the return value is REAL: without it
* gcc stores with `sw $s4,0($s3)` (57 ins) instead of the target's
* addu $v0,$s3,$zero ; sw $s4,0($v0) (the return-value copy that the store's base coalesces onto).
* The flattened `dz` reuse at the end is also load-bearing: making the (dz*sin + dx*cos)>>12
* temp its OWN variable gives it $a1 for the whole chain; reusing `dz` extends that allocno so
* it lands in $s5 exactly as the target does (`sra $s5,$v0,12` / `negu $a1,$s5`), and it also
* demotes dz's priority so the saved-reg order comes out $s3=out, $s4=t, $s5=dz. */
s32 func_8012B77C(s32 out, s32 from, s32 to) {
Ang2_8012B77C_8012B77C t;
s32 dx, dy, dz;
s32 ang;
s32 r1, r2;
dz = *(s16 *)(to + 0xA) - *(s16 *)(from + 0xA);
dx = *(s16 *)(to + 0x2) - *(s16 *)(from + 0x2);
dy = *(s16 *)(to + 0x6) - *(s16 *)(from + 0x6);
ang = (ratan2(-dz, dx) - 0x400) & 0xFFF;
t.hi = ang;
r1 = func_80047948(ang);
r2 = func_8004787C(ang);
dz = (dz * r1 + dx * r2) >> 12;
t.lo = ratan2(dy, -dz);
*(Ang2_8012B77C_8012B77C *)out = t;
return out;
}
DEFINE_func_8012B864() /* dedup: shared engine-core @0x8012B864 (src/shared) */
+74 -1
View File
@@ -3172,7 +3172,80 @@ void func_80175DA8(param_1)
}
INCLUDE_ASM("asm/ov_SC01_008/nonmatchings/ov_SC01_008_jr_801734BC", func_80176144);
/* func_80176144 — RECONCILED variant of .run/uc/func_80176144.c
*
* GATE BLOCKER (whole-binary build, NOT match_one):
* src/ov_SC01_077/ov_SC01_077_jr_801734BC.c:3476: conflicting types for `D_800AF634'
* || previous declaration at :3296
*
* ROOT CAUSE — a HOISTED file-scope typedef, not a bad signature:
* That TU hoists, at FILE scope, for func_80175DA8:
* :3295 typedef struct { s32 g0; s32 pad[2]; } S_AF634_80176144;
* :3296 extern S_AF634_80176144 D_800AF634[];
* :3297 extern S_AF634_80176144 D_800AF638[];
* The stored draft re-declares the SAME struct shape as a BLOCK-scope typedef
* (rule D — it must travel to the 137 sibling overlays, which have no such
* preamble). A block-scope `typedef struct {...} S_AF634_80176144;` is a DISTINCT type
* from the file-scope one (C has no structural typing), so the block-scope
* `extern S_AF634_80176144 D_800AF634[];` re-declares the symbol incompatibly with the
* in-scope file-scope decl -> hard error.
* Note the earlier block-scope copies in the same TU (:3080 func_80175820,
* :3123 func_801759D8) do NOT error: they precede :3296, so no file-scope decl
* of D_800AF634 is in scope there. Anything AFTER :3296 collides. Our
* definition lands at :3476. That is why only this one fired.
*
* FIX — §37/§124 ASM-LABEL ALIAS applied to the DATA symbols (cookbook §2516:
* "asm-label alias for sibling-decl signedness/proto conflicts ... beats
* reconcile's *(u16*)&D_x cast whose address-of PERTURBS regalloc"):
* the two objects are reached through PRIVATE C identifiers aAF634 / aAF638
* carrying __asm__("D_800AF634") / __asm__("D_800AF638"). The emitted
* %hi/%lo relocations are against the same symbols, so codegen is unchanged,
* while the C names can never collide with ANY sibling TU's declaration —
* whether hoisted, block-scope, or absent. No header edit; no src/ edit.
* Strictly better than deleting the local decls (which would bind this
* exemplar to the one TU that happens to hoist them).
*
* The s32 parameter + explicit (s16) narrowing is retained from the stored draft
* (canonical decl in engine_core.h:18985/:4587 is `void func_80176144(s32)`;
* the K&R short param would itself be a conflicting-types error). The (s16)
* narrowing IS the entry `sll $s0,$a0,16 / sra $s0,$s0,16` pair.
*
* Verified: python3 tools/match_one.py func_80176144 --c .run/uc2/func_80176144.c
* --asm-subdir ov_SC01_077/nonmatchings/ov_SC01_077_jr_801734BC -> MATCH (53 ins)
*/
void func_80176144(s32 a0)
{
typedef struct { s32 g0; s32 pad[2]; } S_AF634_80176144; /* size 0x0C */
/* §37 asm-label alias: private C names, canonical relocations. */
extern S_AF634_80176144 aAF634[] __asm__("D_800AF634");
extern S_AF634_80176144 aAF638[] __asm__("D_800AF638");
extern u8 D_8011F7A8;
extern s16 D_8011F7BC;
extern s16 D_8011F7BE;
extern s32 func_80178004(s32 a0, s32 a1, s32 a2);
u32 *slot;
u32 *p;
s16 param_1 = (s16)a0;
p = (u32 *)(aAF638[param_1].g0 + aAF634[param_1].g0 * 4);
slot = (u32 *)(param_1 * 4 + (s32)&D_8011F7A8);
slot[14] = (u32)p;
/* §5a zero-byte sched fence: without it sched1 hoists the two %hi/lhu global
argument loads above the `sw` of slot[14] (16 mismatches, 0 length drift). */
__asm__("");
p = (u32 *)func_80178004((s32)p,
(s16)((*(u16 *)&D_8011F7BC) - 0x17),
(s16)((*(u16 *)&D_8011F7BE) + 0x65));
slot[16] = (u32)p - 0x14;
p += 5;
aAF634[param_1].g0 += ((s32)p - (s32)slot[14]) >> 2;
}
// @class: regalloc-order
+21 -1
View File
@@ -387,7 +387,27 @@ void func_80128AF4(void) {
DEFINE_func_80128C14() /* dedup: shared engine-core @0x80128C14 (src/shared) */
INCLUDE_ASM("asm/ov_SC01_009/nonmatchings/ov_SC01_009", func_80128C98);
typedef struct {
s32 word0;
s32 word4;
} CdFileLoc_80128C98;
extern CdFileLoc_80128C98 cdFileLocTable[];
extern void func_8001ABBC(s32 a0, s32 a1, void *a2, s32 a3, s32 a4);
s32 func_80128C98(s32 arg0) {
extern s16 D_80182C28[];
s16 idx = D_80182C28[arg0];
if (idx >= 0) {
func_8001ABBC(0, 0, (u8 *)&cdFileLocTable[idx], D_801F06C0, 0);
} else {
return 1;
}
}
INCLUDE_ASM("asm/ov_SC01_009/nonmatchings/ov_SC01_009", func_80128CFC);
+78 -1
View File
@@ -481,7 +481,84 @@ INCLUDE_ASM("asm/ov_SC01_009/nonmatchings/ov_SC01_009_after", func_80146A6C);
DEFINE_func_80146AB4() /* dedup: shared engine-core @0x80146AB4 (src/shared) */
INCLUDE_ASM("asm/ov_SC01_009/nonmatchings/ov_SC01_009_after", func_80146AFC);
extern s32 func_80146B9C(void * arg0);
/* func_80146AFC — ASCENDING twin of the byte-proven DEFINE_func_80146B9C()
* in src/shared/engine_core.h (cookbook §71: find the already-matched sibling first).
* Same 0x58-stride slot table (base D_8011D030), same 7-store copy body in the same
* order, same $a2/$a1 giv pair. 80146B9C walks DOWN; this one walks UP, so the guard
* is `p < end`, end = p + 0xA50 (30 slots x 0x58).
*
* DECAY ROOT CAUSE (this redraft): the stored backlog draft had been rewritten to
* `void func_80146AFC(...)`, which drops BOTH `return 0` paths' `addu $v0,$zero,$zero`
* and the hit path's `j .L80146B94` => LENGTH-DRIFT -2 (38 vs 40) plus $v0/$v1 regalloc
* drift on the final lw/sw pair. Restoring the s32 return type (the fleet spelling the
* banked sibling func_80146B9C already uses) restores MATCH at 40/40.
*
* RECONCILE (2026-08-01) — the whole-binary gate failed with
* ov_SC01_077_after.c:592: conflicting types for `D_8011D030' (previous decl :564)
* TWO file-scope collisions were present; both are fixed HERE, with NO edit to
* src/shared/engine_core.h and NO change to the generated code (re-verified MATCH
* after each step):
*
* 1. D_8011D030 (the reported one). DEFINE_func_801469C8() emits
* `extern s32 D_8011D030;` at FILE scope (engine_core.h:10811, above the
* `s32 func_801469C8(...) {` line), and this TU expands that macro at :564 —
extern s32 D_8011D030;
* i.e. before the splice point :570. The draft's `extern u16` therefore
* redeclared it incompatibly at :592. Conformed to the TU's `extern s32`.
* Codegen-neutral: the sole use is `(u8 *)&D_8011D030`, an address-of, so the
* declared object type never reaches a load/store width (cookbook §20).
*
* 2. func_80146AFC ITSELF (latent, would have surfaced next). DEFINE_func_8014C010()
* (:13510) and DEFINE_func_8014AD30() (:13524) each emit a file-scope
* `extern void func_80146AFC(void *a0);`, and this TU expands them at :1386 and
* :1541 — after the splice — so an `s32 func_80146AFC` definition collides on the
* RETURN axis. Fixed with the §37/§124 ASM-LABEL ALIAS: the C identifier is
* aF80146AFC, the emitted label is func_80146AFC, so the canonical void decl and
* this s32 definition never share a namespace. Callers discard the result, so the
* void-typed call sites stay codegen-identical.
*
* Both were reproduced and then cleared against the real cpp+cc1-2.7.2 pair using a
* synthetic copy of this TU's declaration environment (.run/uc2/_recon_probe_80146AFC.c):
* the pre-reconcile spelling emits exactly the gate's error pair; the spelling below
* compiles clean.
*
* ORACLE: tools/match_one.py func_80146AFC --c .run/uc2/func_80146AFC.c
* --asm-subdir asm/ov_SC01_077/nonmatchings/ov_SC01_077_after -> MATCH (40 ins)
*/
s32 aF80146AFC(void *arg0) __asm__("func_80146AFC");
s32 aF80146AFC(void *arg0)
{
register u8 *p __asm__("$6");
register u8 *q __asm__("$5");
u8 *end;
p = (u8 *)&D_8011D030;
end = p + 0xA50;
if ((u32)p < (u32)end) {
q = p + 0x30;
do {
if (*(u16 *)p == 0) {
*(s32 *)(q + 0x4) = *(s32 *)((u8 *)arg0 + 0x8);
*(s16 *)p = *(u16 *)((u8 *)arg0 + 0x0);
*(s16 *)(q - 0x2A) = *(u16 *)((u8 *)arg0 + 0x2);
*(s16 *)(q - 0x26) = *(u16 *)((u8 *)arg0 + 0x4);
*(s16 *)(q - 0x22) = *(u16 *)((u8 *)arg0 + 0x6);
*(s32 *)(q - 0x4) = *(s32 *)((u8 *)arg0 + 0xC);
*(s32 *)(q + 0x0) = *(s32 *)((u8 *)arg0 + 0x10);
return (s32)p;
}
p += 0x58;
q += 0x58;
} while ((u32)p < (u32)end);
}
return 0;
}
DEFINE_func_80146B9C() /* dedup: shared engine-core @0x80146B9C (src/shared) */
+49 -1
View File
@@ -327,7 +327,55 @@ DEFINE_func_8012B70C() /* dedup: shared engine-core @0x8012B70C (src/shared) */
DEFINE_func_8012B744() /* dedup: shared engine-core @0x8012B744 (src/shared) */
INCLUDE_ASM("asm/ov_SC01_009/nonmatchings/ov_SC01_009_jr_8012ACE0", func_8012B77C);
extern s32 ratan2(s32 a0, s32 a1);
extern s32 func_80047948(s32 a0); /* rsin-like: angle (0..0xFFF) -> 1.12 fixed */
extern s32 func_8004787C(s32 a0); /* rcos-like: angle (0..0xFFF) -> 1.12 fixed */
/* The 4-byte destination is a PACKED PAIR of angles held entirely in ONE saved register
* ($s4) across all three calls — that is what produces the target's
* andi $s4,$s4,0xFFFF (read of the still-uninitialized local, hoisted into the prologue)
* ... or $s4,$s4,ang<<16 -> t.hi = yaw
* ... and $s4,$s4,0xFFFF0000 / or $s4,$s4,ang&0xFFFF -> t.lo = pitch
* A `struct { s16 lo, hi; }` has align 2 -> BLKmode-ish handling: gcc spills it to the stack
* and stores it with lwl/lwr + swl/swr (54 ins, 53 mismatched). Two 16-bit BITFIELDS in a
* u32 container give the SImode, align-4 struct gcc keeps in a register. */
typedef struct {
u32 lo : 16;
u32 hi : 16;
} Ang2_8012B77C_8012B77C;
/* a0 = destination packed-angle word, a1 = "from" entity, a2 = "to" entity.
* Both entities carry 16.16 fixed-point x/y/z at +0/+4/+8; the s16 reads at +2/+6/+0xA are
* the integer halves. Returns the destination pointer — the return value is REAL: without it
* gcc stores with `sw $s4,0($s3)` (57 ins) instead of the target's
* addu $v0,$s3,$zero ; sw $s4,0($v0) (the return-value copy that the store's base coalesces onto).
* The flattened `dz` reuse at the end is also load-bearing: making the (dz*sin + dx*cos)>>12
* temp its OWN variable gives it $a1 for the whole chain; reusing `dz` extends that allocno so
* it lands in $s5 exactly as the target does (`sra $s5,$v0,12` / `negu $a1,$s5`), and it also
* demotes dz's priority so the saved-reg order comes out $s3=out, $s4=t, $s5=dz. */
s32 func_8012B77C(s32 out, s32 from, s32 to) {
Ang2_8012B77C_8012B77C t;
s32 dx, dy, dz;
s32 ang;
s32 r1, r2;
dz = *(s16 *)(to + 0xA) - *(s16 *)(from + 0xA);
dx = *(s16 *)(to + 0x2) - *(s16 *)(from + 0x2);
dy = *(s16 *)(to + 0x6) - *(s16 *)(from + 0x6);
ang = (ratan2(-dz, dx) - 0x400) & 0xFFF;
t.hi = ang;
r1 = func_80047948(ang);
r2 = func_8004787C(ang);
dz = (dz * r1 + dx * r2) >> 12;
t.lo = ratan2(dy, -dz);
*(Ang2_8012B77C_8012B77C *)out = t;
return out;
}
DEFINE_func_8012B864() /* dedup: shared engine-core @0x8012B864 (src/shared) */
+74 -1
View File
@@ -3172,7 +3172,80 @@ void func_80175DA8(param_1)
}
INCLUDE_ASM("asm/ov_SC01_009/nonmatchings/ov_SC01_009_jr_801734BC", func_80176144);
/* func_80176144 — RECONCILED variant of .run/uc/func_80176144.c
*
* GATE BLOCKER (whole-binary build, NOT match_one):
* src/ov_SC01_077/ov_SC01_077_jr_801734BC.c:3476: conflicting types for `D_800AF634'
* || previous declaration at :3296
*
* ROOT CAUSE — a HOISTED file-scope typedef, not a bad signature:
* That TU hoists, at FILE scope, for func_80175DA8:
* :3295 typedef struct { s32 g0; s32 pad[2]; } S_AF634_80176144;
* :3296 extern S_AF634_80176144 D_800AF634[];
* :3297 extern S_AF634_80176144 D_800AF638[];
* The stored draft re-declares the SAME struct shape as a BLOCK-scope typedef
* (rule D — it must travel to the 137 sibling overlays, which have no such
* preamble). A block-scope `typedef struct {...} S_AF634_80176144;` is a DISTINCT type
* from the file-scope one (C has no structural typing), so the block-scope
* `extern S_AF634_80176144 D_800AF634[];` re-declares the symbol incompatibly with the
* in-scope file-scope decl -> hard error.
* Note the earlier block-scope copies in the same TU (:3080 func_80175820,
* :3123 func_801759D8) do NOT error: they precede :3296, so no file-scope decl
* of D_800AF634 is in scope there. Anything AFTER :3296 collides. Our
* definition lands at :3476. That is why only this one fired.
*
* FIX — §37/§124 ASM-LABEL ALIAS applied to the DATA symbols (cookbook §2516:
* "asm-label alias for sibling-decl signedness/proto conflicts ... beats
* reconcile's *(u16*)&D_x cast whose address-of PERTURBS regalloc"):
* the two objects are reached through PRIVATE C identifiers aAF634 / aAF638
* carrying __asm__("D_800AF634") / __asm__("D_800AF638"). The emitted
* %hi/%lo relocations are against the same symbols, so codegen is unchanged,
* while the C names can never collide with ANY sibling TU's declaration —
* whether hoisted, block-scope, or absent. No header edit; no src/ edit.
* Strictly better than deleting the local decls (which would bind this
* exemplar to the one TU that happens to hoist them).
*
* The s32 parameter + explicit (s16) narrowing is retained from the stored draft
* (canonical decl in engine_core.h:18985/:4587 is `void func_80176144(s32)`;
* the K&R short param would itself be a conflicting-types error). The (s16)
* narrowing IS the entry `sll $s0,$a0,16 / sra $s0,$s0,16` pair.
*
* Verified: python3 tools/match_one.py func_80176144 --c .run/uc2/func_80176144.c
* --asm-subdir ov_SC01_077/nonmatchings/ov_SC01_077_jr_801734BC -> MATCH (53 ins)
*/
void func_80176144(s32 a0)
{
typedef struct { s32 g0; s32 pad[2]; } S_AF634_80176144; /* size 0x0C */
/* §37 asm-label alias: private C names, canonical relocations. */
extern S_AF634_80176144 aAF634[] __asm__("D_800AF634");
extern S_AF634_80176144 aAF638[] __asm__("D_800AF638");
extern u8 D_8011F7A8;
extern s16 D_8011F7BC;
extern s16 D_8011F7BE;
extern s32 func_80178004(s32 a0, s32 a1, s32 a2);
u32 *slot;
u32 *p;
s16 param_1 = (s16)a0;
p = (u32 *)(aAF638[param_1].g0 + aAF634[param_1].g0 * 4);
slot = (u32 *)(param_1 * 4 + (s32)&D_8011F7A8);
slot[14] = (u32)p;
/* §5a zero-byte sched fence: without it sched1 hoists the two %hi/lhu global
argument loads above the `sw` of slot[14] (16 mismatches, 0 length drift). */
__asm__("");
p = (u32 *)func_80178004((s32)p,
(s16)((*(u16 *)&D_8011F7BC) - 0x17),
(s16)((*(u16 *)&D_8011F7BE) + 0x65));
slot[16] = (u32)p - 0x14;
p += 5;
aAF634[param_1].g0 += ((s32)p - (s32)slot[14]) >> 2;
}
// @class: regalloc-order
+21 -1
View File
@@ -387,7 +387,27 @@ void func_80128AF4(void) {
DEFINE_func_80128C14() /* dedup: shared engine-core @0x80128C14 (src/shared) */
INCLUDE_ASM("asm/ov_SC01_074/nonmatchings/ov_SC01_074", func_80128C98);
typedef struct {
s32 word0;
s32 word4;
} CdFileLoc_80128C98;
extern CdFileLoc_80128C98 cdFileLocTable[];
extern void func_8001ABBC(s32 a0, s32 a1, void *a2, s32 a3, s32 a4);
s32 func_80128C98(s32 arg0) {
extern s16 D_8017E8A8[];
s16 idx = D_8017E8A8[arg0];
if (idx >= 0) {
func_8001ABBC(0, 0, (u8 *)&cdFileLocTable[idx], D_80199750, 0);
} else {
return 1;
}
}
INCLUDE_ASM("asm/ov_SC01_074/nonmatchings/ov_SC01_074", func_80128CFC);
+78 -1
View File
@@ -481,7 +481,84 @@ INCLUDE_ASM("asm/ov_SC01_074/nonmatchings/ov_SC01_074_after", func_80146A6C);
DEFINE_func_80146AB4() /* dedup: shared engine-core @0x80146AB4 (src/shared) */
INCLUDE_ASM("asm/ov_SC01_074/nonmatchings/ov_SC01_074_after", func_80146AFC);
extern s32 func_80146B9C(void * arg0);
/* func_80146AFC — ASCENDING twin of the byte-proven DEFINE_func_80146B9C()
* in src/shared/engine_core.h (cookbook §71: find the already-matched sibling first).
* Same 0x58-stride slot table (base D_8011D030), same 7-store copy body in the same
* order, same $a2/$a1 giv pair. 80146B9C walks DOWN; this one walks UP, so the guard
* is `p < end`, end = p + 0xA50 (30 slots x 0x58).
*
* DECAY ROOT CAUSE (this redraft): the stored backlog draft had been rewritten to
* `void func_80146AFC(...)`, which drops BOTH `return 0` paths' `addu $v0,$zero,$zero`
* and the hit path's `j .L80146B94` => LENGTH-DRIFT -2 (38 vs 40) plus $v0/$v1 regalloc
* drift on the final lw/sw pair. Restoring the s32 return type (the fleet spelling the
* banked sibling func_80146B9C already uses) restores MATCH at 40/40.
*
* RECONCILE (2026-08-01) — the whole-binary gate failed with
* ov_SC01_077_after.c:592: conflicting types for `D_8011D030' (previous decl :564)
* TWO file-scope collisions were present; both are fixed HERE, with NO edit to
* src/shared/engine_core.h and NO change to the generated code (re-verified MATCH
* after each step):
*
* 1. D_8011D030 (the reported one). DEFINE_func_801469C8() emits
* `extern s32 D_8011D030;` at FILE scope (engine_core.h:10811, above the
* `s32 func_801469C8(...) {` line), and this TU expands that macro at :564 —
extern s32 D_8011D030;
* i.e. before the splice point :570. The draft's `extern u16` therefore
* redeclared it incompatibly at :592. Conformed to the TU's `extern s32`.
* Codegen-neutral: the sole use is `(u8 *)&D_8011D030`, an address-of, so the
* declared object type never reaches a load/store width (cookbook §20).
*
* 2. func_80146AFC ITSELF (latent, would have surfaced next). DEFINE_func_8014C010()
* (:13510) and DEFINE_func_8014AD30() (:13524) each emit a file-scope
* `extern void func_80146AFC(void *a0);`, and this TU expands them at :1386 and
* :1541 — after the splice — so an `s32 func_80146AFC` definition collides on the
* RETURN axis. Fixed with the §37/§124 ASM-LABEL ALIAS: the C identifier is
* aF80146AFC, the emitted label is func_80146AFC, so the canonical void decl and
* this s32 definition never share a namespace. Callers discard the result, so the
* void-typed call sites stay codegen-identical.
*
* Both were reproduced and then cleared against the real cpp+cc1-2.7.2 pair using a
* synthetic copy of this TU's declaration environment (.run/uc2/_recon_probe_80146AFC.c):
* the pre-reconcile spelling emits exactly the gate's error pair; the spelling below
* compiles clean.
*
* ORACLE: tools/match_one.py func_80146AFC --c .run/uc2/func_80146AFC.c
* --asm-subdir asm/ov_SC01_077/nonmatchings/ov_SC01_077_after -> MATCH (40 ins)
*/
s32 aF80146AFC(void *arg0) __asm__("func_80146AFC");
s32 aF80146AFC(void *arg0)
{
register u8 *p __asm__("$6");
register u8 *q __asm__("$5");
u8 *end;
p = (u8 *)&D_8011D030;
end = p + 0xA50;
if ((u32)p < (u32)end) {
q = p + 0x30;
do {
if (*(u16 *)p == 0) {
*(s32 *)(q + 0x4) = *(s32 *)((u8 *)arg0 + 0x8);
*(s16 *)p = *(u16 *)((u8 *)arg0 + 0x0);
*(s16 *)(q - 0x2A) = *(u16 *)((u8 *)arg0 + 0x2);
*(s16 *)(q - 0x26) = *(u16 *)((u8 *)arg0 + 0x4);
*(s16 *)(q - 0x22) = *(u16 *)((u8 *)arg0 + 0x6);
*(s32 *)(q - 0x4) = *(s32 *)((u8 *)arg0 + 0xC);
*(s32 *)(q + 0x0) = *(s32 *)((u8 *)arg0 + 0x10);
return (s32)p;
}
p += 0x58;
q += 0x58;
} while ((u32)p < (u32)end);
}
return 0;
}
DEFINE_func_80146B9C() /* dedup: shared engine-core @0x80146B9C (src/shared) */
+49 -1
View File
@@ -327,7 +327,55 @@ DEFINE_func_8012B70C() /* dedup: shared engine-core @0x8012B70C (src/shared) */
DEFINE_func_8012B744() /* dedup: shared engine-core @0x8012B744 (src/shared) */
INCLUDE_ASM("asm/ov_SC01_074/nonmatchings/ov_SC01_074_jr_8012ACE0", func_8012B77C);
extern s32 ratan2(s32 a0, s32 a1);
extern s32 func_80047948(s32 a0); /* rsin-like: angle (0..0xFFF) -> 1.12 fixed */
extern s32 func_8004787C(s32 a0); /* rcos-like: angle (0..0xFFF) -> 1.12 fixed */
/* The 4-byte destination is a PACKED PAIR of angles held entirely in ONE saved register
* ($s4) across all three calls — that is what produces the target's
* andi $s4,$s4,0xFFFF (read of the still-uninitialized local, hoisted into the prologue)
* ... or $s4,$s4,ang<<16 -> t.hi = yaw
* ... and $s4,$s4,0xFFFF0000 / or $s4,$s4,ang&0xFFFF -> t.lo = pitch
* A `struct { s16 lo, hi; }` has align 2 -> BLKmode-ish handling: gcc spills it to the stack
* and stores it with lwl/lwr + swl/swr (54 ins, 53 mismatched). Two 16-bit BITFIELDS in a
* u32 container give the SImode, align-4 struct gcc keeps in a register. */
typedef struct {
u32 lo : 16;
u32 hi : 16;
} Ang2_8012B77C_8012B77C;
/* a0 = destination packed-angle word, a1 = "from" entity, a2 = "to" entity.
* Both entities carry 16.16 fixed-point x/y/z at +0/+4/+8; the s16 reads at +2/+6/+0xA are
* the integer halves. Returns the destination pointer — the return value is REAL: without it
* gcc stores with `sw $s4,0($s3)` (57 ins) instead of the target's
* addu $v0,$s3,$zero ; sw $s4,0($v0) (the return-value copy that the store's base coalesces onto).
* The flattened `dz` reuse at the end is also load-bearing: making the (dz*sin + dx*cos)>>12
* temp its OWN variable gives it $a1 for the whole chain; reusing `dz` extends that allocno so
* it lands in $s5 exactly as the target does (`sra $s5,$v0,12` / `negu $a1,$s5`), and it also
* demotes dz's priority so the saved-reg order comes out $s3=out, $s4=t, $s5=dz. */
s32 func_8012B77C(s32 out, s32 from, s32 to) {
Ang2_8012B77C_8012B77C t;
s32 dx, dy, dz;
s32 ang;
s32 r1, r2;
dz = *(s16 *)(to + 0xA) - *(s16 *)(from + 0xA);
dx = *(s16 *)(to + 0x2) - *(s16 *)(from + 0x2);
dy = *(s16 *)(to + 0x6) - *(s16 *)(from + 0x6);
ang = (ratan2(-dz, dx) - 0x400) & 0xFFF;
t.hi = ang;
r1 = func_80047948(ang);
r2 = func_8004787C(ang);
dz = (dz * r1 + dx * r2) >> 12;
t.lo = ratan2(dy, -dz);
*(Ang2_8012B77C_8012B77C *)out = t;
return out;
}
DEFINE_func_8012B864() /* dedup: shared engine-core @0x8012B864 (src/shared) */
+74 -1
View File
@@ -3172,7 +3172,80 @@ void func_80175DA8(param_1)
}
INCLUDE_ASM("asm/ov_SC01_074/nonmatchings/ov_SC01_074_jr_801734BC", func_80176144);
/* func_80176144 — RECONCILED variant of .run/uc/func_80176144.c
*
* GATE BLOCKER (whole-binary build, NOT match_one):
* src/ov_SC01_077/ov_SC01_077_jr_801734BC.c:3476: conflicting types for `D_800AF634'
* || previous declaration at :3296
*
* ROOT CAUSE — a HOISTED file-scope typedef, not a bad signature:
* That TU hoists, at FILE scope, for func_80175DA8:
* :3295 typedef struct { s32 g0; s32 pad[2]; } S_AF634_80176144;
* :3296 extern S_AF634_80176144 D_800AF634[];
* :3297 extern S_AF634_80176144 D_800AF638[];
* The stored draft re-declares the SAME struct shape as a BLOCK-scope typedef
* (rule D — it must travel to the 137 sibling overlays, which have no such
* preamble). A block-scope `typedef struct {...} S_AF634_80176144;` is a DISTINCT type
* from the file-scope one (C has no structural typing), so the block-scope
* `extern S_AF634_80176144 D_800AF634[];` re-declares the symbol incompatibly with the
* in-scope file-scope decl -> hard error.
* Note the earlier block-scope copies in the same TU (:3080 func_80175820,
* :3123 func_801759D8) do NOT error: they precede :3296, so no file-scope decl
* of D_800AF634 is in scope there. Anything AFTER :3296 collides. Our
* definition lands at :3476. That is why only this one fired.
*
* FIX — §37/§124 ASM-LABEL ALIAS applied to the DATA symbols (cookbook §2516:
* "asm-label alias for sibling-decl signedness/proto conflicts ... beats
* reconcile's *(u16*)&D_x cast whose address-of PERTURBS regalloc"):
* the two objects are reached through PRIVATE C identifiers aAF634 / aAF638
* carrying __asm__("D_800AF634") / __asm__("D_800AF638"). The emitted
* %hi/%lo relocations are against the same symbols, so codegen is unchanged,
* while the C names can never collide with ANY sibling TU's declaration —
* whether hoisted, block-scope, or absent. No header edit; no src/ edit.
* Strictly better than deleting the local decls (which would bind this
* exemplar to the one TU that happens to hoist them).
*
* The s32 parameter + explicit (s16) narrowing is retained from the stored draft
* (canonical decl in engine_core.h:18985/:4587 is `void func_80176144(s32)`;
* the K&R short param would itself be a conflicting-types error). The (s16)
* narrowing IS the entry `sll $s0,$a0,16 / sra $s0,$s0,16` pair.
*
* Verified: python3 tools/match_one.py func_80176144 --c .run/uc2/func_80176144.c
* --asm-subdir ov_SC01_077/nonmatchings/ov_SC01_077_jr_801734BC -> MATCH (53 ins)
*/
void func_80176144(s32 a0)
{
typedef struct { s32 g0; s32 pad[2]; } S_AF634_80176144; /* size 0x0C */
/* §37 asm-label alias: private C names, canonical relocations. */
extern S_AF634_80176144 aAF634[] __asm__("D_800AF634");
extern S_AF634_80176144 aAF638[] __asm__("D_800AF638");
extern u8 D_8011F7A8;
extern s16 D_8011F7BC;
extern s16 D_8011F7BE;
extern s32 func_80178004(s32 a0, s32 a1, s32 a2);
u32 *slot;
u32 *p;
s16 param_1 = (s16)a0;
p = (u32 *)(aAF638[param_1].g0 + aAF634[param_1].g0 * 4);
slot = (u32 *)(param_1 * 4 + (s32)&D_8011F7A8);
slot[14] = (u32)p;
/* §5a zero-byte sched fence: without it sched1 hoists the two %hi/lhu global
argument loads above the `sw` of slot[14] (16 mismatches, 0 length drift). */
__asm__("");
p = (u32 *)func_80178004((s32)p,
(s16)((*(u16 *)&D_8011F7BC) - 0x17),
(s16)((*(u16 *)&D_8011F7BE) + 0x65));
slot[16] = (u32)p - 0x14;
p += 5;
aAF634[param_1].g0 += ((s32)p - (s32)slot[14]) >> 2;
}
// @class: regalloc-order
+49 -1
View File
@@ -397,7 +397,55 @@ DEFINE_func_8012B70C() /* dedup: shared engine-core @0x8012B70C (src/shared) */
DEFINE_func_8012B744() /* dedup: shared engine-core @0x8012B744 (src/shared) */
INCLUDE_ASM("asm/ov_SC01_077/nonmatchings/ov_SC01_077_jr_8012ACE0", func_8012B77C);
extern s32 ratan2(s32 a0, s32 a1);
extern s32 func_80047948(s32 a0); /* rsin-like: angle (0..0xFFF) -> 1.12 fixed */
extern s32 func_8004787C(s32 a0); /* rcos-like: angle (0..0xFFF) -> 1.12 fixed */
/* The 4-byte destination is a PACKED PAIR of angles held entirely in ONE saved register
* ($s4) across all three calls — that is what produces the target's
* andi $s4,$s4,0xFFFF (read of the still-uninitialized local, hoisted into the prologue)
* ... or $s4,$s4,ang<<16 -> t.hi = yaw
* ... and $s4,$s4,0xFFFF0000 / or $s4,$s4,ang&0xFFFF -> t.lo = pitch
* A `struct { s16 lo, hi; }` has align 2 -> BLKmode-ish handling: gcc spills it to the stack
* and stores it with lwl/lwr + swl/swr (54 ins, 53 mismatched). Two 16-bit BITFIELDS in a
* u32 container give the SImode, align-4 struct gcc keeps in a register. */
typedef struct {
u32 lo : 16;
u32 hi : 16;
} Ang2_8012B77C_8012B77C;
/* a0 = destination packed-angle word, a1 = "from" entity, a2 = "to" entity.
* Both entities carry 16.16 fixed-point x/y/z at +0/+4/+8; the s16 reads at +2/+6/+0xA are
* the integer halves. Returns the destination pointer — the return value is REAL: without it
* gcc stores with `sw $s4,0($s3)` (57 ins) instead of the target's
* addu $v0,$s3,$zero ; sw $s4,0($v0) (the return-value copy that the store's base coalesces onto).
* The flattened `dz` reuse at the end is also load-bearing: making the (dz*sin + dx*cos)>>12
* temp its OWN variable gives it $a1 for the whole chain; reusing `dz` extends that allocno so
* it lands in $s5 exactly as the target does (`sra $s5,$v0,12` / `negu $a1,$s5`), and it also
* demotes dz's priority so the saved-reg order comes out $s3=out, $s4=t, $s5=dz. */
s32 func_8012B77C(s32 out, s32 from, s32 to) {
Ang2_8012B77C_8012B77C t;
s32 dx, dy, dz;
s32 ang;
s32 r1, r2;
dz = *(s16 *)(to + 0xA) - *(s16 *)(from + 0xA);
dx = *(s16 *)(to + 0x2) - *(s16 *)(from + 0x2);
dy = *(s16 *)(to + 0x6) - *(s16 *)(from + 0x6);
ang = (ratan2(-dz, dx) - 0x400) & 0xFFF;
t.hi = ang;
r1 = func_80047948(ang);
r2 = func_8004787C(ang);
dz = (dz * r1 + dx * r2) >> 12;
t.lo = ratan2(dy, -dz);
*(Ang2_8012B77C_8012B77C *)out = t;
return out;
}
DEFINE_func_8012B864() /* dedup: shared engine-core @0x8012B864 (src/shared) */
+21 -1
View File
@@ -387,7 +387,27 @@ void func_80128AF4(void) {
DEFINE_func_80128C14() /* dedup: shared engine-core @0x80128C14 (src/shared) */
INCLUDE_ASM("asm/ov_SC01_080/nonmatchings/ov_SC01_080", func_80128C98);
typedef struct {
s32 word0;
s32 word4;
} CdFileLoc_80128C98;
extern CdFileLoc_80128C98 cdFileLocTable[];
extern void func_8001ABBC(s32 a0, s32 a1, void *a2, s32 a3, s32 a4);
s32 func_80128C98(s32 arg0) {
extern s16 D_80183808[];
s16 idx = D_80183808[arg0];
if (idx >= 0) {
func_8001ABBC(0, 0, (u8 *)&cdFileLocTable[idx], D_801C3570, 0);
} else {
return 1;
}
}
INCLUDE_ASM("asm/ov_SC01_080/nonmatchings/ov_SC01_080", func_80128CFC);
+78 -1
View File
@@ -481,7 +481,84 @@ INCLUDE_ASM("asm/ov_SC01_080/nonmatchings/ov_SC01_080_after", func_80146A6C);
DEFINE_func_80146AB4() /* dedup: shared engine-core @0x80146AB4 (src/shared) */
INCLUDE_ASM("asm/ov_SC01_080/nonmatchings/ov_SC01_080_after", func_80146AFC);
extern s32 func_80146B9C(void * arg0);
/* func_80146AFC — ASCENDING twin of the byte-proven DEFINE_func_80146B9C()
* in src/shared/engine_core.h (cookbook §71: find the already-matched sibling first).
* Same 0x58-stride slot table (base D_8011D030), same 7-store copy body in the same
* order, same $a2/$a1 giv pair. 80146B9C walks DOWN; this one walks UP, so the guard
* is `p < end`, end = p + 0xA50 (30 slots x 0x58).
*
* DECAY ROOT CAUSE (this redraft): the stored backlog draft had been rewritten to
* `void func_80146AFC(...)`, which drops BOTH `return 0` paths' `addu $v0,$zero,$zero`
* and the hit path's `j .L80146B94` => LENGTH-DRIFT -2 (38 vs 40) plus $v0/$v1 regalloc
* drift on the final lw/sw pair. Restoring the s32 return type (the fleet spelling the
* banked sibling func_80146B9C already uses) restores MATCH at 40/40.
*
* RECONCILE (2026-08-01) — the whole-binary gate failed with
* ov_SC01_077_after.c:592: conflicting types for `D_8011D030' (previous decl :564)
* TWO file-scope collisions were present; both are fixed HERE, with NO edit to
* src/shared/engine_core.h and NO change to the generated code (re-verified MATCH
* after each step):
*
* 1. D_8011D030 (the reported one). DEFINE_func_801469C8() emits
* `extern s32 D_8011D030;` at FILE scope (engine_core.h:10811, above the
* `s32 func_801469C8(...) {` line), and this TU expands that macro at :564 —
extern s32 D_8011D030;
* i.e. before the splice point :570. The draft's `extern u16` therefore
* redeclared it incompatibly at :592. Conformed to the TU's `extern s32`.
* Codegen-neutral: the sole use is `(u8 *)&D_8011D030`, an address-of, so the
* declared object type never reaches a load/store width (cookbook §20).
*
* 2. func_80146AFC ITSELF (latent, would have surfaced next). DEFINE_func_8014C010()
* (:13510) and DEFINE_func_8014AD30() (:13524) each emit a file-scope
* `extern void func_80146AFC(void *a0);`, and this TU expands them at :1386 and
* :1541 — after the splice — so an `s32 func_80146AFC` definition collides on the
* RETURN axis. Fixed with the §37/§124 ASM-LABEL ALIAS: the C identifier is
* aF80146AFC, the emitted label is func_80146AFC, so the canonical void decl and
* this s32 definition never share a namespace. Callers discard the result, so the
* void-typed call sites stay codegen-identical.
*
* Both were reproduced and then cleared against the real cpp+cc1-2.7.2 pair using a
* synthetic copy of this TU's declaration environment (.run/uc2/_recon_probe_80146AFC.c):
* the pre-reconcile spelling emits exactly the gate's error pair; the spelling below
* compiles clean.
*
* ORACLE: tools/match_one.py func_80146AFC --c .run/uc2/func_80146AFC.c
* --asm-subdir asm/ov_SC01_077/nonmatchings/ov_SC01_077_after -> MATCH (40 ins)
*/
s32 aF80146AFC(void *arg0) __asm__("func_80146AFC");
s32 aF80146AFC(void *arg0)
{
register u8 *p __asm__("$6");
register u8 *q __asm__("$5");
u8 *end;
p = (u8 *)&D_8011D030;
end = p + 0xA50;
if ((u32)p < (u32)end) {
q = p + 0x30;
do {
if (*(u16 *)p == 0) {
*(s32 *)(q + 0x4) = *(s32 *)((u8 *)arg0 + 0x8);
*(s16 *)p = *(u16 *)((u8 *)arg0 + 0x0);
*(s16 *)(q - 0x2A) = *(u16 *)((u8 *)arg0 + 0x2);
*(s16 *)(q - 0x26) = *(u16 *)((u8 *)arg0 + 0x4);
*(s16 *)(q - 0x22) = *(u16 *)((u8 *)arg0 + 0x6);
*(s32 *)(q - 0x4) = *(s32 *)((u8 *)arg0 + 0xC);
*(s32 *)(q + 0x0) = *(s32 *)((u8 *)arg0 + 0x10);
return (s32)p;
}
p += 0x58;
q += 0x58;
} while ((u32)p < (u32)end);
}
return 0;
}
DEFINE_func_80146B9C() /* dedup: shared engine-core @0x80146B9C (src/shared) */
+49 -1
View File
@@ -327,7 +327,55 @@ DEFINE_func_8012B70C() /* dedup: shared engine-core @0x8012B70C (src/shared) */
DEFINE_func_8012B744() /* dedup: shared engine-core @0x8012B744 (src/shared) */
INCLUDE_ASM("asm/ov_SC01_080/nonmatchings/ov_SC01_080_jr_8012ACE0", func_8012B77C);
extern s32 ratan2(s32 a0, s32 a1);
extern s32 func_80047948(s32 a0); /* rsin-like: angle (0..0xFFF) -> 1.12 fixed */
extern s32 func_8004787C(s32 a0); /* rcos-like: angle (0..0xFFF) -> 1.12 fixed */
/* The 4-byte destination is a PACKED PAIR of angles held entirely in ONE saved register
* ($s4) across all three calls — that is what produces the target's
* andi $s4,$s4,0xFFFF (read of the still-uninitialized local, hoisted into the prologue)
* ... or $s4,$s4,ang<<16 -> t.hi = yaw
* ... and $s4,$s4,0xFFFF0000 / or $s4,$s4,ang&0xFFFF -> t.lo = pitch
* A `struct { s16 lo, hi; }` has align 2 -> BLKmode-ish handling: gcc spills it to the stack
* and stores it with lwl/lwr + swl/swr (54 ins, 53 mismatched). Two 16-bit BITFIELDS in a
* u32 container give the SImode, align-4 struct gcc keeps in a register. */
typedef struct {
u32 lo : 16;
u32 hi : 16;
} Ang2_8012B77C_8012B77C;
/* a0 = destination packed-angle word, a1 = "from" entity, a2 = "to" entity.
* Both entities carry 16.16 fixed-point x/y/z at +0/+4/+8; the s16 reads at +2/+6/+0xA are
* the integer halves. Returns the destination pointer — the return value is REAL: without it
* gcc stores with `sw $s4,0($s3)` (57 ins) instead of the target's
* addu $v0,$s3,$zero ; sw $s4,0($v0) (the return-value copy that the store's base coalesces onto).
* The flattened `dz` reuse at the end is also load-bearing: making the (dz*sin + dx*cos)>>12
* temp its OWN variable gives it $a1 for the whole chain; reusing `dz` extends that allocno so
* it lands in $s5 exactly as the target does (`sra $s5,$v0,12` / `negu $a1,$s5`), and it also
* demotes dz's priority so the saved-reg order comes out $s3=out, $s4=t, $s5=dz. */
s32 func_8012B77C(s32 out, s32 from, s32 to) {
Ang2_8012B77C_8012B77C t;
s32 dx, dy, dz;
s32 ang;
s32 r1, r2;
dz = *(s16 *)(to + 0xA) - *(s16 *)(from + 0xA);
dx = *(s16 *)(to + 0x2) - *(s16 *)(from + 0x2);
dy = *(s16 *)(to + 0x6) - *(s16 *)(from + 0x6);
ang = (ratan2(-dz, dx) - 0x400) & 0xFFF;
t.hi = ang;
r1 = func_80047948(ang);
r2 = func_8004787C(ang);
dz = (dz * r1 + dx * r2) >> 12;
t.lo = ratan2(dy, -dz);
*(Ang2_8012B77C_8012B77C *)out = t;
return out;
}
DEFINE_func_8012B864() /* dedup: shared engine-core @0x8012B864 (src/shared) */
+74 -1
View File
@@ -3172,7 +3172,80 @@ void func_80175DA8(param_1)
}
INCLUDE_ASM("asm/ov_SC01_080/nonmatchings/ov_SC01_080_jr_801734BC", func_80176144);
/* func_80176144 — RECONCILED variant of .run/uc/func_80176144.c
*
* GATE BLOCKER (whole-binary build, NOT match_one):
* src/ov_SC01_077/ov_SC01_077_jr_801734BC.c:3476: conflicting types for `D_800AF634'
* || previous declaration at :3296
*
* ROOT CAUSE — a HOISTED file-scope typedef, not a bad signature:
* That TU hoists, at FILE scope, for func_80175DA8:
* :3295 typedef struct { s32 g0; s32 pad[2]; } S_AF634_80176144;
* :3296 extern S_AF634_80176144 D_800AF634[];
* :3297 extern S_AF634_80176144 D_800AF638[];
* The stored draft re-declares the SAME struct shape as a BLOCK-scope typedef
* (rule D — it must travel to the 137 sibling overlays, which have no such
* preamble). A block-scope `typedef struct {...} S_AF634_80176144;` is a DISTINCT type
* from the file-scope one (C has no structural typing), so the block-scope
* `extern S_AF634_80176144 D_800AF634[];` re-declares the symbol incompatibly with the
* in-scope file-scope decl -> hard error.
* Note the earlier block-scope copies in the same TU (:3080 func_80175820,
* :3123 func_801759D8) do NOT error: they precede :3296, so no file-scope decl
* of D_800AF634 is in scope there. Anything AFTER :3296 collides. Our
* definition lands at :3476. That is why only this one fired.
*
* FIX — §37/§124 ASM-LABEL ALIAS applied to the DATA symbols (cookbook §2516:
* "asm-label alias for sibling-decl signedness/proto conflicts ... beats
* reconcile's *(u16*)&D_x cast whose address-of PERTURBS regalloc"):
* the two objects are reached through PRIVATE C identifiers aAF634 / aAF638
* carrying __asm__("D_800AF634") / __asm__("D_800AF638"). The emitted
* %hi/%lo relocations are against the same symbols, so codegen is unchanged,
* while the C names can never collide with ANY sibling TU's declaration —
* whether hoisted, block-scope, or absent. No header edit; no src/ edit.
* Strictly better than deleting the local decls (which would bind this
* exemplar to the one TU that happens to hoist them).
*
* The s32 parameter + explicit (s16) narrowing is retained from the stored draft
* (canonical decl in engine_core.h:18985/:4587 is `void func_80176144(s32)`;
* the K&R short param would itself be a conflicting-types error). The (s16)
* narrowing IS the entry `sll $s0,$a0,16 / sra $s0,$s0,16` pair.
*
* Verified: python3 tools/match_one.py func_80176144 --c .run/uc2/func_80176144.c
* --asm-subdir ov_SC01_077/nonmatchings/ov_SC01_077_jr_801734BC -> MATCH (53 ins)
*/
void func_80176144(s32 a0)
{
typedef struct { s32 g0; s32 pad[2]; } S_AF634_80176144; /* size 0x0C */
/* §37 asm-label alias: private C names, canonical relocations. */
extern S_AF634_80176144 aAF634[] __asm__("D_800AF634");
extern S_AF634_80176144 aAF638[] __asm__("D_800AF638");
extern u8 D_8011F7A8;
extern s16 D_8011F7BC;
extern s16 D_8011F7BE;
extern s32 func_80178004(s32 a0, s32 a1, s32 a2);
u32 *slot;
u32 *p;
s16 param_1 = (s16)a0;
p = (u32 *)(aAF638[param_1].g0 + aAF634[param_1].g0 * 4);
slot = (u32 *)(param_1 * 4 + (s32)&D_8011F7A8);
slot[14] = (u32)p;
/* §5a zero-byte sched fence: without it sched1 hoists the two %hi/lhu global
argument loads above the `sw` of slot[14] (16 mismatches, 0 length drift). */
__asm__("");
p = (u32 *)func_80178004((s32)p,
(s16)((*(u16 *)&D_8011F7BC) - 0x17),
(s16)((*(u16 *)&D_8011F7BE) + 0x65));
slot[16] = (u32)p - 0x14;
p += 5;
aAF634[param_1].g0 += ((s32)p - (s32)slot[14]) >> 2;
}
// @class: regalloc-order
+21 -1
View File
@@ -387,7 +387,27 @@ void func_80128AF4(void) {
DEFINE_func_80128C14() /* dedup: shared engine-core @0x80128C14 (src/shared) */
INCLUDE_ASM("asm/ov_SC01_084/nonmatchings/ov_SC01_084", func_80128C98);
typedef struct {
s32 word0;
s32 word4;
} CdFileLoc_80128C98;
extern CdFileLoc_80128C98 cdFileLocTable[];
extern void func_8001ABBC(s32 a0, s32 a1, void *a2, s32 a3, s32 a4);
s32 func_80128C98(s32 arg0) {
extern s16 D_80186AFC[];
s16 idx = D_80186AFC[arg0];
if (idx >= 0) {
func_8001ABBC(0, 0, (u8 *)&cdFileLocTable[idx], D_801C4F40, 0);
} else {
return 1;
}
}
INCLUDE_ASM("asm/ov_SC01_084/nonmatchings/ov_SC01_084", func_80128CFC);
+78 -1
View File
@@ -481,7 +481,84 @@ INCLUDE_ASM("asm/ov_SC01_084/nonmatchings/ov_SC01_084_after", func_80146A6C);
DEFINE_func_80146AB4() /* dedup: shared engine-core @0x80146AB4 (src/shared) */
INCLUDE_ASM("asm/ov_SC01_084/nonmatchings/ov_SC01_084_after", func_80146AFC);
extern s32 func_80146B9C(void * arg0);
/* func_80146AFC — ASCENDING twin of the byte-proven DEFINE_func_80146B9C()
* in src/shared/engine_core.h (cookbook §71: find the already-matched sibling first).
* Same 0x58-stride slot table (base D_8011D030), same 7-store copy body in the same
* order, same $a2/$a1 giv pair. 80146B9C walks DOWN; this one walks UP, so the guard
* is `p < end`, end = p + 0xA50 (30 slots x 0x58).
*
* DECAY ROOT CAUSE (this redraft): the stored backlog draft had been rewritten to
* `void func_80146AFC(...)`, which drops BOTH `return 0` paths' `addu $v0,$zero,$zero`
* and the hit path's `j .L80146B94` => LENGTH-DRIFT -2 (38 vs 40) plus $v0/$v1 regalloc
* drift on the final lw/sw pair. Restoring the s32 return type (the fleet spelling the
* banked sibling func_80146B9C already uses) restores MATCH at 40/40.
*
* RECONCILE (2026-08-01) — the whole-binary gate failed with
* ov_SC01_077_after.c:592: conflicting types for `D_8011D030' (previous decl :564)
* TWO file-scope collisions were present; both are fixed HERE, with NO edit to
* src/shared/engine_core.h and NO change to the generated code (re-verified MATCH
* after each step):
*
* 1. D_8011D030 (the reported one). DEFINE_func_801469C8() emits
* `extern s32 D_8011D030;` at FILE scope (engine_core.h:10811, above the
* `s32 func_801469C8(...) {` line), and this TU expands that macro at :564 —
extern s32 D_8011D030;
* i.e. before the splice point :570. The draft's `extern u16` therefore
* redeclared it incompatibly at :592. Conformed to the TU's `extern s32`.
* Codegen-neutral: the sole use is `(u8 *)&D_8011D030`, an address-of, so the
* declared object type never reaches a load/store width (cookbook §20).
*
* 2. func_80146AFC ITSELF (latent, would have surfaced next). DEFINE_func_8014C010()
* (:13510) and DEFINE_func_8014AD30() (:13524) each emit a file-scope
* `extern void func_80146AFC(void *a0);`, and this TU expands them at :1386 and
* :1541 — after the splice — so an `s32 func_80146AFC` definition collides on the
* RETURN axis. Fixed with the §37/§124 ASM-LABEL ALIAS: the C identifier is
* aF80146AFC, the emitted label is func_80146AFC, so the canonical void decl and
* this s32 definition never share a namespace. Callers discard the result, so the
* void-typed call sites stay codegen-identical.
*
* Both were reproduced and then cleared against the real cpp+cc1-2.7.2 pair using a
* synthetic copy of this TU's declaration environment (.run/uc2/_recon_probe_80146AFC.c):
* the pre-reconcile spelling emits exactly the gate's error pair; the spelling below
* compiles clean.
*
* ORACLE: tools/match_one.py func_80146AFC --c .run/uc2/func_80146AFC.c
* --asm-subdir asm/ov_SC01_077/nonmatchings/ov_SC01_077_after -> MATCH (40 ins)
*/
s32 aF80146AFC(void *arg0) __asm__("func_80146AFC");
s32 aF80146AFC(void *arg0)
{
register u8 *p __asm__("$6");
register u8 *q __asm__("$5");
u8 *end;
p = (u8 *)&D_8011D030;
end = p + 0xA50;
if ((u32)p < (u32)end) {
q = p + 0x30;
do {
if (*(u16 *)p == 0) {
*(s32 *)(q + 0x4) = *(s32 *)((u8 *)arg0 + 0x8);
*(s16 *)p = *(u16 *)((u8 *)arg0 + 0x0);
*(s16 *)(q - 0x2A) = *(u16 *)((u8 *)arg0 + 0x2);
*(s16 *)(q - 0x26) = *(u16 *)((u8 *)arg0 + 0x4);
*(s16 *)(q - 0x22) = *(u16 *)((u8 *)arg0 + 0x6);
*(s32 *)(q - 0x4) = *(s32 *)((u8 *)arg0 + 0xC);
*(s32 *)(q + 0x0) = *(s32 *)((u8 *)arg0 + 0x10);
return (s32)p;
}
p += 0x58;
q += 0x58;
} while ((u32)p < (u32)end);
}
return 0;
}
DEFINE_func_80146B9C() /* dedup: shared engine-core @0x80146B9C (src/shared) */
+49 -1
View File
@@ -327,7 +327,55 @@ DEFINE_func_8012B70C() /* dedup: shared engine-core @0x8012B70C (src/shared) */
DEFINE_func_8012B744() /* dedup: shared engine-core @0x8012B744 (src/shared) */
INCLUDE_ASM("asm/ov_SC01_084/nonmatchings/ov_SC01_084_jr_8012ACE0", func_8012B77C);
extern s32 ratan2(s32 a0, s32 a1);
extern s32 func_80047948(s32 a0); /* rsin-like: angle (0..0xFFF) -> 1.12 fixed */
extern s32 func_8004787C(s32 a0); /* rcos-like: angle (0..0xFFF) -> 1.12 fixed */
/* The 4-byte destination is a PACKED PAIR of angles held entirely in ONE saved register
* ($s4) across all three calls — that is what produces the target's
* andi $s4,$s4,0xFFFF (read of the still-uninitialized local, hoisted into the prologue)
* ... or $s4,$s4,ang<<16 -> t.hi = yaw
* ... and $s4,$s4,0xFFFF0000 / or $s4,$s4,ang&0xFFFF -> t.lo = pitch
* A `struct { s16 lo, hi; }` has align 2 -> BLKmode-ish handling: gcc spills it to the stack
* and stores it with lwl/lwr + swl/swr (54 ins, 53 mismatched). Two 16-bit BITFIELDS in a
* u32 container give the SImode, align-4 struct gcc keeps in a register. */
typedef struct {
u32 lo : 16;
u32 hi : 16;
} Ang2_8012B77C_8012B77C;
/* a0 = destination packed-angle word, a1 = "from" entity, a2 = "to" entity.
* Both entities carry 16.16 fixed-point x/y/z at +0/+4/+8; the s16 reads at +2/+6/+0xA are
* the integer halves. Returns the destination pointer — the return value is REAL: without it
* gcc stores with `sw $s4,0($s3)` (57 ins) instead of the target's
* addu $v0,$s3,$zero ; sw $s4,0($v0) (the return-value copy that the store's base coalesces onto).
* The flattened `dz` reuse at the end is also load-bearing: making the (dz*sin + dx*cos)>>12
* temp its OWN variable gives it $a1 for the whole chain; reusing `dz` extends that allocno so
* it lands in $s5 exactly as the target does (`sra $s5,$v0,12` / `negu $a1,$s5`), and it also
* demotes dz's priority so the saved-reg order comes out $s3=out, $s4=t, $s5=dz. */
s32 func_8012B77C(s32 out, s32 from, s32 to) {
Ang2_8012B77C_8012B77C t;
s32 dx, dy, dz;
s32 ang;
s32 r1, r2;
dz = *(s16 *)(to + 0xA) - *(s16 *)(from + 0xA);
dx = *(s16 *)(to + 0x2) - *(s16 *)(from + 0x2);
dy = *(s16 *)(to + 0x6) - *(s16 *)(from + 0x6);
ang = (ratan2(-dz, dx) - 0x400) & 0xFFF;
t.hi = ang;
r1 = func_80047948(ang);
r2 = func_8004787C(ang);
dz = (dz * r1 + dx * r2) >> 12;
t.lo = ratan2(dy, -dz);
*(Ang2_8012B77C_8012B77C *)out = t;
return out;
}
DEFINE_func_8012B864() /* dedup: shared engine-core @0x8012B864 (src/shared) */
+74 -1
View File
@@ -3173,7 +3173,80 @@ void func_80175DA8(param_1)
}
INCLUDE_ASM("asm/ov_SC01_084/nonmatchings/ov_SC01_084_jr_801734BC", func_80176144);
/* func_80176144 — RECONCILED variant of .run/uc/func_80176144.c
*
* GATE BLOCKER (whole-binary build, NOT match_one):
* src/ov_SC01_077/ov_SC01_077_jr_801734BC.c:3476: conflicting types for `D_800AF634'
* || previous declaration at :3296
*
* ROOT CAUSE — a HOISTED file-scope typedef, not a bad signature:
* That TU hoists, at FILE scope, for func_80175DA8:
* :3295 typedef struct { s32 g0; s32 pad[2]; } S_AF634_80176144;
* :3296 extern S_AF634_80176144 D_800AF634[];
* :3297 extern S_AF634_80176144 D_800AF638[];
* The stored draft re-declares the SAME struct shape as a BLOCK-scope typedef
* (rule D — it must travel to the 137 sibling overlays, which have no such
* preamble). A block-scope `typedef struct {...} S_AF634_80176144;` is a DISTINCT type
* from the file-scope one (C has no structural typing), so the block-scope
* `extern S_AF634_80176144 D_800AF634[];` re-declares the symbol incompatibly with the
* in-scope file-scope decl -> hard error.
* Note the earlier block-scope copies in the same TU (:3080 func_80175820,
* :3123 func_801759D8) do NOT error: they precede :3296, so no file-scope decl
* of D_800AF634 is in scope there. Anything AFTER :3296 collides. Our
* definition lands at :3476. That is why only this one fired.
*
* FIX — §37/§124 ASM-LABEL ALIAS applied to the DATA symbols (cookbook §2516:
* "asm-label alias for sibling-decl signedness/proto conflicts ... beats
* reconcile's *(u16*)&D_x cast whose address-of PERTURBS regalloc"):
* the two objects are reached through PRIVATE C identifiers aAF634 / aAF638
* carrying __asm__("D_800AF634") / __asm__("D_800AF638"). The emitted
* %hi/%lo relocations are against the same symbols, so codegen is unchanged,
* while the C names can never collide with ANY sibling TU's declaration —
* whether hoisted, block-scope, or absent. No header edit; no src/ edit.
* Strictly better than deleting the local decls (which would bind this
* exemplar to the one TU that happens to hoist them).
*
* The s32 parameter + explicit (s16) narrowing is retained from the stored draft
* (canonical decl in engine_core.h:18985/:4587 is `void func_80176144(s32)`;
* the K&R short param would itself be a conflicting-types error). The (s16)
* narrowing IS the entry `sll $s0,$a0,16 / sra $s0,$s0,16` pair.
*
* Verified: python3 tools/match_one.py func_80176144 --c .run/uc2/func_80176144.c
* --asm-subdir ov_SC01_077/nonmatchings/ov_SC01_077_jr_801734BC -> MATCH (53 ins)
*/
void func_80176144(s32 a0)
{
typedef struct { s32 g0; s32 pad[2]; } S_AF634_80176144; /* size 0x0C */
/* §37 asm-label alias: private C names, canonical relocations. */
extern S_AF634_80176144 aAF634[] __asm__("D_800AF634");
extern S_AF634_80176144 aAF638[] __asm__("D_800AF638");
extern u8 D_8011F7A8;
extern s16 D_8011F7BC;
extern s16 D_8011F7BE;
extern s32 func_80178004(s32 a0, s32 a1, s32 a2);
u32 *slot;
u32 *p;
s16 param_1 = (s16)a0;
p = (u32 *)(aAF638[param_1].g0 + aAF634[param_1].g0 * 4);
slot = (u32 *)(param_1 * 4 + (s32)&D_8011F7A8);
slot[14] = (u32)p;
/* §5a zero-byte sched fence: without it sched1 hoists the two %hi/lhu global
argument loads above the `sw` of slot[14] (16 mismatches, 0 length drift). */
__asm__("");
p = (u32 *)func_80178004((s32)p,
(s16)((*(u16 *)&D_8011F7BC) - 0x17),
(s16)((*(u16 *)&D_8011F7BE) + 0x65));
slot[16] = (u32)p - 0x14;
p += 5;
aAF634[param_1].g0 += ((s32)p - (s32)slot[14]) >> 2;
}
// @class: regalloc-order
+21 -1
View File
@@ -387,7 +387,27 @@ void func_80128AF4(void) {
DEFINE_func_80128C14() /* dedup: shared engine-core @0x80128C14 (src/shared) */
INCLUDE_ASM("asm/ov_SC02_000/nonmatchings/ov_SC02_000", func_80128C98);
typedef struct {
s32 word0;
s32 word4;
} CdFileLoc_80128C98;
extern CdFileLoc_80128C98 cdFileLocTable[];
extern void func_8001ABBC(s32 a0, s32 a1, void *a2, s32 a3, s32 a4);
s32 func_80128C98(s32 arg0) {
extern s16 D_8018AEAC[];
s16 idx = D_8018AEAC[arg0];
if (idx >= 0) {
func_8001ABBC(0, 0, (u8 *)&cdFileLocTable[idx], D_801E5794, 0);
} else {
return 1;
}
}
INCLUDE_ASM("asm/ov_SC02_000/nonmatchings/ov_SC02_000", func_80128CFC);
+78 -1
View File
@@ -481,7 +481,84 @@ INCLUDE_ASM("asm/ov_SC02_000/nonmatchings/ov_SC02_000_after", func_80146A6C);
DEFINE_func_80146AB4() /* dedup: shared engine-core @0x80146AB4 (src/shared) */
INCLUDE_ASM("asm/ov_SC02_000/nonmatchings/ov_SC02_000_after", func_80146AFC);
extern s32 func_80146B9C(void * arg0);
/* func_80146AFC — ASCENDING twin of the byte-proven DEFINE_func_80146B9C()
* in src/shared/engine_core.h (cookbook §71: find the already-matched sibling first).
* Same 0x58-stride slot table (base D_8011D030), same 7-store copy body in the same
* order, same $a2/$a1 giv pair. 80146B9C walks DOWN; this one walks UP, so the guard
* is `p < end`, end = p + 0xA50 (30 slots x 0x58).
*
* DECAY ROOT CAUSE (this redraft): the stored backlog draft had been rewritten to
* `void func_80146AFC(...)`, which drops BOTH `return 0` paths' `addu $v0,$zero,$zero`
* and the hit path's `j .L80146B94` => LENGTH-DRIFT -2 (38 vs 40) plus $v0/$v1 regalloc
* drift on the final lw/sw pair. Restoring the s32 return type (the fleet spelling the
* banked sibling func_80146B9C already uses) restores MATCH at 40/40.
*
* RECONCILE (2026-08-01) — the whole-binary gate failed with
* ov_SC01_077_after.c:592: conflicting types for `D_8011D030' (previous decl :564)
* TWO file-scope collisions were present; both are fixed HERE, with NO edit to
* src/shared/engine_core.h and NO change to the generated code (re-verified MATCH
* after each step):
*
* 1. D_8011D030 (the reported one). DEFINE_func_801469C8() emits
* `extern s32 D_8011D030;` at FILE scope (engine_core.h:10811, above the
* `s32 func_801469C8(...) {` line), and this TU expands that macro at :564 —
extern s32 D_8011D030;
* i.e. before the splice point :570. The draft's `extern u16` therefore
* redeclared it incompatibly at :592. Conformed to the TU's `extern s32`.
* Codegen-neutral: the sole use is `(u8 *)&D_8011D030`, an address-of, so the
* declared object type never reaches a load/store width (cookbook §20).
*
* 2. func_80146AFC ITSELF (latent, would have surfaced next). DEFINE_func_8014C010()
* (:13510) and DEFINE_func_8014AD30() (:13524) each emit a file-scope
* `extern void func_80146AFC(void *a0);`, and this TU expands them at :1386 and
* :1541 — after the splice — so an `s32 func_80146AFC` definition collides on the
* RETURN axis. Fixed with the §37/§124 ASM-LABEL ALIAS: the C identifier is
* aF80146AFC, the emitted label is func_80146AFC, so the canonical void decl and
* this s32 definition never share a namespace. Callers discard the result, so the
* void-typed call sites stay codegen-identical.
*
* Both were reproduced and then cleared against the real cpp+cc1-2.7.2 pair using a
* synthetic copy of this TU's declaration environment (.run/uc2/_recon_probe_80146AFC.c):
* the pre-reconcile spelling emits exactly the gate's error pair; the spelling below
* compiles clean.
*
* ORACLE: tools/match_one.py func_80146AFC --c .run/uc2/func_80146AFC.c
* --asm-subdir asm/ov_SC01_077/nonmatchings/ov_SC01_077_after -> MATCH (40 ins)
*/
s32 aF80146AFC(void *arg0) __asm__("func_80146AFC");
s32 aF80146AFC(void *arg0)
{
register u8 *p __asm__("$6");
register u8 *q __asm__("$5");
u8 *end;
p = (u8 *)&D_8011D030;
end = p + 0xA50;
if ((u32)p < (u32)end) {
q = p + 0x30;
do {
if (*(u16 *)p == 0) {
*(s32 *)(q + 0x4) = *(s32 *)((u8 *)arg0 + 0x8);
*(s16 *)p = *(u16 *)((u8 *)arg0 + 0x0);
*(s16 *)(q - 0x2A) = *(u16 *)((u8 *)arg0 + 0x2);
*(s16 *)(q - 0x26) = *(u16 *)((u8 *)arg0 + 0x4);
*(s16 *)(q - 0x22) = *(u16 *)((u8 *)arg0 + 0x6);
*(s32 *)(q - 0x4) = *(s32 *)((u8 *)arg0 + 0xC);
*(s32 *)(q + 0x0) = *(s32 *)((u8 *)arg0 + 0x10);
return (s32)p;
}
p += 0x58;
q += 0x58;
} while ((u32)p < (u32)end);
}
return 0;
}
DEFINE_func_80146B9C() /* dedup: shared engine-core @0x80146B9C (src/shared) */
+49 -1
View File
@@ -327,7 +327,55 @@ DEFINE_func_8012B70C() /* dedup: shared engine-core @0x8012B70C (src/shared) */
DEFINE_func_8012B744() /* dedup: shared engine-core @0x8012B744 (src/shared) */
INCLUDE_ASM("asm/ov_SC02_000/nonmatchings/ov_SC02_000_jr_8012ACE0", func_8012B77C);
extern s32 ratan2(s32 a0, s32 a1);
extern s32 func_80047948(s32 a0); /* rsin-like: angle (0..0xFFF) -> 1.12 fixed */
extern s32 func_8004787C(s32 a0); /* rcos-like: angle (0..0xFFF) -> 1.12 fixed */
/* The 4-byte destination is a PACKED PAIR of angles held entirely in ONE saved register
* ($s4) across all three calls — that is what produces the target's
* andi $s4,$s4,0xFFFF (read of the still-uninitialized local, hoisted into the prologue)
* ... or $s4,$s4,ang<<16 -> t.hi = yaw
* ... and $s4,$s4,0xFFFF0000 / or $s4,$s4,ang&0xFFFF -> t.lo = pitch
* A `struct { s16 lo, hi; }` has align 2 -> BLKmode-ish handling: gcc spills it to the stack
* and stores it with lwl/lwr + swl/swr (54 ins, 53 mismatched). Two 16-bit BITFIELDS in a
* u32 container give the SImode, align-4 struct gcc keeps in a register. */
typedef struct {
u32 lo : 16;
u32 hi : 16;
} Ang2_8012B77C_8012B77C;
/* a0 = destination packed-angle word, a1 = "from" entity, a2 = "to" entity.
* Both entities carry 16.16 fixed-point x/y/z at +0/+4/+8; the s16 reads at +2/+6/+0xA are
* the integer halves. Returns the destination pointer — the return value is REAL: without it
* gcc stores with `sw $s4,0($s3)` (57 ins) instead of the target's
* addu $v0,$s3,$zero ; sw $s4,0($v0) (the return-value copy that the store's base coalesces onto).
* The flattened `dz` reuse at the end is also load-bearing: making the (dz*sin + dx*cos)>>12
* temp its OWN variable gives it $a1 for the whole chain; reusing `dz` extends that allocno so
* it lands in $s5 exactly as the target does (`sra $s5,$v0,12` / `negu $a1,$s5`), and it also
* demotes dz's priority so the saved-reg order comes out $s3=out, $s4=t, $s5=dz. */
s32 func_8012B77C(s32 out, s32 from, s32 to) {
Ang2_8012B77C_8012B77C t;
s32 dx, dy, dz;
s32 ang;
s32 r1, r2;
dz = *(s16 *)(to + 0xA) - *(s16 *)(from + 0xA);
dx = *(s16 *)(to + 0x2) - *(s16 *)(from + 0x2);
dy = *(s16 *)(to + 0x6) - *(s16 *)(from + 0x6);
ang = (ratan2(-dz, dx) - 0x400) & 0xFFF;
t.hi = ang;
r1 = func_80047948(ang);
r2 = func_8004787C(ang);
dz = (dz * r1 + dx * r2) >> 12;
t.lo = ratan2(dy, -dz);
*(Ang2_8012B77C_8012B77C *)out = t;
return out;
}
DEFINE_func_8012B864() /* dedup: shared engine-core @0x8012B864 (src/shared) */
+74 -1
View File
@@ -3170,7 +3170,80 @@ void func_80175DA8(param_1)
}
INCLUDE_ASM("asm/ov_SC02_000/nonmatchings/ov_SC02_000_jr_801734BC", func_80176144);
/* func_80176144 — RECONCILED variant of .run/uc/func_80176144.c
*
* GATE BLOCKER (whole-binary build, NOT match_one):
* src/ov_SC01_077/ov_SC01_077_jr_801734BC.c:3476: conflicting types for `D_800AF634'
* || previous declaration at :3296
*
* ROOT CAUSE — a HOISTED file-scope typedef, not a bad signature:
* That TU hoists, at FILE scope, for func_80175DA8:
* :3295 typedef struct { s32 g0; s32 pad[2]; } S_AF634_80176144;
* :3296 extern S_AF634_80176144 D_800AF634[];
* :3297 extern S_AF634_80176144 D_800AF638[];
* The stored draft re-declares the SAME struct shape as a BLOCK-scope typedef
* (rule D — it must travel to the 137 sibling overlays, which have no such
* preamble). A block-scope `typedef struct {...} S_AF634_80176144;` is a DISTINCT type
* from the file-scope one (C has no structural typing), so the block-scope
* `extern S_AF634_80176144 D_800AF634[];` re-declares the symbol incompatibly with the
* in-scope file-scope decl -> hard error.
* Note the earlier block-scope copies in the same TU (:3080 func_80175820,
* :3123 func_801759D8) do NOT error: they precede :3296, so no file-scope decl
* of D_800AF634 is in scope there. Anything AFTER :3296 collides. Our
* definition lands at :3476. That is why only this one fired.
*
* FIX — §37/§124 ASM-LABEL ALIAS applied to the DATA symbols (cookbook §2516:
* "asm-label alias for sibling-decl signedness/proto conflicts ... beats
* reconcile's *(u16*)&D_x cast whose address-of PERTURBS regalloc"):
* the two objects are reached through PRIVATE C identifiers aAF634 / aAF638
* carrying __asm__("D_800AF634") / __asm__("D_800AF638"). The emitted
* %hi/%lo relocations are against the same symbols, so codegen is unchanged,
* while the C names can never collide with ANY sibling TU's declaration —
* whether hoisted, block-scope, or absent. No header edit; no src/ edit.
* Strictly better than deleting the local decls (which would bind this
* exemplar to the one TU that happens to hoist them).
*
* The s32 parameter + explicit (s16) narrowing is retained from the stored draft
* (canonical decl in engine_core.h:18985/:4587 is `void func_80176144(s32)`;
* the K&R short param would itself be a conflicting-types error). The (s16)
* narrowing IS the entry `sll $s0,$a0,16 / sra $s0,$s0,16` pair.
*
* Verified: python3 tools/match_one.py func_80176144 --c .run/uc2/func_80176144.c
* --asm-subdir ov_SC01_077/nonmatchings/ov_SC01_077_jr_801734BC -> MATCH (53 ins)
*/
void func_80176144(s32 a0)
{
typedef struct { s32 g0; s32 pad[2]; } S_AF634_80176144; /* size 0x0C */
/* §37 asm-label alias: private C names, canonical relocations. */
extern S_AF634_80176144 aAF634[] __asm__("D_800AF634");
extern S_AF634_80176144 aAF638[] __asm__("D_800AF638");
extern u8 D_8011F7A8;
extern s16 D_8011F7BC;
extern s16 D_8011F7BE;
extern s32 func_80178004(s32 a0, s32 a1, s32 a2);
u32 *slot;
u32 *p;
s16 param_1 = (s16)a0;
p = (u32 *)(aAF638[param_1].g0 + aAF634[param_1].g0 * 4);
slot = (u32 *)(param_1 * 4 + (s32)&D_8011F7A8);
slot[14] = (u32)p;
/* §5a zero-byte sched fence: without it sched1 hoists the two %hi/lhu global
argument loads above the `sw` of slot[14] (16 mismatches, 0 length drift). */
__asm__("");
p = (u32 *)func_80178004((s32)p,
(s16)((*(u16 *)&D_8011F7BC) - 0x17),
(s16)((*(u16 *)&D_8011F7BE) + 0x65));
slot[16] = (u32)p - 0x14;
p += 5;
aAF634[param_1].g0 += ((s32)p - (s32)slot[14]) >> 2;
}
// @class: regalloc-order
+107 -2
View File
@@ -3355,7 +3355,47 @@ void func_8017BF84(int param_1)
}
INCLUDE_ASM("asm/ov_SC02_000/nonmatchings/ov_SC02_000_jr_8017AE2C", func_8017BFE0);
/* Entity record touched by func_8017BFE0 (offsets read straight off the asm):
* 0x02 u16 frame/state counter (lhu / sh)
* 0x1C s32 tick counter (lw / sw), signed compare against 0x20
* 0x2A u16 y-ish delta, decremented by 0x10 (lhu / sh)
* 0x2C u16 sound id passed to func_80147324 (lhu)
* 0x30 s32 suppress flag
*/
typedef struct Ent_8017BFE0_8017BFE0 {
u8 pad00[2]; /* 0x00 */
u16 f02; /* 0x02 */
u8 pad04[0x18];/* 0x04 */
s32 f1c; /* 0x1C */
u8 pad20[0xA]; /* 0x20 */
u16 f2a; /* 0x2A */
u16 f2c; /* 0x2C */
u8 pad2e[2]; /* 0x2E */
s32 f30; /* 0x30 */
} Ent_8017BFE0_8017BFE0;
extern void func_80147324(s32 arg0);
extern void func_8017C218(int);
void func_8017BFE0(Ent_8017BFE0_8017BFE0 *param_1)
{
s32 t;
t = param_1->f1c;
param_1->f1c = t + 1;
if (t < 0x20) {
param_1->f2a = param_1->f2a - 0x10;
} else {
if (param_1->f30 == 0) {
func_80147324(param_1->f2c);
}
param_1->f1c = 0;
param_1->f02 = param_1->f02 + 1;
}
((void (*)(Ent_8017BFE0_8017BFE0 *))func_8017C218)(param_1);
}
INCLUDE_ASM("asm/ov_SC02_000/nonmatchings/ov_SC02_000_jr_8017AE2C", func_8017C064);
@@ -3483,7 +3523,72 @@ void func_8017C7C4(void *a0) {
}
INCLUDE_ASM("asm/ov_SC02_000/nonmatchings/ov_SC02_000_jr_8017AE2C", func_8017C800);
/* func_8017C800 — spawn/scatter tick for the +0x34 sub-object (state word @0x2).
* MATCH (45 ins), match_one + rtu_match. Four levers, in the order they were found:
*
* 1. §71 sibling-first — same entity shape as func_8017C610 / func_8017C69C in this
* TU: sub-object pointer @0x34 read BEFORE the call (it lives in $s1 across the
* jal), state word @0x2 bumped last. §3-T4: `beqz $v1,else` => `if (p->f2C) {..}`.
* ONE rand() feeds three fields; the raw low 6 bits use a bare `andi` (no extend)
* while the >>12 / >>6 uses share one `sll $x,16` — that shared sign-extend is
* what forces `r` to be a `short` local rather than an int.
*
* 2. §5a CROSS-JUMP — both arms end in `sh ?,0xA($s0)`; gcc tail-merged them (23 off).
* They only stay separate because the loaded halfword lands in a DIFFERENT hard
* reg per arm, which needs (a) the load to be its own statement at the TOP of each
* arm and (b) a SEPARATE temp per arm (t / t2) — one shared temp is one pseudo,
* gets one register in both arms, and re-merges. 23 -> 10 -> 6.
*
* 3. +0x16 is SIGNED: the target materialises -0x20 as `addiu $v0,$zero,-0x20`, not
* `ori 0xffe0`, so that store must go through an s16.
*
* 4. §49 BIRTHING BOOST (the last 6 -> 2 -> 0). Residual was two ALU insns swapped
* with identical registers; source statement order does NOT flip it, because
* sched1's `adjust_priority`/`birthing_insn_p` hands every SET(REG,..) whose dest
* has REG_N_SETS==1 a 0x7f000001 priority, so it sinks to just before its consumer
* and fixes the .greg LUID order that sched2's tie-break then reads.
* THE DIAL: give the offending insn's dest a SECOND set so it loses the boost —
* here one `u16 d` reused by both tail statements. It must be a THIRD temp, not
* `c` itself: writing `c = c + 1;` also un-boosts c's LOAD, which then starves to
* the front of the block and swaps the two `lhu`s instead. Boost the loads, starve
* the arithmetic. */
extern int rand(void);
void func_8017C800(void *a0)
{
s32 p;
s32 obj;
short r;
u16 t;
u16 t2;
u16 e;
u16 c;
u16 d;
p = (s32)a0;
obj = *(s32 *)(p + 0x34);
r = rand();
*(u16 *)(p + 0x06) = *(u16 *)(obj + 0x06) + ((r & 0x3F) - 0x20);
if (*(s32 *)(p + 0x2C) != 0) {
t = *(u16 *)(obj + 0x0A);
*(s16 *)(p + 0x16) = 0x20;
*(u16 *)(p + 0x0A) = t - 0x140;
} else {
t2 = *(u16 *)(obj + 0x0A);
*(s16 *)(p + 0x16) = -0x20;
*(u16 *)(p + 0x0A) = t2;
}
e = *(u16 *)(obj + 0x0E);
c = *(u16 *)(p + 0x02);
*(s32 *)(p + 0x30) = (r >> 12) & 3;
d = ((r >> 6) & 0x3F) - 0x20;
*(u16 *)(p + 0x0E) = e + d;
d = c + 1;
*(u16 *)(p + 0x02) = d;
}
DEFINE_func_8017C8B4() /* dedup: shared engine-core @0x8017C8B4 (src/shared) */
+21 -1
View File
@@ -387,7 +387,27 @@ void func_80128AF4(void) {
DEFINE_func_80128C14() /* dedup: shared engine-core @0x80128C14 (src/shared) */
INCLUDE_ASM("asm/ov_SC02_003/nonmatchings/ov_SC02_003", func_80128C98);
typedef struct {
s32 word0;
s32 word4;
} CdFileLoc_80128C98;
extern CdFileLoc_80128C98 cdFileLocTable[];
extern void func_8001ABBC(s32 a0, s32 a1, void *a2, s32 a3, s32 a4);
s32 func_80128C98(s32 arg0) {
extern s16 D_8018AEAC[];
s16 idx = D_8018AEAC[arg0];
if (idx >= 0) {
func_8001ABBC(0, 0, (u8 *)&cdFileLocTable[idx], D_801E5794, 0);
} else {
return 1;
}
}
INCLUDE_ASM("asm/ov_SC02_003/nonmatchings/ov_SC02_003", func_80128CFC);
+78 -1
View File
@@ -481,7 +481,84 @@ INCLUDE_ASM("asm/ov_SC02_003/nonmatchings/ov_SC02_003_after", func_80146A6C);
DEFINE_func_80146AB4() /* dedup: shared engine-core @0x80146AB4 (src/shared) */
INCLUDE_ASM("asm/ov_SC02_003/nonmatchings/ov_SC02_003_after", func_80146AFC);
extern s32 func_80146B9C(void * arg0);
/* func_80146AFC — ASCENDING twin of the byte-proven DEFINE_func_80146B9C()
* in src/shared/engine_core.h (cookbook §71: find the already-matched sibling first).
* Same 0x58-stride slot table (base D_8011D030), same 7-store copy body in the same
* order, same $a2/$a1 giv pair. 80146B9C walks DOWN; this one walks UP, so the guard
* is `p < end`, end = p + 0xA50 (30 slots x 0x58).
*
* DECAY ROOT CAUSE (this redraft): the stored backlog draft had been rewritten to
* `void func_80146AFC(...)`, which drops BOTH `return 0` paths' `addu $v0,$zero,$zero`
* and the hit path's `j .L80146B94` => LENGTH-DRIFT -2 (38 vs 40) plus $v0/$v1 regalloc
* drift on the final lw/sw pair. Restoring the s32 return type (the fleet spelling the
* banked sibling func_80146B9C already uses) restores MATCH at 40/40.
*
* RECONCILE (2026-08-01) — the whole-binary gate failed with
* ov_SC01_077_after.c:592: conflicting types for `D_8011D030' (previous decl :564)
* TWO file-scope collisions were present; both are fixed HERE, with NO edit to
* src/shared/engine_core.h and NO change to the generated code (re-verified MATCH
* after each step):
*
* 1. D_8011D030 (the reported one). DEFINE_func_801469C8() emits
* `extern s32 D_8011D030;` at FILE scope (engine_core.h:10811, above the
* `s32 func_801469C8(...) {` line), and this TU expands that macro at :564 —
extern s32 D_8011D030;
* i.e. before the splice point :570. The draft's `extern u16` therefore
* redeclared it incompatibly at :592. Conformed to the TU's `extern s32`.
* Codegen-neutral: the sole use is `(u8 *)&D_8011D030`, an address-of, so the
* declared object type never reaches a load/store width (cookbook §20).
*
* 2. func_80146AFC ITSELF (latent, would have surfaced next). DEFINE_func_8014C010()
* (:13510) and DEFINE_func_8014AD30() (:13524) each emit a file-scope
* `extern void func_80146AFC(void *a0);`, and this TU expands them at :1386 and
* :1541 — after the splice — so an `s32 func_80146AFC` definition collides on the
* RETURN axis. Fixed with the §37/§124 ASM-LABEL ALIAS: the C identifier is
* aF80146AFC, the emitted label is func_80146AFC, so the canonical void decl and
* this s32 definition never share a namespace. Callers discard the result, so the
* void-typed call sites stay codegen-identical.
*
* Both were reproduced and then cleared against the real cpp+cc1-2.7.2 pair using a
* synthetic copy of this TU's declaration environment (.run/uc2/_recon_probe_80146AFC.c):
* the pre-reconcile spelling emits exactly the gate's error pair; the spelling below
* compiles clean.
*
* ORACLE: tools/match_one.py func_80146AFC --c .run/uc2/func_80146AFC.c
* --asm-subdir asm/ov_SC01_077/nonmatchings/ov_SC01_077_after -> MATCH (40 ins)
*/
s32 aF80146AFC(void *arg0) __asm__("func_80146AFC");
s32 aF80146AFC(void *arg0)
{
register u8 *p __asm__("$6");
register u8 *q __asm__("$5");
u8 *end;
p = (u8 *)&D_8011D030;
end = p + 0xA50;
if ((u32)p < (u32)end) {
q = p + 0x30;
do {
if (*(u16 *)p == 0) {
*(s32 *)(q + 0x4) = *(s32 *)((u8 *)arg0 + 0x8);
*(s16 *)p = *(u16 *)((u8 *)arg0 + 0x0);
*(s16 *)(q - 0x2A) = *(u16 *)((u8 *)arg0 + 0x2);
*(s16 *)(q - 0x26) = *(u16 *)((u8 *)arg0 + 0x4);
*(s16 *)(q - 0x22) = *(u16 *)((u8 *)arg0 + 0x6);
*(s32 *)(q - 0x4) = *(s32 *)((u8 *)arg0 + 0xC);
*(s32 *)(q + 0x0) = *(s32 *)((u8 *)arg0 + 0x10);
return (s32)p;
}
p += 0x58;
q += 0x58;
} while ((u32)p < (u32)end);
}
return 0;
}
DEFINE_func_80146B9C() /* dedup: shared engine-core @0x80146B9C (src/shared) */
+49 -1
View File
@@ -327,7 +327,55 @@ DEFINE_func_8012B70C() /* dedup: shared engine-core @0x8012B70C (src/shared) */
DEFINE_func_8012B744() /* dedup: shared engine-core @0x8012B744 (src/shared) */
INCLUDE_ASM("asm/ov_SC02_003/nonmatchings/ov_SC02_003_jr_8012ACE0", func_8012B77C);
extern s32 ratan2(s32 a0, s32 a1);
extern s32 func_80047948(s32 a0); /* rsin-like: angle (0..0xFFF) -> 1.12 fixed */
extern s32 func_8004787C(s32 a0); /* rcos-like: angle (0..0xFFF) -> 1.12 fixed */
/* The 4-byte destination is a PACKED PAIR of angles held entirely in ONE saved register
* ($s4) across all three calls — that is what produces the target's
* andi $s4,$s4,0xFFFF (read of the still-uninitialized local, hoisted into the prologue)
* ... or $s4,$s4,ang<<16 -> t.hi = yaw
* ... and $s4,$s4,0xFFFF0000 / or $s4,$s4,ang&0xFFFF -> t.lo = pitch
* A `struct { s16 lo, hi; }` has align 2 -> BLKmode-ish handling: gcc spills it to the stack
* and stores it with lwl/lwr + swl/swr (54 ins, 53 mismatched). Two 16-bit BITFIELDS in a
* u32 container give the SImode, align-4 struct gcc keeps in a register. */
typedef struct {
u32 lo : 16;
u32 hi : 16;
} Ang2_8012B77C_8012B77C;
/* a0 = destination packed-angle word, a1 = "from" entity, a2 = "to" entity.
* Both entities carry 16.16 fixed-point x/y/z at +0/+4/+8; the s16 reads at +2/+6/+0xA are
* the integer halves. Returns the destination pointer — the return value is REAL: without it
* gcc stores with `sw $s4,0($s3)` (57 ins) instead of the target's
* addu $v0,$s3,$zero ; sw $s4,0($v0) (the return-value copy that the store's base coalesces onto).
* The flattened `dz` reuse at the end is also load-bearing: making the (dz*sin + dx*cos)>>12
* temp its OWN variable gives it $a1 for the whole chain; reusing `dz` extends that allocno so
* it lands in $s5 exactly as the target does (`sra $s5,$v0,12` / `negu $a1,$s5`), and it also
* demotes dz's priority so the saved-reg order comes out $s3=out, $s4=t, $s5=dz. */
s32 func_8012B77C(s32 out, s32 from, s32 to) {
Ang2_8012B77C_8012B77C t;
s32 dx, dy, dz;
s32 ang;
s32 r1, r2;
dz = *(s16 *)(to + 0xA) - *(s16 *)(from + 0xA);
dx = *(s16 *)(to + 0x2) - *(s16 *)(from + 0x2);
dy = *(s16 *)(to + 0x6) - *(s16 *)(from + 0x6);
ang = (ratan2(-dz, dx) - 0x400) & 0xFFF;
t.hi = ang;
r1 = func_80047948(ang);
r2 = func_8004787C(ang);
dz = (dz * r1 + dx * r2) >> 12;
t.lo = ratan2(dy, -dz);
*(Ang2_8012B77C_8012B77C *)out = t;
return out;
}
DEFINE_func_8012B864() /* dedup: shared engine-core @0x8012B864 (src/shared) */
+74 -1
View File
@@ -3170,7 +3170,80 @@ void func_80175DA8(param_1)
}
INCLUDE_ASM("asm/ov_SC02_003/nonmatchings/ov_SC02_003_jr_801734BC", func_80176144);
/* func_80176144 — RECONCILED variant of .run/uc/func_80176144.c
*
* GATE BLOCKER (whole-binary build, NOT match_one):
* src/ov_SC01_077/ov_SC01_077_jr_801734BC.c:3476: conflicting types for `D_800AF634'
* || previous declaration at :3296
*
* ROOT CAUSE — a HOISTED file-scope typedef, not a bad signature:
* That TU hoists, at FILE scope, for func_80175DA8:
* :3295 typedef struct { s32 g0; s32 pad[2]; } S_AF634_80176144;
* :3296 extern S_AF634_80176144 D_800AF634[];
* :3297 extern S_AF634_80176144 D_800AF638[];
* The stored draft re-declares the SAME struct shape as a BLOCK-scope typedef
* (rule D — it must travel to the 137 sibling overlays, which have no such
* preamble). A block-scope `typedef struct {...} S_AF634_80176144;` is a DISTINCT type
* from the file-scope one (C has no structural typing), so the block-scope
* `extern S_AF634_80176144 D_800AF634[];` re-declares the symbol incompatibly with the
* in-scope file-scope decl -> hard error.
* Note the earlier block-scope copies in the same TU (:3080 func_80175820,
* :3123 func_801759D8) do NOT error: they precede :3296, so no file-scope decl
* of D_800AF634 is in scope there. Anything AFTER :3296 collides. Our
* definition lands at :3476. That is why only this one fired.
*
* FIX — §37/§124 ASM-LABEL ALIAS applied to the DATA symbols (cookbook §2516:
* "asm-label alias for sibling-decl signedness/proto conflicts ... beats
* reconcile's *(u16*)&D_x cast whose address-of PERTURBS regalloc"):
* the two objects are reached through PRIVATE C identifiers aAF634 / aAF638
* carrying __asm__("D_800AF634") / __asm__("D_800AF638"). The emitted
* %hi/%lo relocations are against the same symbols, so codegen is unchanged,
* while the C names can never collide with ANY sibling TU's declaration —
* whether hoisted, block-scope, or absent. No header edit; no src/ edit.
* Strictly better than deleting the local decls (which would bind this
* exemplar to the one TU that happens to hoist them).
*
* The s32 parameter + explicit (s16) narrowing is retained from the stored draft
* (canonical decl in engine_core.h:18985/:4587 is `void func_80176144(s32)`;
* the K&R short param would itself be a conflicting-types error). The (s16)
* narrowing IS the entry `sll $s0,$a0,16 / sra $s0,$s0,16` pair.
*
* Verified: python3 tools/match_one.py func_80176144 --c .run/uc2/func_80176144.c
* --asm-subdir ov_SC01_077/nonmatchings/ov_SC01_077_jr_801734BC -> MATCH (53 ins)
*/
void func_80176144(s32 a0)
{
typedef struct { s32 g0; s32 pad[2]; } S_AF634_80176144; /* size 0x0C */
/* §37 asm-label alias: private C names, canonical relocations. */
extern S_AF634_80176144 aAF634[] __asm__("D_800AF634");
extern S_AF634_80176144 aAF638[] __asm__("D_800AF638");
extern u8 D_8011F7A8;
extern s16 D_8011F7BC;
extern s16 D_8011F7BE;
extern s32 func_80178004(s32 a0, s32 a1, s32 a2);
u32 *slot;
u32 *p;
s16 param_1 = (s16)a0;
p = (u32 *)(aAF638[param_1].g0 + aAF634[param_1].g0 * 4);
slot = (u32 *)(param_1 * 4 + (s32)&D_8011F7A8);
slot[14] = (u32)p;
/* §5a zero-byte sched fence: without it sched1 hoists the two %hi/lhu global
argument loads above the `sw` of slot[14] (16 mismatches, 0 length drift). */
__asm__("");
p = (u32 *)func_80178004((s32)p,
(s16)((*(u16 *)&D_8011F7BC) - 0x17),
(s16)((*(u16 *)&D_8011F7BE) + 0x65));
slot[16] = (u32)p - 0x14;
p += 5;
aAF634[param_1].g0 += ((s32)p - (s32)slot[14]) >> 2;
}
// @class: regalloc-order
+107 -2
View File
@@ -3355,7 +3355,47 @@ void func_8017BF84(int param_1)
}
INCLUDE_ASM("asm/ov_SC02_003/nonmatchings/ov_SC02_003_jr_8017AE2C", func_8017BFE0);
/* Entity record touched by func_8017BFE0 (offsets read straight off the asm):
* 0x02 u16 frame/state counter (lhu / sh)
* 0x1C s32 tick counter (lw / sw), signed compare against 0x20
* 0x2A u16 y-ish delta, decremented by 0x10 (lhu / sh)
* 0x2C u16 sound id passed to func_80147324 (lhu)
* 0x30 s32 suppress flag
*/
typedef struct Ent_8017BFE0_8017BFE0 {
u8 pad00[2]; /* 0x00 */
u16 f02; /* 0x02 */
u8 pad04[0x18];/* 0x04 */
s32 f1c; /* 0x1C */
u8 pad20[0xA]; /* 0x20 */
u16 f2a; /* 0x2A */
u16 f2c; /* 0x2C */
u8 pad2e[2]; /* 0x2E */
s32 f30; /* 0x30 */
} Ent_8017BFE0_8017BFE0;
extern void func_80147324(s32 arg0);
extern void func_8017C218(int);
void func_8017BFE0(Ent_8017BFE0_8017BFE0 *param_1)
{
s32 t;
t = param_1->f1c;
param_1->f1c = t + 1;
if (t < 0x20) {
param_1->f2a = param_1->f2a - 0x10;
} else {
if (param_1->f30 == 0) {
func_80147324(param_1->f2c);
}
param_1->f1c = 0;
param_1->f02 = param_1->f02 + 1;
}
((void (*)(Ent_8017BFE0_8017BFE0 *))func_8017C218)(param_1);
}
INCLUDE_ASM("asm/ov_SC02_003/nonmatchings/ov_SC02_003_jr_8017AE2C", func_8017C064);
@@ -3483,7 +3523,72 @@ void func_8017C7C4(void *a0) {
}
INCLUDE_ASM("asm/ov_SC02_003/nonmatchings/ov_SC02_003_jr_8017AE2C", func_8017C800);
/* func_8017C800 — spawn/scatter tick for the +0x34 sub-object (state word @0x2).
* MATCH (45 ins), match_one + rtu_match. Four levers, in the order they were found:
*
* 1. §71 sibling-first — same entity shape as func_8017C610 / func_8017C69C in this
* TU: sub-object pointer @0x34 read BEFORE the call (it lives in $s1 across the
* jal), state word @0x2 bumped last. §3-T4: `beqz $v1,else` => `if (p->f2C) {..}`.
* ONE rand() feeds three fields; the raw low 6 bits use a bare `andi` (no extend)
* while the >>12 / >>6 uses share one `sll $x,16` — that shared sign-extend is
* what forces `r` to be a `short` local rather than an int.
*
* 2. §5a CROSS-JUMP — both arms end in `sh ?,0xA($s0)`; gcc tail-merged them (23 off).
* They only stay separate because the loaded halfword lands in a DIFFERENT hard
* reg per arm, which needs (a) the load to be its own statement at the TOP of each
* arm and (b) a SEPARATE temp per arm (t / t2) — one shared temp is one pseudo,
* gets one register in both arms, and re-merges. 23 -> 10 -> 6.
*
* 3. +0x16 is SIGNED: the target materialises -0x20 as `addiu $v0,$zero,-0x20`, not
* `ori 0xffe0`, so that store must go through an s16.
*
* 4. §49 BIRTHING BOOST (the last 6 -> 2 -> 0). Residual was two ALU insns swapped
* with identical registers; source statement order does NOT flip it, because
* sched1's `adjust_priority`/`birthing_insn_p` hands every SET(REG,..) whose dest
* has REG_N_SETS==1 a 0x7f000001 priority, so it sinks to just before its consumer
* and fixes the .greg LUID order that sched2's tie-break then reads.
* THE DIAL: give the offending insn's dest a SECOND set so it loses the boost —
* here one `u16 d` reused by both tail statements. It must be a THIRD temp, not
* `c` itself: writing `c = c + 1;` also un-boosts c's LOAD, which then starves to
* the front of the block and swaps the two `lhu`s instead. Boost the loads, starve
* the arithmetic. */
extern int rand(void);
void func_8017C800(void *a0)
{
s32 p;
s32 obj;
short r;
u16 t;
u16 t2;
u16 e;
u16 c;
u16 d;
p = (s32)a0;
obj = *(s32 *)(p + 0x34);
r = rand();
*(u16 *)(p + 0x06) = *(u16 *)(obj + 0x06) + ((r & 0x3F) - 0x20);
if (*(s32 *)(p + 0x2C) != 0) {
t = *(u16 *)(obj + 0x0A);
*(s16 *)(p + 0x16) = 0x20;
*(u16 *)(p + 0x0A) = t - 0x140;
} else {
t2 = *(u16 *)(obj + 0x0A);
*(s16 *)(p + 0x16) = -0x20;
*(u16 *)(p + 0x0A) = t2;
}
e = *(u16 *)(obj + 0x0E);
c = *(u16 *)(p + 0x02);
*(s32 *)(p + 0x30) = (r >> 12) & 3;
d = ((r >> 6) & 0x3F) - 0x20;
*(u16 *)(p + 0x0E) = e + d;
d = c + 1;
*(u16 *)(p + 0x02) = d;
}
DEFINE_func_8017C8B4() /* dedup: shared engine-core @0x8017C8B4 (src/shared) */
+61 -1
View File
@@ -4164,7 +4164,67 @@ INCLUDE_ASM("asm/ov_SC02_003/nonmatchings/ov_SC02_003_jr_8017FCB0", func_8018A3F
INCLUDE_ASM("asm/ov_SC02_003/nonmatchings/ov_SC02_003_jr_8017FCB0", func_8018A440);
INCLUDE_ASM("asm/ov_SC02_003/nonmatchings/ov_SC02_003_jr_8017FCB0", func_8018A550);
extern void func_8001D074(s32 a0, s32 a1);
extern void func_8001CD04(s32 a0, s32 a1);
typedef struct Obj_8018A550_8018A550 {
s32 f0; /* 0x00 */
u32 f4; /* 0x04 */
s32 f8; /* 0x08 */
s32 fC; /* 0x0C */
s32 f10; /* 0x10 */
s32 f14; /* 0x14 */
s16 f18; /* 0x18 */
s16 f1A; /* 0x1A */
s16 f1C; /* 0x1C */
s16 f1E; /* 0x1E */
} Obj_8018A550_8018A550;
typedef struct Rec_8018A550_8018A550 {
u16 f0; /* 0x00 */
u16 f2; /* 0x02 */
s16 f4; /* 0x04 */
s16 f6; /* 0x06 */
s32 f8; /* 0x08 */
s32 fC; /* 0x0C */
} Rec_8018A550_8018A550;
typedef struct Ctl_8018A550_8018A550 {
s32 f0; /* 0x00 */
s16 ids[8]; /* 0x04 */
Obj_8018A550_8018A550 *slots[8]; /* 0x14 */
} Ctl_8018A550_8018A550;
void func_8018A550(Ctl_8018A550_8018A550 *ctl, Rec_8018A550_8018A550 *rec)
{
s32 i;
Obj_8018A550_8018A550 *m;
s16 v;
u16 t;
do {
for (i = 0; i < 8; i++) {
if (ctl->slots[i] == 0) {
break;
}
}
m = (Obj_8018A550_8018A550 *)((s32 (*)(s32, s32))func_8001D074)(0x7E, 0x100);
if (m != 0) {
((void (*)(Obj_8018A550_8018A550 *, s32))func_8001CD04)(m, rec->fC);
m->f4 |= 0xF0000000;
v = rec->f6;
m->f1C = v;
m->f1A = v;
m->f18 = v;
ctl->slots[i] = m;
ctl->ids[i] = rec->f4;
}
t = rec->f0;
rec++;
} while (t != 0xFF);
}
+21 -1
View File
@@ -387,7 +387,27 @@ void func_80128AF4(void) {
DEFINE_func_80128C14() /* dedup: shared engine-core @0x80128C14 (src/shared) */
INCLUDE_ASM("asm/ov_SC02_004/nonmatchings/ov_SC02_004", func_80128C98);
typedef struct {
s32 word0;
s32 word4;
} CdFileLoc_80128C98;
extern CdFileLoc_80128C98 cdFileLocTable[];
extern void func_8001ABBC(s32 a0, s32 a1, void *a2, s32 a3, s32 a4);
s32 func_80128C98(s32 arg0) {
extern s16 D_8017DF8C[];
s16 idx = D_8017DF8C[arg0];
if (idx >= 0) {
func_8001ABBC(0, 0, (u8 *)&cdFileLocTable[idx], D_80193DA4, 0);
} else {
return 1;
}
}
INCLUDE_ASM("asm/ov_SC02_004/nonmatchings/ov_SC02_004", func_80128CFC);
+78 -1
View File
@@ -481,7 +481,84 @@ INCLUDE_ASM("asm/ov_SC02_004/nonmatchings/ov_SC02_004_after", func_80146A6C);
DEFINE_func_80146AB4() /* dedup: shared engine-core @0x80146AB4 (src/shared) */
INCLUDE_ASM("asm/ov_SC02_004/nonmatchings/ov_SC02_004_after", func_80146AFC);
extern s32 func_80146B9C(void * arg0);
/* func_80146AFC — ASCENDING twin of the byte-proven DEFINE_func_80146B9C()
* in src/shared/engine_core.h (cookbook §71: find the already-matched sibling first).
* Same 0x58-stride slot table (base D_8011D030), same 7-store copy body in the same
* order, same $a2/$a1 giv pair. 80146B9C walks DOWN; this one walks UP, so the guard
* is `p < end`, end = p + 0xA50 (30 slots x 0x58).
*
* DECAY ROOT CAUSE (this redraft): the stored backlog draft had been rewritten to
* `void func_80146AFC(...)`, which drops BOTH `return 0` paths' `addu $v0,$zero,$zero`
* and the hit path's `j .L80146B94` => LENGTH-DRIFT -2 (38 vs 40) plus $v0/$v1 regalloc
* drift on the final lw/sw pair. Restoring the s32 return type (the fleet spelling the
* banked sibling func_80146B9C already uses) restores MATCH at 40/40.
*
* RECONCILE (2026-08-01) — the whole-binary gate failed with
* ov_SC01_077_after.c:592: conflicting types for `D_8011D030' (previous decl :564)
* TWO file-scope collisions were present; both are fixed HERE, with NO edit to
* src/shared/engine_core.h and NO change to the generated code (re-verified MATCH
* after each step):
*
* 1. D_8011D030 (the reported one). DEFINE_func_801469C8() emits
* `extern s32 D_8011D030;` at FILE scope (engine_core.h:10811, above the
* `s32 func_801469C8(...) {` line), and this TU expands that macro at :564 —
extern s32 D_8011D030;
* i.e. before the splice point :570. The draft's `extern u16` therefore
* redeclared it incompatibly at :592. Conformed to the TU's `extern s32`.
* Codegen-neutral: the sole use is `(u8 *)&D_8011D030`, an address-of, so the
* declared object type never reaches a load/store width (cookbook §20).
*
* 2. func_80146AFC ITSELF (latent, would have surfaced next). DEFINE_func_8014C010()
* (:13510) and DEFINE_func_8014AD30() (:13524) each emit a file-scope
* `extern void func_80146AFC(void *a0);`, and this TU expands them at :1386 and
* :1541 — after the splice — so an `s32 func_80146AFC` definition collides on the
* RETURN axis. Fixed with the §37/§124 ASM-LABEL ALIAS: the C identifier is
* aF80146AFC, the emitted label is func_80146AFC, so the canonical void decl and
* this s32 definition never share a namespace. Callers discard the result, so the
* void-typed call sites stay codegen-identical.
*
* Both were reproduced and then cleared against the real cpp+cc1-2.7.2 pair using a
* synthetic copy of this TU's declaration environment (.run/uc2/_recon_probe_80146AFC.c):
* the pre-reconcile spelling emits exactly the gate's error pair; the spelling below
* compiles clean.
*
* ORACLE: tools/match_one.py func_80146AFC --c .run/uc2/func_80146AFC.c
* --asm-subdir asm/ov_SC01_077/nonmatchings/ov_SC01_077_after -> MATCH (40 ins)
*/
s32 aF80146AFC(void *arg0) __asm__("func_80146AFC");
s32 aF80146AFC(void *arg0)
{
register u8 *p __asm__("$6");
register u8 *q __asm__("$5");
u8 *end;
p = (u8 *)&D_8011D030;
end = p + 0xA50;
if ((u32)p < (u32)end) {
q = p + 0x30;
do {
if (*(u16 *)p == 0) {
*(s32 *)(q + 0x4) = *(s32 *)((u8 *)arg0 + 0x8);
*(s16 *)p = *(u16 *)((u8 *)arg0 + 0x0);
*(s16 *)(q - 0x2A) = *(u16 *)((u8 *)arg0 + 0x2);
*(s16 *)(q - 0x26) = *(u16 *)((u8 *)arg0 + 0x4);
*(s16 *)(q - 0x22) = *(u16 *)((u8 *)arg0 + 0x6);
*(s32 *)(q - 0x4) = *(s32 *)((u8 *)arg0 + 0xC);
*(s32 *)(q + 0x0) = *(s32 *)((u8 *)arg0 + 0x10);
return (s32)p;
}
p += 0x58;
q += 0x58;
} while ((u32)p < (u32)end);
}
return 0;
}
DEFINE_func_80146B9C() /* dedup: shared engine-core @0x80146B9C (src/shared) */
+49 -1
View File
@@ -327,7 +327,55 @@ DEFINE_func_8012B70C() /* dedup: shared engine-core @0x8012B70C (src/shared) */
DEFINE_func_8012B744() /* dedup: shared engine-core @0x8012B744 (src/shared) */
INCLUDE_ASM("asm/ov_SC02_004/nonmatchings/ov_SC02_004_jr_8012ACE0", func_8012B77C);
extern s32 ratan2(s32 a0, s32 a1);
extern s32 func_80047948(s32 a0); /* rsin-like: angle (0..0xFFF) -> 1.12 fixed */
extern s32 func_8004787C(s32 a0); /* rcos-like: angle (0..0xFFF) -> 1.12 fixed */
/* The 4-byte destination is a PACKED PAIR of angles held entirely in ONE saved register
* ($s4) across all three calls — that is what produces the target's
* andi $s4,$s4,0xFFFF (read of the still-uninitialized local, hoisted into the prologue)
* ... or $s4,$s4,ang<<16 -> t.hi = yaw
* ... and $s4,$s4,0xFFFF0000 / or $s4,$s4,ang&0xFFFF -> t.lo = pitch
* A `struct { s16 lo, hi; }` has align 2 -> BLKmode-ish handling: gcc spills it to the stack
* and stores it with lwl/lwr + swl/swr (54 ins, 53 mismatched). Two 16-bit BITFIELDS in a
* u32 container give the SImode, align-4 struct gcc keeps in a register. */
typedef struct {
u32 lo : 16;
u32 hi : 16;
} Ang2_8012B77C_8012B77C;
/* a0 = destination packed-angle word, a1 = "from" entity, a2 = "to" entity.
* Both entities carry 16.16 fixed-point x/y/z at +0/+4/+8; the s16 reads at +2/+6/+0xA are
* the integer halves. Returns the destination pointer — the return value is REAL: without it
* gcc stores with `sw $s4,0($s3)` (57 ins) instead of the target's
* addu $v0,$s3,$zero ; sw $s4,0($v0) (the return-value copy that the store's base coalesces onto).
* The flattened `dz` reuse at the end is also load-bearing: making the (dz*sin + dx*cos)>>12
* temp its OWN variable gives it $a1 for the whole chain; reusing `dz` extends that allocno so
* it lands in $s5 exactly as the target does (`sra $s5,$v0,12` / `negu $a1,$s5`), and it also
* demotes dz's priority so the saved-reg order comes out $s3=out, $s4=t, $s5=dz. */
s32 func_8012B77C(s32 out, s32 from, s32 to) {
Ang2_8012B77C_8012B77C t;
s32 dx, dy, dz;
s32 ang;
s32 r1, r2;
dz = *(s16 *)(to + 0xA) - *(s16 *)(from + 0xA);
dx = *(s16 *)(to + 0x2) - *(s16 *)(from + 0x2);
dy = *(s16 *)(to + 0x6) - *(s16 *)(from + 0x6);
ang = (ratan2(-dz, dx) - 0x400) & 0xFFF;
t.hi = ang;
r1 = func_80047948(ang);
r2 = func_8004787C(ang);
dz = (dz * r1 + dx * r2) >> 12;
t.lo = ratan2(dy, -dz);
*(Ang2_8012B77C_8012B77C *)out = t;
return out;
}
DEFINE_func_8012B864() /* dedup: shared engine-core @0x8012B864 (src/shared) */
+74 -1
View File
@@ -3172,7 +3172,80 @@ void func_80175DA8(param_1)
}
INCLUDE_ASM("asm/ov_SC02_004/nonmatchings/ov_SC02_004_jr_801734BC", func_80176144);
/* func_80176144 — RECONCILED variant of .run/uc/func_80176144.c
*
* GATE BLOCKER (whole-binary build, NOT match_one):
* src/ov_SC01_077/ov_SC01_077_jr_801734BC.c:3476: conflicting types for `D_800AF634'
* || previous declaration at :3296
*
* ROOT CAUSE — a HOISTED file-scope typedef, not a bad signature:
* That TU hoists, at FILE scope, for func_80175DA8:
* :3295 typedef struct { s32 g0; s32 pad[2]; } S_AF634_80176144;
* :3296 extern S_AF634_80176144 D_800AF634[];
* :3297 extern S_AF634_80176144 D_800AF638[];
* The stored draft re-declares the SAME struct shape as a BLOCK-scope typedef
* (rule D — it must travel to the 137 sibling overlays, which have no such
* preamble). A block-scope `typedef struct {...} S_AF634_80176144;` is a DISTINCT type
* from the file-scope one (C has no structural typing), so the block-scope
* `extern S_AF634_80176144 D_800AF634[];` re-declares the symbol incompatibly with the
* in-scope file-scope decl -> hard error.
* Note the earlier block-scope copies in the same TU (:3080 func_80175820,
* :3123 func_801759D8) do NOT error: they precede :3296, so no file-scope decl
* of D_800AF634 is in scope there. Anything AFTER :3296 collides. Our
* definition lands at :3476. That is why only this one fired.
*
* FIX — §37/§124 ASM-LABEL ALIAS applied to the DATA symbols (cookbook §2516:
* "asm-label alias for sibling-decl signedness/proto conflicts ... beats
* reconcile's *(u16*)&D_x cast whose address-of PERTURBS regalloc"):
* the two objects are reached through PRIVATE C identifiers aAF634 / aAF638
* carrying __asm__("D_800AF634") / __asm__("D_800AF638"). The emitted
* %hi/%lo relocations are against the same symbols, so codegen is unchanged,
* while the C names can never collide with ANY sibling TU's declaration —
* whether hoisted, block-scope, or absent. No header edit; no src/ edit.
* Strictly better than deleting the local decls (which would bind this
* exemplar to the one TU that happens to hoist them).
*
* The s32 parameter + explicit (s16) narrowing is retained from the stored draft
* (canonical decl in engine_core.h:18985/:4587 is `void func_80176144(s32)`;
* the K&R short param would itself be a conflicting-types error). The (s16)
* narrowing IS the entry `sll $s0,$a0,16 / sra $s0,$s0,16` pair.
*
* Verified: python3 tools/match_one.py func_80176144 --c .run/uc2/func_80176144.c
* --asm-subdir ov_SC01_077/nonmatchings/ov_SC01_077_jr_801734BC -> MATCH (53 ins)
*/
void func_80176144(s32 a0)
{
typedef struct { s32 g0; s32 pad[2]; } S_AF634_80176144; /* size 0x0C */
/* §37 asm-label alias: private C names, canonical relocations. */
extern S_AF634_80176144 aAF634[] __asm__("D_800AF634");
extern S_AF634_80176144 aAF638[] __asm__("D_800AF638");
extern u8 D_8011F7A8;
extern s16 D_8011F7BC;
extern s16 D_8011F7BE;
extern s32 func_80178004(s32 a0, s32 a1, s32 a2);
u32 *slot;
u32 *p;
s16 param_1 = (s16)a0;
p = (u32 *)(aAF638[param_1].g0 + aAF634[param_1].g0 * 4);
slot = (u32 *)(param_1 * 4 + (s32)&D_8011F7A8);
slot[14] = (u32)p;
/* §5a zero-byte sched fence: without it sched1 hoists the two %hi/lhu global
argument loads above the `sw` of slot[14] (16 mismatches, 0 length drift). */
__asm__("");
p = (u32 *)func_80178004((s32)p,
(s16)((*(u16 *)&D_8011F7BC) - 0x17),
(s16)((*(u16 *)&D_8011F7BE) + 0x65));
slot[16] = (u32)p - 0x14;
p += 5;
aAF634[param_1].g0 += ((s32)p - (s32)slot[14]) >> 2;
}
// @class: regalloc-order
+21 -1
View File
@@ -387,7 +387,27 @@ void func_80128AF4(void) {
DEFINE_func_80128C14() /* dedup: shared engine-core @0x80128C14 (src/shared) */
INCLUDE_ASM("asm/ov_SC02_005/nonmatchings/ov_SC02_005", func_80128C98);
typedef struct {
s32 word0;
s32 word4;
} CdFileLoc_80128C98;
extern CdFileLoc_80128C98 cdFileLocTable[];
extern void func_8001ABBC(s32 a0, s32 a1, void *a2, s32 a3, s32 a4);
s32 func_80128C98(s32 arg0) {
extern s16 D_80190B90[];
s16 idx = D_80190B90[arg0];
if (idx >= 0) {
func_8001ABBC(0, 0, (u8 *)&cdFileLocTable[idx], D_801E1AD8, 0);
} else {
return 1;
}
}
INCLUDE_ASM("asm/ov_SC02_005/nonmatchings/ov_SC02_005", func_80128CFC);
+78 -1
View File
@@ -481,7 +481,84 @@ INCLUDE_ASM("asm/ov_SC02_005/nonmatchings/ov_SC02_005_after", func_80146A6C);
DEFINE_func_80146AB4() /* dedup: shared engine-core @0x80146AB4 (src/shared) */
INCLUDE_ASM("asm/ov_SC02_005/nonmatchings/ov_SC02_005_after", func_80146AFC);
extern s32 func_80146B9C(void * arg0);
/* func_80146AFC — ASCENDING twin of the byte-proven DEFINE_func_80146B9C()
* in src/shared/engine_core.h (cookbook §71: find the already-matched sibling first).
* Same 0x58-stride slot table (base D_8011D030), same 7-store copy body in the same
* order, same $a2/$a1 giv pair. 80146B9C walks DOWN; this one walks UP, so the guard
* is `p < end`, end = p + 0xA50 (30 slots x 0x58).
*
* DECAY ROOT CAUSE (this redraft): the stored backlog draft had been rewritten to
* `void func_80146AFC(...)`, which drops BOTH `return 0` paths' `addu $v0,$zero,$zero`
* and the hit path's `j .L80146B94` => LENGTH-DRIFT -2 (38 vs 40) plus $v0/$v1 regalloc
* drift on the final lw/sw pair. Restoring the s32 return type (the fleet spelling the
* banked sibling func_80146B9C already uses) restores MATCH at 40/40.
*
* RECONCILE (2026-08-01) — the whole-binary gate failed with
* ov_SC01_077_after.c:592: conflicting types for `D_8011D030' (previous decl :564)
* TWO file-scope collisions were present; both are fixed HERE, with NO edit to
* src/shared/engine_core.h and NO change to the generated code (re-verified MATCH
* after each step):
*
* 1. D_8011D030 (the reported one). DEFINE_func_801469C8() emits
* `extern s32 D_8011D030;` at FILE scope (engine_core.h:10811, above the
* `s32 func_801469C8(...) {` line), and this TU expands that macro at :564 —
extern s32 D_8011D030;
* i.e. before the splice point :570. The draft's `extern u16` therefore
* redeclared it incompatibly at :592. Conformed to the TU's `extern s32`.
* Codegen-neutral: the sole use is `(u8 *)&D_8011D030`, an address-of, so the
* declared object type never reaches a load/store width (cookbook §20).
*
* 2. func_80146AFC ITSELF (latent, would have surfaced next). DEFINE_func_8014C010()
* (:13510) and DEFINE_func_8014AD30() (:13524) each emit a file-scope
* `extern void func_80146AFC(void *a0);`, and this TU expands them at :1386 and
* :1541 — after the splice — so an `s32 func_80146AFC` definition collides on the
* RETURN axis. Fixed with the §37/§124 ASM-LABEL ALIAS: the C identifier is
* aF80146AFC, the emitted label is func_80146AFC, so the canonical void decl and
* this s32 definition never share a namespace. Callers discard the result, so the
* void-typed call sites stay codegen-identical.
*
* Both were reproduced and then cleared against the real cpp+cc1-2.7.2 pair using a
* synthetic copy of this TU's declaration environment (.run/uc2/_recon_probe_80146AFC.c):
* the pre-reconcile spelling emits exactly the gate's error pair; the spelling below
* compiles clean.
*
* ORACLE: tools/match_one.py func_80146AFC --c .run/uc2/func_80146AFC.c
* --asm-subdir asm/ov_SC01_077/nonmatchings/ov_SC01_077_after -> MATCH (40 ins)
*/
s32 aF80146AFC(void *arg0) __asm__("func_80146AFC");
s32 aF80146AFC(void *arg0)
{
register u8 *p __asm__("$6");
register u8 *q __asm__("$5");
u8 *end;
p = (u8 *)&D_8011D030;
end = p + 0xA50;
if ((u32)p < (u32)end) {
q = p + 0x30;
do {
if (*(u16 *)p == 0) {
*(s32 *)(q + 0x4) = *(s32 *)((u8 *)arg0 + 0x8);
*(s16 *)p = *(u16 *)((u8 *)arg0 + 0x0);
*(s16 *)(q - 0x2A) = *(u16 *)((u8 *)arg0 + 0x2);
*(s16 *)(q - 0x26) = *(u16 *)((u8 *)arg0 + 0x4);
*(s16 *)(q - 0x22) = *(u16 *)((u8 *)arg0 + 0x6);
*(s32 *)(q - 0x4) = *(s32 *)((u8 *)arg0 + 0xC);
*(s32 *)(q + 0x0) = *(s32 *)((u8 *)arg0 + 0x10);
return (s32)p;
}
p += 0x58;
q += 0x58;
} while ((u32)p < (u32)end);
}
return 0;
}
DEFINE_func_80146B9C() /* dedup: shared engine-core @0x80146B9C (src/shared) */
+49 -1
View File
@@ -327,7 +327,55 @@ DEFINE_func_8012B70C() /* dedup: shared engine-core @0x8012B70C (src/shared) */
DEFINE_func_8012B744() /* dedup: shared engine-core @0x8012B744 (src/shared) */
INCLUDE_ASM("asm/ov_SC02_005/nonmatchings/ov_SC02_005_jr_8012ACE0", func_8012B77C);
extern s32 ratan2(s32 a0, s32 a1);
extern s32 func_80047948(s32 a0); /* rsin-like: angle (0..0xFFF) -> 1.12 fixed */
extern s32 func_8004787C(s32 a0); /* rcos-like: angle (0..0xFFF) -> 1.12 fixed */
/* The 4-byte destination is a PACKED PAIR of angles held entirely in ONE saved register
* ($s4) across all three calls — that is what produces the target's
* andi $s4,$s4,0xFFFF (read of the still-uninitialized local, hoisted into the prologue)
* ... or $s4,$s4,ang<<16 -> t.hi = yaw
* ... and $s4,$s4,0xFFFF0000 / or $s4,$s4,ang&0xFFFF -> t.lo = pitch
* A `struct { s16 lo, hi; }` has align 2 -> BLKmode-ish handling: gcc spills it to the stack
* and stores it with lwl/lwr + swl/swr (54 ins, 53 mismatched). Two 16-bit BITFIELDS in a
* u32 container give the SImode, align-4 struct gcc keeps in a register. */
typedef struct {
u32 lo : 16;
u32 hi : 16;
} Ang2_8012B77C_8012B77C;
/* a0 = destination packed-angle word, a1 = "from" entity, a2 = "to" entity.
* Both entities carry 16.16 fixed-point x/y/z at +0/+4/+8; the s16 reads at +2/+6/+0xA are
* the integer halves. Returns the destination pointer — the return value is REAL: without it
* gcc stores with `sw $s4,0($s3)` (57 ins) instead of the target's
* addu $v0,$s3,$zero ; sw $s4,0($v0) (the return-value copy that the store's base coalesces onto).
* The flattened `dz` reuse at the end is also load-bearing: making the (dz*sin + dx*cos)>>12
* temp its OWN variable gives it $a1 for the whole chain; reusing `dz` extends that allocno so
* it lands in $s5 exactly as the target does (`sra $s5,$v0,12` / `negu $a1,$s5`), and it also
* demotes dz's priority so the saved-reg order comes out $s3=out, $s4=t, $s5=dz. */
s32 func_8012B77C(s32 out, s32 from, s32 to) {
Ang2_8012B77C_8012B77C t;
s32 dx, dy, dz;
s32 ang;
s32 r1, r2;
dz = *(s16 *)(to + 0xA) - *(s16 *)(from + 0xA);
dx = *(s16 *)(to + 0x2) - *(s16 *)(from + 0x2);
dy = *(s16 *)(to + 0x6) - *(s16 *)(from + 0x6);
ang = (ratan2(-dz, dx) - 0x400) & 0xFFF;
t.hi = ang;
r1 = func_80047948(ang);
r2 = func_8004787C(ang);
dz = (dz * r1 + dx * r2) >> 12;
t.lo = ratan2(dy, -dz);
*(Ang2_8012B77C_8012B77C *)out = t;
return out;
}
DEFINE_func_8012B864() /* dedup: shared engine-core @0x8012B864 (src/shared) */
+74 -1
View File
@@ -3174,7 +3174,80 @@ void func_80175DA8(param_1)
}
INCLUDE_ASM("asm/ov_SC02_005/nonmatchings/ov_SC02_005_jr_801734BC", func_80176144);
/* func_80176144 — RECONCILED variant of .run/uc/func_80176144.c
*
* GATE BLOCKER (whole-binary build, NOT match_one):
* src/ov_SC01_077/ov_SC01_077_jr_801734BC.c:3476: conflicting types for `D_800AF634'
* || previous declaration at :3296
*
* ROOT CAUSE — a HOISTED file-scope typedef, not a bad signature:
* That TU hoists, at FILE scope, for func_80175DA8:
* :3295 typedef struct { s32 g0; s32 pad[2]; } S_AF634_80176144;
* :3296 extern S_AF634_80176144 D_800AF634[];
* :3297 extern S_AF634_80176144 D_800AF638[];
* The stored draft re-declares the SAME struct shape as a BLOCK-scope typedef
* (rule D — it must travel to the 137 sibling overlays, which have no such
* preamble). A block-scope `typedef struct {...} S_AF634_80176144;` is a DISTINCT type
* from the file-scope one (C has no structural typing), so the block-scope
* `extern S_AF634_80176144 D_800AF634[];` re-declares the symbol incompatibly with the
* in-scope file-scope decl -> hard error.
* Note the earlier block-scope copies in the same TU (:3080 func_80175820,
* :3123 func_801759D8) do NOT error: they precede :3296, so no file-scope decl
* of D_800AF634 is in scope there. Anything AFTER :3296 collides. Our
* definition lands at :3476. That is why only this one fired.
*
* FIX — §37/§124 ASM-LABEL ALIAS applied to the DATA symbols (cookbook §2516:
* "asm-label alias for sibling-decl signedness/proto conflicts ... beats
* reconcile's *(u16*)&D_x cast whose address-of PERTURBS regalloc"):
* the two objects are reached through PRIVATE C identifiers aAF634 / aAF638
* carrying __asm__("D_800AF634") / __asm__("D_800AF638"). The emitted
* %hi/%lo relocations are against the same symbols, so codegen is unchanged,
* while the C names can never collide with ANY sibling TU's declaration —
* whether hoisted, block-scope, or absent. No header edit; no src/ edit.
* Strictly better than deleting the local decls (which would bind this
* exemplar to the one TU that happens to hoist them).
*
* The s32 parameter + explicit (s16) narrowing is retained from the stored draft
* (canonical decl in engine_core.h:18985/:4587 is `void func_80176144(s32)`;
* the K&R short param would itself be a conflicting-types error). The (s16)
* narrowing IS the entry `sll $s0,$a0,16 / sra $s0,$s0,16` pair.
*
* Verified: python3 tools/match_one.py func_80176144 --c .run/uc2/func_80176144.c
* --asm-subdir ov_SC01_077/nonmatchings/ov_SC01_077_jr_801734BC -> MATCH (53 ins)
*/
void func_80176144(s32 a0)
{
typedef struct { s32 g0; s32 pad[2]; } S_AF634_80176144; /* size 0x0C */
/* §37 asm-label alias: private C names, canonical relocations. */
extern S_AF634_80176144 aAF634[] __asm__("D_800AF634");
extern S_AF634_80176144 aAF638[] __asm__("D_800AF638");
extern u8 D_8011F7A8;
extern s16 D_8011F7BC;
extern s16 D_8011F7BE;
extern s32 func_80178004(s32 a0, s32 a1, s32 a2);
u32 *slot;
u32 *p;
s16 param_1 = (s16)a0;
p = (u32 *)(aAF638[param_1].g0 + aAF634[param_1].g0 * 4);
slot = (u32 *)(param_1 * 4 + (s32)&D_8011F7A8);
slot[14] = (u32)p;
/* §5a zero-byte sched fence: without it sched1 hoists the two %hi/lhu global
argument loads above the `sw` of slot[14] (16 mismatches, 0 length drift). */
__asm__("");
p = (u32 *)func_80178004((s32)p,
(s16)((*(u16 *)&D_8011F7BC) - 0x17),
(s16)((*(u16 *)&D_8011F7BE) + 0x65));
slot[16] = (u32)p - 0x14;
p += 5;
aAF634[param_1].g0 += ((s32)p - (s32)slot[14]) >> 2;
}
// @class: regalloc-order
+21 -1
View File
@@ -387,7 +387,27 @@ void func_80128AF4(void) {
DEFINE_func_80128C14() /* dedup: shared engine-core @0x80128C14 (src/shared) */
INCLUDE_ASM("asm/ov_SC02_011/nonmatchings/ov_SC02_011", func_80128C98);
typedef struct {
s32 word0;
s32 word4;
} CdFileLoc_80128C98;
extern CdFileLoc_80128C98 cdFileLocTable[];
extern void func_8001ABBC(s32 a0, s32 a1, void *a2, s32 a3, s32 a4);
s32 func_80128C98(s32 arg0) {
extern s16 D_80190FE0[];
s16 idx = D_80190FE0[arg0];
if (idx >= 0) {
func_8001ABBC(0, 0, (u8 *)&cdFileLocTable[idx], D_801E8C34, 0);
} else {
return 1;
}
}
INCLUDE_ASM("asm/ov_SC02_011/nonmatchings/ov_SC02_011", func_80128CFC);
+78 -1
View File
@@ -481,7 +481,84 @@ INCLUDE_ASM("asm/ov_SC02_011/nonmatchings/ov_SC02_011_after", func_80146A6C);
DEFINE_func_80146AB4() /* dedup: shared engine-core @0x80146AB4 (src/shared) */
INCLUDE_ASM("asm/ov_SC02_011/nonmatchings/ov_SC02_011_after", func_80146AFC);
extern s32 func_80146B9C(void * arg0);
/* func_80146AFC — ASCENDING twin of the byte-proven DEFINE_func_80146B9C()
* in src/shared/engine_core.h (cookbook §71: find the already-matched sibling first).
* Same 0x58-stride slot table (base D_8011D030), same 7-store copy body in the same
* order, same $a2/$a1 giv pair. 80146B9C walks DOWN; this one walks UP, so the guard
* is `p < end`, end = p + 0xA50 (30 slots x 0x58).
*
* DECAY ROOT CAUSE (this redraft): the stored backlog draft had been rewritten to
* `void func_80146AFC(...)`, which drops BOTH `return 0` paths' `addu $v0,$zero,$zero`
* and the hit path's `j .L80146B94` => LENGTH-DRIFT -2 (38 vs 40) plus $v0/$v1 regalloc
* drift on the final lw/sw pair. Restoring the s32 return type (the fleet spelling the
* banked sibling func_80146B9C already uses) restores MATCH at 40/40.
*
* RECONCILE (2026-08-01) — the whole-binary gate failed with
* ov_SC01_077_after.c:592: conflicting types for `D_8011D030' (previous decl :564)
* TWO file-scope collisions were present; both are fixed HERE, with NO edit to
* src/shared/engine_core.h and NO change to the generated code (re-verified MATCH
* after each step):
*
* 1. D_8011D030 (the reported one). DEFINE_func_801469C8() emits
* `extern s32 D_8011D030;` at FILE scope (engine_core.h:10811, above the
* `s32 func_801469C8(...) {` line), and this TU expands that macro at :564 —
extern s32 D_8011D030;
* i.e. before the splice point :570. The draft's `extern u16` therefore
* redeclared it incompatibly at :592. Conformed to the TU's `extern s32`.
* Codegen-neutral: the sole use is `(u8 *)&D_8011D030`, an address-of, so the
* declared object type never reaches a load/store width (cookbook §20).
*
* 2. func_80146AFC ITSELF (latent, would have surfaced next). DEFINE_func_8014C010()
* (:13510) and DEFINE_func_8014AD30() (:13524) each emit a file-scope
* `extern void func_80146AFC(void *a0);`, and this TU expands them at :1386 and
* :1541 — after the splice — so an `s32 func_80146AFC` definition collides on the
* RETURN axis. Fixed with the §37/§124 ASM-LABEL ALIAS: the C identifier is
* aF80146AFC, the emitted label is func_80146AFC, so the canonical void decl and
* this s32 definition never share a namespace. Callers discard the result, so the
* void-typed call sites stay codegen-identical.
*
* Both were reproduced and then cleared against the real cpp+cc1-2.7.2 pair using a
* synthetic copy of this TU's declaration environment (.run/uc2/_recon_probe_80146AFC.c):
* the pre-reconcile spelling emits exactly the gate's error pair; the spelling below
* compiles clean.
*
* ORACLE: tools/match_one.py func_80146AFC --c .run/uc2/func_80146AFC.c
* --asm-subdir asm/ov_SC01_077/nonmatchings/ov_SC01_077_after -> MATCH (40 ins)
*/
s32 aF80146AFC(void *arg0) __asm__("func_80146AFC");
s32 aF80146AFC(void *arg0)
{
register u8 *p __asm__("$6");
register u8 *q __asm__("$5");
u8 *end;
p = (u8 *)&D_8011D030;
end = p + 0xA50;
if ((u32)p < (u32)end) {
q = p + 0x30;
do {
if (*(u16 *)p == 0) {
*(s32 *)(q + 0x4) = *(s32 *)((u8 *)arg0 + 0x8);
*(s16 *)p = *(u16 *)((u8 *)arg0 + 0x0);
*(s16 *)(q - 0x2A) = *(u16 *)((u8 *)arg0 + 0x2);
*(s16 *)(q - 0x26) = *(u16 *)((u8 *)arg0 + 0x4);
*(s16 *)(q - 0x22) = *(u16 *)((u8 *)arg0 + 0x6);
*(s32 *)(q - 0x4) = *(s32 *)((u8 *)arg0 + 0xC);
*(s32 *)(q + 0x0) = *(s32 *)((u8 *)arg0 + 0x10);
return (s32)p;
}
p += 0x58;
q += 0x58;
} while ((u32)p < (u32)end);
}
return 0;
}
DEFINE_func_80146B9C() /* dedup: shared engine-core @0x80146B9C (src/shared) */
+49 -1
View File
@@ -327,7 +327,55 @@ DEFINE_func_8012B70C() /* dedup: shared engine-core @0x8012B70C (src/shared) */
DEFINE_func_8012B744() /* dedup: shared engine-core @0x8012B744 (src/shared) */
INCLUDE_ASM("asm/ov_SC02_011/nonmatchings/ov_SC02_011_jr_8012ACE0", func_8012B77C);
extern s32 ratan2(s32 a0, s32 a1);
extern s32 func_80047948(s32 a0); /* rsin-like: angle (0..0xFFF) -> 1.12 fixed */
extern s32 func_8004787C(s32 a0); /* rcos-like: angle (0..0xFFF) -> 1.12 fixed */
/* The 4-byte destination is a PACKED PAIR of angles held entirely in ONE saved register
* ($s4) across all three calls — that is what produces the target's
* andi $s4,$s4,0xFFFF (read of the still-uninitialized local, hoisted into the prologue)
* ... or $s4,$s4,ang<<16 -> t.hi = yaw
* ... and $s4,$s4,0xFFFF0000 / or $s4,$s4,ang&0xFFFF -> t.lo = pitch
* A `struct { s16 lo, hi; }` has align 2 -> BLKmode-ish handling: gcc spills it to the stack
* and stores it with lwl/lwr + swl/swr (54 ins, 53 mismatched). Two 16-bit BITFIELDS in a
* u32 container give the SImode, align-4 struct gcc keeps in a register. */
typedef struct {
u32 lo : 16;
u32 hi : 16;
} Ang2_8012B77C_8012B77C;
/* a0 = destination packed-angle word, a1 = "from" entity, a2 = "to" entity.
* Both entities carry 16.16 fixed-point x/y/z at +0/+4/+8; the s16 reads at +2/+6/+0xA are
* the integer halves. Returns the destination pointer — the return value is REAL: without it
* gcc stores with `sw $s4,0($s3)` (57 ins) instead of the target's
* addu $v0,$s3,$zero ; sw $s4,0($v0) (the return-value copy that the store's base coalesces onto).
* The flattened `dz` reuse at the end is also load-bearing: making the (dz*sin + dx*cos)>>12
* temp its OWN variable gives it $a1 for the whole chain; reusing `dz` extends that allocno so
* it lands in $s5 exactly as the target does (`sra $s5,$v0,12` / `negu $a1,$s5`), and it also
* demotes dz's priority so the saved-reg order comes out $s3=out, $s4=t, $s5=dz. */
s32 func_8012B77C(s32 out, s32 from, s32 to) {
Ang2_8012B77C_8012B77C t;
s32 dx, dy, dz;
s32 ang;
s32 r1, r2;
dz = *(s16 *)(to + 0xA) - *(s16 *)(from + 0xA);
dx = *(s16 *)(to + 0x2) - *(s16 *)(from + 0x2);
dy = *(s16 *)(to + 0x6) - *(s16 *)(from + 0x6);
ang = (ratan2(-dz, dx) - 0x400) & 0xFFF;
t.hi = ang;
r1 = func_80047948(ang);
r2 = func_8004787C(ang);
dz = (dz * r1 + dx * r2) >> 12;
t.lo = ratan2(dy, -dz);
*(Ang2_8012B77C_8012B77C *)out = t;
return out;
}
DEFINE_func_8012B864() /* dedup: shared engine-core @0x8012B864 (src/shared) */
+74 -1
View File
@@ -3172,7 +3172,80 @@ void func_80175DA8(param_1)
}
INCLUDE_ASM("asm/ov_SC02_011/nonmatchings/ov_SC02_011_jr_801734BC", func_80176144);
/* func_80176144 — RECONCILED variant of .run/uc/func_80176144.c
*
* GATE BLOCKER (whole-binary build, NOT match_one):
* src/ov_SC01_077/ov_SC01_077_jr_801734BC.c:3476: conflicting types for `D_800AF634'
* || previous declaration at :3296
*
* ROOT CAUSE — a HOISTED file-scope typedef, not a bad signature:
* That TU hoists, at FILE scope, for func_80175DA8:
* :3295 typedef struct { s32 g0; s32 pad[2]; } S_AF634_80176144;
* :3296 extern S_AF634_80176144 D_800AF634[];
* :3297 extern S_AF634_80176144 D_800AF638[];
* The stored draft re-declares the SAME struct shape as a BLOCK-scope typedef
* (rule D — it must travel to the 137 sibling overlays, which have no such
* preamble). A block-scope `typedef struct {...} S_AF634_80176144;` is a DISTINCT type
* from the file-scope one (C has no structural typing), so the block-scope
* `extern S_AF634_80176144 D_800AF634[];` re-declares the symbol incompatibly with the
* in-scope file-scope decl -> hard error.
* Note the earlier block-scope copies in the same TU (:3080 func_80175820,
* :3123 func_801759D8) do NOT error: they precede :3296, so no file-scope decl
* of D_800AF634 is in scope there. Anything AFTER :3296 collides. Our
* definition lands at :3476. That is why only this one fired.
*
* FIX — §37/§124 ASM-LABEL ALIAS applied to the DATA symbols (cookbook §2516:
* "asm-label alias for sibling-decl signedness/proto conflicts ... beats
* reconcile's *(u16*)&D_x cast whose address-of PERTURBS regalloc"):
* the two objects are reached through PRIVATE C identifiers aAF634 / aAF638
* carrying __asm__("D_800AF634") / __asm__("D_800AF638"). The emitted
* %hi/%lo relocations are against the same symbols, so codegen is unchanged,
* while the C names can never collide with ANY sibling TU's declaration —
* whether hoisted, block-scope, or absent. No header edit; no src/ edit.
* Strictly better than deleting the local decls (which would bind this
* exemplar to the one TU that happens to hoist them).
*
* The s32 parameter + explicit (s16) narrowing is retained from the stored draft
* (canonical decl in engine_core.h:18985/:4587 is `void func_80176144(s32)`;
* the K&R short param would itself be a conflicting-types error). The (s16)
* narrowing IS the entry `sll $s0,$a0,16 / sra $s0,$s0,16` pair.
*
* Verified: python3 tools/match_one.py func_80176144 --c .run/uc2/func_80176144.c
* --asm-subdir ov_SC01_077/nonmatchings/ov_SC01_077_jr_801734BC -> MATCH (53 ins)
*/
void func_80176144(s32 a0)
{
typedef struct { s32 g0; s32 pad[2]; } S_AF634_80176144; /* size 0x0C */
/* §37 asm-label alias: private C names, canonical relocations. */
extern S_AF634_80176144 aAF634[] __asm__("D_800AF634");
extern S_AF634_80176144 aAF638[] __asm__("D_800AF638");
extern u8 D_8011F7A8;
extern s16 D_8011F7BC;
extern s16 D_8011F7BE;
extern s32 func_80178004(s32 a0, s32 a1, s32 a2);
u32 *slot;
u32 *p;
s16 param_1 = (s16)a0;
p = (u32 *)(aAF638[param_1].g0 + aAF634[param_1].g0 * 4);
slot = (u32 *)(param_1 * 4 + (s32)&D_8011F7A8);
slot[14] = (u32)p;
/* §5a zero-byte sched fence: without it sched1 hoists the two %hi/lhu global
argument loads above the `sw` of slot[14] (16 mismatches, 0 length drift). */
__asm__("");
p = (u32 *)func_80178004((s32)p,
(s16)((*(u16 *)&D_8011F7BC) - 0x17),
(s16)((*(u16 *)&D_8011F7BE) + 0x65));
slot[16] = (u32)p - 0x14;
p += 5;
aAF634[param_1].g0 += ((s32)p - (s32)slot[14]) >> 2;
}
// @class: regalloc-order
+266 -5
View File
@@ -3664,7 +3664,67 @@ INCLUDE_ASM("asm/ov_SC02_011/nonmatchings/ov_SC02_011_jr_8017AE2C", func_8017FCA
INCLUDE_ASM("asm/ov_SC02_011/nonmatchings/ov_SC02_011_jr_8017AE2C", func_8017FD2C);
INCLUDE_ASM("asm/ov_SC02_011/nonmatchings/ov_SC02_011_jr_8017AE2C", func_8017FD9C);
/* func_8017FD9C — fade the 4-byte colour quad at D_801EB488 one step toward 0
* (func_80012F74 = "step a value toward a target"), splat the byte over the
* three sibling bytes, mirror the whole quad into the three following quads,
* then tear the entity down once the byte reaches 0.
*
* §71 sibling-first: DEFINE_func_801685EC() (engine_core.h L8520) is the same
* `if (<call result> == 0) ((void (*)(s32))func_80146C3C)(arg0);` teardown tail.
* In-TU sibling func_8017D678 shows D_801EB489/D_801EB48A are SEPARATE u8
* globals (each gets its own lui/%lo sb) while D_801EB488's address lives in a
* callee-saved register.
*
* @class: schedule (LENGTH-DRIFT/-1)
* @stuck: none — MATCH 50/50 (match_one AND rtu_match), iteration 2.
* THE CRACK (one edit): the TRAILING reload `if (*p == 0)` was being hoisted by
* sched2 up past the third block move, where the swl/swr pair covered its load
* delay — costing exactly the one `nop` the target keeps (49 vs 50 ins,
* LENGTH-DRIFT/-1). A second zero-byte `__asm__("")` fence between the last
* struct assignment and the `if` pins the lbu after the copies and the load-delay
* nop reappears. Lesson: an inline block move (swl/swr) is a fat delay-slot
* SPONGE — any following narrow load will be sucked up into it unless fenced.
* The first fence (after the chained byte stores) is what keeps the block moves
* from being interleaved with them.
* Other levers already in this draft, all load-bearing:
* - `u8 *p = &D_801EB488;` (§20) — one address register ($s0, callee-saved
* across the jal) serves the lbu, the sb and all three block-move sources.
* - chained assignment `D_801EB489 = D_801EB48A = *p = f(...)` gives the
* target's store order 880, 882, 881 (right-to-left after the *p store).
* - the 4×u8 struct (align 1) is what makes the assignment expand to inline
* lwl/lwr + swl/swr instead of a `jal memcpy` (cf. §38).
*/
typedef struct {
u8 b0, b1, b2, b3;
} Quad_801EA880_8017FD9C; /* align 1 => movstrsi expands to lwl/lwr + swl/swr */
extern s32 func_80012F74(s32 a0, s32 a1, s32 a2, s32 a3);
extern void func_80146C3C(void);
void func_8017FD9C(s32 arg0) {
extern u8 D_801EB488;
extern u8 D_801EB489;
extern u8 D_801EB48A;
extern u8 D_801EB48C;
extern u8 D_801EB490;
extern u8 D_801EB494;
u8 *p = &D_801EB488;
D_801EB489 = D_801EB48A = *p = func_80012F74(*p, 0, 10, 1);
__asm__("");
*(Quad_801EA880_8017FD9C *)&D_801EB48C = *(Quad_801EA880_8017FD9C *)p;
*(Quad_801EA880_8017FD9C *)&D_801EB490 = *(Quad_801EA880_8017FD9C *)p;
*(Quad_801EA880_8017FD9C *)&D_801EB494 = *(Quad_801EA880_8017FD9C *)p;
__asm__("");
if (*p == 0) {
((void (*)(s32))func_80146C3C)(arg0);
}
}
INCLUDE_ASM("asm/ov_SC02_011/nonmatchings/ov_SC02_011_jr_8017AE2C", func_8017FE64);
@@ -3788,7 +3848,47 @@ void func_801804E8(int param_1)
}
INCLUDE_ASM("asm/ov_SC02_011/nonmatchings/ov_SC02_011_jr_8017AE2C", func_80180544);
/* Entity record touched by func_80180544 (offsets read straight off the asm):
* 0x02 u16 frame/state counter (lhu / sh)
* 0x1C s32 tick counter (lw / sw), signed compare against 0x20
* 0x2A u16 y-ish delta, decremented by 0x10 (lhu / sh)
* 0x2C u16 sound id passed to func_80147324 (lhu)
* 0x30 s32 suppress flag
*/
typedef struct Ent_8017BFE0_80180544 {
u8 pad00[2]; /* 0x00 */
u16 f02; /* 0x02 */
u8 pad04[0x18];/* 0x04 */
s32 f1c; /* 0x1C */
u8 pad20[0xA]; /* 0x20 */
u16 f2a; /* 0x2A */
u16 f2c; /* 0x2C */
u8 pad2e[2]; /* 0x2E */
s32 f30; /* 0x30 */
} Ent_8017BFE0_80180544;
extern void func_80147324(s32 arg0);
extern void func_8018077C(int);
void func_80180544(Ent_8017BFE0_80180544 *param_1)
{
s32 t;
t = param_1->f1c;
param_1->f1c = t + 1;
if (t < 0x20) {
param_1->f2a = param_1->f2a - 0x10;
} else {
if (param_1->f30 == 0) {
func_80147324(param_1->f2c);
}
param_1->f1c = 0;
param_1->f02 = param_1->f02 + 1;
}
((void (*)(Ent_8017BFE0_80180544 *))func_8018077C)(param_1);
}
INCLUDE_ASM("asm/ov_SC02_011/nonmatchings/ov_SC02_011_jr_8017AE2C", func_801805C8);
@@ -3953,7 +4053,72 @@ void func_80180D28(void *a0) {
}
INCLUDE_ASM("asm/ov_SC02_011/nonmatchings/ov_SC02_011_jr_8017AE2C", func_80180D64);
/* func_80180D64 — spawn/scatter tick for the +0x34 sub-object (state word @0x2).
* MATCH (45 ins), match_one + rtu_match. Four levers, in the order they were found:
*
* 1. §71 sibling-first — same entity shape as func_8017C610 / func_8017C69C in this
* TU: sub-object pointer @0x34 read BEFORE the call (it lives in $s1 across the
* jal), state word @0x2 bumped last. §3-T4: `beqz $v1,else` => `if (p->f2C) {..}`.
* ONE rand() feeds three fields; the raw low 6 bits use a bare `andi` (no extend)
* while the >>12 / >>6 uses share one `sll $x,16` — that shared sign-extend is
* what forces `r` to be a `short` local rather than an int.
*
* 2. §5a CROSS-JUMP — both arms end in `sh ?,0xA($s0)`; gcc tail-merged them (23 off).
* They only stay separate because the loaded halfword lands in a DIFFERENT hard
* reg per arm, which needs (a) the load to be its own statement at the TOP of each
* arm and (b) a SEPARATE temp per arm (t / t2) — one shared temp is one pseudo,
* gets one register in both arms, and re-merges. 23 -> 10 -> 6.
*
* 3. +0x16 is SIGNED: the target materialises -0x20 as `addiu $v0,$zero,-0x20`, not
* `ori 0xffe0`, so that store must go through an s16.
*
* 4. §49 BIRTHING BOOST (the last 6 -> 2 -> 0). Residual was two ALU insns swapped
* with identical registers; source statement order does NOT flip it, because
* sched1's `adjust_priority`/`birthing_insn_p` hands every SET(REG,..) whose dest
* has REG_N_SETS==1 a 0x7f000001 priority, so it sinks to just before its consumer
* and fixes the .greg LUID order that sched2's tie-break then reads.
* THE DIAL: give the offending insn's dest a SECOND set so it loses the boost —
* here one `u16 d` reused by both tail statements. It must be a THIRD temp, not
* `c` itself: writing `c = c + 1;` also un-boosts c's LOAD, which then starves to
* the front of the block and swaps the two `lhu`s instead. Boost the loads, starve
* the arithmetic. */
extern int rand(void);
void func_80180D64(void *a0)
{
s32 p;
s32 obj;
short r;
u16 t;
u16 t2;
u16 e;
u16 c;
u16 d;
p = (s32)a0;
obj = *(s32 *)(p + 0x34);
r = rand();
*(u16 *)(p + 0x06) = *(u16 *)(obj + 0x06) + ((r & 0x3F) - 0x20);
if (*(s32 *)(p + 0x2C) != 0) {
t = *(u16 *)(obj + 0x0A);
*(s16 *)(p + 0x16) = 0x20;
*(u16 *)(p + 0x0A) = t - 0x140;
} else {
t2 = *(u16 *)(obj + 0x0A);
*(s16 *)(p + 0x16) = -0x20;
*(u16 *)(p + 0x0A) = t2;
}
e = *(u16 *)(obj + 0x0E);
c = *(u16 *)(p + 0x02);
*(s32 *)(p + 0x30) = (r >> 12) & 3;
d = ((r >> 6) & 0x3F) - 0x20;
*(u16 *)(p + 0x0E) = e + d;
d = c + 1;
*(u16 *)(p + 0x02) = d;
}
extern void func_800D22E4(s32 a0);
extern void func_80146C3C(void);
@@ -5029,7 +5194,53 @@ void func_8018A708(void) {
}
INCLUDE_ASM("asm/ov_SC02_011/nonmatchings/ov_SC02_011_jr_8017AE2C", func_8018A72C);
/* func_8018A72C — cookbook §71 (sibling-first).
* func_8018A7CC is ALREADY MATCHED in the same TU
* (src/ov_SC03_014/ov_SC03_014_jr_8017EB7C.c L4221) as a 3-arg
* `void func_8018A7CC(s32, s32, s32)`, so the untouched $a3 at the first
* jal is just the incoming arg3 living on, not a 4th argument.
* func_8018A8E8 (asm, same TU) reads its 2nd arg as lhu+0 / lhu+2 / lh+4 /
* lh+6 => the sp+0x10 local is a 4 x s16 record.
*
* Two levers took it 32 -> 2 -> 0 (match_one MATCH, rtu_match MATCH):
* 1. LENGTH-DRIFT (-2, cookbook §78): writing `sp10.unk2 = i * 0x100`
* leaves gcc-2.7.2 recomputing `sll v0,s1,8` instead of building the
* strength-reduced giv, so only s0..s3 get saved and the frame is two
* instructions short. An EXPLICIT accumulator (`ang += 0x100`) forces
* the second callee-saved register ($s2) and restores sw/lw $s4.
* 2. REGALLOC-PERM $s1>$s2 (cookbook §3-T2, source order drives emission):
* `ang = 0;` on its own line before the loop emits the $s2 zero-init
* FIRST. Folding it into the for-init (`for (i = 0, ang = 0; ...)`)
* puts $s1's zero-init first, which is the target order.
*/
typedef struct {
s16 unk0;
s16 unk2;
s16 unk4;
s16 unk6;
} Rec_8018A6A4_8018A72C;
extern void func_8018A7CC(s32 arg0, s32 arg1, s32 arg2);
extern void func_8018A8E8(s32 arg0, Rec_8018A6A4_8018A72C *arg1, s32 arg2, s32 arg3);
void func_8018A72C(s32 arg0, s32 arg1, s32 arg2, s32 arg3) {
Rec_8018A6A4_8018A72C sp10;
s32 i;
s32 ang;
func_8018A7CC(arg0, 0x1000, 0);
sp10.unk0 = *(u16 *)(arg3 + 0x0);
sp10.unk4 = *(u16 *)(arg3 + 0x2);
sp10.unk6 = 1;
for (i = 0, ang = 0; i < 16; i++) {
sp10.unk2 = ang;
func_8018A8E8(i, &sp10, arg1, arg2);
ang += 0x100;
}
}
extern s16 D_801EB6DC;
@@ -5061,7 +5272,57 @@ INCLUDE_ASM("asm/ov_SC02_011/nonmatchings/ov_SC02_011_jr_8017AE2C", func_8018A9B
INCLUDE_ASM("asm/ov_SC02_011/nonmatchings/ov_SC02_011_jr_8017AE2C", func_8018A9F8);
INCLUDE_ASM("asm/ov_SC02_011/nonmatchings/ov_SC02_011_jr_8017AE2C", func_8018AA44);
/* func_8018AA44 — 16-entry table walk, stride 0xE, over D_801EB6E4.
* §71 sibling: func_8018A680 (same TU, L4199) already matched the
* `extern s16 D_801EB6E4; s16 *p = &D_801EB6E4; p = (s16*)((s32)p+0xe)`
* shape over the very same array — copy that walker verbatim.
*
* Two induction registers in the target ($s1 = base+0, $s0 = base+4) are NOT
* two source pointers: $s1 is the user pointer (the biv, used for the +0
* accesses) and $s0 is loop.c's single COMBINED address giv for the
* {+4, +9, +13} group (offsets 0/5/9 off $s0). Declaring a second pointer
* splits that group and costs a third register (iter 1: 53 mismatches).
*/
extern void func_8018AB20(s32 arg0);
void func_8018AA44(void) {
extern s16 D_801EB6E4;
s16 *p = &D_801EB6E4;
s32 i = 0;
s16 t;
do {
if (*(u16 *)p != 0) {
func_8018AB20(i);
switch (*(u8 *)((s32)p + 9)) {
case 1:
if (*(s16 *)((s32)p + 4) < *(u8 *)((s32)p + 13)) {
*(s16 *)((s32)p + 4) = *(s16 *)((s32)p + 4) + 8;
} else {
*(u8 *)((s32)p + 9) = 0;
}
break;
case 2:
t = *(s16 *)((s32)p + 4);
if (t != 0) {
t -= 0x10;
*(s16 *)((s32)p + 4) = t;
if (t > 0) {
break;
}
}
*p = 0;
break;
}
}
i++;
p = (s16 *)((s32)p + 0xe);
} while (i < 0x10);
}
INCLUDE_ASM("asm/ov_SC02_011/nonmatchings/ov_SC02_011_jr_8017AE2C", func_8018AB20);
+21 -1
View File
@@ -387,7 +387,27 @@ void func_80128AF4(void) {
DEFINE_func_80128C14() /* dedup: shared engine-core @0x80128C14 (src/shared) */
INCLUDE_ASM("asm/ov_SC02_015/nonmatchings/ov_SC02_015", func_80128C98);
typedef struct {
s32 word0;
s32 word4;
} CdFileLoc_80128C98;
extern CdFileLoc_80128C98 cdFileLocTable[];
extern void func_8001ABBC(s32 a0, s32 a1, void *a2, s32 a3, s32 a4);
s32 func_80128C98(s32 arg0) {
extern s16 D_8017E4F4[];
s16 idx = D_8017E4F4[arg0];
if (idx >= 0) {
func_8001ABBC(0, 0, (u8 *)&cdFileLocTable[idx], D_8018DE8C, 0);
} else {
return 1;
}
}
INCLUDE_ASM("asm/ov_SC02_015/nonmatchings/ov_SC02_015", func_80128CFC);
+78 -1
View File
@@ -481,7 +481,84 @@ INCLUDE_ASM("asm/ov_SC02_015/nonmatchings/ov_SC02_015_after", func_80146A6C);
DEFINE_func_80146AB4() /* dedup: shared engine-core @0x80146AB4 (src/shared) */
INCLUDE_ASM("asm/ov_SC02_015/nonmatchings/ov_SC02_015_after", func_80146AFC);
extern s32 func_80146B9C(void * arg0);
/* func_80146AFC — ASCENDING twin of the byte-proven DEFINE_func_80146B9C()
* in src/shared/engine_core.h (cookbook §71: find the already-matched sibling first).
* Same 0x58-stride slot table (base D_8011D030), same 7-store copy body in the same
* order, same $a2/$a1 giv pair. 80146B9C walks DOWN; this one walks UP, so the guard
* is `p < end`, end = p + 0xA50 (30 slots x 0x58).
*
* DECAY ROOT CAUSE (this redraft): the stored backlog draft had been rewritten to
* `void func_80146AFC(...)`, which drops BOTH `return 0` paths' `addu $v0,$zero,$zero`
* and the hit path's `j .L80146B94` => LENGTH-DRIFT -2 (38 vs 40) plus $v0/$v1 regalloc
* drift on the final lw/sw pair. Restoring the s32 return type (the fleet spelling the
* banked sibling func_80146B9C already uses) restores MATCH at 40/40.
*
* RECONCILE (2026-08-01) — the whole-binary gate failed with
* ov_SC01_077_after.c:592: conflicting types for `D_8011D030' (previous decl :564)
* TWO file-scope collisions were present; both are fixed HERE, with NO edit to
* src/shared/engine_core.h and NO change to the generated code (re-verified MATCH
* after each step):
*
* 1. D_8011D030 (the reported one). DEFINE_func_801469C8() emits
* `extern s32 D_8011D030;` at FILE scope (engine_core.h:10811, above the
* `s32 func_801469C8(...) {` line), and this TU expands that macro at :564 —
extern s32 D_8011D030;
* i.e. before the splice point :570. The draft's `extern u16` therefore
* redeclared it incompatibly at :592. Conformed to the TU's `extern s32`.
* Codegen-neutral: the sole use is `(u8 *)&D_8011D030`, an address-of, so the
* declared object type never reaches a load/store width (cookbook §20).
*
* 2. func_80146AFC ITSELF (latent, would have surfaced next). DEFINE_func_8014C010()
* (:13510) and DEFINE_func_8014AD30() (:13524) each emit a file-scope
* `extern void func_80146AFC(void *a0);`, and this TU expands them at :1386 and
* :1541 — after the splice — so an `s32 func_80146AFC` definition collides on the
* RETURN axis. Fixed with the §37/§124 ASM-LABEL ALIAS: the C identifier is
* aF80146AFC, the emitted label is func_80146AFC, so the canonical void decl and
* this s32 definition never share a namespace. Callers discard the result, so the
* void-typed call sites stay codegen-identical.
*
* Both were reproduced and then cleared against the real cpp+cc1-2.7.2 pair using a
* synthetic copy of this TU's declaration environment (.run/uc2/_recon_probe_80146AFC.c):
* the pre-reconcile spelling emits exactly the gate's error pair; the spelling below
* compiles clean.
*
* ORACLE: tools/match_one.py func_80146AFC --c .run/uc2/func_80146AFC.c
* --asm-subdir asm/ov_SC01_077/nonmatchings/ov_SC01_077_after -> MATCH (40 ins)
*/
s32 aF80146AFC(void *arg0) __asm__("func_80146AFC");
s32 aF80146AFC(void *arg0)
{
register u8 *p __asm__("$6");
register u8 *q __asm__("$5");
u8 *end;
p = (u8 *)&D_8011D030;
end = p + 0xA50;
if ((u32)p < (u32)end) {
q = p + 0x30;
do {
if (*(u16 *)p == 0) {
*(s32 *)(q + 0x4) = *(s32 *)((u8 *)arg0 + 0x8);
*(s16 *)p = *(u16 *)((u8 *)arg0 + 0x0);
*(s16 *)(q - 0x2A) = *(u16 *)((u8 *)arg0 + 0x2);
*(s16 *)(q - 0x26) = *(u16 *)((u8 *)arg0 + 0x4);
*(s16 *)(q - 0x22) = *(u16 *)((u8 *)arg0 + 0x6);
*(s32 *)(q - 0x4) = *(s32 *)((u8 *)arg0 + 0xC);
*(s32 *)(q + 0x0) = *(s32 *)((u8 *)arg0 + 0x10);
return (s32)p;
}
p += 0x58;
q += 0x58;
} while ((u32)p < (u32)end);
}
return 0;
}
DEFINE_func_80146B9C() /* dedup: shared engine-core @0x80146B9C (src/shared) */
+49 -1
View File
@@ -327,7 +327,55 @@ DEFINE_func_8012B70C() /* dedup: shared engine-core @0x8012B70C (src/shared) */
DEFINE_func_8012B744() /* dedup: shared engine-core @0x8012B744 (src/shared) */
INCLUDE_ASM("asm/ov_SC02_015/nonmatchings/ov_SC02_015_jr_8012ACE0", func_8012B77C);
extern s32 ratan2(s32 a0, s32 a1);
extern s32 func_80047948(s32 a0); /* rsin-like: angle (0..0xFFF) -> 1.12 fixed */
extern s32 func_8004787C(s32 a0); /* rcos-like: angle (0..0xFFF) -> 1.12 fixed */
/* The 4-byte destination is a PACKED PAIR of angles held entirely in ONE saved register
* ($s4) across all three calls — that is what produces the target's
* andi $s4,$s4,0xFFFF (read of the still-uninitialized local, hoisted into the prologue)
* ... or $s4,$s4,ang<<16 -> t.hi = yaw
* ... and $s4,$s4,0xFFFF0000 / or $s4,$s4,ang&0xFFFF -> t.lo = pitch
* A `struct { s16 lo, hi; }` has align 2 -> BLKmode-ish handling: gcc spills it to the stack
* and stores it with lwl/lwr + swl/swr (54 ins, 53 mismatched). Two 16-bit BITFIELDS in a
* u32 container give the SImode, align-4 struct gcc keeps in a register. */
typedef struct {
u32 lo : 16;
u32 hi : 16;
} Ang2_8012B77C_8012B77C;
/* a0 = destination packed-angle word, a1 = "from" entity, a2 = "to" entity.
* Both entities carry 16.16 fixed-point x/y/z at +0/+4/+8; the s16 reads at +2/+6/+0xA are
* the integer halves. Returns the destination pointer — the return value is REAL: without it
* gcc stores with `sw $s4,0($s3)` (57 ins) instead of the target's
* addu $v0,$s3,$zero ; sw $s4,0($v0) (the return-value copy that the store's base coalesces onto).
* The flattened `dz` reuse at the end is also load-bearing: making the (dz*sin + dx*cos)>>12
* temp its OWN variable gives it $a1 for the whole chain; reusing `dz` extends that allocno so
* it lands in $s5 exactly as the target does (`sra $s5,$v0,12` / `negu $a1,$s5`), and it also
* demotes dz's priority so the saved-reg order comes out $s3=out, $s4=t, $s5=dz. */
s32 func_8012B77C(s32 out, s32 from, s32 to) {
Ang2_8012B77C_8012B77C t;
s32 dx, dy, dz;
s32 ang;
s32 r1, r2;
dz = *(s16 *)(to + 0xA) - *(s16 *)(from + 0xA);
dx = *(s16 *)(to + 0x2) - *(s16 *)(from + 0x2);
dy = *(s16 *)(to + 0x6) - *(s16 *)(from + 0x6);
ang = (ratan2(-dz, dx) - 0x400) & 0xFFF;
t.hi = ang;
r1 = func_80047948(ang);
r2 = func_8004787C(ang);
dz = (dz * r1 + dx * r2) >> 12;
t.lo = ratan2(dy, -dz);
*(Ang2_8012B77C_8012B77C *)out = t;
return out;
}
DEFINE_func_8012B864() /* dedup: shared engine-core @0x8012B864 (src/shared) */
+74 -1
View File
@@ -3170,7 +3170,80 @@ void func_80175DA8(param_1)
}
INCLUDE_ASM("asm/ov_SC02_015/nonmatchings/ov_SC02_015_jr_801734BC", func_80176144);
/* func_80176144 — RECONCILED variant of .run/uc/func_80176144.c
*
* GATE BLOCKER (whole-binary build, NOT match_one):
* src/ov_SC01_077/ov_SC01_077_jr_801734BC.c:3476: conflicting types for `D_800AF634'
* || previous declaration at :3296
*
* ROOT CAUSE — a HOISTED file-scope typedef, not a bad signature:
* That TU hoists, at FILE scope, for func_80175DA8:
* :3295 typedef struct { s32 g0; s32 pad[2]; } S_AF634_80176144;
* :3296 extern S_AF634_80176144 D_800AF634[];
* :3297 extern S_AF634_80176144 D_800AF638[];
* The stored draft re-declares the SAME struct shape as a BLOCK-scope typedef
* (rule D — it must travel to the 137 sibling overlays, which have no such
* preamble). A block-scope `typedef struct {...} S_AF634_80176144;` is a DISTINCT type
* from the file-scope one (C has no structural typing), so the block-scope
* `extern S_AF634_80176144 D_800AF634[];` re-declares the symbol incompatibly with the
* in-scope file-scope decl -> hard error.
* Note the earlier block-scope copies in the same TU (:3080 func_80175820,
* :3123 func_801759D8) do NOT error: they precede :3296, so no file-scope decl
* of D_800AF634 is in scope there. Anything AFTER :3296 collides. Our
* definition lands at :3476. That is why only this one fired.
*
* FIX — §37/§124 ASM-LABEL ALIAS applied to the DATA symbols (cookbook §2516:
* "asm-label alias for sibling-decl signedness/proto conflicts ... beats
* reconcile's *(u16*)&D_x cast whose address-of PERTURBS regalloc"):
* the two objects are reached through PRIVATE C identifiers aAF634 / aAF638
* carrying __asm__("D_800AF634") / __asm__("D_800AF638"). The emitted
* %hi/%lo relocations are against the same symbols, so codegen is unchanged,
* while the C names can never collide with ANY sibling TU's declaration —
* whether hoisted, block-scope, or absent. No header edit; no src/ edit.
* Strictly better than deleting the local decls (which would bind this
* exemplar to the one TU that happens to hoist them).
*
* The s32 parameter + explicit (s16) narrowing is retained from the stored draft
* (canonical decl in engine_core.h:18985/:4587 is `void func_80176144(s32)`;
* the K&R short param would itself be a conflicting-types error). The (s16)
* narrowing IS the entry `sll $s0,$a0,16 / sra $s0,$s0,16` pair.
*
* Verified: python3 tools/match_one.py func_80176144 --c .run/uc2/func_80176144.c
* --asm-subdir ov_SC01_077/nonmatchings/ov_SC01_077_jr_801734BC -> MATCH (53 ins)
*/
void func_80176144(s32 a0)
{
typedef struct { s32 g0; s32 pad[2]; } S_AF634_80176144; /* size 0x0C */
/* §37 asm-label alias: private C names, canonical relocations. */
extern S_AF634_80176144 aAF634[] __asm__("D_800AF634");
extern S_AF634_80176144 aAF638[] __asm__("D_800AF638");
extern u8 D_8011F7A8;
extern s16 D_8011F7BC;
extern s16 D_8011F7BE;
extern s32 func_80178004(s32 a0, s32 a1, s32 a2);
u32 *slot;
u32 *p;
s16 param_1 = (s16)a0;
p = (u32 *)(aAF638[param_1].g0 + aAF634[param_1].g0 * 4);
slot = (u32 *)(param_1 * 4 + (s32)&D_8011F7A8);
slot[14] = (u32)p;
/* §5a zero-byte sched fence: without it sched1 hoists the two %hi/lhu global
argument loads above the `sw` of slot[14] (16 mismatches, 0 length drift). */
__asm__("");
p = (u32 *)func_80178004((s32)p,
(s16)((*(u16 *)&D_8011F7BC) - 0x17),
(s16)((*(u16 *)&D_8011F7BE) + 0x65));
slot[16] = (u32)p - 0x14;
p += 5;
aAF634[param_1].g0 += ((s32)p - (s32)slot[14]) >> 2;
}
// @class: regalloc-order
+21 -1
View File
@@ -387,7 +387,27 @@ void func_80128AF4(void) {
DEFINE_func_80128C14() /* dedup: shared engine-core @0x80128C14 (src/shared) */
INCLUDE_ASM("asm/ov_SC02_016/nonmatchings/ov_SC02_016", func_80128C98);
typedef struct {
s32 word0;
s32 word4;
} CdFileLoc_80128C98;
extern CdFileLoc_80128C98 cdFileLocTable[];
extern void func_8001ABBC(s32 a0, s32 a1, void *a2, s32 a3, s32 a4);
s32 func_80128C98(s32 arg0) {
extern s16 D_8018472C[];
s16 idx = D_8018472C[arg0];
if (idx >= 0) {
func_8001ABBC(0, 0, (u8 *)&cdFileLocTable[idx], D_801B1A6C, 0);
} else {
return 1;
}
}
INCLUDE_ASM("asm/ov_SC02_016/nonmatchings/ov_SC02_016", func_80128CFC);
+78 -1
View File
@@ -481,7 +481,84 @@ INCLUDE_ASM("asm/ov_SC02_016/nonmatchings/ov_SC02_016_after", func_80146A6C);
DEFINE_func_80146AB4() /* dedup: shared engine-core @0x80146AB4 (src/shared) */
INCLUDE_ASM("asm/ov_SC02_016/nonmatchings/ov_SC02_016_after", func_80146AFC);
extern s32 func_80146B9C(void * arg0);
/* func_80146AFC — ASCENDING twin of the byte-proven DEFINE_func_80146B9C()
* in src/shared/engine_core.h (cookbook §71: find the already-matched sibling first).
* Same 0x58-stride slot table (base D_8011D030), same 7-store copy body in the same
* order, same $a2/$a1 giv pair. 80146B9C walks DOWN; this one walks UP, so the guard
* is `p < end`, end = p + 0xA50 (30 slots x 0x58).
*
* DECAY ROOT CAUSE (this redraft): the stored backlog draft had been rewritten to
* `void func_80146AFC(...)`, which drops BOTH `return 0` paths' `addu $v0,$zero,$zero`
* and the hit path's `j .L80146B94` => LENGTH-DRIFT -2 (38 vs 40) plus $v0/$v1 regalloc
* drift on the final lw/sw pair. Restoring the s32 return type (the fleet spelling the
* banked sibling func_80146B9C already uses) restores MATCH at 40/40.
*
* RECONCILE (2026-08-01) — the whole-binary gate failed with
* ov_SC01_077_after.c:592: conflicting types for `D_8011D030' (previous decl :564)
* TWO file-scope collisions were present; both are fixed HERE, with NO edit to
* src/shared/engine_core.h and NO change to the generated code (re-verified MATCH
* after each step):
*
* 1. D_8011D030 (the reported one). DEFINE_func_801469C8() emits
* `extern s32 D_8011D030;` at FILE scope (engine_core.h:10811, above the
* `s32 func_801469C8(...) {` line), and this TU expands that macro at :564 —
extern s32 D_8011D030;
* i.e. before the splice point :570. The draft's `extern u16` therefore
* redeclared it incompatibly at :592. Conformed to the TU's `extern s32`.
* Codegen-neutral: the sole use is `(u8 *)&D_8011D030`, an address-of, so the
* declared object type never reaches a load/store width (cookbook §20).
*
* 2. func_80146AFC ITSELF (latent, would have surfaced next). DEFINE_func_8014C010()
* (:13510) and DEFINE_func_8014AD30() (:13524) each emit a file-scope
* `extern void func_80146AFC(void *a0);`, and this TU expands them at :1386 and
* :1541 — after the splice — so an `s32 func_80146AFC` definition collides on the
* RETURN axis. Fixed with the §37/§124 ASM-LABEL ALIAS: the C identifier is
* aF80146AFC, the emitted label is func_80146AFC, so the canonical void decl and
* this s32 definition never share a namespace. Callers discard the result, so the
* void-typed call sites stay codegen-identical.
*
* Both were reproduced and then cleared against the real cpp+cc1-2.7.2 pair using a
* synthetic copy of this TU's declaration environment (.run/uc2/_recon_probe_80146AFC.c):
* the pre-reconcile spelling emits exactly the gate's error pair; the spelling below
* compiles clean.
*
* ORACLE: tools/match_one.py func_80146AFC --c .run/uc2/func_80146AFC.c
* --asm-subdir asm/ov_SC01_077/nonmatchings/ov_SC01_077_after -> MATCH (40 ins)
*/
s32 aF80146AFC(void *arg0) __asm__("func_80146AFC");
s32 aF80146AFC(void *arg0)
{
register u8 *p __asm__("$6");
register u8 *q __asm__("$5");
u8 *end;
p = (u8 *)&D_8011D030;
end = p + 0xA50;
if ((u32)p < (u32)end) {
q = p + 0x30;
do {
if (*(u16 *)p == 0) {
*(s32 *)(q + 0x4) = *(s32 *)((u8 *)arg0 + 0x8);
*(s16 *)p = *(u16 *)((u8 *)arg0 + 0x0);
*(s16 *)(q - 0x2A) = *(u16 *)((u8 *)arg0 + 0x2);
*(s16 *)(q - 0x26) = *(u16 *)((u8 *)arg0 + 0x4);
*(s16 *)(q - 0x22) = *(u16 *)((u8 *)arg0 + 0x6);
*(s32 *)(q - 0x4) = *(s32 *)((u8 *)arg0 + 0xC);
*(s32 *)(q + 0x0) = *(s32 *)((u8 *)arg0 + 0x10);
return (s32)p;
}
p += 0x58;
q += 0x58;
} while ((u32)p < (u32)end);
}
return 0;
}
DEFINE_func_80146B9C() /* dedup: shared engine-core @0x80146B9C (src/shared) */
+49 -1
View File
@@ -327,7 +327,55 @@ DEFINE_func_8012B70C() /* dedup: shared engine-core @0x8012B70C (src/shared) */
DEFINE_func_8012B744() /* dedup: shared engine-core @0x8012B744 (src/shared) */
INCLUDE_ASM("asm/ov_SC02_016/nonmatchings/ov_SC02_016_jr_8012ACE0", func_8012B77C);
extern s32 ratan2(s32 a0, s32 a1);
extern s32 func_80047948(s32 a0); /* rsin-like: angle (0..0xFFF) -> 1.12 fixed */
extern s32 func_8004787C(s32 a0); /* rcos-like: angle (0..0xFFF) -> 1.12 fixed */
/* The 4-byte destination is a PACKED PAIR of angles held entirely in ONE saved register
* ($s4) across all three calls — that is what produces the target's
* andi $s4,$s4,0xFFFF (read of the still-uninitialized local, hoisted into the prologue)
* ... or $s4,$s4,ang<<16 -> t.hi = yaw
* ... and $s4,$s4,0xFFFF0000 / or $s4,$s4,ang&0xFFFF -> t.lo = pitch
* A `struct { s16 lo, hi; }` has align 2 -> BLKmode-ish handling: gcc spills it to the stack
* and stores it with lwl/lwr + swl/swr (54 ins, 53 mismatched). Two 16-bit BITFIELDS in a
* u32 container give the SImode, align-4 struct gcc keeps in a register. */
typedef struct {
u32 lo : 16;
u32 hi : 16;
} Ang2_8012B77C_8012B77C;
/* a0 = destination packed-angle word, a1 = "from" entity, a2 = "to" entity.
* Both entities carry 16.16 fixed-point x/y/z at +0/+4/+8; the s16 reads at +2/+6/+0xA are
* the integer halves. Returns the destination pointer — the return value is REAL: without it
* gcc stores with `sw $s4,0($s3)` (57 ins) instead of the target's
* addu $v0,$s3,$zero ; sw $s4,0($v0) (the return-value copy that the store's base coalesces onto).
* The flattened `dz` reuse at the end is also load-bearing: making the (dz*sin + dx*cos)>>12
* temp its OWN variable gives it $a1 for the whole chain; reusing `dz` extends that allocno so
* it lands in $s5 exactly as the target does (`sra $s5,$v0,12` / `negu $a1,$s5`), and it also
* demotes dz's priority so the saved-reg order comes out $s3=out, $s4=t, $s5=dz. */
s32 func_8012B77C(s32 out, s32 from, s32 to) {
Ang2_8012B77C_8012B77C t;
s32 dx, dy, dz;
s32 ang;
s32 r1, r2;
dz = *(s16 *)(to + 0xA) - *(s16 *)(from + 0xA);
dx = *(s16 *)(to + 0x2) - *(s16 *)(from + 0x2);
dy = *(s16 *)(to + 0x6) - *(s16 *)(from + 0x6);
ang = (ratan2(-dz, dx) - 0x400) & 0xFFF;
t.hi = ang;
r1 = func_80047948(ang);
r2 = func_8004787C(ang);
dz = (dz * r1 + dx * r2) >> 12;
t.lo = ratan2(dy, -dz);
*(Ang2_8012B77C_8012B77C *)out = t;
return out;
}
DEFINE_func_8012B864() /* dedup: shared engine-core @0x8012B864 (src/shared) */
+74 -1
View File
@@ -3172,7 +3172,80 @@ void func_80175DA8(param_1)
}
INCLUDE_ASM("asm/ov_SC02_016/nonmatchings/ov_SC02_016_jr_801734BC", func_80176144);
/* func_80176144 — RECONCILED variant of .run/uc/func_80176144.c
*
* GATE BLOCKER (whole-binary build, NOT match_one):
* src/ov_SC01_077/ov_SC01_077_jr_801734BC.c:3476: conflicting types for `D_800AF634'
* || previous declaration at :3296
*
* ROOT CAUSE — a HOISTED file-scope typedef, not a bad signature:
* That TU hoists, at FILE scope, for func_80175DA8:
* :3295 typedef struct { s32 g0; s32 pad[2]; } S_AF634_80176144;
* :3296 extern S_AF634_80176144 D_800AF634[];
* :3297 extern S_AF634_80176144 D_800AF638[];
* The stored draft re-declares the SAME struct shape as a BLOCK-scope typedef
* (rule D — it must travel to the 137 sibling overlays, which have no such
* preamble). A block-scope `typedef struct {...} S_AF634_80176144;` is a DISTINCT type
* from the file-scope one (C has no structural typing), so the block-scope
* `extern S_AF634_80176144 D_800AF634[];` re-declares the symbol incompatibly with the
* in-scope file-scope decl -> hard error.
* Note the earlier block-scope copies in the same TU (:3080 func_80175820,
* :3123 func_801759D8) do NOT error: they precede :3296, so no file-scope decl
* of D_800AF634 is in scope there. Anything AFTER :3296 collides. Our
* definition lands at :3476. That is why only this one fired.
*
* FIX — §37/§124 ASM-LABEL ALIAS applied to the DATA symbols (cookbook §2516:
* "asm-label alias for sibling-decl signedness/proto conflicts ... beats
* reconcile's *(u16*)&D_x cast whose address-of PERTURBS regalloc"):
* the two objects are reached through PRIVATE C identifiers aAF634 / aAF638
* carrying __asm__("D_800AF634") / __asm__("D_800AF638"). The emitted
* %hi/%lo relocations are against the same symbols, so codegen is unchanged,
* while the C names can never collide with ANY sibling TU's declaration —
* whether hoisted, block-scope, or absent. No header edit; no src/ edit.
* Strictly better than deleting the local decls (which would bind this
* exemplar to the one TU that happens to hoist them).
*
* The s32 parameter + explicit (s16) narrowing is retained from the stored draft
* (canonical decl in engine_core.h:18985/:4587 is `void func_80176144(s32)`;
* the K&R short param would itself be a conflicting-types error). The (s16)
* narrowing IS the entry `sll $s0,$a0,16 / sra $s0,$s0,16` pair.
*
* Verified: python3 tools/match_one.py func_80176144 --c .run/uc2/func_80176144.c
* --asm-subdir ov_SC01_077/nonmatchings/ov_SC01_077_jr_801734BC -> MATCH (53 ins)
*/
void func_80176144(s32 a0)
{
typedef struct { s32 g0; s32 pad[2]; } S_AF634_80176144; /* size 0x0C */
/* §37 asm-label alias: private C names, canonical relocations. */
extern S_AF634_80176144 aAF634[] __asm__("D_800AF634");
extern S_AF634_80176144 aAF638[] __asm__("D_800AF638");
extern u8 D_8011F7A8;
extern s16 D_8011F7BC;
extern s16 D_8011F7BE;
extern s32 func_80178004(s32 a0, s32 a1, s32 a2);
u32 *slot;
u32 *p;
s16 param_1 = (s16)a0;
p = (u32 *)(aAF638[param_1].g0 + aAF634[param_1].g0 * 4);
slot = (u32 *)(param_1 * 4 + (s32)&D_8011F7A8);
slot[14] = (u32)p;
/* §5a zero-byte sched fence: without it sched1 hoists the two %hi/lhu global
argument loads above the `sw` of slot[14] (16 mismatches, 0 length drift). */
__asm__("");
p = (u32 *)func_80178004((s32)p,
(s16)((*(u16 *)&D_8011F7BC) - 0x17),
(s16)((*(u16 *)&D_8011F7BE) + 0x65));
slot[16] = (u32)p - 0x14;
p += 5;
aAF634[param_1].g0 += ((s32)p - (s32)slot[14]) >> 2;
}
// @class: regalloc-order
+107 -2
View File
@@ -3518,7 +3518,47 @@ void func_8017D174(int param_1)
}
INCLUDE_ASM("asm/ov_SC02_016/nonmatchings/ov_SC02_016_jr_8017AE2C", func_8017D1D0);
/* Entity record touched by func_8017D1D0 (offsets read straight off the asm):
* 0x02 u16 frame/state counter (lhu / sh)
* 0x1C s32 tick counter (lw / sw), signed compare against 0x20
* 0x2A u16 y-ish delta, decremented by 0x10 (lhu / sh)
* 0x2C u16 sound id passed to func_80147324 (lhu)
* 0x30 s32 suppress flag
*/
typedef struct Ent_8017BFE0_8017D1D0 {
u8 pad00[2]; /* 0x00 */
u16 f02; /* 0x02 */
u8 pad04[0x18];/* 0x04 */
s32 f1c; /* 0x1C */
u8 pad20[0xA]; /* 0x20 */
u16 f2a; /* 0x2A */
u16 f2c; /* 0x2C */
u8 pad2e[2]; /* 0x2E */
s32 f30; /* 0x30 */
} Ent_8017BFE0_8017D1D0;
extern void func_80147324(s32 arg0);
extern void func_8017D408(int);
void func_8017D1D0(Ent_8017BFE0_8017D1D0 *param_1)
{
s32 t;
t = param_1->f1c;
param_1->f1c = t + 1;
if (t < 0x20) {
param_1->f2a = param_1->f2a - 0x10;
} else {
if (param_1->f30 == 0) {
func_80147324(param_1->f2c);
}
param_1->f1c = 0;
param_1->f02 = param_1->f02 + 1;
}
((void (*)(Ent_8017BFE0_8017D1D0 *))func_8017D408)(param_1);
}
INCLUDE_ASM("asm/ov_SC02_016/nonmatchings/ov_SC02_016_jr_8017AE2C", func_8017D254);
@@ -3683,7 +3723,72 @@ void func_8017D9B4(void *a0) {
}
INCLUDE_ASM("asm/ov_SC02_016/nonmatchings/ov_SC02_016_jr_8017AE2C", func_8017D9F0);
/* func_8017D9F0 — spawn/scatter tick for the +0x34 sub-object (state word @0x2).
* MATCH (45 ins), match_one + rtu_match. Four levers, in the order they were found:
*
* 1. §71 sibling-first — same entity shape as func_8017C610 / func_8017C69C in this
* TU: sub-object pointer @0x34 read BEFORE the call (it lives in $s1 across the
* jal), state word @0x2 bumped last. §3-T4: `beqz $v1,else` => `if (p->f2C) {..}`.
* ONE rand() feeds three fields; the raw low 6 bits use a bare `andi` (no extend)
* while the >>12 / >>6 uses share one `sll $x,16` — that shared sign-extend is
* what forces `r` to be a `short` local rather than an int.
*
* 2. §5a CROSS-JUMP — both arms end in `sh ?,0xA($s0)`; gcc tail-merged them (23 off).
* They only stay separate because the loaded halfword lands in a DIFFERENT hard
* reg per arm, which needs (a) the load to be its own statement at the TOP of each
* arm and (b) a SEPARATE temp per arm (t / t2) — one shared temp is one pseudo,
* gets one register in both arms, and re-merges. 23 -> 10 -> 6.
*
* 3. +0x16 is SIGNED: the target materialises -0x20 as `addiu $v0,$zero,-0x20`, not
* `ori 0xffe0`, so that store must go through an s16.
*
* 4. §49 BIRTHING BOOST (the last 6 -> 2 -> 0). Residual was two ALU insns swapped
* with identical registers; source statement order does NOT flip it, because
* sched1's `adjust_priority`/`birthing_insn_p` hands every SET(REG,..) whose dest
* has REG_N_SETS==1 a 0x7f000001 priority, so it sinks to just before its consumer
* and fixes the .greg LUID order that sched2's tie-break then reads.
* THE DIAL: give the offending insn's dest a SECOND set so it loses the boost —
* here one `u16 d` reused by both tail statements. It must be a THIRD temp, not
* `c` itself: writing `c = c + 1;` also un-boosts c's LOAD, which then starves to
* the front of the block and swaps the two `lhu`s instead. Boost the loads, starve
* the arithmetic. */
extern int rand(void);
void func_8017D9F0(void *a0)
{
s32 p;
s32 obj;
short r;
u16 t;
u16 t2;
u16 e;
u16 c;
u16 d;
p = (s32)a0;
obj = *(s32 *)(p + 0x34);
r = rand();
*(u16 *)(p + 0x06) = *(u16 *)(obj + 0x06) + ((r & 0x3F) - 0x20);
if (*(s32 *)(p + 0x2C) != 0) {
t = *(u16 *)(obj + 0x0A);
*(s16 *)(p + 0x16) = 0x20;
*(u16 *)(p + 0x0A) = t - 0x140;
} else {
t2 = *(u16 *)(obj + 0x0A);
*(s16 *)(p + 0x16) = -0x20;
*(u16 *)(p + 0x0A) = t2;
}
e = *(u16 *)(obj + 0x0E);
c = *(u16 *)(p + 0x02);
*(s32 *)(p + 0x30) = (r >> 12) & 3;
d = ((r >> 6) & 0x3F) - 0x20;
*(u16 *)(p + 0x0E) = e + d;
d = c + 1;
*(u16 *)(p + 0x02) = d;
}
extern void func_800D22E4(s32 a0);
extern void func_80146C3C(void);
+21 -1
View File
@@ -387,7 +387,27 @@ void func_80128AF4(void) {
DEFINE_func_80128C14() /* dedup: shared engine-core @0x80128C14 (src/shared) */
INCLUDE_ASM("asm/ov_SC02_017/nonmatchings/ov_SC02_017", func_80128C98);
typedef struct {
s32 word0;
s32 word4;
} CdFileLoc_80128C98;
extern CdFileLoc_80128C98 cdFileLocTable[];
extern void func_8001ABBC(s32 a0, s32 a1, void *a2, s32 a3, s32 a4);
s32 func_80128C98(s32 arg0) {
extern s16 D_8018A784[];
s16 idx = D_8018A784[arg0];
if (idx >= 0) {
func_8001ABBC(0, 0, (u8 *)&cdFileLocTable[idx], D_801ED28C, 0);
} else {
return 1;
}
}
INCLUDE_ASM("asm/ov_SC02_017/nonmatchings/ov_SC02_017", func_80128CFC);
+78 -1
View File
@@ -481,7 +481,84 @@ INCLUDE_ASM("asm/ov_SC02_017/nonmatchings/ov_SC02_017_after", func_80146A6C);
DEFINE_func_80146AB4() /* dedup: shared engine-core @0x80146AB4 (src/shared) */
INCLUDE_ASM("asm/ov_SC02_017/nonmatchings/ov_SC02_017_after", func_80146AFC);
extern s32 func_80146B9C(void * arg0);
/* func_80146AFC — ASCENDING twin of the byte-proven DEFINE_func_80146B9C()
* in src/shared/engine_core.h (cookbook §71: find the already-matched sibling first).
* Same 0x58-stride slot table (base D_8011D030), same 7-store copy body in the same
* order, same $a2/$a1 giv pair. 80146B9C walks DOWN; this one walks UP, so the guard
* is `p < end`, end = p + 0xA50 (30 slots x 0x58).
*
* DECAY ROOT CAUSE (this redraft): the stored backlog draft had been rewritten to
* `void func_80146AFC(...)`, which drops BOTH `return 0` paths' `addu $v0,$zero,$zero`
* and the hit path's `j .L80146B94` => LENGTH-DRIFT -2 (38 vs 40) plus $v0/$v1 regalloc
* drift on the final lw/sw pair. Restoring the s32 return type (the fleet spelling the
* banked sibling func_80146B9C already uses) restores MATCH at 40/40.
*
* RECONCILE (2026-08-01) — the whole-binary gate failed with
* ov_SC01_077_after.c:592: conflicting types for `D_8011D030' (previous decl :564)
* TWO file-scope collisions were present; both are fixed HERE, with NO edit to
* src/shared/engine_core.h and NO change to the generated code (re-verified MATCH
* after each step):
*
* 1. D_8011D030 (the reported one). DEFINE_func_801469C8() emits
* `extern s32 D_8011D030;` at FILE scope (engine_core.h:10811, above the
* `s32 func_801469C8(...) {` line), and this TU expands that macro at :564 —
extern s32 D_8011D030;
* i.e. before the splice point :570. The draft's `extern u16` therefore
* redeclared it incompatibly at :592. Conformed to the TU's `extern s32`.
* Codegen-neutral: the sole use is `(u8 *)&D_8011D030`, an address-of, so the
* declared object type never reaches a load/store width (cookbook §20).
*
* 2. func_80146AFC ITSELF (latent, would have surfaced next). DEFINE_func_8014C010()
* (:13510) and DEFINE_func_8014AD30() (:13524) each emit a file-scope
* `extern void func_80146AFC(void *a0);`, and this TU expands them at :1386 and
* :1541 — after the splice — so an `s32 func_80146AFC` definition collides on the
* RETURN axis. Fixed with the §37/§124 ASM-LABEL ALIAS: the C identifier is
* aF80146AFC, the emitted label is func_80146AFC, so the canonical void decl and
* this s32 definition never share a namespace. Callers discard the result, so the
* void-typed call sites stay codegen-identical.
*
* Both were reproduced and then cleared against the real cpp+cc1-2.7.2 pair using a
* synthetic copy of this TU's declaration environment (.run/uc2/_recon_probe_80146AFC.c):
* the pre-reconcile spelling emits exactly the gate's error pair; the spelling below
* compiles clean.
*
* ORACLE: tools/match_one.py func_80146AFC --c .run/uc2/func_80146AFC.c
* --asm-subdir asm/ov_SC01_077/nonmatchings/ov_SC01_077_after -> MATCH (40 ins)
*/
s32 aF80146AFC(void *arg0) __asm__("func_80146AFC");
s32 aF80146AFC(void *arg0)
{
register u8 *p __asm__("$6");
register u8 *q __asm__("$5");
u8 *end;
p = (u8 *)&D_8011D030;
end = p + 0xA50;
if ((u32)p < (u32)end) {
q = p + 0x30;
do {
if (*(u16 *)p == 0) {
*(s32 *)(q + 0x4) = *(s32 *)((u8 *)arg0 + 0x8);
*(s16 *)p = *(u16 *)((u8 *)arg0 + 0x0);
*(s16 *)(q - 0x2A) = *(u16 *)((u8 *)arg0 + 0x2);
*(s16 *)(q - 0x26) = *(u16 *)((u8 *)arg0 + 0x4);
*(s16 *)(q - 0x22) = *(u16 *)((u8 *)arg0 + 0x6);
*(s32 *)(q - 0x4) = *(s32 *)((u8 *)arg0 + 0xC);
*(s32 *)(q + 0x0) = *(s32 *)((u8 *)arg0 + 0x10);
return (s32)p;
}
p += 0x58;
q += 0x58;
} while ((u32)p < (u32)end);
}
return 0;
}
DEFINE_func_80146B9C() /* dedup: shared engine-core @0x80146B9C (src/shared) */
+49 -1
View File
@@ -327,7 +327,55 @@ DEFINE_func_8012B70C() /* dedup: shared engine-core @0x8012B70C (src/shared) */
DEFINE_func_8012B744() /* dedup: shared engine-core @0x8012B744 (src/shared) */
INCLUDE_ASM("asm/ov_SC02_017/nonmatchings/ov_SC02_017_jr_8012ACE0", func_8012B77C);
extern s32 ratan2(s32 a0, s32 a1);
extern s32 func_80047948(s32 a0); /* rsin-like: angle (0..0xFFF) -> 1.12 fixed */
extern s32 func_8004787C(s32 a0); /* rcos-like: angle (0..0xFFF) -> 1.12 fixed */
/* The 4-byte destination is a PACKED PAIR of angles held entirely in ONE saved register
* ($s4) across all three calls — that is what produces the target's
* andi $s4,$s4,0xFFFF (read of the still-uninitialized local, hoisted into the prologue)
* ... or $s4,$s4,ang<<16 -> t.hi = yaw
* ... and $s4,$s4,0xFFFF0000 / or $s4,$s4,ang&0xFFFF -> t.lo = pitch
* A `struct { s16 lo, hi; }` has align 2 -> BLKmode-ish handling: gcc spills it to the stack
* and stores it with lwl/lwr + swl/swr (54 ins, 53 mismatched). Two 16-bit BITFIELDS in a
* u32 container give the SImode, align-4 struct gcc keeps in a register. */
typedef struct {
u32 lo : 16;
u32 hi : 16;
} Ang2_8012B77C_8012B77C;
/* a0 = destination packed-angle word, a1 = "from" entity, a2 = "to" entity.
* Both entities carry 16.16 fixed-point x/y/z at +0/+4/+8; the s16 reads at +2/+6/+0xA are
* the integer halves. Returns the destination pointer — the return value is REAL: without it
* gcc stores with `sw $s4,0($s3)` (57 ins) instead of the target's
* addu $v0,$s3,$zero ; sw $s4,0($v0) (the return-value copy that the store's base coalesces onto).
* The flattened `dz` reuse at the end is also load-bearing: making the (dz*sin + dx*cos)>>12
* temp its OWN variable gives it $a1 for the whole chain; reusing `dz` extends that allocno so
* it lands in $s5 exactly as the target does (`sra $s5,$v0,12` / `negu $a1,$s5`), and it also
* demotes dz's priority so the saved-reg order comes out $s3=out, $s4=t, $s5=dz. */
s32 func_8012B77C(s32 out, s32 from, s32 to) {
Ang2_8012B77C_8012B77C t;
s32 dx, dy, dz;
s32 ang;
s32 r1, r2;
dz = *(s16 *)(to + 0xA) - *(s16 *)(from + 0xA);
dx = *(s16 *)(to + 0x2) - *(s16 *)(from + 0x2);
dy = *(s16 *)(to + 0x6) - *(s16 *)(from + 0x6);
ang = (ratan2(-dz, dx) - 0x400) & 0xFFF;
t.hi = ang;
r1 = func_80047948(ang);
r2 = func_8004787C(ang);
dz = (dz * r1 + dx * r2) >> 12;
t.lo = ratan2(dy, -dz);
*(Ang2_8012B77C_8012B77C *)out = t;
return out;
}
DEFINE_func_8012B864() /* dedup: shared engine-core @0x8012B864 (src/shared) */
+74 -1
View File
@@ -3172,7 +3172,80 @@ void func_80175DA8(param_1)
}
INCLUDE_ASM("asm/ov_SC02_017/nonmatchings/ov_SC02_017_jr_801734BC", func_80176144);
/* func_80176144 — RECONCILED variant of .run/uc/func_80176144.c
*
* GATE BLOCKER (whole-binary build, NOT match_one):
* src/ov_SC01_077/ov_SC01_077_jr_801734BC.c:3476: conflicting types for `D_800AF634'
* || previous declaration at :3296
*
* ROOT CAUSE — a HOISTED file-scope typedef, not a bad signature:
* That TU hoists, at FILE scope, for func_80175DA8:
* :3295 typedef struct { s32 g0; s32 pad[2]; } S_AF634_80176144;
* :3296 extern S_AF634_80176144 D_800AF634[];
* :3297 extern S_AF634_80176144 D_800AF638[];
* The stored draft re-declares the SAME struct shape as a BLOCK-scope typedef
* (rule D — it must travel to the 137 sibling overlays, which have no such
* preamble). A block-scope `typedef struct {...} S_AF634_80176144;` is a DISTINCT type
* from the file-scope one (C has no structural typing), so the block-scope
* `extern S_AF634_80176144 D_800AF634[];` re-declares the symbol incompatibly with the
* in-scope file-scope decl -> hard error.
* Note the earlier block-scope copies in the same TU (:3080 func_80175820,
* :3123 func_801759D8) do NOT error: they precede :3296, so no file-scope decl
* of D_800AF634 is in scope there. Anything AFTER :3296 collides. Our
* definition lands at :3476. That is why only this one fired.
*
* FIX — §37/§124 ASM-LABEL ALIAS applied to the DATA symbols (cookbook §2516:
* "asm-label alias for sibling-decl signedness/proto conflicts ... beats
* reconcile's *(u16*)&D_x cast whose address-of PERTURBS regalloc"):
* the two objects are reached through PRIVATE C identifiers aAF634 / aAF638
* carrying __asm__("D_800AF634") / __asm__("D_800AF638"). The emitted
* %hi/%lo relocations are against the same symbols, so codegen is unchanged,
* while the C names can never collide with ANY sibling TU's declaration —
* whether hoisted, block-scope, or absent. No header edit; no src/ edit.
* Strictly better than deleting the local decls (which would bind this
* exemplar to the one TU that happens to hoist them).
*
* The s32 parameter + explicit (s16) narrowing is retained from the stored draft
* (canonical decl in engine_core.h:18985/:4587 is `void func_80176144(s32)`;
* the K&R short param would itself be a conflicting-types error). The (s16)
* narrowing IS the entry `sll $s0,$a0,16 / sra $s0,$s0,16` pair.
*
* Verified: python3 tools/match_one.py func_80176144 --c .run/uc2/func_80176144.c
* --asm-subdir ov_SC01_077/nonmatchings/ov_SC01_077_jr_801734BC -> MATCH (53 ins)
*/
void func_80176144(s32 a0)
{
typedef struct { s32 g0; s32 pad[2]; } S_AF634_80176144; /* size 0x0C */
/* §37 asm-label alias: private C names, canonical relocations. */
extern S_AF634_80176144 aAF634[] __asm__("D_800AF634");
extern S_AF634_80176144 aAF638[] __asm__("D_800AF638");
extern u8 D_8011F7A8;
extern s16 D_8011F7BC;
extern s16 D_8011F7BE;
extern s32 func_80178004(s32 a0, s32 a1, s32 a2);
u32 *slot;
u32 *p;
s16 param_1 = (s16)a0;
p = (u32 *)(aAF638[param_1].g0 + aAF634[param_1].g0 * 4);
slot = (u32 *)(param_1 * 4 + (s32)&D_8011F7A8);
slot[14] = (u32)p;
/* §5a zero-byte sched fence: without it sched1 hoists the two %hi/lhu global
argument loads above the `sw` of slot[14] (16 mismatches, 0 length drift). */
__asm__("");
p = (u32 *)func_80178004((s32)p,
(s16)((*(u16 *)&D_8011F7BC) - 0x17),
(s16)((*(u16 *)&D_8011F7BE) + 0x65));
slot[16] = (u32)p - 0x14;
p += 5;
aAF634[param_1].g0 += ((s32)p - (s32)slot[14]) >> 2;
}
// @class: regalloc-order
+107 -2
View File
@@ -3512,7 +3512,47 @@ void func_8017D174(int param_1)
}
INCLUDE_ASM("asm/ov_SC02_017/nonmatchings/ov_SC02_017_jr_8017AE2C", func_8017D1D0);
/* Entity record touched by func_8017D1D0 (offsets read straight off the asm):
* 0x02 u16 frame/state counter (lhu / sh)
* 0x1C s32 tick counter (lw / sw), signed compare against 0x20
* 0x2A u16 y-ish delta, decremented by 0x10 (lhu / sh)
* 0x2C u16 sound id passed to func_80147324 (lhu)
* 0x30 s32 suppress flag
*/
typedef struct Ent_8017BFE0_8017D1D0 {
u8 pad00[2]; /* 0x00 */
u16 f02; /* 0x02 */
u8 pad04[0x18];/* 0x04 */
s32 f1c; /* 0x1C */
u8 pad20[0xA]; /* 0x20 */
u16 f2a; /* 0x2A */
u16 f2c; /* 0x2C */
u8 pad2e[2]; /* 0x2E */
s32 f30; /* 0x30 */
} Ent_8017BFE0_8017D1D0;
extern void func_80147324(s32 arg0);
extern void func_8017D408(int);
void func_8017D1D0(Ent_8017BFE0_8017D1D0 *param_1)
{
s32 t;
t = param_1->f1c;
param_1->f1c = t + 1;
if (t < 0x20) {
param_1->f2a = param_1->f2a - 0x10;
} else {
if (param_1->f30 == 0) {
func_80147324(param_1->f2c);
}
param_1->f1c = 0;
param_1->f02 = param_1->f02 + 1;
}
((void (*)(Ent_8017BFE0_8017D1D0 *))func_8017D408)(param_1);
}
INCLUDE_ASM("asm/ov_SC02_017/nonmatchings/ov_SC02_017_jr_8017AE2C", func_8017D254);
@@ -3677,7 +3717,72 @@ void func_8017D9B4(void *a0) {
}
INCLUDE_ASM("asm/ov_SC02_017/nonmatchings/ov_SC02_017_jr_8017AE2C", func_8017D9F0);
/* func_8017D9F0 — spawn/scatter tick for the +0x34 sub-object (state word @0x2).
* MATCH (45 ins), match_one + rtu_match. Four levers, in the order they were found:
*
* 1. §71 sibling-first — same entity shape as func_8017C610 / func_8017C69C in this
* TU: sub-object pointer @0x34 read BEFORE the call (it lives in $s1 across the
* jal), state word @0x2 bumped last. §3-T4: `beqz $v1,else` => `if (p->f2C) {..}`.
* ONE rand() feeds three fields; the raw low 6 bits use a bare `andi` (no extend)
* while the >>12 / >>6 uses share one `sll $x,16` — that shared sign-extend is
* what forces `r` to be a `short` local rather than an int.
*
* 2. §5a CROSS-JUMP — both arms end in `sh ?,0xA($s0)`; gcc tail-merged them (23 off).
* They only stay separate because the loaded halfword lands in a DIFFERENT hard
* reg per arm, which needs (a) the load to be its own statement at the TOP of each
* arm and (b) a SEPARATE temp per arm (t / t2) — one shared temp is one pseudo,
* gets one register in both arms, and re-merges. 23 -> 10 -> 6.
*
* 3. +0x16 is SIGNED: the target materialises -0x20 as `addiu $v0,$zero,-0x20`, not
* `ori 0xffe0`, so that store must go through an s16.
*
* 4. §49 BIRTHING BOOST (the last 6 -> 2 -> 0). Residual was two ALU insns swapped
* with identical registers; source statement order does NOT flip it, because
* sched1's `adjust_priority`/`birthing_insn_p` hands every SET(REG,..) whose dest
* has REG_N_SETS==1 a 0x7f000001 priority, so it sinks to just before its consumer
* and fixes the .greg LUID order that sched2's tie-break then reads.
* THE DIAL: give the offending insn's dest a SECOND set so it loses the boost —
* here one `u16 d` reused by both tail statements. It must be a THIRD temp, not
* `c` itself: writing `c = c + 1;` also un-boosts c's LOAD, which then starves to
* the front of the block and swaps the two `lhu`s instead. Boost the loads, starve
* the arithmetic. */
extern int rand(void);
void func_8017D9F0(void *a0)
{
s32 p;
s32 obj;
short r;
u16 t;
u16 t2;
u16 e;
u16 c;
u16 d;
p = (s32)a0;
obj = *(s32 *)(p + 0x34);
r = rand();
*(u16 *)(p + 0x06) = *(u16 *)(obj + 0x06) + ((r & 0x3F) - 0x20);
if (*(s32 *)(p + 0x2C) != 0) {
t = *(u16 *)(obj + 0x0A);
*(s16 *)(p + 0x16) = 0x20;
*(u16 *)(p + 0x0A) = t - 0x140;
} else {
t2 = *(u16 *)(obj + 0x0A);
*(s16 *)(p + 0x16) = -0x20;
*(u16 *)(p + 0x0A) = t2;
}
e = *(u16 *)(obj + 0x0E);
c = *(u16 *)(p + 0x02);
*(s32 *)(p + 0x30) = (r >> 12) & 3;
d = ((r >> 6) & 0x3F) - 0x20;
*(u16 *)(p + 0x0E) = e + d;
d = c + 1;
*(u16 *)(p + 0x02) = d;
}
extern void func_800D22E4(s32 a0);
extern void func_80146C3C(void);
+21 -1
View File
@@ -387,7 +387,27 @@ void func_80128AF4(void) {
DEFINE_func_80128C14() /* dedup: shared engine-core @0x80128C14 (src/shared) */
INCLUDE_ASM("asm/ov_SC02_021/nonmatchings/ov_SC02_021", func_80128C98);
typedef struct {
s32 word0;
s32 word4;
} CdFileLoc_80128C98;
extern CdFileLoc_80128C98 cdFileLocTable[];
extern void func_8001ABBC(s32 a0, s32 a1, void *a2, s32 a3, s32 a4);
s32 func_80128C98(s32 arg0) {
extern s16 D_8017FD78[];
s16 idx = D_8017FD78[arg0];
if (idx >= 0) {
func_8001ABBC(0, 0, (u8 *)&cdFileLocTable[idx], D_80190808, 0);
} else {
return 1;
}
}
INCLUDE_ASM("asm/ov_SC02_021/nonmatchings/ov_SC02_021", func_80128CFC);
+78 -1
View File
@@ -481,7 +481,84 @@ INCLUDE_ASM("asm/ov_SC02_021/nonmatchings/ov_SC02_021_after", func_80146A6C);
DEFINE_func_80146AB4() /* dedup: shared engine-core @0x80146AB4 (src/shared) */
INCLUDE_ASM("asm/ov_SC02_021/nonmatchings/ov_SC02_021_after", func_80146AFC);
extern s32 func_80146B9C(void * arg0);
/* func_80146AFC — ASCENDING twin of the byte-proven DEFINE_func_80146B9C()
* in src/shared/engine_core.h (cookbook §71: find the already-matched sibling first).
* Same 0x58-stride slot table (base D_8011D030), same 7-store copy body in the same
* order, same $a2/$a1 giv pair. 80146B9C walks DOWN; this one walks UP, so the guard
* is `p < end`, end = p + 0xA50 (30 slots x 0x58).
*
* DECAY ROOT CAUSE (this redraft): the stored backlog draft had been rewritten to
* `void func_80146AFC(...)`, which drops BOTH `return 0` paths' `addu $v0,$zero,$zero`
* and the hit path's `j .L80146B94` => LENGTH-DRIFT -2 (38 vs 40) plus $v0/$v1 regalloc
* drift on the final lw/sw pair. Restoring the s32 return type (the fleet spelling the
* banked sibling func_80146B9C already uses) restores MATCH at 40/40.
*
* RECONCILE (2026-08-01) — the whole-binary gate failed with
* ov_SC01_077_after.c:592: conflicting types for `D_8011D030' (previous decl :564)
* TWO file-scope collisions were present; both are fixed HERE, with NO edit to
* src/shared/engine_core.h and NO change to the generated code (re-verified MATCH
* after each step):
*
* 1. D_8011D030 (the reported one). DEFINE_func_801469C8() emits
* `extern s32 D_8011D030;` at FILE scope (engine_core.h:10811, above the
* `s32 func_801469C8(...) {` line), and this TU expands that macro at :564 —
extern s32 D_8011D030;
* i.e. before the splice point :570. The draft's `extern u16` therefore
* redeclared it incompatibly at :592. Conformed to the TU's `extern s32`.
* Codegen-neutral: the sole use is `(u8 *)&D_8011D030`, an address-of, so the
* declared object type never reaches a load/store width (cookbook §20).
*
* 2. func_80146AFC ITSELF (latent, would have surfaced next). DEFINE_func_8014C010()
* (:13510) and DEFINE_func_8014AD30() (:13524) each emit a file-scope
* `extern void func_80146AFC(void *a0);`, and this TU expands them at :1386 and
* :1541 — after the splice — so an `s32 func_80146AFC` definition collides on the
* RETURN axis. Fixed with the §37/§124 ASM-LABEL ALIAS: the C identifier is
* aF80146AFC, the emitted label is func_80146AFC, so the canonical void decl and
* this s32 definition never share a namespace. Callers discard the result, so the
* void-typed call sites stay codegen-identical.
*
* Both were reproduced and then cleared against the real cpp+cc1-2.7.2 pair using a
* synthetic copy of this TU's declaration environment (.run/uc2/_recon_probe_80146AFC.c):
* the pre-reconcile spelling emits exactly the gate's error pair; the spelling below
* compiles clean.
*
* ORACLE: tools/match_one.py func_80146AFC --c .run/uc2/func_80146AFC.c
* --asm-subdir asm/ov_SC01_077/nonmatchings/ov_SC01_077_after -> MATCH (40 ins)
*/
s32 aF80146AFC(void *arg0) __asm__("func_80146AFC");
s32 aF80146AFC(void *arg0)
{
register u8 *p __asm__("$6");
register u8 *q __asm__("$5");
u8 *end;
p = (u8 *)&D_8011D030;
end = p + 0xA50;
if ((u32)p < (u32)end) {
q = p + 0x30;
do {
if (*(u16 *)p == 0) {
*(s32 *)(q + 0x4) = *(s32 *)((u8 *)arg0 + 0x8);
*(s16 *)p = *(u16 *)((u8 *)arg0 + 0x0);
*(s16 *)(q - 0x2A) = *(u16 *)((u8 *)arg0 + 0x2);
*(s16 *)(q - 0x26) = *(u16 *)((u8 *)arg0 + 0x4);
*(s16 *)(q - 0x22) = *(u16 *)((u8 *)arg0 + 0x6);
*(s32 *)(q - 0x4) = *(s32 *)((u8 *)arg0 + 0xC);
*(s32 *)(q + 0x0) = *(s32 *)((u8 *)arg0 + 0x10);
return (s32)p;
}
p += 0x58;
q += 0x58;
} while ((u32)p < (u32)end);
}
return 0;
}
DEFINE_func_80146B9C() /* dedup: shared engine-core @0x80146B9C (src/shared) */
+49 -1
View File
@@ -327,7 +327,55 @@ DEFINE_func_8012B70C() /* dedup: shared engine-core @0x8012B70C (src/shared) */
DEFINE_func_8012B744() /* dedup: shared engine-core @0x8012B744 (src/shared) */
INCLUDE_ASM("asm/ov_SC02_021/nonmatchings/ov_SC02_021_jr_8012ACE0", func_8012B77C);
extern s32 ratan2(s32 a0, s32 a1);
extern s32 func_80047948(s32 a0); /* rsin-like: angle (0..0xFFF) -> 1.12 fixed */
extern s32 func_8004787C(s32 a0); /* rcos-like: angle (0..0xFFF) -> 1.12 fixed */
/* The 4-byte destination is a PACKED PAIR of angles held entirely in ONE saved register
* ($s4) across all three calls — that is what produces the target's
* andi $s4,$s4,0xFFFF (read of the still-uninitialized local, hoisted into the prologue)
* ... or $s4,$s4,ang<<16 -> t.hi = yaw
* ... and $s4,$s4,0xFFFF0000 / or $s4,$s4,ang&0xFFFF -> t.lo = pitch
* A `struct { s16 lo, hi; }` has align 2 -> BLKmode-ish handling: gcc spills it to the stack
* and stores it with lwl/lwr + swl/swr (54 ins, 53 mismatched). Two 16-bit BITFIELDS in a
* u32 container give the SImode, align-4 struct gcc keeps in a register. */
typedef struct {
u32 lo : 16;
u32 hi : 16;
} Ang2_8012B77C_8012B77C;
/* a0 = destination packed-angle word, a1 = "from" entity, a2 = "to" entity.
* Both entities carry 16.16 fixed-point x/y/z at +0/+4/+8; the s16 reads at +2/+6/+0xA are
* the integer halves. Returns the destination pointer — the return value is REAL: without it
* gcc stores with `sw $s4,0($s3)` (57 ins) instead of the target's
* addu $v0,$s3,$zero ; sw $s4,0($v0) (the return-value copy that the store's base coalesces onto).
* The flattened `dz` reuse at the end is also load-bearing: making the (dz*sin + dx*cos)>>12
* temp its OWN variable gives it $a1 for the whole chain; reusing `dz` extends that allocno so
* it lands in $s5 exactly as the target does (`sra $s5,$v0,12` / `negu $a1,$s5`), and it also
* demotes dz's priority so the saved-reg order comes out $s3=out, $s4=t, $s5=dz. */
s32 func_8012B77C(s32 out, s32 from, s32 to) {
Ang2_8012B77C_8012B77C t;
s32 dx, dy, dz;
s32 ang;
s32 r1, r2;
dz = *(s16 *)(to + 0xA) - *(s16 *)(from + 0xA);
dx = *(s16 *)(to + 0x2) - *(s16 *)(from + 0x2);
dy = *(s16 *)(to + 0x6) - *(s16 *)(from + 0x6);
ang = (ratan2(-dz, dx) - 0x400) & 0xFFF;
t.hi = ang;
r1 = func_80047948(ang);
r2 = func_8004787C(ang);
dz = (dz * r1 + dx * r2) >> 12;
t.lo = ratan2(dy, -dz);
*(Ang2_8012B77C_8012B77C *)out = t;
return out;
}
DEFINE_func_8012B864() /* dedup: shared engine-core @0x8012B864 (src/shared) */
+74 -1
View File
@@ -3172,7 +3172,80 @@ void func_80175DA8(param_1)
}
INCLUDE_ASM("asm/ov_SC02_021/nonmatchings/ov_SC02_021_jr_801734BC", func_80176144);
/* func_80176144 — RECONCILED variant of .run/uc/func_80176144.c
*
* GATE BLOCKER (whole-binary build, NOT match_one):
* src/ov_SC01_077/ov_SC01_077_jr_801734BC.c:3476: conflicting types for `D_800AF634'
* || previous declaration at :3296
*
* ROOT CAUSE — a HOISTED file-scope typedef, not a bad signature:
* That TU hoists, at FILE scope, for func_80175DA8:
* :3295 typedef struct { s32 g0; s32 pad[2]; } S_AF634_80176144;
* :3296 extern S_AF634_80176144 D_800AF634[];
* :3297 extern S_AF634_80176144 D_800AF638[];
* The stored draft re-declares the SAME struct shape as a BLOCK-scope typedef
* (rule D — it must travel to the 137 sibling overlays, which have no such
* preamble). A block-scope `typedef struct {...} S_AF634_80176144;` is a DISTINCT type
* from the file-scope one (C has no structural typing), so the block-scope
* `extern S_AF634_80176144 D_800AF634[];` re-declares the symbol incompatibly with the
* in-scope file-scope decl -> hard error.
* Note the earlier block-scope copies in the same TU (:3080 func_80175820,
* :3123 func_801759D8) do NOT error: they precede :3296, so no file-scope decl
* of D_800AF634 is in scope there. Anything AFTER :3296 collides. Our
* definition lands at :3476. That is why only this one fired.
*
* FIX — §37/§124 ASM-LABEL ALIAS applied to the DATA symbols (cookbook §2516:
* "asm-label alias for sibling-decl signedness/proto conflicts ... beats
* reconcile's *(u16*)&D_x cast whose address-of PERTURBS regalloc"):
* the two objects are reached through PRIVATE C identifiers aAF634 / aAF638
* carrying __asm__("D_800AF634") / __asm__("D_800AF638"). The emitted
* %hi/%lo relocations are against the same symbols, so codegen is unchanged,
* while the C names can never collide with ANY sibling TU's declaration —
* whether hoisted, block-scope, or absent. No header edit; no src/ edit.
* Strictly better than deleting the local decls (which would bind this
* exemplar to the one TU that happens to hoist them).
*
* The s32 parameter + explicit (s16) narrowing is retained from the stored draft
* (canonical decl in engine_core.h:18985/:4587 is `void func_80176144(s32)`;
* the K&R short param would itself be a conflicting-types error). The (s16)
* narrowing IS the entry `sll $s0,$a0,16 / sra $s0,$s0,16` pair.
*
* Verified: python3 tools/match_one.py func_80176144 --c .run/uc2/func_80176144.c
* --asm-subdir ov_SC01_077/nonmatchings/ov_SC01_077_jr_801734BC -> MATCH (53 ins)
*/
void func_80176144(s32 a0)
{
typedef struct { s32 g0; s32 pad[2]; } S_AF634_80176144; /* size 0x0C */
/* §37 asm-label alias: private C names, canonical relocations. */
extern S_AF634_80176144 aAF634[] __asm__("D_800AF634");
extern S_AF634_80176144 aAF638[] __asm__("D_800AF638");
extern u8 D_8011F7A8;
extern s16 D_8011F7BC;
extern s16 D_8011F7BE;
extern s32 func_80178004(s32 a0, s32 a1, s32 a2);
u32 *slot;
u32 *p;
s16 param_1 = (s16)a0;
p = (u32 *)(aAF638[param_1].g0 + aAF634[param_1].g0 * 4);
slot = (u32 *)(param_1 * 4 + (s32)&D_8011F7A8);
slot[14] = (u32)p;
/* §5a zero-byte sched fence: without it sched1 hoists the two %hi/lhu global
argument loads above the `sw` of slot[14] (16 mismatches, 0 length drift). */
__asm__("");
p = (u32 *)func_80178004((s32)p,
(s16)((*(u16 *)&D_8011F7BC) - 0x17),
(s16)((*(u16 *)&D_8011F7BE) + 0x65));
slot[16] = (u32)p - 0x14;
p += 5;
aAF634[param_1].g0 += ((s32)p - (s32)slot[14]) >> 2;
}
// @class: regalloc-order
+21 -1
View File
@@ -387,7 +387,27 @@ void func_80128AF4(void) {
DEFINE_func_80128C14() /* dedup: shared engine-core @0x80128C14 (src/shared) */
INCLUDE_ASM("asm/ov_SC02_026/nonmatchings/ov_SC02_026", func_80128C98);
typedef struct {
s32 word0;
s32 word4;
} CdFileLoc_80128C98;
extern CdFileLoc_80128C98 cdFileLocTable[];
extern void func_8001ABBC(s32 a0, s32 a1, void *a2, s32 a3, s32 a4);
s32 func_80128C98(s32 arg0) {
extern s16 D_801863CC[];
s16 idx = D_801863CC[arg0];
if (idx >= 0) {
func_8001ABBC(0, 0, (u8 *)&cdFileLocTable[idx], D_801CDC3C, 0);
} else {
return 1;
}
}
INCLUDE_ASM("asm/ov_SC02_026/nonmatchings/ov_SC02_026", func_80128CFC);
+78 -1
View File
@@ -481,7 +481,84 @@ INCLUDE_ASM("asm/ov_SC02_026/nonmatchings/ov_SC02_026_after", func_80146A6C);
DEFINE_func_80146AB4() /* dedup: shared engine-core @0x80146AB4 (src/shared) */
INCLUDE_ASM("asm/ov_SC02_026/nonmatchings/ov_SC02_026_after", func_80146AFC);
extern s32 func_80146B9C(void * arg0);
/* func_80146AFC — ASCENDING twin of the byte-proven DEFINE_func_80146B9C()
* in src/shared/engine_core.h (cookbook §71: find the already-matched sibling first).
* Same 0x58-stride slot table (base D_8011D030), same 7-store copy body in the same
* order, same $a2/$a1 giv pair. 80146B9C walks DOWN; this one walks UP, so the guard
* is `p < end`, end = p + 0xA50 (30 slots x 0x58).
*
* DECAY ROOT CAUSE (this redraft): the stored backlog draft had been rewritten to
* `void func_80146AFC(...)`, which drops BOTH `return 0` paths' `addu $v0,$zero,$zero`
* and the hit path's `j .L80146B94` => LENGTH-DRIFT -2 (38 vs 40) plus $v0/$v1 regalloc
* drift on the final lw/sw pair. Restoring the s32 return type (the fleet spelling the
* banked sibling func_80146B9C already uses) restores MATCH at 40/40.
*
* RECONCILE (2026-08-01) — the whole-binary gate failed with
* ov_SC01_077_after.c:592: conflicting types for `D_8011D030' (previous decl :564)
* TWO file-scope collisions were present; both are fixed HERE, with NO edit to
* src/shared/engine_core.h and NO change to the generated code (re-verified MATCH
* after each step):
*
* 1. D_8011D030 (the reported one). DEFINE_func_801469C8() emits
* `extern s32 D_8011D030;` at FILE scope (engine_core.h:10811, above the
* `s32 func_801469C8(...) {` line), and this TU expands that macro at :564 —
extern s32 D_8011D030;
* i.e. before the splice point :570. The draft's `extern u16` therefore
* redeclared it incompatibly at :592. Conformed to the TU's `extern s32`.
* Codegen-neutral: the sole use is `(u8 *)&D_8011D030`, an address-of, so the
* declared object type never reaches a load/store width (cookbook §20).
*
* 2. func_80146AFC ITSELF (latent, would have surfaced next). DEFINE_func_8014C010()
* (:13510) and DEFINE_func_8014AD30() (:13524) each emit a file-scope
* `extern void func_80146AFC(void *a0);`, and this TU expands them at :1386 and
* :1541 — after the splice — so an `s32 func_80146AFC` definition collides on the
* RETURN axis. Fixed with the §37/§124 ASM-LABEL ALIAS: the C identifier is
* aF80146AFC, the emitted label is func_80146AFC, so the canonical void decl and
* this s32 definition never share a namespace. Callers discard the result, so the
* void-typed call sites stay codegen-identical.
*
* Both were reproduced and then cleared against the real cpp+cc1-2.7.2 pair using a
* synthetic copy of this TU's declaration environment (.run/uc2/_recon_probe_80146AFC.c):
* the pre-reconcile spelling emits exactly the gate's error pair; the spelling below
* compiles clean.
*
* ORACLE: tools/match_one.py func_80146AFC --c .run/uc2/func_80146AFC.c
* --asm-subdir asm/ov_SC01_077/nonmatchings/ov_SC01_077_after -> MATCH (40 ins)
*/
s32 aF80146AFC(void *arg0) __asm__("func_80146AFC");
s32 aF80146AFC(void *arg0)
{
register u8 *p __asm__("$6");
register u8 *q __asm__("$5");
u8 *end;
p = (u8 *)&D_8011D030;
end = p + 0xA50;
if ((u32)p < (u32)end) {
q = p + 0x30;
do {
if (*(u16 *)p == 0) {
*(s32 *)(q + 0x4) = *(s32 *)((u8 *)arg0 + 0x8);
*(s16 *)p = *(u16 *)((u8 *)arg0 + 0x0);
*(s16 *)(q - 0x2A) = *(u16 *)((u8 *)arg0 + 0x2);
*(s16 *)(q - 0x26) = *(u16 *)((u8 *)arg0 + 0x4);
*(s16 *)(q - 0x22) = *(u16 *)((u8 *)arg0 + 0x6);
*(s32 *)(q - 0x4) = *(s32 *)((u8 *)arg0 + 0xC);
*(s32 *)(q + 0x0) = *(s32 *)((u8 *)arg0 + 0x10);
return (s32)p;
}
p += 0x58;
q += 0x58;
} while ((u32)p < (u32)end);
}
return 0;
}
DEFINE_func_80146B9C() /* dedup: shared engine-core @0x80146B9C (src/shared) */
+49 -1
View File
@@ -327,7 +327,55 @@ DEFINE_func_8012B70C() /* dedup: shared engine-core @0x8012B70C (src/shared) */
DEFINE_func_8012B744() /* dedup: shared engine-core @0x8012B744 (src/shared) */
INCLUDE_ASM("asm/ov_SC02_026/nonmatchings/ov_SC02_026_jr_8012ACE0", func_8012B77C);
extern s32 ratan2(s32 a0, s32 a1);
extern s32 func_80047948(s32 a0); /* rsin-like: angle (0..0xFFF) -> 1.12 fixed */
extern s32 func_8004787C(s32 a0); /* rcos-like: angle (0..0xFFF) -> 1.12 fixed */
/* The 4-byte destination is a PACKED PAIR of angles held entirely in ONE saved register
* ($s4) across all three calls — that is what produces the target's
* andi $s4,$s4,0xFFFF (read of the still-uninitialized local, hoisted into the prologue)
* ... or $s4,$s4,ang<<16 -> t.hi = yaw
* ... and $s4,$s4,0xFFFF0000 / or $s4,$s4,ang&0xFFFF -> t.lo = pitch
* A `struct { s16 lo, hi; }` has align 2 -> BLKmode-ish handling: gcc spills it to the stack
* and stores it with lwl/lwr + swl/swr (54 ins, 53 mismatched). Two 16-bit BITFIELDS in a
* u32 container give the SImode, align-4 struct gcc keeps in a register. */
typedef struct {
u32 lo : 16;
u32 hi : 16;
} Ang2_8012B77C_8012B77C;
/* a0 = destination packed-angle word, a1 = "from" entity, a2 = "to" entity.
* Both entities carry 16.16 fixed-point x/y/z at +0/+4/+8; the s16 reads at +2/+6/+0xA are
* the integer halves. Returns the destination pointer — the return value is REAL: without it
* gcc stores with `sw $s4,0($s3)` (57 ins) instead of the target's
* addu $v0,$s3,$zero ; sw $s4,0($v0) (the return-value copy that the store's base coalesces onto).
* The flattened `dz` reuse at the end is also load-bearing: making the (dz*sin + dx*cos)>>12
* temp its OWN variable gives it $a1 for the whole chain; reusing `dz` extends that allocno so
* it lands in $s5 exactly as the target does (`sra $s5,$v0,12` / `negu $a1,$s5`), and it also
* demotes dz's priority so the saved-reg order comes out $s3=out, $s4=t, $s5=dz. */
s32 func_8012B77C(s32 out, s32 from, s32 to) {
Ang2_8012B77C_8012B77C t;
s32 dx, dy, dz;
s32 ang;
s32 r1, r2;
dz = *(s16 *)(to + 0xA) - *(s16 *)(from + 0xA);
dx = *(s16 *)(to + 0x2) - *(s16 *)(from + 0x2);
dy = *(s16 *)(to + 0x6) - *(s16 *)(from + 0x6);
ang = (ratan2(-dz, dx) - 0x400) & 0xFFF;
t.hi = ang;
r1 = func_80047948(ang);
r2 = func_8004787C(ang);
dz = (dz * r1 + dx * r2) >> 12;
t.lo = ratan2(dy, -dz);
*(Ang2_8012B77C_8012B77C *)out = t;
return out;
}
DEFINE_func_8012B864() /* dedup: shared engine-core @0x8012B864 (src/shared) */
+74 -1
View File
@@ -3172,7 +3172,80 @@ void func_80175DA8(param_1)
}
INCLUDE_ASM("asm/ov_SC02_026/nonmatchings/ov_SC02_026_jr_801734BC", func_80176144);
/* func_80176144 — RECONCILED variant of .run/uc/func_80176144.c
*
* GATE BLOCKER (whole-binary build, NOT match_one):
* src/ov_SC01_077/ov_SC01_077_jr_801734BC.c:3476: conflicting types for `D_800AF634'
* || previous declaration at :3296
*
* ROOT CAUSE — a HOISTED file-scope typedef, not a bad signature:
* That TU hoists, at FILE scope, for func_80175DA8:
* :3295 typedef struct { s32 g0; s32 pad[2]; } S_AF634_80176144;
* :3296 extern S_AF634_80176144 D_800AF634[];
* :3297 extern S_AF634_80176144 D_800AF638[];
* The stored draft re-declares the SAME struct shape as a BLOCK-scope typedef
* (rule D — it must travel to the 137 sibling overlays, which have no such
* preamble). A block-scope `typedef struct {...} S_AF634_80176144;` is a DISTINCT type
* from the file-scope one (C has no structural typing), so the block-scope
* `extern S_AF634_80176144 D_800AF634[];` re-declares the symbol incompatibly with the
* in-scope file-scope decl -> hard error.
* Note the earlier block-scope copies in the same TU (:3080 func_80175820,
* :3123 func_801759D8) do NOT error: they precede :3296, so no file-scope decl
* of D_800AF634 is in scope there. Anything AFTER :3296 collides. Our
* definition lands at :3476. That is why only this one fired.
*
* FIX — §37/§124 ASM-LABEL ALIAS applied to the DATA symbols (cookbook §2516:
* "asm-label alias for sibling-decl signedness/proto conflicts ... beats
* reconcile's *(u16*)&D_x cast whose address-of PERTURBS regalloc"):
* the two objects are reached through PRIVATE C identifiers aAF634 / aAF638
* carrying __asm__("D_800AF634") / __asm__("D_800AF638"). The emitted
* %hi/%lo relocations are against the same symbols, so codegen is unchanged,
* while the C names can never collide with ANY sibling TU's declaration —
* whether hoisted, block-scope, or absent. No header edit; no src/ edit.
* Strictly better than deleting the local decls (which would bind this
* exemplar to the one TU that happens to hoist them).
*
* The s32 parameter + explicit (s16) narrowing is retained from the stored draft
* (canonical decl in engine_core.h:18985/:4587 is `void func_80176144(s32)`;
* the K&R short param would itself be a conflicting-types error). The (s16)
* narrowing IS the entry `sll $s0,$a0,16 / sra $s0,$s0,16` pair.
*
* Verified: python3 tools/match_one.py func_80176144 --c .run/uc2/func_80176144.c
* --asm-subdir ov_SC01_077/nonmatchings/ov_SC01_077_jr_801734BC -> MATCH (53 ins)
*/
void func_80176144(s32 a0)
{
typedef struct { s32 g0; s32 pad[2]; } S_AF634_80176144; /* size 0x0C */
/* §37 asm-label alias: private C names, canonical relocations. */
extern S_AF634_80176144 aAF634[] __asm__("D_800AF634");
extern S_AF634_80176144 aAF638[] __asm__("D_800AF638");
extern u8 D_8011F7A8;
extern s16 D_8011F7BC;
extern s16 D_8011F7BE;
extern s32 func_80178004(s32 a0, s32 a1, s32 a2);
u32 *slot;
u32 *p;
s16 param_1 = (s16)a0;
p = (u32 *)(aAF638[param_1].g0 + aAF634[param_1].g0 * 4);
slot = (u32 *)(param_1 * 4 + (s32)&D_8011F7A8);
slot[14] = (u32)p;
/* §5a zero-byte sched fence: without it sched1 hoists the two %hi/lhu global
argument loads above the `sw` of slot[14] (16 mismatches, 0 length drift). */
__asm__("");
p = (u32 *)func_80178004((s32)p,
(s16)((*(u16 *)&D_8011F7BC) - 0x17),
(s16)((*(u16 *)&D_8011F7BE) + 0x65));
slot[16] = (u32)p - 0x14;
p += 5;
aAF634[param_1].g0 += ((s32)p - (s32)slot[14]) >> 2;
}
// @class: regalloc-order
+21 -1
View File
@@ -387,7 +387,27 @@ void func_80128AF4(void) {
DEFINE_func_80128C14() /* dedup: shared engine-core @0x80128C14 (src/shared) */
INCLUDE_ASM("asm/ov_SC02_027/nonmatchings/ov_SC02_027", func_80128C98);
typedef struct {
s32 word0;
s32 word4;
} CdFileLoc_80128C98;
extern CdFileLoc_80128C98 cdFileLocTable[];
extern void func_8001ABBC(s32 a0, s32 a1, void *a2, s32 a3, s32 a4);
s32 func_80128C98(s32 arg0) {
extern s16 D_8018B4F0[];
s16 idx = D_8018B4F0[arg0];
if (idx >= 0) {
func_8001ABBC(0, 0, (u8 *)&cdFileLocTable[idx], D_801D79A8, 0);
} else {
return 1;
}
}
INCLUDE_ASM("asm/ov_SC02_027/nonmatchings/ov_SC02_027", func_80128CFC);
+78 -1
View File
@@ -481,7 +481,84 @@ INCLUDE_ASM("asm/ov_SC02_027/nonmatchings/ov_SC02_027_after", func_80146A6C);
DEFINE_func_80146AB4() /* dedup: shared engine-core @0x80146AB4 (src/shared) */
INCLUDE_ASM("asm/ov_SC02_027/nonmatchings/ov_SC02_027_after", func_80146AFC);
extern s32 func_80146B9C(void * arg0);
/* func_80146AFC — ASCENDING twin of the byte-proven DEFINE_func_80146B9C()
* in src/shared/engine_core.h (cookbook §71: find the already-matched sibling first).
* Same 0x58-stride slot table (base D_8011D030), same 7-store copy body in the same
* order, same $a2/$a1 giv pair. 80146B9C walks DOWN; this one walks UP, so the guard
* is `p < end`, end = p + 0xA50 (30 slots x 0x58).
*
* DECAY ROOT CAUSE (this redraft): the stored backlog draft had been rewritten to
* `void func_80146AFC(...)`, which drops BOTH `return 0` paths' `addu $v0,$zero,$zero`
* and the hit path's `j .L80146B94` => LENGTH-DRIFT -2 (38 vs 40) plus $v0/$v1 regalloc
* drift on the final lw/sw pair. Restoring the s32 return type (the fleet spelling the
* banked sibling func_80146B9C already uses) restores MATCH at 40/40.
*
* RECONCILE (2026-08-01) — the whole-binary gate failed with
* ov_SC01_077_after.c:592: conflicting types for `D_8011D030' (previous decl :564)
* TWO file-scope collisions were present; both are fixed HERE, with NO edit to
* src/shared/engine_core.h and NO change to the generated code (re-verified MATCH
* after each step):
*
* 1. D_8011D030 (the reported one). DEFINE_func_801469C8() emits
* `extern s32 D_8011D030;` at FILE scope (engine_core.h:10811, above the
* `s32 func_801469C8(...) {` line), and this TU expands that macro at :564 —
extern s32 D_8011D030;
* i.e. before the splice point :570. The draft's `extern u16` therefore
* redeclared it incompatibly at :592. Conformed to the TU's `extern s32`.
* Codegen-neutral: the sole use is `(u8 *)&D_8011D030`, an address-of, so the
* declared object type never reaches a load/store width (cookbook §20).
*
* 2. func_80146AFC ITSELF (latent, would have surfaced next). DEFINE_func_8014C010()
* (:13510) and DEFINE_func_8014AD30() (:13524) each emit a file-scope
* `extern void func_80146AFC(void *a0);`, and this TU expands them at :1386 and
* :1541 — after the splice — so an `s32 func_80146AFC` definition collides on the
* RETURN axis. Fixed with the §37/§124 ASM-LABEL ALIAS: the C identifier is
* aF80146AFC, the emitted label is func_80146AFC, so the canonical void decl and
* this s32 definition never share a namespace. Callers discard the result, so the
* void-typed call sites stay codegen-identical.
*
* Both were reproduced and then cleared against the real cpp+cc1-2.7.2 pair using a
* synthetic copy of this TU's declaration environment (.run/uc2/_recon_probe_80146AFC.c):
* the pre-reconcile spelling emits exactly the gate's error pair; the spelling below
* compiles clean.
*
* ORACLE: tools/match_one.py func_80146AFC --c .run/uc2/func_80146AFC.c
* --asm-subdir asm/ov_SC01_077/nonmatchings/ov_SC01_077_after -> MATCH (40 ins)
*/
s32 aF80146AFC(void *arg0) __asm__("func_80146AFC");
s32 aF80146AFC(void *arg0)
{
register u8 *p __asm__("$6");
register u8 *q __asm__("$5");
u8 *end;
p = (u8 *)&D_8011D030;
end = p + 0xA50;
if ((u32)p < (u32)end) {
q = p + 0x30;
do {
if (*(u16 *)p == 0) {
*(s32 *)(q + 0x4) = *(s32 *)((u8 *)arg0 + 0x8);
*(s16 *)p = *(u16 *)((u8 *)arg0 + 0x0);
*(s16 *)(q - 0x2A) = *(u16 *)((u8 *)arg0 + 0x2);
*(s16 *)(q - 0x26) = *(u16 *)((u8 *)arg0 + 0x4);
*(s16 *)(q - 0x22) = *(u16 *)((u8 *)arg0 + 0x6);
*(s32 *)(q - 0x4) = *(s32 *)((u8 *)arg0 + 0xC);
*(s32 *)(q + 0x0) = *(s32 *)((u8 *)arg0 + 0x10);
return (s32)p;
}
p += 0x58;
q += 0x58;
} while ((u32)p < (u32)end);
}
return 0;
}
DEFINE_func_80146B9C() /* dedup: shared engine-core @0x80146B9C (src/shared) */
+49 -1
View File
@@ -327,7 +327,55 @@ DEFINE_func_8012B70C() /* dedup: shared engine-core @0x8012B70C (src/shared) */
DEFINE_func_8012B744() /* dedup: shared engine-core @0x8012B744 (src/shared) */
INCLUDE_ASM("asm/ov_SC02_027/nonmatchings/ov_SC02_027_jr_8012ACE0", func_8012B77C);
extern s32 ratan2(s32 a0, s32 a1);
extern s32 func_80047948(s32 a0); /* rsin-like: angle (0..0xFFF) -> 1.12 fixed */
extern s32 func_8004787C(s32 a0); /* rcos-like: angle (0..0xFFF) -> 1.12 fixed */
/* The 4-byte destination is a PACKED PAIR of angles held entirely in ONE saved register
* ($s4) across all three calls — that is what produces the target's
* andi $s4,$s4,0xFFFF (read of the still-uninitialized local, hoisted into the prologue)
* ... or $s4,$s4,ang<<16 -> t.hi = yaw
* ... and $s4,$s4,0xFFFF0000 / or $s4,$s4,ang&0xFFFF -> t.lo = pitch
* A `struct { s16 lo, hi; }` has align 2 -> BLKmode-ish handling: gcc spills it to the stack
* and stores it with lwl/lwr + swl/swr (54 ins, 53 mismatched). Two 16-bit BITFIELDS in a
* u32 container give the SImode, align-4 struct gcc keeps in a register. */
typedef struct {
u32 lo : 16;
u32 hi : 16;
} Ang2_8012B77C_8012B77C;
/* a0 = destination packed-angle word, a1 = "from" entity, a2 = "to" entity.
* Both entities carry 16.16 fixed-point x/y/z at +0/+4/+8; the s16 reads at +2/+6/+0xA are
* the integer halves. Returns the destination pointer — the return value is REAL: without it
* gcc stores with `sw $s4,0($s3)` (57 ins) instead of the target's
* addu $v0,$s3,$zero ; sw $s4,0($v0) (the return-value copy that the store's base coalesces onto).
* The flattened `dz` reuse at the end is also load-bearing: making the (dz*sin + dx*cos)>>12
* temp its OWN variable gives it $a1 for the whole chain; reusing `dz` extends that allocno so
* it lands in $s5 exactly as the target does (`sra $s5,$v0,12` / `negu $a1,$s5`), and it also
* demotes dz's priority so the saved-reg order comes out $s3=out, $s4=t, $s5=dz. */
s32 func_8012B77C(s32 out, s32 from, s32 to) {
Ang2_8012B77C_8012B77C t;
s32 dx, dy, dz;
s32 ang;
s32 r1, r2;
dz = *(s16 *)(to + 0xA) - *(s16 *)(from + 0xA);
dx = *(s16 *)(to + 0x2) - *(s16 *)(from + 0x2);
dy = *(s16 *)(to + 0x6) - *(s16 *)(from + 0x6);
ang = (ratan2(-dz, dx) - 0x400) & 0xFFF;
t.hi = ang;
r1 = func_80047948(ang);
r2 = func_8004787C(ang);
dz = (dz * r1 + dx * r2) >> 12;
t.lo = ratan2(dy, -dz);
*(Ang2_8012B77C_8012B77C *)out = t;
return out;
}
DEFINE_func_8012B864() /* dedup: shared engine-core @0x8012B864 (src/shared) */
+74 -1
View File
@@ -3172,7 +3172,80 @@ void func_80175DA8(param_1)
}
INCLUDE_ASM("asm/ov_SC02_027/nonmatchings/ov_SC02_027_jr_801734BC", func_80176144);
/* func_80176144 — RECONCILED variant of .run/uc/func_80176144.c
*
* GATE BLOCKER (whole-binary build, NOT match_one):
* src/ov_SC01_077/ov_SC01_077_jr_801734BC.c:3476: conflicting types for `D_800AF634'
* || previous declaration at :3296
*
* ROOT CAUSE — a HOISTED file-scope typedef, not a bad signature:
* That TU hoists, at FILE scope, for func_80175DA8:
* :3295 typedef struct { s32 g0; s32 pad[2]; } S_AF634_80176144;
* :3296 extern S_AF634_80176144 D_800AF634[];
* :3297 extern S_AF634_80176144 D_800AF638[];
* The stored draft re-declares the SAME struct shape as a BLOCK-scope typedef
* (rule D — it must travel to the 137 sibling overlays, which have no such
* preamble). A block-scope `typedef struct {...} S_AF634_80176144;` is a DISTINCT type
* from the file-scope one (C has no structural typing), so the block-scope
* `extern S_AF634_80176144 D_800AF634[];` re-declares the symbol incompatibly with the
* in-scope file-scope decl -> hard error.
* Note the earlier block-scope copies in the same TU (:3080 func_80175820,
* :3123 func_801759D8) do NOT error: they precede :3296, so no file-scope decl
* of D_800AF634 is in scope there. Anything AFTER :3296 collides. Our
* definition lands at :3476. That is why only this one fired.
*
* FIX — §37/§124 ASM-LABEL ALIAS applied to the DATA symbols (cookbook §2516:
* "asm-label alias for sibling-decl signedness/proto conflicts ... beats
* reconcile's *(u16*)&D_x cast whose address-of PERTURBS regalloc"):
* the two objects are reached through PRIVATE C identifiers aAF634 / aAF638
* carrying __asm__("D_800AF634") / __asm__("D_800AF638"). The emitted
* %hi/%lo relocations are against the same symbols, so codegen is unchanged,
* while the C names can never collide with ANY sibling TU's declaration —
* whether hoisted, block-scope, or absent. No header edit; no src/ edit.
* Strictly better than deleting the local decls (which would bind this
* exemplar to the one TU that happens to hoist them).
*
* The s32 parameter + explicit (s16) narrowing is retained from the stored draft
* (canonical decl in engine_core.h:18985/:4587 is `void func_80176144(s32)`;
* the K&R short param would itself be a conflicting-types error). The (s16)
* narrowing IS the entry `sll $s0,$a0,16 / sra $s0,$s0,16` pair.
*
* Verified: python3 tools/match_one.py func_80176144 --c .run/uc2/func_80176144.c
* --asm-subdir ov_SC01_077/nonmatchings/ov_SC01_077_jr_801734BC -> MATCH (53 ins)
*/
void func_80176144(s32 a0)
{
typedef struct { s32 g0; s32 pad[2]; } S_AF634_80176144; /* size 0x0C */
/* §37 asm-label alias: private C names, canonical relocations. */
extern S_AF634_80176144 aAF634[] __asm__("D_800AF634");
extern S_AF634_80176144 aAF638[] __asm__("D_800AF638");
extern u8 D_8011F7A8;
extern s16 D_8011F7BC;
extern s16 D_8011F7BE;
extern s32 func_80178004(s32 a0, s32 a1, s32 a2);
u32 *slot;
u32 *p;
s16 param_1 = (s16)a0;
p = (u32 *)(aAF638[param_1].g0 + aAF634[param_1].g0 * 4);
slot = (u32 *)(param_1 * 4 + (s32)&D_8011F7A8);
slot[14] = (u32)p;
/* §5a zero-byte sched fence: without it sched1 hoists the two %hi/lhu global
argument loads above the `sw` of slot[14] (16 mismatches, 0 length drift). */
__asm__("");
p = (u32 *)func_80178004((s32)p,
(s16)((*(u16 *)&D_8011F7BC) - 0x17),
(s16)((*(u16 *)&D_8011F7BE) + 0x65));
slot[16] = (u32)p - 0x14;
p += 5;
aAF634[param_1].g0 += ((s32)p - (s32)slot[14]) >> 2;
}
// @class: regalloc-order
+107 -2
View File
@@ -3403,7 +3403,47 @@ void func_8017CD9C(int param_1)
}
INCLUDE_ASM("asm/ov_SC02_027/nonmatchings/ov_SC02_027_jr_8017AE2C", func_8017CDF8);
/* Entity record touched by func_8017CDF8 (offsets read straight off the asm):
* 0x02 u16 frame/state counter (lhu / sh)
* 0x1C s32 tick counter (lw / sw), signed compare against 0x20
* 0x2A u16 y-ish delta, decremented by 0x10 (lhu / sh)
* 0x2C u16 sound id passed to func_80147324 (lhu)
* 0x30 s32 suppress flag
*/
typedef struct Ent_8017BFE0_8017CDF8 {
u8 pad00[2]; /* 0x00 */
u16 f02; /* 0x02 */
u8 pad04[0x18];/* 0x04 */
s32 f1c; /* 0x1C */
u8 pad20[0xA]; /* 0x20 */
u16 f2a; /* 0x2A */
u16 f2c; /* 0x2C */
u8 pad2e[2]; /* 0x2E */
s32 f30; /* 0x30 */
} Ent_8017BFE0_8017CDF8;
extern void func_80147324(s32 arg0);
extern void func_8017D030(int);
void func_8017CDF8(Ent_8017BFE0_8017CDF8 *param_1)
{
s32 t;
t = param_1->f1c;
param_1->f1c = t + 1;
if (t < 0x20) {
param_1->f2a = param_1->f2a - 0x10;
} else {
if (param_1->f30 == 0) {
func_80147324(param_1->f2c);
}
param_1->f1c = 0;
param_1->f02 = param_1->f02 + 1;
}
((void (*)(Ent_8017BFE0_8017CDF8 *))func_8017D030)(param_1);
}
INCLUDE_ASM("asm/ov_SC02_027/nonmatchings/ov_SC02_027_jr_8017AE2C", func_8017CE7C);
@@ -3568,7 +3608,72 @@ void func_8017D5DC(void *a0) {
}
INCLUDE_ASM("asm/ov_SC02_027/nonmatchings/ov_SC02_027_jr_8017AE2C", func_8017D618);
/* func_8017D618 — spawn/scatter tick for the +0x34 sub-object (state word @0x2).
* MATCH (45 ins), match_one + rtu_match. Four levers, in the order they were found:
*
* 1. §71 sibling-first — same entity shape as func_8017C610 / func_8017C69C in this
* TU: sub-object pointer @0x34 read BEFORE the call (it lives in $s1 across the
* jal), state word @0x2 bumped last. §3-T4: `beqz $v1,else` => `if (p->f2C) {..}`.
* ONE rand() feeds three fields; the raw low 6 bits use a bare `andi` (no extend)
* while the >>12 / >>6 uses share one `sll $x,16` — that shared sign-extend is
* what forces `r` to be a `short` local rather than an int.
*
* 2. §5a CROSS-JUMP — both arms end in `sh ?,0xA($s0)`; gcc tail-merged them (23 off).
* They only stay separate because the loaded halfword lands in a DIFFERENT hard
* reg per arm, which needs (a) the load to be its own statement at the TOP of each
* arm and (b) a SEPARATE temp per arm (t / t2) — one shared temp is one pseudo,
* gets one register in both arms, and re-merges. 23 -> 10 -> 6.
*
* 3. +0x16 is SIGNED: the target materialises -0x20 as `addiu $v0,$zero,-0x20`, not
* `ori 0xffe0`, so that store must go through an s16.
*
* 4. §49 BIRTHING BOOST (the last 6 -> 2 -> 0). Residual was two ALU insns swapped
* with identical registers; source statement order does NOT flip it, because
* sched1's `adjust_priority`/`birthing_insn_p` hands every SET(REG,..) whose dest
* has REG_N_SETS==1 a 0x7f000001 priority, so it sinks to just before its consumer
* and fixes the .greg LUID order that sched2's tie-break then reads.
* THE DIAL: give the offending insn's dest a SECOND set so it loses the boost —
* here one `u16 d` reused by both tail statements. It must be a THIRD temp, not
* `c` itself: writing `c = c + 1;` also un-boosts c's LOAD, which then starves to
* the front of the block and swaps the two `lhu`s instead. Boost the loads, starve
* the arithmetic. */
extern int rand(void);
void func_8017D618(void *a0)
{
s32 p;
s32 obj;
short r;
u16 t;
u16 t2;
u16 e;
u16 c;
u16 d;
p = (s32)a0;
obj = *(s32 *)(p + 0x34);
r = rand();
*(u16 *)(p + 0x06) = *(u16 *)(obj + 0x06) + ((r & 0x3F) - 0x20);
if (*(s32 *)(p + 0x2C) != 0) {
t = *(u16 *)(obj + 0x0A);
*(s16 *)(p + 0x16) = 0x20;
*(u16 *)(p + 0x0A) = t - 0x140;
} else {
t2 = *(u16 *)(obj + 0x0A);
*(s16 *)(p + 0x16) = -0x20;
*(u16 *)(p + 0x0A) = t2;
}
e = *(u16 *)(obj + 0x0E);
c = *(u16 *)(p + 0x02);
*(s32 *)(p + 0x30) = (r >> 12) & 3;
d = ((r >> 6) & 0x3F) - 0x20;
*(u16 *)(p + 0x0E) = e + d;
d = c + 1;
*(u16 *)(p + 0x02) = d;
}
extern void func_800D22E4(s32 a0);
extern void func_80146C3C(void);
+21 -1
View File
@@ -387,7 +387,27 @@ void func_80128AF4(void) {
DEFINE_func_80128C14() /* dedup: shared engine-core @0x80128C14 (src/shared) */
INCLUDE_ASM("asm/ov_SC02_028/nonmatchings/ov_SC02_028", func_80128C98);
typedef struct {
s32 word0;
s32 word4;
} CdFileLoc_80128C98;
extern CdFileLoc_80128C98 cdFileLocTable[];
extern void func_8001ABBC(s32 a0, s32 a1, void *a2, s32 a3, s32 a4);
s32 func_80128C98(s32 arg0) {
extern s16 D_8018B6F4[];
s16 idx = D_8018B6F4[arg0];
if (idx >= 0) {
func_8001ABBC(0, 0, (u8 *)&cdFileLocTable[idx], D_801D092C, 0);
} else {
return 1;
}
}
INCLUDE_ASM("asm/ov_SC02_028/nonmatchings/ov_SC02_028", func_80128CFC);

Some files were not shown because too many files have changed in this diff Show More