*******************************************************************************
* Assemblierbare Version der Bank 0 der DSR des Atronic FDC,
* basierend auf einem Hexdump der V1.1
*
* Dieses File erzeugt ein bitidentisches Binärfile zum EPROM des Original FDC,
* inklusive der leeren Stellen des EPROMs, die auch hier >FF aufweisen.
*
* Es wurde mit XAS99 im strict Mode assembliert, sollte daher beim assemblieren
* mit E/A ebenso korrekt durchlaufen, was z.Zt. noch nicht verifiziert wurde.
*
* Kommando: xas99.py -s -b -R <filename>
*
* Letzte Aenderung: 2025-10-03 Christopher Winter
*
*******************************************************************************
	AORG >4000
***************************************************************************
* ROM Header
***************************************************************************
	DATA >AA02	DSR-ID und Version
	BYTE >00	Anzahl User Programs - >00 bei DSR ROMs!
	BYTE >00	reserviert,muss >00 sein
	DATA PWRLNK
	DATA >0000 	reserviert für User Program - >0000 bei DSR!
	DATA DSRLNK	Aufruf mit DATA >8
	DATA SBRLNK	Aufruf mit DATA >A oder 10
	DATA >0000	kein INTLNK
	DATA >0000	reserviert für Basic SBR - >0000 bei DSR!
***************************************************************************
* Subroutinen Einsprungtabelle
***************************************************************************
SBRLNK	DATA SBRLK2	Nächste Funktion
	DATA SBR10	Einsprung
	DATA >0110	Funktion 10 (>A) - Sektor lesen/schreiben
SBRLK2	DATA SBRLK3
	DATA SBR11
	DATA >0111	Funktion 11 (>B) - Disk formatieren
SBRLK3	DATA SBRLK4
	DATA SBR12
	DATA >0112	Funktion 12 (>C) - Dateischutz ändern
SBRLK4	DATA SBRLK5
	DATA SBR13
	DATA >0113	Funktion 13 (>D) - Datei umbenennen
SBRLK5	DATA SBRLK6
	DATA SBR14
	DATA >0114	Funktion 14 (>E) - File Direkttransfer Input
SBRLK6	DATA SBRLK7
	DATA SBR15
	DATA >0115	Funktion 15 (>F) - File Direkttransfer Output
SBRLK7	DATA SBRLK8
	DATA SBR16
	DATA >0116	Funktion 16 (>10) - Puffer Allokation
SBRLK8	DATA SBRLK9
	DATA SBRFLS	Einsprung "CALL FILES"
	BYTE >05	Textlänge
	TEXT 'FILES'	Name der Subroutine
SBRLK9	DATA SBRLKA
	DATA SBRMGR	Einsprung "CALL MGR"
	BYTE >03
	TEXT 'MGR'
SBRLKA	DATA >0000	Listenende,keine weiteren Einträge
	DATA SBRMGR	Einsprung "CALL MANAGER" (== CALL MGR)
	BYTE >07
	TEXT 'MANAGER'
***************************************************************************
* Power-Up Einsprungtabelle
***************************************************************************
PWRLNK	DATA >0000 	keine weiteren Einträge
	DATA POWRUP	Einsprungpunkt
	DATA >0000	nicht erforderlich!
************************************************************************************
* I/O Funktionen Einsprungtabelle
************************************************************************************
DSRLNK	DATA DSRLK2
	DATA DSRA
	BYTE >03
	TEXT 'DSK'
DSRLK2	DATA DSRLK3
	DATA DSRB
	BYTE >04
	TEXT 'DSK1'
	EVEN
DSRLK3	DATA DSRLK4
	DATA DSRC
	BYTE >04
	TEXT 'DSK2'
	EVEN
DSRLK4	DATA DSRLK5
	DATA DSRD
	BYTE >04
	TEXT 'DSK3'
	EVEN
DSRLK5	DATA >0000 	keine weiteren Einträge
	DATA DSRE
	BYTE >04
	TEXT 'DSK4'
	EVEN
************************************************************************************
* Power-Up Routine (408E)
*
* Zu diesem Zeitpunkt ist "press any key..." noch nicht angezeigt,
* und es sind noch keine GROM Power-Up Routinen gelaufen.
* Der PAD-Bereich >8304 - >83BF kann benutzt werde,ebenso Register 0-10.
* R6 muss wiederhergestellt bzw. darf nicht benutzt werden!
* Die anderen Register sind wie folge vorbelegt:
* R11	Rückkehradresse
* R12	CRU Basisadresse - Low Byte muss bei Rückkehr >00 sein!
* R13	GROM Read Data Adresse
* R14	System Flags
* R15	VDP Write Address (>8C02)
************************************************************************************
POWRUP	MOV R11,R7	Rückkehr sicherstellen
	STWP R9		zeigt aktuell auf GPLWS (>83E0)
	AI R9,>FF20	minus >E0
	MOV @>70(R9),R0	höchste freie Adresse im VDPRAM. Im PowerUp des FDC ist das i.d.R. noch >3FFF
	MOV R0,R2	Kopie für nachfolgende Initialisierung
	AI R0,>F7D8	minus 2088,entspricht 3 offenen Files, R0 = >37D7
	MOV R0,@>70(R9)	zurückschreiben. Nun ist >37D7 die höchste freie Adresse im VDP
	INC R0		auf das erste reservierte Byte zeigen
	BL @VDPWA	und das als Schreibadresse setzen
	LI R1,>0828	Zähler (2088) aufsetzen
POWRU0	CLR @-2(R15)	und den ganzen Bereich löschen
	DEC R1		fertig?
	JNE POWRU0	nein - weiter
	BL @VDPWA	wieder auf Blockanfang zeigen
	LI R3,>AA03	Init code: Validierung und Anzahl Files
	MOVB R3,@-2(R15)	Schreibe Validierung (>AA)
	NOP
	MOVB R2,@-2(R15)	VDPTOP schreiben (>3F)
	SWPB R2 
	MOVB R2,@-2(R15)	VDPTOP schreiben (>FF)
	NOP
	MOVB R12,@-2(R15)	CRU Basisadresse High Byte (>11)
	SWPB R3 
	MOVB R3,@-2(R15) 	Anzahl Files (3)
	BL @MAINIU
	BL @STKJMP
	DATA L5A04
	CLR @>0054(R9)		I/O mode pointer loeschen
	BLWP @>005A(R9)		R11 wiederherstellen
	DATA >0011
	MOV @FOUR4,@>006C(R9)	>0404 ans Ende des FAC
	RT
*
FOUR4	DATA >0404	Init-Code für DSR-Powerup an Offset>6C
************************************************************************************
* VDPWA - setze VDP Schreibadresse mit R0 (40F8)
************************************************************************************
VDPWA	ORI	R0,>4000
	SWPB	R0 
	MOVB	R0,*R15
	SWPB	R0 
	MOVB	R0,*R15
	RT
************************************************************************************
* Sprung mit Sicherung der Rückkehradresse auf dem VDP Stack (4106)
* 1 Word wird als Parameter (=Sprungziel) übergeben
************************************************************************************
STKJMP	DECT @>0066(R9)		Stackzeiger 2 runter
	MOV @>0066(R9),R10	vorbereiten des Speicherns im VDP RAM
	BLWP @>005a(R9) 
	DATA >0143		Setze R10 als VDP Schreibadresse 
	MOV *R11+,R10		Hole den Sprungvektor und überspringe ihn
	SWPB R11		Low Byte zuerst
	MOVB R11,@-2(R15)	Schreibe die effektive Rückkehradresse
	SWPB R11		High Byte danach
	MOVB R11,@-2(R15) 
	B *R10			Sprung lt. Vektor
************************************************************************************
* Allgemeiner Stack-Rücksprung (4124)
* Auch genutzt als Rückkehrpunkt nach Abschaltung der oberen Bank
************************************************************************************
STKRET	MOV @>0066(R9),R11	Stackpointer
	BLWP @>005a(R9)
	DATA >0162		R11 als Leseadresse setzen
	MOVB @>FBFE(R15),R11	Low Byte zuerst
	SWPB R11
	MOVB @>FBFE(R15),R11	Dann das High Byte
	INCT @>0066(R9)		1 Word auf Stack freigeben
	RT			an gelesene Adress springen
************************************************************************************
* Utility Funktionen,Aufruf per BLWP @>005A(R9) (413E)
* 1 Wort wird als Parameter übergeben
* ACHTUNG: Diese Funktion ist erst nach Aufruf von MAINIT definiert!
*
* Während diese Funktion läuft,ist der WP = >004E(R9) (= >834E bei Standard GPLWS)
* Das heißt,daß R4,R5,R6,R7 und R12 besondere Funktionen haben,und (mit Ausnahme von R12) NICHT VERÄNDERT WERDEN SOLLTEN/DÜRFEN!
* R4	Aktuelle VDP Adresse bzw. Zeiger auf Namenlänge im PAB beim Aufruf
* R5	Zeiger auf Volume ID im VDP-RAM
* R6,R7	Context Switch für die Funktion selbst - TABU!!!
* R12	VDP Stackpointer - der wird in der Tat hier verändert
************************************************************************************
UTLFNC	MOV	R13,R10		alten WS Pointer in R10 sichern
	MOV	*R14+,R8	Argument mittels altem PC nach R8 holen
	MOV	R8,R9
	SRL	R9,4		Funktionscode in R9 ausblenden
	ANDI	R8,>0003	Funktionscode in R8 isolieren
	A R8,R8			mal 2 für Tabellenoffset
	MOV @>1E(R13),R11	Adresse des alten R15,VDPWA
	MOV @UTLTAB(R8),R8	Sprungvektor holen
	B *R8			... und ab nach Kassel
************************************************************************************
* Sprungtabelle für Funktionen 0-3 (4156)
************************************************************************************
UTLTAB	DATA UTIL00	0 - Register auf VDP-Stack sichern
	DATA UTIL10	1 - Register von VDP-Stack wiederherstellen
	DATA UTIL20	2 - VDPWA zum Lesen setzen
	DATA UTIL30	3 - VDPWA zum Schreiben setzen
************************************************************************************
* Utility Funktion 0 (415E)
*
* Sichere bestimmte Register von R0-R11 im VDP-RAM anhand eines Bitmusters,
* das in R9 übergeben wird und aus 12 signifikanten Bits besteht.
* Das höchste Register kommt an die höchste Adresse im Stack.
* Lustigerweise entspricht die Bitfolge nach TI genau den Registern:
* Das höchstwertige Bit (D0) entspricht R0,das niedrigste (D11) R11
* (Zählweise VOR dem Herausschieben des Funktionscodes im niederwertigsten Nibble)
* Registerindex: Jedes gesetzte Bit gibt ein zu rettendes Register an.
* Aufbau:      Bit  11 10  9  8  7  6  5  4  3  2  1  0 Numerierung nach SRL R9,4!
*         Register   0  1  2  3  4  5  6  7  8  9 10 11
* R12	Adresse des Stacks im VDP-RAM
* R11	altes R15 -> VDPWA
* R10	alter WS Pointer
* R9 	Bitmuster,höchste Registernummer rechts
************************************************************************************
UTIL00	AI R10,>0016	Zeiger auf Ende des zu sichernden WS
UTIL01	SRL R9,1	Flag ins Carry herausschieben
	JNC UTIL02	Register nicht sichern
	DECT R12	VDP-Stackadresse (PAD Ofs. >66) runterzählen
	MOV *R10,R8	Registerwert nach R8
	SWPB R12	Stackadresse schreiben
	MOVB R12,*R11	LSByte zuerst
	swpb r12	MSByte
	ORI R12,>4000	Flag "Adresse schreiben"
	movb r12,*r11	Ab dafür
	SWPB R8		LSByte geht zuerst in den Stack
	movb r8,@-2(r11)
	SWPB R8		und das MSByte danach
	movb r8,@-2(r11) 
	MOV R9,R9	noch was zu tun?
	jeq UTIL1X	-> RTWP
UTIL02	DECT R10	Zeiger auf nächstniedrigeres Register
	JMP UTIL01	... und weiter
************************************************************************************
* Komplementärfunkton zu oben - Wiederherstellung von Registern (418A)
* aus dem VDP Stack,in umgekehrter Reihenfolge
************************************************************************************
UTIL10	SLA R9,4	Bitmaske isolieren
UTIL11	SLA R9,1	und stückweise abarbeiten
	JNC UTIL12	dieses Register nicht sichern
	swpb r12
	movb r12,*r11
	swpb r12
	andi r12,>3fff 
	movb r12,*r11 
	nop
	movb @>fbfe(r11),r8	Hole das LSByte
	SWPB R8	an seinen Platz
	movb @>fbfe(r11),r8	Hole das MSByte
	MOV R8,*R10	und ab in den alten WS
	INCT R12	nächste VDP Adresse
	MOV R9,R9	noch was zu tun?
	jeq UTIL1X	-> RTWP
UTIL12	INCT R10	Zeiger auf nächstes Register
	JMP UTIL11	... und weiter
UTIL1X	RTWP	Haben fertig!
************************************************************************************
* VDPWA zum Schreiben setzen,Adresse in einem Register (41B6)
* R9 - Funktionsargument,doppelte (!) Nummer des zu verwendenden Registers
* R13 - alter WS Pointer
************************************************************************************
UTIL30	A R13,R9	Registernummer x2 (R9) zum alten WP addieren
	MOV *R9,R8	Registerinhalt nach R8
	ORI R8,>4000	Flag zum Schreiben einbauen
	jmp UTIL21
************************************************************************************
* VDPWA zum Lesen setzen, Adresse in einem Register (41C0)
* siehe oben
************************************************************************************
UTIL20	A    R13,R9	Registernummer x2 (R9) zum alten WP addieren
	MOV  *R9,R8	Registerinhalt nach R8
	ANDI R8,>3FFF	Adresse zum Lesen setzen
UTIL21	SWPB R8 
	movb r8,*r11 
	swpb r8 
	movb r8,*r11 
	rtwp 
************************************************************************************
* MAIN INIT - Zentrale Initialisierung für I/O Calls und Subroutinen (41D2)
************************************************************************************
MAINIT	INCT R7			Das dem DSRLNK-Call folgende JMP überspringen
MAINIU	MOV  R11,R10		Für Rücksprung sichern
	STWP R9			Kopie GPLWS (>8xE0)
	AI   R9,>FF20		>E0 abziehen
	LI   R0,UTLFNC		Zieladresse für BLWP @>5A(R9)
	MOV  R0,@>005C(R9)	Context Switch Sprungziel
	MOV  R9,R0		Nur Kopie verändern!
	AI   R0,>004E		>8x4E ist der WS für BLWP @>5A(R9)
	MOV  R0,@>005A(R9)	Context Switch Workspace
	MOV  @>0070(R9),R8	Höchste verfügbare Adresse im VDP RAM
MAINI0	INCT R8			Überspringen des >AA als Init-Code
	BL   @VDPRD		Adresse des VDPTOP einer ggf anderen DSR
	MOV  R8,R2		Aktuelle VDP Adresse aufheben
	MOV  R0,R8		vorheriges VDPTOP als Link für nächste Suche
	MOVB @>FBFE(R15),R1	CRU Basisadresse lesen
	CB   R12,R1		Ist das unsere?
	JNE  MAINI0		Nein - weitersuchen
	AI   R8,>FEF6		266 abziehen, zeigt auf Volume Info (>3EF5)
	MOV  R8,@>58(R9)	Zeiger in PAD RAM sichern
	AI   R8,-10		10 abziehen, zeigt auf Disk Drive Info (>3EEB)
	MOV  R8,@>66(R9)	Stackpointer initialisieren, wird bei erster Benutzung de-krementiert
	BLWP @>5A(R9)
	DATA >0100		R7 sichern

MAINI1	MOV @>0056(R9),R7	auf >8x56 steht der VDP-Pointer auf den Unterprogramm- bzw. File-Namen
	mov r7,r3		in R3 sichern
	S @>0054(R9),R7		Device-Name Length davon abziehen
	mov r2,@>0056(r9)	VDP-RAMTOP+2 in @>8x56
	dec r7			R7 zeigt auf die Gesamt-Namenlaenge
	clr r2
	blwp @>005a(r9)
	data >00e2		Wert in R7 setzen
	movb @>fbfe(r15),r2	in R2 steht die Gesamtnamenlaenge
	swpb r2			ins Low-Byte
	s @>0054(r9),r2		Device-Name Length abziehen, R2 enthaelt jetzt die Filenamenlaenge (Laenge incl. Punkt!)
	ai r7,>fff7		R7 minus 9
	mov r7,@>0054(r9)	Pointer auf den I/O-Mode in @>8x54
MAINIX	B *R10			Return über R10 zurück ins Hauptprogramm

*************************************************
* Subroutine File im Output-Mode eroeffnen (4246)
* 2 Referenzen
*************************************************
OPFOUT	BL @STKJMP	Pruefen ob File schon offen ist, Fehler wenn ja, sonst
	DATA L48B0	FDS in einen freien Pufferbereich einlesen
*
* STKJMP Seiteneinsprung (424C)
*
L424C	MOV R4,R4	FDS gefunden?
	JNE OPFONF	Nein - File existiert noch nicht
	BL @STKJMP	Ja - File existiert bereits
	DATA L438C	Alle vom File belegten Sektoren freigeben
	JMP  L42E2	weiter
*
* Seiteneinsprung "Neues File erzeugen" (4258)
*
OPFONF	BL @L45B8	Platz im Sektor 1 Puffer fuer neuen Eintrag schaffen
       SETO R1           Index 'Einen FDS reservieren'
       BL   @STKJMP
       DATA L49A4        Sektor in der Sektor-Bitmap reservieren
       MOV  R0,R0        Nummer des Sektors in R0 zurueck - gleich Null?
       JNE  L426E        Nein - es konnte ein Sektor reserviert werden
       BL   @L4720       File Error,
       DATA >8000        Diskette ist voll
