ROM-Dateisystem (RFS) — Entwicklerhandbuch
RFS-Entwicklerhandbuch
Dieses Handbuch ist eine detaillierte Einfuehrung in den RFS-Quellcode und die Entwicklungsumgebung. Es erklaert Z80-Assembler-Konzepte fuer Entwickler, die moeglicherweise nicht mit der Sprache vertraut sind, fuehrt durch jedes Quellmodul, dokumentiert die Bank-Switching-Architektur und zeigt, wie man neue Befehle hinzufuegt, vorhandene Module aendert und RFS auf neue Hardware portiert.
Fuer Hardware-Architektur und Build-System-Details siehe den Technischen Leitfaden. Fuer die benutzerorientierte Bedienung siehe das Benutzerhandbuch.
Einfuehrung in Z80-Assembler fuer Nicht-Assembler-Programmierer
Die gesamte RFS-Firmware ist in Z80-Assembler 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: Jede Anweisung wird in ein oder einige 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 in RFS verwendeten:
| Register | Groesse | Rolle |
|---|---|---|
| A | 8-Bit | Akkumulator — das primaere Register fuer Arithmetik, Logik und I/O-Operationen. Fast jede Anweisung involviert A. |
| B, C | 8-Bit | Allgemein. BC zusammen bildet ein 16-Bit-Paar, haeufig als Schleifenzaehler oder Byteanzahl verwendet. |
| D, E | 8-Bit | Allgemein. DE zusammen ist ein 16-Bit-Paar, haeufig als Quell- oder Zielzeiger verwendet. |
| H, L | 8-Bit | Allgemein. HL zusammen ist der Haupt-16-Bit-Speicherzeiger — die meisten Speicher-Lese/Schreib-Anweisungen verwenden HL. |
| IX, IY | 16-Bit | Indexregister — verwendet fuer Basis+Offset-Speicheradressierung. Langsamer als HL, aber praktisch fuer strukturierte Daten. |
| SP | 16-Bit | Stapelzeiger — zeigt auf die Spitze des Aufrufstapels. PUSH und POP verwenden SP automatisch. |
| PC | 16-Bit | Programmzaehler — die Adresse der aktuellen Anweisung. Automatisch inkrementiert; durch Spruenge und Aufrufe geaendert. |
| F | 8-Bit | Flagregister — einzelne Bits, die durch arithmetische Operationen gesetzt werden: Z (Null), C (Uebertrag), S (Vorzeichen), P/V (Paritaet/Ueberlauf). |
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 Speicheradresse 0x1200.CALL addr— Unterprogrammaufruf. Legt die Rueckkehradresse (naechste Anweisung) auf den Stapel und springt zuaddr. Entspricht einem Funktionsaufruf.RET— Rueckkehr aus Unterprogramm. Holt die Rueckkehradresse vom Stapel und springt dorthin.JP addr— Unbedingter Sprung zuaddr.JP Z, addrspringt nur, wenn das Zero-Flag gesetzt ist (d.h. die letzte Operation ergab Null).JR offset— Kurzer relativer Sprung (−128 bis +127 Bytes). Schneller und kompakter als JP fuer nahegelegene Verzweigungen.DJNZ offset— B dekrementieren und springen, wenn nicht Null. Die kanonische Z80-Schleifenanweisung:LD B, 10 / LOOP: ... / DJNZ LOOPwiederholt sich 10-mal.ADD A, n— n zu A addieren.SUB nsubtrahiert.AND n,OR n,XOR n— bitweise Logik auf A.IN A, (port)— Aus I/O-Port in A lesen.OUT (port), A— A an I/O-Port schreiben. So kommuniziert der Z80 mit Hardware (dem WD1773, SPI-Controller, der Bank-Verriegelung usw.).PUSH rr / POP rr— Ein 16-Bit-Registerpaar auf dem Stapel sichern/wiederherstellen.EI / DI— Interrupts aktivieren / deaktivieren. Code, der nicht unterbrochen werden darf (z.B. zeitkritische Band-Operationen), wird zwischen DI und EI gekapselt.
Der Z80 bietet verschiedene Moeglichkeiten, um anzugeben, woher Daten kommen oder wohin sie gehen:
GLASS Assembler-Syntax
- Sofort:
LD A, 42— der Wert ist direkt in den Anweisungsbytes eingebettet. - Register:
LD A, B— Daten kommen aus einem Register 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 in der Anweisung. - Indiziert:
LD A, (IX+5)— IX haelt eine Basisadresse; 5 wird addiert, um die effektive Adresse zu erhalten. Wird in RFS fuer den Zugriff auf Felder innerhalb fest formatierter Datenstrukturen verwendet.
RFS verwendet den GLASS Z80-Assembler. Wichtige Syntaxmerkmale:
- Kommentare beginnen mit
;— alles rechts von einem Semikolon wird ignoriert. - Labels sind Bezeichner, gefolgt von
:. Ein Label am Zeilenanfang benennt die Adresse der naechsten Anweisung. EQUdefiniert eine Konstante:BELL EQU 007H— der Assembler ersetzt jedes Vorkommen von BELL durch 0x07.DB(Define Byte) fuegt Rohbytes ein:DB 0x41, 0x42gibt zwei Bytes aus. Wird fuer Zeichenketten und Nachschlagetabellen verwendet.DW(Define Word) fuegt 16-Bit-Little-Endian-Werte ein:DW HANDLERgibt die Adresse des HANDLER-Labels aus.ORG addrsetzt den Assembly-Ursprung — nachfolgender Code wird so assembliert, als laege er anaddr.INCLUDE "file.asm"bindet eine andere Datei textuell an der aktuellen Position ein.IF / ENDIFbedingte Assemblierung:IF BUILD_SFD700 = 1 ... ENDIF— die eingeschlossenen Anweisungen werden nur assembliert, wenn die Bedingung wahr ist. So baut RFS vier verschiedene Firmware-Varianten aus einem Quellbaum.
Quellbaum
| Pfad | Inhalt |
|---|---|
asm/ |
Alle Z80-Assembler-Quelldateien |
asm/include/ |
Gemeinsame Definitionen und Konfigurationsdateien |
asm/dis/ |
Disassemblierte Referenzdateien fuer SA-5510 und XPATCH |
tools/ |
Build-Skripte, GLASS-Assembler, Werkzeug-Binaerdateien |
MZF/ |
MZF-Format-Anwendungsdateien, nach Maschinentyp organisiert |
MZB/ |
Sektorausgerichtete Binaer-Anwendungen (vom Build generiert) |
roms/ |
Build-Ausgabe — ROM-Images und SD-Karten-Images |
releases/ |
Vorgefertigte Release-Binaerdateien |
config/ |
CP/M-Disk-Format-Definitionen (diskdefs) |
cpmtools/ |
cpmtools-Quellcode (Submodul) |
src/ |
Quellcode fuer unterstuetzende Werkzeuge |
Konfiguration: rfs_definitions.asm
Dies ist die zentrale Konfigurationsdatei, die von jeder anderen Quelldatei ueber
Build-Ziel-Flags
INCLUDE "rfs_definitions.asm" eingebunden wird. Jede Assembly-Zeitoption wird hier gesteuert. Die wichtigsten Abschnitte:
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
Genau ein
Adresskonstanten
BUILD_*-Flag muss gleichzeitig auf 1 gesetzt sein. Alle bedingten Assemblierungsbloecke im gesamten Quellcode pruefen diese Flags, um plattformspezifischen Code einzubinden oder auszuschliessen.
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)
Diese Konstanten definieren, wo im Z80-Adressraum jedes ROM-Fenster liegt. Code, der fuer das User-ROM-Fenster kompiliert wird, assembliert immer mit
Zeichen- und Steuerdefinitionen
ORG 0xE800; Code fuer das Monitor-ROM-Fenster assembliert bei ORG 0x0000.
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 SPACE EQU 020H ; ASCII space DELETE EQU 07FH ; Delete key
Bank-Switching im Detail
Bank-Switching ist das Herzstueck der RFS-Architektur. Sein Verstaendnis ist vor jeder Aenderung einer Quelldatei unerlaesslich.
Warum Banking benoetigt wird
Der Sharp MZ-80A gibt dem User-ROM nur 2 KB Adressraum (0xE800–0xEFFF). 2 KB koennen nur ein paar hundert Anweisungen aufnehmen — bei weitem nicht genug fuer ein Dateisystem, einen Assembler, einen Disassembler, einen Band-Controller, einen SD-Karten-Treiber und das CP/M-CBIOS. Die Loesung besteht darin, physisch umzuschalten, welche 2 KB eines 512-KB-Flash-Chips in diesem Adressbereich sichtbar sind. Durch das Speichern von 12 verschiedenen 2-KB-RFS-Baenken (Baenke 0–11) im Flash-Chip und das Umschalten zwischen ihnen bei Bedarf erreicht RFS effektiv 24 KB ROM-Code — mit weiteren 4 Baenken (12–15), die fuer das CP/M-CBIOS reserviert sind. Zusaetzlich halten drei der 16 Monitor-ROM-Seiten (Baenke 6, 7 und 9) die Opcode-Tabellen des Z80-Assemblers/Disassemblers und die RFS-Nachrichtenzeichenketten, wodurch der verfuegbare ROM-Speicher erweitert wird, ohne User-ROM-Kapazitaet zu verbrauchen.
Der Bank-Switch-Stub
Jede Bank beginnt mit einer identischen Kopie des Bank-Switching-Stubs, der die ersten 32 Bytes der Bank (0xE800–0xE81F) belegt. Dieser Stub bietet:
Befehlstabellenformat (rfs.asm)
- Ein Standard-Aufruf-Gateway: Jede Bank kann jede Routine in jeder anderen Bank aufrufen, indem sie den Stub mit der Zielbanknummer und der Zieladresse aufruft. Der Stub schreibt die Banknummer in die Hardware-Verriegelung (typischerweise ein I/O-Port-Schreibvorgang) und ruft dann die angeforderte Adresse auf. Die aufgerufene Routine laeuft in der neuen Bank, und wenn sie zurueckkehrt, schaltet der Stub zur urspruenglichen Bank zurueck.
- Ein konsistenter Einsprungpunkt: Da der Stub an einem festen Offset liegt (0xE800 + 0x20 fuer die Bank-Switch-Tabelle), kann Code in Bank 0 den Stub in Bank 3 zuverlaessig finden, obwohl er die internen Adressen von Bank 3 nie gesehen hat.
Der Monitor-Befehlsverteiler 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 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
Der Verteiler liest die Monitor-Eingabezeile, durchlaeuft die Tabelle und fuer jeden Eintrag:
- Vergleicht die Eingabe mit der Befehlszeichenkette (bei einigen Builds ohne Beachtung der Gross-/Kleinschreibung).
- Bei Uebereinstimmung extrahiert er die Banknummer und Handler-Adresse aus dem Tabelleneintrag.
- Fuehrt einen Bankwechsel zur Zielbank durch.
- Ruft den Handler mit allen verbleibenden Eingaben (Parametern) auf, die im Monitor-Eingabepuffer verfuegbar sind.
CMDTABLE2 fuer den SFD-700-Build und CMDTABLE fuer den RomDisk/picoZ80-Build. Beide sind identisch strukturiert, enthalten aber unterschiedliche Befehlssaetze — insbesondere schliesst die SFD-700-Tabelle SD-Karten-Befehle aus (IC, LC, SC, EC, DUC, T2SD, SD2T), da diese Hardware keine SD-Karte hat. Die Befehle ASM und DASM sind in beiden Tabellen vorhanden.
Modul-Walkthroughs
rfs.asm — Befehlsverteiler (User-ROM Bank 0)
Rolle: Der Einsprungpunkt fuer alle RFS-Funktionalitaet. Wenn der SA-1510-Monitor einen Befehl nicht erkennt, uebergibt er die Kontrolle an den User-ROM-Einsprungpunkt bei 0xE800. Dies ist immer Bank 0.
Schluesselabschnitte:
rfs_bank1.asm — Diskettencontroller (User-ROM Bank 1)
- Bank-Switch-Stub (0xE800–0xE81F): Das oben beschriebene Cross-Bank-Aufruf-Gateway. Jede Bank hat eine identische Kopie.
- Bank-Switch-Tabelle (0xE800 + 0xB0): Eine Sprungtabelle, die Banknummern auf ihre physischen Flash-ROM-Adressen abbildet. Wird beim Booten geaendert, wenn die Hardware eine nicht-sequentielle Bankadressierung erfordert.
- Befehlstabelle (CMDTABLE / CMDTABLE2): Die Liste aller RFS-Befehle mit ihrer Bank- und Handler-Adresse.
- Haupt-Verteilerschleife: Liest den Eingabepuffer des Monitors, durchlaeuft die Befehlstabelle, fuehrt den Bankwechsel durch und ruft den Handler auf. Wenn kein Befehl uebereinstimmt, kehrt sie zum SA-1510-Monitor zurueck, damit dieser den "?"-Fehler ausgibt.
- RFS-Initialisierung: Beim ersten Einsprung nach dem Reset erkennt RFS die Hardware-Plattform (aus dem MODE-Register beim SFD-700 oder aus Flags beim RomDisk), initialisiert SPI und SD-Karte und setzt das anfaengliche Laufwerk auf 0.
BUILD_SFD700 = 1, assembliert rfs.asm mit ORG 0xE000 / ALIGN 0xE300 statt ORG 0xE800, weil der SFD-700 sein User-ROM-Fenster bei 0xE300–0xEFFF abbildet (0xE000–0xE2FF ist fuer speicherabgebildete MZ-700-I/O reserviert).
Rolle: Implementiert Diskettenbefehle — Floppy-Boot (F / FL), Floppy-Verzeichnis (FD) und den direkten AFI-Sprung (f). Der vollstaendige FDC-Befehlssatz wird bei allen Builds assembliert.
Schluesselfunktionen:
rfs_bank2.asm — SD-Karten-Controller (User-ROM Bank 2)
- FLOPPY (FL): Fragt nach einer Laufwerksnummer (falls nicht in der Befehlszeile angegeben), initialisiert die Diskette, liest den Boot-Sektor, verifiziert die Disk-Signatur, extrahiert die Programminformationen (Name, Ladeadresse, Groesse, Ausfuehrungsadresse), laedt das Programm in den Speicher und fuehrt es aus.
- FDDIR (FD): Listet das Verzeichnis der Dateien auf einer Diskette auf. Akzeptiert eine optionale Laufwerksnummer (1–4, Standard 1). Liest den Boot-Sektor, verifiziert das MZ-700-Disk-Format und durchsucht dann die Verzeichnissektoren, wobei Dateinamen, Ladeadressen, Ausfuehrungsadressen und Dateigroessen angezeigt werden.
- FDCK: Liest das Byte bei 0xF000, um zu verifizieren, dass das AFI-ROM vorhanden und ungleich Null ist, und ruft dann 0xF000 direkt auf. Dies ist der f-Befehl (Kleinbuchstabe) bei allen Builds.
- Am Ende der Bank stellt eine
ALIGN 0xF000-Direktive sicher, dass das SFD-700-ROM-Image das AFI-Boot-ROM praezise bei 0xF000 im Flash-Layout positioniert.
Rolle: Das komplette SD-Karten-Subsystem — SPI-Initialisierung, SD-Karten-Befehlsprotokoll und die SDCFS-Verzeichnis- und Datei-I/O-Routinen. Beim SFD-700-Build wird der SD-Karten-Controller-Code nicht assembliert (die SFD-700-Hardware hat keine SD-Karten-Schnittstelle); der Bank-Slot ist im ROM-Image vorhanden, enthaelt aber nur den Bank-Switching-Stub.
Schluesselfunktionen:
rfs_bank3.asm — Speicherwerkzeuge (User-ROM Bank 3)
- SPI-Treiber (Hardware oder Software): Die bedingte Assemblierung waehlt zwischen Hardware-SPI (unter Verwendung der RomDisk v2-SPI-Controller-Register) und Software-Bit-Bang-SPI (Umschalten einzelner I/O-Port-Bits zum Takten des SPI-Busses). Der Hardware-SPI-Pfad ist erheblich schneller und wird auf allen aktuellen Platinen verwendet (
HW_SPI_ENA = 1). - SD-Karten-Initialisierung (SDINIT): Implementiert die SD-Karten-Initialisierungssequenz — sendet CMD0 (GO_IDLE), CMD8 (SEND_IF_COND), ACMD41 (SD_SEND_OP_COND), um die Karte vom SPI-Modus in den aktiven Zustand zu schalten. Behandelt sowohl SD- als auch SDHC/SDXC-Kartentypen durch Pruefung der OCR-Antwort.
- Sektorlesen (SDREAD): Sendet CMD17 (READ_SINGLE_BLOCK) mit einer 32-Bit-Sektoradresse, wartet auf das Datenstart-Token (0xFE) und liest dann 512 Bytes in einen Z80-RAM-Puffer. Verwendet, wo verfuegbar, den Hardware-SPI-Burst-Modus.
- Sektorschreiben (SDWRITE): Sendet CMD24 (WRITE_BLOCK), das Datenstart-Token, 512 Bytes Daten und die CRC. Wartet, bis die Schreibantwort und das Busy-Signal geloescht sind.
- SDCFS-Verzeichnislesen (SDDIR): Liest das Verzeichnis aus den ersten 8 KB des aktiven Laufwerks-Images und baut einen RAM-residenten Verzeichnis-Cache auf, der von den Befehlen IC, LC, SC und EC verwendet wird.
- SDCFS-Datei laden (SDLOAD): Berechnet anhand einer Dateinummer aus dem Verzeichnis die Sektoradresse des 64-KB-Blocks der Datei, liest die tatsaechliche Dateigroesse in Bytes und laedt sie an die im LOAD-ADDR-Feld des Verzeichniseintrags angegebene Z80-Adresse.
- SDCFS-Datei speichern (SDSAVE): Belegt einen neuen Verzeichnis-Slot (oder findet einen vorhandenen Eintrag mit demselben Namen zum Ueberschreiben), setzt die Felder START SECTOR, SIZE, LOAD ADDR und EXEC ADDR und schreibt dann die Dateidaten in den entsprechenden 64-KB-Block.
Rolle: Implementiert die Befehle D (Hex-Dump), M (Speicherbearbeitung), CP (Speicherkopie), IN (I/O-Port-Lesen) und OUT (I/O-Port-Schreiben), die bei allen Builds verfuegbar sind. Die Befehle DUC (SD-Karten-Datei-Dump), T2SD (Band zu SD) und SD2T (SD zu Band) sind ebenfalls hier implementiert, werden aber nur fuer die RomDisk-/picoZ80-Builds assembliert — der SFD-700-Build schliesst sie aus, da es keine SD-Karte gibt.
Hex-Dump (D): Liest bis zu 20 Zeilen mit je 16 Bytes aus dem Zieladressbereich. Fuer jede Zeile gibt er die 4-stellige Hex-Adresse, 16 Hex-Bytewerte (mit einem Leerzeichen zwischen je 4 Bytes) und die 16 ASCII-Zeichen aus (mit einem Punkt fuer nicht druckbare Bytes). Der Sharp MZ verwendet eine ungewoehnliche Zeichenkodierung — Bank 5 stellt die hier verwendete Sharp-zu-ASCII-Konvertierungstabelle bereit.
Speichereditor (M): Praesentiert jedes Byte nacheinander und zeigt die Adresse und den aktuellen Wert an. Der Benutzer kann einen neuen Hex-Wert eingeben (1 oder 2 Ziffern) und Enter druecken, um ihn zu schreiben, oder allein Enter druecken, um ihn unveraendert zu lassen. Druecken von Strg+C oder einer bestimmten Escape-Sequenz beendet die Funktion.
I/O-Port-Befehle (IN / OUT): IN liest einen oder mehrere Z80-I/O-Ports (2- oder 4-stellige Hex-Adressen, durch Komma getrennt) unter Verwendung von
rfs_bank4.asm — CMT-Controller (User-ROM Bank 4)
IN A,(C) und gibt jeden Wert als 2-stelligen Hex aus. OUT schreibt in einen oder mehrere Ports — jeder Eintrag ist eine Portadresse gefolgt von einem Doppelpunkt und einem 2-stelligen Hex-Wert (z.B. OUTD0:01,D1:80), ausgefuehrt mit OUT (C),A. Beide Befehle unterstuetzen den vollstaendigen 16-Bit-Z80-I/O-Port-Adressraum.
T2SD und SD2T: Diese Befehle fuehren eine transparente bidirektionale Kopie zwischen Band (CMT) und SD-Karte durch. T2SD ruft die CMT-Laderoutine aus Bank 4 auf, um eine Banddatei in den RAM zu lesen, und ruft dann die SD-Speicherroutine aus Bank 2 auf, um sie auf das aktive Laufwerk zu schreiben. SD2T ruft die SD-Laderoutine aus Bank 2 auf, um die Datei in den RAM zu legen, und ruft dann die CMT-Speicherroutine aus Bank 4 auf, um sie auf Band zu schreiben. Beide Richtungen verwenden das SDCFS-Verzeichnis, um Dateinamen, Groessen und Adressen beizubehalten.
Rolle: Implementiert die Bandbefehle (CMT) L/LT, LTNX, S/ST und V.
Der Sharp MZ-80A verwendet eine 1200-Baud-Kassettenschnittstelle nach Kansas City Standard. Bytes werden als Bursts von 1200-Hz- (Bit 0) oder 2400-Hz-Toenen (Bit 1) kodiert. Die Bandroutinen sind zeitkritisch — sie muessen jedes Bit innerhalb eines engen Zeitfensters lesen oder schreiben. Sie verwenden den 8253-Timer-Chip (oder CPU-zyklusgezaehlte Schleifen auf Plattformen ohne den Timer), um die eingehende Tonfrequenz zu messen und die ausgehende Wellenform zu erzeugen. Interrupts sind waehrend der Bandoperationen durchgehend deaktiviert (
rfs_bank5.asm — Hilfsfunktionen (User-ROM Bank 5)
DI), um Timing-Stoerungen zu vermeiden.
Das MZF-Bandformat stellt jedem Programm einen 128-Byte-Header voran, der den Dateityp, den Dateinamen, die Datenlaenge, die Ladeadresse und die Ausfuehrungsadresse enthaelt — dieselben Felder, die im SDCFS-Verzeichniseintrag gespeichert sind. Deshalb ist die SD-zu-Band-Kopie transparent: Das Header-Format ist identisch.
Rolle: Eine Bibliothek gemeinsam genutzter Routinen, die von anderen Baenken aufgerufen werden. Da Bank-Switching teuer ist (auf v2+-Platinen die Entriegelungssequenz erfordert), werden haeufig verwendete Routinen hier zentralisiert, um den Umschaltaufwand zu minimieren.
Schluesselroutinen:
rfs_bank6.asm — ASM/DASM-Opcode-Tabelle 1 (User-ROM Bank 6)
- PRTHEX: Gibt das A-Register als zwei Hex-Ziffern auf dem Bildschirm aus.
- PRTHL: Gibt das HL-Register als vier Hex-Ziffern aus.
- PRTSTR: Gibt eine null-terminierte Zeichenkette aus (HL) auf dem Bildschirm aus und behandelt die Sharp-Zeichenkodierungskonvertierung.
- INPHEX: Liest eine Hex-Zahl (bis zu 4 Ziffern) von der Tastatur und gibt den Wert in HL zurueck.
- STRCMP: Vergleicht zwei null-terminierte Zeichenketten.
- SUBSTR: Extrahiert eine Teilzeichenkette, verwendet vom Befehlsverteiler, um Befehlsnamen von Parametern zu trennen.
- WAITKEY: Wartet auf einen Tastendruck und gibt den Tastencode in A zurueck. Verwendet fuer "beliebige Taste druecken, um fortzufahren"-Pausen in IC- und IR-Verzeichnisauflistungen.
Rolle: Speichert die erste Haelfte der Z80-Opcode-Nachschlagetabellen, die sowohl vom Assembler (ASM) als auch vom Disassembler (DASM) verwendet werden, sowie die PRINTMSG-Funktion und die Infrastruktur fuer Nachrichtenzeichenketten. Die Opcode-Tabellen bilden Z80-Mnemonik-Zeichenketten auf Opcode-Bytes und umgekehrt ab. Der Assembler und Disassembler sind bei allen Builds verfuegbar (RomDisk, picoZ80, SFD-700 und FusionX).
Die PRINTMSG-Funktion liest Nachrichtenzeichenketten aus MROM-Bank 9 in einen RAM-Puffer, bevor sie gedruckt werden, da die Monitor-ROM-Funktionen (PRNT, ?DSP usw.) erfordern, dass die Monitor-MROM-Bank waehrend der Zeichenausgabe aktiv ist. Die entsprechende MROM-Bank 6 haelt ebenfalls Opcode-Tabellendaten im 4-KB-Monitor-ROM-Raum und bietet zusaetzlichen Platz fuer den vollstaendigen Z80-Befehlssatz einschliesslich aller Praefix-Byte-Varianten (CB, DD, ED, FD).
rfs_bank7.asm — ASM/DASM-Opcode-Tabelle 2, DASM, Tests (User-ROM Bank 7)
Rolle: Speichert die zweite Haelfte der Z80-Opcode-Nachschlagetabellen, die Hauptroutine des DASM-Disassemblers, den R-DRAM-Test und den T-Timer-Test.
Disassembler (DASM): Liest Maschinencode-Bytes von der Zieladresse, dekodiert jede Anweisung (unter Verwendung der Opcode-Tabellen in den Baenken 6 und 7) und gibt die Adresse, Hex-Bytes und Mnemonik fuer jede Anweisung aus. Behandelt alle Z80-Praefix-Bytes (CB, DD, ED, FD) und erweiterten Anweisungen.
DRAM-Test (R): Fuehrt ein wanderndes Bitmuster-Schreiben/Verifizieren ueber den gesamten Benutzer-RAM-Raum (0x1200–0xCFFF) durch. Meldet alle fehlgeschlagenen Adressen. Nuetzlich zur Diagnose fehlerhafter RAM-Chips — ein haeufiger Fehlermodus bei Vintage-Maschinen.
rfs_bank8.asm — Z80-Assembler (User-ROM Bank 8)
Rolle: Implementiert den interaktiven Assembler-Befehl ASM.
Interaktiver Assembler (ASM): Praesentiert eine Zeileneingabeaufforderung an der Zieladresse. Der Benutzer gibt Z80-Mnemoniken ein (z.B.
rfs_bank9.asm — ROM-Verzeichnis- und Dateifunktionen (User-ROM Bank 9)
LD A, 42), die geparst, zu Maschinencode-Bytes assembliert und direkt an die Zieladresse im RAM geschrieben werden. Die Adresse wird um die Groesse jeder assemblierten Anweisung weitergeschoben. Dies ermoeglicht die Assemblierung kleiner Routinen direkt auf der Hardware ohne externen PC. Die Opcode-Nachschlagetabellen in den Baenken 6 und 7 (und MROM-Baenke 6 und 7) werden fuer die Mnemonik-zu-Opcode-Uebersetzung verwendet.
Rolle: Enthaelt ROM-Verzeichnisaufzaehlung, Dateisuche, Dateiladen und Druckfunktionen, die aus Bank 0 (der Befehlsverteiler-Bank) verschoben wurden, um in Bank 0 Platz fuer zusaetzliche Befehlstabelleneintraege und Infrastruktur freizugeben. Zu den Schluesselfunktionen gehoeren DIRROM9 (ROM-Verzeichnisauflistung), FINDSDX9 (Dateisuche), ISMZF9 (MZF-Header-Validierung) und _PRTMZF9 (MZF-Eintragsanzeige).
rfs_bank11.asm — Hilfebildschirm (User-ROM Bank 11)
Rolle: Speichert den seitenweisen Hilfebildschirmtext (aus Bank 6 verschoben, um Platz fuer die Opcode-Tabellen zu schaffen). Der Hilfebildschirm wird als Folge null-terminierter Zeichenketten gespeichert (eine pro Zeile). Der H-Befehl gibt sie mit automatischer Seitenumbruchsteuerung aus und ruft an jeder Bildschirmgrenze die WAITKEY-Routine aus Bank 5 auf.
rfs_mrom.asm — Monitor-ROM-Hilfsfunktionen (Monitor-ROM Bank 3)
Rolle: Stellt die ROM-Scan- und MZF-Dateilade-Routinen bereit, die aus dem Monitor-ROM-Raum statt aus dem User-ROM-Raum laufen muessen.
Warum eine separate Monitor-ROM-Bank? Die Befehle IR und LR muessen MZF-Dateien aufzaehlen, die in den User-ROM-Flash-Chips gespeichert sind (User-ROM-Baenke jenseits von 15 halten gepackte MZF-Programme). Um eine User-ROM-Bank zu scannen, muss das CPLD das User-ROM-Fenster auf diese Bank umschalten. Aber der Scan-Code selbst lebt im User-ROM — wenn er die User-ROM-Bank umschaltet, ersetzt er sich sofort selbst durch eine andere Bank und stuerzt ab.
Die Loesung besteht darin, die Scan-Schleife in Monitor-ROM-Bank 3 zu platzieren. Das Monitor-ROM-Bank-Switching ist unabhaengig vom User-ROM-Bank-Switching. Die MROM-Scan-Routine kann frei User-ROM-Baenke umschalten (um die MZF-Header-Liste jeder Bank aufzuzaehlen), ohne ihren eigenen Ausfuehrungskontext zu stoeren.
Schluesselfunktionen:
CP/M-CBIOS-Module
- ROMDIR: Scannt alle User-ROM-Baenke ueber 15, liest jeden MZF-Header und baut ein RAM-residentes ROM-Verzeichnis auf, das vom IR-Befehl verwendet wird.
- ROMLOAD: Liest anhand einer Dateinummer aus dem ROM-Verzeichnis die MZF-Daten aus der entsprechenden User-ROM-Bank in die im Header angegebene LOAD ADDR und springt dann optional zu EXEC ADDR.
Die vier CBIOS-User-ROM-Baenke (12–15) und die CBIOS-Monitor-ROM-Bank (2) implementieren zusammen das komplette CP/M 2.2-CBIOS. Jede Bank stellt ein Subsystem bereit:
cbios.asm (Monitor-ROM Bank 2): Die CBIOS-Einsprungpunkttabelle — alle 17 CP/M-API-Vektoren (BOOT bis SECTRN) sind Sprungadressen innerhalb dieses Moduls. Haelt auch die Disk-Parametertabellen (DPH-, DPB-Strukturen, die CP/M die Geometrie jedes Disk-Laufwerks mitteilen), die Kalt-/Warmstart-Sequenzen und den ROM-Disk-Controller (liest Sektoren aus dem User-ROM-Flash).
cbios_bank1.asm (User-ROM Bank 12): Audioausgabe (Glockenton und Melodie unter Verwendung der 8255-PPI des MZ-80A und des Summers), Echtzeituhr-Routinen unter Verwendung des 8253-Timers und Tastatureingabe mit Auto-Wiederholung (eine Taste, die laenger als 500 ms gehalten wird, wiederholt sich mit ~10 Hz, was dem Verhalten entspricht, das Benutzer von einer modernen Tastatur erwarten).
cbios_bank2.asm (User-ROM Bank 13): Bildschirmtreiber — Zeichenausgabe an der aktuellen Cursorposition, Scrollen, Bildschirm loeschen, Cursorpositionierung. Auch der ANSI-Terminalemulator: eine Zustandsmaschine, die VT52/VT100-Escape-Sequenzen (CSI-Codes) erkennt und sie in die entsprechenden MZ-80A-Bildschirmoperationen uebersetzt. Dies laesst CP/M-Anwendungen, die ein intelligentes Terminal voraussetzen (WordStar, Turbo Pascal usw.), korrekt funktionieren, ohne dass an diesen Anwendungen Aenderungen vorgenommen werden muessen.
cbios_bank3.asm (User-ROM Bank 14): SD-Karten-Disk-Treiber fuer CP/M. Uebersetzt CP/M-128-Byte-Sektor-Lese-/Schreibanforderungen in SDCFS-Operationen auf den CP/M-Disk-Images, die nach der 256-MB-Grenze auf der SD-Karte gespeichert sind. Enthaelt die Sektor-Skew-Tabelle, die von SECTRN zur Verbesserung der Disk-Zugriffsleistung verwendet wird.
cbios_bank4.asm (User-ROM Bank 15): Diskettencontroller fuer CP/M. Verwendet den WD1773 (ueber SFD-700) oder einen aequivalenten Diskettencontroller, um CP/M-Disk-Lese-/Schreibanforderungen fuer physische Diskettenlaufwerke zu bedienen. Daten werden nicht invertiert gelesen (im Gegensatz zum MZ-80A-AFI-ROM, das invertierte Daten verwendet), weil das CBIOS sein eigenes erneut invertiertes Format schreibt. Bei Ansteuerung ueber die MZ80AFI-Karte fragt es den Sektorgroessen-Bericht des Controllers ab (Port 0xDF), um 256-Byte-MZ-80A-Disketten von 128-Byte-MZ-80K-Disketten zu unterscheiden, und kann originale (nicht konvertierte) MZ-80K-CP/M-Disketten direkt booten/lesen — erkannt am nicht invertierten
01h + IPLPRO Boot-Marker — und bildet sie auf die CP/M-Laufwerke C:/D: ab (die Hilfsroutinen ?SETDRVMAP / ?SELDRIVE ordnen die physischen Diskettenlaufwerke beim Kaltstart den passenden CP/M-Laufwerksbuchstaben zu).
Einen neuen Monitorbefehl hinzufuegen
Um einen neuen Befehl FOO hinzuzufuegen, der in User-ROM Bank 3 (Speicherwerkzeuge) lebt:
- Den Handler in rfs_bank3.asm schreiben: Eine markierte Routine
FOO_CMD:hinzufuegen, die den Befehl implementiert. Parameter sind im Monitor-Eingabepuffer verfuegbar (HL zeigt auf das erste Zeichen nach dem Befehlsnamen). Nach Abschluss mitRETzurueckkehren. - Einen Eintrag in die Befehlstabelle in rfs.asm hinzufuegen: In die passende
CMDTABLE(oderCMDTABLE2fuer SFD-700) hinzufuegen:
; 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
- Den Hilfetext in rfs_bank6.asm aktualisieren: Eine Zeile zur Beschreibung des neuen Befehls zu den Hilfebildschirm-Textzeichenketten hinzufuegen.
- Neu bauen:
./build.shausfuehren. Der Assembler meldet etwaige Groessenueberschreitungen, falls Bank 3 nun groesser als 2 KB ist — in diesem Fall anderen Code in dieser Bank entfernen oder komprimieren.
Eine neue Hardware-Plattform hinzufuegen
Um RFS auf ein neues Hardware-Ziel zu portieren:
- Ein Build-Flag hinzufuegen in
rfs_definitions.asm:BUILD_NEWBOARD EQU 0(beim Bauen fuer das neue Ziel auf 1 setzen). - Adresskonstanten hinzufuegen, falls die neue Hardware ROM-Fenster an anderen Adressen abbildet.
- Bedingte Assemblierungsbloecke hinzufuegen im gesamten Quellcode, wo sich hardwarespezifisches Verhalten unterscheidet — I/O-Portadressen fuer die Bank-Verriegelung, SPI-Controller-Registerlayout, SD-Karten-Praesenzerkennung usw. Dem Muster vorhandener
IF BUILD_ROMDISK = 1 ... ENDIF-Bloecke folgen. - Ein neues Build-Skript hinzufuegen (oder
make_roms.sherweitern), um das ROM-Image fuer das Flash-Chip-Layout des neuen Ziels zu paketieren. - Die Voraussetzungspruefung aktualisieren in
build.sh, falls das neue Ziel zusaetzliche Werkzeuge benoetigt.
Debugging-Tipps
Debug-Ausgabe aktivieren: Vor dem Bauen
ENADEBUG EQU 1 in rfs_definitions.asm setzen. Dies bindet zusaetzliche Diagnoseausgaben an strategischen Punkten in der SD-Karten-Initialisierung und den SDCFS-Routinen ein.
Eingebauten Disassembler verwenden: Bei SFD-700-Builds DASM addr eingeben, um assemblierten Code im RAM zu disassemblieren. Dies ist von unschaetzbarem Wert, um zu verifizieren, dass eine neu assemblierte Routine durch den ASM-Befehl korrekt kodiert wurde.
Hex-Dump verwenden: D E800 zeigt die ersten 320 Bytes der aktuellen User-ROM-Bank — nuetzlich, um zu verifizieren, dass die Bank-Verriegelung die erwartete Bank auswaehlt.
DRAM-Test nach jeder RAM-Aenderung: R eingeben, um einen umfassenden DRAM-Test auszufuehren, wann immer neue RAM-residente Datenstrukturen hinzugefuegt werden. Dies faengt Adressierungsfehler fruehzeitig ab, bevor sie als mysterioese Abstuerze auftreten.
Bank-Switch-Schutz: Auf RomDisk v2+-Platinen niemals einen DJNZ oder eine andere Schleifenanweisung platzieren, die 0xEFF8–0xEFFF ueberspannt. Die codierte Verriegelung interpretiert Lesevorgaenge aus diesem Bereich als Entriegelungssequenz und kann unerwartet Baenke umschalten.
Build-Umgebung
Die RFS-Build-Toolchain ist unkompliziert — nur eine Java-Laufzeitumgebung und der GLASS Z80-Assembler werden fuer die Z80-Assembly-Komponenten benoetigt. Das globale FusionX-Build-Skript
Voraussetzungen
build.sh automatisiert den gesamten Prozess.
# 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
Die GLASS Z80-Assembler-JAR-Datei ist im Repository unter
Automatisierte Einrichtung und Build (empfohlen)
software/tools/glass-0.5.1.jar mitgeliefert — es ist kein separater Download erforderlich. Jede Java-8-Laufzeitumgebung oder neuer funktioniert.
Der empfohlene Weg, RFS zu bauen, ist das eigenstaendige Setup-Skript fuer Ihre Plattform. Es installiert die Voraussetzungen (eine Java-JRE fuer den GLASS Z80-Assembler, eine C-Toolchain +
make zum Kompilieren des mitgelieferten cpmtools-Submoduls, sowie perl/git/coreutils; unter Windows Git Bash + Java), klont das Repository, laedt das ~110 MB grosse Inhaltspaket (RFS_Files.zip) herunter, schreibt die Umgebungsdatei und kann den ersten Build ausfuehren — alles interaktiv, mit sinnvollen Standardwerten, die Sie durch Druecken von Enter uebernehmen koennen. Kopieren Sie einfach die einzelne Datei fuer Ihre Plattform und fuehren Sie sie aus.
macOS / Linux / WSL — setup_RFS.sh
chmod +x setup_RFS.sh
./setup_RFS.sh
Windows 10 / 11 — setup_RFS_windows_native.ps1 (empfohlen — nativ, kein WSL). An einer PowerShell-Eingabeaufforderung:
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
.\setup_RFS_windows_native.ps1
Das native Skript verwendet winget, um Git for Windows (das bash, coreutils, perl und curl bereitstellt) und eine Temurin 17 JRE (Java) zu installieren, klont das Repo, laedt das Inhaltspaket herunter und fuehrt
./build.sh ueber Git Bash aus — ohne WSL, Docker oder Neustart. Es ist kein C-Compiler erforderlich, da zwei vorkompilierte Host-Werkzeuge (tools\cpmcp.exe und tools\sdtool.exe) mitgeliefert werden.
Windows 10 / 11 — setup_RFS_windows.ps1 (Alternative — baut innerhalb von WSL2 / Ubuntu). Aus einer PowerShell mit Administratorrechten:
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
.\setup_RFS_windows.ps1
Diese WSL-Variante installiert WSL2 + Ubuntu, falls sie noch nicht vorhanden sind (ein einmaliger Neustart ist erforderlich — neu starten, Ubuntu einmal starten, um Ihren Linux-Benutzer zu erstellen, dann das Skript erneut ausfuehren), und fuehrt dann
setup_RFS.sh innerhalb von Ubuntu aus.
Setzen Sie die Umgebungsvariable
RFS_REPO_URL, um die Standard-Repository-URL (https://git.eaw.app/eaw/RFS.git) zu ueberschreiben, ohne das Skript zu bearbeiten, und RFS_FILES_URL, um auf ein alternatives Inhaltspaket zu verweisen.
Ausgabe und Neuerstellung. ROM-Images und SD-Karten-Images werden nach
Bauen
roms/ geschrieben. Um spaeter neu zu bauen, wechseln Sie in das Checkout; unter macOS zuerst source ./rfs_env.sh ausfuehren, um GNU coreutils und die JRE auf den PATH zu legen; dann ./build.sh -m fuer den ersten Build ausfuehren (verarbeitet MZF-Quellen nach MZB/) und ./build.sh fuer nachfolgende Builds. Unter Windows (nativ) fuehren Sie dieselben ./build.sh-Befehle aus Git Bash innerhalb des Checkouts aus.
# 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
Das Build-Skript assembliert jedes ROM- und MZF-Ziel mit dem GLASS-Assembler und uebergibt die passenden Include-Pfade und Build-Flags. MS BASIC-Varianten (MZ-80A, MZ-700, TZ40, TZ80) werden aus derselben Quelldatei mit unterschiedlichen
BUILD_VERSION-Flags gebaut, die ueber generierte Include-Dateien gesetzt werden.
Build-Ausgabe:
| Ausgabe | Beschreibung |
|---|---|
monitor_sa1510.rom |
SA-1510 Monitor-ROM |
monitor_80c_sa1510.rom |
SA-1510 Monitor mit 80-Spalten-Unterstuetzung |
monitor_1z-013a.rom |
1Z-013A Monitor-ROM |
mz80afi.rom |
MZ-80A AFI (Diskettenschnittstelle) ROM |
mz2000_ipl_*.rom |
MZ-2000 IPL-ROMs (Original, TZPU, FusionX) |
mz800_*.rom |
MZ-800 System-ROMs |
msbasic_*.mzf |
MS BASIC fuer jedes Ziel |
sa-5510_tzfs.mzf |
SA-5510 BASIC mit TZFS-Unterstuetzung |
sharpmz-test.mzf |
Hardware-Test-MZF |
Was ist CI/CD? Continuous Integration (CI) ist eine Praxis, bei der ein dedizierter Server Ihr Projekt automatisch jedes Mal baut, wenn Sie Codeaenderungen pushen. Anstatt den Assembler manuell auf Ihrer Entwicklungsmaschine auszufuehren, die ROM-Dateien zu paketieren und sie auf eine Download-Seite hochzuladen, erledigt ein CI-Server all dies automatisch. Wenn der Build fehlschlaegt — zum Beispiel wegen eines Syntaxfehlers oder einer fehlenden Include-Datei — erhalten Sie sofort eine E-Mail-Benachrichtigung. Dies faengt Probleme fruehzeitig ab und stellt sicher, dass jeder veroeffentlichte Release aus einem sauberen, reproduzierbaren Ausgangspunkt gebaut wurde.
Die RFS-ROMs werden als Teil der FusionX-Jenkins-CI-Pipeline gebaut. Jenkins ist ein beliebter Open-Source-Automatisierungsserver, der auf einem VPS (Virtual Private Server) oder einer beliebigen Linux-Maschine laeuft. Er ueberwacht das Gitea-Repository auf Pushes zum
Wie es funktioniert
master-Branch und loest automatisch einen vollstaendigen Build aller Projektkomponenten aus.
Der automatisierte Build-Prozess fuer RFS folgt diesen Schritten:
- Sie pushen Code zum
master-Branch des Gitea-Repositorys. - Gitea sendet einen Webhook (eine HTTP-Benachrichtigung) an den Jenkins-Server.
- Jenkins klont das Repository in einen frischen, sauberen Arbeitsbereich.
- Jenkins fuehrt
./build.sh --asmaus, was alle Z80-Monitor-ROMs und MZF-Dateien mit dem GLASS-Assembler assembliert. - Jenkins paketiert die assemblierten ROM- und MZF-Dateien in einen versionierten Tarball (
FusionX-ROMs-v1.08.tar.gz). - Jenkins erstellt einen Gitea-Release mit dem angehaengten Tarball als herunterladbares Asset.
- Jenkins sendet eine E-Mail, die Erfolg oder Fehlschlag meldet.
Der gesamte Prozess dauert etwa eine Minute und erfordert nach dem ersten Push keine manuelle Intervention.
Jenkins einrichten
Jenkins laeuft fuer einfache Installation und Portabilitaet innerhalb eines Docker-Containers. Die Mindestanforderungen sind ein Linux-Server mit 2 GB RAM, installiertem Docker und Netzwerkzugriff auf Ihr Gitea-Repository. Auf Ihrem Server:
# 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
Erstellen Sie eine
docker-compose.yml-Datei:
# /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
Beim ersten Start fragt Jenkins nach dem in den Logs angezeigten Admin-Passwort. Installieren Sie nach der Anmeldung die "suggested plugins" und fuegen Sie dann das Generic Webhook Trigger-Plugin ueber Manage Jenkins → Plugins → Available hinzu.
Die Pipeline erstellen
Ein Jenkins-"Pipeline"-Job wird durch ein Groovy-Skript definiert, das Jenkins genau mitteilt, welche Befehle auszufuehren sind. Um eine RFS-Build-Pipeline zu erstellen:
- Klicken Sie auf New Item auf dem Jenkins-Dashboard.
- Geben Sie einen Namen ein (z.B.
RFS-Build), waehlen Sie Pipeline, klicken Sie auf OK. - Setzen Sie im Abschnitt Pipeline die Definition auf "Pipeline script" und fuegen Sie dies ein:
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() }
}
}
Dies ist eine vereinfachte Pipeline, die nur die Z80-Assembly-ROMs baut. Fuer die vollstaendige FusionX-Pipeline — die auch TZFS, CP/M, Kernelmodule, CPLD-Bitstreams baut und Gitea-Releases erstellt — siehe den Abschnitt FusionX Developer's Guide — Continuous Integration. Dieses Handbuch behandelt auch die ARM-Cross-Compiler-Einrichtung, die Quartus-Docker-Installation, die Pfaduebersetzung zwischen Geschwister-Containern und das vollstaendige Pipeline-Skript.
Gitea-Webhook
Ein Webhook weist Gitea an, Jenkins zu benachrichtigen, wann immer Code gepusht wird. Gehen Sie in Ihrem Gitea-Repository zu Settings → Webhooks → Add Webhook → Gitea und setzen Sie:
- Target URL:
http://your-server:8080/generic-webhook-trigger/invoke?token=rfs-build-trigger - Content Type:
application/json - Trigger On: Push Events
Pushen Sie nach dem Speichern einen Commit zu
master und pruefen Sie Jenkins — ein neuer Build sollte automatisch erscheinen. Klicken Sie auf die Build-Nummer und dann auf Console Output, um den Fortschritt in Echtzeit zu verfolgen.
Referenz-Links
| Ressource | Link |
|---|---|
| RFS-Projektseite | /de/sharpmz-upgrades-rfs/ |
| RFS-Benutzerhandbuch | /de/sharpmz-upgrades-rfs-usermanual/ |
| RFS-Technischer Leitfaden | /de/sharpmz-upgrades-rfs-technicalguide/ |
| RFS-Galerie | /de/sharpmz-upgrades-rfs-gallery/ |
| SFD-700 mkII Entwicklerhandbuch | /sfd700-developersguide/ |
| picoZ80 Entwicklerhandbuch | /de/picoz80-developersguide/ |
| FusionX Entwicklerhandbuch | /tranzputer-fusionx-developersguide/ |
| GLASS Z80-Assembler | Enthalten in tools/glass-0.5.1.jar |
| Zilog Z80 CPU User Manual | Standard-Datenblatt — Bustiming, Befehlssatz, Registerreferenz |
| CP/M 2.2 Alteration Guide | Digital Research — CBIOS-Design-Referenz |