7.7. BFZ Mini-DOS

Das MINI-DOS ist eine Erweiterung des MAT85 bzw. MAT85+ rund um die Floppy-Baugruppe (4.7. Floppy Disk Baugruppe). Das “Softwarepaket” wird dabei dynamisch in die Monitor (MAT85) bzw. Monitorerweiterung (MAT85+) eingebunden, da hier bereits Routinen enthalten sind, die eine Erweiterung möglich machen.

Über die Mini-DOS-Erweiterung stehen grundlegende Funktionen zur Verfügung, um Speicherbereiche auf Diskette (5 1/4″ oder 3 1/2″) abzuspeichern. Aus heutige Sicht ist die unterstützte Kapazität mit 320kByte allerdings überschaubar, für damalige Verhältnisse aber ein Meilenstein gegenüber der bisherigen Möglichkeit Speicherbereiche recht mühsam und langsam auf Kassetten abzuspeichern.

;*************************************************************************
;
;     ##     ## #### ##    ## ####         ########   #######   ######
;     ###   ###  ##  ###   ##  ##          ##     ## ##     ## ##    ##
;     #### ####  ##  ####  ##  ##          ##     ## ##     ## ##
;     ## ### ##  ##  ## ## ##  ##  ####### ##     ## ##     ##  ######
;     ##     ##  ##  ##  ####  ##          ##     ## ##     ##       ##
;     ##     ##  ##  ##   ###  ##          ##     ## ##     ## ##    ##
;     ##     ## #### ##    ## ####         ########   #######   ######
;
;*************************************************************************
; VERSION            1.4
; LETZTE AENDERUNG:  09.10.85
; COPYRIGHT:         BFZ ESSEN
;                    ALTENESSENER STR.80/84
;                    4300 ESSEN 12
;*************************************************************************
;
;       Aenderungen und Anpassungen
; 2023  thilo.buhl@tau-alpha-c.de
;
;*************************************************************************
;                                                 
; 28.05.2022    Anpassung an Visual Studio Code
;                                                 
;*************************************************************************
; ... 01/2023 - Kommentare ergaenzt
;*************************************************************************
; 
; 26.01.2023 - P01
; - [P01#01] Routine FORMAT: endet in Dauerschleife (JMP FORM1)
;            Ende von FORMAT auf JMP ERROR2 geaendert
; - [P01#02] Routine LINE: Hexadresse des Flag auf CRTFLAG geaendert
; - [P01#03] Unterprogramm SD1: Re-Init des SP auf USRSTK geaendert
; - [P01#04] Adresse des FDC als Variable
;
;*************************************************************************
; Benutzte Assembler-Anweisungen
;*************************************************************************
;
; .target	Prozessorsystem
; .format	Ausgabeformat
; .org      Anfangsadresse setzen
; .equ		Zuweisung Variable
; .byte		Definiere BYTE
; .word		Definiere WORD (Lo/Hi-Byte)
; .text		Definiere Textstelle
; .textz	Definiere Textstelle mit $0 am Ende
;
;*************************************************************************


;*************************************************************************
;MINI-DOS
;VARIABLEN
;*************************************************************************
                                    ;[P01#04]
FDCBAS      .equ $c0                ; FDC Portadresse
FDCCMD      .equ FDCBAS             ; FDC Kommandoregister
FDCSTAT     .equ FDCBAS             ; FDC Statusregister
FDCTRK      .equ FDCBAS+1           ; FDC Trackregister (nicht verwendet)
FDCSEC      .equ FDCBAS+2           ; FDC Sektorregister
FDCDAT      .equ FDCBAS+3           ; FDC Datenregister
FDCPORT     .equ FDCBAS+4           ; FDC Steuer-Port
                                    ; D0 - Select0 (Laufwerk A)
                                    ; D1 - Select1 (Laufwerk B)
                                    ; D2 - Density Select
                                    ;     0 = Double Density
                                    ;     1 = Single Density
                                    ; D3 - Side Select
                                    ;     0 = Seite 0
                                    ;     1 = Seite 1

FDCSTOP     .equ FDCBAS+8           ; FDC Stop-Register
                                    ; Eine Ausgabe an dieses Register
                                    ; haelt die CPU an (READY-Signal)

;*************************************************************************
; STEP-Rate (Gueltig fuer FCD-Clock: 1 MHz, FDC-Test-Anschluss auf H-Pegel)
;
; SR-Wert-Rate in ms
;     0            6
;     1            12
;     2            20
;     3            30

SR          .equ $0

;*************************************************************************
; Steuer-Worte
;*************************************************************************

CREST       .equ %00000000+SR       ; Restore - Step-Rate entspricht SR
CRESTV      .equ %00000100+SR       ; Restore - Verify Track Number
                                    ;           Step-Rate entspricht SR
CSTPIN      .equ %01010000+SR       ; Step-In - Update Track-Register
                                    ;           Step-Rate entspricht SR
CSEEK       .equ %00010100+SR       ; Seek      - Verify
                                    ;           - Delay
                                    ;           - Step-Rate entspricht SR
CWRTRK      .equ %11110000          ; Write Track
CWSEC       .equ %10100000          ; Write Sector - Single Record
                                    ;              - No Side Compare
                                    ;              - No Delay
                                    ;              - DAM not deleted
CRSEC       .equ %10000000          ; Lese Sector - No Delay
                                    ;             - No Side Compare
                            
;*************************************************************************
; Fehler-Masken
;*************************************************************************

MREST       .equ %11011100          ; Restore
                                    ;     B7=1 -> not Ready
                                    ;     B6=1 -> Write protect
                                    ;     B5
                                    ;     B4=1 -> Seek Error
                                    ;     B3=1 -> CRC-Error
                                    ;     B2=1 -> Track 0
                                    ;     B1
                                    ;     B0
MWRTRK      .equ %10000100          ; Write Track
                                    ;     B7=1 -> not Ready
                                    ;     B6
                                    ;     B5
                                    ;     B4
                                    ;     B3
                                    ;     B2=1 -> Lost Data
                                    ;     B1
                                    ;     B0
MWSEC       .equ %11011100          ; Write Sector
                                    ;     B7=1 -> not Ready
                                    ;     B6=1 -> Write protect
                                    ;     B5
                                    ;     B4=1 -> Record not Found
                                    ;     B3=1 -> CRC-Error
                                    ;     B2=1 -> Lost Data
                                    ;     B1
                                    ;     B0
MRSEC       .equ %10011100          ; Read Sector
                                    ;     B7=1 -> not Ready
                                    ;     B6
                                    ;     B5
                                    ;     B4=1 -> Record not Found
                                    ;     B3=1 -> CRC-Error
                                    ;     B2=1 -> Lost Data
                                    ;     B1
                                    ;     B0
MVERI       .equ %00011000          ; Verify Sector
                                    ;     B7
                                    ;     B6
                                    ;     B5
                                    ;     B4=1 -> Record not Found
                                    ;     B3=1 -> CRC-Error
                                    ;     B2
                                    ;     B1
                                    ;     B0
MSEEK       .equ %11011000          ; Seek Track
                                    ;     B7=1 -> not Ready
                                    ;     B6=1 -> Write protect
                                    ;     B5
                                    ;     B4=1 -> Record not Found
                                    ;     B3=1 -> CRC-Error
                                    ;     B2
                                    ;     B1
                                    ;     B0
                            
;*************************************************************************
; Definition der Konstanten
;*************************************************************************

HEADIDLE    .equ 15                 ; Idle-Time fuer Kopf Ruhezeit (15msec)

MAXTRY      .equ $03                ; Maximale Anzahl der Verify-Versuche

BELL        .equ $07                ; ASCII BELL
BS          .equ $08                ; ASCII BACKSPACE
CR          .equ $0D                ; ASCII WAGENRUECKLAUF
LF          .equ $0A                ; ASCII ZEILENVORSCHUB
DEL         .equ $7F                ; ASCII DELETE

DRV_DELAY   .equ 83                 ; Drive Delay 
                                    ; CPU-Takt: 2 MHz
                                    ; CPU-Takt: 4 MHz: 164
DRV_WAIT    .equ 1000               ; Wartezeit fuer Motoranlauf ($0800) i.V.m. DRV_DELAY
                            
BLOCKSIZE   .equ 4096               ; Blockgroesse

IMASK       .equ %00001110          ; Interrupt-Maske (RST 5.5 Enable)
SPACE       .equ $20                ; Leerzeichen

JUMP        .equ $C3                ; Mnemonic-Code für JMP
RETURN      .equ $C9                ; Mnemonic-Code für RET

PRTOFF      .equ $089F              ; Printer Off-Flag
SPS         .equ $272E              ; SPS-Einsprung
SRET1       .equ $27E9              ; Marke im SPS-Programm
CMDINP      .equ $27F0              ; Marke im SPS-Programm
CHROK       .equ $2841              ; Marke im SPS-Programm
ZULKMD      .equ $28BE              ; Marke im SPS-Programm
BASIC       .equ $3091              ; Basic-Neustart

BASBUF      .equ $8013              ; Basic Input-Buffer
TXTUNF      .equ $8064              ; Zeiger auf Basic-PGM-Ende + 1
TXTBGN      .equ $806F              ; Basic-Programm Anfangsadresse

FBUFFER     .equ $E000              ; Track-Buffer fuer Formatbefehl
SPS_PT_END  .equ $E003              ; PGMEND Zeiger auf SPS-Programmende
SPS_RAM_PROG .equ $E0ED             ; PGMANF SPS Programm-Anfangsadresse

MONSTK      .equ $FC80              ; [FEHLER] Monitor-Stack [FC80 statt $FC00]
USRSTK      .equ $FC32              ; USER-STACK-POINTER

PRTST       .equ $FC84              ; Printer-Status-Flag (Ein/Aus)
RSTVEK      .equ $FC95              ; RST 5.5 Sprung-Vektor

BCKFLG      .equ $FCC7              ; Flag fuer MAT85
CRTFLG      .equ $FCC8              ; CRT / PRINTER-FLAG
GROFLG      .equ $FCC9              ; Flag fuer MAT85

M85BE       .equ $FCF2              ; Ende MAT85-Input-Buffer
PCWERT      .equ $FCD7              ; MAT85: GO-Adresse
DIRKOM      .equ $FD16              ; Basic-Direktkommando-Flag
STARTA      .equ $FD6F              ; Zwischenspeicher fuer Start-Adresse
STOPA       .equ $FD71              ; .. Stop-Adresse
                            
;*************************************************************************
; Unterprogramm aus MAT85
;

KMD         .equ $0040              ; MAT85-KMDRoutine
RCHAR       .equ $0043              ; Lese Zeichen in den Akku
WCHAR       .equ $0052              ; Zeichen im Akku ausgeben
PHL         .equ $005B              ; HL als HEX-Wert ausgeben
WBIN        .equ $005E              ; Akku als Binaerwert ausgeben
WDEZ        .equ $0061              ; Akku als Dezimalwert ausgeben
PTXT        .equ $006D              ; Text ausgeben
PTXTCR      .equ $0073              ; Text ausgeben, vorher CR/LF

EXEC        .equ $01EB              ; Kommando ausfuehren
PSTAR       .equ $0228              ; Print "***" + TEXT + "***"
PKLIST      .equ $03B8              ; Kommandoliste ausgeben
SERO        .equ $089F              ;SERO PRT-Flag                                    
HSTART      .equ $0A74              ; Hole Start-Adresse Ersatz durch die MAT85-Einsprungadressen
WBLNKI      .equ $0B93              ; Wiederhole " " X-Mal (Anzahl nach CALL)
BUFCLR      .equ $0CAA              ; Loesche MAT85-Input-Buffer
BREAD       .equ $0D0A              ; Lese Text aus Buffer Ersatz durch die MAT85-Einsprungadressen
TEST        .equ $0EB0              ; Pruefe ob Zeichen in einer Tabelle
GROSS       .equ $0EE9              ; Zeichen in Grossbuchstaben umwandeln
SUB2        .equ $1039              ; HL=HL-DE

;*************************************************************************
; Unterprogramme aus SP1
;

HSTSPA      .equ $215B              ; Hole START/STOP-Adresse
;R4         .equ $31F4              ;
CMPHD       .equ $31F4              ; Vergleiche HL-DE
CMPDH       .equ $31FA              ; Vergleiche DE-HL
R5          .equ $320B              ; Suche naechstes Zeichen ungleich " "
CLEAR       .equ $348C              ; Loesche Basic-Programm und Variablen
BCLEAR      .equ $3FD6              ; Bildschirm loeschen

;*************************************************************************
; Labels fuer MINI-DOS-Erweiterungen
; SIEHE BESCHREIBUNG IN UMG
;

L5000       .equ $5000
L5001       .equ $5001
L5004       .equ $5004
L5005       .equ $5005
L5008       .equ $5008
L5009       .equ $5009
L5010       .equ $5010
L500D       .equ $500D

L5800       .equ $5800
L5801       .equ $5801
L5804       .equ $5804
L5805       .equ $5805
L5808       .equ $5808
L5809       .equ $5809
L5810       .equ $5810
L580D       .equ $580D

;*************************************************************************

                                    ;     *
                                    ;    **
                                    ;   ***
                                    ;  **********************************
           .ORG   $4000             ; ******* MINI-DOS - ANFANGS-ADRESSE 
                                    ;  **********************************
                                    ;   ***
                                    ;    **
                                    ;     *

;*************************************************************************
;
;DAS BFZ-MINI-DQS KANN VON MAT85, SPS UND BASIC AUS AUFGERUFEN WERDEN
;BEI UNBEKANNTEN BEFEHLEN (WIE Z.B. "F" FUER FLOPPY) PRUEFEN DIESE
;PROGRAMME, OB EINE ERWEITERUNG VORLIEGT.
;
;EIN BEISPIEL:
;GIBT MAN BEI SPS DEN BUCHSTABEN "F" ALS KOMMANDO EIN,
;SO PRUEFT DAS SPS-PROGRAMM. OB IN DER SPEICHERZEILE
;4003H DER WERT C3H STEHT (DIE ADRESSE 4003H IST IM
;SPS-PROGRAMM FEST VORGEGEBEN). C3H IST DER CODE FUER
;DEN SPRUNG-BEFEHL "JMP". FINDET SPS DIESEN CODE, SO
;VERZWEIGT ES ZU DER ADRESSE 4003H UND FUERT DEN DORT
;STEHENDEN SPRUNG-BEFEHL AUS. DIE PROGRAMME MATS5 UND
;BASIC PRUEFEN DIE SPEICHERZEILEN 4000H BZW. 4006H.
;
;*************************************************************************

MAT85DOS:
VEKT_FMAT:
            JMP FMAT                ;WIRD FUER MAT85/MAT85+ BENOEGETIGT
VEKT_FSPS:
            JMP FSPS                ;WIRD FUER SPS BENOETIGT
VEKT_FBAS:
            JMP FBAS                ;WIRD FUER BASIC BENOETIGT

;*************************************************************************
;DAS BFZ-MINI-DOS ENTHAELT ZLEI UNTERPROGRAMME, DIE RELATIVE SPRUENGE UND
;RELATIVE UNTERPROGRAMM-AUFRUFE ERMOEGLICHEN. PROGRAMME , DIE NUR RELATIVE
;VERZWEIGUNGEN ENTHALTEN, SIND IN JEDEM SPEICHERBEREICH LAUFFAEHIG.
;"DIESE UNTERPROGRAMME "RELJMP" UND "RELCAL" VERAENDERN DEN INHALT DES
;HL—REGISTERPAARES.

;*************************************************************************
;ANWENDUNGS-BEISPIELE:
; RELATIVER UNTERPROGRAMM-AUFRUF ! RELATIVER SPRUNG
;              ..           !            ..
;      LXI B, NACH-VON      !       LXI B,NACH-VON
;      CALL RELCAL.         !       CALL REL JMP
;VON:          ..           ! VON:        ..
;              ..           !             ..
;NACH: ;NTERPROGRAMM-ANFANG ! NACH: ;SPRUNG-ZIEL
;
;SIND DEM ASSEMBLER DIE WERTE "VON" UND "NACH" NICHT BEKANNT, MUSS
;DIE SUBTRAKTION VOM PROGRAMMIERER DURCHGEFUEHRT WERDEN.
;*************************************************************************

RELCAL:
            JMP RCAL                ;RELATIVER UNTERPROGRAMM-AUFRUF
RELJMP:
            JMP RJMP                ;RELATIVER SPRUNG

;*************************************************************************
;AUFRUF VON UNTERPROGRAMMEN NUTZT MAN IM ALLGEMEINEN DEN CALL-BEFEHL
;IN DER FORM " CALL 1234".. UNTERPROGRAMME IM BFZ-MINI-DOS KOENNEN EBENFALLS
;AUF DIESE ART AUFGERUFEN WERDEN„ IN EVEN TL. SPAETEREN BFZ-MINI-DOS-VERSIONEN
;KOENNEN DIESE UNTERPROGRAMME ABER EVENTUELL IN ANDEREN ADRESSBEREICHEN LIEGEN.
;DIE CALL-BEFEHLE VERZWEIGEN DANN NICHT MEHR ZUM RICHTIGEN UNTERPROGRAMM.
;ABHILFE KANN MAN DURCH DIE VERWENDUNG VON "FUNKTIONS-CODES" SCHAFFENS
;HIERBEI WIRD NUR NOCH EINE EINZIGE UEBERGEORDNETE ROUTINE AUF GERUFEN.
;LIEBER EINEN CODE (DEN FUNKTIONS-CODE) IM C-REGISTER DER CPU GIBT MAN
;DABEI ANw WELCHES UNTERPROGRAMM ABGEARBEITET WERDEN SOLL. DIE EINSPRUNG-
;ADRESSE DER UEBERGEQRDNETEN ROUTINE MUSS DABEI NATUERLICH IN SAEMTLICHEN
;VERSIONEN DES BFZ-MINI-DOS BEIBEHALTEN WERDEN. DIE EINSPRUNG-ADRESSEN DER
;ANDEREN UNTERPROGRAMME KOENNEN SICH ABER AENDERN.

;EIN ANWENDUNGS-BEISPIEL
;     MVI C,FUNKTIONS-CODE    ; FUNKTIONSCODE IN DAS C-REGISTER LADEN
;     CALL ENTRY              ; UEBERGEORDNETES PROGRAMM AUFRUFEN

;*************************************************************************
;DIE HEXADEZIMALEN FUNKTIONS-CODES FINDEN SIE IN DEM KOMMENTAR ZUR VEKTOR-
;TABELLE "VT AB" (S.U.). DIE FUNKTION DER EINZELNEN UNTERPROGRAMME ENTNEHMEN
;SIE BITTE DEREN BESCHREIBUNG IM PROGRAMM-LISTING
;*************************************************************************

ENTRY:
            PUSH H
            PUSH D
            PUSH PSW

                                    ;DAS BFZ-MINI-DOS KANN ERWEITERT WERDEN. DIESE ERWEITERUNGEN
                                    ;KOENNEN EIGENE VEKTOR-TABELLEN "VTAB" BESITZEN. DAMIT DAS BFZ-
                                    ;MINI-DOS DIESE NEUEN TABELLEN VERWENDET. MUSS DIE ERWEITERUNG
                                    ;EINEN BESTIMMTEN CODE ENTHALTEN.
                                    ;SIE MUSS ENTWEDER IN DER SPEICHERZEILE 500CH (ERWEITERUNGS-
                                    ;STUFE 1) ODER IN DER SPEICHERZEILE 580CH (ERWEITERUNGSSTUFE 2)
                                    ;DEN WERT EDH (ERWEITERTES DOS) ENTHALTEN. FINDET DAS BFZ-MINI-
                                    ;DOS DIESEN WERT, SO VERWENDET ES DIE NEUE TABELLE. DIE TABELLE
                                    ;DER STUFE 2 IST DER STUFE 1 UEBERGEORDNET. DIE ERWEITERUNG MUSS
                                    ;DIE ANFANGS-ADRESSEN DER TABELLEN IN BESTIMMTEN SPEICHERZEILEN
                                    ;BEREITHALTEN:

                                    ;     ERW-STUFE   EDH-CODE IN       TABELLEN-ADR IN
                                    ;           1     500C              500D,500E
                                    ;           2     500C              580D,580E

                                    ;DIE NEUEN TABELLEN MUESSEN DEN GLEICHEN AUFBAU BESITZEN, WIE
                                    ;DIE TABELLE "VTAB".

            LHLD L580D              ;LADE ADR DER VEKTOR-TABELLE <ERWEIT. 2)
            LDA L580D - 1           ; LIEGT ERUEITERUNG VOR ?
            CPI $ed
            JZ TABOK                ;JA —> TABOK
            LHLD L500D              ;LADE ADR DER OEKTGR-TABELLE (ERWEIT. 1)
            LDA L500D - 1           ;LIEGT ERUEITERUNG VOR ?
            CPI $ed                 
            JZ TABOK                ;JA —> TABOK
            LXI H,VTAB              ;LADE- ADR DER VEKTOR-TABELLE (GRUNDVERSION)
TABOK:
            MOV A,M                 ;A=MAX. FUNKTIONS-C0DE
            CMP C                   ;VERGLEICHE MIT CODE IN C-REGISTER
            JC VRET0                ;SPRINGE, WENN MAX-CODE UEBERSCHRITTEN
            MOV A,C                 ;FUNKTIONS-CODE NACH A
VRET0:
            ADD A                   ;FUNKTIONS-CODE MAL ZWEI
            MVI D,$00               ;MSB (DE)=00
            MOV E,A                 ;(Funktions-Code * 2) nach E
            INX H                   ;ZEIGER AUF 1. VEKTOR DER TABELLE
            DAD D                   ;ZEIGER AUF RICHTIGEN VEKTOR
            MOV E,M                 ;* VEKTOR NACH HL
            INX H                   ;*
            MOV D,M                 ;*
            XCHG                    ;*
            POP PSW                 ;RESTORE AKKU UND FLAGS
            POP D                   ;RESTORE DE-REGISTERPAAR
            XTHL                    ;HL=HL.ALT, STACK=VEKTOR
VRET:
            RET                     ;SPRUNG ZUR AUFGERUFENEN FUNKTION

;*************************************************************************
VTAB:
            .byte $11               ;MAXIMALER FUNKTIONS-CODE PLUS EINS (17)
                                    ;CODES SIND HEXADEZIMAL ANGEGEBEN
            .word RESTORE           ;VEKTOR-TABELLE (CODE 00)
            .word STEPIN            ;               (CODE 01)
            .word SEEK              ;               (CODE 02)
            .word WSEC              ;               (CODE 03)
            .word RSEC              ;               (CODE 04)
            .word WTRK              ;               (CODE 05)
            .word VERIX             ;               (CODE 06)
            .word SELECT            ;               (CODE 07)
            .word DESEL             ;               (CODE 08)
            .word DREADY            ;               (CODE 09)
            .word DELAY             ;               (CODE 0A)
            .word REPCHR            ;               (CODE 0B)
            .word WAITSP            ;               (CODE 0C)
            .word INTINT            ;               (CODE 0D)
            .word TSTCHR            ;               (CODE 0E)
            .word LETTER            ;               (CODE 0F)
            .word TSTBS             ;               (CODE 10)
            .word VRET              ;               (CODE 11)

;*************************************************************************
;DIE ROUTINEN "RCAL" UND "RJMP" WERDEN BEI ANWENDUNG DER RELATIVEN
;VERZWEIGUNGEN (UNTERPROGRAMME "RELCAL" UND "RELJMP") AUFGERUFEN.
;*************************************************************************

RCAL:
            POP H                   ;"VON" NACH HL.
            PUSH H                  ;RETTE RUECKSPRUNG-ADR
            PUSH H                  ;ZUM AUSGLEICH DES FOLGENDEN "POP'S"
RJMP:
            POP H                   ;"VON" NACH HL
            DAD B                   ;ADDIERE OFFSET
            PCHL                    ;SPRINGE NACH "NACH"

;*************************************************************************
;     DAS PROGRAMM VERZWEIGT ZU DIESER STELLE, WENN EIN UNBEKANNTES 
;     MAT85--KOMMANDO EINGEGEBEN WURDE.

;DAS BFZ-MINI--DOS KANN ERWEITERT WERDEN. DIESE ERWEITERUNG KANN IN DER 
;SPEICHERZEILE 5OOOH (ERWEITERUNGSSTUFE 1 > ODER 5800H (ER WEITERUNGS- 
;STUFE 2) DEN WERT EDH ENTHALTEN. DAS PROGRAMM PRUEFT IM UNTERPROGRAMM 
;"UMG", OB DIESER WERT VORLIEGT. DABEI IST DIE STUFE 2 DER STUFE 1 UEBER- 
;GEORDNET. WIRD EDH GEFUNDEN, SO VERZWEIGT DAS UNTERPROGRAMM "UMG". DIE 
;RUECKSPRUNG—ADRESSE BLEIBT DABEI IM STACK!

;     ERW-STUFE   EDH-GEFUNDEN BEI  "UMG" VERZWEIGT NACH
;           1     5000              5001
;           2     5800              5801
;
; BEI 5001 BZW 5801 MUSS EIN SPRUNGBEFEHL STEHEN!
;*************************************************************************

FMAT:
            LXI H,L5800             ;ADRESSE DES 2. UMGEHUNGS-FLAGS
            CALL UMG                ;SPRINGE, WENN UMGEHUNGS-FLAG GESETZT
FX:            
            MOV A,C                 ;EINGABE-ZEICHEN NACH A
            CPI "F"                 ;FLOPPY?
            JZ FM                   ;JA -> FM

;*************************************************************************
;HIER, WENN NICHT "F"
;*************************************************************************

            LDA L5001               ;MAT85-ERWEITERUNG AB 5001H
            CPI JUMP                ;*
            JZ L5001                ;JA -> 5001H
            RET                     ;NEIN —> RETURN (FEHLER)

;*************************************************************************
;HIER WENN "F"
;*************************************************************************

FM:
            LXI H,$0000             ;VORSCHLAGS-ADRESSE 
            SHLD STARTA             ;START/STOP AUF
            SHLD STOPA              ;0000H SETZEN

;*************************************************************************
;RAM-VEKTOREN VERAENDERH 
;*************************************************************************

            MVI A,JUMP              ;JMP-OPCODE
            STA XSTSP               ;EINSETZEN
            STA XLAD1               ;
            STA XLAD2
            LXI H,GSTSP             ;ADRESSE
            SHLD XSTSP+1            ;EINSETZEN
            LXI H,GSTART
            SHLD XLAD1+1
            LXI H,MATLAD
            SHLD XLAD2+1
            MVI A,RETURN            ;RETURN OPCODE
            STA XSAV1               ;EINSETZEN
            LXI H,KMD               ;SRUNGZIEL FUER DOS-QUIT: KMD
            MVI A,1                 ;FLAG: DOS-AUFRUF VON MAT85
            JMP DOS1

;*************************************************************************
;DIESES UNTERPROGRAMM WIRD VOM DOS BEIM LADEN VON PROGRAMMEN AUFGERUFEN,
;WENN DAS DOS VON MAT85 AUS AUFGERUFEN WURDE.
;*************************************************************************

MATLAD:
            LHLD STARTA             ;START-ADRESSE
            SHLD PCWERT             ;ALS GO-ADRESSE EINSETZEN
            RET

;*************************************************************************
;DAS BFZ-MINI-DOS KANN ERWEITERT WERDEN. DIESE "ERWEITERUNG KANN IN DER
;SPEICHERZEILE 5004H (ERWEITERUNGSSTUFE 1) ODER IN DER SPEICHERZEILE 
;5804H (ERWEITERUNGSSTUFE 2) DEN WERT EDH ENTHALTEN.

;DAS PROGRAMM PRUEFT IM UNTERPROGRAMM "UMG", OB DIESER WERT VORLIEGT. 
;WIRD EDH GEFUNDEN, SO VERZWEIGT DAS UNTERPROGRAMM "UMG". DIE RUECK- 
;SPRUNGADRESSE BLEIBT DABEI IM STACK!

;     ERW-STUFE   EDH-GEFUNDEN BEI  "UMG" VERZWEIGT NACH
;           1     5004              5005
;           2     5804              5805
;
;BEI 5005 BZW- 5805 MUSS EIN SPRUNGBEFEHL STEHEN!
;*************************************************************************

FSPS:
            LXI H,L5804             ;ADR DES 2. UMGEHUNGS-FLAGS 
            CALL UMG                ;SPRINGE, WENN UMGEHUNGS-FLAG GESETZT

;*************************************************************************
;FSPS KANN VON MAT85+SPS UND DER EPROMMER-SOFTWARE AUS AUFGERUFEN 
;WERDEN. ES MUSS FESTGESTELLT WERDEN, OB DER AUFRUF VON SPS AUS ERFOLGTE.
;DIES IST Z.B. MOEGLICH, INDEM MAN PRUEFT, OB "ZULKMD" IM STACK STEHT.
;*************************************************************************

            POP H                   ;WERT AUS STACK
            PUSH D                  ;RETTE EINGABE-ZEICHEN (D)
            LXI D,ZULKMD            ;ZEIGER AUF TABELLE DER ZULAESSIGEN 
                                    ;KOMMANDOS (MAT85+ SPS)
            CALL CMPHD              ;HL=DE?
            POP D                   ;RESTORE EINGABE-ZEICHEN (D)
            PUSH H                  ;WERT ZURUECK IN DEN STACK
            JNZ SP1EXP              ;HL <> DE -> SP1EXP

;*************************************************************************
;HIER, WENN DER AUFRUF VON SPS AUS ERFOLGTE
;*************************************************************************

            MOV A,D                 ;EINGABEZEICHEN NACH A
            CPI "F"                 ;FLOPPY ?
            JZ SPSDOS               ;JA -> SPS-DOS

;*************************************************************************
;HIER, WENN DER AUFRUF NICHT VON SPS AUS ERFOLGTE
;ODER WENN NICHT "F" EINGEGEBEN WURDE.
;*************************************************************************

SP1EXP:
            LDA L5005               ;SPS ERWEITERUNG AB 5005H ?
            CPI JUMP                ;
            JNZ CHROK               ;FEHLER (Z-FLAG = 0 !)
            JMP L5005               ;JA —> 5005H

;*************************************************************************
;HIER, WENN DER AUFRUF VON SPS AUS ERFOLGTE
;UND "F" EINGEGEBEN WURDE.
;*************************************************************************

SPSDOS:
            CALL PTXT               ;PRINT "F"
            .byte "F",$0            
SDOSO:
            CALL RCHAR              ;LESE ZEICHEN VON TASTATUR
            CPI CR                  ;CR
            JZ SDOS                 ;JA -> SDOS
            CALL TSTBS              ;PRINT BS,SPACE,BS WENN BS ODER DEL
            JNZ SDOSO               ;WEDER BS NOCH DEL -> SDOS0

;*************************************************************************
;HIER, WENN BS ODER DEL EINGEGEBEN WURDE
;*************************************************************************
         
SD1:
            DI                      ;DISABLE INTERRUPT
            POP H                   ;HL-ZEIGER AUF ZUL. EINGABE-ZEICHEN (SPS)
SD2:
            LXI SP,USRSTK           ;REINIT STACKPOINTER
                                    ;[P01#03] Originalcode: LXI SP,$FC00 
SD3:
            LXI B,SRET1             ;RUECKSPRUNG-ADR
SD4:
            PUSH B                  ; IN DEN STACK
            JMP CMDINP              ; GEBE NEUES KOMMANDO EIN (CMDINP)

;*************************************************************************
;HIER, WENN DER AUFRUF VON SPS AUS ERFOLGTE
;UND DIE EINGABE "F" MIT <CR> ABGESCHLOSSEN WURDE
;
;DAS PROGRAMM AENDERT NUN RAM-VEKTOREN
;*************************************************************************

SDOS:                               ; Vormals Teil von SDOS, Routine wird oefters benutzt
                                    ; und deshalb als Unterprogramm ausgelagert
            MVI A,RETURN            ;RET-OPCODE EINSETZEN
                                    ; DOS Vektoren setzen fuer externe Programme
            STA XSTSP               ;EINSETZEN
            MVI A,JUMP              ;JMP -OPCODE
            STA XSAV1               ;EINSETZEN
            STA XLAD1
            STA XLAD2
            LXI H,LENSPS            ;ADRESSE EINSETZEN
            SHLD XSAV1+1
            LXI H,SLAD1
            SHLD XLAD1+1
            LXI H,SLAD2
            SHLD XLAD2+1
            LXI H,SPS_RAM_PROG      ; Lade SPS-Speicher Anfangs-Adresse
            SHLD STARTA             ; Anfangsadresse abspeichern
            LHLD SPS_PT_END         ; Lade SPS-Speicher End-Adresse
            SHLD STOPA              ; Endadresse abspeichern
            LXI H,SPS               ; Ruecksprungvektor fuer DOS-Ende
            MVI A,2                 ; FLAG: DOS-AUFRUF VON SPS (Dateityp 2 = SPS)
            JMP DOS1                ; Einsprung ins DOS

;*************************************************************************
;DIE FOLGENDEN DREI UNTERPROGRAMME WERDEN VOM BFZ-MINI-DOS AUS AUFGERUFEN
;
;TEST, OB SPS-PROGRAMMSPEICHER LEER.. (BEI "SAVE")
;*************************************************************************

LENSPS:
            LHLD SPS_PT_END         ;PROGRAMM-SPEI CHER LEER?
            LXI D,SPS_RAM_PROG      ;
            CALL CMPHD              ;
            CZ CODE16               ;JA —> CODE16
            RET
;*************************************************************************
;LOESCHE. ALTES SPS-PROGRAMM IM SPEICHER. (BEI "LOAD")
;*************************************************************************

SLAD1:
            LXI H,SPS_RAM_PROG      ;LOESCHE ALTES PROGRAMM
            MVI M,$FF               ;
            SHLD SPS_PT_END         ;
            RET

;*************************************************************************
;UEBERNEHME NEUE SPS-PROGRAMM-STOPADRESSE. (BEI "LOAD")
;*************************************************************************

SLAD2:
            LHLD STOPA              ;UEBERTRAGE NEUE STOP-ADR
            SHLD SPS_PT_END         ;
            RET

;*************************************************************************
;     DAS PROGRAMM VERZWEIGT ZU DIESER STELLE, WENN EIN UNBEKANNTES 
;     BASIC-KOMMANDO EINGEGEBEN WURDE.

;DAS BFZ—MINI—DOS KANN ERWEITERT WERDEN. DIESE ERWEITERUNG KANN IN DER 
;SPEICHERZEILE 5008H (ERWEITERUNGSSTUFE 1) ODER IN DER SPEICHERZEILE
;580SH (ERWEITERUNGSSTUFE 2) DEN WERT EDH ENTHALTEN.

;DAS PROGRAMM PRUEFT IM UNTERPROGRAMM "UMG", OB DIESER WERT VORLIEGT. 
;DABEI IST DIE STUFE 2 DER STUFE 1 UEBERGEORDNET. WIRD EDH GEFUNDEN, 
;SO VERZWEIGT DAS UNTERPROGRAMM "UMG"- DIE RUEGKSPRUMGADRESSE BLEIBT
;DABEI IM STACK!
;

;     ERW-STUFE   EDH-GEFUNDEN BEI  "UMG" VERZWEIGT NACH
;           1     5008              5009
;           2     5808              5809
;

;*************************************************************************
;BEI 5009 BZW 5809 MUSS EIN SPRUNGBEFEHL STEHEN!
;*************************************************************************

FBAS:
            LXI H,L5808             ;ADRESSE DES 2. UMGEHUNGS-FLAGS
            CALL UMG                ;SPRINGEv WENN UMGEHUNGS-FLAG GESETZT

;*************************************************************************
;DAS BASIC-KOMMANDO "FLOPPY" IST NUR IM DIREKT—MODUS (NICHT IN EINEM
;PROGRAMM) ZULAESSIG. ES MUSS GEPRUEFT WERDEN, OB DER DIREKT-MODUS
;VORLIEGT.
;*************************************************************************

            LDA DIRKOM              ;DIREKT-KOMMANDO ?
            ORA A                   ;
            JNZ BASEXP              ;NEIN —> BASEXP

;*************************************************************************
;DER DIREKT-MODUS LIEGT VOR. WURDE ABER AUCH "FLOPPY" EINGEGEBEN ?
;*************************************************************************
          
            LXI H,BASBUF            ;ZEIGT DE AUF BASIC-INPUT-BUFFER ?
            CALL CMPHD              ;
            JNZ BASEXP              ;NEIN —> BASEXP

            LXI H,FLOPPY            ;ZEIGER AUF "FLOPPY " (VERGLEICHSTEXT)
            MVI B,6                 ;6 ZEICHEN PRUEFEN
PBAS:
            LDAX D                  ;ZEICHEN AUS BUFFER NACH A
            CMP M                   ;VERGLEICHE MIT ZEICHEN AUS "FLOPPY"
            JNZ BASEX0              ;UNGLEICH —> BASEX0
            INX D                   ; STELLE ZEIGER WEITER
            INX H                   ;
            DCR B                   ;6 ZEICHEN GEPRUEFT ?
            JNZ PBAS                ;NEIN —> PBAS

;*************************************************************************
;HIER, WENN "FLOPPY" EINGEGEBEN WURDE.#
;FOLGEN WEITERE ZEICHEN ?
;(JA —> GILT IN DER JETZIGEN VERSION NICHT ALS BFZ-MINI-DOS-AUFRUF)
;IST DIE EINGABE MIT CR ABGESCHLOSSEN?
;*************************************************************************

            CALL R5                 ;WELCHES ZEICHEN (AUSSER " ") FOLGT ?
            CPI CR                  ;CR ?
            JZ BDOS                 ;JA -> BDOS

BASEX0:
            LXI D,BASBUF            ;ZEIGER AUF ANFANG DES INPUT-PUFFERS
BASEXP:
            LDA L5009               ; BASIC ERWEITERUNG AB 5009H ?
            CPI JUMP                ; *
            RNZ                     ;NEIN —> RETURN (FEHLER)
            JMP L5009               ;JA —> 5009H

;*************************************************************************
;VERGLEICHS-TEXT (FLOPPY-BEFEHL)
;*************************************************************************

FLOPPY:
            .byte "FLOPPY"          ;FLOPPY-BEFEHL (BASIC-BEFEHL)

;*************************************************************************
;HIER, WENN "FLOPPY" OHNE WEITERE ZEICHEN IM DIREKTMODUS EINGEGEBEN WURDE
;
;DAS PROGRAMM VERAENDERT RAM-VEKTOREN!
;*************************************************************************

BDOS:
            MVI A,RETURN            ;RET -OPCODE    
            STA XSTSP               ;EINSETZEN
            MVI A,JUMP              ;JMP-OPCODE
            STA XSAV1               ;EINSETZEN
            STA XLAD1
            STA XLAD2
            LXI H,CHKLEN            ;ADRESSE EINSETZEN
            SHLD XSAV1+1
            LXI H,BLAD1
            SHLD XLAD1+1
            LXI H,BLAD2
            SHLD XLAD2+1
            LXI H,TXTBGN            ;PROGRAMM-ANFANG
            SHLD STARTA             ;EINSETZEN
            LHLD TXTUNF             ;PROGRAMM-ENDE
            DCX H                   ; Ende - 1
            SHLD STOPA              ;EINSETZEN

            LXI H,BASIC             ;SPRUNGZIEL FUER DOS-"QUIT": BASIC
            MVI A,3                 ;FLAGS DOS-AUFRUF VON BASIC (Dateityp 3 = BAS)
            JMP DOS1                ;RUFE DOS AUF

;*************************************************************************
;DIE FOLGENDEN DREI UNTERPROGRAMME WERDEN VOM BFZ-MINI-DOS AUFGERUFEN
;
;TEST, OB BASIC-PROGRAMMSPEICHER LEER (BEI "SAVE")
;*************************************************************************

CHKLEN:
            LHLD TXTUNF             ;PROGRAMM -SPEICHER LEER ?
            LXI D,TXTBGN            ;
            CALL CMPHD
            CZ CODE16               ; JA -> CODE16
            RET

;*************************************************************************
;LOESCHE ALTES BASIC-PROGRAMM IM SPEICHER (BEI "LOAD")
;*************************************************************************

BLAD1:
            CALL CLEAR              ;LOESCHE ALTES PROGRAMM
            RET

;*************************************************************************
;UEBERNEHME NEUE BASIC-PROGRAMM-STOPADRESSE (BEI "LOAD")
;*************************************************************************

BLAD2:
            LHLD STOPA              ;UEBERTRAGE NEUE STOP-ADR
            INX H
            SHLD TXTUNF
            RET

;************************************************************************
;*                                                                      *
;*          DOS-INITIALISIERUNGS-TEIL                                   *
;*                                                                      *
;************************************************************************

DOS1:
            LXI SP,USRSTK           ;(RE)-INIT SP
DOS2:
            CALL BCLEAR             ;LOESCHE BILDSCHIRM
DOS3:
            STA EFROM               ;RETTE FLAG (ENTERED FROM)
DOS4:
            SHLD DOSRET             ;RETTE SPRUNGZIEL FUER "QUIT"

                                    ;
                                    ;DAS BFZ-MINI-DOS KANN ERWEITERT WERDEN. DIESE ERWEITERUNG
                                    ;KANN EINE EIGENE INFO-TABELLE HABEN (S.U.). DAMIT DAS BFZ-
                                    ;MINI-DOS DIE NEUE INFO-TABELLE VERWENDET, MUSS DIE ERWEITERUNG
                                    ;ENTWEDER IN DER SPEICHERZEILE 500FH (ERWEITERUNGSSTUFE 1) ODER
                                    ;IN DER SPEICHERZEILE 580FH (ERUIEITERUNGSSTUFE 2) DEN WERT EDH
                                    ;ENTHALTEN. DAS PROGRAMM SUCHT NACH DIESEM WERT. BEI DER SUCHE
                                    ;IST STUFE 2 DER STUFE 1 UEBERGEORDNET. WIRD EDH GEFUNDEN, SO
                                    ;WIRD DIE INFO-TABELLE AUS DER ERWEITERUNG VERWENDET. DIE INFO-
                                    ;TABELLE SELBST MUSS DEN GLEICHEN AUFBAU HABEN WIE DIE TABELLE
                                    ;IN DER BFZ-MINI-DOS-GRUNDVERSION. DIE ZWEI SPEICHERZEILLEN,
                                    ;DIE DEM ED-CODE FOLGEN, MUESSEN DIE ADRESSE DER INFO-TABELLE
                                    ;ENTHALTEN:

                                    ;     ERW-STUFE   EDH-GEFUNDEN BEI  "UMG" VERZWEIGT NACH
                                    ;           1     500F              5010,5011
                                    ;           2     580F              5810,5811
                                    ;

            LHLD L5810              ;ADR DER INFO-TABELLE (STUFE 2)
            LDA L5810 - 1           ; DOS-EEWEITERUNG AB 580FH ?
            CPI $ED                 ; STUFE 2
            JZ DOS                  ;JA — > DOS (TABELLE STUFE 2)
            LHLD L5010              ;ADR DER INFO-TABELLE (STUFE 1)
            LDA L5010 - 1           ; DOS-EEWEITERUNG AB 500FH ?
            CPI $ED                 ; STUFE 2
            JZ DOS                  ;JA — > DOS (TABELLE STUFE 1)
            LXI H,INFOT             ;ADR DER INFO-TABELLE (GRUNDVERSION)

;*************************************************************************
;DAS PROGRAMM ENTNIMMT DER INFO-TABELLE NUN MEHRERE ANGABEN
;
;1. ZEIGER AUF TYP-TABELLE (TABELLE DER FILE-TYPEN WIE: MAT, SPS, BAS)
;*************************************************************************

DOS:
            MOV E,M                 ;LADE ZEIGER AUF TYP-TABELLE 
            INX H                   ;NACH HL 
            MOV D,M                 ;
            INX H                   ;
            XCHG                    ;
            SHLD PTYPT              ;RETTE ZEIGER AUF TYP-TABELLE

;*************************************************************************
;2. ZEIGER AUF ERROR-VEKTOR-TABELLE (WELCHE MELDUNG BEI WELCHEM FEHLER)
;*************************************************************************
            
            XCHG                    ;LADE ZEIGER AUF ERROR-VEKTOR-TABELLE
            MOV E,M                 ;NACH HL
            INX H                   ;
            MOV D,M                 ;
            INX H                   ;
            XCHG                    ;
            SHLD PEVT               ;RETTE ZEIGER AUF ERROR-VEKTOR-TABELLE

;*************************************************************************
;3. VERSIGNS-NUMMER
;*************************************************************************

            XCHG                    ;
            SHLD PVNR               ;RETTE ZEIGER AUF VERSIONSNUMMER

;*************************************************************************
;4. TABELLE DER ZULAESSIGEN EINGABE-ZEICHEN
;*************************************************************************

            INX H                   ;STELLE ZEIGER AUF TABELLE DER
            INX H                   ;ZULAESSIGEN EINGABE-ZEICHEN
            SHLD PTZZ               ;RETTE ZEIGER

;*************************************************************************
;5. ZEIGER AUF KOMMANDO-TABELLE (WELCHE ROUTINE BEI WELCHER EINGABE)
;*************************************************************************

DOS5:
            MOV A,M                 ;SUCHE NACH ENDE DER TABELLE
            INX H                   ;DER ZULAESSIGEN EINGABE-ZEICHEN
            ORA A                   ;
            JNZ DOS5                ;
            SHLD PMENUE             ;RETTE ZEIGER AUF KOMMANDO-TABELLE

;*************************************************************************
;TRITT BEI DER AUSFUEHRUNG EINES KOMMANDOS EIN FEHLER AUF, SO VERZWEIGT
;DAS PROGRAMM NACH "XERR" IM RAM. DORT WIRD AN DIESER STELLE EIN SPRUNG
;NACH "ERROR" EINGESETZT.
;*************************************************************************

            MVI A,JUMP              ;SETZE "JMP ERROR" EIN 
            STA XERR                ;
            LXI H,ERROR             ;
            SHLD XERR+1             ;

;*************************************************************************
;DAS BFZ-MINI-DOS MELDET SICH NUN
;*************************************************************************

            CALL PTXTCR             ;PRINT TEXT
            .byte LF,"BFZ-MINI-DOS V",00
            LHLD PVNR               ;ZEIGER AUF VERSIONS-NUMMER
            MOV A,M                 ;GEBE 1. ZIFFER DER
            CALL WCHAR              ;VERSIONS-NUMMER AUS
            MVI A,"."               ;GEBE "." AUS
            CALL WCHAR              ;
            INX H                   ;GEBE 2. ZIFFER DER
            MOV A,M                 ;VERSIONS-NUMMER AUS
            CALL WCHAR              ;
            CALL PTXTCR             ;PRINT TEXT
            .byte LF,"(C) 1985 BY BFZ, ESSEN, W. GERMANY",00

                                    ;ORIGINAL-CODE AN DIESER STELLE:

            .byte 00,00,00,00,00,00,00      ;Nicht zwingend erforderlich

;*************************************************************************
;TRITT EIN FEHLER AUF, SO ARBEITET DAS DOS DIE "ERROR"—ROUTINE AB.
;DIESE ENDET MIT EINEM SPRUNG ZU DER ADRESSE, DIE UNTER "ERRRET" IM
;RAM STEHT. DAS PROGRAMM TRAEGT HIER "MENUE" EIN.
;*************************************************************************

MENUE:
            DI                      ;INTERRUPT DEAKTIVIEREN
            LXI H,MENUE             ;RETURN-ADR VON ERROR
            SHLD ERRRET             ;ABSPEICHERN

;*************************************************************************
;AUSGABE DES MENUES
;*************************************************************************

            CALL PTXTCR             ;PRINT TEXT
            .byte LF,"MENUE:",LF,CR,00
            LHLD PMENUE             ;ZEIGER AUF KOMMANDO-TABELLE
            CALL PKLIST             ;GEBE TABELLE AUS

;*************************************************************************
;LESE EINGABE
;*************************************************************************

;DOSKMD:
            CALL GETCHR             ;LESE ZEICHEN
            LHLD PTZZ               ;ZEIGER AUF TABELLE DER ZULAESSIGEN ZEICHEN
            CALL TEST               ;ZEICHEN UNGUELTIG?
            CC CODE0                ;NEIN -> CODE 0

;*************************************************************************
;HIER, WENN EINGABEZEICHEN GUELTIG
;*************************************************************************

            MOV C,A                 ;ZEICHEN NACH C
            LHLD PMENUE             ;ZEIGER AUF KOMMANDO-TABELLE
            JMP EXEC                ;FUEHRE KOMMANDO AUS

;*************************************************************************
;INFO-TABELLE DER GRUNDVERSION
;*************************************************************************

INFOT:
            .word TYPT              ;ZEIGER AUF TYP-TABELLE
            .word ERRVEK            ;ZEIGER AUF ERROR-VEKTOR-TABELLE

INFOTV:
DOSVER:
            .byte "14"              ;14 wird vom Editor geprueft!
            .byte "DEFLSQ"          ;TABELLE DER ZULAESSIGEN ZEICHEN
            .byte 00             
                                    ;KOMMANDO-LISTE
                                    ;AUFBAU:
                                    ;1. KOMMANDO-NAME
                                    ;2. 00H
                                    ;3. ADR DER ROUTINE, DIE BEI EINGABE DES KOMMANDOS
                                    ;   ABGEARBEITET WERDEN SOLL

            .byte "DIRECTORY",00    ;DIR
            .word DIR
            .byte "ERASE",00        ;ERASE
            .word ERASE
            .byte "FORMAT",00       ;FORMAT
            .word DSKFORM
            .byte "LOAD",00         ;LOAD
            .word DSKLOAD
            .byte "SAVE",00         ;SAVE
            .word DSKSAVE
            .byte "QUIT",00         ;QUIT
            .word QUIT
            .byte 00                ; KOMMANDO-TABELLE MUSS MIT 00 BEENDET WERDEN.

;*************************************************************************
;
;DOS-BEFEHL QUIT
;
;*************************************************************************
;HIER, WENN "Q" QUIT EINGEGEBEN WURDE
;*************************************************************************

QUIT:
            LHLD DOSRET             ;LADE RUECKSPRUNG-ADR
            PCHL                    ;BEENDE BFZ-MINI-DOS

;*************************************************************************
;
;DOS-BEFEHL DIR
;
;*************************************************************************
;HIER, WENN "D" QUIT EINGEGEBEN WURDE
;*************************************************************************

;TRITT EIN FEHLER AUF, SO ARBEITET DAS DOS DIE ROUTINE "ERROR" AB.
;DIESE ENDET MIT EINEM SPRUNG ZU DER ADRESSE, DIE UNTER "ERRRET" IM
;RAM STEHT. DAS PROGRAMM TRAEGT HIER "DIRE" EIN.
;*************************************************************************

DIR:
            LXI H,DIRE              ;RETURN-ADR VON ERROR
            SHLD ERRRET             ;ABSPEICHERN

;*************************************************************************
;VON WELCHEM LAUFWERK SOLL DAS DIRECTORY ANGEZEIGT WERDEN?
;*************************************************************************

DIRE:
            CALL LAUFW              ;LESE LAUFWERK-NAME
                                    ;PRUEFE IHN
                                    ;BERECHNE SELECT-MASKE
;*************************************************************************
;BEI FEHLERN IM WEITEREN PROGRAMM-ABLAUF RUECKKEHR NACH "MENUE"
;*************************************************************************

            LXI H,MENUE             ;RETURN-ADR VON ERROR
            SHLD ERRRET             ;ABSPEICHERN
            CALL PTXT               ;PRINT 2 x LINE-FEED
            .byte LF,LF,00          ;
            MVI A,$01               ;SETZE FLAG: "DISPLAY DIRECTORY"
            STA DSPLD
            CALL LINE1              ;PRINT UEBERSCHRIFT, INIT ZEICHENZAEHLER
            CALL SEINTR             ;LESE DIRECTORY UND ZEIGE EINTRAEGE AN
            CPI 79                  ;79 FREIE EINTRAEGE?
            JNZ NLEER               ;NEINE -> NLEER (NICHT LEER)

;*************************************************************************
;HIER, WENN DIRECTORY LEER
;*************************************************************************

            LHLD PRTST              ;LADE AKTUELLES DRUCKER "FLAG"
            PUSH H                  ; RETTE HL (FLAG)
            LXI H,SERO              ;DRUCKER-AUS-FLAG
//            LXI H,$089F           ; PRTOFF ????
//                                  ; Muesste geaendert werden da ser-io 
                                    ; bei Drucker nicht richtig funktioniert!
            SHLD PRTST              ;SETZE FLAG EIN (DRUCKER AUS)
            CALL PTXT               ;GEBE STEUERZEICHEN AUS
            .byte $0b," ",CR,00     ;LOESCHE KOPFZEILE
            POP H                   ;ALTES DRUCKER-FLAG HOLEN
            SHLD PRTST              ; WIEDERHESTELLEN
            CALL PTXT               ;TEXT AUSGEBEN
            .byte "*** KEIN EINTRAG IM DIRECTORY ***",LF,LF,CR,00

;*************************************************************************
;HIER, WENN DIRECTORY NIGHT LEER
;BZW. WENN "KEIN EINTRAG IM DIRECTORY" AUSGEGEBEN WURDE
;ANZEIGE DER FREIEN 4K-BYTE—BLOECKE
;*************************************************************************

NLEER:
            CALL CRLF               ;PRINT CR,LF
            CALL WDEZ               ;PRINT ANZAHL
            CALL PTXT               ;TEXT AUSGEBEN
            .byte " FREIE 4K-BYTE-BLOECKE",LF,CR,00

;*************************************************************************
;BEENDE ROUTINE
;DIE ROUTINE WIRD DURCH "JMP ERR0R2" BEENDET, OBWOHL KEIN FEHLER
;AUFGETRETEN IST. ES WERDEN BEFEHLE IN DER "ERROR"-ROUTINE GENUTZT
;UND DADURCH SPEICHERPLATZ GESPART.
;*************************************************************************

            JMP ERROR2              ;DESELECT LAUFWERK
                                    ;WARTE, BIS SPACE EINGEGEBEN WURDE

;*************************************************************************
;
;DOS-BEFEHL ERASE
;
;*************************************************************************
;HIER, WENN "E" ERASE EINGEGEBEN WURDE
;
;TRITT EIN FEHLER AUF, SO VERZWEIGT DAS BFZ-MINI-DOS ZU DER ROUTINE 
;"ERROR"- DIESE WIRD MIT EINEM SPRUNG ZU DER ADRESSE BEENDET, DIE 
;UNTER "ERRRET" IM RAM STEHT. DAS PROGRAMM TRAEGT HIER "ERERR" 
;(ERASE-ERROR) EIN..
;*************************************************************************

ERASE:
            LXI H,ERERR             ;RETURN-ADR VON ERROR
            SHLD ERRRET             ;ABSPEICHERN

;*************************************************************************
;AUF WELCHEM LAUFWERK SOLL GELOESCKT WERDEN ?
;*************************************************************************

ERERR:
            CALL LAUFW              ;LESE LAUFWERKSNAME

;*************************************************************************
;BEI FEHLERN IM WEITEREN PROGRAMMABLAUF RUECKKEHR NACH "MENUE"
;*************************************************************************

            LXI H, MENUE            ;RETURN-ADRESSE VON ERROR
            SHLD ERRRET             ;ABSPEICHERN

;*************************************************************************
;START DES LOESCHVORGANGS
;FILE—EINTRAG IM DIRECTORY SUCHEN
;*************************************************************************

            XRA A                   ;LOESCHE FLAG
            STA DSPLD               ;—> DIRECTORY NICHT ANZEIGEN
            CALL GETNAM             ;LESE FILE-NAME
            CALL SEINTR             ;SUCHE EINTRAG

;*************************************************************************
;WIEVIELE DIRECTORY—EINTRAEGE BESITZT DER FILE ? 
;(NULL EINTRAEGE = FILE NICHT IM VERZEICHNIS)
;*************************************************************************

            LDA ZAEHLV              ;ANZAHL DER ZU LOESCHENDEN EINTRAEGE
            ORA A                   ;NULL?
            CZ CODE11               ;JA —> FILE NICHT IM VERZEICHNIS

;*************************************************************************
;BEIM LOESCHEN (ERASE) WIRD NICHT DER EIGENTLICHE FILE GELOESCHT 
;ES WIRD IM DIRECTORY-EINTRAG NUR EIN BYTE VERAENDERT 
;(AUFBAU DES DIRECTORY'S: SIEHE UNTERPROGRAMM "SEINTR")
;DAZU MUSS AUF DIE DISKETTE GESCHRIEBEN WERDEN
;*************************************************************************

            CALL RESTORE            ;KOPF IST SCHON AUF SPUR NULL 
                                    ;DIENT NUR ZUR AKTUALISIERUNG 
                                    ;DES FDC-STATUS-REGISTERS
            ANI %10011100           ;ALLES OK ?
            CPI %00000100           ;
            CNZ CODE1               ;NEIN —> CODE1
            MOV A,E                 ;STATUS ERNEUT NACH A
            ANI %01000000           ;WRITE PROTECT ?
            CNZ CODE4               ;JA —> CODE4

;*************************************************************************
;DER EIGENTLICHE LOESCHVORGANG WIRD VOM UNTERPROGRAMM "DELETE" AUSGEFUEHRT
;*************************************************************************

            LDA ZAEHLV              ;ANZAHL DER ZU LOESCHENDEN EINTRAEGE   
            CALL DELETE             ;DELETE EINTRAEGE

;*************************************************************************
;LOESCHVORGANG BEENDET
;*************************************************************************

            CALL PSTAR              ;TEXT AUSGEBEN
            .byte "FILE GELOESCHT",00

;*************************************************************************
;ROUTINE BEENDEN
;DIE ROUTINE WIRD DURCH EINEN SPRUNG NACH "ERET" BEENDET OBWOHL KEIN
;FEHLER AUFGETRETEN IST. DURCH DIE NUTZUNG EINIGER BEFEHLE DER "ERROR"-
;ROUTINE WIRD SPEICHERPLATZ GESPART
;*************************************************************************

            JMP ERET                ;FERTIG

;*************************************************************************
;DOS-BEFEHL FORMAT
;HIER, WENN "F" FORMAT EINGEGEBEN WURDE
;*************************************************************************

DSKFORM:
            LXI SP,USRSTK           ;RE-INIT STACKPOINTER

;*************************************************************************
;WENN EIN FEHLER AUFTRITT, WIRD DIE ROUTINE "ERROR" ABGEARBEITET., DIESE
;ENDET MIT EINEM SPRUNG ZU DER ADRESSE, DIE UNTER "ERRRET" IM RAM STEHT-
;DAS PROGRAMM SETZT HIER "F0RM1" EIN.
;*************************************************************************

            LXI H,FORM1             ;RETURN-ADR VON ERROR-ROUTINE
            SHLD ERRRET             ;ABSPEICHERN
                                    ;WARNUNG AUSGEBEN            
            CALL PTXTCR             ;TEXT AUSGEBEN
            .byte 07,LF
            .byte "A C H T U N G !",LF,CR
            .byte "PROGRAMME IM BEREICH E000 - FFFF (Z. B. SPS)",LF,CR
            .byte "UND DATEN AUF DER DISKETTE WERDEN ZERSTOERT !",00

;*************************************************************************
;IN WELCHEM LAUFWERK SOLL FORMATIERT WERDEN ?
;*************************************************************************

FORM1:
            CALL LAUFW              ;LAUFWERK-NAME EINLESEN, MASKE ERSTELLEN
                                    ;BITTE DISKETTE EINLEGEN

            CALL PTXTCR             ;TEXT AUSGEBEN
            .byte "DISKETTE IN LAUFWERK ",$22,$00
            LDA CHAR                ;LAUFWERK-BUCHSTABE NACH A
            CALL WCHAR              ;PRINT BUCHSTABE
            CALL PTXT               ;TEXT AUSGEBEN
            .byte $22,", DANN <SPACE>",00
            CALL WAITSP             ;WARTEN, BIS <SPACE> EINGEBEN WURDE
            CALL CRLF               ;PRINT CR,LF
            MVI D,40                ;40 STRICHE (LINIE)
            CALL PLINE              ;AUSGEBEN

;*************************************************************************
;LAUFWERK SELEKTIEREN
;*************************************************************************

            XRA A                   ;SEITE = 0
            STA SEITE               ;
            CALL SELECT             ; SELECT LAUFWERK

;*************************************************************************
;"ERRRET" MUSS ERNEUT MIT "FORM!" GELADEN WERDEN.
;DA DER WERT DURCH EIN UNTERPROGRAMM VERAENDERT WURDE.
;*************************************************************************

            LXI H,FORM1             ;RETURN-ADR VON ERROR-ROUTINE
            SHLD ERRRET             ;ABSPEICHERN

;*************************************************************************
;LAUFWERK BEREIT?
;*************************************************************************

            CALL DREADY             ;LAUFWERK BEREIT ?
            CC CODE3                ;FEHLER, WENN LAUFWERK NICHT BEREIT

;*************************************************************************
;INITIALISIERUNG DER INTERRUPT-ROUTINE 
;(DAS BFZ—MINI—DOS NUTZT DIE FDC—SIGNALE "DRQ" UND "INTRQ" ZUR 
;SYNCHRONISIERUNG DER DATENUEBERTRAGUNG).
;*************************************************************************

            CALL INTINT             ;INTERRUPT-ROUTINE INITIALISIEREN

;*************************************************************************
;KOPF AUF SPUR 0
;*************************************************************************

            CALL RESTORE            ;RESTORE
            ANI %01000000           ;WRITE PROTECT ?
            CNZ CODE4               ;JA -..........> FEHLER-MELDUNG
            MOV A,E                 ;STATUS NACH A
            ANI %11000100           ;ALLES OK ?
            CPI %00000100           ;
            CNZ CODE1               ;NEIN —> RESTORE ERROR
            LXI H,HEADIDLE          ;15 MS VERZOEGERUNG, DAMIT DER KOPF
            CALL DELAY              ;NACH RESTORE RUHIG STEHT

;*************************************************************************
;TRACK IM RAM AUFBAUEN
;*************************************************************************

            LXI H,VERTAB            ;INIT ZEIGER AUF VERSATZTABELLE
            MOV E,M                 ;LESE ERSTEN EINTRAG
            SHLD VERPTR             ;RETTE POINTER
            LXI H,FBUFFER           ;ZEIGER AUF TRACK BUFFER

;*************************************************************************
;SPUR-VORSPANN
;"VOR--GAP"
;*************************************************************************

            MVI A,$4E               ;80 * 4Eh
            MVI B,80                ;
            CALL REPCHR             ;
            MVI A,0                 ;12 * 00h
            MVI B,12                ;
            CALL REPCHR             ;
            MVI A,$F6               ;3 * F6h (SCHREIBT C2, FEHLENDER 
                                    ;        CLOCK ZWISCHEN BIT 3 UND 4)
            MVI B,3                 ;
            CALL REPCHR             ;
            MVI M,$FC               ;1 * FCh (INDEX-MARKE)
            INX H                   ;
            MVI A,$4E               ;50 * 4Eh
            MVI B,50                ;
            CALL REPCHR             ;

;*************************************************************************
;DIE SEKTOREN
;"GAP"
;*************************************************************************

SECTOR:
            MVI A,0                 ;12 * 00h
            MVI B,12                ;
            CALL REPCHR             ;
            MVI A,$F5               ;3 * F5h
            MVI B,3                 ;
            CALL REPCHR             ;

;*************************************************************************
;MARKE
;*************************************************************************

            MVI M,$FE               ;1 * FEh
            INX H                   ;

;*************************************************************************
;SEKTOR-KENNUNGSFELD            
;*************************************************************************

            INX H                   ;BLEIBT FREI FUER TRACK-NUMMER
            INX H                   ;BLEIBT FREI FUER SEITEN—NUMMER
            MOV M,E                 ;SEKTOR-NUMMER
            INX H
            MVI M,02                ;CODE: 512 BYTES / SEKTOR
            INX H
            MVI M,$F7               ;1 * F7h (ERZEUGT ZWEI CRC BYTES)
            INX H

;*************************************************************************
; "GAP"            
;*************************************************************************

            MVI A,$4E               ;22 * 4Eh
            MVI B,22                ;
            CALL REPCHR             ;
            MVI A,0                 ;12 * 00h
            MVI B,12                ;
            CALL REPCHR             ;
            MVI A,$F5               ;3 * F5h (SCHREIBT Al, FEHLENDER CLOCK
                                    ;         ZWISCHEN BIT 4 UND 5)
            MVI B,3
            CALL REPCHR

;*************************************************************************
;"MARKE"
;*************************************************************************

            MVI M,$FB               ;1 * FBh (DATA ADDRESS MARK)
            INX H

;*************************************************************************
;DATENBLOCK EINES SEKTORS           
;*************************************************************************

            MVI A,$E5               ;512 * E5h (512 DATEN-BYTES)
            MVI C,2
            MVI B,0

FDATA:
            CALL REPCHR
            DCR C
            JNZ FDATA

;*************************************************************************
;PRUEFBYTES            
;*************************************************************************

            MVI M,$F7               ;1 * F7h (ERZEUGT 2 CRC-BYTES)
            INX H

;*************************************************************************
;"GAP"            
;*************************************************************************

            MVI A,$4E               ;54 * 4Eh
            MVI B,54                ;
            CALL REPCHR             ;

;*************************************************************************
;8 SEKTOREN IN SPUR-PUFFER EINGETRAGEN ?
;NEIN —> LESE NAECHSTE SEKTOR-NUMMER AUS DER OERSATZ-TABELLE
;        UND TRAGE DEN SEKTOR IM SPUR-PUFFER EIN
;JA --> WEITER BEI "TRKEND"
;*************************************************************************

            MOV A,E                 ;SEKTOR-NUMMER NACH A
            CPI 8                   ;SEKTOR 8 (TRACK-ENDE) ?
            JZ TRKEND               ;JA —> TRKEND
            PUSH H                  ;RETTE BUFFER-ZEIGER
            LHLD VERPTR             ;HL-POINTER AUF VERSATZ TABELLE
            INX H                   ;STELLE ZEIGER WEITER
            MOV E,M                 ;LESE TABELLEN-EINTRAG
            SHLD VERPTR             ;RETTE POINTER AUF OERSATZ-TABELLE
            POP H                   ;RESTORE BUFFER-ZEIGER
            JMP SECTOR

;*************************************************************************
;NACH "GAP"
;*************************************************************************

TRKEND:
            MVI A,$4E               ;FUELLE BUFFER MIT 4E
            MVI B,0
            MVI D,6
TRKE0:
            CALL REPCHR
            DCR D
            JNZ TRKE0

;*************************************************************************
;GEBE <CR> AUS <CURSOR AUF ANFANG DER "----------"-ZEILE)            
;*************************************************************************

            MVI A,CR                ;SPRUNG AUF ANFANG DER ZEILE
            CALL WCHAR              ;ZEICHEN AUSGEBEN

;*************************************************************************
;SCHREIBE TRACK FUER TRACK AUF DIE DISKETTE
;*************************************************************************

;VORBEREITUNG
LOOP0:
            MVI D,0                 ;INIT TRACK-ZAEHLE
LOOP:
            XRA A                   ;SEITE NULL
            STA SEITE               ;
            MOV H,A                 ;
            MOV L,D                 ;TRACK-NUMMER
            SHLD FBUFFER+162        ; SPUR- UND
            SHLD FBUFFER+788        ; TRACK-NUMMER
            SHLD FBUFFER+1414       ; IM SPUR-PUFFER
            SHLD FBUFFER+2040       ; EINTRAGEN
            SHLD FBUFFER+2666       ; 
            SHLD FBUFFER+3292       ; 
            SHLD FBUFFER+3918       ; 
            SHLD FBUFFER+4544       ; 
;
;*************************************************************************
;            
            MVI A,MAXTRY            ;INIT VERSUCHSZAEHLER FUER VERIFY
            STA RETRY               ;
LOOP10:
            CALL WTRK               ;SCHREIBE TRACK (SEITE 0)
            ANI MWRTRK              ;ALLES OK
            CNZ CODE2               ;NEIN —> WRITE ERROR

;*************************************************************************
;PRUEFE TRACK. BEI FEHLERN WIRD TRACK NEU GESCHRIEBEN (BIS MAXTRY MAL)
;*************************************************************************

            CALL VERIFY             ;PRUEFE TRACK
            JZ LOOP11               ;ALLES OK —> LOOP11
            LDA RETRY               ;ANZAHL DER VERSUCHE
            DCR A                   ;-1
            CZ CODE5                ;0 —> VERIFY-ERROR
            STA RETRY               ;NICHT 0 —> SPEICHERE NEUEN ZAEHLER
            JMP LOOP10              ;NEUER SCHREIB-VERSUCH

;*************************************************************************
;VORBEREITUNG ZUM SCHREIBEN DES TRACKS AUF SEITE 1
;*************************************************************************

LOOP11:
            MVI A,1                 ;SEITE 1
            STA SEITE               ;
            STA FBUFFER+163
            STA FBUFFER+789
            STA FBUFFER+1415
            STA FBUFFER+2041
            STA FBUFFER+2667
            STA FBUFFER+3293
            STA FBUFFER+3919
            STA FBUFFER+4545

;*************************************************************************
;AKTUELLEN TRACK AUF SEITE 1 SCHREIBEN
;*************************************************************************
      
            MVI A,MAXTRY            ;INIT VERSUCHSZAEHLER FUER VERIFY
            STA RETRY               ;

LOOP13:
            CALL WTRK               ;PRUEFE TRACK
            ANI MWRTRK              ;ALLES OK ?
            CNZ CODE2               ;NEIN -> WRITE ERROR

;*************************************************************************
;PRUEFE TRACK. BEI FEHLERN WIRD TRACK NEU GESCHRIEBEN (BIS MAXTRY MAL)            
;*************************************************************************

            CALL VERIFY             ;PRUEFE TRACK
            JZ LOOP12               ;ALLES OK _> LOOP!""
            LDA RETRY               ;ANZAHL DER VERSUCHE
            DCR A                   ;-1
            CZ CODE5                ;0 -> VERIFY-ERROR
            STA RETRY               ;NICHT 0 -> SPEICHERE NEUEN ZAEHLER
            JMP LOOP13              ;NEUER SCHREIB-VERSUCH

;*************************************************************************
;SEINEN TRACK PRO SEITE GESCHRIEBEN. GEBE "+" AUS
;*************************************************************************

LOOP12:
            CALL PPLUS              ;PRINT "+"

;*************************************************************************
;40 TRACKS PRO SEITE GESCHRIEBEN ?
;*************************************************************************
            
            INR D                   ;NAECHSTE TRACK-NUMMER
            MOV A,D                 ;TRACK-NUMMER NACH A
            CPI 40                  ;TRACK 40 ?
            JZ FERTIG               ;JA —> FERTIG

;*************************************************************************
;ES MUESSEN NOCH TRACKS GESCHRIEBEN
;*************************************************************************

            CALL STEPIN             ;STEP IN (KOPF UM EINE SPUR NACH INNEN)
            LXI H,HEADIDLE          ;15 MS VERZOEGERUNGw DAMIT DER
            CALL DELAY              ;NACH STEPIN RUHIG STEHT
            JMP LOOP                ;SCHREIBE NAECHSTEN TRACK

;*************************************************************************
;DISKETTE IST FORMATIERT, DIRECTORY ANLEGEN
;*************************************************************************

FERTIG:
            XRA A                   ;A=0 (DIRECTORY WIRB AUF SEITE 0 GESCHR.)
            STA SEITE               ;SEITE 0
            MOV B,A                 ; SECTOR-PUFFER (512 BYTES)
            LXI H,SECB              ; MIT 00h FUELLEN.
            CALL REPCHR             ;
            CALL REPCHR             ;

;*************************************************************************
;DIREKTORY WIRB AUF SPUR 0 GESSCHRIEBEN. DAHER "RESTORE" (KOPF AUF SPUR 0)
;*************************************************************************

            CALL RESTORE            ;TRACK 0
            ANI MREST               ; ALLES OK ?
            CPI %00000100           ;
            CNZ CODE1               ;NEIN -> CODE1

;*************************************************************************
;DAS DIRECTORY BELEGT AUF DER SPUR DIE SEKTOREN 1 - 5
;SCHREIBE DEN INHALT DES SEKTOR-PUFFERS (ALLES 00H) IN DIE 5 SEKTOREN
;(OOH —> DIRECTORY LEER)
;*************************************************************************

            MVI A,1                 ;SEKTOR-NUMMER
INITD: 
            OUT FDCSEC              ; AN FDC
            MOV B,A                 ;RETTE SEKTOR-NUMMER
            MVI D,MAXTRY            ;MAXIMALE ANZAHL DER VERSUCHE
INITD1:
            CALL WVSEC              ;SCHREIBE UND PRUEFE SEKTOR
            JZ INITD0               ;KEIN FEHLER —> INITD0
            DCR D                   ;NOCH WEITERE VERSUCHE ERLAUBT ? 
            JNZ INITD1              ;JA —> INITD1
            JMP ERROR               ;SPRINGE WENN MEHR ALS "MAXTRY"
INITD0:
            MOV A,B                 ;SEKTOR-NUMMER NACH A
            INR A                   ;NAECHSTER SEKTOR
            CPI 6                   ;BEREITS 5 SEKTOREN GESCHRIEBEN
            JNZ INITD               ;NEIN —> INITD

;*************************************************************************
;FERTIG            
;*************************************************************************

            DI                      ;DISABLE INTERRUPT
            CALL DESEL              ;DESELECT LAUFWERK
            CALL PTXTCR         ;TEXT AUSGEBEN
            .byte LF,"*** DISKETTE FORMATIERT UND GEPRUEFT",LF,CR
            .byte "*** VERZEICHNIS ANGELEGT",LF,CR,00
;            JMP FORM1              ; ??
                                    ; [P01#01]
            JMP ERROR2              ; Ruecksprung ueber ERROR2 

;*************************************************************************
;
;DOS-BEFEHL LOAD
;
;*************************************************************************
;HIER, WENN "L" LOAD EINGEGEBEN WURDE
;

;TRITT EIN FEHLER AUF, SO ARBEITET DAS BFZ-MINI-DOS DIE ROUTINE "ERROR" AB.
;DIESE ENDET MIT EINEM SPRUNG ZU DER ADRESSEv DIE IM RAM UNTER "ERRRET" STEHT,
;DAS PROGRAMM TRAEGT HIER "LER" (LOAD-ERROR) EIN
;*************************************************************************

DSKLOAD:
            LXI H,LER               ;RETURN VON ERROR
            SHLD ERRRET             ;ABSPEICHERN

;*************************************************************************
;VON WELCHEM LAUFWERK SOLL GELADEN WERDEN?
;*************************************************************************

LER:
            CALL LAUFW              ;LESE LAUFWERK-NAME
            CALL CRLF               ;PRINT CR,LF

;*************************************************************************
;BEI FEHLERN IM WEITEREN PROGRAMMABLAUF RUECKKEHR NACH "MENUE"
;*************************************************************************

            LXI H,MENUE             ;RETURN-ADR
            SHLD ERRRET             ;ABSPEICHERN

;*************************************************************************
;DAS FILE IN DEM DIRECTORY GESUCHT WIRD, SOLL DAS DIRECTORY
;NICHT ANGEZEIGT WERDEN
;*************************************************************************

            XRA A                   ;DIRECTORY NICHT ANZEIGEN           
            STA DSPLD               ;

;*************************************************************************
;LESE FILE-NAME UND SUCHE IHN IN DEM DIRECTORY
;*************************************************************************

            CALL GETNAM             ;LESE FILE-NAME
            CALL SEINTR             ;SUCHE EINTRAG

;*************************************************************************
;WENN FILE VORHANDEN, MUSS MINDESTENS EIN EINTRAG IM DIRECTORY
;VORHANDEN SEIN
;("ZAEHLV" =ANZAHL DER VORHANDENEN EINNTRAEGE FUER DAS GESUCHTE FILE)
;*************************************************************************


            LDA ZAEHLV              ;FILE VORHANDEN ?
            ORA A                   ;
            CZ CODE11               ;NEIN —> CODE 11

;*************************************************************************
;HIER, WENN FILE VORHANDEN
;*************************************************************************

            LHLD TVORH              ;LESE POSITION DES 1. EINTRAGS
            MOV A,H                 ;SEKTOR-NUMMER NACH A
            OUT FDCSEC              ;SEKTOR-NUMMER AN FDC
            MOV C,L                 ;EINTRAGS-NUMMER NACH C
            CALL RRS                ;LESE SEKTOR (MAXTRY VERSUCHE)
            MOV A,C                 ;EINTRAGS-NUMMER NACH A
            CALL ANFEIN             ;HL ALS ZEIGER AUF EINTRAGS-ANFANG

;*************************************************************************
;STIMMEN FILE-TYP (MAT,SPS,BAS,) UND AKTUELLER "EFROM" -CODE UEBEREIN ?
;
;DOS-AUFRUF VON   ZUM LADEN ERFORDERLICHER FILE-TYP   "EFROM"-CODE
;
; MAT85           MAT ODER SPS ODER BAS               1
; SPS             SPS                                 2
; BASIC           BAS                                 3
; UNBEKANNT       ???                                 7
;
;*************************************************************************

LKENN:
            MOV A,M                 ;LESE KENN-BYTE
            ANI %01111111           ;LOESCHE BIT 7
            MOV E,A                 ;KENNUNG NACH E
            LDA EFROM               ;LESE ENTERED-FROM-CODE
            CPI 01                  ;DOS OON MAT AUFGERUFEN ?
            JZ KENNOK               ;JA —> KENNUNG OK
            CMP E                   ;VERGLEICHE MIT KENNUNG
            CNZ CODE12              ;<> —> FALSCHER FILE-TYP

;*************************************************************************
;HIER, WENN KENNUNG OK
;LESE START-ADRESSE UND LAENGE AUS DEM DIRECTORY-EINTRAG
;*************************************************************************

KENNOK:
            LXI D,$000D             ;OFFSET ZUR START-ADR (IM DIR-EINTRAG)
            DAD D                   ;ADDIERE OFFSET —> ZEIGER AUF START-ADR
            MOV E,M                 ;LESE START-ADR
            INX H                   ;
            MOV D,M                 ;
            XCHG                    ;
            SHLD STARTA             ;RETTE START-ADR
            XCHG                    ;LESE LAENGE
            INX H                   ;
            MOV E,M                 ;
            INX H                   ;
            MOV D,M                 ;
            XCHG                    ;
            SHLD LAENGE             ;RETTE LAENGE

;*************************************************************************
;STIMMT DIE ANZAHL DER DIRECTORY-EINTRAEGE MIT DER ANZAHL UEBEREIN, DIE SICH
;AUS DER FILE-LAENGE BERECHNEN LAESST ?
;*************************************************************************

            CALL ANZAHL             ;BERECHNE ANZAHL DER BENOETIGTEN EINTRAEGE
            LDA ZAEHLV              ;LADE ANZAHL DER VORHANDENEN EINTRAEGE
            CMP B                   ;VERGLEICHE MIT ANZAHL DER BENOETIGTEN EINTRAEGE
            CNZ CODE13              ;NICHT GLEICH —> DIRECTORY-FEHLER

;*************************************************************************
;DOS-AUFRUF VON MAT85               FORDERE START-ADRESSE AN
;DOS-AUFRUF VON SPS ODER BASIC      LOESCHE ALTES SPS/BASIC-PROGRAMM IM SPEICHER
;*************************************************************************
        
            CALL XLAD1              ;MAT: FORDERE START-ADR AN
                                    ;SPS,BASIC: LOESCHE ALES PROGRAMM

;*************************************************************************
;WIEVIELE EINTRAEGE MUESSEN EINGELESEN WERDEN ? DRUCKE DIE ENTSPRECHENDE
;ANZAHL VON STRICHEN
;*************************************************************************
                                  

            LDA ZAEHLV              ;ANZAHL DER ZU LESENDEN EINTRAEGE
            MOV D,A                 ;ANZAHL NACH D
            CALL PLINE              ;PRINT D-MAL "-"

;*************************************************************************
;VORBEREITUNG:
;SPEICHER VORBELEGEN
;BERECHNUNG DER STOP-ADRESSE
;RAM-VEKTOREN AENDERN
;*************************************************************************


            LHLD STARTA             ;START-ADRESSE
            SHLD TEINT              ;ZEIGER FUER MOVE-ROUTINE
            XCHG                    ;START-ADR NACH DE
            LHLD LAENGE             ;LANGE NACH HL
            DAD D                   ;START-ADR PLUS LAENGE
            DCX H                   ;HL = STOP-ADRESSE
            SHLD STOPA              ;RETTE STOP-ADRESSES

            LXI H,TVORH             ;INIT ZEIGER AUF "TVORH"
            SHLD PTVORH             ;
            LXI H,PTVORH            ;ZEIGER AUF TABELLEN-POINTER
            SHLD ZWSP4              ;
            MVI A,JUMP              ;JUMP-OPCODE
            STA XGP1                ;EINSETZEN
            STA XGP2
            STA XGP3
            LXI H,RRS               ;ADRESSEN EINSETZEN
            SHLD XGP1+1             ;
            LXI H,MOVE              ;
            SHLD XGP2+1             ;
            LXI H,PPLUS             ;
            SHLD XGP3+1             ;

;*************************************************************************
;PRINT <CR> (CURSOR AUF DEN ANFANG DER "--------"-ZEILE)
;*************************************************************************
           
            CALL PTXT               ;TEXT AUSGEBEN
            .byte CR,00             ;CR

;*************************************************************************
;LESE FILE EIN
;*************************************************************************

            CALL GETPUT             ;LESE FILE

;*************************************************************************
;DOS-AUFRUF VON SPS BZW. BASIC: SETZE START-/STOP-POINTER
;DOS-AUFRUF MAT85: SETZE GO-ADRESSE
;
;*************************************************************************
            CALL XLAD2              ;SPS, BASIC: SETZE START-/STOP-POINTER
                                    ;MAT85: SETZE GO-ADRESSE

;*************************************************************************
;VOLLZUGSMELDUNG
;*************************************************************************
            CALL PSTAR              ;TEXT AUSGEBEN
            .byte "FILE GELADEN",00

;*************************************************************************
;ROUTINE BEENDEN
;DIE ROUTINE WIRD DURCH EINE SPRUNG NACH "ERET" BEENDET, OBWOHL KEIN FEHLER
;AUFGETRETEN IST. DURCH DIE VERWENDUNG EINIGER BEFEHLE DER "ERROR" — ROUTINE 
;WIRD SPEICHERPLATZ GESPART
;*************************************************************************

            JMP ERET                ;

;*************************************************************************
;
;DOS-BEFEHL SAVE
;
;*************************************************************************
;HIER, WENN "S" SAVE EINGEGEBEN WURDE
;

;DOS-AUFRUF VON SPS ODER BASIC:     IST DER PROGRAMM-SPEICHER LEER (FEHLER) ? 
;DOS-AUFRUF VON MAT85 :             -----------------------------------------
;*************************************************************************

DSKSAVE:
            CALL XSAV1              ;BAS, SPS:: FEHLER , WENN PGM-SPEICHER LEER

;*************************************************************************
;TRITT BEI DER PROGRAMMAUSFUEHRUNG EIN FEHLER AUF, SO VERZWEIGT DAS PROGRAMM 
;ZUR "ERROR"-ROUTINE. DIESE ENDET MIT EINEM SPRUNG ZU DER ADRESSE, DIE IM 
;RAM UNTER "ERRRET" GESPEICHERT IST. DAS PROGRAMM TRAEGT HIER "SAVER" EIN
;*************************************************************************

            LXI H,SAVER             ;RETURN VON ERROR 
            SHLD ERRRET             ;ABSPEICHERN

;*************************************************************************
;MIT WELCHEM LAUFWERK SOLL GESPEICHERT WERDEN ?

SAVER:
            CALL LAUFW              ;LESE LAUFWERK-NAME 
            CALL CRLF               ;PRINT CR,LF

;*************************************************************************
;BEI WEITEREN FEHLERN IM PROGRAMMABLAUF RUECKKEHR NACH "MENUE"

            LXI H,MENUE             ;RETURN-ADR
            SHLD ERRRET             ;ABSPEICHERN

;*************************************************************************
;DOS-AUFRUF VON MAT85:              HOLE START/STOP-ADR
;DOS-AUFRUF VON SPS ODER BASIC:     ---------------
;*************************************************************************

            CALL XSTSP              ; Hole Start/Stop-Adresse Sprung ueber Vektor
                                    ; (MAT85+) in MAT85
                                    ;MAT: HOLE START/STOP-ADRESSE
                                    ;BAS, SPS: NOP
;*************************************************************************
;BERECHNE LAENGE                                    
;*************************************************************************
            LHLD STARTA             ;HL=START-ADR
            XCHG                    ;DE=START-ADR
            LHLD STOPA              ;HL=STOP-ADR
            CALL SUB2               ; BERECHNE LAENGE
            INX H                   ; 
            MOV A,H                 ; HL=0000 ?
            ORA L                   ; 
            CZ CODE10               ;JA —> CODE10
            SHLD LAENGE             ;RETTE LAENGE

;*************************************************************************
;BEIM FOLGENDEN AUFRUF VON "SEINTR" SOLL DAS DIRECTORY NICHT ANGEZEIGT WERDEN
;*************************************************************************

            XRA A                   ;DIRECTORY NICHT ANZEIGEN
            STA DSPLD               ;

;*************************************************************************
;UNTER WELCHEM NAMEN SOLL DER FILE GESPEICHERT WERDEN ?
;*************************************************************************

            CALL GETNAM             ;LESE FILE-NAME

;*************************************************************************
;PRUEFE OB FILE BEREITS VORHANDEN UND OB DER FREIE SPEICHERPLATZ AUF DER 
;DISKETTE ZUM SPEICHERN AUSREICHT
;*************************************************************************

            CALL SEINTR             ;SUCHE EINTRAG

;*************************************************************************
;WIEVIELE EINTRAEGE WERDEN ZUM ABSPEICHERN BENOETIGT ?
;*************************************************************************

            CALL ANZAHL             ;BERECHNE ANZ. DER BENOET. EINTRAEGE
            PUSH B                  ;RETTE ANZAHL DER BENOETIGTEN EINTRAEGE

;*************************************************************************
;GIBT ES AUF DER DISKETTE NUTZBARE EINTRAEGE ?
;(FREIE EINTRAEGE BZW. EINTRAEGE, DIE EINEM FILE GLEICHEN NAMENS 
;ZUGEORDNET SIND)
;*************************************************************************

            LDA ZAEHL               ;NUTZBARE EINTRAEGE ? 
            ORA A                   ;
            CZ CODE8                ;NEIN —> DISK VOLL

;*************************************************************************
;HIER, WENN MINDESTENS EIN NUTZBARER EINTRAG.
;DIESER EINTRAG IST:    - ENTWEDER FREI
;                       - ODER ER IST EINEM FILE MIT GLEICHEM NAMEN ZUGEORDNET
;*************************************************************************

            CMP B                   ;VERGLEICHE MIT DEN BENOETIGTEN PLATZ
            CC CODE15               ;—> SPEICHERPLATZ REICHT NICHT AUS

;*************************************************************************
;HIER, WENN SPEICHERPLATZ AUSREICHT 
;DER NUTZBARE SPEICHERPLATZ IST:    - ENTWEDER FREI
;                                   - ODER ER IST EINEM FILE MIT GLEICHEM
;                                     NAMEN ZUGEORDNET
;IST DAS FILE BEREITS VORHANDEN ?
;*************************************************************************

            LDA ZAEHLV              ;IST DAS FILE BEREITS VORHANDEN ?
            ORA A                   ;
            JZ NEW                  ;NEIN —> NEW

;*************************************************************************
;HIER, UIENN FILE BEREITS VORHANDEN
;GEBE WRNUNG AUS
;*************************************************************************

SAVER2:
            CALL PTXTCR             ;PRINT TEXT
            .byte LF,07
            .byte "*** FILE BEREITS VORHANDEN !",CR,LF
            .byte "*** ALTES FILE UEBERSCHREIBEN ?",CR,LF
            .byte "*** J = JA, N = NEIN",00
            CALL DESEL              ;DESELECT LAUFWERK

;*************************************************************************
;SOLL DER VORHANDENE FILE UEBERSOHRIEBEN WERDEN ?
;*************************************************************************

            CALL GETCHR             ;JA/NEIN-ANTWORT LESEN
            CPI "N"                 ;NEIN ?
            JZ ERET                 ;N -> ERET
            CPI "J"                 ;JA ?
            JNZ SAVER2              ;WEDER NOCH J/N -> SAVE2

;*************************************************************************
;HIER, WENN DER VORHANDENE FILE UEBERSOHRIEBEN WERDEN SOLL
;*************************************************************************
            CALL CRLF               ;PRINT CR,LF
            LDA ZAEHLV              ;ANZAHL DER LOESCHENDNEN EINTRAEGE
            CALL DELETE             ;LOESCHE ALTE EINTRAEGE

;*************************************************************************
;ABSPEICHERUNG DES FILES

;IST DIE DISKETTE SCHREIBGESCHUETZT
;*************************************************************************

NEW:
            CALL WPTST              ;WRITE-PROTECT-TEST
            CNZ CODE4               ;SCHREIBGESCHUETZT —> CODE4

;*************************************************************************
;HIER, WENN DIE DISKETTE NICHT SCHREIBGESCHUETZT IST
;*************************************************************************

            POP PSW                 ;ANZAHL DER BENOETIGTEN EINTRAEGE
            STA ZWSP2               ;ANZAHL NACH ZWSP2

            MOV D,A                 ;ANZAHL NACH D
            CALL PLINE              ;DRUCKE D-MAL "-"

            LXI H,TEINT             ;INIT ZEIGER AUF
            SHLD PTEINT             ;TEINTS-TABELLE
            LHLD STARTA             ;START—ADR FUER FILE
            SHLD ZWSP1              ;START-ADR FUER AKTUELLEN EINTRAG
            CALL SELECT             ;RE-SELECT LAUFWERK
            CALL DREADY             ;LAUFWERK BEREIT ?
            CC CODE3                ;NEIN -> CODE3

;*************************************************************************
;PRINT <CR>. (CURSOR AN DEN ANFANG DER "-------"-ZEILE)
;*************************************************************************

            MVI A,CR                ;WAGENRUECKLAUF
            CALL WCHAR              ;
            LXI H,PTEINT            ;ZEIGER INITIALISIEREN
            SHLD ZWSP4              ;
            MVI A,JUMP              ;LADE JMP-OPCODE
            STA XGP1                ;SETZE OP-CODE EIN
            STA XGP3
            MVI A,RETURN            ;LADE RETURN-OPCODE
            STA XGP2                ;SETZE OP-CODE EIN
            LXI H,RWVSEC            ;SETZE ADRESSE EIN
            SHLD XGP1+1
            LXI H,PPLUS
            SHLD XGP3+1

;*************************************************************************
;EIGENTLICHER SAVE-VORGANG
;*************************************************************************

            CALL GETPUT             ;SCHREIBE FILE AUF DISKETTE

;*************************************************************************
;EINTRAEGE FUER FILE IM DIRECTORY VERMERKEN
;*************************************************************************

SAVE0:
            LXI H,TEINT             ;INIT ZEIGER AUF "TEINT"
            SHLD ZWSP1              ;
            MVI A,JUMP              ;JMP OP-CODE
            STA XDIR                ;EINSETZEN
            LXI H,VEINTR            ;ADRESSE EINSETZEN
            SHLD XDIR+1             ;
            CALL MDIR               ;VERMERKE EINTRAEGE IN DIRECTORY

;*************************************************************************
;FERTIG
;*************************************************************************

DEB0:
            CALL CRLF               ;PRINT CR,LF
            CALL PSTAR              ;PRINT TEXT
            .byte "FILE ABGESPEICHERT",00

;*************************************************************************
;ROUTINE BEENDEN
;DIE ROUTINE WIRD DURCH EINEN SPRUNG NACH "ERET" BEENDET, OBWOHL KEIN
;FEHLER AUFGETRETEN IST. DURCH DIE VERWENDUNG EINIGER BEFEHLE DER
;"ERROR" - ROUTINE WIRD SPEICHERPLATZ GESPART
;*************************************************************************

            JMP ERET                ;

;******************************************************************
;*                            CODE-TEIL                           *
;*          WIRD BEI FEHLERN LUE EIN UNTERPROGRAMM AUFGERUFEN -   * 
;*          HIER WIRD DEM C-REGISTER EIN CODE ZUGEWIESEN, DER     * 
;*          DIE ART DES FEHLERS ANGIBT..                          * 
;******************************************************************

;LADE C-REGISTER MIT FEHLER-CODE. EINSPRUNG JE NACH FEHLER.
;DURCH DIE ANWEISUNG "DB 21h" SIEHT DER PROZESSOR NACH DER ERSTEN
;"MVI C, .."-ANWEISUNG NUR "LXI H,..."-ANWEISUNGEN (21h = LXI H,..)
;DER WERT DES C-REGISTERS WIRD DADURCH NICHT VERAENDERT.
;VORTEIL: BYTE-ERSPARNIS, DA SONST JEDEM "MVI C,.. " EIN SPRUNG ZUR 
;"XERR"-ROUTINE FOLGEN MUESSTE.
;
;BEISPIEL:  A)    0E    EINSPRUNG BEI A)  DIE CPU "SIEHT" DAS BEFEHLSBYTE
;                 00                      OE "MVI C,.." UND DEN OPERANDEN 00.
;                 21                      DIES ERGIBT "MVI C,00". DAS FOLGENDE
;           B)    0E                      BYTE (21) NIMMT DIE CPU ALS BEFEHLS-
;                 01                      BYTE FUER "LXI H,...". DIE FOLGENDEN
;                 21                      BYTES (0E UND 01) ERGEBEN "LXI H,010E"
;                 '                       FUER DIE CPU FOLGT NUN WIEDER EIN BE-
;                 '                       FEHLSBYTE (21). DAS BEDEUTET, ERNEUT
;                 '                       DER BEFEHL "LXI H,..." USW.
;                 '     EINSPRUNG BEI B)  DIE CPU SIEHT DAS BEFHLSBYTE 0E
;                 '                       "MVI C,..". WEITERER ABLAUF WIE OBEN.
;WERTE BEI "JMP XERR":  C = FEHLER-CODE
;                       H = MAXIMAL MOEGLICHER FEHLER—CODE
;                       L = 0Eh (CODE FUER "MVI C,...")
;
;*************************************************************************

;CODE
CODE0:
            MVI C,0                 ;FALSCHE EINGABE
            .byte $21
CODE1:
            MVI C,1                 ;RUECKSTELL-FEHLER
            .byte $21
CODE2:
            MVI C,2                 ;SCHREIB-FEHLER
            .byte $21
CODE3:
            MVI C,3                 ;LAUFWERK NICHT BEREIT
            .byte $21
CODE4:
            MVI C,4                 ;DISKETTE SCHREIBGESCHUETZT
            .byte $21
CODE5:
            MVI C,5                 ;PRUEF—FEHLER
            .byte $21
CODE6:
            MVI C,6                 ;SUCH—FEHLER
            .byte $21
CODE7:
            MVI C,7                 ;LESE-FEHLER
            .byte $21
CODE8:
            MVI C,8                 ;DISKETTE VOLL
            .byte $21
CODE9:
            MVI C,9                 ;UNERLAUBTER NAME
            .byte $21
CODE10:
            MVI C,10                ;FILE > 65535 (DEZ.. > BYTES 
            .byte $21
CODE11:
            MVI C,11                ;FILE NICHT IM VERZEICHNIS
            .byte $21
CODE12:
            MVI C,12                ;FALSCHER FILE-TYP
            .byte $21
CODE13:
            MVI C,13                ;DIRECTORY-FEHLER
            .byte $21
CODE14:
            MVI C,14                ;SPEICHER-FEHLER
            .byte $21
CODE15:
            MVI C,15                ;SPEICHERPLATZ AUF DER DISKETTE ZU KLEIN
            .byte $21
CODE16:
            MVI C,16                ;PROGRAMM-SPEICHER LEER

            JMP XERR                ;SPRUNG LIEBER RAM—VEKTOR 
                                    ;(WIRD VOM BFZ-MINI-DOS ALS 
                                    ;"JMP ERROR" INITIALISIERT)

;*************************************************************************
;PROGRAMM-SEGMENT "ERROR"
;WIRD BEI DOS—FEHLERN VOM CODE-TEIL AUFGERUFEN
;DESELECTIERT LAUFWERK UND GIBT FEHLERMELDUNG AUS
;
;WERTE BEIM AUFRUF: C = FEHLER-CODE
;
;RETTE FEHLER-STELLE IM RAM UNTER "ERRP". WIRD VOM DOS NICHT GENUTZT«.
;NUTZUNG DES "ERRP"—WERTES DURCH ANDERE PROGRAMME ABER MOEGLICH
;*************************************************************************

ERROR:
            DI                      ;DISABLE INTERRUPT
            POP H                   ;RETURN-ADR (FEHLER-STELLE)
            SHLD ERRP               ;RETTE ADRESSE

;*************************************************************************
;GEBE "*** FEHLER ***" AUS
;*************************************************************************

            CALL PTXTCR             ;TEXT AUSGEBEN
            .byte LF,BELL,"*** FEHLER: ",00

;*************************************************************************
;PRUEFE OB FEHLER-CODE OK
;NEIN —> LADE C-REGISTER MIT SPIELLEN CODE FUER "UNGUELTIGER FEHLERCODE"
;*************************************************************************

            LHLD PEVT               ;LADE POINTER AUF ERROR-VEKTOR-TABELLE
            MOV A,M                 ;LESE MAXIMALEN FEHLER-CODE
            CMP C                   ;VERGLEICHE MIT TATSAECHLICHEM CODE
            JNC ECOK                ;SPRINGE, WENN ERROR-CODE OK
            MOV C,A                 ;LADE CODE FUER:
            INR C                   ;"UNGUELTIGER FEHLER-CODE"

;*************************************************************************
;LADE ZEIGER AUF FEHLERMELDUNG
;*************************************************************************

ECOK:
            INX H                   ;ZEIGER AUF 1. VEKTOR
            MVI B,0                 ;HIGH (BC) = 0
            DAD B                   ;STELLE ZEIGER AUF
            DAD B                   ;RICHTIGEN EINTRAG
            MOV C,M                 ;EINTRAG NACH BC
            INX H                   ;
            MOV B,M                 ;

;*************************************************************************
;GEBE FEHLERMELDUNG AUS
;*************************************************************************

ERROR1:
            LDAX B                  ;TEXT-ZEICHEN NACH A
            ORA A                   ;TEXT ENDE ?
            JZ ERROR2               ;JA — > ERROR2
            CALL WCHAR              ;PRINT ZEICHEN
            INX B                   ;STELLE ZEIGER WEITER
            JMP ERROR1              ;NAECHSTES ZEICHEN

;*************************************************************************
;DESELEKT LAUFWERK. WARTE AUF <SPACE> (FEHLER—QUITTIERUNG)
;*************************************************************************

ERROR2:
            CALL DESEL              ;DESELECT LAUFWERK
            CALL PTXTCR             ;PRINT TEXT
            .byte "==> SPACE",00    
            CALL WAITSP             ;WARTE AUF SPACE

;*************************************************************************
;DESELEKT LAUFWERK. RE-INITIALISIERE STACKPOINTER. RETURN (ERRRET)
;*************************************************************************

ERET:
            CALL DESEL              ;DESELECT LAUFWERK
            LXI SP,USRSTK           ;RE-INIT STACKPOINTER
            LHLD ERRRET             ;"RETURN"-ADRESSE (WURDE VOM PROGRAMM
            PCHL                    ;BEI "ERRRET" EINGESETZT)

;*************************************************************************


;************************************************************************
;*                                                                      *
;*                U N T E R P R O G R A M M E                           *
;*                                                                      *
;************************************************************************

;UNTERPROGRAMM "RESTORE"
;GIBT DAS KOMMANDO "RESTORE" (FAHRE KOPF NACH TRACK 0) AN DEN FDC. 
;SACKGASSEN-UNTERPROGRAMM. WIRD DURCH DEN INTERRUPT VERLASSEN, DEN 
;DER FDC NACH DER AUSFUEHRUNG DES KOMMANDOS ERZEUGT.
;
;WERTE BEIM AUFRUF:     ----
;WERTE NACH RETURN:     SIEHE INTERRUPT-SERVICE-ROUTINE ISR
;*************************************************************************

RESTORE:
            MVI A,CREST             ;RESTORE
            OUT FDCCMD              ;KOMMANDO AN FDC
            HLT                     ;WARTE AUF INTERRUPT

;*************************************************************************
;UNTERPROGRAMM "STEP IN" 
;GIBT AN DEN FDC DEN BEFEHL "STEP IN" AUS.
;SACKGASSEN-UNTERPROGRAMM. WIRD PER INTERRUPT VERLASSEN

;WERTE BEIM AUFRUF:     ---
;WERTE NACH INTERRUPT:  SIEHE IINTERRUPT-SERVICE-ROUTINE ISR
;*************************************************************************

STEPIN:
            MVI A,CSTPIN            ;STEP IN
            OUT FDCCMD              ;KOMMANDO AN DEN FCD
            HLT                     ;WARTE AUF INTERRUPT

;*************************************************************************
;UNTERPROGRAMM "SEEK"
;GIBT AN DEN FDC DEN BEFEHL "SEEK" AUS.
;SACKGASSEN-UNTERPROGRAMM. WIRD PER INTERRUPT VERLASSEN

;WERTE BEIM AUFRUF:     SOLL-TRACK IM FDC-DATENREGISTER 
;WERTE NACH INTERRUPT:  SIEHE INTERRUPT-SERVICE-ROUTINE ISR
;*************************************************************************

SEEK:
            MVI A,CSEEK             ;SEEK
            OUT FDCCMD              ;KOMMANDO AN DEN FDC
            HLT                     ;WARTE AUF INTERRUPT

;*************************************************************************
;UNTERPROGRAMM "USED"
;SCHREIBT EINEN SEKTOR AUF DISKETTE. NACH DER AUSGABE DES 
;"WRITE SECTOR"-KOMMANDOS AN DEN FDC HAELT SICH DIE CPU DURCH 
;"OUT STOP" AN (READY GEHT AUF L-PEGEL). WENN DER FDC DAS ERSTE 
;DATEN-BYTE ANFORDERT, GIBT ER AM ANSCHLUSS DRQ EIN SIGNAL AUS, DAS 
;DIE CPU WIEDER STARTET (READY GEHT AUF H). DIE CPU GIBT DAS 
;DATEN-BYTE AN DEN FDC UND HAELT SICH ERNEUT AN.

;DURCH DIE STEUERUNG UEBER DAS READY-SIGNAL ENTFAELLT DAS ABFRAGEN 
;DES FDC—STATUS. DIE CPU KANN SCHNELLER AUF EINE DATEN-ANFORDERUNG 
;(DRQ,DATA REQUEST) DES FDC REAGIEREN. SO IST TROTZ DER RELATIV 
;NIEDRIGEN CPU-TAKTFREQUENZ VON 2 MHZ DOUBLE-DENSITY-BETRIEB MOEGLICH.

;SACKGASSEN-UNTERPROGRAMM. WIRD PER INTERRUPT VERLASSEN

;WERTE BEI AUFRUF HL—ZEIGT AUF DAS ERSTE BYTE DER ZU SCHREIBENDEN DATEN 
;                 (TRACK BEREITS ANGEFAHRENy SEKTOR-NUMMER IM SEKTOR-REG.)

;WERTE NACH INTERRUPT:  HL=VERAENDERT
;                       (SIEHE AUCH: INTERRUPT-SERVICE-ROUTINE ISR)
;
;*************************************************************************

WSEC:
            MVI A,CWSEC             ;WRITE SECTOR
            OUT FDCCMD              ;KOMMANDO AN DEN FDC
WSEC0:
            OUT FDCSTOP             ;WARTE AUF DRQ
            MOV A,M                 ;ZEICHEN IN AKKU
            OUT FDCDAT              ;ZEICHEN AN DN FDC
            INX H                   ;ZEIGER WEITERSTELLEN
            JMP WSEC0               ;NAECHSTES ZEICHEN

;*************************************************************************
;UNTERPROGRAMM "RSEC"
;LIEST EINEN SEKTOR VON DISKETTE. NACH DER AUSGABE DES "READ SECTOR"- 
;KOMMANDOS AN DEN FDC HAELT SICH DIE CPU DURCH "OUT STOP" AN (READY 
;GEHT AUF L-PEGEL). WENN DER FDC DAS ERSTE DATEN-BYTE VON DER DISKETTE 
;GELESEN HAT, GIBT ER AM ANSCHLUSS DRQ EIN SIGNAL AUS, DAS DIE CPU WIEDER 
;STARTET (READY GEHT AUF H). DIE CPU LIEST DAS DATEN-BYTE AUS DEM FDC- 
;DATENREGISTER UND HAELT SICH ERNEUT AN.

;DURCH DIE STEUERUNG LIEBER DAS READY-SIGNAL ENTFALLET DAS ABFRAGEN 
;DES FDC—STATUS - DIE CPU KANN SCHNELLER AUF EINE DATEN-ANFORDERUNG 
;(DRQ., DATA REQUEST) DES FDC REAGIEREN.. SO IST TROTZ DER RELATIV 
;NIEDRIGEN CPU-TAKTFREQUENZ VON 2 MHZ DOUBLE-DENSITY-BETEIEB MOEGLICH-

;SACKGASSEN-UNTERPROGRAMM- WIRD PER INTERRUPT VERLASSEN

;WERTE BEI AUFRUF:      HL-ZEIGT AUF ANFANG DES SPEICHERBEREICHS, IN DEM DIE
;                       GELESENEN BYTES GESPEICHERT WERDEN SOLLEN.
;                       (TRACK BEREITS ANGEFAHREN, SEKTOR-NUMMER IM
;                       SEKTOR-REGISTER)
;
;WERTE NACH INTERRUPT   HL=VERAENDERT
;                       (SIEHE AUCH INTERRUPT-SERVICE-ROUTINE)
;
;*************************************************************************

RSEC:
            MVI A,CRSEC             ;READ SECTOR
            OUT FDCCMD              ;BEFEHL AN FDC
RSEC0:
            OUT FDCSTOP             ;WARTE AUF DRQ
            IN FDCDAT               ;ZEICHEN IN AKKU
            MOV M,A                 ;ZEICHEN IN BUFFER
            INX H                   ;ZEIGER WEITEESTELLEN
            JMP RSEC0               ;NAECHSTES ZEICHEN

;*************************************************************************
;UNTERPROGRAMM "WTRK"
;SCHREIBT EINEN TRACK AUF DIE DISKETTE. NACH DER AUSGABE DES 
;"WRITE TRACK"-KOMMANDOS AN DEN FDC, HAELT SICH DIE CPU DURCH 
;"OUT STOP" AN (READY GEHT AUF L-PEGEL). WENN DER FDC DAS ERSTE 
;DATEN-BYTE ANFORDERT, GIBT ER AM ANSCHLUSS DRQ EIN SIGNAL AUS, DAS 
;DIE CPU WIEDER STARTET (READY GEHT AUF H). DIE CPU GIBT DAS 
;DATEN-BYTE AN DEN FDC UND HAELT SICH ERNEUT AN.

;DURCH DIE STEUERUNG UEBER DAS READY-SIGNAL ENTFAELLT DAS ABFRAGEN 
;DES FDC-STATUS. DIE CPU KANN SCHNELLER AUF EINE DATEN-ANFORDERUNG 
;(DRQ, DATA REQUEST) DES FDC REAGIEREN. SO IST TROTZ DER RELATIV 
;NIEDRIGEN CPU-TAKTFREQUENZ VON 2 MHZ DOUBLE-DENSITY-BETRIEB MOEGLICH.

;DIES IST EIN SACKGASSEN-UNTERPRQGRAMM. WENN DER FDC DEN BEFEHL 
;WRITE TRACK" ABGEARBEITET HAT, ERZEUGT ER EIN INTERRUPT-SIGNAL

;DAS UNTERPROGRAMM WIRD DURCH DIESEN INTERRUPT VERLASSEN.

;WERTE BEIM AUFRUF:     TRACK BEREITS ANGEFAHREN
;WERTE NACH INTERRUPT:  HL=VERAENDERT
;                       (SIEHE AUCH INTERRUPT-SERVICE-ROUTINE ISR)
;*************************************************************************

WTRK:
            LXI H,FBUFFER           ;ZEIGER AUF TRACK BUFFER
            CALL SELECT             ;SELECT LAUFWERK
            MVI A,CWRTRK            ;WRITE TRACK
            OUT FDCCMD              ;
WARTE:
            OUT FDCSTOP             ;WARTE BIS DRQ
            MOV A,M                 ;LESE DATEN AUS BUFFER
            OUT FDCDAT              ;GEBE DATEN AN FDC
            INX H                   ;STELLE BUFFER-ZEIGER WEITER
            JMP WARTE               ;

;*************************************************************************
;UNTERPROGRAMM "WVSEC"

;SCHREIBT DEN INHALT DES SECTOR-BUFFERS (SECB) AUF DISKETTE UND 
;PRUEFT DEN GESCHRIEBENEN SEKTOR.
;BEIM AUFRUF MUESSEN TRACK- UND SEKTOR-NUMMER BEREITS AN DEN FDC 
;UEBERGEBEN WORDEN SEIN, DER KOPF MUSS SICH UEBER DER RICHTIGEN SPUR 
;BEFINDEN.

;KEIN FEHLER:     Z-FLAG = 1, C = 5
;     FEHLER:     Z-FLAG = 0, C = 5 (VERIFY-ERROR)
;                 Z-FLAG = 0, C = 2 (WRITE-ERROR)

;FEHLER:          Z-FLAG = 0, C 
;*************************************************************************

WVSEC:
            LXI H,SECB              ;ZEIGER AUF SECTOR-BUFFER 
WVSEC0:
            CALL SELECT             ;RE-SELECT DRIVE
            CALL WSEC               ;SCHREIBE SEKTOR
            MVI C,2                 ;CODE FUER "SCHREIB—FEHLER"
            ANI MWSEC               ;ALLES OK ?
            RNZ                     ;NEIN —> RETURN
            CALL VERIX              ;VERIFY SECTOR
            MVI C,5                 ;CODE FUER "PRUEF-FEHLER"
            RET

;*************************************************************************
;UNTERPROGRAMM "RWVSEC"

;SCHREIBT EINEN SEKTOR AUF DISKETTE UND PRUEFT DEN GESCHRIEBENEN SEKTOR» 
;BEI FEHLERN WIRD DER SCHREIBVORGANG "MAXTRY" MAL WIEDERHOLT.

;WERTE BEIM AUFRUF:     BEIM AUFRUF MUESSEN TRACK- UND SEKTOR-NUMMER BEREITS 
;                       AN DEN FDC UEBERGEBEN WORDEN SEIN. DER KOPF MUSS SICH 
;                       UEBER DER RICHTIGEN SPUR BEFINDEN.
;                       HL: SEKTOR—PUFFER-ZEIGER
;*************************************************************************

RWVSEC:
            MVI D,MAXTRY            ;MAX ANZAHL DER SCHREIB-VERSUCHE
            SHLD ZWSP3              ;RETTE ZEIGER
RWVS0:
            CALL SELECT             ;RE—SELECT DRIVE 
            LHLD ZWSP3              ;LESE ZEIGER
            CALL WVSEC0             ;SCHREIBE SEKTOR
            RZ                      ;RETURN, WENN OK
            DCR D                   ;WEITERE VERSUCHE ERLAUBT ?
            JNZ RWVS0               ;JA —> RWVSEC
            CALL CODE2              ;NEIN —> CODE2

;*************************************************************************
;UNTERPROGRAMM "SAVSEC"

;SCHREIBT DEN INHALT DES SEKTOR-PUFFERS (SECB) AUF DISKETTE UND PRUEFT
;DEN GESCHRIEBENEN SEKTOR.
;BEI FEHLERN WIRD DER SCHREIBVORGANG "MAXTRY" MAL WIEDERHOLT.
;WERTE BEIM AUFRUF:     BEIM AUFRUF MUESSEN TRACK- UND SEKTOR-NUMMER
;                       AN DEN FDC UEBERGEBEN WORDEN SEIN. DER KOPF
;                       UEBER DER RICHTIGEN SPUR BEFINDEN.
;*************************************************************************

SAVSEC:
            MVI D,MAXTRY            ;ANZAHL DER VERSUCHE
NTRY:
            CALL SELECT             ;RE-SELECT DRIVE
            CALL WVSEC              ;SPEICHERE SEKTOR AUF DISK
            RZ                      ;RETURN, WENN ALLES OK
            DCR D                   ;WEITERE VERSUCHE ERLAUBT ?
            JNZ NTRY                ;JA —> NTRY
            CALL CODE2              ;NEIN —> CODE2

;*************************************************************************
;UNTERPROGRAMM "RRS"

;LIEST EINEN SEKTOR IN DEN SEKTOR-PUFFER (SECB).
;BEI FEHLERN WIRD DER LESEVORGANG "MAXTRY" MAL WIEDERHOLT.

;WERTE BEIM AUFRUFS:    BEIM AUFRUF MUESSEN TRACK- UND SEKTOR-NUMMER BEREITS
;                       AN DEN FDC UEBERGEBEN WORDEN SEIN. DER KOPF MUSS SICH 
;                       UEBER DER RICHTIGEN SPUR BEFINDEN.
;*************************************************************************

RRS:
            MVI D,MAXTRY            ;MAXIMALE ANZAHL DER LESE-VERSUCHE
RRS0:
            CALL SELECT             ;RE-SELECT DRIVE
            LXI H,SECB              ;BUFFER-ADR
            CALL RSEC               ;LESE SEKTOR
            ANI MRSEC               ;ALLES OK ?
            RZ                      ;JA —> RETURN
            DCR D                   ;NOCH EIN VERSUCH ERLAUBT ?
            JNZ RRS0                ;JA —> RRSO
            CALL CODE7              ;NEIN —> LESE-FEHLER

;*************************************************************************
;UNTERPROGRAMM "VERIFY"

;PRUEFT DIE EINZELNEN SEKTOREN EINES TRACKS IN DER REIHENFOLGE 
;1,2,3,4,5,6,7,8. WENN EIN FEHLERHAFTER SEKTOR GEFUNDEN WIRD,
;WIRD DAS UNTERPROGRAMM VERLASSEN. DAS B-REGISTER ENTHAELT DANN 
;DIE NUMMER DES FEHLERHAFTEN SEKTORS UND DAS Z-FLAG IST NICHT 
;GESETZT.

;IST EIN SEKTOR FEHLERFREI, SO WERDEN DIE WEITEREN SEKTOREN IN DER 
;OBEN ANGEGEBENEN REIHENFOLGE GEPRUEFT.

;WERTE BEIM AUFRUF:     TRACK-NUMMER IM TRACK-REGISTER DES FDC
;                       KOPF MUSS BEREITS UEBER DER SPUR STEHEN

;WERTE NACH RETURN:     ALLE SEKTOREN FEHLERFREI ! FEHLERHAFTER SEKTOR
;                       -------------------------+--------------------
;                             A = 9              !    A = ?
;                             B = 8              !    B = NR DES FEHLERH. SECKTORS
;                       Z-FLAG = 1 (GESETZT)     ! Z-FLAG = 0 (NICHT GESETZT)
;*************************************************************************

VERIFY:
            CALL SELECT             ;RETRIGGER MOTOR-ON-OFF
            MVI A,1                 ;1. SEKTOR
VERI0:
            OUT FDCSEC              ;AN FDC SEKTOR-REGISTER
            MOV B,A                 ;SECTOR ZAEHLER NACH B
            CALL VERIX              ;VERIFY SECTOR
            RNZ                     ;RETURN, WENN FEHLER (Z=0)
            MOV A,B                 ;SEKTOR-ZAEHLER NACH A
            INR A                   ;+1
            CPI 9                   ;ALLE SEKTOREN GEPRUEFT ?
            RZ                      ;RETURN, WENN ALLE SEKTOREN OK (Z=1)
            JMP VERI0

;*************************************************************************
;UNTERPROGRAMM "VERIX"

;PRUEFT SEKTOR. TRACK- UND SEKTOR-NUMMER MUESSEN BEREITS AN FDC
;UEBERGEBEN WORDEN SEIN. DER TRACK MUSS ANGEFAHREN SEIN.

;KEIN FEHLER:     Z = 1
;     FEHLER:     Z = 0
;*************************************************************************

VERIX:
            CALL VERI1              ;READ SECTOR
            ANI MVERI               ;ALLES OK ? JA    -- Z = 1
                                    ;           NEIN  -- Z = 0
            RET

;*************************************************************************
;“UNTERPROGRAMM "VERI1"

;LIEST EINEN SEKTOR EIN OHNE IHN IM RAM ZU SPEICHERN. WIRD ZUM PRUEFEN
;DER SEKTOREN BENUTZT.. WICHTIG SIND DIE STATUS-FLAGS "RECORD NOT FOUND"
;UND "CRC-ERROR" DES FDC NACH DEM EINLESEN.
;SACKGASSEN-UNTERPROGRAMM. WIRD DURCH DEN INTERRUPT VERLASSEN, DEN DER FDC
;NACH DEM EINLESEN DES SEKTORS ERZEUGT.
;ZUM VERSTAENDNIS VON "OUT STOP": SIEHE WTRK (WRITE TRACK)

;WERTE BEIM AUFRUF:     SEKTOR- UND TRACK-NUMMER BEREITS AN FDC UEBERGEBEN
;                       TRACK ANGEFAHREN

;WERTE NACH RETURN:     SIEHE IINTERRUPT-SERVICE-ROUTINE ISR
;*************************************************************************

VERI1:
            MVI A,CRSEC             ;READ SECTOR
            OUT FDCCMD              ;GEBE KOMMANDO AN DEN FDC AUS
VERI2:
            OUT FDCSTOP             ;WARTE BIS DRQ
            IN FDCDAT               ;LESE DATE (RESET DRQ)
            JMP VERI2               ;LOOP

;*************************************************************************
;UNTERPROGRAMM "COMPSM"

;BERECHNET DIE SELECT-MASKE UND SPEICHERT SIE IN SELMSK AB

;WERTE BEIM AUFRUF:     A = 0 (LAUFWERK A) BZW. 1 (LAUFWERK B)
;WERTE NACH RETURN:     A = 1 (LAUFWERK A) BZW. 2 (LAUFWERK B)
;*************************************************************************

COMPSM:
            INR A                   ;ERGIBT SELECT-MASKE
            STA SELMSK              ;RETTE SELECT-MASKE
            RET

;*************************************************************************
;UNTERPROGRAMM "SELECT"

;WAEHLT LAUFWERK UND SEITE AUS. DAS MOTOR—ON—OFF AUF DER FDC-KARTE 
;WIRD DURCH "OUT PORT" FUER ETWA 3 SEC. GESETZT.

;WERTE BEIM AUFRUF:     (SEITE)     = SEITENNUMMER 0 ODER 1 (BINAER)
;                       (SELMSK)    = SELECT-MASKE - LAUFWERK A = 1
;                                                  - LAUFWERK B = 2

;WERTE NACH RETURN:     A = 00000001B, 01h (LAUFWERK A, SEITE 0, DOUBLE DENSITY)
;                       A = 00001001B, 09h (LAUFWERK A, SEITE 1, DOUBLE DENSITY)
;                       A = 00000010B, 02h (LAUFWERK B, SEITE 0, DOUBLE DENSITY)
;                       A = 00001010B, 0Ah (LAUFWERK B, SEITE 1, DOUBLE DENSITY)

; *)  S =   SEITE,      0 = SEITE 0
;                       1 = SEITE 1
; *)  D =   DENSITY,    0 = DOUBLE DENSITY
;                       1 = SINGLE DENSITY
;
; B = LAUFWERK B, (WENN 1)
; A = LAUFWERK A, (WENN 1)
;
;DER AUSGEGEBENE WERT WIRD IM RAM UNTER "LSEL" GESPEICHERT.
;*************************************************************************

SELECT:
            PUSH B                  ;RETTE B-REGISTER
            LDA SEITE               ;LESE SEITEN-NUMMER
            ADD A                   ;SCHIEBE BIT IN POSITION D1
            ADD A                   ;SCHIEBE BIT IN POSITION D2
            ADD A                   ;SCHIEBE BIT IN POSITION D3
            MOV B,A                 ;RETTE BIT IN B
            LDA SELMSK              ;LESE SELECT-MASKE
            ORA B                   ;SETZE SEITEN—BIT
            OUT FDCPORT             ;SELCT LAUFWERK
            STA LSEL                ;RETTE AUSGABEWERT
            POP B                   ;RESTORE B-REGISTER
            RET

;*************************************************************************
;UNTERPROGRAMM "DESEL "

;DESELEKTIERT LAUFWERK.
;IST DER LETZTE AUSGABEWERT (LSEL) = 00H ERFOLGT SOFORT EIN RETURN
;(IN DIESEM FALL IST KEIN LAUFWERK AKTIV). DIES VERHINDERT DAS ER-
;HEUTE ANLAUFEN DER MOTOREN.

;IST "LSEL" UNGLEICH 00H, SO WIRD 00H AUSGEGEBEN. DIESER WERT WIRD UNTER
;"LSEL" GESPEICHERT.

;NACH RETURN: A = 00
;*************************************************************************

DESEL:
            LDA LSEL                ;LETZTER AUSGABEWERT
            ORA A                   ;NULL ?
            RZ                      ;JA —> RETURN
            XRA A                   ;DESELECT LAUFWERK
            OUT FDCPORT             ;KOMMANDO AN FDC AUSGEBEN
            STA LSEL                ;RETTE AUSGABEWERT
            RET

;*************************************************************************
;UNTERPROGRAMM "DREADY"

;DAS UNTERPROGRAMM GIBT DEM MOTOR DES DISKETTENLAUFWERKS 1 SEKUNDE 
;ZEIT UM SEINE NENNDREHZAHL VON 300 UPM ZU ERREICHEN. DANACH WIRD DAS 
;NOT-READY-BIT IM FDC-STATUS-REGISTER ABGEFRAGT. DAS UNTERPROGRAMM 
;WIRD UEBER DEN "RET"-BEFEHL VERLASSEN. DAS CARRY-FLAG GIBT DEN 
;LAUFWERK-ZUSTAND AN:

;           NICHT BEREIT      CARRY = 1 (GESETZT)
;                 BEREIT      CARRY = 0 (NICHT GESETZT)

;WERTE BEIM AUFRUF:     ---
;
;WERTE NACH RETURN:     A  = UNBESTIMMT 
;                       HL = 0000
;                       CARRY-FLAG: SIEHE OBEN
;*************************************************************************

DREADY:
            LXI H,DRV_WAIT          ;$0800 minimum für Motor Anlaufzeit (1 sec)
            CALL DELAY              ;(MOTOR HOCHLAUF-ZEIT)
            IN FDCSTAT              ;LESE STATUS
            RLC                     ;READY
            RET                     ;RETURN (CARRY = 0 -> BEREIT)
                                    ;       (CARRY = 1 -> NICHT BEREIT)

;*************************************************************************
;UNTERPROGRAMM "DELAY"
;
;VERZOEGERUNGSSCHLEIFE. LAUFZEIT ETWA HL*1 MS (BEI 2 MHZ TAKT)

;WERTE BEIM AUFRUF:     HL = LAUFZEIT IN MILLISEKUNDEN
;*************************************************************************

DELAY:
            PUSH H                  ;RETTE ZAEHLER
            LXI H,DRV_DELAY         ; 83 bei 2MHz CPU-Takt
;            LXI H,164              ;164 bei 4MHz CPU-Takt
DELAY0:
            DCX H                   ;LAUFZEIT ETWA 1 MSEC
            MOV A,H                 ;BEI 2 MHz TAKT
            ORA L                   ;
            JNZ DELAY0              ;LOOP
            POP H                   ;RESTORE ZAEHLER
            DCX H                   ;VERMINDERE ZAEHLER UM EINS
            MOV A,H                 ;HL = 0000 ?
            ORA L                   ;
            JNZ DELAY               ;NEIN -> DELAY
            RET

;*************************************************************************
;UNTERPROGRAMM "GETPUT"

;SPEICHERT / LIEST FILES
;FUNKTION WIRD DURCH RAM-VEKTOREN FESTGELEGT. DAS DOS INITIALISIERT 
;DIE VEKTOREN WIE FOLGT:
;
;     VEKTOR      LOAD        SAVE
;     XGP1        CALL RRS    CALL RWVSEC
;     XGP2        CALL MOVE   RET
;     XGP3        CALL PPLUS  CALL PPLUS
;
;WERTE BEIM AUFRUF:     LAENGE      = FILE-LAENGE
;                       ZWSP4       = ZEIGER AUF TABELLE DER NUTZBAREN DIR-EINTR 
;                                     (SIEHE AUCH UNTERPROGRAMM "SEINTR")
;                       ZWSP1       = START-ADR (NUR FUER WRITE)
;                                     SEL.MSK = SELECT-MASKE DES AUSGEW. LAUFWERKS
;*************************************************************************

GETPUT:
            LHLD LAENGE             ;REST = LAENGE
            SHLD REST               ;
GETP0:
            LHLD ZWSP4              ;ZEIGER AUF TABELLEN--POINTER
            CALL GETPOS             ;LESE POSITION AUS TABELLE
            CALL POS                ;POSITIONIERE KOPF
            MVI B,0                 ;SEKTOR 1 MINUS EINS
GPNXT:
            LHLD ZWSP1              ;ANFANG DIESES TEILS (NUR FUER WRITE)
            INR B                   ;NAECHSTER SEKTOR
            MOV A,B                 ;SEKTOR-NUMMER AN FDC
            OUT FDCSEC              ;AN DEN FDC
            CALL XGP1               ;LOAD: LESE SEKTOR 
                                    ;SAVE: SCHREIBE SEKTOR
GPOK:
            SHLD ZWSP1              ;RETTE ZEIGER (NUR FUER WRITE)
            CALL XGP2               ;LOAD: MOVE SEKTOR-BUFFER-INHALT
                                    ;      ZUM ZIEL-SPEICHER
                                    ;SAVE: NOP
            LHLD REST               ;REST-LAENGE
            LXI D,512               ;SEKTOR-LAENGE
            CALL SUB2               ;REST-LAENGE MINUS SEKTOR-LAENGE
            JC GP0                  ;REST < 0000 —> GPO
            MOV A,L                 ;REST = 0000 ?
            ORA H                   ;
            JZ GP0                  ;REST = 000 -> GPO
            SHLD REST               ;RETTE NEUE REST-LAENGE
            MOV A,B                 ;AKTUELLE SEKTOR-NUMMER NACH A
            CPI 8                   ;SEKTOR-NUMMER = 8
            JNZ GPNXT               ;NEIN -> NAECHSTER SEKTOR,
                                    ;        GLEICHE SPUR
            CALL XGP3               ;LOAD, SAVE: PRINT "+"
            JMP GETP0               ;NAECHSTER EINTRAG
GP0:
            CALL XGP3               ;LOAD, SAVE: PRINT "+"
            RET

;*************************************************************************
;UNTERPROGRAMM "POSDIR"

;UEBERGIBT DEM FDC DIE DATEN ZUR KOPF-POSITIONIERUNG UEBER DER 
;DIRECTORY. IN "SEMSK" MUSS DIE SELECT-MASKE DES GEWUENSCHTEN LAUFWERKS 
;STEHEN. IST DAS LAUFWERK NACH 1 SEKUNDE NICHT BEREIT, VERZWEIGT DAS 
;PROGRAMM NACH "CODE3" (LAUFWERK NICHT BEREIT). SONST GEHT DAS PROGRAMM 
;OHNE RETURN IN DAS UNTERPROGRAMM "WPTST" UEBER. (SIEHE AUCH DORT)
;*************************************************************************

POSDIR:
            XRA A                   ;A = 0
            STA SEITE               ;SEITE 0
            CALL SELECT             ;SELECT LAUFWERK
            CALL DREADY             ;LAUFWERK BEREIT ?
            CC CODE3                ;NEIN -> CODE3

;*************************************************************************
;UNTERPROGRAMM "WPTST"

;DAS UNTERPROGRAMM STELLT DEN KOPF DES SELEKTIERTEN LAUFWERKS UEBER
;SPUR 0 UND PRUEFT, OB DIE DARIN ENTHALTENE DISKETTE SCHREIBGESCHUETZT IST.
;TRETEN BEIM RESTORE-BEFEHL FEHLER AUF, VERZWEIGT DAS PROGRAMM NACH "CODE1"
;
;WERTE NACH RETURN:     Z—FLAG = 0 (NICHT GESETZT): DISKETTE SCHREIBGESCHUETZT 
;                       Z—FLAG = 1 ( GESETZT )      DISKETTE NICHT SCHR.-GESCHUETZT
;*************************************************************************

WPTST:
            CALL INTINT             ;INTERRUPT-ROUTINE INITIALISIEREN
            CALL RESTORE            ;KOPF AUF SPUR NULL
            ANI %10011100           ;OK ?
            CPI %00000100           ;
            CNZ CODE1               ;NEIN -> CODE1
            MOV A,E                 ;RESTORE STATUS
            ANI %01000000           ;WRITE PROTECTED ?
            RET                     ;Z-FLAG = 0 -> JA 
                                    ;Z-FLAG = 1 -> NEIN

;*************************************************************************
;UNTERPROGRAMM "POS"

;DAS UNTERPROGRAMM POSITIONIERT DEN KOPF ENTSPRECHEND DEN WERTEN IM 
;B- UND C-REGISTER UEBER EINEN FILE.
;
;WERTE BEIM AUFRUF      B=NUMMER DES DIRECTORY-SEKTORS IN DEM DER FILE-
;                         EINTRAG STEHT
;                       C=RELATIVE NUMMER DES EINTRAGS INNERHALB DES
;                         DIR.-SEKTORS
;
;                       (B- UND C-WERTE: SIEHE AUCH UNTERPROG. "SEINTR")
;
;                       "SELMSK" MUSS DIE SELECT-MASKE DES AUSGEUAEHLTEN
;                       LAUFWERKS ENTHALTEN
;*************************************************************************

POS:
            MOV H,B                 ;SEKTOR-NUMMER NACH H
            MOV L,C                 ;EINTRAGS—NUMMER NACH L
            CALL CTS                ;BERECHNE TRACK UND SEITE
            CALL SELECT             ;SELEKTIERE LAUFWERK UND SEITE
            LDA SPUR                ;POSITIONIERE KOPF AUF SPUR
            OUT FDCDAT              ;
            CALL SEEK               ;
            ANI %10011000           ;SEEK ERROR ?
            CNZ CODE6               ;JA —> CODE6
            MOV A,E                 ;RESTORE STATUS
            RET

;*************************************************************************
;UNTERPROGRAMM "CTS" (COMPUTE TRACK AND SIDE)

;DIESES UNTERPROGRAMM ERMITTELT DIE SPUR (TRACK) UND DIE DISKETTENSEITE,
;AUF DER SICH EIN FILE (BZW. EIN 4K-BLOCK DAVON) BEFINDET.
;BEIM AUFRUF DIESES UNTERPROGRAMMS MUESSEN DIE REGISTER B UND C FOLGENDE 
;ANGABEN ENTHALTEN:

;B-REGISTER:      NUMMER DES DIRECTORY-SEKTORS, IN DEM DER EINTRAG ZU DEM FILE
;                 STEHT (1..5)
;C—REGISTER:      RELATIVE NUMMER DES EINTRAGS IM DIRECTORY-SEKTOR (1..16)
;
;DIE ERRECHNETEN WERTE FUER SPUR UND SEITE WERDEN UNTER "SPUR" BZW- "SEITE"
;IM RAM GESPEICHGERT.
;
;NACH RETURN SIND DIE INHALTE FOLGENDER REGISTER VERAENDERT:
; A = (SPUR)
; B = 00
;*************************************************************************

CTS:
            MVI A,$F0 ;-16          ;BERECHNE ABSOLUTE
ADDSEC:
            ADI 16                  ;NUMMER DES EINTRAGS
            DCR B                   ;(1..79)
            JNZ ADDSEC              ;
            ADD C                   ;
            PUSH PSW                ;RETTE EINTRAGS-NUMMER (1...79)
            ANI %00000001           ;MASKIERE SEITEN-BIT
                                    ;GERADE EINTRAGS-NUMMER = SEITE 0
                                    ;UNGERADE EINTRAGS-NUMMER = SEITE 1
            STA SEITE               ;RETTE SEITEN-NUMMER
            POP PSW                 ;RESTORE EINTRAGS-NUMMER (1...79)
            ORA A                   ;CLEAR CARRY
            RAR                     ;BERECHNE RELATIVE SPUR-NUMMER
                                    ;(0 .. 39) AUF DER SEITE
            STA SPUR                ;RETTE SPUR-NUMMER
            RET

;*************************************************************************
;UNTERPROGRAMM "GETPOS"

;DAS BFZ—MIMI—DOS TEILT FILES IN 4K-BYTE-BL0ECKE EIN. FUER JEDEN DIESER 
;BLOECKE WIRD EIN DIRECTORY-EINTRAG BENOETIGT. DIE POSITIONEN DER EINTRAEGE 
;EINES FILES KANN MAN AUCH EIN EINER TABELLE ANGEBEN. SOLCHE TABELLEN WERDEN 
;Z.B. VOM UNTERPROGRAMM "SEINTR" AUFGESTELLT.

;DIE TABELLEN BESITZEN FOLGENDEN AUFBAU:
;
;REL. POSITION DES EINTRAGS IM DIR.-SEKTOR      ) ANFANG FUER DEN 
;NUMMER DES DIRECTORY-SEKTORS                   ) 1. EINTRAG
;
;REL. POSITION DES EINTRAGS IM DIR.-SEKTOR      ) ANFANG FUER DEN 
;NUMMER DES DIRECTORY-SEKTORS                   ) 2. EINTRAG
;
;           USW.
;
;WILL MAN Z.B. EINEN FILE LESEN, SO MUESSEN DER REIHE NACH ALLE ZU DEN 
;EINZELNEN EIMTRAEGEN GEHOERENDEN BLOECKE EINGELESEN WERDEN.
;ES EXISTIERT EIN ZEIGER, DER ZU BEGINN AUF DEN TABELLENANFANG ZEIGT.
;LIEST MAN DIE ANGABEN FUER EINEN EINTRAG AUS DER TABELLE, SO WIRD DER 
;ZEIGER AUF DIE NAECHSTEN ANGABEN WEITERGESTELLT.
;
;MIT HILFE DIESES UNTERPROGRAMMS KOENNEN DIE EINZELNEN ANGABEN AUS DER 
;TABELLE GELESEN WERDEN. DAS PROGRAMM STELLT DEN TABELLENZEIGER AUTOMATISCH 
;WEITER.
;
;DA MEHRERE TABELLEN EXISTIEREN KOENNEN, DIENT DAS HL—REGISTERPAAR BEIM 
;UNTERPROGRAMMAUFRUF AUCH ALS ZEIGER. ES ZEIGT AUF DEN GERADE AKTUELLEN 
;TABELLENZEIGER:

