MZ-80A RomDisk — Entwicklerhandbuch
RomDisk Entwicklerhandbuch
Dieses Handbuch ist ein detaillierter Durchgang durch den Sharp MZ-80A RomDisk PCB Firmware-Quellcode und die Entwicklungsumgebung. Es erklaert Z80-Assembler-Konzepte fuer Entwickler, die moeglicherweise nicht mit der Sprache vertraut sind, beschreibt den RomDisk-spezifischen Bank-Switching-Mechanismus im Detail, fuehrt durch jedes Quellmodul und zeigt, wie man neue Befehle hinzufuegt, neue SPI-Hardware-Varianten hinzufuegt und Firmware auf realer Hardware debuggt.
Die RomDisk-Firmware ist eine Variante des Rom Filing System (RFS). Sofern nicht anders angegeben, gelten alle Beschreibungen hier fuer Builds mit
BUILD_ROMDISK EQU 1 in rfs_definitions.asm. Fuer Hardware-Architektur und PCB-Konstruktionsdetails siehe die RomDisk Hardware-Seite. Fuer die benutzerseitige Bedienung siehe das RFS Benutzerhandbuch.
Einfuehrung in Z80-Assembler fuer Nicht-Assembler-Programmierer
Die gesamte RomDisk-Firmware ist in Z80-Assemblersprache geschrieben -- der nativen Befehlssprache des Zilog Z80-Prozessors, der in der Sharp MZ-Serie verwendet wird. Im Gegensatz zu Hochsprachen bildet Assembler fast direkt auf die physische Hardware ab: Jeder Befehl wird in ein oder wenige Bytes uebersetzt, die die CPU direkt ausfuehrt.
Register
Der Z80 hat keine "Variablen" -- stattdessen hat er einen kleinen Satz von Registern (schnelle Speicherplaetze innerhalb der CPU). Die am haeufigsten verwendeten 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). |
LD dest, src-- Laden (Kopieren) von Daten.LD A, Bkopiert B nach A.LD A, (HL)liest das Byte an der in HL gehaltenen Speicheradresse nach A.LD (0x1200), Aschreibt A an die Speicheradresse 0x1200.CALL addr-- Aufruf einer Unterroutine. Legt die Rueckkehradresse (naechster Befehl) auf den Stack und springt zuaddr. Entspricht einem Funktionsaufruf.RET-- Rueckkehr aus Unterroutine. Nimmt die Rueckkehradresse vom Stack und springt dorthin.JP addr-- Unbedingter Sprung zuaddr.JP Z, addrspringt nur, wenn das Zero-Flag gesetzt ist (d.h. die letzte Operation Null ergab).JR offset-- Kurzer relativer Sprung (-128 bis +127 Bytes). Schneller und kompakter als JP fuer nahe Verzweigungen.DJNZ offset-- B dekrementieren und springen wenn nicht Null. Der kanonische Z80-Schleifenbefehl:LD B, 10 / LOOP: ... / DJNZ LOOPwiederholt 10 mal.ADD A, n-- n zu A addieren.SUB nsubtrahiert.AND n,OR n,XOR n-- bitweise Logik auf A.IN A, (port)-- Von I/O-Port nach A lesen.OUT (port), A-- A auf I/O-Port schreiben. So kommuniziert der Z80 mit Hardware (dem WD1773 Floppy-Controller, SPI-Schieberegistern, Bank-Latch usw.).PUSH rr / POP rr-- Ein 16-Bit-Registerpaar auf dem Stack sichern/wiederherstellen.EI / DI-- Interrupts aktivieren / deaktivieren. Code, der nicht unterbrochen werden darf (z.B. zeitkritische Bandoperationen), wird zwischen DI und EI eingerahmt.
Der Z80 bietet mehrere Moeglichkeiten, anzugeben, woher Daten kommen oder wohin sie gehen:
GLASS Assembler-Syntax
- Unmittelbar:
LD A, 42-- der Wert ist in den Befehlsbytes selbst eingebettet. - Register:
LD A, B-- Daten kommen aus oder gehen in ein Register. - Indirekt (ueber HL):
LD A, (HL)-- HL enthaelt eine Speicheradresse; Daten werden von dieser Adresse gelesen. - Erweitert (direkte Adresse):
LD A, (0x1200)-- die Adresse ist eine literale 16-Bit-Konstante im Befehl. - Indiziert:
LD A, (IX+5)-- IX haelt eine Basisadresse; 5 wird addiert, um die effektive Adresse zu erhalten. In RFS fuer den Zugriff auf Felder innerhalb von Datenstrukturen mit festem Format verwendet.
RFS verwendet den GLASS Z80-Assembler (mitgeliefert als
tools/glass.jar). Wichtige Syntaxmerkmale:
- Kommentare beginnen mit
;-- alles rechts vom Semikolon wird ignoriert. - Labels sind Bezeichner gefolgt von
:. Ein Label am Zeilenanfang benennt die Adresse des naechsten Befehls. EQUdefiniert eine Konstante:BELL EQU 007H-- der Assembler ersetzt jedes Vorkommen von BELL durch 0x07.DB(Define Byte) fuegt rohe Bytes ein:DB 0x41, 0x42gibt zwei Bytes aus. Verwendet fuer Strings, Lookup-Tabellen und Befehlstabelleneintraege.DW(Define Word) fuegt 16-Bit-Little-Endian-Werte ein:DW HANDLERgibt die Adresse des HANDLER-Labels aus.ORG addrsetzt den Assembler-Ursprung -- nachfolgender Code wird assembliert, als ob er beiaddrliegt.INCLUDE "file.asm"bindet eine andere Datei an der aktuellen Position textuell ein.IF / ENDIFbedingte Assemblierung:IF HW_SPI_ENA = 1 ... ENDIF-- die eingeschlossenen Befehle werden nur assembliert, wenn die Bedingung wahr ist. So waehlt RFS zwischen Hardware-SPI, Software-SPI und Parallelport-SPI aus einem Quellenbaum.
Quellenbaum
| Path | Contents |
|---|---|
README.md |
Top-level project overview |
README_CPM.md |
CP/M-specific notes |
schematics/ |
KiCad schematics for PCB v1.1, v2.0, v2.1 |
pcb/ |
KiCad PCB layout files |
software/RFS/ |
RFS firmware submodule (also at /dvlp/Projects/RFS) |
software/RFS/asm/ |
All Z80 assembly source files |
software/RFS/asm/include/ |
Shared configuration and utility includes |
software/RFS/tools/ |
Build scripts and GLASS assembler (glass.jar) |
software/RFS/build.sh |
Top-level build script |
Die Assembler-Quelldateien und ihre Rollen:
| 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 |
monitor_sa1510.asm |
— | SA-1510 Monitor ROM reference |
monitor_80c_sa1510.asm |
— | SA-1510 Monitor ROM (80-column variant) |
ipl.asm |
— | Initial Program Loader |
include/rfs_definitions.asm |
— | All configuration constants |
include/rfs_utilities.asm |
— | Shared utility macros |
include/macros.asm |
— | Assembler macro definitions |
include/cpm_definitions.asm |
— | CP/M CBIOS constants |
Konfiguration: rfs_definitions.asm
Dies ist die zentrale Konfigurationsdatei, die von jeder anderen Quelldatei ueber
Build-Ziel und SPI-Flags
INCLUDE "rfs_definitions.asm" eingebunden wird. Jede Assembler-Zeit-Option wird hier gesteuert. Die wichtigsten Abschnitte:
; 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) ; Platform options: FUSIONX_ENA EQU 1 ; Include tranZPUter FusionX support KUMA80_ENA EQU 0 ; Target has Kuma 40/80 upgrade installed VIDEOMODULE_ENA EQU 0 ; Target has 40/80 column colour video module ; 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 ; Debugging: ENADEBUG EQU 0 ; Enable debug output during assembly (1 = enable)
Genau ein
Adresskonstanten
BUILD_*-Flag und genau ein SPI-Flag muessen gleichzeitig auf 1 gesetzt sein. Das Setzen von mehr als einem erzeugt inkorrekten oder mehrdeutigen Code -- mehrere bedingte Bloecke in rfs_bank2.asm verwenden verschachtelte IF/ELSE/ENDIF-Ketten, die gegenseitigen Ausschluss voraussetzen. Wenn FUSIONX_ENA = 1, wird zusaetzlicher Code fuer die tranZPUter FusionX-Speicherverwaltung in die Bank-Switch-Stubs assembliert; dies kann bei Standard-RomDisk-Builds sicher aktiviert bleiben, da der FusionX-Pfad nur zur Laufzeit genommen wird, wenn FusionX-Hardware erkannt wird.
UROMADDR EQU 0E800H ; Base of User ROM window UROMBSTBL EQU UROMADDR + 020H ; Bank-switch table entry point (0xE820) RFSJMPTABLE EQU UROMADDR + 0B0H ; Jump table start (0xE8B0) FDCROMADDR EQU 0F000H ; Floppy AFI ROM address ; Bank control registers (only accessible after coded latch unlock): BNKCTRLRST EQU 0EFF8H ; Read here 16 times to unlock control registers BNKCTRLDIS EQU 0EFF9H ; Read here once to re-lock (disable) control registers HWSPIDATA EQU 0EFFBH ; Hardware SPI data register (read/write) HWSPISTART EQU 0EFFCH ; Hardware SPI start trigger (write to begin transfer) BNKSELMROM EQU 0EFFDh ; Monitor ROM bank select register BNKSELUSER EQU 0EFFEh ; User ROM bank select register BNKCTRL EQU 0EFFFH ; Bank control register (read/write)
Beachten Sie, dass BNKCTRLRST bis BNKCTRL (0xEFF8-0xEFFF) denselben Adressraum wie die oberen 8 Bytes des Flash-ROM-Fensters teilen. Beim Reset verhalten sich diese Adressen als gewoehnliche Flash-ROM-Lesevorgaenge. Der Coded-Latch-Schaltkreis -- ein voreinstellbarer 74HCT191-Zaehler -- muss entsperrt werden, bevor Schreibvorgaenge auf BNKSELMROM, BNKSELUSER oder BNKCTRL wirksam werden. Siehe den Bank-Switching-Abschnitt unten fuer die vollstaendige Entsperrsequenz.
Zeichen- und Steuerdefinitionen
Standard-ASCII-Steuerzeichen werden als benannte Konstanten definiert, um den Quellcode selbstdokumentierend zu machen:
BELL EQU 007H ; Terminal bell CR EQU 00DH ; Carriage return LF EQU 00AH ; Line feed CS EQU 00CH ; Clear screen (FF) SPACE EQU 020H ; ASCII space DELETE EQU 07FH ; Delete key
Bank-Switching im Detail
Der RomDisk-Bank-Switching-Mechanismus unterscheidet sich grundlegend von dem in TZFS verwendeten. TZFS verwendet die Speicherverwaltungsmodi des tranZPUter-CPLD, um Adressbereiche in der Hardware umzubilden. RomDisk verwendet stattdessen einen physischen Bank-Latch -- ein 74HCT273 D-Typ-Flipflop -- auf das ueber speicherabgebildete I/O-Register an der Spitze des User-ROM-Adressraums zugegriffen wird. Das Verstaendnis dieses Mechanismus ist wesentlich, bevor eine Quelldatei geaendert wird.
Warum Banking notwendig ist
Der Sharp MZ-80A gibt dem User ROM nur 2 KB Adressraum (0xE800-0xEFFF). 2 KB koennen nur einige hundert Befehle aufnehmen -- bei weitem nicht genug fuer ein Dateisystem, einen Floppy-Controller, einen SD-Karten-Treiber, einen Bandcontroller und Speicherutilitaeten. Die Loesung besteht darin, physisch umzuschalten, welche 2-KB-Seite eines groesseren Flash-Chips an 0xE800-0xEFFF sichtbar ist. Das RomDisk-PCB haelt einen 512-KB-Flash-Chip, der in 2-KB-Baenke unterteilt ist, wobei bis zu 12 Baenke gleichzeitig zugaenglich sind. Das Umschalten zwischen ihnen nach Bedarf gibt RFS effektiv 24 KB ROM-Code, waehrend der SA-1510-Monitor nur ein statisches 2-KB-Fenster sieht.
Der Coded Latch (v2.0 und spaetere Platinen)
Die Bank-Select-Register teilen sich Adressleitungen mit den oberen 8 Bytes der Flash-ROM (0xEFF8-0xEFFF). Wenn das Bank-Select-Register jederzeit beschreibbar waere, wuerde jeder versehentliche Schreibvorgang auf diesen Adressbereich -- oder sogar Z80-Refresh-Zyklen, die diesen Bereich treffen -- still die Baenke mitten in der Ausfuehrung umschalten. Das RomDisk v2.0 PCB fuehrte einen Coded Latch ein, um dies zu verhindern.
Der Coded Latch ist aus einem voreinstellbaren 74HCT191-Zaehler aufgebaut. In seinem Standardzustand (Zaehler nicht bei Terminal Count) ist der I/O-Pfad des Bank-Steuerregisters deaktiviert -- Schreibvorgaenge auf BNKSELMROM, BNKSELUSER und BNKCTRL haben keine Wirkung. Um den Pfad zu aktivieren, muss die Software genau 16 mal von der Adresse BNKCTRLRST (0xEFF8) lesen. Jede Lesung erhoeht den Zaehler um eins. Wenn der Zaehler den Terminal Count (16) erreicht, aktiviert er das Enable-Signal, das den Schreibpfad des Bank-Steuerregisters aktiviert.
Nachdem die Bank-Umschaltung abgeschlossen ist, liest die Software einmal von BNKCTRLDIS (0xEFF9). Dies setzt den 74HCT191 auf seinen Anfangswert zurueck und deaktiviert den Steuerregisterpfad erneut. Der Latch muss vor jeder nachfolgenden Bank-Umschaltsequenz erneut entsperrt werden.
Das RomDisk v2.1 Board fuegt ein AND-Gatter (im Schaltplan als D1/D2 bezeichnet) hinzu, um zu verhindern, dass die DRAM-Refresh-Zyklen des Z80 versehentlich den Zaehler erhoehen. Ohne dieses Gatter koennten die periodischen Refresh-Buszyklen, die der Z80 automatisch erzeugt, den Zaehler von selbst erhoehen und moeglicherweise den Terminal Count ohne absichtliche Softwareaktion erreichen, was unbeabsichtigte Bank-Umschaltungen waehrend des Bootens verursacht.
Die Bank-Switch-Sequenz
Eine vollstaendige Bank-Umschaltung fuer den User ROM erfordert die folgenden Schritte:
Kritisch: Keine Schleife ueber 0xEFF8-0xEFFF platzieren
- Coded Latch entsperren: Genau 16 mal von der Adresse BNKCTRLRST (0xEFF8) lesen. Jede Lesung ist eine Dummy-Lesung -- die zurueckgegebenen Daten sind das Flash-ROM-Byte an dieser Adresse und koennen verworfen werden. Verwenden Sie einen Schleifenzaehler in Register B (auf 16 gesetzt), aber beachten Sie die kritische Warnung unten zur DJNZ-Platzierung.
- Bank-Nummer schreiben: Die gewuenschte Bank-Nummer (0-7 fuer User-ROM-Baenke) in BNKSELUSER (0xEFFE) schreiben. Der 74HCT273 uebernimmt den Wert an der steigenden Flanke des Schreib-Strobes. Fuer die Auswahl des Monitor-ROM-Banks stattdessen in BNKSELMROM (0xEFFD) schreiben.
- Latch wieder sperren: Einmal von BNKCTRLDIS (0xEFF9) lesen. Dies setzt den 74HCT191-Zaehler zurueck und deaktiviert den Schreibpfad des Steuerregisters bis zur naechsten 16-Lese-Sequenz.
UROMBSTBL berechnet -- auch wenn sie nie die internen Adressen von Bank 3 gesehen hat.
Dies ist die wichtigste Implementierungsbeschraenkung im gesamten RomDisk-Code. Der Z80 holt Befehlsbytes, indem er von der Programmzaehler-Adresse liest. Wenn irgendein Befehlsabruf oder Datenlesen im Bereich 0xEFF8-0xEFFF stattfindet, erhoeht es den 74HCT191-Zaehler. Ein
FusionX Bank-Switching (FUSIONX_ENA = 1)
DJNZ-Befehl bei z.B. 0xEFF7 holt seinen Opcode von 0xEFF7 (keine Wirkung), dann sein Offset-Byte von 0xEFF8 (erhoeht den Zaehler), und bei nachfolgenden Schleifendurchlaeufen wird der Zaehler bei jedem Durchlauf weiter erhoeht. Wenn die Schleife 16 oder mehr Male vor einer beabsichtigten Bank-Umschaltung laeuft, erreicht der Zaehler den Terminal Count, die Steuerregister werden aktiv, und der naechste Schreibvorgang auf eine Adresse in 0xEFF8-0xEFFF fuehrt eine unbeabsichtigte Bank-Umschaltung durch -- ersetzt den laufenden Code sofort durch eine andere Bank.
Die Regel ist einfach: Kein Schleifenbefehl (DJNZ, JR, JP) darf sein Sprungziel oder seine eigenen Opcode/Operanden-Bytes innerhalb von 0xEFF8-0xEFFF haben. Der GLASS-Assembler erkennt oder warnt nicht automatisch davor; es liegt in der Verantwortung des Programmierers. Beim Hinzufuegen von Code zu einem Bank pruefen, dass das assemblierte Binaer keine Schleifenbefehle nahe dem oberen Ende des 2-KB-Fensters platziert.
Wenn
Befehlstabellenformat (rfs.asm)
FUSIONX_ENA = 1, enthalten die Bank-Switch-Stubs bedingte Assemblierungsbloecke, die die FusionX-Speicherverwaltungs-Portadressen anstelle der Coded-Latch-Register einsetzen. Auf einem tranZPUter-FusionX-Board wird der Flash-ROM-Paging-Mechanismus durch die Speicherverwaltung des FusionX-CPLD ersetzt, die Bank-Nummern ueber ein anderes I/O-Port-Schema ohne die 16-Lese-Entsperrsequenz akzeptiert. Der RFS-Befehlssatz, das SDCFS-Dateisystem und das gesamte benutzerrelevante Verhalten bleiben auf FusionX identisch -- nur die Low-Level-Bank-Select-Schreibvorgaenge unterscheiden sich.
Der Monitor-Befehlsdispatcher in
rfs.asm verwendet eine kompakte Befehlstabelle. Jeder Eintrag beschreibt einen Befehl und ist wie folgt aufgebaut:
; 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 fields:
; Bit 7 = 1: End of table marker (last entry).
; Bit 6 = 1: Exact match required (entire input must match; no trailing characters).
; Bits 5:3 Bank number where HANDLER_ADDR lives (0–7 maps to User ROM banks 0–7).
; Bits 2:0 Length of the command string in bytes (1–7).
;
; Example — the 'D' (dump) command, handler in bank 3, 1-character string:
DB 000H | 000H | 018H | 001H ; not-end, not-exact, bank 3 (011<<3=0x18), length 1
DB "D"
DW DUMPX
Der Dispatcher liest die Monitor-Eingabezeile, durchlaeuft die Tabelle und prueft fuer jeden Eintrag:
- Vergleicht die ersten SIZE Zeichen der Eingabe mit dem Befehlsstring.
- Wenn das EXACT-Flag gesetzt ist, wird zusaetzlich ueberprueft, ob keine weiteren Nicht-Leerzeichen folgen.
- Bei Uebereinstimmung werden die Bank-Nummer und die Handler-Adresse aus dem Tabelleneintrag extrahiert.
- Fuehrt die Bank-Umschaltung zur Zielbank ueber den Stub bei UROMBSTBL durch.
- Ruft den Handler auf, wobei die restliche Eingabe (Parameter) im Monitor-Eingabepuffer verfuegbar ist.
LTNX vor LT stehen, das wiederum vor L, da sonst der kuerzere Eintrag zuerst uebereinstimmt und der laengere Befehl nie erreicht wird.
Modul-Durchgaenge
rfs.asm -- Befehlsdispatcher (User ROM Bank 0)
Rolle: Der Einstiegspunkt fuer alle RFS-Funktionalitaet. Wenn der SA-1510-Monitor einen Befehl nicht erkennt, uebergibt er die Kontrolle an den User-ROM-Einstiegspunkt bei UROMADDR (0xE800). Diese Adresse ist immer Bank 0.
Wichtige Abschnitte:
rfs_bank1.asm -- Floppy-Disk-Controller (User ROM Bank 1)
- ROM-Einstieg (ROMFS, 0xE800): Ein NOP gefolgt von einem Makroaufruf, der Monitor ROM Bank 0 auswaehlt, dann ein JP zum Ueberspringen des Bank-Switch-Tabellenbereichs. Beim Kaltstart (erkannt durch Pruefen von ROMBK1 auf einen illegalen Wert >= 8) wird die 16-Lese-Coded-Latch-Setup-Sequenz durchgefuehrt und der untere Stack-Bereich genullt. Die initialen MROM- und UROM-Baenke werden dann aus dem gespeicherten Zustand in ROMBK1/ROMBK2 ausgewaehlt.
- Bank-Switch-Stub (UROMBSTBL, 0xE820): Sechzehn bankuebergreifende Aufruf-Gateways -- BKSW0to0 bis BKSW0to7 -- jeweils eins fuer jeden Bank 0→N Uebergang. Jedes Gateway legt die aufrufende Bank-Nummer und die Zielbank-Nummer auf den Stack und ruft dann die gemeinsame BKSW0_0-Sequenz auf, die die Coded-Latch-Entsperrung durchfuehrt, die neue Bank in BNKSELUSER schreibt und zur Ziel-Handler-Adresse springt. Bei der Rueckkehr (BKSWRET0) wird die urspruengliche Bank ueber die gleiche Sequenz wiederhergestellt.
- Sprungtabelle (RFSJMPTABLE, 0xE8B0): JP-Befehle an festen Adressen fuer Funktionen, die der Monitor ROM oder SA-1510-Abfang-Hooks aufrufen muessen: PRTMZF, PRTDBG, CMT_RDINF, CMT_RDDATA, CMT_WRINF, CMT_WRDATA, CMT_VERIFY, CMT_DIR, CNV_ATOS.
- Befehlstabelle (CMDTABLE): Die RomDisk/picoZ80-Build-Befehlsliste. Befehle umfassen: Laufwerksauswahl (0-9), 40/80-Spalten-Modus, B (Glockenumschaltung), BASIC, C (Loeschen), CP, CPM, D (Dump), EC (Loeschen), F (Floppy-Boot), f (AFI ROM), H (Hilfe), IR/IC (Verzeichnis), J (Sprung), LC/LR/LT und ihre NX-Varianten (SD/ROM/Band laden), M (Bearbeiten), P (Druckertest), R (DRAM-Test), SD2T, SC/ST (Speichern), T (Timer-Test), T2SD, V (Verifizieren).
- Initialisierung (MONITOR → SIGNON): Prueft auf Vorhandensein des tranZPUter-Boards ueber den CPLDINFO-I/O-Port. Setzt die anfaengliche SD-Laufwerksnummer auf 0. Erkennt den aktiven Monitor-ROM-Bank, um den 40-Spalten- oder 80-Spalten-Anzeigemodus zu bestimmen und konfiguriert die Anzeige entsprechend. Bei Video-Modul-Builds schreibt den Anzeigemodus in den DSPCTL-Latch.
- Befehlsdispatcher (ST1X): Liest den Eingabepuffer des Monitors, durchlaeuft CMDTABLE, extrahiert Bank und Handler-Adresse bei Uebereinstimmung, ruft den Bank-Switch-Stub auf und kehrt bei der Rueckkehr zur Schleife zurueck, um auf den naechsten Befehl zu warten. Wenn kein Eintrag uebereinstimmt, gibt er die Kontrolle an den SA-1510-Monitor zurueck, damit dieser sein "?"-Fehler ausgeben kann.
Rolle: Implementiert Floppy-Disk-Boot-Befehle. Im RomDisk-Build bietet dieser Bank die vollstaendigen F- (Laufwerksauswahl-Boot) und f- (direkter AFI-ROM-Sprung) Befehle.
Wichtige Funktionen:
rfs_bank2.asm -- SD-Karten-Controller (User ROM Bank 2)
- FLOPPY (F-Befehl): Fordert eine Laufwerksnummer an, wenn nicht in der Befehlszeile angegeben. Schreibt die Laufwerksauswahl- und Motoraktivierungs-Bytes an I/O-Port 0xDC (den WD1773-FDC-Steuerport). Wartet, bis der Spindelmotor die Betriebsgeschwindigkeit erreicht (typischerweise 300-500 ms, gemessen durch eine CPU-taktgezaehlte Verzoegerungsschleife). Liest den Boot-Sektor, ueberprueft das Boot-Disk-Signatur-Byte und uebergibt die Kontrolle an den Boot-Loader-Code im Sektor.
- FDCK (f-Befehl): Liest das Byte bei FDCROMADDR (0xF000), um zu ueberpruefen, ob das AFI-ROM vorhanden und nicht Null ist. Wenn gefunden, ruft direkt 0xF000 auf und uebergibt die Kontrolle an das originale SA-1510-Floppy-Boot-ROM. Dies ist nuetzlich als Fallback, wenn die WD1773-Laufwerksauswahllogik in FLOPPY nicht benoetigt wird.
Rolle: Das vollstaendige SD-Karten-Subsystem -- SPI-Treiber-Initialisierung, SD-Karten-Befehlsprotokoll und die SDCFS-Verzeichnis- und Datei-I/O-Routinen. Der SPI-Treibercode wird zur Assemblierungszeit durch die Flags HW_SPI_ENA, SW_SPI_ENA und PP_SPI_ENA ausgewaehlt.
Wichtige Funktionen:
rfs_bank3.asm -- Speicher-Utilitaeten (User ROM Bank 3)
- SDINIT: Implementiert die SD-Karten-SPI-Initialisierungssequenz. Deaktiviert Chip-Select, ruft SPIINIT auf, um die Karte an den SPI-Takt zu gewoehnen, aktiviert dann Chip-Select und sendet CMD0 (GO_IDLE_STATE) mit bis zu SD_RETRIES Versuchen. Bei Erfolg sendet CMD8 (SEND_IF_COND) zur Erkennung von SD v2-Karten, dann ACMD41 (SD_SEND_OP_COND) zum Verlassen des Leerlaufs. Behandelt SD v1, SD v2, SDHC, SDXC und MMC v3-Karten durch Pruefen der OCR-Antwort von CMD58.
- SDREAD / SDWRITE: Sektor-Level-Lesen (CMD17, READ_SINGLE_BLOCK) und Schreiben (CMD24, WRITE_BLOCK). SDREAD wartet auf das Datenstart-Token (0xFE) und liest dann 512 Bytes in den SDBUF-RAM-Puffer. SDWRITE sendet das Datenstart-Token, 512 Bytes Daten und einen Dummy-CRC und wartet dann auf das Freiwerden des Busy-Signals.
- SDDIR: Liest das Verzeichnis aus den ersten 8 KB der aktiven SD-Drive-Image in einen RAM-residenten Verzeichnis-Cache. Jeder Verzeichniseintrag ist im MZF-Header-Format (128 Bytes): Dateityp, Dateiname (17 Bytes, Sharp-Kodierung), Datengroesse, Ladeadresse, Ausfuehrungsadresse.
- SDLOAD: Berechnet bei einer Dateinummer aus dem Verzeichnis-Cache die 64-KB-ausgerichtete Sektoradresse des Datendblocks der Datei, liest die Datengroesse der Datei und laedt sie direkt an die Z80-Adresse, die im Ladeadressfeld des Verzeichniseintrags gespeichert ist.
- SDSAVE: Weist einen neuen Verzeichnisplatz zu oder findet einen bestehenden Eintrag mit demselben Namen zum Ueberschreiben. Schreibt die MZF-Header-Felder (Startsektor, Groesse, Ladeadresse, Ausfuehrungsadresse), dann schreibt die Dateidaten in den entsprechenden 64-KB-Block auf der SD-Karte.
- SPIINIT: Gewoehnt die SD-Karte an den SPI-Takt. Bei HW_SPI_ENA schreibt 0xFF in HWSPIDATA und loest HWSPISTART 10 mal aus (sendet 80 '1'-Bits). Bei PP_SPI_ENA (Parallelport-Bit-Bang) schaltet die Takt- und Datenleitungen 80 mal mit DJNZ um.
- SPICS: Setzt die SD-Karten-Chip-Select-Leitung. A = 0 aktiviert CS (low), A = 0xFF deaktiviert CS (high). Bei HW_SPI_ENA modifiziert die SDCS- und BBCLK-Bits von BNKCTRL und schreibt zurueck ins Hardware-Register.
- SPIOUT: Sendet ein Byte A an die SD-Karte. Bei HW_SPI_ENA: schreibt A in HWSPIDATA und loest HWSPISTART aus -- zwei Speicherschreibvorgaenge, ungefaehr 1 us pro Byte bei 8 MHz SPI-Takt. Bei PP_SPI_ENA: Bit-bangt das Byte MSB-first durch Umschalten der Takt- und Datenleitungen am Parallelport, 3 OUT-Befehle pro Bit.
- SPIIN: Empfaengt ein Byte von der SD-Karte. Bei HW_SPI_ENA: loest HWSPISTART aus, um 8 Bits einzutakten, liest dann HWSPIDATA. Bei PP_SPI_ENA: taktet jedes Bit ein, indem das Parallelport-Eingangsregister gelesen wird.
Rolle: Implementiert die D- (Hex-Dump), M- (Speicherbearbeitung) und CP- (Speicherkopie) Befehle, verfuegbar in allen Builds. Die T2SD- (Band nach SD) und SD2T- (SD nach Band) Befehle befinden sich ebenfalls in diesem Bank.
DUMPX (D-Befehl): Liest bis zu 20 Zeilen mit je 16 Bytes aus dem Zieladressbereich. Fuer jede Zeile wird die 4-stellige Hex-Adresse, 16 Hex-Byte-Werte mit einem Leerzeichen alle 4 Bytes und die 16 entsprechenden ASCII-Zeichen (Punkt fuer nicht druckbare Bytes) ausgegeben. Der Sharp MZ verwendet eine proprietaere Zeichenkodierung -- Bank 6 stellt die Sharp-zu-ASCII-Konvertierungstabelle bereit, die hier verwendet wird.
MCORX (M-Befehl): Interaktiver Speichereditor. Zeigt jedes Byte der Reihe nach mit Adresse und aktuellem Hex-Wert an. Der Benutzer gibt einen neuen 1- oder 2-stelligen Hex-Wert ein und drueckt Enter zum Schreiben, oder drueckt Enter allein, um das Byte unveraendert zu lassen. Ctrl+C oder die Escape-Taste beendet.
MCOPY (CP-Befehl): Block-Speicherkopie. Akzeptiert Quelladresse, Zieladresse und Byte-Anzahl aus der Befehlszeile als 4-stellige Hex-Werte. Fuehrt je nach Bedarf eine Vorwaerts- oder Rueckwaertskopie durch, um ueberlappende Bereiche korrekt zu behandeln.
T2SD und SD2T: Bidirektionale Band↔SD-Kopie. T2SD ruft die CMT-Laderoutine von Bank 4 auf, um eine Banddatei (einschliesslich ihres MZF-Headers) in den RAM zu laden, dann ruft sie die SDSAVE-Routine von Bank 2 auf, um sie auf das aktive SD-Laufwerk zu schreiben. SD2T ruft SDLOAD von Bank 2 auf, um eine Datei in den RAM zu laden, dann ruft sie die CMT-Speicherroutine von Bank 4 auf, um sie auf Band zu schreiben. Beide Befehle verwenden die MZF-Header-Felder (Dateiname, Groesse, Ladeadresse, Ausfuehrungsadresse), um das Verzeichnis medienuebergreifend konsistent zu halten.
rfs_bank4.asm -- CMT-Controller (User ROM Bank 4)
Rolle: Implementiert die LT/LTNX- (Band laden), ST- (Band speichern) und V- (Band verifizieren) Befehle.
Der Sharp MZ-80A verwendet eine 1200-Baud Kansas City Standard Kassetteninterface. Bytes werden als Bursts von 1200 Hz (Bit 0) oder 2400 Hz (Bit 1) Ton kodiert. Die Bandroutinen sind zeitkritisch -- sie muessen die eingehende Tonfrequenz messen und die ausgehende Wellenform mit Mikrosekundengenauigkeit erzeugen. Sie verwenden den 8253 Programmable Interval Timer (oder CPU-taktgezaehlte Verzoegerungsschleifen auf Plattformen ohne Timer) zur Messung der Bitperioden. Interrupts sind waehrend aller Bandoperationen deaktiviert (
rfs_bank5.asm -- Reserviert (User ROM Bank 5)
DI), um Timing-Stoerungen zu vermeiden.
LOADTAPE / LOADTAPENX: Liest den MZF-Header vom Band (128 Bytes: Dateityp, Dateiname, Datengroesse, Ladeadresse, Ausfuehrungsadresse), zeigt den Dateinamen an und liest dann die Datenbytes an die Ladeadresse. LOADTAPE fuehrt automatisch aus, indem nach einem erfolgreichen Laden an die Ausfuehrungsadresse gesprungen wird; LOADTAPENX kehrt stattdessen zum RFS-Befehlsprompt zurueck.
SAVEX (ST-Befehl): Schreibt den MZF-Header gefolgt von den Datenbytes auf Band. Akzeptiert Startadresse, Endadresse und Ausfuehrungsadresse aus der Befehlszeile oder fragt nach, wenn nicht angegeben.
VERIFYX (V-Befehl): Liest eine Banddatei und vergleicht sie byteweise mit dem RAM an der urspruenglichen Ladeadresse. Meldet Abweichungen mit ihrer Adresse und den erwarteten/tatsaechlichen Werten.
Das von den Bandroutinen verwendete MZF-Header-Format ist identisch mit dem SDCFS-Verzeichniseintrag-Format. Dies ist kein Zufall -- deshalb ist die Band-zu-SD-Kopie vollstaendig transparent und deshalb koennen LT-geladene Programme ohne Header-Konvertierung mit SC auf die SD-Karte zurueckgespeichert werden.
Rolle: Derzeit reserviert und im RomDisk-Build nicht verwendet. Der Bank-Slot existiert im Flash-ROM-Image und enthaelt den Bank-Switch-Stub am Standard-Offset, aber es sind keine benutzerzugaenglichen Befehle hier zugeordnet. Dieser Bank steht fuer zukuenftige Erweiterungen zur Verfuegung -- zum Beispiel das Hinzufuegen eines XModem-Uebertragungsprotokolls, eines Hex-Loaders oder zusaetzlicher speicherabgebildeter Hardware-Treiber.
rfs_bank6.asm -- Nachrichten und Zeichentabellen (User ROM Bank 6)
Rolle: Speichert den Hilfebildschirm-Text, alle Fehler- und Statusmeldungsstrings sowie die Sharp-MZ-Zeichensatz-zu-ASCII-Konvertierungstabelle.
HELPSCR (H-Befehl, ungefaehr Zeile 282): Eine Folge von CR-terminierten Strings, einer pro Zeile des Hilfebildschirms. Die BUILD_ROMDISK-Variante listet alle RomDisk-Befehle auf, einschliesslich T2SD, SD2T, F[X], f, LC, SC, EC, IR/IC und die Laufwerksauswahl-Ziffern 0-9. Die Liste wird durch ein einzelnes 000H-Byte abgeschlossen. Der H-Befehl durchlaeuft diese Liste und gibt jeden String aus, bis er den Terminator erreicht.
PRINTMSG / PRTFN: String-Druckutilitaeten. PRINTMSG verarbeitet eingebettete Marker-Bytes (z.B. 0xFF zum Einfuegen eines Wertes vom Stack) fuer formatierte Diagnosemeldungen. PRTFN gibt einen Sharp-MZ-Dateinamen (17 Bytes in Sharp-Kodierung) als ASCII-Text unter Verwendung der ATBL-Konvertierungstabelle aus.
ATBL (ASCII-zu-Sharp-Konvertierungstabelle): Eine 256-Byte-Lookup-Tabelle, die ASCII-Zeichencodes in ihre Sharp-MZ-Aequivalente und umgekehrt abbildet. Die Sharp-MZ-Serie verwendet eine proprietaere 8-Bit-Zeichenkodierung, bei der druckbare Zeichen andere Codepunkte als ASCII haben -- viele gaengige Zeichen (Buchstaben, Ziffern, Satzzeichen) sind verschoben oder umgeordnet. Jeder Code, der einen in Sharp-Kodierung gespeicherten Dateinamen auf dem Terminal anzeigt, muss jedes Byte durch diese Tabelle leiten.
rfs_bank7.asm -- Diagnosebefehle (User ROM Bank 7)
Rolle: Implementiert die R- (DRAM-Test) und T- (Timer-Test) Befehle im RomDisk-Build.
MEMTEST (R-Befehl): Fuehrt einen Walking-Bit-Pattern Schreib-/Verifikationstest ueber den gesamten Benutzer-RAM-Bereich (0x1200-0xCFFF) durch. Schreibt jedes der 8 Einzelbit-Muster (0x01, 0x02, 0x04, ..., 0x80) in jedes Byte des Bereichs, liest dann zurueck und verifiziert jedes Byte. Jede Abweichung wird mit ihrer Adresse und den erwarteten/tatsaechlichen Werten gemeldet. Fuehren Sie diesen Befehl nach dem Hinzufuegen neuer RAM-residenter Datenstrukturen aus, um zu ueberpruefen, dass die Adressierung korrekt ist, bevor die neuen Strukturen von anderem Code verwendet werden.
TIMERTST (T-Befehl): Testet den 8253 Programmable Interval Timer, indem er in mehrere Modi programmiert und ueberprueft wird, ob er wie erwartet zaehlt und ablaueft. Nuetzlich zur Diagnose von Maschinen, bei denen Bandoperationen unzuverlaessig sind -- inkorrektes 8253-Verhalten manifestiert sich als systematische Timing-Fehler in den CMT-Bitraten-Messungen.
rfs_mrom.asm -- Monitor-ROM-Utilitaeten (Monitor ROM Bank 3)
Rolle: Stellt die ROM-Scan- und MZF-Dateilade-Routinen bereit, die aus dem Monitor-ROM-Bereich statt aus dem User-ROM-Bereich ausgefuehrt werden muessen.
Warum ein separater Monitor-ROM-Bank? Die IR- und LR-Befehle zaehlen MZF-Programmabbilder auf, die in den oberen User-ROM-Flash-Baenken gespeichert sind (User-ROM-Baenke ueber 11 enthalten gepackte MZF-Programme). Um einen dieser Baenke zu scannen, muss die Firmware das User-ROM-Fenster auf diesen Bank umschalten. Aber der Scanning-Code selbst befindet sich im User ROM -- wenn er den User-ROM-Bank umschaltet, ersetzt er sofort seinen eigenen Code durch einen anderen Bank und stuerzt ab.
Die Loesung besteht darin, die Scanning-Schleife in Monitor ROM Bank 3 zu platzieren. Die Monitor-ROM-Bank-Umschaltung (ueber BNKSELMROM) ist vollstaendig unabhaengig von der User-ROM-Bank-Umschaltung (ueber BNKSELUSER). Code, der in Monitor ROM Bank 3 laeuft, kann frei durch die User ROM Baenke 12, 13, 14... zyklieren, um ihre MZF-Header aufzuzaehlen, ohne jemals den Monitor-ROM-Code zu stoeren, der tatsaechlich ausgefuehrt wird.
Wichtige Funktionen:
- ROMDIR: Scannt alle User-ROM-Baenke ueber 11, liest jeden 128-Byte-MZF-Header vom Anfang jedes Banks und baut ein RAM-residentes ROM-Verzeichnis auf. Das Verzeichnis wird vom IR-Befehl verwendet, um eine Liste der ROM-residenten Programme anzuzeigen.
- ROMLOAD: Schaltet bei einer Dateinummer aus dem ROM-Verzeichnis das User-ROM-Fenster zum entsprechenden Bank um, liest den MZF-Header, um Ladeadresse und Datengroesse zu finden, kopiert die Programmdaten vom User ROM an die Ziel-Ladeadresse im RAM und springt optional an die Ausfuehrungsadresse. Die LRNX-Variante kehrt stattdessen zum RFS-Befehlsprompt zurueck.
SPI-Treiber: Hardware vs. Software
Der SPI-Treiber in
rfs_bank2.asm ist auf drei Weisen implementiert, ausschliesslich zur Assemblierungszeit ausgewaehlt. Die Auswahl wird durch die drei sich gegenseitig ausschliessenden Flags in rfs_definitions.asm gesteuert:
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 portHardware-SPI (HW_SPI_ENA = 1)
Verfuegbar auf RomDisk PCB v2.0 und spaeter. Das PCB traegt einen seriellen 74HCT595-Ausgangsschieberegister (MOSI/CLK) und einen parallelen 74HCT165-Eingangsschieberegister (MISO/CLK), getaktet durch dedizierte Hardware-Logik mit 8 MHz -- dem achtfachen des 2-MHz-Bustakts des Z80.
Das Senden eines Bytes erfordert zwei Speicherschreibvorgaenge: das Byte in HWSPIDATA (0xEFFB) schreiben, dann einen beliebigen Wert in HWSPISTART (0xEFFC) schreiben. Die Hardware taktet alle 8 Bits automatisch in etwa 1 us aus. Das Empfangen eines Bytes ist aehnlich: in HWSPISTART schreiben, um 8 Bits einzutakten, dann HWSPIDATA lesen. Der Z80 braucht nur die Zeit, um zwei Speicherschreibbefehle zwischen den Bytes auszufuehren -- die Hardware-Schieberegister arbeiten gleichzeitig.
Da HWSPIDATA und HWSPISTART im Coded-Latch-Bereich 0xEFF8-0xEFFF liegen, sind sie nur zugaenglich, waehrend die Steuerregister entsperrt sind (d.h. nach der 16-Lese-Sequenz). Die SDINIT-, SDREAD- und SDWRITE-Routinen in Bank 2 setzen voraus, dass die Steuerregister bereits entsperrt sind, wenn sie aufgerufen werden, was innerhalb der RFS-Ausfuehrungsumgebung immer der Fall ist.
Software-SPI (SW_SPI_ENA = 1)
Verfuegbar auf RomDisk PCB v2.0 und spaeter als kostenguenstigere Alternative zu den Hardware-Schieberegistern. Die Firmware schaltet manuell einzelne Bits des BNKCTRL-Registers (0xEFFF) um, um die SPI-Takt- (BBCLK) und MOSI-Datenleitungen (BBMOSI) zu treiben, und liest das MISO-Bit von BNKCTRL fuer eingehende Daten. Jedes Bit erfordert mehrere Schreibvorgaenge auf BNKCTRL -- Takt high umschalten, Takt low umschalten -- was ungefaehr 20-40 us pro Byte bei 2 MHz Z80-Takt ergibt, etwa 40x langsamer als Hardware-SPI.
Der SW_SPI_ENA-Codeblock in SPIOUT bangt jedes Byte MSB-first unter Verwendung einer Schleife, die den aktuellen BBMOSI- und BBCLK-Zustand liest, das relevante Bit aendert und zurueck in BNKCTRL schreibt. Die gleiche Coded-Latch-Entsperranforderung gilt -- BNKCTRL ist nur nach der 16-Lese-Sequenz beschreibbar.
Parallelport-SPI (PP_SPI_ENA = 1)
Die urspruengliche RomDisk v1-Implementierung, die den Centronics-Paralleldruckerport des Sharp MZ-80A als improvisierten SPI-Bus verwendet. Die Daten-Leitungen (D0-D7) des Druckerports werden umgewidmet: ein Bit treibt den SPI-Takt (CLOCK), ein Bit treibt MOSI-Daten (DOUT), ein Bit treibt den Chip-Select (CS) und ein Bit liest MISO-Daten (DIN) vom Statusregister des Ports.
Senden eines Bytes in SPIOUT (PP_SPI_ENA-Pfad): Das Byte wird drei Mal nach links rotiert, um Bit 7 mit der DOUT-Pin-Position auszurichten, dann treibt eine 8-Iterationen-Schleife DOUT und Takt high/low unter Verwendung von drei
Wahl einer SPI-Variante
OUT (SPI_OUT), A-Befehlen pro Bit. SPIINIT taktet 80 '1'-Bits, indem die Takt- und Datenleitungen 80 Mal mit DJNZ umgeschaltet werden. Alle Parallelport-Zugriffe verwenden I/O-Port-Befehle (IN / OUT) anstelle von speicherabgebildeten Registern.
PP_SPI_ENA erfordert keine Coded-Latch-Entsperrung -- der Parallelport befindet sich im Z80-I/O-Adressraum, nicht im Speicheradressraum, und ist daher immer zugaenglich. Dies war beabsichtigt fuer das v1-Design, bei dem der Coded-Latch-Schaltkreis noch nicht existierte.
| 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 |
Einen neuen Monitor-Befehl hinzufuegen
Das folgende Beispiel fuegt einen PEEK-Befehl hinzu, der ein einzelnes Byte von einer gegebenen Adresse liest und ausgibt. Der Handler gehoert in Bank 3 (Speicher-Utilitaeten).
Schritt 1: Handler in rfs_bank3.asm schreiben
; 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
Parameter sind im Monitor-Eingabepuffer direkt nach dem Befehlsstring verfuegbar. HLHEX ist eine Utilitaetsroutine (verfuegbar in Bank 5 oder ueber die Sprungtabelle), die 4 Hex-Ziffern aus dem Eingabepuffer liest und den 16-Bit-Wert in HL zurueckgibt. PRTHX gibt den Akkumulator als zwei Grossbuchstaben-Hex-Ziffern aus.
Schritt 2: Befehlstabelleneintrag in rfs.asm hinzufuegen
; In rfs.asm, within the CMDTABLE block (inside IF BUILD_ROMDISK+BUILD_PICOZ80 = 1):
;
; Flags byte: not-end (bit7=0), not-exact (bit6=0),
; bank 3 (bits5:3 = 011 = 0x18), length 4 (bits2:0 = 100 = 0x04)
DB 000H | 000H | 018H | 004H
DB "PEEK"
DW PEEK
Platzieren Sie diesen Eintrag vor kuerzeren Eintraegen, die dieselben fuehrenden Zeichen teilen, um zu vermeiden, dass der kuerzere Eintrag zuerst uebereinstimmt. Das Flags-Byte wird zusammengesetzt als:
000H (nicht Tabellenende) ODER 000H (nicht exakte Uebereinstimmung) ODER 018H (Bank 3: 0b011 um 3 nach links verschoben = 0x18) ODER 004H (Befehlsstring-Laenge 4).
Schritt 3: Hilfetext in rfs_bank6.asm hinzufuegen
; In rfs_bank6.asm, within the HELPSCR block (before the 000H terminator):
DB "PEEKXXXX - read byte at XXXX", 00DH
Der Hilfebildschirm verwendet durchgehend Grossbuchstaben (Kleinbuchstaben sind in der Sharp-Zeichenkodierung schwer einzubetten, ohne die Bytewerte manuell zu berechnen).
Schritt 4: Kompilieren
cd /dvlp/Projects/MZ80A_RFS/software/RFS ./build.sh
Der Assembler meldet einen Fehler, wenn Bank 3 jetzt 2 KB ueberschreitet. Wenn das passiert, suchen Sie nach totem Code, ungenutzten Meldungsstrings oder doppelten Utilitaetsroutinen, die aus diesem Bank entfernt oder nach Bank 5 (derzeit leer) verschoben werden koennen.
Neue Hardware-Unterstuetzung hinzufuegen
Eine neue SPI-Variante hinzufuegen
Um eine neue SPI-Hardware-Variante hinzuzufuegen -- zum Beispiel ein zweites Parallelport-Design mit anderen Bit-Zuordnungen (PP2_SPI_ENA):
- Flag zu rfs_definitions.asm hinzufuegen:
PP2_SPI_ENA EQU 0 ; Second parallel port SPI variant (custom hardware)
- Assertion am Anfang von rfs_bank2.asm hinzufuegen, um versehentliche Doppelaktivierung zu erkennen:
; Guard: only one SPI flag may be set at a time. ; GLASS does not have a built-in ASSERT directive, so encode this as a build-time ; value check. If more than one flag is set, the total sum exceeds 1 and the error ; manifests as wrong code being assembled into the SPI driver functions. ; (Document this constraint prominently in the comment block above SDINIT.)
- Bedingte Assemblierungsbloecke hinzufuegen in rfs_bank2.asm fuer jede SPI-Funktion (SPIINIT, SPICS, SPIOUT, SPIIN). Folgen Sie dem bestehenden verschachtelten IF/ELSE/ENDIF-Muster:
SPIOUT: IF HW_SPI_ENA = 1
; Hardware SPI path (existing code)
LD (HWSPIDATA),A
LD (HWSPISTART),A
RET
ELSE
IF SW_SPI_ENA = 1
; Software bit-bang path (existing code)
ELSE
IF PP2_SPI_ENA = 1
; New PP2 path:
; (implement bit-bang for the new port layout here)
RET
ELSE
; Original PP_SPI_ENA (centronics) path (existing code)
ENDIF
ENDIF
ENDIF
- Neue Port-Konstanten definieren in rfs_definitions.asm neben den bestehenden SPI_OUT, DOUT_MASK, CLOCK_HIGH usw. Konstanten, geschuetzt mit
IF PP2_SPI_ENA = 1 ... ENDIF, um Symbolkonflikte zu vermeiden. - build.sh aktualisieren, wenn die neue Variante ein anderes Flash-Image-Layout oder einen anderen Ausgabedateinamen erfordert.
Um RFS auf eine neue Hardware-Plattform zu portieren (zum Beispiel eine neue FPGA-basierte MZ-80A-Reimplementierung):
- BUILD_*-Flag hinzufuegen in rfs_definitions.asm:
BUILD_NEWBOARD EQU 0. - Adresskonstanten hinzufuegen, wenn das neue Board ROM-Fenster an anderen Adressen abbildet. Die haeufigste Variation ist die User-ROM-Basisadresse und die Bank-Steuerregister-Adressen.
- Bedingte Assemblierungsbloecke hinzufuegen im gesamten Quellcode fuer jeden Punkt, an dem sich das Hardware-Verhalten unterscheidet: Bank-Latch-I/O-Adressen, SPI-Controller-Register, SD-Karten-Erkennungserkennung, Anzeige-Modusumschaltung und der MONITOR-Einstiegspunkt-Plattformerkennungscode in rfs.asm.
- Neue Bank-Switch-Stub-Variante hinzufuegen in jeder Bank-Datei, wenn der Bank-Select-Mechanismus der neuen Plattform sich sowohl vom Coded-Latch- als auch vom FusionX-Port-Schema unterscheidet. Der Stub bei UROMBSTBL muss beim Kaltstart korrekt funktionieren, bevor eine Initialisierung ausgefuehrt wurde.
- build.sh aktualisieren mit einem neuen Build-Abschnitt, der
BUILD_NEWBOARD=1setzt und das entsprechende ROM-Image fuer das neue Flash-Chip-Layout erzeugt.
Debugging-Tipps
Debug-Ausgabe aktivieren: Setzen Sie
ENADEBUG EQU 1 in rfs_definitions.asm vor dem Build. Dies schliesst zusaetzliche Diagnose-Druckausgaben an strategischen Punkten in der SD-Karten-Initialisierungssequenz, SDCMD-Antworten und SDCFS-Verzeichnis-Parsing ein. Der zusaetzliche Code ist bedingt und hat keine Auswirkung auf die RomDisk-ROM-Image-Groesse, wenn er deaktiviert ist.
User-ROM-Bank-0-Eingangsbereich dumpen: Geben Sie D E800 ein, um die ersten 320 Bytes des aktuellen User-ROM-Banks zu dumpen. Die ersten Bytes sollten das NOP bei 0xE800 zeigen, gefolgt von den HWSELROM-Makro-Bytes, gefolgt von einem JP-Befehl. Der Bank-Switch-Stub bei 0xE820 sollte erkennbare Muster von PUSH AF / LD A, n-Sequenzen enthalten. Wenn der Dump wie zufaellige Daten aussieht, wurde der Coded Latch moeglicherweise nicht richtig initialisiert und der falsche Bank wird ausgewaehlt.
Bank-Steuerregister pruefen: Geben Sie D EFF8 ein, um den Bank-Steuerregisterbereich zu dumpen. Nach dem Durchfuehren einer manuellen Bank-Umschaltung sollte das Byte bei 0xEFFF die von Ihnen geschriebene Bank-Nummer widerspiegeln. Wenn es sich nicht aendert, pruefen Sie, ob die 16-Lese-Coded-Latch-Entsperrsequenz vor dem Schreibvorgang ausgefuehrt wird.
Coded-Latch-Entsperrzaehlung ueberpruefen: Wenn Bank-Steuerregister-Schreibvorgaenge keine Wirkung zu haben scheinen, ist die haeufigste Ursache, dass die 16-Lese-Sequenz nicht abgeschlossen wird. Dies kann passieren, wenn ein Schleifenbefehl im Bank waehrend der normalen Ausfuehrung Lesevorgaenge von 0xEFF8-0xEFFF durchfuehrt (siehe die DJNZ-Warnung im Bank-Switching-Abschnitt). Zaehlen Sie die Lesezyklen in der Entsperrsequenz und ueberpruefen Sie, ob der Schleifenzaehler genau auf 16 eingestellt ist.
v2.1-Boot zum SA-1510-Monitor ohne + RFS-Prompt: Wenn die Maschine in den nativen SA-1510-Monitor bootet und die RFS + RFS-Anmeldezeile nicht erscheint, wird der User-ROM-Einstiegspunkt bei 0xE800 nicht aufgerufen. Pruefen Sie, ob der Coded Latch nicht versehentlich durch DRAM-Refresh-Zyklen ausgeloest wird -- das AND-Gatter (D1/D2) auf v2.1 wurde speziell hinzugefuegt, um zu verhindern, dass Refresh-Zyklen den 74HCT191-Zaehler erhoehen. Auf v2.0-Boards ohne dieses Gatter koennen Refresh-Zyklen den Terminal Count erreichen, bevor der ROM-Einstiegspunkt laeuft.
MEMTEST nach dem Hinzufuegen von RAM-residenten Daten ausfuehren: Geben Sie R unmittelbar nach dem Hinzufuegen neuer RAM-residenter Datenstrukturen oder Variablen ein, um Adressierungsfehler fruehzeitig zu erkennen. Eine fehlschlagende Adresse im Bereich 0x1200-0xCFFF, die mit der Groesse einer neuen Struktur korreliert, deutet auf einen Off-by-One-Fehler in der Adressberechnung hin, nicht auf einen defekten RAM-Chip.
SD-Karten-Initialisierungsfehler: Wenn SD-Befehle unerwartete Antwortcodes mit aktiviertem ENADEBUG zurueckgeben, ueberpruefen Sie, ob das SPI-Chip-Select-Timing korrekt ist -- CS muss vor CMD0 aktiviert (low) und waehrend des gesamten Befehls-/Antwortustauschs beibehalten werden. Bei HW_SPI_ENA pruefen Sie, ob das SDCS-Bit in BNKCTRL von SPICS korrekt gesetzt und geloescht wird. Bei PP_SPI_ENA ueberpruefen Sie, ob das Parallelport-Ausgangsregister vor dem ersten SPIINIT-Aufruf initialisiert wird.
Bankuebergreifende Aufruffehler: Wenn ein bankuebergreifender Aufruf den falschen Code auszufuehren scheint oder mit Registerkorruption zurueckkehrt, pruefen Sie, ob der Bank-Switch-Stub im Ziel-Bank bytegenau mit dem in Bank 0 uebereinstimmt. Jeder Bank muss eine identische Kopie des Stubs bei UROMBSTBL haben. Verwenden Sie D E820, um den Stub von Bank 0 zu dumpen, schalten Sie dann manuell zum Ziel-Bank um und dumpen Sie denselben Adressbereich zum Vergleich.
Referenzseiten
| 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 |