From 1e3e01a81048492b4a2fc274a7be660ba6904923 Mon Sep 17 00:00:00 2001 From: J-D-K Date: Wed, 28 Jul 2021 22:23:08 -0400 Subject: [PATCH] Split FS/Threaded funcs, make restore check for empties before wiping, start working on extras (Only delete update works now) --- inc/file.h | 26 +++ inc/fsthrd.h | 14 ++ inc/ui.h | 1 + inc/ui/ext.h | 10 ++ inc/ui/uistr.h | 2 +- inc/util.h | 2 +- src/file.cpp | 420 ++++------------------------------------------ src/fsthrd.cpp | 359 +++++++++++++++++++++++++++++++++++++++ src/ui.cpp | 18 +- src/ui/ext.cpp | 64 +++++++ src/ui/miscui.cpp | 1 - src/ui/sett.cpp | 65 +++---- src/ui/ttl.cpp | 4 +- src/ui/uistr.cpp | 2 +- src/ui/usr.cpp | 3 +- src/util.cpp | 8 +- 16 files changed, 560 insertions(+), 439 deletions(-) create mode 100644 inc/fsthrd.h create mode 100644 inc/ui/ext.h create mode 100644 src/fsthrd.cpp create mode 100644 src/ui/ext.cpp diff --git a/inc/file.h b/inc/file.h index 48ef73f..52f156d 100644 --- a/inc/file.h +++ b/inc/file.h @@ -9,9 +9,12 @@ #include #include "fsfile.h" +#include "fsthrd.h" #include "data.h" #include "miscui.h" +#define BUFF_SIZE 0xC0000 + namespace fs { void init(); @@ -20,6 +23,7 @@ namespace fs //Mounts usr's save data for open. Returns false it fails bool mountSave(const FsSaveDataInfo& _m); inline bool unmountSave() { return fsdevUnmountDevice("sv") == 0; } + bool commitToDevice(const std::string& dev); void copyFile(const std::string& from, const std::string& to); void copyFileCommit(const std::string& from, const std::string& to, const std::string& dev); @@ -36,6 +40,10 @@ namespace fs //Copies unzfile to 'to' void copyZipToDir(unzFile unz, const std::string& to, const std::string& dev); + bool dirNotEmpty(const std::string& _dir); + bool zipNotEmpty(unzFile unzip); + + void mkdirRec(const std::string& _p); //deletes file void delfile(const std::string& path); //Recursively deletes 'path' @@ -127,12 +135,30 @@ namespace fs bool opened = false; }; + //Structs to send data to threads typedef struct { ui::menu *m; fs::dirList *d; } backupArgs; + typedef struct + { + std::string to, from, dev; + zipFile z; + unzFile unz; + bool cleanup = false; + uint64_t offset = 0, fileSize = 0; + ui::progBar *prog; + threadStatus *thrdStatus; + Mutex arglck = 0; + void argLock() { mutexLock(&arglck); } + void argUnlock() { mutexUnlock(&arglck); } + } copyArgs; + + copyArgs *copyArgsCreate(const std::string& from, const std::string& to, const std::string& dev, zipFile z, unzFile unz, bool _cleanup); + void copyArgsDestroy(copyArgs *c); + //Take a pointer to backupArgs^ void createNewBackup(void *a); void overwriteBackup(void *a); diff --git a/inc/fsthrd.h b/inc/fsthrd.h new file mode 100644 index 0000000..0c72e62 --- /dev/null +++ b/inc/fsthrd.h @@ -0,0 +1,14 @@ +#pragma once + +/*Threaded functions for copying files. + file.cpp has wrapper functions for these. + No need to call directly.*/ +namespace fs +{ + void _fileDrawFunc(void *a); + void copyfile_t(void *a); + void copyFileCommit_t(void *a); + void copyDirToZip_t(void *a); + void copyZipToDir_t(void *a); + void closeZip_t(void *a); +} diff --git a/inc/ui.h b/inc/ui.h index 122b73f..4fd0831 100644 --- a/inc/ui.h +++ b/inc/ui.h @@ -13,6 +13,7 @@ #include "ui/usr.h" #include "ui/ttl.h" #include "ui/sett.h" +#include "ui/ext.h" #include "ui/fm.h" #include "ui/ttlview.h" #include "ui/thrdProc.h" diff --git a/inc/ui/ext.h b/inc/ui/ext.h new file mode 100644 index 0000000..5785572 --- /dev/null +++ b/inc/ui/ext.h @@ -0,0 +1,10 @@ +#pragma once + +namespace ui +{ + extern ui::menu *extMenu; + void extInit(); + void extExit(); + void extUpdate(); + void extDraw(SDL_Texture *target); +} diff --git a/inc/ui/uistr.h b/inc/ui/uistr.h index 45303ad..c27300b 100644 --- a/inc/ui/uistr.h +++ b/inc/ui/uistr.h @@ -16,7 +16,7 @@ namespace ui //Strings for extras menu extern std::string exMenuStr[11]; //Strings for options menu - extern std::string optMenuStr[16]; + extern std::string optMenuStr[17]; //Strings for the holding thing extern std::string holdingText[3]; //Strings for sort type diff --git a/inc/util.h b/inc/util.h index 8827027..82c6625 100644 --- a/inc/util.h +++ b/inc/util.h @@ -93,6 +93,6 @@ namespace util Result accountDeleteUser(AccountUid *uid); void setCPU(uint32_t hz); - void checkForUpdate(); + void checkForUpdate(void *a); } #endif // UTIL_H diff --git a/src/file.cpp b/src/file.cpp index d9a79fe..f0f5c4b 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -3,11 +3,8 @@ #include #include #include -#include #include #include -#include -#include #include #include "file.h" @@ -16,8 +13,6 @@ #include "gfx.h" #include "data.h" -#define BUFF_SIZE 0xC0000 - static std::string wd; static std::vector pathFilter; @@ -26,21 +21,7 @@ static FSFILE *debLog; static FsFileSystem sv; -typedef struct -{ - std::string to, from, dev; - zipFile z; - unzFile unz; - bool cleanup = false; - uint64_t offset = 0, fileSize = 0; - ui::progBar *prog; - threadStatus *thrdStatus; - Mutex arglck = 0; - void argLock() { mutexLock(&arglck); } - void argUnlock() { mutexUnlock(&arglck); } -} copyArgs; - -static copyArgs *copyArgsCreate(const std::string& from, const std::string& to, const std::string& dev, zipFile z, unzFile unz, bool _cleanup) +fs::copyArgs *fs::copyArgsCreate(const std::string& from, const std::string& to, const std::string& dev, zipFile z, unzFile unz, bool _cleanup) { copyArgs *ret = new copyArgs; ret->to = to; @@ -55,7 +36,7 @@ static copyArgs *copyArgsCreate(const std::string& from, const std::string& to, return ret; } -static void copyArgsDestroy(copyArgs *c) +void fs::copyArgsDestroy(copyArgs *c) { delete c->prog; delete c; @@ -80,7 +61,7 @@ static struct } } sortDirList; -static void mkdirRec(const std::string& _p) +void fs::mkdirRec(const std::string& _p) { //skip first slash size_t pos = _p.find('/', 0) + 1; @@ -91,7 +72,7 @@ static void mkdirRec(const std::string& _p) } } -static inline bool commitToDevice(const std::string& dev) +bool fs::commitToDevice(const std::string& dev) { bool ret = true; Result res = fsdevCommitDevice(dev.c_str()); @@ -104,34 +85,6 @@ static inline bool commitToDevice(const std::string& dev) return ret; } -static uint64_t getJournalSize(const data::titleInfo *t) -{ - uint64_t journalSize = 0; - switch(data::curData.saveInfo.save_data_type) - { - case FsSaveDataType_Account: - journalSize = t->nacp.user_account_save_data_journal_size; - break; - - case FsSaveDataType_Device: - journalSize = t->nacp.device_save_data_journal_size; - break; - - case FsSaveDataType_Bcat: - journalSize = t->nacp.bcat_delivery_cache_storage_size; - break; - - case FsSaveDataType_Cache: - journalSize = t->nacp.cache_storage_journal_size; - break; - - default: - journalSize = BUFF_SIZE; - break; - } - return journalSize; -} - void fs::init() { if(fs::fileExists("sdmc:/switch/jksv_dir.txt")) @@ -365,81 +318,7 @@ int fs::dataFile::getNextValueInt() return ret; } -//Todo: Weird flickering? -static void _fileDrawFunc(void *a) -{ - threadInfo *t = (threadInfo *)a; - if(!t->finished) - { - copyArgs *c = (copyArgs *)t->argPtr; - std::string tmp; - t->status->getStatus(tmp); - c->argLock(); - c->prog->draw(tmp); - c->argUnlock(); - } -} - -static void copyfile_t(void *a) -{ - threadInfo *t = (threadInfo *)a; - copyArgs *args = (copyArgs *)t->argPtr; - t->status->setStatus("Copying '" + args->from + "'..."); - - uint8_t *buff = new uint8_t[BUFF_SIZE]; - if(data::config["directFsCmd"]) - { - FSFILE *in = fsfopen(args->from.c_str(), FsOpenMode_Read); - FSFILE *out = fsfopen(args->to.c_str(), FsOpenMode_Write); - - if(!in || !out) - { - fsfclose(in); - fsfclose(out); - t->finished = true; - return; - } - size_t readIn = 0; - while((readIn = fsfread(buff, 1, BUFF_SIZE, in)) > 0) - { - fsfwrite(buff, 1, readIn, out); - args->argLock(); - args->offset = in->offset; - args->prog->update(args->offset); - args->argUnlock(); - } - fsfclose(in); - fsfclose(out); - } - else - { - FILE *in = fopen(args->from.c_str(), "rb"); - FILE *out = fopen(args->to.c_str(), "wb"); - if(!in || !out) - { - fclose(in); - fclose(out); - t->finished = true; - return; - } - - size_t readIn = 0; - while((readIn = fread(buff, 1, BUFF_SIZE, in)) > 0) - { - fwrite(buff, 1, readIn, out); - args->argLock(); - args->offset = ftell(in); - args->prog->update(args->offset); - args->argUnlock(); - } - fclose(in); - fclose(out); - } - delete[] buff; - copyArgsDestroy(args); - t->finished = true; -} - +//Wrapper functions to use functions from `fsthrd.cpp` void fs::copyFile(const std::string& from, const std::string& to) { copyArgs *send = copyArgsCreate(from, to, "", NULL, NULL, false); @@ -448,93 +327,6 @@ void fs::copyFile(const std::string& from, const std::string& to) ui::newThread(copyfile_t, send, _fileDrawFunc); } -void copyFileCommit_t(void *a) -{ - threadInfo *t = (threadInfo *)a; - copyArgs *args = (copyArgs *)t->argPtr; - data::titleInfo *info = data::getTitleInfoByTID(data::curData.saveID); - t->status->setStatus("Copying '" + args->from + "'..."); - - uint64_t journalSize = getJournalSize(info), writeCount = 0; - uint8_t *buff = new uint8_t[BUFF_SIZE]; - - if(data::config["directFsCmd"]) - { - FSFILE *in = fsfopen(args->from.c_str(), FsOpenMode_Read); - FSFILE *out = fsfopen(args->to.c_str(), FsOpenMode_Write); - - if(!in || !out) - { - fsfclose(in); - fsfclose(out); - t->finished = true; - return; - } - - size_t readIn = 0; - while((readIn = fsfread(buff, 1, BUFF_SIZE, in)) > 0) - { - fsfwrite(buff, 1, readIn, out); - writeCount += readIn; - if(writeCount >= (journalSize - 0x100000)) - { - writeCount = 0; - fsfclose(out); - if(!commitToDevice(args->dev)) - break; - - out = fsfopen(args->to.c_str(), FsOpenMode_Write | FsOpenMode_Append); - } - args->argLock(); - args->offset = out->offset; - args->prog->update(args->offset); - args->argUnlock(); - } - fsfclose(in); - fsfclose(out); - } - else - { - FILE *in = fopen(args->from.c_str(), "rb"); - FILE *out = fopen(args->to.c_str(), "wb"); - - if(!in || !out) - { - fclose(in); - fclose(out); - t->finished = true; - return; - } - - size_t readIn = 0; - while((readIn = fread(buff, 1, BUFF_SIZE, in)) > 0) - { - fwrite(buff, 1, readIn, out); - writeCount += readIn; - if(writeCount >= (journalSize - 0x100000)) - { - writeCount = 0; - fclose(out); - if(!commitToDevice(args->dev)) - break; - - out = fopen(args->to.c_str(), "ab"); - } - args->argLock(); - args->offset = ftell(out); - args->prog->update(args->offset); - args->argUnlock(); - } - fclose(in); - fclose(out); - } - delete[] buff; - - commitToDevice(args->dev.c_str()); - copyArgsDestroy(args); - t->finished = true; -} - void fs::copyFileCommit(const std::string& from, const std::string& to, const std::string& dev) { copyArgs *send = copyArgsCreate(from, to, dev, NULL, NULL, false); @@ -569,88 +361,6 @@ void fs::copyDirToDir(const std::string& from, const std::string& to) } } -void closeZip_t(void *a) -{ - threadInfo *t = (threadInfo *)a; - zipFile z = t->argPtr; - zipClose(z, NULL); - t->finished = true; -} - -void copyDirToZip_t(void *a) -{ - threadInfo *t = (threadInfo *)a; - copyArgs *args = (copyArgs *)t->argPtr; - - t->status->setStatus("Opening " + args->from + "..."); - fs::dirList *list = new fs::dirList(args->from); - - unsigned listTotal = list->getCount(); - for(unsigned i = 0; i < listTotal; i++) - { - std::string itm = list->getItem(i); - if(fs::pathIsFiltered(args->from + itm)) - continue; - - if(list->isDir(i)) - { - std::string newFrom = args->from + itm + "/"; - //Fake thread and new args to point to src thread stuff - //This wouldn't work spawning a new thread. - threadInfo *tmpThread = new threadInfo; - tmpThread->status = t->status; - copyArgs *tmpArgs = new copyArgs; - tmpArgs->from = newFrom; - tmpArgs->prog = args->prog; - tmpArgs->z = args->z; - tmpArgs->cleanup = false; - tmpThread->argPtr = tmpArgs; - copyDirToZip_t(tmpThread); - delete tmpArgs; - delete tmpThread; - } - else - { - zip_fileinfo inf = {0}; - std::string filename = args->from + itm; - size_t devPos = filename.find_first_of('/') + 1; - t->status->setStatus("Adding '" + itm + "' to ZIP."); - int zOpenFile = zipOpenNewFileInZip64(args->z, filename.substr(devPos, filename.length()).c_str(), &inf, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION, 0); - if(zOpenFile == ZIP_OK) - { - std::string fullFrom = args->from + itm; - args->offset = 0; - args->fileSize = fs::fsize(fullFrom); - args->prog->setMax(args->fileSize); - args->prog->update(0); - FILE *cpy = fopen(fullFrom.c_str(), "rb"); - size_t readIn = 0; - uint8_t *buff = new uint8_t[BUFF_SIZE]; - while((readIn = fread(buff, 1, BUFF_SIZE, cpy)) > 0) - { - zipWriteInFileInZip(args->z, buff, readIn); - args->offset += readIn; - args->prog->update(args->offset); - } - delete[] buff; - fclose(cpy); - zipCloseFileInZip(args->z); - } - } - } - delete list; - if(args->cleanup) - { - if(data::config["ovrClk"]) - util::setCPU(1224000000); - ui::newThread(closeZip_t, args->z, NULL); - delete args->prog; - delete args; - } - - t->finished = true; -} - void fs::copyDirToZip(const std::string& from, zipFile to) { if(data::config["ovrClk"]) @@ -662,97 +372,6 @@ void fs::copyDirToZip(const std::string& from, zipFile to) ui::newThread(copyDirToZip_t, send, _fileDrawFunc); } -void copyZipToDir_t(void *a) -{ - threadInfo *t = (threadInfo *)a; - copyArgs *args = (copyArgs *)t->argPtr; - - data::titleInfo *tinfo = data::getTitleInfoByTID(data::curData.saveID); - uint64_t journalSize = getJournalSize(tinfo), writeCount = 0; - char filename[FS_MAX_PATH]; - uint8_t *buff = new uint8_t[BUFF_SIZE]; - int readIn = 0; - unz_file_info64 info; - if(unzGoToFirstFile(args->unz) == UNZ_OK) - { - do - { - unzGetCurrentFileInfo64(args->unz, &info, filename, FS_MAX_PATH, NULL, 0, NULL, 0); - if(unzOpenCurrentFile(args->unz) == UNZ_OK) - { - t->status->setStatus("Copying '" + std::string(filename) + "'..."); - std::string path = args->to + filename; - mkdirRec(path.substr(0, path.find_last_of('/') + 1)); - - args->fileSize = info.uncompressed_size; - args->offset = 0.0f; - args->prog->setMax(args->fileSize); - size_t done = 0; - if(data::config["directFsCmd"]) - { - FSFILE *out = fsfopen(path.c_str(), FsOpenMode_Write); - while((readIn = unzReadCurrentFile(args->unz, buff, BUFF_SIZE)) > 0) - { - done += readIn; - writeCount += readIn; - args->offset += readIn; - args->prog->update(args->offset); - fsfwrite(buff, 1, readIn, out); - if(writeCount >= (journalSize - 0x100000)) - { - writeCount = 0; - fsfclose(out); - if(!commitToDevice(args->dev.c_str())) - break; - - out = fsfopen(path.c_str(), FsOpenMode_Write | FsOpenMode_Append); - } - } - fsfclose(out); - } - else - { - FILE *out = fopen(path.c_str(), "wb"); - - while((readIn = unzReadCurrentFile(args->unz, buff, BUFF_SIZE)) > 0) - { - done += readIn; - writeCount += readIn; - args->offset += readIn; - args->prog->update(args->offset); - fwrite(buff, 1, readIn, out); - if(writeCount >= (journalSize - 0x100000)) - { - writeCount = 0; - fclose(out); - if(!commitToDevice(args->dev.c_str())) - break; - - out = fopen(path.c_str(), "ab"); - } - } - fclose(out); - } - unzCloseCurrentFile(args->unz); - commitToDevice(args->dev.c_str()); - } - } - while(unzGoToNextFile(args->unz) != UNZ_END_OF_LIST_OF_FILE); - } - else - ui::showPopMessage(POP_FRAME_DEFAULT, "ZIP file is empty!"); - - if(args->cleanup) - { - unzClose(args->unz); - copyArgsDestroy(args); - if(data::config["ovrClk"]) - util::setCPU(1224000000); - } - delete[] buff; - t->finished = true; -} - void fs::copyZipToDir(unzFile unz, const std::string& to, const std::string& dev) { if(data::config["ovrClk"]) @@ -764,6 +383,17 @@ void fs::copyZipToDir(unzFile unz, const std::string& to, const std::string& dev ui::newThread(copyZipToDir_t, send, _fileDrawFunc); } +bool fs::dirNotEmpty(const std::string& _dir) +{ + fs::dirList tmp(_dir); + return tmp.getCount() > 0; +} + +bool fs::zipNotEmpty(unzFile unzip) +{ + return unzGoToFirstFile(unzip) == UNZ_OK; +} + void fs::copyDirToDirCommit(const std::string& from, const std::string& to, const std::string& dev) { dirList list(from); @@ -1088,16 +718,26 @@ void fs::restoreBackup(void *a) if(d->isDir(ind)) { - fs::wipeSave(); std::string fromPath = util::generatePathByTID(data::curData.saveID) + itemName + "/"; - fs::copyDirToDirCommit(fromPath, "sv:/", "sv"); + if(fs::dirNotEmpty(fromPath)) + { + fs::wipeSave(); + fs::copyDirToDirCommit(fromPath, "sv:/", "sv"); + } + else + ui::showPopMessage(POP_FRAME_DEFAULT, "Folder is empty!"); } else if(!d->isDir(ind) && d->getItemExt(ind) == "zip") { - fs::wipeSave(); std::string path = util::generatePathByTID(data::curData.saveID) + itemName; unzFile unz = unzOpen64(path.c_str()); - fs::copyZipToDir(unz, "sv:/", "sv"); + if(unz && fs::zipNotEmpty(unz)) + { + fs::wipeSave(); + fs::copyZipToDir(unz, "sv:/", "sv"); + } + else + ui::showPopMessage(POP_FRAME_DEFAULT, "ZIP is empty!"); } else { diff --git a/src/fsthrd.cpp b/src/fsthrd.cpp new file mode 100644 index 0000000..69fc3ae --- /dev/null +++ b/src/fsthrd.cpp @@ -0,0 +1,359 @@ +#include + +#include "file.h" +#include "util.h" + +static uint64_t getJournalSize(const data::titleInfo *t) +{ + uint64_t journalSize = 0; + switch(data::curData.saveInfo.save_data_type) + { + case FsSaveDataType_Account: + journalSize = t->nacp.user_account_save_data_journal_size; + break; + + case FsSaveDataType_Device: + journalSize = t->nacp.device_save_data_journal_size; + break; + + case FsSaveDataType_Bcat: + journalSize = t->nacp.bcat_delivery_cache_storage_size; + break; + + case FsSaveDataType_Cache: + journalSize = t->nacp.cache_storage_journal_size; + break; + + default: + journalSize = BUFF_SIZE; + break; + } + return journalSize; +} + +//Todo: Weird flickering? +void fs::_fileDrawFunc(void *a) +{ + threadInfo *t = (threadInfo *)a; + if(!t->finished) + { + copyArgs *c = (copyArgs *)t->argPtr; + std::string tmp; + t->status->getStatus(tmp); + c->argLock(); + c->prog->draw(tmp); + c->argUnlock(); + } +} + +void fs::copyfile_t(void *a) +{ + threadInfo *t = (threadInfo *)a; + copyArgs *args = (copyArgs *)t->argPtr; + t->status->setStatus("Copying '" + args->from + "'..."); + + uint8_t *buff = new uint8_t[BUFF_SIZE]; + if(data::config["directFsCmd"]) + { + FSFILE *in = fsfopen(args->from.c_str(), FsOpenMode_Read); + FSFILE *out = fsfopen(args->to.c_str(), FsOpenMode_Write); + + if(!in || !out) + { + fsfclose(in); + fsfclose(out); + t->finished = true; + return; + } + size_t readIn = 0; + while((readIn = fsfread(buff, 1, BUFF_SIZE, in)) > 0) + { + fsfwrite(buff, 1, readIn, out); + args->argLock(); + args->offset = in->offset; + args->prog->update(args->offset); + args->argUnlock(); + } + fsfclose(in); + fsfclose(out); + } + else + { + FILE *in = fopen(args->from.c_str(), "rb"); + FILE *out = fopen(args->to.c_str(), "wb"); + if(!in || !out) + { + fclose(in); + fclose(out); + t->finished = true; + return; + } + + size_t readIn = 0; + while((readIn = fread(buff, 1, BUFF_SIZE, in)) > 0) + { + fwrite(buff, 1, readIn, out); + args->argLock(); + args->offset = ftell(in); + args->prog->update(args->offset); + args->argUnlock(); + } + fclose(in); + fclose(out); + } + delete[] buff; + copyArgsDestroy(args); + t->finished = true; +} + +void fs::copyFileCommit_t(void *a) +{ + threadInfo *t = (threadInfo *)a; + copyArgs *args = (copyArgs *)t->argPtr; + data::titleInfo *info = data::getTitleInfoByTID(data::curData.saveID); + t->status->setStatus("Copying '" + args->from + "'..."); + + uint64_t journalSize = getJournalSize(info), writeCount = 0; + uint8_t *buff = new uint8_t[BUFF_SIZE]; + + if(data::config["directFsCmd"]) + { + FSFILE *in = fsfopen(args->from.c_str(), FsOpenMode_Read); + FSFILE *out = fsfopen(args->to.c_str(), FsOpenMode_Write); + + if(!in || !out) + { + fsfclose(in); + fsfclose(out); + t->finished = true; + return; + } + + size_t readIn = 0; + while((readIn = fsfread(buff, 1, BUFF_SIZE, in)) > 0) + { + fsfwrite(buff, 1, readIn, out); + writeCount += readIn; + if(writeCount >= (journalSize - 0x100000)) + { + writeCount = 0; + fsfclose(out); + if(!commitToDevice(args->dev)) + break; + + out = fsfopen(args->to.c_str(), FsOpenMode_Write | FsOpenMode_Append); + } + args->argLock(); + args->offset = out->offset; + args->prog->update(args->offset); + args->argUnlock(); + } + fsfclose(in); + fsfclose(out); + } + else + { + FILE *in = fopen(args->from.c_str(), "rb"); + FILE *out = fopen(args->to.c_str(), "wb"); + + if(!in || !out) + { + fclose(in); + fclose(out); + t->finished = true; + return; + } + + size_t readIn = 0; + while((readIn = fread(buff, 1, BUFF_SIZE, in)) > 0) + { + fwrite(buff, 1, readIn, out); + writeCount += readIn; + if(writeCount >= (journalSize - 0x100000)) + { + writeCount = 0; + fclose(out); + if(!commitToDevice(args->dev)) + break; + + out = fopen(args->to.c_str(), "ab"); + } + args->argLock(); + args->offset = ftell(out); + args->prog->update(args->offset); + args->argUnlock(); + } + fclose(in); + fclose(out); + } + delete[] buff; + + commitToDevice(args->dev.c_str()); + copyArgsDestroy(args); + t->finished = true; +} + +void fs::copyDirToZip_t(void *a) +{ + threadInfo *t = (threadInfo *)a; + copyArgs *args = (copyArgs *)t->argPtr; + + t->status->setStatus("Opening " + args->from + "..."); + fs::dirList *list = new fs::dirList(args->from); + + unsigned listTotal = list->getCount(); + for(unsigned i = 0; i < listTotal; i++) + { + std::string itm = list->getItem(i); + if(fs::pathIsFiltered(args->from + itm)) + continue; + + if(list->isDir(i)) + { + std::string newFrom = args->from + itm + "/"; + //Fake thread and new args to point to src thread stuff + //This wouldn't work spawning a new thread. + threadInfo tmpThread; + tmpThread.status = t->status; + copyArgs tmpArgs; + tmpArgs.from = newFrom; + tmpArgs.prog = args->prog; + tmpArgs.z = args->z; + tmpArgs.cleanup = false; + tmpThread.argPtr = &tmpArgs; + copyDirToZip_t(&tmpThread); + } + else + { + zip_fileinfo inf = {0}; + std::string filename = args->from + itm; + size_t devPos = filename.find_first_of('/') + 1; + t->status->setStatus("Adding '" + itm + "' to ZIP."); + int zOpenFile = zipOpenNewFileInZip64(args->z, filename.substr(devPos, filename.length()).c_str(), &inf, NULL, 0, NULL, 0, NULL, Z_DEFLATED, Z_DEFAULT_COMPRESSION, 0); + if(zOpenFile == ZIP_OK) + { + std::string fullFrom = args->from + itm; + args->offset = 0; + args->fileSize = fs::fsize(fullFrom); + args->prog->setMax(args->fileSize); + args->prog->update(0); + FILE *cpy = fopen(fullFrom.c_str(), "rb"); + size_t readIn = 0; + uint8_t *buff = new uint8_t[BUFF_SIZE]; + while((readIn = fread(buff, 1, BUFF_SIZE, cpy)) > 0) + { + zipWriteInFileInZip(args->z, buff, readIn); + args->offset += readIn; + args->prog->update(args->offset); + } + delete[] buff; + fclose(cpy); + zipCloseFileInZip(args->z); + } + } + } + delete list; + if(args->cleanup) + { + if(data::config["ovrClk"]) + util::setCPU(1224000000); + ui::newThread(closeZip_t, args->z, NULL); + delete args->prog; + delete args; + } + t->finished = true; +} + +void fs::closeZip_t(void *a) +{ + threadInfo *t = (threadInfo *)a; + zipFile z = t->argPtr; + zipClose(z, NULL); + t->finished = true; +} + +void fs::copyZipToDir_t(void *a) +{ + threadInfo *t = (threadInfo *)a; + copyArgs *args = (copyArgs *)t->argPtr; + + data::titleInfo *tinfo = data::getTitleInfoByTID(data::curData.saveID); + uint64_t journalSize = getJournalSize(tinfo), writeCount = 0; + char filename[FS_MAX_PATH]; + uint8_t *buff = new uint8_t[BUFF_SIZE]; + int readIn = 0; + unz_file_info64 info; + do + { + unzGetCurrentFileInfo64(args->unz, &info, filename, FS_MAX_PATH, NULL, 0, NULL, 0); + if(unzOpenCurrentFile(args->unz) == UNZ_OK) + { + t->status->setStatus("Copying '" + std::string(filename) + "'..."); + std::string path = args->to + filename; + mkdirRec(path.substr(0, path.find_last_of('/') + 1)); + + args->fileSize = info.uncompressed_size; + args->offset = 0.0f; + args->prog->setMax(args->fileSize); + size_t done = 0; + if(data::config["directFsCmd"]) + { + FSFILE *out = fsfopen(path.c_str(), FsOpenMode_Write); + while((readIn = unzReadCurrentFile(args->unz, buff, BUFF_SIZE)) > 0) + { + done += readIn; + writeCount += readIn; + args->offset += readIn; + args->prog->update(args->offset); + fsfwrite(buff, 1, readIn, out); + if(writeCount >= (journalSize - 0x100000)) + { + writeCount = 0; + fsfclose(out); + if(!commitToDevice(args->dev.c_str())) + break; + + out = fsfopen(path.c_str(), FsOpenMode_Write | FsOpenMode_Append); + } + } + fsfclose(out); + } + else + { + FILE *out = fopen(path.c_str(), "wb"); + + while((readIn = unzReadCurrentFile(args->unz, buff, BUFF_SIZE)) > 0) + { + done += readIn; + writeCount += readIn; + args->offset += readIn; + args->prog->update(args->offset); + fwrite(buff, 1, readIn, out); + if(writeCount >= (journalSize - 0x100000)) + { + writeCount = 0; + fclose(out); + if(!commitToDevice(args->dev.c_str())) + break; + + out = fopen(path.c_str(), "ab"); + } + } + fclose(out); + } + unzCloseCurrentFile(args->unz); + commitToDevice(args->dev.c_str()); + } + } + while(unzGoToNextFile(args->unz) != UNZ_END_OF_LIST_OF_FILE); + + if(args->cleanup) + { + unzClose(args->unz); + copyArgsDestroy(args); + if(data::config["ovrClk"]) + util::setCPU(1224000000); + } + delete[] buff; + t->finished = true; +} diff --git a/src/ui.cpp b/src/ui.cpp index 15fe6a0..143fbaf 100644 --- a/src/ui.cpp +++ b/src/ui.cpp @@ -162,6 +162,7 @@ void ui::init() ui::usrInit(); ui::ttlInit(); ui::settInit(); + ui::extInit(); popMessages = new ui::popMessageMngr; threadMngr = new ui::threadProcMngr; @@ -176,6 +177,7 @@ void ui::exit() ui::usrExit(); ui::ttlExit(); ui::settExit(); + ui::extExit(); delete popMessages; delete threadMngr; @@ -241,7 +243,7 @@ void ui::drawUI() if(ui::usrMenu->getSelected() == settPos || ui::mstate == OPT_MNU) ui::settDraw(rightPanel); else if(usrMenu->getSelected() == extPos || ui::mstate == EX_MNU) - gfx::drawTextf(rightPanel, 24, 32, 32, &ui::txtCont, "PLACE HOLDER"); + ui::extDraw(rightPanel); else ui::ttlDraw(rightPanel); @@ -273,25 +275,19 @@ bool ui::runApp() switch(ui::mstate) { case USR_SEL: - usrUpdate(); + ui::usrUpdate(); break; case TTL_SEL: - ttlUpdate(); + ui::ttlUpdate(); break; case OPT_MNU: - settUpdate(); + ui::settUpdate(); break; case EX_MNU: - /*extMenu.update(); - if(down & HidNpadButton_B) - { - ui::changeState(USR_SEL); - mainMenu.setActive(true); - extMenu.setActive(false); - }*/ + ui::extUpdate(); break; } } diff --git a/src/ui/ext.cpp b/src/ui/ext.cpp new file mode 100644 index 0000000..a6a8871 --- /dev/null +++ b/src/ui/ext.cpp @@ -0,0 +1,64 @@ +#include +#include + +#include "ui.h" +#include "file.h" + +ui::menu *ui::extMenu; + +static void extMenuCallback(void *a) +{ + switch(ui::padKeysDown()) + { + case HidNpadButton_B: + ui::extMenu->setActive(false); + ui::usrMenu->setActive(true); + ui::changeState(USR_SEL); + break; + } +} + +static void _delUpdate(void *a) +{ + threadInfo *t = (threadInfo *)a; + t->status->setStatus("Deleting update from NAND..."); + FsFileSystem sys; + fsOpenBisFileSystem(&sys, FsBisPartitionId_System, ""); + fsdevMountDevice("sys", sys); + fs::delDir("sys:/Contents/placehld/"); + fsdevUnmountDevice("sys"); + t->finished = true; +} + +static void extMenuOptRemoveUpdate(void *a) +{ + ui::newThread(_delUpdate, NULL, NULL); +} + +void ui::extInit() +{ + ui::extMenu = new ui::menu; + ui::extMenu->setParams(32, 32, 1016, 24, 5); + ui::extMenu->setCallback(extMenuCallback, NULL); + ui::extMenu->setActive(false); + for(unsigned i = 0; i < 11; i++) + ui::extMenu->addOpt(NULL, ui::exMenuStr[i]); + + //Del update + ui::extMenu->optAddButtonEvent(5, HidNpadButton_A, extMenuOptRemoveUpdate, NULL); +} + +void ui::extExit() +{ + delete ui::extMenu; +} + +void ui::extUpdate() +{ + ui::extMenu->update(); +} + +void ui::extDraw(SDL_Texture *target) +{ + ui::extMenu->draw(target, &ui::txtCont, true); +} diff --git a/src/ui/miscui.cpp b/src/ui/miscui.cpp index b13c87a..a971b0a 100644 --- a/src/ui/miscui.cpp +++ b/src/ui/miscui.cpp @@ -230,7 +230,6 @@ void ui::menu::draw(SDL_Texture *target, const SDL_Color *textClr, bool drawText gfx::texDrawStretch(target, opt[i].icn, x + 20, (y + (rH / 2 - fSize / 2)) + (i * rH), dW, dH); } - } } diff --git a/src/ui/sett.cpp b/src/ui/sett.cpp index 46dcf88..0a0dbae 100644 --- a/src/ui/sett.cpp +++ b/src/ui/sett.cpp @@ -4,6 +4,7 @@ #include "ui.h" #include "file.h" #include "sett.h" +#include "util.h" ui::menu *ui::settMenu; @@ -50,65 +51,69 @@ static void toggleOpt(void *a) break; case 1: - toggleBool(data::config["incDev"]); + ui::newThread(util::checkForUpdate, NULL, NULL); break; case 2: - toggleBool(data::config["autoBack"]); + toggleBool(data::config["incDev"]); break; case 3: - toggleBool(data::config["ovrClk"]); + toggleBool(data::config["autoBack"]); break; case 4: - toggleBool(data::config["holdDel"]); + toggleBool(data::config["ovrClk"]); break; case 5: - toggleBool(data::config["holdRest"]); + toggleBool(data::config["holdDel"]); break; case 6: - toggleBool(data::config["holdOver"]); + toggleBool(data::config["holdRest"]); break; case 7: - toggleBool(data::config["forceMount"]); + toggleBool(data::config["holdOver"]); break; case 8: - toggleBool(data::config["accSysSave"]); + toggleBool(data::config["forceMount"]); break; case 9: - toggleBool(data::config["sysSaveWrite"]); + toggleBool(data::config["accSysSave"]); break; case 10: - toggleBool(data::config["directFsCmd"]); + toggleBool(data::config["sysSaveWrite"]); break; case 11: - toggleBool(data::config["zip"]); + toggleBool(data::config["directFsCmd"]); break; case 12: - toggleBool(data::config["langOverride"]); + toggleBool(data::config["zip"]); break; case 13: - toggleBool(data::config["trashBin"]); + toggleBool(data::config["langOverride"]); break; case 14: + toggleBool(data::config["trashBin"]); + break; + + case 15: if(++data::sortType > 2) data::sortType = 0; data::loadUsersTitles(false); ui::refreshAllViews(); break; - case 15: + case 16: ui::animScale += 0.5f; if(ui::animScale > 8) ui::animScale = 1; @@ -118,24 +123,24 @@ static void toggleOpt(void *a) static void updateMenuText() { - ui::settMenu->editOpt(1, NULL, ui::optMenuStr[1] + getBoolText(data::config["incDev"])); - ui::settMenu->editOpt(2, NULL, ui::optMenuStr[2] + getBoolText(data::config["autoBack"])); - ui::settMenu->editOpt(3, NULL, ui::optMenuStr[3] + getBoolText(data::config["ovrClk"])); - ui::settMenu->editOpt(4, NULL, ui::optMenuStr[4] + getBoolText(data::config["holdDel"])); - ui::settMenu->editOpt(5, NULL, ui::optMenuStr[5] + getBoolText(data::config["holdRest"])); - ui::settMenu->editOpt(6, NULL, ui::optMenuStr[6] + getBoolText(data::config["holdOver"])); - ui::settMenu->editOpt(7, NULL, ui::optMenuStr[7] + getBoolText(data::config["forceMount"])); - ui::settMenu->editOpt(8, NULL, ui::optMenuStr[8] + getBoolText(data::config["accSysSave"])); - ui::settMenu->editOpt(9, NULL, ui::optMenuStr[9] + getBoolText(data::config["sysSaveWrite"])); - ui::settMenu->editOpt(10, NULL, ui::optMenuStr[10] + getBoolText(data::config["directFsCmd"])); - ui::settMenu->editOpt(11, NULL, ui::optMenuStr[11] + getBoolText(data::config["zip"])); - ui::settMenu->editOpt(12, NULL, ui::optMenuStr[12] + getBoolText(data::config["langOverride"])); - ui::settMenu->editOpt(13, NULL, ui::optMenuStr[13] + getBoolText(data::config["trashBin"])); - ui::settMenu->editOpt(14, NULL, ui::optMenuStr[14] + ui::sortString[data::sortType]); + ui::settMenu->editOpt(2, NULL, ui::optMenuStr[2] + getBoolText(data::config["incDev"])); + ui::settMenu->editOpt(3, NULL, ui::optMenuStr[3] + getBoolText(data::config["autoBack"])); + ui::settMenu->editOpt(4, NULL, ui::optMenuStr[4] + getBoolText(data::config["ovrClk"])); + ui::settMenu->editOpt(5, NULL, ui::optMenuStr[5] + getBoolText(data::config["holdDel"])); + ui::settMenu->editOpt(6, NULL, ui::optMenuStr[6] + getBoolText(data::config["holdRest"])); + ui::settMenu->editOpt(7, NULL, ui::optMenuStr[7] + getBoolText(data::config["holdOver"])); + ui::settMenu->editOpt(8, NULL, ui::optMenuStr[8] + getBoolText(data::config["forceMount"])); + ui::settMenu->editOpt(9, NULL, ui::optMenuStr[9] + getBoolText(data::config["accSysSave"])); + ui::settMenu->editOpt(10, NULL, ui::optMenuStr[10] + getBoolText(data::config["sysSaveWrite"])); + ui::settMenu->editOpt(11, NULL, ui::optMenuStr[11] + getBoolText(data::config["directFsCmd"])); + ui::settMenu->editOpt(12, NULL, ui::optMenuStr[12] + getBoolText(data::config["zip"])); + ui::settMenu->editOpt(13, NULL, ui::optMenuStr[13] + getBoolText(data::config["langOverride"])); + ui::settMenu->editOpt(14, NULL, ui::optMenuStr[14] + getBoolText(data::config["trashBin"])); + ui::settMenu->editOpt(15, NULL, ui::optMenuStr[15] + ui::sortString[data::sortType]); char tmp[16]; sprintf(tmp, "%.1f", ui::animScale); - ui::settMenu->editOpt(15, NULL, ui::optMenuStr[15] + std::string(tmp)); + ui::settMenu->editOpt(16, NULL, ui::optMenuStr[16] + std::string(tmp)); } void ui::settInit() @@ -147,7 +152,7 @@ void ui::settInit() optHelpX = 1220 - gfx::getTextWidth(ui::optHelp.c_str(), 18); - for(unsigned i = 0; i < 16; i++) + for(unsigned i = 0; i < 17; i++) { ui::settMenu->addOpt(NULL, ui::optMenuStr[i]); ui::settMenu->optAddButtonEvent(i, HidNpadButton_A, toggleOpt, NULL); diff --git a/src/ui/ttl.cpp b/src/ui/ttl.cpp index 068085e..0340a50 100644 --- a/src/ui/ttl.cpp +++ b/src/ui/ttl.cpp @@ -5,7 +5,7 @@ #include "file.h" #include "util.h" -int ttlHelpX = 0, fldHelpWidth = 0; +static int ttlHelpX = 0, fldHelpWidth = 0; static std::vector ttlViews; static ui::menu *ttlOpts, *fldMenu; static ui::slideOutPanel *ttlOptsPanel, *infoPanel, *fldPanel;//There's no reason to have a separate folder section @@ -344,7 +344,7 @@ void ui::ttlInit() ttlOpts->setActive(false); fldMenu = new ui::menu; - fldMenu->setParams(10, 32, fldHelpWidth + 44, 20, 6); + fldMenu->setParams(10, 32, fldHelpWidth + 44, 20, 7); fldMenu->setCallback(fldMenuCallback, NULL); fldMenu->setActive(false); diff --git a/src/ui/uistr.cpp b/src/ui/uistr.cpp index 9edf368..bc99da0 100644 --- a/src/ui/uistr.cpp +++ b/src/ui/uistr.cpp @@ -41,7 +41,7 @@ std::string ui::errorConnecting = "Error Connecting!"; std::string ui::noUpdate = "No updates available!"; std::string ui::advMenuStr[6] = { "Copy to ", "Delete", "Rename", "Make Dir", "Properties", "Close" }; std::string ui::exMenuStr[11] = { "SD to SD Browser", "BIS: PRODINFOF", "BIS: SAFE", "BIS: SYSTEM", "BIS: USER", "Remove Update", "Terminate Process", "Mount System Save", "Rescan Titles", "Mount Process RomFS", "Backup JKSV Folder" }; -std::string ui::optMenuStr[16] = { "Empty Trash Bin", "Include Device Saves: ", "AutoBackup: ", "Overclock: ", "Hold to Delete: ", "Hold to Restore: ", "Hold to Overwrite: ", "Force Mount: ", "Account Sys. Saves: ", "Write to Sys. Saves: ", "Direct FS Cmd: ", "Export to ZIP: ", "Language Override: ", "Enable Trash Bin: ", "Sort: ", "Animation Scale: "}; +std::string ui::optMenuStr[17] = { "Empty Trash Bin", "Check for Update", "Include Device Saves: ", "AutoBackup: ", "Overclock: ", "Hold to Delete: ", "Hold to Restore: ", "Hold to Overwrite: ", "Force Mount: ", "Account Sys. Saves: ", "Write to Sys. Saves: ", "Direct FS Cmd: ", "Export to ZIP: ", "Language Override: ", "Enable Trash Bin: ", "Sort: ", "Animation Scale: "}; std::string ui::holdingText[3] = { "(Hold) ", "(Keep Holding) ", "(Almost there!) " }; std::string ui::sortString[3] = { "Alphabetical", "Time Played", "Last Played" }; std::string ui::usrOptString[2] = { "Create Save Data", "Delete All User Saves" }; diff --git a/src/ui/usr.cpp b/src/ui/usr.cpp index 3c2c7e6..e219f9d 100644 --- a/src/ui/usr.cpp +++ b/src/ui/usr.cpp @@ -53,6 +53,7 @@ static void toEXT(void *a) { ui::changeState(EX_MNU); ui::usrMenu->setActive(false); + ui::extMenu->setActive(true); } static void usrOptCallback(void *a) @@ -331,7 +332,7 @@ void ui::usrInit() ext = util::createIconGeneric("Extras", 40); pos = usrMenu->addOpt(ext, "Extras"); - usrMenu->optAddButtonEvent(pos, HidNpadButton_A, NULL, NULL); + usrMenu->optAddButtonEvent(pos, HidNpadButton_A, toEXT, NULL); usrMenu->setOnChangeFunc(onMainChange); usrMenu->editParam(MENU_RECT_WIDTH, 126); diff --git a/src/util.cpp b/src/util.cpp index 2d80c5b..885be8e 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -10,6 +10,7 @@ #include "util.h" #include "ui.h" #include "curlfuncs.h" +#include "type.h" static const char verboten[] = { ',', '/', '\\', '<', '>', ':', '"', '|', '?', '*', '™', '©', '®'}; @@ -343,12 +344,15 @@ void util::setCPU(uint32_t hz) clkrstExit(); } -void util::checkForUpdate() +void util::checkForUpdate(void *a) { + threadInfo *t = (threadInfo *)a; + t->status->setStatus("Checking for Updates..."); std::string gitJson = getJSONURL(NULL, "https://api.github.com/repos/J-D-K/JKSV/releases/latest"); if(gitJson.empty()) { ui::showPopMessage(POP_FRAME_DEFAULT, ui::errorConnecting.c_str()); + t->finished = true; return; } @@ -361,6 +365,7 @@ void util::checkForUpdate() //This can throw false positives as is. need to fix sometime if(year > BLD_YEAR || month > BLD_MON || month > BLD_DAY) { + t->status->setStatus("Downloading Update..."); //dunno about NSP yet... json_object *assets, *asset0, *dlUrl; json_object_object_get_ex(jobj, "assets", &assets); @@ -378,6 +383,7 @@ void util::checkForUpdate() ui::showPopMessage(POP_FRAME_DEFAULT, ui::noUpdate.c_str()); json_object_put(jobj); + t->finished = true; } Result util::accountDeleteUser(AccountUid *uid)