diff --git a/Makefile b/Makefile index 01cd30f..a25f172 100644 --- a/Makefile +++ b/Makefile @@ -38,7 +38,7 @@ INCLUDES := inc EXEFS_SRC := exefs_src APP_TITLE := JKSV APP_AUTHOR := JK -APP_VERSION := 07.15.2021 +APP_VERSION := 07.18.2021 ROMFS := romfs ICON := icon.jpg diff --git a/inc/data.h b/inc/data.h index 175dc3f..62149bb 100644 --- a/inc/data.h +++ b/inc/data.h @@ -11,7 +11,7 @@ #define curData users[data::selUser].titleInfo[data::selData] #define BLD_MON 7 -#define BLD_DAY 15 +#define BLD_DAY 18 #define BLD_YEAR 2021 namespace data @@ -94,7 +94,6 @@ namespace data void favoriteTitle(const uint64_t& tid); //Adds path definition for title void pathDefAdd(const uint64_t& tid, const std::string& newPath); - bool isFavorite(const uint64_t& tid); //User vector diff --git a/inc/file.h b/inc/file.h index 68d6cfe..48ef73f 100644 --- a/inc/file.h +++ b/inc/file.h @@ -20,7 +20,6 @@ namespace fs //Mounts usr's save data for open. Returns false it fails bool mountSave(const FsSaveDataInfo& _m); inline bool unmountSave() { return fsdevUnmountDevice("sv") == 0; } - Result extendSaveDataFileSystem(FsSaveDataSpaceId _id, uint64_t _saveID, uint64_t _expSize, uint64_t _journal); void copyFile(const std::string& from, const std::string& to); void copyFileCommit(const std::string& from, const std::string& to, const std::string& dev); @@ -29,13 +28,13 @@ namespace fs void copyDirToDir(const std::string& from, const std::string& to); //Copies from to zipFile to - void copyDirToZip(const std::string& from, zipFile *to); + void copyDirToZip(const std::string& from, zipFile to); //Same as above, but commits data to 'dev' after every file is closed void copyDirToDirCommit(const std::string& from, const std::string& to, const std::string& dev); //Copies unzfile to 'to' - void copyZipToDir(unzFile *unz, const std::string& to, const std::string& dev); + void copyZipToDir(unzFile unz, const std::string& to, const std::string& dev); //deletes file void delfile(const std::string& path); diff --git a/inc/miscui.h b/inc/miscui.h index 0a780b5..ace84ae 100644 --- a/inc/miscui.h +++ b/inc/miscui.h @@ -205,6 +205,22 @@ namespace ui std::vector message; }; + class threadProcMngr + { + public: + ~threadProcMngr(); + void newThread(ThreadFunc func, void *args); + void addThread(threadInfo *t); + void update(); + void draw(); + bool empty(){ return threads.empty(); } + + private: + std::vector threads; + uint8_t lgFrame = 0; + unsigned frameCount = 0; + }; + //General use void showMessage(const char *head, const char *fmt, ...); bool confirm(bool hold, const char *fmt, ...); diff --git a/inc/type.h b/inc/type.h index 47cbde0..eac1ade 100644 --- a/inc/type.h +++ b/inc/type.h @@ -2,3 +2,10 @@ //Misc stuff for new menu code typedef void (*funcPtr)(void *); +typedef struct +{ + bool running = false, finished = false; + Thread *thrdPtr = NULL; + void *argPtr = NULL; + std::string status = ""; +} threadInfo; diff --git a/inc/ui.h b/inc/ui.h index ae20160..05ad26e 100644 --- a/inc/ui.h +++ b/inc/ui.h @@ -32,6 +32,9 @@ namespace ui //Slide/animation scaling extern float animScale; + //Loading glyph + extern const std::string loadGlyphArray[]; + //pad data cause i don't know where else to put it extern PadState pad; extern HidTouchScreenState touchState; @@ -58,7 +61,7 @@ namespace ui txtCont = text that contrasts clearClr txtDiag = text color for dialogs */ - extern SDL_Color clearClr, transparent, txtCont, txtDiag, rectLt, rectSh, tboxClr, sideRect, divClr, heartColor, slidePanelColor; + extern SDL_Color clearClr, transparent, txtCont, txtDiag, rectLt, rectSh, tboxClr, sideRect, divClr, heartColor, slidePanelColor, loadGlyphClr; //Textbox graphics extern SDL_Texture *cornerTopLeft, *cornerTopRight, *cornerBottomLeft, *cornerBottomRight; @@ -81,6 +84,7 @@ namespace ui //Adds a panel pointer to a vector since they need to be drawn over everything else int registerMenu(ui::menu *m); int registerPanel(ui::slideOutPanel *sop); + int newThread(ThreadFunc func, void *args); //Just draws a screen and flips JIC boot takes long. void showLoadScreen(); diff --git a/inc/uistr.h b/inc/uistr.h index 179031a..45303ad 100644 --- a/inc/uistr.h +++ b/inc/uistr.h @@ -16,7 +16,7 @@ namespace ui //Strings for extras menu extern std::string exMenuStr[11]; //Strings for options menu - extern std::string optMenuStr[14]; + extern std::string optMenuStr[16]; //Strings for the holding thing extern std::string holdingText[3]; //Strings for sort type diff --git a/inc/util.h b/inc/util.h index 54213c8..8fa31e0 100644 --- a/inc/util.h +++ b/inc/util.h @@ -32,6 +32,15 @@ namespace util std::string getStringInput(const std::string& def, const std::string& head, size_t maxLength, unsigned dictCnt, const std::string dictWords[]); + inline std::string getExtensionFromString(const std::string& get) + { + size_t ext = get.find_last_of('.'); + if(ext != get.npos) + return get.substr(ext + 1, get.npos); + else + return ""; + } + std::string generateAbbrev(const uint64_t& tid); //removes char from C++ string diff --git a/src/data.cpp b/src/data.cpp index fc1f3cc..fcb6b46 100644 --- a/src/data.cpp +++ b/src/data.cpp @@ -438,7 +438,7 @@ void data::user::addUserTitleInfo(const uint64_t& tid, const FsSaveDataInfo *_sa newInfo.saveID = tid; memcpy(&newInfo.saveInfo, _saveInfo, sizeof(FsSaveDataInfo)); memcpy(&newInfo.playStats, _stats, sizeof(PdmPlayStatistics)); - titleInfo.emplace_back(newInfo); + titleInfo.push_back(newInfo); } void data::loadBlacklist() @@ -523,7 +523,7 @@ void data::loadCfg() fread(&data::sortType, 1, 1, cfg); fread(&ui::animScale, sizeof(float), 1, cfg); if(ui::animScale == 0) - ui::animScale = 3.5f; + ui::animScale = 3.0f; fclose(cfg); data::config["incDev"] = cfgIn >> 63 & 1; @@ -538,6 +538,7 @@ void data::loadCfg() data::config["directFsCmd"] = cfgIn >> 53 & 1; data::config["zip"] = cfgIn >> 51 & 1; data::config["langOverride"] = cfgIn >> 50 & 1; + data::config["trashBin"] = cfgIn >> 49 & 1; } } @@ -560,6 +561,7 @@ void data::saveCfg() cfgOut |= (uint64_t)data::config["directFsCmd"] << 53; cfgOut |= (uint64_t)data::config["zip"] << 51; cfgOut |= (uint64_t)data::config["langOverride"] << 50; + cfgOut |= (uint64_t)data::config["trashBin"] << 49; fwrite(&cfgOut, sizeof(uint64_t), 1, cfg); fwrite(&data::sortType, 1, 1, cfg); fwrite(&ui::animScale, sizeof(float), 1, cfg); @@ -580,8 +582,10 @@ void data::restoreDefaultConfig() data::config["sysSaveWrite"] = false; data::config["directFsCmd"] = false; data::config["zip"] = false; + data::config["langOverride"] = false; + data::config["trashBin"] = true; data::sortType = 0; - ui::animScale = 3.5f; + ui::animScale = 3.0f; } void data::loadFav() diff --git a/src/file.cpp b/src/file.cpp index 37486c7..f1d4703 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -29,28 +29,21 @@ static FsFileSystem sv; typedef struct { std::string to, from, dev; - uint64_t *offset; - zipFile *z; + zipFile z; bool fin; } copyArgs; -static copyArgs *copyArgsCreate(const std::string& from, const std::string& to, const std::string& dev, zipFile *z, uint64_t *offset) +static copyArgs *copyArgsCreate(const std::string& from, const std::string& to, const std::string& dev, zipFile z) { copyArgs *ret = new copyArgs; ret->to = to; ret->from = from; ret->dev = dev; ret->z = z; - ret->offset = offset; ret->fin = false; return ret; } -static inline void copyArgsDestroy(copyArgs *args) -{ - delete args; -} - static struct { bool operator()(const fs::dirItem& a, const fs::dirItem& b) @@ -104,13 +97,13 @@ void fs::init() wd = tmp; util::stripChar('\n', wd); util::stripChar('\r', wd); - mkdirRec(wd); } else - { - mkdir("sdmc:/JKSV", 777); wd = "sdmc:/JKSV/"; - } + + mkdirRec(wd); + mkdir(std::string(wd + "_TRASH_").c_str(), 777); + fs::logOpen(); } @@ -122,54 +115,69 @@ void fs::exit() bool fs::mountSave(const FsSaveDataInfo& _m) { Result svOpen; + FsSaveDataAttribute attr = {0}; switch(_m.save_data_type) { case FsSaveDataType_System: - svOpen = fsOpen_SystemSaveData(&sv, FsSaveDataSpaceId_System, _m.save_data_id, _m.uid); + case FsSaveDataType_SystemBcat: + { + attr.uid = _m.uid; + attr.system_save_data_id = _m.system_save_data_id; + attr.save_data_type = _m.save_data_type; + svOpen = fsOpenSaveDataFileSystemBySystemSaveDataId(&sv, (FsSaveDataSpaceId)_m.save_data_space_id, &attr); + } break; case FsSaveDataType_Account: - svOpen = fsOpen_SaveData(&sv, _m.application_id, _m.uid); - break; - - case FsSaveDataType_Bcat: - svOpen = fsOpen_BcatSaveData(&sv, _m.application_id); + { + attr.uid = _m.uid; + attr.application_id = _m.application_id; + attr.save_data_type = _m.save_data_type; + attr.save_data_rank = _m.save_data_rank; + attr.save_data_index = _m.save_data_index; + svOpen = fsOpenSaveDataFileSystem(&sv, (FsSaveDataSpaceId)_m.save_data_space_id, &attr); + } break; case FsSaveDataType_Device: - svOpen = fsOpen_DeviceSaveData(&sv, _m.application_id); + { + attr.application_id = _m.application_id; + attr.save_data_type = FsSaveDataType_Device; + svOpen = fsOpenSaveDataFileSystem(&sv, (FsSaveDataSpaceId)_m.save_data_space_id, &attr); + } break; - case FsSaveDataType_Temporary: - svOpen = fsOpen_TemporaryStorage(&sv); + case FsSaveDataType_Bcat: + { + attr.application_id = _m.application_id; + attr.save_data_type = FsSaveDataType_Bcat; + svOpen = fsOpenSaveDataFileSystem(&sv, (FsSaveDataSpaceId)_m.save_data_space_id, &attr); + } break; case FsSaveDataType_Cache: - svOpen = fsOpen_CacheStorage(&sv, _m.application_id, _m.save_data_rank); + { + attr.application_id = _m.application_id; + attr.save_data_type = FsSaveDataType_Cache; + attr.save_data_index = _m.save_data_index; + svOpen = fsOpenSaveDataFileSystem(&sv, (FsSaveDataSpaceId)_m.save_data_space_id, &attr); + } break; - case FsSaveDataType_SystemBcat: - svOpen = fsOpen_SystemBcatSaveData(&sv, _m.application_id); + case FsSaveDataType_Temporary: + { + attr.application_id = _m.application_id; + attr.save_data_type = _m.save_data_type; + svOpen = fsOpenSaveDataFileSystem(&sv, (FsSaveDataSpaceId)_m.save_data_space_id, &attr); + } break; default: svOpen = 1; break; } - return R_SUCCEEDED(svOpen) && fsdevMountDevice("sv", sv) != -1; -} -Result fs::extendSaveDataFileSystem(FsSaveDataSpaceId _id, uint64_t _saveID, uint64_t _expSize, uint64_t _journal) -{ - Service *fs = fsGetServiceSession(); - struct - { - uint8_t id; - uint64_t saveID; - uint64_t expSize; - uint64_t journal; - } in = {(uint8_t)_id, _saveID, _expSize, _journal}; - return serviceDispatchIn(fs, 32, in); + return R_SUCCEEDED(svOpen) && fsdevMountDevice("sv", sv) != -1; } fs::dirItem::dirItem(const std::string& pathTo, const std::string& sItem) @@ -193,10 +201,7 @@ std::string fs::dirItem::getName() const std::string fs::dirItem::getExt() const { - size_t extPos = itm.find_last_of('.'); - if(extPos == itm.npos) - return "";//Folder or no extension - return itm.substr(extPos + 1, itm.npos); + return util::getExtensionFromString(itm); } fs::dirList::dirList(const std::string& _path) @@ -314,9 +319,19 @@ int fs::dataFile::getNextValueInt() return ret; } +static inline std::string fileStatusString(const std::string& itm, float complete, float total) +{ + char tmp[512]; + sprintf(tmp, "Copying \"%s\" : %.2f MB / %.2f MB", itm.c_str(), complete, total); + return std::string(tmp); +} + static void copyfile_t(void *a) { - copyArgs *args = (copyArgs *)a; + threadInfo *t = (threadInfo *)a; + copyArgs *args = (copyArgs *)t->argPtr; + + float srcSizeMB = (float)fs::fsize(args->from) / 1024.0f / 1024.0f; uint8_t *buff = new uint8_t[BUFF_SIZE]; if(data::config["directFsCmd"]) @@ -331,12 +346,11 @@ static void copyfile_t(void *a) args->fin = true; return; } - size_t readIn = 0; while((readIn = fsfread(buff, 1, BUFF_SIZE, in)) > 0) { fsfwrite(buff, 1, readIn, out); - *args->offset = in->offset; + t->status = fileStatusString(args->from, (float)in->offset / 1024.0f / 1024.0f, srcSizeMB); } fsfclose(in); fsfclose(out); @@ -357,41 +371,29 @@ static void copyfile_t(void *a) while((readIn = fread(buff, 1, BUFF_SIZE, in)) > 0) { fwrite(buff, 1, readIn, out); - *args->offset = ftell(in); + t->status = fileStatusString(args->from, (float)ftell(in) / 1024.0f / 1024.0f, srcSizeMB); } fclose(in); fclose(out); } delete[] buff; - args->fin = true; + delete args; + t->finished = true; } void fs::copyFile(const std::string& from, const std::string& to) { - uint64_t progress = 0; - copyArgs *send = copyArgsCreate(from, to, "", NULL, &progress); - - //Setup progress bar. This thread updates screen, other handles copying - ui::progBar prog(fsize(from)); - - Thread cpyThread; - threadCreate(&cpyThread, copyfile_t, send, NULL, 0x4000, 0x2B, 1); - threadStart(&cpyThread); - while(!send->fin) - { - prog.update(progress); - prog.draw(from, ui::copyHead); - gfx::present(); - } - threadClose(&cpyThread); - copyArgsDestroy(send); + copyArgs *send = copyArgsCreate(from, to, "", NULL); + ui::newThread(copyfile_t, send); } void copyFileCommit_t(void *a) { - copyArgs *args = (copyArgs *)a; + threadInfo *t = (threadInfo *)a; + copyArgs *args = (copyArgs *)t->argPtr; data::titleInfo *info = data::getTitleInfoByTID(data::curData.saveID); + float srcSizeMB = (float)fs::fsize(args->from) / 1024.0f / 1024.0f; uint64_t journalSize = info->nacp.user_account_save_data_journal_size, writeCount = 0; uint8_t *buff = new uint8_t[BUFF_SIZE]; @@ -422,8 +424,7 @@ void copyFileCommit_t(void *a) out = fsfopen(args->to.c_str(), FsOpenMode_Write | FsOpenMode_Append); } - - *args->offset = in->offset; + t->status = fileStatusString(args->from, (float)out->offset / 1024.0f / 1024.0f, srcSizeMB); } fsfclose(in); fsfclose(out); @@ -455,8 +456,7 @@ void copyFileCommit_t(void *a) out = fopen(args->to.c_str(), "ab"); } - - *args->offset = ftell(in); + t->status = fileStatusString(args->from, (float)ftell(out) / 1024.0f / 1024.0f, srcSizeMB); } fclose(in); fclose(out); @@ -464,27 +464,15 @@ void copyFileCommit_t(void *a) delete[] buff; commitToDevice(args->dev.c_str()); - - args->fin = true; + delete args; + t->finished = true; } void fs::copyFileCommit(const std::string& from, const std::string& to, const std::string& dev) { - uint64_t offset = 0; ui::progBar prog(fsize(from)); - copyArgs *send = copyArgsCreate(from, to, dev, NULL, &offset); - - Thread cpyThread; - threadCreate(&cpyThread, copyFileCommit_t, send, NULL, 0x4000, 0x2B, 1); - threadStart(&cpyThread); - while(!send->fin) - { - prog.update(offset); - prog.draw(from, ui::copyHead); - gfx::present(); - } - threadClose(&cpyThread); - copyArgsDestroy(send); + copyArgs *send = copyArgsCreate(from, to, dev, NULL); + ui::newThread(copyFileCommit_t, send); } void fs::copyDirToDir(const std::string& from, const std::string& to) @@ -522,13 +510,11 @@ void copyFileToZip_t(void *a) uint8_t *inBuff= new uint8_t[BUFF_SIZE]; while((readIn = fread(inBuff, 1, BUFF_SIZE, cpy)) > 0) { - if(zipWriteInFileInZip(*args->z, inBuff, readIn) != 0) + if(zipWriteInFileInZip(args->z, inBuff, readIn) != 0) { fs::logWrite("Failed", "zipWriteInFileInZip -> \"%s\"\n", args->from.c_str()); break; } - - *args->offset = ftell(cpy); } delete[] inBuff; @@ -536,11 +522,11 @@ void copyFileToZip_t(void *a) args->fin = true; } -void copyFileToZip(const std::string& from, zipFile *z) +void copyFileToZip(const std::string& from, zipFile z) { ui::progBar prog(fs::fsize(from)); uint64_t progress = 0; - copyArgs *send = copyArgsCreate(from, "", "", z, &progress); + copyArgs *send = copyArgsCreate(from, "", "", z); Thread cpyThread; threadCreate(&cpyThread, copyFileToZip_t, send, NULL, 0x4000, 0x2B, 1); @@ -552,10 +538,10 @@ void copyFileToZip(const std::string& from, zipFile *z) gfx::present(); } threadClose(&cpyThread); - copyArgsDestroy(send); + free(send); } -void fs::copyDirToZip(const std::string& from, zipFile *to) +void fs::copyDirToZip(const std::string& from, zipFile to) { fs::dirList list(from); @@ -574,14 +560,14 @@ void fs::copyDirToZip(const std::string& from, zipFile *to) zip_fileinfo inf = { 0 }; std::string filename = from + list.getItem(i); size_t devPos = filename.find_first_of('/') + 1; - if(zipOpenNewFileInZip(*to, filename.substr(devPos, filename.length()).c_str(), &inf, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION) == ZIP_OK) + if(zipOpenNewFileInZip(to, filename.substr(devPos, filename.length()).c_str(), &inf, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION) == ZIP_OK) copyFileToZip(std::string(from) + list.getItem(i).c_str(), to); - zipCloseFileInZip(*to); + zipCloseFileInZip(to); } } } -void fs::copyZipToDir(unzFile *unz, const std::string& to, const std::string& dev) +void fs::copyZipToDir(unzFile unz, const std::string& to, const std::string& dev) { data::titleInfo *tinfo = data::getTitleInfoByTID(data::curData.saveID); @@ -590,12 +576,12 @@ void fs::copyZipToDir(unzFile *unz, const std::string& to, const std::string& de uint8_t *buff = new uint8_t[BUFF_SIZE]; int readIn = 0; unz_file_info info; - if(unzGoToFirstFile(*unz) == UNZ_OK) + if(unzGoToFirstFile(unz) == UNZ_OK) { do { - unzGetCurrentFileInfo(*unz, &info, filename, FS_MAX_PATH, NULL, 0, NULL, 0); - if(unzOpenCurrentFile(*unz) == UNZ_OK) + unzGetCurrentFileInfo(unz, &info, filename, FS_MAX_PATH, NULL, 0, NULL, 0); + if(unzOpenCurrentFile(unz) == UNZ_OK) { std::string path = to + filename; mkdirRec(path.substr(0, path.find_last_of('/') + 1)); @@ -604,7 +590,7 @@ void fs::copyZipToDir(unzFile *unz, const std::string& to, const std::string& de if(data::config["directFsCmd"]) { FSFILE *out = fsfopen(path.c_str(), FsOpenMode_Write); - while((readIn = unzReadCurrentFile(*unz, buff, BUFF_SIZE)) > 0) + while((readIn = unzReadCurrentFile(unz, buff, BUFF_SIZE)) > 0) { done += readIn; writeCount += readIn; @@ -630,7 +616,7 @@ void fs::copyZipToDir(unzFile *unz, const std::string& to, const std::string& de { FILE *out = fopen(path.c_str(), "wb"); - while((readIn = unzReadCurrentFile(*unz, buff, BUFF_SIZE)) > 0) + while((readIn = unzReadCurrentFile(unz, buff, BUFF_SIZE)) > 0) { done += readIn; writeCount += readIn; @@ -652,11 +638,11 @@ void fs::copyZipToDir(unzFile *unz, const std::string& to, const std::string& de } fclose(out); } - unzCloseCurrentFile(*unz); + unzCloseCurrentFile(unz); commitToDevice(dev.c_str()); } } - while(unzGoToNextFile(*unz) != UNZ_END_OF_LIST_OF_FILE); + while(unzGoToNextFile(unz) != UNZ_END_OF_LIST_OF_FILE); } else ui::showPopMessage(POP_FRAME_DEFAULT, "ZIP file is empty!"); @@ -769,7 +755,7 @@ bool fs::dumpAllUserSaves(const data::user& u) { std::string outPath = basePath + u.getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YMD) + ".zip"; zipFile zip = zipOpen(outPath.c_str(), 0); - fs::copyDirToZip("sv:/", &zip); + fs::copyDirToZip("sv:/", zip); zipClose(zip, NULL); } break; @@ -904,32 +890,31 @@ void fs::createNewBackup(void *a) util::getDateTime(util::DATE_FMT_ASC), data::users[data::selUser].getUsernameSafe(), data::getTitleInfoByTID(data::curData.saveID)->safeTitle, - util::generateAbbrev(data::curData.saveID) + util::generateAbbrev(data::curData.saveID), + ".zip" }; - out = util::getStringInput("", "Enter a name", 64, 8, dict); + out = util::getStringInput("", "Enter a name", 64, 9, dict); } if(!out.empty()) { + std::string ext = util::getExtensionFromString(out); std::string path = util::generatePathByTID(data::curData.saveID) + out; - switch(data::config["zip"]) + if(data::config["zip"] || ext == "zip") { - case true: - { - path += ".zip"; - zipFile zip = zipOpen(path.c_str(), 0); - fs::copyDirToZip("sv:/", &zip); - zipClose(zip, NULL); - } - break; + if(ext != "zip")//data::zip is on but extension is not zip + path += ".zip"; - case false: - { - mkdir(path.c_str(), 777); - path += "/"; - fs::copyDirToDir("sv:/", path); - } - break; + zipFile zip = zipOpen(path.c_str(), 0); + fs::copyDirToZip("sv:/", zip); + zipClose(zip, NULL); + + } + else + { + mkdir(path.c_str(), 777); + path += "/"; + fs::copyDirToDir("sv:/", path); } ui::populateFldMenu(); } @@ -959,7 +944,7 @@ void fs::overwriteBackup(void *a) std::string toPath = util::generatePathByTID(data::curData.saveID) + itemName; fs::delfile(toPath); zipFile zip = zipOpen(toPath.c_str(), 0); - fs::copyDirToZip("sv:/", &zip); + fs::copyDirToZip("sv:/", zip); zipClose(zip, NULL); } } @@ -977,27 +962,18 @@ void fs::restoreBackup(void *a) std::string itemName = d->getItem(ind); if((data::curData.saveInfo.save_data_type != FsSaveDataType_System || data::config["sysSaveWrite"]) && m->getSelected() > 0 && ui::confirm(data::config["holdRest"], ui::confRestore.c_str(), itemName.c_str())) { - if(data::config["autoBack"]) + if(data::config["autoBack"] && data::config["zip"]) { - switch(data::config["zip"]) - { - case true: - { - std::string autoZip = util::generatePathByTID(data::curData.saveID) + "/AUTO " + data::curUser.getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YMD) + ".zip"; - zipFile zip = zipOpen(autoZip.c_str(), 0); - fs::copyDirToZip("sv:/", &zip); - zipClose(zip, NULL); - } - break; - - case false: - { - std::string autoFolder = util::generatePathByTID(data::curData.saveID) + "/AUTO - " + data::curUser.getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YMD) + "/"; - mkdir(autoFolder.substr(0, autoFolder.length() - 1).c_str(), 777); - fs::copyDirToDir("sv:/", autoFolder); - } - break; - } + std::string autoZip = util::generatePathByTID(data::curData.saveID) + "/AUTO " + data::curUser.getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YMD) + ".zip"; + zipFile zip = zipOpen(autoZip.c_str(), 0); + fs::copyDirToZip("sv:/", zip); + zipClose(zip, NULL); + } + else if(data::config["autoBack"]) + { + std::string autoFolder = util::generatePathByTID(data::curData.saveID) + "/AUTO - " + data::curUser.getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YMD) + "/"; + mkdir(autoFolder.substr(0, autoFolder.length() - 1).c_str(), 777); + fs::copyDirToDir("sv:/", autoFolder); } if(d->isDir(ind)) @@ -1011,7 +987,7 @@ void fs::restoreBackup(void *a) fs::wipeSave(); std::string path = util::generatePathByTID(data::curData.saveID) + itemName; unzFile unz = unzOpen(path.c_str()); - fs::copyZipToDir(&unz, "sv:/", "sv"); + fs::copyZipToDir(unz, "sv:/", "sv"); unzClose(unz); } else @@ -1038,15 +1014,24 @@ void fs::deleteBackup(void *a) std::string itemName = d->getItem(ind); if(ui::confirmDelete(itemName)) { - if(d->isDir(ind)) + if(data::config["trashBin"]) + { + std::string oldPath = util::generatePathByTID(data::curData.saveID) + itemName; + std::string trashPath = wd + "_TRASH_/" + itemName; + rename(oldPath.c_str(), trashPath.c_str()); + ui::showPopMessage(POP_FRAME_DEFAULT, "%s moved to trash.", itemName.c_str()); + } + else if(d->isDir(ind)) { std::string delPath = util::generatePathByTID(data::curData.saveID) + itemName + "/"; fs::delDir(delPath); + ui::showPopMessage(POP_FRAME_DEFAULT, "%s has been deleted.", itemName.c_str()); } else { std::string delPath = util::generatePathByTID(data::curData.saveID) + itemName; fs::delfile(delPath); + ui::showPopMessage(POP_FRAME_DEFAULT, "%s has been deleted.", itemName.c_str()); } ui::populateFldMenu(); } diff --git a/src/ui.cpp b/src/ui.cpp index 654cf5c..aa2d5d4 100644 --- a/src/ui.cpp +++ b/src/ui.cpp @@ -14,7 +14,7 @@ //Current menu state int ui::mstate = USR_SEL, ui::prevState = USR_SEL; -float ui::animScale = 3.5f; +float ui::animScale = 3.0f; //pad data? PadState ui::pad; @@ -28,7 +28,7 @@ std::string ui::folderMenuInfo; //UI colors SDL_Color ui::clearClr, ui::txtCont, ui::txtDiag, ui::rectLt, ui::rectSh, ui::tboxClr, ui::divClr, ui::slidePanelColor; -SDL_Color ui::transparent = {0x00, 0x00, 0x00, 0x00}; +SDL_Color ui::transparent = {0x00, 0x00, 0x00, 0x00}, ui::loadGlyphClr = {0x00, 0xFF, 0xC5, 0xFF}; //textbox pieces //I was going to flip them when I draw them, but then laziness kicked in. @@ -52,9 +52,16 @@ static int settPos, extPos; //Vector of pointers to slideOutPanels. Is looped and drawn last so they are always on top std::vector panels; -static unsigned int panelCount = 0; static ui::popMessageMngr *popMessages; +static ui::threadProcMngr *threadMngr; + +//8 +const std::string ui::loadGlyphArray[] = +{ + "\ue020", "\ue021", "\ue022", "\ue023", + "\ue024", "\ue025", "\ue026", "\ue027" +}; void ui::initTheme() { @@ -158,6 +165,7 @@ void ui::init() ui::settInit(); popMessages = new ui::popMessageMngr; + threadMngr = new ui::threadProcMngr; //Need these from user/main menu settPos = ui::usrMenu->getOptPos("Settings"); @@ -171,6 +179,7 @@ void ui::exit() ui::settExit(); delete popMessages; + delete threadMngr; SDL_DestroyTexture(cornerTopLeft); SDL_DestroyTexture(cornerTopRight); @@ -193,7 +202,13 @@ void ui::exit() int ui::registerPanel(slideOutPanel *sop) { panels.push_back(sop); - return panelCount++; + return panels.size() - 1; +} + +int ui::newThread(ThreadFunc func, void *args) +{ + threadMngr->newThread(func, args); + return 0; } void ui::showLoadScreen() @@ -237,6 +252,9 @@ void ui::drawUI() for(slideOutPanel *s : panels) s->draw(&ui::slidePanelColor); + if(!threadMngr->empty()) + threadMngr->draw(); + popMessages->draw(); } @@ -244,38 +262,44 @@ static bool debugDisp = false; bool ui::runApp() { - ui::updateInput(); - uint64_t down = ui::padKeysDown(); - - if(down & HidNpadButton_StickL && down & HidNpadButton_StickR) - debugDisp = true; - else if(down & HidNpadButton_Plus) - return false; - - switch(ui::mstate) + if(threadMngr->empty()) { - case USR_SEL: - usrUpdate(); - break; + ui::updateInput(); + uint64_t down = ui::padKeysDown(); - case TTL_SEL: - ttlUpdate(); - break; + if(down & HidNpadButton_StickL && down & HidNpadButton_StickR) + debugDisp = true; + else if(down & HidNpadButton_Plus) + return false; - case OPT_MNU: - settUpdate(); - break; + switch(ui::mstate) + { + case USR_SEL: + usrUpdate(); + break; - case EX_MNU: - /*extMenu.update(); - if(down & HidNpadButton_B) - { - ui::changeState(USR_SEL); - mainMenu.setActive(true); - extMenu.setActive(false); - }*/ - break; + case TTL_SEL: + ttlUpdate(); + break; + + case OPT_MNU: + settUpdate(); + break; + + case EX_MNU: + /*extMenu.update(); + if(down & HidNpadButton_B) + { + ui::changeState(USR_SEL); + mainMenu.setActive(true); + extMenu.setActive(false); + }*/ + break; + } } + else + threadMngr->update(); + popMessages->update(); drawUI(); diff --git a/src/ui/miscui.cpp b/src/ui/miscui.cpp index 7161329..eddb9ed 100644 --- a/src/ui/miscui.cpp +++ b/src/ui/miscui.cpp @@ -20,13 +20,7 @@ static const SDL_Color fillDark = {0x32, 0x50, 0xF0, 0xFF}; static const SDL_Color menuColorLight = {0x32, 0x50, 0xF0, 0xFF}; static const SDL_Color menuColorDark = {0x00, 0xFF, 0xC5, 0xFF}; - -//8 -static const std::string loadGlyphArray[] = -{ - "\ue020", "\ue021", "\ue022", "\ue023", - "\ue024", "\ue025", "\ue026", "\ue027" -}; +static const SDL_Color darkenBack = {0x00, 0x00, 0x00, 0xBB}; void ui::menu::setParams(const unsigned& _x, const unsigned& _y, const unsigned& _rW, const unsigned& _fS, const unsigned& _mL) { @@ -535,6 +529,63 @@ void ui::popMessageMngr::draw() } } +ui::threadProcMngr::~threadProcMngr() +{ + for(threadInfo *t : threads) + { + threadWaitForExit(t->thrdPtr); + threadClose(t->thrdPtr); + delete t->thrdPtr; + if(t->argPtr) + free(t->argPtr); + delete t; + } +} + +void ui::threadProcMngr::newThread(ThreadFunc func, void *args) +{ + threadInfo *t = new threadInfo; + t->thrdPtr = new Thread; + t->finished = false; + t->argPtr = args; + + threadCreate(t->thrdPtr, func, t, NULL, 0x8000, 0x2B, 1); + threads.push_back(t); +} + +void ui::threadProcMngr::update() +{ + if(!threads.empty()) + { + threadInfo *t = threads[0]; + if(t->running == false && t->finished == false) + { + t->running = true; + threadStart(t->thrdPtr); + } + else if(t->running == true && t->finished == true) + { + threadWaitForExit(t->thrdPtr); + threadClose(t->thrdPtr); + delete t->thrdPtr; + delete t; + threads.erase(threads.begin()); + } + } +} + +void ui::threadProcMngr::draw() +{ + if(++frameCount % 4 == 0 && ++lgFrame > 7) + lgFrame = 0; + + gfx::drawRect(NULL, &darkenBack, 0, 0, 1280, 720); + gfx::drawTextf(NULL, 128, 576, 296, &ui::loadGlyphClr, loadGlyphArray[lgFrame].c_str()); + int y = 424; + int statX = 640 - (gfx::getTextWidth(threads[0]->status.c_str(), 18) / 2); + gfx::drawTextf(NULL, 18, statX, 440, &ui::txtCont, threads[0]->status.c_str()); +} + void ui::showMessage(const char *head, const char *fmt, ...) { char tmp[1024]; @@ -694,7 +745,7 @@ void ui::drawBoundBox(SDL_Texture *target, int x, int y, int w, int h, uint8_t c gfx::drawRect(target, &rectClr, x + 4, y + 4, w - 8, h - 8); - rectClr = {0x00,(uint8_t)(0x88 + clrSh), (uint8_t)(0xC5 + (clrSh / 2)), 0xFF}; + rectClr = {0x00, (uint8_t)(0x88 + clrSh), (uint8_t)(0xC5 + (clrSh / 2)), 0xFF}; SDL_SetTextureColorMod(mnuTopLeft, rectClr.r, rectClr.g, rectClr.b); SDL_SetTextureColorMod(mnuTopRight, rectClr.r, rectClr.g, rectClr.b); diff --git a/src/ui/sett.cpp b/src/ui/sett.cpp index 60806ff..4aa872a 100644 --- a/src/ui/sett.cpp +++ b/src/ui/sett.cpp @@ -2,6 +2,7 @@ #include #include "ui.h" +#include "file.h" #include "sett.h" ui::menu *ui::settMenu; @@ -43,61 +44,71 @@ static void toggleOpt(void *a) switch(ui::settMenu->getSelected()) { case 0: - toggleBool(data::config["incDev"]); + fs::delDir(fs::getWorkDir() + "_TRASH_/"); + mkdir(std::string(fs::getWorkDir() + "_TRASH_").c_str(), 777); + ui::showPopMessage(POP_FRAME_DEFAULT, "Trash emptied."); break; case 1: - toggleBool(data::config["autoBack"]); + toggleBool(data::config["incDev"]); break; case 2: - toggleBool(data::config["ovrClk"]); + toggleBool(data::config["autoBack"]); break; case 3: - toggleBool(data::config["holdDel"]); + toggleBool(data::config["ovrClk"]); break; case 4: - toggleBool(data::config["holdRest"]); + toggleBool(data::config["holdDel"]); break; case 5: - toggleBool(data::config["holdOver"]); + toggleBool(data::config["holdRest"]); break; case 6: - toggleBool(data::config["forceMount"]); + toggleBool(data::config["holdOver"]); break; case 7: - toggleBool(data::config["accSysSave"]); + toggleBool(data::config["forceMount"]); break; case 8: - toggleBool(data::config["sysSaveWrite"]); + toggleBool(data::config["accSysSave"]); break; case 9: - toggleBool(data::config["directFsCmd"]); + toggleBool(data::config["sysSaveWrite"]); break; case 10: - toggleBool(data::config["zip"]); + toggleBool(data::config["directFsCmd"]); break; case 11: - toggleBool(data::config["langOverride"]); + toggleBool(data::config["zip"]); break; case 12: + toggleBool(data::config["langOverride"]); + break; + + case 13: + toggleBool(data::config["trashBin"]); + break; + + case 14: if(++data::sortType > 2) data::sortType = 0; data::loadUsersTitles(false); ui::refreshAllViews(); break; - case 13: + case 15: ui::animScale += 0.5f; if(ui::animScale > 8) ui::animScale = 1; @@ -107,23 +118,24 @@ static void toggleOpt(void *a) static void updateMenuText() { - ui::settMenu->editOpt(0, NULL, ui::optMenuStr[0] + getBoolText(data::config["incDev"])); - ui::settMenu->editOpt(1, NULL, ui::optMenuStr[1] + getBoolText(data::config["autoBack"])); - ui::settMenu->editOpt(2, NULL, ui::optMenuStr[2] + getBoolText(data::config["ovrClk"])); - ui::settMenu->editOpt(3, NULL, ui::optMenuStr[3] + getBoolText(data::config["holdDel"])); - ui::settMenu->editOpt(4, NULL, ui::optMenuStr[4] + getBoolText(data::config["holdRest"])); - ui::settMenu->editOpt(5, NULL, ui::optMenuStr[5] + getBoolText(data::config["holdOver"])); - ui::settMenu->editOpt(6, NULL, ui::optMenuStr[6] + getBoolText(data::config["forceMount"])); - ui::settMenu->editOpt(7, NULL, ui::optMenuStr[7] + getBoolText(data::config["accSysSave"])); - ui::settMenu->editOpt(8, NULL, ui::optMenuStr[8] + getBoolText(data::config["sysSaveWrite"])); - ui::settMenu->editOpt(9, NULL, ui::optMenuStr[9] + getBoolText(data::config["directFsCmd"])); - ui::settMenu->editOpt(10, NULL, ui::optMenuStr[10] + getBoolText(data::config["zip"])); - ui::settMenu->editOpt(11, NULL, ui::optMenuStr[11] + getBoolText(data::config["langOverride"])); - ui::settMenu->editOpt(12, NULL, ui::optMenuStr[12] + ui::sortString[data::sortType]); + ui::settMenu->editOpt(1, NULL, ui::optMenuStr[1] + getBoolText(data::config["incDev"])); + ui::settMenu->editOpt(2, NULL, ui::optMenuStr[2] + getBoolText(data::config["autoBack"])); + ui::settMenu->editOpt(3, NULL, ui::optMenuStr[3] + getBoolText(data::config["ovrClk"])); + ui::settMenu->editOpt(4, NULL, ui::optMenuStr[4] + getBoolText(data::config["holdDel"])); + ui::settMenu->editOpt(5, NULL, ui::optMenuStr[5] + getBoolText(data::config["holdRest"])); + ui::settMenu->editOpt(6, NULL, ui::optMenuStr[6] + getBoolText(data::config["holdOver"])); + ui::settMenu->editOpt(7, NULL, ui::optMenuStr[7] + getBoolText(data::config["forceMount"])); + ui::settMenu->editOpt(8, NULL, ui::optMenuStr[8] + getBoolText(data::config["accSysSave"])); + ui::settMenu->editOpt(9, NULL, ui::optMenuStr[9] + getBoolText(data::config["sysSaveWrite"])); + ui::settMenu->editOpt(10, NULL, ui::optMenuStr[10] + getBoolText(data::config["directFsCmd"])); + ui::settMenu->editOpt(11, NULL, ui::optMenuStr[11] + getBoolText(data::config["zip"])); + ui::settMenu->editOpt(12, NULL, ui::optMenuStr[12] + getBoolText(data::config["langOverride"])); + ui::settMenu->editOpt(13, NULL, ui::optMenuStr[13] + getBoolText(data::config["trashBin"])); + ui::settMenu->editOpt(14, NULL, ui::optMenuStr[14] + ui::sortString[data::sortType]); char tmp[16]; sprintf(tmp, "%.1f", ui::animScale); - ui::settMenu->editOpt(13, NULL, ui::optMenuStr[13] + std::string(tmp)); + ui::settMenu->editOpt(15, NULL, ui::optMenuStr[15] + std::string(tmp)); } void ui::settInit() @@ -135,7 +147,7 @@ void ui::settInit() optHelpX = 1220 - gfx::getTextWidth(ui::optHelp.c_str(), 18); - for(unsigned i = 0; i < 14; i++) + for(unsigned i = 0; i < 16; i++) { ui::settMenu->addOpt(NULL, ui::optMenuStr[i]); ui::settMenu->optAddButtonEvent(i, HidNpadButton_A, toggleOpt, NULL); diff --git a/src/ui/ttl.cpp b/src/ui/ttl.cpp index a9c5576..ecc7da6 100644 --- a/src/ui/ttl.cpp +++ b/src/ui/ttl.cpp @@ -5,7 +5,7 @@ #include "file.h" #include "util.h" -int ttlHelpX = 0; +int ttlHelpX = 0, fldHelpWidth = 0; static std::vector ttlViews; static ui::menu *ttlOpts, *fldMenu; static ui::slideOutPanel *ttlOptsPanel, *infoPanel, *fldPanel;//There's no reason to have a separate folder section @@ -98,19 +98,6 @@ static void ttlOptsCallback(void *a) } } -static void infoPanelCallback(void *a) -{ - switch(ui::padKeysDown()) - { - case HidNpadButton_B: - infoPanel->closePanel(); - ttlOptsPanel->openPanel(); - ttlOpts->setActive(true); - ui::updateInput(); - break; - } -} - static void ttlOptsPanelDraw(void *a) { SDL_Texture *panel = (SDL_Texture *)a; @@ -139,7 +126,7 @@ static void ttlOptsDefinePath(void *a) { uint64_t tid = data::curData.saveID; std::string safeTitle = data::getTitleInfoByTID(tid)->safeTitle; - std::string newSafeTitle = util::getStringInput(safeTitle, "Input New Output Folder", 32, 0, NULL); + std::string newSafeTitle = util::getStringInput(safeTitle, "Input New Output Folder", 0x200, 0, NULL); if(!newSafeTitle.empty()) data::pathDefAdd(tid, newSafeTitle); } @@ -156,6 +143,89 @@ static void ttlOptsResetSaveData(void *a) } } +static void ttlOptsDeleteSaveData(void *a) +{ + std::string title = data::getTitleNameByTID(data::curData.saveID); + if(ui::confirm(data::config["holdDel"], ui::confEraseNand.c_str(), title.c_str()) && R_SUCCEEDED(fsDeleteSaveDataFileSystemBySaveDataSpaceId((FsSaveDataSpaceId)data::curData.saveInfo.save_data_space_id, data::curData.saveInfo.save_data_id))) + { + data::loadUsersTitles(false); + if(data::curUser.titleInfo.size() == 0) + { + //Kick back to user + ttlOptsPanel->closePanel();//JIC + ttlOpts->setActive(false); + ttlViews[data::selUser]->setActive(false, false); + ui::usrMenu->setActive(true); + ui::changeState(USR_SEL); + } + ui::showPopMessage(POP_FRAME_DEFAULT, ui::saveDataDeleteSuccess.c_str(), title.c_str()); + ttlViews[data::selUser]->refresh(); + } +} + +static void ttlOptsExtendSaveData_t(void *a) +{ + threadInfo *w = (threadInfo *)a; + std::string expSizeStr = util::getStringInput("", "Enter New Size in MB", 4, 0, NULL); + if(!expSizeStr.empty()) + { + data::titleInfo *extend = data::getTitleInfoByTID(data::curData.saveID); + w->status = "Expanding save filesystem for " + extend->title; + uint64_t expMB = strtoul(expSizeStr.c_str(), NULL, 10); + FsSaveDataSpaceId space = (FsSaveDataSpaceId)data::curData.saveInfo.save_data_space_id; + uint64_t sid = data::curData.saveInfo.save_data_id; + int64_t expSize = expMB * 1024 * 1024; + int64_t journ = 0; + if(extend->nacp.user_account_save_data_journal_size_max > extend->nacp.user_account_save_data_journal_size) + journ = extend->nacp.user_account_save_data_journal_size_max; + else + journ = extend->nacp.user_account_save_data_journal_size; + + Result res = 0; + if(R_SUCCEEDED(res = fsExtendSaveDataFileSystem(space, sid, expSize, journ))) + { + ui::showPopMessage(POP_FRAME_DEFAULT, "Save data expanded for %s!", extend->title.c_str()); + fs::logWrite("Extend Succeeded!\n"); + } + else + { + int64_t totalSize = 0; + fs::mountSave(data::curData.saveInfo); + fsFsGetTotalSpace(fsdevGetDeviceFileSystem("sv"), "/", &totalSize); + fs::unmountSave(); + + fs::logWrite("Extend Failed: %uMB to %uMB -> %X\n", totalSize / 1024 / 1024, expSize / 1024 / 1024, res); + ui::showPopMessage(POP_FRAME_DEFAULT, "Failed to expand save data."); + } + } + w->finished = true; +} + +static void ttlOptsExtendSaveData(void *a) +{ + ui::newThread(ttlOptsExtendSaveData_t, NULL); +} + +static void infoPanelDraw(void *a) +{ + SDL_Texture *panel = (SDL_Texture *)a; + gfx::texDraw(panel, data::getTitleIconByTID(data::curData.saveID), 77, 32); + gfx::drawTextfWrap(panel, 18, 32, 320, 362, &ui::txtCont, infoPanelString.c_str()); +} + +static void infoPanelCallback(void *a) +{ + switch(ui::padKeysDown()) + { + case HidNpadButton_B: + infoPanel->closePanel(); + ttlOptsPanel->openPanel(); + ttlOpts->setActive(true); + ui::updateInput(); + break; + } +} + static void fldMenuCallback(void *a) { switch(ui::padKeysDown()) @@ -173,80 +243,14 @@ static void fldPanelDraw(void *a) { SDL_Texture *target = (SDL_Texture *)a; fldMenu->draw(target, &ui::txtCont, true); - gfx::drawLine(target, &ui::divClr, 10, 648, 502, 648); + gfx::drawLine(target, &ui::divClr, 10, 648, fldHelpWidth + 54, 648); gfx::drawTextf(target, 18, 32, 673, &ui::txtCont, ui::folderHelp.c_str()); } -static void ttlOptsDeleteSaveData(void *a) -{ - FsSaveDataAttribute attr; - attr.application_id = data::curData.saveID; - attr.uid = data::curData.saveInfo.save_data_type == FsSaveDataType_Account ? data::curUser.getUID() : util::u128ToAccountUID(0); - attr.system_save_data_id = 0; - attr.save_data_type = data::curData.saveInfo.save_data_type; - attr.save_data_rank = data::curData.saveInfo.save_data_rank; - attr.save_data_index = data::curData.saveInfo.save_data_index; - - std::string title = data::getTitleNameByTID(data::curData.saveID); - if(ui::confirm(data::config["holdDel"], ui::confEraseNand.c_str(), title.c_str()) && R_SUCCEEDED(fsDeleteSaveDataFileSystemBySaveDataAttribute(FsSaveDataSpaceId_User, &attr))) - { - data::loadUsersTitles(false); - if(data::curUser.titleInfo.size() == 0) - { - //Kick back to user - ttlOptsPanel->closePanel();//JIC - ttlOpts->setActive(false); - ttlViews[data::selUser]->setActive(false, false); - ui::usrMenu->setActive(true); - ui::changeState(USR_SEL); - } - ui::showPopMessage(POP_FRAME_DEFAULT, ui::saveDataDeleteSuccess.c_str(), title.c_str()); - ttlViews[data::selUser]->refresh(); - } -} - -static void ttlOptsExtendSaveData(void *a) -{ - std::string expSizeStr = util::getStringInput("", "Enter New Size in MB", 4, 0, NULL); - if(!expSizeStr.empty()) - { - uint64_t expMB = strtoul(expSizeStr.c_str(), NULL, 10); - - data::titleInfo *extend = data::getTitleInfoByTID(data::curData.saveID); - FsSaveDataSpaceId space = (FsSaveDataSpaceId)data::curData.saveInfo.save_data_space_id; - uint64_t sid = data::curData.saveInfo.save_data_id; - uint64_t expSize = expMB * 1024 * 1024; - uint64_t journ = extend->nacp.user_account_save_data_journal_size; - - Result res = 0; - if(R_SUCCEEDED(res = fs::extendSaveDataFileSystem(space, sid, expSize, journ))) - { - ui::showPopMessage(POP_FRAME_DEFAULT, "Save data expanded for %s!", extend->title.c_str()); - fs::logWrite("Extend Succeeded!\n"); - } - else - { - int64_t totalSize = 0; - fs::mountSave(data::curData.saveInfo); - fsFsGetTotalSpace(fsdevGetDeviceFileSystem("sv"), "/", &totalSize); - fs::unmountSave(); - - fs::logWrite("Extend Failed: %uMB to %uMB -> %X\n", totalSize / 1024 / 1024, expSize / 1024 / 1024, res); - ui::showPopMessage(POP_FRAME_DEFAULT, "Failed to expand save data."); - } - } -} - -static void infoPanelDraw(void *a) -{ - SDL_Texture *panel = (SDL_Texture *)a; - gfx::texDraw(panel, data::getTitleIconByTID(data::curData.saveID), 77, 32); - gfx::drawTextfWrap(panel, 18, 32, 320, 362, &ui::txtCont, infoPanelString.c_str()); -} - void ui::ttlInit() { ttlHelpX = 1220 - gfx::getTextWidth(ui::titleHelp.c_str(), 18); + fldHelpWidth = gfx::getTextWidth(ui::folderHelp.c_str(), 18); for(data::user& u : data::users) ttlViews.emplace_back(new ui::titleview(u, 128, 128, 16, 16, 7, ttlViewCallback)); @@ -257,7 +261,7 @@ void ui::ttlInit() ttlOpts->setActive(false); fldMenu = new ui::menu; - fldMenu->setParams(10, 32, 492, 18, 8); + fldMenu->setParams(10, 32, fldHelpWidth + 44, 18, 8); fldMenu->setCallback(fldMenuCallback, NULL); fldMenu->setActive(false); @@ -268,7 +272,7 @@ void ui::ttlInit() ui::registerPanel(infoPanel); infoPanel->setCallback(infoPanelCallback, NULL); - fldPanel = new ui::slideOutPanel(512, 720, 0, fldPanelDraw); + fldPanel = new ui::slideOutPanel(fldHelpWidth + 64, 720, 0, fldPanelDraw); ui::registerPanel(fldPanel); fldList = new fs::dirList; @@ -320,6 +324,6 @@ void ui::ttlUpdate() void ui::ttlDraw(SDL_Texture *target) { ttlViews[data::selUser]->draw(target); - if(ui::mstate == TTL_SEL) + if(ui::mstate == TTL_SEL && !fldPanel->isOpen()) gfx::drawTextf(NULL, 18, ttlHelpX, 673, &ui::txtCont, ui::titleHelp.c_str()); } diff --git a/src/ui/uistr.cpp b/src/ui/uistr.cpp index d3e4781..369495c 100644 --- a/src/ui/uistr.cpp +++ b/src/ui/uistr.cpp @@ -41,7 +41,7 @@ std::string ui::errorConnecting = "Error Connecting!"; std::string ui::noUpdate = "No updates available!"; std::string ui::advMenuStr[6] = { "Copy to ", "Delete", "Rename", "Make Dir", "Properties", "Close" }; std::string ui::exMenuStr[11] = { "SD to SD Browser", "BIS: PRODINFOF", "BIS: SAFE", "BIS: SYSTEM", "BIS: USER", "Remove Update", "Terminate Process", "Mount System Save", "Rescan Titles", "Mount Process RomFS", "Backup JKSV Folder" }; -std::string ui::optMenuStr[14] = { "Include Device Saves: ", "AutoBackup: ", "Overclock: ", "Hold to Delete: ", "Hold to Restore: ", "Hold to Overwrite: ", "Force Mount: ", "Account Sys. Saves: ", "Write to Sys. Saves: ", "Direct FS Cmd: ", "Export to ZIP: ", "Language Override: ", "Sort: ", "Animation Scale: "}; +std::string ui::optMenuStr[16] = { "Empty Trash Bin", "Include Device Saves: ", "AutoBackup: ", "Overclock: ", "Hold to Delete: ", "Hold to Restore: ", "Hold to Overwrite: ", "Force Mount: ", "Account Sys. Saves: ", "Write to Sys. Saves: ", "Direct FS Cmd: ", "Export to ZIP: ", "Language Override: ", "Enable Trash Bin: ", "Sort: ", "Animation Scale: "}; std::string ui::holdingText[3] = { "(Hold) ", "(Keep Holding) ", "(Almost there!) " }; std::string ui::sortString[3] = { "Alphabetical", "Time Played", "Last Played" }; std::string ui::usrOptString[2] = { "Create Save Data", "Delete All User Saves" }; @@ -49,6 +49,9 @@ std::string ui::titleOptString[6] = {"Information", "Blacklist", "Change Output void ui::loadTrans() { + //Disable translation loading until new UI done + return; + bool transFile = fs::fileExists(fs::getWorkDir() + "trans.txt"); if(!transFile && (data::sysLang == SetLanguage_ENUS || data::config["langOverride"])) return;//Don't bother loading from file. It serves as a translation guide diff --git a/src/ui/usr.cpp b/src/ui/usr.cpp index ee90ec5..568be4b 100644 --- a/src/ui/usr.cpp +++ b/src/ui/usr.cpp @@ -129,26 +129,25 @@ static void usrOptSaveCreate(void *a) } //nsDeleteUserSaveDataAll only works if the user is selected at system level +static void usrOptDeleteAllUserSaves_t(void *a) +{ + threadInfo *t = (threadInfo *)a; + data::user *u = &data::users[data::selUser]; + for(data::userTitleInfo& tinf : u->titleInfo) + { + t->status = "Deleting " + data::getTitleNameByTID(tinf.saveID); + fsDeleteSaveDataFileSystemBySaveDataSpaceId(FsSaveDataSpaceId_User, tinf.saveInfo.save_data_id);; + } + data::loadUsersTitles(false); + ui::refreshAllViews(); + t->finished = true; +} + static void usrOptDeleteAllUserSaves(void *a) { data::user *u = &data::users[data::selUser]; if(ui::confirm(true, "*ARE YOU SURE YOU WANT TO DELETE ALL SAVE DATA FOR %s?*", u->getUsername().c_str())) - { - for(data::userTitleInfo& tinf : u->titleInfo) - { - FsSaveDataAttribute attr; - attr.application_id = tinf.saveID; - attr.uid = u->getUID(); - attr.system_save_data_id = 0; - attr.save_data_type = tinf.saveInfo.save_data_type; - attr.save_data_rank = tinf.saveInfo.save_data_rank; - attr.save_data_index = tinf.saveInfo.save_data_index; - - fsDeleteSaveDataFileSystemBySaveDataAttribute(FsSaveDataSpaceId_User, &attr); - } - data::loadUsersTitles(false); - ui::refreshAllViews(); - } + ui::newThread(usrOptDeleteAllUserSaves_t, NULL); } static void usrOptPanelDraw(void *a) @@ -181,9 +180,10 @@ static void cacheSavePanelDraw(void *a) cacheSaveMenu->draw(panel, &ui::txtCont, true); } -static void createSaveData(void *a) +static void createSaveData_t(void *a) { - svCreateArgs *in = (svCreateArgs *)a; + threadInfo *t = (threadInfo *)a; + svCreateArgs *in = (svCreateArgs *)t->argPtr; FsSaveDataType type = in->type; ui::menu *m = in->m; @@ -211,6 +211,7 @@ static void createSaveData(void *a) break; } data::titleInfo *create = data::getTitleInfoByTID(sid); + t->status = "Creating save data for " + create->title; FsSaveDataAttribute attr; memset(&attr, 0, sizeof(FsSaveDataAttribute)); @@ -243,7 +244,7 @@ static void createSaveData(void *a) case FsSaveDataType_Cache: saveSize = 32 * 1024 * 1024;//Todo: Add target folder/zip selection for size - journalSize = create->nacp.user_account_save_data_journal_size; + journalSize = create->nacp.cache_storage_journal_size; break; default: @@ -265,7 +266,6 @@ static void createSaveData(void *a) Result res = 0; if(R_SUCCEEDED(res = fsCreateSaveDataFileSystem(&attr, &svCreate, &meta))) { - ui::showPopMessage(POP_FRAME_DEFAULT, ui::saveCreated.c_str(), create->title.c_str()); data::loadUsersTitles(false); ui::refreshAllViews(); } @@ -274,6 +274,13 @@ static void createSaveData(void *a) ui::showPopMessage(POP_FRAME_DEFAULT, ui::saveCreateFailed.c_str()); fs::logWrite("SaveCreate Failed -> %X\n", res); } + + t->finished = true; +} + +static void createSaveData(void *a) +{ + ui::newThread(createSaveData_t, a); } void ui::usrInit() @@ -317,7 +324,7 @@ void ui::usrInit() ext = util::createIconGeneric("Extras", 40); pos = usrMenu->addOpt(ext, "Extras"); - usrMenu->optAddButtonEvent(pos, HidNpadButton_A, toEXT, NULL); + usrMenu->optAddButtonEvent(pos, HidNpadButton_A, NULL, NULL); usrMenu->setOnChangeFunc(onMainChange); usrMenu->editParam(MENU_RECT_WIDTH, 126); diff --git a/src/util.cpp b/src/util.cpp index 5ba13d8..8944f1d 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -261,9 +261,9 @@ std::string util::getStringInput(const std::string& def, const std::string& head swkbdConfigSetDictionary(&swkbd, (SwkbdDictWord *)words, dictCnt); } - char out[maxLength]; - memset(out, 0, maxLength); - swkbdShow(&swkbd, out, maxLength); + char out[maxLength + 1]; + memset(out, 0, maxLength + 1); + swkbdShow(&swkbd, out, maxLength + 1); swkbdClose(&swkbd); return std::string(out);