diff --git a/CHANGES b/CHANGES index f0fe0a474..9a538caee 100644 --- a/CHANGES +++ b/CHANGES @@ -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 diff --git a/include/mgba/core/core.h b/include/mgba/core/core.h index e8c5df7bc..94dfb1114 100644 --- a/include/mgba/core/core.h +++ b/include/mgba/core/core.h @@ -30,6 +30,7 @@ enum mPlatform { enum mCoreChecksumType { mCHECKSUM_CRC32, + mCHECKSUM_MD5, }; struct mAudioBuffer; diff --git a/src/gb/core.c b/src/gb/core.c index e67fe4232..b97e1ee25 100644 --- a/src/gb/core.c +++ b/src/gb/core.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -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; } diff --git a/src/gba/core.c b/src/gba/core.c index 67550bd7a..e81e66dac 100644 --- a/src/gba/core.c +++ b/src/gba/core.c @@ -30,6 +30,7 @@ #ifdef USE_ELF #include #endif +#include #include #include #include @@ -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; } diff --git a/src/platform/qt/ROMInfo.cpp b/src/platform/qt/ROMInfo.cpp index 9f2537439..25aafeda8 100644 --- a/src/platform/qt/ROMInfo.cpp +++ b/src/platform/qt/ROMInfo.cpp @@ -24,6 +24,7 @@ ROMInfo::ROMInfo(std::shared_ptr 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 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 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); diff --git a/src/platform/qt/ROMInfo.ui b/src/platform/qt/ROMInfo.ui index 655d4810f..a4a179ca8 100644 --- a/src/platform/qt/ROMInfo.ui +++ b/src/platform/qt/ROMInfo.ui @@ -6,154 +6,186 @@ 0 0 - 178 - 198 + 180 + 298 ROM Info - + QLayout::SetFixedSize - - QFormLayout::FieldsStayAtSizeHint - - - - Game name: - - - - - - - {NAME} - - - true - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + File information + + + + + Game name: + + + + + + + {NAME} + + + true + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + File size: + + + + + + + {SIZE} + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + CRC32: + + + + + + + {CRC} + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + MD5 + + + + + + + {MD5} + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + Save file: + + + + + + + {SAVEFILE} + + + + - - - Internal name: - - - - - - - {TITLE} - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - - - - - Game ID: - - - - - - - {ID} - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - - - - - Maker Code: - - - - - - - {MAKER} - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - - - - - Revision: - - - - - - - {VERSION} - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - - - - - File size: - - - - - - - {SIZE} - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - - - - - CRC32: - - - - - - - {CRC} - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - - - - - Save file: - - - - - - - {SAVEFILE} + + + ROM header + + + + + Internal name: + + + + + + + {TITLE} + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + Game ID: + + + + + + + {ID} + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + Maker Code: + + + + + + + {MAKER} + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + Revision: + + + + + + + {VERSION} + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + +