cx16: optimized sys.set_rasterline()

This commit is contained in:
Irmen de Jong 2023-11-22 23:40:44 +01:00
parent 1b2296ad5b
commit 98570ac456
4 changed files with 66 additions and 24 deletions

View File

@ -854,7 +854,7 @@ asmsub restore_vera_context() clobbers(A) {
; Commander X16 IRQ dispatcher routines ; Commander X16 IRQ dispatcher routines
inline asmsub disable_vera_irqs() clobbers(A) { inline asmsub disable_irqs() clobbers(A) {
; Disable all Vera IRQ sources. Note that it does NOT set the CPU IRQ disabled status bit! ; Disable all Vera IRQ sources. Note that it does NOT set the CPU IRQ disabled status bit!
%asm {{ %asm {{
lda #%00001111 lda #%00001111
@ -863,9 +863,9 @@ inline asmsub disable_vera_irqs() clobbers(A) {
} }
asmsub enable_irq_handlers(bool disable_all_irq_sources @Pc) clobbers(A,Y) { asmsub enable_irq_handlers(bool disable_all_irq_sources @Pc) clobbers(A,Y) {
; Install the "master IRQ handler" that will dispatch IRQs. ; Install the "master IRQ handler" that will dispatch IRQs
; to the registered handler for each type. (Only Vera IRQs supported for now). ; to the registered handler for each type. (Only Vera IRQs supported for now).
; The handlers don't need to clear its ISR bit, but have to return 0 or 1 in A: ; The handlers don't need to clear its ISR bit, but have to return 0 or 1 in A,
; where 1 means: continue with the system IRQ handler, 0 means: don't call that. ; where 1 means: continue with the system IRQ handler, 0 means: don't call that.
%asm {{ %asm {{
php php
@ -1007,10 +1007,10 @@ asmsub set_aflow_irq_handler(uword address @AY) clobbers(A) {
} }
asmsub disable_irq_handlers() { inline asmsub disable_irq_handlers() {
; back to the system default IRQ handler. ; back to the system default IRQ handler.
%asm {{ %asm {{
jmp sys.restore_irq jsr sys.restore_irq
}} }}
} }
@ -1189,15 +1189,15 @@ asmsub set_rasterline(uword line @AY) {
php php
sei sei
sta cx16.VERA_IRQLINE_L sta cx16.VERA_IRQLINE_L
lda cx16.VERA_IEN
and #%01111111
sta cx16.VERA_IEN
tya tya
lsr a lsr a
ror a bcs +
and #%10000000 lda #%10000000
ora cx16.VERA_IEN trb cx16.VERA_IEN
sta cx16.VERA_IEN plp
rts
+ lda #%10000000
tsb cx16.VERA_IEN
plp plp
rts rts
}} }}

View File

@ -138,7 +138,7 @@ IRQ Handling
Normally, the system's default IRQ handling is not interfered with. Normally, the system's default IRQ handling is not interfered with.
You can however install your own IRQ handler (for clean separation, it is advised to define it inside its own block). You can however install your own IRQ handler (for clean separation, it is advised to define it inside its own block).
There are a few library routines available to make setting up C64 60hz IRQs and Raster IRQs a lot easier (no assembly code required). There are a few library routines available to make setting up 60hz/vsync IRQs and raster/line IRQs a lot easier (no assembly code required).
These routines are:: These routines are::
@ -146,7 +146,7 @@ These routines are::
sys.set_rasterirq(uword handler_address, uword rasterline) sys.set_rasterirq(uword handler_address, uword rasterline)
sys.restore_irq() ; set everything back to the systems default irq handler 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. 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. 0 means do *not* run the system IRQ handler routine afterwards, 1 means run the system IRQ handler routine afterwards.
@ -158,9 +158,10 @@ when using this handler.
These two helper routines are not particularly suited to handle multiple IRQ sources on the Commander X16. 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 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. or not calling the system IRQ handler routine. See the section below for perhaps a better and easier solution that
is tailored to this system.
The Commander X16 syslib provides two additional routines that should be used *in your IRQ handler routine* if it uses the Vera registers. The Commander X16 syslib provides some 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 They take care of saving and restoring the Vera state of the interrupted main program, otherwise the IRQ handler's manipulation
will corrupt any Vera operations that were going on in the main program. The routines are:: will corrupt any Vera operations that were going on in the main program. The routines are::
@ -184,3 +185,42 @@ will corrupt any Vera operations that were going on in the main program. The rou
of corrupting variables and floating point calculations that are being executed of corrupting variables and floating point calculations that are being executed
in the interrupted main program. These memory locations should be backed up in the interrupted main program. These memory locations should be backed up
and restored at the end of the handler, further increasing its execution time... and restored at the end of the handler, further increasing its execution time...
Commander X16 specific IRQ handling
===================================
Instead of using the routines in `sys` as mentioned above (that are more or less portable
across the C64,C128 and cx16), you can also use the special routines made for the Commander X16,
in `cx16`. The idea is to let Prog8 do the irq dispatching and housekeeping for you, and that
your program only has to register the specific handlers for the specific IRQ sources that you want to handle.
Look at the examples/cx16/multi-irq-new.p8 example to see how these routines can be used.
Here they are, all available in `cx16`:
``disable_irqs ()``
Disables all Vera IRQ sources. Note that the CPU irq disable flag is not changed by this routine.
you can manipulate that via ``sys.set_irqd()`` and ``sys.clear_irqd()`` as usual.
``enable_irq_handlers (bool disable_all_irq_sources)``
Install the "master IRQ handler" that will dispatch IRQs to the registered handler for each type.
Only Vera IRQs supported for now.
The handlers don't need to clear its ISR bit, but have to return 0 or 1 in A,
where 1 means: continue with the system IRQ handler, 0 means: don't call that.
``set_vsync_irq_handler (uword address)``
Sets the verical sync interrupt handler routine. Also enables VSYNC interrupts.
``set_line_irq_handler (uword rasterline, uword address)``
Sets the rasterline interrupt handler routine to trigger on the specified raster line.
Also enables LINE interrupts.
You can use ``sys.set_rasterline()`` later to adjust the rasterline on which to trigger.
``set_sprcol_irq_handler (uword address)``
Sets the sprite collision interrupt handler routine. Also enables SPRCOL interrupts.
``set_aflow_irq_handler (uword address)``
Sets the audio buffer underrun interrupt handler routine. Also enables AFLOW interrupts.
``disable_irq_handlers ()``
Hand control back to the system default IRQ handler.

View File

@ -2,9 +2,6 @@
TODO TODO
==== ====
- optimize sys.set_rasterline on X16
- document new x16 irq handling stuff in docs
- use TRB/TSB instructions more on the x16 such as when ack vera irq bits cx16.VERA_ISR |= 4 - use TRB/TSB instructions more on the x16 such as when ack vera irq bits cx16.VERA_ISR |= 4
xx |= %0001000, xx &= %1110111 xx |= %0001000, xx &= %1110111

View File

@ -3,14 +3,19 @@
%import syslib %import syslib
%zeropage basicsafe %zeropage basicsafe
; Example that shows a way to handle multiple IRQ sources on the X16.
; This uses the "OLD" way using the interrupt handler routines in sys.
; (see multi-irq-new example to do it the "new" way)
; Currently only Vera interrupts are supported. VIA irqs are an exercise for the reader.
main { main {
sub start() { sub start() {
sys.set_rasterline(150) sys.set_rasterline(150)
sys.set_irq(&irq.master_handler) sys.set_irq(&irq.master_handler) ; ..will just enable vsync..
cx16.VERA_IEN |= 2 ; also enable line irq cx16.VERA_IEN |= 2 ; .. so also enable line irq here.
txt.print("\n\n\nisr installed\n") txt.print("\n\n\nx16 irq handlers installed (old style)\n")
txt.print("red = vsync\n") txt.print("red = vsync irq\n")
txt.print("green = first line irq\n") txt.print("green = first line irq\n")
txt.print("blue = second line irq\n") txt.print("blue = second line irq\n")
} }
@ -18,7 +23,7 @@ main {
irq { irq {
sub master_handler() -> bool { sub master_handler() -> bool {
ubyte irqsrc = cx16.VERA_ISR ubyte irqsrc = cx16.VERA_ISR & cx16.VERA_IEN ; only consider sources that are enabled
ror(irqsrc) ror(irqsrc)
if_cs { if_cs {
vsync_irq() vsync_irq()