Commit Graph
135 Commits
Author SHA1 Message Date
Jonas VolmanandClaude Opus 5 1e936afab0 unit_dialogue: 3 function(s) strict exact
Wave w2 landing, adversarially verified. park reopens: _unit_dialogue_determine_variant, _unit_notify_impulse_sound, _unit_dialogue_update. Full ninja build and per-function stable_verdicts sweep: 0 regressions. 3 park(s) removed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 07:40:00 -07:00
Jonas VolmanandClaude Opus 5 4f66b6d8b0 bipeds: 1 function(s) strict exact
Wave w2 landing, adversarially verified. park reopens: _biped_fix_position. Full ninja build and per-function stable_verdicts sweep: 0 regressions. 1 park(s) removed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 07:39:59 -07:00
Jonas VolmanandClaude Opus 5 a7d0d43883 Declare the weapon trigger graph's cross-object callees in their owner headers
actor_firing_blindly (actors.h), player_aim_projectile (aim_assist.h), projectile_kill_tracer (projectiles.h), unit_adjust_projectile_ray (units.h) and the remaining weapon datum flag bits. Removes the verbatim duplicate collision_surface_polygon prototype from collision_bsp.h; without that cleanup the two added declarations regress units::_unit_preprocess_node_orientations (declaration-count sensitivity, bisected). Full build with the weapons body: 0 regressions, parks clean.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-13 19:47:36 -07:00
Jonas VolmanandClaude Opus 5 d154664b21 bipeds: close start_landing and update_jumping; January-derived update_physics fuzzy
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-13 19:19:54 -07:00
Jonas Volman 5d3444f799 Reconcile eighth 10K exact source batch 2026-09-13 02:47:59 -07:00
Jonas Volman eb61c0f746 Reconcile seventh 10K exact source batch 2026-09-12 17:23:46 -07:00
Jonas Volman d6250fa794 Reconcile sixth 10K exact source batch 2026-09-12 12:36:44 -07:00
Jonas Volman 5ca90d450e Reconstruct unit dialogue speech arbitration 2026-09-09 09:57:50 -07:00
Jonas Volman acd35c00b9 ai: narrow runtime declaration ownership 2026-09-09 07:48:00 -07:00
Jonas Volman 105d9acaac Reconcile 10K exact-byte Claude batch 2026-09-09 00:07:34 -07:00
Jonas Volman 292cc29b86 Reconcile final Fable and Opus source batch 2026-09-08 17:34:52 -07:00
Jonas Volman 99a194a4b9 Share diagnostic contracts and source reconstruction references 2026-09-06 10:31:31 -07:00
Jonas Volman c32247e765 Reconcile ActionObey shared owners and verified structure flush 2026-09-05 22:24:15 -07:00
Jonas Volman 857b355d80 Reconcile Profile enter-exit ownership and park typed Biped placement 2026-09-04 21:58:41 -07:00
Jonas Volman 4453bedd7b Match small damage vitality leaves 2026-09-04 06:15:41 -07:00
Jonas Volman 55351b58d0 Reconcile interrupted Opus Leaf and Biped gains 2026-09-04 04:46:30 -07:00
Jonas Volman b175ed2be1 Reconcile Opus effects reconstruction 2026-09-04 03:48:30 -07:00
Jonas Volman 58618a7909 Complete player control input cluster 2026-09-03 05:46:48 -07:00
Jonas Volman ad1ca53e57 Narrow unit dialogue prototype ownership 2026-09-03 05:39:16 -07:00
Jonas Volman d0b35eb8f3 Reconstruct unit dialogue setup and update 2026-09-03 05:22:40 -07:00
Jonas Volman 8b02b172d0 Correct collision movement interfaces 2026-09-02 22:04:26 -07:00
Jonas Volman 01a2daac6d Reconcile limp-noodle collision interfaces 2026-09-02 22:04:26 -07:00
Jonas Volman 019e738610 Reconstruct biped limp-noodle solver 2026-09-02 22:04:26 -07:00
Jonas Volman c5ce04c77c Fix biped limp-noodle interface ownership 2026-09-02 20:41:56 -07:00
Jonas Volman cd10033235 Reconstruct actors creation and spawn wave 2026-09-02 19:59:10 -07:00
Jonas Volman 60957d0cb2 Recover remaining small HUD frontier 2026-09-02 04:42:30 -07:00
Jonas Volman 5ea4a47ca6 bipeds: preserve January point helper ownership 2026-09-02 02:22:06 -07:00
Jonas Volman fede67af5b Preserve Units through owner header cleanup 2026-09-02 02:05:08 -07:00
Jonas Volman 92fd55d6eb Reconstruct nine biped functions 2026-09-02 01:57:40 -07:00
Jonas Volman 4277f892c1 Admit audited Claude reconstruction gains
Retain 18 strict exact-function gains across Actions, Actor Combat, Decals, Game Engine, Object Lights, and Bipeds after removing donor bodies that regressed exact objects, emitted unowned code, or violated source-credibility rules. Name authenticated private symbols, move declarations to owner headers, record honest residual parks, and preserve units.obj at 189/189.
2026-08-31 20:42:01 -07:00
Jonas Volman 9f74e9937f Import 909 authenticated January and HCEA symbol names 2026-08-31 16:11:03 -07:00
Jonas Volman 69ce74cc76 Recover biped export and speech priority leaves 2026-08-31 12:15:39 -07:00
Jonas Volman 179ea4a366 Recover small actor bitmap biped and weapon owners 2026-08-31 11:53:54 -07:00
Jonas Volman 6b797dc3de Recover biped limp and flight pair 2026-08-31 09:17:24 -07:00
Jonas Volman 777a30ba1d Place shared prototypes in owner headers 2026-08-30 23:58:08 -07:00
Jonas Volman 677d098217 Recover Players callers without codegen steering 2026-08-30 23:42:05 -07:00
Jonas Volman e8dd0dfeab Recover recorded animations naturally and park scheduling tie 2026-08-30 21:42:26 -07:00
Jonas Volman 84b67aef73 Remove inert Units control-flow artifacts 2026-08-30 21:06:53 -07:00
Jonas Volman ca0846407c Integrate AI script vehicle dispatch cluster 2026-08-29 21:58:49 -07:00
Jonas Volman 74eeadef77 ai: reconstruct AI debug exact checkpoint 2026-08-29 11:00:04 -07:00
Jonas Volman ce3ca83f34 ai: harvest twelve exact debug functions 2026-08-29 08:56:49 -07:00
Jonas Volman 937c659bb3 Finalize strict units object integration 2026-08-28 21:31:49 -07:00
Jonas VolmanandClaude Opus 5 748da59547 Close unit_export_function_values without a compiler barrier
Remove the _ReadWriteBarrier declaration, the #pragma intrinsic and the
barrier call that UEF-8 introduced, and recover January's schedule from
ordinary C89.

