Systeme de fichiers ROM (RFS) — Guide du developpeur

Guide du developpeur RFS

Ce guide est un parcours detaille du code source RFS et de l'environnement de developpement. Il explique les concepts du langage assembleur Z80 pour les developpeurs qui ne sont peut-etre pas familiers avec ce langage, parcourt chaque module source, documente l'architecture de commutation de banque et montre comment ajouter de nouvelles commandes, modifier des modules existants et porter RFS sur un nouveau materiel.
Pour les details de l'architecture materielle et du systeme de build, voir le Guide technique. Pour l'utilisation quotidienne, voir le Manuel utilisateur.

Introduction a l'assembleur Z80 pour les non-assembleurs

Le firmware RFS est entierement ecrit en langage assembleur Z80 — le langage d'instructions natif du processeur Zilog Z80 utilise dans la serie Sharp MZ. Contrairement aux langages de haut niveau, l'assembleur correspond presque directement au materiel physique : chaque instruction se traduit par un ou quelques octets que le processeur execute directement.

Registres
Le Z80 n'a pas de "variables" — il dispose plutot d'un petit ensemble de registres (emplacements de stockage rapides a l'interieur du processeur). Les plus couramment utilises dans RFS :
Registre Taille Role
A 8 bits Accumulateur — le registre principal pour les operations arithmetiques, logiques et d’E/S. Presque chaque instruction fait intervenir A.
B, C 8 bits Usage general. BC ensemble forme une paire 16 bits, couramment utilisee comme compteur de boucle ou nombre d’octets.
D, E 8 bits Usage general. DE ensemble est une paire 16 bits, couramment utilisee comme pointeur source ou destination.
H, L 8 bits Usage general. HL ensemble est le pointeur memoire 16 bits principal — la plupart des instructions de lecture/ecriture memoire utilisent HL.
IX, IY 16 bits Registres d’index — utilises pour l’adressage memoire base+offset. Plus lents que HL mais pratiques pour les donnees structurees.
SP 16 bits Pointeur de pile — pointe vers le sommet de la pile d’appels. PUSH et POP utilisent SP automatiquement.
PC 16 bits Compteur de programme — l’adresse de l’instruction courante. Incremente automatiquement ; modifie par les sauts et les appels.
F 8 bits Registre de drapeaux — bits individuels definis par les operations arithmetiques : Z (zero), C (retenue), S (signe), P/V (parite/depassement).

Instructions cles
  • LD dest, src — Charge (copie) des donnees. LD A, B copie B dans A. LD A, (HL) lit dans A l'octet a l'adresse memoire contenue dans HL. LD (0x1200), A ecrit A a l'adresse memoire 0x1200.
  • CALL addr — Appelle une sous-routine. Empile l'adresse de retour (instruction suivante) et saute vers addr. Equivalent a un appel de fonction.
  • RET — Retour de sous-routine. Depile l'adresse de retour et y saute.
  • JP addr — Saut inconditionnel vers addr. JP Z, addr ne saute que si le drapeau Zero est positionne (c.-a-d. que la derniere operation a produit zero).
  • JR offset — Saut relatif court (-128 a +127 octets). Plus rapide et plus compact que JP pour les branchements proches.
  • DJNZ offset — Decremente B et saute si non zero (Not Zero). L'instruction de boucle canonique du Z80 : LD B, 10 / LOOP: ... / DJNZ LOOP se repete 10 fois.
  • ADD A, n — Ajoute n a A. SUB n soustrait. AND n, OR n, XOR n — logique bit a bit sur A.
  • IN A, (port) — Lit depuis un port d'E/S dans A. OUT (port), A — ecrit A vers un port d'E/S. C'est ainsi que le Z80 communique avec le materiel (le WD1773, le controleur SPI, le verrou de banque, etc.).
  • PUSH rr / POP rr — Sauvegarde/restaure une paire de registres 16 bits vers/depuis la pile.
  • EI / DI — Active / Desactive les interruptions. Le code qui ne doit pas etre interrompu (par ex. les operations de bande temps-critiques) est encadre par DI et EI.

Modes d'adressage
Le Z80 offre plusieurs facons de specifier la provenance ou la destination des donnees :
  • Immediat : LD A, 42 — la valeur est integree dans les octets de l'instruction eux-memes.
  • Registre : LD A, B — les donnees proviennent d'un registre ou y vont.
  • Indirect (via HL) : LD A, (HL) — HL contient une adresse memoire ; les donnees sont lues depuis cette adresse.
  • Etendu (adresse directe) : LD A, (0x1200) — l'adresse est une constante 16 bits litterale dans l'instruction.
  • Indexe : LD A, (IX+5) — IX contient une adresse de base ; 5 est ajoute pour obtenir l'adresse effective. Utilise dans RFS pour acceder aux champs de structures de donnees a format fixe.

Syntaxe de l'assembleur GLASS
RFS utilise l'assembleur GLASS Z80. Caracteristiques cles de la syntaxe :
  • Les commentaires commencent par ; — tout ce qui se trouve a droite d'un point-virgule est ignore.
  • Les labels sont des identifiants suivis de :. Un label en debut de ligne nomme l'adresse de l'instruction suivante.
  • EQU definit une constante : BELL EQU 007H — l'assembleur remplace chaque occurrence de BELL par 0x07.
  • DB (Define Byte) insere des octets bruts : DB 0x41, 0x42 emet deux octets. Utilise pour les chaines et les tables de correspondance.
  • DW (Define Word) insere des valeurs 16 bits en little-endian : DW HANDLER emet l'adresse du label HANDLER.
  • ORG addr definit l'origine d'assemblage — le code suivant est assemble comme s'il residait a addr.
  • INCLUDE "file.asm" inclut textuellement un autre fichier a la position courante.
  • IF / ENDIF assemblage conditionnel : IF BUILD_SFD700 = 1 ... ENDIF — les instructions encadrees ne sont assemblees que lorsque la condition est vraie. C'est ainsi que RFS construit quatre variantes de firmware differentes a partir d'une seule arborescence source.

Arborescence des sources

Chemin Contenu
asm/ Tous les fichiers source assembleur Z80
asm/include/ Definitions et fichiers de configuration partages
asm/dis/ Fichiers de reference desassembles pour SA-5510 et XPATCH
tools/ Scripts de build, assembleur GLASS, binaires utilitaires
MZF/ Fichiers d’application au format MZF, organises par type de machine
MZB/ Applications binaires alignees par secteur (generees par le build)
roms/ Sortie du build — images ROM et images de carte SD
releases/ Binaires de release preconstruits
config/ Definitions de format de disque CP/M (diskdefs)
cpmtools/ Source cpmtools (sous-module)
src/ Source des outils de support

Configuration : rfs_definitions.asm

C'est le fichier de configuration central, inclus par chaque autre fichier source via INCLUDE "rfs_definitions.asm". Toutes les options a la compilation sont controlees ici. Les sections cles :

Indicateurs de build cible
HW_SPI_ENA    EQU 1    ; 1 = hardware SPI on RomDisk v2+ PCB
SW_SPI_ENA    EQU 0    ; 1 = software bit-bang SPI (RomDisk v1)
PP_SPI_ENA    EQU 0    ; 1 = SPI via parallel port (RomDisk v1 alternative)
FUSIONX_ENA   EQU 0    ; 1 = running on tranZPUter FusionX
KUMA80_ENA    EQU 0    ; 1 = Kuma 40/80 upgrade present
VIDEOMODULE_ENA EQU 0  ; 1 = 40/80 colour video module present
BUILD_ROMDISK EQU 0    ; 1 = build for RomDisk card
BUILD_SFD700  EQU 0    ; 1 = build for SFD-700 floppy interface
BUILD_PICOZ80 EQU 1    ; 1 = build for picoZ80 board
ENADEBUG      EQU 0    ; 1 = enable debug output during assembly
Exactement un indicateur BUILD_* doit etre mis a 1 a la fois. Tous les blocs d'assemblage conditionnel a travers la source testent ces indicateurs pour inclure ou exclure le code specifique a la plateforme.

Constantes d'adresse
UROMADDR    EQU 0E800H   ; Base address of the User ROM window
UROMBSTBL   EQU UROMADDR + 020H   ; Bank-switch table entry point (fixed offset)
RFSJMPTABLE EQU UROMADDR + 0B0H   ; RFS jump table start
FDCROMADDR  EQU 0F000H   ; FDC ROM address (SFD-700 MROM location)

; SFD-700 specific bank defaults (only assembled when BUILD_SFD700 = 1):
BNKDEFMROM_MZ80A EQU 0   ; Default MROM bank for MZ-80A (AFI ROM)
BNKDEFMROM_MZ700 EQU 1   ; Default MROM bank for MZ-700 (AFI ROM)
BNKDEFUROM       EQU 2   ; Default UROM bank for RFS (starts at 8KB in Flash)
Ces constantes definissent ou se situe chaque fenetre de ROM dans l'espace d'adressage du Z80. Le code compile pour la fenetre User ROM s'assemble toujours avec ORG 0xE800 ; le code pour la fenetre Monitor ROM s'assemble a ORG 0x0000.

Definitions de caracteres et de controle
Les caracteres de controle ASCII standard sont definis comme des constantes nommees afin de rendre la source auto-documentee :
BELL    EQU 007H    ; Terminal bell
CR      EQU 00DH    ; Carriage return
LF      EQU 00AH    ; Line feed
CS      EQU 00CH    ; Clear screen
SPACE   EQU 020H    ; ASCII space
DELETE  EQU 07FH    ; Delete key

Commutation de banque en detail

La commutation de banque est au coeur de l'architecture RFS. La comprendre est essentiel avant de modifier le moindre fichier source.

Pourquoi la commutation de banque est necessaire
Le Sharp MZ-80A ne donne a la User ROM que 2 Ko d'espace d'adressage (0xE800-0xEFFF). 2 Ko ne peuvent contenir que quelques centaines d'instructions — loin d'etre suffisant pour un systeme de fichiers, un assembleur, un desassembleur, un controleur de bande, un pilote de carte SD et un CBIOS CP/M. La solution consiste a commuter physiquement quels 2 Ko d'une puce Flash de 512 Ko sont visibles dans cette plage d'adresses. En stockant 12 banques RFS de 2 Ko differentes (banques 0-11) dans la puce Flash et en commutant entre elles a la demande, RFS atteint effectivement 24 Ko de code ROM — avec 4 banques supplementaires (12-15) reservees au CBIOS CP/M. En outre, trois des 16 pages de Monitor ROM (banques 6, 7 et 9) contiennent les tables d'opcodes de l'assembleur/desassembleur Z80 et les chaines de messages RFS, etendant l'espace ROM disponible sans consommer de capacite User ROM.

Le stub de commutation de banque
Chaque banque commence par une copie identique du stub de commutation de banque qui occupe les 32 premiers octets de la banque (0xE800-0xE81F). Ce stub fournit :
  • Une passerelle d'appel standard : toute banque peut appeler n'importe quelle routine dans n'importe quelle autre banque en appelant le stub avec le numero de banque cible et l'adresse cible. Le stub ecrit le numero de banque dans le verrou materiel (typiquement une ecriture sur port d'E/S), puis appelle l'adresse demandee. La routine appelee s'execute dans la nouvelle banque, et lorsqu'elle retourne, le stub recommute vers la banque d'origine.
  • Un point d'entree coherent : parce que le stub se trouve a un offset fixe (0xE800 + 0x20 pour la table de commutation de banque), le code de la banque 0 peut trouver de maniere fiable le stub de la banque 3 meme s'il n'a jamais vu les adresses internes de la banque 3.
Le verrou code des cartes RomDisk v2+ ajoute un mecanisme de protection : le registre de verrou de banque ne devient inscriptible qu'apres que le processeur a lu un certain nombre de fois consecutives dans les 8 octets superieurs de l'espace User ROM (0xEFF8-0xEFFF). Cela evite les commutations de banque accidentelles causees par du code parasite qui ecrirait par hasard a l'adresse du verrou. Le stub gere cette sequence de deverrouillage avant chaque commutation de banque.

Format de la table de commandes (rfs.asm)
Le dispatcher de commandes du moniteur dans rfs.asm utilise une table de commandes compacte. Chaque entree decrit une commande et est disposee comme suit :
; One command table entry:
;
;   DB  FLAGS          ; 1 byte: END|MATCH|BANK[5:3]|SIZE[2:0]
;   DB  "COMMAND"      ; SIZE bytes: the command string (no null terminator)
;   DW  HANDLER_ADDR   ; 2 bytes: address of the handler routine in the named bank
;
; Flags byte:
;   Bit 7 = 1: End of table marker (last entry).
;   Bit 6 = 1: Exact match required (command must be entire input, no trailing chars).
;   Bits 5:3   Bank number where HANDLER_ADDR lives (0-11 for RFS, 12-15 for CBIOS).
;   Bits 2:0   Length of the command string in bytes.
;
; Example - the ASM command (all builds, lives in bank 6, 3-char string):
CMDTABLE:
    DB  000H | 000H | 030H | 003H    ; FLAGS: not-end, not-exact, bank 6, length 3
    DB  "ASM"                         ; Command string
    DW  ASM_MAIN                      ; Handler address in bank 6
Le dispatcher lit la ligne de saisie du moniteur, parcourt la table, et pour chaque entree :
  1. Compare la saisie a la chaine de commande (insensible a la casse sur certains builds).
  2. Si elle correspond, extrait le numero de banque et l'adresse du handler depuis l'entree de la table.
  3. Effectue une commutation vers la banque cible.
  4. Appelle le handler avec toute saisie restante (parametres) disponible dans le tampon de saisie du moniteur.
Deux tables de commandes distinctes existent : CMDTABLE2 pour le build SFD-700, et CMDTABLE pour le build RomDisk/picoZ80. Les deux sont structurees de maniere identique mais contiennent des jeux de commandes differents — notamment la table SFD-700 exclut les commandes de carte SD (IC, LC, SC, EC, DUC, T2SD, SD2T) puisque ce materiel n'a pas de carte SD. Les commandes ASM et DASM sont presentes dans les deux tables.

Parcours des modules

rfs.asm — Dispatcher de commandes (User ROM banque 0)
Role : le point d'entree de toutes les fonctionnalites RFS. Lorsque le moniteur SA-1510 ne reconnait pas une commande, il transfere le controle au point d'entree de la User ROM a 0xE800. C'est toujours la banque 0.
Sections cles :
  • Stub de commutation de banque (0xE800-0xE81F) : la passerelle d'appel inter-banques decrite ci-dessus. Chaque banque en possede une copie identique.
  • Table de commutation de banque (0xE800 + 0xB0) : une table de saut qui associe les numeros de banque a leurs adresses physiques en Flash ROM. Modifiee au demarrage si le materiel requiert un adressage de banque non sequentiel.
  • Table de commandes (CMDTABLE / CMDTABLE2) : la liste de toutes les commandes RFS avec leur banque et l'adresse de leur handler.
  • Boucle principale du dispatcher : lit le tampon de saisie du moniteur, parcourt la table de commandes, effectue la commutation de banque et appelle le handler. Si aucune commande ne correspond, retourne au moniteur SA-1510 afin qu'il affiche l'erreur "?".
  • Initialisation RFS : a la premiere entree apres un reset, RFS detecte la plateforme materielle (depuis le registre MODE sur SFD-700, ou depuis les indicateurs sur RomDisk), initialise le SPI et la carte SD, et fixe le lecteur initial a 0.
Note SFD-700 : lorsque BUILD_SFD700 = 1, rfs.asm s'assemble avec ORG 0xE000 / ALIGN 0xE300 plutot que ORG 0xE800, car le SFD-700 place sa fenetre User ROM a 0xE300-0xEFFF (0xE000-0xE2FF etant reserve aux E/S mappees en memoire du MZ-700).

rfs_bank1.asm — Controleur de disquette (User ROM banque 1)
Role : implemente les commandes de disquette — amorcage disquette (F / FL), repertoire disquette (FD) et le saut AFI direct (f). Le jeu complet de commandes FDC est assemble sur tous les builds.
Fonctions cles :
  • FLOPPY (FL) : demande un numero de lecteur (s'il n'est pas fourni sur la ligne de commande), initialise le disque, lit le secteur d'amorcage, verifie la signature du disque, extrait les informations du programme (nom, adresse de chargement, taille, adresse d'execution), charge le programme en memoire et l'execute.
  • FDDIR (FD) : liste le repertoire des fichiers d'une disquette. Accepte un numero de lecteur optionnel (1-4, par defaut 1). Lit le secteur d'amorcage, verifie le format de disque MZ-700, puis parcourt les secteurs de repertoire en affichant noms de fichiers, adresses de chargement, adresses d'execution et tailles de fichiers.
  • FDCK : lit l'octet a 0xF000 pour verifier que l'AFI ROM est presente et non nulle, puis appelle directement 0xF000. C'est la commande f (minuscule) sur tous les builds.
  • A la fin de la banque, une directive ALIGN 0xF000 garantit que l'image ROM du SFD-700 positionne l'AFI boot ROM precisement a 0xF000 dans l'agencement de la Flash.

rfs_bank2.asm — Controleur de carte SD (User ROM banque 2)
Role : le sous-systeme complet de carte SD — initialisation SPI, protocole de commande de carte SD, et les routines de repertoire et d'E/S de fichiers SDCFS. Sur le build SFD-700, le code du controleur de carte SD n'est pas assemble (le materiel SFD-700 n'a pas d'interface de carte SD) ; l'emplacement de banque est present dans l'image ROM mais ne contient que le stub de commutation de banque.
Fonctions cles :
  • Pilote SPI (materiel ou logiciel) : l'assemblage conditionnel choisit entre le SPI materiel (utilisant les registres du controleur SPI du RomDisk v2) et le SPI logiciel en bit-bang (basculement de bits de port d'E/S individuels pour cadencer le bus SPI). Le chemin SPI materiel est nettement plus rapide et utilise sur toutes les cartes actuelles (HW_SPI_ENA = 1).
  • Initialisation de carte SD (SDINIT) : implemente la sequence d'initialisation de carte SD — envoie CMD0 (GO_IDLE), CMD8 (SEND_IF_COND), ACMD41 (SD_SEND_OP_COND) pour faire passer la carte du mode SPI a l'etat actif. Gere les types de cartes SD et SDHC/SDXC en verifiant la reponse OCR.
  • Lecture de secteur (SDREAD) : envoie CMD17 (READ_SINGLE_BLOCK) avec une adresse de secteur 32 bits, attend le jeton de debut de donnees (0xFE), puis lit 512 octets dans un tampon RAM du Z80. Utilise le mode rafale du SPI materiel lorsqu'il est disponible.
  • Ecriture de secteur (SDWRITE) : envoie CMD24 (WRITE_BLOCK), le jeton de debut de donnees, 512 octets de donnees et le CRC. Attend la reponse d'ecriture et l'effacement du signal d'occupation.
  • Lecture du repertoire SDCFS (SDDIR) : lit le repertoire depuis les 8 premiers Ko de l'image du lecteur actif et construit un cache de repertoire resident en RAM utilise par les commandes IC, LC, SC et EC.
  • Chargement de fichier SDCFS (SDLOAD) : a partir d'un numero de fichier du repertoire, calcule l'adresse de secteur du bloc de 64 Ko du fichier, lit le nombre d'octets correspondant a la taille reelle du fichier et les charge a l'adresse Z80 specifiee dans le champ LOAD ADDR de l'entree de repertoire.
  • Sauvegarde de fichier SDCFS (SDSAVE) : alloue un nouvel emplacement de repertoire (ou trouve une entree existante de meme nom a ecraser), fixe les champs START SECTOR, SIZE, LOAD ADDR et EXEC ADDR, puis ecrit les donnees du fichier dans le bloc de 64 Ko approprie.

