Skip to content

Conversation

glebm
Copy link
Contributor

@glebm glebm commented Sep 8, 2025

@AJenbo and I took @jayschwa's SDL2 DOS port from a few years ago, rebased it onto the current SDL2, and got palettized output and keyboard fully working.

I understand that the current SDL development focuses on SDL3. I'm posting this PR here for visibility, in case someone might be interested in using it, improving it further, or forward-porting it to SDL3.

Supported

  • Toolchain: This port requires the DJGPP toolchain, tested with the latest one based on GCC 14.2.
  • Graphics: The minimum requirement for graphics is VBE 2.0. Only double-buffered graphics modes are supported. An equivalent of vsync is always on.
  • Mouse: Mouse is supported but custom hardware cursors are not. This is not a big problem as most software that would be appropriate to port to DOS already supports software cursor rendering. Mouse wheel is not supported.
  • Keyboard: Text input events assume en-US layout.
  • File system: Works out of the box, courtesy of DJGPP toolchain's POSIX support. Base/pref paths are empty strings (= current directory).

Not supported

  • Threads, audio, gamepad.

Here is a screenshot of DevilutionX running in DOSBox. We also tested on real hardware (hit and miss depending on the graphics card).

image

The performance is pretty good when using the 640x480 8-bit palettized mode.
Building instructions are here in the "DOS" section: https://github.com/diasurgical/DevilutionX/blob/master/docs/building.md

Timers remain unsupported due to lack of multithreading.
A few other minor style things were tweaked too.
This implementation is probably wrong, but it lays the foundation for
doing it better, eventually.
Windows are now always created with the fullscreen flag.
Key release events do not seem to be visible via _bios_keybrd.
This will probably change to use a keyboard interrupt handler.
jayschwa and others added 21 commits August 31, 2025 21:06
It doesn't seem to be necessary.
Example toolchain file:

```bash
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_VERSION 1)

if($ENV{DJGPP_PREFIX})
  set(DJGPP_PREFIX "$ENV{DJGPP_PREFIX}")
else()
  set(DJGPP_PREFIX "/opt/i386-pc-msdosdjgpp-toolchain")
endif()

set(CMAKE_C_COMPILER "${DJGPP_PREFIX}/bin/i386-pc-msdosdjgpp-gcc")
set(CMAKE_CXX_COMPILER "${DJGPP_PREFIX}/bin/i386-pc-msdosdjgpp-g++")
set(CMAKE_STRIP "${DJGPP_PREFIX}/bin/i386-pc-msdosdjgpp-strip")
set(PKG_CONFIG_EXECUTABLE "${DJGPP_PREFIX}/bin/i386-pc-msdosdjgpp-pkg-config" CACHE STRING "Path to pkg-config")

set(CMAKE_EXE_LINKER_FLAGS_INIT "-static")

set(DJGPP_ROOT "${DJGPP_PREFIX}/i386-pc-msdosdjgpp")

set(CMAKE_FIND_ROOT_PATH "${DJGPP_ROOT}")
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

link_directories("${DJGPP_ROOT}/lib")
include_directories(BEFORE SYSTEM "${DJGPP_ROOT}/sys-include" "${DJGPP_ROOT}/include")
```

Example invocation:

```bash
cmake -S. -Bbuild-dos -DCMAKE_TOOLCHAIN_FILE="path/to/djcpp.toolchain.cmake" -DDOS=ON
```
Makes the arrow keys and page up/down work.
Basic TEXTINPUT event firing that assumes US keyboard layout.
This allows S3 trio video cards to work
Calling out via real-mode bridge would kill performance when color
cycling.

Luckily, VBE 2.0 provides protected mode interface for some of the
functions, and setting the palette is one of them.

The asm code is based on Allegro 4.2 `vesa_set_palette_range`.
Luckily, Allegro license is extremely permissive.
@slouken slouken added this to the 2.x milestone Sep 8, 2025
@icculus
Copy link
Collaborator

icculus commented Sep 8, 2025

I have a from-scratch DOS port of SDL3 sitting in https://github.com/icculus/SDL/tree/sdl3-dos ... we should compare notes.

@glebm
Copy link
Contributor Author

glebm commented Sep 8, 2025

@icculus That's awesome! I've had a look at your branch:

  1. Audio is supported in your branch, this is amazing.
  2. Keyboard: this version supports extended input events and sends SDL_TEXTINPUT events. Can be ported pretty much verbatim into your branch.
  3. Video:
    • This version supports palettized 8bpp, which is very important for DevilutionX (non-palette modes are too slow for software rendering on most hardware from the era). Should be straightforward to port over, unless SDL3 removed support for palettized 8bpp (this would be very bad for the source ports community, I really hope it's still there).
    • The vsync implementation is a bit different. This branch uses double-buffered modes together SetDisplayStart with 0x80 in ebx (via a protected-mode interface), which tells the hardware to wait for a vertical refresh. Your branch seems to do some CPU waits in a loop instead. I think the approach here might be better?
  4. Mouse: more work has gone into custom cursor support but still incomplete (not that important though).

@AJenbo
Copy link
Contributor

AJenbo commented Sep 8, 2025

palettized 8bpp is still supported in SDL3

@jayschwa
Copy link
Contributor

jayschwa commented Sep 9, 2025

What a bunch of mad lads 🤠. I know it's not relevant for your Diablo port, but I also had a branch off my VBE work that was for plain old VGA mode 13h. It could serve as a fallback if VBE isn't available for increased compatibility. It keeps its back buffer in RAM (not VGA) though, so it's not as optimal as page-flipping with VBE.

I recently migrated the game I'm working on from SDL 2 to 3, so I guess I'll have to check out @icculus's branch now. 👀

@AJenbo
Copy link
Contributor

AJenbo commented Sep 9, 2025

A similar solution could be used for supporting vba 2.0 or systems with no double buffer modes

@icculus
Copy link
Collaborator

icculus commented Sep 9, 2025

So which one of us is going to be the first to hook the timer interrupt and implement threading? :)

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