Comment fonctionnent les émulateurs et comment sont-ils écrits? [fermé]

968

Comment fonctionnent les émulateurs? Quand je vois des émulateurs NES / SNES ou C64, cela m'étonne.

http://www.tommowalker.co.uk/snemzelda.png

Devez-vous émuler le processeur de ces machines en interprétant ses instructions de montage particulières? Qu'y a-t-il d'autre? Comment sont-ils généralement conçus?

Pouvez-vous donner des conseils à quelqu'un qui souhaite écrire un émulateur (en particulier un système de jeu)?

mmcdole
la source
15
La chose la plus importante que vous devez trouver est le "manuel du programmeur" pour ce système, car il détaille le "contrat" ​​entre le fournisseur de matériel informatique et les programmeurs, et masque les détails qui ne sont pas pertinents et pourraient changer. Vos chances dépendent de la popularité du système.
Uri
155
Bon choix de jeu.
Cristián Romo
16
Pour tous ceux qui se demandent Emulation vs Simulation
Lazer
8
Depuis la première fois que j'ai joué à ce jeu, je me suis toujours demandé pourquoi Hyrule était jonchée de rochers "8-Ball" :-)
Vivian River

Réponses:

1124

L'émulation est un domaine à multiples facettes. Voici les idées de base et les composants fonctionnels. Je vais le diviser en morceaux, puis remplir les détails via des modifications. Beaucoup de choses que je vais décrire nécessiteront une connaissance du fonctionnement interne des processeurs - la connaissance de l'assemblage est nécessaire. Si je suis un peu trop vague sur certaines choses, veuillez poser des questions afin que je puisse continuer à améliorer cette réponse.

Idée basique:

L'émulation fonctionne en gérant le comportement du processeur et des composants individuels. Vous construisez chaque pièce individuelle du système, puis connectez les pièces comme le font les fils dans le matériel.

Émulation de processeur:

Il existe trois façons de gérer l'émulation du processeur:

  • Interprétation
  • Recompilation dynamique
  • Recompilation statique

Avec tous ces chemins, vous avez le même objectif global: exécuter un morceau de code pour modifier l'état du processeur et interagir avec le «matériel». L'état du processeur est une conglomération des registres du processeur, des gestionnaires d'interruption, etc. pour une cible de processeur donnée. Pour le 6502, vous auriez un certain nombre d'entiers 8 bits représentant des registres: A, X, Y, Pet S; vous auriez également un PCregistre 16 bits .

Avec l'interprétation, vous commencez au IP(pointeur d'instruction - également appelé PC, compteur de programme) et lisez l'instruction dans la mémoire. Votre code analyse cette instruction et utilise ces informations pour modifier l'état du processeur comme spécifié par votre processeur. Le problème central de l'interprétation est qu'elle est très lente; chaque fois que vous manipulez une instruction donnée, vous devez la décoder et effectuer l'opération requise.

Avec la recompilation dynamique, vous parcourez le code un peu comme l'interprétation, mais au lieu d'exécuter simplement des opcodes, vous créez une liste d'opérations. Une fois que vous avez atteint une instruction de branche, vous compilez cette liste d'opérations sur le code machine de votre plate-forme hôte, puis vous mettez en cache ce code compilé et l'exécutez. Ensuite, lorsque vous frappez à nouveau un groupe d'instructions donné, vous n'avez qu'à exécuter le code à partir du cache. (BTW, la plupart des gens ne font pas réellement une liste d'instructions mais les compilent à la machine à la volée - cela le rend plus difficile à optimiser, mais cela sort du cadre de cette réponse, sauf si suffisamment de personnes sont intéressées)

Avec la recompilation statique, vous faites la même chose qu'en recompilation dynamique, mais vous suivez les branches. Vous finissez par construire un morceau de code qui représente tout le code du programme, qui peut ensuite être exécuté sans autre interférence. Ce serait un excellent mécanisme s'il n'y avait pas les problèmes suivants:

  • Le code qui n'est pas dans le programme pour commencer (par exemple compressé, chiffré, généré / modifié au moment de l'exécution, etc.) ne sera pas recompilé, il ne s'exécutera donc pas
  • Il a été prouvé que trouver tout le code dans un binaire donné équivaut au problème d'arrêt

Celles-ci se combinent pour rendre la recompilation statique complètement irréalisable dans 99% des cas. Pour plus d'informations, Michael Steil a fait de grandes recherches sur la recompilation statique - le meilleur que j'ai vu.

L'autre côté de l'émulation de processeur est la manière dont vous interagissez avec le matériel. Cela a vraiment deux côtés:

  • Synchronisation du processeur
  • Interruption de la manipulation

Calendrier du processeur:

Certaines plates-formes - en particulier les consoles plus anciennes comme NES, SNES, etc. - nécessitent que votre émulateur ait un timing strict pour être complètement compatible. Avec le NES, vous avez le PPU (unité de traitement des pixels) qui nécessite que le CPU place des pixels dans sa mémoire à des moments précis. Si vous utilisez l'interprétation, vous pouvez facilement compter les cycles et émuler le bon timing; avec la recompilation dynamique / statique, les choses sont / beaucoup / plus complexes.

Interruption de la manipulation:

Les interruptions sont le principal mécanisme que la CPU communique avec le matériel. Généralement, vos composants matériels indiqueront au CPU les interruptions dont il se soucie. C'est assez simple - lorsque votre code lève une interruption donnée, vous regardez la table du gestionnaire d'interruption et appelez le rappel approprié.

Émulation matérielle:

L'émulation d'un périphérique matériel donné a deux côtés:

  • Émuler la fonctionnalité de l'appareil
  • Émulation des interfaces de périphérique réelles

Prenons le cas d'un disque dur. La fonctionnalité est émulée en créant le stockage de sauvegarde, les routines de lecture / écriture / formatage, etc. Cette partie est généralement très simple.

L'interface réelle de l'appareil est un peu plus complexe. Il s'agit généralement d'une combinaison de registres mappés en mémoire (par exemple, des parties de la mémoire que le périphérique surveille pour les modifications à effectuer pour la signalisation) et des interruptions. Pour un disque dur, vous pouvez avoir une zone mappée en mémoire où vous placez des commandes de lecture, des écritures, etc., puis relisez ces données.

J'irais plus en détail, mais il y a un million de façons de procéder. Si vous avez des questions spécifiques ici, n'hésitez pas à me les poser et j'ajouterai les informations.

Ressources:

Je pense que j'ai donné une assez bonne introduction ici, mais il y a une tonne de domaines supplémentaires. Je suis plus qu'heureux de répondre à toutes vos questions; J'ai été très vague dans la plupart de cela simplement en raison de l'immense complexité.

Liens Wikipédia obligatoires:

Ressources d'émulation générales:

  • Zophar - C'est là que j'ai commencé mon émulation, en téléchargeant d'abord des émulateurs et en pillant finalement leurs immenses archives de documentation. C'est la meilleure ressource absolue que vous puissiez avoir.
  • NGEmu - Pas beaucoup de ressources directes, mais leurs forums sont imbattables.
  • RomHacking.net - La section des documents contient des ressources concernant l'architecture de la machine pour les consoles populaires

Projets d'émulation à référencer:

  • IronBabel - Il s'agit d'une plate-forme d'émulation pour .NET, écrite en Nemerle et recompile le code en C # à la volée. Avertissement: Ceci est mon projet, alors pardonnez la fiche sans vergogne.
  • BSnes - Un émulateur SNES génial dans le but d'une précision parfaite du cycle.
  • MAME - L' émulateur d'arcade. Grande référence.
  • 6502asm.com - Il s'agit d'un émulateur JavaScript 6502 avec un petit forum sympa.
  • dynarec'd 6502asm - C'est un petit hack que j'ai fait pendant un jour ou deux. J'ai pris l'émulateur existant de 6502asm.com et l'ai changé pour recompiler dynamiquement le code en JavaScript pour des augmentations de vitesse massives.

Références de recompilation du processeur:

  • La recherche sur la recompilation statique effectuée par Michael Steil (référencé ci-dessus) a abouti à cet article et vous pouvez trouver la source et autres ici .

Addenda:

Cela fait bien plus d'un an que cette réponse a été soumise et avec toute l'attention qu'elle suscite, j'ai pensé qu'il était temps de mettre à jour certaines choses.

La chose la plus excitante dans l'émulation en ce moment est peut-être libcpu , démarré par Michael Steil susmentionné. Il s'agit d'une bibliothèque destinée à prendre en charge un grand nombre de cœurs de processeur, qui utilisent LLVM pour la recompilation (statique et dynamique!). Son potentiel est énorme et je pense que cela fera de grandes choses pour l'émulation.

emu-docs a également été porté à mon attention, qui abrite un grand référentiel de documentation système, qui est très utile à des fins d'émulation. Je n'y ai pas passé beaucoup de temps, mais on dirait qu'ils ont beaucoup de bonnes ressources.

Je suis content que ce post ait été utile, et j'espère que je pourrai me défouler et terminer mon livre sur le sujet d'ici la fin de l'année / au début de l'année prochaine.

Cody Brocious
la source
37
Cela se prépare déjà à être une réponse épique. Si vous pouvez me signaler également des ressources à la fin, ce serait apprécié. Je regarde peut-être le système SNES ou NES à émuler et en faire mon projet de semestre.
mmcdole
8
Certainement. Je vais rassembler une belle liste de ressources. Si vous avez des demandes spécifiques, je ferai de mon mieux pour les remplir.
Cody Brocious
3
@thenonhacker, Le projet IronBabel référencé dans ma section ressources est le mien. (La fiche éhontée est marquée;))
Cody Brocious
1
"Il a été prouvé que trouver tout le code dans un binaire donné équivaut au problème d'arrêt" - Référence s'il vous plaît? Ou devrait-il être "Il a été prouvé que trouver tout le code dans un binaire donné équivaut au problème d'arrêt"?
Impossible
4
Vous mentionnez que vous écrivez un livre; pouvez-vous s'il vous plaît nous donner une mise à jour à ce sujet? Pour ma part, je serais intéressé à le lire.
alex
126

Un gars du nom de Victor Moya del Barrio a écrit sa thèse sur ce sujet. Beaucoup de bonnes informations sur 152 pages. Vous pouvez télécharger le PDF ici .

Si vous ne voulez pas vous inscrire avec scribd , vous pouvez google pour le titre PDF, "Etude des techniques de programmation d'émulation" . Il existe plusieurs sources différentes pour le PDF.

mdm
la source
43

L'émulation peut sembler intimidante mais est en fait bien plus facile que la simulation.

Tout processeur a généralement une spécification bien écrite qui décrit les états, les interactions, etc.

Si vous ne vous souciez pas du tout des performances, vous pouvez facilement émuler la plupart des processeurs plus anciens en utilisant des programmes orientés objet très élégants. Par exemple, un processeur X86 aurait besoin de quelque chose pour maintenir l'état des registres (facile), de quelque chose pour maintenir l'état de la mémoire (facile) et de quelque chose qui prendrait chaque commande entrante et l'appliquerait à l'état actuel de la machine. Si vous vouliez vraiment de la précision, vous émuleriez également des traductions de mémoire, la mise en cache, etc., mais c'est faisable.

En fait, de nombreux fabricants de micropuces et de processeurs testent des programmes contre un émulateur de la puce, puis contre la puce elle-même, ce qui les aide à savoir s'il y a des problèmes dans les spécifications de la puce ou dans la mise en œuvre réelle de la puce dans le matériel. Par exemple, il est possible d'écrire une spécification de puce qui entraînerait des blocages, et lorsqu'une échéance se produit dans le matériel, il est important de voir si elle pourrait être reproduite dans la spécification car cela indique un problème plus important que quelque chose dans la mise en œuvre de la puce.

