I'm tinkering with Marko's IRQ loader, which works great, except for one thing: my IRQ routine also changes $dd00. I've patched my IRQ routine so that it only messes with bits 1 and 0, the VIC-II banking bits, but the loader still causes the screen to flicker -- it seems like it assumes $dd00 isn't changing. I made the changes below (in dasm format) but it just freezes up. Any ideas? Is it timing? (Look for lines with VBMODE in them for my changes -- I've made them conditional if VBMODE = 1.) -- ;---------------------------------------------------------------------- ; Synchronous 1540/1541/1570/1571 fastloader ; Copyright © 1996 Marko Mäkelä <Marko.Makela@HUT.FI> ; ; VBMODE compatibility patch by Cameron Kaiser <ckaiser@oa.ptloma.edu> ; Copyright 1998 Cameron Kaiser ; ; This program is free software; you can redistribute it and/or modify ; it under the terms of the GNU General Public License as published by ; the Free Software Foundation; either version 2 of the License, or ; (at your option) any later version. ;---------------------------------------------------------------------- ; Init: jsr init ; Load: ldx #"A" ;first char of name ; ldy #"B" ;second char of name ; jsr irqload ; ; C=status: 0=ok, 1=error ;---------------------------------------------------------------------- target eqm c64 ; choose the target system vic20 = 1 ; Commodore VIC-20 c64 = 2 ; Commodore 64 c128 = 4 ; Commodore 128 c16 = 8 ; The Commodore 264 Series (C16, C116, plus/4) ; Kaiser's patch for proper VIC-II bank handling (64 only) VBMODE = 1 ; 1 = yes, do try to handle this right ; 0 = no START = $cc00 ; and the start address RETRIES = 5 ; amount of retries when reading a sector LEDFLASH = 2 ; LED flashing level: ; 0 = normal (LED constantly on while loading a file) ; 1 = LED glows on and off while waiting for a command ; 2 = LED on only while reading sectors ; 3 = 1 + 2 ;--------------------------------------- ; source code begins ; no user-modifiable routines inside :-) #processor 6502 ; include the ROM definitions #if target & c16 #include "include/c16rom.lib" #else ; #include "include/cbmrom.lib" ciout = 65448 listn = 65457 secnd = 65427 unlsn = 65454 sal = 172 fa = 186 #endif AMOUNT = $20 ; amount of data bytes to transfer with one M-W command ESCBYTE = $ac ; the escape char used in the transfers ; set the I/O constants and the variables #if target & vic20 iecport1 = $912c dato = 32 clko = 2 iecport2 = $911f atno = 128 clki = 1 dati = 2 #endif #if target & (c64 | c128) iecport1 = $dd00 iecport2 = iecport1 atno = 8 clko = 16 dato = 32 clki = 64 dati = 128 #endif #if target & c16 iecport1 = 1 iecport2 = iecport1 dato = 1 clko = 2 atno = 4 clki = 64 dati = 128 #endif ; declare the zeropage variables store = sal ; temporary byte storage #org START init: ; initialize the self-modifying parts of the code lda #<drvcode sta mwbyte$ + 1 lda #>drvcode sta mwbyte$ + 2 lda #<drive sta mwcmd$ + 2 lda #>drive sta mwcmd$ + 1 ; send the m-w command to write the data mwloop$: jsr inidev$ ldx #lmwcmd$ - 1 smwcmd$: lda mwcmd$,x jsr ciout dex bpl smwcmd$ ; send the actual data bytes ldx #0 mwbyte$: lda drvcode,x jsr ciout inx cpx #AMOUNT bne mwbyte$ ; complete the command jsr unlsn ; update the addresses clc lda #AMOUNT adc mwbyte$ + 1 sta mwbyte$ + 1 bcc noupdhi1$ clc inc mwbyte$ + 2 noupdhi1$: lda #AMOUNT adc mwcmd$ + 2 sta mwcmd$ + 2 tax lda #0 adc mwcmd$ + 1 sta mwcmd$ + 1 cpx #<edrvcode sbc #>edrvcode bcc mwloop$ ; send m-e to start the routine jsr inidev$ ldx #lmecmd$ - 1 sendcmd$: lda mecmd$,x jsr ciout dex bpl sendcmd$ ; perform the command jmp unlsn ; subroutine: make the current drive listen inidev$: lda fa jsr listn lda #$6f jmp secnd ; the m-w command backwards mwcmd$: dc.b AMOUNT,>drive,<drive,"W-M" lmwcmd$ = . - mwcmd$ ; the m-e command backwards mecmd$: dc.b >drive,<drive,"E-M" lmecmd$ = . - mecmd$ ;--------------------------------------- ; the actual irq loader irqload: ; this is not going to work if the irq routine is varying the vic-ii bank, ; so don't bother if VBMODE is on because we need to check on every call then. #if target & (c64|c128) && VBMODE nop ; just a placeholder :-) #else lda iecport1 and #255 - dato - clko sta iec1d1a$ ; CLK=1, DATA=1 sta iec1d1b$ eor #clko sta iec0d1a$ ; CLK=0, DATA=1 sta iec0d1b$ #endif txa ; send the file name's first character jsr putbyt$ tya ; send the file name's second character jsr putbyt$ jsr getbyt$ ; get the start address tay jsr getbyt$ sta adrhi$ loadloop$: jsr getbyt$ ; get next file byte, exit on completion adrhi$ = . + 2 sta $100,y ; store it iny bne loadloop$ inc adrhi$ jmp loadloop$ ;--------------------------------------- ; getbyt$: get a byte, interpret the escape codes getbyt$: jsr getbits$ cmp #ESCBYTE bne getdone$ jsr getbits$ ; escape char fetched, get another byte cmp #ESCBYTE ; another escape char: it is a literal beq getdone$ cmp #1 ; Transfer finished. 0=ok, nonzero=error. pla ; Set the C flag accordingly. pla ; discard the return address getdone$: rts ; getbits$: get a byte getbits$: ldx #8 ; counter: get 8 bits getbit$: lda iecport2 and #dati | clki eor #dati | clki beq getbit$ ; wait for CLK==low || DATA==low #if dati == 128 asl ; Carry = DATA==low #else #if dati < clki and #dati #endif cmp #dati #endif iec0d1a$ = . + 1 #if target & (c64|c128) && VBMODE lda $dd00 and #3 ora #252 ^ dato #else lda #255 - dato #endif bcs gskip$ eor #dato | clko gskip$: sta iecport1 ; acknowledge the bit ror store ; store the data lda #dati | clki wgetack$: bit iecport2 beq wgetack$ ; wait for CLK==high || DATA==high iec1d1a$ = . + 1 #if target & (c64|c128) && VBMODE lda $dd00 and #3 ora #252 ^ clko ^ dato #else lda #255 - clko - dato #endif sta iecport1 ; raise CLK and DATA dex bne getbit$ ; loop until all bits are received lda store rts ; putbyt$ puts a byte putbyt$: sta store ldx #8 ; counter: send all 8 bits putbit$: lsr store ; read a bit iec0d1b$ = . + 1 #if target & (c64|c128) && VBMODE lda $dd00 and #3 ora #252 ^ dato #else lda #255 - dato #endif bcc pskip$ eor #dato | clko pskip$: sta iecport1 ; send the data lda #dati | clki wputack1$: bit iecport2 bne wputack1$ ; wait for CLK==DATA==low iec1d1b$ = . + 1 #if target & (c64|c128) && VBMODE lda $dd00 and #3 ora #252 ^ clko ^ dato #else lda #255 - clko - dato #endif sta iecport1 ; set DATA=CLK=high wputack2$: lda iecport2 and #dati | clki eor #dati | clki bne wputack2$ ; wait for CLK==DATA==high dex bne putbit$ ; loop until all bits are sent rts ;--------------------------------------- ; the drive code drvcode: #rorg $500 acsbf = $01 ;access to buffer 1 trkbf = $08 ;track of buffer 1 sctbf = $09 ;sector of buffer 1 iddrv0 = $12 ;id of drive 0 id = $16 ;id datbf = $14 ;databuffer buf = $0400 ;sector buffer via1pb = $1800 via2pb = $1c00 ;--------------------------------------- drive: cld driveloop: cli ; interrupts enabled until first sector read #if !(LEDFLASH & 1) lda via2pb and #$f7 ; led off sta via2pb #endif jsr recv$ sta temp1$ ; get the file name, first char jsr recv$ sta temp2$ ; second char #if !(LEDFLASH & 2) lda #8 ora via2pb sta via2pb ; led on #endif ldx #18 ldy #1 ; read the disk directory (track 18, sector 1) dirloop$: stx trkbf sty sctbf jsr readsect$ ; read the sector bcs errquit$ ; quit if it could not be read ldy #$02 nextfile$: lda buf,y ; check file type and #$83 cmp #$82 ; must be PRG bne notfound$ lda buf+3,y ; check the first two characters cmp temp1$ bne notfound$ lda buf+4,y cmp temp2$ beq found$ notfound$: tya clc adc #$20 tay bcc nextfile$ ldy buf+1 ; get next sector ldx buf ; and track bne dirloop$ ; keep trying until the last directory block has been searched ; file not found: fall through errquit$: ldx #ESCBYTE ; send the escape byte followed by 1 to notify the computer jsr send$ ldx #1 jsr send$ jmp driveloop found$: lda buf+1,y ; get the track and sector numbers sta trkbf lda buf+2,y sta sctbf nextsect$: jsr readsect$ bcs errquit$ ; quit if the sector could not be read ldy #$00 lda buf+1 ; store the track and sector of next block sta sctbf lda buf sta trkbf bne notlast$ ; if the track is nonzero, this wasn't the last sector ldy buf+1 ; last sector: get sector length iny notlast$: sty temp1$ ldy #2 ; skip the track and sector when sending the buffer sendbuf$: ; send the buffer contents to the computer ldx buf,y cpx #ESCBYTE bne noesc$ jsr send$ ; escape the escape character ldx #ESCBYTE noesc$: jsr send$ iny cpy temp1$ ; were all bytes of the block sent? bne sendbuf$ lda buf bne nextsect$ ; loop until all sectors are loaded finish$: ldx #ESCBYTE ; send the escape byte followed by 0 to notify the computer jsr send$ ldx #0 jsr send$ jmp driveloop ;--------------------------------------- ; readsect$: read a sector readsect$: #if LEDFLASH & 2 lda #8 ora via2pb sta via2pb ; turn the LED on #endif ldy #RETRIES ; load the retry count cli ; enable interrupts, so that the command will be executed retry$: lda #$80 sta acsbf ; code for reading the sector poll1$: lda acsbf ; wait for the command to complete bmi poll1$ cmp #1 bne noexit$ #if LEDFLASH & 2 lda #$f7 and via2pb sta via2pb ; turn the LED off #endif clc sei ; disable interrupts again to make the program faster rts ; success: exit the loop noexit$: dey ; decrement the retry count bmi error$ ; quit if there were too many retries cpy #RETRIES / 2 bne skipcode$ lda #$c0 sta acsbf ; half the retries left: knock the head (seek track 1) skipcode$: lda id ; tolerate disk id changes sta iddrv0 lda id+1 sta iddrv0+1 poll2$: lda acsbf ; wait for the command to complete bmi poll2$ bpl retry$ ; branch always error$: #if LEDFLASH & 2 lda #$f7 and via2pb sta via2pb ; turn the LED off #endif sec sei rts ; send$ sends the X register contents. datbf is used as temporary storage. send$: stx datbf ldx #8 ; send 8 bits ; sendbit$ sends a bit sendbit$: lsr datbf ; read next bit lda #2 ; prepare for CLK=high, DATA=low bcs sskip$ lda #8 ; prepare for CLK=low, DATA=high sskip$: sta via1pb ; send the data sgetack$: lda via1pb ; wait for CLK==DATA==low and #5 eor #5 bne sgetack$ sta via1pb ; set CLK=DATA=high lda #5 swait$: bit via1pb bne swait$ ; wait for CLK==DATA==high dex bne sendbit$ ; loop until all bits have been sent rts ;--------------------------------------- ; recv$ receives a byte to A. datbf is used as temporary storage. recv$: #if LEDFLASH & 1 ldy #0 ; LED brightness (0=dim, 255=lit) tsx fincr$: jsr doflash$ ldy datbf iny bne fincr$ fdecr$: dey jsr doflash$ ldy datbf bne fdecr$ beq fincr$ doflash$: sty datbf ; store the counter for LED flashing lda #$f7 and via2pb sta via2pb ; turn the LED off jsr fdelay$ ; perform the delay lda #8 ora via2pb sta via2pb ; turn the LED on lda datbf eor #$ff tay ; fall through fdelay$: lda #$85 and via1pb ; wait for any signal from the bus bne flashdone$ iny bne fdelay$ rts flashdone$: lda #$f7 and via2pb sta via2pb ; turn the LED off txs ; discard the return address #endif ldx #8 ; counter: receive 8 bits recvbit$: lda #$85 and via1pb ; wait for CLK==low || DATA==low bmi gotatn$ ; quit if ATN was asserted beq recvbit$ lsr ; read the data bit lda #2 ; prepare for CLK=high, DATA=low bcc rskip$ lda #8 ; prepare for CLK=low, DATA=high rskip$: sta via1pb ; acknowledge the bit received ror datbf ; and store it rwait$: lda via1pb ; wait for CLK==high || DATA==high and #5 eor #5 beq rwait$ lda #0 sta via1pb ; set CLK=DATA=high dex bne recvbit$ ; loop until all bits have been received lda datbf ; read the data to A rts gotatn$: pla ; If ATN gets asserted, exit to the operating system. pla ; Discard the return address. cli ; Enable the interrupts. rts temp1$ = . temp2$ = . + 1 edrvcode: #rend -- Cameron Kaiser *** http://calvin.ptloma.edu/~spectre/ *** spectre@ptloma.edu "Please dispose of this message in the usual manner." -- Mission: Impossible - This message was sent through the cbm-hackers mailing list. To unsubscribe: echo unsubscribe | mail cbm-hackers-request@dot.tcm.hut.fi.
Archive generated by hypermail 2.1.1.