diff --git a/inc/data.h b/inc/data.h index f4abe30..175dc3f 100644 --- a/inc/data.h +++ b/inc/data.h @@ -29,6 +29,7 @@ namespace data void loadFav(); void saveFav(); void loadDefs(); + void saveDefs(); //Draws some stats to the upper left corner void dispStats(); @@ -91,6 +92,8 @@ namespace data void blacklistAdd(const uint64_t& tid); //Adds title to favorite list 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); diff --git a/inc/uistr.h b/inc/uistr.h index c0b03e8..179031a 100644 --- a/inc/uistr.h +++ b/inc/uistr.h @@ -24,5 +24,5 @@ namespace ui //Strings for user options extern std::string usrOptString[2]; //Strings for title options - extern std::string titleOptString[5]; + extern std::string titleOptString[6]; } diff --git a/src/data.cpp b/src/data.cpp index c2f35c9..fc1f3cc 100644 --- a/src/data.cpp +++ b/src/data.cpp @@ -158,6 +158,8 @@ static inline void addTitleToList(const uint64_t& tid) data::titles[tid].fav = true; data::titles[tid].icon = gfx::loadJPEGMem(ctrlData->icon, iconSize); + if(!data::titles[tid].icon) + data::titles[tid].icon = util::createIconGeneric(util::getIDStrLower(tid).c_str(), 32); } else { @@ -171,7 +173,6 @@ static inline void addTitleToList(const uint64_t& tid) data::titles[tid].icon = util::createIconGeneric(util::getIDStrLower(tid).c_str(), 32); } - delete ctrlData; } @@ -355,6 +356,7 @@ void data::exit() saveFav(); saveCfg(); saveBlackList(); + saveDefs(); util::setCPU(1020000000); } @@ -451,12 +453,15 @@ void data::loadBlacklist() void data::saveBlackList() { - std::string blPath = fs::getWorkDir() + "blacklist.txt"; - FILE *bl = fopen(blPath.c_str(), "w"); - for(uint64_t id : blacklist) - fprintf(bl, "#%s\n0x%016lX\n", data::getTitleNameByTID(id).c_str(), id); + if(!blacklist.empty()) + { + std::string blPath = fs::getWorkDir() + "blacklist.txt"; + FILE *bl = fopen(blPath.c_str(), "w"); + for(uint64_t id : blacklist) + fprintf(bl, "#%s\n0x%016lX\n", data::getTitleNameByTID(id).c_str(), id); - fclose(bl); + fclose(bl); + } } void data::blacklistAdd(const uint64_t& tid) @@ -487,6 +492,25 @@ void data::favoriteTitle(const uint64_t& tid) std::sort(u.titleInfo.begin(), u.titleInfo.end(), sortTitles); } +void data::pathDefAdd(const uint64_t& tid, const std::string& newPath) +{ + std::string oldSafe = titles[tid].safeTitle; + std::string tmp = util::safeString(newPath); + if(!tmp.empty()) + { + pathDefs[tid] = tmp; + titles[tid].safeTitle = tmp; + + std::string oldOutput = fs::getWorkDir() + oldSafe; + std::string newOutput = fs::getWorkDir() + tmp; + rename(oldOutput.c_str(), newOutput.c_str()); + + ui::showPopMessage(POP_FRAME_DEFAULT, "\"%s\" changed to \"%s\"", oldSafe.c_str(), tmp.c_str()); + } + else + ui::showPopMessage(POP_FRAME_DEFAULT, "\"%s\" contains illegal or non-ASCII characters.", newPath.c_str()); +} + void data::loadCfg() { std::string cfgPath = fs::getWorkDir() + "cfg.bin"; @@ -572,12 +596,15 @@ void data::loadFav() void data::saveFav() { - std::string favPath = fs::getWorkDir() + "favorites.txt"; - FILE *fav = fopen(favPath.c_str(), "w"); - for(uint64_t& fid : favorites) - fprintf(fav, "0x%016lX\n", fid); + if(!favorites.empty()) + { + std::string favPath = fs::getWorkDir() + "favorites.txt"; + FILE *fav = fopen(favPath.c_str(), "w"); + for(uint64_t& fid : favorites) + fprintf(fav, "0x%016lX\n", fid); - fclose(fav); + fclose(fav); + } } void data::loadDefs() @@ -594,6 +621,21 @@ void data::loadDefs() } } +void data::saveDefs() +{ + if(!pathDefs.empty()) + { + std::string defPath = fs::getWorkDir() + "titleDefs.txt"; + FILE *ttlDef = fopen(defPath.c_str(), "w"); + for(auto& d : pathDefs) + { + std::string title = data::titles[d.first].title; + fprintf(ttlDef, "#%s\n0x%016lX = \"%s\";\n", title.c_str(), d.first, d.second.c_str()); + } + fclose(ttlDef); + } +} + static const SDL_Color green = {0x00, 0xDD, 0x00, 0xFF}; void data::dispStats() diff --git a/src/gfx.cpp b/src/gfx.cpp index 359a41f..4776c4c 100644 --- a/src/gfx.cpp +++ b/src/gfx.cpp @@ -135,9 +135,10 @@ SDL_Texture *gfx::loadJPEGMem(const void *jpegData, size_t jpegsize) SDL_RWops *jpeg = SDL_RWFromConstMem(jpegData, jpegsize); SDL_Surface *tmpSurf = IMG_LoadJPG_RW(jpeg); if(tmpSurf) + { ret = SDL_CreateTextureFromSurface(render, tmpSurf); - - SDL_FreeSurface(tmpSurf); + SDL_FreeSurface(tmpSurf); + } SDL_RWclose(jpeg); SDL_SetTextureBlendMode(ret, SDL_BLENDMODE_BLEND); @@ -150,10 +151,10 @@ SDL_Texture *gfx::loadImageFile(const char *file) SDL_Texture *ret = NULL; SDL_Surface *tmpSurf = IMG_Load(file); if(tmpSurf) + { ret = SDL_CreateTextureFromSurface(render, tmpSurf); - - SDL_FreeSurface(tmpSurf); - + SDL_FreeSurface(tmpSurf); + } SDL_SetTextureBlendMode(ret, SDL_BLENDMODE_BLEND); return ret; diff --git a/src/ui/ttl.cpp b/src/ui/ttl.cpp index 7680758..a9c5576 100644 --- a/src/ui/ttl.cpp +++ b/src/ui/ttl.cpp @@ -135,6 +135,15 @@ static void ttlOptsBlacklistTitle(void *a) } } +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); + if(!newSafeTitle.empty()) + data::pathDefAdd(tid, newSafeTitle); +} + static void ttlOptsResetSaveData(void *a) { std::string title = data::getTitleNameByTID(data::curData.saveID); @@ -164,6 +173,8 @@ 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::drawTextf(target, 18, 32, 673, &ui::txtCont, ui::folderHelp.c_str()); } static void ttlOptsDeleteSaveData(void *a) @@ -246,7 +257,7 @@ void ui::ttlInit() ttlOpts->setActive(false); fldMenu = new ui::menu; - fldMenu->setParams(10, 32, 390, 18, 8); + fldMenu->setParams(10, 32, 492, 18, 8); fldMenu->setCallback(fldMenuCallback, NULL); fldMenu->setActive(false); @@ -257,7 +268,7 @@ void ui::ttlInit() ui::registerPanel(infoPanel); infoPanel->setCallback(infoPanelCallback, NULL); - fldPanel = new ui::slideOutPanel(410, 720, 0, fldPanelDraw); + fldPanel = new ui::slideOutPanel(512, 720, 0, fldPanelDraw); ui::registerPanel(fldPanel); fldList = new fs::dirList; @@ -269,11 +280,13 @@ void ui::ttlInit() ttlOpts->addOpt(NULL, ui::titleOptString[1]); ttlOpts->optAddButtonEvent(1, HidNpadButton_A, ttlOptsBlacklistTitle, NULL); ttlOpts->addOpt(NULL, ui::titleOptString[2]); - ttlOpts->optAddButtonEvent(2, HidNpadButton_A, ttlOptsResetSaveData, NULL); + ttlOpts->optAddButtonEvent(2, HidNpadButton_A, ttlOptsDefinePath, NULL); ttlOpts->addOpt(NULL, ui::titleOptString[3]); - ttlOpts->optAddButtonEvent(3, HidNpadButton_A, ttlOptsDeleteSaveData, NULL); + ttlOpts->optAddButtonEvent(3, HidNpadButton_A, ttlOptsResetSaveData, NULL); ttlOpts->addOpt(NULL, ui::titleOptString[4]); - ttlOpts->optAddButtonEvent(4, HidNpadButton_A, ttlOptsExtendSaveData, NULL); + ttlOpts->optAddButtonEvent(4, HidNpadButton_A, ttlOptsDeleteSaveData, NULL); + ttlOpts->addOpt(NULL, ui::titleOptString[5]); + ttlOpts->optAddButtonEvent(5, HidNpadButton_A, ttlOptsExtendSaveData, NULL); } diff --git a/src/ui/uistr.cpp b/src/ui/uistr.cpp index d2d628d..d3e4781 100644 --- a/src/ui/uistr.cpp +++ b/src/ui/uistr.cpp @@ -19,7 +19,7 @@ static std::unordered_map uistrdef = std::string ui::author = "NULL"; std::string ui::userHelp = "[A] Select [X] User Options"; std::string ui::titleHelp = "[A] Select [L][R] Jump [Y] Favorite [X] Title Options [B] Back"; -std::string ui::folderHelp = "[-] File Mode [L]/[R]+[A] Auto [A] Backup [Y] Restore [X] Delete Selected [ZR] Erase [B] Back"; +std::string ui::folderHelp = "[A] Select [Y] Restore [X] Delete [B] Close"; std::string ui::optHelp = "[A] Toggle [X] Defaults [B] Back"; std::string ui::yt = "Yes [A]", ui::nt = "No [B]"; std::string ui::on = ">On>", ui::off = "Off"; @@ -45,12 +45,12 @@ std::string ui::optMenuStr[14] = { "Include Device Saves: ", "AutoBackup: ", "Ov 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" }; -std::string ui::titleOptString[5] = {"Information", "Blacklist", "Reset Save Data", "Delete Save Filesystem", "Extend Save Filesystem"}; +std::string ui::titleOptString[6] = {"Information", "Blacklist", "Change Output folder", "Reset Save Data", "Delete Save Filesystem", "Extend Save Filesystem"}; void ui::loadTrans() { bool transFile = fs::fileExists(fs::getWorkDir() + "trans.txt"); - if(!transFile && data::sysLang == SetLanguage_ENUS) + if(!transFile && (data::sysLang == SetLanguage_ENUS || data::config["langOverride"])) return;//Don't bother loading from file. It serves as a translation guide std::string file; diff --git a/src/util.cpp b/src/util.cpp index c412667..5ba13d8 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -171,7 +171,7 @@ std::string util::safeString(const std::string& s) } //Check for spaces at end - while(ret[ret.length() - 1] == ' ') + while(ret[ret.length() - 1] == ' ' || ret[ret.length() - 1] == '.') ret.erase(ret.length() - 1, 1); return ret;