********************************************************************************
* Assemblierbare Version 1.2 der Bank 1 der DSR des Atronic FDC,
* basierend auf einem Hexdump der V1.1 - ein 2114 mit nur 4 Bit wird angenommen.
*
* Es wurde mit XAS99 im strict Mode assembliert.
*
* Kommando: xas99.py -s -b -R <filename>
*
* Letzte Aenderung: 2025-10-05 Christopher Winter
*
********************************************************************************
	AORG >4000
***************************************************************************
* ROM Header - komplett zu >00 gesetzt um nicht aufzufallen
***************************************************************************
	DATA >0000
	DATA >0000
	DATA >0000
	DATA >0000
	DATA >0000
	DATA >0000
	DATA >0000
	DATA >0000
*
* Equates der Register des Floppy-Disk Controller-Chips
* Alle Labels beginnen mit WD
*
WDSTRD	EQU >5FF0      Statusregister lesen
WDTRRD	EQU >5FF2      Spurregister lesen
WDSERD	EQU >5FF4      Sektorregister lesen	nicht verwendet
WDDARD	EQU >5FF6      Datenregister lesen
*
WDCMWR	EQU >5FF8      Kommandoregister schreiben
WDTRWR	EQU >5FFA      Spurregister schreiben
WDSEWR	EQU >5FFC      Sektorregister schreiben
WDDAWR	EQU >5FFE      Datenregister schreiben, Spur fuer SEEK schreiben
************************************************************************
* CRU-Map
************************************************************************
*	Bit 0	card enable
*	Bit 1	toggle motor monoflop
*	Bit 2	wait enable
*	Bit 3	NC - head load
*	Bit 4	DS0 - drive select LW 1
*	Bit 5	DS1 - drive select LW 2
*	Bit 6	DS2 - drive select LW 3
*	Bit 7	SS1 - side one select
*	Bit 8	DS3 - drive select LW 4
*	Bit 9	NC - interessanterweise bei keinem der analysierten Controller verwendet
*	Bit >A	Double Density enable
*	Bit >B	A13 EPROM
*	Bit >C	NC
*	Bit >D	NC
*	Bit >E	NC
*	Bit >F	/PGM EPROM (ueber Inverter)
************************************************************************
*
* 4010 bis 49FF		DATA >FFFF    nicht programmiert
*
* 4A00 bis 4AFF		System-RAM des Controllers (2114). Pro Byte ist nur das Low Nibble verfuegbar!
* 			Alle Labels beginnen mit SR
*
	AORG >4A00
*
SRLDRV	EQU >4A00	Nummer des zuletzt angesprochenen Drives
*			Die folgenden 4 Labels werden indirekt ueber SRLDRV adressiert,
*			sie zu benennen ist also strenggenommen unnoetig
SRLTR0	EQU >4A02	Letzte Spur auf LW 1, ich verwende die Bus Drive-ID 0
SRLTR1	EQU >4A04       Letzte Spur auf LW 2
SRLTR2	EQU >4A06       Letzte Spur auf LW 3
SRLTR3	EQU >4A08       Letzte Spur auf LW 4

* 4A0A bis 4A18   derzeit keine Verwendung

SRDDBM	EQU >4A1A	Density-Bitmap fuer Sektor-I/O, 0=DD, 1=SD

* 4A1B bis 4A1F   derzeit keine Verwendung

SRPDSV	EQU >4A20 	bis 4A53   Puffer fuer den Inhalt des PAD-RAMs waehrend der
*			Sektor-I/O-Routinen die wegen des Timings den 16 Bit-Bus brauchen!

* 4A54 bis 4AFF   derzeit keine Verwendung
*
* Vektoren fuer den Uebergang von Bank 0 nach Bank 1
*
	AORG >4B00	

B1VTBL	DATA >0000	derzeit nicht zugewiesen, der Bereich ist noch leer
	DATA PWRUP	Fortsetzung des Powerup-Links
	DATA SEKIO	Sektor Schreib/Lese-Operationen
	DATA FMTDSK	Diskette formatieren
	DATA CLLMGR	Fortsetzung von CALL MANAGER
*
* 4B0A bis 4B14		DATA 0		Leer, vermutlich fuer weitere Funktionen vorgehalten
*
	DATA >0000,>0000,>0000,>0000,>0000,>0000
*
* Fortsetzung des Power-Up Link von Bank 0
*
	AORG >4B16

PWRUP	AI   R12,8		CRU-Basis hochschalten
	LDCR @BZERO,5		>00 - Drive-Select- und Side-Select-Leitungen auf Ground.
	AI   R12,-8		Alte Basis (>1100) wiederherstellen
	SBZ  1			Drive-Motoren anwerfen (Monoflop triggern)
	SBO  1			... nuetzlich z.B. fuer das p-System oder Schnellstarts in XB etc.
	MOVB @L4EC6,@WDCMWR	FDC-Chip mit >D0 ruecksetzen. Force Interrupt, Terminate with no Interrupt.
	MOV  @>58(R9),R2	Aus >8x58 die VDP-Adresse des Volume-ID Blocks holen.
	AI   R2,-10		auf die VDP-Startadresse der DISK DRIVE INFO zeigen.
	BL   @SVDPWA		VDP-Adresse mit Wert in R2 zum Schreiben vorbereiten.
	LI   R0,7		Schleifenzaehler und gleichzeitig >00 Byte zum loeschen
L4B3C   MOVB R0,@-2(R15)	R15 enthaelt VDPWA da GPLWS, VDPWA-2 = VDPWD !!
	DEC  R0             	Disk-Info und 3 folgende Bytes loeschen.
	JNE  L4B3C          	noch nicht fertig!
	BL   @WNBUSY		FDC Wait disable, warten bis BUSY-Zustand beendet.
	MOVB @BZERO,@>50(R9)	Wert in >8350 (HBy) loeschen.
*
* System-RAM im 2114 initialisieren
*
* Hier fuer V2 einen Reset-Check vorsehen, damit nach einem Neustart speziell die
* Dichte-Info nicht immer geloescht wird und es so zu unnoetigen Wartezeiten kommt.
* Und natuerlich auch die Konfigurationsdaten des Config-Tools in Ruhe lassen...
*
	CLR  R0		Werte vorbereiten
	SETO R2
	LI   R6,SRLDRV	Anfangsadresse des 4 Bit RAM
	MOV  R0,*R6+	Letztes Drive = 0
	MOV  R2,*R6+	Letzte Spur auf LW1 = >FF. Das zwingt die Sektor-
	MOV  R2,*R6+	Routine zum Initialisieren der aktuellen Spur.
	MOV  R2,*R6+
	MOV  R2,*R6+	alle 4 Laufwerke.
*			Der VDP-Puffer ab >3EEB ist normalerweise nur bis LW 3
*			ausgelegt, er wird aber nicht gelesen.
	MOV  R0,@SRDDBM	Density-Bitmap komplett auf Double Density.
*
* Meldung in das Titelbild setzen.
*
	LI   R2,>01A3		Bildschirmposition der Meldung.
	BL   @SVDPWA		VDP-Adresse mit Wert in R2 zum Schreiben vorbereiten.
	LI   R0,PROMPT		Pointer auf den Text
	LI   R2,PROMPX-PROMPT	Laenge des Textes dynamisch ermitteln!
L4B74   MOVB *R0+,@-2(R15)	Daten sukzessive in VDPWD schreiben
	DEC  R2			fertig?
	JNE  L4B74		nein - weiter
	B    @BNKRET		ROM ausblenden und Rueckkehr aus DSR.    

PROMPT	TEXT 'ATRONIC DISK SYSTEM: READY'
PROMPX	EQU $
	EVEN

************************************************************
* Auf Ende des Busy-Zustands des FDC warten
************************************************************
WNBUSY   SBZ  2              FDC Wait disable.
*
* Seiteneinsprung ohne WAIT DISABLE, etwa bei Step-Befehlen
*
L4B96	MOVB @WDSTRD,R0	FDC Status lesen.
	JLT  L4BA2	High-Bit gesetzt - Drive not ready!
	SRC  R0,9	Low-Bit gesetzt?
	JOC  L4B96	Ja - noch Busy, weiter warten.
	RT		Low-Bit auf Null - Ende.

L4BA2   B @L50B8	Fehler - Abbrechen!
*
WZERO   DATA >0000			(4BB4)
BZERO	DATA >0001		Wird auch als Byte adressiert, wenn eine >00 gefragt ist (4BB6)
	DATA >0002,>0004,>0008		(4BB8)
	DATA >0010,>0020,>0040,>0080	(4BBE)
L4BC4	EQU $-2				Density Maske Referenz -2 da Offset von 2

L4BC6	DATA >0100			Density Maske fuer Laufwerke mit Nummer 1-4
L4BC8	DATA >0200,>0400,>0800	

L4BCC	EQU $-2				Seitenindex
L4BCE	DATA >1000
L4BD0	DATA >2000			Seitenindex
	DATA >4000
L4BD4	DATA >8000

SPTDD	DATA >0012      Anzahl der Sektoren pro Spur bei Double Density (4BD6)
SPTDDB	EQU $-1		Wird auch als Byte adressiert
SPTSD	DATA >0009      Anzahl der Sektoren pro Spur bei Single Density (4BD8)
SPTSDB	EQU $-1		Wird auch als Byte adressiert

DATA4	DATA >0004	Maximale Laufwerksanzahl
BYTE4	EQU $-1		dito als Byte

* Hardcodierter Step-Timing Index fuer alle Laufwerke (war >0200)
*
STPMSK   DATA >0000	Step-Timing Index:
*			0000 bei  6 ms
*			0100 bei 12 ms
*			0200 bei 20 ms
*			0300 bei 30 ms
***************************************
* Sektor Lesen/Schreiben
***************************************
SEKIO   MOVB @SRDDBM,R5		alte Density-Bitmap in R5, R5 dient als Statuspuffer.
	ANDI R5,>0F00		relevante Bits maskieren, aber nur wegen des halben Datenbus'
	BL   @L4E0A		Laufwerk pruefen, Sektor I/O-Routine ins PAD setzen.
	LI   R4,10		Anzahl der zulaessigen Versuche fuer Sektor-I/O.
*
* Seiteneinsprung bei Retry, falls noch Versuche (R4) moeglich sind
*
REPEAT	MOVB @BZERO,@>50(R9)  >8x50 (HBy) loeschen (kein Fehler).
	BL   @L4DB0           Laufwerk-Nr. pruefen, Select-Leitung setzen.
       CLR  R7
       MOVB @>4C(R9),R7    LW-Nummer aus >8x4C holen.
       SRL  R7,7           LW-Nr. mal 2 im Low-Byte.
       MOV  @SRLDRV(R7),R0  Spur-Nr. des zuletzt benutzten LW holen.
       ANDI R0,>0F0F       Low-Nibs isolieren,
       MOV  R0,R1          kopieren,
       SLA  R1,12          High-Nib vom Low- ins High-Byte,
       AB   R1,R0          Low-Nib aufaddieren,
       ANDI R0,>FF00       und High-Byte isolieren.
* Das muss bei einer Revision geaendert werden - die max. Tracknummer muss ins System-RAM!
       CI   R0,>2700       ueber die letzte Spur (ggfs. 1. Zugriff auf das LW).
       JLE  L4C1E          Nein - weiter.
       BL   @SEEKT0         Ja - Kopf ueber Spur 0 fahren (Restore).
       CLR  R0             Spur-Index zu Null setzen.
L4C1E   MOVB R0,@WDTRWR      geforderte Spur-Nr. in das FDC-Reg. Daran erkennt
*                          der Controller die richtige Position ueber der Spur!
       CLR  R0
       MOV  @>4A(R9),R1    in >8x4A wurde die Sektor-Nr. kopiert.
       COC @L4BC4(R7),R5   ist das dem LW entsprechende Bit im Status gesetzt?
       JEQ  L4C36          Ja - dann ist dem LW Single Density zugeordnet!
       SBZ  >A              Nein - Double Density schalten!
       DIV  @SPTDD,R0      Wert in R0 (Sektor-Nr.) durch >12 teilen.
*                           Nach der Division steht in R0 die Spur, in R1 der
*                           Sektor in dieser Spur.
       JMP  L4C3C          weiter.
L4C36   SBO  >A              Single Density schalten.
       DIV  @SPTSD,R0      durch >9 teilen.
L4C3C   SBZ  7              Diskettenoberseite anwaehlen.
       SZC  @L4BD0,R5      Seitenindex im Statusregister loeschen.
       CI   R0,40          Wurde eine Spur ueber 40 berechnet?
       JL   L4C58          Nein
       LI   R2,79          moeglicherweise Seite 2.
       S    R0,R2          79 minus Spur-Nr. gibt Komplement, Spur auf Seite 2.
       JLT  L4D18          weniger als Null - Sektor-Nr. war zu hoch.
       SBO  7              Spur-Nr. i.O., Diskettenrueckseite anwaehlen.
       SOC  @L4BD0,R5      Seitenindex setzen.
       MOV  R2,R0          Spur-Nr. in R2.
L4C58   SWPB R0             Spur-Nr. ins Low-Byte.
       MOVB R0,@SRLDRV(R7)  Spur-Puffer aktualisieren.
       SRC  R0,4
       MOVB R0,@SRLDRV+1(R7)  Byte komplett ablegen.
       SLA  R0,4           Wort reparieren.
       MOVB R0,@WDDAWR      Spur-Nr. fuer Seek in das Datenregister.
       SWPB R1             Sektor-Nr. ins High-Byte.
       MOVB R1,@WDSEWR      Sektor-Nr. in Sektor-Register fuer Verify on Sector!
       CB   R0,@WDTRRD      Track Register lesen, Spur schon erreicht?
       JEQ  L4C84          Ja - weiter.
       BL   @L4D82         Nein - SEEK, Load Head, Verify on Track.
       DATA >1C00          FDC-Kommando Typ I, mit Stepping Rate verODERn!
       BL   @L4B96         warten bis Busy beendet, Abbruch wenn Drive not ready
       SLA  R0,13          Status pruefen.
       JOC  L4D12          SEEK-Error - Abbruch, Retry moeglich!
L4C84   MOVB R1,@WDSEWR      Sektor-Nr. fuer Verify in das Sektor Register.
       MOV  @>4E(R9),R2    PAB-Buffer Adresse holen.
       MOVB @>4D(R9),R0    Schreib-Lese Opcode holen.
       JEQ  L4CDA          wenn 00 dann schreiben.
       BL   @SVDPWA         Adresse des PAB-Buffers setzen.
       MOV  R15,R2         VDPWA kopieren.
       AI   R2,-2          VDPWD erzeugen.
L4C9C   BL   @L4D74         READ SECTOR, Single Record, Compare Side, 30 ms Delay
*                          Enable Side select compare.
       DATA >8600          Kommandotyp II
       LI   R6,256         Byteanzahl fuer Sektor-R/W.
       SOCB @L4BD4,R5      High-Bit setzen.
       SBO  2              Wait enable.
       CLR  R0
       MOVB @>4D(R9),R0    Schreiben oder Lesen?
       JNE  L4CBC          wenn 01 dann lesen.
       CLR  R0
       BL   @>A(R9)        Geschrieben wurde schon, jetzt Verify (Offset A!).
       JMP  L4CBE
L4CBC   BL   *R9            entspricht BL  @>8x00!

L4CBE   SZCB @L4BD4,R5      High-Bit wieder loeschen
*
* Seiteneinsprung der Sektor-Verify Routine im PAD-RAM
*
L4CC2	BL   @WNBUSY	Wait-Disable etc.
	SLA  R0,13	Record not found?
	JOC  L4D24	Ja - Abbruch! Record not found
	JLT  L4D2A	CRC-Error - auch Ende!
	COC  @L4BD4,R5	High-Bit gesetzt?
	JEQ  L4D36	Programmfehler!
	SLA  R0,2	Lost-Data (Timing-Fehler des Programms)?
	JOC  L4D30	Ja
	B    @L4EDA	R5 zurueck nach SRDDBM, PAD reparieren etc.  ENDE
***************************************
* Sektor schreiben
***************************************
L4CDA   BL   @SVDPRA       VDP-Adresse mit R2 zum Lesen setzen.
       MOV  R15,R2
       AI   R2,>FBFE     VDPRD herstellen.
       BL   @L4D74       WRITE SECTOR, Single Record, Compare Side, 30 ms Delay,
*                        Enable Side select compare.
       DATA >A600        Kommandotyp II.
       LI   R6,256       Byte Count.
       SBO  2            Wait enable.
       BL   *R9          Sektor schreiben.
       BL   @WNBUSY       Wait disable etc.
       SLA  R0,11        Bit S6 pruefen.
       JOC  L4D3C        Fehler, Write Protect!
       SLA  R0,2         Bit S4 pruefen.
       JOC  L4D42        Fehler, Record not found!
       SLA  R0,2         Bit S2 pruefen.
       JOC  L4D48        Lost Data, Timing Fehler!
       MOV  @>4E(R9),R2  Buffer-Adresse holen.
       BL   @SVDPRA       VDP-Adresse mit R2 setzen (Lesen)
       MOV  R15,R2
       AI   R2,>FBFE     VDPRD erzeugen.
       JMP  L4C9C        Sektor lesen zum Verify benutzen.

* Fehlerroutinenaufrufe    Aufruf wenn:

L4D12   BL   @RETRY       Alle Retries fehlgeschlagen oder SEEK-Error.
       DATA >1100
L4D18   BL   @RETRY       Sektor-Nr. zu grosz
       DATA >0700
L4D1E   BL   @L4EB6       Drive-Nr. falsch.
       DATA >0700
L4D24   BL   @RETRY       READ-Error, Record not found
       DATA >2100
L4D2A   BL   @RETRY       READ-Error, CRC Error
       DATA >2200
L4D30   BL   @RETRY       READ-Error, Lost Data.
       DATA >2300
L4D36   BL   @RETRY       Verify fehlgeschlagen (war: Software-Fehler!)
       DATA >2800
L4D3C   BL   @L4EB6       WRITE PROTECTED
       DATA >3400
L4D42   BL   @RETRY       WRITE-Error, Record not found
       DATA >3100
L4D48   BL   @RETRY       WRITE-Error, Lost Data
       DATA >3300
******************************************************
* Subroutinen, also solche, die mit RT zurueckkehren
******************************************************

******************************************************
* Kopf ueber Spur Null positionieren
******************************************************
SEEKT0   MOV  R11,R8       R11 sichern.
       BL   @L4D82       RESTORE, Load Head at beginning, no Verify on Track!
       DATA >0800        Kommandotyp I, mit Stepping-Rates verODERn.
       BL   @L4B96       warten auf Busy-Ende.
       BL   @SEEKCH              Status ein Mal pruefen ob Spur 0 erreicht ist.
       MOV  @WZERO,@SRLDRV(R7)   Spur-Puffer loeschen. 
       B    *R8                 Ende.
******************************************************
* Seek Check
* Auf Hardware-Error pruefen, Track 0 nicht erreicht
******************************************************
SEEKCH	MOVB @WDSTRD,R0    FDC-Status lesen.
       SLA  R0,6         Bit S2 pruefen.
       JOC  L4D72        OK - weiter
       B    @L50B8       Error-Exit mit I/O-Error 06! Kopf nicht ueber Spur 0!
L4D72   RT         Ende
******************************************************
* FDC-Kommando Typ II (Read/Write Sector)
******************************************************
L4D74	MOV  *R11+,R0     Data holen.
	COC  @L4BD0,R5    Seite 2?
	JNE  L4D8C        Nein
	SOC  @L4BCC,R0    Ja - Data mit >0800 verodern.
	JMP  L4D8C
******************************************************
* FDC-Kommando Typ I (Seek, Restore, Step)
******************************************************
L4D82   MOV  *R11+,R0     Data holen.
       SOCB @STPMSK,R0    Je nach Step-Time unterschiedliche Werte in STPMSK!
       JMP  L4D8C
******************************************************
* Allgemeine FDC-Kommandoroutine
******************************************************
L4D8A   MOV  *R11+,R0     Data holen falls hier eingesprungen wurde

* gemeinsamer Code, R0 hat bereits den Befehl

L4D8C	MOVB @WDSTRD,R6    Status lesen.
	SLA  R6,1         High-Bit gesetzt, Drive not ready?
	SBZ  1
	SBO  1            Motor anwerfen.
	JNC  L4DA4        Bit nicht gesetzt, Drive ready!
	LI   R6,>7530     Schleife.
L4D9C	SRC  R5,4         Verzoegerung, um den Motor hochlaufen zu
	SRC  R5,4         lassen.
	DEC  R6           Fertig?
	JNE  L4D9C        Nein.

L4DA4	MOVB R0,@WDCMWR	Data in FDC-Chip.
	SBO  3		Head-Load -> wir haben da aber keine Leitung dran!!!
*			Wohl auch deswegen gibt es kein SBZ 3???
	SRC  R5,8	Hiermit wird sichergestellt, dass wir wenigstens
	SRC  R5,8	insgesamt ca. 30 Mikrosekunden verspaetet aus der
	RT		Funktion zurueckkehren um den FDC nicht zu ueberfahren.
********************************************
* Subroutine Laufwerk (@>8x4C) zuschalten
* Bei Laufwerkswechsel das Hochlaufen abwarten
********************************************
L4DB0	SZCB @L4BD4,R5		High-Bit loeschen in der Annahme, wir haben das LW nicht gewechselt
	MOVB @SRLDRV,R0		Letztes LW, das benutzt wurde
	ANDI R0,>0F00		4 Bit maskieren
	CB   R0,@>4C(R9)	ist es das gewuenschte LW?
	JEQ  L4DC6		Ja 
	SOCB @L4BD4,R5		Nein - New-Drive Index setzen
L4DC6   CLR  R0			Gewuenschtes LW
	MOVB @>4C(R9),R0	aktuelle LW-Nr. holen
	JEQ  L4D1E		Fehler, LW-Nr. == 0
	MOVB R0,@SRLDRV		aktuelles LW ist jetzt das letzte Drive
	SRL  R0,8		ins Low-Byte (u.a. als bitshift)
	C    R0,@DATA4		mit 4 vergleichen.
	JH   L4D1E		Fehler, LW-Nr. > 4
	LI   R2,>0080		Bitmuster fuer CRU
	SLA  R2,0		mit R0 links schieben
	AI   R12,8		CRU-Basis hoch, um die unteren Bits nicht zu aendern.
*				Wir beginnen also ab Bit 4 (!)
	LDCR R2,3		Drive-Select Leitung aktivieren
*
*	Anmerkung: Netter Trick - wir erlauben eine 4er Bitshift der >0080
*	wenn das LW == 4 ist, schieben aber nur die unteren 3 Bits raus.
*
	AI   R12,-8		Basis restaurieren.
	CI   R0,4		Laufwerk 4?
*
*	Hier steht in der Version 1.0  C R2,4 weshalb das LW 4 nicht erkannt wird.
*
	JNE  L4DF4		nicht LW 4!
	SBO  8			Drive-Select separat fuer LW 4!
	JMP  L4DF6
L4DF4   SBZ  8			LW 4 ggfs. abschalten.
L4DF6   COC  @L4BD4,R5		High-Bit gesetzt, neues Laufwerk?
	JNE  L4E08		nein - weiter
	LI   R0,>0BB8		Schleife
L4E00	SRC  R5,4
	SRC  R5,4
	DEC  R0
	JNE  L4E00
L4E08   RT			Ende
***************************************************************
* Subroutine Vorbereitung des Disk-I/O
*
* - LW pruefen
* - PAD-RAM sichern
* - I/O-Routinen ins PAD-RAM kopieren
***************************************************************
L4E0A	CLR  R7			R/W-Flag initialisieren, invers zu 8x4D!
	MOVB @>4C(R9),R0	LW-Nr. holen.
	JNE  L4E16		Nicht 0 - OK
L4E12   B    @L4D1E		0 - Fehler, falsches LW!

L4E16	CB   R0,@BYTE4		mit 4 vergleichen -> sollte separate MAXDRV Konstante sein!
	JH   L4E12		zu hoch - Ende
	LI   R6,PRRD-PRRDST	Anzahl der Bytes(!) der Leseroutine
	MOVB @>4D(R9),R0	Schreib/Lese-Code
	JNE  L4E2C        	nicht 00, lesen
	SETO R7           	Schreib-Flag.
	LI   R6,PRWR-PRWRST	Anzahl der Bytes(!) der Schreib-/Verify-Routinen.
*
L4E2C   LI   R3,SRPDSV		Adresse des PAD-Save Puffers im 2114
	MOV  R9,R0		PAD-Basis kopieren.
	MOV  R6,R1		Byteanzahl wird zweimal gebraucht!
L4E34	MOV  *R0+,R2		PAD-Wert holen
	MOV  R2,*R3+		Low-Nibs speichern
	SRA  R2,4
	MOV  R2,*R3+		High-Nibs
	DECT R6			Fertig?
	JNE  L4E34		Nein
*
	MOV  R9,R2		PAD-Basis -> Abweichung EPROM, war MOV R9,R0 (4E40)
	MOV  R7,R7		Schreiben?
	JNE  L4E4C		Ja
	LI   R0,PRRDST		Anfangsadresse der Leseroutinen
	JMP  L4E50
L4E4C	LI   R0,PRWRST		Anfangsadresse der Schreibroutinen
L4E50	MOV  *R0+,*R2+		Verschiebeschleife
	DECT R1
	JNE  L4E50		weiter
	RT			Ende
**********************************************************************************
* Die folgenden drei Routinen werden vom ROM ins PAD-RAM ab >8x00 geschrieben und
* sorgen fuer einen Transfer der Daten vom und zum FDC mit maximalem Tempo.
* Alle Labels beginnen mit PR
* Alle erwarten in R2 den Zeiger auf die VDP-Daten, entweder als VDPWD oder VDPRD,
* sowie in R6 deren Anzahl, die aber nur beim Formatieren != >100 ist.
* Die Verify-Routine wird exakt 10 Bytes hinter der Schreib-Routine erwartet!!!
**********************************************************************************
*
******************************
* 1.Sektorleseroutine (4E58) *
******************************
PRRDST	MOVB @WDDARD,*R2   Wert aus FDC-Read Data nach VDPWD
	DEC  R6
	JNE  PRRDST
	RT
PRRD	EQU $
****************************************
* 2.Sektor-/Trackschreibroutine (4E62) *
****************************************
PRWRST	MOVB *R2,@WDDAWR   Wert aus VDPRD nach FDC-Write Data.
	DEC  R6
	JNE  PRWRST
	RT
********************************
* 3.Sektorverifyroutine (4E6C) *
********************************
PRVFSE	CB   @WDDARD,*R2
	JNE  PRVFSX
	DEC  R6
	JNE  PRVFSE
	RT
PRVFSX	B    @L4CC2       Fehler feststellen.
PRWR	EQU $
*********************************
* VDPWA-Setup Subroutine (4E7C) *
*********************************
SVDPWA	ORI  R2,>4000	Schreiben indizieren.
	ANDI R2,>7FFF	Gueltige Adresse erzeugen.
	JMP  SVDPAD
*********************************
* VDPRA-Setup Subroutine (4E86) *
*********************************
SVDPRA	ANDI R2,>3FFF     Gueltige Adresse
********************
* gemeinsamer Code *
********************
SVDPAD	SWPB R2
	MOVB R2,*R15
	SWPB R2
	MOVB R2,*R15
	ANDI R2,>3FFF	evtl. gesetztes Bit loeschen
	RT		Ende
**********************************************************************************
* Behandlung nicht-terminaler Fehler (4E98)
* R4 = Retry-Zaehler. 10,9,8,7, dann Dichtewechsel und 6,5,4,3,2,1
* Es wird ein DATA hinter dem Aufruf erwartet, das den Fehlercode definiert,
* wenn alle Retries durch sind
**********************************************************************************
RETRY   DEC  R4           	Retry-Counter
	JEQ  L4EB6		alles umsonst - Fehler!
	CI   R4,7		Das muss in einer Revision zu CI R4,6 geaendert werden, so ist es asymmetrisch!
	JHE  L4EB2        	Noch Versuche mit vorheriger Dichte moeglich?
	CLR  R1           	Nein
	MOVB @>4C(R9),R1  	LW-Nr. holen.
	SRL  R1,7		mal 2 ins lowbyte
	XOR  @L4BC4(R1),R5  	Density umschalten.
	BL   @SEEKT0		Restore
L4EB2   B    @REPEAT		Noch Versuche moeglich, weiter mit Fehlerbyteloeschung.
*********************************************************************************
* Fehlerbehandlungsroutine. Wird als SBR aufgerufen, da ein Data uebergeben wird.
*********************************************************************************
L4EB6   MOV  *R11,R0      Data holen
       MOVB R0,@>50(R9)  Error-Code nach >8350.
       CI   R0,>0600     Hardware-Error?
       JNE  L4ED6        Nein - weiter -> und warum nicht gleich >4EDA?
       BL   @L4D8A       Ja, FDC-Chip ruecksetzen bzw. Aktion stoppen!
L4EC6	DATA >D000        gleichen Code wie beim PWRLNK in den FDC-Chip!
L4EC8   MOVB @WDSTRD,R0    Status
       SRC  R0,9         Busy?
       JOC  L4EC8        Ja - Warten.
       SETO R0
       MOV  R0,@SRLDRV(R7)  Spur-Nr. des aktuellen Drives zu >FF setzen,
*                           erzwingt die Initialisierung beim naechsten Zugriff!
L4ED6   B    @L4EDA       Sehr witzig!!!
L4EDA   LI   R6,>A        Anzahl der aus dem PAD-RAM gesicherten Bytes.
       MOVB R5,@SRDDBM    Neue Density-Bitmap.
       COC  @L4BCE,R5    Wurde zuletzt geschrieben?
       JEQ  L4EEE        Ja
       MOVB @>4D(R9),R0  R/W-Indikator holen.
       JNE  L4EF4        01 = lesen.   Dieser Vergleich ist voellig ueberfluessig!
L4EEE   LI   R6,>1A       Anzahl wiederherzustellender Bytes im PAD
       JMP  L4EF8
L4EF4   LI   R6,>A        Ueberfluessig, da schon von vorher R6=A ist!
*
* Seiteneinsprung der Formatierroutine nach korrektem Abschluss
* R6 ist von dort her vorbelegt
*
L4EF8	LI   R3,SRPDSV     Startadresse des Puffers.
	MOV  R9,R2
L4EFE   MOV  *R3+,R1      +---------------------------------------------+
	ANDI R1,>0F0F     ! Dieser Programmteil stellt den alten Inhalt !
	MOV  *R3+,R0      ! des PAD-RAM ab >8300 wieder her.            !
	ANDI R0,>0F0F     +---------------------------------------------+
	SLA  R0,4
	A    R1,R0
	MOV  R0,*R2+
	DECT R6
	JNE  L4EFE
*
	MOV  @>58(R9),R2  Volume-ID Adresse
	AI   R2,-10       Zeiger auf Disk-Drive-Info
	BL   @SVDPWA       VDP-Adresse setzen.
	SLA  R7,7         LW-Nr. wieder ins High-Byte.
	MOVB R7,@-2(R15)  LW-Nr. des letzen Drives in die Disk-Drive-Info.
	B    @BNKRET       ROM ausblenden, weiter im unteren Teil.

	DATA >484D		Wofuer ist das gut? (L4F2A)
L4F2C	DATA >F000
L4F2E	DATA >F700		Nicht benoetigt, siehe BYTEF7 (CRC) in V1.2

*****************************************************
* Diskette formatieren
*
* Falls doppelseitig formatiert werden muss, wird immer zuerst die "opposite" Seite,
* dann die "regulaere" Seite formatiert, bevor die nächste Spur angefahren wird.
*
*>834C (B)	Laufwerknummer im Low Nibble, Versionsinfo im High-Nibble (irrelevant)
*>834D (B)	Spuranzahl (Hex)
*>834E (W)	Datenpuffer für den Spuraufbau, bei DD werden etwa 6,5 KByte benötigt
*>8350 (B)	Dichte, >01 - Single, >02 - Double Density
*>8351 (B)	Seiten, >01 - Single, >02 - Double Sided Nach dem Formatieren werden folgende Werte übergeben:
*
*>834A (W)	Rueckgabe Gesamtzahl aller Sektoren
*>834D (B)	Rueckgabe Anzahl der Sektoren pro Spur (SPT)
*>8350 (B)	Rueckgabe Fehlercode
*****************************************************
FMTDSK	CLR  R5
	SOC  @L4BCE,R5          R5= >1000
	MOVB @>4D(R9),R8        Anzahl der Spuren in R8
	MOVB @WZERO,@>4D(R9)	Loeschen, um in der folgen SBR 'schreiben' anzukuendigen
* 				hier kommen spaeter die SPT hin
	SZCB @L4F2C,@>4C(R9)    LW-Nr. maskieren.
	BL   @L4E0A             LW-Nr. pruefen und Sektor-I/O Routinen ins PAD.
	MOVB R8,@>4D(R9)        Spuranzahl ins Low-Byte zusammen mit LW-Nr.
	CLR  R7
	MOVB @>4C(R9),R7        LW-Nr. in R7
	SRL  R7,7               mal zwei und ins Low-Byte.
	MOVB @>50(R9),@>52(R9)  Density-Code kopieren.
	CB   @>51(R9),@L4BC8    Seitenzahl mit >02 vergleichen
	JNE  L4F68              einseitig
	SETO @>4A(R9)           FAC als Double Sided Index verwenden
L4F68   MOVB @WZERO,@>50(R9)    urspruenglichen Dichte-Code loeschen
	BL   @L4DB0             Drive-Select Leitungen setzen
	BL   @SEEKT0		Restore, Kopf ueber Spur Null.
	CLR  R3			Spurzaehler loeschen
*
L4F78   MOV  @>4A(R9),@>4A(R9)	FAC pruefen ob gesetzt.
	JEQ  L4F8A		FAC nicht gesetzt - Single Sided!
	SBO  7                  Side-Select auf 'Opposite'!
	LI   R10,>0100          Seitenindex fuer den Spuraufbau
	BL   @FMTRK		Formatiere eine Spur
L4F8A   SBZ  7                  Side-Select 'Upper'
	CLR  R10                Seitenindex auf 'Seite 1'
	BL   @FMTRK             eine Spur formatieren
	BL   @L4D82             Step in, update track register, load head
	DATA >5800              no verify on destination track.
*                               Kommandotyp I, mit stepping rates verODERn.
	BL   @L4B96             auf Status-Bit warten
	AI   R3,>0100           Spurzaehler + 1 im High-Byte
	CB   R3,@>4D(R9)        Alle Spuren ?
	JNE  L4F78              Nein - weiter.
*
	BL   @SEEKT0		Fertig - Restore, Kopf zurueck.
*
*	Berechnen der resultierenden Daten fuer die Initialisierung
*
	MOVB @>4D(R9),R0        Spuranzahl in R0
	SRL  R0,8               ins Low-Byte
	CB   @L4BC8,@>51(R9)    Seitenzahl mit >02 vergleichen
	JNE  L4FBA              Single Sided!
	SLA  R0,1		Double Sided, hat die doppelte Spuranzahl!
L4FBA   CB   @L4BC8,@>52(R9)	Density mit >02 vergleichen
	JNE  L4FCE		Single Density!
	MPY  @SPTDD,R0		Double Density, mit >12 malnehmen!
	MOVB @SPTDDB,@>4D(R9)	Anzahl der Sektoren pro Spur
	JMP  L4FD8
L4FCE   MPY  @SPTSD,R0          mit >09 malnehmen, Single Density!
	MOVB @SPTSDB,@>4D(R9)	Sektoren pro Spur =>09
L4FD8   MOV  R1,@>4A(R9)        Gesamtzahl der Sektoren in FAC.
	LI   R6,>1A		Anzahl wiederherzustellener Bytes
	B    @L4EF8             PAD restaurieren und Ende
*************************************************************
* Subroutine zum formatieren einer Spur
*
* R3		Spurnummer (Highbyte), ab >0000
* R10		Seitenindex, >0000 'oben', >0100 'unten'
* @>8x4E	VDP-Adresse fuer Spurdaten
*************************************************************
FMTRK	MOV  R11,R8
	MOV  @>4E(R9),R2	PAB-Buffer Adresse holen
	BL   @SVDPWA		Adresse setzen
	CB   @L4BC8,@>52(R9)	Density-Code >02
	JNE  FMTRSD		Single Density!
	B    @FMTRDD		Double Density!
*************************************************************
* Subroutine zum Formatieren einer Spur Single Density
*************************************************************
FMTRSD	LI   R6,>16		am Anfang der Spur stehen 22 Nullen
	SBO  >A			SD anzeigen
	CLR  R2			Sektor-Zaehler
	JMP  L5008		beim 1. Sektor 22 Nullen
L5004	LI   R6,6		alle weiteren Sektoren haben 6 Nullen!
L5008   MOVB @BZERO,@-2(R15)	Nullen schreiben
	DEC  R6			fertig?
	JNE  L5008		nein
	MOVB @BYTEFE,@-2(R15)	>FE schreiben.
	NOP
	MOVB R3,@-2(R15)        Spur-Nr. schreiben
	NOP
	MOVB R10,@-2(R15)       Seiten-Nr. der Diskette (0 - Upper, 1 - Lower)!
	MOVB R3,R0              Spur-Nr. kopieren
	SRL  R0,8               ins Low-Byte
	SWPB R10                Seiten-Nr. ins Low-Byte.
*
*	Boeser Hack: LSBit wird ignoriert wenn R10==0, ansonsten wird das naechste Word genommen!
*	Macht die TI-DSR auch so, aber das ist keine Entschuldigung.
*
       MPY  @L50C5(R10),R0     Seite 0 - Multiplikation mit @>50C4 (=0006)!
*                               Seite 1 - Multiplikation mit @>50C6 (=0003)!
       SWPB R10                Seitenindex korrigieren 
       A    R2,R1              Sektor-Zaehler zu R1 addieren
       DIV  @SPTSD,R0           teilen durch >0009
       MOVB @L50DF(R1),@-2(R15) Sektor-Nr. aus der Interlace-Tabelle.
       LI   R6,-20
L5040   MOVB @BYTEF7(R6),@-2(R15) Sektor-Praeambel (Sync)
       INC  R6
       JNE  L5040
       LI   R0,>E5E5           Inhalt des Datenbereichs eines Sektors
       BL   @L50AC
       DATA >0100              Wert in R0 256 mal schreiben.
       MOVB @BYTEF7,@-2(R15)    Letzten Wert (>F7) als Teil der Postambel.
       SETO R0
       BL   @L50AC
       DATA >002D              einige >FF anhaengen
       INC  R2                 naechster Sektor
       CI   R2,9               alle 9 bearbeitet?
       JNE  L5004              nein
       BL   @L50AC
       DATA >00E7              noch 231 mal >FF als Spur-Postambel.
       LI   R4,3               beim Formatieren sind 3 Retries erlaubt.
L5074   MOVB @>4E(R9),R2        PAB-Buffer Adresse holen
       BL   @SVDPRA             Adresse setzen
       BL   @L4D8A             Spur ist bereit, geschrieben zu werden
       DATA >F400              Write track, 30 ms delay, Kommandotyp III.
       MOV  R15,R2             VDPWA kopieren
       AI   R2,>FBFE           VDPRD erzeugen
       LI   R6,>0CA3           Anzahl der Bytes einer Spur in SD!
       SBO  2                  Wait enable
       BL   *R9                Werte in FDC schieben
       BL   @WNBUSY             Wait disable, warten
       SLA  R0,11              Write protect?
       JNC  L509C              Nein.
       B    @L4D3C             Doch - Abbruch!
L509C   SLA  R0,4               Lost data?
       JNC  L50AA              Nein - Schreibversuch war O.K.!
       DEC  R4                 Fehlversuch, Retry moeglich?
       JNE  L5074              Ja!
       BL   @L4EB6             Nein - Fehler!
       DATA >3300
L50AA   B    *R8                Ende.
***********************************************************************
* Subroutine VDP-Puffer mit gleichen Bytes (R0) fuellen, Anzahl im DATA
***********************************************************************
L50AC	MOV  *R11+,R6           Anzahl aus DATA holen
L50AE	MOVB R0,@-2(R15)        R0 schreiben
	DEC  R6
	JNE  L50AE
	RT               Ende
*
* Fehlercodeuebergaberoutinen
*
L50B8	BL   @L4EB6
	DATA >0600              Hardware-Error!
L50BE   BL   @L4EB6		nicht genutztes Label
	DATA >0700              Software-Error!
*
* Data fuer den Spuraufbau - seitenabhaengige Multiplikatoren
*
	DATA >0006	
L50C5	EQU $-1		wird auch als Byte pseudo-adressiert
	DATA >0003

	BYTE >F0		
BYTEFE	BYTE >FE
*
* Bytes der Sektor-Praeambel SD
*
* Diese Tabelle wird -20 relativ zu BYTEF7 adressiert
* F7 ist dabei das Kommando fuer die Pruefsumme am Ende des Sektors
*
	BYTE >01,>F7,>FF,>FF,>FF,>FF,>FF,>FF
	BYTE >FF,>FF,>FF,>FF,>FF,>00
	BYTE >00,>00,>00,>00,>00,>FB
BYTEF7	BYTE >F7
*
* Sektor-Interlace Liste Single Density (IL=3)
*
L50DF   BYTE 0,7,5,3,1,8,6,4,2

	BYTE >00,>00
*
*	Identifier Mark des Sektor Identifiers, 12x 0 plus 3 >F5, die als >A1 geschrieben werden
*	Nimmt man das Data Address Mark noch hinzu, wird es das Data Mark
*	Die Tabelle wird -15 relativ zu BYTEFB adressiert
*
	BYTE >00,>00,>00,>00,>00,>00,>00,>00,>00,>00,>00,>F5,>F5,>F5	
*
L50F8	BYTE >FB	Data Address Mark (DAM)

* Sektor-Interlace Liste Double Density (IL=4)

L50F9   BYTE 0,11,4,15,8,1,12,5,16,9,2,13,6,17,10,3,14,7
	EVEN

*************************************************************
* Subroutine zum formatieren einer Spur Double Density
*************************************************************
FMTRDD	CLR  R2			Sektor-Zaehler
	SBZ  >A			Double Density
	LI   R0,>4E4E		Index Gap
	BL   @L50AC		Die ersten 16 Bytes duerfen vom Track-Ende kannibalisiert werden
	DATA >0020		32 mal >4E schreiben, normal waeren 60 mal
*
* Ein Sektor
*
L511A   LI   R6,-15
L511E   MOVB @L50F8(R6),@-2(R15)	Identifier Mark
	INC  R6
	JNE  L511E
	MOVB @BYTEFE,@-2(R15)	noch ein >FE (ID Address Mark) anhaengen
	NOP
	MOVB R3,@-2(R15)	Spur-Nr.
	NOP
	MOVB R10,@-2(R15)		Seiten-Index
	MOVB @L50F9(R2),@-2(R15)	Sektor-Nr. aus der Interlace-Tabelle.
	NOP
	MOVB @L4BC6,@-2(R15)	>01, Sektorlaenge 256 Bytes
	NOP
	MOVB @L4F2E,@-2(R15)	>F7, CRC schreiben (2 Bytes werden hier effektiv geschrieben)
	LI   R0,>4E4E
	BL   @L50AC		22 mal >4E, das ist Standard
	DATA >0016
	LI   R6,-16
L515E	MOVB @>50F9(R6),@-2(R15) 	Data Mark incl. DAM schreiben
	INC  R6
	JNE  L515E
	LI   R0,>E5E5		Leerdaten
	BL   @L50AC		256 Byte >E5
	DATA >0100
	MOVB @L4F2E,@-2(R15)	>F7, CRC ausloesen
	LI   R0,>4E4E
	BL   @L50AC		28x >4E, Standard
	DATA >001C
	INC  R2			naechster Sektor
	C    R2,@SPTDD		gleich >0012?
	JL   L511A		nein - weiter

* Track Gap (Spur Postambel) schreiben

	BL   @L50AC		Track Gap - der laeuft bis zum Index-Puls
	DATA >00BE 		190 Bytes
*
* Tracklaenge = 32 + 190 + 18 * 344 = 6414
*
	LI   R4,3		3 Retries
L5194	MOVB @>4E(R9),R2	PAB-Buffer  
	BL   @SVDPRA		Leseadresse erneut setzen
	BL   @L4D8A		Write track, delay lt. obiger Definition!
	DATA >F400		Kommandotyp III
	MOV  R15,R2		VDP Lesen vorbereiten
	AI   R2,>FBFE		Offset weg
	LI   R6,>190E		Anzahl der Bytes (6414) pro Spur bei DD!
	SBO  2			Wait enable
	BL   *R9		Datentransfer immer am Start des WP
	BL   @WNBUSY		Wait disable, warten
	SLA  R0,11		Write protect?
	JNC  L51BC		Nein
	B    @L4D3C		Ja - Abbruch!
L51BC   SLA  R0,4 		Lost data?
	JNC  L51CA		Nein, OK!
	DEC  R4			noch Retries?
	JNE  L5194		ja
	BL   @L4EB6		nein!
	DATA >3300
L51CA   B    *R8		Ende

******************************
* Fortsetzung von CALL MANAGER
******************************
CLLMGR	LI   R1,MGRBEG             Startadresse der zu kopierenden Routinen.
       LI   R2,>A000             Zieladresse der Verschiebung!
L51D4   MOV  *R1+,*R2+
       CI   R1,MGREND             Ende?
       JNE  L51D4
       B    @>A032               Einsprung in die Laderoutine

****************************************************************
* Loader fuer CALL MANAGER (51E0)
* Wird in die Memexp ab >A000 kopiert und laedt den Manager
* von DSK1-4 ins lower memory ab >2000
****************************************************************

* A000 
MGRBEG   BSS  16              Workspaceregister 0 bis 7
	DATA >0014           Reg. 8
	DATA >0500           Reg. 9
	DATA >0600           Reg. 10
	BSS  2               Reg. 11

* Beginn des PAB, verschachtelt in den Workspace

* A018
	DATA >0000           Reg. 12 - I/O-Opcode.
	DATA >1000           Reg. 13 - PAB-Data Buffer
        DATA >0000           Reg. 14
        DATA >2000           Reg. 15 - File-Laenge

	DATA >600F           Screen-Offset und Filenamenlaenge (A020)
	TEXT 'DSK1.DSKMANAGER'				(A022)
	BYTE 0               Effekt wie 'EVEN'! 	(A031)
	SBZ  >B			(A032)
	SBZ  >0              DSR-ROM abschalten
	LWPI >A000
	MOV  R9,R12          READ-Opcode setzen
MGRL00	LI   R0,>0900        PAB-Buffer im VDP-RAM 	(A03C)
	LI   R1,>A018        PAB-Adresse
	LI   R2,>1A
	BL   @>A08A          VMBW
	AI   R0,9            Namelength
	MOV  R0,@>8356       in POINT
	BLWP @>A0BE          DSRLNK
	DATA 8
	JNE  MGRL01           kein Fehler
	CLR  R2              doch!
	MOVB @>A025,R2       LW-Nr. holen
	AI   R2,>0100        naechstes LW
	MOVB R2,@>A025       wieder in den PAB
	CI   R2,>3500        schon Nr.5?
	JNE  MGRL00           nein
	BLWP @>0000          doch - Ende!
MGRL01	LI   R0,>1000        VDP-Puffer Adresse	(A074)
	LI   R1,>2000        RAM-Startadresse
	LI   R2,>2000        Byteanzahl
	BL   @>A0A8          Programm ins Low-Memory
	B    @>2000          und ausfuehren
	DATA >0000		(A088)
**************************************
* VMBW
**************************************
	SWPB R0			(A08A)
	MOVB R0,@>8C02
	SWPB R0
	ORI  R0,>4000        Schreib-Code
	MOVB R0,@>8C02
	ANDI R0,>3FFF        Wert wieder anpassen
MGRL02	MOVB *R1+,@>8C00		(A09E )
	DEC  R2
	JNE  MGRL02
	RT
**************************************
* VMBR
**************************************
	SWPB R0			(A0A8)
	MOVB R0,@>8C02
	SWPB R0
	MOVB R0,@>8C02
MGRL03	MOVB @>8800,*R1+	(A0B4)
	DEC  R2
	JNE  MGRL03
	RT  

	DATA >A0D2,>A112     DSRLNK Context-Switch (A0BE)
	DATA >A0F2,>A1EC		(52A2   A0C2)
	TEXT ' .'            Blank und Punkt (52A6   A0C6 )
	BYTE >AA             Header	(52A8   A0C8 )

            BYTE 0
	BSS  8               Device-Name Buffer (52AA   A0CA )
	BSS  32              DSRLNK Workspace	( bis   A0D2 )
	BSS  32              VSBR Workspace	(52F1   A0F2 )

* DSRLNK

	MOV  *R14+,R5        Subroutinen-Typ aus dem Data gewinnen. (52F2   A112)
            SZCB @>A0C6,R15       Im Status das Equal Bit loeschen.
            MOV  @>8356,R0       Namelength-Pointer.
            MOV  R0,R6
            AI   R6,>FFF8        Zeiger auf Status-Byte des PAB
            BLWP @>A0C2          VSBR
            MOVB R1,R3           Namelength in R1
            SRL  R3,8
            CI   R3,8
            JLE  MGRL04
            LI   R3,8            Maximal bis zur Namenlaenge=8 pruefen!
MGRL04	SETO R4		(A134)
            LI   R2,>A0CA        Pointer auf den Device-Name Buffer
MGRL05    INC  R0		(A13A)
            INC  R4
            C    R4,R3           schon beim Ende?
            JEQ  MGRL06		Ja
            BLWP @>A0C2          Nein - weiter
            MOVB R1,*R2+         in den Puffer
            CB   R1,@>A0C7       Punkt?
            JNE  MGRL05           Nein
MGRL06	MOV  R4,R4           Laenge 0?	(A14E)
            JEQ  MGRL14
            CI   R4,7            Device-Name Length
            JGT  MGRL14           zu gro~!
            CLR  @>83D0          CRU Search-Pointer
            MOV  R4,@>8354       Device-Name Length sichern
            INC  R4              hinter den Punkt zeigen
            A    R4,@>8356       Pointer auf Filenamen einstellen
            LWPI >83E0           Richtiger Workspace
            CLR  R1              Loop-Counter
            LI   R12,>0F00
MGRL07	 MOV  R12,R12		(A170)
            JEQ  MGRL08
            SBZ  0               ROM im Zweifelsfall ausschalten.
MGRL08  AI   R12,>0100       naechste CRU-Seite (A176)
            CLR  @>83D0          Search-Pointer loeschen
            CI   R12,>2000       Ende?
            JEQ  MGRL13           Ja - Fehler
            MOV  R12,@>83D0
            SBO  0               ROM an
            LI   R2,>4000        Pointer zum Anfang des ROM's
            CB   *R2,@>A0C8      >AA?
            JNE  MGRL07           Nein, kein ROM
            A    @>A0DC,R2       R5 addieren!
            JMP  MGRL10
MGRL09   MOV  @>83D2,R2       Weiterverweisadresse holen (A19A)
            SBO  0
MGRL10    MOV  *R2,R2          Tafelanfang holen (A1A0)
            JEQ  MGRL07           wenn 0 dann ist keine Tafel da!
            MOV  R2,@>83D2       Weiterverweis sichern
            INCT R2              auf Einsprung zeigen
            MOV  *R2+,R9         diese Adresse vorerst merken
            MOVB @>8355,R5       Device-Name Length
            JEQ  MGRL12           Null?
            CB   R5,*R2+         Namelength pruefen
            JNE  MGRL09           Nicht gleich - falsche SBR
            SRL  R5,8            gleich, Counter anpassen
            LI   R6,>A0CA        Startadresse Device-Name Buffer
MGRL11    CB   *R6+,*R2+       Byteweiser Vergleich	(A1BC)
            JNE  MGRL09           Ungleiche Bytes
            DEC  R5              fertig?
            JNE  MGRL11           Nein
MGRL12            INC  R1              doch, Loop-Counter auf 1. Lauf setzen (A1C4)
            BL   *R9             SBR anspringen
            JMP  MGRL09           Rueckkehr bei parallelen Karten
            SBZ  0               normale Rueckkehr
            LWPI >A0D2           alter Workspace
            MOV  R6,R0
            BLWP @>A0C2          Statusbyte lesen
            SRL  R1,>D           Bits 0 bis 3 isolieren
            JNE  MGRL15           nicht 0, dann Fehler
	    RTWP                 Ende von DSRLNK (A1DA)

* Fehler bei DSRLNK

MGRL13  LWPI >A0D2           Workspace bei Error-Return	(A1DC)
MGRL14  CLR  R1			(A1E0)
MGRL15  SWPB R1			(A1E2)
            MOVB R1,*R13         Fehlerbyte in altes Register 0
            SOCB @>A0C6,R15      Status auf Equal aendern.
            RTWP

* VSBR   liefert Wert in R1 des rufenden Programms an der Adresse in R0 (A1EC)

	CLR  R1
            MOV  *R13,R0         R0 des rufenden Prgs. in eigenem Ro
            SWPB R0
            MOVB R0,@>8C02
            SWPB R0
            MOVB R0,@>8C02
            MOVB @>8800,@2(R13)  Wert in R1 des rufenden PRG.
            RTWP
*
MGREND	EQU $
*
* $ bis 5F5F		DATA >FFFF	Leer
*
	AORG >5F60
*
* Umschaltroutine ins untere ROM
*
	SBO  >B			In Bank 1 nicht noetig
	MOV  @B1VTBL(R1),R1	In Bank 0 nicht noetig
	B    *R1		In Bank 0 nicht noetig
BNKRET	SBZ  >B    		Da nun das untere ROM geschaltet ist, kann im oberen ROM danach stehen, was will!
	DATA >FFFF,>FFFF	Den in Bank 0 vorhandenen Sprung B @STKRET hier vom Platz her reservieren
*
* 5FF0 bis 5FFF    Register des Floppy-Disk Controller-Chips, auf geraden Adressen (A15/CRUOUT = 0)
*
	END

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