Je joue rĂ©guliĂšrement Ă  des jeux vidĂ©o sur Ă©mulateur et je comprends dans les grandes lignes le principe de l’émulation mais j’ai envie d’en apprendre plus et de “mettre les mains dedans”. J’aimerais bien savoir Ă©crire un Ă©mulateur de GameBoy, et c’est probablement faisable avec suffisamment de patience, mais j’aime comprendre les choses en partant de la base. C’est pour cette raison que je me suis donnĂ© pour projet de construire un systĂšme Ă©lectronique simple et d’écrire ensuite l’émulateur correspondant. Ainsi je peux commencer en douceur avec les principes fondamentaux de l’émulation, et complexifier progressivement par la suite selon mes envies.

J’ai choisi de me baser sur le processeur 6502 et son interface 6522 et la sĂ©rie de vidĂ©os de Ben Eater qui leur est consacrĂ©e. Le 6502 Ă©tait le CPU utilisĂ© par de nombreux appareils grand public des annĂ©es 1980 notamment l’Apple II, le Commodore 64 et l’Atari 2600. C’est un microprocesseur relativement simple et donc idĂ©al pour dĂ©buter. Des versions modernisĂ©es sont toujours en production aujourd’hui et il existe une large communautĂ© de passionnĂ©s.

Le 6502 est un microprocesseur, et sa fonction principale est donc d’exĂ©cuter des instructions. Contrairement Ă  un microcontrĂŽleur, il n’a aucune mĂ©moire interne et aucun pĂ©riphĂ©rique. Il interragit avec le monde extĂ©rieur via un bus de donnĂ©es et un bus d’addresse, sur lesquels il peut lire et Ă©crire des donnĂ©es. Les instructions Ă  Ă©xĂ©cuter, les donnĂ©es Ă  traiter, et les donnĂ©es produites, tout passe par le bus. En gĂ©nĂ©ral on connecte sur le bus une mĂ©moire qui contient le programme et les donnĂ©es de travail, et des pĂ©riphĂ©rique comme un afficheur, une carte son, etc.

Je commence par installer le 6502 sur une breadboard, je connecte l’alimentation et les signaux de contrĂŽle de base, et j’ajoute un bouton reset. Le signal d’horloge est gĂ©nĂ©rĂ© par un module basĂ© sur un circuit 555 que j’ai construit prĂ©cĂ©demment en suivant les vidĂ©os de Ben Eater sur le sujet. J’utilise mon Arduino comme source d’alimentation et pour faire des observations par la suite.

Pour vĂ©rifier qu’il se passe quelque chose dans le processeur j’ai connectĂ© les 4 bits de poids faible du bus d’adresse sur 4 LEDs, et j’ai constatĂ© une activitĂ©. J’ai Ă©galement connectĂ© les lignes du bus de donnĂ©es directement sur l’alim ou la masse avec des rĂ©sitances pour faire en sorte qu’à chaque fois que le CPU lit une donnĂ©e sur le bus il rĂ©cupĂšre la valeur 0xEA, qui correspond Ă  l’instruction NOP (« No Operation »). Quand on observe les lignes d’adresse, on constate un comptage, qui correspond au fait que le CPU lit les instructions les unes aprĂšs les autres dans la mĂ©moire.

Mon 6502 en fonctionnement

Je connecte les lignes d’adresses Ă  l’Arduino ainsi que le signal d’horloge, et Ă©crit un programme simple pour lire et afficher les donnĂ©es Ă  chaque tic d’horloge via une interruption. Ben Eater utilise un Arduino Mega pour observer les 16 lignes d’adresse et les 8 lignes de donnĂ©es, mais mon Arduino Uno n’a pas assez de pins pour me permettre d’observer toutes les lignes, je suis donc restĂ© sur les 4 bits de poids faible de l’adresse uniquement.

Lorsque le processeur dĂ©marre ou est rĂ©initialisĂ©, il va chercher l’adresse de la premiĂšre instruction Ă  exĂ©cuter. Pour cela il va lire une donnĂ©e de 16 bits aux adresses 0xFFFC et 0xFFFD, puis commence Ă  rĂ©cupĂ©rer les instructions Ă  partir de cette adresse. Comme je n’observe que les 4 derniers bits de l’adresse, je m’attends Ă  voir passer les valeurs C et D, qui correspondent aux valeurs binaires 1100 et 1101 respectivement. Lorsque j’appuie sur le bouton reset, je vois effectivement passer ces adresses. Comme le bus de donnĂ©es est cĂąblĂ© pour renvoyer 0xEA, le CPU va commencer Ă  lire les instructions Ă  partir de l’adresse 0xEAEA. La valeur A en binaire s’écrit 1010, et c’est effectivement la premiĂšre adresse qu’on voit aprĂšs C et D. TrĂšs cool !

Lecture du bus d'adresse en temps réel

Une capture d'Ă©cran du logiciel Arduino oĂč l'on voit une capture de donnĂ©es. La donnĂ©e 1100 est mise en subrillance, la donnĂ©e suivante est 1101, et encore aprĂšs on lit 1010, puis les valeurs s'incrĂ©mentent.

Lecture du bus d'adresse aprĂšs un reset

Le code Arduino est disponible sur GitHub.

La suite

La prochaine Ă©tape est de fournir au CPU des donnĂ©es dynamiques en fonction de l’adresse qu’il demande, de sorte Ă  former un programme qui ait du sens. Classiquement c’est le rĂŽle d’une puce mĂ©moire. Mais on peut aussi utiliser Arduino.