Core: Add MD5 hashing for ROMs

This commit is contained in:
Vicki Pfau 2024-10-08 04:09:26 -07:00
parent 58510ca250
commit 2ccfde0f33
6 changed files with 198 additions and 134 deletions

View File

@ -41,6 +41,7 @@ Other fixes:
Misc: Misc:
- Core: Handle relative paths for saves, screenshots, etc consistently (fixes mgba.io/i/2826) - Core: Handle relative paths for saves, screenshots, etc consistently (fixes mgba.io/i/2826)
- Core: Improve rumble emulation by averaging state over entire frame (fixes mgba.io/i/3232) - Core: Improve rumble emulation by averaging state over entire frame (fixes mgba.io/i/3232)
- Core: Add MD5 hashing for ROMs
- GB: Prevent incompatible BIOSes from being used on differing models - GB: Prevent incompatible BIOSes from being used on differing models
- GB Serialize: Add missing savestate support for MBC6 and NT (newer) - GB Serialize: Add missing savestate support for MBC6 and NT (newer)
- GBA: Improve detection of valid ELF ROMs - GBA: Improve detection of valid ELF ROMs

View File

@ -30,6 +30,7 @@ enum mPlatform {
enum mCoreChecksumType { enum mCoreChecksumType {
mCHECKSUM_CRC32, mCHECKSUM_CRC32,
mCHECKSUM_MD5,
}; };
struct mAudioBuffer; struct mAudioBuffer;

View File

@ -21,6 +21,7 @@
#include <mgba/internal/sm83/sm83.h> #include <mgba/internal/sm83/sm83.h>
#include <mgba/internal/sm83/debugger/debugger.h> #include <mgba/internal/sm83/debugger/debugger.h>
#include <mgba-util/crc32.h> #include <mgba-util/crc32.h>
#include <mgba-util/md5.h>
#include <mgba-util/memory.h> #include <mgba-util/memory.h>
#include <mgba-util/patch.h> #include <mgba-util/patch.h>
#include <mgba-util/vfs.h> #include <mgba-util/vfs.h>
@ -529,6 +530,15 @@ static void _GBCoreChecksum(const struct mCore* core, void* data, enum mCoreChec
case mCHECKSUM_CRC32: case mCHECKSUM_CRC32:
memcpy(data, &gb->romCrc32, sizeof(gb->romCrc32)); memcpy(data, &gb->romCrc32, sizeof(gb->romCrc32));
break; break;
case mCHECKSUM_MD5:
if (gb->romVf) {
md5File(gb->romVf, data);
} else if (gb->memory.rom && gb->isPristine) {
md5Buffer(gb->memory.rom, gb->pristineRomSize, data);
} else {
md5Buffer("", 0, data);
}
break;
} }
return; return;
} }

View File

@ -30,6 +30,7 @@
#ifdef USE_ELF #ifdef USE_ELF
#include <mgba-util/elf-read.h> #include <mgba-util/elf-read.h>
#endif #endif
#include <mgba-util/md5.h>
#include <mgba-util/memory.h> #include <mgba-util/memory.h>
#include <mgba-util/patch.h> #include <mgba-util/patch.h>
#include <mgba-util/vfs.h> #include <mgba-util/vfs.h>
@ -676,6 +677,19 @@ static void _GBACoreChecksum(const struct mCore* core, void* data, enum mCoreChe
case mCHECKSUM_CRC32: case mCHECKSUM_CRC32:
memcpy(data, &gba->romCrc32, sizeof(gba->romCrc32)); memcpy(data, &gba->romCrc32, sizeof(gba->romCrc32));
break; break;
case mCHECKSUM_MD5:
if (gba->romVf) {
md5File(gba->romVf, data);
} else if (gba->mbVf) {
md5File(gba->mbVf, data);
} else if (gba->memory.rom && gba->isPristine) {
md5Buffer(gba->memory.rom, gba->pristineRomSize, data);
} else if (gba->memory.rom) {
md5Buffer(gba->memory.rom, gba->memory.romSize, data);
} else {
md5Buffer("", 0, data);
}
break;
} }
return; return;
} }

View File

