Full logic recovered (all player_datum/game_statistics/game_variant fields
mapped, 7 relocations and both datum_get calls match) but January keeps the
conditional fallback code_00097250() call expanded (112B) where our CL
compacts it to 96B -- same optimiser-determinism class as atmospheric_fog.
Recorded in-source next to get_goal_position for a later schedule pass.
Byte-exact (96 bytes / 8 relocations): zeroes game_engine_globals, clears
postgame_state, and when given a variant with an engine type copies it into
global_variant, runs game_engine_variant_cleanup, and points game_engine at
the matching handler table in game_engines[]. Adds the game_engines[] extern
and a forward prototype for game_engine_variant_cleanup (signature inferred
from this call site: takes struct game_variant *). game_engine exact 57 -> 58.
Byte-exact (48 bytes / 3 relocations): returns whether team indicators
should display -- game_engine present, a game_variant flag set, and teams
enabled. Follows the game_engine_has_teams donor shape (if (game_engine)
result = <expr>;) rather than a flat && chain, which reproduces the
January register schedule (has_teams read into the AL result register).
The tested flag is bit 1 of game_variant.flags, which had no name in the
enum; added as _game_variant_unknown1_bit = 1 (honest placeholder, matching
the codebase unused/unknown convention). game_engine exact 56 -> 57.
get_goal_position reconstructs to the exact size (96 bytes) and relocations
(6) but the trailing real_point3d copy has a residual instruction-schedule
difference (January reuses ESI with redundant pointer moves; our builds
schedule tighter through EDX). ~8 source shapes tried. Recorded as an
in-source note at its January-order position for a later typed-local-alias
pass; representative of the getter-tuning tier (man_out, get_starting_
location_rating).
game_engine_statistics_append, game_engine_handle_client_message and
game_engine_handle_server_message: vtable tail-call dispatchers at handler
offsets 0x20/0x24/0x28, byte-exact (32 bytes / 1 relocation each). Total
game_engine exact 53 -> 56.
Each passes a single argument through to the handler, which is what forces
the /Oy- frame pointer that the no-argument dispatchers (e.g. game_ending)
omit. The argument type/count is byte-identical for any single 4-byte value
and is not constrained by any in-tree caller yet; typed as a best-effort
inference (long statistic / void *message).
Complete scenario.obj: _scenario_get_atmospheric_fog is now byte-exact
(816/816 bytes, 38/38 relocations; all 56 section symbols match).
XDK 3911 CL tail-merges the default-sky lookup with the else-branch
scenario_get_sky() lookup, where the January binary keeps them separate.
Around forty barrier-free source shapes, plus TU-context, register-pressure,
branch-order, hoisted-NULL, parameter-type and second-expansion variants,
failed to reproduce the split tails. Two zero-byte _ReadWriteBarrier()
intrinsics do: one in site-1 blocks the tail-merge, one in the else restores
the je jump-thread. Matches the object_shadows.c precedent; full rationale
is in the source comment.