Loco/Schnelllader
<< zurück zu Loco
Loco/Schnelllader: Die folgenden Abschnitte stellen den disassemblierten Kassetten-Schnelllader des Spiels Loco dar. Sie sind gegliedert in einzelne Codeblöcke, die gemäß ihrer Funktion während und nach dem Laden gruppiert sind.
Startblock der Datassetten-Datei[Bearbeiten | Quelltext bearbeiten]
Das folgende Datensegment ist der erste Block auf der Kassette, sollte also nur den Dateityp, die Anfangs- und Endadresse sowie den Namen des Spiels enthalten. In den darauffolgenden, üblicherweise nicht genutzten 171 Bytes findet sich aber der Code des ebenso kompakten wie leistungsfähigen Schnellladers.
ORG $033C
DB $03 ; Kennzeichen für "Absolut zu ladende Datassetten-Datei"
DW $0300 ; Anfangsadresse
DW $0334 ; Endadresse+1
DB 'LOCO BY A.R.C.',$00,$00 ; Antony 'Ratt' Crowther
; Programmblock von Band lesen und starten
P_AA: JSR P_AB ; Byte von Band lesen
CMP #$00 ; Erneute Synchronisation, falls auf Synchronisationszeichen $09..$01 der Wert $00 folgt
BEQ P_AA
JSR P_AC ; Byte von Band lesen
STA *$C1 ; und als Startadresse (Low-Byte) speichern
JSR P_AC ; Byte von Band lesen
STA *$C2 ; und als Startadresse (High-Byte) speichern
JSR P_AC ; Byte von Band lesen
STA *$2D ; und als Endadresse+1 (Low-Byte) speichern
JSR P_AC ; Byte von Band lesen
STA *$2E ; und als Endadresse+1 (High-Byte) speichern
AA00: JSR P_AC ; Programmbyte von Band lesen
STA ($C1),Y ; und in Speicher schreiben
INC *$C1 ; Schreibzeiger erhöhen (Low-Byte)
BNE AA01 ; Sprung falls kein Übertrag
INC *$C2 ; Schreibzeiger erhöhen (High-Byte)
AA01: LDA *$C1 ; Schreibzeiger holen (Low-Byte)
CMP *$2D ; und mit Endadresse+1 vergleichen (Low-Byte)
LDA *$C2 ; Schreibzeiger holen (High-Byte)
SBC *$2E ; und mit Endadresse+1 vergleichen (High-Byte)
BCC AA00 ; Rücksprung falls Endadresse noch nicht erreicht
STY $02A0 ; Y=0 in IRQ-Vektor während Bandbetrieb schreiben (?)
JSR $FC93 ; Recorderbetrieb beenden
JSR $FD15 ; Hardware und I/O-Vektoren setzen
STY *$C0 ; Flag für Bandmotor auf $FF setzen
CLI ; Interrupts wieder zulassen
JSR $E453 ; BASIC-Vektoren laden
LDA #$FE ; STOP-Vektor verbiegen
STA $0328 ; und damit Stop-Taste deaktivieren
JSR $A660 ; BASIC-Befehl CLR
JSR $A68E ; Programmzeiger auf BASIC-Start
JMP $A7AE ; Interpreterschleife
; Initialisierung und Synchronisation
P_AB: LDY #$00 ; Recordermotor einschalten
STY *$C0
LDA #$0B ; Bildschirm ausschalten
STA $D011
AB00: DEX ; Etwa 330 ms Verzögerung
BNE AB00
DEY
BNE AB00
SEI ; Interrupts während Ladevorgang abschalten
LDA #$07 ; Timer B Low-Byte
STA $DD06 ; setzen
LDX #$01 ; Timer B High-Byte
AB01: JSR P_AD ; setzen und ein Bit von Band holen
ROL *$BD ; Gelesenes Bit von rechts in Speicherzelle $BD schieben
LDA *$BD
CMP #$02 ; Synchronisationszeichen $02 gelesen?
BNE AB01 ; Rücksprung falls nicht
LDY #$09
AB02: JSR P_AC ; Byte von Band lesen
CMP #$02 ; Weitere Synchronisationszeichen $02 überlesen
BEQ AB02
AB03: CPY *$BD ; Synchronisationszeichen $09,...$01 gelesen?
BNE AB01 ; Erneute Synchronisation falls nicht
JSR P_AC ; Byte von Band lesen
DEY ; Synchronisationszeichen herunterzählen
BNE AB03 ; Sprung falls noch nicht alle Synchronsationszeichen $09..$01 gelesen
RTS ; Rückkehr zur aufrufenden Routine
; Ein Byte von Band lesen und nach A
P_AC: LDA #$08 ; Bitzähler
STA *$A3 ; initialisieren
AC00: JSR P_AD ; Ein Bit von Band lesen und nach CF
ROL *$BD ; Gelesenes Bit von rechts in Speicherzelle $BD schieben
DEC *$A3 ; Bitzähler vermindern
BNE AC00 ; Rücksprung falls noch nicht 8 Bit gelesen
LDA *$BD ; Gelesenes Byte nach A holen
RTS ; Rückkehr zur aufrufenden Routine
; Ein Bit von Band lesen und nach CF
P_AD: LDA #$10 ; Bitmaske für Interrupt durch Pin FLAG
AD00: BIT $DC0D ; Auf Interrupt prüfen
BEQ AD00 ; Rücksprung falls kein Impuls vom Band
LDA $DD0D ; Interruptanforderungen CIA2 holen und löschen
STX $DD07 ; CIA2 Timer B High-Byte auf 1 setzen
PHA ; A retten
LDA #$19 ; CIA2 Timer B neu laden und starten (one shot)
STA $DD0F
PLA ; A zurückholen
LSR A ; Bit für "Unterlauf Timer B" nach CF
LSR A
RTS ; Rückkehr zur aufrufenden Routine
NOP
Programmblock[Bearbeiten | Quelltext bearbeiten]
Die Programmdaten, die beim Laden der Datei "LOCO BY A.R.C." von den Datassettenroutinen des Kernals in den Speicher übertragen werden, enthalten keinen ausführbaren Code, sondern überschreiben lediglich die meisten der BASIC-Vektoren mit der Startadresse des Schnellladers und erzwingen damit einen Autostart.
PRG $0300
DW P_AA ; Vektor für BASIC-Warmstart
DW P_AA ; Vektor für Eingabe einer Zeile
DW P_AA ; Vektor für Umwandlung in Interpretercode
DW P_AA ; Vektor für Umwandlung in Klartext (LIST)
DW P_AA ; Vektor für BASIC-Befehlsadresse holen
DW P_AA ; Vektor für Ausdruck auswerten
DB $00 ; Akku für SYS-Befehl
DB $00 ; X-Reg für SYS-Befehl
DB $00 ; Y-Reg für SYS-Befehl
DB $00 ; Status-Register für SYS-Befehl
DB $00 ; eigentlich JMP-Befehl für USR-Funktion
DW $0000 ; eigentlich USR-Vektor
DB $00
DW $EA31 ; IRQ-Vektor
DW $FEC1 ; BRK-Vektor
DW $FEC1 ; NMI-Vektor
DW P_AA ; OPEN-Vektor
DW P_AA ; CLOSE-Vektor
DW P_AA ; CHKIN-Vektor
DW P_AA ; CKOUT-Vektor
DW P_AA ; CLRCH-Vektor
DW P_AA ; INPUT-Vektor
DW P_AA ; OUTPUT-Vektor
DW $E68E ; STOP-Vektor
DW P_AA ; GET-Vektor
DW P_AA ; CLALL-Vektor
DW P_AA ; Warmstart-Vektor
DW P_AA ; LOAD-Vektor
DW P_AA ; SAVE-Vektor