SDL Now Supports DOS
- Notifications You must be signed in to change notification settings
- Fork 2.7k
- Star 15.4k
Conversation
AJenbo
commented
Apr 13, 2026
•
edited
Loading
Uh oh!
There was an error while loading. Please reload this page.
This is the combined work of @icculus @madebr @glebm @jayschwa @ccawley2011 and me rounding it off with stability fixes and missing features, thanks to everyone for pitching in.
This is a fairly complete port to DOS with only minor features like audio recording missing. I have tested it extensively with DevilutionX in DOSBox. But no real hardware testing. The features I didn't add is mostly because I didn't have a good way to test that they worked correctly.
For threading I took some conceptual inspiration from the PS2 port.
What's supported
- Video: VGA and VESA 1.2+ framebuffer, RGB, and 8-bit indexed color with VGA DAC palette programming, hardware page-flipping with vsync, VBE state save/restore on exit
- Audio: Sound Blaster 16 (16-bit stereo, up to 44.1 kHz), Sound Blaster Pro (8-bit stereo, up to 22 kHz), Sound Blaster 2.0/1.x (8-bit mono), all via IRQ-driven DMA with double-buffered auto-init
- Input: PS/2 keyboard with extended scancodes (0xE0 prefix), INT 33h mouse with queried sensitivity, gameport joystick via BIOS INT 15h with auto-calibration
- Threading: Cooperative scheduler using setjmp/longjmp with stack patching. Real mutexes, semaphores, TLS, and condition variables (generic fallback). Yield points in the event pump and delay functions keep audio and other threads responsive.
- Timer: Native PIT-based timer using DJGPP's uclock() at ~1.19 MHz resolution
- Filesystem: GetBasePath / GetPrefPath via DJGPP's searchpath(), POSIX filesystem ops fallback
- Build: CMake cross-compilation toolchain file, DJGPP CI job, preseed cache for faster configure
What's NOT included
- Audio recording playback only
- SDL_TIME native implementation reuses Unix gettimeofday via DJGPP's POSIX layer (works fine)
- Shared library loading support (no SDL_LoadObject).
How to build
cmake -S. -Bbuild-dos \ -DCMAKE_TOOLCHAIN_FILE=build-scripts/i586-pc-msdosdjgpp.cmake \ -DCMAKE_BUILD_TYPE=Release cmake --build build-dos -j$(nproc) icculus and others added 30 commits April 13, 2026 08:50
AJenbo
commented
Apr 23, 2026
•
edited
Loading
Uh oh!
There was an error while loading. Please reload this page.
|
Done:
(and Quake still works) There are a couple of issues with some standard formatting functions that makes it unable to finish the automation tests, I patched around it and got the test to complete, there where still some failing cases that I haven't looked in to and I don't feel confident enough about how to correctly patch the failing formatting functions to include them either, most demos works as one would reasonably expect I think. @slouken if it was up to me I would probably squash merge this PR, GitHub will still provide a reference from the resulting commit to the PR where all the steps can be viewed. This would also give you a chance to add propper attributions to @glebm and @jayschwa who also contributed significant code. @ccawley2011's 1.2 port was mostly used for comparison, but they did significant testing and reviewing so I think it would be fair to include them as well. |
| endif() | ||
|
|
||
| if(DOS) | ||
| set(NAME83_LONG "unifont-15.1.05.hex;unifont-15.1.05-license.txt;physaudiodev.png;logaudiodev.png;audiofile.png;soundboard.png;soundboard_levels.png;trashcan.png;msdf_font.png;msdf_font.csv;gamepad_front.png;gamepad_back.png;gamepad_face_abxy.png;gamepad_face_axby.png;gamepad_face_bayx.png;gamepad_face_sony.png;gamepad_battery.png;gamepad_battery_unknown.png;gamepad_battery_wired.png;gamepad_touchpad.png;gamepad_button.png;gamepad_button_small.png;gamepad_button_background.png;gamepad_axis.png;gamepad_axis_arrow.png;gamepad_wired.png;gamepad_wireless.png;sdl-test_round.png") |
madebr
Apr 23, 2026
•
edited
Loading
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll rewrite this in a nicer way post-merge. :)
sulix commented Apr 23, 2026
|
The latest version is working well here for non-fullscreen windows (in both the test programs and my own code). Fullscreen is giving an empty black screen at the moment, though (e.g. draw.exe --fullscreen). Still, this is definitely usable for me, on both DOSBox and DOS 6.22 on a Vortex86 board (albeit slowly). I'll try it out on a more extensive set of systems sometime in the next ~week, too. Thanks very much! |
AJenbo
commented
Apr 23, 2026
•
edited
Loading
Uh oh!
There was an error while loading. Please reload this page.
|
The issue was SDL_GetClosestFullscreenDisplayMode() dropping the mode to INDEX8 and the application not knowing how to render at INDEX8. The way I hangled this in the internal equivalent was that I only considered INDEX8 modes if the user had already set an INDEX8 fullscreen mode, for SDL to generally support INDEX8 as a display mode SDL_GetClosestFullscreenDisplayMode() should probably be changed to do something similar, it would probably be good to make it more explicit about how it chooses between bpp in general, right now it will probably give you a random bpp based on what order the driver lists modes in and not what bests matchs your current pixel format. For now I have guarding INDEX8 behind SDL_HINT_DOS_ALLOW_INDEX8_MODES so that applications have to explicitly opts into it when they are able to handle it properly. |
slouken commented Apr 23, 2026
This might actually be fixed if you rebase against main. We just changed it so we take the highest bit depth (first mode in the list) rather than the lowest (last in the list). I'd prefer that if it works rather than adding another hint. |
AJenbo
commented
Apr 23, 2026
•
edited
Loading
Uh oh!
There was an error while loading. Please reload this page.
That does solve the bpp issue ... but now I get 1024x768 when asking for best fit for 640x480. This wasn't the case previously so it sems it's part fix part breakage. Should I just rebase and then you guys can fix SDL_GetClosestFullscreenDisplayMode() separately? |
slouken commented Apr 23, 2026
I reverted the change. I don't have time to look into it right now, so if you want to investigate and provide a separate PR for a better fix, I can include that. |
AJenbo
commented
Apr 23, 2026
•
edited
Loading
Uh oh!
There was an error while loading. Please reload this page.
|
@slouken I removed the SDL_HINT_DOS_ALLOW_INDEX8_MODES, if you can merge #15442 then it should allow automatic mode selection to work correctly for applications that don't set a palette and don't pick there full screen mode them selfs, so I think it's ready to merge as well. I would really prefer not to end up in a rabbit hole of fixing existing issues in SDL here. P.s. I'm happy to help with fixes, testing and improvements as follow ups. |
icculus commented Apr 23, 2026
|
Let's merge both these things and call this good to go! I'll do so shortly if there are no objections. |
madebr commented Apr 23, 2026
|
Does sprite.exe work for you? It closes immediately for me on DOSBox. wm.exe and draw.exe render nothing (but close on pressing ESC). |
AJenbo
commented
Apr 23, 2026
•
edited
Loading
Uh oh!
There was an error while loading. Please reload this page.
@madebr this PR currently depends on the other PR for demos to render anything other then black because SDL_GetClosestFullscreenDisplayMode() currently prefer the lowest color depth, which for this port is INDEX8 and so would requires the application to set a palette. sprinte.exe doesn't crash for me either way, you would have to get the SDL_Log() or the DJGPP crash dump for me to know what that's about.
|
icculus commented Apr 23, 2026
|
Other PR is merged. Last call on DOS pull request! |
madebr commented Apr 23, 2026
That was it. Merging that pr locally got everything working :) Only thing is the cursor not being transparent. |
AJenbo commented Apr 23, 2026
Fixed |
icculus commented Apr 23, 2026
|
Worry about cursor later? |
AJenbo
commented
Apr 23, 2026
•
edited
Loading
Uh oh!
There was an error while loading. Please reload this page.
To late I already fixed it :D (I fixed it by using an unoptimized, version for RGB modes, and yeah lets worry about optimizing that til later. It should be correct in both RGB and INDEX8 (what @ccawley2011 had issues with originally) now, slightly better performance on XRGB1555 and RGB565 is very minor I think) |
palxex commented Apr 23, 2026
|
A question: due to https://www.vogons.org/viewtopic.php?f=63&t=57420 , some Nvidia GPUs' 4f07(SetDisplayStart) not works well, though it reports. In my test the range maybe even bigger, up to 3060, down to 9300(not be complete, as we can only test on owed GPUs). In test I also observed the display problem in our project. But disabling features based on GPU vendor in SDL seems unwise; maybe we need a new hint to let users control page_flip_available directly? |
icculus commented Apr 23, 2026
|
We can add that later (unless @AJenbo has already pushed it while I'm typing this, haha). |
Uh oh!
There was an error while loading. Please reload this page.
icculus
commented
Apr 23, 2026
•
edited
Loading
Uh oh!
There was an error while loading. Please reload this page.
|
Too late, it is merged! :) Excellent work, @AJenbo. You went above-and-beyond on this work. (Thank you to everyone else, too!) I'm considering this a 3.6.0 feature, so let's not cherry-pick it to 3.4.x. |
AJenbo commented Apr 24, 2026
If you enable SDL_HINT_DOS_ALLOW_DIRECT_FRAMEBUFFER that probably isn't relevant. |


