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,17 +6,128 @@
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;
static char playtime_loaded = 0;
static int (* ScePspemuConvertAddress)(uint32_t addr, int mode, uint32_t cache_size);
#define ADRENALINE_ADDRESS 0xABCDE000
#define ADRENALINE_SIZE 0x2000
void load_playtime() {
// 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);
} 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) { int sceDisplaySetFrameBuf_patched(const SceDisplayFrameBuf *pParam, int sync) {
uint64_t t_tick = sceKernelGetProcessTimeWide(); uint64_t t_tick = sceKernelGetProcessTimeWide();
// Saving playtime every 10 seconds // Saving playtime every 10 seconds
if ((t_tick - tick) > 10000000){ 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; tick = t_tick;
playtime += 10; playtime += 10;
SceUID fd; SceUID fd;
@ -25,6 +136,7 @@ int sceDisplaySetFrameBuf_patched(const SceDisplayFrameBuf *pParam, int sync) {
kuIoClose(fd); kuIoClose(fd);
} }
exit:
return TAI_CONTINUE(int, ref, pParam, sync); return TAI_CONTINUE(int, ref, pParam, sync);
} }
@ -32,15 +144,26 @@ void _start() __attribute__ ((weak, alias ("module_start")));
int module_start(SceSize argc, const void *args) { int module_start(SceSize argc, const void *args) {
// Getting game Title ID // Getting game Title ID
sceAppMgrAppParamGetString(0, 12, titleid , 256); sceAppMgrAppParamGetString(0, 12, real_titleid , 256);
// Getting current playtime // PspEmu game?
SceUID fd; if (strcmp(real_titleid, "NPXS10028") == 0) {
sprintf(fname, "ux0:/data/TrackPlug/%s.bin", titleid); // Get ScePspemu tai module info
kuIoOpen(fname, SCE_O_RDONLY, &fd); tai_module_info_t ScePspemu_tai_info;
if (fd >= 0){ ScePspemu_tai_info.size = sizeof(tai_module_info_t);
kuIoRead(fd, &playtime, sizeof(uint64_t)); taiGetModuleInfo("ScePspemu", &ScePspemu_tai_info);
kuIoClose(fd);
// 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
@ -56,7 +179,5 @@ int module_start(SceSize argc, const void *args) {
} }
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;
} }