Bref, ne nous arrêtons pas là. Debian 7 (Wheezy) propose toujours le paquet de la bibliothèque. Après quelques hacks (patch 64 bits, création de liens symboliques vers libSDL1.2 et OpenAL, chargement du module snd-pcm-oss), on arrive à avoir un jeu pleinement fonctionnel.
Après quelques parties, intéressons-nous un peu plus sur la façon dont a été créé le jeu. En effet, une des questions d'un de mes collègues (aussi fan du jeu) est de comprendre le système de dépendances des bibliothèques sous Linux. Faisons donc un ldd sur le binaire du jeu :
linux-vdso.so.1 => (0x00007fff0fdff000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fbc2d15a000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fbc2cf3d000)
./libSDL-1.2.so.0 (0x00007fbc2cca1000)
libstdc++.so.5 => /usr/lib/x86_64-linux-gnu/libstdc++.so.5 (0x00007fbc2c9c5000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fbc2c742000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fbc2c52c000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fbc2c1a0000)
/lib64/ld-linux-x86-64.so.2 (0x00007fbc2d381000)
libasound.so.2 => /usr/lib/x86_64-linux-gnu/libasound.so.2 (0x00007fbc2beab000)
libpulse-simple.so.0 => /usr/lib/x86_64-linux-gnu/libpulse-simple.so.0 (0x00007fbc2bca6000)
libpulse.so.0 => /usr/lib/x86_64-linux-gnu/libpulse.so.0 (0x00007fbc2ba5c000)
libX11.so.6 => /usr/lib/x86_64-linux-gnu/libX11.so.6 (0x00007fbc2b720000)
libXext.so.6 => /usr/lib/x86_64-linux-gnu/libXext.so.6 (0x00007fbc2b50e000)
libdirectfb-1.2.so.9 => /usr/lib/x86_64-linux-gnu/libdirectfb-1.2.so.9 (0x00007fbc2b289000)
libfusion-1.2.so.9 => /usr/lib/x86_64-linux-gnu/libfusion-1.2.so.9 (0x00007fbc2b07e000)
libdirect-1.2.so.9 => /usr/lib/x86_64-linux-gnu/libdirect-1.2.so.9 (0x00007fbc2ae66000)
libcaca.so.0 => /usr/lib/x86_64-linux-gnu/libcaca.so.0 (0x00007fbc2ad99000)
libts-0.0.so.0 => /usr/lib/x86_64-linux-gnu/libts-0.0.so.0 (0x00007fbc2ab95000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007fbc2a98d000)
libpulsecommon-2.0.so => /usr/lib/x86_64-linux-gnu/pulseaudio/libpulsecommon-2.0.so (0x00007fbc2a729000)
libcap.so.2 => /lib/x86_64-linux-gnu/libcap.so.2 (0x00007fbc2a525000)
libjson.so.0 => /lib/x86_64-linux-gnu/libjson.so.0 (0x00007fbc2a31b000)
libdbus-1.so.3 => /lib/x86_64-linux-gnu/libdbus-1.so.3 (0x00007fbc2a0d4000)
libxcb.so.1 => /usr/lib/x86_64-linux-gnu/libxcb.so.1 (0x00007fbc29eb4000)
libslang.so.2 => /lib/x86_64-linux-gnu/libslang.so.2 (0x00007fbc29b1d000)
libncursesw.so.5 => /lib/x86_64-linux-gnu/libncursesw.so.5 (0x00007fbc298ed000)
libtinfo.so.5 => /lib/x86_64-linux-gnu/libtinfo.so.5 (0x00007fbc296c4000)
libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007fbc294ac000)
libX11-xcb.so.1 => /usr/lib/x86_64-linux-gnu/libX11-xcb.so.1 (0x00007fbc292ab000)
libICE.so.6 => /usr/lib/x86_64-linux-gnu/libICE.so.6 (0x00007fbc29090000)
libSM.so.6 => /usr/lib/x86_64-linux-gnu/libSM.so.6 (0x00007fbc28e88000)
libXtst.so.6 => /usr/lib/x86_64-linux-gnu/libXtst.so.6 (0x00007fbc28c83000)
libwrap.so.0 => /lib/x86_64-linux-gnu/libwrap.so.0 (0x00007fbc28a78000)
libsndfile.so.1 => /usr/lib/x86_64-linux-gnu/libsndfile.so.1 (0x00007fbc28810000)
libasyncns.so.0 => /usr/lib/x86_64-linux-gnu/libasyncns.so.0 (0x00007fbc2860b000)
libattr.so.1 => /lib/x86_64-linux-gnu/libattr.so.1 (0x00007fbc28406000)
libXau.so.6 => /usr/lib/x86_64-linux-gnu/libXau.so.6 (0x00007fbc28202000)
libXdmcp.so.6 => /usr/lib/x86_64-linux-gnu/libXdmcp.so.6 (0x00007fbc27ffd000)
libuuid.so.1 => /lib/x86_64-linux-gnu/libuuid.so.1 (0x00007fbc27df7000)
libXi.so.6 => /usr/lib/x86_64-linux-gnu/libXi.so.6 (0x00007fbc27be8000)
libnsl.so.1 => /lib/x86_64-linux-gnu/libnsl.so.1 (0x00007fbc279d0000)
libFLAC.so.8 => /usr/lib/x86_64-linux-gnu/libFLAC.so.8 (0x00007fbc27781000)
libvorbisenc.so.2 => /usr/lib/x86_64-linux-gnu/libvorbisenc.so.2 (0x00007fbc272b2000)
libvorbis.so.0 => /usr/lib/x86_64-linux-gnu/libvorbis.so.0 (0x00007fbc27085000)
libogg.so.0 => /usr/lib/x86_64-linux-gnu/libogg.so.0 (0x00007fbc26e7e000)
libresolv.so.2 => /lib/x86_64-linux-gnu/libresolv.so.2 (0x00007fbc26c68000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fbc2d15a000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fbc2cf3d000)
./libSDL-1.2.so.0 (0x00007fbc2cca1000)
libstdc++.so.5 => /usr/lib/x86_64-linux-gnu/libstdc++.so.5 (0x00007fbc2c9c5000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fbc2c742000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fbc2c52c000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fbc2c1a0000)
/lib64/ld-linux-x86-64.so.2 (0x00007fbc2d381000)
libasound.so.2 => /usr/lib/x86_64-linux-gnu/libasound.so.2 (0x00007fbc2beab000)
libpulse-simple.so.0 => /usr/lib/x86_64-linux-gnu/libpulse-simple.so.0 (0x00007fbc2bca6000)
libpulse.so.0 => /usr/lib/x86_64-linux-gnu/libpulse.so.0 (0x00007fbc2ba5c000)
libX11.so.6 => /usr/lib/x86_64-linux-gnu/libX11.so.6 (0x00007fbc2b720000)
libXext.so.6 => /usr/lib/x86_64-linux-gnu/libXext.so.6 (0x00007fbc2b50e000)
libdirectfb-1.2.so.9 => /usr/lib/x86_64-linux-gnu/libdirectfb-1.2.so.9 (0x00007fbc2b289000)
libfusion-1.2.so.9 => /usr/lib/x86_64-linux-gnu/libfusion-1.2.so.9 (0x00007fbc2b07e000)
libdirect-1.2.so.9 => /usr/lib/x86_64-linux-gnu/libdirect-1.2.so.9 (0x00007fbc2ae66000)
libcaca.so.0 => /usr/lib/x86_64-linux-gnu/libcaca.so.0 (0x00007fbc2ad99000)
libts-0.0.so.0 => /usr/lib/x86_64-linux-gnu/libts-0.0.so.0 (0x00007fbc2ab95000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007fbc2a98d000)
libpulsecommon-2.0.so => /usr/lib/x86_64-linux-gnu/pulseaudio/libpulsecommon-2.0.so (0x00007fbc2a729000)
libcap.so.2 => /lib/x86_64-linux-gnu/libcap.so.2 (0x00007fbc2a525000)
libjson.so.0 => /lib/x86_64-linux-gnu/libjson.so.0 (0x00007fbc2a31b000)
libdbus-1.so.3 => /lib/x86_64-linux-gnu/libdbus-1.so.3 (0x00007fbc2a0d4000)
libxcb.so.1 => /usr/lib/x86_64-linux-gnu/libxcb.so.1 (0x00007fbc29eb4000)
libslang.so.2 => /lib/x86_64-linux-gnu/libslang.so.2 (0x00007fbc29b1d000)
libncursesw.so.5 => /lib/x86_64-linux-gnu/libncursesw.so.5 (0x00007fbc298ed000)
libtinfo.so.5 => /lib/x86_64-linux-gnu/libtinfo.so.5 (0x00007fbc296c4000)
libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007fbc294ac000)
libX11-xcb.so.1 => /usr/lib/x86_64-linux-gnu/libX11-xcb.so.1 (0x00007fbc292ab000)
libICE.so.6 => /usr/lib/x86_64-linux-gnu/libICE.so.6 (0x00007fbc29090000)
libSM.so.6 => /usr/lib/x86_64-linux-gnu/libSM.so.6 (0x00007fbc28e88000)
libXtst.so.6 => /usr/lib/x86_64-linux-gnu/libXtst.so.6 (0x00007fbc28c83000)
libwrap.so.0 => /lib/x86_64-linux-gnu/libwrap.so.0 (0x00007fbc28a78000)
libsndfile.so.1 => /usr/lib/x86_64-linux-gnu/libsndfile.so.1 (0x00007fbc28810000)
libasyncns.so.0 => /usr/lib/x86_64-linux-gnu/libasyncns.so.0 (0x00007fbc2860b000)
libattr.so.1 => /lib/x86_64-linux-gnu/libattr.so.1 (0x00007fbc28406000)
libXau.so.6 => /usr/lib/x86_64-linux-gnu/libXau.so.6 (0x00007fbc28202000)
libXdmcp.so.6 => /usr/lib/x86_64-linux-gnu/libXdmcp.so.6 (0x00007fbc27ffd000)
libuuid.so.1 => /lib/x86_64-linux-gnu/libuuid.so.1 (0x00007fbc27df7000)
libXi.so.6 => /usr/lib/x86_64-linux-gnu/libXi.so.6 (0x00007fbc27be8000)
libnsl.so.1 => /lib/x86_64-linux-gnu/libnsl.so.1 (0x00007fbc279d0000)
libFLAC.so.8 => /usr/lib/x86_64-linux-gnu/libFLAC.so.8 (0x00007fbc27781000)
libvorbisenc.so.2 => /usr/lib/x86_64-linux-gnu/libvorbisenc.so.2 (0x00007fbc272b2000)
libvorbis.so.0 => /usr/lib/x86_64-linux-gnu/libvorbis.so.0 (0x00007fbc27085000)
libogg.so.0 => /usr/lib/x86_64-linux-gnu/libogg.so.0 (0x00007fbc26e7e000)
libresolv.so.2 => /lib/x86_64-linux-gnu/libresolv.so.2 (0x00007fbc26c68000)
Grâce à son nom, disons, très particulier, je connaissais son but : le rendu de graphisme en Ascii Art.
Pourquoi ?
L'explication se trouve avec la SDL 1.2. En effet, cette bibliothèque supporte plusieurs pilotes pour le rendu, notamment dans le tampon d'image, ou encore en Ascii art. La question qui restera toujours en suspend pour moi : était-ce vraiment prévu par les créateurs du jeu ?
Après une recherche sur Internet, on ne trouve pas grand-chose à ce sujet (mis à part cette vielle FAQ Ok, donc il y a quelque chose à faire).
Comment
Comment activer ce rendu. Je sais qu'il est là, tout semble bon pour y accéder, mais comment l'activer ?
Un premier réflexe est de chercher dans les fichiers de configuration du jeu (UT2004.ini) :
;RenderDevice=D3DDrv.D3DRenderDevice
;RenderDevice=D3D9Drv.D3D9RenderDevice
;RenderDevice=Engine.NullRenderDevice
;RenderDevice=SDLSoftDrv.SDLSoftwareRenderDevice
RenderDevice=OpenGLDrv.OpenGLRenderDevice
;RenderDevice=PixoDrv.PixoRenderDevice
;RenderDevice=D3D9Drv.D3D9RenderDevice
;RenderDevice=Engine.NullRenderDevice
;RenderDevice=SDLSoftDrv.SDLSoftwareRenderDevice
RenderDevice=OpenGLDrv.OpenGLRenderDevice
;RenderDevice=PixoDrv.PixoRenderDevice
Can't find file for package 'SDLSoftDrv'
History:
Exiting due to error
History:
Exiting due to error
env CACA_DRIVER=ncurses SDL_VIDEODRIVER=caca programme
Wow !
On a la bonne commande pour lancer le jeu en utilisant un autre pilote pour le rendu. Malheureusement, on ne peut pas aller plus loin :
No dynamic GL support in video driver
History:
Exiting due to error
History:
Exiting due to error
En effet, avec un rendu en Ascii art et complètement CPU, il va être difficile d'obtenir un contexte OpenGL. Dans la théorie, cela voudrait dire que le GPU effectue tous les calculs pour préparer l'image, puis qu'il faille récupérer le rendu du GPU pour le redonner à libcaca. Actuellement, cela ne me semble pas du tout possible, sauf peut être avec l'implémentation libre d'OpenGL : mesa (qui propose un rendu logiciel). En réalité, il me reste quelques recherches à faire sur ce point (notamment à cause de : http://caca.zoy.org/list/msg00064.html).
Bref, passons sur OpenGL. Je m'étais souvenu que sous Windows, UT2004 était capable d'utiliser un rendu logiciel (option d'affichage : software). C'était la piste évidente, me permettant ainsi d'échapper à l'erreur demandant le support d'OpenGL. Malheureusement, cette option n'est pas disponible par les menus. Je suis retombé sur un vieux site présentant Unreal Tournament 2004 et mentionnant le rendu logiciel :
Pixomatic software renderer allowing incredible performance with no 3D card required. Play UT2004 on your laptop!
Donc, il faut que je change mon fichier de configuration (UT2004.ini) pour activer le rendu logiciel :
;RenderDevice=D3DDrv.D3DRenderDevice
;RenderDevice=D3D9Drv.D3D9RenderDevice
;RenderDevice=Engine.NullRenderDevice
;RenderDevice=SDLSoftDrv.SDLSoftwareRenderDevice
;RenderDevice=OpenGLDrv.OpenGLRenderDevice
RenderDevice=PixoDrv.PixoRenderDevice
;RenderDevice=D3D9Drv.D3D9RenderDevice
;RenderDevice=Engine.NullRenderDevice
;RenderDevice=SDLSoftDrv.SDLSoftwareRenderDevice
;RenderDevice=OpenGLDrv.OpenGLRenderDevice
RenderDevice=PixoDrv.PixoRenderDevice
Can't find file for package 'PixoDrv'
History:
Exiting due to error
History:
Exiting due to error
Alors, sans plus attendre, j'installe un Debian dans une machine virtuelle, en 32 bits. J'installe le jeu. Je configure le fichier et ...
Voilà !
Cinématique d'introduction :
Avec la commande (qui ouvre une fenêtre X11 pour le rendu):
env CACA_DRIVER=x11 SDL_VIDEODRIVER=caca ./ut2004
Avec la commande dans le TYY:
env CACA_DRIVER=ncurses SDL_VIDEODRIVER=caca ./ut2004
Problèmes de curseur
Malheureusement, le jeu n'est pas totalement jouable. Même si cela permet de jouer dans un TTY (et donc à travers SSH !), le curseur n'est pas correctement géré. En effet, le jeu n'est pas notifié du déplacement du curseur sur l'écran et il ne recevra sa position, qu'au moment d'un clic. Ce qui n'est vraiment pas pratique pour un FPS.
Si on joue avec une fenêtre (X11), le curseur permet bien de bouger la caméra avec ou sans clic. Mais un second problème arrive : le curseur n'est pas bloqué par les bords de la fenêtre (ou encore, une autre technique du monde du jeu vidéo est de bloquer le curseur au centre de l'écran). Du coup, il n'est possible de tourner la caméra que de 90°.
Mots de la fin
Cela a été amusant à mettre en place. Tout cela n'aurait pas été possible sans le travail des développeurs d'Epic Games et du travail des développeurs de la libcaca. D'ailleurs, le rendu est aussi captivant à voir grâce à libcaca.
Quelques questions restent en suspens. Notamment, est-il possible de lancer un contexte OpenGL et d'utiliser la libcaca. Ainsi teeworlds (et d'autres) pourra être lancé en Ascii.