From 2eef9adf7b9043b563c2d299d291bbfc7bfa7ece Mon Sep 17 00:00:00 2001 From: w3irDv <170813473+w3irDv@users.noreply.github.com> Date: Sun, 11 Aug 2024 15:09:05 +0200 Subject: [PATCH 01/22] fix - date for a savedata is now shown --- include/date.h | 4 +++- include/savemng.h | 3 +++ src/savemng.cpp | 21 +++++++++++++++++++-- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/include/date.h b/include/date.h index b5b8134..527aa97 100644 --- a/include/date.h +++ b/include/date.h @@ -2,13 +2,15 @@ #include #include +#include class Date { public: Date(uint32_t high, uint32_t low, uint8_t s) : highID(high), lowID(low), slot(s), - path(StringUtils::stringFormat("sd:/wiiu/backups/%08x%08x/%u/savemiiMeta.json", highID, lowID, slot)) { + //path(StringUtils::stringFormat("sd:/wiiu/backups/%08x%08x/%u/savemiiMeta.json", highID, lowID, slot)) { + path(getUnifiedBackupPath(highID, lowID, slot).append("/savemiiMeta.json")) { } std::string get(); bool set(const std::string &date); diff --git a/include/savemng.h b/include/savemng.h index 9152106..3acb585 100644 --- a/include/savemng.h +++ b/include/savemng.h @@ -108,6 +108,9 @@ std::string getUSB(); void consolePrintPos(int x, int y, const char *format, ...) __attribute__((hot)); bool promptConfirm(Style st, const std::string &question); void promptError(const char *message, ...); +std::string getBackupPath(uint32_t highID, uint32_t lowID, uint8_t slot); +std::string getLegacyBackupPath(uint32_t highID, uint32_t lowID); +std::string getUnifiedBackupPath(uint32_t highID, uint32_t lowID, uint8_t slot); void getAccountsWiiU(); void getAccountsSD(Title *title, uint8_t slot); bool hasAccountSave(Title *title, bool inSD, bool iine, uint32_t user, uint8_t slot, int version); diff --git a/src/savemng.cpp b/src/savemng.cpp index e7bafc7..c2f4e44 100644 --- a/src/savemng.cpp +++ b/src/savemng.cpp @@ -53,6 +53,16 @@ std::string newlibtoFSA(std::string path) { return path; } +std::string getUnifiedBackupPath(uint32_t highId, uint32_t lowId, uint8_t slot) { + + if (((highId & 0xFFFFFFF0) == 0x00010000) && (slot == 255)) + return getLegacyBackupPath(highId, lowId); + else + return getBackupPath(highId, lowId, slot); + +} + + std::string getBackupPath(uint32_t highId, uint32_t lowId, uint8_t slot){ return StringUtils::stringFormat("%s/%08x%08x/%u", backupPath, highId, lowId, slot); } @@ -958,11 +968,14 @@ void backupSavedata(Title *title, uint8_t slot, int8_t allusers, bool common) { const std::string path = (isWii ? "storage_slccmpt01:/title" : (isUSB ? (getUSB() + "/usr/save").c_str() : "storage_mlc01:/usr/save")); std::string srcPath = StringUtils::stringFormat("%s/%08x/%08x/%s", path.c_str(), highID, lowID, isWii ? "data" : "user"); std::string dstPath; + dstPath = getUnifiedBackupPath(highID, lowID, slot); + /* if (isWii && (slot == 255)) dstPath = StringUtils::stringFormat("%s/%08x%08x", legacyBackupPath, highID, lowID); else dstPath = getBackupPath(highID, lowID, slot); - createFolder(dstPath.c_str()); + */ + createFolder(dstPath.c_str()); if ((allusers > -1) && !isWii) { if (common) { @@ -1013,11 +1026,15 @@ void restoreSavedata(Title *title, uint8_t slot, int8_t sdusers, int8_t allusers bool isWii = ((highID & 0xFFFFFFF0) == 0x00010000); std::string srcPath; const std::string path = (isWii ? "storage_slccmpt01:/title" : (isUSB ? (getUSB() + "/usr/save").c_str() : "storage_mlc01:/usr/save")); + srcPath = getUnifiedBackupPath(highID, lowID, slot); + /* if (isWii && (slot == 255)) srcPath = StringUtils::stringFormat("%s/%08x%08x", legacyBackupPath, highID, lowID); else srcPath = getBackupPath(highID, lowID, slot); - std::string dstPath = StringUtils::stringFormat("%s/%08x/%08x/%s", path.c_str(), highID, lowID, isWii ? "data" : "user"); + + */ + std::string dstPath = StringUtils::stringFormat("%s/%08x/%08x/%s", path.c_str(), highID, lowID, isWii ? "data" : "user"); createFolderUnlocked(dstPath); if ((sdusers > -1) && !isWii) { From b75abd8fb4f12038d35de061986653b8c42e2266 Mon Sep 17 00:00:00 2001 From: w3irDv <170813473+w3irDv@users.noreply.github.com> Date: Wed, 14 Aug 2024 23:49:57 +0200 Subject: [PATCH 02/22] fix - user savedata for a given user not found if common save=yes --- src/savemng.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/savemng.cpp b/src/savemng.cpp index c2f4e44..b147023 100644 --- a/src/savemng.cpp +++ b/src/savemng.cpp @@ -979,9 +979,9 @@ void backupSavedata(Title *title, uint8_t slot, int8_t allusers, bool common) { if ((allusers > -1) && !isWii) { if (common) { - srcPath.append("/common"); - dstPath.append("/common"); - if (!copyDir(srcPath, dstPath)) + //srcPath.append("/common"); + //dstPath.append("/common"); + if (!copyDir(srcPath+"/common", dstPath+"/common")) promptError(LanguageUtils::gettext("Common save not found.")); } srcPath.append(StringUtils::stringFormat("/%s", wiiuacc[allusers].persistentID)); From dbcaa9a7433d417a73c0b80f1d606861b6a0aabf Mon Sep 17 00:00:00 2001 From: w3irDv <170813473+w3irDv@users.noreply.github.com> Date: Thu, 15 Aug 2024 20:25:04 +0200 Subject: [PATCH 03/22] fix - wipedata for a given user not deleted if common save=yes --- src/savemng.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/savemng.cpp b/src/savemng.cpp index b147023..b7fd4c1 100644 --- a/src/savemng.cpp +++ b/src/savemng.cpp @@ -622,7 +622,7 @@ static bool removeDir(const std::string &pPath) { return false; struct dirent *data; - + while ((data = readdir(dir)) != nullptr) { DrawUtils::beginDraw(); DrawUtils::clear(COLOR_BLACK); @@ -1110,21 +1110,19 @@ void wipeSavedata(Title *title, int8_t allusers, bool common) { srcPath = StringUtils::stringFormat("%s/%08x/%08x/%s", path.c_str(), highID, lowID, isWii ? "data" : "user"); if ((allusers > -1) && !isWii) { if (common) { - srcPath += "/common"; - origPath = srcPath; - if (!removeDir(srcPath)) + origPath = srcPath + "/common"; + if (!removeDir(origPath)) promptError(LanguageUtils::gettext("Common save not found.")); if (unlink(origPath.c_str()) == -1) promptError(LanguageUtils::gettext("Failed to delete common folder.\n%s"), strerror(errno)); } srcPath += "/" + std::string(wiiuacc[allusers].persistentID); - origPath = srcPath; } if (!removeDir(srcPath)) promptError(LanguageUtils::gettext("Failed to delete savefile.")); if ((allusers > -1) && !isWii) { - if (unlink(origPath.c_str()) == -1) + if (unlink(srcPath.c_str()) == -1) promptError(LanguageUtils::gettext("Failed to delete user folder.\n%s"), strerror(errno)); } std::string volPath; From 5f4f15218cf0a029090a3e1a6324aa8eada144bb Mon Sep 17 00:00:00 2001 From: w3irDv <170813473+w3irDv@users.noreply.github.com> Date: Fri, 16 Aug 2024 22:37:38 +0200 Subject: [PATCH 04/22] new feature - restore from batch backup ~ backupsets - initial version --- include/BackupSetList.h | 22 + include/menu/BackupSetListState.h | 24 ++ include/menu/BatchBackupState.h | 3 + include/savemng.h | 1 + src/BackupSetList.cpp | 54 +++ src/main.cpp | 5 + src/menu/BackupSetListState.cpp | 86 ++++ src/menu/BatchBackupState.cpp | 11 + src/menu/TitleOptionsState.cpp | 673 ++++++++++++++++-------------- src/menu/TitleTaskState.cpp | 1 + src/savemng.cpp | 51 +-- 11 files changed, 587 insertions(+), 344 deletions(-) create mode 100644 include/BackupSetList.h create mode 100644 include/menu/BackupSetListState.h create mode 100644 src/BackupSetList.cpp create mode 100644 src/menu/BackupSetListState.cpp diff --git a/include/BackupSetList.h b/include/BackupSetList.h new file mode 100644 index 0000000..b90bfb1 --- /dev/null +++ b/include/BackupSetList.h @@ -0,0 +1,22 @@ +#pragma once + +#include +#include + +const std::string CURRENT_BS = ">> Current <<"; + +class BackupSetList { +public: + friend class BackupSetListState; + friend class BatchBackupState; + BackupSetList(const char* fPath); + void sort(bool sortAscending = false); + std::string at(int i); + void add(std::string backupSet); + +private: + std::vector backupSets; + bool sortAscending = false; + int entries; + +}; diff --git a/include/menu/BackupSetListState.h b/include/menu/BackupSetListState.h new file mode 100644 index 0000000..e9702e5 --- /dev/null +++ b/include/menu/BackupSetListState.h @@ -0,0 +1,24 @@ +#pragma once + +#include +#include +#include + +class BackupSetListState : public ApplicationState { +public: + BackupSetListState(); + enum eState { + STATE_BACKUPSET_MENU, + STATE_DO_SUBSTATE, + }; + + void render() override; + ApplicationState::eSubState update(Input *input) override; + +private: + std::unique_ptr subState{}; + eState state = STATE_BACKUPSET_MENU; + + int scroll = 0; + bool sortAscending; +}; \ No newline at end of file diff --git a/include/menu/BatchBackupState.h b/include/menu/BatchBackupState.h index 1af5b54..d1600a4 100644 --- a/include/menu/BatchBackupState.h +++ b/include/menu/BatchBackupState.h @@ -5,6 +5,8 @@ #include #include +void resetBackupList(); + class BatchBackupState : public ApplicationState { public: BatchBackupState(Title *wiiutitles, Title *wiititles, int wiiuTitlesCount, int vWiiTitlesCount) : wiiutitles(wiiutitles), @@ -19,6 +21,7 @@ class BatchBackupState : public ApplicationState { void render() override; ApplicationState::eSubState update(Input *input) override; + private: std::unique_ptr subState{}; eState state = STATE_BATCH_BACKUP; diff --git a/include/savemng.h b/include/savemng.h index 3acb585..b63e8e2 100644 --- a/include/savemng.h +++ b/include/savemng.h @@ -111,6 +111,7 @@ void promptError(const char *message, ...); std::string getBackupPath(uint32_t highID, uint32_t lowID, uint8_t slot); std::string getLegacyBackupPath(uint32_t highID, uint32_t lowID); std::string getUnifiedBackupPath(uint32_t highID, uint32_t lowID, uint8_t slot); +void setBackupSetSubPath(); void getAccountsWiiU(); void getAccountsSD(Title *title, uint8_t slot); bool hasAccountSave(Title *title, bool inSD, bool iine, uint32_t user, uint8_t slot, int version); diff --git a/src/BackupSetList.cpp b/src/BackupSetList.cpp new file mode 100644 index 0000000..26dfad3 --- /dev/null +++ b/src/BackupSetList.cpp @@ -0,0 +1,54 @@ +#include "BackupSetList.h" + +#include +#include +#include +#include +#include +#include + +BackupSetList::BackupSetList(const char* fPath) +{ + + backupSets.push_back(CURRENT_BS); + + DIR *dir = opendir(fPath); + if (dir != nullptr) { + struct dirent *data; + while ((data = readdir(dir)) != nullptr) { + if(strcmp(data->d_name,".") == 0 || strcmp(data->d_name,"..") == 0 || ! (data->d_type & DT_DIR)) + continue; + backupSets.push_back(data->d_name); + } + } + closedir(dir); + + this->entries = backupSets.size(); + this->sort(false); + +} + +void BackupSetList::sort(bool sortAscending) +{ + if (sortAscending) { + std::ranges::sort(backupSets.begin()+1,backupSets.end(),std::ranges::less{}); + } else { + std::ranges::sort(backupSets.begin()+1,backupSets.end(),std::ranges::greater{}); + } + this->sortAscending = sortAscending; +} + +std::string BackupSetList::at(int i) +{ + + return backupSets.at(i); + +} + +void BackupSetList::add(std::string backupSet) +{ + backupSets.push_back(backupSet); + this->entries++; + if (!this->sortAscending) + this->sort(false); +} diff --git a/src/main.cpp b/src/main.cpp index fd3deed..cbbd1f5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -18,6 +19,7 @@ #include static int wiiuTitlesCount = 0, vWiiTitlesCount = 0; +std::unique_ptr myBackupSetList; template static bool contains(const T (&arr)[N], const T &element) { @@ -386,6 +388,7 @@ static void unloadTitles(Title *titles, int count) { } int main() { + AXInit(); AXQuit(); @@ -435,6 +438,8 @@ int main() { sortTitle(wiiutitles, wiiutitles + wiiuTitlesCount, 1, true); sortTitle(wiititles, wiititles + vWiiTitlesCount, 1, true); + myBackupSetList = std::make_unique("fs:/vol/external01/wiiu/backups/batch"); + Input input{}; std::unique_ptr state = std::make_unique(wiiutitles, wiititles, wiiuTitlesCount, vWiiTitlesCount); diff --git a/src/menu/BackupSetListState.cpp b/src/menu/BackupSetListState.cpp new file mode 100644 index 0000000..e4a8519 --- /dev/null +++ b/src/menu/BackupSetListState.cpp @@ -0,0 +1,86 @@ +#include +#include +#include +#include +#include +#include + +#define MAX_ROWS_SHOW 14 + +static int cursorPos = 0; + +static std::string language; + +extern std::unique_ptr myBackupSetList; +extern std::string backupSetSubPath; +extern std::string backupSetEntry; + +BackupSetListState::BackupSetListState() { + this->sortAscending = myBackupSetList->sortAscending; +} + +void BackupSetListState::render() { + + consolePrintPos(44, 0, LanguageUtils::gettext("\ue083 Sort: %s \ue084"), + this->sortAscending ? "\u2191" : "\u2193"); + for (int i = 0; i < MAX_ROWS_SHOW; i++) { + if (i + this->scroll < 0 || i + this->scroll >= myBackupSetList->entries) + break; + DrawUtils::setFontColor(static_cast(0x00FF00FF)); + if (myBackupSetList->at(i + this->scroll) == CURRENT_BS) + DrawUtils::setFontColor(static_cast(0xFF9000FF)); + consolePrintPos(M_OFF, i + 2, " %s", myBackupSetList->at(i + this->scroll).c_str()); + DrawUtils::setFontColor(COLOR_TEXT); + } + + consolePrintPos(-1, 2 + cursorPos, "\u2192"); + consolePrintPosAligned(17, 4, 2, LanguageUtils::gettext("\ue000: Select BackupSet \ue001: Back")); +/* + language = LanguageUtils::getLoadedLanguage(); + consolePrintPos(M_OFF, 2, LanguageUtils::gettext(" Language: %s"), language.c_str()); + consolePrintPos(M_OFF, 2 + cursorPos, "\u2192"); +*/ +} + +ApplicationState::eSubState BackupSetListState::update(Input *input) { + if (input->get(TRIGGER, PAD_BUTTON_B)) + return SUBSTATE_RETURN; + if (input->get(TRIGGER, PAD_BUTTON_A)) { + backupSetEntry = myBackupSetList->at(cursorPos + this->scroll); + setBackupSetSubPath(); + DrawUtils::setRedraw(true); + return SUBSTATE_RETURN; + } + if (input->get(TRIGGER, PAD_BUTTON_L)) { + if ( this->sortAscending ) { + this->sortAscending = false; + myBackupSetList->sort(this->sortAscending); + } + } + if (input->get(TRIGGER, PAD_BUTTON_R)) { + if ( ! this->sortAscending ) { + this->sortAscending = true; + myBackupSetList->sort(this->sortAscending); + } + } + if (input->get(TRIGGER, PAD_BUTTON_DOWN)) { + if (myBackupSetList->entries <= MAX_ROWS_SHOW) + cursorPos = (cursorPos + 1) % myBackupSetList->entries; + else if (cursorPos < 6) + cursorPos++; + else if (((cursorPos + this->scroll + 1) % myBackupSetList->entries) != 0) + scroll++; + else + cursorPos = scroll = 0; + } else if (input->get(TRIGGER, PAD_BUTTON_UP)) { + if (scroll > 0) + cursorPos -= (cursorPos > 6) ? 1 : 0 * (scroll--); + else if (cursorPos > 0) + cursorPos--; + else if (myBackupSetList->entries > MAX_ROWS_SHOW) + scroll = myBackupSetList->entries - (cursorPos = 6) - 1; + else + cursorPos = myBackupSetList->entries - 1; + } + return SUBSTATE_RUNNING; +} \ No newline at end of file diff --git a/src/menu/BatchBackupState.cpp b/src/menu/BatchBackupState.cpp index 9c3b66d..e712d6f 100644 --- a/src/menu/BatchBackupState.cpp +++ b/src/menu/BatchBackupState.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -8,6 +9,13 @@ static int cursorPos = 0; +extern std::unique_ptr myBackupSetList; + +void resetBackupList() { + myBackupSetList.reset(); + myBackupSetList = std::make_unique("fs:/vol/external01/wiiu/backups/batch"); +} + void BatchBackupState::render() { consolePrintPos(M_OFF, 2, LanguageUtils::gettext(" Backup All (%u Title%s)"), this->wiiuTitlesCount + this->vWiiTitlesCount, ((this->wiiuTitlesCount + this->vWiiTitlesCount) > 1) ? "s" : ""); @@ -35,14 +43,17 @@ ApplicationState::eSubState BatchBackupState::update(Input *input) { dateTime.tm_year = 0; backupAllSave(this->wiiutitles, this->wiiuTitlesCount, &dateTime); backupAllSave(this->wiititles, this->vWiiTitlesCount, &dateTime); + resetBackupList(); DrawUtils::setRedraw(true); return SUBSTATE_RETURN; case 1: backupAllSave(this->wiiutitles, this->wiiuTitlesCount, nullptr); + resetBackupList(); DrawUtils::setRedraw(true); return SUBSTATE_RETURN; case 2: backupAllSave(this->wiititles, this->vWiiTitlesCount, nullptr); + resetBackupList(); DrawUtils::setRedraw(true); return SUBSTATE_RETURN; default: diff --git a/src/menu/TitleOptionsState.cpp b/src/menu/TitleOptionsState.cpp index f7a1850..261a61e 100644 --- a/src/menu/TitleOptionsState.cpp +++ b/src/menu/TitleOptionsState.cpp @@ -1,367 +1,400 @@ +#include #include #include +#include #include #include #include +extern std::string backupSetSubPath; +extern std::string backupSetEntry; + void TitleOptionsState::render() { - this->isWiiUTitle = (this->title.highID == 0x00050000) || (this->title.highID == 0x00050002); - entrycount = 3; - consolePrintPos(M_OFF, 2, "[%08X-%08X] %s", this->title.highID, this->title.lowID, - this->title.shortName); + if (this->state == STATE_DO_SUBSTATE) { + if (this->subState == nullptr) { + OSFatal("SubState was null"); + } + this->subState->render(); + return; + } + if (this->state == STATE_TITLE_OPTIONS) { + if (this->task == restore) { + consolePrintPosAligned(0, 4, 2,"BackupSet: %s",backupSetEntry.c_str()); + } + this->isWiiUTitle = (this->title.highID == 0x00050000) || (this->title.highID == 0x00050002); + entrycount = 3; + consolePrintPos(M_OFF, 2, "[%08X-%08X] %s", this->title.highID, this->title.lowID, + this->title.shortName); + if (this->task == copytoOtherDevice) { + consolePrintPos(M_OFF, 4, LanguageUtils::gettext("Destination:")); + consolePrintPos(M_OFF, 5, " (%s)", this->title.isTitleOnUSB ? "NAND" : "USB"); + } else if (this->task > 2) { + entrycount = 2; + consolePrintPos(M_OFF, 4, LanguageUtils::gettext("Select %s:"), LanguageUtils::gettext("version")); + consolePrintPos(M_OFF, 5, " < v%u >", this->versionList != nullptr ? this->versionList[slot] : 0); + } else if (this->task == wipe) { + consolePrintPos(M_OFF, 4, LanguageUtils::gettext("Delete from:")); + consolePrintPos(M_OFF, 5, " (%s)", this->title.isTitleOnUSB ? "USB" : "NAND"); + } else { + consolePrintPos(M_OFF, 4, LanguageUtils::gettext("Select %s:"), LanguageUtils::gettext("slot")); - if (this->task == copytoOtherDevice) { - consolePrintPos(M_OFF, 4, LanguageUtils::gettext("Destination:")); - consolePrintPos(M_OFF, 5, " (%s)", this->title.isTitleOnUSB ? "NAND" : "USB"); - } else if (this->task > 2) { - entrycount = 2; - consolePrintPos(M_OFF, 4, LanguageUtils::gettext("Select %s:"), LanguageUtils::gettext("version")); - consolePrintPos(M_OFF, 5, " < v%u >", this->versionList != nullptr ? this->versionList[slot] : 0); - } else if (this->task == wipe) { - consolePrintPos(M_OFF, 4, LanguageUtils::gettext("Delete from:")); - consolePrintPos(M_OFF, 5, " (%s)", this->title.isTitleOnUSB ? "USB" : "NAND"); - } else { - consolePrintPos(M_OFF, 4, LanguageUtils::gettext("Select %s:"), LanguageUtils::gettext("slot")); + if (((this->title.highID & 0xFFFFFFF0) == 0x00010000) && (slot == 255)) + consolePrintPos(M_OFF, 5, " < SaveGame Manager GX > (%s)", + isSlotEmpty(this->title.highID, this->title.lowID, slot) ? LanguageUtils::gettext("Empty") + : LanguageUtils::gettext("Used")); + else + consolePrintPos(M_OFF, 5, " < %03u > (%s)", slot, + isSlotEmpty(this->title.highID, this->title.lowID, slot) ? LanguageUtils::gettext("Empty") + : LanguageUtils::gettext("Used")); + } - if (((this->title.highID & 0xFFFFFFF0) == 0x00010000) && (slot == 255)) - consolePrintPos(M_OFF, 5, " < SaveGame Manager GX > (%s)", - isSlotEmpty(this->title.highID, this->title.lowID, slot) ? LanguageUtils::gettext("Empty") - : LanguageUtils::gettext("Used")); - else - consolePrintPos(M_OFF, 5, " < %03u > (%s)", slot, - isSlotEmpty(this->title.highID, this->title.lowID, slot) ? LanguageUtils::gettext("Empty") - : LanguageUtils::gettext("Used")); - } + if (this->isWiiUTitle) { + if (task == restore) { + if (!isSlotEmpty(this->title.highID, this->title.lowID, slot)) { + entrycount++; + consolePrintPos(M_OFF, 7, LanguageUtils::gettext("Select SD user to copy from:")); + if (sdusers == -1) + consolePrintPos(M_OFF, 8, " < %s >", LanguageUtils::gettext("all users")); + else + consolePrintPos(M_OFF, 8, " < %s > (%s)", getSDacc()[sdusers].persistentID, + hasAccountSave(&this->title, true, false, getSDacc()[sdusers].pID, + slot, 0) + ? LanguageUtils::gettext("Has Save") + : LanguageUtils::gettext("Empty")); + } + } - if (this->isWiiUTitle) { - if (task == restore) { - if (!isSlotEmpty(this->title.highID, this->title.lowID, slot)) { - entrycount++; - consolePrintPos(M_OFF, 7, LanguageUtils::gettext("Select SD user to copy from:")); - if (sdusers == -1) + if (task == wipe) { + consolePrintPos(M_OFF, 7, LanguageUtils::gettext("Select Wii U user to delete from:")); + if (this->allusers == -1) consolePrintPos(M_OFF, 8, " < %s >", LanguageUtils::gettext("all users")); else - consolePrintPos(M_OFF, 8, " < %s > (%s)", getSDacc()[sdusers].persistentID, - hasAccountSave(&this->title, true, false, getSDacc()[sdusers].pID, - slot, 0) + consolePrintPos(M_OFF, 8, " < %s (%s) > (%s)", getWiiUacc()[this->allusers].miiName, + getWiiUacc()[this->allusers].persistentID, + hasAccountSave(&this->title, false, false, getWiiUacc()[this->allusers].pID, + slot, 0) ? LanguageUtils::gettext("Has Save") : LanguageUtils::gettext("Empty")); } - } - if (task == wipe) { - consolePrintPos(M_OFF, 7, LanguageUtils::gettext("Select Wii U user to delete from:")); - if (this->allusers == -1) - consolePrintPos(M_OFF, 8, " < %s >", LanguageUtils::gettext("all users")); - else - consolePrintPos(M_OFF, 8, " < %s (%s) > (%s)", getWiiUacc()[this->allusers].miiName, - getWiiUacc()[this->allusers].persistentID, - hasAccountSave(&this->title, false, false, getWiiUacc()[this->allusers].pID, - slot, 0) - ? LanguageUtils::gettext("Has Save") - : LanguageUtils::gettext("Empty")); - } + if ((task == backup) || (task == restore) || (task == copytoOtherDevice)) { + if ((task == restore) && isSlotEmpty(this->title.highID, this->title.lowID, slot)) + entrycount--; + else { + consolePrintPos(M_OFF, (task == restore) ? 10 : 7, LanguageUtils::gettext("Select Wii U user%s:"), + (task == copytoOtherDevice) ? LanguageUtils::gettext(" to copy from") : ((task == restore) ? LanguageUtils::gettext(" to copy to") : "")); + if (this->allusers == -1) + consolePrintPos(M_OFF, (task == restore) ? 11 : 8, " < %s >", LanguageUtils::gettext("all users")); + else + consolePrintPos(M_OFF, (task == restore) ? 11 : 8, " < %s (%s) > (%s)", + getWiiUacc()[allusers].miiName, getWiiUacc()[allusers].persistentID, + hasAccountSave(&this->title, + (!((task == backup) || (task == restore) || (task == copytoOtherDevice))), + (!((task < 3) || (task == copytoOtherDevice))), + getWiiUacc()[this->allusers].pID, slot, + this->versionList != nullptr ? this->versionList[slot] : 0) + ? LanguageUtils::gettext("Has Save") + : LanguageUtils::gettext("Empty")); + } + } + if ((task == backup) || (task == restore)) + if (!isSlotEmpty(this->title.highID, this->title.lowID, slot)) { + Date *dateObj = new Date(this->title.highID, this->title.lowID, slot); + consolePrintPos(M_OFF, 15, LanguageUtils::gettext("Date: %s"), + dateObj->get().c_str()); + delete dateObj; + } - if ((task == backup) || (task == restore) || (task == copytoOtherDevice)) { - if ((task == restore) && isSlotEmpty(this->title.highID, this->title.lowID, slot)) - entrycount--; - else { - consolePrintPos(M_OFF, (task == restore) ? 10 : 7, LanguageUtils::gettext("Select Wii U user%s:"), - (task == copytoOtherDevice) ? LanguageUtils::gettext(" to copy from") : ((task == restore) ? LanguageUtils::gettext(" to copy to") : "")); - if (this->allusers == -1) - consolePrintPos(M_OFF, (task == restore) ? 11 : 8, " < %s >", LanguageUtils::gettext("all users")); + if (task == copytoOtherDevice) { + entrycount++; + consolePrintPos(M_OFF, 10, LanguageUtils::gettext("Select Wii U user%s:"), (task == copytoOtherDevice) ? LanguageUtils::gettext(" to copy to") : ""); + if (allusers_d == -1) + consolePrintPos(M_OFF, 11, " < %s >", LanguageUtils::gettext("all users")); else - consolePrintPos(M_OFF, (task == restore) ? 11 : 8, " < %s (%s) > (%s)", - getWiiUacc()[allusers].miiName, getWiiUacc()[allusers].persistentID, - hasAccountSave(&this->title, - (!((task == backup) || (task == restore) || (task == copytoOtherDevice))), - (!((task < 3) || (task == copytoOtherDevice))), - getWiiUacc()[this->allusers].pID, slot, - this->versionList != nullptr ? this->versionList[slot] : 0) + consolePrintPos(M_OFF, 11, " < %s (%s) > (%s)", getWiiUacc()[allusers_d].miiName, + getWiiUacc()[allusers_d].persistentID, + hasAccountSave(&titles[this->title.dupeID], false, false, + getWiiUacc()[allusers_d].pID, 0, 0) ? LanguageUtils::gettext("Has Save") : LanguageUtils::gettext("Empty")); } - } - if ((task == backup) || (task == restore)) - if (!isSlotEmpty(this->title.highID, this->title.lowID, slot)) { - Date *dateObj = new Date(this->title.highID, this->title.lowID, slot); - consolePrintPos(M_OFF, 15, LanguageUtils::gettext("Date: %s"), - dateObj->get().c_str()); - delete dateObj; - } - - if (task == copytoOtherDevice) { - entrycount++; - consolePrintPos(M_OFF, 10, LanguageUtils::gettext("Select Wii U user%s:"), (task == copytoOtherDevice) ? LanguageUtils::gettext(" to copy to") : ""); - if (allusers_d == -1) - consolePrintPos(M_OFF, 11, " < %s >", LanguageUtils::gettext("all users")); - else - consolePrintPos(M_OFF, 11, " < %s (%s) > (%s)", getWiiUacc()[allusers_d].miiName, - getWiiUacc()[allusers_d].persistentID, - hasAccountSave(&titles[this->title.dupeID], false, false, - getWiiUacc()[allusers_d].pID, 0, 0) - ? LanguageUtils::gettext("Has Save") - : LanguageUtils::gettext("Empty")); - } - if ((task != importLoadiine) && (task != exportLoadiine)) { - if (this->allusers > -1) { - if (hasCommonSave(&this->title, - (!((task == backup) || (task == wipe) || (task == copytoOtherDevice))), - (!((task < 3) || (task == copytoOtherDevice))), slot, - this->versionList != nullptr ? this->versionList[slot] : 0)) { - consolePrintPos(M_OFF, (task == restore) || (task == copytoOtherDevice) ? 13 : 10, - LanguageUtils::gettext("Include 'common' save?")); - consolePrintPos(M_OFF, (task == restore) || (task == copytoOtherDevice) ? 14 : 11, " < %s >", - common ? LanguageUtils::gettext("yes") : LanguageUtils::gettext("no ")); + if ((task != importLoadiine) && (task != exportLoadiine)) { + if (this->allusers > -1) { + if (hasCommonSave(&this->title, + (!((task == backup) || (task == wipe) || (task == copytoOtherDevice))), + (!((task < 3) || (task == copytoOtherDevice))), slot, + this->versionList != nullptr ? this->versionList[slot] : 0)) { + consolePrintPos(M_OFF, (task == restore) || (task == copytoOtherDevice) ? 13 : 10, + LanguageUtils::gettext("Include 'common' save?")); + consolePrintPos(M_OFF, (task == restore) || (task == copytoOtherDevice) ? 14 : 11, " < %s >", + common ? LanguageUtils::gettext("yes") : LanguageUtils::gettext("no ")); + } else { + common = false; + consolePrintPos(M_OFF, (task == restore) || (task == copytoOtherDevice) ? 13 : 10, + LanguageUtils::gettext("No 'common' save found.")); + entrycount--; + } } else { common = false; - consolePrintPos(M_OFF, (task == restore) || (task == copytoOtherDevice) ? 13 : 10, - LanguageUtils::gettext("No 'common' save found.")); entrycount--; } } else { - common = false; - entrycount--; + if (hasCommonSave(&this->title, true, true, slot, this->versionList != nullptr ? this->versionList[slot] : 0)) { + consolePrintPos(M_OFF, 7, LanguageUtils::gettext("Include 'common' save?")); + consolePrintPos(M_OFF, 8, " < %s >", common ? LanguageUtils::gettext("yes") : LanguageUtils::gettext("no ")); + } else { + common = false; + consolePrintPos(M_OFF, 7, LanguageUtils::gettext("No 'common' save found.")); + entrycount--; + } } + + consolePrintPos(M_OFF, 5 + cursorPos * 3, "\u2192"); + if (this->title.iconBuf != nullptr) + DrawUtils::drawTGA(660, 100, 1, this->title.iconBuf); } else { - if (hasCommonSave(&this->title, true, true, slot, this->versionList != nullptr ? this->versionList[slot] : 0)) { - consolePrintPos(M_OFF, 7, LanguageUtils::gettext("Include 'common' save?")); - consolePrintPos(M_OFF, 8, " < %s >", common ? LanguageUtils::gettext("yes") : LanguageUtils::gettext("no ")); - } else { - common = false; - consolePrintPos(M_OFF, 7, LanguageUtils::gettext("No 'common' save found.")); - entrycount--; + entrycount = 1; + if (this->title.iconBuf != nullptr) + DrawUtils::drawRGB5A3(650, 100, 1, this->title.iconBuf); + if (!isSlotEmpty(this->title.highID, this->title.lowID, slot)) { + Date *dateObj = new Date(this->title.highID, this->title.lowID, slot); + consolePrintPos(M_OFF, 15, LanguageUtils::gettext("Date: %s"), + dateObj->get().c_str()); + delete dateObj; } } - consolePrintPos(M_OFF, 5 + cursorPos * 3, "\u2192"); - if (this->title.iconBuf != nullptr) - DrawUtils::drawTGA(660, 100, 1, this->title.iconBuf); - } else { - entrycount = 1; - if (this->title.iconBuf != nullptr) - DrawUtils::drawRGB5A3(650, 100, 1, this->title.iconBuf); - if (!isSlotEmpty(this->title.highID, this->title.lowID, slot)) { - Date *dateObj = new Date(this->title.highID, this->title.lowID, slot); - consolePrintPos(M_OFF, 15, LanguageUtils::gettext("Date: %s"), - dateObj->get().c_str()); - delete dateObj; + switch (task) { + case backup: + break; + case restore: + consolePrintPosAligned(17, 4, 2, LanguageUtils::gettext("\uE002: Chg BackupSet \ue000: Restore \ue001: Back")); + break; + case wipe: + consolePrintPosAligned(17, 4, 2, LanguageUtils::gettext("\ue000: Wipe \ue001: Back")); + break; + case importLoadiine: + consolePrintPosAligned(17, 4, 2, LanguageUtils::gettext("\ue000: Import \ue001: Back")); + break; + case exportLoadiine: + consolePrintPosAligned(17, 4, 2, LanguageUtils::gettext("\ue000: Export \ue001: Back")); + break; + case copytoOtherDevice: + consolePrintPosAligned(17, 4, 2, LanguageUtils::gettext("\ue000: Copy \ue001: Back")); + break; } } - - switch (task) { - case backup: - consolePrintPosAligned(17, 4, 2, LanguageUtils::gettext("\ue000: Backup \ue001: Back")); - break; - case restore: - consolePrintPosAligned(17, 4, 2, LanguageUtils::gettext("\ue000: Restore \ue001: Back")); - break; - case wipe: - consolePrintPosAligned(17, 4, 2, LanguageUtils::gettext("\ue000: Wipe \ue001: Back")); - break; - case importLoadiine: - consolePrintPosAligned(17, 4, 2, LanguageUtils::gettext("\ue000: Import \ue001: Back")); - break; - case exportLoadiine: - consolePrintPosAligned(17, 4, 2, LanguageUtils::gettext("\ue000: Export \ue001: Back")); - break; - case copytoOtherDevice: - consolePrintPosAligned(17, 4, 2, LanguageUtils::gettext("\ue000: Copy \ue001: Back")); - break; - } } ApplicationState::eSubState TitleOptionsState::update(Input *input) { - if (input->get(TRIGGER, PAD_BUTTON_B)) - return SUBSTATE_RETURN; - if (input->get(TRIGGER, PAD_BUTTON_LEFT)) { - if (this->task == copytoOtherDevice) { - switch (cursorPos) { - case 0: - break; - case 1: - this->allusers = ((this->allusers == -1) ? -1 : (this->allusers - 1)); - allusers_d = this->allusers; - break; - case 2: - allusers_d = (((this->allusers == -1) || (allusers_d == -1)) ? -1 : (allusers_d - 1)); - allusers_d = ((this->allusers > -1) && (allusers_d == -1)) ? 0 : allusers_d; - break; - case 3: - common = common ? false : true; - break; - default: - break; - } - } else if (this->task == restore) { - switch (cursorPos) { - case 0: - getAccountsSD(&this->title, --slot); - break; - case 1: - sdusers = ((sdusers == -1) ? -1 : (sdusers - 1)); - this->allusers = ((sdusers == -1) ? -1 : this->allusers); - break; - case 2: - allusers = (((allusers == -1) || (sdusers == -1)) ? -1 : (allusers - 1)); - allusers = ((sdusers > -1) && (allusers == -1)) ? 0 : allusers; - break; - case 3: - common = common ? false : true; - break; - default: - break; - } - } else if (this->task == wipe) { - switch (cursorPos) { - case 0: - break; - case 1: - allusers = ((allusers == -1) ? -1 : (allusers - 1)); - break; - case 2: - common = common ? false : true; - break; - default: - break; - } - } else if ((this->task == importLoadiine) || (this->task == exportLoadiine)) { - switch (cursorPos) { - case 0: - slot--; - break; - case 1: - common = common ? false : true; - break; - default: - break; - } - } else { - switch (cursorPos) { - case 0: - slot--; - break; - case 1: - allusers = ((allusers == -1) ? -1 : (allusers - 1)); - break; - case 2: - common = common ? false : true; - break; - default: - break; - } + if (this->state == STATE_TITLE_OPTIONS) { + if (input->get(TRIGGER, PAD_BUTTON_B)) { + backupSetSubPath = "/"; // reset nxt operations to current backupSet + return SUBSTATE_RETURN; } - } - if (input->get(TRIGGER, PAD_BUTTON_RIGHT)) { - if (this->task == copytoOtherDevice) { - switch (cursorPos) { - case 0: - break; - case 1: - allusers = ((allusers == (getWiiUaccn() - 1)) ? (getWiiUaccn() - 1) : (allusers + 1)); - allusers_d = allusers; - break; - case 2: - allusers_d = ((allusers_d == (getWiiUaccn() - 1)) ? (getWiiUaccn() - 1) : (allusers_d + 1)); - allusers_d = (allusers == -1) ? -1 : allusers_d; - break; - case 3: - common = common ? false : true; - break; - default: - break; - } - } else if (this->task == restore) { - switch (cursorPos) { - case 0: - getAccountsSD(&this->title, ++slot); - break; - case 1: - sdusers = ((sdusers == (getSDaccn() - 1)) ? (getSDaccn() - 1) : (sdusers + 1)); - allusers = ((sdusers > -1) && (allusers == -1)) ? 0 : allusers; - break; - case 2: - allusers = ((allusers == (getWiiUaccn() - 1)) ? (getWiiUaccn() - 1) : (allusers + 1)); - allusers = (sdusers == -1) ? -1 : allusers; - break; - case 3: - common = common ? false : true; - break; - default: - break; + if (input->get(TRIGGER, PAD_BUTTON_X)) + if (this->task == restore) { + this->state = STATE_DO_SUBSTATE; + this->subState = std::make_unique(); } - } else if (this->task == wipe) { - switch (cursorPos) { - case 0: - break; - case 1: - allusers = ((allusers == (getWiiUaccn() - 1)) ? (getWiiUaccn() - 1) : (allusers + 1)); - break; - case 2: - common = common ? false : true; - break; - default: - break; + if (input->get(TRIGGER, PAD_BUTTON_LEFT)) { + if (this->task == copytoOtherDevice) { + switch (cursorPos) { + case 0: + break; + case 1: + this->allusers = ((this->allusers == -1) ? -1 : (this->allusers - 1)); + allusers_d = this->allusers; + break; + case 2: + allusers_d = (((this->allusers == -1) || (allusers_d == -1)) ? -1 : (allusers_d - 1)); + allusers_d = ((this->allusers > -1) && (allusers_d == -1)) ? 0 : allusers_d; + break; + case 3: + common = common ? false : true; + break; + default: + break; + } + } else if (this->task == restore) { + switch (cursorPos) { + case 0: + getAccountsSD(&this->title, --slot); + break; + case 1: + sdusers = ((sdusers == -1) ? -1 : (sdusers - 1)); + this->allusers = ((sdusers == -1) ? -1 : this->allusers); + break; + case 2: + allusers = (((allusers == -1) || (sdusers == -1)) ? -1 : (allusers - 1)); + allusers = ((sdusers > -1) && (allusers == -1)) ? 0 : allusers; + break; + case 3: + common = common ? false : true; + break; + default: + break; + } + } else if (this->task == wipe) { + switch (cursorPos) { + case 0: + break; + case 1: + allusers = ((allusers == -1) ? -1 : (allusers - 1)); + break; + case 2: + common = common ? false : true; + break; + default: + break; + } + } else if ((this->task == importLoadiine) || (this->task == exportLoadiine)) { + switch (cursorPos) { + case 0: + slot--; + break; + case 1: + common = common ? false : true; + break; + default: + break; + } + } else { + switch (cursorPos) { + case 0: + slot--; + break; + case 1: + allusers = ((allusers == -1) ? -1 : (allusers - 1)); + break; + case 2: + common = common ? false : true; + break; + default: + break; + } } - } else if ((this->task == importLoadiine) || (this->task == exportLoadiine)) { - switch (cursorPos) { - case 0: - slot++; - break; - case 1: - common = common ? false : true; - break; - default: - break; + } + if (input->get(TRIGGER, PAD_BUTTON_RIGHT)) { + if (this->task == copytoOtherDevice) { + switch (cursorPos) { + case 0: + break; + case 1: + allusers = ((allusers == (getWiiUaccn() - 1)) ? (getWiiUaccn() - 1) : (allusers + 1)); + allusers_d = allusers; + break; + case 2: + allusers_d = ((allusers_d == (getWiiUaccn() - 1)) ? (getWiiUaccn() - 1) : (allusers_d + 1)); + allusers_d = (allusers == -1) ? -1 : allusers_d; + break; + case 3: + common = common ? false : true; + break; + default: + break; + } + } else if (this->task == restore) { + switch (cursorPos) { + case 0: + getAccountsSD(&this->title, ++slot); + break; + case 1: + sdusers = ((sdusers == (getSDaccn() - 1)) ? (getSDaccn() - 1) : (sdusers + 1)); + allusers = ((sdusers > -1) && (allusers == -1)) ? 0 : allusers; + break; + case 2: + allusers = ((allusers == (getWiiUaccn() - 1)) ? (getWiiUaccn() - 1) : (allusers + 1)); + allusers = (sdusers == -1) ? -1 : allusers; + break; + case 3: + common = common ? false : true; + break; + default: + break; + } + } else if (this->task == wipe) { + switch (cursorPos) { + case 0: + break; + case 1: + allusers = ((allusers == (getWiiUaccn() - 1)) ? (getWiiUaccn() - 1) : (allusers + 1)); + break; + case 2: + common = common ? false : true; + break; + default: + break; + } + } else if ((this->task == importLoadiine) || (this->task == exportLoadiine)) { + switch (cursorPos) { + case 0: + slot++; + break; + case 1: + common = common ? false : true; + break; + default: + break; + } + } else { + switch (cursorPos) { + case 0: + slot++; + break; + case 1: + allusers = ((allusers == (getWiiUaccn() - 1)) ? (getWiiUaccn() - 1) : (allusers + 1)); + break; + case 2: + common = common ? false : true; + break; + default: + break; + } } - } else { - switch (cursorPos) { - case 0: - slot++; - break; - case 1: - allusers = ((allusers == (getWiiUaccn() - 1)) ? (getWiiUaccn() - 1) : (allusers + 1)); - break; - case 2: - common = common ? false : true; - break; - default: + } + if (input->get(TRIGGER, PAD_BUTTON_DOWN)) { + if (entrycount <= 14) + cursorPos = (cursorPos + 1) % entrycount; + } else if (input->get(TRIGGER, PAD_BUTTON_UP)) { + if (cursorPos > 0) + --cursorPos; + } + if (input->get(TRIGGER, PAD_BUTTON_A)) { + switch (this->task) { + case backup: + backupSavedata(&this->title, slot, allusers, common); + DrawUtils::setRedraw(true); + break; + case restore: + restoreSavedata(&this->title, slot, sdusers, allusers, common); + DrawUtils::setRedraw(true); + break; + case wipe: + wipeSavedata(&this->title, allusers, common); + DrawUtils::setRedraw(true); + break; + case copytoOtherDevice: + for (int i = 0; i < this->titleCount; i++) { + if (titles[i].listID == this->title.dupeID) { + copySavedata(&this->title, &titles[i], allusers, allusers_d, common); + DrawUtils::setRedraw(true); + break; + } + } + DrawUtils::setRedraw(true); break; } } - } - if (input->get(TRIGGER, PAD_BUTTON_DOWN)) { - if (entrycount <= 14) - cursorPos = (cursorPos + 1) % entrycount; - } else if (input->get(TRIGGER, PAD_BUTTON_UP)) { - if (cursorPos > 0) - --cursorPos; - } - if (input->get(TRIGGER, PAD_BUTTON_A)) { - switch (this->task) { - case backup: - backupSavedata(&this->title, slot, allusers, common); - DrawUtils::setRedraw(true); - break; - case restore: - restoreSavedata(&this->title, slot, sdusers, allusers, common); - DrawUtils::setRedraw(true); - break; - case wipe: - wipeSavedata(&this->title, allusers, common); - DrawUtils::setRedraw(true); - break; - case copytoOtherDevice: - for (int i = 0; i < this->titleCount; i++) { - if (titles[i].listID == this->title.dupeID) { - copySavedata(&this->title, &titles[i], allusers, allusers_d, common); - DrawUtils::setRedraw(true); - break; - } - } - DrawUtils::setRedraw(true); - break; + } else if (this->state == STATE_DO_SUBSTATE) { + auto retSubState = this->subState->update(input); + if (retSubState == SUBSTATE_RUNNING) { + // keep running. + return SUBSTATE_RUNNING; + } else if (retSubState == SUBSTATE_RETURN) { + this->subState.reset(); + this->state = STATE_TITLE_OPTIONS; } } return SUBSTATE_RUNNING; diff --git a/src/menu/TitleTaskState.cpp b/src/menu/TitleTaskState.cpp index 886be10..2a44942 100644 --- a/src/menu/TitleTaskState.cpp +++ b/src/menu/TitleTaskState.cpp @@ -61,6 +61,7 @@ ApplicationState::eSubState TitleTaskState::update(Input *input) { } if (this->task == restore) { + setBackupSetSubPath(); getAccountsSD(&this->title, slot); allusers = ((sdusers == -1) ? -1 : allusers); sdusers = ((allusers == -1) ? -1 : sdusers); diff --git a/src/savemng.cpp b/src/savemng.cpp index b7fd4c1..782f430 100644 --- a/src/savemng.cpp +++ b/src/savemng.cpp @@ -1,23 +1,25 @@ +#include +#include #include +#include +#include +#include +#include #include #include -#include #include #include -#include #include -#include -#include -#include #include - #define __FSAShimSend ((FSError(*)(FSAShimBuffer *, uint32_t))(0x101C400 + 0x042d90)) #define IO_MAX_FILE_BUFFER (1024 * 1024) // 1 MB const char *backupPath = "fs:/vol/external01/wiiu/backups"; const char *loadiineSavePath = "fs:/vol/external01/wiiu/saves"; const char *legacyBackupPath = "fs:/vol/external01/savegames"; +std::string backupSetSubPath = "/"; +std::string backupSetEntry = ">> Current <<"; static char *p1; Account *wiiuacc; @@ -56,12 +58,17 @@ std::string newlibtoFSA(std::string path) { std::string getUnifiedBackupPath(uint32_t highId, uint32_t lowId, uint8_t slot) { if (((highId & 0xFFFFFFF0) == 0x00010000) && (slot == 255)) - return getLegacyBackupPath(highId, lowId); + return StringUtils::stringFormat("%s/%08x%08x", legacyBackupPath, highId, lowId); // LegacyBackup else - return getBackupPath(highId, lowId, slot); - + return StringUtils::stringFormat("%s%s%08x%08x/%u", backupPath, backupSetSubPath.c_str(), highId, lowId, slot); } +void setBackupSetSubPath() { + if (backupSetEntry == CURRENT_BS) + backupSetSubPath = "/"; + else + backupSetSubPath = "/batch/"+backupSetEntry+"/"; +} std::string getBackupPath(uint32_t highId, uint32_t lowId, uint8_t slot){ return StringUtils::stringFormat("%s/%08x%08x/%u", backupPath, highId, lowId, slot); @@ -452,7 +459,7 @@ void getAccountsSD(Title *title, uint8_t slot) { if (sdacc != nullptr) free(sdacc); - std::string path = getBackupPath(highID, lowID, slot); + std::string path = getUnifiedBackupPath(highID, lowID, slot); DIR *dir = opendir(path.c_str()); if (dir != nullptr) { struct dirent *data; @@ -729,10 +736,7 @@ static bool getLoadiineUserDir(char *out, const char *fullSavePath, const char * bool isSlotEmpty(uint32_t highID, uint32_t lowID, uint8_t slot) { std::string path; - if (((highID & 0xFFFFFFF0) == 0x00010000) && (slot == 255)) - path = getLegacyBackupPath(highID, lowID); - else - path = getBackupPath(highID, lowID, slot); + path = getUnifiedBackupPath(highID, lowID,slot); int ret = checkEntry(path.c_str()); return ret <= 0; } @@ -766,7 +770,7 @@ bool hasAccountSave(Title *title, bool inSD, bool iine, uint32_t user, uint8_t s } } else { if (!iine) { - sprintf(srcPath, "%s/%08X", getBackupPath(highID, lowID, slot).c_str(), user); + sprintf(srcPath, "%s/%08X", getUnifiedBackupPath(highID, lowID, slot).c_str(), user); } else { if (!getLoadiineGameSaveDir(srcPath, title->productCode, title->longName, title->highID, title->lowID)) { return false; @@ -788,14 +792,12 @@ bool hasAccountSave(Title *title, bool inSD, bool iine, uint32_t user, uint8_t s if (!inSD) { sprintf(srcPath, "storage_slccmpt01:/title/%08x/%08x/data", highID, lowID); } else { - strcpy(srcPath, getBackupPath(highID, lowID, slot).c_str()); + strcpy(srcPath, getUnifiedBackupPath(highID, lowID, slot).c_str()); } } - if (checkEntry(srcPath) == 2) { - if (!folderEmpty(srcPath)) { + if (checkEntry(srcPath) == 2) + if (!folderEmpty(srcPath)) return true; - } - } return false; } @@ -814,7 +816,7 @@ bool hasCommonSave(Title *title, bool inSD, bool iine, uint8_t slot, int version srcPath = StringUtils::stringFormat("%s/%08x/%08x/%s/common", path, highID, lowID, "user"); } else { if (!iine) { - srcPath = getBackupPath(highID, lowID, slot) + "/common"; + srcPath = getUnifiedBackupPath(highID, lowID, slot) + "/common"; } else { if (!getLoadiineGameSaveDir(srcPath.data(), title->productCode, title->longName, title->highID, title->lowID)) return false; @@ -979,13 +981,14 @@ void backupSavedata(Title *title, uint8_t slot, int8_t allusers, bool common) { if ((allusers > -1) && !isWii) { if (common) { - //srcPath.append("/common"); + //srcPath.append("/common"); //dstPath.append("/common"); if (!copyDir(srcPath+"/common", dstPath+"/common")) promptError(LanguageUtils::gettext("Common save not found.")); } srcPath.append(StringUtils::stringFormat("/%s", wiiuacc[allusers].persistentID)); dstPath.append(StringUtils::stringFormat("/%s", wiiuacc[allusers].persistentID)); + if (checkEntry(srcPath.c_str()) == 0) { promptError(LanguageUtils::gettext("No save found for this user.")); return; @@ -1025,7 +1028,6 @@ void restoreSavedata(Title *title, uint8_t slot, int8_t sdusers, int8_t allusers bool isUSB = title->isTitleOnUSB; bool isWii = ((highID & 0xFFFFFFF0) == 0x00010000); std::string srcPath; - const std::string path = (isWii ? "storage_slccmpt01:/title" : (isUSB ? (getUSB() + "/usr/save").c_str() : "storage_mlc01:/usr/save")); srcPath = getUnifiedBackupPath(highID, lowID, slot); /* if (isWii && (slot == 255)) @@ -1034,7 +1036,8 @@ void restoreSavedata(Title *title, uint8_t slot, int8_t sdusers, int8_t allusers srcPath = getBackupPath(highID, lowID, slot); */ - std::string dstPath = StringUtils::stringFormat("%s/%08x/%08x/%s", path.c_str(), highID, lowID, isWii ? "data" : "user"); + const std::string path = (isWii ? "storage_slccmpt01:/title" : (isUSB ? (getUSB() + "/usr/save").c_str() : "storage_mlc01:/usr/save")); + std::string dstPath = StringUtils::stringFormat("%s/%08x/%08x/%s", path.c_str(), highID, lowID, isWii ? "data" : "user"); createFolderUnlocked(dstPath); if ((sdusers > -1) && !isWii) { From a7084465c85ac16bca59a3b7acb436648d3b6b04 Mon Sep 17 00:00:00 2001 From: w3irDv <170813473+w3irDv@users.noreply.github.com> Date: Sat, 17 Aug 2024 09:46:47 +0200 Subject: [PATCH 05/22] backupsets - some refactoring --- include/BackupSetList.h | 4 ++-- include/menu/BackupSetListState.h | 2 ++ include/menu/BatchBackupState.h | 2 -- include/savemng.h | 3 +-- src/BackupSetList.cpp | 8 +++++--- src/main.cpp | 4 +++- src/menu/BatchBackupState.cpp | 7 ------- src/savemng.cpp | 31 +++++++++---------------------- 8 files changed, 22 insertions(+), 39 deletions(-) diff --git a/include/BackupSetList.h b/include/BackupSetList.h index b90bfb1..b0adf1a 100644 --- a/include/BackupSetList.h +++ b/include/BackupSetList.h @@ -8,8 +8,7 @@ const std::string CURRENT_BS = ">> Current <<"; class BackupSetList { public: friend class BackupSetListState; - friend class BatchBackupState; - BackupSetList(const char* fPath); + BackupSetList(const char *backupSetListRoot); void sort(bool sortAscending = false); std::string at(int i); void add(std::string backupSet); @@ -18,5 +17,6 @@ class BackupSetList { std::vector backupSets; bool sortAscending = false; int entries; + std::string backupSetListRoot; }; diff --git a/include/menu/BackupSetListState.h b/include/menu/BackupSetListState.h index e9702e5..1cf4beb 100644 --- a/include/menu/BackupSetListState.h +++ b/include/menu/BackupSetListState.h @@ -21,4 +21,6 @@ class BackupSetListState : public ApplicationState { int scroll = 0; bool sortAscending; + + std::string backupSetListRoot; }; \ No newline at end of file diff --git a/include/menu/BatchBackupState.h b/include/menu/BatchBackupState.h index d1600a4..c919d09 100644 --- a/include/menu/BatchBackupState.h +++ b/include/menu/BatchBackupState.h @@ -5,8 +5,6 @@ #include #include -void resetBackupList(); - class BatchBackupState : public ApplicationState { public: BatchBackupState(Title *wiiutitles, Title *wiititles, int wiiuTitlesCount, int vWiiTitlesCount) : wiiutitles(wiiutitles), diff --git a/include/savemng.h b/include/savemng.h index b63e8e2..2ab31df 100644 --- a/include/savemng.h +++ b/include/savemng.h @@ -108,9 +108,8 @@ std::string getUSB(); void consolePrintPos(int x, int y, const char *format, ...) __attribute__((hot)); bool promptConfirm(Style st, const std::string &question); void promptError(const char *message, ...); -std::string getBackupPath(uint32_t highID, uint32_t lowID, uint8_t slot); -std::string getLegacyBackupPath(uint32_t highID, uint32_t lowID); std::string getUnifiedBackupPath(uint32_t highID, uint32_t lowID, uint8_t slot); +void resetBackupList(); void setBackupSetSubPath(); void getAccountsWiiU(); void getAccountsSD(Title *title, uint8_t slot); diff --git a/src/BackupSetList.cpp b/src/BackupSetList.cpp index 26dfad3..29b94e7 100644 --- a/src/BackupSetList.cpp +++ b/src/BackupSetList.cpp @@ -1,4 +1,4 @@ -#include "BackupSetList.h" +#include #include #include @@ -7,12 +7,14 @@ #include #include -BackupSetList::BackupSetList(const char* fPath) +BackupSetList::BackupSetList(const char *backupSetListRoot) { + this->backupSetListRoot = backupSetListRoot; + backupSets.push_back(CURRENT_BS); - DIR *dir = opendir(fPath); + DIR *dir = opendir(backupSetListRoot); if (dir != nullptr) { struct dirent *data; while ((data = readdir(dir)) != nullptr) { diff --git a/src/main.cpp b/src/main.cpp index cbbd1f5..dbf4ed0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -19,7 +19,9 @@ #include static int wiiuTitlesCount = 0, vWiiTitlesCount = 0; + std::unique_ptr myBackupSetList; +extern char *batchBackupPath; template static bool contains(const T (&arr)[N], const T &element) { @@ -438,7 +440,7 @@ int main() { sortTitle(wiiutitles, wiiutitles + wiiuTitlesCount, 1, true); sortTitle(wiititles, wiititles + vWiiTitlesCount, 1, true); - myBackupSetList = std::make_unique("fs:/vol/external01/wiiu/backups/batch"); + myBackupSetList = std::make_unique(batchBackupPath); Input input{}; std::unique_ptr state = std::make_unique(wiiutitles, wiititles, wiiuTitlesCount, diff --git a/src/menu/BatchBackupState.cpp b/src/menu/BatchBackupState.cpp index e712d6f..52c4580 100644 --- a/src/menu/BatchBackupState.cpp +++ b/src/menu/BatchBackupState.cpp @@ -9,13 +9,6 @@ static int cursorPos = 0; -extern std::unique_ptr myBackupSetList; - -void resetBackupList() { - myBackupSetList.reset(); - myBackupSetList = std::make_unique("fs:/vol/external01/wiiu/backups/batch"); -} - void BatchBackupState::render() { consolePrintPos(M_OFF, 2, LanguageUtils::gettext(" Backup All (%u Title%s)"), this->wiiuTitlesCount + this->vWiiTitlesCount, ((this->wiiuTitlesCount + this->vWiiTitlesCount) > 1) ? "s" : ""); diff --git a/src/savemng.cpp b/src/savemng.cpp index 782f430..b107ca0 100644 --- a/src/savemng.cpp +++ b/src/savemng.cpp @@ -16,10 +16,13 @@ #define IO_MAX_FILE_BUFFER (1024 * 1024) // 1 MB const char *backupPath = "fs:/vol/external01/wiiu/backups"; +const char *batchBackupPath = "fs:/vol/external01/wiiu/backups/batch"; // Must be "backupPath/batch" ~ backupSetListRoot const char *loadiineSavePath = "fs:/vol/external01/wiiu/saves"; const char *legacyBackupPath = "fs:/vol/external01/savegames"; std::string backupSetSubPath = "/"; -std::string backupSetEntry = ">> Current <<"; +std::string backupSetEntry = CURRENT_BS; + +extern std::unique_ptr myBackupSetList; static char *p1; Account *wiiuacc; @@ -70,12 +73,9 @@ void setBackupSetSubPath() { backupSetSubPath = "/batch/"+backupSetEntry+"/"; } -std::string getBackupPath(uint32_t highId, uint32_t lowId, uint8_t slot){ - return StringUtils::stringFormat("%s/%08x%08x/%u", backupPath, highId, lowId, slot); -} - -std::string getLegacyBackupPath(uint32_t highId, uint32_t lowId){ - return StringUtils::stringFormat("%s/%08x%08x", legacyBackupPath, highId, lowId); +void resetBackupList() { + myBackupSetList.reset(); + myBackupSetList = std::make_unique(batchBackupPath); } uint8_t getSDaccn() { @@ -950,7 +950,7 @@ void backupAllSave(Title *titles, int count, OSCalendarTime *date) { bool isWii = ((highID & 0xFFFFFFF0) == 0x00010000); const std::string path = (isWii ? "storage_slccmpt01:/title" : (isUSB ? (getUSB() + "/usr/save").c_str() : "storage_mlc01:/usr/save")); std::string srcPath = StringUtils::stringFormat("%s/%08x/%08x/%s", path.c_str(), highID, lowID, isWii ? "data" : "user"); - std::string dstPath = StringUtils::stringFormat("%s/batch/%s/%08x%08x/0", backupPath, datetime.c_str(), highID, lowID); + std::string dstPath = StringUtils::stringFormat("%s/%s/%08x%08x/0", batchBackupPath, datetime.c_str(), highID, lowID); createFolder(dstPath.c_str()); if (!copyDir(srcPath, dstPath)) @@ -971,13 +971,7 @@ void backupSavedata(Title *title, uint8_t slot, int8_t allusers, bool common) { std::string srcPath = StringUtils::stringFormat("%s/%08x/%08x/%s", path.c_str(), highID, lowID, isWii ? "data" : "user"); std::string dstPath; dstPath = getUnifiedBackupPath(highID, lowID, slot); - /* - if (isWii && (slot == 255)) - dstPath = StringUtils::stringFormat("%s/%08x%08x", legacyBackupPath, highID, lowID); - else - dstPath = getBackupPath(highID, lowID, slot); - */ - createFolder(dstPath.c_str()); + createFolder(dstPath.c_str()); if ((allusers > -1) && !isWii) { if (common) { @@ -1029,13 +1023,6 @@ void restoreSavedata(Title *title, uint8_t slot, int8_t sdusers, int8_t allusers bool isWii = ((highID & 0xFFFFFFF0) == 0x00010000); std::string srcPath; srcPath = getUnifiedBackupPath(highID, lowID, slot); - /* - if (isWii && (slot == 255)) - srcPath = StringUtils::stringFormat("%s/%08x%08x", legacyBackupPath, highID, lowID); - else - srcPath = getBackupPath(highID, lowID, slot); - - */ const std::string path = (isWii ? "storage_slccmpt01:/title" : (isUSB ? (getUSB() + "/usr/save").c_str() : "storage_mlc01:/usr/save")); std::string dstPath = StringUtils::stringFormat("%s/%08x/%08x/%s", path.c_str(), highID, lowID, isWii ? "data" : "user"); createFolderUnlocked(dstPath); From 5061c892586375a97236a8093275578e6632b74c Mon Sep 17 00:00:00 2001 From: w3irDv <170813473+w3irDv@users.noreply.github.com> Date: Sat, 17 Aug 2024 20:45:01 +0200 Subject: [PATCH 06/22] batch backup: add savedata - backupSetList: improve UI --- include/BackupSetList.h | 3 +- include/date.h | 10 ++++- include/menu/BackupSetListState.h | 5 ++- include/savemng.h | 7 +++- include/utils/Colors.h | 5 ++- languages/english.json | 9 ++++- src/BackupSetList.cpp | 12 +++--- src/menu/BackupSetListState.cpp | 41 +++++++++++++-------- src/menu/BatchBackupState.cpp | 35 ++++++++++-------- src/menu/TitleOptionsState.cpp | 2 +- src/savemng.cpp | 61 +++++++++++++++++++------------ 11 files changed, 122 insertions(+), 68 deletions(-) diff --git a/include/BackupSetList.h b/include/BackupSetList.h index b0adf1a..cf6cabb 100644 --- a/include/BackupSetList.h +++ b/include/BackupSetList.h @@ -12,10 +12,11 @@ class BackupSetList { void sort(bool sortAscending = false); std::string at(int i); void add(std::string backupSet); + + static bool sortAscending; private: std::vector backupSets; - bool sortAscending = false; int entries; std::string backupSetListRoot; diff --git a/include/date.h b/include/date.h index 527aa97..98219d1 100644 --- a/include/date.h +++ b/include/date.h @@ -9,9 +9,15 @@ class Date { Date(uint32_t high, uint32_t low, uint8_t s) : highID(high), lowID(low), slot(s), - //path(StringUtils::stringFormat("sd:/wiiu/backups/%08x%08x/%u/savemiiMeta.json", highID, lowID, slot)) { - path(getUnifiedBackupPath(highID, lowID, slot).append("/savemiiMeta.json")) { + path (getUnifiedBackupPath(highID, lowID, slot).append("/savemiiMeta.json")) { } + + Date(uint32_t high, uint32_t low, uint8_t s, std::string datetime) : highID(high), + lowID(low), + slot(s), + path (getBatchBackupPath(highID, lowID, slot, datetime).append("/savemiiMeta.json")) { + } + std::string get(); bool set(const std::string &date); diff --git a/include/menu/BackupSetListState.h b/include/menu/BackupSetListState.h index 1cf4beb..8aea7cc 100644 --- a/include/menu/BackupSetListState.h +++ b/include/menu/BackupSetListState.h @@ -4,9 +4,13 @@ #include #include + + + class BackupSetListState : public ApplicationState { public: BackupSetListState(); + static void resetCursorPosition(); enum eState { STATE_BACKUPSET_MENU, STATE_DO_SUBSTATE, @@ -19,7 +23,6 @@ class BackupSetListState : public ApplicationState { std::unique_ptr subState{}; eState state = STATE_BACKUPSET_MENU; - int scroll = 0; bool sortAscending; std::string backupSetListRoot; diff --git a/include/savemng.h b/include/savemng.h index 2ab31df..2f80609 100644 --- a/include/savemng.h +++ b/include/savemng.h @@ -109,6 +109,7 @@ void consolePrintPos(int x, int y, const char *format, ...) __attribute__((hot)) bool promptConfirm(Style st, const std::string &question); void promptError(const char *message, ...); std::string getUnifiedBackupPath(uint32_t highID, uint32_t lowID, uint8_t slot); +std::string getBatchBackupPath(uint32_t highID, uint32_t lowID, uint8_t slot, std::string datetime); void resetBackupList(); void setBackupSetSubPath(); void getAccountsWiiU(); @@ -119,7 +120,11 @@ bool getLoadiineSaveVersionList(int *out, const char *gamePath); bool isSlotEmpty(uint32_t highID, uint32_t lowID, uint8_t slot); bool hasCommonSave(Title *title, bool inSD, bool iine, uint8_t slot, int version); void copySavedata(Title *title, Title *titled, int8_t allusers, int8_t allusers_d, bool common) __attribute__((hot)); -void backupAllSave(Title *titles, int count, OSCalendarTime *date) __attribute__((hot)); +std::string getNowDateForFolder() __attribute__((hot)); +std::string getNowDate() __attribute__((hot)); +void writeSavedataDate(uint32_t highID,uint32_t lowID,uint8_t slot) __attribute__((hot)); +void writeSavedataDate(uint32_t highID,uint32_t lowID,uint8_t slot, const std::string &batchDatetime) __attribute__((hot)); +void backupAllSave(Title *titles, int count, const std::string &batchDatetime) __attribute__((hot)); void backupSavedata(Title *title, uint8_t slot, int8_t allusers, bool common) __attribute__((hot)); void restoreSavedata(Title *title, uint8_t slot, int8_t sdusers, int8_t allusers, bool common) __attribute__((hot)); void wipeSavedata(Title *title, int8_t allusers, bool common) __attribute__((hot)); diff --git a/include/utils/Colors.h b/include/utils/Colors.h index 3e24658..36c1ae6 100644 --- a/include/utils/Colors.h +++ b/include/utils/Colors.h @@ -3,4 +3,7 @@ #define COLOR_WHITE Color(0xffffffff) #define COLOR_BLACK Color(0, 0, 0, 255) #define COLOR_BACKGROUND Color(0x00006F00) -#define COLOR_TEXT COLOR_WHITE \ No newline at end of file +#define COLOR_TEXT COLOR_WHITE +#define COLOR_LIST_CONTRAST Color(0xFF9000FF) +#define COLOR_LIST Color(0x00FF00FF) +#define COLOR_INFO Color(0x88CC88FF) \ No newline at end of file diff --git a/languages/english.json b/languages/english.json index 74d67c2..13f4653 100644 --- a/languages/english.json +++ b/languages/english.json @@ -94,5 +94,12 @@ "Failed to delete savefile.": "Failed to delete savefile.", "Failed to delete user folder.\n%s": "Failed to delete user folder.\n%s", "Failed to import savedata from loadiine.": "Failed to import savedata from loadiine.", - "Failed to export savedata to loadiine.": "Failed to export savedata to loadiine." + "Failed to export savedata to loadiine.": "Failed to export savedata to loadiine.", + "\ue083 Sort: %s \ue084": "\ue083 Sort: %s \ue084", + "\ue000: Select BackupSet \ue001: Back": "\ue000: Select BackupSet \ue001: Back", + "WiiU USB Savedata >> slot 0": "WiiU USB Savedata >> slot 0", + "WiiU NAND Savedata >> slot 1": "WiiU NAND Savedata >> slot 1", + "vWii Savedata >> slot 0": "vWii Savedata >> slot 0" + "\uE002: Chg BackupSet \ue000: Restore \ue001: Back": "\uE002: Chg BackupSet \ue000: Restore \ue001: Back", + "BackupSet: %s": "BackupSet: %s" } \ No newline at end of file diff --git a/src/BackupSetList.cpp b/src/BackupSetList.cpp index 29b94e7..50dcf74 100644 --- a/src/BackupSetList.cpp +++ b/src/BackupSetList.cpp @@ -7,6 +7,8 @@ #include #include +bool BackupSetList::sortAscending = false; + BackupSetList::BackupSetList(const char *backupSetListRoot) { @@ -26,18 +28,18 @@ BackupSetList::BackupSetList(const char *backupSetListRoot) closedir(dir); this->entries = backupSets.size(); - this->sort(false); + this->sort(sortAscending); } -void BackupSetList::sort(bool sortAscending) +void BackupSetList::sort(bool sortAscending_) { - if (sortAscending) { + if (sortAscending_) { std::ranges::sort(backupSets.begin()+1,backupSets.end(),std::ranges::less{}); } else { std::ranges::sort(backupSets.begin()+1,backupSets.end(),std::ranges::greater{}); } - this->sortAscending = sortAscending; + sortAscending = sortAscending_; } std::string BackupSetList::at(int i) @@ -51,6 +53,6 @@ void BackupSetList::add(std::string backupSet) { backupSets.push_back(backupSet); this->entries++; - if (!this->sortAscending) + if (!sortAscending) this->sort(false); } diff --git a/src/menu/BackupSetListState.cpp b/src/menu/BackupSetListState.cpp index e4a8519..cde1576 100644 --- a/src/menu/BackupSetListState.cpp +++ b/src/menu/BackupSetListState.cpp @@ -8,7 +8,7 @@ #define MAX_ROWS_SHOW 14 static int cursorPos = 0; - +static int scroll = 0; static std::string language; extern std::unique_ptr myBackupSetList; @@ -16,7 +16,18 @@ extern std::string backupSetSubPath; extern std::string backupSetEntry; BackupSetListState::BackupSetListState() { - this->sortAscending = myBackupSetList->sortAscending; + this->sortAscending = BackupSetList::sortAscending; +} + +void BackupSetListState::resetCursorPosition() { // after batch Backup + if ( cursorPos == 0 ) + return; + if (BackupSetList::sortAscending) { + return; + } + else { + cursorPos++; + } } void BackupSetListState::render() { @@ -24,29 +35,23 @@ void BackupSetListState::render() { consolePrintPos(44, 0, LanguageUtils::gettext("\ue083 Sort: %s \ue084"), this->sortAscending ? "\u2191" : "\u2193"); for (int i = 0; i < MAX_ROWS_SHOW; i++) { - if (i + this->scroll < 0 || i + this->scroll >= myBackupSetList->entries) + if (i + scroll < 0 || i + scroll >= myBackupSetList->entries) break; - DrawUtils::setFontColor(static_cast(0x00FF00FF)); - if (myBackupSetList->at(i + this->scroll) == CURRENT_BS) - DrawUtils::setFontColor(static_cast(0xFF9000FF)); - consolePrintPos(M_OFF, i + 2, " %s", myBackupSetList->at(i + this->scroll).c_str()); - DrawUtils::setFontColor(COLOR_TEXT); + DrawUtils::setFontColor(COLOR_LIST); + if (myBackupSetList->at(i + scroll) == CURRENT_BS) + DrawUtils::setFontColor(COLOR_LIST_CONTRAST); + consolePrintPos(M_OFF, i + 2, " %s", myBackupSetList->at(i + scroll).c_str()); } - + DrawUtils::setFontColor(COLOR_TEXT); consolePrintPos(-1, 2 + cursorPos, "\u2192"); consolePrintPosAligned(17, 4, 2, LanguageUtils::gettext("\ue000: Select BackupSet \ue001: Back")); -/* - language = LanguageUtils::getLoadedLanguage(); - consolePrintPos(M_OFF, 2, LanguageUtils::gettext(" Language: %s"), language.c_str()); - consolePrintPos(M_OFF, 2 + cursorPos, "\u2192"); -*/ } ApplicationState::eSubState BackupSetListState::update(Input *input) { if (input->get(TRIGGER, PAD_BUTTON_B)) return SUBSTATE_RETURN; if (input->get(TRIGGER, PAD_BUTTON_A)) { - backupSetEntry = myBackupSetList->at(cursorPos + this->scroll); + backupSetEntry = myBackupSetList->at(cursorPos + scroll); setBackupSetSubPath(); DrawUtils::setRedraw(true); return SUBSTATE_RETURN; @@ -55,12 +60,16 @@ ApplicationState::eSubState BackupSetListState::update(Input *input) { if ( this->sortAscending ) { this->sortAscending = false; myBackupSetList->sort(this->sortAscending); + cursorPos = 0; + scroll = 0; } } if (input->get(TRIGGER, PAD_BUTTON_R)) { if ( ! this->sortAscending ) { this->sortAscending = true; myBackupSetList->sort(this->sortAscending); + cursorPos = 0; + scroll = 0; } } if (input->get(TRIGGER, PAD_BUTTON_DOWN)) { @@ -68,7 +77,7 @@ ApplicationState::eSubState BackupSetListState::update(Input *input) { cursorPos = (cursorPos + 1) % myBackupSetList->entries; else if (cursorPos < 6) cursorPos++; - else if (((cursorPos + this->scroll + 1) % myBackupSetList->entries) != 0) + else if (((cursorPos + scroll + 1) % myBackupSetList->entries) != 0) scroll++; else cursorPos = scroll = 0; diff --git a/src/menu/BatchBackupState.cpp b/src/menu/BatchBackupState.cpp index 52c4580..32fda1f 100644 --- a/src/menu/BatchBackupState.cpp +++ b/src/menu/BatchBackupState.cpp @@ -1,9 +1,12 @@ #include #include +#include #include #include #include #include +#include +#include #define ENTRYCOUNT 3 @@ -16,6 +19,11 @@ void BatchBackupState::render() { (this->wiiuTitlesCount > 1) ? "s" : ""); consolePrintPos(M_OFF, 4, LanguageUtils::gettext(" Backup vWii (%u Title%s)"), this->vWiiTitlesCount, (this->vWiiTitlesCount > 1) ? "s" : ""); + DrawUtils::setFontColor(COLOR_INFO); + consolePrintPosAligned(10,4,2,LanguageUtils::gettext("WiiU USB Savedata >> slot 0")); + consolePrintPosAligned(11,4,2,LanguageUtils::gettext("WiiU NAND Savedata >> slot 1")); + consolePrintPosAligned(12,4,2,LanguageUtils::gettext("vWii Savedata >> slot 0")); + DrawUtils::setFontColor(COLOR_TEXT); consolePrintPos(M_OFF, 2 + cursorPos, "\u2192"); consolePrintPosAligned(17, 4, 2, LanguageUtils::gettext("\ue000: Backup \ue001: Back")); } @@ -30,28 +38,25 @@ ApplicationState::eSubState BatchBackupState::update(Input *input) { if (input->get(TRIGGER, PAD_BUTTON_B)) return SUBSTATE_RETURN; if (input->get(TRIGGER, PAD_BUTTON_A)) { - OSCalendarTime dateTime; + const std::string batchDatetime = getNowDateForFolder(); switch (cursorPos) { case 0: - dateTime.tm_year = 0; - backupAllSave(this->wiiutitles, this->wiiuTitlesCount, &dateTime); - backupAllSave(this->wiititles, this->vWiiTitlesCount, &dateTime); - resetBackupList(); - DrawUtils::setRedraw(true); - return SUBSTATE_RETURN; + backupAllSave(this->wiiutitles, this->wiiuTitlesCount, batchDatetime); + backupAllSave(this->wiititles, this->vWiiTitlesCount, batchDatetime); + break; case 1: - backupAllSave(this->wiiutitles, this->wiiuTitlesCount, nullptr); - resetBackupList(); - DrawUtils::setRedraw(true); - return SUBSTATE_RETURN; + backupAllSave(this->wiiutitles, this->wiiuTitlesCount, batchDatetime); + break; case 2: - backupAllSave(this->wiititles, this->vWiiTitlesCount, nullptr); - resetBackupList(); - DrawUtils::setRedraw(true); - return SUBSTATE_RETURN; + backupAllSave(this->wiititles, this->vWiiTitlesCount, batchDatetime); + break; default: return SUBSTATE_RETURN; } + resetBackupList(); + BackupSetListState::resetCursorPosition(); + DrawUtils::setRedraw(true); + return SUBSTATE_RETURN; } return SUBSTATE_RUNNING; } \ No newline at end of file diff --git a/src/menu/TitleOptionsState.cpp b/src/menu/TitleOptionsState.cpp index 261a61e..c8830f6 100644 --- a/src/menu/TitleOptionsState.cpp +++ b/src/menu/TitleOptionsState.cpp @@ -19,7 +19,7 @@ void TitleOptionsState::render() { } if (this->state == STATE_TITLE_OPTIONS) { if (this->task == restore) { - consolePrintPosAligned(0, 4, 2,"BackupSet: %s",backupSetEntry.c_str()); + consolePrintPosAligned(0, 4, 2,LanguageUtils::gettext("BackupSet: %s"),backupSetEntry.c_str()); } this->isWiiUTitle = (this->title.highID == 0x00050000) || (this->title.highID == 0x00050002); entrycount = 3; diff --git a/src/savemng.cpp b/src/savemng.cpp index b107ca0..2b3dd80 100644 --- a/src/savemng.cpp +++ b/src/savemng.cpp @@ -66,6 +66,10 @@ std::string getUnifiedBackupPath(uint32_t highId, uint32_t lowId, uint8_t slot) return StringUtils::stringFormat("%s%s%08x%08x/%u", backupPath, backupSetSubPath.c_str(), highId, lowId, slot); } +std::string getBatchBackupPath(uint32_t highId, uint32_t lowId, uint8_t slot, std::string datetime) { + return StringUtils::stringFormat("%s/%s/%08x%08x/%u", batchBackupPath, datetime.c_str(),highId, lowId, slot); +} + void setBackupSetSubPath() { if (backupSetEntry == CURRENT_BS) backupSetSubPath = "/"; @@ -925,37 +929,51 @@ void copySavedata(Title *title, Title *titleb, int8_t allusers, int8_t allusers_ } } -void backupAllSave(Title *titles, int count, OSCalendarTime *date) { - OSCalendarTime dateTime; - if (date) { - if (date->tm_year == 0) { - OSTicksToCalendarTime(OSGetTime(), date); - date->tm_mon++; - } - dateTime = (*date); - } else { - OSTicksToCalendarTime(OSGetTime(), &dateTime); - dateTime.tm_mon++; - } +std::string getNowDate() { + OSCalendarTime now; + OSTicksToCalendarTime(OSGetTime(), &now); + return StringUtils::stringFormat("%02d/%02d/%d %02d:%02d", now.tm_mday, ++now.tm_mon, now.tm_year, now.tm_hour, now.tm_min); +} + +std::string getNowDateForFolder() { + OSCalendarTime now; + OSTicksToCalendarTime(OSGetTime(), &now); + return StringUtils::stringFormat("%04d-%02d-%02dT%02d%02d%02d", now.tm_year, ++now.tm_mon, now.tm_mday, + now.tm_hour, now.tm_min, now.tm_sec); +} + +void writeSavedataDate(uint32_t highID,uint32_t lowID,uint8_t slot) { + Date *dateObj = new Date(highID, lowID, slot); + dateObj->set(getNowDate()); + delete dateObj; +} - std::string datetime = StringUtils::stringFormat("%04d-%02d-%02dT%02d%02d%02d", dateTime.tm_year, dateTime.tm_mon, dateTime.tm_mday, - dateTime.tm_hour, dateTime.tm_min, dateTime.tm_sec); +void writeSavedataDate(uint32_t highID,uint32_t lowID,uint8_t slot, const std::string &batchDatetime) { + Date *dateObj = new Date(highID, lowID, slot, batchDatetime); + dateObj->set(getNowDate()); + delete dateObj; +} + +void backupAllSave(Title *titles, int count, const std::string &batchDatetime) { for (int i = 0; i < count; i++) { if (titles[i].highID == 0 || titles[i].lowID == 0 || !titles[i].saveInit) continue; - uint32_t highID = titles[i].highID; uint32_t lowID = titles[i].lowID; bool isUSB = titles[i].isTitleOnUSB; bool isWii = ((highID & 0xFFFFFFF0) == 0x00010000); + uint8_t slot = ( isWii ? 0 : (isUSB ? 0 : 1)); const std::string path = (isWii ? "storage_slccmpt01:/title" : (isUSB ? (getUSB() + "/usr/save").c_str() : "storage_mlc01:/usr/save")); std::string srcPath = StringUtils::stringFormat("%s/%08x/%08x/%s", path.c_str(), highID, lowID, isWii ? "data" : "user"); - std::string dstPath = StringUtils::stringFormat("%s/%s/%08x%08x/0", batchBackupPath, datetime.c_str(), highID, lowID); + std::string dstPath = StringUtils::stringFormat("%s/%s/%08x%08x/%u", batchBackupPath, batchDatetime.c_str(), highID, lowID,slot); createFolder(dstPath.c_str()); if (!copyDir(srcPath, dstPath)) promptError(LanguageUtils::gettext("Backup failed.")); + else + writeSavedataDate(highID,lowID,slot, batchDatetime); } + } void backupSavedata(Title *title, uint8_t slot, int8_t allusers, bool common) { @@ -975,8 +993,6 @@ void backupSavedata(Title *title, uint8_t slot, int8_t allusers, bool common) { if ((allusers > -1) && !isWii) { if (common) { - //srcPath.append("/common"); - //dstPath.append("/common"); if (!copyDir(srcPath+"/common", dstPath+"/common")) promptError(LanguageUtils::gettext("Common save not found.")); } @@ -990,12 +1006,9 @@ void backupSavedata(Title *title, uint8_t slot, int8_t allusers, bool common) { } if (!copyDir(srcPath, dstPath)) promptError(LanguageUtils::gettext("Backup failed. DO NOT restore from this slot.")); - OSCalendarTime now; - OSTicksToCalendarTime(OSGetTime(), &now); - const std::string date = StringUtils::stringFormat("%02d/%02d/%d %02d:%02d", now.tm_mday, ++now.tm_mon, now.tm_year, now.tm_hour, now.tm_min); - Date *dateObj = new Date(title->highID, title->lowID, slot); - dateObj->set(date); - delete dateObj; + else + writeSavedataDate(highID,lowID,slot); + if (dstPath.rfind("storage_slccmpt01:", 0) == 0) { FSAFlushVolume(handle, "/vol/storage_slccmpt01"); } else if (dstPath.rfind("storage_mlc01:", 0) == 0) { From 6255f4c1be7f539899de530f1ee0c467745b5a58 Mon Sep 17 00:00:00 2001 From: w3irDv <170813473+w3irDv@users.noreply.github.com> Date: Sun, 18 Aug 2024 10:01:31 +0200 Subject: [PATCH 07/22] backupsets - more refactoring --- include/BackupSetList.h | 21 +++++++++++++--- include/date.h | 2 +- include/savemng.h | 4 +-- src/BackupSetList.cpp | 24 ++++++++++++++++++ src/main.cpp | 3 +-- src/menu/BackupSetListState.cpp | 30 ++++++++++------------- src/menu/BatchBackupState.cpp | 2 +- src/menu/TitleOptionsState.cpp | 13 ++++++---- src/menu/TitleTaskState.cpp | 3 ++- src/savemng.cpp | 43 +++++++-------------------------- 10 files changed, 77 insertions(+), 68 deletions(-) diff --git a/include/BackupSetList.h b/include/BackupSetList.h index cf6cabb..01df773 100644 --- a/include/BackupSetList.h +++ b/include/BackupSetList.h @@ -2,22 +2,35 @@ #include #include - -const std::string CURRENT_BS = ">> Current <<"; +#include class BackupSetList { public: friend class BackupSetListState; + + BackupSetList() {}; BackupSetList(const char *backupSetListRoot); + static std::unique_ptr currentBackupSetList; + void sort(bool sortAscending = false); std::string at(int i); void add(std::string backupSet); + + static const std::string CURRENT_BS; + static std::string getBackupSetSubPath() { return backupSetSubPath; } + static std::string getBackupSetEntry() { return backupSetEntry; } + static void setBackupSetEntry(int i); + static void setBackupSetSubPath(); + static void initBackupSetList(); + static void setBackupSetSubPathToRoot() { backupSetSubPath = "/"; } - static bool sortAscending; - private: + static bool sortAscending; std::vector backupSets; int entries; std::string backupSetListRoot; + static std::string backupSetSubPath; + static std::string backupSetEntry; }; + diff --git a/include/date.h b/include/date.h index 98219d1..be9ea3a 100644 --- a/include/date.h +++ b/include/date.h @@ -9,7 +9,7 @@ class Date { Date(uint32_t high, uint32_t low, uint8_t s) : highID(high), lowID(low), slot(s), - path (getUnifiedBackupPath(highID, lowID, slot).append("/savemiiMeta.json")) { + path (getDynamicBackupPath(highID, lowID, slot).append("/savemiiMeta.json")) { } Date(uint32_t high, uint32_t low, uint8_t s, std::string datetime) : highID(high), diff --git a/include/savemng.h b/include/savemng.h index 2f80609..b711e47 100644 --- a/include/savemng.h +++ b/include/savemng.h @@ -108,10 +108,8 @@ std::string getUSB(); void consolePrintPos(int x, int y, const char *format, ...) __attribute__((hot)); bool promptConfirm(Style st, const std::string &question); void promptError(const char *message, ...); -std::string getUnifiedBackupPath(uint32_t highID, uint32_t lowID, uint8_t slot); +std::string getDynamicBackupPath(uint32_t highID, uint32_t lowID, uint8_t slot); std::string getBatchBackupPath(uint32_t highID, uint32_t lowID, uint8_t slot, std::string datetime); -void resetBackupList(); -void setBackupSetSubPath(); void getAccountsWiiU(); void getAccountsSD(Title *title, uint8_t slot); bool hasAccountSave(Title *title, bool inSD, bool iine, uint32_t user, uint8_t slot, int version); diff --git a/src/BackupSetList.cpp b/src/BackupSetList.cpp index 50dcf74..c5e6928 100644 --- a/src/BackupSetList.cpp +++ b/src/BackupSetList.cpp @@ -8,6 +8,13 @@ #include bool BackupSetList::sortAscending = false; +const std::string BackupSetList::CURRENT_BS = ">> Current <<"; +std::string BackupSetList::backupSetSubPath = "/";; +std::string BackupSetList::backupSetEntry = CURRENT_BS; + +std::unique_ptr BackupSetList::currentBackupSetList = std::make_unique(); + +extern const char *batchBackupPath; BackupSetList::BackupSetList(const char *backupSetListRoot) { @@ -56,3 +63,20 @@ void BackupSetList::add(std::string backupSet) if (!sortAscending) this->sort(false); } + + +void BackupSetList::initBackupSetList() { + BackupSetList::currentBackupSetList.reset(); + BackupSetList::currentBackupSetList = std::make_unique(batchBackupPath); +} + +void BackupSetList::setBackupSetEntry(int i) { + backupSetEntry = currentBackupSetList->at(i); +} + +void BackupSetList::setBackupSetSubPath() { + if (backupSetEntry == CURRENT_BS) + backupSetSubPath = "/"; + else + backupSetSubPath = "/batch/"+backupSetEntry+"/"; +} diff --git a/src/main.cpp b/src/main.cpp index dbf4ed0..161cc08 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -20,7 +20,6 @@ static int wiiuTitlesCount = 0, vWiiTitlesCount = 0; -std::unique_ptr myBackupSetList; extern char *batchBackupPath; template @@ -440,7 +439,7 @@ int main() { sortTitle(wiiutitles, wiiutitles + wiiuTitlesCount, 1, true); sortTitle(wiititles, wiititles + vWiiTitlesCount, 1, true); - myBackupSetList = std::make_unique(batchBackupPath); + BackupSetList::initBackupSetList(); Input input{}; std::unique_ptr state = std::make_unique(wiiutitles, wiititles, wiiuTitlesCount, diff --git a/src/menu/BackupSetListState.cpp b/src/menu/BackupSetListState.cpp index cde1576..2284f59 100644 --- a/src/menu/BackupSetListState.cpp +++ b/src/menu/BackupSetListState.cpp @@ -11,10 +11,6 @@ static int cursorPos = 0; static int scroll = 0; static std::string language; -extern std::unique_ptr myBackupSetList; -extern std::string backupSetSubPath; -extern std::string backupSetEntry; - BackupSetListState::BackupSetListState() { this->sortAscending = BackupSetList::sortAscending; } @@ -35,12 +31,12 @@ void BackupSetListState::render() { consolePrintPos(44, 0, LanguageUtils::gettext("\ue083 Sort: %s \ue084"), this->sortAscending ? "\u2191" : "\u2193"); for (int i = 0; i < MAX_ROWS_SHOW; i++) { - if (i + scroll < 0 || i + scroll >= myBackupSetList->entries) + if (i + scroll < 0 || i + scroll >= BackupSetList::currentBackupSetList->entries) break; DrawUtils::setFontColor(COLOR_LIST); - if (myBackupSetList->at(i + scroll) == CURRENT_BS) + if (BackupSetList::currentBackupSetList->at(i + scroll) == BackupSetList::CURRENT_BS) DrawUtils::setFontColor(COLOR_LIST_CONTRAST); - consolePrintPos(M_OFF, i + 2, " %s", myBackupSetList->at(i + scroll).c_str()); + consolePrintPos(M_OFF, i + 2, " %s", BackupSetList::currentBackupSetList->at(i + scroll).c_str()); } DrawUtils::setFontColor(COLOR_TEXT); consolePrintPos(-1, 2 + cursorPos, "\u2192"); @@ -51,15 +47,15 @@ ApplicationState::eSubState BackupSetListState::update(Input *input) { if (input->get(TRIGGER, PAD_BUTTON_B)) return SUBSTATE_RETURN; if (input->get(TRIGGER, PAD_BUTTON_A)) { - backupSetEntry = myBackupSetList->at(cursorPos + scroll); - setBackupSetSubPath(); + BackupSetList::setBackupSetEntry(cursorPos + scroll); + BackupSetList::setBackupSetSubPath(); DrawUtils::setRedraw(true); return SUBSTATE_RETURN; } if (input->get(TRIGGER, PAD_BUTTON_L)) { if ( this->sortAscending ) { this->sortAscending = false; - myBackupSetList->sort(this->sortAscending); + BackupSetList::currentBackupSetList->sort(this->sortAscending); cursorPos = 0; scroll = 0; } @@ -67,17 +63,17 @@ ApplicationState::eSubState BackupSetListState::update(Input *input) { if (input->get(TRIGGER, PAD_BUTTON_R)) { if ( ! this->sortAscending ) { this->sortAscending = true; - myBackupSetList->sort(this->sortAscending); + BackupSetList::currentBackupSetList->sort(this->sortAscending); cursorPos = 0; scroll = 0; } } if (input->get(TRIGGER, PAD_BUTTON_DOWN)) { - if (myBackupSetList->entries <= MAX_ROWS_SHOW) - cursorPos = (cursorPos + 1) % myBackupSetList->entries; + if (BackupSetList::currentBackupSetList->entries <= MAX_ROWS_SHOW) + cursorPos = (cursorPos + 1) % BackupSetList::currentBackupSetList->entries; else if (cursorPos < 6) cursorPos++; - else if (((cursorPos + scroll + 1) % myBackupSetList->entries) != 0) + else if (((cursorPos + scroll + 1) % BackupSetList::currentBackupSetList->entries) != 0) scroll++; else cursorPos = scroll = 0; @@ -86,10 +82,10 @@ ApplicationState::eSubState BackupSetListState::update(Input *input) { cursorPos -= (cursorPos > 6) ? 1 : 0 * (scroll--); else if (cursorPos > 0) cursorPos--; - else if (myBackupSetList->entries > MAX_ROWS_SHOW) - scroll = myBackupSetList->entries - (cursorPos = 6) - 1; + else if (BackupSetList::currentBackupSetList->entries > MAX_ROWS_SHOW) + scroll = BackupSetList::currentBackupSetList->entries - (cursorPos = 6) - 1; else - cursorPos = myBackupSetList->entries - 1; + cursorPos = BackupSetList::currentBackupSetList->entries - 1; } return SUBSTATE_RUNNING; } \ No newline at end of file diff --git a/src/menu/BatchBackupState.cpp b/src/menu/BatchBackupState.cpp index 32fda1f..4a7b82c 100644 --- a/src/menu/BatchBackupState.cpp +++ b/src/menu/BatchBackupState.cpp @@ -53,7 +53,7 @@ ApplicationState::eSubState BatchBackupState::update(Input *input) { default: return SUBSTATE_RETURN; } - resetBackupList(); + BackupSetList::initBackupSetList(); BackupSetListState::resetCursorPosition(); DrawUtils::setRedraw(true); return SUBSTATE_RETURN; diff --git a/src/menu/TitleOptionsState.cpp b/src/menu/TitleOptionsState.cpp index c8830f6..d4a0fcd 100644 --- a/src/menu/TitleOptionsState.cpp +++ b/src/menu/TitleOptionsState.cpp @@ -2,13 +2,12 @@ #include #include #include +#include #include +#include #include #include -extern std::string backupSetSubPath; -extern std::string backupSetEntry; - void TitleOptionsState::render() { if (this->state == STATE_DO_SUBSTATE) { if (this->subState == nullptr) { @@ -19,7 +18,9 @@ void TitleOptionsState::render() { } if (this->state == STATE_TITLE_OPTIONS) { if (this->task == restore) { - consolePrintPosAligned(0, 4, 2,LanguageUtils::gettext("BackupSet: %s"),backupSetEntry.c_str()); + DrawUtils::setFontColor(COLOR_INFO); + consolePrintPosAligned(0, 4, 2,LanguageUtils::gettext("BackupSet: %s"),BackupSetList::getBackupSetEntry().c_str()); + DrawUtils::setFontColor(COLOR_TEXT); } this->isWiiUTitle = (this->title.highID == 0x00050000) || (this->title.highID == 0x00050002); entrycount = 3; @@ -190,7 +191,7 @@ void TitleOptionsState::render() { ApplicationState::eSubState TitleOptionsState::update(Input *input) { if (this->state == STATE_TITLE_OPTIONS) { if (input->get(TRIGGER, PAD_BUTTON_B)) { - backupSetSubPath = "/"; // reset nxt operations to current backupSet + BackupSetList::setBackupSetSubPathToRoot(); // reset nxt operations to current backupSet return SUBSTATE_RETURN; } if (input->get(TRIGGER, PAD_BUTTON_X)) @@ -395,6 +396,8 @@ ApplicationState::eSubState TitleOptionsState::update(Input *input) { } else if (retSubState == SUBSTATE_RETURN) { this->subState.reset(); this->state = STATE_TITLE_OPTIONS; + slot = 0; + getAccountsSD(&this->title, slot); } } return SUBSTATE_RUNNING; diff --git a/src/menu/TitleTaskState.cpp b/src/menu/TitleTaskState.cpp index 2a44942..e857d46 100644 --- a/src/menu/TitleTaskState.cpp +++ b/src/menu/TitleTaskState.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -61,7 +62,7 @@ ApplicationState::eSubState TitleTaskState::update(Input *input) { } if (this->task == restore) { - setBackupSetSubPath(); + BackupSetList::setBackupSetSubPath(); getAccountsSD(&this->title, slot); allusers = ((sdusers == -1) ? -1 : allusers); sdusers = ((allusers == -1) ? -1 : sdusers); diff --git a/src/savemng.cpp b/src/savemng.cpp index 2b3dd80..518481d 100644 --- a/src/savemng.cpp +++ b/src/savemng.cpp @@ -19,10 +19,6 @@ const char *backupPath = "fs:/vol/external01/wiiu/backups"; const char *batchBackupPath = "fs:/vol/external01/wiiu/backups/batch"; // Must be "backupPath/batch" ~ backupSetListRoot const char *loadiineSavePath = "fs:/vol/external01/wiiu/saves"; const char *legacyBackupPath = "fs:/vol/external01/savegames"; -std::string backupSetSubPath = "/"; -std::string backupSetEntry = CURRENT_BS; - -extern std::unique_ptr myBackupSetList; static char *p1; Account *wiiuacc; @@ -58,30 +54,18 @@ std::string newlibtoFSA(std::string path) { return path; } -std::string getUnifiedBackupPath(uint32_t highId, uint32_t lowId, uint8_t slot) { +std::string getDynamicBackupPath(uint32_t highId, uint32_t lowId, uint8_t slot) { if (((highId & 0xFFFFFFF0) == 0x00010000) && (slot == 255)) return StringUtils::stringFormat("%s/%08x%08x", legacyBackupPath, highId, lowId); // LegacyBackup else - return StringUtils::stringFormat("%s%s%08x%08x/%u", backupPath, backupSetSubPath.c_str(), highId, lowId, slot); + return StringUtils::stringFormat("%s%s%08x%08x/%u", backupPath, BackupSetList::getBackupSetSubPath().c_str(), highId, lowId, slot); } std::string getBatchBackupPath(uint32_t highId, uint32_t lowId, uint8_t slot, std::string datetime) { return StringUtils::stringFormat("%s/%s/%08x%08x/%u", batchBackupPath, datetime.c_str(),highId, lowId, slot); } -void setBackupSetSubPath() { - if (backupSetEntry == CURRENT_BS) - backupSetSubPath = "/"; - else - backupSetSubPath = "/batch/"+backupSetEntry+"/"; -} - -void resetBackupList() { - myBackupSetList.reset(); - myBackupSetList = std::make_unique(batchBackupPath); -} - uint8_t getSDaccn() { return sdaccn; } @@ -463,7 +447,7 @@ void getAccountsSD(Title *title, uint8_t slot) { if (sdacc != nullptr) free(sdacc); - std::string path = getUnifiedBackupPath(highID, lowID, slot); + std::string path = getDynamicBackupPath(highID, lowID, slot); DIR *dir = opendir(path.c_str()); if (dir != nullptr) { struct dirent *data; @@ -740,7 +724,7 @@ static bool getLoadiineUserDir(char *out, const char *fullSavePath, const char * bool isSlotEmpty(uint32_t highID, uint32_t lowID, uint8_t slot) { std::string path; - path = getUnifiedBackupPath(highID, lowID,slot); + path = getDynamicBackupPath(highID, lowID,slot); int ret = checkEntry(path.c_str()); return ret <= 0; } @@ -774,7 +758,7 @@ bool hasAccountSave(Title *title, bool inSD, bool iine, uint32_t user, uint8_t s } } else { if (!iine) { - sprintf(srcPath, "%s/%08X", getUnifiedBackupPath(highID, lowID, slot).c_str(), user); + sprintf(srcPath, "%s/%08X", getDynamicBackupPath(highID, lowID, slot).c_str(), user); } else { if (!getLoadiineGameSaveDir(srcPath, title->productCode, title->longName, title->highID, title->lowID)) { return false; @@ -796,7 +780,7 @@ bool hasAccountSave(Title *title, bool inSD, bool iine, uint32_t user, uint8_t s if (!inSD) { sprintf(srcPath, "storage_slccmpt01:/title/%08x/%08x/data", highID, lowID); } else { - strcpy(srcPath, getUnifiedBackupPath(highID, lowID, slot).c_str()); + strcpy(srcPath, getDynamicBackupPath(highID, lowID, slot).c_str()); } } if (checkEntry(srcPath) == 2) @@ -820,7 +804,7 @@ bool hasCommonSave(Title *title, bool inSD, bool iine, uint8_t slot, int version srcPath = StringUtils::stringFormat("%s/%08x/%08x/%s/common", path, highID, lowID, "user"); } else { if (!iine) { - srcPath = getUnifiedBackupPath(highID, lowID, slot) + "/common"; + srcPath = getDynamicBackupPath(highID, lowID, slot) + "/common"; } else { if (!getLoadiineGameSaveDir(srcPath.data(), title->productCode, title->longName, title->highID, title->lowID)) return false; @@ -988,7 +972,7 @@ void backupSavedata(Title *title, uint8_t slot, int8_t allusers, bool common) { const std::string path = (isWii ? "storage_slccmpt01:/title" : (isUSB ? (getUSB() + "/usr/save").c_str() : "storage_mlc01:/usr/save")); std::string srcPath = StringUtils::stringFormat("%s/%08x/%08x/%s", path.c_str(), highID, lowID, isWii ? "data" : "user"); std::string dstPath; - dstPath = getUnifiedBackupPath(highID, lowID, slot); + dstPath = getDynamicBackupPath(highID, lowID, slot); createFolder(dstPath.c_str()); if ((allusers > -1) && !isWii) { @@ -1009,15 +993,6 @@ void backupSavedata(Title *title, uint8_t slot, int8_t allusers, bool common) { else writeSavedataDate(highID,lowID,slot); - if (dstPath.rfind("storage_slccmpt01:", 0) == 0) { - FSAFlushVolume(handle, "/vol/storage_slccmpt01"); - } else if (dstPath.rfind("storage_mlc01:", 0) == 0) { - FSAFlushVolume(handle, "/vol/storage_mlc01"); - } else if (dstPath.rfind("storage_usb01:", 0) == 0) { - FSAFlushVolume(handle, "/vol/storage_usb01"); - } else if (dstPath.rfind("storage_usb02:", 0) == 0) { - FSAFlushVolume(handle, "/vol/storage_usb02"); - } } void restoreSavedata(Title *title, uint8_t slot, int8_t sdusers, int8_t allusers, bool common) { @@ -1035,7 +1010,7 @@ void restoreSavedata(Title *title, uint8_t slot, int8_t sdusers, int8_t allusers bool isUSB = title->isTitleOnUSB; bool isWii = ((highID & 0xFFFFFFF0) == 0x00010000); std::string srcPath; - srcPath = getUnifiedBackupPath(highID, lowID, slot); + srcPath = getDynamicBackupPath(highID, lowID, slot); const std::string path = (isWii ? "storage_slccmpt01:/title" : (isUSB ? (getUSB() + "/usr/save").c_str() : "storage_mlc01:/usr/save")); std::string dstPath = StringUtils::stringFormat("%s/%08x/%08x/%s", path.c_str(), highID, lowID, isWii ? "data" : "user"); createFolderUnlocked(dstPath); From 5d2ace7dd93e38a13fd145ae5e132bf91f97f429 Mon Sep 17 00:00:00 2001 From: w3irDv <170813473+w3irDv@users.noreply.github.com> Date: Sun, 18 Aug 2024 22:47:21 +0200 Subject: [PATCH 08/22] fix - keep user persistentId in lowercase --- src/menu/TitleOptionsState.cpp | 1 + src/savemng.cpp | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/menu/TitleOptionsState.cpp b/src/menu/TitleOptionsState.cpp index d4a0fcd..28ab8ff 100644 --- a/src/menu/TitleOptionsState.cpp +++ b/src/menu/TitleOptionsState.cpp @@ -168,6 +168,7 @@ void TitleOptionsState::render() { switch (task) { case backup: + consolePrintPosAligned(17, 4, 2, LanguageUtils::gettext("\ue000: Backup \ue001: Back")); break; case restore: consolePrintPosAligned(17, 4, 2, LanguageUtils::gettext("\uE002: Chg BackupSet \ue000: Restore \ue001: Back")); diff --git a/src/savemng.cpp b/src/savemng.cpp index 518481d..9687763 100644 --- a/src/savemng.cpp +++ b/src/savemng.cpp @@ -414,7 +414,7 @@ void getAccountsWiiU() { if (nn::act::IsSlotOccupied(i)) { unsigned int persistentID = nn::act::GetPersistentIdEx(i); wiiuacc[accn].pID = persistentID; - sprintf(wiiuacc[accn].persistentID, "%08X", persistentID); + sprintf(wiiuacc[accn].persistentID, "%08x", persistentID); nn::act::GetMiiNameEx((int16_t *) out, i); memset(wiiuacc[accn].miiName, 0, sizeof(wiiuacc[accn].miiName)); for (int j = 0, k = 0; j < 10; j++) { @@ -754,11 +754,11 @@ bool hasAccountSave(Title *title, bool inSD, bool iine, uint32_t user, uint8_t s } else if (user == 0xFFFFFFFF) { sprintf(srcPath, "%s/%08x/%08x/%s", path, highID, lowID, "user"); } else { - sprintf(srcPath, "%s/%08x/%08x/%s/%08X", path, highID, lowID, "user", user); + sprintf(srcPath, "%s/%08x/%08x/%s/%08x", path, highID, lowID, "user", user); } } else { if (!iine) { - sprintf(srcPath, "%s/%08X", getDynamicBackupPath(highID, lowID, slot).c_str(), user); + sprintf(srcPath, "%s/%08x", getDynamicBackupPath(highID, lowID, slot).c_str(), user); } else { if (!getLoadiineGameSaveDir(srcPath, title->productCode, title->longName, title->highID, title->lowID)) { return false; From 109bc8c9d61a92880c1b48a3ac3597665087be3d Mon Sep 17 00:00:00 2001 From: w3irDv <170813473+w3irDv@users.noreply.github.com> Date: Mon, 19 Aug 2024 00:32:34 +0200 Subject: [PATCH 09/22] improve backup/restore/wipe when empty users/common saves --- languages/SChinese.json | 8 ++--- languages/TChinese.json | 8 ++--- languages/english.json | 8 ++--- languages/german.json | 8 ++--- languages/italian.json | 8 ++--- languages/japanese.json | 8 ++--- languages/korean.json | 8 ++--- languages/portuguese.json | 8 ++--- languages/russian.json | 8 ++--- languages/spanish.json | 8 ++--- src/savemng.cpp | 74 +++++++++++++++++++++++++++------------ 11 files changed, 92 insertions(+), 62 deletions(-) diff --git a/languages/SChinese.json b/languages/SChinese.json index 0176107..3eff18b 100644 --- a/languages/SChinese.json +++ b/languages/SChinese.json @@ -72,9 +72,9 @@ "Filesize: %d bytes": "文件大小:%d 字节", "Deleting folder %s": "正在删除 %s 文件夹", "From: \n%s": "从:\n%s", - "Failed to delete folder %s\n%s": "删除文件夹失败 %s\n%s", + "Failed to delete folder %s: %s": "删除文件夹失败 %s: %s", "Deleting file %s": "正在删除文件 %s", - "Failed to delete file %s\n%s": "删除文件失败 %s\n%s", + "Failed to delete file %s: %s": "删除文件失败 %s: %s", "Loadiine game folder not found.": "Loadiine游戏文件夹没有发现。", "Failed to open Loadiine game save directory.": "Loadiine游戏文件夹无法打开。", "Are you sure?": "你确定吗?", @@ -90,9 +90,9 @@ "Restore failed.": "还原保存数据失败。", "Hm, are you REALLY sure?": "嘶,你真的真的要这样做?", "Backup current savedata first?": "要不要先备份现在的保存数据?", - "Failed to delete common folder.\n%s": "删除common文件夹失败。\n%s", + "Failed to delete common folder: %s": "删除common文件夹失败: %s", "Failed to delete savefile.": "删除保存数据失败。", - "Failed to delete user folder.\n%s": "删除user文件夹失败。\n%s", + "Failed to delete user folder: %s": "删除user文件夹失败: %s", "Failed to import savedata from loadiine.": "导入loadiine保存数据失败。", "Failed to export savedata to loadiine.": "导出保存数据到loadiine失败。" } diff --git a/languages/TChinese.json b/languages/TChinese.json index a47bf12..a9a56ef 100644 --- a/languages/TChinese.json +++ b/languages/TChinese.json @@ -72,9 +72,9 @@ "Filesize: %d bytes": "資料大小:%d 個字節", "Deleting folder %s": "刪除資料夾 %s", "From: \n%s": "從:\n%s", - "Failed to delete folder %s\n%s": "無法刪除資料夾 %s\n%s", + "Failed to delete folder %s: %s": "無法刪除資料夾 %s: %s", "Deleting file %s": "刪除資料 %s", - "Failed to delete file %s\n%s": "無法刪除資料 %s\n%s", + "Failed to delete file %s: %s": "無法刪除資料 %s: %s", "Loadiine game folder not found.": "未找到Loadiine遊戲資料夾。", "Failed to open Loadiine game save directory.": "打開Loadiine遊戲保存資料夾失敗。", "Are you sure?": "你確定嗎?", @@ -90,9 +90,9 @@ "Restore failed.": "還原失敗。", "Hm, are you REALLY sure?": "蛤?你真的確定嗎?", "Backup current savedata first?": "先備份當前的保存數據?", - "Failed to delete common folder.\n%s": "無法刪除Common資料夾。\n%s", + "Failed to delete common folder: %s": "無法刪除Common資料夾: %s", "Failed to delete savefile.": "無法刪除保存資料。", - "Failed to delete user folder.\n%s": "無法刪除使用者資料夾。\n%s", + "Failed to delete user folder: %s": "無法刪除使用者資料夾: %s", "Failed to import savedata from loadiine.": "無法從loadiine導入保存數據。", "Failed to export savedata to loadiine.": "無法導出保存數據到Loadiine。" } diff --git a/languages/english.json b/languages/english.json index 13f4653..28a46c6 100644 --- a/languages/english.json +++ b/languages/english.json @@ -72,9 +72,9 @@ "Filesize: %d bytes": "Filesize: %d bytes", "Deleting folder %s": "Deleting folder %s", "From: \n%s": "From: \n%s", - "Failed to delete folder %s\n%s": "Failed to delete folder %s\n%s", + "Failed to delete folder %s: %s": "Failed to delete folder %s: %s", "Deleting file %s": "Deleting file %s", - "Failed to delete file %s\n%s": "Failed to delete file %s\n%s", + "Failed to delete file %s: %s": "Failed to delete file %s: %s", "Loadiine game folder not found.": "Loadiine game folder not found.", "Failed to open Loadiine game save directory.": "Failed to open Loadiine game save directory.", "Are you sure?": "Are you sure?", @@ -90,9 +90,9 @@ "Restore failed.": "Restore failed.", "Hm, are you REALLY sure?": "Hm, are you REALLY sure?", "Backup current savedata first?": "Backup current savedata first?", - "Failed to delete common folder.\n%s": "Failed to delete common folder.\n%s", + "Failed to delete common folder: %s": "Failed to delete common folder: %s", "Failed to delete savefile.": "Failed to delete savefile.", - "Failed to delete user folder.\n%s": "Failed to delete user folder.\n%s", + "Failed to delete user folder: %s": "Failed to delete user folder: %s", "Failed to import savedata from loadiine.": "Failed to import savedata from loadiine.", "Failed to export savedata to loadiine.": "Failed to export savedata to loadiine.", "\ue083 Sort: %s \ue084": "\ue083 Sort: %s \ue084", diff --git a/languages/german.json b/languages/german.json index 7089b6a..35b80c5 100644 --- a/languages/german.json +++ b/languages/german.json @@ -72,9 +72,9 @@ "Filesize: %d bytes": "Dateigröße: %d bytes", "Deleting folder %s": "Lösche Ordner %s", "From: \n%s": "Von: \n%s", - "Failed to delete folder %s\n%s": "Löschen von Ordner %s\n%s fehlgeschlagen", + "Failed to delete folder %s: %s": "Löschen von Ordner %s: %s fehlgeschlagen", "Deleting file %s": "Lösche Datei %s", - "Failed to delete file %s\n%s": "Löschen von Datei %s\n%s fehlgeschlagen", + "Failed to delete file %s: %s": "Löschen von Datei %s: %s fehlgeschlagen", "Loadiine game folder not found.": "Loadiine Spielordner nicht gefunden.", "Failed to open Loadiine game save directory.": "Fehlgeschlagen Loadiine Spielspeicherverzeichnis zu öffnen.", "Are you sure?": "Bist du sicher?", @@ -90,9 +90,9 @@ "Restore failed.": "Wiederherstellen fehlgeschlagen.", "Hm, are you REALLY sure?": "Hm, are you REALLY sure?", "Backup current savedata first?": "Sichere aktuellen Speicherstand zuerst?", - "Failed to delete common folder.\n%s": "Löschen von 'gemeinsamem' Ordner fehlgeschlagen.\n%s", + "Failed to delete common folder: %s": "Löschen von 'gemeinsamem' Ordner fehlgeschlagen: %s", "Failed to delete savefile.": "Löschen von Speicherstand fehlgeschlagen.", - "Failed to delete user folder.\n%s": "Löschen vom Nutzerordner fehlgeschlagen.\n%s", + "Failed to delete user folder: %s": "Löschen vom Nutzerordner fehlgeschlagen: %s", "Failed to import savedata from loadiine.": "Importieren von Loadiine Speicherdaten fehlgeschlagen.", "Failed to export savedata to loadiine.": "Exportieren von Loadiine Speicherdaten fehlgeschlagen.", "German": "Deutsch" diff --git a/languages/italian.json b/languages/italian.json index 3bca5ef..2aac1d9 100644 --- a/languages/italian.json +++ b/languages/italian.json @@ -72,9 +72,9 @@ "Filesize: %d bytes": "Dimensione file: %d byte", "Deleting folder %s": "Eliminazione cartella %s", "From: \n%s": "Da: \n%s", - "Failed to delete folder %s\n%s": "Non è stato possibile eliminare il file %s\n%s", + "Failed to delete folder %s: %s": "Non è stato possibile eliminare il file %s: %s", "Deleting file %s": "Eliminazione cartella %s", - "Failed to delete file %s\n%s": "Non è stato possibile eliminare il file %s\n%s", + "Failed to delete file %s: %s": "Non è stato possibile eliminare il file %s: %s", "Loadiine game folder not found.": "Cartella di gioco Loadiine non trovata.", "Failed to open Loadiine game save directory.": "Apertura della directory di salvataggio del gioco Loadiine non riuscita.", "Are you sure?": "Sei sicuro?", @@ -90,9 +90,9 @@ "Restore failed.": "Ripristino fallito.", "Hm, are you REALLY sure?": "Sei DAVVERO sicuro?", "Backup current savedata first?": "Salvare prima il salvataggio corrente?", - "Failed to delete common folder.\n%s": "Impossibile eliminare la cartella comune.\n%s", + "Failed to delete common folder: %s": "Impossibile eliminare la cartella comune: %s", "Failed to delete savefile.": "Non è stato possibile eliminare il salvataggio.", - "Failed to delete user folder.\n%s": "Impossibile eliminare la cartella.\n%s", + "Failed to delete user folder: %s": "Impossibile eliminare la cartella: %s", "Failed to import savedata from loadiine.": "Impossibile importare salvataggi da loadiine.", "Failed to export savedata to loadiine.": "Impossibile importare salvataggi da loadiine." } \ No newline at end of file diff --git a/languages/japanese.json b/languages/japanese.json index ca157d0..ffcf765 100644 --- a/languages/japanese.json +++ b/languages/japanese.json @@ -72,9 +72,9 @@ "Filesize: %d bytes": "ファイルサイズ: %d バイト", "Deleting folder %s": "フォルダ %s を削除しています", "From: \n%s": "差出人: \n%s", - "Failed to delete folder %s\n%s": "フォルダ %s の削除に失敗しました\n%s", + "Failed to delete folder %s: %s": "フォルダ %s の削除に失敗しました: %s", "Deleting file %s": "ファイル %s を削除しています", - "Failed to delete file %s\n%s": "ファイル %s の削除に失敗しました\n%s", + "Failed to delete file %s: %s": "ファイル %s の削除に失敗しました: %s", "Loadiine game folder not found.": "読み込み中のゲーム フォルダが見つかりません。", "Failed to open Loadiine game save directory.": "Loadiine ゲームの保存ディレクトリを開けませんでした。", "Are you sure?": "本当によろしいですか?", @@ -90,9 +90,9 @@ "Restore failed.": "復元に失敗しました。", "Hm, are you REALLY sure?": "うーん、本当によろしいですか?", "Backup current savedata first?": "最初に現在のセーブデータをバックアップしますか?", - "Failed to delete common folder.\n%s": "共通フォルダの削除に失敗しました.\n%s", + "Failed to delete common folder: %s": "共通フォルダの削除に失敗しました: %s", "Failed to delete savefile.": "保存ファイルの削除に失敗しました。", - "Failed to delete user folder.\n%s": "ユーザー フォルダの削除に失敗しました。\n%s", + "Failed to delete user folder: %s": "ユーザー フォルダの削除に失敗しました: %s", "Failed to import savedata from loadiine.": "loadiine からセーブデータをインポートできませんでした。", "Failed to export savedata to loadiine.": "セーブデータを loadiine にエクスポートできませんでした。" } \ No newline at end of file diff --git a/languages/korean.json b/languages/korean.json index 85364d5..db16479 100644 --- a/languages/korean.json +++ b/languages/korean.json @@ -72,9 +72,9 @@ "Filesize: %d bytes": "파일 크기: %d 바이트", "Deleting folder %s": "%s 폴더 삭제 중", "From: \n%s": "%s\n에서", - "Failed to delete folder %s\n%s": "%s 폴더 삭제 실패\n%s", + "Failed to delete folder %s: %s": "%s 폴더 삭제 실패: %s", "Deleting file %s": "%s 파일 삭제 중", - "Failed to delete file %s\n%s": "%s 파일 삭제 실패\n%s", + "Failed to delete file %s: %s": "%s 파일 삭제 실패: %s", "Loadiine game folder not found.": "Loadiine 게임 폴더를 찾을 수 없습니다.", "Failed to open Loadiine game save directory.": "Loadiine 게임 저장 디렉토리를 열지 못했습니다.", "Are you sure?": "확실하나요?", @@ -90,9 +90,9 @@ "Restore failed.": "복원에 실패했습니다.", "Hm, are you REALLY sure?": "흠, 정말 확신하나요?", "Backup current savedata first?": "현재 저장 데이터를 먼저 백업하겠습니까?", - "Failed to delete common folder.\n%s": "공통 폴더를 삭제하지 못했습니다.\n%s", + "Failed to delete common folder: %s": "공통 폴더를 삭제하지 못했습니다: %s", "Failed to delete savefile.": "저장파일을 삭제하지 못했습니다.", - "Failed to delete user folder.\n%s": "사용자 폴더를 삭제하지 못했습니다.\n%s", + "Failed to delete user folder: %s": "사용자 폴더를 삭제하지 못했습니다: %s", "Failed to import savedata from loadiine.": "loadiine에서 저장 데이터를 가져오지 못했습니다.", "Failed to export savedata to loadiine.": "저장 데이터를 loadiine으로 내보내지 못했습니다." } \ No newline at end of file diff --git a/languages/portuguese.json b/languages/portuguese.json index 468b5c1..60d473c 100644 --- a/languages/portuguese.json +++ b/languages/portuguese.json @@ -73,9 +73,9 @@ "Filesize: %d bytes": "Tamanho: %d bytes", "Deleting folder %s": "Excluindo pasta %s", "From: \n%s": "De:\n%s", - "Failed to delete folder %s\n%s": "Falha ao excluir pasta %s\n%s", + "Failed to delete folder %s: %s": "Falha ao excluir pasta %s: %s", "Deleting file %s": "Excluindo arquivo %s", - "Failed to delete file %s\n%s": "Falha ao excluir arquivo %s\n%s", + "Failed to delete file %s: %s": "Falha ao excluir arquivo %s: %s", "Loadiine game folder not found.": "Pasta do jogo não encontrada (Loadiine).", "Failed to open Loadiine game save directory.": "Falha ao abrir pasta de save (Loadiine).", "Are you sure?": "Tem certeza?", @@ -91,9 +91,9 @@ "Restore failed.": "Falha ao restaurar.", "Hm, are you REALLY sure?": "Hum, você quer REALMENTE fazer isso?", "Backup current savedata first?": "Deseja fazer backup do save?", - "Failed to delete common folder.\n%s": "Falha ao excluir pasta 'common'.\n%s", + "Failed to delete common folder: %s": "Falha ao excluir pasta 'common': %s", "Failed to delete savefile.": "Falha ao excluir save.", - "Failed to delete user folder.\n%s": "Falha ao excluir pasta de usuário.\n%s", + "Failed to delete user folder: %s": "Falha ao excluir pasta de usuário: %s", "Failed to import savedata from loadiine.": "Falha ao importar save (Loadiine).", "Failed to export savedata to loadiine.": "Falha ao exportar save (Loadiine)." } \ No newline at end of file diff --git a/languages/russian.json b/languages/russian.json index 8f4397e..5a5771b 100644 --- a/languages/russian.json +++ b/languages/russian.json @@ -72,9 +72,9 @@ "Filesize: %d bytes": "Размер: %d байт", "Deleting folder %s": "Удаление папки %s", "From: \n%s": "Из %s", - "Failed to delete folder %s\n%s": "Не удалось удалить папку %s\n%s", + "Failed to delete folder %s: %s": "Не удалось удалить папку %s: %s", "Deleting file %s": "Удаление файла %s", - "Failed to delete file %s\n%s": "Не удалось удалить файл %s\n%s", + "Failed to delete file %s: %s": "Не удалось удалить файл %s: %s", "Loadiine game folder not found.": "Папка Loadiine не найдена.", "Failed to open Loadiine game save directory.": "Не удалось открыть каталог сохранения Loadiine.", "Are you sure?": "Вы уверены?", @@ -90,9 +90,9 @@ "Restore failed.": "Ошибка восстановления.", "Hm, are you REALLY sure?": "Вы ТОЧНО уверены?", "Backup current savedata first?": "Сделать сперва бекап сохранения?", - "Failed to delete common folder.\n%s": "Не удалось удалить папку \n%s", + "Failed to delete common folder: %s": "Не удалось удалить папку: %s", "Failed to delete savefile.": "Не удалось удалить сохранение.", - "Failed to delete user folder.\n%s": "Не удалось удалить пользовательскую папку\n%s", + "Failed to delete user folder: %s": "Не удалось удалить пользовательскую папку: %s", "Failed to import savedata from loadiine.": "Не удалось импортировать сохранения из loadiine.", "Failed to export savedata to loadiine.": "Не удалось экспортировать сохранения из loadiine." } \ No newline at end of file diff --git a/languages/spanish.json b/languages/spanish.json index eb91c2b..c0a553e 100644 --- a/languages/spanish.json +++ b/languages/spanish.json @@ -72,9 +72,9 @@ "Filesize: %d bytes": "Tamaño: %d bytes", "Deleting folder %s": "Eliminando carpeta %s", "From: \n%s": "Desde:\n%s", - "Failed to delete folder %s\n%s": "Error al eliminar la carpeta %s\n%s", + "Failed to delete folder %s: %s": "Error al eliminar la carpeta %s: %s", "Deleting file %s": "Eliminando archivo %s", - "Failed to delete file %s\n%s": "Error al eliminar el archivo %s\n%s", + "Failed to delete file %s: %s": "Error al eliminar el archivo %s: %s", "Loadiine game folder not found.": "Carpeta del juego de Loadiine no encontrada.", "Failed to open Loadiine game save directory.": "Error al abrir la carpeta de saves del juego de Loadiine.", "Are you sure?": "¿Estás seguro?", @@ -90,9 +90,9 @@ "Restore failed.": "Error al restaurar.", "Hm, are you REALLY sure?": "¿Hm, estás COMPLETAMENTE seguro?", "Backup current savedata first?": "¿Hacer copia antes del save?", - "Failed to delete common folder.\n%s": "Error al eliminar la carpeta common.\n%s", + "Failed to delete common folder: %s": "Error al eliminar la carpeta common: %s", "Failed to delete savefile.": "Error al eliminar el save.", - "Failed to delete user folder.\n%s": "Error al eliminar la carpeta user.\n%s", + "Failed to delete user folder: %s": "Error al eliminar la carpeta user: %s", "Failed to import savedata from loadiine.": "Error al importar el save de loadiine.", "Failed to export savedata to loadiine.": "Error al exportar el save a loadiine." } \ No newline at end of file diff --git a/src/savemng.cpp b/src/savemng.cpp index 9687763..42a34ac 100644 --- a/src/savemng.cpp +++ b/src/savemng.cpp @@ -399,7 +399,7 @@ void promptError(const char *message, ...) { free(tmp); DrawUtils::endDraw(); va_end(va); - sleep(2); + sleep(4); } void getAccountsWiiU() { @@ -635,11 +635,11 @@ static bool removeDir(const std::string &pPath) { consolePrintPos(-2, 0, LanguageUtils::gettext("Deleting folder %s"), data->d_name); consolePrintPosMultiline(-2, 2, LanguageUtils::gettext("From: \n%s"), origPath.c_str()); - if (unlink(origPath.c_str()) == -1) promptError(LanguageUtils::gettext("Failed to delete folder %s\n%s"), origPath.c_str(), strerror(errno)); + if (unlink(origPath.c_str()) == -1) promptError(LanguageUtils::gettext("Failed to delete folder %s: %s"), origPath.c_str(), strerror(errno)); } else { consolePrintPos(-2, 0, LanguageUtils::gettext("Deleting file %s"), data->d_name); consolePrintPosMultiline(-2, 2, LanguageUtils::gettext("From: \n%s"), tempPath.c_str()); - if (unlink(tempPath.c_str()) == -1) promptError(LanguageUtils::gettext("Failed to delete file %s\n%s"), tempPath.c_str(), strerror(errno)); + if (unlink(tempPath.c_str()) == -1) promptError(LanguageUtils::gettext("Failed to delete file %s: %s"), tempPath.c_str(), strerror(errno)); } DrawUtils::endDraw(); @@ -857,23 +857,32 @@ void copySavedata(Title *title, Title *titleb, int8_t allusers, int8_t allusers_ std::string srcPath = StringUtils::stringFormat("%s/%08x/%08x/%s", path.c_str(), highID, lowID, "user"); std::string dstPath = StringUtils::stringFormat("%s/%08x/%08x/%s", pathb.c_str(), highIDb, lowIDb, "user"); createFolderUnlocked(dstPath); + bool commonSaved = false; if (allusers > -1) { if (common) { FSAMakeQuota(handle, newlibtoFSA(dstPath + "/common").c_str(), 0x666, titleb->accountSaveSize); - if (!copyDir(srcPath + "/common", dstPath + "/common")) + if (copyDir(srcPath + "/common", dstPath + "/common")) + commonSaved = true; + else promptError(LanguageUtils::gettext("Common save not found.")); } srcPath.append(StringUtils::stringFormat("/%s", wiiuacc[allusers].persistentID)); dstPath.append(StringUtils::stringFormat("/%s", wiiuacc[allusers_d].persistentID)); - FSAMakeQuota(handle, newlibtoFSA(dstPath).c_str(), 0x666, titleb->accountSaveSize); + if (checkEntry(srcPath.c_str()) == 2) { + FSAMakeQuota(handle, newlibtoFSA(dstPath).c_str(), 0x666, titleb->accountSaveSize); + if (!copyDir(srcPath, dstPath)) + promptError(LanguageUtils::gettext("Copy failed.")); + } + else + if (!commonSaved) + promptError(LanguageUtils::gettext("No save found for this user.")); } else { FSAMakeQuotaFromDir(srcPath.c_str(), dstPath.c_str(), titleb->accountSaveSize); + if (!copyDir(srcPath, dstPath)) + promptError(LanguageUtils::gettext("Copy failed.")); } - if (!copyDir(srcPath, dstPath)) - promptError(LanguageUtils::gettext("Copy failed.")); - if (!titleb->saveInit) { std::string userPath = StringUtils::stringFormat("%s/%08x/%08x/user", pathb.c_str(), highIDb, lowIDb); @@ -974,17 +983,22 @@ void backupSavedata(Title *title, uint8_t slot, int8_t allusers, bool common) { std::string dstPath; dstPath = getDynamicBackupPath(highID, lowID, slot); createFolder(dstPath.c_str()); - + bool commonSaved = false; if ((allusers > -1) && !isWii) { if (common) { - if (!copyDir(srcPath+"/common", dstPath+"/common")) + if (copyDir(srcPath+"/common", dstPath+"/common")) + commonSaved = true; + else promptError(LanguageUtils::gettext("Common save not found.")); } srcPath.append(StringUtils::stringFormat("/%s", wiiuacc[allusers].persistentID)); dstPath.append(StringUtils::stringFormat("/%s", wiiuacc[allusers].persistentID)); if (checkEntry(srcPath.c_str()) == 0) { - promptError(LanguageUtils::gettext("No save found for this user.")); + if (commonSaved) + writeSavedataDate(highID,lowID,slot); + else + promptError(LanguageUtils::gettext("No save found for this user.")); return; } } @@ -1015,21 +1029,34 @@ void restoreSavedata(Title *title, uint8_t slot, int8_t sdusers, int8_t allusers std::string dstPath = StringUtils::stringFormat("%s/%08x/%08x/%s", path.c_str(), highID, lowID, isWii ? "data" : "user"); createFolderUnlocked(dstPath); + bool commonSaved = false; if ((sdusers > -1) && !isWii) { if (common) { FSAMakeQuota(handle, newlibtoFSA(dstPath + "/common").c_str(), 0x666, title->accountSaveSize); - if (!copyDir(srcPath + "/common", dstPath + "/common")) + if (copyDir(srcPath + "/common", dstPath + "/common")) + commonSaved = true; + else promptError(LanguageUtils::gettext("Common save not found.")); } srcPath.append(StringUtils::stringFormat("/%s", sdacc[sdusers].persistentID)); dstPath.append(StringUtils::stringFormat("/%s", wiiuacc[allusers].persistentID)); - FSAMakeQuota(handle, newlibtoFSA(dstPath).c_str(), 0x666, title->accountSaveSize); - } else { + if (checkEntry(srcPath.c_str()) == 2) { + FSAMakeQuota(handle, newlibtoFSA(dstPath).c_str(), 0x666, title->accountSaveSize); + if (!copyDir(srcPath, dstPath)) + promptError(LanguageUtils::gettext("Restore failed.")); + } + else + if (!commonSaved) + promptError(LanguageUtils::gettext("No save found for this user.")); + } + else + { FSAMakeQuotaFromDir(srcPath.c_str(), dstPath.c_str(), title->accountSaveSize); + if (!copyDir(srcPath, dstPath)) + promptError(LanguageUtils::gettext("Restore failed.")); } - if (!copyDir(srcPath, dstPath)) - promptError(LanguageUtils::gettext("Restore failed.")); + if (!title->saveInit && !isWii) { @@ -1092,17 +1119,20 @@ void wipeSavedata(Title *title, int8_t allusers, bool common) { if (!removeDir(origPath)) promptError(LanguageUtils::gettext("Common save not found.")); if (unlink(origPath.c_str()) == -1) - promptError(LanguageUtils::gettext("Failed to delete common folder.\n%s"), strerror(errno)); + promptError(LanguageUtils::gettext("Failed to delete common folder: %s"), strerror(errno)); } srcPath += "/" + std::string(wiiuacc[allusers].persistentID); } - if (!removeDir(srcPath)) - promptError(LanguageUtils::gettext("Failed to delete savefile.")); - if ((allusers > -1) && !isWii) { - if (unlink(srcPath.c_str()) == -1) - promptError(LanguageUtils::gettext("Failed to delete user folder.\n%s"), strerror(errno)); + if (checkEntry(srcPath.c_str()) == 2) { + if (!removeDir(srcPath)) + promptError(LanguageUtils::gettext("Failed to delete savefile.")); + if ((allusers > -1) && !isWii) { + if (unlink(srcPath.c_str()) == -1) + promptError(LanguageUtils::gettext("Failed to delete user folder: %s"), strerror(errno)); + } } + std::string volPath; if (srcPath.find("_usb01") != std::string::npos) { volPath = "/vol/storage_usb01"; From ac31429831f75b5f200c0b234f28ba693872d90a Mon Sep 17 00:00:00 2001 From: w3irDv <170813473+w3irDv@users.noreply.github.com> Date: Mon, 19 Aug 2024 22:46:13 +0200 Subject: [PATCH 10/22] add colors in backupsetlist --- include/utils/Colors.h | 2 +- src/menu/BackupSetListState.cpp | 10 +++++++--- src/menu/TitleOptionsState.cpp | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/include/utils/Colors.h b/include/utils/Colors.h index 36c1ae6..8279c86 100644 --- a/include/utils/Colors.h +++ b/include/utils/Colors.h @@ -4,6 +4,6 @@ #define COLOR_BLACK Color(0, 0, 0, 255) #define COLOR_BACKGROUND Color(0x00006F00) #define COLOR_TEXT COLOR_WHITE -#define COLOR_LIST_CONTRAST Color(0xFF9000FF) +#define COLOR_LIST_HIGH Color(0x40D050FF) #define COLOR_LIST Color(0x00FF00FF) #define COLOR_INFO Color(0x88CC88FF) \ No newline at end of file diff --git a/src/menu/BackupSetListState.cpp b/src/menu/BackupSetListState.cpp index 2284f59..2eeec5d 100644 --- a/src/menu/BackupSetListState.cpp +++ b/src/menu/BackupSetListState.cpp @@ -28,15 +28,19 @@ void BackupSetListState::resetCursorPosition() { // after batch Backup void BackupSetListState::render() { + std::string backupSetItem; consolePrintPos(44, 0, LanguageUtils::gettext("\ue083 Sort: %s \ue084"), this->sortAscending ? "\u2191" : "\u2193"); for (int i = 0; i < MAX_ROWS_SHOW; i++) { if (i + scroll < 0 || i + scroll >= BackupSetList::currentBackupSetList->entries) break; + backupSetItem = BackupSetList::currentBackupSetList->at(i + scroll); DrawUtils::setFontColor(COLOR_LIST); - if (BackupSetList::currentBackupSetList->at(i + scroll) == BackupSetList::CURRENT_BS) - DrawUtils::setFontColor(COLOR_LIST_CONTRAST); - consolePrintPos(M_OFF, i + 2, " %s", BackupSetList::currentBackupSetList->at(i + scroll).c_str()); + if ( backupSetItem == BackupSetList::CURRENT_BS) + DrawUtils::setFontColor(COLOR_LIST_HIGH); + if ( backupSetItem == BackupSetList::getBackupSetEntry()) + DrawUtils::setFontColor(COLOR_INFO); + consolePrintPos(M_OFF, i + 2, " %s", backupSetItem.c_str()); } DrawUtils::setFontColor(COLOR_TEXT); consolePrintPos(-1, 2 + cursorPos, "\u2192"); diff --git a/src/menu/TitleOptionsState.cpp b/src/menu/TitleOptionsState.cpp index 28ab8ff..a843fec 100644 --- a/src/menu/TitleOptionsState.cpp +++ b/src/menu/TitleOptionsState.cpp @@ -171,7 +171,7 @@ void TitleOptionsState::render() { consolePrintPosAligned(17, 4, 2, LanguageUtils::gettext("\ue000: Backup \ue001: Back")); break; case restore: - consolePrintPosAligned(17, 4, 2, LanguageUtils::gettext("\uE002: Chg BackupSet \ue000: Restore \ue001: Back")); + consolePrintPosAligned(17, 4, 2, LanguageUtils::gettext("\uE002: Chg BackupSet \ue000: Restore \ue001: Back")); break; case wipe: consolePrintPosAligned(17, 4, 2, LanguageUtils::gettext("\ue000: Wipe \ue001: Back")); From c7db21c8b4aa0bbab2a20ba9b31516d8414e2cef Mon Sep 17 00:00:00 2001 From: w3irDv <170813473+w3irDv@users.noreply.github.com> Date: Mon, 19 Aug 2024 22:48:13 +0200 Subject: [PATCH 11/22] CURRENT_BS -> ROOT_BS --- include/BackupSetList.h | 2 +- src/BackupSetList.cpp | 8 ++++---- src/menu/BackupSetListState.cpp | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/BackupSetList.h b/include/BackupSetList.h index 01df773..d0f27e0 100644 --- a/include/BackupSetList.h +++ b/include/BackupSetList.h @@ -16,7 +16,7 @@ class BackupSetList { std::string at(int i); void add(std::string backupSet); - static const std::string CURRENT_BS; + static const std::string ROOT_BS; static std::string getBackupSetSubPath() { return backupSetSubPath; } static std::string getBackupSetEntry() { return backupSetEntry; } static void setBackupSetEntry(int i); diff --git a/src/BackupSetList.cpp b/src/BackupSetList.cpp index c5e6928..cc4389e 100644 --- a/src/BackupSetList.cpp +++ b/src/BackupSetList.cpp @@ -8,9 +8,9 @@ #include bool BackupSetList::sortAscending = false; -const std::string BackupSetList::CURRENT_BS = ">> Current <<"; +const std::string BackupSetList::ROOT_BS = ">> Root <<"; std::string BackupSetList::backupSetSubPath = "/";; -std::string BackupSetList::backupSetEntry = CURRENT_BS; +std::string BackupSetList::backupSetEntry = ROOT_BS; std::unique_ptr BackupSetList::currentBackupSetList = std::make_unique(); @@ -21,7 +21,7 @@ BackupSetList::BackupSetList(const char *backupSetListRoot) this->backupSetListRoot = backupSetListRoot; - backupSets.push_back(CURRENT_BS); + backupSets.push_back(ROOT_BS); DIR *dir = opendir(backupSetListRoot); if (dir != nullptr) { @@ -75,7 +75,7 @@ void BackupSetList::setBackupSetEntry(int i) { } void BackupSetList::setBackupSetSubPath() { - if (backupSetEntry == CURRENT_BS) + if (backupSetEntry == ROOT_BS) backupSetSubPath = "/"; else backupSetSubPath = "/batch/"+backupSetEntry+"/"; diff --git a/src/menu/BackupSetListState.cpp b/src/menu/BackupSetListState.cpp index 2eeec5d..eaf2b0d 100644 --- a/src/menu/BackupSetListState.cpp +++ b/src/menu/BackupSetListState.cpp @@ -36,7 +36,7 @@ void BackupSetListState::render() { break; backupSetItem = BackupSetList::currentBackupSetList->at(i + scroll); DrawUtils::setFontColor(COLOR_LIST); - if ( backupSetItem == BackupSetList::CURRENT_BS) + if ( backupSetItem == BackupSetList::ROOT_BS) DrawUtils::setFontColor(COLOR_LIST_HIGH); if ( backupSetItem == BackupSetList::getBackupSetEntry()) DrawUtils::setFontColor(COLOR_INFO); From 04bffc1372c469c6e5e16827292187a82be1eafe Mon Sep 17 00:00:00 2001 From: w3irDv <170813473+w3irDv@users.noreply.github.com> Date: Wed, 21 Aug 2024 16:36:31 +0200 Subject: [PATCH 12/22] date > metadata : source (nand/usb/wiiu serialid ) from where the savedata was backed up is shown --- include/{date.h => metadata.h} | 9 +++++---- include/savemng.h | 4 ++-- languages/english.json | 3 ++- src/main.cpp | 17 +++++++++++++++++ src/menu/TitleOptionsState.cpp | 14 +++++++------- src/{date.cpp => metadata.cpp} | 29 ++++++++++++++++++++++------- src/savemng.cpp | 24 ++++++++++++------------ src/utils/StateUtils.cpp | 1 - 8 files changed, 67 insertions(+), 34 deletions(-) rename include/{date.h => metadata.h} (74%) rename src/{date.cpp => metadata.cpp} (50%) diff --git a/include/date.h b/include/metadata.h similarity index 74% rename from include/date.h rename to include/metadata.h index be9ea3a..20ed622 100644 --- a/include/date.h +++ b/include/metadata.h @@ -4,22 +4,23 @@ #include #include -class Date { +class Metadata { public: - Date(uint32_t high, uint32_t low, uint8_t s) : highID(high), + Metadata(uint32_t high, uint32_t low, uint8_t s) : highID(high), lowID(low), slot(s), path (getDynamicBackupPath(highID, lowID, slot).append("/savemiiMeta.json")) { } - Date(uint32_t high, uint32_t low, uint8_t s, std::string datetime) : highID(high), + Metadata(uint32_t high, uint32_t low, uint8_t s, std::string datetime) : highID(high), lowID(low), slot(s), path (getBatchBackupPath(highID, lowID, slot, datetime).append("/savemiiMeta.json")) { } std::string get(); - bool set(const std::string &date); + bool set(const std::string &date,bool isUSB); + static std::string serialId; private: uint32_t highID; diff --git a/include/savemng.h b/include/savemng.h index b711e47..682ea74 100644 --- a/include/savemng.h +++ b/include/savemng.h @@ -120,8 +120,8 @@ bool hasCommonSave(Title *title, bool inSD, bool iine, uint8_t slot, int version void copySavedata(Title *title, Title *titled, int8_t allusers, int8_t allusers_d, bool common) __attribute__((hot)); std::string getNowDateForFolder() __attribute__((hot)); std::string getNowDate() __attribute__((hot)); -void writeSavedataDate(uint32_t highID,uint32_t lowID,uint8_t slot) __attribute__((hot)); -void writeSavedataDate(uint32_t highID,uint32_t lowID,uint8_t slot, const std::string &batchDatetime) __attribute__((hot)); +void writeMetadata(uint32_t highID,uint32_t lowID,uint8_t slot,bool isUSB) __attribute__((hot)); +void writeMetadata(uint32_t highID,uint32_t lowID,uint8_t slot,bool isUSB,const std::string &batchDatetime) __attribute__((hot)); void backupAllSave(Title *titles, int count, const std::string &batchDatetime) __attribute__((hot)); void backupSavedata(Title *title, uint8_t slot, int8_t allusers, bool common) __attribute__((hot)); void restoreSavedata(Title *title, uint8_t slot, int8_t sdusers, int8_t allusers, bool common) __attribute__((hot)); diff --git a/languages/english.json b/languages/english.json index 28a46c6..ae1a635 100644 --- a/languages/english.json +++ b/languages/english.json @@ -101,5 +101,6 @@ "WiiU NAND Savedata >> slot 1": "WiiU NAND Savedata >> slot 1", "vWii Savedata >> slot 0": "vWii Savedata >> slot 0" "\uE002: Chg BackupSet \ue000: Restore \ue001: Back": "\uE002: Chg BackupSet \ue000: Restore \ue001: Back", - "BackupSet: %s": "BackupSet: %s" + "BackupSet: %s": "BackupSet: %s", + ", from ": ", from" } \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 161cc08..5104dc6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -39,6 +40,20 @@ static void disclaimer() { LanguageUtils::gettext("Everything you do with this software is your own responsibility")); } +static void getWiiUSerialId() { + // from WiiUIdent + WUT_ALIGNAS(0x40) MCPSysProdSettings sysProd{}; + int32_t mcpHandle = MCP_Open(); + if ( mcpHandle >= 0 ) { + MCP_GetSysProdSettings(mcpHandle,&sysProd); + MCP_Close(mcpHandle); + } + + Metadata::serialId = sysProd.code_id; + Metadata::serialId += sysProd.serial_id; + +} + static Title *loadWiiUTitles(int run) { static char *tList; static uint32_t receivedCount; @@ -409,6 +424,8 @@ int main() { KPADInit(); WPADEnableURCC(1); + getWiiUSerialId(); + loadWiiUTitles(0); int res = romfsInit(); diff --git a/src/menu/TitleOptionsState.cpp b/src/menu/TitleOptionsState.cpp index a843fec..95cd185 100644 --- a/src/menu/TitleOptionsState.cpp +++ b/src/menu/TitleOptionsState.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include #include #include @@ -100,10 +100,10 @@ void TitleOptionsState::render() { } if ((task == backup) || (task == restore)) if (!isSlotEmpty(this->title.highID, this->title.lowID, slot)) { - Date *dateObj = new Date(this->title.highID, this->title.lowID, slot); + Metadata *metadataObj = new Metadata(this->title.highID, this->title.lowID, slot); consolePrintPos(M_OFF, 15, LanguageUtils::gettext("Date: %s"), - dateObj->get().c_str()); - delete dateObj; + metadataObj->get().c_str()); + delete metadataObj; } if (task == copytoOtherDevice) { @@ -159,10 +159,10 @@ void TitleOptionsState::render() { if (this->title.iconBuf != nullptr) DrawUtils::drawRGB5A3(650, 100, 1, this->title.iconBuf); if (!isSlotEmpty(this->title.highID, this->title.lowID, slot)) { - Date *dateObj = new Date(this->title.highID, this->title.lowID, slot); + Metadata *metadataObj = new Metadata(this->title.highID, this->title.lowID, slot); consolePrintPos(M_OFF, 15, LanguageUtils::gettext("Date: %s"), - dateObj->get().c_str()); - delete dateObj; + metadataObj->get().c_str()); + delete metadataObj; } } diff --git a/src/date.cpp b/src/metadata.cpp similarity index 50% rename from src/date.cpp rename to src/metadata.cpp index ea369ea..541b151 100644 --- a/src/date.cpp +++ b/src/metadata.cpp @@ -1,8 +1,11 @@ -#include +#include +#include #define FS_ALIGN(x) ((x + 0x3F) & ~(0x3F)) -std::string Date::get() { +std::string Metadata::serialId = ""; + +std::string Metadata::get() { if (checkEntry(path.c_str()) != 0) { FILE *f = fopen(path.c_str(), "rb"); fseek(f, 0, SEEK_END); @@ -19,24 +22,36 @@ std::string Date::get() { json_t *root = json_loads(data, 0, &error); if (root) { - std::string buf; - buf.assign(json_string_value(json_object_get(root, "Date"))); + std::string metadata; + const char* date_ = json_string_value(json_object_get(root, "Date")); + if (date_ != nullptr) { + metadata.assign(json_string_value(json_object_get(root, "Date"))); + } + const char* storage_ = json_string_value(json_object_get(root, "storage")); + if (storage_ != nullptr) { + metadata.append(LanguageUtils::gettext(", from ")).append(storage_); + } + const char* serialId_ = json_string_value(json_object_get(root, "serialId")); + if (serialId_ != nullptr) { + metadata.append(" | ").append(serialId_); + } json_decref(root); - free(data); - return buf; + return metadata; } return ""; } return ""; } -bool Date::set(const std::string &date) { +bool Metadata::set(const std::string &date, bool isUSB) { json_t *config = json_object(); if (config == nullptr) return false; json_object_set_new(config, "Date", json_string(date.c_str())); + json_object_set_new(config, "serialId", json_string(serialId.c_str())); + json_object_set_new(config, "storage", json_string(isUSB ? "USB" : "NAND")); char *configString = json_dumps(config, 0); if (configString == nullptr) diff --git a/src/savemng.cpp b/src/savemng.cpp index 42a34ac..8a45ad2 100644 --- a/src/savemng.cpp +++ b/src/savemng.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include #include #include @@ -935,16 +935,16 @@ std::string getNowDateForFolder() { now.tm_hour, now.tm_min, now.tm_sec); } -void writeSavedataDate(uint32_t highID,uint32_t lowID,uint8_t slot) { - Date *dateObj = new Date(highID, lowID, slot); - dateObj->set(getNowDate()); - delete dateObj; +void writeMetadata(uint32_t highID,uint32_t lowID,uint8_t slot,bool isUSB) { + Metadata *metadataObj = new Metadata(highID, lowID, slot); + metadataObj->set(getNowDate(),isUSB); + delete metadataObj; } -void writeSavedataDate(uint32_t highID,uint32_t lowID,uint8_t slot, const std::string &batchDatetime) { - Date *dateObj = new Date(highID, lowID, slot, batchDatetime); - dateObj->set(getNowDate()); - delete dateObj; +void writeMetadata(uint32_t highID,uint32_t lowID,uint8_t slot,bool isUSB, const std::string &batchDatetime) { + Metadata *metadataObj = new Metadata(highID, lowID, slot, batchDatetime); + metadataObj->set(getNowDate(),isUSB); + delete metadataObj; } void backupAllSave(Title *titles, int count, const std::string &batchDatetime) { @@ -964,7 +964,7 @@ void backupAllSave(Title *titles, int count, const std::string &batchDatetime) { if (!copyDir(srcPath, dstPath)) promptError(LanguageUtils::gettext("Backup failed.")); else - writeSavedataDate(highID,lowID,slot, batchDatetime); + writeMetadata(highID,lowID,slot,isUSB,batchDatetime); } } @@ -996,7 +996,7 @@ void backupSavedata(Title *title, uint8_t slot, int8_t allusers, bool common) { if (checkEntry(srcPath.c_str()) == 0) { if (commonSaved) - writeSavedataDate(highID,lowID,slot); + writeMetadata(highID,lowID,slot,isUSB); else promptError(LanguageUtils::gettext("No save found for this user.")); return; @@ -1005,7 +1005,7 @@ void backupSavedata(Title *title, uint8_t slot, int8_t allusers, bool common) { if (!copyDir(srcPath, dstPath)) promptError(LanguageUtils::gettext("Backup failed. DO NOT restore from this slot.")); else - writeSavedataDate(highID,lowID,slot); + writeMetadata(highID,lowID,slot,isUSB); } diff --git a/src/utils/StateUtils.cpp b/src/utils/StateUtils.cpp index da6b270..32c2eb4 100644 --- a/src/utils/StateUtils.cpp +++ b/src/utils/StateUtils.cpp @@ -22,7 +22,6 @@ void State::init() { WHBProcInit(); } - uint32_t State::ConsoleProcCallbackAcquired(void *context) { From c86ccfd43054c76293b3db6c6ed5447ed392485f Mon Sep 17 00:00:00 2001 From: w3irDv <170813473+w3irDv@users.noreply.github.com> Date: Wed, 21 Aug 2024 16:57:54 +0200 Subject: [PATCH 13/22] bump version to 1.6.3 --- include/version.h | 2 +- src/metadata.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/version.h b/include/version.h index c784e46..18c9efd 100644 --- a/include/version.h +++ b/include/version.h @@ -2,4 +2,4 @@ #define VERSION_MAJOR 1 #define VERSION_MINOR 6 -#define VERSION_MICRO 2 +#define VERSION_MICRO 3 diff --git a/src/metadata.cpp b/src/metadata.cpp index 541b151..ac5ea4c 100644 --- a/src/metadata.cpp +++ b/src/metadata.cpp @@ -3,7 +3,7 @@ #define FS_ALIGN(x) ((x + 0x3F) & ~(0x3F)) -std::string Metadata::serialId = ""; +std::string Metadata::serialId {}; std::string Metadata::get() { if (checkEntry(path.c_str()) != 0) { @@ -22,10 +22,10 @@ std::string Metadata::get() { json_t *root = json_loads(data, 0, &error); if (root) { - std::string metadata; + std::string metadata {}; const char* date_ = json_string_value(json_object_get(root, "Date")); if (date_ != nullptr) { - metadata.assign(json_string_value(json_object_get(root, "Date"))); + metadata.append(json_string_value(json_object_get(root, "Date"))); } const char* storage_ = json_string_value(json_object_get(root, "storage")); if (storage_ != nullptr) { From ff7042b8de33ba2eb8fe26fb9f6d6ac4d56204cc Mon Sep 17 00:00:00 2001 From: w3irDv <170813473+w3irDv@users.noreply.github.com> Date: Wed, 21 Aug 2024 22:30:57 +0200 Subject: [PATCH 14/22] safer way to obtain serialId --- src/main.cpp | 12 +++++------- src/metadata.cpp | 2 +- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 5104dc6..e5666ff 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -41,17 +41,15 @@ static void disclaimer() { } static void getWiiUSerialId() { - // from WiiUIdent + // from WiiUCrashLogDumper WUT_ALIGNAS(0x40) MCPSysProdSettings sysProd{}; int32_t mcpHandle = MCP_Open(); if ( mcpHandle >= 0 ) { - MCP_GetSysProdSettings(mcpHandle,&sysProd); + if (MCP_GetSysProdSettings(mcpHandle,&sysProd)==0) { + Metadata::serialId = std::string(sysProd.code_id) + sysProd.serial_id; + } MCP_Close(mcpHandle); - } - - Metadata::serialId = sysProd.code_id; - Metadata::serialId += sysProd.serial_id; - + } } static Title *loadWiiUTitles(int run) { diff --git a/src/metadata.cpp b/src/metadata.cpp index ac5ea4c..f487823 100644 --- a/src/metadata.cpp +++ b/src/metadata.cpp @@ -3,7 +3,7 @@ #define FS_ALIGN(x) ((x + 0x3F) & ~(0x3F)) -std::string Metadata::serialId {}; +std::string Metadata::serialId { "_WIIU_" }; std::string Metadata::get() { if (checkEntry(path.c_str()) != 0) { From 75e74c62ac0d8db028b62a1930131b23d2b98d57 Mon Sep 17 00:00:00 2001 From: w3irDv <170813473+w3irDv@users.noreply.github.com> Date: Thu, 22 Aug 2024 17:00:25 +0200 Subject: [PATCH 15/22] updated some translations --- languages/english.json | 7 +++---- languages/german.json | 13 ++++++++++--- languages/italian.json | 11 +++++++++-- languages/portuguese.json | 11 +++++++++-- languages/spanish.json | 10 +++++++++- src/menu/TitleOptionsState.cpp | 2 +- 6 files changed, 41 insertions(+), 13 deletions(-) diff --git a/languages/english.json b/languages/english.json index ae1a635..79b492e 100644 --- a/languages/english.json +++ b/languages/english.json @@ -48,7 +48,6 @@ "yes": "yes", "no ": "no ", "No 'common' save found.": "No 'common' save found.", - "\ue000: Restore \ue001: Back": "\ue000: Restore \ue001: Back", "\ue000: Wipe \ue001: Back": "\ue000: Wipe \ue001: Back", "\ue000: Import \ue001: Back": "\ue000: Import \ue001: Back", "\ue000: Export \ue001: Back": "\ue000: Export \ue001: Back", @@ -97,10 +96,10 @@ "Failed to export savedata to loadiine.": "Failed to export savedata to loadiine.", "\ue083 Sort: %s \ue084": "\ue083 Sort: %s \ue084", "\ue000: Select BackupSet \ue001: Back": "\ue000: Select BackupSet \ue001: Back", + "\ue002: Change BackupSet \ue000: Restore \ue001: Back": "\ue002: Change BackupSet \ue000: Restore \ue001: Back", "WiiU USB Savedata >> slot 0": "WiiU USB Savedata >> slot 0", "WiiU NAND Savedata >> slot 1": "WiiU NAND Savedata >> slot 1", - "vWii Savedata >> slot 0": "vWii Savedata >> slot 0" - "\uE002: Chg BackupSet \ue000: Restore \ue001: Back": "\uE002: Chg BackupSet \ue000: Restore \ue001: Back", + "vWii Savedata >> slot 0": "vWii Savedata >> slot 0", "BackupSet: %s": "BackupSet: %s", - ", from ": ", from" + ", from ": ", from " } \ No newline at end of file diff --git a/languages/german.json b/languages/german.json index 35b80c5..1107c7e 100644 --- a/languages/german.json +++ b/languages/german.json @@ -47,8 +47,7 @@ "Include 'common' save?": "'Gemeinsame' Speicherung einschließen?", "yes": "Ja", "no ": "Nein ", - "No 'common' save found.": "Keine 'gemeinsame' Speicherung gefunden.", - "\ue000: Restore \ue001: Back": "\ue000: Wiederherstellen \ue001: Zurück", + "No 'common' save found.": "Keine 'gemeinsame' Speicherung gefunden.",, "\ue000: Wipe \ue001: Back": "\ue000: Lösche \ue001: Zurück", "\ue000: Import \ue001: Back": "\ue000: Importieren \ue001: Zurück", "\ue000: Export \ue001: Back": "\ue000: Exportieren \ue001: Zurück", @@ -95,5 +94,13 @@ "Failed to delete user folder: %s": "Löschen vom Nutzerordner fehlgeschlagen: %s", "Failed to import savedata from loadiine.": "Importieren von Loadiine Speicherdaten fehlgeschlagen.", "Failed to export savedata to loadiine.": "Exportieren von Loadiine Speicherdaten fehlgeschlagen.", - "German": "Deutsch" + "German": "Deutsch", + "\ue083 Sort: %s \ue084": "\ue083 Sortieren: %s \ue084", + "\ue000: Select BackupSet \ue001: Back": "\ue000: Wählen Sie BackupSet \ue001: Zurück", + "\ue002: Change BackupSet \ue000: Restore \ue001: Back": "\ue002: BackupSet ändern \ue000: Wiederherstellen \ue001: Zurück", + "WiiU USB Savedata >> slot 0": "WiiU USB Savedata >> slot 0", + "WiiU NAND Savedata >> slot 1": "WiiU NAND Savedata >> slot 1", + "vWii Savedata >> slot 0": "vWii Savedata >> slot 0", + "BackupSet: %s": "BackupSet: %s", + ", from ": ", aus " } diff --git a/languages/italian.json b/languages/italian.json index 2aac1d9..5b388a7 100644 --- a/languages/italian.json +++ b/languages/italian.json @@ -48,7 +48,6 @@ "yes": "sì", "no ": "no ", "No 'common' save found.": "Nessun salvataggio 'comune' trovato.", - "\ue000: Restore \ue001: Back": "\ue000: Ripristina \ue001: Indietro", "\ue000: Wipe \ue001: Back": "\ue000: Pulire \ue001: Indietro", "\ue000: Import \ue001: Back": "\ue000: Importa \ue001: Indietro", "\ue000: Export \ue001: Back": "\ue000: Esporta \ue001: Indietro", @@ -94,5 +93,13 @@ "Failed to delete savefile.": "Non è stato possibile eliminare il salvataggio.", "Failed to delete user folder: %s": "Impossibile eliminare la cartella: %s", "Failed to import savedata from loadiine.": "Impossibile importare salvataggi da loadiine.", - "Failed to export savedata to loadiine.": "Impossibile importare salvataggi da loadiine." + "Failed to export savedata to loadiine.": "Impossibile importare salvataggi da loadiine.", + "\ue083 Sort: %s \ue084": "\ue083 Ordinare: %s \ue084", + "\ue000: Select BackupSet \ue001: Back": "\ue000: Seleziona BackupSet \ue001: Indietro", + "\ue002: Change BackupSet \ue000: Restore \ue001: Back": "\ue002: Modificare BackupSet \ue000: Ripristina \ue001: Indietro", + "WiiU USB Savedata >> slot 0": "WiiU USB Savedata >> slot 0", + "WiiU NAND Savedata >> slot 1": "WiiU NAND Savedata >> slot 1", + "vWii Savedata >> slot 0": "vWii Savedata >> slot 0", + "BackupSet: %s": "BackupSet: %s", + ", from ": ", da " } \ No newline at end of file diff --git a/languages/portuguese.json b/languages/portuguese.json index 60d473c..126a856 100644 --- a/languages/portuguese.json +++ b/languages/portuguese.json @@ -49,7 +49,6 @@ "yes": "sim", "no ": "não ", "No 'common' save found.": "Save 'common' não encontrado.", - "\ue000: Restore \ue001: Back": "\ue000: Restaurar \ue001: Voltar", "\ue000: Wipe \ue001: Back": "\ue000: Excluir \ue001: Voltar", "\ue000: Import \ue001: Back": "\ue000: Importar \ue001: Voltar", "\ue000: Export \ue001: Back": "\ue000: Exportar \ue001: Voltar", @@ -95,5 +94,13 @@ "Failed to delete savefile.": "Falha ao excluir save.", "Failed to delete user folder: %s": "Falha ao excluir pasta de usuário: %s", "Failed to import savedata from loadiine.": "Falha ao importar save (Loadiine).", - "Failed to export savedata to loadiine.": "Falha ao exportar save (Loadiine)." + "Failed to export savedata to loadiine.": "Falha ao exportar save (Loadiine).", + "\ue083 Sort: %s \ue084": "\ue083 Organizar: %s \ue084", + "\ue000: Select BackupSet \ue001: Back": "\ue000: Selecione BackupSet \ue001: Voltar", + "\ue002: Change BackupSet \ue000: Restore \ue001: Back": "\ue002: Alterar BackupSet \ue000: Restaurar \ue001: Voltar", + "WiiU USB Savedata >> slot 0": "WiiU USB Savedata >> slot 0", + "WiiU NAND Savedata >> slot 1": "WiiU NAND Savedata >> slot 1", + "vWii Savedata >> slot 0": "vWii Savedata >> slot 0", + "BackupSet: %s": "BackupSet: %s", + ", from ": ", de " } \ No newline at end of file diff --git a/languages/spanish.json b/languages/spanish.json index c0a553e..3d67773 100644 --- a/languages/spanish.json +++ b/languages/spanish.json @@ -94,5 +94,13 @@ "Failed to delete savefile.": "Error al eliminar el save.", "Failed to delete user folder: %s": "Error al eliminar la carpeta user: %s", "Failed to import savedata from loadiine.": "Error al importar el save de loadiine.", - "Failed to export savedata to loadiine.": "Error al exportar el save a loadiine." + "Failed to export savedata to loadiine.": "Error al exportar el save a loadiine.", + "\ue083 Sort: %s \ue084": "\ue083 Ordenar: %s \ue084", + "\ue000: Select BackupSet \ue001: Back": "\ue000: Seleccionar BackupSet \ue001: Atrás", + "\ue002: Change BackupSet \ue000: Restore \ue001: Back": "\ue002: Cambiar BackupSet \ue000: Restaurar \ue001: Atrás", + "WiiU USB Savedata >> slot 0": "WiiU USB Savedata >> slot 0", + "WiiU NAND Savedata >> slot 1": "WiiU NAND Savedata >> slot 1", + "vWii Savedata >> slot 0": "vWii Savedata >> slot 0", + "BackupSet: %s": "BackupSet: %s", + ", from ": ", de " } \ No newline at end of file diff --git a/src/menu/TitleOptionsState.cpp b/src/menu/TitleOptionsState.cpp index 95cd185..9b63e74 100644 --- a/src/menu/TitleOptionsState.cpp +++ b/src/menu/TitleOptionsState.cpp @@ -171,7 +171,7 @@ void TitleOptionsState::render() { consolePrintPosAligned(17, 4, 2, LanguageUtils::gettext("\ue000: Backup \ue001: Back")); break; case restore: - consolePrintPosAligned(17, 4, 2, LanguageUtils::gettext("\uE002: Chg BackupSet \ue000: Restore \ue001: Back")); + consolePrintPosAligned(17, 4, 2, LanguageUtils::gettext("\uE002: Change BackupSet \ue000: Restore \ue001: Back")); break; case wipe: consolePrintPosAligned(17, 4, 2, LanguageUtils::gettext("\ue000: Wipe \ue001: Back")); From 4aeaa8a5a29c45358e7e80af4c37f0f6c6bbf43a Mon Sep 17 00:00:00 2001 From: w3irDv <170813473+w3irDv@users.noreply.github.com> Date: Fri, 23 Aug 2024 00:04:29 +0200 Subject: [PATCH 16/22] Dockerfile and actions update --- .github/workflows/main.yml | 6 +++--- Dockerfile | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 356bbf4..e3a2ee1 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 - name: Docker Layer Caching @@ -22,13 +22,13 @@ jobs: docker build . --file Dockerfile --tag builder docker run --rm -v ${PWD}:/project builder make release -j$(nproc) - name: Upload Aroma version - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: SaveMiiModWUTPort-Aroma path: SaveMiiModWUTPort-Aroma.zip if-no-files-found: warn - name: Upload HBL version - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: SaveMiiModWUTPort-HBL path: SaveMiiModWUTPort-HBL.zip diff --git a/Dockerfile b/Dockerfile index c736529..e42cf34 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ -FROM ghcr.io/wiiu-env/devkitppc:20231112 +FROM ghcr.io/wiiu-env/devkitppc:20240704 -COPY --from=ghcr.io/wiiu-env/libmocha:20231127 /artifacts $DEVKITPRO +COPY --from=ghcr.io/wiiu-env/libmocha:20240603 /artifacts $DEVKITPRO RUN git clone --recursive https://github.com/yawut/libromfs-wiiu --single-branch && \ cd libromfs-wiiu && \ From a71ec429d8b465482505d7ca39b82e3f0e102fc7 Mon Sep 17 00:00:00 2001 From: w3irDv <170813473+w3irDv@users.noreply.github.com> Date: Fri, 23 Aug 2024 20:01:45 +0200 Subject: [PATCH 17/22] fix - possible sduser index out of bounds when moving between slots in restore menu --- include/menu/TitleOptionsState.h | 14 ++--- include/savemng.h | 8 +-- src/menu/TitleOptionsState.cpp | 88 ++++++++++++++++++-------------- src/menu/TitleTaskState.cpp | 8 +-- src/savemng.cpp | 38 +++++++------- 5 files changed, 83 insertions(+), 73 deletions(-) diff --git a/include/menu/TitleOptionsState.h b/include/menu/TitleOptionsState.h index 082c60c..12c2d51 100644 --- a/include/menu/TitleOptionsState.h +++ b/include/menu/TitleOptionsState.h @@ -7,13 +7,13 @@ class TitleOptionsState : public ApplicationState { public: - TitleOptionsState(Title title, Task task, int *versionList, int8_t sdusers, int8_t allusers, bool common, int8_t allusers_d, Title *titles, int titleCount) : title(title), + TitleOptionsState(Title title, Task task, int *versionList, int8_t sduser, int8_t wiiuser, bool common, int8_t wiiuser_d, Title *titles, int titleCount) : title(title), task(task), versionList(versionList), - sdusers(sdusers), - allusers(allusers), + sduser(sduser), + wiiuser(wiiuser), common(common), - allusers_d(allusers_d), + wiiuser_d(wiiuser_d), titles(titles), titleCount(titleCount) {} @@ -34,10 +34,10 @@ class TitleOptionsState : public ApplicationState { int *versionList; - int8_t sdusers; - int8_t allusers; + int8_t sduser; + int8_t wiiuser; bool common; - int8_t allusers_d; + int8_t wiiuser_d; Title *titles; int titleCount; diff --git a/include/savemng.h b/include/savemng.h index 682ea74..507f3b5 100644 --- a/include/savemng.h +++ b/include/savemng.h @@ -117,15 +117,15 @@ bool getLoadiineGameSaveDir(char *out, const char *productCode, const char *long bool getLoadiineSaveVersionList(int *out, const char *gamePath); bool isSlotEmpty(uint32_t highID, uint32_t lowID, uint8_t slot); bool hasCommonSave(Title *title, bool inSD, bool iine, uint8_t slot, int version); -void copySavedata(Title *title, Title *titled, int8_t allusers, int8_t allusers_d, bool common) __attribute__((hot)); +void copySavedata(Title *title, Title *titled, int8_t wiiuser, int8_t wiiuser_d, bool common) __attribute__((hot)); std::string getNowDateForFolder() __attribute__((hot)); std::string getNowDate() __attribute__((hot)); void writeMetadata(uint32_t highID,uint32_t lowID,uint8_t slot,bool isUSB) __attribute__((hot)); void writeMetadata(uint32_t highID,uint32_t lowID,uint8_t slot,bool isUSB,const std::string &batchDatetime) __attribute__((hot)); void backupAllSave(Title *titles, int count, const std::string &batchDatetime) __attribute__((hot)); -void backupSavedata(Title *title, uint8_t slot, int8_t allusers, bool common) __attribute__((hot)); -void restoreSavedata(Title *title, uint8_t slot, int8_t sdusers, int8_t allusers, bool common) __attribute__((hot)); -void wipeSavedata(Title *title, int8_t allusers, bool common) __attribute__((hot)); +void backupSavedata(Title *title, uint8_t slot, int8_t wiiuser, bool common) __attribute__((hot)); +void restoreSavedata(Title *title, uint8_t slot, int8_t sduser, int8_t wiiuser, bool common) __attribute__((hot)); +void wipeSavedata(Title *title, int8_t wiiuser, bool common) __attribute__((hot)); void importFromLoadiine(Title *title, bool common, int version); void exportToLoadiine(Title *title, bool common, int version); int checkEntry(const char *fPath); diff --git a/src/menu/TitleOptionsState.cpp b/src/menu/TitleOptionsState.cpp index 9b63e74..0d20e66 100644 --- a/src/menu/TitleOptionsState.cpp +++ b/src/menu/TitleOptionsState.cpp @@ -54,11 +54,11 @@ void TitleOptionsState::render() { if (!isSlotEmpty(this->title.highID, this->title.lowID, slot)) { entrycount++; consolePrintPos(M_OFF, 7, LanguageUtils::gettext("Select SD user to copy from:")); - if (sdusers == -1) + if (sduser == -1) consolePrintPos(M_OFF, 8, " < %s >", LanguageUtils::gettext("all users")); else - consolePrintPos(M_OFF, 8, " < %s > (%s)", getSDacc()[sdusers].persistentID, - hasAccountSave(&this->title, true, false, getSDacc()[sdusers].pID, + consolePrintPos(M_OFF, 8, " < %s > (%s)", getSDacc()[sduser].persistentID, + hasAccountSave(&this->title, true, false, getSDacc()[sduser].pID, slot, 0) ? LanguageUtils::gettext("Has Save") : LanguageUtils::gettext("Empty")); @@ -67,12 +67,12 @@ void TitleOptionsState::render() { if (task == wipe) { consolePrintPos(M_OFF, 7, LanguageUtils::gettext("Select Wii U user to delete from:")); - if (this->allusers == -1) + if (this->wiiuser == -1) consolePrintPos(M_OFF, 8, " < %s >", LanguageUtils::gettext("all users")); else - consolePrintPos(M_OFF, 8, " < %s (%s) > (%s)", getWiiUacc()[this->allusers].miiName, - getWiiUacc()[this->allusers].persistentID, - hasAccountSave(&this->title, false, false, getWiiUacc()[this->allusers].pID, + consolePrintPos(M_OFF, 8, " < %s (%s) > (%s)", getWiiUacc()[this->wiiuser].miiName, + getWiiUacc()[this->wiiuser].persistentID, + hasAccountSave(&this->title, false, false, getWiiUacc()[this->wiiuser].pID, slot, 0) ? LanguageUtils::gettext("Has Save") : LanguageUtils::gettext("Empty")); @@ -84,15 +84,15 @@ void TitleOptionsState::render() { else { consolePrintPos(M_OFF, (task == restore) ? 10 : 7, LanguageUtils::gettext("Select Wii U user%s:"), (task == copytoOtherDevice) ? LanguageUtils::gettext(" to copy from") : ((task == restore) ? LanguageUtils::gettext(" to copy to") : "")); - if (this->allusers == -1) + if (this->wiiuser == -1) consolePrintPos(M_OFF, (task == restore) ? 11 : 8, " < %s >", LanguageUtils::gettext("all users")); else consolePrintPos(M_OFF, (task == restore) ? 11 : 8, " < %s (%s) > (%s)", - getWiiUacc()[allusers].miiName, getWiiUacc()[allusers].persistentID, + getWiiUacc()[wiiuser].miiName, getWiiUacc()[wiiuser].persistentID, hasAccountSave(&this->title, (!((task == backup) || (task == restore) || (task == copytoOtherDevice))), (!((task < 3) || (task == copytoOtherDevice))), - getWiiUacc()[this->allusers].pID, slot, + getWiiUacc()[this->wiiuser].pID, slot, this->versionList != nullptr ? this->versionList[slot] : 0) ? LanguageUtils::gettext("Has Save") : LanguageUtils::gettext("Empty")); @@ -109,19 +109,19 @@ void TitleOptionsState::render() { if (task == copytoOtherDevice) { entrycount++; consolePrintPos(M_OFF, 10, LanguageUtils::gettext("Select Wii U user%s:"), (task == copytoOtherDevice) ? LanguageUtils::gettext(" to copy to") : ""); - if (allusers_d == -1) + if (wiiuser_d == -1) consolePrintPos(M_OFF, 11, " < %s >", LanguageUtils::gettext("all users")); else - consolePrintPos(M_OFF, 11, " < %s (%s) > (%s)", getWiiUacc()[allusers_d].miiName, - getWiiUacc()[allusers_d].persistentID, + consolePrintPos(M_OFF, 11, " < %s (%s) > (%s)", getWiiUacc()[wiiuser_d].miiName, + getWiiUacc()[wiiuser_d].persistentID, hasAccountSave(&titles[this->title.dupeID], false, false, - getWiiUacc()[allusers_d].pID, 0, 0) + getWiiUacc()[wiiuser_d].pID, 0, 0) ? LanguageUtils::gettext("Has Save") : LanguageUtils::gettext("Empty")); } if ((task != importLoadiine) && (task != exportLoadiine)) { - if (this->allusers > -1) { + if (this->wiiuser > -1) { if (hasCommonSave(&this->title, (!((task == backup) || (task == wipe) || (task == copytoOtherDevice))), (!((task < 3) || (task == copytoOtherDevice))), slot, @@ -206,12 +206,12 @@ ApplicationState::eSubState TitleOptionsState::update(Input *input) { case 0: break; case 1: - this->allusers = ((this->allusers == -1) ? -1 : (this->allusers - 1)); - allusers_d = this->allusers; + this->wiiuser = ((this->wiiuser == -1) ? -1 : (this->wiiuser - 1)); + wiiuser_d = this->wiiuser; break; case 2: - allusers_d = (((this->allusers == -1) || (allusers_d == -1)) ? -1 : (allusers_d - 1)); - allusers_d = ((this->allusers > -1) && (allusers_d == -1)) ? 0 : allusers_d; + wiiuser_d = (((this->wiiuser == -1) || (wiiuser_d == -1)) ? -1 : (wiiuser_d - 1)); + wiiuser_d = ((this->wiiuser > -1) && (wiiuser_d == -1)) ? 0 : wiiuser_d; break; case 3: common = common ? false : true; @@ -223,14 +223,19 @@ ApplicationState::eSubState TitleOptionsState::update(Input *input) { switch (cursorPos) { case 0: getAccountsSD(&this->title, --slot); + if ( sduser > getSDaccn() - 1 ) + { + sduser = -1; + wiiuser = -1; + } break; case 1: - sdusers = ((sdusers == -1) ? -1 : (sdusers - 1)); - this->allusers = ((sdusers == -1) ? -1 : this->allusers); + sduser = ((sduser == -1) ? -1 : (sduser - 1)); + this->wiiuser = ((sduser == -1) ? -1 : this->wiiuser); break; case 2: - allusers = (((allusers == -1) || (sdusers == -1)) ? -1 : (allusers - 1)); - allusers = ((sdusers > -1) && (allusers == -1)) ? 0 : allusers; + wiiuser = (((wiiuser == -1) || (sduser == -1)) ? -1 : (wiiuser - 1)); + wiiuser = ((sduser > -1) && (wiiuser == -1)) ? 0 : wiiuser; break; case 3: common = common ? false : true; @@ -243,7 +248,7 @@ ApplicationState::eSubState TitleOptionsState::update(Input *input) { case 0: break; case 1: - allusers = ((allusers == -1) ? -1 : (allusers - 1)); + wiiuser = ((wiiuser == -1) ? -1 : (wiiuser - 1)); break; case 2: common = common ? false : true; @@ -268,7 +273,7 @@ ApplicationState::eSubState TitleOptionsState::update(Input *input) { slot--; break; case 1: - allusers = ((allusers == -1) ? -1 : (allusers - 1)); + wiiuser = ((wiiuser == -1) ? -1 : (wiiuser - 1)); break; case 2: common = common ? false : true; @@ -284,12 +289,12 @@ ApplicationState::eSubState TitleOptionsState::update(Input *input) { case 0: break; case 1: - allusers = ((allusers == (getWiiUaccn() - 1)) ? (getWiiUaccn() - 1) : (allusers + 1)); - allusers_d = allusers; + wiiuser = ((wiiuser == (getWiiUaccn() - 1)) ? (getWiiUaccn() - 1) : (wiiuser + 1)); + wiiuser_d = wiiuser; break; case 2: - allusers_d = ((allusers_d == (getWiiUaccn() - 1)) ? (getWiiUaccn() - 1) : (allusers_d + 1)); - allusers_d = (allusers == -1) ? -1 : allusers_d; + wiiuser_d = ((wiiuser_d == (getWiiUaccn() - 1)) ? (getWiiUaccn() - 1) : (wiiuser_d + 1)); + wiiuser_d = (wiiuser == -1) ? -1 : wiiuser_d; break; case 3: common = common ? false : true; @@ -301,14 +306,19 @@ ApplicationState::eSubState TitleOptionsState::update(Input *input) { switch (cursorPos) { case 0: getAccountsSD(&this->title, ++slot); + if ( sduser > getSDaccn() -1 ) + { + sduser = -1; + wiiuser = -1; + } break; case 1: - sdusers = ((sdusers == (getSDaccn() - 1)) ? (getSDaccn() - 1) : (sdusers + 1)); - allusers = ((sdusers > -1) && (allusers == -1)) ? 0 : allusers; + sduser = ((sduser == (getSDaccn() - 1)) ? (getSDaccn() - 1) : (sduser + 1)); + wiiuser = ((sduser > -1) && (wiiuser == -1)) ? 0 : wiiuser; break; case 2: - allusers = ((allusers == (getWiiUaccn() - 1)) ? (getWiiUaccn() - 1) : (allusers + 1)); - allusers = (sdusers == -1) ? -1 : allusers; + wiiuser = ((wiiuser == (getWiiUaccn() - 1)) ? (getWiiUaccn() - 1) : (wiiuser + 1)); + wiiuser = (sduser == -1) ? -1 : wiiuser; break; case 3: common = common ? false : true; @@ -321,7 +331,7 @@ ApplicationState::eSubState TitleOptionsState::update(Input *input) { case 0: break; case 1: - allusers = ((allusers == (getWiiUaccn() - 1)) ? (getWiiUaccn() - 1) : (allusers + 1)); + wiiuser = ((wiiuser == (getWiiUaccn() - 1)) ? (getWiiUaccn() - 1) : (wiiuser + 1)); break; case 2: common = common ? false : true; @@ -346,7 +356,7 @@ ApplicationState::eSubState TitleOptionsState::update(Input *input) { slot++; break; case 1: - allusers = ((allusers == (getWiiUaccn() - 1)) ? (getWiiUaccn() - 1) : (allusers + 1)); + wiiuser = ((wiiuser == (getWiiUaccn() - 1)) ? (getWiiUaccn() - 1) : (wiiuser + 1)); break; case 2: common = common ? false : true; @@ -366,21 +376,21 @@ ApplicationState::eSubState TitleOptionsState::update(Input *input) { if (input->get(TRIGGER, PAD_BUTTON_A)) { switch (this->task) { case backup: - backupSavedata(&this->title, slot, allusers, common); + backupSavedata(&this->title, slot, wiiuser, common); DrawUtils::setRedraw(true); break; case restore: - restoreSavedata(&this->title, slot, sdusers, allusers, common); + restoreSavedata(&this->title, slot, sduser, wiiuser, common); DrawUtils::setRedraw(true); break; case wipe: - wipeSavedata(&this->title, allusers, common); + wipeSavedata(&this->title, wiiuser, common); DrawUtils::setRedraw(true); break; case copytoOtherDevice: for (int i = 0; i < this->titleCount; i++) { if (titles[i].listID == this->title.dupeID) { - copySavedata(&this->title, &titles[i], allusers, allusers_d, common); + copySavedata(&this->title, &titles[i], wiiuser, wiiuser_d, common); DrawUtils::setRedraw(true); break; } diff --git a/src/menu/TitleTaskState.cpp b/src/menu/TitleTaskState.cpp index e857d46..e9435ad 100644 --- a/src/menu/TitleTaskState.cpp +++ b/src/menu/TitleTaskState.cpp @@ -10,7 +10,7 @@ static int cursorPos = 0; static int entrycount; static uint8_t slot = 0; -static int8_t allusers = -1, allusers_d = -1, sdusers = -1; +static int8_t wiiuser = -1, wiiuser_d = -1, sduser = -1; static bool common = true; void TitleTaskState::render() { @@ -64,8 +64,8 @@ ApplicationState::eSubState TitleTaskState::update(Input *input) { if (this->task == restore) { BackupSetList::setBackupSetSubPath(); getAccountsSD(&this->title, slot); - allusers = ((sdusers == -1) ? -1 : allusers); - sdusers = ((allusers == -1) ? -1 : sdusers); + wiiuser = ((sduser == -1) ? -1 : wiiuser); + sduser = ((wiiuser == -1) ? -1 : sduser); } if (this->task == wipe) { @@ -103,7 +103,7 @@ ApplicationState::eSubState TitleTaskState::update(Input *input) { if (noError) { DrawUtils::setRedraw(true); this->state = STATE_DO_SUBSTATE; - this->subState = std::make_unique(this->title, this->task, this->versionList, sdusers, allusers, common, allusers_d, this->titles, this->titlesCount); + this->subState = std::make_unique(this->title, this->task, this->versionList, sduser, wiiuser, common, wiiuser_d, this->titles, this->titlesCount); } } if (cursorPos > entrycount) diff --git a/src/savemng.cpp b/src/savemng.cpp index 8a45ad2..85ed1c9 100644 --- a/src/savemng.cpp +++ b/src/savemng.cpp @@ -836,7 +836,7 @@ static void FSAMakeQuotaFromDir(const char *src_path, const char *dst_path, uint closedir(src_dir); } -void copySavedata(Title *title, Title *titleb, int8_t allusers, int8_t allusers_d, bool common) { +void copySavedata(Title *title, Title *titleb, int8_t wiiuser, int8_t wiiuser_d, bool common) { uint32_t highID = title->highID; uint32_t lowID = title->lowID; bool isUSB = title->isTitleOnUSB; @@ -848,7 +848,7 @@ void copySavedata(Title *title, Title *titleb, int8_t allusers, int8_t allusers_ return; int slotb = getEmptySlot(titleb->highID, titleb->lowID); if ((slotb >= 0) && promptConfirm(ST_YES_NO, LanguageUtils::gettext("Backup current savedata first to next empty slot?"))) { - backupSavedata(titleb, slotb, allusers, common); + backupSavedata(titleb, slotb, wiiuser, common); promptError(LanguageUtils::gettext("Backup done. Now copying Savedata.")); } @@ -859,7 +859,7 @@ void copySavedata(Title *title, Title *titleb, int8_t allusers, int8_t allusers_ createFolderUnlocked(dstPath); bool commonSaved = false; - if (allusers > -1) { + if (wiiuser > -1) { if (common) { FSAMakeQuota(handle, newlibtoFSA(dstPath + "/common").c_str(), 0x666, titleb->accountSaveSize); if (copyDir(srcPath + "/common", dstPath + "/common")) @@ -867,8 +867,8 @@ void copySavedata(Title *title, Title *titleb, int8_t allusers, int8_t allusers_ else promptError(LanguageUtils::gettext("Common save not found.")); } - srcPath.append(StringUtils::stringFormat("/%s", wiiuacc[allusers].persistentID)); - dstPath.append(StringUtils::stringFormat("/%s", wiiuacc[allusers_d].persistentID)); + srcPath.append(StringUtils::stringFormat("/%s", wiiuacc[wiiuser].persistentID)); + dstPath.append(StringUtils::stringFormat("/%s", wiiuacc[wiiuser_d].persistentID)); if (checkEntry(srcPath.c_str()) == 2) { FSAMakeQuota(handle, newlibtoFSA(dstPath).c_str(), 0x666, titleb->accountSaveSize); if (!copyDir(srcPath, dstPath)) @@ -969,7 +969,7 @@ void backupAllSave(Title *titles, int count, const std::string &batchDatetime) { } -void backupSavedata(Title *title, uint8_t slot, int8_t allusers, bool common) { +void backupSavedata(Title *title, uint8_t slot, int8_t wiiuser, bool common) { if (!isSlotEmpty(title->highID, title->lowID, slot) && !promptConfirm(ST_WARNING, LanguageUtils::gettext("Backup found on this slot. Overwrite it?"))) { return; @@ -984,15 +984,15 @@ void backupSavedata(Title *title, uint8_t slot, int8_t allusers, bool common) { dstPath = getDynamicBackupPath(highID, lowID, slot); createFolder(dstPath.c_str()); bool commonSaved = false; - if ((allusers > -1) && !isWii) { + if ((wiiuser > -1) && !isWii) { if (common) { if (copyDir(srcPath+"/common", dstPath+"/common")) commonSaved = true; else promptError(LanguageUtils::gettext("Common save not found.")); } - srcPath.append(StringUtils::stringFormat("/%s", wiiuacc[allusers].persistentID)); - dstPath.append(StringUtils::stringFormat("/%s", wiiuacc[allusers].persistentID)); + srcPath.append(StringUtils::stringFormat("/%s", wiiuacc[wiiuser].persistentID)); + dstPath.append(StringUtils::stringFormat("/%s", wiiuacc[wiiuser].persistentID)); if (checkEntry(srcPath.c_str()) == 0) { if (commonSaved) @@ -1009,7 +1009,7 @@ void backupSavedata(Title *title, uint8_t slot, int8_t allusers, bool common) { } -void restoreSavedata(Title *title, uint8_t slot, int8_t sdusers, int8_t allusers, bool common) { +void restoreSavedata(Title *title, uint8_t slot, int8_t sduser, int8_t wiiuser, bool common) { if (isSlotEmpty(title->highID, title->lowID, slot)) { promptError(LanguageUtils::gettext("No backup found on selected slot.")); return; @@ -1018,7 +1018,7 @@ void restoreSavedata(Title *title, uint8_t slot, int8_t sdusers, int8_t allusers return; int slotb = getEmptySlot(title->highID, title->lowID); if ((slotb >= 0) && promptConfirm(ST_YES_NO, LanguageUtils::gettext("Backup current savedata first to next empty slot?"))) - backupSavedata(title, slotb, allusers, common); + backupSavedata(title, slotb, wiiuser, common); uint32_t highID = title->highID; uint32_t lowID = title->lowID; bool isUSB = title->isTitleOnUSB; @@ -1030,7 +1030,7 @@ void restoreSavedata(Title *title, uint8_t slot, int8_t sdusers, int8_t allusers createFolderUnlocked(dstPath); bool commonSaved = false; - if ((sdusers > -1) && !isWii) { + if ((sduser > -1) && !isWii) { if (common) { FSAMakeQuota(handle, newlibtoFSA(dstPath + "/common").c_str(), 0x666, title->accountSaveSize); if (copyDir(srcPath + "/common", dstPath + "/common")) @@ -1038,8 +1038,8 @@ void restoreSavedata(Title *title, uint8_t slot, int8_t sdusers, int8_t allusers else promptError(LanguageUtils::gettext("Common save not found.")); } - srcPath.append(StringUtils::stringFormat("/%s", sdacc[sdusers].persistentID)); - dstPath.append(StringUtils::stringFormat("/%s", wiiuacc[allusers].persistentID)); + srcPath.append(StringUtils::stringFormat("/%s", sdacc[sduser].persistentID)); + dstPath.append(StringUtils::stringFormat("/%s", wiiuacc[wiiuser].persistentID)); if (checkEntry(srcPath.c_str()) == 2) { FSAMakeQuota(handle, newlibtoFSA(dstPath).c_str(), 0x666, title->accountSaveSize); if (!copyDir(srcPath, dstPath)) @@ -1098,12 +1098,12 @@ void restoreSavedata(Title *title, uint8_t slot, int8_t sdusers, int8_t allusers } } -void wipeSavedata(Title *title, int8_t allusers, bool common) { +void wipeSavedata(Title *title, int8_t wiiuser, bool common) { if (!promptConfirm(ST_WARNING, LanguageUtils::gettext("Are you sure?")) || !promptConfirm(ST_WARNING, LanguageUtils::gettext("Hm, are you REALLY sure?"))) return; int slotb = getEmptySlot(title->highID, title->lowID); if ((slotb >= 0) && promptConfirm(ST_YES_NO, LanguageUtils::gettext("Backup current savedata first?"))) - backupSavedata(title, slotb, allusers, common); + backupSavedata(title, slotb, wiiuser, common); uint32_t highID = title->highID; uint32_t lowID = title->lowID; bool isUSB = title->isTitleOnUSB; @@ -1113,7 +1113,7 @@ void wipeSavedata(Title *title, int8_t allusers, bool common) { std::string path; path = (isWii ? "storage_slccmpt01:/title" : (isUSB ? (getUSB() + "/usr/save") : "storage_mlc01:/usr/save")); srcPath = StringUtils::stringFormat("%s/%08x/%08x/%s", path.c_str(), highID, lowID, isWii ? "data" : "user"); - if ((allusers > -1) && !isWii) { + if ((wiiuser > -1) && !isWii) { if (common) { origPath = srcPath + "/common"; if (!removeDir(origPath)) @@ -1121,13 +1121,13 @@ void wipeSavedata(Title *title, int8_t allusers, bool common) { if (unlink(origPath.c_str()) == -1) promptError(LanguageUtils::gettext("Failed to delete common folder: %s"), strerror(errno)); } - srcPath += "/" + std::string(wiiuacc[allusers].persistentID); + srcPath += "/" + std::string(wiiuacc[wiiuser].persistentID); } if (checkEntry(srcPath.c_str()) == 2) { if (!removeDir(srcPath)) promptError(LanguageUtils::gettext("Failed to delete savefile.")); - if ((allusers > -1) && !isWii) { + if ((wiiuser > -1) && !isWii) { if (unlink(srcPath.c_str()) == -1) promptError(LanguageUtils::gettext("Failed to delete user folder: %s"), strerror(errno)); } From c63e9dbc4905f51395a97246b9ddcbd04c1bd388 Mon Sep 17 00:00:00 2001 From: w3irDv <170813473+w3irDv@users.noreply.github.com> Date: Fri, 23 Aug 2024 22:35:24 +0200 Subject: [PATCH 18/22] backup before restore redirected to ROOT --- include/BackupSetList.h | 3 +++ languages/english.json | 4 +++- languages/german.json | 7 ++++--- languages/italian.json | 4 +++- languages/portuguese.json | 4 +++- languages/spanish.json | 4 +++- src/BackupSetList.cpp | 1 + src/menu/ConfigMenuState.cpp | 1 + src/savemng.cpp | 7 +++++-- src/utils/LanguageUtils.cpp | 2 ++ 10 files changed, 28 insertions(+), 9 deletions(-) diff --git a/include/BackupSetList.h b/include/BackupSetList.h index d0f27e0..0e5beaa 100644 --- a/include/BackupSetList.h +++ b/include/BackupSetList.h @@ -23,6 +23,8 @@ class BackupSetList { static void setBackupSetSubPath(); static void initBackupSetList(); static void setBackupSetSubPathToRoot() { backupSetSubPath = "/"; } + static void saveBackupSetSubPath() { savedBackupSetSubPath = backupSetSubPath; } + static void restoreBackupSetSubPath() { backupSetSubPath = savedBackupSetSubPath; } private: static bool sortAscending; @@ -31,6 +33,7 @@ class BackupSetList { std::string backupSetListRoot; static std::string backupSetSubPath; static std::string backupSetEntry; + static std::string savedBackupSetSubPath; }; diff --git a/languages/english.json b/languages/english.json index 79b492e..030d62e 100644 --- a/languages/english.json +++ b/languages/english.json @@ -101,5 +101,7 @@ "WiiU NAND Savedata >> slot 1": "WiiU NAND Savedata >> slot 1", "vWii Savedata >> slot 0": "vWii Savedata >> slot 0", "BackupSet: %s": "BackupSet: %s", - ", from ": ", from " + ", from ": ", from ", + "Common save not restored.": "Common save not restored.", + "\ue001: Back": "\ue001: Back" } \ No newline at end of file diff --git a/languages/german.json b/languages/german.json index 1107c7e..c05b974 100644 --- a/languages/german.json +++ b/languages/german.json @@ -47,7 +47,7 @@ "Include 'common' save?": "'Gemeinsame' Speicherung einschließen?", "yes": "Ja", "no ": "Nein ", - "No 'common' save found.": "Keine 'gemeinsame' Speicherung gefunden.",, + "No 'common' save found.": "Keine 'gemeinsame' Speicherung gefunden.", "\ue000: Wipe \ue001: Back": "\ue000: Lösche \ue001: Zurück", "\ue000: Import \ue001: Back": "\ue000: Importieren \ue001: Zurück", "\ue000: Export \ue001: Back": "\ue000: Exportieren \ue001: Zurück", @@ -94,7 +94,6 @@ "Failed to delete user folder: %s": "Löschen vom Nutzerordner fehlgeschlagen: %s", "Failed to import savedata from loadiine.": "Importieren von Loadiine Speicherdaten fehlgeschlagen.", "Failed to export savedata to loadiine.": "Exportieren von Loadiine Speicherdaten fehlgeschlagen.", - "German": "Deutsch", "\ue083 Sort: %s \ue084": "\ue083 Sortieren: %s \ue084", "\ue000: Select BackupSet \ue001: Back": "\ue000: Wählen Sie BackupSet \ue001: Zurück", "\ue002: Change BackupSet \ue000: Restore \ue001: Back": "\ue002: BackupSet ändern \ue000: Wiederherstellen \ue001: Zurück", @@ -102,5 +101,7 @@ "WiiU NAND Savedata >> slot 1": "WiiU NAND Savedata >> slot 1", "vWii Savedata >> slot 0": "vWii Savedata >> slot 0", "BackupSet: %s": "BackupSet: %s", - ", from ": ", aus " + ", from ": ", aus ", + "Common save not restored.": "'Gemeinsame' Sicherung nicht wiederhergestellt", + "\ue001: Back": "\ue001: Zurück" } diff --git a/languages/italian.json b/languages/italian.json index 5b388a7..8cdd6a2 100644 --- a/languages/italian.json +++ b/languages/italian.json @@ -101,5 +101,7 @@ "WiiU NAND Savedata >> slot 1": "WiiU NAND Savedata >> slot 1", "vWii Savedata >> slot 0": "vWii Savedata >> slot 0", "BackupSet: %s": "BackupSet: %s", - ", from ": ", da " + ", from ": ", da ", + "Common save not restored.": "Salvataggio comune non ripristinato", + "\ue001: Back": "\ue001: Indietro" } \ No newline at end of file diff --git a/languages/portuguese.json b/languages/portuguese.json index 126a856..18c3603 100644 --- a/languages/portuguese.json +++ b/languages/portuguese.json @@ -102,5 +102,7 @@ "WiiU NAND Savedata >> slot 1": "WiiU NAND Savedata >> slot 1", "vWii Savedata >> slot 0": "vWii Savedata >> slot 0", "BackupSet: %s": "BackupSet: %s", - ", from ": ", de " + ", from ": ", de ", + "Common save not restored.": "Save 'Common' não restauradoi", + "\ue001: Back": "\ue001: Voltar" } \ No newline at end of file diff --git a/languages/spanish.json b/languages/spanish.json index 3d67773..f40efde 100644 --- a/languages/spanish.json +++ b/languages/spanish.json @@ -102,5 +102,7 @@ "WiiU NAND Savedata >> slot 1": "WiiU NAND Savedata >> slot 1", "vWii Savedata >> slot 0": "vWii Savedata >> slot 0", "BackupSet: %s": "BackupSet: %s", - ", from ": ", de " + ", from ": ", de ", + "Common save not restored.": "No se ha podido restaurar el common save", + "\ue001: Back": "\ue001: Atrás" } \ No newline at end of file diff --git a/src/BackupSetList.cpp b/src/BackupSetList.cpp index cc4389e..bdfc1ef 100644 --- a/src/BackupSetList.cpp +++ b/src/BackupSetList.cpp @@ -11,6 +11,7 @@ bool BackupSetList::sortAscending = false; const std::string BackupSetList::ROOT_BS = ">> Root <<"; std::string BackupSetList::backupSetSubPath = "/";; std::string BackupSetList::backupSetEntry = ROOT_BS; +std::string BackupSetList::savedBackupSetSubPath {}; std::unique_ptr BackupSetList::currentBackupSetList = std::make_unique(); diff --git a/src/menu/ConfigMenuState.cpp b/src/menu/ConfigMenuState.cpp index 1a56616..bbd0d6a 100644 --- a/src/menu/ConfigMenuState.cpp +++ b/src/menu/ConfigMenuState.cpp @@ -11,6 +11,7 @@ void ConfigMenuState::render() { language = LanguageUtils::getLoadedLanguage(); consolePrintPos(M_OFF, 2, LanguageUtils::gettext(" Language: %s"), language.c_str()); consolePrintPos(M_OFF, 2 + cursorPos, "\u2192"); + consolePrintPosAligned(17,4,2,LanguageUtils::gettext("\ue001: Back")); } ApplicationState::eSubState ConfigMenuState::update(Input *input) { diff --git a/src/savemng.cpp b/src/savemng.cpp index 85ed1c9..5b37c3c 100644 --- a/src/savemng.cpp +++ b/src/savemng.cpp @@ -993,7 +993,6 @@ void backupSavedata(Title *title, uint8_t slot, int8_t wiiuser, bool common) { } srcPath.append(StringUtils::stringFormat("/%s", wiiuacc[wiiuser].persistentID)); dstPath.append(StringUtils::stringFormat("/%s", wiiuacc[wiiuser].persistentID)); - if (checkEntry(srcPath.c_str()) == 0) { if (commonSaved) writeMetadata(highID,lowID,slot,isUSB); @@ -1016,9 +1015,13 @@ void restoreSavedata(Title *title, uint8_t slot, int8_t sduser, int8_t wiiuser, } if (!promptConfirm(ST_WARNING, LanguageUtils::gettext("Are you sure?"))) return; + // backups to ROOT backupSet + BackupSetList::saveBackupSetSubPath(); + BackupSetList::setBackupSetSubPathToRoot(); int slotb = getEmptySlot(title->highID, title->lowID); if ((slotb >= 0) && promptConfirm(ST_YES_NO, LanguageUtils::gettext("Backup current savedata first to next empty slot?"))) backupSavedata(title, slotb, wiiuser, common); + BackupSetList::restoreBackupSetSubPath(); uint32_t highID = title->highID; uint32_t lowID = title->lowID; bool isUSB = title->isTitleOnUSB; @@ -1036,7 +1039,7 @@ void restoreSavedata(Title *title, uint8_t slot, int8_t sduser, int8_t wiiuser, if (copyDir(srcPath + "/common", dstPath + "/common")) commonSaved = true; else - promptError(LanguageUtils::gettext("Common save not found.")); + promptError(LanguageUtils::gettext("Common save not restored.")); } srcPath.append(StringUtils::stringFormat("/%s", sdacc[sduser].persistentID)); dstPath.append(StringUtils::stringFormat("/%s", wiiuacc[wiiuser].persistentID)); diff --git a/src/utils/LanguageUtils.cpp b/src/utils/LanguageUtils.cpp index 51f2b7d..468145a 100644 --- a/src/utils/LanguageUtils.cpp +++ b/src/utils/LanguageUtils.cpp @@ -25,6 +25,7 @@ void LanguageUtils::loadLanguage(Swkbd_LanguageType language) { break; */ case Swkbd_LanguageType__German: + DrawUtils::setFont(OS_SHAREDDATATYPE_FONT_STANDARD); gettextLoadLanguage("romfs:/german.json"); break; case Swkbd_LanguageType__Italian: @@ -49,6 +50,7 @@ void LanguageUtils::loadLanguage(Swkbd_LanguageType language) { break; */ case Swkbd_LanguageType__Portuguese: + DrawUtils::setFont(OS_SHAREDDATATYPE_FONT_STANDARD); gettextLoadLanguage("romfs:/portuguese.json"); break; case Swkbd_LanguageType__Russian: From e6b7f6815eb1f2250ab6eac5a5964e63754878f4 Mon Sep 17 00:00:00 2001 From: w3irDv <170813473+w3irDv@users.noreply.github.com> Date: Sat, 24 Aug 2024 10:47:19 +0200 Subject: [PATCH 19/22] use getBatchBackupPath function and Id > ID --- include/menu/TitleOptionsState.h | 10 ++--- include/savemng.h | 8 ++-- src/menu/TitleOptionsState.cpp | 72 ++++++++++++++++---------------- src/menu/TitleTaskState.cpp | 8 ++-- src/savemng.cpp | 49 +++++++++++----------- 5 files changed, 74 insertions(+), 73 deletions(-) diff --git a/include/menu/TitleOptionsState.h b/include/menu/TitleOptionsState.h index 12c2d51..29b3edc 100644 --- a/include/menu/TitleOptionsState.h +++ b/include/menu/TitleOptionsState.h @@ -7,13 +7,13 @@ class TitleOptionsState : public ApplicationState { public: - TitleOptionsState(Title title, Task task, int *versionList, int8_t sduser, int8_t wiiuser, bool common, int8_t wiiuser_d, Title *titles, int titleCount) : title(title), + TitleOptionsState(Title title, Task task, int *versionList, int8_t sduser, int8_t wiiuuser, bool common, int8_t wiiuuser_d, Title *titles, int titleCount) : title(title), task(task), versionList(versionList), sduser(sduser), - wiiuser(wiiuser), + wiiuuser(wiiuuser), common(common), - wiiuser_d(wiiuser_d), + wiiuuser_d(wiiuuser_d), titles(titles), titleCount(titleCount) {} @@ -35,9 +35,9 @@ class TitleOptionsState : public ApplicationState { int *versionList; int8_t sduser; - int8_t wiiuser; + int8_t wiiuuser; bool common; - int8_t wiiuser_d; + int8_t wiiuuser_d; Title *titles; int titleCount; diff --git a/include/savemng.h b/include/savemng.h index 507f3b5..7d48037 100644 --- a/include/savemng.h +++ b/include/savemng.h @@ -117,15 +117,15 @@ bool getLoadiineGameSaveDir(char *out, const char *productCode, const char *long bool getLoadiineSaveVersionList(int *out, const char *gamePath); bool isSlotEmpty(uint32_t highID, uint32_t lowID, uint8_t slot); bool hasCommonSave(Title *title, bool inSD, bool iine, uint8_t slot, int version); -void copySavedata(Title *title, Title *titled, int8_t wiiuser, int8_t wiiuser_d, bool common) __attribute__((hot)); +void copySavedata(Title *title, Title *titled, int8_t wiiuuser, int8_t wiiuuser_d, bool common) __attribute__((hot)); std::string getNowDateForFolder() __attribute__((hot)); std::string getNowDate() __attribute__((hot)); void writeMetadata(uint32_t highID,uint32_t lowID,uint8_t slot,bool isUSB) __attribute__((hot)); void writeMetadata(uint32_t highID,uint32_t lowID,uint8_t slot,bool isUSB,const std::string &batchDatetime) __attribute__((hot)); void backupAllSave(Title *titles, int count, const std::string &batchDatetime) __attribute__((hot)); -void backupSavedata(Title *title, uint8_t slot, int8_t wiiuser, bool common) __attribute__((hot)); -void restoreSavedata(Title *title, uint8_t slot, int8_t sduser, int8_t wiiuser, bool common) __attribute__((hot)); -void wipeSavedata(Title *title, int8_t wiiuser, bool common) __attribute__((hot)); +void backupSavedata(Title *title, uint8_t slot, int8_t wiiuuser, bool common) __attribute__((hot)); +void restoreSavedata(Title *title, uint8_t slot, int8_t sduser, int8_t wiiuuser, bool common) __attribute__((hot)); +void wipeSavedata(Title *title, int8_t wiiuuser, bool common) __attribute__((hot)); void importFromLoadiine(Title *title, bool common, int version); void exportToLoadiine(Title *title, bool common, int version); int checkEntry(const char *fPath); diff --git a/src/menu/TitleOptionsState.cpp b/src/menu/TitleOptionsState.cpp index 0d20e66..c9a66d1 100644 --- a/src/menu/TitleOptionsState.cpp +++ b/src/menu/TitleOptionsState.cpp @@ -67,12 +67,12 @@ void TitleOptionsState::render() { if (task == wipe) { consolePrintPos(M_OFF, 7, LanguageUtils::gettext("Select Wii U user to delete from:")); - if (this->wiiuser == -1) + if (this->wiiuuser == -1) consolePrintPos(M_OFF, 8, " < %s >", LanguageUtils::gettext("all users")); else - consolePrintPos(M_OFF, 8, " < %s (%s) > (%s)", getWiiUacc()[this->wiiuser].miiName, - getWiiUacc()[this->wiiuser].persistentID, - hasAccountSave(&this->title, false, false, getWiiUacc()[this->wiiuser].pID, + consolePrintPos(M_OFF, 8, " < %s (%s) > (%s)", getWiiUacc()[this->wiiuuser].miiName, + getWiiUacc()[this->wiiuuser].persistentID, + hasAccountSave(&this->title, false, false, getWiiUacc()[this->wiiuuser].pID, slot, 0) ? LanguageUtils::gettext("Has Save") : LanguageUtils::gettext("Empty")); @@ -84,15 +84,15 @@ void TitleOptionsState::render() { else { consolePrintPos(M_OFF, (task == restore) ? 10 : 7, LanguageUtils::gettext("Select Wii U user%s:"), (task == copytoOtherDevice) ? LanguageUtils::gettext(" to copy from") : ((task == restore) ? LanguageUtils::gettext(" to copy to") : "")); - if (this->wiiuser == -1) + if (this->wiiuuser == -1) consolePrintPos(M_OFF, (task == restore) ? 11 : 8, " < %s >", LanguageUtils::gettext("all users")); else consolePrintPos(M_OFF, (task == restore) ? 11 : 8, " < %s (%s) > (%s)", - getWiiUacc()[wiiuser].miiName, getWiiUacc()[wiiuser].persistentID, + getWiiUacc()[wiiuuser].miiName, getWiiUacc()[wiiuuser].persistentID, hasAccountSave(&this->title, (!((task == backup) || (task == restore) || (task == copytoOtherDevice))), (!((task < 3) || (task == copytoOtherDevice))), - getWiiUacc()[this->wiiuser].pID, slot, + getWiiUacc()[this->wiiuuser].pID, slot, this->versionList != nullptr ? this->versionList[slot] : 0) ? LanguageUtils::gettext("Has Save") : LanguageUtils::gettext("Empty")); @@ -109,19 +109,19 @@ void TitleOptionsState::render() { if (task == copytoOtherDevice) { entrycount++; consolePrintPos(M_OFF, 10, LanguageUtils::gettext("Select Wii U user%s:"), (task == copytoOtherDevice) ? LanguageUtils::gettext(" to copy to") : ""); - if (wiiuser_d == -1) + if (wiiuuser_d == -1) consolePrintPos(M_OFF, 11, " < %s >", LanguageUtils::gettext("all users")); else - consolePrintPos(M_OFF, 11, " < %s (%s) > (%s)", getWiiUacc()[wiiuser_d].miiName, - getWiiUacc()[wiiuser_d].persistentID, + consolePrintPos(M_OFF, 11, " < %s (%s) > (%s)", getWiiUacc()[wiiuuser_d].miiName, + getWiiUacc()[wiiuuser_d].persistentID, hasAccountSave(&titles[this->title.dupeID], false, false, - getWiiUacc()[wiiuser_d].pID, 0, 0) + getWiiUacc()[wiiuuser_d].pID, 0, 0) ? LanguageUtils::gettext("Has Save") : LanguageUtils::gettext("Empty")); } if ((task != importLoadiine) && (task != exportLoadiine)) { - if (this->wiiuser > -1) { + if (this->wiiuuser > -1) { if (hasCommonSave(&this->title, (!((task == backup) || (task == wipe) || (task == copytoOtherDevice))), (!((task < 3) || (task == copytoOtherDevice))), slot, @@ -206,12 +206,12 @@ ApplicationState::eSubState TitleOptionsState::update(Input *input) { case 0: break; case 1: - this->wiiuser = ((this->wiiuser == -1) ? -1 : (this->wiiuser - 1)); - wiiuser_d = this->wiiuser; + this->wiiuuser = ((this->wiiuuser == -1) ? -1 : (this->wiiuuser - 1)); + wiiuuser_d = this->wiiuuser; break; case 2: - wiiuser_d = (((this->wiiuser == -1) || (wiiuser_d == -1)) ? -1 : (wiiuser_d - 1)); - wiiuser_d = ((this->wiiuser > -1) && (wiiuser_d == -1)) ? 0 : wiiuser_d; + wiiuuser_d = (((this->wiiuuser == -1) || (wiiuuser_d == -1)) ? -1 : (wiiuuser_d - 1)); + wiiuuser_d = ((this->wiiuuser > -1) && (wiiuuser_d == -1)) ? 0 : wiiuuser_d; break; case 3: common = common ? false : true; @@ -226,16 +226,16 @@ ApplicationState::eSubState TitleOptionsState::update(Input *input) { if ( sduser > getSDaccn() - 1 ) { sduser = -1; - wiiuser = -1; + wiiuuser = -1; } break; case 1: sduser = ((sduser == -1) ? -1 : (sduser - 1)); - this->wiiuser = ((sduser == -1) ? -1 : this->wiiuser); + this->wiiuuser = ((sduser == -1) ? -1 : this->wiiuuser); break; case 2: - wiiuser = (((wiiuser == -1) || (sduser == -1)) ? -1 : (wiiuser - 1)); - wiiuser = ((sduser > -1) && (wiiuser == -1)) ? 0 : wiiuser; + wiiuuser = (((wiiuuser == -1) || (sduser == -1)) ? -1 : (wiiuuser - 1)); + wiiuuser = ((sduser > -1) && (wiiuuser == -1)) ? 0 : wiiuuser; break; case 3: common = common ? false : true; @@ -248,7 +248,7 @@ ApplicationState::eSubState TitleOptionsState::update(Input *input) { case 0: break; case 1: - wiiuser = ((wiiuser == -1) ? -1 : (wiiuser - 1)); + wiiuuser = ((wiiuuser == -1) ? -1 : (wiiuuser - 1)); break; case 2: common = common ? false : true; @@ -273,7 +273,7 @@ ApplicationState::eSubState TitleOptionsState::update(Input *input) { slot--; break; case 1: - wiiuser = ((wiiuser == -1) ? -1 : (wiiuser - 1)); + wiiuuser = ((wiiuuser == -1) ? -1 : (wiiuuser - 1)); break; case 2: common = common ? false : true; @@ -289,12 +289,12 @@ ApplicationState::eSubState TitleOptionsState::update(Input *input) { case 0: break; case 1: - wiiuser = ((wiiuser == (getWiiUaccn() - 1)) ? (getWiiUaccn() - 1) : (wiiuser + 1)); - wiiuser_d = wiiuser; + wiiuuser = ((wiiuuser == (getWiiUaccn() - 1)) ? (getWiiUaccn() - 1) : (wiiuuser + 1)); + wiiuuser_d = wiiuuser; break; case 2: - wiiuser_d = ((wiiuser_d == (getWiiUaccn() - 1)) ? (getWiiUaccn() - 1) : (wiiuser_d + 1)); - wiiuser_d = (wiiuser == -1) ? -1 : wiiuser_d; + wiiuuser_d = ((wiiuuser_d == (getWiiUaccn() - 1)) ? (getWiiUaccn() - 1) : (wiiuuser_d + 1)); + wiiuuser_d = (wiiuuser == -1) ? -1 : wiiuuser_d; break; case 3: common = common ? false : true; @@ -309,16 +309,16 @@ ApplicationState::eSubState TitleOptionsState::update(Input *input) { if ( sduser > getSDaccn() -1 ) { sduser = -1; - wiiuser = -1; + wiiuuser = -1; } break; case 1: sduser = ((sduser == (getSDaccn() - 1)) ? (getSDaccn() - 1) : (sduser + 1)); - wiiuser = ((sduser > -1) && (wiiuser == -1)) ? 0 : wiiuser; + wiiuuser = ((sduser > -1) && (wiiuuser == -1)) ? 0 : wiiuuser; break; case 2: - wiiuser = ((wiiuser == (getWiiUaccn() - 1)) ? (getWiiUaccn() - 1) : (wiiuser + 1)); - wiiuser = (sduser == -1) ? -1 : wiiuser; + wiiuuser = ((wiiuuser == (getWiiUaccn() - 1)) ? (getWiiUaccn() - 1) : (wiiuuser + 1)); + wiiuuser = (sduser == -1) ? -1 : wiiuuser; break; case 3: common = common ? false : true; @@ -331,7 +331,7 @@ ApplicationState::eSubState TitleOptionsState::update(Input *input) { case 0: break; case 1: - wiiuser = ((wiiuser == (getWiiUaccn() - 1)) ? (getWiiUaccn() - 1) : (wiiuser + 1)); + wiiuuser = ((wiiuuser == (getWiiUaccn() - 1)) ? (getWiiUaccn() - 1) : (wiiuuser + 1)); break; case 2: common = common ? false : true; @@ -356,7 +356,7 @@ ApplicationState::eSubState TitleOptionsState::update(Input *input) { slot++; break; case 1: - wiiuser = ((wiiuser == (getWiiUaccn() - 1)) ? (getWiiUaccn() - 1) : (wiiuser + 1)); + wiiuuser = ((wiiuuser == (getWiiUaccn() - 1)) ? (getWiiUaccn() - 1) : (wiiuuser + 1)); break; case 2: common = common ? false : true; @@ -376,21 +376,21 @@ ApplicationState::eSubState TitleOptionsState::update(Input *input) { if (input->get(TRIGGER, PAD_BUTTON_A)) { switch (this->task) { case backup: - backupSavedata(&this->title, slot, wiiuser, common); + backupSavedata(&this->title, slot, wiiuuser, common); DrawUtils::setRedraw(true); break; case restore: - restoreSavedata(&this->title, slot, sduser, wiiuser, common); + restoreSavedata(&this->title, slot, sduser, wiiuuser, common); DrawUtils::setRedraw(true); break; case wipe: - wipeSavedata(&this->title, wiiuser, common); + wipeSavedata(&this->title, wiiuuser, common); DrawUtils::setRedraw(true); break; case copytoOtherDevice: for (int i = 0; i < this->titleCount; i++) { if (titles[i].listID == this->title.dupeID) { - copySavedata(&this->title, &titles[i], wiiuser, wiiuser_d, common); + copySavedata(&this->title, &titles[i], wiiuuser, wiiuuser_d, common); DrawUtils::setRedraw(true); break; } diff --git a/src/menu/TitleTaskState.cpp b/src/menu/TitleTaskState.cpp index e9435ad..144c4b9 100644 --- a/src/menu/TitleTaskState.cpp +++ b/src/menu/TitleTaskState.cpp @@ -10,7 +10,7 @@ static int cursorPos = 0; static int entrycount; static uint8_t slot = 0; -static int8_t wiiuser = -1, wiiuser_d = -1, sduser = -1; +static int8_t wiiuuser = -1, wiiuuser_d = -1, sduser = -1; static bool common = true; void TitleTaskState::render() { @@ -64,8 +64,8 @@ ApplicationState::eSubState TitleTaskState::update(Input *input) { if (this->task == restore) { BackupSetList::setBackupSetSubPath(); getAccountsSD(&this->title, slot); - wiiuser = ((sduser == -1) ? -1 : wiiuser); - sduser = ((wiiuser == -1) ? -1 : sduser); + wiiuuser = ((sduser == -1) ? -1 : wiiuuser); + sduser = ((wiiuuser == -1) ? -1 : sduser); } if (this->task == wipe) { @@ -103,7 +103,7 @@ ApplicationState::eSubState TitleTaskState::update(Input *input) { if (noError) { DrawUtils::setRedraw(true); this->state = STATE_DO_SUBSTATE; - this->subState = std::make_unique(this->title, this->task, this->versionList, sduser, wiiuser, common, wiiuser_d, this->titles, this->titlesCount); + this->subState = std::make_unique(this->title, this->task, this->versionList, sduser, wiiuuser, common, wiiuuser_d, this->titles, this->titlesCount); } } if (cursorPos > entrycount) diff --git a/src/savemng.cpp b/src/savemng.cpp index 5b37c3c..450c55e 100644 --- a/src/savemng.cpp +++ b/src/savemng.cpp @@ -54,16 +54,16 @@ std::string newlibtoFSA(std::string path) { return path; } -std::string getDynamicBackupPath(uint32_t highId, uint32_t lowId, uint8_t slot) { +std::string getDynamicBackupPath(uint32_t highID, uint32_t lowID, uint8_t slot) { - if (((highId & 0xFFFFFFF0) == 0x00010000) && (slot == 255)) - return StringUtils::stringFormat("%s/%08x%08x", legacyBackupPath, highId, lowId); // LegacyBackup + if (((highID & 0xFFFFFFF0) == 0x00010000) && (slot == 255)) + return StringUtils::stringFormat("%s/%08x%08x", legacyBackupPath, highID, lowID); // LegacyBackup else - return StringUtils::stringFormat("%s%s%08x%08x/%u", backupPath, BackupSetList::getBackupSetSubPath().c_str(), highId, lowId, slot); + return StringUtils::stringFormat("%s%s%08x%08x/%u", backupPath, BackupSetList::getBackupSetSubPath().c_str(), highID, lowID, slot); } -std::string getBatchBackupPath(uint32_t highId, uint32_t lowId, uint8_t slot, std::string datetime) { - return StringUtils::stringFormat("%s/%s/%08x%08x/%u", batchBackupPath, datetime.c_str(),highId, lowId, slot); +std::string getBatchBackupPath(uint32_t highID, uint32_t lowID, uint8_t slot, std::string datetime) { + return StringUtils::stringFormat("%s/%s/%08x%08x/%u", batchBackupPath, datetime.c_str(),highID, lowID, slot); } uint8_t getSDaccn() { @@ -836,7 +836,7 @@ static void FSAMakeQuotaFromDir(const char *src_path, const char *dst_path, uint closedir(src_dir); } -void copySavedata(Title *title, Title *titleb, int8_t wiiuser, int8_t wiiuser_d, bool common) { +void copySavedata(Title *title, Title *titleb, int8_t wiiuuser, int8_t wiiuuser_d, bool common) { uint32_t highID = title->highID; uint32_t lowID = title->lowID; bool isUSB = title->isTitleOnUSB; @@ -848,7 +848,7 @@ void copySavedata(Title *title, Title *titleb, int8_t wiiuser, int8_t wiiuser_d, return; int slotb = getEmptySlot(titleb->highID, titleb->lowID); if ((slotb >= 0) && promptConfirm(ST_YES_NO, LanguageUtils::gettext("Backup current savedata first to next empty slot?"))) { - backupSavedata(titleb, slotb, wiiuser, common); + backupSavedata(titleb, slotb, wiiuuser, common); promptError(LanguageUtils::gettext("Backup done. Now copying Savedata.")); } @@ -859,7 +859,7 @@ void copySavedata(Title *title, Title *titleb, int8_t wiiuser, int8_t wiiuser_d, createFolderUnlocked(dstPath); bool commonSaved = false; - if (wiiuser > -1) { + if (wiiuuser > -1) { if (common) { FSAMakeQuota(handle, newlibtoFSA(dstPath + "/common").c_str(), 0x666, titleb->accountSaveSize); if (copyDir(srcPath + "/common", dstPath + "/common")) @@ -867,8 +867,8 @@ void copySavedata(Title *title, Title *titleb, int8_t wiiuser, int8_t wiiuser_d, else promptError(LanguageUtils::gettext("Common save not found.")); } - srcPath.append(StringUtils::stringFormat("/%s", wiiuacc[wiiuser].persistentID)); - dstPath.append(StringUtils::stringFormat("/%s", wiiuacc[wiiuser_d].persistentID)); + srcPath.append(StringUtils::stringFormat("/%s", wiiuacc[wiiuuser].persistentID)); + dstPath.append(StringUtils::stringFormat("/%s", wiiuacc[wiiuuser_d].persistentID)); if (checkEntry(srcPath.c_str()) == 2) { FSAMakeQuota(handle, newlibtoFSA(dstPath).c_str(), 0x666, titleb->accountSaveSize); if (!copyDir(srcPath, dstPath)) @@ -958,7 +958,8 @@ void backupAllSave(Title *titles, int count, const std::string &batchDatetime) { uint8_t slot = ( isWii ? 0 : (isUSB ? 0 : 1)); const std::string path = (isWii ? "storage_slccmpt01:/title" : (isUSB ? (getUSB() + "/usr/save").c_str() : "storage_mlc01:/usr/save")); std::string srcPath = StringUtils::stringFormat("%s/%08x/%08x/%s", path.c_str(), highID, lowID, isWii ? "data" : "user"); - std::string dstPath = StringUtils::stringFormat("%s/%s/%08x%08x/%u", batchBackupPath, batchDatetime.c_str(), highID, lowID,slot); + //std::string dstPath = StringUtils::stringFormat("%s/%s/%08x%08x/%u", batchBackupPath, batchDatetime.c_str(), highID, lowID,slot); + std::string dstPath = getBatchBackupPath(highID,lowID,slot, batchDatetime); createFolder(dstPath.c_str()); if (!copyDir(srcPath, dstPath)) @@ -969,7 +970,7 @@ void backupAllSave(Title *titles, int count, const std::string &batchDatetime) { } -void backupSavedata(Title *title, uint8_t slot, int8_t wiiuser, bool common) { +void backupSavedata(Title *title, uint8_t slot, int8_t wiiuuser, bool common) { if (!isSlotEmpty(title->highID, title->lowID, slot) && !promptConfirm(ST_WARNING, LanguageUtils::gettext("Backup found on this slot. Overwrite it?"))) { return; @@ -984,15 +985,15 @@ void backupSavedata(Title *title, uint8_t slot, int8_t wiiuser, bool common) { dstPath = getDynamicBackupPath(highID, lowID, slot); createFolder(dstPath.c_str()); bool commonSaved = false; - if ((wiiuser > -1) && !isWii) { + if ((wiiuuser > -1) && !isWii) { if (common) { if (copyDir(srcPath+"/common", dstPath+"/common")) commonSaved = true; else promptError(LanguageUtils::gettext("Common save not found.")); } - srcPath.append(StringUtils::stringFormat("/%s", wiiuacc[wiiuser].persistentID)); - dstPath.append(StringUtils::stringFormat("/%s", wiiuacc[wiiuser].persistentID)); + srcPath.append(StringUtils::stringFormat("/%s", wiiuacc[wiiuuser].persistentID)); + dstPath.append(StringUtils::stringFormat("/%s", wiiuacc[wiiuuser].persistentID)); if (checkEntry(srcPath.c_str()) == 0) { if (commonSaved) writeMetadata(highID,lowID,slot,isUSB); @@ -1008,7 +1009,7 @@ void backupSavedata(Title *title, uint8_t slot, int8_t wiiuser, bool common) { } -void restoreSavedata(Title *title, uint8_t slot, int8_t sduser, int8_t wiiuser, bool common) { +void restoreSavedata(Title *title, uint8_t slot, int8_t sduser, int8_t wiiuuser, bool common) { if (isSlotEmpty(title->highID, title->lowID, slot)) { promptError(LanguageUtils::gettext("No backup found on selected slot.")); return; @@ -1020,7 +1021,7 @@ void restoreSavedata(Title *title, uint8_t slot, int8_t sduser, int8_t wiiuser, BackupSetList::setBackupSetSubPathToRoot(); int slotb = getEmptySlot(title->highID, title->lowID); if ((slotb >= 0) && promptConfirm(ST_YES_NO, LanguageUtils::gettext("Backup current savedata first to next empty slot?"))) - backupSavedata(title, slotb, wiiuser, common); + backupSavedata(title, slotb, wiiuuser, common); BackupSetList::restoreBackupSetSubPath(); uint32_t highID = title->highID; uint32_t lowID = title->lowID; @@ -1042,7 +1043,7 @@ void restoreSavedata(Title *title, uint8_t slot, int8_t sduser, int8_t wiiuser, promptError(LanguageUtils::gettext("Common save not restored.")); } srcPath.append(StringUtils::stringFormat("/%s", sdacc[sduser].persistentID)); - dstPath.append(StringUtils::stringFormat("/%s", wiiuacc[wiiuser].persistentID)); + dstPath.append(StringUtils::stringFormat("/%s", wiiuacc[wiiuuser].persistentID)); if (checkEntry(srcPath.c_str()) == 2) { FSAMakeQuota(handle, newlibtoFSA(dstPath).c_str(), 0x666, title->accountSaveSize); if (!copyDir(srcPath, dstPath)) @@ -1101,12 +1102,12 @@ void restoreSavedata(Title *title, uint8_t slot, int8_t sduser, int8_t wiiuser, } } -void wipeSavedata(Title *title, int8_t wiiuser, bool common) { +void wipeSavedata(Title *title, int8_t wiiuuser, bool common) { if (!promptConfirm(ST_WARNING, LanguageUtils::gettext("Are you sure?")) || !promptConfirm(ST_WARNING, LanguageUtils::gettext("Hm, are you REALLY sure?"))) return; int slotb = getEmptySlot(title->highID, title->lowID); if ((slotb >= 0) && promptConfirm(ST_YES_NO, LanguageUtils::gettext("Backup current savedata first?"))) - backupSavedata(title, slotb, wiiuser, common); + backupSavedata(title, slotb, wiiuuser, common); uint32_t highID = title->highID; uint32_t lowID = title->lowID; bool isUSB = title->isTitleOnUSB; @@ -1116,7 +1117,7 @@ void wipeSavedata(Title *title, int8_t wiiuser, bool common) { std::string path; path = (isWii ? "storage_slccmpt01:/title" : (isUSB ? (getUSB() + "/usr/save") : "storage_mlc01:/usr/save")); srcPath = StringUtils::stringFormat("%s/%08x/%08x/%s", path.c_str(), highID, lowID, isWii ? "data" : "user"); - if ((wiiuser > -1) && !isWii) { + if ((wiiuuser > -1) && !isWii) { if (common) { origPath = srcPath + "/common"; if (!removeDir(origPath)) @@ -1124,13 +1125,13 @@ void wipeSavedata(Title *title, int8_t wiiuser, bool common) { if (unlink(origPath.c_str()) == -1) promptError(LanguageUtils::gettext("Failed to delete common folder: %s"), strerror(errno)); } - srcPath += "/" + std::string(wiiuacc[wiiuser].persistentID); + srcPath += "/" + std::string(wiiuacc[wiiuuser].persistentID); } if (checkEntry(srcPath.c_str()) == 2) { if (!removeDir(srcPath)) promptError(LanguageUtils::gettext("Failed to delete savefile.")); - if ((wiiuser > -1) && !isWii) { + if ((wiiuuser > -1) && !isWii) { if (unlink(srcPath.c_str()) == -1) promptError(LanguageUtils::gettext("Failed to delete user folder: %s"), strerror(errno)); } From 8f14332b2c396e7834317b5a8abc2593aef8c260 Mon Sep 17 00:00:00 2001 From: w3irDv <170813473+w3irDv@users.noreply.github.com> Date: Sat, 24 Aug 2024 12:17:55 +0200 Subject: [PATCH 20/22] Show console serialId in TitleTask menu --- include/{metadata.h => Metadata.h} | 0 src/{metadata.cpp => Metadata.cpp} | 2 +- src/main.cpp | 2 +- src/menu/TitleOptionsState.cpp | 2 +- src/menu/TitleTaskState.cpp | 5 +++++ src/savemng.cpp | 2 +- 6 files changed, 9 insertions(+), 4 deletions(-) rename include/{metadata.h => Metadata.h} (100%) rename src/{metadata.cpp => Metadata.cpp} (98%) diff --git a/include/metadata.h b/include/Metadata.h similarity index 100% rename from include/metadata.h rename to include/Metadata.h diff --git a/src/metadata.cpp b/src/Metadata.cpp similarity index 98% rename from src/metadata.cpp rename to src/Metadata.cpp index f487823..f1adb73 100644 --- a/src/metadata.cpp +++ b/src/Metadata.cpp @@ -1,4 +1,4 @@ -#include +#include #include #define FS_ALIGN(x) ((x + 0x3F) & ~(0x3F)) diff --git a/src/main.cpp b/src/main.cpp index e5666ff..59ed121 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5,7 +5,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/menu/TitleOptionsState.cpp b/src/menu/TitleOptionsState.cpp index c9a66d1..1a2f772 100644 --- a/src/menu/TitleOptionsState.cpp +++ b/src/menu/TitleOptionsState.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include #include #include diff --git a/src/menu/TitleTaskState.cpp b/src/menu/TitleTaskState.cpp index 144c4b9..91f26b7 100644 --- a/src/menu/TitleTaskState.cpp +++ b/src/menu/TitleTaskState.cpp @@ -3,9 +3,11 @@ #include #include #include +#include #include #include #include +#include static int cursorPos = 0; static int entrycount; @@ -22,6 +24,9 @@ void TitleTaskState::render() { return; } if (this->state == STATE_TITLE_TASKS) { + DrawUtils::setFontColor(COLOR_INFO); + consolePrintPosAligned(0, 4, 2,LanguageUtils::gettext("WiiU Serial Id: %s"),Metadata::serialId.c_str()); + DrawUtils::setFontColor(COLOR_TEXT); this->isWiiUTitle = (this->title.highID == 0x00050000) || (this->title.highID == 0x00050002); entrycount = 3 + 2 * static_cast(this->isWiiUTitle) + 1 * static_cast(this->isWiiUTitle && (this->title.isTitleDupe)); consolePrintPos(M_OFF, 2, " [%08X-%08X] [%s]", this->title.highID, this->title.lowID, diff --git a/src/savemng.cpp b/src/savemng.cpp index 450c55e..c1beb0c 100644 --- a/src/savemng.cpp +++ b/src/savemng.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include #include #include From 112e61643cd00296f2527c1d954ff99dcdab9670 Mon Sep 17 00:00:00 2001 From: w3irDv <170813473+w3irDv@users.noreply.github.com> Date: Sat, 24 Aug 2024 14:23:41 +0200 Subject: [PATCH 21/22] added me to metadata and Makefile --- Makefile | 2 +- meta/hbl/meta.xml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 596886d..a263acb 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ TOPDIR ?= $(CURDIR) #------------------------------------------------------------------------------- APP_NAME := SaveMii WUT Port APP_SHORTNAME := SaveMii -APP_AUTHOR := DaThinkingChair +APP_AUTHOR := DaThinkingChair,w3irDv include $(DEVKITPRO)/wut/share/wut_rules diff --git a/meta/hbl/meta.xml b/meta/hbl/meta.xml index 06de6f8..cdb49fa 100644 --- a/meta/hbl/meta.xml +++ b/meta/hbl/meta.xml @@ -1,9 +1,9 @@ SaveMii WUT - DaThinkingChair - 1.6.1 - 20220306000000 + DaThinkingChair,w3irDv + 1.6.3 + 202408240000 WiiU/vWii Save Manager WiiU/vWii Save Manager From 28bd63aa48a0f78a3e5c224e23fb0f6bdb068623 Mon Sep 17 00:00:00 2001 From: w3irDv <170813473+w3irDv@users.noreply.github.com> Date: Sat, 24 Aug 2024 16:42:02 +0200 Subject: [PATCH 22/22] change in batch backup don't overwrite logic - always use slot 0, slot 1 only for duplicate NAND savedata --- include/savemng.h | 1 + src/menu/BatchBackupState.cpp | 5 ---- src/savemng.cpp | 55 +++++++++++++++++++++++------------ 3 files changed, 37 insertions(+), 24 deletions(-) diff --git a/include/savemng.h b/include/savemng.h index 7d48037..ffb1392 100644 --- a/include/savemng.h +++ b/include/savemng.h @@ -116,6 +116,7 @@ bool hasAccountSave(Title *title, bool inSD, bool iine, uint32_t user, uint8_t s bool getLoadiineGameSaveDir(char *out, const char *productCode, const char *longName, const uint32_t highID, const uint32_t lowID); bool getLoadiineSaveVersionList(int *out, const char *gamePath); bool isSlotEmpty(uint32_t highID, uint32_t lowID, uint8_t slot); +bool isSlotEmpty(uint32_t highID, uint32_t lowID, uint8_t slot, const std::string &batchDatetime); bool hasCommonSave(Title *title, bool inSD, bool iine, uint8_t slot, int version); void copySavedata(Title *title, Title *titled, int8_t wiiuuser, int8_t wiiuuser_d, bool common) __attribute__((hot)); std::string getNowDateForFolder() __attribute__((hot)); diff --git a/src/menu/BatchBackupState.cpp b/src/menu/BatchBackupState.cpp index 4a7b82c..840a312 100644 --- a/src/menu/BatchBackupState.cpp +++ b/src/menu/BatchBackupState.cpp @@ -19,11 +19,6 @@ void BatchBackupState::render() { (this->wiiuTitlesCount > 1) ? "s" : ""); consolePrintPos(M_OFF, 4, LanguageUtils::gettext(" Backup vWii (%u Title%s)"), this->vWiiTitlesCount, (this->vWiiTitlesCount > 1) ? "s" : ""); - DrawUtils::setFontColor(COLOR_INFO); - consolePrintPosAligned(10,4,2,LanguageUtils::gettext("WiiU USB Savedata >> slot 0")); - consolePrintPosAligned(11,4,2,LanguageUtils::gettext("WiiU NAND Savedata >> slot 1")); - consolePrintPosAligned(12,4,2,LanguageUtils::gettext("vWii Savedata >> slot 0")); - DrawUtils::setFontColor(COLOR_TEXT); consolePrintPos(M_OFF, 2 + cursorPos, "\u2192"); consolePrintPosAligned(17, 4, 2, LanguageUtils::gettext("\ue000: Backup \ue001: Back")); } diff --git a/src/savemng.cpp b/src/savemng.cpp index c1beb0c..186e30b 100644 --- a/src/savemng.cpp +++ b/src/savemng.cpp @@ -729,6 +729,13 @@ bool isSlotEmpty(uint32_t highID, uint32_t lowID, uint8_t slot) { return ret <= 0; } +bool isSlotEmpty(uint32_t highID, uint32_t lowID, uint8_t slot, const std::string &batchDatetime) { + std::string path; + path = getBatchBackupPath(highID,lowID,slot,batchDatetime); + int ret = checkEntry(path.c_str()); + return ret <= 0; +} + static int getEmptySlot(uint32_t highID, uint32_t lowID) { for (int i = 0; i < 256; i++) if (isSlotEmpty(highID, lowID, i)) @@ -736,6 +743,14 @@ static int getEmptySlot(uint32_t highID, uint32_t lowID) { return -1; } +static int getEmptySlot(uint32_t highID, uint32_t lowID, const std::string &batchDatetime) { + for (int i = 0; i < 256; i++) + if (isSlotEmpty(highID, lowID, i, batchDatetime)) + return i; + return -1; +} + + bool hasAccountSave(Title *title, bool inSD, bool iine, uint32_t user, uint8_t slot, int version) { uint32_t highID = title->highID; uint32_t lowID = title->lowID; @@ -948,26 +963,28 @@ void writeMetadata(uint32_t highID,uint32_t lowID,uint8_t slot,bool isUSB, const } void backupAllSave(Title *titles, int count, const std::string &batchDatetime) { - for (int i = 0; i < count; i++) { - if (titles[i].highID == 0 || titles[i].lowID == 0 || !titles[i].saveInit) - continue; - uint32_t highID = titles[i].highID; - uint32_t lowID = titles[i].lowID; - bool isUSB = titles[i].isTitleOnUSB; - bool isWii = ((highID & 0xFFFFFFF0) == 0x00010000); - uint8_t slot = ( isWii ? 0 : (isUSB ? 0 : 1)); - const std::string path = (isWii ? "storage_slccmpt01:/title" : (isUSB ? (getUSB() + "/usr/save").c_str() : "storage_mlc01:/usr/save")); - std::string srcPath = StringUtils::stringFormat("%s/%08x/%08x/%s", path.c_str(), highID, lowID, isWii ? "data" : "user"); - //std::string dstPath = StringUtils::stringFormat("%s/%s/%08x%08x/%u", batchBackupPath, batchDatetime.c_str(), highID, lowID,slot); - std::string dstPath = getBatchBackupPath(highID,lowID,slot, batchDatetime); - - createFolder(dstPath.c_str()); - if (!copyDir(srcPath, dstPath)) - promptError(LanguageUtils::gettext("Backup failed.")); - else - writeMetadata(highID,lowID,slot,isUSB,batchDatetime); + for ( int sourceStorage = 0; sourceStorage < 2 ; sourceStorage++ ) { + for (int i = 0; i < count; i++) { + if (titles[i].highID == 0 || titles[i].lowID == 0 || !titles[i].saveInit) + continue; + uint32_t highID = titles[i].highID; + uint32_t lowID = titles[i].lowID; + bool isUSB = titles[i].isTitleOnUSB; + bool isWii = ((highID & 0xFFFFFFF0) == 0x00010000); + if ((sourceStorage == 0 && !isUSB) || (sourceStorage == 1 && isUSB)) // backup first WiiU USB savedata to slot 0 + continue; + uint8_t slot = getEmptySlot(highID,lowID,batchDatetime); + const std::string path = (isWii ? "storage_slccmpt01:/title" : (isUSB ? (getUSB() + "/usr/save").c_str() : "storage_mlc01:/usr/save")); + std::string srcPath = StringUtils::stringFormat("%s/%08x/%08x/%s", path.c_str(), highID, lowID, isWii ? "data" : "user"); + std::string dstPath = getBatchBackupPath(highID,lowID,slot,batchDatetime); + + createFolder(dstPath.c_str()); + if (!copyDir(srcPath, dstPath)) + promptError(LanguageUtils::gettext("Backup failed.")); + else + writeMetadata(highID,lowID,slot,isUSB,batchDatetime); + } } - } void backupSavedata(Title *title, uint8_t slot, int8_t wiiuuser, bool common) {