diff --git a/config/config.json b/config/config.json index 212c4af5..14a35950 100644 --- a/config/config.json +++ b/config/config.json @@ -801,7 +801,7 @@ { "name": "source/ai/path_structure_bsp.c", "index": 426, "status": "NonMatching" }, { "name": "source/ai/path_smoothing.c", "index": 427, "status": "Matching" }, { "name": "source/ai/path_obstacles.c", "index": 428, "status": "NonMatching" }, - { "name": "source/ai/path_obstacle_avoidance.c", "index": 429, "status": "NonMatching" }, + { "name": "source/ai/path_obstacle_avoidance.c", "index": 429, "status": "Matching" }, { "name": "source/ai/path.c", "index": 430, "status": "Matching" }, { "name": "source/ai/encounters.c", "index": 431, "status": "Matching" }, { "name": "source/ai/ai_script.c", "index": 432, "status": "Matching" }, diff --git a/config/parked.json b/config/parked.json index e009a3cd..0b424136 100644 --- a/config/parked.json +++ b/config/parked.json @@ -976,11 +976,11 @@ "unit": "source/ai/ai", "function": "_ai_test_ballistic_line_of_fire", "class": "instruction-scheduling", - "evidence": "Complete typed ballistic trajectory, world-collision, friendly-pill, and debug-recording reconstruction from January code/relocations and HCEA semantics. Target and candidate are both 944 padded bytes with all 49 relocations. Remaining differences are compiler-local x87 and independent instruction scheduling. No fake dependency, raw offset, forced inline, or nonsensical logic is retained. Zero exact credit. See docs/object_matching_logs/ai_obj_large_visibility_spatial_packet_20260909.md. 2026-09-20 Lane A re-baseline (zero exact credit): the recorded 250K-lane w3c 'b5' shape is rebuilt from this baseline and landed. Three changes: block-scope segment_time to the coordinate statement; parenthesise the linear term of the z row as (segment_time * arc_velocity.k + point.z); spell the post-call velocity update as (segment_end_time - segment_start_time) * gravity + arc_velocity.k. Instruction counts become 296/296 (HEAD was 292/296) and objdiff rises 94.50 to 98.99645. It reproduces January's x87 structure for segment_time exactly: fsubr of the parameter home at +0x1e7, fst (store-and-keep) to a dead parameter home at +0x1f4, and a post-call fld from that same home at +0x2cc feeding fmul gravity / fadd / fstp. Surviving hunks: an ebx/edi reload transposition at +0x159, a collision_flags/segment_time parameter-home swap, one 3-versus-2 x87 hunk at +0x21a and a consequent 3-byte alignment pad. Reopen only with a spelling that materialises the second x87 copy the way January does; do not replay operand or declaration sweeps. 2026-09-22 integration rebaseline: shared declaration context changed the normalized code hash while preserving the 944-byte envelope and all 49 relocations; similarity improves to 99.05674, with zero exact-row regressions. No new exact credit is claimed. 2026-09-24 R3 bipeds storage rebaseline: removing the four January file-static prototypes (biped_falling_danger, biped_update_airborne, biped_snap_facing, biped_update_moving) from units/bipeds.h changes only this TU's declaration context; the body returns to the Lane A wave A2 hash 5c03c751 (944 bytes, 49 relocations, objdiff 3.3.1 98.99645: the collision_flags/segment_time parameter-home swap reappears). Zero exact-row change in all 23 bipeds.h includers.", + "evidence": "Complete typed ballistic trajectory, world-collision, friendly-pill, and debug-recording reconstruction from January code/relocations and HCEA semantics. Target and candidate are both 944 padded bytes with all 49 relocations. Remaining differences are compiler-local x87 and independent instruction scheduling. No fake dependency, raw offset, forced inline, or nonsensical logic is retained. Zero exact credit. See docs/object_matching_logs/ai_obj_large_visibility_spatial_packet_20260909.md. 2026-09-20 Lane A re-baseline (zero exact credit): the recorded 250K-lane w3c 'b5' shape is rebuilt from this baseline and landed. Three changes: block-scope segment_time to the coordinate statement; parenthesise the linear term of the z row as (segment_time * arc_velocity.k + point.z); spell the post-call velocity update as (segment_end_time - segment_start_time) * gravity + arc_velocity.k. Instruction counts become 296/296 (HEAD was 292/296) and objdiff rises 94.50 to 98.99645. It reproduces January's x87 structure for segment_time exactly: fsubr of the parameter home at +0x1e7, fst (store-and-keep) to a dead parameter home at +0x1f4, and a post-call fld from that same home at +0x2cc feeding fmul gravity / fadd / fstp. Surviving hunks: an ebx/edi reload transposition at +0x159, a collision_flags/segment_time parameter-home swap, one 3-versus-2 x87 hunk at +0x21a and a consequent 3-byte alignment pad. Reopen only with a spelling that materialises the second x87 copy the way January does; do not replay operand or declaration sweeps. 2026-09-22 integration rebaseline: shared declaration context changed the normalized code hash while preserving the 944-byte envelope and all 49 relocations; similarity improves to 99.05674, with zero exact-row regressions. No new exact credit is claimed. 2026-09-24 R3 bipeds storage rebaseline: removing the four January file-static prototypes (biped_falling_danger, biped_update_airborne, biped_snap_facing, biped_update_moving) from units/bipeds.h changes only this TU's declaration context; the body returns to the Lane A wave A2 hash 5c03c751 (944 bytes, 49 relocations, objdiff 3.3.1 98.99645: the collision_flags/segment_time parameter-home swap reappears). Zero exact-row change in all 23 bipeds.h includers. 2026-09-27 type-ownership rebaseline (owner-approved RF-BE packet K: the hudg, itmc and netgame tag layouts consolidated into hud_definitions.h, item_definitions.h and scenario_definitions.h, hud_globals declared once in hud.h): ai.c is unchanged and sees only scenario_definitions.h, whose three added netgame block types shift this TU's C1 numbering by +23; the body returns to the 2026-09-22 integration hash ea5eb3a4 (944 bytes, 49 relocations, objdiff 3.3.1 99.05674, recorded at 4f4c8502), superseding the 2026-09-24 hash 5c03c751 / 98.99645. Zero exact-row change in the 467-unit sweeps at 04d57ab5 and 399a556b. No new exact credit; reopen criterion unchanged.", "measurements": { "target": { "size": 944, "relocation_count": 49, "normalized_sha256": "6c90076033e91f26356e42166cf4bb0a8d5a902ae35bc67db15aec19ee9982ac" }, - "base": { "size": 944, "relocation_count": 49, "normalized_sha256": "5c03c751c19c33cde8c6645c5fd39d505e2bca6bf161beb6e6126101f3fbcaa8" }, - "objdiff_percent": 98.99645 + "base": { "size": 944, "relocation_count": 49, "normalized_sha256": "ea5eb3a40fbddb9d60f2bcbfeaf6a207f59a2bafe156cff1cc65aee0406692ae" }, + "objdiff_percent": 99.05674 } }, { diff --git a/config/symbols.json b/config/symbols.json index f816b930..f0cd9ff0 100644 --- a/config/symbols.json +++ b/config/symbols.json @@ -22718,7 +22718,7 @@ { "file_offset": 3198336, "flags": 0, "name": "_global_collision_user_names" }, { "file_offset": 3198428, "flags": 0, "name": "_global_collision_log_enable" }, { "file_offset": 3198432, "flags": 0, "name": "_collision_usage_current_period" }, -{ "file_offset": 3198440, "flags": 0, "name": "_collision_fix_pill_offsets", "static": true }, +{ "file_offset": 3198440, "flags": 0, "name": "?offsets@?1??collision_fix_pill@@9@9", "static": true }, { "file_offset": 3198644, "flags": 0, "name": "_global_gravity" }, { "file_offset": 3198648, "flags": 0, "name": "_global_water_density" }, { "file_offset": 3198652, "flags": 0, "name": "_global_air_density" }, @@ -22988,8 +22988,8 @@ { "file_offset": 4449432, "flags": 0, "name": "_global_goal" }, { "file_offset": 4450456, "flags": 0, "name": "_global_variant" }, { "file_offset": 4450560, "flags": 0, "name": "_game_engine" }, -{ "file_offset": 4450564, "flags": 0, "name": "_game_engine_teleport_message_ticks", "static": true }, -{ "file_offset": 4450568, "flags": 0, "name": "_game_engine_teleport_flash_fade_function", "static": true }, +{ "file_offset": 4450564, "flags": 0, "name": "?blocked_message_delay@?1??game_engine_update_teleporter@@9@9", "static": true }, +{ "file_offset": 4450568, "flags": 0, "name": "?fade_function@?1??game_engine_update_teleporter@@9@9", "static": true }, { "file_offset": 4450572, "flags": 0, "name": "_global_autogenerate_list" }, { "file_offset": 4450576, "flags": 0, "name": "_global_autogenerate_count" }, { "file_offset": 4450580, "flags": 0, "name": "_ctf_globals", "static": true }, @@ -23063,15 +23063,15 @@ { "file_offset": 4541168, "flags": 0, "name": "_new_campaign_profile_name", "static": true }, { "file_offset": 4541192, "flags": 0, "name": "_single_player_level_data" }, { "file_offset": 4541272, "flags": 0, "name": "_persistant_game_data_info" }, -{ "file_offset": 4541536, "flags": 0, "name": "_displayed_servers", "static": true }, -{ "file_offset": 4541576, "flags": 0, "name": "_ui_widget_game_data_build_version_wide_string", "static": true }, +{ "file_offset": 4541536, "flags": 0, "name": "?displayed_servers@?1??server_list_menu_update@@9@9", "static": true }, +{ "file_offset": 4541576, "flags": 0, "name": "?build_number_string@?1??set_textbox_to_build_number@@9@9", "static": true }, { "file_offset": 4541704, "flags": 0, "name": "_result", "static": true }, { "file_offset": 4541712, "flags": 0, "name": "_virtual_keyboard_globals" }, { "file_offset": 4541816, "flags": 0, "name": "?time_of_last_tab@?1??virtual_keyboard_process_internal@@9@9", "static": true }, { "file_offset": 4541824, "flags": 0, "name": "_console_globals" }, { "file_offset": 4544324, "flags": 0, "name": "_console_dump_to_file" }, { "file_offset": 4544328, "flags": 0, "name": "_global_debug_key_down" }, -{ "file_offset": 4544336, "flags": 0, "name": "_window_storage", "static": true }, +{ "file_offset": 4544336, "flags": 0, "name": "?window@?1??main_pregame_render@@9@9", "static": true }, { "file_offset": 4544512, "flags": 0, "name": "_main_globals", "static": true }, { "file_offset": 4546080, "flags": 0, "name": "_debug_force_frame_rate_update" }, { "file_offset": 4546081, "flags": 0, "name": "_debug_no_drawing" }, @@ -23111,7 +23111,8 @@ { "file_offset": 4549888, "flags": 0, "name": "_telnet_console_globals" }, { "file_offset": 4550032, "flags": 0, "name": "_light_volume_globals", "static": true }, { "file_offset": 4550212, "flags": 0, "name": "_lightning_globals", "static": true }, -{ "file_offset": 4550216, "flags": 0, "name": "_damage_globals", "static": true }, +{ "file_offset": 4550216, "flags": 0, "name": "?default_damage_material@?1??object_cause_damage@@9@9", "static": true }, +{ "file_offset": 4550288, "flags": 0, "name": "_global_debug_damage_object_index", "static": true }, { "file_offset": 4550292, "flags": 0, "name": "_lights_game_globals" }, { "file_offset": 4550296, "flags": 0, "name": "_processed_bsp_flags", "static": true }, { "file_offset": 4550300, "flags": 0, "name": "_object_name_list", "static": true }, @@ -23263,7 +23264,7 @@ { "file_offset": 4982004, "flags": 0, "name": "_debug_inactive_objects" }, { "file_offset": 4982005, "flags": 0, "name": "_reported_rendered_object_overflow", "static": true }, { "file_offset": 4982008, "flags": 0, "name": "_render_sky_globals", "static": true }, -{ "file_offset": 4982040, "flags": 0, "name": "_build_sprite_vertex_allocation_failure_reported", "static": true }, +{ "file_offset": 4982040, "flags": 0, "name": "?warned@?1??build_sprite_get_group@@9@9", "static": true }, { "file_offset": 4982048, "flags": 0, "name": "_bss_004c0520" }, { "file_offset": 4982936, "flags": 0, "name": "_numeric_countdown_timer_milliseconds" }, { "file_offset": 4982940, "flags": 0, "name": "_numeric_countdown_timer_on" }, diff --git a/docs/object_matching_logs/astra_claude_type_static_reconciliation_20260927.md b/docs/object_matching_logs/astra_claude_type_static_reconciliation_20260927.md new file mode 100644 index 00000000..a9d54bff --- /dev/null +++ b/docs/object_matching_logs/astra_claude_type_static_reconciliation_20260927.md @@ -0,0 +1,123 @@ +# Claude type, static-local and disclosure reconciliation — 2026-09-27 + +Canonical baseline: `a2c73dd8997050e0ecd3ea4691a220ff41d1b258`. +This is an independent, zero-new-credit reconciliation of the completed +packets identified by the owner. The active donor worktree was not modified. +Only the frozen commits below were considered; no moving-tip merge was used. + +## Included + +- `03933e26`: the required game_engine storage prerequisite. Replace the + invented aggregate with the separately evidenced debug global and teleporter + static locals; rename exactly the two corresponding symbol rows. The later + PDBs establish names/types/function scope, not every lexical placement. The + playlist declaration placement remains explicitly inferred. +- `ba7d126f` (K): consolidate the HUD, item-collection and netgame types into + their existing owner headers and remove the incompatible local views. + Rebaseline only the approved ballistic-line-of-fire park, preserving its + history. Its fresh 944-byte / 49-relocation hash is `ea5eb3a4...06692ae`, + matching the donor measurement. It remains residual and earns no credit. +- `1d0e5c58`, `1bd50a79`: OQ-4 P-a and P-b1, after K. Restore the attested + 148-byte window_data view; give rasterizer_lights one complete type and + owning-header extern. No COMMON definition is added. P-b2 through P-b4 are + not included. +- `45070362`, `12fa21bb`, `944b6c27`, `a168f366`: the four remaining approved + static-local packets in game_data_input, main, damage and render_sprite, + together with their five symbol renames and one damage-index symbol row. + Natural block placement and the demo-only damage-index name are disclosed. + The game-data BSS repair places the server array at +0 and the build string + at +0x28, as January does, instead of the inherited reversed ordering. +- `8b94691e`: 48 source-policy disclosure blocks in 37 files. These comments + document existing behavior; they do not approve the underlying reachable UB, + change byte credit, lift a hold or certify another object. + +`f14b19c6` was not repeated: canonical `a567739b` already contains the +collisions static-local repair and its independently verified symbol row. +Canonical's provenance wording is retained. + +Only exact patch hunks were reconciled. In particular, unrelated existing +global_window_parameters externs, the current hs ABI, king storage, and the +render_sprite string-table name were not replaced with donor whole files. + +## G and game_engine admission do not pass on canonical + +The complete `7663fc1a` G packet, without the unattested HUD macro, was applied +and rebuilt after storage + K. It changed the strict board from 7,641 to +7,640 exact rows: `_populate_statistic_buffer` (560 padded bytes) alone became +residual. No debit was authorized for this reconciliation. + +G was therefore removed in full; the `57596ff7` Matching flip was never +applied. game_engine remains NonMatching, despite its already-exact functions +and data. This is the conditional source/admission ruling, not a rejection of +the independently justified K correction. + +The subsequent OQ/static/comment packets touch none of G's compiler-source +dependency closure (103 current dependencies; 115 in the conservative G +overlay). They supply no changed-input reason to expect a different G result. +This dependency check is not a second compiled success/failure receipt: the +first failed G build/snapshot is preserved, but its full object/input archive +was not captured. No declaration-count or symbol-name tuning was attempted. +Reopen G only on new independently justified context/source evidence, then +require a fresh full sweep and 180/180 before admission. + +The new upstream PR62 nav-point candidate also remains in scratch at zero +credit; its load-bearing same-type cast has no new source-policy approval. +Claude's still-running bitmap, COMMON, main-header, library and debit packets +are outside this batch. + +## Independent verification + +- Full configured build/progress/report generation passes, with objdiff + **3.3.1 unchanged**. Storage + K, the additional type/static packets and the + final combined tree each retain all inherited exact rows. +- Stable whole-board sweep: **8,252 rows / 7,641 exact; zero gains, zero + losses**. No new Halo code or data credit is claimed. +- Parks **71 active / 0 stale / 0 invalid**. Admission audit **12 candidates, + 0 contradicted, 1 rejected, 0 revoked**. Fake scan retains the same **26** + inherited leads. Whitespace check passes. +- Tests: **1,161 passed / 5 skipped / 26 subtests**. The initial baseline test + invocation could not access pytest's default external temp directory; the + baseline and final suite both passed using separate workspace temp roots, + without changing tests, assertions or skips. Both receipts are retained. +- Focused game_engine audit: **263/263 January sections, 269/269 symbols**, PDB + storage and BSS layout pass; all **192** BSS references agree. All **39** + surplus definitions match January and current providers. Fourteen provider + pairs pass **28** both-order duplicate-definition probes. These are bounded + diagnostic links, not a complete executable link or boot test. The inherited + ANY-versus-synthetic-NODUP selection differences and `.drectve` are unchanged. +- Nine OQ/static consumer TUs: **999 nondebug sections** checked. No added or + removed sections, new COMMON, changed surplus helper, or selection/alignment + change. The six static symbol/offset corrections agree with the fresh split. + Damage's new scalar symbol replaces aggregate+0x48 references with scalar+0, + preserving resolved addresses. GDI has the intended relocation/layout repair. +- Fresh `/W3` builds using a frozen pre-K source/header tree and final tree + show identical warning multisets for those nine TUs. game_engine changes + **21 -> 23** warnings: exactly the two disclosed C4244 long-to-short + assignments for the attested fade_function and screen_flash_type locals. + No unexplained warning is introduced; default production warnings do not rise. +- Comment-only rebuild proof: **622/622** saved/current objects have identical + nondebug contents, flags, relocations and symbol/auxiliary records. The check + covers 23,889 sections, 103,494 relocation records and 65,635 symbols, + including 79 COMMON records. All 35 line-sensitive source uses preserve their + logical file/line locations. Debug/timestamp differences receive no credit. + +## Totals and publication boundary + +- Halo meaningful code: **1,598,242 / 1,770,166 (90.29%)**. +- Halo accepted functions: **7,469 / 7,574**. +- Halo complete objects: **390 / 468**, unchanged by this batch. +- Halo credited data: **2,588,903**, unchanged. + +The publication range also includes canonical's previously verified +`a567739b`, `a8b2512d` and `a2c73dd8` (static-local repair, path-obstacle +admission, and held object_lights evidence). Their credit is not counted twice. +Previously completed function work through `ef79aeda` was already present on +both remote exact-pilots branches at intake. + +All focused reports, negative G receipts, snapshots, comparison scripts, +compiler/linker logs and input seals remain under +`scratch/astra_reconcile_packets_20260927/`. They are not publication payload. +Only verified source/configuration and this ledger are committed. Inherited +README edits, unrelated research, and private compiler/game/PDB assets remain +untouched. Publish the two authorized jonas/exact-pilots branches and merge +into halo-1 main while preserving its existing README and history; no force. diff --git a/docs/object_matching_logs/astra_collisions_static_local_20260927.md b/docs/object_matching_logs/astra_collisions_static_local_20260927.md new file mode 100644 index 00000000..54b28658 --- /dev/null +++ b/docs/object_matching_logs/astra_collisions_static_local_20260927.md @@ -0,0 +1,64 @@ +# Collisions static-local reconciliation, 2026-09-27 + +Baseline: `ef79aedaba16f9d38f61666041e62e57fad34140`. +Scope: the owner-approved RF-BF `offsets` packet only. Zero new code/data credit +and no object admission. The donor worktree was not modified. + +## Source evidence and implementation + +The 2003 PC demo and HCEX PDB dumps independently record the same static local: +`union real_vector3d offsets[0x11]`, owned by `collision_fix_pill` (demo RVA +`0x293c18`, HCEX RVA `0x1479060`). January corroborates a 204-byte initialized +array at file offset `3198440`, with its only code reference in that function. +The later PDBs establish name, type and function scope, not the exact position +of the declaration within the block. The source comment discloses that limit. + +Move the unchanged initializer from file scope to the function's natural +declaration block, rename its two uses to `offsets`, and change one existing +`symbols.json` row to `?offsets@?1??collision_fix_pill@@9@9`. No new symbol, +initializer, padding, helper, header or compiler setting is introduced. + +Donor evidence: `claude-remaining-frontier-20260926`'s +`research/remaining_frontier_20260926/workers/RF-BF/`, specifically the original +PDB extracts E1, January references E2, prospective card C01 and the collisions +patch. The 2026-09-27 owner ruling admits this storage-form correction only if +fresh gates preserve existing exact rows. No scope/name tuning was performed. + +## Fresh canonical checks + +- Full `ninja all_source progress build/report.json` passes with the unchanged + objdiff 3.3.1 scorer and normal split regeneration. +- All 20 collisions functions remain strict exact, including the newly exact + `collision_move_point` (4,752 padded bytes). +- Stable board: 8,252 owner rows, 7,641 exact; zero gains and zero losses. +- All 42 January-owned sections and 44 symbols pass identity, flags, + alignment, offsets, storage and relocation checks after the rename. +- All 40 surplus code/data sections match January's selected and current + providers; no COMMON, new surplus, or ownership exception. All 32 two-order + provider probes pass duplicate-definition checks. They are not a full game + link; unresolved external diagnostics are expected in these probes. +- Parks 71 active / 0 stale / 0 invalid; admission 13 candidates / 0 + contradicted / 1 rejected / 0 revoked; fake-scan leads unchanged at 26. +- Tests: 1,161 passed / 5 skipped / 26 subtests. `git diff --check` clean. +- Halo meaningful credit remains 1,598,242 / 1,770,166; objects remain 389/468. + +Receipts are under `scratch/astra_object_closeout_20260927/`: `gates/`, +`collisions_static_probe/`, `collisions_static_final/`, `collisions_bytes/`, +and `collisions_policy/`. The final audit binds current source, objects, config, +tools and providers by hashes, with a successful end-of-run input recheck. + +## Whole-object admission remains held + +Byte identity is not sufficient to certify the entire source. Independent +policy review found nine inherited `COLLISION_POINT_FROM_LINE3D` hand-expanded +sites and the separately held radius/component parentheses. Their existing +function-level credit is not newly approved or revoked by this packet. + +Fresh bounded probes on the static-local form: restoring the genuine helper +alone leaves 19/20 exact (loses `collision_move_point`); stripping the two +decorative operand parentheses leaves 18/20; combining both leaves 17/20. +The genuine helper's extra COMDAT is identical and links against its provider +in both orders, but that does not authorize its nonexact caller. No probe is +landed, and no status flip is made. Preserve those candidates and receipts +under `collisions_helpers/`; do not repeat the same controls without new +source evidence or an applicable ruling. diff --git a/docs/object_matching_logs/astra_object_lights_selection_review_20260927.md b/docs/object_matching_logs/astra_object_lights_selection_review_20260927.md new file mode 100644 index 00000000..adb7386a --- /dev/null +++ b/docs/object_matching_logs/astra_object_lights_selection_review_20260927.md @@ -0,0 +1,63 @@ +# Object lights: provider-selection review remains held + +Canonical reviewed: `a8b2512d630b88fa219e09729bbdc7c76e23a516`. +Donor admission not applied: `6bfd934f5ac14ee1535d1f1a327f5e7d2d98f1e7`. +Zero source/config changes and zero credit from this review. + +The owner permits the one `_object_get_bounding_sphere` exception only if its +sole differences are authenticated `__FILE__` targets and the intended link +demonstrably discards this copy, retaining a January-identical provider. +Two-order duplicate-definition checks alone are explicitly insufficient. + +## What the donor actually established + +RF-BG establishes January's provider and a reproducible selection mechanism. +Its controlled link orders Halo inputs by descending January module index; +the linker selects action_vehicle, while swapping the contested objects +selects object_lights. The selected bytes and file-literal references were +inspected, not inferred solely from linker success. + +However, the full-input diagnostic image used `/FORCE:MULTIPLE` for two other +duplicate definitions and a synthetic stub object defining 472 unresolved +names. These qualifications appear in RF-BG's report/notes but are absent from +the proposed admission commit's description and semantic-data reason. That +image is a controlled selection experiment, not an unmodified production link. +No image was executed during this review. + +## Current canonical checks + +The independent read-only audit found all 65 January-owned nondebug sections +and 71 symbols exact in object_lights, including flags, relocation identities, +offsets and storage. All 99 nondebug sections and 104 definitions compared +against the donor proof object are unchanged. + +The current checked-in `tools/link_probe.py` is an opt-in diagnostic, not a +default build/link recipe. It consumes manifest order, not RF-BG's constructed +descending order, and prohibits `/FORCE` and dummy functions. In that manifest +the earliest `_object_get_bounding_sphere` provider is vehicles (index 35), +whose copy is January-identical. The other seven non-object_lights providers +are also identical. Therefore, a different provider module name is **not** a +byte mismatch or a reason by itself to reject the exception. + +The unclosed requirement is a verified current intended-link contract and its +selected output. The default build compiles/splits/reports objects and does not +establish that executable-link contract. Neither a constructed diagnostic order +nor hypothetical first-provider reasoning is reported as an executed final +link. The donor experiment remains useful evidence, not discarded work. + +## Disposition and next action + +Keep object_lights NonMatching and its existing function/data credit unchanged. +Do not import the donor status flip or remove the data entry's incomplete-unit +qualification yet. No other COMDAT policy changes. + +Reopen after establishing the intended link recipe/order and verifying on +current inputs that a January-identical helper is selected, the exceptional +copy is discarded, and the resulting literal references agree. Any use of +forced duplicate resolution or unresolved-symbol stubs must be disclosed and +kept separate from production-link claims; a further owner decision may choose +to accept a suitably bounded diagnostic proof instead. + +Independent receipts and exact comparisons are preserved in +`scratch/astra_object_closeout_20260927/object_lights/`. Donor RF-BG proof, +controls and limitations remain untouched in its worktree. diff --git a/docs/object_matching_logs/astra_path_obstacle_avoidance_admission_20260927.md b/docs/object_matching_logs/astra_path_obstacle_avoidance_admission_20260927.md new file mode 100644 index 00000000..b198ad4b --- /dev/null +++ b/docs/object_matching_logs/astra_path_obstacle_avoidance_admission_20260927.md @@ -0,0 +1,71 @@ +# Path obstacle avoidance admission, 2026-09-27 + +Canonical baseline: `a567739bfc8e363e846669095f1dbdd542d902a0` (the preceding +collisions static-local repair; code-identical to `ef79aeda`). Reconciles only +the source-comment portion of donor `cb25c573e477d1bf92555b965a1b076a8ed094a3` +and the status row from `6d9f88550e6e0aa8bd91fe0369229df9d91dcafa`. + +## Authority and scope + +The 2026-09-27 Q-A3-1 ruling admits this object with the two names +`debug_path` and `debug_obstacles` explicitly disclosed as descriptive, not +recovered. It requires January address/layout ownership evidence independent +of those labels. This is not a general waiver for unnamed globals. + +The twelve obsolete address-based names in the source's symbol-list comment +now use the real identifiers already in production and `symbols.json`. +The BSS comment and definition comment disclose the two inferred names. +No executable source, shared header, symbol configuration, compiler flag, +scorer, ABI or helper emission changes. The older held A3 code-shape patch is +not imported. Only this object's status becomes `Matching`. + +## Independent current-object evidence + +- All 24 functions are strict exact; all 49 January-owned sections and 52 + symbols pass bytes, relocations, sizes, alignment, flags, offsets and storage. +- The 0x2142-byte BSS is verified without comparing private identifier text: + static objects at +0 and +0x1538, public flags at +0x2140 and +0x2141; + all 15 referencing code relocations resolve identically. The two copy sizes + and multi-function uses corroborate types and file scope. A label-renaming + control still passes; an altered-addend and unrelated-object control fail. +- The source changes compile to identical nondebug sections and symbol + records. Only scratch output-path debug metadata differs. Warning multisets + are unchanged: 12 at /W3 and 51 at /W4. +- All 21 surplus code/data COMDATs (15 code, six data) match both January's + selected and current providers. No COMMON. Five provider pairs pass all ten + duplicate-definition probes in both orders. These unresolved-only probes + are bounded link-collision evidence, not a complete executable link. +- January's synthetic split models `_obstacles_get_disc` and + `_valid_real_point2d` with selection 1, while our inherited identical shared + inline copies have selection ANY (2). No selection field changed in this + packet. Provider identity and duplicate tests are recorded, not inferred + merely from equal function bytes. + +The unchanged `error_heap` local real/long union was explicitly retained by +the 2026-09-08 owner reconciliation and cited as an existing accepted form in +the 2026-09-15 wind ruling. January directly reads the same spilled real as +integer bits and as a floating value for the hexadecimal/decimal diagnostic. +This packet neither introduces the union nor uses Q-A3-1 to waive an unrelated +hold. The later A3 confirmation question and the existing provenance are +recorded in the independent report. Its six existing argument views likewise +remain under their recorded per-site attestation and byte-inert controls. + +## Full canonical gate + +- `ninja all_source progress build/report.json` passes, objdiff 3.3.1 unchanged. +- 8,252 stable owner rows / 7,641 exact: zero gains, zero losses. +- Parks: 71 active, zero stale or invalid. +- Admission: 12 candidates, zero contradicted, one rejected, zero revoked. +- Fake-match scan: unchanged 26 inherited leads. +- Tests: 1,161 passed, five skipped, 26 subtests. Diff whitespace check clean. +- Halo complete objects: **389 -> 390 / 468**. +- Halo meaningful code unchanged: **1,598,242 / 1,770,166**, 7,469 accepted + functions. Halo credited data unchanged at **2,588,903**. No new byte credit. + +Focused receipts: `scratch/astra_object_closeout_20260927/path_obstacle_avoidance/`. +Full gates: `scratch/astra_object_closeout_20260927/gates/path_*`. +The independent report includes exact owner-ruling citations, the preserved +failed harness control, all input/provider hashes and final integration checks. + +No donor worktree was changed. Inherited README edits and unrelated research +remain outside this commit. Publication is separate from this local admission. diff --git a/source/ai/action_vehicle.c b/source/ai/action_vehicle.c index 0736dca8..131bfd63 100644 --- a/source/ai/action_vehicle.c +++ b/source/ai/action_vehicle.c @@ -697,6 +697,13 @@ static short action_vehicle_find_impromptu_seat( } } + /* BUG (preserved for exact matching): when no seat qualifies, best_seat_index stays + * NONE and the three copies below store the never-assigned best_* locals (January + * 0x40a1b0 +0xe2..+0x11d copies them with plain dword moves). Reachable whenever no + * seat qualifies; the only caller, action_vehicle_setup_impromptu, reads the outputs + * only when the returned seat index is not NONE. A corrected build should copy them + * only when best_seat_index != NONE. Source-policy approval pending (2026-09-27 audit). + */ if (entry_point) { *entry_point = best_entry_point; diff --git a/source/ai/actions.c b/source/ai/actions.c index 2c996930..7daaff5d 100644 --- a/source/ai/actions.c +++ b/source/ai/actions.c @@ -4440,6 +4440,13 @@ static boolean actor_action_find_escape_from_danger( system_exit(-1); } + /* BUG (preserved for exact matching): alignment_vector is assigned only when the + * unit's dive_distance is positive; otherwise it is stored below unassigned (January + * 0x40c970 +0x386..+0x38f). Reachable for any unit whose dive distance is not + * positive; escape_direction is then NONE, and the only caller, + * actor_action_handle_danger_avoidance, leaves that block without reading the vector. + * A corrected build should store a defined vector on that path. Source-policy + * approval pending (2026-09-27 audit). */ *escape_direction_reference = escape_direction; *escape_distance_reference = evade_distance; *escape_is_ledge_reference = selected_is_ledge; diff --git a/source/ai/actor_looking.c b/source/ai/actor_looking.c index ce714d1c..1e2483f7 100644 --- a/source/ai/actor_looking.c +++ b/source/ai/actor_looking.c @@ -847,6 +847,10 @@ static long actor_look_idle_timer( time_lower_bound = looking_definition->idle_look_time_lower_bound; time_upper_bound = looking_definition->idle_look_time_upper_bound; break; + /* time_lower_bound and time_upper_bound are left unassigned only by this default arm. Not reached unassigned: the + * arm's assertion failure calls system_exit, which does not return in January + * (0x47c960 jumps to halt_and_catch_fire 0x4f21c0, which loops or calls exit). + * Source-policy approval pending (2026-09-27 audit). */ default: match_vassert( "c:\\halo\\SOURCE\\ai\\actor_looking.c", diff --git a/source/ai/actor_perception.c b/source/ai/actor_perception.c index c99fc681..85d2e7b8 100644 --- a/source/ai/actor_perception.c +++ b/source/ai/actor_perception.c @@ -1623,6 +1623,10 @@ void actor_situation_update_target_status( (target_prop->definitely_located != FALSE) + 5; break; + /* target_type is left unassigned only by this default arm. Not reached unassigned: the + * arm's assertion failure calls system_exit, which does not return in January + * (0x47c960 jumps to halt_and_catch_fire 0x4f21c0, which loops or calls exit). + * Source-policy approval pending (2026-09-27 audit). */ default: display_assert( NULL, @@ -6685,6 +6689,10 @@ void actor_perception_update( awareness_delta = 1.0f; break; + /* awareness_delta is left unassigned only by this default arm. Not reached unassigned: the + * arm's assertion failure calls system_exit, which does not return in January + * (0x47c960 jumps to halt_and_catch_fire 0x4f21c0, which loops or calls exit). + * Source-policy approval pending (2026-09-27 audit). */ default: #line 516 "c:\\halo\\SOURCE\\ai\\actor_perception.c" assert(!"unreachable"); diff --git a/source/ai/encounters.c b/source/ai/encounters.c index 1e2e1da4..fe6b46da 100644 --- a/source/ai/encounters.c +++ b/source/ai/encounters.c @@ -2200,6 +2200,10 @@ void encounter_create( case _game_difficulty_level_impossible: count = squad_definition->max_count; break; + /* count is left unassigned only by this default arm. Not reached unassigned: the + * arm's assertion failure calls system_exit, which does not return in January + * (0x47c960 jumps to halt_and_catch_fire 0x4f21c0, which loops or calls exit). + * Source-policy approval pending (2026-09-27 audit). */ default: match_vassert("c:\\halo\\SOURCE\\ai\\encounters.c", 1730, FALSE, NULL); } diff --git a/source/ai/path_obstacle_avoidance.c b/source/ai/path_obstacle_avoidance.c index 3f253a0d..571ce6a0 100644 --- a/source/ai/path_obstacle_avoidance.c +++ b/source/ai/path_obstacle_avoidance.c @@ -19,33 +19,33 @@ symbols in this file: 0004E870 0060: _heap_cost (0000) 0004E8D0 00d0: - _code_0004e8d0 (0000) + _error_heap (0000) 0004E9A0 01b0: - _code_0004e9a0 (0000) + _heap_verify (0000) 0004EB50 0190: - _code_0004eb50 (0000) + _heap_up (0000) 0004ECE0 02a0: - _code_0004ece0 (0000) + _heap_down (0000) 0004EF80 0060: - _code_0004ef80 (0000) + _heap_insert (0000) 0004EFE0 0070: - _code_0004efe0 (0000) + _heap_remove (0000) 0004F050 0260: _render_debug_path (0000) 0004F2B0 0040: _valid_real_point2d (0000) 0004F2F0 0220: - _code_0004f2f0 (0000) + _path_add_step (0000) 0004F510 01e0: - _code_0004f510 (0000) + _path_new (0000) 0004F6F0 0200: - _code_0004f6f0 (0000) + _path_test_pill2d (0000) 0004F8F0 0330: - _code_0004f8f0 (0000) + _path_add_steps (0000) 0004FC20 0130: - _code_0004fc20 (0000) + _path_iterate (0000) 0004FD50 0070: - _code_0004fd50 (0000) + _path_find (0000) 0004FDC0 0550: _path_avoid_obstacles (0000) 00050310 00e0: @@ -99,7 +99,8 @@ symbols in this file: 0024E8D0 0030: ??_C@_0DA@BINHGJIJ@input_step_count?5?$DM?$DN?5MAXIMUM_SMOO@ (0000) 00319D08 2142: - _bss_00319d08 (0000) + _debug_path (0000) + _debug_obstacles (1538) _debug_obstacle_path_on_failure (2140) _debug_obstacle_path (2141) */ @@ -219,7 +220,11 @@ static boolean path_find( /* ---------- globals */ /* the failing search copied out by path_avoid_obstacles for - * render_debug_obstacle_path to replay */ + * render_debug_obstacle_path to replay. + * the names debug_path and debug_obstacles are descriptive, not recovered: no + * first-party record names these two file statics (the feature is debug-only and + * compiled out of every build whose symbols record statics). their storage, types + * and January offsets (+0, +0x1538 of 0x00319D08) are January-proven. */ static struct obstacle_path debug_path; static struct obstacles debug_obstacles; diff --git a/source/ai/path_structure_bsp.c b/source/ai/path_structure_bsp.c index 072a33e0..69e35a43 100644 --- a/source/ai/path_structure_bsp.c +++ b/source/ai/path_structure_bsp.c @@ -641,6 +641,17 @@ boolean structure_test_pill2d( best_result = NULL; } + /* BUG (preserved for exact matching): a side whose p0 surface index is NONE gets only + * its collision flag, so when p0_surface_index is NONE the copy below returns + * left_result's point, surface_index, edge_index and t unassigned (January 0x452500 + * writes only the byte [ebp-0x4c] at +0x189 and copies seven dwords from [ebp-0x4c] + * at +0x24f..+0x25a), and the function returns FALSE. actor_move_try_evasion_vector + * passes the actor's pathfinding surface as p0 and, on a FALSE return, reads + * result->point.z to accept or reject the evasion point; actor_find_pathfinding_location + * leaves that surface NONE for a non-flying actor when no ground surface is found or + * when the actor's vehicle is not a ground vehicle. A runtime occurrence was not + * traced. A corrected build should fill both side results before selecting. + * Source-policy approval pending (2026-09-27 audit). */ if (!best_result || distance_squared2d((real_point2d const *)&best_result->point, p1) < radius * radius) { diff --git a/source/bitmaps/bitmap_drawing.c b/source/bitmaps/bitmap_drawing.c index 9cbde4ef..aaf9dd6a 100644 --- a/source/bitmaps/bitmap_drawing.c +++ b/source/bitmaps/bitmap_drawing.c @@ -396,6 +396,10 @@ void bitmap_fill_rectangle( mode = (alpha != 255) ? _bitmap_fill_blend_r5g6b5 : _bitmap_fill_write_16bit; break; + /* mode and pixel are left unassigned only by this default arm. Not reached unassigned: the + * arm's assertion failure calls system_exit, which does not return in January + * (0x47c960 jumps to halt_and_catch_fire 0x4f21c0, which loops or calls exit). + * Source-policy approval pending (2026-09-27 audit). */ default: match_vassert( "c:\\halo\\SOURCE\\bitmaps\\bitmap_drawing.c", @@ -1069,6 +1073,10 @@ void bitmap_draw_line( mode = (alpha != 255) ? _bitmap_pixel_blend_a8r8g8b8 : _bitmap_pixel_write_32bit; break; + /* mode and pixel are left unassigned only by this default arm. Not reached unassigned: the + * arm's assertion failure calls system_exit, which does not return in January + * (0x47c960 jumps to halt_and_catch_fire 0x4f21c0, which loops or calls exit). + * Source-policy approval pending (2026-09-27 audit). */ default: match_vassert( "c:\\halo\\SOURCE\\bitmaps\\bitmap_drawing.c", diff --git a/source/bitmaps/bitmap_extract.c b/source/bitmaps/bitmap_extract.c index 901aacac..1cc0e3d6 100644 --- a/source/bitmaps/bitmap_extract.c +++ b/source/bitmaps/bitmap_extract.c @@ -1450,6 +1450,10 @@ struct bitmap_data *extract_build_debug_plate( case _bitmap_type_cube_map: slice_count = 6; break; + /* slice_count is left unassigned only by this default arm. Not reached unassigned: the + * arm's assertion failure calls system_exit, which does not return in January + * (0x47c960 jumps to halt_and_catch_fire 0x4f21c0, which loops or calls exit). + * Source-policy approval pending (2026-09-27 audit). */ default: match_vassert( "c:\\halo\\SOURCE\\bitmaps\\bitmap_extract.c", @@ -1522,6 +1526,10 @@ struct bitmap_data *extract_build_debug_plate( case _bitmap_type_cube_map: mipmap_slice_count = 6; break; + /* mipmap_slice_count is left unassigned only by this default arm. Not reached unassigned: the + * arm's assertion failure calls system_exit, which does not return in January + * (0x47c960 jumps to halt_and_catch_fire 0x4f21c0, which loops or calls exit). + * Source-policy approval pending (2026-09-27 audit). */ default: match_vassert( "c:\\halo\\SOURCE\\bitmaps\\bitmap_extract.c", diff --git a/source/bitmaps/bitmap_utilities.c b/source/bitmaps/bitmap_utilities.c index d0ef0859..62ccec09 100644 --- a/source/bitmaps/bitmap_utilities.c +++ b/source/bitmaps/bitmap_utilities.c @@ -2453,6 +2453,10 @@ struct rgb_color *hsv_color_to_rgb_color( } } + /* The sector switch has no default. Not reached unassigned: for a word hue, + * scaled_hue = hue * 6 / 65536 is at most 393210 / 65536 < 6 (exact in real), so + * sector is 0..5 and each of those cases assigns red, green and blue. Source-policy + * approval pending (2026-09-27 audit). */ rgb->red = (word)(long)(red * 65535.0f); rgb->green = (word)(long)(green * 65535.0f); rgb->blue = (word)(long)(blue * 65535.0f); diff --git a/source/cache/cache_files_windows.c b/source/cache/cache_files_windows.c index dc517c64..745c2045 100644 --- a/source/cache/cache_files_windows.c +++ b/source/cache/cache_files_windows.c @@ -848,6 +848,10 @@ short cache_files_precache_map_status( status = _cached_map_file_success; break; + /* status is left unassigned only by this default arm. Not reached unassigned: the + * arm's assertion failure calls system_exit, which does not return in January + * (0x47c960 jumps to halt_and_catch_fire 0x4f21c0, which loops or calls exit). + * Source-policy approval pending (2026-09-27 audit). */ default: match_vassert("c:\\halo\\SOURCE\\cache\\cache_files_windows.c", 1013, FALSE, NULL); break; @@ -1218,6 +1222,10 @@ static short cached_map_files_find_free_map( last_map_file_index = 2; break; + /* first_map_file_index and last_map_file_index are left unassigned only by this default arm. Not reached unassigned: the + * arm's assertion failure calls system_exit, which does not return in January + * (0x47c960 jumps to halt_and_catch_fire 0x4f21c0, which loops or calls exit). + * Source-policy approval pending (2026-09-27 audit). */ default: match_vassert("c:\\halo\\SOURCE\\cache\\cache_files_windows.c", 1172, FALSE, NULL); break; diff --git a/source/cutscene/cinematics.c b/source/cutscene/cinematics.c index 4bfdeb70..43e41ba9 100644 --- a/source/cutscene/cinematics.c +++ b/source/cutscene/cinematics.c @@ -62,6 +62,8 @@ symbols in this file: #include "game/game.h" #include "game/game_globals.h" #include "game/players.h" +#include "interface/hud.h" +#include "interface/hud_definitions.h" #include "interface/ui_widget.h" #include "items/projectiles.h" #include "rasterizer/rasterizer.h" @@ -103,14 +105,6 @@ struct scenario_cutscene_title byte unused50[0x10]; }; -struct hud_global_data -{ - byte unused000[0x54]; - long single_player_font_index; - byte unused058[0x284]; - rectangle2d default_title_bounds; -}; - typedef char verify_scenario_cutscene_title_size[ sizeof(struct scenario_cutscene_title) == 0x60 ? 1 : -1]; typedef char verify_scenario_cutscene_title_name_offset[ @@ -120,9 +114,9 @@ typedef char verify_scenario_cutscene_title_bounds_offset[ typedef char verify_scenario_cutscene_title_fade_offset[ offsetof(struct scenario_cutscene_title, fade_in_time) == 0x44 ? 1 : -1]; typedef char verify_hud_global_single_player_font_offset[ - offsetof(struct hud_global_data, single_player_font_index) == 0x54 ? 1 : -1]; + offsetof(struct hud_globals_definition, messaging.single_player_font.index) == 0x54 ? 1 : -1]; typedef char verify_hud_global_default_title_bounds_offset[ - offsetof(struct hud_global_data, default_title_bounds) == 0x2DC ? 1 : -1]; + offsetof(struct hud_globals_definition, defaults.default_title_bounds) == 0x2DC ? 1 : -1]; /* ---------- prototypes */ @@ -132,7 +126,6 @@ void draw_quad( /* ---------- globals */ -extern struct hud_global_data *hud_globals; struct cinematic_global_data *cinematic_globals = NULL; /* ---------- public code */ @@ -384,7 +377,7 @@ void cinematic_render( if (active_title->title_index == NONE) continue; - font_index = hud_globals->single_player_font_index; + font_index = hud_globals->messaging.single_player_font.index; if (font_index == NONE) continue; @@ -411,7 +404,7 @@ void cinematic_render( if (title_bounds->x1 == title_bounds->x0 || title_bounds->y1 == title_bounds->y0) { - title_bounds = &hud_globals->default_title_bounds; + title_bounds = &hud_globals->defaults.default_title_bounds; } if (!game_in_editor()) diff --git a/source/cutscene/recorded_animation_playback.c b/source/cutscene/recorded_animation_playback.c index e093607a..d7f31077 100644 --- a/source/cutscene/recorded_animation_playback.c +++ b/source/cutscene/recorded_animation_playback.c @@ -411,6 +411,10 @@ boolean recorded_animation_apply_event_stream( time_delta>UNSIGNED_CHAR_MAX); break; + /* time_delta is left unassigned only by this default arm. Not reached unassigned: the + * arm's assertion failure calls system_exit, which does not return in January + * (0x47c960 jumps to halt_and_catch_fire 0x4f21c0, which loops or calls exit). + * Source-policy approval pending (2026-09-27 audit). */ default: match_assert( "c:\\halo\\SOURCE\\cutscene\\recorded_animation_playback.c", diff --git a/source/devices/device_controls.c b/source/devices/device_controls.c index 4e32e854..a4441736 100644 --- a/source/devices/device_controls.c +++ b/source/devices/device_controls.c @@ -188,6 +188,10 @@ static void code_00083e30( case 3: desired_value= definition->control.call_value; break; + /* desired_value is left unassigned only by this default arm. Not reached unassigned: the + * arm's assertion failure calls system_exit, which does not return in January + * (0x47c960 jumps to halt_and_catch_fire 0x4f21c0, which loops or calls exit). + * Source-policy approval pending (2026-09-27 audit). */ default: display_assert( NULL, diff --git a/source/game/game_engine.c b/source/game/game_engine.c index f22915a5..2a1c4dca 100644 --- a/source/game/game_engine.c +++ b/source/game/game_engine.c @@ -547,11 +547,14 @@ symbols in this file: #include "bitmaps/bitmap_group.h" #include "game_globals.h" #include "interface/interface.h" +#include "interface/hud.h" +#include "interface/hud_definitions.h" #include "interface/hud_messaging.h" #include "interface/terminal.h" #include "interface/ui_widget.h" #include "input/input.h" #include "items/equipment_definitions.h" +#include "items/item_definitions.h" #include "items/weapon_definitions.h" #include "items/weapons.h" #include "main/main.h" @@ -584,8 +587,8 @@ enum /* ---------- macros */ -#define game_engine_postgame_hud_definition_get(index) \ - ((struct game_engine_postgame_hud_definition *)tag_get('hudg', (index))) +#define hud_globals_definition_get(index) \ + ((struct hud_globals_definition *)tag_get('hudg', (index))) #define item_collection_definition_get(index) \ ((struct item_collection_definition *)tag_get( \ ITEM_COLLECTION_DEFINITION_TAG, \ @@ -633,40 +636,26 @@ struct rasterizer_debug_options short postgame_player_list_debug; }; -struct game_engine_hud_globals -{ - byte unused00[0x54]; - long no_local_player_message_font_index; - byte unused58[0xC]; - long local_player_message_font_index; -}; - union game_engine_update_iterator { struct data_iterator data; struct object_iterator object; }; -struct game_engine_postgame_hud_definition -{ - byte unused00[0x3D4]; - long bitmap_group_index; -}; - typedef char verify_postgame_statistic_entry_size[ sizeof(struct postgame_statistic_entry) == 0x1C ? 1 : -1]; -typedef char verify_game_engine_hud_globals_no_local_player_message_font_index_offset[ +typedef char verify_hud_globals_single_player_font_index_offset[ offsetof( - struct game_engine_hud_globals, - no_local_player_message_font_index) == 0x54 ? 1 : -1]; -typedef char verify_game_engine_hud_globals_local_player_message_font_index_offset[ + struct hud_globals_definition, + messaging.single_player_font.index) == 0x54 ? 1 : -1]; +typedef char verify_hud_globals_multi_player_font_index_offset[ offsetof( - struct game_engine_hud_globals, - local_player_message_font_index) == 0x64 ? 1 : -1]; -typedef char verify_game_engine_postgame_hud_definition_bitmap_group_index_offset[ + struct hud_globals_definition, + messaging.multi_player_font.index) == 0x64 ? 1 : -1]; +typedef char verify_hud_globals_carnage_report_bitmap_index_offset[ offsetof( - struct game_engine_postgame_hud_definition, - bitmap_group_index) == 0x3D4 ? 1 : -1]; + struct hud_globals_definition, + carnage_report_bitmap.index) == 0x3D4 ? 1 : -1]; typedef char verify_game_engine_goal_size[sizeof(struct game_engine_goal) == 0x20 ? 1 : -1]; typedef char verify_game_engine_globals_postgame_timer_offset[ offsetof(struct game_engine_globals, postgame_timer) == 0x8 ? 1 : -1]; @@ -684,66 +673,16 @@ typedef char verify_game_engine_stage_variant_offset[ offsetof(struct game_engine_stage, variant) == 0x40 ? 1 : -1]; typedef char verify_game_engine_stage_size[ sizeof(struct game_engine_stage) == 0xA8 ? 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]; -struct scenario_netgame_equipment -{ - unsigned long flags; - short game_types[4]; - byte unusedC[2]; - short respawn_time; - byte unused10[0x30]; - real_point3d position; - byte unused4C[0x10]; - long item_collection_index; - byte unused60[0x30]; -}; - typedef char verify_scenario_netgame_equipment_size[ sizeof(struct scenario_netgame_equipment) == 0x90 ? 1 : -1]; -struct scenario_starting_equipment -{ - unsigned long flags; - short game_types[4]; - byte unusedC[0x3C]; - struct - { - long item_collection_index; - byte unused4[0xC]; - } item_collections[5]; - byte unused98[0x34]; -}; - -struct item_collection_permutation -{ - byte unused0[0x20]; - real weight; - byte unused24[0xC]; - long item_index; - byte unused34[0x20]; -}; - -struct item_collection_definition -{ - struct tag_block permutations; - short respawn_time; -}; - typedef char verify_scenario_starting_equipment_size[ sizeof(struct scenario_starting_equipment) == 0xCC ? 1 : -1]; -typedef char verify_item_collection_permutation_size[ - sizeof(struct item_collection_permutation) == 0x54 ? 1 : -1]; +typedef char verify_item_permutation_definition_size[ + sizeof(struct item_permutation_definition) == 0x54 ? 1 : -1]; /* ---------- prototypes */ @@ -979,39 +918,16 @@ struct game_variant *build_game_variant_team_king( /* ---------- globals */ -struct -{ - short value; - word pad; - short teleporter_flash_type; - word teleporter_flash_pad; - real teleporter_flash_maximum_intensity; - real_argb_color teleporter_flash_color; - real teleporter_flash_duration; -} debug_player_color = -{ - NONE, - 0, - 6, - 0, - 1.0f, - { 0.5f, 0.35f, 1.0f, 0.35f }, - 1.0f -}; +short debug_player_color = NONE; struct game_engine_goal global_goal[32] = { 0 }; struct game_variant global_variant = { 0 }; struct game_engine *game_engine = NULL; -static long game_engine_teleport_message_ticks = 0; -static short game_engine_teleport_flash_fade_function = 0; -void *global_autogenerate_list = NULL; -long global_autogenerate_count = 0; extern struct game_engine_globals game_engine_globals; extern struct game_engine_stage global_stage; extern struct game_engine *game_engines[]; extern long timeout_for_endgame_sound; -extern struct game_engine_hud_globals *hud_globals; extern struct rasterizer_debug_options rasterizer_debug_options; /* ---------- public code */ @@ -1950,7 +1866,7 @@ void game_engine_post_rasterize_post_game( tab_stops[4] = 410; tab_stops[5] = 500; - font_index = hud_globals->no_local_player_message_font_index; + font_index = hud_globals->messaging.single_player_font.index; get_postgame_hilite_colors( &winner_color, &normal_color, @@ -1965,8 +1881,8 @@ void game_engine_post_rasterize_post_game( draw_string_set_format(NONE, 0, 0); { - struct game_engine_postgame_hud_definition *hud_definition = - game_engine_postgame_hud_definition_get( + struct hud_globals_definition *hud_definition = + hud_globals_definition_get( interface_get_tag_index(_interface_hud_globals)); rectangle2d bounds; @@ -1974,10 +1890,10 @@ void game_engine_post_rasterize_post_game( bounds.y0 = 0; bounds.x1 = 640; bounds.y1 = 480; - if (bitmap_group_try_and_get_bitmap(hud_definition->bitmap_group_index, 0)) + if (bitmap_group_try_and_get_bitmap(hud_definition->carnage_report_bitmap.index, 0)) { draw_bitmap_in_rect( - bitmap_group_try_and_get_bitmap(hud_definition->bitmap_group_index, 0), + bitmap_group_try_and_get_bitmap(hud_definition->carnage_report_bitmap.index, 0), &bounds, &bounds, NULL, @@ -3154,9 +3070,9 @@ void game_engine_rasterize_message( long terminal_font_index; if (local_player_count()) - font_index = hud_globals->local_player_message_font_index; + font_index = hud_globals->messaging.multi_player_font.index; else - font_index = hud_globals->no_local_player_message_font_index; + font_index = hud_globals->messaging.single_player_font.index; bounds = render.camera.window_bounds; @@ -3615,6 +3531,15 @@ void game_engine_nonplayer_post_rasterize( static void game_engine_update_teleporter( long player_index) { + static int blocked_message_delay = 0; + static long fade_function = 0; + static long screen_flash_type = 6; + static real max_intensity = 1.0f; + static real alpha = 0.5f; + static real red = 0.35f; + static real green = 1.0f; + static real blue = 0.35f; + static real duration = 1.0f; struct scenario *scenario = global_scenario_get(); struct player_datum *player = player_get(player_index); struct unit_datum *unit; @@ -3731,13 +3656,13 @@ static void game_engine_update_teleporter( } } - if (game_engine_teleport_message_ticks > 0) + if (blocked_message_delay > 0) { - game_engine_teleport_message_ticks--; + blocked_message_delay--; return; } - game_engine_teleport_message_ticks = 120; + blocked_message_delay = 120; { long string_list_index = tag_loaded('ustr', "ui\\multiplayer_game_text"); @@ -3765,18 +3690,16 @@ static void game_engine_update_teleporter( { struct screen_flash_definition screen_flash = { 0 }; - screen_flash.fade_function = - game_engine_teleport_flash_fade_function; - screen_flash.type = - debug_player_color.teleporter_flash_type; - screen_flash.duration = - debug_player_color.teleporter_flash_duration; + screen_flash.fade_function = fade_function; + screen_flash.type = screen_flash_type; + screen_flash.duration = duration; screen_flash.priority = 2; - screen_flash.max_intensity = - debug_player_color.teleporter_flash_maximum_intensity; + screen_flash.max_intensity = max_intensity; screen_flash.zero_scale_factor = 0.0f; - screen_flash.screen_flash_color = - debug_player_color.teleporter_flash_color; + screen_flash.screen_flash_color.alpha = alpha; + screen_flash.screen_flash_color.red = red; + screen_flash.screen_flash_color.green = green; + screen_flash.screen_flash_color.blue = blue; player_effect_screen_flash( player_index, &screen_flash, @@ -4479,6 +4402,12 @@ long find_netgame_flag( return flag_index; } +/* playlist data: in the Aug-15-2001 build the playlist functions were the only users of these two globals; + this build no longer reads them. their definition point here, with the playlist code, is inferred (the + Aug-2001 users and the later builds' layout), not attested */ +void *global_autogenerate_list = NULL; +long global_autogenerate_count = 0; + void game_engine_playlist_next( long parameter0, long parameter1, @@ -5984,8 +5913,8 @@ real_rgb_color *game_engine_player_get_change_color( { long color_index = player->network_player_data.primary_color_index; - if (debug_player_color.value != NONE) - color_index = debug_player_color.value; + if (debug_player_color != NONE) + color_index = debug_player_color; result = player_profile_get_rgb_color(color_index); } @@ -6861,7 +6790,7 @@ static void netgame_verify_equipment( if (match_game_type( game_type, 4, - equipment->game_types)) + equipment->game_type)) { matching_count++; } @@ -7345,8 +7274,8 @@ static long adjust_score_for_ranking( static long item_collection_get_total( struct tag_block const *permutations) { - struct item_collection_permutation const *permutation = - (struct item_collection_permutation const *)permutations->address; + struct item_permutation_definition const *permutation = + (struct item_permutation_definition const *)permutations->address; long permutation_count = permutations->count; long result = 0; long permutation_index; @@ -7373,7 +7302,7 @@ static long random_item( get_global_random_seed_address(), 0, (short)item_collection_get_total(permutations)); - struct item_collection_permutation const *permutation = + struct item_permutation_definition const *permutation = permutations->address; long permutation_index = 0; @@ -7383,7 +7312,7 @@ static long random_item( (long)((real)remaining_weight - permutation[permutation_index].weight); if (remaining_weight < 0) - return permutation[permutation_index].item_index; + return permutation[permutation_index].item.index; permutation_index++; } @@ -7409,21 +7338,21 @@ static void game_engine_update_item_spawn( struct scenario_netgame_equipment); if (match_game_type( game_engine_get_type(), - NUMBEROF(equipment->game_types), - equipment->game_types)) + NUMBEROF(equipment->game_type), + equipment->game_type)) { long respawn_period = 30 * TICKS_PER_SECOND; - short respawn_time = equipment->respawn_time; + short respawn_time = equipment->spawn_time; if (respawn_time == 0) { - if (equipment->item_collection_index != NONE) + if (equipment->item_collection.index != NONE) { struct item_collection_definition *item_collection = item_collection_definition_get( - equipment->item_collection_index); + equipment->item_collection.index); - respawn_time = item_collection->respawn_time; + respawn_time = item_collection->spawn_time; if (respawn_time != 0) respawn_period = respawn_time * TICKS_PER_SECOND; } @@ -7436,7 +7365,7 @@ static void game_engine_update_item_spawn( if (game_time_get() % respawn_period == 0) { long definition_index = - random_item(equipment->item_collection_index); + random_item(equipment->item_collection.index); struct object_placement_data placement_data; long object_index; @@ -7488,7 +7417,7 @@ static void handle_custom_starting_equipment( if (match_game_type( game_engine_get_type(), 4, - starting_equipment->game_types)) + starting_equipment->game_type)) { break; } @@ -7505,7 +7434,7 @@ static void handle_custom_starting_equipment( boolean first_weapon = TRUE; long remaining_item_collection_count = 5; long *item_collection = - &starting_equipment->item_collections[0].item_collection_index; + &starting_equipment->item_collection[0].index; do { @@ -7544,7 +7473,7 @@ static void handle_custom_starting_equipment( } } - item_collection += sizeof(starting_equipment->item_collections[0]) / + item_collection += sizeof(starting_equipment->item_collection[0]) / sizeof(*item_collection); remaining_item_collection_count--; } diff --git a/source/game/game_engine_ctf.c b/source/game/game_engine_ctf.c index c75117af..83196541 100644 --- a/source/game/game_engine_ctf.c +++ b/source/game/game_engine_ctf.c @@ -209,15 +209,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]; diff --git a/source/game/game_engine_king.c b/source/game/game_engine_king.c index da0ae0d8..fcb4fbc3 100644 --- a/source/game/game_engine_king.c +++ b/source/game/game_engine_king.c @@ -206,15 +206,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[ diff --git a/source/game/game_engine_oddball.c b/source/game/game_engine_oddball.c index a4bcc30e..be7f65a4 100644 --- a/source/game/game_engine_oddball.c +++ b/source/game/game_engine_oddball.c @@ -232,15 +232,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]; diff --git a/source/game/game_engine_race.c b/source/game/game_engine_race.c index 3c86848a..da0c6b39 100644 --- a/source/game/game_engine_race.c +++ b/source/game/game_engine_race.c @@ -202,15 +202,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]; diff --git a/source/game/players.c b/source/game/players.c index 389a8961..576c8cce 100644 --- a/source/game/players.c +++ b/source/game/players.c @@ -3053,6 +3053,10 @@ static void player_handle_powerup_equipment( powerup_index = 1; break; + /* powerup_index is left unassigned only by this default arm. Not reached unassigned: the + * arm's assertion failure calls system_exit, which does not return in January + * (0x47c960 jumps to halt_and_catch_fire 0x4f21c0, which loops or calls exit). + * Source-policy approval pending (2026-09-27 audit). */ default: display_assert( NULL, diff --git a/source/hs/hs.c b/source/hs/hs.c index e5db1ee8..dc7879a6 100644 --- a/source/hs/hs.c +++ b/source/hs/hs.c @@ -2792,6 +2792,7 @@ symbols in this file: #include "cutscene/recorded_animations.h" #include "devices/devices.h" #include "game/game.h" +#include "interface/hud_definitions.h" #include "interface/hud_messaging.h" #include "interface/hud_unit.h" #include "interface/hud_weapon.h" @@ -3333,12 +3334,6 @@ struct hs_arguments_long_long_long long value2; }; -struct hud_globals_definition -{ - byte reserved_000[0x160]; - struct tag_block waypoint_arrows; -}; - struct hud_message_text_definition { byte reserved_000[0x20]; @@ -13754,7 +13749,7 @@ static void hs_enumerate_navpoints( hud_globals = hud_globals_definition_get( interface_get_tag_index(_interface_hud_globals)); hs_enumerate_block_data( - &hud_globals->waypoint_arrows, + &hud_globals->waypoint.arrows, 0, sizeof(struct hud_waypoint_arrow_definition)); } diff --git a/source/hs/hs_compile.c b/source/hs/hs_compile.c index 7c08a932..79a401ec 100644 --- a/source/hs/hs_compile.c +++ b/source/hs/hs_compile.c @@ -414,6 +414,7 @@ symbols in this file: #include "hs/hs.h" #include "hs/hs_library_internal_compile.h" #include "hs/hs_scenario_definitions.h" +#include "interface/hud_definitions.h" #include "interface/interface.h" #include "memory/data.h" #include "scenario/scenario.h" @@ -497,12 +498,6 @@ struct hs_tokenizer typedef char verify_hs_syntax_node_size[ sizeof(struct hs_syntax_node) == 0x14 ? 1 : -1]; -struct hud_globals_definition -{ - byte reserved000[0x160]; - struct tag_block waypoint_arrows; -}; - struct hud_message_text_definition { byte reserved000[0x20]; @@ -1842,7 +1837,7 @@ static boolean hs_parse_navpoint( result = hs_parse_scenario_datum( expression_index, 0, - &hud_globals->waypoint_arrows, + &hud_globals->waypoint.arrows, hud_waypoint_arrow_size); } diff --git a/source/hs/hs_library_external.c b/source/hs/hs_library_external.c index 24ec09c7..1cb3b0e2 100644 --- a/source/hs/hs_library_external.c +++ b/source/hs/hs_library_external.c @@ -199,6 +199,11 @@ boolean hs_not( void hs_print( char const *message) { + /* BUG (preserved for exact matching): the printed string is passed as the format + * (January 0x4b8970 +0x0c pushes it as terminal_printf's format), so a '%' in the + * text, from a scenario script or typed at this build's console, reads arguments + * that were never passed. A corrected build should print it through "%s". + * Source-policy approval pending (2026-09-27 audit). */ terminal_printf(global_real_argb_green, message); return; diff --git a/source/hs/hs_runtime.c b/source/hs/hs_runtime.c index 72e897a5..82ddcb3d 100644 --- a/source/hs/hs_runtime.c +++ b/source/hs/hs_runtime.c @@ -1040,6 +1040,10 @@ void render_debug_trigger_volumes( matrix4x3_transform_vector(&matrix, &local_extent, &world_extent); break; + /* matrix is left unassigned only by this default arm. Not reached unassigned: the + * arm's assertion failure calls system_exit, which does not return in January + * (0x47c960 jumps to halt_and_catch_fire 0x4f21c0, which loops or calls exit). + * Source-policy approval pending (2026-09-27 audit). */ default: match_assert( "c:\\halo\\SOURCE\\hs\\hs_runtime.c", @@ -2061,6 +2065,10 @@ void hs_evaluate_inspect( if (hs_type_inspectors[expression->type]) { hs_type_inspectors[expression->type](expression->type, *value, string); + /* BUG (preserved for exact matching): the inspected value's text is passed as the + * format (January 0x4bc840 +0xdd..+0xe6), so inspecting a string that contains '%' + * reads arguments that were never passed. A corrected build should print it through + * "%s". Source-policy approval pending (2026-09-27 audit). */ console_printf(FALSE, string); } diff --git a/source/interface/hud.c b/source/interface/hud.c index e63cdafb..59f4a585 100644 --- a/source/interface/hud.c +++ b/source/interface/hud.c @@ -86,6 +86,7 @@ symbols in this file: #include "game/player_control.h" #include "game/players.h" #include "interface/hud.h" +#include "interface/hud_definitions.h" #include "interface/hud_messaging.h" #include "interface/hud_unit.h" #include "interface/hud_weapon.h" @@ -197,24 +198,12 @@ struct weapon_interface_state struct weapon_interface_magazine_state magazines[2]; }; -struct hud_globals_definition -{ - byte reserved000[0x94]; - struct tag_reference hud_item_messages; - byte reserved0A4[0x334]; - short loading_begin_index; - short loading_end_index; - short checkpoint_begin_index; - short checkpoint_end_index; - struct tag_reference checkpoint_sound; -}; - typedef char hud_scripted_globals_size_assert[ sizeof(struct hud_scripted_globals) == 0x4 ? 1 : -1]; typedef char hud_scripted_globals_show_hud_help_text_offset_assert[ offsetof(struct hud_scripted_globals, show_hud_help_text) == 0x1 ? 1 : -1]; typedef char hud_globals_hud_item_messages_index_offset_assert[ - offsetof(struct hud_globals_definition, hud_item_messages.index) == 0xA0 ? 1 : -1]; + offsetof(struct hud_globals_definition, messaging.hud_item_messages.index) == 0xA0 ? 1 : -1]; typedef char hud_globals_loading_begin_index_offset_assert[ offsetof(struct hud_globals_definition, loading_begin_index) == 0x3D8 ? 1 : -1]; typedef char hud_globals_checkpoint_sound_index_offset_assert[ @@ -744,7 +733,7 @@ static void hud_show_action_response( wchar_t const *hud_get_item_string( long string_index) { - long string_list_index = hud_globals->hud_item_messages.index; + long string_list_index = hud_globals->messaging.hud_item_messages.index; wchar_t const *string = default_string; if (string_list_index != NONE) diff --git a/source/interface/hud.h b/source/interface/hud.h index f5a38425..3236da91 100644 --- a/source/interface/hud.h +++ b/source/interface/hud.h @@ -14,6 +14,7 @@ header included in hcex build. /* ---------- structures */ +struct hud_globals_definition; struct tag_block; union real_argb_color; @@ -84,6 +85,8 @@ void hud_play_sound( /* ---------- globals */ +extern struct hud_globals_definition *hud_globals; + /* ---------- public code */ #endif // __HUD_H diff --git a/source/interface/hud_definitions.c b/source/interface/hud_definitions.c index 7e932d58..6a802230 100644 --- a/source/interface/hud_definitions.c +++ b/source/interface/hud_definitions.c @@ -16,6 +16,7 @@ symbols in this file: /* ---------- headers */ +#include "cseries/cseries.h" #include "hud_definitions.h" /* ---------- constants */ diff --git a/source/interface/hud_definitions.h b/source/interface/hud_definitions.h index d4184515..0ef23db5 100644 --- a/source/interface/hud_definitions.h +++ b/source/interface/hud_definitions.h @@ -8,6 +8,11 @@ header included in hcex build. #define __HUD_DEFINITIONS_H #pragma once +/* ---------- headers */ + +#include "math/real_math.h" +#include "tag_files/tag_groups.h" + /* ---------- constants */ enum hud_anchor @@ -25,6 +30,136 @@ enum hud_anchor /* ---------- structures */ +struct hud_absolute_placement_definition +{ + short corner; + short pad; + long unused[8]; +}; + +struct hud_placement_definition +{ + point2d offset; + real_vector2d scale; + short multiplayer_scaling_flags; + short pad; + long unused0[5]; +}; + +struct hud_color_definition +{ + unsigned long color; + unsigned long flash_color; + real flash_period; + real flash_delay; + short number_of_flashes; + word flash_flags; + real flash_length; + unsigned long disabled_color; + union + { + long unused; + struct + { + short up_ticks; + short fade_ticks; + } objective; + } custom; +}; + +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]; +}; + +typedef char hud_absolute_placement_definition_size_assert[ + sizeof(struct hud_absolute_placement_definition) == 0x24 ? 1 : -1]; +typedef char hud_placement_definition_size_assert[ + sizeof(struct hud_placement_definition) == 0x24 ? 1 : -1]; +typedef char hud_color_definition_size_assert[ + sizeof(struct hud_color_definition) == 0x20 ? 1 : -1]; + /* ---------- prototypes/EXAMPLE.C */ /* ---------- globals */ diff --git a/source/interface/hud_draw.c b/source/interface/hud_draw.c index 40238431..2f8f3523 100644 --- a/source/interface/hud_draw.c +++ b/source/interface/hud_draw.c @@ -763,6 +763,10 @@ static void hud_draw_multitexture_overlay( break; } + /* The switch above has no default: a source value outside the eight enumerators + * leaves source_value unassigned for the interpolation below. Not shown reachable: + * the value comes from hud tag data, which was not scanned. Source-policy approval + * pending (2026-09-27 audit). */ if (effector->in_bounds[1] == effector->in_bounds[0] || effector->out_bounds[1] == effector->out_bounds[0]) { diff --git a/source/interface/hud_messaging.c b/source/interface/hud_messaging.c index 862a70ae..641f4478 100644 --- a/source/interface/hud_messaging.c +++ b/source/interface/hud_messaging.c @@ -128,6 +128,7 @@ symbols in this file: #include "interface/hud_draw.h" #include "bitmaps/bitmap_color_conversion.h" #include "interface/hud.h" +#include "interface/hud_definitions.h" #include "interface/hud_messaging.h" #include "interface/interface.h" #include "interface/ui_widget.h" @@ -361,22 +362,6 @@ struct hud_timer_data_definition boolean enabled; }; -struct hud_absolute_placement_definition -{ - short corner; - short pad; - long unused[8]; -}; - -struct hud_placement_definition -{ - point2d offset; - real_vector2d scale; - short multiplayer_scaling_flags; - short pad; - long unused[5]; -}; - struct hud_objective_runtime_definition { struct hud_state_message_definition *message; @@ -396,27 +381,6 @@ struct hud_messaging_globals_definition struct hud_timer_data_definition timer; }; -struct hud_color_definition -{ - unsigned long color; - unsigned long flash_color; - real flash_period; - real flash_delay; - short number_of_flashes; - word flash_flags; - real flash_length; - unsigned long disabled_color; - union - { - long unused; - struct - { - short up_ticks; - short fade_ticks; - } objective; - } custom; -}; - struct number_hud_element_definition { struct hud_placement_definition placement; @@ -441,40 +405,6 @@ struct hud_number_definition long unused[19]; }; -struct hud_timer_definition -{ - struct hud_color_definition color; - struct hud_color_definition time_up_color; - long unused[10]; -}; - -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_globals_definition -{ - struct hud_messaging_parameters_definition messaging; - byte reserved120[0x240]; - struct hud_timer_definition timer_definition; -}; - typedef char hud_timer_data_size_assert[ sizeof(struct hud_timer_data_definition) == 0x10 ? 1 : -1]; typedef char hud_message_valid_offset_assert[ @@ -560,7 +490,6 @@ static void render_state_bitmap( /* ---------- globals */ static struct hud_messaging_globals_definition *hud_messaging_globals; -extern struct hud_globals_definition *hud_globals; extern struct hud_messaging_parameters_definition *hud_msg_def; extern struct hud_scripted_globals_definition *hud_scripted_globals; static char button_mappings[_icon_custom_1 - _icon_action] = diff --git a/source/interface/hud_nav_points.c b/source/interface/hud_nav_points.c index 700a6e03..25b45054 100644 --- a/source/interface/hud_nav_points.c +++ b/source/interface/hud_nav_points.c @@ -160,35 +160,6 @@ enum hud_number_show_flags /* ---------- structures */ -struct hud_absolute_placement_definition -{ - short corner; - short pad; - long unused[8]; -}; - -struct hud_placement_definition -{ - point2d offset; - real_vector2d scale; - short multiplayer_scaling_flags; - short pad; - long unused0[5]; -}; - -struct hud_color_definition -{ - unsigned long color; - unsigned long flash_color; - real flash_period; - real flash_delay; - short number_of_flashes; - unsigned short flash_flags; - real flash_length; - unsigned long disabled_color; - unsigned long custom; -}; - struct number_hud_element_definition { struct hud_placement_definition placement; @@ -200,26 +171,6 @@ struct number_hud_element_definition long unused[3]; }; -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_arrow { char name[0x20]; @@ -234,25 +185,6 @@ struct hud_waypoint_arrow long unused2[6]; }; -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[0x14]; -}; - -struct hud_globals_definition -{ - struct hud_messaging_parameters_definition messaging; - struct hud_waypoint_definition waypoint; - byte unknown1BC[0x294]; -}; - struct hud_nav_point_datum { short nav_index; @@ -318,8 +250,6 @@ void unit_get_head_position( /* ---------- globals */ -extern struct hud_globals_definition *hud_globals; - static struct hud_nav_point_player_datum *nav_point_data; /* ---------- private code */ @@ -1047,6 +977,10 @@ void hud_render_nav_points( } break; + /* position is left unassigned only by this default arm. Not reached unassigned: the + * arm's assertion failure calls system_exit, which does not return in January + * (0x47c960 jumps to halt_and_catch_fire 0x4f21c0, which loops or calls exit). + * Source-policy approval pending (2026-09-27 audit). */ default: match_assert("c:\\halo\\SOURCE\\interface\\hud_nav_points.c", 725, !"unreachable"); break; @@ -1148,6 +1082,11 @@ static void hud_update_nav_point_local_player( break; } + /* The default arm leaves position unassigned. Not reached: every store to + * nav_point->type in this file writes one of the three types handled above or NONE + * (the map-start memset and the deactivations), the nav point array is private to + * this file, and NONE entries are skipped above. Source-policy approval pending + * (2026-09-27 audit). */ position.z += nav_point->z_offset; nav_point->screen_type = hud_get_nav_point_render_type( local_player_index, diff --git a/source/interface/hud_unit.c b/source/interface/hud_unit.c index 1ff72603..d5f11e66 100644 --- a/source/interface/hud_unit.c +++ b/source/interface/hud_unit.c @@ -147,77 +147,6 @@ struct hud_scripted_globals byte reserved2[2]; }; -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[0x40]; -}; - -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[0xB]; -}; - -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_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; -}; - typedef char unit_hud_state_auxilary_flash_time_offset_assert[ offsetof(struct unit_hud_state, auxilary_flash_time) == 0x22 ? 1 : -1]; typedef char unit_hud_state_sound_flags_offset_assert[ @@ -258,7 +187,6 @@ static void hud_update_unit_local_player( 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 */ @@ -740,6 +668,10 @@ void hud_render_damage_indicators( render.camera.viewport_bounds.y1) / 2); break; + /* theta and screen_position are left unassigned only by this default arm. Not reached unassigned: the + * arm's assertion failure calls system_exit, which does not return in January + * (0x47c960 jumps to halt_and_catch_fire 0x4f21c0, which loops or calls exit). + * Source-policy approval pending (2026-09-27 audit). */ default: match_assert( "c:\\halo\\SOURCE\\interface\\hud_unit.c", diff --git a/source/interface/hud_weapon.c b/source/interface/hud_weapon.c index c9bd1e31..139cb240 100644 --- a/source/interface/hud_weapon.c +++ b/source/interface/hud_weapon.c @@ -61,6 +61,7 @@ symbols in this file: #include "game/player_control.h" #include "game/players.h" #include "interface/hud_draw.h" +#include "interface/hud.h" #include "interface/hud_definitions.h" #include "interface/hud_weapon.h" #include "interface/unit_hud_interface_definition.h" @@ -375,17 +376,6 @@ struct weapon_hud_crosshair_item long unused[8]; }; -struct hud_weapon_defaults_definition -{ - struct tag_reference default_weapon_hud; -}; - -struct hud_weapon_globals_definition -{ - byte reserved000[0x2C0]; - struct hud_weapon_defaults_definition defaults; -}; - typedef char weapon_hud_state_size_assert[ sizeof(struct weapon_hud_state) == 0x28 ? 1 : -1]; typedef char crosshair_state_size_assert[ @@ -409,7 +399,7 @@ typedef char weapon_hud_crosshairs_element_size_assert[ typedef char weapon_hud_crosshair_item_size_assert[ sizeof(struct weapon_hud_crosshair_item) == 0x6C ? 1 : -1]; typedef char hud_weapon_globals_default_weapon_hud_index_offset_assert[ - offsetof(struct hud_weapon_globals_definition, defaults.default_weapon_hud.index) == 0x2CC ? 1 : -1]; + offsetof(struct hud_globals_definition, defaults.default_weapon_hud.index) == 0x2CC ? 1 : -1]; /* ---------- prototypes */ @@ -448,7 +438,6 @@ static void render_weapon_hud( /* ---------- globals */ static struct weapon_hud_globals *weapon_hud_globals = NULL; -extern struct hud_weapon_globals_definition *hud_globals; /* ---------- public code */ diff --git a/source/interface/interface.c b/source/interface/interface.c index 8b7ad8ae..79e04e96 100644 --- a/source/interface/interface.c +++ b/source/interface/interface.c @@ -85,6 +85,7 @@ symbols in this file: #include "game/players.h" #include "interface/first_person_weapons.h" #include "interface/hud.h" +#include "interface/hud_definitions.h" #include "interface/interface.h" #include "interface/hud_messaging.h" #include "interface/terminal.h" @@ -190,13 +191,6 @@ struct weapon_flash_state_definition long unused0C[8]; }; -struct hud_absolute_placement_definition -{ - short corner; - short pad02; - long unused04[8]; -}; - struct icon_hud_element_definition { short sequence_index; @@ -255,8 +249,6 @@ typedef char weapon_hud_interface_definition_screen_effects_offset_assert[ offsetof(struct weapon_hud_interface_definition, screen_effects) == 0xAC ? 1 : -1]; typedef char weapon_flash_state_definition_size_assert[ sizeof(struct weapon_flash_state_definition) == 0x2C ? 1 : -1]; -typedef char hud_absolute_placement_definition_size_assert[ - sizeof(struct hud_absolute_placement_definition) == 0x24 ? 1 : -1]; typedef char icon_hud_element_definition_size_assert[ sizeof(struct icon_hud_element_definition) == 0x10 ? 1 : -1]; typedef char weapon_hud_interface_definition_size_assert[ @@ -297,19 +289,8 @@ struct interface_hud_scripted_globals byte unused[2]; }; -struct interface_hud_defaults_definition -{ - struct tag_reference default_weapon_hud; -}; - -struct interface_hud_globals_definition -{ - byte unused[0x2C0]; - struct interface_hud_defaults_definition defaults; -}; - typedef char interface_hud_globals_default_weapon_hud_index_offset_assert[ - offsetof(struct interface_hud_globals_definition, defaults.default_weapon_hud.index) == 0x2CC ? 1 : -1]; + offsetof(struct hud_globals_definition, defaults.default_weapon_hud.index) == 0x2CC ? 1 : -1]; /* ---------- prototypes */ @@ -325,7 +306,6 @@ static void render_debug_profile_stall_tick( real scale); /* ---------- globals */ -extern struct interface_hud_globals_definition *hud_globals; extern struct interface_hud_scripted_globals *hud_scripted_globals; static short profile_game_value_count = NUMBER_OF_PROFILE_GAME_VALUES; diff --git a/source/interface/motion_sensor.c b/source/interface/motion_sensor.c index 7720e0aa..12f8f13c 100644 --- a/source/interface/motion_sensor.c +++ b/source/interface/motion_sensor.c @@ -101,6 +101,8 @@ symbols in this file: #include "game/player_control.h" #include "game/players.h" #include "game_state.h" +#include "interface/hud.h" +#include "interface/hud_definitions.h" #include "interface/hud_draw.h" #include "objects/objects.h" #include "rasterizer/rasterizer.h" @@ -182,22 +184,6 @@ struct motion_sensor_globals_definition byte pad; }; -struct motion_sensor_hud_defaults -{ - 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 motion_sensor_hud_globals -{ - byte unused[0x2C0]; - struct motion_sensor_hud_defaults defaults; -}; - typedef char motion_sensor_blip_size_assert[ sizeof(struct motion_sensor_blip) == 4 ? 1 : -1]; typedef char motion_sensor_datum_size_assert[ @@ -280,7 +266,6 @@ static struct motion_sensor_globals_definition *motion_sensor_globals = NULL; static real sweep_theta = 0.f; boolean debug_motion_sensor_draw_all_units= {0}; -extern struct motion_sensor_hud_globals *hud_globals; extern short blip_player_index; extern real_point2d center_point; diff --git a/source/interface/ui_widget.c b/source/interface/ui_widget.c index eab359fe..3067de03 100644 --- a/source/interface/ui_widget.c +++ b/source/interface/ui_widget.c @@ -645,6 +645,7 @@ struct widget_instance; #include "input/input.h" #include "input/input_abstraction.h" #include "interface/attract_mode.h" +#include "interface/hud.h" #include "interface/hud_definitions.h" #include "interface/hud_draw.h" #include "bitmaps/bitmap_color_conversion.h" @@ -972,17 +973,6 @@ struct icon_hud_element_definition short text_index; }; -struct hud_messaging_parameters_definition -{ - byte reserved000[0xC4]; - struct tag_block button_icons; /* icon_hud_element_definition */ -}; - -struct hud_globals_definition -{ - struct hud_messaging_parameters_definition messaging; -}; - struct interface_tag_references_definition { struct tag_reference tags[NUMBER_OF_INTERFACE_TAGS]; @@ -1460,7 +1450,6 @@ static struct ui_widget_bss_prefix ui_widget_globals_storage; #define we_are_at_the_main_menu ui_widget_globals_storage.we_are_at_the_main_menu #define dpad_event_times ui_widget_globals_storage.dpad_event_times extern real_argb_color ui_plasma_effect_color; -extern struct hud_globals_definition *hud_globals; extern short local_player_index_for_draw_string_and_hack_in_icons; /* January defines this and never references it, as we do not */ diff --git a/source/interface/ui_widget_game_data_input_functions.c b/source/interface/ui_widget_game_data_input_functions.c index 7491f589..78bdebea 100644 --- a/source/interface/ui_widget_game_data_input_functions.c +++ b/source/interface/ui_widget_game_data_input_functions.c @@ -368,7 +368,6 @@ enum { MAXIMUM_NETWORK_MACHINE_COUNT = 4, MAXIMUM_NETWORK_ADVERTISED_GAMES = 9, - MAXIMUM_DISPLAYED_SERVERS = 10, }; enum network_game_platform @@ -625,9 +624,6 @@ static byte const local_player_controller_bitmap_frames[2][MAXIMUM_LOCAL_PLAYERS {{3, 5, 4}, {6, 8, 7}, {9, 11, 10}, {12, 14, 13}} }; -static struct network_advertised_game *displayed_servers[MAXIMUM_DISPLAYED_SERVERS]; -static wchar_t ui_widget_game_data_build_version_wide_string[64]; - /* ---------- public code */ void ui_widget_game_data_function_invoke( @@ -880,6 +876,11 @@ void difficulty_select_menu_update_extended_description( void server_list_menu_update( struct widget_instance *widget) { + /* Name, nine-element size and function scope from the 2003 PC demo PDB and the HCEX PDB (static + local of server_list_menu_update; their element type is named advertised_game_data). Neither + PDB records the block: placing it at the top of the function is unattested. January + corroborates: .bss +0, referenced only by this function. */ + static struct network_advertised_game *displayed_servers[MAXIMUM_NETWORK_ADVERTISED_GAMES]; struct network_game_client *client = global_network_game_client_get(); long displayed_server_count = 0; @@ -1951,19 +1952,24 @@ void netgame_prejoin_players( void set_textbox_to_build_number( struct widget_instance *widget) { - if (!ui_widget_game_data_build_version_wide_string[0]) + /* Name, type and function scope from the 2003 PC demo PDB and the HCEX PDB (static local + wchar_t build_number_string[0x40]). Neither PDB records the block: placing it at the top of + the function is unattested. January corroborates: .bss +0x28, referenced only here. */ + static wchar_t build_number_string[64]; + + if (!build_number_string[0]) { ascii_to_wide( "01.01.14.2342", - ui_widget_game_data_build_version_wide_string, - sizeof(ui_widget_game_data_build_version_wide_string)); + build_number_string, + sizeof(build_number_string)); } if (!widget->parameters.text_box.text) { widget->parameters.text_box.text = ui_widget_realloc( NULL, - sizeof(ui_widget_game_data_build_version_wide_string), + sizeof(build_number_string), "c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c", 0x25E); if (widget->parameters.text_box.text) @@ -1971,7 +1977,7 @@ void set_textbox_to_build_number( csmemset( widget->parameters.text_box.text, 0, - sizeof(ui_widget_game_data_build_version_wide_string)); + sizeof(build_number_string)); } } @@ -1979,9 +1985,9 @@ void set_textbox_to_build_number( { ustrncpy( widget->parameters.text_box.text, - ui_widget_game_data_build_version_wide_string, - NUMBEROF(ui_widget_game_data_build_version_wide_string) - 1); - widget->parameters.text_box.text[NUMBEROF(ui_widget_game_data_build_version_wide_string) - 1] = 0; + build_number_string, + NUMBEROF(build_number_string) - 1); + widget->parameters.text_box.text[NUMBEROF(build_number_string) - 1] = 0; } return; } @@ -2252,6 +2258,12 @@ static void game_options_menu_update_text_desc( } } + /* BUG (preserved for exact matching): description_index is assigned only when the + * list has a focused child. Without one, January stores the low word of the widget + * argument slot instead (0x4e1ce0: +0xa4 branches to +0x119 mov dx,[ebp+8]; the slot + * is never written). Whether a game options list is updated without a focused child + * is not shown. A corrected build should initialise description_index to 0. + * Source-policy approval pending (2026-09-27 audit). */ extended_description->parameters.text_box.string_list_index = (short)description_index; return; } @@ -2313,6 +2325,11 @@ static void game_options_menu_update_pic_desc( } } + /* BUG (preserved for exact matching): as in game_options_menu_update_text_desc, + * without a focused child January stores the low word of the widget argument slot + * (0x4e1ea0 +0x119 mov dx,[ebp+8]). Whether that occurs is not shown. A corrected + * build should initialise description_index to 0. Source-policy approval pending + * (2026-09-27 audit). */ extended_description->animation.current_frame_index = (short)description_index; return; } diff --git a/source/interface/unit_hud_interface_definition.h b/source/interface/unit_hud_interface_definition.h index 706d38ac..7f1a653a 100644 --- a/source/interface/unit_hud_interface_definition.h +++ b/source/interface/unit_hud_interface_definition.h @@ -12,6 +12,7 @@ See docs/object_matching_logs/input_hud_player_ui_followup_20260904.md. /* ---------- headers */ #include "math/real_math.h" +#include "interface/hud_definitions.h" #include "tag_files/tag_groups.h" /* ---------- constants */ @@ -51,47 +52,6 @@ enum auxilary_overlay_use_team_color_flags /* ---------- structures */ -struct hud_absolute_placement_definition -{ - short corner; - short pad; - long unused[8]; -}; - -struct hud_placement_definition -{ - point2d offset; - real_vector2d scale; - short multiplayer_scaling_flags; - short pad; - long unused0[5]; -}; - -struct hud_objective_color_definition -{ - short up_ticks; - short fade_ticks; -}; - -union hud_color_custom_definition -{ - long unused; - struct hud_objective_color_definition objective; -}; - -struct hud_color_definition -{ - unsigned long color; - unsigned long flash_color; - real flash_period; - real flash_delay; - short number_of_flashes; - word flash_flags; - real flash_length; - unsigned long disabled_color; - union hud_color_custom_definition custom; -}; - struct static_hud_element_definition { struct hud_placement_definition placement; @@ -206,12 +166,6 @@ struct unit_hud_interface_definition long unused2[12]; }; -typedef char hud_absolute_placement_definition_size_assert[ - sizeof(struct hud_absolute_placement_definition) == 0x24 ? 1 : -1]; -typedef char hud_placement_definition_size_assert[ - sizeof(struct hud_placement_definition) == 0x24 ? 1 : -1]; -typedef char hud_color_definition_size_assert[ - sizeof(struct hud_color_definition) == 0x20 ? 1 : -1]; typedef char static_hud_element_definition_size_assert[ sizeof(struct static_hud_element_definition) == 0x68 ? 1 : -1]; typedef char meter_hud_element_definition_size_assert[ diff --git a/source/items/item_definitions.h b/source/items/item_definitions.h index 6019e988..bfa83bba 100644 --- a/source/items/item_definitions.h +++ b/source/items/item_definitions.h @@ -54,6 +54,22 @@ struct item_definition struct _item_definition item; }; +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]; +}; + /* ---------- prototypes/EXAMPLE.C */ /* ---------- globals */ diff --git a/source/items/projectiles.c b/source/items/projectiles.c index 8200db6d..622d807b 100644 --- a/source/items/projectiles.c +++ b/source/items/projectiles.c @@ -536,6 +536,10 @@ void projectile_export_function_values( value = 0.f; break; + /* value is left unassigned only by this default arm. Not reached unassigned: the + * arm's assertion failure calls system_exit, which does not return in January + * (0x47c960 jumps to halt_and_catch_fire 0x4f21c0, which loops or calls exit). + * Source-policy approval pending (2026-09-27 audit). */ default: display_assert( NULL, diff --git a/source/main/main.c b/source/main/main.c index d83f0827..9a5acd32 100644 --- a/source/main/main.c +++ b/source/main/main.c @@ -363,6 +363,7 @@ symbols in this file: #include "bitmaps/bitmaps_internal.h" #include "bitmaps/tiff_file.h" #include "interface/hud.h" +#include "interface/hud_definitions.h" #include "interface/attract_mode.h" #include "interface/interface.h" #include "interface/terminal.h" @@ -554,14 +555,8 @@ struct _main_globals byte reserved61C[4]; }; -struct main_hud_globals_definition -{ - byte reserved00[0x54]; - long font_tag_index; -}; - typedef char main_hud_globals_font_tag_index_offset_assert[ - offsetof(struct main_hud_globals_definition, font_tag_index) == 0x54 ? 1 : -1]; + offsetof(struct hud_globals_definition, messaging.single_player_font.index) == 0x54 ? 1 : -1]; typedef char main_globals_size_assert[ sizeof(struct _main_globals) == 0x620 ? 1 : -1]; @@ -640,12 +635,6 @@ struct game_options typedef char game_options_size_assert[ sizeof(struct game_options) == 0x10C ? 1 : -1]; -struct _main_window_storage -{ - struct render_window window; - byte reservedAC[4]; -}; - #pragma pack(push, 1) struct _screenshot_and_framerate_globals { @@ -687,7 +676,6 @@ extern void scripted_camera_set( word camera_point_index0, word camera_point_index1, long transition_time); -extern struct main_hud_globals_definition *hud_globals; /* ---------- globals */ @@ -710,7 +698,6 @@ static char const *scenario_paths[10] = "levels\\d40\\d40" }; -static struct _main_window_storage window_storage = { 0 }; static struct _main_globals main_globals = { 0 }; boolean debug_force_frame_rate_update = FALSE; boolean debug_no_drawing = FALSE; @@ -1789,6 +1776,12 @@ void main_roll_credits( void main_pregame_render( void) { + /* Name, type and function scope from the 2003 PC demo PDB and the HCEX PDB (static local + struct render_window window of main_pregame_render). Neither PDB records the block: placing it + at the top of the function is unattested. January corroborates: .bss +0, the 0xAC-byte window + padded to 0xB0 before main_globals, referenced only by this function. */ + static struct render_window window; + collision_log_continue_period(TRUE); sound_render(); { @@ -1796,13 +1789,13 @@ void main_pregame_render( real_vector3d forward = { 0.0f, 0.0f, 1.0f }; real_vector3d up = { 0.0f, 1.0f, 0.0f }; - window_storage.window.local_player_index = NONE; - window_storage.window.console_window = TRUE; - window_storage.window.rasterizer_camera.position = position; - window_storage.window.rasterizer_camera.forward = forward; - window_storage.window.rasterizer_camera.up = up; - window_storage.window.rasterizer_camera.mirrored = FALSE; - window_storage.window.rasterizer_camera.vertical_field_of_view = + window.local_player_index = NONE; + window.console_window = TRUE; + window.rasterizer_camera.position = position; + window.rasterizer_camera.forward = forward; + window.rasterizer_camera.up = up; + window.rasterizer_camera.mirrored = FALSE; + window.rasterizer_camera.vertical_field_of_view = 2.0f * arctangent( 0.75f * render_camera_get_adjusted_field_of_view_tangent( DEGREES_TO_RADIANS(80.0f)), @@ -1810,13 +1803,13 @@ void main_pregame_render( compute_window_bounds( 0, 1, - &window_storage.window.rasterizer_camera.viewport_bounds, - &window_storage.window.rasterizer_camera.window_bounds); - window_storage.window.rasterizer_camera.z_near = 0.01f; - window_storage.window.rasterizer_camera.z_far = 1.0f; - window_storage.window.render_camera = window_storage.window.rasterizer_camera; + &window.rasterizer_camera.viewport_bounds, + &window.rasterizer_camera.window_bounds); + window.rasterizer_camera.z_near = 0.01f; + window.rasterizer_camera.z_far = 1.0f; + window.render_camera = window.rasterizer_camera; render_frame_pregame( - &window_storage.window, + &window, main_globals.movie); } collision_log_end_period(); @@ -2651,7 +2644,7 @@ void main_framerate_render( { long font_tag_index; - font_tag_index = hud_globals->font_tag_index; + font_tag_index = hud_globals->messaging.single_player_font.index; if (font_tag_index != NONE) { real frame_seconds; @@ -2687,7 +2680,7 @@ void main_framerate_render( { long font_tag_index; - font_tag_index = hud_globals->font_tag_index; + font_tag_index = hud_globals->messaging.single_player_font.index; if (font_tag_index != NONE) { short index; @@ -2724,7 +2717,7 @@ void main_framerate_render( { long font_tag_index; - font_tag_index = hud_globals->font_tag_index; + font_tag_index = hud_globals->messaging.single_player_font.index; if (font_tag_index != NONE) { real progress; diff --git a/source/math/geometry.c b/source/math/geometry.c index d17e0d3b..470d6e44 100644 --- a/source/math/geometry.c +++ b/source/math/geometry.c @@ -771,6 +771,11 @@ short convex_hull2d( break; } + /* current_index and best_index are assigned only inside the scans. For finite + * points with dimension 2 both scans assign them; a NaN or infinite coordinate can + * leave either unassigned. Not shown reachable: the callers' points (king hill + * markers, lens flare projections) were not traced for non-finite values. + * Source-policy approval pending (2026-09-27 audit). */ hull_indices[hull_count++] = current_index; for (index = 0; index < vertex_count; index++) diff --git a/source/math/periodic_functions.c b/source/math/periodic_functions.c index 67c1ee6e..e9b378de 100644 --- a/source/math/periodic_functions.c +++ b/source/math/periodic_functions.c @@ -367,6 +367,10 @@ static void transition_function_build_table( case _transition_function_cosine: result = ((real)sin(value*3.1415927f-1.5707964f)+1.0f)*0.5f; break; + /* result is left unassigned only by this default arm. Not reached unassigned: the + * arm's assertion failure calls system_exit, which does not return in January + * (0x47c960 jumps to halt_and_catch_fire 0x4f21c0, which loops or calls exit). + * Source-policy approval pending (2026-09-27 audit). */ default: display_assert(NULL, "c:\\halo\\SOURCE\\math\\periodic_functions.c", 411, TRUE); system_exit(-1); @@ -455,6 +459,10 @@ static void periodic_function_build_table( result = (real)fmod((double)random_x, 1.0); result *= result; break; + /* result is left unassigned only by this default arm. Not reached unassigned: the + * arm's assertion failure calls system_exit, which does not return in January + * (0x47c960 jumps to halt_and_catch_fire 0x4f21c0, which loops or calls exit). + * Source-policy approval pending (2026-09-27 audit). */ default: display_assert(NULL, "c:\\halo\\SOURCE\\math\\periodic_functions.c", 499, TRUE); system_exit(-1); diff --git a/source/memory/byte_swapping.c b/source/memory/byte_swapping.c index 680f6b80..28446004 100644 --- a/source/memory/byte_swapping.c +++ b/source/memory/byte_swapping.c @@ -334,6 +334,12 @@ next_iteration: } while (repeat_count!=0); +/* A zero array count reaches done with code_index never assigned, and it is stored + * through next_code. Not reached with January's code tables: all 15 _begin_bs_array + * entries in cachebeta.exe's data sections have count 1 (scan of every aligned + * _begin_bs_array word from .rdata onwards), and every byte_swap_definition in the + * source points at a static table. Source-policy approval pending (2026-09-27 audit). + */ done: if (size) *size = offset; diff --git a/source/memory/data_encoding.c b/source/memory/data_encoding.c index c8bd221a..57595c3e 100644 --- a/source/memory/data_encoding.c +++ b/source/memory/data_encoding.c @@ -528,6 +528,10 @@ void *data_decode_array( case -8: element_count = (long)data_decode_int64(state); break; + /* element_count is left unassigned only by this default arm. Not reached unassigned: the + * arm's assertion failure calls system_exit, which does not return in January + * (0x47c960 jumps to halt_and_catch_fire 0x4f21c0, which loops or calls exit). + * Source-policy approval pending (2026-09-27 audit). */ default: display_assert(NULL, "c:\\halo\\SOURCE\\memory\\data_encoding.c", 370, TRUE); system_exit(-1); diff --git a/source/networking/network_server_manager.c b/source/networking/network_server_manager.c index 8845e740..6cfed327 100644 --- a/source/networking/network_server_manager.c +++ b/source/networking/network_server_manager.c @@ -849,6 +849,14 @@ void network_game_server_dispose( struct message_server_graceful_game_exit_pregame message_packet; struct network_message *message; + /* BUG (preserved for exact matching): message_packet is sent without being + * initialised. January serialises the reused argument slot [ebp+8], which still + * holds the server pointer, so four bytes of a host address go to every machine + * (0x51e250 +0x56 lea ecx,[ebp+8] for this pregame message, +0x3b lea eax,[ebp+8] + * for the postgame one below; tools/test_network_server_dispose_payloads.py). The + * receiving client decodes the field but does not read it. Reached whenever a server + * in the pregame or postgame state is disposed. A corrected build should + * zero-initialise both payloads. Source-policy approval pending (2026-09-27 audit). */ message = create_network_game_message( _message_server_graceful_game_exit_pregame, &message_packet, diff --git a/source/objects/damage.c b/source/objects/damage.c index d79414d8..3d19af3d 100644 --- a/source/objects/damage.c +++ b/source/objects/damage.c @@ -95,7 +95,8 @@ symbols in this file: 002896BC 0004: __real@3a422e45 (0000) 00456E48 004c: - _damage_globals (0000) + ?default_damage_material@?1??object_cause_damage@@9@9 (0000) + _global_debug_damage_object_index (0048) */ /* ---------- headers */ @@ -242,12 +243,6 @@ enum /* ---------- structures */ -struct damage_globals -{ - struct damage_resistance_material default_damage_material; - long debug_object_index; -}; - struct damage_region { char name[TAG_STRING_LENGTH+1]; @@ -362,7 +357,12 @@ static void object_destroy_region( extern boolean debug_damage; -static struct damage_globals damage_globals = { 0 }; +/* Name and type from the 2003 PC demo PDB ONLY (file static long); HCEX has no such static, so + the name is singly attested. January corroborates the storage: .bss +0x48, after + object_cause_damage's default material. Both statics are uninitialised and VC7 orders + uninitialised statics by a hash of their names, so this name takes part in producing + January's order; no other name was tested. */ +static long global_debug_damage_object_index; /* ---------- public code */ @@ -378,7 +378,7 @@ void damage_dispose(void) void damage_initialize_for_new_map(void) { - damage_globals.debug_object_index = NONE; + global_debug_damage_object_index = NONE; return; } @@ -669,7 +669,7 @@ void render_debug_object_damage( rectangle2d bounds = render.camera.window_bounds; bounds.x0 += 320; - if (damage_globals.debug_object_index == NONE) + if (global_debug_damage_object_index == NONE) { _snprintf( buffer, @@ -679,7 +679,7 @@ void render_debug_object_damage( else { struct object_datum *object = - object_try_and_get(damage_globals.debug_object_index); + object_try_and_get(global_debug_damage_object_index); if (object) { @@ -697,7 +697,7 @@ void render_debug_object_damage( } else { - damage_globals.debug_object_index = NONE; + global_debug_damage_object_index = NONE; } } @@ -728,7 +728,7 @@ void render_debug_object_damage( "c:\\halo\\SOURCE\\objects\\damage.c", 0x794, collision.type==_collision_result_object); - damage_globals.debug_object_index = collision.object_index; + global_debug_damage_object_index = collision.object_index; } } } @@ -1337,6 +1337,11 @@ void object_cause_damage( short material_index, real_vector3d const *object_normal) { + /* Name and function scope from the 2003 PC demo PDB and the HCEX PDB (static local of + object_cause_damage; their type is named damage_material). Neither PDB records the block: + placing it at the top of the function is unattested. January corroborates: .bss +0, and only + this function takes its address. */ + static struct damage_resistance_material default_damage_material; struct damage_effect_definition *damage_effect; struct damage_definition const *damage_definition; boolean damage_was_modified; @@ -1367,7 +1372,7 @@ void object_cause_damage( (region_index>=0 && region_indexowner_player_index != NONE) - damage_globals.debug_object_index = object_index; + global_debug_damage_object_index = object_index; { real random_damage = real_random_range( @@ -1628,7 +1633,7 @@ void object_cause_damage( } else { - damage_material = &damage_globals.default_damage_material; + damage_material = &default_damage_material; } damage->material_type = damage_material->material_type; @@ -1734,7 +1739,7 @@ void object_cause_damage( } if (debug_damage && - current_object_index == damage_globals.debug_object_index) + current_object_index == global_debug_damage_object_index) { console_printf( FALSE, diff --git a/source/objects/object_lights.c b/source/objects/object_lights.c index 9e77ec23..b5cacc88 100644 --- a/source/objects/object_lights.c +++ b/source/objects/object_lights.c @@ -238,7 +238,7 @@ enum ((struct light_datum *)datum_get(light_data, (index))) #define light_definition_get(index) \ - ((struct light_definition *)tag_get(LIGHT_DEFINITION_TAG, (index))) + ((struct point_light_definition *)tag_get(LIGHT_DEFINITION_TAG, (index))) #define lens_flare_definition_get(index) \ ((struct lens_flare_definition *)tag_get(LENS_FLARE_DEFINITION_TAG, (index))) @@ -289,7 +289,7 @@ struct lights_game_globals byte reserved01[3]; }; -struct light_definition +struct point_light_definition { long flags; real radius; @@ -360,16 +360,6 @@ struct rasterizer_lens_flare_submit_parameters long internal_occlusion_pixels; }; -struct rasterizer_light_submit_parameters -{ - struct light_definition *definition; - real_point3d position; - real_vector3d forward; - real_vector3d up; - real_rgb_color color; - real radius; -}; - struct lights_globals { boolean marker_initialized; @@ -390,13 +380,13 @@ typedef char verify_light_datum_flags_offset[ typedef char verify_light_datum_cluster_reference_offset[ offsetof(struct light_datum, cluster_reference) == 0x10 ? 1 : -1]; typedef char verify_light_definition_lens_flare_offset[ - offsetof(struct light_definition, lens_flare) == 0xAC ? 1 : -1]; + offsetof(struct point_light_definition, lens_flare) == 0xAC ? 1 : -1]; typedef char verify_light_definition_color_offset[ - offsetof(struct light_definition, color_interpolation_flags) == 0x34 ? 1 : -1]; + offsetof(struct point_light_definition, color_interpolation_flags) == 0x34 ? 1 : -1]; typedef char verify_light_definition_transition_duration_offset[ - offsetof(struct light_definition, transition_duration) == 0xF4 ? 1 : -1]; + offsetof(struct point_light_definition, transition_duration) == 0xF4 ? 1 : -1]; typedef char verify_light_definition_falloff_function_offset[ - offsetof(struct light_definition, falloff_function) == 0xFA ? 1 : -1]; + offsetof(struct point_light_definition, falloff_function) == 0xFA ? 1 : -1]; typedef char verify_light_datum_size[ sizeof(struct light_datum) == 0x7C ? 1 : -1]; typedef char verify_rasterizer_light_submit_parameters_size[ @@ -727,7 +717,7 @@ long light_new( short object_function_index, short object_change_color_index) { - struct light_definition *definition = light_definition_get(definition_index); + struct point_light_definition *definition = light_definition_get(definition_index); long light_index = NONE; if (TEST_FLAG(definition->flags, _light_definition_dynamic_bit) @@ -772,7 +762,7 @@ long light_new_unattached( if (light_index != NONE) { struct light_datum *light = light_get(light_index); - struct light_definition *definition = light_definition_get(definition_index); + struct point_light_definition *definition = light_definition_get(definition_index); light->flags = 0; light->parent_light_index = game_time_get(); @@ -824,7 +814,7 @@ void lights_preprocess_scene( light->rasterizer_light_index = NONE; if (light->parent_light_index != NONE) { - struct light_definition *definition = light_definition_get( + struct point_light_definition *definition = light_definition_get( light->definition_index); real elapsed = (real)(current_time - light->parent_light_index); @@ -869,7 +859,7 @@ void lights_preprocess_scene( { long scene_light_handle = lights_globals.scene_point_lights[scene_light_index]; struct light_datum *light = light_get(scene_light_handle); - struct light_definition *definition = light_definition_get( + struct point_light_definition *definition = light_definition_get( light->definition_index); struct object_datum *object; real intensity; @@ -1442,7 +1432,7 @@ static void render_debug_light( if (debug_lights) { struct light_datum *light = light_get(light_index); - struct light_definition *definition = light_definition_get(light->definition_index); + struct point_light_definition *definition = light_definition_get(light->definition_index); real radius = definition->radius_modifier_upper_bound * definition->radius; real_argb_color color = *global_real_argb_orange; @@ -1541,7 +1531,7 @@ static void light_compute_bounding_sphere( real *radius) { struct light_datum *light = light_get(light_index); - struct light_definition *definition = light_definition_get(light->definition_index); + struct point_light_definition *definition = light_definition_get(light->definition_index); real light_radius = maximum ? definition->radius_modifier_upper_bound * definition->radius : light->radius; @@ -1745,7 +1735,7 @@ void light_reconnect_to_map( long light_index) { struct light_datum *light = light_get(light_index); - struct light_definition *definition = light_definition_get(light->definition_index); + struct point_light_definition *definition = light_definition_get(light->definition_index); struct object_marker markers[1]; struct location location; real_point3d position; diff --git a/source/physics/breakable_surfaces.c b/source/physics/breakable_surfaces.c index 68374bd3..8b2bd348 100644 --- a/source/physics/breakable_surfaces.c +++ b/source/physics/breakable_surfaces.c @@ -215,6 +215,11 @@ void breakable_surface_damage_area_of_effect( if (cutoff_radius > 4.0f) { + /* BUG (preserved for exact matching): %d is given a real, which the variadic call + * passes as a double (January 0x536430 +0x73..+0x79 fstp qword [esp]), so the + * message prints the double's low word. Reached for damaging area-of-effect damage + * with a cutoff radius above 4 while breakable surfaces are enabled. A corrected + * build should use %f. Source-policy approval pending (2026-09-27 audit). */ error(_error_silent, "WARNING: area of effect breakable surface damage with radius %d", cutoff_radius); } diff --git a/source/physics/collisions.c b/source/physics/collisions.c index cc0c6e36..b19c4d81 100644 --- a/source/physics/collisions.c +++ b/source/physics/collisions.c @@ -195,27 +195,6 @@ static void collision_fix_pill_nudge_collision( struct collision_plane *collision); /* ---------- globals */ -static real_vector3d collision_fix_pill_offsets[17] = -{ - { { -1.0f, 0.0f, 0.0f } }, - { { 1.0f, 0.0f, 0.0f } }, - { { 0.0f, -1.0f, 0.0f } }, - { { 0.0f, 1.0f, 0.0f } }, - { { -0.70710677f, -0.70710677f, 0.0f } }, - { { 0.70710677f, 0.70710677f, 0.0f } }, - { { 0.70710677f, -0.70710677f, 0.0f } }, - { { -0.70710677f, 0.70710677f, 0.0f } }, - { { 0.0f, 0.0f, 1.0f } }, - { { -0.70710677f, 0.0f, 0.70710677f } }, - { { 0.70710677f, 0.0f, 0.70710677f } }, - { { 0.0f, -0.70710677f, 0.70710677f } }, - { { 0.0f, 0.70710677f, 0.70710677f } }, - { { -0.57735026f, -0.57735026f, 0.57735026f } }, - { { 0.57735026f, 0.57735026f, 0.57735026f } }, - { { 0.57735026f, -0.57735026f, 0.57735026f } }, - { { -0.57735026f, 0.57735026f, 0.57735026f } }, -}; - static struct collision_usage_times collision_usage_times; boolean debug_collision_skip_objects = FALSE; boolean debug_collision_skip_vectors = FALSE; @@ -904,6 +883,30 @@ boolean collision_fix_pill( long ignore_object_index, real_point3d *new_position) { + /* Name, type and function scope: PC demo and HCEX PDBs. + * January confirms the 204-byte array and this function as its sole user. + * The declaration's precise block position is not independently attested. + */ + static real_vector3d offsets[17] = + { + { { -1.0f, 0.0f, 0.0f } }, + { { 1.0f, 0.0f, 0.0f } }, + { { 0.0f, -1.0f, 0.0f } }, + { { 0.0f, 1.0f, 0.0f } }, + { { -0.70710677f, -0.70710677f, 0.0f } }, + { { 0.70710677f, 0.70710677f, 0.0f } }, + { { 0.70710677f, -0.70710677f, 0.0f } }, + { { -0.70710677f, 0.70710677f, 0.0f } }, + { { 0.0f, 0.0f, 1.0f } }, + { { -0.70710677f, 0.0f, 0.70710677f } }, + { { 0.70710677f, 0.0f, 0.70710677f } }, + { { 0.0f, -0.70710677f, 0.70710677f } }, + { { 0.0f, 0.70710677f, 0.70710677f } }, + { { -0.57735026f, -0.57735026f, 0.57735026f } }, + { { 0.57735026f, 0.57735026f, 0.57735026f } }, + { { 0.57735026f, -0.57735026f, 0.57735026f } }, + { { -0.57735026f, 0.57735026f, 0.57735026f } }, + }; boolean result = FALSE; struct collision_feature_list features; struct collision_plane first_collision; @@ -948,10 +951,10 @@ boolean collision_fix_pill( have_fallback = FALSE; for (offset_index = 0; - offset_index < NUMBEROF(collision_fix_pill_offsets); + offset_index < NUMBEROF(offsets); offset_index++) { - real_vector3d const *offset = &collision_fix_pill_offsets[offset_index]; + real_vector3d const *offset = &offsets[offset_index]; real_point3d candidate; candidate.x = offset->i * distance + old_position->x; diff --git a/source/rasterizer/rasterizer.c b/source/rasterizer/rasterizer.c index 191a93c8..60599be6 100644 --- a/source/rasterizer/rasterizer.c +++ b/source/rasterizer/rasterizer.c @@ -2035,6 +2035,13 @@ void rasterizer_debug_model_vertices( camera_dot = dot_product3d( &camera_to_vertex, &global_window_parameters.camera.forward); + /* BUG (preserved for exact matching): closest_debug_vertex_dot is never initialised + * (only closest_debug_vertex_index is), so the first vertex compares an unassigned + * real here (January 0x56cb00 reads [ebp-0x2c] at +0x496 and +0x4a3; its only store + * is +0x4b9). Reached whenever the hs global rasterizer_debug_model_vertices is set + * and the obscuring object is drawn; the value only chooses which vertex label is + * drawn red. A corrected build should initialise it to -1.0f. Source-policy approval + * pending (2026-09-27 audit). */ if ((dot_product3d(&camera_to_vertex, &normal) < 0.f && closest_debug_vertex_dot < camera_dot) || closest_debug_vertex_dot == -1.f) diff --git a/source/rasterizer/rasterizer_lights.c b/source/rasterizer/rasterizer_lights.c index d4dc878f..6770eb10 100644 --- a/source/rasterizer/rasterizer_lights.c +++ b/source/rasterizer/rasterizer_lights.c @@ -312,23 +312,6 @@ struct rasterizer_lens_flare_submit_parameters long internal__occlusion_pixels; }; -struct rasterizer_light_submit_parameters -{ - struct point_light_definition *definition; - real_point3d position; - real_vector3d forward; - real_vector3d up; - real_rgb_color color; - real radius; -}; - -struct rasterizer_lights_globals -{ - long light_count; - struct rasterizer_light_submit_parameters lights[MAXIMUM_LIGHTS_PER_WINDOW]; - long fixed_function_light_count; -}; - typedef char verify_structure_cluster_size[ sizeof(struct structure_cluster) == 0x68 ? 1 : -1]; typedef char verify_structure_cluster_lens_flare_marker_count_offset[ @@ -370,7 +353,6 @@ static struct lens_flare_occlusion_test_results local_lens_flare_occlusion_test_ static byte local_lens_flare_occlusion_test_results2[MAXIMUM_LENS_FLARE_MARKERS_PER_STRUCTURE+MAXIMUM_QUEUED_LENS_FLARES][MAXIMUM_WINDOWS]; static struct rasterizer_lens_flare_submit_parameters local_lens_flare_parameters[MAXIMUM_LENS_FLARES_PER_FRAME] = {0}; static long local_lens_flare_count = 0; -extern struct rasterizer_lights_globals rasterizer_lights; extern struct rasterizer_window_begin_parameters global_window_parameters; extern short global_screenshot_count; extern short global_screenshot_size; diff --git a/source/rasterizer/rasterizer_lights.h b/source/rasterizer/rasterizer_lights.h index 981cca05..3ded0c2b 100644 --- a/source/rasterizer/rasterizer_lights.h +++ b/source/rasterizer/rasterizer_lights.h @@ -9,7 +9,22 @@ RASTERIZER_LIGHTS.H /* ---------- structures */ struct rasterizer_lens_flare_submit_parameters; -struct rasterizer_light_submit_parameters; + +struct rasterizer_light_submit_parameters +{ + struct point_light_definition *definition; + real_point3d position; + real_vector3d forward; + real_vector3d up; + real_rgb_color color; + real radius; +}; + +struct rasterizer_lights +{ + long light_count; + struct rasterizer_light_submit_parameters lights[MAXIMUM_LIGHTS_PER_WINDOW]; +}; /* ---------- prototypes/RASTERIZER_LIGHTS.C */ @@ -28,4 +43,8 @@ void rasterizer_lens_flares_draw( void rasterizer_sun_glow_draw( struct rasterizer_lens_flare_submit_parameters const *parameters); +/* ---------- globals */ + +extern struct rasterizer_lights rasterizer_lights; + #endif // __RASTERIZER_LIGHTS_H diff --git a/source/rasterizer/xbox/rasterizer_xbox.c b/source/rasterizer/xbox/rasterizer_xbox.c index 9ed41418..79622a71 100644 --- a/source/rasterizer/xbox/rasterizer_xbox.c +++ b/source/rasterizer/xbox/rasterizer_xbox.c @@ -720,30 +720,20 @@ struct point_light_definition struct point_light_geometry_parameters geometry; }; -struct rasterizer_light_submit_parameters -{ - struct point_light_definition *definition; - real_point3d position; - real_vector3d forward; - real_vector3d up; - real_rgb_color color; - real radius; -}; -struct rasterizer_lights_globals_prefix +/* the shell's window globals (HCEX `struct window_data`, 0x94 bytes, the size + * of January's pooled window_globals record); this object only reads + * hWndPresentTarget (+8), the name its own IDirect3DDevice8_Present() error + * string spells. */ +struct window_data { - long light_count; - struct rasterizer_light_submit_parameters lights[MAXIMUM_RENDERED_LIGHTS]; -}; - - -/* the platform window globals; only the field this object uses is named, and - * that name comes from this object's own IDirect3DDevice8_Present() error - * string. */ -struct window_globals_prefix -{ - byte reserved00[8]; + HINSTANCE hInstance; + HWND hWnd; HWND hWndPresentTarget; + int nCmdShow; + void *MainWndProc; + char class_name[0x40]; + char window_title[0x40]; }; struct rasterizer_model_skinning_parameters @@ -851,11 +841,9 @@ static struct rasterizer_hardware_state_cache rasterizer_state_cache = }; -extern struct window_globals_prefix window_globals; +extern struct window_data window_globals; extern struct rasterizer_window_begin_parameters global_window_parameters; -extern struct rasterizer_lights_globals_prefix rasterizer_lights; - /* owned by source/bitmaps/bitmaps.c */ extern pixel32 global_vector_palette[NUMBER_OF_ENTRIES_IN_PALETTE]; @@ -3473,6 +3461,10 @@ void *rasterizer_get_bitmap_default_hardware_format( hardware_format = rasterizer_default_cm_hardware_format; break; + /* hardware_format is left unassigned only by this default arm. Not reached unassigned: the + * arm's assertion failure calls system_exit, which does not return in January + * (0x47c960 jumps to halt_and_catch_fire 0x4f21c0, which loops or calls exit). + * Source-policy approval pending (2026-09-27 audit). */ default: display_assert( "### ERROR unsupported bitmap type", diff --git a/source/rasterizer/xbox/rasterizer_xbox_debug.h b/source/rasterizer/xbox/rasterizer_xbox_debug.h index 9896b12e..9a02982c 100644 --- a/source/rasterizer/xbox/rasterizer_xbox_debug.h +++ b/source/rasterizer/xbox/rasterizer_xbox_debug.h @@ -12,6 +12,12 @@ RASTERIZER_XBOX_DEBUG.H /* ---------- prototypes/RASTERIZER_XBOX_DEBUG.C */ +/* rasterizer_xbox_debug.c defines rasterizer_debug_drawing_begin with the single + * parameter opaque, as rasterizer.h declares it. This declaration, used only by + * rasterizer_debug.c, adds zbias because January's rasterizer_debug_draw (0x56d9e0 + * +0x20e, +0x2ee, +0x3a0) pushes two arguments while the callee (0x549db0) reads only + * [ebp+8]. The two declarations conflict (C4031); under cdecl the callee ignores the + * extra argument. Source-policy approval pending (2026-09-27 audit). */ void rasterizer_debug_drawing_begin( boolean opaque, long zbias); diff --git a/source/rasterizer/xbox/rasterizer_xbox_environment.c b/source/rasterizer/xbox/rasterizer_xbox_environment.c index f471cae6..4a20767c 100644 --- a/source/rasterizer/xbox/rasterizer_xbox_environment.c +++ b/source/rasterizer/xbox/rasterizer_xbox_environment.c @@ -156,6 +156,7 @@ symbols in this file: #include "rasterizer/common/rasterizer_common.h" #include "rasterizer/rasterizer_frame_statistics.h" #include "rasterizer/rasterizer_geometry.h" +#include "rasterizer/rasterizer_lights.h" #include "rasterizer/rasterizer_memory_pool.h" #include "rasterizer/rasterizer_transparent_geometry.h" #include "shaders/shader_definitions.h" @@ -429,22 +430,6 @@ struct point_light_definition struct point_light_gel_parameters gel; }; -struct rasterizer_light_submit_parameters -{ - struct point_light_definition *definition; - real_point3d position; - real_vector3d forward; - real_vector3d up; - real_rgb_color color; - real radius; -}; - -struct rasterizer_lights_globals -{ - long light_count; - struct rasterizer_light_submit_parameters lights[128]; -}; - struct shader_environment_diffuse_properties { word flags; @@ -572,7 +557,6 @@ extern struct rasterizer_environment_debug_options rasterizer_debug_options; static struct rasterizer_environment_globals rasterizer_environment_globals; static boolean warned = FALSE; extern struct pixel_shader_definition pixel_shader; -extern struct rasterizer_lights_globals rasterizer_lights; extern struct rasterizer_window_begin_parameters global_window_parameters; short specular_light_vertex_shader_permutation_index= NONE; diff --git a/source/rasterizer/xbox/rasterizer_xbox_hardware_geometry.c b/source/rasterizer/xbox/rasterizer_xbox_hardware_geometry.c index e671c938..46dd4e14 100644 --- a/source/rasterizer/xbox/rasterizer_xbox_hardware_geometry.c +++ b/source/rasterizer/xbox/rasterizer_xbox_hardware_geometry.c @@ -267,6 +267,12 @@ boolean rasterizer_triangle_buffer_new( result, "IDirect3DDevice8_CreateIndexBuffer(global_d3d_device, buffer_size, RASTERIZER_STATIC_BUFFER_USAGE, D3DFMT_INDEX16, RASTERIZER_STATIC_BUFFER_POOL, &d3d_index_buffer)"); } + /* BUG (preserved for exact matching): as in rasterizer_vertex_buffer_new, the + * January XDK CreateIndexBuffer failure path (0x5de5d3..0x5de5d8) returns without + * writing d3d_index_buffer, so after a failed call this test reads it unassigned. + * success is already FALSE on that path and the pointer is cleared below, so the + * result does not depend on the value. Source-policy approval pending (2026-09-27 + * audit). */ if (!d3d_index_buffer) success = FALSE; if (!success) diff --git a/source/rasterizer/xbox/rasterizer_xbox_transparent_geometry.c b/source/rasterizer/xbox/rasterizer_xbox_transparent_geometry.c index d1f90e48..73aaa94d 100644 --- a/source/rasterizer/xbox/rasterizer_xbox_transparent_geometry.c +++ b/source/rasterizer/xbox/rasterizer_xbox_transparent_geometry.c @@ -145,6 +145,8 @@ symbols in this file: #include "rasterizer/xbox/rasterizer_xbox_draw_primitives.h" #include "rasterizer/common/rasterizer_common.h" #include "text/draw_string.h" +#include "interface/hud.h" +#include "interface/hud_definitions.h" #include "interface/hud_draw.h" #include "bitmaps/bitmap_color_conversion.h" #include "bitmaps/bitmap_group.h" @@ -694,12 +696,6 @@ typedef char transparent_geometry_group_active_camouflage_offset_assert[ offsetof(struct transparent_geometry_group, active_camouflage_transparent_source_object_index) == 0x98 ? 1 : -1]; -struct rasterizer_transparent_geometry_hud_globals_prefix -{ - byte reserved00[0x54]; - long single_player_font_index; -}; - struct rasterizer_xbox_transparent_geometry_globals { long last_source_object_index; @@ -720,7 +716,6 @@ static struct rasterizer_xbox_transparent_geometry_globals extern struct rasterizer_transparent_geometry_debug_options_prefix rasterizer_debug_options; extern struct rasterizer_window_begin_parameters global_window_parameters; -extern struct rasterizer_transparent_geometry_hud_globals_prefix *hud_globals; /* ---------- public code */ @@ -865,7 +860,7 @@ void rasterizer_transparent_geometry_groups_end( if (global_window_parameters.window_index == main_get_window_count()-1) { - long font_index = hud_globals->single_player_font_index; + long font_index = hud_globals->messaging.single_player_font.index; if (font_index != NONE) { @@ -2216,6 +2211,10 @@ void rasterizer_transparent_geometry_group_draw( combiner_constant = 0x05; break; + /* combiner_constant is left unassigned only by this default arm. Not reached unassigned: the + * arm's assertion failure calls system_exit, which does not return in January + * (0x47c960 jumps to halt_and_catch_fire 0x4f21c0, which loops or calls exit). + * Source-policy approval pending (2026-09-27 audit). */ default: match_vassert( "c:\\halo\\SOURCE\\rasterizer\\xbox\\rasterizer_xbox_transparent_geometry.c", @@ -2727,6 +2726,10 @@ void rasterizer_transparent_geometry_group_draw( combiner_constant = 0x05; break; + /* combiner_constant is left unassigned only by this default arm. Not reached unassigned: the + * arm's assertion failure calls system_exit, which does not return in January + * (0x47c960 jumps to halt_and_catch_fire 0x4f21c0, which loops or calls exit). + * Source-policy approval pending (2026-09-27 audit). */ default: match_vassert( "c:\\halo\\SOURCE\\rasterizer\\xbox\\rasterizer_xbox_transparent_geometry.c", diff --git a/source/render/render_particles.c b/source/render/render_particles.c index 155c977b..d78a82d8 100644 --- a/source/render/render_particles.c +++ b/source/render/render_particles.c @@ -209,6 +209,12 @@ void render_particles( rendered_particle->attached_to_first_person_weapon == previous_attached_to_first_person_weapon) { + /* current_sprite_group is not initialised. Not reached unassigned: the first + * rendered particle cannot take this arm, because its definition index differs from + * the initial NONE (particle_new returns for NONE and otherwise calls + * particle_definition_get, whose tag lookup halts unless the low word of the index + * is non-negative; the field is written nowhere else). Source-policy approval + * pending (2026-09-27 audit). */ (*current_sprite_group)++; } else diff --git a/source/render/render_sprite.c b/source/render/render_sprite.c index 1666cf40..237428f0 100644 --- a/source/render/render_sprite.c +++ b/source/render/render_sprite.c @@ -203,8 +203,6 @@ struct tag_enum_definition global_sprite_render_orientations_enum = real const one_over_full_circle = 1.f / (2.f*_pi); -static boolean build_sprite_vertex_allocation_failure_reported; - /* ---------- public code */ void build_sprites_begin( @@ -769,6 +767,10 @@ static short build_sprite_get_group( struct build_sprite_data *data, struct bitmap_data *bitmap) { + /* Name, type and function scope from the 2003 PC demo PDB and the HCEX PDB (static local + unsigned char warned). Neither PDB records the block: placing it at the top of the function + is unattested. January corroborates: its one-byte .bss is referenced only here. */ + static boolean warned; short group_index; for (group_index = 0; group_index < data->group_count; group_index++) @@ -813,12 +815,12 @@ static short build_sprite_get_group( } else { - if (!build_sprite_vertex_allocation_failure_reported) + if (!warned) { error( _error_silent, "build_sprite failed to allocate dynamic vertices"); - build_sprite_vertex_allocation_failure_reported = TRUE; + warned = TRUE; } group->vertices = NULL; } diff --git a/source/saved games/saved_game_files.c b/source/saved games/saved_game_files.c index 5d7f43bc..c179191e 100644 --- a/source/saved games/saved_game_files.c +++ b/source/saved games/saved_game_files.c @@ -1878,6 +1878,12 @@ static void enumerate_memory_units( find_data.szSaveGameName, find_data.wfd.cFileName); message[MAXIMUM_FILENAME_LENGTH] = 0; + /* BUG (preserved for exact matching): the message embeds the save's display name + * and file name and is passed as the format (January 0x5b4b00 +0x263 pushes the + * converted text as error's format), so a '%' in either is taken as a conversion. + * Reached for a saved-game directory holding neither blam.sav nor blam.lst; whether + * such a directory occurs is not shown. A corrected build should pass the text + * through "%s". Source-policy approval pending (2026-09-27 audit). */ error( _error_silent, wide_to_ascii(message, (char *)message, sizeof(message))); diff --git a/source/scenario/scenario_definitions.h b/source/scenario/scenario_definitions.h index b0647e36..700d3822 100644 --- a/source/scenario/scenario_definitions.h +++ b/source/scenario/scenario_definitions.h @@ -209,6 +209,38 @@ struct encounter_player_starting_location char __unknown1c[24]; }; +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]; +}; + struct scenario { struct tag_reference ugly_structure_bsp; diff --git a/source/sound/sound_dsound_xbox.c b/source/sound/sound_dsound_xbox.c index b54b7c02..0ea6083a 100644 --- a/source/sound/sound_dsound_xbox.c +++ b/source/sound/sound_dsound_xbox.c @@ -2826,6 +2826,11 @@ static void dsound_error( break; } + /* BUG (preserved for exact matching): the format has three conversions but January + * passes two values (0x5b93e0 +0x93..+0xa2), so "#%d" prints the next stack word. + * Reached on every DirectSound failure reported through dsound_error. A corrected + * build should pass result as the third value. Source-policy approval pending + * (2026-09-27 audit). */ error(_error_silent, "DirectSound: '%s' (%s#%d)", message, result_name); return; diff --git a/source/sound/sound_manager.c b/source/sound/sound_manager.c index 319af9a1..d70f3d27 100644 --- a/source/sound/sound_manager.c +++ b/source/sound/sound_manager.c @@ -2044,6 +2044,10 @@ static real source_distance_squared( source->location.position.z * source->location.position.z; break; + /* distance_squared is left unassigned only by this default arm. Not reached unassigned: the + * arm's assertion failure calls system_exit, which does not return in January + * (0x47c960 jumps to halt_and_catch_fire 0x4f21c0, which loops or calls exit). + * Source-policy approval pending (2026-09-27 audit). */ default: match_vassert( "c:\\halo\\SOURCE\\sound\\sound_manager.c", diff --git a/source/tag_files/files.c b/source/tag_files/files.c index e604f97f..3d8e99d7 100644 --- a/source/tag_files/files.c +++ b/source/tag_files/files.c @@ -356,6 +356,13 @@ boolean datastore_read( } } + /* BUG (preserved for exact matching): success is never initialised, so a missing + * file, a wrong-sized datastore or an absent field returns it unassigned (January + * 0x589370 keeps it in the high byte of the field_name argument slot, [ebp+0xf], + * written only at +0x1f5 and read at +0x19b and +0x20c). Not reached in January: + * cachebeta.exe has no call, jump or address reference to this function. A corrected + * build should initialise success to FALSE. Source-policy approval pending + * (2026-09-27 audit). */ return success; } diff --git a/source/units/unit_dialogue.c b/source/units/unit_dialogue.c index cab1975a..f614baef 100644 --- a/source/units/unit_dialogue.c +++ b/source/units/unit_dialogue.c @@ -919,6 +919,10 @@ boolean unit_scream( case _unit_scream_resurrection: vocalization_type = _vocalization_resurrect; break; + /* vocalization_type is left unassigned only by this default arm. Not reached unassigned: the + * arm's assertion failure calls system_exit, which does not return in January + * (0x47c960 jumps to halt_and_catch_fire 0x4f21c0, which loops or calls exit). + * Source-policy approval pending (2026-09-27 audit). */ default: match_assert( "c:\\halo\\SOURCE\\units\\unit_dialogue.c",