; HL ->      TABELLENZEIGER -> TABELLE
;
;DIE ANGABEN AUS DER TABELLE WERDEN BEIM AUSLESEN IN DIE REGISTER B UND C 
;GELADEN:
;
;B-REGISTER:      DIRECTORY-SEKTOR
;C—REGISTER:      REL. NUMMER DES EINTRAGS IM DIR„-SEKTOR 
;
;NACH RETURN SIND FOLGENDE REGISTER VERAENDERT:;
;
;BC = (SIEHE OBEN)
;DE = NEUER WERT DES TABELLENZEIGERS
;*************************************************************************

GETPOS:
            MOV E,M                 ;E=LOW (TABELLEN-ZEIGER)
            INX H                   ;ZEIGER AUF HIGH(TAB-ZEIGER)
            MOV D,M                 ;D=HIGH (TAB-ZEIGER)
            XCHG                    ;HL-TAB-ZEIGER, DE-ZEIGER AUF H(TAB—ZEIGER)
            MOV C,M                 ;C=LOW (TAB-EINTRAG)
            INX H                   ;ZEIGER AUF HIGH(TAB-EINTRAG)
            MOV B,M                 ;B=HIGH (TAB-EINTRAG)
            INX H                   ;ZEIGER AUF LOW (NAECHST. TAB-EINTRAG)
            XCHG                    ;DE=TAB-ZEIGER, HL-ZEIGER AUF H(TAB-ZEIGER)
            MOV M,D                 ; SPEICHERE NEUEN TAB-ZEIGER
            DCX H                   ;
            MOV M,E                 ;
            RET                     ;

