Skip to content

Add Dreamcast platform support#8489

Open
drpaneas wants to merge 8 commits intodiasurgical:masterfrom
drpaneas:dreamcast-pr
Open

Add Dreamcast platform support#8489
drpaneas wants to merge 8 commits intodiasurgical:masterfrom
drpaneas:dreamcast-pr

Conversation

@drpaneas
Copy link
Copy Markdown

@drpaneas drpaneas commented Mar 1, 2026

The performance is not great because it uses 640x480, and the rendering is not using PVR but SDL 1.2 plus some 8bpp paletted to 16bpp RGB565 conversion. Apart from that, I have some audio glitches. The FPS is ~20-25 in most of the game. I tested with Flycast emulator: town, dungeon, combat, saves all working fine. I got assistance from Claude and Cursor, since I am no C++ savvy. I am using #ifdef __DREAMCAST__ to squeeze some performance. I also has some really long waiting times (loading...) due to MPQ assets in the very beginning or during any scene transitioning.

PS: I have not tested the final version of it in real HW. I just did a home relocation and my DC is somewhere hidden in a box :/

UPDATE: After checking #7453 I also applied the same idea of using SDL with GPF SDL (SDL-dreamhal--GLDC). Now it gets 40-50 FPS :D


Build system:

  • CMake toolchain and platform config for SH4 cross-compilation
  • Bundled libfmt patch for SH4 non-standard long double (64-bit)
  • One-step build script producing a bootable CDI disc image
  • POSIX stubs (flockfile/funlockfile) for KOS newlib gaps

Video:

  • 8bpp paletted to 16bpp RGB565 conversion pipeline
  • Cache-aligned palette LUT with packed 32-bit write path
  • SH4 prefetch hints for the hot conversion loop

Save system:

  • zlib-compressed save containers with versioned header
  • /ram/ for fast in-session access, mirrored to VMU for persistence
  • FNV-1a hashed filenames for VMU filesystem compatibility

Memory optimizations:

  • UI background art caching to reduce CD reads
  • On-demand SFX loading with music muting during loads
  • Cow sprites, towner animations, and stash UI skipped
  • Non-throwing allocation for dungeon cel re-encoding
  • UI assets freed before level loading

