Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
101d9d4
Fix cross-workflow CI regressions across Linux/macOS/Windows
CharlesHoskinson Feb 28, 2026
f37fc79
Fix remaining cross-workflow CI blockers
CharlesHoskinson Mar 1, 2026
a33c644
Merge remote-tracking branch 'origin/master' into ci/fix-ci-failures-…
CharlesHoskinson Mar 1, 2026
902ee6b
Fix merged-master DOS drive type and SDL3 Linux deps
CharlesHoskinson Mar 1, 2026
97b89f7
Fix CI link break in library mount API
CharlesHoskinson Mar 1, 2026
2a0b889
Fix AppleClang pedantic error in InputEvent union
CharlesHoskinson Mar 1, 2026
5230be2
Fix AppleClang unused const in application events test
CharlesHoskinson Mar 1, 2026
b8d9960
Merge remote-tracking branch 'origin/master' into ci/fix-ci-failures-…
CharlesHoskinson Mar 1, 2026
fe35e41
Fix IPC move-only expected returns and shm initialization
CharlesHoskinson Mar 1, 2026
7b1bdbd
Fix redundant-move warnings in IPC expected returns
CharlesHoskinson Mar 1, 2026
294cd35
Add missing chrono includes in POSIX IPC code
CharlesHoskinson Mar 1, 2026
f9a2011
Merge origin/master into ci/fix-ci-failures-2026-02-28
CharlesHoskinson Mar 1, 2026
d353d7d
Make IPC unit tests use portable process ID helper
CharlesHoskinson Mar 1, 2026
aedd171
Fix engine host CLI test includes and macOS warning
CharlesHoskinson Mar 1, 2026
2b05546
Update IPC-related unit tests for current APIs and strict warnings
CharlesHoskinson Mar 1, 2026
9dbbfba
Use dropdown X bounds in menu click handling
CharlesHoskinson Mar 1, 2026
be6f3ab
Add missing standard headers in update checker
CharlesHoskinson Mar 1, 2026
4178fac
Remove unused lambda captures in application handlers
CharlesHoskinson Mar 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 26 additions & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,14 @@ jobs:
cc: gcc-13
cxx: g++-13
pkg: gcc-13 g++-13
cxx_flags: ""
linker_flags: ""
- compiler: clang
cc: clang-18
cxx: clang++-18
pkg: clang-18
pkg: clang-18 libc++-18-dev libc++abi-18-dev
cxx_flags: "-stdlib=libc++"
linker_flags: "-stdlib=libc++"

steps:
- uses: actions/checkout@v4
Expand All @@ -63,6 +67,8 @@ jobs:
cmake -B build -G Ninja \
-DCMAKE_C_COMPILER=${{ matrix.cc }} \
-DCMAKE_CXX_COMPILER=${{ matrix.cxx }} \
-DCMAKE_CXX_FLAGS="${{ matrix.cxx_flags }}" \
-DCMAKE_EXE_LINKER_FLAGS="${{ matrix.linker_flags }}" \
-DCMAKE_BUILD_TYPE=Release \
-DLEGENDS_BUILD_TESTS=ON \
-DLEGENDS_HEADLESS=ON
Expand Down Expand Up @@ -101,10 +107,14 @@ jobs:
cc: gcc-13
cxx: g++-13
pkg: gcc-13 g++-13
cxx_flags: ""
linker_flags: ""
- compiler: clang
cc: clang-18
cxx: clang++-18
pkg: clang-18
pkg: clang-18 libc++-18-dev libc++abi-18-dev
cxx_flags: "-stdlib=libc++"
linker_flags: "-stdlib=libc++"

steps:
- uses: actions/checkout@v4
Expand All @@ -115,7 +125,8 @@ jobs:
sudo apt-get install -y cmake ninja-build ${{ matrix.pkg }} \
libx11-dev libxext-dev libxrandr-dev libxi-dev libxfixes-dev libxcursor-dev \
libwayland-dev libxkbcommon-dev libasound2-dev libpulse-dev \
libdbus-1-dev libudev-dev libdrm-dev libgbm-dev libegl-dev libgl-dev
libdbus-1-dev libudev-dev libdrm-dev libgbm-dev libegl-dev libgl-dev \
libxss-dev libxtst-dev

