From e63016efc2a22c5ceb709368566493cdd16dd17b Mon Sep 17 00:00:00 2001 From: Panagiotis Georgiadis Date: Sun, 1 Mar 2026 22:52:54 +0100 Subject: [PATCH] Switch Dreamcast to GPF SDL for DMA video and hardware palette Replace kos-ports SDL with GPF SDL (SDL-dreamhal--GLDC) which provides PVR DMA framebuffer transfer and native 8bpp hardware palette support. This bypasses the manual 8bpp-to-16bpp conversion in dc_video.cpp, roughly doubling framerate from ~20-25 to ~40-50 FPS. Signed-off-by: Panagiotis Georgiadis --- CMake/platforms/dreamcast.cmake | 15 +++++++++++---- CMake/platforms/dreamcast.toolchain.cmake | 10 ++++++---- Packaging/dreamcast/.gitignore | 3 +++ Packaging/dreamcast/build.sh | 15 +++++++++++++++ Source/utils/display.cpp | 11 +++++++++++ 5 files changed, 46 insertions(+), 8 deletions(-) diff --git a/CMake/platforms/dreamcast.cmake b/CMake/platforms/dreamcast.cmake index 5f9502297..74ea3c64c 100644 --- a/CMake/platforms/dreamcast.cmake +++ b/CMake/platforms/dreamcast.cmake @@ -24,6 +24,12 @@ set(DEFAULT_AUDIO_RESAMPLING_QUALITY 0) set(DEFAULT_PER_PIXEL_LIGHTING 0) set(DEVILUTIONX_PALETTE_TRANSPARENCY_BLACK_16_LUT ON CACHE BOOL "" FORCE) +# GPF SDL supports 8bpp with hardware palette - lets SDL handle the +# palette-to-RGB conversion internally via PVR DMA, avoiding the +# manual 8bpp->16bpp conversion in dc_video.cpp entirely. +set(SDL1_VIDEO_MODE_BPP 8) +set(SDL1_VIDEO_MODE_FLAGS SDL_DOUBLEBUF|SDL_HWSURFACE) + set(DEFAULT_WIDTH 640) set(DEFAULT_HEIGHT 480) @@ -32,11 +38,12 @@ set(UNPACKED_SAVES ON) set(DEVILUTIONX_GAMEPAD_TYPE Generic) -set(JOY_BUTTON_A 0) +# GPF SDL button IDs (from SDL_dreamcast.h SDL_DC_button enum) +set(JOY_BUTTON_A 2) set(JOY_BUTTON_B 1) -set(JOY_BUTTON_X 2) -set(JOY_BUTTON_Y 3) -set(JOY_BUTTON_START 4) +set(JOY_BUTTON_X 5) +set(JOY_BUTTON_Y 6) +set(JOY_BUTTON_START 3) set(JOY_HAT_DPAD_UP_HAT 0) set(JOY_HAT_DPAD_DOWN_HAT 0) diff --git a/CMake/platforms/dreamcast.toolchain.cmake b/CMake/platforms/dreamcast.toolchain.cmake index cfa1f7b57..a08c024e0 100644 --- a/CMake/platforms/dreamcast.toolchain.cmake +++ b/CMake/platforms/dreamcast.toolchain.cmake @@ -15,10 +15,11 @@ set(DREAMCAST ON) # 3. Add our include paths # KOS ports often hide headers in subdirectories +# GPF SDL installs to KOS_BASE/addons/include/dreamcast/SDL/ list(APPEND CMAKE_INCLUDE_PATH "$ENV{KOS_PORTS}/include/zlib" "$ENV{KOS_PORTS}/include/bzlib" - "$ENV{KOS_PORTS}/include/SDL" + "$ENV{KOS_BASE}/addons/include/dreamcast/SDL" ) # 4. Force libraries (The "Nuclear Option" for sub-projects) @@ -28,9 +29,10 @@ set(ZLIB_LIBRARY "$ENV{KOS_PORTS}/lib/libz.a" CACHE FILEPATH "ZLIB Library" FORC set(BZIP2_INCLUDE_DIR "$ENV{KOS_PORTS}/include/bzlib" CACHE PATH "BZip2 Include Dir" FORCE) set(BZIP2_LIBRARIES "$ENV{KOS_PORTS}/lib/libbz2.a" CACHE FILEPATH "BZip2 Library" FORCE) -# 5. Force SDL1 - MUST set SDL_LIBRARY without -lpthreads (KOS has built-in threading) -set(SDL_INCLUDE_DIR "$ENV{KOS_PORTS}/include/SDL" CACHE PATH "SDL Include Dir" FORCE) -set(SDL_LIBRARY "$ENV{KOS_PORTS}/lib/libSDL.a" CACHE FILEPATH "SDL Library" FORCE) +# 5. Force SDL1 - GPF SDL (SDL-dreamhal--GLDC) for DMA video and hardware palette +# GPF SDL installs via its Makefile.dc to KOS_BASE/addons/{lib,include}/dreamcast/ +set(SDL_INCLUDE_DIR "$ENV{KOS_BASE}/addons/include/dreamcast/SDL" CACHE PATH "SDL Include Dir" FORCE) +set(SDL_LIBRARY "$ENV{KOS_BASE}/addons/lib/dreamcast/libSDL.a" CACHE FILEPATH "SDL Library" FORCE) # 6. Fix libfmt and magic_enum compilation # Disable long double support because sh4-gcc's long double (64-bit) confuses libfmt diff --git a/Packaging/dreamcast/.gitignore b/Packaging/dreamcast/.gitignore index d9ebaa131..54690efba 100644 --- a/Packaging/dreamcast/.gitignore +++ b/Packaging/dreamcast/.gitignore @@ -35,6 +35,9 @@ File[0-9]*.xxx File[0-9]*.gif File[0-9]*.smk +# GPF SDL source (cloned by build.sh) +SDL-gpf/ + # Build tool output *.o diff --git a/Packaging/dreamcast/build.sh b/Packaging/dreamcast/build.sh index e5b2fe7e6..db53dc789 100755 --- a/Packaging/dreamcast/build.sh +++ b/Packaging/dreamcast/build.sh @@ -30,6 +30,21 @@ if [ ! -x "${MKDCDISC}" ]; then exit 1 fi +GPF_SDL_DIR="${SCRIPT_DIR}/SDL-gpf" +GPF_SDL_LIB="${KOS_BASE}/addons/lib/dreamcast/libSDL.a" + +if [ ! -f "${GPF_SDL_LIB}" ]; then + echo "Building GPF SDL (SDL-dreamhal--GLDC) for DMA video..." + if [ ! -d "${GPF_SDL_DIR}" ]; then + git clone --depth 1 -b SDL-dreamhal--GLDC \ + https://github.com/GPF/SDL-1.2 "${GPF_SDL_DIR}" + fi + make -C "${GPF_SDL_DIR}" -f Makefile.dc -j"$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 4)" + echo "GPF SDL installed to ${GPF_SDL_LIB}" +else + echo "GPF SDL already installed at ${GPF_SDL_LIB}" +fi + rm -rf "${BUILD_DIR}" mkdir -p "${BUILD_DIR}" diff --git a/Source/utils/display.cpp b/Source/utils/display.cpp index 80d0aad11..85744e8c6 100644 --- a/Source/utils/display.cpp +++ b/Source/utils/display.cpp @@ -63,6 +63,10 @@ #endif #endif +#ifdef __DREAMCAST__ +#include +#endif + namespace devilution { extern SDLSurfaceUniquePtr RendererTextureSurface; /** defined in dx.cpp */ @@ -485,6 +489,13 @@ void SetVideoModeToPrimary(bool fullscreen, int width, int height) #ifdef __3DS__ flags &= ~SDL_FULLSCREEN; flags |= Get3DSScalingFlag(*GetOptions().Graphics.fitToScreen, width, height); +#endif +#ifdef __DREAMCAST__ + SDL_DC_SetVideoDriver(SDL_DC_DMA_VIDEO); + SDL_DC_VerticalWait(SDL_FALSE); + SDL_DC_ShowAskHz(SDL_FALSE); + SDL_DC_EmulateKeyboard(SDL_FALSE); + SDL_DC_EmulateMouse(SDL_FALSE); #endif SetVideoMode(width, height, SDL1_VIDEO_MODE_BPP, flags); if (OutputRequiresScaling())