How to implement bareback interrupts?
Re: How to implement bareback interrupts?
I can try to fix if you upload the complete source code file here + the ca65 config file
Re: How to implement bareback interrupts?
I have a minimal example that works in the emulator.
File: cart.cfg
File: main.asm
Run with: ./x16emu -cartbin cart.bin
File: cart.cfg
Code: Select all
MEMORY {
ZP: file = "", start = $0022, size = $0080 - $0022, define = yes;
CARTRAM: start = $1000, size = $8f00, define = yes;
CARTROM: start = $c000, size = $3fff, fill = yes, fillval = $aa;
}
SEGMENTS {
SETUP: load = CARTROM, type = rw, define = yes;
CODE: load = CARTROM, run = CARTRAM, type=rw, define=yes;
}
Code: Select all
; Build with: cl65 -o cart.bin -t cx16 -C cart.cfg main.asm
.import __CODE_LOAD__
.import __CODE_SIZE__
.import __CODE_RUN__
IRQVec = $0314
.segment "SETUP"
; Magic cartridge string at $c000
.byt "cx16"
; Copy code to RAM
init:
lda #<__CODE_LOAD__
sta $22
lda #>__CODE_LOAD__
sta $23
lda #<__CODE_RUN__
sta $24
lda #>__CODE_RUN__
sta $25
lda #<__CODE_SIZE__
sta $26
lda #>__CODE_SIZE__
sta $27
loop:
lda ($22)
sta ($24)
inc $22
bne :+
inc $23
: inc $24
bne :+
inc $25
: lda $26
bne :+
dec $27
: dec $26
lda $26
ora $27
bne loop
; Jump to RAM code
jmp __CODE_RUN__
.CODE
hello:
; Select Kernal ROM bank
stz $01
; Print hello
ldx #0
: lda msg,x
beq _setup_irq
jsr $ffd2
inx
bra :-
msg:
.byt "hello",0
; Your code...
_setup_irq:
;nop
;php
sei
lda #<loop_irq
sta IRQVec
lda #>loop_irq
sta IRQVec+1
cli
;plp
;lda #1
;sta $9F27
;rts
wait:
bra wait
loop_irq:
jsr handle_clock
jsr handle_joystick
jsr handle_keyboard
jsr show_life
lda #1
sta $9F27 ; ISR, bit 0=VSYNC
ply
plx
pla
rti
handle_clock:
;inc $22
rts
handle_joystick:
rts
handle_keyboard:
rts
show_life:
inc $22
bne :+
lda #'.'
jsr $ffd2
: rts
Re: How to implement bareback interrupts?
Looking at this code that you posted earlier, one thing that stands out is the PLP at the end of _setup_irq. This will disable interrupts, if interrupts were disabled at the beginning of the function, effectively overwriting the CLI.
Code: Select all
_setup_irq:
nop
php
sei
stz ClockLo
stz ClockHi
lda #<loop_irq
sta IRQVec
lda #>loop_irq
sta IRQVec+1
; Setup first VBLANK
lda #$1
sta VERA::IRQ_EN
cli
plp
rts
loop_irq:
jsr handle_clock
jsr handle_joystick
jsr handle_keyboard
; Sign IRQ
lda #$1
sta VERA::IRQ_FLAGS
; Cleanup
ply
plx
pla
rti
- kliepatsch
- Posts: 247
- Joined: Thu Oct 08, 2020 9:54 pm
Re: How to implement bareback interrupts?
This is starting to smell like a bug in the emulator. Maybe the fact that a cartridge is inserted changes its behavior? I think that ISR with a cartridge has so far been rather niche and maybe not been tested very well.
Edit: from skimming through the emulator source I can't find anything suspicious. It seems to be exactly as Stefan explained.
Edit: from skimming through the emulator source I can't find anything suspicious. It seems to be exactly as Stefan explained.
- kliepatsch
- Posts: 247
- Joined: Thu Oct 08, 2020 9:54 pm
Re: How to implement bareback interrupts?
Ah yes, good find Stefan. Didn't see your posts before posting mine
Re: How to implement bareback interrupts?
Boah, thanks guys, you rock! Stefan, you're right, that's the issue. Would never found that, although I still don't understand, why everyting worked fine on the vanilla boot then. I was so focused on the VERA flag set, that I totally forgot about the CPUs one.
For the sake of anybody ever searching for something like this, this is the working code on my side now:
For the sake of anybody ever searching for something like this, this is the working code on my side now:
Code: Select all
_setup_irq:
nop
php
sei
lda #<_loop_irq
sta IRQVec
lda #>_loop_irq
sta IRQVec+1
; Setup first VBLANK
lda VERA::IRQ_EN
ora #$1
sta VERA::IRQ_EN
plp
cli
rts
_loop_irq:
; Sign IRQ
lda #$1
sta VERA::IRQ_FLAGS
; Cleanup
ply
plx
pla
rti
Re: How to implement bareback interrupts?
Without digging deeper it's hard to be sure, but I have at least a theory why it first worked, and not in the cartridge ROM.
When the boot_cartridge function is called during Kernal init from within the start function in kernal/cbm/init.s, interrupts have been disabled with a SEI instructions. When you in the cartridge setup function preserved and restored the status register, you kept interrupts disabled.
If the same setup function is called from BASIC, where interrupts are enabled, you are not hit by this.
When the boot_cartridge function is called during Kernal init from within the start function in kernal/cbm/init.s, interrupts have been disabled with a SEI instructions. When you in the cartridge setup function preserved and restored the status register, you kept interrupts disabled.
If the same setup function is called from BASIC, where interrupts are enabled, you are not hit by this.
Re: How to implement bareback interrupts?
As a side note:
is a common pattern in 6502 assembly when you need to disable interrupts but want to preserve the original state of the interrupt flag.
Code: Select all
php
sei
<do some work>
plp
Re: How to implement bareback interrupts?
Ah, that makes totally sense! Thank you, for pointing this out!