Archives de catégorie : Emulation

Hacking Game & Watch

Si vous êtes comme moi né dans les années 80, vous avez certainement connu les fameuses « Game & Watch » de Nintendo, ces petits jeux portables avec écran à cristaux liquides. Souvent simplistes et énervants, ils sont devenus à travers le temps très rares et une source de nostalgie de notre jeunesse.

Nintendo, devenus champion dans le domaine de réchauffer les restes pour notre plus grand bonheur, a ressorti en 2020 une Game&Watch Super Mario Bros, qui fut ensuite suivie d’une Game&Watch Zelda. La Game&Watch Mario est livrée relativement pauvrement avec Super Mario Bros et Super Mario Bros 2 : The Lost Levels ainsi qu’un jeu pur Game&Watch. La version Zelda est pour sa part un peu mieux pourvue avec Zelda et Zelda 2 sur NES ainsi que Links Awakening sur GameBoy (dans sa version d’origine non-DX, ce qui est un choix discutable).

Il ne fallu que peu de temps à certains hackers pour réussir à déplomber la machine et y injecter du code externe pour permettre de remplacer totalement le contenu de la flashrom et jouer à d’autres jeux que ceux prévus initialement. Le custom firmware injecté contient un émulateur (attention, pas celui employé par Nintendo) qui permet de faire tourner la plupart des consoles 8-Bit de l’époque, le STM32 embarqué dans ces Game&Watch ayant la puissance suffisante pour le faire.

Cet article, basé sur un guide existant plutôt sommaire, va détailler proprement comment réaliser chacune des étapes pour vous permettre de réaliser la même opération. Il s’adresse à un public averti qui maitrise les principes de base de Linux et qui est habitué à l’utilisation d’un Raspberry Pi mais qui est assez flegmard pour juste vouloir faire des copier/coller de commandes Linux pour arriver au résultat attendu 🙂

Prérequis:

  1. Une Game&Watch Super Mario Bros ou The Legend of Zelda
  2. Un Raspberry Pi avec ports GPIO
  3. Trois câbles Dupont (M-F)

Etape 1 : Préparation initiale du Raspberry Pi

  1. Téléchargez et installez sur votre SD la dernière version de Raspbian Lite.
  2. Configurez votre connéxion réseau (LAN ou WiFi)
  3. Activez le SSH (si vous souhaitez faire la suite des opérations depuis une autre machine)

Etape 2 : Script de préparation « All-in-one »

Toujours dans l’objectif d’atteindre l’objectif fixé en un minimum d’effort (qu’on se le dise, la flegmardise stimule la créativité), un utilisateur répondant au nickname de Kalle000 a créé un script va automatiser une grande partie des tâches du guide de base, en commençant par mettre votre système à jour puis en installant toutes les dépendances nécessaires au flash de votre Game&Watch.

On le télécharge :

wget https://raw.githubusercontent.com/Kalle000/game-and-watch/main/gw-rpi-install-script.sh

On le rend exécutable :

chmod a+x gw-rpi-install-script.sh

Et on se lance :

./gw-rpi-install-script.sh

La fin d’installation doit normalement se finir par l’erreur suivante :

Ce script n’est actuellement pas en mesure de supporter la dernière version des outils qui permettent de flasher autant la version Mario que la version Zelda.

A ce stade, nous avons donc presque tout le nécessaire pour aller de l’avant.

Etape 3 : Finalisation du setup

Nous allons customiser un tantinet notre setup afin d’ajouter des fonctionnalités manquantes à l’émulateur Retro-Go, l’émulateur employé dans ce hack. Il est en effet possible de lui faire afficher des vignettes de jeu, ce qui rend l’expérience utilisateur bien plus agréable et propre que d’afficher uniquement des listes des ROMs.

Pour ce faire:

