From 5ec3aaed9de0b034c65f96332d5b06728bb1cbf0 Mon Sep 17 00:00:00 2001 From: Frank Date: Sat, 12 May 2018 18:36:05 -0700 Subject: [PATCH] Dump All and Dump to dir --- Makefile | 3 +- README.md | 2 +- source/main.cpp | 180 ++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 146 insertions(+), 39 deletions(-) diff --git a/Makefile b/Makefile index ab1a8ba..49e7598 100644 --- a/Makefile +++ b/Makefile @@ -32,10 +32,11 @@ include $(DEVKITPRO)/libnx/switch_rules #--------------------------------------------------------------------------------- VERSION_MAJOR := 0 VERSION_MINOR := 1 +VERSION_MICRO := 1 APP_TITLE := Y'allAreNUTs APP_AUTHOR := 3096 -APP_VERSION := ${VERSION_MAJOR}.${VERSION_MINOR} +APP_VERSION := ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_MICRO} TARGET := $(notdir $(CURDIR)) BUILD := build diff --git a/README.md b/README.md index 97577ca..0d36f50 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ But since I know no one would listen to me and try to use this mess anyway... Here's an update. -Now you can use up & down to select a save to dump. All dumps will be saved to `save` by pressing A (will overwrite whatever's already in there.) Pressing X will inject all data that's present in `inject` (sometimes doesn't work due to service being broken on 5.0 and without using it, fsdevCommitDevice() can fail... Use at your own risk and always have backups) +Now you can use UP & DOWN, LEFT & RIGHT to select a save to dump. All dumps will be saved to `save` by pressing A or `save/{titleID}/{userID}/` by pressing Y (will overwrite whatever's already in there.) Press ZR to dump all saves. Pressing X will inject all data that's present in `inject` (sometimes doesn't work due to service being broken on 5.0 and without using it, fsdevCommitDevice() can fail... Use at your own risk and always have backups) Build it with [my fork of libnx](https://github.com/3096/libnx) btw. diff --git a/source/main.cpp b/source/main.cpp index 1ab889d..205dc3a 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -9,6 +9,7 @@ const char * EXPORT_DIR = "save/"; const char * INJECT_DIR = "inject/"; +const char * SAVE_DEV = "save"; Result getSaveList(std::vector & saveInfoList) { Result rc=0; @@ -40,9 +41,13 @@ Result getSaveList(std::vector & saveInfoList) { return 0; } -Result mountSaveByTitleAndUser(u64 titleID, u128 userID) { +Result mountSaveBySaveDataInfo(const FsSaveDataInfo & info, const char * dev) { Result rc=0; int ret=0; + + u64 titleID = info.titleID; + u128 userID = info.userID; + FsFileSystem tmpfs; printf("\n\nUsing titleID=0x%016lx userID: 0x%lx 0x%lx\n", titleID, (u64)(userID>>64), (u64)userID); @@ -53,7 +58,7 @@ Result mountSaveByTitleAndUser(u64 titleID, u128 userID) { return rc; } - ret = fsdevMountDevice("save", tmpfs); + ret = fsdevMountDevice(dev, tmpfs); if (ret==-1) { printf("fsdevMountDevice() failed.\n"); rc = ret; @@ -72,7 +77,7 @@ int isDirectory(const char *path) { int cpFile(const char * filenameI, const char * filenameO) { remove( filenameO ); - + std::ifstream src(filenameI, std::ios::binary); std::ofstream dst(filenameO, std::ios::binary); @@ -82,7 +87,8 @@ int cpFile(const char * filenameI, const char * filenameO) { } -int copyAllSave(const char * dev, const char * path, bool isInject) { +int copyAllSave(const char * dev, const char * path, bool isInject, + const char * exportDir) { DIR* dir; struct dirent* ent; char dirPath[0x100]; @@ -123,19 +129,32 @@ int copyAllSave(const char * dev, const char * path, bool isInject) { strcpy(filenameI, dev); strcat(filenameI, filename); - strcpy(filenameO, EXPORT_DIR); + if (exportDir != NULL) { + strcpy(filenameO, exportDir); + } else { + strcpy(filenameO, EXPORT_DIR); + } strcat(filenameO, filename); } - printf("Copying %s...\n", filenameI); - if(isDirectory(filenameI)) { mkdir(filenameO, 0700); - int res = copyAllSave(dev, filename, isInject); + int res = copyAllSave(dev, filename, isInject, exportDir); if(res != 0) return res; } else { + printf("Copying %s... ", filenameI); cpFile(filenameI, filenameO); + if(isInject) { + if (R_SUCCEEDED(fsdevCommitDevice(SAVE_DEV))) { // Thx yellows8 + printf("committed.\n"); + } else { + printf("fsdevCommitDevice() failed...\n"); + return -2; + } + } else { + printf("\n"); + } } } closedir(dir); @@ -144,6 +163,28 @@ int copyAllSave(const char * dev, const char * path, bool isInject) { } } +int dumpAll() { + return copyAllSave("save:/", ".", false, NULL); +} + +int dumpAllTo(char * dir) { + return copyAllSave("save:/", ".", false, dir); +} + +void dumpToTitleUserDir(FsSaveDataInfo info) { + char exportDir[0x100]; + sprintf(exportDir, "%s%016lx/", EXPORT_DIR, info.titleID); + mkdir(exportDir, 0700); + sprintf(exportDir, "%s%016lx/%lx%lx/", + EXPORT_DIR, info.titleID, (u64)(info.userID>>64), (u64)info.userID); + mkdir(exportDir, 0700); + dumpAllTo(exportDir); +} + +int inject() { + return copyAllSave("save:/", ".", true, NULL); +} + Result getTitleName(u64 titleID, char * name) { Result rc=0; @@ -239,31 +280,58 @@ Result getUserNameById(u128 userID, char * username) { } int selectSaveFromList(int & selection, int change, - std::vector & saveInfoList, FsSaveDataInfo & info) { + std::vector & saveInfoList, FsSaveDataInfo & info, bool printName) { selection += change; - change %= saveInfoList.size(); if (selection < 0) { - selection += saveInfoList.size(); + selection = abs(selection) % saveInfoList.size(); + selection = saveInfoList.size() - selection; } else if (selection > 0 && static_cast(selection) >= saveInfoList.size()) { - selection -= saveInfoList.size(); + selection %= saveInfoList.size(); } info = saveInfoList.at(selection); - char name[0x201]; - getTitleName(info.titleID, name); - char username[0x21]; - getUserNameById(info.userID, username); printf("\r "); gfxFlushBuffers(); gfxSwapBuffers(); gfxWaitForVsync(); - printf("\rSelected: %s \t User: %s", name, username); + if (printName){ + char name[0x201]; + getTitleName(info.titleID, name); + char username[0x21]; + getUserNameById(info.userID, username); + printf("\rSelected: %s \t User: %s", name, username); + } else { + printf("\rSelected titleID: 0x%016lx userID: 0x%lx%lx", + info.titleID, (u64)(info.userID>>64), (u64)info.userID); + } return selection; } +bool userConfirm(const char * msg) { + printf("\n%s\nPress A to confirm, any other button to cancel\n", msg); + + u64 kDownPrevious = hidKeysDown(CONTROLLER_P1_AUTO); + while(appletMainLoop()) + { + hidScanInput(); + u64 kDown = hidKeysDown(CONTROLLER_P1_AUTO); + + if(kDown > kDownPrevious) { + if (kDown & KEY_A) + return true; + else { + printf("Canceled\n"); + return false; + } + } + + kDownPrevious = kDown; + } + return false; +} int main(int argc, char **argv) { @@ -275,18 +343,28 @@ int main(int argc, char **argv) std::vector saveInfoList; + mkdir(EXPORT_DIR, 0700); + mkdir(INJECT_DIR, 0700); + if (R_FAILED(getSaveList(saveInfoList))) { printf("Failed to get save list 0x%x\n", rc); } - printf("Y'allAreNUTs v0.1\n"); - printf("Press A to dump save to 'save/'; Press X to inject contents from 'inject/'\n"); - printf("Press UP and DOWN to select a save; Press PLUS to quit\n\n"); + printf("Y'allAreNUTs v0.1.1\n" + "Press UP and DOWN to select a save\n" + "Press LEFT and RIGHT to skip 5 saves\n" + "Press A to dump save to 'save/'\n" + "Press Y to dump save to 'save/{titleID}/{userID}/'\n" + "Press ZR to dump all of your saves\n" + "Press X to inject contents from 'inject/'\n" + "Press R to toggle title ID (for manual look up) if it's garbled text\n" + "Press PLUS to quit\n\n"); // Main loop - int selection = -1; + int selection = 0; FsSaveDataInfo info; - selectSaveFromList(selection, 1, saveInfoList, info); + bool printName = true; + selectSaveFromList(selection, 0, saveInfoList, info, printName); while(appletMainLoop()) { //Scan all the inputs. This should be done once for each frame @@ -296,33 +374,61 @@ int main(int argc, char **argv) u64 kDown = hidKeysDown(CONTROLLER_P1_AUTO); if (kDown & KEY_UP) { - selectSaveFromList(selection, -1, saveInfoList, info); + selectSaveFromList(selection, -1, saveInfoList, info, printName); } if (kDown & KEY_DOWN) { - selectSaveFromList(selection, 1, saveInfoList, info); + selectSaveFromList(selection, 1, saveInfoList, info, printName); + } + + if (kDown & KEY_LEFT) { + selectSaveFromList(selection, -5, saveInfoList, info, printName); + } + + if (kDown & KEY_RIGHT) { + selectSaveFromList(selection, 5, saveInfoList, info, printName); } + if (kDown & KEY_R) { + printName = !printName; + selectSaveFromList(selection, 0, saveInfoList, info, printName); + } + if (kDown & KEY_A) { - mountSaveByTitleAndUser(info.titleID, info.userID); - mkdir(EXPORT_DIR, 0700); - copyAllSave("save:/", ".", false); + mountSaveBySaveDataInfo(info, SAVE_DEV); + dumpAll(); + fsdevUnmountDevice(SAVE_DEV); + printf("Dump over.\n\n"); + } + + if (kDown & KEY_Y) { + mountSaveBySaveDataInfo(info, SAVE_DEV); + dumpToTitleUserDir(info); + fsdevUnmountDevice(SAVE_DEV); printf("Dump over.\n\n"); - fsdevUnmountDevice("save"); + } + + if (kDown & KEY_ZR) { + if (userConfirm("Dump all saves? This may take a while.")) { + for(u32 i = 0; i < saveInfoList.size(); i++) { + info = saveInfoList.at(i); + mountSaveBySaveDataInfo(info, SAVE_DEV); + dumpToTitleUserDir(info); + fsdevUnmountDevice(SAVE_DEV); + } + printf("Dump over.\n\n"); + } } if (kDown & KEY_X) { - mountSaveByTitleAndUser(info.titleID, info.userID); - if( copyAllSave("save:/", ".", true) == 0 ) { - rc = fsdevCommitDevice("save"); - if (R_SUCCEEDED(rc)) { - printf("Changes committed.\n\n"); - } else { - printf("fsdevCommitDevice() failed: %x\n", rc); - printf("Try injecting less data maybe?\n\n"); + if (userConfirm("Inject data from 'inject/'?")) { + mountSaveBySaveDataInfo(info, SAVE_DEV); + if( inject() == 0 ) { + printf("Inject over.\n\n"); + } + fsdevUnmountDevice(SAVE_DEV); } - fsdevUnmountDevice("save"); } if (kDown & KEY_PLUS) {