Hello Sebiohazard,
C'est une vaste question mais je peux te donner quelques pistes.
Pour mon information, tu cherches à émuler quelle machine ?
Pour construire un émulateur, il faut identifier au préalable les composants "actifs" qui composent l'ordinateur/ou la console, étudier comment ils communiquent avec le processeur, qui reste le chef d'orchestre de l'ensemble et comprendre les fonctions qu'ils accomplissent. Il y a donc un gros travail de documentation à faire au préalable : il te faut récupérer toutes les documentations existantes/datasheets/Schémas électroniques pour comprendre comment de petit monde s'interconnecte pour former un tout cohérent.
Si tu as suivi le fil du post, tu auras remarqué que j'ai traité l'émulation par petits bouts indépendants, composant par composant, que j'ai testé un par un et que j'ai fait fonctionner qu'une fois l'ensemble codé. Cela se traduit dans mon code source en C par autant de fichiers *.cpp que j'ai de composants : Z80.cpp, GateArray.cpp, PPI.cpp, CRTC.cpp ... Les différentes fonctions sont appelées dans une boucle principale de 16 Mhz située dans le Gate-Array.
Si on part sur le CPU, c'est pas si difficile que cela à émuler : c'est juste fastidieux. Il te faudra bien sur avoir une bonne documentation sur le CPU que tu souhaites émuler. Dans mon cas, Z80 est un processeur très bien documenté maintenant qui n'a quasiment plus de secret.
En fait, un processeur ne fait pas grand chose en soi. il va se "contenter" de lire une adresse mémoire pour décoder et traiter une instruction. Une fois cela fait, il incrémente un compteur interne (le PC ou Program Counter) pour lire et traiter l’instruction suivante..
En terme de programmation, il te faudra donc créer autant de variables qu'il y a des registres internes dans le processeur puis affecter à ces variables des valeurs adéquates en fonction de l'instructions à traiter (lire une donnée, écrire une donnée, faire une addition, faire un test conditionnel...).
La phase de décodage va permettre de sélectionner la fonction qui sera exécutée en interne par le CPU. Ce n'est pas si compliqué puisque c'est câblé en dur dans le processeur : par exemple sur un Z80, l'instruction 0x41 va copier le contenu du registre C dans le registre B.
En langage C, tu va ainsi copier le contenu de la variable Reg_C dans Reg_B. Tout simplement....
En pratique, quelques exemples à partir de mon code source :
1. Création des variables internes correspondants aux différents registres du Z80 (A, B, C, F, H, L...)
2. Création d'un tableau de décodage des opcodes (contenant le nom de l'instruction, sa longueur en octet, son timings et M et Tstates
3. Traitement des instructions (ici 0x40 => 0x47 )
J'espère que ces quelques explications te donneront quelques pistes.
La partie la plus délicate à traiter dans un émulateur concerne la partie communication des instructions I/O aux autres composants et la gestion de la synchronisation entre les différentes composants...mais c'est un autre sujet.