The barrier did exactly one thing: it stopped VC7's list scheduler from
hoisting the output-pointer formation above tag_get. Two source controls
replace it.

First, index the arrays instead of walking hand-written pointers. The
sibling object_export_function_values in source/objects/objects.c is
strict-exact and indexes; January's object shows VC7 strength-reducing
that into the same walking pointers and homed down-counter, with the
cdecl cleanup immediately after the call and both bases formed by lea
and no copy. Writing the unit exporter the same way makes the whole
preamble byte-exact and takes the residual from 30 bytes to 9. The
walking pointers in the target are compiler output, not source, which is
why every pointer-form experiment in the UEF matrix plateaued.

Second, bind animation->private_loop_frame_index to a named local used
twice, in the predicate and in the division. The last nine bytes were a
load-order swap; source operand order does not control it, but a two-use
local does. UEF-12 had tested named locals and seen them eliminated, but
it bound both operands with a single use each, and a single-use copy is
propagated away.

_unit_export_function_values is 384/384 bytes, 18/18 relocations, and its
normalized SHA-256 equals the target's 4149e4cd...b20c35;
section_infos_equal is True. The emitted section is raw byte-for-byte
identical to the previously accepted barrier build.

Verified: clean forced rebuild reproduces; compare_object_exact_sets
reports 189 exact both ways with lost_exact empty; verdicts diff over all
8246 functions gains 0 and regresses 0; halobetacache_build,
libcmt_build, semantic_progress and progress pass; object-admission,
semantic-match and parked audits pass; pytest tools 203 passed;
git diff --check clean.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-28 21:17:05 -07:00
Jonas VolmanandClaude Opus 5 978fd91b7e Make unit_update byte-identical to January
Split the camo regrowth guard's three-conjunct condition into nested ifs
with explicit else arms assigning the default rate, and scope the set
flag to the branch that uses it. Behaviour-identical: game_engine_running
is still evaluated exactly once, the short-circuit order is unchanged,
and every path that previously left set FALSE now assigns 1.f/120.f.

