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

@ -19,98 +19,149 @@ 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
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

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) {
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);
}
int snprintf(char *s, size_t n, const char *format, ...);
// ScePspemu
static SceUID sub_810053F8_hookid = -1;
static tai_hook_ref_t sub_810053F8_hookref = {0};
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;
}
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) {
// Getting game Title ID
sceAppMgrAppParamGetString(0, 12, titleid , 256);
// 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);
}
// Getting starting tick
tick = sceKernelGetProcessTimeWide();
hook = taiHookFunctionImport(&ref,
TAI_MAIN_MODULE,
TAI_ANY_LIBRARY,
0x7A410B64,
sceDisplaySetFrameBuf_patched);
return SCE_KERNEL_START_SUCCESS;
char titleid[12];
sceAppMgrAppParamGetString(0, 12, titleid, 12);
if (!strncmp(titleid, "NPXS10028", 9)) {
tai_module_info_t tai_info;
tai_info.size = sizeof(tai_module_info_t);
taiGetModuleInfo("ScePspemu", &tai_info);
sub_810053F8_hookid = taiHookFunctionOffset(
&sub_810053F8_hookref,
tai_info.modid,
0, 0x53F8, 1,
sub_810053F8_patched);
} else {
load_playtime(titleid);
}
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;
}
return SCE_KERNEL_STOP_SUCCESS;
}