rrt/README.md

4.3 KiB

Analysis and reimplementation of Railroad Tycoon 3

The old executable is at ./rt3_wineprefix/drive_c/rt3/RT3.exe

Our first task is to understand the executable's high-level control loops and subsystem boundaries well enough to choose good rewrite targets. As we go, we document evidence, keep a curated function map, and stand up Rust tooling that can validate artifacts and later host replacement code.

The long-term direction is still a DLL we can inject into the original executable, patching in individual functions as we build them out. The active implementation milestone is now a headless runtime rehost layer that can execute deterministic world work, compare normalized state, and grow subsystem breadth without depending on the shell or presentation path. The current packed-event frontier is broader real grouped-descriptor coverage on top of the existing save-slice, snapshot, overlay-import, compact-control, and symbolic company-target workflows. The runtime already carries selected-company and controller-role context through overlay imports, and real descriptors 2 Company Cash, 13 Deactivate Company, and 16 Company Track Pieces Buildable now parse and execute through the ordinary runtime path, and descriptor 1 Player Cash now joins that batch through the same service engine. Synthetic packed records still exercise the same runtime without a parallel packed executor. The first grounded condition-side unlock now exists for negative-sentinel raw_condition_id = -1 company scopes, and the first ordinary nonnegative condition batch now executes too: numeric-threshold company finance, company track, aggregate territory track, and company-territory track rows can import through overlay-backed runtime context. Exact named-territory binding now executes, and the runtime now also carries the minimal event-owned train roster and opaque economic-status lane needed for real descriptors 8 Economic Status, 9 Confiscate All, and 15 Retire Train to execute through the same path. Descriptor 3 Territory - Allow All now executes too, reinterpreted as company-to-territory access rights rather than a territory-owned policy bit. Whole-game ordinary-condition execution now exists too: special-condition thresholds, candidate-availability thresholds, and economic-status-code thresholds now gate imported runtime records through the same service path, with explicit unmapped world-condition and world-descriptor frontier buckets where current checked-in metadata still stops. Shell purchase-flow and selected-profile parity remain out of scope. Mixed supported/unsupported real rows still stay parity-only. The PE32 hook remains useful as capture and integration tooling, but it is no longer the main execution milestone.

Project Docs

Bootstrap design and workflow documents live in docs/.

  • docs/README.md: handbook index and target hashes
  • docs/control-loop-atlas.md: compatibility index for the split atlas
  • docs/control-loop-atlas/: canonical atlas section files
  • docs/setup-workstation.md: toolchain baseline and local setup
  • docs/re-workflow.md: repeatable reverse-engineering workflow
  • docs/function-map.md: canonical function-map schema and conventions

The first committed exports for the canonical 1.06 executable live in artifacts/exports/rt3-1.06/.

Rust Workspace

The Rust workspace is split into focused crates:

  • rrt-model: shared types for addresses, function-map rows, and control-loop concepts
  • rrt-runtime: headless runtime state, stepping, normalized event service, and persistence-facing runtime types
  • rrt-fixtures: fixture schemas, loading, normalization, and diff helpers for rehost validation
  • rrt-cli: validation, runtime fixture execution, state-diff tools, and repo-health checks
  • rrt-hook: minimal Windows DLL scaffold for low-risk in-process loading, capture, and later integration experiments under Wine

For the current headless runtime smoke path, use cargo run -p rrt-cli -- runtime summarize-fixture fixtures/runtime/minimal-world-step-smoke.json or one of the broader runtime fixtures under fixtures/runtime/.

For the current hook smoke test, run tools/run_hook_smoke_test.sh. It builds the PE32 proxy, copies it into the local RT3 install, launches the game briefly under Wine with WINEDLLOVERRIDES=dinput8=n,b, and expects rrt_hook_attach.log to appear.