MZ-80A RomDisk — Guida per Sviluppatori

Guida per Sviluppatori del RomDisk

Questa guida e' una presentazione dettagliata del codice sorgente del firmware del PCB Sharp MZ-80A RomDisk e dell'ambiente di sviluppo. Spiega i concetti del linguaggio assemblativo Z80 per sviluppatori che potrebbero non avere familiarita' con il linguaggio, descrive in dettaglio il meccanismo di commutazione banchi specifico del RomDisk, attraversa ogni modulo sorgente e mostra come aggiungere nuovi comandi, aggiungere nuove varianti hardware SPI e fare il debug del firmware su hardware reale.
Il firmware RomDisk e' una variante del Rom Filing System (RFS). Salvo diversa indicazione, tutte le descrizioni qui si applicano a compilazioni con BUILD_ROMDISK EQU 1 in rfs_definitions.asm. Per l'architettura hardware e i dettagli di costruzione del PCB vedere la pagina hardware del RomDisk. Per l'uso lato utente vedere il Manuale Utente RFS.

Introduzione all'Assemblatore Z80 per Non-Programmatori Assembly

L'intero firmware RomDisk e' scritto in linguaggio assemblativo Z80 -- il linguaggio nativo del processore Zilog Z80 utilizzato nella serie Sharp MZ. A differenza dei linguaggi ad alto livello, l'assembly si mappa quasi direttamente sull'hardware fisico: ogni istruzione viene tradotta in uno o pochi byte che la CPU esegue direttamente.

