État des lieux :

En effet, dans le billet Une Borne d'Arcade maison -4-, je concluais comme ceci :

on se rends compte que le TV ne supporte pas des valeurs de pclock basses […] le TV n'est capable de fonctionner que dans sa résolution native, avec un pixel clock élevé (15 à 17MHz)-- […] à moins d'avoir un téléviseur qui accepte un faible pclock (testé 2 télé, résultats idem), je ne vois pas comment exploiter correctement le mode Frame Buffer d'AdvanceMame sur un TV !!

FAUX, un téléviseur sait très bien exploiter un signal de faible pclock, par exemple, puisqu'une Super Nintendo a toujours su afficher une image de faible résolution.

  • Tout ça en fait est la faute aux pilotes libres ATI et nVidia qui ont vu leurs capacités à fournir des petites résolutions supprimées de linux, ce afin de protéger les écrans informatiques actuels d'une mauvaise manipulation d'un administrateur peu averti.

Comment faire alors ?


Une première piste :

  • Sans la voir, j'avais une partie de l'explication sous les yeux, dans la documentation d'installation indiquant la disponibilité de patchs frame buffer dans les fichiers sources d'Advancemame ( dossier contrib/mame/fb).

Ces patchs de pilotes vidéo servent en fait à faire sauter cette « sécurité », autorisant alors l'utilisation de faible pclock !

Super ! bah voilà, yaka patcher >_<;
Oui mais quoi ? Pas vraiment expliqué, on découvre qu'il s'agit de patch pour linux
Okééé, ça veut dire compilation de noyaux… chouette… Y'a pas un module dispo dés fois ? Arf, bah non -_-.
Bon, alors allons-y, patchons !

  • Sauf que les patchs proposés sont valables pour des vielles versions de linux, et après avoir ressortit un vieux noyaux chez kernel.org (linux-2.4.22), l'avoir patché avec succès (linux-2.4.22-radeonfb-id.diff et linux-2.4.22-rivafb-0.9.4c.diff) la compilation n'a pas aboutit, sans doute due à une mauvaise configuration dans la phase menuconfig que je ne maîtrise pas suffisamment.

Une seconde piste :

  • Amèrement, je laissais cette défaite derrière moi en re-découvrant, la possibilité d'utiliser SVGAlib pour faire à peu de choses près la même chose qu'avec frame buffer; Ici pas besoin de compiler linux, juste installer SVGAlib et de me souvenir que déjà à l'époque, je n'étais pas parvenu à compiler SVGAlib dans la version 1.9.14 recommandée.

En effet la compilation plante lamentablement.
J'ai alors essayé les autres versions, en les patchant à chaque fois (patch dispo dans les fichiers sources, contrib/mame/svgalib), mais sans succès, compilation impossible.
Des pistes de recherches me firent entrevoir que vu la vétusté du truc, les compilateurs actuels n'étaient peut-être par capable de le compiler.
Et donc de me mettre en quête d'installer un OS avec une vieille version de GCC, mais toujours sans résultat T_T.

  • Il fallait que je me fasse une raison, tous ces softs et les patchs disponibles sont trop vieux pour être exploités.

L'ultime solution envisageable restant alors de me fabriquer ma propre distribution grâce à Linux From Scratch… Projet très intéressant, mais… STOP ! Ça va trop loin là, au départ je voulais juste une fonction toute simple ^^;

La troisième, c'est la bonne !

  • Et c'est là qu'intervient le projet GroovyMame !

Celui-ci propose une distribution iso contenant un linux déjà patché 15kHz et le logiciel GroovyMame, qui sans que les modelines de chaque résolutions n'aient besoins d'être listées dans xorg, bascule dans la résolution de chaque jeux :

1 - Lancement du jeu.
2 - Détection de la résolution du jeu par Switchres.
3 - Génération/sélection du modelines par Switchres, envoyée à Xrandr, (le plus proche possible de l'original, mais dés fois bien à l'ouest)
4 - Xrandr sélectionne cette résolution et y bascule l'affichage de Xorg.

  • La solution était là, c'est ce noyaux qu'il me fallait.…

