I'm trying to set up a simple raster interrupt handler to change the background color in a given stripe. However, my interrupt handler seems to be called all the time. (the code uses CA65's format)
.include "c64.inc"
ROW = 100
.segment "ZPSAVE"
.segment "STARTUP"
sei
;; Turn off BASIC and KERNAL ROM
lda #$35
sta $01
;; Flush CIA IRQs
bit CIA1_ICR
bit CIA2_ICR
;; Turn off CIA interrupts
lda #%011111111
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
rts
.macro isr_pre
pha
txa
pha
tya
pha
.endmacro
.macro isr_post
pla
tay
pla
tax
rti
.endmacro
;;; Acknowledge VIC interrupt
.macro ack_vic
lda VIC_IRR
and #$01
sta VIC_IRR
.endmacro
.proc isr
isr_pre
ack_vic
;; Uncommenting these lines works around the problem
;; lda VIC_HLINE
;; cmp #ROW
;; bne exit
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
If I comment out the three lines marked as the "workaround" in the above code, then my interrupt handler is called all the time, not just on (the start of) row ROW:

If I uncomment those three lines, then it works, but it's very unstable, I guess because of those same unintended interrupts:

I've found several problems with my code as posted above, and fixing all of them fixed the problem:
CIA interrupts was wrong (it was accidentally 9 bits long) -- this is what was causing all those extra interrupt firings...ISR postscriptum macro was missing a pla to restore the A register -- this screwed up state royally, so whatever happened with the old code was more-or-less by chance...VIC interrupt was not flushed in the interrupt setup code -- so after fixing the previous two problems, now the interrupts were never triggered.rts to at the end of the setup code, since we turn off kernal and BASIC ROMSo 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With