Comment j’ai réussi à rejouer à mes vieilles consoles

Enfant, j’ai eu la chance d’avoir accès à un ordinateur et à plusieurs consoles de jeux qui m’ont laissé des souvenirs impérissables. Aujourd’hui, l’engouement pour le retrogaming est bien réel, d’ailleurs, un musée du jeu vidéo vient d’ouvrir ses portes à Arcueil.

Ça m’a donné envie de rebrancher mes anciennes consoles. Ne disposant plus d’écran compatible, je me suis tourné vers les émulateurs logiciels, mais le rendu visuel s’est révélé assez décevant. J’ai donc investi dans un convertisseur Péritel vers HDMI, pensant améliorer l’image, mais j’ai rapidement compris que le problème ne venait ni de l’émulateur, ni du convertisseur, mais de l’écran lui-même.

L’interface homme-machine au coeur de l’expérience retro

Les jeux vidéo des années 80 et 90 étaient conçus pour les écrans cathodiques (CRT), dont les spécificités technologiques faisaient partie intégrante du rendu visuel. Ces écrans ne montraient pas les pixels de manière aussi nette que les écrans modernes, l’image résultait d’un balayage électronique qui allumait des phosphores, ce qui lui conférait un rendu particulier avec un léger flou, des lignes de balayage visibles, des interpolations optiques où les couleurs semblaient se fondre naturellement.

Source: depts.washington.edu

Les traits bruts des graphismes étaient adoucis par la technologie cathodique elle-même, ce qui donnait à ces jeux leur aspect si caractéristique, impossible à reproduire fidèlement sur un écran LCD moderne.

Lorsqu’on passe d’un moniteur CRT à un écran LCD, chaque pixel d’origine devient un carré parfaitement net. Le résultat est que l’aliasing, au lieu d’être atténué comme sur les écrans cathodiques, se trouve au contraire accentué.

L’aliasing se produit lorsque deux signaux interfèrent entre eux, générant ainsi du bruit visuel ou des effets d’escaliers sur les contours. Pour corriger ce phénomène, différentes techniques d’anti-aliasing ont été développées. L’une des plus connues est le MSAA (Multi-Sampling Anti-Aliasing). Cet algorithme détecte les arêtes des polygones dans une scène 3D, les épaissit légèrement, puis applique un lissage entre les pixels adjacents appartenant à des polygones différents pour obtenir un rendu plus naturel.

Source: Documentation Vulkan

Il n’existe pas un seul algorithme pour corriger ces effets de bord, plusieurs approches ont été développées, chacune reposant sur des principes différents, comme l’augmentation de la résolution, l’analyse des contours ou encore l’utilisation de techniques d’intelligence artificielle. Parmi les plus connues, on trouve :

  • SSAA (Super Sampling Anti-Aliasing) qui augmente temporairement la résolution du rendu pour lisser les bords.
  • CSAA (Coverage Sampling Anti-Aliasing) qui optimise le calcul du SSAA en échantillonnant plus efficacement les zones.
  • MLAA (Morphological Anti-Aliasing) qui détecte les contours dans l’image finale pour les lisser en post-traitement.
  • DLSS (Deep Learning Super Sampling) qui utilise des réseaux de neurones pour reconstruire une image haute résolution à partir d’un rendu de plus basse définition.

Je me suis donc dit qu’il fallait que je me concentre sur la manière dont les pixels étaient affichés pour revivre les sensations authentiques d’un Silent Hill.

lI existe des solutions matérielles dédiées à l’upscaling des consoles rétro capables de reproduire fidèlement le rendu des écrans d’époque. Ces appareils comme le RetroTINK, le MiSTer FPGA, l’OSSC (Open Source Scan Converter) ne se contentent pas de convertir le signal analogique vers une sortie HDMI, ils proposent également des filtres et shaders avancés qui simulent les caractéristiques visuelles des écrans cathodiques en retravaillant le signal ou offrent la possibilité de faire de l’émulation matérielle.

Analog réalise de très belles rééditions de consoles de ce type:

Les filters et les shaders servent tous deux à créer des effets visuels, mais ils n’agissent pas au même niveau. Les filters ne nécessitent pas de gérer directement le code GPU contrairement aux shaders.

Bref, ceci étant dit, je me suis pris une petite douche froide quand j’ai vu les prix…

Le boitier peut paraitre obscur, mais dedans c’est un FPGA (Field Programmable Gate Array).

What is an FPGA?

Field Programmable Gate Arrays (FPGAs) are integrated circuits often sold off-the-shelf. They’re referred to as ‘field programmable’ because they provide customers the ability to reconfigure the hardware to meet specific use case requirements after the manufacturing process. This allows for feature upgrades and bug fixes to be performed in situ, which is especially useful for remote deployments.

FPGAs contain configurable logic blocks (CLBs) and a set of programmable interconnects that allow the designer to connect blocks and configure them to perform everything from simple logic gates to complex functions. Full SoC designs containing multiple processes can be put onto a single FPGA device.

Source: https://www.arm.com/glossary/fpga

