From 2b6f91e20f4d3f6bb4611407b15a77dbf5b8e3c9 Mon Sep 17 00:00:00 2001 From: J-D-K Date: Mon, 16 Aug 2021 21:58:18 -0400 Subject: [PATCH] Update readme, add legacy config loading, new translation format, remove curUser and curData definition shortcuts --- Makefile | 2 +- README.MD | 3 +- inc/data.h | 17 +- inc/file.h | 10 ++ inc/fsthrd.h | 1 + inc/type.h | 25 +-- inc/ui/uistr.h | 27 +--- romfs/lang/en-US.txt | 233 +++++++++++++-------------- src/cfg.cpp | 132 ++++++++++++--- src/data.cpp | 41 ++++- src/file.cpp | 79 +++++---- src/fsthrd.cpp | 100 ++++++++++-- src/type.cpp | 25 +++ src/ui.cpp | 42 ++--- src/ui/ext.cpp | 19 ++- src/ui/fm.cpp | 29 ++-- src/ui/miscui.cpp | 42 +++-- src/ui/sett.cpp | 46 +++--- src/ui/ttl.cpp | 160 +++++++++++-------- src/ui/uistr.cpp | 370 ++++++++++++++++++++----------------------- src/ui/usr.cpp | 218 +++++++++---------------- src/util.cpp | 17 +- 22 files changed, 927 insertions(+), 711 deletions(-) create mode 100644 src/type.cpp diff --git a/Makefile b/Makefile index b0ce713..6b0c128 100644 --- a/Makefile +++ b/Makefile @@ -38,7 +38,7 @@ INCLUDES := inc inc/ui EXEFS_SRC := exefs_src APP_TITLE := JKSV APP_AUTHOR := JK -APP_VERSION := 08.04.2021 +APP_VERSION := 08.16.2021 ROMFS := romfs ICON := icon.jpg diff --git a/README.MD b/README.MD index c9bca38..547d539 100644 --- a/README.MD +++ b/README.MD @@ -80,8 +80,7 @@ JKSV on Switch started as a small project/port to test some things and get famil 2. Requires switch-freetype, libpng, zlib, libjpeg-turbo, lib-curl, and lib-json-c ## Credits and Thanks: -* [shared-font](https://github.com/switchbrew/switch-portlibs-examples) example by yellows8 -* Authors of switch-examples for account and save mounting code. +* [shared-font](https://github.com/switchbrew/switch-portlibs-examples) example by yellows8 for loading system font with Freetype. All other font handling code (converting to SDL2, resizing on the fly, checking for glyphs, cache, etc) is my own. * [Iguniisu](https://github.com/igniscitrinus) for the icon. * Uses graphics from [Twemoji](https://github.com/twitter/twemoji) covered by the [Creative Commons License](https://creativecommons.org/licenses/by/4.0/legalcode) * [Leo](https://github.com/qazrfv1234) For the Traditional Chinese translation diff --git a/inc/data.h b/inc/data.h index dbd0798..0326b57 100644 --- a/inc/data.h +++ b/inc/data.h @@ -7,11 +7,8 @@ #include "gfx.h" -#define curUser users[data::selUser] -#define curData users[data::selUser].titleInfo[data::selData] - #define BLD_MON 8 -#define BLD_DAY 4 +#define BLD_DAY 16 #define BLD_YEAR 2021 namespace data @@ -86,7 +83,16 @@ namespace data //Title data/info map extern std::unordered_map titles; - //Gets pointer to info + //Sets/Retrieves current user/title + void setUserIndex(unsigned _sUser); + data::user *getCurrentUser(); + unsigned getCurrentUserIndex(); + + void setTitleIndex(unsigned _sTitle); + data::userTitleInfo *getCurrentUserTitleInfo(); + unsigned getCurrentUserTitleInfoIndex(); + + //Gets pointer to info that also has title + nacp data::titleInfo *getTitleInfoByTID(const uint64_t& tid); //More shortcut functions @@ -102,6 +108,5 @@ namespace data } return -1; } - extern int selUser, selData; extern SetLanguage sysLang; } diff --git a/inc/file.h b/inc/file.h index 1dfb65f..19f50f8 100644 --- a/inc/file.h +++ b/inc/file.h @@ -24,6 +24,7 @@ namespace fs bool mountSave(const FsSaveDataInfo& _m); inline bool unmountSave() { return fsdevUnmountDevice("sv") == 0; } bool commitToDevice(const std::string& dev); + void createSaveData(FsSaveDataType _type, uint64_t _tid, AccountUid _userID); void copyFile(const std::string& from, const std::string& to); void copyFileCommit(const std::string& from, const std::string& to, const std::string& dev); @@ -114,6 +115,7 @@ namespace fs public: dataFile(const std::string& _path); ~dataFile(); + void close(){ fclose(f); } bool isOpen() const { return opened; } @@ -154,6 +156,14 @@ namespace fs void argUnlock() { mutexUnlock(&arglck); } } copyArgs; + typedef struct + { + FsSaveDataType type; + uint64_t tid; + AccountUid account; + uint16_t index; + } svCreateArgs; + copyArgs *copyArgsCreate(const std::string& from, const std::string& to, const std::string& dev, zipFile z, unzFile unz, bool _cleanup); void copyArgsDestroy(copyArgs *c); diff --git a/inc/fsthrd.h b/inc/fsthrd.h index b208f72..fb37b84 100644 --- a/inc/fsthrd.h +++ b/inc/fsthrd.h @@ -6,6 +6,7 @@ namespace fs { void _fileDrawFunc(void *a); + void createSaveData_t(void *a); void copyFile_t(void *a); void copyFileCommit_t(void *a); void copyDirToDir_t(void *a); diff --git a/inc/type.h b/inc/type.h index 9b3dd64..d1dcc6f 100644 --- a/inc/type.h +++ b/inc/type.h @@ -6,25 +6,16 @@ //Misc stuff for new menu code typedef void (*funcPtr)(void *); -typedef struct +class threadStatus { - Mutex statusLock = 0; - std::string status; - void setStatus(const std::string& newStatus) - { - mutexLock(&statusLock); - status = newStatus; - mutexUnlock(&statusLock); - } + public: + void setStatus(const char *fmt, ...); + void getStatus(std::string& statusOut); - void getStatus(std::string& statusOut) - { - mutexLock(&statusLock); - statusOut = status; - mutexUnlock(&statusLock); - } - -} threadStatus; + private: + Mutex statusLock = 0; + std::string status; +}; typedef struct { diff --git a/inc/ui/uistr.h b/inc/ui/uistr.h index dd27f19..73b9c56 100644 --- a/inc/ui/uistr.h +++ b/inc/ui/uistr.h @@ -1,28 +1,15 @@ #pragma once +#include + //Strings since translation support namespace ui { + void initStrings(); void loadTrans(); + void saveTranslationFile(void *a); + extern std::map, std::string> strings; - extern std::string author, userHelp, titleHelp, folderHelp, optHelp, \ - confBlacklist, confOverwrite, confRestore, confDel, confCopy, \ - confEraseNand, confEraseFolder, yt, nt, on, off, confirmHead, \ - copyHead, noSavesFound, errorConnecting, noUpdate, saveCreated, saveCreateFailed, \ - saveDataReset, saveDataResetSuccess, saveDataDeleteSuccess; - - //Strings for file mode menu - extern std::string advMenuStr[7]; - //Strings for extras menu - extern std::string exMenuStr[11]; - //Strings for options menu - extern std::string optMenuStr[18]; - //Strings for the holding thing - extern std::string holdingText[3]; - //Strings for sort type - extern std::string sortString[3]; - //Strings for user options - extern std::string usrOptString[2]; - //Strings for title options - extern std::string titleOptString[7]; + inline std::string getUIString(const std::string& _name, int ind){ return strings[std::make_pair(_name, ind)]; } + inline const char *getUICString(const std::string& _name, int ind){ return strings[std::make_pair(_name, ind)].c_str(); } } diff --git a/romfs/lang/en-US.txt b/romfs/lang/en-US.txt index 01ff3a4..a75d2a6 100644 --- a/romfs/lang/en-US.txt +++ b/romfs/lang/en-US.txt @@ -1,133 +1,114 @@ -#JKSV Switch translation guide -#Button strings [X] are replaced by JKSV at boot. -#string = set string to this. -#Translation author. Displayed in UI. NULL is ignored and not displayed. -author = "NULL" +#JKSV Translation File +#File can be placed and named "/JKSV/trans.txt" for testing without building +#Format is: stringName = index, "string" +#You only need to translate "string", there is no need to touch the other two parameters. +#'%s' is replaced with game titles and paths. '#', '*', '>', etc change text color. [x] are replaced with button glyphs +#This is exported from JKSV itself to make adding strings to this easier. +#It can also export already made translations with new strings if added, cutting down work for everyone. +#If there are issues with spacing, line breaking, untranslatable English text, etc let me know in a git issue or your pull request. -#Help/Guide strings on bottom -#User Select -userHelp = "[A] Select [Y] Dump All [X] UI Mode [R] Update [-] Options [ZR] Extras" - -#Title Select -titleHelp = "[A] Select [L][R] Change User [Y] Dump All [X] Favorite [-] BlackList [ZR] Erase [B] Back" - -#Folder Select -folderHelp = "[-] File Mode [L]/[R]+[A] Auto [A] Backup [Y] Restore [X] Delete Selected [ZR] Erase [B] Back" - -#Options Menu -optHelp = "[A] Toggle [X] Defaults [B] Back" - -#Button prompts. -yt = "Yes [A]" -nt = "No [B]" - -#On/Off for options. '>' is used to change color to green. -on = ">On>" -off = "Off" - -#Strings for messages/confirmation. '*' and '#' are used in strings to change color. %s is replaced with titles and names with sprintf. -#Text shown at the top of confirmation boxes -confirmHead = "Confirm" - -#Text shown at top of progress dialog when copying files -copyHead = "Copying File..." - -#Confirm blacklist. -confirmBlacklist = "Are you sure you want to add #%s# to your blacklist?" - -#Confirm overwriting folder -confirmOverwrite = "Are you sure you want to overwrite #%s#?" - -#Confirm restoring save -confirmRestore = "Are you sure you want to restore #%s#?" - -#Confirm deleting. -confirmDelete = "Are you sure you want to delete #%s#? *This is permanent*!" - -#Confirm file copy in file mode -confirmCopy = "Are you sure you want to copy #%s# to #%s#?" - -#Warning for erasing save data from system in title menu -confirmEraseNand = "*WARNING*: This *will* erase the save data for #%s# *from your system*. This is the same as deleting it from #Data Management#! Are you sure you want to continue?" - -#Warning for deleting save data in folder menu -confirmEraseFolder = "*WARNING*: This *will* delete the current save data for #%s# *from your system*! Are you sure you want to continue?" - -#Error displayed in pop-up if no titles are found for user. Rarely happens, but can for Device and BCAT -noSavesFound = "No save data found for #%s#!" - -#Error pop-up displayed when git can't be connected to -errorConnecting = "Error Connecting!" - -#Pop-up shown when no updates are found on git -noUpdate = "No updates available!" - -#Text displayed when holding is required. Should have a trailing space +#If author is not "NULL", your name will be displayed in the UI +author = 0, "NULL" +confirmBlacklist = 0, "Are you sure you want to add #%s# to your blacklist?" +confirmCopy = 0, "Are you sure you want to copy #%s# to #%s#?" +confirmDelete = 0, "Are you sure you want to delete #%s#? *This is permanent*!" +confirmDeleteSaveData = 0, "*WARNING*: This *will* erase the save data for #%s# *from your system*. Are you sure you want to do this?" +confirmOverwrite = 0, "Are you sure you want to overwrite #%s#?" +confirmResetSaveData = 0, "*WARNING*: This *will* reset the save data for this game as if it was never ran before. Are you sure you want to do this?" +confirmRestore = 0, "Are you sure you want to restore #%s#?" +dialogNo = 0, "No [B]" +dialogYes = 0, "Yes [A]" +extrasMenu = 0, "SD to SD Browser" +extrasMenu = 1, "BIS: ProdInfoF" +extrasMenu = 2, "BIS: Safe" +extrasMenu = 3, "BIS: System" +extrasMenu = 4, "BIS: User" +extrasMenu = 5, "Remove Pending Update" +extrasMenu = 6, "Terminate Process" +extrasMenu = 7, "Mount System Save" +extrasMenu = 8, "Rescan Titles" +extrasMenu = 9, "Mount Process RomFS" +extrasMenu = 10, "Backup JKSV Folder" +extrasMenu = 11, "*[DEV]* Output en-US" +fileModeMenu = 0, "Copy To " +fileModeMenu = 1, "Delete" +fileModeMenu = 2, "Rename" +fileModeMenu = 3, "Make Dir" +fileModeMenu = 4, "Properties" +fileModeMenu = 5, "Close" +fileModeMenu = 6, "Add to Path Filters" +helpFolder = 0, "[A] Select [Y] Restore [X] Delete [B] Close" +helpSettings = 0, "[A] Toggle [X] Defaults [B] Back" +helpTitle = 0, "[A] Select [L][R] Jump [Y] Favorite [X] Title Options [B] Back" +helpUser = 0, "[A] Select [X] User Options" holdingText = 0, "(Hold) " holdingText = 1, "(Keep Holding) " holdingText = 2, "(Almost There!) " - -#Menu options are held in arrays of strings. -#The number is the option to set, string is what to set to. -#Only the string after the comma needs to be edited. -#Adv/file mode menu -#'Copy to ' NEEDS a trailing space -advMenu = 0, "Copy to " -advMenu = 1, "Delete" -advMenu = 2, "Rename" -advMenu = 3, "Make Dir" -advMenu = 4, "Properties" -advMenu = 5, "Close" - -#Extras Menu -extMenu = 0, "SD to SD Browser" -extMenu = 1, "BIS: PRODINFOF" -extMenu = 2, "BIS: SAFE" -extMenu = 3, "BIS: SYSTEM" -extMenu = 4, "BIS: USER" -extMenu = 5, "Remove Update" -extMenu = 6, "Terminate Process" -extMenu = 7, "Mount System Save" -extMenu = 8, "Rescan Titles" -extMenu = 9, "Mount Process RomFS" -extMenu = 10, "Backup JKSV Folder" - -#Options menu -#All options need a trailing space. It is the most likely to have things added to it. -optMenu = 0, "Include Dev Sv: " -optMenu = 1, "AutoBackup: " -optMenu = 2, "Overclock: " -optMenu = 3, "Hold to Delete: " -optMenu = 4, "Hold to Restore: " -optMenu = 5, "Hold to Overwrite: " -optMenu = 6, "Force Mount: " -optMenu = 7, "Account Sys. Saves: " -optMenu = 8, "Write to Sys. Saves: " -optMenu = 9, "Text UI Mode: " -optMenu = 10, "Direct FS Cmd: " -optMenu = 11, "Skip User Select: " -optMenu = 12, "Export to ZIP: " -optMenu = 13, "Sort: " -optMenu = 14, "Language Override: " - -#Explanations of what options do. -optMenuExp = 0, "Includes Device Save data in user accounts." -optMenuExp = 1, "Automatically creates a save backup before restoring a save." -optMenuExp = 2, "Applies a small CPU overclock to 1224Mhz at boot. This is the same speed developer units run at." -optMenuExp = 3, "Whether or not holding [A] is required when deleting folders and files." -optMenuExp = 4, "Whether or not holding [A] is required when restoring save data." -optMenuExp = 5, "Whether or not holding [A] is required when overwriting saves on SD." -optMenuExp = 6, "When enabled, JKSV will only load and show save data that can be opened. When disabled, everything found will be shown." -optMenuExp = 7, "When enabled, system save data tied to accounts will be shown." -optMenuExp = 8, "Controls whether system save data and partitions can have files and data written and deleted from them. *This can be extremely dangerous if you don't know what you're doing!*" -optMenuExp = 9, "Changes the UI to be text menu based like the original JKSM for 3DS." -optMenuExp = 10, "Directly uses the Switch's FS commands to copy files instead of stdio." -optMenuExp = 11, "Skips the user selection screen and jumps directly to the first user account found." -optMenuExp = 12, "Exports saves to zip files." -optMenuExp = 13, "Changes the way titles are sorted and listed." -opeMenuExp = 14, "Forces English to be used regardless of system language." - -#Sort Types +onlineErrorConnecting = 0, "Error Connecting!" +onlineNoUpdates = 0, "No Updates Available." +popAddedToPathFilter = 0, "'#%s#' added to path filters." +popCPUBoostEnabled = 0, "CPU Boost Enabled for ZIP." +popErrorCommittingFile = 0, "Error committing file to save!" +popProcessShutdown = 0, "#%s# successfully shutdown." +saveDataBackupDeleted = 0, "#%s# has been deleted." +saveDataBackupMovedToTrash = 0, "#%s# has been moved to trash." +saveDataCreatedForUser = 0, "Save data created for %s!" +saveDataCreationFailed = 0, "Save data creation failed!" +saveDataDeleteAllUser = 0, "*ARE YOU SURE YOU WANT TO DELETE ALL SAVE DATA FOR %s?*" +saveDataDeleteSuccess = 0, "Save data for #%s# deleted!" +saveDataExtendFailed = 0, "Failed to extend save data." +saveDataExtendSuccess = 0, "Save data for #%s# extended!" +saveDataNoneFound = 0, "No saves found for #%s#!" +saveDataResetSuccess = 0, "Save for #%s# reset!" +settingsMenu = 0, "Empty Trash Bin" +settingsMenu = 1, "Check for Updates" +settingsMenu = 2, "Set JKSV Save Output Folder" +settingsMenu = 3, "Include Device Saves With Users: " +settingsMenu = 4, "Auto Backup On Restore: " +settingsMenu = 5, "Overclock/CPU Boost: " +settingsMenu = 6, "Hold To Delete: " +settingsMenu = 7, "Hold To Restore: " +settingsMenu = 8, "Hold To Overwrite: " +settingsMenu = 9, "Force Mount: " +settingsMenu = 10, "Account System Saves: " +settingsMenu = 11, "Enable Writing to System Saves: " +settingsMenu = 12, "Use FS Commands Directly: " +settingsMenu = 13, "Export Saves to ZIP: " +settingsMenu = 14, "Force English To Be Used: " +settingsMenu = 15, "Enable Trash Bin: " +settingsMenu = 16, "Title Sorting Type: " +settingsMenu = 17, "Animation Scale: " +settingsOff = 0, "Off" +settingsOn = 0, ">On>" sortType = 0, "Alphabetical" sortType = 1, "Time Played" sortType = 2, "Last Played" +swkbdEnterName = 0, "Enter a new name" +swkbdMkDir = 0, "Enter a folder name" +swkbdProcessID = 0, "Enter Process ID" +swkbdRename = 0, "Enter a new name for item" +swkbdSaveIndex = 0, "Enter Cache Index" +swkbdSetWorkDir = 0, "Enter a new Output Path" +swkbdSysSavID = 0, "Enter System Save ID" +threadStatusAddingFileToZip = 0, "Adding '#%s#' to ZIP..." +threadStatusCheckingForUpdate = 0, "Checking for updates..." +threadStatusCopyingFile = 0, "Copying '#%s#'..." +threadStatusCreatingSaveData = 0, "Creating Save Data for #%s#..." +threadStatusDecompressingFile = 0, "Decompressing '#%s#'..." +threadStatusDeletingFile = 0, "Deleting..." +threadStatusDeletingSaveData = 0, "Deleting Save Data for #%s#..." +threadStatusDeletingUpdate = 0, "Deleting pending update..." +threadStatusDownloadingUpdate = 0, "Downloading update..." +threadStatusExtendingSaveData = 0, "Extending Save Data for #%s#..." +threadStatusOpeningFolder = 0, "Opening '#%s#'..." +threadStatusResettingSaveData = 0, "Resetting save data..." +titleOptions = 0, "Information" +titleOptions = 1, "Blacklist" +titleOptions = 2, "Change Output Folder" +titleOptions = 3, "Open in File Mode" +titleOptions = 4, "Reset Save Data" +titleOptions = 5, "Delete Save Data" +titleOptions = 6, "Extend Save Data" +userOptions = 0, "Create Save Data" +userOptions = 1, "Create All Save Data" +userOptions = 2, "Delete All User Saves" diff --git a/src/cfg.cpp b/src/cfg.cpp index 5ba4556..411ccbf 100644 --- a/src/cfg.cpp +++ b/src/cfg.cpp @@ -14,13 +14,13 @@ static std::vector blacklist; static std::vector favorites; static std::unordered_map pathDefs; uint8_t cfg::sortType; -const char *cfgPath = "sdmc:/config/JKSV/JKSV.cfg"; +const char *cfgPath = "sdmc:/config/JKSV/JKSV.cfg", *titleDefPath = "sdmc:/config/JKSV/titleDefs.txt", *workDirLegacy = "sdmc:/switch/jksv_dir.txt"; static std::unordered_map cfgStrings = { {"workDir", 0}, {"includeDeviceSaves", 1}, {"autoBackup", 2}, {"overclock", 3}, {"holdToDelete", 4}, {"holdToRestore", 5}, {"holdToOverwrite", 6}, {"forceMount", 7}, {"accountSystemSaves", 8}, {"allowSystemSaveWrite", 9}, {"directFSCommands", 10}, {"exportToZIP", 11}, {"languageOverride", 12}, {"enableTrashBin", 13}, {"titleSortType", 14}, {"animationScale", 15}, - {"favorite", 16}, {"blacklist", 17}, {"pathDef", 18} + {"favorite", 16}, {"blacklist", 17} }; const std::string _true_ = "true", _false_ = "false"; @@ -37,7 +37,8 @@ bool cfg::isBlacklisted(const uint64_t& tid) void cfg::addTitleToBlacklist(void *a) { threadInfo *t = (threadInfo *)a; - uint64_t tid = data::curData.saveID; + data::userTitleInfo *d = data::getCurrentUserTitleInfo(); + uint64_t tid = d->saveID; blacklist.push_back(tid); for(data::user& u : data::users) { @@ -169,8 +170,105 @@ static inline std::string sortTypeText() return ""; } +static void loadWorkDirLegacy() +{ + if(fs::fileExists(workDirLegacy)) + { + char tmp[256]; + memset(tmp, 0, 256); + + FILE *getDir = fopen(workDirLegacy, "r"); + fgets(tmp, FS_MAX_PATH, getDir); + fclose(getDir); + std::string tmpStr = tmp; + util::stripChar('\n', tmpStr); + util::stripChar('\r', tmpStr); + fs::setWorkDir(tmpStr); + fs::delfile(workDirLegacy); + } +} + +static void loadConfigLegacy() +{ + std::string legacyCfgPath = fs::getWorkDir() + "cfg.bin"; + if(fs::fileExists(legacyCfgPath)) + { + FILE *oldCfg = fopen(legacyCfgPath.c_str(), "rb"); + uint64_t cfgIn = 0; + fread(&cfgIn, sizeof(uint64_t), 1, oldCfg); + fread(&cfg::sortType, 1, 1, oldCfg); + fread(&ui::animScale, sizeof(float), 1, oldCfg); + if(ui::animScale == 0) + ui::animScale = 3.0f; + fclose(oldCfg); + + cfg::config["incDev"] = cfgIn >> 63 & 1; + cfg::config["autoBack"] = cfgIn >> 62 & 1; + cfg::config["ovrClk"] = cfgIn >> 61 & 1; + cfg::config["holdDel"] = cfgIn >> 60 & 1; + cfg::config["holdRest"] = cfgIn >> 59 & 1; + cfg::config["holdOver"] = cfgIn >> 58 & 1; + cfg::config["forceMount"] = cfgIn >> 57 & 1; + cfg::config["accSysSave"] = cfgIn >> 56 & 1; + cfg::config["sysSaveWrite"] = cfgIn >> 55 & 1; + cfg::config["directFsCmd"] = cfgIn >> 53 & 1; + cfg::config["zip"] = cfgIn >> 51 & 1; + cfg::config["langOverride"] = cfgIn >> 50 & 1; + cfg::config["trashBin"] = cfgIn >> 49 & 1; + fs::delfile(cfgPath); + } +} + +static void loadFavoritesLegacy() +{ + std::string legacyFavPath = fs::getWorkDir() + "favorites.txt"; + if(fs::fileExists(legacyFavPath)) + { + fs::dataFile fav(legacyFavPath); + while(fav.readNextLine(false)) + favorites.push_back(strtoul(fav.getLine().c_str(), NULL, 16)); + fav.close(); + fs::delfile(legacyFavPath); + } +} + +static void loadBlacklistLegacy() +{ + std::string legacyBlPath = fs::getWorkDir() + "blacklist.txt"; + if(fs::fileExists(legacyBlPath)) + { + fs::dataFile bl(legacyBlPath); + while(bl.readNextLine(false)) + blacklist.push_back(strtoul(bl.getLine().c_str(), NULL, 16)); + bl.close(); + fs::delfile(legacyBlPath); + } +} + +static void loadTitleDefs() +{ + std::string titleDefLegacy = fs::getWorkDir() + "titleDefs.txt"; + if(fs::fileExists(titleDefLegacy)) + rename(titleDefLegacy.c_str(), titleDefPath); + + if(fs::fileExists(titleDefPath)) + { + fs::dataFile getPaths(titleDefPath); + while(getPaths.readNextLine(true)) + { + uint64_t tid = strtoul(getPaths.getName().c_str(), NULL, 16); + pathDefs[tid] = getPaths.getNextValueStr(); + } + } +} + void cfg::loadConfig() { + loadWorkDirLegacy(); + loadConfigLegacy(); + loadFavoritesLegacy(); + loadBlacklistLegacy(); + if(fs::fileExists(cfgPath)) { fs::dataFile cfgRead(cfgPath); @@ -256,7 +354,7 @@ void cfg::loadConfig() case 16: { std::string tid = cfgRead.getNextValueStr(); - favorites.push_back(strtoul(tid.c_str(), NULL, 16)); + favorites.push_back(strtoul(tid.c_str(), NULL, 16)); } break; @@ -266,16 +364,18 @@ void cfg::loadConfig() blacklist.push_back(strtoul(tid.c_str(), NULL, 16)); } break; - - case 18: - { - uint64_t tid = strtoul(cfgRead.getNextValueStr().c_str(), NULL, 16); - pathDefs[tid] = cfgRead.getNextValueStr(); - } - break; } } } + loadTitleDefs(); +} + +static void savePathDefs() +{ + FILE *pathOut = fopen(titleDefPath, "w"); + for(auto& p : pathDefs) + fprintf(pathOut, "0x%016lX = \"%s\"\n", p.first, p.second.c_str()); + fclose(pathOut); } void cfg::saveConfig() @@ -287,7 +387,7 @@ void cfg::saveConfig() fprintf(cfgOut, "overclock = %s\n", boolToText(cfg::config["ovrClk"]).c_str()); fprintf(cfgOut, "holdToDelete = %s\n", boolToText(cfg::config["holdDel"]).c_str()); fprintf(cfgOut, "holdToRestore = %s\n", boolToText(cfg::config["holdRest"]).c_str()); - fprintf(cfgOut, "holdToOverwrite = %s\n", boolToText(cfg::config["autoOver"]).c_str()); + fprintf(cfgOut, "holdToOverwrite = %s\n", boolToText(cfg::config["holdOver"]).c_str()); fprintf(cfgOut, "forceMount = %s\n", boolToText(cfg::config["forceMount"]).c_str()); fprintf(cfgOut, "accountSystemSaves = %s\n", boolToText(cfg::config["accSysSaves"]).c_str()); fprintf(cfgOut, "allowSystemSaveWrite = %s\n", boolToText(cfg::config["sysSaveWrite"]).c_str()); @@ -311,12 +411,8 @@ void cfg::saveConfig() for(uint64_t& b : blacklist) fprintf(cfgOut, "blacklist = 0x%016lX\n", b); } + fclose(cfgOut); if(!pathDefs.empty()) - { - fprintf(cfgOut, "\n#Output Path Definitions\n"); - for(auto& p : pathDefs) - fprintf(cfgOut, "pathDef(0x%016lX, \"%s\")\n", p.first, p.second.c_str()); - } - fclose(cfgOut); + savePathDefs(); } diff --git a/src/data.cpp b/src/data.cpp index eeddd47..f90733d 100644 --- a/src/data.cpp +++ b/src/data.cpp @@ -16,7 +16,7 @@ //FsSaveDataSpaceId_All doesn't work for SD static const unsigned saveOrder [] = { 0, 1, 2, 3, 4, 100, 101 }; -int data::selUser = 0, data::selData = 0; +int selUser = 0, selData = 0; //User vector std::vector data::users; @@ -328,6 +328,36 @@ void data::exit() util::setCPU(1020000000); } +void data::setUserIndex(unsigned _sUser) +{ + selUser = _sUser; +} + +data::user *data::getCurrentUser() +{ + return &users[selUser]; +} + +unsigned data::getCurrentUserIndex() +{ + return selUser; +} + +void data::setTitleIndex(unsigned _sTitle) +{ + selData = _sTitle; +} + +data::userTitleInfo *data::getCurrentUserTitleInfo() +{ + return &users[selUser].titleInfo[selData]; +} + +unsigned data::getCurrentUserTitleInfoIndex() +{ + return selData; +} + data::titleInfo *data::getTitleInfoByTID(const uint64_t& tid) { if(titles.find(tid) != titles.end()) @@ -413,13 +443,16 @@ static const SDL_Color green = {0x00, 0xDD, 0x00, 0xFF}; void data::dispStats() { + data::user *cu = data::getCurrentUser(); + data::userTitleInfo *d = data::getCurrentUserTitleInfo(); + //Easiest/laziest way to do this std::string stats = "User Count: " + std::to_string(users.size()) + "\n"; for(data::user& u : data::users) stats += u.getUsername() + ": " + std::to_string(u.titleInfo.size()) + "\n"; - stats += "Current User: " + data::curUser.getUsername() + "\n"; - stats += "Current Title: " + data::getTitleNameByTID(data::curData.saveID) + "\n"; - stats += "Safe Title: " + data::getTitleSafeNameByTID(data::curData.saveID) + "\n"; + stats += "Current User: " + cu->getUsername() + "\n"; + stats += "Current Title: " + data::getTitleNameByTID(d->saveID) + "\n"; + stats += "Safe Title: " + data::getTitleSafeNameByTID(d->saveID) + "\n"; stats += "Sort Type: " + std::to_string(cfg::sortType) + "\n"; gfx::drawTextf(NULL, 16, 2, 2, &green, stats.c_str()); } diff --git a/src/file.cpp b/src/file.cpp index 2cd2f00..465f684 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -87,12 +87,27 @@ bool fs::commitToDevice(const std::string& dev) if(R_FAILED(res)) { fs::logWrite("Error committing file to device -> 0x%X\n", res); - ui::showPopMessage(POP_FRAME_DEFAULT, "Error committing file to device!"); + ui::showPopMessage(POP_FRAME_DEFAULT, ui::getUICString("popErrorCommittingFile", 0)); ret = false; } return ret; } +void fs::createSaveData(FsSaveDataType _type, uint64_t _tid, AccountUid _userID) +{ + std::string indexStr; + uint16_t index = 0; + if(_type == FsSaveDataType_Cache && !(indexStr = util::getStringInput(SwkbdType_NumPad, "0", ui::getUIString("swkbdSaveIndex", 0), 3, 0, NULL)).empty()) + index = strtoul(indexStr.c_str(), NULL, 10); + + svCreateArgs *send = new svCreateArgs; + send->type = _type; + send->account = _userID; + send->tid = _tid; + send->index = index; + ui::newThread(fs::createSaveData_t, send, NULL); +} + void fs::init() { mkDirRec("sdmc:/config/JKSV/"); @@ -343,7 +358,7 @@ void fs::copyDirToZip(const std::string& from, zipFile to) if(cfg::config["ovrClk"]) { util::setCPU(1785000000); - ui::showPopMessage(POP_FRAME_DEFAULT, "CPU Boost Enabled for ZIP."); + ui::showPopMessage(POP_FRAME_DEFAULT, ui::getUICString("popCPUBoostEnabled", 0)); } copyArgs *send = copyArgsCreate(from, "", "", to, NULL, true); ui::newThread(copyDirToZip_t, send, _fileDrawFunc); @@ -354,7 +369,7 @@ void fs::copyZipToDir(unzFile unz, const std::string& to, const std::string& dev if(cfg::config["ovrClk"]) { util::setCPU(1785000000); - ui::showPopMessage(POP_FRAME_DEFAULT, "CPU Boost Enabled for ZIP."); + ui::showPopMessage(POP_FRAME_DEFAULT, ui::getUICString("popCPUBoostEnabled", 0)); } copyArgs *send = copyArgsCreate("", to, dev, NULL, unz, true); ui::newThread(copyZipToDir_t, send, _fileDrawFunc); @@ -579,14 +594,18 @@ void fs::createNewBackup(void *a) { uint64_t held = ui::padKeysHeld(); + data::user *u = data::getCurrentUser(); + data::userTitleInfo *d = data::getCurrentUserTitleInfo(); + data::titleInfo *t = data::getTitleInfoByTID(d->saveID); + std::string out; if(held & HidNpadButton_R) - out = data::users[data::selUser].getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YMD); + out = u->getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YMD); else if(held & HidNpadButton_L) - out = data::users[data::selUser].getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YDM); + out = u->getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YDM); else if(held & HidNpadButton_ZL) - out = data::users[data::selUser].getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_HOYSTE); + out = u->getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_HOYSTE); else { const std::string dict[] = @@ -596,19 +615,19 @@ void fs::createNewBackup(void *a) util::getDateTime(util::DATE_FMT_HOYSTE), util::getDateTime(util::DATE_FMT_JHK), util::getDateTime(util::DATE_FMT_ASC), - data::users[data::selUser].getUsernameSafe(), - data::getTitleInfoByTID(data::curData.saveID)->safeTitle, - util::generateAbbrev(data::curData.saveID), + u->getUsernameSafe(), + t->safeTitle, + util::generateAbbrev(d->saveID), ".zip" }; - std::string defaultText = data::curUser.getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YMD); - out = util::getStringInput(SwkbdType_QWERTY, defaultText, "Enter a name", 64, 9, dict); + std::string defaultText = u->getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YMD); + out = util::getStringInput(SwkbdType_QWERTY, defaultText, ui::getUIString("swkbdEnterName", 0), 64, 9, dict); } if(!out.empty()) { std::string ext = util::getExtensionFromString(out); - std::string path = util::generatePathByTID(data::curData.saveID) + out; + std::string path = util::generatePathByTID(d->saveID) + out; if(cfg::config["zip"] || ext == "zip") { if(ext != "zip")//data::zip is on but extension is not zip @@ -635,12 +654,14 @@ void fs::overwriteBackup(void *a) ui::menu *m = in->m; fs::dirList *d = in->d; + data::userTitleInfo *cd = data::getCurrentUserTitleInfo(); + unsigned ind = m->getSelected() - 1;;//Skip new std::string itemName = d->getItem(ind); if(d->isDir(ind)) { - std::string toPath = util::generatePathByTID(data::curData.saveID) + itemName + "/"; + std::string toPath = util::generatePathByTID(cd->saveID) + itemName + "/"; //Delete and recreate fs::delDir(toPath); mkdir(toPath.c_str(), 777); @@ -648,7 +669,7 @@ void fs::overwriteBackup(void *a) } else if(!d->isDir(ind) && d->getItemExt(ind) == "zip") { - std::string toPath = util::generatePathByTID(data::curData.saveID) + itemName; + std::string toPath = util::generatePathByTID(cd->saveID) + itemName; fs::delfile(toPath); zipFile zip = zipOpen64(toPath.c_str(), 0); fs::copyDirToZip("sv:/", zip); @@ -663,27 +684,29 @@ void fs::restoreBackup(void *a) ui::menu *m = in->m; fs::dirList *d = in->d; + data::user *u = data::getCurrentUser(); + data::userTitleInfo *cd = data::getCurrentUserTitleInfo(); unsigned ind = m->getSelected() - 1; std::string itemName = d->getItem(ind); - if((data::curData.saveInfo.save_data_type != FsSaveDataType_System || cfg::config["sysSaveWrite"]) && m->getSelected() > 0) + if((cd->saveInfo.save_data_type != FsSaveDataType_System || cfg::config["sysSaveWrite"]) && m->getSelected() > 0) { if(cfg::config["autoBack"] && cfg::config["zip"]) { - std::string autoZip = util::generatePathByTID(data::curData.saveID) + "/AUTO " + data::curUser.getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YMD) + ".zip"; + std::string autoZip = util::generatePathByTID(cd->saveID) + "/AUTO " + u->getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YMD) + ".zip"; zipFile zip = zipOpen64(autoZip.c_str(), 0); fs::copyDirToZip("sv:/", zip); } else if(cfg::config["autoBack"]) { - std::string autoFolder = util::generatePathByTID(data::curData.saveID) + "/AUTO - " + data::curUser.getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YMD) + "/"; + std::string autoFolder = util::generatePathByTID(cd->saveID) + "/AUTO - " + u->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)) { - std::string fromPath = util::generatePathByTID(data::curData.saveID) + itemName + "/"; + std::string fromPath = util::generatePathByTID(cd->saveID) + itemName + "/"; if(fs::dirNotEmpty(fromPath)) { fs::wipeSave(); @@ -694,7 +717,7 @@ void fs::restoreBackup(void *a) } else if(!d->isDir(ind) && d->getItemExt(ind) == "zip") { - std::string path = util::generatePathByTID(data::curData.saveID) + itemName; + std::string path = util::generatePathByTID(cd->saveID) + itemName; unzFile unz = unzOpen64(path.c_str()); if(unz && fs::zipNotEmpty(unz)) { @@ -707,7 +730,7 @@ void fs::restoreBackup(void *a) else { //Just copy file over - std::string fromPath = util::generatePathByTID(data::curData.saveID) + itemName; + std::string fromPath = util::generatePathByTID(cd->saveID) + itemName; std::string toPath = "sv:/" + itemName; fs::copyFileCommit(fromPath, toPath, "sv"); } @@ -726,29 +749,29 @@ void fs::deleteBackup(void *a) ui::menu *m = in->m; fs::dirList *d = in->d; + data::userTitleInfo *cd = data::getCurrentUserTitleInfo(); unsigned ind = m->getSelected() - 1; std::string itemName = d->getItem(ind); - t->status->setStatus("Deleting '" + itemName + "'..."); - + t->status->setStatus("Deleting..."); if(cfg::config["trashBin"]) { - std::string oldPath = util::generatePathByTID(data::curData.saveID) + itemName; + std::string oldPath = util::generatePathByTID(cd->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()); + ui::showPopMessage(POP_FRAME_DEFAULT, ui::getUICString("saveDataBackupMovedToTrash", 0), itemName.c_str()); } else if(d->isDir(ind)) { - std::string delPath = util::generatePathByTID(data::curData.saveID) + itemName + "/"; + std::string delPath = util::generatePathByTID(cd->saveID) + itemName + "/"; fs::delDir(delPath); - ui::showPopMessage(POP_FRAME_DEFAULT, "%s has been deleted.", itemName.c_str()); + ui::showPopMessage(POP_FRAME_DEFAULT, ui::getUICString("saveDataBackupDeleted", 0), itemName.c_str()); } else { - std::string delPath = util::generatePathByTID(data::curData.saveID) + itemName; + std::string delPath = util::generatePathByTID(cd->saveID) + itemName; fs::delfile(delPath); - ui::showPopMessage(POP_FRAME_DEFAULT, "%s has been deleted.", itemName.c_str()); + ui::showPopMessage(POP_FRAME_DEFAULT, ui::getUICString("saveDataBackupDeleted", 0), itemName.c_str()); } ui::populateFldMenu(); t->finished = true; diff --git a/src/fsthrd.cpp b/src/fsthrd.cpp index 81beec0..33b3dda 100644 --- a/src/fsthrd.cpp +++ b/src/fsthrd.cpp @@ -7,7 +7,8 @@ static uint64_t getJournalSize(const data::titleInfo *t) { uint64_t journalSize = 0; - switch(data::curData.saveInfo.save_data_type) + data::userTitleInfo *d = data::getCurrentUserTitleInfo(); + switch(d->saveInfo.save_data_type) { case FsSaveDataType_Account: journalSize = t->nacp.user_account_save_data_journal_size; @@ -49,11 +50,90 @@ void fs::_fileDrawFunc(void *a) } } +void fs::createSaveData_t(void *a) +{ + threadInfo *t = (threadInfo *)a; + fs::svCreateArgs *s = (fs::svCreateArgs *)t->argPtr; + + data::titleInfo *create = data::getTitleInfoByTID(s->tid); + t->status->setStatus(ui::getUICString("threadStatusCreatingSaveData", 0), create->title.c_str()); + + FsSaveDataAttribute attr; + memset(&attr, 0, sizeof(FsSaveDataAttribute)); + attr.application_id = s->tid; + attr.uid = s->account; + attr.system_save_data_id = 0; + attr.save_data_type = s->type; + attr.save_data_rank = 0; + attr.save_data_index = s->index; + + FsSaveDataCreationInfo svCreate; + memset(&svCreate, 0, sizeof(FsSaveDataCreationInfo)); + int64_t saveSize = 0, journalSize = 0; + switch(s->type) + { + case FsSaveDataType_Account: + saveSize = create->nacp.user_account_save_data_size; + journalSize = create->nacp.user_account_save_data_journal_size; + break; + + case FsSaveDataType_Device: + saveSize = create->nacp.device_save_data_size; + journalSize = create->nacp.device_save_data_journal_size; + break; + + case FsSaveDataType_Bcat: + saveSize = create->nacp.bcat_delivery_cache_storage_size; + journalSize = create->nacp.bcat_delivery_cache_storage_size; + break; + + case FsSaveDataType_Cache: + saveSize = 32 * 1024 * 1024;//Todo: Add target folder/zip selection for size + if(create->nacp.cache_storage_journal_size > create->nacp.cache_storage_data_and_journal_size_max) + journalSize = create->nacp.cache_storage_journal_size; + else + journalSize = create->nacp.cache_storage_data_and_journal_size_max; + break; + + default: + delete s; + t->finished = true; + return; + break; + } + svCreate.save_data_size = saveSize; + svCreate.journal_size = journalSize; + svCreate.available_size = 0x4000; + svCreate.owner_id = create->nacp.save_data_owner_id; + svCreate.flags = 0; + svCreate.save_data_space_id = FsSaveDataSpaceId_User; + + FsSaveDataMetaInfo meta; + memset(&meta, 0, sizeof(FsSaveDataMetaInfo)); + meta.size = 0x40060; + meta.type = FsSaveDataMetaType_Thumbnail; + + Result res = 0; + if(R_SUCCEEDED(res = fsCreateSaveDataFileSystem(&attr, &svCreate, &meta))) + { + util::createTitleDirectoryByTID(s->tid); + data::loadUsersTitles(false); + ui::ttlRefresh(); + } + else + { + ui::showPopMessage(POP_FRAME_DEFAULT, ui::getUICString("saveDataCreationFailed", 0)); + fs::logWrite("SaveCreate Failed -> %X\n", res); + } + delete s; + t->finished = true; +} + void fs::copyFile_t(void *a) { threadInfo *t = (threadInfo *)a; copyArgs *args = (copyArgs *)t->argPtr; - t->status->setStatus("Copying '" + args->from + "'..."); + t->status->setStatus(ui::getUICString("threadStatusCopyingFile", 0), args->from.c_str()); args->prog->setMax(fs::fsize(args->from)); args->prog->update(0); @@ -117,8 +197,9 @@ void fs::copyFileCommit_t(void *a) { threadInfo *t = (threadInfo *)a; copyArgs *args = (copyArgs *)t->argPtr; - data::titleInfo *info = data::getTitleInfoByTID(data::curData.saveID); - t->status->setStatus("Copying '" + args->from + "'..."); + data::userTitleInfo *d = data::getCurrentUserTitleInfo(); + data::titleInfo *info = data::getTitleInfoByTID(d->saveID); + t->status->setStatus(ui::getUICString("threadStatusCopyingFile", 0), args->from.c_str()); args->prog->setMax(fs::fsize(args->from)); args->prog->update(0); @@ -316,7 +397,7 @@ void fs::copyDirToZip_t(void *a) threadInfo *t = (threadInfo *)a; copyArgs *args = (copyArgs *)t->argPtr; - t->status->setStatus("Opening " + args->from + "..."); + t->status->setStatus(ui::getUICString("threadStatusOpeningFolder", 0), args->from.c_str()); fs::dirList *list = new fs::dirList(args->from); unsigned listTotal = list->getCount(); @@ -346,7 +427,7 @@ void fs::copyDirToZip_t(void *a) zip_fileinfo inf = {0}; std::string filename = args->from + itm; size_t devPos = filename.find_first_of('/') + 1; - t->status->setStatus("Adding '" + itm + "' to ZIP."); + t->status->setStatus(ui::getUICString("threadStatusAddingFileToZip", 0), itm.c_str()); int zOpenFile = zipOpenNewFileInZip64(args->z, filename.substr(devPos, filename.length()).c_str(), &inf, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION, 0); if(zOpenFile == ZIP_OK) { @@ -386,7 +467,8 @@ void fs::copyZipToDir_t(void *a) threadInfo *t = (threadInfo *)a; copyArgs *args = (copyArgs *)t->argPtr; - data::titleInfo *tinfo = data::getTitleInfoByTID(data::curData.saveID); + data::userTitleInfo *d = data::getCurrentUserTitleInfo(); + data::titleInfo *tinfo = data::getTitleInfoByTID(d->saveID); uint64_t journalSize = getJournalSize(tinfo), writeCount = 0; char filename[FS_MAX_PATH]; uint8_t *buff = new uint8_t[BUFF_SIZE]; @@ -397,7 +479,7 @@ void fs::copyZipToDir_t(void *a) unzGetCurrentFileInfo64(args->unz, &info, filename, FS_MAX_PATH, NULL, 0, NULL, 0); if(unzOpenCurrentFile(args->unz) == UNZ_OK) { - t->status->setStatus("Copying '" + std::string(filename) + "'..."); + t->status->setStatus(ui::getUICString("threadStatusDecompressingFile", 0), filename); std::string path = args->to + filename; mkDirRec(path.substr(0, path.find_last_of('/') + 1)); @@ -470,7 +552,7 @@ void fs::copyZipToDir_t(void *a) void fs::wipesave_t(void *a) { threadInfo *t = (threadInfo *)a; - t->status->setStatus("Resetting current save..."); + t->status->setStatus(ui::getUICString("threadStatusResettingSaveData", 0)); fs::delDir("sv:/"); fs::commitToDevice("sv"); t->finished = true; diff --git a/src/type.cpp b/src/type.cpp new file mode 100644 index 0000000..15325e6 --- /dev/null +++ b/src/type.cpp @@ -0,0 +1,25 @@ +#include +#include +#include + +#include "type.h" + +void threadStatus::setStatus(const char *fmt, ...) +{ + char tmp[1024]; + va_list args; + va_start(args, fmt); + vsprintf(tmp, fmt, args); + va_end(args); + + mutexLock(&statusLock); + status = tmp; + mutexUnlock(&statusLock); +} + +void threadStatus::getStatus(std::string& statusOut) +{ + mutexLock(&statusLock); + statusOut = status; + mutexUnlock(&statusLock); +} diff --git a/src/ui.cpp b/src/ui.cpp index ba10f6b..b7cd7cb 100644 --- a/src/ui.cpp +++ b/src/ui.cpp @@ -46,8 +46,6 @@ SDL_Texture *ui::sideBar; static SDL_Texture *icn, *corePanel; SDL_Color ui::heartColor = {0xFF, 0x44, 0x44, 0xFF}; -//X position of help texts. Calculated to make editing quicker/easier -static unsigned userHelpX, titleHelpX, folderHelpX, optHelpX; static int settPos, extPos; //Vector of pointers to slideOutPanels. Is looped and drawn last so they are always on top @@ -77,7 +75,7 @@ void ui::initTheme() rectSh = {0xCA, 0xCA, 0xCA, 0xFF}; tboxClr = {0xEB, 0xEB, 0xEB, 0xFF}; divClr = {0x00, 0x00, 0x00, 0xFF}; - slidePanelColor = {0xEE, 0xEE, 0xEE, 0xDD}; + slidePanelColor = {0xEE, 0xEE, 0xEE, 0xEE}; break; default: @@ -91,7 +89,7 @@ void ui::initTheme() rectSh = {0x20, 0x20, 0x20, 0xFF}; tboxClr = {0x50, 0x50, 0x50, 0xFF}; divClr = {0xFF, 0xFF, 0xFF, 0xFF}; - slidePanelColor = {0x00, 0x00, 0x00, 0xDD}; + slidePanelColor = {0x00, 0x00, 0x00, 0xEE}; break; } } @@ -136,18 +134,12 @@ void ui::init() loadTrans(); //Replace the button [x] in strings that need it. Needs to be outside loadTrans so even defaults will get replaced - util::replaceButtonsInString(ui::userHelp); - util::replaceButtonsInString(ui::titleHelp); - util::replaceButtonsInString(ui::folderHelp); - util::replaceButtonsInString(ui::optHelp); - util::replaceButtonsInString(ui::yt); - util::replaceButtonsInString(ui::nt); - - //Calculate x position of help text - userHelpX = 1220 - gfx::getTextWidth(ui::userHelp.c_str(), 18); - titleHelpX = 1220 - gfx::getTextWidth(ui::titleHelp.c_str(), 18); - folderHelpX = 1220 - gfx::getTextWidth(ui::folderHelp.c_str(), 18); - optHelpX = 1220 - gfx::getTextWidth(ui::optHelp.c_str(), 18); + util::replaceButtonsInString(ui::strings[std::make_pair("helpUser", 0)]); + util::replaceButtonsInString(ui::strings[std::make_pair("helpTitle", 0)]); + util::replaceButtonsInString(ui::strings[std::make_pair("helpFolder", 0)]); + util::replaceButtonsInString(ui::strings[std::make_pair("helpSettings", 0)]); + util::replaceButtonsInString(ui::strings[std::make_pair("dialogYes", 0)]); + util::replaceButtonsInString(ui::strings[std::make_pair("dialogNo", 0)]); //setup pad padConfigureInput(1, HidNpadStyleSet_NpadStandard); @@ -231,8 +223,11 @@ void ui::drawUI() //Version / translation author gfx::drawTextf(NULL, 12, 8, 700, &ui::txtCont, "v. %02d.%02d.%04d", BLD_MON, BLD_DAY, BLD_YEAR); - if(author != "NULL") - gfx::drawTextf(NULL, 12, 8, 682, &ui::txtCont, "Translation: %s", author.c_str()); + if(ui::getUIString("author", 0) != "NULL") + gfx::drawTextf(NULL, 12, 8, 682, &ui::txtCont, "Translation: %s", ui::getUICString("author", 0)); + + //This only draws the help text now and only does when user select is open + ui::usrDraw(NULL); if((ui::usrMenu->getActive() && ui::usrMenu->getSelected() == settPos) || ui::mstate == OPT_MNU) ui::settDraw(corePanel); @@ -316,12 +311,17 @@ void ui::showPopMessage(int frameCount, const char *fmt, ...) void ui::toTTL(void *a) { - if(data::curUser.titleInfo.size() > 0) + data::user *u = data::getCurrentUser(); + unsigned curUserIndex = data::getCurrentUserIndex(); + if(u->titleInfo.size() > 0) { ui::changeState(TTL_SEL); - ui::ttlSetActive(data::selUser); + ui::ttlSetActive(curUserIndex); ui::usrMenu->setActive(false); } else - ui::showPopMessage(POP_FRAME_DEFAULT, ui::noSavesFound.c_str(), data::curUser.getUsername().c_str()); + { + data::user *u = data::getCurrentUser(); + ui::showPopMessage(POP_FRAME_DEFAULT, ui::getUICString("saveDataNoneFound", 0), u->getUsername().c_str()); + } } diff --git a/src/ui/ext.cpp b/src/ui/ext.cpp index d026cb8..fbc43c3 100644 --- a/src/ui/ext.cpp +++ b/src/ui/ext.cpp @@ -75,7 +75,7 @@ static void toFMUser(void *a) static void _delUpdate(void *a) { threadInfo *t = (threadInfo *)a; - t->status->setStatus("Deleting update from NAND..."); + t->status->setStatus(ui::getUICString("threadStatusDeletingUpdate", 0)); FsFileSystem sys; fsOpenBisFileSystem(&sys, FsBisPartitionId_System, ""); fsdevMountDevice("sys", sys); @@ -91,19 +91,19 @@ static void extMenuOptRemoveUpdate(void *a) static void extMenuTerminateProcess(void *a) { - std::string idStr = util::getStringInput(SwkbdType_QWERTY, "0100000000000000", "Enter Process ID", 18, 0, NULL); + std::string idStr = util::getStringInput(SwkbdType_QWERTY, "0100000000000000", ui::getUIString("swkbdProcessID", 0), 18, 0, NULL); if(!idStr.empty()) { uint64_t termID = std::strtoull(idStr.c_str(), NULL, 16); if(R_SUCCEEDED(pmshellTerminateProgram(termID))) - ui::showPopMessage(POP_FRAME_DEFAULT, "Process %s successfully shutdown.", idStr.c_str()); + ui::showPopMessage(POP_FRAME_DEFAULT, ui::getUICString("popProcessShutdown", 0), idStr.c_str()); } } static void extMenuMountSysSave(void *a) { FsFileSystem sys; - std::string idStr = util::getStringInput(SwkbdType_QWERTY, "8000000000000000", "Enter Sys Save ID", 18, 0, NULL); + std::string idStr = util::getStringInput(SwkbdType_QWERTY, "8000000000000000", ui::getUIString("swkbdSysSavID", 0), 18, 0, NULL); uint64_t mountID = std::strtoull(idStr.c_str(), NULL, 16); if(R_SUCCEEDED(fsOpen_SystemSaveData(&sys, FsSaveDataSpaceId_System, mountID, (AccountUid) {0}))) { @@ -134,13 +134,18 @@ static void extMenuMountRomFS(void *a) } } +static void extMenuOutputEnUs(void *a) +{ + ui::newThread(ui::saveTranslationFile, NULL, NULL); +} + void ui::extInit() { ui::extMenu = new ui::menu(200, 24, 1002, 24, 4); ui::extMenu->setCallback(extMenuCallback, NULL); ui::extMenu->setActive(false); - for(unsigned i = 0; i < 11; i++) - ui::extMenu->addOpt(NULL, ui::exMenuStr[i]); + for(unsigned i = 0; i < 12; i++) + ui::extMenu->addOpt(NULL, ui::getUIString("extrasMenu", i)); //SD to SD ui::extMenu->optAddButtonEvent(0, HidNpadButton_A, toFMSDtoSD, NULL); @@ -162,6 +167,8 @@ void ui::extInit() ui::extMenu->optAddButtonEvent(8, HidNpadButton_A, extMenuReloadTitles, NULL); //RomFS ui::extMenu->optAddButtonEvent(9, HidNpadButton_A, extMenuMountRomFS, NULL); + //Translation so I can be lazy + ui::extMenu->optAddButtonEvent(11, HidNpadButton_A, extMenuOutputEnUs, NULL); } void ui::extExit() diff --git a/src/ui/fm.cpp b/src/ui/fm.cpp index 425fe60..c19eed3 100644 --- a/src/ui/fm.cpp +++ b/src/ui/fm.cpp @@ -249,7 +249,7 @@ static void _copyMenuCopy(void *a) if(ma == devArgs || (ma == sdmcArgs && (type != FsSaveDataType_System || cfg::config["sysSaveWrite"]))) { - ui::confirmArgs *send = ui::confirmArgsCreate(false, _copyMenuCopy_t, ma, true, ui::confCopy.c_str(), srcPath.c_str(), dstPath.c_str()); + ui::confirmArgs *send = ui::confirmArgsCreate(false, _copyMenuCopy_t, ma, true, ui::getUICString("confirmCopy", 0), srcPath.c_str(), dstPath.c_str()); ui::confirm(send); } } @@ -260,7 +260,7 @@ static void _copyMenuDelete_t(void *a) menuFuncArgs *ma = (menuFuncArgs *)t->argPtr; fs::backupArgs *b = ma->b; - t->status->setStatus("Deleting..."); + t->status->setStatus(ui::getUICString("threadStatusDeletingFile", 0)); int sel = b->m->getSelected(); if(ma == devArgs) @@ -321,7 +321,7 @@ static void _copyMenuDelete(void *a) if(ma == sdmcArgs || (ma == devArgs && (sel == 0 || sel > 1) && (type != FsSaveDataType_System || cfg::config["sysSaveWrite"]))) { - ui::confirmArgs *send = ui::confirmArgsCreate(cfg::config["holdDel"], _copyMenuDelete_t, a, true, ui::confDel.c_str(), itmPath.c_str()); + ui::confirmArgs *send = ui::confirmArgsCreate(cfg::config["holdDel"], _copyMenuDelete_t, a, true, ui::getUICString("confirmDelete", 0), itmPath.c_str()); ui::confirm(send); } } @@ -334,7 +334,7 @@ static void _copyMenuRename(void *a) int sel = b->m->getSelected(); if(sel > 1) { - std::string getNewName = util::getStringInput(SwkbdType_QWERTY, b->d->getItem(sel - 2), "Enter a new name", 64, 0, NULL); + std::string getNewName = util::getStringInput(SwkbdType_QWERTY, b->d->getItem(sel - 2), ui::getUIString("swkbdRename", 0), 64, 0, NULL); if(!getNewName.empty()) { std::string prevPath = *ma->path + b->d->getItem(sel - 2); @@ -352,7 +352,7 @@ static void _copyMenuRename(void *a) static void _copyMenuMkDir(void *a) { menuFuncArgs *ma = (menuFuncArgs *)a; - std::string getNewFolder = util::getStringInput(SwkbdType_QWERTY, "New Folder", "Enter a name", 64, 0, NULL); + std::string getNewFolder = util::getStringInput(SwkbdType_QWERTY, "New Folder", ui::getUIString("swkbdMkDir", 0), 64, 0, NULL); if(!getNewFolder.empty()) { std::string createPath = *ma->path + getNewFolder; @@ -390,9 +390,10 @@ static void _devMenuAddToPathFilter(void *a) int sel = b->m->getSelected(); if(sel > 1) { + data::userTitleInfo *d = data::getCurrentUserTitleInfo(); std::string filterPath = *ma->path + b->d->getItem(sel - 2); - cfg::addPathToFilter(data::curData.saveID, filterPath); - ui::showPopMessage(POP_FRAME_DEFAULT, "'%s' added to path filter.", filterPath.c_str()); + cfg::addPathToFilter(d->saveID, filterPath); + ui::showPopMessage(POP_FRAME_DEFAULT, ui::getUICString("popAddedToPathFilter", 0), filterPath.c_str()); } } @@ -416,13 +417,13 @@ void ui::fmInit() devCopyMenu = new ui::menu(10, 185, 268, 20, 5); devCopyMenu->setActive(false); devCopyMenu->setCallback(_devCopyMenuCallback, NULL); - devCopyMenu->addOpt(NULL, ui::advMenuStr[0] + "SDMC"); + devCopyMenu->addOpt(NULL, ui::getUIString("fileModeMenu", 0) + "SDMC"); for(int i = 1; i < 4; i++) - devCopyMenu->addOpt(NULL, advMenuStr[i]); + devCopyMenu->addOpt(NULL, ui::getUIString("fileModeMenu", i)); //Manually do this so I can place the last option higher up - devCopyMenu->addOpt(NULL, advMenuStr[6]); - devCopyMenu->addOpt(NULL, advMenuStr[4]); - devCopyMenu->addOpt(NULL, advMenuStr[5]); + devCopyMenu->addOpt(NULL, ui::getUIString("fileModeMenu", 6)); + devCopyMenu->addOpt(NULL, ui::getUIString("fileModeMenu", 4)); + devCopyMenu->addOpt(NULL, ui::getUIString("fileModeMenu", 5)); devCopyMenu->optAddButtonEvent(0, HidNpadButton_A, _copyMenuCopy, devArgs); devCopyMenu->optAddButtonEvent(1, HidNpadButton_A, _copyMenuDelete, devArgs); @@ -442,7 +443,7 @@ void ui::fmInit() sdCopyMenu->setActive(false); sdCopyMenu->setCallback(_sdCopyMenuCallback, NULL); for(int i = 0; i < 6; i++) - sdCopyMenu->addOpt(NULL, advMenuStr[i]); + sdCopyMenu->addOpt(NULL, ui::getUIString("fileModeMenu", i)); sdCopyMenu->optAddButtonEvent(0, HidNpadButton_A, _copyMenuCopy, sdmcArgs); sdCopyMenu->optAddButtonEvent(1, HidNpadButton_A, _copyMenuDelete, sdmcArgs); sdCopyMenu->optAddButtonEvent(2, HidNpadButton_A, _copyMenuRename, sdmcArgs); @@ -478,7 +479,7 @@ void ui::fmPrep(const FsSaveDataType& _type, const std::string& _dev, bool _comm devPath = _dev; sdPath = "sdmc:/"; - sdCopyMenu->editOpt(0, NULL, ui::advMenuStr[0] + _dev); + sdCopyMenu->editOpt(0, NULL, ui::getUIString("fileModeMenu", 0) + _dev); devList->reassign(dev); sdList->reassign(sdPath); diff --git a/src/ui/miscui.cpp b/src/ui/miscui.cpp index 793c902..1470f62 100644 --- a/src/ui/miscui.cpp +++ b/src/ui/miscui.cpp @@ -50,10 +50,16 @@ void ui::menu::editParam(int _param, int newVal) case MENU_RECT_WIDTH: rW = newVal; + SDL_DestroyTexture(optTex); + optTex = SDL_CreateTexture(gfx::render, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STATIC | SDL_TEXTUREACCESS_TARGET, rW, rH); + SDL_SetTextureBlendMode(optTex, SDL_BLENDMODE_BLEND); break; case MENU_RECT_HEIGHT: rH = newVal; + SDL_DestroyTexture(optTex); + optTex = SDL_CreateTexture(gfx::render, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STATIC | SDL_TEXTUREACCESS_TARGET, rW, rH); + SDL_SetTextureBlendMode(optTex, SDL_BLENDMODE_BLEND); break; case MENU_FONT_SIZE: @@ -222,10 +228,11 @@ void ui::menu::draw(SDL_Texture *target, const SDL_Color *textClr, bool drawText if(tY < -rH || tY > tH) continue; + gfx::clearTarget(optTex, &ui::transparent); + //Todo: Clean this up maybe if(i == selected && drawText) { - gfx::clearTarget(optTex, &ui::transparent); if(isActive) ui::drawBoundBox(target, x, y + (i * rH), rW, rH, clrSh); @@ -235,7 +242,11 @@ void ui::menu::draw(SDL_Texture *target, const SDL_Color *textClr, bool drawText if(hover && opt[i].txtWidth > rW - 24) { if((dX -= 2) <= -(opt[i].txtWidth + spcWidth)) + { dX = 0; + hoverCount = 0; + hover = false; + } gfx::drawTextf(optTex, fSize, dX, ((rH - 8) / 2) - fSize / 2, ui::thmID == ColorSetId_Light ? &menuColorLight : &menuColorDark, opt[i].txt.c_str()); gfx::drawTextf(optTex, fSize, dX + opt[i].txtWidth + spcWidth, ((rH - 8) / 2) - fSize / 2, ui::thmID == ColorSetId_Light ? &menuColorLight : &menuColorDark, opt[i].txt.c_str()); @@ -245,7 +256,6 @@ void ui::menu::draw(SDL_Texture *target, const SDL_Color *textClr, bool drawText dX = 0; gfx::drawTextf(optTex, fSize, 0, ((rH - 8) / 2) - fSize / 2, ui::thmID == ColorSetId_Light ? &menuColorLight : &menuColorDark, opt[i].txt.c_str()); } - gfx::texDraw(target, optTex, x + 20, (y + 4 + (i * rH))); } else if(i == selected && !drawText && opt[i].icn) @@ -258,8 +268,9 @@ void ui::menu::draw(SDL_Texture *target, const SDL_Color *textClr, bool drawText if(isActive) ui::drawBoundBox(target, x, y + (i * rH), rW, rH, clrSh); - gfx::texDrawStretch(target, opt[i].icn, x + 20, (y + (rH / 2 - fSize / 2)) + (i * rH), dW, dH); gfx::drawRect(target, ui::thmID == ColorSetId_Light ? &menuColorLight : &menuColorDark, x + 10, ((y + (rH / 2 - fSize / 2)) + (i * rH)) - 2, 4, fSize + 4); + gfx::texDrawStretch(optTex, opt[i].icn, 0, ((rH - 8) / 2) - fSize / 2, dW, dH); + gfx::texDraw(target, optTex, x + 20, (y + 4 + (i * rH))); } else if(drawText) { @@ -274,7 +285,8 @@ void ui::menu::draw(SDL_Texture *target, const SDL_Color *textClr, bool drawText float scale = (float)fSize / (float)h; int dW = scale * w; int dH = scale * h; - gfx::texDrawStretch(target, opt[i].icn, x + 20, (y + (rH / 2 - fSize / 2)) + (i * rH), dW, dH); + gfx::texDrawStretch(optTex, opt[i].icn, 0, ((rH - 8) / 2) - fSize / 2, dW, dH); + gfx::texDraw(target, optTex, x + 20, (y + 4 + (i * rH))); } } } @@ -340,8 +352,16 @@ void ui::popMessageMngr::update() void ui::popMessageMngr::popMessageAdd(const std::string& mess, int frameTime) { - ui::popMessage newPop = {mess, 0, frameTime}; - popQueue.push_back(newPop); + //Suppress multiple of the same + int lastMessageIndex = message.size() - 1; + std::string lastMessage; + if(lastMessageIndex >= 0) + lastMessage = message[lastMessageIndex].message; + if(lastMessage != mess) + { + ui::popMessage newPop = {mess, 0, frameTime}; + popQueue.push_back(newPop); + } } void ui::popMessageMngr::draw() @@ -421,18 +441,18 @@ void confirmDrawFunc(void *a) ui::confirmArgs *c = (ui::confirmArgs *)t->argPtr; if(!t->finished) { - std::string yesTxt = ui::yt; + std::string yesTxt = ui::getUIString("dialogYes", 0); unsigned yesX = 0; if((ui::padKeysHeld() & HidNpadButton_A) && c->hold) { c->frameCount++; if(c->frameCount <= 40) - yesTxt = ui::holdingText[0]; + yesTxt = ui::getUIString("holdingText", 0); else if(c->frameCount <= 80) - yesTxt = ui::holdingText[1]; + yesTxt = ui::getUIString("holdingText", 1); else if(c->frameCount <= 120) - yesTxt = ui::holdingText[2]; + yesTxt = ui::getUICString("holdingText", 2); yesTxt += ui::loadGlyphArray[c->lgFrame]; } @@ -447,7 +467,7 @@ void confirmDrawFunc(void *a) gfx::drawLine(NULL, &ui::rectSh, 280, 454, 999, 454); gfx::drawLine(NULL, &ui::rectSh, 640, 454, 640, 518); gfx::drawTextf(NULL, 18, yesX, 478, &ui::txtCont, yesTxt.c_str()); - gfx::drawTextf(NULL, 18, 782, 478, &ui::txtCont, ui::nt.c_str()); + gfx::drawTextf(NULL, 18, 782, 478, &ui::txtCont, ui::getUICString("dialogNo", 0)); } } diff --git a/src/ui/sett.cpp b/src/ui/sett.cpp index de7bea1..c03062a 100644 --- a/src/ui/sett.cpp +++ b/src/ui/sett.cpp @@ -9,11 +9,14 @@ ui::menu *ui::settMenu; +//This is the name of strings used here +static const char *settMenuStr = "settingsMenu"; + static unsigned optHelpX = 0; static inline std::string getBoolText(const bool& b) { - return b ? ui::on : ui::off; + return b ? ui::getUIString("settingsOn", 0) : ui::getUIString("settingsOff", 0); } static inline void toggleBool(bool& b) @@ -58,9 +61,12 @@ static void toggleOpt(void *a) case 2: { std::string oldWD = fs::getWorkDir(); - std::string getWD = util::getStringInput(SwkbdType_QWERTY, fs::getWorkDir(), "Enter a new Output Path", 64, 0, NULL); + std::string getWD = util::getStringInput(SwkbdType_QWERTY, fs::getWorkDir(), ui::getUIString("swkbdSetWorkDir", 0), 64, 0, NULL); if(!getWD.empty()) { + if(getWD[getWD.length() - 1] != '/') + getWD += "/"; + rename(oldWD.c_str(), getWD.c_str()); fs::setWorkDir(getWD); } @@ -136,24 +142,24 @@ static void toggleOpt(void *a) static void updateMenuText() { - ui::settMenu->editOpt(3, NULL, ui::optMenuStr[3] + getBoolText(cfg::config["incDev"])); - ui::settMenu->editOpt(4, NULL, ui::optMenuStr[4] + getBoolText(cfg::config["autoBack"])); - ui::settMenu->editOpt(5, NULL, ui::optMenuStr[5] + getBoolText(cfg::config["ovrClk"])); - ui::settMenu->editOpt(6, NULL, ui::optMenuStr[6] + getBoolText(cfg::config["holdDel"])); - ui::settMenu->editOpt(7, NULL, ui::optMenuStr[7] + getBoolText(cfg::config["holdRest"])); - ui::settMenu->editOpt(8, NULL, ui::optMenuStr[8] + getBoolText(cfg::config["holdOver"])); - ui::settMenu->editOpt(9, NULL, ui::optMenuStr[9] + getBoolText(cfg::config["forceMount"])); - ui::settMenu->editOpt(10, NULL, ui::optMenuStr[10] + getBoolText(cfg::config["accSysSave"])); - ui::settMenu->editOpt(11, NULL, ui::optMenuStr[11] + getBoolText(cfg::config["sysSaveWrite"])); - ui::settMenu->editOpt(12, NULL, ui::optMenuStr[12] + getBoolText(cfg::config["directFsCmd"])); - ui::settMenu->editOpt(13, NULL, ui::optMenuStr[13] + getBoolText(cfg::config["zip"])); - ui::settMenu->editOpt(14, NULL, ui::optMenuStr[14] + getBoolText(cfg::config["langOverride"])); - ui::settMenu->editOpt(15, NULL, ui::optMenuStr[15] + getBoolText(cfg::config["trashBin"])); - ui::settMenu->editOpt(16, NULL, ui::optMenuStr[16] + ui::sortString[cfg::sortType]); + ui::settMenu->editOpt(3, NULL, ui::getUIString(settMenuStr, 3) + getBoolText(cfg::config["incDev"])); + ui::settMenu->editOpt(4, NULL, ui::getUIString(settMenuStr, 4) + getBoolText(cfg::config["autoBack"])); + ui::settMenu->editOpt(5, NULL, ui::getUIString(settMenuStr, 5) + getBoolText(cfg::config["ovrClk"])); + ui::settMenu->editOpt(6, NULL, ui::getUIString(settMenuStr, 6) + getBoolText(cfg::config["holdDel"])); + ui::settMenu->editOpt(7, NULL, ui::getUIString(settMenuStr, 7) + getBoolText(cfg::config["holdRest"])); + ui::settMenu->editOpt(8, NULL, ui::getUIString(settMenuStr, 8) + getBoolText(cfg::config["holdOver"])); + ui::settMenu->editOpt(9, NULL, ui::getUIString(settMenuStr, 9) + getBoolText(cfg::config["forceMount"])); + ui::settMenu->editOpt(10, NULL, ui::getUIString(settMenuStr, 10) + getBoolText(cfg::config["accSysSave"])); + ui::settMenu->editOpt(11, NULL, ui::getUIString(settMenuStr, 11) + getBoolText(cfg::config["sysSaveWrite"])); + ui::settMenu->editOpt(12, NULL, ui::getUIString(settMenuStr, 12) + getBoolText(cfg::config["directFsCmd"])); + ui::settMenu->editOpt(13, NULL, ui::getUIString(settMenuStr, 13) + getBoolText(cfg::config["zip"])); + ui::settMenu->editOpt(14, NULL, ui::getUIString(settMenuStr, 14) + getBoolText(cfg::config["langOverride"])); + ui::settMenu->editOpt(15, NULL, ui::getUIString(settMenuStr, 15) + getBoolText(cfg::config["trashBin"])); + ui::settMenu->editOpt(16, NULL, ui::getUIString(settMenuStr, 16) + ui::getUICString("sortType", cfg::sortType)); char tmp[16]; sprintf(tmp, "%.1f", ui::animScale); - ui::settMenu->editOpt(17, NULL, ui::optMenuStr[17] + std::string(tmp)); + ui::settMenu->editOpt(17, NULL, ui::getUIString(settMenuStr, 17) + std::string(tmp)); } void ui::settInit() @@ -162,11 +168,11 @@ void ui::settInit() ui::settMenu->setCallback(settMenuCallback, NULL); ui::settMenu->setActive(false); - optHelpX = 1220 - gfx::getTextWidth(ui::optHelp.c_str(), 18); + optHelpX = 1220 - gfx::getTextWidth(ui::getUICString("helpSettings", 0), 18); for(unsigned i = 0; i < 18; i++) { - ui::settMenu->addOpt(NULL, ui::optMenuStr[i]); + ui::settMenu->addOpt(NULL, ui::getUIString("settingsMenu", i)); ui::settMenu->optAddButtonEvent(i, HidNpadButton_A, toggleOpt, NULL); } } @@ -186,5 +192,5 @@ void ui::settDraw(SDL_Texture *target) updateMenuText(); ui::settMenu->draw(target, &ui::txtCont, true); if(ui::mstate == OPT_MNU) - gfx::drawTextf(NULL, 18, optHelpX, 673, &ui::txtCont, ui::optHelp.c_str()); + gfx::drawTextf(NULL, 18, optHelpX, 673, &ui::txtCont, ui::getUICString("helpSettings", 0)); } diff --git a/src/ui/ttl.cpp b/src/ui/ttl.cpp index cb0b118..d273f2b 100644 --- a/src/ui/ttl.cpp +++ b/src/ui/ttl.cpp @@ -31,7 +31,7 @@ static void fldFuncOverwrite(void *a) int sel = m->getSelected() - 1;//Skip 'New' std::string itm = d->getItem(sel); - ui::confirmArgs *conf = ui::confirmArgsCreate(cfg::config["holdOver"], fs::overwriteBackup, a, true, ui::confOverwrite.c_str(), itm.c_str()); + ui::confirmArgs *conf = ui::confirmArgsCreate(cfg::config["holdOver"], fs::overwriteBackup, a, true, ui::getUICString("confirmOverwrite", 0), itm.c_str()); ui::confirm(conf); } @@ -44,7 +44,7 @@ static void fldFuncDelete(void *a) int sel = m->getSelected() - 1;//Skip 'New' std::string itm = d->getItem(sel); - ui::confirmArgs *conf = ui::confirmArgsCreate(cfg::config["holdDel"], fs::deleteBackup, a, true, ui::confDel.c_str(), itm.c_str()); + ui::confirmArgs *conf = ui::confirmArgsCreate(cfg::config["holdDel"], fs::deleteBackup, a, true, ui::getUICString("confirmDelete", 0), itm.c_str()); ui::confirm(conf); } @@ -57,7 +57,7 @@ static void fldFuncRestore(void *a) int sel = m->getSelected() - 1;//Skip 'New' std::string itm = d->getItem(sel); - ui::confirmArgs *conf = ui::confirmArgsCreate(cfg::config["holdRest"], fs::restoreBackup, a, true, ui::confRestore.c_str(), itm.c_str()); + ui::confirmArgs *conf = ui::confirmArgsCreate(cfg::config["holdRest"], fs::restoreBackup, a, true, ui::getUICString("confirmRestore", 0), itm.c_str()); ui::confirm(conf); } @@ -65,13 +65,14 @@ void ui::populateFldMenu() { fldMenu->reset(); - util::createTitleDirectoryByTID(data::curData.saveID); - std::string targetDir = util::generatePathByTID(data::curData.saveID); + data::userTitleInfo *d = data::getCurrentUserTitleInfo(); + util::createTitleDirectoryByTID(d->saveID); + std::string targetDir = util::generatePathByTID(d->saveID); fldList->reassign(targetDir); char filterPath[128]; - sprintf(filterPath, "sdmc:/config/JKSV/0x%016lX_filter.txt", data::curData.saveID); + sprintf(filterPath, "sdmc:/config/JKSV/0x%016lX_filter.txt", d->saveID); fs::loadPathFilters(filterPath); *backargs = {fldMenu, fldList}; @@ -93,34 +94,37 @@ void ui::populateFldMenu() static void ttlViewCallback(void *a) { - data::selData = ttlViews[data::selUser]->getSelected(); + unsigned curUserIndex = data::getCurrentUserIndex(); + unsigned setUserTitleIndex = ttlViews[curUserIndex]->getSelected(); + data::setTitleIndex(setUserTitleIndex); + data::userTitleInfo *d = data::getCurrentUserTitleInfo(); + switch(ui::padKeysDown()) { case HidNpadButton_A: - if(fs::mountSave(data::curData.saveInfo)) + if(fs::mountSave(d->saveInfo)) ui::populateFldMenu(); break; case HidNpadButton_B: - ttlViews[data::selUser]->setActive(false, false); + ttlViews[curUserIndex]->setActive(false, false); ui::usrMenu->setActive(true); ui::changeState(USR_SEL); break; case HidNpadButton_X: - data::selData = ttlViews[data::selUser]->getSelected(); - ttlViews[data::selUser]->setActive(false, true); + data::setTitleIndex(ttlViews[curUserIndex]->getSelected()); + ttlViews[curUserIndex]->setActive(false, true); ttlOpts->setActive(true); ui::ttlOptsPanel->openPanel(); break; case HidNpadButton_Y: { - uint64_t sid = data::curData.saveID; - cfg::addTitleToFavorites(sid); - int newSel = data::getTitleIndexInUser(data::curUser, sid); + cfg::addTitleToFavorites(d->saveID); + int newSel = data::getTitleIndexInUser(*data::getCurrentUser(), d->saveID); ui::ttlRefresh(); - ttlViews[data::selUser]->setSelected(newSel); + ttlViews[curUserIndex]->setSelected(newSel); } break; } @@ -131,10 +135,13 @@ static void ttlOptsCallback(void *a) switch(ui::padKeysDown()) { case HidNpadButton_B: - ttlOpts->setActive(false); - ui::ttlOptsPanel->closePanel(); - ttlViews[data::selUser]->setActive(true, true); - ui::updateInput(); + { + int curUserIndex = data::getCurrentUserIndex(); + ttlOpts->setActive(false); + ui::ttlOptsPanel->closePanel(); + ttlViews[curUserIndex]->setActive(true, true); + ui::updateInput(); + } break; } } @@ -149,20 +156,20 @@ static void ttlOptsShowInfoPanel(void *a) { ttlOpts->setActive(false); ui::ttlOptsPanel->closePanel(); - infoPanelString = util::getInfoString(data::curUser, data::curData.saveID); + infoPanelString = util::getInfoString(*data::getCurrentUser(), data::getCurrentUserTitleInfo()->saveID); infoPanel->openPanel(); } static void ttlOptsBlacklistTitle(void *a) { - std::string title = data::getTitleNameByTID(data::curData.saveID); - ui::confirmArgs *conf = ui::confirmArgsCreate(false, cfg::addTitleToBlacklist, NULL, true, ui::confBlacklist.c_str(), title.c_str()); + std::string title = data::getTitleNameByTID(data::getCurrentUserTitleInfo()->saveID); + ui::confirmArgs *conf = ui::confirmArgsCreate(false, cfg::addTitleToBlacklist, NULL, true, ui::getUICString("confirmBlacklist", 0), title.c_str()); ui::confirm(conf); } static void ttlOptsDefinePath(void *a) { - uint64_t tid = data::curData.saveID; + uint64_t tid = data::getCurrentUserTitleInfo()->saveID; std::string safeTitle = data::getTitleInfoByTID(tid)->safeTitle; std::string newSafeTitle = util::getStringInput(SwkbdType_QWERTY, safeTitle, "Input New Output Folder", 0x200, 0, NULL); if(!newSafeTitle.empty()) @@ -171,9 +178,10 @@ static void ttlOptsDefinePath(void *a) static void ttlOptsToFileMode(void *a) { - if(fs::mountSave(data::curData.saveInfo)) + data::userTitleInfo *d = data::getCurrentUserTitleInfo(); + if(fs::mountSave(d->saveInfo)) { - ui::fmPrep((FsSaveDataType)data::curData.saveInfo.save_data_type, "sv:/", true); + ui::fmPrep((FsSaveDataType)d->saveInfo.save_data_type, "sv:/", true); ui::usrSelPanel->closePanel(); ui::ttlOptsPanel->closePanel(); ui::changeState(FIL_MDE); @@ -183,23 +191,25 @@ static void ttlOptsToFileMode(void *a) static void ttlOptsResetSaveData_t(void *a) { threadInfo *t = (threadInfo *)a; - std::string title = data::getTitleNameByTID(data::curData.saveID); - t->status->setStatus("Resetting save data for " + title + "..."); + data::userTitleInfo *d = data::getCurrentUserTitleInfo(); + std::string title = data::getTitleNameByTID(d->saveID); + t->status->setStatus(ui::getUICString("threadStatusResettingSaveData", 0), title.c_str()); - fs::mountSave(data::curData.saveInfo); + fs::mountSave(d->saveInfo); fs::delDir("sv:/"); fsdevCommitDevice("sv:/"); fs::unmountSave(); - ui::showPopMessage(POP_FRAME_DEFAULT, ui::saveDataResetSuccess.c_str(), title.c_str()); + ui::showPopMessage(POP_FRAME_DEFAULT, ui::getUICString("saveDataResetSuccess", 0), title.c_str()); t->finished = true; } static void ttlOptsResetSaveData(void *a) { - if(data::curData.saveInfo.save_data_type != FsSaveDataType_System) + data::userTitleInfo *d = data::getCurrentUserTitleInfo(); + if(d->saveInfo.save_data_type != FsSaveDataType_System) { - std::string title = data::getTitleNameByTID(data::curData.saveID); - ui::confirmArgs *conf = ui::confirmArgsCreate(cfg::config["holdDel"], ttlOptsResetSaveData_t, NULL, true, ui::saveDataReset.c_str(), title.c_str()); + std::string title = data::getTitleNameByTID(d->saveID); + ui::confirmArgs *conf = ui::confirmArgsCreate(cfg::config["holdDel"], ttlOptsResetSaveData_t, NULL, true, ui::getUICString("confirmResetSaveData", 0), title.c_str()); ui::confirm(conf); } } @@ -207,47 +217,54 @@ static void ttlOptsResetSaveData(void *a) static void ttlOptsDeleteSaveData_t(void *a) { threadInfo *t = (threadInfo *)a; - std::string title = data::getTitleNameByTID(data::curData.saveID); - t->status->setStatus("Deleting save data for " + title + "..."); - if(R_SUCCEEDED(fsDeleteSaveDataFileSystemBySaveDataSpaceId((FsSaveDataSpaceId)data::curData.saveInfo.save_data_space_id, data::curData.saveInfo.save_data_id))) + data::user *u = data::getCurrentUser(); + data::userTitleInfo *d = data::getCurrentUserTitleInfo(); + unsigned userIndex = data::getCurrentUserIndex(); + + std::string title = data::getTitleNameByTID(d->saveID); + t->status->setStatus(ui::getUICString("threadStatusDeletingSaveData", 0), title.c_str()); + if(R_SUCCEEDED(fsDeleteSaveDataFileSystemBySaveDataSpaceId((FsSaveDataSpaceId)d->saveInfo.save_data_space_id, d->saveInfo.save_data_id))) { data::loadUsersTitles(false); - if(data::curUser.titleInfo.size() == 0) + if(u->titleInfo.size() == 0) { //Kick back to user ui::ttlOptsPanel->closePanel();//JIC ttlOpts->setActive(false); - ttlViews[data::selUser]->setActive(false, false); + ttlViews[userIndex]->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(); + ui::showPopMessage(POP_FRAME_DEFAULT, ui::getUICString("saveDataDeleteSuccess", 0), title.c_str()); + ttlViews[userIndex]->refresh(); } t->finished = true; } static void ttlOptsDeleteSaveData(void *a) { - if(data::curData.saveInfo.save_data_type != FsSaveDataType_System) + data::userTitleInfo *d = data::getCurrentUserTitleInfo(); + if(d->saveInfo.save_data_type != FsSaveDataType_System) { - std::string title = data::getTitleNameByTID(data::curData.saveID); - ui::confirmArgs *conf = ui::confirmArgsCreate(cfg::config["holdDel"], ttlOptsDeleteSaveData_t, NULL, true, ui::confEraseNand.c_str(), title.c_str()); + std::string title = data::getTitleNameByTID(d->saveID); + ui::confirmArgs *conf = ui::confirmArgsCreate(cfg::config["holdDel"], ttlOptsDeleteSaveData_t, NULL, true, ui::getUICString("confirmDeleteSaveData", 0), title.c_str()); ui::confirm(conf); } } static void ttlOptsExtendSaveData_t(void *a) { - threadInfo *w = (threadInfo *)a; + threadInfo *t = (threadInfo *)a; + data::userTitleInfo *d = data::getCurrentUserTitleInfo(); + std::string expSizeStr = util::getStringInput(SwkbdType_NumPad, "", "Enter New Size in MB", 4, 0, NULL); if(!expSizeStr.empty()) { int64_t journ = 0, expSize; - data::titleInfo *extend = data::getTitleInfoByTID(data::curData.saveID); - w->status->setStatus("Expanding save filesystem for " + extend->title); + data::titleInfo *extend = data::getTitleInfoByTID(d->saveID); + t->status->setStatus(ui::getUICString("threadStatusExtendingSaveData", 0), extend->title.c_str()); //Get journal size - switch(data::curData.saveInfo.save_data_type) + switch(d->saveInfo.save_data_type) { case FsSaveDataType_Account: if(extend->nacp.user_account_save_data_journal_size_max > extend->nacp.user_account_save_data_journal_size) @@ -281,33 +298,37 @@ static void ttlOptsExtendSaveData_t(void *a) } uint64_t expMB = strtoul(expSizeStr.c_str(), NULL, 10); expSize = expMB * 0x100000; - FsSaveDataSpaceId space = (FsSaveDataSpaceId)data::curData.saveInfo.save_data_space_id; - uint64_t sid = data::curData.saveInfo.save_data_id; + FsSaveDataSpaceId space = (FsSaveDataSpaceId)d->saveInfo.save_data_space_id; + uint64_t sid = d->saveInfo.save_data_id; Result res = 0; if(R_FAILED(res = fsExtendSaveDataFileSystem(space, sid, expSize, journ))) { int64_t totalSize = 0; - fs::mountSave(data::curData.saveInfo); + fs::mountSave(d->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."); + ui::showPopMessage(POP_FRAME_DEFAULT, ui::getUICString("saveDataExtendFailed", 0)); } + else + ui::showPopMessage(POP_FRAME_DEFAULT, ui::getUICString("saveDataExtendSuccess", 0), extend->title.c_str()); } - w->finished = true; + t->finished = true; } static void ttlOptsExtendSaveData(void *a) { - if(data::curData.saveInfo.save_data_type != FsSaveDataType_System) + data::userTitleInfo *d = data::getCurrentUserTitleInfo(); + if(d->saveInfo.save_data_type != FsSaveDataType_System) ui::newThread(ttlOptsExtendSaveData_t, NULL, NULL); } static void infoPanelDraw(void *a) { + data::userTitleInfo *d = data::getCurrentUserTitleInfo(); SDL_Texture *panel = (SDL_Texture *)a; - gfx::texDraw(panel, data::getTitleIconByTID(data::curData.saveID), 77, 32); + gfx::texDraw(panel, data::getTitleIconByTID(d->saveID), 77, 32); gfx::drawTextfWrap(panel, 18, 32, 320, 362, &ui::txtCont, infoPanelString.c_str()); } @@ -345,13 +366,13 @@ static void fldPanelDraw(void *a) fldMenu->draw(fldBuffer, &ui::txtCont, true); gfx::texDraw(target, fldBuffer, 0, 0); gfx::drawLine(target, &ui::divClr, 10, 648, fldHelpWidth + 54, 648); - gfx::drawTextf(target, 18, 32, 673, &ui::txtCont, ui::folderHelp.c_str()); + gfx::drawTextf(target, 18, 32, 673, &ui::txtCont, ui::getUICString("helpFolder", 0)); } void ui::ttlInit() { - ttlHelpX = 1220 - gfx::getTextWidth(ui::titleHelp.c_str(), 18); - fldHelpWidth = gfx::getTextWidth(ui::folderHelp.c_str(), 18); + ttlHelpX = 1220 - gfx::getTextWidth(ui::getUICString("helpTitle", 0), 18); + fldHelpWidth = gfx::getTextWidth(ui::getUICString("helpFolder", 0), 18); for(data::user& u : data::users) ttlViews.emplace_back(new ui::titleview(u, 128, 128, 16, 16, 7, ttlViewCallback)); @@ -379,19 +400,22 @@ void ui::ttlInit() backargs = new fs::backupArgs; ttlOpts->setActive(false); - ttlOpts->addOpt(NULL, ui::titleOptString[0]); + for(int i = 0; i < 7; i++) + ttlOpts->addOpt(NULL, ui::getUIString("titleOptions", i)); + + //Information ttlOpts->optAddButtonEvent(0, HidNpadButton_A, ttlOptsShowInfoPanel, NULL); - ttlOpts->addOpt(NULL, ui::titleOptString[1]); + //Blacklist ttlOpts->optAddButtonEvent(1, HidNpadButton_A, ttlOptsBlacklistTitle, NULL); - ttlOpts->addOpt(NULL, ui::titleOptString[2]); + //Title Define ttlOpts->optAddButtonEvent(2, HidNpadButton_A, ttlOptsDefinePath, NULL); - ttlOpts->addOpt(NULL, ui::titleOptString[3]); + //File Mode ttlOpts->optAddButtonEvent(3, HidNpadButton_A, ttlOptsToFileMode, NULL); - ttlOpts->addOpt(NULL, ui::titleOptString[4]); + //Reset Save ttlOpts->optAddButtonEvent(4, HidNpadButton_A, ttlOptsResetSaveData, NULL); - ttlOpts->addOpt(NULL, ui::titleOptString[5]); + //Delete Save ttlOpts->optAddButtonEvent(5, HidNpadButton_A, ttlOptsDeleteSaveData, NULL); - ttlOpts->addOpt(NULL, ui::titleOptString[6]); + //Extend ttlOpts->optAddButtonEvent(6, HidNpadButton_A, ttlOptsExtendSaveData, NULL); } @@ -417,15 +441,19 @@ void ui::ttlSetActive(int usr) void ui::ttlUpdate() { + unsigned curUserIndex = data::getCurrentUserIndex(); + ttlOpts->update(); infoPanel->update(); fldMenu->update(); - ttlViews[data::selUser]->update(); + ttlViews[curUserIndex]->update(); } void ui::ttlDraw(SDL_Texture *target) { - ttlViews[data::selUser]->draw(target); + unsigned curUserIndex = data::getCurrentUserIndex(); + + ttlViews[curUserIndex]->draw(target); if(ui::mstate == TTL_SEL && !fldPanel->isOpen()) - gfx::drawTextf(NULL, 18, ttlHelpX, 673, &ui::txtCont, ui::titleHelp.c_str()); + gfx::drawTextf(NULL, 18, ttlHelpX, 673, &ui::txtCont, ui::getUICString("helpTitle", 0)); } diff --git a/src/ui/uistr.cpp b/src/ui/uistr.cpp index 90782d9..9a4cc24 100644 --- a/src/ui/uistr.cpp +++ b/src/ui/uistr.cpp @@ -1,217 +1,197 @@ #include -#include +#include #include "file.h" #include "cfg.h" +#include "type.h" #include "uistr.h" -//Map to associate external string names to unsigned ints for switch case. -static std::unordered_map uistrdef = -{ - {"author", 0}, {"userHelp", 1}, {"titleHelp", 2}, {"folderHelp", 3}, {"optHelp", 4}, - {"yt", 5}, {"nt", 6}, {"on", 7}, {"off", 8}, {"confirmBlacklist", 9}, {"confirmOverwrite", 10}, - {"confirmRestore", 11}, {"confirmDelete", 12}, {"confirmCopy", 13}, {"confirmEraseNand", 14}, - {"confirmReset", 15}, {"confirmHead", 16}, {"copyHead", 17}, {"noSavesFound", 18}, - {"advMenu", 19}, {"extMenu", 20}, {"optMenu", 21}, {"optMenuExp", 22}, {"holdingText", 23}, - {"errorConnecting", 24}, {"noUpdate", 25}, {"sortType", 26}, {"saveCreated", 27}, {"saveCreateFailed", 28}, - {"saveDataResetSuccess", 29}, {"saveDataDeleteSuccess", 30} -}; +std::map, std::string> ui::strings; -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 = "[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"; -std::string ui::confBlacklist = "Are you sure you want to add #%s# to your blacklist?"; -std::string ui::confOverwrite = "Are you sure you want to overwrite #%s#?"; -std::string ui::confRestore = "Are you sure you want to restore #%s#?"; -std::string ui::confDel = "Are you sure you want to delete #%s#? *This is permanent*!"; -std::string ui::confCopy = "Are you sure you want to copy #%s# to #%s#?"; -std::string ui::confirmHead = "Confirm"; -std::string ui::copyHead = "Copying File..."; -std::string ui::confEraseNand = "*WARNING*: This *will* erase the save data for #%s# *from your system*. This is the same as deleting it from #Data Management#! Are you sure you want to continue?"; -std::string ui::noSavesFound = "No saves found for #%s#!"; -std::string ui::saveCreated = "Save data created for %s!"; -std::string ui::saveCreateFailed = "Save data creation failed!"; -std::string ui::saveDataReset = "Are you sure want to reset your current save data for %s?"; -std::string ui::saveDataResetSuccess = "Save for %s reset!"; -std::string ui::saveDataDeleteSuccess = "Save data for %s deleted!"; -std::string ui::errorConnecting = "Error Connecting!"; -std::string ui::noUpdate = "No updates available!"; -std::string ui::advMenuStr[7] = { "Copy to ", "Delete", "Rename", "Make Dir", "Properties", "Close", "Add to Path Filter" }; -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[18] = { "Empty Trash Bin", "Check for Update", "Set Output Folder", "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" }; -std::string ui::titleOptString[7] = {"Information", "Blacklist", "Change Output folder", "Open in File Mode", "Reset Save Data", "Delete Save Filesystem", "Extend Save Filesystem"}; +static inline void addUIString(const std::string& _name, int ind, const std::string& _str) +{ + ui::strings[std::make_pair(_name, ind)] = _str; +} + +void ui::initStrings() +{ + addUIString("author", 0, "NULL"); + addUIString("helpUser", 0, "[A] Select [X] User Options"); + addUIString("helpTitle", 0, "[A] Select [L][R] Jump [Y] Favorite [X] Title Options [B] Back"); + addUIString("helpFolder", 0, "[A] Select [Y] Restore [X] Delete [B] Close"); + addUIString("helpSettings", 0, "[A] Toggle [X] Defaults [B] Back"); + + //Y/N On/Off + addUIString("dialogYes", 0, "Yes [A]"); + addUIString("dialogNo", 0, "No [B]"); + addUIString("settingsOn", 0, ">On>"); + addUIString("settingsOff", 0, "Off"); + addUIString("holdingText", 0, "(Hold) "); + addUIString("holdingText", 1, "(Keep Holding) "); + addUIString("holdingText", 2, "(Almost There!) "); + + //Confirmation Strings + addUIString("confirmBlacklist", 0, "Are you sure you want to add #%s# to your blacklist?"); + addUIString("confirmOverwrite", 0, "Are you sure you want to overwrite #%s#?"); + addUIString("confirmRestore", 0, "Are you sure you want to restore #%s#?"); + addUIString("confirmDelete", 0, "Are you sure you want to delete #%s#? *This is permanent*!"); + addUIString("confirmCopy", 0, "Are you sure you want to copy #%s# to #%s#?"); + addUIString("confirmDeleteSaveData", 0, "*WARNING*: This *will* erase the save data for #%s# *from your system*. Are you sure you want to do this?"); + addUIString("confirmResetSaveData", 0, "*WARNING*: This *will* reset the save data for this game as if it was never ran before. Are you sure you want to do this?"); + + //Save Data related strings + addUIString("saveDataNoneFound", 0, "No saves found for #%s#!"); + addUIString("saveDataCreatedForUser", 0, "Save data created for %s!"); + addUIString("saveDataCreationFailed", 0, "Save data creation failed!"); + addUIString("saveDataResetSuccess", 0, "Save for #%s# reset!"); + addUIString("saveDataDeleteSuccess", 0, "Save data for #%s# deleted!"); + addUIString("saveDataExtendSuccess", 0, "Save data for #%s# extended!"); + addUIString("saveDataExtendFailed", 0, "Failed to extend save data."); + addUIString("saveDataDeleteAllUser", 0, "*ARE YOU SURE YOU WANT TO DELETE ALL SAVE DATA FOR %s?*"); + addUIString("saveDataBackupDeleted", 0, "#%s# has been deleted."); + addUIString("saveDataBackupMovedToTrash", 0, "#%s# has been moved to trash."); + + //Internet Related + addUIString("onlineErrorConnecting", 0, "Error Connecting!"); + addUIString("onlineNoUpdates", 0, "No Updates Available."); + + //File mode menu strings + addUIString("fileModeMenu", 0, "Copy To "); + addUIString("fileModeMenu", 1, "Delete"); + addUIString("fileModeMenu", 2, "Rename"); + addUIString("fileModeMenu", 3, "Make Dir"); + addUIString("fileModeMenu", 4, "Properties"); + addUIString("fileModeMenu", 5, "Close"); + addUIString("fileModeMenu", 6, "Add to Path Filters"); + + //Settings menu + addUIString("settingsMenu", 0, "Empty Trash Bin"); + addUIString("settingsMenu", 1, "Check for Updates"); + addUIString("settingsMenu", 2, "Set JKSV Save Output Folder"); + addUIString("settingsMenu", 3, "Include Device Saves With Users: "); + addUIString("settingsMenu", 4, "Auto Backup On Restore: "); + addUIString("settingsMenu", 5, "Overclock/CPU Boost: "); + addUIString("settingsMenu", 6, "Hold To Delete: "); + addUIString("settingsMenu", 7, "Hold To Restore: "); + addUIString("settingsMenu", 8, "Hold To Overwrite: "); + addUIString("settingsMenu", 9, "Force Mount: "); + addUIString("settingsMenu", 10, "Account System Saves: "); + addUIString("settingsMenu", 11, "Enable Writing to System Saves: "); + addUIString("settingsMenu", 12, "Use FS Commands Directly: "); + addUIString("settingsMenu", 13, "Export Saves to ZIP: "); + addUIString("settingsMenu", 14, "Force English To Be Used: "); + addUIString("settingsMenu", 15, "Enable Trash Bin: "); + addUIString("settingsMenu", 16, "Title Sorting Type: "); + addUIString("settingsMenu", 17, "Animation Scale: "); + + //Sort Strings for ^ + addUIString("sortType", 0, "Alphabetical"); + addUIString("sortType", 1, "Time Played"); + addUIString("sortType", 2, "Last Played"); + + //Extras + addUIString("extrasMenu", 0, "SD to SD Browser"); + addUIString("extrasMenu", 1, "BIS: ProdInfoF"); + addUIString("extrasMenu", 2, "BIS: Safe"); + addUIString("extrasMenu", 3, "BIS: System"); + addUIString("extrasMenu", 4, "BIS: User"); + addUIString("extrasMenu", 5, "Remove Pending Update"); + addUIString("extrasMenu", 6, "Terminate Process"); + addUIString("extrasMenu", 7, "Mount System Save"); + addUIString("extrasMenu", 8, "Rescan Titles"); + addUIString("extrasMenu", 9, "Mount Process RomFS"); + addUIString("extrasMenu", 10, "Backup JKSV Folder"); + addUIString("extrasMenu", 11, "*[DEV]* Output en-US"); + + //User Options + addUIString("userOptions", 0, "Create Save Data"); + addUIString("userOptions", 1, "Create All Save Data"); + addUIString("userOptions", 2, "Delete All User Saves"); + + //Title Options + addUIString("titleOptions", 0, "Information"); + addUIString("titleOptions", 1, "Blacklist"); + addUIString("titleOptions", 2, "Change Output Folder"); + addUIString("titleOptions", 3, "Open in File Mode"); + addUIString("titleOptions", 4, "Reset Save Data"); + addUIString("titleOptions", 5, "Delete Save Data"); + addUIString("titleOptions", 6, "Extend Save Data"); + + //Thread Status Strings + addUIString("threadStatusCreatingSaveData", 0, "Creating save data for #%s#..."); + addUIString("threadStatusCopyingFile", 0, "Copying '#%s#'..."); + addUIString("threadStatusDeletingFile", 0, "Deleting..."); + addUIString("threadStatusOpeningFolder", 0, "Opening '#%s#'..."); + addUIString("threadStatusAddingFileToZip", 0, "Adding '#%s#' to ZIP..."); + addUIString("threadStatusDecompressingFile", 0, "Decompressing '#%s#'..."); + addUIString("threadStatusResettingSaveData", 0, "Resetting Save Data for #%s#..."); + addUIString("threadStatusDeletingSaveData", 0, "Deleting Save Data for #%s#..."); + addUIString("threadStatusExtendingSaveData", 0, "Extending Save Data for #%s#..."); + addUIString("threadStatusCreatingSaveData", 0, "Creating Save Data for #%s#..."); + addUIString("threadStatusResettingSaveData", 0, "Resetting save data..."); + addUIString("threadStatusDeletingUpdate", 0, "Deleting pending update..."); + addUIString("threadStatusCheckingForUpdate", 0, "Checking for updates..."); + addUIString("threadStatusDownloadingUpdate", 0, "Downloading update..."); + + //Random leftover pop-ups + addUIString("popCPUBoostEnabled", 0, "CPU Boost Enabled for ZIP."); + addUIString("popErrorCommittingFile", 0, "Error committing file to save!"); + addUIString("popProcessShutdown", 0, "#%s# successfully shutdown."); + addUIString("popAddedToPathFilter", 0, "'#%s#' added to path filters."); + + //Keyboard hints + addUIString("swkbdEnterName", 0, "Enter a new name"); + addUIString("swkbdSaveIndex", 0, "Enter Cache Index"); + addUIString("swkbdSetWorkDir", 0, "Enter a new Output Path"); + addUIString("swkbdProcessID", 0, "Enter Process ID"); + addUIString("swkbdSysSavID", 0, "Enter System Save ID"); + addUIString("swkbdRename", 0, "Enter a new name for item"); + addUIString("swkbdMkDir", 0, "Enter a folder name"); +} 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 || cfg::config["langOverride"])) - return;//Don't bother loading from file. It serves as a translation guide - - std::string file; - if(transFile) - file = fs::getWorkDir() + "trans.txt"; + ui::initStrings(); else { - file = "romfs:/lang/"; - switch(data::sysLang) + std::string file; + if(transFile) + file = fs::getWorkDir() + "trans.txt"; + else { - case SetLanguage_ZHCN: - case SetLanguage_ZHHANS: - file += "zh-CN.txt"; - break; - - case SetLanguage_ZHTW: - case SetLanguage_ZHHANT: - file += "zh-TW.txt"; - break; - - default: - return; - break; + file = "romfs:/lang/"; + switch(data::sysLang) + { + //I removed these for now. Old translation files are incompatible and will cause crashes. + default: + ui::initStrings(); + return; + break; + } } - } - fs::dataFile lang(file); - while(lang.readNextLine(true)) - { - switch(uistrdef[lang.getName()]) + fs::dataFile lang(file); + while(lang.readNextLine(true)) { - case 0: - ui::author = lang.getNextValueStr(); - break; - - case 1: - ui::userHelp = lang.getNextValueStr(); - break; - - case 2: - ui::titleHelp = lang.getNextValueStr(); - break; - - case 3: - ui::folderHelp = lang.getNextValueStr(); - break; - - case 4: - ui::optHelp = lang.getNextValueStr(); - break; - - case 5: - ui::yt = lang.getNextValueStr(); - break; - - case 6: - ui::nt = lang.getNextValueStr(); - break; - - case 7: - ui::on = lang.getNextValueStr(); - break; - - case 8: - ui::off = lang.getNextValueStr(); - break; - - case 9: - ui::confBlacklist = lang.getNextValueStr(); - break; - - case 10: - ui::confOverwrite = lang.getNextValueStr(); - break; - - case 11: - ui::confRestore = lang.getNextValueStr(); - break; - - case 12: - ui::confDel = lang.getNextValueStr(); - break; - - case 13: - ui::confCopy = lang.getNextValueStr(); - break; - - case 14: - ui::confEraseNand = lang.getNextValueStr(); - break; - - case 15: - ui::saveDataReset = lang.getNextValueStr(); - break; - - case 16: - ui::confirmHead = lang.getNextValueStr(); - break; - - case 17: - ui::copyHead = lang.getNextValueStr(); - break; - - case 18: - ui::noSavesFound = lang.getNextValueStr(); - break; - - case 19: - { - int ind = lang.getNextValueInt(); - ui::advMenuStr[ind] = lang.getNextValueStr(); - } - break; - - case 20: - { - int ind = lang.getNextValueInt(); - ui::exMenuStr[ind] = lang.getNextValueStr(); - } - break; - - case 21: - { - int ind = lang.getNextValueInt(); - ui::optMenuStr[ind] = lang.getNextValueStr(); - } - break; - - case 22: - break; - - case 23: - { - int ind = lang.getNextValueInt(); - ui::holdingText[ind] = lang.getNextValueStr(); - } - break; - - case 24: - ui::errorConnecting = lang.getNextValueStr(); - break; - - case 25: - ui::noUpdate = lang.getNextValueStr(); - break; - - case 26: - { - int ind = lang.getNextValueInt(); - ui::sortString[ind] = lang.getNextValueStr(); - } - break; - - default: - fs::logWrite("Translation File Error -> On Line: %s: '%s' is not a known or valid string name.\n", lang.getLine().c_str(), lang.getName().c_str()); - break; + std::string name = lang.getName(); + int ind = lang.getNextValueInt(); + std::string str = lang.getNextValueStr(); + addUIString(name, ind, str); } } } +void ui::saveTranslationFile(void *a) +{ + threadInfo *t = (threadInfo *)a; + t->status->setStatus("Saving the file master..."); + + std::string out = fs::getWorkDir() + "en-US.txt"; + FILE *enUS = fopen(out.c_str(), "w"); + for(auto& s : ui::strings) + fprintf(enUS, "%s = %i, \"%s\"\n", s.first.first.c_str(), s.first.second, s.second.c_str()); + fclose(enUS); + t->finished = true; +} diff --git a/src/ui/usr.cpp b/src/ui/usr.cpp index 82b5db0..2c69a39 100644 --- a/src/ui/usr.cpp +++ b/src/ui/usr.cpp @@ -25,15 +25,6 @@ static ui::slideOutPanel *usrOptPanel, *saveCreatePanel, *deviceSavePanel, *bcat //Icons for settings + extras static SDL_Texture *sett, *ext; -//Struct to send args to createFunc -typedef struct -{ - FsSaveDataType type; - ui::menu *m; -} svCreateArgs; - -static svCreateArgs accCreate, devCreate, bcatCreate, cacheCreate; - //This stores save ids to match with saveCreateMenu //Probably needs/should be changed static std::vector accSids, devSids, bcatSids, cacheSids; @@ -67,7 +58,10 @@ static struct static void onMainChange(void *a) { if(ui::usrMenu->getSelected() < (int)data::users.size()) - data::selUser = ui::usrMenu->getSelected(); + { + unsigned setUser = ui::usrMenu->getSelected(); + data::setUserIndex(setUser); + } } static void _usrSelPanelDraw(void *a) @@ -168,15 +162,15 @@ static void usrOptSaveCreate(void *a) static void usrOptDeleteAllUserSaves_t(void *a) { threadInfo *t = (threadInfo *)a; - data::user *u = &data::users[data::selUser]; - + data::user *u = data::getCurrentUser(); + int curUserIndex = data::getCurrentUserIndex(); int devUser = ui::usrMenu->getOptPos("Device"); for(data::userTitleInfo& tinf : u->titleInfo) { - if(tinf.saveInfo.save_data_type != FsSaveDataType_System && (tinf.saveInfo.save_data_type != FsSaveDataType_Device || data::selUser == devUser)) + if(tinf.saveInfo.save_data_type != FsSaveDataType_System && (tinf.saveInfo.save_data_type != FsSaveDataType_Device || curUserIndex == devUser)) { - t->status->setStatus("Deleting " + data::getTitleNameByTID(tinf.saveID)); + t->status->setStatus(ui::getUICString("threadStatusDeletingSaveData", 0), data::getTitleNameByTID(tinf.saveID).c_str()); fsDeleteSaveDataFileSystemBySaveDataSpaceId(FsSaveDataSpaceId_User, tinf.saveInfo.save_data_id); } } @@ -187,8 +181,8 @@ static void usrOptDeleteAllUserSaves_t(void *a) static void usrOptDeleteAllUserSaves(void *a) { - data::user *u = &data::users[data::selUser]; - ui::confirmArgs *conf = ui::confirmArgsCreate(true, usrOptDeleteAllUserSaves_t, NULL, true, "*ARE YOU SURE YOU WANT TO DELETE ALL SAVE DATA FOR %s?*", u->getUsername().c_str()); + data::user *u = data::getCurrentUser(); + ui::confirmArgs *conf = ui::confirmArgsCreate(true, usrOptDeleteAllUserSaves_t, NULL, true, ui::getUICString("saveDataDeleteAllUser", 0), u->getUsername().c_str()); ui::confirm(conf); } @@ -222,117 +216,62 @@ static void cacheSavePanelDraw(void *a) cacheSaveMenu->draw(panel, &ui::txtCont, true); } -static void createSaveData_t(void *a) -{ - threadInfo *t = (threadInfo *)a; - svCreateArgs *in = (svCreateArgs *)t->argPtr; - - FsSaveDataType type = in->type; - ui::menu *m = in->m; - uint64_t sid; - switch(type) - { - case FsSaveDataType_Account: - sid = accSids[m->getSelected()]; - break; - - case FsSaveDataType_Device: - sid = devSids[m->getSelected()]; - break; - - case FsSaveDataType_Bcat: - sid = bcatSids[m->getSelected()]; - break; - - case FsSaveDataType_Cache: - sid = cacheSids[m->getSelected()]; - break; - - default: - return; - break; - } - data::titleInfo *create = data::getTitleInfoByTID(sid); - t->status->setStatus("Creating save data for " + create->title); - - FsSaveDataAttribute attr; - memset(&attr, 0, sizeof(FsSaveDataAttribute)); - attr.application_id = sid; - attr.uid = type == FsSaveDataType_Account ? data::curUser.getUID() : util::u128ToAccountUID(0); - attr.system_save_data_id = 0; - attr.save_data_type = type; - attr.save_data_rank = 0; - - uint16_t index = 0; - if(type == FsSaveDataType_Cache) - { - std::string getIndex = util::getStringInput(SwkbdType_NumPad, "", "Input Cache save index", 2, 0, NULL); - index = strtoul(getIndex.c_str(), 0, 10); - } - attr.save_data_index = index; - - FsSaveDataCreationInfo svCreate; - memset(&svCreate, 0, sizeof(FsSaveDataCreationInfo)); - int64_t saveSize = 0, journalSize = 0; - switch(type) - { - case FsSaveDataType_Account: - saveSize = create->nacp.user_account_save_data_size; - journalSize = create->nacp.user_account_save_data_journal_size; - break; - - case FsSaveDataType_Device: - saveSize = create->nacp.device_save_data_size; - journalSize = create->nacp.device_save_data_journal_size; - break; - - case FsSaveDataType_Bcat: - saveSize = create->nacp.bcat_delivery_cache_storage_size; - journalSize = create->nacp.bcat_delivery_cache_storage_size; - break; - - case FsSaveDataType_Cache: - saveSize = 32 * 1024 * 1024;//Todo: Add target folder/zip selection for size - if(create->nacp.cache_storage_journal_size > create->nacp.cache_storage_data_and_journal_size_max) - journalSize = create->nacp.cache_storage_journal_size; - else - journalSize = create->nacp.cache_storage_data_and_journal_size_max; - break; - - default: - return; - break; - } - svCreate.save_data_size = saveSize; - svCreate.journal_size = journalSize; - svCreate.available_size = 0x4000; - svCreate.owner_id = create->nacp.save_data_owner_id; - svCreate.flags = 0; - svCreate.save_data_space_id = FsSaveDataSpaceId_User; - - FsSaveDataMetaInfo meta; - memset(&meta, 0, sizeof(FsSaveDataMetaInfo)); - meta.size = 0x40060; - meta.type = FsSaveDataMetaType_Thumbnail; - - Result res = 0; - if(R_SUCCEEDED(res = fsCreateSaveDataFileSystem(&attr, &svCreate, &meta))) - { - data::loadUsersTitles(false); - ui::ttlRefresh(); - } - else - { - 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, NULL); + data::user *u = data::getCurrentUser(); + u128 uid = u->getUID128(); + + //Device, BCAT, and Cache are hardcoded user IDs in JKSV's data + uint64_t tid = 0; + switch(uid) + { + case 0://This is system + break; + + case 2: + tid = bcatSids[bcatSaveMenu->getSelected()]; + fs::createSaveData(FsSaveDataType_Bcat, tid, util::u128ToAccountUID(0)); + break; + + case 3: + tid = devSids[deviceSaveMenu->getSelected()]; + fs::createSaveData(FsSaveDataType_Device, tid, util::u128ToAccountUID(0)); + break; + + case 5: + tid = cacheSids[cacheSaveMenu->getSelected()]; + fs::createSaveData(FsSaveDataType_Cache, tid, util::u128ToAccountUID(0)); + break; + + default: + tid = accSids[saveCreateMenu->getSelected()]; + fs::createSaveData(FsSaveDataType_Account, tid, u->getUID()); + break; + } +} + +static void usrOptCreateAllSaves(void *a) +{ + data::user *u = data::getCurrentUser(); + int devPos = ui::usrMenu->getOptPos("Device"); + int bcatPos = ui::usrMenu->getOptPos("BCAT"); + int sel = ui::usrMenu->getSelected(); + if(sel < devPos) + { + AccountUid uid = u->getUID(); + for(unsigned i = 0; i < accSids.size(); i++) + fs::createSaveData(FsSaveDataType_Account, accSids[i], uid); + } + else if(sel == devPos) + { + for(unsigned i = 0; i < devSids.size(); i++) + fs::createSaveData(FsSaveDataType_Device, devSids[i], util::u128ToAccountUID(0)); + } + else if(sel == bcatPos) + { + for(unsigned i = 0; i < bcatSids.size(); i++) + fs::createSaveData(FsSaveDataType_Bcat, bcatSids[i], util::u128ToAccountUID(0)); + } } //Sets up save create menus @@ -348,11 +287,6 @@ static void initSaveCreateMenus() bcatSids.clear(); cacheSids.clear(); - accCreate = {FsSaveDataType_Account, saveCreateMenu}; - devCreate = {FsSaveDataType_Device, deviceSaveMenu}; - bcatCreate = {FsSaveDataType_Bcat, bcatSaveMenu}; - cacheCreate = {FsSaveDataType_Cache, cacheSaveMenu}; - //Group into vectors to match for(auto& t : data::titles) { @@ -380,25 +314,25 @@ static void initSaveCreateMenus() for(unsigned i = 0; i < accSids.size(); i++) { saveCreateMenu->addOpt(NULL, data::getTitleNameByTID(accSids[i])); - saveCreateMenu->optAddButtonEvent(i, HidNpadButton_A, createSaveData, &accCreate); + saveCreateMenu->optAddButtonEvent(i, HidNpadButton_A, createSaveData, NULL); } for(unsigned i = 0; i < devSids.size(); i++) { deviceSaveMenu->addOpt(NULL, data::getTitleNameByTID(devSids[i])); - deviceSaveMenu->optAddButtonEvent(i, HidNpadButton_A, createSaveData, &devCreate); + deviceSaveMenu->optAddButtonEvent(i, HidNpadButton_A, createSaveData, NULL); } for(unsigned i = 0; i < bcatSids.size(); i++) { bcatSaveMenu->addOpt(NULL, data::getTitleNameByTID(bcatSids[i])); - bcatSaveMenu->optAddButtonEvent(i, HidNpadButton_A, createSaveData, &bcatCreate); + bcatSaveMenu->optAddButtonEvent(i, HidNpadButton_A, createSaveData, NULL); } for(unsigned i = 0; i < cacheSids.size(); i++) { cacheSaveMenu->addOpt(NULL, data::getTitleNameByTID(cacheSids[i])); - cacheSaveMenu->optAddButtonEvent(i, HidNpadButton_A, createSaveData, &cacheCreate); + cacheSaveMenu->optAddButtonEvent(i, HidNpadButton_A, createSaveData, NULL); } } @@ -451,10 +385,15 @@ void ui::usrInit() usrOptPanel = new ui::slideOutPanel(410, 720, 0, ui::SLD_RIGHT, usrOptPanelDraw); ui::registerPanel(usrOptPanel); - usrOptMenu->addOpt(NULL, ui::usrOptString[0]); + for(int i = 0; i < 3; i++) + usrOptMenu->addOpt(NULL, ui::getUIString("userOptions", i)); + + //Create Save Data usrOptMenu->optAddButtonEvent(0, HidNpadButton_A, usrOptSaveCreate, usrMenu); - usrOptMenu->addOpt(NULL, ui::usrOptString[1]); - usrOptMenu->optAddButtonEvent(1, HidNpadButton_A, usrOptDeleteAllUserSaves, NULL); + //Create All + usrOptMenu->optAddButtonEvent(1, HidNpadButton_A, usrOptCreateAllSaves, NULL); + //Delete All + usrOptMenu->optAddButtonEvent(2, HidNpadButton_A, usrOptDeleteAllUserSaves, NULL); usrOptMenu->setActive(false); saveCreatePanel = new ui::slideOutPanel(512, 720, 0, ui::SLD_RIGHT, saveCreatePanelDraw); @@ -471,7 +410,7 @@ void ui::usrInit() initSaveCreateMenus(); - usrHelpX = 1220 - gfx::getTextWidth(ui::userHelp.c_str(), 18); + usrHelpX = 1220 - gfx::getTextWidth(ui::getUICString("helpUser", 0), 18); } void ui::usrExit() @@ -528,7 +467,6 @@ void ui::usrUpdate() void ui::usrDraw(SDL_Texture *target) { - usrMenu->draw(target, &ui::txtCont, false); if(ui::mstate == USR_SEL) - gfx::drawTextf(NULL, 18, usrHelpX, 673, &ui::txtCont, ui::userHelp.c_str()); + gfx::drawTextf(NULL, 18, usrHelpX, 673, &ui::txtCont, ui::getUICString("helpUser", 0)); } diff --git a/src/util.cpp b/src/util.cpp index ed1251a..cd77008 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -188,7 +188,7 @@ static inline std::string getTimeString(const uint32_t& _h, const uint32_t& _m) std::string util::getInfoString(data::user& u, const uint64_t& tid) { data::titleInfo *tinfo = data::getTitleInfoByTID(tid); - data::userTitleInfo *userTinfo = &u.titleInfo[data::selData]; + data::userTitleInfo *userTinfo = data::getCurrentUserTitleInfo(); std::string ret = tinfo->title + "\n"; @@ -226,8 +226,11 @@ std::string util::getInfoString(data::user& u, const uint64_t& tid) break; case FsSaveDataType_Cache: - ret += "Cache Storage\n"; - ret += "Save Index: " + std::to_string(data::curData.saveInfo.save_data_index) + "\n"; + { + data::userTitleInfo *d = data::getCurrentUserTitleInfo(); + ret += "Cache Storage\n"; + ret += "Save Index: " + std::to_string(d->saveInfo.save_data_index) + "\n"; + } break; case FsSaveDataType_SystemBcat: @@ -354,11 +357,11 @@ void util::setCPU(uint32_t hz) void util::checkForUpdate(void *a) { threadInfo *t = (threadInfo *)a; - t->status->setStatus("Checking for Updates..."); + t->status->setStatus(ui::getUICString("threadStatusCheckingForUpdate", 0)); std::string gitJson = getJSONURL(NULL, "https://api.github.com/repos/J-D-K/JKSV/releases/latest"); if(gitJson.empty()) { - ui::showPopMessage(POP_FRAME_DEFAULT, ui::errorConnecting.c_str()); + ui::showPopMessage(POP_FRAME_DEFAULT, ui::getUICString("onlineErrorConnecting", 0)); t->finished = true; return; } @@ -372,7 +375,7 @@ void util::checkForUpdate(void *a) //This can throw false positives as is. need to fix sometime if(year > BLD_YEAR || month > BLD_MON || month > BLD_DAY) { - t->status->setStatus("Downloading Update..."); + t->status->setStatus(ui::getUICString("threadStatusDownloadingUpdate", 0)); //dunno about NSP yet... json_object *assets, *asset0, *dlUrl; json_object_object_get_ex(jobj, "assets", &assets); @@ -387,7 +390,7 @@ void util::checkForUpdate(void *a) fclose(jksvOut); } else - ui::showPopMessage(POP_FRAME_DEFAULT, ui::noUpdate.c_str()); + ui::showPopMessage(POP_FRAME_DEFAULT, ui::getUICString("onlineNoUpdates", 0)); json_object_put(jobj); t->finished = true;