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:
- 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: Add MD5 hashing for ROMs
- GB: Prevent incompatible BIOSes from being used on differing models
- GB Serialize: Add missing savestate support for MBC6 and NT (newer)
- GBA: Improve detection of valid ELF ROMs

View File

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

View File

@ -21,6 +21,7 @@
#include <mgba/internal/sm83/sm83.h>
#include <mgba/internal/sm83/debugger/debugger.h>
#include <mgba-util/crc32.h>
#include <mgba-util/md5.h>
#include <mgba-util/memory.h>
#include <mgba-util/patch.h>
#include <mgba-util/vfs.h>
@ -529,6 +530,15 @@ static void _GBCoreChecksum(const struct mCore* core, void* data, enum mCoreChec
case mCHECKSUM_CRC32:
memcpy(data, &gb->romCrc32, sizeof(gb->romCrc32));
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;
}

View File

@ -30,6 +30,7 @@
#ifdef USE_ELF
#include <mgba-util/elf-read.h>
#endif
#include <mgba-util/md5.h>
#include <mgba-util/memory.h>
#include <mgba-util/patch.h>
#include <mgba-util/vfs.h>
@ -676,6 +677,19 @@ static void _GBACoreChecksum(const struct mCore* core, void* data, enum mCoreChe
case mCHECKSUM_CRC32:
memcpy(data, &gba->romCrc32, sizeof(gba->romCrc32));
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;
}

View File

@ -24,6 +24,7 @@ ROMInfo::ROMInfo(std::shared_ptr<CoreController> controller, QWidget* parent)
const NoIntroDB* db = GBAApp::app()->gameDB();
#endif
uint32_t crc32 = 0;
uint8_t md5[16]{};
CoreController::Interrupter interrupter(controller);
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));
core->checksum(core, &crc32, mCHECKSUM_CRC32);
core->checksum(core, &md5, mCHECKSUM_MD5);
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.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();
if (!savePath.isEmpty()) {
m_ui.savefile->setText(savePath);

View File

@ -6,154 +6,186 @@
<rect>
<x>0</x>
<y>0</y>
<width>178</width>
<height>198</height>
<width>180</width>
<height>298</height>
</rect>
</property>
<property name="windowTitle">
<string>ROM Info</string>
</property>
<layout class="QFormLayout" name="formLayout">
<layout class="QGridLayout" name="gridLayout">
<property name="sizeConstraint">
<enum>QLayout::SetFixedSize</enum>
</property>
<property name="fieldGrowthPolicy">
<enum>QFormLayout::FieldsStayAtSizeHint</enum>
</property>
<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>
<widget class="QGroupBox" name="formGroupBox">
<property name="title">
<string>File information</string>
</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>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Internal name:</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>
<widget class="QGroupBox" name="formGroupBox_2">
<property name="title">
<string>ROM header</string>
</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>
</item>
</layout>