Dans ces boitiers il y a des connecteurs d’entrées et de sorties. Le signal entrant est d’abord numérisé par un convertisseur analogique-numérique intégré à la carte. Le FPGA capture chaque ligne de balayage (le fameux 240p, 480i), en analysant les signaux de synchronisation, couleur, luminance… À partir de ces données, chaque pixel est reconstruit numériquement à partir du signal original pour obtenir une trame numérique propre du flux vidéo (plus précisément une matrice) . Puis on travaille la trame avec une pipeline de traitement temps réel sur laquelle on peut faire de l’upscaling (c’est de l’interpolation bilinéaire pour faire du x2, x3 et jouer sur la résolution de l’image), ajouter des shaders, effectuer des corrections…

Ce qui est incroyable avec une FPGA, c’est que tout est fait en parallèle via des milliers de circuits logiques, ce qui explique la latence quasi nulle du rendu. Je voulais me prendre une carte FPGA PYNQ mais ça restait cher et je devais me replonger dans du VHDL (de mauvais souvenirs de la fac), c’était la garantit de plonger dans un rabbit hole. Je me garde ce projet pour un peu plus tard.

Un bon talk d’introduction aux FPGA:

Sans aller aussi loin j’ai cherché si il existait des moyens d’appliquer des shaders en dehors des applications comme RetroArch via une émulation logicielle

C’est là que je suis tombé sur ShaderGlass , exactement ce que je cherchais.

Redonner vie à ses anciennes consoles grâce au modding

La Wii c’est littéralement la meilleure console nintendo du moment avec pas moins de 40,23 millions d’unités vendues en Europe, on la trouve d’occasion à vraiment pas cher. Je me suis donc offert une Wii d’occasion, elle ne coûte presque rien et dispose d’une ludothèque immense. Comme elle partage la même architecture matérielle que la GameCube, elle permet de profiter aussi bien des jeux Wii que des jeux GameCube, et même des jeux GameBoy.

Évidemmnent, je télécharge uniquement les ROMs des jeux que je possède déjà.

Il existe de nombreux guides pour le modding de sa Wii dont:

La solution que j’ai trouvé pour recréer l’expérience de jeu

Je ne voulais pas utiliser une émulation logicielle, qui impose de reconfigurer les manettes, fait perdre les vibrations et l’interface d’origine avec des manettes différentes, et puis ça demande pas mal de réglages, j’ai trouvé une solution simple et efficace qui me permet de préserver l’expérience authentique de la console.
ShaderGlass me permet d’obtenir une qualité visuelle sur ma Wii, sans le besoin d’un upscaleur FPGA onéreux. Il me fallait donc trouver un moyen pour lier les deux avec une méthodde réutilisable pour d’autres consoles comme la PlayStation 1 ou la Nintendo 64, à condition de faire un peu de modding.

Voici comment je procède :

  1. Je récupère le signal vidéo de la Wii que je connecte à un adaptateur Péritel vers HDMI.
  2. Ce signal HDMI est ensuite envoyé vers l’Elgato Neo Capture, qui le transmet via USB à mon PC.
  3. Sur le PC, j’utilise le logiciel ShaderGlass pour appliquer des shaders sur la fenêtre d’Elgato, que je mets ensuite en plein écran.

J’arrive à obtenir une bonne qualité d’image, sans latence. Pas besoin de Switch 2 et des systèmes de réédition coûteux pour rejouer à la Gamecube.


Les limites

La principale limite que je rencontre avec ShaderGlass est son exécution exclusive sous Windows. J’aurais aimé pouvoir réutiliser ma solution sous Linux, j’ai eu envie d’analyser un peu plus en détail le fonctionnement de ShaderGlass et voir comment il me serait possible de le porter sur d’autres plateformes.

Le code prend en charge plusieurs langages de shaders : GLSL, SPIR-V et HLSL (gérés dans le répertoire ShaderGC/). Ces shaders sont ensuite compilés puis appliqués via DirectX 11.

À savoir que les shaders qui s’executent via le GPU sont écrits dans différents langages selon l’API graphique :

  • VulkanSPIR-V (format binaire standardisé)
  • OpenGL / OpenGL ESGLSL
  • DirectXHLSL
  • Metal (Apple)MSL

Mais chaque écosystème a ses différences de syntaxe et de sémantique. L’usage de https://github.com/KhronosGroup/SPIRV-Cross permet dans le projet de faire tourner le même shader sur plusieurs systèmes.

En dépilant le code, je me suis aperçu que chaque fonctionnalité du logiciel était fortement couplée aux composants windows (capture, interface, configuration)

Voir le fichier framework.h

#include "targetver.h"
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#define OEMRESOURCE
// Windows Header Files
#include <windows.h>
#include <shellapi.h>
#include <commdlg.h>

(https://learn.microsoft.com/en-us/windows/win32/learnwin32/creating-a-window)

Migrer vers Linux ne serait donc pas une simple adaptation de code, mais une refonte complète de l’infrastructure :

  • réécrire la capture video des fenêtres,
  • refactoriser toute l’interface avec QT,
  • repenser la gestion des préférences, menus et raccourcis,
  • et découpler les modules du système Windows.

Ça ne sera donc pas pour aujourd’hui…

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *