The boundary ledger says which phase spends a turn's words; this says which call site. Each entry point is detoured with its verified prototype and records __builtin_return_address(0) plus the word cost from left before/after -- two 4-byte reads, no record per draw, since NextFloat alone has 109 call sites. Each draw is tagged with WHICH generator it came from. That is not a detail: the first build counted every Mars::RNG instance in the process and reported 44 words against a bracket of 18. The StrategyClient's generator at +0x134 draws 8 times a turn and must not be in the strategic total. Also hooks EncounterDetect::AssignContacts, lane I's one inlined-draw site in ProcessTurn's closure -- invisible to both a call-graph sweep and to the entry- point detours, so only a boundary hook can see it. It did not fire on this workload, which is consistent with the site sums reconciling exactly.
41 lines
1.9 KiB
Text
41 lines
1.9 KiB
Text
# Lane Z -- the per-turn RNG ledger, TRACE. Copy over C:\SOTS\shim.cfg.
|
|
#
|
|
# Every other hook is off so the log holds nothing but the ledger: six records per End Turn
|
|
# instead of ~40 per player. Read `side.rng.before.words` and `side.rng.after.words` on each
|
|
# record -- the difference is the number of 32-bit words the strategic generator consumed inside
|
|
# that call. Because the hooks nest, subtracting the inner subtotals from the outer one
|
|
# attributes the turn.
|
|
#
|
|
# fpu.sample_turn=off is REQUIRED: the fpu module samples the control word at
|
|
# StrategyServer::ProcessTurn, MinHook allows one hook per target, and this config needs that
|
|
# address for the ledger. With it left on, shim.log records which of the two failed to install.
|
|
hooks=trace
|
|
hook.Shim::SelfTest::Fill=off
|
|
hook.Mars::GlobalConsts::LoadFile=off
|
|
hook.Game::WeaponDictionary::Init=off
|
|
hook.Game::SectionDictionary::SectionDictionary=off
|
|
hook.Game::ServerPlayer::ComputeBudget=off
|
|
hook.Game::TechTree::ProcessResearch=off
|
|
hook.Game::ServerPlayer::OnTechResearched=off
|
|
hook.Game::ServerSystem::ProcessTurn=off
|
|
hook.Game::ServerPlayer::ProcessTurn=off
|
|
hook.Game::StrategyServer::MoveFleet=off
|
|
hook.Game::StrategyServer::ProcessFleetMovement=off
|
|
|
|
hook.Game::StrategyHost::Autosave=trace
|
|
hook.Game::StrategyServer::ProcessTurn=trace
|
|
hook.Game::StrategyServer::OnAllCombatDone_Tail=trace
|
|
hook.Game::StrategyServer::ApplyEncounterResult=trace
|
|
hook.Game::StrategyServer::NodeLineDecay=trace
|
|
hook.Game::StrategyServer::ProcessNodeSpaceTravel=trace
|
|
|
|
fpu.sample_turn=off
|
|
fpu.sample_ticks=off
|
|
|
|
# The generator is 0x9cc bytes and every record carries it twice. Inlining it as hex would make
|
|
# each record ~5 kB of state nobody reads -- the `describe` already reduces it to
|
|
# {left, index, block, words, block_hash}, and the raw bytes are only ever a sha256 line.
|
|
trace.inline_max=64
|
|
trace.path=C:\SOTS\shim.trace.jsonl
|
|
trace.flush=always
|
|
hook.Game::EncounterDetect::AssignContacts=trace
|