[EMULATION AMSTRAD CPC] AMSpiriT - work in Progress

Couvre tous les domaines de l'émulation logicielle ou de la virtualisation ainsi que les discussions sur les divers outils associés.

Modérateurs : Papy.G, fneck, Carl

Avatar de l’utilisateur
Sebiohazard
Messages : 425
Inscription : 30 avr. 2019 15:07

Re: [EMULATION AMSTRAD CPC] work in Progress

Message par Sebiohazard »

Bonjour à tous !

Petite question... est-ce que le choix du C est judicieux pour apprendre la programmation & si oui le C++ est-il facilement assimilable avec le C ?

Ne devrais-je pas commencer en BASIC ?

D'avance merci pour vos réponses salutations !
Image
Avatar de l’utilisateur
hlide
Messages : 3469
Inscription : 29 nov. 2017 10:23

Re: [EMULATION AMSTRAD CPC] work in Progress

Message par hlide »

Tu peux parfaitement faire du C dans du C++ ou même utiliser des librairies en C avec du C++ si c'est ça ta question.

Le C++ a quand même pour base le C. Donc si tu commences avec du C pour ensuite partir sur du C++, tu seras certainement mieux armé qu'en partant du BASIC.
__sam__
Messages : 7923
Inscription : 18 sept. 2010 12:08
Localisation : Brest et parfois les Flandres

Re: [EMULATION AMSTRAD CPC] work in Progress

Message par __sam__ »

Moi je trouve le C++ insupportable. Ce standard n'est pas stable. Il change régulièrement, et ca ne va pas du tout en simplifiant les choses (on parle d'évolutions où moi je vois surtout des régressions). Des vieux codes C++ d'il y a 20ans ne compilent simplement plus. Par contre le C, c'est du rock-stable.

Ok on ne fait pas de l'objet en C (en tout cas on n'en fait pas facilement), mais en C++ non plus[*]. La partie objet du c++ est en pratique très mal utilisée et surtout abusée. Les gens disent faire du C++, mais c'est fondamentalement du C avec des bibliothèques en plus leur évitant d'écrire le code d'une hash-map ou d'un tableau de taille dynamique... mais en se coltinant une tartine de bidules bien verbeux abusant des chevrons/static_cast dans tous les sens et ajoutant de la lourdeur à l'assembleur généré.

Peu de temps après ces mêmes gens découvrent le python et sont aux anges: ils ont les mêmes bibliothèques, mais sans lourdeur chiantes du compilo et ses règles à la noix. Bien évidemment tout ceci conduit à une dérive vers des programmes de plus en plus lents, de la perte de savoir faire de la programmation (on se contente d'accoler du code récupéré ici ou là via google), et ca produit des tonnes de bugs pas francs et des logiciels instables caractérisés par de nombreuses mises à jour.

Ils auraient fait du C standard, qu'ils auraient compris que bien coder dès le départ est indispensable et qu'on ne peut s'improviser codeur en assemblant des bouts de code au pif façon Frankenstein sans créer un monstre ingérable.

Bref: C++ beurk perso. C'est une boite de pandore.
___
[*] de toute façon le paradigme objet disparait au profit du fonctionnel dans les languages récents: les fonctions sont une valeur primitive qu'on peut manipuler et combiner pour en produire de nouvelles. Si on veut faire du vrai objet il faut prendre des trucs plus abstraits que le C++ dans lesquels tout est objet dans le tas (pas d'objet local sur la pile) et dont le cycle de vie est géré par un ramasse miette. Par contre on ne fait que du haut niveau avec ca. N'allez pas essayer de répondre à des interruptions temps réel avec ca.
Samuel.
A500 Vampire V2+ ^8^, A1200 (030@50mhz/fpu/64mb/cf 8go),
A500 GVP530(MMU/FPU) h.s., R-Pi, TO9, TO8D, TO8.Démos
Dmanu78
Messages : 268
Inscription : 20 juin 2020 14:28
Localisation : Yvelines

Re: [EMULATION AMSTRAD CPC] work in Progress

Message par Dmanu78 »

Suite de la séquence sur le construction d’un émulateur.
A partir de moment où l’on est à peu prêt Ok sur le langage de programmation et l’environnement de développement se pose la question fatidique : Quelle machine émuler ?