Bien sûr, les émulateurs pour les jeux vidéo se soucient généralement des performances afin de ne pas utiliser d'implémentations naïves, et ils incluent également du code qui s'interface avec le système d'exploitation du système hôte, par exemple pour utiliser le dessin et le son.

Compte tenu des performances très lentes des anciens jeux vidéo (NES / SNES, etc.), l'émulation est assez facile sur les systèmes modernes. En fait, il est encore plus étonnant que vous puissiez simplement télécharger un ensemble de tous les jeux SNES ou tout jeu Atari 2600, étant donné que lorsque ces systèmes étaient populaires, l'accès gratuit à chaque cartouche aurait été un rêve devenu réalité.

Uri
la source
1
Quelles sont les différences entre l'émulation et la simulation?
Wei Hu
2
@Wei: De manière générale, un émulateur est censé se comporter "en externe" comme le système qu'il émule, mais rien ne dit qu'il doit être implémenté de manière similaire. Un simulateur est implémenté de manière à imiter le système simulé et, par conséquent, se comporte comme lui.
Uri
Quand vous voyez "Simulator" pensez que c'est similaire tandis qu'un émulateur "émule"
mP.
29

Je sais que cette question est un peu ancienne, mais je voudrais ajouter quelque chose à la discussion. La plupart des réponses se concentrent ici sur les émulateurs interprétant les instructions machine des systèmes qu'ils émulent.

Cependant, il existe une exception très connue à cela appelée "UltraHLE" ( article WIKIpedia ). UltraHLE, l'un des émulateurs les plus célèbres jamais créés, émulait des jeux commerciaux Nintendo 64 (avec des performances décentes sur les ordinateurs personnels) à une époque où il était largement considéré comme impossible de le faire. En fait, Nintendo produisait encore de nouveaux titres pour la Nintendo 64 lorsque UltraHLE a été créé!

Pour la première fois, j'ai vu des articles sur les émulateurs dans des magazines imprimés où auparavant, je ne les avais vus que discutés sur le Web.

Le concept d'UltraHLE était de rendre possible l'impossible en émulant des appels de bibliothèque C au lieu d'appels de niveau machine.

Rivière Vivian
la source
22

Quelque chose à regarder est la tentative d'Imran Nazar d'écrire un émulateur Gameboy en JavaScript.

Julio
la source
1
Comment obtenir les instructions brutes d'opcode pour le jeu Gameboy?
Pacerier
Il existe un certain nombre d'appareils disponibles à la vente sur le «marché gris». Vous ne les trouverez dans aucun grand magasin du monde développé. Ces appareils sont capables de copier les instructions de la cartouche de jeu dans des fichiers qui sont généralement appelés "ROM". Google "Gameboy Roms", mais attention aux liens dangereux et aux sites d'attaque!
Vivian River
18

Ayant créé mon propre émulateur du micro-ordinateur BBC des années 80 (tapez VBeeb dans Google), il y a un certain nombre de choses à savoir.

  • Vous n'imitez pas la vraie chose en tant que telle, ce serait une réplique. Au lieu de cela, vous imitez l' État . Un bon exemple est une calculatrice, la vraie chose a des boutons, un écran, un boitier, etc. représentant toutes les combinaisons possibles de choses qui peuvent changer dans une calculatrice.
  • Vous avez seulement besoin que l'interface de l'émulateur apparaisse et se comporte comme la vraie chose. Plus cela est convaincant, plus l'émulation est proche. Ce qui se passe dans les coulisses peut être tout ce que vous aimez. Mais, pour faciliter l'écriture d'un émulateur, il existe une correspondance mentale qui se produit entre le système réel, c'est-à-dire les puces, les écrans, les claviers, les cartes de circuits imprimés et le code informatique abstrait.
  • Pour émuler un système informatique, il est plus facile de le diviser en petits morceaux et d'émuler ces morceaux individuellement. Ensuite, enchaînez le tout ensemble pour le produit fini. Tout comme un ensemble de boîtes noires avec entrées et sorties, qui se prête magnifiquement à une programmation orientée objet. Vous pouvez encore subdiviser ces morceaux pour vous faciliter la vie.

