cmake_minimum_required(VERSION 3.19)
# the C runtime is linked in: the executables need no Visual C++ redistributable
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded")
project(cdi_recomp C)

# version (VERSION file): compiled in, and in the executables' file properties
file(STRINGS ${CMAKE_SOURCE_DIR}/VERSION APP_VERSION LIMIT_COUNT 1)
string(REPLACE "." "," APP_VERSION_COMMAS "${APP_VERSION}")
add_compile_definitions(APP_VERSION="${APP_VERSION}")

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()

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

# version resources: original edition and HD edition
set(VERSION_EDITION "")
set(VERSION_FILE ${GAME_EXE}.exe)
configure_file(runtime/version.rc.in ${CMAKE_BINARY_DIR}/version_orig.rc)
set(VERSION_EDITION " HD")
set(VERSION_FILE ${GAME_EXE}_hd.exe)
configure_file(runtime/version.rc.in ${CMAKE_BINARY_DIR}/version_hd.rc)

add_executable(game ${RT_SOURCES} ${GEN_SOURCES} ${CMAKE_BINARY_DIR}/version_orig.rc)
set_target_properties(game PROPERTIES OUTPUT_NAME ${GAME_EXE})
target_include_directories(game PRIVATE ${CMAKE_SOURCE_DIR}/runtime ${CMAKE_SOURCE_DIR}/gen)

if(MSVC)
  target_compile_options(game PRIVATE /O2 /W3 /wd4146 /wd4244 /wd4267 /wd4996 /wd4102 /bigobj /Zi)
  target_compile_definitions(game PRIVATE _CRT_SECURE_NO_WARNINGS)
  target_link_libraries(game PRIVATE winmm gdi32 user32 winhttp comdlg32 shell32)
  target_link_options(game PRIVATE /DEBUG /OPT:REF /OPT:ICF)
  set_target_properties(game PROPERTIES WIN32_EXECUTABLE OFF)
else()
  target_compile_options(game PRIVATE -O2 -Wno-unused-label)
endif()

# HD build (same sources, -DRECOMP_HD): adds the Cartoon HD / Cartoon HD+
# upscaling filters and starts with Cartoon HD: <exe_name>_hd.exe
add_executable(game_hd ${RT_SOURCES} ${GEN_SOURCES} ${CMAKE_BINARY_DIR}/version_hd.rc)
set_target_properties(game_hd PROPERTIES OUTPUT_NAME ${GAME_EXE}_hd)
target_include_directories(game_hd PRIVATE ${CMAKE_SOURCE_DIR}/runtime ${CMAKE_SOURCE_DIR}/gen)
target_compile_definitions(game_hd PRIVATE RECOMP_HD)
if(MSVC)
  target_compile_options(game_hd PRIVATE /O2 /W3 /wd4146 /wd4244 /wd4267 /wd4996 /wd4102 /bigobj /Zi)
  target_compile_definitions(game_hd PRIVATE _CRT_SECURE_NO_WARNINGS)
  target_link_libraries(game_hd PRIVATE winmm gdi32 user32 winhttp comdlg32 shell32)
  target_link_options(game_hd PRIVATE /DEBUG /OPT:REF /OPT:ICF)
endif()

# Lockstep block tracer build (same sources, -DRECOMP_BLOCKTRACE): kether_bt.exe
add_executable(game_bt EXCLUDE_FROM_ALL ${RT_SOURCES} ${GEN_SOURCES})
set_target_properties(game_bt PROPERTIES OUTPUT_NAME ${GAME_EXE}_bt)
target_include_directories(game_bt PRIVATE ${CMAKE_SOURCE_DIR}/runtime ${CMAKE_SOURCE_DIR}/gen)
target_compile_definitions(game_bt PRIVATE RECOMP_BLOCKTRACE)
if(MSVC)
  target_compile_options(game_bt PRIVATE /O2 /W3 /wd4146 /wd4244 /wd4267 /wd4996 /wd4102 /bigobj)
  target_compile_definitions(game_bt PRIVATE _CRT_SECURE_NO_WARNINGS)
  target_link_libraries(game_bt PRIVATE winmm gdi32 user32 winhttp comdlg32 shell32)
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()