rfs_bank3.asm — Utilitaires memoire (User ROM banque 3)
Role : implemente les commandes D (dump hexadecimal), M (edition memoire), CP (copie memoire), IN (lecture de port d'E/S) et OUT (ecriture de port d'E/S), disponibles sur tous les builds. Les commandes DUC (dump de fichier carte SD), T2SD (bande vers SD) et SD2T (SD vers bande) sont egalement implementees ici mais ne sont assemblees que pour les builds RomDisk / picoZ80 — le build SFD-700 les exclut faute de carte SD.
Dump hexadecimal (D) : lit jusqu'a 20 lignes de 16 octets chacune dans la plage d'adresses cible. Pour chaque ligne il affiche l'adresse hexadecimale a 4 chiffres, 16 valeurs d'octets en hexadecimal (avec un espace tous les 4 octets) et les 16 caracteres ASCII (en utilisant un point pour les octets non imprimables). Le Sharp MZ utilise un encodage de caracteres inhabituel — la banque 5 fournit la table de conversion Sharp vers ASCII utilisee ici.
Editeur memoire (M) : presente chaque octet a tour de role, en affichant l'adresse et la valeur courante. L'utilisateur peut taper une nouvelle valeur hexadecimale (1 ou 2 chiffres) et appuyer sur Entree pour l'ecrire, ou appuyer sur Entree seule pour la laisser inchangee. Appuyer sur Ctrl+C ou une sequence d'echappement specifique permet de quitter.
Commandes de port d'E/S (IN / OUT) : IN lit un ou plusieurs ports d'E/S Z80 (adresses a 2 ou 4 chiffres hexadecimaux, separees par des virgules) en utilisant IN A,(C) et affiche chaque valeur en hexadecimal a 2 chiffres. OUT ecrit vers un ou plusieurs ports — chaque entree est une adresse de port suivie d'un deux-points et d'une valeur hexadecimale a 2 chiffres (par ex. OUTD0:01,D1:80), executee avec OUT (C),A. Les deux commandes prennent en charge l'espace complet d'adressage des ports d'E/S Z80 sur 16 bits.
T2SD et SD2T : ces commandes effectuent une copie bidirectionnelle transparente entre la bande (CMT) et la carte SD. T2SD appelle la routine de chargement CMT de la banque 4 pour lire un fichier de bande en RAM, puis appelle la routine de sauvegarde SD de la banque 2 pour l'ecrire sur le lecteur actif. SD2T appelle la routine de chargement SD de la banque 2 pour placer le fichier en RAM, puis appelle la routine de sauvegarde CMT de la banque 4 pour l'ecrire sur bande. Les deux sens utilisent le repertoire SDCFS pour preserver noms de fichiers, tailles et adresses.