Sauf que le site du projet à déménagé 3 fois depuis un sourceforge vers un google code, puis vers un homonyme sans tiret dans l'url, que le dépot GIT ne fonctionne pas… Grrrrr !! Maiiis Heu!!!
Bref, j'ai tout de même réussit à récupérer une vieille version des sources et à tester aussi le binaire de GroovyMame, mais rien pour patcher le noyaux…
Ce n'est qu'en fouillant le forum Arcade Control que j'ai fini par trouver un développeur du projet qui en a posté quelques versions !

Compilation de Linux patché @15kHz :[1]

  • Je vais donc décrire comment j'ai généré ce noyau, mais avant d'aller plus loin, je pense à ceux que la compilation de noyau rebute, ou pour qui le tuto se passerait mal (interruption inexpliquée de la compilation…) et propose de télécharger le linux patché 15kHz que j'ai compilé, prêt à être installé en quelques secondes sur « toutes distributions » de la grande famille Debian (Ubuntu, Mint, etc)… Je n'en ai testé que deux ( Debian Wheezy et sur Ubuntu 10.04LTS), mais ça devrait passer ailleurs…

http://makotoworkshop.org/packages/linux-image-3.2.32-patched15khz_i386.deb
http://makotoworkshop.org/packages/linux-image-3.9.6-patched15khz_i386.deb
Pour l'installer, suffit d'utiliser dpkg avec les droits root ou via un sudo :

dpkg -i linux-image-3.2.32-patched15khz_i386.deb


Bien ! Passons aux choses sérieuses !

  • Préambule, rappel des faits :

Il est en fait, nous l'avions vu, déjà possible d'afficher une image en 15 kHz sur un téléviseur grâce à Xorg configuré à l'ancienne avec le fichier xorg.conf, avec xrandr, ou maintenant avec KMS.
Il suffit pour cela de passer un modeline au pilote libre ATI (radeon) ou nVidia (nouveau).
Voici un exemple de fichier xorg.conf qui fonctionne à tous les coups :

Section "Device"
    Identifier  "ATI"
    Driver      "radeon"
EndSection

Section "Monitor"
        Identifier   "TV"
        HorizSync    15.0 - 20.0
        VertRefresh  50.0 - 60.0
# Le modeline TV @15kHz
    Modeline "768x288x50.08"  15.375000  768 792 880 964 288 288 288 322  -HSync -VSync
EndSection

Section "Screen"
    Identifier "Default Screen"
    Device     "ATI"
    Monitor    "TV"
    DefaultDepth     24
    SubSection "Display"
    Depth     24
    Modes    "768x288x50.08"
    EndSubSection
EndSection

Donc avec ceci, on affiche une image progressive de 768x288 avec un PixelClock de 15.375 MHz.
Pour afficher une image plus petite, le PixelClock sera donc plus petit, de l'ordre de 6 ou 7 MHz…
Et bien comme je l'évoquais, tests à l'appui, force est de constater que les pilotes libres contenus dans Linux ne sont pas capables de gérer un faible PixelClock !
Impossible donc d'afficher une image à 320x240.

L'équipe de GroovyMame fournit des patchs pour modifier les sources de n'importe quel Linux qu'il faut ensuite compiler et installer sur sa distribution préférée.

Les voici rassemblés ici par mes soins : http://makotoworkshop.org/sources/patch15khz/

  • I - Prérequis

Dans cet exemple, nous allons compiler un Linux sur Debian Wheezy, qui tourne pour le moment avec un kernel 3.2.
Notes : Contrairement à mon habitude, je vais indiquer les chemins donnés par le terminal, histoire de pouvoir bien suivre le processus, donc :
- Le caractère # signifie qu'on est logué en root où que les droits root sont nécessaires (sudo).
- Le caractère $ signifie qu'on est logué en utilisateur.
- Le caratère ~ signifie que le chemin actuel se trouve dans le dossier de l'utilisateur (/home/votre_utilisateur, ou /root).

I–1 - Installer les programmes nécessaires à la compilation :

~# apt-get install build-essential kernel-package debconf-utils dpkg-dev debhelper ncurses-dev fakeroot zlib1g-dev


I–2 - Préparation et récupération des sources :

Aller dans son répertoire personnel et créer le répertoire de travail :

~$ cd ~/
~$ mkdir src


