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 dd105da759 SD: a sub-bracket on the ship-design composer 0x006ad700
Extends lane PAR's airng module with a detour on the composer itself, so a
row says what ONE COMPOSER CALL spent rather than what the turn spent.

Three pieces:

  * the detour. The composer's calling convention is neither cdecl nor MSVC
    __fastcall -- two register arguments, two stack arguments, and the CALLER
    cleans -- so it is entered through a hand-written thunk that re-pushes the
    four arguments as cdecl, and the trampoline is re-entered through a second
    thunk that restores ECX/EDX.

  * the sub-bracket. left (RNG+0x9c8) read off the client generator at composer
    entry and exit, and the draws seen in between re-tallied by return address.
    Two independent numbers per row, printed together, because PAR's own
    instrument double-counted a word and only its second measurement caught it.

  * cl_Chance's note is now taken AFTER the trampoline, so a row carries the
    DECISION as well as the call. Site 0x006ae413's 0.3 coin selects the
    fraction that governs the loop-carried draw's trip count, and a call count
    alone cannot say which way it went.

The row also carries the model's prediction beside the measurement: N, the
per-section bank counts and the PointDefence flags are read off the design the
call produced, L is computed from them, and the row says HOLDS, WRONG, or
GATED-OR-WRONG when the prediction is positive and the measurement is zero --
which is the weapon-lookup gate, and is not counted as a confirmation.

Header regenerated from ghidra/addresses.json plus the fragments, never
hand-resolved; the six new lane-sd entries do not change any existing constant
and the module uses none of them by name.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ARBgSooAfokKUy6wKUKEyZ
2026-09-08 20:30: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 SD: predictions for the ship-design composer, written before the build 2026-09-08 20:08:40 -04:00
include/generated SD: a sub-bracket on the ship-design composer 0x006ad700 2026-09-08 20:30:22 -04:00
src SD: a sub-bracket on the ship-design composer 0x006ad700 2026-09-08 20:30:22 -04:00
tests merge lane RB: --turn-commands replay (game_ai test list union-resolved; header regenerated) 2026-09-08 19:08:34 -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 PAR: roll parity -- the AI's per-turn RNG word count is NOT fixed, at any scope 2026-09-08 19:32:19 -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: note uv tool install cmake as the local workaround 2026-09-08 09:07:47 -04:00
LICENSE init commit 2026-09-07 17:07:54 -04:00
README.md src/app: the standalone -- load a save, run a turn, write a save 2026-09-08 10:35:45 -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
  • app — the standalone: sots_turn loads a save, runs one strategic turn over the published phase order of all three turn drivers, and writes a save. 14 of the 44 turn-driver phases are modelled; every phase that is not appears in the run log as a named no-op. How far it is from the byte-match, and what stands in the way, is in docs/S-standalone.md

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)
  • src/app/ — the standalone turn driver (frontend #2): load a save, run a turn, write a save
  • 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).