;*************************************************************************
;UNTERPROGRAMM "GSTART"

;DRUCKT START-ADRESSEN-VORSCHLAG (STEHT IN STARTA) UND HOLT EVTL.
;NEUE ADRESSE. DIE (NEUE) START-ADR WIRD IN "STARTA" GESPEICHERT 
;DAS AUSGEWAEHLTE LAUFWERK (SELEKT-MASKE IN "SELMSK") WIRD SELEKTIERT. 
;FALLS ES NICHT BEREIT IST, VERZWEIGT DAS PROGRAMM NACH "CODE3"
;*************************************************************************

GSTART:
            CALL DESEL              ;DESELECT LAUFWERK
            CALL BUFCLR             ;LOESCHE MAT85-INPUT-BUFFER
            LHLD STARTA             ;LADE START-ADR
            CALL HSTART             ;NEUE START-ADR ?
            SHLD STARTA             ;SPEICHERE (NEUE) START-ADR
            CALL CRLF               ;PRINT CR,LF
            CALL SELECT             ;SELECT LAUFWERK
            CALL DREADY             ;LAUFWERK BEREIT ?
            CC CODE3                ;NEIN -> CODE3
            RET

;*************************************************************************
;UNTERPROGRAMM "GSTSP"

;DRUCKT VORSCHLAGS-ADRESSEN FUER START/STOP (ADRESSEN AUS "STARTA" BZW. 
;"STOPA"), HOLT NEUE ADRESSEN UND SPEICHERT SIE IN "STARTA" BZW. "STOPA" 
;AB.