I–3 - Obtenir les sources à partir des dépôts :

Pour connaître les sources disponibles pour votre système :

~$ aptitude search linux-source

Renverra quelque chose du genre :

v   linux-source              - Linux kernel source (meta-package)
p   linux-source-2.6          - Linux kernel source (dummy package)
p   linux-source-3.2          - Linux kernel source for version 3.2 with Debian patches

Pour obtenir les sources, il suffit d'installer le paquet et de déplacer les données :

~$ su -
mot de passe :
~# apt-get install linux-source-3.2
~# cp /usr/src/linux-source-3.2.tar.bz2 /home/votre_user/src
~# chown votre_user:votre_user /home/votre_user/src/linux-source-3.2.tar.bz2


I–4 - On travaille avec un utilisateur :

Une fois les paquets installés il va falloir décompresser les sources de votre futur noyau. Il est conseillé de déléguer les tâches de configuration du noyau à un utilisateur. Pour cela, l'utilisateur doit appartenir au groupe src.
Pour ajouter par exemple l'utilisateur makoto au groupe src :

~# adduser makoto src
Adding user `makoto' to group `src' ...
Adding user makoto to group src
Done.
~# exit


I–5 - Se placer dans votre répertoire ~/src et décompresser les sources :

~$ cd src/
~/src$ tar xvjf linux-source-3.2.tar.bz2


I–6 - Le chemin vers les sources :

On ajoute enfin les liens symboliques linux qui pointent vers le répertoire de vos sources. Ainsi suivant la version de nos sources on sait qu'elles se trouveront toujours dans le répertoire ~/src/linux :
Remarque: Il est possible que le lien symbolique existe déjà, auquel cas il faudra l'effacer...

~/src$ su -
mot de passe :
~# cd /usr/src/
/usr/src# ln -s /home/votre_user/src/linux-source-3.2 linux
/usr/src# exit
~/src$ ln -s ~/src/linux-source-3.2 linux


  • II - Patcher les sources

II–1 - Récupération des patchs :

Se rendre dans votre home et télécharger puis extraire le TarGz de patch correspondant à votre noyau, ici le fichier patch-3.2.tar.gz pour le noyau 3.2.

~/src$ cd ~/
~$ wget makotoworkshop.org/sources/patch15khz/patch-3.2.tar.gz
~$ tar xvf patch-3.2.tar.gz


II–2 - Tester les patchs :

Se rendre dans le dossier linux

~$ cd src/linux

Lancer successivement ces 3 commandes pour tester chaque patchs sur les sources sans l'appliquer:

~/src/linux$ patch -p1 --dry-run < ~/patch-3.2/ati9200_pllfix-3.4.diff
~/src/linux$ patch -p1 --dry-run < ~/patch-3.2/avga3000-3.4.diff
~/src/linux$ patch -p1 --dry-run < ~/patch-3.2/linux-3.4.diff

Aucune erreur ne doit être retournée.

II–3 - Application des patchs :

Patcher les sources successivement avec ces 3 commandes :

~/src/linux$ patch -p1 < ~/patch-3.2/ati9200_pllfix-3.4.diff
~/src/linux$ patch -p1 < ~/patch-3.2/avga3000-3.4.diff
~/src/linux$ patch -p1 < ~/patch-3.2/linux-3.4.diff


  • III - Configuration du noyau

Récupérer la configuration du noyau :

~/src/linux$ cp -vi /boot/config-`uname -r` .config

Mettre à jour la configuration.

~/src/linux$ make oldconfig

Puisqu'on compile la même version que le noyau actuel, la commande ne doit constater aucune différence, et donc ne poser aucune question.

  • IV - La compilation

Nettoyage avant compilation :

~/src/linux$ make-kpkg clean


La commande fakeroot permet de simuler l'environnement root au programme make-kpkg pour que ce dernier puisse générer les paquets de votre futur noyau. Cela a l'avantage d'éviter de faire la compilation en tant que root.
La compilation sur une machine puissante dure à peine 30 minutes. Cela peut dépasser plusieurs heures en fonction de votre configuration.[2]

~/src/linux$ fakeroot make-kpkg \--initrd \--append-to-version "-pached15khz"  kernel-image kernel-headers

