From 08ac459a41ee40b7069b6f663ba5ba19f0bb0a17 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Tue, 21 Nov 2023 22:33:37 +0100 Subject: [PATCH] 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. --- compiler/res/prog8lib/c128/syslib.p8 | 28 ++++++++------------ compiler/res/prog8lib/c64/syslib.p8 | 34 ++++++++++--------------- compiler/res/prog8lib/cx16/psg.p8 | 5 ++-- compiler/res/prog8lib/cx16/syslib.p8 | 15 +++++------ docs/source/targetsystem.rst | 17 ++++++++++--- docs/source/todo.rst | 2 +- examples/c64/balloonflight.p8 | 5 ++-- examples/c64/bdmusic-irq.p8 | 5 ++-- examples/c64/rasterbars.p8 | 5 ++-- examples/c64/sprites.p8 | 5 ++-- examples/c64/wizzine.p8 | 5 ++-- examples/cx16/bdmusic.p8 | 4 +-- examples/cx16/tehtriz.p8 | 2 +- examples/cx16/zsound/stream-test-zcm.p8 | 5 ++-- examples/test.p8 | 17 ++++++++++--- 15 files changed, 82 insertions(+), 72 deletions(-) diff --git a/compiler/res/prog8lib/c128/syslib.p8 b/compiler/res/prog8lib/c128/syslib.p8 index 9a983d6ef..c2cdfef6d 100644 --- a/compiler/res/prog8lib/c128/syslib.p8 +++ b/compiler/res/prog8lib/c128/syslib.p8 @@ -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 diff --git a/compiler/res/prog8lib/c64/syslib.p8 b/compiler/res/prog8lib/c64/syslib.p8 index 6252db650..28da385f3 100644 --- a/compiler/res/prog8lib/c64/syslib.p8 +++ b/compiler/res/prog8lib/c64/syslib.p8 @@ -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 diff --git a/compiler/res/prog8lib/cx16/psg.p8 b/compiler/res/prog8lib/cx16/psg.p8 index 55fb4cd9f..c2773215d 100644 --- a/compiler/res/prog8lib/cx16/psg.p8 +++ b/compiler/res/prog8lib/cx16/psg.p8 @@ -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 diff --git a/compiler/res/prog8lib/cx16/syslib.p8 b/compiler/res/prog8lib/cx16/syslib.p8 index d79d4746e..a6a1db607 100644 --- a/compiler/res/prog8lib/cx16/syslib.p8 +++ b/compiler/res/prog8lib/cx16/syslib.p8 @@ -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 }} diff --git a/docs/source/targetsystem.rst b/docs/source/targetsystem.rst index 47ed45290..54a2acfa9 100644 --- a/docs/source/targetsystem.rst +++ b/docs/source/targetsystem.rst @@ -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 diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 4eda356b6..ae221d70c 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -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 .... diff --git a/examples/c64/balloonflight.p8 b/examples/c64/balloonflight.p8 index 5086186df..27a5bc397 100644 --- a/examples/c64/balloonflight.p8 +++ b/examples/c64/balloonflight.p8 @@ -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 } } diff --git a/examples/c64/bdmusic-irq.p8 b/examples/c64/bdmusic-irq.p8 index 5abc1b090..ecc6888bc 100644 --- a/examples/c64/bdmusic-irq.p8 +++ b/examples/c64/bdmusic-irq.p8 @@ -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: diff --git a/examples/c64/rasterbars.p8 b/examples/c64/rasterbars.p8 index 4dc1b51b3..f319909d3 100644 --- a/examples/c64/rasterbars.p8 +++ b/examples/c64/rasterbars.p8 @@ -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 } } diff --git a/examples/c64/sprites.p8 b/examples/c64/sprites.p8 index ffa87c5ef..48a9a00ad 100644 --- a/examples/c64/sprites.p8 +++ b/examples/c64/sprites.p8 @@ -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 } } diff --git a/examples/c64/wizzine.p8 b/examples/c64/wizzine.p8 index 06ac80079..9c18a9cd3 100644 --- a/examples/c64/wizzine.p8 +++ b/examples/c64/wizzine.p8 @@ -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 } } diff --git a/examples/cx16/bdmusic.p8 b/examples/cx16/bdmusic.p8 index 4fea29576..b8dafa9fb 100644 --- a/examples/cx16/bdmusic.p8 +++ b/examples/cx16/bdmusic.p8 @@ -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 diff --git a/examples/cx16/tehtriz.p8 b/examples/cx16/tehtriz.p8 index f8df0fceb..c9a3db486 100644 --- a/examples/cx16/tehtriz.p8 +++ b/examples/cx16/tehtriz.p8 @@ -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() { diff --git a/examples/cx16/zsound/stream-test-zcm.p8 b/examples/cx16/zsound/stream-test-zcm.p8 index 941bd1aae..94d3fafe3 100644 --- a/examples/cx16/zsound/stream-test-zcm.p8 +++ b/examples/cx16/zsound/stream-test-zcm.p8 @@ -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 } } diff --git a/examples/test.p8 b/examples/test.p8 index 3cb13a50a..7944fc55d 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -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 } }