This is not a trivial task, either I leave it up to the programmer to insert tickMidi() and tickAudio calls in every processor intensive routine, (which is what I did in Tetronis, not fun), or I build in a seamless system that does it for you automatically, (which I have done).
So currently every intensive tight loop in the runtime, (mostly graphics stuff, busy waits, etc), has a call to a stub routine which by default is just a RET. Calling functions like PLAY MIDI <address> will insert the appropriate runtime function's address into this stub and voila you have seamless time-slicing of real time critical routines.
Ok, that's all well and good, but there's no free lunch and there are some drawbacks:
- it costs cycles even when the stub routine is just a RET.
- if the user's code itself is processor intensive without calling any runtime functions, then they need to insert appropriate TICK MIDI/AUDIO calls in their loops.
- every new non trivial runtime routine needs to have this architecture built into it.
Well, specifically, one vertical blank interrupt for vCPU code built into the ROM; how would it be done and what would be required?
- 2 bytes in zero page allocated for user VBLANK address.
- Native code that runs at vertical blank that saves vPC into vLR and saves vAC, (maybe even vTMP?), on the stack.
- Native code that copies VBLANK address to vPC and calls dispatch.
- Native code that restores vPC from vLR, etc etc
Does anyone have thoughts, ideas, additions? Obviously we could rely on Marcel to do everything when it comes to Native code, or we could help push it in a community driven direction.