L426E   BLWP @>5A(R9)
       DATA >0103        R8 zum Schreiben setzen
       MOVB R0,@-2(R15)
       SWPB R0
       MOVB R0,@-2(R15)  Sektornummer des neuen FDS in Sektor 1
       SWPB R0
       MOV  @>56(R9),R1  Zeiger auf Filename
       AI   R1,-4        Zeigt nun auf Sektornummer im File-Control Block
       BLWP @>5A(R9)
       DATA >0023        R1 zum Schreiben setzen
       MOVB R0,@-2(R15)
       SWPB R0
       MOVB R0,@-2(R15)  Sektornummer in den Filedaten-Header
       AI   R1,3         auf LW-Nummer zeigen
       BLWP @>5A(R9)
       DATA >0023        R1 wieder setzen
       MOVB R6,@-2(R15)  LW Nr. schreiben
       CLR  R2           Schreib-Index
       INC  R1           Datenzeiger
       BL   @STKJMP
       DATA L47E4        Sektor 1 schreiben
       MOV  @>58(R9),R5  Pufferadresse des Volume-ID Blocks
       CLR  R4           Sektornummer = 0
       BL   @STKJMP
       DATA L47FC        Sektor 0 schreiben, Nr. in R4, Puffer in R5
       MOV  R5,R3        Datenpufferadresse kopieren
       AI   R3,>0101     Zeiger auf Filename Compare-Buffer (FNCB)
       LI   R2,>000A     Schleifenzaehler
L42C6   BLWP @>5A(R9)
       DATA >0062           R3 setzen
       MOVB @>FBFE(R15),R0
       INC  R3
       BLWP @>5A(R9)
       DATA >0023        R1 zum Schreiben setzen
       MOVB R0,@-2(R15)  Wert kopieren
       INC  R1
       DEC  R2           Schleife beendet?
       JNE  L42C6        Nein

L42E2   MOV  @>56(R9),R1  Zeiger auf aktuellen Puffer
       AI   R1,>000A     hinter den Filenamen zeigen
       LI   R2,>00F6     Schleifenzaehler 246 Bytes
       BLWP @>5A(R9)
       DATA >0023        R1 zum Schreiben setzen
L42F4   MOVB R2,@-2(R15)  >00 schreiben
       DEC  R2           den gesamten FDS ausser Filenamen loeschen
       JNE  L42F4
       JMP  L431E        R2 ist null, FDS schreiben, enthaelt bis auf den Filenamen nur Nullen
******************************************************
* Subroutine FDS nach Aenderung zurueckschreiben (42FE)
******************************************************
WRTFDS	MOV  @>56(R9),R5  Zeiger auf Filenamen
	BLWP @>5A(R9)
	DATA >00A2           R5 zum Lesen setzen
       MOVB @>FBFE(R15),R4
       JLT  L4310           High-Bit gesetzt? Ja - schreiben
       JMP  L4324        Nein - Ende, keine Veranlassung da keine [nderung!
L4310   ANDI R4,>7F00     High-Bit loeschen
       BLWP @>5A(R9)
       DATA >00A3
       MOVB R4,@-2(R15)  Wert wieder zurueck
L431E   CLR  R2
       B    @L47EE       aktuellen FDS wieder schreiben
L4324   B    @STKRET       Routine beendet

*********************************************************
* Routine Abschluss von File-Operationen (4328)
*********************************************************
FOPEND	BL   @STKJMP
       DATA WRTDBU
       BL   @STKJMP
       DATA WRTFDS	FDS zurueckschreiben wenn notwendig
L4334       MOV  @>56(R9),R5  Zeiger auf 1. Byte im Filenamen
       CLR  R6
       BLWP @>5A(R9)
       DATA >00A3
       MOVB R6,@-2(R15)  Erste Byte des Namens loeschen - Block ist frei!
       B    @L4780       Volume-ID update und Ende

***********************************************************************
* Subroutine Datenpuffer bei Bedarf auf Diskette zurueckschreiben (4348)
************************************************************************
WRTDBU	MOV  @>56(R9),R4  Zeiger auf aktuellen Filenamen im FDS-Puffer
       DEC  R4           auf LW-Nr. zeigen
       BLWP @>5A(R9)
       DATA >0082           R4 setzen
       MOVB @>FBFE(R15),R1  LW-Nr. lesen
       JLT  L435C           High-Bit gesetzt
       JMP  L4388           High-Bit nicht gesetzt, Ende
L435C   ANDI R1,>7F00        High-Bit loeschen
       BLWP @>5A(R9)
       DATA >0083        R4 wieder setzen
       MOVB R1,@-2(R15)  Wert mit geloeschtem High-Bit schreiben
       AI   R4,-5        Zeiger auf File-Record richten
       BLWP @>5A(R9)
       DATA >0082           R4 setzen
       MOVB @>FBFE(R15),R3
       SWPB R3
       MOVB @>FBFE(R15),R3  File-Record lesen
       SWPB R3              Richtig ordnen
       MOV  R4,R7           VDP-Zeiger kopieren
       AI   R7,>0106     Zeiger auf den Datenbereich
       JMP  L43FC        Datensektor schreiben
L4388   B    @STKRET       Ende

***************************************************************
* Subroutine Sektor-Bitmap in Sektor 0 nach 'DELETE FILE' aktualisieren (438C)
******************************************************************
L438C   MOV  @>56(R9),R2     Pufferadresse des Directory-Sektors des Files
       AI   R2,>000C        +12, auf Filetyp/Fileschutz zeigen
       BLWP @>5A(R9)
       DATA >0042           R2 zum Lesen setzen
       MOVB @>FBFE(R15),R0  Filetyp/-schutz lesen
       ANDI R0,>0800        Protection Bit isolieren
       JEQ  L43AA           Bit ist nicht gesetzt
       BL   @L4720          Bit ist gesetzt!
       DATA >2000           gibt Status = 1, Write Protected!
L43AA   MOV  @>56(R9),R8
       AI   R8,>001C        +28, auf Pointer Block 1 zeigen
       SETO R4              mitlaufender Korrekturzaehler fuer Sektoren/Cluster
L43B4   BL   @L4964          Cluster-Daten holen, R1= Startsektor, R2= Offset
       AI   R8,3            auf naechsten Pointer-Block zeigen
       MOV  R1,R1           Sektor Nr. = 0 ? (Ende des Files)
       JEQ  L43D8
       MOV  R2,R0           Record Offset kopieren
       S    R4,R2           Sektoranzahl im Cluster gewinnen
       MOV  R0,R4           der Offset ist im naechsten Lauf der Subtrahend
       BL   @STKJMP
       DATA L4A70           Sektor 0 anhand der Clusterdaten bearbeiten.
       MOV  R8,R1           Pointer in den File-Dir-Puffer nach R1
       S    @>56(R9),R1     Basisadresse des Puffers abziehen
       CI   R1,>0100        Pufferende erreicht?
       JNE  L43B4           Nein
L43D8   B    @STKRET          Ja, Ende

*********************************************
* Subroutineneinsprung Datensektor lesen (43DC)
*********************************************
L43DC   BL   @VDPR56
       DATA >000E        Wert im VDP *R8 + DATA nach R0 (Wort) holen
       C    R0,R3        Sektoranzahl im FDS (R0) mit dem Sektor-Offset (R3) vergleichen
       JH   L43EC        R0 groesser als R3 - O.K.
       BL   @L4720       Nein - File Error
       DATA >A000        ueber EOF gelesen od. File ist geschlossen
L43EC   BL   @STKJMP
       DATA SRCFBK        File-Block suchen
       A    R1,R4        Sektornummer (absolut) berechnen
       SETO R2           Leseindex
L43F6   MOV  R7,R5        aktuelle VDP-Pufferadresse
       B    @L47FC       Sektor lesen/schreiben (siehe R2), phys. Sek.Nr. in R4, Pufferadr. in R5

*****************************************************
* Subroutineneinsprung Datensektor schreiben (43FC)
****************************************************
L43FC   BLWP @>5A(R9)
       DATA >8100        R0 und R7 sichern
       BL   @STKJMP
       DATA L4412        Sektornummer des Eintrages (Datensektor) aus dem File-Record Eintrag ermitteln
       BLWP @>5A(R9)
       DATA >8101        RO und R7 wiederherstellen
       CLR  R2           Schreibindex
       JMP  L43F6        Sektor schreiben

********************************************************************************
* Subroutine Platz eines (neuen) Eintrags im File suchen (4412)
*
* Diese Routine liefert die Sektornummer (absolut) des Sektors, in den ein
* Eintrag (Record) geschrieben werden soll in R4 zurueck. Bestand der Sektor noch
* nicht, so werden Sektor-Bitmap und Block-Link Map aktualisiert.
* R3 (Input): Sektor-Offset des aktuellen Eintrags; Quelle fuer R3 ist i.A. das
* erste Wort im File-Control Header.
* Existiert noch kein Block-Link Eintrag, so werden diese entsprechend dem
* Fuellungszustand der Diskette bis zum aktuellen Sektor-Offset in R3 erzeugt!
******************************************************************************
L4412   BL   @VDPR56       Sektoranzahl aus dem FDS lesen
       DATA >000E
       C    R0,R3        Sektoranzahl mit dem aktuellen Sektor-Offset des Eintrags vergleichen
       JH   L44AA        Sektoranzahl groesser - bestehender Sektor!
       MOV  R0,R0        Sektoranzahl = 0?
       JEQ  L4422        Ja - File ist neu eroeffnet!
       DEC  R0           Nein - Append-Mode!
L4422   MOV  R3,R5        Sektor-Offset, wo geschrieben werden soll, kopieren
       MOV  R0,R3        Maximaler Sektor-Offset im File
       BL   @STKJMP       Fileblock ermitteln, in den der Eintrag kommen soll,
       DATA SRCFBK        in R1 wird der Startsektor dieses Blocks geliefert.
       BLWP @>5A(R9)
       DATA >4000        R1 sichern
       A    R4,R1        Sektor-Offset auf den Startsektor addieren
       MOV  R5,R4        Sektor-Offset des Eintrages kopieren
L4436   BL   @STKJMP
       DATA L49A4        Belegte Sektoren in der Sektor-Bitmap eintragen
       MOV  R0,R0        War noch Platz?
       JNE  L4448        Ja
       MOV  R2,R5        Nein!
       BL   @L44B6       Fehler, Diskette voll!
       JMP  L447E
L4448   MOV  R1,R1
       JEQ  L448C
       INC  R1
       C    R0,R1
       JEQ  L448A
       BLWP @>5A(R9)
       DATA >4001        R1 wiederherstellen
       BLWP @>5A(R9)
       DATA >A000        R0 und R2 sichern
       BL   @L4980       Cluster-Daten in den Block-Link Bereich
       BLWP @>5A(R9)
       DATA >A001        R0, R2 wiederherstellen
       AI   R8,>0003     Zeiger auf naechsten Block
       MOV  R8,R1        kopieren
       S    @>56(R9),R1  Position des Eintrags berechnen
       CI   R1,>0100     Ende des Puffers?
       JNE  L4482        Nein
       BL   @STKJMP       Ja - belegte Sektoren aus der Sektor-Bitmap streichen
       DATA L4A6A
L447E   B    @L48D6       Fehler, Diskette voll!
L4482   MOV  R0,R1
       BLWP @>5A(R9)
       DATA >4000        R1 sichern
L448A   JMP  L449A
L448C   BLWP @>5A(R9)
       DATA >4001        R1 wiederherstellen
       BLWP @>5A(R9)
       DATA >8000        R0 sichern
       SETO R2
L449A   MOV  R0,R1
       INC  R2
       C    R2,R4        Schon fertig?
       JNE  L4436        Nein
       MOV  R4,R5        Ja
       BL   @L44B6       Cluster-Daten in den FDS eintragen
       JMP  L44B2        Ende
L44AA   BL   @STKJMP       File-Block eines bestehenden Sektors suchen
       DATA SRCFBK
       A    R1,R4        Sektornummer absolut berechnen
L44B2   B    @STKRET       Ende

******************************************************************
* Subroutine FDS um einen Sektor erweitern (44B6)
******************************************************************
L44B6 MOV  R11,R10	Rücksprung sichern
     MOV  R1,R4
     BLWP @>5A(R9) 
     DATA >4001          altes R1 wiederherstellen
     MOV  R1,R1          gleich 0?
     JEQ  L44FA          Ja - Abbruch
     BL   @L4980         Cluster-Daten in den Block-Link Bereich schreiben
     MOV  @>56(R9),R2    Zeiger auf Filenamen
     BLWP @>5A(R9)
     DATA >0042          R2 zum Lesen setzen
     MOVB @>FBFE(R15),R1 1. Byte im Filenamen lesen
     ORI  R1,>8000      High-Bit setzen
     BLWP @>5A(R9)
     DATA >0043
     MOVB R1,@-2(R15)    Wert wieder zur}ck, erzwingt r}ckschreiben
     AI   R2,>000E       Zeiger auf Sektoranzahl des Files
     INC  R5             nun gibt's einen mehr
     BLWP @>5A(R9)       R2 setzen
     DATA >0043
     MOVB R5,@-2(R15)    Sektoranzahl neu schreiben
     SWPB R5
     MOVB R5,@-2(R15)    komplettes Wort
L44FA B    *R10           Ende

******************************************************************************
* Subroutine File-Block suchen (44FC)
*
* Es wird der File-Block gesucht, in dem sich der Sektor befindet, dessen
* Offset in R3 steht. Befindet sich in R3 der maximale Sektor-Offset des
* Files, so wird die Position fuer einen APPEND-Eintrag bestimmt.
* Output: Startsektor in R1, Sektoroffset in R4
******************************************************************************
SRCFBK	MOV @>56(R9),R8	Pufferadresse des FDS
     AI   R8,>001C       auf Anfang der Pointer Blocks zeigen
     MOV  R3,R4          Sektor-Offset
L4506 BL   @L4964         Daten des Cluster holen
     C    R2,R3          R2 = max. Sektor-Offset im Cluster, R1 = Startsektor
     JLT  L4510          Suche noch nicht beendet
     JMP  L451C          fertig!
L4510 AI   R8,>0003       n{chster Block/Cluster
     MOV  R3,R4
     S    R2,R4
     DEC  R4
     JMP  L4506          Daten im n{chsten Block holen
L451C B    @STKRET         Ende

*******************************************************************
* DELETE FILE (4520)
*******************************************************************
FODELF	BL @STKJMP	Filenamen aus dem PAB in den FNCB, in allen File-Puffern nach diesem Namen suchen.
	DATA L4852
     MOV  R4,R4          gefunden?
     JEQ  L4538          Ja
     BL   @STKJMP         Nicht gefunden, einen freien Puffer suchen; wenn es
     DATA L48BA          noch einen gibt, dann Sektor 1 lesen und danach den Filenamen auf der Diskette suchen
     MOV  R4,R4          gefunden?
     JEQ  L455A          Ja
     B    @STKRET         Nein - Ende ohne Fehlermeldung!
L4538 INC  R1
     MOV  R1,@>56(R9)    Der VDP-Pointer zeigt nun auf den Filenamen im Puffer fuer den Directory-Sektor des spezifizierten Files.
     BL   @STKJMP
     DATA L47E2          Sektor 1 lesen, LW.Nr. in R6
     BL   @VDPR56
     DATA >FFFC          (-4), Sektor.Nr. des File-Dir-Sektors lesen.
     MOV  R0,R3          Sektor.Nr. in R3 kopieren
     MOV  R5,R8          Pufferadresse, an der Sek.1 beginnt
L454E BL   @VDPRD         Wert *R8(VDP) nach R0 (Wort)
     INCT R8             n{chster Sektor
     C    R0,R3          ist es schon der Sektor des Files?
     JNE  L454E          nein
     DECT R8             Ja- Pointer korrigieren
L455A BLWP @>5A(R9)
     DATA >0080          R8 sichern
     BL   @STKJMP         Sektor-Bitmap clusterweise auf Diskette aktualisieren
     DATA L438C          d.h. belegte Sektoren freigeben
     BLWP @>5A(R9)
     DATA >0081          R8 wiederherstellen
     BL   @L4588         Sektor-Nr. des gel|schten Files mit den folgenden
     CLR  R2             Sektor-Nummern }berschreiben
     BL   @STKJMP
     DATA L47E4          Sektor 1 schreiben
     BL   @VDPR56
     DATA >FFFC          (-4)
     BL   @STKJMP
     DATA L4A6A		Sektoren aus der Sektor-Bitmap streichen
     B    @L4334         Ende

*****************************************************************************
* Subroutine Verschieben eines Datenblocks im VDP um 1 Wort nach unten (4588)
*****************************************************************************
L4588 MOV  @>56(R9),R5    Zeiger auf aktuellen File-Dir-Sektor Puffer (FDS)
     AI   R5,>0100       Start des Datenpuffers, ggfs Sektor 1
     MOV  R5,R3
     AI   R3,>0100       oberes Ende
     MOV  R8,R2          Zeiger auf das zu }berschreibende Wort
     INCT R2             Zeiger auf }berschreibende Daten
L459A BLWP @>5A(R9)
     DATA >0042          R2 setzen
     MOVB @>FBFE(R15),R0 Daten byteweise holen
     INC  R2             Input Pointer weiter
     BLWP @>5A(R9)
     DATA >0103          R8 setzen
     MOVB R0,@-2(R15)    alte Daten Byteweise }berschreiben
     INC  R8             Output Pointer weiter
     C    R2,R3          oberes Ende?
     JNE  L459A          nein - weiter
	RT	Ja - Ende

**********************************************************************
* Subroutine Platz im Sektor 1 Puffer f}r neuen Sektor schaffen (45B8)
*
* R8 zeigt auf den Eintrag im Sektor 1 Puffer, der nach oben geschoben
* werden muss.
**********************************************************************
L45B8 MOV  R11,R10
     MOV  R8,R1          R8 sichern, wird durch BL @VDPR56 veraendert
     BL   @VDPR56
     DATA >01FC          vorletzten Eintrag im Sektor 1 lesen
     MOV  R0,R0          wenn = 0, dann ist noch Platz f}r einen neuen!
     JEQ  >45CA
     B    @L48D6         Directory ist voll!!
L45CA DEC  R8             Verschiebung beginnt oben im Sektor 1
     BLWP @>5A(R9)
     DATA >0102          R8 setzen
     MOVB @>FBFE(R15),R0 Byte holen
     INCT R8
     BLWP @>5A(R9)
     DATA >0103
     MOVB R0,@-2(R15)    Byte h|her ablegen
     DECT R8
     C    R8,R1          Position des neuen Sektors erreicht?
     JNE  L45CA          nein - weiterarbeiten
     B    *R10           Ja - fertig, Sektor Nr. kann eingef}gt werden

