merging Electry's changes so pspemu also works
This commit is contained in:
commit
eb898d9cbb
3
.gitignore
vendored
3
.gitignore
vendored
@ -45,3 +45,6 @@ $RECYCLE.BIN/
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
|
||||
# Build directory
|
||||
build/
|
||||
|
231
app/index.lua
231
app/index.lua
@ -19,51 +19,114 @@ end
|
||||
tbl = System.listDirectory("ux0:/data/TrackPlug")
|
||||
|
||||
if tbl == nil then
|
||||
tbl = {}
|
||||
tbl = {}
|
||||
end
|
||||
|
||||
-- Convert a 32 bit binary string to an integer
|
||||
function bin2int(str)
|
||||
local b1, b2, b3, b4 = string.byte(str, 1, 4)
|
||||
return (b4 << 24) + (b3 << 16) + (b2 << 8) + b1
|
||||
local b1, b2, b3, b4 = string.byte(str, 1, 4)
|
||||
return bit32.lshift(b4, 24) + bit32.lshift(b3, 16) + bit32.lshift(b2, 8) + b1
|
||||
end
|
||||
|
||||
-- Format raw time data
|
||||
function FormatTime(val)
|
||||
local minutes = math.floor(val/60)
|
||||
local seconds = val%60
|
||||
local hours = math.floor(minutes/60)
|
||||
local minutes = minutes%60
|
||||
local res = ""
|
||||
if hours > 0 then
|
||||
res = hours .. "h "
|
||||
end
|
||||
if minutes > 0 then
|
||||
res = res .. minutes .. "m "
|
||||
end
|
||||
res = res .. seconds .. "s "
|
||||
return res
|
||||
local minutes = math.floor(val/60)
|
||||
local seconds = val%60
|
||||
local hours = math.floor(minutes/60)
|
||||
local minutes = minutes%60
|
||||
local res = ""
|
||||
if hours > 0 then
|
||||
res = hours .. "h "
|
||||
end
|
||||
if minutes > 0 then
|
||||
res = res .. minutes .. "m "
|
||||
end
|
||||
res = res .. seconds .. "s "
|
||||
return res
|
||||
end
|
||||
|
||||
-- Recover title from homebrew database
|
||||
function recoverTitle(tid)
|
||||
local file = System.openFile("ux0:/data/TrackPlugArchive/" .. tid .. ".txt", FREAD)
|
||||
fsize = System.sizeFile(file)
|
||||
local title = System.readFile(file, fsize)
|
||||
System.closeFile(file)
|
||||
return title
|
||||
local file = System.openFile("ux0:/data/TrackPlugArchive/" .. tid .. ".txt", FREAD)
|
||||
fsize = System.sizeFile(file)
|
||||
local title = System.readFile(file, fsize)
|
||||
System.closeFile(file)
|
||||
return title
|
||||
end
|
||||
|
||||
-- Extracts title name from an SFO file
|
||||
function extractTitle(file, tid)
|
||||
local data = System.extractSFO(file)
|
||||
if System.doesFileExist("ux0:/data/TrackPlugArchive/" .. tid .. ".txt") then
|
||||
System.deleteFile("ux0:/data/TrackPlugArchive/" .. tid .. ".txt")
|
||||
end
|
||||
local file = System.openFile("ux0:/data/TrackPlugArchive/" .. tid .. ".txt", FCREATE)
|
||||
System.writeFile(file, data.title, string.len(data.title))
|
||||
System.closeFile(file)
|
||||
return data.title
|
||||
local data = System.extractSfo(file)
|
||||
if System.doesFileExist("ux0:/data/TrackPlugArchive/" .. tid .. ".txt") then
|
||||
System.deleteFile("ux0:/data/TrackPlugArchive/" .. tid .. ".txt")
|
||||
end
|
||||
local file = System.openFile("ux0:/data/TrackPlugArchive/" .. tid .. ".txt", FCREATE)
|
||||
System.writeFile(file, data.title, string.len(data.title))
|
||||
System.closeFile(file)
|
||||
return data.title
|
||||
end
|
||||
|
||||
function getRegion(titleid)
|
||||
local regioncode = string.sub(titleid,1,4)
|
||||
local prefix = string.sub(regioncode,1,2)
|
||||
local region = "Unknown"
|
||||
|
||||
-- PSV common
|
||||
if regioncode == "PCSA" or regioncode == "PCSE" then
|
||||
region = "USA"
|
||||
elseif regioncode == "PCSB" or regioncode == "PCSF" then
|
||||
region = "Europe"
|
||||
elseif regioncode == "PCSC" or regioncode == "PCSG" then
|
||||
region = "Japan"
|
||||
elseif regioncode == "PCSD" or regioncode == "PCSH" then
|
||||
region = "Asia"
|
||||
-- Physical & NP releases (PSV/PSP/PS1)
|
||||
elseif prefix == "VC" or prefix == "VL" or
|
||||
prefix == "UC" or prefix == "UL" or
|
||||
prefix == "SC" or prefix == "SL" or
|
||||
prefix == "NP" then
|
||||
n1 = string.sub(regioncode,1,1)
|
||||
n3 = string.sub(regioncode,3,3)
|
||||
n4 = string.sub(regioncode,4,4)
|
||||
if n3 == "A" then
|
||||
region = "Asia"
|
||||
elseif n3 == "C" then
|
||||
region = "China"
|
||||
elseif n3 == "E" then
|
||||
region = "Europe"
|
||||
elseif n3 == "H" then
|
||||
region = "Hong Kong"
|
||||
elseif n3 == "J" or n3 == "P" then
|
||||
region = "Japan"
|
||||
elseif n3 == "K" then
|
||||
region = "Korea"
|
||||
elseif n3 == "U" then
|
||||
region = "USA"
|
||||
end
|
||||
|
||||
if n1 == "S" then
|
||||
region = region .. " (PS1)"
|
||||
elseif n1 == "U" or
|
||||
(prefix == "NP" and (n4 == "G" or n4 == "H")) then
|
||||
region = region .. " (PSP)"
|
||||
elseif prefix == "NP" then
|
||||
if n4 == "E" or n4 == "F" then
|
||||
region = region .. " (PS1 - PAL)"
|
||||
elseif n4 == "I" or n4 == "J" then
|
||||
region = region .. " (PS1 - NTSC)"
|
||||
end
|
||||
end
|
||||
elseif prefix == "PE" then
|
||||
region = "Europe (PS1)"
|
||||
elseif prefix == "PT" then
|
||||
region = "Asia (PS1)"
|
||||
elseif prefix == "PU" then
|
||||
region = "USA (PS1)"
|
||||
elseif string.sub(file.name,1,6) == "PSPEMU" then
|
||||
region = "PSP/PS1"
|
||||
end
|
||||
|
||||
return region
|
||||
end
|
||||
|
||||
-- Loading unknown icon
|
||||
@ -71,46 +134,34 @@ local unk = Graphics.loadImage("app0:/unk.png")
|
||||
|
||||
-- Getting region, playtime, icon and title name for any game
|
||||
for i, file in pairs(tbl) do
|
||||
if file.name == "config.lua" then
|
||||
dofile("ux0:/data/TrackPlug/"..file.name)
|
||||
cfg_idx = i
|
||||
else
|
||||
local titleid = string.sub(file.name,1,-5)
|
||||
local regioncode = string.sub(file.name,1,4)
|
||||
if regioncode == "PCSA" or regioncode == "PCSE" then
|
||||
file.region = "USA"
|
||||
elseif regioncode == "PCSB" then
|
||||
file.region = "EUR"
|
||||
elseif regioncode == "PCSF" then
|
||||
file.region = "AUS"
|
||||
elseif regioncode == "PCSG" then
|
||||
file.region = "JPN"
|
||||
elseif regioncode == "PCSH" then
|
||||
file.region = "ASN"
|
||||
else
|
||||
file.region = "UNK"
|
||||
end
|
||||
if System.doesFileExist("ur0:/appmeta/" .. titleid .. "/icon0.png") then
|
||||
file.icon = Graphics.loadImage("ur0:/appmeta/" .. titleid .. "/icon0.png")
|
||||
else
|
||||
file.icon = unk
|
||||
end
|
||||
if System.doesFileExist("ux0:/data/TrackPlugArchive/" .. titleid .. ".txt") then
|
||||
file.title = recoverTitle(titleid)
|
||||
elseif System.doesFileExist("ux0:/app/" .. titleid .. "/sce_sys/param.sfo") then
|
||||
file.title = extractTitle("ux0:/app/" .. titleid .. "/sce_sys/param.sfo", titleid)
|
||||
else
|
||||
file.title = "Unknown Title"
|
||||
end
|
||||
file.id = titleid
|
||||
fd = System.openFile("ux0:/data/TrackPlug/" .. file.name, FREAD)
|
||||
file.rtime = bin2int(System.readFile(fd, 4))
|
||||
file.ptime = FormatTime(file.rtime)
|
||||
System.closeFile(fd)
|
||||
end
|
||||
if file.name == "config.lua" then
|
||||
dofile("ux0:/data/TrackPlug/"..file.name)
|
||||
cfg_idx = i
|
||||
else
|
||||
local titleid = string.sub(file.name,1,-5)
|
||||
file.region = getRegion(titleid)
|
||||
|
||||
if System.doesFileExist("ur0:/appmeta/" .. titleid .. "/icon0.png") then
|
||||
file.icon = Graphics.loadImage("ur0:/appmeta/" .. titleid .. "/icon0.png")
|
||||
else
|
||||
file.icon = unk
|
||||
end
|
||||
if System.doesFileExist("ux0:/data/TrackPlugArchive/" .. titleid .. ".txt") then
|
||||
file.title = recoverTitle(titleid)
|
||||
elseif System.doesFileExist("ux0:/app/" .. titleid .. "/sce_sys/param.sfo") then
|
||||
file.title = extractTitle("ux0:/app/" .. titleid .. "/sce_sys/param.sfo", titleid)
|
||||
else
|
||||
file.title = "Unknown Title"
|
||||
end
|
||||
file.id = titleid
|
||||
fd = System.openFile("ux0:/data/TrackPlug/" .. file.name, FREAD)
|
||||
file.rtime = bin2int(System.readFile(fd, 4))
|
||||
file.ptime = FormatTime(file.rtime)
|
||||
System.closeFile(fd)
|
||||
end
|
||||
end
|
||||
if cfg_idx ~= nil then
|
||||
table.remove(tbl, cfg_idx)
|
||||
table.remove(tbl, cfg_idx)
|
||||
end
|
||||
|
||||
-- Background wave effect
|
||||
@ -179,23 +230,23 @@ local grey = Color.new(40, 40, 40)
|
||||
local alarm_val = 128
|
||||
local alarm_decrease = true
|
||||
function showAlarm(title, select_idx)
|
||||
if alarm_decrease then
|
||||
alarm_val = alarm_val - 4
|
||||
if alarm_val == 40 then
|
||||
alarm_decrease = false
|
||||
end
|
||||
else
|
||||
alarm_val = alarm_val + 4
|
||||
if alarm_val == 128 then
|
||||
alarm_decrease = true
|
||||
end
|
||||
end
|
||||
local sclr = Color.new(alarm_val, alarm_val, alarm_val)
|
||||
Graphics.fillRect(200, 760, 200, 280, grey)
|
||||
Graphics.debugPrint(205, 205, title, yellow)
|
||||
Graphics.fillRect(200, 760, 215 + select_idx * 20, 235 + select_idx * 20, sclr)
|
||||
Graphics.debugPrint(205, 235, "Yes", white)
|
||||
Graphics.debugPrint(205, 255, "No", white)
|
||||
if alarm_decrease then
|
||||
alarm_val = alarm_val - 4
|
||||
if alarm_val == 40 then
|
||||
alarm_decrease = false
|
||||
end
|
||||
else
|
||||
alarm_val = alarm_val + 4
|
||||
if alarm_val == 128 then
|
||||
alarm_decrease = true
|
||||
end
|
||||
end
|
||||
local sclr = Color.new(alarm_val, alarm_val, alarm_val)
|
||||
Graphics.fillRect(200, 760, 200, 280, grey)
|
||||
Graphics.debugPrint(205, 205, title, yellow)
|
||||
Graphics.fillRect(200, 760, 215 + select_idx * 20, 235 + select_idx * 20, sclr)
|
||||
Graphics.debugPrint(205, 235, "Yes", white)
|
||||
Graphics.debugPrint(205, 255, "No", white)
|
||||
end
|
||||
-- Scroll-list Renderer
|
||||
local sel_val = 128
|
||||
@ -322,10 +373,10 @@ end
|
||||
|
||||
-- No games played yet apparently
|
||||
while true do
|
||||
Graphics.initBlend()
|
||||
Screen.clear()
|
||||
Graphics.debugPrint(5, 5, "No games tracked yet.", white)
|
||||
Graphics.termBlend()
|
||||
Screen.flip()
|
||||
Screen.waitVblankStart()
|
||||
Graphics.initBlend()
|
||||
Screen.clear()
|
||||
Graphics.debugPrint(5, 5, "No games tracked yet.", white)
|
||||
Graphics.termBlend()
|
||||
Screen.flip()
|
||||
Screen.waitVblankStart()
|
||||
end
|
||||
|
@ -8,7 +8,7 @@ if(NOT DEFINED CMAKE_TOOLCHAIN_FILE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
project(TrackPlug)
|
||||
project(TrackPlugX)
|
||||
include("${VITASDK}/share/vita.cmake" REQUIRED)
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-q -Wall -O3 -std=gnu99")
|
||||
@ -25,26 +25,25 @@ if (NOT ${RELEASE})
|
||||
add_definitions(-DENABLE_LOGGING)
|
||||
endif()
|
||||
|
||||
add_executable(TrackPlug
|
||||
add_executable(${PROJECT_NAME}
|
||||
main.c
|
||||
)
|
||||
|
||||
target_link_libraries(TrackPlug
|
||||
target_link_libraries(${PROJECT_NAME}
|
||||
gcc
|
||||
taihen_stub
|
||||
SceAppUtil_stub
|
||||
SceAppMgr_stub
|
||||
SceLibKernel_stub
|
||||
SceDisplay_stub
|
||||
k
|
||||
gcc
|
||||
ScePower_stub
|
||||
kuio_stub
|
||||
SceIofilemgr_stub
|
||||
SceLibc_stub
|
||||
SceKernelModulemgr_stub
|
||||
SceKernelThreadMgr_stub
|
||||
)
|
||||
|
||||
set_target_properties(TrackPlug
|
||||
set_target_properties(${PROJECT_NAME}
|
||||
PROPERTIES LINK_FLAGS "-nostdlib"
|
||||
)
|
||||
|
||||
vita_create_self(TrackPlug.suprx TrackPlug
|
||||
CONFIG ${CMAKE_SOURCE_DIR}/TrackPlug.yml
|
||||
vita_create_self(${PROJECT_NAME}.suprx ${PROJECT_NAME}
|
||||
CONFIG ${CMAKE_SOURCE_DIR}/${PROJECT_NAME}.yml
|
||||
)
|
||||
|
6
plugin/TrackPlug.yml → plugin/TrackPlugX.yml
Normal file → Executable file
6
plugin/TrackPlug.yml → plugin/TrackPlugX.yml
Normal file → Executable file
@ -1,8 +1,8 @@
|
||||
TrackPlug:
|
||||
TrackPlugX:
|
||||
attributes: 0
|
||||
version:
|
||||
major: 1
|
||||
minor: 2
|
||||
major: 2
|
||||
minor: 1
|
||||
main:
|
||||
start: module_start
|
||||
stop: module_stop
|
202
plugin/main.c
202
plugin/main.c
@ -1,62 +1,180 @@
|
||||
#include <vitasdk.h>
|
||||
#include <taihen.h>
|
||||
#include <kuio.h>
|
||||
#include <libk/string.h>
|
||||
#include <libk/stdio.h>
|
||||
|
||||
static SceUID hook;
|
||||
static tai_hook_ref_t ref;
|
||||
static char titleid[16];
|
||||
static char fname[256];
|
||||
static uint64_t playtime = 0;
|
||||
static uint64_t tick = 0;
|
||||
#define SECOND 1000000
|
||||
#define SAVE_PERIOD 10
|
||||
|
||||
int sceDisplaySetFrameBuf_patched(const SceDisplayFrameBuf *pParam, int sync) {
|
||||
int snprintf(char *s, size_t n, const char *format, ...);
|
||||
|
||||
uint64_t t_tick = sceKernelGetProcessTimeWide();
|
||||
// ScePspemu
|
||||
static SceUID sub_810053F8_hookid = -1;
|
||||
static tai_hook_ref_t sub_810053F8_hookref = {0};
|
||||
|
||||
// Saving playtime every 10 seconds
|
||||
if ((t_tick - tick) > 10000000){
|
||||
tick = t_tick;
|
||||
playtime += 10;
|
||||
SceUID fd;
|
||||
kuIoOpen(fname, SCE_O_WRONLY | SCE_O_CREAT | SCE_O_TRUNC, &fd);
|
||||
kuIoWrite(fd, &playtime, sizeof(uint64_t));
|
||||
kuIoClose(fd);
|
||||
}
|
||||
static char adrenaline_titleid[12];
|
||||
|
||||
return TAI_CONTINUE(int, ref, pParam, sync);
|
||||
static uint8_t is_pspemu_loaded = 0;
|
||||
static uint8_t is_pspemu_custom_bbl = 0;
|
||||
static uint8_t is_pspemu_title_written = 0;
|
||||
static uint8_t is_playtime_loaded = 0;
|
||||
|
||||
static char playtime_bin_path[128];
|
||||
static uint64_t playtime_start = 0;
|
||||
static uint64_t tick_start = 0;
|
||||
|
||||
static void load_playtime(const char *titleid) {
|
||||
snprintf(playtime_bin_path, 128, "ux0:/data/TrackPlug/%s.bin", titleid);
|
||||
tick_start = sceKernelGetProcessTimeWide();
|
||||
is_pspemu_title_written = 0;
|
||||
|
||||
SceUID fd = sceIoOpen(playtime_bin_path, SCE_O_RDONLY, 0777);
|
||||
if (fd < 0) {
|
||||
playtime_start = 0;
|
||||
is_playtime_loaded = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
sceIoRead(fd, &playtime_start, sizeof(uint64_t));
|
||||
sceIoClose(fd);
|
||||
|
||||
is_playtime_loaded = 1;
|
||||
}
|
||||
|
||||
static void write_playtime() {
|
||||
uint32_t playtime = playtime_start +
|
||||
(sceKernelGetProcessTimeWide() - tick_start) / SECOND;
|
||||
|
||||
SceUID fd = sceIoOpen(playtime_bin_path,
|
||||
SCE_O_WRONLY | SCE_O_CREAT | SCE_O_TRUNC, 0777);
|
||||
if (fd < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
sceIoWrite(fd, &playtime, sizeof(uint64_t));
|
||||
sceIoClose(fd);
|
||||
}
|
||||
|
||||
void write_title(const char *titleid, const char *title) {
|
||||
char path[128];
|
||||
snprintf(path, 128, "ux0:/data/TrackPlugArchive/%s.txt", titleid);
|
||||
is_pspemu_title_written = 1;
|
||||
|
||||
// Check if already exists
|
||||
SceUID fd = sceIoOpen(path, SCE_O_RDONLY, 0777);
|
||||
if (fd >= 0) {
|
||||
sceIoClose(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
fd = sceIoOpen(path, SCE_O_WRONLY | SCE_O_CREAT, 0777);
|
||||
if (fd < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
sceIoWrite(fd, title, strlen(title));
|
||||
sceIoClose(fd);
|
||||
}
|
||||
|
||||
static int check_adrenaline() {
|
||||
void *SceAdrenaline = (void *)0x73CDE000;
|
||||
|
||||
char *title = SceAdrenaline + 24;
|
||||
char *titleid = SceAdrenaline + 152;
|
||||
|
||||
if (title[0] == 0 || !strncmp(title, "XMB", 3))
|
||||
return 0;
|
||||
|
||||
// Write custom bubble Title
|
||||
if (is_pspemu_custom_bbl && !is_pspemu_title_written)
|
||||
write_title(adrenaline_titleid, title);
|
||||
|
||||
// XMB game changed?
|
||||
if (!is_pspemu_custom_bbl && strncmp(adrenaline_titleid, titleid, 9)) {
|
||||
if (is_playtime_loaded)
|
||||
write_playtime(); // Save closed game
|
||||
|
||||
is_playtime_loaded = 0;
|
||||
strcpy(adrenaline_titleid, titleid);
|
||||
|
||||
load_playtime(titleid);
|
||||
write_title(titleid, title);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int sub_810053F8_patched(int a1, int a2) {
|
||||
char *pspemu_titleid = (char *)(a2 + 68);
|
||||
|
||||
// If using custom bubble
|
||||
if (strncmp(pspemu_titleid, "PSPEMUCFW", 9)) {
|
||||
is_pspemu_custom_bbl = 1;
|
||||
strcpy(adrenaline_titleid, pspemu_titleid);
|
||||
|
||||
load_playtime(pspemu_titleid);
|
||||
}
|
||||
|
||||
is_pspemu_loaded = 1;
|
||||
|
||||
return TAI_CONTINUE(int, sub_810053F8_hookref, a1, a2);
|
||||
}
|
||||
|
||||
static int tracker_thread(SceSize args, void *argp) {
|
||||
while (1) {
|
||||
if (is_pspemu_loaded) {
|
||||
// Check if XMB/game has changed, write Title if necessary
|
||||
int ret = check_adrenaline();
|
||||
if (!is_pspemu_custom_bbl && !ret) {
|
||||
goto CONT;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_playtime_loaded) {
|
||||
write_playtime();
|
||||
}
|
||||
|
||||
CONT:
|
||||
sceKernelDelayThread(SAVE_PERIOD * SECOND);
|
||||
}
|
||||
|
||||
return sceKernelExitDeleteThread(0);
|
||||
}
|
||||
|
||||
void _start() __attribute__ ((weak, alias ("module_start")));
|
||||
int module_start(SceSize argc, const void *args) {
|
||||
char titleid[12];
|
||||
sceAppMgrAppParamGetString(0, 12, titleid, 12);
|
||||
|
||||
// Getting game Title ID
|
||||
sceAppMgrAppParamGetString(0, 12, titleid , 256);
|
||||
if (!strncmp(titleid, "NPXS10028", 9)) {
|
||||
tai_module_info_t tai_info;
|
||||
tai_info.size = sizeof(tai_module_info_t);
|
||||
taiGetModuleInfo("ScePspemu", &tai_info);
|
||||
|
||||
// Getting current playtime
|
||||
SceUID fd;
|
||||
sprintf(fname, "ux0:/data/TrackPlug/%s.bin", titleid);
|
||||
kuIoOpen(fname, SCE_O_RDONLY, &fd);
|
||||
if (fd >= 0){
|
||||
kuIoRead(fd, &playtime, sizeof(uint64_t));
|
||||
kuIoClose(fd);
|
||||
}
|
||||
sub_810053F8_hookid = taiHookFunctionOffset(
|
||||
&sub_810053F8_hookref,
|
||||
tai_info.modid,
|
||||
0, 0x53F8, 1,
|
||||
sub_810053F8_patched);
|
||||
} else {
|
||||
load_playtime(titleid);
|
||||
}
|
||||
|
||||
// Getting starting tick
|
||||
tick = sceKernelGetProcessTimeWide();
|
||||
SceUID tracker_thread_id = sceKernelCreateThread(
|
||||
"TrackPlugX",
|
||||
tracker_thread,
|
||||
0x10000100,
|
||||
0x10000,
|
||||
0, 0, NULL);
|
||||
if (tracker_thread_id >= 0)
|
||||
sceKernelStartThread(tracker_thread_id, 0, NULL);
|
||||
|
||||
hook = taiHookFunctionImport(&ref,
|
||||
TAI_MAIN_MODULE,
|
||||
TAI_ANY_LIBRARY,
|
||||
0x7A410B64,
|
||||
sceDisplaySetFrameBuf_patched);
|
||||
|
||||
return SCE_KERNEL_START_SUCCESS;
|
||||
return SCE_KERNEL_START_SUCCESS;
|
||||
}
|
||||
|
||||
int module_stop(SceSize argc, const void *args) {
|
||||
if (sub_810053F8_hookid >= 0) {
|
||||
taiHookRelease(sub_810053F8_hookid, sub_810053F8_hookref);
|
||||
}
|
||||
|
||||
return SCE_KERNEL_STOP_SUCCESS;
|
||||
|
||||
return SCE_KERNEL_STOP_SUCCESS;
|
||||
}
|
Reference in New Issue
Block a user