cmake_minimum_required(VERSION 3.16)
project(AlisiaDragoonRecomp LANGUAGES C CXX)

set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

set(GENESIS_RECOMP_ROOT "" CACHE PATH "Shared GenesisRecomp engine checkout")
if(GENESIS_RECOMP_ROOT)
    set(RECOMP_ROOT "${GENESIS_RECOMP_ROOT}")
else()
    message(FATAL_ERROR "Pass -DGENESIS_RECOMP_ROOT=<shared segagenesisrecomp checkout>")
endif()
set(RUNNER_ROOT "${RECOMP_ROOT}/runner")

# Match the reference game's Windows SDL2 discovery and keep SDL entry/link setup intact.
if(WIN32)
    list(APPEND CMAKE_PREFIX_PATH "${RUNNER_ROOT}/external/SDL2/SDL2-2.28.5/cmake")
endif()
find_package(SDL2 REQUIRED)
set(SDL2_PARENT_INCLUDE_DIRS "")
foreach(_inc IN LISTS SDL2_INCLUDE_DIRS)
    get_filename_component(_inc_name "${_inc}" NAME)
    if(_inc_name STREQUAL "SDL2")
        get_filename_component(_inc_parent "${_inc}" DIRECTORY)
        list(APPEND SDL2_PARENT_INCLUDE_DIRS "${_inc_parent}")
    endif()
endforeach()

# Configure the current framework and generate game C under build/generated/alisia.
include("${RECOMP_ROOT}/cmake/GenesisRecompRunner.cmake")
option(ALISIA_REVERSE_DEBUG "Generate reverse-debug PC hooks for diagnosing game boot loops" OFF)
include("${RECOMP_ROOT}/cmake/GenesisRecompGenerated.cmake")
genesisrecomp_add_generated_sources(
    ALISIA_GENERATED_SOURCES alisia "${CMAKE_SOURCE_DIR}" alisia_usa.md
    REVERSE_DEBUG "${ALISIA_REVERSE_DEBUG}")

# Current Sonic consumer source architecture: full runner sources plus own backend,
# native Tier-3 floor, ymfm and engine-generated translation units on one executable.
set(FM_SOURCES
    "${RUNNER_ROOT}/audio/ym2612_ymfm.cpp"
    "${RUNNER_ROOT}/external/ymfm/src/ymfm_opn.cpp"
    "${RUNNER_ROOT}/external/ymfm/src/ymfm_ssg.cpp"
    "${RUNNER_ROOT}/external/ymfm/src/ymfm_adpcm.cpp"
    "${RUNNER_ROOT}/external/ymfm/src/ymfm_pcm.cpp")
set(OWN_BACKEND_SOURCES
    "${RUNNER_ROOT}/video/genesis_vdp.c"
    "${RUNNER_ROOT}/video/genesis_bus.c"
    "${RUNNER_ROOT}/video/genesis_machine.c"
    "${RUNNER_ROOT}/external/superzazu/z80.c")
set(NATIVE_FLOOR_SOURCES
    "${RUNNER_ROOT}/m68k_interp.c"
    "${RECOMP_ROOT}/recompiler/src/m68k_decoder.c"
    "${RECOMP_ROOT}/recompiler/src/rom_parser.c")

set(ALISIA_SHARED_SOURCES
    "${RUNNER_ROOT}/main.c"
    "${RUNNER_ROOT}/audio.c"
    "${RUNNER_ROOT}/chip_trace.c"
    "${RUNNER_ROOT}/cmd_server_stub.c"
    "${RUNNER_ROOT}/glue.c"
    "${RUNNER_ROOT}/fiber_compat.c"
    "${RUNNER_ROOT}/crash_report.c"
    "${RUNNER_ROOT}/input_script.c"
    "${RUNNER_ROOT}/gamepad.c"
    "${RUNNER_ROOT}/input_map.c"
    "${RUNNER_ROOT}/app_config.c"
    "${RUNNER_ROOT}/audio/event_queue.c"
    ${FM_SOURCES}
    "${RUNNER_ROOT}/audio/sn76489.c"
    "${RUNNER_ROOT}/audio/mixer.c"
    "${RUNNER_ROOT}/audio/observability.c"
    "${RUNNER_ROOT}/cosim_state.c"
    "${RUNNER_ROOT}/audio/audio_shadow.c"
    "${RUNNER_ROOT}/audio/fm_shadow.cpp"
    "${RUNNER_ROOT}/video/color_lut.c"
    ${ALISIA_GENERATED_SOURCES}
    "${CMAKE_SOURCE_DIR}/alisia_spec.c"
    ${NATIVE_FLOOR_SOURCES})
set(ALISIA_BACKEND_SOURCES ${OWN_BACKEND_SOURCES})
set(ALISIA_INCLUDES
    "${RUNNER_ROOT}"
    "${RUNNER_ROOT}/include"
    "${RUNNER_ROOT}/external/ymfm/src"
    "${RUNNER_ROOT}/external/superzazu"
    "${RUNNER_ROOT}/external/clowncommon"
    "${RUNNER_ROOT}/video"
    "${RECOMP_ROOT}/recompiler/src")