- uses: actions/cache@v4
with:
Expand All @@ -127,6 +138,8 @@ jobs:
cmake -B build -G Ninja \
-DCMAKE_C_COMPILER=${{ matrix.cc }} \
-DCMAKE_CXX_COMPILER=${{ matrix.cxx }} \
-DCMAKE_CXX_FLAGS="${{ matrix.cxx_flags }}" \
-DCMAKE_EXE_LINKER_FLAGS="${{ matrix.linker_flags }}" \
-DCMAKE_BUILD_TYPE=Release \
-DPAL_BACKEND_SDL3=ON \
-DLEGENDS_BUILD_TESTS=ON \
Expand Down Expand Up @@ -298,7 +311,7 @@ jobs:
# MSan requires all code (including libc++) to be instrumented.
# Uses clang-18 with libc++ for full coverage.
- sanitizer: memory
flags: "-fsanitize=memory -fPIE -pie -stdlib=libc++ -fno-omit-frame-pointer"
flags: "-fsanitize=memory -fPIE -pie -fno-omit-frame-pointer"
env: "MSAN_OPTIONS=halt_on_error=1"

steps:
Expand All @@ -307,17 +320,17 @@ jobs:
- name: Install dependencies
run: |
sudo apt-get update -y
sudo apt-get install -y cmake ninja-build clang-18 libc++-18-dev libc++abi-18-dev
sudo apt-get install -y cmake ninja-build clang-18 g++-13 libc++-18-dev libc++abi-18-dev

- name: Configure
run: |
cmake -B build -G Ninja \
-DCMAKE_C_COMPILER=clang-18 \
-DCMAKE_CXX_COMPILER=clang++-18 \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_CXX_FLAGS="${{ matrix.flags }}" \
-DCMAKE_CXX_FLAGS="-stdlib=libc++ ${{ matrix.flags }}" \
-DCMAKE_C_FLAGS="${{ matrix.flags }}" \
-DCMAKE_EXE_LINKER_FLAGS="${{ matrix.flags }}" \
-DCMAKE_EXE_LINKER_FLAGS="-stdlib=libc++ ${{ matrix.flags }}" \
-DLEGENDS_BUILD_TESTS=ON \
-DLEGENDS_HEADLESS=ON

Expand Down Expand Up @@ -373,14 +386,16 @@ jobs:
- name: Install dependencies
run: |
sudo apt-get update -y
sudo apt-get install -y cmake ninja-build clang-18 clang-tidy-18
sudo apt-get install -y cmake ninja-build clang-18 clang-tidy-18 libc++-18-dev libc++abi-18-dev

- name: Configure (generate compile_commands.json)
run: |
cmake -B build -G Ninja \
-DCMAKE_C_COMPILER=clang-18 \
-DCMAKE_CXX_COMPILER=clang++-18 \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_FLAGS="-stdlib=libc++" \
-DCMAKE_EXE_LINKER_FLAGS="-stdlib=libc++" \
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
-DLEGENDS_BUILD_TESTS=ON \
-DLEGENDS_HEADLESS=ON
Expand Down Expand Up @@ -416,14 +431,16 @@ jobs:
- name: Install dependencies
run: |
sudo apt-get update -y
sudo apt-get install -y cmake ninja-build clang-18
sudo apt-get install -y cmake ninja-build clang-18 libc++-18-dev libc++abi-18-dev

- name: Configure
run: |
cmake -B build -G Ninja \
-DCMAKE_C_COMPILER=clang-18 \
-DCMAKE_CXX_COMPILER=clang++-18 \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_FLAGS="-stdlib=libc++" \
-DCMAKE_EXE_LINKER_FLAGS="-stdlib=libc++" \
-DENABLE_FUZZING=ON \
-DENABLE_ASAN=ON \
-DLEGENDS_BUILD_TESTS=ON \
Expand Down
6 changes: 4 additions & 2 deletions .github/workflows/pal-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,14 @@ jobs:
sudo apt-get install -y build-essential cmake g++-13 \
libx11-dev libxext-dev libxrandr-dev libxi-dev libxfixes-dev libxcursor-dev \
libwayland-dev libxkbcommon-dev libasound2-dev libpulse-dev \
libdbus-1-dev libudev-dev libdrm-dev libgbm-dev libegl-dev libgl-dev
libdbus-1-dev libudev-dev libdrm-dev libgbm-dev libegl-dev libgl-dev \
libxss-dev libxtst-dev

- name: Build SDL3 from source
run: |
git clone --depth 1 https://github.com/libsdl-org/SDL.git -b main SDL3-src
cmake -B SDL3-src/build -S SDL3-src -DCMAKE_BUILD_TYPE=Release
cmake -B SDL3-src/build -S SDL3-src -DCMAKE_BUILD_TYPE=Release \
-DSDL_X11_XSCRNSAVER=OFF -DSDL_X11_XTEST=OFF
cmake --build SDL3-src/build -j$(nproc)
sudo cmake --install SDL3-src/build

Expand Down
181 changes: 122 additions & 59 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -724,6 +724,17 @@ if(LEGENDS_BUILD_TESTS)
gsl_CONFIG_CONTRACT_VIOLATION_THROWS=1
)

