mirror of
https://github.com/Cesarus85/ringfall-mjolnir-vr.git
synced 2026-10-18 02:00:27 +02:00
Recover a missing fade relocation in the looping-sound refresh (zero credit)
Wave n3a targeted the 43 eligible parked rows that still carry a structural gap, on the evidence that all five wave n1 landings were parks whose recorded premise did not survive a census. In already-mined units the hypothesis did not pay: no strict exact function, and the verifiers rejected reopens in s3tc (3), motion_sensor, bink_playback (2). Landed at ZERO credit, both strictly closer and both still parked: - _sound_refresh_looping: the park text blamed a compiler-merged duplicate fade call tail. The relocation census refutes that - it was a source defect. Removing the fade_in_time phi local recovers January's fourth _sound_start_fade relocation, so relocations are now exact at 43/43, size moves 1088 -> 1120 against January's 1136, and alndiff regions drop 74 -> 37. - _update_channel_for_looping_sound: size and relocations now both January-exact at 1360/61; the residual is [sha] only. The verifier removed two defective hunks from the submitted refresh body before accepting; the corrected body is byte-identical to the submission. Full ninja, parks 274 active / 0 stale / 0 invalid, stable diff vs scratch/opus5-next150-before.json: gained 7 / 6,832 padded, regressions 0; fake scan 0 leads. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
6ebd05a964
commit
927d135ecb
14 files changed
+2228
-104
No files matched your search
+8
-8
@@ -3520,7 +3520,7 @@
|
||||
"unit": "source/sound/sound_manager",
|
||||
"function": "_sound_refresh_looping",
|
||||
"class": "tu-context-optimization",
|
||||
"evidence": "Best complete ordinary-C refresh graph retained with zero exact credit. January is 1,136 padded bytes with 43 relocations; canonical is 1,088 with 42. Target-backed datum validation calls, the named sound_inaudible_fade_out_time constant, and the source-authentic `loop` assertion spelling are preserved. The remaining missing relocation is a compiler-merged duplicate fade-call tail; HCEA cache-release logic is intentionally absent because January has none of its dependencies. No compiler steering, fake dependency, raw offset, undefined behavior, or nonsensical branch is retained. See docs/object_matching_logs/sound_manager_obj_small_looping_graph_20260908.md.",
|
||||
"evidence": "Best complete ordinary-C refresh graph retained with zero exact credit. January is 1,136 padded bytes with 43 relocations; canonical is 1,088 with 42. Target-backed datum validation calls, the named sound_inaudible_fade_out_time constant, and the source-authentic `loop` assertion spelling are preserved. The remaining missing relocation is a compiler-merged duplicate fade-call tail; HCEA cache-release logic is intentionally absent because January has none of its dependencies. No compiler steering, fake dependency, raw offset, undefined behavior, or nonsensical branch is retained. See docs/object_matching_logs/sound_manager_obj_small_looping_graph_20260908.md. 2026-09-15 (next-150K lane wave n3a): re-baselined at ZERO strict credit and strictly closer than 1088/42. The recorded criterion's premise - that the missing relocation was a compiler-merged duplicate fade-call tail - is REFUTED by the census: it was a source defect. Deleting the fade_in_time phi local recovers January's fourth _sound_start_fade relocation, so the relocation count is now exact at 43/43 and the size moves 1088 -> 1120 toward January's 1136; alndiff regions drop 74 -> 37. The row stays parked and fuzzy [sha].",
|
||||
"measurements": {
|
||||
"target": {
|
||||
"size": 1136,
|
||||
@@ -3528,11 +3528,11 @@
|
||||
"normalized_sha256": "22e6f76584244a8861a4c646d88eb7c301fa5cdc1fc8d98849e505c2d3a391db"
|
||||
},
|
||||
"base": {
|
||||
"size": 1088,
|
||||
"relocation_count": 42,
|
||||
"normalized_sha256": "4820b25c27684fd9430551da92e07ac3c2f358bb66962348d445b5697defb11a"
|
||||
"size": 1120,
|
||||
"relocation_count": 43,
|
||||
"normalized_sha256": "86e26bb3e59f759070492aaa2b2071ff5f9e2db818be0898a711ffe2501ba9e6"
|
||||
},
|
||||
"objdiff_percent": 36.576504
|
||||
"objdiff_percent": 97.800545
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -3723,11 +3723,11 @@
|
||||
"unit": "source/sound/sound_manager",
|
||||
"function": "_update_channel_for_looping_sound",
|
||||
"class": "unclassified",
|
||||
"evidence": "Complete typed looping-channel update reconstructed from January code/relocations and HCEA semantics. It covers properties, cache transitions, linked permutations, definition changes and crossfades. January is 1,360 padded bytes with 61 relocations; canonical is 1,376 with 61. No unique source-level mechanism explains the residual, so it receives zero exact credit. No compiler steering, raw offset, fake dependency, undefined behavior or nonsensical branch is retained. See docs/object_matching_logs/sound_manager_obj_idle_channel_spine_20260908.md.",
|
||||
"evidence": "Complete typed looping-channel update reconstructed from January code/relocations and HCEA semantics. It covers properties, cache transitions, linked permutations, definition changes and crossfades. January is 1,360 padded bytes with 61 relocations; canonical is 1,376 with 61. No unique source-level mechanism explains the residual, so it receives zero exact credit. No compiler steering, raw offset, fake dependency, undefined behavior or nonsensical branch is retained. See docs/object_matching_logs/sound_manager_obj_idle_channel_spine_20260908.md. 2026-09-15 (next-150K lane wave n3a): re-baselined at ZERO strict credit and strictly closer than 1376/61. Size and relocation count are now both January-exact (1360/61); the residual is [sha] only. The row stays parked and fuzzy.",
|
||||
"measurements": {
|
||||
"target": { "size": 1360, "relocation_count": 61, "normalized_sha256": "457d122269e7e06c8b4a557f80eef434e3eb925aa8aaaa73d9e69bce635a6d78" },
|
||||
"base": { "size": 1376, "relocation_count": 61, "normalized_sha256": "5fa29769faf68bcaa178d1a65f979d8641b10b3727a404d00849b345f42a0ff7" },
|
||||
"objdiff_percent": 96.782814
|
||||
"base": { "size": 1360, "relocation_count": 61, "normalized_sha256": "cb7925e4a26b946436b50b7c0f3172fdc975c1e48f7f9780f0d6d1cc8bc12f10" },
|
||||
"objdiff_percent": 99.19809
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -0,0 +1,186 @@
|
||||
# `actor_type_infection.obj` next-150K lane, wave n3a (2026-09-15)
|
||||
|
||||
## Result
|
||||
|
||||
No production change. `source/ai/actor_type_infection.c` is byte-for-byte unchanged
|
||||
(`git diff --stat` empty). The object stays at 4/5 strict exact functions.
|
||||
|
||||
| Function | January padded / relocs / sha16 | Real file (baseline = final) | Disposition |
|
||||
| --- | --- | --- | --- |
|
||||
| `_infection_decide_action` | `304 / 26 / eb35b33e...` | exact | inherited |
|
||||
| `_infection_swarm_aim_jump` | `688 / 22 / 5c2698e0...` | exact | inherited |
|
||||
| `_infection_wander_move_time` | `96 / 5 / 2b2b9cfb...` | exact | inherited |
|
||||
| `_infection_wander_pause_time` | `96 / 5 / b4122501...` | exact | inherited |
|
||||
| `_infection_swarm_control` | `3616 / 104 / 64eacc5c...` | `3360 / 103` residual | NOT-LANDED (census confirms the recorded premise) |
|
||||
|
||||
Gate (baseline and final): `== exact 4 residual 1 unwritten 0`; `_point_from_line3d` guard passed.
|
||||
`config/parked.json` has **no entry for this unit** (`parkcheck.py` prints
|
||||
`no parks for source/ai/actor_type_infection`), so the wave's "currently PARKED" framing does not
|
||||
apply: `_infection_swarm_control` is an ordinary written residual and no parked body was edited
|
||||
anywhere. `fake_match_scan.py`: 0 review leads (real file and candidate).
|
||||
|
||||
## Duplicate prevention
|
||||
|
||||
- Ledgers read in full: `_jonas_helper_pair_20260825`, `_jonas_swarm_jump_recovery_20260827`,
|
||||
`_jonas_exhaustive_census_20260830`, `_aim_jump_owner_reconciliation_20260909`,
|
||||
`_opus5_fresh_graphs_20260914` (including its lead admission correction),
|
||||
`_opus5_150k_w1_20260914`, `_opus5_250k_w3c_20260915`; worker logs
|
||||
`scratch/workers/actor_type_infection.md` and `scratch/workers/w3c_actor_type_infection.md`.
|
||||
- `git log --all --oneline -- source/ai/actor_type_infection.c`: 15 refs, newest `82330421f`.
|
||||
- `branch_sweep.py`: 13 unique blobs; the current file is the unique best
|
||||
(`exact 4 residual 1 sizedelta 256`); 9 blobs compile-fail, the others are worse.
|
||||
- Binding prior decisions (R13): the fresh-graphs 3600/104 body was rejected and reverted because an
|
||||
already-written residual may land only when strict EXACT; w1 recorded SKIPPED-EXHAUSTED; w3c spent
|
||||
2 of 5 shapes and classified the remainder a backend tie.
|
||||
|
||||
## Census (structural-first, run on the REAL FILE)
|
||||
|
||||
Objects: `scratch/workers/n3_actor_type_infection/real.obj` (current production file recompiled) and
|
||||
`v0.obj` (= wave w3c's `c1.c`, re-gated here at 3600/104 — the best known body, used only as the
|
||||
measurement base).
|
||||
|
||||
### Frame census
|
||||
|
||||
| build | `sub esp` | distinct `[ebp-N]` slots | instructions |
|
||||
| --- | --- | --- | --- |
|
||||
| January | `0xe8` | 61 | 1127 |
|
||||
| real file | `0xe4` | 61, **13 of them differ** | 1052 |
|
||||
| `v0` | `0xe8` | 61, **identical set** | 1121 |
|
||||
|
||||
Slots the real file has and January does not: `0x12 0x21 0x80 0xde 0xe2 0xe3`.
|
||||
Slots January has and the real file lacks: `0x24 0x7c 0xcc 0xd6 0xda 0xdb 0xe8`.
|
||||
`[ebp-0x24]/[ebp-0x20]/[ebp-0x1c]` is January's `up` local (`up = biped->object.up;`, three integer
|
||||
moves at `0x113-0x124`); `0xd6/0xda/0xdb` are `unit_control_data` fields. The real file's 4-byte
|
||||
frame gap is a local-set defect, and `v0` already reproduces January's slot set exactly.
|
||||
|
||||
### Relocation census by target (`relocdiff --count-by-target --allow-structural`)
|
||||
|
||||
Every call and global target matches 1:1 between the real file and January **except**:
|
||||
|
||||
| target | January | real file |
|
||||
| --- | --- | --- |
|
||||
| `_normalize3d` | 1 | 3 |
|
||||
|
||||
(The `__real@*` rows that print `0` on our side are the relocation-*spelling* class — our object
|
||||
defines the literal as a `.rdata` select-any COMDAT where January references it undefined;
|
||||
`relocdiff` prints the `symbolic=` equivalence on each of those rows.)
|
||||
|
||||
The real file's single missing relocation is therefore not a missing call but **two surplus
|
||||
out-of-line `normalize3d` calls**: January inlines `normalize3d` at the first and third
|
||||
`has_direction` sites and calls it out of line only at the second, which is reachable only when the
|
||||
`if (has_direction)` block sits at member-loop level rather than nested inside
|
||||
`if (parent == NONE) { if (!airborne) ... }`. `v0` already carries that hoist and matches the whole
|
||||
104-relocation multiset.
|
||||
|
||||
### Census verdict
|
||||
|
||||
The census **confirms** the recorded premise rather than refuting it. The real-file `[size]` and
|
||||
`[relocs]` tags are the already-diagnosed structural gap whose source fix exists and is verified in
|
||||
scratch (`v0`: frame, slot set, relocation multiset, call set, loop spellings, switch layouts,
|
||||
jump-table case targets and literals all match January). What blocks the row is the standing rule
|
||||
that an already-written residual may land only when strict EXACT, together with four backend
|
||||
clusters — not missing evidence.
|
||||
|
||||
## Residual at the best known body (`v0`): 118 instructions, 4 clusters
|
||||
|
||||
1. `0x20f` (4 insns) — inlined `magnitude_squared3d` in the prop scan; A35(2) term age, diagnostic.
|
||||
2. `0x874` (3 insns, +2 bytes) — inlined `normalize3d` #1: January keeps `1/magnitude` live through
|
||||
the third component multiply and pops it at the join shared with the zero path; ours folds the
|
||||
last multiply destructively and needs a `jmp` over the join pop.
|
||||
3. Three `cross_product3d(&up, &direction, ...)` sites (12 insns) — only the two products whose `a`
|
||||
operand is `up.i` commute.
|
||||
4. `0xbfd-0xd18` register web — carries the **entire** 16-byte padded gap.
|
||||
|
||||
## New evidence this wave (decisive negatives — treat as do-not-repeat)
|
||||
|
||||
**N1. The `cross_product3d` header spelling is byte-proven, so cluster 3 can never be closed by
|
||||
respelling `real_math.h`.** `action_obey.obj` owns an out-of-line January COMDAT copy of
|
||||
`_cross_product3d` that is **strict EXACT** against our `real_math.h` body:
|
||||
|
||||
```
|
||||
0009 fld [ecx]; 000b fmul [eax+4]; 000e fld [ecx+4]; 0011 fmul [eax]; 0013 fsubp ; k
|
||||
0015 fld [ecx+8]; 0018 fmul [eax]; 001a fld [ecx]; 001c fmul [eax+8]; 001f fsubp ; j
|
||||
0021 fld [ecx+4]; 0024 fmul [eax+8]; 0027 fld [ecx+8]; 002a fmul [eax+4]; 0030 fsubp ; i
|
||||
```
|
||||
|
||||
January's own helper loads the `a` operand first in every product, including `a->i*b->k`
|
||||
(`fld [ecx]; fmul [eax+8]`) — exactly what our inline expansion emits in the infection body. The
|
||||
alternative hypothesis (January's header writing the `a->i` terms as `b->j*a->i`) is refuted by
|
||||
bytes. Future attempts on cluster 3 must stay inside the caller and must not touch `real_math.h`.
|
||||
|
||||
**N2. Our build already reproduces VC7's commutation where the operands are pointer-based, so this
|
||||
is not a compiler-version gap.** `matrix_math::_matrix3x3_from_forward_and_up` is strict EXACT and
|
||||
commutes 3 of its 6 cross-product products in both builds (`fld [edx+4]; fmul [ecx]` for `a->i*b->j`
|
||||
with `a = ecx = up`, `b = edx = forward`). A tree scan over every `cross_product3d` consumer
|
||||
(`scratch/workers/n3_actor_type_infection/crossscan.py`, 89 functions) shows that **every
|
||||
strict-exact cross-product site in the tree uses register/pointer bases**, and every site whose
|
||||
operands are `ebp`-folded locals is non-exact. The infection anomaly is the offset-0 clause already
|
||||
recorded in laws_w3 **A35(1)**: with `ebp`-folded locals January prefers the older leaf (`up.j` beats
|
||||
`dir.k`, `up.k` beats `dir.j`) except at `up`'s offset 0, where it loads `direction` first. `up` is
|
||||
written once by a named struct copy and never re-aged, so no naming/scoping/aliasing lever remains,
|
||||
and a `{j,k}` pair that resolves both ways proves the rule is not a field-index order.
|
||||
|
||||
**N3. Cluster 4's 16 bytes are exactly the tail duplication of `mov al,1`, and that duplication is a
|
||||
machine-level cross-jump decision, not a source spelling.** January materialises `should_jump = TRUE`
|
||||
at four separate exits (`0xc06`, `0xc3c`, `0xc47`, and the speculative `0xc50 mov al,1; jne 0xc57`),
|
||||
loads the component flags into `cx`, keeps the boolean in caller-saved `al`, converts it *before* the
|
||||
`csmemset` call (`0xcba neg al; push 0x40; push 0; sbb eax,eax; and eax,2; mov esi,eax`) and keeps
|
||||
the unit pointer in `edi`. Ours cross-jumps to one `mov bl,1`, loads the flags into `ax`, keeps the
|
||||
boolean in callee-saved `bl` across the call and converts afterwards (`0xcc8 neg bl` ...
|
||||
`0xcf2 sbb ebx,ebx`). Region measurement: January `0xbfd..0xd18` = 283 bytes, ours
|
||||
`0xbfd..0xd08` = 267 bytes — the entire 16-byte padded gap; after it the two tails are identical up
|
||||
to the `edi`<->`esi` rename. w1's `p1` already wrote the four `should_jump = TRUE;` assignments as
|
||||
separate statements and VC7 still cross-jumped them into one `mov bl,1` (1115 insns, worse); w3c's
|
||||
`c2` (a `word control_flags` local computed before `csmemset`) was byte-inert because VC7 sinks the
|
||||
single-use `?:` to its store. The only spellings that would force the pre-call conversion are
|
||||
prohibited — assigning `control.control_flags` before the `csmemset` that wipes it (dead/nonsensical
|
||||
store) or inventing a second use (fake dependency). Both allocations cost exactly one callee-saved
|
||||
register across the call (January `esi` = flag word + `edi` = unit; ours `ebx` = boolean +
|
||||
`esi` = unit), so this is a genuine allocator/cross-jump tie of the A43 class.
|
||||
|
||||
## Shapes tried
|
||||
|
||||
None. Triage under brief section 5 stopped before any shape: strict exact requires all four clusters
|
||||
at once; cluster 4 alone carries the whole size gap and has no admissible source form (N3); cluster 3
|
||||
is byte-excluded from the header (N1) with no caller-side lever left (N2); clusters 1-2 are x87
|
||||
emission inside inlined `real_math.h` helper bodies (A35(2), diagnostic only). Spending the shape
|
||||
budget on register/x87/scheduling ties is what the wave brief forbids. `v0.c` was re-gated only as
|
||||
the measurement base for the census above.
|
||||
|
||||
## Checks
|
||||
|
||||
Real file untouched, so the final real-file gate equals the baseline
|
||||
(`== exact 4 residual 1 unwritten 0`, all four siblings EXACT); `_point_from_line3d` guard passed;
|
||||
no parked functions in this unit (no drift possible); owner census not applicable (no production
|
||||
change) — for the record, `v0`'s owner set versus the real file adds only `__real@bd888889` and
|
||||
`__real@bfc90fdb` (both present in January's own symbol table) and drops the non-January
|
||||
`__real@3f6eeeef`, with no new code, helper, BSS or COMMON owner; `fake_match_scan.py` reports
|
||||
0 review leads for both.
|
||||
|
||||
## Proposals
|
||||
|
||||
None. No header, `config/symbols.json`, `parked.json` or build-configuration need was found, and no
|
||||
candidate here depends on a FINAL owner ruling.
|
||||
|
||||
Recorded for the owner only, **not re-proposed** (R13 binds): the production body differs from
|
||||
January in 810 of 1127 instructions, has a 4-byte frame gap, 13 wrong frame slots and two surplus
|
||||
out-of-line `normalize3d` calls, which is arguably "materially incomplete" under brief section 8, and
|
||||
`scratch/workers/n3_actor_type_infection/v0.c` is a complete, coherent, strictly-closer replacement
|
||||
(3600/104, 118 differing instructions, all siblings exact, owner census and fake scan clean). The
|
||||
100K lane rejected exactly this landing, so this wave neither lands nor re-proposes it.
|
||||
|
||||
## Reopen criteria (supersede the w3c ledger, narrowed by N1-N3)
|
||||
|
||||
Reopen only when all of the following are answerable at once, or when a same-compiler donor explains
|
||||
the whole `0xbfd-0xd18` register web:
|
||||
|
||||
1. an admissible caller-side source reason for the `up.i`-only (offset-0) operand commutation at the
|
||||
three inlined `cross_product3d` sites — `real_math.h` is now byte-excluded (N1) and no
|
||||
naming/scoping lever remains (N2);
|
||||
2. a source reason that makes `should_jump` dead at the `csmemset` call without a dead store or a
|
||||
fake second use (N3);
|
||||
3. a source reason for the inlined `normalize3d` #1 reciprocal staying live to the shared join.
|
||||
|
||||
Start any future attempt from `scratch/workers/n3_actor_type_infection/v0.c` (3600/104, 118 insns),
|
||||
never from `r3600.c` (151 insns) or from the real file. Do not re-spend the fresh-graphs
|
||||
do-not-repeat list, w1's `p1`, or w3c's `c1`/`c2`.
|
||||
@@ -0,0 +1,200 @@
|
||||
# `bink_playback.obj` — next-150K lane, wave n3a (structural park pass, 2026-09-15)
|
||||
|
||||
## Scope and provenance
|
||||
|
||||
- Translation unit `source/bink/bink_playback.c`; target `build/split/source/bink/bink_playback.obj`
|
||||
(January 2002 Xbox debug build, VC7 13.00.9254, `/O2 /Oy- /DDEBUG /Dxbox`).
|
||||
- Lane `opus/next-150k-house-clean-20260915`. No header, config, park, build or tooling edit; the real
|
||||
file is byte-identical to HEAD (`git diff --stat -- source/bink/bink_playback.c` is empty).
|
||||
- Ledgers read first: `bink_playback_obj_fable_graph_reconciliation_20260908`,
|
||||
`bink_playback_obj_jonas_six_leaf_20260821`, `bink_playback_obj_jonas_stop_render_followup_20260821`,
|
||||
`bink_playback_obj_jonas_anonymous_ret_leaf_20260830`, `bink_playback_obj_opus5_150k_w2_20260914`,
|
||||
`bink_playback_obj_opus5_next150_n1_20260915`, `fable_bink_ui_network_hs_reconciliation_20260908`,
|
||||
all three `config/parked.json` entries, `scratch/workers/n1_bink_playback.md` and the full n1 impl +
|
||||
verifier blocks in `scratch/opus5-next150/wave-n1-results.json`.
|
||||
- Worker notes and every candidate: `scratch/workers/n3_bink_playback.md`,
|
||||
`scratch/workers/n3_bink_playback/`.
|
||||
|
||||
## Baseline correction
|
||||
|
||||
The wave brief quoted `exact 20 / residual 4` with `_bink_free_texture_cache` non-exact. That is stale:
|
||||
n1's reopen of that row has already landed (commit `3083f800b`). The measured baseline at this HEAD is
|
||||
|
||||
== emitted-symbol guard passed (1 forbidden names checked)
|
||||
== exact 21 residual 3 unwritten 0 (of 24 listed)
|
||||
|
||||
and **all three remaining residuals are parked**, so nothing in this object can land in the real file
|
||||
this wave; everything below is a park-reopen proposal measured in scratch.
|
||||
|
||||
| | exact | residual | unwritten |
|
||||
| --- | ---: | ---: | ---: |
|
||||
| baseline real file (guard passed) | 21 | 3 | 0 |
|
||||
| final real file (unchanged, guard passed, park drift 0) | 21 | 3 | 0 |
|
||||
| candidate `reopen_draw_frame_plus_query.c` | 23 | 1 | 0 |
|
||||
|
||||
## Two park reopens proposed — 992 padded bytes, both strict EXACT in scratch
|
||||
|
||||
Candidate for both: `scratch/workers/n3_bink_playback/reopen_draw_frame_plus_query.c` (the current real
|
||||
file plus the two reopened bodies and nothing else). Individually:
|
||||
`reopen_draw_frame.c` (= `d7.c`) and `q3.c`.
|
||||
|
||||
### `_bink_draw_frame` (912) — the recorded `[relocs]` gap was never this function's
|
||||
|
||||
**Census first.** Frame census: `mov eax,0x1128` on both sides, and every `[ebp±N]` slot is shared
|
||||
(`[ebp-4]`/`[ebp-0x14]` fild scratch, `[ebp-0xc]` top, `[ebp-0x18]` the homed `long`, `[ebp-0xac]`
|
||||
`vertices[4]`, `[ebp-0x5c]` bounds, `[ebp-0x112c]` string) — no slot ours lacks or adds. Relocation
|
||||
census by target: 59 == 59, identical targets and addends. The park's `[relocs 61!=59]` tag belongs to the
|
||||
*old parked body*; n1's `d0` shape already closed it, and this wave reproduced that on the post-n1 HEAD as
|
||||
`d0r.c` (912 / 59 / `[sha]`). `d0.c` itself can no longer be gated here — it still spells line 797
|
||||
`match_dassert` and would regress the landed `_bink_free_texture_cache`.
|
||||
|
||||
`alndiff` of `d0r` vs target: 284 vs 284 instructions, all equal except two windows whose start and end
|
||||
addresses agree on both sides:
|
||||
|
||||
| addr | January | `d0r` |
|
||||
| --- | --- | --- |
|
||||
| 0x119 | `inc edx` ; `mov [ecx+0xc],0xffffffff` | `mov [ecx+0xc],0xffffffff` ; `inc edx` |
|
||||
| 0x123 | `inc esi` ; `fxch st(1)` ; `add ecx,0x14` | `add ecx,0x14` ; `fxch st(1)` ; `inc esi` |
|
||||
|
||||
n1 classified that as a machine-scheduler tie. **It is not.** Both windows move together, and what moves
|
||||
them is the identity of the address induction variable: January's vertex cursor ECX is coupled to the
|
||||
**long** counter (`inc esi`, one instruction, `add ecx,0x14`), ours to the **short** counter. That is the
|
||||
lvalue-topology class of laws_w3 A33, i.e. a source fact — which variable the array subscript is written
|
||||
on.
|
||||
|
||||
January's two loop variables, read off its own bytes:
|
||||
|
||||
- EDX — `xor edx,edx` (0), `cmp dx,1 / jle` twice (the `>1` top/bottom selector), `cmp dx,4 / jl` bound.
|
||||
16-bit compares and a signed `jl`: a `short`, 0-based, bounded by a signed literal `4`.
|
||||
- ESI / `[ebp-0x18]` — `mov dword [ebp-0x18],1`, `and esi,2` (`TEST_FLAG(x, 1)`, bit 1), 32-bit: a `long`,
|
||||
1-based, memory-homed because the register file is full (ebx/edi/eax hold left/right/bottom, ecx the
|
||||
cursor, edx the index, esi the scratch).
|
||||
- Quad recovered: bit 1 of {1,2,3,4} = F,T,T,F = left,right,right,left; `>1` of {0,1,2,3} =
|
||||
top,top,bottom,bottom. v0=(left,top) v1=(right,top) v2=(right,bottom) v3=(left,bottom).
|
||||
- `lea ecx,[ebp-0xa8]` = `vertices + 4`, so the cursor is `&vertices[corner_index-1] + 4`.
|
||||
|
||||
**Shapes (7 + 4 controls).**
|
||||
|
||||
| # | shape | result |
|
||||
| --- | --- | --- |
|
||||
| `d0r` | n1's `d0` body rebuilt on this HEAD | 912/59 `[sha]`, the two windows |
|
||||
| `d1` | explicit `vertex` pointer, `vertex++` last in the clause | January's exact ORDER, but cursor bias +8 (`lea ecx,[ebp-0xa4]`; `fstp [ecx-4]` is 3 B where January's `fstp [ecx]` is 2 B) → +1 byte, `[sha]` |
|
||||
| `d2` | clause `corner_index++, vertex_index++` | January's exact BYTE POSITIONS, only `inc esi`/`inc edx` swapped |
|
||||
| `d3` | `corner_index++;` as the last body statement | identical to `d2` |
|
||||
| `d4` | in-loop `struct dynamic_screen_vertex *vertex= &vertices[vertex_index];` | bias +8 like `d1`, `[sha]` |
|
||||
| `d5` | `d1` with `vertex++` between the two index increments | identical to `d1` |
|
||||
| `d6` | initialiser order `corner_index= 1, vertex_index= 0` | byte-identical to `d0r` (init order inert) |
|
||||
| **`d7`** | **subscript `vertices[corner_index-1]`** | **strict EXACT 912 / 59 / `24aa7c5023629b6b`** |
|
||||
| `d8` | one long counter, `short vertex_index` derived in the loop | frame 0x1124 (the short loses its own slot), 60 relocs |
|
||||
| `d10`/`d11`/`d12` | bound moved onto the long (`corner_index<=NUMBEROF(vertices)`, `<5`) | 928 `[size]` |
|
||||
| `d7n` | `d7` with `vertex_index<NUMBEROF(vertices)` | `[sha]` — `NUMBEROF` is `size_t`, so the compare goes unsigned; January's `jl` is signed, so the literal `4` is byte-proven here |
|
||||
|
||||
**What the programmer meant.** A four-corner quad written with a 0-based vertex counter and a 1-based
|
||||
corner number: the left/right bit comes from the 1-based corner (`TEST_FLAG(corner_index, 1)`), the
|
||||
top/bottom half from the 0-based vertex (`vertex_index>1`), and the vertex written is the corner's,
|
||||
`vertices[corner_index-1]`.
|
||||
|
||||
**Disclosure.** The two counters run in lockstep, so with `vertex_index` in scope a programmer could
|
||||
equally have written `vertices[vertex_index]`. The redundancy is a *January* fact (its bytes carry both
|
||||
counters, at two widths, with two different initial values), and so is which of the two carries the
|
||||
address (the IV is built from the 32-bit counter, with no `movsx`). `d0r`/`d2`/`d3` measure exactly what
|
||||
the other choice costs. If the owner rules `corner_index-1` a steering respelling, the fallback is
|
||||
`d0r.c` — 912/59 `[sha]`, zero credit, R11: do not land it.
|
||||
|
||||
### `_bink_query_analog_controller_buttons` (80) — the park premise is refuted
|
||||
|
||||
This row is on the laws_w2 section D do-not-repeat table ("register allocation and scheduling", five
|
||||
shapes) and n1 skipped it. It was re-opened only because a fresh census produced a fact no ledger records.
|
||||
|
||||
**Frame census.** January is `push ebx; push esi` and nothing else — **no `push ebp; mov ebp,esp`, no
|
||||
`sub esp,N`, zero stack slots.** Ours adds `push ebp; mov ebp,esp; push ecx` … `mov esp,ebp; pop ebp` and
|
||||
one slot `[ebp-1]` for `button_pressed`. Under `/Oy-` VC7 keeps an EBP frame exactly when the function has
|
||||
stack locals, so the absent frame *proves* January has no stack local here. The two alignment pads ours
|
||||
carries (`nop` at 0xf, `lea ecx,[ecx]` at 0x2d) exist only because the extra bytes push the two loop heads
|
||||
onto 0x10/0x30; January's heads at 0x6/0x25 are too far from a boundary to be padded. That is the whole
|
||||
16-byte gap.
|
||||
|
||||
**Relocation census.** 1 == 1, `_input_get_gamepad_state`, same site. Nothing missing, nothing extra.
|
||||
|
||||
**The defect.** January holds `button_pressed` in BL (`xor bl,bl` @0x2, `test bl,bl` @0x6 loop head,
|
||||
`mov bl,1` @0x38, `mov al,bl` @0x42) and rematerialises the comparison constant as an immediate
|
||||
(`cmp byte ptr [eax+0x1c], 1` ×3). Ours pins the constant 1 in EBX in the preheader (`mov bl,1` @0xd) and
|
||||
spends the three compares as `cmp byte ptr [...], bl`, one byte cheaper each — which evicts the boolean to
|
||||
`[ebp-1]` and costs the frame, a store/reload pair and both pads. This is the recurring constant-pinning
|
||||
family (memory note "zero-register pinning residual"), inverted: January spends the callee-saved byte
|
||||
register on the live boolean, we spend it on a folded constant.
|
||||
|
||||
**Shapes (3).** `q1` declaration-order swap: inert. `q2` `gamepad` hoisted to a function-scope
|
||||
declaration: inert. **`q3`** — `if (start==1) {p=TRUE;} else if (back==1) {p=TRUE;} else {loop}` — strict
|
||||
EXACT 80 / 1 / `c88d131ba2ff1ac7`. The third assignment site raises the boolean above the folded constant
|
||||
in the allocator's ranking; the boolean takes EBX, the constant returns to an immediate, the stack home
|
||||
and therefore the EBP frame and both pads disappear, and the three sites cross-jump into January's single
|
||||
`mov bl,1` at 0x38.
|
||||
|
||||
**What the programmer meant.** Poll each gamepad; if START was pressed this frame, or BACK was, skip the
|
||||
movie; otherwise scan the eight analog-button mirrors for one pressed this frame. `buttons[]` is a `byte`
|
||||
frames-held tick counter (`update_ticks(byte *ticks, boolean down)`, input.h:209), which is why the test is
|
||||
against the literal 1 rather than a boolean test.
|
||||
|
||||
**Disclosure.** Both arms carry the same assignment and `||` is the more idiomatic spelling, so this is
|
||||
the laws_w3 A26 device (admitted in the w3 newly-admitted list) *without* A26's strongest evidence:
|
||||
January merges all three `je 0x38` into one physical `mov bl,1` block, so its CFG alone does not
|
||||
distinguish `||` from `else if`. The discriminating evidence is the allocation — the `||` form does not
|
||||
reach January's frameless BL-carried shape in any arrangement measured here or in the five shapes of the
|
||||
earlier waves, and the else-if form reaches it byte-for-byte. It is R2-adjacent and needs a verifier
|
||||
judgement.
|
||||
|
||||
## `_bink_alloc@4` (496) — OWNER-BLOCKED, no new lever
|
||||
|
||||
n1 refuted this park in full and produced a strict-EXACT candidate;
|
||||
`scratch/workers/n1_bink_playback/reopen_alloc_plus.c` still gates `EXACT 496 _bink_alloc@4`
|
||||
(`== exact 22 residual 2`) unchanged at this HEAD. The single remaining byte is the corpus-unique `int3`
|
||||
at 0xd1; `__asm { int 3 }` reproduces it and `__debugbreak()` does not.
|
||||
|
||||
New this wave, and negative: there is no existing breakpoint construct in the tree to reuse. The only
|
||||
`__asm` in any header is `fast_ftol` (cseries.h:314); no `__debugbreak`/`DebugBreak`/`debug_break` exists
|
||||
anywhere under `source/`; and the assert family cannot be the source of the int3, because `match_assert`
|
||||
lowers to `display_assert(...); system_exit(-1);` (= January's `add esp,0x14` = 0x10 + 0x4) while
|
||||
`system_exit` and `halt_and_catch_fire` are ordinary out-of-line functions (cseries_windows.c:116,
|
||||
main.c:2766), not traps. So no non-asm route exists, and the n1 verifier's narrow question — a one-site,
|
||||
unit-local `__asm { int 3 }` in a non-helper function — remains the only opening. The declined cseries.h
|
||||
`debug_break()` macro is NOT re-proposed and no body depending on an ungranted item is submitted. Zero
|
||||
shapes spent.
|
||||
|
||||
## Checks
|
||||
|
||||
- Final real-file gate: `== exact 21 residual 3 unwritten 0`, emitted-symbol guard passed, identical to
|
||||
baseline row for row; `scratch/parkcheck.py` on the real object: parks 3, drift 0.
|
||||
- Candidate `reopen_draw_frame_plus_query.c`: gate `== exact 23 residual 1`; the row-by-row diff against
|
||||
the HEAD `--all` listing moves only the two reopened rows and no baseline-EXACT row changes; point guard
|
||||
passed; parkcheck drift 2, each drifting row reaching exactly its target measurement
|
||||
((912, 59, `24aa7c5023629b6b`) and (80, 1, `c88d131ba2ff1ac7`)) with `_bink_alloc@4` unchanged at
|
||||
512/51; owner census vs `build/base` and `build/split`: candidate-only `[]`, absent-from-target `[]`,
|
||||
base-only-lost `[]` (identical to a HEAD control object built the same `--source` way);
|
||||
`tools/fake_match_scan.py` 0 leads, same as HEAD. `q3.c` and `reopen_draw_frame.c` pass the same checks
|
||||
individually. CRLF endings preserved throughout (0 bare LF).
|
||||
|
||||
## Reusable laws measured here
|
||||
|
||||
1. **Address-IV identity is a source fact, not a scheduler tie.** When a loop carries two lockstep
|
||||
counters of different widths, the strength-reduced pointer couples to whichever counter the subscript
|
||||
is written on, and the coupling fixes the emission slots of *both* increments relative to the body
|
||||
stores. Detector: two adjacent-instruction permutations that both involve an induction-variable update,
|
||||
inside windows whose start and end addresses agree — that is not a tie, it is the wrong subscript
|
||||
variable. Cites `d0r`/`d2`/`d3` vs `d7`.
|
||||
2. **Subscript spelling sets the cursor bias.** `array[index].field` biases the strength-reduced cursor by
|
||||
+4 here; an explicit `T *p` walked with `p++` (whether declared outside the loop or re-derived inside
|
||||
it) biases it by +8, which costs one displacement byte on the store that January emits as `fstp [ecx]`.
|
||||
So a one-byte size gap in a pointer-walk loop can distinguish the two spellings. Cites `d1`/`d4`/`d5`.
|
||||
3. **`NUMBEROF` as a loop bound is byte-visible.** `NUMBEROF` is `sizeof/sizeof`, i.e. `size_t`, so a
|
||||
`short < NUMBEROF(x)` compare goes unsigned (`jb`). A signed `jl` against a small literal in January
|
||||
therefore proves a plain integer bound and forbids the house-style macro at that site. Cites `d7n`.
|
||||
4. **An absent EBP frame is a structural proof.** Under `/Oy-`, VC7 emits `push ebp; mov ebp,esp` only for
|
||||
a function with stack locals. A target prologue of bare `push`es where ours has an EBP frame proves the
|
||||
target has *no* stack local, which converts a "register allocation" park into a locatable defect; here
|
||||
the defect was a folded constant pinned into the one callee-saved byte register the live boolean needed.
|
||||
Alignment `npad`s downstream of such a gap are consequences, not independent differences.
|
||||
5. **Duplicating an assignment across an else-if chain can unpin a folded constant** (refines laws_w3 A26
|
||||
/ the zero-register-pinning note): a third source assignment site to a boolean raised it above the
|
||||
comparison constant in VC7's ranking for the callee-saved byte register. Recorded with the caveat that
|
||||
January's CFG merges the sites, so the evidence is allocational, not control-flow.
|
||||
@@ -0,0 +1,177 @@
|
||||
# `biped_limp_noodle.obj` structural park pass (opus5 next-150K lane, wave n3a, 2026-09-15)
|
||||
|
||||
Worker scope: `source/units/biped_limp_noodle.c` only. All three non-exact rows are parked
|
||||
(`config/parked.json`), so every body referenced below is scratch-only. **The real file is unchanged**
|
||||
(`git diff --stat -- source/units/biped_limp_noodle.c` is empty). No exact bytes are claimed and no
|
||||
orchestrator proposal is filed.
|
||||
|
||||
Notes: `scratch/workers/n3_biped_limp_noodle.md`. Scratch: `scratch/workers/n3_biped_limp_noodle/`
|
||||
(`base.obj`, `vp1r.obj`, `vm6pr.obj`, `vp1_full.txt`, `vm6p_diff.txt`).
|
||||
|
||||
Read first: `scratch/opus5-next150/WORKER_BRIEF.md` (incl. the FINAL 2026-09-15 owner rulings),
|
||||
`scratch/w2/laws_w2.md`, `scratch/w3/laws_w3.md`, and every ledger for this object:
|
||||
`biped_limp_noodle_obj_opus5_250k_w3c_20260915.md`, `biped_limp_noodle_obj_opus5_150k_w1_20260914.md`,
|
||||
`biped_limp_noodle_codex_checkpoint.md`, `bipeds_obj_jonas_limp_flight_pair_20260831.md`,
|
||||
plus `scratch/workers/biped_limp_noodle.md` and `scratch/workers/w3c_biped_limp_noodle.md`.
|
||||
|
||||
## Baseline and final (identical)
|
||||
|
||||
Whole-TU gate with `--forbid-emitted-symbol _point_from_line3d`:
|
||||
|
||||
| Function | Target padded / meaningful / relocs | Real file | Status |
|
||||
| --- | --- | --- | --- |
|
||||
| `_biped_limp_noodle_get_max_relaxation_iterations` | 16 | exact | EXACT |
|
||||
| `_biped_limp_noodle_valid_joint_rotation` | 1248 / 1244 / 34 | 1216 / 34 | residual (parked) |
|
||||
| `_biped_limp_noodle_move_relax_and_constrain_positions` | 1968 / 1955 / 66 | 1888 / 66 | residual (parked) |
|
||||
| `_validate_real_vector3d_axes3` | 496 | exact | EXACT |
|
||||
| `_biped_limp_noodle_adjust_orientations` | 704 | exact | EXACT |
|
||||
| `_biped_limp_noodle_relax_nodes_onto_environment` | 256 / 244 / 9 | 240 / 9 | residual (parked) |
|
||||
|
||||
`== exact 3 residual 3 unwritten 0` at baseline and at the end; the `_point_from_line3d` guard passes;
|
||||
`scratch/parkcheck.py` reports parks 3 / drift 0; `tools/fake_match_scan.py` finds 0 leads on the real file.
|
||||
`branch_sweep.py` (8 unique blobs) shows the current blob `706055aa` is the best in history — no donor.
|
||||
|
||||
## 1. Mandatory wave-n3 census
|
||||
|
||||
The wave-n3 method asks whether a fresh census refutes each park's recorded premise (a `[size]`/`[relocs]`
|
||||
gap that the park text calls a compiler tie but that is really a source defect: a missing statement whose
|
||||
relocation January owns, a hand-expanded initializer, a one-use alias, a wrong declared width, or wrong
|
||||
control flow). The census was run before any shape.
|
||||
|
||||
### 1.1 Relocation census by target (`relocdiff --count-by-target --allow-structural`)
|
||||
|
||||
**All three rows carry the identical relocation multiset to January**, target for target and (for
|
||||
`relax_nodes`) in the identical order; only addresses shift. The rows `relocdiff` prints as differing in
|
||||
the summary tables are the csplit representation of the same literal (`symbol:__real@3f800000` versus
|
||||
`defined-noncode:.rdata:__real@3f800000`, whose `symbolic=` form resolves equal) — see
|
||||
`csplit-relocation-alias` / laws_w3 A45 for the class.
|
||||
|
||||
* `relax_nodes_onto_environment` 9/9; `valid_joint_rotation` 34/34; `move_relax_and_constrain_positions` 66/66.
|
||||
|
||||
**No call and no global is missing from any of the three bodies.** The "a missing relocation is a missing
|
||||
statement" route is closed for this object.
|
||||
|
||||
### 1.2 Frame census
|
||||
|
||||
* `relax_nodes_onto_environment`: January `sub esp,0x10`, ours `sub esp,0x10`. Four homed cells each side.
|
||||
January: `[-0x10]` animation_graph, `[-0xc]` node_matrices, `[-8]` node_index, `[-1]` relaxation_complete.
|
||||
Ours: `[-0x10]` biped, `[-0xc]` animation_graph, `[-8]` node_matrices, `[-1]` relaxation_complete.
|
||||
Neither side lacks or adds a slot; the *set* of homed values differs by exactly one swap
|
||||
(January spills `node_index` and keeps `biped` in ESI; ours does the reverse).
|
||||
`alndiff --include-equal`: 103 target instructions including 12 tail-padding bytes versus 93 ours
|
||||
including a 4-byte loop-top pad — **the same 91 real instructions, the same control flow, the same widths.**
|
||||
* `valid_joint_rotation`: January `sub esp,0xe4`; the real file `sub esp,0xcc` (the park's recorded first
|
||||
divergence); the w3c scratch body `vp1.c` `sub esp,0xe4`, 431/431 instructions, **size 1248** — re-gated
|
||||
this wave as `residual 1248 ... [sha]`, i.e. the `[size]` tag is gone.
|
||||
* `move_relax_and_constrain_positions`: the w3c scratch body `vm6p.c` reproduces January's frame
|
||||
**slot for slot with identical per-slot reference counts** (34 distinct `[ebp±N]` cells, including the
|
||||
`[ebp-0x20]` integer-conversion temporary and the `[ebp-0x27]` byte the park text names). The real file
|
||||
differs at −0x48/−0x44/−0x40/−0x32/−0x28/−0x27/−0x24/−0x23/−0x20. Instruction counts: target 631,
|
||||
`vm6p` 619, real file 598. Full table in the worker notes §0.3.
|
||||
|
||||
### 1.3 Verdict
|
||||
|
||||
* `relax_nodes_onto_environment` — the park premise is **CONFIRMED**, not refuted: same frame, same
|
||||
relocations, same instruction count, same widths, same control flow; the only difference is which of
|
||||
`biped` / `node_index` loses the last callee-saved register.
|
||||
* `valid_joint_rotation` and `move_relax_and_constrain_positions` — the **recorded** premises (a frame gap
|
||||
at `+0x03`; a `[ebp-0x20]` vs `[ebp-0x1C]` homing choice) are **stale rather than newly refuted**: w1 and
|
||||
w3c already found the source defects behind them and fixed them in scratch. The remaining blockers are
|
||||
not structural (below).
|
||||
|
||||
**No wave-n3 "hidden source defect" was found.** The structural work on this object was already done; the
|
||||
residuals are a FINAL-OUT helper spelling and one allocation tie.
|
||||
|
||||
## 2. `_biped_limp_noodle_valid_joint_rotation` — three instructions, prohibited-helper-blocked
|
||||
|
||||
`alndiff` of `scratch/workers/w3c_biped_limp_noodle/vp1.obj` against `build/split` (re-run this wave) shows
|
||||
the candidate is **instruction-for-instruction identical to January at every address except one
|
||||
3-instruction block**. The entire residual is the association of the inlined `dot_product3d` inside the
|
||||
assert's `plane3d_distance_to_point(&plane, &rotate_to_position)`:
|
||||
|
||||
* January (T 0x293): `fld [-0xc]; fmul [-0x44]` (j-term, point field first), `fld [-0x10]; fmul [-0x48]`
|
||||
(i-term, point first), `faddp`, `fld [-0x40]; fmul [-8]` (k-term, **normal** first), `faddp`,
|
||||
`fsub [-0x3c]` — the source association `(i*bi + j*bj) + k*bk`, with the leaves of the first add swapped.
|
||||
* Ours emits the same three products with the **same per-term operand orders** but associates `(j + k) + i`.
|
||||
* The preceding `set_real_point3d` compute/store block (T 0x271-0x291,
|
||||
`fld [-0x38]; fmul st(1); fadd [esi]; fstp [-0x10]` and its y/z copies) is byte-equal, so
|
||||
`rotate_to_position` is produced exactly as January produces it.
|
||||
|
||||
The term rank is therefore set by the leaf ages of `plane_normal.i/j/k`, which every admissible call-site
|
||||
spelling reads **by name** (laws_w3 A35(1)/(4)). I enumerated every `__inline` helper in `source/math/real_math.h`:
|
||||
`point_from_line3d` (line 1077) is the only one whose body is `result->x = v->i*t + p->x`; a
|
||||
`scale_vector3d` + `add_vectors3d` pair splits the fused multiply-add into six stores. `vj2.c` is already
|
||||
strict EXACT with the inline helper and fails the lane guard, and the `_point_from_line3d` COMDAT ruling is
|
||||
FINAL (brief §1; laws_w3 C2 and R14, which also rejects re-proposing it).
|
||||
|
||||
Shapes spent to date: w1 j1/j2/j3/j4/j5 and w3c vp1/vp2/vp3 (nine, including the strict-exact OUT body);
|
||||
the post-tie 2-shape budget is spent. **No shape was spent this wave** — the triage result is SKIPPED-EXHAUSTED.
|
||||
|
||||
## 3. `_biped_limp_noodle_move_relax_and_constrain_positions` — 31 real blocks, two of them OUT-shaped
|
||||
|
||||
`alndiff` of `vm6p.obj` against `build/split` gives 76 blocks, of which **31 are real** after filtering the
|
||||
csplit representation rows. They fall into four families:
|
||||
|
||||
1. **First-node block (T 0x1a0-0x1e8).** January forms the segment with full indexed addressing
|
||||
(`fld [edi+esi+0x28]; fsub [eax+esi+0x28]`, then the y pair) and only afterwards emits the two
|
||||
`lea [edi+esi+0x28]` / `lea [eax+esi+0x28]` pointer forms; ours emits the `lea`s first and reads
|
||||
`[ebx]`/`[edi+4]`. This is the accessor-binding split (January uses both forms, per site). w1 tried the
|
||||
reorder as m7/m8/m9/m10/m14 — all byte-identical to m6.
|
||||
2. **Two squared-term hoists (T 0x356, T 0x43f).** Ours hoists `fld [-0x78]; fmul [-0x78]` above the
|
||||
neighbouring `xor ecx,ecx`; January emits it after. Pure schedule; the differing 2- versus 3-byte
|
||||
alignment pad (`mov edi,edi` versus `lea ebx,[ebx]`) follows from it.
|
||||
3. **Endpoint loop (T 0x481-0x4d3).** January colours the counter EDX and the endpoint pointer ECX (ours
|
||||
ECX/EAX) and its layout places the `mov [ebp+ecx*4-0x38],edx; jmp` block between the two ternary arms
|
||||
where ours places it at the tail. Register colouring plus block placement — laws_w3 A43 records that no
|
||||
source lever moves which duplicate tail survives.
|
||||
4. **Apply loop (T 0x632-0x67c).** January holds the scale in `st` across the three components
|
||||
(`fld [-0x10]; fmul st(1); … fstp st(0)`) and, after `collision_move_point`, loads the **vector component
|
||||
first** in each product (`fld [-0x18]; fmul [-4]`), where ours loads the scalar first and re-reads it from
|
||||
memory. That is the two-pointer `point_from_line3d` body; `vm6.c`, which uses it, reaches January's 1968.
|
||||
|
||||
Family 4 occurs at two sites (ray origin and endpoint push), so this row is unreachable in this lane
|
||||
whatever happens to families 1-3.
|
||||
|
||||
`vm6p.c` re-gated this wave: **1952/66** (real file 1888), with `_valid_joint_rotation` simultaneously at
|
||||
1248/34 `[sha]` and all three sibling rows EXACT, guard clean. `parkcheck` on that object reports
|
||||
`DRIFT valid_joint_rotation 1216 -> 1248` and `DRIFT move_relax 1888 -> 1952`, so it cannot land even as a
|
||||
remeasure (R11 rejects zero-credit park remeasures that are not tied to a reopen). Fifteen shapes are spent
|
||||
(m1-m14 plus vm6p); **none this wave**.
|
||||
|
||||
## 4. `_biped_limp_noodle_relax_nodes_onto_environment` — allocation tie, confirmed by the census
|
||||
|
||||
Re-derived from `alndiff --include-equal` this wave: the guard is `cmp dl,cl; sbb cl,cl; inc cl`, i.e.
|
||||
`relaxation_complete = biped->biped.limp_body_current_relaxation_iterations >=
|
||||
biped->biped.limp_body_max_relaxation_iterations` (`[esi+0x47c]` / `[esi+0x47d]`), stored to `[ebp-1]` and
|
||||
returned on both exits — identical on both sides. The snapshot loop uses the same two strength-reduced IVs
|
||||
(`add eax,0x34`, `add ecx,0xc`) and the same two fresh pointer copies per trip (`mov edx,eax` / `mov edi,ecx`
|
||||
in January, `mov esi,eax` / `mov edi,ecx` in ours), i.e. the same struct-copy source shape. The whole
|
||||
residual is that January's loop scratch is EDX so ESI can carry `biped` across both calls, while ours takes
|
||||
ESI for the loop scratch and spills `biped` to `[ebp-0x10]`. Ours is the cheaper schedule (one store plus one
|
||||
reload versus a per-trip reload and store of `node_index`), so January took the option VC7's own cost model
|
||||
disprefers — consistent with w1's `rF` probe, which flipped the allocation by re-reading the two biped fields
|
||||
at the guard but emitted an extra compare and is therefore not January's source.
|
||||
|
||||
Detector sweep this wave: A23 cannot fire (our loop already carries its increment clause; w1's `while`
|
||||
respelling rD was byte-identical); A24 cannot fire (frames equal, no parameter home reused for a temp);
|
||||
A28/A31/A33/A35/A38/A42 have no site. laws_w3 A44 ("frame gaps that are allocation, not missing locals") is
|
||||
the classification. Ten shapes spent (rA, rB, rC, rD, rE, rF, rH2, rH3, rw1, rw2); **none this wave**.
|
||||
|
||||
## Proposals
|
||||
|
||||
None. The only lever that closes `valid_joint_rotation` and `move_relax_and_constrain_positions` is the
|
||||
`_point_from_line3d` COMDAT, whose OUT ruling is FINAL for this lane (brief §1; laws_w3 C2 and R14), and no
|
||||
header, config or `symbols.json` change is needed by any of the three rows.
|
||||
|
||||
## Reopen criteria (all unchanged from w3c)
|
||||
|
||||
* **`valid_joint_rotation`** — an owner ruling admitting an inline `point_from_line3d` that emits no COMDAT.
|
||||
`scratch/workers/biped_limp_noodle/vj2.c` is already strict EXACT; reopening it drifts the
|
||||
`move_relax_and_constrain_positions` park (1888/66 `34b872cd` -> `683135cea08a8197`, the call-site register
|
||||
ABI), so both must move in one commit. Do not re-spend j1/j3/j4/j5 or vp1/vp2/vp3.
|
||||
* **`move_relax_and_constrain_positions`** — (a) an authentic spelling for the first-node-block schedule AND
|
||||
(b) either the same owner ruling (then `vm6.c` is the base) or an admissible two-pointer helper spelling.
|
||||
Start from `scratch/workers/w3c_biped_limp_noodle/vm6p.c` (1952/66, guard-clean). Do not re-spend m1-m14.
|
||||
* **`relax_nodes_onto_environment`** — an authentic spelling that raises `biped`'s allocation weight above
|
||||
the loop index while still branching on the stored `relaxation_complete` boolean. Do not re-spend
|
||||
rA-rH3, rw1, rw2.
|
||||
@@ -0,0 +1,194 @@
|
||||
# `glow.obj`: Opus5 next-150K lane, wave n3a (structural park pass, 2026-09-15)
|
||||
|
||||
## Result
|
||||
|
||||
Nothing landed. `source/objects/widgets/glow.c` is **unchanged** (`git diff --stat` empty).
|
||||
Baseline and final real-file gate, with the `_point_from_line3d` guard: **exact 24 / residual 1 /
|
||||
unwritten 0**, row-for-row identical. Park drift 0, owner census identical to `build/base`,
|
||||
fake scan 0 leads.
|
||||
|
||||
The wave's brief was a structural park pass: run a fresh frame and relocation census on a parked
|
||||
`[size]`/`[relocs]` row on the theory that the recorded park premise would not survive it, as it did
|
||||
not for the five parks wave n1 closed. **Here the census confirms the premise**, and this wave turns
|
||||
the confirmation from an inference into a measurement. Three things are new:
|
||||
|
||||
1. a **measured** proof (shape v3) that no defined-C body can reach January's 1,744 bytes even when
|
||||
its frame and its entire 43-relocation census already match;
|
||||
2. the **refutation of the `precondition` branch** of the park's own reopen criterion;
|
||||
3. the **blocker set narrows from three to two** — the point-to-vector casts the w1 ledger counted as
|
||||
a blocker are now explicitly admitted by laws_w2 and laws_w3.
|
||||
|
||||
## Duplicate checks
|
||||
|
||||
Ledgers read: `glow_obj_opus5_250k_w3d_20260915`, `glow_obj_opus5_150k_w1_20260914`,
|
||||
`glow_obj_house_rule_reconciliation_20260908`, `glow_obj_opus_source_admission_hold_20260906`,
|
||||
`glow_obj_jonas_complete_hcea_packet_20260830`, `glow_obj_jonas_new_20260829`,
|
||||
`glow_obj_jonas_delete_20260829`, `glow_obj_jonas_nonuniform_spline_pair_20260827`,
|
||||
`glow_obj_jonas_parametric_line_leaf_20260821`. The w1 do-not-repeat list (four-statement knot copies,
|
||||
a bound marker pointer, cross-product reordering, the unnamed `cos`/`sin` form, any further defined-C
|
||||
repair aimed at exactness) was honoured; R13 binds it. `git log --all -- source/objects/widgets/glow.c`
|
||||
lists 18 commits, newest `db720270e`. `branch_sweep`: 13 unique blobs; the best historical blob
|
||||
(`aab61c21`) is exact 8 / unwritten 17 — no historical blob beats the current 24/1/0.
|
||||
|
||||
## Census (mandatory)
|
||||
|
||||
| | padded / meaningful / relocs / sha16 / frame |
|
||||
| --- | --- |
|
||||
| January target | 1744 / 1729 / 43 / `84720a5067d22512` / `sub esp,0xc4` |
|
||||
| real file (parked body) | 2528 / — / 55 / `fb7bb3c6b7236d62` / `sub esp,0xf4` |
|
||||
|
||||
### Frame census — the gap is a SURPLUS local, not a missing one
|
||||
|
||||
January's slot map, read off the three `nonuniform_cubic_spline_vector3d` argument `lea`s (pushes are
|
||||
right-to-left, so the last push before each call is the result pointer):
|
||||
|
||||
| range | size | local |
|
||||
| --- | ---: | --- |
|
||||
| `[ebp-0xc4] [-0xb8] [-0xac] [-0xa0]` | 48 | `sides[0..3]` |
|
||||
| `[ebp-0x94]` | 12 | `up` (result of spline 2) |
|
||||
| `[ebp-0x88]`, `[ebp-0x84]` | 4 + 4 | one spilled `real`; one strength-reduced pointer CSE (`lea ecx,[esi+ecx*2+0x22a]` at +0x18d) |
|
||||
| `[ebp-0x80] [-0x74] [-0x68] [-0x5c]` | 48 | `ups[0..3]` |
|
||||
| `[ebp-0x50] [-0x44] [-0x38] [-0x2c]` | 48 | `positions[0..3]`, passed **directly** as the spline's vector arguments |
|
||||
| `[ebp-0x20]` | 12 | `side` (result of spline 3) |
|
||||
| `[ebp-0x14]` | 4 | long marker index |
|
||||
| `[ebp-0x10] [-0xc] [-8] [-4]` | 16 | `knots[0..3]` |
|
||||
|
||||
Sum = 196 = `0xc4`. Spline 1's result pointer is `lea esi,[edi+0x2c]`: January splines straight into
|
||||
`particle->position`, so it has neither a `position` result local nor a vector staging array.
|
||||
|
||||
Ours is 244 = `0xf4`. The whole 48-byte difference is one object our source adds and January does not
|
||||
have: `real_vector3d position_vectors[4]`, plus the four-trip loop that fills it, which exist only so
|
||||
`real_point3d positions[]` never has to be cast to `real_vector3d *`. Measured directly below: removing
|
||||
that hunk alone (v2) takes the frame to `0xb8` and the size down 64 bytes; adding January's `delta` +
|
||||
`point_from_parametric_line` routing on top (v1) reproduces `sub esp,0xc4` exactly.
|
||||
|
||||
### Relocation census by target — nothing missing, twelve surplus constants
|
||||
|
||||
| relocation target | January | ours | delta |
|
||||
| --- | ---: | ---: | ---: |
|
||||
| `_display_assert` | 3 | 3 | 0 |
|
||||
| `_system_exit` | 3 | 3 | 0 |
|
||||
| `_nonuniform_cubic_spline_vector3d` | 3 | 3 | 0 |
|
||||
| assert file + predicate literals | 6 | 6 | 0 |
|
||||
| `__real@3f000000` (0.5f) | 14 | 20 | **+6** |
|
||||
| `__real@3e800000` (0.25f) | 7 | 10 | **+3** |
|
||||
| `__real@3f400000` (0.75f) | 7 | 10 | **+3** |
|
||||
| TOTAL | 43 | 55 | **+12** |
|
||||
|
||||
No missing call, no missing global, no missing literal: ours is a strict superset. `cos`/`sin` lower to
|
||||
`fcos`/`fsin` and carry no relocation; `cross_product3d`, `vector_from_points3d` and
|
||||
`point_from_parametric_line` are inlined and are relocation-invisible.
|
||||
|
||||
An interpolated `real_vector3d` costs three constant references, so the surplus decomposes exactly:
|
||||
+3 at 0.25f and +3 at 0.75f is one extra interpolated pair (the 2-marker path's `sides[1]`, `sides[2]`),
|
||||
and +6 at 0.5f is two extra interpolations (the two 3-marker sub-cases' interior side control).
|
||||
January's 2-marker arm spends 7 × 0.25f and 7 × 0.75f — positions(3) + ups(3) + knots(1) each — and each
|
||||
3-marker sub-case spends 7 × 0.5f on the same three objects. **Side controls are absent from January's
|
||||
constant budget entirely.**
|
||||
|
||||
## Does the census refute the park premise? No — and v3 proves it by measurement
|
||||
|
||||
Shapes (3 of the 5-shape budget; all scratch, the real file was never touched):
|
||||
|
||||
| shape | what it is | size / relocs / frame | verdict |
|
||||
| --- | --- | --- | --- |
|
||||
| real (parked) | defined sides, defined knots, staging array | 2528 / 55 / `0xf4` | baseline |
|
||||
| **v1** `scratch/workers/n3_glow/v1.c` | January's routing and casts (`delta` + `point_from_parametric_line`, named `sine`/`cosine`, knot copy last in the marker loop) but sides and knots still fully defined | 2544 / 55 / **`0xc4`** | frame exact; the whole remaining 800 B / 12-reloc gap is the side+knot initialisation |
|
||||
| **v2** `scratch/workers/n3_glow/v2.c` | the current parked body with ONLY the point→vector cast hunk (drop `position_vectors[4]` and `position`, spline straight into `particle->position`) | 2464 / 55 / `0xb8` | strictly closer, −64 B, 24 siblings unchanged |
|
||||
| **v3** `scratch/workers/n3_glow/v3.c` (measurement probe, not a proposed source form) | v1 with the interior side controls filled by bare struct copies — the cheapest defined fill, costing zero constants | 2336 / **43** / **`0xc4`** | frame and relocation census both match January exactly, and it is still **+592 bytes** |
|
||||
|
||||
v3 is the decisive measurement. Give the function January's frame and January's exact 43-relocation
|
||||
census, then fill `sides[0..3]` in the cheapest way C allows, and it still emits 592 bytes January does
|
||||
not contain — four inline `cross_product3d` expansions for the endpoint controls plus the interior
|
||||
copies. **No defined-C body can reach 1744/43.** The gap is not a repair that could be written more
|
||||
cheaply; it is code January never emitted, because January never gave those controls a value.
|
||||
|
||||
## The `precondition` branch of the reopen criterion is refuted
|
||||
|
||||
The park admits "precondition evidence", i.e. evidence that 2-/3-marker glows can never reach the side
|
||||
spline, which would make the read unreachable rather than indeterminate. That branch is dead:
|
||||
|
||||
- `glow->number_of_markers` is whatever `object_get_marker_by_name(object_index,
|
||||
definition->attachment_marker, glow->markers, MAXIMUM_GLOW_MARKERS)` finds on the model (glow.c:1240);
|
||||
`MAXIMUM_GLOW_MARKERS` is 5, so the range is 0..5 and the count is tag/model data.
|
||||
- Both call sites guard on `glow->number_of_markers > 1`, never `> 3`: `glow_trailing_particle_new`
|
||||
at glow.c:1167, and the `glow_normal_particle_update_position` loop at glow.c:1375/1381.
|
||||
- January's own assert inside the function is `glow->number_of_markers > 1` (glow.c:1083, January line
|
||||
1083, literal `glow->number_of_markers > 1`), not `> 3`; it is one of the three asserts in the
|
||||
relocation census.
|
||||
- January hand-wrote dedicated `case 2:` and `case 3:` arms with roughly 600 bytes of bespoke
|
||||
interpolation. A path the author believed unreachable does not get that.
|
||||
|
||||
The 2- and 3-marker paths are first-class reachable paths and the indeterminate reads are a live
|
||||
original defect, not dead code. No further wave should hunt a precondition.
|
||||
|
||||
## The blocker set narrows from three to two
|
||||
|
||||
The w1 ledger listed three blockers; the third is now admitted lane policy and must not be avoided:
|
||||
|
||||
- laws_w2 section B, "Admitted, so don't avoid them": *point-to-vector `(real_vector3d *)` casts*.
|
||||
- laws_w3 section B, "Newly ADMITTED": *`(real_point2d const *)&point3d` casts into 2D helpers
|
||||
(32 source sites, HCEA)*.
|
||||
|
||||
What remains is a single policy question: may this one function reproduce two reads of an indeterminate
|
||||
value from address-taken automatic arrays?
|
||||
|
||||
## Cross-build corroboration (evidence only, never a January byte proof)
|
||||
|
||||
HCEA's disasm-verified reconstruction of the shipped Xbox build
|
||||
(`...\halocea-review\src\blam\objects\widgets\get_particle_world_position.c`, 0x8380BB00) records the
|
||||
same two quirks independently of this campaign: the side-vector control points are never filled on the
|
||||
2-/3-marker paths, and the 3-marker interval-1 path reads `knot1` from the never-written knot scratch.
|
||||
|
||||
## Candidate, re-verified at this HEAD (`6ebd05a96`)
|
||||
|
||||
`scratch/workers/n3_glow/owner_candidate_n3a.c` — a byte-identical copy of
|
||||
`scratch/workers/glow/owner_candidate.c`, which is the **current real file** with only this one body
|
||||
replaced and two `/* BUG (preserved for exact matching): ... */` comments added:
|
||||
|
||||
- `gate.py source/objects/widgets/glow --source ... --all --forbid-emitted-symbol _point_from_line3d`
|
||||
→ **exact 25 / residual 0 / unwritten 0**; `_get_particle_world_position` EXACT at 1744. It closes
|
||||
the whole object and needs no header or config change (the packet w1 wanted for
|
||||
`_glow_trailing_particle_new` has landed; that row is exact at HEAD with the unchanged real body).
|
||||
- point guard: pass.
|
||||
- `scratch/parkcheck.py`: `DRIFT _get_particle_world_position 2528 55 → (1744, 43, 84720a5067d22512)` —
|
||||
drift only on the reopened park itself, to the target, which is the expected reopen signature.
|
||||
- owner census vs `build/base` and `build/split`: candidate-only `[]`, base-only `[]`.
|
||||
- `tools/fake_match_scan.py`: 0 review leads.
|
||||
|
||||
## Final real-file state
|
||||
|
||||
`exact 24 residual 1 unwritten 0 (of 25 listed)`; guard pass; `parks 1 drift 0`; owner census
|
||||
candidate-only `[]` / base-only `[]`; fake scan 0 leads; `git diff --stat` empty.
|
||||
|
||||
## Owner-ruling proposal (re-raised with the v3 measurement)
|
||||
|
||||
Admit, for `_get_particle_world_position` only, the reproduction of two original defects under the
|
||||
docs' `/* BUG (preserved for exact matching): ... */` form, then replace the parked body with the body
|
||||
in `scratch/workers/n3_glow/owner_candidate_n3a.c` and unpark it in a dedicated commit:
|
||||
|
||||
1. the 2- and 3-marker paths give **no** value to `sides[0..3]`, which the unconditional third
|
||||
`nonuniform_cubic_spline_vector3d` call then reads;
|
||||
2. on the 3-marker `parent_marker_index == 1` path the midpoint knot is written over `knots[2]` instead
|
||||
of `knots[1]` (`marker_time_index[1]` loaded at +0x2EA, midpoint stored at +0x5C6 into `[ebp-8]`,
|
||||
`[ebp-0xc]` read unwritten at +0x5D2), so `knots[1]` is never set.
|
||||
|
||||
Both are reads of an indeterminate value from an address-taken automatic array, which brief section 5
|
||||
lists among the undefined-behaviour exclusions. Supporting evidence: the frame and relocation censuses
|
||||
above; the v3 measurement that the cheapest defined fill is +592 bytes at January's own frame and
|
||||
relocation census; HCEA's independent shipped-build reconstruction naming both quirks; the refuted
|
||||
precondition branch; and a candidate that is strict EXACT, closes the object 25/25, loses no sibling,
|
||||
adds no owner and scans clean. Value: **1,744 padded bytes**, the last non-exact row in `glow.obj`.
|
||||
|
||||
If the owner declines, one optional zero-credit action is measured and ready: re-baseline the park to
|
||||
`scratch/workers/n3_glow/v2.c` (2464 / 55, frame `0xb8`, 24 siblings unchanged, owner census clean,
|
||||
fake scan clean). It is strictly closer than the current 2528 / 55 base and removes an invented
|
||||
`position_vectors[4]` staging array that exists only to dodge a cast the lane has since admitted. It
|
||||
carries zero strict credit and, being a parked-body edit, is the orchestrator's call; it is offered,
|
||||
not claimed.
|
||||
|
||||
## Reopen criterion (restated, narrowed)
|
||||
|
||||
An owner policy ruling admitting the two preserved defects above. The precondition branch is refuted
|
||||
and the cast branch is admitted, so no further defined-C repair and no further January-side evidence
|
||||
can move this row.
|
||||
@@ -0,0 +1,110 @@
|
||||
# hud_unit.obj — opus5 next-150K lane, wave n3a (structural park pass), 2026-09-15
|
||||
|
||||
Unit: `source/interface/hud_unit.c`. Worker notes: `scratch/workers/n3_hud_unit.md`.
|
||||
Scratch: `scratch/workers/n3_hud_unit/` (`w1.c/.obj` control, `v1/d1/d2/d3/d4` probes, `w1.aln`,
|
||||
`w1.full.txt`, `score.py`).
|
||||
|
||||
## Baseline and final state
|
||||
|
||||
| | baseline (HEAD `6ebd05a96`) | final |
|
||||
| --- | --- | --- |
|
||||
| gate | `== exact 21 residual 1 unwritten 0` | `== exact 21 residual 1 unwritten 0` |
|
||||
| `_point_from_line3d` guard | passes | passes |
|
||||
| parkcheck (`build/base/source/interface/hud_unit.obj`) | `parks 1 drift 0` | `parks 1 drift 0` |
|
||||
| fake_match_scan | 0 leads | 0 leads |
|
||||
| real file modified | — | **no** (`git diff --stat` empty) |
|
||||
|
||||
Nothing landed. Nothing was proposed for the orchestrator. The single non-exact row
|
||||
`_hud_render_unit_interface` is PARKED and was investigated in scratch only.
|
||||
|
||||
## `_hud_render_unit_interface` — NOT-LANDED, park premise reclassified
|
||||
|
||||
Target 3504 padded / 3493 meaningful / 102 relocs / sha16 `b82d575e1154cad1`.
|
||||
Park base (real file) 3472 / 102, gate tag `[size 3472!=3504, sha]`, struct-diff **127 blocks / 308 insns**.
|
||||
Frontier body `scratch/workers/hud_unit_messaging/hud_unit_candidate.c` (identical to
|
||||
`scratch/workers/w3c_hud_unit/w1.c`), re-gated at this HEAD: **3504 / 102, tag `[sha]` only**,
|
||||
struct-diff **41 blocks / 56 insns**, all 21 sibling rows still EXACT.
|
||||
**The `[size]` half of the park tag therefore describes the stale park BASE, not the frontier; it is
|
||||
not evidence of a structural source gap.**
|
||||
|
||||
### Census performed (method mandated by the wave brief)
|
||||
|
||||
1. **Relocation census by target** (`relocdiff --count-by-target --allow-structural`, w1 vs January):
|
||||
102 / 102, **every target row equal** across 38 distinct targets in identical order
|
||||
(`_local_player_count` 12, `_hud_draw_static_element` 8, `_fast_ftol_C` 6, `_game_time_get` 5, …).
|
||||
The only deltas are relocation ADDRESS shifts after the first code divergence (reloc 29,
|
||||
0x30b vs 0x30e) and the known `--source` literal-COMDAT naming artifact.
|
||||
⇒ no missing call, no missing global, no missing/extra re-fetch ⇒ **no missing statement**.
|
||||
2. **Frame census** (January `sub esp,0x424`, ours `sub esp,0x420`): aggregates deepest first —
|
||||
January `stack_buffer(512) unit_indices(72) unit_hud_indices(72) health_meter(104)
|
||||
absolute_placement(36) overcharge_meter(104) color(20)`; ours `stack_buffer(512) health_meter(104)
|
||||
unit_indices(72) unit_hud_indices(72) absolute_placement(36) overcharge_meter(104) color(20)`.
|
||||
Exactly two deltas: `health_meter` ranked 2nd instead of 4th, and January owns **one extra 4-byte
|
||||
scalar** (35 vs 34 dwords in −0x8c…−4), which is the entire frame gap.
|
||||
That scalar is a compiler staging cell, not a source local: at January `+0x55e fst dword [ebp-0x44]`
|
||||
ours emits `+0x573 fst dword [ebp-8]`, reusing the `draw_flags` home that January has spilled
|
||||
(`+0x3ac mov [ebp-8],ebx`, `+0x601`, `+0x630`) because it freed EBX for the `color[]` pointer IV.
|
||||
3. **Local-set and type census — new evidence this wave.** `DIA2Dump.exe -sym hud_render_unit_interface`
|
||||
on the HCEX SHIP PDB (brief §10.5) lists `unit_count`, `player_index`, `long unit_indices[0x12]`,
|
||||
`long unit_hud_indices[0x12]`, `auxilary_flags`, `aux_activated_when_disabled_flags`,
|
||||
`float auxilary_values[0x1]`, static `long overcharge_count`, `overcharge_meter`, `health_meter`
|
||||
(both `struct meter_hud_element_definition`), `unsigned long color[0x5]`,
|
||||
`struct hud_absolute_placement_definition absolute_placement`, `union point2d corner`.
|
||||
**Our reconstruction matches 1:1 in names, counts and types**; no local is missing or invented
|
||||
(`stack_buffer`/`return_eip` are January's debug stack-guard pair, absent from the 2011 build).
|
||||
`short value_scale` is independently 16-bit signed on both sides (16-bit `test`, `movsx` before
|
||||
`fild`) and matches the field type at `unit_hud_interface_definition.h:119`.
|
||||
|
||||
Instruction totals are 1062 vs 1062 and every diff block is a register/slot substitution.
|
||||
⇒ The census **refutes** every source-defect hypothesis the structural pass looks for (missing
|
||||
statement, extra/missing local, wrong width, wrong control flow) and **confirms** the park's own
|
||||
recorded verdict: register/x87 colouring plus one frame-rank decision.
|
||||
|
||||
### Probes (5, scratch-only, none landed, real file untouched)
|
||||
|
||||
| # | shape | measurement |
|
||||
| --- | --- | --- |
|
||||
| w1 | control: prior best body re-gated at this HEAD | 3504/102 `[sha]`, 41 blocks / 56 insns, frame 0x420 |
|
||||
| v1 | `health_meter` declared one scope out (B13, the `health_dont_show` if) | 3520/102 (**+16 B worse**), frame 0x420, rank unchanged |
|
||||
| d1 | diagnostic rename `health_meter`→`zz_meter` (never a landing; tests whether the rank is name-hash driven the way `.bss` order is) | 3504/102, identical 41/56, rank unchanged ⇒ **rank is NOT name-driven** |
|
||||
| d2 | `health_meter` declared in B1 (outer if, after `auxilary_values`) | 3504/102; order becomes `ui, uhi, abs, och, health, color` — the index arrays reach January's ranks 2-3 but `health_meter` overshoots to rank 6; 42/58 |
|
||||
| d3, d4 | `health_meter` declared in B6 (`hud_definition` block) / B5 (`while` body) | identical layout to d2; 41/56 and 42/58 |
|
||||
|
||||
**Law candidate (offered, not landed):** VC7's frame ranking of same-alignment aggregates is neither
|
||||
refs/size (w3c v2), nor lexical depth by one level (v1), nor the local's name (d1); it flips between
|
||||
"deepest" and "next-to-last" on whether the aggregate is declared inside the innermost if-chain that
|
||||
uses it (d2/d3/d4), and no setting of that switch reproduces January's intermediate rank.
|
||||
|
||||
### Rejected without building (with reason)
|
||||
|
||||
- Hand pointer walk / alias over `color[]` to force the IV — R16 and laws_w2 A5 counter-law.
|
||||
- `volatile`, barriers, operand permutations for x87 order, redundant stores — prohibited (brief §7);
|
||||
this residual is precisely the class such devices would fake.
|
||||
- `if (body_vitality < max_cutoff)` — refuted by the bytes: January `+0x727 test ah,1` tests C0 alone
|
||||
(`!(a >= b)`); an ordered `<` compiles to `test ah,5`. Already ruled a semantic regression 20260904.
|
||||
- `color[]`/`overcharge_meter` declared with initializers at the top of B9 — refuted by the bytes:
|
||||
January initialises `color` (`+0x46e`) after `_game_engine_running` (`+0x3e1`) and after the
|
||||
`overcharge_meter` copy (`+0x430`), so the nested block is January's own C89-forced shape.
|
||||
- `health_meter` as a declaration initializer — impossible in C89 here, and January's `rep movsd`
|
||||
(`+0x70e`) follows the `value_scale` test (`+0x6eb`), which is our current form.
|
||||
- A1 static linkage, A23/A24/A28/A40 detectors — do not fire (statics already static and covered by the
|
||||
2026-09-15 census; all helpers out-of-line on both sides; the only parameter has no packed temp).
|
||||
|
||||
### Reopen criterion (supersedes the w3c wording)
|
||||
|
||||
Reopen only when a source-level lever (a) stops VC7 keeping `hud_unit` in EBX across the shield
|
||||
`draw_flags` chain — reproducing January's `+0x380 mov edx,[ebp-0x24]` rematerialisation, which alone
|
||||
yields the `color[]` pointer IV, the `draw_flags` spill and the extra `fast_ftol_C` staging cell
|
||||
(frame 0x424) — AND (b) ranks `health_meter` between `unit_hud_indices` and `absolute_placement`;
|
||||
refs/size, lexical scope and the local's name are now all measured inert or overshooting. A C2
|
||||
frame-allocator decode is the natural next evidence source. The park's own clause ("reopen only for new
|
||||
authentic January source/type/compiler-context evidence, not spelling or allocation searches") keeps
|
||||
this otherwise closed.
|
||||
|
||||
### Orchestrator options (zero credit, not proposed)
|
||||
|
||||
The park BASE could be re-measured to `scratch/workers/n3_hud_unit/w1.c` (3504 / 102 — January's exact
|
||||
size and relocation count, 41 blocks / 56 insns versus the current base's 127 / 308), which would also
|
||||
retire the misleading `[size 3472!=3504]` gate tag. This was already offered by waves w1 and w3c and not
|
||||
taken; R11 applies (strictly-closer body that changes size, not tied to a reopen). No header, config or
|
||||
`symbols.json` change is needed for this unit.
|
||||
@@ -0,0 +1,206 @@
|
||||
# `input_xbox.obj` structural park pass — opus5 next-150K house-clean lane, wave n3a (2026-09-15)
|
||||
|
||||
## Scope, baseline and outcome
|
||||
|
||||
- Worktree `C:\halo-worktrees\opus5-150k-house-clean-20260914`, branch `opus/next-150k-house-clean-20260915`,
|
||||
HEAD `6ebd05a96`, lane baseline `ae10935da`.
|
||||
- Owned source: `source/input/input_xbox.c` only. No header, config, build, tool or other source was touched and
|
||||
nothing was committed. Both remaining non-exact rows are parked in `config/parked.json`, so every measurement was
|
||||
made in scratch; the real file is byte-unchanged (`git diff --stat -- source/input/input_xbox.c` empty).
|
||||
- **Baseline correction.** The wave prompt listed `== exact 24 residual 3` with
|
||||
`_input_update_analog_button_state` residual. That is stale: the w3d park reopen landed in the lane baseline
|
||||
commit `ae10935da`, so at this HEAD the measured real-file gate (with the `_point_from_line3d` guard) is
|
||||
|
||||
== exact 25 residual 2 unwritten 0
|
||||
|
||||
and `config/parked.json` holds only two input_xbox entries. There is no third row and no credit available for it.
|
||||
- Final real-file gate: identical to the baseline, `== exact 25 residual 2 unwritten 0`.
|
||||
`scratch/parkcheck.py`: 2 parks, 0 drift. `tools/fake_match_scan.py`: 0 review leads.
|
||||
- Nothing landed; nothing proposed. Both rows were re-censused from January's bytes and both park premises were
|
||||
found structurally refuted, but what survives the refutation is a C2 register-allocation tie, which laws_w2 R11
|
||||
and brief section 5 both forbid spending further on.
|
||||
|
||||
| function | January padded / relocs / sha16 | real file | best scratch body | outcome |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| `_input_get_device_states` | 1232 / 28 / `56316233dc2ab683` | 1280 / 32 / `b7cded6529564446` | 1216 / 28 (`n0`, = w2 `fn/d2.c`) | NOT LANDED — 1 instruction / 1 encoding byte |
|
||||
| `_input_update_keyboard_devices` | 640 / 49 / `80bcd2f76c52c728` | 640 / 51 | 640 / 49 `[sha]` (`n0`, = w2 `fn/k3.c`) | NOT LANDED — L3 pin + the same L2 tie |
|
||||
| `_input_update_analog_button_state` | 48 / 0 / `5850a17e99380c54` | **EXACT** | — | SKIPPED-EXACT (landed at `ae10935da`) |
|
||||
|
||||
Ledgers read: all 13 `input_xbox_obj_*.md`, in particular `input_xbox_obj_device_keyboard_pollers_wave_20260904.md`
|
||||
(owns both park criteria), `input_xbox_obj_opus5_150k_w2_20260914.md` (shapes d1-d6, k1-k4) and
|
||||
`input_xbox_obj_opus5_250k_w3d_20260915.md` (hd1, e1-e6, hd_d6, kA/kB/kE/kF and laws L1-L3) — w3d ran the identical
|
||||
structural park-pass method on these same two rows earlier today. Also `scratch/w2/laws_w2.md` (R11 rejects the
|
||||
`input_xbox d2/k3` zero-credit park remeasures by name), `scratch/w3/laws_w3.md`, and the next-150K worker brief.
|
||||
`git log --all -- source/input/input_xbox.c`: 23 commits, latest `ae10935da`.
|
||||
`branch_sweep.py source/input/input_xbox`: 18 unique blobs; the current file is the best (exact 25).
|
||||
|
||||
Worker notes with the full tables: `scratch/workers/n3_input_xbox.md`.
|
||||
Scratch: `scratch/workers/n3_input_xbox/` (`sub.py`, `mk.sh`, `real.obj`/`real.gate.txt`, the combined structural
|
||||
base `n0.c`/`n0.obj`/`n0.gate.txt`, `full.txt` = the complete aligned instruction dump).
|
||||
|
||||
---
|
||||
|
||||
## 1. `_input_get_device_states` — park premise refuted; one instruction remains
|
||||
|
||||
### Recorded park criterion (quoted)
|
||||
|
||||
> Typed January Xbox gamepad/memory-unit hotplug and state poller reconstructed with genuine XDK 3911 API/layout
|
||||
> declarations, semantic private owners, named device flags and exact natural lookup-table ownership. First natural
|
||||
> pointer/count implementation retains frame, register, table-hoisting and scheduling differences: 1280 versus 1232
|
||||
> padded bytes and 32 versus 28 relocations. This is not a proven narrow compiler tie or a byte-exact claim. …
|
||||
> Reopen for new authentic ABI/type/control-flow evidence, not equivalent-expression trials.
|
||||
|
||||
### Census (run before any shape)
|
||||
|
||||
**tinfo.** January has 28 relocations. `.bss` `_input_globals` at **+282** (`raw_gamepad_states`), **+316**
|
||||
(`gamepad_handles`), **+332** (`gamepad_states`); the two lookup tables `_gamepad_analog_button_indices` (@0x259)
|
||||
and `_gamepad_binary_button_masks` (@0x2c7) are referenced at `symbol+0` — January builds no displaced table base.
|
||||
There is no relocation to `_update_ticks` or `_input_update_analog_button_state`: January inlines both, as we do.
|
||||
|
||||
**Frame census.** January `sub esp,0x30`; the real body `sub esp,0x44` — five extra cells. January's slots:
|
||||
`[ebp-8]` insertions, `[ebp-0x10]` removals, `[ebp-0x14]`/`[ebp-0x18]` the memory-unit pair, `[ebp-4]`
|
||||
`device_change_flags`, `[ebp-0xc]` the hot-plug count, `[ebp-0x30]` the `XINPUT_STATE`; then in the poll loop the
|
||||
four homed induction variables `[ebp-0xc]` = raw_gamepad_states, `[ebp-4]` = gamepad_states, `[ebp-8]` =
|
||||
gamepad_handles, `[ebp-0x10]` = count, all four rehomed in the loop tail at 0x492-0x4b4. The real body additionally
|
||||
materialises and homes two strength-reduction table bases; that is exactly the five-cell surplus.
|
||||
|
||||
**Relocation census by target** (`relocdiff --count-by-target`, real body, 28 vs 32):
|
||||
|
||||
| target | January | ours |
|
||||
| --- | ---: | ---: |
|
||||
| `_input_globals+282` | 1 | 0 |
|
||||
| `_input_globals+284` | 0 | 1 |
|
||||
| `_input_globals+316` | 2 | 4 |
|
||||
| `_input_globals+332` | 1 | 2 |
|
||||
| `_input_globals+340` | 0 | 1 |
|
||||
| every other target | equal | equal |
|
||||
|
||||
### Verdict on the premise: REFUTED
|
||||
|
||||
The premise attributes the frame, table-hoisting and relocation gaps to "the first natural pointer/count
|
||||
implementation". They are a source defect, not a property of natural source: the pointer-walk spelling builds
|
||||
`&array[0].field` bases (`+284`, `+340`) and re-materialises `+316`/`+332`. The w2 body `fn/d2.c` — indexed `for`
|
||||
loops over `input_globals.<array>[gamepad_index]`, with the gamepad insert/remove work in its own block —
|
||||
reproduces January's frame **and** its relocation census exactly. Re-measured this wave as `n0`
|
||||
(`fn/d2.c` + `fn/k3.c` spliced into the current real file, sha256
|
||||
`e329841cb9cb7f4320ffe642b0b197ec5743962256f58027996b7c7df2d2c05c`): gate `== exact 25 residual 2 unwritten 0`,
|
||||
row `residual 1232 _input_get_device_states [size 1216!=1232, sha]` — the `[relocs]` tag is gone and no exact row
|
||||
is lost.
|
||||
|
||||
### What remains: one instruction
|
||||
|
||||
`alndiff` of `n0.obj` reports target 400 instructions versus ours 385 plus 15 trailing pad nops — 385 aligned
|
||||
instructions of which exactly **one** differs, a register-role swap inside the binary-button loop's inlined
|
||||
`update_ticks`:
|
||||
|
||||
T 2c0 mov bl,[ebp-0x2c] 2c3 lea eax,[esi+0x18] 2c6 mov edx,masks 2cb mov esi,8
|
||||
T 2d0 test byte [edx],bl 2d2 je 2d4 movzx ecx,[eax] 2d7 inc ecx 2d8 cmp ecx,0xff (81 F9, 6 B)
|
||||
T 2e9 mov [eax],cl 2eb inc eax 2ec inc edx 2ed dec esi 2ee jne
|
||||
O 2c0 mov bl,[ebp-0x2c] 2c3 lea ecx,[esi+0x18] 2c6 mov edx,masks 2cb mov esi,8
|
||||
O 2d0 test byte [edx],bl 2d2 je 2d4 movzx eax,[ecx] 2d7 inc eax 2d8 cmp eax,0xff (3D, 5 B)
|
||||
O 2e8 mov [ecx],al 2ea inc ecx 2eb inc edx 2ec dec esi 2ed jne
|
||||
|
||||
January puts the pointer induction variable in EAX and the helper's 32-bit temp in ECX; we reverse them. The entire
|
||||
1217-versus-1216 meaningful gap (and therefore the 16-byte padded gap) is the one encoding byte between
|
||||
`cmp ecx,imm32` and the EAX short form `cmp eax,imm32`. Everything else matches, including the `mov bl,[ebp-0x2c]`
|
||||
wButtons hoist before the loop, the ESI counter, the EDX mask pointer, all four homed IVs and the entire
|
||||
`fix_dead_zone` tail.
|
||||
|
||||
### Why there is no source lever (evidence, not assertion)
|
||||
|
||||
- In the **analog**-button loop immediately above, our build already matches January byte for byte with the roles
|
||||
January wants: IV in EAX (`lea eax,[esi+8]`, used at `[eax-8]`, `[eax]`, `[eax+8]`), helper temp in ECX. Only the
|
||||
**binary** loop — whose body is nothing but the inlined helper call — swaps.
|
||||
- Nine distinct spellings of that loop have now been measured across three waves and all swap identically: the
|
||||
pointer/count `while` in the real file today, an indexed `for` (d1/d2), a separate `short` index (e1), the mask
|
||||
test with operands swapped (e2), `buttons[button_index + FIRST_GAMEPAD_BINARY_BUTTON]` (e3), a `byte *` base with
|
||||
`[button_index]` (e4, 1248), a one-use pointer local bound before the call (e5), a pointer/count `while` rewrite
|
||||
(e6, 1248), and the `- FIRST_GAMEPAD_BINARY_BUTTON` index base (d6). `fn/d6.c` reaches 1232 only by acquiring
|
||||
three new hunks: it loses the BL wButtons hoist (`mov al,[ebp-0x2c]` reloaded inside the loop) and gains a second
|
||||
EAX/ECX flip at +0x330 — confirmed here by `alndiff` of `hd_d6.obj`.
|
||||
- Both plausible origins for the IV (a genuine source-level pointer variable, and a strength-reduced index
|
||||
expression) give the same swap, so the "which temp was created first in the IL" explanation has no source handle.
|
||||
- **New hypothesis tested and refuted this wave.** Under the A1 static-linkage law, a `static` `update_ticks` could
|
||||
inline with different IL. `scratch/pdb200-current/pdb_symbols.json` contains the January public `_update_ticks`
|
||||
(and `_fix_dead_zone`), so the helper has external linkage exactly as our source declares it. Dead end; recorded
|
||||
so no later wave re-spends it.
|
||||
|
||||
Classification: **C2 register-allocation tie** (w3d law L2), not structural. Zero new source shapes were spent this
|
||||
wave: the w2/w3d budget of 13 is already spent and brief section 5 caps post-tie work at two.
|
||||
|
||||
**Not proposed.** Re-baselining the park from 1280/32 to 1216/28 is a zero-credit park remeasure that also changes
|
||||
size — rejected by laws_w2 **R11** by name for this exact body (`input_xbox d2/k3`) and reaffirmed in laws_w3 B.
|
||||
No coupled A8 re-baseline is required either: the real file is untouched and `parkcheck.py` reports 0 drift.
|
||||
|
||||
**Reopen criterion.** A measured source lever that moves which of EAX/ECX the C2 allocator gives to a pointer
|
||||
induction variable versus an inlined helper's 32-bit temp, in a loop whose body is only that helper call — not an
|
||||
equivalent-expression permutation. Then re-gate `scratch/workers/n3_input_xbox/n0.c` (equivalently w3d `hd1.c`),
|
||||
which is one instruction from strict exact.
|
||||
|
||||
---
|
||||
|
||||
## 2. `_input_update_keyboard_devices` — relocation premise refuted; pin + the same tie remain
|
||||
|
||||
### Recorded park criterion (quoted)
|
||||
|
||||
> Typed January debug-keyboard hotplug, key-tick aging and SDK keystroke queue/ring handling using the genuine XDK
|
||||
> keystroke type, semantic modifier/key constants and exact private ASCII/virtual-key tables. Natural source reaches
|
||||
> the 640-byte target extent but retains scheduling and relocation differences (51 versus 49); no exact or general
|
||||
> equivalence claim. … Reopen only for new authentic source or ABI/control-flow evidence.
|
||||
|
||||
### Census
|
||||
|
||||
**Frame.** No `sub esp` gap; every slot agrees. `[ebp-8]`/`[ebp-4]` are insertions/removals in the hot-plug block;
|
||||
the `struct key_stroke key` then occupies `[ebp-8]` (modifier_flags), `[ebp-7]` (ascii_code), `[ebp-6]` (key_code),
|
||||
and the `XINPUT_DEBUG_KEYSTROKE` sits at `[ebp-4]`. No slot is missing or extra on either side.
|
||||
|
||||
**Relocations by target** (49 vs 51): `_input_globals+568` (`key_ticks`) **5 vs 6** and `_input_globals+672`
|
||||
(`key_latches`) **2 vs 3**; every other target equal. January walks **one** induction variable over `key_ticks` and
|
||||
reaches `key_latches` through the constant displacement `+0x68` (`mov cl,[eax+0x68]`, `movzx ecx,[eax]`).
|
||||
|
||||
### Verdict on the premise: REFUTED for the relocation half
|
||||
|
||||
The 51-versus-49 gap is not scheduling; it is a `long key_code` loop that keeps a second array base alive. w2's
|
||||
`fn/k3.c` (a `short key_code` `for` loop indexing both arrays, with the ascii store as a ternary) reproduces
|
||||
January's single induction variable and measures **640 / 49** — January's exact size and exact relocation count.
|
||||
Re-measured in `n0` this wave: `residual 640 _input_update_keyboard_devices [sha]`. The park's "extent already
|
||||
reached" half stands; only `[sha]` is left.
|
||||
|
||||
### What remains
|
||||
|
||||
`alndiff` against `n0.obj`: target 193 instructions, ours 197, in two hunks.
|
||||
|
||||
1. **Byte-constant unification (w3d law L3).** Ours emits `push ebx` in the prologue plus `mov ebx,0xff`, then
|
||||
`cmp eax,ebx` / `mov eax,ebx` in the tick loop and `mov [ebp-7],bl` for the ascii `NONE` arm. January
|
||||
shrink-wraps `push ebx` to +0x27 and `pop ebx` to +0xd7 (EBX is needed only in the hot-plug block) and
|
||||
rematerialises the constant three times: `cmp ecx,0xff`, `mov ecx,0xff`, `mov byte [ebp-7],0xff`. w3d's `kA`/`kF`
|
||||
proved the cause is the *third* use of the byte value 0xFF — two inside the inlined `update_ticks` plus
|
||||
`key.ascii_code = NONE`; remove it and VC7 rematerialises exactly as January does. The third use is a genuine
|
||||
`NONE`, so no admissible spelling avoids it. Checked this wave: `struct key_stroke::ascii_code` is `byte`
|
||||
(`source/input/input.h:188`), so `(byte)NONE` and a bare `NONE` are the same IL constant 255 — consistent with
|
||||
w3d's cast-free `kB`, where the pin stayed. A `char` field would give a distinct IL constant, but
|
||||
`mov byte [ebp-7],0xff` is identical for both widths, so there is no January byte evidence for a header packet.
|
||||
2. **The same L2 EAX/ECX swap** in the inlined `update_ticks`. `kA` shows it survives even when the pin is removed,
|
||||
so this row cannot close on the pin alone.
|
||||
|
||||
Zero new source shapes were spent (w2 k1-k4 plus w3d kA/kB/kE/kF = 8; `kE` proved the `short key_code`).
|
||||
|
||||
**Not proposed** (laws_w2 R11: the `k3` park remeasure was already rejected as zero credit).
|
||||
|
||||
**Reopen criterion.** (a) a source lever that stops VC7 unifying a byte constant across a loop and a later byte
|
||||
store — or January-side evidence that `key_stroke::ascii_code` is `char` — **and** (b) the L2 allocator lever the
|
||||
`_input_get_device_states` row needs; then re-gate `scratch/workers/n3_input_xbox/n0.c`.
|
||||
|
||||
---
|
||||
|
||||
## 3. Conclusion for the orchestrator
|
||||
|
||||
1. `input_xbox.obj` is **25 exact / 2 residual / 0 unwritten** at this HEAD, not 24/3. Please correct the board row
|
||||
for `_input_update_analog_button_state`; it is exact and unparked since `ae10935da`.
|
||||
2. Both remaining park premises are structurally refuted, and both structural fixes already exist in scratch and
|
||||
measure at January's frame and relocation counts (`n0.c`). Neither is landable or proposable today: R11 forbids
|
||||
the zero-credit remeasure, and the surviving difference in both rows is the same C2 allocator role swap.
|
||||
3. `_input_get_device_states` is the single cheapest large row known in this object — **one encoding byte**
|
||||
(1232 padded) behind a lever that nine measured spellings have failed to move. If any future wave measures a
|
||||
source lever for "pointer IV versus inlined-helper temp" register roles, this row and half of
|
||||
`_input_update_keyboard_devices` close immediately from `n0.c`.
|
||||
@@ -0,0 +1,142 @@
|
||||
# `main.obj` opus5 next-150K lane, wave n3a - structural park pass (2026-09-15)
|
||||
|
||||
Worker `n3a:main`. Unit `source/main/main.c`. **Real file unchanged** (`git diff --stat -- source/main/main.c`
|
||||
empty). Per-function report blocks: `scratch/workers/n3_main.md`. Candidates and micro-labs:
|
||||
`scratch/workers/n3_main/` (`f1.c`, `f2.c`, `f4.c`, `s1.c`, `s2.c`, `w1.c`, `lab/sf.c`, `lab/sf2.c`, `lab/wc.c`).
|
||||
The previous wave's candidates (`scratch/workers/w3d_main/`) survive and were reused, not re-derived.
|
||||
|
||||
## Baseline and final
|
||||
|
||||
`gate.py source/main/main --all --forbid-emitted-symbol _point_from_line3d`:
|
||||
**baseline == final == `exact 88 residual 6 unwritten 1`**; `_point_from_line3d` guard passed;
|
||||
`scratch/parkcheck.py` reports 5 parks / drift 0; `tools/fake_match_scan.py` 0 review leads.
|
||||
Nothing landed. Every target is PARKED (or owner-blocked) and none reached strict EXACT.
|
||||
|
||||
Duplicate prevention: read `main_obj_opus5_250k_w3d_20260915` (the immediately preceding wave on this unit),
|
||||
`main_obj_opus5_150k_w1_20260914`, `main_obj_opus5_100k_waveD_20260914`,
|
||||
`main_obj_natural_state_and_render_packet_20260909`, `main_obj_lifecycle_and_fuzzy_reconstruction_20260909`,
|
||||
`main_obj_jonas_window_count_rejection_20260828`, `main_obj_jonas_crash_policy_closeout_20260826`,
|
||||
`main_obj_tiny_geometry_input_closeout_20260901`, plus `scratch/workers/w3d_main.md`.
|
||||
|
||||
## Per-function outcomes
|
||||
|
||||
| Function | Padded | Baseline (parked) | Best measured | Verdict |
|
||||
| --- | ---: | --- | --- | --- |
|
||||
| `_main_frame_rate_debug` | 544 | 528 / 51 | **544 / 52** (`f1.c`: size AND relocation count both == January) | source form refuted by a new law |
|
||||
| `_main_get_window_count` | 64 | 64 / 5, objdiff 79.2 % | micro-lab `lab_long`: 61 meaningful / 19 insns / 5 relocs == January | park premise REFUTED; owner-blocked |
|
||||
| `_compute_subframe_counts` | 112 | 112 / 4, objdiff 94.3 % | unchanged | park premise CONFIRMED (19 spellings) |
|
||||
| `_main_game_render` | 448 | 464 / 29 | w3d `gr_v4.c` 464 / 29 | census re-verified; no new lever |
|
||||
| `_main_update_time` | 1440 | 1440 / 118 | w3d `ut_v10.c` 1440 / **117** | re-baseline still pending from w3d |
|
||||
| `_main_crash` | 16 | UNWRITTEN | - | OWNER-BLOCKED (NULL-deref UB) |
|
||||
|
||||
## `_main_frame_rate_debug` - the missing relocation is closed, and the residual is now proved unreachable
|
||||
|
||||
Census (re-verified): frame `sub esp,0x214` identical; from 0x70 to the end (86 instructions) w3d's `frd_v2.c` is
|
||||
byte-identical to January; the only relocation row missing was a fourth `_global_screenshot_count+902`
|
||||
(`framerate_sample_index`). January's decoded control flow holds **two distinct copies** of
|
||||
`sample_index = global_screenshot_count.framerate_sample_index;` - one at 0x56 reached by the `!framerate_reset`
|
||||
edge (falling into the second `debug_frame_rate` test) and one at 0x6a reached by the `framerate_reset &&
|
||||
debug_frame_rate` edge (falling straight into the sample body, the redundant test threaded away) - laid out
|
||||
**after** the clear block.
|
||||
|
||||
**New measured law (n3a-1, identical-arm merge).** With everything else in the function held fixed, VC7 13.00.9254
|
||||
merges two textually identical assignment arms of the same if/else tree into a single block in every spelling
|
||||
except the one where both copies are `then` arms:
|
||||
|
||||
| shape | source | size / relocs | copies kept |
|
||||
| --- | --- | --- | ---: |
|
||||
| `f1.c` | `if (!reset) S else if (debug) S else CLEAR` | **544 / 52** | 2 |
|
||||
| `f2.c` | `if (reset && !debug) CLEAR else if (!reset) S else S` | 544 / 51 | 1 |
|
||||
| `f4.c` | `if (!reset) S else if (!debug) CLEAR else S` | 544 / 51 | 1 |
|
||||
| w3d `frd_v2/v4/v5/v6` | nested both ways, `&&`, `\|\|` | 544 / 51 | 1 |
|
||||
|
||||
Block layout follows source arm order in all of them (confirms laws_w3 A44). That settles the row: January's
|
||||
layout puts the clear block first, which forces `S` into the outer `else` position, and an `else`-arm `S` always
|
||||
merges. Keeping two copies (f1) forces them **before** the clear block. The two requirements are mutually
|
||||
exclusive in C, so no source shape in this family reaches January's bytes. `f1.c` is nonetheless the first body
|
||||
whose size AND relocation count both equal January's; it is **not** proposed for landing because its duplicated
|
||||
`else if` arm is not a spelling a programmer would write.
|
||||
|
||||
## `_main_get_window_count` - the recorded park premise is refuted
|
||||
|
||||
Recorded criterion (`config/parked.json`): *"Ordinary source produces a 79.210526 percent residual because VC7
|
||||
reorders the repeated local_player_count calls and branch tails ..."*. That is not what the bytes say.
|
||||
|
||||
January returns a **32-bit** value on all three paths: `mov eax,1` (0x12), `mov eax,4` (0x2e) and
|
||||
`call _local_player_count; movsx eax,ax; ret` (0x34..0x3c). Our `short main_get_window_count(void)` emits
|
||||
`mov ax,1`, `mov ax,4` and a tail `jmp _local_player_count` - reproduced exactly by micro-lab `lab_short`
|
||||
(`scratch/workers/n3_main/lab/wc.c`). Therefore **January's definition returns `long`** (laws_w2 A3c return-width
|
||||
detector applied to constant returns). `lab_long` is 61 meaningful bytes / 19 instructions / 5 relocations,
|
||||
identical to January on size and on relocation identity; the single remaining difference is that January keeps the
|
||||
merged `return 1;` block at the first return's source position and branches backward into it, while our build sinks
|
||||
it to the function end (laws_w3 A43 cross-jump-survivor family, a recorded negative; `lab_long_single`, the
|
||||
single-exit result-variable form, is byte-identical to `lab_long`).
|
||||
|
||||
The fix is blocked, and the block was measured rather than assumed:
|
||||
- `long` on the definition alone does not compile - `scratch/workers/n3_main/w1.c` gives
|
||||
`error C2371: 'main_get_window_count' : redefinition; different basic types`, `main_runtime.h(17)`.
|
||||
- January's **callers declare it `short`**: in `build/split`, `_interface_draw_screen` calls it twice and both
|
||||
times compares `cmp ax, 1`; `__rasterizer_window_end` does the same at +0x34. A `long` prototype makes those
|
||||
32-bit compares, and `_interface_draw_screen` (928), `_rasterizer_dynamic_geometry_begin` (256) and
|
||||
`_rasterizer_screen_effect_set_texture_transforms` (2128) are EXACT today.
|
||||
|
||||
So January's own source carried a cross-TU declaration mismatch. A header-only change trades 3,312 exact bytes for
|
||||
at most 64, which brief section 7 forbids outright. Filed as type-fidelity evidence and an owner question; the
|
||||
exact proposed text and the complete consumer list are in `scratch/workers/n3_main.md`.
|
||||
|
||||
## `_compute_subframe_counts` - park premise confirmed and narrowed
|
||||
|
||||
Census: no frame; 4 relocations identical; exactly one block differs - January materialises the loop-body
|
||||
predicate (`cmp esi,edi; setl al; test al,al; je`) where ours folds it into `jge`. 19 spellings were measured
|
||||
(two in-tree candidates plus two micro-lab batches, `lab/sf.c` and `lab/sf2.c`). Nothing natural materialises the
|
||||
predicate: `long`/`boolean` temporaries in and out of the loop, `!= FALSE`, `== TRUE`, `| 0`, `?: TRUE/FALSE`,
|
||||
a `(boolean)` cast, the negated reversed comparison, `short` counters and an inlined `static __inline` predicate
|
||||
all fold to `jge` (the inline predicate additionally emits a candidate-only COMDAT, R14). The three spellings that
|
||||
do materialise are all inadmissible: `(a<b) & (c>0)` (two `setcc` rows), `(boolean)(a<b) & (boolean)TRUE`
|
||||
(`setl dl; test dl,1` - an R7 representation cast and the wrong test form), and inventing a second use of the
|
||||
boolean. `horizontal - vertical < 0` emits `sub esi,ecx` and is refuted.
|
||||
|
||||
Byte-inert hygiene fact for whoever reopens this park: the plain `while (vertical*horizontal<num_players) {...}`
|
||||
spelling (`s2.c`) is byte-identical to the parked body's hand-rotated `if (num_players>1) do {} while (...)`,
|
||||
because VC7 rotates the loop itself and constant-folds the preheader test to `cmp ebx,1; jle`.
|
||||
|
||||
## `_main_game_render` and `_main_update_time`
|
||||
|
||||
Both censuses were re-run and reproduce w3d's exactly, so nothing new was spent on them.
|
||||
|
||||
`_main_game_render`: frame identical, one relocation row differs (`_observer_get_camera` 1 vs 2), instructions
|
||||
0..66 byte-identical; the two remaining differences are one defect - January stores the `observer` call result to
|
||||
its home (`mov [ebp-0x14],eax` at 0xfc) which makes the shared tail six instructions, so VC7 does not tail-duplicate
|
||||
it into the film-playback arm; ours forwards EAX (five instructions) and duplicates. HCEA
|
||||
(`blam/main/main_game_render.c`, a flat else-if chain with a call in every arm - refuted by w3d's gr_v2 at 480/30)
|
||||
and Stian (`main/main.c:4224`, one shared call and `camera = NULL;` at the loop top - what `gr_v4.c` already has)
|
||||
were re-read this wave; neither reads the camera after the loop, so w3d's `lab_d` mechanism has no source support
|
||||
and would be a synthetic lifetime anchor.
|
||||
|
||||
`_main_update_time`: w3d's `ut_v10.c` remains 1440 / **117** (size and relocation identity both equal to January,
|
||||
27 register-allocation blocks left) against the parked 1440 / 118. The zero-credit re-baseline proposal from
|
||||
w3d is still outstanding.
|
||||
|
||||
## Proposals
|
||||
|
||||
1. **No park reopen** - nothing reached strict EXACT.
|
||||
2. Still outstanding from w3d (not re-litigated here): the zero-credit park re-baselines of `_main_update_time`
|
||||
to `scratch/workers/w3d_main/ut_v10.c` (1440/117) and `_main_frame_rate_debug` to
|
||||
`scratch/workers/w3d_main/frd_v2.c` (544/51). `scratch/workers/n3_main/f1.c` is closer still on relocations
|
||||
(544/52) but is withheld on credibility grounds.
|
||||
3. Owner question only (does not pay for itself): the `long main_get_window_count(void)` return-type fidelity
|
||||
packet described above.
|
||||
4. No header or config change is requested by this wave.
|
||||
|
||||
## Reopen criteria
|
||||
|
||||
- `_main_frame_rate_debug`: a source form that keeps two distinct `framerate_sample_index` load blocks AND lays
|
||||
them after the clear block. Law n3a-1 says that combination is unreachable from C; reopen only on a new
|
||||
compiler mechanism, not another CFG spelling.
|
||||
- `_main_get_window_count`: an owner ruling permitting the `long` definition with a `short` view preserved in
|
||||
interface.c, rasterizer_xbox_draw_primitives.c and rasterizer_xbox_screen_effect.c; then only the merged
|
||||
`return 1` block placement (A43) remains.
|
||||
- `_compute_subframe_counts`: a natural spelling - no representation cast, no invented second use, no bitwise
|
||||
`&` of two comparisons - that makes VC7 emit `setl al; test al,al; jcc` for a simple `<` in a bottom-tested
|
||||
loop, or authoritative January source.
|
||||
- `_main_game_render`, `_main_update_time`, `_main_crash`: unchanged from w3d.
|
||||
@@ -0,0 +1,173 @@
|
||||
# `motion_sensor.obj` — opus5 next-150K lane, wave n3a (2026-09-15), STRUCTURAL PARK PASS
|
||||
|
||||
Unit `source/interface/motion_sensor`. Worker scope: `source/interface/motion_sensor.c` only.
|
||||
All five non-exact rows are PARKED, so every measurement here is a scratch candidate or a shadow-tree probe.
|
||||
**The real file is unchanged** (`git diff --stat -- source/interface/motion_sensor.c` is empty).
|
||||
Final real-file gate: `== exact 14 residual 5 unwritten 0` (identical to baseline); the `_point_from_line3d`
|
||||
guard passes; `scratch/parkcheck.py` reports `parks 5 drift 0`; `tools/fake_match_scan.py` reports 0 leads.
|
||||
|
||||
Worker notes and every probe: `scratch/workers/n3_motion_sensor.md`, `scratch/workers/n3_motion_sensor/`.
|
||||
|
||||
## Baseline
|
||||
|
||||
| Function | January padded / relocs | Parked body | Gate tag |
|
||||
| --- | ---: | ---: | --- |
|
||||
| `_blip_begin` | 112 / 10 | 112 / 10 | sha |
|
||||
| `_motion_sensor_update` | 1168 / 43 | 1136 / 44 | size, relocs, sha |
|
||||
| `_render_blip` | 400 / 18 | 384 / 17 | size, relocs, sha |
|
||||
| `_render_motion_sensor` | 768 / 40 | 768 / 40 | sha |
|
||||
| `_update_motion_sensor` | 864 / 39 | 816 / 37 | size, relocs, sha |
|
||||
|
||||
Duplicate prevention: the three prior ledgers (`..._opus5_250k_w3c_20260915.md` — wave w3c, the same day —
|
||||
`..._opus5_150k_w1_20260914.md`, `..._jonas_census_tick_one_shot_20260829.md`),
|
||||
`lane_reconciliation_batch5_fuzzy_ui_world_20260909.md`, laws_w2 and laws_w3 in full,
|
||||
`git log --all -- source/interface/motion_sensor.c` (last body change `800179a20`, byte-equal to the current file)
|
||||
and `branch_sweep` (11 blobs; the current file is the best at `exact 14`).
|
||||
|
||||
## 1. Structural census (run fresh, before any shape)
|
||||
|
||||
### Frame census
|
||||
|
||||
| Function | January | parked body | best scratch body |
|
||||
| --- | --- | --- | --- |
|
||||
| `_update_motion_sensor` | `sub esp,0x2c0` | `sub esp,0x2c4` (+4, one extra cell) | `w3c/u7.c` = `0x2c0`, slot set identical |
|
||||
| `_motion_sensor_update` | `sub esp,0x284` | `sub esp,0x270` (-20, different short-array topology) | `w1/v13.c` = `0x284`, slot set identical |
|
||||
| `_render_blip` | `sub esp,0xc` | `sub esp,0xc` | identical; the gap is not the frame |
|
||||
|
||||
### Relocation census by target
|
||||
|
||||
`_motion_sensor_update` — January owns `_blip_type_get` ×1, `_object_get_and_verify_type` ×1, `_tag_get` ×1 and
|
||||
`_object_try_and_get_and_verify_type` ×2 where we call `_motion_sensor_blip_set_type_and_size` ×1 and
|
||||
`_object_try_and_get_and_verify_type` ×1; we additionally own two surplus `_local_player_get_player_index`, one
|
||||
`_datum_get` and one `_player_data`. **Both builds emit two `_game_engine_running` calls**, so the recorded park
|
||||
criterion ("January emits the otherwise-discarded `game_engine_running` call") is refuted: the residual is the
|
||||
inlined blip type/size helper plus a duplicated local-player fetch.
|
||||
|
||||
`_render_blip` — January owns `__real@3f800000` ×2, `__real@3fe6666666666666` (double 0.7) and `__real@3dd6774d`;
|
||||
we own one `__real@3f800000`, the widened `__real@3fe6666660000000` and `__real@3dd67750`.
|
||||
|
||||
`_update_motion_sensor` — January owns two `__real@00000000` loads we lack; everything else is address shift only.
|
||||
|
||||
### Owner census (candidates vs `build/base`, checked against `build/split`)
|
||||
|
||||
`w3c/bb1.c` clean. `w3c/rb6.c` swaps two literals for January's own. **`w3c/u7.c` and `w1/v13.c` each add
|
||||
`_distance_squared3d` and `_vector_from_points3d`** — `real_math.h:1177` defines `distance_squared3d` as
|
||||
`magnitude_squared3d(vector_from_points3d(a, b, &v))`, so the pair is inseparable from any call. The pending
|
||||
laws_w3 R14 `_vector_from_points3d` ruling therefore gates **2,032 padded bytes in this unit**, not the 1,168 the
|
||||
w3c ledger recorded.
|
||||
|
||||
### Candidate re-verification at this HEAD
|
||||
|
||||
`w3c/bb1.c` → `exact 15 residual 4` (`_blip_begin` strict EXACT). `w1/v13.c` → `exact 16 residual 3`
|
||||
(`_blip_begin` + `_motion_sensor_update` strict EXACT). `w3c/u7.c` → `_update_motion_sensor` **864 / 39, [sha] only**.
|
||||
`w3c/rb6.c` → `_render_blip` **384 / 18** against the real headers.
|
||||
|
||||
## 2. Outcomes
|
||||
|
||||
### `_motion_sensor_update` (1168 / 43) — OWNER-BLOCKED, 0 shapes spent
|
||||
|
||||
The structural gap is solved (`w1/v13.c` is strict EXACT and reproduces January's frame and relocation set exactly).
|
||||
Both recorded blockers are policy, so no laws_w2/laws_w3 law applies and spending shapes a standing policy forbids
|
||||
is itself a defect (R13):
|
||||
|
||||
1. January leaves `camera_positions[i]` uninitialised for a local player whose unit is NONE, and the object loop
|
||||
reads it. Verified independently this wave that the array is not covered by any existing clear: January's single
|
||||
`csmemset` is `csmemset(&sentinel, 0x62, 0x200)` at `[ebp-0x284]`, the stack-corruption sentinel; the 0x84 bytes
|
||||
of real locals above it are never written at entry.
|
||||
2. The owner census gains `_distance_squared3d` + `_vector_from_points3d` (R14).
|
||||
|
||||
### `_update_motion_sensor` (864 / 39) — NOT LANDED; structural gap closed, residual is a reassociation tie
|
||||
|
||||
`w3c/u7.c` reaches **864 / 39 with 285 vs 285 instructions**. `alndiff` leaves exactly one hunk, 8 bytes at
|
||||
`0x16b..0x178` in loop 1: January associates the squared length as `(j*j + i*i) + k*k`, ours as `(i*i + k*k) + j*j`
|
||||
(laws_w2 A22 / laws_w3 A35(2); January = the S4 ranking, ours = S5). The leaf bytes at `0x14b..0x16a` are identical
|
||||
and loop 2 already matches, so the leaves and their ages are equal — the summation lives inside
|
||||
`magnitude_squared3d` (real_math.h:1123), which a worker may not edit.
|
||||
|
||||
**The recorded park criterion is refuted.** January's two `__real@00000000` relocations are not "unresolved x87
|
||||
scheduling": they are the `k*k` term of `distance_squared3d(&reference_position, &object_position)` where
|
||||
`reference_position.z = object_position.z`. Copy forwarding folds `z-z` to the zero literal while the multiply that
|
||||
was already built survives — a source shape, reproduced exactly by u7.
|
||||
|
||||
No shapes spent this wave: the difference is pure x87 term order (the orchestrator's instruction is not to grind
|
||||
such ties), w1 and w3c together spent 15 shapes on it with a clear tie verdict, and an exact body would still be an
|
||||
R17 conditional reopen behind the R14 ruling.
|
||||
|
||||
### `_render_blip` (400 / 18) — NOT LANDED; E7 is now measured NOT to be count-neutral
|
||||
|
||||
`w3c/rb6.c` is 384 / 18 against the real headers and **400 / 18** under a shadow `real_math.h` carrying the laws_w3
|
||||
**E7** `rotate_vector2d` body (re-measured this wave with `sgate2.py`). The remaining 16 bytes are entirely the
|
||||
helper's body: January emits the j row into a temporary and copies it back with an integer move AFTER the i store,
|
||||
which the repo body (`result->i` first, then a second read of `v->i` — the in-place aliasing bug) cannot produce.
|
||||
|
||||
**New measured negative.** Six shadow-header probes (`scratch/workers/n3_motion_sensor/sh{A,B,D,E,G,H}`):
|
||||
|
||||
| shadow `real_math.h` | `bitmap_drawing` | `game_engine_race` |
|
||||
| --- | --- | --- |
|
||||
| A — two temps, j first (E7 text) | `_bitmap_copy` LOST (2784/69 both sides, sha only) | — |
|
||||
| B — one temp (`real j`), i stored inline | `_bitmap_copy` LOST | `_race_engine_player_update` LOST (160/9), `_race_touch_flag` LOST (336/28 vs 30) |
|
||||
| G — one temp caching the input (`real i = v->i`) | `_bitmap_copy` LOST | — |
|
||||
| H — two temps, i first | `_bitmap_copy` LOST | — |
|
||||
| D — ORIGINAL body + 1 extra prototype | `7 of 7 EXACT` | — |
|
||||
| E — ORIGINAL body + 2 extra prototypes | `7 of 7 EXACT` | — |
|
||||
|
||||
Neither `bitmap_drawing.c` nor `game_engine_race.c` contains a single textual reference to `rotate_vector2d`, yet
|
||||
every correct body flips them while pure declaration additions do not. This **refutes the declaration-count
|
||||
attribution in laws_w3 A41 for these victims and confirms the body-IL attribution**, and it settles E7's open
|
||||
question: **no count-neutral compensation exists**, so a duplicate-prototype cleanup cannot rescue the packet.
|
||||
E7 is +400 (this row) against -3,280 unless the three victim rows are re-closed in their own units under the header.
|
||||
|
||||
### `_blip_begin` (112 / 10) — PARK REOPEN PROPOSED (re-verified; duplicates the w3c proposal)
|
||||
|
||||
`scratch/workers/w3c_motion_sensor/bb1.c` = the current real file plus the January four-slot ABI and a disclosure
|
||||
comment. Whole-TU gate at this HEAD `== exact 15 residual 4`; no baseline-EXACT row lost; guard passes; owner census
|
||||
empty in both directions; fake-match scan 0 leads.
|
||||
|
||||
January evidence re-derived this wave: the body asserts `reference` from **ESI** (`test esi,esi; jne` with the
|
||||
`"reference"` literal), reads `in_multiplayer` at `[ebp+0xc]` and `local_player_index` at `[ebp+0x10]`, and never
|
||||
touches `[ebp+8]`; the only caller does `lea esi,[ebp-0x10]; push esi; push eax; push 0; call _blip_begin;
|
||||
add esp,0xc`, so the literal zero is argument two with `reference` enregistered.
|
||||
|
||||
Independent name search (new this wave): HCEA `halocea-review/src/blam/rasterizer/dx9/blip_begin.c` is the later
|
||||
build's **three**-parameter `void blip_begin(const real_point2d *center, uint8_t in_multiplayer,
|
||||
int16_t local_player_index)` and its "4th num_blips param" line is an explicit decompiler DEVIATION note, not a
|
||||
name; a whole-tree grep of `_research-stian-halo`, `stian-current`, `reference/halocea` and
|
||||
`public-donor-census-20260829` finds no `blip_begin` at all. `long 0` and `real 0.0f` emit identical bytes.
|
||||
`long unused` plus the disclosure comment remains the only honest spelling (precedents
|
||||
`actor_perception_find_sense_position`, `profile_rasterizer_stalls`).
|
||||
|
||||
**Coupled park re-baseline required in the same commit:** `_render_motion_sensor` 768 / 40 → **784 / 40**,
|
||||
sha `de9701add36aae94` (laws_w2 A8 callee-ABI cascade).
|
||||
|
||||
### `_render_motion_sensor` (768 / 40) — SKIPPED-EXHAUSTED
|
||||
|
||||
Not a target of this wave. w1 spent 15 shapes, w3c ran A5/A12/A23/A24/A25 as detectors and none fires; the residual
|
||||
is the C2 scheduler interleaving the sensor-index integer statement with the x87 weight chain. Listed only because
|
||||
the `_blip_begin` reopen re-baselines it.
|
||||
|
||||
## Proposals
|
||||
|
||||
1. **Park reopen — `_blip_begin` (112 B).** `scratch/workers/w3c_motion_sensor/bb1.c`, coupled with the
|
||||
`_render_motion_sensor` re-baseline to 784 / 40 sha `de9701add36aae94`. Needs the owner ruling on the never-read
|
||||
second parameter's name and type. (Same candidate the w3c ledger proposed; re-verified unchanged at this HEAD,
|
||||
with an independent, now-exhaustive donor-tree name search.)
|
||||
2. **Owner ruling — `_vector_from_points3d` surplus COMDAT (R14), scope corrected.** It gates `_motion_sensor_update`
|
||||
(1,168) *and* `_update_motion_sensor` (864) in this unit — 2,032 B — on top of sun_glow's 2,352.
|
||||
3. **Owner ruling — `_motion_sensor_update` uninitialised `camera_positions` read.** Exact body `w1/v13.c`.
|
||||
4. **laws_w3 E7 re-evaluation.** E7 cannot be made count-neutral (measured above). If the orchestrator still wants
|
||||
the 400 B, E7 must ride with a worker owning `source/bitmaps/bitmap_drawing.c` and `source/game/game_engine_race.c`
|
||||
who re-closes `_bitmap_copy`, `_race_engine_player_update` and `_race_touch_flag` under the E7 header.
|
||||
5. **parked.json evidence text.** The recorded criteria for `_motion_sensor_update` (the "otherwise-discarded
|
||||
`game_engine_running` call") and `_update_motion_sensor` ("zero-real relocations reflect unresolved x87
|
||||
scheduling") are both refuted by this census and should be replaced by the causes recorded here.
|
||||
|
||||
## Reopen criteria
|
||||
|
||||
- `_blip_begin`: owner ruling on the unused parameter's name and type.
|
||||
- `_motion_sensor_update`: owner rulings on the uninitialised read AND the `_vector_from_points3d` census.
|
||||
- `_update_motion_sensor`: the `_vector_from_points3d` ruling PLUS a spelling in which the folded-zero `k` term is
|
||||
not reassociated into the first partial sum (start from `w3c/u7.c`).
|
||||
- `_render_blip`: E7 landed together with re-closures of its three measured victims, plus a lever that moves
|
||||
`fmul dword [esi+0x2d0]` three integer instructions later inside its basic block.
|
||||
- `_render_motion_sensor`: a spelling that emits `sub eax, dword ptr [ebp-0x18]` as a memory operand and finishes
|
||||
the integer sensor-index statement before the x87 weight chain.
|
||||
@@ -0,0 +1,138 @@
|
||||
# `player_effects.obj` — opus5 next-150K lane, wave n3a (2026-09-15), STRUCTURAL PARK PASS
|
||||
|
||||
## Result
|
||||
|
||||
| Measure | Baseline (HEAD) | Final |
|
||||
| --- | --- | --- |
|
||||
| Focused gate | 25 exact / 4 residual / 0 unwritten | 25 exact / 4 residual / 0 unwritten |
|
||||
| `_point_from_line3d` guard | pass | pass |
|
||||
| Parks (`scratch/parkcheck.py`) | 3 active | 3 active, drift 0 |
|
||||
| `tools/fake_match_scan.py` | 0 leads | 0 leads |
|
||||
| `git diff --stat -- source/effects/player_effects.c` | — | empty |
|
||||
|
||||
**Nothing landed, by design: the census closed the question instead.** The real file was never edited.
|
||||
|
||||
**Baseline correction for the lane board.** The wave packet lists this unit at `exact 24 / residual 5`
|
||||
with `_player_effect_get_screen_flash` still `residual 800 [size 816!=800, sha]`. The measured gate at this
|
||||
HEAD is `exact 25 / residual 4`: `_player_effect_get_screen_flash` is already strict EXACT in the real file
|
||||
(landed by wave w3c, `player_effects_obj_opus5_250k_w3c_20260915.md`). The packet's row list is one wave
|
||||
stale.
|
||||
|
||||
## Target: `_player_effect_get_camera_effect_matrix` (1312 padded / 1303 meaningful / 49 relocs) — PARKED
|
||||
|
||||
### The park premise, and what the census did to it
|
||||
|
||||
`config/parked.json`, class `unclassified`, records: *"Target and candidate carry the same ordered 49
|
||||
relocation identities and the same 0x48-byte frame … **the candidate is 1280 padded bytes against
|
||||
January's 1312**."*
|
||||
|
||||
Candidate `scratch/workers/n3_player_effects/v0.c` — the **current** real file with **only** this parked
|
||||
body replaced by the w1 `pe_m6` shape (m1 `set_real_point3d` scripted translation, m2/m6 direct
|
||||
`temporary_duration` / `camera_shake.duration` arguments, m3 two-pass impulse translation) — gates at
|
||||
**1312 / 49 [sha]**, i.e. **January's exact padded size and relocation set**, with the whole-TU `--all`
|
||||
listing identical row for row to baseline (`exact 25 residual 4`, no sibling loss, guard passes).
|
||||
|
||||
So **the recorded size premise is refuted**: the 32-byte gap was two source defects (the `real duration`
|
||||
locals, and the one-pass `position.x = direction.i*translation + jitter.i*scale` form), both fixable in
|
||||
admissible C.
|
||||
|
||||
### Frame census — January vs candidate
|
||||
|
||||
Both `sub esp, 0x48`. Slot-by-slot reference counts are identical for every slot
|
||||
(`[ebp+8]` 18, `[ebp+0xc]` 6, `[ebp-4]` 17, `[ebp-8]` 27, `[ebp-0xc]` 1, `[ebp-0x10]` 1, `[ebp-0x14]` 2,
|
||||
`[ebp-0x18]` 3, `[ebp-0x1c]` 3, `[ebp-0x48]` 6) **except `[ebp-0x20]` (`effect_matrix.position.x`):
|
||||
January 1 reference, ours 3.** Ours lacks no slot and adds none — no missing local, no extra local, no
|
||||
width gap.
|
||||
|
||||
### Relocation census by target
|
||||
|
||||
`relocdiff --count-by-target --allow-structural`: `49 target, 49 candidate, 0 differing row(s)`. Every
|
||||
call and global matches by target and count. **No missing statement.**
|
||||
|
||||
### Therefore
|
||||
|
||||
The census **refutes the park's size premise** and at the same time **proves no structural source defect
|
||||
remains**: no missing call, no absent or surplus frame slot, no wrong declared width, no wrong control
|
||||
flow. What is left is 390 vs 389 instructions in two x87 clusters:
|
||||
|
||||
* **A — inlined `cross_product3d(global_up3d, &effect->direction, &axis)` (4 instruction slots).** January
|
||||
`+0x2cf fld [ebx+8]; fmul [eax]` and `+0x2d6 fld [ebx+8]; fmul [eax+4]`; ours loads the `global_up3d`
|
||||
leaf first in exactly those two products. The other four products and the k,j,i term order are
|
||||
byte-identical. A35(1) verbatim.
|
||||
* **B — impulse translation (1 net instruction).** January keeps `translation * effect->direction.i` on the
|
||||
x87 stack across the `y` and `z` stores (`fld st(1)` … `fxch st(1)` … `fadd st(1)` … `fstp st(0)`); ours
|
||||
stores `position.x` and reloads it. `y` and `z` use a memory `fadd` in **both** builds, which is what
|
||||
proves the two-pass source shape.
|
||||
|
||||
### Shapes measured this wave (4, all scratch, all reverted)
|
||||
|
||||
| id | shape | result |
|
||||
| --- | --- | --- |
|
||||
| `v0.c` | current real file + the w1 m1/m2/m3/m6 body | **1312 / 49**, clusters A + B only, siblings unchanged |
|
||||
| `v1.c` | `position.x = position.x + effect->jitter.i * scale;` (×3) instead of `+=` | byte-identical to v0 |
|
||||
| `v2.c` | pass 1 reordered `y, z, x` | y/z stores reach January's offsets; **x still spills and reloads** |
|
||||
| `v3.c` | `scale_vector3d` + `scale_vector3d` into a temp + `add_vectors3d`, with the admitted point→vector casts | **frame 0x48 → 0x54**; January's frame has no room for a temporary vector — helper routing through a temp is structurally refuted |
|
||||
| `v4.c` | v0 **minus m1** (scripted translation as three direct `z, y, x` stores) | **cluster A vanishes (the cross product becomes byte-exact)** while the scripted block degrades to eval/store ×3 (393 insns vs 390) |
|
||||
|
||||
### The blocker, stated precisely
|
||||
|
||||
**(a) The two blocks are mutually exclusive.** January's scripted branch evaluates all three translation
|
||||
products and *then* stores x, y, z (`+0x204..+0x229`) — only the `set_real_point3d` grouping reproduces
|
||||
that (A4); the direct-store spelling interleaves eval and store (v4, and the parked body). But that
|
||||
grouping is exactly what flips the two `cross_product3d` leaf loads in the **other arm of the same
|
||||
if/else** — a distant count-driven tie inside one function (the declaration-count oracle, not leaf age:
|
||||
the two blocks never execute together). v0 vs v4 measures the exclusive-or directly at this HEAD, which is
|
||||
the first time it has been reproduced since w1. The only third grouping (three named product locals) is
|
||||
refuted by the frame census, exactly as v3 was.
|
||||
|
||||
**(b) January never stores the x product.** `+=` (v0), `x = x + e` (v1), "x last" (v2) all reload from
|
||||
memory, and a temp vector costs frame (v3). Every source form with January's property is asymmetric — one
|
||||
component as a single combined expression, or a named `real` for x alone — i.e. a shape written to
|
||||
reproduce bytes rather than source a programmer would write. None was tried, under house rule 8 and the
|
||||
no-fake-matching gate.
|
||||
|
||||
**No reopen is proposed** (a reopen needs strict EXACT; an R11 size-changing "strictly closer" re-baseline
|
||||
is not proposable). The park is untouched.
|
||||
|
||||
**Reopen criterion, sharpened.** The park's size, frame, slot and relocation premises are all satisfied by
|
||||
`scratch/workers/n3_player_effects/v0.c` (1312 / 49, four differing instruction slots). Reopen needs
|
||||
**(a)** a source form that groups three evaluations before three stores in the scripted branch *without*
|
||||
the `set_real_point3d` inline, or an admissible count-neutral compensation for the flip it causes, **and
|
||||
(b)** a natural source form in which `translation * effect->direction.i` is never stored to `position.x`
|
||||
before the jitter add.
|
||||
|
||||
## Rows not spent
|
||||
|
||||
| Function | Padded | Classification | Why not spent |
|
||||
| --- | ---: | --- | --- |
|
||||
| `_player_effect_add_continuous_effect` | 320 | x87 evaluation-order tie, no structural delta | 5 shapes already spent (w1 ×3, w3c ×2); both leaves are the same memory operand so A35 cannot discriminate; outside the structural mandate |
|
||||
| `_player_effect_start` (parked) | 736 | A35(1) offset-0 leaf-age tie, 2 instructions | identical size, frame, relocations and instruction count; no admissible untried shape (w1, w3c) |
|
||||
| `_player_effect_update_camera_impulse` (parked) | 752 | x87 term order in inlined helpers | identical size, frame, relocations and instruction count; A24/A6/A31/A35/A46 run as detectors by w3c, none fires |
|
||||
|
||||
## Observation for the lane (no tree change requested)
|
||||
|
||||
Three of this unit's four residuals — `_player_effect_get_camera_effect_matrix` cluster A,
|
||||
`_player_effect_start`, `_player_effect_update_camera_impulse` — are one defect class: the operand load
|
||||
order of terms inside inlined `real_math.h` `cross_product3d` / `dot_product3d` bodies, with **no**
|
||||
structural delta anywhere (identical frames, identical relocation sets, and identical instruction counts
|
||||
in two of the three). That is a systemic inline-IL question (A35 / A41), not three independent per-site
|
||||
source defects; per-site spellings are now spent across four waves (w1, the 0904 closeout, w3c, n3a).
|
||||
|
||||
## Proposals
|
||||
|
||||
None. No header, config, symbols.json or parked.json change is requested. No park reopen is proposed.
|
||||
|
||||
## Verification performed
|
||||
|
||||
- `python -B tools/campaign/gate.py source/effects/player_effects --all --forbid-emitted-symbol
|
||||
_point_from_line3d` → `exact 25 residual 4 unwritten 0`, before and after (real file never edited).
|
||||
- `--source scratch/workers/n3_player_effects/v0.c --all` → identical row for row to baseline; the target
|
||||
row moves `[size 1280!=1312, sha]` → `[sha]` at 1312 / 49.
|
||||
- `python -B -m tools.campaign.alndiff` and `relocdiff --count-by-target --allow-structural` for v0…v4;
|
||||
per-slot `[ebp±N]` censuses via `scratch/workers/n3_player_effects/slots.py`.
|
||||
- `python -B scratch/parkcheck.py source/effects/player_effects <real.obj>` → `parks 3 drift 0`.
|
||||
- `python -B tools/fake_match_scan.py source/effects/player_effects.c` → 0 review leads.
|
||||
- No ninja, configure, pytest or git state command was run; no header, config or other source file was
|
||||
touched.
|
||||
|
||||
Details, byte evidence and the full census tables are in `scratch/workers/n3_player_effects.md`.
|
||||
+218
@@ -0,0 +1,218 @@
|
||||
# `rasterizer_xbox_environment.obj`: next-150K house-clean lane, wave n3a (2026-09-15)
|
||||
|
||||
## Scope and provenance
|
||||
|
||||
- Translation unit `source/rasterizer/xbox/rasterizer_xbox_environment.c`; target
|
||||
`build/split/source/rasterizer/xbox/rasterizer_xbox_environment.obj` (the January split COFF is byte authority).
|
||||
- Lane `C:\halo-worktrees\opus5-150k-house-clean-20260914`, branch `opus/next-150k-house-clean-20260915`,
|
||||
frozen baseline `ae10935da`. Structural park pass, wave n3.
|
||||
- Worker-only measurements: `tools/campaign/gate.py`, `tools.campaign.tinfo`, `tools.campaign.relocdiff`,
|
||||
`tools.campaign.alndiff`, `scratch/parkcheck.py`, `tools/fake_match_scan.py`, plus a micro-TU lab compiled with this
|
||||
unit's own `build.ninja` cflags and CL (`scratch/workers/n3_rasterizer_xbox_environment/lab.py`). No ninja,
|
||||
configure, pytest, header, config or tool edits; no other source file touched.
|
||||
- Prior ledgers read in full: `_codex_small_exact_20260902`, `_diffuse_texture_reconciliation_20260909`,
|
||||
`_lightmap_draw_fuzzy_20260912`, `_opus_reflections_reconciliation_20260909`, `_opus5_100k_20260914`,
|
||||
`_opus5_100k_waveC_20260914`, `_opus5_150k_w1_20260914`, `_opus5_250k_w3c_20260915`; worker notes
|
||||
`scratch/workers/rasterizer_xbox_environment.md` and `scratch/workers/w3c_rasterizer_xbox_environment.md`.
|
||||
- Laws applied as detectors: WORKER_BRIEF section 5/9, `scratch/w2/laws_w2.md` (A1-A22, R1-R12, D),
|
||||
`scratch/w3/laws_w3.md` (A23-A45, R13-R19, C, D).
|
||||
- Worker notes for this wave: `scratch/workers/n3_rasterizer_xbox_environment.md`; scratch dir
|
||||
`scratch/workers/n3_rasterizer_xbox_environment/`.
|
||||
|
||||
## Baseline and final gate (identical; nothing landed)
|
||||
|
||||
`python -B tools/campaign/gate.py source/rasterizer/xbox/rasterizer_xbox_environment --all --forbid-emitted-symbol _point_from_line3d`
|
||||
|
||||
**exact 42, residual 2, unwritten 0 of 44** at baseline and at the end of the wave. Point guard pass;
|
||||
`scratch/parkcheck.py` 1 park, drift 0; `tools/fake_match_scan.py` 0 leads; owner census vs
|
||||
`build/base/.../rasterizer_xbox_environment.obj` 91 = 91, no candidate-only and no lost owner;
|
||||
`git diff --stat -- source/rasterizer/xbox/rasterizer_xbox_environment.c` empty.
|
||||
|
||||
| Row | Target size/relocs/sha16 | Real file | Status |
|
||||
| --- | --- | --- | --- |
|
||||
| `__rasterizer_environment_lightmap_draw` | 4016 / 248 / 7818e559325c1524 | 3984 / 246 / 02f716db92e8099f | residual [size, relocs, sha] |
|
||||
| `_rasterizer_environment_specular_spot_light_begin` | 960 / 64 / e0331f6b94a74f9c | 944 / 64 / d103843ee5f01bad | residual, PARKED |
|
||||
|
||||
`__rasterizer_environment_diffuse_light_begin` (w1 park reopen) and `_IDirect3DDevice8_SetTexture@12` are inherited
|
||||
exact and were not revisited.
|
||||
|
||||
## `__rasterizer_environment_lightmap_draw` - NOT LANDED (1 shape; the search space is now closed on the C side)
|
||||
|
||||
This row is **not** in `config/parked.json`; it is an ordinary residual. The applicable recorded criterion is the
|
||||
w3c one: "January or donor evidence of a real intensity/brightness term or a double/cast intermediate - OR an
|
||||
owner/policy ruling on the laws_w3 C3 x87-staged-argument family that also covers stack-local leaves."
|
||||
|
||||
### Relocation census by target
|
||||
|
||||
Every relocation target agrees except two, and both deficits are in the same struct:
|
||||
|
||||
| Target | January | real file |
|
||||
| --- | --- | --- |
|
||||
| `_pixel_shader+32` = `final_combiner_inputs_abcd` | 9 | 8 |
|
||||
| `_pixel_shader+36` = `final_combiner_inputs_efg` | 2 | 1 |
|
||||
|
||||
**Cause proven.** Our two illumination arms (`illumination->map.index == NONE` and the animated arm) end with the
|
||||
identical two-statement tail `final_combiner_inputs_abcd = 0x0A0F000C; final_combiner_inputs_efg = 0x1C011800;`, and
|
||||
VC7 cross-jumps those tails into a single copy. January does not merge them: in January the animated arm's constant
|
||||
block *ends* at `+32`/`+36` (0xd1d, 0xd27) and is followed by the five `real_*_to_pixel32` calls, so the two arms
|
||||
share no tail. That is precisely wave B's recorded correction "all constant `pixel_shader` stores before the five
|
||||
`real_*_to_pixel32` calls". A missing relocation here is therefore a store-ORDER defect, not a missing statement.
|
||||
|
||||
### Frame census
|
||||
|
||||
January `sub esp,0x218`; ours `sub esp,0x218`. A complete `[ebp±N]` census of both bodies gives **132 distinct slots
|
||||
on each side with identical per-slot reference counts**. The per-slot instruction lists are identical too: for
|
||||
`[ebp-4]` both sides have the same 11 references and for `[ebp-0xc]` the same 3, differing in exactly one instruction
|
||||
each. **No local is missing, extra, differently sized or differently scoped.** The census refutes every
|
||||
missing-statement / extra-slot / wrong-width / wrong-control-flow hypothesis for this row.
|
||||
|
||||
### Shape n1 (wave B reproduced on the current baseline)
|
||||
|
||||
`scratch/workers/n3_rasterizer_xbox_environment/n1.c` = the real file plus only wave B's four structural corrections
|
||||
(stage-0 MAG/MIN/MIP filters written inside each test-pattern arm; genuine XDK `PS_TEXTUREMODES(...)` for both
|
||||
`texture_modes` stores; all constant `pixel_shader` stores before the five `real_*_to_pixel32` calls; the
|
||||
`specular_mask` case placed after the `bump_edge` case). Gate: **4000 / 248 [size, sha]**, whole TU 42 exact /
|
||||
2 residual / 0 unwritten, point guard pass. Relocation count and every relocation target now equal January.
|
||||
Not landed: it is a non-exact body replacing an already-written residual (brief sections 6 and 8), and the w1
|
||||
verifier required exactly these hunks reverted (R13).
|
||||
|
||||
### The entire remaining gap
|
||||
|
||||
947 vs 939 instructions / 16 padded bytes, in two instruction pairs:
|
||||
|
||||
```
|
||||
January 0xb88 fld dword [ebp-4] ; add esp,0xc ; ... ; push ecx ; fstp dword [esp]
|
||||
ours 0xb88 mov ecx,[ebp-4] ; ... ; push ecx
|
||||
January 0xba6 fld dword [ebp-0xc] ; add esp,0x10 ; ... ; push ecx ; fstp dword [esp]
|
||||
ours 0xba0 mov edx,[ebp-0xc] ; ... ; push edx
|
||||
```
|
||||
|
||||
January stages the `t` argument of both `point_from_line3d` calls through the x87, which forces it to flush the two
|
||||
pending cdecl cleanups so `[esp]` is the argument slot; we integer-copy and merge five cleanups into one
|
||||
`add esp,0x44`. Everything after that is offset and allocation cascade.
|
||||
|
||||
### NEW MEASURED LAW: VC7 float-argument staging (15 controls)
|
||||
|
||||
A micro-TU that reproduces the block in shape (`rep1.c`, `rep2.c`, `rep3.c` with
|
||||
`scratch/workers/n3_rasterizer_xbox_environment/lab.py`, compiled with this unit's own cflags and CL) was used to
|
||||
enumerate the rule. The baseline probe emits our exact integer-copy shape; a `double`-parameter control emits
|
||||
`fstp qword [esp]`, so the detector is sound.
|
||||
|
||||
Integer-copied (no FPU staging) for every one of: a plain `real` local defined by a call return; named `1.0f - v`
|
||||
off-scale locals; a field of a local struct; an element of a local `real[2]`; an address-taken local; a `real` global;
|
||||
a `real` parameter; a parenthesised `(v)`; declare+initialize; a value with an extra later fp use; a helper whose
|
||||
pointer return is discarded; a value with no other fp use at all; a local *defined* by an fp expression and passed
|
||||
unchanged; a tag-block field read through the pointer; an element of a `real const *` parameter.
|
||||
|
||||
FPU-staged only for: an fp-VALUED argument expression, and a directly nested call result.
|
||||
|
||||
> **Law.** VC7 integer-copies every plain float lvalue argument - local, parameter, global, struct field, array
|
||||
> element or address-taken local, however it was defined. Only an fp-valued expression (or a call result consumed
|
||||
> directly in the argument list) is staged `push reg; fstp dword [esp]`.
|
||||
|
||||
This also corrects the w3c framing that the 68 other January `fld [reg+off] -> fstp [esp]` sites are "pointer field"
|
||||
staging: a pointer field on its own does not do it.
|
||||
|
||||
### Consequence and classification
|
||||
|
||||
January's `t` argument must be an fp expression whose emitted code is a single `fld dword [ebp-N]` - i.e. an
|
||||
expression that c2 folds to the bare local value. Every such expression is an identity (`v*1.0f`, `v+0.0f`,
|
||||
`(real)v`, `+v`): the w1 `intensity = 1.0f` family, rejected by the w1 verifier as fake arithmetic, bound by R13 and
|
||||
by this wave's orchestrator note, and separately R7 for the cast forms. The one non-identity form that does stage
|
||||
through the FPU - a directly nested `periodic_function_evaluate` call - is refuted by January's call order
|
||||
(scale, scale, point, point; nesting would emit scale, point, scale, point).
|
||||
|
||||
**Classification:** unresolved source form - x87 argument staging - with the C-side search space now closed. Not a
|
||||
register tie; not a missing statement.
|
||||
|
||||
**Reopen criterion (refined).** Reopen only on (a) an owner/policy ruling admitting a named self-illumination
|
||||
intensity of 1.0 - the January-side argument being the two `push 0x3f800000` constants at the plasma
|
||||
`scale_vector3d` calls, the only constant-1.0 pushes among January's twelve out-of-line `_scale_vector3d` calls - or
|
||||
(b) donor/January evidence of a genuine non-identity factor or double intermediate. Do **not** spend further shapes
|
||||
on plain-lvalue spellings of the argument: fifteen controls in this wave say they cannot work. Start from
|
||||
`scratch/workers/n3_rasterizer_xbox_environment/n1.c` (4000/248, relocation- and frame-exact).
|
||||
|
||||
## `_rasterizer_environment_specular_spot_light_begin` - NOT LANDED (park locked; 1 shape) - PARK CLASS REFUTED
|
||||
|
||||
Park's recorded criterion (`config/parked.json`, class `register-allocation`): *"... January is 960 padded bytes and
|
||||
the candidate 944, with all 64 relocations shared ... The remaining difference is compiler vector/local allocation
|
||||
and scheduling, not absent renderer behavior; bounded helper and declaration-shape probes did not close it. ...
|
||||
Reopen only for authoritative January source/local records or a natural same-compiler donor that explains the vector
|
||||
lifetime schedule."*
|
||||
|
||||
### Frame census - the park premise does not survive it
|
||||
|
||||
January `sub esp,0x84`; the parked body `sub esp,0x74`. January's slots are vertex constants `[-0x84,-0x34)`, an
|
||||
unreferenced 4 bytes at `-0x34`, forward `-0x30`, cross result `-0x24`, up `-0x18`, and an unreferenced 12 bytes at
|
||||
`-0xc`: exactly `real_matrix4x3 {scale; forward; left; up; position}` with `scale` and `position` never written. The
|
||||
parked body declares three separate `real_vector3d` locals, so its slots pack with no gaps and it is one aggregate
|
||||
short. **The 16-byte gap is a wrong declared local TYPE - a structural source defect - not "compiler vector/local
|
||||
allocation and scheduling".** The recorded class `register-allocation` is refuted.
|
||||
|
||||
### Relocation census
|
||||
|
||||
64 / 64 identical by target for both the parked body and the corrected candidate. No call or global is missing or
|
||||
extra on either side.
|
||||
|
||||
### Shape s1
|
||||
|
||||
`scratch/workers/n3_rasterizer_xbox_environment/s1.c` = the current real file with only this body replaced by w1's
|
||||
`s3a` shape (`real_matrix4x3 matrix; matrix.forward = light->forward; matrix.up = light->up;
|
||||
normalize3d(cross_product3d(&light->forward, &light->up, &matrix.left));`, vertex constants read from `matrix.*`).
|
||||
Gate: **960 / 64 [sha]**, frame `sub esp,0x84`, whole TU 42 exact / 2 residual, point guard pass. Size, relocations
|
||||
and frame are January-exact; 247 vs 248 instructions. It supersedes `s3a.c`, which also carries the rejected
|
||||
`intensity` tree and the pre-reopen diffuse body.
|
||||
|
||||
### What is left
|
||||
|
||||
Three commutative x87 operand-order pairs inside the shared `real_math.h cross_product3d` inline, plus their
|
||||
downstream allocation (`eax = &light->forward = esi+0x10`, `ecx = &light->up = esi+0x1c`):
|
||||
|
||||
```
|
||||
j term January fld [ecx] ; fmul [eax+8] ours fld [eax+8] ; fmul [ecx]
|
||||
January fld [ecx+8] ; fmul [eax] ours fld [eax] ; fmul [ecx+8]
|
||||
k term January fld [ecx+4] ; fmul [eax] ours fld [eax] ; fmul [ecx+4]
|
||||
```
|
||||
|
||||
plus one eax/ecx/edx rotation in the `light->position` copy, `lea ecx` vs `lea edx` at 0x1b5, and one extra
|
||||
`fxch st(1)` at 0x1ea. The i term already matches byte for byte on both sides, and January itself is not uniform
|
||||
(5 of 6 products load `up` first, ours 2 of 6), which is the fingerprint of leaf age rather than of a source operand
|
||||
order. Three independent pins block a source lever:
|
||||
|
||||
- **argument order** is pinned - the matching i term computes `up.k*forward.j - forward.k*up.j` =
|
||||
`cross(forward, up).i`, so swapping the arguments (and dropping the `vertex_constants[2]` negations, which is
|
||||
mathematically equivalent) would break a currently-exact hunk;
|
||||
- **operand addresses** are pinned by w3c's `s3b` proof (matrix members make VC7 read the local slots, while January
|
||||
reads `light`-relative addresses);
|
||||
- the **integer struct-copy schedule** is byte-identical on both sides, so the two member copies are pinned as well.
|
||||
|
||||
Buying the last `fxch` with a commutative swap of `cone_scale * (radius * 0.5f)` is R3.
|
||||
|
||||
**Classification:** the structural half is closed in scratch; the residual is an x87 commutative leaf-age tie inside
|
||||
a shared header inline, with no TU-local handle. No park-reopen is proposed - the brief requires strict EXACT and
|
||||
`s1.c` is `[sha]`.
|
||||
|
||||
**Reopen criterion (unchanged from w3c):** (a) a measured VC7 law explaining the `fld` order for pointer-read
|
||||
commutative operands, or (b) an owner-approved `real_math.h cross_product3d` change measured across its consumers,
|
||||
noting that the current body is REQUIRED by the exact sibling `__rasterizer_environment_diffuse_light_begin`.
|
||||
|
||||
## Rejected / do-not-repeat (added by this wave)
|
||||
|
||||
- Any plain-lvalue spelling of the `point_from_line3d` `t` argument in `lightmap_draw` (15 measured controls).
|
||||
- Nesting the `periodic_function_evaluate` call inside the `point_from_line3d` argument list - the only non-identity
|
||||
FPU-staging form - refuted by January's call order.
|
||||
- Re-landing wave B's four structural corrections alone (4000/248): brief sections 6/8 plus the w1 verifier's
|
||||
full-revert requirement (R13).
|
||||
- Swapping `cross_product3d`'s arguments in the spot light: breaks the currently-matching i term.
|
||||
|
||||
## Proposals
|
||||
|
||||
- **parked.json evidence/class correction (no byte effect, orchestrator-owned).** For
|
||||
`_rasterizer_environment_specular_spot_light_begin`, change `"class"` from `register-allocation` to
|
||||
`x87-operand-order` and amend the evidence text: the 16-byte gap is a `real_matrix4x3` local whose `scale` and
|
||||
`position` are never written (frame census: January `sub esp,0x84` vs the parked body's `0x74`, January's
|
||||
unreferenced 4 bytes at `-0x34` and 12 bytes at `-0xc`), closed in scratch at 960/64 with frame parity by
|
||||
`scratch/workers/n3_rasterizer_xbox_environment/s1.c`; the remaining difference is the commutative `fld`/`fmul`
|
||||
leaf order inside the shared `real_math.h cross_product3d` inline. No source, header, symbols.json or config change
|
||||
arises from this wave, and the park stays locked.
|
||||
- No header or config need. The real file is unchanged.
|
||||
@@ -0,0 +1,205 @@
|
||||
# `s3tc.obj` structural park pass (opus5 next-150K lane, wave n3a, 2026-09-15)
|
||||
|
||||
Unit `source/bitmaps/s3tc/s3tc.c`, baseline `ae10935da`. **All six non-exact rows are parked**
|
||||
(`config/parked.json`), so all work was scratch-only and **the real source file is unchanged**
|
||||
(`git diff --stat` empty). No exact credit is claimed by this wave.
|
||||
|
||||
Prior passes read in full: `s3tc_obj_opus5_250k_w3c_20260915.md`, `s3tc_obj_opus5_150k_w1_20260914.md`,
|
||||
`player_profile_s3tc_batch_reconciliation_20260907.md` (the batch that installed the parks) and the four
|
||||
`s3tc_obj_jonas_*` ledgers. `git log --all` 9 commits; `branch_sweep` best history blob `dc1eb5bd`
|
||||
(same 12/6/0, sizedelta 464) — re-read this wave and used as evidence, see section 1.
|
||||
|
||||
## Baseline and final gate
|
||||
|
||||
| gate | result |
|
||||
| --- | --- |
|
||||
| baseline (`--all`, `_point_from_line3d` guard) | exact 12 / residual 6 / unwritten 0; guard passed |
|
||||
| final real file | identical: exact 12 / residual 6 / unwritten 0; guard passed |
|
||||
| park drift (`scratch/parkcheck.py`, real object) | 6 parks, drift 0 |
|
||||
| fake-match scan (real file and the best candidate) | 0 review leads each |
|
||||
| real file modified | **no** |
|
||||
|
||||
## Per-function outcomes
|
||||
|
||||
| function | target | best scratch this wave | outcome |
|
||||
| --- | --- | --- | --- |
|
||||
| `_DecodeBlockRGB__single_pixel` | 496 / 10 | **496 / 10 strict EXACT** (`d2.c`); `d1.c` = 1 instruction away | PARK-REOPEN-PROPOSED |
|
||||
| `_DecodeBlockRGB` | 448 / 2 | 448 / 2 **EXACT**, no body change | PARK-REOPEN-PROPOSED (coupled) |
|
||||
| `_EncodeBlockRGBColorKey` | 2192 / 36 | 2192 / 36 `[sha]` (w3c `e7_probe.c`, re-verified) | OWNER-BLOCKED (structure solved) |
|
||||
| `_DecodeBlockAlpha3__single_pixel` | 432 / 1 | 432 padded / 427 meaningful / 1 (w3c `a1.c`) | NOT-LANDED (A43 register web; park premise survives) |
|
||||
| `_RGBToColor` (coupled, not a target) | 96 / 0 | 96 / 0 **EXACT** | PARK-REOPEN-PROPOSED (policy ruling, unadjudicated since w1) |
|
||||
| `_Quantize` (coupled, not a target) | 528 / 30 | 528 / 30 `[sha]`, re-bases to `57685b731729ce83` | park remeasure needed in the reopen commit |
|
||||
|
||||
## 1. `_DecodeBlockRGB__single_pixel` — one instruction from exact; January's assert TEXT recovered
|
||||
|
||||
### Census
|
||||
|
||||
Frame: January `sub esp,0x10`, ours `sub esp,0x10` — **identical**. The 16 bytes are
|
||||
`struct s3tc_color colors[4]` on both sides, so January's local palette is 4 entries too; the 64-byte clear is
|
||||
not an oversized local but a write through the OUTPUT parameter
|
||||
(`mov eax,[ebp+0xc]; push 0x40; push edi; push eax; call _csmemset`, `edi` being the NULL `source` reused as the
|
||||
fill byte).
|
||||
|
||||
Relocations, by target, against `scratch/workers/s3tc/reopen_rgbtocolor.c`: `_csmemset` 1/1, `_RGBToColor` 1/1,
|
||||
`_display_assert` 2/2, `_system_exit` 2/2, file-name literal 2/2 — equal. Two rows differ, both assert-text
|
||||
literals:
|
||||
|
||||
| | mangled name | length | text |
|
||||
| --- | --- | --- | --- |
|
||||
| January | `??_C@_0N@CLDKFKKD@u?$DO?$DN0?5?$CG?$CG?5u?$DM?$DN4?$AA@` | `_0N` = 13 | `u>=0 && u<=4` |
|
||||
| ours | `??_C@_0BA@MDFLADHG@u?5?$DO?$DN?50?5?$CG?$CG?5u?5?$DM?54?$AA@` | `_0BA` = 16 | `u >= 0 && u < 4` |
|
||||
|
||||
(and the same pair for `v`). **Census verdict: the park premise survives only for the memset. Its assert clause
|
||||
is refuted.**
|
||||
|
||||
### New evidence
|
||||
|
||||
1. **Stringization spacing law.** MSVC `#expr` deletes whitespace around the macro argument and collapses each
|
||||
internal run to a single space, but inserts none where the source had none. A `??_C@` assert literal therefore
|
||||
names the author's spelling character-for-character — here: no spaces around `>=` / `<=`, one space around
|
||||
`&&`. This is byte evidence about source text, and it is invisible to `gate.py`'s tags.
|
||||
2. **Independent second proof of the operator:** `alndiff` shows `T 180 jle` vs `O 180 jl` and `T 1ae jle` vs
|
||||
`O 1ae jl`. Signed `jle` is `u <= 4`. Literal and opcode agree.
|
||||
3. **The clear is a copy-paste, not a magic number.** `0x40` = `S3TC_BLOCK_PIXELS * sizeof(struct s3tc_color)`,
|
||||
the verbatim expression of the sibling `DecodeBlockRGB` **in the same TU, four functions up**
|
||||
(`source/bitmaps/s3tc/s3tc.c:586`), where the output parameter really is
|
||||
`struct s3tc_color colors[S3TC_BLOCK_PIXELS]`. R19's "same-TU precedent" requirement for an original-bug
|
||||
admission is met.
|
||||
4. **Historical corroboration.** `branch_sweep` blob `dc1eb5bd` (the pre-2026-09-07 body) already carried
|
||||
`memset(color, 0, S3TC_BLOCK_PIXELS * sizeof(struct s3tc_color));` (line 652) and `u >= 0 && u <= 4`
|
||||
(lines 689-690) — the right operator but with spaces. No body in this repository's history has ever
|
||||
reproduced January's literal; this wave is the first.
|
||||
5. **HCEX.pdb (SHIP, `DIA2Dump -sym`)**: `pblockSrc` (const struct S3TCBlockRGB \*), `colorDst`
|
||||
(struct S3TC_COLOR \*), `short u`, `short v`, local `struct S3TC_COLOR[0x4] clut`. Corroborates the 4-entry
|
||||
palette and short coordinates. A pointer parameter cannot distinguish `T *p` from `T p[16]`, so HCEX neither
|
||||
confirms nor refutes the clear size.
|
||||
|
||||
### Measurements
|
||||
|
||||
| candidate | whole-TU gate | this row |
|
||||
| --- | --- | --- |
|
||||
| `scratch/workers/s3tc/reopen_rgbtocolor.c` | exact 14 / residual 4 | 496 / 10 `[sha]`, 5 differing instructions |
|
||||
| `scratch/workers/n3_s3tc/d1.c` (+ January assert text) | exact 14 / residual 4 | 496 / 10, **0 differing relocation rows, 1 differing instruction** (`push 0x40` vs `push 4`) |
|
||||
| `scratch/workers/n3_s3tc/d2.c` (+ the 64-byte clear) | **exact 15 / residual 3** | **strict EXACT 496 / 10** |
|
||||
|
||||
Zero sibling loss in both: all 12 baseline-exact rows remain exact. Guard passes. `fake_match_scan d2.c` = 0
|
||||
leads (same as HEAD). Owner census: no new owner — the two new `.rdata` literals replace the two wrong ones.
|
||||
`parkcheck` on `d2.obj`: 4 parks drift (3 become exact = the reopen; `_Quantize` re-bases to 528/30 sha
|
||||
`57685b731729ce83`).
|
||||
|
||||
### Reopen criterion (two independent halves)
|
||||
|
||||
- **(a) assert text** — restore `match_assert("c:\\halo\\SOURCE\\bitmaps\\s3tc\\s3tc.c", 773, u>=0 && u<=4);`
|
||||
and the `774, v>=0 && v<=4` line. This is **not** UB: an assert reads its operands and writes nothing, a weaker
|
||||
predicate cannot by itself create an out-of-range shift, and both January callers pass 0..3. `docs/assertions.md`
|
||||
requires not losing "original diagnostic text ... failure polarity, or source locations", so the 2026-09-07
|
||||
repair is itself the deviation. Closes 4 of the 5 differences with no policy question.
|
||||
- **(b) the clear** — `memset(color, 0, S3TC_BLOCK_PIXELS * sizeof(struct s3tc_color));` writes 60 bytes past a
|
||||
4-byte object. A genuine overrun: needs the original-bug ruling plus a
|
||||
`/* BUG (preserved for exact matching): */` comment at the statement. Closes the 5th.
|
||||
|
||||
Together with the `_RGBToColor` ruling this object gains **1,040 padded bytes** (96 + 448 + 496).
|
||||
|
||||
## 2. `_DecodeBlockRGB` — inline boundary, not scheduling (re-verified)
|
||||
|
||||
The park text ("remaining instruction selection and scheduling are non-exact") is refuted: the `[size]` +
|
||||
`[relocs]` gap is an inline boundary owned by `_RGBToColor`. With the Microsoft/S3 reference body January's
|
||||
auto-inliner inlines the first call and calls the second out of line — 2 relocations, not 3 — and this function
|
||||
becomes strict EXACT **with no edit to its own body**. Re-verified at this HEAD (`exact 14 residual 4`).
|
||||
Blocked only on the coupled `_RGBToColor` policy ruling (the never-assigned `color.rgba[3]` inside an aggregate
|
||||
copy; `rgb` and `color` share the single `push ecx` slot, so any initialiser destroys the merge).
|
||||
|
||||
## 3. `_EncodeBlockRGBColorKey` — structure solved, exactness owner-blocked (0 shapes spent)
|
||||
|
||||
Independent census at this HEAD: January `sub esp,0x1a8` (424 B) vs real file `sub esp,0x19c` (412 B), 739 vs
|
||||
914 instructions, 36 vs 36 relocations. Re-verified w3c's two candidates: `e6.c` (do-while + aggregate axis, no
|
||||
original forms) = **2224 / 37** — one relocation over, because a fourth `_AllSame` site fails to cross-jump;
|
||||
`e7_probe.c` = **2192 / 36, `[sha]` only** (size and relocation count both exact).
|
||||
|
||||
The park's "provenance for the projection-loop index width" clause is superseded by w3c's do-while unroller law
|
||||
plus the `struct s3tc_fcolor` axis home. What remains is three target-proven ORIGINAL forms:
|
||||
(a) uninitialised `long axis`; (b) `if (len2 == 0.0f && cOpaque == 16)` — the guard that merges the two `AllSame`
|
||||
tails, whose preserved path computes `0/0`, `__ftol2(NaN)` = `0x80000000` and indexes `mapRGB3[0x80000000]`;
|
||||
(c) no `block->bitmap = 0;` before the selector loop. (a) and (b) are UB; (c) is behaviour-neutral but explicitly
|
||||
required by the park text.
|
||||
|
||||
No shape was spent: (b) is the only route to the 36th relocation and is inseparable from the NaN path, because a
|
||||
non-UB spelling would have to call `AllSame` with identical arguments in both cases, which changes behaviour.
|
||||
|
||||
## 4. `_DecodeBlockAlpha3__single_pixel` — the 11 bytes are integer promotions; park premise survives
|
||||
|
||||
Frame: `sub esp,0x10` on both sides; `[ebp-0x10 .. -0x2]` is the same `word alpha[8]` on both sides — no missing
|
||||
or extra slot. Relocations 1 vs 1 (`_DecodeBlockRGB__single_pixel` at @001d). The first **123 instructions are
|
||||
byte-identical at identical offsets**.
|
||||
|
||||
The whole `[size]` tag is four integer promotions, accounted to the byte: ours emits `movsx ecx,di` (3) +
|
||||
`movsx edx,word [ebp+0x10]` (4) in arm A and `movsx edx,di` (3) + `movsx ecx,word [ebp+0x10]` (4) in arm B = 14 B;
|
||||
January hoists ONE `mov ecx,dword [ebp+0x10]` (3 B) above the branch and uses EDI directly.
|
||||
**14 - 3 = 11 = 443 - 432 exactly.** January may read the raw parameter dwords only because `3*(4*v+u)` is needed
|
||||
modulo 2^16, i.e. the shift/index variable is 16-bit; `short u` / `short v` are byte-proven by the shared signed
|
||||
`cmp di,2`, so the parameters are not the lever.
|
||||
|
||||
**New measurement (corrects w1):** w3c's `a1.c` (`short shift`) is **427 meaningful** bytes, not 432 — the gate's
|
||||
"432" is 16-byte padding. Removing the 11 promotion bytes exposes an opposite 5-byte defect: our arms then end
|
||||
with the identical `shl eax,8; or eax,edx` pair, which VC7 cross-jumps to the join, while January keeps a copy in
|
||||
each arm because its index `lea eax,[ecx+edi*4]` must come last (it reuses the temp register EAX freed by
|
||||
`or edx,eax`). So the narrow width does not close the size envelope — it overshoots it.
|
||||
|
||||
The residual is one register web: January's bitmap accumulator is EDX and the `b[0]` temp EAX; ours are swapped,
|
||||
which also moves the index into ECX mid-arm and delays the `color` load past the table read. Eight prior shapes
|
||||
(w1 x5, w3c x3) failed to move it; this is laws_w3 **A43** (cross-jump survivor), a recorded negative class.
|
||||
0 shapes spent this wave.
|
||||
|
||||
Evidence search: HCEX.pdb has the function (RVA 0xD922A8, len 0x1D0) with `pblockSrc`
|
||||
(const struct S3TCBlockAlpha3 \*), `colorDst` (struct S3TC_COLOR \*), `short u`, `short v` — corroborating the
|
||||
park's retained signature — but no locals (enregistered scalars are absent from a SHIP PPC build), so no `shift`
|
||||
width. The Microsoft Windows Server 2003 reference (`research-cache/windows-server-2003-dxtn`, `5c6fe3db`)
|
||||
contains only `ref8/common/dxtn.cpp` and `d3d/ref/rast/refs3tc.cpp`, both block-only — no single-pixel helper and
|
||||
no encoder — so the "authentic Microsoft source" half of the reopen criterion is now measured unreachable from
|
||||
this corpus.
|
||||
|
||||
## Rejected / not proposed
|
||||
|
||||
- Any `_RGBToColor` form that initialises `color.rgba[3]` (w1 proved it breaks the slot merge).
|
||||
- `axis` uninitialised, `len2 == 0 && cOpaque == 16`, dropping `block->bitmap = 0` — all re-confirmed, all
|
||||
policy-gated; no shape spent.
|
||||
- `short shift` as a standalone park remeasure for `_DecodeBlockAlpha3__single_pixel` (R11 plus the park's
|
||||
artificial-width clause; and it is now measured strictly *shorter* than the target, not equal).
|
||||
- Landing anything in the real file: all six rows are parked.
|
||||
|
||||
## Orchestrator proposals
|
||||
|
||||
1. **Park reopen, `_DecodeBlockRGB__single_pixel` (496 B), candidate `scratch/workers/n3_s3tc/d2.c`**, with the
|
||||
intermediate `scratch/workers/n3_s3tc/d1.c` isolating the admissible half. Two rulings: (a) restore January's
|
||||
assert text (recommended independently of (b): it is required by `docs/assertions.md`, is not UB, and closes
|
||||
4 of 5 differences); (b) admit the copy-pasted 64-byte clear under the original-bug policy with a
|
||||
`/* BUG (preserved for exact matching): */` comment and the same-TU precedent at s3tc.c:586.
|
||||
2. **Park reopen (re-surfaced, still unadjudicated since w1): `_RGBToColor` + `_DecodeBlockRGB` (544 B)**,
|
||||
candidate `scratch/workers/s3tc/reopen_rgbtocolor.c`, re-verified at this HEAD. `d2.c` contains it, so a
|
||||
single commit can land all three rows (1,040 B) and must also remeasure the `_Quantize` park to
|
||||
528 / 30 / `57685b731729ce83`.
|
||||
3. **`config/parked.json` evidence updates (text only, zero bytes).**
|
||||
- `_DecodeBlockRGB__single_pixel`: replace "Require coordinates 0..3, not the original inclusive 4" with
|
||||
January's proven text `u>=0 && u<=4` / `v>=0 && v<=4` (mangled-literal and `jle` proofs); keep only the
|
||||
clear as the open question.
|
||||
- `_EncodeBlockRGBColorKey`: drop the projection-loop index-width clause (superseded) and narrow the criterion
|
||||
to rulings on (a), (b), (c).
|
||||
- `_DecodeBlockAlpha3__single_pixel`: record that the Microsoft 2003 corpus is measured to contain no
|
||||
single-pixel helper, and that the width alone yields 427 meaningful bytes (overshoot), so the reopen needs
|
||||
the EDX-accumulator distinction as well.
|
||||
4. **Lane-wide sweep (new, validated on this unit): assert / diagnostic literal spelling.**
|
||||
A wrong assert string is invisible to `gate.py` tags and appears only in `relocdiff --count-by-target` or
|
||||
`alndiff` relocation annotations. `scratch/workers/n3_s3tc/assertlit2.py` (read-only, ~20 s over all objects)
|
||||
compares the `??_C@` literal symbol sets of `build/split` and `build/base` and reports **39 objects that emit
|
||||
a literal January does not have**; output in `scratch/workers/n3_s3tc/assert_literal_sweep.txt`. s3tc.obj
|
||||
appears with exactly the 2 literals this wave repaired, which validates the detector. Same-class spot checks:
|
||||
`bitmap_group` ("space_between>=0" vs "space_between >= 0"), `rasterizer_xbox_screen_effect`
|
||||
("combiner_count<=RASTERIZER_MAXIM..." vs the spaced form, plus 4 `IDirect3DDevice8_SetVertexData2f`
|
||||
diagnostics of different length), `network_connection` (PROTECTED; the same defect in the opposite direction),
|
||||
and a shared `ai/encounters.h` assert set in `encounters`/`ai`/`ai_debug`/`actors`. The `real_math.h` trio
|
||||
(`projection>=_x && projection<=_z`, `~(sign&~1)`) in 7 objects is the systemic select-any header-inline class
|
||||
(A30), not a defect.
|
||||
5. **Laws addition (n3a).** MSVC `#expr` stringization preserves the source's internal token spacing, so a
|
||||
January `??_C@` assert literal names the original expression character-for-character (operator choice AND
|
||||
whitespace). Combined with the jcc opcode it is a two-proof recovery of assert source text, and the
|
||||
`_0<len>` field gives the exact character count before any candidate is built.
|
||||
@@ -0,0 +1,187 @@
|
||||
# `sound_manager.obj`: opus5 next-150K lane, wave n3a (structural park pass, 2026-09-15)
|
||||
|
||||
## 1. Scope and provenance
|
||||
|
||||
- Translation unit `source/sound/sound_manager.c`; target `build/split/source/sound/sound_manager.obj`.
|
||||
- Lane worktree `C:\halo-worktrees\opus5-150k-house-clean-20260914`, branch
|
||||
`opus/next-150k-house-clean-20260915`, frozen baseline `ae10935da`. XDK VC7 13.00.9254 with the repository
|
||||
flags; no flag changed or passed.
|
||||
- **Nothing was written to `sound_manager.c`, to any header, or to `config/*.json`.** No ninja, configure, pytest
|
||||
or git write command was run. `git diff --stat -- source/sound/sound_manager.c` is empty.
|
||||
- Worker notes `scratch/workers/n3_sound_manager.md`; candidates, objects and listings in
|
||||
`scratch/workers/n3_sound_manager/`.
|
||||
- Evidence: January split-object bytes, relocations and section order (authoritative); the in-TU EXACT donor
|
||||
`_refresh_sounds`; HCEA `reference/halocea/src/sound_refresh_looping.c` (later build, semantics only);
|
||||
`config/parked.json`; all eleven earlier `sound_manager_obj_*` ledgers; `scratch/w2/laws_w2.md` and
|
||||
`scratch/w3/laws_w3.md` applied as detectors.
|
||||
|
||||
## 2. Baseline and final state (identical)
|
||||
|
||||
`python -B tools/campaign/gate.py source/sound/sound_manager --all --forbid-emitted-symbol _point_from_line3d`
|
||||
reports `== exact 58 residual 7 unwritten 0 (of 65 listed)` at both ends; the guard passed;
|
||||
`scratch/parkcheck.py` on the real object reports `parks 5 drift 0`; `tools/fake_match_scan.py` reports 0 leads.
|
||||
`branch_sweep` finds no historical blob above 58 exact.
|
||||
|
||||
| Function | Target padded / relocs | Real file | Tag | Park | n3a result |
|
||||
|---|---:|---|---|---|---|
|
||||
| `_refresh_listener` | 496 / 25 | 496 / 25 | sha | - | skipped-exhausted |
|
||||
| `_sound_dispose_from_old_map` | 240 / 21 | 272 / 23 | size, relocs, sha | - | skipped-exhausted (census re-confirmed) |
|
||||
| `_sound_find_like_channel` | 272 / 16 | 272 / 16 | sha | P | skipped-exhausted |
|
||||
| `_sound_refresh_looping` | 1136 / 43 | 1088 / 42 | size, relocs, sha | P | **park re-baseline proposed: 1120 / 43** |
|
||||
| `_sound_set_definition_end` | 208 / 9 | 208 / 9 | sha | P | owner-blocked (mechanism now proven) |
|
||||
| `_update_channel_for_impulse_sound` | 528 / 29 | 528 / 29 | sha | P | skipped-exhausted |
|
||||
| `_update_channel_for_looping_sound` | 1360 / 61 | 1376 / 61 | size, sha | P | **park re-baseline proposed: 1360 / 61** |
|
||||
|
||||
## 3. Result
|
||||
|
||||
Nothing landed in the real file (both live targets are parked bodies). The wave produced three new byte-proven
|
||||
structural findings, two of which refute the recorded park premises outright, and a combined scratch candidate
|
||||
`scratch/workers/n3_sound_manager/cand.c` that improves both parked rows with zero regressions.
|
||||
|
||||
## 4. `_update_channel_for_looping_sound` - park premise REFUTED, size and relocations now exact
|
||||
|
||||
The park entry says "No unique source-level mechanism explains the residual". Two do.
|
||||
|
||||
**4.1 If/else arm order (closes the whole 16-byte size gap).** January `0x452 mov ecx,[ebp-0x1c]; 0x455 test
|
||||
byte [ecx],2; 0x458 jne 0x4e8` places the `_looping_sound_fake_impulse_sound_bit` arm FAR (0x4e8, after the
|
||||
function tail, ending `jmp 0x482`) and makes the `sound_definition_next_permutation(definition, ..., NONE)` arm
|
||||
the fall-through at 0x45e. The retained body emits the mirror image. VC7 lays if/else arms in source order
|
||||
(laws_w3 A39/A44; A27 is the accepted precedent for reading polarity off arm layout), so January's source writes
|
||||
the next_permutation arm first:
|
||||
|
||||
```c
|
||||
if (!TEST_FLAG(
|
||||
looping_definition->flags,
|
||||
_looping_sound_fake_impulse_sound_bit))
|
||||
{
|
||||
permutation_index = sound_definition_next_permutation(
|
||||
definition,
|
||||
sound->pitch_range_index,
|
||||
NONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
sound->type = _sound_stop_track;
|
||||
looping_sound->ordered_sounds_finished = TRUE;
|
||||
}
|
||||
```
|
||||
|
||||
Alone (`u1.c`) this takes the row from 1376/61 to **1360/61** - size and relocation count exact.
|
||||
|
||||
**4.2 `limited_pitch` is not a separate local (closes the whole frame permutation).** Frame census: both sides
|
||||
`sub esp,0x40`, eight 4-byte slots, none missing or extra, but three rotate:
|
||||
|
||||
| slot | January | retained body |
|
||||
|---|---|---|
|
||||
| [ebp-4] | `sound` | `sound` |
|
||||
| [ebp-8] | `pitch` / limit result (shared) | `channel` |
|
||||
| [ebp-0xc] | `channel` | `scale` |
|
||||
| [ebp-0x10] | `scale` | `pitch` / limit result |
|
||||
| [ebp-0x14] .. [ebp-0x20] | primary_sound_index, track, looping_definition, looping_sound | same |
|
||||
|
||||
January `fstp [ebp-8]` @0xdd stores `pitch` and `fst [ebp-8]` @0x2b2 stores the `limit_pitch` result into the
|
||||
SAME cell: one source variable with five references, which outranks `channel`. With two separate locals VC7 ranks
|
||||
each alone and the cell falls to fourth. Clamping in place removes the local:
|
||||
|
||||
```c
|
||||
pitch = limit_pitch(
|
||||
pitch,
|
||||
channel_get(sound->playing_channel_index)->pitch * pitch_range->natural_pitch,
|
||||
definition->maximum_bend_per_second);
|
||||
properties.pitch = pitch * pitch_range->playback_rate;
|
||||
```
|
||||
|
||||
With 4.1 (`u2.c`) every frame slot matches January: **1360 / 61 / `cb7925e4a26b9464`**, 418 vs 420 instructions.
|
||||
|
||||
**4.3 What is left (2 instructions, owner-blocked).** `@0x2ea` January `xor ecx,ecx; mov cx,word [edi+0x8e];
|
||||
push ecx` vs our `movzx ecx, word [edi+0x8e]; push ecx`, and `@0x37e` January's extra `xor eax,eax` before
|
||||
`call _channel_get_state`. Both are laws_w3 A34 zero-extension into a full push slot, the fingerprint of a 16-bit
|
||||
PARAMETER. `u3.c` proves an inline `(word)` cast at the call site is byte-inert, so there is no in-file lever.
|
||||
The size is already exact, so these four bytes are absorbed by padding.
|
||||
|
||||
## 5. `_sound_refresh_looping` - park premise REFUTED, relocations and block layout now exact
|
||||
|
||||
**5.1 The missing relocation is a source defect, not "a compiler-merged duplicate fade-call tail".** Confirmed
|
||||
and adopted from the w3c finding: deleting the `real fade_in_time;` phi local and writing the two
|
||||
`sound_start_fade` calls restores 43/43 with matching per-target counts and January's 0x14 frame.
|
||||
|
||||
**5.2 NEW: the `goto begin_stop;` spelling inverts the loop block layout.** The retained body emits the stop
|
||||
block FIRST (ours @0x1e0 `cmp word [ebx+0x52],2`, main path jumped to @0x2d2); January falls through into the
|
||||
main path @0x1db and jumps forward to the stop block @0x30a. Replacing the label and goto with the equivalent
|
||||
|
||||
```c
|
||||
if (refresh_state != _looping_sound_refresh_stop && !loop->ordered_sounds_finished)
|
||||
{
|
||||
...
|
||||
}
|
||||
else if (loop->state != _looping_sound_refresh_stop)
|
||||
{
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
reproduces January instruction-for-instruction from 0xaf to the end, and deletes a `goto`.
|
||||
|
||||
**5.3 NEW: the early exits do not return `result`.** January shares ONE frame cell `[ebp-1]` between `result`
|
||||
(`sete byte [ebp-1]` @0x10) and `new_looping_sound` (`mov byte [ebp-1],0` @0x80, `,1` @0xa5), which forces
|
||||
`source` into EBX (`mov ebx,[ebp+0x10]` @0xc, `push ebx` @0x93) - the retained body colours `result` into BL
|
||||
instead and has to reload `[ebp+0x10]`. Measured: any early exit that names `result` (`a2`, `a6`, and w1's S1)
|
||||
gives `result` its own cell `[ebp-2]` and loses the colouring; spelling both early exits
|
||||
`return !new_looping_sound;` (`a1.c`) reproduces January's shared cell and EBX exactly. HCEA corroborates the
|
||||
expression (`reference/halocea/src/sound_refresh_looping.c:117-125`, annotated as the original `return v16==0`).
|
||||
|
||||
`a1.c` = **1120 / 43 / `86e26bb3e59f7590`**, 365 vs 378 instructions, with only two facts left: January's
|
||||
`mov cl,1` @0x84 (the last flag-safe slot before `jne 0xaf`) and its private `mov al,cl` epilogue @0x451 for the
|
||||
stop-and-not-found return, where our build constant-folds that return and cross-jumps it into the `datum_delete`
|
||||
`mov al,1` epilogue. That is one tail-merge decision, laws_w3 A43 class. `a5` and `a7` refute the merged-exit and
|
||||
extra-local explanations.
|
||||
|
||||
## 6. The other rows
|
||||
|
||||
- **`_sound_set_definition_end`** (park, 208/9): 72 vs 73 instructions, the single difference being the same
|
||||
`xor eax,eax; mov ax,word [esi+0x8e]` vs `movzx`. `sd1.c` (a `word` local modelled on the EXACT in-TU donor
|
||||
`_refresh_sounds`, sound_manager.c:3233) yields `mov ax,word [...]` plus a compensating `movzx eax,ax`, so it
|
||||
is a clean negative. The mechanism is now proven: the January header declared a 16-bit third parameter for
|
||||
`sound_definition_find_pitch_range_by_pitch` while the exact `sound_definitions.c` definition is `long`. The
|
||||
owner already ruled that prototype an ABI lie (w1 4.4, w3c 5); per laws_w3 R13 the ruling binds and **no packet
|
||||
is proposed**. Recorded for the owner's original-bug adjudication only.
|
||||
- **`_sound_dispose_from_old_map`** (active residual, 272/23 vs 240/21): fresh census re-confirms the w3c
|
||||
finding - January's wait loop is unrotated (`0xa6 jmp 0x82` back to a single header), ours duplicates the whole
|
||||
10-instruction header into the latch (+12 instructions, +32 bytes, +2 relocations). 11 loop spellings across 6
|
||||
lanes are measured inert and no w2/w3 law fires on header duplication. No shape spent.
|
||||
- **`_refresh_listener`, `_sound_find_like_channel`, `_update_channel_for_impulse_sound`**: measured ties with
|
||||
their levers spent (w3c section 5). No shapes spent.
|
||||
|
||||
## 7. Proposals (orchestrator; zero strict credit)
|
||||
|
||||
Candidate `scratch/workers/n3_sound_manager/cand.c` = the current real file plus exactly the two reopened bodies
|
||||
(`a1` + `u2`). Measured: `== exact 58 residual 7 unwritten 0`, row-for-row identical to baseline except the two
|
||||
target rows; `_point_from_line3d` guard passed; `parkcheck` drift only on the two intended parks; owner census
|
||||
identical to `build/base` (no new candidate-only owner, 22 candidate-only vs target on both sides); fakescan 0.
|
||||
|
||||
1. Re-baseline `config/parked.json` `_sound_refresh_looping` 1088/42/`4820b25c...` -> **1120/43/`86e26bb3e59f7590`**
|
||||
and land `a1`'s body. Supersedes the w3c `rl1` proposal (also 1120/43 but still block-inverted).
|
||||
2. Re-baseline `_update_channel_for_looping_sound` 1376/61/`5fa29769...` -> **1360/61/`cb7925e4a26b9464`** and
|
||||
land `u2`'s body; reclassify the park from `unclassified` to the 16-bit-parameter owner-ruling class.
|
||||
|
||||
Both are strictly closer on every measured axis and both delete a local rather than adding anything.
|
||||
|
||||
## 8. Reopen criteria (replacing the recorded ones)
|
||||
|
||||
- `_sound_refresh_looping`: a source fact that stops VC7 constant-folding the stop-and-not-found
|
||||
`return !new_looping_sound;` and cross-jumping it into the `datum_delete` `return TRUE;` epilogue - i.e.
|
||||
anything that yields `mov cl,1` in the block ending at `jne` plus a private `mov al,cl` epilogue. Everything
|
||||
else in `a1.c` is byte-proven. Do not re-spend w1 S1-S8, waveC R1-R10, w3c rl1-rl3, or n3a a1/a2/a5/a6/a7.
|
||||
- `_update_channel_for_looping_sound`: an owner ruling on the width of
|
||||
`sound_definition_find_pitch_range_by_pitch`'s third parameter, plus a form that zero-extends
|
||||
`sound->playing_channel_index` into the full EAX before `channel_get_state`. Everything else in `u2.c` is
|
||||
byte-proven. Do not re-spend the frame-permutation or block-order searches, or `u3`'s cast.
|
||||
- `_sound_set_definition_end`: unchanged (same owner ruling).
|
||||
- `_sound_dispose_from_old_map`: an EXACT January sibling whose `while (call() < real)` loop keeps a single header
|
||||
copy, with a nameable source cause.
|
||||
|
||||
## 9. Disposition
|
||||
|
||||
`sound_manager.obj` stays at 58/65 strict exact; this wave claims no bytes. It leaves two actionable zero-credit
|
||||
park re-baselines that together take the two largest residual rows from 1088/42 and 1376/61 to 1120/43 and
|
||||
1360/61, and it reduces both to a single named compiler decision each.
|
||||
@@ -2620,32 +2620,52 @@ boolean sound_refresh_looping(
|
||||
_sound_start_track);
|
||||
}
|
||||
}
|
||||
else if (refresh_state == _looping_sound_refresh_stop)
|
||||
{
|
||||
goto begin_stop;
|
||||
}
|
||||
|
||||
if (loop->ordered_sounds_finished)
|
||||
if (refresh_state != _looping_sound_refresh_stop &&
|
||||
!loop->ordered_sounds_finished)
|
||||
{
|
||||
goto begin_stop;
|
||||
}
|
||||
|
||||
sound_definition_index = track->loop_sound.index;
|
||||
if (alternate && track->alternate_loop_sound.index != NONE)
|
||||
{
|
||||
sound_definition_index = track->alternate_loop_sound.index;
|
||||
}
|
||||
|
||||
if (sound_definition_index != NONE)
|
||||
{
|
||||
if (*playing_sound_index != NONE &&
|
||||
(refresh_state != _looping_sound_refresh_start ||
|
||||
!TEST_FLAG(track->flags, _fade_in_at_start_bit)))
|
||||
sound_definition_index = track->loop_sound.index;
|
||||
if (alternate && track->alternate_loop_sound.index != NONE)
|
||||
{
|
||||
sound_get(*playing_sound_index);
|
||||
sound_definition_index = track->alternate_loop_sound.index;
|
||||
}
|
||||
|
||||
if (alternate != loop->alternate &&
|
||||
TEST_FLAG(track->flags, _fade_in_alternate_bit))
|
||||
if (sound_definition_index != NONE)
|
||||
{
|
||||
if (*playing_sound_index != NONE &&
|
||||
(refresh_state != _looping_sound_refresh_start ||
|
||||
!TEST_FLAG(track->flags, _fade_in_at_start_bit)))
|
||||
{
|
||||
sound_get(*playing_sound_index);
|
||||
|
||||
if (alternate != loop->alternate &&
|
||||
TEST_FLAG(track->flags, _fade_in_alternate_bit))
|
||||
{
|
||||
long new_sound_index =
|
||||
update_potentially_audible_looping_sound(
|
||||
sound_definition_index,
|
||||
looping_sound_index,
|
||||
track_index,
|
||||
_sound_loop_track);
|
||||
|
||||
if (new_sound_index != NONE)
|
||||
{
|
||||
sound_start_fade(
|
||||
_sound_fade_mode_linear,
|
||||
track->fade_out_duration,
|
||||
new_sound_index,
|
||||
*playing_sound_index);
|
||||
*playing_sound_index = new_sound_index;
|
||||
}
|
||||
}
|
||||
else if (!new_looping_sound)
|
||||
{
|
||||
sound_set_definition_begin(
|
||||
*playing_sound_index,
|
||||
sound_definition_index);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
long new_sound_index =
|
||||
update_potentially_audible_looping_sound(
|
||||
@@ -2656,65 +2676,34 @@ boolean sound_refresh_looping(
|
||||
|
||||
if (new_sound_index != NONE)
|
||||
{
|
||||
sound_start_fade(
|
||||
_sound_fade_mode_linear,
|
||||
track->fade_out_duration,
|
||||
new_sound_index,
|
||||
*playing_sound_index);
|
||||
sound_get(new_sound_index);
|
||||
|
||||
if (refresh_state == _looping_sound_refresh_start)
|
||||
{
|
||||
if (TEST_FLAG(track->flags, _fade_in_at_start_bit))
|
||||
{
|
||||
sound_start_fade(
|
||||
_sound_fade_mode_linear,
|
||||
track->fade_in_duration,
|
||||
new_sound_index,
|
||||
NONE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sound_start_fade(
|
||||
_sound_fade_mode_linear,
|
||||
sound_inaudible_fade_out_time,
|
||||
new_sound_index,
|
||||
NONE);
|
||||
}
|
||||
|
||||
*playing_sound_index = new_sound_index;
|
||||
}
|
||||
}
|
||||
else if (!new_looping_sound)
|
||||
{
|
||||
sound_set_definition_begin(
|
||||
*playing_sound_index,
|
||||
sound_definition_index);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
long new_sound_index =
|
||||
update_potentially_audible_looping_sound(
|
||||
sound_definition_index,
|
||||
looping_sound_index,
|
||||
track_index,
|
||||
_sound_loop_track);
|
||||
|
||||
if (new_sound_index != NONE)
|
||||
{
|
||||
real fade_in_time;
|
||||
sound_get(new_sound_index);
|
||||
|
||||
if (refresh_state != _looping_sound_refresh_start)
|
||||
{
|
||||
fade_in_time = sound_inaudible_fade_out_time;
|
||||
}
|
||||
else if (TEST_FLAG(
|
||||
track->flags,
|
||||
_fade_in_at_start_bit))
|
||||
{
|
||||
fade_in_time = track->fade_in_duration;
|
||||
}
|
||||
else
|
||||
{
|
||||
*playing_sound_index = new_sound_index;
|
||||
continue;
|
||||
}
|
||||
|
||||
sound_start_fade(
|
||||
_sound_fade_mode_linear,
|
||||
fade_in_time,
|
||||
new_sound_index,
|
||||
NONE);
|
||||
*playing_sound_index = new_sound_index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
|
||||
begin_stop:
|
||||
if (loop->state != _looping_sound_refresh_stop)
|
||||
else if (loop->state != _looping_sound_refresh_stop)
|
||||
{
|
||||
if (fade_time != 0.f)
|
||||
{
|
||||
@@ -2740,16 +2729,16 @@ boolean sound_refresh_looping(
|
||||
*playing_sound_index);
|
||||
}
|
||||
|
||||
sound_definition_index = track->stop_sound.index;
|
||||
if (alternate &&
|
||||
track->alternate_stop_sound.index != NONE)
|
||||
if (track->stop_sound.index != NONE)
|
||||
{
|
||||
sound_definition_index =
|
||||
track->alternate_stop_sound.index;
|
||||
}
|
||||
sound_definition_index = track->stop_sound.index;
|
||||
if (alternate &&
|
||||
track->alternate_stop_sound.index != NONE)
|
||||
{
|
||||
sound_definition_index =
|
||||
track->alternate_stop_sound.index;
|
||||
}
|
||||
|
||||
if (sound_definition_index != NONE)
|
||||
{
|
||||
if (TEST_FLAG(
|
||||
track->flags,
|
||||
_fade_out_at_stop_bit))
|
||||
@@ -2786,7 +2775,8 @@ boolean sound_refresh_looping(
|
||||
|
||||
loop->alternate = alternate;
|
||||
loop->state = refresh_state;
|
||||
result = FALSE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2867,25 +2857,23 @@ static void update_channel_for_looping_sound(
|
||||
}
|
||||
else
|
||||
{
|
||||
real limited_pitch;
|
||||
|
||||
pitch_range = TAG_BLOCK_GET_ELEMENT(
|
||||
&definition->pitch_ranges,
|
||||
sound->pitch_range_index,
|
||||
struct sound_pitch_range);
|
||||
limited_pitch = limit_pitch(
|
||||
pitch = limit_pitch(
|
||||
pitch,
|
||||
channel_get(sound->playing_channel_index)->pitch *
|
||||
pitch_range->natural_pitch,
|
||||
definition->maximum_bend_per_second);
|
||||
properties.pitch = limited_pitch * pitch_range->playback_rate;
|
||||
properties.pitch = pitch * pitch_range->playback_rate;
|
||||
|
||||
if (sound->type == _sound_loop_track &&
|
||||
(sound->fade_start_time == sound->fade_stop_time ||
|
||||
sound->fade_interpolation_end != 0.f) &&
|
||||
sound_definition_find_pitch_range_by_pitch(
|
||||
definition,
|
||||
limited_pitch,
|
||||
pitch,
|
||||
(word)sound->pitch_range_index) != sound->pitch_range_index &&
|
||||
channel->sound_index == *primary_sound_index &&
|
||||
!sound_manager_globals.idling)
|
||||
@@ -2943,20 +2931,20 @@ static void update_channel_for_looping_sound(
|
||||
0xA1C,
|
||||
TEST_FLAG(definition->flags, _sound_definition_linked_permutations_bit));
|
||||
|
||||
if (TEST_FLAG(
|
||||
if (!TEST_FLAG(
|
||||
looping_definition->flags,
|
||||
_looping_sound_fake_impulse_sound_bit))
|
||||
{
|
||||
sound->type = _sound_stop_track;
|
||||
looping_sound->ordered_sounds_finished = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
permutation_index = sound_definition_next_permutation(
|
||||
definition,
|
||||
sound->pitch_range_index,
|
||||
NONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
sound->type = _sound_stop_track;
|
||||
looping_sound->ordered_sounds_finished = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (permutation_index != NONE)
|
||||
|
||||
Reference in new issue
Block a user