The vblank interrupt triggers every 1/60 second. Using the following function:
Code: Select all
int sceKernelRegisterSubIntrHandler(int intno, int no, void *handler, void *arg);
Code: Select all
void vblank_handler(int sub, void* arg);
Code: Select all
enabled = 0 / 1 -> disabled / enabled
calls = number of times handler has been called since registration
intr_code = interrupt number, e.g. 0x1e = PSP_VBLANK_INT
common = "common" parameter pass during handler registration
entry = handler function pointer
intr_level = 3 (?)
PSP_SYSTIMER(N)_INT
Calls to register or enable on these interrupts always yield 0x80020065 (illegal intr code), which seems plausible if they are system interrupts. QueryIntrHandlerInfo yields the following interesting information:
Code: Select all
min_clock_low = 0xFFFFFFFF
min_clock_hi = 0xFFFFFFFF
max_clock_low = 0x00000000
max_clock_hi = 0x00000000
enabled = always 0
gp = 0x88052FB0
entry = 0x8804A4E2
common = 0x8804AF30 for timer #0, (#1 -> AF50, #2 -> AF70, #3 -> AF90)
VTimers
VTimers are configurable virtual timers that are called from system interrupts, possibly PSP_SYSTIMER(N)_INT. sceKernelCreateVTimer returns the UID of a new timer. I managed to create 1300 timers before my PSP asploded, but I didn't try to use them all. The upper limit may be imposed by the size of the UID table. Timer resolution is in microseconds and calling sceKernelGetVTimerTime before the timer has started returns 0. Each timer can be started using the sceKernelStartVTimer using the UID returned from sceKernelCreateVTimer.
The sceKernelSetVTimerHandler function is used to register a handler with the timer. In user mode, simply pass in the address of the function. When called from kernel mode, the handler seems to be required to reside in kernel space (> 0x80000000) otherwise registration fails with a return code of 0x800200D3 (illegal address). Adding 0x80000000 to the address of the handler seems to work well. Kernel mode can be detected by checking the "attr" field of the current thread's info struct.
When registering the timer, the "time" parameter indicates the period before the handler is triggered (assuming the timer is started from zero)
The handler prototype is:
Code: Select all
SceUInt vtimer_handler(SceUID uid, SceKernelSysClock* requested, SceKernelSysClock* actual, void* common);
btw, this research was sponsored by psplink :)