mirror of
https://github.com/etaHEN/etaHEN.git
synced 2026-01-12 11:25:27 +08:00
etaHEN 2.5B
This commit is contained in:
@@ -4,9 +4,9 @@ PS5_PORT ?= 9021
|
||||
ELF := hen.elf
|
||||
BIN := hen.bin
|
||||
|
||||
CFLAGS := -std=c++11 -Wall -Werror -D_KERNEL -I./include -O2 -fno-builtin -nostdlib -fno-stack-protector -fno-plt -fPIC -Wno-error=frame-address -Wno-unused-const-variable
|
||||
CFLAGS := -std=c++11 -Wall -Werror -D_KERNEL -I./include -O2 -fno-builtin -nostartfiles -nostdlib -fno-stack-protector -fno-plt -fPIC -Wno-error=frame-address -I${PS5_PAYLOAD_SDK}include/freebsd -g3
|
||||
#SFLAGS := -nostartfiles -nostdlib -fPIC
|
||||
LFLAGS := -Xlinker -T ./link.x -Wl,--build-id=none -nostartfiles
|
||||
LFLAGS := -Xlinker -T ./link.x -Wl,--build-id=none
|
||||
|
||||
ODIR := build
|
||||
SDIR := src
|
||||
|
||||
@@ -60,7 +60,7 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0")
|
||||
target_sources(${PROJECT_NAME} PRIVATE ${SrcFiles})
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE "${D_CWD}/include" "${D_SRC}/../Byepervisor/include" "${D_SRC}/../Byepervisor_DevKit/include" "${D_SRC}/../Byepervisor_DevKit/include/offsets")
|
||||
target_link_directories (${PROJECT_NAME} PUBLIC "${PROJECT_ROOT}/lib")
|
||||
target_link_libraries (${PROJECT_NAME} PUBLIC NineS SceSystemService SceUserService kernel_sys elfldr sqlite3)
|
||||
target_link_libraries (${PROJECT_NAME} PUBLIC NineS SceSystemService SceUserService kernel_sys elfldr sqlite3 SceNotification)
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
add_dependencies(${PROJECT_NAME} daemon util shellui)
|
||||
|
||||
|
||||
BIN
Source Code/bootstrapper/assets/fps.prx
Normal file
BIN
Source Code/bootstrapper/assets/fps.prx
Normal file
Binary file not shown.
@@ -73,4 +73,15 @@ __asm__(".intel_syntax noprefix\n"
|
||||
"kstuff_size:\n"
|
||||
".int kstuff_end - kstuff_start\n"
|
||||
|
||||
".global fps_prx_start\n"
|
||||
".type fps_prx_start, @object\n"
|
||||
".align 16\n"
|
||||
"fps_prx_start:\n"
|
||||
".incbin \"assets/fps.prx\"\n"
|
||||
"fps_prx_end:\n"
|
||||
".global fps_prx_size\n"
|
||||
".type fps_prx_size, @object\n"
|
||||
".align 4\n"
|
||||
"fps_prx_size:\n"
|
||||
".int fps_prx_end - fps_prx_start\n"
|
||||
);
|
||||
|
||||
@@ -72,7 +72,63 @@ along with this program; see the file COPYING. If not, see
|
||||
|
||||
extern uint8_t fps_prx_start[];
|
||||
extern const unsigned int fps_prx_size;
|
||||
|
||||
int sceNotificationSend(int userId, bool isLogged, const char* payload);
|
||||
}
|
||||
|
||||
|
||||
const char json_payload[] =
|
||||
"{\n"
|
||||
" \"rawData\": {\n"
|
||||
" \"viewTemplateType\": \"InteractiveToastTemplateB\",\n"
|
||||
" \"channelType\": \"Downloads\",\n"
|
||||
" \"useCaseId\": \"IDC\",\n"
|
||||
" \"toastOverwriteType\": \"No\",\n"
|
||||
" \"isImmediate\": true,\n"
|
||||
" \"priority\": 100,\n"
|
||||
" \"viewData\": {\n"
|
||||
" \"icon\": {\n"
|
||||
" \"type\": \"Url\",\n"
|
||||
" \"parameters\": {\n"
|
||||
" \"url\": \"/user/data/etaHEN/etahen.png\"\n"
|
||||
" }\n"
|
||||
" },\n"
|
||||
" \"message\": {\n"
|
||||
" \"body\": \"etaHEN is starting...\"\n"
|
||||
" },\n"
|
||||
" \"subMessage\": {\n"
|
||||
" \"body\": \"Please Wait For The Welcome Message\"\n"
|
||||
" },\n"
|
||||
" \"actions\": [\n"
|
||||
" {\n"
|
||||
" \"actionName\": \"Go to Debug Settings\",\n"
|
||||
" \"actionType\": \"DeepLink\",\n"
|
||||
" \"defaultFocus\": true,\n"
|
||||
" \"parameters\": {\n"
|
||||
" \"actionUrl\": \"pssettings:play?function=debug_settings\"\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" ]\n"
|
||||
" },\n"
|
||||
" \"platformViews\": {\n"
|
||||
" \"previewDisabled\": {\n"
|
||||
" \"viewData\": {\n"
|
||||
" \"icon\": {\n"
|
||||
" \"type\": \"Predefined\",\n"
|
||||
" \"parameters\": {\n"
|
||||
" \"icon\": \"download\"\n"
|
||||
" }\n"
|
||||
" },\n"
|
||||
" \"message\": {\n"
|
||||
" \"body\": \"etaHEN is starting...\"\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" },\n"
|
||||
" \"createdDateTime\": \"2025-12-14T03:14:51.473Z\",\n"
|
||||
" \"localNotificationId\": \"588193127\"\n"
|
||||
"}";
|
||||
|
||||
/******************************************************************************
|
||||
* Macros and Constants
|
||||
@@ -280,8 +336,22 @@ static void cleanup(void);
|
||||
return;
|
||||
}
|
||||
close(fd);
|
||||
#endif
|
||||
if (!if_exists("/data/etaHEN/assets/store.png")) {
|
||||
#endif
|
||||
#if 0
|
||||
/// if (!if_exists("/data/etaHEN/fps.prx")) {
|
||||
int fd = open("/data/etaHEN/fps.prx", O_WRONLY | O_CREAT | O_TRUNC, 0777);
|
||||
if (fd == -1) {
|
||||
perror("open failed");
|
||||
return;
|
||||
}
|
||||
if (write(fd, &fps_prx_start, fps_prx_size) == -1) {
|
||||
perror("write failed");
|
||||
}
|
||||
close(fd);
|
||||
// }
|
||||
#endif
|
||||
|
||||
if (!if_exists("/data/etaHEN/assets/store.png")) {
|
||||
int fd = open("/data/etaHEN/assets/store.png", O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||
if (fd == -1) {
|
||||
perror("open failed");
|
||||
@@ -304,6 +374,18 @@ if (!if_exists("/data/etaHEN/assets/store.png")) {
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
if (!if_exists("/data/etaHEN/etahen.png")) {
|
||||
int fd = open("/data/etaHEN/etahen.png", O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||
if (fd == -1) {
|
||||
perror("open failed");
|
||||
return;
|
||||
}
|
||||
if (write(fd, & sicon_start, sicon_size) == -1) {
|
||||
perror("write failed");
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
if (!if_exists("/system_ex/rnps/apps/NPXS40008/assets/src/modules/categoriesList/assets/texture/etahen_sicon.png")) {
|
||||
int fd = open("/system_ex/rnps/apps/NPXS40008/assets/src/modules/categoriesList/assets/texture/etahen_sicon.png", O_WRONLY | O_CREAT | O_TRUNC, 0666);
|
||||
@@ -932,9 +1014,9 @@ bool sceKernelIsTestKit() {
|
||||
return if_exists("/system/priv/lib/libSceDeci5Ttyp.sprx");
|
||||
}
|
||||
#define PUBLIC_TEST 0
|
||||
#define EXPIRE_YEAR 2025
|
||||
#define EXPIRE_MONTH 12
|
||||
#define EXPIRE_DAY 25
|
||||
#define EXPIRE_YEAR 2026
|
||||
#define EXPIRE_MONTH 1
|
||||
#define EXPIRE_DAY 1
|
||||
|
||||
|
||||
bool isPastBetaDate(int year, int month, int day);
|
||||
@@ -1034,16 +1116,14 @@ int main(void) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
notify("[Bootstrapper] etaHEN is starting...\n DO NOT EXIT \nwait for "
|
||||
"the etaHEN welcome message");
|
||||
|
||||
klog_puts("============== Spawner (Bootstrapper) Started =================");
|
||||
|
||||
mkdir("/data/etaHEN", 0777);
|
||||
mkdir("/data/etaHEN/plugins", 0777);
|
||||
mkdir("/data/etaHEN/payloads", 0777);
|
||||
mkdir("/data/etaHEN/daemons", 0777);
|
||||
mkdir("/data/etaHEN/assets", 0777);
|
||||
mkdir("/data/etaHEN/games", 0777);
|
||||
|
||||
klog_printf("Registering signal handler ...");
|
||||
fault_handler_init(cleanup);
|
||||
@@ -1066,6 +1146,8 @@ int main(void) {
|
||||
write_embedded_assets();
|
||||
klog_printf(" Written!\n");
|
||||
|
||||
sceNotificationSend(0xFE, true, &json_payload[0]);
|
||||
|
||||
klog_printf("Unmounting /update forcefully ...");
|
||||
// block updates
|
||||
unlink("/update/PS5UPDATE.PUP");
|
||||
@@ -1086,7 +1168,7 @@ int main(void) {
|
||||
klog_puts("kstuff loading disabled in config.ini or no_kstuff file found");
|
||||
}
|
||||
if (!dont_load_kstuff && sys_ver.version >= 0x3000000) {
|
||||
notify("Loading kstuff ...");
|
||||
//notify("Loading kstuff ...");
|
||||
|
||||
bool cleanup_kstuff = false;
|
||||
uint8_t* kstuff_address = get_kstuff_address(cleanup_kstuff);
|
||||
|
||||
@@ -62,7 +62,7 @@ target_sources(${PROJECT_NAME} PRIVATE ${SrcFiles})
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE "${D_CWD}/include")
|
||||
target_link_directories (${PROJECT_NAME} PUBLIC "${PROJECT_ROOT}/lib")
|
||||
add_dependencies(${PROJECT_NAME} NineS shellui hijacker SelfDecryptor elfldr)
|
||||
target_link_libraries (${PROJECT_NAME} PUBLIC hijacker ScePad SceSystemService SceNet SceRegMgr SceSysmodule SceUserService SceNetCtl SceSysCore kernel_sys SceAppInstUtil NineS elfldr SelfDecryptor)
|
||||
target_link_libraries (${PROJECT_NAME} PUBLIC hijacker ScePad SceSystemService SceNotification SceNet SceRegMgr SceSysmodule SceUserService SceNetCtl SceSysCore kernel_sys SceAppInstUtil NineS elfldr SelfDecryptor)
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
# Add post-build command
|
||||
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
|
||||
|
||||
@@ -36,11 +36,14 @@ struct daemon_settings {
|
||||
bool allow_data = true;
|
||||
bool DPIv2 = false;
|
||||
bool elf_loader = true;
|
||||
bool enable_fan_speed = false;
|
||||
bool toolbox_auto_start = true;
|
||||
bool debug_app_jb_msg = false;
|
||||
bool auto_eject_disc = false;
|
||||
bool overlay_fps = false;
|
||||
StartOpts start_opt = NONE;
|
||||
int seconds = 0; // seconds to wait before starting toolbox
|
||||
int fan_threshold = 77; // default fan threshold
|
||||
};
|
||||
|
||||
extern struct daemon_settings global_conf;
|
||||
|
||||
@@ -381,6 +381,7 @@ bool is_whitelisted_app(const std::string &tid) {
|
||||
"NPXS39041",
|
||||
"DUMP00000",
|
||||
"PKGI13337",
|
||||
"PKGI12345",
|
||||
"TOOL00001",
|
||||
};
|
||||
|
||||
@@ -553,6 +554,10 @@ bool Open_Utility_Elf(const char *path, uint8_t **buffer) {
|
||||
return true;
|
||||
}
|
||||
bool cmd_enable_fps(int appid);
|
||||
void LoadSettings();
|
||||
extern bool is_800;
|
||||
bool set_fan_threshold(int THRESHOLDTEMP);
|
||||
bool cmd_enable_fps_new(int appid);
|
||||
void *fifo_and_dumper_thread(void *args) noexcept {
|
||||
char *json_str = nullptr;
|
||||
constexpr uint32_t MAX_TOKENS = 256;
|
||||
@@ -596,15 +601,25 @@ void *fifo_and_dumper_thread(void *args) noexcept {
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&jb_lock);
|
||||
|
||||
if(global_conf.enable_fan_speed)
|
||||
set_fan_threshold(global_conf.fan_threshold);
|
||||
|
||||
int bappid;
|
||||
if (!Get_Running_App_TID(tid, bappid)) {
|
||||
pthread_mutex_unlock(&jb_lock);
|
||||
continue;
|
||||
}
|
||||
#if 0
|
||||
if(tid.rfind("CUSA") != std::string::npos || tid.rfind("SCUS") != std::string::npos)
|
||||
cmd_enable_fps(bappid);
|
||||
#endif
|
||||
|
||||
|
||||
if( if_exists("/system_tmp/fps_enabled") && (tid.rfind("CUSA") != std::string::npos || tid.rfind("SCUS") != std::string::npos)){
|
||||
// cmd_enable_fps(bappid);
|
||||
if(is_800)
|
||||
cmd_enable_fps_new(bappid);
|
||||
else
|
||||
cmd_enable_fps(bappid);
|
||||
}
|
||||
|
||||
if (is_dumper_enabled) {
|
||||
if (strstr(tid.c_str(), "ITEM00001") != 0) {
|
||||
pthread_mutex_unlock(&jb_lock);
|
||||
@@ -719,7 +734,7 @@ void *fifo_and_dumper_thread(void *args) noexcept {
|
||||
notify(true, "App (PID %i) has been granted a jailbreak", reserved_value);
|
||||
|
||||
spawned->jailbreak(true);
|
||||
spawned.release();
|
||||
spawned.release();
|
||||
// jailbreak_proc(reserved_value);
|
||||
unlink(sandbox_dir.c_str());
|
||||
}
|
||||
|
||||
@@ -26,5 +26,28 @@
|
||||
"shellui_prx_size:\n"
|
||||
".int shellui_elf_end - shellui_elf_start\n"
|
||||
|
||||
".global fps_elf_start\n"
|
||||
".type fps_elf_start, @object\n"
|
||||
".align 16\n"
|
||||
"fps_elf_start:\n"
|
||||
".incbin \"assets/fps_elf.elf\"\n"
|
||||
"fps_elf_end:\n"
|
||||
".global fps_elf_size\n"
|
||||
".type fps_elf_size, @object\n"
|
||||
".align 4\n"
|
||||
"fps_elf_size:\n"
|
||||
".int fps_elf_end - fps_elf_start\n"
|
||||
|
||||
".global dumper_elf_start\n"
|
||||
".type dumper_elf_start, @object\n"
|
||||
".align 16\n"
|
||||
"dumper_elf_start:\n"
|
||||
".incbin \"assets/ps5-app-dumper.elf\"\n"
|
||||
"dumper_elf_end:\n"
|
||||
".global dumper_elf_size\n"
|
||||
".type dumper_elf_size, @object\n"
|
||||
".align 4\n"
|
||||
"dumper_elf_size:\n"
|
||||
".int dumper_elf_end - dumper_elf_start\n"
|
||||
|
||||
);
|
||||
@@ -107,6 +107,7 @@ extern "C" {
|
||||
// External data
|
||||
extern uint8_t ps5debug_start[];
|
||||
extern const unsigned int ps5debug_size;
|
||||
int sceNotificationSend(int userId, bool isLogged, const char* payload);
|
||||
|
||||
}
|
||||
|
||||
@@ -297,7 +298,7 @@ int ItemzLaunchByUri(const char* uri) {
|
||||
|
||||
bool cmd_enable_toolbox();
|
||||
void LoadSettings();
|
||||
|
||||
bool is_800 = false;
|
||||
int main() {
|
||||
char buz[255];
|
||||
pthread_t fifo_thr = nullptr;
|
||||
@@ -332,6 +333,7 @@ int main() {
|
||||
bool is_lite = if_exists("/system_tmp/lite_mode");
|
||||
bool toolbox_only = (fw_ver >= 0x10000);
|
||||
bool no_ps5debug = (fw_ver >= 0x800);
|
||||
is_800 = (fw_ver >= 0x800);
|
||||
|
||||
|
||||
LoadSettings();
|
||||
@@ -366,13 +368,60 @@ int main() {
|
||||
if (!elfldr_spawn("/", STDOUT_FILENO, ps5debug_start, "ps5debug"))
|
||||
notify(true, "Failed to load PS5Debug");
|
||||
}
|
||||
|
||||
// Display IP and service info
|
||||
std::string dpi_url = "Direct Package Installer V2: http://" + std::string(buz) + ":12800";
|
||||
notify(true,
|
||||
"etaHEN 2.4b by LM\n\nAIO HEN\n\nCurrent IP: %s\n\nFTP Port: "
|
||||
"1337\nKlog Port: 9081\n%s",
|
||||
buz, global_conf.DPIv2 ? dpi_url.c_str() : "");
|
||||
|
||||
const char json_payload[] =
|
||||
"{\n"
|
||||
" \"rawData\": {\n"
|
||||
" \"viewTemplateType\": \"InteractiveToastTemplateB\",\n"
|
||||
" \"channelType\": \"Downloads\",\n"
|
||||
" \"useCaseId\": \"IDC\",\n"
|
||||
" \"toastOverwriteType\": \"No\",\n"
|
||||
" \"isImmediate\": true,\n"
|
||||
" \"priority\": 100,\n"
|
||||
" \"viewData\": {\n"
|
||||
" \"icon\": {\n"
|
||||
" \"type\": \"Url\",\n"
|
||||
" \"parameters\": {\n"
|
||||
" \"url\": \"/user/data/etaHEN/etahen.png\"\n"
|
||||
" }\n"
|
||||
" },\n"
|
||||
" \"message\": {\n"
|
||||
" \"body\": \"etaHEN 2.5B AIO HEN By LM\"\n"
|
||||
" },\n"
|
||||
" \"subMessage\": {\n"
|
||||
" \"body\": \"Welcome to etaHEN\"\n"
|
||||
" },\n"
|
||||
" \"actions\": [\n"
|
||||
" {\n"
|
||||
" \"actionName\": \"Go to the etaHEN Toolbox\",\n"
|
||||
" \"actionType\": \"DeepLink\",\n"
|
||||
" \"defaultFocus\": true,\n"
|
||||
" \"parameters\": {\n"
|
||||
" \"actionUrl\": \"pssettings:play?function=debug_settings\"\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" ]\n"
|
||||
" },\n"
|
||||
" \"platformViews\": {\n"
|
||||
" \"previewDisabled\": {\n"
|
||||
" \"viewData\": {\n"
|
||||
" \"icon\": {\n"
|
||||
" \"type\": \"Predefined\",\n"
|
||||
" \"parameters\": {\n"
|
||||
" \"icon\": \"download\"\n"
|
||||
" }\n"
|
||||
" },\n"
|
||||
" \"message\": {\n"
|
||||
" \"body\": \"etaHEN Running\"\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" },\n"
|
||||
" \"createdDateTime\": \"2025-12-14T03:14:51.473Z\",\n"
|
||||
" \"localNotificationId\": \"588193127\"\n"
|
||||
"}";
|
||||
sceNotificationSend(0xFE, true, &json_payload[0]);
|
||||
|
||||
|
||||
etaHEN_log("StartUp thread created!! - welcome to etaHEN");
|
||||
|
||||
@@ -24,6 +24,7 @@ along with this program; see the file COPYING. If not, see
|
||||
#include <signal.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <strings.h>
|
||||
#include <sys/_pthreadtypes.h>
|
||||
#include <sys/_stdint.h>
|
||||
@@ -80,6 +81,9 @@ extern const unsigned int shellui_elf_size;
|
||||
extern uint8_t fps_elf_start[];
|
||||
extern const unsigned int fps_elf_size;
|
||||
|
||||
extern uint8_t dumper_elf_start[];
|
||||
extern const unsigned int dumper_elf_size;
|
||||
|
||||
bool Inject_Toolbox(int pid, uint8_t *elf);
|
||||
int sceKernelGetAppInfo(int pid, app_info_t *title);
|
||||
int sceKernelGetProcessName(int pid, char *name);
|
||||
@@ -346,51 +350,94 @@ int change_permissions_recursive(const char* path) {
|
||||
}
|
||||
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
struct ConfigState {
|
||||
time_t last_modified = 0;
|
||||
};
|
||||
|
||||
ConfigState config_state;
|
||||
|
||||
void LoadSettings() {
|
||||
if (if_exists("/data/etaHEN/config.ini")) {
|
||||
IniParser parser;
|
||||
if (ini_parser_load( & parser, "/data/etaHEN/config.ini")) {
|
||||
const char * libhijacker_cheats_str =
|
||||
ini_parser_get( & parser, "Settings.libhijacker_cheats", "0");
|
||||
const char * PS5Debug_str =
|
||||
ini_parser_get( & parser, "Settings.PS5Debug", "0");
|
||||
const char * start_option =
|
||||
ini_parser_get( & parser, "Settings.StartOption", "0");
|
||||
const char * DPI_v2 = ini_parser_get( & parser, "Settings.DPI_v2", "0");
|
||||
const char * auto_eject_disc = ini_parser_get( & parser, "Settings.auto_eject_disc", "0");
|
||||
// Check if the std::strings are not nullptr before converting
|
||||
global_conf.libhijacker_cheats =
|
||||
libhijacker_cheats_str ? atoi(libhijacker_cheats_str) : 0;
|
||||
global_conf.PS5Debug = PS5Debug_str ? atoi(PS5Debug_str) : 0;
|
||||
global_conf.start_opt =
|
||||
start_option ? (StartOpts) atoi(start_option) : NONE;
|
||||
global_conf.DPIv2 = DPI_v2 ? atoi(DPI_v2) : 0;
|
||||
global_conf.toolbox_auto_start = atoi(ini_parser_get( & parser, "Settings.toolbox_auto_start", "1"));
|
||||
|
||||
global_conf.seconds = atol(ini_parser_get( & parser, "Settings.Rest_Mode_Delay_Seconds", "0"));
|
||||
global_conf.debug_app_jb_msg = atoi(ini_parser_get( & parser, "Settings.APP_JB_Debug_Msg", "0"));
|
||||
global_conf.auto_eject_disc = auto_eject_disc ? atoi(auto_eject_disc) : 0;
|
||||
|
||||
if (if_exists("/mnt/usb0/toolbox_auto_start"))
|
||||
global_conf.toolbox_auto_start = false;
|
||||
} else {
|
||||
notify(true, "Failed to Read the Settings file");
|
||||
}
|
||||
} else {
|
||||
// Create default config if it doesn't exist
|
||||
struct stat file_stat;
|
||||
const char* config_path = "/data/etaHEN/config.ini";
|
||||
|
||||
// Check if file exists and get its modification time
|
||||
if (stat(config_path, &file_stat) != 0) {
|
||||
// File doesn't exist, create default config
|
||||
etaHEN_log("[Daemon] Config file not found. Creating default...");
|
||||
std::string ini_file(
|
||||
"[Settings]\nPS5Debug=0\nFTP=1\nlaunch_itemzflow="
|
||||
"0\ndiscord_rpc=0\nAllow_data_in_sandbox=1\nDPI=0\ntoolbox_auto_start=1\nDPI_v2=0\nKlog=0\nAPP_JB_Debug_Msg=0\nauto_eject_disc=0\n");
|
||||
int fd = open("/data/etaHEN/config.ini", O_WRONLY | O_CREAT | O_TRUNC, 0777);
|
||||
int fd = open(config_path, O_WRONLY | O_CREAT | O_TRUNC, 0777);
|
||||
if (fd >= 0) {
|
||||
write(fd, ini_file.c_str(), ini_file.length());
|
||||
close(fd);
|
||||
notify(true, "etaHEN config created! @ /data/etaHEN/config.ini");
|
||||
config_state.last_modified = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Only reload if file has been modified since last load
|
||||
if (file_stat.st_mtime <= config_state.last_modified) {
|
||||
return; // File hasn't changed, skip reload
|
||||
}
|
||||
|
||||
// File has changed, proceed with loading
|
||||
etaHEN_log("[Daemon] Loading Settings...");
|
||||
|
||||
IniParser parser;
|
||||
if (ini_parser_load(&parser, config_path)) {
|
||||
etaHEN_log("[Daemon] Reading Settings...");
|
||||
|
||||
const char * libhijacker_cheats_str =
|
||||
ini_parser_get(&parser, "Settings.libhijacker_cheats", "0");
|
||||
const char * PS5Debug_str =
|
||||
ini_parser_get(&parser, "Settings.PS5Debug", "0");
|
||||
const char * start_option =
|
||||
ini_parser_get(&parser, "Settings.StartOption", "0");
|
||||
const char * DPI_v2 = ini_parser_get(&parser, "Settings.DPI_v2", "0");
|
||||
const char * auto_eject_disc =
|
||||
ini_parser_get(&parser, "Settings.auto_eject_disc", "0");
|
||||
const char* fan_threshold =
|
||||
ini_parser_get(&parser, "Settings.fan_threshold", "77");
|
||||
const char* enable_fan_speed =
|
||||
ini_parser_get(&parser, "Settings.enable_fan_speed", "0");
|
||||
const char* overlay_fps =
|
||||
ini_parser_get(&parser, "Settings.overlay_fps", "0");
|
||||
|
||||
etaHEN_log("fan_threshold: %s", fan_threshold);
|
||||
etaHEN_log("enable_fan_speed: %s", enable_fan_speed);
|
||||
|
||||
global_conf.fan_threshold = fan_threshold ? atoi(fan_threshold) : 77;
|
||||
global_conf.enable_fan_speed = enable_fan_speed ? atoi(enable_fan_speed) : 0;
|
||||
global_conf.overlay_fps = overlay_fps ? atoi(overlay_fps) : 0;
|
||||
global_conf.libhijacker_cheats =
|
||||
libhijacker_cheats_str ? atoi(libhijacker_cheats_str) : 0;
|
||||
global_conf.PS5Debug = PS5Debug_str ? atoi(PS5Debug_str) : 0;
|
||||
global_conf.start_opt =
|
||||
start_option ? (StartOpts) atoi(start_option) : NONE;
|
||||
global_conf.DPIv2 = DPI_v2 ? atoi(DPI_v2) : 0;
|
||||
global_conf.toolbox_auto_start =
|
||||
atoi(ini_parser_get(&parser, "Settings.toolbox_auto_start", "1"));
|
||||
|
||||
global_conf.seconds =
|
||||
atol(ini_parser_get(&parser, "Settings.Rest_Mode_Delay_Seconds", "0"));
|
||||
global_conf.debug_app_jb_msg =
|
||||
atoi(ini_parser_get(&parser, "Settings.APP_JB_Debug_Msg", "0"));
|
||||
global_conf.auto_eject_disc = auto_eject_disc ? atoi(auto_eject_disc) : 0;
|
||||
|
||||
if (if_exists("/mnt/usb0/toolbox_auto_start"))
|
||||
global_conf.toolbox_auto_start = false;
|
||||
|
||||
// Update last modified time after successful load
|
||||
config_state.last_modified = file_stat.st_mtime;
|
||||
} else {
|
||||
notify(true, "Failed to Read the Settings file");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static pid_t find_pid(const char *name) {
|
||||
int mib[4] = {1, 14, 8, 0};
|
||||
pid_t pid = -1;
|
||||
@@ -806,12 +853,83 @@ bool HookGame(UniquePtr<Hijacker>& hijacker, uint64_t alsr_b) {
|
||||
}
|
||||
|
||||
int done_appid;
|
||||
extern "C" int sceKernelGetCurrentFanDuty(int *unk, int *duty);
|
||||
bool set_fan_threshold(int THRESHOLDTEMP) {
|
||||
|
||||
if(THRESHOLDTEMP > 100){
|
||||
THRESHOLDTEMP = 100;
|
||||
}
|
||||
|
||||
int fd = open("/dev/icc_fan", O_RDONLY, 0);
|
||||
if (fd <= 0) {
|
||||
notify(true, "Unable to Open Fan Settings!");
|
||||
return false;
|
||||
}
|
||||
|
||||
char data[10] = {0x00, 0x00, 0x00, 0x00, 0x00, static_cast<char>(THRESHOLDTEMP), 0x00, 0x00, 0x00, 0x00};
|
||||
if(ioctl(fd, 0xC01C8F07, data) < 0) {
|
||||
notify(true, "Unable to Set Fan Speed!");
|
||||
close(fd);
|
||||
return false;
|
||||
}
|
||||
close(fd);
|
||||
//etaHEN_log("Fan speed set to %d%% THRESHOLDTEMP", THRESHOLDTEMP);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool cmd_enable_fps_new(int appid) {
|
||||
|
||||
if(done_appid == appid){
|
||||
// etaHEN_log("FPS already enabled for %x", appid);
|
||||
return true;
|
||||
}
|
||||
|
||||
etaHEN_log("Enabling fps for appid %d", appid);
|
||||
|
||||
sleep(5);
|
||||
|
||||
SuspendApp(appid);
|
||||
char buz[100] = { 0 };
|
||||
if (sceKernelMprotect(&buz[0], 100, 0x7) == 0) {
|
||||
if (pause_resume_kstuff()) {
|
||||
etaHEN_log("Paused kstuff...");
|
||||
touch_file("/system_tmp/kstuff_paused");
|
||||
}
|
||||
}
|
||||
|
||||
int pid = get_game_pid();
|
||||
if (pid < 0) {
|
||||
pause_resume_kstuff();
|
||||
notify(true, "Failed to get game pid");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Inject_Toolbox(pid, fps_elf_start)) {
|
||||
pause_resume_kstuff();
|
||||
ForceKillProc(pid);
|
||||
notify(true, "Failed to inject fps");
|
||||
return false;
|
||||
}
|
||||
|
||||
pause_resume_kstuff();
|
||||
|
||||
sleep(1);
|
||||
ResumeApp(pid);
|
||||
|
||||
done_appid = appid;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool cmd_enable_fps(int appid) {
|
||||
|
||||
if(done_appid == appid){
|
||||
// etaHEN_log("FPS already enabled for %x", appid);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
SuspendApp(appid);
|
||||
|
||||
@@ -878,7 +996,7 @@ bool cmd_enable_toolbox(){
|
||||
sleep(global_conf.seconds);
|
||||
}
|
||||
|
||||
notify(true, "Loading the etaHEN ToolBox...");
|
||||
//notify(true, "Loading the etaHEN ToolBox...");
|
||||
|
||||
int pid = get_shellui_pid();
|
||||
if (pid < 0) {
|
||||
@@ -1180,6 +1298,44 @@ void handleIPC(struct clientArgs *client, std::string &inputStr,
|
||||
reply(sender_app, true);
|
||||
break;
|
||||
}
|
||||
case BREW_LAUNCH_DUMPER:{
|
||||
#if 1
|
||||
if (elfldr_spawn("/", STDOUT_FILENO, dumper_elf_start, "Dumper") < 0) {
|
||||
notify(true, "Dumper is starting\nPlease wait...");
|
||||
}
|
||||
#endif
|
||||
reply(sender_app, false);
|
||||
break;
|
||||
}
|
||||
case BREW_ADJUST_FAN_SPEED: {
|
||||
int speed = json_getInteger(json_getProperty(my_json, "speed"));
|
||||
int enabled = json_getInteger(json_getProperty(my_json, "enabled"));
|
||||
etaHEN_log("Adjusting Fan Speed to: %d", speed);
|
||||
if (speed < 0 || speed > 100) {
|
||||
notify(true, "Invalid fan speed: %d. Must be between 0 and 100.", speed);
|
||||
reply(sender_app, true);
|
||||
break;
|
||||
}
|
||||
|
||||
global_conf.enable_fan_speed = enabled;
|
||||
|
||||
if (!enabled) {
|
||||
notify(true, "Fan speed adjustment is disabled.");
|
||||
set_fan_threshold(77);
|
||||
reply(sender_app, false);
|
||||
break;
|
||||
}
|
||||
|
||||
if (set_fan_threshold(speed)) {
|
||||
notify(true, "Fan threshold adjusted to %i°C.", speed);
|
||||
global_conf.fan_threshold = speed;
|
||||
reply(sender_app, false);
|
||||
} else {
|
||||
notify(true, "Failed to adjust fan speed.");
|
||||
reply(sender_app, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BREW_KILL_DAEMON:{
|
||||
is_handler_enabled = false;
|
||||
exit(1337);
|
||||
@@ -1201,7 +1357,7 @@ void handleIPC(struct clientArgs *client, std::string &inputStr,
|
||||
}
|
||||
case BREW_RELOAD_SETTINGS: {
|
||||
LoadSettings();
|
||||
// notify(true, "Reloaded Settings");
|
||||
notify(true, "Reloaded Settings");
|
||||
reply(sender_app, false);
|
||||
break;
|
||||
}
|
||||
@@ -1214,8 +1370,8 @@ void handleIPC(struct clientArgs *client, std::string &inputStr,
|
||||
break;
|
||||
}
|
||||
// kernel_set_ucred_authid(getpid(), 0x4801000000000013L);
|
||||
change_permissions_recursive(path);
|
||||
reply(sender_app, false);
|
||||
change_permissions_recursive(path);
|
||||
reply(sender_app, false);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
||||
@@ -60,7 +60,7 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 ")
|
||||
target_sources(${PROJECT_NAME} PRIVATE ${SrcFiles})
|
||||
target_include_directories(${PROJECT_NAME} PRIVATE "${D_CWD}/include")
|
||||
target_link_directories (${PROJECT_NAME} PUBLIC "${PROJECT_ROOT}/lib")
|
||||
target_link_libraries (${PROJECT_NAME} PUBLIC hijacker ScePad SceSystemService SceNet SceSysmodule SceUserService SceNetCtl kernel )
|
||||
target_link_libraries (${PROJECT_NAME} PUBLIC kernel SceGnmDriver)
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
# Add post-build command
|
||||
|
||||
@@ -17,7 +17,7 @@ along with this program; see the file COPYING. If not, see
|
||||
#pragma once
|
||||
extern "C" {
|
||||
#include "ucred.h"
|
||||
#include "external_symbols.hpp"
|
||||
#include "defs.h"
|
||||
#include "../lib/libmprotect.h"
|
||||
#include <cstdint>
|
||||
#include <sys/mman.h>
|
||||
|
||||
@@ -15,10 +15,10 @@ along with this program; see the file COPYING. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#pragma once
|
||||
#define PUBLIC_TEST 1
|
||||
#define PRE_RELEASE 0
|
||||
#define SHELL_DEBUG 1
|
||||
#define etaHEN_VERSION "2.4"
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
extern "C" int sceKernelMprotect(void *addr, size_t len, int prot);
|
||||
|
||||
#define libSceKernelHandle 0x2001
|
||||
#define KERNEL_DLSYM(handle, sym) \
|
||||
|
||||
@@ -516,6 +516,7 @@ public:
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}; // namespace IPC
|
||||
|
||||
#endif // IPC_HEADER_H
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
extern "C"{
|
||||
#include "../include/proc.h"
|
||||
#include <ps5/klog.h>
|
||||
}
|
||||
struct proc* find_proc_by_name(const char* proc_name)
|
||||
{
|
||||
@@ -92,21 +93,24 @@ void list_proc_modules(struct proc* proc)
|
||||
{
|
||||
size_t num_handles = 0;
|
||||
syscall(SYS_dl_get_list, proc->pid, NULL, 0, &num_handles);
|
||||
klog_printf("Number of modules: %zu\n", num_handles);
|
||||
|
||||
if (num_handles)
|
||||
{
|
||||
uintptr_t* handles = (uintptr_t*) calloc(num_handles, sizeof(uintptr_t));
|
||||
klog_printf("Allocated handles array at %p\n", handles);
|
||||
syscall(SYS_dl_get_list, proc->pid, handles, num_handles, &num_handles);
|
||||
|
||||
klog_printf("Retrieved module handles for PID %d\n", proc->pid);
|
||||
for (int i = 0; i < num_handles; ++i)
|
||||
{
|
||||
module_info_t mod_info;
|
||||
bzero(&mod_info, sizeof(mod_info));
|
||||
|
||||
klog_printf("Getting info for handle %p\n", (void*)handles[i]);
|
||||
syscall(SYS_dl_get_info_2, proc->pid, 1, handles[i], &mod_info);
|
||||
|
||||
printf("%s - ", mod_info.filename);
|
||||
printf("%#02lx\n", mod_info.init);
|
||||
klog_printf("%s - ", mod_info.filename);
|
||||
klog_printf("%#02lx\n", mod_info.init);
|
||||
}
|
||||
|
||||
free(handles);
|
||||
|
||||
@@ -23,12 +23,26 @@ along with this program; see the file COPYING. If not, see
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include "webserver.hpp"
|
||||
#include <chrono>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <util.hpp>
|
||||
|
||||
extern "C" long ptr_syscall = 0;
|
||||
#define u32 uint32_t
|
||||
#define s32 int32_t
|
||||
|
||||
|
||||
|
||||
extern "C" {
|
||||
long ptr_syscall = 0;
|
||||
|
||||
int sceKernelLoadStartModule(const char *moduleFileName, int args, const void *argp, int flags, void *opt, int *pRes) ;
|
||||
int sceKernelDlsym(int handle, const char *symbol, void **addrp);
|
||||
|
||||
s32 sceGnmSubmitAndFlipCommandBuffersForWorkload(
|
||||
u32 workload, u32 count, u32* dcb_gpu_addrs[], u32* dcb_sizes_in_bytes, u32* ccb_gpu_addrs[],
|
||||
u32* ccb_sizes_in_bytes, u32 vo_handle, u32 buf_idx, u32 flip_mode, u32 flip_arg);
|
||||
}
|
||||
void __syscall() {
|
||||
asm(".intel_syntax noprefix\n"
|
||||
" mov rax, rdi\n"
|
||||
@@ -56,6 +70,8 @@ extern "C" {
|
||||
int sceKernelClockGettime(int clockId, OrbisKernelTimespec* tp);
|
||||
}
|
||||
|
||||
static int frame_count = 0;
|
||||
|
||||
bool touch_file(const char* destfile) {
|
||||
static constexpr int FLAGS = 0777;
|
||||
int fd = open(destfile, O_WRONLY | O_CREAT | O_TRUNC, FLAGS);
|
||||
@@ -66,71 +82,110 @@ bool touch_file(const char* destfile) {
|
||||
return false;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
int32_t type; // 0x00
|
||||
int32_t req_id; // 0x04
|
||||
int32_t priority; // 0x08
|
||||
int32_t msg_id; // 0x0C
|
||||
int32_t target_id; // 0x10
|
||||
int32_t user_id; // 0x14
|
||||
int32_t unk1; // 0x18
|
||||
int32_t unk2; // 0x1C
|
||||
int32_t app_id; // 0x20
|
||||
int32_t error_num; // 0x24
|
||||
int32_t unk3; // 0x28
|
||||
char use_icon_image_uri; // 0x2C
|
||||
char message[1024]; // 0x2D
|
||||
char uri[1024]; // 0x42D
|
||||
char unkstr[1024]; // 0x82D
|
||||
} OrbisNotificationRequest; // Size = 0xC30
|
||||
|
||||
void notify(const char* text, ...)
|
||||
extern "C" int sceKernelSendNotificationRequest(int userId, OrbisNotificationRequest *request, size_t requestSize, int flags);
|
||||
|
||||
void printf_notification(const char* fmt, ...)
|
||||
{
|
||||
OrbisNotificationRequest req;
|
||||
memset(&req, 0, sizeof(OrbisNotificationRequest));
|
||||
char buff[1024];
|
||||
OrbisNotificationRequest noti_buffer{};
|
||||
|
||||
// printf("******************** text: %s\n", text);
|
||||
va_list args{};
|
||||
va_start(args, fmt);
|
||||
int len = vsnprintf(noti_buffer.message, sizeof(noti_buffer.message), fmt, args);
|
||||
va_end(args);
|
||||
|
||||
va_list args{};
|
||||
va_start(args, text);
|
||||
vsnprintf(buff, sizeof(buff), text, args);
|
||||
va_end(args);
|
||||
|
||||
req.type = 0;
|
||||
req.unk3 = 0;
|
||||
req.use_icon_image_uri = 1;
|
||||
req.target_id = -1;
|
||||
strncpy(req.uri, "cxml://psnotification/tex_icon_system", 38);
|
||||
strncpy(req.message, buff, 1024);
|
||||
|
||||
game_log("Sending notification: %s", req.message);
|
||||
sceKernelSendNotificationRequest(0, &req, sizeof(req), 0);
|
||||
// these dont do anything currently
|
||||
// that or the structure has changed
|
||||
// lets just copy messages for now
|
||||
/*
|
||||
noti_buffer.type = 0;
|
||||
noti_buffer.unk3 = 0;
|
||||
noti_buffer.use_icon_image_uri = 0;
|
||||
noti_buffer.target_id = -1;
|
||||
*/
|
||||
// trim newline
|
||||
if (noti_buffer.message[len - 1] == '\n')
|
||||
{
|
||||
noti_buffer.message[len - 1] = '\0';
|
||||
}
|
||||
sceKernelSendNotificationRequest(0, (OrbisNotificationRequest*)¬i_buffer, sizeof(noti_buffer), 0);
|
||||
}
|
||||
|
||||
#define KERNEL_DLSYM(handle, sym) \
|
||||
(*(void**)&sym=(void*)kernel_dynlib_dlsym(-1, handle, #sym))
|
||||
void CalculateAndPrintFPS() {
|
||||
auto current_time = std::chrono::high_resolution_clock::now();
|
||||
static auto last_time = current_time;
|
||||
auto delta = std::chrono::duration<double>(current_time - last_time).count();
|
||||
|
||||
frame_count++;
|
||||
|
||||
if (delta >= 1.0) {
|
||||
double fps = frame_count / delta;
|
||||
// Send FPS
|
||||
printf_notification("FPS %.2f", fps);
|
||||
|
||||
frame_count = 0;
|
||||
last_time = current_time;
|
||||
}
|
||||
}
|
||||
|
||||
s32 (*sceGnmSubmitAndFlipCommandBuffersForWorkload_orig)(
|
||||
u32 workload, u32 count, u32* dcb_gpu_addrs[], u32* dcb_sizes_in_bytes, u32* ccb_gpu_addrs[],
|
||||
u32* ccb_sizes_in_bytes, u32 vo_handle, u32 buf_idx, u32 flip_mode, u32 flip_arg) = nullptr;
|
||||
|
||||
s32 sceGnmSubmitAndFlipCommandBuffersForWorkload_hook(
|
||||
u32 workload, u32 count, u32* dcb_gpu_addrs[], u32* dcb_sizes_in_bytes, u32* ccb_gpu_addrs[],
|
||||
u32* ccb_sizes_in_bytes, u32 vo_handle, u32 buf_idx, u32 flip_mode, u32 flip_arg) {
|
||||
//printf("sceGnmSubmitAndFlipCommandBuffersForWorkload_hook called!\n");
|
||||
CalculateAndPrintFPS();
|
||||
int ret = sceGnmSubmitAndFlipCommandBuffersForWorkload_orig(
|
||||
workload, count, dcb_gpu_addrs, dcb_sizes_in_bytes, ccb_gpu_addrs,
|
||||
ccb_sizes_in_bytes, vo_handle, buf_idx, flip_mode, flip_arg);
|
||||
if(ret == 0x80D11081){
|
||||
printf("sceGnmSubmitAndFlipCommandBuffersForWorkload returned BUSY\n");
|
||||
}
|
||||
else
|
||||
if(ret != 0) {
|
||||
printf("sceGnmSubmitAndFlipCommandBuffersForWorkload returned error: %d\n", ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char const* argv[]) {
|
||||
//OrbisKernelSwVersion sw;
|
||||
char buff[256];
|
||||
klog_puts("============== fps_elf Started =================");
|
||||
printf_notification("fps_counter loaded!");
|
||||
|
||||
notify("fps_elf loaded!");
|
||||
while(sceKernelMprotect(&buff, sizeof(buff), PROT_READ | PROT_WRITE | PROT_EXEC) != 0) {
|
||||
klog_puts("sceKernelMprotect failed, retrying...");
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
pid_t pid = getpid();
|
||||
uintptr_t old_authid = set_ucred_to_debugger();
|
||||
|
||||
|
||||
int libkernelsys_handle = get_module_handle(pid, "libkernel.sprx");
|
||||
|
||||
KERNEL_DLSYM(libkernelsys_handle, sceKernelDebugOutText);
|
||||
KERNEL_DLSYM(libkernelsys_handle, sceKernelMkdir);
|
||||
KERNEL_DLSYM(libkernelsys_handle, scePthreadCreate);
|
||||
KERNEL_DLSYM(libkernelsys_handle, sceKernelMprotect);
|
||||
KERNEL_DLSYM(libkernelsys_handle, sceKernelSendNotificationRequest);
|
||||
KERNEL_DLSYM(libkernelsys_handle, sceKernelGetProsperoSystemSwVersion);
|
||||
KERNEL_DLSYM(libkernelsys_handle, sceKernelGetAppInfo);
|
||||
KERNEL_DLSYM(libkernelsys_handle, sceKernelGetProcessName);
|
||||
|
||||
game_log("Starting game ELF ....");
|
||||
|
||||
KERNEL_DLSYM(libSceKernelHandle, ioctl);
|
||||
|
||||
// get the yscall address for the ioctl hook
|
||||
static __attribute__((used)) long getpid = 0;
|
||||
KERNEL_DLSYM(libSceKernelHandle, getpid);
|
||||
ptr_syscall = getpid;
|
||||
ptr_syscall += 0xa; // jump directly to the syscall instruction
|
||||
|
||||
// file to let the main daemon know that its finished loading
|
||||
touch_file("/system_tmp/fps_online");
|
||||
set_proc_authid(pid, old_authid);
|
||||
klog_printf("sceGnmSubmitAndFlipCommandBuffersForWorkload addr: %p\n", &sceGnmSubmitAndFlipCommandBuffersForWorkload);
|
||||
sceGnmSubmitAndFlipCommandBuffersForWorkload_orig = (decltype(sceGnmSubmitAndFlipCommandBuffersForWorkload_orig))DetourFunction((uint64_t)&sceGnmSubmitAndFlipCommandBuffersForWorkload, (void*)&sceGnmSubmitAndFlipCommandBuffersForWorkload_hook);
|
||||
|
||||
while (true) {
|
||||
game_log("sleeping ....");
|
||||
sleep(0x100000);
|
||||
sleep(0x10000);
|
||||
}
|
||||
return 0;
|
||||
|
||||
|
||||
Binary file not shown.
@@ -30,7 +30,7 @@
|
||||
</setting_list>
|
||||
|
||||
<setting_list id="id_etahen_credits" title="etaHEN Credits" second_title="Credits and Supporters">
|
||||
<label id="id_etahen_creds_display" title="★ etaHEN Beta 2.4" style="center"/>
|
||||
<label id="id_etahen_creds_display" title="★ etaHEN Beta 2.5" style="center"/>
|
||||
<label id="id_lead_devs" title="★ Lead Developer(s) ★" style="center"/>
|
||||
<label id="id_lead_devs_2" title="- LM (X @LightningMods_, GitHub @LightningMods, Discord @lm_dev)" style="center"/>
|
||||
<label id="id_ddkdkd" title="★ etaHEN Contributors ★" style="center"/>
|
||||
|
||||
Binary file not shown.
@@ -33,7 +33,7 @@
|
||||
<list_item id="id_overlay_pos_3" title="Bottom Left" value="2"/>
|
||||
<list_item id="id_overlay_pos_4" title="Bottom Right" value="3"/>
|
||||
</list>
|
||||
<!-- <toggle_switch id="id_overlay_fps" title="FPS Section" description="Toggle the FPS Section from the game overlay" value="0"/> -->
|
||||
<toggle_switch id="id_overlay_fps" title="*Experimental* PS4 FPS Section" description="Toggle the FPS Section from the game overlay NOTE: not for regular use yet" value="0"/>
|
||||
<toggle_switch id="id_overlay_gpu" title="GPU Section" description="Toggle the GPU Section from the game overlay" value="0"/>
|
||||
<toggle_switch id="id_overlay_cpu" title="CPU Section" description="Toggle the CPU Section from the game overlay" value="0"/>
|
||||
<toggle_switch id="id_all_cpu_usage" title="Show ALL CPU Core Usage" description="Toggle the advanced CPU usage from the game overlay" value="0"/>
|
||||
@@ -51,12 +51,19 @@
|
||||
<list_item id="id_pause_kstuff_3" title="PS4 sysentvec Only" value="2"/>
|
||||
<list_item id="id_pause_kstuff_4" title="Pause Both PS5 and PS4 sysentvecs" value="3"/>
|
||||
</list>
|
||||
|
||||
<button id="id_download_kstuff" title="Replace kstuff with the latest Kstuff via Github" description="Downloads and Installs the latest kstuff from EchoStretch's Github Repo, will replace the one etaHEN auto loads on startup"/>
|
||||
<toggle_switch id="id_pause_kstuff_on_open" title="Pause Kstuff on Game Launch" description="This will pause Kstuff when launching games or apps after the provided delay" value="0"/>
|
||||
<text_field id="id_pause_kstuff_on_open_secs" title="Kstuff pause delay" second_title="Delay in seconds used for auto pausing kstuff after app launch" keyboard_type="number" min_length="1" max_length="3"/>
|
||||
<toggle_switch id="id_enable_kstuff_on_close" title="Unpause Kstuff on Game Close" description="This will unpause Kstuff when closing games or apps, Note: if not paused no action will be taken" value="0"/>
|
||||
<button id="id_download_kstuff" title="Replace kstuff with the latest Kstuff via Github" description="Downloads and Installs the latest kstuff from EchoStretch's Github Repo to /data/etaHEN/kstuff.elf, will replace the one etaHEN auto loads on startup"/>
|
||||
<button id="id_delete_kstuff" title="Delete Kstuff installed via Github" description="This will switch back to etaHENs built-in kstuff"/>
|
||||
<toggle_switch id="id_kstuff_autoload" title="Auto load Kstuff on etaHEN startup" value="0"/>
|
||||
|
||||
</setting_list>
|
||||
|
||||
|
||||
<toggle_switch id="id_enable_fan_speed" title="Enable Manual Fan Speed Threshold" value="0"/>
|
||||
|
||||
<text_field id="id_fan_speed" title="Adjust Fan Threshold" second_title="Adjust Fan Threshold in celsius" keyboard_type="number" min_length="2" max_length="2"/>
|
||||
|
||||
<toggle_switch id="id_sistro_ps5debug" title="Enable PS5Debug by Sistr0 and CTN" value="0"/>
|
||||
|
||||
@@ -70,7 +77,7 @@
|
||||
|
||||
<toggle_switch id="id_ftp_dev_access" title="Allow FTP access to the /dev directory" value="0"/>
|
||||
|
||||
<!-- <link id="id_whitelist_menu" title="Whitelisted Apps (SuperUser) Menu" file="superuser.xml"/> -->
|
||||
<!-- <link id="id_whitelist_menu" title="Whitelisted Apps (SuperUser) Menu" file="superuser.xml"/> -->
|
||||
|
||||
<!-- Debug setting extra 1 -->
|
||||
<link id="id_licenseactivation" title="Blu-Ray (license) Activation" file="DebugSettings/data/debug_settings_licenseactivation.xml"/>
|
||||
@@ -162,7 +169,7 @@
|
||||
</setting_list>
|
||||
|
||||
<setting_list id="id_etahen_credits" title="etaHEN Credits" second_title="Credits and Supporters">
|
||||
<label id="id_etahen_creds_display" title="★ etaHEN Beta 2.4" style="center"/>
|
||||
<label id="id_etahen_creds_display" title="★ etaHEN Beta 2.5" style="center"/>
|
||||
<label id="id_lead_devs" title="★ Lead Developer(s) ★" style="center"/>
|
||||
<label id="id_lead_devs_2" title="- LM (X @LightningMods_, GitHub @LightningMods, Discord @lm_dev)" style="center"/>
|
||||
<label id="id_ddkdkd" title="★ etaHEN Contributors ★" style="center"/>
|
||||
|
||||
@@ -194,6 +194,11 @@ enum Cheats_Shortcut{
|
||||
OVERLAY_POS_BOTTOM_RIGHT
|
||||
};
|
||||
|
||||
enum cheats_repo_source{
|
||||
CHEATS_REPO_ETAHEN = 0,
|
||||
CHEATS_REPO_GOLDHEN
|
||||
};
|
||||
|
||||
typedef struct etaHENSettings_t
|
||||
{
|
||||
bool FTP = true;
|
||||
@@ -224,12 +229,17 @@ typedef struct etaHENSettings_t
|
||||
bool overlay_ip = false;
|
||||
bool overlay_kstuff = false;
|
||||
bool overlay_kstuff_active = false;
|
||||
bool enable_kstuff_on_close = false;
|
||||
bool pause_kstuff_on_open = false;
|
||||
bool all_cpu_usage = false;
|
||||
int start_option = 0;
|
||||
int trial_soft_expire_time = 0;
|
||||
int kit_panel_info = 0;
|
||||
int kstuff_pause_opt = NOT_PAUSED;
|
||||
uint64_t rest_delay_seconds = 0;
|
||||
bool enable_fan_speed = false;
|
||||
int fan_threshold = 77;
|
||||
int pause_kstuff_on_open_secs = 0;
|
||||
|
||||
// Shortcuts
|
||||
Cheats_Shortcut cheats_shortcut_opt = CHEATS_SC_OFF;
|
||||
@@ -254,6 +264,7 @@ typedef struct etaHENSettings_t
|
||||
float overlay_ip_y = 110.0f;
|
||||
|
||||
overlay_positions overlay_pos = OVERLAY_POS_TOP_LEFT; //0=top left, 1=top right, 2=bottom left, 3=bottom right
|
||||
cheats_repo_source selected_cheats_repo = CHEATS_REPO_ETAHEN;
|
||||
|
||||
} etaHENSettings;
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ along with this program; see the file COPYING. If not, see
|
||||
#define PUBLIC_TEST 0
|
||||
#define PRE_RELEASE 0
|
||||
#define SHELL_DEBUG 0
|
||||
#define etaHEN_VERSION "2.4"
|
||||
#define etaHEN_VERSION "2.5"
|
||||
|
||||
#define libSceKernelHandle 0x2001
|
||||
#define KERNEL_DLSYM(handle, sym) \
|
||||
|
||||
@@ -38,6 +38,8 @@ along with this program; see the file COPYING. If not, see
|
||||
#include <unistd.h>
|
||||
#include <vector>
|
||||
#include <ps5/klog.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
enum Cheat_Actions {
|
||||
DOWNLOAD_CHEATS = 0,
|
||||
@@ -112,7 +114,7 @@ public:
|
||||
// erase the old message
|
||||
bzero(msg.msg, sizeof(msg.msg));
|
||||
|
||||
int timeout_ms = 10 * 1000;
|
||||
int timeout_ms = 25 * 1000;
|
||||
// Set receive timeout
|
||||
struct timeval tv;
|
||||
tv.tv_sec = timeout_ms / 1000;
|
||||
@@ -124,6 +126,7 @@ public:
|
||||
return -1; // Error setting timeout
|
||||
}
|
||||
|
||||
shellui_log("Waiting for daemon response...");
|
||||
int ret = recv(socket_fd, reinterpret_cast<void*>(&msg), sizeof(msg), MSG_NOSIGNAL);
|
||||
if (ret < 0) {
|
||||
shellui_log("recv failed with: 0X%X", ret);
|
||||
@@ -478,7 +481,7 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Cheats_Action(Cheat_Actions act) {
|
||||
bool Cheats_Action(Cheat_Actions act, int repo) {
|
||||
DaemonCommands cmd;
|
||||
if (!util_daemon) {
|
||||
shellui_log("This IPC command is NOT in the main daemon");
|
||||
@@ -497,12 +500,28 @@ public:
|
||||
|
||||
}
|
||||
std::string ipc_msg;
|
||||
if (!IPCSendCommand(cmd, ipc_msg)) {
|
||||
std::string json = "{\"repo\": " + std::to_string(repo) + "}";
|
||||
if (!IPCSendCommand(cmd, ipc_msg, json)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Set_Fan_Threshold(int temp, bool enabled) {
|
||||
if (util_daemon) {
|
||||
shellui_log("This IPC command is NOT in the util daemon");
|
||||
return false;
|
||||
}
|
||||
std::string ipc_msg;
|
||||
//and enabled
|
||||
std::string json = "{\"speed\": " + std::to_string(temp) + ", \"enabled\": " + std::to_string(enabled) + "}";
|
||||
if (!IPCSendCommand(BREW_ADJUST_FAN_SPEED, ipc_msg, json)) {
|
||||
shellui_log("Failed to adjust fan speed");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ToggleDPI(bool turn_on, bool is_v2) {
|
||||
if (!util_daemon) {
|
||||
shellui_log("This IPC command is NOT in the main daemon");
|
||||
@@ -520,6 +539,73 @@ public:
|
||||
|
||||
return true;
|
||||
}
|
||||
void Launch_Dumper() {
|
||||
if (util_daemon) {
|
||||
shellui_log("This IPC command is in the main daemon");
|
||||
return;
|
||||
}
|
||||
std::string ipc_msg;
|
||||
if (!IPCSendCommand(BREW_LAUNCH_DUMPER, ipc_msg)) {
|
||||
shellui_log("Failed to launch dumper");
|
||||
}
|
||||
}
|
||||
|
||||
static void generate_default_games_xml(std::string &xml_buffer, bool game_shortcut_activated) {
|
||||
std::string list_id = game_shortcut_activated ? "id_debug_settings" : "id_ps5_backups";
|
||||
|
||||
xml_buffer = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
|
||||
"<system_settings version=\"1.0\" plugin=\"debug_settings_plugin\">\n"
|
||||
"\n";
|
||||
|
||||
xml_buffer += "<setting_list id=\"" + list_id + "\" title=\"(Beta) PS5 webMAN Games (ERROR)\">\n";
|
||||
xml_buffer += "</setting_list>\n</system_settings> ";
|
||||
}
|
||||
|
||||
bool GetGamesList(bool cheats_activated_shortcut, std::string &games_list) {
|
||||
if (!util_daemon) {
|
||||
shellui_log("This IPC command is in the util daemon");
|
||||
generate_default_games_xml(games_list, cheats_activated_shortcut);
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string json = "{\"shortcut\": " + std::to_string(cheats_activated_shortcut) + "}";
|
||||
if (!IPCSendCommand(BREW_UTIL_GET_GAMES_LIST, games_list, json)) {
|
||||
shellui_log("Failed to get games list");
|
||||
generate_default_games_xml(games_list, cheats_activated_shortcut);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
std::ifstream file("/user/data/etaHEN/games_list.xml");
|
||||
if (file) {
|
||||
std::string content((std::istreambuf_iterator<char>(file)),
|
||||
std::istreambuf_iterator<char>());
|
||||
games_list = content;
|
||||
file.close();
|
||||
return true;
|
||||
} else {
|
||||
shellui_log("Failed to open games list file: %s", games_list.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
shellui_log("Games list: %s", games_list.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Launch_Game_By_ID(const std::string& button_id) {
|
||||
if (!util_daemon) {
|
||||
shellui_log("This IPC command is in the util daemon");
|
||||
return false;
|
||||
}
|
||||
std::string ipc_msg;
|
||||
std::string json = "{\"button_id\": \"" + button_id + "\"}";
|
||||
if (!IPCSendCommand(BREW_UTIL_LAUNCH_GAME_BY_BUTTON_ID, ipc_msg, json)) {
|
||||
shellui_log("Failed to launch game by button id: %s", button_id.c_str());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}; // namespace IPC
|
||||
|
||||
#endif // IPC_HEADER_H
|
||||
|
||||
@@ -59,15 +59,6 @@ typedef enum {
|
||||
MONO_IMAGE_IMAGE_INVALID
|
||||
} MonoImageOpenStatus;
|
||||
|
||||
typedef struct app_launch_ctx
|
||||
{
|
||||
int structsize;
|
||||
int user_id;
|
||||
int app_opt;
|
||||
uint64_t crash_report;
|
||||
int check_flag;
|
||||
} app_launch_ctx_t;
|
||||
|
||||
typedef guint32 mono_array_size_t;
|
||||
typedef gint32 mono_array_lower_bound_t;
|
||||
|
||||
@@ -395,7 +386,7 @@ extern "C" {
|
||||
} while (0)
|
||||
|
||||
int replace_all(unsigned char * buffer, int * buffer_size, int buffer_capacity, const char * target, const char * replacement);
|
||||
int sceSystemServiceLaunchApp(const char *, char **, app_launch_ctx_t *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -35,6 +35,8 @@ along with this program; see the file COPYING. If not, see
|
||||
extern "C"{
|
||||
#include <ps5/kernel.h>
|
||||
}
|
||||
|
||||
extern bool is_6xx, is_3xx;
|
||||
/* ================================= ORIG HOOKED MONO FUNCS ============================================= */
|
||||
int (*oOnPress)(MonoObject* Instance, MonoObject* element, MonoObject* e) = nullptr;
|
||||
int (*oOnPreCreate)(MonoObject* Instance, MonoObject* element) = nullptr;
|
||||
@@ -543,6 +545,16 @@ void pause_resume_kstuff(KstuffPauseStatus opt, bool notify_user)
|
||||
|
||||
}
|
||||
|
||||
void* kstuff_pause_thread(void* arg){
|
||||
sleep(2);
|
||||
sleep(global_conf.pause_kstuff_on_open_secs);
|
||||
|
||||
if(!if_exists("/user/data/etaHEN/no_kstuff") && !if_exists("/usb0/etaHEN/no_kstuff")){
|
||||
pause_resume_kstuff(BOTH_PAUSED, true);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
extern "C" int sceKernelGetSocSensorTemperature(int numb, int *temp);
|
||||
|
||||
extern "C" int sceNetGetIfList(SceNetIfName ifName_num, SceNetIfList* ifListArray, int n);
|
||||
@@ -940,7 +952,6 @@ void* switch_to_lite(void*) {
|
||||
main_ipc.KillDaemon();
|
||||
|
||||
notify("Lite mode is active!");
|
||||
pause_resume_kstuff(NOT_PAUSED, false);
|
||||
pthread_exit(nullptr);
|
||||
return nullptr;
|
||||
|
||||
@@ -1020,10 +1031,10 @@ void* download_cheats_thr(void*){
|
||||
return nullptr;
|
||||
}
|
||||
cheat_action_in_progress = true;
|
||||
notify("Preparing to download the cheats repo...");
|
||||
notify("Preparing to download the %s cheats repo...", global_conf.selected_cheats_repo == CHEATS_REPO_ETAHEN ? "etaHEN PS5" : "GoldHEN PS4");
|
||||
IPC_Client& util_ipc = IPC_Client::getInstance(true);
|
||||
// daemon shows notification when done
|
||||
util_ipc.Cheats_Action(DOWNLOAD_CHEATS);
|
||||
util_ipc.Cheats_Action(DOWNLOAD_CHEATS, global_conf.selected_cheats_repo);
|
||||
|
||||
cheat_action_in_progress = false;
|
||||
pthread_exit(nullptr);
|
||||
@@ -1038,7 +1049,7 @@ void* reload_cheats_thr(void*){
|
||||
}
|
||||
cheat_action_in_progress = true;
|
||||
IPC_Client& util_ipc = IPC_Client::getInstance(true);
|
||||
if (util_ipc.Cheats_Action(RELOAD_CHEATS))
|
||||
if (util_ipc.Cheats_Action(RELOAD_CHEATS, 0))
|
||||
notify("The Cheats have been Cache and cheats list has been successfully reloaded");
|
||||
|
||||
cheat_action_in_progress = false;
|
||||
@@ -1079,6 +1090,7 @@ int OnPress_Hook(MonoObject* Instance, MonoObject* element, MonoObject* e)
|
||||
bool& DPI_v2 = global_conf.DPI_v2;
|
||||
int& kstuff_pause_opt = global_conf.kstuff_pause_opt;
|
||||
bool& dis_tids = global_conf.display_tids;
|
||||
cheats_repo_source& selected_cheats_repo = global_conf.selected_cheats_repo;
|
||||
|
||||
// Define the array of IDs to exclude (you can put this at the top of your function or as a static/global)
|
||||
const std::vector<std::string> excludedIds = {
|
||||
@@ -1104,7 +1116,7 @@ int OnPress_Hook(MonoObject* Instance, MonoObject* element, MonoObject* e)
|
||||
std::string value = GetPropertyValue(element, "Value");
|
||||
std::string title = GetPropertyValue(element, "Title");
|
||||
|
||||
bool is_game = (id.rfind("id_game_") != std::string::npos);
|
||||
bool is_game = (id.rfind("id_etahen_game_loader_") != std::string::npos);
|
||||
bool is_cust_pkg = (id.rfind("id_pkg_") != std::string::npos);
|
||||
|
||||
if (id.rfind("id_cheat_") != std::string::npos && !is_current_game_open) {
|
||||
@@ -1188,9 +1200,12 @@ int OnPress_Hook(MonoObject* Instance, MonoObject* element, MonoObject* e)
|
||||
}
|
||||
if (!atoi(value.c_str())) {
|
||||
RemoveGameWidget(REMOVE_FPS_OVERLAY);
|
||||
unlink("/system_tmp/fps_enabled");
|
||||
|
||||
}
|
||||
else {
|
||||
CreateGameWidget(CREATE_FPS_OVERLAY);
|
||||
touch_file("/system_tmp/fps_enabled");
|
||||
}
|
||||
|
||||
global_conf.overlay_fps = !global_conf.overlay_fps;
|
||||
@@ -1310,10 +1325,19 @@ int OnPress_Hook(MonoObject* Instance, MonoObject* element, MonoObject* e)
|
||||
CreateGameWidget(CREATE_IP_OVERLAY);
|
||||
}
|
||||
}
|
||||
else if (id == "id_enable_kstuff_on_close"){
|
||||
global_conf.enable_kstuff_on_close = atoi(value.c_str());
|
||||
}
|
||||
else if (id == "id_pause_kstuff_on_open"){
|
||||
global_conf.pause_kstuff_on_open = atoi(value.c_str());
|
||||
}
|
||||
else if (id == "id_pause_kstuff_on_open_secs") {
|
||||
global_conf.pause_kstuff_on_open_secs = atol(value.c_str());
|
||||
}
|
||||
else if (id == "id_kstuff_autoload") {
|
||||
if(atoi(value.c_str()) == if_exists("/user/data/etaHEN/no_kstuff")) {
|
||||
return oOnPress(Instance, element, e);
|
||||
}
|
||||
// if(atoi(value.c_str()) == if_exists("/user/data/etaHEN/no_kstuff")) {
|
||||
// return oOnPress(Instance, element, e);
|
||||
//}
|
||||
if(atol(value.c_str())){
|
||||
unlink("/user/data/etaHEN/no_kstuff");
|
||||
notify("Kstuff will be loaded on next boot");
|
||||
@@ -1341,11 +1365,16 @@ int OnPress_Hook(MonoObject* Instance, MonoObject* element, MonoObject* e)
|
||||
{
|
||||
if (plugin.id == id)
|
||||
{
|
||||
int pid = -1;
|
||||
if(plugin.tid.rfind(".elf") != std::string::npos && (pid = sceSystemServiceGetAppId(plugin.tid.c_str())) > 0){
|
||||
IPC_Client::getInstance(false).ForceKillPID(pid);
|
||||
notify("killed payload %s", plugin.tid.c_str());
|
||||
break;
|
||||
}
|
||||
char pbuf[256];
|
||||
snprintf(pbuf, sizeof(pbuf), "/system_tmp/%s.PID", plugin.tid.c_str());
|
||||
|
||||
int f = open(pbuf, O_RDONLY);
|
||||
int pid = -1;
|
||||
if (f >= 0)
|
||||
{
|
||||
char t[32];
|
||||
@@ -1380,6 +1409,7 @@ int OnPress_Hook(MonoObject* Instance, MonoObject* element, MonoObject* e)
|
||||
unlink(pbuf);
|
||||
|
||||
notify("%s killed", plugin.tid.c_str());
|
||||
break;
|
||||
}
|
||||
else if (pid <= 0 && atol(value.c_str()) == 1)
|
||||
{
|
||||
@@ -1402,8 +1432,8 @@ int OnPress_Hook(MonoObject* Instance, MonoObject* element, MonoObject* e)
|
||||
shellui_log("[Clicked %s] %s path: %s", selected_pkgs.id.c_str(), selected_pkgs.name.c_str(), selected_pkgs.shellui_path.c_str());
|
||||
#endif
|
||||
std::string dl_url;
|
||||
if (0)
|
||||
dl_url = "http:///192.168.123.116:1304" + selected_pkgs.shellui_path;
|
||||
if (is_6xx)
|
||||
dl_url = "http://127.0.0.1:12800" + selected_pkgs.path;
|
||||
else
|
||||
dl_url = (selected_pkgs.path.rfind("/data") != std::string::npos) ? selected_pkgs.shellui_path : selected_pkgs.path;
|
||||
|
||||
@@ -1422,7 +1452,7 @@ int OnPress_Hook(MonoObject* Instance, MonoObject* element, MonoObject* e)
|
||||
shellui_log("Installing package from: %s", metainfo.uri);
|
||||
int num = sceAppInstUtilInstallByPackage(&metainfo, &pkginfo, &playgoinfo);
|
||||
if (num != 0) {
|
||||
notify("Failed to install %s\nError: 0x%X", selected_pkgs.name.c_str(), num);
|
||||
notify("Failed to install %s\nError: 0x%X\nis DPIv2 enabled???", selected_pkgs.name.c_str(), num);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1432,21 +1462,9 @@ int OnPress_Hook(MonoObject* Instance, MonoObject* element, MonoObject* e)
|
||||
}
|
||||
}
|
||||
else if (is_game) {
|
||||
if (games_list.empty()){
|
||||
return oOnPress(Instance, element, e);
|
||||
}
|
||||
for (auto game : games_list) {
|
||||
if (game.id == id) {
|
||||
#if SHELL_DEBUG==1
|
||||
shellui_log("[Clicked %s] TID: %s title: %s version: %s path: %s", game.id.c_str(), game.tid.c_str(), game.title.c_str(), game.version.c_str(), game.path.c_str());
|
||||
#endif
|
||||
notify("Launching %s (%s)\nPath: %s", game.title.c_str(), game.tid.c_str(), game.path.c_str());
|
||||
//const char *path, const char* title_id, const char* title
|
||||
int res = Launch_FG_Game(game.path.c_str(), game.tid.c_str(), game.title.c_str());
|
||||
if (res < 0 && res != SCE_LNC_UTIL_ERROR_ALREADY_RUNNING_KILL_NEEDED && res != SCE_LNC_UTIL_ERROR_ALREADY_RUNNING && res != SCE_LNC_UTIL_ERROR_ALREADY_RUNNING_SUSPEND_NEEDED) {
|
||||
notify("Failed to launch %s (%s)\nError: 0x%X", game.title.c_str(), game.tid.c_str(), res);
|
||||
}
|
||||
}
|
||||
if(IPC_Client::getInstance(true).Launch_Game_By_ID(id) && global_conf.pause_kstuff_on_open){
|
||||
pthread_t thread;
|
||||
pthread_create(&thread, nullptr, kstuff_pause_thread, nullptr);
|
||||
}
|
||||
}
|
||||
else if (id.rfind("id_auto_plugin") != std::string::npos) {
|
||||
@@ -1546,6 +1564,15 @@ int OnPress_Hook(MonoObject* Instance, MonoObject* element, MonoObject* e)
|
||||
dis_tids = !dis_tids;
|
||||
ReloadRNPSApp("NPXS40002");
|
||||
}
|
||||
else if (id == "id_enable_fan_speed") {
|
||||
if (atol(value.c_str()) == global_conf.enable_fan_speed) {
|
||||
shellui_log("Fan speed control already %s", global_conf.enable_fan_speed ? "Enabled" : "Disabled");
|
||||
return oOnPress(Instance, element, e);
|
||||
}
|
||||
global_conf.enable_fan_speed = !global_conf.enable_fan_speed;
|
||||
IPC_Client::getInstance(false).Set_Fan_Threshold(global_conf.fan_threshold, global_conf.enable_fan_speed);
|
||||
|
||||
}
|
||||
else if (id == "id_lm_test")
|
||||
{
|
||||
shellui_log("LM's Test Button Pressed");
|
||||
@@ -1667,6 +1694,17 @@ int OnPress_Hook(MonoObject* Instance, MonoObject* element, MonoObject* e)
|
||||
Auto_ItemzFlow = false;
|
||||
shellui_log("Start option: %d", StartOption);
|
||||
}
|
||||
else if (id == "id_selected_cheats_repo") {
|
||||
selected_cheats_repo = static_cast<cheats_repo_source>(atoi(value.c_str()));
|
||||
shellui_log("Selected cheats repo: %s", selected_cheats_repo == CHEATS_REPO_ETAHEN ? "etaHEN PS5" : "GoldHEN PS4");
|
||||
}
|
||||
else if (id == "id_lite_mode") {
|
||||
if (atoi(value.c_str()) == lite_mode) {
|
||||
shellui_log("Lite Mode already %s", lite_mode ? "Enabled" : "Disabled");
|
||||
return oOnPress(Instance, element, e);
|
||||
}
|
||||
lite_mode = !lite_mode;
|
||||
}
|
||||
else if (id == "id_trial_soft") {
|
||||
trial_expire = atoi(value.c_str());
|
||||
}
|
||||
@@ -1715,6 +1753,16 @@ int OnPress_Hook(MonoObject* Instance, MonoObject* element, MonoObject* e)
|
||||
else if (id == "id_rest_1") {
|
||||
delay_secs = atol(value.c_str());
|
||||
}
|
||||
else if (id == "id_fan_speed") {
|
||||
int &fan_speed = global_conf.fan_threshold;
|
||||
fan_speed = atoi(value.c_str());
|
||||
if(!global_conf.enable_fan_speed){
|
||||
notify("Manual Fan speed threshold is not enabled");
|
||||
return oOnPress(Instance, element, e);
|
||||
}
|
||||
shellui_log("Setting fan speed to %d%%", fan_speed);
|
||||
IPC_Client::getInstance(false).Set_Fan_Threshold(fan_speed, global_conf.enable_fan_speed);
|
||||
}
|
||||
else if (id == "id_rest_2") {
|
||||
if (atoi(value.c_str()) == util_rest_kill) {
|
||||
shellui_log("util_rest_kill already %s", util_rest_kill ? "Enabled" : "Disabled");
|
||||
@@ -1938,7 +1986,6 @@ int OnPress_Hook(MonoObject* Instance, MonoObject* element, MonoObject* e)
|
||||
notify("%s killed", plugin.tid.c_str());
|
||||
}
|
||||
}
|
||||
pause_resume_kstuff(BOTH_PAUSED, false);
|
||||
if(!Try_connect_to_host(9021) && !IPC_Client::getInstance(true).Launch_Elfldr()){
|
||||
notify("Failed to Launch Johns Elfldr, failed to enter lite mode");
|
||||
return oOnPress(Instance, element, e);
|
||||
@@ -2094,7 +2141,8 @@ uint64_t GetManifestResourceStream_Hook(uint64_t inst, MonoString* FileName) {
|
||||
// shellui_log("games found");
|
||||
}
|
||||
|
||||
generate_games_xml(new_xml_string, game_shortcut_activated);
|
||||
//generate_games_xml(new_xml_string, game_shortcut_activated);
|
||||
IPC_Client::getInstance(true).GetGamesList(game_shortcut_activated, new_xml_string);
|
||||
game_shortcut_activated = false;
|
||||
}
|
||||
else if (is_tk_menu) {
|
||||
@@ -2299,9 +2347,21 @@ int OnPreCreate_Hook(MonoObject* Instance, MonoObject* element) {
|
||||
else if (id == "id_kstuff_autoload") {
|
||||
s_MonoText = mono_string_new(Root_Domain, !if_exists("/user/data/etaHEN/no_kstuff") ? "1" : "0");
|
||||
}
|
||||
else if (id == "id_enable_kstuff_on_close") {
|
||||
s_MonoText = mono_string_new(Root_Domain, global_conf.enable_kstuff_on_close ? "1" : "0");
|
||||
}
|
||||
else if (id == "id_pause_kstuff_on_open"){
|
||||
s_MonoText = mono_string_new(Root_Domain, global_conf.pause_kstuff_on_open ? "1" : "0");
|
||||
}
|
||||
else if (id == "id_pause_kstuff_on_open_secs"){
|
||||
s_MonoText = mono_string_new(Root_Domain, std::to_string(global_conf.pause_kstuff_on_open_secs).c_str());
|
||||
}
|
||||
else if (id == "id_disp_titleids"){
|
||||
s_MonoText = mono_string_new(Root_Domain, global_conf.display_tids ? "1" : "0");
|
||||
}
|
||||
else if (id == "id_enable_fan_speed"){
|
||||
s_MonoText = mono_string_new(Root_Domain, global_conf.enable_fan_speed ? "1" : "0");
|
||||
}
|
||||
else if (id == "id_ftp_service") {
|
||||
s_MonoText = mono_string_new(Root_Domain, FTP ? "1" : "0");
|
||||
}
|
||||
@@ -2314,6 +2374,9 @@ int OnPreCreate_Hook(MonoObject* Instance, MonoObject* element) {
|
||||
else if (id == "id_DPI_v2_service") {
|
||||
s_MonoText = mono_string_new(Root_Domain, DPI_v2 ? "1" : "0");
|
||||
}
|
||||
else if (id == "id_selected_cheats_repo") {
|
||||
s_MonoText = mono_string_new(Root_Domain, global_conf.selected_cheats_repo ? "1" : "0");
|
||||
}
|
||||
else if (id == "id_start_opt") {
|
||||
int opt = global_conf.start_option;
|
||||
if (global_conf.launch_itemzflow && !global_conf.start_option) {
|
||||
@@ -2339,6 +2402,9 @@ int OnPreCreate_Hook(MonoObject* Instance, MonoObject* element) {
|
||||
else if (id == "id_rest_1") {
|
||||
s_MonoText = mono_string_new(Root_Domain, std::to_string(global_conf.rest_delay_seconds).c_str());
|
||||
}
|
||||
else if (id == "id_fan_speed") {
|
||||
s_MonoText = mono_string_new(Root_Domain, std::to_string(global_conf.fan_threshold).c_str());
|
||||
}
|
||||
else if (id == "id_rest_2") {
|
||||
s_MonoText = mono_string_new(Root_Domain, global_conf.util_rest_kill ? "1" : "0");
|
||||
}
|
||||
@@ -2460,7 +2526,21 @@ bool handle_uri_boot_common(MonoString* uri, int opt, MonoString* titleIdForBoot
|
||||
cheats_shortcut_activated_not_open = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
else if (uri_string == "etaHEN?Dump") {
|
||||
#if SHELL_DEBUG==1
|
||||
shellui_log("Dump URI detected");
|
||||
#endif
|
||||
IPC_Client::getInstance(false).Launch_Dumper();
|
||||
return true; // Signal to redirect
|
||||
}
|
||||
else if (uri_string == "etaHEN?DL_UPDATE") {
|
||||
#if SHELL_DEBUG==1
|
||||
shellui_log("DL_UPDATE URI detected");
|
||||
#endif
|
||||
|
||||
return true; // Signal to redirect
|
||||
}
|
||||
|
||||
return false; // No redirect needed
|
||||
}
|
||||
|
||||
@@ -2471,6 +2551,11 @@ bool handle_uri_boot_common(MonoString* uri, int opt, MonoString* titleIdForBoot
|
||||
notify("Lite mode is enabled, shortcuts are disabled");
|
||||
return boot_orig(uri, opt, titleIdForBootAction);
|
||||
}
|
||||
|
||||
std::string uri_string = Mono_to_String(uri);
|
||||
if(uri_string == "etaHEN?Dump") {
|
||||
return boot_orig(mono_string_new(Root_Domain, "pshomeui:navigateToHome?bootCondition=psButton"), opt, titleIdForBootAction);
|
||||
}
|
||||
// Redirect to debug settings
|
||||
return boot_orig(mono_string_new(Root_Domain, "pssettings:play?mode=settings&function=debug_settings"), opt, titleIdForBootAction);
|
||||
}
|
||||
@@ -2489,6 +2574,12 @@ bool handle_uri_boot_common(MonoString* uri, int opt, MonoString* titleIdForBoot
|
||||
notify("Lite mode is enabled, shortcuts are disabled");
|
||||
return boot_orig_2(uri, opt);
|
||||
}
|
||||
|
||||
std::string uri_string = Mono_to_String(uri);
|
||||
if(uri_string == "etaHEN?Dump") {
|
||||
return boot_orig_2(mono_string_new(Root_Domain, "pshomeui:navigateToHome?bootCondition=psButton"), opt);
|
||||
}
|
||||
|
||||
return boot_orig_2(mono_string_new(Root_Domain, "pssettings:play?function=debug_settings"), opt);
|
||||
}
|
||||
|
||||
@@ -2850,11 +2941,26 @@ bool app_launched = false;
|
||||
int LaunchApp(MonoString* titleId, uint64_t* args, int argsSize, LaunchAppParam *param){
|
||||
#if 1
|
||||
if(!if_exists("/system_tmp/patch_plugin")) {
|
||||
#if SHELL_DEBUG == 1
|
||||
shellui_log("patch plugin not running .. returning with orig");
|
||||
#endif
|
||||
app_launched = true;
|
||||
return LaunchApp_orig(titleId, args, argsSize, param);
|
||||
#if SHELL_DEBUG == 1
|
||||
shellui_log("patch plugin not running .. returning with orig");
|
||||
#endif
|
||||
unsigned int ret = LaunchApp_orig(titleId, args, argsSize, param);
|
||||
if (ret < 0) {
|
||||
#if SHELL_DEBUG == 1
|
||||
notify("LaunchApp failed with error code: %d", ret);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
app_launched = true;
|
||||
if(global_conf.pause_kstuff_on_open && Mono_to_String(titleId) != "ITEM00001" && Mono_to_String(titleId).rfind("NPXS") == std::string::npos){
|
||||
pthread_t thread;
|
||||
shellui_log("Pausing Kstuff on app launch for %s in %d seconds", mono_string_to_utf8(titleId), global_conf.pause_kstuff_on_open_secs);
|
||||
pthread_create(&thread, nullptr, kstuff_pause_thread, nullptr);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
#endif
|
||||
#if SHELL_DEBUG == 1
|
||||
@@ -2870,6 +2976,13 @@ int LaunchApp(MonoString* titleId, uint64_t* args, int argsSize, LaunchAppParam
|
||||
return ret;
|
||||
}
|
||||
|
||||
app_launched = true;
|
||||
if(global_conf.pause_kstuff_on_open && Mono_to_String(titleId) != "ITEM00001" && Mono_to_String(titleId).rfind("NPXS") == std::string::npos){
|
||||
pthread_t thread;
|
||||
shellui_log("Pausing Kstuff on app launch for %s in %d seconds", mono_string_to_utf8(titleId), global_conf.pause_kstuff_on_open_secs);
|
||||
pthread_create(&thread, nullptr, kstuff_pause_thread, nullptr);
|
||||
}
|
||||
|
||||
#if SHELL_DEBUG == 1
|
||||
notify("LaunchApp returned: %d", ret);
|
||||
#endif
|
||||
@@ -2988,9 +3101,9 @@ void createJson_hook(MonoObject* inst, MonoObject* array, MonoString* id, MonoSt
|
||||
shellui_log("Updated menu titleId: %s", current_menu_tid.c_str());
|
||||
#endif
|
||||
}
|
||||
#if 0
|
||||
if(id_str == "MENU_ID_SAVE_DATA_MANAGEMENT_PS4_MANUAL"){
|
||||
createJson(inst, array, mono_string_new(Root_Domain, "MENU_ID_CUST_UPDATES"), mono_string_new(Root_Domain, "★ Game Updates"), mono_string_new(Root_Domain, "etaHEN?Pick_Update"), actionId, nullptr, subMenu, enable);
|
||||
#if 1
|
||||
if(id_str == "MENU_ID_SAVE_DATA_MANAGEMENT_PS4_MANUAL" || id_str == "MENU_ID_SAVE_DATA_MANAGEMENT_PS5_MANUAL" || (id_str == "MENU_ID_UPDATE_HISTORY" && 0)){
|
||||
createJson(inst, array, mono_string_new(Root_Domain, "MENU_ID_CUST_UPDATES"), mono_string_new(Root_Domain, "★ (Beta) Dump Game/App"), mono_string_new(Root_Domain, "etaHEN?Dump"), actionId, nullptr, subMenu, enable);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -3000,6 +3113,12 @@ void createJson_hook(MonoObject* inst, MonoObject* array, MonoString* id, MonoSt
|
||||
return;
|
||||
}
|
||||
|
||||
if(id_str == "MENU_ID_INTELLECTUAL_PROPERTY_NOTICES"){
|
||||
std::string uri = "psappinst:pat-uninstall?titleid=" + current_menu_tid;
|
||||
createJson(inst, array, mono_string_new(Root_Domain, "MENU_ID_REMOVE_UPDATE"), mono_string_new(Root_Domain, "★ Delete"), mono_string_new(Root_Domain, uri.c_str()), actionId, nullptr, subMenu, enable);
|
||||
return;
|
||||
}
|
||||
|
||||
createJson(inst, array, id, label, actionUrl, actionId, messageId, subMenu, enable);
|
||||
}
|
||||
|
||||
@@ -3022,5 +3141,6 @@ void Terminate() {
|
||||
IPC_Client& ipc = IPC_Client::getInstance(true);
|
||||
ipc.SendRestModeAction();
|
||||
}
|
||||
pause_resume_kstuff(NOT_PAUSED, true);
|
||||
oTerminate();
|
||||
}
|
||||
@@ -32,7 +32,6 @@ along with this program; see the file COPYING. If not, see
|
||||
#include "../../extern/tiny-json/tiny-json.hpp"
|
||||
#include "proc.h"
|
||||
|
||||
#include <json.hpp>
|
||||
#include <fstream>
|
||||
#include <ctime>
|
||||
#include <iostream>
|
||||
@@ -256,86 +255,6 @@ void Widget_Append_Child(MonoObject* widget, MonoObject* child)
|
||||
mono_runtime_invoke(appendChild, widget, args, nullptr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int endswith(const char *string, const char *suffix)
|
||||
{
|
||||
size_t suffix_len = strlen(suffix);
|
||||
size_t string_len = strlen(string);
|
||||
|
||||
if (string_len < suffix_len)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return strncmp(string + string_len - suffix_len, suffix, suffix_len) != 0;
|
||||
}
|
||||
|
||||
int chmod_bins(const char *path)
|
||||
{
|
||||
char buf[PATH_MAX + 1];
|
||||
struct dirent *entry;
|
||||
struct stat st;
|
||||
DIR *dir;
|
||||
|
||||
if (stat(path, &st) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (endswith(path, ".prx") || endswith(path, ".sprx") || endswith(path, "/eboot.bin"))
|
||||
{
|
||||
chmod(path, 0755);
|
||||
}
|
||||
|
||||
if (S_ISDIR(st.st_mode))
|
||||
{
|
||||
dir = opendir(path);
|
||||
while (1)
|
||||
{
|
||||
entry = readdir(dir);
|
||||
if (entry == nullptr)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, ".."))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
sprintf(buf, "%s/%s", path, entry->d_name);
|
||||
chmod_bins(buf);
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Launch_FG_Game(const char *path, const char* title_id, const char* title){
|
||||
app_launch_ctx_t ctx = {0};
|
||||
char dst[PATH_MAX + 1];
|
||||
|
||||
strcpy(dst, "/system_ex/app/");
|
||||
strcat(dst, title_id);
|
||||
//mkdir(dst, 0777);
|
||||
|
||||
sceUserServiceInitialize(0);
|
||||
sceUserServiceGetForegroundUser(&ctx.user_id);
|
||||
IPC_Client& main_ipc = IPC_Client::getInstance(false);
|
||||
if(!main_ipc.Remount(path, dst)){
|
||||
// shellui_log("Failed to mount app");
|
||||
return -1;
|
||||
}
|
||||
chmod_bins(path);
|
||||
|
||||
char *argv[] = {(char*)title, nullptr};
|
||||
|
||||
return sceSystemServiceLaunchApp(title_id, &argv[0], &ctx);
|
||||
}
|
||||
|
||||
int find_and_replace(unsigned char * buffer, int buffer_size,
|
||||
const char * target,
|
||||
const char * replacement) {
|
||||
@@ -657,17 +576,27 @@ bool LoadSettings()
|
||||
const char *jb_debug_msg_str = ini_parser_get(&parser, "Settings.APP_JB_Debug_Msg", "0");
|
||||
const char *game_opts_str = ini_parser_get(&parser, "Settings.etaHEN_Game_Options", "1");
|
||||
const char *auto_eject_disc_str = ini_parser_get(&parser, "Settings.auto_eject_disc", "0");
|
||||
const char* overlay_ram = ini_parser_get(&parser, "Settings.overlay_ram", "1");
|
||||
const char* overlay_cpu = ini_parser_get(&parser, "Settings.overlay_cpu", "1");
|
||||
const char* overlay_gpu = ini_parser_get(&parser, "Settings.overlay_gpu", "1");
|
||||
const char* overlay_fps = ini_parser_get(&parser, "Settings.overlay_fps", "0");
|
||||
const char* overlay_ip = ini_parser_get(&parser, "Settings.overlay_ip", "0");
|
||||
const char* overlay_position = ini_parser_get(&parser, "Settings.Overlay_pos", "0"); // 0: Top-Left, 1: Top-Right, 2: Bottom-Left, 3: Bottom-Right
|
||||
const char* overlay_kstuff = ini_parser_get(&parser, "Settings.overlay_kstuff", "0");
|
||||
const char* overlay_ram = ini_parser_get(&parser, "Settings.overlay_ram", "1");
|
||||
const char* overlay_cpu = ini_parser_get(&parser, "Settings.overlay_cpu", "1");
|
||||
const char* overlay_gpu = ini_parser_get(&parser, "Settings.overlay_gpu", "1");
|
||||
const char* overlay_fps = ini_parser_get(&parser, "Settings.overlay_fps", "0");
|
||||
const char* overlay_ip = ini_parser_get(&parser, "Settings.overlay_ip", "0");
|
||||
const char* overlay_position = ini_parser_get(&parser, "Settings.Overlay_pos", "0"); // 0: Top-Left, 1: Top-Right, 2: Bottom-Left, 3: Bottom-Right
|
||||
const char* overlay_kstuff = ini_parser_get(&parser, "Settings.overlay_kstuff", "0");
|
||||
const char* enable_kstuff_on_close = ini_parser_get(&parser, "Settings.enable_kstuff_on_close", "0");
|
||||
const char* id_pause_kstuff_on_open = ini_parser_get(&parser, "Settings.pause_kstuff_on_open", "0");
|
||||
const char* id_pause_kstuff_on_open_secs = ini_parser_get(&parser, "Settings.pause_kstuff_on_open_secs", "10");
|
||||
const char* fan_threshold = ini_parser_get(&parser, "Settings.fan_threshold", "77");
|
||||
const char* enable_fan_speed = ini_parser_get(&parser, "Settings.enable_fan_speed", "0");
|
||||
|
||||
|
||||
// Check if the strings are not nullptr before converting
|
||||
global_conf.overlay_kstuff = overlay_kstuff ? atoi(overlay_kstuff) : 0;
|
||||
global_conf.enable_kstuff_on_close = enable_kstuff_on_close ? atoi(enable_kstuff_on_close) : 0;
|
||||
global_conf.pause_kstuff_on_open = id_pause_kstuff_on_open ? atoi(id_pause_kstuff_on_open) : 0;
|
||||
global_conf.pause_kstuff_on_open_secs = id_pause_kstuff_on_open_secs ? atoi(id_pause_kstuff_on_open_secs) : 10;
|
||||
global_conf.enable_fan_speed = enable_fan_speed ? atoi(enable_fan_speed) : 0;
|
||||
global_conf.overlay_kstuff = overlay_kstuff ? atoi(overlay_kstuff) : 0;
|
||||
global_conf.fan_threshold = fan_threshold ? atoi(fan_threshold) : 77;
|
||||
global_conf.FTP = FTP_str ? atoi(FTP_str) : 0;
|
||||
global_conf.etaHEN_game_opts = game_opts_str ? atoi(game_opts_str) : 0;
|
||||
global_conf.display_tids = dip_tid ? atoi(dip_tid) : 0;
|
||||
@@ -693,6 +622,9 @@ bool LoadSettings()
|
||||
global_conf.overlay_cpu = overlay_cpu ? atoi(overlay_cpu) : 1;
|
||||
global_conf.overlay_gpu = overlay_gpu ? atoi(overlay_gpu) : 1;
|
||||
global_conf.overlay_fps = overlay_fps ? atoi(overlay_fps) : 0;
|
||||
if (global_conf.overlay_fps ){
|
||||
touch_file("/system_tmp/fps_enabled");
|
||||
}
|
||||
global_conf.overlay_ip = overlay_ip ? atoi(overlay_ip) : 0;
|
||||
|
||||
//apply ovelay pos values
|
||||
@@ -808,6 +740,11 @@ bool SaveSettings()
|
||||
buff += "overlay_fps=" + std::to_string(global_conf.overlay_fps) + "\n";
|
||||
buff += "overlay_ip=" + std::to_string(global_conf.overlay_ip) + "\n";
|
||||
buff += "overlay_kstuff=" + std::to_string(global_conf.overlay_kstuff) + "\n";
|
||||
buff += "enable_kstuff_on_close=" + std::to_string(global_conf.enable_kstuff_on_close) + "\n";
|
||||
buff += "pause_kstuff_on_open=" + std::to_string(global_conf.pause_kstuff_on_open) + "\n";
|
||||
buff += "enable_fan_speed=" + std::to_string(global_conf.enable_fan_speed) + "\n";
|
||||
buff += "fan_threshold=" + std::to_string(global_conf.fan_threshold) + "\n";
|
||||
buff += "pause_kstuff_on_open_secs=" + std::to_string(global_conf.pause_kstuff_on_open_secs) + "\n";
|
||||
//shortcuts
|
||||
buff += "Cheats_shortcut_opt=" + std::to_string(global_conf.cheats_shortcut_opt) + "\n";
|
||||
buff += "Toolbox_shortcut_opt=" + std::to_string(global_conf.toolbox_shortcut_opt) + "\n";
|
||||
@@ -1166,7 +1103,7 @@ void generate_plugin_xml(std::string &xml_buffer, bool plugins_xml)
|
||||
}
|
||||
else if(is_elf){
|
||||
strncpy(header.prefix, "<elf>", 5);
|
||||
strncpy(header.plugin_version, "?.??", 4);
|
||||
strncpy(header.plugin_version, "", 4);
|
||||
}
|
||||
shellui_log("Valid plugin file.");
|
||||
|
||||
@@ -1181,11 +1118,13 @@ void generate_plugin_xml(std::string &xml_buffer, bool plugins_xml)
|
||||
|
||||
shown_path = (path.substr(0, 4) == "/usb") ? "/mnt" + path : shown_path;
|
||||
|
||||
std::string version_str = !is_elf ? "(v" + std::string(header.plugin_version) + ")" : "";
|
||||
|
||||
id = plugins_xml ? "id_plugin_" + std::to_string(toggle_switch_id++) : "id_auto_plugin_" + std::to_string(toggle_switch_id++);
|
||||
if (plugins_xml)
|
||||
toggle_switch = "<toggle_switch id=\"" + id + "\" title=\"" + entry->d_name + " (v" + header.plugin_version + ")\" second_title=\"Start/Stop " + entry->d_name + " (Path: " + shown_path + ") (" + (is_elf ? entry->d_name : header.titleID) + ")\" value=\"0\"/>\n";
|
||||
toggle_switch = "<toggle_switch id=\"" + id + "\" title=\"" + entry->d_name + " " + version_str + "\" second_title=\"Start/Stop " + entry->d_name + " (Path: " + shown_path + ") (" + (is_elf ? entry->d_name : header.titleID) + ")\" value=\"0\"/>\n";
|
||||
else
|
||||
toggle_switch = "<toggle_switch id=\"" + id + "\" title=\"" + entry->d_name + " (v" + header.plugin_version + ")\" second_title=\"Enable/Disable auto start for " + entry->d_name + " (" + shown_path + ")\" value=\"0\"/>\n";
|
||||
toggle_switch = "<toggle_switch id=\"" + id + "\" title=\"" + entry->d_name + " " + version_str + "\" second_title=\"Enable/Disable auto start for " + entry->d_name + " (" + shown_path + ")\" value=\"0\"/>\n";
|
||||
|
||||
xml_buffer += toggle_switch;
|
||||
new_list.tid = (is_elf ? entry->d_name : header.titleID);
|
||||
@@ -1372,213 +1311,6 @@ void escapeXML(std::string& input)
|
||||
}
|
||||
}
|
||||
|
||||
bool getContentInfofromJson(const std::string& file_path, std::string& tid, std::string& title, std::string &ver) {
|
||||
try {
|
||||
std::ifstream input_file(file_path);
|
||||
if (!input_file.is_open()) {
|
||||
shellui_log("Failed to open file for reading: %s", file_path.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
json j;
|
||||
input_file >> j;
|
||||
input_file.close();
|
||||
|
||||
if (!j.contains("titleId")) {
|
||||
shellui_log("JSON does not contain a required value");
|
||||
return false;
|
||||
}
|
||||
|
||||
tid = j["titleId"];
|
||||
|
||||
#if SHELL_DEBUG==1
|
||||
shellui_log("getContentInfofromJson Title ID: %s", tid.c_str());
|
||||
#endif
|
||||
|
||||
if (j.contains("localizedParameters") && j["localizedParameters"].contains("defaultLanguage")) {
|
||||
std::string defaultLanguage = j["localizedParameters"]["defaultLanguage"];
|
||||
if (j["localizedParameters"].contains(defaultLanguage) && j["localizedParameters"][defaultLanguage].contains("titleName")) {
|
||||
title = j["localizedParameters"][defaultLanguage]["titleName"];
|
||||
}
|
||||
}
|
||||
else
|
||||
title = "App Title not found";
|
||||
|
||||
if (j.contains("contentVersion"))
|
||||
ver = j["contentVersion"];
|
||||
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
shellui_log("Exception: %s", e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
int list_directories(const char *path) {
|
||||
DIR *dir;
|
||||
struct dirent *entry;
|
||||
struct stat statbuf;
|
||||
char fullpath[1024];
|
||||
|
||||
// Open the directory
|
||||
if ((dir = opendir(path)) == NULL) {
|
||||
perror("opendir");
|
||||
return -1;
|
||||
}
|
||||
|
||||
shellui_log("Directories in %s:\n", path);
|
||||
|
||||
// Read directory entries
|
||||
while ((entry = readdir(dir)) != NULL) {
|
||||
// Skip "." and ".." entries
|
||||
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
|
||||
continue;
|
||||
|
||||
// Construct the full path
|
||||
snprintf(fullpath, sizeof(fullpath), "%s/%s", path, entry->d_name);
|
||||
|
||||
// Get information about the file
|
||||
if (stat(fullpath, &statbuf) == -1) {
|
||||
perror("stat");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if it's a directory
|
||||
if (S_ISDIR(statbuf.st_mode)) {
|
||||
shellui_log("%s", entry->d_name);
|
||||
}
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Function to escape a string for XML
|
||||
void generate_games_xml(std::string &xml_buffer, bool game_shortcut_activated)
|
||||
{
|
||||
struct dirent *entry;
|
||||
// do outside func
|
||||
// games_list.clear();
|
||||
|
||||
std::vector<std::string> directories = {
|
||||
"/user/data/etaHEN/games",
|
||||
"/usb0/etaHEN/games",
|
||||
"/usb1/etaHEN/games",
|
||||
"/usb2/etaHEN/games",
|
||||
"/usb3/etaHEN/games",
|
||||
"/mnt/ext1/etaHEN/games",
|
||||
"/mnt/ext2/etaHEN/games",
|
||||
"/mnt/ext0/etaHEN/games",
|
||||
};
|
||||
// list_directories("/mnt/sandbox/NPXS40087_000");
|
||||
|
||||
std::string list_id = game_shortcut_activated ? "id_debug_settings" : "id_ps5_backups";
|
||||
|
||||
xml_buffer = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
|
||||
"<system_settings version=\"1.0\" plugin=\"debug_settings_plugin\">\n"
|
||||
"\n";
|
||||
|
||||
xml_buffer += "<setting_list id=\"" + list_id + "\" title=\"(Beta) PS5 webMAN Games\">\n";
|
||||
|
||||
|
||||
// Initialize random number generator
|
||||
std::random_device rd;
|
||||
std::mt19937 gen(rd());
|
||||
std::uniform_int_distribution<int> dist(1000, 9999);
|
||||
|
||||
for (const auto &directory : directories)
|
||||
{
|
||||
DIR *dir = opendir(directory.c_str());
|
||||
// Open the directory
|
||||
if (!dir)
|
||||
{
|
||||
#if SHELL_DEBUG==1
|
||||
shellui_log("Failed to open directory: %s", directory.c_str());
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
// Iterate over each entry in the games directory
|
||||
while ((entry = readdir(dir)) != nullptr)
|
||||
{
|
||||
// Skip . and .. directories
|
||||
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
|
||||
continue;
|
||||
|
||||
std::string game_dir = directory + "/" + entry->d_name;
|
||||
|
||||
// Check if this is a directory by trying to open it
|
||||
struct stat st;
|
||||
if (stat(game_dir.c_str(), &st) != 0 || !S_ISDIR(st.st_mode)) {
|
||||
#if SHELL_DEBUG==1
|
||||
shellui_log("Skipping non-directory: %s", game_dir.c_str());
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string param_path = game_dir + "/sce_sys/param.json";
|
||||
std::string icon_path = game_dir + "/sce_sys/icon0.png";
|
||||
|
||||
// Check if param.json exists
|
||||
if (access(param_path.c_str(), F_OK) != 0) {
|
||||
#if SHELL_DEBUG==1
|
||||
shellui_log("No param.json found in: %s", game_dir.c_str());
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
#if SHELL_DEBUG==1
|
||||
shellui_log("Found Game: %s", game_dir.c_str());
|
||||
#endif
|
||||
|
||||
// Parse the JSON to get title_id, content_id, title, and version
|
||||
std::string title_id, title, ver;
|
||||
if (!getContentInfofromJson(param_path, title_id, title, ver)) {
|
||||
#if SHELL_DEBUG==1
|
||||
shellui_log("Failed to parse param.json in: %s", game_dir.c_str());
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string shown_path = game_dir; // Initialize with the original path
|
||||
|
||||
const std::string prefix = "/user";
|
||||
if (shown_path.find(prefix) == 0) { // Check if the path starts with "/user"
|
||||
shown_path = shown_path.substr(prefix.length()); // Remove "/user"
|
||||
}
|
||||
|
||||
shown_path = (game_dir.substr(0, 4) == "/usb") ? "/mnt" + game_dir : shown_path;
|
||||
// Generate a random number for the ID
|
||||
int random_num = dist(gen);
|
||||
|
||||
// Escape the icon path for XML
|
||||
escapeXML(icon_path);
|
||||
|
||||
// Create and populate a GameEntry
|
||||
GameEntry game;
|
||||
game.tid = title_id;
|
||||
game.title = title;
|
||||
game.version = ver;
|
||||
game.path = shown_path;
|
||||
game.dir_name = entry->d_name;
|
||||
game.icon_path = icon_path;
|
||||
game.id = "id_game_" + title_id + "_" + std::to_string(random_num);
|
||||
|
||||
// Add to the games list
|
||||
games_list.push_back(game);
|
||||
|
||||
// Format the button XML
|
||||
std::string button = "<button id=\"" + game.id + "\" title=\"(" + title_id + ") " + title +
|
||||
"\" icon=\"" + icon_path + "\" second_title=\"" + shown_path + " | Version: " + ver + "\"/>\n";
|
||||
|
||||
xml_buffer += button;
|
||||
}
|
||||
//shellui_log("cloaing dir %s", directory.c_str());
|
||||
closedir(dir);
|
||||
}
|
||||
|
||||
xml_buffer += "</setting_list>\n</system_settings> ";
|
||||
}
|
||||
|
||||
void ReloadRNPSApp(const char* title_id){
|
||||
void (*ReloadApp)(MonoString* tid) = (void(*)(MonoString*))Get_Address_of_Method(react_common_img, "ReactNative.Vsh.Common", "ReactApplicationSceneManager", "ReloadApp", 1);
|
||||
@@ -1596,7 +1328,12 @@ void generate_cheats_xml(std::string &new_xml, std::string& not_open_tid, bool r
|
||||
std::string list_id = running_as_debug_settings ? "id_debug_settings" : "id_cheat_title";
|
||||
|
||||
// buttons for if nothing is found
|
||||
std::string dl_cheats = R"(<button id="id_dl_cheats" title="Download/Update Cheats" second_title="Downloads the latest cheats from the PS5_Cheats GitHub repo"/>)";
|
||||
std::string dl_cheats = R"(<list id="id_selected_cheats_repo" title="Cheats Repo Source" >
|
||||
<list_item id="id_selected_cheats_repo_1" title="etaHEN PS5 Cheats repo" value="0"/>
|
||||
<list_item id="id_selected_cheats_repo_2" title="GoldHEN PS4 Cheats repo" value="1"/>
|
||||
</list>
|
||||
<button id="id_dl_cheats" title="Download/Update Cheats" second_title="Downloads the latest cheats from the selected GitHub repo"/>)";
|
||||
|
||||
std::string reload_cheats = R"(<button id="id_reload_cheats" title="Cache and reload Cheats list" second_title="New cheats added to /data/etaHEN/cheats/EXT_HERE will be cached and the cheats list will be reloaded"/>)";
|
||||
//
|
||||
|
||||
@@ -1859,7 +1596,7 @@ void generate_plapps_xml(std::string& new_xml) {
|
||||
game.dir_name = entry->d_name;
|
||||
escapeXML(game.dir_name);
|
||||
game.icon_path = icon_path;
|
||||
game.id = "id_game_" + title_id + "_" + std::to_string(random_num);
|
||||
game.id = "id_etahen_pl_loader_" + title_id + "_" + std::to_string(random_num);
|
||||
|
||||
// Add to the games list
|
||||
games_list.push_back(game);
|
||||
|
||||
@@ -82,6 +82,42 @@ void ReloadApp(MonoString *str){
|
||||
Orig_ReloadApp(str);
|
||||
}
|
||||
|
||||
#define PLAYGOSCENARIOID_SIZE 3
|
||||
#define CONTENTID_SIZE 0x30
|
||||
#define LANGUAGE_SIZE 8
|
||||
|
||||
typedef char playgo_scenario_id_t[PLAYGOSCENARIOID_SIZE];
|
||||
typedef char language_t[LANGUAGE_SIZE];
|
||||
typedef char content_id_t[CONTENTID_SIZE];
|
||||
|
||||
typedef struct
|
||||
{
|
||||
content_id_t content_id;
|
||||
int content_type;
|
||||
int content_platform;
|
||||
} SceAppInstallPkgInfo;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char* uri;
|
||||
const char* ex_uri;
|
||||
const char* playgo_scenario_id;
|
||||
const char* content_id;
|
||||
const char* content_name;
|
||||
const char* icon_url;
|
||||
} MetaInfo;
|
||||
|
||||
#define NUM_LANGUAGES 30
|
||||
#define NUM_IDS 64
|
||||
|
||||
typedef struct {
|
||||
language_t languages[NUM_LANGUAGES];
|
||||
playgo_scenario_id_t playgo_scenario_ids[NUM_IDS];
|
||||
content_id_t content_ids[NUM_IDS];
|
||||
long unknown[810];
|
||||
} PlayGoInfo;
|
||||
|
||||
|
||||
//int _AppInstUtilInstallByPackage(string uri, string ex_uri, string playgo_scenario_id, string content_id, string content_name, string icon_url, uint slot, bool is_playgo_enabled, ref AppInstUtilWrapper.SceAppInstallPkgInfo pkg_info, string[] languages, string[] playgo_scenario_ids, string[] content_ids);
|
||||
|
||||
int (*Orig_AppInstUtilInstallByPackage)(MonoString* uri, MonoString* ex_uri, MonoString* playgo_scenario_id, MonoString* content_id, MonoString* content_name, MonoString* icon_url, uint32_t slot, bool is_playgo_enabled, MonoObject* pkg_info, MonoArray* languages, MonoArray* playgo_scenario_ids, MonoArray* content_ids) = nullptr;
|
||||
@@ -150,6 +186,21 @@ Proc_Stats Stat_Data[3072];
|
||||
thread_usages gThread_Data[2];
|
||||
|
||||
|
||||
extern "C" int sceLncUtilKillAppWithReason(int appId, int reason);
|
||||
void pause_resume_kstuff(KstuffPauseStatus opt, bool notify_user);
|
||||
|
||||
int KillAppWithReason_Hook(int appId, int reason)
|
||||
{
|
||||
// shellui_log("KillAppWithReason_Hook called with appId: %d, reason: %d", appId, reason);
|
||||
//notify("Killing app %d", appId);
|
||||
if(global_conf.enable_kstuff_on_close)
|
||||
pause_resume_kstuff(NOT_PAUSED, true);
|
||||
|
||||
int ret = sceLncUtilKillAppWithReason(appId, reason);
|
||||
//shellui_log("KillAppWithReason_Hook returned: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Get_Page_Table_Stats(int vm, int type, int* Used, int* Free, int* Total)
|
||||
{
|
||||
int _Total = 0, _Free = 0;
|
||||
@@ -243,8 +294,94 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
AtomicString fps_string;
|
||||
void* search_bytes(const void* haystack, size_t haystack_len,
|
||||
const void* needle, size_t needle_len){
|
||||
|
||||
if (needle_len == 0 || needle_len > haystack_len) {
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
const unsigned char* h = (const unsigned char*)haystack;
|
||||
const unsigned char* n = (const unsigned char*)needle;
|
||||
|
||||
|
||||
for (size_t i = 0; i <= haystack_len - needle_len; i++) {
|
||||
if (memcmp(&h[i], n, needle_len) == 0) {
|
||||
return (void*)&h[i];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
}
|
||||
void ShellHexDump(const void* data, size_t size) {
|
||||
const unsigned char* byteData = static_cast<const unsigned char*>(data);
|
||||
char line[256];
|
||||
|
||||
for (size_t i = 0; i < size; i += 16) {
|
||||
int pos = 0;
|
||||
|
||||
// Offset
|
||||
pos += snprintf(line + pos, sizeof(line) - pos, "%08zx ", i);
|
||||
|
||||
// Hex bytes
|
||||
for (size_t j = 0; j < 16; ++j) {
|
||||
if (i + j < size) {
|
||||
pos += snprintf(line + pos, sizeof(line) - pos, "%02x ",
|
||||
byteData[i + j]);
|
||||
} else {
|
||||
pos += snprintf(line + pos, sizeof(line) - pos, " ");
|
||||
}
|
||||
}
|
||||
|
||||
pos += snprintf(line + pos, sizeof(line) - pos, " ");
|
||||
|
||||
// ASCII representation
|
||||
for (size_t j = 0; j < 16; ++j) {
|
||||
if (i + j < size) {
|
||||
unsigned char c = byteData[i + j];
|
||||
pos += snprintf(line + pos, sizeof(line) - pos, "%c",
|
||||
isprint(c) ? c : '.');
|
||||
}
|
||||
}
|
||||
|
||||
shellui_log(line);
|
||||
}
|
||||
}
|
||||
AtomicString fps_string;
|
||||
ssize_t(*read_orig)(int fd, void *buf, size_t count) = nullptr;
|
||||
ssize_t read_hook(int fd, void* buf, size_t count) {
|
||||
ssize_t ret = read_orig(fd, buf, count);
|
||||
// shellui_log("read_hook called: fd=%d, count=%zu, ret=%zd", fd, count, ret);
|
||||
if (count == 65536) {
|
||||
void* found = search_bytes(buf, 100, "FPS", 3);
|
||||
if (found) {
|
||||
const char* fps_ptr = (const char*)found;
|
||||
|
||||
// Skip "FPS" and any separators (: = space etc)
|
||||
fps_ptr += 3; // Skip "FPS"
|
||||
while (*fps_ptr && !isdigit(*fps_ptr)) {
|
||||
fps_ptr++;
|
||||
}
|
||||
|
||||
// Extract the number
|
||||
std::string fps_value;
|
||||
while (*fps_ptr && (isdigit(*fps_ptr) || *fps_ptr == '.')) {
|
||||
fps_value += *fps_ptr;
|
||||
fps_ptr++;
|
||||
}
|
||||
|
||||
if (!fps_value.empty()) {
|
||||
fps_string.store(fps_value);
|
||||
// shellui_log("Captured FPS: %s", fps_value.c_str());
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int get_ip_address(char* ip_address);
|
||||
void OnRender_Hook(MonoObject* instance)
|
||||
@@ -276,7 +413,7 @@ void OnRender_Hook(MonoObject* instance)
|
||||
|
||||
if (!Do_Once)
|
||||
{
|
||||
#if 0
|
||||
#if 1
|
||||
fps_string.store("LOADING");
|
||||
#else
|
||||
fps_string.store("NOT SUPPORTED IN THIS BUILD");
|
||||
@@ -420,6 +557,145 @@ void OnRender_Hook(MonoObject* instance)
|
||||
}
|
||||
|
||||
|
||||
|
||||
int (*sceAppInstUtilInstallByPackage_orig)(MetaInfo* arg1, SceAppInstallPkgInfo* pkg_info, PlayGoInfo* arg2) = nullptr;
|
||||
void hex_dump(const char* label, const void* data, size_t size) {
|
||||
const unsigned char* bytes = (const unsigned char*)data;
|
||||
shellui_log("=== %s (size: %zu bytes) ===", label, size);
|
||||
|
||||
for (size_t i = 0; i < size; i += 16) {
|
||||
char line[128];
|
||||
int offset = 0;
|
||||
|
||||
// Print offset
|
||||
offset += snprintf(line + offset, sizeof(line) - offset,
|
||||
"%04zx: ", i);
|
||||
|
||||
// Print hex values
|
||||
for (size_t j = 0; j < 16; j++) {
|
||||
if (i + j < size) {
|
||||
offset += snprintf(line + offset, sizeof(line) - offset,
|
||||
"%02x ", bytes[i + j]);
|
||||
}
|
||||
else {
|
||||
offset += snprintf(line + offset, sizeof(line) - offset,
|
||||
" ");
|
||||
}
|
||||
}
|
||||
|
||||
// Print ASCII representation
|
||||
offset += snprintf(line + offset, sizeof(line) - offset, " |");
|
||||
for (size_t j = 0; j < 16 && i + j < size; j++) {
|
||||
unsigned char c = bytes[i + j];
|
||||
offset += snprintf(line + offset, sizeof(line) - offset,
|
||||
"%c", (c >= 32 && c <= 126) ? c : '.');
|
||||
}
|
||||
offset += snprintf(line + offset, sizeof(line) - offset, "|");
|
||||
|
||||
shellui_log("%s", line);
|
||||
}
|
||||
}
|
||||
extern "C" int sceAppInstUtilInitialize();
|
||||
|
||||
int sceAppInstUtilInstallByPackage_hook(MetaInfo* arg1,
|
||||
SceAppInstallPkgInfo* pkg_info,
|
||||
PlayGoInfo* arg2) {
|
||||
|
||||
shellui_log("========== sceAppInstUtilInstallByPackage_hook ==========");
|
||||
|
||||
sceAppInstUtilInitialize();
|
||||
|
||||
// Print MetaInfo
|
||||
if (arg1) {
|
||||
shellui_log("--- MetaInfo ---");
|
||||
shellui_log("uri: %s", arg1->uri ? arg1->uri : "(null)");
|
||||
shellui_log("ex_uri: %s", arg1->ex_uri ? arg1->ex_uri : "(null)");
|
||||
shellui_log("playgo_scenario_id: %s",
|
||||
arg1->playgo_scenario_id ? arg1->playgo_scenario_id : "(null)");
|
||||
shellui_log("content_id: %s",
|
||||
arg1->content_id ? arg1->content_id : "(null)");
|
||||
shellui_log("content_name: %s",
|
||||
arg1->content_name ? arg1->content_name : "(null)");
|
||||
shellui_log("icon_url: %s",
|
||||
arg1->icon_url ? arg1->icon_url : "(null)");
|
||||
}
|
||||
else {
|
||||
shellui_log("MetaInfo: (null)");
|
||||
}
|
||||
|
||||
// Print SceAppInstallPkgInfo
|
||||
if (pkg_info) {
|
||||
shellui_log("--- SceAppInstallPkgInfo ---");
|
||||
shellui_log("content_id: %.*s", CONTENTID_SIZE, pkg_info->content_id);
|
||||
shellui_log("content_type: %d", pkg_info->content_type);
|
||||
shellui_log("content_platform: %d", pkg_info->content_platform);
|
||||
}
|
||||
else {
|
||||
shellui_log("SceAppInstallPkgInfo: (null)");
|
||||
}
|
||||
|
||||
// Print PlayGoInfo
|
||||
if (arg2) {
|
||||
shellui_log("--- PlayGoInfo ---");
|
||||
|
||||
// Print languages
|
||||
shellui_log("Languages:");
|
||||
for (int i = 0; i < NUM_LANGUAGES; i++) {
|
||||
if (arg2->languages[i][0] != '\0') {
|
||||
shellui_log(" [%d]: %.*s", i, LANGUAGE_SIZE,
|
||||
arg2->languages[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Print playgo_scenario_ids
|
||||
shellui_log("PlayGo Scenario IDs:");
|
||||
for (int i = 0; i < NUM_IDS; i++) {
|
||||
if (arg2->playgo_scenario_ids[i][0] != '\0') {
|
||||
shellui_log(" [%d]: %.*s", i, PLAYGOSCENARIOID_SIZE,
|
||||
arg2->playgo_scenario_ids[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Print content_ids
|
||||
shellui_log("Content IDs:");
|
||||
for (int i = 0; i < NUM_IDS; i++) {
|
||||
if (arg2->content_ids[i][0] != '\0') {
|
||||
shellui_log(" [%d]: %.*s", i, CONTENTID_SIZE,
|
||||
arg2->content_ids[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Hex dump unknown portion
|
||||
hex_dump("PlayGoInfo::unknown", arg2->unknown,
|
||||
sizeof(arg2->unknown));
|
||||
}
|
||||
else {
|
||||
shellui_log("PlayGoInfo: (null)");
|
||||
}
|
||||
|
||||
shellui_log("========== Calling Original Function ==========");
|
||||
notify("Installing package from:\n%s",
|
||||
arg1 ? (arg1->uri ? arg1->uri : "(null)") : "(null)");
|
||||
|
||||
int ret = sceAppInstUtilInstallByPackage_orig(arg1, pkg_info, arg2);
|
||||
|
||||
shellui_log("sceAppInstUtilInstallByPackage_hook returned: %d", ret);
|
||||
notify("Installation finished with code: %d", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
bool is_6xx = false, is_3xx = false;
|
||||
|
||||
void* dialogue_thread(void* arg) {
|
||||
while (true) {
|
||||
sleep(1);
|
||||
if(if_exists("/user/data/test.flag")){
|
||||
|
||||
unlink("/user/data/test.flag");
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
int main(int argc, char const *argv[]) {
|
||||
OrbisKernelSwVersion sw;
|
||||
char buz[100];
|
||||
@@ -428,10 +704,15 @@ int main(int argc, char const *argv[]) {
|
||||
}
|
||||
|
||||
static ssize_t(*read)(int fd, void* buf, size_t count) = nullptr;
|
||||
static int (*sceAppInstUtilInstallByPackage)(MetaInfo * arg1, SceAppInstallPkgInfo * pkg_info, PlayGoInfo * arg2) = nullptr;
|
||||
|
||||
|
||||
pid_t pid = getpid();
|
||||
uintptr_t old_authid = set_ucred_to_debugger();
|
||||
|
||||
|
||||
int appinstaller_handle = get_module_handle(pid, "libSceAppInstUtil.sprx");
|
||||
KERNEL_DLSYM(appinstaller_handle, sceAppInstUtilInstallByPackage);
|
||||
|
||||
|
||||
int libkernelsys_handle = get_module_handle(pid, "libkernel_sys.sprx");
|
||||
@@ -623,7 +904,8 @@ int main(int argc, char const *argv[]) {
|
||||
std::string term = base64_decode("VGVybWluYXRl"); // "Terminate"
|
||||
|
||||
sceKernelGetProsperoSystemSwVersion(&sw);
|
||||
bool is_3xx = (sw.version < 0x4000042);
|
||||
is_3xx = (sw.version < 0x4000042);
|
||||
is_6xx = (sw.version >= 0x6000000);
|
||||
shellui_log("System Software Version: %s is_3xx: %s", sw.version_str, is_3xx ? "Yes" : "No");
|
||||
|
||||
#if 0
|
||||
@@ -655,7 +937,7 @@ int main(int argc, char const *argv[]) {
|
||||
dec_ver += etaHEN_VERSION;
|
||||
std::string final_ver;
|
||||
#if PUBLIC_TEST == 1
|
||||
final_ver = dec_ver + " -PUBLIC_TEST" + " (" + sw.version_str + " )";
|
||||
final_ver = dec_ver + "-PUBLIC_TEST" + " (" + sw.version_str + " )";
|
||||
#elif PRE_RELEASE == 1
|
||||
final_ver = dec_ver + " PRE_RELEASE" + " (" + sw.version_str + " )";
|
||||
#else
|
||||
@@ -779,8 +1061,6 @@ int main(int argc, char const *argv[]) {
|
||||
}
|
||||
|
||||
shellui_log("Game ContainerScene: %p", Game);
|
||||
|
||||
OnRender_orig = (void(*)(MonoObject*)) DetourFunction(Get_Address_of_Method(pui_img, "Sce.PlayStation.PUI", "Application", "Update", 0), (void*)&OnRender_Hook);
|
||||
}
|
||||
|
||||
// System.Reflection.RuntimeAssembly.GetManifestResourceStream
|
||||
@@ -795,24 +1075,33 @@ int main(int argc, char const *argv[]) {
|
||||
shellui_log("Kstuff Paused, resuming kstuff");
|
||||
pause_resume_kstuff(NOT_PAUSED, false);
|
||||
unlink("/system_tmp/kstuff_paused");
|
||||
|
||||
while(sceKernelMprotect(&buz, sizeof(buz), PROT_READ | PROT_WRITE | PROT_EXEC) != 0) {
|
||||
klog_puts("sceKernelMprotect failed, retrying...");
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
has_hv_bypass = (sceKernelMprotect( & buz[0], 100, 0x7) == 0);
|
||||
|
||||
//SimpleHTTPServer server(1304, "/");
|
||||
//server.start();
|
||||
|
||||
Patch_Main_thread_Check(image_core);
|
||||
|
||||
|
||||
OnRender_orig = (void(*)(MonoObject*)) DetourFunction(Get_Address_of_Method(pui_img, "Sce.PlayStation.PUI", "Application", "Update", 0), (void*)&OnRender_Hook);
|
||||
|
||||
#if 0
|
||||
Orig_AppInstUtilInstallByPackage = (int (*)(MonoString * uri, MonoString * ex_uri, MonoString * playgo_scenario_id, MonoString * content_id, MonoString * content_name, MonoString * icon_url, uint32_t slot, bool is_playgo_enabled, MonoObject * pkg_info, MonoArray * languages, MonoArray * playgo_scenario_ids, MonoArray * content_ids)) DetourFunction(Get_Address_of_Method(AppInstallUtil_img, "Sce.Vsh", "AppInstUtilWrapper", "_AppInstUtilInstallByPackage", 12), (void*)&AppInstUtilInstallByPackage_Hook);
|
||||
if (!Orig_AppInstUtilInstallByPackage) {
|
||||
notify("Failed to hook AppInstUtilInstallByPackage");
|
||||
return -1;
|
||||
}
|
||||
|
||||
sceAppInstUtilInstallByPackage_orig = (int (*)(MetaInfo * arg1, SceAppInstallPkgInfo * pkg_info, PlayGoInfo * arg2)) DetourFunction((uintptr_t)sceAppInstUtilInstallByPackage, (void*)&sceAppInstUtilInstallByPackage_hook);
|
||||
if (!sceAppInstUtilInstallByPackage_orig) {
|
||||
notify("Failed to detour sceAppInstUtilInstallByPackage");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
if(sceRegMgrGetInt) {
|
||||
sceRegMgrGetInt = (int( * )(long, int * )) DetourFunction((uintptr_t)sceRegMgrGetInt, (void *)&sceRegMgrGetInt_hook);
|
||||
if (!sceRegMgrGetInt) {
|
||||
@@ -825,6 +1114,14 @@ int main(int argc, char const *argv[]) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if 1
|
||||
read_orig = (ssize_t(*)(int fd, void *buf, size_t count)) DetourFunction((uintptr_t)read, (void*)&read_hook);
|
||||
if (!read_orig) {
|
||||
notify("Failed to detour read func");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
void* createJson_addr = DetourFunction(Get_Address_of_Method(ReactNativeShellAppReactNativeShellApp_img, "ReactNative.Modules.ShellUI.HomeUI", "OptionMenu", "createJson", 8), (void * )&createJson_hook);
|
||||
createJson = (void( * )(MonoObject *, MonoObject * , MonoString * , MonoString * , MonoString * , MonoString * , MonoString * , MonoObject * , bool)) createJson_addr;
|
||||
if (!createJson_addr) {
|
||||
@@ -838,6 +1135,11 @@ int main(int argc, char const *argv[]) {
|
||||
// return -1;
|
||||
}
|
||||
|
||||
void* KillAppWithReason_orig = DetourFunction(Get_Address_of_Method(lnc_img, "Sce.Vsh.LncUtil", "LncUtilWrapper","KillAppWithReason", 2), (void *)&KillAppWithReason_Hook);
|
||||
if (!KillAppWithReason_orig) {
|
||||
notify("Failed to detour KillAppWithReason");
|
||||
}
|
||||
|
||||
UpdateImposeStatusFlag_Orig = (void( * )(MonoObject * , MonoObject * )) DetourFunction(Get_Address_of_Method(AppSystem_img, appsystem_namespace.c_str(), layer_manager.c_str(), update_impose_flag.c_str(), 2), (void * )&UpdateImposeStatusFlag_hook);
|
||||
if (!UpdateImposeStatusFlag_Orig) {
|
||||
notify("Failed to detour Func Set -1");
|
||||
@@ -943,6 +1245,8 @@ int main(int argc, char const *argv[]) {
|
||||
shellui_log("Performed Magic");
|
||||
|
||||
hooked = true;
|
||||
pthread_t thread_id;
|
||||
scePthreadCreate(&thread_id, nullptr, dialogue_thread, nullptr, "dialogue_thread");
|
||||
|
||||
// file to let the main daemon know that its finished loading
|
||||
touch_file("/system_tmp/toolbox_online");
|
||||
|
||||
@@ -243,7 +243,7 @@ int32_t sceKernelSendNotificationRequest(int32_t device, OrbisNotificationReques
|
||||
|
||||
bool IniliatizeHTTP(void);
|
||||
bool download_file(const char *url, const char *dst);
|
||||
bool check_for_new_commit();
|
||||
bool check_for_new_commit(int repo);
|
||||
bool extract_zip(const char *zip_path, const char *extract_dir);
|
||||
|
||||
|
||||
|
||||
24596
Source Code/util/include/json.hpp
Normal file
24596
Source Code/util/include/json.hpp
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
434
Source Code/util/source/gameslist.cpp
Normal file
434
Source Code/util/source/gameslist.cpp
Normal file
@@ -0,0 +1,434 @@
|
||||
#include "json.hpp"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <dirent.h>
|
||||
#include <unordered_map>
|
||||
extern "C" {
|
||||
#include "common_utils.h"
|
||||
|
||||
typedef struct app_launch_ctx
|
||||
{
|
||||
int structsize;
|
||||
int user_id;
|
||||
int app_opt;
|
||||
uint64_t crash_report;
|
||||
int check_flag;
|
||||
} app_launch_ctx_t;
|
||||
|
||||
int sceSystemServiceLaunchApp(const char *, char **, app_launch_ctx_t *);
|
||||
|
||||
#define SCE_LNC_UTIL_ERROR_ALREADY_RUNNING 0x8094000c
|
||||
#define SCE_LNC_UTIL_ERROR_ALREADY_RUNNING_KILL_NEEDED 0x80940010
|
||||
#define SCE_LNC_UTIL_ERROR_ALREADY_RUNNING_SUSPEND_NEEDED 0x80940011
|
||||
}
|
||||
|
||||
#define SHELL_DEBUG 1
|
||||
#include <sys/stat.h>
|
||||
#include <fstream>
|
||||
#include <ctime>
|
||||
#include <iostream>
|
||||
#include <random>
|
||||
#include <sys/mount.h>
|
||||
#include <sstream>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
// Game Entry structure definition
|
||||
struct GameEntry {
|
||||
std::string tid; // Title ID
|
||||
std::string title; // Game title
|
||||
std::string version; // Game version
|
||||
std::string path; // Displayed path
|
||||
std::string dir_name; // Directory name
|
||||
std::string icon_path; // Path to icon
|
||||
std::string id; // Button ID
|
||||
};
|
||||
|
||||
std::vector<GameEntry> games_list;
|
||||
|
||||
void escapePath(std::string& input)
|
||||
{
|
||||
std::unordered_map<std::string, std::string> escapeSequences =
|
||||
{
|
||||
{"&", "&"},
|
||||
{"<", "<"},
|
||||
{">", ">"},
|
||||
{"\"", """},
|
||||
{"/", "//"}
|
||||
};
|
||||
|
||||
for (const auto& pair : escapeSequences)
|
||||
{
|
||||
size_t pos = 0;
|
||||
while ((pos = input.find(pair.first, pos)) != std::string::npos)
|
||||
{
|
||||
input.replace(pos, pair.first.length(), pair.second);
|
||||
pos += pair.second.length(); // Move past the replaced part
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void escapeXML(std::string& input)
|
||||
{
|
||||
std::unordered_map<std::string, std::string> escapeSequences =
|
||||
{
|
||||
{"&", "&"},
|
||||
{"<", "<"},
|
||||
{">", ">"},
|
||||
{"\"", """},
|
||||
};
|
||||
|
||||
for (const auto& pair : escapeSequences)
|
||||
{
|
||||
size_t pos = 0;
|
||||
while ((pos = input.find(pair.first, pos)) != std::string::npos)
|
||||
{
|
||||
input.replace(pos, pair.first.length(), pair.second);
|
||||
pos += pair.second.length(); // Move past the replaced part
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool getContentInfofromJson(const std::string& file_path, std::string& tid, std::string& title, std::string &ver) {
|
||||
try {
|
||||
std::ifstream input_file(file_path);
|
||||
if (!input_file.is_open()) {
|
||||
etaHEN_log("Failed to open file for reading: %s", file_path.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
json j;
|
||||
input_file >> j;
|
||||
input_file.close();
|
||||
|
||||
if (!j.contains("titleId")) {
|
||||
etaHEN_log("JSON does not contain a required value");
|
||||
return false;
|
||||
}
|
||||
|
||||
tid = j["titleId"];
|
||||
|
||||
#if SHELL_DEBUG==1
|
||||
etaHEN_log("getContentInfofromJson Title ID: %s", tid.c_str());
|
||||
#endif
|
||||
|
||||
if (j.contains("localizedParameters") && j["localizedParameters"].contains("defaultLanguage")) {
|
||||
std::string defaultLanguage = j["localizedParameters"]["defaultLanguage"];
|
||||
if (j["localizedParameters"].contains(defaultLanguage) && j["localizedParameters"][defaultLanguage].contains("titleName")) {
|
||||
title = j["localizedParameters"][defaultLanguage]["titleName"];
|
||||
}
|
||||
}
|
||||
else
|
||||
title = "App Title not found";
|
||||
|
||||
if (j.contains("contentVersion"))
|
||||
ver = j["contentVersion"];
|
||||
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
etaHEN_log("Exception: %s", e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Helper function to check if path is from external storage
|
||||
bool isExternalStorage(const std::string &path) {
|
||||
return path.rfind("/mnt/ext") != std::string::npos;
|
||||
}
|
||||
|
||||
// Helper function to copy files
|
||||
bool copyFile(const std::string &src, const std::string &dst) {
|
||||
std::ifstream source(src, std::ios::binary);
|
||||
if (!source.is_open()) {
|
||||
#if SHELL_DEBUG==1
|
||||
etaHEN_log("Failed to open source file: %s", src.c_str());
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
std::ofstream dest(dst, std::ios::binary);
|
||||
if (!dest.is_open()) {
|
||||
#if SHELL_DEBUG==1
|
||||
etaHEN_log("Failed to open destination file: %s", dst.c_str());
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
dest << source.rdbuf();
|
||||
source.close();
|
||||
dest.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Main function
|
||||
void generate_games_xml(std::string &xml_buffer, bool game_shortcut_activated)
|
||||
{
|
||||
struct dirent *entry;
|
||||
unlink("/data/etaHEN/games_list.xml");
|
||||
|
||||
std::vector<std::string> directories = {
|
||||
"/user/data/etaHEN/games",
|
||||
"/mnt/usb0/etaHEN/games",
|
||||
"/mnt/usb1/etaHEN/games",
|
||||
"/mnt/usb2/etaHEN/games",
|
||||
"/mnt/usb3/etaHEN/games",
|
||||
"/mnt/ext1/etaHEN/games",
|
||||
"/mnt/ext2/etaHEN/games",
|
||||
"/mnt/ext0/etaHEN/games",
|
||||
};
|
||||
|
||||
std::string list_id = game_shortcut_activated ? "id_debug_settings" : "id_ps5_backups";
|
||||
|
||||
xml_buffer = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
|
||||
"<system_settings version=\"1.0\" plugin=\"debug_settings_plugin\">\n"
|
||||
"\n";
|
||||
|
||||
xml_buffer += "<setting_list id=\"" + list_id + "\" title=\"(Beta) PS5 webMAN Games\">\n";
|
||||
|
||||
// Initialize random number generator
|
||||
std::random_device rd;
|
||||
std::mt19937 gen(rd());
|
||||
std::uniform_int_distribution<int> dist(1000, 9999);
|
||||
|
||||
// Create cache directory
|
||||
mkdir("/data/etaHEN/cache", 0777);
|
||||
|
||||
for (const auto &directory : directories)
|
||||
{
|
||||
DIR *dir = opendir(directory.c_str());
|
||||
if (!dir)
|
||||
{
|
||||
#if SHELL_DEBUG==1
|
||||
etaHEN_log("Failed to open directory: %s error %s", directory.c_str(), strerror(errno));
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
while ((entry = readdir(dir)) != nullptr)
|
||||
{
|
||||
// Skip . and .. directories
|
||||
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
|
||||
continue;
|
||||
|
||||
std::string game_dir = directory + "/" + entry->d_name;
|
||||
|
||||
// Check if this is a directory
|
||||
struct stat st;
|
||||
if (stat(game_dir.c_str(), &st) != 0 || !S_ISDIR(st.st_mode)) {
|
||||
#if SHELL_DEBUG==1
|
||||
etaHEN_log("Skipping non-directory: %s", game_dir.c_str());
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string param_path = game_dir + "/sce_sys/param.json";
|
||||
std::string icon_path = game_dir + "/sce_sys/icon0.png";
|
||||
|
||||
// Check if param.json exists
|
||||
if (access(param_path.c_str(), F_OK) != 0) {
|
||||
#if SHELL_DEBUG==1
|
||||
etaHEN_log("No param.json found in: %s", game_dir.c_str());
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
#if SHELL_DEBUG==1
|
||||
etaHEN_log("Found Game: %s", game_dir.c_str());
|
||||
#endif
|
||||
|
||||
// Parse JSON to get title_id, content_id, title, and version
|
||||
std::string title_id, title, ver;
|
||||
if (!getContentInfofromJson(param_path, title_id, title, ver)) {
|
||||
#if SHELL_DEBUG==1
|
||||
etaHEN_log("Failed to parse param.json in: %s", game_dir.c_str());
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string shown_path = game_dir;
|
||||
|
||||
const std::string prefix = "/user";
|
||||
if (shown_path.find(prefix) == 0) {
|
||||
shown_path = shown_path.substr(prefix.length());
|
||||
}
|
||||
|
||||
shown_path = (game_dir.substr(0, 4) == "/usb") ? "/mnt" + game_dir : shown_path;
|
||||
|
||||
// Generate a random number for the ID
|
||||
int random_num = dist(gen);
|
||||
|
||||
// Handle icon path and caching
|
||||
if (isExternalStorage(game_dir)) {
|
||||
// Cache icon from external storage
|
||||
// not /data but /user/data for shellui as it's not accessible from /data
|
||||
std::string cached_icon_path = "/user/data/etaHEN/cache/" + title_id + ".png";
|
||||
|
||||
// Copy icon if it doesn't exist
|
||||
if (access(cached_icon_path.c_str(), F_OK) != 0) {
|
||||
if (!copyFile(icon_path, cached_icon_path)) {
|
||||
#if SHELL_DEBUG==1
|
||||
etaHEN_log("Failed to cache icon from: %s", icon_path.c_str());
|
||||
#endif
|
||||
cached_icon_path = icon_path; // Fallback to original
|
||||
} else {
|
||||
#if SHELL_DEBUG==1
|
||||
etaHEN_log("Cached icon: %s", cached_icon_path.c_str());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
icon_path = cached_icon_path;
|
||||
} else if (icon_path.find("/mnt/usb") == 0) {
|
||||
// Transform /mnt/usb... to /usb...
|
||||
icon_path = icon_path.substr(4); // Remove "/mnt"
|
||||
}
|
||||
|
||||
|
||||
// Escape paths for XML
|
||||
escapePath(icon_path);
|
||||
escapeXML(title);
|
||||
escapeXML(shown_path);
|
||||
|
||||
// Create and populate a GameEntry
|
||||
GameEntry game;
|
||||
game.tid = title_id;
|
||||
game.title = title;
|
||||
game.version = ver;
|
||||
game.path = shown_path;
|
||||
game.dir_name = entry->d_name;
|
||||
game.icon_path = icon_path;
|
||||
game.id = "id_etahen_game_loader_" + title_id + "_" + std::to_string(random_num);
|
||||
|
||||
// Add to the games list
|
||||
games_list.push_back(game);
|
||||
|
||||
// Format the button XML
|
||||
std::string button = "<button id=\"" + game.id + "\" title=\"(" + title_id + ") " + title +
|
||||
"\" icon=\"" + icon_path + "\" second_title=\"" + shown_path + " | Version: " + ver + "\"/>\n";
|
||||
|
||||
xml_buffer += button;
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
}
|
||||
|
||||
xml_buffer += "</setting_list>\n</system_settings>";
|
||||
}
|
||||
|
||||
#define IOVEC_ENTRY(x) {x ? (char *)x : 0, x ? strlen(x) + 1 : 0}
|
||||
#define IOVEC_SIZE(x) (sizeof(x) / sizeof(struct iovec))
|
||||
|
||||
int mount_nullfs(const char *src, const char *dst)
|
||||
{
|
||||
struct iovec iov[] = {
|
||||
IOVEC_ENTRY("fstype"),
|
||||
IOVEC_ENTRY("nullfs"),
|
||||
IOVEC_ENTRY("from"),
|
||||
IOVEC_ENTRY(src),
|
||||
IOVEC_ENTRY("fspath"),
|
||||
IOVEC_ENTRY(dst),
|
||||
};
|
||||
|
||||
return nmount(iov, IOVEC_SIZE(iov), 0);
|
||||
}
|
||||
|
||||
int endswith(const char *string, const char *suffix)
|
||||
{
|
||||
size_t suffix_len = strlen(suffix);
|
||||
size_t string_len = strlen(string);
|
||||
|
||||
if (string_len < suffix_len)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return strncmp(string + string_len - suffix_len, suffix, suffix_len) != 0;
|
||||
}
|
||||
|
||||
int chmod_bins(const char *path)
|
||||
{
|
||||
char buf[PATH_MAX + 1];
|
||||
struct dirent *entry;
|
||||
struct stat st;
|
||||
DIR *dir;
|
||||
|
||||
if (stat(path, &st) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (endswith(path, ".prx") || endswith(path, ".sprx") || endswith(path, "/eboot.bin"))
|
||||
{
|
||||
chmod(path, 0755);
|
||||
}
|
||||
|
||||
if (S_ISDIR(st.st_mode))
|
||||
{
|
||||
dir = opendir(path);
|
||||
while (1)
|
||||
{
|
||||
entry = readdir(dir);
|
||||
if (entry == nullptr)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, ".."))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
sprintf(buf, "%s/%s", path, entry->d_name);
|
||||
chmod_bins(buf);
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Launch_FG_Game(const char *path, const char* title_id, const char* title){
|
||||
app_launch_ctx_t ctx = {0};
|
||||
char dst[PATH_MAX + 1];
|
||||
|
||||
strcpy(dst, "/system_ex/app/");
|
||||
strcat(dst, title_id);
|
||||
mkdir(dst, 0777);
|
||||
|
||||
sceUserServiceInitialize(0);
|
||||
sceUserServiceGetForegroundUser(&ctx.user_id);
|
||||
mount_nullfs(path, dst);
|
||||
chmod_bins(path);
|
||||
|
||||
char *argv[] = {(char*)title, nullptr};
|
||||
|
||||
return sceSystemServiceLaunchApp(title_id, &argv[0], &ctx);
|
||||
}
|
||||
|
||||
|
||||
bool Launch_Game_By_ID(const char* button_id){
|
||||
if (games_list.empty()){
|
||||
return false;
|
||||
}
|
||||
for (auto game : games_list) {
|
||||
if (game.id == button_id) {
|
||||
|
||||
etaHEN_log("[Clicked %s] TID: %s title: %s version: %s path: %s", game.id.c_str(), game.tid.c_str(), game.title.c_str(), game.version.c_str(), game.path.c_str());
|
||||
|
||||
notify(true, "Launching %s (%s)\nPath: %s", game.title.c_str(), game.tid.c_str(), game.path.c_str());
|
||||
//const char *path, const char* title_id, const char* title
|
||||
int res = Launch_FG_Game(game.path.c_str(), game.tid.c_str(), game.title.c_str());
|
||||
if (res < 0 && res != SCE_LNC_UTIL_ERROR_ALREADY_RUNNING_KILL_NEEDED && res != SCE_LNC_UTIL_ERROR_ALREADY_RUNNING && res != SCE_LNC_UTIL_ERROR_ALREADY_RUNNING_SUSPEND_NEEDED) {
|
||||
notify(true, "Failed to launch %s (%s)\nError: 0x%X", game.title.c_str(), game.tid.c_str(), res);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -34,7 +34,8 @@ along with this program; see the file COPYING. If not, see
|
||||
#define MAX_CONCURRENT_REQUEST (4)
|
||||
#define PRIVATE_CA_CERT_NUM (0)
|
||||
#define COMMIT_HASH_FILE "/data/etaHEN/cheat_commit_hash.txt"
|
||||
#define GITHUB_API_URL "https://api.github.com/repos/etaHEN/PS5_Cheats/commits"
|
||||
#define ETAHEN_GITHUB_API_URL "https://api.github.com/repos/etaHEN/PS5_Cheats/commits"
|
||||
#define GOLDHEN_GITHUB_API_URL "https://api.github.com/repos/GoldHEN/GoldHEN_Cheat_Repository/commits"
|
||||
|
||||
uint64_t sceKernelGetProcessTime(void);
|
||||
|
||||
@@ -94,12 +95,12 @@ static int progress_callback(void* clientp, curl_off_t dltotal, curl_off_t dlnow
|
||||
int percent = (int)(((float)dlnow / dltotal) * 100);
|
||||
|
||||
snprintf(notifyMsg, sizeof(notifyMsg),
|
||||
"Downloading the cheats repo:..\n%.1f/%.1f MB (%d%%)",
|
||||
"Downloading..\n%.1f/%.1f MB (%d%%)",
|
||||
dlnow_mb, dltotal_mb, percent);
|
||||
}
|
||||
else {
|
||||
snprintf(notifyMsg, sizeof(notifyMsg),
|
||||
"Downloading the cheats repo...\n%.1f MB Downloaded",
|
||||
"Downloading...\n%.1f MB Downloaded",
|
||||
dlnow_mb);
|
||||
}
|
||||
|
||||
@@ -237,11 +238,13 @@ static char* download_json(const char* url) {
|
||||
|
||||
// Initialize JSON data structure
|
||||
struct json_data json = {
|
||||
.data = malloc(1024),
|
||||
.data = malloc(0x1000),
|
||||
.size = 0,
|
||||
.capacity = 1024
|
||||
.capacity = 0x1000
|
||||
};
|
||||
|
||||
etaHEN_log("Downloading JSON data from %s", url);
|
||||
|
||||
if (!json.data) {
|
||||
etaHEN_log("Failed to allocate initial memory for JSON data");
|
||||
return NULL;
|
||||
@@ -556,7 +559,7 @@ static bool write_commit_hash(const char* hash) {
|
||||
}
|
||||
|
||||
// Main function to check for new commits
|
||||
bool check_for_new_commit() {
|
||||
bool check_for_new_commit(int repo) {
|
||||
char* json_data = NULL;
|
||||
char latest_commit[64] = {0};
|
||||
char stored_commit[64] = {0};
|
||||
@@ -566,7 +569,7 @@ bool check_for_new_commit() {
|
||||
notify(true, "Checking for updates to the cheats repo...");
|
||||
|
||||
// Download the latest commit information
|
||||
json_data = download_json(GITHUB_API_URL);
|
||||
json_data = download_json(repo ? GOLDHEN_GITHUB_API_URL : ETAHEN_GITHUB_API_URL);
|
||||
if (!json_data) {
|
||||
etaHEN_log("Failed to download commit information from GitHub API");
|
||||
notify(true, "Failed to check the cheats repo for updates\nCheck your Connection and try again");
|
||||
|
||||
@@ -25,7 +25,7 @@ extern "C" {
|
||||
#include <sys/mount.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
int sceKernelMprotect(void *addr, size_t len, int prot);
|
||||
pid_t elfldr_spawn(const char* cwd, int stdio, uint8_t* elf, const char* name);
|
||||
@@ -48,7 +48,8 @@ extern bool is_handler_enabled;
|
||||
|
||||
extern pthread_t cmd_server;
|
||||
void* runCommandNControlServer(void*);
|
||||
|
||||
void generate_games_xml(std::string &xml_buffer, bool game_shortcut_activated);
|
||||
bool Launch_Game_By_ID(const char* button_id);
|
||||
// pop -Winfinite-recursion error for this func for clang
|
||||
#define MB(x) ((size_t)(x) << 20)
|
||||
#define READ_SIZE 0x1024
|
||||
@@ -542,13 +543,16 @@ void handleIPC(struct clientArgs *client, std::string &inputStr,
|
||||
break;
|
||||
}
|
||||
case BREW_UTIL_DOWNLOAD_CHEATS: {
|
||||
if(!check_for_new_commit()){
|
||||
json_t const *target_repo_property = json_getProperty(my_json, "repo");
|
||||
int repo = json_getInteger(target_repo_property);
|
||||
|
||||
if(!check_for_new_commit(repo)){
|
||||
etaHEN_log("Failed to check for new commit or is up to date");
|
||||
reply(sender_app, false);
|
||||
break;
|
||||
}
|
||||
notify(true, "Downloading the latest etaHEN Cheats repo....");
|
||||
if (!download_file("https://api.github.com/repos/etaHEN/PS5_Cheats/zipball",
|
||||
notify(true, "Downloading the latest %s Cheats repo....", repo ? "GoldHEN PS4" : "etaHEN PS5");
|
||||
if (!download_file(repo ? "https://api.github.com/repos/GoldHEN/GoldHEN_Cheat_Repository/zipball" : "https://api.github.com/repos/etaHEN/PS5_Cheats/zipball",
|
||||
"/data/etaHEN/cheats.zip")) {
|
||||
etaHEN_log("Failed to download cheats");
|
||||
reply(sender_app, true);
|
||||
@@ -603,6 +607,46 @@ void handleIPC(struct clientArgs *client, std::string &inputStr,
|
||||
reply(sender_app, false);
|
||||
break;
|
||||
}
|
||||
case BREW_UTIL_GET_GAMES_LIST:{
|
||||
bool cheats_activated_shortcut = json_getInteger(json_getProperty(my_json, "shortcut"));
|
||||
std::string games_list;
|
||||
generate_games_xml(games_list, cheats_activated_shortcut);
|
||||
|
||||
std::string shm_path = "/user/data/etaHEN/games_list.xml";
|
||||
//make file
|
||||
int fd = open(shm_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0777);
|
||||
if (fd >= 0) {
|
||||
// Write the buffer to the file
|
||||
if (write(fd, games_list.c_str(), games_list.length()) == -1) {
|
||||
perror("write failed");
|
||||
close(fd);
|
||||
reply(sender_app, true);
|
||||
break;
|
||||
}
|
||||
// Close the file descriptor
|
||||
close(fd);
|
||||
reply(sender_app, false, shm_path);
|
||||
break;
|
||||
} else {
|
||||
notify(true, "Failed to create shared file for games list!");
|
||||
// generate_default_games_xml(games_list, cheats_activated_shortcut);
|
||||
reply(sender_app, true);
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case BREW_UTIL_LAUNCH_GAME_BY_BUTTON_ID:{
|
||||
std::string button_id = std::string(json_getPropertyValue(my_json, "button_id"));
|
||||
etaHEN_log("Launching game with button id: %s", button_id.c_str());
|
||||
int res = Launch_Game_By_ID(button_id.c_str());
|
||||
if (res < 0) {
|
||||
reply(sender_app, true);
|
||||
break;
|
||||
}
|
||||
reply(sender_app, false);
|
||||
break;
|
||||
}
|
||||
case BREW_KILL_DAEMON:{
|
||||
is_handler_enabled = false;
|
||||
exit(1337);
|
||||
|
||||
BIN
etaHEN-2.5B.bin
Normal file
BIN
etaHEN-2.5B.bin
Normal file
Binary file not shown.
Reference in New Issue
Block a user