merging Electry's changes so pspemu also works

This commit is contained in:
Furkan Mudanyali 2020-03-15 13:41:20 +03:00
commit eb898d9cbb
5 changed files with 328 additions and 157 deletions

3
.gitignore vendored
View File

@ -45,3 +45,6 @@ $RECYCLE.BIN/
Network Trash Folder
Temporary Items
.apdisk
# Build directory
build/

View File

@ -25,7 +25,7 @@ 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
return bit32.lshift(b4, 24) + bit32.lshift(b3, 16) + bit32.lshift(b2, 8) + b1
end
-- Format raw time data
@ -56,7 +56,7 @@ end
-- Extracts title name from an SFO file
function extractTitle(file, tid)
local data = System.extractSFO(file)
local data = System.extractSfo(file)
if System.doesFileExist("ux0:/data/TrackPlugArchive/" .. tid .. ".txt") then
System.deleteFile("ux0:/data/TrackPlugArchive/" .. tid .. ".txt")
end
@ -66,6 +66,69 @@ function extractTitle(file, tid)
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
local unk = Graphics.loadImage("app0:/unk.png")
@ -76,20 +139,8 @@ for i, file in pairs(tbl) do
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
file.region = getRegion(titleid)
if System.doesFileExist("ur0:/appmeta/" .. titleid .. "/icon0.png") then
file.icon = Graphics.loadImage("ur0:/appmeta/" .. titleid .. "/icon0.png")
else

View File

@ -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
View 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

View File

@ -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];
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;
}
return TAI_CONTINUE(int, ref, pParam, sync);
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();
hook = taiHookFunctionImport(&ref,
TAI_MAIN_MODULE,
TAI_ANY_LIBRARY,
0x7A410B64,
sceDisplaySetFrameBuf_patched);
SceUID tracker_thread_id = sceKernelCreateThread(
"TrackPlugX",
tracker_thread,
0x10000100,
0x10000,
0, 0, NULL);
if (tracker_thread_id >= 0)
sceKernelStartThread(tracker_thread_id, 0, NULL);
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;
}