Page 1 of 2
Using the WAI instruction correctly
Posted: Mon Mar 20, 2023 5:20 pm
by grml
I have this code (64tass) and I would expect it to print
ABABABABAB...
, but it only prints
A
once and nothing else happens.
Not installing the irq_handler and letting the default CINV routine run gives the desired result. What is wrong with my
irq_handler, or what is wrong with my understanding of the WAI instruction?
Code: Select all
.cpu 'w65c02'
CHROUT = $ffd2
CINV = $0314
* = $0801
.word (+)
.text 0, 0, $9e, format("%d", hello), 0
+ .word 0
hello .proc
sei
; removing this makes it work
lda <#irq_handler
sta CINV
lda >#irq_handler
sta CINV+1
_loop:
lda #'A'
jsr CHROUT
cli ; allow irqs
wai ; wait for irq to happen
; we continue to execute here after the next RTI
sei ; don't allow irqs
lda #'B'
jsr CHROUT
bra _loop
.pend
irq_handler .proc
ply
plx
pla
rti
.pend
Re: Using the WAI instruction correctly
Posted: Mon Mar 20, 2023 5:57 pm
by DragWx
You need to tell the VERA that you've acknowledged its interrupt, or else it'll just continually trigger that same IRQ over and over (i.e., running your irq handler in an endless loop), preventing your main code from ever advancing.
The kernal enables only the VSYNC interrupt by default, so try acknowledging it by writing #$01 to $9F27 in your IRQ handler.
Re: Using the WAI instruction correctly
Posted: Mon Mar 20, 2023 6:24 pm
by grml
Yep, that's it. Thanks!
Re: Using the WAI instruction correctly
Posted: Mon Mar 20, 2023 6:36 pm
by grml
And just to make sure I didn't miss something: CINV is the only way hook into interrupts; the vector at $fffe can't be changed because it's always in ROM. If you want to use interrupts, you must make sure $314/$315 contains a valid function pointer. These are hardcoded, constant addresses.
Is that correct? (ignoring NMI completely, only IRQ is relevant)
Re: Using the WAI instruction correctly
Posted: Mon Mar 20, 2023 7:33 pm
by DragWx
Yes, modifying the CINV vector is the only way to supply your own IRQ handler (and there's no way to bypass the short "preamble" baked into the kernal rom), so always make sure it points to a valid IRQ handler or else Fun Stuff™ happens.
Also of note, the CINV vector's memory address is part of the C64's original API, so I think it's safe to always count on it being the same between kernal revisions.
Re: Using the WAI instruction correctly
Posted: Tue Mar 21, 2023 5:10 pm
by StephenHorn
DragWx wrote: ↑Mon Mar 20, 2023 7:33 pm
Yes, modifying the CINV vector is the only way to supply your own IRQ handler (and there's no way to bypass the short "preamble" baked into the kernal rom), so always make sure it points to a valid IRQ handler or else Fun Stuff™ happens.
Also of note, the CINV vector's memory address is part of the C64's original API, so I think it's safe to always count on it being the same between kernal revisions.
This is mostly true, and likely to be completely true as of hardware revision 2.
tl;dr: If you want the all the ugly details, keep reading, otherwise just assume that CINV is the only way to implement IRQs, and that CINV will be always invoked with the ROM bank set to 0.
At present, the kernal and BASIC ROM banks (0 and 4, respectively) have handlers for IRQs baked into them, but not all ROM banks have the interrupt vectors or logic. If other ROM banks are selected, this means allowing an IRQ to occur may result in a system crash.
If you explore cartridges, their memory uses the same address region as ROM banks, and as a result they can currently implement their own IRQ handling logic, even bypassing the kernal's default preamble. Simply make sure the appropriate cartridge bank is selected when the IRQ occurs.
But be aware that this behavior is likely to change in the future.
That having been said, and looking towards the future, Wavicle seems likely to take over the hardware design of the X16 for the gen-2 hardware, and he strongly wants to add a feature that would force the X16 to always reference bank 0 for interrupts. There are good technical reasons for this, particularly when it comes to interrupts that may happen early in the boot process and create race conditions. As far as the kernal is concerned, we're confident enough that this hardware change will occur to have already changed the kernal preamble to account for this change. If/when this change occurs, it would also mean that cartridges could no longer implement their own whole-cloth interrupt handlers, requiring them to go through CINV, and CINV would always execute with the current ROM bank set to 0.
Re: Using the WAI instruction correctly
Posted: Tue Mar 21, 2023 5:29 pm
by grml
"We're adding one RAM bank to the ROM space so you can do whatever the hell you want" would have made me happier.
Re: Using the WAI instruction correctly
Posted: Tue Mar 21, 2023 5:44 pm
by StephenHorn
grml wrote: ↑Tue Mar 21, 2023 5:29 pm
"We're adding one RAM bank to the ROM space so you can do whatever the hell you want" would have made me happier.
Well, the cartridge feature in the emulator will let you do exactly that right now, if that's your wish. Author a cartridge with
makecart and load it with
-cart, or make an empty 3.5MB file and load it with
-cartbin. Proceed to enjoy your memory.
Nevertheless, Gen-2 is likely to change the IRQ behavior as described.
Re: Using the WAI instruction correctly
Posted: Tue Mar 21, 2023 6:23 pm
by BruceRMcF
StephenHorn wrote: ↑Tue Mar 21, 2023 5:10 pm ... Wavicle seems likely to take over the hardware design of the X16 for the gen-2 hardware, and he strongly wants to add a feature that would force the X16 to always reference bank 0 for interrupts. There are good technical reasons for this, particularly when it comes to interrupts that may happen early in the boot process and create race conditions. ...
I would very much like this for any ROM based Forth system, as my approach for defining and combining modules for additional ROM banks is looking toward a "smallest power of two" package with manual fitting together of pieces -- 2^(7+index) where index runs from 0 to 6 for RAM segment modules, 0 to 7 for ROM segment modules ... 128, 256, 512, 1KB, 2KB, 4KB, 8KB, [16KB, ROM only] ... and not having to fit IRQ support into the top page of the ROM segment would substantially simplify module packaging.
Re: Using the WAI instruction correctly
Posted: Tue Mar 21, 2023 6:34 pm
by Yazwho
Wavicle seems likely to take over the hardware design of the X16 for the gen-2 hardware, and he strongly wants to add a feature that would force the X16 to always reference bank 0 for interrupts.
Thats really disappointing. Having the ability to remove the kernel completely and construct your own is one of the most exciting features of the 'cartridge'.
Constricting devs to whatever happens in the Kernel's handler feels awful. It hamstrings projects from the get go. If you're writing things for a cartridge you should understand how the system works, so what is needed is better documentation and tooling. Then we don't need to coddle developers.