From 9662dd745456bac922c669e924de7a4bf80516ab Mon Sep 17 00:00:00 2001 From: Michal Chvila Date: Mon, 30 Jul 2018 15:21:41 +0200 Subject: [PATCH 01/12] plugin: Add hacky support for Adrenaline titles Signed-off-by: Michal Chvila --- plugin/CMakeLists.txt | 1 + plugin/main.c | 187 ++++++++++++++++++++++++++++++++++-------- 2 files changed, 155 insertions(+), 33 deletions(-) diff --git a/plugin/CMakeLists.txt b/plugin/CMakeLists.txt index 4379dc2..a105c8f 100644 --- a/plugin/CMakeLists.txt +++ b/plugin/CMakeLists.txt @@ -39,6 +39,7 @@ target_link_libraries(TrackPlug gcc ScePower_stub kuio_stub + SceKernelModulemgr_stub ) set_target_properties(TrackPlug diff --git a/plugin/main.c b/plugin/main.c index 892a9a7..36a4a95 100644 --- a/plugin/main.c +++ b/plugin/main.c @@ -6,34 +6,24 @@ static SceUID hook; 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_title[256]; + static uint64_t playtime = 0; static uint64_t tick = 0; -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); -} +static char playtime_loaded = 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); - +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); @@ -41,22 +31,153 @@ int module_start(SceSize argc, const void *args) { 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) { + + 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 tick = sceKernelGetProcessTimeWide(); - + hook = taiHookFunctionImport(&ref, - TAI_MAIN_MODULE, - TAI_ANY_LIBRARY, - 0x7A410B64, - sceDisplaySetFrameBuf_patched); - + TAI_MAIN_MODULE, + TAI_ANY_LIBRARY, + 0x7A410B64, + sceDisplaySetFrameBuf_patched); + return SCE_KERNEL_START_SUCCESS; } int module_stop(SceSize argc, const void *args) { - return SCE_KERNEL_STOP_SUCCESS; - -} \ No newline at end of file +} From 72c015b63e7a666bf5ab169d7936e490b813112c Mon Sep 17 00:00:00 2001 From: Michal Chvila Date: Wed, 9 Jan 2019 02:08:35 +0100 Subject: [PATCH 02/12] Add full support for Adrenaline Signed-off-by: Michal Chvila --- plugin/CMakeLists.txt | 20 ++- plugin/main.c | 279 ++++++++++++++++++++---------------------- 2 files changed, 143 insertions(+), 156 deletions(-) diff --git a/plugin/CMakeLists.txt b/plugin/CMakeLists.txt index a105c8f..7e67f11 100644 --- a/plugin/CMakeLists.txt +++ b/plugin/CMakeLists.txt @@ -25,27 +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 ) diff --git a/plugin/main.c b/plugin/main.c index 36a4a95..e5b9321 100644 --- a/plugin/main.c +++ b/plugin/main.c @@ -1,183 +1,172 @@ #include #include -#include -#include -#include -static SceUID hook; -static tai_hook_ref_t ref; +#define SECOND 1000000 +#define SAVE_PERIOD 10 -static char real_titleid[16]; -static char titleid[128]; -static char full_title[128]; +int snprintf(char *s, size_t n, const char *format, ...); -static char fname[256]; -static char fname_title[256]; +// ScePspemu +static SceUID sub_810053F8_hookid = -1; +static tai_hook_ref_t sub_810053F8_hookref = {0}; -static uint64_t playtime = 0; -static uint64_t tick = 0; +static char adrenaline_titleid[12]; -static char playtime_loaded = 0; +static uint8_t is_pspemu_loaded = 0; +static uint8_t is_pspemu_custom_bbl = 0; +static uint8_t is_playtime_loaded = 0; -static int (* ScePspemuConvertAddress)(uint32_t addr, int mode, uint32_t cache_size); -#define ADRENALINE_ADDRESS 0xABCDE000 -#define ADRENALINE_SIZE 0x2000 +static char playtime_bin_path[128]; +static uint64_t playtime_start = 0; +static uint64_t tick_start = 0; -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; +static void load_playtime(const char *titleid) { + + snprintf(playtime_bin_path, 128, "ux0:/data/TrackPlug/%s.bin", titleid); + tick_start = sceKernelGetProcessTimeWide(); + + 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; } -int get_pspemu_title() { - void *adrenaline = (void *)ScePspemuConvertAddress(ADRENALINE_ADDRESS, 0x1/*KERMIT_INPUT_MODE*/, ADRENALINE_SIZE); - if (adrenaline <= 0) - return 0; +static void write_playtime(uint64_t playtime) { - char *title = adrenaline + 0x18; + SceUID fd = sceIoOpen(playtime_bin_path, SCE_O_WRONLY | SCE_O_CREAT | SCE_O_TRUNC, 0777); + if (fd < 0) { + return; + } - 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; + sceIoWrite(fd, &playtime, sizeof(uint64_t)); + sceIoClose(fd); } -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; +void write_title(const char *titleid, const char *title) { - 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); - } - } + char path[128]; + snprintf(path, 128, "ux0:/data/TrackPlugArchive/%s.txt", titleid); + + // 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); } -int sceDisplaySetFrameBuf_patched(const SceDisplayFrameBuf *pParam, int sync) { +static int check_adrenaline() { + void *SceAdrenaline = (void *)0x73CDE000; - uint64_t t_tick = sceKernelGetProcessTimeWide(); + char *title = SceAdrenaline + 24; + char *titleid = SceAdrenaline + 152; - // 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 (title[0] == 0 || !strncmp(title, "XMB", 3)) + return 0; - if (!playtime_loaded) { - goto exit; - } + // Game changed? + if (strncmp(adrenaline_titleid, titleid, 9)) { + is_playtime_loaded = 0; + strcpy(adrenaline_titleid, titleid); - 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); - } + load_playtime(titleid); + write_title(titleid, title); + return 0; + } -exit: - return TAI_CONTINUE(int, ref, pParam, sync); + 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; + 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) { + uint64_t tick_now = sceKernelGetProcessTimeWide(); + + if (is_pspemu_loaded) { + // Check if XMB/game has changed + if (!is_pspemu_custom_bbl && !check_adrenaline()) { + goto CONT; + } + } + + if (!is_playtime_loaded) { + goto CONT; + } + + write_playtime(playtime_start + (tick_now - tick_start)/SECOND); + +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, real_titleid , 256); + char titleid[12]; + sceAppMgrAppParamGetString(0, 12, titleid, 12); - // 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); + if (!strncmp(titleid, "NPXS10028", 9)) { - // Module info - SceKernelModuleInfo ScePspemu_mod_info; - ScePspemu_mod_info.size = sizeof(SceKernelModuleInfo); - sceKernelGetModuleInfo(ScePspemu_tai_info.modid, &ScePspemu_mod_info); + tai_module_info_t tai_info; + tai_info.size = sizeof(tai_module_info_t); + taiGetModuleInfo("ScePspemu", &tai_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(); - } + sub_810053F8_hookid = taiHookFunctionOffset( + &sub_810053F8_hookref, + tai_info.modid, + 0, 0x53F8, 1, + sub_810053F8_patched); - // Getting starting tick - tick = sceKernelGetProcessTimeWide(); + } else { - hook = taiHookFunctionImport(&ref, - TAI_MAIN_MODULE, - TAI_ANY_LIBRARY, - 0x7A410B64, - sceDisplaySetFrameBuf_patched); + load_playtime(titleid); + } - return SCE_KERNEL_START_SUCCESS; + 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) { - return SCE_KERNEL_STOP_SUCCESS; + + if (sub_810053F8_hookid >= 0) { + taiHookRelease(sub_810053F8_hookid, sub_810053F8_hookref); + } + + return SCE_KERNEL_STOP_SUCCESS; } From a094af68425f7c77d86178900d436ce0f150c85b Mon Sep 17 00:00:00 2001 From: Michal Chvila Date: Wed, 9 Jan 2019 09:08:59 +0100 Subject: [PATCH 03/12] plugin: Formatting Signed-off-by: Michal Chvila --- plugin/main.c | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/plugin/main.c b/plugin/main.c index e5b9321..53594fa 100644 --- a/plugin/main.c +++ b/plugin/main.c @@ -21,7 +21,6 @@ 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(); @@ -39,8 +38,8 @@ static void load_playtime(const char *titleid) { } static void write_playtime(uint64_t playtime) { - - SceUID fd = sceIoOpen(playtime_bin_path, SCE_O_WRONLY | SCE_O_CREAT | SCE_O_TRUNC, 0777); + SceUID fd = sceIoOpen(playtime_bin_path, + SCE_O_WRONLY | SCE_O_CREAT | SCE_O_TRUNC, 0777); if (fd < 0) { return; } @@ -50,7 +49,6 @@ static void write_playtime(uint64_t playtime) { } void write_title(const char *titleid, const char *title) { - char path[128]; snprintf(path, 128, "ux0:/data/TrackPlugArchive/%s.txt", titleid); @@ -93,7 +91,6 @@ static int check_adrenaline() { } int sub_810053F8_patched(int a1, int a2) { - char *pspemu_titleid = (char *)(a2 + 68); // If using custom bubble @@ -108,10 +105,7 @@ int sub_810053F8_patched(int a1, int a2) { } static int tracker_thread(SceSize args, void *argp) { - - while(1) { - uint64_t tick_now = sceKernelGetProcessTimeWide(); - + while (1) { if (is_pspemu_loaded) { // Check if XMB/game has changed if (!is_pspemu_custom_bbl && !check_adrenaline()) { @@ -123,7 +117,8 @@ static int tracker_thread(SceSize args, void *argp) { goto CONT; } - write_playtime(playtime_start + (tick_now - tick_start)/SECOND); + write_playtime(playtime_start + + (sceKernelGetProcessTimeWide() - tick_start)/SECOND); CONT: sceKernelDelayThread(SAVE_PERIOD * SECOND); @@ -134,12 +129,10 @@ CONT: void _start() __attribute__ ((weak, alias ("module_start"))); int module_start(SceSize argc, const void *args) { - 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); @@ -149,13 +142,16 @@ int module_start(SceSize argc, const void *args) { 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); + SceUID tracker_thread_id = sceKernelCreateThread( + "TrackPlugX", + tracker_thread, + 0x10000100, + 0x10000, + 0, 0, NULL); if (tracker_thread_id >= 0) sceKernelStartThread(tracker_thread_id, 0, NULL); @@ -163,7 +159,6 @@ int module_start(SceSize argc, const void *args) { } int module_stop(SceSize argc, const void *args) { - if (sub_810053F8_hookid >= 0) { taiHookRelease(sub_810053F8_hookid, sub_810053F8_hookref); } From 86e47c9f59e52adff5b0650d64b91b3ff1727140 Mon Sep 17 00:00:00 2001 From: Michal Chvila Date: Wed, 9 Jan 2019 12:32:41 +0100 Subject: [PATCH 04/12] app: Fix sorting & deleting Signed-off-by: Michal Chvila --- app/index.lua | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/app/index.lua b/app/index.lua index bce1b19..1a5d7bf 100644 --- a/app/index.lua +++ b/app/index.lua @@ -64,15 +64,15 @@ for i, file in pairs(tbl) do 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" + file.region = "US" elseif regioncode == "PCSB" then - file.region = "EUR" + file.region = "EU" elseif regioncode == "PCSF" then - file.region = "AUS" + file.region = "AU" elseif regioncode == "PCSG" then - file.region = "JPN" + file.region = "JP" elseif regioncode == "PCSH" then - file.region = "ASN" + file.region = "ASIA" else file.region = "UNK" end @@ -270,6 +270,7 @@ local big_tbl = {} function RenderList() local r_max = 0 local r = 0 + big_tbl = {} if #tbl < 4 then r_max = 8 else @@ -357,7 +358,7 @@ while #tbl > 0 do new_list_idx = #tbl end mov_y = 1 - mov_step = 22 + mov_step = 33 end elseif Controls.check(pad, SCE_CTRL_DOWN) and mov_y == 0 then if freeze then @@ -368,7 +369,7 @@ while #tbl > 0 do new_list_idx = 1 end mov_y = -1 - mov_step = -22 + mov_step = -33 end elseif Controls.check(pad, SCE_CTRL_LTRIGGER) and not Controls.check(oldpad, SCE_CTRL_LTRIGGER) and not freeze then order_idx = order_idx - 1 From bdd1ee48e3510bae2713559536246a567d48169f Mon Sep 17 00:00:00 2001 From: Michal Chvila Date: Wed, 9 Jan 2019 12:38:05 +0100 Subject: [PATCH 05/12] app: Add missing region codes Signed-off-by: Michal Chvila --- app/index.lua | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/index.lua b/app/index.lua index 1a5d7bf..31a67b0 100644 --- a/app/index.lua +++ b/app/index.lua @@ -65,14 +65,14 @@ for i, file in pairs(tbl) do local regioncode = string.sub(file.name,1,4) if regioncode == "PCSA" or regioncode == "PCSE" then file.region = "US" - elseif regioncode == "PCSB" then + elseif regioncode == "PCSB" or regioncode == "PCSF" then file.region = "EU" - elseif regioncode == "PCSF" then - file.region = "AU" - elseif regioncode == "PCSG" then + elseif regioncode == "PCSC" or regioncode == "PCSG" then file.region = "JP" - elseif regioncode == "PCSH" then + elseif regioncode == "PCSD" or regioncode == "PCSH" then file.region = "ASIA" + elseif string.sub(file.name,1,6) == "PSPEMU" then + file.region = "PSP/PSX" else file.region = "UNK" end From ad93ee1a1800ccd27787debded296826e329cbd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Chv=C3=ADla?= Date: Thu, 22 Aug 2019 03:18:18 +0200 Subject: [PATCH 06/12] main: Minor refactor --- plugin/main.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/plugin/main.c b/plugin/main.c index 53594fa..989a54d 100644 --- a/plugin/main.c +++ b/plugin/main.c @@ -37,7 +37,10 @@ static void load_playtime(const char *titleid) { is_playtime_loaded = 1; } -static void write_playtime(uint64_t playtime) { +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) { @@ -79,6 +82,9 @@ static int check_adrenaline() { // Game changed? if (strncmp(adrenaline_titleid, titleid, 9)) { + if (is_playtime_loaded) + write_playtime(); // Save closed game + is_playtime_loaded = 0; strcpy(adrenaline_titleid, titleid); @@ -113,13 +119,10 @@ static int tracker_thread(SceSize args, void *argp) { } } - if (!is_playtime_loaded) { - goto CONT; + if (is_playtime_loaded) { + write_playtime(); } - write_playtime(playtime_start + - (sceKernelGetProcessTimeWide() - tick_start)/SECOND); - CONT: sceKernelDelayThread(SAVE_PERIOD * SECOND); } From 1543b6afc3cba4f0b5e32d5c785ed3ba49f6a2a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Chv=C3=ADla?= Date: Thu, 22 Aug 2019 03:19:18 +0200 Subject: [PATCH 07/12] .gitignore: Ignore build dir --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index cd2946a..338b05b 100644 --- a/.gitignore +++ b/.gitignore @@ -45,3 +45,6 @@ $RECYCLE.BIN/ Network Trash Folder Temporary Items .apdisk + +# Build directory +build/ From c4aa43f27c58123ce5bee75e311980c486a36fd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Chv=C3=ADla?= Date: Thu, 22 Aug 2019 03:20:50 +0200 Subject: [PATCH 08/12] Rebrand to TrackPlugX --- plugin/CMakeLists.txt | 2 +- plugin/{TrackPlug.yml => TrackPlugX.yml} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename plugin/{TrackPlug.yml => TrackPlugX.yml} (89%) diff --git a/plugin/CMakeLists.txt b/plugin/CMakeLists.txt index 7e67f11..dbc8444 100644 --- a/plugin/CMakeLists.txt +++ b/plugin/CMakeLists.txt @@ -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") diff --git a/plugin/TrackPlug.yml b/plugin/TrackPlugX.yml similarity index 89% rename from plugin/TrackPlug.yml rename to plugin/TrackPlugX.yml index 11cab3b..b34308e 100644 --- a/plugin/TrackPlug.yml +++ b/plugin/TrackPlugX.yml @@ -1,4 +1,4 @@ -TrackPlug: +TrackPlugX: attributes: 0 version: major: 1 From 2161d1c11df76f0508a9ba61cc8464a6f57bb57f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Chv=C3=ADla?= Date: Thu, 22 Aug 2019 04:27:04 +0200 Subject: [PATCH 09/12] app: Add more region codes --- app/index.lua | 79 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 65 insertions(+), 14 deletions(-) diff --git a/app/index.lua b/app/index.lua index 31a67b0..9633da9 100644 --- a/app/index.lua +++ b/app/index.lua @@ -52,6 +52,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") @@ -62,20 +125,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 = "US" - elseif regioncode == "PCSB" or regioncode == "PCSF" then - file.region = "EU" - elseif regioncode == "PCSC" or regioncode == "PCSG" then - file.region = "JP" - elseif regioncode == "PCSD" or regioncode == "PCSH" then - file.region = "ASIA" - elseif string.sub(file.name,1,6) == "PSPEMU" then - file.region = "PSP/PSX" - 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 From f03aa4a50471f0bf8e925fd89b59583886650d88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Chv=C3=ADla?= Date: Thu, 22 Aug 2019 04:49:02 +0200 Subject: [PATCH 10/12] plugin: Bump up the version to 2.1 --- plugin/TrackPlugX.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) mode change 100644 => 100755 plugin/TrackPlugX.yml diff --git a/plugin/TrackPlugX.yml b/plugin/TrackPlugX.yml old mode 100644 new mode 100755 index b34308e..c8b86b3 --- a/plugin/TrackPlugX.yml +++ b/plugin/TrackPlugX.yml @@ -1,8 +1,8 @@ TrackPlugX: attributes: 0 version: - major: 1 - minor: 2 + major: 2 + minor: 1 main: start: module_start stop: module_stop From 50160454fc6ebcfc51ecef5d973b0229f2453751 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Chv=C3=ADla?= Date: Fri, 23 Aug 2019 01:18:05 +0200 Subject: [PATCH 11/12] plugin: Write pspemu Title to archive for bubbles as well MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Get around bug in ABM/lpp-vita where SFO Title is wrongly parsed This isn't ideal but ¯\_(ツ)_/¯ --- plugin/main.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/plugin/main.c b/plugin/main.c index 989a54d..638d627 100644 --- a/plugin/main.c +++ b/plugin/main.c @@ -14,6 +14,7 @@ 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]; @@ -23,6 +24,7 @@ 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) { @@ -54,6 +56,7 @@ static void write_playtime() { 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); @@ -80,8 +83,12 @@ static int check_adrenaline() { if (title[0] == 0 || !strncmp(title, "XMB", 3)) return 0; - // Game changed? - if (strncmp(adrenaline_titleid, titleid, 9)) { + // 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 @@ -102,6 +109,8 @@ int sub_810053F8_patched(int a1, int a2) { // If using custom bubble if (strncmp(pspemu_titleid, "PSPEMUCFW", 9)) { is_pspemu_custom_bbl = 1; + strcpy(adrenaline_titleid, pspemu_titleid); + load_playtime(pspemu_titleid); } @@ -113,8 +122,9 @@ int sub_810053F8_patched(int a1, int a2) { static int tracker_thread(SceSize args, void *argp) { while (1) { if (is_pspemu_loaded) { - // Check if XMB/game has changed - if (!is_pspemu_custom_bbl && !check_adrenaline()) { + // Check if XMB/game has changed, write Title if necessary + int ret = check_adrenaline(); + if (!is_pspemu_custom_bbl && !ret) { goto CONT; } } From 9227503bef4f9a22ee02afd6b16330b7764532d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Chv=C3=ADla?= Date: Fri, 23 Aug 2019 01:18:29 +0200 Subject: [PATCH 12/12] app: Update for latest lpp-vita --- app/index.lua | 760 +++++++++++++++++++++++++------------------------- 1 file changed, 380 insertions(+), 380 deletions(-) diff --git a/app/index.lua b/app/index.lua index 9633da9..5ea35d8 100644 --- a/app/index.lua +++ b/app/index.lua @@ -5,257 +5,257 @@ System.createDirectory("ux0:/data/TrackPlugArchive") -- Scanning TrackPlug folder local tbl = System.listDirectory("ux0:/data/TrackPlug") if tbl == nil then - tbl = {} + tbl = {} end -- Convert a 32 bit binary string to a 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" + 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 + -- 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 + 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 + 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) - file.region = getRegion(titleid) + 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 + 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 local colors = { - {Color.new(0,132,255), Color.new(72,185,255), Color.new(0,132,255)}, -- Cyan - {Color.new(255,132,0), Color.new(255,185,72), Color.new(255,132,0)}, -- Orange - {Color.new(255,72,72), Color.new(255,132,132), Color.new(255,72,72)}, -- Pink - {Color.new(255,0,0), Color.new(255,72,72), Color.new(255,0,0)}, -- Red - {Color.new(255,72,255), Color.new(255,185,255), Color.new(255,72,255)}, -- Magenta - {Color.new(72,72,72), Color.new(0,0,0), Color.new(0,255,0)} -- Black'N'Green + {Color.new(0,132,255), Color.new(72,185,255), Color.new(0,132,255)}, -- Cyan + {Color.new(255,132,0), Color.new(255,185,72), Color.new(255,132,0)}, -- Orange + {Color.new(255,72,72), Color.new(255,132,132), Color.new(255,72,72)}, -- Pink + {Color.new(255,0,0), Color.new(255,72,72), Color.new(255,0,0)}, -- Red + {Color.new(255,72,255), Color.new(255,185,255), Color.new(255,72,255)}, -- Magenta + {Color.new(72,72,72), Color.new(0,0,0), Color.new(0,255,0)} -- Black'N'Green } if col_idx == nil then - col_idx = 6 + col_idx = 6 end -local function LoadWave(height,dim,f,style,x_dim) - if style == 1 then - f=f or 0.1 - local onda={pi=math.pi,Frec=f,Long_onda=dim,Amplitud=height} - function onda:color(a,b,c) self.a=a self.b=b self.c=c end - function onda:init(desfase) - desfase=desfase or 0 - if not self.contador then - self.contador=Timer.new() - end - if not self.a or not self.b or not self.c then - self.a = 0 - self.b = 0 - self.c = 255 - end - local t,x,y,i - t = Timer.getTime(self.contador)/1000+desfase - for x = 0,x_dim,4 do - y = 252+self.Amplitud*math.sin(2*self.pi*(t*self.Frec-x/self.Long_onda)) - i = self.Amplitud*(-2*self.pi/self.Long_onda)*math.cos(2*self.pi*(t*self.Frec-x/self.Long_onda)) - Graphics.drawLine(x-200,x+200,y-i*200,y+i*200,Color.new(self.a,self.b,self.c,math.floor(x/40))) - end - collectgarbage() - end - function onda:destroy() - Timer.destroy(self.contador) - end - return onda - end - if style == 2 then - f=f or 0.1 - local onda={pi=math.pi,Frec=f,Long_onda=dim,Amplitud=height} - function onda:color(a,b,c) self.a=a self.b=b self.c=c end - function onda:init(desfase) - desfase=desfase or 0 - if not self.contador then - self.contador=Timer.new() - end - if not self.a or not self.b or not self.c then - self.a = 0 - self.b = 0 - self.c = 255 - end - local t,x,y,i,a - t = Timer.getTime(self.contador)/1000+desfase - if self.Amplitud <= 5 then - self.aumento = true - elseif self.Amplitud >= 110 then - self.aumento = false - end - if self.aumento then - self.Amplitud = self.Amplitud+0.1 - else - self.Amplitud = self.Amplitud-0.1 - end - for x = 0,x_dim,10 do - y = 272+self.Amplitud*math.sin(2*self.pi*(t*self.Frec-x/self.Long_onda)) - i = self.Amplitud*(-2*self.pi/self.Long_onda)*math.cos(2*self.pi*(t*self.Frec-x/self.Long_onda)) - for a = -3,3 do - Graphics.drawLine(x-20,x+20,a+y-i*20,a+y+i*20,Color.new(self.a,self.b,self.c,25-math.abs(a*5))) - end - end - collectgarbage() - end - function onda:destroy() - Timer.destroy(self.contador) - end - return onda - end - if style == 3 then - f=f or 0.1 - local onda={pi=math.pi,Frec=f,Long_onda=dim,Amplitud=height} - function onda:color(a,b,c) self.Color=Color.new(a,b,c,40) end - function onda:init(desfase) - desfase=desfase or 0 - if not self.contador then - self.contador=Timer.new() - end - if not self.Color then - self.Color=Color.new(0,0,255,40) - end - local t,x,y,i - t = Timer.getTime(self.contador)/1000+desfase - for x = 0,x_dim do - y = 252+self.Amplitud*math.sin(2*self.pi*(t*self.Frec-x/self.Long_onda)) - Graphics.drawLine(x,x,y,240,self.Color) - end - collectgarbage() - end - function onda:destroy() - Timer.destroy(self.contador) - end - return onda - end +local function LoadWave(height,dim,f,style,x_dim) + if style == 1 then + f=f or 0.1 + local onda={pi=math.pi,Frec=f,Long_onda=dim,Amplitud=height} + function onda:color(a,b,c) self.a=a self.b=b self.c=c end + function onda:init(desfase) + desfase=desfase or 0 + if not self.contador then + self.contador=Timer.new() + end + if not self.a or not self.b or not self.c then + self.a = 0 + self.b = 0 + self.c = 255 + end + local t,x,y,i + t = Timer.getTime(self.contador)/1000+desfase + for x = 0,x_dim,4 do + y = 252+self.Amplitud*math.sin(2*self.pi*(t*self.Frec-x/self.Long_onda)) + i = self.Amplitud*(-2*self.pi/self.Long_onda)*math.cos(2*self.pi*(t*self.Frec-x/self.Long_onda)) + Graphics.drawLine(x-200,x+200,y-i*200,y+i*200,Color.new(self.a,self.b,self.c,math.floor(x/40))) + end + collectgarbage() + end + function onda:destroy() + Timer.destroy(self.contador) + end + return onda + end + if style == 2 then + f=f or 0.1 + local onda={pi=math.pi,Frec=f,Long_onda=dim,Amplitud=height} + function onda:color(a,b,c) self.a=a self.b=b self.c=c end + function onda:init(desfase) + desfase=desfase or 0 + if not self.contador then + self.contador=Timer.new() + end + if not self.a or not self.b or not self.c then + self.a = 0 + self.b = 0 + self.c = 255 + end + local t,x,y,i,a + t = Timer.getTime(self.contador)/1000+desfase + if self.Amplitud <= 5 then + self.aumento = true + elseif self.Amplitud >= 110 then + self.aumento = false + end + if self.aumento then + self.Amplitud = self.Amplitud+0.1 + else + self.Amplitud = self.Amplitud-0.1 + end + for x = 0,x_dim,10 do + y = 272+self.Amplitud*math.sin(2*self.pi*(t*self.Frec-x/self.Long_onda)) + i = self.Amplitud*(-2*self.pi/self.Long_onda)*math.cos(2*self.pi*(t*self.Frec-x/self.Long_onda)) + for a = -3,3 do + Graphics.drawLine(x-20,x+20,a+y-i*20,a+y+i*20,Color.new(self.a,self.b,self.c,25-math.abs(a*5))) + end + end + collectgarbage() + end + function onda:destroy() + Timer.destroy(self.contador) + end + return onda + end + if style == 3 then + f=f or 0.1 + local onda={pi=math.pi,Frec=f,Long_onda=dim,Amplitud=height} + function onda:color(a,b,c) self.Color=Color.new(a,b,c,40) end + function onda:init(desfase) + desfase=desfase or 0 + if not self.contador then + self.contador=Timer.new() + end + if not self.Color then + self.Color=Color.new(0,0,255,40) + end + local t,x,y,i + t = Timer.getTime(self.contador)/1000+desfase + for x = 0,x_dim do + y = 252+self.Amplitud*math.sin(2*self.pi*(t*self.Frec-x/self.Long_onda)) + Graphics.drawLine(x,x,y,240,self.Color) + end + collectgarbage() + end + function onda:destroy() + Timer.destroy(self.contador) + end + return onda + end end wav = LoadWave(15,1160, 0.1, 2, 960) wav:color(Color.getR(colors[col_idx][3]),Color.getG(colors[col_idx][3]),Color.getB(colors[col_idx][3])) @@ -268,17 +268,17 @@ local orders = {"Name", "Playtime"} -- Ordering titles table.sort(tbl, function (a, b) return (a.title:lower() < b.title:lower() ) end) function resortList(o_type, m_idx) - local old_id = tbl[m_idx].id - if o_type == 1 then -- Name - table.sort(tbl, function (a, b) return (a.title:lower() < b.title:lower() ) end) - elseif o_type == 2 then -- Playtime - table.sort(tbl, function (a, b) return (a.rtime > b.rtime ) end) - end - for i, title in pairs(tbl) do - if title.id == old_id then - return i - end - end + local old_id = tbl[m_idx].id + if o_type == 1 then -- Name + table.sort(tbl, function (a, b) return (a.title:lower() < b.title:lower() ) end) + elseif o_type == 2 then -- Playtime + table.sort(tbl, function (a, b) return (a.rtime > b.rtime ) end) + end + for i, title in pairs(tbl) do + if title.id == old_id then + return i + end + end end -- Internal stuffs @@ -290,23 +290,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 @@ -319,152 +319,152 @@ local new_list_idx = nil local real_i = 1 local big_tbl = {} function RenderList() - local r_max = 0 - local r = 0 - big_tbl = {} - if #tbl < 4 then - r_max = 8 - else - r_max = 2 - end - while r < r_max do - for k, v in pairs(tbl) do - table.insert(big_tbl, v) - end - r = r + 1 - end - local y = -124 - local i = list_idx - 1 - if not freeze then - if decrease then - sel_val = sel_val - 4 - if sel_val == 0 then - decrease = false - end - else - sel_val = sel_val + 4 - if sel_val == 128 then - decrease = true - end - end - end - local sclr = Color.new(sel_val, sel_val, sel_val, 100) - Graphics.fillRect(0, 960, 4, 140, sclr) - Graphics.debugPrint(800, 520, "Order: " .. orders[order_idx], white) - if mov_y ~= 0 then - mov_y = mov_y + mov_step - if math.abs(mov_y) >= 132 then - mov_y = 0 - list_idx = new_list_idx - i = new_list_idx - 1 - end - end - while i <= list_idx + 4 do - if i < 1 then - real_i = i - i = #big_tbl - math.abs(i) - end - if i ~= list_idx + 4 then - Graphics.drawImage(5, y + mov_y, big_tbl[i].icon) - end - Graphics.debugPrint(150, y + 25 + mov_y, big_tbl[i].title, yellow) - Graphics.debugPrint(150, y + 45 + mov_y, "Title ID: " .. big_tbl[i].id, white) - Graphics.debugPrint(150, y + 65 + mov_y, "Region: " .. big_tbl[i].region, white) - Graphics.debugPrint(150, y + 85 + mov_y, "Playtime: " .. big_tbl[i].ptime, white) - local r_idx = i % #tbl - if r_idx == 0 then - r_idx = #tbl - end - Graphics.debugPrint(900, y + 85 + mov_y, "#" .. r_idx, white) - y = y + 132 - if real_i <= 0 then - i = real_i - real_i = 1 - end - i = i + 1 - end + local r_max = 0 + local r = 0 + big_tbl = {} + if #tbl < 4 then + r_max = 8 + else + r_max = 2 + end + while r < r_max do + for k, v in pairs(tbl) do + table.insert(big_tbl, v) + end + r = r + 1 + end + local y = -124 + local i = list_idx - 1 + if not freeze then + if decrease then + sel_val = sel_val - 4 + if sel_val == 0 then + decrease = false + end + else + sel_val = sel_val + 4 + if sel_val == 128 then + decrease = true + end + end + end + local sclr = Color.new(sel_val, sel_val, sel_val, 100) + Graphics.fillRect(0, 960, 4, 140, sclr) + Graphics.debugPrint(800, 520, "Order: " .. orders[order_idx], white) + if mov_y ~= 0 then + mov_y = mov_y + mov_step + if math.abs(mov_y) >= 132 then + mov_y = 0 + list_idx = new_list_idx + i = new_list_idx - 1 + end + end + while i <= list_idx + 4 do + if i < 1 then + real_i = i + i = #big_tbl - math.abs(i) + end + if i ~= list_idx + 4 then + Graphics.drawImage(5, y + mov_y, big_tbl[i].icon) + end + Graphics.debugPrint(150, y + 25 + mov_y, big_tbl[i].title, yellow) + Graphics.debugPrint(150, y + 45 + mov_y, "Title ID: " .. big_tbl[i].id, white) + Graphics.debugPrint(150, y + 65 + mov_y, "Region: " .. big_tbl[i].region, white) + Graphics.debugPrint(150, y + 85 + mov_y, "Playtime: " .. big_tbl[i].ptime, white) + local r_idx = i % #tbl + if r_idx == 0 then + r_idx = #tbl + end + Graphics.debugPrint(900, y + 85 + mov_y, "#" .. r_idx, white) + y = y + 132 + if real_i <= 0 then + i = real_i + real_i = 1 + end + i = i + 1 + end end -- Main loop local f_idx = 1 local oldpad = Controls.read() while #tbl > 0 do - Graphics.initBlend() - Graphics.fillRect(0,960,0,544,colors[col_idx][2]) - wav:init() - RenderList() - if freeze then - showAlarm("Do you want to delete this record permanently?", f_idx) - end - Graphics.termBlend() - Screen.flip() - Screen.waitVblankStart() - local pad = Controls.read() - if Controls.check(pad, SCE_CTRL_UP) and mov_y == 0 then - if freeze then - f_idx = 1 - else - new_list_idx = list_idx - 1 - if new_list_idx == 0 then - new_list_idx = #tbl - end - mov_y = 1 - mov_step = 33 - end - elseif Controls.check(pad, SCE_CTRL_DOWN) and mov_y == 0 then - if freeze then - f_idx = 2 - else - new_list_idx = list_idx + 1 - if new_list_idx > #tbl then - new_list_idx = 1 - end - mov_y = -1 - mov_step = -33 - end - elseif Controls.check(pad, SCE_CTRL_LTRIGGER) and not Controls.check(oldpad, SCE_CTRL_LTRIGGER) and not freeze then - order_idx = order_idx - 1 - if order_idx == 0 then - order_idx = #orders - end - list_idx = resortList(order_idx, list_idx) - elseif Controls.check(pad, SCE_CTRL_RTRIGGER) and not Controls.check(oldpad, SCE_CTRL_RTRIGGER) and not freeze then - order_idx = order_idx + 1 - if order_idx > #orders then - order_idx = 1 - end - list_idx = resortList(order_idx, list_idx) - elseif Controls.check(pad, SCE_CTRL_TRIANGLE) and not Controls.check(oldpad, SCE_CTRL_TRIANGLE) and not freeze then - freeze = true - f_idx = 1 - elseif Controls.check(pad, SCE_CTRL_CROSS) and not Controls.check(oldpad, SCE_CTRL_CROSS) and freeze then - freeze = false - if f_idx == 1 then -- Delete - System.deleteFile("ux0:/data/TrackPlug/" .. tbl[list_idx].name) - table.remove(tbl, list_idx) - if list_idx > #tbl then - list_idx = list_idx - 1 - end - end - elseif Controls.check(pad, SCE_CTRL_SELECT) and not Controls.check(oldpad, SCE_CTRL_SELECT) then - col_idx = col_idx + 1 - if col_idx > #colors then - col_idx = 1 - end - wav:color(Color.getR(colors[col_idx][3]),Color.getG(colors[col_idx][3]),Color.getB(colors[col_idx][3])) - fd = System.openFile("ux0:/data/TrackPlug/config.lua", FCREATE) - System.writeFile(fd, "col_idx="..col_idx, 9) - System.closeFile(fd) - end - oldpad = pad + Graphics.initBlend() + Graphics.fillRect(0,960,0,544,colors[col_idx][2]) + wav:init() + RenderList() + if freeze then + showAlarm("Do you want to delete this record permanently?", f_idx) + end + Graphics.termBlend() + Screen.flip() + Screen.waitVblankStart() + local pad = Controls.read() + if Controls.check(pad, SCE_CTRL_UP) and mov_y == 0 then + if freeze then + f_idx = 1 + else + new_list_idx = list_idx - 1 + if new_list_idx == 0 then + new_list_idx = #tbl + end + mov_y = 1 + mov_step = 11 + end + elseif Controls.check(pad, SCE_CTRL_DOWN) and mov_y == 0 then + if freeze then + f_idx = 2 + else + new_list_idx = list_idx + 1 + if new_list_idx > #tbl then + new_list_idx = 1 + end + mov_y = -1 + mov_step = -11 + end + elseif Controls.check(pad, SCE_CTRL_LTRIGGER) and not Controls.check(oldpad, SCE_CTRL_LTRIGGER) and not freeze then + order_idx = order_idx - 1 + if order_idx == 0 then + order_idx = #orders + end + list_idx = resortList(order_idx, list_idx) + elseif Controls.check(pad, SCE_CTRL_RTRIGGER) and not Controls.check(oldpad, SCE_CTRL_RTRIGGER) and not freeze then + order_idx = order_idx + 1 + if order_idx > #orders then + order_idx = 1 + end + list_idx = resortList(order_idx, list_idx) + elseif Controls.check(pad, SCE_CTRL_TRIANGLE) and not Controls.check(oldpad, SCE_CTRL_TRIANGLE) and not freeze then + freeze = true + f_idx = 1 + elseif Controls.check(pad, SCE_CTRL_CROSS) and not Controls.check(oldpad, SCE_CTRL_CROSS) and freeze then + freeze = false + if f_idx == 1 then -- Delete + System.deleteFile("ux0:/data/TrackPlug/" .. tbl[list_idx].name) + table.remove(tbl, list_idx) + if list_idx > #tbl then + list_idx = list_idx - 1 + end + end + elseif Controls.check(pad, SCE_CTRL_SELECT) and not Controls.check(oldpad, SCE_CTRL_SELECT) then + col_idx = col_idx + 1 + if col_idx > #colors then + col_idx = 1 + end + wav:color(Color.getR(colors[col_idx][3]),Color.getG(colors[col_idx][3]),Color.getB(colors[col_idx][3])) + fd = System.openFile("ux0:/data/TrackPlug/config.lua", FCREATE) + System.writeFile(fd, "col_idx="..col_idx, 9) + System.closeFile(fd) + end + oldpad = pad 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() -end \ No newline at end of file + Graphics.initBlend() + Screen.clear() + Graphics.debugPrint(5, 5, "No games tracked yet.", white) + Graphics.termBlend() + Screen.flip() + Screen.waitVblankStart() +end