Main file : speed1581.s Current file: speed1581.s 000000r 1 ; Speed-Loader für 1581 & C64 000000r 1 ; 000000r 1 ; ******** Labels 1581 *********** 000000r 1 000000r 1 buffer := $0300 000000r 1 bytesect = $ff 000000r 1 c64off = utilend-c64+2 000000r 1 cache := $0c00 000000r 1 channel := $50 000000r 1 chnopn := $9027 000000r 1 chntab := $bb 000000r 1 data := $023b 000000r 1 delay := $ad30 000000r 1 dirflg := $026e 000000r 1 drivenr := $ef 000000r 1 eoi = $80 000000r 1 error = $01 000000r 1 getbuffp := $9442 000000r 1 getbyte := $909b 000000r 1 getdir := $8f03 000000r 1 hostflg := $76 000000r 1 jallocbf := $ff66 000000r 1 jbootrtn := $ff5a 000000r 1 jdejavu := $ff60 000000r 1 jerror := $ff2d 000000r 1 jjidle := $aed9 000000r 1 jobnr = $06 000000r 1 job := jobnr+2 000000r 1 okmess := $a862 000000r 1 pointer := $64 000000r 1 quantity := $54 000000r 1 read = $80 000000r 1 secadr := $52 000000r 1 sector := jobnr*2+12 000000r 1 side := $96 000000r 1 srchcmd := $01db 000000r 1 status := $0234 000000r 1 talk := $ad5c 000000r 1 temp := $45 000000r 1 tlkcode := $ad6a 000000r 1 tlkbroff = $adf0-tlkcode 000000r 1 tlklen = $ae34-tlkcode 000000r 1 tlkvect := $01b2 000000r 1 track := jobnr*2+11 000000r 1 wrport := $4001 000000r 1 000000r 1 000000r 1 ; ******** Programm 1581 ********* 000000r 1 000000r 1 .segment "utldr0" 000000r 1 00 03 .addr :+ ; UTLDR Ladeadresse 000002r 1 DE .byte copy-:+ ; Anzahl Bytes 000003r 1 .org buffer 000300 1 : 000300 1 000300 1 A9 9D lda #ntalk ; neue Routine 000307 1 8D B3 01 sta tlkvect+1 00030A 1 00030A 1 A2 CA ldx #tlklen 00030C 1 BD 69 AD copylp: lda tlkcode-1,x ; kopiert TALK-Routine 00030F 1 9D DD 03 sta copy-1,x ; aus ROM ins RAM 000312 1 CA dex 000313 1 D0 F7 bne copylp 000315 1 A9 48 lda #datah-(copy+tlkbroff+2) ; korrigiert 000317 1 8D 65 04 sta copy+tlkbroff+1 ; Branch in TALK-Kopie 00031A 1 A9 0F lda #%00001111 ; reserviert Puffer 0-3 für 00031C 1 20 66 FF jsr jallocbf ; diesen Code ($0300-$06ff) 00031F 1 18 clc ; verhindert erneute 000320 1 20 60 FF jsr jdejavu ; Initialisierung durch 'UI' 000323 1 A9 1A lda #%00011010 000325 1 8D DB 01 sta srchcmd ; beschleunigt Kopfbewegung 000328 1 20 03 8F jsr getdir ; Directory-Spur einlesen 00032B 1 4C 5A FF jmp jbootrtn ; Rückkehr vom Autostart 00032E 1 00032E 1 00032E 1 ; die durschnittlichen 46.2 µs pro empfangenem Byte mit der 00032E 1 ; C64 PAL-Version entsprechen etwa 92 Zyklen auf der 1581 mit 00032E 1 ; 2 MHz Takt (für NTSC müsste auf 89 Zyklen reduziert werden) 00032E 1 00032E 1 A0 00 transcmd: ldy #%00000000 000330 1 8C 01 40 sty wrport ;| 4 | DATA & CLOCK low setzen 000333 1 C1 64 cmp (pointer,x) ;| 6 | = nop 000335 1 C1 64 cmp (pointer,x) ;| 6 | = nop 000337 1 C8 iny ;| 2 | = 1 Kommandobyte 000338 1 A2 02 ldx #%00000010 ;| 2 | 00033A 1 8E 01 40 stx wrport ;| 4 | DATA high setzen 00033D 1 C1 64 cmp (pointer,x) ;| 6 | = nop 00033F 1 C1 64 cmp (pointer,x) ;| 6 | = nop 000341 1 A2 0A ldx #%00001010 ;| 2 | 000343 1 8E 01 40 stx wrport ;| 4 | DATA & CLOCK high setzen 000346 1 D0 0C bne trans1 ;| 3 | = jmp 000348 1 000348 1 EA trans: nop ;| 2 | 000349 1 A9 00 lda #%00000000 ;| 2 | 00034B 1 8D 01 40 sta wrport ;| 4 | DATA & CLOCK low setzen 00034E 1 8E 01 40 stx wrport ;| 4 | CLOCK high: Synchronisation 000351 1 B1 64 lda (pointer),y ;| 5 | nächstes Byte holen 000353 1 EA nop ;| 2 | 000354 1 C1 64 trans1: cmp (pointer,x) ;| 6 | = nop 000356 1 8D 45 00 sta a:temp ;| 4 | höherwertiges Nibble retten 000359 1 29 0F and #%00001111 ;| 2 | niederwert. Nibble isolieren 00035B 1 AA tax ;| 2 | 00035C 1 BD 8D 03 lda tab,x ;| 4 | Nibble konvertieren 00035F 1 8D 01 40 sta wrport ;| 4 | Bit 0&1 senden 000362 1 0A asl ;| 2 | Bit 2&3 in Position 000363 1 29 0A and #%00001010 ;| 2 | ATN ACK löschen 000365 1 AA tax ;| 2 | 000366 1 AD 45 00 lda a:temp ;| 4 | höherwertiges Nibble holen 000369 1 4A lsr ;| 2 | 00036A 1 8E 01 40 stx wrport ;| 4 | Bit 2&3 übertragen 00036D 1 4A lsr ;| 2 | 00036E 1 4A lsr ;| 2 | höherwertiges Nibble 00036F 1 4A lsr ;| 2 | in Position bringen 000370 1 AA tax ;| 2 | 000371 1 BD 8D 03 lda tab,x ;| 4 | Nibble konvertieren 000374 1 8D 01 40 sta wrport ;| 4 | Bit 4&5 übertragen 000377 1 0A asl ;| 2 | Bit 6&7 in Position 000378 1 29 0A and #%00001010 ;| 2 | ATN ACK löschen 00037A 1 A2 08 ldx #%00001000 ;| 2 | 00037C 1 EA nop ;| 2 | 00037D 1 EA nop ;| 2 | 00037E 1 88 dey ;| 2 | Anzahl Bytes erniedrigen 00037F 1 8D 01 40 sta wrport ;| 4 | Bit 6&7 senden 000382 1 D0 C4 bne trans ;|2/3| schon alle Bytes gesendet? 000384 1 000384 1 D1 64 cmp (pointer),y ;| 5 | = nop 000386 1 8C 01 40 sty wrport ;| 4 | CLOCK & DATA low setzen 000389 1 8E 01 40 stx wrport ;| 4 | CLOCK high setzen 00038C 1 60 return: rts ;| 6 | Rückkehr 00038D 1 .assert >transcmd = >*, error 00038D 1 00038D 1 0F 07 0D 05 tab: .repeat $10, i ; Konvertierungs-Tabelle 000391 1 0B 03 09 01 000395 1 0E 06 0C 04 000399 1 0A 02 08 00 00039D 1 .byte ~(i<<3 | i&%0110 | i>>3) & %1111 ; ____ 00039D 1 .endrep ; aus Bits 3210 werden 0213 00039D 1 .assert >tab = >*, error 00039D 1 00039D 1 78 ntalk: sei ; verhindert Interrupt 00039E 1 24 EF bit drivenr ; Doppelpunkt dem File- 0003A0 1 10 2C bpl jtalk ; Namen vorangestellt? 0003A2 1 A5 76 lda hostflg ; im VC-20- oder 0003A4 1 29 30 and #%00110000 ; C128-Modus? 0003A6 1 05 52 ora secadr ; Sekundäradresse <> 0? 0003A8 1 0D 6E 02 ora dirflg ; wird Directory geladen? 0003AB 1 D0 21 bne jtalk ; ja, originale TALK-Routine 0003AD 1 20 27 90 jsr chnopn ; Kanal zum Lesen öffnen 0003B0 1 B0 DA bcs return ; Kanal aktiv? 0003B2 1 BD 34 02 lda status,x ; READ-Flag gesetzt? 0003B5 1 10 D5 bpl return ; nein, WRITE 0003B7 1 BD 3B 02 lda data,x ; 1. Byte als Startadresse 0003BA 1 8D A7 05 sta ldstrtl+1+c64off ; LSB speichern 0003BD 1 20 9B 90 jsr getbyte ; nächstes Datum holen 0003C0 1 C9 04 cmp #>$0400 ; Autostart-Programm? 0003C2 1 B0 0D bcs noauto ; nein, dann Schnell-Laden 0003C4 1 D6 BB dec chntab,x ; ja, Zeiger zurücksetzen 0003C6 1 A6 50 ldx channel ; Kanal-Nummer 0003C8 1 AD A7 05 lda ldstrtl+1+c64off ; 1. Byte wieder 0003CB 1 9D 3B 02 sta data,x ; herstellen und 0003CE 1 4C 5C AD jtalk: jmp talk ; normal laden 0003D1 1 0003D1 1 8D A9 05 noauto: sta ldstrth+1+c64off ; Startadresse MSB 0003D4 1 A6 50 ldx channel ; Kanal-Nummer 0003D6 1 A0 12 ldy #$100-(2+c64end-c64) ; Zeiger auf C64-PRG 0003D8 1 B9 41 05 loop: lda c64end+c64off-$100,y ; Byte holen 0003DB 1 9D 3B 02 sta data,x ; und bereitstellen 0003DE 1 copy: ; TALK-Code aus ROM 0003DE 1 0003DE 1 .segment "utldr1" 0003DE 1 A8 04 .addr :+ ; UTLDR Chunk Ladeadresse 0003E0 1 AB .byte utilend-:+ ; Anzahl Bytes 0003E1 1 .org copy+tlklen ; Lücke für TALK-Kopie 0004A8 1 : 0004A8 1 0004A8 1 C8 iny ; Zeiger erhöhen 0004A9 1 F0 06 beq spdtrans ; letztes Byte übertragen? 0004AB 1 4C D8 03 jmp loop ; nein, nächstes übertragen 0004AE 1 0004AE 1 4C D9 AE datah: jmp jjidle ; BUS nicht aktiv 0004B1 1 0004B1 1 2C 01 40 spdtrans: bit wrport ; DATA low? 0004B4 1 F0 0B beq hndshk ; ja 0004B6 1 88 dey ; nein, Y-Register erniedrigen 0004B7 1 D0 F8 bne spdtrans ; Zeit abgelaufen? 0004B9 1 0004B9 1 A9 80 lda #eoi ; ja, EOI senden, da 0004BB 1 9D 34 02 sta status,x ; relativ geladen wurde 0004BE 1 4C 5C AD jmp talk ; LOAD beenden 0004C1 1 0004C1 1 8D 01 40 hndshk: sta wrport ; CLOCK & DATA low setzen 0004C4 1 A9 04 lda #%00000100 0004C6 1 0004C6 1 2C 01 40 shklp: bit wrport ; wartet, bis CLOCK low 0004C9 1 D0 FB bne shklp 0004CB 1 0004CB 1 0A asl ; A = %00001000 0004CC 1 8D 01 40 sta wrport ; CLOCK high setzen 0004CF 1 0004CF 1 20 42 94 jsr getbuffp ; holt Pufferadresse 0004D2 1 A0 00 ldy #$00 ; des 1. Sektors 0004D4 1 84 64 sty pointer ; Zeiger auf 1. Byte setzen 0004D6 1 B1 64 lda (pointer),y ; Spur 0004D8 1 D0 07 bne notlast ; letzter Sektor? 0004DA 1 C8 iny ; ja 0004DB 1 B1 64 lda (pointer),y ; Anzahl Bytes des Sektors 0004DD 1 38 sec 0004DE 1 E9 02 sbc #$02 ; -2 Bytes Startadresse 0004E0 1 2C .byte $2c ; lda überlesen 0004E1 1 A9 FD notlast: lda #bytesect-2 ; Anzahl Bytes 1. Sektor 0004E3 1 A2 03 ldx #$03 ; Zeiger auf 4. Byte 0004E5 1 86 64 stx pointer 0004E7 1 D0 43 bne first ; = jmp 0004E9 1 0004E9 1 C8 mainloop: iny ; Zeiger auf Sektor 0004EA 1 C5 17 cmp track ; gleiche Spur? 0004EC 1 85 17 sta track 0004EE 1 D0 0A bne newtrack ; nein, neue Spur einlesen 0004F0 1 B1 64 lda (pointer),y ; Sektor 0004F2 1 C9 14 cmp #20 0004F4 1 2A rol ; auf gleicher Seite 0004F5 1 45 96 eor side ; des Zylinders? 0004F7 1 4A lsr 0004F8 1 90 19 bcc sideok ; ja, Sektor übertragen 0004FA 1 B1 64 newtrack: lda (pointer),y 0004FC 1 85 18 sta sector ; Sektor retten 0004FE 1 A9 80 lda #read ; Jobcode für 'Sektor lesen' 000500 1 85 08 sta job ; übergeben 000502 1 58 cli ; Kopf auf Spur 000503 1 00 brk ; Spur einlesen 000504 1 EA nop ; Korrektur wegen brk 000505 1 A5 08 jobwt: lda job ; wartet, bis 000507 1 30 FC bmi jobwt ; Job ausgeführt 000509 1 78 sei ; verhindert Interrupt 00050A 1 C9 02 cmp #$02 ; Fehler? 00050C 1 A9 01 lda #error ; Kommando-Byte für Fehler 00050E 1 B0 2E bcs end ; Fehler aufgetreten 000510 1 A5 18 lda sector ; Sektor 000512 1 2C .byte $2c ; lda überlesen 000513 1 B1 64 sideok: lda (pointer),y ; Sektor 000515 1 C9 14 cmp #20 ; grösser als 19? 000517 1 B0 02 bcs subtr ; ja, Subtraktion 000519 1 69 15 adc #20+1 ; nein, Addition 00051B 1 E9 08 subtr: sbc #20->cache ; berechnet Zeiger auf Cache 00051D 1 85 65 sta pointer+1 ; MSB Zeiger 00051F 1 88 dey ; Y = 0 000520 1 B1 64 lda (pointer),y ; Spur 000522 1 D0 04 bne notlast1 ; letzter Sektor? 000524 1 C8 iny ; ja 000525 1 B1 64 lda (pointer),y ; Anzahl Bytes 000527 1 2C .byte $2c ; lda überlesen 000528 1 A9 FF notlast1: lda #bytesect ; Bytes pro Sektor normal 00052A 1 E6 64 inc pointer ; Zeiger auf 2. Byte 00052C 1 85 54 first: sta quantity ; Anzahl Bytes sichern 00052E 1 20 2E 03 jsr transcmd ; und senden 000531 1 A4 54 ldy quantity ;| 3 | Anzahl 000533 1 88 dey ;| 2 | -1 als Zähler 000534 1 EA nop ;| 2 | 000535 1 20 48 03 jsr trans ;| 6 | Bytes übertragen 000538 1 84 64 sty pointer ; Zeiger auf Spur 00053A 1 B1 64 lda (pointer),y ; letzter Sektor übertragen? 00053C 1 D0 AB bne mainloop ; nein, nächste Übertragung 00053E 1 00053E 1 20 30 AD end: jsr delay ; wartet 39 µs 000541 1 20 2E 03 jsr transcmd ; übermittelt Kommando 000544 1 A5 08 lda job ; (0 = Ende, 1 = Fehler) 000546 1 F0 05 beq okmssg ; Fehler aufgetreten? 000548 1 A2 06 ldx #jobnr ; Fehlermeldung bereitstellen 00054A 1 20 2D FF jsr jerror ; = jmp 00054D 1 00054D 1 20 62 A8 okmssg: jsr okmess ; OK-Meldung bereitstellen 000550 1 4C 03 8F jmp getdir ; Directory-Spur einlesen 000553 1 000553 1 utilend: .assert * <= $0700, error ; in Puffer 0-3 000553 1 000553 1 000553 1 ; ******** Labels C64 ************ 000553 1 000553 1 basicend := $2d 000553 1 bsicvect := $e453 000553 1 c64 := $0300 000553 1 chroutign := $f1b4 000553 1 clr := $a660 000553 1 clrchnign := $f349 000553 1 exec := $a7ae 000553 1 illegqnt := $b248 000553 1 irq := $ea31 000553 1 irqign := $ea7e 000553 1 jioerror8 := $f602 000553 1 ldend := $f5aa 000553 1 link := $a533 000553 1 loaderr = 29 000553 1 opsvect := $fd15 000553 1 point := $ae 000553 1 quant := $b9 000553 1 rdport := $dd00 000553 1 ready := $a474 000553 1 relad := $c3 000553 1 run := $a659 000553 1 screen := $d011 000553 1 secad := $b8 000553 1 stop := $f6ed 000553 1 sys := $e130 000553 1 sysjmp := $14 000553 1 tmp := quant 000553 1 warmstart := $fe66 000553 1 000553 1 ; ******** Programm C64 ********** 000553 1 000553 1 .segment "utldr2" 000553 1 53 05 .addr utilend ; UTLDR Ladeadresse Floppy 000555 1 EE .byte 2+c64end-:+ ; Anzahl Bytes 000556 1 000556 1 00 03 .addr :+ ; PRG Ladeadresse C64 000558 1 .org c64 000300 1 : 000300 1 000300 1 00 00 .addr $0000 ; Endkennzeichen falls relativ geladen 000302 1 000302 1 ; Programmstart über den STOP-Vektor, der nach jedem gespeicherten 000302 1 ; Byte angesprungen wird. Da zuerst nur das LSB überschrieben wird 000302 1 ; muss das auch eine gültige Adresse sein. Verbiegen der CLRCHN- & 000302 1 ; CHROUT-Vektoren macht den Code dort harmlos ausser Löschen von Z. 000302 1 000302 1 A5 AE stopnew: lda point ; Ende des Ladeprogramms erreicht? 000304 1 C9 EC cmp #irqign = >irq, error 000316 1 09 03 .addr warmnew ; BRK-Vektor: Warmstart 000318 1 09 03 .addr warmnew ; NMI-Vektor: Warmstart 00031A 1 xx xx xx xx .res $0322-* 00031E 1 xx xx xx xx 000322 1 49 F3 .addr clrchnign ; CLRCHN-Vektor: auf rts 000324 1 xx xx .res $0326-* 000326 1 B4 F1 .addr chroutign ; CHROUT-Vektor: auf rts 000328 1 02 03 .addr stopnew ; STOP-Vektor: abfangen 00032A 1 .assert >jioerror8 = >stop && wait = >sync1, error 00038E 1 00038E 1 48 endld: pha ; Bit 0 retten 00038F 1 20 15 FD jsr opsvect ; setzt Betriebssystem- & 000392 1 20 53 E4 jsr bsicvect ; BASIC-Vektoren 000395 1 68 pla ; setzt bei 000396 1 4A lsr ; Fehler Carry 000397 1 68 pla ; stellt Bit l4&15 vom 000398 1 8D 00 DD sta rdport ; VIC wieder her 00039B 1 68 pla 00039C 1 8D 11 D0 sta screen ; schaltet Bild ein 00039F 1 58 cli ; Interrupt ermöglichen 0003A0 1 B0 28 bcs lderr ; bei Fehler Lade-Ende 0003A2 1 A6 B8 ldx secad ; Sekundäradresse 0003A4 1 E8 inx 0003A5 1 8A txa ; 3-6 = Autostart 0003A6 1 29 04 and #%00000100 0003A8 1 F0 22 beq ldend1 ; kein Autostart 0003AA 1 8A txa 0003AB 1 4A lsr 0003AC 1 B0 0C bcs bscrun 0003AE 1 20 60 A6 jsr clr ; 1,3 = SYS-Aufruf 0003B1 1 A9 A4 lda #>(ready-1) ; Rücksprungadresse MSB 0003B3 1 48 pha ; auf Stapel 0003B4 1 A9 73 lda #<(ready-1) ; Rücksprungadresse LSB 0003B6 1 48 pha ; auf Stapel 0003B7 1 4C 30 E1 jmp sys ; Maschinen-PRG ausführen 0003BA 1 0003BA 1 20 AA F5 bscrun: jsr ldend ; 2,4 = RUN-Befehl 0003BD 1 86 2D stx basicend ; BASIC-Ende setzen 0003BF 1 84 2E sty basicend+1 0003C1 1 20 59 A6 jsr run ; CHRGET auf Programmstart 0003C4 1 20 33 A5 jsr link ; Zeilen binden 0003C7 1 4C AE A7 jmp exec ; BASIC-PRG ausführen 0003CA 1 0003CA 1 A9 1D lderr: lda #loaderr ; Nummer '?LOAD ERROR' 0003CC 1 4C AA F5 ldend1: jmp ldend ; Ende Laderoutine 0003CF 1 0003CF 1 0003CF 1 ; pro empfangenem Byte werden 45 oder 46 Zyklen benötigt, 0003CF 1 ; das sind im Durchschnitt 46.2 µs für die C64 PAL-Version 0003CF 1 ; mit 985.2486 kHz Takt (NTSC: 44.5 µs bei 1.0227271 MHz) 0003CF 1 0003CF 1 91 AE getlp: sta (point),y ;| 6 | legt Byte im Speicher ab 0003D1 1 AD 00 DD get: lda rdport ;| 4 | lädt Bit 0&1 0003D4 1 4A lsr ;| 2 | schiebt Byte 0003D5 1 4A lsr ;| 2 | 2 Stellen nach rechts 0003D6 1 0D 00 DD ora rdport ;| 4 | fügt Bit 2&3 hinzu 0003D9 1 4A lsr ;| 2 | schiebt Byte 0003DA 1 4A lsr ;| 2 | 2 Stellen nach rechts 0003DB 1 0D 00 DD ora rdport ;| 4 | fügt Bit 4&5 hinzu 0003DE 1 4A lsr ;| 2 | schiebt Byte 0003DF 1 4A lsr ;| 2 | 2 Stellen nach rechts 0003E0 1 0D 00 DD ora rdport ;| 4 | fügt Bit 6&7 hinzu 0003E3 1 2C 00 DD bit rdport ;| 4 | Synchronisation mit 1581 0003E6 1 70 00 bvs sync2 ;|2/3| +1 Zyklus falls zu schnell 0003E8 1 88 sync2: dey ;| 2 | erniedrigt Anzahl Bytes 0003E9 1 D0 E4 bne getlp ;|2/3| letztes Byte empfangen? 0003EB 1 60 rts ;| 6 | ja, Rückkehr 0003EC 1 .assert >getlp = >*, error 0003EC 1 0003EC 1 c64end: .assert * <= $0400, warning 0003EC 1