That flips VC7 from eager to lazy placement of the partially redundant
[ebp+8] reload. January duplicates it per predecessor -- 0x49c on the
main path, 0x4f6 at the bypass merge, 0x533 in the else arm, with the
jne going to 0x4f9 to skip the merge copy -- where we had hoisted a
single dominating copy to 0x48a.

_unit_update is now 1642 instructions with normalized_sha256 EQUAL to
January: zero differing bytes, from 632.

section_infos_equal still reports False on 2 of 259 relocations, both
the same function-local static spelled two ways: build/split has
`unit_update'::`114'::last_time where CL emits
?last_time@?HC@??unit_update@@9@9. That is the known naming gap in
config/symbols.json, not a codegen difference -- all 259 addresses and
types match and the other 69 differing records are forgiven by
symbolic_target.

CL /Zs /W3 unchanged at 43 diagnostics.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-28 21:17:04 -07:00
Jonas VolmanandClaude Opus 5 51d3958e3b Name the two animation flag bits in unit_update (byte-neutral)
units.c:5569 and 5582 tested and cleared animation flags by raw bit
number, which the campaign's own source rules forbid. The 2011 HCEX PDB
resolves both enumerators: _unit_animation_fallen_on_front_bit is 3 and
_unit_animation_ignore_translation_bit is 2, matching our units.h and
the emitted masks (shr cl,3 and and byte ptr [ebx+0x248],0FBh).

The names also make the resurrect ternary read correctly: fallen on the
front resurrects front, otherwise back.

Verified byte-neutral: census stays 188/1/0 code, data unchanged, and
_unit_update is bit-identical. CL /Zs /W3 unchanged at 43 diagnostics.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-28 21:17:04 -07:00
Jonas VolmanandClaude Opus 5 bc6208e46d Close unit_update_animation by fixing code_0019b160's parameter order
The 2011 HCEX PDB compiland dump records this helper as
unit_animation_update(long, long, struct animation_state *) -- the
animation pointer is the THIRD parameter. Our reconstruction had it
first. Reordering the prototype, the definition and all four call sites
to (long unit_index, long animation_graph_index, struct animation_state
*animation) also puts unit_index first, matching the convention used
everywhere else in this file.

That was the whole residual. VC7 assigns its custom register convention
by parameter order, so the wrong order changed which argument landed in
which register at every code_0019b160 call site -- the 23 differing
bytes all began at 0x195, inside the first of those argument setups.
The "one missing scratch allocation" reading of the residual was a
symptom, not the cause.

units.obj code census 187/2/0 -> 188/1/0; data unchanged.
_unit_update_animation and _code_0019b160 are both byte-exact.
CL /Zs /W3 unchanged at 43 diagnostics with identical codes.

Only _unit_update remains.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-28 21:17:04 -07:00
Jonas VolmanandClaude Opus 5 c462b1df7f Adopt the PDB's parameter linkage and January's local names (byte-neutral)
The 2011 HCEX PDB records unit_update_animation's second parameter as
struct unit_animation_update_data * -- non-const. Drop the const from
both the prototype and the definition.

Adopt January's local names from the same source: old_world_matrix and
exit_velocity in unit_update_animation, last_aiming_vector and
object_matrix in unit_update.

Also apply the layout implied by January's own assert line numbers. The
two match_assert calls in unit_update_animation carry lines 0xb61 = 2913
and 0xb73 = 2931, so seventeen lines hold the whole if, declaration and
seven-arm switch. That fits only with the declaration carrying its
initialiser and no default arm, so write
short desired_base_seat_index = NONE; and drop default: break;.

Verified byte-neutral: census stays 187/2/0 code and unchanged data;
unit_update_animation stays at 23 differing bytes and unit_update at its
one instruction. CL /Zs /W3 unchanged at 43 diagnostics.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-28 21:17:04 -07:00
Jonas VolmanandClaude Opus 5 884f9db1e1 Close unit_animation_set_state with a graph-index carrier local
Route the three animation_choose_random_permutation_internal call sites
through a long animation_graph_index local, matching the byte-exact
unit_start_animation_impulse idiom at units.c:8535 and units.c:3245.
unit_animation_set_state was the file's only site that inlined the field
expression into the call.

That flips one allocator decision: January spends EDI on the unit_seat
pointer (mov edi,eax / lea eax,[edi+0x58] / mov [ebp-0x1c],edi, then
direct mov ecx,[edi+0x40] and [edi+0x44] later) and homes animation_index
at [ebp-0xc); we did the reverse and reloaded the pointer at every use.
The frame going 0x18 -> 0x1c and all three or edx,0ffffffffh sites were
consequences, not separate differences.

