mirror of
https://github.com/Cesarus85/ringfall-mjolnir-vr.git
synced 2026-10-18 23:00:26 +02:00
Handoff: owner ruling queue (measured at cdc8ebd3), final handoff, waves 4-5 evidence
- docs/object_matching_logs/claude_fifty_objects_20260925_owner_queue.md: 14 held items, each apply-ready oncdc8ebd3with measured unlocks (18 objects on an all-yes; models and hs_scenario_definitions since superseded by canonical). - Ledger final handoff: commit order, changed paths, target vs result (18 of 50), tallies, house-rule review, held items, process incidents, and the trial merge against canonicaldbcea3d6(5 conflicting files, resolution guidance, and the dynavobgeom / SDK-table policy conflict with its census). - research/fifty_objects_20260925: waves 4-5 worker/reviewer ledgers, owner queue packets with APPLY_ORDER, and the integrator kit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
eb33baecf8
commit
4e84c212f3
359 files changed
+116543
-175
No files matched your search
@@ -333,3 +333,210 @@ review ledgers and patches, `results/wave*/` for the structured results).
|
||||
best non-exact candidates as `*.vs_tree.diff` against this tree. `.obj` files, split copies and
|
||||
symbols.json copies are excluded, and the folder is exempt from EOL and whitespace conversion so
|
||||
the patches stay byte-exact.
|
||||
|
||||
## Final handoff
|
||||
|
||||
- **Branch:** `claude/fifty-objects-20260925`. Local only; never pushed; canonical never edited.
|
||||
- **Base:** e9e62b78, the `git ls-remote` tip of `jonas/exact-pilots` at lane start.
|
||||
- **Tip:** the commit that adds this section. The last code commit is cdc8ebd3.
|
||||
- **Scorer:** objdiff-cli **3.3.1** (sha1 3130e428) for every number. Not upgraded; 3.6.0 figures appear only where marked scorer-only.
|
||||
|
||||
### Commit order
|
||||
|
||||
| Commit | Content |
|
||||
|---|---|
|
||||
| bf937aac | Batch 1: files_windows, objects; 5 exact functions; ownership corrections |
|
||||
| 931ed8dc | Layer 2: real_math.h helper bodies, provider hand-copy removal (**lock/unlock prototype move pending owner ruling**) |
|
||||
| b807f9f6 | Header prerequisites: objects.h `OBJECTS_H_FILE`, path.h HCEX field |
|
||||
| b9a8d587 | Batch 3: 12 objects, 4 exact functions |
|
||||
| 954eebd2 | Research evidence (waves 1-2) |
|
||||
| f7cd2e72 | Batch 4a: player_ui (game_engine.h/player_ui.h), sound_manager (sound_definitions.h) |
|
||||
| 6e3e2d35 | Batch 4b: dynavobgeom; damage `_object_damage_body`; storage packets |
|
||||
| 16542e46 | Ledger + wave-3 evidence |
|
||||
| 466698b8 | Batch 5a: hud_unit via the hud_draw.h `check_stack_buffer` inline (**P7 pending owner ruling**) |
|
||||
| cdc8ebd3 | Batch 5b: zero-credit storage and provider hygiene |
|
||||
| eb33baec | Ledger: batch 5 |
|
||||
| (this commit) | Owner queue, final handoff, wave-4/5 evidence |
|
||||
|
||||
Changed paths, excluding `research/`, as of eb33baec: 75 files, +3,717 / -4,304 lines. This commit adds the owner-queue doc.
|
||||
|
||||
- **config (5):** config.json, object_admission_rejections.json, parked.json,
|
||||
semantic_data_matches.json, symbols.json.
|
||||
- **Shared headers (10):** real_math.h, random_math.h, objects.h, path.h, game_engine.h,
|
||||
player_ui.h, sound_definitions.h, hud_draw.h, first_person_weapons.h, light_volumes.h.
|
||||
- **Source (59 .c files)** and **docs (2):** this ledger and the owner queue.
|
||||
|
||||
### Target vs result
|
||||
|
||||
**Target: 50 new complete Halo objects. Verified: 18** (361 -> 379). The evidence cannot support
|
||||
50 without owner rulings. The measured owner queue
|
||||
(`claude_fifty_objects_20260925_owner_queue.md`) adds 16 more on an all-yes, excluding the two
|
||||
items canonical already superseded. That gives 34, still short of 50. Every remaining
|
||||
self-landable residual in the pool is a documented tie, where the stop rule fired, or an
|
||||
owner-gated form.
|
||||
|
||||
| # | Object | Kind of work |
|
||||
|---:|---|---|
|
||||
| 1 | tag_files/files_windows | new code (file_get_size) |
|
||||
| 2 | objects/objects | provider repair (Layer 1) + data entry |
|
||||
| 3 | units/units | ownership: first-party names, storage, data entry |
|
||||
| 4 | physics/collision_debug | house-rule fix (/Od helper calls) + storage |
|
||||
| 5 | render/render_objects | provider packet (objects.h) + static-local storage |
|
||||
| 6 | camera/editor_flying_camera | new code + storage |
|
||||
| 7 | rasterizer/xbox/rasterizer_xbox_shadows | new code + storage |
|
||||
| 8 | cache/cache_files_windows | new code |
|
||||
| 9 | objects/widgets/light_volumes | new code + storage |
|
||||
| 10 | ai/actor_firing_position | admission (storage packet verified) |
|
||||
| 11 | ai/path | admission + path.h HCEX field |
|
||||
| 12 | units/biped_limp_noodle | storage (HCEX file statics) |
|
||||
| 13 | structures/leaf_map | house-rule fix (/Od helper calls) |
|
||||
| 14 | models/model_animations | house-rule fix (/Od helper call) |
|
||||
| 15 | interface/player_ui | shared-header layout recovery (game_variant) |
|
||||
| 16 | sound/sound_manager | new code + shared header |
|
||||
| 17 | rasterizer/xbox/rasterizer_xbox_dynavobgeom | view removal + storage (**see policy conflict below**) |
|
||||
| 18 | interface/hud_unit | header inline + house-rule fix (**P7 disclosure**) |
|
||||
|
||||
Checkpoints: 10 objects at b9a8d587. 20/30/40/50 were not reached. No 10,000-meaningful-byte
|
||||
checkpoint was reached either: the total is 8,775.
|
||||
|
||||
### Tallies (vs e9e62b78, objdiff 3.3.1)
|
||||
|
||||
| Tally | Value |
|
||||
|---|---|
|
||||
| 1. Net newly complete Halo objects | **18** |
|
||||
| 2. New strict functions | **14** (stable 8,245-function diff; 0 regressions) |
|
||||
| 3. New meaningful exact bytes | **8,775** |
|
||||
| 4. New padded exact bytes | **8,864** |
|
||||
| 5. New verified data bytes / admission-only closures | **3,294** / **12** |
|
||||
| 6. Fuzzy improvements at zero credit | `_main_update_time` 62.64 -> 98.99, `_main_frame_rate_debug` 94.52 -> 98.65, `_player_profile_write_thread_proc@4` 88.41 -> 88.45, first_person_weapons A 95.21506; more in `research/.../results/` |
|
||||
| Scorer-only (not counted) | +147 code / +7 functions (`$L` label credit on status flips); objdiff 3.6.0 would add hs 54,780 and actions 2,404 data bytes at zero source cost |
|
||||
| Regressions / revocations | **0 / 0** |
|
||||
|
||||
**Contingent credits:**
|
||||
|
||||
- Layer 2 ruling: `_convex_hull2d_perimeter`, `_player_set_action_result`, and the leaf_map,
|
||||
biped_limp_noodle, actor_firing_position, path and model_animations admissions.
|
||||
- P7 ruling: the hud_unit admission.
|
||||
|
||||
### House-rule review (source, headers, COMDATs, providers)
|
||||
|
||||
**Source.**
|
||||
|
||||
- Every landed packet passed an independent adversarial reviewer. Each reviewer checked house
|
||||
rules 1-22 and the strip test, ran /Od declaration-order checks for any new scope, and verified
|
||||
storage claims against cachebeta publics.
|
||||
- Where a reviewer issued an amendment, the amendment is what landed:
|
||||
- units (unit_vectors_are_valid);
|
||||
- light_volumes (/Od declaration order);
|
||||
- dynavobgeom (MAX);
|
||||
- hs (`hs_enumerate_scenario_data`, no cleanup COMDAT);
|
||||
- main (`main_exit` /Od shape);
|
||||
- damage (B+, not A);
|
||||
- player_ui (patch 07);
|
||||
- hud_unit (01RS; P6 dropped).
|
||||
- The fake-match lead count went 25 -> 26. The new lead is the /Od-attested empty then-arm in
|
||||
the still-parked first_person_weapons update.
|
||||
|
||||
**Headers.** Every shared-header edit landed with a full ninja and stable diff, with 0 regressions:
|
||||
|
||||
- real_math.h/random_math.h;
|
||||
- objects.h, path.h;
|
||||
- game_engine.h, player_ui.h, sound_definitions.h;
|
||||
- hud_draw.h;
|
||||
- first_person_weapons.h.
|
||||
|
||||
Count-sensitive edits are disclosed (Layer 2 move, P7). No filler declarations landed.
|
||||
|
||||
**COMDATs.** Newly emitted header-inline COMDATs come only from strictly exact callers (rule i).
|
||||
Each is identical to January's selected copy and passes provider links in both orders.
|
||||
|
||||
**Providers.** Four sets of NODUP hand copies were removed:
|
||||
|
||||
- Layers 1 and 2: 17 helpers;
|
||||
- action_vehicle `object_get_bounding_sphere`;
|
||||
- geometry `plane2d_distance_to_point`;
|
||||
- hud_draw `check_stack_buffer`.
|
||||
|
||||
Known remaining NODUP conflicts:
|
||||
|
||||
- actor_combat `cross_product2d` (owner item P1);
|
||||
- effects `real_local_random`;
|
||||
- player_control `limit2d`;
|
||||
- decals `plane2d_from_points`;
|
||||
- items `object_get_type`.
|
||||
|
||||
**Disclosed judgement calls:**
|
||||
|
||||
- the Layer 2 prototype move and P7 (count effects, pending rulings);
|
||||
- editor_flying_camera's /Od-attested dead `left` pair;
|
||||
- the descriptive names of rasterizer_xbox_shadows' gap statics and of the
|
||||
`match_assert_stack_frame` macro;
|
||||
- cache_files_windows' analog evidence;
|
||||
- rasterizer_lights' load-bearing `= {0}`. Canonical a595bbc2 later landed the same idiom for
|
||||
models.
|
||||
|
||||
### Held and rejected items
|
||||
|
||||
Every held item has an apply-ready packet, a ruling question and measured unlocks in
|
||||
`claude_fifty_objects_20260925_owner_queue.md`. The items with no object at stake are in the
|
||||
held-items table above. Evidence for each is under `research/fifty_objects_20260925/`.
|
||||
|
||||
Items that are not to be retried without new evidence:
|
||||
|
||||
- the brief's do-not-reopen list (decals/physics, path_obstacles parenthesis, aim_grenade goto, hud_draw pragma, s3tc, render_sprite, incompatible providers, flags `x * height`);
|
||||
- periodic_functions' DAG tie (~150 respellings);
|
||||
- the residuals whose stop rule fired, listed in `results/wave3` and `results/wave4`.
|
||||
|
||||
### Process incidents
|
||||
|
||||
Both happened in wave 3, inside reviewer agents, and both were repaired byte-exact before
|
||||
integration:
|
||||
|
||||
- `rm -rf .git` in the worktree root;
|
||||
- a hs.c rewrite by `volatile_scan.py`.
|
||||
|
||||
No tracked change resulted. The worker brief now forbids both patterns.
|
||||
|
||||
### Expected integration conflicts (trial `git merge-tree` against canonical dbcea3d6)
|
||||
|
||||
Canonical gained 9 commits after e9e62b78. The two lanes' new Matching sets are disjoint:
|
||||
canonical added models, hs_scenario_definitions and hs_globals_external. A resolved merge
|
||||
therefore expects **382** Halo objects, subject to a full gate. Five files conflict:
|
||||
|
||||
| File | Resolution guidance |
|
||||
|---|---|
|
||||
| `source/ai/path_structure_bsp.c` | Both lanes added the same HCEX tables (canonical e208c87b). Take canonical's spelling `static real const ...[8]`, drop this lane's comment, and re-gate (bytes expected identical). |
|
||||
| `source/hs/hs_scenario_definitions.c` | Take canonical's separate data definitions (Matching upstream). This lane's static `byte_swap_script_syntax_data` rename (6e3e2d35) is subsumed if canonical has it; keep canonical's symbols.json rows. |
|
||||
| `source/rasterizer/xbox/rasterizer_xbox_dynavobgeom.c` | Both lanes replaced the local views with genuine owner types. This lane also has the /Od helper calls, HCEX locals, the `warned` latch and MAX, and admits the object. Canonical 641e1466 keeps a narrowed rejection instead. **Policy conflict, needs an owner decision:** see below. |
|
||||
| `config/symbols.json` | Line-level overlaps on the dynavobgeom wrapper rows, the path_structure_bsp tables and the hs rows. Take the union; the rows are identical where both edited. Never re-serialise. |
|
||||
| `config/object_admission_rejections.json` | Take the union of retirements. This lane retired objects, leaf_map, biped_limp_noodle, units, the hud_unit `_fast_ftol` rejection and dynavobgeom. Canonical retired hs_scenario_definitions, hs_globals_external and models. Canonical's new narrowed dynavobgeom entry follows the policy decision below. |
|
||||
|
||||
Canonical also changed `tools/campaign/gate.py`, `stable_verdicts.py` and `verdicts.py`, which
|
||||
now identify functions by COFF type 0x20, so fastcall functions count. Re-take the stable
|
||||
snapshot after merging before comparing function counts.
|
||||
|
||||
**Dynavobgeom and SDK-table policy conflict.** Canonical 641e1466 declined to admit dynavobgeom
|
||||
for two reasons:
|
||||
|
||||
- the unreconciled `global_window_parameters` extern;
|
||||
- selected-provider links "not a complete ordinary program link" for the three stock D3D SDK
|
||||
tables every D3D8.h TU emits.
|
||||
|
||||
This lane admitted objects under the brief's criterion: identical to January's selected copy,
|
||||
plus pair links passing in both orders. A census on this tree (built objects vs build/split) finds:
|
||||
|
||||
- **55 objects canonical already lists as Matching emit the same three surplus D3D SDK tables.**
|
||||
- **9 of this lane's 18 admissions emit them too:** files_windows, objects, units,
|
||||
collision_debug, rasterizer_xbox_shadows, cache_files_windows, biped_limp_noodle,
|
||||
sound_manager and rasterizer_xbox_dynavobgeom.
|
||||
- Seven Matching objects declare `global_window_parameters` the same consumer-local way as
|
||||
dynavobgeom.
|
||||
|
||||
Two outcomes:
|
||||
|
||||
- If the owner applies canonical's stricter standard uniformly, those 64 objects need revisiting,
|
||||
not only this lane's.
|
||||
- If the owner keeps the brief's standard, canonical's narrowed dynavobgeom rejection should be
|
||||
retired at reconciliation.
|
||||
|
||||
This conflict was found at handoff, after all admissions landed.
|
||||
@@ -0,0 +1,502 @@
|
||||
# Fifty-object lane: owner ruling queue (measured at cdc8ebd3)
|
||||
|
||||
Every item below is a packet that is ready to apply to cdc8ebd3 and has been measured. The worker ledger for each item recorded its gate, whole-object audit, provider-link and data measurements. None of these packets has landed. Each item is one yes/no (or pick) question. The "Would complete" column lists every object that becomes COMPLETE on a yes. The integrator then applies the packet in APPLY_ORDER and runs the full batch gate: ninja, the stable 8,245-function diff, parks, admission, fake scan, pytest and diff-check.
|
||||
|
||||
If every item were a yes, **18** more Halo objects would complete (379 -> 397; +36 over the lane base, before any regression the full gate might show).
|
||||
|
||||
Packets and evidence: `research/fifty_objects_20260925/w/owner_queue/<lane>/` (patches/, APPLY_ORDER, RULING.md, MEASURED.md, LEDGER.md). The integrator kit is in `research/fifty_objects_20260925/integrator_kit/`.
|
||||
|
||||
**Canonical moved during the lane.** `jonas/exact-pilots` is now at dbcea3d6, 9 commits past this lane's base e9e62b78. It independently admitted models (a595bbc2, file-scope `= { 0 }` statics, the same form as item "models .bss" option P1), hs_scenario_definitions (c5fe0f40/d99a8658, separate data definitions) and hs_globals_external (3da50d63). **The models and hs_scenario_definitions items below are therefore SUPERSEDED by canonical**: take canonical's version at reconciliation and drop this lane's packets. Excluding them, a yes on every remaining item completes 16 objects.
|
||||
|
||||
| # | Item | Would complete | Functions gained | Apply-ready |
|
||||
|---:|---|---|---|---|
|
||||
| 1 | actor_combat P1 | ai/path_obstacle_avoidance, ai/path_smoothing, math/real_math, physics/collision_features, ai/path_structure_bsp | - | yes |
|
||||
| 2 | rasterizer_xbox .bss split with 9 descriptive static names (whole-object admission) | rasterizer/xbox/rasterizer_xbox | - | yes |
|
||||
| 3 | hs_scenario_definitions data split with 9 descriptive static names (whole-object admission, rejection retirement) **(SUPERSEDED by canonical)** | hs/hs_scenario_definitions | - | yes |
|
||||
| 4 | object_lights | objects/object_lights | - | yes |
|
||||
| 5 | render_debug | render/render_debug | - | yes |
|
||||
| 6 | game_engine admission pick | game/game_engine | - | yes |
|
||||
| 7 | rasterizer_xbox_hardware_geometry | rasterizer/xbox/rasterizer_xbox_hardware_geometry | - | yes |
|
||||
| 8 | models .bss **(SUPERSEDED by canonical)** | models/models | - | yes |
|
||||
| 9 | dead_camera _dead_camera_update | camera/dead_camera | _dead_camera_update | yes |
|
||||
| 10 | saved_game_files _saved_game_files_enumerate_available_to_local_player_index | saved games/saved_game_files | _saved_game_files_enumerate_available_to_local_player_index | yes |
|
||||
| 11 | first_person_weapons patch B (authentic unguarded NULL dereference of first_person_weapon_animations; rebased onto cdc8ebd3 after patch A landed in b9a8d587) | interface/first_person_weapons | _first_person_weapon_update | yes |
|
||||
| 12 | player_profile R1-R3 (uninitialised serialised 512-byte block; seek failure skips file_close; close(&file, NONE) after delete-while-open), rebased onto cdc8ebd3 after zero-credit packet A landed in 6e3e2d35; R3 BUG comment amended | saved games/player_profile | _player_profile_create_default_profiles_on_disk, _player_profile_write_thread_proc@4, _player_profile_new | yes |
|
||||
| 13 | game_engine_king | game/game_engine_king | - | yes |
|
||||
| 14 | glow _get_particle_world_position | objects/widgets/glow | _get_particle_world_position | yes |
|
||||
|
||||
Items landed but pending a ruling, which are not in the table above:
|
||||
|
||||
- **Layer 2** (931ed8dc): the lock/unlock_global_random_seed prototype move.
|
||||
- **P7** (466698b8): the dead hud_draw.h include in rasterizer_xbox_models.
|
||||
|
||||
Both are described in the main ledger, with their revert costs.
|
||||
|
||||
Held items with no object at stake are listed in the main ledger's held-items table:
|
||||
|
||||
- main header_swap and main_crash;
|
||||
- transport `net_startup_debug();`;
|
||||
- the damage A and hs cleanup COMDATs;
|
||||
- actions grouped data;
|
||||
- breakable_surfaces B1;
|
||||
- network_connection;
|
||||
- rasterizer_xbox_profile;
|
||||
- bitmap_drawing.
|
||||
|
||||
## 1. actor_combat P1: cross_product2d (remove the NODUP hand copy and restore the /Od-attested call in _actor_aim_grenade)
|
||||
|
||||
- **Question:** Should patch 01 be admitted while _actor_aim_grenade is still not strict exact (576 bytes vs January's 544)? Patch 01 deletes actor_combat.c's hand-written NODUP cross_product2d copy and its #define/#undef cross_product2d_inline rename, so the genuine real_math.h __inline emits January's actor_combat-owned _cross_product2d section. It also spells the /Od-attested call as cross_product2d((real_vector2d const *)&actor->input.facing_vector, &aim_vector2d) > 0.0f. All 88 actor_combat sections stay byte-identical; the only change is the _cross_product2d COMDAT selection, NODUPLICATES -> ANY. If YES, patches 02 and 03 (or 03b) also apply, and 5 objects are admitted (Halo 379 -> 384).
|
||||
- **Would complete:** source/ai/path_obstacle_avoidance; source/ai/path_smoothing; source/math/real_math; source/physics/collision_features; source/ai/path_structure_bsp
|
||||
- **Packet:** `research/fifty_objects_20260925/w/owner_queue/p1_cross_product2d`
|
||||
- **Apply-ready at cdc8ebd3:** yes
|
||||
|
||||
**Evidence for.** 1. /Od fn 0x44ebb0 is _actor_aim_grenade (from its RTC names). At 0x44ed38-0x44ed45 it pushes &horizontal_aim_vector and actor+0x140 (facing_vector, a real_vector3d), then calls cross_product2d (fn 0x455250). That is a real call with the 3D facing vector as the 2D operand, and it is the only cross_product2d caller in the actor_combat range.
|
||||
2. January's own bytes bind &facing_vector once (lea ecx,[edi+0x174] at 0xe4) and read both inlined 2D products through that register. This is the pointer-parameter signature. h.j*f.i-h.i*f.j at 0x105-0x120 is the only 2D cross product in the whole object.
|
||||
3. January selected actor_combat's _cross_product2d. The genuine header inline emits a byte-identical copy, so P1 adds NO surplus. It removes a Rule-6 hand copy of the same class as the 17 removed by the Layer 1/2 repairs.
|
||||
4. The only known EXACT diagnostic of aim_grenade (G1) is built on the /Od helper-call list, with _cross_product2d coming from the header.
|
||||
5. The same cast expression is already landed in Matching objects: action_obey:2593 and :1259, and action_vehicle:395.
|
||||
6. Status-quo cost: 10 objects carry an LNK2005 on _cross_product2d, and 5 of them are otherwise complete.
|
||||
|
||||
**Evidence against.** 1. The caller _actor_aim_grenade is not strict exact (576 vs 544, the held declaration-scope/goto residual). Both law (i) and the view-cast rule require a strictly exact caller, and byte exactness cannot tell the call apart from the hand expansion at this site.
|
||||
2. The /Od build is a later revision; January's scope for horizontal_aim_vector differed from it (frame 0x24 vs 0x28).
|
||||
3. P1 restores only cross_product2d. The adjacent /Od-attested dot_product2d(&facing,&h) stays hand-expanded, because restoring it would newly emit a _dot_product2d COMDAT from the non-exact caller.
|
||||
4. Precedent risk: admitting a byte-inert header-COMDAT respelling in a non-exact caller. The proposal limits this to sections the same object already owns in January's split, with no new surplus.
|
||||
|
||||
**Still blocked / integrator notes.** Nothing in the packet is blocked. The integrator still owes the full batch gate: ninja, stable_verdicts sweep, parks, admission audit, fake scan and pytest. Workers may not run these, but since only actor_combat.c changes and it is byte-identical apart from the COMDAT selection, a zero-regression result is expected.
|
||||
|
||||
actor_combat itself stays NonMatching: aim_grenade and plan_grenade_trajectory are residual, and it has 4 pre-existing _actor_combat_*_inline externals with no January provider.
|
||||
|
||||
These objects lose the cross_product2d failure but remain incomplete:
|
||||
- decals: 2 residuals; patch 03b optionally retires its now-premise-less _cross_product2d rejection
|
||||
- collision_bsp: 3 residuals
|
||||
- actor_looking: _actor_look_update
|
||||
- geometry: 3 residuals plus a _plane2d_from_points conflict
|
||||
- bipeds: 9 residuals plus an _object_get_type conflict
|
||||
|
||||
**Measured.** All measured at cdc8ebd3; the tree was clean before and after.
|
||||
|
||||
Patches: the wave-2 patch applies unchanged, because actor_combat.c did not change between 931ed8dc and cdc8ebd3. The patched file is byte-identical to wave-2 p1.c. git apply --check is clean for 01, 02 and 03 each, for 01+02+03 together, and for 01+02+03b together. A sandbox apply on the cdc8ebd3 blobs gives 497 -> 502 Matching statuses and 8 -> 7 rejections.
|
||||
|
||||
actor_combat gate --all: production, P1 and P1-strip all give 32 EXACT plus the same 2 residuals (_actor_aim_grenade 576/544 sha e9bba5b0; parked _actor_combat_plan_grenade_trajectory 288/5 sha ff9a7477, which equals the park base). A keyed raw-COFF diff over 88 sections finds exactly 1 difference between production and P1: _cross_product2d NODUP -> ANY. P1 against P1-strip: 0 differences, so the view cast is byte-inert. object_audit output is identical for production and P1: FAIL(2), the two residuals only, 0 of 60 symbols differ. /W3 warnings are the same 17 for P1; the strip adds only C4133. The fake scan finds 0 leads in either version.
|
||||
|
||||
The five objects (tree source, no change; each gate object is keyed-identical to build/base):
|
||||
- path_obstacle_avoidance: 24/24 EXACT, audit PASS (52 symbols, 0 differ), PDB 0, surplus 0 of 11 not identical
|
||||
- path_smoothing: 6/6, PASS (15), PDB 0, 0 of 10
|
||||
- real_math: 84/84, PASS (134), PDB 0, 0 of 35
|
||||
- collision_features: 20/20, PASS (30), PDB 0, 0 of 29; _projection_from_vector3d is IDENTICAL to January's decals copy and links PASS, so its rejection is stale
|
||||
- path_structure_bsp: 6/6, PASS (13), PDB 0, 0 of 10; the HCEX tables are already landed and the split is current
|
||||
|
||||
provider_link against production actor_combat: each of the five is FAIL(1), on _cross_product2d only. Against P1 (provlink2 --subst=source/ai/actor_combat:P1 obj, both orders): all PASS, every row. objdiff 3.3.1 report shows all five at 100% code, functions and data. The admission audit, emulated with the five marked complete and the rejection from patch 03 removed, reports 0 contradicted and 0 revoked.
|
||||
|
||||
Board census: there are 11 _cross_product2d definers. All 10 non-actor_combat copies are SELECT_ANY and section_infos_equal to January's copy. All 10 FAIL the pair link against production and PASS against P1. After P1:
|
||||
- actor_looking, decals and collision_bsp have no link failures left, but still have function residuals (15/16, 31/33, 27/30).
|
||||
- geometry still fails on _plane2d_from_points and has 27/30 functions.
|
||||
- bipeds still fails on _object_get_type and has 42/51 functions.
|
||||
|
||||
No symbols.json, header, parked.json or semantic_*.json change is needed.
|
||||
|
||||
## 2. rasterizer_xbox .bss split with 9 descriptive static names (whole-object admission)
|
||||
|
||||
- **Question:** Should rasterizer_xbox be admitted as Matching? The invented rasterizer_xbox_d3d_globals aggregate and its 23 #define redirects become 23 '= 0' file statics. 14 of the names are bare in January's IDirect3D*() strings. The 9 below are not first-party: - node_matrix_constants (+0x000): INVENTED. - bitmap_dimensions_non_blocking (+0x840): HCEX-convention stem (HCEX static-local 'dimensions'; the HCEX scope form is refuted for January's .bss order). - bitmap_dimensions (+0x844): HCEX-convention stem, same as above. - global_d3d_texture_render_primary[2] (+0x84C): convention stem (January global_d3d_{texture,surface}_<target> pattern plus the HCEX/Od _rasterizer_target_render_primary enum). - global_d3d_surface_render_primary (+0x854): convention stem; January attests the sibling _render_primary_z. - global_d3d_texture_render_secondary_z (+0x860): convention stem (render_secondary and the _z suffix are attested). - global_d3d_surface_render_secondary_z (+0x868): convention stem, same as above. - global_d3d_texture_render_primary_copy (+0x8A0): INVENTED '_copy' suffix. - global_d3d_surface_render_primary_copy (+0x8A4): INVENTED '_copy' suffix. Yes = apply patches 01-05. No = nothing lands; the object stays NonMatching with object_audit FAIL(22).
|
||||
- **Would complete:** source/rasterizer/xbox/rasterizer_xbox
|
||||
- **Packet:** `research/fifty_objects_20260925/w/owner_queue/names_xbox_hs_scen`
|
||||
- **Apply-ready at cdc8ebd3:** yes
|
||||
|
||||
**Evidence for.** - Fake-stringification: January's strings name 14 of the globals bare, and no string contains 'rasterizer_xbox_d3d_globals', so the aggregate is invented.
|
||||
- '= 0' declaration order reproduces January's .bss exactly. The strip test fails the audit on 23 rows, so the initialisers are layout-attested.
|
||||
- There is no cachebeta public in 0x45E028..0x45E8CF, so every name is static.
|
||||
- Every other audit row is first-party: HCEX static-local srcblend/destblend/blendop_table; the filthy_bitmap_defaults_initialize rename (atlas, 2001 map, HCEX); d3d_palette strings; January's D3DDevice_ flicker relocations.
|
||||
- Counter-precedents: rasterizer_xbox_shadows was admitted with 2 disclosed descriptive gap statics; collision_debug's descriptive split landed for function credit; eb33baec landed the descriptive macro name match_assert_stack_frame.
|
||||
|
||||
**Evidence against.** - The 2026-09-15 owner ruling prefers no descriptive or invented static names in symbols.json; it held the env_fog (21) and models (13) .bss splits.
|
||||
- The 2026-09-24 canonical held path_obstacle_avoidance because its 'BSS relabel lacks authenticated private identities'.
|
||||
- 3 of the 9 names are invented outright (node_matrix_constants and the two _copy names).
|
||||
- The packet's block comment says the error strings name 'these globals' bare, which overstates it for the 9. RULING.md proposes an optional byte-inert disclosure comment; it is not in the patch.
|
||||
|
||||
**Still blocked / integrator notes.** Only the owner's policy ruling on the 9 names. There is no technical blocker.
|
||||
|
||||
Rebase note: a NEW required config change at cdc8ebd3. 05_parked.json.patch re-baselines __rasterizer_model_draw, because models.c lost its hud_draw.h include and patch 02's prototype removal now flips a declaration-count tie in that parked fuzzy body. It has no strict effect and needs no source change.
|
||||
|
||||
Independent and not name-gated: the reviewer-approved rasterizer_xbox_debug static-wrapper symbols patch (object_audit FAIL(8) -> PASS, gate 18/18, split radius 1) is included under patches/independent/.
|
||||
|
||||
**Measured.** At cdc8ebd3 (HEAD later moved to eb33baec, a docs-only commit; patches re-checked clean there).
|
||||
|
||||
Apply checks:
|
||||
- All 4 wave-2 patches apply as-is. I regenerated them with zero offsets as 01-04.
|
||||
- The post-image .c equals the worker's cand_L.c, and the header equals the worker's header.
|
||||
|
||||
Split and gate:
|
||||
- csplit with the patched config: of 833 objects, only rasterizer_xbox.obj changes. The control split equals build/split.
|
||||
- gate, candidate plus patched header (shadow; the #error control proves it is used) vs the emulated split: 95/95 EXACT, and the _point_from_line3d guard passes.
|
||||
|
||||
Audits:
|
||||
- object_audit (split override): PASS. 188 sections ok (.bss 2230 8-align, blend .rdata 108 4-align, .data 6) and 216/216 symbols. Production is FAIL(22).
|
||||
- provider_link: PASS 15/15 in both orders.
|
||||
- Storage vs cachebeta: 216/0 disagreements (production has 25).
|
||||
- /W3 warnings identical to production; fake_match_scan 0.
|
||||
|
||||
Data: objdiff 3.3.1 identical for production and candidate: data 9048/9048, code 91/95 raw with the same 4 pre-existing under-credits.
|
||||
|
||||
Header blast radius (7 includers):
|
||||
- 6 objects are byte-identical.
|
||||
- rasterizer_xbox_models: the PARKED __rasterizer_model_draw moves (sha 89b0d7ea -> cbfa8585 at the same 5168 bytes / 348 relocs; objdiff 95.08453 -> 95.07629; strict status unchanged at 12/2).
|
||||
- tools.parked_functions reports STALE 1 without a re-baseline, and active 2 / stale 0 with the new 05_parked.json.patch.
|
||||
|
||||
Names are load-bearing: reverting only the .bss rows gives gate 86/95 (9 reloc-identity residuals) and audit FAIL(15).
|
||||
|
||||
Combined application with item 2 (either route) is clean, and the post-images are cmp-identical when applied outside the repo.
|
||||
|
||||
## 3. hs_scenario_definitions data split with 9 descriptive static names (whole-object admission, rejection retirement) (SUPERSEDED by canonical; see top)
|
||||
|
||||
- **Question:** Should hs_scenario_definitions be admitted as Matching? The invented wrapper structs, #pragma pack, 11 __declspec(align(4)) and the field_table_alignment padding member become 18 separate January data definitions. This retires the source-layout-incomplete rejection and adds 9 non-first-party static names: - hs_scripts_block_fields (+0x018): HCEX-convention stem; <block>_fields plus January's public block name. - hs_globals_block_fields (+0x090): HCEX-convention stem. - hs_references_block_reference (+0x110): INVENTED; no convention exists for a TU-local any-tag tag_reference_definition. - hs_references_block_fields (+0x11C): HCEX-convention stem. - hs_source_files_block_fields (+0x17C): HCEX-convention stem. - data_array_header_bs_codes (+0x1CC): HCEX-convention stem; <name>_bs_codes plus January's own string 'data_array_header'. - data_array_header_bs_definition (+0x204): HCEX-convention stem. - syntax_node_bs_codes (+0x218): HCEX-convention stem; stem is January's string 'syntax_node'. - syntax_node_bs_definition (+0x240): HCEX-convention stem. Yes = route A (A01-A04) or route C (C01-C03 + A02-A04; C adds HCEX's MAXIMUM_HS_*_PER_SCENARIO enum to the shared header). No = nothing lands; the rejection stays; data stays 484/1112.
|
||||
- **Would complete:** source/hs/hs_scenario_definitions
|
||||
- **Packet:** `research/fifty_objects_20260925/w/owner_queue/names_xbox_hs_scen`
|
||||
- **Apply-ready at cdc8ebd3:** yes
|
||||
|
||||
**Evidence for.** - It retires every objection the rejection cites: invented aggregates, pack/align directives and the padding member.
|
||||
- .data alignment 8 arises naturally from the two field arrays of 64 bytes or more; the 0x8C..0x90 gap is VC7's per-object alignment pad.
|
||||
- The candidate's .rdata literal order equals January's. This attests the block-before-fields definition order, and January's leaf_map shows the same idiom.
|
||||
- The data credit is native, with no semantic_data_matches entry.
|
||||
- 8 of the 9 names come mechanically from January's own names (public block names, byte_swap_definition name strings) via HCEX-attested Bungie conventions: 10 *_block_fields and 23 *_bs_definition in HCEX.
|
||||
- Route C's enum is HCEX's exact enum, and January's hs_compile assert text attests it.
|
||||
|
||||
**Evidence against.** - The 2026-09-15 owner ruling prefers no descriptive or invented static names in symbols.json.
|
||||
- hs_globals_external was rejected because a later build does not authenticate its names; here HCEX has no hs_scenario_definitions compiland at all, so no build authenticates these names.
|
||||
- hs_references_block_reference is invented.
|
||||
- The packet has no disclosure comment for the names; RULING.md offers an optional byte-inert one.
|
||||
- Two new C4090 warnings, caused by the reconstructed tag_groups.h 'char **names' member type.
|
||||
|
||||
**Still blocked / integrator notes.** Only the owner's policy ruling on the 9 names; there is no technical blocker. The owner may rename any single name, for example #3, as a pure rename in A01+A02.
|
||||
|
||||
The function rename (the reviewer fallback) already landed in 6e3e2d35, so no fallback remains. A no leaves the object at the current rejection with 484/1112 data.
|
||||
|
||||
**Measured.** Rebase at cdc8ebd3:
|
||||
- The worker's A, B and C2 no longer applied, because 6e3e2d35 landed the static byte_swap_script_syntax_data rename.
|
||||
- A01 and C03 are the worker's final post-images (cand1.c/cand2.c, CRLF) diffed against the tree; they carry only the data split.
|
||||
- A02 is the 9 inserted static rows only.
|
||||
- D is split into A03 (config.json) and A04 (rejection removal).
|
||||
- C1 is reproduced as C01 (header) + C02 (hs.c).
|
||||
- Every patch passes git apply --check, alone and per route, and together with item 1. Post-images applied outside the repo are cmp-identical.
|
||||
|
||||
Split: csplit with the edited config changes only hs_scenario_definitions.obj (833 compared).
|
||||
|
||||
Gate, audit and storage:
|
||||
- gate vs the emulated split: EXACT 224 _byte_swap_script_syntax_data 1/1 for both routes (route C with the shadow header and an #error control), guard passed.
|
||||
- object_audit: PASS for both routes. 23 sections ok, including .data 628/628 with align 4/4 (January's 8-byte alignment), and 40/40 symbols. Production is FAIL(1) on alignment.
|
||||
- Storage: 40/0; none of the 9 names is a cachebeta public.
|
||||
- provider_link: nothing to link, PASS.
|
||||
|
||||
Data:
|
||||
- objdiff 3.3.1: 1112/1112 native, +628 data bytes (production 484/1112, .data 92.773094).
|
||||
- Without the 9 symbols.json rows, .data is 48.931007%, so the rows are load-bearing.
|
||||
|
||||
Route C consumer sweep (re-run because hs.c changed heavily in 6e3e2d35):
|
||||
- hs 447/1 (1410 sections, 0 differ), hs_compile 61/3 (0 differ), hs_runtime 64/2 (0 section diffs; 64 $L names shift only).
|
||||
- objdiff per-function maps are identical to build/base.
|
||||
|
||||
Other checks: /W3 adds 2 C4090 (byte-inert, disclosed); fake_match_scan 0. No parks involved.
|
||||
|
||||
## 4. object_lights: the surplus _object_get_bounding_sphere copy that carries its per-TU __FILE__ literal, plus data_gap's packet (4 statics, the should_render_lights call, the _lights_section entry)
|
||||
|
||||
- **Question:** Should we admit object_lights' surplus _object_get_bounding_sphere COMDAT as it is? It matches January's selected action_vehicle copy in size (144), normalized bytes, all 9 relocation sites/types and 7 of 9 targets. Only its two __FILE__ DIR32 targets differ: they point to "c:\halo\source\objects\objects.h", which is January object_lights' own 33-byte .rdata literal, instead of "..\objects\objects.h". Rule 6 as written ('byte-identical to the selected provider') cannot be met by any source, because object_audit requires that January-owned literal and VC7 emits it only when this COMDAT references it. YES: apply 01, 02, 03_YES, 04_YES and object_lights becomes Matching. NO: 01 and 02 can still land at zero credit, and optionally 03_NO_ALT (+1,541 data under allow_incomplete_unit).
|
||||
- **Would complete:** source/objects/object_lights
|
||||
- **Packet:** `research/fifty_objects_20260925/w/owner_queue/objlights_render_debug`
|
||||
- **Apply-ready at cdc8ebd3:** yes
|
||||
|
||||
**Evidence for.** The January string census gives one owner per spelling. The c:\ objects.h literal is defined only in object_lights, and no relocation anywhere references it. The ..\ literal is defined by action_vehicle and imported by render_objects. _object_get_bounding_sphere is defined by action_vehicle and imported (UNDEF) by the other 8 users, object_lights included. NEW: of 9,420 January literals across all 833 split objects, exactly one has no referrer, and it is this literal, so its only possible referrer is object_lights' own discarded COMDAT copy. The /Od build asserts in 0x443f50 (object_get_bounding_sphere) with "D:\P4\Halo1\source\objects/objects.h", which shows the header used plain __FILE__. Link order is consistent: the image is in descending module order and action_vehicle (module 461) precedes object_lights (152), so a pick-first link keeps the ..\ copy January selected. The P2 control (a single-spelling header) loses the January-owned .rdata: the audit reports it MISSING and data credit drops by 1,100.
|
||||
|
||||
**Evidence against.** The rule 6 text is not met literally, so this is a new exception class: an authentic non-identical surplus COMDAT, proven by an orphan January literal. A whole-program relink that put object_lights first would select the c:\ copy. That cannot happen with January's link order and changes no January-owned section.
|
||||
|
||||
**Still blocked / integrator notes.** Nothing, once the owner answers yes. Advisory: object_lights also carries 5 consumer-local externs with no definer: debug_lights, debug_object_lights, light_data, light_cluster_partition, debug_rasterizer_light_count. They are the same class as render_debug (e). Precedent does not treat that class as a blocker (render_objects and scenario are Matching with such externs). Optional patch 07 resolves them as tentative definitions: byte-inert, and links clean against January's linker_common in both orders.
|
||||
|
||||
**Measured.** Every patch applies at cdc8ebd3. `git apply --check` is clean for each patch alone and for the YES set, the YES+(e) set, the NO set and 01-08 together. The patches are LF; applied one at a time in a throwaway repo with core.autocrlf=true, they reproduce the measured trees byte for byte. The data_gap object_lights.patch rebased unchanged (every hunk offset +4 by the landed OBJECTS_H_FILE define). symbols.json needs 4 in-place "static": true rows; the edited copy is ./symbols.json. Control: csplit with an unmodified config copy reproduced build/split 833/833. With the 4 rows (cfg_OL), only object_lights.obj changes. object_lights is 43/43 EXACT against the emulated split. object_audit PASS: 71 January symbols, 0 differ. The production object against the same split FAILs on exactly the 4 storage rows. pdb_storage: 0 disagreements. The other object_lights_rendering.h includers (render 13/13, render_objects 22/22) are objcmp-IDENTICAL to build/base. surplus: 12 candidate-only COMDATs, 11 identical; the only different one is _object_get_bounding_sphere (only the DIR32 rows at +37/+76 differ). provider_link PASS in both orders for all 33 surplus names. Mini objdiff 3.3.1: code 12294/12294, 43/43, data 1104/2645. Running tools.semantic_progress.apply_semantic_data_matches on the entry credits +1541 (2645/2645) for both the YES entry (unit complete) and the NO_ALT entry (allow_incomplete_unit). The negative control fails closed as expected. fake_match_scan: 0 leads. /W3: only the pre-existing C4133 and C4244 warnings. The full tree built from the patch files only (treeFINAL) gives the same rows: action_vehicle 17/17 and every includer identical.
|
||||
|
||||
## 5. render_debug: helper/vehicle patch (a)-(c), plus the held (d) invented render_debug_globals_definition aggregate and (e) six consumer-local extern boolean debug_*
|
||||
|
||||
- **Question:** (d) How should render_debug's 29,708-byte cache state be spelled? D1: seven separate zero-initialised file statics in the aggregate's member order, with descriptive names render_debug_cache_{strings,entries,game_time,entry_count,string_offset,entry_overflow_reported,string_overflow_reported}. This needs a symbols.json rename plus 6 static rows (lab/D1_OPTION_*.patch). D0: admit the existing aggregate, with its two opaque pad arrays, as it is. Or HOLD. Either yes, with 05 (+06) and 08, makes render_debug Matching. (e) is answerable without a ruling: January's definer is render_debug.c itself (tentative definitions the linker pooled into COMMON). The integrator only needs to confirm optional patch 06, bare `boolean debug_bsp;` etc., the same form as the objects.c precedent.
|
||||
- **Would complete:** source/render/render_debug
|
||||
- **Packet:** `research/fifty_objects_20260925/w/owner_queue/objlights_render_debug`
|
||||
- **Apply-ready at cdc8ebd3:** yes
|
||||
|
||||
**Evidence for.** (e): The six are January linker_common COMMON records 50-55 (1 byte each), referenced only by render_debug.obj and hs_globals_external.obj. Pool oracle over all 242 records: 102 of 105 single-referencer records follow module order. hs_globals_external references 81 pool records and is the position-admissible owner of none of them. The six sit between render_objects' cluster and render's _render, and render_debug (module 87) is the only referencer in that range. The 2001 Bungie linker maps show the six exist exactly when render_debug.obj is linked: 08-15 beta has 5 toggles and no render_debug_structure_decals; 09-25 beta adds debug_permanent_decals together with its only user, render_debug_structure_decals; 09-25 retail has no render_debug.obj and none of the six, while render_objects/render records and other hs toggles remain. The later /Od build interleaves the six byte by byte with render_debug's own cache variables (0xf0afb0-0xf0afc0), which only one object's .bss can do. (d): January's short/gap/short/gap/short/bool/bool layout equals separate `= 0` statics; the aggregate needs pad members (the law (j) signature of an invented aggregate). In the /Od build, hs toggles sit inside the cache-variable span, so it was not a struct there.
|
||||
|
||||
**Evidence against.** (d): No first-party names exist anywhere (cachebeta publics, HCEX.pdb, the 2001 maps, the atlas), so D1 adds 7 descriptive .bss names, an already-held class. The zero initialisers are layout-evidenced, not text-attested. (e): The 2026-09-22 canonical reconciliation excluded a 116-definition COMMON wave because pool adjacency cannot prove TU ownership (rasterizer_frame_statistics counterexample). This packet uses per-symbol evidence (map presence/absence and /Od interleaving), but the /Od build is a later revision, so the integrator should confirm the evidence standard. Advisory: render_debug has 6 C4013 implicit declarations (ai_debug_render and collision_debug_render lack their header includes; 4 callees have no header prototype at all). Production has them too; render.c is Matching with 2 C4013.
|
||||
|
||||
**Still blocked / integrator notes.** (d) needs the owner's choice between D1 and D0 (the naming class). Without it render_debug stays NonMatching, though 05 and 06 can land at zero credit. The C4013 debt is a reviewer advisory that needs owner-header edits with a declaration-count sweep; it was not touched here.
|
||||
|
||||
**Measured.** The review_admit2 (a)-(c) patch (05) applies unchanged at cdc8ebd3; render_debug.c and vehicle_datum.h have not changed since 931ed8dc. render_debug: 36/36 EXACT, object_audit PASS (63/0), pdb_storage 0. surplus: 12 COMDATs, 0 not identical; the new _point_from_line3d is identical to action_charge's selected copy, and its callers are strictly exact. provider_link PASS in both orders. vehicle_datum.h is included only by actor_moving (31/36), physics (13/17) and vehicles (37/39), all objcmp-IDENTICAL to build/base; no header includes it. Mini objdiff 3.3.1 matches production: code 8235/9448, 34/36 on the known hidden_exact under-credit rows, data 30236/30236. (e) patch 06: 36/36, objcmp IDENTICAL; the only change is 6 external symbols UNDEF(0) -> COMMON(1). It links with January's linker_common.obj and with base hs_globals_external in both orders: 0 LNK2005/LNK1169, all six resolved (production leaves 12 unresolved lines). (d) lab (never lands): zero-initialised separate statics reproduce January's .bss exactly (0/0x400/0x7400/0x7404/0x7408/0x740A/0x740B, 29708 B). The whole-TU D1 lab is 36/36 and passes object_audit (69/0) against a lab split. Uninitialised statics give name-hash order and FAIL the audit, so the initialisers are load-bearing and layout-proven. 08 (status flip) applies cleanly. The treeFINAL rebuild from patch files gives the same rows. fake_match_scan: 0 leads.
|
||||
|
||||
## 6. game_engine admission pick: the motion-sensor copy in game_engine_player_get_custom_motion_sensor_positions. (A) the in-loop alias `struct netgame_goal *goal = &global_goal[goal_index];` vs (B) F07's /Od-attested `positions[count] = *(real_point2d *)&global_goal[goal_index].position;`. Each is packaged as a complete admission packet: the review4 house-clean (F01R/F01RB, F02, F03aR, F03b, F04) plus the status flip. There is also a variant without the one-consumer focused headers.
|
||||
|
||||
- **Question:** Q1: game_engine is 180/180 strict exact and passes the whole-object audit either way, and A and B give byte-identical objects. Do you admit (A) the in-loop alias, which the /Od frame at 0x5a20e0 does not have and which is load-bearing, or (B) the /Od-attested view copy, which is load-bearing and so fails the byte-inert condition of your rule-24 narrow admission? Or neither, and game_engine stays held? Q2 (only if Q1 is yes): the 2026-09-21 'do not invent a one-consumer header' ruling applies to F02. Do you take F02 as is (4 new headers), or the variant_no_single_consumer_headers packet? The variant puts the hudg, itmc and netgame layouts back in game_engine.c, their only consumer, and is byte-identical in all 447 TUs. It keeps hud_nav_points.h (one non-owner consumer), because moving the nav-point trio into the genuine hud.h breaks _populate_statistic_buffer through a declared-name-count tie. Q3 (disclosure): admitting game_engine also admits the pre-existing debug_player_color anonymous aggregate with `word pad` members, and the descriptive .bss names _game_engine_teleport_message_ticks and _game_engine_teleport_flash_fade_function. HCEX has these values as static locals of game_engine_update_teleporter. Do you accept them, or are they the held invented-aggregate / descriptive-static class?
|
||||
- **Would complete:** source/game/game_engine
|
||||
- **Packet:** `research/fifty_objects_20260925/w/owner_queue/pick_game_engine`
|
||||
- **Apply-ready at cdc8ebd3:** yes
|
||||
|
||||
**Evidence for.** For B: /Od 0x5a20e0 does one 8-byte aggregate copy. The index is computed once (shl ecx,5) and x and y move as an integer mov pair; this build uses integer movs for struct copies (get_goal_position at 0x59d5b9) and movss for float scalars. The frame is only count, player and goal_index. real_point2d is a layout prefix of real_point3d, and HCEX's real_point3d has no 2D member. The caller is strictly exact. January's assert strings stringify Bungie view casts in actors, actor_looking, actor_moving and observer. For A: plain C, no cast. The same alias idiom is first-party in this TU: /Od goal_matches_player at 0x5b23c0 keeps a goal pointer slot [ebp-8] = &global_goal[i].
|
||||
|
||||
**Evidence against.** Against A: the /Od frame has no goal pointer slot and copies an aggregate rather than components. The alias is load-bearing (strip -> RESIDUAL). That makes it a non-/Od-attested, load-bearing named local: an owner-gated class, which review3 listed as blocking OBJECT_COMPLETE. Against B: rule-24 narrow admission requires a byte-inert cast, and this one is load-bearing: its strip gives the same RESIDUAL. Ruling 2 of 2026-09-21 keeps rule 24 strict for new punning casts. Both options also inherit the Q3 construct, which the owner has not ruled on: an anonymous debug_player_color aggregate with word pad members. HCEX has those values as static locals red/green/blue/duration of game_engine_update_teleporter. The 2020 /Od build puts unrelated globals between debug_player_color and the flash values.
|
||||
|
||||
**Still blocked / integrator notes.** Needs the owner's pick for Q1 (or hold). The focused-header ruling (Q2) must be settled: F02 as is, or the TU-local variant, which still needs hud_nav_points.h. The debug_player_color / descriptive-static disclosure (Q3) must be settled too. Whoever lands this must re-sweep it together with any concurrent owner-queue packet that edits game_engine.h, player_control.h, hud_messaging.h, sound_classes.h, hud.h or game_engine_king.c. F06 (optional, not packaged) edits game_engine_king.c, a separately held item, and does not fit the NP variant. Full ninja plus stable_verdicts remain the official gate. Nit, not changed: the dead local local_player_count shadows the public function local_player_count().
|
||||
|
||||
**Measured.** All at cdc8ebd3; the tree was clean before and after. git apply --check is clean for all 19 patch files alone, and for each packet's full set in one call: optionA, optionB, NP-alias and NP-view-copy. F07 alone does not --check at cdc8ebd3, so optionB ships a standalone F01RB (= F01R + F07, byte-checked). Rebuilding each packet from a HEAD export gives exactly the shadow that was measured. Compiles use the production cflags, cwd = shadow root, and coff_compare.section_infos_equal: optionA, optionB and both NP variants are 180/180 EXACT with 0/302 sections changed vs build/base; the control is 180/180. The optionA and optionB objects are identical: same order and no content difference. Full 447-TU sweep with canonical COFF: control head vs build/base is 447/447 SAME. optionA and optionB each give 446 SAME plus game_engine. game_engine differs only in three ways, all EXACT: always_invis is emitted later; the csplit alias `_global_goal+0x400` replaces `_global_variant+0` at 2 relocations; and $L numbering changes. NP vs optionA: 447/447 SAME. The 37 game_engine.h consumers all fall inside the sweep. Admission battery (every candidate): object_audit PASS with text identical to production; pdb_storage 0/269 disagreements; surplus 11 COMDATs, all identical; provider_link PASS, both orders, 39 surplus externals. objdiff 3.3.1 mini project: 27922/32397 code, 173/180 functions, 3792/3792 data, 0 deltas vs prod. audit_semantic_matches accepts 180/180, with the same 7 semantic-coff-only functions as production. tools/audit_object_admission already lists game_engine as a candidate with 0/0 gaps, so the status flip will not be revoked: Halo objects 379 -> 380. /W3: no new warnings. The C4013 console_printf warning and two long->short warnings are gone. Strip test (lab): with neither the alias nor the cast, the function is RESIDUAL, because the induction-variable base shifts to position.y (+4). Both spellings are load-bearing. Ruling variants: the three single-consumer layouts TU-local (vTUnp) are byte-identical everywhere. The genuine broad headers all fail. item_definitions.h moves hud_weapon's _render_weapon_hud. scenario_definitions.h plus the F06 siblings is a strict regression in ai_communication (_ai_communication_update_speech_timers) and makes the parked _ai_test_ballistic_line_of_fire stale. hud.h costs game_engine.c 23 names and flips _populate_statistic_buffer (count oracle, lab only: K=8-12 flips it). hudg cannot move without rewriting 7 HUD TUs.
|
||||
|
||||
## 7. rasterizer_xbox_hardware_geometry: spelling of the no-op MoveResourceMemory wrapper at 0x158460 (A = IDirect3DResource8_MoveResourceMemory vs B = D3DVertexBuffer_MoveResourceMemory)
|
||||
|
||||
- **Question:** January emits two static no-op wrappers: 0x158450 = _D3DResource_MoveResourceMemory@8, and 0x158460 = one directly called MoveResourceMemory forwarder. Which spelling should rasterizer_vertex_buffer_new use for that one call? A: IDirect3DResource8_MoveResourceMemory((D3DResource *)d3d_vertex_buffer, D3DMEM_VIDEO), with 0x158460 named _IDirect3DResource8_MoveResourceMemory@8. B: D3DVertexBuffer_MoveResourceMemory(d3d_vertex_buffer, D3DMEM_VIDEO), with 0x158460 named _D3DVertexBuffer_MoveResourceMemory@8. The argument and the position after the vertex-buffer Unlock block are byte-inert, and a 3-line comment in the source says so. Either A or B completes the object; if you reject both, the hg0 fallback is zero-credit hygiene only.
|
||||
- **Would complete:** source/rasterizer/xbox/rasterizer_xbox_hardware_geometry
|
||||
- **Packet:** `research/fifty_objects_20260925/w/owner_queue/pick_hwgeom_models/patches`
|
||||
- **Apply-ready at cdc8ebd3:** yes
|
||||
|
||||
**Evidence for.** Both options: January's emitted static wrappers prove the call exists (static-COMDAT law, whole-image ret-8 census). The d3d8.h emission order excludes every other forwarder spelling. A only (style census, not byte proof): all 33 of January's Halo-side resource lib calls go through IDirect3D*8_ compat wrappers, with 0 native resource-level spellings. January emits _IDirect3DResource8_Release@4 in progress_bar, and the tree has IDirect3DResource8_Release((D3DResource *)...) at progress_bar.c:1812. This TU already uses typed compat names. B: needs no cast.
|
||||
|
||||
**Evidence against.** No first-party evidence names the spelling. The /Od build is the PC DX9 port, HCEX links no hardware_geometry code, and the October 2001 beta has the same pair without names. D3DMEM_VIDEO and the call position are chosen and byte-inert; the comment discloses that. A needs an XDK-convention (D3DResource *) cast; it is byte-inert, since B produces the same bytes without it.
|
||||
|
||||
**Still blocked / integrator notes.** Nothing, once the owner picks A or B. If neither, the object stays NonMatching: the two _code_ placeholder stubs remain (house rule 7 names; external where January is static).
|
||||
|
||||
**Measured.** Rebase: the source file is unchanged at cdc8ebd3 (blob c2bb9095) and symbols.json rows 5813-5825 are unchanged. The wave-2 patches apply clean. Only the symbols patch index line was refreshed, and a config.json status flip (NonMatching -> Matching) was added. No real change was needed. csplit: split_ctl == build/split (833/833); split_hgA and split_hgB each change only rasterizer_xbox_hardware_geometry.obj. A vs split_hgA: gate --all 17/17 EXACT (_point_from_line3d guard passed); object_audit PASS (25 symbols, 0 differ); pdb storage 0 disagreements (production has 13); 0 candidate-only code COMDATs; provider_link PASS in both orders (6 pre-existing rows: 3 pooled literals + 3 SDK tables); fake_match_scan 0. B vs split_hgB: identical results. cand_A and cand_B have byte-identical Halo sections (vertex_buffer_new 5442bf32, triangle_buffer_new e90e066b) and both 0x158460 bodies are sha 2a2f950f; only the name differs. objdiff 3.3.1 mini report: 898/898 code, 584/584 data for production, A and B, so there is no credit change. hg0 fallback vs split_hg0: 17/17, audit PASS, link PASS, but pdb shows 2 disagreements (the external _code_00158450/460 stubs), so it is not admissible. verify_apply.py: every packet passes git apply --check in the repo and sequential scratch application, and the post-images equal the measured files byte for byte. This also holds stacked with each models packet.
|
||||
|
||||
## 8. models .bss: file-scope `= {0}` statics in January (reverse-use) order (P1; variant P2 with fv as the HCEX static local) vs the first-party in-block static-local form (SL) (SUPERSEDED by canonical; see top)
|
||||
|
||||
- **Question:** Do you admit models.obj with load-bearing `= {0}` initialisers on the render_model defaults, declared in January's .bss order? There are two forms. P1: four file-scope statics fv, change_colors, effect, region, each `= {0}`. P2: default_function_values as an uninitialised static local at render_model function scope (as HCEX records it), plus the other three as `= {0}` file statics. Both contradict the later first-party form: HCEX -lines and the /Od build declare all four uninitialised inside their if (!param) blocks. The strip test fails: without `= {0}` the layout falls back to hash order. YES (P1 or P2) completes models and retires the bss-symbol-layout-mismatch rejection. NO means landing models_C1 (zero-credit storage fix) or models_optSL (first-party form, measured FAIL(4)); the object then stays blocked until first-party names for the three other defaults are found.
|
||||
- **Would complete:** source/models/models
|
||||
- **Packet:** `research/fifty_objects_20260925/w/owner_queue/pick_hwgeom_models/patches`
|
||||
- **Apply-ready at cdc8ebd3:** yes
|
||||
|
||||
**Evidence for.** Measured VC7 law: uninitialised statics are laid out in decorated-name hash order, then `= {0}` statics in declaration order. P1 and P2 are the only name-independent exact forms. Project precedents for a load-bearing `= {0}` that fixes .bss layout: rasterizer_lights (cdc8ebd3), and the player_ui player1_profile_path `= { 0 }` (f7cd2e72); source/ has 69 column-0 static `= {0}` definitions. P1 adds no new names, and program semantics are unchanged. P2 keeps HCEX's first-party static-local storage for default_function_values.
|
||||
|
||||
**Evidence against.** HCEX.pdb and HCEX_Release.pdb record default_function_values as a Static Local of render_model, not a file static. HCEX -lines (the +2-line gaps at 124/128..154/158) and the /Od profile-scope sizes show all four declared inside their if-blocks, uninitialised. The P1/P2 declaration order is the exact reverse of the use and in-block order, with no first-party support. The strip test fails (the redundant-zero-initialiser class). The standing rejection's reopen clause forbids matching-only constructs. Three of the four names are third-party (halocea).
|
||||
|
||||
**Still blocked / integrator notes.** If the owner says NO: models stays NonMatching. The first-party SL form gives offsets 32/48/96/0 vs January's 0/16/64/104, because January's order depends on the decorated-name hash of three lost names, and hash-steering names are forbidden. Not built in this wave (it would be a new form): P2 with fv inside its if-block, which by the law should lay out identically.
|
||||
|
||||
**Measured.** Rebase: models.c/h are unchanged since 954eebd2. The wave-3 C1 patches apply clean and reproduce new/models.{c,h}; OWNER_OPTION_P1 reproduces new/models_owner_option_P1.c. No real change was needed. The packets were rebuilt as standalone per-file patches, because a stacked models.c pair fails `git apply --check` in-repo under core.autocrlf. SL and P2 are the wave-3 lab L1 and P2 forms rebased on C1 (the diff vs the labs is the C1 hunks only). csplit: split_mC1, split_mSL and split_mP2 each change only models.obj. Gate --all is 12/12 EXACT for every candidate; render_model is identical in all four (2144 B, sha bb666c87, 98 relocs). object_audit: production FAIL(4) (offsets 72/88/32/0); C1 FAIL(4); P1 PASS 30/0 (0/16/64/104); P2 PASS 30/0 (0/16/64/104); SL FAIL(4) (32/48/96/0). pdb storage is 0 for C1, P1, P2 and SL (production has 2). surplus_identity: _negate_vector3d and _set_real_point3d are IDENTICAL and pre-existing. provider_link PASS (11 rows) and fake scan 0 for every candidate. models.h shared-header sweep (shadow header, #error control failed every compile, so the shadow was used): first_person_weapons 33/34 (same residual), model_animations 32/32, objects 121/121, render_objects 22/22, render_sky 1/1, all IDENTICAL between the current and C1 headers. objdiff 3.3.1 mini report: 5038/5038 code and 2368/2368 data for every candidate (credit-neutral). The combined hwgeom+models symbols.json changes are independent (csplit), and verify_apply.py passes ALL OK.
|
||||
|
||||
## 9. dead_camera _dead_camera_update: authentic uninitialised next_unit_index read (source/camera/dead_camera.c)
|
||||
|
||||
- **Question:** Can source/camera/dead_camera.c declare `long next_unit_index;` with no initialiser and no else arm, under the original-bug policy? That deletes the current defined stand-in `else { next_unit_index = (long)result; }` and its comment. When no next player is found, the test then reads the indeterminate local. The methodology-template BUG comment in RULING.md would be added. YES/NO.
|
||||
- **Would complete:** source/camera/dead_camera (4/4 strict, 6/6 sections, 6/6 symbols, PDB storage 0, surplus identical, provider_link PASS 19/19, data 100%)
|
||||
- **Functions gained:** _dead_camera_update (1,248 padded / 1,235 meaningful)
|
||||
- **Packet:** `research/fifty_objects_20260925/w/owner_queue/ub_dead_camera_saved_game`
|
||||
- **Apply-ready at cdc8ebd3:** yes
|
||||
|
||||
**Evidence for.** - January +0x176 `mov eax,[ebp+0x10]` is the fallback of the phi, and the slot is never written before it. Production's defined stand-in differs by exactly this one instruction (`mov eax,esi`).
|
||||
- n1 20260915: every defined initialiser costs an extra store that VC7 never elides.
|
||||
- The later /Od build (0x522c90) adds `= NONE` (mov [ebp-8],-1) at the top of the block with no else arm, i.e. the fix was an initialiser. The HCEA donor also uses -1.
|
||||
- /W4 C4701 on the candidate.
|
||||
- Landed precedent: ai_communication.c:2527 (7a1d0d91) leaves cause_point uninitialised under the same BUG template.
|
||||
- The whole-object audit is clean.
|
||||
|
||||
**Evidence against.** - Earlier decisions rejected this exact read: dead_camera_obj_codex_checkpoint ('Recreating the uninitialized read is forbidden'), legacy_residual_donor_truth_audit_20260913 (rejected the 1,235-byte donor), and opus5_150k_w1 (skipped as UB). They were taken under briefs that forbade UB, not as owner rulings under the original-bug policy.
|
||||
- The read is formally undefined C. The current stand-in is defined and has the same January runtime value.
|
||||
- There is no _RTC_UninitUse attestation, because the /Od build contains the fix.
|
||||
- House rules 20 and 21 and the source-credibility gate allow only the narrow original-bug exception.
|
||||
|
||||
**Still blocked / integrator notes.** Nothing technical. Only the owner ruling is outstanding. The integrator must run a full ninja and the stable sweep (workers may not run ninja), then flip config.json:743 to Matching. There is no park to retire.
|
||||
|
||||
**Measured.** Patch 01 (CRLF form, plus an index_lf form) passes `git apply --check`, alone and together with 02/03, in worktree and --cached modes, at both cdc8ebd3 and eb33baec. Applied outside the repo, it reproduces landing.c byte for byte.
|
||||
|
||||
The code change is the same as the held owner_update_bug.patch. Only the comment moves to the methodology BUG template, and it is byte-inert: 26/26 sections and all symbols are identical to the held form.
|
||||
|
||||
- Gate --all: production 3/1/0; candidate EXACT 4/4 (new 288, update 1248, next_player 176, has_allies 112).
|
||||
- head.obj equals build/base. The candidate differs only in the _dead_camera_update section.
|
||||
- object_audit against the current split: PASS. No symbols.json change is needed; the _dead_camera_constants static landed in batch 1 and the split already has storage 3.
|
||||
- pdb_storage: 0 disagreements.
|
||||
- surplus_identity: 8 COMDATs, all identical to January's selected copies. All are already emitted by production.
|
||||
- provider_link: PASS 19/19 in both orders. The wave-1 _valid_real_vector3d_axes2 FAIL is gone.
|
||||
- Data: .rdata 48/48. fake_match_scan: 0 leads. /W3: clean.
|
||||
- /W4: exactly one new warning, C4701 on next_unit_index (the compiler confirms the disclosed path).
|
||||
- January bytes: [ebp+0x10] is only read before +0x176, so January deterministically uses the caller's result pointer.
|
||||
|
||||
## 10. saved_game_files _saved_game_files_enumerate_available_to_local_player_index: indeterminate count stored on saved-game-files mutex failure (source/saved games/saved_game_files.c)
|
||||
|
||||
- **Question:** Can number_of_available_profiles be declared without an initialiser and zeroed only after count_enumerated_profiles_in_mapfile(), inside the successful general-mutex branch? On mutex failure, *number_of_profiles then receives an indeterminate value (January stores the low word of the caller's player_index). The held BUG comment would be added, and this reverses the 20260904/20260908 rejection recorded in the parked.json park. YES/NO. (Patch 02 is a zero-credit storage fix that needs no ruling.)
|
||||
- **Would complete:** source/saved games/saved_game_files: strictly exact 46/46 and audit-exact against the emulated split. Clean completion is CONDITIONAL: 3 PDB-storage disagreements remain unless the lab helper-storage follow-up is reviewed and landed, or the owner accepts the three functions as external.
|
||||
- **Functions gained:** _saved_game_files_enumerate_available_to_local_player_index (368 padded / 359 meaningful)
|
||||
- **Packet:** `research/fifty_objects_20260925/w/owner_queue/ub_dead_camera_saved_game`
|
||||
- **Apply-ready at cdc8ebd3:** yes
|
||||
|
||||
**Evidence for.** - January bytes show the count zeroed only after the count call, inside the success branch. The failure tail stores the untouched player_index home.
|
||||
- The /Od 0x8646c0 build zeroes the accumulator twice: at the declaration (the later fix) and after the count, which is January's position.
|
||||
- Every defined alternative was already refuted from the bytes (checkpoint 20260908, n1 20260915, Lane D 20260922). The only defined source that matches would reuse player_index as the counter, which contradicts /Od and makes no sense as code.
|
||||
- /W4 C4701.
|
||||
- ai_communication.c:2527 precedent.
|
||||
- Clean gate, audit and link results. Header blast radius 0.
|
||||
|
||||
**Evidence against.** - The config/parked.json park explicitly records 'reproducing that undefined behavior is rejected even though it makes the section strict exact'. The same position appears in claude_fable_opus_reconciliation_checkpoint_20260908 and saved_game_files_obj_opus_reconciliation_20260904.
|
||||
- The indeterminate value escapes through an out-parameter the caller can see, which is harder to defend than dead_camera's internal read.
|
||||
- Rule 17 (combine declaration and initialisation) is locally reversed. /Od attests only the late zeroing position.
|
||||
- There is no _RTC_UninitUse attestation, because the /Od build contains the fix.
|
||||
|
||||
**Still blocked / integrator notes.** 1. The owner ruling on 03. Patch 02 can land without a ruling.
|
||||
2. Whole-object COMPLETE under brief section 4, step 3: 3 PDB-storage disagreements remain (_saved_game_files_take_mapfile_mutex, _saved_game_files_release_mapfile_mutex, _saved_game_files_enumerate_default_files).
|
||||
- /Od attests the mapfile-helper calls at the 6 hand-expanded sites.
|
||||
- enumerate_default_files has no /Od call-site attestation.
|
||||
- The fix is a real source change, preserved as lab/LAB_ONLY_saved_game_files_helper_storage_on_top_of_03.diff. It needs its own review. Alternatively, the owner accepts the three as external.
|
||||
3. Do not flip config.json:398 to Matching on the ruling alone.
|
||||
4. The integrator must run a full ninja and the stable sweep, then retire the enumerate_available park via tools.campaign.unpark.
|
||||
|
||||
**Measured.** Source is unchanged since wave 1. Patches 02 (storage; its +/- lines equal the held production_storage.patch) and 03 (the held production_bug.patch rebased onto 02) pass --check in both EOL forms, alone and together, at cdc8ebd3 and eb33baec. Applied sequentially outside the repo, they reproduce the candidate .c, the header and symbols.json byte for byte.
|
||||
|
||||
- Gate --all: production 45/1; 02 only 45/1 (storage flip only); 03 only 46/46; 02+03 46/46. Shadow headers were verified with an #error probe.
|
||||
- csplit emulation: the control run reproduces 833/833 split objects. The edited symbols.json (line 7376, in place) changes only saved_game_files.obj, and only the storage of _enumerate_memory_units.
|
||||
- object_audit, candidate against the emulated split: PASS (152 symbols, 0 differ).
|
||||
- surplus: 0 code COMDATs. provider_link: PASS 11/11 in both orders. Data 100% (.bss 540, .data 8, .rdata 5608).
|
||||
- Header blast radius on 6 includers (game, player_ui, ui_widget, virtual_keyboard, player_profile, playlist_profile): identical gate rows, sections and symbols.
|
||||
- fake_match_scan: 0 leads. /W3: unchanged at 33. /W4: one new C4701 on number_of_available_profiles.
|
||||
- January bytes re-verified: +0x91 spill, +0x94 xor edi, and the +0x156 `mov dx,[ebp+8]` failure tail.
|
||||
- pdb_storage: 3 disagreements remain (take/release_mapfile_mutex, enumerate_default_files). The wave-1 'proven external' dismissal is refuted by law (h).
|
||||
- LAB variant (static helpers called at the hand-expanded sites): 46/46, sections identical, PDB storage 0, audit PASS against a lab split, link PASS, blast radius 0.
|
||||
|
||||
## 11. first_person_weapons patch B (authentic unguarded NULL dereference of first_person_weapon_animations; rebased onto cdc8ebd3 after patch A landed in b9a8d587)
|
||||
|
||||
- **Question:** May _first_person_weapon_update read first_person_weapon_animations->animations.count without a NULL test at two sites (moving animation and overcharged jitter)? The pointer comes from `count ? TAG_BLOCK_GET_ELEMENT(...,0,...) : NULL`. The patch also drops REAL_MATH_EXTERNAL_{SQUARE_ROOT,MAGNITUDE_SQUARED3D,MAGNITUDE3D}, so magnitude3d inlines as in January and the TU emits three header __inline COMDATs from a strictly exact caller. The rule-6 exception conditions hold.
|
||||
- **Would complete:** source/interface/first_person_weapons
|
||||
- **Functions gained:** _first_person_weapon_update (1,533 meaningful / 1,536 padded)
|
||||
- **Packet:** `research/fifty_objects_20260925/w/owner_queue/ub_fpw_player_profile`
|
||||
- **Apply-ready at cdc8ebd3:** yes
|
||||
|
||||
**Evidence for.** January bytes: `xor eax,eax; jmp`, then `cmp dword [eax+0x10],3/0xf` with no test, at both sites. The later /Od build (0x61fcea and 0x61fd99) also reads without a NULL test. The HCEA 2011 decompiled source (first_person_weapon_update.c, around lines 138-145) has the same unguarded read. With the guards restored, the only difference from January is 4 inserted instructions, so no defined spelling can match. The path is latent: switch_weapons commits weapon_index only when first_person_weapon_animations.count is nonzero. BUG-commented authentic defects already exist in 18 source files, including uninitialised reads.
|
||||
|
||||
**Evidence against.** The source dereferences a pointer that the statement before it may set to NULL, so house rule 21 ('undefined/nonsensical logic') applies literally even though the path is unreachable. The defined-behaviour body is already in the tree at zero credit (park 95.21506). Refusing costs one function.
|
||||
|
||||
**Still blocked / integrator notes.** Nothing technical. The item needs only the owner's yes on the authentic-defect class. The integrator must then run the full ninja build and the stable sweep; only this TU changes.
|
||||
|
||||
**Measured.** Patches 01_fpw_B_source, 02_fpw_B_retire_park and 03_fpw_B_status_matching pass git apply --check at cdc8ebd3 (and on eb33baec, a docs-only commit that landed during the run). Tree: gate 33/1. With B: gate --all 34 exact / 0 residual / 0 unwritten, _point_from_line3d guard passed. No split regeneration is needed: a control csplit from cdc8ebd3 config matches build/split on all 833 objects. object_audit against the emulated split PASSES, with 45 January symbols and 0 differences. The only new surplus is _magnitude3d, _magnitude_squared3d and _square_root. All three are IDENTICAL to January's selected copies (action_charge, action_alert) and have 0 NODUP definers; provider_link passes both orders for all 12 surplus symbols. pdb_storage: 0 disagreements. Data 536/536. objdiff 3.3.1 against the emulated split: 29/34, with update at 100 (tree 28/34, update 95.21506). The other 5 functions are objdiff 3.3.1 false negatives already credited by semantic_matches.json or the accepted_ledger, and all 5 are gate-EXACT, so the strict view is 34/34. fake_match_scan finds the same single authenticated lead as the tree. /W3 shows 0 TU-local warnings; the one extra line is the existing real_math.h(810) warning. No header is touched, so there is no blast radius. January bytes confirm both unguarded reads (0x23e/0x255 and 0x28d/0x2a5). The BUG comment's claim that the path is unreachable was checked in switch_weapons.
|
||||
|
||||
## 12. player_profile R1-R3 (uninitialised serialised 512-byte block; seek failure skips file_close; close(&file, NONE) after delete-while-open), rebased onto cdc8ebd3 after zero-credit packet A landed in 6e3e2d35; R3 BUG comment amended
|
||||
|
||||
- **Question:** Does the owner reverse the 2026-09-09 saved-game rejection and admit all three January failure-path defects with BUG comments? R1: the `union player_profile_block block;` in write_thread_proc and create_default has no initialiser, so 444 stack bytes are written to disk. R2: create_default folds file_set_position into the open condition, so a failed seek leaks the file. R3: player_profile_new deletes the file while it is still open, sets the index to NONE, then calls saved_game_file_close(&profile_file, NONE), which fails its assertions. All three are required for the object.
|
||||
- **Would complete:** source/saved games/player_profile
|
||||
- **Functions gained:** _player_profile_create_default_profiles_on_disk (275/288); _player_profile_write_thread_proc@4 (349/352); _player_profile_new (456/464)
|
||||
- **Packet:** `research/fifty_objects_20260925/w/owner_queue/ub_fpw_player_profile`
|
||||
- **Apply-ready at cdc8ebd3:** yes
|
||||
|
||||
**Evidence for.** Since the 2026-09-09 rejection, all three shapes have first-party /Od attestation. R1: 0x8596d0 and 0x85acf0 have no initialiser on block. R2: 0x85ae02 has the seek inside the open condition. R3: 0x85d1fa sets NONE, then 0x85d20c runs the shared close. HCEX.pdb gives the union player_profile_block type and the profile_file/full_path local names. No defined spelling can reproduce the bytes; earlier waves measured the alternatives. BUG-commented authentic defects already exist in the tree, for example the uninitialised cause_point read in ai_communication (7a1d0d91).
|
||||
|
||||
**Evidence against.** The owner already rejected exactly these three shapes on 2026-09-09. R1 discloses 444 stack bytes into a saved file. The /Od build attests only the missing initialiser: in the later format the block is fully overwritten, so the disclosure is January-format-specific. R3 passes NONE to an asserted API and deletes a file that is still open. R2 leaks a handle on seek failure. House rule 21 applies.
|
||||
|
||||
**Still blocked / integrator notes.** Nothing technical. The object needs yes on all three of R1, R2 and R3; with a partial yes it stays incomplete (R1 blocks write_thread and create_default, R2 blocks create_default, R3 blocks new). Disclosed non-blockers: read and get_from_path keep `byte block[512]`, although HCEX types read's local as the union; the globals type names stay descriptive unless optional 04a is used. The integrator must then run the full ninja build and the stable sweep.
|
||||
|
||||
**Measured.** The old owner_gated_over_production.patch still applies at cdc8ebd3 and reproduces final_og.c exactly. The R3 BUG comment was amended to state the delete-while-open; this is comment-only and changes 0 of 60 sections. Patches 04_pp_R1R3_source, 05_pp_retire_parks and 06_pp_status_matching pass git apply --check, individually and together with 01-03. Tree: gate 19/3. Candidate: gate --all 22 exact / 0 residual / 0 unwritten, guard passed, with no split regeneration needed. object_audit PASSES, with 51 January symbols and 0 differences. The surplus list is identical to the tree's (no new surplus, 0 code COMDATs), and provider_link passes both orders for all 8 surplus symbols. pdb_storage: 0 disagreements. Data 1644/1644. objdiff 3.3.1: 100.0, code 4119/4119, 22/22 (tree 95.34539). fake_match_scan: 0 leads. /W3 is identical to the tree, with 0 TU-local warnings. No header is touched. January bytes were re-read: R3 at 0x151 delete, 0x159 `or esi,-1`, 0x164 close(&file, esi); R2 at 0xa3 `je 0xec`, which skips file_close; R1 has no fill before file_write(0x200). There is also an optional variant with the byte-inert HCEX type names advised by reviewer 3: optional/04a, then 04b, applied as two separate git apply commands. It gates 22/22 and all 60 sections are identical.
|
||||
|
||||
## 13. game_engine_king: _find_next_hill keeps January's uninitialised no-candidate return (next_hill), plus the cachebeta storage fix, for whole-object admission
|
||||
|
||||
- **Question:** Do you admit game_engine_king.obj as a complete object when _find_next_hill keeps January's uninitialised no-candidate return, disclosed by the policy-form 'BUG (preserved for exact matching)' comment? If yes, which spelling: 01, the review2 packet's early-return form, or 01A, the /Od 0x5bd630 single-exit form (`next_hill = king_engine_hills[hill_index]; break;` then one `return next_hill;`)? The two produce byte-identical objects. A NO applies only if_declined/king_source_storage_only.patch + 02 at zero credit, but it leaves open whether the function credit production already takes for this read (_find_next_hill, 112 B, since 2026-09-02) should stand.
|
||||
- **Would complete:** source/game/game_engine_king
|
||||
- **Packet:** `research/fifty_objects_20260925/w/owner_queue/ub_king_glow/king`
|
||||
- **Apply-ready at cdc8ebd3:** yes
|
||||
|
||||
**Evidence for.** January bytes: at +03, push ecx reserves [ebp-4], which is never written; at +52, mov eax,[ebp-4] returns it on the loop-exhausted path.
|
||||
|
||||
The later first-party /Od build (0x5bd630) sets its RTC init flag only on the found path, then calls _RTC_UninitUse with the string "next_hill". So the local's name and the read are both in the later source. The function is single-exit there.
|
||||
|
||||
Playbook 'Original bugs' gate: January proves the read, an independent build corroborates it, and every defined form measured is 28/29 (5 at 931ed8dc, 1 at cdc8ebd3).
|
||||
|
||||
The function and the whole object reach strict exact with a clean section-4 audit.
|
||||
|
||||
Owner precedents (2026-09-20):
|
||||
- ai_script.c is Matching and carries an owner-admitted read of an unset stack slot: a missing vsprintf argument makes it read the saved-EDI home (ai_script.c:2765).
|
||||
- _actor_emotion_update: an out-of-bounds read admitted at 8e4309dd.
|
||||
|
||||
The read has been in production since 2026-09-02; the ruling certifies it, it adds no behaviour.
|
||||
|
||||
**Evidence against.** Brief sections 2 and 7 make this class owner-gated, and dead_camera is still held on the same class.
|
||||
|
||||
On 2026-09-20 the owner excluded the uninitialised-read donors _dead_camera_update and _compare_profile_sections (astra rejected-hypotheses, item 8). Those were not /Od-authenticated, but the class is the same.
|
||||
|
||||
King would be the first Matching object with a load-bearing C4700.
|
||||
|
||||
In the packet form (01), next_hill is never assigned, so a reviewer could read it as a local whose only role is the match. The /Od single-exit form (01A) answers this: it is byte-identical and raises no C4700.
|
||||
|
||||
Behaviour: on a map with one distinct hill and moving hills enabled, January stores garbage in king_globals.hill_id. The corrected build keeps the current hill.
|
||||
|
||||
**Still blocked / integrator notes.** Only the owner ruling. On a YES the integrator still has to run the full ninja, the stable function diff, parks, the admission audit and pytest. The header edit reaches only king.c. Nothing technical is open.
|
||||
|
||||
**Measured.** Tree: HEAD eb33baec, which is cdc8ebd3 plus one ledger-only commit; clean before and after.
|
||||
|
||||
Rebase: the review2 OWNER_GATED source patch applied unchanged. The result is review2's owner_bug_comment.c plus exactly the two f7cd2e72 game_variant renames. The semantic_data_matches patch failed (b9a8d587 had appended entries), so I regenerated it. All patches are regenerated as canonical git patches 01-05, plus alt/01A and if_declined/.
|
||||
|
||||
Apply checks: git apply --check passes on each patch, on 01-05 combined, and on king + glow combined. --whitespace=error-all is clean. Trial-applying onto tip copies reproduces king/new byte-for-byte (CRLF), and the JSON parses.
|
||||
|
||||
Gates (shadow patched header; a #error probe proved the patched header is the one used):
|
||||
- 01: 29/29 EXACT against build/split and against the emulated split (csplit with the edited symbols.json). The emulated split differs from build/split only in game_engine_king.obj.
|
||||
- 01A and storage-only: also 29/29. Their objects have 59 sections, 0 section differences and 0 symbol-row differences against 01.
|
||||
- Only warning: C4700 next_hill. The /Od single-exit form raises none.
|
||||
- Defined result in the /Od shape (next_hill = hill_id): 28/29, so the read stays load-bearing.
|
||||
|
||||
Audit and linkage:
|
||||
- object_audit against the emulated split: PASS, 39/39 January symbols, .data 136/136 and .bss 560/560. The controls FAIL(23) on storage, as expected.
|
||||
- pdb_storage: 0 disagreements (production has 23).
|
||||
- Surplus: 22 sections, all identical to January's copies. provider_link: 22 rows, PASS in both orders. 0 NODUP definers.
|
||||
- 0 UNDEF references to the 23 re-storaged names in build/base (621 objects) or build/split (833).
|
||||
- The header is included only by king.c. fake_match_scan: 0 leads.
|
||||
- The _king_engine data entry measures 136 / 23 / 4009f5b6... with target == base in 8 of 8 combinations.
|
||||
|
||||
Emulated chain (objdiff 3.3.1; the control mini row equals the production row):
|
||||
- Halo complete units 379 -> 380; complete_code +4,865; complete_data +876; matched_data +136.
|
||||
- The data credit validates without allow_incomplete_unit. The .bss ownership snapshot validates.
|
||||
- Revoked []; parks 86/0/0; admission 11/0/2/0 with 0 contradicted.
|
||||
- With glow also applied: 381.
|
||||
|
||||
## 14. glow _get_particle_world_position: two uninitialised stack-array reads (traversal_left_vectors never built on the 2- and 3-marker paths; traversal_time_indices[1] never set on 3-marker interval 1)
|
||||
|
||||
- **Question:** Do you admit glow.obj as a complete object when get_particle_world_position reproduces January's two uninitialised stack-array reads? The first is that the 2- and 3-marker paths never build traversal_left_vectors, which spline 3 reads. The second is that 3-marker interval 1 writes its midpoint knot into [2], so [1] is read unset. Each carries a policy-form BUG comment. These are in-bounds reads of automatic arrays with no struct-layout dependency, so do you also waive the compile-time layout assertion that the 2026-09-20 ruling attached to _actor_emotion_update? On a NO nothing is applied and the current defined-C park (2528/55, 49.07%) stays; review2 rejected the only defined fallback.
|
||||
- **Would complete:** source/objects/widgets/glow
|
||||
- **Functions gained:** _get_particle_world_position (1,744 padded / 1,729 objdiff bytes)
|
||||
- **Packet:** `research/fifty_objects_20260925/w/owner_queue/ub_king_glow/glow`
|
||||
- **Apply-ready at cdc8ebd3:** yes
|
||||
|
||||
**Evidence for.** Both defects are target-proven by January's control flow. The later first-party /Od build (0x798de0) contains both verbatim:
|
||||
- Its RTC descriptor names traversal_left_vectors [ebp-0xa8], which only the default loop's cross_product3d writes.
|
||||
- In case 1, both the time_indices stores (0x799533 and 0x799639) go to [2].
|
||||
|
||||
HCEX.pdb gives the same local names.
|
||||
|
||||
The bounded defined search fails: n3a v3 is +592 B, P8 has 71 REAL regions, and this wave's single-defect repairs are each 24/1.
|
||||
|
||||
The function and the object become strict exact with a clean section-4 audit.
|
||||
|
||||
Owner precedents (2026-09-20): Matching ai_script.c has an admitted unset-stack-slot read, and _actor_emotion_update's out-of-bounds read was admitted at 8e4309dd.
|
||||
|
||||
The reads have no layout dependency, so no assertion is meaningful.
|
||||
|
||||
**Evidence against.** The class is owner-gated (brief sections 2 and 7), dead_camera is held on the same class, and the owner refused the 2026-09-20 uninitialised donors (dead_camera, compare_profile_sections).
|
||||
|
||||
The behaviour is real and visible: glows with 2 or 3 markers use stack garbage for the left offset (v*cosine), and on 3-marker interval 1 the second spline knot is garbage.
|
||||
|
||||
The packet adds point<->vector view casts. They meet the brief's rule (/Od-attested per site, compatible layout, byte-inert strip, strictly exact caller, disclosed) but still need to be admitted.
|
||||
|
||||
Byte-inert nits: NUMBEROF vs the /Od signed literal 4; the locals sine/cosine shadow the real_math.h inlines; the BUG comment's range is end-exclusive (correct as written).
|
||||
|
||||
**Still blocked / integrator notes.** Only the owner ruling, including the layout-assertion waiver. On a YES, 01, 02 and 03 must land together, followed by the integrator's full ninja, stable diff, parks, admission audit and pytest. Only glow.c changes; no header.
|
||||
|
||||
**Measured.** Rebase:
|
||||
- glow.c/.h are untouched since e9e62b78. The glow.c and parked.json parts of wave-2 production.patch apply unchanged.
|
||||
- The rebased glow.c == scratch/w/glow/cand_final.c byte-for-byte.
|
||||
- The config.json hunk failed (b9a8d587 flipped light_volumes.c two lines above), so I regenerated it as a one-line status flip.
|
||||
- Patches 01-03 are canonical git patches. git apply --check passes on each, on 01-03 combined, and on king + glow combined. --whitespace=error-all is clean. Trial-applying reproduces glow/new byte-for-byte.
|
||||
|
||||
Gates (gate.py --all --forbid-emitted-symbol _point_from_line3d):
|
||||
- Packet: 25/25 EXACT; _get_particle_world_position EXACT 1744.
|
||||
- Tip control: 24/1, [size 2528!=1744, relocs 55!=43, sha].
|
||||
- 0 TU-local /W3 warnings.
|
||||
- objcmp tip vs packet: 1 of 56 sections differs (this function); 0 symbol-row differences.
|
||||
|
||||
Strip tests at cdc8ebd3:
|
||||
- Knot repaired only: 24/1 [sha].
|
||||
- Left vectors = {0} only: 24/1 [size 1776!=1744, sha]. Each defect is therefore independently load-bearing.
|
||||
- index < 4: 25/25 (byte-inert).
|
||||
- review2's no-casts variant: 25/25, but raises C4133, so the casts are type correctness, not decoration.
|
||||
|
||||
Audit and linkage:
|
||||
- object_audit: PASS, 36/36 symbols; the surplus list is identical to production's.
|
||||
- Surplus: 20 sections, all identical to January's copies. provider_link: 20 rows, PASS in both orders. 0 NODUP definers.
|
||||
- pdb_storage: 0 disagreements. Data .rdata 392/392; no data entry is needed.
|
||||
- January bytes re-read: left vectors live at [ebp-0xc4, ebp-0x94). They are written only by the default loop (+0x21b/+0x23e/+0x259) and read by the spline-3 leas (+0x637..+0x64c). Case 1 jumps to +0x5c6, which stores [ebp-8]; +0x5d2 then reads [ebp-0xc] unwritten.
|
||||
- /Od RTC names confirmed.
|
||||
|
||||
Emulated chain:
|
||||
- Halo complete units 379 -> 380; complete_code +6,987; complete_data +392; matched_code +1,729; matched functions +1.
|
||||
- Parks 86 -> 85 (0 stale or invalid); revoked []; admission 11/0/2/0.
|
||||
- Applying 01 without 02 fails progress with 'parked-function evidence is stale or invalid'.
|
||||
- With king also applied: 381.
|
||||
@@ -4,6 +4,8 @@ C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\bounding_sphere\final\
|
||||
C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\collisions\final\matrix_math.c (diff vs source/physics/collisions.c is 76828 bytes; wrong mapping or whole-file rewrite)
|
||||
C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\game_engine_clean\final\source\game\game_engine.c (diff vs source/game/game_engine.c is 80693 bytes; wrong mapping or whole-file rewrite)
|
||||
C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\game_engine_clean\final\source\interface\hud_nav_points.c (diff vs source/game/game_engine.c is 229480 bytes; wrong mapping or whole-file rewrite)
|
||||
C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\game_engine_finish\final\source\game\game_engine.c (diff vs source/game/game_engine.c is 155153 bytes; wrong mapping or whole-file rewrite)
|
||||
C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\game_engine_finish\final\source\interface\hud_nav_points.c (diff vs source/game/game_engine.c is 229482 bytes; wrong mapping or whole-file rewrite)
|
||||
C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\path_audit\lab\cand_av_dist.c (diff vs source/ai/path.c is 76483 bytes; wrong mapping or whole-file rewrite)
|
||||
C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\path_audit\lab\cand_av_ogbs.c (diff vs source/render/render_objects.c is 61655 bytes; wrong mapping or whole-file rewrite)
|
||||
C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\path_audit\lab\cand_decals_pp2d.c (diff vs source/render/render_debug.c is 129147 bytes; wrong mapping or whole-file rewrite)
|
||||
@@ -14,7 +16,7 @@ C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\provider\bored_camera\
|
||||
C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\provider\object_lights\cand1.c (diff vs source/structures/leaf_map.c is 106196 bytes; wrong mapping or whole-file rewrite)
|
||||
C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\provider\path_obstacles\cand2.c (diff vs source/objects/objects.c is 162670 bytes; wrong mapping or whole-file rewrite)
|
||||
C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\provider\player_control\cand1.c (diff vs source/objects/objects.c is 197248 bytes; wrong mapping or whole-file rewrite)
|
||||
C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\provider\players\cand1.c (diff vs source/math/geometry.c is 159020 bytes; wrong mapping or whole-file rewrite)
|
||||
C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\provider\players\cand1.c (diff vs source/math/geometry.c is 158783 bytes; wrong mapping or whole-file rewrite)
|
||||
C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\rasterizer_xbox_profile\candidate_files\source\rasterizer\rasterizer.c (diff vs source/rasterizer/xbox/rasterizer_xbox_profile.c is 76410 bytes; wrong mapping or whole-file rewrite)
|
||||
C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\sound_manager\final\sound_definitions.c (diff vs source/sound/sound_manager.c is 107261 bytes; wrong mapping or whole-file rewrite)
|
||||
C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\weapons\final\action_charge.c (diff vs source/items/weapons.c is 130496 bytes; wrong mapping or whole-file rewrite)
|
||||
|
||||
@@ -0,0 +1,230 @@
|
||||
# Worker brief - Halo January 50-object campaign (lane claude/fifty-objects-20260925)
|
||||
|
||||
Worktree (shared by all workers): `C:\halo-worktrees\claude-fifty-objects-20260925`
|
||||
Base: canonical jonas/exact-pilots `e9e62b78`. Scorer frozen: objdiff **3.3.1** (never replace it).
|
||||
|
||||
## 0. Hard rules for workers (violations corrupt everyone's work)
|
||||
|
||||
- **Never edit any tracked file** (source/, config/, tools/, docs/, headers, symbols.json,
|
||||
parked.json, config.json). Never run `ninja`, `configure.py`, `git add/commit/checkout/reset/stash`.
|
||||
The integrator applies every change. You work ONLY under `scratch/w/<your-unit-slug>/`.
|
||||
- Compile candidates with `python tools/campaign/gate.py source/<unit> --source scratch/w/<slug>/cand.c --all --out scratch/w/<slug>/cand.obj`
|
||||
(PID-isolated; safe in parallel). `--source` may be anywhere; the unit's directory is on /I.
|
||||
- The January target object is `build/split/<unit>.obj`; the current production build is
|
||||
`build/base/<unit>.obj`. Treat both as read-only.
|
||||
- Analyze leaked/first-party executables as DATA only. Never execute them.
|
||||
- Append findings to `scratch/w/<slug>/LEDGER.md` AS YOU GO (a cut-off run keeps nothing else).
|
||||
|
||||
## 1. What counts
|
||||
|
||||
Strict exact = `coff_compare.section_infos_equal` (size, normalized bytes, relocation count,
|
||||
type, address, target, addend). gate.py prints `EXACT` rows. Fuzzy %, instruction counts or a
|
||||
coincidental SHA are not exactness. An object is COMPLETE only when every January-owned function
|
||||
AND data/BSS section, every symbol (name, storage class, section, offset), and all surplus
|
||||
emissions (COMDAT helpers, literals, SDK tables) are admissible - see section 4.
|
||||
|
||||
Never count: scorer-version effects, status edits, already-identical bytes, fuzzy gains.
|
||||
|
||||
## 2. House rules (all changed source) - docs/campaign_house_rules.md is authoritative
|
||||
|
||||
void on its own line for empty params; one parameter per line; explicit `return;` / valid
|
||||
return values; typed tag/object access macros; prototypes in genuine owner headers (never a
|
||||
consumer-local prototype for another file's function); `real` not `float`; cseries.h macros
|
||||
(TEST_FLAG/SET_FLAG/FLAG/PIN/MIN/MAX/NUMBEROF...) over hand bit twiddling; correct enum constants
|
||||
(also in switch tables); combine declaration+initialisation where natural; authentic or
|
||||
descriptive names (never code_/bss_+address); assertions via the lazy project macros
|
||||
(match_assert/match_vassert/... with the right predicate sense; see docs/assertions.md).
|
||||
|
||||
Rule 6: never hand-expand or hand-copy point_from_line3d or any header helper. A shared-header
|
||||
`__inline` may emit a COMDAT ONLY if the copy is byte-identical to January's selected provider,
|
||||
the caller is strictly exact, the full sweep has zero regressions and ordinary provider links
|
||||
pass in BOTH orders (scratch/tools/provider_link.py). No blanket COMDAT permission.
|
||||
|
||||
Rejected as fake matching (the STRIP TEST: remove the decoration; if the plain spelling no longer
|
||||
matches, the decoration IS the fake): decoration-only parentheses, redundant zero stores without
|
||||
independent evidence, filler declarations/dummy locals (they are the name-count ORACLE, never a
|
||||
landing), do{}while(FALSE) or one-trip loops to buy inline budget, volatile/aliasing tricks,
|
||||
pragmas, forced inline, inline asm as a general lever, invented UB. A new 3D-to-2D (or other
|
||||
representation) view cast needs per-site first-party /Od attestation, compatible prefix layout,
|
||||
a byte-inert strip test, a strictly exact caller and ledger disclosure. Reproducing an authentic
|
||||
January bug needs target+layout proof, a BUG comment and owner approval - report, don't land.
|
||||
|
||||
Held items you must NOT retry: path_obstacles bare-parenthesis match, actor_aim_grenade invented
|
||||
goto, hud_draw optimizer pragma, s3tc live out-of-bounds behaviour, render_sprite memory
|
||||
corruption, flags `x * height` with x just set to zero, any incompatible helper provider.
|
||||
decals.c / physics.c are closed for this lane unless you hold NEW evidence for the specific
|
||||
load/slot/x87 residuals recorded in docs/object_matching_logs/claude_decals_physics_20260924.md.
|
||||
|
||||
## 3. Evidence sources and tools (use these before guessing)
|
||||
|
||||
- January bytes/relocs: `python tools/campaign/tinfo.py source/<unit> [--fn F] [--data]`,
|
||||
`python tools/campaign/alndiff.py source/<unit> <fn> --ours-object <obj>` (aligned diff; never
|
||||
trust gate.py --disas index pairing), `python tools/campaign/relocdiff.py source/<unit> <fn> [obj]`,
|
||||
`python tools/campaign/real_regions.py source/<unit> <fn> --ours-object <obj>`.
|
||||
- Lane helpers in scratch/tools/: `sbs.py` (side-by-side range), `dis_range.py`,
|
||||
`reloc_segments.py` (instruction census between relocation anchors), `slot_census.py` and
|
||||
`slot_refs.py` (frame slots), `leafswaps.py` (classify alndiff blocks LEAF/SLOT/REG/OTHER).
|
||||
- Later first-party **/Od+/RTC build** (statement order, real calls vs expressions, named locals as
|
||||
frame slots, RTC descriptors naming every address-taken aggregate, assert LINE numbers):
|
||||
`python scratch/tools/odbuild.py str "<string>"`, `... callers 0xADDR`, `... fn 0xADDR --out f.txt`.
|
||||
odbuild misses aligned-frame prologues (`push ebx; mov ebx,esp; and esp,-8`): then use
|
||||
`python scratch/tools/od_linear.py 0xSTART 0xEND out.txt`. It is a LATER revision - evidence for
|
||||
names/types/shape only; every fact must be double-attested against January's own bytes.
|
||||
- **HCEX.pdb** (2011 PPC SHIP build; real names/types of params and stack locals, file statics):
|
||||
`"C:/Users/isabe/Documents/Codex/2026-07-13/i-w/research/tools/DIA2Dump/x64/Release/DIA2Dump.exe" -sym <function> "C:/Users/isabe/Documents/Codex/2026-07-13/i-w/research/hcea_jun2011_prototype/payload/Halo CE Anniversary (Jun 24 2011)/HCEX.pdb"`
|
||||
(enregistered scalars are absent; layouts/offsets do not transfer).
|
||||
- cachebeta.pdb publics (January storage truth: public = external, absent = file-static):
|
||||
`scratch/tools/cachebeta_publics.txt`, checked by `python scratch/tools/pdb_storage.py source/<unit>`.
|
||||
- Halo CE symbol atlas / Marathon source / Bungie fragments: names and idioms, not byte proof.
|
||||
- Ghidra 12.1.2 headless: `C:/Users/isabe/Documents/Codex/halo-tools/apps/ghidra_12.1.2_PUBLIC`
|
||||
(support/analyzeHeadless.bat); IDA Free 9.4 is GUI-only. Record exactly what a tool established;
|
||||
a decompiler rendering is not original source.
|
||||
- Existing ledgers: `docs/object_matching_logs/*<unit>*`, parks in `config/parked.json`
|
||||
(`python -B -m tools.parked_functions`), rejections in `config/object_admission_rejections.json`.
|
||||
READ THE NEGATIVE EXPERIMENTS before probing; do not repeat recorded inert spellings.
|
||||
|
||||
## 4. Whole-object admission audit (for any object you claim complete)
|
||||
|
||||
1. `python tools/campaign/gate.py source/<unit> --source <cand> --all --out <obj>`: every row EXACT.
|
||||
2. `python scratch/tools/object_audit.py source/<unit> <obj>`: every January-owned section and
|
||||
symbol (storage, section, offset) matches; lists candidate-only surplus.
|
||||
3. `python scratch/tools/pdb_storage.py source/<unit>` (on the production build; for a candidate
|
||||
reason from its symbols): storage vs cachebeta publics.
|
||||
4. Surplus: `python scratch/tools/surplus_identity.py source/<unit>` and
|
||||
`python scratch/tools/provider_link.py source/<unit> <obj>` - every surplus COMDAT must be
|
||||
byte-identical to January's selected copy and pair-link (no LNK2005/LNK1169) in both orders.
|
||||
Known conflicts: NODUP hand copies (`python scratch/tools/nodup_census.py _sym ...`).
|
||||
5. Data: `python tools/campaign/tinfo.py source/<unit> --data` vs `--base`; objdiff 3.3.1 has a
|
||||
known '$'-literal relocation-name defect - a data section that is byte+relocation identical
|
||||
under coff_compare but <100% in build/report.json is a scorer defect, handled by a pinned
|
||||
config/semantic_data_matches.json entry (integrator applies; single-section entries only).
|
||||
6. Check config/object_admission_rejections.json and parks for the unit.
|
||||
|
||||
## 5. Decoded compiler laws (use as hypothesis generators; each has a ledger)
|
||||
|
||||
- Frame-size mismatch (`sub esp,N`, see scratch/baseline/frame_census.txt) is STRUCTURAL: a
|
||||
different set/scope/type of homed locals, never a tie. Slot sharing is gated by declaration
|
||||
SCOPE (an object may merge into another's slot only if neither scope encloses the other);
|
||||
address-taken locals conflict until the end of their declaration scope. Below 0x80 total the
|
||||
frame order is size-ascending + per-reference bubble-up; above 0x80 a quicksort on
|
||||
(1000*refs)/size. A partly homed aggregate costs its whole extent.
|
||||
- Single-exit law: January usually returns ONCE at the bottom (result/valid flag), not early
|
||||
returns; count return statements. Fixing it on a static cascades to callers (private ABI).
|
||||
- /Od readout first: named locals (count user-area frame slots, not only RTC aggregates), statement
|
||||
order, which helpers are real calls, loop-counter scoping, argument order of helper calls.
|
||||
- Inline gating: per call SITE, callee cost vs block-weight budget; each extra if/&&/|| level on
|
||||
the path lowers the budget; an early return costs one step for the rest of the function; a
|
||||
`= {0}` aggregate initialiser and a match_assert in the helper raise cost. Measure the boundary
|
||||
with lab copies of the call placed along the path (lab only).
|
||||
- M8: x87 operand order of inlined helpers follows IL-local ordinals mod 8 of their parameters;
|
||||
helper ARGUMENT order matters, bare source operand order of `a*b` is inert.
|
||||
- Store/call order: a store through a pointer cannot cross a call, so its position relative to a
|
||||
call IS January's statement order. Post-increment inside a call argument vs a separate
|
||||
statement changes whether the increment precedes the call.
|
||||
- LAW Z: "January pins a zero register and we don't" is a SOURCE defect (a surplus long-lived
|
||||
value/alias, declaration order of zero-initialised locals), not a tie.
|
||||
- Accessor binding: `&accessor(...)->field` inline folds destructively; binding to a local gives
|
||||
the non-destructive lea - read the bytes per site.
|
||||
- VC7 unrolls small constant-trip for/while but not do..while; NUMBEROF is size_t (unsigned
|
||||
compare); `and 80000007h` proves a signed divisor; a float literal 1 ULP off proves a folded
|
||||
expression.
|
||||
- Warnings as detectors: `CL /Zs /W3` C4013 implicit declarations push real args as doubles.
|
||||
- Name-count / declaration-count ties: dummy declarations flip distant ties - use ONLY as an
|
||||
oracle to locate genuinely missing January declarations; never land fillers.
|
||||
- Methodology stop rule: after ~5 evidence-based source shapes with only an interchangeable
|
||||
register / dependency-free order left, stop, preserve the best credible candidate at zero
|
||||
credit, record reopen criteria.
|
||||
|
||||
## 6. Reporting
|
||||
|
||||
Your final answer must be the structured result requested by the orchestrator. Keep full
|
||||
evidence in `scratch/w/<slug>/` (candidate .c, gate rows before/after, alndiff excerpts,
|
||||
LEDGER.md with every probe: hypothesis -> evidence -> change -> measured result).
|
||||
|
||||
## 7. Wave-2 state and new findings (base commit 931ed8dc)
|
||||
|
||||
- LANDED: Layer 1 + Layer 2 helper-provider repairs. These hand-written NODUP copies are GONE
|
||||
(the genuine real_math.h inline now emits byte-identical SELECT_ANY copies): real_random,
|
||||
signed_angular_difference, interpolate_scalar, valid_real_vector3d_axes2, valid_real_normal3d,
|
||||
point_in_sphere, rotate_vector2d, project_point3d, point_in_circle, distance_squared2d/3d,
|
||||
distance2d/3d, negate_vector2d, plane3d_from_point_and_normal, plane3d_negate,
|
||||
projection_sign_from_vector3d, triple_product3d, project_point2d. real_math.h's distance2d/3d
|
||||
and project_point2d bodies now equal January's selected copies. Remaining known conflicts:
|
||||
actor_combat `_cross_product2d` (NODUP hand copy; its genuine use is in the held aim_grenade),
|
||||
action_vehicle `_object_get_bounding_sphere` (assert-string differs: "..\objects\objects.h"),
|
||||
effects `_real_local_random`, player_control `limit2d`, plus any found by provider_link.py.
|
||||
- Owner-gated classes (report with evidence, never self-land): reproducing authentic January
|
||||
uninitialised reads / NULL dereferences; new representation view casts or aggregate view
|
||||
copies that are load-bearing (not byte-inert); header edits that regress declaration-count
|
||||
canaries or keep an extern prototype over a static definition; dead or unattested named
|
||||
locals whose only role is the match (they fail the strip test); non-/Od-attested staging temps.
|
||||
- Decoded in wave 1: (a) C2 compiles functions in definition order except a function calling a
|
||||
not-yet-defined TU function is deferred to the end - recovers January's definition order from
|
||||
emission order; (b) allocator block weight = number of webs referenced in the block, so an
|
||||
inlined helper's named local can flip caller colouring; (c) a load from a FILE-STATIC const
|
||||
aggregate whose address is never taken is hoisted above pointer stores, an external one is not
|
||||
- check cachebeta publics for any const global in an emission-order residual.
|
||||
- Git Bash rewrites `gate.py --cflag /X` into a Windows path; prefix with MSYS_NO_PATHCONV=1.
|
||||
- Wave-1 worker dirs scratch/w/<unit>/ still exist; resume from their LEDGER.md when re-tasked.
|
||||
|
||||
## 8. Wave-3 state (base commit 954eebd2; Halo objects 375)
|
||||
|
||||
- LANDED since 931ed8dc: b807f9f6 objects.h OBJECTS_H_FILE (bounding-sphere inline assertions
|
||||
report January's per-TU __FILE__; default "..\objects\objects.h", object_lights defines the
|
||||
absolute spelling first) + action_vehicle bounding-sphere hand copy removed; path.h HCEX field
|
||||
`struct path_result result`. b9a8d587 admitted units, collision_debug, render_objects,
|
||||
editor_flying_camera, rasterizer_xbox_shadows, cache_files_windows, light_volumes,
|
||||
actor_firing_position, path, biped_limp_noodle, leaf_map, model_animations.
|
||||
- `_object_get_bounding_sphere` is NO LONGER a provider conflict for non-objects/ units.
|
||||
- Held owner items (do not self-land; do not re-probe unless you have NEW evidence): actor_combat
|
||||
P1 cross_product2d (w/cross_product2d), king/glow/fpw-B/dead_camera authentic-bug class,
|
||||
object_lights __FILE__ surplus, rasterizer_xbox .bss names, hardware_geometry A/B wrapper,
|
||||
network_connection connect form, breakable_surfaces real_local_random count, actions grouped
|
||||
data verifier, render_debug invented aggregate, bitmap_drawing unnamed static.
|
||||
- Wave-2 laws: (d) reviewers REJECT scope/block groupings that contradict the /Od frame's
|
||||
DECLARATION order even when exact - check /Od declaration order before proposing any block;
|
||||
(e) the escape law: only a local whose address reaches an out-of-line call needs a scope;
|
||||
(f) /Od RTC names + same statement pair + zero assert-anchor drift authenticated a dead
|
||||
statement pair (editor_flying_camera) - a dead statement WITHOUT /Od attestation is a filler;
|
||||
(g) caller-local struct views with opaque spans, consumer-local prototypes of other files'
|
||||
functions, hand-expanded header helpers and `float` for `real` all block admission even when
|
||||
every byte matches - scan for them before claiming OBJECT_COMPLETE_CANDIDATE.
|
||||
- Every earlier wave's ledgers are also in research/fifty_objects_20260925/ (tracked copies).
|
||||
|
||||
## 9. Wave-4 state and INCIDENT RULES (base commit 16542e46; Halo objects 378)
|
||||
|
||||
INCIDENTS in wave 3 (both repaired): a reviewer's broken `&&` chain ran `rm -rf .git` in the
|
||||
worktree ROOT (deleting the worktree pointer), and `tools/campaign/volatile_scan.py --help` (no
|
||||
argparse) ran a hard-coded scan that REWROTE source/hs/hs.c. Therefore:
|
||||
- NEVER run rm/mv/cp/sed -i/redirects whose target is not under YOUR scratch/w/<slug>/. Always use
|
||||
absolute slug paths for destructive commands; never `cd` then `rm -rf` in one chain.
|
||||
- NEVER touch `.git`, build/, config/, source/ or tools/ files (read only).
|
||||
- Before running ANY repo script you have not run before, READ its source; do not assume --help
|
||||
is safe. If a script writes files, copy it into your slug and point its outputs there.
|
||||
- If you see the tree modified by someone else (git status not clean), STOP and report it.
|
||||
|
||||
LANDED since 954eebd2: f7cd2e72 player_ui (game_engine.h game_variant layout with HCEX member
|
||||
names + member renames across game engines; player_ui.h) and sound_manager (sound_definitions.h
|
||||
short old_range_index). Batch 4b: dynavobgeom admission, damage _object_damage_body, players
|
||||
storage + COMMON definitions, player_profile/main zero-credit packets, hs storage (839 statics +
|
||||
hs_enumerate_scenario_data helper), hs_scenario_definitions static rename.
|
||||
Wave-3 laws: (h) an unreferenced non-public STATIC function is still emitted if the source USES
|
||||
it (148 Halo examples) - storage cannot be inferred from "unreferenced"; (i) a newly emitted header
|
||||
__inline COMDAT is admissible only if its caller is strictly exact (the damage patch A and hs cleanup
|
||||
were rejected on this; P1 class); (j) VC7 /O2 pads every file-scope static to 4 bytes, so pad members
|
||||
in a TU-private struct are the signature of an INVENTED aggregate.
|
||||
|
||||
## 10. Wave-5: OWNER-QUEUE VERIFICATION (base commit cdc8ebd3; Halo objects 379)
|
||||
|
||||
Nothing in this wave lands. Each lane takes one or two HELD owner items (ledger held-items table)
|
||||
and makes them APPLY-READY on the current tip: rebase every patch onto cdc8ebd3 (the tree moved:
|
||||
f7cd2e72 renamed game_variant members in game_engine*.c incl. king; b807f9f6 objects.h; 466698b8
|
||||
hud_draw.h), re-measure, and write everything under scratch/w/owner_queue/<item>/:
|
||||
- patches/ (git apply --check clean at cdc8ebd3, in apply order, plus an APPLY_ORDER.txt),
|
||||
- the edited symbols.json copy if needed (in-place edits, based on cdc8ebd3),
|
||||
- MEASURED.md: gate --all (every January function of every affected object), object_audit against
|
||||
an emulated split, provider_link both orders, data status, and the exact list of objects that
|
||||
become COMPLETE if the owner says yes (and those that still would not, with why),
|
||||
- RULING.md: the precise yes/no question for the owner, the first-party evidence for and against,
|
||||
the BUG/disclosure comments exactly as they would land, and the house-rule classes touched.
|
||||
Obey sections 0 and 9 (incident rules) strictly.
|
||||
@@ -0,0 +1,71 @@
|
||||
"""Integrator admission helper: flip config.json statuses, append semantic data entries, drop rejections.
|
||||
|
||||
python scratch/campaign/admit.py --match source/x/y.c [...] [--unmatch source/..c]
|
||||
[--data-entry entry.json ...] [--drop-rejection <unit> <symbol-prefix>] ...
|
||||
All edits are textual and in place (no JSON re-serialisation of config.json / rejections).
|
||||
"""
|
||||
import json
|
||||
import re
|
||||
import sys
|
||||
|
||||
args = sys.argv[1:]
|
||||
match, unmatch, entries, drops = [], [], [], []
|
||||
i = 0
|
||||
while i < len(args):
|
||||
a = args[i]
|
||||
if a == '--match':
|
||||
match.append(args[i + 1]); i += 2
|
||||
elif a == '--unmatch':
|
||||
unmatch.append(args[i + 1]); i += 2
|
||||
elif a == '--data-entry':
|
||||
entries.append(args[i + 1]); i += 2
|
||||
elif a == '--drop-rejection':
|
||||
drops.append((args[i + 1], args[i + 2])); i += 3
|
||||
else:
|
||||
sys.exit('bad arg ' + a)
|
||||
|
||||
|
||||
def edit_status(names, new):
|
||||
p = 'config/config.json'
|
||||
raw = open(p, 'rb').read().decode('utf-8')
|
||||
for n in names:
|
||||
pat = re.compile(r'(\{ "name": "%s", "index": \d+, "status": ")(\w+)(" \})' % re.escape(n))
|
||||
hits = pat.findall(raw)
|
||||
if len(hits) != 1:
|
||||
sys.exit('status: %d hits for %s' % (len(hits), n))
|
||||
raw = pat.sub(lambda m: m.group(1) + new + m.group(3), raw)
|
||||
print('status', n, hits[0][1], '->', new)
|
||||
open(p, 'wb').write(raw.encode('utf-8'))
|
||||
|
||||
|
||||
if match:
|
||||
edit_status(match, 'Matching')
|
||||
if unmatch:
|
||||
edit_status(unmatch, 'NonMatching')
|
||||
|
||||
if entries:
|
||||
p = 'config/semantic_data_matches.json'
|
||||
raw = open(p, 'rb').read().decode('utf-8')
|
||||
nl = '\r\n' if '\r\n' in raw else '\n'
|
||||
body = raw.rstrip()
|
||||
assert body.endswith(']'), 'unexpected end'
|
||||
body = body[:-1].rstrip()
|
||||
for e in entries:
|
||||
obj = json.load(open(e))
|
||||
txt = json.dumps(obj, indent=2).replace('\n', nl)
|
||||
txt = nl.join(' ' + l for l in txt.split(nl))
|
||||
body += ',' + nl + txt
|
||||
print('data entry', obj['unit'], obj.get('symbol'))
|
||||
open(p, 'wb').write((body + nl + ']' + nl).encode('utf-8'))
|
||||
json.load(open(p))
|
||||
|
||||
if drops:
|
||||
p = 'config/object_admission_rejections.json'
|
||||
d = json.load(open(p))
|
||||
before = len(d['entries'])
|
||||
for unit, sym in drops:
|
||||
d['entries'] = [e for e in d['entries'] if not (e['unit'] == unit and e['symbol'].startswith(sym))]
|
||||
print('rejections', before, '->', len(d['entries']))
|
||||
raw = open(p, 'rb').read().decode('utf-8')
|
||||
nl = '\r\n' if '\r\n' in raw else '\n'
|
||||
open(p, 'wb').write((json.dumps(d, indent=2, ensure_ascii=False).replace('\n', nl) + nl).encode('utf-8'))
|
||||
@@ -0,0 +1,35 @@
|
||||
"""Run the whole-object admission battery on production build/base for a list of units.
|
||||
|
||||
python scratch/campaign/audit_battery.py <unit> [<unit> ...] (units like ai/path)
|
||||
Prints per unit: gate totals, object_audit verdict (+ failing lines), PDB disagreements,
|
||||
surplus identity, provider-link verdict (+ failing symbols), report data %.
|
||||
"""
|
||||
import json
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
rep = {u['name']: u for u in json.load(open('build/report.json'))['units']}
|
||||
|
||||
|
||||
def run(cmd):
|
||||
r = subprocess.run(cmd, capture_output=True, text=True)
|
||||
return (r.stdout + r.stderr).strip().splitlines()
|
||||
|
||||
|
||||
for u in sys.argv[1:]:
|
||||
unit = 'source/' + u
|
||||
g = run([sys.executable, 'tools/campaign/gate.py', unit, '--all'])
|
||||
oa = run([sys.executable, 'scratch/tools/object_audit.py', unit])
|
||||
pdb = run([sys.executable, 'scratch/tools/pdb_storage.py', unit])
|
||||
si = run([sys.executable, 'scratch/tools/surplus_identity.py', unit])
|
||||
pl = run([sys.executable, 'scratch/tools/provider_link.py', unit])
|
||||
m = rep.get(unit, {}).get('measures', {})
|
||||
print('=' * 20, u)
|
||||
print(' gate :', g[-1] if g else '?')
|
||||
bad = [l for l in oa if 'DIFF' in l or 'MISSING' in l or 'storage' in l.lower() and '!=' in l]
|
||||
print(' audit :', oa[-1] if oa else '?', '|', ' ; '.join(x.strip() for x in bad[:6]))
|
||||
print(' pdb :', pdb[-1] if pdb else '?')
|
||||
print(' surplus:', si[-1] if si else '?', '|', ' ; '.join(x.strip() for x in si if 'DIFFERENT' in x)[:300])
|
||||
fails = [l.split()[0] for l in pl if l.rstrip().endswith('FAIL') or 'NO JANUARY PROVIDER' in l]
|
||||
print(' link :', pl[-1] if pl else '?', fails)
|
||||
print(' data : %s/%s' % (m.get('matched_data'), m.get('total_data')))
|
||||
@@ -0,0 +1,88 @@
|
||||
"""Integrator batch gate: run the full verification chain and summarise against the frozen baseline.
|
||||
|
||||
python scratch/campaign/batch_gate.py <label>
|
||||
|
||||
Steps: guard objdiff version (3.3.1) and CL path, ninja (full; re-patch build.ninja if configure
|
||||
re-ran), parse progress, stable_verdicts snapshot+diff vs scratch/baseline/stable.json, parks,
|
||||
admission audit, fake-match scan (lead count vs baseline), pytest, git diff --check.
|
||||
Writes scratch/campaign/gate_<label>/ with every raw log.
|
||||
"""
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
os.chdir(ROOT)
|
||||
label = sys.argv[1]
|
||||
out = os.path.join('scratch', 'campaign', 'gate_' + label)
|
||||
os.makedirs(out, exist_ok=True)
|
||||
|
||||
|
||||
def run(name, cmd, timeout=3600):
|
||||
r = subprocess.run(cmd, capture_output=True, text=True, timeout=timeout, shell=isinstance(cmd, str))
|
||||
open(os.path.join(out, name + '.log'), 'w', encoding='utf-8').write(r.stdout + '\n' + r.stderr)
|
||||
return r
|
||||
|
||||
|
||||
def objdiff_version():
|
||||
return run('objdiff_version', [os.path.join('build', 'tools', 'objdiff-cli.exe'), '--version']).stdout.strip()
|
||||
|
||||
|
||||
summary = {}
|
||||
v = objdiff_version()
|
||||
summary['objdiff'] = v
|
||||
if '3.3.1' not in v:
|
||||
print('ABORT: objdiff is not 3.3.1:', v)
|
||||
sys.exit(2)
|
||||
|
||||
# ninja; if configure re-ran, re-patch the CL path and rebuild
|
||||
r = run('ninja', ['ninja'])
|
||||
if r.returncode != 0 and 'The system cannot find the file specified' in (r.stdout + r.stderr):
|
||||
run('ninja_manifest', ['ninja', 'build.ninja'])
|
||||
run('patch', [sys.executable, 'scratch/patch_ninja.py'])
|
||||
r = run('ninja', ['ninja'])
|
||||
bn = open('build.ninja').read()
|
||||
if 'command = xbox/bin/vc7/CL.Exe' in bn:
|
||||
run('patch', [sys.executable, 'scratch/patch_ninja.py'])
|
||||
r = run('ninja', ['ninja'])
|
||||
summary['ninja_exit'] = r.returncode
|
||||
v2 = objdiff_version()
|
||||
summary['objdiff_after'] = v2
|
||||
log = r.stdout
|
||||
m = re.search(r'halobetacache: ([\d.]+)% matched, ([\d.]+)% linked \((\d+) / (\d+) files\)\s+Code: (\d+) / (\d+) bytes \((\d+) / (\d+) functions\)\s+Data: (\d+) / (\d+) bytes', log)
|
||||
if m:
|
||||
summary['halo'] = {'objects': int(m.group(3)), 'of': int(m.group(4)), 'code': int(m.group(5)),
|
||||
'code_total': int(m.group(6)), 'functions': int(m.group(7)), 'data': int(m.group(9))}
|
||||
m = re.search(r'All: [\d.]+% matched, [\d.]+% linked \((\d+) / (\d+) files\)', log)
|
||||
if m:
|
||||
summary['all_objects'] = int(m.group(1))
|
||||
|
||||
run('snapshot', [sys.executable, '-m', 'tools.campaign.stable_verdicts', 'snapshot', os.path.join(out, 'stable.json')])
|
||||
d = run('stable_diff', [sys.executable, '-m', 'tools.campaign.stable_verdicts', 'diff', 'scratch/baseline/stable.json', os.path.join(out, 'stable.json')])
|
||||
summary['stable_diff_exit'] = d.returncode
|
||||
summary['stable_diff_tail'] = d.stdout.strip().splitlines()[-6:]
|
||||
|
||||
p = run('parks', [sys.executable, '-B', '-m', 'tools.parked_functions'])
|
||||
try:
|
||||
summary['parks'] = json.loads(p.stdout)['summary']
|
||||
except Exception:
|
||||
summary['parks'] = p.stdout[-400:]
|
||||
a = run('admission', [sys.executable, 'tools/audit_object_admission.py'])
|
||||
try:
|
||||
aj = json.loads(a.stdout)
|
||||
summary['admission'] = aj['summary']
|
||||
summary['admission_contradicted'] = [c.get('unit') for c in aj.get('contradicted', [])]
|
||||
summary['admission_revoked'] = [c.get('unit') for c in aj.get('revoked', [])]
|
||||
except Exception:
|
||||
summary['admission'] = a.stdout[-400:]
|
||||
f = run('fake_scan', [sys.executable, 'tools/fake_match_scan.py'])
|
||||
m = re.search(r'(\d+) review lead', f.stdout)
|
||||
summary['fake_leads'] = int(m.group(1)) if m else f.stdout[-200:]
|
||||
t = run('pytest', [sys.executable, '-m', 'pytest', '-q', 'tools', '--basetemp=' + os.path.join(ROOT, 'scratch', 'pytest_tmp')])
|
||||
summary['pytest'] = t.stdout.strip().splitlines()[-1] if t.stdout.strip() else t.stderr[-200:]
|
||||
g = run('diff_check', ['git', 'diff', '--check'])
|
||||
summary['diff_check'] = 'clean' if not g.stdout.strip() else g.stdout[:400]
|
||||
json.dump(summary, open(os.path.join(out, 'summary.json'), 'w'), indent=1)
|
||||
print(json.dumps(summary, indent=1))
|
||||
@@ -0,0 +1,96 @@
|
||||
"""Copy curated worker evidence from ignored scratch/ into tracked research/fifty_objects_20260925/.
|
||||
|
||||
python scratch/campaign/curate.py
|
||||
|
||||
Copies, per scratch/w/<slug>/: every *.md, *.patch and *.diff (outside split/ and config/ copies),
|
||||
plus a diff against the tree for every .c candidate that wave results name in candidate_files; and every wave result/review record under scratch/campaign/wave*/units/.
|
||||
Skips any single file over 400 KB (listed in SKIPPED.txt). .obj, split and symbols.json copies are
|
||||
never copied. Idempotent: re-running overwrites with the current scratch contents.
|
||||
"""
|
||||
import glob
|
||||
import json
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
|
||||
ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
os.chdir(ROOT)
|
||||
DEST = os.path.join('research', 'fifty_objects_20260925')
|
||||
LIMIT = 400 * 1024
|
||||
skipped = []
|
||||
copied = 0
|
||||
|
||||
|
||||
def want_dir(rel):
|
||||
parts = rel.replace('\\', '/').split('/')
|
||||
return not any(p in ('split', 'config', '__pycache__') or p.startswith('split_') for p in parts)
|
||||
|
||||
|
||||
def copy(src, dst):
|
||||
global copied
|
||||
if os.path.getsize(src) > LIMIT:
|
||||
skipped.append('%s (%d bytes)' % (src, os.path.getsize(src)))
|
||||
return
|
||||
os.makedirs(os.path.dirname(dst), exist_ok=True)
|
||||
shutil.copyfile(src, dst)
|
||||
copied += 1
|
||||
|
||||
|
||||
for slug in sorted(os.listdir(os.path.join('scratch', 'w'))):
|
||||
base = os.path.join('scratch', 'w', slug)
|
||||
if not os.path.isdir(base):
|
||||
continue
|
||||
for dirpath, dirnames, filenames in os.walk(base):
|
||||
rel = os.path.relpath(dirpath, base)
|
||||
if not want_dir(rel):
|
||||
dirnames[:] = []
|
||||
continue
|
||||
for f in filenames:
|
||||
ext = os.path.splitext(f)[1].lower()
|
||||
if ext in ('.md', '.patch', '.diff') or f.startswith('APPLY_ORDER') or f == 'SHA256SUMS.txt':
|
||||
copy(os.path.join(dirpath, f), os.path.join(DEST, 'w', slug, rel, f))
|
||||
|
||||
# named candidate sources are stored as diffs against the tree's version of the unit's .c
|
||||
named = {}
|
||||
for res in glob.glob(os.path.join('scratch', 'campaign', 'wave*', 'result.json')):
|
||||
data = json.load(open(res, encoding='utf-8'))
|
||||
for r in data.get('results', []):
|
||||
for u in (r or {}).get('units', []) or []:
|
||||
src = (u.get('unit') or '').split(' ')[0]
|
||||
src = src if src.endswith('.c') else src + '.c'
|
||||
for c in u.get('candidate_files', []) or []:
|
||||
if c.lower().endswith('.c'):
|
||||
named[os.path.normpath(c)] = src
|
||||
for c, src in sorted(named.items()):
|
||||
rel = os.path.relpath(c, os.path.join(ROOT, 'scratch', 'w'))
|
||||
if rel.startswith('..') or not os.path.exists(c):
|
||||
continue
|
||||
dst = os.path.join(DEST, 'w', rel[:-2] + '.vs_tree.diff')
|
||||
if os.path.exists(src):
|
||||
d = subprocess.run(['git', 'diff', '--no-index', '--ignore-cr-at-eol', src, c], capture_output=True, text=True,
|
||||
encoding='utf-8', errors='replace').stdout
|
||||
if d and len(d) > 60000:
|
||||
skipped.append('%s (diff vs %s is %d bytes; wrong mapping or whole-file rewrite)' % (c, src, len(d)))
|
||||
elif d:
|
||||
os.makedirs(os.path.dirname(dst), exist_ok=True)
|
||||
open(dst, 'w', encoding='utf-8', newline='\n').write(d)
|
||||
copied += 1
|
||||
else:
|
||||
copy(c, os.path.join(DEST, 'w', rel))
|
||||
|
||||
for rec in glob.glob(os.path.join('scratch', 'campaign', 'wave*', 'units', '*.md')):
|
||||
wave = rec.split(os.sep)[-3]
|
||||
copy(rec, os.path.join(DEST, 'results', wave, os.path.basename(rec)))
|
||||
|
||||
# the integrator kit that applies these packets
|
||||
for f in ('batch_gate.py', 'admit.py', 'sym_edit.py', 'sym_ops_from_copy.py', 'rebaseline_parks.py', 'audit_battery.py', 'curate.py', 'WORKER_BRIEF.md'):
|
||||
copy(os.path.join('scratch', 'campaign', f), os.path.join(DEST, 'integrator_kit', f))
|
||||
copy(os.path.join('scratch', 'patch_ninja.py'), os.path.join(DEST, 'integrator_kit', 'patch_ninja.py'))
|
||||
with open(os.path.join(DEST, '.gitattributes'), 'w', newline='\n') as fh:
|
||||
fh.write('# evidence copies are kept byte-for-byte (patches must still apply) and are not style-checked\n'
|
||||
'* -text -whitespace\n')
|
||||
with open(os.path.join(DEST, 'SKIPPED.txt'), 'w', encoding='utf-8', newline='\n') as fh:
|
||||
fh.write('Files over %d bytes left in scratch (not copied):\n' % LIMIT)
|
||||
for s in skipped:
|
||||
fh.write(s + '\n')
|
||||
print('copied', copied, 'skipped', len(skipped))
|
||||
@@ -0,0 +1,13 @@
|
||||
"""Patch build.ninja's cl rule to the absolute backslash CL path (run after every configure)."""
|
||||
import os
|
||||
|
||||
BS = chr(92)
|
||||
root = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
|
||||
cl = BS.join([root.replace('/', BS), 'xbox', 'bin', 'vc7', 'CL.Exe'])
|
||||
p = os.path.join(root, 'build.ninja')
|
||||
s = open(p).read()
|
||||
old = 'command = xbox/bin/vc7/CL.Exe'
|
||||
n = s.count(old)
|
||||
s = s.replace(old, 'command = ' + cl)
|
||||
open(p, 'w').write(s)
|
||||
print('patched', n, cl)
|
||||
@@ -0,0 +1,84 @@
|
||||
"""Re-baseline named stale parks to the current build's base measurements (textual, in place).
|
||||
|
||||
python scratch/campaign/rebaseline_parks.py "<unit>::<function>" [...] [--note "text"]
|
||||
|
||||
Runs tools.parked_functions validation against build/report.json, and for each NAMED key that is
|
||||
stale only in its base block / objdiff_percent (never target), rewrites those lines in
|
||||
config/parked.json. With --note, appends the sentence to that entry's evidence string.
|
||||
Any other stale or invalid entry is reported and left alone.
|
||||
"""
|
||||
import json
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parents[2]))
|
||||
from tools.parked_functions import validate_parked_functions # noqa: E402
|
||||
|
||||
root = Path(__file__).resolve().parents[2]
|
||||
args = sys.argv[1:]
|
||||
note = None
|
||||
if '--note' in args:
|
||||
i = args.index('--note')
|
||||
note = args[i + 1]
|
||||
del args[i:i + 2]
|
||||
wanted = set(args)
|
||||
|
||||
res = validate_parked_functions(root, root / 'build' / 'report.json', root / 'objdiff.json',
|
||||
root / 'config' / 'parked.json')
|
||||
path = root / 'config' / 'parked.json'
|
||||
raw = path.read_bytes().decode('utf-8')
|
||||
nl = '\r\n' if '\r\n' in raw else '\n'
|
||||
lines = raw.split(nl)
|
||||
done = []
|
||||
for item in res['stale']:
|
||||
key = '%s::%s' % (item['unit'], item['function'])
|
||||
if key not in wanted:
|
||||
print('stale (not named, left alone):', key, item.get('differences'))
|
||||
continue
|
||||
if any(d['measurement'].startswith('target') for d in item['differences']):
|
||||
sys.exit('ABORT: target measurement changed for ' + key)
|
||||
fn_pat = '"function": %s,' % json.dumps(item['function'])
|
||||
unit_pat = '"unit": %s,' % json.dumps(item['unit'])
|
||||
hits = [k for k, l in enumerate(lines) if l.strip() == fn_pat and lines[k - 1].strip() == unit_pat]
|
||||
if len(hits) != 1:
|
||||
sys.exit('ABORT: %d entry matches for %s' % (len(hits), key))
|
||||
k = hits[0]
|
||||
cur = item['measurements']
|
||||
end = k
|
||||
depth = 1 # entry '{' opened on line k-2
|
||||
for j in range(k, len(lines)):
|
||||
depth += lines[j].count('{') - lines[j].count('}')
|
||||
if depth <= 0:
|
||||
end = j
|
||||
break
|
||||
span = range(k, end + 1)
|
||||
b = next(j for j in span if lines[j].strip().startswith('"base":'))
|
||||
if lines[b].strip() == '"base": {':
|
||||
for j, field in ((b + 1, 'size'), (b + 2, 'relocation_count'), (b + 3, 'normalized_sha256')):
|
||||
m = re.match(r'^(\s*"%s": )(.*?)(,?)$' % field, lines[j])
|
||||
if not m:
|
||||
sys.exit('ABORT: layout of %s near line %d' % (key, j + 1))
|
||||
lines[j] = m.group(1) + json.dumps(cur['base'][field]) + m.group(3)
|
||||
else:
|
||||
m = re.match(r'^(\s*"base": )\{.*\}(,?)$', lines[b])
|
||||
if not m:
|
||||
sys.exit('ABORT: compact layout of %s near line %d' % (key, b + 1))
|
||||
lines[b] = m.group(1) + '{ "size": %d, "relocation_count": %d, "normalized_sha256": %s }' % (
|
||||
cur['base']['size'], cur['base']['relocation_count'], json.dumps(cur['base']['normalized_sha256'])) + m.group(2)
|
||||
o = next(j for j in span if lines[j].strip().startswith('"objdiff_percent":'))
|
||||
m = re.match(r'^(\s*"objdiff_percent": )(.*?)(,?)$', lines[o])
|
||||
lines[o] = m.group(1) + json.dumps(cur['objdiff_percent']) + m.group(3)
|
||||
if note:
|
||||
e = next(j for j in span if lines[j].strip().startswith('"evidence":'))
|
||||
m = re.match(r'^(\s*"evidence": ")(.*)(",?)$', lines[e])
|
||||
lines[e] = m.group(1) + m.group(2) + ' ' + json.dumps(note)[1:-1] + m.group(3)
|
||||
done.append(key)
|
||||
print('rebaselined', key, cur['base'], cur['objdiff_percent'])
|
||||
missing = wanted - set(done)
|
||||
if missing:
|
||||
print('named but not stale (unchanged):', sorted(missing))
|
||||
path.write_bytes(nl.join(lines).encode('utf-8'))
|
||||
json.loads(path.read_text(encoding='utf-8'))
|
||||
for inv in res['invalid']:
|
||||
print('invalid (left alone):', inv)
|
||||
@@ -0,0 +1,56 @@
|
||||
"""In-place config/symbols.json line surgery (never re-serialises; preserves order and CRLF).
|
||||
|
||||
python scratch/campaign/sym_edit.py ops.json [--dry]
|
||||
|
||||
ops.json: list of operations, each keyed by the exact file_offset and current name:
|
||||
{"op": "static", "file_offset": 75280, "name": "_foo"} -> add "static": true
|
||||
{"op": "unstatic", "file_offset": 518208, "name": "_foo"} -> remove "static": true
|
||||
{"op": "rename", "file_offset": 2600880, "name": "_old", "new": "_new"}
|
||||
{"op": "insert_after", "file_offset": 2600880, "name": "_anchor", "line": "{ ... },"}
|
||||
Each op must match exactly one line (file_offset AND name) or the script aborts.
|
||||
"""
|
||||
import json
|
||||
import re
|
||||
import sys
|
||||
|
||||
ops = json.load(open(sys.argv[1]))
|
||||
dry = '--dry' in sys.argv
|
||||
p = 'config/symbols.json'
|
||||
raw = open(p, 'rb').read().decode('utf-8')
|
||||
crlf = '\r\n' in raw
|
||||
lines = raw.split('\r\n' if crlf else '\n')
|
||||
|
||||
|
||||
def find(off, name):
|
||||
pat = re.compile(r'"file_offset": %d, "flags": \d+, "name": "%s"' % (off, re.escape(name)))
|
||||
hits = [i for i, l in enumerate(lines) if pat.search(l)]
|
||||
if len(hits) != 1:
|
||||
sys.exit('ABORT: %d matches for %s @%d' % (len(hits), name, off))
|
||||
return hits[0]
|
||||
|
||||
|
||||
inserts = []
|
||||
for op in ops:
|
||||
i = find(op['file_offset'], op['name'])
|
||||
line = lines[i]
|
||||
if op['op'] == 'static':
|
||||
if '"static": true' in line:
|
||||
print('already static', op['name'])
|
||||
continue
|
||||
lines[i] = re.sub(r'\s*\}(,?)\s*$', r', "static": true }\1', line)
|
||||
elif op['op'] == 'unstatic':
|
||||
lines[i] = line.replace(', "static": true', '')
|
||||
elif op['op'] == 'rename':
|
||||
lines[i] = line.replace('"name": "%s"' % op['name'], '"name": "%s"' % op['new'])
|
||||
elif op['op'] == 'insert_after':
|
||||
lines.insert(i + 1, op['line'])
|
||||
print('inserted after %s: %s' % (op['name'], op['line']))
|
||||
continue
|
||||
else:
|
||||
sys.exit('unknown op ' + op['op'])
|
||||
print('%-12s %s -> %s' % (op['op'], line.strip(), lines[i].strip()))
|
||||
for i, l in sorted(inserts, reverse=True):
|
||||
lines.insert(i + 1, l)
|
||||
print('inserted after line %d: %s' % (i + 1, l))
|
||||
if not dry:
|
||||
open(p, 'wb').write(('\r\n' if crlf else '\n').join(lines).encode('utf-8'))
|
||||
@@ -0,0 +1,68 @@
|
||||
"""Derive sym_edit.py ops from a worker's edited symbols.json copy vs HEAD's config/symbols.json.
|
||||
|
||||
python scratch/campaign/sym_ops_from_copy.py <worker_symbols.json> <out_ops.json> [<base-ref>]
|
||||
The worker copy is diffed against <base-ref>:config/symbols.json (default HEAD); use the commit the
|
||||
worker started from so later integrated edits are not read as reversions.
|
||||
Handles in-place static add/remove, renames at the same file_offset, and inserted lines.
|
||||
"""
|
||||
import difflib
|
||||
import json
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
base = subprocess.run(['git', 'show', (sys.argv[3] if len(sys.argv) > 3 else 'HEAD') + ':config/symbols.json'], capture_output=True, text=True, encoding='utf-8').stdout
|
||||
base = base.replace('\r\n', '\n').split('\n')
|
||||
new = open(sys.argv[1], 'rb').read().decode('utf-8').replace('\r\n', '\n').split('\n')
|
||||
R = re.compile(r'"file_offset": (\d+), "flags": \d+, "name": "([^"]+)"')
|
||||
ops = []
|
||||
sm = difflib.SequenceMatcher(a=base, b=new, autojunk=False)
|
||||
for tag, i1, i2, j1, j2 in sm.get_opcodes():
|
||||
if tag == 'equal':
|
||||
continue
|
||||
if tag == 'replace' and (i2 - i1) == (j2 - j1):
|
||||
for a, b in zip(base[i1:i2], new[j1:j2]):
|
||||
ma, mb = R.search(a), R.search(b)
|
||||
assert ma and mb and ma.group(1) == mb.group(1), (a, b)
|
||||
off, name = int(ma.group(1)), ma.group(2)
|
||||
if ma.group(2) != mb.group(2):
|
||||
ops.append({'op': 'rename', 'file_offset': off, 'name': name, 'new': mb.group(2)})
|
||||
name = mb.group(2)
|
||||
sa, sb = '"static": true' in a, '"static": true' in b
|
||||
if sb and not sa:
|
||||
ops.append({'op': 'static', 'file_offset': off, 'name': name})
|
||||
elif sa and not sb:
|
||||
ops.append({'op': 'unstatic', 'file_offset': off, 'name': name})
|
||||
elif tag == 'insert':
|
||||
anchor = R.search(base[i1 - 1])
|
||||
prev = (int(anchor.group(1)), anchor.group(2))
|
||||
# anchor must reference the (possibly renamed) previous line in new
|
||||
pm = R.search(new[j1 - 1])
|
||||
for k, l in enumerate(new[j1:j2]):
|
||||
ops.append({'op': 'insert_after', 'file_offset': int(pm.group(1)), 'name': pm.group(2), 'line': l.strip()})
|
||||
pm = R.search(l)
|
||||
elif tag == 'replace':
|
||||
# mixed: pair the common prefix, insert the rest
|
||||
n = min(i2 - i1, j2 - j1)
|
||||
for a, b in zip(base[i1:i1 + n], new[j1:j1 + n]):
|
||||
ma, mb = R.search(a), R.search(b)
|
||||
assert ma and mb and ma.group(1) == mb.group(1), (a, b)
|
||||
off, name = int(ma.group(1)), ma.group(2)
|
||||
if ma.group(2) != mb.group(2):
|
||||
ops.append({'op': 'rename', 'file_offset': off, 'name': name, 'new': mb.group(2)})
|
||||
name = mb.group(2)
|
||||
if '"static": true' in b and '"static": true' not in a:
|
||||
ops.append({'op': 'static', 'file_offset': off, 'name': name})
|
||||
elif '"static": true' in a and '"static": true' not in b:
|
||||
ops.append({'op': 'unstatic', 'file_offset': off, 'name': name})
|
||||
assert (i2 - i1) <= (j2 - j1), 'deletions unsupported'
|
||||
pm = R.search(new[j1 + n - 1])
|
||||
for l in new[j1 + n:j2]:
|
||||
ops.append({'op': 'insert_after', 'file_offset': int(pm.group(1)), 'name': pm.group(2), 'line': l.strip()})
|
||||
pm = R.search(l)
|
||||
else:
|
||||
raise SystemExit('unsupported opcode %s at %d' % (tag, i1))
|
||||
json.dump(ops, open(sys.argv[2], 'w'), indent=1)
|
||||
print(len(ops), 'ops')
|
||||
for o in ops:
|
||||
print(o)
|
||||
@@ -0,0 +1,158 @@
|
||||
# REVIEW source/game/game_engine
|
||||
|
||||
approve: False
|
||||
|
||||
## per_object
|
||||
[
|
||||
{
|
||||
"unit": "source/game/game_engine (whole-object admission)",
|
||||
"approve": false,
|
||||
"issues": "The motion-sensor copy is still owner-gated. The default in-loop goal alias is contradicted by the /Od 0x5a20e0 frame and is load-bearing (lab s4 is RESIDUAL). The F07 view copy is also load-bearing, so it fails the s.2 byte-inert strip test. Review3's open blocker is therefore still unresolved, and admission needs the owner to pick the alias or F07."
|
||||
},
|
||||
{
|
||||
"unit": "worker packet F01+F02+F03a+F03b+F04 (as submitted)",
|
||||
"approve": false,
|
||||
"issues": "F01 keeps get_rating `long inverse` on a refuted 'January ABI' claim: `boolean inverse` (HCEX, /Od movzx byte) is byte-identical, per lab s1, and `long` adds the new C4244. There are also three byte-inert /Od-order nits: render_nav_points' bare block, did_player_win_default's declaration order, and the flag name should be HCEX `_disable_dynamic_light_bit`. Every other claim reproduces: 180/180, sweep 446 SAME plus game_engine, audit/surplus/pdb/provider_link PASS, objdiff equal, consumers equal."
|
||||
},
|
||||
{
|
||||
"unit": "reviewer-amended packet F01R+F02+F03aR+F03b+F04 (zero-credit house-clean)",
|
||||
"approve": true,
|
||||
"issues": "Verified: git apply --check is clean on the tree; the independent shadow equals amended/; 180/180 EXACT; 0 of 302 sections changed vs build/base and vs the worker's final; object_audit PASS with identical text; 11/11 surplus identical; 0 PDB storage disagreements; provider_link PASS; objdiff 3.3.1 unchanged. The full 447-TU sweep gives 446 SAME plus game_engine (only the always_invis order and the _global_goal+0x400 spelling, both EXACT). /W3 adds no new warnings. It earns no credit on its own; the object is admitted only after the owner's motion-sensor ruling."
|
||||
}
|
||||
]
|
||||
|
||||
## checks
|
||||
Everything was run independently, and everything I wrote is under scratch/w/review4_game_engine/. The tree was clean before and after.
|
||||
|
||||
1. Setup and inputs:
|
||||
- Tree clean at 16542e46.
|
||||
- Read: WORKER_BRIEF sections 0-9, house rules, the lane log's held table, the worker LEDGER F0-F16 and the review3 REVIEW.
|
||||
- No parks or admission rejections exist for this object.
|
||||
2. Patch application:
|
||||
- `git apply --check` on the real tree is clean for F01, F02, F03a, F03b and F04, each alone and all together.
|
||||
- F05h and F06 are also clean on the tree. F05c and F07 are clean on top of F01 (and on top of the amended F01R).
|
||||
3. Independent shadow:
|
||||
- Built as `git -c core.autocrlf=false archive HEAD source`, then the patches via `git apply` with GIT_CEILING_DIRECTORIES, then converted to CRLF.
|
||||
- It equals the worker's final/ for all 10 files.
|
||||
- The HEAD shadow equals the working tree for 989/989 files.
|
||||
4. Compile harness (rc.py):
|
||||
- Production cflags from build.ninja, cwd set to the shadow root.
|
||||
- gatecmp.py checks gate rows vs build/split and section_infos_equal vs build/base.
|
||||
- Worker final: 180/180 EXACT, 0 of 302 sections changed. Control: 180/180, 0 changed.
|
||||
- gate.py --source can't compile this packet, because its /I list points at the tree's unpatched headers.
|
||||
5. Full sweep (sweep.py):
|
||||
- Covers all 447 build/base source TUs. Compares raw bytes, relocations by name and the full symbol table, excluding .debug$S, with $L and $label$N numbering canonicalised.
|
||||
- Control: 447/447 match build/base.
|
||||
- Worker packet: 446 SAME. game_engine differs only in:
|
||||
- the position of _game_engine_update_player_always_invis;
|
||||
- the `_global_goal+0x400` spelling of `_global_variant+0` in motion_sensor_positions and render_nav_points. Both functions are strict EXACT.
|
||||
6. /W3 /Zs census over 447 TUs (w3.py, path-normalised):
|
||||
- game_engine: C4013 console_printf gone, two C4244 long->short gone, +1 C4244 long->boolean.
|
||||
- hud_nav_points: only the pre-existing C4013 moves.
|
||||
7. Consumer census (/showIncludes over 447 TUs): identical to CONSUMERS.txt.
|
||||
- game_engine.h 37, player_control.h 21, hud_messaging.h 8, sound_classes.h 6.
|
||||
- New headers 1, 2, 1, 1. players.h 71.
|
||||
8. Admission audit on my compiled obj:
|
||||
- object_audit PASS; its text is identical to production's.
|
||||
- surplus_identity (pointed at the candidate): 11 COMDATs, 0 differ.
|
||||
- pdb_storage (candidate): 0 disagreements.
|
||||
- provider_link: PASS.
|
||||
- objdiff-cli 3.3.1 mini project: prod, final and amended all score 27922/32397 code, 173/180 functions and 3792/3792 data, with 0 per-function deltas.
|
||||
9. /Od re-dumps and readouts:
|
||||
- 0x5a20e0: the motion-sensor frame is count, player and goal_index only, with one 8-byte copy.
|
||||
- 0x5b6920: the dead local_player_count is attested.
|
||||
- 0x5b6370: get_rating reads `inverse` with movzx byte.
|
||||
- 0x59bb90: did_player_win_default's /Od declaration order.
|
||||
- 0x5ad780: render_nav_points declares goal_index before head_position.
|
||||
- 0x5a0b90: man_out.
|
||||
- 0x5aea50 -> 0x5af860 -> 0x5ae9c0: update, always_invis, test_trait.
|
||||
- /Od builders 0x5916e0, 0x591b30, 0x593e50, 0x596e30, 0x598820, 0x59a260: one SET_FLAG per bit, but the bit order and meanings differ from January.
|
||||
10. HCEX enums: flag names (_game_engine_disable_dynamic_light_bit etc.), universal variant flags 0-5, game_engine_weapons 0-13, goal_radar.
|
||||
11. Lab strip tests:
|
||||
- s1: get_rating `boolean inverse` is EXACT.
|
||||
- s2: get_rating with declaration and initialisation combined is EXACT.
|
||||
- s3: game_engine_update without the bare block is RESIDUAL.
|
||||
- s4: motion-sensor component copies without the alias are RESIDUAL.
|
||||
- s5: did_player_win_default in the /Od declaration order is EXACT.
|
||||
- s6: render_nav_points without the bare block is EXACT.
|
||||
12. Scans: bare blocks, prototypes, externs, placeholder names and `float` in the final file.
|
||||
13. Amended packet (F01R + F03aR), re-verified end to end:
|
||||
- Applies cleanly to the tree.
|
||||
- Independent shadow equals amended/.
|
||||
- 180/180; 0 of 302 sections changed vs build/base and vs the worker's final.
|
||||
- Audit, surplus, pdb and provider_link all pass.
|
||||
- objdiff unchanged.
|
||||
- Full sweep: 446 SAME plus game_engine (same two notes).
|
||||
- /W3: no new warnings.
|
||||
- Optional F05h, F05c, F06 and F07 on top: 446 SAME plus game_engine, 180/180.
|
||||
|
||||
## issues
|
||||
APPROVE=FALSE: the object cannot be self-admitted.
|
||||
|
||||
**BLOCKER (owner ruling needed; I cannot fix it): the motion-sensor copy in game_engine_player_get_custom_motion_sensor_positions.**
|
||||
- Review3 listed this construct as "still blocking OBJECT_COMPLETE". It is still unresolved; the worker itself writes "OWNER picks".
|
||||
- The default packet keeps the in-loop `struct netgame_goal *goal = &global_goal[goal_index];` alias.
|
||||
- /Od 0x5a20e0 contradicts it: the frame has only count, player and goal_index, and the copy is one 8-byte struct copy.
|
||||
- The alias is load-bearing: lab s4 (direct component copies) is RESIDUAL.
|
||||
- That makes it a non-/Od-attested, load-bearing local, which is owner-gated (brief s.7).
|
||||
- The alternative, F07's /Od-attested `*(real_point2d *)&...position` view copy, is also load-bearing. It fails the byte-inert strip test that brief s.2 requires for a new 3D-to-2D view cast, so it is owner-gated too.
|
||||
- An object whose completion depends on an owner pick is not an OBJECT_COMPLETE candidate.
|
||||
|
||||
**DEFECT (fixed in my amendment): refuted evidence claim in the worker's F5.**
|
||||
- The worker kept `long inverse` in postgame_statistic_get_rating, calling it "January's ABI, proven by the dword read" and saying `boolean inverse` is residual.
|
||||
- Lab s1 changed only the get_rating prototype and definition to `boolean inverse`. Result: 180/180 EXACT and 0 of 302 sections changed. VC7 forwards a boolean parameter with the same dword load.
|
||||
- HCEX (`unsigned char inverse`) and /Od 0x5b6370 (`movzx eax, byte ptr [ebp+0x10]`) both attest boolean.
|
||||
- So `long` is not byte-required, contradicts first-party evidence, and is the only source of the packet's new C4244 long->boolean warning.
|
||||
|
||||
**NITS (fixed, all byte-inert and verified):**
|
||||
- render_nav_points:
|
||||
- HEAD's bare `{ long goal_index; for ...}` block after unit_get_head_position contradicts /Od 0x5ad780's declaration order, where goal_index (-0x10) comes before head_position (-0x24). This is law (d).
|
||||
- Lab s6 (no block; goal_index declared after player) is EXACT, so the block is decoration.
|
||||
- did_player_win_default declares player before winning_team_index. /Od 0x59bb90 has winning_team_index first (slots -0x14 then -0x18). Lab s5 is EXACT.
|
||||
- The flag name `_game_engine_disable_dynamic_lighting_bit` should be HCEX's verbatim `_game_engine_disable_dynamic_light_bit`. The rename is count-neutral.
|
||||
|
||||
**Verified acceptable (disclosed):**
|
||||
- game_engine_update's three disjoint bare-block iterators.
|
||||
- They are load-bearing: lab s3 without the block is RESIDUAL.
|
||||
- The escape law (e) justifies them: the iterators' addresses reach data_iterator_new/object_iterator_new.
|
||||
- No /Od attestation is possible, because the 2020 build moved the postgame loops out of update. The /Od declaration order is consistent.
|
||||
- The /Od-attested dead local_player_count.
|
||||
- The strip-inert, /Od-attested `= 0` initialisations.
|
||||
- The TU-local flag bits 3, 4 and 5, which avoid breaking the header's name-count canaries.
|
||||
- The focused headers, following the matrix_math.h precedent.
|
||||
- The weapon-set-10 name `_no_grenades`, based on January's behaviour (HCEX has 13 = no_grenades).
|
||||
- The worker's sweep count was 446 TUs; build.ninja has 447. My 447-TU sweep gives the same result.
|
||||
|
||||
**Advisory, zero-credit follow-ups (these predate the packet and do not block it):**
|
||||
- Scalar-only bare blocks not audited against /Od:
|
||||
- post_rasterize_post_game's entry_index block;
|
||||
- update_player_no_shield's player block;
|
||||
- update_teleporter's message and angle blocks;
|
||||
- postspawn's grenade block.
|
||||
- The goal_radar 0/1/2 literals, where HCEX has `enum goal_radar`.
|
||||
- The `parameter0`/`parameter1` placeholder names in game_engine_playlist_next. Its TU prototype also duplicates game_engine_playlist.h.
|
||||
- The 2020 byte local `inverse` in /Od select_players_to_display is not present in the packet.
|
||||
- Other sites still mix `if (game_engine)` with /Od's `game_engine_running()`.
|
||||
- game_engine_globals, global_stage and timeout_for_endgame_sound are still extern.
|
||||
|
||||
**PRODUCTION CHANGES (zero credit; landable as a verified house-clean packet; admission waits on the owner's alias-vs-F07 pick). Land these together:**
|
||||
- C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\review4_game_engine\patches\F01R_game_engine_c.patch. It replaces F01; the full file is amended\source\game\game_engine.c.
|
||||
- The worker's F02_new_focused_headers.patch, unchanged.
|
||||
- C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\review4_game_engine\patches\F03aR_shared_header_game_engine_h.patch. It replaces F03a; the full file is amended\source\game\game_engine.h.
|
||||
- It is a shared header with 37 consumer TUs, the same list as CONSUMERS.txt:
|
||||
- ai/encounters, camera/dead_camera;
|
||||
- game/{game, game_engine, game_engine_ctf, game_engine_king, game_engine_list, game_engine_oddball, game_engine_race, game_engine_slayer, game_globals, game_statistics, players};
|
||||
- interface/{hud, hud_messaging, hud_unit, interface, motion_sensor, player_ui, ui_widget};
|
||||
- items/{items, projectiles, weapons};
|
||||
- main/main, math/random_math;
|
||||
- networking/{network_client_manager, network_client_message_handler, network_game_manager, network_server_manager, network_server_message_handler};
|
||||
- objects/{damage, object_lights, objects};
|
||||
- render/render, `saved games/playlist_profile`;
|
||||
- units/{bipeds, units}.
|
||||
- The worker's F03b_shared_header_prototypes.patch, unchanged. Consumers: player_control.h 21, hud_messaging.h 8 (includes `saved games/game_state`), sound_classes.h 6.
|
||||
- The worker's F04_hud_nav_points_owner_include.patch, unchanged.
|
||||
- The worker's F02/F03b/F04 patches are in C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\game_engine_finish\patches\.
|
||||
- Optional F05h/F05c/F06/F07 still apply on top and sweep clean. F07 is the owner's motion-sensor choice.
|
||||
- config/symbols.json: no change.
|
||||
|
||||
Evidence: C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\review4_game_engine\REVIEW.md and LEDGER.md (R0-R11), plus lab\s1..s6.
|
||||
@@ -0,0 +1,120 @@
|
||||
# REVIEW source/interface/hud_draw
|
||||
|
||||
approve: False
|
||||
|
||||
## per_object
|
||||
[
|
||||
{
|
||||
"unit": "source/interface/hud_draw (P2 hud_draw.c)",
|
||||
"approve": true,
|
||||
"issues": "The content is correct.\n- Gate rows are unchanged: 22 EXACT / 1 UNWRITTEN.\n- The only raw difference is `_check_stack_buffer` changing from NODUP to ANY (checksum unchanged), plus an unscored order swap.\n- The object_audit text is identical.\nLand it only inside the amended atomic set. The object is still not admissible because `_fast_ftol_C` is unwritten."
|
||||
},
|
||||
{
|
||||
"unit": "source/interface/hud_draw.h (P1 shared header)",
|
||||
"approve": true,
|
||||
"issues": "The content is correct: a non-static __inline that matches PUBLIC cachebeta, a macro attested by the shared line literals, and an enum moved out of the TUs.\n- It cannot land with P2 alone. HEAD hud_unit.c then fails to compile (C2365/C2086), models loses an exact function unless P7 lands, and hud_weapon drifts unless P5 lands.\n- There are 23 consumers, and I verified the list independently."
|
||||
},
|
||||
{
|
||||
"unit": "source/interface/hud_unit (P3 or 01RS)",
|
||||
"approve": true,
|
||||
"issues": "Required by P1 for compilation.\n- P3 alone gives 22/22 against the production split, with one new ANY COMDAT from exact callers.\n- 01RS is covered by the hud_unit review and also needs patches 02/03/04R."
|
||||
},
|
||||
{
|
||||
"unit": "source/interface/hud_weapon (P5)",
|
||||
"approve": true,
|
||||
"issues": "Required by P1: it keeps `_render_weapon_hud` byte-stable.\nThe new ANY COMDAT has exact callers (`render_grenade_hud`, `hud_update_weapon`), is identical to January's copy, and pair-links in both orders."
|
||||
},
|
||||
{
|
||||
"unit": "source/rasterizer/xbox/rasterizer_xbox_models (P7)",
|
||||
"approve": true,
|
||||
"issues": "Required by P1; disclose to the owner.\n- The include is dead and removing it alone is byte-inert.\n- It is load-bearing only as declared-name-count shielding against P1's inline. That is the class this lane has held for Layer 2 and main header_swap, while the 100K lane landed duplicate removal."
|
||||
},
|
||||
{
|
||||
"unit": "source/interface/hud_nav_points (P4)",
|
||||
"approve": true,
|
||||
"issues": "Optional: byte-inert without it. Its COMDAT has the exact caller `hud_update_nav_point_local_player`."
|
||||
},
|
||||
{
|
||||
"unit": "source/interface/motion_sensor (P6)",
|
||||
"approve": false,
|
||||
"issues": "Exclude. It is not needed for bytes (0 differences with P1 alone). It newly emits `_check_stack_buffer` in motion_sensor.obj, and all three callers are residual and parked, which breaks law (i) (P1 class)."
|
||||
}
|
||||
]
|
||||
|
||||
## checks
|
||||
All checks used my own tools in scratch/w/review4_hud_draw/ (sweep.py, rawcoff.py, warn.py, plink.py, secorder.py). The tree was 16542e46 and stayed clean throughout.
|
||||
|
||||
(1) Patch application:
|
||||
- `git apply --check` is clean for each patch alone.
|
||||
- It is also clean for P1+P2 and for the sets {P1,P2,P3,P5,P7}, {P1,P2,01RS,P5,P7} and {P1,P2,01RS,P4,P5,P7}.
|
||||
- Replaying the patches with `patch` onto `git show HEAD:` copies reproduces the worker's candidate hud_draw.h and hud_draw.c exactly.
|
||||
|
||||
(2) Consumer list:
|
||||
- My own grep (`-rlE`, .c/.h/.cpp/.inl, safe for paths with spaces) finds the same 23 TUs.
|
||||
- No header includes hud_draw.h, there are no .c-in-.c includes, and there are no alternate include spellings.
|
||||
|
||||
(3) Harness control: each TU copy points its include at a verbatim HEAD header. All 23 objects are raw-identical to production, including bytes, relocations by target, COMDAT selection and checksum, symbol table and section order.
|
||||
|
||||
(4) Candidate sweep (P1 P2 01RS P4 P5 P6 P7):
|
||||
- gate.py --source --all rows are identical to production for all 23 consumers. The one exception is hud_unit, which shows 20 exact + 2 unwritten because the 01RS renames need symbols.json patch 02.
|
||||
- hud_draw is 22 EXACT / 1 UNWRITTEN (_fast_ftol_C), the same as production.
|
||||
- The 18 non-sentinel consumers show 0 differences, provided P7 is applied.
|
||||
- hud_draw differs only in `_check_stack_buffer` selection, NODUP to ANY. Its checksum 0x4957c551 is unchanged, and the section order changes (below).
|
||||
|
||||
(5) Header-only probes (P1 against HEAD TUs):
|
||||
- hud_draw fails to compile (C2365/C2086/C2084).
|
||||
- hud_unit fails to compile (C2365/C2086 redefinition of STACK_BUFFER_LENGTH/FILL at hud_unit.c:118-119).
|
||||
- In models, `__rasterizer_model_transparent_geometry_submit` goes from EXACT to residual (12/2 becomes 11/3).
|
||||
- The bytes of `_render_weapon_hud` in hud_weapon drift; it is residual and unparked.
|
||||
- nav and motion_sensor show 0 differences.
|
||||
|
||||
(6) Minimal set {P1,P2,P3,P5,P7}:
|
||||
- gate summaries equal production for all 23, and hud_unit is 22/22 against the production split.
|
||||
- Only hud_unit and hud_weapon gain the ANY COMDAT, and both have exact callers.
|
||||
- The other 20 objects are raw-identical.
|
||||
|
||||
(7) hud_draw admission tools:
|
||||
- object_audit text is identical for production and candidate. It carries the same pre-existing FAIL(2) for the unwritten `_fast_ftol_C`.
|
||||
- Data sections are identical (tinfo --data), apart from `.debug$S`, which holds the gate's temp-file path.
|
||||
- `/W3 /Zs` warning multisets are identical for hud_draw, hud_unit, nav, weapon, motion_sensor and models.
|
||||
- fake_match_scan reports the same 2 pre-existing leads, from `get_return_eip`.
|
||||
|
||||
(8) Surplus identity: `_check_stack_buffer` in all five candidate objects is section_infos_equal to January hud_draw's copy (48 B, 0 relocations, sha c7049c31...).
|
||||
|
||||
(9) Pair links (the same Link.Exe command as provider_link.py):
|
||||
- The candidate hud_draw passes with each emitter in both orders, and with all five together.
|
||||
- Control: production hud_draw (NODUP) gives LNK2005 in both orders, so the check discriminates.
|
||||
- The minimal set also passes.
|
||||
|
||||
(10) Evidence:
|
||||
- `_check_stack_buffer` and `_get_return_eip` are PUBLIC in cachebeta.
|
||||
- HCEX.pdb bytes contain no sentinel names, and the /Od build has no "corrupt stack" or "corrupt return" strings.
|
||||
- The Sept-2001 atlas marks get_return_eip, fast_ftol_C, real_argb, real_rgb and real_alpha_intensity as 'i hud_draw.obj', and does not list check_stack_buffer.
|
||||
- models uses none of the 25 hud_draw.h names. January's models references only real_argb/rgb, which come from bitmap_color_conversion.h.
|
||||
|
||||
(11) Section-order table: January vs production vs candidate.
|
||||
|
||||
(12) tools/regression_gate.py compares the comdat_selection of accepted functions, which matters for issue 3.
|
||||
|
||||
## issues
|
||||
APPROVE=FALSE AS SUBMITTED. Land P1/P2 unchanged; only their packaging needs fixing. I verified an amended atomic landing set end to end.
|
||||
|
||||
1. **The landing condition is wrong.** "P1 and P2 must land together (+P7)" does not build.
|
||||
- With P1 applied, HEAD hud_unit.c fails to compile: C2365/C2086 for STACK_BUFFER_LENGTH/FILL at hud_unit.c:118-119. So P3 or 01RS must land in the same commit.
|
||||
- P5 is also required; without it the bytes of hud_weapon's unparked residual `_render_weapon_hud` drift.
|
||||
- P7 is also required; without it models loses the exact `__rasterizer_model_transparent_geometry_submit` (1,296 B).
|
||||
|
||||
2. **The worker's own "full atomic set" includes P6.** P6 is not needed for bytes: motion_sensor shows 0 differences with P1 alone. It also breaks law (i): it newly emits `_check_stack_buffer` in motion_sensor.obj, and all three callers are residual and parked. Exclude it. P4 is optional; it is byte-inert without it and its caller `hud_update_nav_point_local_player` is exact.
|
||||
- **Amended set:** P1 + P2 + (P3 or 01RS) + P5 + P7, with P4 optional and P6 excluded.
|
||||
- Byte-identical copies are in C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\review4_hud_draw\patches\ with SHA256SUMS.txt (same hashes as the worker's).
|
||||
- Verified: git apply --check clean; all 23 gate summaries equal production; 20 objects raw-identical; hud_unit and hud_weapon gain only the new ANY COMDAT, identical to January's; pair links pass in both orders; warnings unchanged.
|
||||
|
||||
3. **Disclosures for the owner and integrator (not defects in P1/P2 content).**
|
||||
- (a) P7 is load-bearing only as declared-name-count shielding for P1, whose inline costs about 9 name units in models. The include is genuinely dead (635bd83d origin; removing it alone is byte- and warning-inert). But this lane held the Layer-2 prototype move and the main header_swap as count compensation, while the 100K lane landed duplicate removal. The ruling request must state P7's role.
|
||||
- (b) hud_draw's January-exact `_check_stack_buffer` changes selection from NODUP to ANY. gate, object_audit and objdiff don't see this, but tools/regression_gate.py would report "accepted function evidence changed". Its only adjudication recipe is xdk-stock-d3dinline. This is the same change class as the Layer 1 provider repairs.
|
||||
- (c) Emission order (unscored): the candidate emits `_check_stack_buffer` before `_get_return_eip`, the reverse of January's image. Production's hud_draw order already diverges from January's throughout; for example, January has get_sprite_clip_rect 3rd and we have it 15th, and the landed ARGB header inlines are 9th-10th in January and 3rd-4th in ours. So this is not evidence against P1.
|
||||
- (d) The header location (hud_draw.h) and the macro name `match_assert_stack_frame` are inferred and descriptive, not first-party. Neither the /Od build nor HCEX has the sentinel.
|
||||
- (e) hud_draw itself stays non-admissible and gets zero credit: `_fast_ftol_C` is unwritten and the `_fast_ftol` rejection stands.
|
||||
- (f) After applying, re-sweep all 23 consumers and the parks on the live tree, together with other wave-4 header packets.
|
||||
|
||||
Details are in C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\review4_hud_draw\REVIEW.md and LEDGER.md.
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
# REVIEW source/interface/hud_nav_points
|
||||
|
||||
approve: True
|
||||
|
||||
## per_object
|
||||
[
|
||||
{
|
||||
"unit": "source/interface/hud_nav_points",
|
||||
"approve": true,
|
||||
"issues": "Approve P4 only atomically with P1+P2 (+P3/01RS, P5, P6, P7). Byte-inert apart from the new SELECT_ANY _check_stack_buffer, which is identical to January's hud_draw copy and emitted by the strictly exact _hud_update_nav_point_local_player. Park sha unchanged. Zero credit; the object is NOT admission-ready: besides the park it has pre-existing law (g) blockers (consumer-local prototypes for objects.h/game_engine.h/units.h functions, TU-local opaque-span struct views hud_globals_definition and hud_nav_object_datum, float z_offset/vertical_offset)."
|
||||
}
|
||||
]
|
||||
|
||||
## checks
|
||||
All checks were independent; notes and evidence are in C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\review4_hud_nav_points\ (LEDGER.md, REVIEW.md). Tree 16542e46, clean before and after.
|
||||
(1) git apply --check on 16542e46: P4 alone, P1 and P2 each clean; the full set P1+P2+01RS+P4+P5+P6+P7 is clean.
|
||||
(2) Rebuilt the candidate from `git show HEAD` blobs plus `patch -p1` P1/P2/P4. The text equals the worker's cand/interface/{hud_nav_points.c, hud_draw.h, hud_draw.c}.
|
||||
(3) Harness control: the production TU with its include redirected to a verbatim header copy shows 0 non-debug differences.
|
||||
(4) gate.py --all on the candidate: 31 EXACT / 1 residual (_custom_render_nav_point), the same rows as production.
|
||||
(5) Own strict comparer (fullcmp.py: raw bytes, relocs, flags, COMDAT selection, every symbol including UNDEF), production vs candidate: the only difference is a new _check_stack_buffer (.text 48 B, SELECT_ANY, external). The worker's h2_out object is identical to mine.
|
||||
(6) Park: the normalized sha of _custom_render_nav_point is ad77c226..., equal to the parked.json base. The reloc-masked diff against January is still only +0x58a..+0x591. The inlined sentinel tail (+0x5bb to the end) is byte-identical to January.
|
||||
(7) The new COMDAT is section_infos_equal to January's build/split hud_draw _check_stack_buffer (48 B, 0 relocs, c7049c31).
|
||||
(8) object_audit: the production and candidate reports differ only by `+.text _check_stack_buffer 48`. All 46 January symbols match. FAIL(1) is the pre-existing park.
|
||||
(9) surplus_identity (slug copy that takes a candidate obj): 5 candidate-only code COMDATs, all IDENTICAL to January's selected copies.
|
||||
(10) provider_link: against the production hud_draw it fails with LNK2005 (the expected control). Against HEAD+P1+P2 hud_draw.obj (my own compile: 22/0/1 rows, only change NODUP->ANY) all 21 surplus pass. A 5-object packet link (draw, nav, and the worker's hud_unit/hud_weapon/motion_sensor) in 3 orders gives 0 LNK2005/1169.
|
||||
(11) pdb_storage: 0 disagreements. _check_stack_buffer and _get_return_eip are PUBLIC in cachebeta.
|
||||
(12) /W3 /Zs: the warning multisets are identical.
|
||||
(13) fake_match_scan: 0 leads.
|
||||
(14) Data: every January data/rdata/bss section is ok, and raw-identical to production.
|
||||
(15) Law (i) lab: with the parked caller's macro use removed, the COMDAT is still emitted and identical, and _hud_update_nav_point_local_player stays EXACT. The emission therefore comes from a strictly exact caller.
|
||||
(16) STRIP TEST: a plain expansion with `short corrupt_index` at function top and no macro block is EXACT and whole-object identical. The block is byte-inert.
|
||||
(17) /Od build: odbuild str finds neither sentinel string (sanity: `file hud_nav_points.c` finds 5 fns), so no /Od frame can contradict the block. HCEX has no check_stack_buffer.
|
||||
(18) Consumer grep (recursive, all spellings, including spaced dirs): 23 TUs, matching the worker's list.
|
||||
(19) Own shadow sweep of all 23 consumers with the full packet: gate rows identical everywhere. With $Lnnnn label numbers normalised, raw bytes and relocs are identical in every section. The only changes are the expected _check_stack_buffer NODUP->ANY in hud_draw and +ANY in hud_nav_points, hud_unit, hud_weapon and motion_sensor. models with P7: 0 differences.
|
||||
(20) Atlas 7eacac85 read directly: `_get_return_eip i hud_draw.obj` at 0xcff20, with a 0x40 gap before _get_sprite_clip_rect.
|
||||
|
||||
## issues
|
||||
P4 is APPROVED only as part of the atomic packet P1+P2+(P3 or 01RS)+P4+P5+P6+P7. It cannot land alone: it needs P1's macro and STACK_BUFFER_LENGTH to compile, and it needs P2's ANY hud_draw copy to link (LNK2005 against the production NODUP copy, reproduced in both orders). If the owner rejects P1, or picks the P-A focused header, P4 is void and must be regenerated.
|
||||
|
||||
The verdict label overstates the result. P4 is zero-credit hygiene: it removes one law (g) blocker class, two hand-expanded check_stack_buffer copies with 4 invented labels/gotos. It does NOT make hud_nav_points admission-ready apart from the park. The lane log line "only _custom_render_nav_point remains" misses pre-existing law (g) blockers that P4 does not touch:
|
||||
- Consumer-local prototypes of other files' functions that have owner headers: object_get_bounding_sphere (objects.h), game_engine_render_nav_points (game_engine.h), unit_get_head_position (units.h). Also object_try_and_get_and_verify_type, game_engine_get_goal_position and `extern struct hud_globals_definition *hud_globals`.
|
||||
- TU-local struct views with opaque spans: `struct hud_globals_definition { messaging; waypoint; byte unknown1BC[0x294]; }`, `struct hud_nav_object_datum { byte unused[0xB6]; word damage_flags; }` and a local `struct scenario_cutscene_flag`.
|
||||
- `float` instead of `real`: hud_nav_point_datum.z_offset and several `float vertical_offset` parameters.
|
||||
These should be recorded as open hud_nav_points admission blockers.
|
||||
|
||||
Advisory for P1, not a P4 defect: the Sept-2001 atlas flags `_get_return_eip i hud_draw.obj` (a header inline in 2001), but P1 keeps it a plain naked hud_draw.c function. This is byte-inert and earns no credit. check_stack_buffer is absent from the Sept-2001 publics but PUBLIC in January, which is a storage change between the builds, not a contradiction.
|
||||
|
||||
The macro name match_assert_stack_frame is descriptive (Bungie's name is lost) and follows the match_assert_valid_*(file, line, ...) convention.
|
||||
|
||||
The integrator should still run a full build and sweep of all 23 hud_draw.h consumers and the parks on the live tree, together with any other wave-4 header packets. I found no defect in the P4 diff itself, so no amended patch is needed.
|
||||
@@ -0,0 +1,115 @@
|
||||
# REVIEW source/interface/hud_unit
|
||||
|
||||
approve: False
|
||||
|
||||
## per_object
|
||||
[
|
||||
{
|
||||
"unit": "source/interface/hud_unit",
|
||||
"approve": true,
|
||||
"issues": "Approve only with the amended packet (01RS, not 01RaltS). Results against the emulated split: 22/22 EXACT, audit PASS (30/30), surplus _fast_ftol and _check_stack_buffer IDENTICAL, provider link 12/12 in both orders with the packet's hud_draw.obj, strict emulation 22/22 + 152/152 data. Needs P1+P2+P7+02+03+04R in the same atomic set. 01RaltS keeps an /Od-contradicted invented goto: reject."
|
||||
},
|
||||
{
|
||||
"unit": "source/interface/hud_draw",
|
||||
"approve": true,
|
||||
"issues": "P2 is byte-identical on every section; the only changes are _check_stack_buffer NODUP->ANY and its emission order (now before _get_return_eip, while January's image has it after). The object is not being admitted; the order is an advisory for its own future admission."
|
||||
},
|
||||
{
|
||||
"unit": "source/interface/hud_nav_points",
|
||||
"approve": true,
|
||||
"issues": "P4 adds only the new ANY COMDAT (strictly exact caller: hud_update_nav_point_local_player); the parked custom_render_nav_point stays byte-identical. Optional hygiene: without P4 the object is byte-identical to production."
|
||||
},
|
||||
{
|
||||
"unit": "source/interface/hud_weapon",
|
||||
"approve": true,
|
||||
"issues": "P5 adds only the new ANY COMDAT (exact callers render_grenade_hud and hud_update_weapon). It keeps the unparked _render_weapon_hud residual byte-stable, which drifts under P1 alone, and removes the invented gotos from two EXACT functions."
|
||||
},
|
||||
{
|
||||
"unit": "source/interface/motion_sensor",
|
||||
"approve": false,
|
||||
"issues": "P6 newly emits _check_stack_buffer from three residual, parked callers only, which breaks owner ruling 20260921 #2 / law (i) (P1 class). Drop P6; motion_sensor is then byte-identical to production. Reopen when a sentinel caller is strict-exact or the owner admits the class."
|
||||
},
|
||||
{
|
||||
"unit": "source/rasterizer/xbox/rasterizer_xbox_models",
|
||||
"approve": true,
|
||||
"issues": "P7 removes a dead include; the object is RAW-IDENTICAL and warnings are unchanged. It is load-bearing only as count shielding against P1 (without it __rasterizer_model_transparent_geometry_submit goes EXACT to residual). Disclose this in the ruling request (precedent: duplicate-declaration removal)."
|
||||
}
|
||||
]
|
||||
|
||||
## checks
|
||||
All runs are my own, under C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\review4_hud_unit\. The tree was 16542e46 and git status was clean before and after.
|
||||
|
||||
(1) git apply --check on the current tree: all 12 patches are clean alone, as the full set, as the full alt set, and as the amended set.
|
||||
(2) Patch replay with patch -p1 onto `git show HEAD:` copies (tree/, tree_alt/). Every patched file equals the worker's candidate files; 01RS equals cand01R and 01RaltS equals cand01Ralt.
|
||||
(3) Consumer list from my own grep over source/ (all extensions, case-insensitive): 23 .c files, no header includes, no .c-includes-.c, no paths with spaces. The new names collide with nothing.
|
||||
(4) My own sweep harness (tools/sweep.py: redirected TU copies, gate.py --all --out) plus a strict raw COFF comparer (tools/rawcmp.py: section order, bytes, relocs by target name, COMDAT selection, full symbol table; only $L numbers normalised) and an owner-keyed comparer (tools/keycmp.py).
|
||||
- Control (verbatim header): 23/23 RAW-IDENTICAL to build/base.
|
||||
- Full packet: the 17 non-sentinel consumers and models are RAW-IDENTICAL.
|
||||
- nop7: models __rasterizer_model_transparent_geometry_submit goes EXACT to residual, so P7 is load-bearing.
|
||||
- hdronly: hud_weapon residual drift.
|
||||
- amend (drop P6): motion_sensor RAW-IDENTICAL.
|
||||
- min (drop P4+P6): hud_nav_points identical.
|
||||
- strict (P1,P2,01RS,P7 only): only unparked _render_weapon_hud bytes drift.
|
||||
- Sentinel objects: the only change is the new ANY _check_stack_buffer; parked bodies are byte-identical.
|
||||
- hud_draw: NODUP to ANY, plus a text-order swap.
|
||||
(5) csplit (build/tools/csplit.exe) into the slug. The control config equals build/split 833/833. The emulated config (4 in-place symbols.json edits, CRLF kept, byte-identical to the worker's copy) differs only in hud_unit.obj.
|
||||
(6) gate_split (gate.py rule plus storage) against split_emu: 01RS and 01RaltS each 22/22 EXACT, 0 storage mismatches.
|
||||
(7) object_audit (slug copy, SPLIT_ROOT=split_emu): PASS for both. 30 January-owned sections ok, 30 January symbols with 0 differences. Surplus: .drectve, 5 pooled strings, 5 __real, _fast_ftol, _check_stack_buffer.
|
||||
(8) surplus_identity (slug copy taking obj paths): hud_unit _fast_ftol is IDENTICAL to actor_combat and _check_stack_buffer to hud_draw. All surplus in nav/weapon/motion/hud_draw is IDENTICAL.
|
||||
(9) provider_link (slug copy with provider override; Link.Exe temp dir inside the slug):
|
||||
- With the packet's hud_draw.obj: 12/12 PASS in both orders.
|
||||
- Control with production NODUP hud_draw: LNK2005 in both orders.
|
||||
(10) objdiff-cli 3.3.1 single-unit projects plus the repo semantic/admission pipeline (strict_emulate):
|
||||
- With 04R: 22/22 functions, 6176/6176 code, 152/152 data, and contradicted/rejected/revoked all empty.
|
||||
- With the HEAD rejections: contradicted.
|
||||
(11) /W3 /Zs warning census (own script, temp TU inside the slug): multisets identical for all 6 edited TUs, including 01RaltS.
|
||||
(12) fake_match_scan on explicit files, prod vs cand: lead counts unchanged (hud_unit 0).
|
||||
(13) cachebeta publics: no public at C6590/C65A0/C65C0/C6600/C6B80; _check_stack_buffer PUBLIC at C08F0.
|
||||
(14) January split census: _check_stack_buffer is defined only by hud_draw, with 0 references or relocations; _get_return_eip is UNDEF in the other 4 sentinel TUs. 26 macro sites in the candidate equal January's 26.
|
||||
(15) House rules and law (g)/(i)/(j) review of every hunk.
|
||||
- Strip test: the plain goto-free loops are not exact (review3 S1/S2). The inline is attested by first-party evidence (inlined return merge at 26 sites, PUBLIC, never called).
|
||||
- /Od: the later build has no sentinel code, so no declaration-order evidence applies.
|
||||
- History of the models include: from commit 635bd83d. Only the struct tag bitmap_data overlaps.
|
||||
(16) Precedents consulted: owner rulings 20260921 #2/#4/#6, the review3_damage patch-A rule 6, the review3_main header_swap class, and the review3_hud_unit blockers.
|
||||
|
||||
## issues
|
||||
APPROVE=FALSE AS SUBMITTED. There are two defects, and an amended packet that fixes both is verified and ready.
|
||||
|
||||
(A) P6 (motion_sensor.c) breaks owner ruling 20260921 #2 / law (i), which requires a strictly exact caller.
|
||||
- All three motion_sensor sentinel callers are residual AND parked: _motion_sensor_update, _update_motion_sensor, _render_motion_sensor.
|
||||
- P6 therefore newly emits the ANY _check_stack_buffer COMDAT in motion_sensor.obj from non-exact callers only. This is the same class as damage patch A and actor_combat P1, both of which are held.
|
||||
- Fix: drop P6. The hud_unit admission does not need it, and dropping it is raw-inert: motion_sensor with the production .c and the new header is byte-identical to production.
|
||||
- Revisit P6 when one of those callers becomes strict-exact or the owner admits the P1 class.
|
||||
|
||||
(B) 01RaltS is not admissible. It keeps `goto update_finished`, while the /Od build has three per-arm last_shield_hit_time stores and no goto. That is the invented-goto held class. Use 01RS only.
|
||||
|
||||
AMENDED PACKET: C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\review4_hud_unit\patches\. The files are byte-identical copies of the worker's patches; hashes are in SHA256SUMS.txt.
|
||||
- Apply atomically, in this order: P1_hud_draw_h_check_stack_buffer_inline_and_macro.patch (shared header, separate), P2_hud_draw_c_shared_stack_frame.patch, 01RS_hud_unit_c_01R_plus_shared_stack_frame.patch, P4_hud_nav_points_c_shared_stack_frame.patch, P5_hud_weapon_c_shared_stack_frame.patch, P7_rasterizer_xbox_models_c_drop_dead_hud_draw_include.patch, 02_symbols_json_hud_unit_names_static.patch, 03_config_json_hud_unit_matching.patch, 04R_admission_rejections_retire_hud_unit_fast_ftol.patch.
|
||||
- git apply --check is CLEAN as a set on 16542e46.
|
||||
- Verification results:
|
||||
- 23-consumer sweep: identical to production except the intended changes.
|
||||
- hud_unit: 22/22 EXACT against the emulated split, audit PASS, surplus IDENTICAL, provider link 12/12 in both orders.
|
||||
- Strict emulation: 22/22 functions, 6176/6176 code, 152/152 data.
|
||||
- Warnings: unchanged.
|
||||
- P1+P2 must land with 01RS: the production NODUP hud_draw gives LNK2005.
|
||||
- 04R is required: without it the result is contradicted.
|
||||
- P4 is optional. The strict fallback (P1,P2,01RS,P7,02,03,04R) was also measured; its only effect is a same-size drift of the unparked residual _render_weapon_hud.
|
||||
- Header consumers of hud_draw.h, for the integrator's full sweep: source/interface/{hud_draw,hud_messaging,hud_nav_points,hud_unit,hud_weapon,motion_sensor,ui_widget}.c, source/objects/widgets/lightning.c, source/rasterizer/{rasterizer_debug,rasterizer_lights}.c, source/rasterizer/xbox/{rasterizer_xbox,rasterizer_xbox_debug,rasterizer_xbox_dynavobgeom,rasterizer_xbox_environment,rasterizer_xbox_environment_fog,rasterizer_xbox_models,rasterizer_xbox_screen_effect,rasterizer_xbox_shadows,rasterizer_xbox_transparent_geometry,rasterizer_xbox_water,shader_transparent_generic_preprocessor}.c, source/render/{render_contrails,render_sprite}.c. There are no paths with spaces. After the packet, models no longer includes it.
|
||||
|
||||
DISCLOSE:
|
||||
|
||||
(1) P7 is count shielding by removing a genuinely dead include.
|
||||
- models uses none of hud_draw.h's names except the struct tag bitmap_data, which bitmap headers already declare.
|
||||
- The include was added by project commit 635bd83d.
|
||||
- Removing it is raw-inert and warning-inert, and follows the precedent of removing verbatim duplicates.
|
||||
- It is load-bearing only relative to P1: the inline costs about 9 name units in models.
|
||||
- It differs from the held Layer-2 / main header_swap class, which ADDS declarations chosen by count. It must still be stated in any ruling request.
|
||||
- The P-A fallback (an invented focused header) conflicts with owner ruling #4.
|
||||
|
||||
(2) Newly emitted symbols (ruling #6):
|
||||
- An ANY _check_stack_buffer (48 B, identical to January's hud_draw copy) in hud_unit.obj, hud_nav_points.obj and hud_weapon.obj. The last two each have strictly exact callers.
|
||||
- hud_draw.obj's copy changes from NODUP to ANY.
|
||||
|
||||
ADVISORY (not scored): VC7 emits a referenced header inline at its definition position, so the candidate hud_draw.obj emits _check_stack_buffer BEFORE _get_return_eip. January's image has get_return_eip at C08E0 before check_stack_buffer at C08F0. That fits get_return_eip also being a hud_draw.h inline defined first, matching the Sept-2001 'i' flag. Relevant to hud_draw's own admission; not proposed now, because it would emit _get_return_eip from motion_sensor's non-exact callers.
|
||||
|
||||
Integrator: accumulation with other wave-4 header packets must be re-swept on the live tree (23 consumers plus parks). Full notes: C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\review4_hud_unit\REVIEW.md and LEDGER.md.
|
||||
@@ -0,0 +1,69 @@
|
||||
# REVIEW source/interface/hud_weapon
|
||||
|
||||
approve: True
|
||||
|
||||
## per_object
|
||||
[
|
||||
{
|
||||
"unit": "source/interface/hud_weapon",
|
||||
"approve": true,
|
||||
"issues": "Approve P5 unchanged (sha256 55cb5670...) only inside the atomic set P1+P2+(P3|01RS)+P5+P7. P5 needs P1 to compile and P2 to link (LNK2005 vs the production NODUP hud_draw copy, reproduced). Zero credit: 13/3 unchanged, residual bodies byte-identical, the only object change is the new ANY _check_stack_buffer, identical to January's. The COMDAT has two strictly exact callers, which alone emit it identically (lab L1), so law (i) is met. Strip test: the macro block is byte-inert. There is no /Od sentinel. Pre-existing admission blockers remain: an opaque hud_weapon_globals_definition view, a consumer-local extern hud_globals, and 3 residuals."
|
||||
}
|
||||
]
|
||||
|
||||
## checks
|
||||
All checks were run independently with tools in scratch/w/review4_hud_weapon/. Tree 16542e46; git status was clean before and after.
|
||||
|
||||
1. **Patch application.** `git apply --check` is clean for each of these sets: P5 alone; P1+P5; {P1,P2,P3,P5,P7}; {P1,P2,01RS,P4,P5,P6,P7}. `git show HEAD:` blobs plus `patch -p1` (P5, P1, P2) reproduce the worker's cand hud_weapon.c, hud_draw.h and hud_draw.c (EOL-normalised). Patch sha256 values match review4_hud_draw's pins (P5 55cb5670...).
|
||||
2. **Gate.** `gate.py --all` on prod, a verbatim-header control and the candidate (P5 + P1 header) gives 13 EXACT / 3 residual everywhere, with identical rows:
|
||||
- `_crosshairs_draw` relocs 77!=76
|
||||
- `_hud_update_weapon_local_player` size 1456!=1472
|
||||
- `_render_weapon_hud` size 2624!=2656
|
||||
3. **Raw compare (own rawcmp.py).** It checks bytes, relocations with $L labels normalised by value, flags, COMDAT selection and the full symbol table.
|
||||
- prod vs control: 0 differences.
|
||||
- prod vs cand: only the new ANY `_check_stack_buffer` section and its external symbol.
|
||||
- P1 without P5: `_render_weapon_hud` bytes drift, which reproduces the worker's A5.
|
||||
- Lab L0 (P1 header, all five goto copies kept, the TU `HUD_WEAPON_STACK_BUFFER_*` enum dropped) equals cand minus the COMDAT. So the drift comes from the TU's duplicate enum names, and removing them is genuine de-duplication, not count compensation.
|
||||
4. **Inlined sentinel tails (sentinel_tail.py / tail_dis.py).**
|
||||
- The exact callers `_render_grenade_hud` and `_hud_update_weapon` have tails byte- and reloc-identical to January.
|
||||
- The three residual callers have January's inlined shape. The differences are only alignment filler and pre-existing frame offsets, and no site calls the helper out of line.
|
||||
5. **Law (i) labs.** L1 (only the exact callers use the inline) still emits the identical COMDAT, with 0 object differences, so the emission is owned by strictly exact callers. L2 (only the residual callers use it) also gives 0 differences.
|
||||
6. **Strip test.** ST1 and ST2 (no macro braces; `short corrupt_index` declared after stack_buffer, or first) are identical to cand, so the block scope is byte-inert.
|
||||
7. **/Od build.** odbuild finds no "corrupt stack at" or "corrupt return address" strings, and the hud_weapon functions' RTC descriptors have no `stack_buffer`. No /Od frame exists, so law (d) does not apply.
|
||||
8. **Surplus identity (slug copy that reads the candidate object).** `_check_stack_buffer` is IDENTICAL to January hud_draw's copy. The pre-existing `_square_root` and `_power` are IDENTICAL too.
|
||||
9. **Provider links.**
|
||||
- Repo provider_link.py with production providers: `_check_stack_buffer` gives LNK2005 in both orders. This is the expected control and proves P5 also needs P2.
|
||||
- Slug pair link against my HEAD+P1+P2 hud_draw.obj (22/0/1; differs from prod only by selection 1->2): PASS in both orders.
|
||||
- The 3-object hud_weapon + hud_draw + hud_unit link: PASS in both orders.
|
||||
- hud_draw is the only production definer of `_check_stack_buffer`.
|
||||
10. **object_audit prod vs cand.** The text differs only by `+.text _check_stack_buffer 48`. All 23 January symbols are ok, and every data/rdata/bss section is ok. FAIL(3) is the three pre-existing residuals.
|
||||
11. **pdb_storage.** 0 disagreements. `_check_stack_buffer` is PUBLIC in cachebeta at 000C08F0.
|
||||
12. **Warnings.** The /W3 /Zs multisets are identical.
|
||||
13. **P1 consumer list.** A spaces-safe grep over .c/.h/.cpp/.inl finds 23 TUs, the same as the worker's list. Every consumer spells the include `interface/hud_draw.h`, and no header includes hud_draw.h.
|
||||
14. **Own shadow sweep of all 23 consumers.**
|
||||
- Control: 23/23 show 0 differences against build/base.
|
||||
- Minimal set P1+P2+P3+P5+P7: 20 objects show 0 differences (models with P7); hud_draw differs only by the selection change; hud_unit and hud_weapon differ only by the new ANY COMDAT. Gate summaries are identical everywhere.
|
||||
15. **Records checked.** parked.json and object_admission_rejections.json have no hud_weapon entries. The earlier hud_weapon ledgers record no sentinel negatives.
|
||||
|
||||
Notes are in REVIEW.md and LEDGER.md in the slug.
|
||||
|
||||
## issues
|
||||
P5's content is approved unchanged (sha256 55cb5670...; verbatim copy in scratch/w/review4_hud_weapon/patches/). It is approved ONLY inside the atomic hud_draw.h packet, and it is zero credit: hud_weapon stays 13/3 and is not an admission.
|
||||
|
||||
1. **The worker's dependency statement ("depends on P1") is incomplete.** The correct dependencies are:
|
||||
- P5 needs P1 to compile (the macro and `STACK_BUFFER_*` live in the header).
|
||||
- P5 needs P2 to link: against production's NODUP hud_draw `_check_stack_buffer` it gives LNK2005 in both orders, which I reproduced.
|
||||
- P1 in turn needs P3 or 01RS (hud_unit `STACK_BUFFER_*` redefinition) and P7 (the models declaration-count flip).
|
||||
- P1 needs P5 (`_render_weapon_hud` drift, which I reproduced).
|
||||
- Landing set: P1 + P2 + (P3|01RS) + P5 + P7 in one commit. P4 is optional; P6 follows the review4_hud_draw exclusion.
|
||||
- If the owner picks the P-A focused header instead of P1, P5 must be regenerated with the new include.
|
||||
2. **Disclosures.**
|
||||
- `match_assert_stack_frame` is a descriptive macro name that replaces the equally descriptive `hud_weapon_stack_buffer_check`; Bungie's name is lost.
|
||||
- The macro's block scope is byte-inert (strip test identical). The macro form rests on the F2 evidence that both asserts of every January site carry one line literal.
|
||||
- The new `_check_stack_buffer` COMDAT has two strictly exact callers (`_render_grenade_hud`, `_hud_update_weapon`), and lab L1 shows they alone emit it identically. So this is not the damage-A/P6 class. Three callers stay residual (unparked), and their inlined tails match January's shape.
|
||||
3. **Pre-existing hud_weapon admission blockers that P5 does not touch.**
|
||||
- A caller-local opaque view `struct hud_weapon_globals_definition { byte reserved000[0x2C0]; ... }`, with a consumer-local `extern ... *hud_globals`.
|
||||
- The three residuals.
|
||||
- Unassessed `goto finished` / `draw_crosshair` / `use_flat_color` control flow.
|
||||
- `_code_000c8xxx` placeholders in the header comment.
|
||||
4. **Integrator.** Re-sweep all 23 hud_draw.h consumers and the parks on the live tree, together with the other wave-4 header packets. hud_weapon's residuals are declaration-count sensitive, and isolated measurements do not compose.
|
||||
+134
@@ -0,0 +1,134 @@
|
||||
# REVIEW source/interface/motion_sensor
|
||||
|
||||
approve: False
|
||||
|
||||
## per_object
|
||||
[
|
||||
{
|
||||
"unit": "source/interface/motion_sensor :: P6 as submitted (hud_stack_check)",
|
||||
"approve": false,
|
||||
"issues": "Law (i) / rule 6 condition 2: the new SELECT_ANY _check_stack_buffer COMDAT is emitted only from 3 residual+parked callers (P1 class, same as the held damage patch A). With P1 landed, P6 is byte-inert for motion_sensor (0 raw diffs without it). The stated dependency is incomplete: P6 also needs P2 (LNK2005 against the production NODUP hud_draw)."
|
||||
},
|
||||
{
|
||||
"unit": "source/interface/motion_sensor :: P6A amendment (reviewer; P6 + goto-free /Od u9 update_motion_sensor + parked.json unpark), lands only inside/after the P1+P2 hud_draw.h packet",
|
||||
"approve": true,
|
||||
"issues": "Verified: _update_motion_sensor STRICT EXACT (+864 B), the other parks byte-unchanged, all 12 surplus COMDATs identical, the 4 new surplus symbols link in both orders, /W3 unchanged, /Od declaration and statement order respected, strip test shows the genuine inline is load-bearing and first-party attested, the exact-caller-only lab is identical. Conditions: P1 packet admission (P7 disclosure); full build + parked_functions validation + consumer sweep by the integrator; re-measure after other wave-4 header packets (M8 ordinal-sensitive). Byte-identical fallback: P6Aalt."
|
||||
}
|
||||
]
|
||||
|
||||
## checks
|
||||
All checks ran on tree 16542e46 and are my own re-runs in scratch/w/review4_motion_sensor/. git status was clean before and after. LEDGER.md has V1-V14 and REVIEW.md is written.
|
||||
|
||||
(1) Patch application
|
||||
- git apply --check is clean for:
|
||||
- P6 alone, P1 alone, P1+P6 and P1..P7;
|
||||
- P6 composed with the parallel w/motion_sensor production.patch and with bss_only.patch, in both orders.
|
||||
- `git show HEAD:` blobs plus `patch -p1` (P1, P2, P6) reproduce the worker's candidate hud_draw.h and motion_sensor.c.
|
||||
|
||||
(2) gate.py --all (TU copies with the include redirected to slug headers)
|
||||
- prod, ctrl (verbatim header), hdronly (P1 header with the HEAD TU) and cand (P1+P6) all give 16 EXACT / 3 residual with identical rows.
|
||||
- My own raw COFF comparer (rawcmp.py) checks bytes, relocations by normalised target, flags, COMDAT selection and checksum, the full symbol table and section order.
|
||||
- base = prod = ctrl = hdronly: 0 differences.
|
||||
- prod vs cand: the only difference is +ANY _check_stack_buffer (48 B). The parked bodies are byte-identical.
|
||||
|
||||
(3) Admission tools
|
||||
- object_audit: prod and cand differ only by `+.text _check_stack_buffer 48`.
|
||||
- tinfo --data: identical.
|
||||
- surplus_identity (slug copy that takes an obj): _check_stack_buffer is IDENTICAL to January's hud_draw copy.
|
||||
- provider_link.py against production hud_draw: LNK2005 in both orders, so P6 also needs P2. provider_link_ovr against a HEAD+P1+P2 hud_draw.obj: PASS in both orders.
|
||||
- /W3 /Zs warning multisets: identical.
|
||||
- cachebeta publics: _check_stack_buffer at C08F0 and _get_return_eip at C08E0 are PUBLIC.
|
||||
- pdb_storage: 44/0.
|
||||
- There is no rejection entry for motion_sensor.
|
||||
|
||||
(4) Evidence
|
||||
- January bytes: each of the 3 functions has one sentinel loop and pushes its line literal (642/756/830) twice.
|
||||
- /Od build: no "corrupt stack" or "corrupt return" strings, and no stack_buffer in the RTC descriptors of 0x641b60, 0x642ff0 or 0x642868.
|
||||
- HCEX: no check_stack_buffer or get_return_eip symbol.
|
||||
|
||||
(5) Strip test
|
||||
- P6 in production context: the macro-free expansion is raw-identical.
|
||||
- In the u9 context:
|
||||
- stripA (inline called directly, declaration at function top): identical.
|
||||
- stripB (goto-free hand loop without the inline): residual.
|
||||
|
||||
(6) NEW: P6 on top of w/motion_sensor's /Od u9 update body
|
||||
- On HEAD, on HEAD + ms production.patch and on the owner-gated cand_full, _update_motion_sensor goes STRICT EXACT (864).
|
||||
- Labs:
|
||||
- goto-free nested-if form: identical.
|
||||
- labC and labD declaration placements: identical.
|
||||
- exact-caller-only lab (the parked callers keep hand copies): identical.
|
||||
- January's update sentinel tail equals ours instruction for instruction.
|
||||
|
||||
(7) Amended P6A (HEAD-based)
|
||||
- git apply --check is clean alone, with P1, with the full packet P1,P2,P3|01RS,P4,P5,P7 plus the parked patch, and with ms production.patch in both orders. The patch replay equals the candidate (cmp).
|
||||
- Gate: 17/2. The two parked bodies are unchanged.
|
||||
- object_audit: update `ok 864/864`.
|
||||
- surplus_identity: all 12 code COMDATs IDENTICAL (_distance_squared3d and _vector_from_points3d against action_alert).
|
||||
- provider_link: the 4 new surplus symbols PASS in both orders, and the full list PASSES.
|
||||
- nodup_census: no NODUP copies.
|
||||
- /W3: identical.
|
||||
- symbols.json already has _update_motion_sensor static:true, and both new helpers are PUBLIC in cachebeta.
|
||||
- Composed with the ms production packet: 17/2, and the audit shows 44/44 symbols.
|
||||
|
||||
(8) Not run (forbidden or impossible here)
|
||||
- ninja, the full build and the parked_functions validation against report.json.
|
||||
- A full 23-consumer shadow sweep for P1: P6A itself touches no header, and P1's sweep is covered by the review4_hud_draw, hud_unit, hud_weapon and hud_nav_points reviews.
|
||||
|
||||
## issues
|
||||
P6 AS SUBMITTED IS REJECTED (approve=false)
|
||||
|
||||
(a) Law (i) / rule 6 condition 2 (P1 class). P6's only object effect is a new SELECT_ANY _check_stack_buffer COMDAT in motion_sensor.obj.
|
||||
- Its only users are the 3 sentinel sites. All three sit in RESIDUAL and PARKED functions: _motion_sensor_update, _update_motion_sensor and _render_motion_sensor.
|
||||
- This is the same class as the held "damage patch A / hs real_random_range cleanup" (a zero-credit house-clean that emits a new header COMDAT from a non-exact caller).
|
||||
- Identity, pair link and sweep all pass, but they do not cure the missing strictly exact caller.
|
||||
- The sibling reviews review4_hud_draw and review4_hud_unit reached the same conclusion.
|
||||
|
||||
(b) The dependency statement "Depends on P1" is incomplete. P6 also needs P2: against production's NODUP hud_draw it gets LNK2005 in both orders.
|
||||
|
||||
(c) Worker A5 says "P4-P6 are NOT optional". That is wrong for P6: with P1 alone, motion_sensor has 0 raw differences.
|
||||
|
||||
FIX FOUND AND VERIFIED: P6A (+1 strict function, 864 meaningful bytes)
|
||||
- Combining P6 with the /Od-attested u9 update_motion_sensor body closes u9's single residual (the inlined distance_squared3d sum association, the M8 IL-ordinal mechanism). The u9 body comes from scratch/w/motion_sensor/owner_gated_full.patch, WITHOUT the m4 authentic-bug part.
|
||||
- u9 had been gated only by rule (i) through m4. With update exact:
|
||||
- _check_stack_buffer has a strictly exact caller; the exact-caller-only lab is raw-identical.
|
||||
- _distance_squared3d and _vector_from_points3d have their own exact caller.
|
||||
- The load-bearing construct is the genuine header inline. The stripB hand loop fails. The inline is first-party attested: 26/26 January inlined-return-merge sites, January's update tail is identical to ours, it is PUBLIC in cachebeta, and it has a single definer.
|
||||
- P6A lands the goto-free single-exit form (raw-identical) and the /Od declaration order (customs in block 2; a blip_index/blips block after block 1; all placements raw-identical; law (d)).
|
||||
- P6Aalt, with the blip locals hoisted to the top, is a byte-identical fallback if the owner rejects the loop-1 block.
|
||||
|
||||
DISCLOSURES
|
||||
- match_assert_stack_frame is a descriptive macro name.
|
||||
- P6A depends on the whole P1 packet: P1 + P2 + (P3 or 01RS) + P5 + P7, with P7's count-shielding disclosure.
|
||||
- The M8 closure is ordinal-sensitive. Re-measure it on the live tree after the other wave-4 header packets.
|
||||
- motion_sensor stays non-complete:
|
||||
- 2 parked residuals;
|
||||
- the render goto in its parked body;
|
||||
- the pre-existing render_blip view casts;
|
||||
- the .bss offsets, which belong to the parallel bss packet.
|
||||
|
||||
PRODUCTION CHANGES
|
||||
|
||||
1. Land the hud_draw.h packet in one commit, per review4_hud_draw/hud_unit: P1 + P2 + (P3 or 01RS) + P5 + P7, with P4 optional. Do NOT use P6; use P6A instead.
|
||||
|
||||
2. Apply C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\review4_motion_sensor\patches\P6A_motion_sensor_c_stack_frame_and_update_od_body.patch
|
||||
- sha256 827a09cca0db7229b6172f8bc5e3b92dd82202cc4302c731cb8bc92937372b47.
|
||||
- Full candidate file: scratch\w\review4_motion_sensor\amend\source\interface\motion_sensor.c.
|
||||
- It changes source/interface/motion_sensor.c only; there is no header edit.
|
||||
- It is P6's three match_assert_stack_frame(...642/756/830) sites and STACK_BUFFER_LENGTH, plus update_motion_sensor replaced by the goto-free /Od body.
|
||||
|
||||
3. Apply C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\review4_motion_sensor\patches\P6A_parked_json_unpark_update_motion_sensor.patch
|
||||
- sha256 03eab1e92277439c84149a7b9670ef1e6a2df49a348b905b5e8cd0d3f83b4a9c.
|
||||
- It deletes the _update_motion_sensor entry object: HEAD config/parked.json lines 1275-1293, CRLF kept, 86 -> 85 entries.
|
||||
- Full edited copy: scratch\w\review4_motion_sensor\config\parked.json.
|
||||
- It uses -U2 context, so it composes with the ms render park re-baseline.
|
||||
|
||||
4. Optional fallback, byte-identical: scratch\w\review4_motion_sensor\patches\P6Aalt_motion_sensor_c_top_level_blip_locals.patch (sha256 fbf8aab8...).
|
||||
|
||||
5. After applying, run:
|
||||
- a full build;
|
||||
- parked_functions validation;
|
||||
- the stable per-function sweep of the 23 hud_draw.h consumers and the parks.
|
||||
- Expected result: +1 strict function (_update_motion_sensor), 0 regressions.
|
||||
|
||||
No symbols.json change is needed.
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
# REVIEW source/interface/motion_sensor :: .bss symbol layout (object admission)
|
||||
|
||||
approve: True
|
||||
|
||||
## per_object
|
||||
[
|
||||
{
|
||||
"unit": "source/interface/motion_sensor (.bss hunk: motion_sensor_globals = NULL, sweep_theta = 0.f)",
|
||||
"approve": true,
|
||||
"issues": "None blocking. Gate unchanged at exact 16 / residual 3, and all 75 sections are coff-identical to base. object_audit symbols go from 2 differing to 0, and resolved .bss relocation targets now equal January's. Lab tests show both initialisers are required and the declaration order is January's. HCEX confirms the names, types and file-static storage. No new surplus; provider link PASS; data already 100%, so zero credit. Apply bss_only.patch from the reviewer slug (hunk 1 only); the render hunks of production.patch are out of scope."
|
||||
}
|
||||
]
|
||||
|
||||
## checks
|
||||
All checks ran at 16542e46; git status was empty before and after. Scope is only the first hunk of scratch/w/motion_sensor/production.patch. Reviewer slug: C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\review4_motion_sensor_____bss_symbol_layout__object_admission_\ (LEDGER.md, REVIEW.md).
|
||||
|
||||
(1) Candidate. Built cand_bss.c as the working-tree motion_sensor.c plus only hunk 1. The patch file is bss_only.patch, the worker's first hunk verbatim with a CRLF body. `git apply --check` passes, and `patch -o` onto the working-tree copy reproduces cand_bss.c byte for byte. The whole production.patch also applies and equals the worker's cand_prod.c.
|
||||
|
||||
(2) gate.py --all. Base and candidate give identical output: exact 16, residual 3 (motion_sensor_update, render_motion_sensor, update_motion_sensor, all pre-existing). No row lost.
|
||||
|
||||
(3) Object-level comparison. My objcmp.py (coff_compare.section_infos_equal over all 75 sections) finds 0 section differences between base and candidate, apart from the .debug$S path. The only symbol changes are _next_vertex_index 8->0 and _sweep_theta 0->8. My base compile also equals build/base/…/motion_sensor.obj on every section.
|
||||
|
||||
(4) object_audit. Base: 44 January symbols, 2 differ, FAIL(5). Candidate: 44 January symbols, 0 differ, FAIL(3). The 3 remaining failures are the residual .text functions; the .bss section is 13/13 ok.
|
||||
|
||||
(5) Lab proof of the VC7 .bss law in this TU:
|
||||
- only motion_sensor_globals initialised: 3 symbols differ
|
||||
- only sweep_theta initialised: 2 differ
|
||||
- both spelled `= {0}`: 0 differ (the zero spelling is inert)
|
||||
- both initialised, declared in swapped order: 2 differ
|
||||
Both initialisers are necessary and sufficient, and the current declaration order is January's. The gate stays at 16/3 in all four variants.
|
||||
|
||||
(6) January side. config/contribs.json has the object's own 13-byte .bss contribution at 0x453AC8. It contains the public next_vertex_index at offset 0 and debug_motion_sensor_draw_all_units at 0xc, so both are initialised definitions, not COMMON, and no uninitialised static can come before offset 0. tinfo relocations show initialize storing the malloc result to .bss+4 and tick using .bss+8 as a float. That is consistent with the symbols.json attribution, so this is not an attribution defect.
|
||||
|
||||
(7) Resolved relocation targets (section owner + offset) of the 16 exact functions:
|
||||
- Base differs from January in 6 functions; the candidate differs in 4.
|
||||
- Every .bss reference now resolves identically to January.
|
||||
- The 4 remaining differences are the pre-existing folded-literal class (__real@ and ??_C@ literals).
|
||||
|
||||
(8) pdb_storage: 0 disagreements. motion_sensor_globals and sweep_theta are absent from the cachebeta publics, so they are file statics, and the hunk keeps storage class 3.
|
||||
|
||||
(9) HCEX.pdb (DIA2Dump):
|
||||
- motion_sensor_globals: File Static, `struct motion_sensor_globals_definition *`
|
||||
- sweep_theta: File Static, float (= real)
|
||||
Names, types and storage match. The atlas has no data entries for these names. I inspected the later /Od 2020 build's data layout; it is inconclusive because it comes from a modern compiler, and I did not rely on it.
|
||||
|
||||
(10) Surplus and link:
|
||||
- provider_link with the candidate and --baseline=base.obj: no new surplus, PASS.
|
||||
- Full provider_link: 14/14 PASS.
|
||||
- surplus_identity: 9 COMDATs, 0 not identical, unchanged.
|
||||
|
||||
(11) Data: build/report.json shows motion_sensor data at 501/501 (100%), so zero credit, as the worker claimed. There are no semantic_data_matches, object_admission_rejections or parked.json entries that this hunk touches.
|
||||
|
||||
(12) House-rule review:
|
||||
- STRIP TEST: removing the initialisers brings back the 2-symbol difference, so they are load-bearing. January's own .bss layout attests them under a measured compiler law, which is the established data-closure lever. They add no code store, filler, pragma or name, and change no semantics.
|
||||
- Spelling follows precedent in the sibling HUD files: `= NULL` as in hud_unit.c and hud_weapon.c (also game.c, objects.c, game_allegiance.c), and `0.f` as in players.c. `real` is kept.
|
||||
- The hunk changes no header, symbols.json, block scope, prototype, view cast or COMDAT, and falls in no owner-gated class. It does not overlap the held hud_unit stack-sentinel item or any other held item.
|
||||
|
||||
## issues
|
||||
No blocking issues. The admission fix is verified and approved as zero-credit hygiene. It removes the 2-symbol .bss offset blocker: object_audit goes from 44/2 to 44/0 with no code, relocation or data change.
|
||||
|
||||
The integrator should apply C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\review4_motion_sensor_____bss_symbol_layout__object_admission_\bss_only.patch. It is exactly hunk 1 of the worker's production.patch. The file has CRLF content lines, and `git apply --check` is clean at 16542e46.
|
||||
|
||||
The render_motion_sensor hunks in that same production.patch (the one-`weight`-local change, `pow`, and the corner/blip_pos renames) are NOT covered by this review. Apply them only under their own review.
|
||||
|
||||
Non-blocking observations, outside this hunk:
|
||||
(a) HCEX types `next_vertex_index` as `short` while ours is `long`. It is unreferenced in the TU and byte-inert under the 4-byte static padding law. I left it untouched; it could be revisited later as type hygiene with January evidence.
|
||||
(b) The object is still not complete. Three residual functions remain: _motion_sensor_update is owner-gated (authentic uninitialised-read bug class), and _render_motion_sensor and _update_motion_sensor are scheduler/sum-order residuals. This fix only removes the .bss symbol-offset blocker.
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
# REVIEW source/math/geometry (provider repair that unblocks collision_bsp's link) - review of scratch/w/collision_bsp/geometry_provider_repair.patch
|
||||
|
||||
approve: True
|
||||
|
||||
## per_object
|
||||
[
|
||||
{
|
||||
"unit": "source/math/geometry",
|
||||
"approve": true,
|
||||
"issues": "Byte-inert everywhere: the only object change is `_plane2d_distance_to_point` COMDAT selection NODUP->ANY. Still 27/3 exact; the 3 parked residuals are unchanged and the parks stay valid. Pre-existing and out of scope: provider_link FAIL(2) (cross_product2d P1, plane2d_from_points decals hand copy), and vector_intersect_plane2d hand-expands the helper."
|
||||
},
|
||||
{
|
||||
"unit": "source/physics/collision_bsp",
|
||||
"approve": true,
|
||||
"issues": "Not modified by this patch. Its latent LNK2005 against geometry on `_plane2d_distance_to_point` is removed; the pair link with cand.obj is clean in both orders, and st1.obj + cand.obj is also clean. The object is still not complete: 3 residual .text functions and the held `_cross_product2d` P1 conflict."
|
||||
}
|
||||
]
|
||||
|
||||
## checks
|
||||
All notes are in C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\review4_geometry__provider_repair_that_unblocks_collision_bsp_s_link_\REVIEW.md (R1-R20). The tree was clean at 16542e46 for the whole review.
|
||||
|
||||
R1 Patch applies and round-trips: git apply --check passes for the geometry patch alone and together with collision_bsp production.patch. HEAD blob + patch == worker geom/g1.c byte-for-byte (sha256 192ee6c3...).
|
||||
|
||||
R2 Header body: the real_math.h:1301 `__inline` body text is identical to the deleted hand copy. geometry.h has no prototype. The only users are geometry.c lines 712, 1166 and 1171 and collision_bsp.c lines 1435 and 1995.
|
||||
|
||||
R3 gate.py --all: HEAD and candidate are both exact 27 / residual 3 / unwritten 0, and the two outputs are identical.
|
||||
|
||||
R4 Full object comparison (slug objcmp.py: section_infos_equal, raw bytes, flags, COMDAT selection, and every symbol's storage/section/value). head.obj vs cand.obj has exactly ONE difference: `_plane2d_distance_to_point` selection changes from NODUP (1) to ANY (2); bytes and storage are unchanged. Production geometry.obj == head.obj.
|
||||
|
||||
R5 January's 32 bytes appear in only one split object board-wide (geometry).
|
||||
|
||||
R6/R7 Link order and pair links: collision_bsp (0x136C00) and bsp2d (0x136590) both follow geometry (0xF4F00) in January's link order. Production collision_bsp.obj linked with production geometry.obj (or head.obj) gives LNK2005 in BOTH orders, so the current tree has a latent defect. Linked with cand.obj (and with the prior reviewer's st1.obj), there is no LNK2005/LNK1169 in either order.
|
||||
|
||||
R8 provider_link (slug copy): identical for head and cand. It FAILs on 2 pre-existing items: cross_product2d (held P1) and plane2d_from_points (decals NODUP hand copy).
|
||||
|
||||
R9 object_audit: identical for head and cand (3 residual .text DIFFs, 90 January symbols with 0 differences) and equal to the worker's audit_g1.txt. The 3 parked.json measurements match cand exactly, so no park goes stale. There are no rejection entries.
|
||||
|
||||
R10 Law (i) / owner ruling 2 (all-inlined header-inline COMDATs): the COMDAT is owned by January's geometry object and is already emitted today. `_points_dimension2d` is a strictly exact user of the inline (EXACT 160). The residual caller's source and bytes are unchanged.
|
||||
|
||||
R13 Precedent: owner-landed commit 5e81dabf removed the identical rename + hand copy for vector_intersect_plane3d from the same #define block.
|
||||
|
||||
R14 Symbol storage: cachebeta lists `_plane2d_distance_to_point` as public, so no symbols.json change is needed.
|
||||
|
||||
R15 /W3 /Zs warnings: 13 in both, same set.
|
||||
|
||||
R16 objdiff-cli 3.3.1 single-unit projects: identical rows for head and cand (8838/12751 code, 2288/2288 data, 27/30 functions), matching build/report.json.
|
||||
|
||||
R17 Surplus identity: unchanged (1 pre-existing plane2d_from_points difference in both).
|
||||
|
||||
R18 Adversarial single-body test (lab only, shadow real_math.h in the slug, verified with /showIncludes). I put the /Od-attested body `dot_product2d(point,&plane->n) - plane->d` (from /Od function 0x6bf170) in the header. collision_bsp shows 0 section differences, and its bsp2d sphere/pill functions stay EXACT. In geometry only the already-residual convex_polygon2d_clip_to_plane changes. So one shared header body is consistent with every exact user.
|
||||
|
||||
R19 bsp2d_test_point with the /Od helper-call spelling (lab only) is EXACT. It LNK2005s against production geometry but links clean with the candidate.
|
||||
|
||||
R20 House-rule / strip-test / section-7-9 scan: the patch only deletes code and adds no decoration. It changes no header, so there is no consumer list. Nothing includes geometry.c.
|
||||
|
||||
## issues
|
||||
No blocking issues. APPROVE scratch/w/collision_bsp/geometry_provider_repair.patch as proposed, with no amendment. It can be applied mechanically:
|
||||
- `git apply` the patch; no header, symbols.json, config or park change is needed.
|
||||
- The only change to geometry.obj is the COMDAT selection byte for `_plane2d_distance_to_point` (NODUP -> ANY).
|
||||
- gate rows, objdiff rows, parks and data stay unchanged.
|
||||
- It removes the current tree's latent collision_bsp<->geometry LNK2005 in both link orders.
|
||||
|
||||
Non-blocking notes:
|
||||
(1) The worker cites "owner ruling 20260921 #5". The all-inlined header-inline COMDAT admission is ruling #2 in claude_lane_b_HANDOFF_20260920.md section 3 and in the lanes-AB table. Correct the number in any ledger text.
|
||||
(2) Pre-existing problems this patch does not introduce:
|
||||
- geometry stays 27/3.
|
||||
- geometry's surplus provider_link FAILs on `_cross_product2d` (held P1) and `_plane2d_from_points` (decals NODUP hand copy, also not identical).
|
||||
- geometry.c vector_intersect_plane2d and bsp2d.c bsp2d_test_point hand-expand the plane2d helper; the /Od build shows real calls in bsp2d.
|
||||
(3) Follow-ups the repair enables, NOT part of this patch:
|
||||
- bsp2d.c could use its /Od-attested helper call (lab: still EXACT, and links clean only after this repair).
|
||||
- Lane D's convex_polygon2d_clip_to_plane route needs the /Od-attested header body `dot_product2d((real_vector2d *)point, &plane->n) - plane->d`. That now has to be a real_math.h body packet with a full sweep; the lab shows collision_bsp is byte-inert to it.
|
||||
(4) January image section order does not decide the question either way. January puts its selected header-inline copies in a mid-object block in every Layer-1 object, while our VC7 emits them at the top. Section order earns no credit.
|
||||
(5) collision_bsp stays NOT complete: 3 residual .text functions and the held `_cross_product2d` P1 provider conflict.
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
# REVIEW source/physics/collision_bsp (whole object: admission) - review of ADMISSION_FIX_PROPOSED storage packet
|
||||
|
||||
approve: True
|
||||
|
||||
## per_object
|
||||
null
|
||||
|
||||
## checks
|
||||
All work is in C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\review4_collision_bsp__whole_object__admission_\ (REVIEW.md holds the full log). HEAD is 16542e46 and the tree was clean before and after.
|
||||
|
||||
1. gate.py --all on the worker's st1.c: exact 27, residual 3, unwritten 0. The residuals are _bsp3d_test_pill_recursive (sha), _bsp3d_test_sphere_recursive (sha) and _collision_surface_test_sphere (size 848 vs 880). The HEAD source gives the same 27/3. st1.obj and base.obj have 69/69 sections equal under section_infos_equal. The only symbol-table difference is _collision_bsp_usage_times, storage 2 -> 3.
|
||||
2. The patch: `git apply --check scratch/w/collision_bsp/production.patch` is OK against the current tree. Its index b4438fa9 equals the HEAD blob. Applying it to HEAD (CRLF) reproduces st1.c byte-for-byte.
|
||||
3. symbols.json: I made the same edit myself on a copy of HEAD config/symbols.json, in place at line 23117 with CRLF kept (+16 bytes). The result is byte-identical to the worker's copy at scratch/w/collision_bsp/config/symbols.json.
|
||||
4. Emulated csplit (build/tools/csplit.exe, output in my slug): the control split equals build/split for 833/833 objects. The edited split differs only in source/physics/collision_bsp.obj. There, 35/35 sections are equal and the only change is _collision_bsp_usage_times 2 -> 3.
|
||||
5. object_audit (slug copy pointed at the emulated split): st1.obj has 35 January symbols with 0 differences. The only DIFF rows are the 3 residual .text sections. Controls show the two edits must land together: base.obj vs the emulated split fails on storage 3/2, and st1.obj vs the control split fails on 2/3.
|
||||
6. Storage truth:
|
||||
- `_collision_bsp_usage_times` is not a cachebeta.pdb public. The collision_bsp compiland is present: its external functions are public and its statics are absent, so the oracle holds in this TU. The sibling `_collision_usage_times` is also non-public and already static in symbols.json and in collisions.c.
|
||||
- PDB storage check on the candidate vs the emulated split: 0 disagreements (production has 1).
|
||||
- relocs.json: offsets 0x456EB0..0x456EBC are referenced only by _collision_bsp_test_vector (+0,+4) and _collision_bsp_test_sphere (+8,+0xC).
|
||||
- No other split object names the symbol. A grep of all of source/ and the headers finds it only in collision_bsp.c, with no extern declaration anywhere.
|
||||
- HCEX 2011: the collision_bsp compiland dump (DIA2Dump by full module path) has no file-scope data, so it neither confirms nor contradicts. The atlas lists functions only.
|
||||
7. objdiff-cli 3.3.1 single-unit projects: the emulated pair (split_emu vs st1) and the control pair (split_ctrl vs base) both give code 7134/10292, data 176/176 (100%) and 27/30 functions. This matches build/report.json.
|
||||
8. surplus_identity (slug copy run on st1.obj): 21 candidate-only code COMDATs, all IDENTICAL to January's selected providers.
|
||||
9. provider_link on st1.obj (temp files under my slug): FAIL (2), both pre-existing and disclosed by the worker:
|
||||
- _cross_product2d vs actor_combat: the held P1 item.
|
||||
- _plane2d_distance_to_point vs geometry: a NODUP hand copy.
|
||||
The storage edit touches no external surplus.
|
||||
10. /W3 /Zs warnings: 22 on base, 22 on the candidate, identical multisets.
|
||||
11. STRIP TEST on the only remaining construct, the `= { 0 }` on the now-static object:
|
||||
- Without the initialiser the object still gates 27/3 with identical function hashes and passes the owner-keyed audit (0 symbol diffs). Only the .bss section index moves.
|
||||
- So the initialiser is not load-bearing. It is pre-existing production text, and the minimal one-keyword diff is fine.
|
||||
12. parked.json: all 3 collision_bsp parks keep identical size, relocation count and normalized_sha256 on both the target side (ctrl, emu, manifest) and the base side (base, st1, manifest), so no park goes stale. There are no collision_bsp entries in object_admission_rejections.json, and no semantic, semantic-data or ownership entry names the symbol.
|
||||
13. House rules and section 7/8/9 blockers: the diff adds one `static` keyword. It adds no header change, consumer prototype, view cast, hand-expanded helper, float, new name, new aggregate or new COMDAT. There is no new block scope, so the /Od declaration-order check does not apply. It follows the admitted collisions.c idiom.
|
||||
14. Informational only (not part of this proposal): the worker's geometry_provider_repair.patch passes git apply --check and round-trips to g1.c. The geometry gate rows are identical and all 61 geometry .text hashes are unchanged. Linking st1.obj with g1.obj gives 0 LNK2005 in both orders; linking with production geometry.obj gives 1 LNK2005, so the check discriminates.
|
||||
|
||||
## issues
|
||||
The storage packet itself has no blocking issues. The object stays incomplete, and the integrator should note:
|
||||
|
||||
(a) What to apply:
|
||||
- production.patch (`static` on collision_bsp_usage_times at source/physics/collision_bsp.c line 305).
|
||||
- The config/symbols.json edit at line 23117, in place: append `, "static": true` before ` }`, keep CRLF, do not re-serialise. It is identical to scratch/w/collision_bsp/config/symbols.json.
|
||||
- A csplit-only regen. Expect only build/split/source/physics/collision_bsp.obj to change; its emulated sha256 is 35f9f040674643c5...
|
||||
- The source patch and the symbols.json edit must land together; either one alone introduces a storage mismatch.
|
||||
- There is no header change, so no consumer sweep is needed.
|
||||
|
||||
(b) The object remains NOT complete:
|
||||
- 3 residual .text sections: _collision_surface_test_sphere (the owner-held SSE __asm class) and the two bsp3d parity-bit residuals (sphere and pill).
|
||||
- 2 LNK2005 errors in the selected-provider link: _cross_product2d (held P1) and _plane2d_distance_to_point (geometry NODUP hand copy).
|
||||
|
||||
(c) This review does NOT approve the worker's separate geometry_provider_repair.patch. My light check matched the worker's claims, but it is a different unit and needs its own review.
|
||||
|
||||
(d) Disclosed pre-existing item, not introduced by this diff: the `struct collision_bsp_usage_times {vector; sphere}` aggregate and its descriptive name are not first-party attested.
|
||||
- The bytes cannot distinguish the struct from two loose statics: LARGE_INTEGER forces 8-byte alignment either way, and no assert string names it.
|
||||
- It has no pad members (law j), its layout agrees with January's relocations, and it mirrors the admitted collisions.c sibling.
|
||||
- A final whole-object admission should disclose this.
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
# REVIEW source/rasterizer/rasterizer_lights :: P1 storage/.bss layout packet (admission prerequisite)
|
||||
|
||||
approve: True
|
||||
|
||||
## per_object
|
||||
[
|
||||
{
|
||||
"unit": "source/rasterizer/rasterizer_lights (P1: P1_storage_layout.patch + P1_symbols_json.patch)",
|
||||
"approve": true,
|
||||
"issues": "Zero credit; must land both halves in one commit (a half-landing costs 333,605 objdiff data bytes and one reloc-identity row). The 'HCEX declaration order' rationale is overstated: bss2 is an equivalent alternative, so disclose it in the ledger. production.patch's P2 / parked.json / reset parts are out of scope and not approved here."
|
||||
}
|
||||
]
|
||||
|
||||
## checks
|
||||
All work is in C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\review4__bss_layout_packet__P1__admission_prerequisite_\ (LEDGER.md has 15 checks, REVIEW.md has the verdict). git status was clean before and after.
|
||||
(1) Patch hygiene:
|
||||
- `git apply --check` passes on 16542e46 for P1_storage_layout.patch, P1_symbols_json.patch, the two together, and production.patch.
|
||||
- Applying both P1 patches outside the repo reproduces worker stg.c and worker config/symbols.json byte for byte (CRLF).
|
||||
- I re-derived the 6 in-place symbols.json line edits (6213, 23227-23231) myself and got the same file. Nothing is re-serialised.
|
||||
(2) csplit:
|
||||
- A regen with the unmodified config equals build/split (833/833).
|
||||
- A regen with the P1 symbols.json changes only rasterizer_lights.obj, and matches the worker's regen.
|
||||
(3) gate.py against the current split: base.c gives 10 exact / 3 residual. p1.c gives 9/4, because `_rasterizer_lens_flare_submit` becomes [reloc-identity].
|
||||
(4) The same gate logic against the regen split: p1 gives 10 exact / 3 residual, with the same residual set (submit_for_cluster, draw, reset). p1.obj sections equal worker stg.obj.
|
||||
(5) object_audit copy with AUDIT_SPLIT_ROOT:
|
||||
- p1 vs regen: .bss section ok, 41/41 January symbols match, FAIL(3) = the known code residuals only.
|
||||
- base vs current: FAIL(9).
|
||||
- base vs regen (symbols.json alone): FAIL(7).
|
||||
(6) PDB storage: 6 disagreements on the current tree, 0 with P1+regen.
|
||||
- None of the 6 names is a cachebeta public. No public lies in the .bss range 0x466B80-0x4B82A5.
|
||||
- Data publics share the symbols.json address space (760/760 match), so absence means static.
|
||||
(7) objdiff 3.3.1, one-unit reports:
|
||||
- prod reproduces the build/report.json row (only metadata source_path differs).
|
||||
- p1+regen is identical to prod: code 1996/5244, data 335089/335089.
|
||||
- A half-landing (either half alone) gives data 1484/335089 (.bss 99.9997%).
|
||||
(8) VC7 .bss law re-measured in this TU (labA-E): declaration order has no effect on uninitialised statics; only results `= {0}` (bss1) or both `= {0}` with results2 first (bss2) give January's layout.
|
||||
(9) STRIP TEST: without results `= {0}`, results goes back to @0. Without `= FALSE`, warned moves to @262176. Both are load-bearing.
|
||||
(10) /Od (halo_cache_symbols.exe) layout read: the latch byte at 0xecea08 is not adjacent to the file statics, which is consistent with a function-static latch. Its .bss order comes from a different compiler, so it does not decide bss1 vs bss2.
|
||||
(11) HCEX compiland re-dumped with DIA2Dump -compiland: 4 File Statics plus the Static Local `unsigned char warned` of rasterizer_lens_flare_submit. The atlas has no data rows for this range.
|
||||
(12) Runtime test tools/test_rasterizer_lights_frame_runtime.py: its relocation-name resolution, simulated on the regen split and p1.obj, still resolves.
|
||||
(13) January side of the regen split: all 13 function normalized hashes are unchanged, including the draw park target 05fb3208. The park base 25834daf is unchanged by P1.
|
||||
(14) /W3 /Zs gives the same 13 diagnostics.
|
||||
- fake_match_scan finds 0 leads.
|
||||
- provider_link PASSES, both full and restricted to new surplus.
|
||||
- surplus_identity finds 11 COMDATs, 0 differing, and P1's surplus equals base.
|
||||
(15) House-rule review:
|
||||
- No header, prototype, float, view cast or new block scope.
|
||||
- The function-scope static local has the same form as the landed dynavobgeom `warned`.
|
||||
- The invented name local_lens_flare_error_printed is replaced by HCEX's `warned`.
|
||||
|
||||
## issues
|
||||
APPROVED for P1 only, with conditions. P1 earns zero credit: every metric is unchanged.
|
||||
|
||||
1. MUST LAND ATOMICALLY. Apply source/rasterizer/rasterizer_lights.c from scratch/w/rasterizer_lights/P1_storage_layout.patch and the 6 symbols.json line edits (P1_symbols_json.patch, or line ops from the full copy scratch/w/rasterizer_lights/config/symbols.json, lines 6213 and 23227-23231) in the same commit. Either half alone does two things:
|
||||
- `_rasterizer_lens_flare_submit` becomes [reloc-identity].
|
||||
- objdiff 3.3.1 data drops from 335089 to 1484/335089 (.bss 99.9997%), a loss of 333,605 data bytes.
|
||||
The worker reported only the code half of this.
|
||||
2. SCOPE. production.patch also bundles P2 (the draw respelling), the parked.json re-baseline of `_rasterizer_lens_flares_draw`, and the owner-gated reset. None of those are reviewed here, so do not take production.patch on this verdict; use the two split P1 patches.
|
||||
3. RATIONALE CORRECTION (disclosure, not a blocker). The worker says "bss1 keeps HCEX declaration order", but HCEX's address order results<results2 does not prove declaration order:
|
||||
- Under the VC7 law, uninitialised statics are ordered by name hash. I re-measured this: declaration order has no effect.
|
||||
- VC16's .bss law is unmeasured. My census found no TU with an HCEX SHIP compiland to calibrate it.
|
||||
- bss2 (both arrays `= {0}`, results2 declared first) is byte-identical and equally consistent with the evidence. bss1 is simply the minimal edit that keeps the tree's existing declaration order.
|
||||
- If VC16 followed the VC7 law, the 2011 source lacked the initialiser. But every January-exact spelling departs from that inferred source, so it cannot be used against bss1.
|
||||
Record this ambiguity in the object ledger.
|
||||
4. POLICY BASIS for the load-bearing `= {0}`. The strip test fails without it. I accept it anyway, as a reconstruction attested by January's own .bss layout plus the VC7 law I re-measured:
|
||||
- With the HCEX names, results must be in the initialised group.
|
||||
- It follows the landed precedent: 69faf435, the render_media / fog / shadows zero-initialised owners, and this lane's rasterizer_xbox_shadows statics.
|
||||
- Unlike the held models .bss item, it contradicts no first-party structure: HCEX has these as File Statics.
|
||||
- The `= FALSE` on warned is also load-bearing, but it already exists on the latch and matches the landed dynavobgeom idiom.
|
||||
5. P1 is not an object admission. submit_for_cluster (x87 order), draw (+0x31c / +0x738) and the owner-gated reset stay residual. After P1, object_audit fails only on those 3 code sections.
|
||||
|
||||
No amended patch is needed; the worker's P1 patches are verified as-is.
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
# REVIEW source/rasterizer/xbox/rasterizer_xbox_models
|
||||
|
||||
approve: True
|
||||
|
||||
## per_object
|
||||
null
|
||||
|
||||
## checks
|
||||
All work is in C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\review4_rasterizer_xbox_models\ (LEDGER.md sections V1-V9, REVIEW.md). Tree 16542e46; git status was clean (0 entries) before and after.
|
||||
|
||||
1. Patch check. `git apply --check` of P7 on the current tree is clean. I derived the candidate myself (CRLF kept, the one include line deleted) and it matches the worker's cand/interface/rasterizer_xbox_models.c byte for byte.
|
||||
|
||||
2. Gate. `gate.py --source prod.c --all` and `--source cand_p7.c --all` give identical rows: 12 exact, 2 residual (`__rasterizer_model_draw` [relocs 348!=350, sha]; `_rasterizer_model_draw_environment_shader` [sha]).
|
||||
|
||||
3. Raw object comparison. I wrote my own comparer (rawcmp.py): every section's bytes, flags and relocations by symbol name, plus the full symbol table including COMDAT aux records. prod vs cand_p7 is 71/71 sections and 233/233 symbols. The only difference is the `.file` aux (source path). The same holds against build/base. The park hashes are unchanged: draw 89b0d7ea and env 5179768e, both equal to config/parked.json.
|
||||
|
||||
4. P1 interaction, reproduced with a shadow hud_draw.h (git blob plus P1, identical to the worker's header; the redirect harness control is inert).
|
||||
- P1 without P7: `__rasterizer_model_transparent_geometry_submit` goes EXACT -> residual [sha]. Only that section changes, and no `_check_stack_buffer` COMDAT appears.
|
||||
- P1 with P7: production bytes, because the TU no longer includes hud_draw.h.
|
||||
|
||||
5. Warnings. A `/W3 /Zs` census (my own copy, temp file kept in the slug) finds 13 warnings in both versions, the same multiset. The pre-existing C4013 shifts by one line; there is no new C4013.
|
||||
|
||||
6. Dead-include evidence.
|
||||
- Grep for all 27 names hud_draw.h declares: 0 hits, except `struct bitmap_data`, which rasterizer.h and render.h already declare before its use at line 337.
|
||||
- hud_draw.h's own includes are already in the TU: integer_math.h via bitmap_color_conversion.h, and real_math.h directly.
|
||||
- git provenance: 635bd83d added the include while hud_draw.h declared `real_argb_color_to_pixel32` and `real_rgb_color_to_pixel32`, which models.c called. The owner's ed3e308a moved the ARGB prototype to bitmap_color_conversion.h, which models already includes.
|
||||
|
||||
7. object_audit. The output text is identical for prod and cand: FAIL(7) = the 2 parked .text sections plus 5 XDK wrapper storage rows, which the separately reviewed symbols.json packet fixes.
|
||||
|
||||
8. Surplus and links.
|
||||
- surplus_identity: the 3 code COMDATs are IDENTICAL.
|
||||
- provider_link on cand_p7.obj: 16/16 PASS in both orders.
|
||||
- build/report.json: data 1912/1912.
|
||||
|
||||
9. Consumer grep. `grep -rl 'hud_draw\.h' source` finds 23 .c files and no header that includes it, matching the worker's list.
|
||||
|
||||
10. K-oracle (lab only: K dummy enum constants at the include position, never landed).
|
||||
- Production: submit is exact at K=0..3, 5 and 27..30. This reproduces the worker's oracle.
|
||||
- With P7: submit is exact at K=0..10, 12..15 and 24..30.
|
||||
- All other exact rows stay exact at every K. P7 widens the tolerance rather than placing submit on a knife edge.
|
||||
|
||||
11. Composition with the models worker's wave-4 production.patch (scratch\w\rasterizer_xbox_models). The two patches apply in either order.
|
||||
- production.patch alone: draw 771bf2e7 (= its parked.patch).
|
||||
- production.patch + P7: 12/2 and submit stays exact, but draw becomes d0f694cc2484838753ad6add239c2493bfd8b345ecc4b7008df7f8c9323f192b.
|
||||
|
||||
12. House rules, strip test and owner-gated classes. The diff only deletes a line: no added decoration, name, prototype, scope, view, COMDAT or symbols.json edit. P7 is itself the plain spelling, so the strip test passes trivially. It adds no section 8/9 blocker.
|
||||
|
||||
## issues
|
||||
P7 is approved as-is. It is a zero-credit, byte-inert removal of a dead include. The notes below are for the integrator and owner; none is a defect in the patch.
|
||||
|
||||
(1) This is not an admission of rasterizer_xbox_models. The object stays at 12/14 functions with 2 parks (draw, env). object_audit still fails with FAIL(7): the 2 parked sections plus 5 wrapper storage rows, which the sibling symbols.json packet fixes. The TU-local struct views and the C4013 debt are also still there. Read ADMISSION_FIX_PROPOSED as "takes models out of the hud_draw.h P1 packet's blast radius", not as closing models.
|
||||
|
||||
(2) Land P7 together with P1, or before it. P1 without P7 turns `__rasterizer_model_transparent_geometry_submit` (1,296 B) from exact to residual. I reproduced that.
|
||||
|
||||
(3) Composition hazard. If the models worker's wave-4 production.patch and parked.patch also land, the combined tree moves the zero-credit draw park body:
|
||||
- the draw normalized_sha256 becomes d0f694cc2484838753ad6add239c2493bfd8b345ecc4b7008df7f8c9323f192b (5168/348);
|
||||
- parked.patch expects 771bf2e7 and parked.json expects 89b0d7ea, so both would be wrong;
|
||||
- env (a4a4ca43) and submit (exact) are unaffected.
|
||||
|
||||
In that case, re-baseline the draw park on the combined tree, including objdiff_percent, or the parks go stale and PROGRESS fails. P7 alone keeps both current park hashes.
|
||||
|
||||
(4) Disclosure for the owner. P7 changes bytes only in combination with P1. I do not class it as declared-name-count compensation (the held Layer-2 class), because the include was not chosen by count. It is provably dead: no hud_draw.h name is used, and no warning changes. git history documents it as residue of the owner's own ed3e308a ARGB migration. It is byte-inert on its own. There is no first-party evidence of January's include list either way. If the owner still objects, the worker's P-A fallback applies: a focused header included only by the 5 sentinel TUs, measured identical.
|
||||
|
||||
(5) Housekeeping. I left gate.py's usual scratch/_gate_<pid>.c/.obj temporaries in scratch/ and did not delete them, because they are outside my slug.
|
||||
|
||||
Production change: apply C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\hud_stack_check\patches\P7_rasterizer_xbox_models_c_drop_dead_hud_draw_include.patch unchanged. It deletes only `#include "interface/hud_draw.h"` from source/rasterizer/xbox/rasterizer_xbox_models.c, and `git apply --check` is clean on 16542e46. No amended patch is needed. Evidence and notes are in C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\review4_rasterizer_xbox_models\REVIEW.md and LEDGER.md.
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
# REVIEW source/rasterizer/xbox/rasterizer_xbox_models (ownership: config/symbols.json storage for the 5 XDK D3DINLINE wrappers)
|
||||
|
||||
approve: True
|
||||
|
||||
## per_object
|
||||
null
|
||||
|
||||
## checks
|
||||
All checks ran against tree 16542e46. git status was clean before and after (0 porcelain lines), and no stray LEDGER.md exists.
|
||||
|
||||
1. Patch mechanics:
|
||||
- `git apply --check scratch/w/rasterizer_xbox_models/symbols.patch` is clean.
|
||||
- I derived the edit independently: python, CRLF preserved, each line's file_offset asserted, then `, "static": true` appended on lines 5844, 5845, 5847, 5848 and 5849. The result is byte-identical to the worker's full copy.
|
||||
- `git apply --directory` onto a copy in my slug also gives the worker's copy byte-for-byte.
|
||||
- Both files have 23,852 lines, and exactly those 5 lines differ.
|
||||
|
||||
2. Storage evidence:
|
||||
- None of the 5 names is in `scratch/tools/cachebeta_publics.txt`.
|
||||
- I mapped the file offsets through cachebeta.exe's section table, read as data only. The RVAs are 0x15a150, 0x15a300, 0x15a740, 0x15a960 and 0x15a9c0, and no public of any name sits at any of them. The neighbouring publics `__rasterizer_models_begin` (0x15a9d0) and `__rasterizer_model_draw` (0x15bdf0) confirm the mapping.
|
||||
- The image holds 17 to 19 separate copies of each wrapper. External definitions could not coexist, and SELECT_ANY copies would be deduplicated, so every copy is file-local.
|
||||
- The d3d8.h used by the build has `#define D3DINLINE static __forceinline`, and all 5 wrappers are D3DINLINE.
|
||||
- Our production object already emits all 5 as storage class 3.
|
||||
- Precedent: commit 6e3e2d35 landed the same class for dynavobgeom's nine wrappers, and the shadows, lights, water and decals rows are static.
|
||||
- This is not a held item, and there is no admission-rejection or park entry for this change.
|
||||
|
||||
3. csplit regeneration in my own slug:
|
||||
- I ran `build/tools/csplit.exe -i cachebeta.exe` with config/* plus the patched symbols.json: rc 0, 833 objects.
|
||||
- An unpatched regeneration from config/ equals build/split for all 833 objects, so build/split is current.
|
||||
- Patched against unpatched, only `rasterizer_xbox_models.obj` differs, by exactly 5 bytes: the storage-class bytes change from 2 to 3.
|
||||
- All 46 coff_compare section infos are identical between the two splits, so no gate row can move.
|
||||
- A census of all 833 patched objects finds no UNDEF reference to any of the 5 names, so making them static orphans nothing.
|
||||
|
||||
4. Audit against the regenerated split, using a copy of object_audit with a split-root option:
|
||||
- Production build/base: 58/58 symbols equal, FAIL(2). The two failures are only the known residual .text sections. Against the current split the result is FAIL(7), the extra 5 being these storage differences.
|
||||
- A fresh gate compile of the production source and the worker's g6.obj give the same result: 58/58, FAIL(2).
|
||||
- A copy of pdb_storage pointed at the regenerated split reports 0 disagreements (it was 5).
|
||||
|
||||
5. Gate on the production source: exact 12, residual 2 (draw [relocs 348!=350, sha], env [sha]). Unchanged.
|
||||
|
||||
6. objdiff-cli 3.3.1 mini-project (target current vs regenerated, base = build/base):
|
||||
- The per-function report is identical for the two targets.
|
||||
- The unit scores 96.91414, code 4111/12379, data 1912/1912, 12 matched functions, which reproduces build/report.json.
|
||||
|
||||
7. surplus_identity: 3 candidate-only code COMDATs, all IDENTICAL. provider_link: SELECTED-PROVIDER LINK PASS. Neither is affected by this packet.
|
||||
|
||||
Notes are in `scratch/w/review4_rasterizer_xbox_models__ownership_/REVIEW.md` and `LEDGER.md`. The regenerated split, audit outputs and objdiff project are in the same slug.
|
||||
|
||||
## issues
|
||||
No blocking issues. I approve the packet as-is, with no amendment.
|
||||
|
||||
Integrator notes:
|
||||
- **Credit:** the packet earns zero credit. It only removes the 5 symbol-storage differences; the object is still incomplete because of the two residual functions and the TU-local view debt recorded in the worker ledger.
|
||||
- **Split regeneration:** build/split must be regenerated after applying. Only `rasterizer_xbox_models.obj` changes.
|
||||
- **Git EOL behaviour:** the HEAD blob of symbols.json is LF-normalised while the working tree is CRLF. The patch and full copy match the working tree, and `git apply --check` passes against it.
|
||||
- **Out of scope:** the worker's `.c` production.patch and parked.patch are not covered by this review and need their own adversarial review.
|
||||
- **Possible follow-up, not reviewed:** some rasterizer_xbox wrapper rows (for example symbols.json lines 5502, 5503 and 5512) are still non-static. This is not part of this packet.
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
# source/math/geometry (provider repair that unblocks collision_bsp's link)
|
||||
|
||||
## verdict
|
||||
ADMISSION_FIX_PROPOSED
|
||||
|
||||
## newly_exact_functions
|
||||
[]
|
||||
|
||||
## candidate_files
|
||||
[
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\collision_bsp\\geom\\g1.c",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\collision_bsp\\geometry_provider_repair.patch"
|
||||
]
|
||||
|
||||
## production_changes
|
||||
C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\collision_bsp\geometry_provider_repair.patch, a separate unit patch (git apply --check clean together with production.patch). In source/math/geometry.c it deletes `#define plane2d_distance_to_point plane2d_distance_to_point_inline` and `#undef plane2d_distance_to_point` around `#include "real_math.h"`. It also deletes the hand-written `real plane2d_distance_to_point(...)` body at line 546, so the genuine real_math.h __inline is used. This is the same pattern as the landed Layer-1 repairs. No header is changed.
|
||||
|
||||
## evidence
|
||||
Candidate geom\g1.c: the geometry gate stays at 27 exact / 3 residual. Every geometry function's normalized hash is unchanged, including the 3 parked residuals, so there is no park drift. `_plane2d_distance_to_point` is EXACT at 32 B and is now emitted with SELECT_ANY (2) instead of NODUP (1). object_audit output is byte-identical before and after. In our build only geometry.obj and collision_bsp.obj define the symbol. Linking collision_bsp base.obj with g1.obj gives no LNK2005 and no LNK1169 in either order. The current tree fails that link, because the bsp2d sphere/pill reopen made collision_bsp emit the used-inline COMDAT. Authenticity argument: January's collision_bsp also uses the inline, so it emitted that COMDAT too (owner-accepted lab law, ruling 20260921 #5), and January still linked. That is only possible if geometry's copy was select-any, i.e. the header inline.
|
||||
|
||||
## blockers
|
||||
None for this patch. The integrator should run the usual full build and stable sweep.
|
||||
|
||||
## reopen_criteria
|
||||
null
|
||||
|
||||
## task notes
|
||||
No function became exact. The tracked tree was never edited and git status is clean. All filler, dead-local and sink variants were lab instruments only and must never land. There are two landable admission packets, independent of each other: (a) production.patch plus the symbols.json line edit (static storage for _collision_bsp_usage_times, followed by a csplit-only regen of collision_bsp); (b) geometry_provider_repair.patch, which fixes a provider LNK2005 introduced when the bsp2d reopen started emitting _plane2d_distance_to_point from collision_bsp. Please add collision_bsp to the list of objects the held P1 cross_product2d item blocks. New mechanism facts, useful for other x87 ties: (1) the in-function j/k term order flips with one live operator between two dots and does not respond to TU names; (2) inline-temp M8 ordinals respond to named locals declared after the operand local (a tail local fixes the node i-terms) and to later helper composition, while inline sites added after a dot are inert; (3) VC7 performs self tail-recursion elimination, so the /Od recursive form and the while loop give identical bytes.
|
||||
ledger: C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\collision_bsp\LEDGER.md (every probe: hypothesis, evidence, change, result; sections 0-3). Lab tools in C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\collision_bsp\tools\: dots.py (x87 dot term and operand-order signature), c4.py (class-4 interleave signature), dsweep.py (M8 dead-local instrument, lab only), probe_many.py, fnedit.py, sweep.py (TU-name oracle, lab only).
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
# source/physics/collision_bsp::_bsp3d_test_pill_recursive
|
||||
|
||||
## verdict
|
||||
NO_PROGRESS
|
||||
|
||||
## newly_exact_functions
|
||||
[]
|
||||
|
||||
## candidate_files
|
||||
[
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\collision_bsp\\pv2.c",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\collision_bsp\\pv2.vs_tree.diff",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\collision_bsp\\od_pill3d.txt"
|
||||
]
|
||||
|
||||
## production_changes
|
||||
none (the best reconstruction, pv2, is not landable: it emits new header COMDATs from a non-exact caller, which is P1 class)
|
||||
|
||||
## evidence
|
||||
The residual splits into four classes. (1) M8 i-term operand orders at n1 0x3c, n2 0x59, L1 0x23e and L2 0x265. pv2 fixes all four: the /Od 2020 helper-form leaf (projection_from_vector3d, point_from_line3d x4, plane3d_negate) plus the /Od node locals `distance, dot, distance0 = distance, distance1 = distance + dot`. pv2 is 26 hunks against 30 for base. The helper leaf removes exactly 8 named locals, which is why Lane B's P2 was inert. Neither the node locals alone (pb1/pb2) nor dropping point_from_line3d (pc1) fixes all four. pv2's new COMDATs, _point_from_line3d and _projection_from_vector3d, are byte-identical to January's selected copies in action_charge and decals. (2) The leaf j/k dots and (3) the 0x3cc k,i,j term order are the SAME parity bit as the sphere: on pv2, the long-stack_index or no-NONE instrument flips both classes. (4) The int/x87 interleave at 0x4da, 0x4ea, 0x520 and 0x52c (tools\c4.py signature) is unaffected by the D sweep, by the parity bit, by helper versus expansion, by a nested return value and by operand order. The /Od-form push `(x & LONG_MAX) | (front ? LONG_MIN : 0)` is worse (p1).
|
||||
|
||||
## blockers
|
||||
The shared parity bit, the class-4 scheduler interleave, and the P1 rule that bars new header COMDATs from a fuzzy caller.
|
||||
|
||||
## reopen_criteria
|
||||
Start from pv2. Reopen when two facts are in hand: the shared parity-bit fact (the same one as the sphere), and a fact about the class-4 interleave between the point_from_line3d x87 computation and the project_point3d argument setup. January emits its integer ops one x87 op later in both blocks. Land only if the result is strict exact, so the two new COMDATs qualify under ruling 20260921 #5.
|
||||
|
||||
## task notes
|
||||
No function became exact. The tracked tree was never edited and git status is clean. All filler, dead-local and sink variants were lab instruments only and must never land. There are two landable admission packets, independent of each other: (a) production.patch plus the symbols.json line edit (static storage for _collision_bsp_usage_times, followed by a csplit-only regen of collision_bsp); (b) geometry_provider_repair.patch, which fixes a provider LNK2005 introduced when the bsp2d reopen started emitting _plane2d_distance_to_point from collision_bsp. Please add collision_bsp to the list of objects the held P1 cross_product2d item blocks. New mechanism facts, useful for other x87 ties: (1) the in-function j/k term order flips with one live operator between two dots and does not respond to TU names; (2) inline-temp M8 ordinals respond to named locals declared after the operand local (a tail local fixes the node i-terms) and to later helper composition, while inline sites added after a dot are inert; (3) VC7 performs self tail-recursion elimination, so the /Od recursive form and the while loop give identical bytes.
|
||||
ledger: C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\collision_bsp\LEDGER.md (every probe: hypothesis, evidence, change, result; sections 0-3). Lab tools in C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\collision_bsp\tools\: dots.py (x87 dot term and operand-order signature), c4.py (class-4 interleave signature), dsweep.py (M8 dead-local instrument, lab only), probe_many.py, fnedit.py, sweep.py (TU-name oracle, lab only).
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
# source/physics/collision_bsp::_bsp3d_test_sphere_recursive
|
||||
|
||||
## verdict
|
||||
NO_PROGRESS
|
||||
|
||||
## newly_exact_functions
|
||||
[]
|
||||
|
||||
## candidate_files
|
||||
[
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\collision_bsp\\s1.c",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\collision_bsp\\s1.vs_tree.diff",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\collision_bsp\\od_sphere3d.txt",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\collision_bsp\\hcex_lines.txt"
|
||||
]
|
||||
|
||||
## production_changes
|
||||
none
|
||||
|
||||
## evidence
|
||||
The residual is one pair: the leaf plane-distance dot at T 0x1e7. January emits the terms j,k,i; ours emits k,j,i. The instruction count (287/287) and relocations (22) are equal, and the node dot matches. /Od 0x7aafe0 readout (od_sphere3d.txt) reads like our body, and three /Od-attested shapes were byte-identical to base: s1, the full /Od helper leaf (point_from_line3d, projection_from_vector3d, projection_sign); s2, the /Od tail-call recursion form (VC7 performs tail-recursion elimination and reproduces January's loop exactly); s4, the /Od `count + first` loop bound. The TU-name oracle (0-24 names before the function) changed no hash. H-FOR (a while-loop increment created after the dot) was refuted, and the while-form stack loop changes the code. Lab L1sp shows that adding one live operator anywhere in the shared leaf walk flips BOTH bsp3d functions' leaf dots to January's order. A diagnostic map found that each single op tested between the node dot and the leaf dot toggles the order (dropping `| LONG_MIN`, `& LONG_MAX` or the NONE test, or a long stack_index). No /Od- or HCEX-attested construct differs in that region.
|
||||
|
||||
## blockers
|
||||
A hidden parity key: January has an odd count of extra distinct live operator expressions between the node dot and the leaf dot. No natural, attested construct was found. Stop rule reached; Lane B had already spent 50+ lab points here.
|
||||
|
||||
## reopen_criteria
|
||||
Reopen for a January-era source fact that adds or removes exactly one live operator expression in the shared node-tail/leaf-walk idiom. It must flip both bsp3d functions at once. Score candidates with tools\dots.py before landing. If found, the base form or s1 (its COMDATs are byte-identical to January's) becomes exact.
|
||||
|
||||
## task notes
|
||||
No function became exact. The tracked tree was never edited and git status is clean. All filler, dead-local and sink variants were lab instruments only and must never land. There are two landable admission packets, independent of each other: (a) production.patch plus the symbols.json line edit (static storage for _collision_bsp_usage_times, followed by a csplit-only regen of collision_bsp); (b) geometry_provider_repair.patch, which fixes a provider LNK2005 introduced when the bsp2d reopen started emitting _plane2d_distance_to_point from collision_bsp. Please add collision_bsp to the list of objects the held P1 cross_product2d item blocks. New mechanism facts, useful for other x87 ties: (1) the in-function j/k term order flips with one live operator between two dots and does not respond to TU names; (2) inline-temp M8 ordinals respond to named locals declared after the operand local (a tail local fixes the node i-terms) and to later helper composition, while inline sites added after a dot are inert; (3) VC7 performs self tail-recursion elimination, so the /Od recursive form and the while loop give identical bytes.
|
||||
ledger: C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\collision_bsp\LEDGER.md (every probe: hypothesis, evidence, change, result; sections 0-3). Lab tools in C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\collision_bsp\tools\: dots.py (x87 dot term and operand-order signature), c4.py (class-4 interleave signature), dsweep.py (M8 dead-local instrument, lab only), probe_many.py, fnedit.py, sweep.py (TU-name oracle, lab only).
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
# source/physics/collision_bsp::_collision_surface_test_sphere
|
||||
|
||||
## verdict
|
||||
BLOCKED
|
||||
|
||||
## newly_exact_functions
|
||||
[]
|
||||
|
||||
## candidate_files
|
||||
[
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\collision_bsp\\owner_gated_asm.c",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\collision_bsp\\owner_gated_asm.vs_tree.diff"
|
||||
]
|
||||
|
||||
## production_changes
|
||||
none
|
||||
|
||||
## evidence
|
||||
owner_gated_asm.c is Lane B's variantA: base plus the unit-local `fast_distance_squared3d` SSE __asm macro. It still gates EXACT 880 at 16542e46 (28 exact / 2 residual), with no new symbols. Without the asm, the natural scalar body is 848 B with frame 0x24 against January's 0x2c. The packed shufps 0x0E/0x39 kernel is unique in the image. The /Od RTC locals dsqr and vec and HCEX's `v` were already presented to the owner by Lane B, so there is no new evidence.
|
||||
|
||||
## blockers
|
||||
Owner ruling 20260915: keep it parked, and no new __asm enters production.
|
||||
|
||||
## reopen_criteria
|
||||
The owner admits the unit-local asm macro, or authenticated January source for the packed reduction turns up.
|
||||
|
||||
## task notes
|
||||
No function became exact. The tracked tree was never edited and git status is clean. All filler, dead-local and sink variants were lab instruments only and must never land. There are two landable admission packets, independent of each other: (a) production.patch plus the symbols.json line edit (static storage for _collision_bsp_usage_times, followed by a csplit-only regen of collision_bsp); (b) geometry_provider_repair.patch, which fixes a provider LNK2005 introduced when the bsp2d reopen started emitting _plane2d_distance_to_point from collision_bsp. Please add collision_bsp to the list of objects the held P1 cross_product2d item blocks. New mechanism facts, useful for other x87 ties: (1) the in-function j/k term order flips with one live operator between two dots and does not respond to TU names; (2) inline-temp M8 ordinals respond to named locals declared after the operand local (a tail local fixes the node i-terms) and to later helper composition, while inline sites added after a dot are inert; (3) VC7 performs self tail-recursion elimination, so the /Od recursive form and the while loop give identical bytes.
|
||||
ledger: C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\collision_bsp\LEDGER.md (every probe: hypothesis, evidence, change, result; sections 0-3). Lab tools in C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\collision_bsp\tools\: dots.py (x87 dot term and operand-order signature), c4.py (class-4 interleave signature), dsweep.py (M8 dead-local instrument, lab only), probe_many.py, fnedit.py, sweep.py (TU-name oracle, lab only).
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
# source/physics/collision_bsp (whole object: admission)
|
||||
|
||||
## verdict
|
||||
ADMISSION_FIX_PROPOSED
|
||||
|
||||
## newly_exact_functions
|
||||
[]
|
||||
|
||||
## candidate_files
|
||||
[
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\collision_bsp\\st1.c",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\collision_bsp\\production.patch",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\collision_bsp\\config\\symbols.json",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\collision_bsp\\LEDGER.md"
|
||||
]
|
||||
|
||||
## production_changes
|
||||
C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\collision_bsp\production.patch (git apply --check clean). It changes one line in source/physics/collision_bsp.c, line 305: `struct collision_bsp_usage_times collision_bsp_usage_times = { 0 };` becomes `static struct collision_bsp_usage_times collision_bsp_usage_times = { 0 };`. It needs a matching config/symbols.json edit. The edited full copy is C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\collision_bsp\config\symbols.json. The only change is line 23117, edited in place: `{ "file_offset": 4550320, "flags": 0, "name": "_collision_bsp_usage_times" },` becomes `{ "file_offset": 4550320, "flags": 0, "name": "_collision_bsp_usage_times", "static": true },`. After that, a csplit-only regen of collision_bsp is needed. No header is touched and no other TU names the variable. The object still cannot complete; see blockers.
|
||||
|
||||
## evidence
|
||||
pdb_storage.py reports that `_collision_bsp_usage_times` has split storage 2 and ours 2, but it is not a cachebeta.pdb public, while neighbouring data publics are listed (_collision_usage_current_period, _global_collision_log_enable). Only collision_bsp.obj defines it; no January split object references it, and no other source file uses it. So it was file-static in January. Candidate st1.c gates 27 exact / 3 residual, unchanged. object_audit on st1.obj shows every section equal except the 3 residual functions; the only symbol difference is this storage (2/3), which the symbols.json edit resolves. .bss is 16 B and data stays at 100% in build/report.json. surplus_identity: all 21 candidate-only COMDATs are byte-identical to January's selected providers.
|
||||
|
||||
## blockers
|
||||
(1) _collision_surface_test_sphere is exact only with the owner-held SSE __asm macro (owner ruling 20260915, no new __asm). (2) _bsp3d_test_sphere_recursive and _bsp3d_test_pill_recursive share one unexplained x87 term-order parity bit. The pill also has an independent int/x87 interleave residual. (3) Provider link for the object has two LNK2005s. `_cross_product2d` conflicts with actor_combat's NODUP hand copy; this is the held P1 item, and collision_bsp is a sixth object it blocks. `_plane2d_distance_to_point` conflicts with geometry's NODUP hand copy; the geometry unit below fixes that one.
|
||||
|
||||
## reopen_criteria
|
||||
The object completes only when three things hold: the owner admits the asm macro or authenticated source appears; the shared parity-bit fact is found (see the function units); and P1 cross_product2d is admitted.
|
||||
|
||||
## task notes
|
||||
No function became exact. The tracked tree was never edited and git status is clean. All filler, dead-local and sink variants were lab instruments only and must never land. There are two landable admission packets, independent of each other: (a) production.patch plus the symbols.json line edit (static storage for _collision_bsp_usage_times, followed by a csplit-only regen of collision_bsp); (b) geometry_provider_repair.patch, which fixes a provider LNK2005 introduced when the bsp2d reopen started emitting _plane2d_distance_to_point from collision_bsp. Please add collision_bsp to the list of objects the held P1 cross_product2d item blocks. New mechanism facts, useful for other x87 ties: (1) the in-function j/k term order flips with one live operator between two dots and does not respond to TU names; (2) inline-temp M8 ordinals respond to named locals declared after the operand local (a tail local fixes the node i-terms) and to later helper composition, while inline sites added after a dot are inert; (3) VC7 performs self tail-recursion elimination, so the /Od recursive form and the while loop give identical bytes.
|
||||
ledger: C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\collision_bsp\LEDGER.md (every probe: hypothesis, evidence, change, result; sections 0-3). Lab tools in C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\collision_bsp\tools\: dots.py (x87 dot term and operand-order signature), c4.py (class-4 interleave signature), dsweep.py (M8 dead-local instrument, lab only), probe_many.py, fnedit.py, sweep.py (TU-name oracle, lab only).
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
# source/game/game_engine
|
||||
|
||||
## verdict
|
||||
OBJECT_COMPLETE_CANDIDATE
|
||||
|
||||
## newly_exact_functions
|
||||
[]
|
||||
|
||||
## candidate_files
|
||||
[
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\game_engine_finish\\final\\source\\game\\game_engine.c",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\game_engine_finish\\final\\source\\game\\game_engine.h",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\game_engine_finish\\final\\source\\game\\player_control.h",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\game_engine_finish\\final\\source\\interface\\hud_globals_definitions.h",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\game_engine_finish\\final\\source\\interface\\hud_messaging.h",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\game_engine_finish\\final\\source\\interface\\hud_nav_points.c",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\game_engine_finish\\final\\source\\interface\\hud_nav_points.h",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\game_engine_finish\\final\\source\\items\\item_collection_definitions.h",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\game_engine_finish\\final\\source\\scenario\\scenario_netgame_definitions.h",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\game_engine_finish\\final\\source\\sound\\sound_classes.h",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\game_engine_finish\\patches\\F01_game_engine_c.patch",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\game_engine_finish\\patches\\F02_new_focused_headers.patch",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\game_engine_finish\\patches\\F03a_shared_header_game_engine_h.patch",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\game_engine_finish\\patches\\F03b_shared_header_prototypes.patch",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\game_engine_finish\\patches\\F04_hud_nav_points_owner_include.patch",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\game_engine_finish\\patches\\F05h_optional_players_teleporter_index_h.patch",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\game_engine_finish\\patches\\F05c_optional_teleporter_index_c_afterF01.patch",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\game_engine_finish\\patches\\F06_optional_sibling_netgame_flag.patch",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\game_engine_finish\\patches\\F07_optional_owner_motion_sensor_view_copy.patch",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\game_engine_finish\\CONSUMERS.txt",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\game_engine_finish\\LEDGER.md"
|
||||
]
|
||||
|
||||
## production_changes
|
||||
All patches are in C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\game_engine_finish\patches\. They are LF git patches. `git apply --check` is clean for each one alone and for all together against 16542e46. The full resulting files are in ...\game_engine_finish\final\source\ (LF).
|
||||
|
||||
Land F01+F02+F03a+F03b+F04 together. F01 needs the new headers (F02), the renamed constants and members (F03a) and the prototypes (F03b) to compile.
|
||||
|
||||
- F01_game_engine_c.patch (source/game/game_engine.c). This is reviewer R01 rebased onto f7cd2e72 (2 conflicts resolved; see LEDGER F0), plus:
|
||||
- man_out uses the /Od form `boolean man_out = player->quit_out_of_game || game_engine_player_is_out_of_lives(i) || game_engine_player_is_odd_man_out(i); return man_out;`.
|
||||
- populate_statistic_buffer and postgame_statistic_get_rating: HCEX parameters (statistic_buffer, enum postgame_statistic statistic, boolean inverse). get_rating keeps a 32-bit `long inverse`, which is January's ABI. Indexed loops; match_assert followed by a separate if; the /Od locals.
|
||||
- get_player_place: `while (TRUE) { if (...) break; ... }`.
|
||||
- select_players_to_display: /Od names statistic_buffer and outside_range, plus the /Od local-player count.
|
||||
- did_player_win_default: single exit with explicit NONE/TRUE/FALSE stores (both `goto tied` removed). team_has_players: goto + else.
|
||||
- TU enums:
|
||||
- `enum game_engine_mode` (HCEX; replaces the invented mid-file postgame enum).
|
||||
- `enum postgame_statistic` (the HCEX tag; the constants have descriptive names).
|
||||
- `enum game_engine_weapons` 0..10: value 10 is `_no_grenades`, from January's behaviour.
|
||||
- `enum game_engine_vehicles` 0..4.
|
||||
- `_weapon_list_*` 0..13.
|
||||
- The continuation flag bits 3, 4 and 5.
|
||||
- These constants replace the literals in every switch table, in the postgame_state compares, in the builder stores and in the PINs.
|
||||
- Builder flags become one SET_FLAG per bit.
|
||||
- HCEX `struct netgame_goal` names (player_index / ignore_player_index / nav_index). The pad members are dropped.
|
||||
- Hand-inlines replaced with calls:
|
||||
- list_index_to_weapon_definition_index (14 sites in predict_resources, plus a `for` loop);
|
||||
- game_globals_get_weapon;
|
||||
- game_engine_infinite_grenades_internal;
|
||||
- linear_to_non_linear_alpha (x2);
|
||||
- game_engine_has_teams (x3);
|
||||
- get_place_string (x2);
|
||||
- game_engine_test_flag and game_engine_test_trait.
|
||||
- weapon_definition_index_to_list_index: /Od indexed form.
|
||||
- game_engine_update: the invented `union game_engine_update_iterator` is removed. Three disjoint block-scoped iterators, per-player helper calls, a single `if (game_engine)` exit, and the function-pointer staging temp is removed.
|
||||
- GET_GAME_ENGINE_HUD_FORMAT local macro replaced by /Od statement form with a `format` local.
|
||||
- HCEX message parameter names (message/message_data/buffer/buffer_size).
|
||||
- F02_new_focused_headers.patch (NEW files): hud_globals_definitions.h, hud_nav_points.h, item_collection_definitions.h and scenario_netgame_definitions.h. These are R02, plus the HCEX `_netgame_starting_equipment_flag_no_grenades_bit` / `_plasma_greandes_bit` (sic) enum in scenario_netgame_definitions.h, whose only includer is game_engine.c.
|
||||
- F03a_shared_header_game_engine_h.patch (SHARED HEADER, 37 consumer TUs). Contents:
|
||||
- R03's game_engine.h hunks: float->real, `short local_player_index`, and the two multiplayer-sound prototypes.
|
||||
- Flag-bit renames to HCEX semantics: disable_dynamic_lighting, disable_integrated_lights, 5_or_more_players, allow_friendly_navpoints.
|
||||
- `unknown2C` -> `pregame_post_rasterize` and `unknown44` -> `update`.
|
||||
- Parameter renames in format_message and set_goal_position.
|
||||
- The declared-name count is the same as HEAD+R03. Adding the three new bits to the header broke the units and network_client_message_handler canaries, so those bits are TU-local.
|
||||
- Consumers: ai/encounters camera/dead_camera game/{game, game_engine, game_engine_ctf, game_engine_king, game_engine_list, game_engine_oddball, game_engine_race, game_engine_slayer, game_globals, game_statistics, players} interface/{hud, hud_messaging, hud_unit, interface, motion_sensor, player_ui, ui_widget} items/{items, projectiles, weapons} main/main math/random_math networking/{network_client_manager, network_client_message_handler, network_game_manager, network_server_manager, network_server_message_handler} objects/{damage, object_lights, objects} render/render `saved games/playlist_profile` units/{bipeds, units}.
|
||||
- F03b_shared_header_prototypes.patch (SHARED HEADERS, R03 unchanged):
|
||||
- player_control.h, 21 consumers: ai/ai_debug camera/{bored_camera, director, editor_flying_camera, following_camera} effects/player_effects game/{aim_assist, game, game_engine, player_control, players} hs/hs_library_external input/input_abstraction interface/{first_person_weapons, hud, hud_draw, hud_weapon, interface, motion_sensor, ui_widget} main/main.
|
||||
- hud_messaging.h, 8 consumers: game/game_engine game/players hs/hs interface/{hud, hud_messaging, interface, player_ui} `saved games/game_state`.
|
||||
- sound_classes.h, 6 consumers: game/game game/game_engine sound/{game_sound, sound_classes, sound_definitions, sound_manager}.
|
||||
- The full list is in ...\game_engine_finish\CONSUMERS.txt.
|
||||
- F04_hud_nav_points_owner_include.patch (source/interface/hud_nav_points.c) = R04.
|
||||
- OPTIONAL, verified on top:
|
||||
- F05h + F05c: players.h `unknown70` -> `teleporter_index` (71 consumers) plus the game_engine.c part regenerated after F01.
|
||||
- F06: R06, sibling engines include scenario_netgame_definitions.h.
|
||||
- F07 (OWNER): the /Od-attested motion-sensor view copy.
|
||||
- config/symbols.json: no change.
|
||||
|
||||
## evidence
|
||||
Every step is in ...\game_engine_finish\LEDGER.md (F0-F16). Lab variants are in lab/.
|
||||
|
||||
- Rebase check: the rebased R01-R04 packet alone at HEAD gives 180/180, and the 446-TU sweep gives 445 SAME plus game_engine's raw reloc spelling.
|
||||
- Final packet, compiled from an independent shadow_F (`git archive HEAD source` + F01..F04 == final/ byte-for-byte), with production cflags:
|
||||
- 180/180 EXACT vs build/split.
|
||||
- 0 of 302 section-defining symbols changed vs build/base.
|
||||
- Symbol multiset identical (853/853).
|
||||
- object_audit PASS; the audit text is identical to production's.
|
||||
- provider_link PASS.
|
||||
- 11 surplus COMDATs, all identical.
|
||||
- pdb_storage 0 disagreements.
|
||||
- objdiff-cli 3.3.1 mini-report: production and final both 27922/32397 code, 173/180 fns (the 7 undercredited are pre-existing) and 3792/3792 data, with 0 per-function deltas.
|
||||
- No parks and no admission rejections for this object.
|
||||
- Full sweep of 446 TUs vs build/base: 445 SAME. game_engine differs only in:
|
||||
- (a) section order: C2 now emits update_player_always_invis later, because it calls test_trait, which this file defines later. Production's order already differs from January's.
|
||||
- (b) the known `_global_goal+0x400` spelling of `_global_variant+0`. The resolved target is identical and coff_compare reports EXACT.
|
||||
- Control sweep of pristine HEAD: 446 SAME.
|
||||
- With the optional F05-F07 on top: 180/180, and the sweep result is the same.
|
||||
- /W3: only game_engine.c changes. C4013 is gone. A C4244 long->boolean is added; it is January's ABI, proven by a dword read in get_rating and a byte read in populate.
|
||||
|
||||
Key /Od attestations:
|
||||
- man_out 0x5a0b90: named byte local assigned from the || chain.
|
||||
- populate 0x5b5e60: the assert-anchor span of 53 lines equals January's (712/765 vs 1162/1215), and generate_title_string's anchor keeps the same +450 offset.
|
||||
- update 0x5aea50: calls update_player_always_invis 0x5af860, which calls test_trait 0x5ae9c0.
|
||||
- Two lookup helpers: list_index 0x5b4150 calls game_globals_get_weapon 0x5b1170; post_rasterize_in_game and target_name call linear_to_non_linear_alpha 0x5b4100.
|
||||
- Other helper calls: title/in_game_score call has_teams 0x5a06a0; post_game/in_game_score call get_place_string 0x5b2000; internal_rasterize_score calls game_engine_test_flag(1).
|
||||
- Weapon set 10: the decoded /Od jump tables give set 13 (no_grenades) January's set-10 behaviour.
|
||||
- The /Od functions are laid out alphabetically; odmap.py maps them and diffs call edges.
|
||||
|
||||
## blockers
|
||||
None of the section-8(g) blocker classes remain. The owner needs to decide:
|
||||
|
||||
- Motion-sensor copy. Both forms are EXACT.
|
||||
- The default keeps the reviewer's in-loop `struct netgame_goal *goal` alias, which is not in the /Od 0x5a20e0 frame.
|
||||
- F07 is the /Od-attested one-statement copy `positions[count] = *(real_point2d *)&global_goal[goal_index].position;`. It is load-bearing (direct component copies pick the +4 strength-reduction base), so the house rules make it owner-gated.
|
||||
- Policy items, all disclosed in the LEDGER:
|
||||
- descriptive `_postgame_statistic_*` constant names (HCEX has only the tag);
|
||||
- set 10 named `no_grenades` against HCEX's `covenant` numbering;
|
||||
- TU-local continuation flag bits 3/4/5, because game_engine.h's declared-name count is fragile;
|
||||
- the /Od-attested dead `local_player_count` and the strip-inert `= 0` inits.
|
||||
- Zero-credit follow-ups, not done:
|
||||
- `extern` COMMON globals that the pool places in game_engine.c;
|
||||
- engine test_flag, trait and sound literals, which would need count-fragile game_engine.h names.
|
||||
|
||||
## reopen_criteria
|
||||
- The owner rules on F07 against the alias. On F07 the object needs no further source work.
|
||||
- Or a reviewer finds another missing /Od helper call among the 141 /Od functions not yet mapped (tools: odmap.py plus odmap_extra.json in the slug).
|
||||
- Any future game_engine.h edit must leave the declared-name count unchanged. Sweep units and network_client_message_handler first; +3 names and -2 names both flipped `_unit_preprocess_node_orientations`.
|
||||
|
||||
## task notes
|
||||
No tracked file was modified; git status stays clean at 16542e46. All work is under scratch/w/game_engine_finish/.
|
||||
|
||||
**Evidence tools (all in the slug):**
|
||||
- rcompile.py, rcompile_F.py, rcompile_O.py: production-cflag shadow compiles.
|
||||
- rsweep.py: 446-TU sweep.
|
||||
- rconsumers.py and warnfilter.py: consumer census and /W3 comparison.
|
||||
- make_patches.py: patch generation.
|
||||
- lab/*.py: edit generators. The lab/*.json edit sets are applied in combine.py order.
|
||||
- od_scan.py and odmap.py: /Od build call-edge census. The /Od functions are sorted alphabetically per TU.
|
||||
|
||||
**Incident-rule note:** once, `rm -rf` ran on a relative slug path after a `cd` in the same chain. The target was inside my own slug (scratch/w/game_engine_finish/shadow_F) and nothing else was touched. Every later destructive command used absolute slug paths.
|
||||
|
||||
**Integrator actions after the full ninja:**
|
||||
- Confirm in report.json that `_game_engine_player_get_custom_motion_sensor_positions` and `_game_engine_render_nav_points` still score 100%. The reviewer's and my objdiff 3.3.1 mini-projects both show 100%.
|
||||
- The COMMON-owner question for game_engine_globals, global_stage and timeout_for_endgame_sound is a separate zero-credit follow-up.
|
||||
ledger: C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\game_engine_finish\LEDGER.md
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
# source/interface/hud_draw
|
||||
|
||||
## verdict
|
||||
ADMISSION_FIX_PROPOSED
|
||||
|
||||
## newly_exact_functions
|
||||
[]
|
||||
|
||||
## candidate_files
|
||||
[
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\hud_stack_check\\cand\\interface\\hud_draw.h",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\hud_stack_check\\cand\\interface\\hud_draw.c",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\hud_stack_check\\patches\\P1_hud_draw_h_check_stack_buffer_inline_and_macro.patch",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\hud_stack_check\\patches\\P2_hud_draw_c_shared_stack_frame.patch"
|
||||
]
|
||||
|
||||
## production_changes
|
||||
SHARED HEADER patch P1_hud_draw_h_check_stack_buffer_inline_and_macro.patch adds four things to hud_draw.h:
|
||||
- `enum { STACK_BUFFER_LENGTH = 0x80, STACK_BUFFER_FILL = 0x62626262 };`
|
||||
- the macro `#define match_assert_stack_frame(file, line) { short corrupt_index = check_stack_buffer(stack_buffer); match_vassert(file, line, return_eip==get_return_eip(), "corrupt return address!"); match_vassert(file, line, corrupt_index==NONE, csprintf(temporary, "corrupt stack at %d!", corrupt_index)); }`
|
||||
- section markers
|
||||
- `__inline short check_stack_buffer(long *buffer)`: the unchanged hud_draw.c body, placed in the header's public code section.
|
||||
|
||||
P2_hud_draw_c_shared_stack_frame.patch changes hud_draw.c:
|
||||
- drops its plain check_stack_buffer definition, its TU-local STACK_BUFFER enum and its TU-local hud_draw_stack_buffer_check macro;
|
||||
- the 14 sites become match_assert_stack_frame("c:\\halo\\SOURCE\\interface\\hud_draw.c", N);
|
||||
- get_return_eip (naked) is unchanged.
|
||||
|
||||
P1 and P2 must land together; the header inline and the plain definition cannot coexist.
|
||||
|
||||
hud_draw.h consumer TUs for the full sweep (23; no header includes it; grep also covered paths with spaces):
|
||||
- source/interface/: hud_draw.c, hud_messaging.c, hud_nav_points.c, hud_unit.c, hud_weapon.c, motion_sensor.c, ui_widget.c
|
||||
- source/objects/widgets/lightning.c
|
||||
- source/rasterizer/: rasterizer_debug.c, rasterizer_lights.c
|
||||
- source/rasterizer/xbox/: rasterizer_xbox.c, rasterizer_xbox_debug.c, rasterizer_xbox_dynavobgeom.c, rasterizer_xbox_environment.c, rasterizer_xbox_environment_fog.c, rasterizer_xbox_models.c (P7 removes its include), rasterizer_xbox_screen_effect.c, rasterizer_xbox_shadows.c, rasterizer_xbox_transparent_geometry.c, rasterizer_xbox_water.c, shader_transparent_generic_preprocessor.c
|
||||
- source/render/: render_contrails.c, render_sprite.c
|
||||
|
||||
The canaries _bitmap_copy (bitmap_drawing.c), _rasterizer_frame_statistics_draw and _get_edge_vertex (geometry.c) do not include hud_draw.h.
|
||||
|
||||
## evidence
|
||||
Harness control: a verbatim header copy in the slug with an include-swapped TU copy is objcmp-identical for all 23 consumers.
|
||||
|
||||
Full packet sweep (h2_out), objcmp covers every owned section, anonymous sections except .debug$S, and symbol sets:
|
||||
- hud_draw: 0 differences, 22 EXACT / 1 unwritten (_fast_ftol_C) as before.
|
||||
- The emitted _check_stack_buffer is now SELECT_ANY. It is section_infos_equal to January's selected section (48 B, 0 relocs, sha c7049c3184d2ed3e, COMDAT checksum 0x4957c551 unchanged).
|
||||
- object_audit text is identical for production and candidate.
|
||||
- 18 non-sentinel consumers: 0 differences, provided P7 is applied.
|
||||
- /W3 warnings: unchanged.
|
||||
|
||||
Bisect of the v1 header on models:
|
||||
- enum only: EXACT; macro only: EXACT.
|
||||
- inline, with or without the enum, at any position: models residual.
|
||||
|
||||
## blockers
|
||||
Whole-object hud_draw admission is still blocked by pre-existing items outside this packet:
|
||||
- _fast_ftol_C is UNWRITTEN (COMDAT tail-padding / hud_draw_meter inline trade, per the n4 ledger);
|
||||
- the hud_draw _fast_ftol candidate-only rejection;
|
||||
- surplus _square_root.
|
||||
|
||||
## reopen_criteria
|
||||
Unchanged pre-existing hud_draw items: _fast_ftol_C placement/padding and the _fast_ftol veto.
|
||||
|
||||
## task notes
|
||||
**hud_unit (primary goal):** the packet makes source/interface/hud_unit an OBJECT_COMPLETE_CANDIDATE.
|
||||
|
||||
**What January's bytes settle:**
|
||||
- build/split's COMDAT selection cannot tell a header inline from a plain .c function, because csplit writes NODUP for every code COMDAT.
|
||||
- The decisive evidence is elsewhere:
|
||||
- _check_stack_buffer has zero relocations in any split object.
|
||||
- All 26 sites in 5 objects are identical inlined return-merges.
|
||||
- Each site uses a single line literal for both asserts (a macro).
|
||||
- The helper is PUBLIC in cachebeta.
|
||||
- The Sept-2001 map gives an 'i' (inline) flag to its sibling get_return_eip, with the 48-byte gap next to it.
|
||||
|
||||
**Packet:**
|
||||
- hud_draw.h gets:
|
||||
- `__inline short check_stack_buffer(long *buffer)`, the unchanged body;
|
||||
- the STACK_BUFFER constants;
|
||||
- `match_assert_stack_frame(file, line)`.
|
||||
- The 5 TUs use the macro. The invented gotos and the TU-local duplicates are gone.
|
||||
- All 23 hud_draw.h consumers keep every section byte+reloc identical. The only exception is the new SELECT_ANY _check_stack_buffer in hud_unit, hud_nav_points, hud_weapon and motion_sensor, which is identical to January's selected copy and pair-links in both orders against the packet's hud_draw.obj.
|
||||
- This holds only with P7, which removes rasterizer_xbox_models' dead hud_draw.h include. Without P7, the inline's declared names flip __rasterizer_model_transparent_geometry_submit.
|
||||
|
||||
**Integration:**
|
||||
- The set is atomic: P1 and P2 cannot be split, and P3-P6 also depend on P1. The P4-P6 edits are required too, because without P5 hud_weapon's residual _render_weapon_hud drifts.
|
||||
- After applying, the integrator must run a full ninja sweep plus a parks check on the live tree. Other wave-4 header packets can interact through declaration counts.
|
||||
- Two tracked files would need CRLF-safe handling: symbols.json (the slug copy keeps CRLF) and object_admission_rejections.json.
|
||||
- In this lab, repo provider_link.py reports FAIL for _check_stack_buffer only because build/base still holds the production NODUP hud_draw.obj. After the rebuild it should pass; provider_link_override.py demonstrates this.
|
||||
ledger: C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\hud_stack_check\LEDGER.md (sections R0, F1, F2, B0, C0, H1, H1b, K-oracle, L1, S1, S2, A1-A5, H2, P-A, RESULT)
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
# source/interface/hud_nav_points
|
||||
|
||||
## verdict
|
||||
ADMISSION_FIX_PROPOSED
|
||||
|
||||
## newly_exact_functions
|
||||
[]
|
||||
|
||||
## candidate_files
|
||||
[
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\hud_stack_check\\cand\\interface\\hud_nav_points.c",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\hud_stack_check\\patches\\P4_hud_nav_points_c_shared_stack_frame.patch"
|
||||
]
|
||||
|
||||
## production_changes
|
||||
P4_hud_nav_points_c_shared_stack_frame.patch:
|
||||
- Both goto sentinel blocks become match_assert_stack_frame("c:\\halo\\SOURCE\\interface\\hud_nav_points.c", 675); and (..., 496);. The labels were corrupt_stack_found_custom_render_nav_point/stack_buffer_checked_* and corrupt_stack_found/stack_buffer_checked.
|
||||
- `long stack_buffer[0x80];` becomes `long stack_buffer[STACK_BUFFER_LENGTH];` (x2).
|
||||
- Depends on P1.
|
||||
|
||||
## evidence
|
||||
Full-packet sweep:
|
||||
- gate rows unchanged: 31 EXACT / 1 residual (parked _custom_render_nav_point, bytes identical, no park drift).
|
||||
- objcmp: the only difference is the new external ANY _check_stack_buffer, which is IDENTICAL to January's selected hud_draw copy. Its pair link against the packet's hud_draw.obj passes in both orders.
|
||||
- All other surplus: IDENTICAL.
|
||||
- object_audit: only the added surplus line.
|
||||
- /W3 warnings: unchanged.
|
||||
|
||||
## blockers
|
||||
Whole object is still blocked by the parked _custom_render_nav_point (pre-existing). The sentinel no longer contains invented gotos.
|
||||
|
||||
## reopen_criteria
|
||||
The existing park criteria for _custom_render_nav_point.
|
||||
|
||||
## task notes
|
||||
**hud_unit (primary goal):** the packet makes source/interface/hud_unit an OBJECT_COMPLETE_CANDIDATE.
|
||||
|
||||
**What January's bytes settle:**
|
||||
- build/split's COMDAT selection cannot tell a header inline from a plain .c function, because csplit writes NODUP for every code COMDAT.
|
||||
- The decisive evidence is elsewhere:
|
||||
- _check_stack_buffer has zero relocations in any split object.
|
||||
- All 26 sites in 5 objects are identical inlined return-merges.
|
||||
- Each site uses a single line literal for both asserts (a macro).
|
||||
- The helper is PUBLIC in cachebeta.
|
||||
- The Sept-2001 map gives an 'i' (inline) flag to its sibling get_return_eip, with the 48-byte gap next to it.
|
||||
|
||||
**Packet:**
|
||||
- hud_draw.h gets:
|
||||
- `__inline short check_stack_buffer(long *buffer)`, the unchanged body;
|
||||
- the STACK_BUFFER constants;
|
||||
- `match_assert_stack_frame(file, line)`.
|
||||
- The 5 TUs use the macro. The invented gotos and the TU-local duplicates are gone.
|
||||
- All 23 hud_draw.h consumers keep every section byte+reloc identical. The only exception is the new SELECT_ANY _check_stack_buffer in hud_unit, hud_nav_points, hud_weapon and motion_sensor, which is identical to January's selected copy and pair-links in both orders against the packet's hud_draw.obj.
|
||||
- This holds only with P7, which removes rasterizer_xbox_models' dead hud_draw.h include. Without P7, the inline's declared names flip __rasterizer_model_transparent_geometry_submit.
|
||||
|
||||
**Integration:**
|
||||
- The set is atomic: P1 and P2 cannot be split, and P3-P6 also depend on P1. The P4-P6 edits are required too, because without P5 hud_weapon's residual _render_weapon_hud drifts.
|
||||
- After applying, the integrator must run a full ninja sweep plus a parks check on the live tree. Other wave-4 header packets can interact through declaration counts.
|
||||
- Two tracked files would need CRLF-safe handling: symbols.json (the slug copy keeps CRLF) and object_admission_rejections.json.
|
||||
- In this lab, repo provider_link.py reports FAIL for _check_stack_buffer only because build/base still holds the production NODUP hud_draw.obj. After the rebuild it should pass; provider_link_override.py demonstrates this.
|
||||
ledger: C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\hud_stack_check\LEDGER.md (sections R0, F1, F2, B0, C0, H1, H1b, K-oracle, L1, S1, S2, A1-A5, H2, P-A, RESULT)
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
# source/interface/hud_unit
|
||||
|
||||
## verdict
|
||||
OBJECT_COMPLETE_CANDIDATE
|
||||
|
||||
## newly_exact_functions
|
||||
[]
|
||||
|
||||
## candidate_files
|
||||
[
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\hud_stack_check\\cand01R\\hud_unit.c",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\hud_stack_check\\cand01Ralt\\hud_unit.c",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\hud_stack_check\\cand\\interface\\hud_unit.c",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\hud_stack_check\\config\\symbols.json",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\hud_stack_check\\config\\object_admission_rejections.json",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\hud_stack_check\\patches\\01RS_hud_unit_c_01R_plus_shared_stack_frame.patch",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\hud_stack_check\\patches\\01RaltS_hud_unit_c_01Ralt_plus_shared_stack_frame.patch",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\hud_stack_check\\patches\\P3_hud_unit_c_shared_stack_frame.patch",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\hud_stack_check\\patches\\02_symbols_json_hud_unit_names_static.patch",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\hud_stack_check\\patches\\03_config_json_hud_unit_matching.patch",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\hud_stack_check\\patches\\04R_admission_rejections_retire_hud_unit_fast_ftol.patch"
|
||||
]
|
||||
|
||||
## production_changes
|
||||
Apply as ONE atomic set, all in C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\hud_stack_check\patches\: P1_hud_draw_h_check_stack_buffer_inline_and_macro.patch (shared header, separate), P2_hud_draw_c_shared_stack_frame.patch, 01RS_hud_unit_c_01R_plus_shared_stack_frame.patch, P4_hud_nav_points_c_shared_stack_frame.patch, P5_hud_weapon_c_shared_stack_frame.patch, P6_motion_sensor_c_shared_stack_frame.patch, P7_rasterizer_xbox_models_c_drop_dead_hud_draw_include.patch, 02_symbols_json_hud_unit_names_static.patch, 03_config_json_hud_unit_matching.patch, 04R_admission_rejections_retire_hud_unit_fast_ftol.patch.
|
||||
- 01RS is review3's 01R plus P3 in one patch. Equivalent: 01R then P3 applied in sequence (verified).
|
||||
- The minimal alternative is 01RaltS in place of 01RS.
|
||||
- 04R replaces hud_unit_audit's 04, which no longer applies on 16542e46 because the rejection entry moved.
|
||||
- Full files for the integrator:
|
||||
- cand01R\hud_unit.c (and cand01Ralt\hud_unit.c)
|
||||
- cand\interface\{hud_draw.h, hud_draw.c, hud_nav_points.c, hud_weapon.c, motion_sensor.c, rasterizer_xbox_models.c}
|
||||
- config\symbols.json: 4 in-place line edits, CRLF kept
|
||||
- config\object_admission_rejections.json
|
||||
- git apply --check on 16542e46: every patch is clean alone, and the full set is clean together (also with 01RaltS).
|
||||
- `patch` replay onto copies reproduces every slug file byte for byte.
|
||||
- hud_unit.c change: both goto blocks (lines 0x201 and 0x3C9) become `match_assert_stack_frame("c:\\halo\\SOURCE\\interface\\hud_unit.c", 0x201);` (and 0x3C9), and the TU-local STACK_BUFFER enum is dropped because it is now in hud_draw.h.
|
||||
|
||||
## evidence
|
||||
January bytes (scratch\w\hud_stack_check\sites2.py):
|
||||
- All 26 sentinel sites across the 5 objects are the same inlined shape: a 0x7F..0 loop, then `or esi,-1`, `call _get_return_eip`, and an out-of-line `mov esi,eax; jmp back` return merge.
|
||||
- Both asserts at every site carry one line literal. hud_unit uses 0x201 and 0x3c9; full list in the ledger F2. This is one shared macro.
|
||||
- January's _check_stack_buffer (hud_draw section 2, 48 B) disassembles to `short check_stack_buffer(long *buffer)`. It has 0 relocations anywhere and is PUBLIC at 0xC08F0 in cachebeta publics.
|
||||
- The Sept-2001 map flags _get_return_eip as 'i hud_draw.obj', with a 0x40 gap that exactly holds get_return_eip plus check_stack_buffer.
|
||||
- build/split's COMDAT selection carries NO January information: every code COMDAT in build/split/source is NODUP (7,561 of them, including the proven header inline _fast_ftol), so NODUP vs ANY cannot be read from the split.
|
||||
|
||||
Results with the packet:
|
||||
- gate vs production split: 20 EXACT plus 2 rows that only lack their new names.
|
||||
- gate_split vs the emulated csplit (slug config; the control equals build/split 833/833, and only hud_unit.obj differs): 22/22 EXACT for both 01RS and 01RaltS.
|
||||
- object_audit_split: PASS, 30 January symbols with 0 differing.
|
||||
- Surplus: _fast_ftol and _check_stack_buffer, both IDENTICAL to January's selected copies (actor_combat and hud_draw).
|
||||
- Compared with review3's cand_final_amended.obj, the only difference is the new ANY _check_stack_buffer.
|
||||
- Pair links (plink.py and provider_link_override.py with the packet's hud_draw.obj as provider): 12/12 PASS in both orders.
|
||||
- Control: the production NODUP hud_draw.obj gives LNK2005 in both orders, so P1 and P2 must land with this change.
|
||||
- strict_emulate (objdiff 3.3.1 single-unit report plus the repo's semantic/admission pipeline): 22/22 functions, 6176/6176 code, 152/152 data; contradicted/rejected empty. With the old _fast_ftol veto kept the result is 'contradicted', so 04R is required.
|
||||
- fake_match_scan on hud_unit: 0 leads. /W3 warning census: unchanged.
|
||||
|
||||
## blockers
|
||||
None for hud_unit once the atomic set lands.
|
||||
|
||||
Owner/reviewer decision points:
|
||||
- (a) P7 removes rasterizer_xbox_models' dead `#include "interface/hud_draw.h"`. models uses none of the header's names, and the removal is byte-inert on all 62 models sections. It is needed because the inline's roughly 9 declared names flip __rasterizer_model_transparent_geometry_submit. K-oracle, lab only: dummies alone are exact at K 0-3, 5, 27+; with the inline, exact only at K>=18.
|
||||
- Fallback if (a) is refused: P-A, a focused header included only by the 5 sentinel TUs (lab name interface/hud_draw_stack_check.h), with models untouched. Measured objcmp-identical.
|
||||
- (b) The macro name match_assert_stack_frame is descriptive. The /Od build has no sentinel and HCEX has none, so Bungie's own name is lost.
|
||||
|
||||
## reopen_criteria
|
||||
If the owner rejects both P7 and a focused header: January's original hud_draw.h/models include topology or declared-name set, recovered from first-party evidence, that tolerates the inline in models.
|
||||
|
||||
## task notes
|
||||
**hud_unit (primary goal):** the packet makes source/interface/hud_unit an OBJECT_COMPLETE_CANDIDATE.
|
||||
|
||||
**What January's bytes settle:**
|
||||
- build/split's COMDAT selection cannot tell a header inline from a plain .c function, because csplit writes NODUP for every code COMDAT.
|
||||
- The decisive evidence is elsewhere:
|
||||
- _check_stack_buffer has zero relocations in any split object.
|
||||
- All 26 sites in 5 objects are identical inlined return-merges.
|
||||
- Each site uses a single line literal for both asserts (a macro).
|
||||
- The helper is PUBLIC in cachebeta.
|
||||
- The Sept-2001 map gives an 'i' (inline) flag to its sibling get_return_eip, with the 48-byte gap next to it.
|
||||
|
||||
**Packet:**
|
||||
- hud_draw.h gets:
|
||||
- `__inline short check_stack_buffer(long *buffer)`, the unchanged body;
|
||||
- the STACK_BUFFER constants;
|
||||
- `match_assert_stack_frame(file, line)`.
|
||||
- The 5 TUs use the macro. The invented gotos and the TU-local duplicates are gone.
|
||||
- All 23 hud_draw.h consumers keep every section byte+reloc identical. The only exception is the new SELECT_ANY _check_stack_buffer in hud_unit, hud_nav_points, hud_weapon and motion_sensor, which is identical to January's selected copy and pair-links in both orders against the packet's hud_draw.obj.
|
||||
- This holds only with P7, which removes rasterizer_xbox_models' dead hud_draw.h include. Without P7, the inline's declared names flip __rasterizer_model_transparent_geometry_submit.
|
||||
|
||||
**Integration:**
|
||||
- The set is atomic: P1 and P2 cannot be split, and P3-P6 also depend on P1. The P4-P6 edits are required too, because without P5 hud_weapon's residual _render_weapon_hud drifts.
|
||||
- After applying, the integrator must run a full ninja sweep plus a parks check on the live tree. Other wave-4 header packets can interact through declaration counts.
|
||||
- Two tracked files would need CRLF-safe handling: symbols.json (the slug copy keeps CRLF) and object_admission_rejections.json.
|
||||
- In this lab, repo provider_link.py reports FAIL for _check_stack_buffer only because build/base still holds the production NODUP hud_draw.obj. After the rebuild it should pass; provider_link_override.py demonstrates this.
|
||||
ledger: C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\hud_stack_check\LEDGER.md (sections R0, F1, F2, B0, C0, H1, H1b, K-oracle, L1, S1, S2, A1-A5, H2, P-A, RESULT)
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
# source/interface/hud_weapon
|
||||
|
||||
## verdict
|
||||
ADMISSION_FIX_PROPOSED
|
||||
|
||||
## newly_exact_functions
|
||||
[]
|
||||
|
||||
## candidate_files
|
||||
[
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\hud_stack_check\\cand\\interface\\hud_weapon.c",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\hud_stack_check\\patches\\P5_hud_weapon_c_shared_stack_frame.patch"
|
||||
]
|
||||
|
||||
## production_changes
|
||||
P5_hud_weapon_c_shared_stack_frame.patch:
|
||||
- removes the TU-local goto macro hud_weapon_stack_buffer_check (labels inside a macro) and the HUD_WEAPON_STACK_BUFFER_LENGTH/FILL enum constants;
|
||||
- the 5 sites become match_assert_stack_frame("c:\\halo\\SOURCE\\interface\\hud_weapon.c", 0x3A2 / 0x19E / 0x4E2 / 0x308 / 0xD4);
|
||||
- stack_buffer arrays use STACK_BUFFER_LENGTH;
|
||||
- depends on P1.
|
||||
|
||||
## evidence
|
||||
Full-packet sweep:
|
||||
- gate 13 EXACT / 3 residual, unchanged; all residual bodies byte-identical.
|
||||
- objcmp: the only difference is the new ANY _check_stack_buffer, IDENTICAL to January's copy. Pair link PASS in both orders.
|
||||
|
||||
Subset measurement (P1 without P5): hud_weapon's residual _render_weapon_hud bytes DRIFT through the declaration count. P5 is therefore required, not optional.
|
||||
|
||||
## blockers
|
||||
Pre-existing residuals: _crosshairs_draw, _hud_update_weapon_local_player, _render_weapon_hud.
|
||||
|
||||
## reopen_criteria
|
||||
Existing hud_weapon residual ledgers.
|
||||
|
||||
## task notes
|
||||
**hud_unit (primary goal):** the packet makes source/interface/hud_unit an OBJECT_COMPLETE_CANDIDATE.
|
||||
|
||||
**What January's bytes settle:**
|
||||
- build/split's COMDAT selection cannot tell a header inline from a plain .c function, because csplit writes NODUP for every code COMDAT.
|
||||
- The decisive evidence is elsewhere:
|
||||
- _check_stack_buffer has zero relocations in any split object.
|
||||
- All 26 sites in 5 objects are identical inlined return-merges.
|
||||
- Each site uses a single line literal for both asserts (a macro).
|
||||
- The helper is PUBLIC in cachebeta.
|
||||
- The Sept-2001 map gives an 'i' (inline) flag to its sibling get_return_eip, with the 48-byte gap next to it.
|
||||
|
||||
**Packet:**
|
||||
- hud_draw.h gets:
|
||||
- `__inline short check_stack_buffer(long *buffer)`, the unchanged body;
|
||||
- the STACK_BUFFER constants;
|
||||
- `match_assert_stack_frame(file, line)`.
|
||||
- The 5 TUs use the macro. The invented gotos and the TU-local duplicates are gone.
|
||||
- All 23 hud_draw.h consumers keep every section byte+reloc identical. The only exception is the new SELECT_ANY _check_stack_buffer in hud_unit, hud_nav_points, hud_weapon and motion_sensor, which is identical to January's selected copy and pair-links in both orders against the packet's hud_draw.obj.
|
||||
- This holds only with P7, which removes rasterizer_xbox_models' dead hud_draw.h include. Without P7, the inline's declared names flip __rasterizer_model_transparent_geometry_submit.
|
||||
|
||||
**Integration:**
|
||||
- The set is atomic: P1 and P2 cannot be split, and P3-P6 also depend on P1. The P4-P6 edits are required too, because without P5 hud_weapon's residual _render_weapon_hud drifts.
|
||||
- After applying, the integrator must run a full ninja sweep plus a parks check on the live tree. Other wave-4 header packets can interact through declaration counts.
|
||||
- Two tracked files would need CRLF-safe handling: symbols.json (the slug copy keeps CRLF) and object_admission_rejections.json.
|
||||
- In this lab, repo provider_link.py reports FAIL for _check_stack_buffer only because build/base still holds the production NODUP hud_draw.obj. After the rebuild it should pass; provider_link_override.py demonstrates this.
|
||||
ledger: C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\hud_stack_check\LEDGER.md (sections R0, F1, F2, B0, C0, H1, H1b, K-oracle, L1, S1, S2, A1-A5, H2, P-A, RESULT)
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
# source/interface/motion_sensor
|
||||
|
||||
## verdict
|
||||
ADMISSION_FIX_PROPOSED
|
||||
|
||||
## newly_exact_functions
|
||||
[]
|
||||
|
||||
## candidate_files
|
||||
[
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\hud_stack_check\\cand\\interface\\motion_sensor.c",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\hud_stack_check\\patches\\P6_motion_sensor_c_shared_stack_frame.patch"
|
||||
]
|
||||
|
||||
## production_changes
|
||||
P6_motion_sensor_c_shared_stack_frame.patch:
|
||||
- The 3 goto sentinel blocks become match_assert_stack_frame("c:\\halo\\SOURCE\\interface\\motion_sensor.c", 642 / 756 / 830), keeping each block's own decimal literals.
|
||||
- `long stack_buffer[0x80];` becomes STACK_BUFFER_LENGTH (x3).
|
||||
- Depends on P1.
|
||||
|
||||
## evidence
|
||||
Full-packet sweep:
|
||||
- gate 16 EXACT / 3 residual, unchanged; the 3 parked bodies (_motion_sensor_update, _update_motion_sensor, _render_motion_sensor) are byte-identical.
|
||||
- objcmp: the only difference is the new ANY _check_stack_buffer, IDENTICAL to January's copy. Pair link PASS in both orders.
|
||||
- /W3 warnings: unchanged.
|
||||
|
||||
## blockers
|
||||
Pre-existing parks on 3 functions.
|
||||
|
||||
## reopen_criteria
|
||||
Existing motion_sensor park criteria.
|
||||
|
||||
## task notes
|
||||
**hud_unit (primary goal):** the packet makes source/interface/hud_unit an OBJECT_COMPLETE_CANDIDATE.
|
||||
|
||||
**What January's bytes settle:**
|
||||
- build/split's COMDAT selection cannot tell a header inline from a plain .c function, because csplit writes NODUP for every code COMDAT.
|
||||
- The decisive evidence is elsewhere:
|
||||
- _check_stack_buffer has zero relocations in any split object.
|
||||
- All 26 sites in 5 objects are identical inlined return-merges.
|
||||
- Each site uses a single line literal for both asserts (a macro).
|
||||
- The helper is PUBLIC in cachebeta.
|
||||
- The Sept-2001 map gives an 'i' (inline) flag to its sibling get_return_eip, with the 48-byte gap next to it.
|
||||
|
||||
**Packet:**
|
||||
- hud_draw.h gets:
|
||||
- `__inline short check_stack_buffer(long *buffer)`, the unchanged body;
|
||||
- the STACK_BUFFER constants;
|
||||
- `match_assert_stack_frame(file, line)`.
|
||||
- The 5 TUs use the macro. The invented gotos and the TU-local duplicates are gone.
|
||||
- All 23 hud_draw.h consumers keep every section byte+reloc identical. The only exception is the new SELECT_ANY _check_stack_buffer in hud_unit, hud_nav_points, hud_weapon and motion_sensor, which is identical to January's selected copy and pair-links in both orders against the packet's hud_draw.obj.
|
||||
- This holds only with P7, which removes rasterizer_xbox_models' dead hud_draw.h include. Without P7, the inline's declared names flip __rasterizer_model_transparent_geometry_submit.
|
||||
|
||||
**Integration:**
|
||||
- The set is atomic: P1 and P2 cannot be split, and P3-P6 also depend on P1. The P4-P6 edits are required too, because without P5 hud_weapon's residual _render_weapon_hud drifts.
|
||||
- After applying, the integrator must run a full ninja sweep plus a parks check on the live tree. Other wave-4 header packets can interact through declaration counts.
|
||||
- Two tracked files would need CRLF-safe handling: symbols.json (the slug copy keeps CRLF) and object_admission_rejections.json.
|
||||
- In this lab, repo provider_link.py reports FAIL for _check_stack_buffer only because build/base still holds the production NODUP hud_draw.obj. After the rebuild it should pass; provider_link_override.py demonstrates this.
|
||||
ledger: C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\hud_stack_check\LEDGER.md (sections R0, F1, F2, B0, C0, H1, H1b, K-oracle, L1, S1, S2, A1-A5, H2, P-A, RESULT)
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
# source/rasterizer/xbox/rasterizer_xbox_models
|
||||
|
||||
## verdict
|
||||
ADMISSION_FIX_PROPOSED
|
||||
|
||||
## newly_exact_functions
|
||||
[]
|
||||
|
||||
## candidate_files
|
||||
[
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\hud_stack_check\\cand\\interface\\rasterizer_xbox_models.c",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\hud_stack_check\\patches\\P7_rasterizer_xbox_models_c_drop_dead_hud_draw_include.patch"
|
||||
]
|
||||
|
||||
## production_changes
|
||||
P7_rasterizer_xbox_models_c_drop_dead_hud_draw_include.patch deletes the line `#include "interface/hud_draw.h"`. The line is dead: the TU references no name hud_draw.h declares. It was added by 635bd83d, when hud_draw.h still declared the ARGB converter, which has since moved to bitmap_color_conversion.h.
|
||||
|
||||
## evidence
|
||||
- Lab labs/models_noinc.c (production header, no include): 12/2 rows, and objcmp against production shows 0 differences across all 62 owned sections, anonymous sections and symbols.
|
||||
- With P1 and without P7: __rasterizer_model_transparent_geometry_submit goes EXACT to residual (declaration-count class; the inline costs about 9 name units).
|
||||
- With P1 and P7: 0 differences.
|
||||
|
||||
## blockers
|
||||
Owner may view P7 as load-bearing relative to P1. Fallback P-A: a focused header included only by the 5 sentinel TUs, which leaves models untouched. Measured objcmp-identical for the 5 objects.
|
||||
|
||||
## reopen_criteria
|
||||
n/a
|
||||
|
||||
## task notes
|
||||
**hud_unit (primary goal):** the packet makes source/interface/hud_unit an OBJECT_COMPLETE_CANDIDATE.
|
||||
|
||||
**What January's bytes settle:**
|
||||
- build/split's COMDAT selection cannot tell a header inline from a plain .c function, because csplit writes NODUP for every code COMDAT.
|
||||
- The decisive evidence is elsewhere:
|
||||
- _check_stack_buffer has zero relocations in any split object.
|
||||
- All 26 sites in 5 objects are identical inlined return-merges.
|
||||
- Each site uses a single line literal for both asserts (a macro).
|
||||
- The helper is PUBLIC in cachebeta.
|
||||
- The Sept-2001 map gives an 'i' (inline) flag to its sibling get_return_eip, with the 48-byte gap next to it.
|
||||
|
||||
**Packet:**
|
||||
- hud_draw.h gets:
|
||||
- `__inline short check_stack_buffer(long *buffer)`, the unchanged body;
|
||||
- the STACK_BUFFER constants;
|
||||
- `match_assert_stack_frame(file, line)`.
|
||||
- The 5 TUs use the macro. The invented gotos and the TU-local duplicates are gone.
|
||||
- All 23 hud_draw.h consumers keep every section byte+reloc identical. The only exception is the new SELECT_ANY _check_stack_buffer in hud_unit, hud_nav_points, hud_weapon and motion_sensor, which is identical to January's selected copy and pair-links in both orders against the packet's hud_draw.obj.
|
||||
- This holds only with P7, which removes rasterizer_xbox_models' dead hud_draw.h include. Without P7, the inline's declared names flip __rasterizer_model_transparent_geometry_submit.
|
||||
|
||||
**Integration:**
|
||||
- The set is atomic: P1 and P2 cannot be split, and P3-P6 also depend on P1. The P4-P6 edits are required too, because without P5 hud_weapon's residual _render_weapon_hud drifts.
|
||||
- After applying, the integrator must run a full ninja sweep plus a parks check on the live tree. Other wave-4 header packets can interact through declaration counts.
|
||||
- Two tracked files would need CRLF-safe handling: symbols.json (the slug copy keeps CRLF) and object_admission_rejections.json.
|
||||
- In this lab, repo provider_link.py reports FAIL for _check_stack_buffer only because build/base still holds the production NODUP hud_draw.obj. After the rebuild it should pass; provider_link_override.py demonstrates this.
|
||||
ledger: C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\hud_stack_check\LEDGER.md (sections R0, F1, F2, B0, C0, H1, H1b, K-oracle, L1, S1, S2, A1-A5, H2, P-A, RESULT)
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
# source/interface/hud_weapon::_crosshairs_draw
|
||||
|
||||
## verdict
|
||||
BLOCKED
|
||||
|
||||
## newly_exact_functions
|
||||
[]
|
||||
|
||||
## candidate_files
|
||||
[
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\hud_weapon\\cd_r0.c"
|
||||
]
|
||||
|
||||
## production_changes
|
||||
None.
|
||||
|
||||
## evidence
|
||||
Held owner item; not re-probed beyond a re-measure. The ruling form (production with an uninitialised firing_active, cd_r0.c) stays residual: relocs 77 against 76, 693 against 704 instructions, 157 alndiff hunks, frame 0x314 against 0x318.
|
||||
|
||||
January facts re-read from T_cd.txt:
|
||||
- The if-chain handles states 18/8/9, and the state-14 path reads firing at T+0x495 with no reaching write (the /Od build at 0x6363e0 behaves the same).
|
||||
- The animated/zoom colour tails cross-jump (T+0x51c `jmp 0x393`).
|
||||
- The aim case jumps straight to draw when frame_index=0 is known.
|
||||
|
||||
Prior art: the structural c2r /Od switch shape reached 2224/74; binding bitmap_group_get (Lane C P5) gives January's 0x318 frame.
|
||||
|
||||
## blockers
|
||||
Authentic uninitialised read (brief section 7 owner class). On top of that, still structurally fuzzy even in the ruling form.
|
||||
|
||||
## reopen_criteria
|
||||
The owner admits the uninitialised firing read. Then a full /Od-guided rebuild combining the c2r switch shape, the P5 bitmap_group_get binding and the cross-jumped colour tail.
|
||||
|
||||
## task notes
|
||||
Nothing was landed or made landable for credit. uwlp is exact, but only in the held form: `result` is left unassigned on the unreachable default arm. January's T+0x144 load of the never-stored home proves that form. Patches are provided for both tree states: before and after the hud_stack_check P5.
|
||||
|
||||
rwh has a new partial decode. The flash-loop and statics-loop allocation residuals share one cause: a +1 ESI neighbour preference in the C2 chooser. It comes from the copy of local_player_index into get_hud_state's private ESI argument; lab G1 and G2 flip both loops to January's registers. The x87 add-chain order is a separate residual. No evidence-backed source lever was found. Every TU name-count, prototype and dead-local oracle is inert for rwh.
|
||||
|
||||
The rwh fidelity candidate cannot land alone. It newly emits header COMDATs from a non-exact caller (P1 class).
|
||||
|
||||
Interaction with the concurrent hud_stack_check packet: the rwh bytes are identical with its inline check_stack_buffer. The uwlp owner body stays exact on top of it. My production-tree uwlp patch conflicts with P5 on one context line, so use the _after_P5 variant once P5 has landed.
|
||||
|
||||
Tools copied into the slug and run only there: Lane A dbg32c.exe (sha1 21c75281, our own debugger over our CL). Its outputs are confined to scratch/w/hud_weapon/dbg.
|
||||
ledger: C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\hud_weapon\LEDGER.md
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
# source/interface/hud_weapon::_hud_update_weapon_local_player
|
||||
|
||||
## verdict
|
||||
BLOCKED
|
||||
|
||||
## newly_exact_functions
|
||||
[]
|
||||
|
||||
## candidate_files
|
||||
[
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\hud_weapon\\owner_uwlp.c",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\hud_weapon\\owner_gated_uwlp.patch",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\hud_weapon\\owner_gated_uwlp_after_P5.patch",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\hud_weapon\\after_p5\\owner_hud_weapon.c"
|
||||
]
|
||||
|
||||
## production_changes
|
||||
None landable. There is an owner-gated exact form, ready and held. (a) scratch/w/hud_weapon/owner_gated_uwlp.patch: `git apply --check` is clean against 16542e46. (b) scratch/w/hud_weapon/owner_gated_uwlp_after_P5.patch: the same body for use after the hud_stack_check lane's P5 (hud_weapon.c shared stack frame) lands. The two conflict on the stack_buffer context line, so apply the one that matches the tree. Both replace only the uwlp body with the structural-lane body (claude-structural-20260923 REPORT) plus BUG-style comments. No header/config/symbols change and no new symbols (the owner_uwlp.obj symbol census equals build/base).
|
||||
|
||||
## evidence
|
||||
Re-measured on 16542e46. s1.c/owner_uwlp.c: gate --all gives exact 14 / residual 2; the uwlp row is EXACT 1472/68, sha 0524ed47, and no other row moved; the _point_from_line3d guard passes. It is also exact on top of the stack-check lane's header inline (after_p5/gtu_owner.c, 14/16).
|
||||
|
||||
The shape is /Od-attested (fn 0x638150): jump-table case order, `long unit_index` local, `struct crosshair_state *state`, the redundant `(rem||loaded)&&` terms, and the primary trigger tested in fired_secondary_with_no_ammo (/Od 0x638a07 `and edx,0x800`; January T+0x3b7 `test ch,8`).
|
||||
|
||||
January byte proof of the uninitialised web: T+0x144 `mov esi,[ebp-0x28]` loads return_eip's home into result's register at loop entry. result's home is never stored, so the frame packer merged it with return_eip; the default arm (T+0x404 assert, falling to +0x424 `test si,si`) reads it. /Od 0x638ac2..0x638af3 has the same missing store and NO _RTC_UninitUse (its RTC descriptor lists only the two 64-byte arrays). Load-bearing controls (structural lane): restoring `result = FALSE` gives 1488 (wrong size); the secondary trigger bit gives 1488.
|
||||
|
||||
object_audit with owner_uwlp.obj: 23/23 January symbols ok, .bss ok, FAIL(2) = _crosshairs_draw and _render_weapon_hud only. pdb_storage: 0 disagreements.
|
||||
|
||||
## blockers
|
||||
Brief section 7 / structural owner packet section 7: the exact form needs `result` unassigned on the default arm after match_assert(!"unreachable"). It is read only if system_exit returns, which is the authentic uninitialised-read class (same as _effect_allowed_by_environment). The primary-trigger test in the secondary state is authentic January and /Od behaviour, and the owner should also confirm it (production currently tests the secondary bit).
|
||||
|
||||
## reopen_criteria
|
||||
The owner admits the unreachable-default unassigned-result form (and the primary-trigger test). Then apply owner_gated_uwlp.patch, or the _after_P5 variant if the stack-check packet has landed, and run the full sweep. No hud_weapon.h/header consumers are involved.
|
||||
|
||||
## task notes
|
||||
Nothing was landed or made landable for credit. uwlp is exact, but only in the held form: `result` is left unassigned on the unreachable default arm. January's T+0x144 load of the never-stored home proves that form. Patches are provided for both tree states: before and after the hud_stack_check P5.
|
||||
|
||||
rwh has a new partial decode. The flash-loop and statics-loop allocation residuals share one cause: a +1 ESI neighbour preference in the C2 chooser. It comes from the copy of local_player_index into get_hud_state's private ESI argument; lab G1 and G2 flip both loops to January's registers. The x87 add-chain order is a separate residual. No evidence-backed source lever was found. Every TU name-count, prototype and dead-local oracle is inert for rwh.
|
||||
|
||||
The rwh fidelity candidate cannot land alone. It newly emits header COMDATs from a non-exact caller (P1 class).
|
||||
|
||||
Interaction with the concurrent hud_stack_check packet: the rwh bytes are identical with its inline check_stack_buffer. The uwlp owner body stays exact on top of it. My production-tree uwlp patch conflicts with P5 on one context line, so use the _after_P5 variant once P5 has landed.
|
||||
|
||||
Tools copied into the slug and run only there: Lane A dbg32c.exe (sha1 21c75281, our own debugger over our CL). Its outputs are confined to scratch/w/hud_weapon/dbg.
|
||||
ledger: C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\hud_weapon\LEDGER.md
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
# source/interface/hud_weapon::_render_weapon_hud
|
||||
|
||||
## verdict
|
||||
FUZZY_IMPROVED
|
||||
|
||||
## newly_exact_functions
|
||||
[]
|
||||
|
||||
## candidate_files
|
||||
[
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\hud_weapon\\rwh_fidelity_candidate.c",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\hud_weapon\\rwh_fidelity_candidate.patch",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\hud_weapon\\c_od_union_names_tblock.c",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\hud_weapon\\mkcand.py",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\hud_weapon\\rv.py",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\hud_weapon\\dbg\\run_prio.py",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\hud_weapon\\dbg\\show.py"
|
||||
]
|
||||
|
||||
## production_changes
|
||||
None landable now. The fidelity candidate is scratch/w/hud_weapon/rwh_fidelity_candidate.c, with patch rwh_fidelity_candidate.patch (`git apply --check` clean on 16542e46). It replaces only the rwh body. It is held by wave-3 law (i)/P1: compared with build/base it newly emits the header-inline COMDATs _distance3d, _distance_squared3d, _magnitude_squared3d, _vector_from_points3d and _fast_ftol from a non-exact caller, and drops _power. Land it only together with an rwh closure.
|
||||
|
||||
## evidence
|
||||
Base: the w1 R3 / structural r3u body. Changes applied: /Od-attested, byte-inert spellings (pow(10.0f,4), since /Od 0x632150 is C++ pow(float,int), not real_math power; the ?: unit index and the fast_ftol decimal inline as call arguments; `scenario = global_scenario_get(); map_type_flags = 0; SET_FLAG(...,0,...)` from /Od 0x63b40a, with crosshairs /Od 0x636452 the same idiom); RTC 0x63ba40 names numbers/numbers_real/position/target_position; /Od target-block declaration order; the admitted local-union sentinel transfer.
|
||||
|
||||
Candidate result: 2672/84, and the relocation-target multiset equals January's (production has an extra __ftol2). Relocations 0..53 sit at January's addresses, with 118 alndiff hunks against production's 208 (production is 2624/85, uses a hand-expanded distance (rule 6), (short)fmod, and flags/cutoffs locals). The TU-level union-element variant (CC4 E7d; invented type name, and HCEX says float[8]) gives 112 hunks and relocs 0..57 aligned.
|
||||
|
||||
Decoded residual (new):
|
||||
1. The flash-loop IV swap (T hud=ESI/flags=EDI) and the statics-loop allocation (T definition in EDI, &statics in ESI, element_index homed), plus the frame-slot permutation downstream of them, share ONE cause. The C2 chooser (Lane A dbg32c run on a byte-identical lab TU, scratch/w/hud_weapon/dbg) gives p_hud (pri 46) and the statics &statics web (pri 34) an ESI cost of 1 against EDI 0. That +1 is the neighbour preference of the local_player_index web's copy into get_hud_state's private ESI argument (T+0x35 `mov esi,[ebp+0xc]`, the same bytes in both). Lab G1 (get_hud_state made non-static) and G2 (constant argument) both flip the flash loop and the statics loop to January's registers. Bisection shows the hw_v4 overlay `flags` webs, which take ESI earlier, have the same effect. So the tie is source-reachable in principle but upstream.
|
||||
2. The x87 add-chain order (T j2,i2,+,k2,+ against ours k2,j2,+,i2,+) is independent (it stays kji in G1/hyb).
|
||||
|
||||
Measured inert (lab oracles, never landing): extern names 0..40 before the prototype and before the definition, prototypes 0..34, dead locals 0..16, initialised locals, definition order (January section order), pow/power, cutoffs pointer, age_percentage local, flash-counter scope ×2, the state_index local, the scenario idiom ×2, inverted flash if/else, the stack-check lane's inline check_stack_buffer (rwh byte-identical with it), and 1-6 later magnitude3d inlines for the x87 order.
|
||||
|
||||
## blockers
|
||||
(1) Allocation tie keyed on an unidentified upstream IL fact: the ESI neighbour preference from the get_hud_state private-ABI argument copy. (2) An independent x87 add-chain order. (3) Admission of the candidate is held by P1 (new header COMDATs from a non-exact caller). Its explicit block after csmemset follows January's prologue order and does not depend on the stack-check packet (the bytes are identical with it). Methodology stop rule reached.
|
||||
|
||||
## reopen_criteria
|
||||
A first-party fact that changes local_player_index's web or ESI copy preference, or colours a higher-priority web into ESI before the flash loop, while keeping the else-block bytes (they already match January). Test with scratch/w/hud_weapon/rv.py (it prints the x87/flash/statics signatures) and dbg/run_prio.py plus show.py (chooser costs). Also a source construct that yields January's jik x87 order: only ctf_init's first distance_squared3d site shows it. Land rwh_fidelity_candidate.patch only with the closure.
|
||||
|
||||
## task notes
|
||||
Nothing was landed or made landable for credit. uwlp is exact, but only in the held form: `result` is left unassigned on the unreachable default arm. January's T+0x144 load of the never-stored home proves that form. Patches are provided for both tree states: before and after the hud_stack_check P5.
|
||||
|
||||
rwh has a new partial decode. The flash-loop and statics-loop allocation residuals share one cause: a +1 ESI neighbour preference in the C2 chooser. It comes from the copy of local_player_index into get_hud_state's private ESI argument; lab G1 and G2 flip both loops to January's registers. The x87 add-chain order is a separate residual. No evidence-backed source lever was found. Every TU name-count, prototype and dead-local oracle is inert for rwh.
|
||||
|
||||
The rwh fidelity candidate cannot land alone. It newly emits header COMDATs from a non-exact caller (P1 class).
|
||||
|
||||
Interaction with the concurrent hud_stack_check packet: the rwh bytes are identical with its inline check_stack_buffer. The uwlp owner body stays exact on top of it. My production-tree uwlp patch conflicts with P5 on one context line, so use the _after_P5 variant once P5 has landed.
|
||||
|
||||
Tools copied into the slug and run only there: Lane A dbg32c.exe (sha1 21c75281, our own debugger over our CL). Its outputs are confined to scratch/w/hud_weapon/dbg.
|
||||
ledger: C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\hud_weapon\LEDGER.md
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
# source/interface/hud_weapon (object)
|
||||
|
||||
## verdict
|
||||
BLOCKED
|
||||
|
||||
## newly_exact_functions
|
||||
[]
|
||||
|
||||
## candidate_files
|
||||
[
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\hud_weapon\\LEDGER.md"
|
||||
]
|
||||
|
||||
## production_changes
|
||||
None landable. Owner-gated: owner_gated_uwlp.patch or owner_gated_uwlp_after_P5.patch. Research-held: rwh_fidelity_candidate.patch.
|
||||
|
||||
## evidence
|
||||
Baseline: 13 exact / 3 residual. With the owner uwlp body: 14/16. object_audit (owner_uwlp.obj): 23/23 January symbols, .bss _weapon_hud_globals ok, FAIL(2) = _crosshairs_draw and _render_weapon_hud. pdb_storage: 0 disagreements. git status stayed clean.
|
||||
|
||||
## blockers
|
||||
_crosshairs_draw (owner uninitialised-read class plus fuzzy), _render_weapon_hud (allocation and x87 tie), _hud_update_weapon_local_player (owner uninitialised-read class).
|
||||
|
||||
## reopen_criteria
|
||||
Owner rulings on the authentic uninitialised-read class (uwlp and crosshairs_draw), plus an rwh lever per the rwh entry.
|
||||
|
||||
## task notes
|
||||
Nothing was landed or made landable for credit. uwlp is exact, but only in the held form: `result` is left unassigned on the unreachable default arm. January's T+0x144 load of the never-stored home proves that form. Patches are provided for both tree states: before and after the hud_stack_check P5.
|
||||
|
||||
rwh has a new partial decode. The flash-loop and statics-loop allocation residuals share one cause: a +1 ESI neighbour preference in the C2 chooser. It comes from the copy of local_player_index into get_hud_state's private ESI argument; lab G1 and G2 flip both loops to January's registers. The x87 add-chain order is a separate residual. No evidence-backed source lever was found. Every TU name-count, prototype and dead-local oracle is inert for rwh.
|
||||
|
||||
The rwh fidelity candidate cannot land alone. It newly emits header COMDATs from a non-exact caller (P1 class).
|
||||
|
||||
Interaction with the concurrent hud_stack_check packet: the rwh bytes are identical with its inline check_stack_buffer. The uwlp owner body stays exact on top of it. My production-tree uwlp patch conflicts with P5 on one context line, so use the _after_P5 variant once P5 has landed.
|
||||
|
||||
Tools copied into the slug and run only there: Lane A dbg32c.exe (sha1 21c75281, our own debugger over our CL). Its outputs are confined to scratch/w/hud_weapon/dbg.
|
||||
ledger: C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\hud_weapon\LEDGER.md
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
# source/interface/motion_sensor :: _motion_sensor_update (1168)
|
||||
|
||||
## verdict
|
||||
BLOCKED
|
||||
|
||||
## newly_exact_functions
|
||||
null
|
||||
|
||||
## candidate_files
|
||||
[
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\motion_sensor\\cand_full.c",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\motion_sensor\\owner_gated_full.patch",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\motion_sensor\\m4.c",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\motion_sensor\\od_motion_sensor_update.txt"
|
||||
]
|
||||
|
||||
## production_changes
|
||||
None landable (owner-gated). The strict-EXACT body (n4 m4, re-verified at 16542e46) is in cand_full.c / owner_gated_full.patch. It carries HCEX/Od names positions, local_player_true_index, num_recorded_blips, iter, center, dummy, and (m5) drops the player_index local as /Od 0x641c98 shows. Gate for cand_full: exact 17, residual 2 (_motion_sensor_update 1168/43 EXACT). object_audit: 44 January symbols, 0 differ. Its new COMDATs are identical to January's selected copies and pass provider_link both ways. If the owner admits it, unpark _motion_sensor_update and apply owner_gated_full.patch instead of production.patch; it contains production.patch. _update_motion_sensor then re-baselines to 864/39.
|
||||
|
||||
## evidence
|
||||
The exact body keeps January's uninitialised positions[] read for a local player without a unit, with a BUG comment. NEW first-party evidence that this is an authentic January bug: the later /Od build (0x641b60) zeroes positions[i] (xorps stores at 0x641cf4) and re-tests the scan player's unit in the object loop (0x641e35..0x641e8c). So the code was fixed after January, the same class as king, glow and dead_camera. The fix-free spelling is impossible: n4 showed January's frame (0x284) and relocation multiset force this shape.
|
||||
|
||||
## blockers
|
||||
Owner ruling on the authentic uninitialised-read BUG class. Rule (i) is then satisfied, because this exact function is the caller of the new COMDATs.
|
||||
|
||||
## reopen_criteria
|
||||
The owner admits the BUG-commented uninitialised read. Land owner_gated_full.patch and unpark _motion_sensor_update in the same commit.
|
||||
|
||||
## task notes
|
||||
Landable now: production.patch. It is zero exact credit: a structural fix to _render_motion_sensor (the slot swap is gone; the park re-baselines to 784/40, sha 69f4678045fb...), one less surplus COMDAT (`_power`), and a .bss symbol-order fix, so object_audit now shows 0 of 44 January symbols wrong. The patch touches only motion_sensor.c: no header, no consumer sweep, and no symbols.json change.
|
||||
|
||||
Dependency on the stack sentinel: none of the three residuals depends on check_stack_buffer (lab diagnostics e2 and e3 remove the whole sentinel and the residuals stay). The only sentinel-area byte difference in render is an alignment pad driven by code offsets. The object still needs the hud_stack_check lane's check_stack_buffer packet before it can be admitted.
|
||||
|
||||
Held by owner: owner_gated_full.patch gives exact 17 / residual 2. After an owner ruling, the only open rows would be the render scheduler tie and the update reassociation tie.
|
||||
ledger: C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\motion_sensor\LEDGER.md. It records every probe with hypothesis, evidence, change and result: r1-r9 for render, u7-u10 for update, the m4/m5 re-verification, lab e1-e3, d1-d3, L1-L9 and bss1, and all name/local-count oracles. /Od dumps are in od_*.txt. The tree was clean before and after (`git status` empty); no tracked file was touched.
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
# source/interface/motion_sensor :: _render_motion_sensor (768)
|
||||
|
||||
## verdict
|
||||
FUZZY_IMPROVED
|
||||
|
||||
## newly_exact_functions
|
||||
null
|
||||
|
||||
## candidate_files
|
||||
[
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\motion_sensor\\production.patch",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\motion_sensor\\cand_prod.c",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\motion_sensor\\od_render_motion_sensor.txt"
|
||||
]
|
||||
|
||||
## production_changes
|
||||
The rest of production.patch (== cand_prod.c, CRLF). In render_motion_sensor: (1) one `real weight` local holds the history weight and is then reassigned `weight = (real)(pow(1.0f - weight, 3.5) * 7.0 + 1.0);` (with a one-line comment); the separate `radius` local is removed and both render_blip calls pass `weight`. (2) pow is called directly instead of the power() wrapper. (3) HCEX local names `corner` (was center) and `blip_pos` (was point, in both blocks). (4) /Od declaration order: `short history_index;` before `real_point2d corner;`. Park re-baseline: 784/40, normalized sha 69f4678045fb7eb843cd57c0a6715f102f2e7982cdeed68468dda6be4250ed44 (was de9701add36aae94...). The integrator must re-measure objdiff%. The other two parks are unchanged by this patch (1136/44 sha 40e4819de2760a22..., 816/37 sha 5bae910d9c27cad0...). Surplus shrinks: `_power` is no longer emitted. provider_link --baseline finds no new surplus. The _point_from_line3d guard passes.
|
||||
|
||||
## evidence
|
||||
NEW /Od evidence (0x6426c0, od_render_motion_sensor.txt). [ebp-0x34] holds (10-i)/10.0f; fade [ebp-0x38] = w*w; the pow result is stored back into [ebp-0x34] and pushed as render_blip's radius argument. /Od never merges locals, so the source uses ONE variable for both. January's own bytes agree: the radius store `fstp [ebp-8]` reuses the weight slot, and the inner trip counter sits at [ebp-0x20]. The two-variable form produced the [ebp-8]/[ebp-0x20] slot swap that every prior wave carried; probe r1 removes it (alndiff blocks 34 -> 32). /Od calls a pow<float,double> template (0x62fcb0), so the source called pow(x, 3.5) directly; render_blip in the same TU already does. HCEX.pdb names the aggregates corner and blip_pos. Inert probes (all recorded): r2 /Od (active+10-i) operand order; r4/r5 `/ MOTION_SENSOR_HISTORY_COUNT` and `/10.0f` (a lab shows VC7 folds both to fmul 0.1f); r3 long history_index (contradicts /Od short, and worse); r6 declaration order; r7 direct pow; r8 single-exit nested if (byte-identical to r7, not proposed because it touches the label next to the stack-check block); d1-d3 statement orders (farther); the name-count oracle K=0..50 gives one identical sha. Diagnostics: e1 shows the `sub eax,[ebp-0x18]` fold and the idiv-first order appear exactly when no x87 op is in the block, so the residual is x87/integer interleaving. e2 removes the whole stack sentinel and the residual is unchanged, so it does NOT depend on check_stack_buffer.
|
||||
|
||||
## blockers
|
||||
Remaining machine difference, all in the loop-head block. January emits `sub eax,dword ptr [ebp-0x18]` and finishes add/cdq/mov ecx,10/idiv plus the player reload before the x87 chain (fmul 0.1f; fst; fmul; fstp). Ours emits `mov edx,[ebp-0x18]; sub eax,edx` and interleaves the x87 chain into the integer statement. That changes code offsets by 2 bytes, which then adds two loop-alignment pads (0x11a, 0x19a) and a 5-byte `jmp`+lea pad in the stack-check loop; the pads are offset-driven only. It is a scheduler tie that survived every /Od-attested spelling. Methodology stop rule reached (8 shapes).
|
||||
|
||||
## reopen_criteria
|
||||
A decoded C2 scheduler rule, or first-party evidence, for why January does not interleave the x87 weight chain into an idiv statement: for example a C2 trace of the loop-head block's list scheduler, or a corpus function with the same fild-IV + idiv + x87 block that we already match. Do not respend on statement order, index spelling, division form, loop-counter width or name/local-count oracles; all are measured inert.
|
||||
|
||||
## task notes
|
||||
Landable now: production.patch. It is zero exact credit: a structural fix to _render_motion_sensor (the slot swap is gone; the park re-baselines to 784/40, sha 69f4678045fb...), one less surplus COMDAT (`_power`), and a .bss symbol-order fix, so object_audit now shows 0 of 44 January symbols wrong. The patch touches only motion_sensor.c: no header, no consumer sweep, and no symbols.json change.
|
||||
|
||||
Dependency on the stack sentinel: none of the three residuals depends on check_stack_buffer (lab diagnostics e2 and e3 remove the whole sentinel and the residuals stay). The only sentinel-area byte difference in render is an alignment pad driven by code offsets. The object still needs the hud_stack_check lane's check_stack_buffer packet before it can be admitted.
|
||||
|
||||
Held by owner: owner_gated_full.patch gives exact 17 / residual 2. After an owner ruling, the only open rows would be the render scheduler tie and the update reassociation tie.
|
||||
ledger: C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\motion_sensor\LEDGER.md. It records every probe with hypothesis, evidence, change and result: r1-r9 for render, u7-u10 for update, the m4/m5 re-verification, lab e1-e3, d1-d3, L1-L9 and bss1, and all name/local-count oracles. /Od dumps are in od_*.txt. The tree was clean before and after (`git status` empty); no tracked file was touched.
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
# source/interface/motion_sensor :: _update_motion_sensor (864)
|
||||
|
||||
## verdict
|
||||
NO_PROGRESS
|
||||
|
||||
## newly_exact_functions
|
||||
null
|
||||
|
||||
## candidate_files
|
||||
[
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\motion_sensor\\u9.c",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\motion_sensor\\cand_full.c",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\motion_sensor\\owner_gated_full.patch",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\motion_sensor\\od_update_motion_sensor.txt"
|
||||
]
|
||||
|
||||
## production_changes
|
||||
None landable. A held candidate body is in owner_gated_full.patch / cand_full.c: the /Od-faithful u9 body, 864/39, sha 0dcb6bf20658cf6fc67d2948266ab15da7ff49e2cf3d2d2f33d343cb2fe7cf1c. It newly emits the _distance_squared3d and _vector_from_points3d COMDATs. Both are byte-identical to January's selected action_alert copies and pass provider_link in both orders, but rule (i) admits a new header COMDAT only from a strictly exact caller. So this body can land only together with the exact _motion_sensor_update (the owner ruling below), or once it is itself exact.
|
||||
|
||||
## evidence
|
||||
/Od 0x642ff0 (od_update_motion_sensor.txt) plus RTC and HCEX names (reference_point x2, unit_center, player_center, point, dummy, customs, custom_temp; HCEX puts the first reference_point and unit_center at the same offset). These fix the statement order and the local set: no player_index local; short loop-1 counter with a blips pointer; separate long loop-2 counter; customs[i] indexed. u9 reproduces the w3c u7 result on the current tree. The only difference is 8 bytes at 0x16b..0x178 in loop 1: January sums (jj+ii)+kk, ours (ii+kk)+jj. Loop 2 matches. Measured inert: u8 /Od declaration order; u9 local set; u10 dead named game_time_get local; dead-local oracles (long K=0..16, real K=0..8), a used copy-chain oracle (long K=0..10, real K=0..8) and a TU extern oracle (K=0..40), all one sha, so this is not M8, H3 or a name-count tie; lab L3/L4/L5/L7/L8/L9 statement and argument permutations. Only L1 (point computation removed, not admissible) moves the order, to k,j,i. Diagnostic e3 removes the stack sentinel and the order is unchanged, so there is NO check_stack_buffer dependency.
|
||||
|
||||
## blockers
|
||||
(1) The loop-1 reassociation order of the inlined distance_squared3d, which depends on the preceding point.x/point.y computation. (2) The P1/rule-(i) COMDAT admission, coupled to _motion_sensor_update.
|
||||
|
||||
## reopen_criteria
|
||||
A decoded rule for VC7 FP reassociation ranking (which addend pairs first), or first-party evidence of a different loop-1 data flow. After the owner rules on _motion_sensor_update, land u9 as a zero-credit park re-baseline (864/39, sha 0dcb6bf2...).
|
||||
|
||||
## task notes
|
||||
Landable now: production.patch. It is zero exact credit: a structural fix to _render_motion_sensor (the slot swap is gone; the park re-baselines to 784/40, sha 69f4678045fb...), one less surplus COMDAT (`_power`), and a .bss symbol-order fix, so object_audit now shows 0 of 44 January symbols wrong. The patch touches only motion_sensor.c: no header, no consumer sweep, and no symbols.json change.
|
||||
|
||||
Dependency on the stack sentinel: none of the three residuals depends on check_stack_buffer (lab diagnostics e2 and e3 remove the whole sentinel and the residuals stay). The only sentinel-area byte difference in render is an alignment pad driven by code offsets. The object still needs the hud_stack_check lane's check_stack_buffer packet before it can be admitted.
|
||||
|
||||
Held by owner: owner_gated_full.patch gives exact 17 / residual 2. After an owner ruling, the only open rows would be the render scheduler tie and the update reassociation tie.
|
||||
ledger: C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\motion_sensor\LEDGER.md. It records every probe with hypothesis, evidence, change and result: r1-r9 for render, u7-u10 for update, the m4/m5 re-verification, lab e1-e3, d1-d3, L1-L9 and bss1, and all name/local-count oracles. /Od dumps are in od_*.txt. The tree was clean before and after (`git status` empty); no tracked file was touched.
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
# source/interface/motion_sensor :: .bss symbol layout (object admission)
|
||||
|
||||
## verdict
|
||||
ADMISSION_FIX_PROPOSED
|
||||
|
||||
## newly_exact_functions
|
||||
null
|
||||
|
||||
## candidate_files
|
||||
[
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\motion_sensor\\production.patch",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\motion_sensor\\cand_prod.c",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\motion_sensor\\lab\\bss1.c"
|
||||
]
|
||||
|
||||
## production_changes
|
||||
Part of C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\motion_sensor\production.patch (the first hunk; `git apply --check` is clean at 16542e46). In source/interface/motion_sensor.c, `static struct motion_sensor_globals_definition *motion_sensor_globals;` becomes `... = NULL;` and `static real sweep_theta;` becomes `static real sweep_theta = 0.f;`. There are no header, symbols.json or config changes.
|
||||
|
||||
## evidence
|
||||
object_audit on the current build reported 2 of 44 January symbols wrong. January's .bss is next_vertex_index@0, motion_sensor_globals@4, sweep_theta@8, debug_motion_sensor_draw_all_units@0xc; ours put sweep_theta@0 and next_vertex_index@8. By the VC7 .bss law, uninitialised statics come first in name-hash order and `= 0` statics follow in declaration order. The public, `= {0}`-initialised next_vertex_index sits at offset 0 in January, so January's two statics must also have been initialised. With the initialisers, object_audit gives 44 January symbols and 0 differences. The gate stays at exact 16 / residual 3 with no row lost, and pdb_storage gives 0 disagreements. House precedent for the spelling: game.c `static ... *game_globals = NULL;`, players.c `static real ... = 0.f;`. Data was already 100% in report.json, so this earns zero byte credit. It only removes a symbol-offset blocker for completing the object.
|
||||
|
||||
## blockers
|
||||
None for this change. The object still needs the three functions below, plus the hud_stack_check lane's check_stack_buffer packet (held class: the hand-copied sentinel with invented gotos).
|
||||
|
||||
## reopen_criteria
|
||||
n/a
|
||||
|
||||
## task notes
|
||||
Landable now: production.patch. It is zero exact credit: a structural fix to _render_motion_sensor (the slot swap is gone; the park re-baselines to 784/40, sha 69f4678045fb...), one less surplus COMDAT (`_power`), and a .bss symbol-order fix, so object_audit now shows 0 of 44 January symbols wrong. The patch touches only motion_sensor.c: no header, no consumer sweep, and no symbols.json change.
|
||||
|
||||
Dependency on the stack sentinel: none of the three residuals depends on check_stack_buffer (lab diagnostics e2 and e3 remove the whole sentinel and the residuals stay). The only sentinel-area byte difference in render is an alignment pad driven by code offsets. The object still needs the hud_stack_check lane's check_stack_buffer packet before it can be admitted.
|
||||
|
||||
Held by owner: owner_gated_full.patch gives exact 17 / residual 2. After an owner ruling, the only open rows would be the render scheduler tie and the update reassociation tie.
|
||||
ledger: C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\motion_sensor\LEDGER.md. It records every probe with hypothesis, evidence, change and result: r1-r9 for render, u7-u10 for update, the m4/m5 re-verification, lab e1-e3, d1-d3, L1-L9 and bss1, and all name/local-count oracles. /Od dumps are in od_*.txt. The tree was clean before and after (`git status` empty); no tracked file was touched.
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
# source/effects/player_effects
|
||||
|
||||
## verdict
|
||||
FUZZY_IMPROVED
|
||||
|
||||
## newly_exact_functions
|
||||
[]
|
||||
|
||||
## candidate_files
|
||||
[
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\player_effects\\production.patch",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\player_effects\\cm_final.c",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\player_effects\\optional_add_continuous_periodic_local.patch",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\player_effects\\ac1.c",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\player_effects\\cm2.c",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\player_effects\\cm2b.c",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\player_effects\\cm2e.c",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\player_effects\\shadow\\cseries\\cseries.h",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\player_effects\\sweep_pin.txt",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\player_effects\\LEDGER.md"
|
||||
]
|
||||
|
||||
## production_changes
|
||||
One optional zero-credit patch: C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\player_effects\production.patch. `git apply --check` is clean against 16542e46. The full candidate file is scratch/w/player_effects/cm_final.c.
|
||||
|
||||
The patch changes only the body of player_effect_get_camera_effect_matrix. Every change is attested by the /Od build at 0x57ba70:
|
||||
(a) The single `effect_matrix` plus the invented `source` pointer become the RTC-named `real_matrix4x3 impulse_matrix` (declared inside the impulse if-block) and `real_matrix4x3 shake_matrix` (declared inside the shake if-block).
|
||||
(b) The impulse branch now does `*matrix = impulse_matrix;` and the else-branch does `*matrix = *global_identity4x3;`.
|
||||
(c) The invented `real duration` locals are dropped. The effect_scale_value calls read effect->camera_impulse.temporary_duration and effect->camera_shake.duration directly, as /Od does.
|
||||
(d) Declarations follow the /Od order: impulse_matrix, scale, axis; then shake_matrix, scalars, and continuous last (still initialised, per house rule 17).
|
||||
|
||||
What it does not change: the translation keeps production's single-pass arithmetic and the scripted branch keeps its direct stores, so no new header COMDAT is emitted.
|
||||
|
||||
Measured effect:
|
||||
- Whole-TU gate: exact 26 / residual 3, unchanged. Only this row's section bytes change; the symbol set is identical.
|
||||
- provider_link: nothing new to link. fake_match_scan: 0 leads.
|
||||
- Row moves from 1280 [size] to 1296 [size], 49 relocs, normalized sha d4c8a437224a8ecdf17ee890798e95e93e1a546a772b17ca024e02e09a558110.
|
||||
- alndiff difference lines drop from 97 to 65 (375 to 385 of 390 instructions).
|
||||
|
||||
Park impact: the unclassified park for _player_effect_get_camera_effect_matrix must be re-baselined to size 1296 / 49 / the sha above. Land only if re-measured objdiff is above 91.115486.
|
||||
|
||||
Optional and byte-inert: scratch/w/player_effects/optional_add_continuous_periodic_local.patch (`git apply --check` OK). It adds the /Od-attested named `real periodic = periodic_function_evaluate(...)` local between scale and magnitude, and the section sha is identical to production. It matters only as the prerequisite for the PIN route described below.
|
||||
|
||||
No header, config or symbols.json change is proposed.
|
||||
|
||||
## evidence
|
||||
Full log: C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\player_effects\LEDGER.md. Baseline gate: exact 26 / residual 3. _player_effect_start was already exact via 417fc10e.
|
||||
|
||||
(1) _player_effect_add_continuous_effect
|
||||
- /Od readout (0x57b490): the frame has a named local at [ebp-0x14] between scale [ebp-0x10] and magnitude [ebp-0x18] that receives the raw periodic_function_evaluate result. The PIN and MAX compiler temps sit after the named locals, so this is a named local, not a temp.
|
||||
- In a lab TU the named local reproduces January's `fld 1.0; fsub w; fxch st(1); fmul w; faddp` order. In the real TU it does not.
|
||||
- Bisecting cseries.h line by line pins the flip to line 133, `PIN ... CEILING((n),(ceiling))`. Marathon's first-party cseries.h spells it `CEILING(n,ceiling)`.
|
||||
- With a shadow cseries.h (sgate.py), ac1 (named local) plus the Marathon PIN makes the function strict EXACT, with the TU at 27/2. Either change alone stays residual.
|
||||
- Board sweep (sweep.py, all 84 units that expand PIN or interpolate_scalar, SHADOW-SEEN on every compile): exact 2576 -> 2571, 0 gains. Losses: _path_state_traverse, _rasterizer_transparent_geometry_group_draw (15120), _unit_preprocess_node_orientations, _update_human_boat_physics, _update_human_plane_physics.
|
||||
- Other PIN spellings also lose functions. s1 `CEILING(n,(ceiling))` makes ac1 exact but loses 3; s2 `CEILING((n),ceiling)` leaves ac1 residual and loses 2.
|
||||
- Conclusion: the macro's parenthesisation acts as a hidden per-function ordering key, and the production spelling is the board's local optimum.
|
||||
- Inert, measured (production spelling unless noted):
|
||||
- ac2 (declare periodic/magnitude, assign later)
|
||||
- ac4 (scale/periodic/magnitude all declare-then-assign)
|
||||
- ac5 (drop the parens on 1-w)
|
||||
- ac6 (scale* first)
|
||||
- ac7 (p*w first)
|
||||
- ac8 ((real)game_time_get())
|
||||
- ac9 (staged +=; VC7 re-forwards it into one tree)
|
||||
- dead-local sweeps D=0..16
|
||||
- prototype sweeps N=1..32
|
||||
|
||||
(2) _player_effect_get_camera_effect_matrix
|
||||
- /Od readout (0x57ba70; RTC impulse_matrix/axis/shake_matrix): scale_vector3d + point_from_line3d for the impulse translation, set_real_point3d for the scripted translation, and two matrices.
|
||||
- cm2 (fully /Od-shaped): 1312/49, and cluster B (x product forwarded on x87) is SOLVED by scoping each matrix to its own block. The remaining difference is the inlined cross_product3d leaf loads: 22 diff lines here, and 8 (2 transposed pairs) in the hand-expanded twin cm2b.
|
||||
- cm2's new _point_from_line3d and _set_real_point3d COMDATs are IDENTICAL to January's selected copies (ai/action_charge, ai/ai_debug) and pair-link in both orders.
|
||||
- cm2e (without set_real_point3d): the cross product becomes exact, but the scripted-branch store interleave is wrong. This is the n3a exclusive-or, now without cluster B.
|
||||
- Inert on cm2/cm2b:
|
||||
- M8 initialised-dead-local sweeps at the top and at 4 scopes
|
||||
- camera_impulse/camera_shake pointer locals (-> 1296, the A46 RMW flip)
|
||||
- no rotation/translation locals
|
||||
- no camera_shake_ticks
|
||||
- the ?: scale initialiser
|
||||
- /Od declaration order
|
||||
- Marathon PIN
|
||||
|
||||
(3) _player_effect_update_camera_impulse
|
||||
- /Od readout (0x57dea0, RTC names normalized_direction/facing/normalized_facing/facing/perp/permanent_impulse): the calls and their argument order already equal ours.
|
||||
- The residual is the 2 jitter cross_product3d leaf loads plus January's i,k,j term order in BOTH permanent dot products, against our k,j,i.
|
||||
- A lab TU shows the order is intrinsic to the permanent block. Removing the whole temporary block leaves k,j,i. Inert: product-chain order, argument swap, triple_product3d, decl order, preceding functions, dead locals.
|
||||
- ikjscan.py board census: January emits ikj 19 times; the byte-identical examples involve freshly written or nested-inline operands, and no such construct appears in the /Od permanent block.
|
||||
- /Od-attested variants u1 (game_time local), u2 (decl order) and u12 are byte-identical; the M8 sweep D=0..8 is insensitive.
|
||||
|
||||
## blockers
|
||||
The object cannot complete this wave.
|
||||
- _player_effect_add_continuous_effect: EXACT is reachable only with a shared cseries.h PIN respelling, which regresses 5 strict-exact functions board-wide (not landable).
|
||||
- _player_effect_get_camera_effect_matrix: 2 to 5 x87 leaf-order flips remain in the inlined cross_product3d(global_up3d, &effect->direction, &axis). They are coupled to the /Od-attested set_real_point3d scripted translation. The genuine /Od form (cm2) also emits new _point_from_line3d and _set_real_point3d COMDATs from a non-exact caller, which is owner-gated (P1 class) until the row is strictly exact.
|
||||
- _player_effect_update_camera_impulse: January's i,k,j order in both permanent dot products and 2 jitter cross-product leaf loads, with no source lever found.
|
||||
|
||||
## reopen_criteria
|
||||
- add_continuous_effect: a TU-local genuine construct that reproduces the ordering key flipped by the Marathon PIN spelling (ac1 + Marathon PIN is strict EXACT), or a PIN spelling proven on all 84 PIN-expanding units with 0 losses (production, Marathon, s1 and s2 all lose at least 2).
|
||||
- camera_effect_matrix: a source cause for the cross_product3d leaf order under set_real_point3d, starting from cm2.c (22 diff lines, /Od-faithful) or cm2b.c (8). Once strictly exact, cm2's COMDATs are already measured identical and link-clean, so the owner-gated part disappears.
|
||||
- update_camera_impulse: evidence for January's i,k,j dot-term order (both permanent dots) and the 2 jitter cross-product leaf loads. Not local count, argument order, product-chain order or preceding-block context (all measured inert).
|
||||
|
||||
## task notes
|
||||
- Tree was clean at the start and at the end. No tracked file was edited, and no ninja, configure or git-mutating command was run.
|
||||
- Tools written in the slug:
|
||||
- sgate.py: a copy of gate.py whose temp .c sits next to --source, so a shadow header dir wins the quoted-include lookup.
|
||||
- sweep.py: before/after board sweep.
|
||||
- lab.py, m8cm.py, m8pos.py, cmcombo.py, ucivar.py, permorder.py, ikjscan.py, dotctx.py.
|
||||
- New cross-unit observations for the lane:
|
||||
- (a) cseries.h's PIN parenthesisation acts as a hidden x87 ordering key. Marathon's first-party `CEILING(n,ceiling)` fixes add_continuous_effect but costs 5 exact functions board-wide, including _unit_preprocess_node_orientations and a 15,120-byte function. Do not attempt a PIN header packet.
|
||||
- (b) The /Od RTC two-matrix block scoping fixes the camera-matrix x-product forwarding (cluster B). The escape scope of the address-taken matrix is the lever.
|
||||
- (c) For the M8 instrument, uninitialised dead `real` locals are completely inert. Only initialised `long x = 0;` locals exercise the mod-8 key, so earlier "insensitive" readings are only valid if they used initialised locals.
|
||||
ledger: C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\player_effects\LEDGER.md
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
# source/rasterizer/rasterizer_lights :: _rasterizer_lens_flare_submit_for_cluster (400)
|
||||
|
||||
## verdict
|
||||
NO_PROGRESS
|
||||
|
||||
## newly_exact_functions
|
||||
null
|
||||
|
||||
## candidate_files
|
||||
[
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\rasterizer_lights\\od_submit_for_cluster.txt",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\rasterizer_lights\\LEDGER.md"
|
||||
]
|
||||
|
||||
## production_changes
|
||||
none
|
||||
|
||||
## evidence
|
||||
- New characterisation:
|
||||
- January decodes the marker direction per component in i,j,k order: fild/fmul(1/127)/fstp for each. All three char loads (j->ecx, k->edx, i->eax) are hoisted above the first store.
|
||||
- Our set_real_vector3d evaluates the arguments right-to-left (k,j,i) on the x87 stack and then stores i,j,k.
|
||||
- Direct component statements (prior c1-c5 and my x3 C4204 initializer) reproduce January's x87 order but not the load hoisting, because direction's address is taken.
|
||||
- January's own hs_runtime set_real_vector3d(&extents, x1-x0, ...) is also right-to-left.
|
||||
- The later /Od 0x82f710 calls set_real_vector3d with the three products and keeps an otherwise-unused const 1/127 local [ebp-0x58] between parameters and direction.
|
||||
- Measured inert:
|
||||
- const, non-const and outer-block scale locals (kc_const, kc_var, kc_outer, s1).
|
||||
- set_real_vector3d(raw chars) followed by scale_vector3d (x4): loads hoisted, but filds still k,j,i.
|
||||
- Dead-local oracle D=0..17: inert.
|
||||
- TU-name oracles: inert.
|
||||
- The loop-tail load placement (movzx after `add esp; inc`) also still differs.
|
||||
|
||||
## blockers
|
||||
An instruction-order tie in the inline-argument evaluation of the direction decode. No first-party or law-backed spelling reproduces 'loads hoisted + per-component compute/store'.
|
||||
|
||||
## reopen_criteria
|
||||
Reopen with either:
|
||||
- first-party evidence of a different January decode form, for example a byte-direction helper whose parameters are integers; or
|
||||
- a decoded VC7 inline-argument ordering key that produces i-first evaluation with sunk x87 work.
|
||||
Do not replay the c1-c5, s1, x3, x4 or kc_* shapes.
|
||||
|
||||
## task notes
|
||||
No function became strict-exact without an owner ruling, and the object stays blocked by the draw function, submit_for_cluster, and the owner-gated reset.
|
||||
|
||||
**Ready to land** (zero credit, park re-baseline): C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\rasterizer_lights\production.patch. It passes git apply --check and touches three files:
|
||||
- source/rasterizer/rasterizer_lights.c: the P1 storage/layout packet plus the P2 draw changes.
|
||||
- config/symbols.json: 6 in-place line edits; the full edited copy is scratch/w/rasterizer_lights/config/symbols.json.
|
||||
- config/parked.json: the draw park re-baseline.
|
||||
|
||||
Integrator checklist:
|
||||
- Run the csplit regen after applying: only rasterizer_lights.obj changes, verified in the slug with 833 objects.
|
||||
- No header is touched and only this TU changes, so no consumer sweep is needed beyond the normal full ninja.
|
||||
- Verified at the regen split: symbols match 41/41, PDB storage has 0 disagreements, and the unit keeps 10 exact rows.
|
||||
- Every surplus COMDAT is identical to production, so the provider-link status does not change.
|
||||
|
||||
**Owner-gated:** scratch/w/rasterizer_lights/owner_gated_reset.patch makes reset exact (48). It needs an owner ruling on the preserved overrun; the new evidence is that P1 makes the overrun's neighbour identical to January's.
|
||||
|
||||
Laws re-confirmed this wave:
|
||||
- A35 leaf aging is driven by the first definition: an /Od-attested declaration initializer flipped an x87 frame-scalar operand order.
|
||||
- A44: dot_product3d argument order is canonicalised and inert.
|
||||
- The VC7 .bss law: uninitialised statics come first, and the HCEX names force `= {0}` on results.
|
||||
|
||||
One process fact for later workers: Windows file names are case-insensitive, so lab files S1..S5 overwrote s1..s3. The ledger records this, and the affected labs were redone as kc_*.
|
||||
|
||||
A one-unit objdiff 3.3.1 report reproduces build/report.json exactly and was used for all fuzzy numbers (slug od_proj/).
|
||||
ledger: C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\rasterizer_lights\LEDGER.md
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
# source/rasterizer/rasterizer_lights :: _rasterizer_lens_flares_draw (2240, parked)
|
||||
|
||||
## verdict
|
||||
FUZZY_IMPROVED
|
||||
|
||||
## newly_exact_functions
|
||||
null
|
||||
|
||||
## candidate_files
|
||||
[
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\rasterizer_lights\\fin2.c",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\rasterizer_lights\\e3.c",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\rasterizer_lights\\P2_draw_on_P1.patch",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\rasterizer_lights\\P2_draw_standalone.patch",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\rasterizer_lights\\P2_parked_json_rebaseline.patch",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\rasterizer_lights\\config\\parked.json",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\rasterizer_lights\\od_draw.txt"
|
||||
]
|
||||
|
||||
## production_changes
|
||||
Part of production.patch (on top of P1): P2_draw_on_P1.patch. P2_draw_standalone.patch is the draw change alone and applies to the current tree. P2_parked_json_rebaseline.patch re-baselines the park: base normalized_sha256 39103012d0bd42ef0f16cc285c5617331a95ce432f2d7bae17376d3781d79972, objdiff_percent 99.38626, plus appended evidence.
|
||||
Changes:
|
||||
(a) The hand-expanded reflection point (`real offset` plus three component statements, a rule-6 violation) is replaced by the /Od-attested genuine `point_from_line3d(&position, &mirror, reflection->offset, &point);`. It is inlined, so relocations stay at 115/115 and no new COMDAT appears.
|
||||
(b) `real light_brightness = 1.0f;` together with `light_brightness = definition->far_fade_distance > 0.0f ? PIN(...) : 1.0f;`.
|
||||
(c) /Od-attested named locals: `brightness_upper_bound`, `radius_upper_bound`, `boolean set_texture_result` (stores the rasterizer_widget_set_texture result before the unchanged `break` test), and a separate `short sun_lens_flare_index` counter for the ray_of_buddha loop.
|
||||
|
||||
## evidence
|
||||
- /Od 0x82fa10 (the later first-party build), by address:
|
||||
- 0x82fb92: the light variable [ebp-0x6c] is set to 1.0f at block entry.
|
||||
- 0x82fcad-0x82fd8b: the assignment goes through a ?: temporary.
|
||||
- 0x8308c5: point_from_line3d(&corona_position, &corona_axis, reflection->offset, &point) is a real call.
|
||||
- Named slots [ebp-0xc0]/[ebp-0xc4] (brightness lower/upper), [ebp-0xfc]/[ebp-0x100] (radius lower/upper), [ebp-0x105] (set_texture result byte), [ebp-0x140] (second loop counter).
|
||||
- RTC names match the 9 HCEX aggregates.
|
||||
- Measurements:
|
||||
- The initializer closes the +0x202 site: January loads occlusion_fraction first; the initializer ages light_brightness, in line with A35.
|
||||
- The draw function goes from 6 to 5 REAL regions, hash 25834daf -> 39103012.
|
||||
- objdiff one-unit: 99.38321 -> 99.38626.
|
||||
- Unit rows are unchanged (10 exact).
|
||||
- The surplus section set and hashes are identical to production.
|
||||
- fake_match_scan: 0 leads; /W3 warnings unchanged.
|
||||
- The genuine call without the four locals is 19 REAL. Any 4 of the /Od-attested locals {T,B,R,S,C} reach 39103012; the choice is disclosed in LEDGER k3.
|
||||
- The if/else and ?: forms are byte-identical; ?: is taken as /Od-faithful.
|
||||
- Negative results this wave (the pre-existing site-3 interleave was never moved by any variant):
|
||||
- Dead locals at function top, loop body, window block and visible block, D up to 48: inert, or plateaus, never January.
|
||||
- Unused aggregates: inert.
|
||||
- TU names (extern K=0..40 before draw; prototypes K=1..33 at file top): inert.
|
||||
- Visible-block declaration order in /Od order: inert.
|
||||
- Scope moves of camera_offset/direction: inert.
|
||||
- dot_product3d argument swap (A44): inert.
|
||||
- Operand order `occlusion_fraction*light_brightness`: inert.
|
||||
|
||||
## blockers
|
||||
Two residual sites remain:
|
||||
(1) +0x31c: the i-term of the inlined dot_product3d(&direction, &camera_offset). January loads direction.i first; we load camera_offset.i first.
|
||||
(2) +0x738..+0x74e: set_texture argument setup (`xor edx,edx; mov dx,[edi+4]`, `push edx`) is interleaved one x87 slot earlier than in January.
|
||||
No attested lever moved either site. The four /Od locals serve only to keep the fuzzy state and are disclosed; a reviewer may prefer the minimal genuine-call form, which scores lower (19 REAL).
|
||||
|
||||
## reopen_criteria
|
||||
Reopen with either:
|
||||
- a first-party fact that makes `direction` younger than `camera_offset` at the light_to_camera dot (a later definition or escape of direction, or an early definition of camera_offset); or
|
||||
- a decoded C2 scheduling key for the integer/x87 interleave at the set_texture argument setup.
|
||||
Do not replay dead-local, TU-name, declaration-order, scope or argument-order sweeps.
|
||||
|
||||
## task notes
|
||||
No function became strict-exact without an owner ruling, and the object stays blocked by the draw function, submit_for_cluster, and the owner-gated reset.
|
||||
|
||||
**Ready to land** (zero credit, park re-baseline): C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\rasterizer_lights\production.patch. It passes git apply --check and touches three files:
|
||||
- source/rasterizer/rasterizer_lights.c: the P1 storage/layout packet plus the P2 draw changes.
|
||||
- config/symbols.json: 6 in-place line edits; the full edited copy is scratch/w/rasterizer_lights/config/symbols.json.
|
||||
- config/parked.json: the draw park re-baseline.
|
||||
|
||||
Integrator checklist:
|
||||
- Run the csplit regen after applying: only rasterizer_lights.obj changes, verified in the slug with 833 objects.
|
||||
- No header is touched and only this TU changes, so no consumer sweep is needed beyond the normal full ninja.
|
||||
- Verified at the regen split: symbols match 41/41, PDB storage has 0 disagreements, and the unit keeps 10 exact rows.
|
||||
- Every surplus COMDAT is identical to production, so the provider-link status does not change.
|
||||
|
||||
**Owner-gated:** scratch/w/rasterizer_lights/owner_gated_reset.patch makes reset exact (48). It needs an owner ruling on the preserved overrun; the new evidence is that P1 makes the overrun's neighbour identical to January's.
|
||||
|
||||
Laws re-confirmed this wave:
|
||||
- A35 leaf aging is driven by the first definition: an /Od-attested declaration initializer flipped an x87 frame-scalar operand order.
|
||||
- A44: dot_product3d argument order is canonicalised and inert.
|
||||
- The VC7 .bss law: uninitialised statics come first, and the HCEX names force `= {0}` on results.
|
||||
|
||||
One process fact for later workers: Windows file names are case-insensitive, so lab files S1..S5 overwrote s1..s3. The ledger records this, and the affected labs were redone as kc_*.
|
||||
|
||||
A one-unit objdiff 3.3.1 report reproduces build/report.json exactly and was used for all fuzzy numbers (slug od_proj/).
|
||||
ledger: C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\rasterizer_lights\LEDGER.md
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
# source/rasterizer/rasterizer_lights :: _rasterizer_lights_reset_for_new_map (48)
|
||||
|
||||
## verdict
|
||||
BLOCKED
|
||||
|
||||
## newly_exact_functions
|
||||
null
|
||||
|
||||
## candidate_files
|
||||
[
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\rasterizer_lights\\fin_owner2.c",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\rasterizer_lights\\owner_gated_reset.patch"
|
||||
]
|
||||
|
||||
## production_changes
|
||||
OWNER-GATED; do not self-land. scratch/w/rasterizer_lights/owner_gated_reset.patch applies on top of production.patch. It changes the first memset length to `(MAXIMUM_LIGHTS_PER_MAP+1)*sizeof(struct lens_flare_occlusion_test_results)` (0x7722) and adds a `BUG (preserved for exact matching)` comment. The candidate file is fin_owner2.c.
|
||||
|
||||
## evidence
|
||||
- fin_owner2 vs the regen split: 11 exact / 2 residual, and reset is EXACT (48). audit_r: 41/41 January symbols. objdiff one-unit: reset 100, matched code 1996 -> 2044.
|
||||
- New fact: once P1 restores January's .bss layout, the rebuilt object places local_lens_flare_parameters directly after the results array, exactly as January does. The 34 overrun bytes therefore hit params[0] bytes 0..33 in both builds.
|
||||
- This removes the premise of the 2026-09-22 canonical exclusion, which rejected the overrun because "COFF places a different array immediately after the overwritten one".
|
||||
- The lane C 5.4 harmlessness proof then applies verbatim: count is reset in the same function, every read is count-bounded, and records become readable only after a full memcpy.
|
||||
- The alternative spelling from earlier blobs, `sizeof(array)+sizeof(array[0])`, compiles identically.
|
||||
|
||||
## blockers
|
||||
Authentic-bug class (buffer overrun). It needs an explicit owner ruling admitting the BUG-commented overrun. It depends on P1 landing first.
|
||||
|
||||
## reopen_criteria
|
||||
Owner ruling that admits the preserved overrun, now that the neighbour-mismatch objection is gone.
|
||||
|
||||
## task notes
|
||||
No function became strict-exact without an owner ruling, and the object stays blocked by the draw function, submit_for_cluster, and the owner-gated reset.
|
||||
|
||||
**Ready to land** (zero credit, park re-baseline): C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\rasterizer_lights\production.patch. It passes git apply --check and touches three files:
|
||||
- source/rasterizer/rasterizer_lights.c: the P1 storage/layout packet plus the P2 draw changes.
|
||||
- config/symbols.json: 6 in-place line edits; the full edited copy is scratch/w/rasterizer_lights/config/symbols.json.
|
||||
- config/parked.json: the draw park re-baseline.
|
||||
|
||||
Integrator checklist:
|
||||
- Run the csplit regen after applying: only rasterizer_lights.obj changes, verified in the slug with 833 objects.
|
||||
- No header is touched and only this TU changes, so no consumer sweep is needed beyond the normal full ninja.
|
||||
- Verified at the regen split: symbols match 41/41, PDB storage has 0 disagreements, and the unit keeps 10 exact rows.
|
||||
- Every surplus COMDAT is identical to production, so the provider-link status does not change.
|
||||
|
||||
**Owner-gated:** scratch/w/rasterizer_lights/owner_gated_reset.patch makes reset exact (48). It needs an owner ruling on the preserved overrun; the new evidence is that P1 makes the overrun's neighbour identical to January's.
|
||||
|
||||
Laws re-confirmed this wave:
|
||||
- A35 leaf aging is driven by the first definition: an /Od-attested declaration initializer flipped an x87 frame-scalar operand order.
|
||||
- A44: dot_product3d argument order is canonicalised and inert.
|
||||
- The VC7 .bss law: uninitialised statics come first, and the HCEX names force `= {0}` on results.
|
||||
|
||||
One process fact for later workers: Windows file names are case-insensitive, so lab files S1..S5 overwrote s1..s3. The ledger records this, and the affected labs were redone as kc_*.
|
||||
|
||||
A one-unit objdiff 3.3.1 report reproduces build/report.json exactly and was used for all fuzzy numbers (slug od_proj/).
|
||||
ledger: C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\rasterizer_lights\LEDGER.md
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
# source/rasterizer/rasterizer_lights :: storage/.bss layout packet (P1, admission prerequisite)
|
||||
|
||||
## verdict
|
||||
ADMISSION_FIX_PROPOSED
|
||||
|
||||
## newly_exact_functions
|
||||
null
|
||||
|
||||
## candidate_files
|
||||
[
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\rasterizer_lights\\stg.c",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\rasterizer_lights\\P1_storage_layout.patch",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\rasterizer_lights\\P1_symbols_json.patch",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\rasterizer_lights\\config\\symbols.json",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\rasterizer_lights\\split\\source\\rasterizer\\rasterizer_lights.obj"
|
||||
]
|
||||
|
||||
## production_changes
|
||||
Part of C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\rasterizer_lights\production.patch (git apply --check clean). The pieces are also split out: P1_storage_layout.patch and P1_symbols_json.patch. The edited full copy is scratch/w/rasterizer_lights/config/symbols.json, with 6 lines edited in place (CRLF kept, no re-serialise).
|
||||
(1) rasterizer_lights.c: `local_lens_flare_occlusion_test_results[MAXIMUM_LIGHTS_PER_MAP] = {0};` (results2 stays uninitialised).
|
||||
(2) Remove the file-scope `local_lens_flare_error_printed`. Use HCEX's function-static `static boolean warned = FALSE;` as the first line of rasterizer_lens_flare_submit (and use it in the error branch).
|
||||
(3) symbols.json: add "static": true on the rows for _lens_flare_evaluate_corona_rotation_function (line 6213) and _local_lens_flare_occlusion_test_results2, _local_lens_flare_occlusion_test_results, _local_lens_flare_parameters and _local_lens_flare_count (lines 23227-23230).
|
||||
(4) Line 23231: rename _local_lens_flare_error_printed to `?warned@?1??rasterizer_lens_flare_submit@@9@9` with "static": true.
|
||||
The edit is .c-local; no header is touched. Its csplit regen changes only rasterizer_lights.obj.
|
||||
|
||||
## evidence
|
||||
- Layout: January's .bss is results2@0, results@262176, params@292640, count@333600, latch@333604. Ours is results@0, results2@30464.
|
||||
- The VC7 .bss law was measured in a lab. With both arrays uninitialised under their HCEX-attested names (HCEX compiland: local_lens_flare_occlusion_test_results[0x380], ..._results2, local_lens_flare_parameters[0x400], local_lens_flare_count, static-local `warned`), the order is always results first (base, bss3).
|
||||
- `= {0}` on results alone (bss1) gives January's layout, and so does the bss2 form (both initialised, results2 declared first).
|
||||
- bss1 is chosen because it keeps HCEX's declaration order (results, results2).
|
||||
- The static-local latch lands at the same offset 333604. VC7 names it ?warned@?1??rasterizer_lens_flare_submit@@9@9, following the dynavobgeom precedent.
|
||||
- The storage truth comes from cachebeta publics: none of the 6 symbols is public.
|
||||
- csplit regen (build/tools/csplit.exe -i cachebeta.exe -p slug/config -o slug/split): rc 0, 833 objects, and only rasterizer_lights.obj differs from build/split.
|
||||
- Against the regen split:
|
||||
- gate_r: 10 exact, the same as the base, with no loss.
|
||||
- audit_r: 41 January symbols, 0 differ.
|
||||
- PDB storage: 0 disagreements.
|
||||
- objdiff 3.3.1 one-unit data: 335089/335089.
|
||||
- Against the CURRENT split, rasterizer_lens_flare_submit reads [reloc-identity] until the symbols.json line lands, so the source and symbols.json changes must land together.
|
||||
|
||||
## blockers
|
||||
Zero code credit. The object stays blocked by the draw and submit_for_cluster residuals and by the owner-gated reset. The integrator must run the csplit regen and the full sweep. tools/test_rasterizer_lights_frame_runtime.py relies on relocation names _local_lens_flare_count and _local_lens_flare_parameters; this packet leaves both names unchanged (it only adds static storage).
|
||||
|
||||
## reopen_criteria
|
||||
n/a (ready to land).
|
||||
|
||||
## task notes
|
||||
No function became strict-exact without an owner ruling, and the object stays blocked by the draw function, submit_for_cluster, and the owner-gated reset.
|
||||
|
||||
**Ready to land** (zero credit, park re-baseline): C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\rasterizer_lights\production.patch. It passes git apply --check and touches three files:
|
||||
- source/rasterizer/rasterizer_lights.c: the P1 storage/layout packet plus the P2 draw changes.
|
||||
- config/symbols.json: 6 in-place line edits; the full edited copy is scratch/w/rasterizer_lights/config/symbols.json.
|
||||
- config/parked.json: the draw park re-baseline.
|
||||
|
||||
Integrator checklist:
|
||||
- Run the csplit regen after applying: only rasterizer_lights.obj changes, verified in the slug with 833 objects.
|
||||
- No header is touched and only this TU changes, so no consumer sweep is needed beyond the normal full ninja.
|
||||
- Verified at the regen split: symbols match 41/41, PDB storage has 0 disagreements, and the unit keeps 10 exact rows.
|
||||
- Every surplus COMDAT is identical to production, so the provider-link status does not change.
|
||||
|
||||
**Owner-gated:** scratch/w/rasterizer_lights/owner_gated_reset.patch makes reset exact (48). It needs an owner ruling on the preserved overrun; the new evidence is that P1 makes the overrun's neighbour identical to January's.
|
||||
|
||||
Laws re-confirmed this wave:
|
||||
- A35 leaf aging is driven by the first definition: an /Od-attested declaration initializer flipped an x87 frame-scalar operand order.
|
||||
- A44: dot_product3d argument order is canonicalised and inert.
|
||||
- The VC7 .bss law: uninitialised statics come first, and the HCEX names force `= {0}` on results.
|
||||
|
||||
One process fact for later workers: Windows file names are case-insensitive, so lab files S1..S5 overwrote s1..s3. The ledger records this, and the affected labs were redone as kc_*.
|
||||
|
||||
A one-unit objdiff 3.3.1 report reproduces build/report.json exactly and was used for all fuzzy numbers (slug od_proj/).
|
||||
ledger: C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\rasterizer_lights\LEDGER.md
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
# source/rasterizer/xbox/rasterizer_xbox_models::__rasterizer_model_draw
|
||||
|
||||
## verdict
|
||||
FUZZY_IMPROVED
|
||||
|
||||
## newly_exact_functions
|
||||
[]
|
||||
|
||||
## candidate_files
|
||||
[
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\rasterizer_xbox_models\\production.patch",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\rasterizer_xbox_models\\best_candidate.c",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\rasterizer_xbox_models\\parked.patch",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\rasterizer_xbox_models\\config\\parked.json",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\rasterizer_xbox_models\\owner_F1_draw_lab_scaffold.c",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\rasterizer_xbox_models\\LEDGER.md"
|
||||
]
|
||||
|
||||
## production_changes
|
||||
Apply C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\rasterizer_xbox_models\production.patch (one file, source/rasterizer/xbox/rasterizer_xbox_models.c, no header touched; git apply --check clean; applying it to a copy reproduces best_candidate.c (g6) byte for byte). For draw it moves perpendicular, parallel, vertex_constants[3] and specular_constants[2][4] out of function scope into one block. The block opens after shader_get_and_verify_type, at the reflection-colour computation, and closes after the two-sided pass. Declaration order follows the /Od RTC order. Apply it together with parked.patch (config/parked.json; a full edited copy is in scratch/w/rasterizer_xbox_models/config/parked.json), which re-baselines this park: base 5168/348, normalized_sha256 771bf2e799fe91d357ec0dc2e56d91cb8f05be67aad0fc11ea49ffeafc002f26, objdiff 95.71134, with an evidence note appended. Zero exact credit.
|
||||
|
||||
## evidence
|
||||
Baseline: gate 12 exact / 2 residual. Draw is [relocs 348!=350, sha], 56 real regions, 95.08453% (park value reproduced exactly with objdiff-cli 3.3.1 on a private mini-project). The relocation multiset differs only by January's out-of-line _subtract_vectors3d and _point_from_line3d calls at 0x5d2 and 0x605.
|
||||
|
||||
Source shape, three independent sources:
|
||||
- January bytes, via /Od 0x7f6710 (RTC gradient_color [ebp-0x84]), 0x7f704f..0x7f70cd: subtract_vectors3d(&upper,&lower,&gradient_color), then point_from_line3d(&lower,&gradient_color,periodic_function_evaluate(..),&self_illumination_color).
|
||||
- January slot sharing: gradient_color shares with cc1 and seed shares with vertex_shader_work. By the escape-scope law these locals sit in a block that closes before those uses; /Od declares them in the later build's guarded block.
|
||||
- HCEX: real_rgb_color is a union with no vector member, so the casts are needed.
|
||||
|
||||
Finding F1 (lab):
|
||||
- The /Od form alone (c1) still inlines subtract_vectors3d (5184/349).
|
||||
- The site sits exactly one inline-gating step above subtract's cost: one extra if puts the call out of line.
|
||||
- VC7 counts a conditional region BEFORE folding it. `if (TRUE)`, `if (sizeof..)`, `if (shader_model)` and `if (shader)` produce no code, yet make draw [sha]-only: 5168, 350 relocations, frame 0xa4, every January slot including gradient [ebp-0x48].
|
||||
- The same trick around the camera vector_from_points3d breaks it. So January's invisible region starts after the camera-distance statement and encloses the self-illumination block.
|
||||
- Both later lineages guard exactly that section: /Od `if (ps>=1.4 || detail_mask==none)`, and the third-party HCEX decompile (corroboration only) `if (!detail_mask)`. January's bytes have no test there.
|
||||
|
||||
Other decoded fixes:
|
||||
- Plasma sub-structure: /Od 0x7f035c `add eax,0x28` into a named pointer. This makes 0xba exact but flips submit's name-count tie.
|
||||
- Constant-array block: CALL-RESULT ALIAS SCOPE law; January stores the constants early at +0xa88 and +0x12bd.
|
||||
- The lab scaffold c8 (owner_F1_draw_lab_scaffold.c) reaches 99.57182% with 10 real regions, all H3/M8 ties: 0x1da edi reload (+1..3 pre-function declarations), 0x5f9 fstp order, 0xa17 perpendicular.alpha reassociation, and 0xdf9/0xf6d fog x87 first-term order.
|
||||
|
||||
Measured inert: fog operand order (byte-identical), fog declaration order, gradient as real_vector3d, a camo `return;`, extra inline expansions, block position, the C4013 prototype, and dead/unused-local oracles.
|
||||
|
||||
Landable result (best_candidate.c):
|
||||
- 12/14 exact kept; tags unchanged; frame and emitted-symbol set identical to production.
|
||||
- 95.08453 -> 95.71134%, 56 -> 55 real regions.
|
||||
- fake_match_scan 0 leads; /W3 warning set unchanged.
|
||||
|
||||
## blockers
|
||||
F1: January's zero-code conditional region around the self-illumination block cannot be recovered from bytes. Every tested form is an invented condition until there is first-party evidence or an owner ruling.
|
||||
|
||||
The /Od-attested rgb->vector/point casts for the subtract_vectors3d/point_from_line3d calls are byte-inert. They are still owner-gated while the caller is not strictly exact.
|
||||
|
||||
In every bare-block form the plasma sub-structure edit flips the transparent-submit name-count tie. The oracle shows +1..+4 declarations before submit restores it.
|
||||
|
||||
H3/M8 ties remain even with the scaffold.
|
||||
|
||||
## reopen_criteria
|
||||
Reopen if the owner rules on, or first-party evidence names, the January form of the conditional region around the self-illumination block. Measured-equivalent candidates: `if (TRUE)`, `if (shader_model)`, `if (shader)`. That ruling should come together with admitting the /Od-attested casts on the self-illumination colours.
|
||||
|
||||
Then apply the plasma sub-structure (/Od 0x7f035c) and close the H3/M8 ties listed in owner_F1_draw_lab_scaffold.c. Re-gate transparent submit after every draw edit; it is a name-count canary.
|
||||
|
||||
## task notes
|
||||
Neither function became exact.
|
||||
|
||||
Key new mechanism, F1: VC7's per-site inline gating counts an if-region before it folds the condition. `if (TRUE)` or a null test of an already-dereferenced pointer produces no code, yet drops the site's budget by one step. This explains January's out-of-line _subtract_vectors3d in draw, with no visible test in the bytes. With such a region plus the /Od-attested calls, the block scopes and the plasma sub-structure, draw reaches [sha]-only at 99.57%: size, relocations, frame and every slot are exact. That is an owner question (the January condition is unrecoverable), not a landing.
|
||||
|
||||
Also measured: plane3d_distance_to_point inlines at any depth when its argument is a constant global address, and stays out of line when the argument is a pointer local. That argument-shape effect contradicts the Lane C law that argument shape is inert, and it explains the draw/env asymmetry.
|
||||
|
||||
The transparent-submit function (already exact) is a fragile canary: plasma and many bare-block draw edits flip its tie. The integrator must run the full sweep after applying. The production patch keeps submit and all other 11 exact functions exact against both the current and the regenerated split.
|
||||
ledger: C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\rasterizer_xbox_models\LEDGER.md has every probe, recorded as hypothesis, evidence, change and result: c1..c9, d1/d3, f1..f3, g1..g6, lab L_*, oracle o/u/f/s series, env e_* and L_h_*. It also has the evidence pass (E1-E6), the objdiff mini-project measurements, the csplit/audit verification, the do-not-repeat list and the reopen criteria.
|
||||
|
||||
No tracked file was modified; git status is clean. One stray redirect to /LEDGER.md was attempted before a shell variable was set. It failed with permission denied and nothing was created (verified).
|
||||
|
||||
Deliverables are in scratch/w/rasterizer_xbox_models/:
|
||||
- production.patch (.c only; draw 95.08->95.71, env 95.87->96.39; 12/14 exact kept);
|
||||
- parked.patch and config/parked.json (both parks re-baselined);
|
||||
- symbols.patch and config/symbols.json (5 wrapper storage rows; csplit changes only this object);
|
||||
- best_candidate.c (g6);
|
||||
- owner_F1_draw_lab_scaffold.c (not landable).
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
# source/rasterizer/xbox/rasterizer_xbox_models::_rasterizer_model_draw_environment_shader
|
||||
|
||||
## verdict
|
||||
FUZZY_IMPROVED
|
||||
|
||||
## newly_exact_functions
|
||||
[]
|
||||
|
||||
## candidate_files
|
||||
[
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\rasterizer_xbox_models\\production.patch",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\rasterizer_xbox_models\\best_candidate.c",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\rasterizer_xbox_models\\env\\L_h_blkpp.c",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\rasterizer_xbox_models\\mk_envh.py"
|
||||
]
|
||||
|
||||
## production_changes
|
||||
Part of the same production.patch. The environment shader changes are:
|
||||
- The hand-expanded camera vector is replaced by vector_from_points3d(&camera.position,&local_parameters->centroid,&camera_to_model), as in /Od 0x7f305a.
|
||||
- perpendicular and parallel become real_argb_color, the /Od RTC 16-byte reflection colours, replacing four brightness/colour locals.
|
||||
- cc0_error becomes real_rgb_color (/Od 12 bytes); the pixel call passes &cc0_error.
|
||||
- Fog block, in /Od RTC declaration order: `real camera_plane_distance= plane3d_distance_to_point(&fog.plane,&camera.position)` and `camera_distance = dot_product3d(&camera.forward,&camera_to_model)` (/Od 0x7f37bb and 0x7f385b). These replace the hand-expanded plane distance and dot product inside the PINs.
|
||||
- vertex_constants and specular_constants, plus a declared-and-initialised detail_map_scale, move into a block around the constant stores (CALL-RESULT ALIAS SCOPE law).
|
||||
- vertex_shader_permutation is declared right after shader_environment (/Od order).
|
||||
|
||||
parked.patch re-baselines this park: base 3104/235, normalized_sha256 a4a4ca436d309778ff1ad21a7b5cbe35e4701fc4b4c22e06ae7263d206dfa9bb, objdiff 96.38508, with an evidence note appended. Zero exact credit.
|
||||
|
||||
## evidence
|
||||
Baseline [sha], 70 real regions, 95.87124%. /Od 0x7f2f80 RTC names: forward, argb reflection_view_perpendicular_color and parallel_color, vsh_constants__texscale 48, vsh_constants__effect 32, cc0 16, cc0_error 12, cc1 12. Named fog locals come from the /Od code.
|
||||
|
||||
January inlines plane3d_distance_to_point here. This fits a draw-side finding: a constant global address makes the helper cheap enough to inline at any depth, while a pointer local keeps it out of line.
|
||||
|
||||
Measured:
|
||||
- w3 a2 spellings: 41 real regions (3104).
|
||||
- Adding the named fog locals and the constants block (odloc + blk) gives 38 real regions and 96.38508%. Submit and draw hashes are unchanged, so no canary moves.
|
||||
- Variants g3/g4/g5/g6 (declaration+initialisation, detail scale declared in the block, /Od declaration orders) are byte-identical.
|
||||
|
||||
Lab only, not landable:
|
||||
- A TU-local __inline set_real_vector4d plus perpendicular/parallel/constants in one block (L_h_blkpp) reproduces January's 0x3f3..0x46b window. That window is the `mov edx,[esi+0xb4]; mov ecx,edx` copy with stores after the perpendicular stores, which fixes the w3 blocker. Size is still 3120 (97.39%).
|
||||
- L_h_noblk (w3 s3) scores 97.88% at 3120.
|
||||
- Direct D3DDevice_SetRenderState for ALPHATESTENABLE: inert.
|
||||
- Detail scale read twice: 3120.
|
||||
|
||||
In this build and in the split, set_real_vector4d's only definer is environment_fog, as a NODUP copy (flags 32 in symbols.json).
|
||||
|
||||
## blockers
|
||||
January's detail-scale copy needs set_real_vector4d as a genuine shared-header __inline. That is a shared real_math.h-class header edit (board-wide declaration-count blast radius) that replaces environment_fog's NODUP hand copy. It is P1 class until this caller is strictly exact.
|
||||
|
||||
Remaining +16 bytes: January computes the ALPHATESTENABLE value straight into edi (`movzx edi,byte [esi+0x28]`), while ours computes it in eax and copies it (allocator homing). Plus downstream register rotations and the cc0/cc1 pixel edi/ebx permutation. No decoded source cause.
|
||||
|
||||
## reopen_criteria
|
||||
Reopen when a shared-header packet turns set_real_vector4d into the genuine header __inline, with a board sweep and environment_fog's hand copy removed. Combine it with the measured blkpp scope and a decoded cause for the edi homing of the ALPHATESTENABLE value and the cc0/cc1 pixel edi/ebx permutation.
|
||||
|
||||
## task notes
|
||||
Neither function became exact.
|
||||
|
||||
Key new mechanism, F1: VC7's per-site inline gating counts an if-region before it folds the condition. `if (TRUE)` or a null test of an already-dereferenced pointer produces no code, yet drops the site's budget by one step. This explains January's out-of-line _subtract_vectors3d in draw, with no visible test in the bytes. With such a region plus the /Od-attested calls, the block scopes and the plasma sub-structure, draw reaches [sha]-only at 99.57%: size, relocations, frame and every slot are exact. That is an owner question (the January condition is unrecoverable), not a landing.
|
||||
|
||||
Also measured: plane3d_distance_to_point inlines at any depth when its argument is a constant global address, and stays out of line when the argument is a pointer local. That argument-shape effect contradicts the Lane C law that argument shape is inert, and it explains the draw/env asymmetry.
|
||||
|
||||
The transparent-submit function (already exact) is a fragile canary: plasma and many bare-block draw edits flip its tie. The integrator must run the full sweep after applying. The production patch keeps submit and all other 11 exact functions exact against both the current and the regenerated split.
|
||||
ledger: C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\rasterizer_xbox_models\LEDGER.md has every probe, recorded as hypothesis, evidence, change and result: c1..c9, d1/d3, f1..f3, g1..g6, lab L_*, oracle o/u/f/s series, env e_* and L_h_*. It also has the evidence pass (E1-E6), the objdiff mini-project measurements, the csplit/audit verification, the do-not-repeat list and the reopen criteria.
|
||||
|
||||
No tracked file was modified; git status is clean. One stray redirect to /LEDGER.md was attempted before a shell variable was set. It failed with permission denied and nothing was created (verified).
|
||||
|
||||
Deliverables are in scratch/w/rasterizer_xbox_models/:
|
||||
- production.patch (.c only; draw 95.08->95.71, env 95.87->96.39; 12/14 exact kept);
|
||||
- parked.patch and config/parked.json (both parks re-baselined);
|
||||
- symbols.patch and config/symbols.json (5 wrapper storage rows; csplit changes only this object);
|
||||
- best_candidate.c (g6);
|
||||
- owner_F1_draw_lab_scaffold.c (not landable).
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
# source/rasterizer/xbox/rasterizer_xbox_models (ownership)
|
||||
|
||||
## verdict
|
||||
ADMISSION_FIX_PROPOSED
|
||||
|
||||
## newly_exact_functions
|
||||
[]
|
||||
|
||||
## candidate_files
|
||||
[
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\rasterizer_xbox_models\\config\\symbols.json",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\rasterizer_xbox_models\\symbols.patch",
|
||||
"C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\rasterizer_xbox_models\\audit_r.py"
|
||||
]
|
||||
|
||||
## production_changes
|
||||
config/symbols.json: in-place edits keeping CRLF. Full edited copy: C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\rasterizer_xbox_models\config\symbols.json. Patch: C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\rasterizer_xbox_models\symbols.patch (git apply --check clean).
|
||||
|
||||
Append `, "static": true` to lines 5844 (_D3DDevice_SetRenderState, 1417552), 5845 (_D3DDevice_SetTextureStageState, 1417984), 5847 (_IDirect3DDevice8_SetRenderState@12, 1419072), 5848 (_IDirect3DDevice8_SetTextureStageState@16, 1419616) and 5849 (_IDirect3DDevice8_SetVertexShaderConstant@16, 1419712).
|
||||
|
||||
This is independent of the .c patch and earns zero code credit. It needs a csplit regen.
|
||||
|
||||
## evidence
|
||||
pdb_storage: the five D3DINLINE wrapper rows of this object are external in the split, static in ours, and absent from cachebeta publics. Same fix class as the dynavobgeom, shadows and rasterizer_xbox wrapper rows.
|
||||
|
||||
csplit regen (build/tools/csplit.exe -i cachebeta.exe -p slug/cfg -o slug/split): rc 0, 833 objects, only rasterizer_xbox_models.obj differs.
|
||||
|
||||
Against the regenerated split, best_candidate.obj is 12/14 strict exact. The slug-copied object audit (AUDIT_SPLIT_ROOT) shows 58/58 January symbols equal; only the two residual .text sections differ, FAIL(2).
|
||||
|
||||
build/report.json data is 1912/1912 (100%). No object_admission_rejections entry exists. The surplus COMDAT set is unchanged from production.
|
||||
|
||||
## blockers
|
||||
The object is not admissible even when all bytes match:
|
||||
- the two residual functions above;
|
||||
- TU-local struct views with opaque spans (rasterizer_debug_options, rasterizer_model_begin_parameters, shader_*_definition, rasterizer_models_frame_statistics);
|
||||
- the C4013 implicit declaration of rasterizer_frame_statistics_count_static_vertices. The owner header include is blocked by the local frame-statistics view (w3 A7, owner decision).
|
||||
|
||||
## reopen_criteria
|
||||
Reopen the whole object when both functions close. It also needs genuine shared declarations to replace the TU-local views (dynavobgeom precedent) and the rasterizer_frame_statistics.h layout/owner ruling (vertices_by_permutation vs the object counts at +0x14; renaming +0x150..+0x168).
|
||||
|
||||
## task notes
|
||||
Neither function became exact.
|
||||
|
||||
Key new mechanism, F1: VC7's per-site inline gating counts an if-region before it folds the condition. `if (TRUE)` or a null test of an already-dereferenced pointer produces no code, yet drops the site's budget by one step. This explains January's out-of-line _subtract_vectors3d in draw, with no visible test in the bytes. With such a region plus the /Od-attested calls, the block scopes and the plasma sub-structure, draw reaches [sha]-only at 99.57%: size, relocations, frame and every slot are exact. That is an owner question (the January condition is unrecoverable), not a landing.
|
||||
|
||||
Also measured: plane3d_distance_to_point inlines at any depth when its argument is a constant global address, and stays out of line when the argument is a pointer local. That argument-shape effect contradicts the Lane C law that argument shape is inert, and it explains the draw/env asymmetry.
|
||||
|
||||
The transparent-submit function (already exact) is a fragile canary: plasma and many bare-block draw edits flip its tie. The integrator must run the full sweep after applying. The production patch keeps submit and all other 11 exact functions exact against both the current and the regenerated split.
|
||||
ledger: C:\halo-worktrees\claude-fifty-objects-20260925\scratch\w\rasterizer_xbox_models\LEDGER.md has every probe, recorded as hypothesis, evidence, change and result: c1..c9, d1/d3, f1..f3, g1..g6, lab L_*, oracle o/u/f/s series, env e_* and L_h_*. It also has the evidence pass (E1-E6), the objdiff mini-project measurements, the csplit/audit verification, the do-not-repeat list and the reopen criteria.
|
||||
|
||||
No tracked file was modified; git status is clean. One stray redirect to /LEDGER.md was attempted before a shell variable was set. It failed with permission denied and nothing was created (verified).
|
||||
|
||||
Deliverables are in scratch/w/rasterizer_xbox_models/:
|
||||
- production.patch (.c only; draw 95.08->95.71, env 95.87->96.39; 12/14 exact kept);
|
||||
- parked.patch and config/parked.json (both parks re-baselined);
|
||||
- symbols.patch and config/symbols.json (5 wrapper storage rows; csplit changes only this object);
|
||||
- best_candidate.c (g6);
|
||||
- owner_F1_draw_lab_scaffold.c (not landable).
|
||||
@@ -0,0 +1,153 @@
|
||||
# collision_bsp worker ledger (wave 4, base 16542e46)
|
||||
|
||||
## 0. Baseline
|
||||
- base.c == source/physics/collision_bsp.c at 16542e46.
|
||||
- gate --all: exact 27 / residual 3 / unwritten 0.
|
||||
- residual 1504 _bsp3d_test_pill_recursive [sha]
|
||||
- residual 800 _bsp3d_test_sphere_recursive [sha]
|
||||
- residual 880 _collision_surface_test_sphere [size 848!=880, sha]
|
||||
- Prior ledgers read: waveD 20260914, 150k w2 20260914, lane B REPORT + rejected hypotheses 20260920.
|
||||
- Owner-held: collision_surface_test_sphere SSE __asm macro (20260915 "leave parked for now"); no new __asm in production.
|
||||
- Recorded negatives (do not repeat): operand/argument spelling of dot/plane-distance helpers; point_from_line3d
|
||||
(guarded; physics collision_bsp not in the 17-object list?); early fabs locals; named center pointer; dot before distance;
|
||||
HCEA result->t > t; dead locals D=1..8 at fn top (M8 instrument); assert form variants; && vs nested if; same-size casts
|
||||
(unsigned long plane_stack); S2 named distance; S3 local projection_from_vector3d copy; S4 LONG_MAX|LONG_MIN; P1-P3 pill.
|
||||
|
||||
## 1. bsp3d_test_sphere_recursive
|
||||
- Residual at base: ONE pair: leaf plane-distance dot at T 0x1e7..0x1f3 January loads j-term first (fld [eax+4]; add esp,0xc;
|
||||
fmul [edi+4]; fld [eax+8]; fmul [edi+8]) where ours loads k first. Everything else (287/287 insns, 22 relocs) equal.
|
||||
- /Od 0x7aafe0 readout (od_sphere3d.txt): leaf = distance=plane3d_distance_to_point(plane,data->center) (real call);
|
||||
point_from_line3d(data->center,&plane->n,-distance,¢er_projected_on_plane [RTC 12B]);
|
||||
data->projection_axis=projection_from_vector3d(&plane->n); int tmp=(designator&LONG_MIN)?1:0;
|
||||
data->projection_sign=projection_sign_from_vector3d(&plane->n,data->projection_axis)!=tmp; project_point3d(&cpop,axis,sign,&data->center2d);
|
||||
bsp2d_test_sphere_recursive(data, reference->root_index); break. Loop bound /Od: movsx count; add first.
|
||||
Assert lines /Od 0x207/0x211 vs January 0x206/0x210 (1-line drift).
|
||||
- NEW since Lane B (20260920): real_math.h projection_from_vector3d body corrected 4f4c8502 (Sep 22), and the
|
||||
all-inlined header-COMDAT class admitted (owner 20260921 #5) -> the /Od helper form is now landable if exact.
|
||||
- s1 (hyp: full /Od leaf helper form changes IL ordinals/expression count and flips j/k): leaf = distance local +
|
||||
point_from_line3d(-distance) + projection_from_vector3d + projection_sign helper. RESULT: byte-identical residual
|
||||
(same single j/k pair; 27/3). Helper-vs-expansion INERT for this function (consistent with Lane B P2 for pill).
|
||||
- Lane B lab files preserved at C:/halo-worktrees/claude-lane-b-ai-physics-units-20260920/scratch/lane_b/w/collision_bsp/
|
||||
(micro1-7, lab_site_*, lab_sph_D1-8, lab_pill_D1-7). Lane B kept `while` because "January has a real loop" and never
|
||||
measured the /Od tail-call spelling.
|
||||
- NEW HYPOTHESIS H-TRE: /Od 0x7ab1d3..0x7ab1e8 shows the single-sided descent is a real self-recursive TAIL CALL
|
||||
(`bsp3d_test_sphere_recursive(data, node->children[b])`) inside `if (!(node_index & LONG_MIN)) {...} else if (node_index != NONE) {...}`.
|
||||
If VC7 /O2 performs tail-recursion elimination, January's loop (test/js top, jns bottom, reference_index homed in the
|
||||
node_index param slot) is the COMPILER's loop, and the IL (call args -> param reassignment) carries a different
|
||||
expression inventory before the leaf dot -> can flip the j/k parity bit. Test s2.
|
||||
- s2 (H-TRE: /Od tail-call recursion `if{...}else recurse(children[b])` + `else if (node_index != NONE)` leaf, no while):
|
||||
RESULT byte-identical to base (VC7 /O2 DOES do tail-recursion elimination here; produces January's loop exactly).
|
||||
Inert for the j/k bit. (Fact: the /Od recursive spelling and the while loop are byte-equivalent in this function.)
|
||||
- Emission-order finding: January emits in bottom-up order edge_count, polygon, add_feature, render_debug x4, edge_length,
|
||||
perimeter, area, project_point2d, test_point2d, find_closest_point2d, test_line2d, surface_test_sphere, surface_test_point,
|
||||
sphere_test_vector, test_pill_new_recursive, bsp2d_sphere, leaf_test_vector, pill_test_vector, test_pill_new, bsp3d_sphere,
|
||||
test_vector_recursive, surface_test_pill, test_sphere, test_vector, bsp2d_pill, bsp3d_pill, test_pill. Ours defers
|
||||
test_pill_new/test_pill/test_sphere/test_vector to the end (public-first definition order) and emits add_feature after test_line2d.
|
||||
=> January's DEFINITION order differs from ours. Assert anchors: polygon 0xe1=225, sphere3d 0x206=518, pill3d 0x498=1176;
|
||||
only ~293 January lines between polygon and sphere3d => January's definition order is NOT its emission order either
|
||||
(deferral happened). TU name-count law (lane C 20260921): names declared BEFORE a function in the TU span set arena
|
||||
ordinals -> definition order is a candidate source fact for the hidden-key ties.
|
||||
- /Od build link order is ALPHABETICAL (add_feature 0x7aa190, bsp2d_pill, bsp2d_sphere, bsp3d_pill, bsp3d_sphere,
|
||||
collision_bsp_test_pill, ...): gives no definition-order evidence.
|
||||
- HCEX.pdb line info (hcex_lines.txt): 2011 file order polygon 213, project_point2d 243, test_point2d 258, find_closest 297,
|
||||
test_line2d 397, test_sphere 475, bsp3d_sphere 507-592, bsp2d_sphere 597, surface_test_sphere 619-755, [756-842 ?],
|
||||
add_feature 843, test_vector 904, tvr 946, leaf_test_vector 1074, surface_test_point 1115, test_pill 1163, bsp3d_pill 1182,
|
||||
bsp2d_pill 1340, surface_test_pill 1373, pill_test_vector 1443, sphere_test_vector 1527 (top-down by query).
|
||||
HCEX emission order = LEVEL ORDER (repeated deferral passes, ties in def order) - reproduced exactly by the model
|
||||
"compile in def order; defer a function whose TU callee is not yet compiled; re-scan deferred list until empty".
|
||||
Same model reproduces OUR emission order. January emission = level order with pass1 = [edge_count, polygon, add_feature,
|
||||
rd_vertex, rd_edge, rd_surface, rd_bsp, edge_length, perimeter, area, p2d, tp2d, fcp, tl2d, sts, stp, stv, pnr],
|
||||
pass2 = [bsp2d_sphere, ltv, ptv, test_pill_new], pass3 = [bsp3d_sphere, tvr, stpill], pass4 = [test_sphere, test_vector,
|
||||
bsp2d_pill], pass5 = [bsp3d_pill], pass6 = [test_pill] => January is TOP-DOWN like HCEX (callers before callees), unlike
|
||||
ours (public first, private bottom-up). add_feature is defined before surface_test_sphere in January (pass 1).
|
||||
- ORACLE (lab only, never lands): K=0..24 opaque `struct oracle_k;` names at file scope right before bsp3d_test_sphere_recursive:
|
||||
all three residual hashes (947b5817 / 0f9c2342 / b8b40ff3) and 27/3 UNCHANGED for every K. => the TU name-count
|
||||
(arena ordinal) key does NOT govern these x87 order ties; the key is in-function (M8 / Lane B parity law). Definition
|
||||
order of OTHER functions is therefore not a lever for them either (it only changes names before the function).
|
||||
- /Od loop bound reads `movsx edx,word[count]; add edx,[first]` => 2020 source spells `leaf->bsp2d_reference_count +
|
||||
leaf->first_bsp2d_reference_index` (count first); ours spells first + count. Same op count; IL node order differs. Test s4.
|
||||
- s4 (/Od count+first loop bound in sphere3d): byte-identical residual. INERT.
|
||||
- Read lane C research (claude-lane-c .../scratch/research/x87-scheduling/FINDINGS.md): LAW T (single-expression sum emits
|
||||
reversed k,j,i; accumulator form emits forward i,j,k). January's sphere leaf is j,k,i = neither; so LAW T does not apply.
|
||||
astra research5 (20260920): sphere leaf j/k is a nonzero-offset term pair, outside M8.
|
||||
- LAB L1sp (instrument only, never lands): `lab_sink_long(node_index > 5);` (one live GT + extern call) inserted at the top of
|
||||
the LEAF WALK of BOTH bsp3d functions => the sphere leaf dot flips to January's j,k order AND the pill's two leaf dots
|
||||
flip to January's k,j order simultaneously (all other diffs are the added call). CONFIRMS Lane B's single shared parity
|
||||
bit in situ: January has an odd count of extra distinct live operator expressions between the node dot and the leaf dot
|
||||
in BOTH functions (most naturally in the shared leaf walk or node tail idiom).
|
||||
- p1 (pill: /Od 2020 push form `(plane & LONG_MAX) | (front ? LONG_MIN : 0)`): WORSE (+1 insn, many new hunks at 0x11e..).
|
||||
=> January's pill push is the two-arm ?: (current source); the 2020 /Od source differs from January here. Rejected.
|
||||
- Diagnostic parity map (lab only, instruments; lab_diag1.py): sphere leaf dot flips with: long stack_index (D3), dropping
|
||||
`| LONG_MIN` (D4), dropping `& LONG_MAX` (D5), dropping the NONE test (D7); NOT with children[1] for children[b] (D6, even).
|
||||
=> every single live op between node dot and leaf dot toggles it; no /Od-attested construct differs there.
|
||||
- Lane B dead-local instrument objects re-read with tools/dots.py (i-term first operand per D):
|
||||
pill n1(0x3c) D0..7 = eax,eax,eax,ECX,ECX,eax,eax,eax (Jan ecx); n2(0x59) = ecx,ecx,EAX,ecx,ecx,ecx,ecx,ecx (Jan eax);
|
||||
L1(0x23e) = eax,eax,eax,eax,edi,edi,edi,eax (Jan eax); L2(0x265) = edi x7, EAX at D7 (Jan eax).
|
||||
sphere node/leaf S0..8 = (eax,edi)(eax,edi)(eax,edi)(eax,eax)(ecx,eax)(ecx,eax)(ecx,edi)(eax,edi)(eax,edi) (Jan eax,edi).
|
||||
M8 fit: n1 operands (n-temp = point-temp - 2); n2 (n-temp = vector-temp + 1). January needs relative shifts n1 +3/+4,
|
||||
n2 +2, L2 +7(-1): i.e. January has 1-2 FEWER ordinals between the n1 and n2 temps and 3 fewer between n2 and L2 than ours.
|
||||
- KEY M8 observation: the full /Od helper-form leaf removes exactly 8 named locals (absolute_i/j/k, projection,
|
||||
plane_distance, negative_distance, negative_dot, result_plane) => local count unchanged mod 8, and the helper temps are
|
||||
created after the leaf dots => explains why Lane B P2 (full /Od leaf) was byte-identical to P1.
|
||||
- pv1 (pill: full /Od 2020 helper-form leaf: projection_from_vector3d, projection_sign, point_from_line3d x4 incl. the
|
||||
(real_point3d*) sweep-vector view, -plane3d_distance_to_point arg, plane3d_negate): L2 i-term now matches (eax) =
|
||||
Lane B P1 effect; hunks 30 -> 29; n1/n2 i-terms and leaf j/k unchanged. Emits point_from_line3d/projection_from_vector3d
|
||||
COMDATs (only admissible if the caller becomes strict exact).
|
||||
- pv1 + D dead locals (instrument): D0 (eax,ecx,eax,eax) D1 (eax,EAX,eax,eax) h28, D2 same h24, D3 (ECX,ecx,edi,eax)...
|
||||
=> with pv1 the node sites respond DIFFERENTLY than with base although pv1 removed exactly 8 locals: the node i-term
|
||||
ordinals depend on the LEAF's inline-helper composition (consistent with Lane B S3: a leaf helper flipped node i-terms).
|
||||
- Tail labs on pv1 (instrument): T1/T2 (extra helper dot sites at the function end): node i-terms UNCHANGED (later inline
|
||||
sites do not renumber earlier ones). T3 (one live named `real` local declared at the END): n1 -> ECX and n2 -> EAX, i.e.
|
||||
BOTH node i-terms become January's, and L1/L2 i-terms stay January's (eax,eax). => the node i-term operands are the
|
||||
named `plane` local vs an inline temp; January has +1 (mod 8) named local declared AFTER `plane` relative to pv1.
|
||||
/Od 2020 node has exactly one more named local than ours: `d` plus `distance0 = d` (d,dot,distance0,distance1). Test pv2.
|
||||
- pv2 = pv1 + /Od node locals (`real distance = plane3d_distance_to_point(...); real dot = ...; real distance0 = distance;
|
||||
real distance1 = distance + dot;`): ALL FOUR i-terms now January's (n1 ecx, n2 eax, L1 eax, L2 eax). 26 hunks.
|
||||
Remaining: (2) leaf j/k at 0x23e/0x265, (3) 0x3cc k,i,j, (4) int/x87 interleave 0x4da/0x4ea/0x520/0x52c.
|
||||
- Parity instruments on pv2 (I1 long stack_index, I2 no NONE test, I3 sink): leaf j/k flip to January AND the 0x3cc hunk
|
||||
VANISHES => class (3) is the same parity bit as class (2) (and as the sphere's leaf). Only class (4) is independent.
|
||||
- pb1 (base + /Od node locals only) and pb2 (pb1 + real plane3d_negate call, no new COMDAT): node i-terms UNCHANGED
|
||||
(eax,ecx), L2 still edi, 30 hunks => the i-term fixes need the /Od leaf helper composition (pv1) AND the node locals.
|
||||
pv2 is therefore the best reconstruction but it emits point_from_line3d/projection_from_vector3d COMDATs (P1 class unless
|
||||
the pill becomes strict exact).
|
||||
- pc1 = pb2 + real projection_from_vector3d (no point_from_line3d): n1 ECX, n2 EAX (fixed) but L1 -> edi (broken), 28 hunks.
|
||||
Every i-term-correct variant needs a NEW header COMDAT (projection_from_vector3d and/or point_from_line3d) from a non-exact
|
||||
caller (P1 class) => not landable while the pill is fuzzy. pv2 retained as evidence only.
|
||||
- owner_gated_asm.c (= Lane B surfsphere_asm_variantA.c, base + unit-local SSE __asm macro) still gates
|
||||
EXACT 880 _collision_surface_test_sphere at 16542e46 (28/2). Owner-held (no new __asm, 20260915); NOT landable.
|
||||
- NEW HYPOTHESIS H-FOR: C1 parses a for-header's increment expression BEFORE the loop body, a while-loop's end-of-body
|
||||
increment AFTER it. So `for (...; ...; stack_index++)` creates the ADD before the leaf dot, `while` after => -1 live op
|
||||
before the dot = the parity flip, with (probably) identical loop code. Test a while-form stack loop / reference loop.
|
||||
- w1b (reference loop as while with end-of-body increment): byte-identical to base (dot order unchanged) => H-FOR REFUTED
|
||||
for the reference loop. w1a/w1c (stack loop as while): code changes massively (720 bytes, frame differs) => January's
|
||||
stack loop is a `for`. Parity bit still unexplained.
|
||||
- k4 (project_point3d(point_from_line3d(...)) nested, pv2+parity instrument): identical to k0 -> class-4 interleave inert.
|
||||
c4a/c4b (operand order of the hand-expanded start/sweep components): class 4 inert. tools/c4.py signature:
|
||||
JAN "IXXIIIXIXXX XXIIIXIXXXX" vs ours "IXIXIIIXXXX XIXIIIXXXXX" (int ops one x87 op early in both blocks), unchanged by
|
||||
D (M8), parity, helper/hand-expansion, nesting, operand order.
|
||||
|
||||
## 2. Admission findings (whole-object audit, brief section 4)
|
||||
- pdb_storage: `_collision_bsp_usage_times` is NOT a cachebeta public (only collision_bsp.obj defines it; no January object
|
||||
references it) => January file-static. st1.c = base + `static` on its definition: gate 27/3 unchanged, all sections equal,
|
||||
ours storage 3. Needs config/symbols.json `"static": true` on its line (edited copy: config/symbols.json) + csplit-only regen.
|
||||
=> production.patch (+ symbols.json line op). Data stays 100% (.bss 16 B).
|
||||
- provider_link on the full candidate: TWO LNK2005 conflicts block eventual completion:
|
||||
(a) `_cross_product2d` vs actor_combat.obj NODUP hand copy (the held P1 item; collision_bsp is a 6th object it blocks);
|
||||
(b) `_plane2d_distance_to_point` vs geometry.obj NODUP hand copy (`#define plane2d_distance_to_point ..._inline` rename +
|
||||
hand-written body in source/math/geometry.c). NEW. Only geometry and collision_bsp define the symbol board-wide.
|
||||
geom/g1.c = Layer-1-style repair (drop the rename and the hand copy; the genuine real_math.h inline is used): geometry gate
|
||||
27/3 unchanged, EVERY geometry function hash unchanged (incl. the 3 parked residuals), `_plane2d_distance_to_point` EXACT
|
||||
32 B with SELECT_ANY (2) instead of NODUP (1), object_audit output identical, pair link with collision_bsp clean in both
|
||||
orders. January's own link had collision_bsp emitting the used-inline COMDAT, which is only link-compatible with an ANY
|
||||
geometry copy => the header inline is the authentic provider form. => geometry_provider_repair.patch (separate unit).
|
||||
- Surplus COMDATs of base: all 21 byte-identical to January's selected providers (surplus_identity).
|
||||
|
||||
## 3. Final disposition (stop rule reached)
|
||||
- _collision_surface_test_sphere: owner-held SSE __asm (exact with the held macro, owner_gated_asm.c); no new evidence.
|
||||
- _bsp3d_test_sphere_recursive: ONE parity bit (leaf dot j/k). /Od shapes s1/s2/s4 inert; TU-name oracle inert; H-FOR refuted.
|
||||
- _bsp3d_test_pill_recursive: decomposed into (1) M8 i-terms [fixed by pv2 = /Od helper leaf + /Od node locals, but needs
|
||||
point_from_line3d + projection_from_vector3d COMDATs (both byte-identical to January's selected copies) => only landable
|
||||
if the function becomes strict exact], (2)+(3) the SAME parity bit as the sphere, (4) int/x87 interleave (independent).
|
||||
- Reopen: a January-era source fact adding/removing exactly ONE live operator expression in the shared node-tail/leaf-walk
|
||||
idiom (it must flip BOTH bsp3d functions; lab L1sp proves any one op there does). Then sphere = exact from base or s1;
|
||||
pill = pv2 + that fact + a class-4 fact (scheduler interleave of project_point3d argument setup).
|
||||
@@ -0,0 +1,28 @@
|
||||
diff --git a/source/math/geometry.c b/source/math/geometry.c
|
||||
index 34401c6b..d17e0d3b 100644
|
||||
--- a/source/math/geometry.c
|
||||
+++ b/source/math/geometry.c
|
||||
@@ -185,9 +185,7 @@ symbols in this file:
|
||||
|
||||
#include "cseries.h"
|
||||
|
||||
-#define plane2d_distance_to_point plane2d_distance_to_point_inline
|
||||
#include "real_math.h"
|
||||
-#undef plane2d_distance_to_point
|
||||
|
||||
#include "geometry.h"
|
||||
|
||||
@@ -543,13 +541,6 @@ boolean convex_hull3d_verify(void)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
-real plane2d_distance_to_point(
|
||||
- real_plane2d const *plane,
|
||||
- real_point2d const *point)
|
||||
-{
|
||||
- return (plane->n.i*point->x + plane->n.j*point->y) - plane->d;
|
||||
-}
|
||||
-
|
||||
real vector_intersect_plane2d(
|
||||
real_point2d const *point,
|
||||
real_vector2d const *vector,
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,48 @@
|
||||
diff --git source/physics/collision_bsp.c scratch/w/collision_bsp/owner_gated_asm.c
|
||||
index b4438fa9..23e70768 100644
|
||||
--- source/physics/collision_bsp.c
|
||||
+++ scratch/w/collision_bsp/owner_gated_asm.c
|
||||
@@ -118,6 +118,9 @@ enum contents
|
||||
#define BSP3D_TEST_PILL_EPSILON (1.f/4096.f)
|
||||
#define BSP2D_TEST_PILL_EPSILON (1.f/8192.f)
|
||||
|
||||
+/* hand-written SSE squared distance between the points a and b, stored through result */
|
||||
+#define fast_distance_squared3d(a, b, result) { real_point3d const *fast_distance_a = (a); real_point3d const *fast_distance_b = (b); real *fast_distance_result = (result); __asm mov eax, fast_distance_result __asm mov ecx, fast_distance_a __asm movss xmm0, dword ptr [ecx] __asm movhps xmm0, qword ptr [ecx+4] __asm mov ecx, fast_distance_b __asm movss xmm1, dword ptr [ecx] __asm movhps xmm1, qword ptr [ecx+4] __asm subps xmm0, xmm1 __asm mulps xmm0, xmm0 __asm movss xmm2, xmm0 __asm shufps xmm0, xmm0, 0Eh __asm addss xmm2, xmm0 __asm shufps xmm0, xmm0, 39h __asm addss xmm2, xmm0 __asm movss dword ptr [eax], xmm2 }
|
||||
+
|
||||
/* ---------- structures */
|
||||
|
||||
struct collision_bsp_test_pill_new_context
|
||||
@@ -1078,7 +1081,7 @@ static void collision_surface_test_sphere(
|
||||
byte breakable_surface_index;
|
||||
long edge_index;
|
||||
real radius_squared;
|
||||
- boolean hit_feature = FALSE;
|
||||
+ boolean hit_feature;
|
||||
|
||||
if (TEST_FLAG(surface->flags, _collision_surface_breakable_bit))
|
||||
{
|
||||
@@ -1092,6 +1095,7 @@ static void collision_surface_test_sphere(
|
||||
}
|
||||
}
|
||||
|
||||
+ hit_feature = FALSE;
|
||||
radius_squared = data->radius * data->radius;
|
||||
edge_index = surface->first_edge_index;
|
||||
do
|
||||
@@ -1106,14 +1110,9 @@ static void collision_surface_test_sphere(
|
||||
&data->bsp->vertices,
|
||||
vertex_index,
|
||||
struct collision_vertex);
|
||||
- real delta_x = vertex->point.x - data->center->x;
|
||||
- real delta_y = vertex->point.y - data->center->y;
|
||||
- real delta_z = vertex->point.z - data->center->z;
|
||||
- real distance_squared =
|
||||
- delta_x * delta_x +
|
||||
- delta_y * delta_y +
|
||||
- delta_z * delta_z;
|
||||
+ real distance_squared;
|
||||
|
||||
+ fast_distance_squared3d(&vertex->point, data->center, &distance_squared);
|
||||
if (distance_squared <= radius_squared)
|
||||
{
|
||||
add_feature(
|
||||
@@ -0,0 +1,13 @@
|
||||
diff --git a/source/physics/collision_bsp.c b/source/physics/collision_bsp.c
|
||||
index b4438fa9..49456e37 100644
|
||||
--- a/source/physics/collision_bsp.c
|
||||
+++ b/source/physics/collision_bsp.c
|
||||
@@ -302,7 +302,7 @@ void render_debug_collision_edge(
|
||||
|
||||
/* ---------- globals */
|
||||
|
||||
-struct collision_bsp_usage_times collision_bsp_usage_times = { 0 };
|
||||
+static struct collision_bsp_usage_times collision_bsp_usage_times = { 0 };
|
||||
|
||||
/* ---------- public code */
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,121 @@
|
||||
diff --git source/physics/collision_bsp.c scratch/w/collision_bsp/pv2.c
|
||||
index b4438fa9..37906fd8 100644
|
||||
--- source/physics/collision_bsp.c
|
||||
+++ scratch/w/collision_bsp/pv2.c
|
||||
@@ -2036,9 +2036,10 @@ static boolean bsp3d_test_pill_recursive(
|
||||
&data->bsp->bsp3d.planes,
|
||||
node->plane_designator,
|
||||
real_plane3d);
|
||||
- real distance0 = plane3d_distance_to_point(plane, data->point);
|
||||
+ real distance = plane3d_distance_to_point(plane, data->point);
|
||||
real dot = dot_product3d(data->vector, &plane->n);
|
||||
- real distance1 = dot + distance0;
|
||||
+ real distance0 = distance;
|
||||
+ real distance1 = distance + dot;
|
||||
boolean reaches_back =
|
||||
distance0 <= data->radius + BSP3D_TEST_PILL_EPSILON ||
|
||||
distance1 <= data->radius + BSP3D_TEST_PILL_EPSILON;
|
||||
@@ -2115,34 +2116,20 @@ static boolean bsp3d_test_pill_recursive(
|
||||
|
||||
if (data->result->t > t)
|
||||
{
|
||||
- real absolute_i = fabs(plane->n.i);
|
||||
- real absolute_j = fabs(plane->n.j);
|
||||
- real absolute_k = fabs(plane->n.k);
|
||||
- short projection;
|
||||
real_point3d pill_point;
|
||||
- real plane_distance;
|
||||
real_point2d point2d;
|
||||
long surface_index;
|
||||
- real_point3d start_point;
|
||||
- real_point3d sweep_point;
|
||||
- real negative_distance;
|
||||
- real negative_dot;
|
||||
-
|
||||
- if (absolute_k >= absolute_j && absolute_k >= absolute_i)
|
||||
- projection = _z;
|
||||
- else
|
||||
- projection = absolute_j >= absolute_i ? _y : _x;
|
||||
- data->projection_axis = projection;
|
||||
+
|
||||
+ data->projection_axis = projection_from_vector3d(&plane->n);
|
||||
data->projection_sign =
|
||||
- projection_sign_from_vector3d(&plane->n, projection) !=
|
||||
+ projection_sign_from_vector3d(&plane->n, data->projection_axis) !=
|
||||
(reference->plane_designator & LONG_MIN ? TRUE : FALSE);
|
||||
- pill_point.x = data->vector->i*t + data->point->x;
|
||||
- pill_point.y = data->vector->j*t + data->point->y;
|
||||
- pill_point.z = data->vector->k*t + data->point->z;
|
||||
- plane_distance = -plane3d_distance_to_point(plane, &pill_point);
|
||||
- pill_point.x = plane->n.i*plane_distance + pill_point.x;
|
||||
- pill_point.y = plane->n.j*plane_distance + pill_point.y;
|
||||
- pill_point.z = plane->n.k*plane_distance + pill_point.z;
|
||||
+ point_from_line3d(data->point, data->vector, t, &pill_point);
|
||||
+ point_from_line3d(
|
||||
+ &pill_point,
|
||||
+ &plane->n,
|
||||
+ -plane3d_distance_to_point(plane, &pill_point),
|
||||
+ &pill_point);
|
||||
project_point3d(
|
||||
&pill_point,
|
||||
data->projection_axis,
|
||||
@@ -2169,12 +2156,7 @@ static boolean bsp3d_test_pill_recursive(
|
||||
data->result->t = t;
|
||||
if (reference->plane_designator & LONG_MIN)
|
||||
{
|
||||
- real_plane3d *result_plane = &data->result->plane;
|
||||
-
|
||||
- result_plane->n.i = -plane->n.i;
|
||||
- result_plane->n.j = -plane->n.j;
|
||||
- result_plane->n.k = -plane->n.k;
|
||||
- result_plane->d = -plane->d;
|
||||
+ plane3d_negate(plane, &data->result->plane);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2185,24 +2167,27 @@ static boolean bsp3d_test_pill_recursive(
|
||||
hit = TRUE;
|
||||
}
|
||||
|
||||
- negative_distance = -distance0;
|
||||
- start_point.x = plane->n.i*negative_distance + data->point->x;
|
||||
- start_point.y = plane->n.j*negative_distance + data->point->y;
|
||||
- start_point.z = plane->n.k*negative_distance + data->point->z;
|
||||
- project_point3d(
|
||||
- &start_point,
|
||||
- data->projection_axis,
|
||||
- data->projection_sign,
|
||||
- &data->point2d);
|
||||
- negative_dot = -dot;
|
||||
- sweep_point.x = plane->n.i*negative_dot + data->vector->i;
|
||||
- sweep_point.y = plane->n.j*negative_dot + data->vector->j;
|
||||
- sweep_point.z = plane->n.k*negative_dot + data->vector->k;
|
||||
- project_point3d(
|
||||
- &sweep_point,
|
||||
- data->projection_axis,
|
||||
- data->projection_sign,
|
||||
- (real_point2d *)&data->vector2d);
|
||||
+ {
|
||||
+ real_point3d start_point;
|
||||
+ real_vector3d sweep_vector;
|
||||
+
|
||||
+ point_from_line3d(data->point, &plane->n, -distance0, &start_point);
|
||||
+ project_point3d(
|
||||
+ &start_point,
|
||||
+ data->projection_axis,
|
||||
+ data->projection_sign,
|
||||
+ &data->point2d);
|
||||
+ point_from_line3d(
|
||||
+ (real_point3d const *)data->vector,
|
||||
+ &plane->n,
|
||||
+ -dot,
|
||||
+ (real_point3d *)&sweep_vector);
|
||||
+ project_point3d(
|
||||
+ (real_point3d const *)&sweep_vector,
|
||||
+ data->projection_axis,
|
||||
+ data->projection_sign,
|
||||
+ (real_point2d *)&data->vector2d);
|
||||
+ }
|
||||
if (bsp2d_test_pill_recursive(data, reference->root_index))
|
||||
{
|
||||
hit = TRUE;
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,48 @@
|
||||
diff --git source/physics/collision_bsp.c scratch/w/collision_bsp/s1.c
|
||||
index b4438fa9..cb41dc74 100644
|
||||
--- source/physics/collision_bsp.c
|
||||
+++ scratch/w/collision_bsp/s1.c
|
||||
@@ -1694,32 +1694,20 @@ static void bsp3d_test_sphere_recursive(
|
||||
&data->bsp->bsp3d.planes,
|
||||
reference->plane_designator & LONG_MAX,
|
||||
real_plane3d);
|
||||
- real plane_distance = -plane3d_distance_to_point(plane, data->center);
|
||||
- real_point3d projected_center;
|
||||
- real absolute_i;
|
||||
- real absolute_j;
|
||||
- real absolute_k;
|
||||
- short projection;
|
||||
-
|
||||
- projected_center.x =
|
||||
- plane->n.i * plane_distance + data->center->x;
|
||||
- projected_center.y =
|
||||
- plane->n.j * plane_distance + data->center->y;
|
||||
- projected_center.z =
|
||||
- plane->n.k * plane_distance + data->center->z;
|
||||
- absolute_i = fabs(plane->n.i);
|
||||
- absolute_j = fabs(plane->n.j);
|
||||
- absolute_k = fabs(plane->n.k);
|
||||
- if (absolute_k >= absolute_j && absolute_k >= absolute_i)
|
||||
- projection = _z;
|
||||
- else
|
||||
- projection = absolute_j >= absolute_i ? _y : _x;
|
||||
- data->projection_axis = projection;
|
||||
+ real distance = plane3d_distance_to_point(plane, data->center);
|
||||
+ real_point3d center_projected_on_plane;
|
||||
+
|
||||
+ point_from_line3d(
|
||||
+ data->center,
|
||||
+ &plane->n,
|
||||
+ -distance,
|
||||
+ ¢er_projected_on_plane);
|
||||
+ data->projection_axis = projection_from_vector3d(&plane->n);
|
||||
data->projection_sign =
|
||||
- projection_sign_from_vector3d(&plane->n, projection) !=
|
||||
+ projection_sign_from_vector3d(&plane->n, data->projection_axis) !=
|
||||
(reference->plane_designator & LONG_MIN ? TRUE : FALSE);
|
||||
project_point3d(
|
||||
- &projected_center,
|
||||
+ ¢er_projected_on_plane,
|
||||
data->projection_axis,
|
||||
data->projection_sign,
|
||||
&data->center2d);
|
||||
@@ -0,0 +1,295 @@
|
||||
# game_engine_finish LEDGER (tree 16542e46; task: finish whole-object admission of source/game/game_engine)
|
||||
|
||||
## F0 setup / rebase
|
||||
- Tree clean at 16542e46. review3 R01/R03/R05c patches no longer apply (f7cd2e72 renamed game_variant members,
|
||||
game_engine.h struct rewritten). R02/R04/R05h/R06 still apply.
|
||||
- Rebase method: `git merge-file -p HEAD 954eebd2 review3-final` (LF-normalised copies in base954/ head/ theirs/ merged/).
|
||||
2 conflicts only:
|
||||
(a) game_engine.c render_nav_points condition: head `universal_variant.goal_radar == 1 && (short)local_player_index != NONE`
|
||||
vs R01 `unknown24 == 1 && local_player_index != NONE` (R01 made the parameter `short`) -> resolved to
|
||||
`global_variant.universal_variant.goal_radar == 1 && local_player_index != NONE`.
|
||||
(b) game_engine.h struct universal_variant/game_variant: R03 did not touch it (base struct) -> took HEAD's recovered layout.
|
||||
R03's other hunks (float->real, short local_player_index, 2 multiplayer-sound prototypes) merged cleanly.
|
||||
- rebased/ = LF files; shadow/ = full copy of working-tree source/ with rebased files installed (CRLF).
|
||||
- rcompile.py (copy of reviewer harness, production cflags, cwd = shadow):
|
||||
control real tree: 180/180 EXACT, 0 changed vs base. REBASED shadow: 180/180 EXACT, 0 of 302 changed vs build/base.
|
||||
|
||||
## F1 open item (1) game_engine_man_out -> CLOSED (EXACT, /Od-attested)
|
||||
- Hypothesis: January's man_out has NO int materialisation on the false path (`test al,al; jne T; pop edi; pop ebp; ret`,
|
||||
T: `mov al,1`), i.e. a BOOLEAN-typed value reaches the return; reviewer's mo_v1/v2 (`return a||b||c;`) give
|
||||
`xor eax,eax / mov eax,1` (int-typed || result), mo_v3 (`result=FALSE; if(chain) result=TRUE;`) adds a callee-saved bl.
|
||||
/Od 0x5a0b90: player slot [ebp-4], a NAMED byte local [ebp-5] assigned from the ||-temp [ebp-6], then `mov al,[ebp-5]`
|
||||
=> `boolean man_out = player->quit_out_of_game || is_out_of_lives(player_index) || is_odd_man_out(player_index); return man_out;`
|
||||
(the one spelling the reviewer did not try: a declaration-initialised named boolean).
|
||||
- mo_a1 (exactly that; is_out_of_lives stays the ordinary public call, VC7 inlines it as January did):
|
||||
180/180 EXACT, 0 of 302 changed vs build/base.
|
||||
- /Od cross-check: our VC7 at /Od /RTC1 on mo_a1 gives the same topology (player slot, named byte local, ||-temp,
|
||||
3 real calls, one return); only the temp width differs (VC7 dword temp vs the 2020 compiler's byte temp) = compiler version.
|
||||
- Storage: _game_engine_player_is_out_of_lives and _game_engine_man_out are cachebeta PUBLICS (external, used by race/slayer);
|
||||
_game_engine_player_is_odd_man_out absent = static (already static). No storage change.
|
||||
|
||||
## F2 open item (2) motion-sensor copy (evidence; no new EXACT natural form yet)
|
||||
- HCEX: `struct netgame_goal { real_point3d position; uchar in_use; long player_index@0x10; short team_index@0x14;
|
||||
long ignore_player_index@0x18; short nav_index@0x1C }` (global `global_goal[0x20]`, external), real_point3d has NO 2d member
|
||||
(x,y,z / u,v,w / n[3]). HCEX params: (long player_index, real_point2d *points, char *goal_indices, short max_points).
|
||||
- /Od 0x5a20e0: frame 0xc = count(short,[ebp-4]) + player([ebp-8]) + goal_index(long,[ebp-0xc]); NO goal pointer slot;
|
||||
ONE statement copies 8 bytes with integer movs (index recomputed once: `shl ecx,5; mov edx,[ecx+x]; mov eax,[ecx+y];
|
||||
mov [esi+ecx*8],edx; mov [esi+ecx*8+4],eax`) => `points[count] = *(real_point2d *)&global_goal[goal_index].position;`
|
||||
(a /Od component copy would be two statements, each re-indexing). The 3D->2D view is a pervasive Bungie idiom (January
|
||||
assert strings in actors.c/actor_looking.c stringify `(real_vector2d *) &...`).
|
||||
- January O2 differs between spellings only in the strength-reduced IV base: ms_n1 (direct component copies) picks
|
||||
`&global_goal[i].position.y` (+4) as IV (`mov esi,4`, `cmp esi,0x404`); January/ms_n2(alias)/ms_n3(view copy) use +0.
|
||||
- Status: ms_n2 (in-loop `struct game_engine_goal *goal = &global_goal[goal_index];`, current rebased packet) EXACT but the
|
||||
alias is an extra named local absent from the /Od frame; ms_n3 (/Od view copy) EXACT but a LOAD-BEARING view copy (strip
|
||||
-> ms_n1 residual) = owner-gated class (brief s.2/s.7). Both are compliant with every other rule.
|
||||
|
||||
## F3 name-count sensitivity oracle (lab only, never lands)
|
||||
- nc_K: K dummy enum constants inserted after the TU MULTIPLAYER_MAXIMUM_PLAYERS enum (top of TU), K = 1,2,4,8,13,16,24,32,40:
|
||||
all 180/180 EXACT, 0 changed vs base => game_engine.c has no name-count-fragile function for +1..+40 TU-top names.
|
||||
(So TU-local enum definitions for rule 16 are low-risk; still re-measured on every candidate.)
|
||||
|
||||
## F4 open item (4) populate_statistic_buffer walks -> CLOSED (EXACT, /Od-attested)
|
||||
- /Od 0x5b5e60 (RTC: player_iterator 16B): locals in order player_count(=0 init), invert byte = `statistic==4 ? !inverse : inverse`
|
||||
(int ternary temps), player_iterator, player (loop-1 `while (player = data_iterator_next(&it))`), loop index,
|
||||
player_index, player (loop 2), loop index 3; loop 1 body = `match_assert(player_count < MAX); if (player_count < MAX)
|
||||
{ buf[player_count].player_index = it.datum_index; player_count++; }`; loops 2/3 INDEXED (imul 0x1c every access), no
|
||||
entry pointer; last loop calls sort_statistic_buffer_ranking(&buf[i-1], &buf[i]) == 0.
|
||||
- Assert-anchor drift: January asserts 0x2C8 -> 0x2FD (53 lines), /Od 0x48a -> 0x4bf (53 lines): same span length =>
|
||||
the /Od source for this span is January's.
|
||||
- HCEX: populate_statistic_buffer(struct statistic_buffer *statistic_buffer, enum postgame_statistic statistic,
|
||||
unsigned char inverse) local player_iterator.
|
||||
- psb_a1 = exactly that shape (params statistic_buffer/statistic/boolean inverse; indexed loops with one index local
|
||||
`statistic_index` reused for loops 2 and 3; the tied bit stays `|= 0x80000000`): 180/180 EXACT, 0 changed vs base.
|
||||
Replaces: `long invert_parameter` + `(boolean)` casts, if/else assert shape, do/while `entry++` walks, `previous` alias.
|
||||
|
||||
## F5 more statistic-walk items (all EXACT, /Od-attested)
|
||||
- Assert-anchor drift proves the /Od span populate..get_player_place..generate_title_string is January's text length:
|
||||
January 712/765 -> 866 -> 878; /Od 1162/1215 -> 1316 -> 1328 (constant +450 offset).
|
||||
- gpp_a1 game_engine_get_player_place = /Od 0x59d9f0: `struct statistic_buffer statistic_buffer[MULTIPLAYER_MAXIMUM_PLAYERS];
|
||||
long place = 0; populate_statistic_buffer(statistic_buffer, 0, FALSE); while (TRUE) { if (buf[place].player_index ==
|
||||
player_index) break; place++; match_assert(place<MULTIPLAYER_MAXIMUM_PLAYERS); } return buf[place];` (/Od `mov edx,1;
|
||||
test edx,edx` = constant-true loop) -> EXACT (gpp_a2 plain while-condition also EXACT; a1 chosen = /Od form).
|
||||
Replaces the hand-rotated `if (x) do {...} while (x)`.
|
||||
- sp_a1 select_players_to_display = /Od 0x5b6920 names (RTC statistic_buffer 448B, outside_range 112B) + the /Od
|
||||
local-player COUNT in loop 1 (`if (player->local_player_index != NONE) local_player_count++;`, dead at /O2: January's
|
||||
loop body is exactly the surviving player_get call) -> EXACT, byte-inert (replaces the bare discarded
|
||||
`player_get(...)` statement). Disclosure: local_player_count is dead in January (/Od-attested, not a filler).
|
||||
sp_a2 (the 2020 memmove size `(max - k - 1) * sizeof`) RESIDUAL -> January keeps `max*sizeof - (k+1)*sizeof`.
|
||||
- gr_a1 postgame_statistic_get_rating with HCEX `boolean inverse` RESIDUAL: January forwards the 3rd param with
|
||||
`mov eax,dword ptr [ebp+0x10]` (32-bit param) while populate reads `mov al,byte ptr [ebp+0x10]` (byte param).
|
||||
gr_a3 get_rating(long player_index, long statistic, long inverse) + populate(..., boolean inverse) + /Od locals
|
||||
(statistic_buffer[MAX], `player_count = 0` init then call, rating = 0 after the call) -> EXACT.
|
||||
- c1 = rebased + mo_a1 + psb_a1 + gpp_a1 + sp_a1 + gr_a3 (+TU prototypes renamed): 180/180 EXACT, 0 changed vs base.
|
||||
|
||||
## F6 NEW blocker found + fixed: game_engine_predict_resources hand-inlined list_index_to_weapon_definition_index (rule 13)
|
||||
- Source had 14 hand copies of `game_globals = scenario_get_game_globals(); weapon = TAG_BLOCK_GET_ELEMENT(&game_globals->
|
||||
weapon_list, N, struct tag_reference); ... weapon->index` (grenades 12/13, ball 10, flag 11, weapon_indices[0..9]).
|
||||
- /Od 0x5a5fc0 (2020 revision, more vehicle sets + 16-entry initialiser) calls list_index_to_weapon_definition_index
|
||||
(0x5b4150, same callee as /Od remap_equipment's final call) for every one; January emits list_index_to_... (#65) before
|
||||
predict_resources (#118), so VC7 inlines the calls (NONE guard folds).
|
||||
- pr_a1 (calls restored, `struct tag_reference *weapon` local dropped) EXACT; pr_a2 (+ `for (weapon_index = 0;
|
||||
weapon_index < 10; weapon_index++)` replacing the hand while-loop) EXACT; pr_a3 (NUMBEROF bound, unsigned) RESIDUAL.
|
||||
- Side finding (zero-credit, optional): COMMON pool records game_engine_globals/timeout_for_endgame_sound/global_stage
|
||||
(0x592540..) sit between the players(288) cluster and game.c(309)'s game_variant_global; game_engine.c (module 307) is
|
||||
the only TU using game_engine_globals/global_stage, but ours only has `extern` declarations and no TU defines them.
|
||||
Not an audit blocker (split shows them UNDEF); not changed here.
|
||||
|
||||
## F7 open item (3) rule-16 switch tables -> CLOSED (byte-inert, all EXACT)
|
||||
- lab/r16.py -> lab/r16.json (48 count-checked edits) on top of c2; c3 = c2 + r16: 180/180 EXACT, 0 changed vs base.
|
||||
- TU-local enums added in the constants block (after MULTIPLAYER_MAXIMUM_PLAYERS; F3 showed no name-count fragility):
|
||||
* `enum game_engine_mode` {game_engine_mode_active, _postgame_delay, _postgame_rasterize_delay, _postgame_rasterize}
|
||||
= HCEX names verbatim; REPLACES the invented mid-file `enum game_engine_postgame_state` (removed); used in the 4
|
||||
postgame_state switches and every postgame_state compare/store.
|
||||
* `enum postgame_statistic` (HCEX tag name; HCEX PDB has no constants) {_postgame_statistic_ranking (0: fills the
|
||||
sort_statistic_buffer_ranking fields; January public name), _score, _kills, _assists, _deaths,
|
||||
NUMBER_OF_POSTGAME_STATISTICS}: DESCRIPTIVE constant names (disclosed).
|
||||
* `enum game_engine_weapons` (HCEX names) 0..9 = HCEX 0..9 (behaviour-checked against remap_weapon: pistols ->
|
||||
pistol/plasma pistol, rifles -> AR/plasma rifle, plasma, sniping, no sniping, rockets, shotguns, short range, human).
|
||||
VALUE 10 = `_game_engine_weapons_no_grenades`, NOT HCEX's `_covenant`: January's set 10 (a) makes remap_equipment
|
||||
return NONE for grenades, (b) zeroes starting grenades unless infinite, (c) has NO remap_weapon case; /Od 2020 gives
|
||||
exactly (a)+(b) to set 13 `_no_grenades` (jump tables decoded: remap_equipment 3,10->plasma 9->frag 13->NONE;
|
||||
starting grenades 3,10->plasma 9->frag 13->zero) and adds a covenant remap case => the enum was reordered after
|
||||
January. NUMBER_OF_GAME_ENGINE_WEAPON_SETS = 11 matches January's `PIN(weapon_set, 0, 10)`.
|
||||
* `enum game_engine_vehicles` (HCEX names) 0..4 {default, none, warthog, ghost, tank} (remap_vehicle: 1 -> NONE,
|
||||
2/3/4 -> vehicles block 0/1/2), NUMBER = 5 matches January's `PIN(vehicle_set, 0, 4)`.
|
||||
* unnamed `_weapon_list_*` enum (HCEX names) 0..13 (12/13 grenades attested by remap_equipment, 10/11 ball/flag by
|
||||
remap_weapon + predict_resources' oddball/ctf branches); HCEX's 14/15 + count omitted (no January evidence).
|
||||
- Converted: statistic switch + callers (select_players_to_display, get_player_place, 4x get_rating), weapon_set switches
|
||||
(remap_equipment, remap_weapon, starting-grenade switch), weapon_list switches/compares, vehicle_set switches
|
||||
(remap_vehicle, predict_resources, `!= none`), variant_cleanup PINs + game_engine_index switch (existing
|
||||
game_engine_ctf/game_engine_slayer), predict_resources oddball/ctf compares, both internal_rasterize_score switches
|
||||
(existing TU `_game_engine_message_*`), and the 52 builder `weapon_set/vehicle_set = N` stores.
|
||||
- Left as literals (not enums): `switch (remaining_lives)` 0/1 (a count), did_player_win NONE/FALSE/TRUE (January's
|
||||
tied value is NONE, not HCEX game_win_type's 0xFF).
|
||||
|
||||
## F8 goal-struct naming (rule 21) + flag/constant pass (rule 18) -> all EXACT
|
||||
- HCEX `struct netgame_goal {position; in_use; long player_index@0x10; short team_index@0x14; long ignore_player_index@0x18;
|
||||
short nav_index@0x1C}`; our `game_engine_goal` had 0x10 `target_object_index` (compared with player_index in
|
||||
goal_matches_player = semantically a player index) and 0x18 `player_index` (the `player_index != x` exclusion = HCEX
|
||||
ignore_player_index). lab/goal.py: tag -> netgame_goal, fields renamed per HCEX, explicit pad members dropped
|
||||
(natural alignment = same 0x20 layout, verify typedef kept), set_goal_position params (player_index, team_index,
|
||||
ignore_player_index) in definition + game_engine.h prototype. c4 = c3 + goal: 180/180, 0 changed.
|
||||
- NEW rule-13 find: game_engine_infinite_grenades hand-expanded game_engine_infinite_grenades_internal (the
|
||||
`!TEST_FLAG(globals.flags,2) && TEST_FLAG(variant.flags, infinite)` body). /Od 0x5a08d0: `result = FALSE; if
|
||||
(game_engine_running() && player_index != NONE) result = internal();` (calls 0x5a0920 = internal). ig_a1 (keep
|
||||
`game_engine &&`) and ig_a2 (/Od form) both EXACT; ig_a2 adopted.
|
||||
- Builders: `flags = (flags & ~M) | V` is hand bit twiddling (rule 18). /Od 2020 builders spell one SET_FLAG per bit
|
||||
(constant-condition ternaries). bf_asc / bf_desc (one SET_FLAG per bit in M|V, ascending/descending): both EXACT
|
||||
(VC7 folds them into January's single `and ecx,~M; or ecx,V`). Adopted ascending order with named bits.
|
||||
- Flag names corrected per HCEX semantics, all consistent with January code:
|
||||
game_engine_globals.flags: bit0 was `_game_engine_allow_dynamic_lighting_bit` but SET when many players/vehicles and
|
||||
allow_dynamic_lighting returns !TEST_FLAG -> HCEX `disable` semantics => `_game_engine_disable_dynamic_lighting_bit`;
|
||||
bit1 likewise `_disable_integrated_lights_bit`; bit2 was `_game_engine_disable_infinite_grenades_bit` but set iff
|
||||
player_count >= 5 (build_lighting) => HCEX `_game_engine_5_or_more_players_bit`; + bit3 `_9_or_more_players_bit`
|
||||
(set iff >= 9; remap_equipment 0.3 vs 0.55 spawn thinning), bit4 `_game_over_sound_disabled_bit` (set with the
|
||||
postgame sound-class fade).
|
||||
universal_variant.flags: bit1 placeholder `_game_variant_unknown1_bit` -> `_game_variant_allow_friendly_navpoints_bit`
|
||||
(display_team_indicators; HCEX _allow_friendly_navpoints_bit); + bit5 `_game_variant_generic_starting_equipment_bit`
|
||||
(gates handle_custom_starting_equipment; HCEX _generic_starting_equipment_bit).
|
||||
These live in game_engine.h (header patch; renames + 3 added enum constants; only game_engine.c references them).
|
||||
- Also: remap_equipment powerup_type 2/3 -> existing `_equipment_powerup_overshield/_active_camouflage`; get_place_name
|
||||
`(place.flags & FLAG(2))` + bare bits -> TEST_FLAG with the existing HCEX `_place_*` constants (game_engine_place.h);
|
||||
game_engine_index 1/2/5 compares and the 26 builder stores -> existing game_engine_type constants.
|
||||
- c5 = c4 + fl (17 edits) with the header in the shadow: 180/180 EXACT, 0 changed vs base.
|
||||
- fl2: starting-equipment flags bits 0/1 -> HCEX `_netgame_starting_equipment_flag_no_grenades_bit` /
|
||||
`_netgame_starting_equipment_flag_plasma_greandes_bit` (HCEX spelling, marked sic) added to the NEW focused header
|
||||
scenario_netgame_definitions.h (R02; game_engine.c is its only includer); postspawn TEST_FLAG(globals.flags, 3/2) ->
|
||||
9_or_more/5_or_more names. c6 = c5 + fl2: 180/180 EXACT, 0 changed vs base.
|
||||
|
||||
## F9 did_player_win_default gotos -> single exit (EXACT, /Od-attested); team_has_players else
|
||||
- /Od 0x59bb90: `result` [ebp-8] = 0 at entry; tied/winner/loser are DIRECT stores in if / else-if / else arms
|
||||
(`mov [ebp-8],-1 | 1 | 0`, no int temp) => `if (w == NONE) result = NONE; else if (player->team_index == w)
|
||||
result = TRUE; else result = FALSE;` and in the place arm `if (tied && !pos) result = NONE; else if (!pos) result =
|
||||
TRUE; else result = FALSE;`, one return. The reviewer's single-exit dpw_v2 used `result = a == b` expressions
|
||||
(int setcc temps) -> residual, hence its kept `goto tied`.
|
||||
- dpw_s1 (/Od form, `long result = 0;`) EXACT; dpw_s2 (no `= 0`) EXACT (strip-inert init); dpw_s3/s4 (`result = a == b`)
|
||||
RESIDUAL. Adopted s1: both `goto tied` + label gone.
|
||||
- team_has_players: /Od 0x5b6f70 has `mov [ebp-1],1; jmp END; jmp END` = a jump statement in the then-block FOLLOWED by
|
||||
the if/else skip jump => `if (...) { result = TRUE; goto done; } else { ... }`. th_a1 (bare block -> else) EXACT.
|
||||
goto kept (reviewer: if/else without the goto is residual).
|
||||
- c7 = c6 + dpw_s1 + th_a1: 180/180 EXACT, 0 changed vs base.
|
||||
|
||||
## F10 internal_rasterize_score local macro + HCEX message parameter names (EXACT)
|
||||
- The function-local `#define GET_GAME_ENGINE_HUD_FORMAT(index) ((string_list_index = tag_loaded(..)) != NONE ?
|
||||
get_string(..) : L"")` (27 uses) is an invented macro. /Od 2020 (0x5b29xx..) spells each case as statements:
|
||||
`string_list_index = tag_loaded('ustr', ..); if (!= NONE) format = unicode_string_list_get_string(.., 0x4a); else
|
||||
format = L"";` into a named local ([ebp-0x14] string_list_index, [ebp-0xc] format), then usnprintf/ustrncpy.
|
||||
irs_a1 (macro deleted; `wchar_t const *format;` local; 17 usnprintf + 10 ustrncpy sites rewritten) EXACT.
|
||||
- HCEX multiplayer_message_internal(player_index, message, message_data, buffer, buffer_size) (same January ABI as
|
||||
internal_rasterize_score); multiplayer_message(..., message, message_data) (HCEX adds later params; January has 3).
|
||||
msg: parameter1/parameter2/message/message_character_count -> message/message_data/buffer/buffer_size in
|
||||
internal_rasterize_score (+ prototype), multiplayer_message_internal, multiplayer_message (local buffer renamed
|
||||
buffer), game_show_score_one_player. c9 = c8 + msg: 180/180, 0 changed. (First attempt without renaming
|
||||
multiplayer_message's local `message` array collided -> 7 residual; fixed.)
|
||||
- upd: HCEX `struct game_engine` = January's with `player_removed` inserted at 0x18 (January members from 0x18 on sit
|
||||
at HCEX-4: post_rasterize_objects=post_rasterize, player_update_each_tick=player_update, objective_weapon_update=
|
||||
weapon_update, picking_up=weapon_pickup, weapon_dropped=weapon_drop, get_player_score=get_score) => placeholder
|
||||
members `unknown2C` -> `pregame_post_rasterize` (HCEX 0x30), `unknown44` -> `update` (HCEX 0x48; called from
|
||||
game_engine_update). Header member renames (count-neutral; only game_engine.c names them) + format_message
|
||||
callback params -> HCEX message/message_data/buffer/buffer_size. c10: 180/180, 0 changed.
|
||||
- st_a1: statistic params typed HCEX `enum postgame_statistic` (populate, get_rating, select_players_to_display + prototypes). c11: 180/180, 0 changed.
|
||||
|
||||
## F11 shared-header count fragility (declaration-count oracle) -> count-neutral header
|
||||
- First full sweep of the packet (game_engine.h with +3 enum constants: 9_or_more, game_over_sound, generic_starting
|
||||
bits): units `_unit_preprocess_node_orientations` and network_client_message_handler
|
||||
`_network_game_client_handle_message` CHANGED (the known units canary). V2 (globals-flag enum moved into the TU, +1
|
||||
variant bit in header = net -2 names) still breaks units. V1 (header renames ONLY, count-neutral vs the reviewer's R03)
|
||||
= clean. Adopted V1: game_engine.h keeps its 3+5 flag constants (renamed, same count); the three extra bits live in a
|
||||
TU enum in game_engine.c with explicit values 3/4 and 5 (only game_engine.c uses them). No count compensation.
|
||||
- Control sweep (pristine HEAD archive): 446/446 SAME vs build/base. Rebased R01..R04 alone: 445 SAME + game_engine raw
|
||||
reloc spelling.
|
||||
|
||||
## F12 more rule-13 hand-inlines found by /Od call sets (all EXACT)
|
||||
- list_index_to_weapon_definition_index: /Od 0x5b4150 calls game_globals_get_weapon (0x5b1170, 2 args) after
|
||||
scenario_get_game_globals(); ours hand-expanded its TAG_BLOCK_GET_ELEMENT + ->index. li_a1 (call) EXACT; li_a2 (+ /Od
|
||||
0x5b1170's named result local in game_globals_get_weapon) EXACT -> adopted.
|
||||
- weapon_definition_index_to_list_index: /Od 0x5b7640 = `weapons = count ? element(0) : NULL` ternary, INDEXED
|
||||
`weapons[i].index` into an in-loop local, no pointer walk (ours: `weapon++` walk). wd_a1 (/Od form) EXACT; wd_a2
|
||||
(without the in-loop local) EXACT; adopted wd_a1.
|
||||
- linear_to_non_linear_alpha (/Od 0x5b4100 = pow(x, 1.9f)) is CALLED by /Od post_rasterize_in_game (0x5a4360) and
|
||||
internal_rasterize_target_name (0x5b3d10); ours hand-expanded `(real)pow((double)x, 1.9f)` at both sites. ltn_a1b
|
||||
(`real alpha = linear_to_non_linear_alpha(fade);`) and ltn_a2 (`alpha = linear_to_non_linear_alpha(hold_time * 0.1f)
|
||||
* 0.5f;`) EXACT. (ltn_a1 without the alpha local also EXACT.)
|
||||
- c13 = final + li_a2 + wd_a1 + ltn_a1b + ltn_a2: 180/180, 0 changed.
|
||||
|
||||
## F13 game_engine_update: invented iterator union + hand-inlined per-player helpers (EXACT after fix)
|
||||
- /Od functions are laid out ALPHABETICALLY per TU (anchors: find_closest 0x59aae0 ... weapon_definition_index_to_list_
|
||||
index 0x5b7640) -> odmap.py maps equal-count alphabetical gaps 1:1 (61 of 233) and diffs intra-TU call edges.
|
||||
- /Od game_engine_update (0x5aea50; RTC player_iterator 16B) loop body = CALLS update_player_no_shield, update_player_
|
||||
always_invis (0x5af860), update_teleporter, then the player_update_each_tick callback. Ours: `union
|
||||
game_engine_update_iterator {data_iterator data; object_iterator object;}` (invented aggregate to share the frame
|
||||
slot), a hand-inlined + restructured copy of update_player_always_invis (extra `always_invisible` local, if/else-if),
|
||||
a `{ long player_index = ...; }` block, a `void (*player_update)(long)` staging temp, and an early `return`.
|
||||
January frame 0x14 = one 16-byte iterator + the inlined no_shield byte local.
|
||||
- /Od update_player_always_invis calls game_engine_test_trait (0x5ae9c0) - ours hand-expanded `game_engine->test_trait
|
||||
&& game_engine->test_trait(player_index, 1)`.
|
||||
- gu_a1 (natural update: `if (game_engine) {...}` single exit, three DISJOINT block-scoped iterators (player loop /
|
||||
postgame player loop / object_iterator) so VC7 shares the slot, helper calls) alone RESIDUAL; ai_a1 (always_invis
|
||||
-> game_engine_test_trait(player_index, 1)) EXACT alone; gu_a2 = both: EXACT. The union type is removed.
|
||||
- c14 = c13 + gu_a2 - union: 180/180, 0 changed.
|
||||
|
||||
## F14 more helper hand-inlines via /Od call edges (all EXACT)
|
||||
- game_engine_has_teams (/Od 0x5a06a0): /Od generate_title_string (0x59c350) calls it twice (`boolean has_teams =
|
||||
game_engine_has_teams();` right after did_player_win, and `else if (game_engine_has_teams())`), /Od rasterize_in_game_
|
||||
score (0x5abbb0) initialises `has_teams = game_engine_has_teams()`. Ours hand-expanded `has_teams = FALSE; if
|
||||
(game_engine) has_teams = global_variant...teams;` (x2) and `game_engine && ...teams`. tt_a1/a2/a3 EXACT -> tt_a2.
|
||||
(get_distance_rating_for_spawn's `game_engine ? teams : FALSE` is /Od-consistent: /Od 0x59cff0 writes the ternary with
|
||||
running(), no has_teams call -> kept.)
|
||||
- get_place_string (/Od 0x5b2000; `PIN(place & 0x7F, 0, 15)` nested ternary, +0x24) is CALLED by /Od post_rasterize_post_
|
||||
game (0x5a4870) and rasterize_in_game_score; ours hand-expanded it at both sites (PIN + tag_loaded + ?:/if-else).
|
||||
gps2_a1/a2/a3 EXACT; adopted a3 + the two now-dead locals (`place_index`, `place`, `string_list_index`) removed (c17).
|
||||
- Corrected /Od identification: 0x5b20e0 = get_postgame_hilite_colors (calls 0x5b21a0 = get_selected_color) - the
|
||||
alphabetical 1:1 mapping in that gap was off by one (2020 extra function).
|
||||
- c17: 180/180, 0 changed.
|
||||
- internal_rasterize_score: /Od 0x5b2940 begins `result = TRUE; if (game_engine_test_flag(1))` (calls 0x5ae940); ours
|
||||
hand-expanded `game_engine && game_engine->test_flag && game_engine->test_flag(1)`. ts_a1 EXACT (c18).
|
||||
- Edge census (odmap.py with 92 identified /Od functions): every remaining /Od helper edge into a January-shaped
|
||||
function is now a real call in ours, except (a) `game_engine_running()` vs `if (game_engine)` (the 2020 build mixes
|
||||
both spellings per site; not changed except where adopted above) and (b) 2020-only logic (goal_matches_player /
|
||||
render_nav_points / netgame_verify_equipment get_type calls: different 2020 code, January bytes differ).
|
||||
|
||||
## F15 FINAL verification (final/ = c18; patches F01..F04 regenerated)
|
||||
- `git apply --check` F01, F02, F03a, F03b, F04 individually and together vs the tree (16542e46): clean; tree status clean.
|
||||
F01 needs F02+F03a+F03b to compile (new headers, renamed constants/members, prototypes) - land together.
|
||||
- Independent shadow_F = `git archive HEAD source` + F01..F04 (git apply, GIT_CEILING_DIRECTORIES) == final/ byte-for-byte
|
||||
(CRLF-normalised).
|
||||
- rcompile (production cflags, cwd shadow_F): 180/180 EXACT vs build/split; 0 of 302 section-defining symbols changed vs
|
||||
build/base; symbol-table multiset identical to production (853/853, $L collapsed).
|
||||
- object_audit PASS (text identical to production's audit); provider_link SELECTED-PROVIDER LINK PASS; surplus 11 COMDATs
|
||||
identical (unchanged set); pdb_storage 0 disagreements (no storage changes); objdiff-cli 3.3.1 mini-report: production
|
||||
and final both 27922/32397 code, 173/180 fns (7 pre-existing undercredited), 3792/3792 data, 0 per-function deltas.
|
||||
- Full sweep (rsweep, 446 TUs, vs build/base): 445 SAME; game_engine differs only in (a) section ORDER -
|
||||
_game_engine_update_player_always_invis is now emitted later (C2 defers it: it now calls game_engine_test_trait, which
|
||||
our file defines later; production's order already differs from January's split order in many places) and (b) the
|
||||
known raw reloc spelling `_global_goal+0x400` for `_global_variant+0` in motion-sensor/render_nav_points (resolved
|
||||
target identical; coff_compare EXACT). Control sweep of pristine HEAD: 446 SAME.
|
||||
- Optional F05h+F05c+F06+F07 on top: 180/180; sweep 445 SAME + game_engine (same order/reloc notes).
|
||||
- /W3: game_engine.c only: C4013 console_printf gone; +1 C4244 'function' long->boolean (get_rating's 32-bit `inverse`
|
||||
forwarded to populate's byte `inverse` = January's ABI, proven by the dword vs byte reads). No other TU changes.
|
||||
- Consumer census: CONSUMERS.txt (game_engine.h 37 TUs incl. `saved games/playlist_profile`; hud_messaging.h 8 incl.
|
||||
`saved games/game_state`; sound_classes.h 6; player_control.h 21; new headers only game_engine (+hud_nav_points)).
|
||||
|
||||
## F16 VERDICT / owner items / reopen criteria
|
||||
- Open list (review3 s.4): (1) man_out CLOSED (mo_a1, /Od form); (3) rule-16 switches CLOSED (r16 + fl/fl2); (4)
|
||||
statistic walks CLOSED (psb_a1, gpp_a1, sp_a1, gr_a3); (2) motion-sensor copy: both forms EXACT - default keeps the
|
||||
reviewer's in-loop `goal` alias (not in the /Od frame); F07 (optional) = the /Od-attested one-statement 8-byte view
|
||||
copy `positions[count] = *(real_point2d *)&global_goal[goal_index].position;` (load-bearing: component copies pick the
|
||||
+4 IV) -> OWNER picks.
|
||||
- Additional blockers found and fixed (not in the review): invented `union game_engine_update_iterator` + hand-inlined
|
||||
update_player_always_invis/test_trait/test_flag/has_teams/get_place_string/linear_to_non_linear_alpha/
|
||||
list_index_to_weapon_definition_index(x14)/game_globals_get_weapon/infinite_grenades_internal, GET_GAME_ENGINE_HUD_FORMAT
|
||||
local macro, hand bit-twiddled builder flags, did_player_win_default gotos, weapon list pointer walk, semantically
|
||||
wrong netgame_goal field names and flag-bit names, placeholder `unknown2C/unknown44/parameter1/parameter2` names.
|
||||
- Section-8(g) scan of final: no caller-local views with opaque spans (TU structs are HCEX netgame_goal/statistic_buffer
|
||||
+ TU-private globals), no consumer-local prototypes (all 47 TU prototypes are TU functions), no hand-expanded header
|
||||
helpers found (teleporter/find_closest fixed by R01; /Od call-edge census for 92 mapped functions clean), no `float`.
|
||||
- Disclosed (owner/policy): descriptive `_postgame_statistic_*` constants (HCEX has only the tag); weapon set 10 named
|
||||
`no_grenades` (January behaviour) not HCEX `covenant`; TU-local continuation bits (3/4/5) because game_engine.h's name
|
||||
count is fragile (units/network canaries); /Od-attested dead `local_player_count` (select_players_to_display) and
|
||||
strip-inert `= 0` inits (get_rating player_count, did_player_win_default result); authentic C4244 long->boolean.
|
||||
- NOT done (zero-credit follow-ups): game_engine_globals/global_stage/timeout_for_endgame_sound stay `extern` although
|
||||
the COMMON pool places them in game_engine.c's cluster; engine test_flag/test_trait/multiplayer-sound/string-index
|
||||
literals (would need new game_engine.h names = count-fragile); `if (game_engine)` vs /Od `game_engine_running()` mix.
|
||||
- Reopen: a reviewer finds another /Od call edge in the 141 unmapped /Od functions (odmap.py + odmap_extra.json), or the
|
||||
owner rules on F07; any game_engine.h edit must keep the declared-name count (sweep units + network_client_message_
|
||||
handler first).
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
+4590
File diff suppressed because it is too large.
Load diff
+281
@@ -0,0 +1,281 @@
|
||||
diff --git a/source/interface/hud_globals_definitions.h b/source/interface/hud_globals_definitions.h
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/source/interface/hud_globals_definitions.h
|
||||
@@ -0,0 +1,125 @@
|
||||
+/*
|
||||
+HUD_GLOBALS_DEFINITIONS.H
|
||||
+
|
||||
+HUD globals ('hudg') tag layout, as recorded by the HCEX PDB, and the global
|
||||
+owned by HUD.C. The shared placement and color elements come from
|
||||
+UNIT_HUD_INTERFACE_DEFINITION.H. Focused owner header: HUD_DEFINITIONS.H
|
||||
+cannot carry this layout while several HUD translation units still define
|
||||
+their own local struct hud_globals_definition.
|
||||
+*/
|
||||
+
|
||||
+#ifndef __HUD_GLOBALS_DEFINITIONS_H
|
||||
+#define __HUD_GLOBALS_DEFINITIONS_H
|
||||
+#pragma once
|
||||
+
|
||||
+/* ---------- headers */
|
||||
+
|
||||
+#include "interface/unit_hud_interface_definition.h"
|
||||
+
|
||||
+/* ---------- constants */
|
||||
+
|
||||
+enum
|
||||
+{
|
||||
+ HUD_GLOBALS_DEFINITION_TAG = 'hudg',
|
||||
+};
|
||||
+
|
||||
+/* ---------- macros */
|
||||
+
|
||||
+#define hud_globals_definition_get(index) \
|
||||
+ ((struct hud_globals_definition *)tag_get( \
|
||||
+ HUD_GLOBALS_DEFINITION_TAG, \
|
||||
+ (index)))
|
||||
+
|
||||
+/* ---------- structures */
|
||||
+
|
||||
+struct hud_messaging_parameters_definition
|
||||
+{
|
||||
+ struct hud_absolute_placement_definition absolute_placement;
|
||||
+ struct hud_placement_definition placement;
|
||||
+ struct tag_reference single_player_font;
|
||||
+ struct tag_reference multi_player_font;
|
||||
+ real up_time;
|
||||
+ real fade_time;
|
||||
+ real_argb_color state_color;
|
||||
+ real_argb_color text_color;
|
||||
+ real spacing;
|
||||
+ struct tag_reference hud_item_messages;
|
||||
+ struct tag_reference messaging_icons;
|
||||
+ struct tag_reference alternate_icon_text;
|
||||
+ struct tag_block button_icons;
|
||||
+ struct hud_color_definition color;
|
||||
+ struct tag_reference hud_messages;
|
||||
+ struct hud_color_definition objective_color;
|
||||
+};
|
||||
+
|
||||
+struct hud_waypoint_definition
|
||||
+{
|
||||
+ real top_offset;
|
||||
+ real bottom_offset;
|
||||
+ real left_offset;
|
||||
+ real right_offset;
|
||||
+ long unused0[8];
|
||||
+ struct tag_reference arrow_bitmap;
|
||||
+ struct tag_block arrows;
|
||||
+ long unused1[20];
|
||||
+};
|
||||
+
|
||||
+struct hud_multiplayer_parameters_definition
|
||||
+{
|
||||
+ real hud_scale;
|
||||
+ long unused[64];
|
||||
+};
|
||||
+
|
||||
+struct hud_defaults_definition
|
||||
+{
|
||||
+ struct tag_reference default_weapon_hud;
|
||||
+ real motion_sensor_range;
|
||||
+ real motion_sensor_velocity_sensitivity;
|
||||
+ real motion_sensor_scale;
|
||||
+ rectangle2d default_title_bounds;
|
||||
+ long unused[11];
|
||||
+};
|
||||
+
|
||||
+struct hud_damage_indicators_definition
|
||||
+{
|
||||
+ short top_offset;
|
||||
+ short bottom_offset;
|
||||
+ short left_offset;
|
||||
+ short right_offset;
|
||||
+ long unused[8];
|
||||
+ struct tag_reference indicator_bitmap;
|
||||
+ short sequence_index;
|
||||
+ short multiplayer_sequence_index;
|
||||
+ unsigned long color;
|
||||
+ long unused2[4];
|
||||
+};
|
||||
+
|
||||
+struct hud_timer_definition
|
||||
+{
|
||||
+ struct hud_color_definition color;
|
||||
+ struct hud_color_definition time_up_color;
|
||||
+ long unused[10];
|
||||
+};
|
||||
+
|
||||
+struct hud_globals_definition
|
||||
+{
|
||||
+ struct hud_messaging_parameters_definition messaging;
|
||||
+ struct hud_waypoint_definition waypoint;
|
||||
+ struct hud_multiplayer_parameters_definition multiplayer;
|
||||
+ struct hud_defaults_definition defaults;
|
||||
+ struct hud_damage_indicators_definition damage_indicators;
|
||||
+ struct hud_timer_definition timer_definition;
|
||||
+ struct tag_reference carnage_report_bitmap;
|
||||
+ short loading_begin_index;
|
||||
+ short loading_end_index;
|
||||
+ short checkpoint_begin_index;
|
||||
+ short checkpoint_end_index;
|
||||
+ struct tag_reference checkpoint_sound;
|
||||
+ long unused2[24];
|
||||
+};
|
||||
+
|
||||
+/* ---------- globals */
|
||||
+
|
||||
+extern struct hud_globals_definition *hud_globals;
|
||||
+
|
||||
+#endif // __HUD_GLOBALS_DEFINITIONS_H
|
||||
diff --git a/source/interface/hud_nav_points.h b/source/interface/hud_nav_points.h
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/source/interface/hud_nav_points.h
|
||||
@@ -0,0 +1,33 @@
|
||||
+/*
|
||||
+HUD_NAV_POINTS.H
|
||||
+
|
||||
+Narrow cross-translation-unit interface owned by HUD_NAV_POINTS.C for the
|
||||
+multiplayer game engine goal markers. The rest of the nav-point API is
|
||||
+declared in HUD.H; focused owner header because adding these three
|
||||
+prototypes to the broad HUD.H moves distant declaration-count ties.
|
||||
+*/
|
||||
+
|
||||
+#ifndef __HUD_NAV_POINTS_H
|
||||
+#define __HUD_NAV_POINTS_H
|
||||
+#pragma once
|
||||
+
|
||||
+/* ---------- structures */
|
||||
+
|
||||
+union real_point3d;
|
||||
+
|
||||
+/* ---------- prototypes/HUD_NAV_POINTS.C */
|
||||
+
|
||||
+short find_nav_point(
|
||||
+ char const *name);
|
||||
+short hud_get_nav_point_render_type(
|
||||
+ short local_player_index,
|
||||
+ union real_point3d const *head,
|
||||
+ union real_point3d const *position,
|
||||
+ long reference_object_index);
|
||||
+void custom_render_nav_point(
|
||||
+ short local_player_index,
|
||||
+ union real_point3d const *position,
|
||||
+ short nav_index,
|
||||
+ short waypoint_type);
|
||||
+
|
||||
+#endif // __HUD_NAV_POINTS_H
|
||||
diff --git a/source/items/item_collection_definitions.h b/source/items/item_collection_definitions.h
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/source/items/item_collection_definitions.h
|
||||
@@ -0,0 +1,40 @@
|
||||
+/*
|
||||
+ITEM_COLLECTION_DEFINITIONS.H
|
||||
+
|
||||
+Item collection ('itmc') tag layout, as recorded by the HCEX PDB. The tag
|
||||
+group constant lives with the item definitions in ITEM_DEFINITIONS.H.
|
||||
+Focused owner header: adding these types to the broad ITEM_DEFINITIONS.H
|
||||
+moves distant declaration-count ties.
|
||||
+*/
|
||||
+
|
||||
+#ifndef __ITEM_COLLECTION_DEFINITIONS_H
|
||||
+#define __ITEM_COLLECTION_DEFINITIONS_H
|
||||
+#pragma once
|
||||
+
|
||||
+/* ---------- headers */
|
||||
+
|
||||
+#include "items/item_definitions.h"
|
||||
+
|
||||
+/* ---------- macros */
|
||||
+
|
||||
+#define item_collection_definition_get(index) ((struct item_collection_definition *)tag_get(ITEM_COLLECTION_DEFINITION_TAG, index))
|
||||
+
|
||||
+/* ---------- structures */
|
||||
+
|
||||
+struct item_permutation_definition
|
||||
+{
|
||||
+ long unused1[8];
|
||||
+ real weight;
|
||||
+ struct tag_reference item;
|
||||
+ long unused2[8];
|
||||
+};
|
||||
+
|
||||
+struct item_collection_definition
|
||||
+{
|
||||
+ struct tag_block permutations;
|
||||
+ short spawn_time;
|
||||
+ short pad;
|
||||
+ long unused[19];
|
||||
+};
|
||||
+
|
||||
+#endif // __ITEM_COLLECTION_DEFINITIONS_H
|
||||
diff --git a/source/scenario/scenario_netgame_definitions.h b/source/scenario/scenario_netgame_definitions.h
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/source/scenario/scenario_netgame_definitions.h
|
||||
@@ -0,0 +1,63 @@
|
||||
+/*
|
||||
+SCENARIO_NETGAME_DEFINITIONS.H
|
||||
+
|
||||
+Narrow cross-translation-unit interface to the scenario tag's multiplayer
|
||||
+blocks (netgame flags, netgame equipment and starting equipment), used by the
|
||||
+multiplayer game engines. Member names and layouts follow the HCEX PDB
|
||||
+records; SCENARIO_DEFINITIONS.H keeps the enclosing struct scenario.
|
||||
+Focused owner header: adding these types to the broad
|
||||
+SCENARIO_DEFINITIONS.H moves distant declaration-count ties.
|
||||
+*/
|
||||
+
|
||||
+#ifndef __SCENARIO_NETGAME_DEFINITIONS_H
|
||||
+#define __SCENARIO_NETGAME_DEFINITIONS_H
|
||||
+#pragma once
|
||||
+
|
||||
+/* ---------- headers */
|
||||
+
|
||||
+#include "math/real_math.h"
|
||||
+#include "tag_files/tag_groups.h"
|
||||
+
|
||||
+/* ---------- constants */
|
||||
+
|
||||
+enum
|
||||
+{
|
||||
+ _netgame_starting_equipment_flag_no_grenades_bit = 0,
|
||||
+ _netgame_starting_equipment_flag_plasma_greandes_bit, /* (sic) HCEX spelling */
|
||||
+};
|
||||
+
|
||||
+/* ---------- structures */
|
||||
+
|
||||
+struct scenario_netgame_flag
|
||||
+{
|
||||
+ real_point3d position;
|
||||
+ real facing;
|
||||
+ short type;
|
||||
+ short team_index;
|
||||
+ long unused[32];
|
||||
+};
|
||||
+
|
||||
+struct scenario_netgame_equipment
|
||||
+{
|
||||
+ long flags;
|
||||
+ short game_type[4];
|
||||
+ short team_index;
|
||||
+ short spawn_time;
|
||||
+ long run_time_spawned_item_index;
|
||||
+ long unused1[11];
|
||||
+ real_point3d position;
|
||||
+ real facing;
|
||||
+ struct tag_reference item_collection;
|
||||
+ long unused2[12];
|
||||
+};
|
||||
+
|
||||
+struct scenario_starting_equipment
|
||||
+{
|
||||
+ long flags;
|
||||
+ short game_type[4];
|
||||
+ long unused1[12];
|
||||
+ struct tag_reference item_collection[6];
|
||||
+ long unused2[12];
|
||||
+};
|
||||
+
|
||||
+#endif // __SCENARIO_NETGAME_DEFINITIONS_H
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
diff --git a/source/game/game_engine.h b/source/game/game_engine.h
|
||||
--- a/source/game/game_engine.h
|
||||
+++ b/source/game/game_engine.h
|
||||
@@ -14,16 +14,16 @@ header included in hcex build.
|
||||
|
||||
enum
|
||||
{
|
||||
- _game_engine_allow_dynamic_lighting_bit = 0,
|
||||
- _game_engine_allow_integrated_lights_bit,
|
||||
- _game_engine_disable_infinite_grenades_bit,
|
||||
+ _game_engine_disable_dynamic_lighting_bit = 0,
|
||||
+ _game_engine_disable_integrated_lights_bit,
|
||||
+ _game_engine_5_or_more_players_bit,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
_game_variant_draw_object_in_motion_sensor_bit = 0,
|
||||
- _game_variant_unknown1_bit = 1,
|
||||
- _game_variant_infinite_grenades_bit = 2,
|
||||
+ _game_variant_allow_friendly_navpoints_bit,
|
||||
+ _game_variant_infinite_grenades_bit,
|
||||
_game_variant_no_shields_bit,
|
||||
_game_variant_always_invisible_bit,
|
||||
};
|
||||
@@ -154,7 +154,7 @@ struct game_engine
|
||||
void (*statistics_append)(long statistic);
|
||||
void (*handle_client_message)(void *message);
|
||||
void (*handle_server_message)(void *message);
|
||||
- void (*unknown2C)(void);
|
||||
+ void (*pregame_post_rasterize)(void);
|
||||
void (*post_rasterize_objects)(void);
|
||||
void (*player_update_each_tick)(
|
||||
long player_index);
|
||||
@@ -166,7 +166,7 @@ struct game_engine
|
||||
long player_index);
|
||||
void (*weapon_dropped)(
|
||||
long weapon_index);
|
||||
- void (*unknown44)(void);
|
||||
+ void (*update)(void);
|
||||
long (*get_player_score)(
|
||||
long player_index,
|
||||
enum get_score_type score_type);
|
||||
@@ -192,11 +192,11 @@ struct game_engine
|
||||
boolean friendly_fire);
|
||||
boolean (*format_message)(
|
||||
long player_index,
|
||||
- long parameter1,
|
||||
- long parameter2,
|
||||
- wchar_t *message,
|
||||
- long message_character_count);
|
||||
- float (*starting_location_rating)(
|
||||
+ long message,
|
||||
+ long message_data,
|
||||
+ wchar_t *buffer,
|
||||
+ long buffer_size);
|
||||
+ real (*starting_location_rating)(
|
||||
long player_index,
|
||||
struct player_starting_location const *starting_location);
|
||||
void (*prespawn_player_update)(
|
||||
@@ -268,7 +268,7 @@ long game_engine_get_team_score(
|
||||
long players_in_game(
|
||||
void);
|
||||
|
||||
-float get_blink_alpha(
|
||||
+real get_blink_alpha(
|
||||
void);
|
||||
|
||||
long game_engine_player_get_team_index(
|
||||
@@ -331,7 +331,7 @@ void game_engine_nonplayer_post_rasterize(
|
||||
void);
|
||||
|
||||
void game_engine_update_non_deterministic(
|
||||
- float delta_seconds);
|
||||
+ real delta_seconds);
|
||||
|
||||
boolean match_game_type(
|
||||
long game_type,
|
||||
@@ -344,7 +344,7 @@ void game_engine_initialize(
|
||||
void game_engine_initialize_for_new_map(
|
||||
void);
|
||||
|
||||
-float game_engine_get_distance_rating_for_spawn(
|
||||
+real game_engine_get_distance_rating_for_spawn(
|
||||
long player_index,
|
||||
union real_point3d const *position);
|
||||
|
||||
@@ -399,11 +399,11 @@ boolean game_engine_get_goal_in_use(
|
||||
void game_engine_set_goal_position(
|
||||
short goal_index,
|
||||
union real_point3d const *position,
|
||||
- float height,
|
||||
+ real height,
|
||||
char const *name,
|
||||
- long target_object_index,
|
||||
+ long player_index,
|
||||
short team_index,
|
||||
- long player_index);
|
||||
+ long ignore_player_index);
|
||||
|
||||
boolean game_engine_has_teams(
|
||||
void);
|
||||
@@ -439,7 +439,7 @@ short game_engine_player_get_custom_motion_sensor_positions(
|
||||
short maximum_count);
|
||||
|
||||
void game_engine_render_nav_points(
|
||||
- long local_player_index);
|
||||
+ short local_player_index);
|
||||
|
||||
union real_rgb_color *game_engine_player_get_change_color(
|
||||
union real_rgb_color *change_color,
|
||||
@@ -513,6 +513,10 @@ boolean game_engine_force_autopickup(
|
||||
|
||||
void game_engine_play_multiplayer_sound(
|
||||
long sound_index);
|
||||
+void game_engine_update_multiplayer_sound(
|
||||
+ void);
|
||||
+void game_engine_intialize_queued_sounds(
|
||||
+ void);
|
||||
|
||||
long game_engine_remap_object_definition(long definition_index);
|
||||
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
diff --git a/source/game/player_control.h b/source/game/player_control.h
|
||||
--- a/source/game/player_control.h
|
||||
+++ b/source/game/player_control.h
|
||||
@@ -152,6 +152,8 @@ void player_control_get_unit_camera_info(
|
||||
struct player_control_unit_camera_info *camera_info);
|
||||
long player_control_get_unit_index(
|
||||
short local_player_index);
|
||||
+short unit_get_local_player_index(
|
||||
+ long unit_index);
|
||||
long player_control_get_desired_weapon(
|
||||
short local_player_index,
|
||||
long unit_index);
|
||||
diff --git a/source/interface/hud_messaging.h b/source/interface/hud_messaging.h
|
||||
--- a/source/interface/hud_messaging.h
|
||||
+++ b/source/interface/hud_messaging.h
|
||||
@@ -15,6 +15,7 @@ header included in hcex build.
|
||||
/* ---------- structures */
|
||||
|
||||
struct icon_hud_element_definition;
|
||||
+union real_argb_color;
|
||||
|
||||
/* ---------- prototypes/HUD_MESSAGING.C */
|
||||
|
||||
@@ -78,6 +79,10 @@ void hud_set_state_text(
|
||||
wchar_t const *message);
|
||||
wchar_t *hud_messaging_get_objective(
|
||||
void);
|
||||
+long hud_get_font_index(
|
||||
+ void);
|
||||
+union real_argb_color *hud_get_text_color(
|
||||
+ union real_argb_color *result);
|
||||
|
||||
/* ---------- globals */
|
||||
|
||||
diff --git a/source/sound/sound_classes.h b/source/sound/sound_classes.h
|
||||
--- a/source/sound/sound_classes.h
|
||||
+++ b/source/sound/sound_classes.h
|
||||
@@ -64,6 +64,10 @@ struct sound_class_definition *sound_class_get(
|
||||
|
||||
real sound_class_get_gain(
|
||||
short class_index);
|
||||
+void sound_class_set_gain(
|
||||
+ char const *name,
|
||||
+ real gain,
|
||||
+ short interpolation_ticks);
|
||||
|
||||
void sound_classes_dispose_from_old_map(
|
||||
void);
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
diff --git a/source/interface/hud_nav_points.c b/source/interface/hud_nav_points.c
|
||||
--- a/source/interface/hud_nav_points.c
|
||||
+++ b/source/interface/hud_nav_points.c
|
||||
@@ -113,6 +113,7 @@ symbols in this file:
|
||||
#include "tag_files/tag_groups.h"
|
||||
#include "interface/hud.h"
|
||||
#include "interface/hud_definitions.h"
|
||||
+#include "interface/hud_nav_points.h"
|
||||
#include "bitmaps/bitmap_color_conversion.h"
|
||||
#include "interface/hud_draw.h"
|
||||
#include "objects/object_types.h"
|
||||
@@ -303,12 +304,6 @@ real_point3d *game_engine_get_goal_position(
|
||||
real_point3d *position,
|
||||
short goal_index);
|
||||
|
||||
-void custom_render_nav_point(
|
||||
- short local_player_index,
|
||||
- real_point3d const *position,
|
||||
- short nav_index,
|
||||
- short render_type);
|
||||
-
|
||||
void game_engine_render_nav_points(
|
||||
short local_player_index);
|
||||
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
diff --git a/source/game/game_engine.c b/source/game/game_engine.c
|
||||
--- a/source/game/game_engine.c
|
||||
+++ b/source/game/game_engine.c
|
||||
@@ -976,7 +976,7 @@ static void initialize_player_multiplayer_data(
|
||||
player->state_message = NONE;
|
||||
player->state_message_player_index = NONE;
|
||||
player->speed_multiplier = 1.0f;
|
||||
- player->unknown70 = NONE;
|
||||
+ player->teleporter_index = NONE;
|
||||
player->unknown7c = NONE;
|
||||
csmemset(
|
||||
&player->statistics.multiplayer_statistics,
|
||||
@@ -3423,15 +3423,15 @@ static void game_engine_update_teleporter(
|
||||
return;
|
||||
|
||||
unit = unit_get(player->unit_index);
|
||||
- if (player->unknown70 != NONE)
|
||||
+ if (player->teleporter_index != NONE)
|
||||
{
|
||||
struct scenario_netgame_flag *previous_flag = TAG_BLOCK_GET_ELEMENT(
|
||||
&scenario->netgame_flags,
|
||||
- player->unknown70,
|
||||
+ player->teleporter_index,
|
||||
struct scenario_netgame_flag);
|
||||
|
||||
if (distance_squared3d(&previous_flag->position, &unit->object.position) > 1.0f)
|
||||
- player->unknown70 = NONE;
|
||||
+ player->teleporter_index = NONE;
|
||||
}
|
||||
|
||||
source_flag_index = NONE;
|
||||
@@ -3444,7 +3444,7 @@ static void game_engine_update_teleporter(
|
||||
1,
|
||||
&source_flag_index);
|
||||
if (source_flag_index == NONE ||
|
||||
- source_flag_index == player->unknown70)
|
||||
+ source_flag_index == player->teleporter_index)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -3591,7 +3591,7 @@ static void game_engine_update_teleporter(
|
||||
if (player->local_player_index != NONE)
|
||||
player_control_set_facing(player->local_player_index, &forward);
|
||||
|
||||
- player->unknown70 = find_netgame_flag(
|
||||
+ player->teleporter_index = find_netgame_flag(
|
||||
&unit->object.position,
|
||||
1.0f,
|
||||
0.0f,
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
diff --git a/source/game/players.h b/source/game/players.h
|
||||
index 34ee5f08..769ca943 100644
|
||||
--- a/source/game/players.h
|
||||
+++ b/source/game/players.h
|
||||
@@ -100,7 +100,7 @@ struct player_datum
|
||||
struct network_player network_player_data;
|
||||
short powerup_durations[NUMBER_OF_PLAYER_POWERUPS];
|
||||
real speed_multiplier;
|
||||
- long unknown70;
|
||||
+ long teleporter_index;
|
||||
long state_message;
|
||||
long state_message_player_index;
|
||||
long unknown7c;
|
||||
+123
@@ -0,0 +1,123 @@
|
||||
diff --git a/source/game/game_engine_ctf.c b/source/game/game_engine_ctf.c
|
||||
index 28df215b..d5faf45f 100644
|
||||
--- a/source/game/game_engine_ctf.c
|
||||
+++ b/source/game/game_engine_ctf.c
|
||||
@@ -129,6 +129,7 @@ symbols in this file:
|
||||
#include "objects/objects.h"
|
||||
#include "scenario/scenario.h"
|
||||
#include "scenario/scenario_definitions.h"
|
||||
+#include "scenario/scenario_netgame_definitions.h"
|
||||
#include "tag_files/tag_groups.h"
|
||||
#include "text/text_group.h"
|
||||
#include "text/unicode.h"
|
||||
@@ -209,18 +210,6 @@ enum
|
||||
|
||||
/* ---------- structures */
|
||||
|
||||
-struct scenario_netgame_flag
|
||||
-{
|
||||
- real_point3d position;
|
||||
- real facing;
|
||||
- short type;
|
||||
- short team_index;
|
||||
- byte unused[0x80];
|
||||
-};
|
||||
-
|
||||
-typedef char verify_scenario_netgame_flag_size[
|
||||
- sizeof(struct scenario_netgame_flag) == 0x94 ? 1 : -1];
|
||||
-
|
||||
struct ctf_globals
|
||||
{
|
||||
struct scenario_netgame_flag *flags[NUMBER_OF_CTF_TEAMS];
|
||||
diff --git a/source/game/game_engine_king.c b/source/game/game_engine_king.c
|
||||
index df345537..eec5e0a0 100644
|
||||
--- a/source/game/game_engine_king.c
|
||||
+++ b/source/game/game_engine_king.c
|
||||
@@ -94,6 +94,7 @@ symbols in this file:
|
||||
#include "render/render.h"
|
||||
#include "scenario/scenario.h"
|
||||
#include "scenario/scenario_definitions.h"
|
||||
+#include "scenario/scenario_netgame_definitions.h"
|
||||
#include "shaders/shader_definitions.h"
|
||||
#include "shaders/shaders.h"
|
||||
#include "tag_files/tag_groups.h"
|
||||
@@ -206,17 +207,6 @@ typedef char verify_rasterizer_model_begin_parameters_size[
|
||||
sizeof(struct rasterizer_model_begin_parameters) == 0xCC ? 1 : -1];
|
||||
|
||||
/* January scenario flag layout consumed by the King map scan. */
|
||||
-struct scenario_netgame_flag
|
||||
-{
|
||||
- real_point3d position;
|
||||
- real facing;
|
||||
- short type;
|
||||
- short team_index;
|
||||
- byte unused[0x80];
|
||||
-};
|
||||
-
|
||||
-typedef char verify_scenario_netgame_flag_size[
|
||||
- sizeof(struct scenario_netgame_flag) == 0x94 ? 1 : -1];
|
||||
typedef char verify_scenario_netgame_flags_offset[
|
||||
offsetof(struct scenario, netgame_flags) == 0x378 ? 1 : -1];
|
||||
|
||||
diff --git a/source/game/game_engine_oddball.c b/source/game/game_engine_oddball.c
|
||||
index a567f524..57fe087a 100644
|
||||
--- a/source/game/game_engine_oddball.c
|
||||
+++ b/source/game/game_engine_oddball.c
|
||||
@@ -114,6 +114,7 @@ symbols in this file:
|
||||
#include "players.h"
|
||||
#include "scenario/scenario.h"
|
||||
#include "scenario/scenario_definitions.h"
|
||||
+#include "scenario/scenario_netgame_definitions.h"
|
||||
#include "tag_files/tag_groups.h"
|
||||
#include "text/text_group.h"
|
||||
#include "text/unicode.h"
|
||||
@@ -239,18 +240,6 @@ typedef char verify_oddball_globals_ball_spawn_timer_offset[
|
||||
typedef char verify_oddball_globals_current_ball_owner_offset[
|
||||
offsetof(struct oddball_globals, current_ball_owner) == 0xC4 ? 1 : -1];
|
||||
|
||||
-struct scenario_netgame_flag
|
||||
-{
|
||||
- real_point3d position;
|
||||
- real facing;
|
||||
- short type;
|
||||
- short team_index;
|
||||
- byte unused[0x80];
|
||||
-};
|
||||
-
|
||||
-typedef char verify_scenario_netgame_flag_size[
|
||||
- sizeof(struct scenario_netgame_flag) == 0x94 ? 1 : -1];
|
||||
-
|
||||
/* ---------- prototypes */
|
||||
|
||||
/* ---------- globals */
|
||||
diff --git a/source/game/game_engine_race.c b/source/game/game_engine_race.c
|
||||
index 0de4df0f..2e076851 100644
|
||||
--- a/source/game/game_engine_race.c
|
||||
+++ b/source/game/game_engine_race.c
|
||||
@@ -111,6 +111,7 @@ symbols in this file:
|
||||
#include "objects/objects.h"
|
||||
#include "scenario/scenario.h"
|
||||
#include "scenario/scenario_definitions.h"
|
||||
+#include "scenario/scenario_netgame_definitions.h"
|
||||
#include "tag_files/tag_groups.h"
|
||||
#include "text/text_group.h"
|
||||
#include "text/unicode.h"
|
||||
@@ -206,18 +207,6 @@ enum multiplayer_game_text
|
||||
|
||||
/* ---------- structures */
|
||||
|
||||
-struct scenario_netgame_flag
|
||||
-{
|
||||
- real_point3d position;
|
||||
- real facing;
|
||||
- short type;
|
||||
- short team_index;
|
||||
- byte unused[0x80];
|
||||
-};
|
||||
-
|
||||
-typedef char verify_scenario_netgame_flag_size[
|
||||
- sizeof(struct scenario_netgame_flag) == 0x94 ? 1 : -1];
|
||||
-
|
||||
struct race_globals
|
||||
{
|
||||
unsigned long lap_completed_value;
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
diff --git a/source/game/game_engine.c b/source/game/game_engine.c
|
||||
--- a/source/game/game_engine.c
|
||||
+++ b/source/game/game_engine.c
|
||||
@@ -4451,13 +4451,11 @@ short game_engine_player_get_custom_motion_sensor_positions(
|
||||
|
||||
for (goal_index = 0; goal_index < 32; goal_index++)
|
||||
{
|
||||
- struct netgame_goal *goal = &global_goal[goal_index];
|
||||
-
|
||||
if (goal_matches_player(goal_index, player, player_index) && count < maximum_count)
|
||||
{
|
||||
goal_indices[count] = goal_index;
|
||||
- positions[count].x = goal->position.x;
|
||||
- positions[count].y = goal->position.y;
|
||||
+ /* /Od 0x5a20e0: one 8-byte copy of the goal's x,y (the 3D point viewed as its 2D prefix) */
|
||||
+ positions[count] = *(real_point2d *)&global_goal[goal_index].position;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
diff --git a/source/interface/hud_nav_points.c "b/C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\hud_nav_points\\st1.c"
|
||||
index 700a6e03..36b392c3 100644
|
||||
--- a/source/interface/hud_nav_points.c
|
||||
+++ "b/C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\hud_nav_points\\st1.c"
|
||||
@@ -776,7 +776,7 @@ void custom_render_nav_point(
|
||||
short waypoint_type)
|
||||
{
|
||||
long return_eip = get_return_eip();
|
||||
- long stack_buffer[STACK_BUFFER_LENGTH];
|
||||
+ long stack_buffer[0x80];
|
||||
struct hud_waypoint_arrow *arrow;
|
||||
real_point3d view_point;
|
||||
real distance;
|
||||
@@ -986,7 +986,37 @@ void custom_render_nav_point(
|
||||
}
|
||||
}
|
||||
|
||||
- match_assert_stack_frame("c:\\halo\\SOURCE\\interface\\hud_nav_points.c", 675);
|
||||
+ {
|
||||
+ short corrupt_index;
|
||||
+ short buffer_index;
|
||||
+
|
||||
+ for (buffer_index = 0x7F; buffer_index>=0; buffer_index--)
|
||||
+ {
|
||||
+ if (stack_buffer[buffer_index]!=0x62626262)
|
||||
+ {
|
||||
+ goto corrupt_stack_found_custom_render_nav_point;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ corrupt_index = NONE;
|
||||
+ goto stack_buffer_checked_custom_render_nav_point;
|
||||
+
|
||||
+corrupt_stack_found_custom_render_nav_point:
|
||||
+ corrupt_index = buffer_index;
|
||||
+
|
||||
+stack_buffer_checked_custom_render_nav_point:
|
||||
+
|
||||
+ match_vassert(
|
||||
+ "c:\\halo\\SOURCE\\interface\\hud_nav_points.c",
|
||||
+ 675,
|
||||
+ return_eip==get_return_eip(),
|
||||
+ "corrupt return address!");
|
||||
+ match_vassert(
|
||||
+ "c:\\halo\\SOURCE\\interface\\hud_nav_points.c",
|
||||
+ 675,
|
||||
+ corrupt_index==NONE,
|
||||
+ csprintf(temporary, "corrupt stack at %d!", corrupt_index));
|
||||
+ }
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1070,7 +1100,7 @@ static void hud_update_nav_point_local_player(
|
||||
short local_player_index)
|
||||
{
|
||||
long return_eip = get_return_eip();
|
||||
- long stack_buffer[STACK_BUFFER_LENGTH];
|
||||
+ long stack_buffer[0x80];
|
||||
struct hud_nav_point_player_datum *datum;
|
||||
long unit_index;
|
||||
short nav_point_index;
|
||||
@@ -1157,7 +1187,37 @@ static void hud_update_nav_point_local_player(
|
||||
}
|
||||
}
|
||||
|
||||
- match_assert_stack_frame("c:\\halo\\SOURCE\\interface\\hud_nav_points.c", 496);
|
||||
+ {
|
||||
+ short corrupt_index;
|
||||
+ short buffer_index;
|
||||
+
|
||||
+ for (buffer_index = 0x7F; buffer_index>=0; buffer_index--)
|
||||
+ {
|
||||
+ if (stack_buffer[buffer_index]!=0x62626262)
|
||||
+ {
|
||||
+ goto corrupt_stack_found;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ corrupt_index = NONE;
|
||||
+ goto stack_buffer_checked;
|
||||
+
|
||||
+corrupt_stack_found:
|
||||
+ corrupt_index = buffer_index;
|
||||
+
|
||||
+stack_buffer_checked:
|
||||
+
|
||||
+ match_vassert(
|
||||
+ "c:\\halo\\SOURCE\\interface\\hud_nav_points.c",
|
||||
+ 496,
|
||||
+ return_eip==get_return_eip(),
|
||||
+ "corrupt return address!");
|
||||
+ match_vassert(
|
||||
+ "c:\\halo\\SOURCE\\interface\\hud_nav_points.c",
|
||||
+ 496,
|
||||
+ corrupt_index==NONE,
|
||||
+ csprintf(temporary, "corrupt stack at %d!", corrupt_index));
|
||||
+ }
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
# hud_stack_check - hud_draw.h __inline check_stack_buffer packet (wave 4) - LEDGER
|
||||
|
||||
Slug: scratch/w/hud_stack_check/. Tree 16542e46 (git status clean at start). Units: hud_draw, hud_unit,
|
||||
hud_nav_points, hud_weapon, motion_sensor (+ all hud_draw.h consumers for the declaration-count sweep).
|
||||
|
||||
## R0 reading
|
||||
- WORKER_BRIEF 0-9, house rules, lane log held table (hud_unit row: this packet is the wave-4 reopen path;
|
||||
'hud_draw optimizer pragma' is a separate held item - not touched), review3_hud_unit LEDGER/REVIEW,
|
||||
hud_unit_audit LEDGER (lab F = lab-local __inline check_stack_buffer in hud_unit: 41/41 sections identical + ANY 48-B COMDAT),
|
||||
rejections: hud_draw + hud_unit `_fast_ftol` candidate-only-comdat-owner (hud_unit one to be retired by patch 04).
|
||||
- hud_draw.h consumers (grep `#include "(interface/)?hud_draw.h"`, no header includes it): 23 TUs:
|
||||
hud_draw hud_messaging hud_nav_points hud_unit hud_weapon motion_sensor ui_widget lightning rasterizer_debug
|
||||
rasterizer_lights rasterizer_xbox rasterizer_xbox_debug rasterizer_xbox_dynavobgeom rasterizer_xbox_environment
|
||||
rasterizer_xbox_environment_fog rasterizer_xbox_models rasterizer_xbox_screen_effect rasterizer_xbox_shadows
|
||||
rasterizer_xbox_transparent_geometry rasterizer_xbox_water shader_transparent_generic_preprocessor render_contrails render_sprite.
|
||||
|
||||
## F1 COMDAT selection in build/split is a csplit CONVENTION, not January evidence
|
||||
- comdat.py (slug, read-only COFF reader): build/split hud_draw.obj _get_return_eip sec1 0x10 NODUP, _check_stack_buffer sec2 0x30 NODUP.
|
||||
- selcensus2.py over build/split/source: EVERY code COMDAT is NODUP (5,299 external + 2,262 static, 0 ANY);
|
||||
ANY appears only on data (9,686 string literals). The proven header inline _fast_ftol (actor_combat) is also NODUP there.
|
||||
=> the split's selection type carries NO January information; it cannot discriminate header-inline vs plain .c.
|
||||
(The linked image does not preserve COMDAT selection.) Other evidence needed (map flags, inlining census, assert-line shape).
|
||||
|
||||
## F2 January sentinel census (sites2.py, build/split, read-only)
|
||||
- 26 check sites, ALL identical inlined shape: `mov eax,7Fh; mov ecx,62626262h; L: movsx edx,ax; cmp [ebp+edx*4-X],ecx;
|
||||
jne HIT; dec eax; test ax,ax; jge L; or esi,-1; call _get_return_eip; cmp [ebp-Y],eax; ...` and out-of-line
|
||||
`HIT: mov esi,eax; jmp back` (= inlined-function return merge); both asserts of every site carry ONE line literal:
|
||||
hud_draw x14 (0x64,0xe4,0x38b,0x408,0xb5,0x137,0x3d9,0x55c,0x32e,0x358,0x1ac,0x25a,0x2ad,0x2ec),
|
||||
hud_unit update_local_player 0x201, render 0x3c9; hud_nav_points custom_render 0x2a3, update_local 0x1f0;
|
||||
hud_weapon grenade 0x3a2, crosshairs 0x4e2, update_local 0x19e, render_weapon 0x308, update_weapon 0xd4;
|
||||
motion_sensor motion_sensor_update 0x282, update_motion_sensor 0x2f4, render_motion_sensor 0x33e.
|
||||
=> ONE shared macro (loop via inlined helper, then return-eip assert, then index assert at the invocation line).
|
||||
- January _check_stack_buffer (hud_draw sec2, 0x30): `push ebp; mov ebp,esp; mov ecx,[ebp+8]; mov eax,7Fh; ...;
|
||||
cmp [ecx+edx*4],62626262h; ...; or ax,0FFFFh; pop ebp; ret` => signature `short check_stack_buffer(long *buffer)`
|
||||
(short return in ax, short index, dword compare). 0 relocations to it in any split object. cachebeta publics:
|
||||
_check_stack_buffer PUBLIC at 0xC08F0, _get_return_eip PUBLIC at 0xC08E0 (external linkage, consistent with non-static __inline).
|
||||
- Sept-2001 map atlas 7eacac85: `_get_return_eip` 0xcff20 flag `i hud_draw.obj`; next listed symbol 0xcff60
|
||||
(_get_sprite_clip_rect): gap 0x40 = 0x10 get_return_eip + 0x30 check_stack_buffer (unlisted). 556 'i' entries
|
||||
in that map are all known header inlines (real_math distance3d/point_from_line3d..., objects.h bounding sphere, fast_ftol_C...).
|
||||
|
||||
## B0 production baseline sweep (sweep.py -> base/): 23 consumers
|
||||
hud_draw 22/0/1unw, hud_messaging 36/0, hud_nav_points 31/1, hud_unit 22/0, hud_weapon 13/3, motion_sensor 16/3,
|
||||
ui_widget 96/6, lightning 8/1, rasterizer_debug 12/0, rasterizer_lights 10/3, rasterizer_xbox 95/0, rasterizer_xbox_debug 18/0,
|
||||
dynavobgeom 17/0, environment 42/2, environment_fog 26/1, models 12/2, screen_effect 13/0, shadows 18/0,
|
||||
transparent_geometry 22/0, water 14/0, shader_transparent_generic_preprocessor 9/0, render_contrails 6/0, render_sprite 7/3.
|
||||
- Canaries _bitmap_copy (bitmap_drawing.c), _rasterizer_frame_statistics_draw (rasterizer_frame_statistics.c),
|
||||
_get_edge_vertex (geometry.c): none of these TUs includes hud_draw.h (not in the 23) -> unaffected by construction.
|
||||
|
||||
## C0 harness control (ctrl/interface/hud_draw.h = verbatim copy; gtu_ctrl/ TU copies with ONLY the include line
|
||||
changed to "w/hud_stack_check/ctrl/interface/hud_draw.h"; gate copies land in scratch/ so the relative path resolves)
|
||||
- sweep ctrl_out: identical gate rows to B0 for all 23; objcmp.py (every owned section both directions + anonymous
|
||||
sections except .debug$S + external/static symbol sets) base vs ctrl_out: 0 differences x 23. Harness is inert.
|
||||
|
||||
## H1 packet v1 (cand/interface/hud_draw.h + mkcand.py TUs; gtu_h1 -> h1_out)
|
||||
- hypothesis (F2 + lab F of hud_unit_audit): January had `__inline short check_stack_buffer(long *buffer)` visible in the
|
||||
5 sentinel TUs and ONE shared macro; spelling the inline in hud_draw.h + `match_assert_stack_frame(file, line)` macro
|
||||
(block: corrupt_index = check_stack_buffer(stack_buffer); return-eip vassert; index vassert) reproduces all 26 sites.
|
||||
- header v1 adds: enum {STACK_BUFFER_LENGTH=0x80, STACK_BUFFER_FILL=0x62626262} (moved from hud_draw.c/hud_unit.c TU-locals;
|
||||
hud_weapon's HUD_WEAPON_STACK_BUFFER_* replaced), the macro, section markers, and the __inline in '/* ---------- public code */'.
|
||||
- result: the 5 sentinel objects: EVERY section byte+reloc identical to production (objcmp 0 diffs for hud_draw; hud_unit,
|
||||
hud_nav_points, hud_weapon, motion_sensor differ ONLY by the new 48-B _check_stack_buffer COMDAT (external)). Gate rows
|
||||
unchanged (hud_draw 22/0/1, hud_unit 22/0, hud_nav_points 31/1, hud_weapon 13/3, motion_sensor 16/3; residuals byte-identical).
|
||||
- REGRESSION (declaration-count class): rasterizer_xbox_models __rasterizer_model_transparent_geometry_submit EXACT -> residual
|
||||
(12/2 -> 11/3). All other 17 non-user consumers: 0 section differences. -> bisect the added names.
|
||||
|
||||
## H1b bisect on rasterizer_xbox_models (hvariants.py; gate --fn row)
|
||||
- enum only (+2 names): EXACT; macro only: EXACT; inline with literals only: residual; inline+enum: residual;
|
||||
full v1: residual; inline placed right after the enum: residual. => the __inline DEFINITION flips it (position inert).
|
||||
## K-oracle (LAB ONLY, koracle.py: K dummy enum constants appended to hud_draw.h; never lands)
|
||||
- models __rasterizer_model_transparent_geometry_submit, dummies only: K=0..3 E, 4 r, 5 E, 6..26 r, 27..30 E.
|
||||
- with the inline + K dummies: K=0..17 r, 18..30 E => the inline definition costs ~9 name units in this TU
|
||||
(18+9=27 = first exact of the upper window). Needed: net added names <=3 (or 5) before the function, or a header the TU does not include.
|
||||
|
||||
## L1 models stale include (lab labs/models_noinc.c = production models minus `#include "interface/hud_draw.h"`)
|
||||
- rasterizer_xbox_models.c references NO hud_draw.h name (grep of all 19 declared names/constants: 0 hits; the include was
|
||||
added by 635bd83d when hud_draw.h still declared the ARGB converter, since moved to bitmap_color_conversion.h).
|
||||
14 of the 18 non-sentinel consumers use nothing from hud_draw.h (only hud_messaging, ui_widget, environment_fog do).
|
||||
- result: compiles; 12/2 unchanged; objcmp vs production: 0 section differences (all 62 owned sections + anon + symbols).
|
||||
=> dropping the dead include is byte-inert for models and removes models from the hud_draw.h blast radius.
|
||||
|
||||
## S1 emitted COMDAT identity + selection (h1_out objects)
|
||||
- hud_draw cand: _check_stack_buffer sel=ANY (production NODUP), chk 0x4957c551 unchanged; hud_unit/hud_nav_points/hud_weapon/
|
||||
motion_sensor: one new ANY _check_stack_buffer each. All five section_infos_equal to January build/split hud_draw
|
||||
_check_stack_buffer (48 B, 0 relocs, sha c7049c3184d2ed3e). _get_return_eip stays NODUP (plain naked definition, not moved).
|
||||
## S2 pair links (plink.py = provider_link.py's Link.Exe command with an explicit provider object)
|
||||
- provider = candidate hud_draw.obj (ANY): hud_unit, hud_nav_points, hud_weapon, motion_sensor each PASS both orders;
|
||||
all five together forward and reverse PASS.
|
||||
- CONTROL provider = production build/base hud_draw.obj (NODUP): hud_unit cand FAILS (LNK2005 both orders) => the hud_draw.c
|
||||
change (plain definition -> header inline) is REQUIRED in the same atomic packet; the probe discriminates.
|
||||
|
||||
## A1 hud_unit admission packet on the current tree (16542e46)
|
||||
- 01R, 01Ralt, 02, 03: git apply --check CLEAN on 16542e46. 04 (hud_unit_audit) FAILS on 16542e46 (rejections file moved:
|
||||
the hud_unit entry is now lines 36-43, followed by source/models/models) -> regenerated as 04R (see patches/).
|
||||
- No commits touched hud_unit.c/hud_draw.c/.h/hud_weapon.c/hud_nav_points.c/motion_sensor.c/rasterizer_xbox_models.c since
|
||||
954eebd2, so review3 cand_final_amended.c (= prod + 01R) and cand_minimal_amended.c (= prod + 01Ralt) are current.
|
||||
- config/symbols.json full copy (config/symbols.json in slug): 4 in-place line edits (CRLF kept; `patch` would have LF-converted
|
||||
the whole file - not used). config_ctrl = verbatim copies. csplit control -> split_ctrl == build/split 833/833;
|
||||
csplit emulated (slug config) -> split_emu differs ONLY in source/interface/hud_unit.obj.
|
||||
- cand01R/hud_unit.c = 01R + stack packet (mkcand --base-hud-unit), cand01Ralt/hud_unit.c = 01Ralt + stack packet:
|
||||
gate vs production split 20 exact + 2 names-only; gate_split vs split_emu 22/22 EXACT (both).
|
||||
object_audit_split (SPLIT_ROOT=split_emu) cand01R: every January-owned section ok, 30 January symbols 0 differ, PASS;
|
||||
surplus = .drectve, 5 pooled strings, 5 __real, _fast_ftol, _check_stack_buffer (new).
|
||||
objcmp vs review3 cand_final_amended.obj / cand_minimal_amended.obj: ONLY the new _check_stack_buffer COMDAT differs.
|
||||
- surplus identity: _check_stack_buffer IDENTICAL to January hud_draw's; _fast_ftol IDENTICAL to actor_combat's (also for 01Ralt,
|
||||
and every surplus of hud_nav_points/hud_weapon/motion_sensor candidates is IDENTICAL to its January provider).
|
||||
- provider_link.py (repo, build/base providers): all PASS except _check_stack_buffer vs PRODUCTION hud_draw (NODUP) -> LNK2005,
|
||||
expected until the packet's hud_draw.c/hud_draw.h change is built. provider_link_override.py (slug copy, provider hud_draw ->
|
||||
h1_out/hud_draw.obj): hud_unit 12/12 PASS both orders; hud_nav_points/hud_weapon/motion_sensor (--baseline) PASS.
|
||||
|
||||
## H2 FINAL packet v2 = v1 header + TU edits + `long stack_buffer[STACK_BUFFER_LENGTH]` in hud_nav_points(2)/motion_sensor(3)
|
||||
+ rasterizer_xbox_models.c drops its dead `#include "interface/hud_draw.h"` (gtu_h2 -> h2_out)
|
||||
- 23-consumer sweep: gate summaries identical to baseline; objcmp vs production: 0 differences in 19 objects (incl. models,
|
||||
every residual/parked body byte-identical => no park drift); hud_unit/hud_nav_points/hud_weapon/motion_sensor differ ONLY
|
||||
by the new ANY _check_stack_buffer (IDENTICAL to January's selected hud_draw copy).
|
||||
- /W3 /Zs warning census (warn.py) for the 6 edited TUs: identical warning multisets (hud_draw 5, hud_unit 3, nav 4, weapon 4,
|
||||
motion 4, models 4 kinds) - no new warnings.
|
||||
- canaries _bitmap_copy / _rasterizer_frame_statistics_draw / _get_edge_vertex: their TUs do not include hud_draw.h (not consumers).
|
||||
## P-A fallback (measured, NOT the proposal): focused header (lab name interface/hud_draw_stack_check.h) with enum+macro+inline,
|
||||
included only by the 5 sentinel TUs, hud_draw.h and models untouched: the 5 objects are objcmp-identical to H2 (0 diffs);
|
||||
the 18 other consumers are untouched by construction. Viable if the owner rejects the models dead-include removal.
|
||||
|
||||
## A2 patches (patches/, LF-normalised like the repo's other patches; core.autocrlf=true)
|
||||
- P1 hud_draw.h (SHARED HEADER, separate), P2 hud_draw.c, P3 hud_unit.c (standalone), P4 hud_nav_points.c, P5 hud_weapon.c,
|
||||
P6 motion_sensor.c, P7 rasterizer_xbox_models.c; 01RS = 01R + P3 in one hud_unit.c patch, 01RaltS = 01Ralt + P3;
|
||||
02 (unchanged, clean), 03 (unchanged, clean), 04R (regenerated for 16542e46). 01R/01Ralt copied verbatim.
|
||||
- git apply --check on 16542e46: every patch CLEAN alone; P1..P7 together CLEAN; FULL set P1,P2,01RS,P4..P7,02,03,04R CLEAN;
|
||||
FULL-alt (01RaltS) CLEAN. `patch` replay on LF copies (verify/): every result IDENTICAL to the slug candidate files;
|
||||
01R then P3 sequentially also reproduces cand01R/hud_unit.c.
|
||||
- fake_match_scan: candidates carry exactly the production leads (hud_draw.c get_return_eip naked/asm, pre-existing,
|
||||
unchanged); hud_unit 0 leads.
|
||||
## A3 strict emulation (objdiff 3.3.1 single-unit projects + repo semantic/admission pipeline; strict_emulate.py copy)
|
||||
- objproj_final (split_emu target, cand01R obj, complete=True, slug config with 04R): strict 22/22 fns, 6176/6176 code,
|
||||
152/152 data; rejections [] revoked []; classify candidates [] contradicted [] rejected []. Same for 01Ralt.
|
||||
- CONTROL with production rejections file (hud_unit _fast_ftol veto kept): 'contradicted' -> 04R is required.
|
||||
|
||||
## A4 object audits (repo object_audit.py, production split)
|
||||
- hud_draw: audit text IDENTICAL for production vs candidate (pre-existing FAIL (2): unwritten _fast_ftol_C / surplus _fast_ftol,
|
||||
_square_root - unchanged; the NODUP->ANY selection change of _check_stack_buffer is invisible to audit and scorer).
|
||||
- hud_nav_points / hud_weapon / motion_sensor: audit text differs ONLY by the added surplus line `+.text _check_stack_buffer 48`.
|
||||
- hud_unit: see A1 (PASS against split_emu).
|
||||
## Notes / not done
|
||||
- get_return_eip stays a plain naked hud_draw.c function with its hud_draw.h prototype (byte-identical everywhere; moving it
|
||||
to a header __inline, which the Sept-2001 'i' flag suggests, would only add 4 surplus COMDATs with no credit) - not probed.
|
||||
- git status of the worktree: clean (no tracked file touched).
|
||||
|
||||
## A5 subset measurement (P1 header only; hud_nav_points/hud_weapon/motion_sensor TUs left as production; gtu_sub -> sub_out)
|
||||
- hud_nav_points, motion_sensor: 0 section differences. hud_weapon: residual _render_weapon_hud BYTES DRIFT (same row class)
|
||||
- declaration-count effect of the header's names on an unchanged TU; with P5 (full set, H2) hud_weapon is objcmp-identical.
|
||||
=> P4-P6 are NOT optional hygiene: apply the full set P1,P2,(P3|01RS),P4,P5,P6,P7 atomically.
|
||||
|
||||
## RESULT
|
||||
- hud_unit: OBJECT_COMPLETE_CANDIDATE with the atomic packet P1+P2+P4+P5+P6+P7 + 01RS (=01R+P3; or 01RaltS) + 02 + 03 + 04R.
|
||||
BLOCKER 2 (hand-copied check_stack_buffer with invented gotos) is resolved by the genuine header inline + shared macro;
|
||||
BLOCKER 1 is 01R's. gate_split 22/22, object_audit PASS vs emulated split, surplus _fast_ftol + _check_stack_buffer both
|
||||
IDENTICAL to January's selected copies, pair links PASS both orders against the packet's hud_draw.obj, strict emulation 22/22.
|
||||
- hud_draw / hud_nav_points / hud_weapon / motion_sensor: all functions byte-identical (exact rows unchanged, residual/parked
|
||||
bodies byte-identical); the goto hand copies and TU-local duplicate macros/constants are gone (future admission hygiene).
|
||||
- 18 other hud_draw.h consumers: 0 section differences with P7 (models dead include) applied.
|
||||
- Reopen/owner points: (1) P7 is load-bearing only relative to P1 (the inline's ~9 declared names flip
|
||||
__rasterizer_model_transparent_geometry_submit); the include is dead (models uses no hud_draw.h name) and dropping it is
|
||||
byte-inert; fallback P-A = focused header included only by the 5 sentinel TUs (measured identical). (2) The macro name
|
||||
match_assert_stack_frame is descriptive (Bungie's is lost: /Od build has no sentinel, HCEX none). (3) get_return_eip left as is.
|
||||
- Integrator: after applying, full sweep of all 23 hud_draw.h consumers + parks; accumulation with other wave-4 header packets
|
||||
must be re-measured on the live tree (isolated tests do not compose).
|
||||
+154
@@ -0,0 +1,154 @@
|
||||
diff --git a/source/interface/hud_unit.c "b/C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\hud_stack_check\\cand\\interface\\hud_unit.c"
|
||||
index 1ff72603..73d9957f 100644
|
||||
--- a/source/interface/hud_unit.c
|
||||
+++ "b/C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\hud_stack_check\\cand\\interface\\hud_unit.c"
|
||||
@@ -3,13 +3,13 @@ HUD_UNIT.C
|
||||
|
||||
symbols in this file:
|
||||
000C6590 0010:
|
||||
- _unit_hud_outline_mapper_tick (0000)
|
||||
+ _code_000c6590 (0000)
|
||||
000C65A0 0010:
|
||||
- _unit_hud_shield_meter_mapper_tick (0000)
|
||||
+ _code_000c65a0 (0000)
|
||||
000C65B0 0010:
|
||||
_unit_hud_shield_meter_mapper_init (0000)
|
||||
000C65C0 0040:
|
||||
- _initialize_hud_state (0000)
|
||||
+ _code_000c65c0 (0000)
|
||||
000C6600 0070:
|
||||
_get_hud_state (0000)
|
||||
000C6670 0040:
|
||||
@@ -59,7 +59,7 @@ symbols in this file:
|
||||
002702D8 001d:
|
||||
??_C@_0BN@NPOPPJAG@old_local_player_index?$CB?$DNNONE?$AA@ (0000)
|
||||
002E4C68 0004:
|
||||
- ?overcharge_count@?1??hud_render_unit_interface@@9@9 (0000)
|
||||
+ _data_002e4c68 (0000)
|
||||
00453AC0 0004:
|
||||
_unit_hud_globals (0000)
|
||||
*/
|
||||
@@ -260,22 +260,20 @@ static struct unit_hud_globals *unit_hud_globals = NULL;
|
||||
extern struct hud_scripted_globals *hud_scripted_globals;
|
||||
extern struct hud_globals_definition *hud_globals;
|
||||
|
||||
-/* ---------- private code */
|
||||
+/* ---------- public code */
|
||||
|
||||
-static void unit_hud_outline_mapper_tick(
|
||||
+void code_000c6590(
|
||||
void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
-static void unit_hud_shield_meter_mapper_tick(
|
||||
+void code_000c65a0(
|
||||
void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
-/* ---------- public code */
|
||||
-
|
||||
void unit_hud_shield_meter_mapper_init(
|
||||
void)
|
||||
{
|
||||
@@ -354,8 +352,27 @@ void hud_initialize_unit_interface_for_new_map(
|
||||
local_player_index < MAXIMUM_NUMBER_OF_LOCAL_PLAYERS;
|
||||
local_player_index++)
|
||||
{
|
||||
- hud_state = get_hud_state(local_player_index);
|
||||
- initialize_hud_state(hud_state);
|
||||
+ match_assert(
|
||||
+ "c:\\halo\\SOURCE\\interface\\hud_unit.c",
|
||||
+ 0x106,
|
||||
+ local_player_index>=0 &&
|
||||
+ local_player_index<MAXIMUM_NUMBER_OF_LOCAL_PLAYERS);
|
||||
+ match_assert(
|
||||
+ "c:\\halo\\SOURCE\\interface\\hud_unit.c",
|
||||
+ 0x107,
|
||||
+ unit_hud_globals);
|
||||
+
|
||||
+ hud_state = &unit_hud_globals->hud_states[local_player_index];
|
||||
+ csmemset(
|
||||
+ hud_state->auxilary_flash_time,
|
||||
+ NONE,
|
||||
+ sizeof(hud_state->auxilary_flash_time));
|
||||
+ hud_state->last_body_vitality = -1.0f;
|
||||
+ hud_state->last_shield_vitality = -1.0f;
|
||||
+ hud_state->last_health_flash_time = NONE;
|
||||
+ hud_state->last_motion_sensor_flash_time = NONE;
|
||||
+ hud_state->fade_time = -1.0f;
|
||||
+ hud_state->last_unit_index = NONE;
|
||||
hud_state->sound_flags = 0;
|
||||
csmemset(
|
||||
hud_state->last_sound_handles,
|
||||
@@ -605,36 +622,38 @@ static void hud_update_unit_local_player(
|
||||
if (game_time_get() - hud_state->last_shield_hit_time < 15)
|
||||
{
|
||||
hud_state->fade_time = 0.0f;
|
||||
+ goto update_finished;
|
||||
}
|
||||
- else
|
||||
- {
|
||||
- hud_state->last_shield_vitality = unit->object.shield_vitality;
|
||||
- hud_state->fade_time +=
|
||||
- (real)(game_time_get() - hud_state->last_shield_hit_time) *
|
||||
- (1.0f / TICKS_PER_SECOND);
|
||||
- hud_state->last_shield_hit_time = game_time_get();
|
||||
- }
|
||||
- }
|
||||
- else if (hud_state->last_shield_vitality < unit->object.shield_vitality)
|
||||
- {
|
||||
+
|
||||
hud_state->last_shield_vitality = unit->object.shield_vitality;
|
||||
- hud_state->fade_time = -1.0f;
|
||||
- hud_state->last_shield_hit_time = game_time_get();
|
||||
+ hud_state->fade_time +=
|
||||
+ (real)(game_time_get() - hud_state->last_shield_hit_time) *
|
||||
+ (1.0f / TICKS_PER_SECOND);
|
||||
}
|
||||
else
|
||||
{
|
||||
- hud_state->last_shield_vitality = unit->object.shield_vitality;
|
||||
- if (hud_state->fade_time > 0.0f)
|
||||
+ if (hud_state->last_shield_vitality < unit->object.shield_vitality)
|
||||
+ {
|
||||
+ hud_state->last_shield_vitality = unit->object.shield_vitality;
|
||||
+ hud_state->fade_time = -1.0f;
|
||||
+ }
|
||||
+ else
|
||||
{
|
||||
- hud_state->fade_time +=
|
||||
- (real)(game_time_get() - hud_state->last_shield_hit_time) *
|
||||
- (1.0f / TICKS_PER_SECOND);
|
||||
+ hud_state->last_shield_vitality = unit->object.shield_vitality;
|
||||
+ if (hud_state->fade_time > 0.0f)
|
||||
+ {
|
||||
+ hud_state->fade_time +=
|
||||
+ (real)(game_time_get() - hud_state->last_shield_hit_time) *
|
||||
+ (1.0f / TICKS_PER_SECOND);
|
||||
+ }
|
||||
}
|
||||
- hud_state->last_shield_hit_time = game_time_get();
|
||||
}
|
||||
+
|
||||
+ hud_state->last_shield_hit_time = game_time_get();
|
||||
}
|
||||
}
|
||||
|
||||
+update_finished:
|
||||
if (cinematic_in_progress())
|
||||
{
|
||||
long player_index = local_player_get_player_index(local_player_index);
|
||||
@@ -838,9 +857,6 @@ void hud_render_unit_interface(
|
||||
0x209,
|
||||
player->local_player_index==render.local_player_index);
|
||||
|
||||
- unit_hud_shield_meter_mapper_tick();
|
||||
- unit_hud_outline_mapper_tick();
|
||||
-
|
||||
if (player->local_player_index == render.local_player_index &&
|
||||
player->unit_index != NONE)
|
||||
{
|
||||
+150
@@ -0,0 +1,150 @@
|
||||
diff --git a/source/interface/motion_sensor.c "b/C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\hud_stack_check\\cand\\interface\\motion_sensor.c"
|
||||
index c5094d45..70c4977b 100644
|
||||
--- a/source/interface/motion_sensor.c
|
||||
+++ "b/C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\hud_stack_check\\cand\\interface\\motion_sensor.c"
|
||||
@@ -276,8 +276,8 @@ real scale[] =
|
||||
};
|
||||
|
||||
long next_vertex_index= {0};
|
||||
-static struct motion_sensor_globals_definition *motion_sensor_globals = NULL;
|
||||
-static real sweep_theta = 0.f;
|
||||
+static struct motion_sensor_globals_definition *motion_sensor_globals;
|
||||
+static real sweep_theta;
|
||||
boolean debug_motion_sensor_draw_all_units= {0};
|
||||
|
||||
extern struct motion_sensor_hud_globals *hud_globals;
|
||||
@@ -309,7 +309,7 @@ static void motion_sensor_update(
|
||||
void)
|
||||
{
|
||||
long return_eip = get_return_eip();
|
||||
- long stack_buffer[0x80];
|
||||
+ long stack_buffer[STACK_BUFFER_LENGTH];
|
||||
long current_time;
|
||||
short active_sensor_index;
|
||||
|
||||
@@ -471,34 +471,7 @@ static void motion_sensor_update(
|
||||
}
|
||||
}
|
||||
|
||||
- {
|
||||
- short corrupt_index;
|
||||
- short buffer_index;
|
||||
-
|
||||
- for (buffer_index = 0x7F; buffer_index >= 0; buffer_index--)
|
||||
- {
|
||||
- if (stack_buffer[buffer_index] != 0x62626262)
|
||||
- goto corrupt_stack_found_motion_sensor_update;
|
||||
- }
|
||||
-
|
||||
- corrupt_index = NONE;
|
||||
- goto stack_buffer_checked_motion_sensor_update;
|
||||
-
|
||||
-corrupt_stack_found_motion_sensor_update:
|
||||
- corrupt_index = buffer_index;
|
||||
-
|
||||
-stack_buffer_checked_motion_sensor_update:
|
||||
- match_vassert(
|
||||
- "c:\\halo\\SOURCE\\interface\\motion_sensor.c",
|
||||
- 642,
|
||||
- return_eip == get_return_eip(),
|
||||
- "corrupt return address!");
|
||||
- match_vassert(
|
||||
- "c:\\halo\\SOURCE\\interface\\motion_sensor.c",
|
||||
- 642,
|
||||
- corrupt_index == NONE,
|
||||
- csprintf(temporary, "corrupt stack at %d!", corrupt_index));
|
||||
- }
|
||||
+ match_assert_stack_frame("c:\\halo\\SOURCE\\interface\\motion_sensor.c", 642);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -507,7 +480,7 @@ static void update_motion_sensor(
|
||||
short local_player_index)
|
||||
{
|
||||
long return_eip = get_return_eip();
|
||||
- long stack_buffer[0x80];
|
||||
+ long stack_buffer[STACK_BUFFER_LENGTH];
|
||||
struct motion_sensor_player *player;
|
||||
short active_sensor_index;
|
||||
long player_index;
|
||||
@@ -613,34 +586,7 @@ static void update_motion_sensor(
|
||||
sensor->custom_blip_count -= (byte)out_of_range_count;
|
||||
|
||||
update_motion_sensor_done:
|
||||
- {
|
||||
- short corrupt_index;
|
||||
- short buffer_index;
|
||||
-
|
||||
- for (buffer_index = 0x7F; buffer_index >= 0; buffer_index--)
|
||||
- {
|
||||
- if (stack_buffer[buffer_index] != 0x62626262)
|
||||
- goto corrupt_stack_found_update_motion_sensor;
|
||||
- }
|
||||
-
|
||||
- corrupt_index = NONE;
|
||||
- goto stack_buffer_checked_update_motion_sensor;
|
||||
-
|
||||
-corrupt_stack_found_update_motion_sensor:
|
||||
- corrupt_index = buffer_index;
|
||||
-
|
||||
-stack_buffer_checked_update_motion_sensor:
|
||||
- match_vassert(
|
||||
- "c:\\halo\\SOURCE\\interface\\motion_sensor.c",
|
||||
- 756,
|
||||
- return_eip == get_return_eip(),
|
||||
- "corrupt return address!");
|
||||
- match_vassert(
|
||||
- "c:\\halo\\SOURCE\\interface\\motion_sensor.c",
|
||||
- 756,
|
||||
- corrupt_index == NONE,
|
||||
- csprintf(temporary, "corrupt stack at %d!", corrupt_index));
|
||||
- }
|
||||
+ match_assert_stack_frame("c:\\halo\\SOURCE\\interface\\motion_sensor.c", 756);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -651,7 +597,7 @@ static void render_motion_sensor(
|
||||
point2d const *reference)
|
||||
{
|
||||
long return_eip = get_return_eip();
|
||||
- long stack_buffer[0x80];
|
||||
+ long stack_buffer[STACK_BUFFER_LENGTH];
|
||||
director_perspective perspective;
|
||||
struct motion_sensor_player *player;
|
||||
real relative_scale;
|
||||
@@ -743,34 +689,7 @@ static void render_motion_sensor(
|
||||
rasterizer_hud_motion_sensor_blip_end(¢er_point, sweep_theta);
|
||||
|
||||
render_motion_sensor_done:
|
||||
- {
|
||||
- short corrupt_index;
|
||||
- short buffer_index;
|
||||
-
|
||||
- for (buffer_index = 0x7F; buffer_index >= 0; buffer_index--)
|
||||
- {
|
||||
- if (stack_buffer[buffer_index] != 0x62626262)
|
||||
- goto corrupt_stack_found_render_motion_sensor;
|
||||
- }
|
||||
-
|
||||
- corrupt_index = NONE;
|
||||
- goto stack_buffer_checked_render_motion_sensor;
|
||||
-
|
||||
-corrupt_stack_found_render_motion_sensor:
|
||||
- corrupt_index = buffer_index;
|
||||
-
|
||||
-stack_buffer_checked_render_motion_sensor:
|
||||
- match_vassert(
|
||||
- "c:\\halo\\SOURCE\\interface\\motion_sensor.c",
|
||||
- 830,
|
||||
- return_eip == get_return_eip(),
|
||||
- "corrupt return address!");
|
||||
- match_vassert(
|
||||
- "c:\\halo\\SOURCE\\interface\\motion_sensor.c",
|
||||
- 830,
|
||||
- corrupt_index == NONE,
|
||||
- csprintf(temporary, "corrupt stack at %d!", corrupt_index));
|
||||
- }
|
||||
+ match_assert_stack_frame("c:\\halo\\SOURCE\\interface\\motion_sensor.c", 830);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
diff --git a/source/interface/hud_unit.c "b/C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\hud_stack_check\\cand01Ralt\\hud_unit.c"
|
||||
index 1ff72603..195128e0 100644
|
||||
--- a/source/interface/hud_unit.c
|
||||
+++ "b/C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\hud_stack_check\\cand01Ralt\\hud_unit.c"
|
||||
@@ -605,36 +605,38 @@ static void hud_update_unit_local_player(
|
||||
if (game_time_get() - hud_state->last_shield_hit_time < 15)
|
||||
{
|
||||
hud_state->fade_time = 0.0f;
|
||||
+ goto update_finished;
|
||||
}
|
||||
- else
|
||||
- {
|
||||
- hud_state->last_shield_vitality = unit->object.shield_vitality;
|
||||
- hud_state->fade_time +=
|
||||
- (real)(game_time_get() - hud_state->last_shield_hit_time) *
|
||||
- (1.0f / TICKS_PER_SECOND);
|
||||
- hud_state->last_shield_hit_time = game_time_get();
|
||||
- }
|
||||
- }
|
||||
- else if (hud_state->last_shield_vitality < unit->object.shield_vitality)
|
||||
- {
|
||||
+
|
||||
hud_state->last_shield_vitality = unit->object.shield_vitality;
|
||||
- hud_state->fade_time = -1.0f;
|
||||
- hud_state->last_shield_hit_time = game_time_get();
|
||||
+ hud_state->fade_time +=
|
||||
+ (real)(game_time_get() - hud_state->last_shield_hit_time) *
|
||||
+ (1.0f / TICKS_PER_SECOND);
|
||||
}
|
||||
else
|
||||
{
|
||||
- hud_state->last_shield_vitality = unit->object.shield_vitality;
|
||||
- if (hud_state->fade_time > 0.0f)
|
||||
+ if (hud_state->last_shield_vitality < unit->object.shield_vitality)
|
||||
{
|
||||
- hud_state->fade_time +=
|
||||
- (real)(game_time_get() - hud_state->last_shield_hit_time) *
|
||||
- (1.0f / TICKS_PER_SECOND);
|
||||
+ hud_state->last_shield_vitality = unit->object.shield_vitality;
|
||||
+ hud_state->fade_time = -1.0f;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ hud_state->last_shield_vitality = unit->object.shield_vitality;
|
||||
+ if (hud_state->fade_time > 0.0f)
|
||||
+ {
|
||||
+ hud_state->fade_time +=
|
||||
+ (real)(game_time_get() - hud_state->last_shield_hit_time) *
|
||||
+ (1.0f / TICKS_PER_SECOND);
|
||||
+ }
|
||||
}
|
||||
- hud_state->last_shield_hit_time = game_time_get();
|
||||
}
|
||||
+
|
||||
+ hud_state->last_shield_hit_time = game_time_get();
|
||||
}
|
||||
}
|
||||
|
||||
+update_finished:
|
||||
if (cinematic_in_progress())
|
||||
{
|
||||
long player_index = local_player_get_player_index(local_player_index);
|
||||
+239
@@ -0,0 +1,239 @@
|
||||
diff --git a/source/interface/hud_unit.c b/source/interface/hud_unit.c
|
||||
index cfa13729..1ff72603 100644
|
||||
--- a/source/interface/hud_unit.c
|
||||
+++ b/source/interface/hud_unit.c
|
||||
@@ -3,13 +3,13 @@ HUD_UNIT.C
|
||||
|
||||
symbols in this file:
|
||||
000C6590 0010:
|
||||
- _code_000c6590 (0000)
|
||||
+ _unit_hud_outline_mapper_tick (0000)
|
||||
000C65A0 0010:
|
||||
- _code_000c65a0 (0000)
|
||||
+ _unit_hud_shield_meter_mapper_tick (0000)
|
||||
000C65B0 0010:
|
||||
_unit_hud_shield_meter_mapper_init (0000)
|
||||
000C65C0 0040:
|
||||
- _code_000c65c0 (0000)
|
||||
+ _initialize_hud_state (0000)
|
||||
000C6600 0070:
|
||||
_get_hud_state (0000)
|
||||
000C6670 0040:
|
||||
@@ -59,7 +59,7 @@ symbols in this file:
|
||||
002702D8 001d:
|
||||
??_C@_0BN@NPOPPJAG@old_local_player_index?$CB?$DNNONE?$AA@ (0000)
|
||||
002E4C68 0004:
|
||||
- _data_002e4c68 (0000)
|
||||
+ ?overcharge_count@?1??hud_render_unit_interface@@9@9 (0000)
|
||||
00453AC0 0004:
|
||||
_unit_hud_globals (0000)
|
||||
*/
|
||||
@@ -113,12 +113,6 @@ enum hud_damage_indicator_direction
|
||||
NUMBER_OF_HUD_DAMAGE_INDICATOR_DIRECTIONS
|
||||
};
|
||||
|
||||
-enum
|
||||
-{
|
||||
- STACK_BUFFER_LENGTH = 0x80,
|
||||
- STACK_BUFFER_FILL = 0x62626262,
|
||||
-};
|
||||
-
|
||||
/* ---------- macros */
|
||||
|
||||
/* ---------- structures */
|
||||
@@ -266,20 +260,22 @@ static struct unit_hud_globals *unit_hud_globals = NULL;
|
||||
extern struct hud_scripted_globals *hud_scripted_globals;
|
||||
extern struct hud_globals_definition *hud_globals;
|
||||
|
||||
-/* ---------- public code */
|
||||
+/* ---------- private code */
|
||||
|
||||
-void code_000c6590(
|
||||
+static void unit_hud_outline_mapper_tick(
|
||||
void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
-void code_000c65a0(
|
||||
+static void unit_hud_shield_meter_mapper_tick(
|
||||
void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
+/* ---------- public code */
|
||||
+
|
||||
void unit_hud_shield_meter_mapper_init(
|
||||
void)
|
||||
{
|
||||
@@ -358,27 +354,8 @@ void hud_initialize_unit_interface_for_new_map(
|
||||
local_player_index < MAXIMUM_NUMBER_OF_LOCAL_PLAYERS;
|
||||
local_player_index++)
|
||||
{
|
||||
- match_assert(
|
||||
- "c:\\halo\\SOURCE\\interface\\hud_unit.c",
|
||||
- 0x106,
|
||||
- local_player_index>=0 &&
|
||||
- local_player_index<MAXIMUM_NUMBER_OF_LOCAL_PLAYERS);
|
||||
- match_assert(
|
||||
- "c:\\halo\\SOURCE\\interface\\hud_unit.c",
|
||||
- 0x107,
|
||||
- unit_hud_globals);
|
||||
-
|
||||
- hud_state = &unit_hud_globals->hud_states[local_player_index];
|
||||
- csmemset(
|
||||
- hud_state->auxilary_flash_time,
|
||||
- NONE,
|
||||
- sizeof(hud_state->auxilary_flash_time));
|
||||
- hud_state->last_body_vitality = -1.0f;
|
||||
- hud_state->last_shield_vitality = -1.0f;
|
||||
- hud_state->last_health_flash_time = NONE;
|
||||
- hud_state->last_motion_sensor_flash_time = NONE;
|
||||
- hud_state->fade_time = -1.0f;
|
||||
- hud_state->last_unit_index = NONE;
|
||||
+ hud_state = get_hud_state(local_player_index);
|
||||
+ initialize_hud_state(hud_state);
|
||||
hud_state->sound_flags = 0;
|
||||
csmemset(
|
||||
hud_state->last_sound_handles,
|
||||
@@ -628,38 +605,36 @@ static void hud_update_unit_local_player(
|
||||
if (game_time_get() - hud_state->last_shield_hit_time < 15)
|
||||
{
|
||||
hud_state->fade_time = 0.0f;
|
||||
- goto update_finished;
|
||||
}
|
||||
-
|
||||
+ else
|
||||
+ {
|
||||
+ hud_state->last_shield_vitality = unit->object.shield_vitality;
|
||||
+ hud_state->fade_time +=
|
||||
+ (real)(game_time_get() - hud_state->last_shield_hit_time) *
|
||||
+ (1.0f / TICKS_PER_SECOND);
|
||||
+ hud_state->last_shield_hit_time = game_time_get();
|
||||
+ }
|
||||
+ }
|
||||
+ else if (hud_state->last_shield_vitality < unit->object.shield_vitality)
|
||||
+ {
|
||||
hud_state->last_shield_vitality = unit->object.shield_vitality;
|
||||
- hud_state->fade_time +=
|
||||
- (real)(game_time_get() - hud_state->last_shield_hit_time) *
|
||||
- (1.0f / TICKS_PER_SECOND);
|
||||
+ hud_state->fade_time = -1.0f;
|
||||
+ hud_state->last_shield_hit_time = game_time_get();
|
||||
}
|
||||
else
|
||||
{
|
||||
- if (hud_state->last_shield_vitality < unit->object.shield_vitality)
|
||||
- {
|
||||
- hud_state->last_shield_vitality = unit->object.shield_vitality;
|
||||
- hud_state->fade_time = -1.0f;
|
||||
- }
|
||||
- else
|
||||
+ hud_state->last_shield_vitality = unit->object.shield_vitality;
|
||||
+ if (hud_state->fade_time > 0.0f)
|
||||
{
|
||||
- hud_state->last_shield_vitality = unit->object.shield_vitality;
|
||||
- if (hud_state->fade_time > 0.0f)
|
||||
- {
|
||||
- hud_state->fade_time +=
|
||||
- (real)(game_time_get() - hud_state->last_shield_hit_time) *
|
||||
- (1.0f / TICKS_PER_SECOND);
|
||||
- }
|
||||
+ hud_state->fade_time +=
|
||||
+ (real)(game_time_get() - hud_state->last_shield_hit_time) *
|
||||
+ (1.0f / TICKS_PER_SECOND);
|
||||
}
|
||||
+ hud_state->last_shield_hit_time = game_time_get();
|
||||
}
|
||||
-
|
||||
- hud_state->last_shield_hit_time = game_time_get();
|
||||
}
|
||||
}
|
||||
|
||||
-update_finished:
|
||||
if (cinematic_in_progress())
|
||||
{
|
||||
long player_index = local_player_get_player_index(local_player_index);
|
||||
@@ -672,34 +647,7 @@ update_finished:
|
||||
}
|
||||
}
|
||||
|
||||
- {
|
||||
- short corrupt_index;
|
||||
- short buffer_index;
|
||||
-
|
||||
- for (buffer_index = STACK_BUFFER_LENGTH - 1; buffer_index >= 0; buffer_index--)
|
||||
- {
|
||||
- if (stack_buffer[buffer_index] != STACK_BUFFER_FILL)
|
||||
- goto corrupt_stack_found;
|
||||
- }
|
||||
-
|
||||
- corrupt_index = NONE;
|
||||
- goto stack_buffer_checked;
|
||||
-
|
||||
-corrupt_stack_found:
|
||||
- corrupt_index = buffer_index;
|
||||
-
|
||||
-stack_buffer_checked:
|
||||
- match_vassert(
|
||||
- "c:\\halo\\SOURCE\\interface\\hud_unit.c",
|
||||
- 0x201,
|
||||
- return_eip == get_return_eip(),
|
||||
- "corrupt return address!");
|
||||
- match_vassert(
|
||||
- "c:\\halo\\SOURCE\\interface\\hud_unit.c",
|
||||
- 0x201,
|
||||
- corrupt_index == NONE,
|
||||
- csprintf(temporary, "corrupt stack at %d!", corrupt_index));
|
||||
- }
|
||||
+ match_assert_stack_frame("c:\\halo\\SOURCE\\interface\\hud_unit.c", 0x201);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -890,6 +838,9 @@ void hud_render_unit_interface(
|
||||
0x209,
|
||||
player->local_player_index==render.local_player_index);
|
||||
|
||||
+ unit_hud_shield_meter_mapper_tick();
|
||||
+ unit_hud_outline_mapper_tick();
|
||||
+
|
||||
if (player->local_player_index == render.local_player_index &&
|
||||
player->unit_index != NONE)
|
||||
{
|
||||
@@ -1439,34 +1390,7 @@ void hud_render_unit_interface(
|
||||
}
|
||||
}
|
||||
|
||||
- {
|
||||
- short corrupt_index;
|
||||
- short buffer_index;
|
||||
-
|
||||
- for (buffer_index = STACK_BUFFER_LENGTH - 1; buffer_index >= 0; buffer_index--)
|
||||
- {
|
||||
- if (stack_buffer[buffer_index] != STACK_BUFFER_FILL)
|
||||
- goto corrupt_stack_found;
|
||||
- }
|
||||
-
|
||||
- corrupt_index = NONE;
|
||||
- goto stack_buffer_checked;
|
||||
-
|
||||
-corrupt_stack_found:
|
||||
- corrupt_index = buffer_index;
|
||||
-
|
||||
-stack_buffer_checked:
|
||||
- match_vassert(
|
||||
- "c:\\halo\\SOURCE\\interface\\hud_unit.c",
|
||||
- 0x3C9,
|
||||
- return_eip == get_return_eip(),
|
||||
- "corrupt return address!");
|
||||
- match_vassert(
|
||||
- "c:\\halo\\SOURCE\\interface\\hud_unit.c",
|
||||
- 0x3C9,
|
||||
- corrupt_index == NONE,
|
||||
- csprintf(temporary, "corrupt stack at %d!", corrupt_index));
|
||||
- }
|
||||
+ match_assert_stack_frame("c:\\halo\\SOURCE\\interface\\hud_unit.c", 0x3C9);
|
||||
|
||||
return;
|
||||
}
|
||||
+154
@@ -0,0 +1,154 @@
|
||||
diff --git a/source/interface/hud_unit.c b/source/interface/hud_unit.c
|
||||
index cfa13729975a4a59a5d4df323152ea62d97b9600..858a739cfca3d1e930d813529f7869635ac58af4 100644
|
||||
--- a/source/interface/hud_unit.c
|
||||
+++ b/source/interface/hud_unit.c
|
||||
@@ -3,13 +3,13 @@ HUD_UNIT.C
|
||||
|
||||
symbols in this file:
|
||||
000C6590 0010:
|
||||
- _code_000c6590 (0000)
|
||||
+ _unit_hud_outline_mapper_tick (0000)
|
||||
000C65A0 0010:
|
||||
- _code_000c65a0 (0000)
|
||||
+ _unit_hud_shield_meter_mapper_tick (0000)
|
||||
000C65B0 0010:
|
||||
_unit_hud_shield_meter_mapper_init (0000)
|
||||
000C65C0 0040:
|
||||
- _code_000c65c0 (0000)
|
||||
+ _initialize_hud_state (0000)
|
||||
000C6600 0070:
|
||||
_get_hud_state (0000)
|
||||
000C6670 0040:
|
||||
@@ -59,7 +59,7 @@ symbols in this file:
|
||||
002702D8 001d:
|
||||
??_C@_0BN@NPOPPJAG@old_local_player_index?$CB?$DNNONE?$AA@ (0000)
|
||||
002E4C68 0004:
|
||||
- _data_002e4c68 (0000)
|
||||
+ ?overcharge_count@?1??hud_render_unit_interface@@9@9 (0000)
|
||||
00453AC0 0004:
|
||||
_unit_hud_globals (0000)
|
||||
*/
|
||||
@@ -266,20 +266,22 @@ static struct unit_hud_globals *unit_hud_globals = NULL;
|
||||
extern struct hud_scripted_globals *hud_scripted_globals;
|
||||
extern struct hud_globals_definition *hud_globals;
|
||||
|
||||
-/* ---------- public code */
|
||||
+/* ---------- private code */
|
||||
|
||||
-void code_000c6590(
|
||||
+static void unit_hud_outline_mapper_tick(
|
||||
void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
-void code_000c65a0(
|
||||
+static void unit_hud_shield_meter_mapper_tick(
|
||||
void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
+/* ---------- public code */
|
||||
+
|
||||
void unit_hud_shield_meter_mapper_init(
|
||||
void)
|
||||
{
|
||||
@@ -358,27 +360,8 @@ void hud_initialize_unit_interface_for_new_map(
|
||||
local_player_index < MAXIMUM_NUMBER_OF_LOCAL_PLAYERS;
|
||||
local_player_index++)
|
||||
{
|
||||
- match_assert(
|
||||
- "c:\\halo\\SOURCE\\interface\\hud_unit.c",
|
||||
- 0x106,
|
||||
- local_player_index>=0 &&
|
||||
- local_player_index<MAXIMUM_NUMBER_OF_LOCAL_PLAYERS);
|
||||
- match_assert(
|
||||
- "c:\\halo\\SOURCE\\interface\\hud_unit.c",
|
||||
- 0x107,
|
||||
- unit_hud_globals);
|
||||
-
|
||||
- hud_state = &unit_hud_globals->hud_states[local_player_index];
|
||||
- csmemset(
|
||||
- hud_state->auxilary_flash_time,
|
||||
- NONE,
|
||||
- sizeof(hud_state->auxilary_flash_time));
|
||||
- hud_state->last_body_vitality = -1.0f;
|
||||
- hud_state->last_shield_vitality = -1.0f;
|
||||
- hud_state->last_health_flash_time = NONE;
|
||||
- hud_state->last_motion_sensor_flash_time = NONE;
|
||||
- hud_state->fade_time = -1.0f;
|
||||
- hud_state->last_unit_index = NONE;
|
||||
+ hud_state = get_hud_state(local_player_index);
|
||||
+ initialize_hud_state(hud_state);
|
||||
hud_state->sound_flags = 0;
|
||||
csmemset(
|
||||
hud_state->last_sound_handles,
|
||||
@@ -628,38 +611,36 @@ static void hud_update_unit_local_player(
|
||||
if (game_time_get() - hud_state->last_shield_hit_time < 15)
|
||||
{
|
||||
hud_state->fade_time = 0.0f;
|
||||
- goto update_finished;
|
||||
}
|
||||
-
|
||||
+ else
|
||||
+ {
|
||||
+ hud_state->last_shield_vitality = unit->object.shield_vitality;
|
||||
+ hud_state->fade_time +=
|
||||
+ (real)(game_time_get() - hud_state->last_shield_hit_time) *
|
||||
+ (1.0f / TICKS_PER_SECOND);
|
||||
+ hud_state->last_shield_hit_time = game_time_get();
|
||||
+ }
|
||||
+ }
|
||||
+ else if (hud_state->last_shield_vitality < unit->object.shield_vitality)
|
||||
+ {
|
||||
hud_state->last_shield_vitality = unit->object.shield_vitality;
|
||||
- hud_state->fade_time +=
|
||||
- (real)(game_time_get() - hud_state->last_shield_hit_time) *
|
||||
- (1.0f / TICKS_PER_SECOND);
|
||||
+ hud_state->fade_time = -1.0f;
|
||||
+ hud_state->last_shield_hit_time = game_time_get();
|
||||
}
|
||||
else
|
||||
{
|
||||
- if (hud_state->last_shield_vitality < unit->object.shield_vitality)
|
||||
- {
|
||||
- hud_state->last_shield_vitality = unit->object.shield_vitality;
|
||||
- hud_state->fade_time = -1.0f;
|
||||
- }
|
||||
- else
|
||||
+ hud_state->last_shield_vitality = unit->object.shield_vitality;
|
||||
+ if (hud_state->fade_time > 0.0f)
|
||||
{
|
||||
- hud_state->last_shield_vitality = unit->object.shield_vitality;
|
||||
- if (hud_state->fade_time > 0.0f)
|
||||
- {
|
||||
- hud_state->fade_time +=
|
||||
- (real)(game_time_get() - hud_state->last_shield_hit_time) *
|
||||
- (1.0f / TICKS_PER_SECOND);
|
||||
- }
|
||||
+ hud_state->fade_time +=
|
||||
+ (real)(game_time_get() - hud_state->last_shield_hit_time) *
|
||||
+ (1.0f / TICKS_PER_SECOND);
|
||||
}
|
||||
+ hud_state->last_shield_hit_time = game_time_get();
|
||||
}
|
||||
-
|
||||
- hud_state->last_shield_hit_time = game_time_get();
|
||||
}
|
||||
}
|
||||
|
||||
-update_finished:
|
||||
if (cinematic_in_progress())
|
||||
{
|
||||
long player_index = local_player_get_player_index(local_player_index);
|
||||
@@ -890,6 +871,9 @@ void hud_render_unit_interface(
|
||||
0x209,
|
||||
player->local_player_index==render.local_player_index);
|
||||
|
||||
+ unit_hud_shield_meter_mapper_tick();
|
||||
+ unit_hud_outline_mapper_tick();
|
||||
+
|
||||
if (player->local_player_index == render.local_player_index &&
|
||||
player->unit_index != NONE)
|
||||
{
|
||||
+181
@@ -0,0 +1,181 @@
|
||||
diff --git a/source/interface/hud_unit.c b/source/interface/hud_unit.c
|
||||
index cfa13729..195128e0 100644
|
||||
--- a/source/interface/hud_unit.c
|
||||
+++ b/source/interface/hud_unit.c
|
||||
@@ -3,13 +3,13 @@ HUD_UNIT.C
|
||||
|
||||
symbols in this file:
|
||||
000C6590 0010:
|
||||
- _code_000c6590 (0000)
|
||||
+ _unit_hud_outline_mapper_tick (0000)
|
||||
000C65A0 0010:
|
||||
- _code_000c65a0 (0000)
|
||||
+ _unit_hud_shield_meter_mapper_tick (0000)
|
||||
000C65B0 0010:
|
||||
_unit_hud_shield_meter_mapper_init (0000)
|
||||
000C65C0 0040:
|
||||
- _code_000c65c0 (0000)
|
||||
+ _initialize_hud_state (0000)
|
||||
000C6600 0070:
|
||||
_get_hud_state (0000)
|
||||
000C6670 0040:
|
||||
@@ -59,7 +59,7 @@ symbols in this file:
|
||||
002702D8 001d:
|
||||
??_C@_0BN@NPOPPJAG@old_local_player_index?$CB?$DNNONE?$AA@ (0000)
|
||||
002E4C68 0004:
|
||||
- _data_002e4c68 (0000)
|
||||
+ ?overcharge_count@?1??hud_render_unit_interface@@9@9 (0000)
|
||||
00453AC0 0004:
|
||||
_unit_hud_globals (0000)
|
||||
*/
|
||||
@@ -113,12 +113,6 @@ enum hud_damage_indicator_direction
|
||||
NUMBER_OF_HUD_DAMAGE_INDICATOR_DIRECTIONS
|
||||
};
|
||||
|
||||
-enum
|
||||
-{
|
||||
- STACK_BUFFER_LENGTH = 0x80,
|
||||
- STACK_BUFFER_FILL = 0x62626262,
|
||||
-};
|
||||
-
|
||||
/* ---------- macros */
|
||||
|
||||
/* ---------- structures */
|
||||
@@ -266,20 +260,22 @@ static struct unit_hud_globals *unit_hud_globals = NULL;
|
||||
extern struct hud_scripted_globals *hud_scripted_globals;
|
||||
extern struct hud_globals_definition *hud_globals;
|
||||
|
||||
-/* ---------- public code */
|
||||
+/* ---------- private code */
|
||||
|
||||
-void code_000c6590(
|
||||
+static void unit_hud_outline_mapper_tick(
|
||||
void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
-void code_000c65a0(
|
||||
+static void unit_hud_shield_meter_mapper_tick(
|
||||
void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
+/* ---------- public code */
|
||||
+
|
||||
void unit_hud_shield_meter_mapper_init(
|
||||
void)
|
||||
{
|
||||
@@ -358,27 +354,8 @@ void hud_initialize_unit_interface_for_new_map(
|
||||
local_player_index < MAXIMUM_NUMBER_OF_LOCAL_PLAYERS;
|
||||
local_player_index++)
|
||||
{
|
||||
- match_assert(
|
||||
- "c:\\halo\\SOURCE\\interface\\hud_unit.c",
|
||||
- 0x106,
|
||||
- local_player_index>=0 &&
|
||||
- local_player_index<MAXIMUM_NUMBER_OF_LOCAL_PLAYERS);
|
||||
- match_assert(
|
||||
- "c:\\halo\\SOURCE\\interface\\hud_unit.c",
|
||||
- 0x107,
|
||||
- unit_hud_globals);
|
||||
-
|
||||
- hud_state = &unit_hud_globals->hud_states[local_player_index];
|
||||
- csmemset(
|
||||
- hud_state->auxilary_flash_time,
|
||||
- NONE,
|
||||
- sizeof(hud_state->auxilary_flash_time));
|
||||
- hud_state->last_body_vitality = -1.0f;
|
||||
- hud_state->last_shield_vitality = -1.0f;
|
||||
- hud_state->last_health_flash_time = NONE;
|
||||
- hud_state->last_motion_sensor_flash_time = NONE;
|
||||
- hud_state->fade_time = -1.0f;
|
||||
- hud_state->last_unit_index = NONE;
|
||||
+ hud_state = get_hud_state(local_player_index);
|
||||
+ initialize_hud_state(hud_state);
|
||||
hud_state->sound_flags = 0;
|
||||
csmemset(
|
||||
hud_state->last_sound_handles,
|
||||
@@ -672,34 +649,7 @@ update_finished:
|
||||
}
|
||||
}
|
||||
|
||||
- {
|
||||
- short corrupt_index;
|
||||
- short buffer_index;
|
||||
-
|
||||
- for (buffer_index = STACK_BUFFER_LENGTH - 1; buffer_index >= 0; buffer_index--)
|
||||
- {
|
||||
- if (stack_buffer[buffer_index] != STACK_BUFFER_FILL)
|
||||
- goto corrupt_stack_found;
|
||||
- }
|
||||
-
|
||||
- corrupt_index = NONE;
|
||||
- goto stack_buffer_checked;
|
||||
-
|
||||
-corrupt_stack_found:
|
||||
- corrupt_index = buffer_index;
|
||||
-
|
||||
-stack_buffer_checked:
|
||||
- match_vassert(
|
||||
- "c:\\halo\\SOURCE\\interface\\hud_unit.c",
|
||||
- 0x201,
|
||||
- return_eip == get_return_eip(),
|
||||
- "corrupt return address!");
|
||||
- match_vassert(
|
||||
- "c:\\halo\\SOURCE\\interface\\hud_unit.c",
|
||||
- 0x201,
|
||||
- corrupt_index == NONE,
|
||||
- csprintf(temporary, "corrupt stack at %d!", corrupt_index));
|
||||
- }
|
||||
+ match_assert_stack_frame("c:\\halo\\SOURCE\\interface\\hud_unit.c", 0x201);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -890,6 +840,9 @@ void hud_render_unit_interface(
|
||||
0x209,
|
||||
player->local_player_index==render.local_player_index);
|
||||
|
||||
+ unit_hud_shield_meter_mapper_tick();
|
||||
+ unit_hud_outline_mapper_tick();
|
||||
+
|
||||
if (player->local_player_index == render.local_player_index &&
|
||||
player->unit_index != NONE)
|
||||
{
|
||||
@@ -1439,34 +1392,7 @@ void hud_render_unit_interface(
|
||||
}
|
||||
}
|
||||
|
||||
- {
|
||||
- short corrupt_index;
|
||||
- short buffer_index;
|
||||
-
|
||||
- for (buffer_index = STACK_BUFFER_LENGTH - 1; buffer_index >= 0; buffer_index--)
|
||||
- {
|
||||
- if (stack_buffer[buffer_index] != STACK_BUFFER_FILL)
|
||||
- goto corrupt_stack_found;
|
||||
- }
|
||||
-
|
||||
- corrupt_index = NONE;
|
||||
- goto stack_buffer_checked;
|
||||
-
|
||||
-corrupt_stack_found:
|
||||
- corrupt_index = buffer_index;
|
||||
-
|
||||
-stack_buffer_checked:
|
||||
- match_vassert(
|
||||
- "c:\\halo\\SOURCE\\interface\\hud_unit.c",
|
||||
- 0x3C9,
|
||||
- return_eip == get_return_eip(),
|
||||
- "corrupt return address!");
|
||||
- match_vassert(
|
||||
- "c:\\halo\\SOURCE\\interface\\hud_unit.c",
|
||||
- 0x3C9,
|
||||
- corrupt_index == NONE,
|
||||
- csprintf(temporary, "corrupt stack at %d!", corrupt_index));
|
||||
- }
|
||||
+ match_assert_stack_frame("c:\\halo\\SOURCE\\interface\\hud_unit.c", 0x3C9);
|
||||
|
||||
return;
|
||||
}
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
diff --git a/source/interface/hud_unit.c b/source/interface/hud_unit.c
|
||||
index cfa13729975a4a59a5d4df323152ea62d97b9600..dd0dff95d009a8423aabf18b11d239f084e3c848 100644
|
||||
--- a/source/interface/hud_unit.c
|
||||
+++ b/source/interface/hud_unit.c
|
||||
@@ -3,13 +3,13 @@ HUD_UNIT.C
|
||||
|
||||
symbols in this file:
|
||||
000C6590 0010:
|
||||
- _code_000c6590 (0000)
|
||||
+ _unit_hud_outline_mapper_tick (0000)
|
||||
000C65A0 0010:
|
||||
- _code_000c65a0 (0000)
|
||||
+ _unit_hud_shield_meter_mapper_tick (0000)
|
||||
000C65B0 0010:
|
||||
_unit_hud_shield_meter_mapper_init (0000)
|
||||
000C65C0 0040:
|
||||
- _code_000c65c0 (0000)
|
||||
+ _initialize_hud_state (0000)
|
||||
000C6600 0070:
|
||||
_get_hud_state (0000)
|
||||
000C6670 0040:
|
||||
@@ -59,7 +59,7 @@ symbols in this file:
|
||||
002702D8 001d:
|
||||
??_C@_0BN@NPOPPJAG@old_local_player_index?$CB?$DNNONE?$AA@ (0000)
|
||||
002E4C68 0004:
|
||||
- _data_002e4c68 (0000)
|
||||
+ ?overcharge_count@?1??hud_render_unit_interface@@9@9 (0000)
|
||||
00453AC0 0004:
|
||||
_unit_hud_globals (0000)
|
||||
*/
|
||||
@@ -266,20 +266,22 @@ static struct unit_hud_globals *unit_hud_globals = NULL;
|
||||
extern struct hud_scripted_globals *hud_scripted_globals;
|
||||
extern struct hud_globals_definition *hud_globals;
|
||||
|
||||
-/* ---------- public code */
|
||||
+/* ---------- private code */
|
||||
|
||||
-void code_000c6590(
|
||||
+static void unit_hud_outline_mapper_tick(
|
||||
void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
-void code_000c65a0(
|
||||
+static void unit_hud_shield_meter_mapper_tick(
|
||||
void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
+/* ---------- public code */
|
||||
+
|
||||
void unit_hud_shield_meter_mapper_init(
|
||||
void)
|
||||
{
|
||||
@@ -358,27 +360,8 @@ void hud_initialize_unit_interface_for_new_map(
|
||||
local_player_index < MAXIMUM_NUMBER_OF_LOCAL_PLAYERS;
|
||||
local_player_index++)
|
||||
{
|
||||
- match_assert(
|
||||
- "c:\\halo\\SOURCE\\interface\\hud_unit.c",
|
||||
- 0x106,
|
||||
- local_player_index>=0 &&
|
||||
- local_player_index<MAXIMUM_NUMBER_OF_LOCAL_PLAYERS);
|
||||
- match_assert(
|
||||
- "c:\\halo\\SOURCE\\interface\\hud_unit.c",
|
||||
- 0x107,
|
||||
- unit_hud_globals);
|
||||
-
|
||||
- hud_state = &unit_hud_globals->hud_states[local_player_index];
|
||||
- csmemset(
|
||||
- hud_state->auxilary_flash_time,
|
||||
- NONE,
|
||||
- sizeof(hud_state->auxilary_flash_time));
|
||||
- hud_state->last_body_vitality = -1.0f;
|
||||
- hud_state->last_shield_vitality = -1.0f;
|
||||
- hud_state->last_health_flash_time = NONE;
|
||||
- hud_state->last_motion_sensor_flash_time = NONE;
|
||||
- hud_state->fade_time = -1.0f;
|
||||
- hud_state->last_unit_index = NONE;
|
||||
+ hud_state = get_hud_state(local_player_index);
|
||||
+ initialize_hud_state(hud_state);
|
||||
hud_state->sound_flags = 0;
|
||||
csmemset(
|
||||
hud_state->last_sound_handles,
|
||||
@@ -890,6 +873,9 @@ void hud_render_unit_interface(
|
||||
0x209,
|
||||
player->local_player_index==render.local_player_index);
|
||||
|
||||
+ unit_hud_shield_meter_mapper_tick();
|
||||
+ unit_hud_outline_mapper_tick();
|
||||
+
|
||||
if (player->local_player_index == render.local_player_index &&
|
||||
player->unit_index != NONE)
|
||||
{
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
diff --git a/config/symbols.json b/config/symbols.json
|
||||
index 83830013..b2f762e4 100644
|
||||
--- a/config/symbols.json
|
||||
+++ b/config/symbols.json
|
||||
@@ -3422,11 +3422,11 @@
|
||||
{ "file_offset": 811472, "flags": 32, "name": "_hud_update_nav_point_local_player", "static": true },
|
||||
{ "file_offset": 812032, "flags": 32, "name": "_hud_update_nav_points" },
|
||||
{ "file_offset": 812080, "flags": 32, "name": "_hud_play_sound" },
|
||||
-{ "file_offset": 812432, "flags": 32, "name": "_code_000c6590" },
|
||||
-{ "file_offset": 812448, "flags": 32, "name": "_code_000c65a0" },
|
||||
+{ "file_offset": 812432, "flags": 32, "name": "_unit_hud_outline_mapper_tick", "static": true },
|
||||
+{ "file_offset": 812448, "flags": 32, "name": "_unit_hud_shield_meter_mapper_tick", "static": true },
|
||||
{ "file_offset": 812464, "flags": 32, "name": "_unit_hud_shield_meter_mapper_init" },
|
||||
{ "file_offset": 812480, "flags": 32, "name": "_initialize_hud_state", "static": true },
|
||||
-{ "file_offset": 812544, "flags": 32, "name": "_get_hud_state" },
|
||||
+{ "file_offset": 812544, "flags": 32, "name": "_get_hud_state", "static": true },
|
||||
{ "file_offset": 812656, "flags": 32, "name": "_hud_initialize_unit_interface" },
|
||||
{ "file_offset": 812720, "flags": 32, "name": "_hud_initialize_unit_interface_for_new_map" },
|
||||
{ "file_offset": 812960, "flags": 32, "name": "_hud_dispose_unit_interface_from_old_map" },
|
||||
@@ -3439,7 +3439,7 @@
|
||||
{ "file_offset": 813232, "flags": 32, "name": "_scripted_hud_blink_motion_sensor" },
|
||||
{ "file_offset": 813280, "flags": 32, "name": "_hud_play_unit_sounds" },
|
||||
{ "file_offset": 813824, "flags": 32, "name": "_hud_fix_unit_data" },
|
||||
-{ "file_offset": 813952, "flags": 32, "name": "_hud_update_unit_local_player" },
|
||||
+{ "file_offset": 813952, "flags": 32, "name": "_hud_update_unit_local_player", "static": true },
|
||||
{ "file_offset": 814496, "flags": 32, "name": "_hud_render_damage_indicators" },
|
||||
{ "file_offset": 815184, "flags": 32, "name": "_hud_tick_shield" },
|
||||
{ "file_offset": 815248, "flags": 32, "name": "_hud_update_unit" },
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
diff --git a/config/symbols.json b/config/symbols.json
|
||||
index 8e165740..14bf5f26 100644
|
||||
--- a/config/symbols.json
|
||||
+++ b/config/symbols.json
|
||||
@@ -3422,11 +3422,11 @@
|
||||
{ "file_offset": 811472, "flags": 32, "name": "_hud_update_nav_point_local_player", "static": true },
|
||||
{ "file_offset": 812032, "flags": 32, "name": "_hud_update_nav_points" },
|
||||
{ "file_offset": 812080, "flags": 32, "name": "_hud_play_sound" },
|
||||
-{ "file_offset": 812432, "flags": 32, "name": "_code_000c6590" },
|
||||
-{ "file_offset": 812448, "flags": 32, "name": "_code_000c65a0" },
|
||||
+{ "file_offset": 812432, "flags": 32, "name": "_unit_hud_outline_mapper_tick", "static": true },
|
||||
+{ "file_offset": 812448, "flags": 32, "name": "_unit_hud_shield_meter_mapper_tick", "static": true },
|
||||
{ "file_offset": 812464, "flags": 32, "name": "_unit_hud_shield_meter_mapper_init" },
|
||||
{ "file_offset": 812480, "flags": 32, "name": "_initialize_hud_state", "static": true },
|
||||
-{ "file_offset": 812544, "flags": 32, "name": "_get_hud_state" },
|
||||
+{ "file_offset": 812544, "flags": 32, "name": "_get_hud_state", "static": true },
|
||||
{ "file_offset": 812656, "flags": 32, "name": "_hud_initialize_unit_interface" },
|
||||
{ "file_offset": 812720, "flags": 32, "name": "_hud_initialize_unit_interface_for_new_map" },
|
||||
{ "file_offset": 812960, "flags": 32, "name": "_hud_dispose_unit_interface_from_old_map" },
|
||||
@@ -3439,7 +3439,7 @@
|
||||
{ "file_offset": 813232, "flags": 32, "name": "_scripted_hud_blink_motion_sensor" },
|
||||
{ "file_offset": 813280, "flags": 32, "name": "_hud_play_unit_sounds" },
|
||||
{ "file_offset": 813824, "flags": 32, "name": "_hud_fix_unit_data" },
|
||||
-{ "file_offset": 813952, "flags": 32, "name": "_hud_update_unit_local_player" },
|
||||
+{ "file_offset": 813952, "flags": 32, "name": "_hud_update_unit_local_player", "static": true },
|
||||
{ "file_offset": 814496, "flags": 32, "name": "_hud_render_damage_indicators" },
|
||||
{ "file_offset": 815184, "flags": 32, "name": "_hud_tick_shield" },
|
||||
{ "file_offset": 815248, "flags": 32, "name": "_hud_update_unit" },
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
diff --git a/config/config.json b/config/config.json
|
||||
index e7b839a2..be7d86c8 100644
|
||||
--- a/config/config.json
|
||||
+++ b/config/config.json
|
||||
@@ -641,7 +641,7 @@
|
||||
{ "name": "source/interface/unit_hud_interface_definition.c", "index": 266, "status": "Matching" },
|
||||
{ "name": "source/interface/motion_sensor.c", "index": 267, "status": "NonMatching" },
|
||||
{ "name": "source/interface/hud_weapon.c", "index": 268, "status": "NonMatching" },
|
||||
- { "name": "source/interface/hud_unit.c", "index": 269, "status": "NonMatching" },
|
||||
+ { "name": "source/interface/hud_unit.c", "index": 269, "status": "Matching" },
|
||||
{ "name": "source/interface/hud_sounds.c", "index": 270, "status": "Matching" },
|
||||
{ "name": "source/interface/hud_nav_points.c", "index": 271, "status": "NonMatching" },
|
||||
{ "name": "source/interface/hud_messaging_definitions.c", "index": 272, "status": "Matching" },
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
diff --git a/config/object_admission_rejections.json b/config/object_admission_rejections.json
|
||||
index a9191071..8b6b428f 100644
|
||||
--- a/config/object_admission_rejections.json
|
||||
+++ b/config/object_admission_rejections.json
|
||||
@@ -33,14 +33,6 @@
|
||||
"evidence": "docs/object_matching_logs/hud_draw_obj_two_exact_leaves_integration_20260904.md#complete-owner-boundary",
|
||||
"reopen": "Require authentic source topology or an ordinary base/base link with an authenticated compatible canonical selected helper before clearing this veto. Do not force inline, manually expand math, alter target/COMDAT metadata, invent a discard pass, or credit candidate-only helper bytes. All remaining HUD Draw functions/data/linkage/source checks must independently pass before whole-object Matching."
|
||||
},
|
||||
- {
|
||||
- "unit": "source/interface/hud_unit",
|
||||
- "class": "candidate-only-comdat-owner",
|
||||
- "symbol": "_fast_ftol",
|
||||
- "reason": "The new source-authentic renderer naturally emits an unreferenced select-any32-byte fast_ftol copy absent from January HUD Unit. Its body equals January's selected Actor Combat helper, but that selected owner is no-duplicates and the prior ordinary XDK link test rejects the duplicate. Genuine initializer/data credit and the honest renderer park remain valid; identical helper bytes do not prove whole-object ownership.",
|
||||
- "evidence": "docs/object_matching_logs/hud_unit_obj_renderer_integration_20260904.md#honest-residual-and-complete-owner-boundary",
|
||||
- "reopen": "Remove only after authentic source topology preserves the January helper schedule without extra emission, or an ordinary base/base link proves a compatible authenticated canonical selected owner can coalesce the copy. Do not force inline, manually expand the helper, alter comparator/selection metadata, invent a discard pass, or count another object's selected bytes. The renderer must independently become strict and all other source/data/linkage checks must pass before Matching admission."
|
||||
- },
|
||||
{
|
||||
"unit": "source/models/models",
|
||||
"class": "bss-symbol-layout-mismatch",
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
diff --git a/source/interface/hud_draw.h b/source/interface/hud_draw.h
|
||||
index 4c0505cd..f041b019 100644
|
||||
--- a/source/interface/hud_draw.h
|
||||
+++ b/source/interface/hud_draw.h
|
||||
@@ -11,6 +11,14 @@ Narrow cross-translation-unit interface owned by HUD_DRAW.C.
|
||||
#include "math/integer_math.h"
|
||||
#include "math/real_math.h"
|
||||
|
||||
+/* ---------- constants */
|
||||
+
|
||||
+enum
|
||||
+{
|
||||
+ STACK_BUFFER_LENGTH = 0x80,
|
||||
+ STACK_BUFFER_FILL = 0x62626262,
|
||||
+};
|
||||
+
|
||||
enum hud_draw_flags
|
||||
{
|
||||
_hud_draw_flashing_bit = 0,
|
||||
@@ -20,6 +28,22 @@ enum hud_draw_flags
|
||||
NUMBER_OF_HUD_DRAW_FLAGS
|
||||
};
|
||||
|
||||
+/* ---------- macros */
|
||||
+
|
||||
+/* The stack sentinel: a guarded function starts with
|
||||
+ long return_eip = get_return_eip();
|
||||
+ long stack_buffer[STACK_BUFFER_LENGTH];
|
||||
+ csmemset(stack_buffer, 0x62, sizeof(stack_buffer));
|
||||
+and ends with this check of both its return address and its fill pattern. */
|
||||
+#define match_assert_stack_frame(file, line) \
|
||||
+{ \
|
||||
+ short corrupt_index = check_stack_buffer(stack_buffer); \
|
||||
+ match_vassert(file, line, return_eip==get_return_eip(), "corrupt return address!"); \
|
||||
+ match_vassert(file, line, corrupt_index==NONE, csprintf(temporary, "corrupt stack at %d!", corrupt_index)); \
|
||||
+}
|
||||
+
|
||||
+/* ---------- structures */
|
||||
+
|
||||
struct bitmap_data;
|
||||
struct hud_absolute_placement_definition;
|
||||
struct hud_color_definition;
|
||||
@@ -29,6 +53,8 @@ struct number_hud_element_definition;
|
||||
struct static_hud_element_definition;
|
||||
struct weapon_hud_overlay_definition;
|
||||
|
||||
+/* ---------- prototypes/HUD_DRAW.C */
|
||||
+
|
||||
long get_return_eip(
|
||||
void);
|
||||
real hud_globals_get_scale(
|
||||
@@ -110,4 +136,20 @@ void hud_draw_numbers(
|
||||
long flash_reference_time,
|
||||
real override_scale);
|
||||
|
||||
+/* ---------- public code */
|
||||
+
|
||||
+__inline short check_stack_buffer(
|
||||
+ long *buffer)
|
||||
+{
|
||||
+ short index;
|
||||
+
|
||||
+ for (index = STACK_BUFFER_LENGTH-1; index>=0; index--)
|
||||
+ {
|
||||
+ if (buffer[index]!=STACK_BUFFER_FILL)
|
||||
+ return index;
|
||||
+ }
|
||||
+
|
||||
+ return NONE;
|
||||
+}
|
||||
+
|
||||
#endif /* __HUD_DRAW_H */
|
||||
+178
@@ -0,0 +1,178 @@
|
||||
diff --git a/source/interface/hud_draw.c b/source/interface/hud_draw.c
|
||||
index b79e256b..40238431 100644
|
||||
--- a/source/interface/hud_draw.c
|
||||
+++ b/source/interface/hud_draw.c
|
||||
@@ -107,12 +107,6 @@ symbols in this file:
|
||||
|
||||
/* ---------- constants */
|
||||
|
||||
-enum
|
||||
-{
|
||||
- STACK_BUFFER_LENGTH = 0x80,
|
||||
- STACK_BUFFER_FILL = 0x62626262,
|
||||
-};
|
||||
-
|
||||
enum
|
||||
{
|
||||
_hud_dont_scale_offset_bit = 0,
|
||||
@@ -231,13 +225,6 @@ enum
|
||||
|
||||
/* ---------- macros */
|
||||
|
||||
-#define hud_draw_stack_buffer_check(line) \
|
||||
-{ \
|
||||
- short corrupt_index = check_stack_buffer(stack_buffer); \
|
||||
- match_vassert("c:\\halo\\SOURCE\\interface\\hud_draw.c", line, return_eip==get_return_eip(), "corrupt return address!"); \
|
||||
- match_vassert("c:\\halo\\SOURCE\\interface\\hud_draw.c", line, corrupt_index==NONE, csprintf(temporary, "corrupt stack at %d!", corrupt_index)); \
|
||||
-}
|
||||
-
|
||||
#define hud_number_definition_get(index) \
|
||||
((struct hud_number_definition *)tag_get(hud_number_group_tag, (index)))
|
||||
|
||||
@@ -435,20 +422,6 @@ __declspec(naked) long get_return_eip(
|
||||
}
|
||||
}
|
||||
|
||||
-short check_stack_buffer(
|
||||
- long *buffer)
|
||||
-{
|
||||
- short index;
|
||||
-
|
||||
- for (index = STACK_BUFFER_LENGTH-1; index>=0; index--)
|
||||
- {
|
||||
- if (buffer[index]!=STACK_BUFFER_FILL)
|
||||
- return index;
|
||||
- }
|
||||
-
|
||||
- return NONE;
|
||||
-}
|
||||
-
|
||||
real hud_globals_get_scale(
|
||||
boolean in_multiplayer)
|
||||
{
|
||||
@@ -505,7 +478,7 @@ void hud_retrieve_bitmap_and_bounding_rect(
|
||||
else
|
||||
*clip = NULL;
|
||||
|
||||
- hud_draw_stack_buffer_check(228);
|
||||
+ match_assert_stack_frame("c:\\halo\\SOURCE\\interface\\hud_draw.c", 228);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -561,7 +534,7 @@ static boolean hud_draw_multitexture_overlay_get_current_weapon_definition(
|
||||
result = TRUE;
|
||||
}
|
||||
|
||||
- hud_draw_stack_buffer_check(1032);
|
||||
+ match_assert_stack_frame("c:\\halo\\SOURCE\\interface\\hud_draw.c", 1032);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -922,7 +895,7 @@ static void hud_draw_multitexture_overlay(
|
||||
|
||||
rasterizer_psuedo_dynamic_screen_quad_draw(¶meters, vertices);
|
||||
|
||||
- hud_draw_stack_buffer_check(1372);
|
||||
+ match_assert_stack_frame("c:\\halo\\SOURCE\\interface\\hud_draw.c", 1372);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1059,7 +1032,7 @@ void hud_calculate_point(
|
||||
result->x = (short)fast_ftol(point.x);
|
||||
result->y = (short)fast_ftol(point.y);
|
||||
|
||||
- hud_draw_stack_buffer_check(181);
|
||||
+ match_assert_stack_frame("c:\\halo\\SOURCE\\interface\\hud_draw.c", 181);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1168,7 +1141,7 @@ pixel32 get_flash_color(
|
||||
result = base_color;
|
||||
}
|
||||
|
||||
- hud_draw_stack_buffer_check(311);
|
||||
+ match_assert_stack_frame("c:\\halo\\SOURCE\\interface\\hud_draw.c", 311);
|
||||
|
||||
return real_argb_color_to_pixel32(&result);
|
||||
}
|
||||
@@ -1260,7 +1233,7 @@ void hud_draw_weapon_overlays(
|
||||
}
|
||||
}
|
||||
|
||||
- hud_draw_stack_buffer_check(748);
|
||||
+ match_assert_stack_frame("c:\\halo\\SOURCE\\interface\\hud_draw.c", 748);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1407,7 +1380,7 @@ void hud_draw_static_element(
|
||||
}
|
||||
}
|
||||
|
||||
- hud_draw_stack_buffer_check(685);
|
||||
+ match_assert_stack_frame("c:\\halo\\SOURCE\\interface\\hud_draw.c", 685);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1464,7 +1437,7 @@ static void hud_draw_bitmap_internal(
|
||||
|
||||
rasterizer_psuedo_dynamic_screen_quad_draw(¶meters, vertices);
|
||||
|
||||
- hud_draw_stack_buffer_check(985);
|
||||
+ match_assert_stack_frame("c:\\halo\\SOURCE\\interface\\hud_draw.c", 985);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1536,7 +1509,7 @@ static void hud_draw_bitmap_with_meter(
|
||||
theta,
|
||||
color);
|
||||
|
||||
- hud_draw_stack_buffer_check(814);
|
||||
+ match_assert_stack_frame("c:\\halo\\SOURCE\\interface\\hud_draw.c", 814);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1574,7 +1547,7 @@ static real_rectangle2d const *get_sprite_clip_rect(
|
||||
}
|
||||
}
|
||||
|
||||
- hud_draw_stack_buffer_check(100);
|
||||
+ match_assert_stack_frame("c:\\halo\\SOURCE\\interface\\hud_draw.c", 100);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1638,7 +1611,7 @@ static void hud_calculate_bitmap_bounds(
|
||||
break;
|
||||
}
|
||||
|
||||
- hud_draw_stack_buffer_check(907);
|
||||
+ match_assert_stack_frame("c:\\halo\\SOURCE\\interface\\hud_draw.c", 907);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1696,7 +1669,7 @@ void hud_draw_bitmap_direct(
|
||||
theta,
|
||||
color);
|
||||
|
||||
- hud_draw_stack_buffer_check(856);
|
||||
+ match_assert_stack_frame("c:\\halo\\SOURCE\\interface\\hud_draw.c", 856);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1816,7 +1789,7 @@ void hud_draw_meter(
|
||||
FALSE);
|
||||
}
|
||||
|
||||
- hud_draw_stack_buffer_check(428);
|
||||
+ match_assert_stack_frame("c:\\halo\\SOURCE\\interface\\hud_draw.c", 428);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -2108,7 +2081,7 @@ void hud_draw_numbers(
|
||||
}
|
||||
}
|
||||
|
||||
- hud_draw_stack_buffer_check(602);
|
||||
+ match_assert_stack_frame("c:\\halo\\SOURCE\\interface\\hud_draw.c", 602);
|
||||
|
||||
return;
|
||||
}
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
diff --git a/source/interface/hud_unit.c b/source/interface/hud_unit.c
|
||||
index cfa13729..73d9957f 100644
|
||||
--- a/source/interface/hud_unit.c
|
||||
+++ b/source/interface/hud_unit.c
|
||||
@@ -113,12 +113,6 @@ enum hud_damage_indicator_direction
|
||||
NUMBER_OF_HUD_DAMAGE_INDICATOR_DIRECTIONS
|
||||
};
|
||||
|
||||
-enum
|
||||
-{
|
||||
- STACK_BUFFER_LENGTH = 0x80,
|
||||
- STACK_BUFFER_FILL = 0x62626262,
|
||||
-};
|
||||
-
|
||||
/* ---------- macros */
|
||||
|
||||
/* ---------- structures */
|
||||
@@ -672,34 +666,7 @@ update_finished:
|
||||
}
|
||||
}
|
||||
|
||||
- {
|
||||
- short corrupt_index;
|
||||
- short buffer_index;
|
||||
-
|
||||
- for (buffer_index = STACK_BUFFER_LENGTH - 1; buffer_index >= 0; buffer_index--)
|
||||
- {
|
||||
- if (stack_buffer[buffer_index] != STACK_BUFFER_FILL)
|
||||
- goto corrupt_stack_found;
|
||||
- }
|
||||
-
|
||||
- corrupt_index = NONE;
|
||||
- goto stack_buffer_checked;
|
||||
-
|
||||
-corrupt_stack_found:
|
||||
- corrupt_index = buffer_index;
|
||||
-
|
||||
-stack_buffer_checked:
|
||||
- match_vassert(
|
||||
- "c:\\halo\\SOURCE\\interface\\hud_unit.c",
|
||||
- 0x201,
|
||||
- return_eip == get_return_eip(),
|
||||
- "corrupt return address!");
|
||||
- match_vassert(
|
||||
- "c:\\halo\\SOURCE\\interface\\hud_unit.c",
|
||||
- 0x201,
|
||||
- corrupt_index == NONE,
|
||||
- csprintf(temporary, "corrupt stack at %d!", corrupt_index));
|
||||
- }
|
||||
+ match_assert_stack_frame("c:\\halo\\SOURCE\\interface\\hud_unit.c", 0x201);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1439,34 +1406,7 @@ void hud_render_unit_interface(
|
||||
}
|
||||
}
|
||||
|
||||
- {
|
||||
- short corrupt_index;
|
||||
- short buffer_index;
|
||||
-
|
||||
- for (buffer_index = STACK_BUFFER_LENGTH - 1; buffer_index >= 0; buffer_index--)
|
||||
- {
|
||||
- if (stack_buffer[buffer_index] != STACK_BUFFER_FILL)
|
||||
- goto corrupt_stack_found;
|
||||
- }
|
||||
-
|
||||
- corrupt_index = NONE;
|
||||
- goto stack_buffer_checked;
|
||||
-
|
||||
-corrupt_stack_found:
|
||||
- corrupt_index = buffer_index;
|
||||
-
|
||||
-stack_buffer_checked:
|
||||
- match_vassert(
|
||||
- "c:\\halo\\SOURCE\\interface\\hud_unit.c",
|
||||
- 0x3C9,
|
||||
- return_eip == get_return_eip(),
|
||||
- "corrupt return address!");
|
||||
- match_vassert(
|
||||
- "c:\\halo\\SOURCE\\interface\\hud_unit.c",
|
||||
- 0x3C9,
|
||||
- corrupt_index == NONE,
|
||||
- csprintf(temporary, "corrupt stack at %d!", corrupt_index));
|
||||
- }
|
||||
+ match_assert_stack_frame("c:\\halo\\SOURCE\\interface\\hud_unit.c", 0x3C9);
|
||||
|
||||
return;
|
||||
}
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
diff --git a/source/interface/hud_nav_points.c b/source/interface/hud_nav_points.c
|
||||
index 36b392c3..700a6e03 100644
|
||||
--- a/source/interface/hud_nav_points.c
|
||||
+++ b/source/interface/hud_nav_points.c
|
||||
@@ -776,7 +776,7 @@ void custom_render_nav_point(
|
||||
short waypoint_type)
|
||||
{
|
||||
long return_eip = get_return_eip();
|
||||
- long stack_buffer[0x80];
|
||||
+ long stack_buffer[STACK_BUFFER_LENGTH];
|
||||
struct hud_waypoint_arrow *arrow;
|
||||
real_point3d view_point;
|
||||
real distance;
|
||||
@@ -986,37 +986,7 @@ void custom_render_nav_point(
|
||||
}
|
||||
}
|
||||
|
||||
- {
|
||||
- short corrupt_index;
|
||||
- short buffer_index;
|
||||
-
|
||||
- for (buffer_index = 0x7F; buffer_index>=0; buffer_index--)
|
||||
- {
|
||||
- if (stack_buffer[buffer_index]!=0x62626262)
|
||||
- {
|
||||
- goto corrupt_stack_found_custom_render_nav_point;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- corrupt_index = NONE;
|
||||
- goto stack_buffer_checked_custom_render_nav_point;
|
||||
-
|
||||
-corrupt_stack_found_custom_render_nav_point:
|
||||
- corrupt_index = buffer_index;
|
||||
-
|
||||
-stack_buffer_checked_custom_render_nav_point:
|
||||
-
|
||||
- match_vassert(
|
||||
- "c:\\halo\\SOURCE\\interface\\hud_nav_points.c",
|
||||
- 675,
|
||||
- return_eip==get_return_eip(),
|
||||
- "corrupt return address!");
|
||||
- match_vassert(
|
||||
- "c:\\halo\\SOURCE\\interface\\hud_nav_points.c",
|
||||
- 675,
|
||||
- corrupt_index==NONE,
|
||||
- csprintf(temporary, "corrupt stack at %d!", corrupt_index));
|
||||
- }
|
||||
+ match_assert_stack_frame("c:\\halo\\SOURCE\\interface\\hud_nav_points.c", 675);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1100,7 +1070,7 @@ static void hud_update_nav_point_local_player(
|
||||
short local_player_index)
|
||||
{
|
||||
long return_eip = get_return_eip();
|
||||
- long stack_buffer[0x80];
|
||||
+ long stack_buffer[STACK_BUFFER_LENGTH];
|
||||
struct hud_nav_point_player_datum *datum;
|
||||
long unit_index;
|
||||
short nav_point_index;
|
||||
@@ -1187,37 +1157,7 @@ static void hud_update_nav_point_local_player(
|
||||
}
|
||||
}
|
||||
|
||||
- {
|
||||
- short corrupt_index;
|
||||
- short buffer_index;
|
||||
-
|
||||
- for (buffer_index = 0x7F; buffer_index>=0; buffer_index--)
|
||||
- {
|
||||
- if (stack_buffer[buffer_index]!=0x62626262)
|
||||
- {
|
||||
- goto corrupt_stack_found;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- corrupt_index = NONE;
|
||||
- goto stack_buffer_checked;
|
||||
-
|
||||
-corrupt_stack_found:
|
||||
- corrupt_index = buffer_index;
|
||||
-
|
||||
-stack_buffer_checked:
|
||||
-
|
||||
- match_vassert(
|
||||
- "c:\\halo\\SOURCE\\interface\\hud_nav_points.c",
|
||||
- 496,
|
||||
- return_eip==get_return_eip(),
|
||||
- "corrupt return address!");
|
||||
- match_vassert(
|
||||
- "c:\\halo\\SOURCE\\interface\\hud_nav_points.c",
|
||||
- 496,
|
||||
- corrupt_index==NONE,
|
||||
- csprintf(temporary, "corrupt stack at %d!", corrupt_index));
|
||||
- }
|
||||
+ match_assert_stack_frame("c:\\halo\\SOURCE\\interface\\hud_nav_points.c", 496);
|
||||
|
||||
return;
|
||||
}
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
diff --git a/source/interface/hud_weapon.c b/source/interface/hud_weapon.c
|
||||
index 6e6a13f0..80b563a8 100644
|
||||
--- a/source/interface/hud_weapon.c
|
||||
+++ b/source/interface/hud_weapon.c
|
||||
@@ -93,8 +93,6 @@ enum
|
||||
MAXIMUM_WEAPON_HUD_DEFINITION_DEPTH = 16,
|
||||
NUMBER_OF_WEAPON_HUD_FLASH_REFERENCES = 8,
|
||||
NUMBER_OF_WEAPON_HUD_CROSSHAIR_STATES = 19,
|
||||
- HUD_WEAPON_STACK_BUFFER_LENGTH = 0x80,
|
||||
- HUD_WEAPON_STACK_BUFFER_FILL = 0x62626262,
|
||||
};
|
||||
|
||||
enum weapon_crosshair_type
|
||||
@@ -179,24 +177,6 @@ enum
|
||||
|
||||
/* ---------- macros */
|
||||
|
||||
-#define hud_weapon_stack_buffer_check(line) \
|
||||
-{ \
|
||||
- short corrupt_index; \
|
||||
- short buffer_index; \
|
||||
- for (buffer_index = HUD_WEAPON_STACK_BUFFER_LENGTH - 1; buffer_index >= 0; buffer_index--) \
|
||||
- { \
|
||||
- if (stack_buffer[buffer_index] != HUD_WEAPON_STACK_BUFFER_FILL) \
|
||||
- goto corrupt_stack_found; \
|
||||
- } \
|
||||
- corrupt_index = NONE; \
|
||||
- goto stack_buffer_checked; \
|
||||
-corrupt_stack_found: \
|
||||
- corrupt_index = buffer_index; \
|
||||
-stack_buffer_checked: \
|
||||
- match_vassert("c:\\halo\\SOURCE\\interface\\hud_weapon.c", line, return_eip == get_return_eip(), "corrupt return address!"); \
|
||||
- match_vassert("c:\\halo\\SOURCE\\interface\\hud_weapon.c", line, corrupt_index == NONE, csprintf(temporary, "corrupt stack at %d!", corrupt_index)); \
|
||||
-}
|
||||
-
|
||||
#define grenade_hud_interface_definition_get(index) \
|
||||
((struct grenade_hud_interface_definition *)tag_get( \
|
||||
GRENADE_HUD_INTERFACE_TAG, \
|
||||
@@ -583,7 +563,7 @@ static void render_grenade_hud(
|
||||
long unit_index)
|
||||
{
|
||||
long return_eip = get_return_eip();
|
||||
- long stack_buffer[HUD_WEAPON_STACK_BUFFER_LENGTH];
|
||||
+ long stack_buffer[STACK_BUFFER_LENGTH];
|
||||
struct unit_datum *unit;
|
||||
long weapon_index;
|
||||
long parent_index;
|
||||
@@ -711,7 +691,7 @@ static void render_grenade_hud(
|
||||
}
|
||||
|
||||
finished:
|
||||
- hud_weapon_stack_buffer_check(0x3A2);
|
||||
+ match_assert_stack_frame("c:\\halo\\SOURCE\\interface\\hud_weapon.c", 0x3A2);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -722,7 +702,7 @@ static void hud_update_weapon_local_player(
|
||||
struct weapon_interface_state *weapon_state)
|
||||
{
|
||||
long return_eip = get_return_eip();
|
||||
- long stack_buffer[HUD_WEAPON_STACK_BUFFER_LENGTH];
|
||||
+ long stack_buffer[STACK_BUFFER_LENGTH];
|
||||
struct player_datum *player;
|
||||
struct unit_datum *unit;
|
||||
struct crosshair_hud_state *crosshair;
|
||||
@@ -1008,7 +988,7 @@ static void hud_update_weapon_local_player(
|
||||
}
|
||||
|
||||
finished:
|
||||
- hud_weapon_stack_buffer_check(0x19E);
|
||||
+ match_assert_stack_frame("c:\\halo\\SOURCE\\interface\\hud_weapon.c", 0x19E);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1019,7 +999,7 @@ static void crosshairs_draw(
|
||||
struct weapon_interface_state *weapon_state)
|
||||
{
|
||||
long return_eip = get_return_eip();
|
||||
- long stack_buffer[HUD_WEAPON_STACK_BUFFER_LENGTH];
|
||||
+ long stack_buffer[STACK_BUFFER_LENGTH];
|
||||
boolean firing_active = FALSE;
|
||||
|
||||
csmemset(
|
||||
@@ -1327,7 +1307,7 @@ static void crosshairs_draw(
|
||||
}
|
||||
}
|
||||
|
||||
- hud_weapon_stack_buffer_check(0x4E2);
|
||||
+ match_assert_stack_frame("c:\\halo\\SOURCE\\interface\\hud_weapon.c", 0x4E2);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1341,7 +1321,7 @@ static void render_weapon_hud(
|
||||
short const *new_numbers)
|
||||
{
|
||||
long return_eip = get_return_eip();
|
||||
- long stack_buffer[HUD_WEAPON_STACK_BUFFER_LENGTH];
|
||||
+ long stack_buffer[STACK_BUFFER_LENGTH];
|
||||
struct weapon_hud_interface_definition *definition;
|
||||
struct weapon_hud_state *hud_state;
|
||||
short state_flags[NUMBER_OF_WEAPON_HUD_FLASH_REFERENCES] = { 0 };
|
||||
@@ -1827,7 +1807,7 @@ static void render_weapon_hud(
|
||||
}
|
||||
}
|
||||
|
||||
- hud_weapon_stack_buffer_check(0x308);
|
||||
+ match_assert_stack_frame("c:\\halo\\SOURCE\\interface\\hud_weapon.c", 0x308);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1856,7 +1836,7 @@ void hud_update_weapon(
|
||||
void)
|
||||
{
|
||||
long return_eip = get_return_eip();
|
||||
- long stack_buffer[HUD_WEAPON_STACK_BUFFER_LENGTH];
|
||||
+ long stack_buffer[STACK_BUFFER_LENGTH];
|
||||
short local_player_index;
|
||||
|
||||
csmemset(
|
||||
@@ -1944,7 +1924,7 @@ void hud_update_weapon(
|
||||
}
|
||||
}
|
||||
|
||||
- hud_weapon_stack_buffer_check(0xD4);
|
||||
+ match_assert_stack_frame("c:\\halo\\SOURCE\\interface\\hud_weapon.c", 0xD4);
|
||||
|
||||
return;
|
||||
}
|
||||
+139
@@ -0,0 +1,139 @@
|
||||
diff --git a/source/interface/motion_sensor.c b/source/interface/motion_sensor.c
|
||||
index 76b25379..70c4977b 100644
|
||||
--- a/source/interface/motion_sensor.c
|
||||
+++ b/source/interface/motion_sensor.c
|
||||
@@ -309,7 +309,7 @@ static void motion_sensor_update(
|
||||
void)
|
||||
{
|
||||
long return_eip = get_return_eip();
|
||||
- long stack_buffer[0x80];
|
||||
+ long stack_buffer[STACK_BUFFER_LENGTH];
|
||||
long current_time;
|
||||
short active_sensor_index;
|
||||
|
||||
@@ -471,34 +471,7 @@ static void motion_sensor_update(
|
||||
}
|
||||
}
|
||||
|
||||
- {
|
||||
- short corrupt_index;
|
||||
- short buffer_index;
|
||||
-
|
||||
- for (buffer_index = 0x7F; buffer_index >= 0; buffer_index--)
|
||||
- {
|
||||
- if (stack_buffer[buffer_index] != 0x62626262)
|
||||
- goto corrupt_stack_found_motion_sensor_update;
|
||||
- }
|
||||
-
|
||||
- corrupt_index = NONE;
|
||||
- goto stack_buffer_checked_motion_sensor_update;
|
||||
-
|
||||
-corrupt_stack_found_motion_sensor_update:
|
||||
- corrupt_index = buffer_index;
|
||||
-
|
||||
-stack_buffer_checked_motion_sensor_update:
|
||||
- match_vassert(
|
||||
- "c:\\halo\\SOURCE\\interface\\motion_sensor.c",
|
||||
- 642,
|
||||
- return_eip == get_return_eip(),
|
||||
- "corrupt return address!");
|
||||
- match_vassert(
|
||||
- "c:\\halo\\SOURCE\\interface\\motion_sensor.c",
|
||||
- 642,
|
||||
- corrupt_index == NONE,
|
||||
- csprintf(temporary, "corrupt stack at %d!", corrupt_index));
|
||||
- }
|
||||
+ match_assert_stack_frame("c:\\halo\\SOURCE\\interface\\motion_sensor.c", 642);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -507,7 +480,7 @@ static void update_motion_sensor(
|
||||
short local_player_index)
|
||||
{
|
||||
long return_eip = get_return_eip();
|
||||
- long stack_buffer[0x80];
|
||||
+ long stack_buffer[STACK_BUFFER_LENGTH];
|
||||
struct motion_sensor_player *player;
|
||||
short active_sensor_index;
|
||||
long player_index;
|
||||
@@ -613,34 +586,7 @@ static void update_motion_sensor(
|
||||
sensor->custom_blip_count -= (byte)out_of_range_count;
|
||||
|
||||
update_motion_sensor_done:
|
||||
- {
|
||||
- short corrupt_index;
|
||||
- short buffer_index;
|
||||
-
|
||||
- for (buffer_index = 0x7F; buffer_index >= 0; buffer_index--)
|
||||
- {
|
||||
- if (stack_buffer[buffer_index] != 0x62626262)
|
||||
- goto corrupt_stack_found_update_motion_sensor;
|
||||
- }
|
||||
-
|
||||
- corrupt_index = NONE;
|
||||
- goto stack_buffer_checked_update_motion_sensor;
|
||||
-
|
||||
-corrupt_stack_found_update_motion_sensor:
|
||||
- corrupt_index = buffer_index;
|
||||
-
|
||||
-stack_buffer_checked_update_motion_sensor:
|
||||
- match_vassert(
|
||||
- "c:\\halo\\SOURCE\\interface\\motion_sensor.c",
|
||||
- 756,
|
||||
- return_eip == get_return_eip(),
|
||||
- "corrupt return address!");
|
||||
- match_vassert(
|
||||
- "c:\\halo\\SOURCE\\interface\\motion_sensor.c",
|
||||
- 756,
|
||||
- corrupt_index == NONE,
|
||||
- csprintf(temporary, "corrupt stack at %d!", corrupt_index));
|
||||
- }
|
||||
+ match_assert_stack_frame("c:\\halo\\SOURCE\\interface\\motion_sensor.c", 756);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -651,7 +597,7 @@ static void render_motion_sensor(
|
||||
point2d const *reference)
|
||||
{
|
||||
long return_eip = get_return_eip();
|
||||
- long stack_buffer[0x80];
|
||||
+ long stack_buffer[STACK_BUFFER_LENGTH];
|
||||
director_perspective perspective;
|
||||
struct motion_sensor_player *player;
|
||||
real relative_scale;
|
||||
@@ -743,34 +689,7 @@ static void render_motion_sensor(
|
||||
rasterizer_hud_motion_sensor_blip_end(¢er_point, sweep_theta);
|
||||
|
||||
render_motion_sensor_done:
|
||||
- {
|
||||
- short corrupt_index;
|
||||
- short buffer_index;
|
||||
-
|
||||
- for (buffer_index = 0x7F; buffer_index >= 0; buffer_index--)
|
||||
- {
|
||||
- if (stack_buffer[buffer_index] != 0x62626262)
|
||||
- goto corrupt_stack_found_render_motion_sensor;
|
||||
- }
|
||||
-
|
||||
- corrupt_index = NONE;
|
||||
- goto stack_buffer_checked_render_motion_sensor;
|
||||
-
|
||||
-corrupt_stack_found_render_motion_sensor:
|
||||
- corrupt_index = buffer_index;
|
||||
-
|
||||
-stack_buffer_checked_render_motion_sensor:
|
||||
- match_vassert(
|
||||
- "c:\\halo\\SOURCE\\interface\\motion_sensor.c",
|
||||
- 830,
|
||||
- return_eip == get_return_eip(),
|
||||
- "corrupt return address!");
|
||||
- match_vassert(
|
||||
- "c:\\halo\\SOURCE\\interface\\motion_sensor.c",
|
||||
- 830,
|
||||
- corrupt_index == NONE,
|
||||
- csprintf(temporary, "corrupt stack at %d!", corrupt_index));
|
||||
- }
|
||||
+ match_assert_stack_frame("c:\\halo\\SOURCE\\interface\\motion_sensor.c", 830);
|
||||
|
||||
return;
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
diff --git a/source/rasterizer/xbox/rasterizer_xbox_models.c b/source/rasterizer/xbox/rasterizer_xbox_models.c
|
||||
index 86d2eb5a..ef1545e6 100644
|
||||
--- a/source/rasterizer/xbox/rasterizer_xbox_models.c
|
||||
+++ b/source/rasterizer/xbox/rasterizer_xbox_models.c
|
||||
@@ -102,7 +102,6 @@ symbols in this file:
|
||||
#include "cseries/errors.h"
|
||||
#define REAL_MATH_EXTERNAL_POINT_FROM_LINE3D
|
||||
#include "bitmaps/bitmap_color_conversion.h"
|
||||
-#include "interface/hud_draw.h"
|
||||
#include "math/periodic_functions.h"
|
||||
#include "math/real_math.h"
|
||||
#undef REAL_MATH_EXTERNAL_POINT_FROM_LINE3D
|
||||
@@ -1,66 +1,177 @@
|
||||
diff --git a/source/interface/hud_unit.c "b/C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\hud_unit_audit\\cand.c"
|
||||
index cfa13729..c41e946d 100644
|
||||
index 1ff72603..c41e946d 100644
|
||||
--- a/source/interface/hud_unit.c
|
||||
+++ "b/C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\hud_unit_audit\\cand.c"
|
||||
@@ -3,13 +3,13 @@ HUD_UNIT.C
|
||||
@@ -113,6 +113,12 @@ enum hud_damage_indicator_direction
|
||||
NUMBER_OF_HUD_DAMAGE_INDICATOR_DIRECTIONS
|
||||
};
|
||||
|
||||
symbols in this file:
|
||||
000C6590 0010:
|
||||
- _code_000c6590 (0000)
|
||||
+ _unit_hud_outline_mapper_tick (0000)
|
||||
000C65A0 0010:
|
||||
- _code_000c65a0 (0000)
|
||||
+ _unit_hud_shield_meter_mapper_tick (0000)
|
||||
000C65B0 0010:
|
||||
_unit_hud_shield_meter_mapper_init (0000)
|
||||
000C65C0 0040:
|
||||
- _code_000c65c0 (0000)
|
||||
+ _initialize_hud_state (0000)
|
||||
000C6600 0070:
|
||||
_get_hud_state (0000)
|
||||
000C6670 0040:
|
||||
@@ -59,7 +59,7 @@ symbols in this file:
|
||||
002702D8 001d:
|
||||
??_C@_0BN@NPOPPJAG@old_local_player_index?$CB?$DNNONE?$AA@ (0000)
|
||||
002E4C68 0004:
|
||||
- _data_002e4c68 (0000)
|
||||
+ ?overcharge_count@?1??hud_render_unit_interface@@9@9 (0000)
|
||||
00453AC0 0004:
|
||||
_unit_hud_globals (0000)
|
||||
*/
|
||||
@@ -266,20 +266,22 @@ static struct unit_hud_globals *unit_hud_globals = NULL;
|
||||
extern struct hud_scripted_globals *hud_scripted_globals;
|
||||
extern struct hud_globals_definition *hud_globals;
|
||||
|
||||
-/* ---------- public code */
|
||||
+/* ---------- private code */
|
||||
|
||||
-void code_000c6590(
|
||||
+static void unit_hud_outline_mapper_tick(
|
||||
void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
-void code_000c65a0(
|
||||
+static void unit_hud_shield_meter_mapper_tick(
|
||||
void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
+/* ---------- public code */
|
||||
+enum
|
||||
+{
|
||||
+ STACK_BUFFER_LENGTH = 0x80,
|
||||
+ STACK_BUFFER_FILL = 0x62626262,
|
||||
+};
|
||||
+
|
||||
void unit_hud_shield_meter_mapper_init(
|
||||
void)
|
||||
{
|
||||
@@ -890,6 +892,9 @@ void hud_render_unit_interface(
|
||||
0x209,
|
||||
player->local_player_index==render.local_player_index);
|
||||
/* ---------- macros */
|
||||
|
||||
+ unit_hud_shield_meter_mapper_tick();
|
||||
+ unit_hud_outline_mapper_tick();
|
||||
+
|
||||
if (player->local_player_index == render.local_player_index &&
|
||||
player->unit_index != NONE)
|
||||
/* ---------- structures */
|
||||
@@ -354,8 +360,27 @@ void hud_initialize_unit_interface_for_new_map(
|
||||
local_player_index < MAXIMUM_NUMBER_OF_LOCAL_PLAYERS;
|
||||
local_player_index++)
|
||||
{
|
||||
- hud_state = get_hud_state(local_player_index);
|
||||
- initialize_hud_state(hud_state);
|
||||
+ match_assert(
|
||||
+ "c:\\halo\\SOURCE\\interface\\hud_unit.c",
|
||||
+ 0x106,
|
||||
+ local_player_index>=0 &&
|
||||
+ local_player_index<MAXIMUM_NUMBER_OF_LOCAL_PLAYERS);
|
||||
+ match_assert(
|
||||
+ "c:\\halo\\SOURCE\\interface\\hud_unit.c",
|
||||
+ 0x107,
|
||||
+ unit_hud_globals);
|
||||
+
|
||||
+ hud_state = &unit_hud_globals->hud_states[local_player_index];
|
||||
+ csmemset(
|
||||
+ hud_state->auxilary_flash_time,
|
||||
+ NONE,
|
||||
+ sizeof(hud_state->auxilary_flash_time));
|
||||
+ hud_state->last_body_vitality = -1.0f;
|
||||
+ hud_state->last_shield_vitality = -1.0f;
|
||||
+ hud_state->last_health_flash_time = NONE;
|
||||
+ hud_state->last_motion_sensor_flash_time = NONE;
|
||||
+ hud_state->fade_time = -1.0f;
|
||||
+ hud_state->last_unit_index = NONE;
|
||||
hud_state->sound_flags = 0;
|
||||
csmemset(
|
||||
hud_state->last_sound_handles,
|
||||
@@ -605,36 +630,38 @@ static void hud_update_unit_local_player(
|
||||
if (game_time_get() - hud_state->last_shield_hit_time < 15)
|
||||
{
|
||||
hud_state->fade_time = 0.0f;
|
||||
+ goto update_finished;
|
||||
}
|
||||
- else
|
||||
- {
|
||||
- hud_state->last_shield_vitality = unit->object.shield_vitality;
|
||||
- hud_state->fade_time +=
|
||||
- (real)(game_time_get() - hud_state->last_shield_hit_time) *
|
||||
- (1.0f / TICKS_PER_SECOND);
|
||||
- hud_state->last_shield_hit_time = game_time_get();
|
||||
- }
|
||||
- }
|
||||
- else if (hud_state->last_shield_vitality < unit->object.shield_vitality)
|
||||
- {
|
||||
+
|
||||
hud_state->last_shield_vitality = unit->object.shield_vitality;
|
||||
- hud_state->fade_time = -1.0f;
|
||||
- hud_state->last_shield_hit_time = game_time_get();
|
||||
+ hud_state->fade_time +=
|
||||
+ (real)(game_time_get() - hud_state->last_shield_hit_time) *
|
||||
+ (1.0f / TICKS_PER_SECOND);
|
||||
}
|
||||
else
|
||||
{
|
||||
- hud_state->last_shield_vitality = unit->object.shield_vitality;
|
||||
- if (hud_state->fade_time > 0.0f)
|
||||
+ if (hud_state->last_shield_vitality < unit->object.shield_vitality)
|
||||
{
|
||||
- hud_state->fade_time +=
|
||||
- (real)(game_time_get() - hud_state->last_shield_hit_time) *
|
||||
- (1.0f / TICKS_PER_SECOND);
|
||||
+ hud_state->last_shield_vitality = unit->object.shield_vitality;
|
||||
+ hud_state->fade_time = -1.0f;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ hud_state->last_shield_vitality = unit->object.shield_vitality;
|
||||
+ if (hud_state->fade_time > 0.0f)
|
||||
+ {
|
||||
+ hud_state->fade_time +=
|
||||
+ (real)(game_time_get() - hud_state->last_shield_hit_time) *
|
||||
+ (1.0f / TICKS_PER_SECOND);
|
||||
+ }
|
||||
}
|
||||
- hud_state->last_shield_hit_time = game_time_get();
|
||||
}
|
||||
+
|
||||
+ hud_state->last_shield_hit_time = game_time_get();
|
||||
}
|
||||
}
|
||||
|
||||
+update_finished:
|
||||
if (cinematic_in_progress())
|
||||
{
|
||||
long player_index = local_player_get_player_index(local_player_index);
|
||||
@@ -647,7 +674,34 @@ static void hud_update_unit_local_player(
|
||||
}
|
||||
}
|
||||
|
||||
- match_assert_stack_frame("c:\\halo\\SOURCE\\interface\\hud_unit.c", 0x201);
|
||||
+ {
|
||||
+ short corrupt_index;
|
||||
+ short buffer_index;
|
||||
+
|
||||
+ for (buffer_index = STACK_BUFFER_LENGTH - 1; buffer_index >= 0; buffer_index--)
|
||||
+ {
|
||||
+ if (stack_buffer[buffer_index] != STACK_BUFFER_FILL)
|
||||
+ goto corrupt_stack_found;
|
||||
+ }
|
||||
+
|
||||
+ corrupt_index = NONE;
|
||||
+ goto stack_buffer_checked;
|
||||
+
|
||||
+corrupt_stack_found:
|
||||
+ corrupt_index = buffer_index;
|
||||
+
|
||||
+stack_buffer_checked:
|
||||
+ match_vassert(
|
||||
+ "c:\\halo\\SOURCE\\interface\\hud_unit.c",
|
||||
+ 0x201,
|
||||
+ return_eip == get_return_eip(),
|
||||
+ "corrupt return address!");
|
||||
+ match_vassert(
|
||||
+ "c:\\halo\\SOURCE\\interface\\hud_unit.c",
|
||||
+ 0x201,
|
||||
+ corrupt_index == NONE,
|
||||
+ csprintf(temporary, "corrupt stack at %d!", corrupt_index));
|
||||
+ }
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1390,7 +1444,34 @@ void hud_render_unit_interface(
|
||||
}
|
||||
}
|
||||
|
||||
- match_assert_stack_frame("c:\\halo\\SOURCE\\interface\\hud_unit.c", 0x3C9);
|
||||
+ {
|
||||
+ short corrupt_index;
|
||||
+ short buffer_index;
|
||||
+
|
||||
+ for (buffer_index = STACK_BUFFER_LENGTH - 1; buffer_index >= 0; buffer_index--)
|
||||
+ {
|
||||
+ if (stack_buffer[buffer_index] != STACK_BUFFER_FILL)
|
||||
+ goto corrupt_stack_found;
|
||||
+ }
|
||||
+
|
||||
+ corrupt_index = NONE;
|
||||
+ goto stack_buffer_checked;
|
||||
+
|
||||
+corrupt_stack_found:
|
||||
+ corrupt_index = buffer_index;
|
||||
+
|
||||
+stack_buffer_checked:
|
||||
+ match_vassert(
|
||||
+ "c:\\halo\\SOURCE\\interface\\hud_unit.c",
|
||||
+ 0x3C9,
|
||||
+ return_eip == get_return_eip(),
|
||||
+ "corrupt return address!");
|
||||
+ match_vassert(
|
||||
+ "c:\\halo\\SOURCE\\interface\\hud_unit.c",
|
||||
+ 0x3C9,
|
||||
+ corrupt_index == NONE,
|
||||
+ csprintf(temporary, "corrupt stack at %d!", corrupt_index));
|
||||
+ }
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1,124 +1,119 @@
|
||||
diff --git a/source/interface/hud_unit.c "b/C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\hud_unit_audit\\cand_final.c"
|
||||
index cfa13729..dc853fe5 100644
|
||||
index 1ff72603..dc853fe5 100644
|
||||
--- a/source/interface/hud_unit.c
|
||||
+++ "b/C:\\halo-worktrees\\claude-fifty-objects-20260925\\scratch\\w\\hud_unit_audit\\cand_final.c"
|
||||
@@ -3,13 +3,13 @@ HUD_UNIT.C
|
||||
@@ -113,6 +113,12 @@ enum hud_damage_indicator_direction
|
||||
NUMBER_OF_HUD_DAMAGE_INDICATOR_DIRECTIONS
|
||||
};
|
||||
|
||||
symbols in this file:
|
||||
000C6590 0010:
|
||||
- _code_000c6590 (0000)
|
||||
+ _unit_hud_outline_mapper_tick (0000)
|
||||
000C65A0 0010:
|
||||
- _code_000c65a0 (0000)
|
||||
+ _unit_hud_shield_meter_mapper_tick (0000)
|
||||
000C65B0 0010:
|
||||
_unit_hud_shield_meter_mapper_init (0000)
|
||||
000C65C0 0040:
|
||||
- _code_000c65c0 (0000)
|
||||
+ _initialize_hud_state (0000)
|
||||
000C6600 0070:
|
||||
_get_hud_state (0000)
|
||||
000C6670 0040:
|
||||
@@ -59,7 +59,7 @@ symbols in this file:
|
||||
002702D8 001d:
|
||||
??_C@_0BN@NPOPPJAG@old_local_player_index?$CB?$DNNONE?$AA@ (0000)
|
||||
002E4C68 0004:
|
||||
- _data_002e4c68 (0000)
|
||||
+ ?overcharge_count@?1??hud_render_unit_interface@@9@9 (0000)
|
||||
00453AC0 0004:
|
||||
_unit_hud_globals (0000)
|
||||
*/
|
||||
@@ -266,20 +266,22 @@ static struct unit_hud_globals *unit_hud_globals = NULL;
|
||||
extern struct hud_scripted_globals *hud_scripted_globals;
|
||||
extern struct hud_globals_definition *hud_globals;
|
||||
|
||||
-/* ---------- public code */
|
||||
+/* ---------- private code */
|
||||
|
||||
-void code_000c6590(
|
||||
+static void unit_hud_outline_mapper_tick(
|
||||
void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
-void code_000c65a0(
|
||||
+static void unit_hud_shield_meter_mapper_tick(
|
||||
void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
+/* ---------- public code */
|
||||
+enum
|
||||
+{
|
||||
+ STACK_BUFFER_LENGTH = 0x80,
|
||||
+ STACK_BUFFER_FILL = 0x62626262,
|
||||
+};
|
||||
+
|
||||
void unit_hud_shield_meter_mapper_init(
|
||||
void)
|
||||
{
|
||||
@@ -628,38 +630,36 @@ static void hud_update_unit_local_player(
|
||||
if (game_time_get() - hud_state->last_shield_hit_time < 15)
|
||||
{
|
||||
hud_state->fade_time = 0.0f;
|
||||
- goto update_finished;
|
||||
}
|
||||
-
|
||||
+ else
|
||||
+ {
|
||||
+ hud_state->last_shield_vitality = unit->object.shield_vitality;
|
||||
+ hud_state->fade_time +=
|
||||
+ (real)(game_time_get() - hud_state->last_shield_hit_time) *
|
||||
+ (1.0f / TICKS_PER_SECOND);
|
||||
+ hud_state->last_shield_hit_time = game_time_get();
|
||||
+ }
|
||||
+ }
|
||||
+ else if (hud_state->last_shield_vitality < unit->object.shield_vitality)
|
||||
+ {
|
||||
hud_state->last_shield_vitality = unit->object.shield_vitality;
|
||||
- hud_state->fade_time +=
|
||||
- (real)(game_time_get() - hud_state->last_shield_hit_time) *
|
||||
- (1.0f / TICKS_PER_SECOND);
|
||||
+ hud_state->fade_time = -1.0f;
|
||||
+ hud_state->last_shield_hit_time = game_time_get();
|
||||
}
|
||||
else
|
||||
{
|
||||
- if (hud_state->last_shield_vitality < unit->object.shield_vitality)
|
||||
+ hud_state->last_shield_vitality = unit->object.shield_vitality;
|
||||
+ if (hud_state->fade_time > 0.0f)
|
||||
{
|
||||
- hud_state->last_shield_vitality = unit->object.shield_vitality;
|
||||
- hud_state->fade_time = -1.0f;
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- hud_state->last_shield_vitality = unit->object.shield_vitality;
|
||||
- if (hud_state->fade_time > 0.0f)
|
||||
- {
|
||||
- hud_state->fade_time +=
|
||||
- (real)(game_time_get() - hud_state->last_shield_hit_time) *
|
||||
- (1.0f / TICKS_PER_SECOND);
|
||||
- }
|
||||
+ hud_state->fade_time +=
|
||||
+ (real)(game_time_get() - hud_state->last_shield_hit_time) *
|
||||
+ (1.0f / TICKS_PER_SECOND);
|
||||
}
|
||||
+ hud_state->last_shield_hit_time = game_time_get();
|
||||
}
|
||||
-
|
||||
- hud_state->last_shield_hit_time = game_time_get();
|
||||
/* ---------- macros */
|
||||
|
||||
/* ---------- structures */
|
||||
@@ -354,8 +360,27 @@ void hud_initialize_unit_interface_for_new_map(
|
||||
local_player_index < MAXIMUM_NUMBER_OF_LOCAL_PLAYERS;
|
||||
local_player_index++)
|
||||
{
|
||||
- hud_state = get_hud_state(local_player_index);
|
||||
- initialize_hud_state(hud_state);
|
||||
+ match_assert(
|
||||
+ "c:\\halo\\SOURCE\\interface\\hud_unit.c",
|
||||
+ 0x106,
|
||||
+ local_player_index>=0 &&
|
||||
+ local_player_index<MAXIMUM_NUMBER_OF_LOCAL_PLAYERS);
|
||||
+ match_assert(
|
||||
+ "c:\\halo\\SOURCE\\interface\\hud_unit.c",
|
||||
+ 0x107,
|
||||
+ unit_hud_globals);
|
||||
+
|
||||
+ hud_state = &unit_hud_globals->hud_states[local_player_index];
|
||||
+ csmemset(
|
||||
+ hud_state->auxilary_flash_time,
|
||||
+ NONE,
|
||||
+ sizeof(hud_state->auxilary_flash_time));
|
||||
+ hud_state->last_body_vitality = -1.0f;
|
||||
+ hud_state->last_shield_vitality = -1.0f;
|
||||
+ hud_state->last_health_flash_time = NONE;
|
||||
+ hud_state->last_motion_sensor_flash_time = NONE;
|
||||
+ hud_state->fade_time = -1.0f;
|
||||
+ hud_state->last_unit_index = NONE;
|
||||
hud_state->sound_flags = 0;
|
||||
csmemset(
|
||||
hud_state->last_sound_handles,
|
||||
@@ -647,7 +672,34 @@ static void hud_update_unit_local_player(
|
||||
}
|
||||
}
|
||||
|
||||
-update_finished:
|
||||
if (cinematic_in_progress())
|
||||
{
|
||||
long player_index = local_player_get_player_index(local_player_index);
|
||||
@@ -890,6 +890,9 @@ void hud_render_unit_interface(
|
||||
0x209,
|
||||
player->local_player_index==render.local_player_index);
|
||||
|
||||
+ unit_hud_shield_meter_mapper_tick();
|
||||
+ unit_hud_outline_mapper_tick();
|
||||
- match_assert_stack_frame("c:\\halo\\SOURCE\\interface\\hud_unit.c", 0x201);
|
||||
+ {
|
||||
+ short corrupt_index;
|
||||
+ short buffer_index;
|
||||
+
|
||||
if (player->local_player_index == render.local_player_index &&
|
||||
player->unit_index != NONE)
|
||||
{
|
||||
+ for (buffer_index = STACK_BUFFER_LENGTH - 1; buffer_index >= 0; buffer_index--)
|
||||
+ {
|
||||
+ if (stack_buffer[buffer_index] != STACK_BUFFER_FILL)
|
||||
+ goto corrupt_stack_found;
|
||||
+ }
|
||||
+
|
||||
+ corrupt_index = NONE;
|
||||
+ goto stack_buffer_checked;
|
||||
+
|
||||
+corrupt_stack_found:
|
||||
+ corrupt_index = buffer_index;
|
||||
+
|
||||
+stack_buffer_checked:
|
||||
+ match_vassert(
|
||||
+ "c:\\halo\\SOURCE\\interface\\hud_unit.c",
|
||||
+ 0x201,
|
||||
+ return_eip == get_return_eip(),
|
||||
+ "corrupt return address!");
|
||||
+ match_vassert(
|
||||
+ "c:\\halo\\SOURCE\\interface\\hud_unit.c",
|
||||
+ 0x201,
|
||||
+ corrupt_index == NONE,
|
||||
+ csprintf(temporary, "corrupt stack at %d!", corrupt_index));
|
||||
+ }
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1390,7 +1442,34 @@ void hud_render_unit_interface(
|
||||
}
|
||||
}
|
||||
|
||||
- match_assert_stack_frame("c:\\halo\\SOURCE\\interface\\hud_unit.c", 0x3C9);
|
||||
+ {
|
||||
+ short corrupt_index;
|
||||
+ short buffer_index;
|
||||
+
|
||||
+ for (buffer_index = STACK_BUFFER_LENGTH - 1; buffer_index >= 0; buffer_index--)
|
||||
+ {
|
||||
+ if (stack_buffer[buffer_index] != STACK_BUFFER_FILL)
|
||||
+ goto corrupt_stack_found;
|
||||
+ }
|
||||
+
|
||||
+ corrupt_index = NONE;
|
||||
+ goto stack_buffer_checked;
|
||||
+
|
||||
+corrupt_stack_found:
|
||||
+ corrupt_index = buffer_index;
|
||||
+
|
||||
+stack_buffer_checked:
|
||||
+ match_vassert(
|
||||
+ "c:\\halo\\SOURCE\\interface\\hud_unit.c",
|
||||
+ 0x3C9,
|
||||
+ return_eip == get_return_eip(),
|
||||
+ "corrupt return address!");
|
||||
+ match_vassert(
|
||||
+ "c:\\halo\\SOURCE\\interface\\hud_unit.c",
|
||||
+ 0x3C9,
|
||||
+ corrupt_index == NONE,
|
||||
+ csprintf(temporary, "corrupt stack at %d!", corrupt_index));
|
||||
+ }
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
# hud_weapon worker ledger (wave 4, base 16542e46)
|
||||
|
||||
Slug: scratch/w/hud_weapon/. Unit: source/interface/hud_weapon.
|
||||
Missing: _hud_update_weapon_local_player (1472), _crosshairs_draw (2256), _render_weapon_hud (2656).
|
||||
|
||||
## Baseline (production, gate --all)
|
||||
residual 2256 _crosshairs_draw [relocs 77!=76, sha]
|
||||
residual 1472 _hud_update_weapon_local_player [size 1456!=1472, sha]
|
||||
residual 2656 _render_weapon_hud [size 2624!=2656, relocs 85!=84, sha]
|
||||
== exact 13 residual 3 unwritten 0 (of 16)
|
||||
|
||||
## Prior art read (do not repeat)
|
||||
- opus5 150k w1/w3 ledgers; private_graph_fuzzy; fable crosshair x3; astra wave9 packet 9 (render_weapon_hud hold)
|
||||
- Lane C CC4 FINDINGS (claude-lane-c-graphics-ui-20260920/scratch/research/CC4-hud-weapon): E7a no_grenades &&; E7b fast_ftol decimal
|
||||
(closes reloc 85->84); E7c = {0} arrays in block after csmemset; E7d union-typed number_fractions (frame 0x288 vs 0x284:
|
||||
magazine_size spill).
|
||||
- Structural lane (claude-structural-20260923/scratch/lane/w/interface__hud_weapon/REPORT.md): uwlp EXACT via /Od case
|
||||
order + state pointer + unit_index local + default w/o result assignment (OWNER-HELD: structural owner packet sec 7);
|
||||
render_grenade_hud g1 landed (6eb9cb76). crosshairs_draw: firing uninit read authentic (/Od 0x6363e0) held; c2r ruling
|
||||
variant 2224/74 still fuzzy. render_weapon_hud r3u 2672 fuzzy; /Od local-count variants inert.
|
||||
|
||||
## P0 (re-measure) uwlp: structural-lane body spliced into production -> s1.c
|
||||
gate: == exact 14 residual 2; _hud_update_weapon_local_player EXACT on this tree (no other row moved).
|
||||
January proof of the uninitialised `result` web: T+0x144 `mov esi,[ebp-0x28]` loads return_eip's home into ESI
|
||||
(result's register) at loop entry - result's home is never stored, so the frame packer merged it with return_eip's
|
||||
slot; the default arm (T+0x404 assert, falls to +0x424 `test si,si`) reads it. /Od 0x638ac2..0x638af3: default arm
|
||||
has no store and falls to the read at 0x638af3; NO _RTC_UninitUse for `result` (RTC descriptor lists only the two
|
||||
64-byte arrays). => exact form is the held owner class (read reachable only if system_exit returns). Not landable.
|
||||
|
||||
## P1 render_weapon_hud re-measure of donors on this tree
|
||||
- CC4 hw_v4 (production body + E7a-d): 2624/84 sha (size -32). structural r3u (w1 R3 + union array): 2672/84 sha (size +16),
|
||||
876 vs 871 insns. r3u residual = pure allocation: frame-slot permutation (definition T-0x1c/O-0x14, element_index T-0x18
|
||||
homed vs O statics-loop ESI), flash-loop ESI/EDI swap, statics/numbers/overlays loop latch registers, x87 distance sum
|
||||
(T j2,i2,add,k2,add vs O k2,j2,add,i2,add). Every other instruction identical.
|
||||
- B.c = s1 (structural uwlp, +2 locals before rwh) + r3u rwh: rwh byte-identical to r3u (sha b420177a...). +2 names inert.
|
||||
|
||||
## P2 oracle sweeps on B.c render_weapon_hud (LAB ONLY; fillers never land)
|
||||
- names before rwh prototype k=0..40: all byte-identical (b420177a). names right before rwh DEFINITION k=0..40: identical.
|
||||
- dead locals (`long x;`) D=0..16 in rwh: identical. initialised copies (`long x = hud_index;`) D=1..9: one flip (param-home
|
||||
reuse, 2656/84 but 159 hunks) then identical for all D -> count inert.
|
||||
- pow(10.0f, 4) (the /Od 0x632150 float,int overload = direct pow, not real_math power()) vs power(): byte-identical.
|
||||
=> none of the three residual ties (statics-loop allocation, flash-loop IV regs, x87 sum order) is keyed on TU name count
|
||||
or in-function local count.
|
||||
- x87 micro-lab (scratch/w/hud_weapon/micro): plain distance3d gives three different sum orders (kij/kji/jik) depending on
|
||||
inline helper expansions AFTER the site (after_mag1-2 kij, after_mag3+ kji; after_dot1-8 kij; after_dist1+ kji);
|
||||
plain statements before/after, dead locals, names, param count, arg order, decl order all inert. So the order is keyed on
|
||||
later inline-helper content in the same function (not M8 dead-local count). January rwh = jik (same as ctf_init site 1).
|
||||
- rv_V1/V1b: flash-loop counter declared in the outer block (before/after map/element_index; /Od has it at -0x80 right after
|
||||
numbers_real): byte-identical to B (b420177a). Inert.
|
||||
- Harness rv.py prints the three tie signatures. January = x87 jik, flash[hud=esi flags=edi], statics lea-esi, frame 0x284.
|
||||
B/r3u = x87 kji, flash[hud=edi flags=esi], statics other.
|
||||
- micro-lab refinement: the x87 order flips with the operands' frame placement (mag3 moved position nearer EBP) - it follows
|
||||
frame/reference facts of the aggregates, not local counts. In rwh both points already sit at January's slots.
|
||||
- prototypes (`void p(void);`) k=0..34 right before rwh definition: all identical (H3-style prototype-unit key inert too).
|
||||
- K1: `cutoffs` pointer local replacing definition->flash_cutoffs.* in the else block: byte-identical (VC7 folds).
|
||||
- A1: `long age_percentage` local for the two overlay PINs: byte-identical.
|
||||
- M1/M2 (/Od idiom `scenario = global_scenario_get(); map_type_flags = 0; SET_FLAG(map_type_flags, 0, ...)`, /Od 0x63b40f
|
||||
and crosshairs /Od 0x636452): byte-identical to B (VC7 folds to setne).
|
||||
- S1 (state_index local in statics loop): identical.
|
||||
- BISECTION r3u(B) x hw_v4 else-block segments (hyb.py): only the hw_v4 OVERLAY section (flags local copies, dword ops)
|
||||
flips the statics loop to January's allocation (lea esi,[edi+0x60], element_index homed) - but it breaks the overlay
|
||||
bytes (size 2624). hw_v4/production statics loop == January's. So the statics-loop allocation IS source-reachable and
|
||||
keyed on upstream else-block content, not counts.
|
||||
|
||||
## P3 allocator trace (Lane A dbg32c copied into scratch/w/hud_weapon/dbg; runs our own CL/C2 under INT3, outputs only in slug)
|
||||
- lab_min.c = B with every body except get_hud_state + rwh removed, rwh last, plus a trivial caller: rwh byte-identical
|
||||
(b420177a). Trace (res_min.txt / show.py) lists rwh webs 11..78.
|
||||
- Flash loop webs: p_hud W=75a8 pri 46 pos 110 -> EDI (cost esi=1, edi=0), p_flags W=75f0 pri 28 pos 111 -> ESI,
|
||||
counter W=c740 pri 16 pos 10f -> EBX. Pop order is by priority; the EDI choice is the chooser's used-register cost
|
||||
(EDI already used by the first-popped web W=c620 pri 204 pos 2d1, the numbers-loop element; EBX still unused = 4200).
|
||||
January's p_hud=ESI therefore needs ESI cheaper than/equal to EDI when p_hud is coloured, i.e. a different set of
|
||||
higher-priority webs (upstream IL fact), not a flash-loop spelling. lab_F1 (inverted flash if/else) stays hud=edi.
|
||||
- hyb_00100 trace (res_hyb.txt): the hw_v4 overlay `flags` webs (pri 63-90) are popped before the flash loop and take ESI;
|
||||
from then on the chooser's ESI cost is 0 (tie with EDI -> class order ESI), so p_hud=ESI (January) and the statics-loop
|
||||
&statics web (pri 34) also takes ESI (January). In ours (res_min.txt) a persistent +1 ESI cost (neighbour preference
|
||||
from long-lived param webs W=e298/e208, pos 2, coloured last with ESI) makes EDI win for p_hud (#28) AND for the statics
|
||||
&statics web (#32). => the flash-loop and statics-loop residuals share ONE cause: the ESI-vs-EDI tie in the chooser
|
||||
(neighbour preference weight 1). January's source must differ upstream in something that either colours a
|
||||
high-priority web into ESI earlier or removes the ESI preference of the long-lived param webs. Not found.
|
||||
- LAB G1 (get_hud_state made non-static, cdecl push instead of the private ESI-argument ABI): flash loop becomes
|
||||
hud=esi flags=edi AND statics loop lea-esi (both January). => the ESI neighbour-preference that flips both residuals
|
||||
comes from get_hud_state's private register-argument call (`mov esi,[ebp+0xc]; call _get_hud_state`, T+0x35).
|
||||
January has the same call bytes, so the difference is in how that ESI web is weighted (upstream).
|
||||
- Full cost tables (mem idx 4=ebx,7=esi,8=edi): ours p_hud #28 esi=1 edi=0 -> EDI; hyb p_hud #33 esi=0 edi=0 -> ESI.
|
||||
The +1 ESI is a neighbour preference from a later-coloured long-lived web (param webs W=e298/e208, pos 2, coloured
|
||||
last into ESI). Could not map it to a source fact (no symbol names in the web record without a debugger rebuild).
|
||||
- Definition order (January section order, reorder.py -> Bord.c): rwh byte-identical (inert, as w3 found).
|
||||
|
||||
## P4 candidate construction (mkcand.py; r3u body + /Od-attested inert spellings + RTC names)
|
||||
| variant | rwh | note |
|
||||
| c_union (=r3u) | 2672/84 b420177a, 112 hunks | TU-level union element type (CC4 E7d; invented type name; HCEX says float[8]) |
|
||||
| c_od_union_names_tblock | 2672/84 b420177a | /Od: pow(10.0f,4), inline unit-index ?: arg, inline decimal arg, scenario+map=0+SET_FLAG; RTC names numbers/numbers_real/position; /Od target-block decl order - all byte-inert |
|
||||
| c_od_realarr_names_tblock | 2672/84 a4f40686, 118 hunks | real numbers_real[] + admitted local-union transfers (homes the sentinel/fraction temps) |
|
||||
| c_cast (lab) | 2672/84 ec333ee6 (= old R3 hash), 111 hunks | pointer-cast sentinel (inadmissible representation access) |
|
||||
| production | 2624/85, 208 hunks | hand-expanded distance (rule 6), (short)fmod (extra __ftol2), flags/cutoffs locals |
|
||||
All variants keep the same three residuals: x87 kji vs jik, flash hud=edi vs esi, statics loop.
|
||||
- x87 order: lab_G1 (no private ABI) and hyb both still kji -> independent residual. Lab x87o_1..6 (1-6 extra
|
||||
magnitude3d inlines after the site): kji. Micro variants (frame/pointer/param args, dsq vs d3d, compare use): kij or
|
||||
other; could not reproduce January's jik outside the ctf_init first-site context. No lever.
|
||||
|
||||
## P5 admission side-effects of the rwh fidelity candidate (cand.c = c_od_realarr_names_tblock)
|
||||
- gate --all: exact 13 residual 3 (no row lost); emitted-symbol guard (_point_from_line3d) passes; /W3 clean.
|
||||
- relocation-target multiset == January (production has an extra __ftol2); relocations 0..53 at January's addresses.
|
||||
- Symbol census vs build/base: drops _power, ADDS header-inline COMDATs _distance3d, _distance_squared3d,
|
||||
_magnitude_squared3d, _vector_from_points3d, _fast_ftol (January's split defines none; COMDAT folding invisible).
|
||||
=> wave-3 law (i)/P1: new header COMDATs from a NON-exact caller are held. The fidelity packet is NOT landable now;
|
||||
it becomes the base to land when rwh closes. Also: its block after csmemset depends on the stack-sentinel prologue
|
||||
(hud_stack_check lane) - if that lane introduces a block-opening sentinel macro, drop the explicit block.
|
||||
|
||||
## P6 uwlp owner-gated packet
|
||||
- owner_uwlp.c = s1.c + BUG-style comments (default-arm unassigned result; primary-trigger test in the secondary
|
||||
state, /Od 0x638a07). gate: EXACT 1472/68 (0524ed47), 14/16, guard passes, no new symbols vs base.
|
||||
- owner_gated_uwlp.patch: `git apply --check` clean against 16542e46.
|
||||
- object_audit with owner_uwlp.obj: FAIL(2) = _crosshairs_draw, _render_weapon_hud; 23/23 January symbols ok; bss ok;
|
||||
surplus = literals + production's _power/_square_root COMDATs. pdb_storage: 0 disagreements.
|
||||
|
||||
## crosshairs_draw (not re-probed beyond a re-measure; held owner item)
|
||||
- cd_r0 (production + uninitialised firing_active = the ruling form): residual [relocs 77!=76], 693 vs 704 insns,
|
||||
157 hunks, frame 0x314 vs 0x318. Prior art: P5 lane-C (bind bitmap_group_get -> 0x318 frame), structural c2r
|
||||
(/Od switch shape, 2224/74). January facts re-read: aim/zoom/animated colour tails cross-jump (T+0x51c jmp 0x393),
|
||||
if-chain 18/8/9 with the state-14 read of firing at T+0x495. Needs owner ruling + a full /Od-guided rebuild.
|
||||
|
||||
## STOP (methodology stop rule)
|
||||
rwh: >5 evidence-based shapes (pow, /Od idioms x4, flash scope x2, names, target-block order, sentinel forms x3) plus
|
||||
three count oracles all inert; remaining difference is the decoded ESI/EDI chooser tie (+1 ESI neighbour preference
|
||||
tied to the get_hud_state private register-argument call) and an independent x87 add-chain order.
|
||||
|
||||
## P7 interaction with the concurrent hud_stack_check packet (P1 header inline check_stack_buffer + P5 hud_weapon.c)
|
||||
- lab/sc_*.c = stack-lane gtu_h2 hud_weapon TU + my rwh candidates: rwh byte-identical (b420177a / a4f40686) -> the rwh
|
||||
residual does NOT depend on the sentinel implementation (hand macro vs header inline).
|
||||
- LAB G2 get_hud_state(0) (no local_player_index->ESI copy): flash + statics go January's way -> the +1 ESI preference is
|
||||
the local_player_index web's copy into the get_hud_state ESI argument (T+0x35 `mov esi,[ebp+0xc]`, identical in both).
|
||||
- owner uwlp on top of the stack packet (after_p5/gtu_owner.c): EXACT, 14/16. owner_gated_uwlp_after_P5.patch applies
|
||||
(git apply --check --directory=after_p5) to production+P5; owner_gated_uwlp.patch applies to 16542e46 (they conflict on
|
||||
the stack_buffer context line, use the one matching the tree state).
|
||||
- git status: clean throughout (no tracked file touched).
|
||||
|
||||
## FINAL
|
||||
- _hud_update_weapon_local_player: strict EXACT only in the held authentic-bug form (default arm leaves `result`
|
||||
unassigned; owner packet sec 7 / brief sec 7). Patches ready, not landable.
|
||||
- _render_weapon_hud: best candidate cand.c (reloc multiset == January, 54/84 relocs at January addresses, 2672 vs 2656);
|
||||
held by P1 (new header COMDATs from a non-exact caller). Residual = ESI/EDI chooser tie from the get_hud_state
|
||||
private-ABI copy preference (flash loop + statics loop + downstream frame permutation) + x87 add-chain order.
|
||||
- _crosshairs_draw: held (authentic uninitialised firing read) and still fuzzy (157 hunks in the ruling form).
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,420 @@
|
||||
--- a/source/interface/hud_weapon.c
|
||||
+++ b/source/interface/hud_weapon.c
|
||||
@@ -724,6 +724,7 @@
|
||||
long return_eip = get_return_eip();
|
||||
long stack_buffer[HUD_WEAPON_STACK_BUFFER_LENGTH];
|
||||
struct player_datum *player;
|
||||
+ long unit_index;
|
||||
struct unit_datum *unit;
|
||||
struct crosshair_hud_state *crosshair;
|
||||
struct weapon_hud_interface_definition *root_definition;
|
||||
@@ -733,7 +734,8 @@
|
||||
0x62,
|
||||
sizeof(stack_buffer));
|
||||
player = player_get(local_player_get_player_index(local_player_index));
|
||||
- unit = unit_try_and_get(player->unit_index);
|
||||
+ unit_index = player->unit_index;
|
||||
+ unit = unit_try_and_get(unit_index);
|
||||
if (!unit)
|
||||
goto finished;
|
||||
|
||||
@@ -784,223 +786,189 @@
|
||||
crosshair_index < NUMBER_OF_CROSSHAIR_STATES;
|
||||
crosshair_index++)
|
||||
{
|
||||
- short result;
|
||||
-
|
||||
- if (!TEST_FLAG(valid_crosshair_types, crosshair_index))
|
||||
- continue;
|
||||
-
|
||||
- switch (crosshair_index)
|
||||
- {
|
||||
- case _crosshair_state_aim:
|
||||
- result = weapon_index == NONE ?
|
||||
- FALSE :
|
||||
- player_control_get_autoaim_level(player->local_player_index) == 1.0f;
|
||||
- break;
|
||||
-
|
||||
- case _crosshair_state_zoom:
|
||||
- result = player_control_get_zoom_level(player->local_player_index) == NONE ?
|
||||
- 1 :
|
||||
- player_control_get_zoom_level(player->local_player_index) + 2;
|
||||
- break;
|
||||
-
|
||||
- case _crosshair_state_charge:
|
||||
- result = FALSE;
|
||||
- break;
|
||||
-
|
||||
- case _crosshair_state_flash_ammo:
|
||||
- if (weapon_state->magazines[0].rounds_remaining)
|
||||
- {
|
||||
- result = weapon_state->magazines[0].rounds_loaded <=
|
||||
- root_definition->flash_cutoffs.loaded_ammo;
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- result = FALSE;
|
||||
- }
|
||||
- break;
|
||||
-
|
||||
- case _crosshair_state_flash_heat:
|
||||
- result = weapon_state->heat * 100.0f >=
|
||||
- (real)root_definition->flash_cutoffs.heat;
|
||||
- break;
|
||||
-
|
||||
- case _crosshair_state_flash_total_ammo:
|
||||
- result = weapon_state->magazines[0].rounds_remaining <=
|
||||
- root_definition->flash_cutoffs.total_ammo &&
|
||||
- !weapon_state->magazines[0].reloading;
|
||||
- break;
|
||||
-
|
||||
- case _crosshair_state_flash_total_battery:
|
||||
- result = weapon_state->age < 1.0f &&
|
||||
- (1.0f - weapon_state->age) * 100.0f <=
|
||||
- (real)root_definition->flash_cutoffs.age;
|
||||
- break;
|
||||
-
|
||||
- case _crosshair_state_reload:
|
||||
- result = weapon_state->magazines[0].reloading;
|
||||
- break;
|
||||
-
|
||||
- case _crosshair_state_fired_with_no_ammo:
|
||||
- if (!weapon_state->magazines[0].rounds_loaded &&
|
||||
- !weapon_state->magazines[0].rounds_remaining &&
|
||||
- TEST_FLAG(unit->unit.control_flags, _unit_control_weapon_primary_trigger_bit))
|
||||
- {
|
||||
- result = TRUE;
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- result = crosshair->states[crosshair_index].value.reference_data != NONE;
|
||||
- }
|
||||
- break;
|
||||
-
|
||||
- case _crosshair_state_threw_with_no_grenade:
|
||||
+ if (TEST_FLAG(valid_crosshair_types, crosshair_index))
|
||||
{
|
||||
- boolean no_grenades = TRUE;
|
||||
- short grenade_type;
|
||||
+ struct crosshair_state *state = &crosshair->states[crosshair_index];
|
||||
+ short result;
|
||||
|
||||
- for (grenade_type = 0; grenade_type < NUMBER_OF_UNIT_GRENADE_TYPES; grenade_type++)
|
||||
+ switch (crosshair_index)
|
||||
{
|
||||
- if (unit->unit.grenade_counts[grenade_type])
|
||||
- no_grenades = FALSE;
|
||||
- }
|
||||
- if (no_grenades &&
|
||||
- !unit->unit.grenade_throw_state &&
|
||||
- TEST_FLAG(unit->unit.control_flags, _unit_control_throw_grenade_bit))
|
||||
- {
|
||||
- result = TRUE;
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- result = crosshair->states[crosshair_index].value.reference_data != NONE;
|
||||
- }
|
||||
- break;
|
||||
- }
|
||||
+ case _crosshair_state_primary_trigger_ready:
|
||||
+ result = weapon_state->magazines[0].can_fire;
|
||||
+ break;
|
||||
+
|
||||
+ case _crosshair_state_secondary_trigger_ready:
|
||||
+ result = weapon_state->magazines[1].can_fire;
|
||||
+ break;
|
||||
+
|
||||
+ case _crosshair_state_aim:
|
||||
+ result = weapon_index == NONE ?
|
||||
+ FALSE :
|
||||
+ player_control_get_autoaim_level(player->local_player_index) == 1.0f;
|
||||
+ break;
|
||||
+
|
||||
+ case _crosshair_state_zoom:
|
||||
+ result = player_control_get_zoom_level(player->local_player_index) != NONE ?
|
||||
+ player_control_get_zoom_level(player->local_player_index) + 2 :
|
||||
+ 1;
|
||||
+ break;
|
||||
+
|
||||
+ case _crosshair_state_reload:
|
||||
+ result = weapon_state->magazines[0].reloading;
|
||||
+ break;
|
||||
+
|
||||
+ case _crosshair_state_flash_ammo:
|
||||
+ result = (weapon_state->magazines[0].rounds_remaining || weapon_state->magazines[0].rounds_loaded) &&
|
||||
+ weapon_state->magazines[0].rounds_remaining &&
|
||||
+ weapon_state->magazines[0].rounds_loaded <= root_definition->flash_cutoffs.loaded_ammo;
|
||||
+ break;
|
||||
+
|
||||
+ case _crosshair_state_flash_heat:
|
||||
+ result = weapon_state->heat * 100.0f >=
|
||||
+ (real)root_definition->flash_cutoffs.heat;
|
||||
+ break;
|
||||
+
|
||||
+ case _crosshair_state_flash_total_ammo:
|
||||
+ result = weapon_state->magazines[0].rounds_remaining <=
|
||||
+ root_definition->flash_cutoffs.total_ammo &&
|
||||
+ !weapon_state->magazines[0].reloading;
|
||||
+ break;
|
||||
+
|
||||
+ case _crosshair_state_flash_total_battery:
|
||||
+ result = weapon_state->age < 1.0f &&
|
||||
+ (1.0f - weapon_state->age) * 100.0f <=
|
||||
+ (real)root_definition->flash_cutoffs.age;
|
||||
+ break;
|
||||
|
||||
- case _crosshair_state_flash_ammo_none_for_reload:
|
||||
- result = !weapon_state->magazines[0].rounds_remaining &&
|
||||
- weapon_state->magazines[0].rounds_loaded &&
|
||||
- weapon_state->magazines[0].rounds_loaded <=
|
||||
- root_definition->flash_cutoffs.loaded_ammo;
|
||||
- break;
|
||||
-
|
||||
- case _crosshair_state_flash_secondary_ammo:
|
||||
- if (weapon_state->magazines[1].rounds_remaining)
|
||||
- {
|
||||
- result = weapon_state->magazines[1].rounds_loaded <=
|
||||
- root_definition->flash_cutoffs.loaded_ammo;
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
+ case _crosshair_state_charge:
|
||||
result = FALSE;
|
||||
- }
|
||||
- break;
|
||||
-
|
||||
- case _crosshair_state_flash_secondary_total_ammo:
|
||||
- result = weapon_state->magazines[1].rounds_remaining <=
|
||||
- root_definition->flash_cutoffs.total_ammo &&
|
||||
- !weapon_state->magazines[1].reloading;
|
||||
- break;
|
||||
-
|
||||
- case _crosshair_state_secondary_reload:
|
||||
- result = weapon_state->magazines[1].reloading;
|
||||
- break;
|
||||
-
|
||||
- case _crosshair_state_fired_secondary_with_no_ammo:
|
||||
- if (!weapon_state->magazines[1].rounds_loaded &&
|
||||
- !weapon_state->magazines[1].rounds_remaining &&
|
||||
- TEST_FLAG(unit->unit.control_flags, _unit_control_weapon_secondary_trigger_bit))
|
||||
- {
|
||||
- result = TRUE;
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- result = crosshair->states[crosshair_index].value.reference_data != NONE;
|
||||
- }
|
||||
- break;
|
||||
-
|
||||
- case _crosshair_state_flash_secondary_ammo_none_for_reload:
|
||||
- result = !weapon_state->magazines[1].rounds_remaining &&
|
||||
- weapon_state->magazines[1].rounds_loaded &&
|
||||
- weapon_state->magazines[1].rounds_loaded <=
|
||||
- root_definition->flash_cutoffs.loaded_ammo;
|
||||
- break;
|
||||
-
|
||||
- case _crosshair_state_primary_trigger_ready:
|
||||
- result = weapon_state->magazines[0].can_fire;
|
||||
- break;
|
||||
-
|
||||
- case _crosshair_state_secondary_trigger_ready:
|
||||
- result = weapon_state->magazines[1].can_fire;
|
||||
- break;
|
||||
+ break;
|
||||
|
||||
- case _crosshair_state_flash_fired_battery_depleted:
|
||||
- if (weapon_state->age == 1.0f &&
|
||||
- TEST_FLAG(unit->unit.control_flags, _unit_control_weapon_primary_trigger_bit))
|
||||
- {
|
||||
- result = TRUE;
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- result = crosshair->states[crosshair_index].value.reference_data != NONE;
|
||||
- }
|
||||
- break;
|
||||
-
|
||||
- default:
|
||||
- match_assert(
|
||||
- "c:\\halo\\SOURCE\\interface\\hud_weapon.c",
|
||||
- 0x16E,
|
||||
- !"unreachable");
|
||||
- result = FALSE;
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
- SET_FLAG(
|
||||
- render_flags,
|
||||
- crosshair_index,
|
||||
- result > 0 || crosshair_index == _crosshair_state_aim);
|
||||
- switch (crosshair_index)
|
||||
- {
|
||||
- case _crosshair_state_aim:
|
||||
- crosshair->states[crosshair_index].value.reference_data = result;
|
||||
- break;
|
||||
-
|
||||
- case _crosshair_state_zoom:
|
||||
- crosshair->states[crosshair_index].value.reference_data = result - 1;
|
||||
- break;
|
||||
-
|
||||
- case _crosshair_state_charge:
|
||||
- case _crosshair_state_flash_ammo:
|
||||
- case _crosshair_state_flash_heat:
|
||||
- case _crosshair_state_flash_total_ammo:
|
||||
- case _crosshair_state_flash_total_battery:
|
||||
- case _crosshair_state_reload:
|
||||
- case _crosshair_state_fired_with_no_ammo:
|
||||
- case _crosshair_state_threw_with_no_grenade:
|
||||
- case _crosshair_state_flash_ammo_none_for_reload:
|
||||
- case _crosshair_state_flash_secondary_ammo:
|
||||
- case _crosshair_state_flash_secondary_total_ammo:
|
||||
- case _crosshair_state_secondary_reload:
|
||||
- case _crosshair_state_fired_secondary_with_no_ammo:
|
||||
- case _crosshair_state_flash_secondary_ammo_none_for_reload:
|
||||
- case _crosshair_state_primary_trigger_ready:
|
||||
- case _crosshair_state_secondary_trigger_ready:
|
||||
- case _crosshair_state_flash_fired_battery_depleted:
|
||||
- if (!result)
|
||||
- {
|
||||
- crosshair->states[crosshair_index].value.reference_data = NONE;
|
||||
+ case _crosshair_state_flash_fired_battery_depleted:
|
||||
+ result = (weapon_state->age == 1.0f &&
|
||||
+ TEST_FLAG(unit->unit.control_flags, _unit_control_weapon_primary_trigger_bit)) ||
|
||||
+ state->value.reference_data != NONE;
|
||||
+ break;
|
||||
+
|
||||
+ case _crosshair_state_fired_with_no_ammo:
|
||||
+ result = (!weapon_state->magazines[0].rounds_loaded &&
|
||||
+ !weapon_state->magazines[0].rounds_remaining &&
|
||||
+ TEST_FLAG(unit->unit.control_flags, _unit_control_weapon_primary_trigger_bit)) ||
|
||||
+ state->value.reference_data != NONE;
|
||||
+ break;
|
||||
+
|
||||
+ case _crosshair_state_threw_with_no_grenade:
|
||||
+ {
|
||||
+ boolean no_grenades = TRUE;
|
||||
+ short grenade_type;
|
||||
+
|
||||
+ for (grenade_type = 0; grenade_type < NUMBER_OF_UNIT_GRENADE_TYPES; grenade_type++)
|
||||
+ {
|
||||
+ no_grenades = no_grenades && !unit->unit.grenade_counts[grenade_type];
|
||||
+ }
|
||||
+ result = (no_grenades &&
|
||||
+ !unit->unit.grenade_throw_state &&
|
||||
+ TEST_FLAG(unit->unit.control_flags, _unit_control_throw_grenade_bit)) ||
|
||||
+ state->value.reference_data != NONE;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ case _crosshair_state_flash_ammo_none_for_reload:
|
||||
+ result = (weapon_state->magazines[0].rounds_remaining || weapon_state->magazines[0].rounds_loaded) &&
|
||||
+ !weapon_state->magazines[0].rounds_remaining &&
|
||||
+ weapon_state->magazines[0].rounds_loaded <= root_definition->flash_cutoffs.loaded_ammo;
|
||||
+ break;
|
||||
+
|
||||
+ case _crosshair_state_flash_secondary_ammo:
|
||||
+ result = (weapon_state->magazines[1].rounds_remaining || weapon_state->magazines[1].rounds_loaded) &&
|
||||
+ weapon_state->magazines[1].rounds_remaining &&
|
||||
+ weapon_state->magazines[1].rounds_loaded <= root_definition->flash_cutoffs.loaded_ammo;
|
||||
+ break;
|
||||
+
|
||||
+ case _crosshair_state_flash_secondary_total_ammo:
|
||||
+ result = weapon_state->magazines[1].rounds_remaining <=
|
||||
+ root_definition->flash_cutoffs.total_ammo &&
|
||||
+ !weapon_state->magazines[1].reloading;
|
||||
+ break;
|
||||
+
|
||||
+ case _crosshair_state_secondary_reload:
|
||||
+ result = weapon_state->magazines[1].reloading;
|
||||
+ break;
|
||||
+
|
||||
+ case _crosshair_state_fired_secondary_with_no_ammo:
|
||||
+ /* January (T+0x3b7 shared tail `test ch,8`) and the later /Od build (0x638a07
|
||||
+ `and edx,0x800`) both test the primary trigger for this secondary state. */
|
||||
+ result = (!weapon_state->magazines[1].rounds_loaded &&
|
||||
+ !weapon_state->magazines[1].rounds_remaining &&
|
||||
+ TEST_FLAG(unit->unit.control_flags, _unit_control_weapon_primary_trigger_bit)) ||
|
||||
+ state->value.reference_data != NONE;
|
||||
+ break;
|
||||
+
|
||||
+ case _crosshair_state_flash_secondary_ammo_none_for_reload:
|
||||
+ result = (weapon_state->magazines[1].rounds_remaining || weapon_state->magazines[1].rounds_loaded) &&
|
||||
+ !weapon_state->magazines[1].rounds_remaining &&
|
||||
+ weapon_state->magazines[1].rounds_loaded <= root_definition->flash_cutoffs.loaded_ammo;
|
||||
+ break;
|
||||
+
|
||||
+ default:
|
||||
+ match_assert(
|
||||
+ "c:\\halo\\SOURCE\\interface\\hud_weapon.c",
|
||||
+ 0x16E,
|
||||
+ !"unreachable");
|
||||
+ /* BUG (preserved for exact matching): January and the later /Od build
|
||||
+ (0x638ac2) leave result unassigned here, so it is read uninitialised
|
||||
+ below if system_exit returns (T+0x144 loads its never-stored home). */
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ SET_FLAG(
|
||||
+ render_flags,
|
||||
+ crosshair_index,
|
||||
+ result > 0 || crosshair_index == _crosshair_state_aim);
|
||||
+ switch (crosshair_index)
|
||||
+ {
|
||||
+ case _crosshair_state_aim:
|
||||
+ state->value.reference_data = result;
|
||||
+ break;
|
||||
+
|
||||
+ case _crosshair_state_zoom:
|
||||
+ state->value.reference_data = result - 1;
|
||||
+ break;
|
||||
+
|
||||
+ case _crosshair_state_charge:
|
||||
+ case _crosshair_state_flash_ammo:
|
||||
+ case _crosshair_state_flash_heat:
|
||||
+ case _crosshair_state_flash_total_ammo:
|
||||
+ case _crosshair_state_flash_total_battery:
|
||||
+ case _crosshair_state_reload:
|
||||
+ case _crosshair_state_fired_with_no_ammo:
|
||||
+ case _crosshair_state_threw_with_no_grenade:
|
||||
+ case _crosshair_state_flash_ammo_none_for_reload:
|
||||
+ case _crosshair_state_flash_secondary_ammo:
|
||||
+ case _crosshair_state_flash_secondary_total_ammo:
|
||||
+ case _crosshair_state_secondary_reload:
|
||||
+ case _crosshair_state_fired_secondary_with_no_ammo:
|
||||
+ case _crosshair_state_flash_secondary_ammo_none_for_reload:
|
||||
+ case _crosshair_state_primary_trigger_ready:
|
||||
+ case _crosshair_state_secondary_trigger_ready:
|
||||
+ case _crosshair_state_flash_fired_battery_depleted:
|
||||
+ if (!result)
|
||||
+ {
|
||||
+ state->value.reference_data = NONE;
|
||||
+ }
|
||||
+ else if (state->value.reference_data == NONE)
|
||||
+ {
|
||||
+ state->value.reference_data = game_time_get();
|
||||
+ }
|
||||
+ break;
|
||||
+
|
||||
+ default:
|
||||
+ match_assert(
|
||||
+ "c:\\halo\\SOURCE\\interface\\hud_weapon.c",
|
||||
+ 0x197,
|
||||
+ !"unreachable");
|
||||
+ break;
|
||||
}
|
||||
- else if (crosshair->states[crosshair_index].value.reference_data == NONE)
|
||||
- {
|
||||
- crosshair->states[crosshair_index].value.reference_data = game_time_get();
|
||||
- }
|
||||
- break;
|
||||
-
|
||||
- default:
|
||||
- match_assert(
|
||||
- "c:\\halo\\SOURCE\\interface\\hud_weapon.c",
|
||||
- 0x197,
|
||||
- !"unreachable");
|
||||
- break;
|
||||
}
|
||||
}
|
||||
|
||||
Loaded 100 of 359 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user