cmake_minimum_required(VERSION 3.20)

# ============================================================================
# Marvel vs. Capcom 2 (Original Xbox, NTSC-U) - static recompilation, Windows x64
#
# Builds mvc2_recomp.exe from the recompiled game code in src/recomp/gen (generated by
# scripts/regen.ps1, not stored in git), the hand-written glue in src/, and the xboxrecomp
# toolkit (commit f0f8a46 plus patches/0001-0005 and 0007-0022, in order). XBOXRECOMP_DIR below points
# at the toolkit checkout. See README.md for the full build steps.
# ============================================================================

project(mvc2_recomp C)

set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)

# Player release build, in its own directory: cmake -S . -B build_release -DMVC2_RELEASE=ON
# Game files next to the exe (game_files), saves and settings in %LOCALAPPDATA%\MvC2Recomp, RECOMP_* from outside ignored,
# C runtime linked in so a player needs no Visual C++ redistributable. Adds the importer and config.exe.
option(MVC2_RELEASE "Player release build" OFF)
if(MVC2_RELEASE)
    if(MSVC)
        set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded")
    endif()
    add_compile_definitions(MVC2_RELEASE=1)
    # Symbols for every release, kept on the build PC and never shipped: a player's freeze or crash report gives code
    # offsets, and scripts/symbolize_log.py names them with this .pdb (build_installer.py copies it to out/symbols).
    # /OPT:REF and /OPT:ICF keep the code the same as without /DEBUG. The game's /PDBALTPATH is set on its target below.
    if(MSVC)
        string(APPEND CMAKE_C_FLAGS_RELEASE " /Zi /FS")
        string(APPEND CMAKE_CXX_FLAGS_RELEASE " /Zi /FS")
        string(APPEND CMAKE_EXE_LINKER_FLAGS_RELEASE " /DEBUG /OPT:REF /OPT:ICF")
    endif()
endif()

# Common definitions
add_compile_definitions(
    WIN32_LEAN_AND_MEAN
    NOMINMAX
)

# ── xboxrecomp toolkit ──────────────────────────────────────────
#
# Option A: xboxrecomp as a subdirectory (simplest)
#   Place xboxrecomp/ next to your game project and use a relative path.
#
# Option B: find_package (if you install xboxrecomp system-wide)
#   find_package(xboxrecomp REQUIRED)
#
# Adjust this path to point to your xboxrecomp clone:
set(XBOXRECOMP_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../tools/xboxrecomp" CACHE PATH
    "Path to the xboxrecomp toolkit root directory")

# Add xboxrecomp as a subdirectory -- this builds all 6 runtime libraries
# and provides the 'xboxrecomp' umbrella target to link against.
add_subdirectory(${XBOXRECOMP_DIR} ${CMAKE_BINARY_DIR}/xboxrecomp)

# ── Recompiled game executable ──────────────────────────────────

# Collect generated recompiled code.
# The recomp pipeline outputs files into src/recomp/gen/.
# With --split 1000, you get gen_0000.c, gen_0001.c, etc.
# CONFIGURE_DEPENDS so re-running the recompiler picks up added/removed files
# without a manual re-configure. A plain GLOB is evaluated once at configure
# time, so a newly generated file (an extra chunk, recomp_stubs_unresolved.c)
# is silently left out of the build and shows up as unresolved externals.
file(GLOB RECOMP_GEN_SOURCES CONFIGURE_DEPENDS "src/recomp/gen/*.c")

# Core game sources
set(GAME_SOURCES
    src/main.c
    src/recomp_manual.c
    src/gpu_backend.c
    src/mvc2_overlay.c
    src/mvc2_keymap.c
    src/mvc2_diag.c
    src/sprite_filter.c
    # Add game-specific sources here, e.g.:
    # src/asset_loader.c
    # src/custom_renderer.c
)

# The recomp pipeline also generates a dispatch header and function declarations.
# These are included by the generated .c files:
#   src/recomp/gen/recomp_funcs.h    - extern declarations for all recompiled functions
#   src/recomp/recomp_dispatch.h     - binary search dispatch table
#   src/recomp/recomp_types.h        - register model, ICALL macros, MEM helpers

enable_language(RC)
add_executable(${PROJECT_NAME} WIN32
    ${GAME_SOURCES}
    ${RECOMP_GEN_SOURCES}
    resources/mvc2.rc
)

# Link against the xboxrecomp umbrella target (all 6 runtime libraries)
target_link_libraries(${PROJECT_NAME} PRIVATE xboxrecomp)

# Include paths for generated recomp headers
target_include_directories(${PROJECT_NAME} PRIVATE
    ${CMAKE_CURRENT_SOURCE_DIR}/src
    ${CMAKE_CURRENT_SOURCE_DIR}/src/recomp
    ${XBOXRECOMP_DIR}/include
    ${XBOXRECOMP_DIR}/src
)

# Windows SDK libraries needed at link time
target_link_libraries(${PROJECT_NAME} PRIVATE
    d3d11
    d3dcompiler
    windowscodecs
    ole32
    dxgi
    dxguid
    $<IF:$<BOOL:${MINGW}>,xinput1_4,xinput>   # see src/input/CMakeLists.txt
    winmm
    # Lets the fault handler resolve the host RIP back to the generated
    # function's symbol, i.e. to the guest function that faulted.
    dbghelp
)