units.obj code census 186/3/0 -> 187/2/0; data unchanged at 129/0/0.

Also reproduce January's setcc spelling in unit_update_animation: split
the shared alert/suspicious case arm and write the in_combat arm with no
byte-typed intermediate. setcc r8 ; movzx r16,r8 occurs zero times in all
9352 January functions; the new shape emits January's
xor ebx,ebx / test cl,cl / setne bl / add ebx,2 and matches January's
relocation layout exactly (relocation_infos_equal was False, now True).
Still non-exact: 23 bytes, all register choices.

CL /Zs /W3 unchanged at 43 diagnostics with identical codes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-28 21:17:04 -07:00
Jonas VolmanandClaude Opus 5 c5f84ee42a Adopt the PDB's types and linkage for animation_set_state (byte-free)
Zero owners changed: the emitted object is byte-identical, verified by
function body hash and by a whole-object comparison across all 415
owners and 447 sections.  Census stays 186/3/0, /Zs /W3 stays at 43
warnings.  This is fidelity only.

DIA2Dump on the June-2011 HCEX.pdb reports, for unit_animation_set_state:
`Type: short, interpolation_frame_count` and `static function: true`.
Both are adopted:

  - interpolation_frame_count becomes short, code_00198230 goes back to
    returning short with `short result = 6;`, and the now-redundant
    (short) cast at object_start_interpolation is dropped.  This reverts
    the "code_00198230 returns long" reconstruction landed in f38ea306,
    which was only ever justified by removing one `movsx eax,ax`; the
    short spelling removes it too and matches the PDB, so the long
    spelling has no remaining evidence behind it.
  - unit_animation_set_state becomes static.  Nothing outside units.c
    references it - it appears in no header and in no other translation
    unit - so this cannot break a link.

Both changes were measured byte-identical individually and together
before landing, by SHA1 of the reloc-zeroed function bodies rather than
by equal counters.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-28 21:17:04 -07:00
Jonas VolmanandClaude Opus 5 0ae5430283 Home animation_set_state's result via goto, as January does
Replaces the previous commit's `result = code_001981f0(...)` spelling
with the one January actually used.  All SIX of the function's target
idioms now match: `xor dl,dl`, `mov dl,1`, `test dl,dl`, the homed
`mov byte ptr [ebp-2],1`, its `mov al,[ebp-2]` reload at the return, and
the `xor al,al` early epilogue.  The head 0x83-0x99 is now
instruction-for-instruction identical to January including register
choices.

    -           result = code_001981f0(new_state);
    -           if (!result) { return result; }
    +           if (!code_001981f0(new_state))
    +           {
    +                   result = FALSE;
    +
    +                   goto done;
    +           }
    ...
    +done:
        return result;

`goto <label>;` is house style here - eleven other files in source/ use
it.  Behaviour is unchanged: the only path to the label sets result FALSE
first, so `return result` returns FALSE exactly as `return FALSE` did.

Why it works where every earlier attempt failed: VC7 constant-folds a
definition that is consumed by an immediately following `return`, which
is why `result = FALSE; return result;` has always been byte-identical to
base.  A `goto` to a label in front of the common return survives
allocation, so `result` genuinely has two reaching definitions and is
homed; VC7 then tail-duplicates that exit into `xor al,al`, reproducing
January's 0x2de epilogue.

    landed before  raw 232/232  reg+slot 63/34 blocks  51 -> no result home
    landed now     raw 210/194  reg+slot 68/31 blocks       result homed

reg+slot reads three bytes worse, which is normalisation noise; raw diff
bytes, block counts and the idiom set all improve, and the structural
match is what counts.

The size now reads 1392 against 1408.  That is honest rather than a
regression: real code is 1195 versus January's 1203, and the previous
1408 was a 16-byte COMDAT alignment artifact.  A separate drift analysis
confirms there is no block where the target has code we lack - 366
instructions against 365 - so the whole remainder is one allocator
decision: January homes a seventh carrier, the inner short
animation_index, sharing [ebp-0xc] with interpolation_frame_count, giving
sub esp,0x1c where we keep it in di and get 0x18.

Census unchanged at 186/3/0; exactly one owner changed; /Zs /W3 identical
at 43 warnings.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-28 21:17:04 -07:00