04. Irq without KERNAL (irq_no_kernal) - RetroAsmDev/C64AsmGameJourney GitHub Wiki

We swap out the KERNAL and BASIC ROM, so 6510 now see the whole 64 kB of the RAM. When we do something like this there are certain steps to be done:

  • The IRQ handling routine address must be set to the address $FFFE, where was originally the pointer to the KERNAL ROM handling routine, which jumped to the RAM address $0314 to allow custom interrupt routine handlers.

  • Once the CIA-1 IRQ handling is over we need to acknowledge the interrupt (i.e. inform CIA that the interrupt was handled, so it releases the IRQ signal to CPU). If app fails to acknowledge an IRQ before the interrupt flag is cleared, the CPU will instantly start to service it locking up in an endless IRQ loop. To acknowledge it is enough to just read from Interrupt Control Register $DC0D

  • ROM swap out is done by setting the value to the $01 register

  • Last, but not least, since KERNAL is no longer handling the NMI interrupts, we need to provide the at least simple routine with RTI instruction.

Combinations for register R6510 $01 which determines, which RAM or ROM blocks 6510 CPU sees:

Value of     A000-BFFF   E000-FFFF   D000-DFFF 
Location 1   Basic ROM   Kernal ROM  I/O Area 
----------   ---------   ----------  --------- 
   $30       ram         ram         ram 
   $31       ram         ram         Char ROM 
   $32       ram         ROM         Char ROM 
   $33       ROM         ROM         Char ROM 
   $34       ram         ram         ram 
   $35       ram         ram         I/O 
   $36       ram         ROM         I/O 
   $37       ROM         ROM         I/O

Besides 64kB RAM there is 8kB ROM with BASIC Interpret, 8kB ROM with KERNAL Operating system, 4kB with Character ROM and 4kB for I/O operations, so in total we can address 88kB, 24kB past 16bit addressing limit of 6510.

App code:

    sei     ; Disabling maskabke IRQs is necessary, so we can safely change the address
            ; of the interrupt service routine

    ; Set own IRQ and NMI routines
    lda #<MyIRQ
    sta IRQRCA_FFFE ; Little-endian => the least significant byte on lower memory position

    lda #>MyIRQ
    sta IRQRCA_FFFE+1

    lda #<MyNMI
    sta NMIRCA_FFFA

    lda #>MyNMI
    sta NMIRCA_FFFA+1

    ; Swap out ROMs
    lda #$35        ; Kernal out, BASIC out
    sta $01         ; Save ROM swap out
    

    cli

; -----------------------------
; Game loop
GameLoop  
      
    jmp GameLoop          

; -----------------------------
; NMI handler
MyNMI
    rti

; -----------------------------
; IRQ handler        
MyIRQ
    dec EXTCOL_D020 ; Change the border color

    lda CIAICR_DC0D ; Acknowledge CIA 1
    rti

Memory map: