Déboguer et piloter
Phosphoric n’est pas seulement une machine pour jouer : c’est un banc pour comprendre un programme 6502. Points d’arrêt, retour en arrière, gdb branché sur l’Oric, et une API pour tout piloter de l’extérieur.
Dans cette page
Le débogueur intégré
On y entre par F9 pendant l’émulation, par -D (--debug) au lancement, ou sur un point d’arrêt
(--break ADR).
| Commande | Effet |
|---|---|
s, n, c | une instruction, une instruction sans entrer dans les JSR, continuer |
step-out | aller jusqu’au retour de la routine en cours |
undo | revenir en arrière : jusqu’à 16 instantanés du processeur et de la RAM |
r, set reg val | voir et modifier les registres |
d [adr] [n] | désassembler, avec les symboles résolus dans les opérandes |
m adr [n] | voir et modifier la mémoire |
a ADR MNÉMONIQUE [opérande] | assembler une instruction en mémoire |
find B1 B2 …, find "texte" | chercher en mémoire |
b ADR, b ADR if EXPR | point d’arrêt (16 au plus), éventuellement conditionnel |
br LIGNE | point d’arrêt raster : quand le faisceau atteint une ligne (8 au plus) |
w ADR | point d’observation en écriture (8 au plus) |
via, psg, disk, acia, tape, loci | l’état des périphériques |
stack | la pile |
--symbols FICHIER charge une table de symboles (formats .sym, .lab, EQU, VICE) : le
désassembleur et les traces les affichent.
En mode texte
Construit avec TUI=1 et lancé avec --tui, le débogueur s’affiche dans un terminal, en six
panneaux : registres, pile, désassemblage, mémoire, points d’arrêt et d’observation, état.
gdb, lldb, VS Code
--gdb[=PORT] ouvre un serveur GDB Remote Serial Protocol (port 1234 par défaut). On y attache
gdb, lldb ou un environnement de développement :
./oric1-emu -r roms/basic11b.rom --gdb
gdb -ex 'target remote :1234'
(gdb) info registers # A X Y SP PC P
(gdb) x/8xb 0xfffc # les vecteurs
(gdb) break *0xc000
(gdb) stepi
(gdb) set {char}0x0400 = 0xa9
La machine démarre arrêtée au vecteur de reset ; c’est gdb qui pilote. gdb ne connaît pas
l’architecture mos6502 et peut le signaler, mais mémoire, points d’arrêt et pas à pas fonctionnent ;
le serveur décrit ses registres par target.xml.
Les traces et le profileur
| Option | Ce qu’elle écrit |
|---|---|
--trace FICHIER | une ligne par instruction : cycles, PC, octets, désassemblage, registres |
--cycle-trace FICHIER | une ligne par cycle : type d’accès, adresse, donnée, registres, lignes d’interruption |
--psg-trace FICHIER | chaque écriture dans un registre du PSG, avec son cycle |
--serial-trace FICHIER | les octets émis et reçus, et les signaux du port série |
--kbd-scan-trace FICHIER | chaque lecture du port B du VIA : pour déboguer un programme qui balaie le clavier lui-même |
--profile FICHIER | passages et cycles par adresse, histogramme des opcodes, 20 points chauds |
--rom-info [FICHIER] | une ROM analysée : vecteurs, sous-programmes, chaînes, code et données |
--dump-ram-when ADR:VAL:FICHIER | les 64 Ko quand une case mémoire prend une valeur |
Piloter de l’extérieur : --control
Avec --control, Phosphoric parle un protocole texte sur son entrée et sa sortie standard (les
journaux vont sur la sortie d’erreur). Il a été conçu pour l’environnement de développement
OricForge. Trois genres de messages :
| Sens | Préfixe | Rôle |
|---|---|---|
| client → émulateur | aucun | une commande par ligne |
| émulateur → client | OK ou ERR | la réponse |
| émulateur → client | EVT | un événement spontané : ready, stopped, halt |
Les commandes : hello (négociation des capacités), regs, set, read, bread (binaire),
write, peek (un périphérique), break, watch, raster, step, next, step-out,
continue, pause (même en marche), reset, nmi, load-tap, load-rom, load-sym,
load-disk, eject-disk, disasm, keys, hunt (chercher une valeur qui change),
state-save, state-load, et d’autres. Tous les nombres sont en hexadécimal, longueurs
comprises.
Un client de démonstration en Python, sans dépendance, est fourni
(tests/integration/phos_smoke_client.py).
Piloter par HTTP
Construit avec HTTPAPI=1, --http-api[=PORT] (8888 par défaut) expose les mêmes commandes en
HTTP et JSON, sans dupliquer la logique :
| Requête | Effet |
|---|---|
GET /hello, /regs, /mem?addr=&len=, /peek/via | lire |
POST /keys avec text=… | taper au clavier : un programme BASIC entier, à distance |
POST /reset, /nmi, /exec/step, /exec/continue, /exec/pause | agir |
POST /tape, /disk/A ; DELETE /tape, /disk/A | changer de média |
POST /break, /watch, /raster, /state/save, /trace | déboguer |
curl -X POST --data-urlencode 'text=PRINT 2+2\n' http://127.0.0.1:8888/keys
Les réponses sont en JSON ({"ok":true,"reply":…}), avec CORS. Les opérations sur les fichiers sont
cantonnées à --http-api-root DOSSIER : chemins absolus et .. refusés. Les commandes s’exécutent
dans le fil de l’émulateur, à la frontière de trame (décision 0002).
Automatiser sans affichage
Toutes ces briques se combinent sans fenêtre :
# Charger, attendre, taper, capturer, enregistrer le son, puis sortir
./oric1-emu --headless -r roms/basic11b.rom -t prog.tap -f \
--type-keys '3000000:RUN\n' --screenshot-at 20000000:fin.png \
--audio-wav son.wav --cycles 20100000
--record FICHIERet--replay FICHIERenregistrent et rejouent les entrées du clavier, au bit près : de quoi reproduire un défaut ou tenir un test de régression.--screenshot-when ADR:VAL:FICHIERcapture quand le programme atteint un état (code de sortie 2 s’il ne l’atteint jamais).--ula-ng-pokeet--type-keys-whenpréparent la machine sans deviner le bon cycle.
C’est exactement ainsi que les images de la galerie ont été faites.