mirror of
https://gitlab.com/Theopse/fbi-i18n-zh.git
synced 2025-04-05 19:41:43 +08:00
189 lines
4.1 KiB
C
189 lines
4.1 KiB
C
#include <sys/iosupport.h>
|
|
#include <malloc.h>
|
|
|
|
#include <3ds.h>
|
|
|
|
#include "../core/clipboard.h"
|
|
#include "../core/error.h"
|
|
#include "../core/fs.h"
|
|
#include "../core/screen.h"
|
|
#include "../core/task/task.h"
|
|
#include "../core/ui/ui.h"
|
|
#include "section.h"
|
|
#include "task/uitask.h"
|
|
|
|
#define CURRENT_KPROCESS (*(void**) 0xFFFF9004)
|
|
|
|
#define KPROCESS_PID_OFFSET_OLD (0xB4)
|
|
#define KPROCESS_PID_OFFSET_NEW (0xBC)
|
|
|
|
static bool backdoor_ran = false;
|
|
static bool n3ds = false;
|
|
static u32 old_pid = 0;
|
|
|
|
#pragma GCC diagnostic push
|
|
#pragma GCC diagnostic ignored "-Wreturn-type"
|
|
static __attribute__((naked)) Result svcGlobalBackdoor(s32 (*callback)()) {
|
|
asm volatile(
|
|
"svc 0x30\n"
|
|
"bx lr"
|
|
);
|
|
}
|
|
#pragma GCC diagnostic pop
|
|
|
|
static s32 patch_pid_kernel() {
|
|
u32 *pidPtr = (u32*) (CURRENT_KPROCESS + (n3ds ? KPROCESS_PID_OFFSET_NEW : KPROCESS_PID_OFFSET_OLD));
|
|
|
|
old_pid = *pidPtr;
|
|
*pidPtr = 0;
|
|
|
|
backdoor_ran = true;
|
|
return 0;
|
|
}
|
|
|
|
static s32 restore_pid_kernel() {
|
|
u32 *pidPtr = (u32*) (CURRENT_KPROCESS + (n3ds ? KPROCESS_PID_OFFSET_NEW : KPROCESS_PID_OFFSET_OLD));
|
|
|
|
*pidPtr = old_pid;
|
|
|
|
backdoor_ran = true;
|
|
return 0;
|
|
}
|
|
|
|
static bool attempt_patch_pid() {
|
|
backdoor_ran = false;
|
|
APT_CheckNew3DS(&n3ds);
|
|
|
|
svcGlobalBackdoor(patch_pid_kernel);
|
|
srvExit();
|
|
srvInit();
|
|
svcGlobalBackdoor(restore_pid_kernel);
|
|
|
|
return backdoor_ran;
|
|
}
|
|
|
|
static void (*exit_funcs[16])()= {NULL};
|
|
static u32 exit_func_count = 0;
|
|
|
|
static void* soc_buffer = NULL;
|
|
|
|
void cleanup_services() {
|
|
for(u32 i = 0; i < exit_func_count; i++) {
|
|
if(exit_funcs[i] != NULL) {
|
|
exit_funcs[i]();
|
|
exit_funcs[i] = NULL;
|
|
}
|
|
}
|
|
|
|
exit_func_count = 0;
|
|
|
|
if(soc_buffer != NULL) {
|
|
free(soc_buffer);
|
|
soc_buffer = NULL;
|
|
}
|
|
}
|
|
|
|
#define INIT_SERVICE(initStatement, exitFunc) (R_SUCCEEDED(res = (initStatement)) && (exit_funcs[exit_func_count++] = (exitFunc)))
|
|
|
|
Result init_services() {
|
|
Result res = 0;
|
|
|
|
soc_buffer = memalign(0x1000, 0x100000);
|
|
if(soc_buffer != NULL) {
|
|
Handle tempAM = 0;
|
|
if(R_SUCCEEDED(res = srvGetServiceHandle(&tempAM, "am:net"))) {
|
|
svcCloseHandle(tempAM);
|
|
|
|
if(INIT_SERVICE(amInit(), amExit)
|
|
&& INIT_SERVICE(cfguInit(), cfguExit)
|
|
&& INIT_SERVICE(acInit(), acExit)
|
|
&& INIT_SERVICE(ptmuInit(), ptmuExit)
|
|
&& INIT_SERVICE(pxiDevInit(), pxiDevExit)
|
|
&& INIT_SERVICE(httpcInit(0), httpcExit)
|
|
&& INIT_SERVICE(socInit(soc_buffer, 0x100000), (void (*)()) socExit));
|
|
}
|
|
} else {
|
|
res = R_APP_OUT_OF_MEMORY;
|
|
}
|
|
|
|
if(R_FAILED(res)) {
|
|
cleanup_services();
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static u32 old_time_limit = UINT32_MAX;
|
|
|
|
void init() {
|
|
gfxInitDefault();
|
|
|
|
Result romfsRes = romfsInit();
|
|
if(R_FAILED(romfsRes)) {
|
|
error_panic("無法掛載 RomFS: %08lX", romfsRes);
|
|
return;
|
|
}
|
|
|
|
if(R_FAILED(init_services())) {
|
|
if(!attempt_patch_pid()) {
|
|
error_panic("無法操控內核\n請確認已獲得內核權限");
|
|
return;
|
|
}
|
|
|
|
Result initRes = init_services();
|
|
if(R_FAILED(initRes)) {
|
|
error_panic("無法初始化服務: %08lX", initRes);
|
|
return;
|
|
}
|
|
}
|
|
|
|
osSetSpeedupEnable(true);
|
|
|
|
APT_GetAppCpuTimeLimit(&old_time_limit);
|
|
Result cpuRes = APT_SetAppCpuTimeLimit(30);
|
|
if(R_FAILED(cpuRes)) {
|
|
error_panic("無法設置 Syscore CPU 時間限制: %08lX", cpuRes);
|
|
return;
|
|
}
|
|
|
|
AM_InitializeExternalTitleDatabase(false);
|
|
|
|
screen_init();
|
|
ui_init();
|
|
task_init();
|
|
}
|
|
|
|
void cleanup() {
|
|
clipboard_clear();
|
|
|
|
task_exit();
|
|
ui_exit();
|
|
screen_exit();
|
|
|
|
if(old_time_limit != UINT32_MAX) {
|
|
APT_SetAppCpuTimeLimit(old_time_limit);
|
|
}
|
|
|
|
osSetSpeedupEnable(false);
|
|
|
|
cleanup_services();
|
|
|
|
romfsExit();
|
|
|
|
gfxExit();
|
|
}
|
|
|
|
int main(int argc, const char* argv[]) {
|
|
if(argc > 0 && envIsHomebrew()) {
|
|
fs_set_3dsx_path(argv[0]);
|
|
}
|
|
|
|
init();
|
|
|
|
mainmenu_open();
|
|
while(aptMainLoop() && ui_update());
|
|
|
|
cleanup();
|
|
|
|
return 0;
|
|
} |