BETA — Сайт у режимі бета-тестування. Можливі помилки та зміни.
UK | EN |
LIVE
Технології 🇺🇸 США

SDL Now Supports DOS

Hacker News Jayschwa 0 переглядів 40 хв читання
/ SDL Public

Conversation

@AJenbo Copy link Copy Markdown Contributor

@AJenbo 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.

image

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 @icculus @AJenbo dos: Some initial work. b6c2f2f @icculus @AJenbo dos: Turn off buffer on stdio SDL_IOStreams.8bf81e3 Seeking breaks otherwise. We might be able to just fflush() before or seeking instead? @icculus @AJenbo dos: Audio implementation using the Sound Blaster 16. 4c13af7 @icculus @AJenbo dos: remove audio Pump interface.d0868c7 Turns out DosBox-X was having trouble with the Sound Blaster or something; standard DosBox works correctly directly from the interrupt handler, and without doubling the buffer size. @icculus @AJenbo dos: just dump and restore the stdio buffer when seeking.dcc721c This is MUCH faster than just leaving buffering disabled, and also works around getting bogus reads after an fseek. SDL_LoadWAV on test/sample.wav no longer takes several seconds to finish, and comes up with the correct data. I wonder if we're triggering this in LoadWAV because we're malloc'ing data between seeks/reads, and it's causing the djgpp transfer buffer to change. Or maybe the Fat DS trick is confusing it? I don't know, I haven't had time to debug it, it might just be a legit libc bug in djgpp too, for all I know. @icculus @AJenbo dos: Protect audio device "thread" iterations when streams are locked.23ecf0d This uses an old trick we used in SDL 1.2 for MacOS Classic, which did its audio callback in a hardware interrupt. If the audio is locked when the interrupt fires, make a note of it and return immediately. When the lock is released, if the interrupt has been fired, run the audio device iteration right then. Since there isn't a big device lock in SDL3 (available to the app, at least), this keeps a counter of when any SDL_AudioStream is locked, which is probably good enough. @icculus @AJenbo dos: Implemented initial video subsystem.62726d7 This uses VESA interfaces to manage the display and works with the software renderer. Events aren't hooked up yet, so prepare to close DosBox on each run. :) @icculus @AJenbo dos: Whoops, forgot to add these to revision control. Core and Main s…ccffbee …upport. @icculus @AJenbo dos: Wired up basic filesystem support.fac1d20 This gets most of the rendering examples, which use SDL_GetBasePath() to find textures to load, working. @icculus @AJenbo dos: Fixed compiler warning. fcdcad5 @icculus @AJenbo dos: Initial mouse support! 3028098 @icculus @AJenbo dos: Move interrupt hooking code into core/dos. c86a2e3 @icculus @AJenbo dos: Initial keyboard support! 4b80172 @icculus @AJenbo dos: Use a simple ring buffer for keyboard events.5fa9dbb Of course Quake 1 solved this better, haha. It's smart: less memory, dirt simple, and you don't even have to worry about synchronizing with the interrupt handler, because it's safe for both sides no matter when an interrupt fires. @madebr @AJenbo ci: add djgpp job1164f40 [sdl-ci-filter djgpp] [sdl-ci-artifacts] @AJenbo dos: Fix build issues after rebase onto current main3423584 - SDL_runapp.c: Add SDL_PLATFORM_DOS to the exclusion list so the generic SDL_RunApp() is disabled when the DOS-specific one is compiled. - SDL.c: Exclude SDL_Gtk_Quit() on DOS. DJGPP defines __unix__ which sets SDL_PLATFORM_UNIX, but DOS has no GTK/display server. The GTK source is not compiled (CMake UNIX is false for DOS) so this was a link error. - sdlplatform.cmake: Add DOS case to SDL_DetectCMakePlatform so the platform is properly detected from CMAKE_SYSTEM_NAME=DOS. - i586-pc-msdosdjgpp.cmake: Add i386-pc-msdosdjgpp-gcc as a fallback compiler name, since some DJGPP toolchain builds use the i386 prefix. @AJenbo Add 8-bit palette support to DOS VESA driver 4a76c43 @AJenbo Add VBE page-flipping, state restore, and robust keyboard handling750f61a - Implement double-buffered page-flipping for VBE modes with >1 image page - Save and restore full VBE state on video init/quit for clean mode switching - Improve DOS keyboard handling: support extended scancodes and Pause key - Lock ISR code/data to prevent page faults during interrupts - Always vsync when blitting in single-buffered modes to reduce tearing @AJenbo Refactor Sound Blaster audio mixing to main loop8c07e7d Move audio mixing out of IRQ handler to main loop for improved stability and to avoid reentrancy issues. Add SDL_DOS_PumpAudio function, update DMA buffer handling, and adjust sample rate to 22050 Hz. Silence stale DMA buffer halves to prevent stutter during load. @AJenbo Add DOS timer support and update build config 998baf8 @AJenbo Add support for pre-SB16 8-bit mono Sound Blaster audioed6adf2 Detect SB version and select 8-bit mono or 16-bit stereo mode. Handle DMA and DSP setup for both SB16 and pre-SB16 hardware. Add FORCE_SB_8BIT option for testing in DOSBox. @AJenbo Add SB Pro stereo support and simplify IRQ handler cf1e599 @AJenbo Add DOS joystick driver support d3b2510 @AJenbo Improve DOS hardware handling and clarify memory allocation8565d56 - Poll Sound Blaster DSP status instead of fixed delay after speaker-on - Clarify DPMI conventional memory is always locked; update comments - Document and justify DMA memory allocation strategy - Free IRET wrapper after restoring interrupt vector to avoid leaks - Throttle joystick axis polling to ~60 Hz to reduce BIOS timing loop cost - Always poll joystick buttons directly for responsiveness @AJenbo Query and use mouse sensitivity from INT 33h function 0x1B d9a7438 @AJenbo Add support for VESA banked framebuffer modes9d631c4 Implement banked framebuffer access for VBE 1.2+ modes without LFB. Detect and initialize banked modes, copy framebuffer data using bank switching, and blank the framebuffer on mode set. Page-flipping is disabled in banked mode. @AJenbo Add optional vsync to page flipping in DOS VESA driver 6a29b3b @AJenbo Add cooperative threading support for DOS platform 9cce6b1 @AJenbo Move SoundBlaster audio mixing to SDL audio thread 738fa40 @AJenbo Fix DOS platform comments and workarounds for DJGPP support 1abf5d8 AJenbo added 4 commits April 23, 2026 03:02 @AJenbo DOS: Cap mouse range e1d21fd @AJenbo DOS: Map test resources to 8.3 names 4c8867c @AJenbo DOS: Skip unsupported WM color modes e277825 @AJenbo Fix "windowed" resolution selection 479a6b4 @AJenbo Copy link Copy Markdown Contributor Author

