Principe de compilation

Le projet nesformer intègre le processeur 6502 de la console NES directement dans les poids d’un modèle Qwen3_5ForCausalLM. Aucun entraînement n’est réalisé ; un compilateur calcule chaque poids à partir du code source du CPU, de ses 2 KB de RAM et du programme ROM d’une cartouche. Le modèle prédit alors, token après token, le journal d’exécution du processeur, tandis qu’un petit programme hôte gère l’affichage, la lecture du contrôleur et l’interruption vblank.

Cette approche s’appuie sur le travail antérieur Qwenputer, qui avait déjà compilé un interpréteur CHIP‑8 puis un CPU RISC‑V dans le même type de modèle. Le même compilateur est réutilisé, ce qui permet de charger n’importe quel jeu au format NROM (mapper 0) sans recompilation des poids.

Architecture mémoire DeltaNet

Le modèle Qwen utilise un état Gated DeltaNet constitué d’une matrice 128 × 128. Chaque ligne représente une cellule mémoire ; l’ouverture du gate et une clé one‑hot permettent d’écrire exactement une ligne, tandis qu’une requête one‑hot lit la même ligne. Ainsi, les registres du CPU, la RAM et le contenu de la cartouche sont stockés dans les rangées de cette matrice, transformant le réseau de neurones en une mémoire adressable par le processeur virtuel.

Le flux d’exécution se déroule comme suit : le modèle reçoit le token actuel, met à jour la matrice selon la règle delta, puis renvoie le token suivant qui correspond à la prochaine instruction ou donnée du 6502. Aucun accès direct aux registres n’est effectué par l’hôte ; il ne voit que le flux de tokens et les images générées.

Performances et limites

Le premier lancement compile le moteur avec numba en environ 20 secondes. Chaque image générée nécessite entre 1 et 6 secondes de calcul, ce qui implique qu’une séquence de 600 frames (10 secondes de jeu) dure approximativement 25 minutes sur du matériel standard. Le projet indique que les sorties d’image et de logique correspondent exactement à celles d’un émulateur 6502 conventionnel, vérifiées via une comparaison cadre à cadre.

Les exigences logicielles comprennent Python 3.11+, les bibliothèques numpy, scipy, numba et pillow. Les poids sont fournis dans un répertoire weights/ compatible Hugging Face et se chargent avec Qwen3_5ForCausalLM.from_pretrained. Les jeux supportés sont limités aux cartouches NROM ; toute autre mapper déclenche un message d’erreur, reflétant une contrainte du modèle de mémoire linéaire.

Utilisation pratique

python -m nesformer run roms/smb.nes --frames 600 --show \
  --buttons "start@60-65,right@200-600,a@250-265+300-315"

Cette commande charge le ROM de Super Mario Bros., démarre le jeu, maintient la direction droite pendant 400 frames et appuie sur le bouton A à deux intervalles pour faire sauter le personnage. Le paramètre --show dessine chaque frame dans le terminal, tandis que le GIF final smb.gif est sauvegardé automatiquement. Le système accepte également les modes check et trace pour comparer les tokens générés à une référence ou afficher les tokens en temps réel.