sverx/devkitSMS

Ability to install a vblank handler

DUSTINODELLOFFICIAL opened this issue · 7 comments

It would be nice to have a SMS_setVerticalInterruptHandler() to install a callback that would run every vblank, similar to the way line interrupts work.

sverx commented

Theoretically, yes.
Unfortunately this would break everything else, as the current vblank handler handles the vblank flag and reads the inputs.
Your best bet is to have your code run right after the SMS_waitForVBlank, you'll still be in vblank.
Otherwise, you can always replace the library provided handler with our own handler.

Recently I was also thinking of requesting or implementing something like this. Similar to what SMS_setLineInterruptHandler (void (*theHandlerFunction)(void)) does, but for vblank.

The current handler in SMSlib.c could still do everything it does (set the flag, read the inputs) but at the end, if a user provided function pointer is not NULL, it would then call it. I don't think anything would break?

Here is my use case. So usually I update the SAT, update tiles and tilemap right after calling SMS_waitForVBlank(). But in one of my project I have a problem. I am running rather complex random level generation code, which take several frames to complete. This causes noticeable pauses/slow downs in the music. So before starting this long operation, I would like to hook an interrupt handler which would take care of calling the PSG frame function. (BY the way, my music data is accessed through slot 2, so here's another nice use for SAVE/RESTORE BANK we are discussing in issue #28 )

The only alternative I see is periodically checking the vblank flag myself to call PSG_frame, but this is not very practical. If done too often, I am slowing down an already slow operation... And it adds unrelated code to the level generation code. So having this done using interrupts would be great!

sverx commented

This is indeed a real use case for both the vblank interrupt hook and the save/restore bank functionality.

Unfortunately saving the current bank in the interrupt routine could break the interrupted code if that was using the same save/restore banks functionality, provided we don't have a real push/pop stack for the banks since the bank save is implemented with a single variable.

So my point is - if we add this hook functionality and the bank save/restore functionality then we must warn the users to make sure they either don't use the bank save/restore functionality in the custom routine or they don't use it in the code that could be interrupted by a custom routine using that.

Or we should implement two set of macros, one for regular processing and one for interrupt, with separate variables.

Your thoughts on this?

If there is only one version of the macro which uses a local variable as I suggest, I don't think there is a problem. Each use of SAVEBANK() will store the current bank in a different location. Provided that RESTOREBANK() is not omitted in the interrupt handler, the code running in non-interrupt context will never know that the bank was momentarily changed.

Or is there a race I don't see?

sverx commented

My fault, the global variable version of this was stuck in my head. Sorry!

I created pull request #31 for this feature.

sverx commented

It would be nice to have a SMS_setVerticalInterruptHandler() to install a callback that would run every vblank, similar to the way line interrupts work.

SMS_setFrameInterruptHandler (void (*theHandlerFunction)(void)) added, thanks to raphnet's great work 😃

use it to trigger your own function at next vblank by setting it to your function address:

SMS_setFrameInterruptHandler (your_vblank_function);

turn it off it by setting it to NULL:

SMS_setFrameInterruptHandler (NULL);