From-scratch reimplementation of the Sword of the Stars (2006) engine. Clean-room; engine code only — bring your own game copy. Planning/RE evidence live in sots-re.
Find a file
alex 410f980832 V: live verification of lane P's event posting; the advance prediction held
Ran the queued VM140 verification of docs/P-events-wiring.md §4 with main dd38117
unchanged, cross-built on CT111 as eventlive-dd38117-20260908T0916Z and staged to
C:\SOTS\shimdist-v.

First End Turn on shim.cfg.recapb3 unchanged: 3 calls, 3 compared, 0 divergent,
tracecmp exit 0. Every field lane P forecast for call 0 read as predicted, including
turn=3, events_turn_bucket_exists=true, events_dedup_risk=0, next_id 3->4 on both
sides and observed_techs.bytes unchanged on all three calls.

Five End Turns: exit 1 with two divergent calls instead of three, both short by
exactly one id (7/6 and 12/11) — the unmodelled EVENT_TECHS_UNLOCKED, at the size
lane P said it would be.

sizeof(Game::ObservedTech) measured live at 44 on both completion calls
(observed_techs.bytes 440->484 and 484->528), confirming a static pin behaviourally.
That confirmation was written into the RE repo's addresses.json and has already
reached the generated header on main, so this branch carries docs only.

One deviation from lane R: rng diverged on call 9 because the completed tech had
research_roll_pending set, so the OnTechResearched callback drew one word ours does
not. That is a declared out-of-scope boundary, and it means lane R's "RNG 15/15" was
workload luck rather than a property of the hook.

Also closed the Zuul double roll behaviourally on a species-5 save made for the
purpose: 8 calls, 0 divergent, and all four species-5 researching calls advance the
generator by two with ours matching bit-for-bit.

clean_room_check.sh OK; host ctest 33/33. Run as separate commands.
2026-09-08 06:00:01 -04:00
cmake m0: binkw32 proxy shim, minhook, trace hook on Application::Initialize; build/deploy tooling 2026-09-07 17:22:15 -04:00
docs V: live verification of lane P's event posting; the advance prediction held 2026-09-08 06:00:01 -04:00
include/generated sync generated header (414 entries) after strings merge 2026-09-08 05:13:20 -04:00
src merge lane S: std::string is 0x1c confirmed (one layout); ObservedTech fully mapped from serializer enumeration 2026-09-08 05:11:50 -04:00
tests Merge branch 'main' into wip/post-events 2026-09-08 04:17:35 -04:00
third_party mars/vfs: gob ZIP reader + native override, miniz 3.1.2; oracle-verified 8352+2035 entries 2026-09-07 17:40:51 -04:00
tools b4: colony + movement hooks; 22 formula corrections (growth curve has no capacity term, range margin +0.05f, ties-to-even rounding); 3 verified signatures 2026-09-08 00:57:55 -04:00
.gitignore init commit 2026-09-07 17:07:54 -04:00
CMakeLists.txt merge lane F: x87 control-word sensitivity - 53-bit and 64-bit identical; 24-bit and round-up each move 2 named leaves 2026-09-08 05:10:21 -04:00
CMakePresets.json m0: binkw32 proxy shim, minhook, trace hook on Application::Initialize; build/deploy tooling 2026-09-07 17:22:15 -04:00
CONTRIBUTING.md CONTRIBUTING: cmake >=3.25 requirement and the uv workaround 2026-09-08 05:13:31 -04:00
LICENSE init commit 2026-09-07 17:07:54 -04:00
README.md b3: research hook + RNG-snapshot compare design; fix draw mapping to y/(2^32-1), NextInt inclusive, float32 odds, spend floor, decay constants 2026-09-07 23:14:08 -04:00

sots-engine

A from-scratch, functional reimplementation of the engine behind Sword of the Stars (2006). Not a byte-for-byte decompilation: behavior-equivalent code, built up one verified piece at a time (OpenRCT2-style) until the tree can build the whole application on its own.

Bring your own game. This repository contains engine code only. Game data, assets, saves, and the original binaries are never included; tests and tools read an owner-supplied copy via $SOTS_DATA_DIR. See CONTRIBUTING.md for the clean-room rules.

Status

Phase 2. M0 done — the shim frontend (src/shim/, a proxy binkw32.dll the original game loads) builds, deploys, hooks, and logs from a real game launch. Engine code accrues under src/mars/ and src/game/; each module is oracle-verified against the owner's game data before merge:

  • mars/parse — brace-block + .effect readers (1,531/1,531 files agree with the reference)
  • mars/text — flat key/value tables, id manifests, CSV (64/64 files agree)
  • game/sim — strategic formulas (economy, research, colonies, movement) as pure functions; 356 hand-computed checks
  • mars/vfs — .gob (ZIP) archive reader + loose-file override; entry counts and bytes verified against unzip
  • mars/stream — the game's self-describing save/serialization format (reader, writer, typed shapes) + gzip; three real saves round-trip byte-identical
  • mars/rng — MT19937 with save-state load/store; layout confirmed against real saves, draw mappings read off the binary (docs/mars-rng.md)
  • game/data — typed catalogs (weapons, ship sections, turrets, id registries, tech tree, strings) with cross-reference checks; 229k values agree with the reference
  • game/design — ship-design assembly/fit/tech-gating rules and derived stats; validates all 127 stock designs from real saves

Build: cmake --preset host && cmake --build --preset host && ctest --preset host (Linux); tools/sync-build.sh cross-builds the shim on the lab box and stages it for deployment.

Layout (grows with the work)

  • src/shim/ — binkw32 proxy + hooks + old-vs-new compare harness (frontend #1)
  • src/mars/, src/game/ — the engine and game reimplementation (accruing)
  • include/generated/sots_addresses.h — binary facts (RVAs/prototypes), generated from the RE repo
  • tests/ — host tests; real-data tests skip unless $SOTS_DATA_DIR is set
  • tools/ — build (MinGW i686 cross) and deploy scripts

Planning, findings, and verification evidence are tracked in the private RE repo (sots-re).