Registri
Lo Z80 non ha "variabili" -- invece ha un piccolo insieme di registri (locazioni di memoria veloce all'interno della CPU). I piu' comunemente usati in RFS:
Register Size Role
A 8-bit Accumulator — the primary register for arithmetic, logic, and I/O operations. Almost every instruction involves A.
B, C 8-bit General purpose. BC together forms a 16-bit pair, commonly used as a loop counter or byte count.
D, E 8-bit General purpose. DE together is a 16-bit pair, commonly used as a source or destination pointer.
H, L 8-bit General purpose. HL together is the main 16-bit memory pointer — most memory read/write instructions use HL.
IX, IY 16-bit Index registers — used for base+offset memory addressing. Slower than HL but convenient for structured data.
SP 16-bit Stack Pointer — points to the top of the call stack. PUSH and POP use SP automatically.
PC 16-bit Program Counter — the address of the current instruction. Incremented automatically; modified by jumps and calls.
F 8-bit Flags register — individual bits set by arithmetic operations: Z (zero), C (carry), S (sign), P/V (parity/overflow).

Istruzioni Chiave
  • LD dest, src -- Caricare (copiare) dati. LD A, B copia B in A. LD A, (HL) legge il byte all'indirizzo di memoria contenuto in HL in A. LD (0x1200), A scrive A all'indirizzo di memoria 0x1200.
  • CALL addr -- Chiamare una subroutine. Mette l'indirizzo di ritorno sullo stack e salta a addr. Equivalente a una chiamata di funzione.
  • RET -- Ritorno dalla subroutine. Preleva l'indirizzo di ritorno dallo stack e vi salta.
  • JP addr -- Salto incondizionato a addr. JP Z, addr salta solo se il flag Zero e' impostato.
  • JR offset -- Salto relativo breve (-128 a +127 byte). Piu' veloce e compatto di JP per salti vicini.
  • DJNZ offset -- Decrementare B e saltare se non zero. L'istruzione di loop canonica dello Z80.
  • ADD A, n -- Aggiungere n ad A. SUB n sottrae. AND n, OR n, XOR n -- logica bit a bit su A.
  • IN A, (port) -- Leggere dalla porta I/O in A. OUT (port), A -- scrivere A sulla porta I/O.
  • PUSH rr / POP rr -- Salvare/ripristinare una coppia di registri 16 bit sullo/dallo stack.
  • EI / DI -- Abilitare / Disabilitare gli interrupt.

Modi di Indirizzamento
Lo Z80 offre diversi modi per specificare da dove vengono o dove vanno i dati:
  • Immediato: LD A, 42 -- il valore e' incorporato nei byte dell'istruzione stessa.
  • Registro: LD A, B -- i dati vengono da o vanno in un registro.
  • Indiretto (tramite HL): LD A, (HL) -- HL contiene un indirizzo di memoria; i dati vengono letti da quell'indirizzo.
  • Esteso (indirizzo diretto): LD A, (0x1200) -- l'indirizzo e' una costante letterale 16 bit nell'istruzione.
  • Indicizzato: LD A, (IX+5) -- IX contiene un indirizzo base; 5 viene aggiunto per ottenere l'indirizzo effettivo.

Sintassi dell'Assemblatore GLASS
RFS utilizza l'assemblatore GLASS Z80 (incluso come tools/glass.jar). Principali caratteristiche sintattiche:
  • I commenti iniziano con ; -- tutto a destra del punto e virgola viene ignorato.
  • Le etichette sono identificatori seguiti da :.
  • EQU definisce una costante: BELL EQU 007H.
  • DB (Define Byte) inserisce byte grezzi.
  • DW (Define Word) inserisce valori 16 bit little-endian.
  • ORG addr imposta l'origine dell'assemblaggio.
  • INCLUDE "file.asm" include testualmente un altro file.
  • IF / ENDIF assemblaggio condizionale.

Albero dei Sorgenti

Path Contents
README.md Top-level project overview
schematics/ KiCad schematics for PCB v1.1, v2.0, v2.1
pcb/ KiCad PCB layout files
software/RFS/ RFS firmware submodule
software/RFS/asm/ All Z80 assembly source files
software/RFS/tools/ Build scripts and GLASS assembler (glass.jar)
software/RFS/build.sh Top-level build script

I file sorgente assemblatore e i loro ruoli:

File Bank Role
rfs.asm User ROM Bank 0 Entry point, command table, bank-switch stubs, jump table
rfs_bank1.asm User ROM Bank 1 Floppy disk controller
rfs_bank2.asm User ROM Bank 2 SD card controller (SPI driver, SDCFS)
rfs_bank3.asm User ROM Bank 3 Memory utilities (D, M, CP, T2SD, SD2T)
rfs_bank4.asm User ROM Bank 4 CMT (cassette tape) controller
rfs_bank5.asm User ROM Bank 5 Reserved / unused
rfs_bank6.asm User ROM Bank 6 Messages, help screen, ASCII↔Sharp character conversion
rfs_bank7.asm User ROM Bank 7 Memory test (R command), timer test (T command)
rfs_mrom.asm Monitor ROM Bank 3 MZF ROM scanning and loading (ROMDIR, ROMLOAD)
cbios.asm Monitor ROM Bank 2 CP/M CBIOS entry point table and ROM disk controller
cbios_bank1–4.asm User ROM Banks 8–11 CP/M CBIOS subsystems
include/rfs_definitions.asm All configuration constants

Configurazione: rfs_definitions.asm

Questo e' il file di configurazione centrale, incluso da ogni altro file sorgente tramite INCLUDE "rfs_definitions.asm". Ogni opzione al momento dell'assemblaggio e' controllata qui.

Target di Compilazione e Flag SPI
; SPI hardware selection — exactly ONE must be 1:
HW_SPI_ENA    EQU 1    ; Hardware SPI on RomDisk v2+ PCB (74HCT595/165 shift registers)
SW_SPI_ENA    EQU 0    ; Software bit-bang SPI via Z80 I/O port bits
PP_SPI_ENA    EQU 0    ; Parallel printer port SPI (v1 boards only)

; Build target — exactly ONE must be 1:
BUILD_ROMDISK EQU 1    ; Build for the MZ-80A RomDisk card
BUILD_SFD700  EQU 0    ; Build for the SFD-700 floppy interface
BUILD_PICOZ80 EQU 0    ; Build for the picoZ80 board
Esattamente un flag BUILD_* ed esattamente un flag SPI devono essere impostati a 1 contemporaneamente. Impostarne piu' di uno produrra' codice errato o ambiguo -- diversi blocchi condizionali in rfs_bank2.asm utilizzano catene IF/ELSE/ENDIF annidate che presuppongono l'esclusione reciproca.

Commutazione Banchi in Dettaglio

Il meccanismo di commutazione banchi del RomDisk e' fondamentalmente diverso da quello usato da TZFS. TZFS usa le modalita' di gestione memoria del CPLD tranZPUter per rimappare i range di indirizzi nell'hardware. Il RomDisk usa invece un latch fisico di banco -- un flip-flop tipo D 74HCT273 -- accessibile tramite registri I/O mappati in memoria nella parte superiore dello spazio indirizzi User ROM.

Perche' il Banking e' Necessario
Lo Sharp MZ-80A concede allo User ROM solo 2 KB di spazio indirizzi (0xE800-0xEFFF). 2 KB possono contenere solo alcune centinaia di istruzioni -- molto meno di quanto necessario per un file system, un controller floppy, un driver per scheda SD, un controller per nastro e utilita' di memoria. La soluzione consiste nel commutare fisicamente quale pagina da 2 KB di un chip Flash piu' grande e' visibile a 0xE800-0xEFFF.

Il Latch Codificato (Schede v2.0 e Successive)
I registri di selezione banco condividono linee di indirizzo con gli 8 byte superiori della Flash ROM (0xEFF8-0xEFFF). Il PCB RomDisk v2.0 ha introdotto un latch codificato per impedire commutazioni accidentali. Il latch codificato e' costruito da un contatore presettabile 74HCT191. Il software deve leggere dall'indirizzo BNKCTRLRST (0xEFF8) esattamente 16 volte per sbloccare i registri di controllo.

La Sequenza di Commutazione Banco
Una commutazione di banco completa per lo User ROM richiede i seguenti passi:
  1. Sbloccare il latch codificato: Leggere esattamente 16 volte dall'indirizzo BNKCTRLRST (0xEFF8).
  2. Scrivere il numero di banco: Scrivere il numero di banco desiderato in BNKSELUSER (0xEFFE).
  3. Ribloccare il latch: Leggere una volta da BNKCTRLDIS (0xEFF9).
Lo stub di commutazione banco in ogni banco (che inizia a UROMBSTBL, 0xE820) esegue questa sequenza automaticamente.

Critico: Mai Posizionare un Loop che Copra 0xEFF8-0xEFFF
Questo e' il vincolo di implementazione piu' importante nell'intero codice RomDisk. La regola e' semplice: nessuna istruzione di loop (DJNZ, JR, JP) deve avere il suo target di salto o i propri byte di opcode/operando all'interno di 0xEFF8-0xEFFF.

Formato della Tabella dei Comandi (rfs.asm)
Il dispatcher dei comandi del monitor in rfs.asm utilizza una tabella di comandi compatta. Ogni voce descrive un comando ed e' strutturata come segue:
; One command table entry:
;   DB  FLAGS          ; 1 byte: END|MATCH|BANK[5:3]|SIZE[2:0]
;   DB  "COMMAND"      ; SIZE bytes: the command string
;   DW  HANDLER_ADDR   ; 2 bytes: address of the handler routine

Percorso dei Moduli

rfs.asm -- Dispatcher dei Comandi (User ROM Bank 0)
Ruolo: Il punto di ingresso per tutte le funzionalita' RFS. Quando il monitor SA-1510 non riconosce un comando, passa il controllo al punto di ingresso User ROM a UROMADDR (0xE800).

rfs_bank1.asm -- Controller Floppy Disk (User ROM Bank 1)
Ruolo: Implementa i comandi di avvio da floppy disk.

rfs_bank2.asm -- Controller Scheda SD (User ROM Bank 2)
Ruolo: Il sottosistema completo della scheda SD -- inizializzazione del driver SPI, protocollo di comando della scheda SD e le routine di directory e I/O file SDCFS.

rfs_bank3.asm -- Utilita' di Memoria (User ROM Bank 3)
Ruolo: Implementa i comandi D (dump esadecimale), M (modifica memoria), CP (copia memoria), T2SD (nastro a SD) e SD2T (SD a nastro).

rfs_bank4.asm -- Controller CMT (User ROM Bank 4)
Ruolo: Implementa i comandi LT/LTNX (caricamento nastro), ST (salvataggio nastro) e V (verifica nastro).

rfs_bank5.asm -- Riservato (User ROM Bank 5)
Ruolo: Attualmente riservato e non utilizzato nella compilazione RomDisk.

rfs_bank6.asm -- Messaggi e Tabelle Caratteri (User ROM Bank 6)
Ruolo: Memorizza il testo della schermata di aiuto, tutte le stringhe di messaggi di errore e stato, e la tabella di conversione del set di caratteri Sharp MZ in ASCII.

rfs_bank7.asm -- Comandi Diagnostici (User ROM Bank 7)
Ruolo: Implementa i comandi R (test DRAM) e T (test timer) nella compilazione RomDisk.

rfs_mrom.asm -- Utilita' Monitor ROM (Monitor ROM Bank 3)
Ruolo: Fornisce le routine di scansione ROM e caricamento file MZF che devono essere eseguite dallo spazio Monitor ROM piuttosto che dallo spazio User ROM.

Driver SPI: Hardware vs. Software

Il driver SPI in rfs_bank2.asm e' implementato in tre modi, selezionati interamente al momento dell'assemblaggio. La selezione e' controllata dai tre flag mutuamente esclusivi in rfs_definitions.asm.
HW_SPI_ENA   EQU 1    ; 74HCT595/74HCT165 hardware shift registers on RomDisk v2+ PCB
SW_SPI_ENA   EQU 0    ; Software bit-bang SPI using the RomDisk v2+ I/O port bits
PP_SPI_ENA   EQU 0    ; Software bit-bang SPI via the Sharp MZ-80A parallel printer port
  HW_SPI_ENA SW_SPI_ENA PP_SPI_ENA
PCB required v2.0+ v2.0+ v1.x
Approx. byte rate ~1 µs/byte ~30 µs/byte ~50 µs/byte
Coded latch required Yes Yes No
Additional ICs 74HCT595, 74HCT165 None None
Suitable for All current builds Low-cost v2 variant Legacy v1 boards

Aggiungere un Nuovo Comando del Monitor

L'esempio seguente aggiunge un comando PEEK che legge e visualizza un singolo byte da un dato indirizzo. L'handler appartiene al banco 3 (utilita' di memoria).

Passo 1: Scrivere l’handler in rfs_bank3.asm

; In rfs_bank3.asm (bank 3, memory utilities):
PEEK:   CALL  HLHEX              ; Parse 4-digit hex address from input buffer into HL
        LD    A,(HL)              ; Read the byte at that address
        CALL  PRTHX              ; Print A as 2 hex digits
        RET

Passo 2: Aggiungere una voce nella tabella comandi in rfs.asm

    DB  000H | 000H | 018H | 004H
    DB  "PEEK"
    DW  PEEK

Passo 3: Aggiungere testo di aiuto in rfs_bank6.asm

    DB  "PEEKXXXX - read byte at XXXX",    00DH

Passo 4: Compilare

cd /dvlp/Projects/MZ80A_RFS/software/RFS
./build.sh

Aggiungere Nuovo Supporto Hardware

Per aggiungere una nuova variante SPI hardware o portare RFS su una nuova piattaforma, seguire le istruzioni dettagliate nel file sorgente inglese originale, modificando rfs_definitions.asm, aggiungendo blocchi di assemblaggio condizionale e aggiornando build.sh secondo necessita'.

Suggerimenti per il Debug

Abilitare l'output di debug: Impostare ENADEBUG EQU 1 in rfs_definitions.asm prima della compilazione.
Dump dell'area di ingresso del banco User ROM 0: Digitare D E800 per fare il dump dei primi 320 byte del banco User ROM corrente.
Controllare il registro di controllo banco: Digitare D EFF8 per fare il dump dell'area del registro di controllo banco.
Verificare il conteggio di sblocco del latch codificato: Se le scritture al registro di controllo banco sembrano non avere effetto, la causa piu' comune e' che la sequenza di 16 letture non si completa.
Avvio v2.1 al monitor SA-1510 senza prompt + RFS: Se la macchina si avvia nel monitor SA-1510 nativo e la riga di accesso RFS + RFS non appare, il punto di ingresso User ROM a 0xE800 non viene chiamato.
Eseguire MEMTEST dopo l'aggiunta di dati residenti in RAM: Digitare R immediatamente dopo l'aggiunta di nuove strutture dati o variabili residenti in RAM.
Fallimenti dell'inizializzazione della scheda SD: Se i comandi SD restituiscono codici di risposta inattesi con ENADEBUG abilitato, verificare che il timing del chip select SPI sia corretto.
Fallimenti di chiamate inter-banco: Se una chiamata inter-banco sembra eseguire il codice sbagliato o ritorna con corruzione dei registri, verificare che lo stub di commutazione banco nel banco target corrisponda byte per byte a quello nel banco 0.

Siti di Riferimento

Resource Link
RomDisk hardware page /sharpmz-upgrades-romdisk/
RFS project page /sharpmz-upgrades-rfs/
RFS User Manual /sharpmz-upgrades-rfs-usermanual/
RFS Technical Guide /sharpmz-upgrades-rfs-technicalguide/
RFS Developer’s Guide (RFS) /rfs-developersguide/
TZFS Developer’s Guide /tzfs-developersguide/
tranZPUter FusionX page /tranzputer-fusionx/
GLASS Z80 Assembler Bundled in software/RFS/tools/glass.jar
Zilog Z80 CPU User Manual Standard datasheet — bus timing, instruction set, register reference
WD1773 FDC Datasheet Western Digital — floppy disk controller I/O port reference
SD Card Physical Layer Spec SD Association — CMD0/CMD8/ACMD41/CMD17/CMD24 protocol
Sharp MZ-80A Service Manual Hardware schematics, SA-1510 ROM listing, memory map