Il n’y a une pluralité de réponses bien sûr mais je répondrais avant tout la machine qui nous plaît bien sûr :D
Mais pour éviter bien de désillusions, surtout si c’est une première, comme pour moi, mieux vaut éviter pour commencer de choisir un ordinateur/console complexe pour débuter. Quand je dis complexe, c’est à dire contenant circuits intégrés propriétaires ou spécialisés pour accélérer les traitements en « hardware » (affichage de sprite en hard par exemple) La présence de ses puces complexifient grandement l’écriture d’un émulateur. S’agissant le plus souvent de puces propriétaires faites sur mesure au secret bien gardé, il est très compliqué de retrouver leurs caractéristiques et donc de les émuler. Seul un gros travail de rétro engineering permet de deviner leur fonctionnement...pas forcément à la portée de tout le monde et encore moins d’un néophyte. J’éviterai donc les Commodore 64, Amiga, Texas Instruments ...
De même, il est plus simple de commencer sur un ordinateur dont la ROM est librement accessible sur internet.

Si j’ai choisi l’Amstrad CPC c’est qu’il s’agit de ma machine coup de cœur de mon adolescence que je connais (connaissais plutôt) plutôt bien, sûr laquelle j’ai passé de très nombreuses heures et appris les bases de la programmation et notamment l’assembleur du Z80. J’ai en outre gardé de nombreux livres de programmation et notamment la fameuse Bible du programmeur de « micro application » contenant toute le ROM du CPC 464 désassemblée et commentée. Avec le recul, c’est un petit trésor que j’ai beaucoup lu sans jamais le comprendre complètement et que je redécouvre au fur et à mesure que j’avance dans l’écriture de l’émulateur. L’Amstrad ayant été très diffusé, de nombreuses docs sont disponibles sur internet, de nombreux forums sont encore actifs....

L’Amstrad a en outre l’énorme avantage de s’appuyer sur des puces électroniques grand public qui sont bien documentées (data sheets dispo librement) sauf le « Gate Array » qui est propriétaire mais désormais bien documenté.

Bref, l’Amstrad était pour moi la machine parfaite pour commencer ce gros chantier...
À suivre.
Dernière modification par Dmanu78 le 26 nov. 2020 23:41, modifié 1 fois.
Avatar de l’utilisateur
Sebiohazard
Messages : 425
Inscription : 30 avr. 2019 15:07

Re: [EMULATION AMSTRAD CPC] work in Progress

Message par Sebiohazard »

Hello Dmanu !
Dmanu78 a écrit : 24 oct. 2020 19:52 J’ai en outre gardé de nombreux livres de programmation et notamment la fameuse Bible du programmeur de « micro application » contenant toute le ROM du CPC 464 désassemblée et commentée.
C'est bien cet ouvrage ici ?

Salutations !
Dernière modification par Sebiohazard le 27 oct. 2020 11:13, modifié 2 fois.
Image
__sam__
Messages : 7923
Inscription : 18 sept. 2010 12:08
Localisation : Brest et parfois les Flandres

Re: [EMULATION AMSTRAD CPC] work in Progress

Message par __sam__ »

J'ai pas écrit le message cité. @Sebiohazard: un bot t'a volé ton identité ou as tu mélangé les citations?
Samuel.
A500 Vampire V2+ ^8^, A1200 (030@50mhz/fpu/64mb/cf 8go),
A500 GVP530(MMU/FPU) h.s., R-Pi, TO9, TO8D, TO8.Démos
Avatar de l’utilisateur
fneck
Site Admin
Messages : 17424
Inscription : 01 avr. 2007 12:03
Localisation : Drôme Provençale (26)
Contact :

Re: [EMULATION AMSTRAD CPC] work in Progress

Message par fneck »

Cafouillage de citation probablement, celle-ci provient du message juste au-dessus de Dmanu78.
Fabien https://www.system-cfg.com
Les bonnes pratiques de l'utilisateur du forum viewtopic.php?f=14&t=3
__sam__
Messages : 7923
Inscription : 18 sept. 2010 12:08
Localisation : Brest et parfois les Flandres

Re: [EMULATION AMSTRAD CPC] work in Progress

Message par __sam__ »

Ouf il m'a fait peur, je pensais à un bot super évolué qui reprends un message supra, et le modifie pour ajouter une URL vers un truc commercial. Ca y ressemblait fortement et ca pourrait presque arriver si les mots de passe fuitaient.

sam (en mode parano de l'usurpation d'identité numérique).
Samuel.
A500 Vampire V2+ ^8^, A1200 (030@50mhz/fpu/64mb/cf 8go),
A500 GVP530(MMU/FPU) h.s., R-Pi, TO9, TO8D, TO8.Démos
Dmanu78
Messages : 268
Inscription : 20 juin 2020 14:28
Localisation : Yvelines

Re: [EMULATION AMSTRAD CPC] work in Progress

Message par Dmanu78 »

@sebiohazard
Oui tout à fait. C’est bien cet ouvrage. Il contient quelques coquilles ou approximations mais pour avoir une vision globale du fonctionnement d’un CPC il est plutôt pas mal fait. Et la ROM en listing aide beaucoup pour les phases de déboggage de l’émulateur. Sur ma version, il y a désormais beaucoup d’annotations au crayon de papier... :D
Avatar de l’utilisateur
Sebiohazard
Messages : 425
Inscription : 30 avr. 2019 15:07

Re: [EMULATION AMSTRAD CPC] work in Progress

Message par Sebiohazard »

fneck a écrit : 26 oct. 2020 09:35 Cafouillage de citation probablement, celle-ci provient du message juste au-dessus de Dmanu78.
Oui milles excuses je viens de corriger cela :)
__sam__ a écrit : 26 oct. 2020 13:07 Ouf il m'a fait peur, je pensais à un bot super évolué qui reprends un message supra, et le modifie pour ajouter une URL vers un truc commercial. Ca y ressemblait fortement et ca pourrait presque arriver si les mots de passe fuitaient.

sam (en mode parano de l'usurpation d'identité numérique).
MDR je n'ai pas encore le niveau pour programmer un tel bot :lol:
Image
Dmanu78
Messages : 268
Inscription : 20 juin 2020 14:28
Localisation : Yvelines

Re: [EMULATION AMSTRAD CPC] work in Progress

Message par Dmanu78 »

Je reprends le fil de ce post pour expliciter les différentes étapes de la création de mon émulateur.

A partir du moment où les outils de développement sont en place, que la programmation sous Windows commence à être maitrisée vient la première question : par où commencer pour créer un émulateur ? vaste question...

Les différentes documentations que j'ai lues indiquent que développer un émulateur est conceptuellement assez simple : c'est une simple boucle dans laquelle on va lire une zone mémoire prédéfinie afin d'y récupérer une valeur, l'interpréter [ce sera le rôle du processeur émulée], permettant une mise à jour des variables internes du processeur, lire une autre zone mémoire et ... ainsi de suite, tout simplement !

Et voilà, c'est fini !

Bon, en pratique c'est bien évidemment un peu plus complexe que cela et le premier aspect sur lequel j'ai travaillé est la question du ... TIMING.
Car faire une boucle est facile, faire une boucle qui exécute des instructions avec un timing très précis l'est un peu moins.

Tout ordinateur fonctionne au rythme d'un signal périodique très précis fourni par d'un cristal de quartz. La première chose à faire est d'émuler ce battement cardiaque et c'est d'autant plus primordial sur un AMSTRAD CPC dans lequel plusieurs des composants sont cadencés et synchronisés via ce signal périodique.

Le premier obstacle que j'ai rencontré a donc été d'ordre technique : comment à partir de la fréquence de mon PC (qui tourne en Ghz) créer une boucle qui me permette d'émuler le signal d'horloge de 16 Mhz correspondant à la fréquence d'origine du Gate Array équipant le CPC ?

[MAITRISER LES HORLOGES]
Au début, j'ai pensé utiliser les fonctions intégrées du C++ pour cet usage (bibliothèque <chrono> notamment) et je me suis vite aperçu qu'elles n'étaient pas assez rapide. Une boucle de 16 Mhz nécessite un chronomètre qui puisse donner un top tous les 62,5 nanosecondes. Au final, la solution que j'ai trouvé est de faire directement appel à une instruction hardware du microprocesseur, à savoir RDTSC, qui s'incrémente en temps réel à chaque nouveau cycle processeur.
L'utilisation de cette instruction va me permettre d'en déduire la fréquence réelle du microprocesseur qui sera ainsi divisée par 16 Mhz afin d'en déduire le nombre de cycles d'attente qu'il faudra faire tourner dans une boucle vide au sein de ma boucle principal pour cadencer l'émulateur à la fréquence souhaitée.

