Result LOADER_GetProgramInfo(ExHeader_Info* exheaderInfo, u64 programHandle) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); u32 *staticbufs = getThreadStaticBuffers(); cmdbuf[0] = IPC_MakeHeader(4, 2, 0); // 0x40080 cmdbuf[1] = (u32)programHandle; cmdbuf[2] = (u32)(programHandle >> 32); u32 staticbufscpy[2] = {staticbufs[0], staticbufs[1]}; staticbufs[0] = IPC_Desc_StaticBuffer(0x400, 0); staticbufs[1] = (u32)exheaderInfo; if(R_FAILED(ret = svcSendSyncRequest(loaderHandle))) return ret; staticbufs[0] = staticbufscpy[0]; staticbufs[1] = staticbufscpy[1]; return (Result)cmdbuf[1]; }
Result task_populate_titledb(populate_titledb_data* data) { if(data == NULL || data->items == NULL) { return R_APP_INVALID_ARGUMENT; } task_clear_titledb(data->items); data->itemsListed = false; data->finished = false; data->result = 0; data->cancelEvent = 0; Result res = 0; if(R_SUCCEEDED(res = svcCreateEvent(&data->cancelEvent, RESET_STICKY))) { if(R_SUCCEEDED(res = svcCreateEvent(&data->resumeEvent, RESET_STICKY))) { svcSignalEvent(data->resumeEvent); if(threadCreate(task_populate_titledb_thread, data, 0x10000, 0x19, 1, true) == NULL) { res = R_APP_THREAD_CREATE_FAILED; } } } if(R_FAILED(res)) { data->itemsListed = true; data->finished = true; if(data->resumeEvent != 0) { svcCloseHandle(data->resumeEvent); data->resumeEvent = 0; } if(data->cancelEvent != 0) { svcCloseHandle(data->cancelEvent); data->cancelEvent = 0; } } return res; }
static Result udsipc_InitializeWithVersion(udsNodeInfo *nodeinfo, Handle sharedmem_handle, u32 sharedmem_size, Handle *eventhandle) { u32* cmdbuf=getThreadCommandBuffer(); cmdbuf[0]=IPC_MakeHeader(0x1B,12,2); // 0x1B0302 cmdbuf[1]=sharedmem_size; memcpy(&cmdbuf[2], nodeinfo, sizeof(udsNodeInfo)); cmdbuf[12] = 0x400;//version cmdbuf[13] = IPC_Desc_SharedHandles(1); cmdbuf[14] = sharedmem_handle; Result ret=0; if(R_FAILED(ret=svcSendSyncRequest(__uds_servhandle)))return ret; ret = cmdbuf[1]; if(R_SUCCEEDED(ret)) { if(eventhandle)*eventhandle = cmdbuf[3]; } return ret; }
static int GDB_ParseCommonThreadInfo(char *out, GDBContext *ctx, int sig) { u32 threadId = ctx->currentThreadId; ThreadContext regs; s64 dummy; u32 core; Result r = svcGetDebugThreadContext(®s, ctx->debug, threadId, THREADCONTEXT_CONTROL_ALL); int n = sprintf(out, "T%02xthread:%x;", sig, threadId); if(R_FAILED(r)) return n; r = svcGetDebugThreadParam(&dummy, &core, ctx->debug, ctx->currentThreadId, DBGTHREAD_PARAMETER_CPU_CREATOR); // Creator = "first ran, and running the thread" if(R_SUCCEEDED(r)) n += sprintf(out + n, "core:%x;", core); if(ctx->isGDB) { for(u32 i = 0; i <= 12; i++) n += sprintf(out + n, "%x:%08x;", i, __builtin_bswap32(regs.cpu_registers.r[i])); } n += sprintf(out + n, "d:%08x;e:%08x;f:%08x;19:%08x;", __builtin_bswap32(regs.cpu_registers.sp), __builtin_bswap32(regs.cpu_registers.lr), __builtin_bswap32(regs.cpu_registers.pc), __builtin_bswap32(regs.cpu_registers.cpsr)); if(ctx->isGDB) { for(u32 i = 0; i < 16; i++) { u64 val; memcpy(&val, ®s.fpu_registers.d[i], 8); n += sprintf(out + n, "%x:%016llx;", 26 + i, __builtin_bswap64(val)); } n += sprintf(out + n, "2a:%08x;2b:%08x;", __builtin_bswap32(regs.fpu_registers.fpscr), __builtin_bswap32(regs.fpu_registers.fpexc)); } return n; }
Result TextureManager::load(void) { printf("Loading ballLoadingScreen: @%p\n", (ballLoadingScreen = sfil_load_PNG_file(ROMFS "ball_loading_screen.png", SF2D_PLACE_RAM))); if (!ballLoadingScreen) return -5; drawStaticLoadingScreen(); // s32 prio = 0; // threadMainLoop = true; // svcGetThreadPriority(&prio, CUR_THREAD_HANDLE); // threadCreate(_loadingScreen, (void*) this, 4*1024, prio-1, -2, true); Result ret = (loadTextures() ? 0 : -5); if (R_FAILED(ret)) return ret; sf2d_texture_set_params(this->boxTiles, GPU_TEXTURE_MAG_FILTER(GPU_LINEAR) | GPU_TEXTURE_MIN_FILTER(GPU_LINEAR)); // threadMainLoop = false; return ret; }
Result _HTTPC_CloseContext(Handle handle, Handle contextHandle, Handle *httpheap_sharedmem_handle, Handle *ropvmem_sharedmem_handle, Handle *httpc_sslc_handle) { u32* cmdbuf=getThreadCommandBuffer(); cmdbuf[0]=IPC_MakeHeader(0x3,1,0); // 0x30040 cmdbuf[1]=contextHandle; Result ret=0; if(R_FAILED(ret=svcSendSyncRequest(handle)))return ret; if(cmdbuf[1]==0) { if(cmdbuf[0]!=0x00030045)return -1;//The ROP is supposed to return a custom cmdreply. if(cmdbuf[2]!=(0x10 | ((0x2-1)<<26)) || cmdbuf[5]!=0x0)return -1; if(httpheap_sharedmem_handle)*httpheap_sharedmem_handle = cmdbuf[3]; if(ropvmem_sharedmem_handle)*ropvmem_sharedmem_handle = cmdbuf[4]; if(httpc_sslc_handle)*httpc_sslc_handle = cmdbuf[6]; } return cmdbuf[1]; }
Result ERRF_ThrowResult(Result failure) { ERRF_FatalErrInfo error; Result ret; if (R_FAILED(ret = errfInit())) return ret; memset(&error, 0, sizeof(error)); error.type = ERRF_ERRTYPE_GENERIC; // pcAddr is not used by ErrDisp for ERRF_ERRTYPE_FAILURE error.pcAddr = (u32)__builtin_extract_return_addr(__builtin_return_address(0)); getCommonErrorData(&error, failure); ret = ERRF_Throw(&error); errfExit(); return ret; }
Result IFile_Read(IFile *file, u64 *total, void *buffer, u32 len) { u32 read; u32 left; char *buf; u64 cur; Result res; if (len == 0) { *total = 0; return 0; } buf = (char *)buffer; cur = 0; left = len; while (1) { res = FSFILE_Read(file->handle, &read, file->pos, buf, left); if (R_FAILED(res)) { break; } cur += read; file->pos += read; if (read == left) { break; } buf += read; left -= read; } *total = cur; return res; }
static void action_launch_title_update(ui_view* view, void* data, float* progress, char* text) { title_info* info = (title_info*) data; Result res = 0; aptOpenSession(); if(R_SUCCEEDED(res = APT_PrepareToDoAppJump(0, info->titleId, info->mediaType))) { u8 buf0[0x300]; u8 buf1[0x20]; res = APT_DoAppJump(0x300, 0x20, buf0, buf1); } aptCloseSession(); if(R_FAILED(res)) { ui_pop(); info_destroy(view); error_display_res(NULL, info, ui_draw_title_info, res, "Failed to launch title."); } }
Result udsPullPacket(const udsBindContext *bindcontext, void *buf, size_t size, size_t *actual_size, u16 *src_NetworkNodeID) { u32* cmdbuf=getThreadCommandBuffer(); u32 saved_threadstorage[2]; u32 aligned_size = (size+0x3) & ~0x3; cmdbuf[0]=IPC_MakeHeader(0x14,3,0); // 0x1400C0 cmdbuf[1]=bindcontext->BindNodeID; cmdbuf[2]=aligned_size>>2; cmdbuf[3]=size; u32 * staticbufs = getThreadStaticBuffers(); saved_threadstorage[0] = staticbufs[0]; saved_threadstorage[1] = staticbufs[1]; staticbufs[0] = IPC_Desc_StaticBuffer(aligned_size,0); staticbufs[1] = (u32)buf; Result ret=0; ret=svcSendSyncRequest(__uds_servhandle); staticbufs[0] = saved_threadstorage[0]; staticbufs[1] = saved_threadstorage[1]; if(R_FAILED(ret))return ret; ret = cmdbuf[1]; if(R_SUCCEEDED(ret)) { if(actual_size)*actual_size = cmdbuf[2]; if(src_NetworkNodeID)*src_NetworkNodeID = cmdbuf[3]; } return ret; }
void files_open(FS_Archive archive) { files_data* data = (files_data*) calloc(1, sizeof(files_data)); data->archive = archive; if(data->archive.lowPath.size > 0) { data->archivePath = calloc(1, data->archive.lowPath.size); memcpy(data->archivePath, data->archive.lowPath.data, data->archive.lowPath.size); data->archive.lowPath.data = data->archivePath; } data->archive.handle = 0; Result res = 0; if(R_FAILED(res = FSUSER_OpenArchive(&data->archive))) { error_display_res(NULL, NULL, NULL, res, "Failed to open file listing archive."); if(data->archivePath != NULL) { free(data->archivePath); } free(data); return; } data->currDir.archive = &data->archive; snprintf(data->currDir.path, PATH_MAX, "/"); util_get_path_file(data->currDir.name, data->currDir.path, NAME_MAX); data->currDir.isDirectory = true; data->currDir.containsCias = false; data->currDir.size = 0; data->currDir.isCia = false; memcpy(&data->parentDir, &data->currDir, sizeof(data->parentDir)); list_display("Files", "A: Select, B: Back, X: Refresh, Y: Directory Action", data, files_update, files_draw_top); }
static void action_install_cdn_update(ui_view* view, void* data, float* progress, char* text) { install_cdn_data* installData = (install_cdn_data*) data; if(installData->installInfo.finished) { ui_pop(); info_destroy(view); Result res = 0; if(R_SUCCEEDED(installData->installInfo.result)) { if(R_SUCCEEDED(res = AM_InstallTitleFinish()) && R_SUCCEEDED(res = AM_CommitImportTitles(((installData->ticket->titleId >> 32) & 0x8010) != 0 ? MEDIATYPE_NAND : MEDIATYPE_SD, 1, false, &installData->ticket->titleId))) { util_import_seed(installData->ticket->titleId); if(installData->ticket->titleId == 0x0004013800000002 || installData->ticket->titleId == 0x0004013820000002) { res = AM_InstallFirm(installData->ticket->titleId); } } } if(R_SUCCEEDED(installData->installInfo.result) && R_SUCCEEDED(res)) { if(installData->finishedPrompt) { prompt_display("Success", "Install finished.", COLOR_TEXT, false, installData->ticket, NULL, ui_draw_ticket_info, NULL); } } else { AM_InstallTitleAbort(); if(R_FAILED(res)) { error_display_res(NULL, installData->ticket, ui_draw_ticket_info, res, "Failed to install CDN title."); } } action_install_cdn_free_data(installData); return; }
void action_install_tickets(file_info* info, bool* populated) { install_tickets_data* data = (install_tickets_data*) calloc(1, sizeof(install_tickets_data)); data->base = info; data->installInfo.data = data; data->installInfo.op = DATAOP_COPY; data->installInfo.copyEmpty = false; data->installInfo.isSrcDirectory = action_install_tickets_is_src_directory; data->installInfo.makeDstDirectory = action_install_tickets_make_dst_directory; data->installInfo.openSrc = action_install_tickets_open_src; data->installInfo.closeSrc = action_install_tickets_close_src; data->installInfo.getSrcSize = action_install_tickets_get_src_size; data->installInfo.readSrc = action_install_tickets_read_src; data->installInfo.openDst = action_install_tickets_open_dst; data->installInfo.closeDst = action_install_tickets_close_dst; data->installInfo.writeDst = action_install_tickets_write_dst; data->installInfo.error = action_install_tickets_error; data->cancelEvent = 0; Result res = 0; if(R_FAILED(res = util_populate_contents(&data->contents, &data->installInfo.total, info->archive, info->path, false, false, ".tik", util_filter_file_extension))) { error_display_res(NULL, info, ui_draw_file_info, res, "Failed to retrieve content list."); free(data); return; } prompt_display("Confirmation", "Install the selected ticket(s)?", COLOR_TEXT, true, data, NULL, action_install_tickets_draw_top, action_install_tickets_onresponse); }
void postprocess(IpcParsedCommand &r, u64 cmd_id) override { if (this->active_object == this->service_object && (r.CommandType == IpcCommandType_Request || r.CommandType == IpcCommandType_RequestWithContext)) { IpcCommand c; ipcInitialize(&c); this->service_object->postprocess(cur_out_r, c, cmd_id, (u8 *)this->pointer_buffer, this->pointer_buffer_size); } else if (r.CommandType == IpcCommandType_Control || r.CommandType == IpcCommandType_ControlWithContext) { if (cmd_id == IpcCtrl_Cmd_ConvertCurrentObjectToDomain) { this->is_domain = true; this->domain = std::make_shared<DomainOwner>(); struct { u64 magic; u64 result; u32 domain_id; } *resp = (decltype(resp))cur_out_r.Raw; Result rc; if (R_FAILED((rc = this->domain->set_object(this->service_object, resp->domain_id)))) { fatalSimple(rc); } this->mitm_domain_id = resp->domain_id; this->forward_service.type = ServiceType_Domain; this->forward_service.object_id = resp->domain_id; } } }
void __attribute__((weak)) __libnx_initheap(void) { void* addr; size_t size = 0; size_t mem_available = 0, mem_used = 0; if (envHasHeapOverride()) { addr = envGetHeapOverrideAddr(); size = envGetHeapOverrideSize(); } else { if (__nx_heap_size==0) { svcGetInfo(&mem_available, 6, CUR_PROCESS_HANDLE, 0); svcGetInfo(&mem_used, 7, CUR_PROCESS_HANDLE, 0); if (mem_available > mem_used+0x200000) size = (mem_available - mem_used - 0x200000) & ~0x1FFFFF; if (size==0) size = 0x2000000*16; } else { size = __nx_heap_size; } Result rc = svcSetHeapSize(&addr, size); if (R_FAILED(rc)) fatalSimple(MAKERESULT(Module_Libnx, LibnxError_HeapAllocFailed)); } // Newlib extern char* fake_heap_start; extern char* fake_heap_end; fake_heap_start = (char*)addr; fake_heap_end = (char*)addr + size; }
Result PS_EncryptDecryptAes(u32 size, u8* in, u8* out, PS_AESAlgorithm aes_algo, PS_AESKeyType key_type, u8* iv) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); u32 *_iv = (u32*)iv; cmdbuf[0] = IPC_MakeHeader(0x4,8,4); // 0x40204 cmdbuf[1] = size; cmdbuf[2] = size; memcpy(&cmdbuf[3], _iv, 16); cmdbuf[7] = aes_algo; cmdbuf[8] = key_type; cmdbuf[9] = IPC_Desc_Buffer(size, IPC_BUFFER_R); cmdbuf[10] = (u32)in; cmdbuf[11] = IPC_Desc_Buffer(size, IPC_BUFFER_W); cmdbuf[12] = (u32)out; if(R_FAILED(ret = svcSendSyncRequest(psHandle)))return ret; memcpy(_iv, &cmdbuf[2], 16); return (Result)cmdbuf[1]; }
/*! Write to an open file * * @param[in,out] r newlib reentrancy struct * @param[in,out] fd Pointer to sdmc_file_t * @param[in] ptr Pointer to data to write * @param[in] len Length of data to write * * @returns number of bytes written * @returns -1 for error */ static ssize_t sdmc_write_safe(struct _reent *r, void *fd, const char *ptr, size_t len) { Result rc; u32 bytes, bytesWritten = 0; u32 sync = 0; /* get pointer to our data */ sdmc_file_t *file = (sdmc_file_t*)fd; /* check that the file was opened with write access */ if((file->flags & O_ACCMODE) == O_RDONLY) { r->_errno = EBADF; return -1; } /* check if this is synchronous or not */ if(file->flags & O_SYNC) sync = FS_WRITE_FLUSH | FS_WRITE_UPDATE_TIME; if(file->flags & O_APPEND) { /* append means write from the end of the file */ rc = FSFILE_GetSize(file->fd, &file->offset); if(R_FAILED(rc)) { r->_errno = sdmc_translate_error(rc); return -1; } } /* Copy to internal buffer and write in chunks. * You cannot write from read-only memory. */ static __thread char tmp_buffer[8192]; while(len > 0) { size_t toWrite = len; if(toWrite > sizeof(tmp_buffer)) toWrite = sizeof(tmp_buffer); /* copy to internal buffer */ memcpy(tmp_buffer, ptr, toWrite); /* write the data */ rc = FSFILE_Write(file->fd, &bytes, file->offset, (u32*)tmp_buffer, (u32)toWrite, sync); if(R_FAILED(rc)) { /* return partial transfer */ if(bytesWritten > 0) return bytesWritten; r->_errno = sdmc_translate_error(rc); return -1; } file->offset += bytes; bytesWritten += bytes; ptr += bytes; len -= bytes; } return bytesWritten; }
static Result task_data_op_copy(data_op_data* data, u32 index) { data->currProcessed = 0; data->currTotal = 0; data->bytesPerSecond = 0; data->estimatedRemainingSeconds = 0; Result res = 0; bool isDir = false; if(R_SUCCEEDED(res = data->isSrcDirectory(data->data, index, &isDir)) && isDir) { res = data->makeDstDirectory(data->data, index); } else { u32 srcHandle = 0; if(R_SUCCEEDED(res = data->openSrc(data->data, index, &srcHandle))) { if(R_SUCCEEDED(res = data->getSrcSize(data->data, srcHandle, &data->currTotal))) { if(data->currTotal == 0) { if(data->copyEmpty) { u32 dstHandle = 0; if(R_SUCCEEDED(res = data->openDst(data->data, index, NULL, data->currTotal, &dstHandle))) { res = data->closeDst(data->data, index, true, dstHandle); } } else { res = R_APP_BAD_DATA; } } else { u8* buffer = (u8*) calloc(1, data->bufferSize); if(buffer != NULL) { u32 dstHandle = 0; u64 ioStartTime = 0; u64 lastBytesPerSecondUpdate = osGetTime(); u32 bytesSinceUpdate = 0; bool firstRun = true; while(data->currProcessed < data->currTotal) { if(R_FAILED(res = task_data_op_check_running(data, data->processed, &srcHandle, &dstHandle))) { break; } u32 bytesRead = 0; if(R_FAILED(res = data->readSrc(data->data, srcHandle, &bytesRead, buffer, data->currProcessed, data->bufferSize))) { break; } if(firstRun) { firstRun = false; if(R_FAILED(res = data->openDst(data->data, index, buffer, data->currTotal, &dstHandle))) { break; } } u32 bytesWritten = 0; if(R_FAILED(res = data->writeDst(data->data, dstHandle, &bytesWritten, buffer, data->currProcessed, bytesRead))) { break; } data->currProcessed += bytesWritten; bytesSinceUpdate += bytesWritten; u64 time = osGetTime(); u64 elapsed = time - lastBytesPerSecondUpdate; if(elapsed >= 1000) { data->bytesPerSecond = (u32) (bytesSinceUpdate / (elapsed / 1000.0f)); if(ioStartTime != 0) { data->estimatedRemainingSeconds = (u32) ((data->currTotal - data->currProcessed) / (data->currProcessed / ((time - ioStartTime) / 1000.0f))); } else { data->estimatedRemainingSeconds = 0; } if(ioStartTime == 0 && data->currProcessed > 0) { ioStartTime = time; } bytesSinceUpdate = 0; lastBytesPerSecondUpdate = time; } } if(dstHandle != 0) { Result closeDstRes = data->closeDst(data->data, index, res == 0, dstHandle); if(R_SUCCEEDED(res)) { res = closeDstRes; } } free(buffer); } else { res = R_APP_OUT_OF_MEMORY; } } } Result closeSrcRes = data->closeSrc(data->data, index, res == 0, srcHandle); if(R_SUCCEEDED(res)) { res = closeSrcRes; } } } return res; }
void action_paste_contents(linked_list* items, list_item* selected) { if(!clipboard_has_contents()) { prompt_display("Failure", "Clipboard empty.", COLOR_TEXT, false, NULL, NULL, NULL); return; } paste_files_data* data = (paste_files_data*) calloc(1, sizeof(paste_files_data)); if(data == NULL) { error_display(NULL, NULL, "Failed to allocate paste files data."); return; } data->items = items; data->target = (file_info*) selected->data; data->pasteInfo.data = data; data->pasteInfo.op = DATAOP_COPY; data->pasteInfo.copyBufferSize = 256 * 1024; data->pasteInfo.copyEmpty = true; data->pasteInfo.isSrcDirectory = action_paste_files_is_src_directory; data->pasteInfo.makeDstDirectory = action_paste_files_make_dst_directory; data->pasteInfo.openSrc = action_paste_files_open_src; data->pasteInfo.closeSrc = action_paste_files_close_src; data->pasteInfo.getSrcSize = action_paste_files_get_src_size; data->pasteInfo.readSrc = action_paste_files_read_src; data->pasteInfo.openDst = action_paste_files_open_dst; data->pasteInfo.closeDst = action_paste_files_close_dst; data->pasteInfo.writeDst = action_paste_files_write_dst; data->pasteInfo.suspendCopy = action_paste_files_suspend_copy; data->pasteInfo.restoreCopy = action_paste_files_restore_copy; data->pasteInfo.suspend = action_paste_files_suspend; data->pasteInfo.restore = action_paste_files_restore; data->pasteInfo.error = action_paste_files_error; data->pasteInfo.finished = true; linked_list_init(&data->contents); populate_files_data popData; memset(&popData, 0, sizeof(popData)); popData.items = &data->contents; popData.archive = clipboard_get_archive(); strncpy(popData.path, clipboard_get_path(), FILE_PATH_MAX); popData.recursive = true; popData.includeBase = !clipboard_is_contents_only() || !util_is_dir(clipboard_get_archive(), clipboard_get_path()); popData.filter = NULL; popData.filterData = NULL; Result listRes = task_populate_files(&popData); if(R_FAILED(listRes)) { error_display_res(NULL, NULL, listRes, "Failed to initiate clipboard content list population."); action_paste_files_free_data(data); return; } while(!popData.finished) { svcSleepThread(1000000); } if(R_FAILED(popData.result)) { error_display_res(NULL, NULL, popData.result, "Failed to populate clipboard content list."); action_paste_files_free_data(data); return; } data->pasteInfo.total = linked_list_size(&data->contents); data->pasteInfo.processed = data->pasteInfo.total; prompt_display("Confirmation", "Paste clipboard contents to the current directory?", COLOR_TEXT, true, data, action_paste_files_draw_top, action_paste_files_onresponse); }
static Result ndspInitialize(bool resume) { Result rc; rc = ndspLoadComponent(); if (R_FAILED(rc)) return rc; rc = svcCreateEvent(&irqEvent, 1); if (R_FAILED(rc)) goto _fail1; rc = DSP_RegisterInterruptEvents(irqEvent, 2, 2); if (R_FAILED(rc)) goto _fail2; rc = DSP_GetSemaphoreHandle(&dspSem); if (R_FAILED(rc)) goto _fail3; DSP_SetSemaphoreMask(0x2000); u16 val = resume ? 2 : 0; if (resume) memcpy(ndspVars[5][0], dspVar5Backup, sizeof(dspVar5Backup)); DSP_WriteProcessPipe(2, &val, 4); DSP_SetSemaphore(0x4000); ndspWaitForIrq(); DSP_ReadPipeIfPossible(2, 0, &val, sizeof(val), NULL); u16 vars[16]; DSP_ReadPipeIfPossible(2, 0, vars, val*2, NULL); int i; for (i = 0; i < val; i ++) { DSP_ConvertProcessAddressFromDspDram(vars[i], (u32*)&ndspVars[i][0]); DSP_ConvertProcessAddressFromDspDram(vars[i] | 0x10000, (u32*)&ndspVars[i][1]); } DSP_SetSemaphore(0x4000); ndspFrameId = 4; ndspSetCounter(0, 4); ndspFrameId++; svcSignalEvent(dspSem); ndspBufferCurId = ndspFrameId & 1; ndspBufferId = ndspFrameId & 1; bDspReady = true; ndspDirtyMaster(); ndspUpdateMaster(); if (resume) { ndspiDirtyChn(); ndspiUpdateChn(); // Force update effect params here } return 0; _fail3: DSP_RegisterInterruptEvents(0, 2, 2); _fail2: svcCloseHandle(irqEvent); _fail1: DSP_UnloadComponent(); return rc; }
int main(void) { gfxInitDefault(); consoleInitDefault(); Result ret; state = STATE_START; ret = FS_Init(); if (R_FAILED(ret)) { consoleLog("\nCouldn't initialize the FS module!\n"); consoleLog("Have you selected a title?\n"); consoleLog("Error code: 0x%lx\n", ret); // state = STATE_ERROR; // TODO: Remove out of Citra } ret = saveInit(); if (R_FAILED(ret)) { consoleLog("\nCouldn't initialize the Save module!\n"); consoleLog("Error code: 0x%lx\n", ret); // state = STATE_ERROR; // TODO: Remove out of Citra } ret = saveGetTitleId(&titleid); if (R_FAILED(ret)) { consoleLog("\nCouldn't get the title id of the game!\n"); consoleLog("Error code: 0x%lx\n", ret); // state = STATE_ERROR; // TODO: Remove out of Citra } fsDirInit(); fsBackInit(titleid); switchState(&state); consoleSelectNew(&consoleLog); drawHelp(); u64 heldUp = 0; u64 heldDown = 0; u32 kDown, kHeld; while (aptMainLoop()) { gspWaitForVBlank(); hidScanInput(); kDown = hidKeysDown(); kHeld = hidKeysHeld(); switch (state) { case STATE_BROWSE: { if (kDown & (KEY_LEFT | KEY_RIGHT)) { fsDirSwitch(NULL); fsDirPrintSave(); fsDirPrintSdmc(); } if (kDown & KEY_ZL) { fsDirSwitch(&saveDir); fsDirPrintSave(); fsDirPrintSdmc(); } if (kDown & KEY_ZR) { fsDirSwitch(&sdmcDir); fsDirPrintSave(); fsDirPrintSdmc(); } if (kDown & KEY_UP) { fsDirMove(-1); fsDirPrintCurrent(); heldUp = svcGetSystemTick() + HELD_TICK * 2; } #ifndef NO_HELD_TICK else if (kHeld & KEY_UP) { if (heldUp + HELD_TICK < svcGetSystemTick()) { fsDirMove(-1); fsDirPrintCurrent(); heldUp = svcGetSystemTick(); } } #endif if (kDown & KEY_DOWN) { fsDirMove(+1); fsDirPrintCurrent(); heldDown = svcGetSystemTick() + HELD_TICK * 2; } #ifndef NO_HELD_TICK else if (kHeld & KEY_DOWN) { if (heldDown + HELD_TICK < svcGetSystemTick()) { fsDirMove(+1); fsDirPrintCurrent(); heldDown = svcGetSystemTick(); } } #endif if (kDown & KEY_A) { ret = fsDirGotoSubDir(); consoleLog(" > fsDirGotoSubDir: %lx\n", ret); fsDirPrintCurrent(); } if (kDown & KEY_B) { ret = fsDirGotoParentDir(); consoleLog(" > fsDirGotoParentDir: %lx\n", ret); fsDirPrintCurrent(); } if (kDown & KEY_X) { ret = fsDirDeleteCurrentEntry(); consoleLog(" > fsDirDeleteCurrentEntry: %lx\n", ret); fsDirPrintCurrent(); } if (kDown & KEY_Y) { ret = fsDirCopyCurrentEntry(false); consoleLog(" > fsDirCopyCurrentEntry: %lx\n", ret); fsDirPrintDick(); } break; } case STATE_BACKUP: { if (kDown & KEY_A) { ret = fsBackImport(); consoleLog(" > fsBackImport: %lx\n", ret); fsBackPrintSave(); } if (kDown & KEY_B) { state = STATE_BACKUP_KEY; // TODO: setKeyboardString consoleSelectNew(&logConsole); } if (kDown & KEY_X) { ret = fsBackDelete(); consoleLog(" > fsBackDelete: %lx\n", ret); fsBackPrintBackup(); } if (kDown & KEY_Y) { ret = fsBackExport(); consoleLog(" > fsBackExport: %lx\n", ret); fsBackPrintBackup(); } if (kDown & KEY_UP) { fsBackMove(-1); fsBackPrintBackup(); heldUp = svcGetSystemTick() + HELD_TICK * 2; } #ifndef NO_HELD_TICK else if (kHeld & KEY_UP) { if (heldUp + HELD_TICK < svcGetSystemTick()) { fsBackMove(-1); fsBackPrintBackup(); heldUp = svcGetSystemTick(); } } #endif if (kDown & KEY_DOWN) { fsBackMove(+1); fsBackPrintBackup(); heldDown = svcGetSystemTick() + HELD_TICK * 2; } #ifndef NO_HELD_TICK else if (kHeld & KEY_DOWN) { if (heldDown + HELD_TICK < svcGetSystemTick()) { fsBackMove(+1); fsBackPrintBackup(); heldDown = svcGetSystemTick(); } } #endif break; } case STATE_BACKUP_KEY: { // TODO: updateKeyboard if (kDown & KEY_A) { state = STATE_BACKUP; // TODO: getKeyboardString drawBackup(); } if (kDown & KEY_B) { state = STATE_BACKUP; drawBackup(); } break; } case STATE_ERROR: { consoleLog("\nAn error has occured...\n"); consoleLog("Please check previous logs!\n"); consoleLog("\nPress start to exit.\n"); state = STATE_EOF; break; } default: break; } { if (kDown & KEY_L) { // TODO: Prev switchState(&state); } if (kDown & KEY_R) { // TODO: Next switchState(&state); } if (kDown & KEY_SELECT) { drawHelp(); } } if (kDown & KEY_START) break; gfxFlushBuffers(); gfxSwapBuffers(); } fsDirExit(); fsBackExit(); FS_Exit(); { hidScanInput(); if (!(hidKeysHeld() & KEY_L) && !(hidKeysHeld() & KEY_R)) { u8 out = 0; FS_MediaType mediaType = 3; FSUSER_GetMediaType(&mediaType); Result ret = saveRemoveSecureValue(titleid, mediaType, &out); if (R_FAILED(ret)) { consoleSelect(&logConsole); printf("\nSecure value not removed.\n"); printf("It might already be unitialized.\n"); printf("Error code: 0x%lx (%i)\n", ret, out); printf("\n\nPress any key to exit.\n"); waitKey(KEY_ANY); } } } gfxExit(); return 0; }
Result APT_LaunchLibraryApplet(NS_APPID appID, Handle inhandle, u32 *parambuf, u32 parambufsize) { Result ret=0; u8 tmp=0; u8 buf1[4]; u8 buf2[4]; aptOpenSession(); APT_ReplySleepQuery(currentAppId, 0); aptCloseSession(); aptOpenSession(); ret=APT_PrepareToStartLibraryApplet(appID); aptCloseSession(); if(R_FAILED(ret))return ret; memset(buf1, 0, 4); aptOpenSession(); APT_AppletUtility(NULL, 0x4, 0x1, buf1, 0x1, buf2); aptCloseSession(); while(1) { aptOpenSession(); ret=APT_IsRegistered(appID, &tmp); aptCloseSession(); if(R_FAILED(ret))return ret; if(tmp!=0)break; } aptCallHook(APTHOOK_ONSUSPEND); __apt_launchapplet_appID = appID; __apt_launchapplet_inhandle = inhandle; __apt_launchapplet_parambuf = parambuf; __apt_launchapplet_parambufsize = parambufsize; // Set status to SUSPENDED. svcClearEvent(aptStatusEvent); aptSetStatus(APP_SUSPENDED); // Save Vram GSPGPU_SaveVramSysArea(); // Capture screen. memset(__ns_capinfo, 0, 0x20); aptInitCaptureInfo(__ns_capinfo); // Send capture-screen info to the library applet. aptOpenSession(); APT_SendParameter(currentAppId, appID, 0x20, __ns_capinfo, 0x0, 0x2); aptCloseSession(); // Release GSP module. GSPGPU_ReleaseRight(); return 0; }
static Result usd_parsebeacon(u8 *buf, u32 size, udsNetworkScanInfo *networkscan) { Result ret=0; u8 tagid, tag_datalen; u8 *tagptr; u8 oui[3] = {0x00, 0x1f, 0x32}; u8 oui_type; u8 appdata_size; //Index0 = 21(0x15), index1=24(0x18), index2=25(0x19). u8 *tags_data[3] = {0}; u32 tags_sizes[3] = {0}; int tagindex; u8 tmp_tagdata[0xfe*2]; if(size < 0xc)return -3; buf+=0xc;//Skip down to the tagged parameters in the beacon. size-=0xc; while(size)//Locate each of the Nintendo vendor tags which this code uses. { if(size < 2)return -3; tagid = buf[0]; tag_datalen = buf[1]; buf+= 0x2; size-= 0x2; if(tag_datalen > size)return -3; if(tagid==0xdd)//Vendor tag { if(tag_datalen < 4)return -3; if(memcmp(buf, oui, sizeof(oui))==0) { oui_type = buf[3]; tagindex = -1; if(oui_type==21) { tagindex = 0; } else if(oui_type==24) { tagindex = 1; } else if(oui_type==25) { tagindex = 2; } if(tagindex>=0) { tags_data[tagindex] = buf; tags_sizes[tagindex] = tag_datalen; } } } buf+= tag_datalen; size-= tag_datalen; } for(tagindex=0; tagindex<3; tagindex++)//Verify that the required tags exist and have valid sizes. { if(tagindex!=2 && (tags_data[tagindex]==NULL || tags_sizes[tagindex]==0))return -3; if(tagindex && tags_sizes[tagindex] > 0xFE)return -3; if(tagindex==1 && tags_sizes[tagindex] < 0x12)return -3; if(tagindex==0 && ((tags_sizes[tagindex]<0x34) || (tags_sizes[tagindex]>0x34+0xC8)))return -3; } //Tag type21 tagindex = 0; { tagptr = tags_data[tagindex]; tag_datalen = tags_sizes[tagindex]; appdata_size = tagptr[0x33]; if((appdata_size > 0xC8) || (appdata_size > tag_datalen-0x34))return -3;//Verify the appdata size. memset(&networkscan->network, 0, sizeof(udsNetworkStruct)); memcpy(&networkscan->network.oui_value, tagptr, 0x1F); networkscan->network.appdata_size = appdata_size; if(appdata_size)memcpy(networkscan->network.appdata, &tagptr[0x34], appdata_size); networkscan->network.initialized_flag = 1; networkscan->network.channel = networkscan->datareply_entry.channel; memcpy(networkscan->network.host_macaddress, networkscan->datareply_entry.mac_address, sizeof(networkscan->network.host_macaddress)); } memset(tmp_tagdata, 0, sizeof(tmp_tagdata)); for(tagindex=1; tagindex<3; tagindex++) { if(tags_data[tagindex])memcpy(&tmp_tagdata[0xfe * (tagindex-1)], tags_data[tagindex], tags_sizes[tagindex]); } ret = udsipc_DecryptBeaconData(&networkscan->network, tmp_tagdata, &tmp_tagdata[0xfe], networkscan->nodes); if(R_FAILED(ret))return ret; return 0; }
Result udsScanBeacons(void *buf, size_t maxsize, udsNetworkScanInfo **networks, size_t *total_networks, u32 wlancommID, u8 id8, const u8 *host_macaddress, bool connected) { Result ret=0; Handle event=0; u8 *outbuf = (u8*)buf; u32 entpos, curpos; nwmScanInputStruct scaninput; nwmBeaconDataReplyHeader *hdr; nwmBeaconDataReplyEntry *entry; udsNetworkScanInfo *networks_ptr; if(total_networks)*total_networks = 0; if(networks)*networks = NULL; memset(&scaninput, 0, sizeof(nwmScanInputStruct)); scaninput.unk_x0 = 0x1; scaninput.unk_x2 = 0x2; scaninput.unk_x4 = 0x0421; scaninput.unk_x6 = 0x6e; memset(scaninput.mac_address, 0xff, sizeof(scaninput.mac_address)); if(host_macaddress)memcpy(scaninput.mac_address, host_macaddress, sizeof(scaninput.mac_address)); if(maxsize < sizeof(nwmBeaconDataReplyHeader))return -2; ret = svcCreateEvent(&event, RESET_ONESHOT); if(R_FAILED(ret))return ret; if(!connected)ret = udsipc_RecvBeaconBroadcastData(outbuf, maxsize, &scaninput, wlancommID, id8, event); if(connected)ret = udsipc_ScanOnConnection(outbuf, maxsize, &scaninput, wlancommID, id8); svcCloseHandle(event); if(R_FAILED(ret))return ret; hdr = (nwmBeaconDataReplyHeader*)outbuf; curpos = sizeof(nwmBeaconDataReplyHeader); if(hdr->maxsize != maxsize)return -2; if(hdr->size > maxsize)return -2; if(hdr->total_entries) { if(networks) { networks_ptr = malloc(sizeof(udsNetworkScanInfo) * hdr->total_entries); if(networks_ptr == NULL)return -1; if(total_networks)*total_networks = hdr->total_entries; memset(networks_ptr, 0, sizeof(udsNetworkScanInfo) * hdr->total_entries); *networks = networks_ptr; for(entpos=0; entpos<hdr->total_entries; entpos++) { if(curpos >= hdr->size) { ret = -2; break; } entry = (nwmBeaconDataReplyEntry*)&outbuf[curpos]; if(entry->size > hdr->size || curpos + entry->size > hdr->size || entry->size <= sizeof(nwmBeaconDataReplyEntry)) { ret = -2; break; } memcpy(&networks_ptr[entpos].datareply_entry, entry, sizeof(nwmBeaconDataReplyEntry)); ret = usd_parsebeacon(&outbuf[curpos + sizeof(nwmBeaconDataReplyEntry)], entry->size - sizeof(nwmBeaconDataReplyEntry), &networks_ptr[entpos]); if(R_FAILED(ret))break; curpos+= entry->size; } } if(R_FAILED(ret)) { if(networks) { free(*networks); *networks = NULL; } if(total_networks)*total_networks = 0; } } return ret; }
static void __handle_notification(void) { APT_Signal type; Result ret=0; // Get notification type. aptOpenSession(); ret = APT_InquireNotification(currentAppId, &type); aptCloseSession(); if(R_FAILED(ret)) return; _aptDebug(1, type); switch(type) { case APTSIGNAL_HOMEBUTTON: case APTSIGNAL_POWERBUTTON: // The main thread should call aptReturnToMenu() when the status gets set to this. if(aptGetStatus() == APP_RUNNING) { aptOpenSession(); APT_ReplySleepQuery(currentAppId, 0x0); aptCloseSession(); if(type == APTSIGNAL_HOMEBUTTON) aptSetStatusPower(0); if(type == APTSIGNAL_POWERBUTTON) aptSetStatusPower(1); aptSetStatus(APP_SUSPENDING); } break; case APTSIGNAL_PREPARESLEEP: // Reply to sleep-request. aptStatusBeforeSleep = aptGetStatus(); aptSetStatus(APP_PREPARE_SLEEPMODE); svcWaitSynchronization(aptSleepSync, U64_MAX); svcClearEvent(aptSleepSync); aptOpenSession(); APT_ReplySleepQuery(currentAppId, 0x1); aptCloseSession(); break; case APTSIGNAL_ENTERSLEEP: if(aptGetStatus() == APP_PREPARE_SLEEPMODE) { // Report into sleep-mode. aptSetStatus(APP_SLEEPMODE); aptOpenSession(); APT_ReplySleepNotificationComplete(currentAppId); aptCloseSession(); } break; // Leaving sleep-mode. case APTSIGNAL_WAKEUP: if(aptGetStatus() == APP_SLEEPMODE) { if(aptStatusBeforeSleep == APP_RUNNING)GSPGPU_SetLcdForceBlack(0); // Restore old aptStatus. aptSetStatus(aptStatusBeforeSleep); } break; default: break; } }
int main(int argc, char **argv) { (void) argc, (void) argv; Result res = MAKERESULT(RL_SUCCESS, RS_SUCCESS, 0, RD_SUCCESS); gfxInitDefault(); PrintConsole top; consoleInit(GFX_TOP, &top); util_debug_init(); consoleSelect(&top); if (R_FAILED(res = acInit())) { util_presult("acInit failed", res); goto ac_failure; } u32 wifi = 0; if (R_FAILED(res = ACU_GetWifiStatus(&wifi))) { util_presult("ACU_GetWifiStatus failed", res); fprintf(stderr, "Did you enable Wifi?\n"); goto wifi_check_failure; } if (!wifi) { fprintf(stderr, "Wifi disabled.\n"); goto wifi_check_failure; } if ((sock_ctx = memalign(SOCU_BUFSZ, SOCU_ALIGN)) == NULL) { util_perror("Allocating SOC buffer"); res = MAKERESULT( RL_PERMANENT, RS_OUTOFRESOURCE, RM_SOC, RD_OUT_OF_MEMORY); goto soc_alloc_failure; } if (R_FAILED(res = socInit(sock_ctx, SOCU_BUFSZ))) { util_presult("socInit failed", res); goto soc_failure; } if (R_FAILED(res = hidInit())) { util_presult("hidInit failed", res); goto hid_failure; } if (R_FAILED(res = HIDUSER_EnableAccelerometer())) { util_presult("Failed to enable accelerometer", res); goto accel_failure; } if (R_FAILED(res = ctrollerInit())) { fprintf(stderr, "Do you have a valid IP in\n '" CFG_FILE "'?"); goto failure; } bool isHomebrew = envIsHomebrew(); printf("Press %s to exit.\n", isHomebrew ? EXIT_DESC : "HOME"); fflush(stdout); while (aptMainLoop()) { if (isHomebrew) { if (hidKeysHeld() == EXIT_KEYS) { res = RL_SUCCESS; break; } } if (ctrollerSendHIDInfo()) { util_perror("Sending HID info"); fflush(stderr); for (int i = 3; i > 0; i--) { util_debug_printf("\rRetrying in %ds... ", i); svcSleepThread(1000000000L); } util_debug_printf("\rRetrying now.\x1b[K\n"); } gspWaitForVBlank(); gfxFlushBuffers(); gfxSwapBuffers(); } puts("Exiting..."); failure: HIDUSER_DisableAccelerometer(); accel_failure: hidExit(); hid_failure: socExit(); soc_failure: free(sock_ctx); soc_alloc_failure: wifi_check_failure: acExit(); ac_failure: if (R_FAILED(res)) { util_hang(res); } gfxExit(); return res; }
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 read_savedata(const char* path, void** data, size_t* size) { if(!path || !data || !size) return -1; Result ret = -1; int fail = 0; void* buffer = NULL; fsUseSession(save_session); ret = FSUSER_OpenArchive(&save_archive, ARCHIVE_SAVEDATA, (FS_Path){PATH_EMPTY, 1, (u8*)""}); if(R_FAILED(ret)) { fail = -1; goto readFail; } Handle file = 0; ret = FSUSER_OpenFile(&file, save_archive, fsMakePath(PATH_ASCII, path), FS_OPEN_READ, 0); if(R_FAILED(ret)) { fail = -2; goto readFail; } u64 file_size = 0; ret = FSFILE_GetSize(file, &file_size); buffer = malloc(file_size); if(!buffer) { fail = -3; goto readFail; } u32 bytes_read = 0; ret = FSFILE_Read(file, &bytes_read, 0, buffer, file_size); if(R_FAILED(ret)) { fail = -4; goto readFail; } ret = FSFILE_Close(file); if(R_FAILED(ret)) { fail = -5; goto readFail; } readFail: FSUSER_CloseArchive(save_archive); fsEndUseSession(); if(fail) { sprintf(status, "Failed to read file: %d\n %08lX %08lX", fail, ret, bytes_read); if(buffer) free(buffer); } else { sprintf(status, "Successfully read file.\n %08lX ", bytes_read); *data = buffer; *size = bytes_read; } return ret; }
Result aptInit(void) { Result ret=0; if (AtomicPostIncrement(&aptRefCount)) return 0; // Initialize APT stuff, escape load screen. ret = __apt_initservicehandle(); if(R_FAILED(ret)) goto _fail; if(R_FAILED(ret=APT_GetLockHandle(0x0, &aptLockHandle))) goto _fail; svcCloseHandle(aptuHandle); currentAppId = envGetAptAppId(); svcCreateEvent(&aptStatusEvent, 0); svcCreateEvent(&aptSleepSync, 0); LightLock_Init(&aptStatusMutex); aptStatus=0; if(!aptIsCrippled()) { aptOpenSession(); if(R_FAILED(ret=APT_Initialize(currentAppId, &aptEvents[0], &aptEvents[1])))return ret; aptCloseSession(); aptOpenSession(); if(R_FAILED(ret=APT_Enable(0x0))) goto _fail; aptCloseSession(); // create APT close event svcCreateEvent(&aptEvents[2], 0); // After a cycle of APT_Finalize+APT_Initialize APT thinks the // application is suspended, so we need to tell it to unsuspend us. if (aptIsReinit()) { aptOpenSession(); APT_PrepareToJumpToApplication(0x0); aptCloseSession(); aptOpenSession(); APT_JumpToApplication(0x0, 0x0, 0x0); aptCloseSession(); } aptOpenSession(); if(R_FAILED(ret=APT_NotifyToWait(currentAppId)))goto _fail; aptCloseSession(); // create APT event handler thread aptEventHandlerThread = threadCreate(aptEventHandler, 0x0, APT_HANDLER_STACKSIZE, 0x31, -2, true); // Wait for the state to become APT_RUNNING aptWaitStatusEvent(); } else aptAppStarted(); return 0; _fail: AtomicDecrement(&aptRefCount); return ret; }
/*! Open a file * * @param[in,out] r newlib reentrancy struct * @param[out] fileStruct Pointer to file struct to fill in * @param[in] path Path to open * @param[in] flags Open flags from open(2) * @param[in] mode Permissions to set on create * * @returns 0 for success * @returns -1 for error */ static int sdmc_open(struct _reent *r, void *fileStruct, const char *path, int flags, int mode) { Handle fd; Result rc; u32 sdmc_flags = 0; u32 attributes = 0; FS_Path fs_path; fs_path = sdmc_utf16path(r, path); if(fs_path.data == NULL) return -1; /* get pointer to our data */ sdmc_file_t *file = (sdmc_file_t*)fileStruct; /* check access mode */ switch(flags & O_ACCMODE) { /* read-only: do not allow O_APPEND */ case O_RDONLY: sdmc_flags |= FS_OPEN_READ; if(flags & O_APPEND) { r->_errno = EINVAL; return -1; } break; /* write-only */ case O_WRONLY: sdmc_flags |= FS_OPEN_WRITE; break; /* read and write */ case O_RDWR: sdmc_flags |= (FS_OPEN_READ | FS_OPEN_WRITE); break; /* an invalid option was supplied */ default: r->_errno = EINVAL; return -1; } /* create file */ if(flags & O_CREAT) sdmc_flags |= FS_OPEN_CREATE; /* Test O_EXCL. */ if((flags & O_CREAT) && (flags & O_EXCL)) { rc = FSUSER_CreateFile(sdmcArchive, fs_path, attributes, 0); if(R_FAILED(rc)) { r->_errno = sdmc_translate_error(rc); return -1; } } /* set attributes */ /*if(!(mode & S_IWUSR)) attributes |= FS_ATTRIBUTE_READONLY;*/ /* open the file */ rc = FSUSER_OpenFile(&fd, sdmcArchive, fs_path, sdmc_flags, attributes); if(R_SUCCEEDED(rc)) { if((flags & O_ACCMODE) != O_RDONLY && (flags & O_TRUNC)) { rc = FSFILE_SetSize(fd, 0); if(R_FAILED(rc)) { FSFILE_Close(fd); r->_errno = sdmc_translate_error(rc); return -1; } } file->fd = fd; file->flags = (flags & (O_ACCMODE|O_APPEND|O_SYNC)); file->offset = 0; return 0; } r->_errno = sdmc_translate_error(rc); return -1; }