cmake_minimum_required(VERSION 3.20) project(bt411 CXX) set(CMAKE_CXX_STANDARD 14) # BattleTech 4.11 -- Virtual World Entertainment pod BattleTech (Tesla rel 4.10) # reconstructed on the shared RP411 Windows engine. Build 32-bit (Win32) with # the VS2019 BuildTools instance -- see README.md for the exact configure line. # 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") 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 . #===========================================================================# 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/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/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}) #===========================================================================# # Game logic: reconstructed BT modules + surviving-original BT source. # Headers come from game/original/BT{,_L4} and the game/fwd shims # (which forward -> 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}) #===========================================================================# # 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}) 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: the 1995 headers define free funcs/globals without inline/extern, so # identical symbols land in every TU (~124 LNK2005); MULTIPLE keeps the first. # UNRESOLVED tolerates the dead offline-tool factory in mech3.cpp. See docs. target_link_options(btl4 PRIVATE /FORCE) # 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" "$")