cmake_minimum_required(VERSION 3.20)

# ============================================================================
# Spyro: A Hero's Tail (Xbox) - Static Recompilation
#
# Copy this template to your game project root and customize:
#   1. Change the project name below
#   2. Set XBOXRECOMP_DIR to where you cloned xboxrecomp
#   3. Adjust source file lists as you add game-specific code
#   4. Add any game-specific compile definitions or link libraries
# ============================================================================

project(spyro_aht_recomp C RC)

set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)

# The C runtime linked in, so the release runs without the Visual C++
# Redistributable installed. Set before any target, the toolkit's included.
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded")

# 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}/../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.
# One game executable per edition (src/edition.h): each is the recompilation of
# that edition's default.xbe, generated into its own folder.
#   spyro_aht_recomp      US       src/recomp/gen
#   spyro_aht_recomp_eu   Europe   src/recomp/gen_eu   (AHT_EU)
function(aht_game TARGET GEN_DIR)
file(GLOB RECOMP_GEN_SOURCES CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${GEN_DIR}/*.c")

# Core game sources
set(GAME_SOURCES
    src/main.c
    src/recomp_manual.c
    src/gpu_backend.c
    src/gpu_vsh.c
    src/settings.c
    src/prompts.c
    src/sampler.c
    src/game.rc
    # 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

add_executable(${TARGET} WIN32
    ${GAME_SOURCES}
    ${RECOMP_GEN_SOURCES}
)

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

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

# Windows SDK libraries needed at link time
target_link_libraries(${TARGET} PRIVATE
    d3d11
    dxgi
    dxguid
    d3dcompiler
    $<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(${TARGET} PRIVATE
        /LARGEADDRESSAWARE
    )
    # The generated code files can be very large. Increase object file section limit.
    target_compile_options(${TARGET} PRIVATE /bigobj)
endif()

endfunction()

aht_game(${PROJECT_NAME} src/recomp/gen)
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src/recomp/gen_eu/recomp_funcs.h")
    aht_game(spyro_aht_recomp_eu src/recomp/gen_eu)
    target_compile_definitions(spyro_aht_recomp_eu PRIVATE AHT_EU=1)
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
# )

# Launcher: a settings window for spyro.ini with a Play button, built beside the game.
add_executable(spyro_launcher WIN32
    src/launcher/launcher.c
    src/launcher/import.c
    src/launcher/launcher.rc
    src/launcher/launcher.manifest
    src/settings.c
)
target_include_directories(spyro_launcher PRIVATE src src/launcher)
target_link_libraries(spyro_launcher PRIVATE shell32 user32 comctl32 bcrypt ole32 uuid)
# The game folder of this checkout, for the launcher's "installed" check
# while developing; Setup's game_files beside the .exe comes first.
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/game_files/default.xbe")
    target_compile_definitions(spyro_launcher PRIVATE
        SPYRO_DEV_GAME_DIR="${CMAKE_CURRENT_SOURCE_DIR}/game_files")
endif()
if(MSVC)
    target_link_options(spyro_launcher PRIVATE /ENTRY:wWinMainCRTStartup)
endif()