AJenbo commented Apr 23, 2026 • edited Loading

Uh oh!

There was an error while loading. Please reload this page.

Done:

Screenshot From 2026-04-23 07-28-19

(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.
So add this on top of what GitHub suggests:

Co-authored-by: Gleb Mazovetskiy <glex.spb@gmail.com> Co-authored-by: Jay Petacat <jay@jayschwa.net> Tested-by: Cameron Cawley <ccawley2011@gmail.com>
madebr madebr reviewed Apr 23, 2026 View reviewed changes Comment thread test/CMakeLists.txt
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")
Copy link Copy Markdown Contributor

@madebr 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 Copy link Copy Markdown Contributor

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 DOS: Hide INDEX8 modes behind SDL_DOS_ALLOW_INDEX8_MODES 16b180a @AJenbo Copy link Copy Markdown Contributor Author

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 Copy link Copy Markdown Collaborator

slouken commented Apr 23, 2026

The issue was SDL_GetClosestFullscreenDisplayMode() dropping the mode to INDEX8 and the application not knowing how to render at INDEX8.

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 Copy link Copy Markdown Contributor Author

AJenbo commented Apr 23, 2026 • edited Loading

Uh oh!

There was an error while loading. Please reload this page.

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.

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 Copy link Copy Markdown Collaborator

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.

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?

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 Remove SDL_HINT_DOS_ALLOW_INDEX8_MODES and order modes logically 74ea44f @AJenbo Copy link Copy Markdown Contributor Author

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 Copy link Copy Markdown Collaborator

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 Copy link Copy Markdown Contributor

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).
Running testpalette segfaults.

@AJenbo Copy link Copy Markdown Contributor Author

AJenbo commented Apr 23, 2026 • edited Loading

Uh oh!

There was an error while loading. Please reload this page.

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). Running testpalette segfaults.

image

@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.

image
@icculus Copy link Copy Markdown Collaborator

icculus commented Apr 23, 2026

Other PR is merged. Last call on DOS pull request!

@madebr Copy link Copy Markdown Contributor

madebr commented Apr 23, 2026

@madebr this PR currently depends on #15442 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

That was it. Merging that pr locally got everything working :)

Only thing is the cursor not being transparent.

@AJenbo Don't convert cursor if dest is not INDEX8 3a8a287 @AJenbo Copy link Copy Markdown Contributor Author

AJenbo commented Apr 23, 2026

Only thing is the cursor not being transparent.

Fixed

@icculus Copy link Copy Markdown Collaborator

icculus commented Apr 23, 2026

Worry about cursor later?

@AJenbo Copy link Copy Markdown Contributor Author

AJenbo commented Apr 23, 2026 • edited Loading

Uh oh!

There was an error while loading. Please reload this page.

Worry about cursor later?

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)

madebr madebr approved these changes Apr 23, 2026 View reviewed changes @palxex Copy link Copy Markdown

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 Copy link Copy Markdown Collaborator

icculus commented Apr 23, 2026

We can add that later (unless @AJenbo has already pushed it while I'm typing this, haha).

Hide details View details @icculus icculus merged commit a8ecd67 into libsdl-org:main Apr 23, 2026 46 checks passed

Uh oh!

There was an error while loading. Please reload this page.

@icculus Copy link Copy Markdown Collaborator

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 AJenbo deleted the sdl3-dos branch April 24, 2026 01:23 @AJenbo Copy link Copy Markdown Contributor Author

AJenbo commented Apr 24, 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?

If you enable SDL_HINT_DOS_ALLOW_DIRECT_FRAMEBUFFER that probably isn't relevant.

This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters Show hidden characters Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

14 participants

@AJenbo @sulix @icculus @madebr @jayschwa @ccawley2011 @jpernst @sezero @LekKit @slouken @volkertb @arrowgent @otonoton @palxex Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Поділитися

Схожі новини