# MSVC-specific: large address aware, increase section limit for big generated files
if(MSVC)
    target_link_options(${PROJECT_NAME} PRIVATE
        /LARGEADDRESSAWARE
    )
    # The generated code files can be very large. Increase object file section limit.
    target_compile_options(${PROJECT_NAME} PRIVATE $<$<COMPILE_LANGUAGE:C>:/bigobj>)
    # The exe names its .pdb without the build folder (%_PDB% does not survive MSBuild's escaping).
    if(MVC2_RELEASE)
        target_link_options(${PROJECT_NAME} PRIVATE /PDBALTPATH:mvc2_recomp.pdb)
    endif()
endif()

# ── Debug flavour: the xrdbg self-monitoring kit (tools/xrdbg) ───
#
# OFF by default and never for a release. Build it in its own directory:
#   cmake -S . -B build_debug -DMVC2_DEBUGKIT=ON
#   cmake --build build_debug --config Release
# It adds the kit + src/mvc2_debug.c, defines XRDBG (turns MVC2_DEBUG_* / XRDBG_* on), links dbghelp/psapi/shell32 and
# keeps a PDB (crash dumps are only readable with the exact exe + PDB pair: keep both for any build given to a player).
# Log, dumps and mark screenshots go to %LOCALAPPDATA%\MvC2Recomp\debug; the kit is not part of this repo.
option(MVC2_DEBUGKIT "Debug build with the xrdbg self-monitoring kit" OFF)
option(MVC2_SAVE_STATES "F6/F9 save states (kit: tools/xrdbg/xboxrecomp)" OFF)
if(MVC2_SAVE_STATES AND NOT MVC2_DEBUGKIT)
    message(FATAL_ERROR "MVC2_SAVE_STATES requires MVC2_DEBUGKIT=ON")
endif()
if(MVC2_DEBUGKIT)
    if(NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/tools/xrdbg/cmake/xrdbg.cmake)
        message(FATAL_ERROR "MVC2_DEBUGKIT needs the xrdbg debug kit in tools/xrdbg, which is not part of this repo")
    endif()
    include(${CMAKE_CURRENT_SOURCE_DIR}/tools/xrdbg/cmake/xrdbg.cmake)
    # Buffered log, flushed by the kit every 200 ms: this title logs heavily from the GPU thread the game waits on.
    if(MVC2_SAVE_STATES)
        xrdbg_enable(${PROJECT_NAME} STDERR_BUFFER 65536 SAVE_STATES)
        include(tools/xrdbg/xboxrecomp/cmake/xrx_state.cmake)
        xrx_state_enable(${PROJECT_NAME})
        include(CTest)
        if(BUILD_TESTING)
            add_executable(xrx_state_test tools/xrdbg/xboxrecomp/tests/xrx_state_test.c tools/xrdbg/src/xrdbg_state.c)
            target_include_directories(xrx_state_test PRIVATE tools/xrdbg/include tools/xrdbg/xboxrecomp/include)
            target_compile_definitions(xrx_state_test PRIVATE XRDBG=1)
            target_link_libraries(xrx_state_test PRIVATE user32)
            add_test(NAME xrx_state COMMAND xrx_state_test)
            add_test(NAME xrx_runtime_generation COMMAND "${Python3_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/tools/xrdbg/xboxrecomp/tests/runtime_generation_test.py" "${XBOXRECOMP_DIR}")
        endif()
        set_property(SOURCE src/mvc2_debug.c src/gpu_backend.c APPEND PROPERTY COMPILE_DEFINITIONS MVC2_SAVE_STATES=1)
    else()
        xrdbg_enable(${PROJECT_NAME} STDERR_BUFFER 65536)
    endif()
    target_sources(${PROJECT_NAME} PRIVATE src/mvc2_debug.c src/mvc2_watch.c)
endif()

if(MVC2_RELEASE)
    if(MVC2_DEBUGKIT)
        message(FATAL_ERROR "MVC2_RELEASE and MVC2_DEBUGKIT are separate builds")
    endif()
    add_executable(mvc2_import installer/mvc2_import.c)
    target_link_libraries(mvc2_import PRIVATE bcrypt shell32)
    add_executable(mvc2_config WIN32 installer/config.c resources/config.rc)
    target_include_directories(mvc2_config PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
    target_link_libraries(mvc2_config PRIVATE comctl32 user32 gdi32 shell32 version advapi32)
    set_target_properties(mvc2_config PROPERTIES OUTPUT_NAME config)
    # The installers' download helper for the hi-res texture pack (not installed; Setup runs it from its temp folder).
    add_executable(mvc2_texture_download installer/texture_download.c)
    target_link_libraries(mvc2_texture_download PRIVATE winhttp bcrypt shell32)
endif()

# ── Game-specific additions ─────────────────────────────────────
#
# Add any game-specific libraries, loaders, or custom renderers below.
# Examples:
#
# # Custom texture loader for your game's format
# target_sources(${PROJECT_NAME} PRIVATE src/texture_loader.c)
#
# # If your game uses RenderWare, you may need a RW bridge layer
# target_sources(${PROJECT_NAME} PRIVATE src/rw_bridge.c)
#
# # Additional compile definitions for debugging
# target_compile_definitions(${PROJECT_NAME} PRIVATE
#     ENABLE_ICALL_TRACE=1
#     VERBOSE_KERNEL_LOG=1
# )
