Salut tout le monde, vu l’intérêt croissant pour la conversion de jeux disquette en cartouche GX4000, je me suis dit que j’allais rassembler un petit tuto/FAQ (enfin, c’était censé être court dans ma tête) détaillant les méthodes que j’utilise. Avertissement préalable : je ne fais ça que depuis peu de temps et j’apprends sur le tas, alors ne prenez pas tout ce que je dis pour parole d’évangile, je ne suis absolument pas un expert du matériel Amstrad. Cependant, j’aime énormément en apprendre sur cette vieille machine et me lancer des défis, c’est un passe-temps très satisfaisant et addictif.
Quand j’ai décidé de tenter ma chance la première fois, j’ai lu ce très bon article du fanzine CPC : https://www.cpcwiki.eu/imgs/6/6f/CPC_Fanzine_-_GX4000_conversion.pdf
Cet article contient énormément d’informations très utiles qui m’ont permis de me lancer, et j’ai eu beaucoup de chance que le premier jeu que j’ai choisi de convertir, Dynamite Dan, se prête bien à une conversion avec les méthodes décrites. Malheureusement, il y a plusieurs cas de figure que l’article ne mentionne pas, et en fait la majorité des jeux que j’ai convertis depuis n’auraient pas pu l’être avec les méthodes de cet article.
L’article explique comment utiliser un éditeur hexadécimal pour modifier directement un fichier disquette, afin d’apporter des modifications au niveau des octets dans le code du jeu. Cela ne fonctionne que lorsque le programme n’est ni compressé ni chiffré. Pour la plupart des jeux que vous chercherez à convertir, le fichier disquette de départ aura été « cracké », et les hackers adorent chiffrer et (surtout) compresser leurs créations. Bien qu’avec des formes de chiffrement rudimentaires (utilisant souvent de simples algorithmes XOR) vous puissiez faire le chemin inverse pour deviner quels devraient être les octets sur la disquette (je l’ai fait pour Shogun), c’est très laborieux et cela demande une concentration intense et une prise de notes rigoureuse. Ce n’est pas une voie que je recommande.
Pourquoi devez-vous souvent partir d’une version crackée plutôt que d’une version commerciale ? Dans de nombreux cas, les jeux sur disquette chargent des données depuis la disquette à un moment donné — même s’il ne s’agit que d’un écran de chargement. Beaucoup de jeux plus volumineux chargent chaque niveau individuellement. Souvent, les jeux commerciaux accédaient directement au contrôleur de disquette (FDC) plutôt que de passer par la ROM AMSDOS. Dès qu’un jeu fait cela, il ne peut pas être converti avec nocart, et ne tournera donc pas sur la GX4000. Les hackers ont souvent pris des jeux commerciaux et remplacé l’accès direct au lecteur de disquette par des appels au firmware AMSDOS, car cela permettait de contourner la protection contre la copie, etc. Les versions crackées fonctionnent donc souvent directement avec nocart, telles quelles.
Il existe deux moyens fiables de vérifier si le fichier .dsk que vous avez utilise le firmware ou non. D’abord, chargez-le dans WinAPE et allez dans le menu « Edit disk ». Cliquez sur « Show system files ». Si vous voyez plusieurs fichiers, il y a de fortes chances qu’il fonctionne tel quel avec nocart, car il utilise les fichiers standards AMSDOS avec des en-têtes standards. Pour confirmer, vous pouvez lancer le jeu dans WinAPE et poser un point d’arrêt (breakpoint) sur le FDC via Debug → Breakpoints → Input/Output → Add → FDC Data. Lorsque le débogueur s’interrompt quand le jeu essaie de charger des données, jetez un œil en bas du débogueur et vérifiez si la case « Upper ROM » est cochée. Si c’est le cas, c’est bon signe, cela signifie qu’AMSDOS est utilisé.
Je dois préciser que je n’ai pas essayé tous les émulateurs de la terre, mais parmi ceux que j’ai testés, WinAPE est de loin le meilleur pour faire du développement, malgré quelques petits détails mineurs que j’aimerais pouvoir changer.
J’ai donc converti quelques jeux en utilisant la méthode d’édition manuelle du fichier .dsk (avec un éditeur hexadécimal, HxD), mais j’ai trouvé ça frustrant car c’était très difficile de garder une trace des modifications apportées. Si vous vous trompiez d’un octet, vous pouviez vous retrouver revenu à la case départ ou dans un état indéterminé. Étant développeur de métier, j’ai l’habitude d’utiliser un outil de contrôle de version comme Git pour pouvoir découper toutes mes modifications en petits commits, ce qui me permet de toujours voir l’historique avec des notes sur ce que j’ai fait.
Pour le jeu suivant que j’ai converti, j’ai donc décidé d’expérimenter une autre méthode. Elle s’est avérée payante et c’est celle que j’utilise pour tous les jeux que j’ai convertis depuis.
Je pars d’un projet vierge CPCTelera. Vous connaissez peut-être cet excellent utilitaire, c’est un compilateur C pour l’Amstrad qui génère un fichier .dsk. Il y a plein de docs si vous cherchez sur Google.
Il y a maintenant deux possibilités pour un jeu donné : les fichiers sont-ils compressés ou non ? Pour le savoir, lancez le jeu (la partie réelle, là où vous jouez) et mettez son exécution en pause n’importe où avec F7. Dans le débogueur, vous verrez l’adresse de l’instruction en cours (PC) avec les octets de l’opcode sur la droite. Ouvrez le fichier .dsk dans un éditeur hexadécimal et cherchez la poignée d’octets qui commence à l’endroit où vous êtes en pause. Si vous les trouvez dans le fichier .dsk et que tout correspond, super, les binaires ne sont probablement pas compressés et vous pouvez sauter la section suivante.
S’ils sont compressés, c’est un peu plus délicat car vous devez repérer l’endroit exact où la décompression se termine et où le jeu se lance. Le moyen le plus simple est de lancer le jeu (par exemple run "disc) et de mettre un point d’arrêt dans WinAPE sur l’adresse de départ réelle au préalable. Vous pouvez la trouver dans l’éditeur de disquette, en faisant un clic droit sur un fichier, puis « Properties » et en regardant « Exec Address ».
Maintenant, je vais vous parler de l’utilisation de l’IA pour commenter et annoter le désassemblage, ce qui est l’outil le plus utile de la boîte à outils. Faire cela à la main est possible, mais c’est un travail titanesque, chronophage et frustrant — pas vraiment réalisable si vous avez un travail, une famille ou d’autres hobbys. Donc, une fois que vous êtes en pause quelque part au début ou à l’intérieur de la routine de décompression, faites défiler le débogueur, généralement vers l’avant dans la mémoire, et continuez sur environ 0x1000 octets. En général jusqu’à ce que vous voyiez un « RET », mais l’adresse de fin n’est pas cruciale car vous pourrez en reprendre plus tard. Faites Maj+Clic pour sélectionner ce bloc d’instructions, puis clic droit et « Disassemble ». Cliquez simplement sur OK dans la boîte de dialogue. Appuyez sur F3 pour afficher l’assembleur s’il n’est pas apparu. Vous avez maintenant le code source, mais dans un format très brut, qui est pratiquement inutile s’il n’est pas découpé en routines et abondamment commenté.
Une fois que vous avez l’assembleur brut de WinAPE, copiez-le et collez-le dans un nouveau fichier de votre projet (créez un nouveau dossier/projet Git pour chaque jeu que vous convertissez). J’utilise une convention de nommage du style « GameZ0x1000-0x2000.raw.asm ». Utilisez ensuite un outil d’IA avec un prompt spécifique pour convertir tout ça en quelque chose de lisible. Pas besoin de dépenser de l’argent pour des outils d’IA ! Les gratuits sont amplement suffisants. Ceux que j’utilise sont Opencode et Freebuff, ils proposent tous deux divers modèles utilisables totalement gratuitement. Ils sont extrêmement faciles à configurer et à utiliser. Choisissez le modèle le plus puissant disponible à son réglage maximum (demandez à l’IA si vous n’êtes pas sûr duquel est le meilleur). Je vous mets le prompt que j’utilise ci-dessous, vous pouvez le placer dans un fichier et soit le copier/coller, soit pointer l’outil d’IA dessus ainsi que sur votre fichier .asm :
« For the z80 code block at (votre chemin de fichier), designed to run on the Amstrad CPC, add inline comments showing high-level functions and separate into subroutines, with a header for each major/minor subroutine describing its purpose. Alter any labels to be more descriptive, but retain the address at the end of the label. At the top of the file add a summary comment with a bullet point list of the major functions contained within. Output the commented disassembly as a single block without dropping any instructions or data into a new file beside the existing. Try to identify any areas that are actually data and not code where possible. Refer to the firmware manual here if necessary for ROM calls etc: https://www.cantrell.org.uk/david/tech/cpc/cpc-firmware/firmware.pdf »
Une fois que l’IA a fait son travail, vous aurez quelque chose d’espérons-le lisible que vous pourrez analyser. Si elle a fait du mauvais travail, ou si les routines ne semblent pas liées à la décompression et au lancement du jeu, prenez simplement une autre section de la mémoire et répétez l’opération, ou essayez un autre modèle d’IA.
Avec un peu de chance, vous verrez quelque chose comme la décompression des données, puis un JP 0xXXXX pour lancer réellement le jeu (ou son écran titre). D’expérience, il y a presque toujours une instruction JP XXXXX qui est le point d’entrée de ce qui se serait trouvé dans le jeu commercial. C’est très souvent un nombre rond comme 0x100 ou 0x500 car les développeurs aiment bien choisir des chiffres ronds. Une autre solution pour trouver le point d’entrée est de lancer la version commerciale réelle et de voir où elle se lance en examinant les propriétés du fichier disquette.
Une fois que vous avez le point d’entrée du jeu (ce qui est enfantin si vous n’avez pas de version compressée/chiffrée), vous pouvez vider le contenu de la RAM en plaçant un point d’arrêt à cette adresse.
OK, tout cela devient beaucoup plus long que ce que je prévoyais, donc si quelqu’un est intéressé par la suite, dites-le-moi et je continuerai à écrire ci-dessous ou je déplacerai ça dans un article du wiki !