;WERTE NACH RETURN:     DE = START-ADRESSE
;                       HL = STOP-ADRESSE
;*************************************************************************

GSTSP:
            CALL BUFCLR             ;LOESCHE MAT85-INPUT—BUFFER
            CALL HSTSPA             ;HOLE START/STOP-ADR
            SHLD STARTA             ;RETTE START-ADR
            XCHG                    ;HL=STOP—ADR
            SHLD STOPA              ;RETTE STOP-ADR
            RET

;*************************************************************************
;UNTERPROGRAMM "MOVE"

;DIESES UNTERPROGRAMM KOPIERT DIE DATENBYTES AUS DEM SEKTOR-PUFFER "SECB"
;IN DEN ZIEL-SPEICHER. ES PRUEFT, OB DAS BYTE ERFOLGREICH IN DEN ZIEL-
;SPEICHER GESCHRIEBEN WURDE.
;BEI EINEM FEHLER, VERZWEIGT DAS PROGRAMM NACH "CODE14".
;
;WERTE BEIM AUFRUF:     (TEINT) =   ANFANG DES ZIELSPEICHERS
;                       (REST)  =   ANGABE UEBER DIE ANZAHL DER ZU
;                                   KOPIERENDEN BYTES:
;                                   (REST) >= 512 -> 512 BYTES KOPIEREN
;                                   (REST) < 512 -> (REST) BYTES KOPIEREN
;
;WERTE NACH RETURN:     (TEINT) =   ALTER WERT + ANZ. DER KOPIERTEN BYTES
;
;VERAENDERTE REGISTER:  A = 00
;
;*************************************************************************

MOVE:
            PUSH B                  ;RETTE REGISTER
            PUSH D                  ;
            PUSH H                  ;
            LHLD REST               ;LADE REST-LAENGE
            XCHG                    ;REST-LAENGE NACH DE
            LXI H,512               ;SEKTOR-LAENGE
            CALL CMPHD              ;REST > SEKTOR-LAENGE
            JNC MOVE0               ;NEIN —> MOVE0
            XCHG                    ;DE=SEKTOR-LAENGE (512)
MOVE0:
            LHLD TEINT              ;ZIEL-ADR NACH HL
            LXI B,SECB              ;ZEIGER AUF SEKTOR-BUFFER
MOVE1:
            LDAX B                  ;ZEICHEN AUS BUFFER IN AKKU
            MOV M,A                 ;ZEICHEN IN ZIEL-SPEICHER
            CMP M                   ;ZEICHEN IN ZIEL-SPEICHER ?
            CNZ CODE14              ;NEIN —> CODE14
            INX H                   ;ZEIGER WEITERSTELLEN
            INX B                   ;
            DCX D                   ;EIN BYTE UEBERTRAGEN
            MOV A,D                 ;ZAEHLER = 0000 ?
            ORA E                   ;
            JNZ MOVE1               ;NEIN —> NAECHSTES BYTE
            SHLD TEINT              ;RETTE NEUE ZIEL-ADR
            POP H                   ;RESTORE REGISTER
            POP D                   ;
            POP B                   ;
            RET

