SDL unterstützt jetzt DOS
(github.com/libsdl-org)- Ein DOS-Port auf Basis von DJGPP wurde zu SDL hinzugefügt, mit breiter Unterstützung für Video, Audio, Eingabe, Threading, Timer, Dateisystem und Build-Chain, und in
mainzusammengeführt - Enthalten sind Implementierungen für VGA- und VESA-1.2+-Video, Audiowiedergabe für die Sound-Blaster-Familie, PS/2-Tastatur und -Maus, BIOS-basierten Joystick sowie kooperatives Threading und PIT-Timer, angepasst an die DOS-Umgebung
- Das seek/read-Problem von DJGPP wurde umgangen, indem beim Seek der Puffer verworfen und wiederhergestellt wird; dadurch wurden fehlerhafte Lesevorgänge und mehrsekündige Verzögerungen bei
SDL_LoadWAVbeseitigt, und der Audiopfad wurde weiter verfeinert, um IRQ-Reentrancy und Stottern zu reduzieren - Der schwarze Bildschirm im Fullscreen hing mit der Auswahl des INDEX8-Modus zusammen; statt eines DOS-spezifischen Hints wurde die Reihenfolge der Modi logisch sortiert, und auch ein Problem mit der Cursor-Transparenz wurde in einem weiteren Commit behoben
- Tests auf echter Hardware sind begrenzt, und einige Funktionen wie Audioaufnahme,
SDL_LoadObjectund eine DOS-spezifische Implementierung vonSDL_TIMEfehlen noch, aber 46 Checks wurden bestanden, die Änderungen wurden zusammengeführt und als Feature für 3.6.0 eingeordnet
Unterstützungsumfang der DOS-Plattform
- Zu SDL wurde ein DOS-Port hinzugefügt, der auf DJGPP basiert und einen vergleichsweise hohen Reifegrad erreicht hat
- Die Arbeit wurde auf mehrere Personen verteilt; in der Schlussphase kamen Stabilitätskorrekturen und Ergänzungen fehlender Funktionen hinzu
- DevilutionX wurde in DOSBox ausführlich getestet, aber Tests auf echter Hardware fehlen
- Einige Funktionen wurden bewusst ausgelassen, wenn es dafür keine sinnvolle Testmethode gab
- Die unterstützten Funktionen sind konkret aufgeführt
- Video umfasst VGA und VESA-1.2+-Framebuffer, RGB und 8-Bit-Indexfarben, VGA-DAC-Palettenprogrammierung, VSync und Hardware-Page-Flipping sowie das Speichern und Wiederherstellen des VBE-Zustands beim Beenden
- Audio unterstützt Sound Blaster 16, Sound Blaster Pro und Sound Blaster 2.0/1.x und verwendet IRQ-basierte DMA sowie einen Double-Buffer-Auto-Init-Pfad
- Eingabe umfasst PS/2-Tastaturen mit erweiterten Scancodes, INT-33h-Maus sowie BIOS-INT-15h-basierten Gameport-Joystick
- Threading nutzt einen kooperativen Scheduler auf Basis von
setjmp/longjmpund Stack-Patching und enthält zudem allgemeine Fallbacks für Mutex, Semaphore, TLS und Condition Variables - In Event-Pump und Delay-Funktionen wurden Yield-Punkte eingefügt, um die Reaktionsfähigkeit von Audio und anderen Threads zu erhalten
- Timer basieren auf einer PIT-Implementierung mit DJGPPs
uclock()und bieten etwa 1,19 MHz Auflösung - Das Dateisystem verarbeitet
GetBasePathundGetPrefPathüber DJGPPssearchpath()und enthält außerdem Fallbacks für POSIX-Dateisystemoperationen - Der Build umfasst eine CMake-Toolchain-Datei für Cross-Compiling, einen DJGPP-CI-Job und einen Preseed-Cache für schnelleres Configure
- Auch nicht enthaltene Funktionen sind klar benannt
- Audioaufnahme fehlt; unterstützt wird nur Wiedergabe
- Eine native Implementierung von
SDL_TIMEfür DOS gibt es nicht; stattdessen wird Unix-gettimeofdayüber die POSIX-Schicht von DJGPP wiederverwendet - Laden gemeinsamer Bibliotheken wird nicht unterstützt, daher fehlt
SDL_LoadObject
Implementierungsverlauf und zentrale Änderungen
- Der DOS-Port wurde über mehrere Commits hinweg schrittweise um Video, Audio, Eingabe, Timer, Threading und Build-Chain erweitert
- Nach den ersten Arbeiten wurden nacheinander stdio-Pufferung, Audioimplementierung, Video-Subsystem, Dateisystem, Maus, Tastatur, CI und Plattformerkennung ergänzt
- Bei stdio und Dateizugriff wurde ein DJGPP-spezifisches seek/read-Problem umgangen
- Zunächst gab es Versuche, den Puffer von stdio-
SDL_IOStreamszu deaktivieren; später wurde dies durch das Verwerfen und Wiederherstellen des Puffers beim Seek ersetzt - Diese Änderung ist deutlich schneller, als den Puffer vollständig abzuschalten, und vermeidet auch falsche Lesevorgänge nach
fseek - Dass
SDL_LoadWAVbeim Lesen vontest/sample.wavmehrere Sekunden brauchte, verschwand, und die Daten wurden korrekt eingelesen
- Zunächst gab es Versuche, den Puffer von stdio-
- Auch die Audioverarbeitung wurde fortlaufend auf Stabilität optimiert
- Die Implementierung begann mit Sound Blaster 16; später kamen Unterstützung für 8-Bit-Mono vor SB16 und SB-Pro-Stereo hinzu
- Das Audio-Mixing wurde zunächst direkt im IRQ-Handler ausgeführt, dann über die Main-Loop geführt und schließlich wieder in den SDL-Audio-Thread verlagert
- Die Richtung wurde geändert, um Reentrancy-Probleme innerhalb von IRQs zu vermeiden, und beim Laden wurde die alte Hälfte des DMA-Puffers mit Stille gefüllt, um Stottern zu reduzieren
- Außerdem wurden Anpassungen bei Sampleraten, DSP-Status-Polling, Begründung der DMA-Speicherallokation sowie das Freigeben des IRET-Wrappers nach Wiederherstellung des Interrupt-Vektors dokumentiert
- Auch Video wurde entsprechend den Einschränkungen von DOS detailliert ausgebaut
- Eine erste Implementierung brachte einen Software-Renderer über die VESA-Schnittstelle zum Laufen
- Danach kamen 8-Bit-Palettenunterstützung, VBE-Page-Flipping, Zustandswiederherstellung, VSync im Single-Buffer-Modus und VESA-Modi mit banked Framebuffer hinzu
- Wenn bei VBE 1.2+ kein LFB vorhanden ist, wird der Framebuffer per Bank-Switching kopiert; in diesem Modus wird Page-Flipping deaktiviert
- Beim Initialisieren und Beenden des Video-Subsystems wird der vollständige VBE-Zustand gespeichert und wiederhergestellt, um den Moduswechsel sauber zu halten
- Auch Eingabe- und Interrupt-Behandlung wurden bis zur praktischen Nutzbarkeit verfeinert
- Die Tastatur behandelt erweiterte Scancodes bis hin zur Pause-Taste; für das Event-Queueing wird ein einfacher Ringpuffer verwendet
- Die Maus nutzt INT 33h, Funktion
0x1B, um die Empfindlichkeit abzufragen - Beim Joystick wird das Polling der Achsen auf etwa 60 Hz begrenzt, um die Kosten der BIOS-Timing-Schleife zu senken; die Buttons werden für gute Reaktionsfähigkeit weiterhin direkt gepollt
- ISR-Code und -Daten werden gesperrt, um Page Faults während Interrupts zu verhindern
- Auch Probleme bei Build und Plattformerkennung wurden behoben
- Es wurde ein CI-Job für DJGPP hinzugefügt und die CMake-Plattformerkennung für DOS ergänzt
SDL_PLATFORM_DOSwurde in die Ausschlussliste vonSDL_RunApp()aufgenommen, um Konflikte mit einem DOS-spezifischen Launcher zu vermeiden- Obwohl DJGPP
__unix__definiert, gibt es unter DOS weder GTK noch einen Display-Server; deshalb wurdeSDL_Gtk_Quit()unter DOS ausgeschlossen, um Linkerfehler zu verhindern - Berücksichtigt wurde auch, dass manche DJGPP-Toolchains das Präfix
i386-pc-msdosdjgpp-gccverwenden
Teststatus und verbleibende Einschränkungen
- Die automatisierten Tests liefen nicht vollständig reibungslos, erreichten aber einen mit Patches durchlaufbaren Stand
- Wegen Problemen mit einigen Standard-Formatting-Funktionen kamen die automatisierten Tests nicht bis zum Ende; mit einem Workaround-Patch konnten die Tests dennoch abgeschlossen werden
- Einige fehlschlagende Fälle blieben bestehen, wurden aber nicht aufgenommen, weil unklar war, wie die betreffenden Formatting-Funktionen korrekt zu beheben wären
- Die meisten Demos liefen nach Einschätzung im Wesentlichen wie zu erwarten
- Es wurden auch Ergebnisse aus der Praxis ergänzt
- In DOSBox und unter DOS 6.22 auf einem Vortex86-Board funktionierten nicht-fullscreen Fenster sowohl für Testprogramme als auch für Nutzercode gut
- Fullscreen zeigte zu diesem Zeitpunkt in Beispielen wie
draw.exe --fullscreenjedoch einen schwarzen leeren Bildschirm - Die Geschwindigkeit wurde als langsam, aber brauchbar beschrieben
- Auch einige Probleme mit Testprogrammen wurden festgestellt
sprite.exebeendet sich in DOSBox sofortwm.exeunddraw.exerendern nicht, lassen sich aber mit ESC beendentestpaletteverursacht einen Segmentation Fault
Problem bei der Farbtiefenauswahl im Fullscreen und Anpassung
- Die direkte Ursache für den schwarzen Fullscreen war das Verhalten von
SDL_GetClosestFullscreenDisplayMode(), auf einen INDEX8-Modus zu fallen- Wenn eine Anwendung INDEX8-Rendering nicht verarbeiten kann, bleibt der Bildschirm schwarz
- Intern wurde das so behandelt, dass INDEX8 nur berücksichtigt wird, wenn der Benutzer bereits explizit einen INDEX8-Fullscreen-Modus gesetzt hat
- Zunächst wurde eine DOS-spezifische Maßnahme eingebaut, die INDEX8-Modi nur hinter
SDL_HINT_DOS_ALLOW_INDEX8_MODESsichtbar machte- Ziel war, dass Anwendungen nur dann explizit opt-in machen, wenn sie damit korrekt umgehen können
- Im Main-Branch war jedoch bereits eine Änderung enthalten, die statt der niedrigsten Bit-Tiefe die höchste auswählt, und es wurde geprüft, ob das Problem damit gelöst ist
- Diese Änderung behob zwar das bpp-Problem, führte aber zu einem neuen Problem, bei dem für die Best-Fit-Anfrage 640x480 plötzlich 1024x768 ausgewählt wurde
- Die Änderung wurde schließlich zurückgenommen; eine bessere Korrektur sollte in einem separaten PR behandelt werden
- Am Ende wurde der DOS-spezifische Hint wieder entfernt und stattdessen die Reihenfolge der Modi logisch sortiert
- Der Commit
Remove SDL_HINT_DOS_ALLOW_INDEX8_MODES and order modes logicallywurde hinzugefügt - Wenn #15442 zusammengeführt wird, sollte die automatische Moduswahl auch bei Apps korrekt funktionieren, die keine Palette setzen oder den Fullscreen-Modus nicht direkt selbst wählen
- Zugleich wurde die Grenze gezogen, in diesem PR nicht noch weitere, allgemeinere SDL-Probleme endlos mitzuverfolgen
- Der Commit
Demo-Rendering und Cursor-Fix
- Dass Demos schwarz erschienen, hing nicht allein an diesem PR, sondern auch daran, ob #15442 bereits zusammengeführt war
- Solange
SDL_GetClosestFullscreenDisplayMode()die niedrigste Farbtiefe bevorzugte, wurde in diesem Port INDEX8 gewählt, und wenn die App keine Palette setzte, blieb der Bildschirm schwarz - Nach lokalem Zusammenführen dieses PR wurde bestätigt, dass alle getesteten Fälle funktionierten
- Solange
- Das verbleibende visuelle Problem war die Cursor-Transparenz
- Bei lokaler Prüfung zeigte sich zusätzlich, dass nur der Cursor nicht transparent war
- Zur Behebung wurde der Commit
Don't convert cursor if dest is not INDEX8hinzugefügt - Nach der Änderung wird in RGB-Modi zwar eine weniger optimierte Variante verwendet, dafür funktioniert es nun in RGB und INDEX8 korrekt
- Etwas Potenzial für bessere Performance in XRGB1555 und RGB565 bleibt, hatte aber geringe Priorität
Review und Merge-Entscheidung
- Für den PR wurde ein Squash-Merge als passend angesehen
- Da GitHub im resultierenden Commit den PR-Verweis beibehält, gilt der Arbeitsverlauf weiterhin als nachvollziehbar
- Es wurde auch vorgeschlagen, im Ergebnis-Commit zusätzliche Danksagungen aufzunehmen
- Einschließlich konkreter Formulierungen für zwei
Co-authored-by-Einträge und einenTested-by-Eintrag
- Ein Reviewer merkte an, dass er nach dem Merge einige Formulierungen in Build-Skripten noch sauberer umschreiben wolle
- Kurz vor dem finalen Merge wurde entschieden, auch andere zusammenhängende PRs zu mergen und dann den DOS-PR weiterzuführen
- Nach „Last call on DOS pull request!“ wurde der Merge-Status der zugehörigen PRs bestätigt
- Anschließend wurde der PR mit 46 checks passed in
mainzusammengeführt
- Auch der Release-Umfang wurde nach dem Merge klar festgehalten
- Diese Änderung gilt als Feature für 3.6.0
-
Kein Cherry-Pick nach 3.4.x
- Am Tag nach dem Merge wurde der DOS-Arbeitsbranch gelöscht
Folgeaufgaben und verbleibende Hardware-Probleme
- Es wurde auch ein Problem mit der Implementierung von
4f07(SetDisplayStart)auf einigen Nvidia-GPUs angesprochen- Mit Verweis auf einen VOGONS-Thread wurde festgehalten, dass manche GPUs laut Bericht zwar Unterstützung melden, tatsächlich aber nicht funktionieren
- Der Testbereich könnte von GeForce 9300 bis 3060 reichen, basiert aber nur auf vorhandener Hardware und ist daher nicht vollständig
- Auch in den Tests des Projekts wurde dasselbe Anzeigeproblem beobachtet
- Ein Abschalten der Funktion anhand des GPU-Herstellers wurde bei SDL als unerwünscht angesehen; stattdessen wurde auch die Möglichkeit eines Hints zur Benutzersteuerung angesprochen
- Ein neuer Hint, mit dem der Nutzer
page_flip_availabledirekt steuern kann, könnte sinnvoller sein - Das wurde nicht sofort umgesetzt, sondern als mögliche spätere Ergänzung stehen gelassen
- Ein neuer Hint, mit dem der Nutzer
- Nach dem Merge wurde außerdem ein Hint für die direkte Framebuffer-Nutzung erwähnt
- Wenn
SDL_HINT_DOS_ALLOW_DIRECT_FRAMEBUFFERaktiviert wird, könnte das obigeSetDisplayStart-Problem deutlich weniger relevant sein
- Wenn
1 Kommentare
Hacker-News-Kommentare
Jetzt braucht man nur noch SDL für UEFI, dann kann man Spiele sogar vor dem Booten des OS laufen lassen
Ob es inzwischen besser abgesichert ist oder immer noch zugänglich, würde mich auch interessieren https://www.zdnet.com/article/minix-intels-hidden-in-chip-operating-system/
Soweit ich weiß, hat UEFI nur keine Sound-Treiber, und heutzutage gibt es selbst für Audio-Codec-Chips oft nur noch Datenblätter unter NDA, was das Selberschreiben erschwert
Noch absurder ist, dass dem graphics output protocol Vsync-Informationen fehlen, sodass Blitting ohne Tearing nicht möglich ist; das ist buchstäblich schlechter als VGA
Wenn man sich vorstellt, über ein Menü wie bei grub zu booten und dann erscheint eine Liste klassischer Spiele, ist das schon aufregend
Dieser Screenshot ist besonders witzig, weil DosBOX selbst auf SDL aufgebaut ist
Das hier verwendet DJGPP, also wird die CPU per DPMI in den 32-Bit-Modus versetzt
Dadurch fehlt dieses echte Oldschool-Gefühl mit segmented memory, near pointer und all den 64-KB-Beschränkungen
Cool
Ich frage mich, wie das zusammen mit den MS-DOS-Executables für 386+ von FreeBASIC funktionieren würde, das SDL-Bindings unterstützt
[1] - https://github.com/freebasic/fbc
Ich nehme mir schon seit Jahren vor, OHRRPGCE, das ursprünglich aus der DOS-Welt kommt, wieder zurück nach DOS zu portieren
Und wenn man bedenkt, wie aggressiv SDL damals zu Zeiten von SDL 1.2 fast alle Ports und die OS-Unterstützung gestrichen hat, ist es ziemlich überraschend, dass SDL3 den DOS-Support zurückholt
Perfekt
Heute Morgen habe ich in Turbo C innerhalb von DOSBox-X innerhalb von Debian GNU/Linux innerhalb von VMware Fusion innerhalb von macOS entwickelt, also passt diese Nachricht genau
Ich erinnere mich noch ganz schwach daran, vor Jahrzehnten mit turboc gearbeitet zu haben
Streng genommen war das mit HXDOS schon möglich
Es hat DirectDraw gut genug emuliert, dass SDL es verwenden konnte
Dann frage ich mich, für welches SDL-Target man kompiliert
Exklusives Win32-Vollbild oder eine VESA-Auflösung wie 640x480?
Wenn solche Unterstützung in ein Open-Source-Projekt wie SDL aufgenommen wird, hängt das meist davon ab, wie invasiv die Änderungen sind und ob der Beitragende tatsächlich langfristig die Wartung übernimmt
Jedes Projekt hat da seine eigene Politik, und ich kenne die von SDL nicht, aber bei der Zahl vorhandener Ports wird man wohl wissen, worauf man sich einlässt
Mein Lieblingsbeispiel ist openbsd luna88k https://www.openbsd.org/luna88k.html
Ich habe überhaupt keine Ahnung, wie viele echte Nutzer es gibt. Es war wohl ein ziemlich seltenes System, das vermutlich nur in Japan verkauft wurde, und selbst wenn es Nutzer gibt, sind die wahrscheinlich überwiegend in Japan und damit außerhalb meines Blickfelds, also fühlt es sich an, als gäbe es genau einen Nutzer: den Porter selbst
Trotzdem tauchen bei jedem Release wie aus dem Wald, ein paar Wochen nach dem offiziellen Veröffentlichungstermin, wieder luna88k-Dateien und -Pakete auf
Vielleicht dauert es einfach so lange, weil auf echter luna88k-Hardware kompiliert wird; jedenfalls reicht das offenbar aus, damit es als offizielle Hardwareplattform von OpenBSD erhalten bleibt
Ich selbst will gar keine luna88k besitzen, aber ich habe großen Respekt vor der Person, die dafür sorgt, dass das alles weiterläuft
Es fühlt sich an, als würde SDL wieder zu seinen Wurzeln aus der Loki-Ära zurückkehren
Cool
Warum? Keine Ahnung, aber wenn etwas cool ist, reicht das als Grund
Wie das Internet Archive zeigt, kann man mit Tastatur und Maus praktisch überall die AAA-Komplexität der mittleren 90er ausführen
Spiele wie Tomb Raider, Command & Conquer oder Quake zeigen das, und wenn man einfach eine Plattform will, die funktioniert, ist das ziemlich attraktiv
Mit SDL wird es dann noch viel einfacher
Das freut mich wirklich sehr
Das macht mich ausgesprochen glücklich