From a35d44f799246f9480d08ba72372f9a10ced8b5d 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 | 1 + src/core/library.c | 59 +++++++++++++++++++++++- 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 | 2 +- src/platform/qt/utils.cpp | 7 ++- src/platform/qt/utils.h | 2 +- 8 files changed, 77 insertions(+), 7 deletions(-) diff --git a/include/mgba/core/library.h b/include/mgba/core/library.h index d12aa0411f1..ed78bfacfc6 100644 --- a/include/mgba/core/library.h +++ b/include/mgba/core/library.h @@ -22,6 +22,7 @@ struct mLibraryEntry { enum mPlatform platform; size_t filesize; uint32_t crc32; + uint8_t platformModels; }; #ifdef USE_SQLITE3 diff --git a/src/core/library.c b/src/core/library.c index 44148f7f50d..e2611310e1d 100644 --- a/src/core/library.c +++ b/src/core/library.c @@ -6,6 +6,8 @@ #include #include +#include +#include #include #ifdef USE_SQLITE3 @@ -91,12 +93,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 != GB_MODEL_AUTODETECT) { + 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 +151,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 +169,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 +341,13 @@ 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 = GB_MODEL_AUTODETECT; + if (entry.platform == mPLATFORM_GB) { + struct GB* gb = (struct GB*) core->board; + if (gb->memory.rom) { + entry.platformModels = GBValidModels(gb->memory.rom); + } + } entry.title = NULL; entry.base = base; entry.filename = filename; @@ -407,6 +460,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 02460aeb889..e980081e8a6 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -118,7 +118,7 @@ Window::Window(CoreManager* manager, ConfigController* config, int playerId, QWi if (value.toBool()) { attachWidget(m_libraryView); } else { - attachWidget(m_screenWidget); + attachWidget(m_screenWidget); } } }, this); @@ -127,7 +127,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..9987e4c0c1c 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..54daaf6cbd5 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; + uint8_t 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..859be47adec 100644 --- a/src/platform/qt/library/LibraryModel.cpp +++ b/src/platform/qt/library/LibraryModel.cpp @@ -348,7 +348,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 8be5cad823f..469b214a8ab 100644 --- a/src/platform/qt/utils.cpp +++ b/src/platform/qt/utils.cpp @@ -5,6 +5,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "utils.h" +#include + #include #include #include @@ -29,7 +31,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, uint8_t validModels) { switch (platform) { #ifdef M_CORE_GBA case mPLATFORM_GBA: @@ -37,6 +39,9 @@ QString nicePlatformFormat(mPlatform platform) { #endif #ifdef M_CORE_GB case mPLATFORM_GB: + if (validModels != GB_MODEL_AUTODETECT && (validModels & GB_MODEL_CGB)) { + return QObject::tr("GBC"); + } return QObject::tr("GB"); #endif default: diff --git a/src/platform/qt/utils.h b/src/platform/qt/utils.h index 055e1a18e2b..2dc7dbb0b85 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, uint8_t validModels = 0); bool convertAddress(const QHostAddress* input, Address* output);