;*************************************************************************
;UNTERPROGRAMM "DELETE"

;BEREITET DAS UNTERPROGRAMM "MDIR" ZUM LOESCHEN VON DIRECTORY-EINTRAEGEN
;VOR. DAS UNTERPROGRAMM "DELETE" GEHT OHNE RETURN IN DAS UNTERPROGRAMM
;"MDIR" UEBER.
;
;WERTE BEIM AUFRUF:     ANZAHL DER ZU LOESCHENDEN EINTRAEGE
;                       DIE POSITIONEN DER EINTRAEGE MUESSEN IN DER TABELLE
;                       "TVORH" STEHEN.
;                       AUFBAU DER TABELLEN-ANGABEN:
;                       DIE TABELLE ENTH. FUER JEDEN EINTRAG EINE 2-BYTE ANGABE
;                       LOW-BYTE: POSITION DES EINTRAGS INNERHALB DES DIR—SEKTORS
;                       HIGH-BYTE: NUMMER DES DIRECTORY-SEKTORS
;
;*************************************************************************

DELETE:
            STA ZWSP2               ;ANZAHL DER ZU LOESCHENDEN EINTRAEGE
            LXI H,TVORH             ;ZEIGER AUF "TVORH" INITIALISIEREN
            SHLD ZWSP1              ;
            LXI H,$0036             ;CODE: "MVI M,00"
            SHLD XDIR               ;EINSETZEN
            MVI A,RETURN            ;RET-OPCODE
            STA XDIR+2              ;EINSETZEN

;*************************************************************************
;UNTERPROGRAMM "MDIR" (MODIFIZIERE DIRECTORY)
;
;DIESES UNTERPROGRAMM MODIFIZIERT DAS DIRECTORY. DIE ART DER MODIFIKATION
;(EINTRAG ERSTELLEN, EINTRAG LOESCHEN) MUSS VOR DEM UNTERPROGRAMM-AUFRUF
;DURCH MODIFIKATION DES VEKTORS "XDIR" FESTGELEGT WERDEN.
;
;EINTRAG LOESCHEN:      XDIR = MVI M,00
;                              RET
;
;EINTRAG ERSTELLEN:     XDIR = CALL VEINTR
;
;WERTE BEIM AUFRUF:     (ZUSP1) = ZEIGER AUF EINEN TABELLENZEIGER
;                       (ZUSPl) = TAB.-ZEIGER --> TABELLE
;                       DIE TABELLE ENTHAELT ANGABEN UEBER DIE POSITION
;                       DER ZU MODIFIZ. EINTRAEGE INNERHALB DES DIRECTORY.
;                       PRO EINTRAG ENTH. DIE TABELLE EINE 2—BYTE—ANGABE:
;                       LOW-BYTE: POS. DES EINTRAGS INNERN. DES DIR.-SEKTORS
;                       HIGH-BYTE: NUMMER DES DIRECTORY-SEKTORS
;
;                       (ZUSP2) - ANZAHL. DER ZU MODIFIZIERENDEN EINTRAEGE
;
;*************************************************************************

MDIR:
            CALL POSDIR             ;POSITIONIERE KOPF AUF DIRECTORY
            
            LXI H,ZWSP1             ;ZEIGER AUF TABELLEN-POINTER
            CALL GETPOS             ;LESE POSITION AUS TABELLE
MDIR1:
            MOV A,B                 ;SEKTOR-NUMMER NACH A
            OUT FDCSEC              ;SEKTOR-NUMMER AN FDC
            CALL RRS                ;LESE SEKTOR (MAXTRY VERSUCHE)
MDIR0:
            CALL SELECT             ;KEEP DRIVE ROTATING
            MOV A,C                 ;EINTRAGS-NUMMER NACH A
            CALL ANFEIN             ;ZEIGER AUF EINTRAGS-ANFANG
            CALL XDIR               ;MODIFIZI ERE DI RECTORY-SEKTOR
            LXI H,ZWSP2             ;ZEIGER AUF ZAEHLER
            DCR M                   ;ZAEHLER MINUS EINS
            JZ MDEND                ;SPRINGEv WENN ALLE EINTRAEGE MODIFIZIERT
            MOV A,B                 ;ALTE SEKTOR-NUMMER NACH A
            LXI H,ZWSP1             ;ZEIGER AUF TABELLEN-POINTER
            CALL GETPOS             ;LESE POSITION AUS TABELLE
            CMP B                   ;GLEICHER SEKTOR WIE LETZTER EINTRAG ?
            JZ MDIR0                ;JA —> MDIR0
            PUSH B                  ;RETTE SEKTOR-NR. (B) UND EINTRAGS-NR.(C)
            CALL SAVSEC             ;SCHREIBE GEAENDERTEN DIRECTORY-SEKTOR
            POP B                   ;RESTORE SEKTOR- (B) UND EINTRAGS-NR. (C)
            JMP MDIR1               ;LESE ZU AENDERNDEN SEKTOR EIN
MDEND:
            CALL SAVSEC             ;SCHREIBE GEAENDERTEN DIRECTORY-SEKTOR
            RET

;*************************************************************************
;
;UNTERPROGRAMM "ANZAHL"
;
;DIESES UNTERPROGRAMM BERECHNET AUS DER FILE-LAENGE WIEVIELE 4K-BYTE-
;BLOECKE ZUM ABSPEICHERN BENOETIGT WERDEN.
;
;WERTE BEIM AUFRUF:     HL = FILE-LAENGE
;
;WERTE NACH RETURN:     HL = REST (FILELAENGE / 4096)
;
;                       WENN HL = 0000          WENN HL <> 0000
;                       B=FILELAENGE/4096       B=FILELAENGE/4096 + 1
;
;*************************************************************************

ANZAHL:
            MVI B,0                 ;BERECHNE:
            LHLD LAENGE             ;WIEVIELE VOLLE TRACKS
            LXI D,BLOCKSIZE         ;A 4k-BYTE WERDEN ZUM
ANZ1:
            CALL SUB2               ;ABSPEICHERN BENOETIGT
            JC ANZ0                 ;RECHNUNG: HL/1000H
            INR B                   ;ERGEBNIS:  B
            JMP ANZ1                ;REST:      HL
ANZ0:
            DAD D                   ;
            MOV A,H                 ;REST = 0000 ?
            ORA L                   ;
            RZ                      ;JA —> RETURN
            INR B                   ;PLUS EIN EINTRAG FUER DEN REST
            RET                     ;

;*************************************************************************
;UNTERPROGRAMM "VEINTRAG" (VERMERKE DIRECTORY-EINTRAG)
;
;WIRD VON "MDIR"UEBER DEN VEKRTOR "XDIR" AUFGERUFEN, WENN NEUE DIRECTORY-
;EINTRAEGE ERSTELLT WERDEN SOLLEN.
;
;WERTE BEIM AUFRUF:     (EFROM) =   ENTERED-FROM-CODE (VON WO WURDE DAS DOS
;                                   AUFGERUFEN?) 01=MAT85, 02= SPS, 03=BASIC
;                       (ZWSP2) =   ANZAHL DER BENOETIGTEN EINTRAEGE
;                                   (EIN FILE BENOETIGT FUER JEDEN 4K-BYTE-BL0CK 
;                                   EINEN EINTRAG. DIESES UNTERPROGRAMM ERZEUGT 
;                                   NUR EINEN EINTRAG UND MUSS DESHALB ENTSPRECHEND 
;                                   OFT AUFGERUFEN WERDEN. WIRD DER LETZTE EINTRAG 
;                                   EINES FILES ERZEUGT, SO ERHAELT DIESER EINE BESONDERE 
;                                   MARKIERUNG. UM ERKENNEN ZU KOENNEN, DASS ES SICH 
;                                   UM DEN LETZTEN EINTRAG HANDELT, MUSS DER INHALT
;                                   VON "ZWSP2" DANN DEN WERT "01" HABEN.)
;
;                       (START) =   START-ADRESSE DES FILES
;
;                       (LAENGE) =  LAENGE DES FILES
;
;                       MAT85-INPUT-PUFFER = FILE—NAME (RUECKWAERTS)
;                       (EVENTUELL MIT 80H AUF 12 ZEICHEN AUFGEFUELLT)
;*************************************************************************

VEINTR:
            PUSH B                  ;RETTE BC
            LDA EFROM               ;LESE ENTERED-FROM-CODE: 01 = MAT
                                    ;                        02 = SPS
                                    ;                        03 = BASIC
            MOV D,A                 ;RETTE CODE IN D
            LDA ZWSP2               ;ANZAHL DER BENOETIGTEN EINTRAEGE
            DCR A                   ;ANZAHL MINUS EINS
            JZ LASTE                ;SPRINGE, WENN LETZTER EINTRAG
            MVI A,%10000000         ;SETZE BIT 7, LOESCHE BIT 1 ... BIT 6
LASTE:
            ORA D                   ;VERKNUEPFE MIT ENTERED-FROM-CODE
            MOV M,A                 ;SETZE KENNBYTE EIN
            INX H                   ;ZEIGER AUF NAMENS-FELD
            LXI D,M85BE-1           ;MAT85-INPUT-BUFFER (FILE-NAME)
            MVI B,12                ;LAENGE (NAME)
NXTCHR:
            LDAX D                  ;ZEICHEN IN AKKU
            MOV M,A                 ;ZEICHEN IN BUFFER
            INX H                   ;STELLE ZEIGER WEITER
            DCX D                   ;
            DCR B                   ;ALLE ZEICHEN UEBERTRAGEN ?
            JNZ NXTCHR              ;NEIN —> NXTCHR
            
            XCHG                    ;DE = BUFFER-ZEIGER
            LHLD STARTA             ;HL = START-ADR
            XCHG                    ;DE = START-ADR, HL = BUFFER-ZEIGER
            MOV M,E                 ;SETZE START-ADR EIN
            INX H                   ;
            MOV M,D                 ;
            INX H                   ;

            XCHG                    ;DE = BUFFER-ZEIGER
            LHLD LAENGE             ;HL = LAENGE
            XCHG                    ;DE = LAENGE, HL = BUFFER—ZEIGER
            MOV M,E                 ;SETZE LAENGE EIN
            INX H                   ;
            MOV M,D                 ;
            POP B                   ;RESTORE BC
            RET                     ;

;*************************************************************************
;UNTERPROGRAMM "ANFEIN"
;
;DIESES UNTERPROGRAMM STELLT DEN ZEIGER IM HL-REGISTERPAAR UEBER DEN
;ANFANG EINES BESTIMMTEN DIRECTORY-EINTRAGS. DER DIRECTORY-SEKTOR MUSS
;DAZU IM SEKTOR-PUFFEF "SECB" STEHEN UND DER AKKUMULATOR MUSS DIE NUMMER
;DES EINTRAGS (1...16) INNERHALB DES SEKTORS ENTHALTEN
;
;*************************************************************************

ANFEIN:
            LXI H,SECB-32           ;BUFFER-ANFANG MINUS 32
            LXI D,32                ;OFFSET VON EINTRAG ZU EINTRAG
DADOFS:
            DAD D                   ;ADD OFFSET
            DCR A                   ;SO OFT WIE NOETIG
            JNZ DADOFS              ;
            RET

;*************************************************************************
;UNTERPROGRAMM "GETNAM "
;LIEST FILE-NAME UND PRUEFT IHN AUF GUELTIGKEIT
;
;GEBE ANFORDERUNG AUS
;
;*************************************************************************

GETNAM:
            CALL PTXTCR         ;TEXT AUSGEBEN
            .byte LF,"NAME: ",00    

;*************************************************************************
;VORBEREITUNG
;ERWARTET WERDEN MAXIMAL 12 ASCII-ZEICHEN (KEIN "+", KEIN "-")
;WANDLE ALLE EINGEGEBENEN BUCHSTABEN IN GROSSBUCHSTABEN UM
;
;*************************************************************************

            XRA A                   ;A=0
            STA GROFLG              ;NUR GROSSBUCHSTABEN
            STA BCKFLG              ;KEIN +,-
            MOV C,A                 ;ASCII
            MVI B,12                ;MAX 12 ZEICHEN
            CALL BUFCLR             ;LOESCHE EINGABE-BUFFER

;*************************************************************************
;LESE FILE-NAME EIN
;*************************************************************************

            CALL BREAD              ;LESE NAME
            CALL CRLF               ;PRINT CR,LF

;*************************************************************************
;PRUEFE NAME AUF GUELITIGKEIT 
;(ER STEHT RUECKUAERTS IM MAT85-INPUT-PUFFER, EINE MAT85-EIGENART)
;*************************************************************************

TSTNAM:
            LXI H,M85BE-1           ;ZEIGER AUF 1. ZEICHEN
            MOV A,M                 ;LESE 1. ZEICHEN
            CALL TSTCHR             ;BUCHSTABE ODER ZIFFER ?
            CNC CODE9               ;NEIN —> CODE9

            MVI C,7                 ;MAX 7 WEITERE ZEICHEN BIS "."
TNAM0:
            DCX H                   ;ZEIGER AUF NAECHSTES ZEICHEN
            MOV A,M                 ;LESE ZEICHEN
            CALL TSTCHR             ;BUCHSTABE ODER ZIFFER ?
            JNC TNAM1               ;NEIN -> TNAM1 ("." ODER ENDE)
            DCR C                   ;ZAEHLER MINUS EINS
            JNZ TNAM0               ;
            DCX H                   ;ZEIGER AUF NAECHSTES ZEICHEN
            MOV A,M                 ;LESE ZEICHEN
TNAM1:
            ORA A                   ;BIT 7 GESETZT (ENDE) ?
            RM                      ;JA — > RETURN
            CPI "."                 ;PUNKT ?
            CNZ CODE9               ;NEIN —> C0DE9 
            DCX H                   ;ZEIGER AUF NAECHSTES ZEICHEN 
            MOV A,M                 ;LESE ZEICHEN
            CALL TSTCHR             ;BUCHSTABE ODER ZIFFER ?
            CNC CODE9               ;NEIN —> CODE9
            MVI C,2                 ;MAX 2 WEITERE ZEICHEN 
TNAM2:
            DCX H                   ;ZEIGER AUF NAECHSTES ZEICHEN 
            MOV A,M                 ;LESE ZEICHEN
            ORA A                   ;BIT 7 GESETZT (ENDE) ?
            RM                      ;JA —> RETURN 
            CALL TSTCHR             ;BUCHSTABE ODER ZIFFER ? 
            CNC CODE9               ;NEIN —> CODE?
            DCR C                   ;ZAEHLER MINUS EINS
            JNZ TNAM2               ;
            DCX H                   ;ZEIGER AUF NAECHSTES ZEICHEN
            MOV A,M                 ;LESE ZEICHEN
            ORA A                   ;BIT 7 GESETZT (ENDE) ?
            RM                      ;JA —> RETURN 
            CALL CODE9              ;NEIN —> CODE?

