cmake_minimum_required(VERSION 3.20)
project(coi_port C CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Link the C/C++ runtime statically on Windows, so coi.exe runs without the Visual C++
# Redistributable installed.
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")

set(THIRD_PARTY ${CMAKE_CURRENT_SOURCE_DIR}/../third_party)
if(NOT EXISTS ${THIRD_PARTY}/SDL/CMakeLists.txt)
    message(FATAL_ERROR "third_party/ is missing: run python tools/fetch_deps.py first")
endif()

# --- SDL3, built as a static library ---------------------------------------
set(SDL_SHARED OFF CACHE BOOL "" FORCE)
set(SDL_STATIC ON CACHE BOOL "" FORCE)
set(SDL_TEST_LIBRARY OFF CACHE BOOL "" FORCE)
set(SDL_EXAMPLES OFF CACHE BOOL "" FORCE)
add_subdirectory(${THIRD_PARTY}/SDL ${CMAKE_BINARY_DIR}/SDL EXCLUDE_FROM_ALL)

# --- Musashi 68000 core ------------------------------------------------------
# m68kmake generates the opcode handlers from m68k_in.c at build time.
set(MUSASHI ${THIRD_PARTY}/Musashi)
set(MUSASHI_GEN ${CMAKE_BINARY_DIR}/musashi)
add_executable(m68kmake ${MUSASHI}/m68kmake.c)
target_compile_definitions(m68kmake PRIVATE _CRT_SECURE_NO_WARNINGS)
add_custom_command(
    OUTPUT ${MUSASHI_GEN}/m68kops.c ${MUSASHI_GEN}/m68kops.h
    COMMAND ${CMAKE_COMMAND} -E make_directory ${MUSASHI_GEN}
    COMMAND m68kmake ${MUSASHI_GEN} ${MUSASHI}/m68k_in.c
    DEPENDS m68kmake ${MUSASHI}/m68k_in.c
    COMMENT "Generating Musashi opcode handlers")

add_library(musashi STATIC
    ${MUSASHI}/m68kcpu.c
    ${MUSASHI}/m68kdasm.c
    ${MUSASHI}/softfloat/softfloat.c
    ${MUSASHI_GEN}/m68kops.c)
# Our configuration (src/musashi_conf.h) wraps Musashi's own m68kconf.h.
target_include_directories(musashi PUBLIC ${MUSASHI} ${MUSASHI_GEN} ${CMAKE_CURRENT_SOURCE_DIR}/src)
target_compile_definitions(musashi PUBLIC MUSASHI_CNF="musashi_conf.h" PRIVATE _CRT_SECURE_NO_WARNINGS)

# --- ymfm (YM2612) and the Z80 core ------------------------------------------
file(GLOB YMFM_SOURCES ${THIRD_PARTY}/ymfm/src/*.cpp)
add_library(ymfm STATIC ${YMFM_SOURCES})
target_include_directories(ymfm PUBLIC ${THIRD_PARTY}/ymfm/src)

add_library(z80 STATIC ${THIRD_PARTY}/z80/z80.c)
target_include_directories(z80 PUBLIC ${THIRD_PARTY}/z80)

# --- Dear ImGui (the F1 menu), with its SDL3 and OpenGL 3 backends ----------
set(IMGUI ${THIRD_PARTY}/imgui)
add_library(imgui STATIC
    ${IMGUI}/imgui.cpp
    ${IMGUI}/imgui_demo.cpp
    ${IMGUI}/imgui_draw.cpp
    ${IMGUI}/imgui_tables.cpp
    ${IMGUI}/imgui_widgets.cpp
    ${IMGUI}/backends/imgui_impl_sdl3.cpp
    ${IMGUI}/backends/imgui_impl_opengl3.cpp)
target_include_directories(imgui PUBLIC ${IMGUI} ${IMGUI}/backends)
target_compile_definitions(imgui PUBLIC IMGUI_DISABLE_DEMO_WINDOWS)
target_link_libraries(imgui PUBLIC SDL3::SDL3-static)

# --- hqx (libretro glsl-shaders, LGPL 2.1 or later) -------------------------
# The two shader passes and the lookup tables are built into the program as a generated
# header; display.cpp compiles the shaders as they are.
set(HQX ${THIRD_PARTY}/glsl-shaders/hqx)
set(HQX_HEADER ${CMAKE_CURRENT_BINARY_DIR}/generated/hqx_data.h)
set(HQX_FILES ${HQX}/shader-files/hqx-pass1.glsl ${HQX}/shader-files/hqx-pass2.glsl
    ${HQX}/resources/hq2x.png ${HQX}/resources/hq3x.png ${HQX}/resources/hq4x.png)
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${HQX_FILES})
file(READ ${HQX}/shader-files/hqx-pass1.glsl HQX_PASS1)
file(READ ${HQX}/shader-files/hqx-pass2.glsl HQX_PASS2)
set(HQX_TEXT "// Generated by port/CMakeLists.txt from third_party/glsl-shaders/hqx.\n#pragma once\n\n")
string(APPEND HQX_TEXT "static const char kHqxPass1[] = R\"hqx(${HQX_PASS1})hqx\";\n")
string(APPEND HQX_TEXT "static const char kHqxPass2[] = R\"hqx(${HQX_PASS2})hqx\";\n")
foreach(N 2 3 4)
    file(READ ${HQX}/resources/hq${N}x.png PNG HEX)
    string(REGEX REPLACE "([0-9a-f][0-9a-f])" "0x\\1," PNG "${PNG}")
    string(APPEND HQX_TEXT "static const unsigned char kHq${N}xLut[] = {${PNG}};\n")
endforeach()
file(WRITE ${HQX_HEADER}.new "${HQX_TEXT}")
configure_file(${HQX_HEADER}.new ${HQX_HEADER} COPYONLY)    # rewritten only when it changes

# --- The port ----------------------------------------------------------------
add_executable(coi
    src/main.cpp
    src/bus.cpp
    src/cheats.cpp
    src/interp.cpp
    src/mdplus.cpp
    src/display.cpp
    src/fade.cpp
    src/menu.cpp
    src/patches.cpp
    src/settings.cpp
    src/smooth_scroll.cpp
    src/smooth_swing.cpp
    src/sound.cpp
    src/vdp.cpp)
target_link_libraries(coi PRIVATE musashi ymfm z80 imgui SDL3::SDL3-static)
set_target_properties(coi PROPERTIES WIN32_EXECUTABLE TRUE)    # no terminal window; --console shows one
target_compile_definitions(coi PRIVATE _CRT_SECURE_NO_WARNINGS)
target_include_directories(coi PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/generated)
