I've found several problems with my code as posted above, and fixing all of them fixed the problem:
- The bitmask for turning off
CIA
interrupts was wrong (it was accidentally 9 bits long) -- this is what was causing all those extra interrupt firings... - The
ISR
postscriptum macro was missing apla
to restore theA
register -- this screwed up state royally, so whatever happened with the old code was more-or-less by chance... - The
VIC
interrupt was not flushed in the interrupt setup code -- so after fixing the previous two problems, now the interrupts were never triggered. - There's nothing to
rts
to at the end of the setup code, since we turn off kernal and BASIC ROM
So the fixed code is as follows:
.include "c64.inc"
ROW = 100
;;; Acknowledge VIC interrupt
.macro ack_vic
lda VIC_IRR
and #$01
sta VIC_IRR
.endmacro
.segment "ZPSAVE"
.segment "STARTUP"
sei
;; Turn off BASIC and KERNAL ROM
lda #$35
sta $01
;; Flush CIA IRQs
bit CIA1_ICR
bit CIA2_ICR
ack_vic
;; Turn off CIA interrupts
lda #%01111111
sta CIA1_ICR
sta CIA2_ICR
;; Set target raster line
lda #%01111111
and VIC_CTRL1
sta VIC_CTRL1
lda #ROW
sta VIC_HLINE
;; Enable VIC interrupt
lda #%00000001
sta VIC_IMR
;; Install interrupt handler
lda #<isr
sta $fffe
lda #>isr
sta $ffff
cli
jmp *
.macro isr_pre
pha
txa
pha
tya
pha
.endmacro
.macro isr_post
pla
tay
pla
tax
pla
rti
.endmacro
.proc isr
isr_pre
ack_vic
lda #1
sta VIC_BORDERCOLOR
sta VIC_BG_COLOR0
ldx #50
: dex
bne :-
lda #0
sta VIC_BORDERCOLOR
sta VIC_BG_COLOR0
exit: isr_post
.endproc
This results, as expected, in a solid white stripe. For some unknown reason, the stripe starts at the middle of the screen horizontally, but I guess that'd be one for a separate SO question.