****************************************************************************
* Subroutine Filenamen im File-Buffer mit Inhalt des FNCB vergleichen (45EA)
****************************************************************************
L45EA MOV  @>58(R9),R2    Adresse des Volume-ID Blocks
     AI   R2,>0100       zeigt auf Anfang FNCB (Filename Compare-Buffer)
L45F2 BLWP @>5A(R9)
     DATA >0022          R1 setzen, Startwert extern definiert
     MOVB @>FBFE(R15),R0
     ANDI R0,>7FFF       ASCII maskieren
     BLWP @>5A(R9)
     DATA >0042          R2 setzen
     MOVB @>FBFE(R15),R3
     CB   R0,R3          beide gleich?
     JNE  L4616
     INC  R1
     INC  R2
     DEC  R4             Schleifenz{hler, Startwert extern gesetzt
     JNE  L45F2          noch nicht komplett durch
L4616	RT	Ende

*****************************************************************
* 3 verschiedene Einsprünge in VDPRD (4618) - je nachdem welcher
* VDP-Zeiger zu nutzen ist, 2 davon mit Offset als Word Parameter
*****************************************************************
VDPR54	MOV @>0054(R9),R8	Zeiger auf PAB
	JMP VDPRGP
VDPR56	MOV @>0056(R9),R8	>461E
VDPRGP	A *R11+,R8		>4622	Parameter holen
***************************************************************************
* VDPRD - lese das Wort an Adresse in R8 nach R0 und setze die Flags (4624)
***************************************************************************
VDPRD	blwp @>005a(r9)
	DATA >0102		Setze R8 zum Lesen aus VDP
	movb @>fbfe(r15),r0	Lesen von >8800
	SWPB R0			SWPB ändert keine Flags!
	movb @>fbfe(r15),r0
	SRC R0,8		Damit werden die Flags L>,A>,EQ,C gleich gesetzt
	RT

******************************************************************
* Suche Diskettenlaufwerk mit einer Disk anhand deren Namen (4638)
* Rückgabe der Nummer (1-4) im MSB von R6, LSB ist >00
******************************************************************
SRCDSK	MOV @>0058(R9),R1	Volume-ID Adresse
     AI   R1,>0100       Zeigt auf FNCB
     BL   @L46C2         Disknamen aus PAB in den FNCB
     BLWP @>5A(R9)
     DATA >3000          R2 und R3 sichern
     MOV  R0,R0
     JLT  L4650
     JMP  L465A
L4650 MOV  R0,R6
     ANDI R6,>0700 
     JEQ  L46C6          File Error
     JMP  L46B8
L465A CLR  R6
     BL   @STKJMP
     DATA L4780          Sektor 0 update
L4662 AI   R6,>0100       nächstes Laufwerk
     SETO R7		Statuspuffer vorbelegen
     SETO R2		Sektor lesen
     CLR  R4		Sektor 0
     BL   @STKJMP
     DATA L47FE
     MOV  R7,R7          Fehler bei diesem Laufwerk?
     JNE  L46B0          Ja - weitersuchen
     LI   R4,>000A
     MOV  @>58(R9),R1    Zeiger auf Volume-ID, Diskname
     BLWP @>5A(R9)
     DATA >7000          R1,2,3 retten
     BL   @L45EA         FNCB mit Vol-ID-Buffer vergleichen
     BLWP @>5A(R9)
     DATA >7001          R1,2,3 wiederherstellen
     MOV  R4,R4          Namensgleichheit
     JNE  L46B0          Nein - weitersuchen
     MOV  R6,R0          Laufwerknummer kopieren
     ORI  R0,>8000       High-Bit setzen
     BLWP @>5A(R9)
     DATA >0063          R3 setzen
     MOVB R0,@-2(R15)    LW-Nr. mit gesetztem High-Bit schreiben
     DEC  R5
     BLWP @>5A(R9)
     DATA >00A3          R5 setzen
     MOVB R6,@-2(R15)    LW-Nr. ohne gesetztes High-Bit schreiben
     JMP  L46B8          weiter
L46B0 CI   R6,>0400       Laufwerk 4?
     JNE  L4662          Nein - weitersuchen
     JMP  L46C6          File Error
L46B8 BLWP @>5A(R9)
     DATA >3001          R2 und R3 wiederherstellen
     B    @STKRET         Ende
***********************************************************
* Subroutine Namen aus dem PAB in den FNCB kopieren (46C2)
*
* R1	Zeiger in den FNCB
* R2	Namenlänge+1
* R3	Zeiger auf den zu verschiebenden Namen.
***********************************************************
L46C2 DEC  R2             R2 enthält nun die Namenlänge (ohne Device!)
     JH   L46CC          größer 0
L46C6 BL   @FOSCRA	Seiteneinsprung SCRATCH
     DATA >E000          File Error, Status = 7
L46CC LI   R0,>2000       Blanks
     BLWP @>5A(R9)
     DATA >0023
     LI   R8,>000A       Schleife
L46DA MOVB R0,@-2(R15)    FNCB löschen
     DEC  R8
     JNE  L46DA
     LI   R8,>000B       Schleifenzähler, nur bei richtigem Symbol dekrementi.
L46E6 INC  R3             PAB Pointer
     BLWP @>5A(R9)
     DATA >0062          R3 als Leseadresse setzen
     MOVB @>FBFE(R15),R0 Byte aus PAB holen
     JEQ  L46C6          =0, dann Fehler im Filenamen, File Error
     JLT  L4716          negativ ist im Filenamen unzulässig
     CI   R0,>2E00       Punkt?
     JEQ  L4716          im Filenamen unzuläsig
     DEC  R8             ASCII OK, Counter - 1
     JEQ  L46C6          wenn R8=0, dann war der Name länger als 10 Byte!
     CI   R0,>2000       Blanks im Namen sind auch verboten
     JEQ  L46C6          gibt auch File Error
     BLWP @>5A(R9)
     DATA >0023          R1 wieder setzen
     MOVB R0,@-2(R15)    gelesenen, richtigen Wert in den FNCB
     INC  R1             FNCB-Pointer weiterschalten
     DEC  R2             Namenlänge - 1
     JNE  L46E6          noch nicht durch
L4716 CI   R8,>000B       Fehler vor einem gültigen Symbol?
	JEQ  L46C6          Ja - File Error
	RT	Ende
*
L471E	BYTE >AA	Na das haben wir ja schon ganz vorne...
	EVEN

***********************************************
* Subroutine Behandlung von I/O-Fehlern (4720)
**********************************************
L4720 MOV  R11,R0         Data-Pointer sichern
     MOV  @>56(R9),R3    VDP-RAMTOP+2
     DEC  R3             zeigt auf Validation Code
     BLWP @>5A(R9)	R3 setzen
     DATA >0062
     MOVB @>FBFE(R15),R2 realen Wert lesen
     CB   R2,@L471E      gleich >AA?	AU WEIA!
     JEQ  L474A          Ja
     BLWP @>5A(R9)
     DATA >8000          R0 und damit R11 sichern
     BL   @STKJMP
     DATA FOPEND
     BLWP @>5A(R9)
     DATA >8001          R0 wiederherstellen
L474A MOV  R0,R11         Data-Pointer
*
* Behandlung von SCRATCH RECORD und FILE ERROR
*
FOSCRA MOV  @>54(R9),R1    Pointer auf I/O-Mode
     JEQ  L476C          gelöscht, Uebergabe des Codes nicht im Statusbyte!
     INC  R1             weiter, auf Status zeigen
     BLWP @>5A(R9)
     DATA >0022
     MOVB @>FBFE(R15),R2 Status lesen
     SOC  *R11+,R2       mit Fehlercode (Data) verodern
     BLWP @>5A(R9)
     DATA >0023
     MOVB R2,@-2(R15)    geänderten Wert schreiben
     JMP  L4770
L476C MOV  *R11+,@>50(R9) Übergabe des Codes in >8350
L4770 MOV  @>58(R9),R8    Startadresse Volume-ID
     AI   R8,-12         auf 1.Eintrag im VDP-Stack zeigen
     MOV  R8,@>66(R9)    zum aktuellen Stackpointer machen
	B @STKRET	DSR-ROM verlassen
*
* Subroutine Volume-ID lesen/schreiben/updaten (4780)
*
L4780 BLWP @>5A(R9)
     DATA >3000          R2 und R3 sichern
     MOV  @>58(R9),R5    Startadresse des Volume-ID nach R5
     DEC  R5             auf LW-Nr. des Vol-ID zeigen
     BLWP @>5A(R9)
     DATA >00A2          R5 zum Lesen setzen
     MOVB @>FBFE(R15),R2 LW-Nr. lesen
     MOV  R2,R3          sichern
     CLR  R4             Sektor-Nr. = 0
     ANDI R2,>0700       Update-Bit löschen, 'Sektor schreiben' Index
     CB   R2,R6          ]bereinstimmung mit dem gewünschten Laufwerk?
     JEQ  L47D6          Ja
     MOV  R3,R3          alten LW-Eintrag prüfen
*                         Sektor 0 im Puffer gehört nicht zu dem jetzt
*                         angewählten Laufwerk, der aktuelle Stand des
*                         Volume-ID muss auf 'seine' Diskette zurück, erst
*                         dann kann der Sektor 0 des jetzt aktuellen Lauf-
*                         werks gelesen und beeinflusst werden!
     JLT  L47A8          High-Bit gesetzt - Updated Volume-ID!
     JMP  L47BC          Volume-ID auf neuen Stand bringen
L47A8 BLWP @>5A(R9)       Einsprung wenn Sektor 0 aktuell ist
     DATA >00A3          mit R5 schreiben
     MOVB R4,@-2(R15)    LW-Nr. zu Null setzen
     INC  R5             Zeiger auf Pufferbereich für Sektor 0 setzen
     BL   @STKJMP
     DATA L4800          Sektor 0 mit Lw-Nr. in R2 schreiben
     DEC  R5             wieder auf LW-Nr. zeigen
L47BC SETO R2             'Sektor Lesen' Index setzen, Einsprung wenn der Sektor 0 bereits geschrieben wurde.
     MOVB R6,R2          Aktuelles LW
     JEQ  L47CC          Gleich Null - Sektor 0 nicht lesen!
     INC  R5             Pufferzeiger auf Vol-ID Puffer
     BL   @STKJMP
     DATA L47FE          Sektor 0 lesen, Pufferzeiger in R5
     DEC  R5             wieder auf LW-Nr.
L47CC BLWP @>5A(R9)
     DATA >00A3          mit R5 schreiben
     MOVB R6,@-2(R15)    LW-Nr. des gelesenen Vol-ID vor dessen Puffer
L47D6 INC  R5             Einsprung wenn Sektor 0 bereits o.K. war. VDP-Zeiger auf Vol-ID korrigieren
     BLWP @>5A(R9)
     DATA >3001          R2 und R3 wiederherstellen
     B @STKRET         Return via VDP-Stack, Ende

*************************************
* Subroutine Sektor lesen/schreiben (47E2)
*
* Diese Routine hat diverse Einsprungadressen, je nachdem welche Default-Werte übernommen werden sollen.
********************************************
L47E2	SETO R2             'Sektor lesen' Index
L47E4   LI   R4,>0001       Sektor-Nummer 1
     	LI   R5,>0100       Offset für den Pufferbereich des Sektors
     	JMP  L47F8
L47EE	BL   @VDPR56
     	DATA >FFFC          Sektor-Nr. des File-Directory-Sektors nach R0
L47F4 	MOV  R0,R4          in den Sektor-Puffer (R4) kopieren
     	CLR  R5             Puffer-Offset gleich Null
*
* STKJMP Seiteneinsprung
*
L47F8 	A    @>56(R9),R5    Offset zur aktuellen VDP-Arbeitsadresse addieren
L47FC 	CLR  R7             Statuspuffer löschen
L47FE   MOVB R6,R2          LW-Nr. in den I/O-Index

L4800 	BLWP @>5A(R9)
     	DATA >FF80          R0 bis R8 sichern
     	MOV  R4,@>4A(R9)    Sektor-Nr. übergeben
     	MOV  R2,@>4C(R9)    Lw-Nr. im High-Byte, I/O-Code im Low-Byte Low-Byte = 00 -> Sektor schreiben, FF -> lesen
     	MOV  R5,@>4E(R9)    Sektor-Puffer Adresse
     	BL   @STKJMP
	DATA L5A0A          Sektor-I/O-Routine aufrufen
     	BLWP @>5A(R9)
     	DATA >FF81          Register 0 bis 8 wiederherstellen
     	MOVB @>50(R9),R7    Error-Code lesen
     	SWPB R7             ins Low-Byte
     	JEQ  L484A          kein Fehler
     	MOV  R7,R7          prüfen
     	JGT  L482C          Wert ist nicht negativ
     	JMP  L4842          Wert ist negativ
L482C 	ANDI R7,>00FF       positiven Wert normieren
     	CI   R7,>0034       Write Protected?
     	JNE  L483C          Nein
     	BL   @L4720
     	DATA >2000          Fehlerbehandlung, Statusbyte im PAB = 1
L483C 	BL   @L4720
     	DATA >C000             Fehlercode = 3 im PAB , Illegale Operation
L4842 	MOVB @>4D(R9),@>4D(R9) Einsprung bei negativem Fehlercode alten I/O-Code holen
     	JEQ  L482C          Sektor-Operation war 'Schreiben', vorherige Fehlerbehandlung mit benutzen
L484A 	ANDI R7,>00FF       Code normieren
     	B    @STKRET         Rücksprung

***************************************************************************
* Subroutine Filename vergleichen, passenden File-Puffer suchen (4852)
*
* Es wird der String im FNCB nacheinander mit allen Einträgen in den FDS-Puffern
* verglichen. R1 zeigt nach erfolgreicher Suche auf das LW-Byte vor dem Filenamen.
***************************************************************************
L4852 MOV  @>58(R9),R1    Adresse des Volume-ID holen
     AI   R1,>0100       Zeiger auf Anfang des FNCB (Filename Compare Buffer)
     BLWP @>5A(R9)
     DATA >0023          R1 zum schreiben
     MOVB R6,@-2(R15)    LW-Nr. ist das erste Byte
     INC  R1             Beginn des Namensfeldes
     BL   @L46C2         SBR Filenamen in den FNCB
     MOV  R2,R2          wurde bis zum Ende gearbeitet?
     JEQ  L4872          Ja
L486E B    @L46C6         File-Error!
*
* STKJMP Seiteneinsprung
*
L4872 MOV  @>56(R9),R1    Zeiger auf VDP-RAMTOP+2
     AI   R1,>0003       auf Anzahl offener Files zeigen
     BLWP @>5A(R9)
     DATA >0022          Leseadresse mit R1 setzen
     MOVB @>FBFE(R15),R2 Anzahl zulässiger offener Files nach R2
     SRL  R2,8           ins Low-Byte
     MOV  R2,R3          kopieren
     AI   R1,>0006       auf LW-Nr. des ersten File-Control Blocks zeigen
L488C LI   R4,>000B       Schleifenzähler, 10 Byte Name plus LW-Nr.
     BLWP @>5A(R9)
     DATA >7000          R1,2,3 retten
     BL   @L45EA         FNCB mit Puffer-Inhalt vergleichen
     BLWP @>5A(R9)
     DATA >7001          R1,2,3 wiederherstellen
     MOV  R4,R4          Flag prüfen, ob Namen gleich waren
     JEQ  L48AC          Ja
     AI   R1,>0206       auf den nächsten Block zeigen, gleiche Position!
     DEC  R2             Fileanzahl reduzieren
     JNE  L488C          noch nicht alle Puffer durchgesehen - weiter
L48AC	B @STKRET	Ende, R4 ist Flag für das rufende Programm ob o.K.

***********************************************************************************
* Subroutine FDS in freien Pufferbereich schreiben (48B0)
* 
* Also: Datei öffnen.
* Wurde ein FDS gefunden, d.h. wurde ein bereits vorhandenes File neu eröffnet,
* dann wird dessen Sektornummer in den Header des FDS-Puffers geschrieben.
* Wurde kein FDS gefunden, so zeigt R8 auf die Position im Sektor 1 Puffer,
* an der die Sektornummer des FDS eines Files stehen müsste, das den
* angegebenen Namen hätte.
***********************************************************************************
L48B0	BL   @STKJMP         Filenamen zuerst im Pufferbereich suchen
     DATA L4852          Filenamen vergleichen
*
* STKJMP Seiteneinsprung
*
L48B6     MOV  R4,R4          Flag prüfen
     JEQ  L486E          File-Error, Datei schon offen!
L48BA     MOV  @>56(R9),R5    VDP-RAMTOP+2
     AI   R5,>000A       plus 10 - zeigt auf Puffer des File-Directory Sektors
L48C2 BLWP @>5A(R9)
     DATA >00A2          R5 als Leseadresse setzen
     MOVB @>FBFE(R15),R2 1. Filenamenbyte lesen
     JEQ  L48DC          Nullbyte - Puffer ist noch unberührt
     AI   R5,>0206       Puffer belegt, nächsten prüfen
     DEC  R3             kopierten Wert der Fileanzahl reduzieren
     JNE  L48C2          noch Chancen - weiter suchen

L48D6 BL   @L4720
     DATA >8000          Fehler, Status = 4, Out of Table or Buffer-Space, alle Datenpuffer sind belegt.
L48DC MOV  R5,@>56(R9)    R5 zeigt auf Anfang eines verfügbaren FDS-Puffers
     BL   @STKJMP
     DATA L47E2          Sektor 1 in den Puffer ab @>8x56 + >100 lesen
* Seiteneinsprung
L48E6     MOV  @>56(R9),R8    Pufferadresse - >100 nach R8
     AI   R8,>017E       mitten in den Puffer von Sektor 1 zeigen, für die Suche von Files ist das der beste Startwert.
     LI   R2,>0040       Interpolationsoffset für die Suche
