Files
BT412/CMakeLists.txt
T
CydandClaude Fable 5 335396912e Build: the BT412 compile gate -- one tree builds the pod game and the Steam game
option(BT412 ... ON) gates the steamification layer for the merge-back into
BT411, so the unified repo serves both fronts:

- Default (BT412=ON): pod/dev game + PadRIO / plasma / front end / lobby --
  all runtime-gated, so a -egg/-net launch still behaves as 4.11.
- Pod-minimal (-DBT412=OFF, build-pod/): compiles OUT L4PADRIO, L4PADBINDINGS,
  L4KEYLIGHT, L4PLASMASCREEN, L4STEAMTRANSPORT, btl4fe, btl4console, btl4lobby.
  Seam sites carry #ifdef BT412: L4CTRL.cpp PAD token (log + ignore), L4GREND.cpp
  L4PLASMA=SCREEN (log + ignore), L4VB16.cpp (inert PadRIO stub -- call sites
  identical in both flavors), btl4main.cpp (front-end/marshal/lobby blocks out;
  zero-arg launch = 4.11 behavior).
- The NetTransport seam ALWAYS compiles -- it is the wire for both flavors
  (WinsockNetTransport, verified byte-identical to the pre-seam arcade path).
- BT412_STEAM now requires BT412 (configure-time FATAL_ERROR; negative-tested).

Verified: OFF -- clean v143 link, solo DEV.EGG mission runs (31 subsystems
tick, gait, targeting). ON -- zero-arg launch engages the front-end menu.
STEAM -- links clean, ships steam_api.dll.

Also: README/context docs for the flavors + the merge-back; corrected the stale
Phase 3b DEFERRED note (the single-window cockpit landed 07-16) and the README's
leftover 0xBD3 valve-gate claim (it is a damage/explosion hub).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 15:45:45 -05:00

427 lines
16 KiB
CMake