La commande ci-dessus vous sortira un paquet nommé "linux-image-3.2-patched15khz_3.2-patched15khz-10.00.Custom_i386.deb"

  • V - Installation du noyau
~/src/linux$ su -
mot de passe :
~# cd /home/votre_user/src/
/home/votre_user/src# dpkg -i linux-image-3.2-patched15khz_3.2-patched15khz-10.00.Custom_i386.deb


  • VI - Test du noyau

Redémarrer l'ordinateur sur ce noyau fraîchement installé. Si tout va bien le démarrage se passera sans encombre, sinon en cas de Kernel Panic, voir VII

VI–1 - Pour tester le noyau avec xorg.conf :

  • Modifier ou créer le fichier :
~# nano /etc/X11/xorg.conf

Et remplacer le modeline par celui-ci, en 320x240. (testé compatible ATI Radeon 9000 et 9200 et nVdia TNT2 Model 64 et Elsa Erazor X)

Section "Device"
    Identifier  "ATI"
    Driver      "radeon"
EndSection

Section "Monitor"
        Identifier   "TV"
        HorizSync    15.0 - 20.0
        VertRefresh  50.0 - 60.0
# Le modeline TV @15kHz
    Modeline "320x240"  6.452  320 344 376 408 240 242 245 264  -HSync -VSync
EndSection

Section "Screen"
    Identifier "Default Screen"
    Device     "ATI"
    Monitor    "TV"
    DefaultDepth     24
    SubSection "Display"
    Depth     24
    Modes    "320x240"
    EndSubSection
EndSection

Pour une carte nVidia, remplacer simplement :

  Driver      "radeon"

par

  Driver      "nouveau"
  • Démarrer X :
$ startx

Enjoy !!!


VI–2 - Pour tester le noyau avec Xrandr, sans fichier xorg.conf :

Oui, ce fichier n'est plus nécessaire de nos jours. Son absence n'empêchera par X de démarrer.

Démarrer X :

$ startx
  • Xrandr permet de changer de la résolution d'X par une simple commande.

Elle permet aussi d'ajouter des modelines en plus; Taper :

$ xrandr

Et apparaît alors la liste des résolutions disponibles, donc en 31kHz !
Une astérisque repère la résolution en cour…

  • Pour ajouter le modeline d'exemple, taper ceci :
$ xrandr --newmode "320x240" 6.452 320 344 376 408 240 242 245 264 -hsync -vsync
  • Taper à nouveau xrandr permet de voir que le mode a été créé, mais il n'est pas encore utilisable en l'état !
320x240 (0x1da)    6.0MHz
h: width   320 start  344 end  376 total  408 skew    0 clock   14.7KHz
v: height  240 start  242 end  245 total  264           clock   55.7Hz
  • En effet, il faut l'associer à une sortie de la carte graphique (selon la carte, VGA-0 ou DVI-0 avec ATI)
$ xrandr --addmode DVI-0 "320x240"

Un nouveau xrandr listera maintenant la résolution disponible.

  • Reste donc à basculer dessus avec :
$ xrandr --output DVI-0 --mode "320x240"

L'affichage bascule en 320x240, débrancher vite l'écran VGA et connecter le téléviseur sur la carte graphique…

Enjoy !!!


  • Il est bien sûr possible d'automatiser un peu cela avec un script bash, histoire de ne pas avoir à se repalucher les lignes de commande !

Genre comme ça :

#!/bin/bash
xrandr --newmode "256x264" 5.356 256 272 296 328 264 265 268 278 -hsync -vsync
xrandr --newmode "304x240" 6.208 304 328 360 392 240 243 246 264 -hsync -vsync
xrandr --newmode "320x240" 6.452 320 344 376 408 240 242 245 264 -hsync -vsync
xrandr --newmode "384x288" 7.851 384 408 448 496 288 289 292 309 -hsync -vsync
xrandr --newmode "640x288" 13.125 640 680 744 832 288 289 292 309 -hsync -vsync
xrandr --addmode DVI-0 "256x264"
xrandr --addmode DVI-0 "304x240"
xrandr --addmode DVI-0 "320x240"
xrandr --addmode DVI-0 "384x288"
xrandr --addmode DVI-0 "640x288"

