#include #include #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("无法设置系统核心 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; }