void hidExit() { if(!hidInitialised) return; // Unmap HID sharedmem and close handles. u8 val=0; int i; for(i=0; i<5; i++)svcCloseHandle(hidEvents[i]); svcUnmapMemoryBlock(hidMemHandle, (u32)hidSharedMem); svcCloseHandle(hidMemHandle); svcCloseHandle(hidHandle); APT_CheckNew3DS(NULL, &val); if(val) { irrstExit(); } if(hidSharedMem != NULL) { mappableFree((void*) hidSharedMem); hidSharedMem = NULL; } hidInitialised = false; }
/* fills exploit_data structure with information that is specific to 3DS model and firmware version returns: 0 on failure, 1 on success */ s32 get_exploit_data (struct exploit_data *data) { u32 fversion = 0; u8 isN3DS = 0; s32 i; s32 result = 0; u32 sysmodel = SYS_MODEL_NONE; if(!data) return result; fversion = osGetFirmVersion(); APT_CheckNew3DS(&isN3DS); sysmodel = isN3DS ? SYS_MODEL_NEW_3DS : SYS_MODEL_OLD_3DS; /* copy platform and firmware dependent data */ for(i=0; i < sizeof(supported_systems) / sizeof(supported_systems[0]); i++) { if (supported_systems[i].firm_version == fversion && supported_systems[i].sys_model & sysmodel) { memcpy(data, &supported_systems[i], sizeof(struct exploit_data)); result = 1; break; } } return result; }
Result hidInit(void) { u8 val=0; Result ret=0; if (AtomicPostIncrement(&hidRefCount)) return 0; // Request service. ret = srvGetServiceHandle(&hidHandle, "hid:USER"); if (R_FAILED(ret)) ret = srvGetServiceHandle(&hidHandle, "hid:SPVR"); if (R_FAILED(ret)) goto cleanup0; // Get sharedmem handle. if(R_FAILED(ret=HIDUSER_GetHandles(&hidMemHandle, &hidEvents[HIDEVENT_PAD0], &hidEvents[HIDEVENT_PAD1], &hidEvents[HIDEVENT_Accel], &hidEvents[HIDEVENT_Gyro], &hidEvents[HIDEVENT_DebugPad]))) goto cleanup1; // Map HID shared memory. hidSharedMem=(vu32*)mappableAlloc(0x2b0); if(!hidSharedMem) { ret = -1; goto cleanup1; } if(R_FAILED(ret=svcMapMemoryBlock(hidMemHandle, (u32)hidSharedMem, MEMPERM_READ, 0x10000000)))goto cleanup2; APT_CheckNew3DS(&val); if(val) { ret = irrstInit(); } // Reset internal state. kOld = kHeld = kDown = kUp = 0; return ret; cleanup2: svcCloseHandle(hidMemHandle); if(hidSharedMem != NULL) { mappableFree((void*) hidSharedMem); hidSharedMem = NULL; } cleanup1: svcCloseHandle(hidHandle); cleanup0: AtomicDecrement(&hidRefCount); return ret; }
int main (int argc, char **argv) { float time, oldtime; APT_CheckNew3DS(&isN3DS); if(isN3DS) osSetSpeedupEnable(true); gfxInit(GSP_RGB565_OES,GSP_RGB565_OES,false); gfxSetDoubleBuffering(GFX_TOP, false); gfxSetDoubleBuffering(GFX_BOTTOM, false); gfxSet3D(true); consoleInit(GFX_BOTTOM, NULL); #ifdef _3DS_CIA if(chdir("sdmc:/3ds/ctrQuake") != 0) Sys_Error("Could not find folder: sdmc:/3ds/ctrQuake"); #endif static quakeparms_t parms; parms.memsize = 24*1024*1024; parms.membase = malloc (parms.memsize); parms.basedir = "."; COM_InitArgv (argc, argv); parms.argc = com_argc; parms.argv = com_argv; Host_Init (&parms); Sys_Init(); oldtime = Sys_FloatTime() -0.1; while (aptMainLoop()) { time = Sys_FloatTime(); separation_distance = osGet3DSliderState(); Host_Frame (time - oldtime); oldtime = time; } gfxExit(); return 0; }
void patch_srv(void) { APT_CheckNew3DS(&is_n3ds); u32 pid1; svcGetProcessId(&pid1, 0xFFFF8001); // Set the current process id (PID) to 0 svcBackdoor(&patch_pid); u32 pid2; svcGetProcessId(&pid2, 0xFFFF8001); // Re-initialize srv connection. It will consider this the process with id 0 // so we will have access to any service srvExit(); srvInit(); // Once we tricked srv we can restore the real PID svcBackdoor(&restore_pid); u32 pid3; svcGetProcessId(&pid3, 0xFFFF8001); printf("%lu=%lu=%lu %lu=0 %s %s\n", pid1, pid_backup, pid3, pid2, patch_result, unpatch_result); }
void hidExit(void) { if (AtomicDecrement(&hidRefCount)) return; // Unmap HID sharedmem and close handles. u8 val=0; int i; for(i=0; i<5; i++)svcCloseHandle(hidEvents[i]); svcUnmapMemoryBlock(hidMemHandle, (u32)hidSharedMem); svcCloseHandle(hidMemHandle); svcCloseHandle(hidHandle); APT_CheckNew3DS(&val); if(val) { irrstExit(); } if(hidSharedMem != NULL) { mappableFree((void*) hidSharedMem); hidSharedMem = NULL; } }
void saveConstants() { u32 kversion = *(vu32*)0x1FF80000; // KERNEL_VERSION register u8 is_n3ds = 0; APT_CheckNew3DS(NULL, &is_n3ds); if(kversion < 0x022C0600) { kproc_size = 0x260; kproc_num = 0x2C; // TODO: Verify kproc_codeset_offset = 0xA8; kproc_pid_offset = 0xAC; } else if(!is_n3ds) { kproc_size = 0x268; kproc_num = 0x2C; // TODO: Verify kproc_codeset_offset = 0xB0; kproc_pid_offset = 0xB4; } else { kproc_size = 0x270; kproc_num = 0x2F; // TODO: Verify kproc_codeset_offset = 0xB8; kproc_pid_offset = 0xBC; } kernelBackdoor(scanKProcList); }
int main(int argc, char* argv[]) { gfxInitDefault(); //Initialize console on top screen. Using NULL as the second argument tells the console library to use the internal console structure as current one consoleInit(GFX_TOP, &topScreen); consoleInit(GFX_BOTTOM,&bottomScreen); consoleSelect(&topScreen); APT_CheckNew3DS(&consoletype); printf("Console type:%s\n",consoletype?"New3DS. Good job!":"Old3DS. This may be a bit slow."); // Main loop while (aptMainLoop()) { printf("Welcome to the adventure. Press A to continue, or any other key to exit.\n"); hidScanInput(); //hidKeysDown returns information about which buttons have been just pressed (and they weren't in the previous frame) u32 kDown = hidKeysDown(); //hidKeysHeld returns information about which buttons have are held down in this frame u32 kHeld = hidKeysHeld(); //hidKeysUp returns information about which buttons have been just released u32 kUp = hidKeysUp(); while (!kDown) {hidScanInput(); u32 kDown = hidKeysDown(); u32 kHeld = hidKeysHeld(); u32 kUp = hidKeysUp(); if (kDown || kHeld || kUp) printf("Down:%d Held:%d Up:%d", kDown, kHeld, kUp);} if (kDown & !KEY_A) break; else if (kDown) { notknow: rendscreen("\n\nYou are walking in a forest. You come to a part you don't know. You can go three ways. Do you go left, right, or straight? (Use the D-Pad to select) "); hidScanInput(); //hidKeysDown returns information about which buttons have been just pressed (and they weren't in the previous frame) kDown = hidKeysDown(); //hidKeysHeld returns information about which buttons have are held down in this frame kHeld = hidKeysHeld(); //hidKeysUp returns information about which buttons have been just released kUp = hidKeysUp(); while (!kDown) {hidScanInput(); u32 kDown = hidKeysDown(); u32 kHeld = hidKeysHeld(); u32 kUp = hidKeysUp();} if (kDown & KEY_LEFT) { if (ldone) { rendscreen("You've already gone here! (A)"); isButtonPressed('a'); move="0"; goto notknow; } else { rendscreen("You found a chest! Inside it was 5 bars of gold. (A to continue)"); if (input()) goto exit; gold +=5; rendscreen("It's at a dead end, however. You walk back."); if (input()) goto exit; move="0"; ldone=true; goto notknow; } } else if (kDown & KEY_RIGHT) { if (rdone) { rendscreen("You've already gone here!"); if (input()) goto exit; move="0"; } else { rendscreen("You walk into a trap and lose a life.(A to continue)"); if (input()) goto exit; lives+=-1; rendscreen("You walk back."); if (input()) goto exit; move="0"; rdone=true; } } else if (kDown & KEY_UP) continue; else if (kDown & KEY_START) goto exit; else goto notknow; rendscreen("You walk forward for a while.(A to continue)"); if (input()) goto exit; rendscreen("The ground begins to shake...(A to continue)"); if (input()) goto exit; cls(); print("Louder..."); usleep(1000); rendscreen("You come up to a monster!"); usleep(1000); rendscreen("'I will eat you!'"); usleep(1000); rendscreen("How to fight: Press A to kick and B to punch."); if (input()) goto exit; rendscreen("When it's your enemy's turn, hope for the best!"); if (input()) goto exit; rendscreen("Press A to start."); if (input()) goto exit; while (enemyh>0) { rendscreenf(); char fmove='0'; printf("Kick or punch? \n"); while (fmove != 'K' && fmove != 'P' && fmove != 'a') { if (isButtonPressed('a')) fmove = 'K'; else if (isButtonPressed('b')) fmove = 'P'; else if (isButtonPressed('e')) { if (isButtonPressed('l')) fmove = 'a'; } else if (isButtonPressed('t')) goto exit; } if (fmove=='K') { sub=floor(random()*10)+5; enemyh=enemyh-sub*10; printf("Damage dealt: %i\n",sub*10); if (input()) goto exit; } else if (fmove=='a') { enemyh=0; } else { sub=floor(random()*10); enemyh+=-sub*18; printf("Damage dealt: %i\n", sub*18); if (input()) goto exit; } rendscreenf(); usleep(200); if (enemyh>0) { health+=-floor(random()*100); health+=-60; printf("Monster attacks! Damage dealt: %i\n", sub+60); if (input()) goto exit; } } rendscreen("You won the battle!"); if (input()) goto exit; rendscreen("The monster had 20 gold and you gained two lives from defeating him!"); gold+=20; lives+=2; if (input()) goto exit; rendscreen("You continue along the path."); if (input()) goto exit; char berries = 'x'; // Entrypoint 2 =============== rendscreen("You find some berries. Do you eat them? (A/B) "); while (berries != 'y' && berries != 'n') { if (isButtonPressed('a')) berries = 'y'; else if (isButtonPressed('b')) berries = 'n'; else if (isButtonPressed('t')) goto exit; } if (berries=='y') { rendscreen("Under the leaves, you found a glove! It grants +50 health in all battles!"); ebhealth+=50; special.push_back("Glove"); if (input()) goto exit; rendscreen("After eating some berries, you continue walking."); } else { rendscreen("You continue walking."); } if (input()) goto exit; char river='0'; rendscreen("After walking for quite some time, you come to a river. There's a bear right behind you. Do you try to cross the river? (A/B) "); while (river!='y' && river!='n') { if (isButtonPressed('a')) river = 'y'; else if (isButtonPressed('b')) river = 'n'; else if (isButtonPressed('t')) goto exit; } if (river=='y') { rendscreen("You manage to cross the river, but you get sick and lose a life."); lives+=-1; } else { rendscreen("You stay and fight the bear!"); if (input()) goto exit; health=1000+ebhealth; enemyh=400; while (enemyh>0) { rendscreenf(); char fmove='0'; printf("Kick or punch? \n"); while (fmove!='k' && fmove!='p' && fmove!='a') { if (isButtonPressed('a')) fmove = 'k'; else if (isButtonPressed('b')) fmove = 'p'; else if (isButtonPressed('e')) {if (isButtonPressed('l')) fmove = 'a';} else if (kDown & KEY_START) goto exit; } if (fmove=='k') { sub=floor(random()*10)+6; enemyh=enemyh-sub*10; printf("Damage dealt: %i\n", sub*10); if (input()) goto exit; } else if (fmove=='a') enemyh=0; else { sub=floor(random()*10); enemyh+=-sub*1.85*10; printf("Damage dealt: %d\n", sub*1.85*10); if (input()) goto exit; } rendscreenf(); usleep(200); if (enemyh>0) { sub=floor(random()*10)*1.4*10; health+=-sub; health+=-4*10; printf("Bear attacks! Damage dealt: %d\n", sub+4*10); if (input()) goto exit; } if (health<0) { lives+=-1; health=1000+ebhealth; } } rendscreen("You won the battle!"); if (input()) goto exit; rendscreen("You keep the fur coat from the bear. It gives you +200 health in all battles!"); if (input()) goto exit; ebhealth+=200; special.push_back("Fur Coat"); rendscreen("You decide to put down a log and cross the river."); } if (input()) goto exit; printf("Unfortunately, this is an *alpha* release for debugging only. This is the end of the program.\n\n\n"); usleep(2000); printf("Exiting...\n"); usleep(500); goto exit; } } exit: // Exit services gfxExit(); return 0; }
void Player::Init(int argc, char *argv[]) { static bool init = false; frames = 0; if (init) return; // Display a nice version string std::stringstream header; std::string addtl_ver(PLAYER_ADDTL); header << "EasyRPG Player " << PLAYER_VERSION; if (!addtl_ver.empty()) header << " " << addtl_ver; header << " started"; Output::Debug(header.str().c_str()); unsigned int header_width = header.str().length(); header.str(""); header << std::setfill('=') << std::setw(header_width) << "="; Output::Debug(header.str().c_str()); #ifdef GEKKO // Init libfat (Mount SD/USB) if (!fatInitDefault()) { Output::Error("Couldn't mount any storage medium!"); } #elif defined(_3DS) // Starting debug console gfxInitDefault(); consoleInit(GFX_BOTTOM, NULL); APT_SetAppCpuTimeLimit(30); if (osGetKernelVersion() < SYSTEM_VERSION(2, 48, 3)) khaxInit(); // Executing libkhax just to be sure... consoleClear(); // Check if we already have access to csnd:SND, if not, we will perform a kernel privilege escalation Handle csndHandle = 0; use_dsp = false; #ifndef FORCE_DSP srvGetServiceHandleDirect(&csndHandle, "csnd:SND"); if (csndHandle) { Output::Debug("csnd:SND has been selected as audio service."); svcCloseHandle(csndHandle); } else { Output::Debug("csnd:SND is unavailable..."); #endif srvGetServiceHandleDirect(&csndHandle, "dsp::DSP"); if (csndHandle) { Output::Debug("dsp::DSP has been selected as audio service."); use_dsp = true; svcCloseHandle(csndHandle); } else { Output::Error("dsp::DSP is unavailable. Please dump a DSP firmware to use EasyRPG Player. If the problem persists, please report us the issue."); } #ifndef FORCE_DSP } #endif fsInit(); sdmcInit(); #ifndef CITRA3DS_COMPATIBLE romfsInit(); #endif hidInit(); // Enable 804 Mhz mode if on N3DS bool isN3DS; APT_CheckNew3DS(&isN3DS); if (isN3DS) { osSetSpeedupEnable(true); } #endif #if (defined(_WIN32) && defined(NDEBUG) && defined(WINVER) && WINVER >= 0x0600) InitMiniDumpWriter(); #endif srand(time(NULL)); ParseCommandLine(argc, argv); #ifdef EMSCRIPTEN Output::IgnorePause(true); // Create initial directory structure in our private area // Retrieve save directory from persistent storage EM_ASM( FS.mkdir("easyrpg"); FS.chdir("easyrpg"); var dirs = ['Backdrop', 'Battle', 'Battle2', 'BattleCharSet', 'BattleWeapon', 'CharSet', 'ChipSet', 'FaceSet', 'Frame', 'GameOver', 'Monster', 'Movie', 'Music', 'Panorama', 'Picture', 'Sound', 'System', 'System2', 'Title', 'Save']; dirs.forEach(function(dir) { FS.mkdir(dir) }); FS.mount(IDBFS, {}, 'Save'); FS.syncfs(true, function(err) { }); );
int main() { gfxInitDefault(); gfxSet3D(false); PrintConsole topConsole, botConsole; consoleInit(GFX_TOP, &topConsole); consoleInit(GFX_BOTTOM, &botConsole); consoleSelect(&topConsole); consoleClear(); state_t current_state = STATE_NONE; state_t next_state = STATE_INITIALIZE; FS_ProductInfo product_info; char exploitname[64] = {0}; char titlename[64] = {0}; char versiondir[64] = {0}; char displayversion[64] = {0}; u32 flags_bitmask = 0; static char top_text[2048]; char top_text_tmp[256]; top_text[0] = '\0'; int firmware_version[6] = {0}; int firmware_selected_value = 0; int selected_slot = 0; int selected_version = 0; u32 selected_remaster = 0; AM_TitleEntry update_title; bool update_exists = false; int version_maxnum = 0; void* payload_buffer = NULL; size_t payload_size = 0; u64 program_id = 0; while(aptMainLoop()) { hidScanInput(); if(hidKeysDown() & KEY_START) break; // transition function if(next_state != current_state) { memset(top_text_tmp, 0, sizeof(top_text_tmp)); switch(next_state) { case STATE_INITIALIZE: strncat(top_text, "Initializing... You may press START at any time\nto return to menu.\n\n", sizeof(top_text) - 1); break; case STATE_INITIAL: strncat(top_text, "Welcome to sploit_installer: SALT edition!\nPlease proceed with caution, as you might lose\ndata if you don't.\n\nPress A to continue.\n\n", sizeof(top_text) - 1); break; case STATE_SELECT_VERSION: snprintf(top_text_tmp, sizeof(top_text_tmp) - 1, "Auto-detected %s version: %s\nD-Pad to select, A to continue.\n\n", titlename, displayversion); break; case STATE_SELECT_SLOT: snprintf(top_text_tmp, sizeof(top_text_tmp) - 1, "Please select the savegame slot %s will be\ninstalled to. D-Pad to select, A to continue.\n", exploitname); break; case STATE_SELECT_FIRMWARE: strncat(top_text, "Please select your console's firmware version.\nOnly select NEW 3DS if you own a New 3DS (XL).\nD-Pad to select, A to continue.\n", sizeof(top_text) - 1); break; case STATE_DOWNLOAD_PAYLOAD: snprintf(top_text, sizeof(top_text) - 1, "%s\n\n\nDownloading payload...\n", top_text); break; case STATE_COMPRESS_PAYLOAD: strncat(top_text, "Processing payload...\n", sizeof(top_text) - 1); break; case STATE_INSTALL_PAYLOAD: strncat(top_text, "Installing payload...\n\n", sizeof(top_text) - 1); break; case STATE_INSTALLED_PAYLOAD: snprintf(top_text_tmp, sizeof(top_text_tmp) - 1, "Done!\n%s was successfully installed.", exploitname); break; case STATE_ERROR: strncat(top_text, "Looks like something went wrong. :(\n", sizeof(top_text) - 1); break; default: break; } if(top_text_tmp[0]) strncat(top_text, top_text_tmp, sizeof(top_text) - 1); current_state = next_state; } consoleSelect(&topConsole); printf("\x1b[0;%dHsploit_installer: SALT edition\n\n\n", (50 - 31) / 2); printf(top_text); // state function switch(current_state) { case STATE_INITIALIZE: { fsInit(); // get an fs:USER session as the game Result ret = srvGetServiceHandleDirect(&save_session, "fs:USER"); if(R_SUCCEEDED(ret)) ret = FSUSER_Initialize(save_session); if(R_FAILED(ret)) { snprintf(status, sizeof(status) - 1, "Failed to get game fs:USER session.\n Error code: %08lX", ret); next_state = STATE_ERROR; break; } ret = httpcInit(0); if(R_FAILED(ret)) { snprintf(status, sizeof(status) - 1, "Failed to initialize httpc.\n Error code: %08lX", ret); next_state = STATE_ERROR; break; } OS_VersionBin nver_versionbin, cver_versionbin; ret = osGetSystemVersionData(&nver_versionbin, &cver_versionbin); if(R_FAILED(ret)) { snprintf(status, sizeof(status) - 1, "Failed to get the system version.\n Error code: %08lX", ret); next_state = STATE_ERROR; break; } ret = cfguInit(); if(R_FAILED(ret)) { snprintf(status, sizeof(status) - 1, "Failed to initialize cfgu.\n Error code: %08lX", ret); next_state = STATE_ERROR; break; } u8 region = 0; ret = CFGU_SecureInfoGetRegion(®ion); if(R_FAILED(ret)) { snprintf(status, sizeof(status) - 1, "Failed to get the system region.\n Error code: %08lX", ret); next_state = STATE_ERROR; break; } cfguExit(); bool is_new3ds = false; APT_CheckNew3DS(&is_new3ds); firmware_version[0] = is_new3ds; firmware_version[5] = region; firmware_version[1] = cver_versionbin.mainver; firmware_version[2] = cver_versionbin.minor; firmware_version[3] = cver_versionbin.build; firmware_version[4] = nver_versionbin.mainver; u32 pid = 0; ret = svcGetProcessId(&pid, CUR_PROCESS_HANDLE); if(R_FAILED(ret)) { snprintf(status, sizeof(status) - 1, "Failed to get the process ID for the current process.\n Error code: %08lX", ret); next_state = STATE_ERROR; break; } ret = FSUSER_GetProductInfo(&product_info, pid); selected_remaster = product_info.remasterVersion; if(R_FAILED(ret)) { snprintf(status, sizeof(status) - 1, "Failed to get the product info for the current process.\n Error code: %08lX", ret); next_state = STATE_ERROR; break; } ret = APT_GetProgramID(&program_id); if(R_FAILED(ret)) { snprintf(status, sizeof(status) - 1, "Failed to get the program ID for the current process.\n Error code: %08lX", ret); next_state = STATE_ERROR; break; } u64 update_program_id = 0; if(((program_id >> 32) & 0xFFFF) == 0) update_program_id = program_id | 0x0000000E00000000ULL; if(update_program_id) { ret = amInit(); if(R_FAILED(ret)) { snprintf(status, sizeof(status) - 1, "Failed to initialize AM.\n Error code: %08lX", ret); next_state = STATE_ERROR; break; } ret = AM_GetTitleInfo(1, 1, &update_program_id, &update_title); amExit(); if(R_SUCCEEDED(ret)) update_exists = true; } ret = romfsInit(); if(R_FAILED(ret)) { snprintf(status, sizeof(status) - 1, "Failed to initialize romfs for this application (romfsInit()).\n Error code: %08lX", ret); next_state = STATE_ERROR; break; } ret = load_exploitlist_config("romfs:/exploitlist_config", &program_id, exploitname, titlename, &flags_bitmask); if(ret) { snprintf(status, sizeof(status) - 1, "Failed to select the exploit.\n Error code: %08lX", ret); if(ret == 1) strncat(status, " Failed to\nopen the config file in romfs.", sizeof(status) - 1); if(ret == 2) strncat(status, " This title is not supported.", sizeof(status) - 1); next_state = STATE_ERROR; break; } int version_index = 0; u32 this_remaster = 0; char this_displayversion[64] = {0}; while(true) { ret = load_exploitversion(exploitname, &program_id, version_index, &this_remaster, this_displayversion); if(ret) break; if(this_remaster == selected_remaster) { strncpy(displayversion, this_displayversion, 63); selected_version = version_index; } version_index++; } if(version_index == 0) { snprintf(status, sizeof(status) - 1, "Failed to read remaster versions from config."); next_state = STATE_ERROR; break; } version_maxnum = version_index - 1; next_state = STATE_INITIAL; } break; case STATE_INITIAL: { if(hidKeysDown() & KEY_A) { if(version_maxnum != 0) next_state = STATE_SELECT_VERSION; else if(flags_bitmask & 0x10) next_state = STATE_SELECT_FIRMWARE; else next_state = STATE_SELECT_SLOT; } } break; case STATE_SELECT_VERSION: { if(hidKeysDown() & KEY_UP) selected_version++; if(hidKeysDown() & KEY_DOWN) selected_version--; if(hidKeysDown() & KEY_A) { if(flags_bitmask & 0x10) next_state = STATE_SELECT_FIRMWARE; else next_state = STATE_SELECT_SLOT; } if(selected_version < 0) selected_version = 0; if(selected_version > version_maxnum) selected_version = version_maxnum; Result ret = load_exploitversion(exploitname, &program_id, selected_version, &selected_remaster, displayversion); if(ret) { snprintf(status, sizeof(status) - 1, "Failed to read remaster version from config."); next_state = STATE_ERROR; break; } printf((selected_version >= version_maxnum) ? " \n" : " ^\n"); printf(" Selected version: %s \n", displayversion); printf((!selected_version) ? " \n" : " v\n"); } break; case STATE_SELECT_SLOT: { if(hidKeysDown() & KEY_UP) selected_slot++; if(hidKeysDown() & KEY_DOWN) selected_slot--; if(hidKeysDown() & KEY_A) next_state = STATE_SELECT_FIRMWARE; if(selected_slot < 0) selected_slot = 0; if(selected_slot > 2) selected_slot = 2; printf((selected_slot >= 2) ? " \n" : " ^\n"); printf(" Selected slot: %d \n", selected_slot + 1); printf((!selected_slot) ? " \n" : " v\n"); } break; case STATE_SELECT_FIRMWARE: { if(hidKeysDown() & KEY_LEFT) firmware_selected_value--; if(hidKeysDown() & KEY_RIGHT) firmware_selected_value++; if(firmware_selected_value < 0) firmware_selected_value = 0; if(firmware_selected_value > 5) firmware_selected_value = 5; if(hidKeysDown() & KEY_UP) firmware_version[firmware_selected_value]++; if(hidKeysDown() & KEY_DOWN) firmware_version[firmware_selected_value]--; int firmware_maxnum = 256; if(firmware_selected_value == 0) firmware_maxnum = 2; if(firmware_selected_value == 5) firmware_maxnum = 7; if(firmware_version[firmware_selected_value] < 0) firmware_version[firmware_selected_value] = 0; if(firmware_version[firmware_selected_value] >= firmware_maxnum) firmware_version[firmware_selected_value] = firmware_maxnum - 1; if(hidKeysDown() & KEY_A) next_state = STATE_DOWNLOAD_PAYLOAD; int offset = 26; if(firmware_selected_value) { offset += 7; for(int i = 1; i < firmware_selected_value; i++) { offset += 2; if(firmware_version[i] >= 10) offset++; } } printf((firmware_version[firmware_selected_value] < firmware_maxnum - 1) ? "%*s^%*s" : "%*s-%*s", offset, " ", 50 - offset - 1, " "); printf(" Selected firmware: %s %d-%d-%d-%d %s \n", firmware_version[0] ? "New3DS" : "Old3DS", firmware_version[1], firmware_version[2], firmware_version[3], firmware_version[4], regions[firmware_version[5]]); printf((firmware_version[firmware_selected_value] > 0) ? "%*sv%*s" : "%*s-%*s", offset, " ", 50 - offset - 1, " "); } break; case STATE_DOWNLOAD_PAYLOAD: { httpcContext context; static char in_url[512]; static char out_url[512]; snprintf(in_url, sizeof(in_url) - 1, "http://smea.mtheall.com/get_payload.php?version=%s-%d-%d-%d-%d-%s", firmware_version[0] ? "NEW" : "OLD", firmware_version[1], firmware_version[2], firmware_version[3], firmware_version[4], regions[firmware_version[5]]); char user_agent[64]; snprintf(user_agent, sizeof(user_agent) - 1, "salt_sploit_installer-%s", exploitname); Result ret = get_redirect(in_url, out_url, 512, user_agent); if(R_FAILED(ret)) { sprintf(status, "Failed to grab payload url\n Error code: %08lX", ret); next_state = STATE_ERROR; break; } ret = httpcOpenContext(&context, HTTPC_METHOD_GET, out_url, 0); if(R_FAILED(ret)) { sprintf(status, "Failed to open http context\n Error code: %08lX", ret); next_state = STATE_ERROR; break; } ret = download_file(&context, &payload_buffer, &payload_size, user_agent); if(R_FAILED(ret)) { sprintf(status, "Failed to download payload\n Error code: %08lX", ret); next_state = STATE_ERROR; break; } if(flags_bitmask & 0x1) next_state = STATE_COMPRESS_PAYLOAD; else next_state = STATE_INSTALL_PAYLOAD; } break; case STATE_COMPRESS_PAYLOAD: payload_buffer = BLZ_Code(payload_buffer, payload_size, &payload_size, BLZ_NORMAL); next_state = STATE_INSTALL_PAYLOAD; break; case STATE_INSTALL_PAYLOAD: { u32 selected_remaster_version = 0; Result ret = load_exploitconfig(exploitname, &program_id, selected_remaster, update_exists ? &update_title.version : NULL, &selected_remaster_version, versiondir, displayversion); if(ret) { snprintf(status, sizeof(status) - 1, "Failed to find your version of\n%s in the config / config loading failed.\n Error code: %08lX", titlename, ret); if(ret == 1) strncat(status, " Failed to\nopen the config file in romfs.", sizeof(status) - 1); if(ret == 2 || ret == 4) strncat(status, " The romfs config file is invalid.", sizeof(status) - 1); if(ret == 3) { snprintf(status, sizeof(status) - 1, "this update-title version (v%u) of %s is not compatible with %s, sorry\n", update_title.version, titlename, exploitname); next_state = STATE_ERROR; break; } if(ret == 5) { snprintf(status, sizeof(status) - 1, "this remaster version (%04lX) of %s is not compatible with %s, sorry\n", selected_remaster_version, titlename, exploitname); next_state = STATE_ERROR; break; } next_state = STATE_ERROR; break; } if(flags_bitmask & 0x8) { fsUseSession(save_session); Result ret = FSUSER_FormatSaveData(ARCHIVE_SAVEDATA, (FS_Path){PATH_EMPTY, 1, (u8*)""}, 0x200, 10, 10, 11, 11, true); fsEndUseSession(); if(ret) { sprintf(status, "Failed to format savedata.\n Error code: %08lX", ret); next_state = STATE_ERROR; break; } } if(flags_bitmask & 0x2) { Result ret = parsecopy_saveconfig(versiondir, firmware_version[0], selected_slot); if(ret) { sprintf(status, "Failed to install the savefiles with romfs %s savedir.\n Error code: %08lX", firmware_version[0] == 0?"Old3DS" : "New3DS", ret); next_state = STATE_ERROR; break; } } if(flags_bitmask & 0x4) { Result ret = parsecopy_saveconfig(versiondir, 2, selected_slot); if(ret) { sprintf(status, "Failed to install the savefiles with romfs %s savedir.\n Error code: %08lX", "common", ret); next_state = STATE_ERROR; break; } } } { Result ret; if(payload_embed.enabled) { void* buffer = NULL; size_t size = 0; ret = read_savedata(payload_embed.path, &buffer, &size); if(ret) { sprintf(status, "Failed to embed payload\n Error code: %08lX", ret); next_state = STATE_ERROR; break; } if((payload_embed.offset + payload_size + sizeof(u32)) >= size) { sprintf(status, "Failed to embed payload (too large)\n 0x%X >= 0x%X", (payload_embed.offset + payload_size + sizeof(u32)), size); next_state = STATE_ERROR; break; } *(u32*)(buffer + payload_embed.offset) = payload_size; memcpy(buffer + payload_embed.offset + sizeof(u32), payload_buffer, payload_size); ret = write_savedata(payload_embed.path, buffer, size); free(buffer); } else ret = write_savedata("/payload.bin", payload_buffer, payload_size); if(ret) { sprintf(status, "Failed to install payload\n Error code: %08lX", ret); next_state = STATE_ERROR; break; } next_state = STATE_INSTALLED_PAYLOAD; } break; case STATE_INSTALLED_PAYLOAD: next_state = STATE_NONE; break; default: break; } consoleSelect(&botConsole); printf("\x1b[0;0H Current status:\n %s\n", status); gspWaitForVBlank(); } if(payload_buffer) free(payload_buffer); romfsExit(); httpcExit(); svcCloseHandle(save_session); fsExit(); gfxExit(); return 0; }
Result load_hblauncher() { Result ret = 0; u8 region=0; u8 new3dsflag = 0; OS_VersionBin nver_versionbin; OS_VersionBin cver_versionbin; u32 payloadsize = 0, payloadsize_aligned = 0; u32 payload_src = 0; char payload_sysver[32]; char payloadurl[0x80]; char payload_sdpath[0x80]; void (*funcptr)(u32*, u32*) = NULL; u32 *paramblk = NULL; memset(&nver_versionbin, 0, sizeof(OS_VersionBin)); memset(&cver_versionbin, 0, sizeof(OS_VersionBin)); memset(payload_sysver, 0, sizeof(payload_sysver)); memset(payloadurl, 0, sizeof(payloadurl)); memset(payload_sdpath, 0, sizeof(payload_sdpath)); printf("Getting system-version/system-info etc...\n"); ret = cfguInit(); if(ret!=0) { printf("Failed to init cfgu: 0x%08x.\n", (unsigned int)ret); return ret; } ret = CFGU_SecureInfoGetRegion(®ion); if(ret!=0) { printf("Failed to get region from cfgu: 0x%08x.\n", (unsigned int)ret); return ret; } if(region>=7) { printf("Region value from cfgu is invalid: 0x%02x.\n", (unsigned int)region); ret = -9; return ret; } cfguExit(); APT_CheckNew3DS(&new3dsflag); ret = osGetSystemVersionData(&nver_versionbin, &cver_versionbin); if(ret!=0) { printf("Failed to load the system-version: 0x%08x.\n", (unsigned int)ret); return ret; } snprintf(payload_sysver, sizeof(payload_sysver)-1, "%s-%d-%d-%d-%d-%s", new3dsflag?"NEW":"OLD", cver_versionbin.mainver, cver_versionbin.minor, cver_versionbin.build, nver_versionbin.mainver, regionids_table[region]); snprintf(payloadurl, sizeof(payloadurl)-1, "http://smea.mtheall.com/get_payload.php?version=%s", payload_sysver); snprintf(payload_sdpath, sizeof(payload_sdpath)-1, "sdmc:/hblauncherloader_otherapp_payload_%s.bin", payload_sysver); printf("Detected system-version: %s %d.%d.%d-%d %s\n", new3dsflag?"New3DS":"Old3DS", cver_versionbin.mainver, cver_versionbin.minor, cver_versionbin.build, nver_versionbin.mainver, regionids_table[region]); memset(filebuffer, 0, filebuffer_maxsize); hidScanInput(); if((hidKeysHeld() & KEY_X) == 0) { printf("Since the X button isn't pressed, this will now check for the otherapp payload on SD, with the following filepath: %s\n", payload_sdpath); ret = loadsd_payload(payload_sdpath, &payloadsize); } else { printf("Skipping SD payload load-attempt since the X button is pressed.\n"); ret = 1; } if(ret==0) { printf("The otherapp payload for this app already exists on SD, that will be used instead of downloading the payload via HTTP.\n"); payload_src = 0; } else { printf("Requesting the actual payload URL with HTTP...\n"); ret = http_getactual_payloadurl(payloadurl, payloadurl, sizeof(payloadurl)); if(ret!=0) { printf("Failed to request the actual payload URL: 0x%08x.\n", (unsigned int)ret); printf("If the server isn't down, and the HTTP request was actually done, this may mean your system-version or region isn't supported by the hblauncher-payload currently.\n"); return ret; } printf("Downloading the actual payload with HTTP...\n"); ret = http_download_payload(payloadurl, &payloadsize); if(ret!=0) { printf("Failed to download the actual payload with HTTP: 0x%08x.\n", (unsigned int)ret); printf("If the server isn't down, and the HTTP request was actually done, this may mean your system-version or region isn't supported by the hblauncher-payload currently.\n"); return ret; } if(ret==0)payload_src = 1; } printf("Initializing payload data etc...\n"); payloadsize_aligned = (payloadsize + 0xfff) & ~0xfff; if(payloadsize_aligned > PAYLOAD_TEXTMAXSIZE) { printf("Invalid payload size: 0x%08x.\n", (unsigned int)payloadsize); ret = -3; return ret; } if(payload_src) { hidScanInput(); if(hidKeysHeld() & KEY_Y) { printf("Saving the downloaded payload to SD since the Y button is pressed...\n"); ret = savesd_payload(payload_sdpath, payloadsize); if(ret!=0) { printf("Payload saving failed: 0x%08x.\n", (unsigned int)ret); } else { printf("Payload saving was successful.\n"); } } else { printf("Skipping saving the downloaded payload to SD since the Y button isn't pressed.\n"); } } memcpy(PAYLOAD_TEXTADDR, filebuffer, payloadsize_aligned); memset(filebuffer, 0, filebuffer_maxsize); ret = svcFlushProcessDataCache(0xffff8001, PAYLOAD_TEXTADDR, payloadsize_aligned);//Flush dcache for the payload which was copied into .text. Since that area was never executed, icache shouldn't be an issue. if(ret!=0) { printf("svcFlushProcessDataCache failed: 0x%08x.\n", (unsigned int)ret); return ret; } paramblk = linearMemAlign(0x10000, 0x1000); if(paramblk==NULL) { ret = 0xfe; printf("Failed to alloc the paramblk.\n"); return ret; } httpcExit(); memset(paramblk, 0, 0x10000); paramblk[0x1c>>2] = (u32)gxlowcmd_4; paramblk[0x20>>2] = (u32)gsp_flushdcache; paramblk[0x48>>2] = 0x8d;//flags paramblk[0x58>>2] = (u32)&gspGpuHandle; printf("Jumping into the payload...\n"); funcptr = (void*)PAYLOAD_TEXTADDR; funcptr(paramblk, (u32*)(0x10000000-0x1000)); ret = 0xff; printf("The payload returned back into the app, this should *never* happen with the actual hblauncher-payload.\n"); return ret; }
//Gets system version from kernel and writes it to system.txt void getSystemVersion() { //FIRSTLY, CHECK NEW 3DS u8 isN3DS = 0; APT_CheckNew3DS(NULL, &isN3DS); unsigned int kversion = *(unsigned int *)0x1FF80000; if (!isN3DS || kversion < 0x022C0600) { //-----------> OLD 3DS switch (kversion) { default: // Unsupported type = '0'; systemVersion = "unsupported"; break; case 0x02220000: // 4.x type = '1'; systemVersion = "Old 3DS V. 4.1 - 4.5"; break; case 0x02230600: // 5.0 type = '2'; systemVersion = "Old 3DS V. 5.0"; break; case 0x02240000: // 5.1 type = '3'; systemVersion = "Old 3DS V. 5.1"; break; case 0x02250000: // 6.0 type = '4'; systemVersion = "Old 3DS V. 6.0"; break; case 0x02260000: // 6.1 type = '5'; systemVersion = "Old 3DS V. 6.1 - 6.3"; break; case 0x02270400: // 7.0-7.1 type = '6'; systemVersion = "Old 3DS V. 7.0 - 7.1"; break; case 0x02280000: // 7.2 type = '7'; systemVersion = "Old 3DS V. 7.2"; break; case 0x022C0600: // 8.x type = '8'; systemVersion = "Old 3DS V. 8.0 - 8.1"; break; case 0x022E0000: // 9.x type = '9'; systemVersion = "Old 3DS V. 9.0 - 9.2"; break; } } else { //-----------> NEW 3DS switch (kversion) { case 0x022C0600: // 8.x type = 'a'; systemVersion = "New 3DS V. 8.1"; break; case 0x022E0000: // 9.x type = 'b'; systemVersion = "New 3DS V. 9.0 - 9.2"; break; default: // Unsupported type = '0'; systemVersion = "unsupported"; break; } } }
int main() { static char load_filename[512]; char *romname = NULL; float audioStart; // this is a float to count the half sample per frame needed ho have precise timing u32 audioTarget, audioEnd; srvInit(); aptInit(); hidInit(); APT_CheckNew3DS(&isN3DS); if(isN3DS) osSetSpeedupEnable(true); get_config_path(); sprintf(savename, "%s/Handy3ds.cfg", config_base_path); // using savename char buffer to save memory do_config(savename); handy_3ds_video_init(); sprintf(bios_path_and_name, "%s/%s", config_bios_path, "lynxboot.img"); // Call filebrowser if(gui_LoadFile(load_filename)!= -1) { romname = (char *)&load_filename; do { hidScanInput(); } while (hidKeysHeld()); } else { handy_3ds_quit(); } // Primary initalise of Handy - should be called AFTER _Init() but BEFORE handy_3ds_video_setup() handy_3ds_core_init(romname); // Initialise Handy 3ds video handy_3ds_video_setup(1, 0, 0, 32, LynxScale, 0, 0); // Initialise Handy 3ds audio printf("\nInitialising 3DS Audio... "); gAudioEnabled = handy_3ds_audio_init(); printf("[DONE]\n"); // Setup of Handy Core video handy_3ds_video_reinit(32); printf("Starting Lynx Emulation...\n"); bool touched = false; audioStart = gAudioBufferPointer; // both should be 0 at this point // initialize timers u64 tickcurr, syncticknext,synctickres; u64 fpsticknext,fpstickres; int frameSyncPeriod; if(isN3DS) frameSyncPeriod = 1; else frameSyncPeriod = 12; fpstickres= TICKS_PER_SEC; synctickres = TICKS_PER_FRAME * frameSyncPeriod; // on o3ds the sync is every 12 frame, i.e. 5 times every sec tickcurr=svcGetSystemTick(); fpsticknext = tickcurr + fpstickres; syncticknext = tickcurr + synctickres; int fpscnt = 0, synccnt = 0; gThrottleMaxPercentage = isN3DS?100:50; // !! TO DO: check if 50 is the best value. while(!emulation) { // Initialise Handy button events int OldKeyMask, KeyMask = mpLynx->GetButtonData(); OldKeyMask = KeyMask; // Getting events for keyboard and/or joypad handling hidScanInput(); if (hidKeysHeld() & KEY_TOUCH) { touched = true; } else { if (touched) { handy_3ds_audio_pause(); gui_Run(); KeyMask = 0; touched = false; // audioStart = gAudioBufferPointer; do { hidScanInput(); } while (hidKeysHeld()); gThrottleMaxPercentage = isN3DS?100:50; // !! Loading a savestate overrides this value, so we force it again exiting menu fpscnt = 0; synccnt = 0; tickcurr=svcGetSystemTick(); fpsticknext = tickcurr + fpstickres; syncticknext = tickcurr + synctickres; } else { touched = false; } } KeyMask = handy_3ds_on_key_down(hidKeysHeld(), KeyMask); // Check if there are handling events and then update the Handy button events. if (OldKeyMask != KeyMask) mpLynx->SetButtonData(KeyMask); // Update TimerCount gTimerCount++; while( handy_3ds_update() ) { //!! hidScanInput(); u32 held = hidKeysHeld(); if (held & KEY_SELECT) { // handy_3ds_video_quit(); // handy_3ds_audio_quit(); // exit(EXIT_SUCCESS); //break; touched = true; // enter menu } //!! if(!gSystemHalt) { if (!handy_3ds_audio_getstate()) { audioStart=0.0; // reset counter gAudioBufferPointer = 0; // reset buffer. really not needed since we set it to 0 in handy_3ds_audio_pause(). } // increase sound samples counter - 367,5 samples per frame at 60 fps audioEnd = (int)(audioStart + 367.5) % HANDY_AUDIO_BUFFER_SIZE; // filling 1 half of the buffer, roughly enough for slow frames on o3DS without risk of buffer head to reach the tail during the 10 frames before resync. audioTarget = (int)(audioStart + HANDY_AUDIO_BUFFER_SIZE/2.1) % HANDY_AUDIO_BUFFER_SIZE; if (audioTarget>audioStart) while (gAudioBufferPointer<audioTarget) mpLynx->Update(); else while ((gAudioBufferPointer>audioStart)||(gAudioBufferPointer<audioTarget)) mpLynx->Update(); if(Handy_cfg_Throttle && Handy_cfg_Sound && gAudioEnabled) { if (handy_3ds_audio_getstate()) handy_3ds_audio_callback(audioStart, (int)(audioTarget-audioStart)); else handy_3ds_audio_start(22050, audioStart); } audioStart = audioEnd; } else { printf("gSystemHalt : %ld\n", gSystemHalt); gTimerCount++; } system_checkPolls(); } // Timing fpscnt++; synccnt++; if (Handy_cfg_Throttle) { if (synccnt==frameSyncPeriod){ svcSleepThread((syncticknext - svcGetSystemTick()) / TICKS_PER_NSEC); } } tickcurr=svcGetSystemTick(); if (tickcurr >= syncticknext) { syncticknext += synctickres; synccnt = 0; } if (tickcurr >= fpsticknext) { fpsticknext += fpstickres; fps_counter = fpscnt; fpscnt = 0; } } // while(!emulation) osSetSpeedupEnable(true); return 0; }