Voilà, nous en avons terminé !

Utiliser Advancemame avec Xorg en 15kHz :

Vous êtes encore là ??

Bien, alors on en arrive au but de la manœuvre ^_^

Mais ça, c'eut été vrai en utilisant la méthode d'affichage en frame buffer ou SVGAlib.
Avec Xorg, on est obligé d'utiliser la méthode d'affichage SDL qui n'est pas capable de cela.

  • Néanmoins, il est possible de renseigner la Section Monitor du fichier Xorg.conf avec tous les modelines dont on a besoin, et de configurer AdvanceMame afin qu'il les exploite à bon escient :
Section "Monitor"
        Identifier   "TV"
        HorizSync    15.0 - 20.0
        VertRefresh  50.0 - 60.0
# Les modelines TV @15kHz
    Modeline "256x264" 5.356 256 272 296 328 264 265 268 278  -HSync -VSync
    Modeline "304x240" 6.208 304 328 360 392 240 243 246 264  -HSync -VSync
    Modeline "320x240" 6.452 320 344 376 408 240 242 245 264  -HSync -VSync
    Modeline "384x288" 7.851 384 408 448 496 288 289 292 309  -HSync -VSync
    Modeline "640x288" 13.125 640 680 744 832 288 289 292 309  -HSync -VSync
EndSection
  • Pour utiliser ces modelines inscrit dans xorg.conf, le fichier ~/.advance/advmame.rc devra donc contenir les options suivantes :[3]
device_video sdl
device_video_output fullscreen
device_video_overlaysize auto 
display_resize none
display_resizeeffect none
  • Maintenant après avoir lancé un jeu, il suffit de faire apparaître le menu (Tab), d'aller dans la section video, d'entrer dans la sous section mode et de choisir le modeline correspondant à la résolution indiquée par le carton qui s'est affiché au lancement du jeu.

L'affichage va basculer dans ce mode…

Puis sortir de cette section et aller en bas sur Save for this game size/freq, qui aura pour effet de sauvegarder ce réglage dans le fichier advmame.rc !

  • C'est fait, on utilise à présent les résolutions natives de chaque jeux ^_^

Note importante :
Pour utiliser l'émulateur sous Debian, il faut, après avoir activé les dépots « non-free », ajouter le paquet « firmware-linux-nonfree » qui contient des bouts de drivers non libre, permettant donc d'activer le Direct Rendering, ceci pour résoudre des problèmes de cisaillement dans l'image (tearing), en plus d'un crénelage excessif.
Ce problème n'apparaît pas avec Ubuntu, car le paquet non-libre « linux-firmware » est installé par défaut…[4]


  • VII - Désinstallation :

Si pour une raison ou une autre vous n'arrivez pas à démarrer sur votre nouveau noyau et que vous souhaitiez le désinstaller. Redémarrez sur le dernier noyau opérationnel, puis :

~$ su -
mot de passe : 
~# apt-get remove --purge linux-image-3.2-patched15khz_3.2-patched15khz-10.00.Custom_i386.deb


À suivre…

Ressources :

http://advancemame.sourceforge.net/doc.html
http://www.isalo.org/wiki.debian-fr/index.php?title=Compiler_et_patcher_son_noyau
easymamecab.mameworld.info/html/svgalib.htm

Notes

[1] - Quand je dis «Linux» je parle bien entendu du noyau (kernel) et non de la distribution GNU/Linux (debian, Ubuntu, RedHat…)

[2] Astuce : Il peut alors être utile d'utiliser VirtualBox pour compiler le noyau sur un PC puissant, puis de récupérer le paquet compilé pour aller l'installer sur sa vieille machine de récup destinée à la borne.

[3] Ces options sont décrites dans la documentation dispo avec les sources, ou en ligne : http://advancemame.sourceforge.net/doc-advdev.html#4 et http://advancemame.sourceforge.net/doc-advmame.html#8.3

[4] Pourquoi Ubuntu contient déjà ces morceaux de code ? Peut-être parce que la distribution n'est pas si libre qu'elle en à l'air, mais c'est pour faciliter la vie parait-il… En attendant ça m'a fait perdre beaucoup de temps dans ma quête de la compréhension du système -_-