Qt: Load ROM name from No-Intro
@@ -9,6 +9,7 @@ #include "AudioProcessor.h"
#include "Display.h" #include "GameController.h" #include "Window.h" +#include "VFileDevice.h" #include <QFileInfo> #include <QFileOpenEvent>@@ -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 @@
GBAApp::GBAApp(int& argc, char* argv[]) : QApplication(argc, argv) , m_windows{} + , m_db(nullptr) { g_app = this;@@ -58,6 +61,14 @@ if (loaded && args.showHelp) {
usage(argv[0], subparser.usage); ::exit(0); 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()) {
@@ -12,6 +12,8 @@
#include "ConfigController.h" #include "MultiplayerController.h" +struct NoIntroDB; + extern "C" { #include "gba/sio.h" }@@ -36,6 +38,8 @@
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 @@
ConfigController m_configController; Window* m_windows[MAX_GBAS]; MultiplayerController m_multiplayer; + NoIntroDB* m_db; }; }
@@ -5,7 +5,12 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this
* 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;@@ -16,6 +21,8 @@ if (!controller->isLoaded()) {
return; } + const NoIntroDB* db = GBAApp::app()->noIntroDB(); + controller->threadInterrupt(); GBA* gba = controller->thread()->gba; char title[13] = {};@@ -25,5 +32,15 @@ GBAGetGameTitle(gba, title);
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(); }
@@ -7,7 +7,7 @@ <rect>
<x>0</x> <y>0</y> <width>236</width> - <height>142</height> + <height>146</height> </rect> </property> <property name="windowTitle">@@ -21,16 +21,19 @@ <property name="fieldGrowthPolicy">
<enum>QFormLayout::FieldsStayAtSizeHint</enum> </property> <item row="0" column="0"> - <widget class="QLabel" name="label_2"> + <widget class="QLabel" name="label_5"> <property name="text"> - <string>Game ID:</string> + <string>Game name:</string> </property> </widget> </item> <item row="0" column="1"> - <widget class="QLabel" name="id"> + <widget class="QLabel" name="name"> <property name="text"> - <string>{ID}</string> + <string>{NAME}</string> + </property> + <property name="wordWrap"> + <bool>true</bool> </property> <property name="textInteractionFlags"> <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>@@ -55,13 +58,30 @@ </property>
</widget> </item> <item row="2" column="0"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Game ID:</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QLabel" name="id"> + <property name="text"> + <string>{ID}</string> + </property> + <property name="textInteractionFlags"> + <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set> + </property> + </widget> + </item> + <item row="3" column="0"> <widget class="QLabel" name="label_3"> <property name="text"> <string>File size:</string> </property> </widget> </item> - <item row="2" column="1"> + <item row="3" column="1"> <widget class="QLabel" name="size"> <property name="text"> <string>{SIZE}</string>@@ -71,14 +91,14 @@ <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property> </widget> </item> - <item row="3" column="0"> + <item row="4" column="0"> <widget class="QLabel" name="label_4"> <property name="text"> <string>CRC32:</string> </property> </widget> </item> - <item row="3" column="1"> + <item row="4" column="1"> <widget class="QLabel" name="crc"> <property name="text"> <string>{CRC}</string>
@@ -41,6 +41,7 @@ #include "VideoView.h"
extern "C" { #include "platform/commandline.h" +#include "util/nointro.h" #include "util/vfs.h" }@@ -604,7 +605,6 @@ char title[13] = { '\0' };
MutexLock(&context->stateMutex); if (context->state < THREAD_EXITING) { emit startDrawing(context); - GBAGetGameTitle(context->gba, title); } else { MutexUnlock(&context->stateMutex); return;@@ -715,10 +715,15 @@ QString title;
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) {
@@ -108,6 +108,48 @@ }
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; }
@@ -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