bool arnMigrate() { const static FS_Path aurei = fsMakePath(PATH_ASCII, "/aurei"); const static FS_Path luma = fsMakePath(PATH_ASCII, "/luma"); FS_Archive sdmcArchive = { 0x00000009,{ PATH_EMPTY, 1, (u8*) "" } }; if (FSUSER_OpenArchive(&sdmcArchive) != 0) { std::printf("\nCould not access SD Card (?)\n\n"); return false; } // Check if /luma already existsHandle directory = { 0 }; if (FSUSER_OpenDirectory(NULL, sdmcArchive, luma) == 0) { std::printf("Luma directory already exists, skipping migration..\n"); return true; } if (!renameRecursive(sdmcArchive, "/aurei", "/luma")) { FSUSER_CloseArchive(&sdmcArchive); return false; } // Delete the source directory and check if it succeeds Result res = FSUSER_DeleteDirectoryRecursively(sdmcArchive, aurei); if (res != 0) { std::printf("\nWARN: Could not delete original /aurei (%ld)!\n\n", res); } FSUSER_CloseArchive(&sdmcArchive); return true; }
Result write_savedata(const char* path, const void* data, size_t size) { if(!path || !data || size == 0) return -1; Result ret = -1; int fail = 0; fsUseSession(save_session); ret = FSUSER_OpenArchive(&save_archive, ARCHIVE_SAVEDATA, (FS_Path){PATH_EMPTY, 1, (u8*)""}); if(R_FAILED(ret)) { fail = -1; goto writeFail; } // delete file FSUSER_DeleteFile(save_archive, fsMakePath(PATH_ASCII, path)); FSUSER_ControlArchive(save_archive, ARCHIVE_ACTION_COMMIT_SAVE_DATA, NULL, 0, NULL, 0); Handle file = 0; ret = FSUSER_OpenFile(&file, save_archive, fsMakePath(PATH_ASCII, path), FS_OPEN_CREATE | FS_OPEN_WRITE, 0); if(R_FAILED(ret)) { fail = -2; goto writeFail; } u32 bytes_written = 0; ret = FSFILE_Write(file, &bytes_written, 0, data, size, FS_WRITE_FLUSH | FS_WRITE_UPDATE_TIME); if(R_FAILED(ret)) { fail = -3; goto writeFail; } ret = FSFILE_Close(file); if(R_FAILED(ret)) { fail = -4; goto writeFail; } ret = FSUSER_ControlArchive(save_archive, ARCHIVE_ACTION_COMMIT_SAVE_DATA, NULL, 0, NULL, 0); if(R_FAILED(ret)) fail = -5; writeFail: FSUSER_CloseArchive(save_archive); fsEndUseSession(); if(fail) sprintf(status, "Failed to write to file: %d\n %08lX %08lX", fail, ret, bytes_written); else sprintf(status, "Successfully wrote to file!\n %08lX ", bytes_written); return ret; }
bool renameRecursive(const FS_Archive archive, const std::string source, const std::string target) { const FS_Path sourcePath = fsMakePath(PATH_ASCII, source.c_str()); const FS_Path targetPath = fsMakePath(PATH_ASCII, target.c_str()); // Open source directory Handle directory = NULL; if (FSUSER_OpenDirectory(&directory, archive, sourcePath) != 0) { std::printf("\nCould not open %s\n\n", source.c_str()); return false; } // Make target directory if (FSUSER_CreateDirectory(archive, targetPath, FS_ATTRIBUTE_DIRECTORY) != 0) { std::printf("\nCould not create %s\n\n", target.c_str()); return false; } u32 fileRead = 0; while (true) { FS_DirectoryEntry entry = {}; FSDIR_Read(directory, &fileRead, 1, &entry); if (!fileRead) { break; } // Convert name to ASCII (just cut the other bytes) char name8[262] = { 0 }; for (size_t i = 0; i < 262; i++) { name8[i] = entry.name[i] % 0xff; } std::string filePath = std::string("/") + name8; std::string from = source + filePath; std::string to = target + filePath; // Is a directory? Recurse rename if (entry.attributes & FS_ATTRIBUTE_DIRECTORY) { std::printf(" %s -> %s (DIR)\n", from.c_str(), to.c_str()); if (!renameRecursive(archive, source + filePath, target + filePath)) { return false; } } else { FS_Path sourceFilePath = fsMakePath(PATH_ASCII, from.c_str()); FS_Path targetFilePath = fsMakePath(PATH_ASCII, to.c_str()); if (FSUSER_RenameFile(archive, sourceFilePath, archive, targetFilePath) != 0) { std::printf("\nCould not rename %s\n\n", (char*)sourceFilePath.data); return false; } std::printf(" %s -> %s\n", (char*)sourceFilePath.data, (char*)targetFilePath.data); } } return true; }
Directory::Directory(FS_Archive archive, const std::u16string& root) { load = false; err = 0; Handle handle; list.clear(); err = FSUSER_OpenDirectory(&handle, archive, fsMakePath(PATH_UTF16, root.c_str())); if (R_FAILED(err)) { return; } u32 result = 0; do { FS_DirectoryEntry item; err = FSDIR_Read(handle, &result, 1, &item); if (result == 1) { list.push_back(item); } } while(result); err = FSDIR_Close(handle); if (R_FAILED(err)) { list.clear(); return; } load = true; }
static int lua_addCert(lua_State *L) { int argc = lua_gettop(L); #ifndef SKIP_ERROR_HANDLING if (argc != 1) return luaL_error(L, "wrong number of arguments"); #endif const char *text = luaL_checkstring(L, 1); fileStream fileHandle; if (strncmp("romfs:/",text,7) == 0){ fileHandle.isRomfs = true; FILE* handle = fopen(text,"r"); #ifndef SKIP_ERROR_HANDLING if (handle == NULL) return luaL_error(L, "file doesn't exist."); #endif fileHandle.handle = (u32)handle; }else{ fileHandle.isRomfs = false; FS_Path filePath = fsMakePath(PATH_ASCII, text); FS_Archive script=(FS_Archive){ARCHIVE_SDMC, (FS_Path){PATH_EMPTY, 1, (u8*)""}}; Result ret = FSUSER_OpenFileDirectly( &fileHandle.handle, script, filePath, FS_OPEN_READ, 0x00000000); #ifndef SKIP_ERROR_HANDLING if (ret) return luaL_error(L, "file doesn't exist."); #endif } u64 cert_size; u32 bytesRead; FS_GetSize(&fileHandle, &cert_size); u8* cert = (u8*)malloc(cert_size); FS_Read(&fileHandle, &bytesRead, 0, cert, cert_size); sslcAddTrustedRootCA(RootCertChain_contexthandle, cert, cert_size, NULL); free(cert); FS_Close(&fileHandle); return 0; }
Result FS_ReadFile(const char* path, void* dst, u64 maxSize, FS_Archive archive, u32* bytesRead) { if (!path || !dst || !archive || !bytesRead) return -1; Result ret; u64 size; Handle fileHandle; debug_print("FS_ReadFile:\n"); ret = FSUSER_OpenFile(&fileHandle, archive, fsMakePath(PATH_ASCII, path), FS_OPEN_READ, FS_ATTRIBUTE_NONE); r(" > FSUSER_OpenFile: %lx\n", ret); if (R_FAILED(ret)) return ret; ret = FSFILE_GetSize(fileHandle, &size); r(" > FSFILE_GetSize: %lx\n", ret); if (R_FAILED(ret) || size > maxSize) ret = -2; if (R_SUCCEEDED(ret)) { ret = FSFILE_Read(fileHandle, bytesRead, 0x0, dst, size); r(" > FSFILE_Read: %lx\n", ret); if (R_FAILED(ret) || *bytesRead < size) ret = -3; } FSFILE_Close(fileHandle); r(" > FSFILE_Close\n"); return ret; }
struct VDir* VDirOpen(const char* path) { struct VDir3DS* vd3d = malloc(sizeof(struct VDir3DS)); if (!vd3d) { return 0; } // TODO: Use UTF-16 FS_Path newPath = fsMakePath(PATH_ASCII, path); Result res = FSUSER_OpenDirectory(&vd3d->handle, sdmcArchive, newPath); if (res & 0xFFFC03FF) { free(vd3d); return 0; } vd3d->path = strdup(path); vd3d->d.close = _vd3dClose; vd3d->d.rewind = _vd3dRewind; vd3d->d.listNext = _vd3dListNext; vd3d->d.openFile = _vd3dOpenFile; vd3d->d.openDir = _vd3dOpenDir; vd3d->vde.d.name = _vd3deName; vd3d->vde.d.type = _vd3deType; return &vd3d->d; }
struct VFile* VFileOpen3DS(FS_Archive* archive, const char* path, int flags) { struct VFile3DS* vf3d = malloc(sizeof(struct VFile3DS)); if (!vf3d) { return 0; } uint16_t utf16Path[PATH_MAX + 1]; ssize_t units = utf8_to_utf16(utf16Path, (const uint8_t*) path, PATH_MAX); utf16Path[units] = 0; FS_Path newPath = fsMakePath(PATH_UTF16, utf16Path); Result res = FSUSER_OpenFile(&vf3d->handle, *archive, newPath, flags, 0); if (res & 0xFFFC03FF) { free(vf3d); return 0; } vf3d->offset = 0; vf3d->d.close = _vf3dClose; vf3d->d.seek = _vf3dSeek; vf3d->d.read = _vf3dRead; vf3d->d.readline = VFileReadline; vf3d->d.write = _vf3dWrite; vf3d->d.map = _vf3dMap; vf3d->d.unmap = _vf3dUnmap; vf3d->d.truncate = _vf3dTruncate; vf3d->d.size = _vf3dSize; vf3d->d.sync = _vf3dSync; return &vf3d->d; }
Result FS_WriteFile(const char* path, const void* src, u64 size, FS_Archive archive, u32* bytesWritten) { if (!path || !src || !archive || !bytesWritten) return -1; Result ret; Handle fileHandle; debug_print("FS_WriteFile:\n"); ret = FSUSER_OpenFile(&fileHandle, archive, fsMakePath(PATH_ASCII, path), FS_OPEN_WRITE | FS_OPEN_CREATE, FS_ATTRIBUTE_NONE); r(" > FSUSER_OpenFile: %lx\n", ret); if (R_FAILED(ret)) return ret; if (R_SUCCEEDED(ret)) { ret = FSFILE_Write(fileHandle, bytesWritten, 0L, src, size, FS_WRITE_FLUSH); r(" > FSFILE_Write: %lx\n", ret); if (R_FAILED(ret) || *bytesWritten != size) ret = -2; } FSFILE_Close(fileHandle); r(" > FSFILE_Close\n"); return ret; }
struct VDir* VDirOpen(const char* path) { struct VDir3DS* vd3d = malloc(sizeof(struct VDir3DS)); if (!vd3d) { return 0; } uint16_t utf16Path[PATH_MAX + 1]; ssize_t units = utf8_to_utf16(utf16Path, (const uint8_t*) path, PATH_MAX); utf16Path[units] = 0; FS_Path newPath = fsMakePath(PATH_UTF16, utf16Path); Result res = FSUSER_OpenDirectory(&vd3d->handle, sdmcArchive, newPath); if (res & 0xFFFC03FF) { free(vd3d); return 0; } vd3d->path = strdup(path); vd3d->d.close = _vd3dClose; vd3d->d.rewind = _vd3dRewind; vd3d->d.listNext = _vd3dListNext; vd3d->d.openFile = _vd3dOpenFile; vd3d->d.openDir = _vd3dOpenDir; vd3d->d.deleteFile = _vd3dDeleteFile; vd3d->vde.d.name = _vd3deName; vd3d->vde.d.type = _vd3deType; return &vd3d->d; }
struct VFile* VFileOpen3DS(FS_Archive* archive, const char* path, int flags) { struct VFile3DS* vf3d = malloc(sizeof(struct VFile3DS)); if (!vf3d) { return 0; } // TODO: Use UTF-16 FS_Path newPath = fsMakePath(PATH_ASCII, path); Result res = FSUSER_OpenFile(&vf3d->handle, *archive, newPath, flags, 0); if (res & 0xFFFC03FF) { free(vf3d); return 0; } vf3d->offset = 0; vf3d->d.close = _vf3dClose; vf3d->d.seek = _vf3dSeek; vf3d->d.read = _vf3dRead; vf3d->d.readline = VFileReadline; vf3d->d.write = _vf3dWrite; vf3d->d.map = _vf3dMap; vf3d->d.unmap = _vf3dUnmap; vf3d->d.truncate = _vf3dTruncate; vf3d->d.size = _vf3dSize; vf3d->d.sync = _vf3dSync; return &vf3d->d; }
static void _vd3dRewind(struct VDir* vd) { struct VDir3DS* vd3d = (struct VDir3DS*) vd; FSDIR_Close(vd3d->handle); // TODO: Use UTF-16 FS_Path newPath = fsMakePath(PATH_ASCII, vd3d->path); FSUSER_OpenDirectory(&vd3d->handle, sdmcArchive, newPath); }
Result FSCIA_Init(u64 titleid, FS_MediaType mediatype) { Result ret = 1; debug_print("FSCIA_Init:\n"); if (!saveInitialized) { lowPath[0] = mediatype; lowPath[1] = titleid; /// titleid & 0xFFFFFFFF lowPath[2] = titleid >> 32; // (titleid >> 32) & 0xFFFFFFFF debug_print(" > [0]: 0x%016lx\n", lowPath[0]); debug_print(" > [1]: 0x%016lx\n", lowPath[1]); debug_print(" > [2]: 0x%016lx\n", lowPath[2]); ret = FSUSER_OpenArchive(&saveArchive, ARCHIVE_USER_SAVEDATA, (FS_Path) { PATH_BINARY, 12, lowPath }); r(" > FSUSER_OpenArchive: %lx\n", ret); saveInitialized = R_SUCCEEDED(ret); // true if (!saveInitialized) { ret = FSUSER_OpenArchive(&saveArchive, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, NULL)); r(" > FSUSER_OpenArchive: %lx\n", ret); saveInitialized = R_SUCCEEDED(ret); // true } }
// don't bother with log messages, this is only used before the logging is started int deleteFile(const char *path) { FS_Path filePath = fsMakePath(PATH_ASCII, path); if(R_FAILED(FSUSER_DeleteFile(sdmcArchive, filePath))) { return(-1); } return(0); }
static void _vd3dRewind(struct VDir* vd) { struct VDir3DS* vd3d = (struct VDir3DS*) vd; FSDIR_Close(vd3d->handle); uint16_t utf16Path[PATH_MAX + 1]; ssize_t units = utf8_to_utf16(utf16Path, (const uint8_t*) vd3d->path, PATH_MAX); utf16Path[units] = 0; FS_Path newPath = fsMakePath(PATH_UTF16, utf16Path); FSUSER_OpenDirectory(&vd3d->handle, sdmcArchive, newPath); }
Result initFS() { u32 extdata_archive_lowpathdata[3] = { MEDIATYPE_NAND, 0xf000000e, 0 }; extdata_archive = (FS_Archive ) { ARCHIVE_SHARED_EXTDATA, (FS_Path ) { PATH_BINARY, 0xC, (u8*) extdata_archive_lowpathdata } }; verListPath = fsMakePath(PATH_ASCII, "/versionList.dat"); return FSUSER_OpenArchive(&extdata_archive); }
Handle openDirectory(const char *path) { Handle dir; LOG_VERBOSE("openDirectory: %s", path); FS_Path filePath = fsMakePath(PATH_ASCII, path); if(R_FAILED(FSUSER_OpenDirectory(&dir, sdmcArchive, filePath))) { LOG_VERBOSE("FSUSER_OpenDirectory failed."); return(0); } LOG_VERBOSE("Directory opened successfully."); return(dir); }
Handle openFileHandle(const char *path, u32 openFlags) { Handle fileHandle = 0; LOG_VERBOSE("openFileHandle: %s, %d", path, openFlags); FS_Path filePath = fsMakePath(PATH_ASCII, path); if(R_FAILED(FSUSER_OpenFile(&fileHandle, sdmcArchive, filePath, openFlags, 0))) { LOG_VERBOSE("FSUSER_OpenFile failed."); return(0); } LOG_VERBOSE("File opened successfully."); return(fileHandle); }
Result FS_DeleteFile(const char* path, FS_Archive archive) { if (!path || !archive) return -1; Result ret; debug_print("FS_DeleteFile:\n"); ret = FSUSER_DeleteFile(archive, fsMakePath(PATH_ASCII, path)); r(" > FSUSER_DeleteFile: %lx\n", ret); return ret; }
void GBAConfigDirectory(char* out, size_t outLength) { struct VFile* portable; #ifdef _WIN32 wchar_t wpath[MAX_PATH]; wchar_t wprojectName[MAX_PATH]; MultiByteToWideChar(CP_UTF8, 0, projectName, -1, wprojectName, MAX_PATH); HMODULE hModule = GetModuleHandleW(NULL); GetModuleFileNameW(hModule, wpath, MAX_PATH); PathRemoveFileSpecW(wpath); WideCharToMultiByte(CP_UTF8, 0, wpath, -1, out, outLength, 0, 0); StringCchCatA(out, outLength, "\\portable.ini"); portable = VFileOpen(out, O_RDONLY); if (portable) { portable->close(portable); } else { wchar_t* home; SHGetKnownFolderPath(&FOLDERID_RoamingAppData, 0, NULL, &home); StringCchPrintfW(wpath, MAX_PATH, L"%ws\\%ws", home, wprojectName); CoTaskMemFree(home); CreateDirectoryW(wpath, NULL); } WideCharToMultiByte(CP_UTF8, 0, wpath, -1, out, outLength, 0, 0); #elif defined(PSP2) UNUSED(portable); snprintf(out, outLength, "cache0:/%s", projectName); sceIoMkdir(out, 0777); #elif defined(GEKKO) UNUSED(portable); snprintf(out, outLength, "/%s", projectName); mkdir(out, 0777); #elif defined(_3DS) UNUSED(portable); snprintf(out, outLength, "/%s", projectName); FSUSER_CreateDirectory(sdmcArchive, fsMakePath(PATH_ASCII, out), 0); #else getcwd(out, outLength); strncat(out, PATH_SEP "portable.ini", outLength - strlen(out)); portable = VFileOpen(out, O_RDONLY); if (portable) { getcwd(out, outLength); portable->close(portable); return; } char* home = getenv("HOME"); snprintf(out, outLength, "%s/.config", home); mkdir(out, 0755); snprintf(out, outLength, "%s/.config/%s", home, binaryName); mkdir(out, 0755); #endif }
std::vector<std::string> listPayloads() { std::vector<std::string> files = {}; FS_Archive sdmcArchive; // Open SD card if (FSUSER_OpenArchive(&sdmcArchive, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, NULL)) != 0) { logPrintf("\nCould not access SD Card (?)\n\n"); return files; } // Open source directory Handle directory = 0; if (FSUSER_OpenDirectory(&directory, sdmcArchive, fsMakePath(PATH_ASCII, "/luma/payloads")) != 0) { logPrintf("\nCould not open /luma/payloads\n\n"); FSUSER_CloseArchive(sdmcArchive); return files; } u32 fileRead = 0; while (true) { FS_DirectoryEntry entry = {}; FSDIR_Read(directory, &fileRead, 1, &entry); if (!fileRead) { break; } // Convert name to ASCII (just cut the other bytes) and compare with prefix char name8[262] = { 0 }; for (size_t i = 0; i < 262; i++) { name8[i] = entry.name[i] % 0xff; } files.push_back(std::string(name8)); } FSUSER_CloseArchive(sdmcArchive); return files; }
//same thing as contructor. can be used to reinit dirList too void dirList::reassign(const std::u16string p) { entry.clear(); FSUSER_OpenDirectory(&d, a, fsMakePath(PATH_UTF16, p.data())); u32 read = 0; do { FS_DirectoryEntry getEnt; FSDIR_Read(d, &read, 1, &getEnt); entry.push_back(getEnt); }while(read > 0); FSDIR_Close(d); }
static bool _vd3dDeleteFile(struct VDir* vd, const char* path) { struct VDir3DS* vd3d = (struct VDir3DS*) vd; if (!path) { return 0; } const char* dir = vd3d->path; char* combined = malloc(sizeof(char) * (strlen(path) + strlen(dir) + 2)); sprintf(combined, "%s/%s", dir, path); uint16_t utf16Path[PATH_MAX + 1]; ssize_t units = utf8_to_utf16(utf16Path, (const uint8_t*) combined, PATH_MAX); utf16Path[units] = 0; FS_Path newPath = fsMakePath(PATH_UTF16, utf16Path); bool ret = !FSUSER_DeleteFile(sdmcArchive, newPath); free(combined); return ret; }
static Result action_import_twl_save_open_src(void* data, u32 index, u32* handle) { import_twl_save_data* importData = (import_twl_save_data*) data; Result res = 0; char path[FILE_PATH_MAX]; snprintf(path, sizeof(path), "/fbi/save/%s.sav", importData->title->productCode); FS_Path* fsPath = util_make_path_utf8(path); if(fsPath != NULL) { res = FSUSER_OpenFileDirectly(handle, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, ""), *fsPath, FS_OPEN_READ, 0); util_free_path_utf8(fsPath); } else { res = R_FBI_OUT_OF_MEMORY; } return res; }
static int lua_download(lua_State *L){ int argc = lua_gettop(L); #ifndef SKIP_ERROR_HANDLING if (argc != 2) return luaL_error(L, "wrong number of arguments"); #endif const char* url = luaL_checkstring(L,1); const char* file = luaL_checkstring(L,2); httpcContext context; Result ret = httpcOpenContext(&context, (char*)url , 0); #ifndef SKIP_ERROR_HANDLING if(ret==0){ #endif httpcBeginRequest(&context); /*httpcReqStatus loading; httpcGetRequestState(&context, &loading); while (loading == 0x5){ httpcGetRequestState(&context, &loading); }*/ u32 statuscode=0; u32 contentsize=0; httpcGetResponseStatusCode(&context, &statuscode, 0); #ifndef SKIP_ERROR_HANDLING if (statuscode != 200) luaL_error(L, "download request error"); #endif httpcGetDownloadSizeState(&context, NULL, &contentsize); u8* buf = (u8*)malloc(contentsize); memset(buf, 0, contentsize); httpcDownloadData(&context, buf, contentsize, NULL); Handle fileHandle; u32 bytesWritten; FS_Archive sdmcArchive=(FS_Archive){ARCHIVE_SDMC, (FS_Path){PATH_EMPTY, 1, (u8*)""}}; FS_Path filePath=fsMakePath(PATH_ASCII, file); FSUSER_OpenFileDirectly( &fileHandle, sdmcArchive, filePath, FS_OPEN_CREATE|FS_OPEN_WRITE, 0x00000000); FSFILE_Write(fileHandle, &bytesWritten, 0, buf, contentsize,0x10001); FSFILE_Close(fileHandle); svcCloseHandle(fileHandle); free(buf); #ifndef SKIP_ERROR_HANDLING }else luaL_error(L, "error opening url"); #endif httpcCloseContext(&context); return 0; }
dirList::dirList(FS_Archive arch, const std::u16string p) { //keep archive data a = arch; //save path path = p; //open path given by p FSUSER_OpenDirectory(&d, a, fsMakePath(PATH_UTF16, p.data())); //loop until we stop reading anymore entries u32 read = 0; do { FS_DirectoryEntry getEnt; FSDIR_Read(d, &read, 1, &getEnt); entry.push_back(getEnt); }while(read > 0); FSDIR_Close(d); }
void task_populate_titledb_update_status(list_item* item) { titledb_info* info = (titledb_info*) item->data; info->cia.installed = false; info->tdsx.installed = false; if(info->cia.exists) { AM_TitleEntry entry; info->cia.installed = R_SUCCEEDED(AM_GetTitleInfo(fs_get_title_destination(info->cia.titleId), 1, &info->cia.titleId, &entry)) && task_populate_titledb_cache_get(info->id, true, &info->cia.installedInfo); } if(info->tdsx.exists) { char path3dsx[FILE_PATH_MAX]; fs_make_3dsx_path(path3dsx, info->meta.shortDescription, sizeof(path3dsx)); FS_Path* fsPath = fs_make_path_utf8(path3dsx); if(fsPath != NULL) { Handle handle = 0; if(R_SUCCEEDED(FSUSER_OpenFileDirectly(&handle, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, ""), *fsPath, FS_OPEN_READ, 0))) { FSFILE_Close(handle); info->tdsx.installed = task_populate_titledb_cache_get(info->id, false, &info->tdsx.installedInfo); } fs_free_path_utf8(fsPath); } } if((info->cia.installed && info->cia.installedInfo.id != info->cia.id) || (info->tdsx.installed && info->tdsx.installedInfo.id != info->tdsx.id)) { item->color = COLOR_TITLEDB_OUTDATED; } else if(info->cia.installed || info->tdsx.installed) { item->color = COLOR_TITLEDB_INSTALLED; } else { item->color = COLOR_TITLEDB_NOT_INSTALLED; } }
void files_open_twl_sound() { files_open(ARCHIVE_TWL_SOUND, fsMakePath(PATH_EMPTY, "")); }
void files_open_twl_photo() { files_open(ARCHIVE_TWL_PHOTO, fsMakePath(PATH_EMPTY, "")); }
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; }