lane CR: our code ran instead of ProcessResearch on a real completion; the oracle missed by 16 leaves, all of them OnTechResearched's

Replace mode was tried live on a turn that actually completes a tech, with a
two-process hooks=off oracle established first on that exact (save, procedure,
route). Verdict: game/sim/research stays compared.

What displaced: all 13 tech-tree leaves the turn moves -- 2 from the pass itself
and 11 from the SetResearched cascade -- produced by our code in live game memory,
with the original's ProcessResearch never executing.

What did not: 16 leaves, every one written by ServerPlayer::OnTechResearched.
Five player tech-effect fields (OutMod, ConMod[0..2], ResTNm), one ObservedTech
element, two event records plus EvNxID, and five derived leaves behind them.

Also: ref-turn2 + one End Turn does NOT complete a tech, so every research oracle
before this one was taken on a quiet turn; and a config that names all 27 registered
hooks off and passes check_shim_configs.py still installs six detours, because the
M0 stub and the FPU module's four sampling detours have no hook. key.
This commit is contained in:
alex 2026-09-09 10:05:48 -04:00
parent ea7b771c76
commit 7dcc66bc66
19 changed files with 4760 additions and 0 deletions

View file

@ -249,3 +249,305 @@ OK; `tools/check_shim_configs.py` OK with 27 registered hooks and all four CR co
## 4. Results ## 4. Results
*(added after the runs; nothing above this line is edited)* *(added after the runs; nothing above this line is edited)*
### 4.0 The five runs, in order
All five on **VM145**, held by this lane, each a **fresh process**, `SavedGames` reset to exactly
`turn3-state.sav` before every launch, `C:\SOTS\shimdist-cr\binkw32.dll`
(25,274,723 B, sha256 `d2ad56b32c1b5f6b…`, `BUILD_ID cr-618ccb1-20260909T131556Z`, exports 66/66
identical to the real `binkw32.dll`), one config per run and nothing else changed. Every screen —
main menu, Load-Game chooser, the one-row file list, the **lobby**, the loaded map at "Turn 3", the
post-turn map at "Turn 4" — was verified from a live `qm monitor` screendump before the next click.
No run was driven by sleeping.
| run | config | mode | `research.replace_cascade` | `(Autosave EndTurn).sav` | `(Autosave).sav` |
|---|---|---|---|---|---|
| **C1** | `croff` | `hooks=off` | – | 67,212 `e00eed0c…` | 67,811 `79df5047…` |
| **C2** | `croff` | `hooks=off` | – | 67,212 **`e00eed0c…`** | 67,811 **`79df5047…`** |
| **N** | `crcompare` | compare | off | 67,212 **`e00eed0c…`** | 67,811 **`79df5047…`** |
| **R0** | `crreplace0` | **replace** | off | 67,212 `e00eed0c…` | 67,511 **`6b51db99…`** |
| **R1** | `crreplace1` | **replace** | **on** | 67,212 `e00eed0c…` | 67,537 **`8a4309ee…`** |
`(Autosave EndTurn).sav` is the *pre*-turn resave and is identical in all five runs, as it must be —
nothing has run yet when it is written. The verdict is carried entirely by `(Autosave).sav`.
### 4.1 P0 held: the oracle
**C1 and C2 agree byte-for-byte in two fresh processes.** The pair, in the standing
`certified-pairs.md` format:
| input | procedure | route | `(Autosave EndTurn)` | `(Autosave)` | processes | evidence |
|---|---|---|---|---|---:|---|
| `turn3-state.sav` `978041ac…` | one End Turn | **load** | `e00eed0c…` | `79df5047…` | **3** | lane CR ×2 `hooks=off`, ×1 compare-instrumented |
**Masks that must be on the line.** Measured, not assumed —
`state_checksum.py turn3-state.sav <(Autosave EndTurn)>` gives **exactly 5 leaves**:
`/Summary/Checksum` and `Player.Status 4 → 0` on each of the four live players (16 `re`,
32 `Fane Lao`, 496 and 512 `Singularity`). **There is no `/CD[1]/NPrvVa` term on this state** —
`CD[1]`'s diplomacy block is early-game and the leaf does not move — so the `--mask resave` rule
holds here in the form the docs originally stated, and the lane BQ exception does not apply.
**Exposure facts next to the hashes** (certified-pairs standing rule 4): §1.3's table — no player
with an AI client enters the turn with `ResTNm == ''`; `NumDes` does not move; the two ships that
complete join existing fleets; the four factions at 528–576 carry the empty-`ResTNm` signature
inertly (`Status 0`, no client). The turn does create fleets (`Flt[50]`, `Flt[1808]`) and retire one
(`Flt[1776]`) — that is a fleet-assignment shape, and it agreed anyway. **Which is the point of
rule 26(c)'s retraction: the screen said "likely fine" and only the two-process control decided it.**
### 4.2 P3 held: the instrument is neutral, and it counts the completion itself
Run **N** reproduced the control's two hashes exactly, so rule 19 is satisfied on *this* save and
*this* route and everything below is read from runs that passed their own check.
`tracecmp verify/traces/cr-N.jsonl.gz`: **3 calls, 3 compared, 0 diverged, exit 0**, coverage verdict
`partial`, 8 unmodelled notes — and the undeclared-write set is **exactly the six spans predicted**:
```
player+0x10c:3 player+0x110:3 player+0x114:3 player+0x124:3 player+0x294:4 tree_header+0x20:1
```
The hook's own per-call line, which is the instrument saying a completion fired rather than the save
being asked to imply it:
```
research: mode=compare steps=1 completions=1 overbudget=1166 cascade_possible=1 ok=1
cascade_completions=1 unlocked=3 otch_appends=1 roll_draws=0 failures=0 depth=0
research: mode=compare steps=1 completions=0 … (×2, all zero)
```
**A correction to the campaign's read of the detour count, and it goes the other way from the
brief's warning.** My config names all **27** registered template hooks and
`check_shim_configs.py` passes it as `# exhaustive` — and the shim still installed **six** detours,
not one:
| detour | source | named by a `hook.` key? |
|---|---|---|
| `Mars::Application::Initialize` | the M0 asm stub, installed unconditionally whenever `hooks != off` | **no** |
| `Game::TechTree::ProcessResearch` | the one template hook | yes |
| `StrategyClient::EndTurn`, `StrategyServer::BeginProcessTurn`, `StrategyServer::ProcessTurn`, `DemoApp::OnTick` | the **FPU-force module**, which installs four *sampling* detours by default (`fpu: module init … force=off value=0x0000 sample_ticks=on`, `sample_turn=on`) | **no** |
`Shim::SelfTest::Fill` additionally emits one `trace` record at startup; it is an in-shim self-test,
not a detour on the game. So **`# exhaustive` is exhaustive over the template-hook set only**, and
`tools/check_shim_configs.py` cannot see the other five. It was the *neutrality check* (N identical
to C1/C2), not the config check, that made this run safe — which is worth saying plainly, because a
lane reading "exhaustive, therefore one detour" would be wrong by five.
For the record, `fpu_cw = 0x027f` (53-bit, round-to-nearest) in every CR run.
### 4.3 P1 and P2 held exactly, on the LOAD route
The load route reproduced the continuation's turn-4 call in every particular — allocations, the
completion, the unlock set, the arithmetic. From `cr-N.jsonl.gz` (compare) and confirmed identically
in `cr-R1.jsonl.gz` (replace):
| call | owner | species | alloc | what moved |
|---|---|---|---|---|
| 1 | `Player[32 "Fane Lao"]` | 2 | `{144, 2898}` | the completion (below) |
| 2 | `Player[496 "Singularity"]` | 0 | `{90, 0}` | **nothing at all** |
| 3 | `Player[512 "Singularity"]` | 2 | `{9, 0}` | **nothing at all** |
Call 1, node **144 `IND_Waldo`**: `state 3 → 4`, `progress 5768 → 7500`, `turn_researched −1 → 4`,
`order −1 → 22`; `overbudget 0 → 1166`; three nodes unlocked —
**132 `IND_OrbFound` @ 10000**, **136 `IND_RefCoat` @ 16000**, **142 `IND_TrkStl` @ 8000**, each
`state 0 → 2`, `cost_rp INT_MAX → …`, `turn_available −1 → 4`; `events.next_id 5 → 7`;
`observed_techs 440 → 484 bytes`.
P2's hand arithmetic is confirmed to the unit: `cost 5000`, `lo 2500`, `hi 7500`,
`spent = min(2898, 1732) = 1732`, `progress = 7500` **exactly on the ceiling**,
`overbudget = 2898 − 1732 = 1166`; `progress < hi` false so **no draw**; `ratio = 1.5`, not below
`0.800000011920929`, so **`flag` unchanged**. The `rng` region **did not move on any of the three
calls** in any run.
That last fact is a coverage hole, not a success — see §4.6.
### 4.4 P4 and P5 held: replace diverges, and the cascade closes exactly eleven leaves
`state_checksum.py cr-oracle-autosave.sav <replace autosave>`:
| run | diverging leaves | file size |
|---|---:|---|
| **R0** — replace, cascade **off** (the shipped behaviour) | **27** | 67,511 B |
| **R1** — replace, cascade **on** | **16** | 67,537 B |
| (the turn itself, `turn3-state` → oracle, for scale) | 128 | – |
**The eleven leaves the cascade closes — R0 has them, R1 does not.** All eleven are `TechTree`:
```
Player[32]/TechTree/St[94] TResCost[94] TUnlck[94] (node 132 IND_OrbFound, 10000)
Player[32]/TechTree/St[98] TResCost[98] TUnlck[98] (node 136 IND_RefCoat, 16000)
Player[32]/TechTree/St[104] TResCost[104] TUnlck[104] (node 142 IND_TrkStl, 8000)
Player[32]/TechTree/TAcq[106] TiAcq[106] (node 144, turn 4 / order 22)
```
The tree is serialised as parallel arrays indexed by **tree slot**, not tech id — slots 94/98/104/106
are tech ids 132/136/142/144 — and the pass's own two words, `St[106] 3 → 4` and
`TResDone[106] 5768 → 7500`, are correct in **both** replace runs because
`ProcessResearchTurn` writes them without the cascade. So of the **13 tech-tree leaves this turn
moves, our code produced all 13 in live memory with the original's `ProcessResearch` never
executing** — 2 from the pass, 11 from `SetResearched`.
**One prediction I cannot test and must retract as written.** P4 item 2 said the completion-order
counter would be "left at 22" in R0. `TechTree+0x20` **is not a save leaf** — the counter's value
surfaces only through the per-node `TiAcq` stamp — so the oracle cannot see it either way. What is
observable is the trace: R1's only guard hit is `tree_header+0x20:1` (ours writing 22 → 23, the same
byte the original moves in compare mode) and R0 has **0 undeclared writes in 0 calls**. The counter
matters for the *next* completion, not for this save.
### 4.5 P6 held: the residual is `ServerPlayer::OnTechResearched`, entirely
R1's **16** leaves, every one of them named, with nothing left over:
| leaf | what it is | modelled by `ours`? |
|---|---|---|
| `Player[32]/OutMod` `1.25 → 1.1` | a tech effect | no — B2's milestone |
| `Player[32]/ConMod[0..2]` `0.9 → 1.0` (×3) | tech effects | no — B2's milestone |
| `Player[32]/Events/EvNxID` `7 → 5` | the two events not posted | decision modelled, **write is compare-only** |
| `…/Events/.[EvTurn=4]/Events/.[EvEID=5]`, `.[EvEID=6]` `only-in-A` | the two event records | text comes from the game's string table |
| `…/Events/.[EvTurn=4]/Events/.[0]` `3 → 1` | that turn's event count | ditto |
| `Player[32]/otch/.[11]` `only-in-A`, `otch/.[0]` `11 → 10` | the `ObservedTech` element | append **decided** (`otch_appends=1`), element not constructed |
| `Player[32]/ResTNm` `'' → 'IND_Waldo'` | `ResT` never cleared | inside the callback |
| `Player[32]/BnkPr`, `BnkEl` | bankruptcy projection | **downstream of `OutMod`** |
| `Sys[288 "Ke'Dolarra"]/RepCur`, `RepMax` `421640 → 371040` | repair capacity | **downstream of `ConMod`** |
| `/Summary/Checksum` | derived | derived |
So the residual decomposes into **5 primary player fields** (`OutMod`, `ConMod[0..2]`, `ResTNm`),
**1 `ObservedTech` element**, **2 event records + their id counter**, and **5 derived leaves** that
follow from those. Every single one is written by `ServerPlayer::OnTechResearched`, none of them by
`TechTree::ProcessResearch` or by `SetResearched`.
That also closes the loop with §4.2's guard: the four `player` spans the compare reported as
undeclared (`+0x10c`, `+0x110`, `+0x114`, `+0x124`, all three bytes wide — float writes whose top
byte did not change) plus `+0x294` (`ResT`, four bytes) are **five** writes, and the save shows
**five** primary player fields. The guard was reporting exactly what the oracle later billed us for.
**The input class that breaks it is a completion, and only a completion.** Both replace runs are
byte-perfect on the two null calls and on every other leaf of the 128 the turn moves. A replace run
over a turn where research does not complete would be byte-identical — and would prove nothing
(rule 1), which is why this lane refused to run it on `ref-turn2`.
### 4.6 Coverage, reported as loudly as the result (rules 15 and 23)
* **1 completion. 1 distinct tech (144 `IND_Waldo`). 3 unlocked nodes. 3 calls.**
* **2 of the 3 calls allocate zero points and write nothing at all**, in any mode. Their entire
contribution to "3 calls, 0 diverged" is that two null calls stayed null.
* **1 of 4 tech trees is exercised.** Player 16's tree is never processed (`ResTNm == ''`); players
496 and 512 are the null calls.
* **The RNG region did not move on any call in any run.** The spend cap bound exactly, so the
odds/roll branch was skipped, and `roll_pending_in` was false on the completing call, so
`RollResearchEvent` drew nothing (`roll_draws=0`). **`region:rng` — the single strongest check in
this hook's compare — compared "unchanged against unchanged" on this workload and established
nothing.** The generator parity evidence for this module is entirely lane U's and lane V's,
on other turns.
* **Branches that did not execute here:** the Zuul double roll (species 2, not 5); the
completed-early flag (`ratio 1.5`); the over-budget notification (`flag` already 2 from turn 3);
`RollResearchEvent`'s draw and, behind it, the plague / AI-rebellion paths; `SetResearched`'s
zero-cost recursion; the `def+0xb0` `NoAutoAvailable` skip; an empty prerequisite group; a
re-observed tech (the dedup's negative case); and the decay sweep, which ran over every node and
**changed nothing** because no other `Available` node had non-zero progress.
* **The event model is count-only by construction** and stayed compare-only in replace mode by
design; the two missing records are two of the sixteen residual leaves.
* **`TechTree::Cost` is the original's.** `ours` calls the game's read-only `Cost` for every cost it
needs, in both modes. The effective-cost formula is **not** displaced, and any claim about this
module inherits that dependency.
### 4.7 Verdict
**No. `game/sim/research` does not move from `compared` to `replaced`.**
The bar is "our code ran instead of the original's **and a byte-level oracle held afterwards**". Our
code did run instead — `mode=replace`, `completions=1`, `unlocked=3`, the original's
`ProcessResearch` never executed, and the game finished the turn and wrote a save. The oracle did
**not** hold: 16 leaves in the best configuration. There is no qualified reading that rescues it,
because the failure is not a rounding residual — it is a set of writes nobody has implemented.
What the lane did establish, and it is worth more than the rung would have been:
1. **The research pass and the entire `SetResearched` cascade are displaceable and were displaced.**
All 13 tech-tree leaves the turn moves were produced by our code in live game memory, on a turn
with a real completion and a real three-node unlock cascade — which is a strictly stronger
statement than the 35 compared calls the board already carried, because in a compare the
original's code still did the work.
2. **The blocking boundary is named and measured, not guessed:** `ServerPlayer::OnTechResearched`,
5 player fields + 1 `ObservedTech` element + 2 events, and 5 derived leaves behind them.
`ProcessResearch` **cannot** reach `replaced` on any workload containing a completion until
`OnTechResearched` is displaced — and that is B2's milestone and its own `compared` board row,
not a defect in the research model.
3. **A new certified pair** on a turn that exercises the completion path, which the campaign did not
have: `ref-turn2` + one End Turn is a *quiet* turn for research, and every oracle the module had
been checked against was that one.
The cheapest route to the rung, now that the boundary is priced: implement the ~90-field
`ApplyTechEffect` write-back live (B2 already has `game/effects/tech_effects` host-tested), construct
the `ObservedTech` element, and decide what to do about the two event records — whose *text* comes
from the game's string table and therefore cannot be produced clean-room at all. **The event text is
a hard stop for a byte-identical oracle on any completion turn**, and that should be settled as a
policy question (call the game's `PostEvent`, and accept the `ComputeBudget`-shaped QUALIFIED
caveat) before anyone spends another lane on it.
---
## 5. Proposed board rows
**I have not edited `campaign/board.md`.** I *have* added the certified pair to
`verify/results/saves/certified-pairs.md`, which the brief pointed at as the standing format and
whose four standing rules for adding a row are all satisfied (two fresh `hooks=off` processes; the
control run before anything was read from an instrumented run; not an extension of an existing pair
but its own agreement; exposure facts recorded beside the hashes).
### 5.1 `tools/displacement.py` — the rung does NOT move
The verdict is **no**, so `"compared"` stays. What I do propose is replacing the evidence and caveat
strings, which currently understate what is known and do not name the gate:
```python
("TechTree::ProcessResearch + unlock cascade", "compared",
"35 calls across 3 workloads, 0 divergences, tracecmp exit 0; advance prediction held on a "
"changed workload (unlock costs no earlier report contained); REPLACE ATTEMPTED live (lane "
"CR): ours ran instead of the original on a real completion and produced all 13 tech-tree "
"leaves the turn moves, but the save oracle missed by 16 leaves",
"compare only. The replace attempt failed on ServerPlayer::OnTechResearched, not on the "
"research model: 5 player tech-effect fields, 1 ObservedTech element and 2 event records, "
"plus 5 derived leaves. Gated on B2. Thin: 1 completion, 1 tech, 2 of 3 calls allocate zero "
"points, and the RNG region did not move at all on the replace workload"),
```
### 5.2 Board rows to add
| row | class | status | conf | cov | date | evidence |
|---|---|---|---|---|---|---|
| **`ProcessResearch` replace: our code ran instead of the original's, and the oracle missed by 16 leaves — all of them `OnTechResearched`'s** | phase2 | verified | high | 95% | 2026-09-09 | **Lane CR, VM145**, `findings/subsystems/research-replace.md`. Predictions committed before the build (`sots-re` 4b3cc82); engine `wip/cr` 618ccb1 adds `research.replace_cascade=on\|off` (default off) so the shipped and extended behaviours differ by **a config line, not a binary**. New certified pair `turn3-state.sav` → one End Turn, **load** route, `e00eed0c…`/`79df5047…`, 2 `hooks=off` processes + 1 compare. Compare run **3/3/0 exit 0** and byte-identical to the control (rule 19 satisfied), undeclared writes exactly the 6 predicted spans. **Replace, cascade on: 16 diverging leaves; cascade off: 27.** The 11-leaf delta is the whole `SetResearched` cascade and it is **ours**; with the pass's own 2 words that is **13 of 13 tech-tree leaves the turn moves, produced live by our code**. The 16 residual leaves are `OutMod`, `ConMod[0..2]`, `ResTNm`, one `ObservedTech` element, two event records + `EvNxID`, and 5 derived. **Verdict: stays `compared`.** |
| **`ref-turn2` + one End Turn does NOT exercise a research completion** | verify | verified | high | 100% | 2026-09-09 | Lane CR. The campaign's most-reproduced oracle is a **quiet turn for the completion path**: `unlock-b3-t1.md` reports `0 undeclared write(s) in 0 call(s)` and `unlock-shim.log`'s first three lines read `completions=0`. It *is* a real workload for the pass (one RNG word, `flag 1 → 2`, one over-budget event) — but a replace-mode oracle taken there would be rule 1's green verdict on a hook comparing nothing. The completing turn is the **next** one, from `turn3-state.sav`. |
| **`# exhaustive` is exhaustive over the 27 template hooks only — six detours are installed, not one** | phase2 | verified | high | 100% | 2026-09-09 | Lane CR. A config naming all 27 registered hooks `off` except one, passing `tools/check_shim_configs.py`, still installs **6** detours: the M0 `Application::Initialize` asm stub (unconditional whenever `hooks != off`) and the **FPU-force module's four sampling detours** (`force=off value=0x0000 sample_ticks=on sample_turn=on`, on by default). `check_shim_configs.py` cannot see either group — no `hook.` key names them. What made lane CR's runs safe was the **neutrality check** (compare run byte-identical to two `hooks=off` controls), not the config check. A lane reading "exhaustive, therefore one detour" is wrong by five. |
| **A replace of `ProcessResearch` is gated on `ServerPlayer::OnTechResearched`, and partly on a policy question** | phase2 | open | high | – | 2026-09-09 | Lane CR. To reach `replaced`, three things are needed: the ~90-field tech-effect write-back applied live (B2 has `game/effects/tech_effects` host-tested), the `ObservedTech` element constructed (`ours` already decides the append), and the two research event **records** written. The third is not an implementation gap: their `EvDsc`/`EvMsg` text comes from the game's string table, which the engine must not carry, so a byte-identical oracle on any completion turn requires calling the game's own `PostEvent` and accepting a `ComputeBudget`-shaped **QUALIFIED** `replaced`. Settle that before spending a lane. |
### 5.3 Artefacts
| what | where |
|---|---|
| predictions commit (before the build) | `sots-re` `4b3cc82` |
| engine change | `sots-engine` worktree `wip/cr`, `618ccb1` — `research.replace_cascade`, a mode-independent completion counter, four `shim.cfg.cr*` configs |
| oracle + replace saves | `verify/results/saves/cr/cr-{oracle-endturn,oracle-autosave,replace0-autosave,replace1-autosave}.sav` |
| traces | `verify/traces/cr-{N,R0,R1}.jsonl.gz` |
| `tracecmp` reports | `verify/results/compare/cr-{compare,replace0,replace1}.{md,json}` |
| shim logs (the per-call counters) | `verify/results/shim/cr/cr-{N,R0,R1}.log` |
| certified pair | `verify/results/saves/certified-pairs.md`, row 4 |
No `ghidra/addresses.d/cr.json`: this lane read no new address. No game data, save, disassembly or
`FUN_xxxxxxxx` name reached `sots-engine`; `tools/clean_room_check.sh` OK.
### 5.4 VM145 released
Held for this lane only; **VM140 untouched**. Restored and verified byte-for-byte to as-found:
```
binkw32.dll 15,527,327 B 903527F4A698EEA9FBE25F3A6236657C7D8348F994EEF394696F187E5E554B97 (= shimdist-recap)
shim.cfg 0AE410CC72FE155837D711C78543E14B1F5743310CD023298EB1E5BBD5457E71 (= shimdist-recap\shim.cfg.recaptrace)
SavedGames the same 9 files, every size and sha256 identical to the as-found survey
game not running (as found)
```
Left behind: `C:\SOTS\shimdist-cr\`, `C:\SOTS\ui\cr\` (the input save, the four run outputs and the
restore set) and `C:\SOTS\ui\cr{deploy,click,grab,snap,restore,find}.ps1`. `click_helper.ps1` is
unmodified. **One thing not restored:** my deploy helper *deletes* `C:\SOTS\shim.log` rather than
rotating it to `.prev` the way lane BQ's does, so whatever log was there when I took the guest is
gone. Logs are not simulation state and no measurement depends on it, but the next lane should
rotate rather than delete.

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,28 @@
## tracecmp report: N.trace.jsonl
- build: cr-618ccb1-20260909T131556Z started: 2026-09-09T13:33:54Z inline_max: 256
- calls: 4 compared: 3 diverged: 0 invalid records: 0 warnings: 0
- coverage: 3 guarded call(s), 6 undeclared write(s) in 1 call(s); 0 hook(s) unstated, 0 contradicted
| hook | calls | modes | compared | diverged | errors |
|---|---|---|---|---|---|
| Game::TechTree::ProcessResearch | 3 | compare:3 | 3 | 0 | 0 |
| Shim::SelfTest::Fill | 1 | trace:1 | 0 | 0 | 0 |
### coverage
| hook | verdict | compared regions | guards | undeclared writes | unmodelled |
|---|---|---|---|---|---|
| Game::TechTree::ProcessResearch | partial | events, node[0], node[105], node[106], node[107], node[108], +271 | player, tree_header | 6 in 1 call(s) | 8 |
| Shim::SelfTest::Fill | complete | buf | - | not watched | 0 |
#### Game::TechTree::ProcessResearch — not checked by this run
- (medium) posts EVENT_RESEARCH_OVERBUDGET on the owner's EventStorage: ours reproduces the decision and the id sequence, so region:events compares next_id, but the composed EvDsc/EvMsg text is not reproduced and no region can see it — text comes from the game's string table, which the engine must not carry; ours posts into its own EventStorage and writes only the counts into the scratch copy, so no live byte moves and replace mode posts nothing at all [region:events]
- (low) composes EVENT_TECHS_UNLOCKED's message from the unlocked techs' names — the trigger and the list are modelled (SetResearched's availability sweep plus the tail collector, both read off the instruction stream), so region:events compares next_id; the names come from the game's string table, so the message is composed from node indices instead and is not the game's text [region:events]
- (high) TechTree::SetResearched in REPLACE mode: only its TechTree half runs, and only when research.replace_cascade=on — with the flag OFF (the default) nothing of the cascade runs, so a replace run leaves the completed node unstamped and no tech unlocked. With it ON, the four TechNode words (costRP, turnAvailable, turnResearched, order) and the tree's completion-order counter are written live, and the ServerPlayer half is still not: no event is posted, no ObservedTech element is appended and no tech effect is applied. Neither setting is a full displacement of the completion path; the pair measures where the boundary is [guard:player, guard:tree_header]
- (high) ServerPlayer::OnTechResearched's tech effects: the ~90 hard-coded ServerPlayer field writes, the plague-cure masks, the design-option bitmasks and the species tech flags — B2's milestone. `ours` models only the two parts of the callback this hook's regions can see -- the observed-tech append and the RNG word RollResearchEvent draws before its branch (one word on a missed roll, two on a fired plague roll) -- and the rest is what the player guard reports [guard:player]
- (high) the research-event branch RollResearchEvent takes when its roll beats the odds (ServerPlayer::OnResearchRollSucceeded: the plague and AI-rebellion event paths) — RollResearchEvent draws one NextFloat unconditionally and that draw IS modelled -- but that is only the cost of REACHING the branch. A FIRED roll costs one or two words: the plague path draws a SECOND word (NextInt) to pick an owned system and posts EVENT_PLAGUE_OUTBREAK, while the rebellion path allocates an AIRebellion at ServerPlayer+0x3b8 and CANCELS the current research (no further draw). The branch is entered only for the plague and AI-rebellion tech families, whose odds are 0 everywhere else, and it has never been observed firing in three sessions -- which is why every earlier note in this repo said 'exactly one NextFloat' and nothing caught it. If it is ever entered, region:rng is the check [region:rng]
- (medium) constructs the ObservedTech element it appends to ServerPlayer+0x274 — `ours` models the append DECISION -- RecordObservedTech de-duplicates by tech name, so it decides whether the vector grows -- and moves the scratch header's byte span by one 0x2c element per append. The element's own fields (turn_first, turn_last, detected, the name string, `with`) are not built, and no region can see them [region:observed_techs]
- (low) the tree's completion-order counter (TechTree+0x20) is read pre-call, not modelled as a region — the per-node `order` word IS compared, and it is stamped from a counter `ours` seeds from the pre-call read and advances itself; the counter's own final value is only seen by the tree_header guard [guard:tree_header]
- (low) writes a completion line to the game log — log text is not simulation state
- guard hits in compare mode: player+0x10c:3, player+0x110:3, player+0x114:3, player+0x124:3, player+0x294:4, tree_header+0x20:1

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,27 @@
## tracecmp report: R0.trace.jsonl
- build: cr-618ccb1-20260909T131556Z started: 2026-09-09T13:51:31Z inline_max: 256
- calls: 4 compared: 0 diverged: 0 invalid records: 0 warnings: 0
- coverage: 3 guarded call(s), 0 undeclared write(s) in 0 call(s); 0 hook(s) unstated, 0 contradicted
| hook | calls | modes | compared | diverged | errors |
|---|---|---|---|---|---|
| Game::TechTree::ProcessResearch | 3 | replace:3 | 0 | 0 | 0 |
| Shim::SelfTest::Fill | 1 | trace:1 | 0 | 0 | 0 |
### coverage
| hook | verdict | compared regions | guards | undeclared writes | unmodelled |
|---|---|---|---|---|---|
| Game::TechTree::ProcessResearch | partial | events, node[0], node[105], node[106], node[107], node[108], +271 | player, tree_header | 0 | 8 |
| Shim::SelfTest::Fill | complete | buf | - | not watched | 0 |
#### Game::TechTree::ProcessResearch — not checked by this run
- (medium) posts EVENT_RESEARCH_OVERBUDGET on the owner's EventStorage: ours reproduces the decision and the id sequence, so region:events compares next_id, but the composed EvDsc/EvMsg text is not reproduced and no region can see it — text comes from the game's string table, which the engine must not carry; ours posts into its own EventStorage and writes only the counts into the scratch copy, so no live byte moves and replace mode posts nothing at all [region:events]
- (low) composes EVENT_TECHS_UNLOCKED's message from the unlocked techs' names — the trigger and the list are modelled (SetResearched's availability sweep plus the tail collector, both read off the instruction stream), so region:events compares next_id; the names come from the game's string table, so the message is composed from node indices instead and is not the game's text [region:events]
- (high) TechTree::SetResearched in REPLACE mode: only its TechTree half runs, and only when research.replace_cascade=on — with the flag OFF (the default) nothing of the cascade runs, so a replace run leaves the completed node unstamped and no tech unlocked. With it ON, the four TechNode words (costRP, turnAvailable, turnResearched, order) and the tree's completion-order counter are written live, and the ServerPlayer half is still not: no event is posted, no ObservedTech element is appended and no tech effect is applied. Neither setting is a full displacement of the completion path; the pair measures where the boundary is [guard:player, guard:tree_header]
- (high) ServerPlayer::OnTechResearched's tech effects: the ~90 hard-coded ServerPlayer field writes, the plague-cure masks, the design-option bitmasks and the species tech flags — B2's milestone. `ours` models only the two parts of the callback this hook's regions can see -- the observed-tech append and the RNG word RollResearchEvent draws before its branch (one word on a missed roll, two on a fired plague roll) -- and the rest is what the player guard reports [guard:player]
- (high) the research-event branch RollResearchEvent takes when its roll beats the odds (ServerPlayer::OnResearchRollSucceeded: the plague and AI-rebellion event paths) — RollResearchEvent draws one NextFloat unconditionally and that draw IS modelled -- but that is only the cost of REACHING the branch. A FIRED roll costs one or two words: the plague path draws a SECOND word (NextInt) to pick an owned system and posts EVENT_PLAGUE_OUTBREAK, while the rebellion path allocates an AIRebellion at ServerPlayer+0x3b8 and CANCELS the current research (no further draw). The branch is entered only for the plague and AI-rebellion tech families, whose odds are 0 everywhere else, and it has never been observed firing in three sessions -- which is why every earlier note in this repo said 'exactly one NextFloat' and nothing caught it. If it is ever entered, region:rng is the check [region:rng]
- (medium) constructs the ObservedTech element it appends to ServerPlayer+0x274 — `ours` models the append DECISION -- RecordObservedTech de-duplicates by tech name, so it decides whether the vector grows -- and moves the scratch header's byte span by one 0x2c element per append. The element's own fields (turn_first, turn_last, detected, the name string, `with`) are not built, and no region can see them [region:observed_techs]
- (low) the tree's completion-order counter (TechTree+0x20) is read pre-call, not modelled as a region — the per-node `order` word IS compared, and it is stamped from a counter `ours` seeds from the pre-call read and advances itself; the counter's own final value is only seen by the tree_header guard [guard:tree_header]
- (low) writes a completion line to the game log — log text is not simulation state

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,28 @@
## tracecmp report: R1.trace.jsonl
- build: cr-618ccb1-20260909T131556Z started: 2026-09-09T13:42:14Z inline_max: 256
- calls: 4 compared: 0 diverged: 0 invalid records: 0 warnings: 0
- coverage: 3 guarded call(s), 1 undeclared write(s) in 1 call(s); 0 hook(s) unstated, 0 contradicted
| hook | calls | modes | compared | diverged | errors |
|---|---|---|---|---|---|
| Game::TechTree::ProcessResearch | 3 | replace:3 | 0 | 0 | 0 |
| Shim::SelfTest::Fill | 1 | trace:1 | 0 | 0 | 0 |
### coverage
| hook | verdict | compared regions | guards | undeclared writes | unmodelled |
|---|---|---|---|---|---|
| Game::TechTree::ProcessResearch | partial | events, node[0], node[105], node[106], node[107], node[108], +271 | player, tree_header | 1 in 1 call(s) | 8 |
| Shim::SelfTest::Fill | complete | buf | - | not watched | 0 |
#### Game::TechTree::ProcessResearch — not checked by this run
- (medium) posts EVENT_RESEARCH_OVERBUDGET on the owner's EventStorage: ours reproduces the decision and the id sequence, so region:events compares next_id, but the composed EvDsc/EvMsg text is not reproduced and no region can see it — text comes from the game's string table, which the engine must not carry; ours posts into its own EventStorage and writes only the counts into the scratch copy, so no live byte moves and replace mode posts nothing at all [region:events]
- (low) composes EVENT_TECHS_UNLOCKED's message from the unlocked techs' names — the trigger and the list are modelled (SetResearched's availability sweep plus the tail collector, both read off the instruction stream), so region:events compares next_id; the names come from the game's string table, so the message is composed from node indices instead and is not the game's text [region:events]
- (high) TechTree::SetResearched in REPLACE mode: only its TechTree half runs, and only when research.replace_cascade=on — with the flag OFF (the default) nothing of the cascade runs, so a replace run leaves the completed node unstamped and no tech unlocked. With it ON, the four TechNode words (costRP, turnAvailable, turnResearched, order) and the tree's completion-order counter are written live, and the ServerPlayer half is still not: no event is posted, no ObservedTech element is appended and no tech effect is applied. Neither setting is a full displacement of the completion path; the pair measures where the boundary is [guard:player, guard:tree_header]
- (high) ServerPlayer::OnTechResearched's tech effects: the ~90 hard-coded ServerPlayer field writes, the plague-cure masks, the design-option bitmasks and the species tech flags — B2's milestone. `ours` models only the two parts of the callback this hook's regions can see -- the observed-tech append and the RNG word RollResearchEvent draws before its branch (one word on a missed roll, two on a fired plague roll) -- and the rest is what the player guard reports [guard:player]
- (high) the research-event branch RollResearchEvent takes when its roll beats the odds (ServerPlayer::OnResearchRollSucceeded: the plague and AI-rebellion event paths) — RollResearchEvent draws one NextFloat unconditionally and that draw IS modelled -- but that is only the cost of REACHING the branch. A FIRED roll costs one or two words: the plague path draws a SECOND word (NextInt) to pick an owned system and posts EVENT_PLAGUE_OUTBREAK, while the rebellion path allocates an AIRebellion at ServerPlayer+0x3b8 and CANCELS the current research (no further draw). The branch is entered only for the plague and AI-rebellion tech families, whose odds are 0 everywhere else, and it has never been observed firing in three sessions -- which is why every earlier note in this repo said 'exactly one NextFloat' and nothing caught it. If it is ever entered, region:rng is the check [region:rng]
- (medium) constructs the ObservedTech element it appends to ServerPlayer+0x274 — `ours` models the append DECISION -- RecordObservedTech de-duplicates by tech name, so it decides whether the vector grows -- and moves the scratch header's byte span by one 0x2c element per append. The element's own fields (turn_first, turn_last, detected, the name string, `with`) are not built, and no region can see them [region:observed_techs]
- (low) the tree's completion-order counter (TechTree+0x20) is read pre-call, not modelled as a region — the per-node `order` word IS compared, and it is stamped from a counter `ours` seeds from the pre-call read and advances itself; the counter's own final value is only seen by the tree_header guard [guard:tree_header]
- (low) writes a completion line to the game log — log text is not simulation state
- guard hits in replace mode: tree_header+0x20:1

View file

@ -20,6 +20,7 @@ those columns is an observation, not a certification.
| `ref-turn2.sav` `ab4ac2d7…` | one End Turn | load | `bb4fd9ac…` | `978041ac…` | 5 + 1 | runs A–E; reproduced by lane H after everything changed | | `ref-turn2.sav` `ab4ac2d7…` | one End Turn | load | `bb4fd9ac…` | `978041ac…` | 5 + 1 | runs A–E; reproduced by lane H after everything changed |
| `ar-turn37-816raiders.sav` `b6f4e05f…` | End Turn, **auto-resolve peacefully**, End Turn | load | `15b99255…` | `7a8b3d5e…` | **4** | lane AR ×3 `hooks=off`, lane BS ×1 instrumented | | `ar-turn37-816raiders.sav` `b6f4e05f…` | End Turn, **auto-resolve peacefully**, End Turn | load | `15b99255…` | `7a8b3d5e…` | **4** | lane AR ×3 `hooks=off`, lane BS ×1 instrumented |
| `ar-oracle-A-pre.sav` `15b99255…` | one End Turn | **load** | `33e30092…` | `4c356f59…` | **3** | lane BQ ×2 `hooks=off`, lane BS ×1 instrumented | | `ar-oracle-A-pre.sav` `15b99255…` | one End Turn | **load** | `33e30092…` | `4c356f59…` | **3** | lane BQ ×2 `hooks=off`, lane BS ×1 instrumented |
| `turn3-state.sav` `978041ac…` | one End Turn | **load** | `e00eed0c…` | `79df5047…` | **3** | lane CR ×2 `hooks=off`, ×1 compare-instrumented |
**The second and third rows are the same lineage and they do not agree with each other.** Row 2's **The second and third rows are the same lineage and they do not agree with each other.** Row 2's
second turn reached by continuation gives `7a8b3d5e…`; the identical turn reached by *loading* row 2's second turn reached by continuation gives `7a8b3d5e…`; the identical turn reached by *loading* row 2's
@ -29,6 +30,22 @@ boundary, and it is why the route column exists.
**Row 3 is the standalone's first trade-raid pair** — one End Turn, no encounter, four raid rolls at **Row 3 is the standalone's first trade-raid pair** — one End Turn, no encounter, four raid rolls at
one word each. one word each.
**Row 4 is the first pair on a turn that completes a research tech** (lane CR, 2026-09-09).
`turn3-state.sav` is the *output* of row 1 — the `(Autosave).sav` that `ref-turn2` + one End Turn
produces — and the turn it starts is the one where `Player[32 "Fane Lao"]` completes tech 144
`IND_Waldo` and the cascade unlocks three nodes. Row 1's own turn does **not** complete anything
(`unlock-b3-t1.md`: `0 undeclared write(s) in 0 call(s)`), so every research oracle before this row
was taken on a turn where the completion path did not run. Exposure at entry: none of the three
players with an AI client (32, 496, 512) has `ResTNm == ''`; `NumDes` does not move; two ships
complete and join existing fleets; the four factions at 528–576 carry the empty-`ResTNm` signature
inertly (`Status 0`, no client). Two ships completing *and* three fleets changing did **not** expose
this turn — a reminder that 26(c) is a screen and the control is the decision.
Masks for row 4, measured against the input: **exactly `/Summary/Checksum` and `Player.Status 4 → 0`
on the four live players. No `/CD[1]/NPrvVa` term** — this state's `CD[1]` diplomacy block is
early-game and the leaf does not move, so the documented `--mask resave` rule holds here in its
original form.
### Masks that must be on the line ### Masks that must be on the line
- `Player.Status` (4 → 0 on load) and the derived `Summary.Checksum`. - `Player.Status` (4 → 0 on load) and the derived `Summary.Checksum`.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -37,3 +37,11 @@ b6f4e05ff226eabd1695003b36293553642553cea96ef417364393e2332a7094 verify/results
1c8baa27680809d585ab1728391e82729642d32aaedffd5bf95b616f0a11a436 verify/results/saves/ad-turn27-two-raiders.sav 1c8baa27680809d585ab1728391e82729642d32aaedffd5bf95b616f0a11a436 verify/results/saves/ad-turn27-two-raiders.sav
e913ff41188211c02d536da616337544e64133996cd7cc7a6521a8df1960226f verify/results/saves/bp-pinA-turn28.sav e913ff41188211c02d536da616337544e64133996cd7cc7a6521a8df1960226f verify/results/saves/bp-pinA-turn28.sav
724528ffde9a7514b69ab9e82ed3b8c8ade63d622c0720de30503a73a92df11e verify/results/saves/bp-pinB-turn28.sav 724528ffde9a7514b69ab9e82ed3b8c8ade63d622c0720de30503a73a92df11e verify/results/saves/bp-pinB-turn28.sav
# Lane CR, 2026-09-09 -- VM145. Input turn3-state.sav (= the (Autosave).sav of certified-pairs
# row 1), one End Turn, LOAD route. Build cr-618ccb1-20260909T131556Z, shimdist-cr.
# C1/C2 hooks=off (two fresh processes), N compare, R0/R1 replace.
e00eed0c03a31d27a81b7470a9dcc9ba08a2ac48c20baeee4f34749164743e3f 67212 (Autosave EndTurn).sav C1 == C2 == N == R0 == R1
79df50475a7b83afa927d992b9f030dcf45710f4bda0133b8b1fa4800a72e420 67811 (Autosave).sav C1 == C2 == N [THE ORACLE]
6b51db992b158caa5424d71b2dccf72924af7198b4165bfcfc870e0d438fb6d5 67511 (Autosave).sav R0 replace, research.replace_cascade=off -> 27 leaves
8a4309ee4fe0b3177a2820600b5016c7c256d0f51b065df469ecd0b4f2342235 67537 (Autosave).sav R1 replace, research.replace_cascade=on -> 16 leaves

View file

@ -0,0 +1,118 @@
09:33:54.650 [tid 880] ==== sots-engine shim (binkw32 proxy) build cr-618ccb1-20260909T131556Z ====
09:33:54.650 [tid 880] exe: C:\SOTS\Sword of the Stars.exe
09:33:54.650 [tid 880] exe base=0x00f40000 (link-time image base 0x00400000, ASLR delta +11796480) pid=20996 shim=71d70000
09:33:54.650 [tid 880] addresses: Source: sots-re ghidra/addresses.json @ aa8d3fb, generated 2026-09-09 by tools/gen_addresses.py
09:33:54.650 [tid 880] config: hooks=trace
09:33:54.650 [tid 880] config: hook.Game::EncounterDetect::AssignContacts=off
09:33:54.650 [tid 880] config: hook.Game::EncounterDetect::ProcessTeamRecord=off
09:33:54.650 [tid 880] config: hook.Game::SVSOSlaversRefuel::UpdateDifficultyTier=off
09:33:54.650 [tid 880] config: hook.Game::SVSOSwarmQueen::OnTurnBegin=off
09:33:54.650 [tid 880] config: hook.Game::SVSOSwarmQueen::RegisterHives=off
09:33:54.650 [tid 880] config: hook.Game::SVSOSwarmQueen::TickHives=off
09:33:54.650 [tid 880] config: hook.Game::SectionDictionary::SectionDictionary=off
09:33:54.650 [tid 880] config: hook.Game::ServerPlayer::ComputeBudget=off
09:33:54.650 [tid 880] config: hook.Game::ServerPlayer::OnTechResearched=off
09:33:54.650 [tid 880] config: hook.Game::ServerPlayer::ProcessTurn=off
09:33:54.650 [tid 880] config: hook.Game::ServerSystem::ComputeTotalOutput=off
09:33:54.650 [tid 880] config: hook.Game::ServerSystem::GroupOutput=off
09:33:54.650 [tid 880] config: hook.Game::ServerSystem::ProcessTurn=off
09:33:54.650 [tid 880] config: hook.Game::StrategyApp::RunAI=off
09:33:54.650 [tid 880] config: hook.Game::StrategyHost::Autosave=off
09:33:54.650 [tid 880] config: hook.Game::StrategyServer::ApplyEncounterResult=off
09:33:54.650 [tid 880] config: hook.Game::StrategyServer::BeginProcessTurn=off
09:33:54.650 [tid 880] config: hook.Game::StrategyServer::MoveFleet=off
09:33:54.650 [tid 880] config: hook.Game::StrategyServer::NodeLineDecay=off
09:33:54.650 [tid 880] config: hook.Game::StrategyServer::OnAllCombatDone_Tail=off
09:33:54.650 [tid 880] config: hook.Game::StrategyServer::ProcessFleetMovement=off
09:33:54.650 [tid 880] config: hook.Game::StrategyServer::ProcessNodeSpaceTravel=off
09:33:54.650 [tid 880] config: hook.Game::StrategyServer::ProcessTurn=off
09:33:54.650 [tid 880] config: hook.Game::WeaponDictionary::Init=off
09:33:54.650 [tid 880] config: hook.Mars::GlobalConsts::LoadFile=off
09:33:54.650 [tid 880] config: hook.Mars::RNG::Seed=off
09:33:54.650 [tid 880] config: hook.Game::TechTree::ProcessResearch=compare
09:33:54.650 [tid 880] config: research.replace_cascade=off
09:33:54.650 [tid 880] config: trace.path=C:\SOTS\shim.trace.jsonl
09:33:54.650 [tid 880] config: trace.inline_max=256
09:33:54.650 [tid 880] config: trace.flush=always
09:33:54.728 [tid 880] trace: C:\SOTS\shim.trace.jsonl (default mode trace, inline_max 256, flush always)
09:33:54.728 [tid 880] hook: Mars_Application_Initialize rva=0x004a0e50 -> va=013e0e50
09:33:54.728 [tid 880] hook: MH_Initialize -> MH_OK
09:33:54.728 [tid 880] hook: MH_CreateHook -> MH_OK (trampoline=00a30fe0)
09:33:54.759 [tid 880] hook: MH_EnableHook -> MH_OK
09:33:54.759 [tid 880] cfg: GlobalConsts hook ready (scale constant 0.017453292519943295)
09:33:54.759 [tid 880] hook: Mars::GlobalConsts::LoadFile rva=0x004b73c0 mode=off (not installed)
09:33:54.759 [tid 880] dict: dictionaries hook ready (crt new=73e7232b delete=73e70174)
09:33:54.759 [tid 880] hook: Game::WeaponDictionary::Init rva=0x0019a4c0 mode=off (not installed)
09:33:54.759 [tid 880] hook: Game::SectionDictionary::SectionDictionary rva=0x00176f40 mode=off (not installed)
09:33:54.759 [tid 880] research: ProcessResearch hook ready (Cost=010bda00, node=0x34, rng=0x9cc, fpu_cw=0x027f, replace_cascade=off)
09:33:54.759 [tid 880] hook: Game::TechTree::ProcessResearch rva=0x001876c0 -> va=010c76c0 MH_CreateHook -> MH_OK (trampoline=00a30fc0)
09:33:54.775 [tid 880] hook: Game::TechTree::ProcessResearch MH_EnableHook -> MH_OK mode=compare
09:33:54.775 [tid 880] techfx: OnTechResearched hook ready (regions=15, gate=0/0, fpu_cw=0x027f)
09:33:54.775 [tid 880] hook: Game::ServerPlayer::OnTechResearched rva=0x00491790 mode=off (not installed)
09:33:54.775 [tid 880] hook: Game::ServerPlayer::ComputeBudget rva=0x00463030 mode=off (not installed)
09:33:54.775 [tid 880] hook: Game::ServerSystem::ProcessTurn rva=0x003598e0 mode=off (not installed)
09:33:54.775 [tid 880] hook: Game::ServerSystem::GroupOutput rva=0x0034b7a0 mode=off (not installed)
09:33:54.775 [tid 880] hook: Game::ServerSystem::ComputeTotalOutput rva=0x00350480 mode=off (not installed)
09:33:54.775 [tid 880] player_turn: ServerPlayer::ProcessTurn hook armed (ratio helper at 010be950)
09:33:54.775 [tid 880] hook: Game::ServerPlayer::ProcessTurn rva=0x00491340 mode=off (not installed)
09:33:54.775 [tid 880] hook: Game::StrategyServer::MoveFleet rva=0x003d9ee0 mode=off (not installed)
09:33:54.775 [tid 880] hook: Game::StrategyServer::ProcessFleetMovement rva=0x003da9a0 mode=off (not installed)
09:33:54.775 [tid 880] hook: Game::StrategyHost::Autosave rva=0x00495210 mode=off (not installed)
09:33:54.775 [tid 880] hook: Game::StrategyServer::ProcessTurn rva=0x003dc6c0 mode=off (not installed)
09:33:54.775 [tid 880] hook: Game::StrategyServer::OnAllCombatDone_Tail rva=0x003d92a0 mode=off (not installed)
09:33:54.775 [tid 880] hook: Game::StrategyServer::ApplyEncounterResult rva=0x003d8920 mode=off (not installed)
09:33:54.775 [tid 880] hook: Game::StrategyServer::NodeLineDecay rva=0x003ae010 mode=off (not installed)
09:33:54.775 [tid 880] hook: Game::StrategyServer::ProcessNodeSpaceTravel rva=0x003a0e20 mode=off (not installed)
09:33:54.775 [tid 880] hook: Game::EncounterDetect::AssignContacts rva=0x003aa240 mode=off (not installed)
09:33:54.775 [tid 880] hook: Game::EncounterDetect::ProcessTeamRecord rva=0x003ca640 mode=off (not installed)
09:33:54.775 [tid 880] hook: Game::StrategyServer::BeginProcessTurn rva=0x003d98e0 mode=off (not installed)
09:33:54.775 [tid 880] hook: Game::SVSOSwarmQueen::OnTurnBegin rva=0x00129930 mode=off (not installed)
09:33:54.775 [tid 880] hook: Game::SVSOSwarmQueen::RegisterHives rva=0x00127630 mode=off (not installed)
09:33:54.775 [tid 880] hook: Game::SVSOSwarmQueen::TickHives rva=0x00127770 mode=off (not installed)
09:33:54.775 [tid 880] hook: Game::SVSOSlaversRefuel::UpdateDifficultyTier rva=0x00115820 mode=off (not installed)
09:33:54.775 [tid 880] hook: Mars::RNG::Seed rva=0x0009fdf0 mode=off (not installed)
09:33:54.775 [tid 880] hook: Game::StrategyApp::RunAI rva=0x004706f0 mode=off (not installed)
09:33:54.806 [tid 880] drawsite: Mars::RNG::NextFloat rva=0x0007d830 -> va=00fbd830 create=MH_OK enable=MH_OK
09:33:54.822 [tid 880] drawsite: Mars::RNG::NextInt rva=0x000271c0 -> va=00f671c0 create=MH_OK enable=MH_OK
09:33:54.853 [tid 880] drawsite: Mars::RNG::Chance rva=0x004e6dd0 -> va=01426dd0 create=MH_OK enable=MH_OK
09:33:54.869 [tid 880] drawsite: Mars::RNG::NextUInt rva=0x000f7670 -> va=01037670 create=MH_OK enable=MH_OK
09:33:54.884 [tid 880] drawsite: Mars::RNG::FloatRange rva=0x0007d8a0 -> va=00fbd8a0 create=MH_OK enable=MH_OK
09:33:54.916 [tid 880] drawsite: Mars::RNG::IntRangeBell rva=0x004e6d80 -> va=01426d80 create=MH_OK enable=MH_OK
09:33:54.931 [tid 880] drawsite: Mars::RNG::GaussianRange rva=0x004e6e30 -> va=01426e30 create=MH_OK enable=MH_OK
09:33:54.931 [tid 880] probe: installing 12 of 12 (probes= in shim.cfg)
09:33:54.947 [tid 880] probe: Game::ServerSpyManager::vslot13 rva=0x004877b0 -> va=013c77b0 create=MH_OK enable=MH_OK
09:33:54.963 [tid 880] probe: Game::ServerSpyManager::vslot14 rva=0x0048db80 -> va=013cdb80 create=MH_OK enable=MH_OK
09:33:54.994 [tid 880] probe: Game::ServerTradeManagerImpl::vslot13 rva=0x0048ef80 -> va=013cef80 create=MH_OK enable=MH_OK
09:33:55.009 [tid 880] probe: Game::ServerTradeManagerImpl::vslot15 rva=0x0042cca0 -> va=0136cca0 create=MH_OK enable=MH_OK
09:33:55.025 [tid 880] probe: Game::SpyManager::Slot13RngCallee rva=0x004408e0 -> va=013808e0 create=MH_OK enable=MH_OK
09:33:55.041 [tid 880] probe: Game::TradeManager::Slot13RngCalleeA rva=0x00420ca0 -> va=01360ca0 create=MH_OK enable=MH_OK
09:33:55.072 [tid 880] probe: Game::TradeManager::Slot13RngCalleeB rva=0x0048b440 -> va=013cb440 create=MH_OK enable=MH_OK
09:33:55.088 [tid 880] probe: Game::ServerTradeManager::CreateRaidEncounter rva=0x004938a0 -> va=013d38a0 create=MH_OK enable=MH_OK
09:33:55.103 [tid 880] probe: Game::ServerTradeManager::GenerateTradeRaidEncounters rva=0x00493290 -> va=013d3290 create=MH_OK enable=MH_OK
09:33:55.134 [tid 880] probe: Game::ServerSpyManager::vslot15 [control] rva=0x00487f30 -> va=013c7f30 create=MH_OK enable=MH_OK
09:33:55.150 [tid 880] probe: Game::ServerTradeManagerImpl::vslot14 [control] rva=0x004590d0 -> va=013990d0 create=MH_OK enable=MH_OK
09:33:55.166 [tid 880] probe: Game::EncounterDetect::Run [control] rva=0x003cb080 -> va=0130b080 create=MH_OK enable=MH_OK
09:33:55.166 [tid 880] watch: disabled (watch=off)
09:33:55.166 [tid 880] aiorders: disabled (aiorders=off)
09:33:55.166 [tid 880] fpu: module init, entry cw=0x027f 53bit-double/nearest; force=off value=0x0000 sample_ticks=on
09:33:55.166 [tid 880] fpu: sample_turn=on (off releases StrategyServer::ProcessTurn for another hook)
09:33:55.166 [tid 880] fpu: StrategyClient::EndTurn rva=0x00383be0 -> va=012c3be0 MH_CreateHook -> MH_OK (trampoline=00a30d40)
09:33:55.197 [tid 880] fpu: StrategyClient::EndTurn MH_EnableHook -> MH_OK
09:33:55.197 [tid 880] fpu: StrategyServer::BeginProcessTurn rva=0x003d98e0 -> va=013198e0 MH_CreateHook -> MH_OK (trampoline=00a30d20)
09:33:55.213 [tid 880] fpu: StrategyServer::BeginProcessTurn MH_EnableHook -> MH_OK
09:33:55.213 [tid 880] fpu: StrategyServer::ProcessTurn rva=0x003dc6c0 -> va=0131c6c0 MH_CreateHook -> MH_OK (trampoline=00a30d00)
09:33:55.228 [tid 880] fpu: StrategyServer::ProcessTurn MH_EnableHook -> MH_OK
09:33:55.228 [tid 880] fpu: DemoApp::OnTick rva=0x0049a640 -> va=013da640 MH_CreateHook -> MH_OK (trampoline=00a30ce0)
09:33:55.259 [tid 880] fpu: DemoApp::OnTick MH_EnableHook -> MH_OK
09:33:55.259 [tid 880] selftest: Shim::SelfTest::Fill mode=trace checksum=075ef0c3 records=1
09:33:55.275 [tid 880] Application::Initialize called (this=00a88128)
09:33:56.166 [tid 880] fpu: TICK BASELINE at OnTick (this=00a88128): cw=0x127f 53bit-double/nearest
09:39:38.180 [tid 880] fpu: sample at StrategyClient::EndTurn (this=1e0711e8): cw=0x127f 53bit-double/nearest [no fpu.force configured]
09:39:41.289 [tid 880] fpu: sample at StrategyClient::EndTurn (this=32c5e628): cw=0x127f 53bit-double/nearest [no fpu.force configured]
09:39:41.336 [tid 880] fpu: sample at StrategyClient::EndTurn (this=32c58038): cw=0x127f 53bit-double/nearest [no fpu.force configured]
09:39:41.383 [tid 880] fpu: sample at StrategyClient::EndTurn (this=32c5d798): cw=0x127f 53bit-double/nearest [no fpu.force configured]
09:39:42.305 [tid 880] fpu: sample at StrategyServer::BeginProcessTurn (this=0d2908c8): cw=0x127f 53bit-double/nearest [no fpu.force configured]
09:39:42.305 [tid 880] fpu: sample at StrategyServer::ProcessTurn (this=0d2908c8): cw=0x127f 53bit-double/nearest
09:39:42.336 [tid 880] research: mode=compare steps=1 completions=1 overbudget=1166 cascade_possible=1 ok=1 cascade_completions=1 unlocked=3 otch_appends=1 roll_draws=0 failures=0 depth=0 name_unreadable=0
09:39:42.383 [tid 880] research: mode=compare steps=1 completions=0 overbudget=0 cascade_possible=1 ok=1 cascade_completions=0 unlocked=0 otch_appends=0 roll_draws=0 failures=0 depth=0 name_unreadable=0
09:39:42.398 [tid 880] research: mode=compare steps=1 completions=0 overbudget=0 cascade_possible=1 ok=1 cascade_completions=0 unlocked=0 otch_appends=0 roll_draws=0 failures=0 depth=0 name_unreadable=0

View file

@ -0,0 +1,118 @@
09:51:31.009 [tid 19724] ==== sots-engine shim (binkw32 proxy) build cr-618ccb1-20260909T131556Z ====
09:51:31.009 [tid 19724] exe: C:\SOTS\Sword of the Stars.exe
09:51:31.009 [tid 19724] exe base=0x00f40000 (link-time image base 0x00400000, ASLR delta +11796480) pid=20348 shim=71d70000
09:51:31.009 [tid 19724] addresses: Source: sots-re ghidra/addresses.json @ aa8d3fb, generated 2026-09-09 by tools/gen_addresses.py
09:51:31.009 [tid 19724] config: hooks=trace
09:51:31.009 [tid 19724] config: hook.Game::EncounterDetect::AssignContacts=off
09:51:31.009 [tid 19724] config: hook.Game::EncounterDetect::ProcessTeamRecord=off
09:51:31.009 [tid 19724] config: hook.Game::SVSOSlaversRefuel::UpdateDifficultyTier=off
09:51:31.009 [tid 19724] config: hook.Game::SVSOSwarmQueen::OnTurnBegin=off
09:51:31.009 [tid 19724] config: hook.Game::SVSOSwarmQueen::RegisterHives=off
09:51:31.009 [tid 19724] config: hook.Game::SVSOSwarmQueen::TickHives=off
09:51:31.009 [tid 19724] config: hook.Game::SectionDictionary::SectionDictionary=off
09:51:31.025 [tid 19724] config: hook.Game::ServerPlayer::ComputeBudget=off
09:51:31.025 [tid 19724] config: hook.Game::ServerPlayer::OnTechResearched=off
09:51:31.025 [tid 19724] config: hook.Game::ServerPlayer::ProcessTurn=off
09:51:31.025 [tid 19724] config: hook.Game::ServerSystem::ComputeTotalOutput=off
09:51:31.025 [tid 19724] config: hook.Game::ServerSystem::GroupOutput=off
09:51:31.025 [tid 19724] config: hook.Game::ServerSystem::ProcessTurn=off
09:51:31.025 [tid 19724] config: hook.Game::StrategyApp::RunAI=off
09:51:31.025 [tid 19724] config: hook.Game::StrategyHost::Autosave=off
09:51:31.025 [tid 19724] config: hook.Game::StrategyServer::ApplyEncounterResult=off
09:51:31.025 [tid 19724] config: hook.Game::StrategyServer::BeginProcessTurn=off
09:51:31.025 [tid 19724] config: hook.Game::StrategyServer::MoveFleet=off
09:51:31.025 [tid 19724] config: hook.Game::StrategyServer::NodeLineDecay=off
09:51:31.025 [tid 19724] config: hook.Game::StrategyServer::OnAllCombatDone_Tail=off
09:51:31.025 [tid 19724] config: hook.Game::StrategyServer::ProcessFleetMovement=off
09:51:31.025 [tid 19724] config: hook.Game::StrategyServer::ProcessNodeSpaceTravel=off
09:51:31.025 [tid 19724] config: hook.Game::StrategyServer::ProcessTurn=off
09:51:31.025 [tid 19724] config: hook.Game::WeaponDictionary::Init=off
09:51:31.025 [tid 19724] config: hook.Mars::GlobalConsts::LoadFile=off
09:51:31.025 [tid 19724] config: hook.Mars::RNG::Seed=off
09:51:31.025 [tid 19724] config: hook.Game::TechTree::ProcessResearch=replace
09:51:31.025 [tid 19724] config: research.replace_cascade=off
09:51:31.025 [tid 19724] config: trace.path=C:\SOTS\shim.trace.jsonl
09:51:31.025 [tid 19724] config: trace.inline_max=256
09:51:31.025 [tid 19724] config: trace.flush=always
09:51:31.088 [tid 19724] trace: C:\SOTS\shim.trace.jsonl (default mode trace, inline_max 256, flush always)
09:51:31.088 [tid 19724] hook: Mars_Application_Initialize rva=0x004a0e50 -> va=013e0e50
09:51:31.088 [tid 19724] hook: MH_Initialize -> MH_OK
09:51:31.088 [tid 19724] hook: MH_CreateHook -> MH_OK (trampoline=017e0fe0)
09:51:31.119 [tid 19724] hook: MH_EnableHook -> MH_OK
09:51:31.119 [tid 19724] cfg: GlobalConsts hook ready (scale constant 0.017453292519943295)
09:51:31.119 [tid 19724] hook: Mars::GlobalConsts::LoadFile rva=0x004b73c0 mode=off (not installed)
09:51:31.119 [tid 19724] dict: dictionaries hook ready (crt new=73e7232b delete=73e70174)
09:51:31.119 [tid 19724] hook: Game::WeaponDictionary::Init rva=0x0019a4c0 mode=off (not installed)
09:51:31.119 [tid 19724] hook: Game::SectionDictionary::SectionDictionary rva=0x00176f40 mode=off (not installed)
09:51:31.119 [tid 19724] research: ProcessResearch hook ready (Cost=010bda00, node=0x34, rng=0x9cc, fpu_cw=0x027f, replace_cascade=off)
09:51:31.119 [tid 19724] hook: Game::TechTree::ProcessResearch rva=0x001876c0 -> va=010c76c0 MH_CreateHook -> MH_OK (trampoline=017e0fc0)
09:51:31.134 [tid 19724] hook: Game::TechTree::ProcessResearch MH_EnableHook -> MH_OK mode=replace
09:51:31.134 [tid 19724] techfx: OnTechResearched hook ready (regions=15, gate=0/0, fpu_cw=0x027f)
09:51:31.134 [tid 19724] hook: Game::ServerPlayer::OnTechResearched rva=0x00491790 mode=off (not installed)
09:51:31.134 [tid 19724] hook: Game::ServerPlayer::ComputeBudget rva=0x00463030 mode=off (not installed)
09:51:31.134 [tid 19724] hook: Game::ServerSystem::ProcessTurn rva=0x003598e0 mode=off (not installed)
09:51:31.134 [tid 19724] hook: Game::ServerSystem::GroupOutput rva=0x0034b7a0 mode=off (not installed)
09:51:31.134 [tid 19724] hook: Game::ServerSystem::ComputeTotalOutput rva=0x00350480 mode=off (not installed)
09:51:31.134 [tid 19724] player_turn: ServerPlayer::ProcessTurn hook armed (ratio helper at 010be950)
09:51:31.134 [tid 19724] hook: Game::ServerPlayer::ProcessTurn rva=0x00491340 mode=off (not installed)
09:51:31.134 [tid 19724] hook: Game::StrategyServer::MoveFleet rva=0x003d9ee0 mode=off (not installed)
09:51:31.134 [tid 19724] hook: Game::StrategyServer::ProcessFleetMovement rva=0x003da9a0 mode=off (not installed)
09:51:31.134 [tid 19724] hook: Game::StrategyHost::Autosave rva=0x00495210 mode=off (not installed)
09:51:31.134 [tid 19724] hook: Game::StrategyServer::ProcessTurn rva=0x003dc6c0 mode=off (not installed)
09:51:31.134 [tid 19724] hook: Game::StrategyServer::OnAllCombatDone_Tail rva=0x003d92a0 mode=off (not installed)
09:51:31.134 [tid 19724] hook: Game::StrategyServer::ApplyEncounterResult rva=0x003d8920 mode=off (not installed)
09:51:31.134 [tid 19724] hook: Game::StrategyServer::NodeLineDecay rva=0x003ae010 mode=off (not installed)
09:51:31.134 [tid 19724] hook: Game::StrategyServer::ProcessNodeSpaceTravel rva=0x003a0e20 mode=off (not installed)
09:51:31.134 [tid 19724] hook: Game::EncounterDetect::AssignContacts rva=0x003aa240 mode=off (not installed)
09:51:31.134 [tid 19724] hook: Game::EncounterDetect::ProcessTeamRecord rva=0x003ca640 mode=off (not installed)
09:51:31.134 [tid 19724] hook: Game::StrategyServer::BeginProcessTurn rva=0x003d98e0 mode=off (not installed)
09:51:31.134 [tid 19724] hook: Game::SVSOSwarmQueen::OnTurnBegin rva=0x00129930 mode=off (not installed)
09:51:31.134 [tid 19724] hook: Game::SVSOSwarmQueen::RegisterHives rva=0x00127630 mode=off (not installed)
09:51:31.134 [tid 19724] hook: Game::SVSOSwarmQueen::TickHives rva=0x00127770 mode=off (not installed)
09:51:31.134 [tid 19724] hook: Game::SVSOSlaversRefuel::UpdateDifficultyTier rva=0x00115820 mode=off (not installed)
09:51:31.134 [tid 19724] hook: Mars::RNG::Seed rva=0x0009fdf0 mode=off (not installed)
09:51:31.134 [tid 19724] hook: Game::StrategyApp::RunAI rva=0x004706f0 mode=off (not installed)
09:51:31.166 [tid 19724] drawsite: Mars::RNG::NextFloat rva=0x0007d830 -> va=00fbd830 create=MH_OK enable=MH_OK
09:51:31.181 [tid 19724] drawsite: Mars::RNG::NextInt rva=0x000271c0 -> va=00f671c0 create=MH_OK enable=MH_OK
09:51:31.213 [tid 19724] drawsite: Mars::RNG::Chance rva=0x004e6dd0 -> va=01426dd0 create=MH_OK enable=MH_OK
09:51:31.228 [tid 19724] drawsite: Mars::RNG::NextUInt rva=0x000f7670 -> va=01037670 create=MH_OK enable=MH_OK
09:51:31.275 [tid 19724] drawsite: Mars::RNG::FloatRange rva=0x0007d8a0 -> va=00fbd8a0 create=MH_OK enable=MH_OK
09:51:31.291 [tid 19724] drawsite: Mars::RNG::IntRangeBell rva=0x004e6d80 -> va=01426d80 create=MH_OK enable=MH_OK
09:51:31.306 [tid 19724] drawsite: Mars::RNG::GaussianRange rva=0x004e6e30 -> va=01426e30 create=MH_OK enable=MH_OK
09:51:31.306 [tid 19724] probe: installing 12 of 12 (probes= in shim.cfg)
09:51:31.338 [tid 19724] probe: Game::ServerSpyManager::vslot13 rva=0x004877b0 -> va=013c77b0 create=MH_OK enable=MH_OK
09:51:31.353 [tid 19724] probe: Game::ServerSpyManager::vslot14 rva=0x0048db80 -> va=013cdb80 create=MH_OK enable=MH_OK
09:51:31.369 [tid 19724] probe: Game::ServerTradeManagerImpl::vslot13 rva=0x0048ef80 -> va=013cef80 create=MH_OK enable=MH_OK
09:51:31.400 [tid 19724] probe: Game::ServerTradeManagerImpl::vslot15 rva=0x0042cca0 -> va=0136cca0 create=MH_OK enable=MH_OK
09:51:31.416 [tid 19724] probe: Game::SpyManager::Slot13RngCallee rva=0x004408e0 -> va=013808e0 create=MH_OK enable=MH_OK
09:51:31.431 [tid 19724] probe: Game::TradeManager::Slot13RngCalleeA rva=0x00420ca0 -> va=01360ca0 create=MH_OK enable=MH_OK
09:51:31.463 [tid 19724] probe: Game::TradeManager::Slot13RngCalleeB rva=0x0048b440 -> va=013cb440 create=MH_OK enable=MH_OK
09:51:31.478 [tid 19724] probe: Game::ServerTradeManager::CreateRaidEncounter rva=0x004938a0 -> va=013d38a0 create=MH_OK enable=MH_OK
09:51:31.494 [tid 19724] probe: Game::ServerTradeManager::GenerateTradeRaidEncounters rva=0x00493290 -> va=013d3290 create=MH_OK enable=MH_OK
09:51:31.525 [tid 19724] probe: Game::ServerSpyManager::vslot15 [control] rva=0x00487f30 -> va=013c7f30 create=MH_OK enable=MH_OK
09:51:31.541 [tid 19724] probe: Game::ServerTradeManagerImpl::vslot14 [control] rva=0x004590d0 -> va=013990d0 create=MH_OK enable=MH_OK
09:51:31.572 [tid 19724] probe: Game::EncounterDetect::Run [control] rva=0x003cb080 -> va=0130b080 create=MH_OK enable=MH_OK
09:51:31.572 [tid 19724] watch: disabled (watch=off)
09:51:31.572 [tid 19724] aiorders: disabled (aiorders=off)
09:51:31.572 [tid 19724] fpu: module init, entry cw=0x027f 53bit-double/nearest; force=off value=0x0000 sample_ticks=on
09:51:31.572 [tid 19724] fpu: sample_turn=on (off releases StrategyServer::ProcessTurn for another hook)
09:51:31.572 [tid 19724] fpu: StrategyClient::EndTurn rva=0x00383be0 -> va=012c3be0 MH_CreateHook -> MH_OK (trampoline=017e0d40)
09:51:31.588 [tid 19724] fpu: StrategyClient::EndTurn MH_EnableHook -> MH_OK
09:51:31.588 [tid 19724] fpu: StrategyServer::BeginProcessTurn rva=0x003d98e0 -> va=013198e0 MH_CreateHook -> MH_OK (trampoline=017e0d20)
09:51:31.619 [tid 19724] fpu: StrategyServer::BeginProcessTurn MH_EnableHook -> MH_OK
09:51:31.619 [tid 19724] fpu: StrategyServer::ProcessTurn rva=0x003dc6c0 -> va=0131c6c0 MH_CreateHook -> MH_OK (trampoline=017e0d00)
09:51:31.634 [tid 19724] fpu: StrategyServer::ProcessTurn MH_EnableHook -> MH_OK
09:51:31.634 [tid 19724] fpu: DemoApp::OnTick rva=0x0049a640 -> va=013da640 MH_CreateHook -> MH_OK (trampoline=017e0ce0)
09:51:31.666 [tid 19724] fpu: DemoApp::OnTick MH_EnableHook -> MH_OK
09:51:31.666 [tid 19724] selftest: Shim::SelfTest::Fill mode=trace checksum=075ef0c3 records=1
09:51:31.681 [tid 19724] Application::Initialize called (this=03938128)
09:51:32.556 [tid 19724] fpu: TICK BASELINE at OnTick (this=03938128): cw=0x127f 53bit-double/nearest
09:57:42.520 [tid 19724] fpu: sample at StrategyClient::EndTurn (this=0dc22d40): cw=0x127f 53bit-double/nearest [no fpu.force configured]
09:57:45.614 [tid 19724] fpu: sample at StrategyClient::EndTurn (this=345fdee8): cw=0x127f 53bit-double/nearest [no fpu.force configured]
09:57:45.645 [tid 19724] fpu: sample at StrategyClient::EndTurn (this=345fabf0): cw=0x127f 53bit-double/nearest [no fpu.force configured]
09:57:45.692 [tid 19724] fpu: sample at StrategyClient::EndTurn (this=345fb338): cw=0x127f 53bit-double/nearest [no fpu.force configured]
09:57:46.598 [tid 19724] fpu: sample at StrategyServer::BeginProcessTurn (this=0dc25ab8): cw=0x127f 53bit-double/nearest [no fpu.force configured]
09:57:46.598 [tid 19724] fpu: sample at StrategyServer::ProcessTurn (this=0dc25ab8): cw=0x127f 53bit-double/nearest
09:57:46.614 [tid 19724] research: mode=replace steps=1 completions=1 overbudget=1166 cascade_possible=0 ok=0 cascade_completions=0 unlocked=0 otch_appends=0 roll_draws=0 failures=0 depth=0 name_unreadable=0
09:57:46.629 [tid 19724] research: mode=replace steps=1 completions=0 overbudget=0 cascade_possible=0 ok=0 cascade_completions=0 unlocked=0 otch_appends=0 roll_draws=0 failures=0 depth=0 name_unreadable=0
09:57:46.629 [tid 19724] research: mode=replace steps=1 completions=0 overbudget=0 cascade_possible=0 ok=0 cascade_completions=0 unlocked=0 otch_appends=0 roll_draws=0 failures=0 depth=0 name_unreadable=0

View file

@ -0,0 +1,118 @@
09:42:14.649 [tid 19172] ==== sots-engine shim (binkw32 proxy) build cr-618ccb1-20260909T131556Z ====
09:42:14.649 [tid 19172] exe: C:\SOTS\Sword of the Stars.exe
09:42:14.649 [tid 19172] exe base=0x00f40000 (link-time image base 0x00400000, ASLR delta +11796480) pid=20592 shim=71d70000
09:42:14.649 [tid 19172] addresses: Source: sots-re ghidra/addresses.json @ aa8d3fb, generated 2026-09-09 by tools/gen_addresses.py
09:42:14.649 [tid 19172] config: hooks=trace
09:42:14.649 [tid 19172] config: hook.Game::EncounterDetect::AssignContacts=off
09:42:14.649 [tid 19172] config: hook.Game::EncounterDetect::ProcessTeamRecord=off
09:42:14.649 [tid 19172] config: hook.Game::SVSOSlaversRefuel::UpdateDifficultyTier=off
09:42:14.649 [tid 19172] config: hook.Game::SVSOSwarmQueen::OnTurnBegin=off
09:42:14.649 [tid 19172] config: hook.Game::SVSOSwarmQueen::RegisterHives=off
09:42:14.649 [tid 19172] config: hook.Game::SVSOSwarmQueen::TickHives=off
09:42:14.649 [tid 19172] config: hook.Game::SectionDictionary::SectionDictionary=off
09:42:14.649 [tid 19172] config: hook.Game::ServerPlayer::ComputeBudget=off
09:42:14.649 [tid 19172] config: hook.Game::ServerPlayer::OnTechResearched=off
09:42:14.649 [tid 19172] config: hook.Game::ServerPlayer::ProcessTurn=off
09:42:14.649 [tid 19172] config: hook.Game::ServerSystem::ComputeTotalOutput=off
09:42:14.649 [tid 19172] config: hook.Game::ServerSystem::GroupOutput=off
09:42:14.649 [tid 19172] config: hook.Game::ServerSystem::ProcessTurn=off
09:42:14.649 [tid 19172] config: hook.Game::StrategyApp::RunAI=off
09:42:14.649 [tid 19172] config: hook.Game::StrategyHost::Autosave=off
09:42:14.649 [tid 19172] config: hook.Game::StrategyServer::ApplyEncounterResult=off
09:42:14.649 [tid 19172] config: hook.Game::StrategyServer::BeginProcessTurn=off
09:42:14.649 [tid 19172] config: hook.Game::StrategyServer::MoveFleet=off
09:42:14.649 [tid 19172] config: hook.Game::StrategyServer::NodeLineDecay=off
09:42:14.649 [tid 19172] config: hook.Game::StrategyServer::OnAllCombatDone_Tail=off
09:42:14.649 [tid 19172] config: hook.Game::StrategyServer::ProcessFleetMovement=off
09:42:14.649 [tid 19172] config: hook.Game::StrategyServer::ProcessNodeSpaceTravel=off
09:42:14.649 [tid 19172] config: hook.Game::StrategyServer::ProcessTurn=off
09:42:14.649 [tid 19172] config: hook.Game::WeaponDictionary::Init=off
09:42:14.649 [tid 19172] config: hook.Mars::GlobalConsts::LoadFile=off
09:42:14.649 [tid 19172] config: hook.Mars::RNG::Seed=off
09:42:14.649 [tid 19172] config: hook.Game::TechTree::ProcessResearch=replace
09:42:14.649 [tid 19172] config: research.replace_cascade=on
09:42:14.649 [tid 19172] config: trace.path=C:\SOTS\shim.trace.jsonl
09:42:14.649 [tid 19172] config: trace.inline_max=256
09:42:14.649 [tid 19172] config: trace.flush=always
09:42:14.742 [tid 19172] trace: C:\SOTS\shim.trace.jsonl (default mode trace, inline_max 256, flush always)
09:42:14.742 [tid 19172] hook: Mars_Application_Initialize rva=0x004a0e50 -> va=013e0e50
09:42:14.742 [tid 19172] hook: MH_Initialize -> MH_OK
09:42:14.742 [tid 19172] hook: MH_CreateHook -> MH_OK (trampoline=00cd0fe0)
09:42:14.773 [tid 19172] hook: MH_EnableHook -> MH_OK
09:42:14.773 [tid 19172] cfg: GlobalConsts hook ready (scale constant 0.017453292519943295)
09:42:14.773 [tid 19172] hook: Mars::GlobalConsts::LoadFile rva=0x004b73c0 mode=off (not installed)
09:42:14.773 [tid 19172] dict: dictionaries hook ready (crt new=73e7232b delete=73e70174)
09:42:14.773 [tid 19172] hook: Game::WeaponDictionary::Init rva=0x0019a4c0 mode=off (not installed)
09:42:14.773 [tid 19172] hook: Game::SectionDictionary::SectionDictionary rva=0x00176f40 mode=off (not installed)
09:42:14.773 [tid 19172] research: ProcessResearch hook ready (Cost=010bda00, node=0x34, rng=0x9cc, fpu_cw=0x027f, replace_cascade=on)
09:42:14.773 [tid 19172] hook: Game::TechTree::ProcessResearch rva=0x001876c0 -> va=010c76c0 MH_CreateHook -> MH_OK (trampoline=00cd0fc0)
09:42:14.805 [tid 19172] hook: Game::TechTree::ProcessResearch MH_EnableHook -> MH_OK mode=replace
09:42:14.805 [tid 19172] techfx: OnTechResearched hook ready (regions=15, gate=0/0, fpu_cw=0x027f)
09:42:14.805 [tid 19172] hook: Game::ServerPlayer::OnTechResearched rva=0x00491790 mode=off (not installed)
09:42:14.805 [tid 19172] hook: Game::ServerPlayer::ComputeBudget rva=0x00463030 mode=off (not installed)
09:42:14.805 [tid 19172] hook: Game::ServerSystem::ProcessTurn rva=0x003598e0 mode=off (not installed)
09:42:14.805 [tid 19172] hook: Game::ServerSystem::GroupOutput rva=0x0034b7a0 mode=off (not installed)
09:42:14.805 [tid 19172] hook: Game::ServerSystem::ComputeTotalOutput rva=0x00350480 mode=off (not installed)
09:42:14.805 [tid 19172] player_turn: ServerPlayer::ProcessTurn hook armed (ratio helper at 010be950)
09:42:14.805 [tid 19172] hook: Game::ServerPlayer::ProcessTurn rva=0x00491340 mode=off (not installed)
09:42:14.805 [tid 19172] hook: Game::StrategyServer::MoveFleet rva=0x003d9ee0 mode=off (not installed)
09:42:14.805 [tid 19172] hook: Game::StrategyServer::ProcessFleetMovement rva=0x003da9a0 mode=off (not installed)
09:42:14.805 [tid 19172] hook: Game::StrategyHost::Autosave rva=0x00495210 mode=off (not installed)
09:42:14.805 [tid 19172] hook: Game::StrategyServer::ProcessTurn rva=0x003dc6c0 mode=off (not installed)
09:42:14.805 [tid 19172] hook: Game::StrategyServer::OnAllCombatDone_Tail rva=0x003d92a0 mode=off (not installed)
09:42:14.805 [tid 19172] hook: Game::StrategyServer::ApplyEncounterResult rva=0x003d8920 mode=off (not installed)
09:42:14.805 [tid 19172] hook: Game::StrategyServer::NodeLineDecay rva=0x003ae010 mode=off (not installed)
09:42:14.805 [tid 19172] hook: Game::StrategyServer::ProcessNodeSpaceTravel rva=0x003a0e20 mode=off (not installed)
09:42:14.805 [tid 19172] hook: Game::EncounterDetect::AssignContacts rva=0x003aa240 mode=off (not installed)
09:42:14.805 [tid 19172] hook: Game::EncounterDetect::ProcessTeamRecord rva=0x003ca640 mode=off (not installed)
09:42:14.805 [tid 19172] hook: Game::StrategyServer::BeginProcessTurn rva=0x003d98e0 mode=off (not installed)
09:42:14.805 [tid 19172] hook: Game::SVSOSwarmQueen::OnTurnBegin rva=0x00129930 mode=off (not installed)
09:42:14.805 [tid 19172] hook: Game::SVSOSwarmQueen::RegisterHives rva=0x00127630 mode=off (not installed)
09:42:14.805 [tid 19172] hook: Game::SVSOSwarmQueen::TickHives rva=0x00127770 mode=off (not installed)
09:42:14.805 [tid 19172] hook: Game::SVSOSlaversRefuel::UpdateDifficultyTier rva=0x00115820 mode=off (not installed)
09:42:14.805 [tid 19172] hook: Mars::RNG::Seed rva=0x0009fdf0 mode=off (not installed)
09:42:14.805 [tid 19172] hook: Game::StrategyApp::RunAI rva=0x004706f0 mode=off (not installed)
09:42:14.820 [tid 19172] drawsite: Mars::RNG::NextFloat rva=0x0007d830 -> va=00fbd830 create=MH_OK enable=MH_OK
09:42:14.852 [tid 19172] drawsite: Mars::RNG::NextInt rva=0x000271c0 -> va=00f671c0 create=MH_OK enable=MH_OK
09:42:14.867 [tid 19172] drawsite: Mars::RNG::Chance rva=0x004e6dd0 -> va=01426dd0 create=MH_OK enable=MH_OK
09:42:14.883 [tid 19172] drawsite: Mars::RNG::NextUInt rva=0x000f7670 -> va=01037670 create=MH_OK enable=MH_OK
09:42:14.916 [tid 19172] drawsite: Mars::RNG::FloatRange rva=0x0007d8a0 -> va=00fbd8a0 create=MH_OK enable=MH_OK
09:42:14.945 [tid 19172] drawsite: Mars::RNG::IntRangeBell rva=0x004e6d80 -> va=01426d80 create=MH_OK enable=MH_OK
09:42:14.961 [tid 19172] drawsite: Mars::RNG::GaussianRange rva=0x004e6e30 -> va=01426e30 create=MH_OK enable=MH_OK
09:42:14.961 [tid 19172] probe: installing 12 of 12 (probes= in shim.cfg)
09:42:14.992 [tid 19172] probe: Game::ServerSpyManager::vslot13 rva=0x004877b0 -> va=013c77b0 create=MH_OK enable=MH_OK
09:42:15.008 [tid 19172] probe: Game::ServerSpyManager::vslot14 rva=0x0048db80 -> va=013cdb80 create=MH_OK enable=MH_OK
09:42:15.039 [tid 19172] probe: Game::ServerTradeManagerImpl::vslot13 rva=0x0048ef80 -> va=013cef80 create=MH_OK enable=MH_OK
09:42:15.070 [tid 19172] probe: Game::ServerTradeManagerImpl::vslot15 rva=0x0042cca0 -> va=0136cca0 create=MH_OK enable=MH_OK
09:42:15.086 [tid 19172] probe: Game::SpyManager::Slot13RngCallee rva=0x004408e0 -> va=013808e0 create=MH_OK enable=MH_OK
09:42:15.118 [tid 19172] probe: Game::TradeManager::Slot13RngCalleeA rva=0x00420ca0 -> va=01360ca0 create=MH_OK enable=MH_OK
09:42:15.133 [tid 19172] probe: Game::TradeManager::Slot13RngCalleeB rva=0x0048b440 -> va=013cb440 create=MH_OK enable=MH_OK
09:42:15.148 [tid 19172] probe: Game::ServerTradeManager::CreateRaidEncounter rva=0x004938a0 -> va=013d38a0 create=MH_OK enable=MH_OK
09:42:15.180 [tid 19172] probe: Game::ServerTradeManager::GenerateTradeRaidEncounters rva=0x00493290 -> va=013d3290 create=MH_OK enable=MH_OK
09:42:15.211 [tid 19172] probe: Game::ServerSpyManager::vslot15 [control] rva=0x00487f30 -> va=013c7f30 create=MH_OK enable=MH_OK
09:42:15.226 [tid 19172] probe: Game::ServerTradeManagerImpl::vslot14 [control] rva=0x004590d0 -> va=013990d0 create=MH_OK enable=MH_OK
09:42:15.258 [tid 19172] probe: Game::EncounterDetect::Run [control] rva=0x003cb080 -> va=0130b080 create=MH_OK enable=MH_OK
09:42:15.258 [tid 19172] watch: disabled (watch=off)
09:42:15.258 [tid 19172] aiorders: disabled (aiorders=off)
09:42:15.258 [tid 19172] fpu: module init, entry cw=0x027f 53bit-double/nearest; force=off value=0x0000 sample_ticks=on
09:42:15.258 [tid 19172] fpu: sample_turn=on (off releases StrategyServer::ProcessTurn for another hook)
09:42:15.258 [tid 19172] fpu: StrategyClient::EndTurn rva=0x00383be0 -> va=012c3be0 MH_CreateHook -> MH_OK (trampoline=00cd0d40)
09:42:15.273 [tid 19172] fpu: StrategyClient::EndTurn MH_EnableHook -> MH_OK
09:42:15.273 [tid 19172] fpu: StrategyServer::BeginProcessTurn rva=0x003d98e0 -> va=013198e0 MH_CreateHook -> MH_OK (trampoline=00cd0d20)
09:42:15.305 [tid 19172] fpu: StrategyServer::BeginProcessTurn MH_EnableHook -> MH_OK
09:42:15.305 [tid 19172] fpu: StrategyServer::ProcessTurn rva=0x003dc6c0 -> va=0131c6c0 MH_CreateHook -> MH_OK (trampoline=00cd0d00)
09:42:15.320 [tid 19172] fpu: StrategyServer::ProcessTurn MH_EnableHook -> MH_OK
09:42:15.320 [tid 19172] fpu: DemoApp::OnTick rva=0x0049a640 -> va=013da640 MH_CreateHook -> MH_OK (trampoline=00cd0ce0)
09:42:15.351 [tid 19172] fpu: DemoApp::OnTick MH_EnableHook -> MH_OK
09:42:15.351 [tid 19172] selftest: Shim::SelfTest::Fill mode=trace checksum=075ef0c3 records=1
09:42:15.367 [tid 19172] Application::Initialize called (this=03548128)
09:42:16.336 [tid 19172] fpu: TICK BASELINE at OnTick (this=03548128): cw=0x127f 53bit-double/nearest
09:48:17.041 [tid 19172] fpu: sample at StrategyClient::EndTurn (this=0d6dd1e0): cw=0x127f 53bit-double/nearest [no fpu.force configured]
09:48:20.150 [tid 19172] fpu: sample at StrategyClient::EndTurn (this=32e7aed0): cw=0x127f 53bit-double/nearest [no fpu.force configured]
09:48:20.181 [tid 19172] fpu: sample at StrategyClient::EndTurn (this=32e7f7a0): cw=0x127f 53bit-double/nearest [no fpu.force configured]
09:48:20.228 [tid 19172] fpu: sample at StrategyClient::EndTurn (this=32e7a040): cw=0x127f 53bit-double/nearest [no fpu.force configured]
09:48:21.134 [tid 19172] fpu: sample at StrategyServer::BeginProcessTurn (this=0d66ade8): cw=0x127f 53bit-double/nearest [no fpu.force configured]
09:48:21.134 [tid 19172] fpu: sample at StrategyServer::ProcessTurn (this=0d66ade8): cw=0x127f 53bit-double/nearest
09:48:21.150 [tid 19172] research: mode=replace steps=1 completions=1 overbudget=1166 cascade_possible=1 ok=1 cascade_completions=1 unlocked=3 otch_appends=1 roll_draws=0 failures=0 depth=0 name_unreadable=0
09:48:21.181 [tid 19172] research: mode=replace steps=1 completions=0 overbudget=0 cascade_possible=1 ok=1 cascade_completions=0 unlocked=0 otch_appends=0 roll_draws=0 failures=0 depth=0 name_unreadable=0
09:48:21.197 [tid 19172] research: mode=replace steps=1 completions=0 overbudget=0 cascade_possible=1 ok=1 cascade_completions=0 unlocked=0 otch_appends=0 roll_draws=0 failures=0 depth=0 name_unreadable=0

BIN
verify/traces/cr-N.jsonl.gz Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.