@ -24,6 +24,7 @@ ROMInfo::ROMInfo(std::shared_ptr<CoreController> controller, QWidget* parent)
const NoIntroDB* db = GBAApp::app()->gameDB(); const NoIntroDB* db = GBAApp::app()->gameDB();
#endif #endif
uint32_t crc32 = 0; uint32_t crc32 = 0;
uint8_t md5[16]{};
CoreController::Interrupter interrupter(controller); CoreController::Interrupter interrupter(controller);
mCore* core = controller->thread()->core; mCore* core = controller->thread()->core;
@ -39,6 +40,7 @@ ROMInfo::ROMInfo(std::shared_ptr<CoreController> controller, QWidget* parent)
m_ui.version->setText(QString::number(info.version)); m_ui.version->setText(QString::number(info.version));
core->checksum(core, &crc32, mCHECKSUM_CRC32); core->checksum(core, &crc32, mCHECKSUM_CRC32);
core->checksum(core, &md5, mCHECKSUM_MD5);
m_ui.size->setText(QString::number(core->romSize(core)) + tr(" bytes")); m_ui.size->setText(QString::number(core->romSize(core)) + tr(" bytes"));
@ -63,6 +65,10 @@ ROMInfo::ROMInfo(std::shared_ptr<CoreController> controller, QWidget* parent)
m_ui.name->setText(tr("(unknown)")); m_ui.name->setText(tr("(unknown)"));
} }
m_ui.md5->setText(QString::asprintf("%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
md5[0x0], md5[0x1], md5[0x2], md5[0x3], md5[0x4], md5[0x5], md5[0x6], md5[0x7],
md5[0x8], md5[0x9], md5[0xA], md5[0xB], md5[0xC], md5[0xD], md5[0xE], md5[0xF]));
QString savePath = controller->savePath(); QString savePath = controller->savePath();
if (!savePath.isEmpty()) { if (!savePath.isEmpty()) {
m_ui.savefile->setText(savePath); m_ui.savefile->setText(savePath);

View File

@ -6,154 +6,186 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>178</width> <width>180</width>
<height>198</height> <height>298</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>ROM Info</string> <string>ROM Info</string>
</property> </property>
<layout class="QFormLayout" name="formLayout"> <layout class="QGridLayout" name="gridLayout">
<property name="sizeConstraint"> <property name="sizeConstraint">
<enum>QLayout::SetFixedSize</enum> <enum>QLayout::SetFixedSize</enum>
</property> </property>
<property name="fieldGrowthPolicy">
<enum>QFormLayout::FieldsStayAtSizeHint</enum>
</property>
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="label_5"> <widget class="QGroupBox" name="formGroupBox">
<property name="text"> <property name="title">
<string>Game name:</string> <string>File information</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="name">
<property name="text">
<string notr="true">{NAME}</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property> </property>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Game name:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="name">
<property name="text">
<string notr="true">{NAME}</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>File size:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="size">
<property name="text">
<string notr="true">{SIZE}</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>CRC32:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="crc">
<property name="text">
<string notr="true">{CRC}</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_9">
<property name="text">
<string>MD5</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="md5">
<property name="text">
<string notr="true">{MD5}</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Save file:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLabel" name="savefile">
<property name="text">
<string notr="true">{SAVEFILE}</string>
</property>
</widget>
</item>
</layout>
</widget> </widget>
</item> </item>
<item row="1" column="0"> <item row="1" column="0">
<widget class="QLabel" name="label"> <widget class="QGroupBox" name="formGroupBox_2">
<property name="text"> <property name="title">
<string>Internal name:</string> <string>ROM header</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="title">
<property name="text">
<string notr="true">{TITLE}</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</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 notr="true">{ID}</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Maker Code:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="maker">
<property name="text">
<string notr="true">{MAKER}</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Revision:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLabel" name="version">
<property name="text">
<string notr="true">{VERSION}</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>File size:</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLabel" name="size">
<property name="text">
<string notr="true">{SIZE}</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>CRC32:</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QLabel" name="crc">
<property name="text">
<string notr="true">{CRC}</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Save file:</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QLabel" name="savefile">
<property name="text">
<string notr="true">{SAVEFILE}</string>
</property> </property>
<layout class="QFormLayout" name="formLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Internal name:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="title">
<property name="text">
<string notr="true">{TITLE}</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Game ID:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="id">
<property name="text">
<string notr="true">{ID}</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Maker Code:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="maker">
<property name="text">
<string notr="true">{MAKER}</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Revision:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="version">
<property name="text">
<string notr="true">{VERSION}</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
</layout>
</widget> </widget>
</item> </item>
</layout> </layout>