En pratique, vous cherchez généralement à écrire pour la vitesse et la fidélité de l'émulation. Cela est dû au fait que le logiciel sur le système cible fonctionnera (peut) plus lentement que le matériel d'origine sur le système source. Cela peut limiter le choix du langage de programmation, des compilateurs, du système cible, etc.
En outre, vous devez circonscrire ce que vous êtes prêt à émuler, par exemple, il n'est pas nécessaire d'émuler l'état de tension des transistors dans un microprocesseur, mais c'est probablement nécessaire pour émuler l'état de l'ensemble de registres du microprocesseur.
De manière générale, plus le niveau de détail de l'émulation est petit, plus vous obtiendrez de fidélité au système d'origine.
Enfin, les informations sur les anciens systèmes peuvent être incomplètes ou inexistantes. Il est donc essentiel de se procurer l'équipement d'origine, ou du moins de mettre à part un autre bon émulateur que quelqu'un d'autre a écrit!

Guillermo Phillips
la source
17

Oui, vous devez interpréter le désordre du code machine binaire entier "à la main". Non seulement cela, la plupart du temps, vous devez également simuler du matériel exotique qui n'a pas d'équivalent sur la machine cible.

L'approche simple consiste à interpréter les instructions une par une. Cela fonctionne bien, mais c'est lent. Une approche plus rapide est la recompilation - la conversion du code machine source en code machine cible. Ceci est plus compliqué, car la plupart des instructions ne seront pas mappées un à un. Au lieu de cela, vous devrez effectuer des contournements élaborés qui impliquent du code supplémentaire. Mais au final, c'est beaucoup plus rapide. La plupart des émulateurs modernes le font.

Vilx-
la source
1
Le pire, c'est de loin la documentation manquante. C'est lorsque vous découvrez que le noyau Z80 modifié de la GameBoy Color a des opérations de drapeau non documentées que le jeu que vous testez utilise que vous commencez vraiment à perdre confiance.
Callum Rogers
1
Pet peeve: c'est le code machine (singulier), pas les codes machine (pluriel); tout comme c'est le code Morse et non les codes Morse .
Lawrence Dol
1
@Vilx: En fait non - le terme "code machine", se référant au jeu d'instructions pour un CPU, est utilisé depuis la création du logiciel et n'est pas pluriel. Il fait référence au " jeu d' instructions ", une forme singulière, et non au pluriel "instructions". Identique au code du programme, au code Morse, etc.
Lawrence Dol
1
@Software Monkey - Mais ne puis-je pas utiliser le mot "code" pour faire référence à un seul élément de l'ensemble? Par exemple: " ... --- ...- ces trois codes Morse représentent les trois lettres S, O, S." Parce que ...c'est un code représentant la lettre "S". Non?
Vilx-
1
Non, le code est un nom indénombrable, il n'a pas de forme plurielle comme l'eau ou le sable ..
Ivan
15

Lorsque vous développez un émulateur, vous interprétez l'assemblage de processeur sur lequel le système travaille (Z80, 8080, CPU PS, etc.).

Vous devez également émuler tous les périphériques du système (sortie vidéo, contrôleur).

Vous devriez commencer à écrire des émulateurs pour les systèmes simpe comme le bon vieux Game Boy (qui utilise un processeur Z80, je ne me trompe pas) OU pour C64.

Baget
la source
9
C64 un système "simple"? Alors que le 6510 est relativement simple (une fois que vous avez couvert les opcodes non répertoriés), les puces audio (SID) et vidéo (VIC) sont tout sauf simples. Pour atteindre un niveau de compatibilité décent, vous devez les émuler - bogues matériels et tout.
moobaa
10

Les émulateurs sont très difficiles à créer car il existe de nombreux hacks (comme dans les effets inhabituels), des problèmes de synchronisation, etc. que vous devez simuler.

Pour un exemple de cela, voir http://queue.acm.org/detail.cfm?id=1755886 .

Cela vous montrera également pourquoi vous avez besoin d'un processeur multi-GHz pour émuler un processeur à 1 MHz.