L48F2 SETO R4
     BL   @VDPRD         Wert aus VDP-RAM *R8 nach R0, hier Sektor Nr. eines File-Directory Sektors
     MOV  R0,R0          Sektornr. = 0?
     JEQ  L4958          Ja - Bereich ist nicht belegt, weitersuchen
     BLWP @>5A(R9)
     DATA >2000          R2 sichern
     SETO R2             Leseindex
     BL   @STKJMP       spezifizierten Sektor lesen
     DATA L47F4          Sektornummer wird in R4 zurückgeliefert
     MOV  R5,R1          Pufferadresse kopieren
     AI   R5,>FFFC       4 abziehen, zeigt auf Sektornr. in der File-Info
     BLWP @>5A(R9)
     DATA >00A3          R5 als Schreibadresse setzen
     MOVB R4,@-2(R15)
     SWPB R4
     MOVB R4,@-2(R15)    Sektornr. in den File-Info Block
     MOV  R1,R5          Wert der Pufferadresse wieder gewinnen
     DEC  R1             R1 zeigt auf die Laufwerknummer
     BLWP @>5A(R9)
     DATA >0023          R1 als Schreibadresse setzen
     MOVB R6,@-2(R15)    LW-Nr. schreiben
     LI   R4,>000B
     BL   @L45EA         Filenamen im gelesenen Sektor mit dem aktuellen Namen *R1 vergleichen
     BLWP @>5A(R9)
     DATA >2001          R2 wiederherstellen
     JEQ  L4954          Equal-Bit ist noch durch R4 beim Vergleich definiert
     BLWP @>5A(R9)       Ende, wenn Gleichheit bestand
     DATA >00A3          R5 wieder setzen,
     MOVB R4,@-2(R15)
     C    R0,R3          Pointer des Namensvergleichs testen
     JH   L4958          Filename ist im Alphabet zu weit oben, weiter unten suchen
     A    R2,R8          Interpolationsoffset zu dem Zeiger in den Puffer für
*                         Sektor 1 addieren, der Filename muss im Alphabet höher 
*                         gesucht werden
     MOV  R2,R2          Index auf Null prüfen, zeigt das Ende des Suchvorgangs an
     JNE  L495E          nicht Null, Offset reduzieren und weiter suchen
     INCT R8             Sektor 1-Pointer korrigieren
L4954 B    @STKRET         Ende

L4958 S    R2,R8          Interpolationsoffset subtrahieren, es wurde im Alphabet zu hoch angesetzt
     MOV  R2,R2          prüfen ob Schluss der Suche ist
     JEQ  L4954          Ja - Ende
L495E SRL  R2,2           Suchoffset durch 4 teilen, klassisches Interpolationsverfahren
     A    R2,R2          mal 2, vermeidet ungerade Adressen
     JMP  L48F2          und weiter suchen
*
* Subroutine Cluster-Daten aus dem Puffer des File-Descriptors lesen (4964)
* R8 zeigt auf den richtigen 3 Byte Block
* Übergabe der Sektornr. in R1, Sektor Offset in R2
*
L4964 MOV  R11,R10
     BL   @VDPRD         Wert im VDP-RAM *R8 nach R0
     SWPB R0             1. Wort des Block-Link umdrehen
     MOVB @>FBFE(R15),R2 und noch das dritte Byte lesen
     MOV  R0,R1          Sektornr plus SO1-Nibble in R1
     ANDI R1,>0FFF       Sektornummer des Cluster isolieren, Offset-Nibble weg
     SZC  R1,R0          Sektor-Offset Nibble isolieren
     SRL  R2,8           Offset-Byte korrigieren
     SOC  R0,R2          SO1-Byte ins High-Nibble
     SRC  R2,12          Sektor-Offset richtigstellen
     B    *R10           Ende
*
* Subroutine Cluster-Daten in den File-Descriptor Puffer schreiben-0
* R1: Sektornummer
* R2: Sektoroffset, beide Male nur 12-Bit Worte!
*
L4980	SRC R2,4           Sektoroffset Nibble 0 (SO1) ins High-Byte
	MOV R2,R0          kopieren
	ANDI R0,>F000        SO1 isolieren
	SOC R0,R1          als High-Nibble im Startsektor
	BLWP @>5A(R9)
	DATA >0103          R8 als Schreibadresse setzen
	SWPB R1
	MOVB R1,@-2(R15)    SS2, SS1 schreiben
	SWPB R1
	MOVB R1,@-2(R15)    SO1, SS3 schreiben
	SWPB R2
	MOVB R2,@-2(R15)    SO3, SO2 schreiben
	RT	Ende
****************************************************************************
* Subroutine Belegte Sektoren in der Sektor-Bitmap indizieren (49A4)
*
* R1 bis R4 werden nicht verändert!
* In R0 wird die Nummer des Sektors geliefert, der neu belegt werden konnte.
* War keiner mehr frei, dann ist R0 = 0!
* In R1 (Input) befindet sich das Sektortyp-Flag:
* R1 = 0 : Datensektor, Suche beginnt oberhalb Sektor >21
* R1 =>FF: FDS, Suche beginnt bei Sektor 3.
****************************************************************************
L49A4 BLWP @>5A(R9)
     DATA >7800          R1 bis R4 sichern
     BL   @STKJMP
     DATA L4780          Volume-ID update, R1 - 3 werden nicht verändert, R5 zeigt auf die Vol-ID Pufferadresse
     MOV  R1,R1          R1 = 0?
     JNE  L49B8          Nein - FDS
     LI   R1,>0042       avisierter Datensektor -1	ACHTUNG: Abweichung Hexdump von Disassembly! war >0021
L49B8 INC  R1
     MOV  R1,R0          Sektornummer kopieren
     SRL  R1,3           geteilt durch 8 -> INTEGER-Anteil
     LI   R2,>00FF
     ANDI R0,>0007       Ermittlung des Divisionsrests
     JEQ  L49CA          kein Rest, also Bit 0 gefordert
     SLA  R2,0           Einsen um die Bitnummer nach links schieben, die letzte Null ist die Bitposition
L49CA MOV  R1,R3          kopieren des Integer-Anteils, relative Position innerhalb der Sektor-Bitmap
     A    R5,R3          Basisadresse des Volume-ID Blockes addieren
     AI   R3,>0038       Basisadresse der Sektor-Bitmap addieren
     CI   R1,>00C8       bei dieser Sektor-Basis ist das Ende von Sektor 0 erreicht
     JLT  L49DA          berechnete Sektorposition ist i.O.
     CLR  R1             berechnete Sektornummer ist zu groß, Offset nach >21 löschen
L49DA A    R5,R1          Puffer-Basisadresse addieren
     AI   R1,>0038
     BLWP @>5A(R9)
     DATA >0022          R1 als Leseadresse setzen
L49E6 SETO R0
     MOVB @>FBFE(R15),R0 alten Eintrag lesen
     MOV  R0,R4
     SOC  R2,R0          mit dem neuen Byte für die Belegung verodern
     CLR  R2
     INC  R0
     JNE  L4A16
     INC  R1
     MOV  R1,R0
     AI   R0,>FF00       255 abziehen
     C    R0,R5          oberes Ende der Sektor-Bitmap erreicht?
     JNE  L4A0C          Nein
     AI   R1,>FF38       Ja - vor Sektor >22 probieren
     BLWP @>5A(R9)
     DATA >0022          R1 als Leseadresse setzen
L4A0C C    R1,R3
     JNE  L49E6
     MOV  R4,R0          ursprünglichen Eintrag der Sektor-Bitmap wieder holen
     INC  R0             +1
     JEQ  L4A60          gleich Null, dann war kein freier Sektor mehr drin
L4A16 DEC  R0
     MOV  R0,R2
     CLR  R0
     SWPB R2
L4A1E INC  R0
     SRC  R2,1
     JOC  L4A1E
     LI   R2,>0080       Walking-Bit initialisieren
     SLA  R2,0           nach R0 ins High-Byte schieben
     DEC  R0
     SOC  R2,R4
     BLWP @>5A(R9)
     DATA >0023          R1 als Schreibadresse setzen
     MOVB R4,@-2(R15)
     AI   R1,>FFC8       Bitmap-Basis abziehen
     S    R5,R1          Puffer-Basis abziehen
     SLA  R1,3           mal 8
     SOC  R0,R1          Low-Nibble erzeugen
     MOV  R1,R0          kopieren, R0 enthält die Nr. des neu belegten Sektors
*
L4A44 DEC  R5             Zeiger auf LW-Nr. des Volume-ID
     BLWP @>5A(R9)
     DATA >00A2
     MOVB @>FBFE(R15),R1 LW-Nr. lesen
     ORI  R1,>8000       High-Bit setzen, schreiben des Volume-ID erzwingen
     BLWP @>5A(R9)
     DATA >00A3
     MOVB R1,@-2(R15)    LW-Nr. wieder zurückschreiben
     INC  R5             Pufferadresse reparieren
L4A60 BLWP @>5A(R9)
     DATA >7801          R1 bis R4 wiederherstellen
	B @STKRET	Ende
*********************************************************************
* Subroutine Sektoren aus der Sektor-Bitmap entfernen (4A6A)
*
* Es wird nur 1 Cluster bearbeitet.
* R1	Startsektor
* R2	Sektoranzahl
* R3	Sektor-Nummer des FDS
* R4	extern inkrementierter Zähler zur Bestimmung der Anzahl der Sektoren pro Cluster (Block).
*	Dies ist notwendig, da die Daten des Sektor-Offset im Cluster auf den ersten Block bezogen sind.
* R5	Pufferadresse des Volume-ID im VDP-RAM.
*********************************************************************
L4A6A MOV  R0,R1	ACHTUNG Abweichung von Disassembly und Hexdump! Beide zeigen MOV R0,R1, was mir nicht einleuchtet, war MOV R1,R0
     LI   R2,>0001
L4A70     BLWP @>5A(R9)
     DATA >7800          R1 bis R4 sichern
     BL   @STKJMP
     DATA L4780          Volume-ID update
     MOV  R1,R0          Nummer des Startsektors des Files kopieren
     ANDI R0,>0007       jedes Byte der Sektor-Bitmap beschreibt Sektoren #0-#7
     SRL  R1,3           Byte-Offset des Sektors berechnen
     A    R5,R1          Basisadresse des Puffers addieren
     AI   R1,>0038       Startadresse der Sektor-Bitmap addieren, R1 ist ab jetzt der Zeiger in die Sektor-Bitmap
     MOV  R0,R3
     NEG  R0
     AI   R0,8
     LI   R4,>00FF
     C    R2,R0
     JLT  L4A9C
     JMP  L4AAE
L4A9C LI   R0,>0008
     S    R2,R0
     SRC  R4,0
     MOV  R3,R0
     JEQ  L4AAA
     SLA  R4,0
L4AAA SWPB R4
     JMP  L4AE0
L4AAE SRC  R4,0
L4AB0 S    R0,R2
     BLWP @>5A(R9)
     DATA >0022          R1 ist Zeiger in die Sektor-Bitmap
     MOVB @>FBFE(R15),R0 alten Eintrag holen
     SZC  R4,R0          Sektoren als frei eintragen
     BLWP @>5A(R9)
     DATA >0023
     MOVB R0,@-2(R15)    geänderten Wert schreiben
     LI   R4,>FF00
     INC  R1             nächstes Byte
     LI   R0,>0008
     C    R2,R0
     JLT  L4AD8
     JMP  L4AB0
L4AD8 MOV  R2,R0
     LI   R4,>00FF
     SLA  R4,0
L4AE0 BLWP @>5A(R9)
     DATA >0022          Bitmap-Pointer setzen
     MOVB @>FBFE(R15),R0 Eintrag lesen
     SZC  R4,R0          Bits löschen
     BLWP @>5A(R9)
     DATA >0023
     MOVB R0,@-2(R15)    neuen Wert in die Tafel
     JMP  L4A44          Ende

************************************************************
* Diskettenzugriff mit Diskname statt Laufwerksnummer (4AF8)
************************************************************
DSRA	MOV R11,R7
	BL @MAINIT
	BL @STKJMP
	DATA SRCDSK
	JMP DSRG
************************************************************
* Zugriff auf physikalisches Diskettenlaufwerk Nr. 1 (4B06)
************************************************************
DSRB	LI R6,>0100
	JMP DSRF
************************************************************
* Zugriff auf physikalisches Diskettenlaufwerk Nr. 2 (4B0C)
************************************************************
DSRC	LI R6,>0200
	JMP DSRF
************************************************************
* Zugriff auf physikalisches Diskettenlaufwerk Nr. 3 (4B12)
************************************************************
DSRD	LI R6,>0300
	JMP DSRF
************************************************************
* Zugriff auf physikalisches Diskettenlaufwerk Nr. 4 (4B18)
************************************************************
DSRE	LI R6,>0400
************************************************************
* Seiteneinsprung der numerierten Laufwerke (4B1C)
************************************************************
DSRF	MOV R11,R7
	BL @MAINIT
************************************************************
* Seiteneinsprung der Laufwerkssuche,
* ab jetzt ein gemeinsamer Code für alle (4B22)
************************************************************
DSRG	MOV @>54(R9),R0		Zeiger auf I/O Mode
	BLWP @>5A(R9)
	DATA >0002		Leseadresse darauf setzen
	MOVB @>FBFE(R15),R1	I/O mode abholen
	SRL R1,8		ins Low Byte
	CI R1,9		Zulässiger I/O Code?
	JH ILEGOP	Nein - Illegale Operation
	CI R2,1		Filenamenlänge incl. Punkt == 1?
	JNE DSRGGO	Nein, kein Directory Befehl
	AI R1,10	Doch - Sprungoffset addieren
	CI R1,12	Mehr als 12 Funktionen haben wir nicht!
	JH ILEGOP	Fehler - Illegale Operation
DSRGGO	A R1,R1			Sprungindex mal 2
	MOV @IOFNCT(R1),R1	Vektor
	B *R1			Und ab nach...
*
* Sprungtabelle für die entspr. Operationen
*
* Abschnitt 1 - Dateifunktionen
IOFNCT	DATA FOOPEN	0 OPEN
	DATA FOCLOS	1 CLOSE
	DATA FOREAD	2 READ
	DATA FOWRIT	3 WRITE
	DATA FOREST	4 RESTORE
	DATA FOLOPF	5 LOAD
	DATA FOSVPF	6 SAVE
	DATA FODELF	7 DELETE
	DATA FOSCRA	8 SCRATCH RECORD
	DATA FOSTAT	9 STATUS
* Abschnitt 2 - Directory Funktionen
	DATA DOOPEN	0 OPEN DIRECTORY
	DATA DOCLOS	1 CLOSE DIRECTORY
	DATA DOREAD	2 INPUT DIRECTORY RECORD
*
ILEGOP	BL @L4720	Fehler
	DATA >6000	Illegale Operation
**********************************
* Ausführung OPEN FILE (>4B70)
***********************************
FOOPEN	CLR R0
     MOVB @>FBFE(R15),R0 Flag-Byte aus dem PAB holen
     BLWP @>5A(R9)
     DATA >8000          R0 sichern
     ANDI R0,>1600       Record-Type und Eröffnungsmodus isolieren, Datentyp wird ignoriert!
     CI   R0,>0600       Append-Mode mit FIXED?
     JNE  L4B8C          Nein
L4B86 BL   @L4720         Ja - Fehler, geht nicht mit FIXED-Dateien!
     DATA >4000          Status = 2, Bad Open Attribute!

L4B8C JLE  L4BA2          Input, Output oder Update
     MOV  R0,R1          Append, Flag-Byte kopieren
     BL   @VDPR54
     DATA >0004          Reclen und Char-Count nach R0
     CI   R0,>FF00       Reclen=255 und Char-Count = 0?
     JHE  L4B86          Nein - Fehler!
     MOV  R1,R0          Modus-Byte kopieren
     ANDI R0,>0600
L4BA2 CI   R0,>0200       Output? (Wird auch bei APPEND benutzt)
     JNE  L4C56          Nein
     BL   @STKJMP
     DATA OPFOUT          File eröffnen, ob neu oder nicht

L4BAE BL   @L4D30         File-Status Byte für FDS aus PAB-Mode erzeugen
     BLWP @>5A(R9)
     DATA >0083          R4 als Schreibadresse setzen
     MOVB R2,@-2(R15)    File-Status in den FDS
     MOV  @>54(R9),R3    Zeiger auf Status
     AI   R3,>0004       auf Record-Length zeigen
     CLR  R5
     BLWP @>5A(R9)
     DATA >0062          R3 als Leseadresse setzen
     MOVB @>FBFE(R15),R5 Record-Length lesen
     JNE  L4BE0          es wurde ein Wert angegeben
*
     LI   R5,>5000       Default-Wert 80 wenn keine Länge angegeben wurde
     BLWP @>5A(R9)
     DATA >0063          R3 zum Schreiben
     MOVB R5,@-2(R15)    Default-Wert in den PAB
L4BE0 AI   R4,>0005       Zeiger auf Satzlänge im FDS
     BLWP @>5A(R9)
     DATA >0083          R4 zum Schreiben setzen
     MOVB R5,@-2(R15)    Satzlänge schreiben
*
* Anzahl Datensätze pro Sektor berechnen
*
	LI R1,>0100	256, aber nur das Highbyte wird genutzt, also >01!
     MOV  R2,R2          File-Status prüfen
     	JLT  L4BF8          gesetztes High-Bit -> VAR-Datei
     	JMP  L4BFC          FIXED-Datei
L4BF8 	A    R1,R5          Satzlänge + 1 für Längenbyte
     	DEC  R1             R1 = >00FF
L4BFC	SWPB R5	Satzlänge ins Low-Byte, also normieren auf 16 Bit
	CLR R0	Division vorbereiten
	DIV R5,R0	Anzahl Datensätze pro Sektor berechnen (RPS): Bytes pro Sektor geteilt durch Bytes pro Datensatz
     	AI   R4,>FFFC       4 abziehen, zeigt auf RPS-Eintrag im FDS
     	MOV  R0,R1          RPS kopieren, nur ganzzahlieger Anteil ist relevant
     	SWPB R0             ins High-Byte
     BLWP @>5A(R9)
     DATA >0083          R4 setzen
     MOVB R0,@-2(R15)    RPS schreiben
     MOV  @>56(R9),R8    Zeiger auf FDS
     BLWP @>5A(R9)
     DATA >0102          R8 setzen
     MOVB @>FBFE(R15),R0 1. Filenamenbyte lesen
     ORI  R0,>8000       High-Bit setzen
     BLWP @>5A(R9)
     DATA >0103          R8 wieder setzen
     MOVB R0,@-2(R15)    Wert zurückschreiben
     BLWP @>5A(R9)
     DATA >8001          R0 wiederherstellen, nur um den Stack zu ordnen!
     BL   @VDPR54
     DATA >0006          Record-Nr. aus dem PAB lesen
     MOV  R0,R4          kopieren
     JEQ  L4C52          Null? -> File-Pointer rücksetzen
     JLT  L4B86          größer als 32767? -> Fehler!
     A    R1,R4          R1 = RPS plus Record-Nr.       0000 Recnum-1+RPS
     DEC  R4             Recnum -1                     ------------------- = R3
     CLR  R3                                                   RPS
     DIV  R1,R3           Sektornummer (relativ im File) bestimmen
     DEC  R3             daraus den Sektor-Offset bestimmen
     BL   @STKJMP
     DATA L4412          Sektornummer (absolut) bestimmen
L4C52	B @L5158	Subset von 'Restore' benutzen, Header in Grundzustand, Record Offset 0.

L4C56 BLWP @>5A(R9)       Einsprung wenn Input oder Update
     DATA >8000          R0 retten
     BL   @STKJMP
	DATA L48B0	FDS in einen freien Pufferbereich einlesen
     BLWP @>5A(R9)
     DATA >8001          R0 wiederherstellen
     MOV  R4,R4
     JEQ  L4C7E
     CI   R0,>0400       Input?
     JEQ  L4C7A          Ja
	BL @STKJMP	Nein - Update
     DATA OPFONF
     JMP  L4BAE
L4C7A B    @L4B86         Fehler 2: Bad Open Attribute

L4C7E MOV  R0,R7
     BL   @L4D30         File-Status erzeugen (PAB Status zu FCB)
     BLWP @>5A(R9)
     DATA >0082          R4 setzen
     MOVB @>FBFE(R15),R0 File-Status lesen
     MOV  R0,R3          kopieren
     ANDI R3,>0800       Protection-Bit isolieren
     JEQ  L4CA2          Nicht gesetzt!
     CI   R7,>0400       Doch gesetzt, Input?
     JEQ  L4CA2          Ja, dann darf das File ruhig geschützt sein
     BL   @L4720         Update-Mode, nicht mit geschütztem File erlaubt!
     DATA >2000          Fehler, Status = 1, Schreibgeschützt

L4CA2 ANDI R0,>8300       File-Status Byte maskieren, Protection Bit ist weg
	XOR R2,R0	Stimmt das Statusbyte mit dem im PAB überein?
	JNE L4C7A	Nein! -> Bad Open Attribute
	MOV @>54(R9),R3	PAB-Zeiger
	AI R3,>0004	Logische Satzlänge
	AI R4,>0005	Satzlänge lt. PAB
	BLWP @>5A(R9)
	DATA >0082          R4 setzen
     MOVB @>FBFE(R15),R0	Satzlänge aus PAB lesen
     BLWP @>5A(R9)
	DATA >0062          R3 setzen
     MOVB @>FBFE(R15),R2	Log. Satzlänge lesen
     JEQ  L4CD0		Null? Weitermachen, wir nehmen die aus dem File
     CB   R0,R2		Identisch?
     JNE  L4C7A		Nein - Bad Open Attribute!

L4CD0 BLWP @>5A(R9)
     DATA >0063	R3 zum lesen setzen
     MOVB R0,@-2(R15)	Satzlänge lt. FCB
     BLWP @>5A(R9)
     DATA >8001          R0 wiederherstellen
     ANDI R0,>0600	Mode Bits isolieren
     CLR  R2
     SETO R3
     CI   R0,>0600	Append?
     JNE  L4D28          nicht Append
     MOV  @>56(R9),R4	FCB Zeiger
     MOV  R4,R7	aufheben
     AI   R4,>000E	zeigt auf Anzahl derzeit belegter Sektoren
     BLWP @>5A(R9)
     DATA >0082	R4 setzen
     MOVB @>FBFE(R15),R3	High-Byte lesen
     SWPB R3
     MOVB @>FBFE(R15),R3	Low-Byte lesen
     SWPB R3	justieren
     MOVB @>FBFE(R15),R2	EOF Offset
     DEC  R3		berechne Offset des letzten Sektors
     JLT  L4D28		Keine Datensektoren - haben fertig
     BLWP @>5A(R9)
     DATA >3000          R2,3 sichern
     AI   R7,>0100	FCB-Zeiger auf Datenpuffer richten
     BL   @STKJMP
     DATA L43DC		Lese den FDS des Files
     BLWP @>5A(R9)
     DATA >3001          R2,3 wiederherstellen
L4D28	BL @L4D5A
	B @STKRET	Ende
*************************************************************************
* Subroutine File-Status Byte im FDS anhand des Status-Byte im PAB setzen
* 
* R2	Status-Byte
* R4	zeigt auf die entsprechende Stelle im aktuellen FDS.
*************************************************************************
L4D30 BLWP @>5A(R9)
     DATA >8001          R0 wiederherstellen, Flag/Status
     BLWP @>5A(R9)
     DATA >8000          und gleich wieder sichern

     LI   R2,>0002       INT/FIX
     MOV  @>56(R9),R4    Zeiger auf FDS-Puffer
     SLA  R0,4           Record-Type Bit ins Carry
     JNC  L4D4E          Null - also FIXED
     LI   R2,>0082       File-Status INT/VAR
     MOV  R0,R0	Display?
L4D4E JLT  L4D52          High-Bit -> INTERNAL
     DECT R2             Status DIS/VAR
L4D52 AI   R4,>000C       Zeiger auf File-Status Byte im FDS
     SWPB R2             Byte zum schreiben vorbereiten
	RT	Ende

*****************************************************************
* Subroutine Record-Pointer in den Header des File-Control Blocks
*****************************************************************
L4D5A MOV  @>56(R9),R4    FCB-Puffer Adresse
     AI   R4,>FFFA       -6, zeigt auf Puffer für Record-Offset
     BLWP @>5A(R9)
     DATA >0083          R4 setzen
     MOVB R3,@-2(R15)    Record-Offset setzen
     SWPB R3
     MOVB R3,@-2(R15)
     AI   R4,>0004       zeigt auf File Record-Offset (logischer Offset)
     BLWP @>5A(R9)
     DATA >0083          R4 setzen
     MOVB R2,@-2(R15)    File Record-Offset setzen
	RT	Ende

********************************
* Ausführung CLOSE FILE (4D82)
********************************
FOCLOS BL   @STKJMP
     DATA L4F80
     B    @FOPEND

********************************
* Ausführung READ RECORD (4D8C)
********************************
FOREAD	BL   @STKJMP
     DATA L4F80		Finde FCB, hole Statusbyte
     ANDI R0,>0200	Output?
     JEQ  L4D9C		Nein
L4D98	B    @ILEGOP	Ja -> Illegale Operation!
*
L4D9C BL @L4FAC	Statusflag aus FCB holen
     JLT L4DB6	Variable Länge -> weiter
     BL @L4FC0	Satznummer ermitteln
     JL L4DAE	Satznummer kleiner als letzter Satz? -> OK
L4DA8	BL @L4720	Fehler!
	DATA >A000	Status = 5, End Of File (EOF) oder File geschlossen
*
* Feste Länge
*
L4DAE BL   @STKJMP
     DATA L5026		Berechne und lese korrekten Sektor, R1: *Datenpuffer, R2: *Satz im FCB
     JMP  L4DD8		Mit diesen Daten weiterarbeiten
*
* Variable Länge
*
L4DB6	BL @STKJMP
	DATA L4E12	Datenzeiger, PAB-Zeiger und Byteanzahl ermitteln
	JMP L4DA8	Fehler - EOF oder Datei geschlossen - wird uebersprungen falls kein Fehler
*
	INC R2	Überspringe Längenbyte
	A R4,R0	Gelesene Satzlänge zu Record-Offset addieren
	INC R0	Auf nächsten Eintrag zeigen
	MOV @>56(R9),R5	FCB-Zeiger wieder holen
	DECT R5	auf log. Record-Offset
	SWPB R0
	BLWP @>5A(R9)	
	DATA >00A3	R5 setzen
	MOVB R0,@-2(R15)	logischen Record-Offset schreiben
	MOV R4,R0	Anzahl zu lesender Bytes in R0 aufheben
*
* Ab hier gemeinsamer Code für VAR und FIX
*
L4DD8 MOV  @>54(R9),R4	PAB-Zeiger
     AI   R4,5	auf maximale Datenlänge zeigen
     SWPB R0	Datenlänge vorbereiten
     BLWP @>5A(R9)
     DATA >0083          R4 setzen
     MOVB R0,@-2(R15)    Datenanzahl/Feldlänge in Puffer
     SWPB R0             Längenbyte ins Low-Byte

**********************************************************
* 4DEE	Feld im VDP-RAM *R2 nach *R1 verschieben
* 	R0: Anzahl
*	Aufrufe: 2
**********************************************************
L4DEE MOV  R0,R0          gleich null?
     JEQ  L4E0E          Ja - Ende

L4DF2 BLWP @>5A(R9)
     DATA >0042          R2 setzen
     MOVB @>FBFE(R15),R3 Eintrag lesen
     INC  R2             Input-Pointer weiter
     BLWP @>5A(R9)
     DATA >0023          R1 setzen
	MOVB R3,@-2(R15)    Eintrag schreiben
	INC  R1             Output-Pointer weiter
	DEC  R0             Schleifenzähler - 1
	JNE  L4DF2          weiter
L4E0E	B @STKRET	Ende

***********************************************************
* 4E12	Hole Zeiger auf Daten, Anzahl zu liefernder Bytes und PAB Puffer für VAR Datensätze
*
*	Achtung: direkt hinter dem Aufruf mit STKJMP befindet sich ein Sprung zur Fehlerbehandlung!
*	Dieser wird durch Manipulation des Ruecksprungvektors uebergangen, falls es keinen Fehler (i.d.R. EOF) gab!
***********************************************************
L4E12 BL   @L5100	Akt. log. Record-Offset (R0), Sektor-Offset (R3) und Satzanzahl (R2) ermitteln
     MOV  R3,R3		Offset im Sektor
     JLT  L4E1C		Negativ?
     JMP  L4E40
L4E1C MOV  R3,R0
     INC  R0
     C    R0,R2
     JEQ  L4E0E          Ende mit Fehler!
     BL   @STKJMP
     DATA WRTDBU	Datenpuffer ggf. zurueckschreiben
     MOV  R0,R3
     CLR  R5
     BL   @L509E
     AI   R7,>0100
     BL   @STKJMP
     DATA L43DC
     CLR  R0
     JMP  L4E48
L4E40 MOV  R0,R0
     JNE  L4E48
     C    R0,R2
     JEQ  L4E0E          Ende, Aufruf der Fehlerroutine der rufenden Funktion
L4E48 MOV  R0,R2
     BL   @STKJMP
     DATA L507A
     BLWP @>5A(R9)
     DATA >0042          R2 setzen
     MOVB @>FBFE(R15),R4
     SRL  R4,8
     MOV  R0,R0
     JEQ  L4E6C
     CI   R4,>00FF
     JNE  L4E6C
     BL   @L5100
     JMP  L4E1C
L4E6C BLWP @>5A(R9)	Hier umgehen wir die STKRET Funktion!
     DATA >0011         R11 aus dem letzten Eintrag im VDP-Stack gewinnen
     INCT R11           2 Byte weiter zurückkehren, JMP ueberspringen
     RT			Ende

***************************************
* Ausf}hrung WRITE RECORD
***************************************
FOWRIT BL   @STKJMP
     DATA L4F80
     ANDI R0,>0600       File-Status isolieren
     CI   R0,>0400       Datei im Input-Mode er|ffnet?
     JEQ  L4D98          Ja - Fehler, illegale Operation
     BL   @L4FAC
     JLT  L4EB2
     BL   @L4FC0
     JL   L4EAA
     BLWP @>5A(R9)
     DATA >D800          R0,1,3,4 sichern
     MOV  R0,R3
     BL   @STKJMP
     DATA L4412
     BLWP @>5A(R9)
     DATA >D801          R0,1,3,4 wiederherstellen
     BL   @L50CA
L4EAA BL   @STKJMP
     DATA L5026
     JMP  L4F58		! ACHTUNG: evtl Sprungziel falsch > pruefen! Code >1053
L4EB2 BL   @L5100
     MOV  R3,R3
     JLT  L4EBC
     JMP  L4ED2
L4EBC BLWP @>5A(R9)
     DATA >3000          R2,3 sichern
     BL   @STKJMP
     DATA WRTDBU
     BLWP @>5A(R9)
     DATA >3001          R2,3 wiederherstellen
     INC  R3
     CLR  R0
L4ED2 C    R3,R2
     JNE  L4EE8
     BLWP @>5A(R9)
     DATA >9000          R0,3 sichern
     BL   @STKJMP
     DATA L4412		Sektornummer (absolut) aus File Offset in R3 bestimmen
     BLWP @>5A(R9)
     DATA >9001          R0,3 wiederherstellen
L4EE8 MOV  @>54(R9),R5
     AI   R5,>0005
     BLWP @>5A(R9)
     DATA >00A2          R5 setzen
     MOVB @>FBFE(R15),R4
     SRL  R4,8           Wert ins Low-Byte
     MOV  R4,R5
     A    R0,R5
     INC  R5
     CI   R5,>00FF
     JH   L4EBC
     SETO R2
     MOV  @>56(R9),R1
     A    R5,R1
     AI   R1,>0100
     BLWP @>5A(R9)
     DATA >0023          R1 setzen
     MOVB R2,@-2(R15)
     BLWP @>5A(R9)
     DATA >8000          R0 sichern
     MOV  R3,R0
     BL   @L509E
     AI   R1,>0012
     BLWP @>5A(R9)
     DATA >0023          R1 setzen
     MOVB R5,@-2(R15)
     BL   @L50CA
     BLWP @>5A(R9)
     DATA >2001          R2 wiederherstellen
     MOV  R4,R0
     BL   @STKJMP
     DATA L507A
     SWPB R4
     BLWP @>5A(R9)
     DATA >0043          R2 setzen
     MOVB R4,@-2(R15)
     INC  R2
L4F58 MOV  R2,R3
     MOV  R1,R2
     MOV  R3,R1
     MOV  @>56(R9),R4
     DEC  R4
     BLWP @>5A(R9)
     DATA >0082          R4 setzen
     MOVB @>FBFE(R15),R5
     ORI  R5,>8000       High-Bit setzen
     BLWP @>5A(R9)
     DATA >0083          R4 setzen
     MOVB R5,@-2(R15)    Wert mit gesetztem High-Bit schreiben
     B    @L4DEE         Verschieberoutine aufrufen, Ende

*************************************************
* Subroutine FDS im Pufferbereich suchen (4F80)
*
* Setzt den VDP-Arbeitszeiger an >8356 auf die erste Adresse im korrekten FDS
* und liefert das Flag-Byte aus dem PAB in R0 zur}ck.
************************************************************
L4F80 BL   @STKJMP
     DATA L4852          Filenamen suchen
     MOV  R4,R4          gefunden?
     JEQ  L4F90          Ja
     BL   @L4720         Nein - Fehler!
     DATA >E000          Status = 7, File Error
*
* Seiteneinsprung
*
L4F90 INC  R1             Zeiger auf 1. Filenamenbyte im aktuellen FDS-Puffer
     MOV  R1,@>56(R9)    als VDP-Arbeitszeiger ablegen
     MOV  @>54(R9),R4    PAB-Pointer
     INC  R4             Zeiger auf Flag/Status
     CLR  R0
     BLWP @>5A(R9)
     DATA >0082          R4 setzen
     MOVB @>FBFE(R15),R0 Flag-Byte lesen
     B    @STKRET	Ende

***********************************************
* Subroutine File-Status Byte aus FDS lesen (4FAC)
***********************************************
L4FAC MOV  @>56(R9),R4
     AI   R4,>000C       plus 12
     BLWP @>5A(R9)
     DATA >0082
     MOVB @>FBFE(R15),R0
     RT

***********************************************
* Subroutine Satznummer ermitteln
***********************************************
L4FC0 MOVB @>FBFE(R15),R5
     SRL  R5,8
     JNE  L4FCC
     LI   R5,>0100
L4FCC MOV  @>54(R9),R3
     AI   R3,>0006
     BLWP @>5A(R9)
     DATA >0062          R3 setzen
     MOVB @>FBFE(R15),R1
     SWPB R1
     MOVB @>FBFE(R15),R1
     SWPB R1
     MOV  R1,R0
     JLT  L4FEC
     JMP  L4FF2
L4FEC BL   @L4720         Fehler!
     DATA >8000          Status = 4, Speicher- od. Pufferbereichs}berschreitung
L4FF2 INC  R0
     BLWP @>5A(R9)
     DATA >0063          R3 setzen
     MOVB R0,@-2(R15)
     SWPB R0
     MOVB R0,@-2(R15)
     CLR  R0
     MOV  R1,R3
     DIV  R5,R0
*
* Seiteneinsprung der Offsetberechnung (5100)
*
L500A	MOV @>56(R9),R2	Zeiger auf FCB
	AI   R2,>0012	plus 18 - Anzahl Datensätze
	BLWP @>5A(R9)
	DATA >0042	R2 setzen
	MOVB @>FBFE(R15),R2
	SWPB R2
	MOVB @>FBFE(R15),R2
	C R3,R2	Vergleiche geforderte Satznummer mit maximaler Datensatzanzahl
	RT	Rücksprung

*****************************
* Subroutine
*****************************
L5026 BLWP @>5A(R9)
     DATA >4000          R1 sichern
     AI   R4,>FFEE       18 abziehen
     BLWP @>5A(R9)
     DATA >0082          R4 setzen
     MOVB @>FBFE(R15),R5
     SWPB R5
     MOVB @>FBFE(R15),R5
     SRC  R5,8
     JLT  L504E
     C    R5,R0
     JEQ  L505E
     BL   @STKJMP
     DATA WRTDBU
L504E MOV  R0,R3
     BL   @L509E
     AI   R7,>0100
     BL   @STKJMP
     DATA L43DC
L505E BLWP @>5A(R9)
     DATA >4001          R1 wiederherstellen
     MOV  @>56(R9),R3
     AI   R3,>0011       plus 17
     BLWP @>5A(R9)
     DATA >0062
     MOVB @>FBFE(R15),R0
     SRL  R0,8
     MPY  R0,R1
*
* Seiteneinsprung
*
L507A     A    @>56(R9),R2
     AI   R2,>0100
     MOV  @>54(R9),R3
     INCT R3
	BLWP @>5A(R9)
     DATA >0062          R3 setzen
     MOVB @>FBFE(R15),R1
     SWPB R1
     MOVB @>FBFE(R15),R1
     SWPB R1
     B    @STKRET         Ende

