cmake_minimum_required(VERSION 3.20)
project(LagoonSNESRecomp C CXX)

set(CMAKE_C_STANDARD 11)

# Release pin for lobby matching. Release builds stamp the VERSION file so two
# peers can prove they are the same build; everything else stamps "dev".
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/VERSION")
file(READ "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" _GAME_VER_RAW)
string(STRIP "${_GAME_VER_RAW}" GAME_RELEASE_VERSION)
set(SNESRECOMP_BUILD_VERSION "" CACHE STRING
    "Lobby release pin (empty = Release uses VERSION, else dev)")
if(SNESRECOMP_BUILD_VERSION STREQUAL "")
    get_property(_is_multi GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
    if(_is_multi)
        set(SNESRECOMP_BUILD_VERSION "$<IF:$<CONFIG:Release>,${GAME_RELEASE_VERSION},dev>")
    elseif(CMAKE_BUILD_TYPE STREQUAL "Release")
        set(SNESRECOMP_BUILD_VERSION "${GAME_RELEASE_VERSION}")
    else()
        set(SNESRECOMP_BUILD_VERSION "dev")
    endif()
endif()

set(_lagoon_sdk "${CMAKE_SOURCE_DIR}/snesrecomp")
if(DEFINED ENV{LAGOON_FRAMEWORK_ROOT})
    set(_lagoon_sdk "$ENV{LAGOON_FRAMEWORK_ROOT}")
elseif(EXISTS "${CMAKE_SOURCE_DIR}/framework.local")
    file(READ "${CMAKE_SOURCE_DIR}/framework.local" _lagoon_sdk)
    string(STRIP "${_lagoon_sdk}" _lagoon_sdk)
    get_filename_component(_lagoon_sdk "${_lagoon_sdk}" ABSOLUTE BASE_DIR "${CMAKE_SOURCE_DIR}")
endif()
set(SNESRECOMP_ROOT "${_lagoon_sdk}" CACHE PATH
    "Path to the snesrecomp checkout used by this game")
if(NOT EXISTS "${SNESRECOMP_ROOT}/runner/runner.cmake")
    message(FATAL_ERROR
        "snesrecomp submodule missing at ${SNESRECOMP_ROOT}.\n"
        "Run: git submodule update --init --recursive")
endif()
if(EXISTS "${SNESRECOMP_ROOT}/.git")
    find_package(Git REQUIRED)
    execute_process(COMMAND "${GIT_EXECUTABLE}" -C "${SNESRECOMP_ROOT}" rev-parse HEAD
        OUTPUT_VARIABLE _lagoon_sdk_head OUTPUT_STRIP_TRAILING_WHITESPACE COMMAND_ERROR_IS_FATAL ANY)
    file(STRINGS "${CMAKE_SOURCE_DIR}/framework_pins.txt" _lagoon_sdk_pin REGEX "^snesrecomp=")
    string(REPLACE "snesrecomp=" "" _lagoon_sdk_pin "${_lagoon_sdk_pin}")
    if(NOT _lagoon_sdk_head STREQUAL _lagoon_sdk_pin)
        message(FATAL_ERROR "Selected SDK ${_lagoon_sdk_head} differs from ${_lagoon_sdk_pin}. Preserve dirty SDKs; select the upgrade worktree and use a separate build directory.")
    endif()
endif()
# Mod packages are part of every project, not an option. The launcher's Mods
# page, the .snesmod loader, the trusted-plugin registry and netplay's mod-set
# gate all hang off this one switch; a build without it cannot exchange mods
# with a peer that has them, and the framework says so at every lobby init.
# Must precede the include: runner.cmake reads it to add the loader sources.
set(SNESRECOMP_ENABLE_MODS ON CACHE BOOL
    "Mod package loader + trusted plugins (required for every title)" FORCE)
# Build-selected exact upstream optimizations; callers can retain references.
set(SNESRECOMP_DSP_MIX_IMPL "NATIVE" CACHE STRING "DSP mixer implementation")
set(SNESRECOMP_INTERP_READ_IMPL "FUSED" CACHE STRING "Interpreter immutable ROM reads")
include(${SNESRECOMP_ROOT}/runner/runner.cmake)

add_executable(LagoonSNESRecomp
    ${SNESRECOMP_RUNNER_SOURCES}
    src/main.c
    src/lagoon_follower.c
    src/lagoon_map.c
    src/lagoon_frame_probe.c
    src/lagoon_actor_compute.c
    src/lagoon_native_actor_commands.c
    src/lagoon_native_boot62.c
    src/lagoon_native_decode63.c
    src/lagoon_native_spc63.c
    src/lagoon_native_menu_input67.c
    src/lagoon_native_scheduler67.c
    src/lagoon_native_sprites67.c
    src/lagoon_native_death_menu68.c
    src/lagoon_native_camera68.c
    src/lagoon_native_collision68.c
    src/lagoon_native_irq_stack68.c
    src/lagoon_native_dispatch68.c
    src/lagoon_native_map68.c
    src/lagoon_native_player_intent68.c
    src/lagoon_native_nmi_prep68.c
    src/lagoon_native_tiles68.c
    src/lagoon_native_staging68.c
    src/lagoon_native_backend69.c
    src/lagoon_native_interrupt66.c
    src/lagoon_native_services65.c
    src/lagoon_native_reset63.c
    src/lagoon_native_iterator52.c
    src/lagoon_native_scripts53.c
    src/host_contract.c
    src/game_rtl.c
    src/lagoon_native_recovery.c
    src/lagoon_native_revival.c
    src/lagoon_native_camera.c
    src/lagoon_native_endgame.c
    src/lagoon_native_inline.c
    src/lagoon_native_music.c
    src/lagoon_state.c
    src/lagoon_fast_menus.c
    src/lagoon_menu_decode.c
  src/lagoon_menu_close.c
  src/lagoon_menu_dma.c
    src/lagoon_menu_presentation.c
    src/gen_stubs.c
    src/lagoon_qol.c
    src/lagoon_soundtrack.c
    src/lagoon_widescreen.c
    src/lagoon_wide_entities.c
    src/lagoon_wide_ai.c
    src/lagoon_boss_hud.c
    src/lagoon_wide_multipart.c
    src/lagoon_wide_spell3.c
    src/lagoon_scene_renderer.c
    src/lagoon_transition_present.c
    src/lagoon_quest_guidance.c
    src/lagoon_journal.c
    src/lagoon_item_guide.c
    src/lagoon_return.c
    src/lagoon_return_runtime.c
    src/lagoon_settings.c
    src/lagoon_ui.c
    src/lagoon_achievements.c
    src/lagoon_achievement_ui.c
    src/lagoon_achievement_sound.c
    src/lagoon_achievement_ending.c
    src/lagoon_easter_egg.c
    src/lagoon_easter_collision.c
    src/lagoon_dialogue_font.c
    third_party/companion_achievements/companion_achievements.c
    third_party/cjson/cJSON.c
    src/lagoon_sword_visual.c
    src/lagoon_sword_range.c
    src/lagoon_campaign_debug.c
)

if(WIN32)
    enable_language(RC)
    target_sources(LagoonSNESRecomp PRIVATE assets/icons/lagoon-game.rc)
endif()

# ROM identity. rom_identity.txt is the one place the digests live: the build
# turns it into snesrecomp_rom_identity.h (SNESRECOMP_ROM_EXPECTED_SHA256 and
# friends) for src/main.c, and tools/regen.sh, scripts/package_release.sh and
# the release workflow read the same file. A revision bump is one edit there.
snesrecomp_rom_identity(LagoonSNESRecomp ${CMAKE_SOURCE_DIR}/rom_identity.txt)

# Generated C stays local and is not committed or included as release source.
# Windows previews include the qualified executable, which still loads and
# verifies the player's own ROM at runtime; no ROM/assets are embedded.
set(LAGOON_GENERATED_DIR "${CMAKE_SOURCE_DIR}/src/gen" CACHE PATH
    "Generated program directory; use a private path for coverage candidates")
snesrecomp_target_generated_code(LagoonSNESRecomp ${LAGOON_GENERATED_DIR})
option(LAGOON_GENERATE_NATIVE69_FROM_ROM
    "Generate the reviewed architectural native profiles privately from your ROM" OFF)
set(LAGOON_NATIVE69_ROM "" CACHE FILEPATH "Unmodified Lagoon USA ROM for opt-in native69 generation")
if(LAGOON_GENERATE_NATIVE69_FROM_ROM)
    if(SNESRECOMP_SETUP_HOST OR NOT EXISTS "${LAGOON_NATIVE69_ROM}")
        message(FATAL_ERROR "Native69 generation requires a playable build and an explicit LAGOON_NATIVE69_ROM")
    endif()
    if(LAGOON_NATIVE_BLOCKS69_SOURCE OR LAGOON_NATIVE_BLOCKS69_CAMERA_SOURCE)
        message(FATAL_ERROR "Choose native69 generation or explicit generated source paths, not both; use a fresh build directory")
    endif()
    # Establish typed cache entries before setting normal generated-path values.
    # CMake 3.20's CMP0126 OLD otherwise removes those normal bindings below.
    set(LAGOON_NATIVE_BLOCKS69_SOURCE "" CACHE FILEPATH "Private generated native base source")
    set(LAGOON_NATIVE_BLOCKS69_CAMERA_SOURCE "" CACHE FILEPATH "Private generated native camera source")
    find_package(Python3 3.10 COMPONENTS Interpreter REQUIRED)
    file(GLOB _lagoon_native69_inputs CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/config/native69/*")
    file(GLOB _lagoon_native69_compiler CONFIGURE_DEPENDS "${SNESRECOMP_ROOT}/recompiler/v2/*.py")
    set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS
        ${_lagoon_native69_inputs} ${_lagoon_native69_compiler}
        "${CMAKE_CURRENT_SOURCE_DIR}/tools/generate_native_backend69.py"
        "${CMAKE_CURRENT_SOURCE_DIR}/src/lagoon_qol.c"
        "${CMAKE_CURRENT_SOURCE_DIR}/src/lagoon_follower.c"
        "${SNESRECOMP_ROOT}/recompiler/snes65816.py"
        "${SNESRECOMP_ROOT}/recompiler/snes_cycles.py"
        "${SNESRECOMP_ROOT}/runner/src/native_blocks.h" "${LAGOON_NATIVE69_ROM}")
    execute_process(COMMAND "${Python3_EXECUTABLE}" -P
        "${CMAKE_CURRENT_SOURCE_DIR}/tools/generate_native_backend69.py"
        --rom "${LAGOON_NATIVE69_ROM}" --sdk "${SNESRECOMP_ROOT}"
        --out-dir "${CMAKE_CURRENT_BINARY_DIR}/native69"
        RESULT_VARIABLE _lagoon_native69_result OUTPUT_VARIABLE _lagoon_native69_output
        ERROR_VARIABLE _lagoon_native69_error)
    if(NOT _lagoon_native69_result EQUAL 0)
        message(FATAL_ERROR "Native69 generation refused: ${_lagoon_native69_error}")
    endif()
    set(LAGOON_NATIVE_BLOCKS69_SOURCE "${CMAKE_CURRENT_BINARY_DIR}/native69/ordinary69.generated.c")
    set(LAGOON_NATIVE_BLOCKS69_CAMERA_SOURCE "${CMAKE_CURRENT_BINARY_DIR}/native69/camera69.generated.c")
endif()
set(LAGOON_NATIVE_BLOCKS69_SOURCE "" CACHE FILEPATH
    "Private compiler-generated architectural native blocks; empty keeps the existing execution route")
if(LAGOON_NATIVE_BLOCKS69_SOURCE)
    if(SNESRECOMP_SETUP_HOST OR NOT EXISTS "${LAGOON_NATIVE_BLOCKS69_SOURCE}")
        message(FATAL_ERROR "Architectural native blocks require an existing private generated source and a playable build")
    endif()
    target_sources(LagoonSNESRecomp PRIVATE "${LAGOON_NATIVE_BLOCKS69_SOURCE}")
    target_compile_definitions(LagoonSNESRecomp PRIVATE LAGOON_NATIVE_BLOCKS69_ENABLED=1)
endif()
set(LAGOON_NATIVE_BLOCKS69_CAMERA_SOURCE "" CACHE FILEPATH
    "Private generated approved centered-camera native source profile")
if(LAGOON_NATIVE_BLOCKS69_CAMERA_SOURCE)
    if(NOT LAGOON_NATIVE_BLOCKS69_SOURCE OR NOT EXISTS "${LAGOON_NATIVE_BLOCKS69_CAMERA_SOURCE}")
        message(FATAL_ERROR "Camera native profile requires the base generated native source and an existing camera source")
    endif()
    target_sources(LagoonSNESRecomp PRIVATE "${LAGOON_NATIVE_BLOCKS69_CAMERA_SOURCE}")
    target_compile_definitions(LagoonSNESRecomp PRIVATE LAGOON_NATIVE_BLOCKS69_CAMERA_ENABLED=1)
endif()
option(LAGOON_NATIVE_RELEASE_DEFAULT "Use strict native CPU execution by default when both profiles are linked" ON)
option(LAGOON_REQUIRE_NATIVE_CPU "Refuse a playable non-native build (disable only for development/reference)" ON)
set(_lagoon_native_cpu_json false)
set(_lagoon_native_only_json false)
if(LAGOON_NATIVE_BLOCKS69_SOURCE AND LAGOON_NATIVE_BLOCKS69_CAMERA_SOURCE)
    set(_lagoon_native_cpu_json true)
    if(LAGOON_NATIVE_RELEASE_DEFAULT)
        target_compile_definitions(LagoonSNESRecomp PRIVATE LAGOON_NATIVE_RELEASE_DEFAULT=1)
        set(_lagoon_native_only_json true)
    endif()
endif()
if(NOT SNESRECOMP_SETUP_HOST AND LAGOON_REQUIRE_NATIVE_CPU AND NOT _lagoon_native_only_json)
    message(FATAL_ERROR "Playable Lagoon requires both native CPU profiles and strict native defaults. Supply LAGOON_GENERATE_NATIVE69_FROM_ROM=ON with LAGOON_NATIVE69_ROM, or both private generated source paths. LAGOON_REQUIRE_NATIVE_CPU=OFF is a development/reference opt-out.")
endif()
if(EXISTS "${LAGOON_GENERATED_DIR}/program_manifest.json")
    find_package(Python3 COMPONENTS Interpreter REQUIRED)
    add_custom_target(lagoon_camera_patch_safety
        COMMAND "${Python3_EXECUTABLE}" -P "${CMAKE_SOURCE_DIR}/tools/check_camera_patch_safety.py"
            "${LAGOON_GENERATED_DIR}/program_manifest.json"
        VERBATIM)
    add_dependencies(LagoonSNESRecomp lagoon_camera_patch_safety)
endif()

# The mod catalog. This names WHERE the packages are; the framework owns the
# layout they are staged into beside the executable, and stages them on every
# build OF THE EXECUTABLE -- including the launcher's own Generate & rebuild on
# a player's machine, which builds only this target and would skip a sibling
# ALL target. mods/preloaded/packages/ holds reviewed, default-disabled
# packages; players install .snesmod archives through the launcher.
# snesrecomp/docs/MOD_PACKAGES.md.
#
# It used to be `snesrecomp_target_stage_dir(... ${CMAKE_SOURCE_DIR}/mods mods)`
# -- the destination spelled per title, which is how three ports in the same
# workspace ended up shipping an empty Mods page and nothing said so. Declaring
# it is now also enforced: a project with packages that never calls this fails
# to configure.
snesrecomp_target_mod_catalog(LagoonSNESRecomp ${CMAKE_SOURCE_DIR}/mods/preloaded)
snesrecomp_target_stage_dir(LagoonSNESRecomp ${CMAKE_SOURCE_DIR}/assets/shaders assets/shaders)
snesrecomp_target_stage_dir(LagoonSNESRecomp ${CMAKE_SOURCE_DIR}/assets/achievements assets/achievements)
snesrecomp_target_stage_dir(LagoonSNESRecomp ${CMAKE_SOURCE_DIR}/assets/easter_egg assets/easter_egg)
# Any other directory the game reads exe-relative (a translations/ table, ...)
# is staged with snesrecomp_target_stage_dir, never with a separate ALL target.

target_include_directories(LagoonSNESRecomp PRIVATE
    ${SNESRECOMP_RUNNER_INCLUDE_DIRS}
    # common_rtl.c includes "config.h": the desktop key-map / Config contract
    # the framework host supplies (snesrecomp_target_desktop_host below).
    ${SNESRECOMP_ROOT}/runner/src/desktop
    ${CMAKE_SOURCE_DIR}/src
    ${CMAKE_SOURCE_DIR}/recomp
    ${CMAKE_SOURCE_DIR}/third_party/companion_achievements
    ${CMAKE_SOURCE_DIR}/third_party/cjson
)
target_link_libraries(LagoonSNESRecomp PRIVATE ${SNESRECOMP_RUNNER_LIBRARIES})
if(WIN32)
    target_sources(LagoonSNESRecomp PRIVATE src/lagoon_d3d11.cpp)
    target_link_libraries(LagoonSNESRecomp PRIVATE d3d11 dxgi d3dcompiler)
endif()
target_compile_definitions(LagoonSNESRecomp PRIVATE
    SNES_GAME_VERSION="${SNESRECOMP_BUILD_VERSION}"
    SNES_GAME_TITLE="Lagoon"
)
# Portable release jobs deliberately compile the pinned SDL3 source as static;
# a developer machine's Homebrew or distribution SDL shared library must not
# become an undeclared package dependency. Windows keeps its existing toolchain.
option(LAGOON_PORTABLE_STATIC_SDL3 "Build pinned static SDL3 for a Unix portable package" OFF)
if(LAGOON_PORTABLE_STATIC_SDL3)
    if(NOT UNIX OR NOT SNESRECOMP_SDL_BACKEND STREQUAL "SDL3" OR NOT SNESRECOMP_SDL3_FETCH)
        message(FATAL_ERROR "LAGOON_PORTABLE_STATIC_SDL3 requires Unix, SDL3 and its pinned source fallback")
    endif()
    set(CMAKE_DISABLE_FIND_PACKAGE_SDL3 TRUE)
endif()
snesrecomp_target_sdl(LagoonSNESRecomp)

# Explicit target-host persistence checks; never part of the playable executable
# or an automatic campaign. The caller supplies a fresh private output directory.
option(LAGOON_BUILD_PORT_TESTS "Build Linux/macOS persistence integration checks" OFF)
if(LAGOON_BUILD_PORT_TESTS)
    if(NOT UNIX OR NOT TARGET SDL3::SDL3)
        message(FATAL_ERROR "LAGOON_BUILD_PORT_TESTS requires Unix and SDL3")
    endif()
    add_executable(lagoon_posix_achievements_test EXCLUDE_FROM_ALL
        tests/lagoon_achievements_posix_test.c
        src/lagoon_achievements.c
        third_party/companion_achievements/companion_achievements.c
        third_party/cjson/cJSON.c)
    target_include_directories(lagoon_posix_achievements_test PRIVATE
        src third_party/companion_achievements third_party/cjson)
    target_compile_definitions(lagoon_posix_achievements_test PRIVATE _POSIX_C_SOURCE=200809L)
    if(APPLE)
        # flock is a BSD API: POSIX-only feature selection hides LOCK_EX even
        # though macOS provides the actual lock used by the game.
        target_compile_definitions(lagoon_posix_achievements_test PRIVATE _DARWIN_C_SOURCE=1)
    endif()
    target_link_libraries(lagoon_posix_achievements_test PRIVATE SDL3::SDL3 m)
    add_executable(lagoon_host_path_test EXCLUDE_FROM_ALL tests/lagoon_host_path_test.c)
    target_include_directories(lagoon_host_path_test PRIVATE src)
    add_executable(lagoon_platform_probe EXCLUDE_FROM_ALL tests/lagoon_platform_probe.c)
    target_link_libraries(lagoon_platform_probe PRIVATE SDL3::SDL3)
endif()

# The desktop host: launcher flow, ROM resolution, config.ini + [KeyMap],
# window + SDL/OpenGL presenters, audio, gamepads, the save-state browser and
# rewind filmstrip, the pacing clock, crash handlers and the post-mortem
# report. src/main.c is the shim that names this title and supplies its
# hooks; the host is the framework's and improves on a submodule pull.
# Add TIER2 once this port reads the interpreter-gap manifest after each run.
snesrecomp_target_desktop_host(LagoonSNESRecomp)
if(WIN32 AND TARGET SDL3::SDL3)
    add_executable(lagoon_d3d11_test EXCLUDE_FROM_ALL tests/lagoon_d3d11_test.cpp src/lagoon_d3d11.cpp)
    target_include_directories(lagoon_d3d11_test PRIVATE src ${SNESRECOMP_ROOT}/runner/src ${SNESRECOMP_ROOT}/runner/src/desktop)
    target_compile_definitions(lagoon_d3d11_test PRIVATE SNESRECOMP_SDL3=1 SDL_MAIN_HANDLED)
    target_link_libraries(lagoon_d3d11_test PRIVATE SDL3::SDL3 d3d11 dxgi d3dcompiler)
    if(MINGW)
        target_link_options(lagoon_d3d11_test PRIVATE -static)
    endif()
endif()
# rom.cfg (the ROM the wizard set this project up from; git-ignored) is
# staged beside the executable when none is there yet, so the first launch
# opens on that dump rather than asking for one.
snesrecomp_target_rom_cache(LagoonSNESRecomp)

# Package qualification is explicit. A ROM-free CI setup host can prove that the
# authored host compiles on an OS, but must never be labelled a playable port.
set(_lagoon_manifest_sha256 "")
if(EXISTS "${LAGOON_GENERATED_DIR}/program_manifest.json")
    file(SHA256 "${LAGOON_GENERATED_DIR}/program_manifest.json" _lagoon_manifest_sha256)
endif()
file(SHA256 "${CMAKE_SOURCE_DIR}/patches/lagoon-framework.patch" _lagoon_patch_sha256)
file(GENERATE OUTPUT "$<TARGET_FILE_DIR:LagoonSNESRecomp>/lagoon-build.json" CONTENT
"{\n  \"format_version\": 1,\n  \"version\": \"${GAME_RELEASE_VERSION}\",\n  \"system\": \"${CMAKE_SYSTEM_NAME}\",\n  \"processor\": \"${CMAKE_SYSTEM_PROCESSOR}\",\n  \"playable\": $<IF:$<BOOL:${SNESRECOMP_SETUP_HOST}>,false,true>,\n  \"native_cpu\": ${_lagoon_native_cpu_json},\n  \"native_only_default\": ${_lagoon_native_only_json},\n  \"executable\": \"$<TARGET_FILE_NAME:LagoonSNESRecomp>\",\n  \"generated_manifest_sha256\": \"${_lagoon_manifest_sha256}\",\n  \"framework_patch_sha256\": \"${_lagoon_patch_sha256}\"\n}\n")

# Companion is the normal entry point. Retain the old UI only as an explicit
# development option; it is not linked into the default game executable.
option(LAGOON_ENABLE_LEGACY_LAUNCHER "Build the legacy SNESRecomp pre-boot UI" OFF)
if(LAGOON_ENABLE_LEGACY_LAUNCHER)
# Shared Dear ImGui pre-boot launcher (ROM picker, verification, display /
# audio / input settings). Self-contained: it brings its own ImGui, GL link and
# staged assets, and defines RECOMP_LAUNCHER so src/main.c compiles its GUI path.
set(RECOMP_UI_ROOT "${CMAKE_SOURCE_DIR}/recomp-ui" CACHE PATH
    "Root directory of the recomp-ui launcher repo" FORCE)
if(NOT EXISTS "${RECOMP_UI_ROOT}/recomp_ui.cmake")
    message(FATAL_ERROR
        "recomp-ui missing at ${RECOMP_UI_ROOT}.\n"
        "Run: git submodule update --init --recursive recomp-ui")
endif()
include(${RECOMP_UI_ROOT}/recomp_ui.cmake)
# BOXART stages launcher_assets/img/boxart.tga beside the exe; the launcher
# shows assets/img/boxart.tga by default. EXISTS-guarded in recomp_ui.cmake,
# so this configures cleanly before any art is fetched.
recomp_target_launcher_ui(LagoonSNESRecomp CONSOLE snes
    BOXART "${CMAKE_SOURCE_DIR}/launcher_assets/img/boxart.tga")

# Generate & rebuild from inside the launcher: pick ROM -> recompile locally
# -> cmake --build -> relaunch. The implementation is the framework's; this
# project contributes no configuration (snesrecomp_codegen_host_autowire in
# src/main.c). recomp-ui/src is on the include path because the host speaks
# RecompLauncherCGameInfo.
target_sources(LagoonSNESRecomp PRIVATE
    ${SNESRECOMP_ROOT}/host/snesrecomp_codegen_host.c)
target_include_directories(LagoonSNESRecomp PRIVATE
    ${SNESRECOMP_ROOT}/host
    ${RECOMP_UI_ROOT}/src)
endif()

# Netplay is not built into this target.
# No multitap: two seats, one controller per port.