rfs_bank4.asm — Controleur CMT (User ROM banque 4)
Role : implemente les commandes de bande (CMT) L/LT, LTNX, S/ST et V.
Le Sharp MZ-80A utilise une interface cassette Kansas City Standard a 1200 bauds. Les octets sont encodes sous forme de bursts de tonalite a 1200 Hz (bit 0) ou 2400 Hz (bit 1). Les routines de bande sont temps-critiques — elles doivent lire ou ecrire chaque bit dans une fenetre de timing serree. Elles utilisent la puce timer 8253 (ou des boucles comptees en cycles processeur sur les plateformes sans le timer) pour mesurer la frequence de la tonalite entrante et generer la forme d'onde sortante. Les interruptions sont desactivees (DI) pendant toutes les operations de bande pour eviter toute perturbation du timing.
Le format de bande MZF prefixe chaque programme par un en-tete de 128 octets contenant le type de fichier, le nom de fichier, la longueur des donnees, l'adresse de chargement et l'adresse d'execution — les memes champs que ceux stockes dans l'entree de repertoire SDCFS. C'est pourquoi la copie SD<->bande est transparente : le format d'en-tete est identique.

rfs_bank5.asm — Fonctions utilitaires (User ROM banque 5)
Role : une bibliotheque de routines partagees appelees par les autres banques. Comme la commutation de banque est couteuse (elle requiert la sequence de deverrouillage sur les cartes v2+), les routines frequemment utilisees sont centralisees ici afin de minimiser le surcout de commutation.
Routines cles :
  • PRTHEX : affiche le registre A sous forme de deux chiffres hexadecimaux a l'ecran.
  • PRTHL : affiche le registre HL sous forme de quatre chiffres hexadecimaux.
  • PRTSTR : affiche a l'ecran une chaine terminee par null depuis (HL), en gerant la conversion d'encodage de caracteres Sharp.
  • INPHEX : lit un nombre hexadecimal (jusqu'a 4 chiffres) depuis le clavier, renvoyant la valeur dans HL.
  • STRCMP : compare deux chaines terminees par null.
  • SUBSTR : extrait une sous-chaine, utilisee par le dispatcher de commandes pour separer les noms de commandes des parametres.
  • WAITKEY : attend une frappe et renvoie le code de la touche dans A. Utilise pour les pauses "appuyez sur une touche pour continuer" dans les listings de repertoire IC et IR.

rfs_bank6.asm — Table d'opcodes ASM/DASM 1 (User ROM banque 6)
Role : stocke la premiere moitie des tables de correspondance d'opcodes Z80 utilisees a la fois par les commandes assembleur (ASM) et desassembleur (DASM), plus la fonction PRINTMSG et l'infrastructure des chaines de messages. Les tables d'opcodes font correspondre les chaines mnemoniques Z80 aux octets d'opcode et vice versa. L'assembleur et le desassembleur sont disponibles sur tous les builds (RomDisk, picoZ80, SFD-700 et FusionX).
La fonction PRINTMSG lit les chaines de messages depuis la banque MROM 9 vers un tampon RAM avant l'affichage, car les fonctions du moniteur ROM (PRNT, ?DSP, etc.) requierent que la banque MROM du moniteur soit active pendant la sortie de caracteres. La banque MROM 6 correspondante contient egalement des donnees de table d'opcodes dans l'espace de 4 Ko de la Monitor ROM, offrant de l'espace supplementaire pour le jeu d'instructions Z80 complet, y compris toutes les variantes a octet de prefixe (CB, DD, ED, FD).

rfs_bank7.asm — Table d'opcodes ASM/DASM 2, DASM, tests (User ROM banque 7)
Role : stocke la seconde moitie des tables de correspondance d'opcodes Z80, la routine principale du desassembleur DASM, le test DRAM R et le test timer T.
Desassembleur (DASM) : lit les octets de code machine depuis l'adresse cible, decode chaque instruction (a l'aide des tables d'opcodes des banques 6 et 7) et affiche l'adresse, les octets hexadecimaux et le mnemonique de chaque instruction. Gere tous les octets de prefixe Z80 (CB, DD, ED, FD) et les instructions etendues.
Test DRAM (R) : effectue une ecriture/verification a motif de bit glissant sur tout l'espace RAM utilisateur (0x1200-0xCFFF). Signale toute adresse en echec. Utile pour diagnostiquer des puces RAM defectueuses — un mode de panne courant sur les machines anciennes.

rfs_bank8.asm — Assembleur Z80 (User ROM banque 8)
Role : implemente la commande d'assembleur interactif ASM.
Assembleur interactif (ASM) : presente une invite de saisie de ligne a l'adresse cible. L'utilisateur tape des mnemoniques Z80 (par ex. LD A, 42) qui sont analyses, assembles en octets de code machine, et ecrits directement a l'adresse cible en RAM. L'adresse avance de la taille de chaque instruction assemblee. Cela permet d'assembler de petites routines directement sur le materiel sans PC externe. Les tables de correspondance d'opcodes des banques 6 et 7 (et des banques MROM 6 et 7) sont utilisees pour la traduction mnemonique vers opcode.

rfs_bank9.asm — Fonctions de repertoire et de fichiers ROM (User ROM banque 9)
Role : contient les fonctions d'enumeration du repertoire ROM, de recherche de fichier, de chargement de fichier et d'affichage qui ont ete deplacees depuis la banque 0 (la banque du dispatcher de commandes) afin de liberer de l'espace dans la banque 0 pour des entrees de table de commandes et de l'infrastructure supplementaires. Les fonctions cles incluent DIRROM9 (listing du repertoire ROM), FINDSDX9 (recherche de fichier), ISMZF9 (validation d'en-tete MZF) et _PRTMZF9 (affichage d'entree MZF).

rfs_bank11.asm — Ecran d'aide (User ROM banque 11)
Role : stocke le texte de l'ecran d'aide pagine (deplace depuis la banque 6 pour faire de la place aux tables d'opcodes). L'ecran d'aide est stocke comme une suite de chaines terminees par null (une par ligne). La commande H les affiche avec une pagination automatique, en appelant la routine WAITKEY de la banque 5 a chaque fin d'ecran.

rfs_mrom.asm — Utilitaires Monitor ROM (Monitor ROM banque 3)
Role : fournit les routines de scan ROM et de chargement de fichier MZF qui doivent s'executer depuis l'espace Monitor ROM plutot que depuis l'espace User ROM.
Pourquoi une banque Monitor ROM separee ? Les commandes IR et LR doivent enumerer les fichiers MZF stockes dans les puces Flash User ROM (les banques User ROM au-dela de 15 contiennent des programmes MZF compactes). Pour scanner une banque User ROM, le CPLD doit commuter la fenetre User ROM pour pointer vers cette banque. Mais le code de scan lui-meme reside dans la User ROM — s'il commute la banque User ROM, il se remplace instantanement par une autre banque et plante.
La solution consiste a placer la boucle de scan dans la banque Monitor ROM 3. La commutation de banque Monitor ROM est independante de la commutation de banque User ROM. La routine de scan MROM peut librement commuter les banques User ROM (pour enumerer la liste d'en-tetes MZF de chaque banque) sans perturber son propre contexte d'execution.
Fonctions cles :
  • ROMDIR : scanne toutes les banques User ROM au-dela de 15, lit chaque en-tete MZF, et construit un repertoire ROM resident en RAM utilise par la commande IR.
  • ROMLOAD : a partir d'un numero de fichier du repertoire ROM, lit les donnees MZF depuis la banque User ROM appropriee vers le LOAD ADDR specifie dans l'en-tete, puis saute optionnellement vers EXEC ADDR.

Modules CBIOS CP/M
Les quatre banques User ROM du CBIOS (12-15) et la banque Monitor ROM du CBIOS (2) implementent ensemble le CBIOS CP/M 2.2 complet. Chaque banque fournit un sous-systeme :
cbios.asm (Monitor ROM banque 2) : la table des points d'entree du CBIOS — les 17 vecteurs d'API CP/M (de BOOT a SECTRN) sont des adresses de saut dans ce module. Contient egalement les tables de parametres de disque (structures DPH, DPB qui indiquent a CP/M la geometrie de chaque lecteur de disque), les sequences de boot a froid/a chaud, et le controleur de ROM disk (lit les secteurs depuis la Flash User ROM).
cbios_bank1.asm (User ROM banque 12) : sortie audio (tonalite de cloche et melodie utilisant le PPI 8255 du MZ-80A et le buzzer), routines d'horloge temps-reel utilisant le timer 8253, et saisie clavier avec auto-repetition (touche maintenue > 500 ms repetee a ~10 Hz, correspondant au comportement attendu par les utilisateurs d'un clavier moderne).
cbios_bank2.asm (User ROM banque 13) : pilote d'ecran — sortie de caracteres a la position courante du curseur, defilement, effacement d'ecran, positionnement du curseur. Egalement l'emulateur de terminal ANSI : une machine a etats qui reconnait les sequences d'echappement VT52/VT100 (codes CSI) et les traduit en operations d'ecran MZ-80A equivalentes. Cela permet aux applications CP/M qui supposent un terminal intelligent (WordStar, Turbo Pascal, etc.) de fonctionner correctement sans aucune modification de ces applications.
cbios_bank3.asm (User ROM banque 14) : pilote de disque carte SD pour CP/M. Traduit les requetes de lecture/ecriture de secteurs CP/M de 128 octets en operations SDCFS sur les images de disque CP/M stockees apres la limite des 256 Mo sur la carte SD. Inclut la table de decalage (skew) de secteurs utilisee par SECTRN pour ameliorer les performances d'acces disque.
cbios_bank4.asm (User ROM banque 15) : controleur de disquette pour CP/M. Utilise le WD1773 (via SFD-700) ou un controleur de disquette equivalent pour servir les requetes de lecture/ecriture de disque CP/M sur des lecteurs de disquette physiques. Les donnees sont lues non inversees (contrairement a l'AFI ROM du MZ-80A qui utilise des donnees inversees) car le CBIOS ecrit son propre format reinverse. Lorsqu'il est pilote via la carte MZ80AFI, il interroge le rapport de taille de secteur du controleur (port 0xDF) pour distinguer les disques MZ-80A de 256 octets des disques MZ-80K de 128 octets, et peut amorcer/lire directement les disques CP/M MZ-80K d'origine (non convertis) — identifies par le marqueur d'amorcage non inverse 01h + IPLPRO — en les associant aux lecteurs CP/M C:/D: (les helpers ?SETDRVMAP / ?SELDRIVE affectent les lecteurs de disquette physiques aux lettres de lecteur CP/M appropriees au demarrage a froid).

Ajouter une nouvelle commande moniteur

Pour ajouter une nouvelle commande FOO qui reside dans la User ROM banque 3 (utilitaires memoire) :
  1. Ecrire le handler dans rfs_bank3.asm : ajouter une routine etiquetee FOO_CMD: qui implemente la commande. Les parametres sont disponibles dans le tampon de saisie du moniteur (HL pointe vers le premier caractere apres le nom de la commande). Terminer par RET une fois fini.
  2. Ajouter une entree dans la table de commandes dans rfs.asm : dans la CMDTABLE appropriee (ou CMDTABLE2 pour SFD-700), ajouter :
; FLAGS: not-end (bit7=0), not-exact (bit6=0), bank 3 (bits5:3 = 011 = 0x18), length 3 (bits2:0 = 011)
    DB  000H | 000H | 018H | 003H
    DB  "FOO"
    DW  FOO_CMD
  1. Mettre a jour le texte d'aide dans rfs_bank6.asm : ajouter une ligne decrivant la nouvelle commande aux chaines de texte de l'ecran d'aide.
  2. Recompiler : lancer ./build.sh. L'assembleur signalera tout depassement de taille si la banque 3 depasse desormais 2 Ko — dans ce cas, supprimer ou compresser d'autre code dans cette banque.

Ajouter une nouvelle plateforme materielle

Pour porter RFS sur une nouvelle cible materielle :
  1. Ajouter un indicateur de build dans rfs_definitions.asm : BUILD_NEWBOARD EQU 0 (a mettre a 1 lors de la compilation pour la nouvelle cible).
  2. Ajouter des constantes d'adresse si le nouveau materiel place les fenetres de ROM a des adresses differentes.
  3. Ajouter des blocs d'assemblage conditionnel a travers la source la ou le comportement specifique au materiel differe — adresses de port d'E/S pour le verrou de banque, agencement des registres du controleur SPI, detection de presence de carte SD, etc. Suivre le modele des blocs IF BUILD_ROMDISK = 1 ... ENDIF existants.
  4. Ajouter un nouveau script de build (ou etendre make_roms.sh) pour empaqueter l'image ROM selon l'agencement de la puce Flash de la nouvelle cible.
  5. Mettre a jour la verification des prerequis dans build.sh si la nouvelle cible necessite des outils supplementaires.

Conseils de debogage

Activer la sortie de debogage : mettre ENADEBUG EQU 1 dans rfs_definitions.asm avant de compiler. Cela inclut une sortie de diagnostic supplementaire a des points strategiques de l'initialisation de la carte SD et des routines SDCFS.
Utiliser le desassembleur integre : sur les builds SFD-700, taper DASM addr pour desassembler le code assemble en RAM. C'est inestimable pour verifier qu'une routine nouvellement assemblee a ete correctement encodee par la commande ASM.
Utiliser le dump hexadecimal : D E800 affiche les 320 premiers octets de la banque User ROM courante — utile pour verifier que le verrou de banque selectionne bien la banque attendue.
Test DRAM apres toute modification de RAM : taper R pour lancer un test DRAM complet chaque fois que vous ajoutez de nouvelles structures de donnees residentes en RAM. Cela detecte tot les bugs d'adressage avant qu'ils n'apparaissent sous forme de plantages mysterieux.
Garde-fou de commutation de banque : sur les cartes RomDisk v2+, ne jamais placer de DJNZ ni aucune autre instruction de boucle qui enjambe 0xEFF8-0xEFFF. Le verrou code interprete les lectures de cette plage comme la sequence de deverrouillage et pourrait commuter de banque de maniere inattendue.

Environnement de build

La chaine d'outils de build RFS est simple — seuls un environnement d'execution Java et l'assembleur GLASS Z80 sont requis pour les composants en assembleur Z80. Le script de build global FusionX build.sh automatise l'ensemble du processus.

Prerequis
# Install Java runtime (required for the GLASS assembler)
sudo apt install -y default-jre git

# Clone the repository
git clone https://git.eaw.app/eaw/tzpuFusionX.git
cd tzpuFusionX

# Initialise git submodules
git submodule update --init --recursive
Le fichier JAR de l'assembleur GLASS Z80 est inclus dans le depot a software/tools/glass-0.5.1.jar — aucun telechargement separe n'est necessaire. Tout environnement d'execution Java 8 ou ulterieur fonctionnera.

Installation et build automatises (recommande)
La maniere recommandee de construire RFS est le script d'installation autonome pour votre plateforme. Il installe les prerequis (un JRE Java pour l'assembleur GLASS Z80, une chaine d'outils C + make pour compiler le sous-module cpmtools inclus, plus perl/git/coreutils ; sous Windows, Git Bash + Java), clone le depot, recupere le bundle de contenu d'environ 110 Mo (RFS_Files.zip), ecrit le fichier d'environnement, et peut lancer le premier build — le tout de maniere interactive, avec des valeurs par defaut sensees que vous pouvez accepter en appuyant sur Entree. Copiez simplement le fichier unique correspondant a votre plateforme et executez-le.

macOS / Linux / WSL — setup_RFS.sh

chmod +x setup_RFS.sh
./setup_RFS.sh

Windows 10 / 11 — setup_RFS_windows_native.ps1 (recommande — natif, sans WSL). Depuis une invite PowerShell :

Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
.\setup_RFS_windows_native.ps1
Le script natif utilise winget pour installer Git for Windows (qui fournit bash, coreutils, perl et curl) et un JRE Temurin 17 (Java), clone le depot, recupere le bundle de contenu, et lance ./build.sh via Git Bash — sans WSL, Docker ni redemarrage. Aucun compilateur C n'est requis car deux outils hotes preconstruits (tools\cpmcp.exe et tools\sdtool.exe) sont inclus.

Windows 10 / 11 — setup_RFS_windows.ps1 (alternative — build a l’interieur de WSL2 / Ubuntu). Depuis une invite PowerShell Administrateur :

Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
.\setup_RFS_windows.ps1
Cette variante WSL installe WSL2 + Ubuntu s'ils ne sont pas deja presents (un redemarrage unique est necessaire — redemarrez, lancez Ubuntu une fois pour creer votre utilisateur Linux, puis relancez le script), puis lance setup_RFS.sh a l'interieur d'Ubuntu.
Definissez la variable d'environnement RFS_REPO_URL pour remplacer l'URL de depot par defaut (https://git.eaw.app/eaw/RFS.git) sans modifier le script, et RFS_FILES_URL pour pointer vers un bundle de contenu alternatif.
Sortie et reconstruction. Les images ROM et les images de carte SD sont ecrites dans roms/. Pour reconstruire ulterieurement, placez-vous dans le checkout ; sous macOS, lancez d'abord source ./rfs_env.sh pour ajouter GNU coreutils et le JRE au PATH ; puis lancez ./build.sh -m pour le premier build (traite les sources MZF vers MZB/) et ./build.sh pour les builds suivants. Sous Windows (natif), lancez les memes commandes ./build.sh depuis Git Bash a l'interieur du checkout.

Compilation
# Build all Z80 assembly ROMs and MZF files (includes RFS)
./build.sh --asm

# Build output appears in software/roms/
ls software/roms/*.rom software/roms/*.mzf
Le script de build assemble chaque cible ROM et MZF a l'aide de l'assembleur GLASS, en passant les chemins d'inclusion et les indicateurs de build appropries. Les variantes MS BASIC (MZ-80A, MZ-700, TZ40, TZ80) sont construites a partir du meme fichier source avec differents indicateurs BUILD_VERSION definis via des fichiers d'inclusion generes.
Sortie du build :
Sortie Description
monitor_sa1510.rom ROM moniteur SA-1510
monitor_80c_sa1510.rom Moniteur SA-1510 avec prise en charge 80 colonnes
monitor_1z-013a.rom ROM moniteur 1Z-013A
mz80afi.rom ROM AFI (interface disquette) du MZ-80A
mz2000_ipl_*.rom ROMs IPL du MZ-2000 (originale, TZPU, FusionX)
mz800_*.rom ROMs systeme du MZ-800
msbasic_*.mzf MS BASIC pour chaque cible
sa-5510_tzfs.mzf SA-5510 BASIC avec prise en charge TZFS
sharpmz-test.mzf MZF de test materiel

Integration continue
Qu'est-ce que le CI/CD ? L'integration continue (CI) est une pratique ou un serveur dedie construit automatiquement votre projet a chaque fois que vous poussez des modifications de code. Au lieu de lancer manuellement l'assembleur sur votre machine de developpement, d'empaqueter les fichiers ROM et de les televerser vers une page de telechargement, un serveur CI fait tout cela automatiquement. Si le build echoue — par exemple a cause d'une erreur de syntaxe ou d'un fichier d'inclusion manquant — vous recevez immediatement une notification par e-mail. Cela detecte les problemes tot et garantit que chaque release publiee a ete construite a partir d'un point de depart propre et reproductible.
Les ROMs RFS sont construites dans le cadre du pipeline CI Jenkins de FusionX. Jenkins est un serveur d'automatisation open-source populaire qui s'execute sur un VPS (serveur prive virtuel) ou sur n'importe quelle machine Linux. Il surveille le depot Gitea pour les pushs vers la branche master et declenche automatiquement un build complet de tous les composants du projet.

Comment ca fonctionne
Le processus de build automatise pour RFS suit ces etapes :
  1. Vous poussez du code vers la branche master du depot Gitea.
  2. Gitea envoie un webhook (une notification HTTP) au serveur Jenkins.
  3. Jenkins clone le depot dans un espace de travail propre et neuf.
  4. Jenkins lance ./build.sh --asm qui assemble toutes les ROMs moniteur Z80 et les fichiers MZF a l'aide de l'assembleur GLASS.
  5. Jenkins empaquete les fichiers ROM et MZF assembles dans une archive tarball versionnee (FusionX-ROMs-v1.08.tar.gz).
  6. Jenkins cree une release Gitea avec le tarball joint comme ressource telechargeable.
  7. Jenkins envoie un e-mail rapportant le succes ou l'echec.
L'ensemble du processus prend environ une minute et ne necessite aucune intervention manuelle apres le push initial.

Mise en place de Jenkins
Jenkins s'execute dans un conteneur Docker pour une installation et une portabilite faciles. Les prerequis minimaux sont un serveur Linux avec 2 Go de RAM, Docker installe et un acces reseau a votre depot Gitea. Sur votre serveur :
# Install Docker (Debian/Ubuntu)
sudo apt update && sudo apt install -y docker.io docker-compose
sudo systemctl enable docker && sudo systemctl start docker

# Create the Jenkins directory
sudo mkdir -p /srv/jenkins/data
cd /srv/jenkins
Creer un fichier docker-compose.yml :
# /srv/jenkins/docker-compose.yml
version: '3.8'
services:
  jenkins:
    image: jenkins/jenkins:lts
    ports:
      - "8080:8080"
    volumes:
      - /srv/jenkins/data:/var/jenkins_home
    environment:
      - JAVA_OPTS=-Djenkins.install.runSetupWizard=false
    restart: unless-stopped
# Start Jenkins
docker-compose up -d

# Get the initial admin password (first run only)
docker-compose logs jenkins | grep "initial admin password" -A 2

# Open http://your-server:8080 in a browser
Au premier lancement, Jenkins demande le mot de passe administrateur affiche dans les journaux. Apres connexion, installez les "plugins suggeres" puis ajoutez le plugin Generic Webhook Trigger via Manage Jenkins -> Plugins -> Available.

Creation du pipeline
Un job "Pipeline" Jenkins est defini par un script Groovy qui indique a Jenkins exactement quelles commandes executer. Pour creer un pipeline de build RFS :
  1. Cliquez sur New Item sur le tableau de bord Jenkins.
  2. Entrez un nom (par ex. RFS-Build), selectionnez Pipeline, cliquez sur OK.
  3. Dans la section Pipeline, reglez Definition sur "Pipeline script" et collez ceci :
pipeline {
    agent any
    environment {
        GITEA_URL   = "https://git.eaw.app"
        REPO_URL    = "https://git.eaw.app/eaw/tzpuFusionX.git"
        GITEA_TOKEN = credentials('gitea-api-token')
        GITEA_OWNER = "eaw"
        GITEA_REPO  = "tzpuFusionX"
    }
    triggers {
        GenericTrigger(
            genericVariables: [[key: 'ref', value: '$.ref']],
            causeString: 'Triggered by Gitea push to $ref',
            token: 'rfs-build-trigger',
            regexpFilterText: '$ref',
            regexpFilterExpression: '^refs/heads/(main|master)$'
        )
    }
    stages {
        stage('Checkout') {
            steps {
                cleanWs()
                git url: "${REPO_URL}", branch: 'master'
                sh 'git submodule update --init --recursive'
            }
        }
        stage('Build Assembly ROMs') {
            steps {
                sh 'chmod +x build.sh && mkdir -p software/tmp software/roms'
                sh './build.sh --asm'
            }
        }
        stage('Package') {
            steps {
                script {
                    def ver = readFile('VERSION').trim()
                    sh "cd software/roms && tar czf ../../FusionX-ROMs-v${ver}.tar.gz *.rom *.mzf"
                    archiveArtifacts artifacts: "FusionX-ROMs-v${ver}.tar.gz"
                }
            }
        }
    }
    post {
        success { mail to: 'your-email@example.com', subject: "RFS Build - SUCCESS", body: "Build completed." }
        failure { mail to: 'your-email@example.com', subject: "RFS Build - FAILED", body: "Check console output." }
        always  { cleanWs() }
    }
}
Il s'agit d'un pipeline simplifie qui ne construit que les ROMs en assembleur Z80. Pour le pipeline FusionX complet — qui construit egalement TZFS, CP/M, les modules noyau, les bitstreams CPLD et cree les releases Gitea — voir la section Guide du developpeur FusionX — Integration continue. Ce guide couvre egalement la configuration du compilateur croise ARM, l'installation de Quartus sous Docker, la traduction des chemins entre conteneurs freres, et le script de pipeline complet.

Webhook Gitea
Un webhook indique a Gitea de notifier Jenkins chaque fois que du code est pousse. Dans votre depot Gitea, allez dans Settings -> Webhooks -> Add Webhook -> Gitea et reglez :
  • Target URL : http://your-server:8080/generic-webhook-trigger/invoke?token=rfs-build-trigger
  • Content Type : application/json
  • Trigger On : Push Events
Apres avoir enregistre, poussez un commit vers master et verifiez Jenkins — un nouveau build devrait apparaitre automatiquement. Cliquez sur le numero du build puis sur Console Output pour suivre la progression en temps reel.

Liens de reference

Ressource Lien
Page du projet RFS /fr/sharpmz-upgrades-rfs/
Manuel utilisateur RFS /fr/sharpmz-upgrades-rfs-usermanual/
Guide technique RFS /fr/sharpmz-upgrades-rfs-technicalguide/
Galerie RFS /fr/sharpmz-upgrades-rfs-gallery/
Guide du developpeur SFD-700 mkII /fr/sfd700-developersguide/
Guide du developpeur picoZ80 /fr/picoz80-developersguide/
Guide du developpeur FusionX /fr/tranzputer-fusionx-developersguide/
Assembleur GLASS Z80 Fourni dans tools/glass-0.5.1.jar
Manuel CPU Zilog Z80 Fiche technique standard — timing de bus, jeu d’instructions, reference des registres
Guide d’adaptation CP/M 2.2 Digital Research — reference de conception du CBIOS