Je me permets un gros update sur les avancées plus ou moins récentes au sujet du BricoNeo, parce qu'il n'a pas l'air d'avancer des masses de loin, alors qu'il se passe quelques trucs. Attention, pavé en approche, mais j'ai mis des images pour que ce soit plus beau.
Tout d'abord, sachez qu'il y a 3 exemplaires de la carte dans la nature. L'un est chez moi pour le dev, et les deux autres sont chez les amis @Illusionrip et @ragefan , qui testent les différents patchs et évolutions. Ils en profitent pour faire du cheerleading (par exemple: "ohhhhh!!!", ou "ahhhhh...", pour me garder motivé).
@ragefan contribue également au développement de la ROM de test côté NeoGeo, on en reparle plus bas!
Génération de menus
Pour commencer, un bout de projet que vous aviez déjà vu, et qui m'a permis d'avancer un peu sur le dev de la carte BricoNeo: le menu pour les 161in1. L'idée serait de proposer un menu alternatif au menu moche d'origine.
Ca a été l'occasion de développer quelques trucs pour le BricoNeo, dont la possibilité d'envoyer des commandes au microcontrôleur depuis le code 68000. C'est ce qui permet de switcher la cartouche sur un autre jeu, et de basculer sur un Unibios dans la foulée.
Petit retour sur le processus de création d'un écran de menu:
Tout commence par un patch sur MAME pour comprendre comment marchent les savestates. A partir de là, je prends le savestate que je veux sur un jeu NeoGeo.. Puis je l'ouvre dans mon outil maison pour recombiner les sprites comme je veux à partir de plusieurs savestates (et d'éditer le fix layer): Derrière, cet outil peut être appelé en ligne de commande depuis le Makefile de mon projet 68000 sous VS Code, pour générer les données des sprites (tiles, positions, palettes, fix...) sous forme de data en assembleur. Ca permet de les référencer facilement dans le code par la suite. D'un appui sur une touche (F7, en l'occurrence), le code est assemblé et transféré sur le BricoNeo pour un résultat en 2 secondes chrono sur le matériel d'origine.