;*************************************************************************
;UNTERPROGRAMM "SEINTR" (SUCHE EINTRAG) 
;
;FUNKTION:  1.    WENN (DSPLD) = 00
;                 ES WERDEN ALLE DIRECTORY-EINTRAEGE GEZAEHLT, DIE ENTWEDER
;                 FREI SIND ODER, DEREN NAMEN MIT DEM IM MAT85-INPUT—PUFFER
;                 UEBEREINSTIMMEN.
;                 DER ZAEHLER WIRD IN "ZAEHL" ABGESPEICHERT.
;                 DIE ERSTEN 16 EINTRAEGE WERDEN IN DER TABELLE "TEINT" VERMERKT.
;                 ANZAHL DER GUELTIGEN EINTRAEGE IN "TEINT":
;                 (ZAEHL) < 17  : (ZAEHL) GIBT DIE ANZAHL AN.
;                 (ZAEHL) >= 17 : 16 GUELTIGE EINTRAEGE.
;
;                 AUSSERDEM WERDEN ALLE EINTRAEGE GEZAEHLTy DEREN NAMEN MIT DEM
;                 IM MAT85-INPUT-BUFFER UEBEREINSTIMMEN (IM GEGENSATZ ZUM ERSTEN
;                 ZAEHLER WERDEN FREIE EINTRAEGE NICHT MITGEZAEHLT). DA FUER
;                 JEDEN 4K-BYTE-BLOCK EIN EINTRAG BESTEHT UND DA DIE MAXIMALE
;                 FILE-LAENGE 65535 BYTE BETRAEGT, KANN DER ZAEHLER MAXIMAL DEN
;                 WERT 16 ANNEHMEN.
;
;                 DER ZAEHLER WIRD IN "ZAEHLV" ABGESPEICHERT.
;                 DIE EINTRAEGE WERDEN IN DER TABELLE "TVORH" VERMERKT.
;                 "ZAEHLV" GIBT DIE ANZAHL DER GUELTIGEN EINTRAEGE IN DIESER
;                 TABELLE AN.
;
;           2.    WENN (DSPLD) <> 00
;                 DAS INHALTSVERZEICHNIS WIRD ANGEZEIGT.
;                 ES WERDEN DANN NUR DIE FREIEN EINTRAEGE IN "ZAEHL" GEZAEHLT.
;                 DIE ERSTEN 16 DIESER EINTRAEGE WERDEN IN DER TABELLE "TEINT"
;                 VERMERKT.
;
;                 ANZAHL DER GUELTIGEN EINTRAEGE IN "TEINT":
;                 (ZAEHL) < 17  : (ZAEHL) GIBT DIE ANZAHL AN.
;                 (ZAEHL) >= 17 : 16 GUELTIGE EINTRAEGE.
;
;DAS INHALTSVERZEICHNIS IST WIE FOLGT AUFGEBAUT:
;ES BESTEHT AUS DEN SEKTOREN 1,2,3,4 UND 5 AUF SPUR 0, SEITE 0.
;JEDER SEKTOR BESTEHT AUS 16 EINTRAEGEN MIT JE 32 BYTE.
;DER LETZTE EINTRAG IM 5. SEKTOR WIRD NICHT GENUTZT.
;DAMIT ERGIBT SICH EINE ANZAHL VON 79 GENUTZTEN EINTRAEGEN.
;
;FUER JEDES FILE WIRD PRO ANGEFANGENE 4K—BYTE EIN EINTRAG BELEGT.
;FILES, DIE MEHR ALS EINEN EINTRAG BELEGEN (LAENGE > 4K—BYTE), WERDEN 
;ALS "MEHRFACH-EINTRAG" BEZEICHNET. FILES, DIE NUR EINEN EINTRAG BELEGEN 
;(LAENGE <= 4K-BYTE), WERDEN ALS "EINZEL-EINTRAG" BEZEICHNET.
;
;BEI MEHRFACH-EINTRÄEGEN BEFINDEN SICH DIE EINTRAEGE ZU DEN EINZELNEN 
;4K-BYTE-BL0ECKEN IN DER REIHENFOLGE, IN DER DIE EINZELNEN BLOECKE BEIM 
;ABSPEICHERN IM SPEICHER STANDEN.
;
;EIN EINTRAG ENTHAELT FOLGENDE INFORMATION:
;        1. BYTE : KENNBYTE
;  2. - 13. BYTE : FILE-NAME INCL. ".", RECHTS MIT 80h AUFGEFUELLT
; 14. - 15. BYTE : START-ADR (BEI MEHRFACH-EINTRAEGEN START-ADR DES 1. BLOCKS)
; 16. - 17. BYTE : LAENGE (BEI MEHRFACH—EINTRAEGEN LAENGE DES GESAMT-FILES)
; 18. - 32. BYTE : OHNE BEDEUTUNG
;
;DAS KENNBYTE HAT FOLGENDE BEDEUTUNG:
;0000 0000 - EINTRAG FREI 
;
;SONST:
;1XXX XXXX - TEIL 1 ... N EINES N-TEILIGEN MEHRFACH-EINTRAGS
;0XXX XXXX - TEIL N EINES N-TEILIGEN MEHRFACH-EINTRAGS 
;            ODER EINZEL-EINTRAG
;
;BEI EINEM BELEGTEN EINTRAG GEBEN DIE BITS 0 BIS 6 AUSKUNFT 
;UEBER DEN FILE-TYP:
;X000 0001 - MAT 
;X000 0010 - SPS
;X000 0011 - BAS
;
;DER TYP GIBT AN, VON WO DAS DOS VOR DEM ABSPEICHERN EINES FILES 
;AUFGERUFEN WURDE.
;
;BEISPIEL:  TYP = "BAS":      DAS DOS WURDE VON BASIC AUFGERUFEN
;                             DAS FILE IST SOMIT EIN BASIC-PROGRAMM
;
;DIE POSITION EINES EINTRAGS INNERHALB DES VERZEICHNISES GIBT 
;AUSKUNFT DARUEBER, WO DER IM EINTRAG ANGEGEBENE FILE AUF DER 
;DISKETTE GESPEICHERT IST.
;
;DAZU WERDEN DIE EINZELNEN DIRECTORY-EINTRAEGE UEBER ALLE DIRECTORY-
;SEKTOREN VON 1 BIS 79 DURCHNUMMERIERT.
;
;STELLT MAN DIE EINTRAGS-NUMMER (1 ... 79) BINAER DA, SO GIBT BIT 0
;DIE SEITE AN:
;XXXX XXX0 - SEITE 0
;XXXX XXX1 - SEITE 1
;
;DIE BITS 1 BIS 7 GEBEN DIE SPUR AN:
;
;BEISPIELE: EINTRAGS-NUMMER   BINAER-DARSTELLUNG      SEITE       SPUR
;                 1                 0000 0001         1           0
;                 2                 0000 0010         0           1
;                 3                 0000 0011         1           1
;                 4                 0000 0100         0           2
;                 5                 0000 0101         1           2
;                 .
;                 .
;                78                 0100 1110         0           39
;                79                 0100 1111         1           39
;
;SEITE 0, SPUR 0 IST DURCH DAS VERZEICHNIS BELEGT.
;
;NACH RETURN:     1.    WENN (DSPLD) = 00
;                       (ZAEHL) =   ANZAHL DER FREIEN EINTRAEGE
;                                 + ANZAHL DER EINTRAEGE MIT DEM FILE-NAMEN, 
;                                   DER IM MAT85-INPUT-PUFFER STEHT.
;                       A       =   ZAEHL
;                       WENN (ZAEHL) = 00 IST DAS Z-FLAG GESETZT.
;
;                       (ZAEHLV) =  ANZAHL DER EINTRAEGE MIT DEM FILE-NAMEN,
;                                   DER IM MAT85-INPUT-PUFFER STEHT
;
;                       DIE ERSTEN 16 EINTRAEGE, DIE ENTWEDER 
;                       - FREI SIND ODER
;                       - DEREN NAME MIT DEM IM MAT85-INPUT-BUFFER UEBEREIMSTIMMT
;                       WERDEN IN DER TABELLE "TEINT" VERMERKT.
;
;                       ANZAHL DER GUELTIGEN EINTRAEGE IN "TEINT":
;                       (ZAEHL) < 17  : (ZAEHL) GIBT DIE ANZAHL AN
;                       <ZAEHL> >= 17 : 16 GUELTIGE EINTRAEGE
;
;                       DIE EINTRAEGE, DEREN NAME MIT DEM IM MAT85-INPUT-PUFFER 
;                       UEBEREINSTIMMT, WERDEN IN DER TABELLE "TVORH" VERMERKT.
;                       (ZAEHLV) GIBT DIE ANZAHL DER GUELTIGEN EINTRAEGE IN 
;                       DIESER TABELLE AN.
;
;                 2.    WENN (DSPLD) <> 00
;                       (ZAEHL) =   ANZAHL DER FREIEN EINTRAEGE 
;                       A       =   ZAEHL
;                       WENN (ZAEHL) = 00 IST DAS Z-FLAG GESETZT
;
;                       DIE ERSTEN 16 EINTRAEGE, DIE FREI SIND, WERDEN IN DER 
;                       TABELLE "TEINT" VERMERKT.
;                       ANZAHL DER GUELTIGEN EINTRAEGE IN "TEINT":
;                       (ZAEHL) < 17  : (ZAEHL) GIBT DIE ANZAHL AN.
;                       (ZAEHL) >= 17 : 16 GUELTIGE EINTRAEGE.
;
;DIE EINTRAEGE IN DEN TABELLEN "TEINT" UND "TVORH" BESTEHEN AUS JE ZWEI BYTES:
;                 - LOW BYTE: NUMMER DES RELATIVEN DIRECTORY-EINTRAGS <1 ... 16)
;                 - HIGH BYTE: NUMMER DES DIRECTORY-SEKTORS (1 ... 5)
;
;*************************************************************************
;VORBEREITUNG
;*************************************************************************

SEINTR:
            XRA A                   ;A = 0
            STA SEITE               ;SEITE 0
            STA ZAEHL               ;ZAEHLER AUF NULL
            STA ZAEHLV              ;
            LXI H,TEINT             ;ZEIGER AUF DIE TABELLEN
            SHLD PTEINT             ;"TEINT" UND
            LXI H,TVORH             ;"TVORH"
            SHLD PTVORH             ;INITIALISIEREN

;*************************************************************************
;KOPF LIEBER DIREKTORY POSITIONIEREN
;*************************************************************************

            CALL POSDIR             ;POSITIONIERE KOPF AUF DIRECTORY

;*************************************************************************
;LESE DIRECTORY-SEKTOR EIN
;*************************************************************************

            MVI B,1                 ;SEKTOR-NUMMER
NEXT2:
            CALL SELECT             ;RE—SELECT LAUFWERK
            MOV A,B                 ;SEKTOR—NUMMER NACH A
            OUT FDCSEC              ;AN FDC
            CALL RRS                ;READ SECTOR (MAXTRY VERSUCHE)

;*************************************************************************
;PRUEFE DIE EINTRAEGE
;*************************************************************************

            LXI H,SECB              ;ZEIGER AUF SECTOR-BUFFER
            MVI C,1                 ;1. EINTRAG DES SEKTORS
NEXT1:
            SHLD ZWSP1              ;RETTE ZEIGER
            MOV A,M                 ;LESE ERSTES BYTE DES EINTRAGS
            ORA A                   ;EINTRAG FREI ?
            JNZ EBEL                ;NEIN -> EBEL

;*************************************************************************
;HIER, WENN EINTRAG FREI
;*************************************************************************
            
EFREI:
            LDA ZAEHL               ;LADE ZAEHLER FUER "TEINT"
            INR A                   ;PLUS EINS
            STA ZAEHL               ;RETTE NEUEN ZAEHLER-STAND
            LHLD PTEINT             ;LADE ZEIGER AUF "TEINT"
            CALL REINTR             ;REGISTRIERE EINTRAG
            SHLD PTEINT             ;RETTE NEUEN ZEIGER
            JMP NEXT                ;

;*************************************************************************
;HIER, WENN EINTRAG BELEGT
;SOLL DAS DIRECTORY ANGEZEIGT WERDEN ?
;*************************************************************************

EBEL:
            MOV D,A                 ;RETTE KENN-BYTE IN D
            LDA DSPLD               ;DISPLAY DIRECTORY ?
            ORA A                   ;
            JZ NODSPL               ;NEIN —> NODSPL