# gtest_discover_tests runs the executable during build; copy SDL3 runtime
# DLL on Windows so test discovery can load dependencies.
if(WIN32 AND PAL_BACKEND_SDL3 AND TARGET SDL3::SDL3-shared)
add_custom_command(TARGET legends_unit_tests POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"$<TARGET_FILE:SDL3::SDL3-shared>"
"$<TARGET_FILE_DIR:legends_unit_tests>"
COMMENT "Copying SDL3.dll to legends_unit_tests output directory"
)
endif()

gtest_discover_tests(legends_unit_tests
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
PROPERTIES LABELS "unit"
Expand Down Expand Up @@ -906,6 +917,15 @@ if(LEGENDS_BUILD_TESTS)
LEGENDS_LIBRARY_MODE=1
)

if(WIN32 AND PAL_BACKEND_SDL3 AND TARGET SDL3::SDL3-shared)
add_custom_command(TARGET legends_integration_tests POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"$<TARGET_FILE:SDL3::SDL3-shared>"
"$<TARGET_FILE_DIR:legends_integration_tests>"
COMMENT "Copying SDL3.dll to legends_integration_tests output directory"
)
endif()

gtest_discover_tests(legends_integration_tests
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
PROPERTIES
Expand Down Expand Up @@ -1045,32 +1065,91 @@ endif()
# Main Executable
# ─────────────────────────────────────────────────────────────────────────────

set(LEGENDS_APP_EXEC_SOURCES
src/app/application.cpp
src/app/action_bus.cpp
src/app/capture.cpp
src/app/input_mapper.cpp
src/app/save_manager.cpp
src/app/menu_system.cpp
src/app/hotkey_dispatcher.cpp
src/app/cli_parser.cpp
src/app/config_parser.cpp
src/app/platform_dirs.cpp
src/app/scancode_map.cpp
src/app/mount_manager.cpp
src/app/image_validator.cpp
src/app/zmbv_codec.cpp
src/app/video_capture.cpp
src/app/mapper_ui.cpp
src/app/save_browser.cpp
# Phase 3: Enhanced Features
src/app/joystick_mapper.cpp
src/app/shader_renderer.cpp
src/app/shader_presets.cpp
src/app/ai_config.cpp
src/app/ai_http_client.cpp
src/app/ai_screen_context.cpp
src/app/ai_panel.cpp
src/app/audio_mixer.cpp
src/app/midi_config.cpp
src/app/printer_manager.cpp
src/app/ttf_renderer.cpp
src/app/ipx_config.cpp
src/app/glide_config.cpp
src/app/pc98_config.cpp
# Phase 4: Polish & Release
src/app/file_logger.cpp
src/app/error_reporter.cpp
src/app/crash_breadcrumb.cpp
src/app/crash_reporter.cpp
# Phase 4 Sprint 4: SSIM
src/app/ssim.cpp
# Phase 4 Sprint 6: Portable mode
src/app/portable_mode.cpp
# Phase 4 Sprint 7: Update checker (platform-conditional)
src/app/update_checker.cpp
$<$<PLATFORM_ID:Windows>:src/app/update_checker_win.cpp>
$<$<PLATFORM_ID:Darwin>:src/app/update_checker_mac.cpp>
$<$<AND:$<NOT:$<PLATFORM_ID:Windows>>,$<NOT:$<PLATFORM_ID:Darwin>>>:src/app/update_checker_linux.cpp>
external/glad/glad.c
engine/src/libs/zmbv/zmbv.cpp
engine/src/libs/zmbv/zmbv_stubs.cpp # ZMBV codec fallback when C_SSHOT is disabled
)

# Build the interactive emulator executable when SDL2 is available
if(PAL_BACKEND_SDL2)
add_executable(project_legends
src/main.cpp
${LEGENDS_APP_EXEC_SOURCES}
)

legends_set_strict_cxx_standard(project_legends)

target_include_directories(project_legends PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_CURRENT_SOURCE_DIR}/external/SDL2/include
${CMAKE_CURRENT_SOURCE_DIR}/src
${CMAKE_CURRENT_SOURCE_DIR}/external
${CMAKE_CURRENT_SOURCE_DIR}/external/glad
${CMAKE_CURRENT_SOURCE_DIR}/engine/src/libs # ZMBV codec headers
${CMAKE_BINARY_DIR}/include
)

target_link_directories(project_legends PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/external/SDL2/lib
)
if(WIN32)
target_include_directories(project_legends PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/external/SDL2/include
)
target_link_directories(project_legends PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/external/SDL2/lib
)
endif()

