sots-re/tools
alex 1d50f1edda lane Z: the RNG ledger for one strategic turn, measured end to end
We consume 18-22 generator words per turn and model none of them as a count.
All of it is inside StrategyServer::ProcessTurn; OnAllCombatDone_Tail costs 0
on every turn observed; the residual outside the two drivers is exactly 0. The
generator does not move between turns at all, so the interval a standalone has
to reproduce is closed at both ends.

The instrument reads generator STATE, not calls, and that choice paid: the
image has four draw entry points, not three (NextUInt 0x004f7670 is in no
lane's primitive set) plus inlined draws in twelve functions, two reachable
from the turn roots. A primitive-counting hook would have undercounted
silently.

Checked against the save files independently: the turn-6 autosave pair gives
18 words read from the two Sim.RNG blobs, and with twists == 0 that number
never passes through a twist implementation -- so the two instruments do not
share the hidden assumption they could have.

Corrections to combat-done-tail.md, in place:
  * the node-line 0x20000-fleet check runs AFTER the Chance(0.5f) call and
    cannot gate the draw; the expiry test is NodePath::RemainingLife 0x006e2130
    and is now a formula rather than a description
  * StrategyHost::Autosave is ret 8 and returns the std::string* in EAX
  * SNMAllCombatDone IS delivered every End Turn (8 of 8) -- lane K's inference
    was right; the stronger no-encounter reading is narrowed, not closed
  * S+0x8 advances 12-14 times per turn, not twice

Node-line decay still has not fired. The hook reports the distance instead of
the absence: 51 of 53 lines are permanent, the mortal ones are dug ~1/turn by
the Zuul, each ~40 turns from expiry. It stays a labelled hypothesis.
2026-09-08 09:45:06 -04:00
..
cache_functions.py lane X: x86 displacement xref scanner; pin sizeof(ObservedTech) and its append site 2026-09-08 04:44:18 -04:00
dashboard.py dashboard: count addresses.d fragments (was undercounting 615 vs 722), read layouts.json (22 -> 384), fix the layouts denominator and the 'objects' type row 2026-09-08 08:30:46 -04:00
DASHBOARD_README.md dashboard: coverage generator + first render 2026-09-07 17:36:27 -04:00
gen_addresses.py gen_addresses: per-lane fragment dir; duplicate names are a hard error 2026-09-08 05:55:03 -04:00
gen_stream_schema.py lane G: wire-schema channel — layouts.json -> generated stream schema for sots-engine 2026-09-08 06:29:30 -04:00
reva_call.py reva_call.py: HTTP fallback for Ghidra when the MCP link drops; claim VM140 for recapture lane 2026-09-08 02:12:16 -04:00
rng_ledger_report.py lane Z: the RNG ledger for one strategic turn, measured end to end 2026-09-08 09:45:06 -04:00
rtti_map.py lane D: automated struct recovery from the IStreamable serializers 2026-09-08 05:51:37 -04:00
serializers.py lane D: automated struct recovery from the IStreamable serializers 2026-09-08 05:51:37 -04:00
serializers_ghidra.py lane D: automated struct recovery from the IStreamable serializers 2026-09-08 05:51:37 -04:00
serializers_golden.py lane D: automated struct recovery from the IStreamable serializers 2026-09-08 05:51:37 -04:00
streams.py lane G: wire-schema channel — layouts.json -> generated stream schema for sots-engine 2026-09-08 06:29:30 -04:00
strfootprint.py lane S: std::string is 0x1c binary-wide; ObservedTech element fully mapped 2026-09-08 05:09:33 -04:00
x86disp.py lane X: x86 displacement xref scanner; pin sizeof(ObservedTech) and its append site 2026-09-08 04:44:18 -04:00