#include #include #include #include #include #include #include "ui.h" #include "data.h" #include "file.h" #include "util.h" #include "ex.h" static ui::menu userMenu, titleMenu, devMenu; extern ui::menu folderMenu; extern std::vector usrNav, ttlNav, fldNav; namespace ui { void clsUserPrep() { userMenu.reset(); userMenu.setParams(42, 98, 424); for(unsigned i = 0; i < data::users.size(); i++) userMenu.addOpt(data::users[i].getUsername()); } void clsTitlePrep(data::user& u) { titleMenu.reset(); titleMenu.setParams(42, 98, 424); for(unsigned i = 0; i < u.titles.size(); i++) titleMenu.addOpt(u.titles[i].getTitle()); } void clsFolderPrep(data::user& usr, data::titledata& dat) { folderMenu.setParams(488, 98, 762); folderMenu.reset(); util::makeTitleDir(usr, dat); std::string scanPath = util::getTitleDir(usr, dat); fs::dirList list(scanPath); folderMenu.addOpt("New"); for(unsigned i = 0; i < list.getCount(); i++) folderMenu.addOpt(list.getItem(i)); folderMenu.adjust(); } void classicUserMenuUpdate(const uint64_t& down, const uint64_t& held, const touchPosition& p) { userMenu.handleInput(down, held, p); userMenu.draw(mnuTxt); for(unsigned i = 0; i < usrNav.size(); i++) usrNav[i].update(p); if(down & KEY_A || usrNav[0].getEvent() == BUTTON_RELEASED) { data::curUser = data::users[userMenu.getSelected()]; clsTitlePrep(data::curUser); mstate = CLS_TTL; } else if(down & KEY_Y || usrNav[1].getEvent() == BUTTON_RELEASED) { for(unsigned i = 0; i < data::users.size(); i++) fs::dumpAllUserSaves(data::users[i]); } else if(down & KEY_X || usrNav[2].getEvent() == BUTTON_RELEASED) { std::remove(std::string(fs::getWorkDir() + "cls.txt").c_str()); clsMode = false; mstate = USR_SEL; } else if(down & KEY_MINUS || usrNav[3].getEvent() == BUTTON_RELEASED) { fsdevUnmountDevice("sv"); ui::exMenuPrep(); ui::mstate = EX_MNU; } } void classicTitleMenuUpdate(const uint64_t& down, const uint64_t& held, const touchPosition& p) { titleMenu.handleInput(down, held, p); titleMenu.draw(mnuTxt); for(unsigned i = 0; i < ttlNav.size(); i++) ttlNav[i].update(p); if(down & KEY_A || ttlNav[0].getEvent() == BUTTON_RELEASED) { data::curData = data::curUser.titles[titleMenu.getSelected()]; if(fs::mountSave(data::curUser, data::curData)) { util::makeTitleDir(data::curUser, data::curData); clsFolderPrep(data::curUser, data::curData); folderMenuInfo = util::getInfoString(data::curUser, data::curData); mstate = CLS_FLD; } } else if(down & KEY_Y || ttlNav[1].getEvent() == BUTTON_RELEASED) { fs::dumpAllUserSaves(data::curUser); } else if(down & KEY_X || ttlNav[2].getEvent() == BUTTON_RELEASED) { std::string confStr = "Are you 100% sure you want to add \"" + data::curUser.titles[titleMenu.getSelected()].getTitle() + \ "\" to your blacklist?"; if(ui::confirm(confStr)) data::blacklistAdd(data::curUser, data::curUser.titles[titleMenu.getSelected()]); } else if(down & KEY_B || ttlNav[3].getEvent() == BUTTON_RELEASED) mstate = CLS_USR; } void classicFolderMenuUpdate(const uint64_t& down, const uint64_t& held, const touchPosition& p) { titleMenu.draw(mnuTxt); folderMenu.handleInput(down, held, p); folderMenu.draw(mnuTxt); for(unsigned i = 0; i < fldNav.size(); i++) fldNav[i].update(p); if(down & KEY_A || fldNav[0].getEvent() == BUTTON_RELEASED || folderMenu.getTouchEvent() == MENU_DOUBLE_REL) { if(folderMenu.getSelected() == 0) { std::string folder; //Add back 3DS shortcut thing if(held & KEY_R) folder = data::curUser.getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YMD); else if(held & KEY_L) folder = data::curUser.getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YDM); else if(held & KEY_ZL) folder = data::curUser.getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_HOYSTE); else { const std::string dict[] = { util::getDateTime(util::DATE_FMT_YMD).c_str(), util::getDateTime(util::DATE_FMT_YDM).c_str(), util::getDateTime(util::DATE_FMT_HOYSTE).c_str(), data::curUser.getUsernameSafe().c_str(), data::curData.getTitle().length() < 24 ? data::curData.getTitleSafe() : util::generateAbbrev(data::curData) }; folder = util::getStringInput("", "New Folder", 64, 5, dict); } if(!folder.empty()) { std::string path = util::getTitleDir(data::curUser, data::curData) + "/" + folder; mkdir(path.c_str(), 777); path += "/"; std::string root = "sv:/"; fs::copyDirToDir(root, path); clsFolderPrep(data::curUser, data::curData); } } else { std::string scanPath = util::getTitleDir(data::curUser, data::curData); fs::dirList list(scanPath); std::string folderName = list.getItem(folderMenu.getSelected() - 1); if(confirm("Are you sure you want to overwrite \"" + folderName + "\"?")) { std::string toPath = util::getTitleDir(data::curUser, data::curData) + folderName + "/"; //Delete and recreate fs::delDir(toPath); mkdir(toPath.c_str(), 777); std::string root = "sv:/"; fs::copyDirToDir(root, toPath); } } } else if(down & KEY_Y || fldNav[1].getEvent() == BUTTON_RELEASED) { if(data::curData.getType() != FsSaveDataType_SystemBcat) { if(folderMenu.getSelected() > 0) { std::string scanPath = util::getTitleDir(data::curUser, data::curData); fs::dirList list(scanPath); std::string folderName = list.getItem(folderMenu.getSelected() - 1); if(confirm("Are you sure you want to restore \"" + folderName + "\"?")) { std::string fromPath = util::getTitleDir(data::curUser, data::curData) + folderName + "/"; std::string root = "sv:/"; fs::delDir(root); fsdevCommitDevice("sv"); fs::copyDirToDirCommit(fromPath, root, "sv"); } } } else ui::showMessage("Writing data to system save data is not allowed currently. It CAN brick your system.", "Sorry, bro:"); } else if(down & KEY_X || fldNav[2].getEvent() == BUTTON_RELEASED) { if(folderMenu.getSelected() > 0) { std::string scanPath = util::getTitleDir(data::curUser, data::curData); fs::dirList list(scanPath); std::string folderName = list.getItem(folderMenu.getSelected() - 1); if(confirm("Are you sure you want to delete \"" + folderName + "\"?")) { std::string delPath = scanPath + folderName + "/"; fs::delDir(delPath); } clsFolderPrep(data::curUser, data::curData); } } else if(down & KEY_MINUS) { advModePrep("sv:/", true); mstate = ADV_MDE; } else if(down & KEY_B || fldNav[3].getEvent() == BUTTON_RELEASED) { fsdevUnmountDevice("sv"); mstate = CLS_TTL; } } void exMenuPrep() { devMenu.reset(); devMenu.setParams(42, 98, 424); devMenu.addOpt("SD to SD Browser"); devMenu.addOpt("Bis: PRODINFOF"); devMenu.addOpt("Bis: SAFE"); devMenu.addOpt("Bis: SYSTEM"); devMenu.addOpt("Bis: USER"); devMenu.addOpt("NAND Backup (exFat)"); devMenu.addOpt("NAND Backup (FAT32)"); devMenu.addOpt("Remove Downloaded Update"); devMenu.addOpt("Terminate Process ID"); devMenu.addOpt("Mount System Save ID"); devMenu.addOpt("Mount Process RomFS"); } void updateExMenu(const uint64_t& down, const uint64_t& held, const touchPosition& p) { devMenu.handleInput(down, held, p); if(down & KEY_A) { FsFileSystem sv; data::curData.setType(FsSaveDataType_SystemBcat); switch(devMenu.getSelected()) { case 0: data::curData.setType(FsSaveDataType_Bcat); fsdevUnmountDevice("sv"); advModePrep("sdmc:/", false); mstate = ADV_MDE; prevState = EX_MNU; break; case 1: fsdevUnmountDevice("sv"); fsOpenBisFileSystem(&sv, FsBisPartitionId_CalibrationFile, ""); fsdevMountDevice("prodInfo-f", sv); advModePrep("profInfo-f:/", false); mstate = ADV_MDE; prevState = EX_MNU; break; case 2: fsdevUnmountDevice("sv"); fsOpenBisFileSystem(&sv, FsBisPartitionId_SafeMode, ""); fsdevMountDevice("safe", sv); advModePrep("safe:/", false); mstate = ADV_MDE; prevState = EX_MNU; break; case 3: fsdevUnmountDevice("sv"); fsOpenBisFileSystem(&sv, FsBisPartitionId_System, ""); fsdevMountDevice("sys", sv); advModePrep("sys:/", false); mstate = ADV_MDE; prevState = EX_MNU; break; case 4: fsdevUnmountDevice("sv"); fsOpenBisFileSystem(&sv, FsBisPartitionId_User, ""); fsdevMountDevice("user", sv); advModePrep("user:/", false); mstate = ADV_MDE; prevState = EX_MNU; break; case 5: { fsdevUnmountDevice("sv"); FsStorage nand; fsOpenBisStorage(&nand, FsBisPartitionId_UserDataRoot); s64 nandSize = 0, offset = 0; fsStorageGetSize(&nand, &nandSize); std::fstream nandOut("sdmc:/JKSV/nand.bin", std::ios::out | std::ios::binary); size_t nandBuffSize = 1024 * 1024 * 4; uint8_t *nandBuff = new uint8_t[nandBuffSize]; progBar nandProg(nandSize); while(offset < nandSize) { size_t readLen = 0; if(offset + nandBuffSize < nandSize) readLen = nandBuffSize; else readLen = nandSize - offset; if(R_SUCCEEDED(fsStorageRead(&nand, offset, nandBuff, readLen))) { nandOut.write((char *)nandBuff, readLen); offset += readLen; } else { ui::showMessage("Something went wrong while dumping your NAND.", "*ERROR*"); break; } gfxBeginFrame(); nandProg.update(offset); nandProg.draw("", "Copying NAND"); gfxEndFrame(); } delete[] nandBuff; nandOut.close(); fsStorageClose(&nand); } break; case 6: { unsigned fcount = 1; fsdevUnmountDevice("sv"); FsStorage nand; fsOpenBisStorage(&nand, FsBisPartitionId_UserDataRoot); s64 nandSize = 0, offset = 0; fsStorageGetSize(&nand, &nandSize); std::fstream nandOut("sdmc:/JKSV/nand.bin.00", std::ios::out | std::ios::binary); size_t nandBuffSize = 1024 * 1024 * 3; uint8_t *nandBuff = new uint8_t[nandBuffSize]; progBar nandProg(nandSize); while(offset < nandSize) { size_t readLen = 0; if(offset + nandBuffSize < nandSize) readLen = nandBuffSize; else readLen = nandSize - offset; if(R_SUCCEEDED(fsStorageRead(&nand, offset, nandBuff, readLen))) { if((size_t)nandOut.tellp() + readLen >= 0x100000000) { nandOut.close(); char newPath[128]; sprintf(newPath, "sdmc:/JKSV/nand.bin.%02d", fcount++); nandOut.open(newPath, std::ios::out | std::ios::binary); } nandOut.write((char *)nandBuff, readLen); offset += readLen; } else { ui::showMessage("Something went wrong while dumping your NAND.", "*ERROR*"); break; } gfxBeginFrame(); nandProg.update(offset); nandProg.draw("", "Copying NAND"); gfxEndFrame(); } delete[] nandBuff; nandOut.close(); fsStorageClose(&nand); } break; case 7: { fsdevUnmountDevice("sv"); fsOpenBisFileSystem(&sv, FsBisPartitionId_System, ""); fsdevMountDevice("sv", sv); std::string delPath = "sv:/Contents/placehld/"; fs::dirList plcHld(delPath); for(unsigned i = 0; i < plcHld.getCount(); i++) { std::string fullPath = delPath + plcHld.getItem(i); std::remove(fullPath.c_str()); } fsdevUnmountDevice("sv"); if(ui::confirm("System needs to be restarted for nag to go away. Reboot now?")) { bpcInitialize(); bpcRebootSystem(); } } break; case 8: { fsdevUnmountDevice("sv"); std::string idStr = util::getStringInput("0100000000000000", "Enter Process ID", 18, 0, NULL); if(!idStr.empty()) { uint64_t termID = std::strtoull(idStr.c_str(), NULL, 16); pmshellInitialize(); if(R_SUCCEEDED(pmshellTerminateProcess(termID))) ui::showMessage("Process " + idStr + " successfully shutdown.", "Success!"); pmshellExit(); } } break; case 9: { fsdevUnmountDevice("sv"); std::string idStr = util::getStringInput("8000000000000000", "Enter Sys Save ID", 18, 0, NULL); uint64_t mountID = std::strtoull(idStr.c_str(), NULL, 16); if(R_SUCCEEDED(fsOpen_SystemSaveData(&sv, FsSaveDataSpaceId_System, mountID, (AccountUid){0}))) { fsdevMountDevice("sv", sv); advModePrep("sv:/", true); data::curData.setType(FsSaveDataType_SystemBcat); prevState = EX_MNU; mstate = ADV_MDE; } } break; case 10: { fsdevUnmountDevice("sv"); FsFileSystem tromfs; Result res = fsOpenDataFileSystemByCurrentProcess(&tromfs); if(R_SUCCEEDED(res)) { fsdevMountDevice("tromfs", tromfs); advModePrep("tromfs:/", false); data::curData.setType(FsSaveDataType_SystemBcat); ui::mstate = ADV_MDE; ui::prevState = EX_MNU; } } } } else if(down & KEY_B) { fsdevUnmountDevice("sv"); if(ui::clsMode) mstate = CLS_USR; else mstate = USR_SEL; prevState = USR_SEL; } devMenu.draw(mnuTxt); } }