From c32247e7651d680dcd133d72b2fbf4e8009cc124 Mon Sep 17 00:00:00 2001 From: Jonas Volman Date: Sat, 5 Sep 2026 22:24:15 -0700 Subject: [PATCH] Reconcile ActionObey shared owners and verified structure flush --- config/parked.json | 6 +- ...bj_api_leaf_independent_review_20260905.md | 152 ++++++++ ..._obey_obj_private_closure_plan_20260905.md | 142 ++++++++ ...structure_flush_reconciliation_20260905.md | 163 +++++++++ ...bey_obj_shared_schema_evidence_20260905.md | 340 ++++++++++++++++++ ...j_shared_schema_residual_proof_20260905.md | 83 +++++ ...itmaps_obj_fable_packet_intake_20260905.md | 151 ++++++++ ...session_reconciliation_backlog_20260903.md | 33 +- source/ai/action_charge.c | 3 - source/ai/action_obey.c | 19 +- source/ai/actions.c | 16 - source/ai/actions.h | 29 ++ source/ai/actor_perception.c | 20 +- source/ai/actor_type_infection.c | 53 --- source/ai/actors.c | 14 - source/ai/actors.h | 40 +++ source/ai/ai_scenario_definitions.h | 23 ++ source/cutscene/recorded_animations.h | 10 + source/game/player_control.c | 5 - source/game/players.c | 2 +- source/hs/hs.c | 10 +- source/units/bipeds.c | 6 - source/units/bipeds.h | 7 +- source/units/units.c | 10 +- 24 files changed, 1187 insertions(+), 150 deletions(-) create mode 100644 docs/object_matching_logs/action_obey_obj_api_leaf_independent_review_20260905.md create mode 100644 docs/object_matching_logs/action_obey_obj_private_closure_plan_20260905.md create mode 100644 docs/object_matching_logs/action_obey_obj_shared_schema_and_structure_flush_reconciliation_20260905.md create mode 100644 docs/object_matching_logs/action_obey_obj_shared_schema_evidence_20260905.md create mode 100644 docs/object_matching_logs/action_obey_obj_shared_schema_residual_proof_20260905.md create mode 100644 docs/object_matching_logs/bitmaps_obj_fable_packet_intake_20260905.md diff --git a/config/parked.json b/config/parked.json index 8399d9e4..0b32b5c7 100644 --- a/config/parked.json +++ b/config/parked.json @@ -2777,7 +2777,7 @@ "unit": "source/ai/ai_communication", "function": "_ai_communication_update_speech_timers", "class": "register-allocation", - "evidence": "Fuzzy-parked under the current house rule after restoring the complete typed speech-timer update through its genuine ai_communication_started caller. Independent HCEA source authenticates the semantic ai_communication_update_speech_timers and actor_reset_idle_vocalization_timer names; the retained implementation uses unit_get and actor_get, named speech-priority constants, the typed AI communication globals, and the established dialogue/reply table structures. Target and candidate are both 672 padded bytes with all 43 relocation identities. The owning game_sound.h migration previously measured 97.67839 percent. The September 5 genuine Encounters platoon schema and named flag additions naturally transpose only two independent stack loads at +0x167..0x16E; the unchanged source now measures 97.76382 percent. Complete thirteen-consumer inspection preserves all other runtime records apart from compiler-local label spelling, with no new owner, helper, COMMON, ABI change, or inherited strict loss. Root independently verifies that both loads use distinct destinations and stack locations, change no flags, and have no incoming branch inside the reordered block. See docs/object_matching_logs/encounters_obj_initialize_cluster_natural_20260905.md. The remaining gap is the previously documented C2 register/lifetime schedule: January retains the unit in EDI and time in ESI while the natural candidate selects the inverse allocation, with a small associated load-order tie. Prior bounded declaration, initialization, and expression-order probes did not close it naturally. No register hint, volatile access, barrier, pragma, assembly, fake dependency, false alias, raw offset, forced inline/noinline, or nonsensical branch is retained. Reopen only for authoritative January source/local records or a natural same-compiler donor explaining the register lifetimes.", + "evidence": "Fuzzy-parked under the current house rule after restoring the complete typed speech-timer update through its genuine ai_communication_started caller. Independent HCEA source authenticates the semantic ai_communication_update_speech_timers and actor_reset_idle_vocalization_timer names; the retained implementation uses unit_get and actor_get, named speech-priority constants, the typed AI communication globals, and the established dialogue/reply table structures. Target and candidate are both 672 padded bytes with all 43 relocation identities. The owning game_sound.h migration previously measured 97.67839 percent. The September 5 genuine Encounters platoon schema and named flag additions naturally transpose only two independent stack loads at +0x167..0x16E; the unchanged source then measured 97.76382 percent. Complete thirteen-consumer inspection preserves all other runtime records apart from compiler-local label spelling, with no new owner, helper, COMMON, ABI change, or inherited strict loss. Root independently verifies that both loads use distinct destinations and stack locations, change no flags, and have no incoming branch inside the reordered block. See docs/object_matching_logs/encounters_obj_initialize_cluster_natural_20260905.md. The remaining gap is the previously documented C2 register/lifetime schedule: January retains the unit in EDI and time in ESI while the natural candidate selects the inverse allocation, with a small associated load-order tie. Prior bounded declaration, initialization, and expression-order probes did not close it naturally. No register hint, volatile access, barrier, pragma, assembly, fake dependency, false alias, raw offset, forced inline/noinline, or nonsensical branch is retained. Reopen only for authoritative January source/local records or a natural same-compiler donor explaining the register lifetimes. The later September 5 shared swarm/biped owner-schema and API correction returns exactly those two independent stack loads to the prior 97.67839-percent order. Full frozen comparison across all 58 actual consumers preserves every one of the 6,233 inherited exact owners, all data/COMMON/owner contracts, and all other runtime records apart from compiler-local labels and the separately proven signed-word mask encoding change in infection_swarm_control. No speech-timer source change or schedule tuning was made. Both load orders have the same register, memory and flag effects on the valid-frame domain. See docs/object_matching_logs/action_obey_obj_shared_schema_and_structure_flush_reconciliation_20260905.md for the independent complete delta review.", "measurements": { "target": { "size": 672, @@ -2787,9 +2787,9 @@ "base": { "size": 672, "relocation_count": 43, - "normalized_sha256": "7db4861a5adf519e0457a0ffe785ff4d47e878fda47cc0a06206a529776ac91c" + "normalized_sha256": "885fdb81966284acf5ba7138a4bbbd2221e7c61c89114fdd6f53b96ba89b81a0" }, - "objdiff_percent": 97.76382 + "objdiff_percent": 97.67839 } }, { diff --git a/docs/object_matching_logs/action_obey_obj_api_leaf_independent_review_20260905.md b/docs/object_matching_logs/action_obey_obj_api_leaf_independent_review_20260905.md new file mode 100644 index 00000000..cee03719 --- /dev/null +++ b/docs/object_matching_logs/action_obey_obj_api_leaf_independent_review_20260905.md @@ -0,0 +1,152 @@ +# ActionObey public API and structure-flush leaf: independent admission review + +## Conclusion + +The frozen public-API owner packet is **admission-safe and runtime-neutral**. The structure-index flush leaf is also technically sound: it adds exactly one genuine public function owner, is a strict all-section match to January, preserves every inherited section, has the correct 32-bit C ABI and owner metadata, and matches January behavior in 1,024 bounded executions. It adds **46 meaningful / 48 padded code bytes** and no data credit. + +One provenance caveat remains for the root's policy decision. The body is typed, idiomatic, semantically corroborated, and contains no byte-forcing construct, but the Fable report explicitly says its exact source shape corrected the earlier 2026-08-21 miss by introducing the local `state_data` pointer. It therefore must not be described as an independently natural first candidate. If admission requires first-shot provenance rather than an authenticated exact reconstruction, this leaf needs explicit adjudication; its object, ABI, runtime, API-owner, and no-surplus evidence otherwise pass. + +This review does not cover the parallel shared swarm/enum schema packet. No production, donor, build, configuration, park, or frozen object was changed, and no compile or gate was run. + +## Source packet and owner boundary + +There is no `action_obey.h`. `source/ai/actions.h` is the genuine narrow owner because it already owns `action_specification`, all obey control/state records, the other action-family public declarations, and an explicit `prototypes/ACTION_OBEY.C` section. The frozen API change adds these nine target-public declarations there: + +```c +boolean action_obey_command_list_setup( + long actor_index, + short command_list_index, + struct obey_state_data *state_data); +void action_obey_flush_command_indices( + long actor_index); +void action_obey_flush_structure_indices( + long actor_index); +void action_obey_advance_command_list( + long actor_index); +void action_obey_begin( + long actor_index); +boolean action_obey_perform( + long actor_index); +void action_obey_update( + long actor_index); +void action_obey_control( + long actor_index); +void action_obey_end( + long actor_index); +``` + +`action_obey_describe_command` was already present in that owner section. Every added symbol is an external January function (`storage=2`, `type=0x20`, `value=0`, NODUP function COMDAT). The signatures agree with the existing consumer-local declarations, the `action_specification` callbacks, January's ordinary 32-bit stack accesses, and the retained HCEA semantics. In particular, `action_obey_command_list_setup(long, short, obey_state_data *)` preserves the pre-existing `actions.c` declaration exactly. + +The paired cleanup removes from `actions.c` only the now-owned local declarations for `action_obey_command_list_setup` and the five action-table callbacks (`begin`, `perform`, `update`, `control`, `end`). It later removes the local `actor_action_change` declaration from `action_obey.c`; `actions.h` already owns that exact three-argument declaration. Moving declarations does not create a definition, helper, or alternate ABI. + +The three no-current-cross-TU-call declarations (`flush_command_indices`, `flush_structure_indices`, and `advance_command_list`) are not synthetic helpers: all three are genuine external January owners. Later/HCEA callers also corroborate their public nature. `perform` and `control` are presently unwritten in canonical, but `actions.c` genuinely references both from the obey action table; their prototypes are necessary public contracts rather than promises invented for this leaf. + +The frozen public API source hashes are: + +- before: `actions.h` `f62df99f9ad20305ed01ebd09e120378aa513874dc3b990c2a07775a41e98086`, `actions.c` `3dbb2e77c2f4fd40cc0376589b9d3024f47f7a47d6e8375d8b0e9a3a616e44a2`; +- after: `actions.h` `962973471e872cf3f159ef06d1f8209c9a962a8fae5cac8bbb18e2e7d21146ac`, `actions.c` `f6347eb2573a36f12cf0c9253da66504441b8743269e8847fd3866770571d7ec`. + +At review time the current `actions.c` still has the frozen after hash, while `actions.h` has subsequently changed to `ea1bec48dfcc5bdad4dc01137e8c9d4a1f6aa878ee6f3eae4d0ef13e64aee62` from the root's parallel schema work. The nine API declarations themselves remain textually unchanged. This report makes no claim about that later schema content. + +## Public API dependent audit + +The capture script resolved all real `actions.h` dependencies from the Ninja graph and froze 47 objects. The before and after unit lists are identical. Independent review of the runtime summary found: + +- 47/47 units preserved; +- 3,079 runtime sections unchanged; +- 54 changes classified solely as compiler-local label spelling across 22 units; +- zero review-required units; +- zero runtime sections added, lost, or genuinely changed; +- zero genuine function-owner changes and zero new helpers; +- zero COMMON additions/removals; +- zero new `_point_from_line3d` emission or reference. + +The full stable verdict maps are byte-identical: both contain 8,245 entries and share SHA-256 `223b39e9a64198e10ff6dab9fe24a92b1d715b87e385c9389fee4188d6a0f458`. The captured park census is 284 active, 0 stale, 0 invalid. Thus the API move has no inherited exact/residual loss and no ordinary-link owner side effect. + +Primary frozen files: + +- `scratch/action-obey-public-api-before-20260905.json` — SHA-256 `22082d37d81366a681520949d9502107f7ea43b8e185f29936643cd07c89d0d5`; +- `scratch/action-obey-public-api-after-20260905.json` — SHA-256 `49d6f456321f119a67d25ac7324d82b4fc282d43cf1e86044f4a342e43284f65`; +- `scratch/action-obey-public-api-runtime-audit-20260905/summary.json` — SHA-256 `6f473b63e0918f9f085c664dbccebcac2c28668cfc2196a95e5a510504f70e9e`; +- `scratch/action-obey-public-api-parks-20260905.json` — SHA-256 `6c212dbc1d83de169bccde32a1c1ed3acc281d998bc8ec42ebe9e1b37e850cfa`. + +## Leaf body and source authenticity + +The current leaf is: + +```c +void action_obey_flush_structure_indices( + long actor_index) +{ + struct actor_datum *actor = actor_get(actor_index); + struct obey_state_data *state_data = &actor->state.action_data.obey; + + if (state_data->complex_control.destination_valid) + { + state_data->complex_control.destination_surface_index = NONE; + } + + return; +} +``` + +This is a genuine typed implementation. It uses the owning records, an existing typed actor accessor, the named valid/surface fields, and the repository's `NONE` constant. It contains no raw offset, cast reconstruction, aliasing trick, inline/optimizer directive, synthetic anchor, or surplus wrapper. + +Three independent sources support the behavior: + +1. January PC code loads the full dword argument from `[ebp+8]`, passes that full handle with `_actor_data` to `_datum_get`, reads the byte at actor `+0xCC`, materializes the obey-state base at actor `+0x9C`, and conditionally stores `0xFFFFFFFF` at state `+0x40` (actor `+0xDC`). +2. The retained HCEA function tests `obey.complex_control.destination_valid` and sets `destination_surface_index=-1` on true. +3. The adjacent accepted canonical obey wrappers use the same `actor` then `state_data` local source pattern. + +The HCEA extraction spells this one function's actor parameter `uint16_t`, unlike the surrounding `int` functions. That later-platform/decompiler spelling is not PC ABI authority. January's dword load, the target relocation/call sequence, the callback-family contract, and the runtime harness's untruncated handle prove canonical `long` is correct. + +The caveat is derivation history, not source semantics. The 2026-08-21 natural batch produced a different 46/48 candidate hash and removed the miss after one attempt. Fable later recorded that the exact body added the `state_data` pointer missing from that attempt. Because it explicitly consumed the previous mismatch boundary, this implementation cannot inherit the earlier ledger's first-shot label even though the resulting ordinary C body is authentic in form. + +## Exact object and owner evidence + +January target object SHA-256 is `0e4f889a35b97c44f6ae91e4906b547bd64f2ff12b9f399e02b46f02b69633fb`. The frozen owner-clean candidate object SHA-256 is `543ef02661eafabe28197ce23ddd345fdfb4818d543017219ce933d56562da0e`. + +For `_action_obey_flush_structure_indices`, target and candidate agree on: + +- 46 meaningful bytes and a 48-byte padded section (two terminal NOPs); +- normalized SHA-256 `9f0facf2a5e64545b5b323119ea1ce6c45813a307bf0fb256308aab64fe0db82`; +- relocation `+0x08`, `IMAGE_REL_I386_DIR32`, to `_actor_data`; +- relocation `+0x0F`, `IMAGE_REL_I386_REL32`, to `_datum_get`; +- `.text` flags `0x60501020`, external storage 2, function type 32, value 0, COMDAT selection 1. + +The first leaf comparison (before to after) adds exactly one runtime section and one genuine function owner. It changes no inherited runtime section, adds/removes no COMMON, emits no forbidden point helper, and has no debug delta. The later owner cleanup (removing the redundant `actor_action_change` local declaration) preserves all 12 runtime sections and every program symbol identity; it creates no new helper or owner. + +Frozen leaf chain: + +- before manifest `ee343e4c289c0b81eaa4972b030f1f1db83a150d1cd13096a5393e82c3f0c91e` / object `10ee91a816e424347da9cc3ccf6c820e6f4b7f4f4aba09d303eef26a0b547c5f`; +- body-after manifest `928b2bde2a3aa4c568d726ff87457c2ff91ad64f47f0b8d22aa8fdc9c47ae426` / object `9edaf5bafdd56b1ab3864f7b3a777e6b8ad688084571346efc2b1b0d6429a531`; +- owner-clean manifest `d8435f09c9c20d28562d4c62b5b587a57df19a99c2961c6d3255313e6ee3f581` / object `543ef02661eafabe28197ce23ddd345fdfb4818d543017219ce933d56562da0e`. + +The isolated replay object (`69ae82ce4432cbe0df25eeb0d4e5912e16e19c8527a3aef7e645d31fac58d238`) defines the nine inherited exact functions plus this leaf—ten function owners total—and no unexpected code owner. The full before/after runtime report identifies only the new leaf; the owner-clean comparison is completely unchanged. + +## Runtime differential + +The final scratch runtime harness tests target, owner-clean actual, and isolated objects over all 256 possible `destination_valid` byte representations and four prior surface values (`0`, `17`, `0x80000000`, `0xFFFFFFFF`), or 1,024 cases per object. All three produce trace SHA-256 `999e2273e77f3347e5871616830525f72c861071faf31f8e1757762f2767becd`. + +It also verifies: + +- one and only one `_datum_get(_actor_data, actor_index)` call; +- the full 32-bit handle reaches the accessor; +- the surface changes to `NONE` iff the valid byte is nonzero; +- no other modeled actor byte changes; +- callee-saved registers, stack cleanup, and direction flag behavior; +- exact target section and owner metadata before execution. + +The stated limit is appropriate: this models a valid actor handle and the `datum_get` contract; it is not a whole actor subsystem or image-link test. There is no uncovered input branch inside this leaf once those API preconditions hold. + +Evidence: + +- `scratch/action-obey-structure-leaf-owned-runtime-20260905.json` — SHA-256 `65e17c98c27a46eb49b0e25e92e95984d7d9b291e9b8dc11ec60f80d632b3752`; +- runtime script SHA-256 `d686a0c4c2251909cc6d7d4428091f318f2f867c35841c09a5441a6ae034b704`; +- owner-clean all-section summary SHA-256 `97a66ae9554056837a796f433621a966546b8ade2f21fdde4da1da4d9ceb5bf6`. + +## Accounting and admission statement + +Before this leaf, canonical `action_obey.obj` had 9/27 exact functions and 439 meaningful / 480 padded code bytes. This packet advances it to **10/27 exact**, **485 meaningful**, and **528 padded** code bytes. The incremental claim is exactly one function and **46 meaningful / 48 padded bytes**. It claims no `.rdata`, `.data`, BSS, COMMON, or other data owner. + +Technical verdict: **PASS** for API ownership, exactness, ABI, runtime semantics, inherited-owner preservation, and accounting. Provenance verdict: **review required only for the “natural first candidate” label**; the frozen record establishes that it is a later exact correction. Do not roll this caveat into the separate shared-schema trial, and do not use this leaf as blanket precedent for the larger Fable ActionObey donor cluster. diff --git a/docs/object_matching_logs/action_obey_obj_private_closure_plan_20260905.md b/docs/object_matching_logs/action_obey_obj_private_closure_plan_20260905.md new file mode 100644 index 00000000..f439e1a4 --- /dev/null +++ b/docs/object_matching_logs/action_obey_obj_private_closure_plan_20260905.md @@ -0,0 +1,142 @@ +# Fable `action_obey` private-closure intake (2026-09-05) + +Read-only/source-plan audit. No production, donor, build, configuration, or generated-object file was changed or compiled. This note does not change the earlier intake accounting: the initial Fable report started at 9 exact / 0 residual / 18 unwritten, and the reported donor `+11` remains donor evidence rather than admitted campaign progress. This audit admits zero functions. + +## Conclusion + +The two missing routines can be restored as a coherent, genuine same-translation-unit closure: + +```c +static boolean action_obey_command_begin( + long actor_index, + long unit_index, + short command_list_index, + struct obey_individual_simple_control *simple_control, + struct obey_individual_complex_control *complex_control); + +static boolean action_obey_command_perform( + long actor_index, + long unit_index, + short command_list_index, + struct obey_individual_simple_control *simple_control, + struct obey_individual_complex_control *complex_control); +``` + +January proves that these are private register-ABI functions, not public ABI. `_code_000060c0` receives the complex-control pointer in EAX and unit index in ECX; actor index, command-list index, and simple-control pointer remain stack arguments. `_code_000071a0` receives unit index in EAX and its other four arguments on the stack. Those allocations are consistent with VC7 optimizing the ordinary source signature above after it sees the same-TU callers. The audit aliases should name the private sections, but production source must not declare either body non-static or manufacture an external relocation. + +Once both bodies exist, the retained `action_obey_individual_perform` has a real private callee closure and can continue to support public `action_obey_perform`. There is no missing third private body behind either routine. The remaining preconditions are authentic shared schema and owner prototypes, not an ABI invention. + +## Primary evidence + +- January PC object: `build/split/source/ai/action_obey.obj`, SHA-256 `0e4f889a35b97c44f6ae91e4906b547bd64f2ff12b9f399e02b46f02b69633fb`. + - `_code_000060c0`: 4,320 padded bytes, 167 relocations, normalized SHA-256 `5b56fdd8b88a4456f893740a2f972a21d114b032c636f6b90c9d86e0114fd640`. + - `_code_000071a0`: 1,408 padded bytes, 51 relocations, normalized SHA-256 `afc109dc8ddf7e3f4ee6ed60f606b1e597702f063a81488fb2f8fd24f3713b07`. +- Semantic donor, read in full: + - `research-cache/halocea-full-blobs-20260830/src/blam/ai/action_obey_command_begin.c`, SHA-256 `4373d536adedb3dbdadfeaf62cfd1369ba2d1c53e92acae8477b6837a0a9461f`. + - `research-cache/halocea-full-blobs-20260830/src/blam/ai/action_obey_command_perform.c`, SHA-256 `bd22ee99d261de2f8b1db20ca548bb2158031a7e0d907bdfd78a9813842bd531`. + - `research-cache/halocea-full-blobs-20260830/src/blam/ai/action_obey_individual_perform.c`, SHA-256 `05d10cbc643b6b1b3eee5fe725bb257188a9521ea09df5deeb1370775532dade`. + - `research-cache/halocea-full-blobs-20260830/src/blam/ai/action_obey_directmovement_update_facing.c`, SHA-256 `3295935a5a1602fe4cdbfba17bf2762734699ef1e1bc981aae5c346a6bdcb042`. +- Retained PC source is not a full donor: Stian's `src/halo/ai/action_obey.c` is zero bytes; Punpckhdq retains the January symbol/literal manifest only; Pastudan history commit `ba72a7d7` contains only a raw-float `cross_product3d` reconstruction. It independently corroborates that math operation, but supplies neither private body. +- Fable source reviewed: `C:/halo-worktrees/fable-50k-small-families-20260904/source/ai/action_obey.c`, SHA-256 `067b4900d5494c5341ca609337f0d220dedd4f95778a935d601427de96575a59`. + +HCEA is an Xbox/PPC semantic donor. January PC disassembly, relocation destinations, literals, assertion strings, record strides, and register/stack use take precedence wherever the two diverge. + +## Natural `command_begin` source plan + +Start by resolving the typed actor, command list, current command, point block, actor definition, and actor variant. Return false if `current_command_index` is outside the command count. Dispatch on the 28 `ai_atom_type` values and use the existing simple/complex control fields: + +1. `pause`: convert seconds to ticks (`parameter1 * 30`). +2. `go_to` / `go_to_and_face`: validate point indices; set destination point/surface/keep-moving state; call `actor_move_to_point`; optionally call `actor_move_keep_moving_past_destination`; for the facing form, set the typed facing point. +3. `move_direction`: sample actor body position or `object_get_origin`; for a point command call `vector_from_points3d` then `normalize3d`, otherwise use `vector3d_from_angle`; set the facing mode, halt the actor when it owns the unit, and set direct-movement flags. +4. `look`, `look_random`, `look_player`, `look_object`: resolve a command point, active prop, nearest player, or named object; use `random_range(low, high + 1)` and `real_random_range` for the random look; construct a complete local `direction_specification` directly and call `actor_look_secondary`; store the duration in ticks. Do **not** import HCEA's one-argument/variadic `direction_get_empty` declaration: January has no such relocation and writes the local type/object/point fields directly. +5. `animation_mode`, `crouch`, `shoot`, `grenade`: validate domains and populate complex control. Grenade setup takes the grenade type from the actor variant, calls `unit_add_grenade_type_to_inventory`, and initializes trajectory/target/timer state. +6. `vehicle`: iterate `_object_mask_vehicle`, keep at most 16 typed `vehicle_possibility` records, compute distance, `qsort` with the already genuine same-TU `vehicle_possibility_qsort`, and try candidates through `actor_action_try_to_enter_vehicle` using the ordinary empty string literal. The record is TU-private; no public header is owed. +7. `running_jump`, `targeted_jump`: reject the actor's mounted unit case; set jump bits/timers/velocity. January uses `dot_product3d` for the non-actor unit's facing/velocity test. +8. `script`, `animate`, `recording`: call `hs_wake_by_name`; resolve the animation reference/default object animation graph and call `unit_start_user_animation`; update typed biped runtime flags; or resolve/play a recorded animation. +9. `action`, `vocalize`: map modifiers to animation impulses/communication types, or fill a real `unit_speech_item`, initialize its `ai_information_packet`, and call `unit_speak`. +10. `targeting`, `initiative`, `wait`, `loop`, `die`, `move_immediate`, `set_radius`, `teleport`: update the named flag/state fields. Teleport filters with `_object_mask_biped`, reads `biped_definition.biped.flags`, uses full 3D facing for flying/climb-anything bipeds and a typed 2D facing otherwise, then calls `object_set_position`, `object_reset`, `object_compute_node_matrices_recursive`, `actor_input_sample_position`, and `actor_move_halt`. + +The PC-only debug epilogue must also be retained. When `ai_debug` is enabled, January formats `` or `encounter/squad`, calls `action_obey_describe_command(..., temporary, 256)`, and reports `"%s: %s #%d%s: %s"` with either `""` or `" FAILED"`. HCEA returns immediately after the switch and does not contain this epilogue. + +PC-shape corrections relative to HCEA include ordinary `random_range` / `real_random_range`, `vector_from_points3d`, `distance_squared3d`, and `dot_product3d` calls; direct construction of the look-direction record; the PC debug epilogue; the January empty-string literal; and typed biped/object/tag access. HCEA's seed calls, manually expanded vector/distance products, `nullptr`, raw object header casts, and its `direction_get_empty` facade are semantic hints only. + +## Natural `command_perform` source plan + +Resolve the typed command and actor, default `done` to true, and use the January switch grouping: + +- `pause` and all look atoms, plus `move_immediate`: finish when `pause_timer == 0`. +- `go_to` / `go_to_and_face`: for the actor's own unit with complex control, test `actor_path_at_destination`; apply keep-moving tolerance/velocity logic; wait ten ticks while the actor is still moving; when destination facing is active, assert at source line 983 that the current atom is `_ai_atom_go_to_and_face`, normalize a 3D or 2D vector to the facing point, compare against `0.98400003f`, then halt on completion. +- `move_direction`: obtain actor body position or object origin, form a vector from the stored start position, and compare its dot product with the commanded travel distance. +- Immediate atoms (`animation_mode`, `crouch`, `vehicle`, `script`, `targeting`, `initiative`, `loop`, `die`, `set_radius`, `teleport`) return true. +- `shoot`: require the actor unit and complex control; compare the manual fire target with the ordered point (`distance_squared3d < 0.25f`); otherwise set pause from `actor_variant_definition.ranged_combat.first_burst_delay_upper_bound * 30`, floored at 60. +- `grenade`: inspect `unit.grenade_throw_state` after start, or call `actor_combat_plan_grenade_trajectory` and depress the trigger when the unit is not busy. +- Jump atoms: require the jump flag, use actor `input.in_midair` or `unit_flying_through_air`, and clear the timer after the jumped bit and airborne state coincide. +- `animate`, `recording`, `action`, `vocalize`: inspect `unit.animation.state`, `recorded_animation_controlling_unit`, `complex_control->play_action`, or `unit.speech.current.priority` respectively. +- `wait`: preserve the January three-way combat-status/told-to-advance ladder. + +Use `vector_from_points3d`, `distance_squared3d`, `magnitude_squared3d`, `dot_product3d`, `normalize3d`, and `normalize2d` as the typed math vocabulary instead of HCEA's manually expanded products. January's relocations authenticate every non-inlined call. + +## Inline-math ownership and true callers + +The four currently exact out-of-line bodies are authenticated `source/math/real_math.h` inline operations, but the present macro-renaming plus hand-appended definitions are a temporary facade. Preserve their current exact credit until the real callers are present, then remove the four include-time renames and four manual definitions atomically and let ordinary header ownership materialize them. A normal compile must prove all four sections remain exact before that cleanup is retained. + +| Target section | January | True source caller | PC evidence | +| --- | --- | --- | --- | +| `_random_range` | 32 bytes, 2 relocs | `action_obey_command_begin`, `look_random` | call relocation at private-body `+0x25f`; body calls `get_global_random_seed_address` and `seed_random_range` | +| `_vector_from_points2d` | 32 bytes, 0 relocs | `action_obey_command_perform`, non-flying destination-facing branch | the helper is inlined into `+0x211..+0x22e`: two point-coordinate subtractions followed by `normalize2d`; emitted wrapper plus inline sequence identifies the reference | +| `_cross_product3d` | 64 bytes, 0 relocs | `action_obey_directmovement_update_facing` | two direct call relocations at `+0x9e` and `+0xd0` | +| `_negate_vector3d` | 48 bytes, 0 relocs | `action_obey_directmovement_update_facing` | backwards/right cases are inlined at `+0x72..+0x88` and `+0x123..+0x138` | + +For the 2D facing call, use a genuinely typed `real_point2d`/`real_vector2d` projection or authentic shared view. Do not recover it with a pointer cast between unrelated point/vector types, an inactive-union read, or a prefix facade merely to provoke the wrapper. + +## Owner headers and API closure + +Most dependencies already have the correct owner declarations and should be consumed by includes, not redeclared in `action_obey.c`: + +| Owner | Required declarations/types | +| --- | --- | +| `source/ai/actions.h` | shared obey simple/complex/state types; `actor_action_try_to_enter_vehicle`; public ActionObey declarations | +| `source/ai/actors.h` | `actor_datum`, `direction_specification`, movement/look/path/grenade APIs, `actor_input_sample_position` | +| `source/ai/actor_definitions.h` | actor/variant tags, idle-look range, ranged first-burst delay, grenade properties | +| `source/ai/ai_scenario_definitions.h` | command-list/command/point records and all atom/command-list/modifier domains | +| `source/ai/props.h` | `prop_iterator`, `prop_iterator_new/next`, `prop_get_active_by_unit_index` | +| `source/ai/ai_communication.h` and `source/ai/ai.h` | communication enums and complete `ai_information_packet` | +| `source/game/players.h`, `source/memory/data.h` | `player_data`, `player_datum`, typed `data_iterator_new/next` | +| `source/objects/objects.h`, `source/objects/object_definitions.h` | object iterators/accessors/origin/name/position/reset/node matrices, masks, damage flags, animation graph tag | +| `source/units/units.h`, `source/units/bipeds.h`, `source/units/biped_definitions.h` | unit speech/animation/grenade/facing APIs and complete unit/biped runtime/tag fields | +| `source/scenario/scenario.h`, `source/scenario/scenario_definitions.h` | `global_scenario_get`, command/reference blocks, encounter/squad debug names | +| `source/cutscene/recorded_animation_definitions.h`, `source/cutscene/recorded_animations.h` | scenario animation lookup and recorded-animation control/playback | +| `source/hs/hs.h` | `hs_wake_by_name` | +| `source/math/real_math.h` | all point/vector/random helpers and constants | +| `` plus project cseries/error headers | `qsort`, memset/string/format/error/debug support | + +Two genuine owner-prototype gaps were found: + +1. `actor_move_keep_moving_past_destination(long)` is defined by `source/ai/actor_moving.c` but is absent from `source/ai/actors.h`; `source/ai/action_charge.c` currently carries a foreign C-local declaration. Add the owner prototype to `actors.h` and remove consumer-local copies. +2. `recorded_animation_play(long, short)` is defined by `source/cutscene/recorded_animations.c` but is absent from `source/cutscene/recorded_animations.h`; `source/hs/hs.c` currently declares it locally (with a `word` second parameter). Add the definition-compatible owner prototype to `recorded_animations.h` and remove/repair foreign copies. + +No `direction_get_empty` declaration should be added: it is not a January dependency. `vehicle_possibility_qsort`, `action_obey_directmovement_update_facing`, `action_obey_command_begin`, and `action_obey_command_perform` remain genuine statics in this TU. `qsort` comes from the standard header, not a handwritten extern. + +## Shared schema/enum prerequisites + +Before integration, the owning headers must supply one authentic definition for: + +- `obey_individual_simple_control` (0x24), `obey_individual_complex_control` (0x58), and `obey_state_data` (0x84), including direct-movement/jump union arms and every destination/action/shoot/grenade field; +- the complete shared actor/swarm layouts already being audited separately; no obey-only prefix, opaque tail, or parallel incompatible record is acceptable; +- `direction_specification`, `unit_speech_item`, `ai_information_packet`, `vehicle_possibility` (TU-private), and the command/reference records with January strides: command list 0x60, command 0x20, point 0x14; +- the command-list flags, simple-control bits, atom modifier domains (look, move facing, grenade, animate, action, loop), unit animation impulses, biped runtime flags, and existing biped-definition/communication/speech/object domains in their natural owners. + +Current Fable-local enums explicitly labeled “belongs in ...” should migrate to those owners with the full packet; they are not a reason to create another private copy. The exact signedness of the shared swarm component flags remains part of the separate schema closure and must not be inferred from this pair of functions. + +## Admissible packet boundary + +A coherent implementation packet is: + +1. land the authentic shared schema and the two owner-prototype fixes; +2. include the actual owners; +3. add both private static bodies together, including the PC-only assertion/debug behavior and ordinary typed accesses; +4. keep `action_obey_individual_perform` calling those statics and remove the two non-static placeholder declarations; +5. reconcile the four math wrappers only after their true calls are present, in the same verified packet; +6. add audit-only aliases from the two authentic names to `_code_000060c0` / `_code_000071a0` for measurement. + +This packet is source/API/schema feasible and does not require an external facade. `command_perform` is the smaller, higher-confidence body; `command_begin` is large but semantically closed. Neither should be admitted alone if the goal is to retain public perform without unresolved private ABI. diff --git a/docs/object_matching_logs/action_obey_obj_shared_schema_and_structure_flush_reconciliation_20260905.md b/docs/object_matching_logs/action_obey_obj_shared_schema_and_structure_flush_reconciliation_20260905.md new file mode 100644 index 00000000..d6dff8be --- /dev/null +++ b/docs/object_matching_logs/action_obey_obj_shared_schema_and_structure_flush_reconciliation_20260905.md @@ -0,0 +1,163 @@ +# ActionObey: shared owners and structure-cache flush reconciliation + +Date: 2026-09-05. Parent publication: `31a1927c951479106d0475ee99e1fb236a15e89d`. + +## Accepted checkpoint and accounting + +This checkpoint adds the genuine `action_obey_flush_structure_indices` leaf +and repairs the shared types, enum owners, and public API declarations needed +by the larger Fable ActionObey packet. It does not import that packet wholesale. + +- ActionObey advances from 9/27 to **10/27 exact functions**, 439 to **485 + meaningful code bytes**, and 480 to 528 padded bytes. +- Incremental credit is **46 meaningful / 48 padded bytes**, one function, + and no data. The complete-object count does not change. +- The final canonical build reports **910,347 / 2,198,102 meaningful exact + code bytes**, **6,187 / 11,060 credited functions**, **2,061,020 / 4,176,062 + matched data bytes**, and **391/833 Matching objects**. +- The complete stable sweep advances 6,232 to **6,233** exact owners out of + 8,245 measured owners, with zero inherited exact losses. This owner census + is not the same denominator or admission policy as the credited-function total. + +Canonical root: +`C:/Users/isabe/Documents/Codex/2026-07-13/i-w/work/rasterizer-model-wrapper-alias-20260829`. +Donor root, read-only throughout: +`C:/halo-worktrees/fable-50k-small-families-20260904`, tip +`f9dd42218b3325e1b3a63d7860e5309f69fd3d8e`. + +## Source ownership and credibility + +`actions.h` owns the public ActionObey declarations. The packet adds the nine +genuine target-public declarations in its existing ACTION_OBEY section and +removes their six consumer-local copies from `actions.c`. The redundant +`actor_action_change` declaration in `action_obey.c` is removed; its existing +owner declaration is unchanged. + +The leaf uses `actor_get`, the complete `obey_state_data`, the named +`destination_valid` and `destination_surface_index` fields, `NONE`, and an +explicit return. January independently materializes the obey state at actor +offset 0x9C, tests the byte at 0xCC, and conditionally stores -1 at 0xDC. + +Provenance adjudication: this is an authenticated exact reconstruction, **not +a natural first-shot result**. Fable's report says the local `state_data` +pointer corrected an earlier missed candidate. That history remains visible +in the independent review. The accepted pointer is ordinary meaningful source, +matches adjacent action-family source organization, and is independently +supported by the target state-base computation. It is not an inert lifetime +anchor, aliasing trick, or invented control flow. This ruling does not authorize +replaying exhausted spelling/order searches on other functions. + +The shared owner correction is one coherent packet: + +- `actors.h` owns the full 0x40 `swarm_component_datum`, the 0x14 + `swarm_wander_control`, the five component flags, and `swarm_component_get`. + Direct HCEX and HCEX_Release PDB records prove signed `short flags`, the + explicit byte `pad` at 0x1B, and the complete anonymous wander/obey union at + 0x1C. The wander record has ordinary implicit alignment, not an invented + named padding field. Local partial/duplicate views are removed from + `actors.c`, `actor_type_infection.c`, and `actor_perception.c`. +- `actions.h` owns the five simple-control bits. Existing 0x24/0x58/0x84 + obey record shapes are unchanged. Infection's local copies are removed. +- `bipeds.h` owns the six directly authenticated runtime bits. Bit zero is + airborne, not limping. The five misleading uses in `units.c` and one in + `players.c` are renamed; duplicate local enums in Infection, Bipeds, and + PlayerControl are removed. All values and underlying datum storage remain + unchanged. Units remains **189/189 exact**. +- `ai_scenario_definitions.h` owns the five authenticated command-list bits, + loop-until modifier, and four movement-facing values. The latter names are + explicitly descriptive reconstructions from January behavior, not claimed + recovered spellings. Unneeded later manual-BSP and count names are not imported. +- `actors.h` owns `actor_move_keep_moving_past_destination(long)` and + `action_charge.c` loses its foreign local declaration. +- `recorded_animations.h` owns the genuine play/play-and-delete/play-and-hover + signatures `(long, short)`. `hs.c` includes that owner and loses the three + mismatched local `(long, word)` declarations. Definition and caller code + are unchanged. + +No private begin/perform facade, flat obey-only swarm view, new raw offset, +new inline directive, or new math wrapper is introduced by this checkpoint. +It does not bless the inherited ActionObey math-wrapper/callback debt: that +requires the real private caller graph and remains the next reconciliation step. + +## Verification and the two residual changes + +The public-header phase freezes all 47 actual Ninja consumers: 3,079 runtime +sections unchanged, 54 compiler-local-label spelling changes, and no runtime, +owner, COMMON, or forbidden point-helper addition. All 6,232 exact owners survive. + +The subsequent shared-schema phase freezes all **58 actual consumers**, not +merely lexical include matches. Its full runtime comparison has 4,544 unchanged +sections, 62 compiler-local-label-only changes, and exactly two residual code +changes. Neither was accepted from strict-function counts alone: + +1. `infection_swarm_control` remains 3,360 padded bytes with 103 relocations. + Three clear-bit masks use shorter signed-immediate encodings after the + authenticated signed-word field correction. Exhaustive evaluation covers + every 16-bit flag value at all three sites: **196,608 comparisons pass**. + The first two sites explicitly zero upper EAX. The third does not require + that assumption: only AL is tested and AX stored; TEST replaces the flags, + and both successor paths fully define EAX before reading it full-width. + All 130 direct branches, both table jumps, all 103 relocation records, + shifted local labels, exact allowed alignment bytes, and the masked + 80-byte table/tail are checked. No owner, data, COMMON, or definition changes. +2. `ai_communication_update_speech_timers` remains 672 bytes with the same 43 + ordered relocations. Its only change swaps the independent loads of DI + from `[EBP+0x10]` and EBX from `[EBP-8]` in 0x167..0x16E. All 27 branches + are unchanged; none enters the block interior; there is no indirect jump + or relocated operand in the block. The rest of the bytes are identical. + Its honest fuzzy score returns from 97.76382% to the previously observed + **97.67839%**. This is explicitly disclosed, not hidden as an exact gain. + No speech-timer source or scheduling hint was changed. + +The first Ninja invocation compiled the consumers but correctly stopped its +progress step on the now-stale speech-timer evidence. Only after full semantic +review and independent proof was that park remeasured. Final Ninja succeeds. +Root independently replays the hardened residual proof with the same JSON hash. +The final 58-object freeze matches the reviewed after-freeze across all **4,608 +runtime sections** with no changes at all. + +Final checks: + +- Complete stable sweep: +1 exact function / 48 padded bytes, zero losses. +- Leaf: **1,024 cases each** against the January target, final actual object, + and isolated build. All 256 flag-byte representations and four surface + values; full modeled actor-state writes, call arguments, stack, preserved + registers, and direction flag checked. Limit: valid modeled actor handle + and `datum_get` contract, not a whole-game execution test. +- Separate VC7 scratch TU: **24 compile-time layout/value checks** pass; + it emits no code and earns no progress credit. +- **288 tests plus 26 subtests pass** after the final park update. +- Parks: **284 active, zero stale, zero invalid**. +- Admission: zero candidates, zero contradictions, five existing displayed + rejections, zero revocations. No new `_point_from_line3d` emission/reference. +- Protected bitmap source/header hashes are unchanged. No source implementation + in the new Opus rasterizer/device/widget reservation is modified. + +## Frozen evidence and continuation + +Key manifests (all under canonical `scratch/`): + +- `action-obey-public-api-before-20260905.json` / `...after...`: + `22082d37d81366a681520949d9502107f7ea43b8e185f29936643cd07c89d0d5` + / `49d6f456321f119a67d25ac7324d82b4fc282d43cf1e86044f4a342e43284f65`. +- `action-obey-shared-schema-before-20260905.json` / `...after...` / `...final...`: + `90becfaff10da7f9e549e43d28385da41c37675d51d3c9319347bb7b71600253` + / `b7fef54d4e8030efd58299c5dd290f7e3e9a0ba0c80e8bd8aaa70a929d95c831` + / `d88762b5f013727b37c746f8e290a5719779e40ec00a9ae10b5accc6e9fd24bb`. +- `action_obey_shared_schema_residual_independent_proof_v2_20260905.json` + and root replay both hash + `2a673deafe4714f0ad74ff074feb24d8cb34cb4f87fe6485fbca89d5911c2e4f`. +- `action-obey-structure-leaf-final-runtime-20260905.json`: + `b4ce9623dafa0c31d541f6a6aa16528c3c843522f542c47e367c45566b08e059`. + +See the sibling API/leaf independent review, shared-schema evidence, and +shared-schema residual proof ledgers for source hashes and detailed ownership. +The private-closure plan is preserved separately. Both real private command +bodies, further actor/modifier enum ownership, and ordinary math-header +materialization remain scratch research until their coherent packet passes. +Do not count the donor's remaining exact claims or these proposals as integrated. + +The separate Bitmaps intake preserves 18 distinct donor exact candidates / +4,736 padded bytes, with prototype/ownership/provenance issues still awaiting +reconciliation. It adds no canonical credit in this checkpoint. The Fable lane +as a whole remains unfinished; donor committed and dirty work is preserved. diff --git a/docs/object_matching_logs/action_obey_obj_shared_schema_evidence_20260905.md b/docs/object_matching_logs/action_obey_obj_shared_schema_evidence_20260905.md new file mode 100644 index 00000000..a0bf7f33 --- /dev/null +++ b/docs/object_matching_logs/action_obey_obj_shared_schema_evidence_20260905.md @@ -0,0 +1,340 @@ +# ActionObey shared swarm schema and enum-owner audit (2026-09-05) + +## Disposition + +The shared `swarm_component_datum` / `swarm_wander_control` schema is +authenticated strongly enough for one coherent owner-header trial. The +natural owner is `source/ai/actors.h`: that header already owns +`swarm_datum`, `SWARM_COMPONENT_DATUM_SIZE`, `swarm_data`, +`swarm_component_data`, and the neighboring actor/swarm accessors. + +The decisive evidence is direct DIA type information in both `HCEX.pdb` and +`HCEX_Release.pdb`, not the Fable donor's flat local view. In particular, +`swarm_component_datum.flags` is a signed `short`, the byte at `+0x1B` is an +explicit member named `pad`, and the `+0x1C` tail is an anonymous union of +`wander` and `obey`. `swarm_wander_control` has no named member at `+2`; +that two-byte interval is ordinary alignment before its vector. + +This is a read-only/source-ownership result. No production, donor, header, +configuration, build, or object file was changed or compiled by this audit. +The current root-owned ActionObey API/flush-leaf work was observed but not +modified or re-audited here. + +## Direct PDB schema + +Reproduction tool: + +`C:/Users/isabe/Documents/Codex/2026-07-13/i-w/research/tools/DIA2Dump/x64/Release/DIA2Dump.exe` + +Primary type source: + +`C:/Users/isabe/Documents/Codex/2026-07-13/i-w/research/hcea_jun2011_prototype/payload/Halo CE Anniversary (Jun 24 2011)/HCEX.pdb` + +SHA-256: `f55cfe957da8079a62a26a6753f1ddbb700b067a66de0bd5db5aac182d985ff1` + +Independent same-result PDB: + +`C:/Users/isabe/Documents/Codex/2026-07-13/i-w/research/hcea_jun2011_prototype/payload/Halo CE Anniversary (Jun 24 2011)/HCEX_Release.pdb` + +SHA-256: `0fd11b084fd2169cafe071fd8c3e4083d6e9564f01e7964f6c26e5a03eee4dff` + +The relevant commands are `DIA2Dump.exe -sym `. Both PDBs give +the same two principal layouts: + +| type/member | offset | DIA type | +| --- | ---: | --- | +| `swarm_component_datum` | | size `0x40` | +| `identifier` | `0x00` | `short` | +| `flags` | `0x02` | `short` | +| `position` | `0x04` | `real_point3d` | +| `surface_index` | `0x10` | `long` | +| `combat_target_prop_index` | `0x14` | `long` | +| `attached_to_unit_ticks` | `0x18` | `unsigned char` | +| `ground_ticks` | `0x19` | `unsigned char` | +| `attack_delay_ticks` | `0x1A` | `unsigned char` | +| `pad` | `0x1B` | `unsigned char` | +| `wander` | `0x1C` | `struct swarm_wander_control` | +| `obey` | `0x1C` | `struct obey_individual_simple_control` | +| `swarm_wander_control` | | size `0x14` | +| `pause_ticks` | `0x00` | `unsigned char` | +| `move_ticks` | `0x01` | `unsigned char` | +| implicit alignment | `0x02..0x03` | no DIA member | +| `vector` | `0x04` | `real_vector3d` | +| `angle` | `0x10` | `float` | + +The already-shared ActionObey arm in `actions.h` also agrees with the PDB: +`obey_individual_simple_control` is `0x24`, with bytes at `+0/+1`, signed +`short pause_timer` at `+2`, bytes at `+4/+5`, and anonymous +`directmovement` / `jump` arms at `+8`. The direct-movement arm is `0x1C` +(`short facing +0`, vector `+4`, start position `+0x10`); the jump arm is +`0x0C` (`short delay_ticks +0`, reals `+4/+8`). Those existing records need +no shape change. + +`DIA2Dump -sym swarm_component_data HCEX.pdb` identifies the global as +`struct data_array *`, matching the existing `actors.h` declaration. + +## Source-authentic owner shape + +The following is the evidence-backed shape for `actors.h`. The enumerator +count is deliberately omitted because the named `NUMBER_OF_*` symbol is not +present in either PDB and no current consumer needs it. + +```c +enum +{ + _swarm_component_attacking_in_melee_bit = 0, + _swarm_component_attached_to_unit_bit, + _swarm_component_wander_bit, + _swarm_component_obey_bit, + _swarm_component_obey_desire_jump_bit, +}; + +struct swarm_wander_control +{ + byte pause_ticks; + byte move_ticks; + real_vector3d vector; + real angle; +}; + +struct swarm_component_datum +{ + short identifier; + short flags; + real_point3d position; + long surface_index; + long combat_target_prop_index; + byte attached_to_unit_ticks; + byte ground_ticks; + byte attack_delay_ticks; + byte pad; + union + { + struct swarm_wander_control wander; + struct obey_individual_simple_control obey; + }; +}; +``` + +Owner assertions should lock, at minimum: + +- `sizeof(swarm_wander_control)==0x14`, vector `+4`, angle `+0x10`; +- `sizeof(swarm_component_datum)==0x40`, flags `+2`, position `+4`, + surface `+0x10`, target prop `+0x14`, the four bytes `+0x18..+0x1B`, and + both union arms `+0x1C`; and +- the already-proven composed access + `obey.directmovement.vector==+0x28`. + +The retained HCEA generated header spells an explicit `pad[2]` in +`swarm_wander_control`. That is a reconstruction convenience, not a named +member recovered by DIA, and must not be promoted into the owning schema. + +## Signed flags: independent January corroboration + +January `_code_00005350` (`action_obey_individuals_iterate`, `0x130` padded) +zeros exactly `0x24` bytes at component `+0x1C`, then loads the word at `+2` +and emits: + +```text +xor eax,eax +mov ax,word ptr [esi+2] +and eax,0xfffffffb +or eax,8 +mov word ptr [esi+2],ax +``` + +This is the component's `wander`-clear / `obey`-set operation. The frozen +Fable measurement records that `short flags` reproduces the +`and eax,0xfffffffb` encoding while its prior unsigned `word` spelling emits +the different `and eax,0xfffb` form. That code observation corroborates the +direct PDB `short`; it is not being used as a spelling-search instruction. + +The committed Fable source must therefore not contribute its flat +obey-only component record, even though that local record also uses `short`. +Its source SHA-256 is +`067b4900d5494c5341ca609337f0d220dedd4f95778a935d601427de96575a59`. + +## Enum owners and provenance tiers + +### `actors.h`: component flags + +Direct `HCEX.pdb` constants authenticate all five spellings and values: + +| enumerator | value | +| --- | ---: | +| `_swarm_component_attacking_in_melee_bit` | 0 | +| `_swarm_component_attached_to_unit_bit` | 1 | +| `_swarm_component_wander_bit` | 2 | +| `_swarm_component_obey_bit` | 3 | +| `_swarm_component_obey_desire_jump_bit` | 4 | + +These belong with `swarm_component_datum.flags` in `actors.h`. +`NUMBER_OF_SWARM_COMPONENT_FLAGS` is absent from the PDB and unused by the +candidate; do not add it merely because a later extracted DB header has it. + +### `actions.h`: simple-control flags + +Direct `HCEX.pdb` constants authenticate all five spellings and values: + +| enumerator | value | +| --- | ---: | +| `_obey_simple_directmovement_bit` | 0 | +| `_obey_simple_directmovement_update_continuously_bit` | 1 | +| `_obey_simple_jump_bit` | 2 | +| `_obey_simple_jump_jumped_bit` | 3 | +| `_obey_simple_jump_targeted_bit` | 4 | + +They belong beside `obey_individual_simple_control.simple_control_flags` in +`actions.h`. `NUMBER_OF_OBEY_SIMPLE_FLAGS` is absent from the PDB and unused, +so the proposed owner packet need not invent it. + +### `bipeds.h`: runtime biped flags + +The PDB defines `_biped_datum.flags` as `unsigned long` and directly +authenticates the complete six-name set: + +| enumerator | value | +| --- | ---: | +| `_biped_airborne_bit` | 0 | +| `_biped_slipping_bit` | 1 | +| `_biped_absolute_movement_bit` | 2 | +| `_biped_no_collision_bit` | 3 | +| `_biped_movement_passes_through_bipeds_bit` | 4 | +| `_biped_limp_body_physics_active_bit` | 5 | + +These belong next to `_biped_datum.flags` in `bipeds.h`. +`NUMBER_OF_BIPED_FLAGS` is not returned by DIA and is unnecessary. + +The existing header's `_biped_limping_bit=0` is not an authentic alias: +`DIA2Dump -sym _biped_limping_bit` returns no symbol, while bit 0 is directly +named `_biped_airborne_bit`. It is also not unused. Current source has five +uses in `units.c` (lines 2364, 4219, 4302, 6547, and 10051 at audit time) and +one in `players.c` (line 2111). The strongest semantic anchors select +`_unit_state_melee_airborne` and `_unit_state_dying_airborne` when the bit is +set. A coherent owner repair must rename those six uses to +`_biped_airborne_bit`, remove the wrong placeholder, and not retain it as a +second same-value name. + +### `ai_scenario_definitions.h`: command-list flags and atom modifiers + +`ai_command_list_definition.flags` is directly `unsigned long` at `+0x20`. +The PDB authenticates exactly these five command-list names: + +| enumerator | value | +| --- | ---: | +| `_ai_command_list_allow_initiative_bit` | 0 | +| `_ai_command_list_allow_targeting_bit` | 1 | +| `_ai_command_list_disable_looking_bit` | 2 | +| `_ai_command_list_disable_communication_bit` | 3 | +| `_ai_command_list_disable_falling_damage_bit` | 4 | + +January `action_obey_command_list_setup` independently reads masks +`1/2/4/8`, and `action_obey_individual_begin` reads mask `0x10`. +`_ai_command_list_manual_structure_bsp_bit=5` and +`NUMBER_OF_AI_COMMAND_LIST_FLAGS=6` occur in later extracted DB/Demon +material but are not returned by either PDB and are unused by the evidenced +eleven-function donor subset. They must not be included in this PDB-grounded +packet. + +`ai_command_definition.atom_modifier` is directly a signed `short` at `+2`. +The PDB authenticates only +`_ai_atom_loop_modifier_until_told_to_advance=1`; January command-end compares +the word against 1. The donor's `_ai_atom_loop_modifier_always=0` and count +are not needed and have no direct PDB result, so omit them. + +The direct-movement facing domain is the one remaining naming caveat. +January `_code_00005f70` proves a signed-short read at simple-control `+8`, an +unsigned range check for values `0..3`, and these behaviors: + +- 0: copy the base facing; +- 1: negate the base facing; +- 2: store the normalized perpendicular; +- 3: negate that perpendicular; +- any other value: leave the output unchanged. + +This authenticates the values and semantics of the donor spellings +`_ai_atom_move_facing_forwards/backwards/left/right`, and the natural owner is +the atom-modifier domain in `ai_scenario_definitions.h`. It does **not** +authenticate those exact source spellings: DIA returns no such names and the +retained HCEA function explicitly records that its enum oracle found none. +If descriptive reconstructed enum names are allowed with an explicit +provenance comment, those four donor names are semantically credible. If an +original-name requirement applies, the private direct-movement/update pair +remains withheld; raw integers or a TU-private enum are not acceptable +workarounds. + +## Duplicate/facade removal inventory + +One coherent shared-owner trial must address all current production views, +not only the donor file: + +| file | current debt | owner-coherent action | +| --- | --- | --- | +| `source/ai/actors.c` | partial `swarm_component_datum` with unsigned `word flags` and `unknown_tail`; local accessor macro; two local layout typedefs | remove the partial type; consume the owner type; relocate/remove redundant asserts; use the shared typed accessor if installed | +| `source/ai/actor_type_infection.c` | local component/wander types (`word flags`, synthetic named `word pad`); local component and obey-simple enums; local biped-airborne enum; local accessor and layout typedefs | remove duplicate types/enums/asserts and consume `actors.h`, `actions.h`, and `bipeds.h` owners | +| `source/ai/actor_perception.c` | 0x40 prefix facade `actor_perception_swarm_component_view`; local accessor; raw `TEST_FLAG(...,1)` | remove facade/assert, use `swarm_component_datum`, and name bit 1 `_swarm_component_attached_to_unit_bit` | +| `source/units/bipeds.c` | local bit 0 / bit 5 enum | remove it after the complete owner enum lands | +| `source/game/player_control.c` | local `_biped_airborne_bit=0` enum | remove it after the owner enum lands | +| `source/units/units.c`, `source/game/players.c` | six uses of wrong `_biped_limping_bit` name | migrate all six to direct-PDB `_biped_airborne_bit` | +| prospective Fable `source/ai/action_obey.c` body | flat obey-only component, local component/simple/biped/command/modifier enums, local accessor | do not import those definitions; consume the owning headers and shared full-union type | + +`actor_type_infection.c` also copies the field into a local +`word component_flags`. DIA proves the **record field** is signed; it does +not recover that local variable's source type. Do not retune this local as +part of the ownership packet without January function evidence—the header +correction alone removes the false record declaration. + +Because `actors.h` already owns `swarm_get`, `swarm_try_and_get`, and the +`swarm_component_data` declaration, a single typed `swarm_component_get` +macro there is the natural source-owner cleanup for the three current local +macros and the future ActionObey caller. Macro ownership is a source-design +inference (PDBs do not retain macros), not a recovered original symbol; root +may instead retain identical local macros, but the perception facade's return +type still must be corrected. + +## Trial boundary and dependency scope + +This audit found 43 direct lexical includers of `actors.h` (42 C files plus +`ai_debug.h`), 27 direct includers of `actions.h`, 13 of +`ai_scenario_definitions.h`, and 13 of `bipeds.h`. These are only source-text +counts, not a substitute for the build dependency graph; the root-owned +trial must freeze and compare every actual dependent object and all inherited +strict/residual owners. + +The first coherent trial should therefore be one ownership packet: + +1. install the PDB-authenticated full schema and five component bits in + `actors.h`; +2. remove the three production type facades and migrate perception's raw bit; +3. install the five PDB-authenticated obey-simple bits in `actions.h`; +4. install the six PDB-authenticated biped bits in `bipeds.h`, remove three + local enum bodies, and repair all six wrong bit-0 consumer names; +5. install only the PDB-authenticated command-list bits 0..4 and loop-until + value 1 in `ai_scenario_definitions.h`; +6. decide explicitly whether the four behavior-authenticated but + source-name-unproven move-facing enumerators are acceptable; and +7. only then compile the unchanged natural ActionObey donor-body subset under + real owner headers, with a complete dependent-object/runtime census. + +No enum counts, manual-BSP bit, flat union, synthetic wander pad, raw bit +numbers, prefix views, or TU-private fallback enums are part of this +recommendation. + +## Evidence read + +- `scratch/fable_action_obey_intake_20260905.md`, SHA-256 + `587bda8055043f26957944b40939f0a7e9a831957c8cace07e0d3c007238eef6`; +- current `actors.h/.c`, `actor_type_infection.c`, `actor_perception.c`, + `actions.h`, `ai_scenario_definitions.h`, `bipeds.h/.c`, + `player_control.c`, `units.c`, and `players.c`; +- the committed Fable `action_obey.c` at + `f9dd42218b3325e1b3a63d7860e5309f69fd3d8e`, its saved + `scratch/reports/action_obey.md`, and its frozen exactness notes; +- complete January disassemblies for `_code_00005350`, + `_action_obey_command_list_setup`, `_code_00005290`, `_code_00004fb0`, and + `_code_00005f70` from `build/split/source/ai/action_obey.obj`; +- direct DIA queries against both PDBs for all types and enumerators recorded + above; and +- retained HCEA generated headers/functions and Demon command-schema source, + used only as corroboration where explicitly identified, never as January + original-source proof. diff --git a/docs/object_matching_logs/action_obey_obj_shared_schema_residual_proof_20260905.md b/docs/object_matching_logs/action_obey_obj_shared_schema_residual_proof_20260905.md new file mode 100644 index 00000000..171138a2 --- /dev/null +++ b/docs/object_matching_logs/action_obey_obj_shared_schema_residual_proof_20260905.md @@ -0,0 +1,83 @@ +# ActionObey shared-schema residual proof (final) + +Date: 2026-09-05 + +Scope: the two `runtime_or_owner_changed_REVIEW` sections selected by the frozen +58-consumer shared-schema audit. This proof reads only the frozen before/after +inventories and objects. It does not read live objects or source, compile, +run a gate, refresh a park, or decide packet ownership. + +## Frozen inputs + +- Before inventory SHA-256: + `90becfaff10da7f9e549e43d28385da41c37675d51d3c9319347bb7b71600253` +- After inventory SHA-256: + `b7fef54d4e8030efd58299c5dd290f7e3e9a0ba0c80e8bd8aaa70a929d95c831` +- Infection objects: + `8bb55ad955ced508c5db6cd768ef437575b3b6e6a83f2140757282854197f531` + -> `80caf88f6bc3db25ecffa0488ac480eba0997618be066f5d2cfca6b8fd76de62` +- Communication objects: + `329718faba04602a5809c17849c23f824ee483b4f854c58bc62d11c7c3e97141` + -> `be4f557e04d2b99155594435035bef9705c6e317e85162efe9494d1f5909ed5e` + +## Result + +Both residuals preserve their public ABI, COFF owner/linkage/type/value, +section flags/alignment/COMDAT selection, relocation identities and topology, +control-flow topology, and observable behavior for a valid call. + +### `_infection_swarm_control` + +- Size remains 3,360 bytes and all 103 relocations map exactly. Thirty-eight + relocation source offsets move with the shortened encodings. The six + changed internal table destinations map as + `1254->1252` three times, `1701->1697` twice, and `1793->1789` once; the + table slots themselves remain fixed. +- All 130 direct branches and both indirect table jumps map exactly. No branch + enters either alignment/trailing-padding interior. +- The only executable changes are three `AND EAX, imm32` encodings becoming + their sign-extended `imm8` forms: `0x0000fffe -> 0xfffffffe` twice and + `0x0000fff7 -> 0xfffffff7` once. Exhaustive evaluation of all 65,536 16-bit + flag inputs at all three sites (196,608 comparisons) is exact. +- The first two sites explicitly zero EAX before loading AX. At the third + site, upper EAX is not assumed zero: only AL is tested and AX is stored; + `TEST AL,1` overwrites the `AND` flags before the branch, and each successor + fully defines EAX before any full-width read. +- The exact allowed padding bytes are asserted, not merely described: old + `LEA ESP,[ESP]` becomes `JMP 0x940` plus skipped `LEA EBX,[EBX]`; the old + post-`RET` `NOP` becomes post-`RET` `LEA ECX,[ECX]`. +- After masking relocation slots, the complete 80-byte `[0xcd0,0xd20)` table + and tail are byte-identical, SHA-256 + `eb8ad26cf1b215d3d0731e00af0d53823547fa6cd4254298bafa1996d58f96c1`. +- No runtime/data section was added or lost, no COMMON changed, no definition + transition occurred, and the complete function-owner name inventory is + unchanged. Shifted compiler-local labels are fully accounted for by the + same offset map. + +### `_ai_communication_update_speech_timers` + +- Size remains 672 bytes and all 43 relocation records are byte-for-byte + identical. +- The only change is the order of adjacent loads in `[0x167,0x16e)`: + `DI <- word [EBP+0x10]` and `EBX <- dword [EBP-8]`. They read distinct + stack slots, write disjoint registers, and do not touch flags or memory. +- Bytes before `0x167` and from `0x16e` onward are identical. All 27 direct + branches are identical, two enter at the block boundary `0x167`, the jump at + `0x165` rejoins at `0x16e`, no branch targets the strict interior, there are + zero indirect jumps, and the block contains zero relocations. +- No runtime/data section was added or lost, no COMMON changed, no definition + transition occurred, and the complete function-owner name inventory is + unchanged. + +This is a frozen-object equivalence proof for these two deltas, not a blanket +exception for future schema packets or other compiler-shape changes. It does +not replace the root owner's admission, park, build, or stable-gate decision. + +## Artifacts + +- Hardened proof script SHA-256: + `b9aa2a4c8b4509c368b9bbd96d5907abd4944202b635edc29c852807e2df74b0` +- Final v2 JSON SHA-256: + `2a673deafe4714f0ad74ff074feb24d8cb34cb4f87fe6485fbca89d5911c2e4f` +- Preserved preliminary v1 JSON SHA-256: + `b44e5ed4c6d5e469a0ae821fbd4b91aa6af04393242238d0df7e4670081226c8` diff --git a/docs/object_matching_logs/bitmaps_obj_fable_packet_intake_20260905.md b/docs/object_matching_logs/bitmaps_obj_fable_packet_intake_20260905.md new file mode 100644 index 00000000..02977128 --- /dev/null +++ b/docs/object_matching_logs/bitmaps_obj_fable_packet_intake_20260905.md @@ -0,0 +1,151 @@ +# Bitmaps Fable packet intake (read-only support audit, 2026-09-05) + +## Disposition + +The committed Fable `source/bitmaps/bitmaps.c` packet contains **18 distinct strict object matches over canonical's existing 9**, totaling **4,736 padded bytes**. The object evidence is real, but the packet is **not admission-ready as one natural packet**. It lacks its cited bitmap header note, retains a C-local declaration for the foreign public `rasterizer_bitmap_new` API, assigns two indistinguishable static helper aliases by inferred order, and includes several functions whose exact bodies followed documented target-guided corrections (including eight variants for `bitmap_verify`). + +The safe next review unit is therefore a frozen, staged source packet, not a wholesale cherry-pick. Keep protected `source/bitmaps/bitmap_utilities.c` and `source/bitmaps/bitmaps.h` untouched. First authenticate the missing public prototype in its narrow owner `source/bitmaps/bitmaps_mipmap.h`, resolve the genuine owner surface for `rasterizer_bitmap_new`, and separate the stronger first-pass subset from the explicitly tuned functions. + +No source/header/build/config file was edited and no compile, gate, or park operation was run for this audit. + +## Frozen identity and dirt + +- Canonical: `C:/Users/isabe/Documents/Codex/2026-07-13/i-w/work/rasterizer-model-wrapper-alias-20260829` + - HEAD: `31a1927c951479106d0475ee99e1fb236a15e89d` + - January target `build/split/source/bitmaps/bitmaps.obj`: 39,678 bytes, SHA-256 `6439102f24b216ed618a8c13e06d7c51b601a66214a6c17130ccb5586e41f042` + - current canonical `build/source/bitmaps/bitmaps.obj`: 9,413 bytes, SHA-256 `de6ca5e983ea03c75cf0d7446207538825844c4e9de50765517e5287607e32c1` +- Fable: `C:/halo-worktrees/fable-50k-small-families-20260904` + - HEAD: `f9dd42218b3325e1b3a63d7860e5309f69fd3d8e` + - committed packet changes only `source/bitmaps/bitmaps.c` under `source/bitmaps` (`+543/-10`); no bitmap header is committed + - committed/current bitmap source: 33,657 bytes, SHA-256 `ead2c4f5e80e5ff3668fcd9bcbe7aa759ec3b7f9d925ae4e72c4b43b4d331a0f`, git blob `4ab5acc7ae274687a63ccd7cbd424fe136c85aeb` + - parent blob: `f9f114820d9028782cf0ccc359aa15ce91ae983b`; canonical has the same pre-packet content modulo line endings + - final candidate object: 24,700 bytes, SHA-256 `dba76b32d4cf4c4292e299282b49788e34b0d12876ffd0544b7d6b3017531e25` + - Fable target object: 39,730 bytes, SHA-256 `63435e13ed14ff4f0de291956f4a59849fe32bc529869c781de6a9709ed2eda7` + - tracked Fable `source/bitmaps/` is clean. Other dirty Fable paths (`config/symbols.json`, AI/effects/interface/structures/tool sources, and scratch) are outside this committed bitmap packet and were not used as packet content. + +The Fable report cites `scratch/hdr/bitmaps.md`, but exhaustive bitmap-named scratch inventory found no such file. This is a concrete missing provenance artifact, not merely an untracked header edit. + +## Exact gains over canonical + +Every row below is a hardened all-section match (`section_infos_equal=True`), including ordered symbolic relocations. Sizes are padded target sizes. + +| Candidate symbol | Canonical target identity | Padded bytes / relocations | Normalized hash | +|---|---|---:|---| +| `_bitmap_format_type_valid_width` | `_code_0006ba70` | 32 / 0 | `9c186b7da111114d12055376cee720362e4c2c187874effe3cced0da106d76f1` | +| `_bitmap_format_type_valid_height` | `_code_0006ba90` | 32 / 0 | `9c186b7da111114d12055376cee720362e4c2c187874effe3cced0da106d76f1` | +| `_bitmap_format_type_valid_depth` | `_code_0006bab0` | 48 / 0 | `75a481c693ac7721c67910f76259d485877d2484e0c7d6f0b181d96042d317b4` | +| `_bitmap_rebuild` | `_bitmap_rebuild` | 128 / 11 | `3e6fd87fe17484f181ec6e3f795d4584b2df5fcad4ee728fa39d08f32ecd94ac` | +| `_bitmap_mipmap_get_depth` | same | 144 / 9 | `9a864fce4b366f198a5f4b9cfdb1d2df5753fb5c12473a8c9865c746f5eb4ff4` | +| `_bitmap_mipmap_get_pixel_data_size` | same | 144 / 11 | `49991b5f859b2586d8376832cb0e9a9e9ed81950130a7cbf3de1a18c72f29457` | +| `_bitmap_mipmap_get_width` | same | 160 / 9 | `23d665ecb68ff9891e6bc9e06ceb67e57b1c33093164e19cd221c99ee4ecaf2f` | +| `_bitmap_mipmap_get_height` | same | 160 / 9 | `832b9bfe3bb3f5d40095d322069ed2ab8255ad6fe4cc5fee6d2ad48ba382f686` | +| `_bitmap_mipmap_get_pixel_count` | same | 176 / 12 | `ad3adfeb2cdfb5185c6b515b40fc6ee5a3bcb05f974319280aba43352ae988f4` | +| `_bitmap_mipmap_address` | same | 208 / 15 | `1f23ac477450722c3652ca7881f25452a7a8819f660f516d106b1c6385401d16` | +| `_bitmap_mipmap_get_row_pitch` | same | 224 / 19 | `2bd2fa900e7f0b7a6680b4aa66345616606e3d22df260c48fb9619ec422c7541` | +| `_bitmap_verify` | same | 352 / 10 | `46bb936937128d116aa5eef083323407df4caf6fce00ca85ff1ddcc546f5c49d` | +| `_bitmap_cube_map_new` | same | 368 / 23 | `c5813e5fab4c269cf106bc74a63892fdefa8a96715a08980e669ca0c78edcecd` | +| `_bitmap_2d_new` | same | 384 / 23 | `68479ae7014792a3394f7ecf09e4bf4d07fda2ef53575f98765c3e74f64723cd` | +| `_bitmap_3d_new` | same | 448 / 27 | `c0e0185511ef75dcb7ffd898be4d1b85dc28df147625aa74ea9117f4c77767b7` | +| `_bitmap_cube_map_address` | same | 528 / 33 | `43ae8a218be87e73ca8b99320a75588a3fa17e7431b1dcd5510174180d02ff63` | +| `_bitmap_2d_address` | same | 544 / 33 | `e05dbed80aad3c4fe4f6f38ea9cd93fee9962dac42e6bb59e57b630a6296853e` | +| `_bitmap_3d_address` | same | 656 / 37 | `f837a023753386d82cd1b0d4ace9d01fe337e4155945e08e31c4ada3a4452f86` | + +The nine canonical baseline matches remain strict and all-section stable in the Fable candidate: `bitmap_type_get_string`, `bitmap_format_get_string`, `bitmap_changed`, `bitmap_delete`, `bitmap_byte_swap`, `bitmap_get_max_mipmap_count`, `bitmap_get_pixel_count`, `bitmap_get_pixel_data_size`, and `bitmap_format_get_bits_per_pixel`. + +The final Fable accounting is 27 exact, 0 residual, 7 unwritten, or 5,600 padded exact bytes in total. Subtracting canonical's existing nine leaves precisely the 18 functions and 4,736 padded bytes above. The seven unwritten functions are not packet gains: `palette_find_closest_match`, `bitmap_format_to_a8r8g8b8`, four slice/face functions, and `bitmap_2d_get_pixel`. + +## Linkage, sections, literals, and inherited owners + +- The three validator helpers are static (`storage=3`); the other 15 new functions are external (`storage=2`). All are `type=32`, `value=0`, `.text` COMDAT NODUP (`selection=1`, flags `0x60501020`). +- There is no COMMON symbol in canonical baseline, Fable candidate, or target, and the packet adds no writable `.data`/BSS owner. +- Candidate runtime growth is exactly 44 COMDAT sections: 18 code and 26 `.rdata`. It also adds two debug sections. No baseline runtime section is lost. +- Of the 26 packet-added `.rdata` COMDAT ANY owners, 22 have exact target sections. Four are ordinary candidate-emitted/coalescible assertions absent as definitions from this target object: `bitmap->type==_bitmap_type_3d`, `bitmap->type==_bitmap_type_2d`, `bitmap->type==_bitmap_type_cube_map`, and `### ERROR unsupported bitmap type`. They are compiler/literal owners, not independent target data credit. +- `_global_vector_palette` remains strict-exact (1,116 padded bytes / 21 relocations; hash beginning `443063…`). Apparent symbol-table ownership movement does not change its bytes or ordered relocations. +- `_bitmap_verify` and `_bitmap_mipmap_get_pixel_count` transition undefined to defined. Three inherited functions (`bitmap_get_max_mipmap_count`, `bitmap_get_pixel_count`, `bitmap_get_pixel_data_size`) retain identical bytes/relocations; only their target-symbol metadata changes because calls become same-object definitions. +- Newly required undefined externals are `_error`, `_rasterizer_bitmap_new`, `_csmemset`, and `_debug_malloc`, each explained by genuine packet calls. There is no unexpected new code helper beyond the 18 listed functions. + +## Helper identity caveat + +Canonical intentionally retains generic target names `_code_0006ba70`, `_code_0006ba90`, and `_code_0006bab0`. Depth is uniquely distinguishable: its 48-byte body differs and `bitmap_verify` relocates to `_code_0006bab0`. + +Width and height are each 32 bytes, have no relocations, are byte-identical, and are not independently called from another target section. The Fable mapping `ba70=width`, `ba90=height` follows source/assertion order. That is a plausible inference, but not a unique object-level bijection. Do not import those two `config/symbols.json` aliases as independently authenticated facts. + +## Genuine API owner and caller closure + +`source/bitmaps/bitmaps_mipmap.h` is the narrow existing owner. It already declares mipmap address, cube-map address, width, height, depth, pixel-data-size, and row-pitch, but omits the public function implemented by this packet. The source-authentic declaration is: + +```c +long bitmap_mipmap_get_pixel_count( + struct bitmap_data *bitmap, + short mipmap_index); +``` + +It belongs after depth and before pixel-data-size in `bitmaps_mipmap.h`. A future staged patch should include that header from `bitmaps.c` and remove the C-local declaration. It must not broaden `bitmaps.h`. + +Direct current consumers of `bitmaps_mipmap.h` are: + +- `source/rasterizer/rasterizer_swizzle.c` +- `source/rasterizer/xbox/rasterizer_xbox_hardware_bitmaps.c` + +Adding the owner TU gives an initial three-TU header blast; a complete admission still needs the ordinary all-section/COMMON dependent sweep. + +January undefined-reference caller census for the 15 external additions: + +| Function | January cross-TU callers | +|---|---| +| `bitmap_rebuild` | none | +| `bitmap_mipmap_get_depth` | `rasterizer_swizzle`, `rasterizer_xbox_hardware_bitmaps` | +| `bitmap_mipmap_get_pixel_data_size` | same two | +| `bitmap_mipmap_get_width`, `bitmap_mipmap_get_height` | `bitmap_utilities`, `rasterizer_swizzle`, `rasterizer_xbox_hardware_bitmaps` | +| `bitmap_mipmap_get_pixel_count` | none (same-TU call from `bitmap_get_pixel_count`) | +| `bitmap_mipmap_address` | `bitmap_extract`, `bitmap_utilities`, `rasterizer_swizzle`, `rasterizer_xbox_hardware_bitmaps` | +| `bitmap_mipmap_get_row_pitch` | `xbox_texture_cache`, `rasterizer_swizzle` | +| `bitmap_verify` | `bitmaps_quantitize`, `bitmap_extract`, `bitmap_group`, `bitmap_utilities`, `rasterizer_swizzle` | +| `bitmap_cube_map_new` | `bitmap_extract`, `bitmap_utilities` | +| `bitmap_2d_new` | `bitmap_extract`, `bitmap_utilities`, `tiff_file`, `main`, `rasterizer_text` | +| `bitmap_3d_new` | `bitmap_extract`, `bitmap_utilities` | +| `bitmap_cube_map_address` | `bitmap_extract`, `rasterizer_xbox_hardware_bitmaps` | +| `bitmap_2d_address` | `bitmaps_quantitize`, `bitmap_drawing`, `bitmap_extract`, `bitmap_utilities`, `targa_file`, `tiff_file`, `rasterizer_text`, `rasterizer_xbox` | +| `bitmap_3d_address` | `bitmap_extract`, `bitmap_utilities` | + +The target census is object authority; some target callers remain unwritten in current source. Existing local shadows in `tiff_file.c`, `targa_file.c`, and `main.c` should not be swept into this packet. + +`bitmap_rebuild` is externally linked but has neither a current declaration nor a current/January cross-TU caller. Its eventual public/internal owner is unresolved and need not be invented for this isolated implementation. + +The Fable source adds a local declaration for `rasterizer_bitmap_new`. That is a foreign public facade. Current definitions live in `source/rasterizer/xbox/rasterizer_xbox_hardware_bitmaps.c`; the only shared declaration found for `rasterizer_bitmap_new`/`rasterizer_bitmap_changed` is misleadingly housed in `source/rasterizer/rasterizer_text.h`, while delete has no common owner. This owner gap must be adjudicated rather than perpetuating another C-local prototype. + +The type/format/flag constants added by Fable are TU-private. Other TUs also duplicate subsets, and no authenticated shared enum owner currently exists. HCEA corroborates their values, but they should not be promoted into protected `bitmaps.h` as part of this intake. + +## Natural/provenance classification + +The final exact object is not a retained first-natural candidate. Both scratch `ng_bitmaps.obj` and `w_bitmaps.obj` already contain all 27 exact bodies, while `w_bitmaps_v1` through `v9` source artifacts demonstrate experimentation without a frozen first-natural object/inventory. + +Specific conflicts with a clean natural claim: + +- Canonical `docs/object_matching_logs/bitmaps_obj_jonas_max_mipmap_leaf_20260821.md` froze earlier rejection evidence for width, height, depth, and pixel-count. The Fable report records corrected `MAX` polarity for width/height/depth and corrected call order for pixel-count; these reuse already measured boundaries. +- Pixel-data-size was first 160 bytes and corrected after a prototype issue. +- `bitmap_verify` was measured across eight variants, exceeding the worker's stated bounded-variant rule. It is an exact reconstruction, not a natural first candidate. +- The report's batch heading “first compile + one bounded correction” is therefore not a reliable function-level provenance description. + +The strongest reported tier, without elevating worker prose to proof, is the 12-function / 3,600-padded-byte subset with no recorded second-try marker: the three validators, rebuild, mipmap-address, row-pitch, three constructors, and three address functions. Address trio is explicitly reported exact on first compile. The six remaining functions (width, height, depth, pixel-count, pixel-data-size, and verify) total 1,136 padded bytes and carry explicit correction/tuning concerns. + +HCEA sources support semantics, types, and names, and Stian supports later Xbox disassembly reconstruction; neither is authentic January PC source authority. They cannot erase the preserved canonical rejection history. + +## Safe staged next action for the owner + +1. Freeze the source fragment and inventories before adapting it. +2. Trial only the missing `bitmap_mipmap_get_pixel_count` declaration in `bitmaps_mipmap.h`, include that owner header in `bitmaps.c`, and remove the local duplicate. Blast the two existing consumers plus owner, then run the full all-section/COMMON dependent check. +3. Resolve `rasterizer_bitmap_new` in a genuine rasterizer owner surface; do not add another foreign C-local facade. +4. Keep `bitmaps.h` and `bitmap_utilities.c` untouched. The prior selective-donor ledger records that broad `bitmaps.h` expansion changed protected Units (189 to 188). +5. Review the stronger 12-function tier separately from the six target-guided functions. Do not use the final 27-exact object as first-natural evidence. +6. Retain generic aliases for the indistinguishable width/height helpers unless another direct symbol source authenticates their address-to-name ordering. +7. Leave the seven unwritten residuals and the separate `bitmap_drawing.c`/`tiff_file.c` pending lanes outside this packet. + +## Evidence read + +- Fable `scratch/reports/bitmaps.md` — SHA-256 `d8a0b71d81cf1bfb7edd4aea6dc5006612e0e7f5cf44b96f80bb42d45cbdce5f` +- Fable `scratch/facts/bitmaps.md` — SHA-256 `4712f9f4e9c85eb02e88e35a60cf14230b4f9b07969b5b011544e126bbc1addd` +- Canonical `docs/object_matching_logs/fable_50k_small_families_interrupted_lane_intake_20260905.md` — SHA-256 `788f18e1b6303604e8be6ca8f82838f0f813e59d926073c3b18d14fd7fc07125` +- Canonical `docs/object_matching_logs/bitmaps_obj_jonas_max_mipmap_leaf_20260821.md` — SHA-256 `d70b30…` +- Canonical `docs/object_matching_logs/bitmap_utilities_obj_selective_donor_reconciliation_20260831.md` — SHA-256 `c62522…` +- Current canonical/Fable bitmap sources and headers, Fable commit diff, scratch object inventories, January target symbol/relocation census, and HCEA/Stian bitmap source evidence. diff --git a/docs/opus_unfinished_session_reconciliation_backlog_20260903.md b/docs/opus_unfinished_session_reconciliation_backlog_20260903.md index b1b252b3..2f59ca4e 100644 --- a/docs/opus_unfinished_session_reconciliation_backlog_20260903.md +++ b/docs/opus_unfinished_session_reconciliation_backlog_20260903.md @@ -2,17 +2,20 @@ ## Current verified canonical / publication-batch totals (2026-09-05) -The current ErrorGeometry publication batch after `e98e3ff62852c1031f9ff74101eb0396136b42d9` contains: -**910,301 meaningful matched code bytes**, **6,186 credited functions**, +The current ActionObey owner/leaf publication batch after `31a1927c951479106d0475ee99e1fb236a15e89d` contains: +**910,347 meaningful matched code bytes**, **6,187 credited functions**, **2,061,020 matched data bytes**, and **391/833 Matching objects**. -The full sweep preserves all6,222 inherited strict owners and adds ten, -for **6,232 strict owners**. There are now **284 approved fuzzy parks**. -The batch adds2,955 meaningful exact code bytes and ten functions; matched -data and complete-object totals are unchanged. Its complete natural polygon -writer is an honest99.91892% scheduling residual. The genuine owning header -passes its complete two-consumer audit. All288 tests plus26 subtests pass. -Independent owner review and24-case behavioral comparisons pass for both the -actual and isolated builds; the reusable harness is included with the packet. +The full sweep preserves all6,232 inherited strict owners and adds one, +for **6,233 strict owners**. There are **284 approved fuzzy parks**. +This checkpoint adds46 meaningful exact code bytes and one function; matched +data and complete-object totals are unchanged. Genuine ActionObey public API +and shared swarm/biped schema ownership pass complete47- and58-consumer +audits. Two residual encoding/load-order changes are independently proven; +speech-timer fuzzy coverage returns97.76382% to97.67839% with no exact loss. +All288 tests plus26 subtests pass; the final leaf passes1,024 cases each in +target, actual and isolated objects. Units remains189/189 exact. The preceding +ErrorGeometry batch contributed2,955 meaningful bytes and ten functions; +its polygon writer remains an honest99.91892% scheduling residual. Publication status must be verified against the canonical GitHub branch refs. ActorCombat grenade aim's unsupported vehicle-path park remains withdrawn. The preceding @@ -31,11 +34,17 @@ is lifted. The main and shadow intake is complete; the tip is not safe to cherry-pick wholesale because its retained Path source/snapshot disagree and its particle-header zero-loss claim lacks a successful retained blast log. The first coherent ErrorGeometry packet is retained, while its two later -dirty residual additions remain preserved for separate review. ActionObey -is next in read-only assessment. Preserve all donor committed/dirty work, +dirty residual additions remain preserved for separate review. ActionObey's +owner/schema and structure-flush checkpoint is verified; the larger real +private command graph and math ownership are still scratch work. Bitmaps has +18 distinct donor exact candidates/4,736 padded bytes, with ownership and +provenance review still required; these are not new canonical credit. +Preserve all donor committed/dirty work, compare against current canonical and never sum historical totals into ours. See `object_matching_logs/fable_50k_small_families_interrupted_lane_intake_20260905.md` and `object_matching_logs/error_geometry_obj_fable_natural_reconciliation_20260905.md`. +See also `object_matching_logs/action_obey_obj_shared_schema_and_structure_flush_reconciliation_20260905.md` +and `object_matching_logs/bitmaps_obj_fable_packet_intake_20260905.md`. New Opus implementation reservations are recorded in the separately delivered 30,000-byte prompt; no implementation in those scopes is part of this packet. diff --git a/source/ai/action_charge.c b/source/ai/action_charge.c index 5223a61e..6200deb7 100644 --- a/source/ai/action_charge.c +++ b/source/ai/action_charge.c @@ -138,9 +138,6 @@ enum /* ---------- prototypes */ -void actor_move_keep_moving_past_destination( - long actor_index); - boolean unit_get_melee_range_and_ticks( long unit_index, boolean secondary, diff --git a/source/ai/action_obey.c b/source/ai/action_obey.c index 770920ff..6b1aa115 100644 --- a/source/ai/action_obey.c +++ b/source/ai/action_obey.c @@ -327,11 +327,6 @@ void code_00007840( struct obey_individual_simple_control *simple_control, struct obey_individual_complex_control *complex_control, void *user_data); -void actor_action_change( - long actor_index, - long new_action_type, - struct action_state_data *new_action_data); - /* ---------- globals */ /* ---------- public code */ @@ -363,6 +358,20 @@ void action_obey_flush_command_indices( return; } +void action_obey_flush_structure_indices( + long actor_index) +{ + struct actor_datum *actor = actor_get(actor_index); + struct obey_state_data *state_data = &actor->state.action_data.obey; + + if (state_data->complex_control.destination_valid) + { + state_data->complex_control.destination_surface_index = NONE; + } + + return; +} + void action_obey_advance_command_list( long actor_index) { diff --git a/source/ai/actions.c b/source/ai/actions.c index 651decb1..b1f6be22 100644 --- a/source/ai/actions.c +++ b/source/ai/actions.c @@ -461,11 +461,6 @@ boolean action_flee_setup( boolean allow_occluded_points, struct flee_state_data *state_data); -boolean action_obey_command_list_setup( - long actor_index, - short command_list_index, - struct obey_state_data *state_data); - boolean action_guard_setup_from_fleeing( long actor_index, struct flee_state_data *flee_state, @@ -778,17 +773,6 @@ void action_charge_update( void action_charge_control( long actor_index); -void action_obey_begin( - long actor_index); -boolean action_obey_perform( - long actor_index); -void action_obey_update( - long actor_index); -void action_obey_control( - long actor_index); -void action_obey_end( - long actor_index); - void action_converse_begin( long actor_index); boolean action_converse_perform( diff --git a/source/ai/actions.h b/source/ai/actions.h index 68797f52..5df907fa 100644 --- a/source/ai/actions.h +++ b/source/ai/actions.h @@ -24,6 +24,15 @@ enum NUMBER_OF_OBEY_METADATA_FLAGS, }; +enum +{ + _obey_simple_directmovement_bit = 0, + _obey_simple_directmovement_update_continuously_bit, + _obey_simple_jump_bit, + _obey_simple_jump_jumped_bit, + _obey_simple_jump_targeted_bit, +}; + enum { _pursuit_location_target = 0, @@ -526,6 +535,26 @@ real normalize3d( /* ---------- prototypes/ACTION_OBEY.C */ +boolean action_obey_command_list_setup( + long actor_index, + short command_list_index, + struct obey_state_data *state_data); +void action_obey_flush_command_indices( + long actor_index); +void action_obey_flush_structure_indices( + long actor_index); +void action_obey_advance_command_list( + long actor_index); +void action_obey_begin( + long actor_index); +boolean action_obey_perform( + long actor_index); +void action_obey_update( + long actor_index); +void action_obey_control( + long actor_index); +void action_obey_end( + long actor_index); void action_obey_describe_command( struct scenario *scenario, struct ai_command_definition *command, diff --git a/source/ai/actor_perception.c b/source/ai/actor_perception.c index f9116647..6610e36f 100644 --- a/source/ai/actor_perception.c +++ b/source/ai/actor_perception.c @@ -294,14 +294,6 @@ symbols in this file: /* ---------- structures */ -struct actor_perception_swarm_component_view -{ - short identifier; - word flags; - real_point3d position; - byte __unknown010[SWARM_COMPONENT_DATUM_SIZE - 0x10]; -}; - struct actor_perception_ai_debug_state_view { byte __unknown000[6]; @@ -357,10 +349,6 @@ struct ai_profile_globals } data; }; -#define swarm_component_get(index) \ - ((struct actor_perception_swarm_component_view *)datum_get( \ - swarm_component_data, (index))) - #define actor_perception_ai_debug_get() \ ((struct actor_perception_ai_debug_state_view *)&ai_debug) @@ -918,8 +906,6 @@ typedef char actor_perception_prop_view_perception_result_offset_assert[ offsetof(struct actor_perception_prop_view, perception_result) == 0x30 ? 1 : -1]; typedef char actor_perception_prop_view_dangerous_vehicle_driver_offset_assert[ offsetof(struct actor_perception_prop_view, dangerous_vehicle_driver) == 0x136 ? 1 : -1]; -typedef char actor_perception_swarm_component_position_offset_assert[ - offsetof(struct actor_perception_swarm_component_view, position) == 4 ? 1 : -1]; typedef char actor_perception_status_unit_flags_offset_assert[ offsetof(struct actor_perception_status_unit_view, status_flags) == 0x1B4 ? 1 : -1]; typedef char actor_perception_target_unit_active_region_offset_assert[ @@ -3201,7 +3187,7 @@ void actor_perception_find_sense_position( for (unit_index = 0; unit_index < swarm->unit_count; unit_index++) { - struct actor_perception_swarm_component_view *component = + struct swarm_component_datum *component = swarm_component_get(swarm->component_indices[unit_index]); real distance_squared = distance_squared3d(&component->position, position); @@ -3257,14 +3243,14 @@ static long actor_perception_unit_from_swarm( for (unit_index = 0; unit_index < swarm->unit_count; unit_index++) { - struct actor_perception_swarm_component_view *component = + struct swarm_component_datum *component = swarm_component_get(swarm->component_indices[unit_index]); real distance_squared = distance_squared3d( &component->position, &position->body_position); - if (TEST_FLAG(component->flags, 1)) + if (TEST_FLAG(component->flags, _swarm_component_attached_to_unit_bit)) { distance_squared *= 2.25f; } diff --git a/source/ai/actor_type_infection.c b/source/ai/actor_type_infection.c index f4af6b52..0ef1df6f 100644 --- a/source/ai/actor_type_infection.c +++ b/source/ai/actor_type_infection.c @@ -79,29 +79,6 @@ enum _swarm_movement_obey, }; -enum -{ - _swarm_component_attacking_in_melee_bit = 0, - _swarm_component_attached_to_unit_bit, - _swarm_component_wander_bit, - _swarm_component_obey_bit, - _swarm_component_obey_desire_jump_bit, -}; - -enum -{ - _obey_simple_directmovement_bit = 0, - _obey_simple_directmovement_update_continuously_bit, - _obey_simple_jump_bit, - _obey_simple_jump_jumped_bit, - _obey_simple_jump_targeted_bit, -}; - -enum -{ - _biped_airborne_bit = 0, -}; - enum { _unit_melee_attack_none = 0, @@ -113,38 +90,8 @@ enum /* ---------- macros */ -#define swarm_component_get(index) \ - ((struct swarm_component_datum *)datum_get(swarm_component_data, (index))) - /* ---------- structures */ -struct swarm_wander_control -{ - byte pause_ticks; - byte move_ticks; - word pad; - real_vector3d vector; - real angle; -}; - -struct swarm_component_datum -{ - short identifier; - word flags; - real_point3d position; - long surface_index; - long combat_target_prop_index; - byte attached_to_unit_ticks; - byte ground_ticks; - byte attack_delay_ticks; - byte pad; - union - { - struct swarm_wander_control wander; - struct obey_individual_simple_control obey; - }; -}; - struct unit_control_data { char animation_state; diff --git a/source/ai/actors.c b/source/ai/actors.c index a533a7a4..109a99aa 100644 --- a/source/ai/actors.c +++ b/source/ai/actors.c @@ -463,10 +463,6 @@ enum /* ---------- macros */ -#define swarm_component_get(index) \ - ((struct swarm_component_datum *)datum_get( \ - swarm_component_data, (index))) - /* These object chains are polymorphic. The accessors preserve January's * broad verification masks while giving each use site the complete layout it * needs after checking object.type. */ @@ -514,16 +510,6 @@ typedef char actor_iterator_size_assert[ typedef char actor_iterator_index_offset_assert[ offsetof(struct actor_iterator, index) == 0x14 ? 1 : -1]; -struct swarm_component_datum -{ - short identifier; - word flags; - real_point3d position; - long surface_index; - long combat_target_prop_index; - byte unknown_tail[SWARM_COMPONENT_DATUM_SIZE - 0x18]; -}; - struct actor_variant_change_colors { real_rgb_color color_lower_bound; diff --git a/source/ai/actors.h b/source/ai/actors.h index 4de25a2d..ea715dbe 100644 --- a/source/ai/actors.h +++ b/source/ai/actors.h @@ -31,6 +31,15 @@ enum SWARM_COMPONENT_DATUM_SIZE = 0x40, }; +enum +{ + _swarm_component_attacking_in_melee_bit = 0, + _swarm_component_attached_to_unit_bit, + _swarm_component_wander_bit, + _swarm_component_obey_bit, + _swarm_component_obey_desire_jump_bit, +}; + enum { _actor_target_none = 0, @@ -259,6 +268,9 @@ enum #define swarm_get(index) ((struct swarm_datum *)datum_get(swarm_data, (index))) #define swarm_try_and_get(index) ((struct swarm_datum *)datum_try_and_get(swarm_data, (index))) +#define swarm_component_get(index) \ + ((struct swarm_component_datum *)datum_get(swarm_component_data, (index))) + /* ---------- structures */ struct firing_position_search_definition; @@ -800,6 +812,32 @@ struct swarm_datum long component_indices[MAXIMUM_COMPONENT_INDICES_PER_SWARM]; }; +struct swarm_wander_control +{ + byte pause_ticks; + byte move_ticks; + real_vector3d vector; + real angle; +}; + +struct swarm_component_datum +{ + short identifier; + short flags; + real_point3d position; + long surface_index; + long combat_target_prop_index; + byte attached_to_unit_ticks; + byte ground_ticks; + byte attack_delay_ticks; + byte pad; + union + { + struct swarm_wander_control wander; + struct obey_individual_simple_control obey; + }; +}; + struct vehicle_avoidance_cylinder { long object_index; @@ -1083,6 +1121,8 @@ boolean actor_move_to_point( real_point3d const *destination, long surface_index, long ignore_target_object_index); +void actor_move_keep_moving_past_destination( + long actor_index); boolean actor_move_to_move_position( long actor_index, short move_position_index); diff --git a/source/ai/ai_scenario_definitions.h b/source/ai/ai_scenario_definitions.h index 6b181d31..75aaa083 100644 --- a/source/ai/ai_scenario_definitions.h +++ b/source/ai/ai_scenario_definitions.h @@ -105,6 +105,29 @@ enum NUMBER_OF_AI_ATOM_TYPES, }; +enum +{ + _ai_command_list_allow_initiative_bit = 0, + _ai_command_list_allow_targeting_bit, + _ai_command_list_disable_looking_bit, + _ai_command_list_disable_communication_bit, + _ai_command_list_disable_falling_damage_bit, +}; + +enum +{ + _ai_atom_loop_modifier_until_told_to_advance = 1, +}; + +/* Descriptive names for January's four movement-facing modifier values. */ +enum +{ + _ai_atom_move_facing_forwards = 0, + _ai_atom_move_facing_backwards, + _ai_atom_move_facing_left, + _ai_atom_move_facing_right, +}; + /* ---------- macros */ diff --git a/source/cutscene/recorded_animations.h b/source/cutscene/recorded_animations.h index 63263980..0cb19a8c 100644 --- a/source/cutscene/recorded_animations.h +++ b/source/cutscene/recorded_animations.h @@ -28,6 +28,16 @@ void recorded_animations_clear_debug_storage( boolean recorded_animation_controlling_unit( long unit_index); +boolean recorded_animation_play( + long unit_index, + short animation_index); +boolean recorded_animation_play_and_delete( + long unit_index, + short animation_index); +boolean recorded_animation_play_and_hover( + long unit_index, + short animation_index); + /* ---------- globals */ /* ---------- public code */ diff --git a/source/game/player_control.c b/source/game/player_control.c index 38365503..a226bdf9 100644 --- a/source/game/player_control.c +++ b/source/game/player_control.c @@ -233,11 +233,6 @@ enum control_button NUMBER_OF_ACTION_CONTROL_BUTTONS, }; -enum -{ - _biped_airborne_bit = 0, -}; - enum mouse_button { _mouse_button_left = 0, diff --git a/source/game/players.c b/source/game/players.c index 5aee282e..8c41a5f2 100644 --- a/source/game/players.c +++ b/source/game/players.c @@ -2108,7 +2108,7 @@ boolean players_respawn_coop( { dangerous = TEST_FLAG( biped->biped.flags, - _biped_limping_bit); + _biped_airborne_bit); } else { diff --git a/source/hs/hs.c b/source/hs/hs.c index 3c788c71..6a5e2f2e 100644 --- a/source/hs/hs.c +++ b/source/hs/hs.c @@ -2783,6 +2783,7 @@ symbols in this file: #include "ai/ai_scenario_definitions.h" #include "ai/ai_profile.h" #include "cutscene/recorded_animation_definitions.h" +#include "cutscene/recorded_animations.h" #include "devices/devices.h" #include "game/game.h" #include "interface/hud_messaging.h" @@ -3793,15 +3794,6 @@ boolean hs_trigger_volume_test_objects_any( boolean hs_trigger_volume_test_objects_all( short trigger_volume_index, long object_list_index); -boolean recorded_animation_play( - long unit_index, - word recording_index); -boolean recorded_animation_play_and_delete( - long unit_index, - word recording_index); -boolean recorded_animation_play_and_hover( - long unit_index, - word recording_index); boolean lights_enable( boolean enable); boolean unit_start_user_animation( diff --git a/source/units/bipeds.c b/source/units/bipeds.c index 2b9b97a9..cf03bd42 100644 --- a/source/units/bipeds.c +++ b/source/units/bipeds.c @@ -251,12 +251,6 @@ symbols in this file: /* ---------- constants */ -enum -{ - _biped_airborne_bit = 0, - _biped_limp_body_physics_active_bit = 5, -}; - /* ---------- macros */ #define BIPED_CLIMBING_SNAP_ANGLE ((real)(10.0*M_PI/180.0)) diff --git a/source/units/bipeds.h b/source/units/bipeds.h index 512e202f..42a32c96 100644 --- a/source/units/bipeds.h +++ b/source/units/bipeds.h @@ -16,7 +16,12 @@ header included in hcex build. enum { - _biped_limping_bit = 0, + _biped_airborne_bit = 0, + _biped_slipping_bit, + _biped_absolute_movement_bit, + _biped_no_collision_bit, + _biped_movement_passes_through_bipeds_bit, + _biped_limp_body_physics_active_bit, }; /* ---------- macros */ diff --git a/source/units/units.c b/source/units/units.c index b2872e0b..0d72851d 100644 --- a/source/units/units.c +++ b/source/units/units.c @@ -2361,7 +2361,7 @@ void unit_scripting_suspended( if (unit->object.type==_object_type_biped) { struct biped_datum *biped = biped_get(unit_index); - SET_FLAG(biped->biped.flags, _biped_limping_bit, FALSE); + SET_FLAG(biped->biped.flags, _biped_airborne_bit, FALSE); } } @@ -4216,7 +4216,7 @@ boolean unit_melee_attack_begin( struct biped_datum *biped = (struct biped_datum *)unit; limping = TEST_FLAG( biped->biped.flags, - _biped_limping_bit); + _biped_airborne_bit); } if (continuous) @@ -4299,7 +4299,7 @@ boolean unit_leap_begin( { biped_limping = TEST_FLAG( ((struct biped_datum *)unit)->biped.flags, - _biped_limping_bit); + _biped_airborne_bit); } if (!biped_limping && @@ -6544,7 +6544,7 @@ void code_001a0cf0( biped = biped_get(unit_index); biped_definition = biped_definition_get(biped->definition_index); - if (TEST_FLAG(biped->biped.flags, _biped_limping_bit) && + if (TEST_FLAG(biped->biped.flags, _biped_airborne_bit) && !TEST_FLAG( biped_definition->biped.flags, _biped_has_no_dying_airborne_bit)) @@ -10048,7 +10048,7 @@ short unit_update_animation( biped = biped_get(unit_index); biped_definition = biped_definition_get(biped->definition_index); - if (!TEST_FLAG(biped->biped.flags, _biped_limping_bit) || + if (!TEST_FLAG(biped->biped.flags, _biped_airborne_bit) || TEST_FLAG( biped_definition->biped.flags, _biped_has_no_dying_airborne_bit))