set(ALISIA_SHARED_LIBS SDL2::SDL2main SDL2::SDL2)
if(WIN32)
    list(APPEND ALISIA_SHARED_LIBS ws2_32 comdlg32)
endif()

add_executable(AlisiaDragoonRecomp ${ALISIA_SHARED_SOURCES} ${ALISIA_BACKEND_SOURCES})
add_dependencies(AlisiaDragoonRecomp ${ALISIA_GENERATED_SOURCES_TARGET})

# --- Statically recompiled Z80 sound driver (optional, default ON) -----------
# Generated by SmsRecomp --flat-step from the cartridge's uploaded driver image
# (z80/z80_driver_image.bin, reconstructed from the ROM upload at $08B784/$08C89E).
# The adapter (runner/z80_recomp.c) keeps the Genesis scheduler authoritative for
# reset/BUSREQ/interrupts and falls back per instruction to SuperZazu for live code
# outside the captured image.
option(ALISIA_Z80_RECOMP "Run the Z80 sound driver through statically generated C" ON)
set(ALISIA_Z80_AOT_SOURCE "${CMAKE_SOURCE_DIR}/z80/alisia_z80_step.c" CACHE FILEPATH
    "SmsRecomp --flat-step output for the Z80 driver")
if(ALISIA_Z80_RECOMP)
    add_subdirectory("${RECOMP_ROOT}/external/z80-recomp-core"
                     "${CMAKE_BINARY_DIR}/z80-recomp-core")
    target_sources(AlisiaDragoonRecomp PRIVATE
        "${RUNNER_ROOT}/z80_recomp.c"
        "${ALISIA_Z80_AOT_SOURCE}")
    target_include_directories(AlisiaDragoonRecomp PRIVATE
        "${RECOMP_ROOT}/external/z80-recomp-core/include"
        "${CMAKE_SOURCE_DIR}/z80")
    target_link_libraries(AlisiaDragoonRecomp PRIVATE z80_recomp_core)
    message(STATUS "Alisia: Z80 static recomp ENABLED (${ALISIA_Z80_AOT_SOURCE})")
endif()

target_compile_definitions(AlisiaDragoonRecomp PRIVATE
    INCLUDE_GENERATED_CODE=1
    ENABLE_RECOMPILED_CODE=1
    OWN_BACKEND=1
    GENESIS_GAME_VERSION="${PROJECT_VERSION}")
if(ALISIA_Z80_RECOMP)
    target_compile_definitions(AlisiaDragoonRecomp PRIVATE GENESIS_Z80_RECOMP=1)
endif()
target_include_directories(AlisiaDragoonRecomp PRIVATE ${ALISIA_INCLUDES} ${SDL2_PARENT_INCLUDE_DIRS})
target_link_libraries(AlisiaDragoonRecomp PRIVATE ${ALISIA_SHARED_LIBS})



# Patch generated code to release Z80 from reset after program load.
add_custom_command(TARGET AlisiaDragoonRecomp PRE_BUILD
    COMMAND python "${CMAKE_CURRENT_SOURCE_DIR}/patch_z80_reset.py" "${CMAKE_CURRENT_BINARY_DIR}/generated/alisia"
    VERBATIM)

genesisrecomp_runner_target(AlisiaDragoonRecomp)
# Sonic's consumer explicitly aligns compile-time hook ABI with codegen option.
if(ALISIA_REVERSE_DEBUG)
    target_compile_definitions(AlisiaDragoonRecomp PRIVATE SONIC_REVERSE_DEBUG=1)
else()
    target_compile_definitions(AlisiaDragoonRecomp PRIVATE SONIC_REVERSE_DEBUG=0)
endif()
genesisrecomp_runner_sources(ALISIA_EXTRA_RUNNER_SOURCES TRACE OFF REVERSE_DEBUG ${ALISIA_REVERSE_DEBUG})
if(ALISIA_REVERSE_DEBUG)
    target_sources(AlisiaDragoonRecomp PRIVATE "${RUNNER_ROOT}/reverse_debug.c")
endif()
if(MSVC)
    target_compile_options(AlisiaDragoonRecomp PRIVATE /W3 /WX- /utf-8 /wd4102 /wd4996)
    target_link_options(AlisiaDragoonRecomp PRIVATE /MAP /CETCOMPAT:NO)
endif()
if(WIN32)
    add_custom_command(TARGET AlisiaDragoonRecomp POST_BUILD
        COMMAND ${CMAKE_COMMAND} -E copy_if_different
            "${RUNNER_ROOT}/external/SDL2/SDL2-2.28.5/lib/x64/SDL2.dll"
            "$<TARGET_FILE_DIR:AlisiaDragoonRecomp>"
        COMMENT "Copying framework SDL2.dll")
endif()