sudo apt-get install libopenjp2-7
sudo apt-get install python3-pippython -m pip install -r requirements.txt
cd opt
cd game-and-watch-retro-go
git remote add olderzeus https://github.com/olderzeus/game-and-watch-retro-go.git
git fetch olderzeus
git checkout NewUI
git submodule update
make clean
git pull
chmod a+x scripts/*.sh

Etape 4 : Transfert des ROMs

Ne vous reste ainsi plus qu’à transférer vos ROMs dans le répertoire de la console émulée correspondante dans le répertoire opt/game-and-watch-retro-go/roms dans son format natif (non zippé, soit .nes pour la NES, .gb pour GameBoy, etc.).

Pour ma part, afin de le faire simplement via FTP, j’ai installé le serveur ProFTPd :

sudo apt install proftpd

Puis transféré les ROMs (vous pouvez également ajouter des PNG à cet instant pour enrichir l’interface finale) :

Pour ma part, j’ai sélectionné les jeux suivants qui passent dans les FlashROM de base (1MB pour Mario et 4MB pour Zelda) :

  • Game&Watch Super Mario Bros
    • GameBoy
      • Super Mario Land (World)
      • Super Mario Land 2 – 6 Golden Coins (USA, Europe)
    • NES
      • Mario Bros. Classic (Europe)
      • Super Mario Bros. (World)
      • Super Mario Bros. 2 (Europe)
      • Super Mario Bros. 3 (Europe)

  • Game&Watch Legend of Zelda
    • GameBoy
      • Legend of Zelda, The – Link’s Awakening (France)
    • NES
      • Legend of Zelda, The (Trad FR)
      • Zelda II – The Adventure of Link (Trad FR)

Etape 5 : Préparation matérielle de la Game&Watch

La Game&Watch dispose bien d’un port USB-C mais ce dernier ne sert qu’à recharger la batterie. Par défaut, aucune data ne transite malheureusement par son biais. Par chance, Nintendo a laissé sur le PCB des ports de debug qui vont nous permettre de réaliser certaines tâches pour mener à bien notre mission.

Commencez donc par ouvrir votre Game&Watch en dévissant les 4 vis triangulaires à l’arrière. Si vous n’avez pas de tournevis adapté, un petit torx peut faire l’affaire. Je vous recommande de ne pas forcer car ces petites vis s’abiment vite et elles deviendront rapidement difficile à utiliser dans le futur. Attention à ne pas perdre le bouton Power qui se ballade facilement.

Une fois ouvert, il vous faudra déconnecter la batterie en soulevant le connecteur avec précaution car nous alimenterons la Game&Watch par l’USB dans les étapes à venir.

Etape 6 : Connection du Raspberry Pi à la Game&Watch

L’opération physique suivante est très importante car le succès de l’opération en dépend. En effet, une mauvaise connection entre les deux équipements peut entrainer un flash présumément réussi de votre Game&Watch mais avec des donnes corrompues, une interruption de la procédure de flash ou même le refus total de flasher l’appareil.

Pour les besoins de ce guide, je vais détailler la façon de procéder pour la Game&Watch Mario mais la version Zelda est très similaire. Hormis un pin-out légèrement différent qui sera précisé, les opérations sont identiques.

Raspberry Pi GPIO

Commencez par connecter un câble Dupont à chaque Pin suivant de votre Raspberry Pi :

  • GPIO24 (Pin 18)
  • GPIO25 (Pin 22)
  • GROUND (Pin 39)

Et connectez les de la sorte sur votre Game&Watch :

  • GPIO24 vers SWDIO
  • GPIO25 vers SWCLK
  • GND vers GND

Pour Mario :

Pour Zelda :

Pour ressembler au final à quelque chose du genre (ghetto style, si vous avez des connecteurs type pinces croco, c’est beaucoup mieux) :

Etape 6 : Vérification du setup

Un script va nous permettre (soi-disant) de vérifier que tout fonctionne bien :

cd /home/pi/opt/game-and-watch-backup

./1_sanity_check.sh rpi mario

Ce script devrait vous retourner ceci :

Etape 7 : Backup de la FlashROM externe

Passé cette étape, nous allons ensuite faire une copie de votre FlashROM afin de pouvoir la restorer en cas de besoin.

./2_backup_flash.sh

Etape 8 : Backup de la FlashROM interne

Ensuite, une fois votre FlashROM d’origine sauvegardée, le script suivant va backuper la FlashROM interne de votre Game&Watch.

./3_backup_internal_flash.sh

Gardez bien les 3 fichiers générés à cette étape à la précédente de côté afin de pouvoir les restorer en cas de problèmes.

Etape 9 : Unlock de la Game&Watch

L’étape finale avant de flasher à proprement parlé votre Game&Watch sera de débloquer le STM32 de votre Game&Watch. Ce dernier va modifier l’état « pas de lecture externe » de votre STM32 pour permettre d’exécuter le payload fraichement injecté.

./4_unlock_device.sh

Si tout s’est bien déroulé, l’écran de votre Game&Watch devrait être d’un bleu resplendissant.

Etape 10 : Compilation de Retro-Go et flash

Nous allons désormais procéder à l’étape finale qui sera de compiler et flasher l’émulateur Retro-Go

cd ..

cd cd game-and-watch-retro-go/

make GCC_PATH=/home/pi/opt/xpack-arm-none-eabi-gcc-10.2.1-1.1/bin/ flash_all

Si vous disposez d’une FlashROM moddée (de 16, 32 ou 64MB), utilisez les commandes suivantes :

make GCC_PATH=/home/pi/opt/xpack-arm-none-eabi-gcc-10.2.1-1.1/bin/ COVERFLOW=1 COMPRESS=lzma EXTFLASH_SIZE_MB=16 flash_all

make GCC_PATH=/home/pi/opt/xpack-arm-none-eabi-gcc-10.2.1-1.1/bin/ COVERFLOW=1 COMPRESS=lzma EXTFLASH_SIZE_MB=32 flash_all

make GCC_PATH=/home/pi/opt/xpack-arm-none-eabi-gcc-10.2.1-1.1/bin/ COVERFLOW=1 COMPRESS=lzma EXTFLASH_SIZE_MB=64 flash_all

En cas de problème

En cas de problème de flash, sachez que vous pourrez toujours revenir en arrière en invoquant le script de restore de votre FlashROM.

./5_restore.sh

Si pour une raison ou une autre les scripts vous retournent des erreurs lors du flashage, c’est que la connéxion entre votre Raspberry Pi et Game&Watch n’est pas bonne. Vérifiez là et refaites des tentatives. J’ai du m’y reprendre à plusieurs reprises avant d’arriver un flash parfait.

Conclusion

Si tout a fonctionné comme il se doit, vous devriez être recompensé par le message suivant :

Et surtout :

RetroPie x86

Cela fait un moment que je n’ai pas écrit sur ce blog et je me suis dit qu’un dimanche pluvieux comme aujorud’hui serait un jour idéal pour ça.

J’ai un NUC peu puissant qui traine dans un coin acheté à bas pris sur Ricardo.ch que j’utilise pour faire des tests et me suis dit que j’allais une fois essayer d’installer RetroPie sur un processeur x86 pour comparer la qualité de l’émulation et la vitesse par rapport à un Raspberry.

En cherchant, je suis tombé sur un article très bien fait qui récapitule toutes les étapes pour le faire de manière simple et rapide. Il comprend cependant des typo dans les commandes à passer qui sont pour moi génantes si quelqu’un d’inexpérimenté veut le refaire. Le bug de cet article est donc de reprendre ce qui a été, de corriger ces quelques typos et l’expliquer en français.

Edit : après avoir rédigé cet article, je me suis rendu compte que quelqu’un avait encore plus facilité le processus, rendant caduque le reste de l’article, grâce à ce script que je vous recommande fortemment.

La première étape est donc de télécharger un ISO de Ubuntu 18.04 LTS version serveur et d’imager une clé USB avec (par exemple avec Balena Etcher). Pourquoi la version serveur ? Simplement parce qu’elle est dénuée d’interface graphique que nous n’utiliserons pas, ce qui la rend plus light et ne consommera pas de l’espace de stockage inutilement.

Pour l’installation d’Ubuntu, je vous recommande de laisser toutes les options par défaut : utiliser le disque complet, pas de LVM, pas d’encrpytion, DHCP pour l’Ethernet et cliquer sur installer.

Ensuite, pour la création d’un user de base, entrez les mêmes identifiants que vous utiliseriez sur un Pi, pas besoin de complexifier quelque chose qui ne le nécessite pas (après, c’est vous qui voyez…).

  • User: Retro Pie
  • Server Name: retropie
  • Username: Pi
  • Password: raspberry

J’ai également configuré l’OS pour activer SSH afin de pouvoir facilement effectuer les opérations suivantes depuis ma machine principes.

Après quelques minutes se termine l’installation et vous pouvez retirer la clé USB.

Il est recommandé d’utiliser le noyeau HWE pour RetroPie car les kernels plus récents disposent de fonctionnalités que RetroPie n’utilise pas. Rappelez-vous : light is right. Pour le faire, commencez avec ceci :

sudo apt update
sudo apt upgrade
sudo apt install --install-recommends linux-generic-hwe-18.04

Puis redémarrez votre NUC. Une fois redémarré, on va entrer dans le vif du sujet avec RetroPie. Connectez-vous donc à votre NUC en SSH.

On va d’abord faire en sorte que l’utilisateur « pi » soit en mesure de lancer des commandes en tant que root (sudo) sans pasword (ça ira beaucoup plus vite pour la suite):

sudo sed -i -e '$a\pi ALL=(ALL) NOPASSWD:ALL' /etc/sudoers

Rentrez le password configuré et nous serons bons, vous n’aurez plus à rentrer de manière systématique ce password.

Ensuite, nous allons ajouter le repository universe avec toutes les dépendances nécessaires à RetroPie :

sudo apt-add-repository universe
sudo apt update -y
sudo apt upgrade -y 
sudo apt install xorg openbox pulseaudio alsa-utils menu libglib2.0-bin python-xdg at-spi2-core dbus-x11 git dialog unzip xmlstarlet --no-install-recommends -y

On va ensuite créer un script d’autodémarrage OpenBox afin de démarrer le terminal puis démarrer EmulationStation :

mkdir -p ~/.config/openbox
echo 'gnome-terminal --full-screen --hide-menubar -- emulationstation' >> ~/.config/openbox/autostart

Puis un fichier .xsession adapté

echo 'exec openbox-session' >> ~/.xsession

On fait en suite que X11 démarre au boot :

echo 'if [[ -z $DISPLAY ]] && [[ $(tty) = /dev/tty1 ]]; then' >> ~/.bash_profile
sed -i '$ a\startx -- -nocursor >/dev/null 2>&1' ~/.bash_profile 
sed -i '$ a\fi' ~/.bash_profile

On souhaite ensuite que l’utilisateur pi se logue automatiquement et que EmulationStation devienne l’écran principale affiché :

sudo mkdir /etc/systemd/system/getty@tty1.service.d
sudo sh -c 'echo [Service] >> /etc/systemd/system/getty@tty1.service.d/override.conf' 
sudo sed -i '$ a\ExecStart=' /etc/systemd/system/getty@tty1.service.d/override.conf
sudo sed -i '$ a\ExecStart=-/sbin/agetty --skip-login --noissue --autologin pi %I $TERM' /etc/systemd/system/getty@tty1.service.d/override.conf
sudo sed -i '$ a\Type=idle' /etc/systemd/system/getty@tty1.service.d/override.conf

Après ça, nous sommes désormais prêts pour démarrer le téléchargement de RetroPie depuis le repository Git et lancer le script d’isntallation :

git clone --depth=1 https://github.com/RetroPie/RetroPie-Setup.git
sudo RetroPie-Setup/retropie_setup.sh

Ceci va lancer l’installation de RetroPie. Acceptez l’EULA et choisissez l’installation « Basic ». Selectionnez « Yes » pour installer tous les packages de Core et Main. C’est désormais le moment où vous pouvez aller faire autre chose, le processus de compilation va prendre du temps.

Une fois la compilation terminée, vous pouvez redémmarer votre NUC depuis le menu.

L’article original contient ensuite des instructions de customisation pour l’utilisation d’une manette Xbox One. N’en ayant pas une, je passerai au dessus de ces explications. Si cela vous intéresse, je vous recommande de vous référer à l’article original.

L’étape suivante sera de rendre les choses un peu plus jolies et cacher toutes ces vilains logs au boot qui démontrent trop qu’il s’agit d’un bête Linux. On va donc cacher tout ça avec Plymouth avec le theme par défaut de Pacman :

sudo apt update
sudo apt install plymouth plymouth-themes plymouth-x11 -y
git clone --depth=1 https://github.com/HerbFargus/plymouth-themes.git tempthemes
sudo cp -r ~/tempthemes/. /usr/share/plymouth/themes/
rm -rf tempthemes
sudo update-alternatives --install /usr/share/plymouth/themes/default.plymouth default.plymouth /usr/share/plymouth/themes/retropie-pacman/retropie-pacman.plymouth 10
sudo update-alternatives --set default.plymouth /usr/share/plymouth/themes/retropie-pacman/retropie-pacman.plymouth
sudo update-initramfs -u
sudo cp /etc/default/grub /etc/default/grub.backup
sudo sed -i -e 's/GRUB_TIMEOUT=10/GRUB_TIMEOUT=2/g' /etc/default/grub
sudo sed -i -e 's/GRUB_CMDLINE_LINUX=""/GRUB_CMDLINE_LINUX="quiet splash"/g' /etc/default/grub
sudo update-grub

Puis on cache les infos de last login :

sudo sed -i -e 's/session optional pam_lastlog.so/#session  optional pam_lastlog.so/g' /etc/pam.d/login
sudo sed -i -e 's/session optional pam_motd.so motd=\/run\/motd.dynamic/#session optional pam_motd.so motd=\/run\/motd.dynamic/g' /etc/pam.d/login
sudo sed -i -e 's/session optional pam_motd.so noupdate/#session optional pam_motd.so noupdate/g' /etc/pam.d/login
sudo sed -i -e 's/session optional pam_mail.so standard/#session optional pam_mail.so standard/g' /etc/pam.d/login

On cache le terminal :

sed -i '1 i\dbus-launch gsettings set org.gnome.Terminal.Legacy.Profile:/org/gnome/terminal/legacy/profiles:/:b1dcc9dd-5262-4d8d-a863-c897e6d979b9/ use-theme-colors false' ~/.bash_profile 
sed -i '1 i\dbus-launch gsettings set org.gnome.Terminal.Legacy.Profile:/org/gnome/terminal/legacy/profiles:/:b1dcc9dd-5262-4d8d-a863-c897e6d979b9/ use-theme-transparency false' ~/.bash_profile 
sed -i '1 i\dbus-launch gsettings set org.gnome.Terminal.Legacy.Profile:/org/gnome/terminal/legacy/profiles:/:b1dcc9dd-5262-4d8d-a863-c897e6d979b9/ default-show-menubar false' ~/.bash_profile 
sed -i "1 i\dbus-launch gsettings set org.gnome.Terminal.Legacy.Profile:/org/gnome/terminal/legacy/profiles:/:b1dcc9dd-5262-4d8d-a863-c897e6d979b9/ foreground-color '#FFFFFF'" ~/.bash_profile 
sed -i "1 i\dbus-launch gsettings set org.gnome.Terminal.Legacy.Profile:/org/gnome/terminal/legacy/profiles:/:b1dcc9dd-5262-4d8d-a863-c897e6d979b9/ background-color '#000000'" ~/.bash_profile 
sed -i "1 i\dbus-launch gsettings set org.gnome.Terminal.Legacy.Profile:/org/gnome/terminal/legacy/profiles:/:b1dcc9dd-5262-4d8d-a863-c897e6d979b9/ cursor-blink-mode 'off'" ~/.bash_profile 
sed -i "1 i\dbus-launch gsettings set org.gnome.Terminal.Legacy.Profile:/org/gnome/terminal/legacy/profiles:/:b1dcc9dd-5262-4d8d-a863-c897e6d979b9/ scrollbar-policy 'never'" ~/.bash_profile 
sed -i '1 i\dbus-launch gsettings set org.gnome.Terminal.Legacy.Profile:/org/gnome/terminal/legacy/profiles:/:b1dcc9dd-5262-4d8d-a863-c897e6d979b9/ audible-bell false' ~/.bash_profile 
cp /etc/xdg/openbox/rc.xml ~/.config/openbox/rc.xml 
cp ~/.config/openbox/rc.xml ~/.config/openbox/rc.xmlbackup 
sed -i '//a ' ~/.config/openbox/rc.xml 
sed -i '//a true ' ~/.config/openbox/rc.xml 
sed -i '//a no ' ~/.config/openbox/rc.xml 
sed -i '//a below ' ~/.config/openbox/rc.xml 
sed -i '//a no ' ~/.config/openbox/rc.xml 
sed -i '//a yes ' ~/.config/openbox/rc.xml 
sed -i '//a ' ~/.config/openbox/rc.xml

Vous comprenez maintenant pourquoi il est recommandé d’utiliser SSH ? 🙂

Et pour finir, on va retirer cloud-init, qui ne nous sert à rien :

sudo apt purge cloud-init -y
sudo rm -rf /etc/cloud/
sudo rm -rf /var/lib/cloud/

Voilà, vous devriez désormais être opérationnels ! Il se peut qu’il faille tweaker un peu certains paramètres graphiques pour obtenir de meilleures performances. Il s’avère que jouer en 4k va rendre l’expérience très mauvaise et il vous est suggéré de rester en 1080p.

Amusez-vous bien !

Cheshire Cat Case

Cheshire Cat Case

Etant fan d’Alice au Pay des Merveille, ce boitier me faisait de l’oeil depuis un moment et plaisait également à ma compagne. J’étais rétissent au début pour le côté portable du boitier et du fait qu’il faille faire de la soudure sur un PCB dédié pour les LEDs mais finalement tout s’est bien passé et j’ai pu mettre à profit récentes compétences acquises en soudure 🙂

https://www.modmypi.com/raspberry-pi/cases/modmypi-single-colour/modmypi-pi-b-plus2-head-case-cheshire-project-case