Image

Au début je mesurais constamment ce rapport car je pensais que la fréquence du CPU variait constamment dans le temps. Et bien non, quand l'émulateur démarre il semblerait bien que la fréquence du CPU soit fixée une fois pour toute et ne varie plus tant que celui-ci est actif. Tant mieux !

La division par 4 et 16 de ce signal va ainsi me permettre de fixer les fréquences pour l'émulation du Z80 (4Mhz) et pour les autres chipsets fonctionnant à 1 Mhz (CRTC / PSG notamment).

Maintenant, dernière question : comment être certain que la fréquence de l'émulateur soit bien celle voulue ?
Il suffit de mettre une variable qui s'incrémente à la fin de chaque cycle d'attente, de faire tourner en parallèle un timer qui va mesurer précisément le nombre de cycles écoulés chaque seconde afin d'en déduire la fréquence d'émulation et enfin de l'afficher dans la fenêtre Windows. Cela me permet de vérifier s'il n'y a pas un problème de timing lors de l'exécution de l'émulateur...

Image

Au final, je suis surpris de voir que la fréquence d'émulation est extrêmement précise et fluctue très peu dans le temps. C'est très utile pour vérifier que certaines routines ne consomment pas trop de ressources CPU entre chaque tour de boucle. J'en reparlerai plus tard.

Voilà pour cette première étape importante. A suivre :)

PS : La méthode que je donne ici correspond la solution empirique que j'ai trouvé pour répondre à mon problème de Timing. Il y a certainement d’autres techniques pour arriver à cette même fin. Je serai ravi d'échanger dessus avec d'autres concepteurs d'émulateurs. :)
Avatar de l’utilisateur
hlide
Messages : 3469
Inscription : 29 nov. 2017 10:23

Re: [EMULATION AMSTRAD CPC] work in Progress

Message par hlide »

Les très vieux processeurs ont un RDTSC précis - encore qu'avec le nombre de cœur et la variation de vitesse, cela peut aussi poser un problème car ils n'auront pas la même valeur par cœur et la variation de vitesse fera qu'il ne sera pas possible d'appliquer un diviseur fixe. Toutefois, les processeurs plus récents posent un problème tout à fait différent en faisant toujours tourner le TSC à une fréquence fixe, même si le processeur ralentit. Cela permet d'avoir l'heure mais le cycle compté n'a plus rien à avoir avec le cycle réel du CPU.

Comment savoir si ton CPU ne compte plus les cycle CPU : en lisant le bit TSC_invariant du CPUID. il faut affecter 80000007H à EAX et lire le bit 8 de EDX. S'il est à un, les cycles CPU ne sont plus comptés et il faut profiler avec un CPU qui s'exécute à 100%.

Le système d'exploitation change de processeur logique pour un thread à l'insu du programme, donc entre deux appels à RDTSC on pouvait avoir une désynchronisation.

Bref, l'idéal c'est d'avoir deux sources : le RDTSC pour les cycles et un timer moins fin qui permet de vérifier la cohérence des cycles.

On peut aussi faire que le thread qui fait l'émulation puisse ne tourner que sur le même processeur logique et s'assurer qu'il tourne à 100% pour que la division du nombre de cycles CPU par le nombre de cycles du RDTSC soit un facteur fixe.

Maintenant, il ne faut pas oublier de compter les cycles Z80 à chaque instruction et les autres également pour pouvoir les confronter à ceux du RDTSC pour temporiser dynamiquement (si le CPU a une vitesse variable).
Dmanu78
Messages : 268
Inscription : 20 juin 2020 14:28
Localisation : Yvelines

Re: [EMULATION AMSTRAD CPC] work in Progress

Message par Dmanu78 »

