cmake_minimum_required(VERSION 3.20)
project(xboxrecomp VERSION 0.9.0 LANGUAGES C)

# Xbox Static Recompilation Runtime Library
# Provides link-time libraries for statically recompiled Xbox games.
# Pattern: extract emulator subsystems (xemu) into reusable static libraries.
#
# Libraries:
#   xbox_kernel    - Xbox kernel replacement layer (147 imports → Win32)
#   xbox_d3d8      - D3D8 → D3D11 graphics compatibility
#   xbox_dsound    - DirectSound → software mixer compatibility
#   xbox_input     - Xbox gamepad → XInput compatibility
#   xbox_apu       - MCPX APU audio emulation (extracted from xemu)
#   xbox_nv2a      - NV2A GPU emulation (extracted from xemu)

set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)

# Common definitions for all targets
add_compile_definitions(
    WIN32_LEAN_AND_MEAN
    NOMINMAX
)

# Windows: the toolkit's own path is Direct3D 11, XAudio2 and XInput. With
# XBOXRECOMP_WIN_SDL_GL a Windows build takes the desktop path instead: the
# pushbuffer executor with the OpenGL renderer, SDL2 for the window, sound
# and pads, as on Linux and macOS (MinGW/clang; the kernel stays Win32).
option(XBOXRECOMP_WIN_SDL_GL "Windows: OpenGL renderer + SDL2 host, as on Linux/macOS" OFF)
if(NOT WIN32 OR XBOXRECOMP_WIN_SDL_GL)
    set(XBOXRECOMP_SDL_HOST ON)
else()
    set(XBOXRECOMP_SDL_HOST OFF)
endif()
if(WIN32 AND XBOXRECOMP_WIN_SDL_GL)
    add_compile_definitions(XBOXRECOMP_SDL_HOST=1)
endif()

# ── Runtime Libraries ─────────────────────────────────────────

# Platform: Win32/NT type vocabulary + POSIX implementation of generic
# Per-port application name. On the Switch the renderers keep their caches in
# sdmc:/switch/<name>/; Vulkan also reports it as the application name.
set(XBOXRECOMP_APP_NAME "xboxrecomp" CACHE STRING
    "Application name (Switch data directory sdmc:/switch/<name>/)")
add_compile_definitions(XBOXRECOMP_APP_NAME="${XBOXRECOMP_APP_NAME}")

# Win32 host primitives. Carries no Xbox semantics; provides the foundation
# the kernel HLE and the graphics/audio/input layers build on.
add_subdirectory(src/platform)

# Core: Xbox kernel replacement (memory layout, file I/O, threading, sync)
add_subdirectory(src/kernel)

# Graphics: D3D8 → D3D11 compatibility layer
add_subdirectory(src/d3d)

option(XBOXRECOMP_VULKAN "Build the Vulkan renderer (nv2a_vk) instead of OpenGL" OFF)

# The Vulkan build on the Switch links mesa-switch's NVK. switch-sdl2 brings
# switch-mesa's EGL/GL, a second copy of Mesa's utilities: strip them from
# SDL2::SDL2 here, before the subdirectories find it (SDL is only the audio
# output there; its unused video driver's EGL calls are stubbed in nv2a_vk).
if(NINTENDO_SWITCH AND XBOXRECOMP_VULKAN)
    find_package(SDL2 REQUIRED)
    get_target_property(_sdl2_real SDL2::SDL2 ALIASED_TARGET)
    if(NOT _sdl2_real)
        set(_sdl2_real SDL2::SDL2)
    endif()
    get_target_property(_sdl2_libs ${_sdl2_real} INTERFACE_LINK_LIBRARIES)
    list(FILTER _sdl2_libs EXCLUDE REGEX "EGL|GLES|glapi|drm_nouveau|^GL$|OpenGL")
    set_property(TARGET ${_sdl2_real} PROPERTY INTERFACE_LINK_LIBRARIES "${_sdl2_libs}")
    message(STATUS "SDL2 link interface (Vulkan build): ${_sdl2_libs}")
endif()

# Audio: DirectSound → software mixer compatibility
add_subdirectory(src/audio)

# Audio: MCPX APU hardware emulation (voice processor, DSP)
add_subdirectory(src/apu)

# GPU: NV2A hardware emulation (register handlers, MMIO, push buffer)
add_subdirectory(src/nv2a)

# USB: MCPX OHCI host controllers. A title's XAPI is statically linked and
# drives these registers directly, so a pad only exists if they do.
add_subdirectory(src/usb)

# Input: Xbox gamepad → XInput
add_subdirectory(src/input)

# Shared FMV player (Media Foundation -> D3D8 texture)
add_subdirectory(src/video)

# Renderer for the pushbuffer executor (Linux, macOS, Switch; Windows with
# XBOXRECOMP_WIN_SDL_GL): OpenGL, or Vulkan with XBOXRECOMP_VULKAN=ON.
# Windows otherwise keeps its D3D11 path.
if(XBOXRECOMP_SDL_HOST)
    if(XBOXRECOMP_VULKAN)
        add_subdirectory(src/nv2a_vk)
    else()
        add_subdirectory(src/nv2a_gl)
    endif()
endif()

# ── Umbrella target ───────────────────────────────────────────

# Convenience target that links all runtime libraries
add_library(xboxrecomp INTERFACE)
target_link_libraries(xboxrecomp INTERFACE
    xbox_kernel
    xbox_d3d8
    xbox_dsound
    xbox_input
    xbox_usb
    xbox_apu
    xbox_nv2a
    xbox_video
)
if(XBOXRECOMP_SDL_HOST)
    if(XBOXRECOMP_VULKAN)
        target_link_libraries(xboxrecomp INTERFACE xbox_nv2a_vk)
    else()
        target_link_libraries(xboxrecomp INTERFACE xbox_nv2a_gl)
    endif()
endif()

