plugin: Add hacky support for Adrenaline titles

Signed-off-by: Michal Chvila <miso.chvila@gmail.com>
This commit is contained in:
Michal Chvila 2018-07-30 15:21:41 +02:00
parent 8e20fe7337
commit 9662dd7454
2 changed files with 155 additions and 33 deletions

View File

@ -39,6 +39,7 @@ target_link_libraries(TrackPlug
gcc gcc
ScePower_stub ScePower_stub
kuio_stub kuio_stub
SceKernelModulemgr_stub
) )
set_target_properties(TrackPlug set_target_properties(TrackPlug

View File

@ -6,34 +6,24 @@
static SceUID hook; static SceUID hook;
static tai_hook_ref_t ref; static tai_hook_ref_t ref;
static char titleid[16];
static char real_titleid[16];
static char titleid[128];
static char full_title[128];
static char fname[256]; static char fname[256];
static char fname_title[256];
static uint64_t playtime = 0; static uint64_t playtime = 0;
static uint64_t tick = 0; static uint64_t tick = 0;
int sceDisplaySetFrameBuf_patched(const SceDisplayFrameBuf *pParam, int sync) { static char playtime_loaded = 0;
uint64_t t_tick = sceKernelGetProcessTimeWide();
// 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);
}
return TAI_CONTINUE(int, ref, pParam, sync);
}
void _start() __attribute__ ((weak, alias ("module_start"))); static int (* ScePspemuConvertAddress)(uint32_t addr, int mode, uint32_t cache_size);
int module_start(SceSize argc, const void *args) { #define ADRENALINE_ADDRESS 0xABCDE000
#define ADRENALINE_SIZE 0x2000
// Getting game Title ID
sceAppMgrAppParamGetString(0, 12, titleid , 256); void load_playtime() {
// Getting current playtime // Getting current playtime
SceUID fd; SceUID fd;
sprintf(fname, "ux0:/data/TrackPlug/%s.bin", titleid); sprintf(fname, "ux0:/data/TrackPlug/%s.bin", titleid);
@ -41,22 +31,153 @@ int module_start(SceSize argc, const void *args) {
if (fd >= 0){ if (fd >= 0){
kuIoRead(fd, &playtime, sizeof(uint64_t)); kuIoRead(fd, &playtime, sizeof(uint64_t));
kuIoClose(fd); kuIoClose(fd);
} else {
playtime = 0;
} }
playtime_loaded = 1;
}
int get_pspemu_title() {
void *adrenaline = (void *)ScePspemuConvertAddress(ADRENALINE_ADDRESS, 0x1/*KERMIT_INPUT_MODE*/, ADRENALINE_SIZE);
if (adrenaline <= 0)
return 0;
char *title = adrenaline + 0x18;
if (title[0] == 0 || strncmp(title, "XMB", 3) == 0)
return 0;
// Game changed?
if (strcmp(full_title, title) != 0) {
playtime_loaded = 0;
}
strcpy(full_title, title);
titleid[0] = 'P';
titleid[1] = 'S';
titleid[2] = 'P';
titleid[3] = '_';
int j = 4, i = 0;
while (j < sizeof(titleid) - 1 && title[i] != 0) {
if ((title[i] >= 'A' && title[i] <= 'Z') ||
(title[i] >= 'a' && title[i] <= 'z') ||
(title[i] >= '0' && title[i] <= '9')) {
titleid[j++] = title[i];
}
i++;
}
// Pad to min 9 chars, prevent app crashes
while (j < 9) {
titleid[j++] = 'x';
}
titleid[j] = 0;
return 1;
}
void write_pspemu_title() {
char buffer[128];
snprintf(buffer, sizeof(buffer), "[PSP] ");
int i = 0, j = 6;
while (j < sizeof(buffer) && full_title[i] != 0) {
// Strip invalid chars
if (full_title[i] >= 32 && full_title[i] <= 126) {
buffer[j++] = full_title[i];
}
i++;
}
buffer[j++] = 0;
SceUID fd;
sprintf(fname_title, "ux0:/data/TrackPlugArchive/%s.txt", titleid);
kuIoOpen(fname_title, SCE_O_RDONLY, &fd);
if (fd < 0){
kuIoOpen(fname_title, SCE_O_WRONLY|SCE_O_CREAT, &fd);
if (fd >= 0) {
kuIoWrite(fd, buffer, strlen(buffer));
kuIoClose(fd);
}
}
}
int sceDisplaySetFrameBuf_patched(const SceDisplayFrameBuf *pParam, int sync) {
uint64_t t_tick = sceKernelGetProcessTimeWide();
// Saving playtime every 10 seconds
if ((t_tick - tick) > 10000000){
// If in PspEmu
if (strcmp(real_titleid, "NPXS10028") == 0) {
if (get_pspemu_title()) {
// New game?
if (!playtime_loaded) {
load_playtime();
write_pspemu_title();
}
} else {
// No game running
playtime_loaded = 0;
}
}
if (!playtime_loaded) {
goto exit;
}
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);
}
exit:
return TAI_CONTINUE(int, ref, pParam, sync);
}
void _start() __attribute__ ((weak, alias ("module_start")));
int module_start(SceSize argc, const void *args) {
// Getting game Title ID
sceAppMgrAppParamGetString(0, 12, real_titleid , 256);
// PspEmu game?
if (strcmp(real_titleid, "NPXS10028") == 0) {
// Get ScePspemu tai module info
tai_module_info_t ScePspemu_tai_info;
ScePspemu_tai_info.size = sizeof(tai_module_info_t);
taiGetModuleInfo("ScePspemu", &ScePspemu_tai_info);
// Module info
SceKernelModuleInfo ScePspemu_mod_info;
ScePspemu_mod_info.size = sizeof(SceKernelModuleInfo);
sceKernelGetModuleInfo(ScePspemu_tai_info.modid, &ScePspemu_mod_info);
// Addresses
uint32_t text_addr = (uint32_t)ScePspemu_mod_info.segments[0].vaddr;
ScePspemuConvertAddress = (void *)(text_addr + 0x6364 + 0x1);
} else {
strcpy(titleid, real_titleid);
load_playtime();
}
// Getting starting tick // Getting starting tick
tick = sceKernelGetProcessTimeWide(); tick = sceKernelGetProcessTimeWide();
hook = taiHookFunctionImport(&ref, hook = taiHookFunctionImport(&ref,
TAI_MAIN_MODULE, TAI_MAIN_MODULE,
TAI_ANY_LIBRARY, TAI_ANY_LIBRARY,
0x7A410B64, 0x7A410B64,
sceDisplaySetFrameBuf_patched); sceDisplaySetFrameBuf_patched);
return SCE_KERNEL_START_SUCCESS; return SCE_KERNEL_START_SUCCESS;
} }
int module_stop(SceSize argc, const void *args) { int module_stop(SceSize argc, const void *args) {
return SCE_KERNEL_STOP_SUCCESS; return SCE_KERNEL_STOP_SUCCESS;
}
}