Кто вызывает мой обработчик прерываний, если у меня отключены оба ЦРУ?

Я пытаюсь настроить простой обработчик растровых прерываний, чтобы изменить цвет фона в заданной полосе. Однако мой обработчик прерываний, кажется, вызывается все время. (код использует формат CA65)

.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

Если я закомментирую три строки, помеченные как "обходной путь" в приведенном выше коде, то мой обработчик прерываний будет вызываться постоянно, а не только в (начале) строки ROW:

Без обходного пути

Если я раскомментирую эти три строки, то это сработает, но очень нестабильно, наверное, из-за тех же непреднамеренных прерываний:

С обходным путем

1 ответ

Решение

Я обнаружил несколько проблем с моим кодом, опубликованным выше, и исправление всех из них устранило проблему:

  1. Битовая маска для выключения CIA прерывания были неправильными (это было случайно 9 бит длиной) - это то, что вызывало все эти дополнительные прерывания...
  2. ISR Макрос постскриптума отсутствовал pla восстановить A регистр - это испорченное состояние по-королевски, так что все, что случилось со старым кодом, было более или менее случайно...
  3. VIC прерывание не было сброшено в коде установки прерываний - поэтому после устранения двух предыдущих проблем прерывания никогда не запускались.
  4. Там нет ничего rts в конце установочного кода, так как мы выключаем Kernal и BASIC ROM

Итак, фиксированный код выглядит следующим образом:

.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

Это приводит, как и ожидалось, к сплошной белой полосе. По какой-то неизвестной причине полоса начинается в середине экрана по горизонтали, но я думаю, что это будет один для отдельного вопроса SO.

Другие вопросы по тегам