Aller au contenu
Phosphoricwiki
Sommaire

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).

CommandeEffet
s, n, cune instruction, une instruction sans entrer dans les JSR, continuer
step-outaller jusqu’au retour de la routine en cours
undorevenir en arrière : jusqu’à 16 instantanés du processeur et de la RAM
r, set reg valvoir 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 EXPRpoint d’arrêt (16 au plus), éventuellement conditionnel
br LIGNEpoint d’arrêt raster : quand le faisceau atteint une ligne (8 au plus)
w ADRpoint d’observation en écriture (8 au plus)
via, psg, disk, acia, tape, locil’état des périphériques
stackla 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

OptionCe qu’elle écrit
--trace FICHIERune ligne par instruction : cycles, PC, octets, désassemblage, registres
--cycle-trace FICHIERune ligne par cycle : type d’accès, adresse, donnée, registres, lignes d’interruption
--psg-trace FICHIERchaque écriture dans un registre du PSG, avec son cycle
--serial-trace FICHIERles octets émis et reçus, et les signaux du port série
--kbd-scan-trace FICHIERchaque lecture du port B du VIA : pour déboguer un programme qui balaie le clavier lui-même
--profile FICHIERpassages 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:FICHIERles 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 :

SensPréfixeRôle
client → émulateuraucunune commande par ligne
émulateur → clientOK ou ERRla réponse
émulateur → clientEVTun é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êteEffet
GET /hello, /regs, /mem?addr=&len=, /peek/vialire
POST /keys avec text=…taper au clavier : un programme BASIC entier, à distance
POST /reset, /nmi, /exec/step, /exec/continue, /exec/pauseagir
POST /tape, /disk/A ; DELETE /tape, /disk/Achanger de média
POST /break, /watch, /raster, /state/save, /tracedé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 FICHIER et --replay FICHIER enregistrent 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:FICHIER capture quand le programme atteint un état (code de sortie 2 s’il ne l’atteint jamais).
  • --ula-ng-poke et --type-keys-when préparent la machine sans deviner le bon cycle.

C’est exactement ainsi que les images de la galerie ont été faites.

Sources dans le dépôt : README.md, docs/gdb_remote.md, docs/control_protocol.md, docs/http-api.md, docs/movie_replay.md.