CFW framework for PS Vita
Here are a couple of examples that demonstrate how to use the taiHEN APIs.
Configure the following user plugin to load on an application named "AppName" with the title id "ABCD01234".
We can build this as
myplugin.suprx and add it to
ux0:tai/config.txt under the section
*ABCD01234 and it will be loaded when
ABCD01234 is started and insert the hook.
The following example will log all file opens from applications. Compile it as
kernellog.skprx and add to
*KERNEL section in
Consider one kernel plugin with the code above. Now consider a second kernel plugin as follows.
Now we have both filesystem filtering and logging.
This plugin will be loaded in kernel and changes the return value of a function that does a check to enable dynarec.
The above examples are all global hooks: every call regardless of origin will be hooked. You can also insert local hooks: a library import from a module. In this example, we have a user plugin loaded with "AppName" that only logs
sceIoOpen calls from that application.
Below are some common tasks and paradigms that might be of interest to people writing advanced hooks.
Currently taiHEN does not support hooking the exports of shared libraries (or the imports from shared libraries). Shared libraries are ones loaded in the
0xE0000000 address range and are mainly in modules that most applications import from (example being
SceGxm). You can, however, hook imports of shared libraries as usual. So, if multiple non-shared modules import a function of interest, you must hook all of them (if desired).
Weak imports are imports of modules not loaded at application startup and are loaded by
SceLibKernel) or some other function. They typically are loaded on-demand and unloaded when no longer needed to save memory. That means that your hooks must be created after the module is loaded and removed before the module is unloaded. To do this, you have to first hook the module load and unload imports and in those hooks, you create/remove the desired hook. In this example, we wish to hook
sceScreenShotDisable which is loaded by the game from
You can specify
suprx to load with specific titles, but you cannot do so with
skprx. This is a limitation of the Vita kernel. A workaround is to use the taiHEN APIs to manually load and unload the kernel module directly. Please note this feature only works with unsafe homebrew enabled. Be aware that
module_stop of your user plugin is not automatically called so you should not use that to cleanup your kernel plugin. Instead, your kernel plugin's
module_start can return
SCE_KERNEL_START_NO_RESIDENT to be cleaned up automatically after running. In the case that it is not possible, you should be careful not to load the same kernel module twice.
It it important to remember to always clean up hooks and injections in
module_stop for kernel modules. You should be doing this for user modules as well, but patches in user-space will be cleaned up by taiHEN when the process exits. Patches in kernel will not be cleaned up automatically.
When writing a kernel module that exposes new syscalls, know that the syscall stack is only 4096 bytes. That means you might easily run out of space. You should use
sceKernelRunWithStack to increase the stack size if needed.
By default, the Vita does not allow unloading modules that exposes syscalls (you will get
SCE_KERNEL_ERROR_MODULEMGR_IN_USE). To get around this, you can hook an override function in the module manager. This hook will be released when the module is unloaded.
There is currently a bug in the implementation where a crash may happen if you are hooking a function while it is being used. Usually this doesn't happen (except by chance), but some functions might be called in a tight loop. A temporary workaround is listed in the issue tracker.