Close unit_place exactly: units.obj reaches 179/10/0

Census 178/11/0 -> 179/10/0 code, data unchanged at 129/0/0.

The residual was two coupled levers, which is why every previous attempt --
roughly 400 measured variants, including all 120 permutations of the local
declarations -- came out worse:

1. Split the unit.flags read-modify-write into a named temp, so the value is
   held in a register across the intervening frame_index store. On its own this
   is not enough; VC7 sinks it back past that store and re-folds it to
   or dword ptr [mem], imm.
2. The object.flags store must come AFTER the unit.flags store. With the object
   store first, VC7 re-folds the unit.flags update every time.

A sweep of all 210 legal orderings of the seven statements finds exactly seven
that are exact; the landed one is object-flags load, clamp, damage SET_FLAG,
unit-flags load-or, frame store, unit-flags store, object-flags store.

Two secondary facts: exactly one of the two dword read-modify-writes gets a
register temp unless both are forced, and forcing the other simply swaps which
one folds; and the eax/edx role swap seen in near misses is a size-driven
allocator preference (or eax,imm32 is five bytes against six for edx) that
resolves once the ordering is right.

Wave gates: /Zs exit 0 with no warnings; contained deletion with a dry run
proving exactly one CL edge; one emission; owner gate pinned to 8cdede3e shows
exactly one changed owner of 220, the intended one; determinism replay identical
across all 220 owners.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Jonas VolmanandClaude Fable 5 committed 2026-08-27 22:33:42 -07:00
1 parent 8cdede3edc
commit 97fc12301b
1 file changed
+5 -3
+5 -3
View File
@@ -4631,6 +4631,7 @@ void unit_place(
if (unit->unit.animation.state==_unit_state_dying)
{
unsigned long object_flags;
unsigned long unit_flags;
long death_frame_index;
struct animation_graph *animation_graph;
struct animation *animation;
@@ -4653,12 +4654,13 @@ void unit_place(
&animation_graph->animations,
unit->object.animation.state.index,
struct animation);
object_flags = unit->object.flags;
death_frame_index = MAX(0, animation->frame_count - 4);
SET_FLAG(unit->object.damage_flags, _object_dead_bit, TRUE);
SET_FLAG(unit->unit.flags, _unit_placed_here_dead_bit, TRUE);
object_flags = unit->object.flags;
unit->object.flags = object_flags | FLAG(_object_cannot_be_garbage_bit);
unit_flags = unit->unit.flags | FLAG(_unit_placed_here_dead_bit);
unit->object.animation.state.frame_index = (short)death_frame_index;
unit->unit.flags = unit_flags;
unit->object.flags = object_flags | FLAG(_object_cannot_be_garbage_bit);
unit->unit.time_of_death = game_time_get();
unit->object.body_vitality = 0.f;
unit->object.shield_vitality = 0.f;