Files
Cesarus85--mjolnir-vr/docs/players_matching_notes.md
T

4.9 KiB

Players.obj matching notes

code_000ab820 powerup expiry

The authentic reconstruction iterates the two player.powerup_durations, decrements active timers, and calls code_000aa560 when a timer expires. A compile-time-dead reference to code_000ab820 retained both private bodies.

  • January and candidate were both 0x70 padded bytes with five identical relocations.
  • The first normalized divergence was the inlined powerup-index test: January emitted the long test edi, edi; the exact standalone code_000aa560 source requires (short)powerup_type and inlined as test di, di.
  • Adding an explicit long outer guard allowed the inner short test to fold, but VC7 expanded code_000ab820 to 0x80 bytes.
  • Calling code_000aa4f0/code_000aa530 from the already-exact public powerup handlers changed their machine code, so those call-form experiments were reverted.

The code_000ab820 foundation was not admitted because it added no exact function credit. Its source and retention experiment may be revisited when players_update_after_game is reconstructed.

players_update_before_game

The dependency-complete action/update loop reconstructs to January's exact 0x6E0 padded size with all 101 relocation identities and addresses aligned. After restoring the proper main_respawn(boolean) declaration, only four normalized instruction bytes differ:

  • January keeps the player pointer in ECX, loads the unit index into EDX, and later forms &iterator in EAX.
  • VC7 instead coalesces the unit index into ECX and forms &iterator in EDX.
  • Passing player->unit_index directly increased the residual to ten bytes.
  • Removing the compiler barrier produced the same worse schedule.

The proven four-byte baseline retains the local player_unit_index and _ReadWriteBarrier(). The function remains dormant and uncredited until its register-allocation tie is resolved.

players_update_after_game

The authentic post-game loop and its expiry dependency reconstruct to January's exact 0x330 padded size with all 52 relocations. The first CFG divergence occurs when forming the scenario BSP-switch block pointer:

  • January emits lea ecx, [eax+0x39C] and keeps the loop index in EDI.
  • VC7 emits a base copy, offset load, and offset add, then keeps the loop index in EBX; this creates a nonuniform register/branch-layout drift through the loop.
  • The historically grounded byte * + offsetof(...) expression compiled identically to the named-field expression and did not improve the residual.

The semantic lift remains uncredited and is not retained in players.c.

code_000a9ff0

The semantic PVS reconstruction has January's exact 0x170 padded size and all 22 relocation identities. Only one instruction-scheduling window differs:

  • January emits lea ecx, [ebp-0x14], stores the activation-call result at [ebp-4], then loads player_data.
  • VC7 stores the result, loads and pushes player_data, and only then forms &iterator; the player_data relocation is therefore at +0x32 instead of January's +0x35.
  • The normalized residual is 11 bytes at offsets 0x2E through 0x39; every instruction after that window matches.
  • An explicit iterator pointer, a result temporary plus compiler barrier, and an aggregate exposing the iterator/result stack adjacency all compiled to the same baseline schedule. Argument-expression and premature-pointer variants either retained that schedule or worsened it.

The function remains dormant and uncredited as a scheduler/lifetime tie.

code_000aa9e0

The independent-pointer reconstruction retains January's exact 0x510 padded size and all 61 relocation identities. Its residual begins with a stack-home and register-allocation difference and expands into a block-layout tie:

  • January homes player, player_unit_index, biped, and source_root_object at [ebp-8], [ebp-0x14], [ebp-0x10], and [ebp-0xC]; VC7 uses a 0x78 frame, omits the source-root home, and maps the other three to [ebp-4], [ebp-0xC], and [ebp-0x14].
  • January keeps the initial biped_get result in ESI before homing it and later uses a stack-homed source-root pointer. VC7 instead homes the biped immediately and keeps the source-root pointer in ESI.
  • Splitting the two-pointer aggregate into independent locals restored the exact 0x510 size after a failed CFG experiment, but did not resolve the opening register allocation and is not retained in production source.
  • Whole-variable and targeted volatile access produced the 0x7C frame but inflated the body to 0x520 and mapped the homes incorrectly.
  • Hoisting/reordering scalar declarations was byte-identical to the best form.
  • Late-label and single-fallback CFG rewrites shortened the body to 0x500; VC7 either placed the fallback block early or over-merged the source paths.

The aggregate baseline remains dormant and uncredited pending a compiler register-allocation/block-layout solution.