From 964b303eda055da917d5f7ea5943ed3ea5e5477c Mon Sep 17 00:00:00 2001 From: Adam Higerd Date: Sat, 2 Jul 2022 14:10:48 -0500 Subject: [PATCH] Library: store platform models in database, render GBC icons --- include/mgba/core/library.h | 3 ++ src/core/library.c | 64 +++++++++++++++++++++++- src/platform/qt/Window.cpp | 4 +- src/platform/qt/library/LibraryEntry.cpp | 7 +++ src/platform/qt/library/LibraryEntry.h | 2 + src/platform/qt/library/LibraryModel.cpp | 3 +- src/platform/qt/utils.cpp | 12 ++++- src/platform/qt/utils.h | 2 +- 8 files changed, 90 insertions(+), 7 deletions(-) diff --git a/include/mgba/core/library.h b/include/mgba/core/library.h index d12aa0411f1..d4c0d04389f 100644 --- a/include/mgba/core/library.h +++ b/include/mgba/core/library.h @@ -13,6 +13,8 @@ CXX_GUARD_START #include #include +#define M_LIBRARY_MODEL_UNKNOWN -1 + struct mLibraryEntry { const char* base; const char* filename; @@ -22,6 +24,7 @@ struct mLibraryEntry { enum mPlatform platform; size_t filesize; uint32_t crc32; + int platformModels; }; #ifdef USE_SQLITE3 diff --git a/src/core/library.c b/src/core/library.c index 44148f7f50d..1520994be2f 100644 --- a/src/core/library.c +++ b/src/core/library.c @@ -8,6 +8,11 @@ #include #include +#ifdef M_CORE_GB +#include +#include +#endif + #ifdef USE_SQLITE3 #include @@ -91,12 +96,38 @@ static void _bindConstraints(sqlite3_stmt* statement, const struct mLibraryEntry sqlite3_bind_int(statement, useIndex, 1); sqlite3_bind_int(statement, index, constraints->platform); } + + if (constraints->platformModels != M_LIBRARY_MODEL_UNKNOWN) { + index = sqlite3_bind_parameter_index(statement, ":models"); + sqlite3_bind_int(statement, index, constraints->platformModels); + } } struct mLibrary* mLibraryCreateEmpty(void) { return mLibraryLoad(":memory:"); } +static int _mLibraryTableVersion(struct mLibrary* library, const char* tableName) { + int version = -1; + + static const char getVersion[] = "SELECT version FROM version WHERE tname=?"; + sqlite3_stmt* getVersionStmt; + if (sqlite3_prepare_v2(library->db, getVersion, -1, &getVersionStmt, NULL)) { + goto error; + } + + sqlite3_clear_bindings(getVersionStmt); + sqlite3_reset(getVersionStmt); + sqlite3_bind_text(getVersionStmt, 1, tableName, -1, SQLITE_TRANSIENT); + if (sqlite3_step(getVersionStmt) != SQLITE_DONE) { + version = sqlite3_column_int(getVersionStmt, 0); + } + +error: + sqlite3_finalize(getVersionStmt); + return version; +} + struct mLibrary* mLibraryLoad(const char* path) { struct mLibrary* library = malloc(sizeof(*library)); memset(library, 0, sizeof(*library)); @@ -123,6 +154,7 @@ struct mLibrary* mLibraryLoad(const char* path) { "\n internalTitle TEXT," "\n internalCode TEXT," "\n platform INTEGER NOT NULL DEFAULT -1," + "\n models INTEGER NULL," "\n size INTEGER," "\n crc32 INTEGER," "\n md5 BLOB," @@ -140,18 +172,35 @@ struct mLibrary* mLibraryLoad(const char* path) { "\n CREATE INDEX IF NOT EXISTS crc32 ON roms (crc32);" "\n INSERT OR IGNORE INTO version (tname, version) VALUES ('version', 1);" "\n INSERT OR IGNORE INTO version (tname, version) VALUES ('roots', 1);" - "\n INSERT OR IGNORE INTO version (tname, version) VALUES ('roms', 1);" + "\n INSERT OR IGNORE INTO version (tname, version) VALUES ('roms', 2);" "\n INSERT OR IGNORE INTO version (tname, version) VALUES ('paths', 1);"; if (sqlite3_exec(library->db, createTables, NULL, NULL, NULL)) { goto error; } + int romsTableVersion = _mLibraryTableVersion(library, "roms"); + if (romsTableVersion < 0) { + goto error; + } else if (romsTableVersion < 2) { + static const char upgradeRomsTable[] = + " ALTER TABLE roms" + "\nADD COLUMN models INTEGER NULL"; + if (sqlite3_exec(library->db, upgradeRomsTable, NULL, NULL, NULL)) { + goto error; + } + + static const char updateRomsTableVersion[] = "UPDATE version SET version=2 WHERE tname='roms'"; + if (sqlite3_exec(library->db, updateRomsTableVersion, NULL, NULL, NULL)) { + goto error; + } + } + static const char insertPath[] = "INSERT INTO paths (romid, path, customTitle, rootid) VALUES (?, ?, ?, ?);"; if (sqlite3_prepare_v2(library->db, insertPath, -1, &library->insertPath, NULL)) { goto error; } - static const char insertRom[] = "INSERT INTO roms (crc32, size, internalCode, platform) VALUES (:crc32, :size, :internalCode, :platform);"; + static const char insertRom[] = "INSERT INTO roms (crc32, size, internalCode, platform, models) VALUES (:crc32, :size, :internalCode, :platform, :models);"; if (sqlite3_prepare_v2(library->db, insertRom, -1, &library->insertRom, NULL)) { goto error; } @@ -295,6 +344,15 @@ bool _mLibraryAddEntry(struct mLibrary* library, const char* filename, const cha core->getGameCode(core, entry.internalCode); core->checksum(core, &entry.crc32, mCHECKSUM_CRC32); entry.platform = core->platform(core); + entry.platformModels = M_LIBRARY_MODEL_UNKNOWN; +#ifdef M_CORE_GB + if (entry.platform == mPLATFORM_GB) { + struct GB* gb = (struct GB*) core->board; + if (gb->memory.rom) { + entry.platformModels = GBValidModels(gb->memory.rom); + } + } +#endif entry.title = NULL; entry.base = base; entry.filename = filename; @@ -407,6 +465,8 @@ size_t mLibraryGetEntries(struct mLibrary* library, struct mLibraryListing* out, } } else if (strcmp(colName, "platform") == 0) { entry->platform = sqlite3_column_int(library->select, i); + } else if (strcmp(colName, "models") == 0) { + entry->platformModels = sqlite3_column_int(library->select, i); } else if (strcmp(colName, "size") == 0) { entry->filesize = sqlite3_column_int64(library->select, i); } else if (strcmp(colName, "internalCode") == 0 && sqlite3_column_type(library->select, i) == SQLITE_TEXT) { diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index 6003b88a378..f904af0bfab 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -122,7 +122,7 @@ Window::Window(CoreManager* manager, ConfigController* config, int playerId, QWi if (value.toBool()) { attachWidget(m_libraryView); } else { - attachWidget(m_screenWidget); + attachWidget(m_screenWidget); } } }, this); @@ -131,7 +131,7 @@ Window::Window(CoreManager* manager, ConfigController* config, int playerId, QWi ConfigOption* showFilenameInLibrary = m_config->addOption("showFilenameInLibrary"); showFilenameInLibrary->connect([this](const QVariant& value) { m_libraryView->setShowFilename(value.toBool()); - }, this); + }, this); m_config->updateOption("showFilenameInLibrary"); ConfigOption* libraryStyle = m_config->addOption("libraryStyle"); libraryStyle->connect([this](const QVariant& value) { diff --git a/src/platform/qt/library/LibraryEntry.cpp b/src/platform/qt/library/LibraryEntry.cpp index 27feb64e89d..25a5976c922 100644 --- a/src/platform/qt/library/LibraryEntry.cpp +++ b/src/platform/qt/library/LibraryEntry.cpp @@ -6,6 +6,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "LibraryEntry.h" +#include "utils.h" + #include using namespace QGBA; @@ -22,6 +24,7 @@ LibraryEntry::LibraryEntry(const mLibraryEntry* entry) , internalTitle(entry->internalTitle) , internalCode(entry->internalCode) , platform(entry->platform) + , platformModels(entry->platformModels) , filesize(entry->filesize) , crc32(entry->crc32) { @@ -38,6 +41,10 @@ QString LibraryEntry::displayTitle(bool showFilename) const { return title; } +QString LibraryEntry::displayPlatform() const { + return nicePlatformFormat(platform, platformModels); +} + bool LibraryEntry::operator==(const LibraryEntry& other) const { return other.fullpath == fullpath; } diff --git a/src/platform/qt/library/LibraryEntry.h b/src/platform/qt/library/LibraryEntry.h index 2a733db4ab0..3d8e6c8a8d5 100644 --- a/src/platform/qt/library/LibraryEntry.h +++ b/src/platform/qt/library/LibraryEntry.h @@ -25,6 +25,7 @@ struct LibraryEntry { bool isNull() const; QString displayTitle(bool showFilename = false) const; + QString displayPlatform() const; QString base; QString filename; @@ -33,6 +34,7 @@ struct LibraryEntry { QByteArray internalTitle; QByteArray internalCode; mPlatform platform; + int platformModels; size_t filesize; uint32_t crc32; diff --git a/src/platform/qt/library/LibraryModel.cpp b/src/platform/qt/library/LibraryModel.cpp index bc08228c10a..ebb8f97e6ee 100644 --- a/src/platform/qt/library/LibraryModel.cpp +++ b/src/platform/qt/library/LibraryModel.cpp @@ -21,6 +21,7 @@ static const QStringList iconSets{ "GBA", "GBC", "GB", + "SGB", // "DS", }; @@ -348,7 +349,7 @@ QVariant LibraryModel::data(const QModelIndex& index, int role) const { switch (index.column()) { case COL_NAME: if (role == Qt::DecorationRole) { - return m_icons.value(nicePlatformFormat(entry->platform), qApp->style()->standardIcon(QStyle::SP_FileIcon)); + return m_icons.value(entry->displayPlatform(), qApp->style()->standardIcon(QStyle::SP_FileIcon)); } return entry->displayTitle(m_showFilename); case COL_LOCATION: diff --git a/src/platform/qt/utils.cpp b/src/platform/qt/utils.cpp index f90ed085b55..b24b498bb50 100644 --- a/src/platform/qt/utils.cpp +++ b/src/platform/qt/utils.cpp @@ -5,6 +5,9 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "utils.h" +#include +#include + #include #include #include @@ -30,7 +33,7 @@ QString niceSizeFormat(size_t filesize) { return unit.arg(size, 0, 'f', int(size * 10) % 10 ? 1 : 0); } -QString nicePlatformFormat(mPlatform platform) { +QString nicePlatformFormat(mPlatform platform, int validModels) { switch (platform) { #ifdef M_CORE_GBA case mPLATFORM_GBA: @@ -38,6 +41,13 @@ QString nicePlatformFormat(mPlatform platform) { #endif #ifdef M_CORE_GB case mPLATFORM_GB: + if (validModels != M_LIBRARY_MODEL_UNKNOWN) { + if (validModels & GB_MODEL_CGB) { + return QObject::tr("GBC"); + } else if (validModels & GB_MODEL_SGB) { + return QObject::tr("SGB"); + } + } return QObject::tr("GB"); #endif default: diff --git a/src/platform/qt/utils.h b/src/platform/qt/utils.h index f2e226cfc64..f912bc0af59 100644 --- a/src/platform/qt/utils.h +++ b/src/platform/qt/utils.h @@ -31,7 +31,7 @@ enum class Endian { }; QString niceSizeFormat(size_t filesize); -QString nicePlatformFormat(mPlatform platform); +QString nicePlatformFormat(mPlatform platform, int validModels = 0); bool convertAddress(const QHostAddress* input, Address* output);