From 527f2359347213a4e7614ee75a567437c9a9a921 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 5 Jan 2021 00:23:52 -0800 Subject: [PATCH] Core: Adding to library is now recursive --- CHANGES | 1 + include/mgba/core/library.h | 2 +- src/core/library.c | 69 +++++++++++-------- src/platform/qt/library/LibraryController.cpp | 12 ++-- src/platform/qt/library/LibraryController.h | 4 +- 5 files changed, 50 insertions(+), 38 deletions(-) diff --git a/CHANGES b/CHANGES index af4a2d7d7..413f1c41e 100644 --- a/CHANGES +++ b/CHANGES @@ -94,6 +94,7 @@ Misc: - Core: Add shutdown callback - Core: Rework thread state synchronization - Core: Improve support for ROM patch cheats, supporting disabling overlapping patches + - Core: Adding to library is now recursive - GB: Allow pausing event loop while CPU is blocked - GB: Add support for sleep and shutdown callbacks - GB: Redo double speed emulation (closes mgba.io/i/1515) diff --git a/include/mgba/core/library.h b/include/mgba/core/library.h index d55ad4094..d12aa0411 100644 --- a/include/mgba/core/library.h +++ b/include/mgba/core/library.h @@ -35,7 +35,7 @@ void mLibraryDestroy(struct mLibrary*); struct VDir; struct VFile; -void mLibraryLoadDirectory(struct mLibrary* library, const char* base); +void mLibraryLoadDirectory(struct mLibrary* library, const char* base, bool recursive); void mLibraryClear(struct mLibrary* library); size_t mLibraryCount(struct mLibrary* library, const struct mLibraryEntry* constraints); diff --git a/src/core/library.c b/src/core/library.c index 530ad6cb9..eeb7794de 100644 --- a/src/core/library.c +++ b/src/core/library.c @@ -42,7 +42,7 @@ struct mLibrary { static void _mLibraryDeleteEntry(struct mLibrary* library, struct mLibraryEntry* entry); static void _mLibraryInsertEntry(struct mLibrary* library, struct mLibraryEntry* entry); -static void _mLibraryAddEntry(struct mLibrary* library, const char* filename, const char* base, struct VFile* vf); +static bool _mLibraryAddEntry(struct mLibrary* library, const char* filename, const char* base, struct VFile* vf); static void _bindConstraints(sqlite3_stmt* statement, const struct mLibraryEntry* constraints) { if (!constraints) { @@ -212,7 +212,7 @@ void mLibraryDestroy(struct mLibrary* library) { free(library); } -void mLibraryLoadDirectory(struct mLibrary* library, const char* base) { +void mLibraryLoadDirectory(struct mLibrary* library, const char* base, bool recursive) { struct VDir* dir = VDirOpenArchive(base); if (!dir) { dir = VDirOpen(base); @@ -248,44 +248,55 @@ void mLibraryLoadDirectory(struct mLibrary* library, const char* base) { dir->rewind(dir); struct VDirEntry* dirent = dir->listNext(dir); while (dirent) { - struct VFile* vf = dir->openFile(dir, dirent->name(dirent), O_RDONLY); - if (!vf) { - dirent = dir->listNext(dir); - continue; + const char* name = dirent->name(dirent); + struct VFile* vf = dir->openFile(dir, name, O_RDONLY); + bool wasAdded = false; + + if (vf) { + wasAdded = _mLibraryAddEntry(library, name, base, vf); + } + if (!wasAdded && name[0] != '.') { + char newBase[PATH_MAX]; + snprintf(newBase, sizeof(newBase), "%s" PATH_SEP "%s", base, name); + + if (recursive) { + mLibraryLoadDirectory(library, newBase, recursive); + } else if (dirent->type(dirent) == VFS_FILE) { + mLibraryLoadDirectory(library, newBase, true); // This will add as an archive + } } - _mLibraryAddEntry(library, dirent->name(dirent), base, vf); dirent = dir->listNext(dir); } dir->close(dir); sqlite3_exec(library->db, "COMMIT;", NULL, NULL, NULL); } -void _mLibraryAddEntry(struct mLibrary* library, const char* filename, const char* base, struct VFile* vf) { - struct mCore* core; +bool _mLibraryAddEntry(struct mLibrary* library, const char* filename, const char* base, struct VFile* vf) { if (!vf) { - return; + return false; } - core = mCoreFindVF(vf); - if (core) { - struct mLibraryEntry entry; - memset(&entry, 0, sizeof(entry)); - core->init(core); - core->loadROM(core, vf); - - core->getGameTitle(core, entry.internalTitle); - core->getGameCode(core, entry.internalCode); - core->checksum(core, &entry.crc32, mCHECKSUM_CRC32); - entry.platform = core->platform(core); - entry.title = NULL; - entry.base = base; - entry.filename = filename; - entry.filesize = vf->size(vf); - _mLibraryInsertEntry(library, &entry); - // Note: this destroys the VFile - core->deinit(core); - } else { + struct mCore* core = mCoreFindVF(vf); + if (!core) { vf->close(vf); + return false; } + struct mLibraryEntry entry; + memset(&entry, 0, sizeof(entry)); + core->init(core); + core->loadROM(core, vf); + + core->getGameTitle(core, entry.internalTitle); + core->getGameCode(core, entry.internalCode); + core->checksum(core, &entry.crc32, mCHECKSUM_CRC32); + entry.platform = core->platform(core); + entry.title = NULL; + entry.base = base; + entry.filename = filename; + entry.filesize = vf->size(vf); + _mLibraryInsertEntry(library, &entry); + // Note: this destroys the VFile + core->deinit(core); + return true; } static void _mLibraryInsertEntry(struct mLibrary* library, struct mLibraryEntry* entry) { diff --git a/src/platform/qt/library/LibraryController.cpp b/src/platform/qt/library/LibraryController.cpp index 51fa6d619..2c8c37741 100644 --- a/src/platform/qt/library/LibraryController.cpp +++ b/src/platform/qt/library/LibraryController.cpp @@ -108,10 +108,10 @@ QPair LibraryController::selectedPath() { return e ? qMakePair(e->base(), e->filename()) : qMakePair("", ""); } -void LibraryController::addDirectory(const QString& dir) { +void LibraryController::addDirectory(const QString& dir, bool recursive) { // The worker thread temporarily owns the library std::shared_ptr library = m_library; - m_libraryJob = GBAApp::app()->submitWorkerJob(std::bind(&LibraryController::loadDirectory, this, dir), this, [this, library]() { + m_libraryJob = GBAApp::app()->submitWorkerJob(std::bind(&LibraryController::loadDirectory, this, dir, recursive), this, [this, library]() { m_libraryJob = -1; refresh(); }); @@ -181,10 +181,10 @@ void LibraryController::selectLastBootedGame() { } } -void LibraryController::loadDirectory(const QString& dir) { - // This class can get delted during this function (sigh) so we need to hold onto this +void LibraryController::loadDirectory(const QString& dir, bool recursive) { + // This class can get deleted during this function (sigh) so we need to hold onto this std::shared_ptr library = m_library; - mLibraryLoadDirectory(library.get(), dir.toUtf8().constData()); + mLibraryLoadDirectory(library.get(), dir.toUtf8().constData(), recursive); } void LibraryController::freeLibrary() { @@ -192,4 +192,4 @@ void LibraryController::freeLibrary() { mLibraryEntryFree(mLibraryListingGetPointer(&m_listing, i)); } mLibraryListingClear(&m_listing); -} \ No newline at end of file +} diff --git a/src/platform/qt/library/LibraryController.h b/src/platform/qt/library/LibraryController.h index 9f88cdff5..2b5a595ee 100644 --- a/src/platform/qt/library/LibraryController.h +++ b/src/platform/qt/library/LibraryController.h @@ -84,7 +84,7 @@ public: void selectLastBootedGame(); - void addDirectory(const QString& dir); + void addDirectory(const QString& dir, bool recursive = true); public slots: void clear(); @@ -97,7 +97,7 @@ private slots: void refresh(); private: - void loadDirectory(const QString&); // Called on separate thread + void loadDirectory(const QString&, bool recursive = true); // Called on separate thread void freeLibrary(); ConfigController* m_config = nullptr;