diff --git a/installer/Makefile b/installer/Makefile index 189aeb4..2e21400 100644 --- a/installer/Makefile +++ b/installer/Makefile @@ -15,6 +15,7 @@ TOOLCHAIN ?= $(OO_PS4_TOOLCHAIN) ifeq ($(TOOLCHAIN),) TOOLCHAIN := /Users/mac/PS4Toolchain/OpenOrbis/PS4Toolchain endif +export OO_PS4_TOOLCHAIN := $(TOOLCHAIN) PROJDIR := installer COMMONDIR := $(TOOLCHAIN)/samples/_common INTDIR := $(PROJDIR)/x64/Debug @@ -48,8 +49,8 @@ installer/sce_sys/param.sfo: installer/Makefile $(TOOLCHAIN)/bin/$(CDIR)/PkgTool.Core sfo_new $@ $(TOOLCHAIN)/bin/$(CDIR)/PkgTool.Core sfo_setentry $@ APP_TYPE --type Integer --maxsize 4 --value 1 $(TOOLCHAIN)/bin/$(CDIR)/PkgTool.Core sfo_setentry $@ APP_VER --type Utf8 --maxsize 8 --value '$(VERSION)' - $(TOOLCHAIN)/bin/$(CDIR)/PkgTool.Core sfo_setentry $@ ATTRIBUTE --type Integer --maxsize 4 --value 0 - $(TOOLCHAIN)/bin/$(CDIR)/PkgTool.Core sfo_setentry $@ CATEGORY --type Utf8 --maxsize 4 --value 'gd' + $(TOOLCHAIN)/bin/$(CDIR)/PkgTool.Core sfo_setentry $@ ATTRIBUTE --type Integer --maxsize 4 --value 32 + $(TOOLCHAIN)/bin/$(CDIR)/PkgTool.Core sfo_setentry $@ CATEGORY --type Utf8 --maxsize 4 --value 'gde' $(TOOLCHAIN)/bin/$(CDIR)/PkgTool.Core sfo_setentry $@ CONTENT_ID --type Utf8 --maxsize 48 --value '$(CONTENT_ID)' $(TOOLCHAIN)/bin/$(CDIR)/PkgTool.Core sfo_setentry $@ DOWNLOAD_DATA_SIZE --type Integer --maxsize 4 --value 0 $(TOOLCHAIN)/bin/$(CDIR)/PkgTool.Core sfo_setentry $@ SYSTEM_VER --type Integer --maxsize 4 --value 0 @@ -59,7 +60,7 @@ installer/sce_sys/param.sfo: installer/Makefile installer/eboot.bin: $(OBJS) $(LD) $(INTDIR)/*.o -o $(INTDIR)/$(PROJDIR).elf $(LDFLAGS) - $(TOOLCHAIN)/bin/$(CDIR)/create-fself-macos -in=$(INTDIR)/$(PROJDIR).elf -out=$(INTDIR)/$(PROJDIR).oelf --eboot "installer/eboot.bin" --paid 0x3800000000000011 + $(TOOLCHAIN)/bin/$(CDIR)/create-fself-macos -in=$(INTDIR)/$(PROJDIR).elf -out=$(INTDIR)/$(PROJDIR).oelf --eboot "installer/eboot.bin" --paid 0x3800000000000011 --authinfo 000000000000000000000000001C004000FF000000000080000000000000000000000000000000000000008000400040000000000000008000000000000000080040FFFF000000F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 $(INTDIR)/%.o: $(PROJDIR)/%.c $(CC) $(CFLAGS) -o $@ $< diff --git a/installer/sce_sys/param.sfo b/installer/sce_sys/param.sfo index aca6e5a..c799805 100644 Binary files a/installer/sce_sys/param.sfo and b/installer/sce_sys/param.sfo differ diff --git a/orbisrpc/detect.c b/orbisrpc/detect.c index bbf874a..580b70d 100644 --- a/orbisrpc/detect.c +++ b/orbisrpc/detect.c @@ -52,43 +52,8 @@ static int is_title_prefix(const char *n); * A launched game shows up as an "eboot.bin" process; its identity comes * from the freshest savedata dir (gameplay writes saves continuously). * Both facts verified live via probes before wiring them in. */ -/* Count eboot.bin processes. A change means launch/close: callers drop - * stale state immediately instead of waiting out debounce windows. */ -int detect_eboot_count(void){ - int mib[4] = { 1, 14, 8, 0 }; - size_t sz = 0; - int n = 0; - if(sysctl(mib, 4, NULL, &sz, NULL, 0) != 0) return -1; - static unsigned char buf[256*1024]; - if(sz > sizeof buf) return -1; - if(sysctl(mib, 4, buf, &sz, NULL, 0) != 0) return -1; - size_t off = 0; - while(off + 4 <= sz){ - int recsz = *(int *)(buf + off); - if(recsz <= 0 || off + (size_t)recsz > sz) break; - if(recsz >= 479 && !memcmp(buf + off + 447, "eboot.bin", 10)) - n++; - off += (size_t)recsz; - } - return n; -} -static int proc_has_eboot(void){ - int mib[4] = { 1, 14, 8, 0 }; - size_t sz = 0; - if(sysctl(mib, 4, NULL, &sz, NULL, 0) != 0) return -1; - static unsigned char buf[256*1024]; - if(sz > sizeof buf) return -1; - if(sysctl(mib, 4, buf, &sz, NULL, 0) != 0) return -1; - size_t off = 0; - while(off + 4 <= sz){ - int recsz = *(int *)(buf + off); - if(recsz <= 0 || off + (size_t)recsz > sz) return -1; - if(recsz >= 479 && !memcmp(buf + off + 447, "eboot.bin", 10)) - return 1; - off += (size_t)recsz; - } - return 0; -} +/* Count eboot.bin processes etc. live below (shared sysctl fallback, + * outside the SDK-only ifdef so both builds probe identically). */ /* Sandbox mounts: /mnt/sandbox/_000 exists exactly while that * title's game process lives. This is authoritative foreground identity @@ -240,6 +205,52 @@ static long scan_newest_save(char *out, size_t cap){ static const char *users } #endif +/* --- shared sysctl fallback (payload-SDK builds only) ------------------ */ +/* OpenOrbis SDK ships no <sys/sysctl.h>, so this probe lives in SDK builds; + * OpenOrbis builds fall back to the UserService foreground user instead. + * Both builds probe ShellCoreUtil first (see detect_foreground_active). */ +#ifdef ORBISRPC_SDK_PAYLOAD + +/* Count eboot.bin processes. A change means launch/close: callers drop + * stale state immediately instead of waiting out debounce windows. */ +int detect_eboot_count(void){ + int mib[4] = { 1, 14, 8, 0 }; + size_t sz = 0; + int n = 0; + if(sysctl(mib, 4, NULL, &sz, NULL, 0) != 0) return -1; + static unsigned char buf[256*1024]; + if(sz > sizeof buf) return -1; + if(sysctl(mib, 4, buf, &sz, NULL, 0) != 0) return -1; + size_t off = 0; + while(off + 4 <= sz){ + int recsz = *(int *)(buf + off); + if(recsz <= 0 || off + (size_t)recsz > sz) break; + if(recsz >= 479 && !memcmp(buf + off + 447, "eboot.bin", 10)) + n++; + off += (size_t)recsz; + } + return n; +} +static int proc_has_eboot(void){ + int mib[4] = { 1, 14, 8, 0 }; + size_t sz = 0; + if(sysctl(mib, 4, NULL, &sz, NULL, 0) != 0) return -1; + static unsigned char buf[256*1024]; + if(sz > sizeof buf) return -1; + if(sysctl(mib, 4, buf, &sz, NULL, 0) != 0) return -1; + size_t off = 0; + while(off + 4 <= sz){ + int recsz = *(int *)(buf + off); + if(recsz <= 0 || off + (size_t)recsz > sz) return -1; + if(recsz >= 479 && !memcmp(buf + off + 447, "eboot.bin", 10)) + return 1; + off += (size_t)recsz; + } + return 0; +} + +#endif /* ORBISRPC_SDK_PAYLOAD (sysctl fallback) */ + static int s_user_inited = 0; static int s_user_ok = 0; static int user_init(void){ @@ -273,7 +284,7 @@ static int scu_init(void){ if(s_scu_tried) return s_is_app_launched != NULL; s_scu_tried = 1; void *h = dlopen("libSceShellCoreUtil.sprx", 0); - if(!h){ log_msg("ShellCoreUtil unavailable (dlopen fail); using foreground-user fallback"); return 0; } + if(!h){ log_msg("ShellCoreUtil unavailable (dlopen fail); using sysctl eboot scan"); return 0; } s_is_app_launched = (shellcore_isapplaunched_fn)(uintptr_t)dlsym(h, "sceShellCoreUtilIsAppLaunched"); log_msg("ShellCoreUtil IsAppLaunched %s", s_is_app_launched ? "resolved" : "unavailable (dlsym fail)"); return s_is_app_launched != NULL; @@ -281,24 +292,20 @@ static int scu_init(void){ /* --- foreground-active: the core "a game is running" signal ---------- */ int detect_foreground_active(void){ + /* ShellCoreUtil dlopen works on all firmwares (libkernel exports + * dlopen/dlsym directly). Firmware-independent — preferred over the + * fragile sysctl kinfo_proc scan which assumes a hardcoded process-table + * layout (offset 447, recsz>=479) that differs across PS4 firmware versions. */ + if(scu_init() && s_is_app_launched){ + return s_is_app_launched() ? 1 : 0; /* 0 when sitting on the home screen */ + } + /* Fallback depends on toolchain capability: SDK builds scan the + * process table; OpenOrbis builds ask UserService for the + * foreground user. Both fail closed (inactive) on error. */ #ifdef ORBISRPC_SDK_PAYLOAD - /* Spawned processes see no ShellCoreUtil/UserService; the eboot.bin - * process itself is the signal (system has no other eboot). */ return proc_has_eboot(); #else - if(scu_init() && s_is_app_launched){ - int on = s_is_app_launched(); - return (on != 0) ? 1 : 0; /* 0 when sitting on the home screen */ - } -#endif - /* fallback: foreground user exists. If UserService itself failed, - * report inactive instead of guessing "playing". */ if(user_init() != 0) return 0; -#ifdef ORBISRPC_SDK_PAYLOAD - /* No UserService API in SDK builds (user_init always fails there, - * so this is unreachable); fail closed regardless. */ - return 0; -#else int32_t fg = -1; int32_t rc = sceUserServiceGetForegroundUser(&fg); if(rc != 0){ log_msg("GetForegroundUser err %d", rc); return 0; } diff --git a/scripts/build.sh b/scripts/build.sh index cfa3a67..ee6fb9b 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -61,7 +61,7 @@ echo "ELF -> $OUT/orbisrpc.elf ($(stat -f%z "$OUT/orbisrpc.elf" 2>/dev/null || s MODE="${1:-all}" if [ "$MODE" = "fself" ] || [ "$MODE" = "all" ]; then "$SDK/bin/macos/create-fself-macos" -in="$OUT/orbisrpc.elf" \ - -out="$OUT/orbisrpc.fself" --eboot "$OUT/orbisrpc-eboot.bin" --paid 0x3800000000000011 || fail "fself creation" + -out="$OUT/orbisrpc.fself" --eboot "$OUT/orbisrpc-eboot.bin" --paid 0x3800000000000011 --authinfo 000000000000000000000000001C004000FF000000000080000000000000000000000000000000000000008000400040000000000000008000000000000000080040FFFF000000F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 || fail "fself creation" echo "FSELF -> $OUT/orbisrpc.fself" echo " (GoldHEN payload to deploy is $OUT/orbisrpc.elf -> /data/GoldHEN/payloads/orbisrpc.bin)" fi