cmake_minimum_required(VERSION 3.16)
project(linewars2 C)

set(CMAKE_C_STANDARD 99)
set(CMAKE_C_STANDARD_REQUIRED ON)

# The engine is platform-free. Every hardware touch goes through a backend, and
# exactly one backend is compiled in. See docs/ARCHITECTURE.md.
option(LW2_BACKEND_SDL3 "Build the SDL3 backend" ON)

# SDL 3.4.12, built from source with the same compiler as the game. If it is not
# on the default search path, point CMAKE_PREFIX_PATH at the install prefix:
#     cmake -S . -B build -G Ninja -DCMAKE_PREFIX_PATH=/path/to/SDL3
set(LW2_ENGINE_SOURCES
    src/game_main.c
    src/lw2_state.c
    src/lw2_kbd.c
    src/lw2_rng.c
    src/lw2_fmt.c
    src/lw2_sprintf.c
    src/lw2_math3d.c
    src/lw2_render.c
    src/lw2_flight.c
    src/lw2_missions.c
    src/lw2_gfx_vga.c
    src/lw2_menu.c
    src/lw2_intro.c
    src/lw2_splash.c
    src/lw2_hud.c
    src/lw2_cockpit.c
    src/lw2_music.c
    src/lw2_snd_blaster.c
    src/lw2_snd_speaker.c
    src/lw2_image.c
)

set(LW2_SDL_SOURCES
    platform/sdl3/hal_sdl.c
    platform/sdl3/sdl_vga.c
    platform/sdl3/sdl_video.c
    platform/sdl3/sdl_input.c
    platform/sdl3/sdl_file.c
    platform/sdl3/sdl_time.c
    platform/sdl3/sdl_font16.c
    platform/sdl3/sdl_text.c
    platform/sdl3/sdl_setup.c
    platform/sdl3/sdl_audio.c
)

add_executable(linewars2 ${LW2_ENGINE_SOURCES})
target_include_directories(linewars2 PRIVATE include)

if(LW2_BACKEND_SDL3)
    find_package(SDL3 REQUIRED)
    target_sources(linewars2 PRIVATE ${LW2_SDL_SOURCES})
    target_include_directories(linewars2 PRIVATE platform/sdl3)
    target_link_libraries(linewars2 PRIVATE SDL3::SDL3)

    # Selects the external-leaf arm of lw2_gfx_vga.c (the same arm the host
    # verification gates use): the five VGA I/O leaves are supplied by
    # platform/sdl3/sdl_vga.c instead of being compiled as DOS port writes.
    #
    # This define must be one the engine actually tests. Until 2026-07-14 it was
    # not, and an SDL build silently selected the no-op leaves: a black window
    # and no diagnostic. See src/lw2_gfx_vga.c:406.
    target_compile_definitions(linewars2 PRIVATE LW2_GFX_SDL_IO LW2_SND_SDL_IO)

    # SDL3.dll has to sit next to the .exe on Windows.
    if(WIN32)
        add_custom_command(TARGET linewars2 POST_BUILD
            COMMAND ${CMAKE_COMMAND} -E copy_if_different
                $<TARGET_FILE:SDL3::SDL3> $<TARGET_FILE_DIR:linewars2>
            VERBATIM)
    endif()

    # game.dat travels next to the executable so SDL_GetBasePath() finds it.
    add_custom_command(TARGET linewars2 POST_BUILD
        COMMAND ${CMAKE_COMMAND} -E copy_if_different
            ${CMAKE_SOURCE_DIR}/assets/game.dat $<TARGET_FILE_DIR:linewars2>
        VERBATIM)
endif()

if(MSVC)
    target_compile_options(linewars2 PRIVATE /W4)
else()
    target_compile_options(linewars2 PRIVATE -Wall -Wextra)
endif()

# The gates are not built here. They compile the engine with the host compiler
# and diff it against the original game's machine code running in an emulator:
#     tools/run_unit_tests.sh
# Keep them green. A cleanup that changes a gate's output is a bug, not a cleanup.
#
# tests/gates/test_gfx_runner_chunky.c is the proof that the SDL backend's chunky
# framebuffer is byte-exact: it is the planar gate runner with the storage layout
# swapped for pixel = 4*off + plane, and it passes all 431 oracle cases against
# the original VGADRV machine code. Rebuild and re-run it if you touch sdl_vga.c.
