Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion PLAN.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ game until that gate is met.
interpreter (the correctness floor running the firmware's own copied
bytes). The firmware menu runs interpreted at first, promoted to banks
later.
- **Host:** SDL2, single window stacked 256×384 (engine A top / B
- **Host:** SDL3 by default, single window stacked 256×384 (engine A top / B
bottom), software rendering; mouse → ARM7 TSC touch.

## Inputs (verified, in `bios/`, git-ignored)
Expand Down
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,10 @@ cmake -G Ninja -B runner/build runner
cmake --build runner/build
```

SDL2 is optional at configure time; without it, the runner is headless and
interactive presentation is unavailable.
SDL3 is the default host presentation backend. Configure with
`-DNDS_SDL_BACKEND=SDL2` for the compatibility backend, or
`-DNDS_SDL_BACKEND=NONE` for a headless runner with no interactive
presentation.

### Game-owned static banks

Expand Down
59 changes: 59 additions & 0 deletions docs/sdl3-default.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# SDL3 default frontend

## Goal

`nds_runner` uses SDL3 as the default interactive host frontend. SDL2 remains
available as an explicit compatibility backend, and headless builds remain
available for non-interactive tooling.

## Build contract

- `NDS_SDL_BACKEND=SDL3` is the default and requires `SDL3::SDL3`.
- `NDS_SDL_BACKEND=SDL2` selects the compatibility backend and requires
`SDL2::SDL2`.
- `NDS_SDL_BACKEND=NONE` builds without the SDL presentation layer.
- `NDS_ENABLE_COMPUTE_RENDERER=ON` requires `NDS_SDL_BACKEND=SDL3` or `SDL2`
because the compute renderer owns an SDL-created GL context.

## Implementation notes

The compatibility layer is local to `runner/src/frontend.cpp` and
`runner/src/melonds_compute/ComputeHost.cpp`. The public runner behavior stays
the same: one stacked DS display window, keyboard/gamepad input, mouse/touch
mapping, optional audio, and the existing software/compute renderer switch.

SDL3 uses `SDL_AudioStream` through `SDL_OpenAudioDeviceStream`. SDL2 keeps the
existing callback-backed ring buffer. SDL3 exclusive fullscreen currently maps
to SDL3's fullscreen window state; display-mode selection can be added later if
a title needs true mode switching.

## Verified commands

```powershell
& C:\msys64\mingw64\bin\cmake.exe -G Ninja `
-S F:\Projects\ndsrecomp\worktrees\ndsrecomp-sdl3-default\runner `
-B F:\Projects\ndsrecomp\worktrees\ndsrecomp-sdl3-default\runner\build-sdl3-default `
-DCMAKE_BUILD_TYPE=Release `
-DNDS_ENABLE_COMPUTE_RENDERER=ON `
-DNDS_BOOTSTRAP_FIRMWARE=ON `
-DNDS_GENERATED_DIR=F:\Projects\ndsrecomp\ndsrecomp\generated `
-DCMAKE_PREFIX_PATH=C:\msys64\mingw64\lib\cmake
& C:\msys64\mingw64\bin\cmake.exe --build `
F:\Projects\ndsrecomp\worktrees\ndsrecomp-sdl3-default\runner\build-sdl3-default `
--target nds_runner -j 12
```

```powershell
& C:\msys64\mingw64\bin\cmake.exe -G Ninja `
-S F:\Projects\ndsrecomp\worktrees\ndsrecomp-sdl3-default\runner `
-B F:\Projects\ndsrecomp\worktrees\ndsrecomp-sdl3-default\runner\build-sdl2-fallback `
-DCMAKE_BUILD_TYPE=Release `
-DNDS_SDL_BACKEND=SDL2 `
-DNDS_ENABLE_COMPUTE_RENDERER=ON `
-DNDS_BOOTSTRAP_FIRMWARE=ON `
-DNDS_GENERATED_DIR=F:\Projects\ndsrecomp\ndsrecomp\generated `
-DCMAKE_PREFIX_PATH=C:\msys64\mingw64\lib\cmake
& C:\msys64\mingw64\bin\cmake.exe --build `
F:\Projects\ndsrecomp\worktrees\ndsrecomp-sdl3-default\runner\build-sdl2-fallback `
--target nds_runner -j 12
```
8 changes: 4 additions & 4 deletions docs/wiimmfi-runbook.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ Verified present on this machine:
the `-G Ninja` generator.
- `g++.exe (Rev9, Built by MSYS2 project) 15.2.0` at
`C:\msys64\mingw64\bin\g++.exe`.
- SDL2 CMake config at `C:\msys64\mingw64\lib\cmake\SDL2` (required because
the runner defaults `NDS_ENABLE_COMPUTE_RENDERER=ON`, which hard-requires
SDL2 at configure time).
- SDL3 CMake config at `C:\msys64\mingw64\lib\cmake\SDL3` (default host
presentation backend). SDL2 remains available with
`-DNDS_SDL_BACKEND=SDL2`.
- `ccache` auto-detected and enabled by the framework's
`NdsCompilerCache.cmake` (`AUTO` policy) — configure log prints
`ndsrecomp: compiler cache enabled: C:/msys64/mingw64/bin/ccache.exe`.
Expand Down Expand Up @@ -152,7 +152,7 @@ Configure (PowerShell):

Result: configure succeeded in **1.6 seconds**. `CMakeCache.txt` confirms
`NDS_TITLE_BANK_DIR=F:/Projects/ndsrecomp/mariokartdsrecomp-wiimmfi/generated/recomp`,
`NDS_BOOTSTRAP_FIRMWARE=ON`, `SDL2_DIR=C:/msys64/mingw64/lib/cmake/SDL2`,
`NDS_BOOTSTRAP_FIRMWARE=ON`, `SDL3_DIR=C:/msys64/mingw64/lib/cmake/SDL3`,
`CMAKE_C_COMPILER=C:/msys64/mingw64/bin/cc.exe`.

Build:
Expand Down
36 changes: 28 additions & 8 deletions runner/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ option(NDS_BOOTSTRAP_FIRMWARE
option(NDS_ENABLE_COMPUTE_RENDERER
"Build the preferred melonDS OpenGL 4.3 compute renderer"
ON)
set(NDS_SDL_BACKEND "SDL3" CACHE STRING
"Host presentation backend: SDL3, SDL2, or NONE")
set_property(CACHE NDS_SDL_BACKEND PROPERTY STRINGS SDL3 SDL2 NONE)
option(NDS_ENABLE_PCAP_BACKEND
"Build the vendored melonDS Net_PCap backend (dynamically loads Npcap/WinPcap at runtime; off by default per docs/adr-melonds-wifi-vendoring.md §2)"
OFF)
Expand Down Expand Up @@ -541,16 +544,33 @@ if(SM64DS_BANK_SOURCES)
endif()
endif()

# SDL is a host-only presentation layer. The runner remains buildable without
# it for headless deterministic/oracle work; --interactive reports that the
# configured binary has no frontend in that case.
find_package(SDL2 CONFIG QUIET)
if(TARGET SDL2::SDL2)
target_compile_definitions(nds_runner PRIVATE NDS_HAVE_SDL2=1)
# SDL is a host-only presentation layer. SDL3 is the default runtime frontend;
# SDL2 and a no-frontend headless build are explicit compatibility choices.
if(NDS_SDL_BACKEND STREQUAL "SDL3")
find_package(SDL3 CONFIG REQUIRED)
if(NOT TARGET SDL3::SDL3)
message(FATAL_ERROR "NDS_SDL_BACKEND=SDL3 requires target SDL3::SDL3")
endif()
target_compile_definitions(nds_runner PRIVATE
NDS_HAVE_SDL3=1
NDS_SDL_BACKEND_NAME="SDL3")
target_link_libraries(nds_runner PRIVATE SDL3::SDL3)
elseif(NDS_SDL_BACKEND STREQUAL "SDL2")
find_package(SDL2 CONFIG REQUIRED)
if(NOT TARGET SDL2::SDL2)
message(FATAL_ERROR "NDS_SDL_BACKEND=SDL2 requires target SDL2::SDL2")
endif()
target_compile_definitions(nds_runner PRIVATE
NDS_HAVE_SDL2=1
NDS_SDL_BACKEND_NAME="SDL2")
target_link_libraries(nds_runner PRIVATE SDL2::SDL2)
elseif(NDS_SDL_BACKEND STREQUAL "NONE")
target_compile_definitions(nds_runner PRIVATE NDS_SDL_BACKEND_NAME="NONE")
else()
message(FATAL_ERROR "NDS_SDL_BACKEND must be SDL3, SDL2, or NONE")
endif()
if(NDS_ENABLE_COMPUTE_RENDERER AND NOT TARGET SDL2::SDL2)
message(FATAL_ERROR "NDS_ENABLE_COMPUTE_RENDERER requires SDL2")
if(NDS_ENABLE_COMPUTE_RENDERER AND NDS_SDL_BACKEND STREQUAL "NONE")
message(FATAL_ERROR "NDS_ENABLE_COMPUTE_RENDERER requires NDS_SDL_BACKEND=SDL3 or SDL2")
endif()
if(NDS_ENABLE_COMPUTE_RENDERER AND CMAKE_DL_LIBS)
target_link_libraries(nds_runner PRIVATE ${CMAKE_DL_LIBS})
Expand Down
Loading