BattleTech – The Crescent Hawk's Inception/Schnelllader

Aus C64-Wiki
Zur Navigation springenZur Suche springen

<< 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


Artikel des Monats.gif Dieser Artikel wurde Artikel des Monats.