bool appIsInstalled(App app) { if(!serviceRequire("am")) { return false; } u32 titleCount; Result titleCountResult = AM_GetTitleCount(appMediatypeToByte(app.mediaType), &titleCount); if(titleCountResult != 0) { platformSetError(serviceParseError((u32) titleCountResult)); return false; } u64 titleIds[titleCount]; Result titleIdsResult = AM_GetTitleIdList(appMediatypeToByte(app.mediaType), titleCount, titleIds); if(titleIdsResult != 0) { platformSetError(serviceParseError((u32) titleIdsResult)); return false; } for(u32 i = 0; i < titleCount; i++) { if(titleIds[i] == app.titleId) { return true; } } return false; }
std::vector<TitleInfo> getTitleInfos(FS_MediaType mediaType) { char tmpStr[16]; extern u8 sysLang; // We got this in main.c u32 count, bytesRead; Result res; Handle fileHandle; TitleInfo tmpTitleInfo; u32 archiveLowPath[4] = {0, 0, mediaType, 0}; const FS_Archive iconArchive = {0x2345678A, {PATH_BINARY, 0x10, (u8*)archiveLowPath}}; const u32 fileLowPath[5] = {0, 0, 2, 0x6E6F6369, 0}; const FS_Path filePath = {PATH_BINARY, 0x14, (const u8*)fileLowPath}; if((res = AM_GetTitleCount(mediaType, &count))) throw titleException(_FILE_, __LINE__, res, "Failed to get title count!"); std::vector<TitleInfo> titleInfos; titleInfos.reserve(count); Buffer<u64> titleIdList(count, false); Buffer<AM_TitleEntry> titleList(count, false); Buffer<Icon> icon(1, false); if((res = AM_GetTitleIdList(mediaType, count, &titleIdList))) throw titleException(_FILE_, __LINE__, res, "Failed to get title ID list!"); if((res = AM_ListTitles(mediaType, count, &titleIdList, &titleList))) throw titleException(_FILE_, __LINE__, res, "Failed to get title list!"); for(u32 i=0; i<count; i++) { // Copy title ID, size and version directly memcpy(&tmpTitleInfo.titleID, &titleList[i].titleID, 18); if(AM_GetTitleProductCode(mediaType, titleIdList[i], tmpStr)) memset(tmpStr, 0, 16); tmpTitleInfo.productCode = tmpStr; // Copy the title ID into our archive low path memcpy(archiveLowPath, &titleIdList[i], 8); icon.clear(); if(!FSUSER_OpenFileDirectly(&fileHandle, iconArchive, filePath, FS_OPEN_READ, 0)) { // Nintendo decided to release a title with an icon entry but with size 0 so this will fail. // Ignoring errors because of this here. FSFILE_Read(fileHandle, &bytesRead, 0, &icon, sizeof(Icon)); FSFILE_Close(fileHandle); } tmpTitleInfo.title = icon[0].appTitles[sysLang].longDesc; tmpTitleInfo.publisher = icon[0].appTitles[sysLang].publisher; memcpy(tmpTitleInfo.icon, icon[0].icon48, 0x1200); titleInfos.push_back(tmpTitleInfo); } return titleInfos; }
std::vector<App> appList(MediaType mediaType) { std::vector<App> titles; if(!serviceRequire("am")) { return titles; } u32 titleCount; Result titleCountResult = AM_GetTitleCount(appMediatypeToByte(mediaType), &titleCount); if(titleCountResult != 0) { platformSetError(serviceParseError((u32) titleCountResult)); return titles; } u64 titleIds[titleCount]; Result titleIdsResult = AM_GetTitleIdList(appMediatypeToByte(mediaType), titleCount, titleIds); if(titleIdsResult != 0) { platformSetError(serviceParseError((u32) titleIdsResult)); return titles; } TitleList titleList[titleCount]; Result titleListResult = AM_ListTitles(appMediatypeToByte(mediaType), titleCount, titleIds, titleList); if(titleListResult != 0) { platformSetError(serviceParseError((u32) titleListResult)); return titles; } for(u32 i = 0; i < titleCount; i++) { u64 titleId = titleList[i].titleID; App app; app.titleId = titleId; app.uniqueId = ((u32*) &titleId)[0]; AM_GetTitleProductCode(appMediatypeToByte(mediaType), titleId, app.productCode); if(strcmp(app.productCode, "") == 0) { strcpy(app.productCode, "<N/A>"); } app.mediaType = mediaType; app.platform = appPlatformFromId(((u16*) &titleId)[3]); app.category = appCategoryFromId(((u16*) &titleId)[2]); app.version = titleList[i].titleVersion; app.size = titleList[i].size; titles.push_back(app); } return titles; }
Result AM_GetPokemonTitleEntryList(AM_TitleMediaEntry** titleList, u32* count) { if (!titleList) return -1; Result ret; u32 ccount = 0; u32 count_SD = 0; u32 count_Card = 0; u32 pkmCount_SD = 0; u32 pkmCount_Card = 0; u32 pkmCount_Total = 0; u64* titleIDs_SD = NULL; u64* titleIDs_Card = NULL; debug_print("AM_GetPokemonTitleEntryList:\n"); ret = AM_GetTitleCount(MEDIATYPE_SD, &count_SD); r(" > AM_GetTitleCount: %lx\n", ret); ret = AM_GetTitleCount(MEDIATYPE_GAME_CARD, &count_Card); r(" > AM_GetTitleCount: %lx\n", ret); titleIDs_SD = (u64*) malloc(count_SD * sizeof(u64)); titleIDs_Card = (u64*) malloc(count_Card * sizeof(u64)); ret = AM_GetTitleIdList(MEDIATYPE_SD, count_SD, titleIDs_SD); r(" > AM_GetTitleIdList: %lx\n", ret); ret = AM_GetTitleIdList(MEDIATYPE_GAME_CARD, count_Card, titleIDs_Card); r(" > AM_GetTitleIdList: %lx\n", ret); debug_print("Count SD : %lu\n", count_SD); debug_print("Count Card: %lu\n", count_Card); for (u32 i = 0; i < count_SD; i++) for (u32 ii = 0; ii < pokemonTitleCount; ii++) if (titleIDs_SD[i] == pokemonTitleIDs[ii]) pkmCount_SD++; for (u32 i = 0; i < count_Card; i++) for (u32 ii = 0; ii < pokemonTitleCount; ii++) if (titleIDs_Card[i] == pokemonTitleIDs[ii]) pkmCount_Card++; pkmCount_Total = pkmCount_SD + pkmCount_Card; if (count) *count = pkmCount_Total; debug_print("PkmCount SD : %lu\n", pkmCount_SD); debug_print("PkmCount Card: %lu\n", pkmCount_Card); debug_print("PkmCount Total: %lu\n", pkmCount_Total); AM_TitleMediaEntry* titleIDs = (AM_TitleMediaEntry*) malloc(pkmCount_Total * sizeof(AM_TitleMediaEntry)); *titleList = titleIDs; debug_print("Caring about card! (%lu/%lu done)\n", ccount, pkmCount_Total); // Card first for the final list. for (u32 i = 0; i < count_Card; i++) for (u32 ii = 0; ii < pokemonTitleCount; ii++) if (titleIDs_Card[i] == pokemonTitleIDs[ii]) { debug_print("Adding title: %016llx (%lu/%lu)", pokemonTitleIDs[ii], ccount+1, pkmCount_Total); titleIDs[ccount] = (AM_TitleMediaEntry) { pokemonTitleIDs[ii], NULL, MEDIATYPE_GAME_CARD }; ret = AM_GetSmdh(&(titleIDs[ccount])); r(" > AM_GetSmdh: %lx\n", ret); ccount++; } debug_print("Caring about SD! (%lu/%lu done)\n", ccount , pkmCount_Total); // SD second for the final list. for (u32 i = 0; i < count_SD; i++) for (u32 ii = 0; ii < pokemonTitleCount; ii++) if (titleIDs_SD[i] == pokemonTitleIDs[ii]) { debug_print("Adding title: %016llx (%lu/%lu)", pokemonTitleIDs[ii], ccount+1, pkmCount_Total); titleIDs[ccount] = (AM_TitleMediaEntry) { pokemonTitleIDs[ii], NULL, MEDIATYPE_SD }; ret = AM_GetSmdh(&(titleIDs[ccount])); r(" > AM_GetSmdh: %lx\n", ret); ccount++; } free(titleIDs_SD); free(titleIDs_Card); return ret; }
Result backupAllExtdata(u8 *filebuffer, size_t bufsize) { Result ret=0; u8 region=0; memset(filebuffer, 0, bufsize); ret = initCfgu(); if(ret!=0) { printf("initCfgu() failed: 0x%08x\n", (unsigned int)ret); gfxFlushBuffers(); gfxSwapBuffers(); return ret; } ret = CFGU_SecureInfoGetRegion(®ion); if(ret!=0) { printf("CFGU_SecureInfoGetRegion() failed: 0x%08x\n", (unsigned int)ret); gfxFlushBuffers(); gfxSwapBuffers(); return ret; } exitCfgu(); amInit(); u32 titleCount = 0; ret = AM_GetTitleCount(mediatype_SDMC, &titleCount); if(ret!=0) { printf("AM_GetTitleCount() failed: 0x%08x\n", (unsigned int)ret); gfxFlushBuffers(); gfxSwapBuffers(); return ret; } u64* titleList = (u64*)malloc(sizeof(u64) * titleCount); ret = AM_GetTitleIdList(mediatype_SDMC, titleCount, titleList); if(ret!=0) { printf("AM_GetTitleIdList() failed: 0x%08x\n", (unsigned int)ret); gfxFlushBuffers(); gfxSwapBuffers(); return ret; } int i; for (i=0; i<titleCount; ++i) { unsigned int title = (titleList[i]>>8) & 0xFFFFFF; dumpArchive(mediatype_SDMC, title, ARCH_EXTDATA, user_extdata_dumpfolder, filebuffer, bufsize); if (title == 0x725) { svcSleepThread(5000000000LL); } } free(titleList); amExit(); for (i=0xE0000000; i<0xE0000100; ++i) { dumpArchive(mediatype_NAND, i, ARCH_SHARED_EXTDATA, shared_extdata_dumpfolder, filebuffer, bufsize); } for (i=0xF0000000; i<0xF0000100; ++i) { dumpArchive(mediatype_NAND, i, ARCH_SHARED_EXTDATA, shared_extdata_dumpfolder, filebuffer, bufsize); } printf("Success!\n"); gfxFlushBuffers(); gfxSwapBuffers(); //svcSleepThread(5000000000LL); return 0; }
bool installTTP(char* path, u8 mediatype) { // Install a TTP file. (needs libzip and installCIA) Result res; FS_Archive archive = {ARCHIVE_SDMC, {PATH_EMPTY, 0, 0}}; FSUSER_OpenArchive(&archive); FSUSER_DeleteDirectoryRecursively(archive, fsMakePath(PATH_ASCII, "/tmp/cias")); FSUSER_CreateDirectory(archive, fsMakePath(PATH_ASCII, "/tmp/cias"), 0); FILE* ttp = fopen(path, "rb"); FILE* tmp = fopen("/tmp/cias/ttp.tmp", "wb"); u32 titlesAmount; AM_GetTitleCount(mediatype, &titlesAmount); u64* titleIDs = malloc(sizeof(u64) * titlesAmount); AM_GetTitleIdList(mediatype, titlesAmount, titleIDs); u32 size; fseek(ttp, 0x19, SEEK_SET); fread(&size, 0x4, 1, ttp); fseek(ttp, 0x1D, SEEK_SET); u32 blockAmount = size / 0x160000; // Finds how many blocks of 4MB you have in the file u32 i; char* block = malloc(0x160000); for (i = 0; i < blockAmount; i++) { fread(block, 1, 0x160000, ttp); fwrite(block, 1, 0x160000, tmp); } if (size % 0x160000 != 0) { fread(block, 1, size-0x160000*blockAmount, ttp); fwrite(block, 1, size-0x160000*blockAmount, tmp); } free(block); fclose(ttp); fclose(tmp); FSUSER_DeleteDirectoryRecursively(archive, fsMakePath(PATH_ASCII, "/tmp/cias")); FSUSER_CreateDirectory(archive, fsMakePath(PATH_ASCII, "/tmp/cias"), 0); Zip *zipHandle = ZipOpen("/tmp/cias/ttp.tmp"); ZipExtract(zipHandle, NULL); ZipClose(zipHandle); Handle ciaDir; FS_Archive fsarchive; u32 actualAmount; FS_DirectoryEntry* entries; FSUSER_DeleteFile(archive, fsMakePath(PATH_ASCII, "/tmp/cias/ttp.tmp")); res = FSUSER_OpenDirectory(&ciaDir, fsarchive, fsMakePath(PATH_ASCII, "/tmp/cias")); if (res != 0) { free(titleIDs); return false; } entries = malloc(256 * sizeof(FS_DirectoryEntry)); res = FSDIR_Read(ciaDir, &actualAmount, 256, entries); if (res != 0) { free(titleIDs); return false; } char* ciaPath; Handle ciaFileHandle; AM_TitleEntry ciaInfo; for (i = 0; i < actualAmount; i++) { ciaPath = malloc(14 + strlen(entries[i].shortName)); strcpy(ciaPath, "/tmp/cias/"); strcat(ciaPath, entries[i].shortName); strcat(ciaPath, ".cia"); FSUSER_OpenFile(&ciaFileHandle, archive, fsMakePath(PATH_ASCII, ciaPath), FS_OPEN_READ, 0); AM_GetCiaFileInfo(mediatype, &ciaInfo, ciaFileHandle); FSFILE_Close(ciaFileHandle); if (ciaInfo.titleID == 0x0004013800000002LL || ciaInfo.titleID == 0x0004013820000002LL) { if (!installCIA(ciaPath, mediatype, titleIDs, entries[i].shortName)) if (!installCIA(ciaPath, mediatype, titleIDs, entries[i].shortName)) // Tries to install the CIA 3 times then give up. If it has to give up, that probably means brick. if (!installCIA(ciaPath, mediatype, titleIDs, entries[i].shortName)) return false; break; } free(ciaPath); } for (i = 0; i < actualAmount; i++) { ciaPath = malloc(14 + strlen(entries[i].shortName)); strcpy(ciaPath, "/tmp/cias/"); strcat(ciaPath, entries[i].shortName); strcat(ciaPath, ".cia"); if (!installCIA(ciaPath, mediatype, titleIDs, entries[i].shortName)) if (!installCIA(ciaPath, mediatype, titleIDs, entries[i].shortName)) // Tries to install the CIA 3 times then give up. If it has to give up, that probably means brick. installCIA(ciaPath, mediatype, titleIDs, entries[i].shortName); free(ciaPath); } FSUSER_DeleteDirectoryRecursively(archive, fsMakePath(PATH_ASCII, "/tmp/cias")); FSUSER_CloseArchive(&archive); free(titleIDs); return true; }