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 ; Füllbytes $00 überlesen 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 0.33 s 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