The boundary ledger says which phase spends a turn's words; this says which call site. Each entry point is detoured with its verified prototype and records __builtin_return_address(0) plus the word cost from left before/after -- two 4-byte reads, no record per draw, since NextFloat alone has 109 call sites. Each draw is tagged with WHICH generator it came from. That is not a detail: the first build counted every Mars::RNG instance in the process and reported 44 words against a bracket of 18. The StrategyClient's generator at +0x134 draws 8 times a turn and must not be in the strategic total. Also hooks EncounterDetect::AssignContacts, lane I's one inlined-draw site in ProcessTurn's closure -- invisible to both a call-graph sweep and to the entry- point detours, so only a boundary hook can see it. It did not fire on this workload, which is consistent with the site sums reconciling exactly.
125 lines
7.1 KiB
CMake
125 lines
7.1 KiB
CMake
cmake_minimum_required(VERSION 3.25)
|
|
project(sots-engine LANGUAGES C CXX)
|
|
|
|
set(CMAKE_CXX_STANDARD 17)
|
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
|
|
|
# Build id stamped into the shim log banner (tools/build-shim.sh passes git describe + UTC time).
|
|
set(SHIM_BUILD_ID "dev" CACHE STRING "Build identifier logged by the shim")
|
|
|
|
# Provenance of the binary facts: the generated header's own "Source:" line, forwarded verbatim
|
|
# so every shim.log records which RE snapshot the RVAs came from.
|
|
file(STRINGS include/generated/sots_addresses.h _addr_provenance REGEX "^// Source:")
|
|
list(GET _addr_provenance 0 _addr_provenance)
|
|
string(REGEX REPLACE "^// " "" SOTS_ADDR_PROVENANCE "${_addr_provenance}")
|
|
|
|
add_library(sots_addresses INTERFACE)
|
|
target_include_directories(sots_addresses INTERFACE ${CMAKE_SOURCE_DIR}/include)
|
|
|
|
# ---- engine modules (host + cross): pure, oracle-verified code accrues here ----
|
|
add_subdirectory(src/mars/parse) # brace-block + .effect readers (lib mars_parse)
|
|
add_subdirectory(src/mars/text) # flat-kv, id-manifest, csv (lib mars_text)
|
|
add_subdirectory(src/game/sim) # strategic formulas, pure (lib sots_game_sim)
|
|
add_subdirectory(src/mars/vfs) # .gob ZIP reader + native override (lib mars_vfs, miniz)
|
|
add_subdirectory(src/mars/stream) # Streamable save format + gzip (lib mars_stream)
|
|
add_subdirectory(src/mars/rng) # MT19937 (lib mars_rng)
|
|
add_subdirectory(src/game/config) # flat KEY/value constants loader (lib sots_game_config)
|
|
add_subdirectory(src/game/data) # typed catalogs on mars/parse+text (lib game_data)
|
|
add_subdirectory(src/game/effects) # tech effects (TechId table + apply) (lib game_effects)
|
|
add_subdirectory(src/game/design) # ship-design rules + derived stats (lib game_design)
|
|
add_subdirectory(src/game/events) # player event log + research events (lib sots_game_events)
|
|
|
|
# ---- shim trace/compare infrastructure (host-testable; linked into binkw32) ----
|
|
add_library(shim_trace STATIC
|
|
src/shim/trace/sha256.cpp
|
|
src/shim/trace/emitter.cpp
|
|
src/shim/trace/tracer.cpp
|
|
src/shim/trace/selftest.cpp)
|
|
target_include_directories(shim_trace PUBLIC ${CMAKE_SOURCE_DIR}/src)
|
|
target_compile_options(shim_trace PRIVATE -Wall -Wextra -Werror)
|
|
if(MINGW)
|
|
target_compile_definitions(shim_trace PUBLIC __USE_MINGW_ANSI_STDIO=1) # C99 %lld/%.17g
|
|
endif()
|
|
|
|
# ---- B1 budget adapter: ServerPlayer snapshot <-> game::sim economy (pure, host-tested) ----
|
|
add_library(shim_budget STATIC src/shim/hooks/budget_inputs.cpp)
|
|
target_link_libraries(shim_budget PUBLIC shim_trace sots_game_sim)
|
|
target_compile_options(shim_budget PRIVATE -Wall -Wextra -Werror)
|
|
|
|
# ---- B2 tech-effect adapter: ServerPlayer fields <-> game::effects state (pure, host-tested) ----
|
|
add_library(shim_techfx STATIC src/shim/hooks/tech_effect_fields.cpp)
|
|
target_link_libraries(shim_techfx PUBLIC shim_trace sots_addresses sots_game_effects)
|
|
target_compile_options(shim_techfx PRIVATE -Wall -Wextra -Werror)
|
|
|
|
# ---- B4 colony adapter: ServerSystem snapshot <-> game::sim colony turn (pure, host-tested) ----
|
|
add_library(shim_colony STATIC src/shim/hooks/colony_inputs.cpp)
|
|
target_link_libraries(shim_colony PUBLIC shim_trace sots_game_sim)
|
|
target_compile_options(shim_colony PRIVATE -Wall -Wextra -Werror)
|
|
|
|
# ---- B4 movement adapter: StarFleet snapshot <-> game::sim movement (pure, host-tested) ----
|
|
add_library(shim_movement STATIC src/shim/hooks/movement_inputs.cpp)
|
|
target_link_libraries(shim_movement PUBLIC shim_trace sots_game_sim)
|
|
target_compile_options(shim_movement PRIVATE -Wall -Wextra -Werror)
|
|
|
|
# ---- T turn-driver adapter: ServerPlayer snapshot <-> the driver's own writes (pure, host-tested) ----
|
|
add_library(shim_player_turn STATIC src/shim/hooks/player_turn_inputs.cpp)
|
|
target_link_libraries(shim_player_turn PUBLIC shim_trace)
|
|
target_compile_options(shim_player_turn PRIVATE -Wall -Wextra -Werror)
|
|
|
|
# ---- P events adapter: live Game::EventStorage <-> sots::events model (pure, host-tested) ----
|
|
add_library(shim_events STATIC src/shim/hooks/event_inputs.cpp)
|
|
target_link_libraries(shim_events PUBLIC shim_trace sots_addresses sots_game_events)
|
|
target_compile_options(shim_events PRIVATE -Wall -Wextra -Werror)
|
|
|
|
# ---- shim: the strategic RNG word ledger (lane Z) -- absolute generator position recovered
|
|
# from (mt[624], left) alone, so a turn's RNG cost can be attributed to a phase without
|
|
# hooking a single RNG primitive. Host-testable; linked into the hook descriptors below.
|
|
add_library(shim_rng_ledger STATIC src/shim/hooks/rng_ledger.cpp)
|
|
target_link_libraries(shim_rng_ledger PUBLIC shim_trace sots_addresses mars_rng)
|
|
target_compile_options(shim_rng_ledger PRIVATE -Wall -Wextra -Werror)
|
|
|
|
if(WIN32)
|
|
# ---- shim: proxy binkw32.dll that the original game loads (Phase 2 frontend) ----
|
|
add_library(minhook STATIC
|
|
third_party/minhook/src/buffer.c
|
|
third_party/minhook/src/hook.c
|
|
third_party/minhook/src/trampoline.c
|
|
third_party/minhook/src/hde/hde32.c)
|
|
target_include_directories(minhook PUBLIC third_party/minhook/include)
|
|
|
|
# ---- hooks: one descriptor per hooked game function (src/shim/hooks/*) ----
|
|
add_library(shim_hooks STATIC src/shim/hooks/global_consts.cpp src/shim/hooks/dictionaries.cpp
|
|
src/shim/hooks/research.cpp
|
|
src/shim/hooks/tech_effects.cpp
|
|
src/shim/hooks/compute_budget.cpp
|
|
src/shim/hooks/colony_turn.cpp
|
|
src/shim/hooks/fleet_movement.cpp
|
|
src/shim/hooks/player_turn.cpp
|
|
src/shim/hooks/tail_rng.cpp
|
|
src/shim/hooks/draw_sites.cpp)
|
|
target_link_libraries(shim_hooks PUBLIC shim_trace sots_addresses sots_game_config sots_game_sim
|
|
sots_game_effects mars_rng shim_budget shim_techfx
|
|
shim_colony shim_movement shim_events
|
|
shim_player_turn shim_rng_ledger)
|
|
target_compile_options(shim_hooks PRIVATE -Wall -Wextra -Werror)
|
|
|
|
add_library(binkw32 SHARED src/shim/main.cpp src/shim/fpu_force.cpp src/shim/binkw32.def)
|
|
target_link_libraries(binkw32 PRIVATE minhook sots_addresses shim_trace shim_hooks)
|
|
target_compile_definitions(binkw32 PRIVATE
|
|
SHIM_BUILD_ID="${SHIM_BUILD_ID}"
|
|
SOTS_ADDR_PROVENANCE="${SOTS_ADDR_PROVENANCE}")
|
|
# Must be exactly binkw32.dll (no "lib" prefix); export names come solely from the .def.
|
|
set_target_properties(binkw32 PROPERTIES PREFIX "" OUTPUT_NAME "binkw32")
|
|
else()
|
|
# ---- host: engine module tests (ctest) + a header smoke test ----
|
|
enable_testing()
|
|
add_executable(addr_smoke tests/addr_smoke.cpp)
|
|
target_link_libraries(addr_smoke PRIVATE sots_addresses)
|
|
add_test(NAME addr_smoke COMMAND addr_smoke)
|
|
foreach(_t mars_parse game_config game_data game_design game_sim mars_stream mars_text mars_vfs shim_trace game_effects game_events shim_budget shim_techfx shim_colony shim_movement shim_events shim_player_turn shim_rng_ledger)
|
|
if(EXISTS ${CMAKE_SOURCE_DIR}/tests/${_t}/CMakeLists.txt)
|
|
add_subdirectory(tests/${_t})
|
|
endif()
|
|
endforeach()
|
|
endif()
|