cmake_minimum_required(VERSION 3.20)
project(bt412 CXX)
set(CMAKE_CXX_STANDARD 14)
# BattleTech 4.12 -- the Steamification of the BT411 pod port (Virtual World
# Entertainment pod BattleTech, Tesla rel 4.10, reconstructed on the shared
# RP411 Windows engine). Build 32-bit (Win32) -- see README.md for the exact
# configure line, docs/BT412-ROADMAP.md for the plan.
# Run from the content dir: cd content && ../build/Debug/btl4.exe -egg DEV.EGG
# --- external dependency: legacy DirectX SDK (June 2010); override with -DDXSDK=... ---
set(DXSDK "C:/Program Files (x86)/Microsoft DirectX SDK (June 2010)" CACHE PATH "Legacy DirectX SDK root")
# --- BT412 steamification layer (compile gate): PadRIO virtual cockpit input,
# desktop PlasmaScreen, KeyLight, the in-game front end + LocalConsole
# marshal + Steam lobby. ON by default -- every piece is runtime-inert on
# a pod (env/arg gated: L4CONTROLS=PAD, L4PLASMA=SCREEN, zero-arg launch).
# -DBT412=OFF builds the minimal pod image: the BT411 baseline plus the
# NetTransport seam, which is the wire for BOTH flavors (WinsockNetTransport
# default, verified byte-identical to the pre-seam arcade behavior). ---
option(BT412 "Steamification layer: PadRIO, plasma screen, front end, lobby" ON)
# --- Steam networking (internet multiplayer): OFF by default so the LAN/dev
# TCP path builds with no Steamworks dependency. ON vendors the SDK at
# extern/steamworks_sdk_164 and ships steam_api.dll. ---
option(BT412_STEAM "Build the Steam Networking Sockets transport (ISteamNetworkingSockets)" OFF)
set(STEAMWORKS "${CMAKE_SOURCE_DIR}/extern/steamworks_sdk_164/sdk" CACHE PATH "Vendored Steamworks SDK root")
if(BT412_STEAM AND NOT BT412)
message(FATAL_ERROR "BT412_STEAM requires the BT412 layer (configure with -DBT412=ON)")
endif()
set(BT_DEFS WIN32 _WINDOWS UNICODE _UNICODE NOMINMAX
_CRT_SECURE_NO_DEPRECATE _CRT_SECURE_NO_WARNINGS
_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS)
set(BT_OPTS /permissive /W0 /wd4996 /EHsc /bigobj /MP)
#===========================================================================#
# Engine: MUNGA (shared sim/render engine) + MUNGA_L4 (Win32/D3D9 HAL).
# The 2007 RP411 Windows engine, carrying our BT render/loader work
# (bgfload/L4D3D/L4VIDEO: BSL bit-slice decode, LOD/ground/shadow models).
# Include path is DXSDK + shim ONLY -- adding MUNGA dirs shadows <time.h>.
#===========================================================================#
add_library(munga_engine STATIC
"engine/MUNGA/AFFNMTRX.cpp"
"engine/MUNGA/ANGLE.cpp"
"engine/MUNGA/ANIMTOOL.cpp"
"engine/MUNGA/APP.cpp"
"engine/MUNGA/APPMGR.cpp"
"engine/MUNGA/APPMSG.cpp"
"engine/MUNGA/APPTASK.cpp"
"engine/MUNGA/AUDCMP.cpp"
"engine/MUNGA/AUDENT.cpp"
"engine/MUNGA/AUDIO.cpp"
"engine/MUNGA/AUDLOC.cpp"
"engine/MUNGA/AUDLVL.cpp"
"engine/MUNGA/AUDMIDI.cpp"
"engine/MUNGA/AUDREND.cpp"
"engine/MUNGA/AUDSEQ.cpp"
"engine/MUNGA/AUDSRC.cpp"
"engine/MUNGA/AUDTIME.cpp"
"engine/MUNGA/AUDTOOLS.cpp"
"engine/MUNGA/AUDWGT.cpp"
"engine/MUNGA/AUDWTHR.cpp"
"engine/MUNGA/AVERAGE.cpp"
"engine/MUNGA/BNDGBOX.cpp"
"engine/MUNGA/BOXCONE.cpp"
"engine/MUNGA/BOXDISKS.cpp"
"engine/MUNGA/BOXIRAMP.cpp"
"engine/MUNGA/BOXLIST.cpp"
"engine/MUNGA/BOXRAMP.cpp"
"engine/MUNGA/BOXSOLID.cpp"
"engine/MUNGA/BOXSORT.cpp"
"engine/MUNGA/BOXSPHR.cpp"
"engine/MUNGA/BOXTILE.cpp"
"engine/MUNGA/BOXTREE.cpp"
"engine/MUNGA/BOXWEDGE.cpp"
"engine/MUNGA/CAMINST.cpp"
"engine/MUNGA/CAMMGR.cpp"
"engine/MUNGA/CAMMPPR.cpp"
"engine/MUNGA/CAMSHIP.cpp"
"engine/MUNGA/CHAIN.cpp"
"engine/MUNGA/CMPNNT.cpp"
"engine/MUNGA/COLLASST.cpp"
"engine/MUNGA/COLLORGN.cpp"
"engine/MUNGA/COLOR.cpp"
"engine/MUNGA/CONSOLE.cpp"
"engine/MUNGA/CONTROLS.cpp"
"engine/MUNGA/CSTR.cpp"
"engine/MUNGA/CULTURAL.cpp"
"engine/MUNGA/DAMAGE.cpp"
"engine/MUNGA/DIRECTOR.cpp"
"engine/MUNGA/DOOR.cpp"
"engine/MUNGA/DOORFRAM.cpp"
"engine/MUNGA/DROPZONE.cpp"
"engine/MUNGA/ENTITY.cpp"
"engine/MUNGA/ENTITY2.cpp"
"engine/MUNGA/ENTITYID.cpp"
"engine/MUNGA/ENVIRNMT.cpp"
"engine/MUNGA/EVENT.cpp"
"engine/MUNGA/EVTSTAT.cpp"
"engine/MUNGA/EXPLODE.cpp"
"engine/MUNGA/EXPTBL.cpp"
"engine/MUNGA/EXTNTBOX.cpp"
"engine/MUNGA/EYECANDY.cpp"
"engine/MUNGA/FILESTRM.cpp"
"engine/MUNGA/FILESTUB.cpp"
"engine/MUNGA/FILEUTIL.cpp"
"engine/MUNGA/GAUGALRM.cpp"
"engine/MUNGA/GAUGE.cpp"
"engine/MUNGA/GAUGMAP.cpp"
"engine/MUNGA/GAUGREND.cpp"
"engine/MUNGA/GRAPH2D.cpp"
"engine/MUNGA/HASH.cpp"
"engine/MUNGA/HOST.cpp"
"engine/MUNGA/HOSTMGR.cpp"
"engine/MUNGA/ICOM.cpp"
"engine/MUNGA/INTEREST.cpp"
"engine/MUNGA/INTORGN.cpp"
"engine/MUNGA/ITERATOR.cpp"
"engine/MUNGA/JMOVER.cpp"
"engine/MUNGA/JOINT.cpp"
"engine/MUNGA/LAMP.cpp"
"engine/MUNGA/LATTICE.cpp"
"engine/MUNGA/LINE.cpp"
"engine/MUNGA/LINK.cpp"
"engine/MUNGA/LINMTRX.cpp"
"engine/MUNGA/MAPTOOL.cpp"
"engine/MUNGA/MATRIX.cpp"
"engine/MUNGA/MEMBLOCK.cpp"
"engine/MUNGA/MEMREG.cpp"
"engine/MUNGA/MEMSTRM.CPP"
"engine/MUNGA/MISSION.cpp"
"engine/MUNGA/MODE.cpp"
"engine/MUNGA/MODTOOL.cpp"
"engine/MUNGA/MOTION.cpp"
"engine/MUNGA/MOVER.cpp"
"engine/MUNGA/MTRXSTK.cpp"
"engine/MUNGA/NAMELIST.cpp"
"engine/MUNGA/NETWORK.cpp"
"engine/MUNGA/NODE.cpp"
"engine/MUNGA/NORMAL.cpp"
"engine/MUNGA/NOTATION.cpp"
"engine/MUNGA/NTTMGR.cpp"
"engine/MUNGA/OBJSTRM.cpp"
"engine/MUNGA/ORIGIN.cpp"
"engine/MUNGA/PLANE.cpp"
"engine/MUNGA/PLAYER.cpp"
"engine/MUNGA/PLUG.cpp"
"engine/MUNGA/POINT3D.cpp"
"engine/MUNGA/RANDOM.cpp"
"engine/MUNGA/RAY.cpp"
"engine/MUNGA/RECEIVER.cpp"
"engine/MUNGA/RECT2D.cpp"
"engine/MUNGA/REGISTRY.cpp"
"engine/MUNGA/RENDERER.cpp"
"engine/MUNGA/RESOURCE.cpp"
"engine/MUNGA/RETICLE.cpp"
"engine/MUNGA/RNDORGN.cpp"
"engine/MUNGA/ROTATION.cpp"
"engine/MUNGA/SCALAR.cpp"
"engine/MUNGA/SCHAIN.cpp"
"engine/MUNGA/SCNROLE.cpp"
"engine/MUNGA/SEGMENT.cpp"
"engine/MUNGA/SET.cpp"
"engine/MUNGA/SFESKT.cpp"
"engine/MUNGA/SIMULATE.cpp"
"engine/MUNGA/SLOT.cpp"
"engine/MUNGA/SOCKET.cpp"
"engine/MUNGA/SPHERE.cpp"
"engine/MUNGA/SPLINE.cpp"
"engine/MUNGA/SPOOLER.cpp"
"engine/MUNGA/SRTSKT.cpp"
"engine/MUNGA/SUBSYSTM.cpp"
"engine/MUNGA/TABLE.cpp"
"engine/MUNGA/TEAM.cpp"
"engine/MUNGA/TERRAIN.cpp"
"engine/MUNGA/TESTALL.cpp"
"engine/MUNGA/TIME.cpp"
# TIMESTUB.cpp REMOVED (2026-07-14): its GetRTC/GetHiRes were 2007 call-counter
# stubs (`return time++` -- the "clock" advanced per CALL, not per ms) that WON
# the /FORCE duplicate-symbol race over the REAL QueryPerformanceCounter clock
# in L4TIME.cpp (LNK4006 "second definition ignored"). Every Now()-domain
# consumer (dead-reckoning above all) ran on call-count pseudo-time -> the
# replicant stall/jump chop. L4TIME.cpp covers every symbol TIMESTUB defined.
"engine/MUNGA/TOOL.cpp"
"engine/MUNGA/TRACE.cpp"
"engine/MUNGA/TRACSTUB.cpp"
"engine/MUNGA/TREE.cpp"
"engine/MUNGA/UNITVEC.cpp"
"engine/MUNGA/UPDATE.cpp"
"engine/MUNGA/VCHAIN.cpp"
"engine/MUNGA/VDATA.cpp"
"engine/MUNGA/VECTOR3D.cpp"
"engine/MUNGA/VECTOR4D.cpp"
"engine/MUNGA/VERIFY.cpp"
"engine/MUNGA/VIDREND.cpp"
"engine/MUNGA/WATCHER.cpp"
"engine/MUNGA/WRHOUS.cpp"
"engine/MUNGA_L4/DXUtils.cpp"
"engine/MUNGA_L4/L4APP.cpp"
"engine/MUNGA_L4/L4AUDEFX.cpp"
"engine/MUNGA_L4/L4AUDHDW.cpp"
"engine/MUNGA_L4/L4AUDIO.cpp"
"engine/MUNGA_L4/L4AUDLVL.cpp"
"engine/MUNGA_L4/L4AUDRES.cpp"
"engine/MUNGA_L4/L4AUDRND.cpp"
"engine/MUNGA_L4/L4AUDTUL.cpp"
"engine/MUNGA_L4/L4AUDWTR.cpp"
"engine/MUNGA_L4/L4CTLTUL.cpp"
"engine/MUNGA_L4/L4CTRL.cpp"
"engine/MUNGA_L4/L4D3D.cpp"
"engine/MUNGA_L4/L4DINPUT.cpp"
"engine/MUNGA_L4/L4DPLMEM.cpp"
"engine/MUNGA_L4/L4GAUGE.cpp"
"engine/MUNGA_L4/L4GAUIMA.cpp"
"engine/MUNGA_L4/L4GAUTUL.cpp"
"engine/MUNGA_L4/L4GREND.cpp"
"engine/MUNGA_L4/L4HOST.cpp"
"engine/MUNGA_L4/L4ICOM.cpp"
"engine/MUNGA_L4/L4KEYBD.cpp"
"engine/MUNGA_L4/L4LAMP.cpp"
"engine/MUNGA_L4/L4MOUSE.cpp"
"engine/MUNGA_L4/L4MPPR.cpp"
"engine/MUNGA_L4/L4NET.CPP"
"engine/MUNGA_L4/L4NETTRANSPORT.cpp"
"engine/MUNGA_L4/L4PARTICLES.cpp"
"engine/MUNGA_L4/L4PCSPAK.cpp"
"engine/MUNGA_L4/L4PLASMA.cpp"
"engine/MUNGA_L4/L4RIO.cpp"
"engine/MUNGA_L4/L4SERIAL.cpp"
"engine/MUNGA_L4/L4SPLR.cpp"
"engine/MUNGA_L4/L4TIME.cpp"
"engine/MUNGA_L4/L4TRACE.cpp"
"engine/MUNGA_L4/L4TSTALL.cpp"
"engine/MUNGA_L4/L4VB16.cpp"
"engine/MUNGA_L4/L4VB8.cpp"
"engine/MUNGA_L4/L4VIDEO.cpp"
"engine/MUNGA_L4/L4VIDPER.cpp"
"engine/MUNGA_L4/L4VIDRND.cpp"
"engine/MUNGA_L4/L4VIDTUL.cpp"
"engine/MUNGA_L4/L4WRHOUS.cpp"
"engine/MUNGA_L4/WTPresets.cpp"
"engine/MUNGA_L4/temp.cpp"
"engine/MUNGA_L4/bgfload.cpp"
"engine/MUNGA_L4/image.cpp"
)
target_include_directories(munga_engine BEFORE PRIVATE
"${CMAKE_SOURCE_DIR}/engine/shim"
"${DXSDK}/Include")
target_compile_definitions(munga_engine PRIVATE ${BT_DEFS})
target_compile_options(munga_engine PRIVATE ${BT_OPTS})
# --- BT412 layer TUs (compile gate): PadRIO + bindings + KeyLight + the
# desktop PlasmaScreen + the Steam transport TU. The seam (L4NETTRANSPORT)
# always compiles -- it is the wire for both flavors. L4STEAMTRANSPORT.cpp
# is a no-op TU unless BT412_STEAM is also defined. ---
if(BT412)
target_sources(munga_engine PRIVATE
"engine/MUNGA_L4/L4PADBINDINGS.cpp"
"engine/MUNGA_L4/L4PADRIO.cpp"
"engine/MUNGA_L4/L4KEYLIGHT.cpp"
"engine/MUNGA_L4/L4PLASMASCREEN.cpp"
"engine/MUNGA_L4/L4STEAMTRANSPORT.cpp")
target_compile_definitions(munga_engine PRIVATE BT412)
# L4KEYLIGHT (RGB keyboard lamp mirror) is C++/WinRT: it needs C++17 and
# conformance mode, and must not include engine headers (see its header
# comment). The engine's /std:c++14 is overridden per-file; MSVC takes the
# last /std on the command line.
set_source_files_properties("engine/MUNGA_L4/L4KEYLIGHT.cpp" PROPERTIES
COMPILE_OPTIONS "/std:c++17;/permissive-")
message(STATUS "BT412: steamification layer ENABLED (PadRIO/plasma/front end/lobby)")
else()
message(STATUS "BT412: steamification layer OFF -- pod-minimal build (BT411 baseline + NetTransport seam)")
endif()
# --- Steam transport (opt-in): the engine builds /Zp1; Steam headers are
# wrapped in #pragma pack(push,8) inside the TU, so no per-file packing
# override is needed here (unlike RP412, whose /Zp1 was project-wide). ---
if(BT412_STEAM)
target_compile_definitions(munga_engine PRIVATE BT412_STEAM)
target_include_directories(munga_engine PRIVATE "${STEAMWORKS}/public")
message(STATUS "BT412: Steam Networking Sockets transport ENABLED")
endif()
#===========================================================================#
# Game logic: reconstructed BT modules + surviving-original BT source.
# Headers come from game/original/BT{,_L4} and the game/fwd shims
# (which forward <NAME.hpp> -> the engine's NAME.h).
#===========================================================================#
add_library(bt410_l4 STATIC
"game/reconstructed/ammobin.cpp"
"game/reconstructed/btdirect.cpp"
"game/reconstructed/btl4app.cpp"
"game/reconstructed/btl4galm.cpp"
"game/reconstructed/btl4gau2.cpp"
"game/reconstructed/btl4gau3.cpp"
"game/reconstructed/btl4gaug.cpp"
"game/reconstructed/btl4grnd.cpp"
"game/reconstructed/btl4mppr.cpp"
"game/reconstructed/btl4mssn.cpp"
"game/reconstructed/btl4pb.cpp"
"game/reconstructed/btl4rdr.cpp"
"game/reconstructed/btl4vid.cpp"
"game/reconstructed/btplayer.cpp"
"game/reconstructed/btvisgnd.cpp"
"game/reconstructed/dmgtable.cpp"
"game/reconstructed/emitter.cpp"
"game/reconstructed/gnrator.cpp"
"game/reconstructed/gyro.cpp"
"game/reconstructed/heat.cpp"
"game/reconstructed/heatfamily_reslice.cpp"
"game/reconstructed/hud.cpp"
"game/reconstructed/mech.cpp"
"game/reconstructed/mech2.cpp"
"game/reconstructed/mech3.cpp"
"game/reconstructed/mech4.cpp"
"game/reconstructed/mechdmg.cpp"
"game/reconstructed/mechmppr.cpp"
"game/reconstructed/mechsub.cpp"
"game/reconstructed/mechtech.cpp"
"game/reconstructed/mechweap.cpp"
"game/reconstructed/messmgr.cpp"
"game/reconstructed/mislanch.cpp"
"game/reconstructed/missile.cpp"
"game/reconstructed/misthrst.cpp"
"game/reconstructed/myomers.cpp"
"game/reconstructed/powersub.cpp"
"game/reconstructed/projtile.cpp"
"game/reconstructed/projweap.cpp"
"game/reconstructed/searchlight.cpp"
"game/reconstructed/seeker.cpp"
"game/reconstructed/sensor.cpp"
"game/reconstructed/seqctl.cpp"
"game/reconstructed/thermalsight.cpp"
"game/reconstructed/torso.cpp"
"game/reconstructed/btstubs.cpp"
"game/reconstructed/audiopresets.cpp"
"game/reconstructed/dpl2d.cpp"
"game/original/BT/BTMSSN.CPP"
"game/original/BT/BTREG.CPP"
"game/original/BT/BTTEAM.CPP"
"game/original/BT/BTSCNRL.CPP"
"game/original/BT/BTCNSL.CPP"
"game/original/BT/GAUSS.CPP"
"game/original/BT/PPC.CPP"
"game/original/BT_L4/BTL4MODE.CPP"
"game/original/BT_L4/BTL4ARND.CPP"
)
target_include_directories(bt410_l4 BEFORE PRIVATE
"${CMAKE_SOURCE_DIR}/engine/shim"
"${CMAKE_SOURCE_DIR}/game/reconstructed"
"${CMAKE_SOURCE_DIR}/game/original/BT"
"${CMAKE_SOURCE_DIR}/game/original/BT_L4"
"${CMAKE_SOURCE_DIR}/game/fwd"
"${DXSDK}/Include")
target_compile_definitions(bt410_l4 PRIVATE ${BT_DEFS})
target_compile_options(bt410_l4 PRIVATE ${BT_OPTS})
# --- BT412 layer TUs (compile gate): the front end (menu + egg builder), the
# in-process LocalConsole marshal, and the Steam lobby. ---
if(BT412)
target_sources(bt410_l4 PRIVATE
"game/reconstructed/btl4fe.cpp"
"game/reconstructed/btl4console.cpp"
"game/reconstructed/btl4lobby.cpp")
target_compile_definitions(bt410_l4 PRIVATE BT412)
endif()
# --- Steam lobby (btl4lobby.cpp) lives in this lib; under BT412_STEAM it needs
# the gate define + the Steamworks headers (wrapped #pragma pack(push,8)). ---
if(BT412_STEAM)
target_compile_definitions(bt410_l4 PRIVATE BT412_STEAM)
target_include_directories(bt410_l4 PRIVATE "${STEAMWORKS}/public")
endif()
#===========================================================================#
# Executable: btl4.exe (WinMain launcher + game lib + engine lib + D3D9/audio)
#===========================================================================#
add_executable(btl4 WIN32 "${CMAKE_SOURCE_DIR}/game/btl4main.cpp")
target_include_directories(btl4 BEFORE PRIVATE
"${CMAKE_SOURCE_DIR}/engine/shim"
"${CMAKE_SOURCE_DIR}/game/reconstructed"
"${CMAKE_SOURCE_DIR}/game/original/BT"
"${CMAKE_SOURCE_DIR}/game/original/BT_L4"
"${CMAKE_SOURCE_DIR}/game/fwd"
"${DXSDK}/Include")
target_compile_definitions(btl4 PRIVATE ${BT_DEFS})
target_compile_options(btl4 PRIVATE ${BT_OPTS})
# --- BT412 layer (compile gate): WinMain's front-end/marshal/lobby blocks. ---
if(BT412)
target_compile_definitions(btl4 PRIVATE BT412)
endif()
target_link_libraries(btl4 PRIVATE
bt410_l4
munga_engine
"${CMAKE_SOURCE_DIR}/engine/lib/OpenAL32.lib"
"${DXSDK}/Lib/x86/d3d9.lib"
"${DXSDK}/Lib/x86/d3dx9.lib"
"${DXSDK}/Lib/x86/dinput8.lib"
"${DXSDK}/Lib/x86/dxguid.lib"
"${DXSDK}/Lib/x86/DxErr.lib"
winmm dbghelp shell32 user32 gdi32 ole32 ws2_32)
# /FORCE:MULTIPLE: the 1995 headers define free funcs/globals without
# inline/extern, so identical symbols land in every TU (~124 LNK2005);
# MULTIPLE keeps the first. UNRESOLVED is gone (BT412/v143): the dead
# offline-tool factory in mech3.cpp is neutralized behind BT412_OFFLINE_TOOLS,
# so any unresolved external is now a REAL link error, not a runtime AV.
target_link_options(btl4 PRIVATE /FORCE:MULTIPLE)
# --- Steam transport (opt-in): link steam_api.lib + define the gate so the
# game-side install path compiles; ship steam_api.dll beside the exe. ---
if(BT412_STEAM)
target_compile_definitions(btl4 PRIVATE BT412_STEAM)
target_include_directories(btl4 PRIVATE "${STEAMWORKS}/public")
target_link_libraries(btl4 PRIVATE "${STEAMWORKS}/redistributable_bin/steam_api.lib")
add_custom_command(TARGET btl4 POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${STEAMWORKS}/redistributable_bin/steam_api.dll"
"$<TARGET_FILE_DIR:btl4>")
endif()
# Copy the OpenAL runtime DLL next to the built exe. (libsndfile is gone: its
# repo DLL was a no-op STUB -- L4AUDRES now loads the soundbank WAVs with an
# in-tree RIFF/PCM reader, no external dependency.)
add_custom_command(TARGET btl4 POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${CMAKE_SOURCE_DIR}/engine/lib/OpenAL32.dll"
"$<TARGET_FILE_DIR:btl4>")