# In IPC mode, link the proxy (MIT) instead of legends_core (GPL).
# In monolithic mode (default), link legends_core directly.
if(LEGENDS_USE_IPC)
target_link_libraries(project_legends PRIVATE
legends_proxy
legends_pal
mingw32
SDL2main
SDL2
)
target_compile_definitions(project_legends PRIVATE
LEGENDS_USE_IPC=1
Expand All @@ -1079,73 +1158,57 @@ if(PAL_BACKEND_SDL2)
target_link_libraries(project_legends PRIVATE
legends_core
legends_pal
gsl::gsl-lite-v1
)
endif()

if(WIN32)
target_link_libraries(project_legends PRIVATE
mingw32
SDL2main
SDL2
)
else()
target_link_libraries(project_legends PRIVATE SDL2::SDL2)
endif()

# Copy SDL2.dll to output directory
add_custom_command(TARGET project_legends POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${CMAKE_CURRENT_SOURCE_DIR}/external/SDL2/bin/SDL2.dll"
"$<TARGET_FILE_DIR:project_legends>"
target_compile_definitions(project_legends PRIVATE
gsl_CONFIG_DEFAULTS_VERSION=1
gsl_CONFIG_CONTRACT_CHECKING_ON
gsl_CONFIG_CONTRACT_VIOLATION_THROWS=1
)

# Phase 3: Optional feature-gated library linking
if(LEGENDS_ENABLE_AI AND CURL_FOUND)
target_link_libraries(project_legends PRIVATE CURL::libcurl)
target_compile_definitions(project_legends PRIVATE LEGENDS_HAS_CURL=1)
endif()
if(LEGENDS_ENABLE_FLUIDSYNTH AND FluidSynth_FOUND)
target_link_libraries(project_legends PRIVATE FluidSynth::FluidSynth)
target_compile_definitions(project_legends PRIVATE LEGENDS_HAS_FLUIDSYNTH=1)
endif()
if(LEGENDS_ENABLE_MT32 AND TARGET mt32emu)
target_link_libraries(project_legends PRIVATE mt32emu)
target_compile_definitions(project_legends PRIVATE LEGENDS_HAS_MT32=1)
endif()

# Copy SDL2.dll to output directory (vendored Windows layout)
if(WIN32 AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/external/SDL2/bin/SDL2.dll")
add_custom_command(TARGET project_legends POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${CMAKE_CURRENT_SOURCE_DIR}/external/SDL2/bin/SDL2.dll"
"$<TARGET_FILE_DIR:project_legends>"
)
endif()

message(STATUS "Building project_legends executable with SDL2")
endif()

# Build the interactive emulator executable when SDL3 is available
if(PAL_BACKEND_SDL3)
add_executable(project_legends
src/main.cpp
src/app/application.cpp
src/app/action_bus.cpp
src/app/capture.cpp
src/app/input_mapper.cpp
src/app/save_manager.cpp
src/app/menu_system.cpp
src/app/hotkey_dispatcher.cpp
src/app/cli_parser.cpp
src/app/config_parser.cpp
src/app/platform_dirs.cpp
src/app/scancode_map.cpp
src/app/mount_manager.cpp
src/app/image_validator.cpp
src/app/video_capture.cpp
src/app/mapper_ui.cpp
src/app/save_browser.cpp
# Phase 3: Enhanced Features
src/app/joystick_mapper.cpp
src/app/shader_renderer.cpp
src/app/shader_presets.cpp
src/app/ai_config.cpp
src/app/ai_http_client.cpp
src/app/ai_screen_context.cpp
src/app/ai_panel.cpp
src/app/audio_mixer.cpp
src/app/midi_config.cpp
src/app/printer_manager.cpp
src/app/ttf_renderer.cpp
src/app/ipx_config.cpp
src/app/glide_config.cpp
src/app/pc98_config.cpp
# Phase 4: Polish & Release
src/app/file_logger.cpp
src/app/error_reporter.cpp
src/app/crash_breadcrumb.cpp
src/app/crash_reporter.cpp
# Phase 4 Sprint 4: SSIM
src/app/ssim.cpp
# Phase 4 Sprint 6: Portable mode
src/app/portable_mode.cpp
# Phase 4 Sprint 7: Update checker (platform-conditional)
src/app/update_checker.cpp
$<$<PLATFORM_ID:Windows>:src/app/update_checker_win.cpp>
$<$<PLATFORM_ID:Darwin>:src/app/update_checker_mac.cpp>
$<$<AND:$<NOT:$<PLATFORM_ID:Windows>>,$<NOT:$<PLATFORM_ID:Darwin>>>:src/app/update_checker_linux.cpp>
external/glad/glad.c
engine/src/libs/zmbv/zmbv.cpp # ZMBV codec for video capture
${LEGENDS_APP_EXEC_SOURCES}
)

legends_set_strict_cxx_standard(project_legends)
Expand Down
Loading
Loading