From 413881fec20b27c486ade2a69e86050211636b29 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sun, 20 Dec 2015 14:03:55 -0800 Subject: [PATCH] Qt: Load ROM name from No-Intro --- src/platform/qt/GBAApp.cpp | 11 ++++++++ src/platform/qt/GBAApp.h | 5 ++++ src/platform/qt/ROMInfo.cpp | 17 +++++++++++++ src/platform/qt/ROMInfo.ui | 36 ++++++++++++++++++++------ src/platform/qt/Window.cpp | 15 +++++++---- src/util/nointro.c | 50 +++++++++++++++++++++++++++++++++---- src/util/nointro.h | 2 +- 7 files changed, 117 insertions(+), 19 deletions(-) diff --git a/src/platform/qt/GBAApp.cpp b/src/platform/qt/GBAApp.cpp index 24f59af4a..2a4225cae 100644 --- a/src/platform/qt/GBAApp.cpp +++ b/src/platform/qt/GBAApp.cpp @@ -9,6 +9,7 @@ #include "Display.h" #include "GameController.h" #include "Window.h" +#include "VFileDevice.h" #include #include @@ -17,6 +18,7 @@ extern "C" { #include "gba/supervisor/thread.h" #include "platform/commandline.h" +#include "util/nointro.h" #include "util/socket.h" } @@ -27,6 +29,7 @@ static GBAApp* g_app = nullptr; GBAApp::GBAApp(int& argc, char* argv[]) : QApplication(argc, argv) , m_windows{} + , m_db(nullptr) { g_app = this; @@ -60,6 +63,14 @@ GBAApp::GBAApp(int& argc, char* argv[]) return; } + char path[PATH_MAX]; + GBAConfigDirectory(path, sizeof(path)); + VFile* vf = VFileDevice::open(QString::fromUtf8(path) + "/nointro.dat", O_RDONLY); + if (vf) { + m_db = NoIntroDBLoad(vf); + vf->close(vf); + } + if (!m_configController.getQtOption("audioDriver").isNull()) { AudioProcessor::setDriver(static_cast(m_configController.getQtOption("audioDriver").toInt())); } diff --git a/src/platform/qt/GBAApp.h b/src/platform/qt/GBAApp.h index 129e94a6c..82f5d838b 100644 --- a/src/platform/qt/GBAApp.h +++ b/src/platform/qt/GBAApp.h @@ -12,6 +12,8 @@ #include "ConfigController.h" #include "MultiplayerController.h" +struct NoIntroDB; + extern "C" { #include "gba/sio.h" } @@ -36,6 +38,8 @@ public: QFileDialog* getOpenFileDialog(QWidget* owner, const QString& title, const QString& filter = QString()); QFileDialog* getSaveFileDialog(QWidget* owner, const QString& title, const QString& filter = QString()); + const NoIntroDB* noIntroDB() const { return m_db; } + public slots: void interruptAll(); void continueAll(); @@ -59,6 +63,7 @@ private: ConfigController m_configController; Window* m_windows[MAX_GBAS]; MultiplayerController m_multiplayer; + NoIntroDB* m_db; }; } diff --git a/src/platform/qt/ROMInfo.cpp b/src/platform/qt/ROMInfo.cpp index ec918cebc..d77c8ecaf 100644 --- a/src/platform/qt/ROMInfo.cpp +++ b/src/platform/qt/ROMInfo.cpp @@ -5,8 +5,13 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ROMInfo.h" +#include "GBAApp.h" #include "GameController.h" +extern "C" { +#include "util/nointro.h" +} + using namespace QGBA; ROMInfo::ROMInfo(GameController* controller, QWidget* parent) { @@ -16,6 +21,8 @@ ROMInfo::ROMInfo(GameController* controller, QWidget* parent) { return; } + const NoIntroDB* db = GBAApp::app()->noIntroDB(); + controller->threadInterrupt(); GBA* gba = controller->thread()->gba; char title[13] = {}; @@ -25,5 +32,15 @@ ROMInfo::ROMInfo(GameController* controller, QWidget* parent) { m_ui.title->setText(QLatin1String(title)); m_ui.size->setText(QString::number(gba->pristineRomSize)); m_ui.crc->setText(QString::number(gba->romCrc32, 16)); + if (db) { + NoIntroGame game; + if (NoIntroDBLookupGameByCRC(db, gba->romCrc32, &game)) { + m_ui.name->setText(game.name); + } else { + m_ui.name->setText(tr("(unknown)")); + } + } else { + m_ui.name->setText(tr("(no database present)")); + } controller->threadContinue(); } diff --git a/src/platform/qt/ROMInfo.ui b/src/platform/qt/ROMInfo.ui index 08211a68e..a328bbd98 100644 --- a/src/platform/qt/ROMInfo.ui +++ b/src/platform/qt/ROMInfo.ui @@ -7,7 +7,7 @@ 0 0 236 - 142 + 146 @@ -21,16 +21,19 @@ QFormLayout::FieldsStayAtSizeHint - + - Game ID: + Game name: - + - {ID} + {NAME} + + + true Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse @@ -55,13 +58,30 @@ + + + Game ID: + + + + + + + {ID} + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + File size: - + {SIZE} @@ -71,14 +91,14 @@ - + CRC32: - + {CRC} diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index 0fb1577a0..6170d7dd5 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -41,6 +41,7 @@ extern "C" { #include "platform/commandline.h" +#include "util/nointro.h" #include "util/vfs.h" } @@ -604,7 +605,6 @@ void Window::gameStarted(GBAThread* context) { MutexLock(&context->stateMutex); if (context->state < THREAD_EXITING) { emit startDrawing(context); - GBAGetGameTitle(context->gba, title); } else { MutexUnlock(&context->stateMutex); return; @@ -715,10 +715,15 @@ void Window::updateTitle(float fps) { m_controller->threadInterrupt(); if (m_controller->isLoaded()) { - char gameTitle[13] = { '\0' }; - GBAGetGameTitle(m_controller->thread()->gba, gameTitle); - - title = (gameTitle); + const NoIntroDB* db = GBAApp::app()->noIntroDB(); + NoIntroGame game; + if (db && NoIntroDBLookupGameByCRC(db, m_controller->thread()->gba->romCrc32, &game)) { + title = QLatin1String(game.name); + } else { + char gameTitle[13] = { '\0' }; + GBAGetGameTitle(m_controller->thread()->gba, gameTitle); + title = gameTitle; + } } MultiplayerController* multiplayer = m_controller->multiplayerController(); if (multiplayer && multiplayer->attached() > 1) { diff --git a/src/util/nointro.c b/src/util/nointro.c index 9773a13fd..d8587b25a 100644 --- a/src/util/nointro.c +++ b/src/util/nointro.c @@ -108,6 +108,48 @@ static void _dbDeinit(void* value) { NoIntroCategoryDeinit(category); } +static bool _itemToGame(const struct NoIntroItem* item, struct NoIntroGame* game) { + if (item->type != NI_HASH) { + return false; + } + struct NoIntroItem* subitem; + struct NoIntroItem* rom; + + memset(game, 0, sizeof(*game)); + subitem = HashTableLookup(&item->hash, "name"); + if (subitem && subitem->type == NI_STRING) { + game->name = subitem->string; + } + subitem = HashTableLookup(&item->hash, "description"); + if (subitem && subitem->type == NI_STRING) { + game->description = subitem->string; + } + + rom = HashTableLookup(&item->hash, "rom"); + if (!rom || rom->type != NI_HASH) { + return false; + } + subitem = HashTableLookup(&rom->hash, "name"); + if (subitem && subitem->type == NI_STRING) { + game->romName = subitem->string; + } + subitem = HashTableLookup(&rom->hash, "size"); + if (subitem && subitem->type == NI_STRING) { + char* end; + game->size = strtoul(subitem->string, &end, 0); + if (!end || *end) { + game->size = 0; + } + } + // TODO: md5, sha1 + subitem = HashTableLookup(&rom->hash, "flags"); + if (subitem && subitem->type == NI_STRING && strcmp(subitem->string, "verified")) { + game->verified = true; + } + + return true; +} + struct NoIntroDB* NoIntroDBLoad(struct VFile* vf) { struct NoIntroDB* db = malloc(sizeof(*db)); HashTableInit(&db->categories, 0, _dbDeinit); @@ -224,15 +266,13 @@ void NoIntroDBDestroy(struct NoIntroDB* db) { HashTableDeinit(&db->categories); } -bool NoIntroDBLookupGame(const struct NoIntroDB* db, const void* data, size_t len, struct NoIntroGame* info) { +bool NoIntroDBLookupGameByCRC(const struct NoIntroDB* db, uint32_t crc32, struct NoIntroGame* game) { if (!db) { return false; } - uint32_t crc = doCrc32(data, len); - struct NoIntroItem* item = TableLookup(&db->gameCrc, crc); + struct NoIntroItem* item = TableLookup(&db->gameCrc, crc32); if (item) { - // TODO - return true; + return _itemToGame(item, game); } return false; } diff --git a/src/util/nointro.h b/src/util/nointro.h index c224612e5..50f4a23d2 100644 --- a/src/util/nointro.h +++ b/src/util/nointro.h @@ -24,6 +24,6 @@ struct VFile; struct NoIntroDB* NoIntroDBLoad(struct VFile* vf); void NoIntroDBDestroy(struct NoIntroDB* db); -bool NoIntroDBLookupGame(const struct NoIntroDB* db, const void* data, size_t len, struct NoIntroGame* info); +bool NoIntroDBLookupGameByCRC(const struct NoIntroDB* db, uint32_t crc32, struct NoIntroGame* game); #endif