BattleTech – The Crescent Hawk's Inception/Schnelllader
<< zurück zu Battletech
Battletech/Schnelllader: Die folgenden Abschnitte stellen den disassemblierten Floppy-Schnelllader des Spiels Battletech dar. Sie sind gegliedert in einzelne Codeblöcke, die gemäß ihrer Funktion vor dem und während des Ladens gruppiert sind.
Startroutinen[Bearbeiten | Quelltext bearbeiten]
Die nachfolgende Routine P_IG überträgt einen Teil der Floppy-seitigen Schnelllade-Routinen mittels des "M-W"-Befehls ("Memory-Write") in Abschnitten zu jeweils 32 Bytes in das RAM der Floppy. Da der Floppy-seitige Schnelllader aus zwei Teilen besteht (Routine P_AA ab Adresse TARGET1=$0500 sucht die zu ladende Datei im Directory, und Routine P_AB ab Adresse TARGET2=$0400 überträgt die Datei zum C64), wird die Routine zweimal vom übergeordneten Programmteil P_JA aufgerufen. Anschließend können die beiden Schnelllade-Routinen abwechselnd mit den User-Befehlen "U3" (für Routine P_AA) und "U4" (für Routine P-AB) gestartet werden.
DEVICE EQU 8 ; Geräteadresse
; Einen Floppy-seitigen Schnelllader ins RAM der Floppy kopieren
P_IG: STA T004 ; Anzahl Blocks zu je 32 Bytes merken
IG00: JSR P_JC ; "M-W"-Befehl an Floppy senden
LDY #$00 ; Lesezeiger initialisieren
IG01: LDA ($FB),Y ; Floppy-seitigen Schnelllader byteweise lesen
JSR $FFA8 ; und an Floppy senden
INY ; Lesezeiger erhöhen
CPY #32 ; Blockgröße erreicht
BNE IG01 ; Rücksprung falls noch nicht erreicht
LDA #$00 ; Etwa 1,8 ms Verzögerung
IG02: SEC
SBC #$01
BNE IG02
JSR $FFAE ; UNLISTEN senden
TYA ; A=Blockgröße (32 Bytes)
CLC ; zur Leseadresse addieren
ADC *$FB
STA *$FB ; und zurückschreiben
BCC IG03 ; Sprung falls kein Additionsübertrag
INC *$FC ; Additionsübertrag berücksichtigen
CLC
IG03: LDA T003+$03 ; Low-Byte der Zieladresse im "M-W"-Befehl
ADC #32 ; um Blockgröße erhöhen
TAY ; Y=Low-Byte der Zieladresse im Floppy-RAM (unnötig)
BCC IG04 ; Sprung falls kein Additionsübertrag
INC T003+$04 ; sonst High-Byte der Zieladresse im "M-W"-Befehl erhöhen
IG04: LDX T003+$04 ; X=High-Byte der Zieladresse im Floppy-RAM (unnötig)
DEC T004 ; Anzahl Blocks erniedrigen
BNE IG00 ; Rücksprung falls noch nicht alle Blocks übertragen
RTS
T004: DB $00 ; Zähler für Anzahl der "M-W"-Blocks
; Beide Teile des Floppy-seitigen Schnellladers ins RAM der Floppy schreiben
P_JA: LDA #<SOURCE1 ; Low-Byte Anfangsadresse Floppy-seitiger Schnelllader Teil 1
STA *$FB ; als Low-Byte des Lesezeigers setzen
LDA #>SOURCE1 ; High-Byte Anfangsadresse Floppy-seitiger Schnelllader Teil 1
STA *$FC ; als High-Byte des Lesezeigers setzen
LDY #$00 ; Low-Byte der Zieladresse im Floppy-RAM
LDX #$05 ; High-Byte der Zeiladresse im Floppy-RAM
LDA #$07 ; Anzahl Blocks zu je 32 Bytes
JSR P_IG ; per "M-W" in Floppyspeicher schreiben
LDA #<SOURCE2 ; Low-Byte Anfangsadresse Floppy-seitiger Schnelllader Teil 2
STA *$FB ; als Low-Byte des Lesezeigers setzen
LDA #>SOURCE2 ; High-Byte Anfangsadresse Floppy-seitiger Schnelllader Teil 2
STA *$FC ; als High-Byte des Lesezeigers setzen
LDY #$00 ; Low-Byte der Zieladresse im Floppy-RAM
LDX #$04 ; High-Byte der Zieladresse im Floppy-RAM
LDA #$05 ; Anzahl Blocks zu je 32 Bytes
JSR P_IG ; per "M-W" in Floppyspeicher schreiben
RTS
; Einzelnes Byte mit "M-W" ins RAM der Floppy schreiben
P_JB: STA T003+$06 ; Zu schreibendes Byte an "M-W"-Befehl anhängen
LDA #$01 ; 1 Byte
STA T003+$05 ; per "M-W" ins Floppy-RAM schreiben
JSR P_JC ; "M-W"-Befehl mit Zieladresse X/Y an Floppy senden
LDA T003+$06 ; Zu schreibendes Byte holen
JSR $FFA8 ; und an Floppy senden
LDA #$00 ; Etwa 1,8 ms Verzögerung
JB00: SEC
SBC #$01
BNE JB00
JSR $FFAE ; UNLISTEN senden
LDA #$20 ; Übliche Blockgröße (32 Bytes)
STA T003+$05 ; im "M-W"-Befehl wiederherstellen
RTS
; "M-W"-Befehl mit Zieladresse X/Y an Floppy senden
P_JC: STY T003+$03 ; Schreibadresse im Floppy-RAM in "M-W"-Befehl aufnehmen (Low-Byte)
STX T003+$04 ; Schreibadresse im Floppy-RAM in "M-W"-Befehl aufnehmen (High-Byte)
JSR P_JD ; LISTEN an Befehlskanal der Floppy
LDY #$00 ; Lesezeiger für "M-W"-Befehl
JC00: LDA T003,Y ; "M-W"-Befehl zeichenweise lesen
JSR $FFA8 ; und an Floppy senden
INY ; Lesezeiger weiterbewegen
CPY #$06 ; Schon alle Zeichen gesendet?
BNE JC00 ; Sprung falls noch nicht alle Zeichen
RTS
; Befehlskanal der Floppy zum Schreiben öffnen
P_JD: LDA #DEVICE ; Geräteadresse
JSR $FFB1 ; LISTEN senden
LDA #$6F ; Sekundäradresse 15 (Befehlskanal der Floppy)
JMP $FF93 ; Sekundäradresse nach LISTEN senden
C64-seitige Schnelllade-Routinen[Bearbeiten | Quelltext bearbeiten]
Jedes Laden einer Datei geschieht in drei Schritten: Zunächst wird der Name der Datei (abgeschlossen mit Endekennzeichen $00) mit Hilfe des "Memory-Write" ("M-W")-Befehls in den Puffer T006 im RAM der Floppy geschrieben. Der User-Befehl "U4" (Routine P_AB) durchsucht anschließend das Directory der Diskette nach diesem Namen; im Erfolgsfall schreibt er Spur- und Sektornummer des ersten Dateiblocks nach Adresse $0300/$0301 und setzt die Leitungen DATA und CLOCK auf low. Bleibt die Suche erfolglos (beispielsweise weil der Aufforderung, die Diskette zu wenden, nicht Folge geleistet wurde), so teilt die Routine dies mit DATA high und CLOCK low mit. Wurde die Datei gefunden, so kann dann mit dem User-Befehl "U3" die Übertragung zum C64 gestartet werden.
T000: DB $00 ; Attribute der zu ladenden Datei
; Zeiger an Adresse $FB/$FC auf Ladeadresse der Datei setzen, X/Y zeigen auf Dateinamen
P_IA: STX IA02+$01
STY IA03+$01
LDY #$00 ; Lesezeiger für Tabelle der Dateinamen
LDA ($FB),Y ; Erstes Headerbyte
STA IA04+$01 ; merken
AND #$04 ;
BNE IA00
LDY #$01
LDA ($FB),Y ; Zweites Headerbyte (Low-Byte der Ladeadresse)
STA IA03+$01 ; merken
INY ; Lesezeiger weiterbewegen
LDA ($FB),Y ; Drittes Headerbyte (High-Byte der Ladeadresse)
STA IA02+$01
IA00: LDA *$FB ; Adresszeiger
CLC ; um Länge des Headers weiterbewegen (3 Bytes)
ADC #$03
STA *$FB ; und zurückschreiben
BCC IA01 ; Sprung falls kein Additionsübertrag
INC *$FC ; Additionsübertrag berücksichtigen
IA01: LDA *$FC ; Altes High-Byte des Adresszeigers (Zeiger auf Dateinamen)
IA02: LDX #$00 ; High-Byte der Ladeadresse
STX *$FC ; im Adresszeiger speichern
TAX ; X zeigt auf Dateinamen (Low-Byte)
LDA *$FB ; Altes Low-Byte des Adresszeigers (Zeiger auf Dateinamen)
IA03: LDY #$00 ; Low-Byte der Ladeadresse
STY *$FB ; in Adresszeiger speichern
TAY ; Y zeigt auf Dateinamen (High-Byte)
IA04: LDA #$00 ; Dateiattribute
STA T000 ; merken
RTS
; Zeiger an Adresse $FB/$FC auf Namen der Datei mit der Nummer <A> richten
P_IB: STA IB05+$01 ; A retten
STX IB06+$01 ; X retten
STA IB00+$01 ; Laufende Nummer der zu lesenden Datei (0..11)
LDX #$00 ; Index für Zugriff über ($FB,X)
LDA #<T001 ; Zeiger auf Tabelle der Dateinamen, Low-Byte
STA *$FB ; als Initialwert für Zeiger
LDA #>T001 ; Zeiger auf Tabelle der Dateinamen, High-Byte
STA *$FC ; als Initialwert für Zeiger
IB00: LDA #$00 ; Namen der gewünschten Datei erreicht?
BEQ IB05 ; Sprung falls erreicht
LDA #$03 ; Anzahl Headerbytes vor Dateinamen in Tabelle T001
CLC ; zu Adresse addieren
ADC *$FB
STA *$FB
BCC IB02 ; Sprung falls kein Additionsübertrag
IB01: INC *$FC ; Additionsübertrag berücksichtigen
IB02: LDA ($FB,X) ; Zeichenweise Dateinamen lesen
BEQ IB03 ; Sprung falls Endemarkierung gefunden
INC *$FB ; Addresse erhöhen
BNE IB02 ; Sprung falls kein Additionsübertrag
BEQ IB01 ; Sprung mit Berücksichtigung des Additionsübertrags
IB03: INC *$FB ; Endemarkierung überlesen
BNE IB04 ; Sprung falls kein Additionsübertrag
INC *$FC ; Additionsübertrag berücksichtigen
IB04: DEC IB00+$01 ; Laufende Nummer der Datei herunterzählen
JMP IB00 ; und nächsten Tabelleneintrag behandeln
IB05: LDA #$00 ; A wiederherstellen
IB06: LDX #$00 ; X wiederherstellen
RTS
P_IC: STA IC02+$01 ; A retten
STX IC03+$01 ; X retten
STY IC04+$01 ; Y retten
IC00: STA IC01+$01 ; A retten
LDA #$18 ; CLC
STA IC05 ;
IC01: LDA #$00 ; A wiederherstellen (laufende Nummer der zu ladenden Datei)
JSR P_IB ; Zeiger an Adresse $FB/$FC auf Namen der zu ladenden Datei richten
JSR P_IA ; Zeiger an Adresse $FB/$FC auf Ladeadresse setzen, X/Y zeigt auf Dateinamen
JSR P_IE ; Dateinamen an Adresse (X/Y) ins Floppy-RAM und Datei laden
IC02: LDA #$00 ; A wiederherstellen
IC03: LDX #$00 ; X wiederherstellen
IC04: LDY #$00 ; Y wiederherstellen
BCS IC00
IC05: CLC
RTS
; Tabelle der Dateinamen, Format: Attribut, Ladeadresse low/high, Dateiname, $00
T001: DB $02,$00,$C0,'BSET',$00
DB $02,$00,$CC,'BCOL',$00
DB $02,$00,$CC,'BCHR',$00
DB $02,$00,$E0,'TPAG',$00
DB $02,$00,$B8,'TCOL',$00
DB $02,$00,$BC,'TCHR',$00
DB $02,$00,$13,'WESTWOOD',$00
DB $02,$40,$03,'I0',$00
DB $02,$40,$0B,'D',$00
DB $03,$00,$C8,'F/X',$00
DB $03,$00,$B8,'BEGTXT',$00
DB $03,$ED,$11,'ZAP',$00
T002: DB $00,$00,$00
T003: DB 'M-W',$00,$05,$20,$00
; Datei laden
P_ID: STX ID01+$01 ; Erstes per "M-W" zu schreibendes Byte
STY ID02+$01 ; Zweites per "M-W" zu schreibendes Byte
LDA #$01 ; Flag setzen
STA T002+$02 ; unnötig
LDA $D015 ; Momentan aktive Sprites
STA ID09+$01 ; merken
LDA #$00 ; und alle Sprites
STA $D015 ; abschalten
LDA *$FC ; Ladeadresse der Datei (High-Byte)
PHA ; retten
LDA *$FB ; Ladeadresse der Datei (Low-Byte)
PHA ; retten
ID00: LDA #$00 ; Nummer des zuletzt gesendeten User-Befehls (0 oder 1)
BNE ID03 ; Sprung falls "U4"
LDX #$03 ; Zieladresse $0300 für "M-W"-Befehl
LDY #$00
ID01: LDA #$FF ; An diese Adresse zu schreibendes Byte
JSR P_JB ; Byte per "M-W" an Zieladresse schreiben
LDX #$03 ; Zieladresse $0301 für "M-W"-Befehl
LDY #$01
ID02: LDA #$FF ; An diese Adresse zu schreibendes Byte
JSR P_JB ; Byte per "M-W" an Zieladresse schreiben
ID03: LDA #$00 ; User-Befehl "U3" ('3'+$00)
STA ID00+$01 ; merken
JSR P_IF ; User-Befehl "U3" an Floppy senden
PLA ; Low-Byte der Ladeadresse der Datei zurückholen
SEC ; um 2 vermindern
SBC #$02
STA *$FB ; und in Adresszeiger speichern
PLA ; High-Byte der Ladeadresse der Datei zurückholen
SBC #$00 ; Eventuellen Subtraktionsübertrag berücksichtigen
STA *$FC ; und in Adresszeiger speichern
LDA #$01
ID04: JSR P_IH ; Block aus Datei laden
LDA T002 ; Spurnummer im zuletzt geladenen Block holen
BEQ ID07 ; Sprung falls letzter Block
BPL ID06 ; Sprung falls gültige Spurnummer
LDA T002+$01 ; Anzahl gültiger Datenbytes im letzten Block holen
ID05: SEC ; "Fehler"
BCS ID08 ; Immer Sprung
ID06: LDA #$00 ; Datenblock ist komplett gefüllt
JMP ID04 ; Nächsten Block laden
ID07: LDA T002+$01 ; Anzahl gültiger Datenbytes im letzten Block holen
BEQ ID05 ; Sprung falls nicht 0 Bytes
CLC ; "Kein Fehler"
ID08: LDX #$00 ; Flag löschen
STX T002+$02 ; unnötig
ID09: LDX #$FF ; Momentan aktive Sprites
STX $D015 ; wiederherstellen
RTS
; Dateinamen ab Adresse $0407 ins Floppy-RAM schreiben und Datei laden
P_IE: LDA *$FC ; High-Byte der Ladeaddresse
PHA ; retten
LDA *$FB ; Low-Byte der Ladeadresse
PHA ; retten
STY *$FB ; Low-Byte der Anfangsadresse des Dateinamens
STX *$FC ; High-Byte der Anfangsadresse des Dateinamens
LDA #17 ; 17 Zeichen ins Floppy-RAM schreiben
STA T003+$05 ; als Länge in Befehl "M-W..." aufnehmen
LDX #$04 ; Schreibadresse im Floppy-RAM (High-Byte)
LDY #$07 ; Schreibadresse im Floppy-RAM (Low-Byte)
JSR P_JC ; "M-W"-Befehl an Floppy senden
LDY #$00 ; Lesezeiger für Dateinamen initialisieren
IE00: LDA ($FB),Y ; Dateinamen zeichenweise lesen
JSR $FFA8 ; und an Floppy senden
INY ; Lesezeiger weiterbewegen
CPY #16 ; Schon 16 Zeichen übertragen (müssten 17 sein)
BCC IE00 ; Sprung falls noch nicht 16 Zeichen
LDA #$00 ; Etwa 1,8 ms Verzögerung
IE01: SEC
SBC #$01
BNE IE01
JSR $FFAE ; UNLISTEN senden
LDA #$20 ; Übliche Blockgröße (32 Bytes)
STA T003+$05 ; im "M-W"-Befehl wiederherstellen
LDA #$01 ; User-Befehl "U4" ('3'+$01)
STA ID00+$01 ; merken
JSR P_IF ; und an Floppy senden
PLA ; Low-Byte der Ladeadresse zurückholen
STA *$FB ; Adresszeiger wiederherstellen
PLA ; High-Byte der Ladeadresse zurückholen
STA *$FC ; Adresszeiger wiederherstellen
IE02: LDA $DD00 ; Leitungsstatus holen
AND #$C0 ; DATA und CLOCK low?
BEQ IE03 ; Sprung falls DATA und CLOCK low (bereit zum Laden)
CMP #$80 ; DATA high, CLOCK low?
BEQ IE04 ; Sprung falls DATA high, CLOCK low (Fehler)
BNE IE02 ; sonst warten
IE03: JMP P_ID ; Datei laden
IE04: LDA #$00 ; Nummer des zuletzt gesendeten User-Befehls
STA ID00+$01 ; zurücksetzen
LDA #$07 ; wird ignoriert
SEC ; Fehlerflag
RTS
; User-Befehl <A> an Floppy senden
P_IF: CLC ; Zeichen '3' um Nummer des Befehls erhöhen
ADC #$33
STA IF00+$01 ; und in Befehl aufnehmen
JSR P_JD ; Befehlskanal der Floppy zum Schreiben öffnen
LDA #$55 ; 'U'
JSR $FFA8 ; an Floppy senden
IF00: LDA #$33 ; '3' plus Nummer des User-Befehls
JSR $FFA8 ; an Floppy senden
LDA #$00 ; Etwa 1,8 ms Verzögerung
IF01: SEC
SBC #$01
BNE IF01
JSR $FFAE ; UNLISTEN senden
RTS
; Datei laden
P_IH: STA IH11+$01 ; $01 speichern
LDA #$00
STA IH14+$01 ; $00 speichern
LDA $DD00 ; Status der Leitungen holen
AND #$03 ; DATA, CLOCK und ATN high setzen, VIC-Bank unverändert lassen
STA IH00+$01 ; und in Laderoutine aufnehmen
STA IH04+$01
ORA #$08 ; ATN low setzen
STA IH02+$01 ; und in Laderoutine aufnehmen
LDA *$FB ; Low-Byte der Ladeadresse holen
SEC ; Offset $02 subtrahieren (Ladeadresse ignorieren)
SBC #$02
STA *$FB ; und zurückschreiben
BCS IH00 ; Sprung falls kein Subtraktionsübertrag
DEC *$FC ; Subtraktionsübertrag berücksichtigen
IH00: LDA #$03 ; ATN high
STA $DD00 ; setzen
LDY #$00
IH01: LDX #$03 ; 4 Bitpaare (3+1) empfangen
IH02: LDA #$0B ; ATN low
STA $DD00 ; setzen
IH03: LDA $DD00 ; Auf DATA high
BPL IH03 ; warten
IH04: LDA #$03 ; ATN high
STA $DD00 ; setzen
LDA #$01 ; 13 Systemtakte Verzögerung
SEC
IH05: SBC #$01
BPL IH05
LDA $DD00 ; Pegel der Leitungen holen
STA T005,X ; und merken
LDA IH02+$01 ; ATN low
STA $DD00 ; setzen
IH06: LDA $DD00 ; Auf DATA low
BMI IH06 ; warten
LDA IH04+$01 ; ATN high
STA $DD00 ; setzen
DEX ; Schon 4 Bitpaare gesendet?
BPL IH02 ; Rücksprung falls noch nicht
LDA T005+$00 ; T005+$00 enthält Datenbit 5 in DATA (Bit 7), Datenbit 7 in CLOCK (Bit 6)
ASL A ; Datenbit 5 ins CF, Datenbit 7 in Bit 7
BCC IH07 ; Sprung falls Datenbit 5 gelöscht
ORA #$20 ; sonst Bit 5 setzen
IH07: AND #$A0 ; Jetzt Datenbit 5 in Bit 5, Datenbit 7 in Bit 7
STA T005+$00 ; merken
LDA T005+$01 ; T005+$01 enthält Datenbit 4 in DATA (Bit 7), Datenbit 6 in CLOCK (Bit 6)
BPL IH08 ; Sprung falls Datenbit 4 gelöscht
ORA #$10 ; sonst Bit 4 setzen
IH08: AND #$50 ; Jetzt Datenbit 4 in Bit 4, Datenbit 6 in Bit 6
ORA T005+$00 ; mit Bits aus erstem Byte ODER-verknüpfen
STA T005+$00 ; und zurückschreiben
LDA T005+$02 ; T005+$02 enthält Datenbit 1 in DATA (Bit 7), Datenbit 3 in CLOCK (Bit 6)
ASL A ; Datenbit 1 ins CF, Datenbit 3 in Bit 7
BCC IH09 ; Sprung falls Datenbit 1 gelöscht
ORA #$20 ; sonst Bit 5 setzen
IH09: AND #$A0 ; Jetzt Datenbit 1 in Bit 5, Datenbit 3 in Bit 7
STA T005+$02 ; merken
LDA T005+$03 ; T005+$03 enthält Datenbit 0 in DATA (Bit 7), Datenbit 2 in CLOCK (Bit 6)
BPL IH10 ; Sprung falls Datenbit 0 gelöscht
ORA #$10 ; sonst Bit 4 setzen
IH10: AND #$50 ; Jetzt Datenbit 0 in Bit 4, Datenbit 2 in Bit 6
ORA T005+$02 ; mit Bits aus drittem Byte ODER-verknüpfen
LSR A ; und ins Low-Nibble schieben
LSR A
LSR A
LSR A
ORA T005+$00 ; mit High-Nibble ODER-verknüpfen
EOR #$FF ; und invertieren, weil C64(in) nicht genegiert, Floppy(out) negiert
CPY #$02 ; Innerhalb der ersten beiden Bytes (Verkettungspointer)?
BCC IH15 ; Sprung falls ja
IH11: LDX #$FF ; Erster Block?
BNE IH16 ; Sprung falls erster Block
IH12: STA ($FB),Y ; Empfangenes Datenbyte schreiben
IH13: INY ; Schreibzeiger erhöhen
IH14: CPY #$FF ; Anzahl gültiger Bytes erreicht?
BNE IH01 ; Rücksprung falls nicht erreicht
INC *$FC ; High-Byte erhöhen
RTS
; Sonderbehandlung erste beide Datenbytes des Blocks (Verkettungspointer)
IH15: STA T002,Y ; Verkettungspointer merken
CPY #$01 ; Zweites Byte des Verkettungspointers?
BNE IH13 ; Sprung falls erstes Byte
LDX T002 ; Erstes Byte (Spurnummer) holen
BNE IH13 ; Sprung falls nicht letzter Block
ADC #$00 ; sonst Anzahl gültiger Datenbytes in A, um Offset erhöhen
STA IH14+$01 ; als Anzahl gültiger
JMP IH13
IH16: CPY #$04 ; Innerhalb der ersten vier Bytes (Verkettungspointer/Ladeadresse)?
BCS IH12 ; Sprung falls nicht innerhalb, Datenbyte schreiben
BCC IH13 ; Sprung falls innerhalb, Datenbyte ignorieren
T005: DB $00,$00,$00,$00
Floppy-seitige Schnelllade-Routinen[Bearbeiten | Quelltext bearbeiten]
Der Floppy-seitige Schnelllader besteht aus zwei unabhängigen Routinen, die mit den User-Befehlen "U3" und "U4" aufgerufen werden. "U4" durchsucht das Directory der Diskette nach einem Dateinamen, der zuvor mittels "M-W" im Puffer T006 abgelegt wurde, und schreibt im Erfolgsfall Spur- und Sektornummer des ersten Dateiblocks an Adresse $0300/$0301. "U3" liest anschließend diese Datei Block für Block und transferiert ihren Inhalt — einschließlich der Verkettungszeiger in den ersten Bytes jedes Blocks, aber ohne die Füllbytes im nur teilweise belegten letzten Block — zum C64.
SOURCE1: // im Floppy-RAM ab Adresse $0500
; Sprungverteiler
P_AA: CLC ; Einsprung für Befehl "U3": Datei laden und an C64 übertragen
BCC AA03
AA00: JMP P_AB ; Einsprung für Befehl "U4": Dateinamen im Directory suchen, Spur und Sektor des ersten Blocks nach $0300/$0301
AA01: JMP AB00 ; Einsprung für Befehl "U5" (nicht verwendet): Dateinamen mit Verzeichniseintrag vergleichen
AA02: CLC ; Einsprung für Befehl "U6" (nicht verwendet): Zeropage initialisieren
BCC AA10
AA03: SEI ; Jobschleife deaktivieren
LDA #$00
STA *$85
JSR $C118 ; LED am Laufwerk einschalten
LDA $0300 ; Spur des ersten Blocks holen
BNE AA04 ; Sprung falls Spur gültig
LDA #$07 ; ?
BNE AA08
AA04: LDA $0301 ; Sektornummer des nächsten Blocks holen
STA *$07 ; als Sektor für Puffer 0 (Adresse $0300) setzen
LDA $0300 ; Spurnummer des nächsten Blocks holen
BEQ AA10 ; Sprung wenn 0 (letzter Block)
BMI AA10 ; Sprung wenn ungültig
STA *$06 ; als Spur für Puffer 0 (Adresse $0300) setzen
LDX #$03 ; Anzahl Leseversuche
AA05: LDA #$80 ; Jobcode für "Lesen eines Sektors"
STA *$00 ; als Job für Puffer 0 (Adresse $0300) setzen
CLI ; Jobschleife aktivieren
AA06: LDA *$00 ; Rückmeldung des Jobs holen
BMI AA06 ; Rücksprung falls noch nicht erledigt
SEI ; Jobschleife wieder deaktivieren
CMP #$03 ; Fehler "Sync Markierung nicht gefunden"?
BEQ AA07 ; Sprung falls ja
CMP #$0B ; Fehler "Falsche ID/Diskette gewechselt"?
BNE AA11 ; Spung falls nein
AA07: LDY *$16 ; ID aus gelesenem Sektor holen (erstes Zeichen)
STY *$12 ; und als aktuelle ID setzen
LDY *$17 ; ID aus gelesenem Sektor holen (zweites Zeichen)
STY *$13 ; und als aktuelle ID setzen
DEX ; Anzahl Leseversuche erniedrigen
BNE AA05 ; Sprung falls noch nicht letzter Leseversuch
AA08: STA $0301 ; ?
LDA #$FF ; 255 gültige Bytes im Sektor
STA $0300 ; merken
BNE AA11
AA09: BCC AA04
AA10: CLC
BCC AA18
AA11: LDA #$0F
STA $1800 ; DATA und CLOCK low
LDA $0300 ; Spurnummer des nächsten Blocks holen
BNE AA12 ; Sprung falls nicht letzter Block
LDA $0301 ; Anzahl Datenbytes im letzten Block holen
STA *$85 ; und merken
INC *$85 ; um Offset erhöhen
AA12: LDY #$00 ; Lesezeiger initialisieren
AA13: LDA $0300,Y ; Sektor byteweise aus Puffer lesen
TAX ; und nach A
LSR A ; Bit 4 nach DATA, Bit 6 nach CLOCK
LSR A
LSR A
STA $04FD ; vormerken
LSR A ; Bit 5 nach DATA, Bit 7 nach CLOCK
STA $04FC ; vormerken
TXA ; Bit 1 nach DATA, Bit 3 nach CLOCK
STA $04FE ; vormerken
ASL A ; Bit 0 nach DATA, Bit 2 nach CLOCK
STA $04FF ; vormerken
LDX #$03 ; Anzahl zu übertragender Bitpaare minus 1
AA14: BIT $1800 ; Auf ATN low warten
BPL AA14
LDA #$10 ; DATA und CLOCK high
STA $1800
LDA $04FC,X ; Vorbereitete Bytepaare nacheinander holen
AND #$0F ; Bits für Leitungsstatus isolieren
AA15: BIT $1800 ; Auf ATN high warten
BMI AA15
STA $1800 ; Leitungen setzen
AA16: BIT $1800 ; Auf ATN low warten
BPL AA16
LDA #$0F ; DATA und CLOCK low
STA $1800
AA17: BIT $1800 ; Auf ATN high warten
BMI AA17
DEX ; Zähler für Bitpaare vermindern
BPL AA14 ; Rücksprung falls noch nicht 4 Bitpaare übertragen
INY ; Lesezeiger erhöhen
CPY *$85 ; Mit Anzahl gültiger Datenbytes im Puffer vergleichen
BNE AA13 ; Rücksprung falls noch nicht alle Datenbytes übertragen
CLC ; Unbedingter Sprung
BCC AA09
AA18: LDX #$76 ; 119 Byte langen Codeabschnitt
AA19: LDA $EB4B,X ; aus Routine "Zeropage initialisieren"
STA $0300,X ; in Puffer umkopieren
DEX ; Lesezeiger vermindern
BPL AA19 ; Rücksprung falls noch nicht ganzer Codeabschnitt kopiert
LDA #$60 ; RTS
STA $0377 ; ans Ende des umkopierten Codeabschnitts setzen
JSR $0300 ; Codeabschnitt aufrufen
JMP $EBE7 ; Sprung zur "Warteschleife zur Befehlserkennung"
SOURCE2: // im Floppy-RAM ab Adresse $0400
; Einsprung für "Dateinamen im Directory suchen, Spur und Sektor des ersten Blocks nach $0300/$0301"
P_AB: SEI
CLC
BCC P_AB01
; Einsprung für "Dateinamen mit Verzeichniseintrag vergleichen" (nicht verwendet)
AB00: CLC
BCC AB09
; Puffer für Namen der zu ladenden Datei (maximal 16 Zeichen plus Endekennzeichen $00)
T006: DB $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
; Spur und Sektor des ersten Blocks der gewünschten Datei nach $0300/$0301
; Dateiname der gewünschten Datei wird zuvor per "M-W" in T006 eingetragen
AB01: LDA #$10 ; DATA und CLOCK high, ATN nicht automatisch beantworten
STA $1800
LDA #$12 ; Spur des Directory
STA $0300
LDA #$01 ; Erster Sektor des Directory
STA $0301
AB02: LDA $0300 ; Spurnummer des nächsten Blocks im Directory holen
STA *$06 ; und als Spur für Puffer 0 (Adresse $0300) merken
BEQ AB12 ; Sprung falls kein weiterer Block im Directory
LDA $0301 ; Sektornummer des nächsten Blocks im Directory holen
STA *$07 ; und als Sektor für Puffer 0 (Adresse $0300) merken
LDX #$03 ; Anzahl Leseversuche
AB03: LDA #$80 ; Jobcode für "Lesen eines Sektors"
STA *$00 ; als Job für Puffer 0 (Adresse $0300) speichern
CLI ; Jobschleife aktivieren
AB04: LDA *$00 ; Rückmeldung des Jobs holen
BMI AB04 ; Rücksprung falls noch nicht erledigt
SEI ; Jobschleife wieder deaktivieren
CMP #$03 ; Fehler "Sync Markierung nicht gefunden"?
BEQ AB05 ; Sprung falls ja
CMP #$0B ; Fehler "Falsche ID/Diskette gewechselt"?
BNE AB06 ; Sprung falls nein
AB05: LDY *$16 ; ID aus gelesenem Sektor holen (erstes Zeichen)
STY *$12 ; und als aktuelle ID setzen
LDY *$17 ; ID aus gelesenem Sektor holen (zweites Zeichen)
STY *$13 ; und als aktuelle ID setzen
DEX ; Anzahl Leseversuche erniedrigen
BNE AB03 ; Sprung falls noch nicht letzter Leseversuch
AB06: LDY #$00 ; Lesezeiger für Directory-Einträge initialisieren
AB07: LDA $0302,Y ; Dateityp des nächsten Directory-Eintrags holen
BEQ AB13 ; Sprung falls gelöscht
LDX #$00 ; Lesezeiger für Dateinamens-Vergleich initialisieren
AB08: LDA $0407,X ; Gewünschten Dateinamen zeichenweise lesen
BNE AB09 ; Sprung falls nicht Stringende
CPX #$10 ; Maximale Länge eines Dateinamens erreicht?
BEQ AB10 ; Sprung falls ja
LDA $0305,Y ; Dateinamen im Directory-Eintrag zeichenweise lesen
CMP #$A0 ; Ende des Directory-Eintrags (<Shift>-<Space>)
BNE AB13 ; Sprung falls nicht Ende, weitervergleichen
BEQ AB10 ; Sprung falls Ende, gewünschten Dateinamen gefunden
AB09: CMP $0305,Y ; Gewünschten und gefundenen Dateinamen zeichenweise vergleichen
BNE AB13 ; Zum nächsten Directory-Eintrag übergehen, falls ungleich
INY ; Lesezeiger im Directory weiterbewegen
INX ; Lesezeiger auf gewünschten Dateinamen weiterbewegen
BNE AB08 ; und immer Rücksprung
AB10: TYA ; Lesezeiger auf Directory-Eintrag nach A holen
AND #$E0 ; auf Anfangsadresse des aktuellen Eintrags zurücksetzen
TAY ; und zurück nach Y übertragen
LDA $0303,Y ; Spurnummer des ersten Blocks zum aktuellen Eintrag holen
STA $0300 ; und in erstes Byte des aktuellen Puffers kopieren
LDA $0304,Y ; Sektornummer des ersten Blocks zum aktuellen Eintrag holen
STA $0301 ; und in zweites Byte des aktuellen Puffers kopieren
LDA #$0F ; CLOCK und DATA auf low
AB11: STA $1800
CLI ; Jobschleife aktivieren
RTS ; Unterprogramm beendet
AB12: LDA #$0C ; CLOCK und DATA high
BNE AB11 ; als Fehlerkennzeichen setzen
AB13: TYA ; Lesezeiger auf Directory-Eintrag nach A holen
AND #$E0 ; auf Anfangsadresse des aktuellen Eintrags zurücksetzen
CLC ; auf nächsten Eintrag weiterbewegen
ADC #$20 ; indem die Länge eines Directory-Eintrags addiert wird
TAY ; und zurück nach Y übertragen
BCC AB07 ; Sprung falls nicht Ende des aktuellen Directory-Blocks erreicht
BCS AB02 ; Sprung zum Einlesen des nächsten Directory-Sektors
| Dieser Artikel wurde Artikel des Monats. |