I'm revisiting an old problem I had with interrupts, maybe somebody can explain what's going on.
To my knowledge when an interrupt is generated, it has to be acknowledged - the SCU doesn't auto-acknowledge interrupts.
Based on the first SCU manual, you have these:
$25FE00A0 - Interrupt mask register. Write '0' in a bit position to enable an interrupt source, write '1' to disable it.
OK, so I can set it to something like $0000BFFE to enable the V-Blank IN interrupt only.
$25FE00A4 - Interrupt status register. Read to return interrupt status, write '0' to acknowledge (they say 'reset') interrupt source, writing '1' does nothing.
To my understanding within an interrupt handler I'd write something like $FFFFFFFE to acknowledge the V-Blank IN interrupt source only.
Of course there's a catch:
Writing to the interrupt status register does nothing. In fact the system gets all crazy because the interrupt isn't really acknowledged. Furthermore the updated SCU manual says not to write to it.
What I had done in my timer 0/1 example program was to re-write the original value last set to the interrupt mask register (to keep the interrupts I wanted enabled) which seemed to acknowledge interrupts too. So I'd re-write $0000BFFE to keep the V-Blank IN interrupt enabled and automagically acknowledge it at the same time.
I'd like to know what's really going on in respect to how interrupts are handled by the system, and what I need to do on my end to properly acknowledge an interrupt. If anyone has looked at commercial games in an emulator or debugger, what do they do?
The other thing I'm interested in is how to call a "C" function from assembly code. I'm assuming to tie a "C" function to an interrupt, I'll need to have a stub function in assembly to save all the registers that GCC won't normally save, then call the function (just void foobar(void); in this case, no parameters) and return.
For performance reasons I want to push the registers GCC will trash, how do I know what they are? Or do I really have to push every single one?
To my knowledge when an interrupt is generated, it has to be acknowledged - the SCU doesn't auto-acknowledge interrupts.
Based on the first SCU manual, you have these:
$25FE00A0 - Interrupt mask register. Write '0' in a bit position to enable an interrupt source, write '1' to disable it.
OK, so I can set it to something like $0000BFFE to enable the V-Blank IN interrupt only.
$25FE00A4 - Interrupt status register. Read to return interrupt status, write '0' to acknowledge (they say 'reset') interrupt source, writing '1' does nothing.
To my understanding within an interrupt handler I'd write something like $FFFFFFFE to acknowledge the V-Blank IN interrupt source only.
Of course there's a catch:
Writing to the interrupt status register does nothing. In fact the system gets all crazy because the interrupt isn't really acknowledged. Furthermore the updated SCU manual says not to write to it.
What I had done in my timer 0/1 example program was to re-write the original value last set to the interrupt mask register (to keep the interrupts I wanted enabled) which seemed to acknowledge interrupts too. So I'd re-write $0000BFFE to keep the V-Blank IN interrupt enabled and automagically acknowledge it at the same time.
I'd like to know what's really going on in respect to how interrupts are handled by the system, and what I need to do on my end to properly acknowledge an interrupt. If anyone has looked at commercial games in an emulator or debugger, what do they do?
The other thing I'm interested in is how to call a "C" function from assembly code. I'm assuming to tie a "C" function to an interrupt, I'll need to have a stub function in assembly to save all the registers that GCC won't normally save, then call the function (just void foobar(void); in this case, no parameters) and return.
For performance reasons I want to push the registers GCC will trash, how do I know what they are? Or do I really have to push every single one?