Effet surprise que je n'avais pas prévu: vu que je récupère toutes les infos de la VRAM depuis le savestate, je récupère aussi les données d'animation des décors. Ca permet de faire des trucs un peu cool comme ça sans écrire de code supplémentaire (si le GIF passe)...
Amélioration de la ROM de diagnostic
Et pendant ce temps-là, l'ami @ragefan nous développait un patch sur la ROM de diagnostic du BricoNeo. Une faiblesse de mon code de test de la VRAM et qu'il n'était pas super simple d'utilisation quand une erreur survenait.
Il écrivait l'adresse en défaut, la donnée attendue et la donnée lue dans la WRAM, demndant à l'utilisateur de dumper 3 words de celle-ci pour récupérer les infos de l'erreur.
Non seulement ce n'était pas pratique, mais en plus, ça impliquait d'avoir de la WRAM en état de marche; ce qui est en contradiction avec l'esprit du BricoNeo: faire du diagnostic de parties de la NeoGeo alors que presque rien ne fonctionne.
La dernière version en date contient donc un joli patch qui indique, comme avec les ROM NeoDiag et Unibios, toutes les infos nécessaires pour avancer dans le diagnostic.
Merci @ragefan, c'est top!
Un debugger sur NeoGeo!
Et voilà maintenant un développement qui m'a bouffé pas mal d'énergie pour un résultat à l'utilité discutable...
A la base, l'idée du BricoNeo est de comprendre ce qui se passe sur les cartes NeoGeo. Rien de plus frustrant que de devoir deviner ce qui se passe sur la machine à partir d'infos parcellaires.
Seulement voilà: quand on développe une ROM système, on n'a pas forcément les compétences, les outils ou l'environnement pour la debugger sous émulateur, comme on pourrait le faire pour un jeu vidéo basé sur une cartouche. Et moi, je voulais vraiment pouvoir debugger des choses!
Etant tombé par hasard sur le flag "Trace" du registre d'état du processeur 68000 dans une doc technique, je me suis mis en tête de comprendre comment il pouvait bien fonctionner.
Et voilà donc une ébauche de debugger, qui permet d'afficher l'état des registres, et l'emplacement mémoire de l'instruction en cours de lecture.
Ici, on voit en vis-à-vis le code compilé, à savoir un boucle, et la version en cours de debug sur un slot MVS via le BricoNeo. On voit que le code met la valeur 3 dans le registre D0, et le décrémente dans une boucle. La trace montre les valeurs successives de D0, jsuqu'à la bascule en négatif. OK, c'est un peu pratique, mais il faut savoir lire les opcodes sous forme hexadécimale. Et personnellement, je ne sais pas faire.
Je me suis donc lancé dans l'écriture d'un désassembleur pour le BricoNeo. Donc en C++ avec pour cible un microcontrôleur RP2040 et moins de 100ko de RAM. Spoiler alert: on ne peut pas utiliser grand chose d'existant, du genre MAME, parce que ça consomme beaucoup trop de RAM.
Le but de ce désassembleur n'est pas d'être méga rapide, mais de ne pas consommer d'espace de stockage ou de RAM.
Qu'à cela ne tienne => direction la doc technique du 68000 et je me suis tapé l'intégralité des opcodes, et la (quasi?) totalité des modes d'adressage du 68000.
Résultat: c'est largement plus agréable de suivre l'exécution du programme comme ça! On voit l'instruction qui va être exécutée, et les instructions suivantes. C'est l'occasion d'observer les changements discrets faits par VASM, qui tranforme les JSR en BSR, le fourbe! (il a raison).
Un debugger UTILISABLE sur NeoGeo!
Hier après-midi, je me suis dit que debugger de la ROM système perso, c'est cool, mais que ce serait encore plus cool de pouvoir debugger une ROM Système SNK ou un Unibios.
J'ai regardé comment étaient déclarés les vecteurs d'interruptions de trace, et il semblerait que toutes les ROM système et certains jeux (je n'ai pas fait de stats, mais KOF97 le fait, évidemment) déclarent ce vecteur de trace. C'est très probablement un vestige du développement des jeux.
En gros, pour faire de la trace, il faut 3 choses:
- Une entrée dans le vecteur d'interruption de trace, dans la ROM système ET dans la ROM des jeux (sinon on ne peut plus tracer à partir de l'instant où la ROM système fait un bank switching des vacteurs sur ceux de la cartouche #charabia)
- Du code stub pour gérer l'interruption et dans mon cas l'échange avec le BricoNeo
- Le plus important: du code quelque part qui active le mode trace du 68000 en bricolant le registre d'état du processeur.
Quand je bosse sur une ROM à moi, pas de souci: j'ai un petit fichier assembleur "Trace.s" à ajouter au projet, qui produit les 174 octets de code nécessaires aux échanges 68000-BricoNeo pour faire de l'exécution pas à pas. J'ajoute une référence à la routine de trace dans les vecteurs d'interruption de la ROM, et j'utilise une macro "Breakpoint" qui se contente de basculer le flag Trace du 68000.
Mais ici, on n'est plus à la maison. Je n'ai pas la main sur les vecteurs, ce n'est pas mon code qui tourne dans la ROM (donc ma routine de trace n'est pas dedans), et les jeux n'activent pas naturellement le flag Trace!
La réponse technique version rapide (je peux développer si quelqu'un suit encore):
- Les ROM système courantes (SNK ou Unibios, celui-ci étant un hack d'une ROM SNK) définissent toutes un vecteur de trace. Certains jeux le font aussi (je n'ai pas de stats, mais ce bon vieux KOF97 le fait). Il pointe toujours vers la même adresse dans la ROM. A cette adresse, il y a du code qui n'est jamais joué pour le commun des mortels, je n'ai pas regardé ce qu'il faisait, mais il commence par faire un saut quelque part dans le code de la ROM. Je vais donc me brancher sur ce saut, et le patcher pour qu'il arrive dans ma routine à moi!
- OK, mais où je la colle, ma routine de trace? Eh bien les ROM système contienent des tables de références (ou Lookup tables, ou LUT). Il y en a plusieurs, avec des valeurs en dur pour faire plein de trucs: des rampes de valeurs non linéaires, des tables de sinus, et des listes de nombres pseudo-aléatoires. C'est cette dernière qui m'intéresse: elle fait 256 octets et elle contient naturellement n'importe quoi. C'est donc un bonne candidate pour contenir ma routine de 174 octets!
- D'accord, donc on a un vecteur d'interruption qui pointe sur notre routine d'interruption. Mais comment on la déclenche, cette interruption? Eh bien pour ça, on regarde vers quoi pointe le vecteur de l'interruption RESET. Ca nous amène au code exécuté au démarrage de la machine. Là, on trouve systématiquement comme première instruction.... la configuration du registre d'état du 68000! Il suffit donc de patcher cette première instruction pour activer le registre de trace!
- Mais alors on doit patcher les ROM système qu'on utilise? C'est pas super pratique...? => Non, le BricoNeo le fait tout seul à la volée quand on lui demande de passer en mode debug. Il reconnait la ROM qu'il a en face de lui et la patche directement en mémoire. Ca donne la séquence suivante, sur laquelle on observe le patchage et le démarrage du debug sur un Unibios + KOF97
BricoNeo, ça sert à réparer : une sonde logique fréquence-mètre
Un autre développement, nettement moins énergivore, mais nettement plus utile pour les bricoleurs réparateurs diagnostiqueurs: un semblant de sonde logique / fréquence-mètre. L'idée étant de pouvoir contrôler facilement les fréquences fournies par les différentes puces, et de contrôler l'activité sur les différentes lignes de bus ou d'activation de puces, le tout sans utiliser d'oscilloscope. C'est forcément moins bien, parce que ça ne montre pas les conflits de bus, mais c'est bien moins cher aussi

L'idée est ici d'utiliser une section PIO (Programmable Input/Output) inutilisée par le BricoNeo dans le cadre de son émulation de ROM pour faire des trucs cool avec. Etant donné qu'on ne peut pas vraiment faire de debug des programmes PIO et que le langage est un peu barbare, je me retourne vers le super outil Wokwi, qui permet de faire des tests de conception en ligne et de tracer l'activité des registres des machines à état des PIO.
Ici, j'injecte une fréquence en PWM sur une broche du RP2040, et j'essaie de compter combien de pulsations par seconde elle reçoit.

Une fois que j'ai quelque chose qui semble fonctionner, je porte le code sur le BricoNeo, et je m'aperçois que je ne peux pas compter de fréquence au-dessus de 23MHz avec ce code. Manque de bol, la NeoGeo a une horloge principale qui tourne à 24MHz!
Quelques gros mots et pas mal de grattage de tête plus tard, je trouve une nouvelle manière de compter et je peux monter aux alentours de 60MHz (je crois, j'ai oublié). En tout cas, je peux monter plus haut que la fréquence max du système.
L'idée est alors de brancher une sonde (un fil) sur la broche "IN" du BricoNeo née pour ça (merci @illusionrip pour la jolie photo). Cette entrée utilise une entrée libre sur la puce OR compatible 5V du BricoNeo. Celle-ci sert à la base à générer l'interruption READ lorsque les broches /CE et /OE de l'EPROM émulée sont activées #charabia.

En collant sa sonde sur n'importe quoi qui ne tourne pas en 12V (section audio) parce qu'on n'a pas envie de tout cramer, on a un rendu instantané de la vitesse observée, dans le terminal connecté au BricoNeo.
Quand on détecte une très basse fréquence, on décide qu'il s'agit d'une tention constante et on affiche l'état de la broche (HIGH ou LOW, c'est le côté sonde logique).
Voilà ma super sonde et je pointe sur n'importe quelle patte au hasard d'une puce de fast RAM. Easy:

L'ami @illusionROM nous fait une démo plus convaincante, avec le relevé de fréquence du quartz d'une AES. Les AES ont une fréquence un poil plus élevée que les 24MHz des MVS pour faire les précieuses (et pour la génération du signal NTSC?). Voilà le relevé du BricoNeo: Et celui de son oscilloscope, on n'est pas super loin! La précision va dépendre largement de la qualité du résonateur présent sur la carte BricoNeo. Je n'ai pas mis du premier prix, mais le but initial n'était pas non plus de se synchroniser avec un satellite, donc ça vaut ce que ça vaut

Un nouveau BricoNeo?
Voilà, et pour finir, j'ai bossé sur la re-conception du PCB du BricoNeo pour passer d'un microcontrôleur RP2040 au nouveau modèle RP2354, principalement dans le but d'avoir plus de RAM disponible pour gérer plus facilement la partie mass storage du BricoNeo, qui est actuellement un sac de noeuds.
Le RP2354 (toujours chez Raspberry Pi) a 4 broches de plus que le RP2040, mais il a surtout une gestion de l'alimentation très différente qui oblige à intéger de nouveaux composants sur le peu d'espace dont je dispose! J'ai choisi la variante 2354 parce qu'elle intègre 2Mo de mémoire flash sur la même puce que le microcontrôleur (ils ont superposé les dies #charabia). Ca me libère un peu de place pour mettre les composants supplémentaires.
Je suis arrivé à un design qui pourrait fonctionner, mais........ la puce n'est pas disponible sur le marché. Elle devrait l'être depuis plusieurs mois, mais je l'attends toujours. Et notamment chez LCSC, qui fournit les composants pour l'assemblage de la partie supérieure de la carte chez JLCPCB.
Résultat: pour le moment, il va falloir faire avec seulement une image de la nouvelle carte!