Quelqu'un
la source
9

Consultez également Emulators.com de Darek Mihocka pour d'excellents conseils sur l'optimisation de niveau d'instruction pour les JIT, et de nombreux autres goodies sur la construction d'émulateurs efficaces.

Barry Bond
la source
7

Je n'ai jamais rien fait d'extraordinaire pour émuler une console de jeu, mais j'ai suivi un cours où la tâche consistait à écrire un émulateur pour la machine décrite dans Andrew Tanenbaums Structured Computer Organization . C'était amusant et m'a donné beaucoup de moments aha. Vous voudrez peut-être prendre ce livre avant de plonger dans l'écriture d'un véritable émulateur.

oivvio
la source
4

Des conseils pour émuler un vrai système ou votre propre truc? Je peux dire que les émulateurs fonctionnent en émulant le matériel ENTIER. Peut-être pas dans le circuit (comme le ferait le déplacement de bits comme le ferait le matériel. Le déplacement de l'octet est le résultat final, donc la copie de l'octet est très bien). Les émulateurs sont très difficiles à créer car il existe de nombreux hacks (comme dans les effets inhabituels), des problèmes de synchronisation, etc. que vous devez simuler. Si une pièce (entrée) est erronée, tout le système peut être en panne ou au mieux avoir un bug / problème.


la source
4

L' émulateur de périphérique source partagé contient du code source à construire vers un émulateur PocketPC / Smartphone (nécessite Visual Studio, s'exécute sur Windows). J'ai travaillé sur V1 et V2 de la version binaire.

Il résout de nombreux problèmes d'émulation: - traduction d'adresse efficace du virtuel invité au physique invité en virtuel hôte - Compilation JIT du code invité - simulation de périphériques tels que les adaptateurs réseau, l'écran tactile et l'audio - Intégration d'interface utilisateur, pour le clavier et la souris hôte - sauvegarde / restauration de l'état, pour simulation de reprise à partir du mode basse consommation

Barry Bond
la source
1

Pour ajouter la réponse fournie par @Cody Brocious
Dans le contexte de la virtualisation où vous émulez un nouveau système (CPU, E / S, etc.) sur une machine virtuelle, nous pouvons voir les catégories d'émulateurs suivantes.

Interprétation: bochs est un exemple d'interprète, c'est un émulateur PC x86, il prend chaque instruction du système invité la traduit dans un autre ensemble d'instructions (de l'hôte ISA) pour produire l'effet souhaité.Oui c'est très lent, ça ne marche pas 'cache rien donc chaque instruction passe par le même cycle.

Emalateur dynamique: Qemu est un émulateur dynamique. La traduction à la volée des instructions invitées met également en cache les résultats. La meilleure partie est d'exécuter autant d'instructions que possible directement sur le système hôte afin que l'émulation soit plus rapide. Aussi, comme mentionné par Cody, il divise le code en blocs (1 flux d'exécution unique).

Émulateur statique: Pour autant que je sache, aucun émulateur statique ne peut être utile pour la virtualisation.

Pensée profonde
la source
1

Comment commencer l'émulation.

1.Obtenez des livres basés sur une programmation de bas niveau, vous en aurez besoin pour le système d'exploitation "simulé" du Nintendo ... game boy ...

2.Obtenez des livres sur l'émulation en particulier, et peut-être sur le développement du système d'exploitation. (vous ne ferez pas un os, mais le plus proche de lui.

3. regardez certains émulateurs open source, en particulier ceux du système pour lequel vous souhaitez créer un émulateur.

4. copiez des extraits du code plus complexe dans votre IDE / compilateur. Cela vous évitera d'écrire du code long. C'est ce que je fais pour le développement du système d'exploitation, utilisez un district de Linux

5Mixer
la source
1

J'ai écrit un article sur l'émulation du Chip-8 en JavaScript .

C'est un excellent endroit pour commencer car le système n'est pas très compliqué, mais vous apprenez toujours comment les opcodes, la pile, les registres, etc.

J'écrirai bientôt un guide plus long pour la NES.

alex
la source