Main file : speed1581.s Current file: speed1581.s 0000r ; Speed-Loader für 1581 & C64 0000r ; 0000r ; ******** Labels 1581 *********** 0000r 0000r buffer := $0300 0000r bytesect = $ff 0000r c64off = utilend-c64+2 0000r cache := $0c00 0000r channel := $50 0000r chnopn := $9027 0000r chntab := $bb 0000r data := $023b 0000r delay := $ad30 0000r dirflg := $026e 0000r drivenr := $ef 0000r eoi = $80 0000r error = $01 0000r getbuffp := $9442 0000r getbyte := $909b 0000r getdir := $8f03 0000r hostflg := $76 0000r jallocbf := $ff66 0000r jbootrtn := $ff5a 0000r jdejavu := $ff60 0000r jerror := $ff2d 0000r jjidle := $aed9 0000r jobnr = $06 0000r job := jobnr+2 0000r okmess := $a862 0000r pointer := $64 0000r quantity := $54 0000r read = $80 0000r secadr := $52 0000r sector := jobnr*2+12 0000r side := $96 0000r srchcmd := $01db 0000r status := $0234 0000r talk := $ad5c 0000r temp := $45 0000r tlkcode := $ad6a 0000r tlkbroff = $adf0-tlkcode 0000r tlklen = $ae34-tlkcode 0000r tlkvect := $01b2 0000r track := jobnr*2+11 0000r wrport := $4001 0000r 0000r 0000r ; ******** Programm 1581 ********* 0000r 0000r .segment "utldr0" 0000r 00 03 .addr :+ ; UTLDR Ladeadresse 0002r de .byte copy-:+ ; Anzahl Bytes 0003r .org buffer 0300 : 0300 0300 a9 9d lda #<ntalk ; Autostart-Einsprung 0302 8d b2 01 sta tlkvect ; setzt TALK-Vektor auf 0305 a9 03 lda #>ntalk ; neue Routine 0307 8d b3 01 sta tlkvect+1 030a 030a a2 ca ldx #tlklen 030c bd 69 ad copylp: lda tlkcode-1,x ; kopiert TALK-Routine 030f 9d dd 03 sta copy-1,x ; aus ROM ins RAM 0312 ca dex 0313 d0 f7 bne copylp 0315 a9 48 lda #datah-(copy+tlkbroff+2) ; korrigiert 0317 8d 65 04 sta copy+tlkbroff+1 ; Branch in TALK-Kopie 031a a9 0f lda #%00001111 ; reserviert Puffer 0-3 für 031c 20 66 ff jsr jallocbf ; diesen Code ($0300-$06ff) 031f 18 clc ; verhindert erneute 0320 20 60 ff jsr jdejavu ; Initialisierung durch 'UI' 0323 a9 1a lda #%00011010 0325 8d db 01 sta srchcmd ; beschleunigt Kopfbewegung 0328 20 03 8f jsr getdir ; Directory-Spur einlesen 032b 4c 5a ff jmp jbootrtn ; Rückkehr vom Autostart 032e 032e 032e ; die durschnittlichen 46.2 µs pro empfangenem Byte mit der 032e ; C64 PAL-Version entsprechen etwa 92 Zyklen auf der 1581 mit 032e ; 2 MHz Takt (für NTSC müsste auf 89 Zyklen reduziert werden) 032e 032e a0 00 transcmd: ldy #%00000000 0330 8c 01 40 sty wrport ;| 4 | DATA & CLOCK low setzen 0333 c1 64 cmp (pointer,x) ;| 6 | = nop 0335 c1 64 cmp (pointer,x) ;| 6 | = nop 0337 c8 iny ;| 2 | = 1 Kommandobyte 0338 a2 02 ldx #%00000010 ;| 2 | 033a 8e 01 40 stx wrport ;| 4 | DATA high setzen 033d c1 64 cmp (pointer,x) ;| 6 | = nop 033f c1 64 cmp (pointer,x) ;| 6 | = nop 0341 a2 0a ldx #%00001010 ;| 2 | 0343 8e 01 40 stx wrport ;| 4 | DATA & CLOCK high setzen 0346 d0 0c bne trans1 ;| 3 | = jmp 0348 0348 ea trans: nop ;| 2 | 0349 a9 00 lda #%00000000 ;| 2 | 034b 8d 01 40 sta wrport ;| 4 | DATA & CLOCK low setzen 034e 8e 01 40 stx wrport ;| 4 | CLOCK high: Synchronisation 0351 b1 64 lda (pointer),y ;| 5 | nächstes Byte holen 0353 ea nop ;| 2 | 0354 c1 64 trans1: cmp (pointer,x) ;| 6 | = nop 0356 8d 45 00 sta a:temp ;| 4 | höherwertiges Nibble retten 0359 29 0f and #%00001111 ;| 2 | niederwert. Nibble isolieren 035b aa tax ;| 2 | 035c bd 8d 03 lda tab,x ;| 4 | Nibble konvertieren 035f 8d 01 40 sta wrport ;| 4 | Bit 0&1 senden 0362 0a asl ;| 2 | Bit 2&3 in Position 0363 29 0a and #%00001010 ;| 2 | ATN ACK löschen 0365 aa tax ;| 2 | 0366 ad 45 00 lda a:temp ;| 4 | höherwertiges Nibble holen 0369 4a lsr ;| 2 | 036a 8e 01 40 stx wrport ;| 4 | Bit 2&3 übertragen 036d 4a lsr ;| 2 | 036e 4a lsr ;| 2 | höherwertiges Nibble 036f 4a lsr ;| 2 | in Position bringen 0370 aa tax ;| 2 | 0371 bd 8d 03 lda tab,x ;| 4 | Nibble konvertieren 0374 8d 01 40 sta wrport ;| 4 | Bit 4&5 übertragen 0377 0a asl ;| 2 | Bit 6&7 in Position 0378 29 0a and #%00001010 ;| 2 | ATN ACK löschen 037a a2 08 ldx #%00001000 ;| 2 | 037c ea nop ;| 2 | 037d ea nop ;| 2 | 037e 88 dey ;| 2 | Anzahl Bytes erniedrigen 037f 8d 01 40 sta wrport ;| 4 | Bit 6&7 senden 0382 d0 c4 bne trans ;|2/3| schon alle Bytes gesendet? 0384 0384 d1 64 cmp (pointer),y ;| 5 | = nop 0386 8c 01 40 sty wrport ;| 4 | CLOCK & DATA low setzen 0389 8e 01 40 stx wrport ;| 4 | CLOCK high setzen 038c 60 return: rts ;| 6 | Rückkehr 038d .assert >transcmd = >*, error 038d 038d 0f 07 0d 05 tab: .repeat $10, i ; Konvertierungs-Tabelle 0391 0b 03 09 01 0395 0e 06 0c 04 0399 0a 02 08 00 039d .byte ~(i<<3 | i&%0110 | i>>3) & %1111 ; ____ 039d .endrep ; aus Bits 3210 werden 0213 039d .assert >tab = >*, error 039d 039d 78 ntalk: sei ; verhindert Interrupt 039e 24 ef bit drivenr ; Doppelpunkt dem File- 03a0 10 2c bpl jtalk ; Namen vorangestellt? 03a2 a5 76 lda hostflg ; im VC-20- oder 03a4 29 30 and #%00110000 ; C128-Modus? 03a6 05 52 ora secadr ; Sekundäradresse <> 0? 03a8 0d 6e 02 ora dirflg ; wird Directory geladen? 03ab d0 21 bne jtalk ; ja, originale TALK-Routine 03ad 20 27 90 jsr chnopn ; Kanal zum Lesen öffnen 03b0 b0 da bcs return ; Kanal aktiv? 03b2 bd 34 02 lda status,x ; READ-Flag gesetzt? 03b5 10 d5 bpl return ; nein, WRITE 03b7 bd 3b 02 lda data,x ; 1. Byte als Startadresse 03ba 8d a7 05 sta ldstrtl+1+c64off ; LSB speichern 03bd 20 9b 90 jsr getbyte ; nächstes Datum holen 03c0 c9 04 cmp #>$0400 ; Autostart-Programm? 03c2 b0 0d bcs noauto ; nein, dann Schnell-Laden 03c4 d6 bb dec chntab,x ; ja, Zeiger zurücksetzen 03c6 a6 50 ldx channel ; Kanal-Nummer 03c8 ad a7 05 lda ldstrtl+1+c64off ; 1. Byte wieder 03cb 9d 3b 02 sta data,x ; herstellen und 03ce 4c 5c ad jtalk: jmp talk ; normal laden 03d1 03d1 8d a9 05 noauto: sta ldstrth+1+c64off ; Startadresse MSB 03d4 a6 50 ldx channel ; Kanal-Nummer 03d6 a0 12 ldy #$100-(2+c64end-c64) ; Zeiger auf C64-PRG 03d8 b9 41 05 loop: lda c64end+c64off-$100,y ; Byte holen 03db 9d 3b 02 sta data,x ; und bereitstellen 03de copy: ; TALK-Code aus ROM 03de 03de .segment "utldr1" 03de a8 04 .addr :+ ; UTLDR Chunk Ladeadresse 03e0 ab .byte utilend-:+ ; Anzahl Bytes 03e1 .org copy+tlklen ; Lücke für TALK-Kopie 04a8 : 04a8 04a8 c8 iny ; Zeiger erhöhen 04a9 f0 06 beq spdtrans ; letztes Byte übertragen? 04ab 4c d8 03 jmp loop ; nein, nächstes übertragen 04ae 04ae 4c d9 ae datah: jmp jjidle ; BUS nicht aktiv 04b1 04b1 2c 01 40 spdtrans: bit wrport ; DATA low? 04b4 f0 0b beq hndshk ; ja 04b6 88 dey ; nein, Y-Register erniedrigen 04b7 d0 f8 bne spdtrans ; Zeit abgelaufen? 04b9 04b9 a9 80 lda #eoi ; ja, EOI senden, da 04bb 9d 34 02 sta status,x ; relativ geladen wurde 04be 4c 5c ad jmp talk ; LOAD beenden 04c1 04c1 8d 01 40 hndshk: sta wrport ; CLOCK & DATA low setzen 04c4 a9 04 lda #%00000100 04c6 04c6 2c 01 40 shklp: bit wrport ; wartet, bis CLOCK low 04c9 d0 fb bne shklp 04cb 04cb 0a asl ; A = %00001000 04cc 8d 01 40 sta wrport ; CLOCK high setzen 04cf 04cf 20 42 94 jsr getbuffp ; holt Pufferadresse 04d2 a0 00 ldy #$00 ; des 1. Sektors 04d4 84 64 sty pointer ; Zeiger auf 1. Byte setzen 04d6 b1 64 lda (pointer),y ; Spur 04d8 d0 07 bne notlast ; letzter Sektor? 04da c8 iny ; ja 04db b1 64 lda (pointer),y ; Anzahl Bytes des Sektors 04dd 38 sec 04de e9 02 sbc #$02 ; -2 Bytes Startadresse 04e0 2c .byte $2c ; lda überlesen 04e1 a9 fd notlast: lda #bytesect-2 ; Anzahl Bytes 1. Sektor 04e3 a2 03 : ldx #$03 ; Zeiger auf 4. Byte 04e5 86 64 stx pointer 04e7 d0 43 bne first ; = jmp 04e9 04e9 c8 mainloop: iny ; Zeiger auf Sektor 04ea c5 17 cmp track ; gleiche Spur? 04ec 85 17 sta track 04ee d0 0a bne newtrack ; nein, neue Spur einlesen 04f0 b1 64 lda (pointer),y ; Sektor 04f2 c9 14 cmp #20 04f4 2a rol ; auf gleicher Seite 04f5 45 96 eor side ; des Zylinders? 04f7 4a lsr 04f8 90 19 bcc sideok ; ja, Sektor übertragen 04fa b1 64 newtrack: lda (pointer),y 04fc 85 18 sta sector ; Sektor retten 04fe a9 80 lda #read ; Jobcode für 'Sektor lesen' 0500 85 08 sta job ; übergeben 0502 58 cli ; Kopf auf Spur 0503 00 brk ; Spur einlesen 0504 ea nop ; Korrektur wegen brk 0505 a5 08 jobwt: lda job ; wartet, bis 0507 30 fc bmi jobwt ; Job ausgeführt 0509 78 sei ; verhindert Interrupt 050a c9 02 cmp #$02 ; Fehler? 050c a9 01 lda #error ; Kommando-Byte für Fehler 050e b0 2e bcs end ; Fehler aufgetreten 0510 a5 18 lda sector ; Sektor 0512 2c .byte $2c ; lda überlesen 0513 b1 64 sideok: lda (pointer),y ; Sektor 0515 c9 14 : cmp #20 ; grösser als 19? 0517 b0 02 bcs subtr ; ja, Subtraktion 0519 69 15 adc #20+1 ; nein, Addition 051b e9 08 subtr: sbc #20->cache ; berechnet Zeiger auf Cache 051d 85 65 sta pointer+1 ; MSB Zeiger 051f 88 dey ; Y = 0 0520 b1 64 lda (pointer),y ; Spur 0522 d0 04 bne notlast1 ; letzter Sektor? 0524 c8 iny ; ja 0525 b1 64 lda (pointer),y ; Anzahl Bytes 0527 2c .byte $2c ; lda überlesen 0528 a9 ff notlast1: lda #bytesect ; Bytes pro Sektor normal 052a e6 64 : inc pointer ; Zeiger auf 2. Byte 052c 85 54 first: sta quantity ; Anzahl Bytes sichern 052e 20 2e 03 jsr transcmd ; und senden 0531 a4 54 ldy quantity ;| 3 | Anzahl 0533 88 dey ;| 2 | -1 als Zähler 0534 ea nop ;| 2 | 0535 20 48 03 jsr trans ;| 6 | Bytes übertragen 0538 84 64 sty pointer ; Zeiger auf Spur 053a b1 64 lda (pointer),y ; letzter Sektor übertragen? 053c d0 ab bne mainloop ; nein, nächste Übertragung 053e 053e 20 30 ad end: jsr delay ; wartet 39 µs 0541 20 2e 03 jsr transcmd ; übermittelt Kommando 0544 a5 08 lda job ; (0 = Ende, 1 = Fehler) 0546 f0 05 beq okmssg ; Fehler aufgetreten? 0548 a2 06 ldx #jobnr ; Fehlermeldung bereitstellen 054a 20 2d ff jsr jerror ; = jmp 054d 054d 20 62 a8 okmssg: jsr okmess ; OK-Meldung bereitstellen 0550 4c 03 8f jmp getdir ; Directory-Spur einlesen 0553 0553 utilend: .assert * <= $0700, error ; in Puffer 0-3 0553 0553 0553 ; ******** Labels C64 ************ 0553 0553 basicend := $2d 0553 bsicvect := $e453 0553 c64 := $0300 0553 chroutign := $f1b4 0553 clr := $a660 0553 clrchnign := $f349 0553 exec := $a7ae 0553 illegqnt := $b248 0553 irq := $ea31 0553 irqign := $ea7e 0553 jioerror8 := $f602 0553 ldend := $f5aa 0553 link := $a533 0553 loaderr = 29 0553 opsvect := $fd15 0553 point := $ae 0553 quant := $b9 0553 rdport := $dd00 0553 ready := $a474 0553 relad := $c3 0553 run := $a659 0553 screen := $d011 0553 secad := $b8 0553 stop := $f6ed 0553 sys := $e130 0553 sysjmp := $14 0553 tmp := quant 0553 warmstart := $fe66 0553 0553 ; ******** Programm C64 ********** 0553 0553 .segment "utldr2" 0553 53 05 .addr utilend ; UTLDR Ladeadresse Floppy 0555 ee .byte 2+c64end-:+ ; Anzahl Bytes 0556 0556 00 03 .addr :+ ; PRG Ladeadresse C64 0558 .org c64 0300 : 0300 0300 00 00 .addr $0000 ; Endkennzeichen falls relativ geladen 0302 0302 ; Programmstart über den STOP-Vektor, der nach jedem gespeicherten 0302 ; Byte angesprungen wird. Da zuerst nur das LSB überschrieben wird 0302 ; muss das auch eine gültige Adresse sein. Verbiegen der CLRCHN- & 0302 ; CHROUT-Vektoren macht den Code dort harmlos ausser Löschen von Z. 0302 0302 a5 ae stopnew: lda point ; Ende des Ladeprogramms erreicht? 0304 c9 ec cmp #<c64end 0306 f0 22 beq start ; ja, Schnell-Laden starten 0308 60 rts ; nein, weiter laden, mit Z gelöscht 0309 0309 20 53 e4 warmnew: jsr bsicvect ; BASIC-Vektoren setzen 030c 4c 66 fe jmp warmstart ; Warmstart 030f 030f .res $030f-* 030f 00 .byte %00000000 ; Status-Register von SYS-Befehl 0310 4c 48 b2 jmp illegqnt ; USR() Code 0313 xx .res $0314-* 0314 7e ea .addr irqign ; IRQ-Vektor: Tastaturabfrage aus 0316 .assert >irqign = >irq, error 0316 09 03 .addr warmnew ; BRK-Vektor: Warmstart 0318 09 03 .addr warmnew ; NMI-Vektor: Warmstart 031a xx xx xx xx .res $0322-* 031e xx xx xx xx 0322 49 f3 .addr clrchnign ; CLRCHN-Vektor: auf rts 0324 xx xx .res $0326-* 0326 b4 f1 .addr chroutign ; CHROUT-Vektor: auf rts 0328 02 03 .addr stopnew ; STOP-Vektor: abfangen 032a .assert >jioerror8 = >stop && <stopnew = <jioerror8, error 032a .assert c64end-* < $100, error 032a 032a 032a 78 start: sei ; IRQ aus 032b 68 pla ; LSB Rücksprungadresse 032c 68 pla ; MSB Rücksprungadresse 032d ad 11 d0 lda screen ; VIC-Steuerregister 1 retten 0330 48 pha 0331 ad 00 dd lda rdport ; Bit 14&15 vom VIC retten 0334 48 pha 0335 a9 13 lda #%00010011 0337 8d 00 dd sta rdport ; CLOCK high, DATA low setzen 033a a9 00 lda #%00000000 033c 8d 11 d0 sta screen ; Bild aus 033f 2c 11 d0 scr: bit screen ; wartet, bis Rasterstrahl im 0342 10 fb bpl scr ; unteren Bildrahmenbereich 0344 8d 00 dd sta rdport ; CLOCK low setzen 0347 0347 a6 c3 ldx relad ; BASIC-Start LSB 0349 a4 c4 ldy relad+1 ; BASIC-Start MSB 034b a5 b8 lda secad ; Sekundäradresse 034d 29 09 and #%00001001 ; 1,3,5,7-9 = absolut laden 034f f0 08 beq rel ; 2,4,6 = relativ laden 0351 a2 00 ldstrtl: ldx #$00 ; Ladeadresse LSB (wird modifiziert) 0353 a0 00 ldstrth: ldy #$00 ; Ladeadresse MSB (wird modifiziert) 0355 86 14 stx sysjmp ; SYS-Adresse für 0357 84 15 sty sysjmp+1 ; Autostart setzen 0359 86 ae rel: stx point ; Zeiger setzen 035b 84 af sty point+1 035d 035d a0 01 block: ldy #$01 ; 1 Kommandobyte 035f 2c 00 dd wait: bit rdport ;| 4 | 0362 50 fb bvc wait ;|2/3| wartet, bis CLOCK low 0364 2c 00 dd bit rdport ;| 4 | synchronisiert C64 0367 10 02 bpl sync ;|2/3| mit Floppy 1581 0369 e6 b9 inc z:tmp ;| 5 | = nop 036b 2c 00 dd sync: bit rdport ;| 4 | 036e 50 02 bvc sync1 ;|2/3| 0370 24 b9 bit z:tmp ;| 3 | = nop 0372 20 d1 03 sync1: jsr get ;| 6 | holt Kommandobyte 0375 a8 tay ;| 2 | = 0? 0376 f0 16 beq endld ;| 2 | ja, Ende 0378 88 dey ;| 2 | = 1? 0379 f0 13 beq endld ;| 2 | ja, Ladefehler 037b 84 b9 sty quant ;| 3 | nein, Anzahl Bytes 037d 20 d1 03 jsr get ;| 6 | Bytes laden 0380 91 ae sta (point),y ; letztes Byte auch speichern 0382 a5 ae lda point 0384 65 b9 adc quant ; Anzahl Bytes zu 0386 85 ae sta point ; Zeiger addieren 0388 90 d3 bcc block ; kein Übertrag 038a e6 af inc point+1 ; MSB erhöhen 038c b0 cf bcs block ; = jmp 038e .assert >wait = >sync1, error 038e 038e 48 endld: pha ; Bit 0 retten 038f 20 15 fd jsr opsvect ; setzt Betriebssystem- & 0392 20 53 e4 jsr bsicvect ; BASIC-Vektoren 0395 68 pla ; setzt bei 0396 4a lsr ; Fehler Carry 0397 68 pla ; stellt Bit l4&15 vom 0398 8d 00 dd sta rdport ; VIC wieder her 039b 68 pla 039c 8d 11 d0 sta screen ; schaltet Bild ein 039f 58 cli ; Interrupt ermöglichen 03a0 b0 28 bcs lderr ; bei Fehler Lade-Ende 03a2 a6 b8 ldx secad ; Sekundäradresse 03a4 e8 inx 03a5 8a txa ; 3-6 = Autostart 03a6 29 04 and #%00000100 03a8 f0 22 beq ldend1 ; kein Autostart 03aa 8a txa 03ab 4a lsr 03ac b0 0c bcs bscrun 03ae 20 60 a6 jsr clr ; 1,3 = SYS-Aufruf 03b1 a9 a4 lda #>(ready-1) ; Rücksprungadresse MSB 03b3 48 pha ; auf Stapel 03b4 a9 73 lda #<(ready-1) ; Rücksprungadresse LSB 03b6 48 pha ; auf Stapel 03b7 4c 30 e1 jmp sys ; Maschinen-PRG ausführen 03ba 03ba 20 aa f5 bscrun: jsr ldend ; 2,4 = RUN-Befehl 03bd 86 2d stx basicend ; BASIC-Ende setzen 03bf 84 2e sty basicend+1 03c1 20 59 a6 jsr run ; CHRGET auf Programmstart 03c4 20 33 a5 jsr link ; Zeilen binden 03c7 4c ae a7 jmp exec ; BASIC-PRG ausführen 03ca 03ca a9 1d lderr: lda #loaderr ; Nummer '?LOAD ERROR' 03cc 4c aa f5 ldend1: jmp ldend ; Ende Laderoutine 03cf 03cf 03cf ; pro empfangenem Byte werden 45 oder 46 Zyklen benötigt, 03cf ; das sind im Durchschnitt 46.2 µs für die C64 PAL-Version 03cf ; mit 985.2486 kHz Takt (NTSC: 44.5 µs bei 1.0227271 MHz) 03cf 03cf 91 ae getlp: sta (point),y ;| 6 | legt Byte im Speicher ab 03d1 ad 00 dd get: lda rdport ;| 4 | lädt Bit 0&1 03d4 4a lsr ;| 2 | schiebt Byte 03d5 4a lsr ;| 2 | 2 Stellen nach rechts 03d6 0d 00 dd ora rdport ;| 4 | fügt Bit 2&3 hinzu 03d9 4a lsr ;| 2 | schiebt Byte 03da 4a lsr ;| 2 | 2 Stellen nach rechts 03db 0d 00 dd ora rdport ;| 4 | fügt Bit 4&5 hinzu 03de 4a lsr ;| 2 | schiebt Byte 03df 4a lsr ;| 2 | 2 Stellen nach rechts 03e0 0d 00 dd ora rdport ;| 4 | fügt Bit 6&7 hinzu 03e3 2c 00 dd bit rdport ;| 4 | Synchronisation mit 1581 03e6 70 00 bvs sync2 ;|2/3| +1 Zyklus falls zu schnell 03e8 88 sync2: dey ;| 2 | erniedrigt Anzahl Bytes 03e9 d0 e4 bne getlp ;|2/3| letztes Byte empfangen? 03eb 60 rts ;| 6 | ja, Rückkehr 03ec .assert >getlp = >*, error 03ec 03ec c64end: .assert * <= $0400, warning 03ec