10 ; SPEED-LOADER für 1581 & C64 20 ; 100 ; ******** LABELS 1581 *********** 110 ; 120 .EQUATE BYTESECT = $ FF 130 .EQUATE CACHE = $0C00 140 .EQUATE CHANNEL = $ 50 150 .EQUATE CHNOPN = $9027 160 .EQUATE CHNTAB = $ BB 170 .EQUATE DATA = $023B 180 .EQUATE DELAY = $AD30 190 .EQUATE DIRFLG = $026E 200 .EQUATE DRIVENR = $ EF 210 .EQUATE EOI = $ 80 220 .EQUATE ERROR = $ 01 230 .EQUATE GETBUFFP = $9442 240 .EQUATE GETBYTE = $909B 250 .EQUATE GETDIR = $8F03 260 .EQUATE HOSTFLG = $ 76 270 .EQUATE JALLOCBF = $FF66 280 .EQUATE JBOOTRTN = $FF5A 290 .EQUATE JDEJAVU = $FF60 300 .EQUATE JERROR = $FF2D 310 .EQUATE JJIDLE = $AED9 320 .EQUATE JOBNR = $ 06 330 .EQUATE JOB = JOBNR+2 340 .EQUATE OKMESS = $A862 350 .EQUATE POINTER = $ 64 360 .EQUATE QUANTITY = $ 54 370 .EQUATE READ = $ 80 380 .EQUATE SECADR = $ 52 390 .EQUATE SECTOR = JOBNR*2+12 400 .EQUATE SIDE = $ 96 410 .EQUATE SPTMP = $ 4F 420 .EQUATE SRCHCMD = $01DB 430 .EQUATE STATUS = $0234 440 .EQUATE TALK = $AD5C 450 .EQUATE TLKVECT = $01B2 460 .EQUATE TRACK = JOBNR*2+11 470 .EQUATE WRPORT = $4001 480 ; 1000 ; ******** PROGRAM 1581 ********** 1010 ; 1020 .BASE $0300 1030 .CODE * 1040 ; 1050 LDA #<(NTALK) ; Autostart-Einsprung 1060 STA TLKVECT ; setzt TALK-Vektor auf 1070 LDA #>(NTALK) ; neue Routine 1080 STA TLKVECT+1 1090 .EQUATE TLKLEN=$AE34-$AD6A; Länge TALK-Kopie 1100 LDX #TLKLEN 1110 COPYLP LDA $AD6A-1,X ; kopiert TALK-Routine 1120 STA COPY-1,X ; aus ROM ins RAM 1130 DEX 1140 BNE COPYLP 1150 LDA #<(BR1) ; korrigiert BRANCH-Befehl 1160 STA BR ; in TALK-Kopie 1170 LDA #%00001111 1180 JSR JALLOCBF ; belegt Puffer 0-3 1190 CLC ; verhindert erneute 1200 JSR JDEJAVU ; Initialisierung durch 'UI' 1210 LDA #%00011010 1220 STA SRCHCMD ; beschleunigt Kopfbewegung 1230 JSR GETDIR ; DIRECTORY-Spur einlesen 1240 JMP JBOOTRTN ; Rückkehr vom Autostart 1250 ; 1260 ; 2000 TRANSCMD LDY #%00000000 2010 STY WRPORT ; DATA & CLOCK low setzen 2020 CMP (POINTER,X) 2030 CMP (POINTER,X) ; = 6*NOP 2040 INY ; = 1 Kommandobyte 2050 LDX #%00000010 2060 STX WRPORT ; DATA high setzen 2070 CMP (POINTER,X) 2080 CMP (POINTER,X) ; = 6*NOP 2090 LDX #%00001010 2100 STX WRPORT ; DATA & CLOCK high setzen 2110 BNE TRANS1 ; = JMP 2120 ; 2130 TRANS NOP 2140 LDA #%00000000 2150 STA WRPORT ; DATA & CLOCK low setzen 2160 STX WRPORT ; CLOCK high: Synchronisation 2170 LDA (POINTER),Y ; nächstes Byte holen 2180 NOP 2190 TRANS1 CMP (POINTER,X) ; = 3*NOP 2200 STA ABSTMP ; höherwertiges Nibble retten 2210 AND #%00001111 ; niederwert. Nibble isolieren 2220 TAX 2230 LDA TAB,X ; Nibble konvertieren 2240 STA WRPORT ; Bit 0&1 senden 2250 ASL ; Bit 2&3 in Position 2260 AND #%00001010 ; ATN ACK löschen 2270 TAX 2280 LDA ABSTMP ; höherwertiges Nibble holen 2290 LSR 2300 STX WRPORT ; Bit 2&3 übertragen 2310 LSR 2320 LSR ; höherwertiges Nibble 2330 LSR ; in Position bringen 2340 TAX 2350 LDA TAB,X ; Nibble konvertieren 2360 STA WRPORT ; Bit 4&5 übertragen 2370 ASL ; Bit 6&7 in Position 2380 AND #%00001010 ; ATN ACK löschen 2390 LDX #%00001000 2400 NOP 2410 NOP 2420 DEY ; Anzahl Bytes erniedrigen 2430 STA WRPORT ; Bit 6&7 senden 2440 BNE TRANS ; schon alle Bytes gesendet? 2450 ; 2460 CMP (POINTER),Y ; = 2.5*NOP 2470 STY WRPORT ; CLOCK & DATA low setzen 2480 STX WRPORT ; CLOCK high setzen 2490 RTS RTS ; Rückkehr 2500 ; 2510 TAB .BYTE %00001111 ; Konvertierungs-Tabelle 2520 .BYTE %00000111 2530 .BYTE %00001101 2540 .BYTE %00000101 ; aus den Bits 3210 2550 .BYTE %00001011 ; ____ 2560 .BYTE %00000011 ; werden 0213 2570 .BYTE %00001001 2580 .BYTE %00000001 2590 .BYTE %00001110 2600 .BYTE %00000110 2610 .BYTE %00001100 2620 .BYTE %00000100 2630 .BYTE %00001010 2640 .BYTE %00000010 2650 .BYTE %00001000 2660 .BYTE %00000000 2670 ; 2680 ; 3000 NTALK SEI ; verhindert Interrupt 3010 BIT DRIVENR ; Doppelpunkt dem File- 3020 BPL JTALK ; Namen vorangestellt? 3030 LDA HOSTFLG ; im VC-20- oder 3040 AND #%00110000 ; C128-Modus? 3050 ORA SECADR ; Sekundäradresse <> 0? 3060 ORA DIRFLG ; wird DIRECTORY geladen? 3070 BNE JTALK ; ja, originale TALK-Routine 3080 JSR CHNOPN ; Kanal zum Lesen öffnen 3090 BCS RTS ; Kanal aktiv? 3100 LDA STATUS,X ; READ-Flag gesetzt? 3110 BPL RTS ; nein, WRITE 3120 LDA DATA,X ; 1. Byte als Startadresse 3130 STA STRTADL ; LSB speichern 3140 JSR GETBYTE ; nächstes Datum holen 3150 CMP #>($0400) ; Autostart-Programm? 3160 BCS NOAUTO ; nein, dann Schnelladen 3170 DEC CHNTAB,X ; ja, Zeiger zurücksetzen 3180 LDX CHANNEL ; Kanal-Nummer 3190 LDA STRTADL ; 1. Byte wieder 3200 STA DATA,X ; herstellen und 3210 JTALK JMP TALK ; normal laden 3220 ; 3230 NOAUTO STA STRTADH ; gibt Startadresse MSB 3240 LDX CHANNEL ; Kanal-Nummer 3250 LDY #<($100+C64-PGEND); Zeiger auf C64-PRG 3260 LOOP LDA PGEND-$100,Y ; Byte holen 3270 STA DATA,X ; und bereitstellen 3280 ; 3290 COPY .DS TLKLEN ; Lücke für TALK-Kopie 3300 ; 3310 INY ; Zeiger erhöhen 3320 BEQ SPDTRANS ; letztes Byte übertragen? 3330 JMP LOOP ; nein, nächstes übertragen 3340 ; 3350 DATAH JMP JJIDLE ; BUS nicht aktiv 3360 .EQUATE BR=$ADF1-$AD6A+COPY 3370 .EQUATE BR1=DATAH-BR-1 3380 ; 3390 SPDTRANS BIT WRPORT ; DATA low? 3400 BEQ HNDSHK ; ja 3410 DEY ; nein, Y-Register erniedrigen 3420 BNE SPDTRANS ; Zeit abgelaufen? 3430 ; 3440 LDA #EOI ; ja, EOI senden, da 3450 STA STATUS,X ; relativ geladen wurde 3460 JMP TALK ; LOAD beenden 3470 ; 3480 HNDSHK STA WRPORT ; CLOCK & DATA low setzen 3490 LDA #%00000100 3500 ; 3510 SHKLP BIT WRPORT ; wartet, bis CLOCK low 3520 BNE SHKLP 3530 ; 3540 ASL ; A = %00001000 3550 STA WRPORT ; CLOCK high setzen 3560 ; 3570 JSR GETBUFFP ; holt Pufferadresse 3580 LDY #$00 ; des 1. Sektors 3590 STY POINTER ; Zeiger auf 1. Byte setzen 3600 LDA (POINTER),Y ; Spur 3610 BNE NOLAST ; letzter Sektor? 3620 INY ; ja 3630 LDA (POINTER),Y ; Anzahl Bytes des Sektors 3640 SEC 3650 SBC #$02 ; -2 Bytes Startadresse 3660 .BYTE $2C ; LDA überlesen 3670 NOLAST LDA #BYTESECT-2 ; Anzahl Bytes 1. Sektor 3680 LDX #$03 ; Zeiger auf 4. Byte 3690 STX POINTER 3700 BNE FIRST ; = JMP 3710 ; 3720 MAINLOOP INY ; Zeiger auf Sektor 3730 CMP TRACK ; gleiche Spur? 3740 STA TRACK 3750 BNE NEWTRACK ; nein, neue Spur einlesen 3760 LDA (POINTER),Y ; Sektor 3770 CMP #20 3780 ROL ; auf gleicher Seite 3790 EOR SIDE ; des Zylinders? 3800 LSR 3810 BCC SIDEOK ; ja, Sektor übertragen 3820 NEWTRACK LDA (POINTER),Y 3830 STA SECTOR ; Sektor retten 3840 LDA #READ ; Jobcode für 'Sektor lesen' 3850 STA JOB ; übergeben 3860 CLI ; Kopf auf Spur 3870 BRK ; Spur einlesen 3880 NOP ; Korrektur wegen BRK 3890 JOBWT LDA JOB ; wartet, bis 3900 BMI JOBWT ; Job ausgeführt 3910 SEI ; verhindert Interrupt 3920 CMP #$02 ; Fehler? 3930 LDA #ERROR ; Kommando-Byte für Fehler 3940 BCS END ; Fehler aufgetreten 3950 LDA SECTOR ; Sektor 3960 .BYTE $2C ; LDA überlesen 3970 SIDEOK LDA (POINTER),Y ; Sektor 3980 CMP #20 ; grösser als 19? 3990 BCS SUBTR ; ja, Subtraktion 4000 ADC #20+1 ; nein, Addition 4010 SUBTR SBC #20->(CACHE) ; berechnet Zeiger auf Cache 4020 STA POINTER+1 ; MSB Zeiger 4030 DEY ; Y = 0 4040 LDA (POINTER),Y ; Spur 4050 BNE NOLAST1 ; letzter Sektor? 4060 INY ; ja 4070 LDA (POINTER),Y ; Anzahl Bytes 4080 .BYTE $2C ; LDA überlesen 4090 NOLAST1 LDA #BYTESECT ; Bytes pro Sektor normal 4100 INC POINTER ; Zeiger auf 2. Byte 4110 FIRST STA QUANTITY ; Anzahl Bytes sichern 4120 JSR TRANSCMD ; und senden 4130 LDY QUANTITY ; Anzahl 4140 DEY ; -1 als Zähler 4150 NOP 4160 JSR TRANS ; Bytes übertragen 4170 STY POINTER ; Zeiger auf Spur 4180 LDA (POINTER),Y ; letzter Sektor übertragen? 4190 BNE MAINLOOP ; nein, nächste Übertragung 4200 ; 4210 END JSR DELAY ; wartet 39 Microsec. 4220 JSR TRANSCMD ; übermittelt Kommando 4230 LDA JOB ; (0=Ende, 1=Fehler) 4240 BEQ OKMSSG ; Fehler aufgetreten? 4250 LDX #JOBNR ; Fehlermeldung bereitstellen 4260 JSR JERROR ; = JMP 4270 ; 4280 OKMSSG JSR OKMESS ; OK-Meldung bereitstellen 4290 JMP GETDIR ; DIRECTORY-Spur einlesen 4300 ; 4310 ; 5000 ; ******** LABELS C64 ************ 5010 ; 5020 .EQUATE BASICEND = $ 2D 5030 .EQUATE BSICVECT = $E453 5040 .EQUATE CHROUT = $F1B4 5050 .EQUATE CLR = $A660 5060 .EQUATE CLRCHN = $F349 5070 .EQUATE EXEC = $A7AE 5080 .EQUATE ILLEGQNT = $B248 5090 .EQUATE IRQ = $EA7E 5100 .EQUATE LDEND = $F5AA 5110 .EQUATE LINK = $A533 5120 .EQUATE LOADERR = 29 5130 .EQUATE NMI = $FE66 5140 .EQUATE OPSVECT = $FD15 5150 .EQUATE POINT = $ AE 5160 .EQUATE QUANT = $ B9 5170 .EQUATE RDPORT = $DD00 5180 .EQUATE READY = $A474 5190 .EQUATE RELAD = $ C3 5200 .EQUATE RUN = $A659 5210 .EQUATE SCREEN = $D011 5220 .EQUATE SECAD = $ B8 5230 .EQUATE SYS = $E130 5240 .EQUATE SYSJMP = $ 14 5250 .EQUATE TMP = QUANT 5260 ; 6000 ; ******** PROGRAM C64 *********** 6010 ; 6020 C64 .WORD $0300 6030 ; 6040 CODE .BASE $0300 6050 .CODE CODE 6060 .EQUATE DIFF=CODE-* 6070 ; 6080 .BYTE $00 ; verhindert 'Aufhängen' 6090 .BYTE $00 ; beim Binden der Zeilen 6100 ; 6110 START LDA POINT ; Ende des 6120 CMP #<(PRGEND) ; Programms erreicht? 6130 BNE CONTLD ; nein, weiter laden 6140 SEI ; IRQ aus 6150 PLA ; LSB Rücksprungadresse 6160 BCS JMP ; = JMP 6170 ; 6180 .BYTE $00 ; AKKU SYS-Befehl 6190 .BYTE $00 ; X-Register 6200 .BYTE $00 ; Y-Register 6210 .BYTE $00 ; STATUS-Register 6220 ; 6230 JMP ILLEGQNT ; USR-Vektor 6240 ; 6250 .BYTE $00 6260 .WORD IRQ ; IRQ-Tastaturabfrage aus 6270 ; 6280 JMP PLA ; MSB Rücksprungadresse 6290 BIT NMI1 ; NMI-Vektor auf NMI1 6300 BCS JMP1 ; = JMP 6310 ; 6320 NMI1 JSR BSICVECT ; BASIC-Vektoren setzen 6330 JMP NMI ; normaler NMI 6340 ; 6350 .WORD CLRCHN ; CLRCHN-Vektor auf RTS setzen 6360 ; 6370 CONTLD RTS 6380 ; 6390 AT .DS 1 ; Füllbyte 6400 ; 6410 .WORD CHROUT ; CHROUT-Vektor auf RTS setzen 6420 .WORD START ; STOP-Vektor auf Autostart 6430 ; 6440 ; 6450 JMP1 LDA SCREEN ; VIC-Steuerregister 1 retten 6460 PHA 6470 LDA RDPORT ; Bit 14&15 vom VIC retten 6480 PHA 6490 LDA #%00010011 6500 STA RDPORT ; CLOCK high, DATA low setzen 6510 LDA #%00000000 6520 STA SCREEN ; Bild aus 6530 SCR BIT SCREEN ; wartet, bis Rasterstrahl im 6540 BPL SCR ; unteren Bildrahmenbereich 6550 STA RDPORT ; CLOCK low setzen 6560 ; 6570 LDX RELAD ; BASIC-Start LSB 6580 LDY RELAD+1 ; BASIC-Start MSB 6590 LDA SECAD ; Sekundäradresse 6600 AND #%00001001 ; 1,3,5,7-9 = absolut laden 6610 BEQ REL ; 2,4,6 = relativ laden 6620 STRTADRL LDX #$00 ; absolute Ladeadresse LSB 6630 STRTADRH LDY #$00 ; absolute Ladeadresse MSB 6640 STX SYSJMP ; SYS-Adresse für 6650 STY SYSJMP+1 ; Autostart setzen 6660 REL STX POINT ; Zeiger setzen 6670 STY POINT+1 6680 ; 6690 BLOCK LDY #$01 ; 1 Kommandobyte 6700 WAIT BIT RDPORT 6710 BVC WAIT ; wartet, bis CLOCK low 6720 BIT RDPORT 6730 BPL SYNC 6740 INC TMP ; synchronisiert C64 6750 SYNC BIT RDPORT ; mit Floppy 1581 6760 BVC SYNC1 6770 BIT TMP 6780 SYNC1 JSR GET ; holt Kommandobyte 6790 TAY ; = 0? 6800 BEQ ENDLD ; ja, Ende 6810 DEY ; = 1? 6820 BEQ ENDLD ; ja, Ladefehler 6830 STY QUANT ; nein, Anzahl Bytes 6840 JSR GET ; Bytes laden 6850 STA (POINT),Y ; letztes Byte auch speichern 6860 LDA POINT 6870 ADC QUANT ; Anzahl Bytes zu 6880 STA POINT ; Zeiger addieren 6890 BCC BLOCK ; kein Übertrag 6900 INC POINT+1 ; MSB erhöhen 6910 BCS BLOCK ; = JMP 6920 ; 6930 ENDLD PHA ; Bit 0 retten 6940 JSR OPSVECT ; setzt Betriebssystem- & 6950 JSR BSICVECT ; BASIC-Vektoren 6960 PLA ; setzt bei 6970 LSR ; Fehler Carry 6980 PLA ; stellt Bit l4&15 vom 6990 STA RDPORT ; VIC wieder her 7000 PLA 7010 STA SCREEN ; schaltet Bild ein 7020 CLI ; Interrupt ermöglichen 7030 BCS LDERR ; bei Fehler Lade-Ende 7040 LDX SECAD ; Sekundäradresse 7050 INX 7060 TXA ; 3-6 = Autostart 7070 AND #%00000100 7080 BEQ LDEND1 ; kein Autostart 7090 TXA 7100 LSR 7110 BCS BSCRUN 7120 JSR CLR ; 1,3 = SYS-Aufruf 7130 LDA #>(READY-1) ; Rücksprungadresse MSB 7140 PHA ; auf Stapel 7150 LDA #<(READY-1) ; Rücksprungadresse LSB 7160 PHA ; auf Stapel 7170 JMP SYS ; Maschinen-PRG ausführen 7180 ; 7190 BSCRUN JSR LDEND ; 2,4 = RUN-Befehl 7200 STX BASICEND ; BASIC-Ende setzen 7210 STY BASICEND+1 7220 JSR RUN ; CHRGET auf Programmstart 7230 JSR LINK ; Zeilen binden 7240 JMP EXEC ; BASIC-PRG ausführen 7250 ; 7260 LDERR LDA #LOADERR ; Nummer '?LOAD ERROR' 7270 LDEND1 JMP LDEND ; Ende Laderoutine 7280 ; 7290 ; 7300 GETLP STA (POINT),Y ; legt Byte im Speicher ab 7310 GET LDA RDPORT ; lädt Bit 0&1 7320 LSR ; schiebt Byte 7330 LSR ; 2 Stellen nach rechts 7340 ORA RDPORT ; fügt Bit 2&3 hinzu 7350 LSR ; schiebt Byte 7360 LSR ; 2 Stellen nach rechts 7370 ORA RDPORT ; fügt Bit 4&5 hinzu 7380 LSR ; schiebt Byte 7390 LSR ; 2 Stellen nach rechts 7400 ORA RDPORT ; fügt Bit 6&7 hinzu 7410 BIT RDPORT ; Synchronisation mit 1581 7420 BVS SYNC2 ; (2 oder 3 Taktzyklen) 7430 SYNC2 DEY ; erniedrigt Anzahl Bytes 7440 BNE GETLP ; letztes Byte empfangen? 7450 RTS ; ja, Rückkehr 7460 ; 7470 PRGEND .EQUATE PGEND=PRGEND+DIFF 7480 ; 8000 ; ******************************** 8010 ; 8020 .TEXT "* MG '88 * 8030 ; 8040 .EQUATE ABSTMP=AT+DIFF 8050 .EQUATE STRTADL=STRTADRL+1+DIFF 8060 .EQUATE STRTADH=STRTADRH+1+DIFF 8070 ; 9000 ; (C) M. Gyger 13.11.'88