**********************************************
* Subroutine (509E)
**********************************************
L509E MOV  @>56(R9),R7
     MOV  R7,R1
     AI   R1,>FFFA       minus 6
     BLWP @>5A(R9)
     DATA >0023          R1 setzen
     MOVB R0,@-2(R15)
     SWPB R0
     MOVB R0,@-2(R15)
     AI   R1,>0004
     SWPB R5
     BLWP @>5A(R9)
     DATA >0023          R1 setzen
     MOVB R5,@-2(R15)
     RT			Ende

******************************************
* Subroutine (50CA)
******************************************
L50CA MOV  @>56(R9),R2
     BLWP @>5A(R9)
     DATA >0042          R2 setzen
     MOVB @>FBFE(R15),R10
     ORI  R10,>8000
     BLWP @>5A(R9)
     DATA >0043          R2 setzen
     MOVB R10,@-2(R15)   Wert mit gesetztem High-Bit rueckschreiben
     AI   R2,>0012       plus 18
     INC  R3
     BLWP @>5A(R9)
     DATA >0043          R2 setzen
     SWPB R3
     MOVB R3,@-2(R15)
     SWPB R3
     MOVB R3,@-2(R15)
	RT	Ende

******************************************************************
* 5100 	Logischen Record Offset (R0), aktuellen Record Offset (R3)
*	und gesamte Datensatzanzahl des Files (R2) ermitteln
*	Nach Rückkehr ist das Statusbit L (less than) anhand des
*	Vergleichs der geforderten mit der maximalen Satzanzahl
*	gesetzt. Ist L gesetzt (JLT), befindet sich die Satznummer
*	vor dem aktuellen Ende der Datei.
*******************************************************************
L5100 MOV @>56(R9),R8	FCB Zeiger
     MOV R8,R4	Sichern
     AI R4,>0100	Zeiger auf Datenpuffer
     DECT R8	log. Record-Offset
     BLWP @>5A(R9)
     DATA >0102          	R8 setzen
     MOVB @>FBFE(R15),R2	log. Record-Offset lesen
     SRL R2,8	Als Word nutzbar machen
     MOV R11,R10	Rückkehr sichern
     BL @VDPRGP		Record Offset nach R0 lesen
     DATA >FFFC          -4, Offset zu Satznummer
     MOV R0,R3	In R3 zurückgeben
     MOV R10,R11
     MOV R2,R0	Log. Record-Offset in R0
	B @L500A	Nutze Teil dieser Funktion um die gesamte Anzahl der Datensätze nach R2 zu bringen und mit R3 zu vergleichen

**********************************************
* Ausf}hrung RESTORE (File-Pointer) (512A)
**********************************************
FOREST	BL   @STKJMP
	DATA L4F80          FDS im Puffer suchen, Flag-Byte aus dem PAB lesen
     BLWP @>5A(R9)
     DATA >8000          R0 (Flag/Status) sichern
     ANDI R0,>0600       Filestatus isolieren
     JEQ  L5146          Update
     CI   R0,>0400       Input?
     JEQ  L5146          Ja
     B    @ILEGOP         Nein - Fehler, illegale Operation
L5146 BL   @STKJMP
     DATA WRTDBU          Datensektor schreiben wenn High-Bit der LW-Nr. gesetzt
     BLWP @>5A(R9)
     DATA >8001          R0 wiederherstellen, Filestatus
     ANDI R0,>0100       Filetyp isolieren
     JNE  L517A          Bit gesetzt, relatives File, Befehl ignorieren!
L5158 CLR  R2             Einsprung aus OPEN FILE mit Angabe eines Records<>0
*                         -> Filedatenheader in den Grundzustand bringen
     SETO R3
     BL   @L4D5A         Pointer in den FCH (File Control Header), R2: Record-
*                         Offset im File, R3: Record Offset
     CLR  R0
     MOV  @>54(R9),R8    PAB-Pointer
     AI   R8,>0006       Zeiger auf Recnum
     BLWP @>5A(R9)
     DATA >0103          R8 setzen
     MOVB R0,@-2(R15)
     NOP
     MOVB R0,@-2(R15)    Record-Number in PAB schreiben
L517A B    @STKRET         Ende

*************************************
* Ausf}hrung LOAD PROGRAM-FILE (517E)
*************************************
FOLOPF	BL @STKJMP
     DATA L48B0          freien FDS-Puffer suchen, FDS einlesen
     MOV  R4,R4          gefunden?
     JEQ  L518E          Ja
L5188 BL   @L4720         Nein - Fehler!
     DATA >E000          Status = 7, File Error
L518E BL   @VDPR56
     DATA >000C          File-Status lesen
     ANDI R0,>0100       P-File Bit isolieren
     JEQ  L5188          nicht gesetzt - Fehler! -> Datenfile!
     INCT R8
     BLWP @>5A(R9)
     DATA >0102          R8 setzen
     MOVB @>FBFE(R15),R1
     SWPB R1
     MOVB @>FBFE(R15),R1 Sektoranzahl lesen
     SRC  R1,8
     JEQ  L5188          Null - Fehler!
     BL   @L5270         File-Parameter aus dem PAB ermitteln
     INCT R8             Zeiger auf EOF-Offset Byte
     CLR  R4
     BLWP @>5A(R9)
     DATA >0102          R8 setzen
     MOVB @>FBFE(R15),R4 EOF-Offset lesen
     C    R1,R2          Anzahl der File-Sektoren (R1) mit der aus dem PAB ermittelten Sektoranzahl vergleichen (R2).
     JH   L5188          Fehler! -> File ist l{nger als erlaubt
     JNE  L51CC
     C    R0,R4          EOF-Offset im PAB (R0) mit EOF-Offset im FDS (R4) vergleichen.
     JL   L5188          Fehler! -> einige Bytes zuviel im File
L51CC CLR  R3
     SWPB R4             EOF-Offset aus dem FDS holen (ist im Zweifelsfall geringer als im PAB erlaubt!)
L51D0 DEC  R1             Sektoranzahl -1
     JEQ  L51EE          wenn Sektornr. =0 dann fertig
     BLWP @>5A(R9)
     DATA >D900          R0,1,3,4,7 sichern
     BL   @STKJMP
     DATA L43DC          Sektor-I/O
     BLWP @>5A(R9)
     DATA >D901          R0,1,3,4,7 wiederherstellen
     INC  R3
     AI   R7,>0100       R7 ist der Zeiger in den Datenpufferbereich (aus PAB)
     JMP  L51D0          n{chsten Sektor lesen
L51EE MOV  R4,R4          Sektor-Offset pr}fen
     JNE  L51FA          nicht null!
     BL   @STKJMP
     DATA L43DC          Null - letzten Sektor lesen
     JMP  L521C          Ende
L51FA MOV  R7,R5          Pufferzeiger kopieren
     MOV  @>56(R9),R7    Zeiger auf FDS
     AI   R7,>0100       auf Datenbereich zeigen
     BLWP @>5A(R9)
     DATA >0D00          R4,5,7 sichern
     BL   @STKJMP
     DATA L43DC          letzten Sektor in separaten Bereich lesen
     BLWP @>5A(R9)
     DATA >E001          R0,1,2 wiederherstellen, R0: altes R4, EOF-Offset
*                         R1: altes R5, Zeiger in P-File Puffer, R2: altes R7,
*                         Zeiger in den Zwischenpuffer.
     BL   @STKJMP
     DATA L4DEE          Block *R2 nach *R1 verschieben
L521C B    @FOPEND         Ende, Filedatenbereich freigeben etc.

**************************************
* Ausfuehrung SAVE PROGRAM-FILE
**************************************
FOSVPF BL   @STKJMP
     DATA OPFOUT
     BL   @L5270	Parameter ermitteln
     CLR  R3
L522C BLWP @>5A(R9)
     DATA >B100          R0,2,3,7 sichern
     BL   @STKJMP
     DATA L43FC		Datensektor schreiben
     BLWP @>5A(R9)
     DATA >B101          R0,2,3,7 wiederherstellen
     INC  R3
     AI   R7,>0100
     DEC  R2
     JNE  L522C
     MOV  @>56(R9),R1
     AI   R1,>000C
     LI   R2,>0100
     BLWP @>5A(R9)
     DATA >0023          R1 setzen
     MOVB R2,@-2(R15)
     AI   R1,>0004
     BLWP @>5A(R9)
     DATA >0023          R1 setzen
     MOVB R0,@-2(R15)
     B    @FOPEND	Ende File-Ops

****************************************************
* Subroutine P-File Parameter aus dem PAB holen (5270)
*
*     Output: R0: EOF-Offset im letzten Sektor
*             R2: Sektoranzahl, R7: PAB-Pufferadresse der Daten.
**********************************************
L5270 MOV  @>54(R9),R0    PAB-Pointer
     INCT R0
     BLWP @>5A(R9)
     DATA >0002          R0 setzen
     MOVB @>FBFE(R15),R7
     SWPB R7
     MOVB @>FBFE(R15),R7 Adresse des Datenpuffers nach R7
     SWPB R7
     AI   R0,>0004       Zeiger auf Anzahl zu lesender/schreibender Bytes
     BLWP @>5A(R9)
     DATA >0002          R0 setzen
     MOVB @>FBFE(R15),R2 High-Byte lesen, damit = Sektoranzahl da n mal >100 !
     SRL  R2,8
     CLR  R0
     MOVB @>FBFE(R15),R0 Low-Byte lesen
     JEQ  L52A2          null
     INC  R2             nicht null, also ein Sektor mehr
L52A2 B    *R11           Ende


**************************************************
* Ausfuehrung FILE STATUS (52A4)
**************************************************
FOSTAT BL   @STKJMP
     DATA L4852	Filenamen aus dem PAB in den FNCB, in allen File-Puffern nach diesem Namen suchen
     MOV  R4,R4
     JEQ  L52CE
     BL   @STKJMP
     DATA L48BA		einen freien Puffer suchen; wenn es noch einen gibt, dann Sektor 1 lesen und danach den Filenamen auf der Diskette suchen
     LI   R0,>8000
     MOV  R4,R4
     JNE  L5350
     MOV  @>56(R9),R1
     CLR  R2
     BLWP @>5A(R9)
     DATA >0023          R1 setzen
     MOVB R2,@-2(R15)
     JMP  L533A
L52CE BL   @STKJMP
     DATA L4F90
     BL   @L4FAC
     JLT  L52DC
     JMP  L52E8
L52DC BL   @STKJMP
     DATA L4E12
     JMP  L530A
     CLR  R2
     JMP  L533A
L52E8 MOVB @>FBFE(R15),R5
     SRL  R5,8
     JNE  L52F4
     LI   R5,>0100
L52F4 BL   @VDPR54
     DATA >0006
     MOV  R0,R3
     JLT  L5336
     BL   @L500A
     CLR  R2
     JL   L533A		Status stammt noch aus dem Vergleich der geforderten mit der maximalen Satznummer!
     DIV  R5,R2
     MOV  R2,R3
L530A BL   @VDPR56
     DATA >000E
     INC  R3
     LI   R2,>0100
     S    R0,R3
     JGT  L531C
     JMP  L533A
L531C BL   @STKJMP
     DATA L4780          Volume-ID Update
     MOV  R3,R4
     MOV  R5,R8
     AI   R8,>000A       plus 10
     BL   @L551A
     LI   R2,>0100
     C    R3,R4
     JHE  L533A
L5336 LI   R2,>0200
L533A BL   @VDPR56
     DATA >000C
     ANDI R0,>8F00
     JGT  L534C		Was ist das denn? Funktioniert JHE nicht?
     JEQ  L534C
     ORI  R0,>0080
L534C SLA  R0,3
     SOCB R2,R0
L5350 MOV  @>54(R9),R1
     AI   R1,>0008
     BLWP @>5A(R9)
     DATA >0023          R1 setzen
     MOVB R0,@-2(R15)
     B    @STKRET         Ende

**************************************************
* Ausfuehrung OPEN DISK-Directory
**************************************************
DOOPEN MOVB @>FBFE(R15),R0 Flag/Status lesen
     ANDI R0,>1E00       Filetyp ignorieren, Sequentiell ist Standard
     CI   R0,>0C00       Internal,Input,Fixed?
     JEQ  L537A          Ja
L5374 BL   @FOSCRA         File Error, Seiteneinsprung Scratch Record
     DATA >4000          Bad Open Attribute
L537A BL   @VDPR54         Record Length lesen
     DATA >0004
     SRL  R0,8           ins Low-Byte
     JEQ  L538A          Null
     CI   R0,>0026       oder 38
     JNE  L5374          File Error
L538A LI   R0,>2600       Default-Wert f}r Reclen
     BLWP @>5A(R9)
     DATA >0103          R8 setzen
     MOVB R0,@-2(R15)    Reclen in PAB
     CLR  R7             Puffer f}r Adresse eines freien Blocks
     BL   @L5554         Platz im VDP-RAM suchen
     DATA L53A6          Fortsetzung des Programms im Fehlerfall!

* Seiteneinsprung CLOSE DIRECTORY bei Fehler (Datei nicht geoeffnet)

L53A0 BL   @L4720         Ruecksprung bei Blank im ersten Namensbyte und LW-Nr.
*			gleich. Das bedeutet, dass das File schon offen ist.
     DATA >E000          File Error
L53A6 MOV  R7,R7          Wurde ein freier Puffer gefunden?
     JNE  L53B0          Ja
     BL   @FOSCRA         Nein, Seiteneinsprung SCRATCH
     DATA >8000          Fehler, kein Platz im Speicher
L53B0 BLWP @>5A(R9)
     DATA >00E3          R7 setzen
     MOVB R3,@-2(R15)    LW-Nr.
     SWPB R3
     MOVB R3,@-2(R15)    Blank, um bei der n{chsten Suche diesen Block als belegt zu melden
     B    @STKRET         Ende

**************************************************
* Ausfuehrung CLOSE DISK-DIRECTORY
**************************************************
DOCLOS BL   @L5554         Datenpuffer suchen
     DATA L53A0          Adresse im Fehlerfall, wenn File nicht offen ist
     CLR  R0
     BLWP @>5A(R9)
     DATA >0103          R8 setzen
     MOVB R0,@-2(R15)
     B    @STKRET         Ende

********************************************
* Ausf}hrung INPUT DISK-DIRECTORY RECORD-0
********************************************
DOREAD BL   @L5554         Datenpuffer suchen, Zeiger auf Filenamen in R8 zur}ck
     DATA L53A0          Ansprung im Fehlerfall, wenn File nicht offen ist
     INC  R8             zeigt auf 2. Byte des Filenamenpuffers
     MOV  R8,R5          kopieren
     BL   @VDPR54
     DATA >0006          Recnum aus PAB lesen
     MOV  R0,R2          kopieren
     INC  R2             +1
     BLWP @>5A(R9)
     DATA >0103          R8 setzen
     MOVB R2,@-2(R15)
     SWPB R2
     MOVB R2,@-2(R15)    inkrementierten Wert zur}ck, n{chster Eintrag
     SLA  R0,1           aktuelle Record Nummer mal 2
     MOVB R0,R0          unter 256 (also vorher 128)?
     JEQ  L540A          Ja - weiter
     BL   @L4720         Nein - Fehler
     DATA >A000          Status = 5, EOF
L540A SETO R2
     MOV  R0,R4          erster Aufruf?
     JEQ  L5486          Ja - Volume-ID lesen
     LI   R4,>0001       Sektornr. = 1
     BL   @STKJMP
     DATA L47FC          Sektor 1 lesen
     MOV  R5,R8          Adresse des Datenpuffers
     AI   R5,>00FF
     DECT R0
     A    R0,R8          Position im Sektor 1 Puffer
     BL   @VDPRD         Sektornr. aus dem Puffer holen
     MOV  R0,R4          das ist die Nummer des zu lesenden FDS
     JEQ  L547C          wenn Null, dann ist Schlu~
     BL   @STKJMP
     DATA L47FC          den angegebenen FDS lesen
     BL   @VDPR56
     DATA >010E          Anzahl der vom File belegten Sektoren lesen. Die Basisadresse des FDS-Puffer steht in >8356!
     MOV  R0,R6          diesen Wert f}r sp{ter aufheben
     INC  R6             den durch den FDS belegten Sektor addieren
     MOVB @>FBFE(R15),R3 EOF-Eintrag im FDS }berspringen
     LI   R2,>0A00		ABWEICHUNG - war >000A
     MOVB @>FBFE(R15),R3 Satzl{nge holen
     SRL  R3,8           ins Low-Byte
     DECT R8             R8 zeigt nun auf das File-Status Byte im FDS
     BLWP @>5A(R9)
     DATA >0102          R8 setzen
     MOVB @>FBFE(R15),R0 File-Status lesen
     MOV  R0,R7          kopieren
     ANDI R0,>0800       Protection-Bit isolieren
     SZCB R0,R7          dieses Bit ggfs. in R7 l|schen
     SRL  R7,8           Filetyp ins Low-Byte
     INC  R7             plus 1
     CI   R7,>0002       Program-File?
     JNE  L546C          Nein
     AI   R7,>0003       Ja - Filetyp gleich 5
L546C CI   R7,>0008       VAR-Bit gesetzt?
     JL   L5476          Nein
     AI   R7,>FF81       Ja - richtige Typnummer erzeugen
L5476 SLA  R0,4
     SOC  R0,R7
     JMP  L5484
*******************************
* Bearbeitung beim ersten Record nach EOF
******************************
L547C CLR  R2             Namen}bergabe }berspringen
     CLR  R6             Gesamtsektorzahl
     CLR  R3             Record Length
     CLR  R7             Dateityp
L5484 JMP  L54A4
********************************
* Einsprung, wenn 1 Eintrag gelesen werden soll
***********************************
L5486 AI   R5,>00FF       Pufferadresse erh|hen, hinter FDS-Bereich
     BL   @STKJMP
     DATA L47FC          Sektor 0 lesen
     BL   @VDPR56
     DATA >010A          Gesamtzahl der Disksektoren lesen, >8x56 zeigt auf den Pufferbereich
     MOV  R0,R6          kopieren
     DECT R6             Systemsektoren abziehen
     BL   @L551A         Anzahl freier Sektoren bestimmen, Rueckgabe in R3
     CLR  R7
     LI   R2,>0A00       Schleifenz{hler
L54A4 BL   @VDPR54
     DATA >0002          Datenpufferadresse aus dem PAB holen
     MOV  R0,R8          kopieren
     INC  R8             +1
     SRL  R2,8           Schleifenz{hler ins Low-Byte
     JEQ  L54DE
     CLR  R1
L54B4 BLWP @>5A(R9)
     DATA >00A2          R5 setzen
     MOVB @>FBFE(R15),R1 Namensbyte lesen
     CI   R1,>2000       Blank?
     JEQ  L54D6          Ja
     BLWP @>5A(R9)
     DATA >0103          R8 setzen
     MOVB R1,@-2(R15)    Namensbyte }bergeben
     INC  R5             Input +1
     INC  R8             Output +1
     DEC  R2             Z{hler -1
     JNE  L54B4          weiter
L54D6 NEG  R2
     AI   R2,>000A       Namenl{nge berechnen
     SWPB R2             ins High-Byte
L54DE BLWP @>5A(R9)
     DATA >0003          R0 setzen
     MOVB R2,@-2(R15)    L{ngenbyte }bergeben, vor dem Namen
     BLWP @>5A(R9)
     DATA >0103          R8 setzen, Startposition der numerischen Daten
     MOV  R7,R1          Dateityp nach R1
	BL @C2R100	Wert in R1 im Radix 100 Format im VDP-RAM ablegen
     MOV R6,R1
     BL @C2R100		desgleichen die Gesamtsektorzahl dahinter
     MOV R3,R1
     BL @C2R100		und die freien Sektoren/Record Length
     MOV @>54(R9),R8
     AI R8,>0005
     LI R0,>2600
     BLWP @>5A(R9)
     DATA >0103          R8 setzen
     MOVB R0,@-2(R15)
     B    @STKRET         Ende

****************************************************
* Subroutine Anzahl der freien Sektoren berechnen
*****************************************************
L551A AI   R8,>002E       von der Gesamtsektorzahl auf den Beginn der Bitmap
     LI   R2,>00C8       Offset auf das Ende der Bitmap
     CLR  R3             Z{hler der freien Sektoren
     BLWP @>5A(R9)
     DATA >0102          R8 setzen
L552A MOVB @>FBFE(R15),R1 Eintrag lesen
     AI   R1,>0100       Schleifenoffset
     SRL  R1,8           ins Low-Byte
     JEQ  L554E          Eintrag war >FF
     DEC  R1             Schleifenoffset weg
     JNE  L5540          nicht alle Bits null!
     AI   R3,>0008       doch - gibt 8 freie Sektoren dazu
     JMP  L554E          weiter
L5540 LI   R0,>0008       8 Bits pr}fen
L5544 SRL  R1,1           unteres Bit herausschieben ins Carry-Bit
     JOC  L554A          gesetzt - Sektor belegt
     INC  R3             nicht gesetzt - noch ein freier Sektor dazu
L554A DEC  R0             Schleife beendet?
     JNE  L5544          Nein
L554E DEC  R2             n{chster Eintrag der Sektor-Bitmap
     JNE  L552A          noch nicht Schlu~!
     RT           Ende

***************************************************************
* Subroutine Freien Puffer f}r's Directory suchen
*
*Erkennt einen freien Puffer daran, da~ das erste Namensbyte >00 ist und springt
*}ber das DATA zur}ck. Liefert die Adresse dieses Bytes (Pufferanfang) in R7
*zur}ck. War das erste Byte im Namen ein Blank (Leerzeichen) und stand die
*aktuelle LW-Nr. davor, dann erfolgt der R}cksprung ins rufende Programm, da
*dann die Datei f}r dieses LW bereits offen ist. Die Adresse des Puffers wird
*dann in R8 und >8356 zur}ckgegeben.
**************************************************************************
L5554 MOV  *R11+,R10      R}ckkehradresse aus dem DATA
     MOV  R11,R5         R}ckkehr Programm
     MOV  @>56(R9),R8    VDP-RAMTOP+2
     AI   R8,>0003       auf Fileanzahl zeigen
     BLWP @>5A(R9)
     DATA >0102          R8 setzen
     MOVB @>FBFE(R15),R2 Filezahl lesen
     SRA  R2,8           ins Low-Byte
     AI   R8,6           Zeiger auf Laufwerknummer
     LI   R3,>0020       Blank
     MOVB R6,R3          LW-Nr. im High-Byte
L5576 BL   @VDPRD         Wert *R8 nach R0 lesen
     C    R3,R0          Laufwerknummer o.K. und von Blank gefolgt?
     JEQ  L5590          Ja - File ist schon offen
     ANDI R0,>00FF       High-Byte l|schen
     JNE  L5586          nicht null, Puffer belegt
     MOV  R8,R7          Zeiger auf freien Puffer sichern
L5586 AI   R8,>0206       auf den n{chsten Pufferblock zeigen
     DEC  R2             Filezahl - 1
     JNE  L5576          es gibt noch was zu suchen
     B    *R10           R}cksprung }ber DATA, kein Platz wenn R7 = >0000 !!
*
L5590 INC  R8             Pointer auf Filenamen
     MOV  R8,@>56(R9)    in VDP-Pointer
     B    *R5            ins Programm zur}ck

*******************************************************************************
* Subroutine Wert in R1 in Radix 100 Format bringen und im VDP-RAM ablegen (5598)
* Referenzen: 3
* Die VDP-Zieladresse wird vom aufrufenden Programm gesetzt
********************************************************************************
C2R100	LI R2,>0800	Laengenbyte
     MOVB R2,@-2(R15)    als erste Position
     MOV  R1,R5          Rechenwert kopieren
     ANDI R1,>7FFF       nur positive Werte
	CI R1,100	mit .100 vergleichen
     JL   L55BA          kleiner
     CLR  R0
	LI R4,100	Divisor laden
     DIV  R4,R0          Wert in R0,1 durch 100 teilen. Der ganzzahlige Teil ist in R0
     ORI  R0,>4100       Exponent 1 (100E1)
     JMP  L55C4
L55BA MOV  R1,R0
     JEQ  L55C2          Wert ist >0000
     ORI  R0,>4000       Exponent 0 (100E0) -> Einer
L55C2 CLR  R1
L55C4 MOV  R5,R5          alten Rechenwert pr}fen
     JLT  L55CA          Wert war negativ
     JMP  L55CC
L55CA NEG  R0             Exponent negieren
L55CC MOVB R0,@-2(R15)    Exponent schreiben
     SWPB R0
     MOVB R0,@-2(R15)    Ganzzahlige Mantisse schreiben
     SWPB R1
     MOVB R1,@-2(R15)    1. und 2. Nachkommastelle
     LI   R2,>0005
L55E0 MOVB R2,@-2(R15)    5 Nullen anfuegen
     DEC  R2
     JNE  L55E0
	RT	Ende

***************************************************************
* Ausf}hrung Subroutine >10, Sektor lesen/schreiben
******************************************************
SBR10C	MOV  R11,R7
     BL   @MAINIT             allgemeine Initialisierung
     MOV  @>50(R9),@>4A(R9)  Wert der Sektornummer kopieren
     B    @L5A0A             Programm im oberen ROM fortsetzen
*************************************************************
* Ausfuehrung Subroutine >11, Diskette formatieren/initialisieren
*************************************************************
SBR11C MOV  R11,R7
     BL   @MAINIT         allgemeine Initialisierung
     B    @L5A10         ab ins obere ROM

****************************************************************
* Ausfuehrung Subroutine >12, Fileschutz aendern
*     Input: LW-Nr. in >834C (B), Fileschutzbyte in >834D (B), Filenamenzeiger in
*     >834E (W) (Name im VDP-RAM!)
********************************************************
SBR12C MOV  R11,R7
     BL   @MAINIT         allgemeine Initialisierung
     MOVB  @>4D(R9),R0    Fileschutzcode lesen
     ANDI R0,>0800       Protection-Bit isolieren, der Rest ist irrelevant
     BLWP @>5A(R9)
     DATA >8000          R0 sichern
     MOV  @>4E(R9),R0    Pointer auf Filenamen
     BL   @STKJMP
     DATA L5706          kopieren, FDS laden, Fehlermeldung ggfs. extern
     BLWP @>5A(R9)
     DATA >2001          R2 wiederherstellen, altes R0, Fileschutzcode
     BL   @VDPR56
     DATA >000C          File-Status lesen
     ANDI R0,>F700       Low-Byte l|schen
     SOCB R2,R0          neues Fileschutzbit einbringen
     BLWP @>5A(R9)
     DATA >0103          R8 setzen 
     MOVB R0,@-2(R15)    ge{nderten Wert zur}ckschreiben
L563E MOV  @>56(R9),R8    Zeiger auf erstes Byte im Filenamen
     BLWP @>5A(R9)
     DATA >0102          neues R8 setzen
     MOVB @>FBFE(R15),R0 Byte lesen
     ORI  R0,>8000       High-Bit setzen
     BLWP @>5A(R9)
     DATA >0103          R8 wieder setzen
     MOVB R0,@-2(R15)    Wert mit gesetztem High-Bit wieder schreiben
     B    @FOPEND         Ende in externem Programmteil

**************************************************************
*-1Ausf}hrung Subroutine >13, Filenamen {ndern-0
*
*     Input: LW-Nr. in >834C (B), VDP-Zeiger 'Neuer Name' in >834E (W),
*     VDP-Zeiger 'Alter Name' in >8350 (W).
******************************************************************
SBR13C MOV  R11,R7
     BL   @MAINIT         Initialisierung
     MOV  @>4E(R9),R0    Filenamenzeiger neu
     BLWP @>5A(R9)
     DATA >8000          R0 sichern
     MOV  @>50(R9),R0    Filenamenzeiger alt
     BL   @STKJMP
     DATA L5706          Sektor 1 und FDS lesen
     BL   @L4588         Datenblock um 1 Wort nach unten verschieben
     BL   @VDPR56         Filestatus lesen
     DATA >000C
     ANDI R0,>0800       Protecion-Bit isolieren
     JEQ  L568E          Nicht gesetzt
     BL   @L4720         Gesetzt - Fehler
     DATA >2000          Status = 1, schreibgesch}tzt
L568E BL   @VDPR56
     DATA >FFFC          Sektornummer des gelesenen FDS
     MOV  R0,R1          in R1 sichern
     BLWP @>5A(R9)
     DATA >8001          R0 wiederherstellen, Filenamenzeiger neu
     BLWP @>5A(R9)
     DATA >4000          R1 sichern, Sektornummer
     BL   @L594E         LW-Nr. in R6, Pointer auf Filenamen in R0, Name (neu) mit LW-Nr. in den FNCB
     BL   @STKJMP
     DATA L48E6          passenden FDS lesen
     MOV  R4,R4          gibt's das File mit diesem Namen schon?
     JEQ  L5720          Ja - Fehler
     BL   @L45B8         Nein, das File existiert noch nicht, Platz im Sektor 1 Puffer f}r einen neuen Eintrag schaffen.
     BLWP @>5A(R9)
     DATA >0801          R4 wiederherstellen
     BLWP @>5A(R9)
     DATA >0103          R8 setzen
     MOVB R4,@-2(R15)
     SWPB R4
     MOVB R4,@-2(R15)    die alte Sektornummer wieder schreiben, jedoch an anderer Position
     SWPB R4
     SETO R2
     CLR  R5
     BL   @STKJMP
     DATA L47F8          alten FDS wieder lesen
     MOV  R5,R1          Zeiger auf FDS-Puffer
     MOV  @>58(R9),R0
     AI   R0,>0101       Zeiger auf FNCB
     DEC  R1
     BL   @>5964         Namen verschieben
     CLR  R2		Sektor schreiben index fuer folgenden Funktionsaufruf
     BL   @STKJMP
     DATA L47FC          FDS mit neuem Namen wieder schreiben
     BL   @STKJMP
     DATA L47E4          Sektor 1 schreiben
     MOV  @>56(R9),R1    Zeiger auf 1. Namensbyte
     BLWP @>5A(R9)
     DATA >0023          R1 setzen
     MOVB R4,@-2(R15)    1. Bye l|schen, Puffer wieder freigeben
     B    @STKRET         Ende

**************************************************************************
* Subroutine FDS anhand des Filenamens *R0 in einen freien Puffer bringen
*********************************************************************
L5706 CLR  R6
     MOVB @>4C(R9),R6    LW-Nr.
     BL   @L594E         Filenamen *R0 in den FNCB
     BL   @STKJMP
     DATA L4872          Filenamen suchen, bzw. freien Puffer, R1 zeigt bei erfolgreicher Suche auf die Startadresse des Puffers.
     BL   @STKJMP
     DATA L48B6          FDS suchen und lesen
     MOV  R4,R4          Namensgleichheit?
     JEQ  L5726          Ja
L5720	BL   @FOSCRA         Nein! Seiteneinsprung SCRATCH
     DATA >E000          File Error
L5726	B @STKRET	Ende

*******************************************************
* Ausf}hrung Subroutine >14, File kopieren INPUT-0
*
*
*     Input: LW-Nr. in >834C (B), Kopier/Status-Flag in >834D (B) (00 - Filesta-
*     tus, sonst -> Sektoranzahl), Filenamenzeiger (VDP) in >834E, Datenblockoff-
*     set in >8350 (B).
*     Output: Anzahl tats{chlich gelesener Sektoren in >834C (W)
*     Die Benutzung des Datenblocks wird in einem Beispielprogramm gezeigt
************************************************************************************
SBR14C MOV  R11,R7

     BL   @MAINIT         Initialisierung
     BL   @L5986         Parameter }bernehmen
     BL   @L59AC         File lesen, Output: R0: Anzahl vom File belegter Sektoren,
*			R2: altes R0, R4:+2, R7: Inhalt *R4+, R3: Inhalt *R4.
     MOV  R2,R2          Flag =0 ?
     JEQ  L5778          Ja - Status
     S    R3,R0          Record Offset abziehen
     JGT  L5744          noch was }brig?
     CLR  R2             Nein, Z{hler bearbeiteter Sektoren = 0
     JMP  L5772          ]bergabe des Wertes
L5744 C    R2,R0          geforderte Anzahl Sektoren (R2) mit Rest vergleichen
     JL   L574A          nicht bis zum Ende
     MOV  R0,R2          Doch - neue Anzahl bestimmen
L574A BLWP @>5A(R9)
     DATA >2000          R2 sichern, f}r ]bergabe in PAD (>834C)
L5750 BLWP @>5A(R9)
     DATA >3100          R2,3,7 sichern
     BL   @STKJMP
     DATA L43DC          Datensektor lesen, R3: Record-Offset, R7: Pufferadresse
     BLWP @>5A(R9)
     DATA >3101          R2,3,7 wiederherstellen
     INC  R3             n{chster Record
     AI   R7,>0100       Puffer weiter
     DEC  R2             Sektorz{hler auf Null?
     JNE  L5750          Nein - weiter
L576C BLWP @>5A(R9)
     DATA >2001          R2 wiederherstellen, Anzahl gelesener Sektoren
L5772 MOV  R2,@>4C(R9)    im PAD zur}ckgeben
     JMP  L578C          Ende
L5778 MOV  R0,*R4+        Anzahl belegter Sektoren in den Puffer f}r den Sektor-Offset bringen.
     DECT R8             zeigt auf File-Status
     INCT R2             R2 = 2!
     BL   @L59E0         File-Status und RPS *R4 abliefern
     LI   R2,>0004
     A    R2,R8
     BL   @L59E0         EOF-Offset, Reclen und Recnum (max) }bernehmen (*R4)
L578C BL   @STKJMP
     DATA FOPEND          Pufferbereich freigeben
     CLR  @>50(R9)       Fehlerbyte l|schen, Fehler wurden ggfs. extern gemeldet
     B    @STKRET         Ende

*********************************************************
* Ausführung Subroutine >15, File kopieren, OUTPUT (579A)
*********************************************************
SBR15C	MOV  R11,R7
     BL   @MAINIT         Initialisierung
     BL   @L5986         Parameter }bernehmen
     JEQ  L57CE          Sektoranzahl = 0 -> er|ffnen, 1. Zugriff
     BL   @L59AC         FDS lesen
     BLWP @>5A(R9)
     DATA >2000          R2 sichern
L57B0 BLWP @>5A(R9)
     DATA >3100          R2,3,7 sichern
     BL   @STKJMP
     DATA L43FC          Datensektor schreiben
     BLWP @>5A(R9)
     DATA >3101          R2,3,7 wiederherstellen
     INC  R3             Sektor-Offset +1
     AI   R7,>0100       Pointer weiter
     DEC  R2             Sektorz{hler -1
     JNE  L57B0          noch nicht fertig!
     JMP  L576C          SBR >14 mitbenutzen, Ende
L57CE BL   @STKJMP         1. Zugriff
     DATA L4872          FDS im Puffer suchen, freien Puffer suchen
     BL   @STKJMP
     DATA L48B6          pr}fen, ob File schon offen ist (Fehler wenn ja)
     BL   @STKJMP
     DATA L424C          Namen in Sektor 1 eintragen ggfs. altes File freigeben
     BLWP @>5A(R9)
     DATA >0801          R4 wiederherstellen
     MOV  @>56(R9),R8    VDP Zeiger auf Filenamen im FDS
     INCT R4             Zeiger auf Sektoranzahl im PAB
     MOV  *R4+,R3        Sektoranzahl lesen, Zeiger auf File-Status
     AI   R8,>000A	VDP-Zeiger auf 2 Byte VOR(!) Status
     BL   @L59F0         File-Status und RPS in den FDS
     DATA >0002		Offset UND(!) Anzahl
     BL   @L59F0
     DATA >0004          EOF-Offset, Reclen und Recnum (max) in FDS
     DEC  R3             Sektoranzahl =0
     JLT  L5808          Ja - FDS r}ckschreiben
     BL   @STKJMP
     DATA L4412          Nein - Block-Link Map bis zu diesem Sektor-Offset erzeugen
L5808 B    @L563E         SBR >12 mitbenutzen, FDS ge{ndert schreiben

*******************************************************************
* Ausf}hrung CALL FILES (580C)
*******************************************************************
SBRFLS MOV  R11,R7
     BL   @MAINIT
     MOV  @>2C(R9),R8       Textpointer in die aktuelle Basic-Zeile
     AI   R8,>0007          auf die Position von '(' zeigen
     BL   @VDPRD            Wert in R0 holen
     CI   R0,>C801          Token '(' mit 1 Byte String ohne "?
     JNE  L585C             Nein
     INCT R8                Ja - weiter, auf Zahl zeigen
     BL   @VDPRD            Zahl lesen
     SWPB R0
     AI   R0,>49D0          Klammer-Token weg, g}ltige Zahl erzeugen
     CI   R0,>0009          bei Basic max. 9 offene Files gleichzeitig
     JH   L585C             zu viele!
     SWPB R0
     MOVB R0,@>4C(R9)       Argument f}r SBR >16 vorbereiten
     BL   @STKJMP
     DATA SBR16A	SBR >16 mitbenutzen
     MOVB @>50(R9),@>50(R9) Fehlerbyte pr}fen
     JNE  L585C             Fehler!
     MOV  @>2C(R9),R8       Basic-Pointer
     AI   R8,>000C          Zeilenende
     MOV  R8,@>2C(R9)       zur}ck
     SZCB @>42(R9),@>42(R9) Byte in Arbeit zu >00 (GPL RTN) setzen
L585C B    @STKRET            Ende

*****************************************************************
* Ausfuehrung SBR >16, Subset von CALL FILES (5860)
*****************************************************************
SBR16 MOV  R11,R7
     BL   @MAINIT
* Seiteneinsprung (5866)
SBR16A     CLR  R0
     MOVB @>4C(R9),R0    Fileanzahl holen
     JEQ  L5946          Null ist nicht erlaubt, Fehler
     MOV  @>56(R9),R8    VDP-RAMTOP+2, Zeiger auf VDP-Max (>3FFF normal)
     AI   R8,>0003       Zeiger auf Anzahl offener Files
     CLR  R3
     BLWP @>5A(R9)
     DATA >0102          R8 setzen
     MOVB @>FBFE(R15),R3 Anzahl bisher erlaubter Files lesen
     LI   R5,>0206       Groesse der Bloecke
     CB   R0,R3          Gleiche Anzahl wie zuvor gefordert?
     JEQ  L5940          Ja - Ende
     JLE  L58E2          Weniger als vorher
     MOV  R0,R6          Fileanzahl zum spaeteren Eintrag in den Header sichern
     CI   R0,>1000       16 Files sind aus Assembler erlaubt!
     JH   L5946          mehr gefordert - Fehler!
     S    R3,R0          Differenzbetrag errechnen
     SRL  R0,8           ins Low-Byte
     MPY  R5,R0          mit der Blockgr|~e multiplizieren
     MOV  R1,R4          ben|tigte Bytezahl kopieren
     NEG  R4             f}r den Suchvorgang anpassen, Pufferheader weiter unten
     MOV  @>70(R9),R2    alten Pointer holen
     MOV  R2,R0          kopieren
     S    R1,R0          Bytezahl hinzugekommener Bl|cke abziehen
     CI   R0,>0800       Mindestgrenze des restlichen VDP-RAM's
     JLT  L5946          unterschritten - Fehler
     MOV  R0,R1
L58AE INC  R2             Pointer in bestehenden Block (6 Byte Header)
     INC  R0             Pointer an den neuen Anfang
     BLWP @>5A(R9)
     DATA >0042          R2 setzen
     MOVB @>FBFE(R15),R3
     BLWP @>5A(R9)
     DATA >0003          R0 setzen
     MOVB R3,@-2(R15)    Wert an neuen Platz
     C    R2,R8          an der Position der Filezahl angekommen?
     JNE  L58AE          Nein - weiter
     BLWP @>5A(R9)
     DATA >0003          R0 setzen, neue Position des Files-Eintrages
     MOVB R6,@-2(R15)    neuen Files-Wert schreiben
     CLR  R6
     S    R0,R2          Anzahl der Bytes der hinzugekommenen Bl|cke berechnen
L58D8 MOVB R6,@-2(R15)
     DEC  R2             den neuen Bereich l|schen
     JNE  L58D8
     JMP  L5916
L58E2 BLWP @>5A(R9)       Segment 'Weniger Bl|cke als zuvor'
     DATA >0103          R8 setzen
     MOVB R0,@-2(R15)    neue Fileanzahl schreiben
     S    R0,R3          Differenz berechnen
     SRL  R3,8
     MPY  R5,R3          mal Blockgr|~e
     MOV  R4,R1          zum rechnen kopieren
     A    R8,R1          neue Position des Headers
     MOV  @>70(R9),R2    alter Zeiger
L58FA BLWP @>5A(R9)       Headerblock nach oben verschieben
     DATA >0102          R8 setzen
     MOVB @>FBFE(R15),R0
     BLWP @>5A(R9)
     DATA >0023          R1 setzen
     MOVB R0,@-2(R15)    Wert an neue Position
     DEC  R1
     DEC  R8
     C    R8,R2          >AA kopiert?
     JNE  L58FA          Nein - weiter
L5916 MOV  R1,@>70(R9)    neuen Wert f}r die h|chste freie Adresse im VDP-RAM
     MOV  R1,R8          Search-Pointer
L591C INCT R8
     BL   @VDPRD         altes VDP-Ende (>3FFF) lesen
     MOVB @>FBFE(R15),R1 CRU-ID Byte lesen
     CB   R12,R1         richtig?
     JEQ  L5940          Ja - Ende
     A    R4,R0          Nein - Blockoffset dazu
     BLWP @>5A(R9)
     DATA >0103          R8 setzen
     MOVB R0,@-2(R15)
     MOV  R0,R8          kopieren
     SWPB R0
     MOVB R0,@-2(R15)    neues VDP-Ende in den Header
     JMP  L591C          weitersuchen
L5940 CLR  @>50(R9)       Fehlerbyte l|schen
     JMP  L594A          Ende
L5946 SETO @>50(R9)       Fehler!
L594A B    @STKRET         Ende

*************************************************
* Subroutine FNCB aufbauen (59AE)
*
* L|scht den PAB-Pointer, schreibt LW-Nr. aus R6,
* verschiebt Filenamen *R0 in den FNCB.
*************************************************
L594E CLR  @>54(R9)
     MOV  @>58(R9),R1    Volume-ID Adresse
     AI   R1,>0100       auf FNCB zeigen
     BLWP @>5A(R9)
     DATA >0023          R1 setzen
     MOVB R6,@-2(R15)    LW-Nr. setzen
     LI   R2,>000A       Namenl{nge (max)
L5968 INC  R1
     BLWP @>5A(R9)
     DATA >0002          R0 setzen
     MOVB @>FBFE(R15),R3 Wert aus Input lesen
     INC  R0
     BLWP @>5A(R9)
     DATA >0023          R1 setzen
     MOVB R3,@-2(R15)    Wert in FNCB
     DEC  R2
     JNE  L5968          weiter
	RT	Ende

*******************************************************
* Subroutine Parameter aus dem PAD-RAM }bernehmen (5986)
* >834C (B): LW-Nr.,
* >834D (B): Flag,
* >834E (W): Filenamenpointer (VDP),
* >8350 (B): Parameteroffset.
*******************************************************
L5986 MOV  R11,R10
     CLR  R6
     MOVB @>4C(R9),R6    LW-Nr.
     MOV @>4E(R9),R0    Pointer auf Filenamen
     BL   @L594E         Namen in den FNCB bringen
     MOVB @>50(R9),R4    Low-Byte der Parameterblockadresse
     SRL  R4,8           ins Low-Byte
     A    R9,R4          WP addieren
     MOVB @>4D(R9),R0    Flag
     BLWP @>5A(R9)
     DATA >0800          R4 sichern
     SRL  R0,8           Flag ins Low-Byte
     B    *R10

****************************************
* Subroutine Parameterblock lesen (59AC)
****************************************
L59AC BLWP @>5A(R9)
     DATA >8010          R0,11 sichern
     BL   @STKJMP
     DATA L4872          File-Puffer Bereich nach dem Filenamen absuchen
     BL   @STKJMP
     DATA L48B6          noch nicht offen, FDS lesen, wenn m|glich
     MOV  R4,R4          File gefunden?
     JEQ  L59C8          Ja
     BL   @L4720         Nein - Fehler
     DATA >E000          File Error

L59C8 BL   @VDPR56
     DATA >000E          Anzahl vom File belegter Sektoren nach R0
     BLWP @>5A(R9)
     DATA >2011          R2,11 wiederherstellen
     BLWP @>5A(R9)
     DATA >0801          R4 wiederherstellen
     MOV  *R4+,R7        VDP-Pufferadresse der Daten
     MOV  *R4,R3         Startsektor
	RT	Ende

*****************************************************************
* Subroutine Block im VDP-RAM *R8 ins RAM *R4, Anzahl in R2
***************************************************************
L59E0 BLWP @>5A(R9)
     DATA >0102              R8 setzen
L59E6 MOVB @>FBFE(R15),*R4+
     DEC  R2
     JNE  L59E6
     B    *R11               Ende

**********************************************************
* Subroutine Block aus dem RAM ins VDP-RAM kopieren (59F0)
* Referenzen: 2 (nur SBR >15)
* R4	RAM-Pointer, wird fortgeschaltet
* R8	VDP Adresse, wird um Anzahl/Offset weitergeschaltet
* DATA	Anzahl/Offset
*
* Das ist eine verrueckte Funktion - sie vermischt Offset
* und Transferlänge, was nur in genau einem Fall Sinn ergibt
************************************************************
L59F0	MOV *R11+,R2	Data holen (-> Anzahl Bytes und Offset)
	A R2,R8		Anzahl/Offset auf VDP-Adresse addieren
	BLWP @>5A(R9)
	DATA >0103	R8 setzen
L59FA	MOVB *R4+,@-2(R15)	Daten verschieben
	DEC R2
	JNE L59FA
	RT	Ende

*********************************************************************************
* Vorbereitung des Bankswitching (5A04)
*
* Die Zieladressen liegen bereits in Bank 2,wobei Funktion 0 nicht definiert ist,
* bzw auf nicht programmierten Bereich zeigt (!)
* Funktion 1	Power-Up Teil 2
* Funktion 2 	Sektor I/O
* Funktion 3	Disk formatieren
* Funktion 4	Call Manager (benötigt Diskette)
***********************************************************************************
L5A04	LI R1,>0002	Einsprung aus Power Up
	JMP L5A04X
L5A0A	LI R1,>0004	Sektor lesen/schreiben
	JMP L5A04X
L5A10	LI R1,>0006	Diskette formatieren
L5A04X	B @BANKSW
**********************************************************************
* Call MGR,oder Call Manager
**********************************************************************
SBRMGR	MOV R11,R7	Direkten Ruecksprung zur DSRLNK erlauben
	BL @MAINIT
	LI R1,>0008		Funktion 4 - Call Manager
	C @>8330,@>8332		Nanana - R9 ist doch schon gesetzt!
	JEQ L5A04X	Bankswitch
	B @STKRET
*
	DATA >FFFF	Wird nicht benutzt (L5A2E)
*
MAXDRV	DATA >0400	(5A30)
************************************************************************
* Sektor I/O,SBR >10 			(5A32)
*
* PAD RAM Nutzung:
* >4A,>4B	Rückgabe Sektornummer
* >4C	Laufwerk (1-4)
* >4D	Flag Lesen (!=0)/Schreiben (==0)
* >4E,>4F	Adresse VDP Puffer
* >50,>51	Übergabe Sektornummer,Rückgabe Fehlernummer in >50
* >56,>57	Adresse des PAB im VDP RAM, der nur >0110 enthält
************************************************************************
SBR10	MOV R11,R7	Direkten Ruecksprung zur DSRLNK erlauben
	BL @SBINIT
	B @SBR10C
************************************************************************
* Disk formatieren,SBR >11 		(5A3C)
*
* PAD RAM Nutzung:
* >4A,>4B	Rückgabe Sektoren pro Disk
* >4C	MS Nibble: DSR Version,LS Nibble: Laufwerk
* Version:
* 0 - Format ist mit jeder DSR Version möglich
* 1 - Doppelseitig oder Non Standard Spuranzahl (weder 35 noch 40)
* 	Bedingt Version 2 der DSR (das ist hier gegeben)
* 2 - Format benötigt Optionen die der TI-FDC nicht kann -> Fehler!
* >4D	Anzahl Spuren
* >4E,>4F	Adresse VDP Puffer (z.B. 3300 Bytes für eine SD Spur)
* >50	Dichte (1 oder 2, von dem TI-FDC ignoriert), Rückgabe Fehlercode
* >51	Seiten (1 oder 2)
* >56,>57	Adresse des PAB im VDP RAM, der nur >0111 enthält
************************************************************************
SBR11	MOV R11,R7	Direkten Ruecksprung zur DSRLNK erlauben
	BL @SBINIT
	B @SBR11C
************************************************************************
* Dateischutz ändern,SBR >12 		(5A46)
*
* PAD RAM Nutzung:
* >4C	Laufwerk
* >4D	Schutzflag:	>08 schützen,>00 nicht schützen
* >4E,>4F	Zeiger auf Dateinamen im VDP RAM. Der Name muss 10 Zeichen lang sein und ggf. mit Blanks aufgefüllt werden
* >50 (B)	Rückgabe Fehlercode
* >56,>57	Adresse des PAB im VDP RAM,der nur >0112 enthält
************************************************************************
SBR12	MOV R11,R7	Direkten Ruecksprung zur DSRLNK erlauben
	BL @SBINIT
	B @SBR12C
************************************************************************
* Datei umbenennen,SBR >13 		(5A50)
*
* PAD RAM Nutzung:
* >4C	Laufwerk
* >4E,>4F	Zeiger auf neuen Dateinamen im VDP RAM
* >50,>51	Zeiger auf aktuellen Dateinamen im VDP RAM
* 	Beide Dateinamen müssen mit Blanks auf 10 Zeichen gefüllt sein
* >50 (B)	Rückgabe Fehlercode
* >56,>57	Adresse des PAB im VDP RAM, der nur >0113 enthält
************************************************************************
SBR13	MOV R11,R7	Direkten Rücksprung zur DSRLNK erlauben
	BL @SBINIT
	B @SBR13C
************************************************************************
* Datei Direkttransfer Input,SBR >14 		(5A5A)
*
* PAD RAM Nutzung:
* >4C	Laufwerk
* >4D	Funktionscode: == 0 - Status lesen,!= 0 - Daten lesen
* >4E,>4F	Zeiger auf Dateinamen im VDP RAM
* >50	Zeiger (PAD Offset) auf extra Datenblock im CPU RAM, Rückgabe Fehlercode
*
* Die folgenden Infos sind ein Copy-&-Paste aus dem Technical Drive Book
* ab Seite 66. Die dort zu findenden Infos sind weder eindeutig noch
* konsistent, und müssen durch eigene Analysen ergänzt werden!
* Ansonsten wird auf den Abschnitt "Aufbau der FDS" verwiesen.
*
* Datenblock - Offset, Nutzung Funktion 0, Funktion 1 (AU = Sektor)
* --------------------------------------------------------------------
* >00,>01	Adresse des Puffers im VDP-RAM
* >02,>03	Anzahl AUs, Funktion 1: Erste AU eines zu lesenden Blocks
* >04	Status Flags (FCB)
* >05	Datensätze pro AU (FCB)
* >06	EOF Offset (FCB)
* >07	Record Size (FCB)
* >08,>09	Anzahl Datensätze (FCB)
************************************************************************
SBR14	MOV R11,R7	Direkten Ruecksprung zur DSRLNK erlauben
	BL @SBINIT
	B @SBR14C
************************************************************************
* Datei Direkttransfer Output,SBR >15 		(5A64)
************************************************************************
SBR15	MOV R11,R7	Direkten Ruecksprung zur DSRLNK erlauben
	BL @SBINIT
	B @SBR15C
************************************************************************
* Initialisierung beim Aufruf einer SBR >10 bis >15 (5A6E)
* R7 enthält die Rückkehradresse zu DSRLNK!
************************************************************************
SBINIT	STWP R9			Erwartet wird hier >8xE0 (GPLWS)!
	AI R9,>FF20		>E0 abziehen
	MOVB @>4C(R9),R10	Laufwerksnummer, bei >11 mit DSR Version
	SZCB @>4F2C,R10		Fehler! Hier sollte das MSNibble gelöscht werden, aber an der Adresse 4F2C steht in Bank 1 das Argument des Befehls AI R1,>0012, also eine >00. In Bank 2 allerdings steht an >4F2C ein >F0 - das wäre korrekt. Wie sich nun ein Datum aus Bank 2 nach Bank 1 verirren konnte, kann ich mir nicht ohne weiteres erklären. Es wäre interessant zu sehen, ob der Atronic-Diskmanager dieses Problem dadurch umgeht, daß er die Version beim Aufruf von SBR >11 leer lässt, denn alle anderen Diskmanager setzen bei DD die Version, was zum Abbruch führt.
	CB R10,@MAXDRV	>04
	JH SBINIX	LW Nummer zu hoch -> Fehler (nur welcher?)
	MOV R11,R9	R11 brauchen wir noch zum Exit in DSRLNK
	MOV R7,R11	DSRLNK Return in R11
	B *R9	Weitermachen
SBINIX	B *R7	Abbruch!
*
* Beginn des unbenutzten Bereiches
*
* L5A8A
	DATA >FFFF,>FFFF,>FFFF
* 5A90
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
* 5B00
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
* 5C00
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
* 5D00
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
* 5E00
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
* 5F00
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF

B2VTBL	EQU >4B00	Adresse der Sprungtabelle in Bank 1 (!)

	AORG >5F60
*****************************************************************************
* Sprung in Bank 2
* Der Code findet sich identisch in Bank 2 an derselben Stelle
* Lediglich der letzte Sprungbefehl fehlt dort, da zu diesem
* Zeitpunkt (nach SBZ >B) die obere Hälfte des EPROM schon nicht
* mehr aktiv ist. Eigentlich wäre auch alles nach SBO >B nicht nötig...
* R1 - Nummer der Funktion x 2 (Offset in Sprungtabelle in Bank 2)
*****************************************************************************
BANKSW	SBO >B	Adressleitung umschalten 
	MOV @B2VTBL(R1),R1	Sprungvektoren in Bank 2
	B *R1	Ab geht's
	SBZ >B	Rückkehr von Bank 2
	B @STKRET	Dieser Befehl steht bereits nicht mehr in Bank 2
*
* Bis zum Ende der 8K in Bank 1 ist alles leer
*
* 5F6E
	DATA >FFFF
* 5F70
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF
	DATA >FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF,>FFFF

* (d) Christopher Winter
* (c) Programm    ATRONIC Meiendorfer Weg 7  2000 Hamburg 73