mirror of https://github.com/mgba-emu/mgba.git
Qt: Load ROM name from No-Intro
This commit is contained in:
parent
746af3ff82
commit
413881fec2
|
@ -9,6 +9,7 @@
|
|||
#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 @@ 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<AudioProcessor::Driver>(m_configController.getQtOption("audioDriver").toInt()));
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>236</width>
|
||||
<height>142</height>
|
||||
<height>146</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
@ -21,16 +21,19 @@
|
|||
<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 @@
|
|||
</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 @@
|
|||
</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 @@
|
|||
|
||||
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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue