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.