;*************************************************************************
;HIER, WENN DIRECTORY ANGEZEIGT WERDEN SOLL
;*************************************************************************

            MOV A,D                 ;RESTORE KENN-BYTE
            ORA A                   ;BIT 7 GESETZT ?
            JM NEXT                 ;JA —> NEXT
                                    ;(TEIL 1 ... N-l EINES N—TEILIGEN
                                    ;MEHRFACH-EINTRAGS. BEI MEHRFACH-
                                    ;EINTRAEGEN WIRD NUR DER LETZTE
                                    ;EINTRAG ANGEZEIGT.

;*************************************************************************
;EINTRAG ANZEIGEN
;*************************************************************************

            PUSH B                  ;RETTE SEKTOR-NR. (B) UND EINTRAGS-NR. (C)
            MVI B,12                ;12 ZEICHEN ANZEIGEN
DISPL:
            INX H                   ;ZEIGER AUF NAECHSTES ZEICHEN
            MOV A,M                 ;LESE ZEICHEN
            ORA A                   ;BIT 7 GESETZT (80H) ?
            JP NOB0                 ;NEIN —> NOB0
            MVI A," "               ;LADE SPACE
NOB0:
            CALL WCHAR              ;PRINT ZEICHEN
            DCR B                   ;12 ZEICHEN GEDRUCKT ?
            JNZ DISPL               ;NEIN —> DISPL

;*************************************************************************
;DRUCKE ZUSATZINFORMATIONEN
; 1. FILE-TYP (MAT,SPS,BASIC)
;*************************************************************************

            CALL WBLNKI             ;PRINT 3 BLANKS
            .byte 3
            CALL TYP                ;PRINT FILE-TYP

;*************************************************************************
;2. START-ADRESSE            
;*************************************************************************
            CALL WBLNKI             ;PRINT 6 BLANKS
            .byte 6                 ;
            INX H                   ;START-ABR LESEN
            MOV E,M                 ;
            INX H                   ;
            MOV D,M                 ;
            XCHG                    ;
            PUSH H                  ;RETTE START-ADR
            CALL PHL                ;PRINT START-ADR

;*************************************************************************
;3. STOP-ADRESSE (WIRD AUS START-ADRESSE UND LAENGE BERECHNET)
;*************************************************************************

            CALL WBLNKI             ;PRINT 10 BLANKS
            .byte 10
            XCHG                    ;HL = BUFFER-ZEIGER
            INX H                   ;LAENGE LADEN
            MOV E,M                 ;
            INX H                   ;
            MOV D,M                 ;
            XCHG                    ;
            SHLD LAENGE             ;RETTE LAENGE
            POP D                   ;RESTORE START-ADR
            DAD D                   ;HL-START-ADR PLUS LAENGE
            DCX H                   ;HL=STOP-ADR
            CALL PHL                ;PRINT STOP-ADR

;*************************************************************************
;4. ANZAHL DER BLOECKE
;*************************************************************************

            CALL WBLNKI             ;PRINT 7 BLANKS
            .byte 7                 ;
            CALL ANZAHL             ;BERECHNE ANZAHL DER BLOECKE
            MOV A,B                 ;ANZAHL NACH A
            CALL WDEZ               ;PRINT ANZAHL

;*************************************************************************
;NAECHSTE ZEILE. PRUEFE, OB BILDSCHIRM VOLL (UNTERPROB. "LINE").
;*************************************************************************

            CALL CRLF               ;PRINT CR,LF
            CALL LINE               ;ZAEHLE DIE AUSGEGEBENEN ZEILEN
            CALL SELECT             ;KEEP DRIOE ROTATING
            JMP NEXT0               ;NAECHSTER EINTRAG

;*************************************************************************
;HIER, WENN DIRECTORY NICHT ANGEZEIGT WERDEN SOLL
;
;IST DER FILE-NAME IM DIRECTORY-EINTRAG IDENTISCH MIT DEM IM EINGABE-PUFFER ?
;*************************************************************************

NODSPL:
            PUSH B                  ;RETTE SEKTOR-NR <B> UND EINTRAGS-NR. (C)
            MVI B,12                ;PRUEFE 12 ZEICHEN
            LXI D,M85BE-1           ;ZEIGER AUF FILE-NAMEN
EBEL0:
            INX H                   ;STELLE ZEIGER AUF NAECHSTES ZEICHEN
            LDAX D                  ;ZEICHEN DES FILE-NAMENS NACH A
            CMP M                   ;VERGLEICHE MIT ZEICHEN AUS DIRECTORY
            JNZ NEXT0               ;SPRINGE, WENN UNGLEICH
            DCX D                   ;STELLE MAT85-BUFFER-ZEIGER WEITER
            DCR B                   ;12 ZEICHEN GEPRUEFT ?
            JNZ EBEL0               ;NEIN -> EBEL0

;*************************************************************************
;HIER, WENN EINTRAGS-NAME = NAME (MAT85-INPUT-PUFFER)
;
;ZAEHLE EINTRAG UND REGISTRIERE IHN.
;*************************************************************************

            LDA ZAEHLV              ;LADE ZAEHLER
            INR A                   ;ERHOEHE ZAEHLER
            STA ZAEHLV              ;RETTE NEUEN ZAEHLER-STAND
            POP B                   ;RESTORE SEKTOR- (B) UND EINTRAGS-NR. (C)
            LHLD PTVORH             ;ZEIGER AUF "TVORH"
            CALL REINTR             ;REGISTRIERE EINTRAG
            SHLD PTVORH             ;RETTE NEUEN ZEIGER
            PUSH B                  ;

;*************************************************************************
;NAECHSTER EINTRAG
;*************************************************************************

NEXT0:
            POP B                   ;RESTORE SEKTOR- <B> UND EINTRAGS-NR. (C)
NEXT:
            LXI D,32                ;OFFSET ZUM NAECHSTEN EINTRAG
            LHLD ZWSP1              ;ALTEM ZEIGER LADEN
            DAD D                   ;OFFSET ADDIEREN
            INR C                   ;NAECHSTER EINTRAG
            MVI A,17                ;MAX EINTRAG + EINS
            CMP C                   ;C-MAX EINTRAG + EINS ?
            JNZ NEXT1               ;NEIN —> NEXT1

;*************************************************************************
;HIER, WENN NAECHSTER EINTRAG IM NAECHSTEN SEKTOR
;*************************************************************************

            INR B                   ;NAECHSTER SEKTOR
            MVI A,6                 ;MAX SEKTOR + EINS
            CMP B                   ;B-MAX SEKTOR + EINS ?
            JNZ NEXT2               ;NEIN —> NEXT2
            LDA ZAEHL               ;KORRIGIERE ZAEHLER
            DCR A                   ;
            STA ZAEHL               ;
            RET

;*************************************************************************
;UNTERPROGRAMM "REINTR" (REGISTRIERE EINTRAG)
;
;REGISTRIERT GEFUNDENEN EINTRAG IN TABELLE. (ALLERDINGS MAX. 16 EINTRAEGE)
;
;WERTE BEI AUFRUF:      A = ANZAHL DER BEREITS REGISTR. EINTRAEGE + EINS
;                       B = NUMMER DES DIRECTORY-SEKTORS (1...5)
;                       C = REL. NUMMER DES EINTRAGS IM DIR.-SEKTOR (1...16)
;                      HL = ZEIGER AUF DIE TABELLENPOSITION, IN DER DER EINTRAG
;                           REGISTRIERT WERDEN SOLL.
;*************************************************************************

REINTR:
            CPI 17                  ;BEREITS 16 EINTRAEGE IN TABELLE ?
            RNC                     ;JA —> RETURN
            MOV M,C                 ;RETTE EINTRAGS-NUMMER
            INX H                   ;STELLE ZEIGER WEITER
            MOV M,B                 ;RETTE SEKTOR-NUMMER
            INX H                   ;STELLE ZEIGER WEITER
            RET

;*************************************************************************
;UNTERPROGRAMM "TYP"
;
;GIBT BEI DER ANZEIGE DES DIRECTORY DEN FILE-TYP ENTSPRECHEND DEM
;CODE ALS TEXT AUS: 01 = MAT, 02 = SPS, 03 = BAS. 
;FUER CODES >3 WIRD "???" AUSGEGEBEN.
;
;SIEHE AUCH TYP-TABELLE.
;*************************************************************************


TYP:
            PUSH H                  ;RETTE HL—REGISTERPAAR
            LHLD ZWSP1              ;HL = ZEIGER AUF KENN-BYTE
            MOV A,M                 ;KENN-BYTE: NACH A
            ANI %01111111           ;BIT 7 AUF 0 SETZEN
            LHLD PTYPT              ;HL-ZEIGER AUF TYP-TABELLE
            CMP M                   ;VERGLEICHE MIT MAX TYP-CODE + EINS
            JC TYPOK                ;SPRINGE, WENN TYP-CODE OK
            MOV A,M                 ;LADE MAX TYP-CODE
TYPOK:
            DCX H                   ;KORRIGIERE ZEIGER
            DCX H                   ;
            MOV E,A                 ;CODE NACH LSB(DE)
            MVI D,0                 ;          MSB(DE) = 00
            DAD D                   ;STELLE ZEIGER AUF RICHTIGEN
            DAD D                   ;TABELLEN-EINTRAG
            DAD D                   ;
            MVI D,3                 ;3 ZEICHEN SIND AUSZUGEBEN
NTYPZ:
            MOV A,M                 ;LESE ZEICHEN
            CALL WCHAR              ;PRINT ZEICHEN
            INX H                   ;STELLE ZEIGER WEITER
            DCR D                   ;3 ZEICHEN AUSGEGEBEN ?
            JNZ NTYPZ               ;NEIN —> NTYPZ
            POP H                   ;RESTORE HL-REGISTERPAAR
            RET

;*************************************************************************
;UNTERPROGRAMM "LINE"
;WIRD NUR ABGEARBEITET, WENN DRUCKER AUS.
;
;WEBERWACHT BEI DEM DIRECTORY DIE ANZAHL DER AUSGEGEBENEN ZEILEN
;WENN DER BILDSCHIRM VOLL IST, WIRD DIE ANZEIGE DES DIRECTORY UNTER-
;BRUCHEN. ES WIRD DANN DIE EINGABE VON <SP> FUER "WEITER" BZW. <CR>
;FUER "ABBRUCH" ERWARTET UND ENTSPRECHEND VERFAHREN.
;*************************************************************************

LINE:
            LDA CRTFLG              ;RETURN, WENN DRUCKER AN
                                    ;[P01#02] Hexadresse auf CRTFLG geaendert
            DCR A                   ;
            RZ                      ;
            LXI H,LCOUNT            ;ZEIGER AUF ZEILEN-ZAEHLER
            DCR M                   ;ZEILEN-ZAEHLER MINUS EINS
            RNZ                     ;RETURN, WENN NICHT NULL
            CALL PTXTCR             ;PRINT TEXT
            .byte "SPACE = WEITER, CR = ABBRUCH",00
            CALL DESEL              ;DESELECT LAUFWERK
LINE0:
            CALL RCHAR              ;LESE ZEICHEN
            CPI CR                  ;CR ?
            JZ ERET                 ;JA —> ABBRUCH
            CPI " "                 ;SPACE ?
            JNZ LINE0               ;NEIN —> LINE0
LINE1:
            CALL PTXT               ;PRINT TEXT
            .byte CR
            .byte "--- NAME ---   TYP   START (HEX)   STOP (HEX)"
            .byte "   BLOECKE"
            .byte CR,LF,00
            MVI A,12                ;RE-INIT ZEILENZAEHLER
            STA LCOUNT              ;
            CALL SELECT             ;RE-SELECT LAUFWERK
            CALL DREADY             ;LAUFWERK BEREIT ?
            CC CODE3                ;NEIN -> CODE3
            RET

;*************************************************************************
;UNTERPROGRAMM "LAUFW"
;
;FORDERT ZUR EINGABE DER LAUFWERKSBEZEICHNUNG (BZW. "M" FUER "MENUE) AUF
;PRUEFT EINGABE UND BERECHNET DIE SELECTMASKE (UNTERPROGRAMM "DRIVE")
;
;*************************************************************************

LAUFW:                              
            CALL PTXTCR             ;PRINT TEXT
            .byte LF
            .byte "A = LAUFWERK A",LF,CR
            .byte "B = LAUFWERK B",LF,CR
            .byte "M = MENUE",00
            CALL DRIVE              ;LESE BUCHSTABEN
                                    ;UND PRUEFE AUF GUELTIGKEIT
                                    ;BERECHNE MASKE
            RET

;*************************************************************************
;UNTERPROGRAMM "TSTCHR / LETTER"
;
;EINSPRUNG "TSTCHR":    PRUEFT OB ZEICHEN IM AKKU ZIFFER ODER BUCHSTABE IST.
;                       WENN JA, DANN CARRY = 1
;
;EINSPRUNG "LETTER":    PRUEFT OB ZEICHEN IM AKKU EIN BUCHSTABE IST
;                       WENN JA, DANN CARRY = 1
;
;*************************************************************************

TSTCHR:
            CPI "9" + 1             ;>= "9" + 1
            JNC LETTER              ;JA -> LETTER
            CPI "0"                 ;< "0" ?
            CMC                     ;KOMPL. CARRY (C = 1, ZIFFER)
            RC                      ;RETURN WENN ZIFFER

LETTER:
            CPI "Z" + 1             ;>= "Z" + 1 ?
            RNC                     ;JA -> RETURN
            CPI "A"                 ;< "A" ?
            CMC                     ;KOMPL. CARRY (C = 1, BUCHSTABE)
            RET                     ;

;*************************************************************************
;UNTERPROGRAMM "DRIME"
;
;LIEST ZEICHEN DER TASTATUR. BEI "M" VERZWEIGUNG ZUM "MENUE"
;BEI EINGABE VON "A" BZW. "B" WIRD DER SELECT-CODE DES LAUFWERKS
;BERECHNET.
;ANDERE EINGABEN ALS "A", "B" ODER "M" FUEHREN ZU DER
;FEHLERMELDUNGs "FALSCHE EINGABE"
;
;*************************************************************************

DRIVE:
            CALL GETCHR             ;ZEICHEN LESEN
            CPI "M"                 ;ZURUECK ZUM MENUE ?
            JZ MENUE                ;JA -> HAUPT-MENUE
DRIVE0:
            SUI "A"                 ;AUS "A" WIRD 0, AUS "B" WIRD 1
            CPI 02                  ;MAXIMAL-WERT UEBERSCHRITTEN ?
            CNC CODE0               ;JA —> FALSCHE EINGABE
            CALL COMPSM             ;BERECHNE SELECT-MASKE
            RET

;*************************************************************************
;UNTERPROGRAMM "GETCHR"
;
;FORDERT ZUR EINGABE EINES BUCHSTABENS AUF. EINGABEZEICHEN WERDEN
;GEPRUEFT. DABEI WERDEN NUR BUCHSTABEN AKZEPTIERT. KLEINBUCHSTABEN
;WERDEN IN GROSSBUCHSTABEN UMGEWANDELT. DER EINGEGEBENE BUCHSTABE
;WIRD ANGEZEIGT. DIE EINGABE KANN UEBER DIE TASTEN <BS> UND <DEL>
;KORRIGIERT WERDEN.
;DIE EINGABE MUSS DURCH <CR> ABGESCHLOSSEN WERDEN.
;
;*************************************************************************

GETCHR:                             
            CALL PTXTCR             ;PRINT TEXT
            .byte LF,"BITTE BUCHSTABE EINGEBEN: ",00

GETC0:
            CALL RCHAR              ;LESE ZEICHEN VON DER TASTATUR
            CALL GROSS              ;WANDLE IN GROSS-BUCHSTABEN
            CPI "A"                 ;< "A"
            JC GETC0                ;JA —> GETC0
            CPI "Z" + 1             ;> "Z"
            JNC GETC0               ;JA —> GETC0
            STA CHAR                ;RETTE ZEICHEN
            CALL WCHAR              ;DRUCKE BUCHSTABEN
GETC1:      
            CALL RCHAR              ;LESE ZEICHEN VON DER TASTATUR
            CALL TSTBS              ;<BS> ODER <DEL> ? -> BS,SPACE,BS
            JZ GETC0                ;<BS> ODER <DEL> ? -> GETC0
            CPI CR                  ;CD ?
            JNZ GETC1               ;NEIN -> GETC1
            LDA CHAR                ;ZEICHEN NACH A
            RET                     ;

;*************************************************************************
;UNTERPROGRAMM "REFPCHR"
;
;SETZT DAS ZEICHEN IM AKKU B-MAL IM SPEICHER EIN. HL DIENT ALS ZEIGER
;UND WIRD NACH JEDEM EINSETZEN UM EINS ERHOEHT.
;
;WERTE BEIM AUFRUF:     A = EINZUSETZEMHES ZEICHEN
;                       B = ANZAHL (WIE OFT EINSETZEN)
;                      HL = ZEIGER AUF ERSTE EINSETZ-STELLE
;
;WERTE NACH RETURN:     B = 0
;                      HL = ZEIGER AUF LETZTE EINSETZ-STELLE + EINS
;
;*************************************************************************

REPCHR:
            MOV M,A                 ;SETZE ZEICHEN EIN
            INX H                   ;STELLE ZEIGER WEITER
            DCR B                   ;ALLE ZEICHEN EINGESETZT ?
            JNZ REPCHR              ;NEIN -> REPCHR
            RET                     ;JA -> RETURN

;*************************************************************************
;UNTERPROGRAMM "WAITSPACE"
;
;WARTESCHLEIFE, BIS <SPACE> BETAETIGT WIRD.
;
;WERTE BEIM AUFRUF:     ---
;
;WERTE NACH RETURN:     A = 20H (ASCII SPACE)
;
;*************************************************************************

WAITSP:
            CALL RCHAR              ;LESE ZEICHEN VON TASTATUR
            CPI " "                 ;SPACE ?
            JNZ WAITSP              ;NEIN —> WAITSP
            RET                     ;JA —> RETURN

;*************************************************************************
;UNTERPROGRAMM "TSTBS"
;
;PRUEFT, OB DAS ZEICHEN IM AKKU = 08H (BACKSPACE) ODER 7FH (DELETE) IST
;
;WENN JA, WIRD DIE ZEICHENFOLGE "BACKSPACE, SPACE, BACKSPACE" AUSGEGEBEN
;UND DAS ZERO-FLAG WIRD GESETZT.
;
;WERTE BEIM AUFRUF:     A = ZU PRUEFENDES ZEICHEN
;
;WERTE NACH RETURN:     (WENN NICHT BS ODER DEL)   ! (WENN BS ODER DEL)
;                       -----------------------------------------------
;                       A = ZU PRUEFENDES ZEICHEN  ! A = 0
;                       Z-FLAG = 0 (NICHT GESETZT) ! Z-FLAG = 1 (GESETZT)
;
;*************************************************************************

TSTBS:
            CPI BS                  ;BS ?
            JZ TSTBS0               ;JA —> TSTBS0
            CPI DEL                 ;DEL ?
            RNZ                     ;WEDER BS NOCH DEL -> RET
TSTBS0:
            CALL PTXT               ;PRINT TEXT
            .byte BS,SPACE,BS,00
            XRA A                   ;SET ZERO-FLAG
            RET

;*************************************************************************
;UNTERPROGRAMM "PPLUS"
;
;GIBT DAS ZEICHEN "+" AUS
;
;*************************************************************************

PPLUS:
            CALL PTXT               ;PRINT "+"
            .byte "+",00
            RET

;*************************************************************************
;UNTERPROGRAMM "PLINE"
;
;GIBT DAS ZEICHEN AUS. DIE ANZAHL DER STRICHE, DIE AUSGEGEBEN WERDEN
;SOLLEN, MUSS IM D-REGISTER STEHEN.
;
;*************************************************************************

PLINE:
            CALL PTXT               ;PRINT TEXT
            .byte "-",00            
            DCR D                   ;NOCH EIN "-" ?
            JNZ PLINE               ;JA -> PLINE
            RET                     ;NEIN -> FERTIG

;*************************************************************************
;UNTERPROGRAMM "CRLF"
;
;GIBT DIE ZEICHENFOLGE CR, LF AUS
;
;WERTE BEIM AUFRUF:     -----
;
;WERTE NACH RETURN:     -----
;
;*************************************************************************

; Kein Ersatz durch MAT85-Routine CRLF, da CRTTEST enthalten

CRLF:
            CALL PTXTCR             ;PRINT CR,LF
            .byte 00
            RET

;*************************************************************************
;UNTERPROGRAMM "UMG"
;
;PRUEFT, OB DAS DOS ERWEITERT IST UND DAS UMGEHUNGSFLAG "EDH" GESETZT IST.
;
;WERTE BEIM AUFRUF:     HL = ZEIGER AUF POSITION DES UMGEHUNGSFLAGS
;
;REAKTION   FLAG   =    EDh --> SPRUNG NACH (HL)+1 (EIN BYTE HINTER DEM FLAG)
;
;           FLAG   <>   EDh --> HL = HL - 800h
;                               ERNEUTER TEST
;                               WENN "EDH" --> SPRUNG WIE OBEN
;                               WENN NICHT "EDH" --> RETURN
;
;*************************************************************************

UMG:
            MVI A,$ED               ;UMGEHUNGS-FLAG 
UMG1:
            CMP M                   ;UMGEHUNGS-FLAG GESETZT ?
            JZ UMG0                 ;JA —> UMG0

            PUSH B                  ;RETTE BC
            LXI B,$F800             ;BERECHNE ADRESSE DES NAECHSTEN FLAGS
                                    ; -800
            DAD B                   ;
            POP B                   ;RESTORE BC
            CMP M                   ;UMGEHUNGS-FLAG GESETZT ?
            RNZ                     ;NEIN -> RETURN
UMG0:
            INX H                   ;HL ZEIGT AUF SPRUNG-ZIEL
            PCHL                    ;SPRINGE NACH (HL)

;*************************************************************************
;UNTERPROGRAMM "INTINT"
;
;INITIALISIERT DEN RAM-VEKTOR FUER DEN RST5.5-INTERRUPT AUF "JMP ISR"
;
;*************************************************************************

INTINT:
            MVI A,JUMP              ;LADE OP-CODE JMP
            STA RSTVEK              ;EINSETZEN
            LXI H,ISR               ;ZEIGER AUF ISR
            SHLD RSTVEK+1           ;IN RST-VEKTIOR EINSETZEN
            MVI A,IMASK             ;INTERRUPT-MASKE
            SIM                     ;SETZEN
            EI                      ;ENABLE INTERRUPT
            RET                     ;

;
;************************************************************************
;*                                                                      *
;*                      INTERRUPT-SERVICE-ROUTINE                       *
;*                                                                      *
;************************************************************************
;
;NACH DER AUSFUEHRUNG EINES KOMMANDOS LOEST DER FDC EINEN INTERRUPT AUS
;UND DIE CPU VERZWEIGT DANN ZU DIESER ROUTINE.
;
;DA SICH DIE CPU BEIM AUFRUF DER ISR DIE ADRESSE DES UNTERBROCHENEN PRO-
;GRAMMS IM STACK MERKT, WUERDE DIESES PROGRAMM NACH DEM RETURN-BEFEHL
;(IN DER ISR) FORTGESETZT.
;
;DURCH DEN BEFEHL "POP PSW" WIRD DIE RUECKSPRUNG-ADR ZUM UNTERBROCHENEN
;PROGRAMM AUS DEM STACK ENTFERNT. BEDINGT DURCH DIE STRUKTUR DES BFZ-
;MINI-DOS TRITT EIN INTERRUPT NUR DANN AUF, WENN DIE CPU EIN UNTERPROGRAMM
;ABARBEITET. WIRD NUN (NACH "POP PSW") DER RETURN-BEFEHL AUSGEFUEHRT, SO
;KEHRT DIE CPU INS HAUPTPROGRAMM ZURUECK.
;
;DAS INTERRUPT-SIGNAL, DAS VOM FDC AUSGEGEBEN WIRD, WIRD DURCH DAS
;LESEN DES FDC-STATUS ABGESCHALTET. DA ES DABEI ABER ZU ZEIT-PROBLEMEN
;KOMMEN KANN, WIRD IN DER ISR DER STATUS SOLANGE GELESEN BIS DER FDC
;NICHT—BUSY IST..
;
;DER STATUS STEHT NACH DEM RETURN IM AKKU UND IM E-REGISTER
;ER WIRD AUSSERDEM IM RAM UNTER "LASTST" GESPEICHERT. DAS BFZ-MINI-DOS
;NUTZT DIESEN GESPEICHERTEN WERT NICHT. ER KANN ABER VON ANDEREN
;PROGRAMMEN VERWENDET WERDEN.

;WERTE BEIM AUFRUF:     ---
;WERTE NACH RETURN:     A = STATUS
;                       E = STATUS
;
;*************************************************************************

ISR:
            POP PSW                 ;SAEUBERE STACK
                                    ;URSPRUENGLICHE RUECKSPRUNGADRESSE ENTFERNEN
ISR0:
            IN FDCSTAT              ;LESE STATUS, LOESCHE INTERRUPT-SIGNAL
            MOV E,A                 ;STATUS NACH E
            RAR                     ;BUSY ?
            JC ISR0                 ;JA —> ISR0 (LESE STATUS ERNEUT)
            MOV A,E                 ;A = STATUS
            STA LASTST              ;RETTE STATUS
            EI                      ;ENABLE INTERRUPT
            RET                     ;RETURN (UEBER STACK - 1)

;*************************************************************************
;VEKTOR-TABELLE AUF DIE FEHLER-MELDUNGEN
;DIE ZIFFER GIBT DEN FEHLER-CODE AN
;*************************************************************************

ERRVEK:
            .byte 16                ;MAXIMALER FEHLERCODE
            .word ERR0
            .word ERR1
            .word ERR2
            .word ERR3
            .word ERR4
            .word ERR5
            .word ERR6
            .word ERR7
            .word ERR8
            .word ERR9
            .word ERR10
            .word ERR11
            .word ERR12
            .word ERR13
            .word ERR14
            .word ERR15
            .word ERR16
            .word ERR17

;*************************************************************************
;FEHLERMELDUNGEN
;DIE ZIFFER HINTER DEM LABEL GIBT DEN FEHLER-CODE AN
;*************************************************************************

ERR0:
            .textz "FALSCHE EINGABE"
ERR1:
            .textz "RUECKSTELL-FEHLER"
ERR2:
            .textz "SCHREIB-FEHLER"
ERR3:
            .textz "LAUFWERK NICHT BEREIT"
ERR4:
            .textz "DISKETTE SCHREIBGESCHUETZT"
ERR5:
            .textz "PRUEF-FEHLER"
ERR6:
            .textz "SUCH-FEHLER"
ERR7:
            .textz "LESE-FEHLER"
ERR8:
            .textz "DISKETTE VOLL"
ERR9:
            .textz "UNERLAUBTER NAME"
ERR10:
            .textz "FILE > 65535 (DEZ.) BYTES"
ERR11:
            .textz "FILE NICHT IM VERZEICHNIS"
ERR12:
            .textz "FALSCHER FILE-TYP"
ERR13:
            .textz "DIRECTORY-FEHLER"
ERR14:
            .textz "SPEICHER-FEHLER"
ERR15:
            .textz "SPEICHERPLATZ AUF DER DISKETTE ZU KLEIN"
ERR16:
            .textz "PROGRAMM-SPEICHER LEER"
ERR17:
            .textz "UNGUELTIGER FEHLER-CODE"
 
;*************************************************************************
; DATEITYPEN
;*************************************************************************

TYPT:                               ;Verschiedene Dateitypen
            .byte 04                ;Anzahl der verschiedenen Dateitypen
            .byte "MAT"             ;MAT85-Systemcode
            .byte "SPS"             ;SPS-Programme
            .byte "BAS"             ;BASIC-Programme
            .byte "???"             ;Unbekannter Dateitypen

;*************************************************************************
; VERSATZTABELLE
;*************************************************************************

VERTAB:
            .byte 1,5,2,6,3,7,4,8   ;REIHENFOLGE DER EINZELNEN SEKTOREN

;*************************************************************************
; ENDE MINI-DOS
;*************************************************************************

            .byte $FF,$FF           ;Ende Mini-DOS
                                    ;Ohne Bedeutung

;*************************************************************************
; RAM-Reservierungen
;*************************************************************************

;           .org $F800
SECB:       .equ  $F800           ; DS 512, Byte Sektorpuffer
LAENGE:     .equ  $FA00           ; WORD, Laenge des Files
PTEINT:     .equ  $FA02           ; WORD, Zeiger fuer TEINIT
ZAEHL:      .equ  $FA04           ; BYTE, Zaehler
TEINT:      .equ  $FA05           ; WORD, Eintrag 1
                                    ; WORD, Eintrag 2
                                    ; WORD, Eintrag 3
                                    ; WORD, Eintrag 4
                                    ; WORD, Eintrag 5
                                    ; WORD, Eintrag 6
                                    ; WORD, Eintrag 7
                                    ; WORD, Eintrag 8
                                    ; WORD, Eintrag 9
                                    ; WORD, Eintrag 10
                                    ; WORD, Eintrag 11
                                    ; WORD, Eintrag 12
                                    ; WORD, Eintrag 13
                                    ; WORD, Eintrag 14
                                    ; WORD, Eintrag 15
                                    ; WORD, Eintrag 16

PTVORH:     .equ  $FA25           ; WORD, Zeiger fuer TVORH
ZAEHLV:     .equ  $FA27           ; BYTE, Zaehler
TVORH:      .equ  $FA28           ; WORD, Eintrag 1
                                    ; WORD, Eintrag 2
                                    ; WORD, Eintrag 3
                                    ; WORD, Eintrag 4
                                    ; WORD, Eintrag 5
                                    ; WORD, Eintrag 6
                                    ; WORD, Eintrag 7
                                    ; WORD, Eintrag 8
                                    ; WORD, Eintrag 9
                                    ; WORD, Eintrag 10
                                    ; WORD, Eintrag 11
                                    ; WORD, Eintrag 12
                                    ; WORD, Eintrag 13
                                    ; WORD, Eintrag 14
                                    ; WORD, Eintrag 15
                                    ; WORD, Eintrag 16

;*************************************************************************
ZWSP1:      .equ  $FA48             ; WORD, Zwischenspeicher
ZWSP2:      .equ  $FA4A             ; WORD, Zwischenspeicher
ZWSP3:      .equ  $FA4C             ; WORD, Zwischenspeicher
ZWSP4:      .equ  $FA4E             ; WORD, Zwischenspeicher
REST:       .equ  $FA50             ; WORD, Rest-Laenge eines zu speichernden Files
SPUR:       .equ  $FA52             ; BYTE, Zwischenspeicher fuer Spur-Nummer (0-79)
CHAR:       .equ  $FA53             ; BYTE, Zwischenspeicher fuer Eingabe-Zeichen
DSPLD:      .equ  $FA54             ; BYTE, Zwischenspeicher FLAG (00   = Suche Directory-Eintrag)
                                    ;                              Sonst: Display Directory)
LCOUNT:     .equ  $FA55             ; BYTE, Zwischenspeicher Zeilenzaehler fuer Directory-Anzeige

VERPTR:     .equ  $FA56             ; WORD, Zwischenspeicher fuer Zeiger auf Versatztabelle
ERRRET:     .equ  $FA58             ; WORD, Returnadresse von Error-Routine
ERRP:       .equ  $FA5A             ; WORD, Adresse des letzten Fehlers
DOSRET:     .equ  $FA5C             ; WORD, Return-Adresse von DOS
PTYPT:      .equ  $FA5E             ; WORD, Zeiger auf TYP-Tabelle
PEVT:       .equ  $FA60             ; WORD, Zeiger auf Error-Vektor-Tabelle
PVNR:       .equ  $FA62             ; WORD, Zeiger auf Versionsnummer
PTZZ:       .equ  $FA64             ; WORD, Zeiger auf zulaessige Zeichen
PMENUE:     .equ  $FA66             ; WORD, Zeiger auf Kommando-Liste

XSAV1:      .equ  $FA68             ; BYTE, OP-Code
                                    ; WORD, Adresse
XSTSP:      .equ  $FA6B             ; BYTE, OP-Code
                                    ; WORD, Adresse
XDIR:       .equ  $FA6E             ; BYTE, OP-Code
                                    ; WORD, Adresse
XGP1:       .equ  $FA71             ; BYTE, OP-Code
                                    ; WORD, Adresse
XGP2:       .equ  $FA74             ; BYTE, OP-Code
                                    ; WORD, Adresse
XGP3:       .equ  $FA77             ; BYTE, OP-Code
                                    ; WORD, Adresse
XLAD1:      .equ  $FA7A             ; BYTE, OP-Code
                                    ; WORD, Adresse
XLAD2:      .equ  $FA7D             ; BYTE, OP-Code
                                    ; WORD, Adresse
XERR:       .equ  $FA80             ; BYTE, OP-Code
                                    ; WORD, Adresse
EFROM:      .equ  $FA83             ; BYTE, ENTERED FROM gibt auskunft darueber
                                    ; von wo das DOS aufgerufen wurde
                                    ; 01 = MAT85
                                    ; 02 = SPS
                                    ; 03 = BASIC
                                    ; 04 = ???
                                    ; 
SEITE:      .equ  $FA84             ; BYTE, Zwischenspeicher fuer Seitennummer
                                    ; Seite = 0h, Seite 1 = 1h
SELMSK:     .equ  $FA85             ; BYTE, Zwischenspeicher fuer Select-Maske
                                    ; Laufwerk A = 1h, Laufwerk B = 2h
LSEL:       .equ  $FA86             ; BYTE, LAST SELECT Wert, der als letzter an
                                    ; "PORT" ausgegeben wurde
LASTST:     .equ  $FA87             ; BYTE, Letzter Status
RETRY:      .equ  $FA88             ; BYTE, Zwischenspeicher fuer VERIFY-Zaehler

;*************************************************************************
; Anhang zm BFZ-Mini-DOS
; DOS-Erweiterungen 
;
;     Adresse (Stufe 1) Adresse (Stufe 2) Inhalt      Bemerkung
;           5000            5800            ED            1
;           5801            C3            2
;           5002            5802            XX            
;           5003            5803            XX            
;           5004            5804            ED            3
;           5005            5805            C3            4
;           5006            5806            XX            
;           5007            5807            XX            
;           5008            5808            ED            5
;           5009            5809            C3            6
;           500A            580A            XX            
;           500B            580B            XX            
;           500C            580C            ED            7
;           500D            580D            XX            8
;           500E            580E            XX            9
;           500F            580F            ED            10
;           5010            5810            XX            11
;           5011            5811            XX            12
;
; ERLAEUTERUNG:
;
; 1.  ERKENNT MAT85 EINEN BEFEHL NICHT, UND ENTHAELT DIE UNTER 1. ANGEGEBENE 
;     SPEICHERZEILE DEN WERTE "ED", SO FUEHRT DAS PROGRAMM DEN UNTER 
;     2. ANGEGEBENEN SPRUNG-BEFEHL AUS. DER IN DER JETZIGEN DOS-VERSION 
;     ENTHALTENE TEST AUF "F" WIRD UMGANGEN.
;
; 2.  SIEHE 1. ZUSAETZLICHE WIRD EIN UNBEKANNTES MAT85-KOMMANDO EINGEGEBEN,
;     SO PRUEFT DAS DOS, OB ES SICH UM DAS "F"-KOMMANDO HANDELT. IST DIES
;     NICHT DER FALL, SO PRUEFT ES, OB UNTER 2. (STUFE 1> DER WERT "C3" STEHT.
;     WENN JA, WIRD DER SPRUNG-BEFEHL AUSGEFUERT. NEIN —> FEHLERMELDUNG
;
; 3.  ERKENNT SP1 (AUSSER BASIC —> SPS, MAT85+ EPROMMER) EINEN BEFEHL NICHT,
;     UND ENTHAELT DIE UNTER 3. ANGEGEBENE SPEICHERZEILE DEN WERT "ED", SO
;     FUEHRT DAS PROGRAMM DEN UNTER 4. ANGEGEBENEN SPRUNG-BEFEHL AUS. DER
;     IN DER JETZIGEN DOS-VERSIQN VORHANDENE TEST (WURDE "F" VON SPS AUS
;     EINGEGEBEN > WIRD UMGANGEN.
;
; 4.  SIEHE 3. ZUSAETZLICHE WIRD EIN UNBEKANNTES SP1 EINGEGEBEN, SO PRUEFT
;     DAS DOS, OB ES SICH UM DAS "F"-KOMMANDO HANDELT UND OB DIESES KOMMANDO
;     VON SPS AUS EINGEGEBEN WURDE. IST ES NICHT DAS "F"-KOMMANDO ODER WURDE
;     ES NICHT VON SPS AUS EINGEGEBEN, PRUEFT DAS DOS, OB DIE UNTER 4. (STUFE 1)
;     ANGEGEBENE ADRESSE "C3" ANTHAELT. WENN JA, WIRD DER SPRUNG AUSGEFUEHRT.
;     WENN NEIN, ERFOLGT EINE FEHLERMELDUNG.
;
; 5.  ERKENNT BASIC EINEN BEFEHL NICHT, UND ENTHAELT DIE UNTER 6. ANGEGEBENE
;     SPEICHERZEILE DEN WERT "ED", SO FUEHRT DAS PROGRAMM DEN UNTER 4. ANGE—
;     GEBENEN SPRUNG-BEFEHL. AUS. DER IN DER JETZIGEN DOS-VERSIGN VORHANDENE 
;     TEST (WURDE "FLOPPY" IM DIREKTMODUS EINGEGEBEN) WIRD UMGANGEN.
;
; 6. SIEHE 5. ZUSAETZLICHE WIRD EIN UNBEKANNTES BASIC-KOMMANDO EINGEGEBEN,
;     SO PRUEFT DAS DOS. OB ES DAS "FLOPPY"-KOMMANDO IST UND OB ES IM DIREKT-
;     MODUS EINGEGEBEN WURDE. TRIFFT EINE DER BEIDEN BEDINGUNGEN NICHT ZU, SO
;     PRUEFT DAS DOSv OB DIE UNTER 6. (STUFE 1) ANGEGEBENE ADRESSE "C3" ENT-
;     HAELT. WENN JA, WIRD DER SPRUNG AUSGEFUEHRT. WENN NEIN, ERFOLGT EINE
;     FEHLERMELDUNG.
;
; 7. EIN "ED" IN DER UNTER 7. ANGEGEBENEN ADRESSE ZEIGT DEM DOS AN, DASS NICHT
;     DIE VEKTOR-TABELLE DER GRUND-VERSION GENUTZT WERDEN SOLL. DIE ADRESSE DER
;     NEUEN VEKTOR-TABELLE MUSS UNTER 8. UND 9. ANGEGEBEN SEIN.
;
; 8.  LOW-BYTE DER ADRESSE FUER DIE NEUE VEKTOR-TABELLE
;
; 9.  HIGH-BYTE DER ADRESSE FUER DIE NEUE VEKTOR-TABELLE
;
;10.  EIN "ED" IN DER UNTER 10. ANGEGEBENEN ADRESSE ZEIGT DEM DOS AN, DASS NICHT
;     DIE INFO-TABELLE DER GRUND-VERSION GENUTZT WERDEN SOLL. DIE ADRESSE DER
;     NEUEN INFO-TABELLE MUSS UNTER 11. UND 12. ANGEGEBEN SEIN.
;
;11.  LOW-BYTE DER ADRESSE FUER DIE NEUE INFO-TABELLE
;
;12.  HIGH-BYTE DER ADRESSE FUER DIE NEUE INFO-TABELLE
;
; DIE ERWEITERUNGS-STUFE 2 IST DER STUFE 1 UEBERGEORDNET.
; EINE ERWEITERUNG MUSS MINDESTENS EIN "ED" BZW. MINDESTENS EINEN "C3 XX XX"-
; BEFEHL ENTHALTEN.

;
;---------------------------------------------------------------------------------------------------
;
; ######## ##    ## ########  ########    ##     ## #### ##    ## ####         ########   #######   ######
; ##       ###   ## ##     ## ##          ###   ###  ##  ###   ##  ##          ##     ## ##     ## ##    ##
; ##       ####  ## ##     ## ##          #### ####  ##  ####  ##  ##          ##     ## ##     ## ##
; ######   ## ## ## ##     ## ######      ## ### ##  ##  ## ## ##  ##  ####### ##     ## ##     ##  ######
; ##       ##  #### ##     ## ##          ##     ##  ##  ##  ####  ##          ##     ## ##     ##       ##
; ##       ##   ### ##     ## ##          ##     ##  ##  ##   ###  ##          ##     ## ##     ## ##    ##
; ######## ##    ## ########  ########    ##     ## #### ##    ## ####         ########   #######   ######
;
;---------------------------------------------------------------------------------------------------
;

Zusätzliche Informationen

Dokumente