Engine adaptations (guarded by #ifdef __DREAMCAST__):

  • Palette lighting and color cycling disabled
  • Movie/splash playback skipped
  • Sound loading failures made non-fatal
  • Read-only filesystem test skipped
  • SDL_GetBasePath/SDL_GetPrefPath backports

For testing this PR you need to do:

  • Install KallistiOS (KOS) with kos-ports providing SDL 1.2, zlib, bzip2, and Lua. That's pretty std for homebrew DC development.
  • Install mkdcdisc
  • Copy game data cp /path/to/DIABDAT.MPQ Packaging/dreamcast/cd_root/
  • Build it: KOS_BASE=/path/to/kos MKDCDISC=/path/to/mkdcdisc ./Packaging/dreamcast/build.sh

Youtube video of gameplay: https://youtu.be/oynvVJHfTxs

drpaneas added 2 commits March 1, 2026 21:25
Signed-off-by: Panagiotis Georgiadis <pgeorgia@redhat.com>
Made-with: Cursor
Signed-off-by: Panagiotis Georgiadis <pgeorgia@redhat.com>
@StephenCWills
Copy link
Copy Markdown
Member

Can someone fill me in on why #7453 couldn't be merged? Does this port solve those problems somehow?

drpaneas added 3 commits March 1, 2026 22:53
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 <pgeorgia@redhat.com>
Preload frequently used effects and rate-limit on-demand loads so missing or slow files are skipped instead of stalling gameplay frames.
Limit save-slot probing on hero selection, skip unnecessary hero-item reads for list rendering, and throttle repeated progress-event error logs that slow loading.

Signed-off-by: Panagiotis Georgiadis <pgeorgia@redhat.com>
@drpaneas
Copy link
Copy Markdown
Author

drpaneas commented Mar 1, 2026

Can someone fill me in on why #7453 couldn't be merged? Does this port solve those problems somehow?

  1. no saves
  2. no audio

yes I do provide both.

Prevent out-of-bounds access if the sgSFX vector index exceeds the
fixed-size SfxLoadRetryAfterMs array.

Signed-off-by: Panagiotis Georgiadis <pgeorgia@redhat.com>
@SnackSBR
Copy link
Copy Markdown

SnackSBR commented Mar 3, 2026

tested on real hardware using gdemu.

had to downgrade my kos lua to 5.4.8 to be able to compile and install smpq.

Screenshot 2026-03-03 01-26-14 Screenshot 2026-03-03 01-27-16 Screenshot 2026-03-03 01-28-12 Screenshot 2026-03-03 01-30-02

@drpaneas
Copy link
Copy Markdown
Author

drpaneas commented Mar 3, 2026

Thanks for testing it @SnackSBR 👍

So, are we good here? What else is missing or needs addressing?

@SnackSBR
Copy link
Copy Markdown

SnackSBR commented Mar 3, 2026

Thanks for testing it @SnackSBR 👍

So, are we good here? What else is missing or needs addressing?

Are you going to try and implement modem/broadband support?

@drpaneas
Copy link
Copy Markdown
Author

drpaneas commented Mar 3, 2026

Modem/Broadband in Dreamcast I have no clue. Never tried that apart form some basic fixes in a tool that helps me loading the games remotely via network. So, this is a long shot.

@SnackSBR
Copy link
Copy Markdown

SnackSBR commented Mar 3, 2026

support for dreampi would be really cool but I get it. If you try something it's probably better to focus on the modem side. The ethernet one is pretty rare and most people don't have it.

@jader-Fox
Copy link
Copy Markdown

Does anyone know what might be causing this error? The Diablo compilation occurs without errors, it generates the CDI, but this error occurs in the emulator. KallistiOS v2.2.2 [dreamcast/pristine]
Git revision: 4d861ff3
Tue Feb 10 11:55:20 -03 2026
jaderfox@Fox.localdomain:/opt/toolchains/dc/kos
sh-elf-gcc (GCC) 13.2.0
maple: active drivers:
Dreameye (Camera): Camera
Sound Input Peripheral: Microphone
PuruPuru (Vibration) Pack: JumpPack
VMU Driver: Clock, LCD, MemoryCard
Mouse Driver: Mouse
Keyboard Driver: Keyboard
Controller Driver: Controller
Lightgun: LightGun
DMA Buffer at ac352e00
vid_set_mode: 640x480IL NTSC with 1 framebuffers.
maple: attached devices:
A0: Dreamcast Controller (01000000: Controller)
A1: Visual Memory (0e000000: Clock, LCD, MemoryCard)
A2: Visual Memory (0e000000: Clock, LCD, MemoryCard)
B0: Emulated Dreamcast Mouse (00020000: Mouse)

fs_iso9660: disc change detected
(joliet level 3 extensions detected)
INFO: Adding joystick 0: Dreamcast Controller Produced By or Under License From SEGA ENTERPRISES,LTD. «☺¶☺
INFO: Setting video mode 640x480 bpp=8 flags=0xE0000001
vid_set_mode: 640x480IL NTSC with 1 framebuffers.
INFO: Video surface is now 640x480 bpp=8 flags=0xE0000020
INFO: Will render directly to the SDL output surface
ERROR: Lua is in a panic state and will now abort() the application:
attempt to index a nil value
arch: aborting the system

KOS newlib does not support popen, system, or tmpfile. Without
LUA_USE_C89, Lua's os library tries to register wrappers for these
functions, which can leave the os table nil and crash with
"attempt to index a nil value" during sandbox creation.

Signed-off-by: Panagiotis Georgiadis <pgeorgia@redhat.com>
@drpaneas
Copy link
Copy Markdown
Author

drpaneas commented Mar 4, 2026

@jader-Fox thanks for trying to build it 👍 This is likely caused by the bundled Lua 5.4 being compiled without LUA_USE_C89. Without that flag, Lua's os library tries to use POSIX functions like popen(), system(), and tmpfile() that KOS's newlib doesn't support. This leaves the os table nil at runtime, and the sandbox creation crashes when it tries to access os["date"] - which is the "attempt to index a nil value" you're seeing.

I just pushed a fix for this: 80437d8ae
The change is one line in 3rdParty/Lua/CMakeLists.txt - adding DREAMCAST to the list of platforms that get LUA_USE_C89 (alongside 3DS, Vita, Switch, etc.). In my case I had already pre-built Lua, so this why I am not getting this error.

Can you try pulling the latest and rebuilding?

PS: this reminds me we need a CI for that to avoid #worksonmymachine issues.

@jader-Fox
Copy link
Copy Markdown

@jader-FoxObrigado por tentar compilar 👍 Isso provavelmente ocorre porque o Lua incluído 5.4foi compilado sem a LUA_USE_C89flag --os. Sem essa flag, a biblioteca os do Lua tenta usar funções POSIX como __get__ popen(), system()``__set__ e tmpfile()``__set__, que a newlib do KOS não suporta. Isso deixa a tabela os nilem tempo de execução, e a criação do sandbox falha quando tenta acessar os["date"]``__get__, que é a "tentativa de indexar um valor nulo" que você está vendo.

Acabei de enviar uma correção para isso: 80437d8ae. A alteração está em uma linha 3rdParty/Lua/CMakeLists.txt- adicionando o DREAMCAST à lista de plataformas que recebem o código LUA_USE_C89(junto com 3DS, Vita, Switch, etc.). No meu caso, eu já tinha o Lua pré-compilado, por isso não estou recebendo esse erro.

Você pode tentar baixar a versão mais recente e recompilar?

PS: isso me lembra que precisamos de CI para evitar problemas com #funcionameminhamáquina.

With these updates, I was able to get it working, thank you very much! I'll now check the possibility of adding network support, especially for the w5500 model.

Ensures the LUA_USE_C89 fix always applies regardless of whether
kos-ports Lua happens to be installed, and removes Lua as a
kos-ports prerequisite.

Signed-off-by: Panagiotis Georgiadis <pgeorgia@redhat.com>
@StephenCWills
Copy link
Copy Markdown
Member

PS: this reminds me we need a CI for that to avoid #worksonmymachine issues.

You can reference .github/workflows/dreamcast.yml in #7453. I don't think the job will actually run unless the yml is merged into master so it doesn't particularly matter if we get it added to this PR or add it later in a separate PR. That said, if you want to test the yml script, you can merge it into the master branch of your fork with the workflow_dispatch trigger and run it manually against your dreamcast-pr branch via the Actions tab.

@SnackSBR
Copy link
Copy Markdown

SnackSBR commented Mar 5, 2026

  • The delete option don't delete the character
  • Options are not saved (or maybe not loaded?), let's say I turn run on city on, next time I launch the game it's off
  • After saving the "game saved" popup don't go away until I open the menu
  • Overlays like npc dialogue or map tank the fps
  • When playing with mouse and keyboard the right mouse click (move key) acts like it's always pressed
  • Also when playing with mouse and keyboard if you keep colliding (caused by previous behavior) with a npc the fps will go to 1 (doesn't happen with controller)

Forgot to report the first time but I think it's missing something because I can't compile without adding fmt::fmt to dreamcast CMakeLists.txt

@jader-Fox
Copy link
Copy Markdown

jader-Fox commented Mar 6, 2026

The Diablo version is the same for all platforms here. I was trying to connect the Dreamcast to a game on PC, that's why I'm asking =X

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants