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