Beispiel #1
0
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];
}
Beispiel #2
0
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;
}
Beispiel #3
0
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;
}
Beispiel #4
0
static int GDB_ParseCommonThreadInfo(char *out, GDBContext *ctx, int sig)
{
    u32 threadId = ctx->currentThreadId;
    ThreadContext regs;
    s64 dummy;
    u32 core;
    Result r = svcGetDebugThreadContext(&regs, 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, &regs.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;
}
Beispiel #5
0
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];
}
Beispiel #7
0
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;
}
Beispiel #8
0
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;
}
Beispiel #9
0
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.");
    }
}
Beispiel #10
0
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;
}
Beispiel #11
0
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);
}
Beispiel #12
0
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;
    }
Beispiel #13
0
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;
         }
     }
 }
Beispiel #15
0
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;
}
Beispiel #16
0
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];
}
Beispiel #17
0
/*! 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;
}
Beispiel #18
0
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;
}
Beispiel #19
0
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);
}
Beispiel #20
0
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;
}
Beispiel #21
0
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;
}
Beispiel #22
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;
}
Beispiel #23
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;
}
Beispiel #24
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;
}
Beispiel #25
0
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;
	}
}
Beispiel #26
0
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;
}
Beispiel #27
0
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(&region);
                    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;
}
Beispiel #28
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;
}
Beispiel #29
0
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;
}
Beispiel #30
0
/*! 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;
}