Merci de ton retour hlide. C’est très intéressant.
C’est exactement cela, dans mon cas, le processeur semble être à 100% de charge dès le lancement de l’émulateur et RDTSC renvoie toujours la même valeur. Donc je ne le teste qu’une fois et envoie je laisse un timer moins précis vérifier que les timing ne changent pas. Je n’ai testé que sur 2 processeurs Intel (core i7 et i9) et le comportement semble identique.
A voir comment cela évoluera sur d’autres processeurs quand je diffuserai la première bêta... :)
Dmanu78
Messages : 268
Inscription : 20 juin 2020 14:28
Localisation : Yvelines

Re: [EMULATION AMSTRAD CPC] work in Progress

Message par Dmanu78 »

Suite de l’aventure ...
Une fois les sujets de timing plus ou moins réglés se posent une question d’ordre conceptuel qui va conditionner toute la suite du développement : l’émulateur sera-t-il développé en T-States ou en NOP ?
Il y a 2 écoles sur le sujet avec des avantages et des inconvénients : simplicité, rapidité mais une émulation moins précise pour l’école NOP, une émulation plus précise mais beaucoup plus complexe à implémenter et d’exécution plus lente pour l’école T-State. Je ne rentrerai pas dans le débat, j’ai vu par ailleurs un post dans lequel Daniel aborde très clairement le sujet. Dès le départ, je voulais émuler le CPC le plus fidèlement possible ne serait ce que pour comprendre comment cet ensemble de puces électroniques à l’intérieur du CPC pouvait fonctionner de concert pour lui donner vie, en ne communiquant que via des bus. Le choix était aisé, j’ai donc choisi la voie T-State. Avec 2 ans de recul, je me dis que c’est peut être un choix un peu trop radical, avec un code parfois inutilement complexe et difficile à appréhender, mais bon, je suis parti sur cette voie, je l’assume :D

Dans mon cas de figure, j’ai donc considéré que chacun des composants principaux du CPC serait conçu comme une boîte noire autonome ne communiquant avec l’extérieur qu’à travers les broches de connexion décrits dans les Datasheets : processeur, gate Array, CRTC, puce sonore, PPI ... chacune de ses puces serait émulée en vase clos et cadencée au rythme des signaux d’horloge.

Au tout début du développement, je voulais créer des threads spécifiques à chacune des puces. Ces thread fonctionneraient ainsi de manière synchrones les uns avec les autres via les signaux d’horloge. J’ai très vite réalisé que ce n’était pas possible : les threads loupaient régulièrement des cycles d’horloges et se retrouvaient vite désynchronisés entre eux. Gênant pour un émulateur.
Au final, je décidais que seules quelques fonctionnalités très gourmandes en ressources CPU et n’ayant pas besoin d’être précisément synchronisées seraient mises en thread et que les autre composants seraient appelés séquentiellement, à des fréquences différentes, au sein de ma fameuse boucle principale synchronisée à 16 MHz.
Ainsi dans cette boucle, les routines émulant le Gate Array tournent précisément à 16Mhz, par division du signal, celles du CPU à 4Mhz, celles émulant le AY et le CRTC à 1 MHz...Les routines gérant l’affichage de l’écran ainsi que le Mapping clavier seront par contre mises dans des threads indépendants de la boucle principale.
Car un autre problème va surgir très vite : multiplier les appels aux différentes routines au sein de la même boucle consomme de précieuses ressources CPU et je vais vite le constater, il est très facile de perdre la synchro à 16 MHz . Dans mon cas, il m’a fallu très vite optimiser mon code avec des astuces de programmation afin de trouver un compromis entre compacité du code et vitesse d’exécution en temps reel.

Ces généralités passées, le cadre du projet étant posé et plutôt bien clair dans ma tête commence alors le vrai développement de l’émulateur et une autre question se pose dès lors : par quoi commencer maintenant ??...car devant moi il y a alors une énorme page blanche...
A suivre... :)
Dernière modification par Dmanu78 le 26 nov. 2020 23:06, modifié 1 fois.
Avatar de l’utilisateur
Sebiohazard
Messages : 425
Inscription : 30 avr. 2019 15:07

Re: [EMULATION AMSTRAD CPC] work in Progress

Message par Sebiohazard »

Hello Dmanu !

Merci pour la suite de ce récit passionnant même si pour moi cela reste incompréhensible :) j'aimerais déjà comprendre ce que sont les T-States ou les NOP ?

Y a-t-il un moyen simple & vulgarisé de m'expliquer ?

Salutations !
Image
Répondre