# nxdk-gles11-app — Original Xbox / NXDK + OpenGL ES 1.1 (nxdk-gles11)
# Copyright (c) 2026 wutno (aaron@installgentoo.net)
#
# nxdk and nxdk-gles11 are vendored as submodules under external/. First checkout:
#   git submodule update --init --recursive
#   ( then build nxdk once: cd external/nxdk && make NXDK_ONLY=y && make tools )
# Configure & build (no external NXDK_DIR needed — the in-tree nxdk is used automatically):
#   cmake -B build -DCMAKE_BUILD_TYPE=Release
#   cmake --build build
# Output: build/bin/default.xbe (and build/bin/<name>.exe)
# Override the vendored copy by passing -DCMAKE_TOOLCHAIN_FILE=... or setting NXDK_DIR in the env.
# NOTE: after changing anything under external/nxdk or external/nxdk-gles11, rm -rf build first.

cmake_minimum_required(VERSION 3.16)

# Pick the nxdk toolchain before the first project() call. Precedence:
#   1. an explicit -DCMAKE_TOOLCHAIN_FILE (respected, we touch nothing)
#   2. NXDK_DIR already set in the environment (external nxdk)
#   3. the vendored in-tree copy at external/nxdk
# so a bare `cmake -B build` just works against the submodule.
if(NOT DEFINED CMAKE_TOOLCHAIN_FILE)
    if(DEFINED ENV{NXDK_DIR})
        set(_NXDK_ROOT "$ENV{NXDK_DIR}")
    else()
        set(_NXDK_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/external/nxdk")
        set(ENV{NXDK_DIR} "${_NXDK_ROOT}")
    endif()
    if(NOT EXISTS "${_NXDK_ROOT}/share/toolchain-nxdk.cmake")
        message(FATAL_ERROR
            "nxdk toolchain not found at ${_NXDK_ROOT}.\n"
            "Vendored copy missing? Run: git submodule update --init --recursive")
    endif()
    set(CMAKE_TOOLCHAIN_FILE "${_NXDK_ROOT}/share/toolchain-nxdk.cmake"
        CACHE FILEPATH "nxdk toolchain (auto: vendored external/nxdk)")
endif()

project(nxdk-gles11-app LANGUAGES C)

# NXDK_DIR is defined by the toolchain (from $ENV{NXDK_DIR}); guard in case a custom toolchain didn't.
if(NOT DEFINED NXDK_DIR)
    message(FATAL_ERROR "NXDK_DIR not set by the toolchain file")
endif()

set(XBE_TITLE "${PROJECT_NAME}" CACHE STRING "Title string embedded in default.xbe")
option(BUILD_XISO "Also produce a .iso via extract-xiso" OFF)
option(NXDK_GLES11_WITH_GL4ES "Enable gl4es desktop-GL wrapper inside nxdk-gles11" OFF)

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)

# --- optimisation / LTO --------------------------------------------------------
if(NOT CMAKE_BUILD_TYPE)
    set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE)
endif()
# Release: -O3 -DNDEBUG (CMake default) plus fp/codegen options that are safe for this code.
# nxdk-cc already sets -march=pentium3; the nxdk libs (pbkit, SDL2, pdclib) are prebuilt and
# unaffected by these flags.
set(RELEASE_C_OPTS
    -fomit-frame-pointer
    -fno-math-errno
    -fno-trapping-math
    -ffp-contract=fast
    -fno-plt
    -fmerge-all-constants
)
# The nxdk toolchain feeds <FLAGS> (CMAKE_C_FLAGS_<CONFIG>) to nxdk-link too, where lld
# warns about each unknown option — so keep the per-config flags to what lld tolerates and
# apply the extra codegen options compile-only via add_compile_options.
set(CMAKE_C_FLAGS_RELEASE "")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "-g")
add_compile_options(
    "$<$<CONFIG:Release>:-O3;-DNDEBUG>"
    "$<$<CONFIG:RelWithDebInfo>:-O2;-DNDEBUG>"
    "$<$<CONFIG:Release,RelWithDebInfo>:${RELEASE_C_OPTS}>"
)

# Link-time optimisation, on by default for Release. Set before add_subdirectory so nxdk-gles11's
# objects are bitcode too. nxdk's lld-link does the LTO link automatically on clang's bitcode and
# doesn't understand -flto as a link flag, so keep IPO's link options empty.
if(CMAKE_BUILD_TYPE STREQUAL "Release")
    set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
endif()
set(CMAKE_C_LINK_OPTIONS_IPO "")

# --- nxdk-gles11 (submodule) -------------------------------------------------
add_subdirectory(external/nxdk-gles11 nxdk-gles11)

# --- application -------------------------------------------------------------
add_executable(${PROJECT_NAME}
    src/main.c
    src/render.c
    src/lights.c
    src/textures.c
    src/ribbon.c
    src/stats.c
    src/overlay.c
    src/input.c
    src/profile.c
)
target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_SOURCE_DIR}/src ${NXDK_DIR}/lib/sdl/SDL2/include)
target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra)
target_compile_definitions(${PROJECT_NAME} PRIVATE XBOX)   # required by nxdk SDL2 headers
target_link_libraries(${PROJECT_NAME} PRIVATE
    GLESv1_CM
    ${NXDK_DIR}/lib/libpbkit.lib
    ${NXDK_DIR}/lib/libSDL2.lib
)
if(NXDK_GLES11_WITH_GL4ES)
    target_link_libraries(${PROJECT_NAME} PRIVATE GL)
endif()

# --- .exe -> default.xbe -----------------------------------------------------
set(XBE_OUT ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/default.xbe)
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
    COMMAND ${NXDK_DIR}/tools/cxbe/cxbe
            -OUT:${XBE_OUT}
            -TITLE:${XBE_TITLE}
            $<TARGET_FILE:${PROJECT_NAME}>
    COMMENT "cxbe -> ${XBE_OUT}"
    VERBATIM
)

# --- optional xiso -----------------------------------------------------------
if(BUILD_XISO)
    set(XISO_DIR ${CMAKE_BINARY_DIR}/xiso)
    add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
        COMMAND ${CMAKE_COMMAND} -E make_directory ${XISO_DIR}
        COMMAND ${CMAKE_COMMAND} -E copy ${XBE_OUT} ${XISO_DIR}/default.xbe
        COMMAND ${NXDK_DIR}/tools/extract-xiso/build/extract-xiso -c ${XISO_DIR}
                ${CMAKE_BINARY_DIR}/${PROJECT_NAME}.iso
        COMMENT "extract-xiso -> ${PROJECT_NAME}.iso"
        VERBATIM
    )
endif()
