breaking change: sys.set_irq() and sys.set_rasterirq() no longer have useKernal parameter! The irq handler routine must return a boolean instead in the A register.

When it returns true it means run the system IRQ handler afterwards. When it returns false, the system handler is NOT ran afterwards.
This commit is contained in:
Irmen de Jong 2023-11-21 22:33:37 +01:00
parent a83e9d9a0a
commit 08ac459a41
15 changed files with 82 additions and 72 deletions

View File

@ -431,13 +431,10 @@ save_SCRATCH_ZPWORD2 .word 0
}}
}
asmsub set_irq(uword handler @AY, bool useKernal @Pc) clobbers(A) {
asmsub set_irq(uword handler @AY) clobbers(A) {
%asm {{
sta _modified+1
sty _modified+2
lda #0
rol a
sta _use_kernal
sei
lda #<_irq_handler
sta cbm.CINV
@ -450,20 +447,20 @@ _irq_handler
cld
_modified
jsr $ffff ; modified
pha
jsr sys.restore_prog8_internals
lda _use_kernal
bne +
lda #$ff
pla
beq +
jmp cbm.IRQDFRT ; continue with normal kernal irq routine
+ lda #$ff
sta c64.VICIRQ ; acknowledge raster irq
lda c64.CIA1ICR ; acknowledge CIA1 interrupt
; end irq processing - don't use kernal's irq handling
pla
tay
pla
tax
pla
rti
+ jmp cbm.IRQDFRT ; continue with normal kernal irq routine
_use_kernal .byte 0
}}
@ -485,13 +482,10 @@ asmsub restore_irq() clobbers(A) {
}}
}
asmsub set_rasterirq(uword handler @AY, uword rasterpos @R0, bool useKernal @Pc) clobbers(A) {
asmsub set_rasterirq(uword handler @AY, uword rasterpos @R0) clobbers(A) {
%asm {{
sta _modified+1
sty _modified+2
lda #0
rol a
sta set_irq._use_kernal
lda cx16.r0
ldy cx16.r0+1
sei
@ -508,19 +502,19 @@ _raster_irq_handler
cld
_modified
jsr $ffff ; modified
pha
jsr sys.restore_prog8_internals
lda #$ff
sta c64.VICIRQ ; acknowledge raster irq
lda set_irq._use_kernal
bne +
; end irq processing - don't use kernal's irq handling
pla
beq +
jmp cbm.IRQDFRT ; continue with kernal irq routine
+ pla
tay
pla
tax
pla
rti
+ jmp cbm.IRQDFRT ; continue with kernal irq routine
_setup_raster_irq
pha

View File

@ -433,13 +433,10 @@ save_SCRATCH_ZPWORD2 .word 0
}}
}
asmsub set_irq(uword handler @AY, bool useKernal @Pc) clobbers(A) {
asmsub set_irq(uword handler @AY) clobbers(A) {
%asm {{
sta _modified+1
sty _modified+2
lda #0
rol a
sta _use_kernal
sei
lda #<_irq_handler
sta cbm.CINV
@ -452,23 +449,21 @@ _irq_handler
cld
_modified
jsr $ffff ; modified
pha
jsr sys.restore_prog8_internals
lda _use_kernal
bne +
lda #$ff
pla
beq +
jmp cbm.IRQDFRT ; continue with normal kernal irq routine
+ lda #$ff
sta c64.VICIRQ ; acknowledge raster irq
lda c64.CIA1ICR ; acknowledge CIA1 interrupt
; end irq processing - don't use kernal's irq handling
pla
tay
pla
tax
pla
rti
+ jmp cbm.IRQDFRT ; continue with normal kernal irq routine
_use_kernal .byte 0
}}
}}
}
asmsub restore_irq() clobbers(A) {
@ -487,13 +482,10 @@ asmsub restore_irq() clobbers(A) {
}}
}
asmsub set_rasterirq(uword handler @AY, uword rasterpos @R0, bool useKernal @Pc) clobbers(A) {
asmsub set_rasterirq(uword handler @AY, uword rasterpos @R0) clobbers(A) {
%asm {{
sta _modified+1
sty _modified+2
lda #0
rol a
sta set_irq._use_kernal
lda cx16.r0
ldy cx16.r0+1
sei
@ -510,19 +502,19 @@ _raster_irq_handler
cld
_modified
jsr $ffff ; modified
pha
jsr sys.restore_prog8_internals
lda #$ff
sta c64.VICIRQ ; acknowledge raster irq
lda set_irq._use_kernal
bne +
; end irq processing - don't use kernal's irq handling
pla
pla
beq +
jmp cbm.IRQDFRT ; continue with kernal irq routine
+ pla
tay
pla
tax
pla
rti
+ jmp cbm.IRQDFRT ; continue with kernal irq routine
_setup_raster_irq
pha

View File

@ -104,11 +104,11 @@ psg {
}
}
sub envelopes_irq() {
sub envelopes_irq() -> bool {
; If you want to use real-time volume envelopes (Attack-Sustain-Release),
; you have to call this routine every 1/60th second, for example from your vsync irq handler,
; or just install this routine as the only irq handler if you don't have to do other things there.
; Example: cx16.set_irq(&psg.envelopes_irq, true)
; Example: cx16.set_irq(&psg.envelopes_irq)
; NOTE: this routine calls save/restore_vera_context() for you, don't nest this or call it yourself!
; cx16.r0 = the volume word (volume scaled by 256)
@ -170,6 +170,7 @@ psg {
pop(cx16.r2L)
pop(cx16.r1L)
popw(cx16.r0)
return true ; run the system IRQ handler afterwards
}
ubyte[16] envelope_states

View File

@ -930,13 +930,10 @@ asmsub cleanup_at_exit() {
}}
}
asmsub set_irq(uword handler @AY, bool useKernal @Pc) clobbers(A) {
asmsub set_irq(uword handler @AY) clobbers(A) {
%asm {{
sta _modified+1
sty _modified+2
lda #0
rol a
sta _use_kernal
sei
lda #<_irq_handler
sta cx16.CINV
@ -953,17 +950,17 @@ _irq_handler
cld
_modified
jsr $ffff ; modified
pha
jsr sys.restore_prog8_internals
lda _use_kernal
bne +
; end irq processing - don't use kernal's irq handling
lda #1
pla
beq +
jmp (restore_irq._orig_irqvec) ; continue with normal kernal irq routine
+ lda #1
sta cx16.VERA_ISR ; clear Vera Vsync irq status
ply
plx
pla
rti
+ jmp (restore_irq._orig_irqvec) ; continue with normal kernal irq routine
_use_kernal .byte 0
}}

View File

@ -142,14 +142,23 @@ There are a few library routines available to make setting up C64 60hz IRQs and
These routines are::
sys.set_irq(uword handler_address, bool useKernal)
sys.set_rasterirq(uword handler_address, uword rasterline, boolean useKernal)
sys.set_irq(uword handler_address)
sys.set_rasterirq(uword handler_address, uword rasterline)
sys.restore_irq() ; set everything back to the systems default irq handler
The IRQ handler routine must return a boolean value (0 or 1) in the A register.
0 means do *not* run the system IRQ handler routine afterwards, 1 means run the system IRQ handler routine afterwards.
**CommanderX16 specific notes**
Note that for the CommanderX16 the "useKernal" parameter doesn't exists for the set_rasterirq() routine;
it will always disable the system IRQ handler (which also means the default sys.wait() routine won't work anymore)
Note that for the CommanderX16 the set_rasterirq() will disable VSYNC irqs and never call the system IRQ handler regardless
of the return value of the user handler routine. This also means the default sys.wait() routine won't work anymore,
when using this handler.
These two helper routines are not particularly suited to handle multiple IRQ sources on the Commander X16.
It's possible but it requires correct fiddling with IRQ enable bits, acknowledging the IRQs, and properly calling
or not calling the system IRQ handler routine.
The Commander X16 syslib provides two additional routines that should be used *in your IRQ handler routine* if it uses the Vera registers.
They take care of saving and restoring the Vera state of the interrupted main program, otherwise the IRQ handler's manipulation

View File

@ -2,7 +2,7 @@
TODO
====
- IRQ callback should return boolean to tell Prog8 to call the kernal ISR or not.
- use TRB/TSB instructions more on the x16 such as when ack vera irq bits
- [on branch: shortcircuit] investigate McCarthy evaluation again? this may also reduce code size perhaps for things like if a>4 or a<2 ....

View File

@ -23,7 +23,7 @@ main {
c64.SCROLX &= %11110111 ; 38 column mode
sys.set_rasterirq(&irq.irqhandler, 200, false) ; enable animation via raster interrupt
sys.set_rasterirq(&irq.irqhandler, 200) ; enable animation via raster interrupt
ubyte target_height = 10
ubyte active_height = 24
@ -130,10 +130,11 @@ spritedata $0f00 {
irq {
ubyte smoothx=0
sub irqhandler() {
sub irqhandler() -> bool {
smoothx = (smoothx-1) & 7
main.perform_scroll = smoothx==7
c64.SCROLX = (c64.SCROLX & %11111000) | smoothx
return false
}
}

View File

@ -6,7 +6,7 @@ main {
sub start() {
txt.print("playing the music from boulderdash,\nmade in 1984 by peter liepa.\n\n")
sys.set_rasterirq(&irq.irqhandler, 60, true) ; enable playback via raster irq
sys.set_rasterirq(&irq.irqhandler, 60) ; enable playback via raster irq
}
}
@ -15,7 +15,7 @@ irq {
ubyte note_index = 0
ubyte delay = 0
sub irqhandler() {
sub irqhandler() -> bool {
c64.EXTCOL++
delay++
if delay >= 8 {
@ -41,6 +41,7 @@ irq {
}
c64.EXTCOL--
return true
}
; details about the boulderdash music can be found here:

View File

@ -5,7 +5,7 @@ main {
sub start() {
c64.SCROLY &= %11101111 ; blank the screen
sys.set_rasterirq(&irq.irqhandler, 40, false) ; register exclusive raster irq handler
sys.set_rasterirq(&irq.irqhandler, 40) ; register exclusive raster irq handler
repeat {
; enjoy the moving bars :)
@ -22,7 +22,7 @@ irq {
ubyte color = 0
ubyte yanim = 0
sub irqhandler() {
sub irqhandler() -> bool {
if color!=len(colors) {
c64.EXTCOL = colors[color]
c64.RASTER += barheight ; next raster Irq for next color
@ -35,5 +35,6 @@ irq {
c64.RASTER = math.sin8u(yanim)/2+30 ; new start of raster Irq
}
c64.SCROLY &= $7f ; set high bit of the raster pos to zero
return false
}
}

View File

@ -46,14 +46,14 @@ main {
}
c64.SPENA = 255 ; enable all sprites
sys.set_rasterirq(&irq.irqhandler, 255, true) ; enable animation
sys.set_rasterirq(&irq.irqhandler, 255) ; enable animation
}
}
irq {
sub irqhandler() {
sub irqhandler() -> bool {
c64.EXTCOL--
; float up & wobble horizontally
@ -68,6 +68,7 @@ irq {
}
c64.EXTCOL++
return true
}
}

View File

@ -38,7 +38,7 @@ main {
c64.set_sprite_ptr(i, $0a00) ; alternatively, set directly: c64.SPRPTR[i] = $0a00 / 64
}
c64.SPENA = 255 ; enable all sprites
sys.set_rasterirq(&irq.irqhandler, 230, true) ; enable animation
sys.set_rasterirq(&irq.irqhandler, 230) ; enable animation
}
}
@ -47,7 +47,7 @@ irq {
ubyte angle1=200
ubyte angle2=0
sub irqhandler() {
sub irqhandler() -> bool {
angle1 += 2
angle2 += 3
c64.MSIGX=0
@ -61,5 +61,6 @@ irq {
if msb(x) c64.MSIGX++
}
c64.EXTCOL-=8
return true
}
}

View File

@ -7,7 +7,7 @@ main {
sub explosion() {
; this subroutine is not used but it is an example of how to make a sound effect using the psg library!
psg.silent()
sys.set_irq(&psg.envelopes_irq, true)
sys.set_irq(&psg.envelopes_irq)
psg.voice(0, psg.LEFT, 0, psg.NOISE, 0)
psg.voice(1, psg.RIGHT, 0, psg.NOISE, 0)
psg.freq(0, 1000)
@ -59,7 +59,7 @@ main {
psg.silent()
psg.voice(0, psg.LEFT, 63, psg.TRIANGLE, 0)
psg.voice(1, psg.RIGHT, 63, psg.TRIANGLE, 0)
sys.set_irq(&psg.envelopes_irq, true)
sys.set_irq(&psg.envelopes_irq)
repeat {
uword note

View File

@ -679,7 +679,7 @@ sound {
sub init() {
cx16.vpoke(1, $f9c2, %00111111) ; volume max, no channels
psg.silent()
sys.set_irq(&psg.envelopes_irq, true)
sys.set_irq(&psg.envelopes_irq)
}
sub blockrotate() {

View File

@ -59,7 +59,7 @@ zsound_lib:
pcm_init()
pcm_trigger_digi(digi_bank, digi_address)
sys.set_irq(&zsm_playroutine_irq, true)
sys.set_irq(&zsm_playroutine_irq)
txt.print("\nstreaming from file, playback in irq!\n")
uword size = 1
@ -79,7 +79,8 @@ zsound_lib:
pcm_stop() ;unreached
}
sub zsm_playroutine_irq() {
sub zsm_playroutine_irq() -> bool {
pcm_play()
return true
}
}

View File

@ -1,10 +1,21 @@
%import palette
%import textio
%import syslib
%zeropage basicsafe
main {
sub start() {
sys.save_prog8_internals()
txt.print("ok\n")
sys.restore_prog8_internals()
sys.set_rasterirq(&handler, 200)
txt.print("installed\n")
}
sub handler() -> bool {
palette.set_color(0, $f00)
repeat 1000 {
cx16.r0++
}
palette.set_color(0, $000)
return true
}
}