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
lane P f3c6d551de lane P: post the research events from ours (count-only), declare ObservedTech
TechTree::ProcessResearch's events region now compares a modelled value instead of
reporting a known defect. ours posts the pass's events into its own
sots::events::EventStorage, seeded from a scan of the owner's list taken BEFORE the
original runs, and writes only the counts into the region's scratch copy. The game's
PostEvent is never called and no live byte moves; replace mode still posts nothing,
because a bumped EvNxID with no record behind it would corrupt the oracle's save.

- game/events: PostResearchPassEvents (the decision half, pure) + KeylessEventText
- shim/hooks/event_inputs (new lib shim_events, host-tested): the live<->model adapter,
  carrying game pointers as explicit uint32 so a 64-bit host build cannot alias them
- research hook: the wiring, a new observed_techs region for ServerPlayer+0x274, and
  turn / events_next_id_in / events_dedup_risk in the args so the count model's own
  assumption is measured rather than assumed
- EVENT_TECHS_UNLOCKED is NOT posted: its trigger is pinned but needs SetResearched's
  unlock cascade, which ours does not run. The driver takes the unlock list as an input
  and is handed 'no list', so a missing input cannot look like a modelled negative.
  Predicted residual: next_id short by exactly 1 on a completion call.

ctest 33/33 (shim_events_unit is new), clean_room_check OK. The shim TU is
syntax-checked only: no MinGW cross toolchain on this box.

See docs/P-events-wiring.md for the exact prediction for the next VM run.
2026-09-08 04:16:22 -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 lane P: post the research events from ours (count-only), declare ObservedTech 2026-09-08 04:16:22 -04:00
include/generated lane P: post the research events from ours (count-only), declare ObservedTech 2026-09-08 04:16:22 -04:00
src lane P: post the research events from ours (count-only), declare ObservedTech 2026-09-08 04:16:22 -04:00
tests lane P: post the research events from ours (count-only), declare ObservedTech 2026-09-08 04:16:22 -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 lane P: post the research events from ours (count-only), declare ObservedTech 2026-09-08 04:16:22 -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 init commit 2026-09-07 17:07:54 -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).