SDL prend désormais en charge DOS
(github.com/libsdl-org)- Un portage DOS basé sur DJGPP a été ajouté à SDL et fusionné dans
main, avec une couverture étendue incluant la vidéo, l’audio, les entrées, le threading, les timers, le système de fichiers et la chaîne de build - La prise en charge de la vidéo VGA et VESA 1.2+, de la lecture audio de type Sound Blaster, du clavier et de la souris PS/2, du joystick basé sur le BIOS, ainsi que du threading coopératif et des timers PIT, a été implémentée pour l’environnement DOS
- Le problème de seek/read de DJGPP a été contourné en vidant puis restaurant le tampon lors d’un seek, ce qui supprime les lectures incorrectes et les délais de plusieurs secondes dans
SDL_LoadWAV; le chemin audio a aussi été affiné pour réduire la réentrance IRQ et les saccades - L’écran noir en fullscreen était lié à la sélection du mode INDEX8 ; au lieu d’ajouter un hint spécifique à DOS, l’ordre des modes a été réorganisé de façon logique, et un commit supplémentaire a corrigé le problème de transparence du curseur
- Les tests sur matériel réel restent limités ; certaines fonctions comme l’enregistrement audio,
SDL_LoadObjectet une implémentation DOS spécifique deSDL_TIMEmanquent encore, mais le port a été fusionné après avoir passé 46 vérifications et est prévu comme fonctionnalité de la 3.6.0
Étendue de la prise en charge de la plateforme DOS
- Un portage DOS a été ajouté à SDL et, sur la base de DJGPP, il atteint un niveau de maturité relativement élevé
- Le travail a été réparti entre plusieurs personnes, puis la phase finale a ajouté des correctifs de stabilité et des fonctions manquantes
- DevilutionX a été largement testé dans DOSBox, mais aucun test sur matériel réel n’a été effectué
- Certaines fonctions ont été volontairement exclues lorsqu’il n’existait pas de méthode de test satisfaisante
- Les fonctions prises en charge sont décrites précisément
- La vidéo inclut les framebuffers VGA et VESA 1.2+, les couleurs RGB et indexées 8 bits, la programmation de palette VGA DAC, le vsync et le page flipping matériel, ainsi que la sauvegarde et la restauration de l’état VBE à la sortie
- L’audio prend en charge Sound Blaster 16, Sound Blaster Pro et Sound Blaster 2.0/1.x, avec un chemin DMA basé sur IRQ et double tampon en mode auto-init
- Les entrées comprennent le clavier PS/2 avec scancodes étendus, la souris via INT 33h et le joystick gameport via le BIOS INT 15h
- Le threading utilise un ordonnanceur coopératif fondé sur
setjmp/longjmpet du patching de pile, avec des fallbacks génériques pour mutex, sémaphores, TLS et variables de condition - Des points de yield ont été ajoutés dans la pompe d’événements et la fonction de delay afin de préserver la réactivité de l’audio et des autres threads
- Les timers reposent sur une implémentation PIT via
uclock()de DJGPP, avec une résolution d’environ 1,19 MHz - Le système de fichiers gère
GetBasePathetGetPrefPathviasearchpath()de DJGPP, avec des fallbacks pour les opérations de système de fichiers POSIX - Le build inclut un fichier toolchain CMake de cross-compilation, une tâche CI pour DJGPP et un cache preseed pour accélérer la configuration
- Les fonctions non incluses sont aussi clairement listées
- L’enregistrement audio est absent ; seule la lecture est prise en charge
- Il n’existe pas d’implémentation native de
SDL_TIME; la couche POSIX de DJGPP réutilise legettimeofdayUnix - Le chargement de bibliothèques partagées n’est pas pris en charge, donc
SDL_LoadObjectest absent
Mise en œuvre et changements clés
- Le port DOS a progressé via plusieurs commits qui ont ajouté progressivement vidéo, audio, entrées, timers, threading et chaîne de build
- Après les premiers travaux, la mise en tampon stdio, l’audio, le sous-système vidéo, le système de fichiers, la souris, le clavier, la CI et la détection de plateforme ont été complétés dans cet ordre
- Pour stdio et l’accès aux fichiers, le port contourne un problème spécifique de seek/read de DJGPP
- Une tentative a d’abord été faite pour désactiver le tampon des SDL_IOStreams stdio, mais elle a ensuite été remplacée par une approche qui vide puis restaure le tampon lors d’un seek
- Ce changement est bien plus rapide qu’une désactivation complète du tampon et évite aussi les mauvaises lectures après
fseek - Le cas où
SDL_LoadWAVmettait plusieurs secondes à liretest/sample.wava disparu, et les données sont désormais correctes
- La méthode de traitement audio a elle aussi été ajustée en continu pour privilégier la stabilité
- L’implémentation a commencé avec Sound Blaster 16, puis a ajouté la prise en charge du mono 8 bits pré-SB16 et de la stéréo SB Pro
- Le mixage audio est passé d’une exécution directe dans le gestionnaire IRQ au passage par la boucle principale, puis de nouveau vers le thread audio SDL
- Ce changement visait à éviter les problèmes de réentrance dans l’IRQ, et l’ancienne moitié du tampon DMA est remplie de silence pendant le chargement pour réduire les saccades
- Le réglage de la fréquence d’échantillonnage, le polling de l’état DSP, la justification de l’allocation mémoire DMA et la libération du wrapper IRET après restauration du vecteur d’interruption ont également été clarifiés
- La vidéo a elle aussi été enrichie pour tenir compte des contraintes de DOS
- Une première implémentation via l’interface VESA a été ajoutée pour fonctionner avec le moteur de rendu logiciel
- S’y sont ensuite ajoutés la prise en charge de la palette 8 bits, le page flipping VBE, la restauration d’état, le vsync en mode simple tampon et le mode framebuffer banked VESA
- Lorsque VBE 1.2+ ne dispose pas de LFB, le framebuffer est copié via bank switching, et le page flipping est désactivé dans ce mode
- L’ensemble de l’état VBE est sauvegardé à l’initialisation vidéo puis restauré à la fermeture pour garder des transitions de mode propres
- La gestion des entrées et des interruptions a aussi été affinée jusqu’à un niveau exploitable en pratique
- Le clavier gère les scancodes étendus ainsi que la touche Pause, et les événements sont stockés dans un simple ring buffer
- La souris utilise la fonction INT 33h
0x1Bpour récupérer la sensibilité - Pour le joystick, le polling des axes est limité à environ 60 Hz afin de réduire le coût de la boucle de timing BIOS, tandis que les boutons restent interrogés directement pour préserver la réactivité
- Le code et les données ISR sont verrouillés afin d’éviter les page faults pendant les interruptions
- Des problèmes liés au build et à la détection de plateforme ont aussi été corrigés
- Une tâche CI pour DJGPP a été ajoutée et la détection de plateforme DOS a été intégrée à CMake
SDL_PLATFORM_DOSa été ajouté à la liste d’exclusion deSDL_RunApp()pour éviter les conflits avec le lanceur spécifique à DOS- Bien que DJGPP définisse
__unix__, DOS ne dispose ni de GTK ni de display server ;SDL_Gtk_Quit()a donc été exclu sur DOS afin d’éviter des erreurs d’édition de liens - Le fait que certaines toolchains DJGPP utilisent le préfixe
i386-pc-msdosdjgpp-gcca également été pris en compte
État des tests et limites restantes
- Les tests automatisés ne se sont pas tous terminés sans accroc, mais le projet a atteint un niveau où ils peuvent être menés à terme avec des correctifs
- En raison de problèmes dans certaines fonctions de formatting standard, les tests automatisés n’allaient pas jusqu’au bout ; un patch de contournement a toutefois permis de les exécuter
- Quelques cas en échec subsistaient, mais ils n’ont pas été inclus faute de certitude sur la bonne manière de corriger ces fonctions de formatting
- La plupart des démos fonctionnent globalement à un niveau jugé conforme aux attentes
- Des retours d’usage réel ont aussi été ajoutés
- Dans DOSBox et sur DOS 6.22 sur une carte Vortex86, le mode fenêtré non fullscreen fonctionne bien, aussi bien pour le programme de test que pour le code utilisateur
- En revanche, à ce moment-là, le fullscreen affichait un écran noir vide dans des exemples comme
draw.exe --fullscreen - Les performances sont lentes, mais considérées comme utilisables
- Certains problèmes dans les programmes de test ont également été constatés
sprite.exese ferme immédiatement dans DOSBoxwm.exeetdraw.exen’affichent rien, mais se ferment quand on appuie sur ESCtestpaletteprovoque une segfault
Problème de sélection de profondeur de couleur en fullscreen et ajustements
- La cause directe de l’écran noir en fullscreen était le comportement de
SDL_GetClosestFullscreenDisplayMode()qui retombait sur un mode INDEX8- Si l’application ne gère pas le rendu INDEX8, l’écran devient noir
- En interne, INDEX8 n’est pris en compte que si l’utilisateur a déjà configuré un mode fullscreen INDEX8
- Au départ, une solution consistant à masquer les modes INDEX8 derrière un
SDL_HINT_DOS_ALLOW_INDEX8_MODESpropre à DOS a été ajoutée- L’objectif était de forcer un opt-in explicite, uniquement lorsque l’application peut traiter correctement ce cas
- Mais la branche principale contenait déjà un changement sélectionnant la profondeur de bits la plus élevée au lieu de la plus faible, et la discussion s’est poursuivie pour vérifier si cela suffisait à résoudre le problème
- Ce changement corrigeait le problème de bpp, mais introduisait un nouveau souci en sélectionnant 1024x768 pour une demande de meilleur ajustement en 640x480
- Il a finalement été annulé, et une meilleure correction a été renvoyée vers une PR distincte
- Finalement, le hint spécifique à DOS a été supprimé au profit d’un ordonnancement plus logique des modes
- Le commit
Remove SDL_HINT_DOS_ALLOW_INDEX8_MODES and order modes logicallya été ajouté - Une fois #15442 fusionnée, il a été conclu que la sélection automatique de mode pourrait fonctionner correctement même pour les applications qui ne définissent pas de palette ou ne choisissent pas elles-mêmes le mode fullscreen
- Une limite a aussi été posée : il ne s’agissait pas de poursuivre indéfiniment dans cette PR le traitement d’autres problèmes existants de SDL
- Le commit
Correctifs de rendu des démos et du curseur
- Le problème des démos noires ne dépendait pas uniquement de cette PR, mais aussi de l’état de fusion de #15442
- Tant que
SDL_GetClosestFullscreenDisplayMode()privilégiait la profondeur de couleur la plus basse, ce port choisissait INDEX8 et l’application affichait un écran noir si elle ne définissait pas de palette - Une fois cette PR fusionnée localement, il a été confirmé que toutes les cibles de test fonctionnaient
- Tant que
- Le dernier problème visuel restant concernait la transparence du curseur
- Après vérification locale, il est apparu que seul le curseur n’était pas transparent
- Le commit
Don't convert cursor if dest is not INDEX8a été ajouté pour corriger ce point - Après la correction, une version non optimisée est utilisée en mode RGB, mais le comportement devient correct à la fois en RGB et en INDEX8
- Il resterait une petite marge d’amélioration des performances en XRGB1555 et RGB565, mais cela a été jugé peu prioritaire
Revue et décision de fusion
- La PR a été jugée adaptée à une squash merge
- GitHub conservant la référence à la PR dans le commit résultant, le déroulé du travail restait traçable
- Il a aussi été proposé d’ajouter une mention de crédit supplémentaire dans le commit final
- Une formulation précise a été fournie pour ajouter deux
Co-authored-byet unTested-by
- Le relecteur a indiqué qu’il réécrirait plus proprement certains scripts de build après la fusion
- Juste avant la fusion finale, la décision a été prise de fusionner aussi d’autres PR liées en même temps et de faire avancer la PR DOS
- Après « Last call on DOS pull request! », l’état de fusion des PR associées a été confirmé
- La PR a ensuite été fusionnée dans
mainavec 46 checks passed
- Le périmètre de release a aussi été clarifié après la fusion
- Ce changement est considéré comme une fonctionnalité de la 3.6.0
-
Pas de cherry-pick vers la 3.4.x
- Le lendemain de la fusion, la branche de travail DOS a été supprimée
Travaux à venir et problèmes matériels restants
- Un problème sur l’implémentation de
4f07(SetDisplayStart)de certains GPU Nvidia a également été soulevé- Avec un lien vers un fil VOGONS, il est indiqué que certains GPU annoncent cette prise en charge mais ne fonctionnent pas réellement
- Il est mentionné que la plage concernée pourrait s’étendre de la GeForce 9300 à la 3060, mais cela reste non exhaustif car limité au matériel disponible
- Les tests du projet ont aussi observé le même problème d’affichage
- Il a été jugé peu souhaitable que SDL désactive cette fonction selon le constructeur GPU, et la possibilité d’un hint laissé au contrôle de l’utilisateur a été évoquée
- L’idée d’un nouveau hint permettant à l’utilisateur de contrôler directement
page_flip_availablea été avancée - Le sujet n’a pas été traité immédiatement et a été laissé pour plus tard
- L’idée d’un nouveau hint permettant à l’utilisateur de contrôler directement
- Après la fusion, un hint concernant l’usage direct du framebuffer a également été mentionné
- En activant
SDL_HINT_DOS_ALLOW_DIRECT_FRAMEBUFFER, le problèmeSetDisplayStartévoqué plus haut pourrait devenir beaucoup moins important
- En activant
1 commentaires
Commentaires Hacker News
Il suffit maintenant d’avoir SDL pour UEFI pour pouvoir lancer des jeux avant même le démarrage de l’OS
Je me demande si la sécurité a été renforcée, ou si ça reste toujours accessible https://www.zdnet.com/article/minix-intels-hidden-in-chip-operating-system/
Par contre, à ma connaissance, l’UEFI n’a pas de pilote audio, et de nos jours même les puces de codec audio n’ont souvent que des datasheets sous NDA, donc en écrire un soi-même est compliqué
Le plus absurde, c’est que le graphics output protocol n’a pas d’info de vsync, donc on ne peut pas faire de blitting sans tearing, et là-dessus c’est littéralement pire que le VGA
Imaginer démarrer sur un menu façon grub et voir apparaître toute une liste de jeux rétro, c’est assez excitant
Ce qui rend cette capture d’écran particulièrement drôle, c’est que DosBOX lui-même est construit au-dessus de SDL
Ça utilise DJGPP, donc ça passe le CPU en mode 32 bits via DPMI
Du coup, on ne retrouve pas vraiment le vrai feeling old school avec la mémoire segmentée, les near pointers et toutes ces limitations de 64 KB dans tous les sens
Excellent
Je me demande ce que ça donnerait avec les exécutables MS-DOS pour 386+ de FreeBASIC, qui prend en charge les bindings SDL
[1] - https://github.com/freebasic/fbc
Ça fait des années que je me dis qu’il faudrait reporter à nouveau OHRRPGCE, à l’origine issu de DOS, vers DOS
Et quand on se rappelle à quel point SDL avait agressivement supprimé presque tous les ports et supports d’OS de l’époque SDL 1.2, le fait que SDL3 récupère le support de DOS est assez surprenant
Parfait
Ce matin, j’étais justement en train de développer dans Turbo C, dans DOSBox-X, dans Debian GNU/Linux, dans VMware Fusion, dans macOS, donc la nouvelle tombe à pic
J’ai un vague souvenir d’avoir travaillé avec turboc il y a des décennies
Techniquement, c’était déjà possible avec HXDOS
Il émulait suffisamment bien DirectDraw pour que SDL puisse l’utiliser
Du coup, je me demande pour quelle cible SDL on compile
Plein écran exclusif Win32, ou bien une résolution VESA comme 640x480 ?
Quand un projet open source comme SDL ajoute ce genre de support, tout dépend généralement du niveau d’intrusion des changements, et de la volonté du contributeur de continuer à assurer la maintenance
Chaque projet a sa propre politique, et je ne connais pas celle de SDL, mais vu le nombre de ports déjà existants, j’imagine qu’ils savent dans quoi ils s’engagent
Mon exemple préféré, c’est openbsd luna88k https://www.openbsd.org/luna88k.html
Je n’ai absolument aucune idée du nombre réel d’utilisateurs. La machine me semble assez rare et probablement distribuée seulement au Japon, et s’il y a des utilisateurs, ils sont sans doute surtout au Japon, donc hors de mon champ de vision ; dans les faits, j’ai l’impression qu’il n’y a qu’un seul utilisateur : le porteur lui-même
Et pourtant, à chaque release, quelques semaines après la date officielle, il surgit de la forêt comme si de rien n’était pour publier les fichiers et paquets luna88k
Je me dis que c’est peut-être simplement parce que compiler sur une vraie luna88k prend du temps, mais quoi qu’il en soit, ça suffit largement pour que luna88k reste une plateforme matérielle officielle d’OpenBSD
Je ne veux pas spécialement posséder une luna88k moi-même, mais j’ai énormément de respect pour la personne qui continue de faire tourner tout ça
On a l’impression que SDL revient à ses racines de l’époque Loki
Excellent
Pourquoi ? Aucune idée, mais si c’est cool, c’est cool
Comme on peut le voir sur Internet Archive, avec juste un clavier et une souris, on peut pratiquement exécuter partout des jeux de la complexité AAA du milieu des années 90
Des jeux comme Tomb Raider, Command & Conquer ou Quake le montrent bien, et si on veut simplement une plateforme qui marche bien, c’est plutôt séduisant
Avec SDL en plus, ça devient bien plus facile
Ça me fait vraiment plaisir
Ça me rend très heureux