cmake_minimum_required(VERSION 3.19)
project(cdi_recomp C)

set(CMAKE_C_STANDARD 11)

# executable name comes from game.json ("exe_name")
file(READ ${CMAKE_SOURCE_DIR}/game.json GAME_JSON)
string(JSON GAME_EXE ERROR_VARIABLE json_err GET ${GAME_JSON} exe_name)
if(json_err)
  set(GAME_EXE cdigame)
endif()

# self-contained executables: the C runtime is linked statically (no Visual C++
# Redistributable needed on the player's PC)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")

file(GLOB GEN_SOURCES ${CMAKE_SOURCE_DIR}/gen/*.c)
file(GLOB RT_SOURCES ${CMAKE_SOURCE_DIR}/runtime/*.c)

# The generated code is compiled once and shared by both executables.
add_library(gamecode OBJECT ${GEN_SOURCES})
target_include_directories(gamecode PRIVATE ${CMAKE_SOURCE_DIR}/runtime ${CMAKE_SOURCE_DIR}/gen)

# game:    the original presentation
# game_hd: adds the Cartoon HD / HD+ upscalers and 60 fps sprite interpolation
foreach(tgt game game_hd)
  add_executable(${tgt} ${RT_SOURCES} $<TARGET_OBJECTS:gamecode>)
  if(WIN32 AND EXISTS ${CMAKE_SOURCE_DIR}/gen/version_${tgt}.rc)
    target_sources(${tgt} PRIVATE ${CMAKE_SOURCE_DIR}/gen/version_${tgt}.rc)
  endif()
  target_include_directories(${tgt} PRIVATE ${CMAKE_SOURCE_DIR}/runtime ${CMAKE_SOURCE_DIR}/gen)
endforeach()
set_target_properties(game PROPERTIES OUTPUT_NAME ${GAME_EXE})
set_target_properties(game_hd PROPERTIES OUTPUT_NAME ${GAME_EXE}_hd)
target_compile_definitions(game_hd PRIVATE HD_BUILD=1)

foreach(tgt gamecode game game_hd)
  if(MSVC)
    target_compile_options(${tgt} PRIVATE /O2 /W3 /wd4146 /wd4244 /wd4267 /wd4996 /wd4102 /bigobj)
    target_compile_definitions(${tgt} PRIVATE _CRT_SECURE_NO_WARNINGS)
  else()
    target_compile_options(${tgt} PRIVATE -O2 -Wno-unused-label)
  endif()
endforeach()
if(MSVC)
  foreach(tgt game game_hd)
    target_link_libraries(${tgt} PRIVATE winmm gdi32 user32 comdlg32)
    # a windowed program (no console); the log is saves
ecomp.log
    set_target_properties(${tgt} PROPERTIES WIN32_EXECUTABLE ON LINK_FLAGS "/ENTRY:mainCRTStartup")
  endforeach()
endif()

# Differential instruction tester (recompiled semantics vs interpreter).
# Generate test/insn_tests.c with: python tools/gen_tests.py
if(EXISTS ${CMAKE_SOURCE_DIR}/test/insn_tests.c)
  add_executable(insn_test test/harness.c test/insn_tests.c runtime/interp.c runtime/alu.c runtime/disc.c)
  target_include_directories(insn_test PRIVATE ${CMAKE_SOURCE_DIR}/runtime ${CMAKE_SOURCE_DIR}/gen)
  target_compile_definitions(insn_test PRIVATE RECOMP_TEST _CRT_SECURE_NO_WARNINGS)
  if(MSVC)
    target_compile_options(insn_test PRIVATE /O1 /bigobj /wd4146 /wd4244 /wd4267 /wd4996 /wd4102)
  endif()
endif()

# ALU helper check against an independent reference model (python test/gen_alu_vectors.py)
if(EXISTS ${CMAKE_SOURCE_DIR}/test/alu_vectors.h)
  add_executable(alu_test test/alu_test.c runtime/alu.c)
  target_include_directories(alu_test PRIVATE ${CMAKE_SOURCE_DIR}/runtime ${CMAKE_SOURCE_DIR}/gen ${CMAKE_SOURCE_DIR}/test)
endif()
