Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,14 @@ Misc:
- Core: Add callback for memoryBlocksChanged (fixes mgba.io/i/3640)
- FFmpeg: Add Ut Video option
- GB: Prevent incompatible BIOSes from being used on differing models
- GB: Allow use of some bootleg BIOSes
- GB MBC: Add M161 support for one Mani 4-in-1 multicart
- GB Memory: Decay cart bus eagerly when executing from RAM
- GB Serialize: Add missing savestate support for MBC6 and NT (newer)
- GBA: Improve detection of valid ELF ROMs
- GBA Audio: Remove broken XQ audio pending rewrite
- GBA BIOS: Move SoftReset implementation to assembly
- GBA BIOS: Prevent using known-broken "debug" BIOS
- GBA e-Reader: Use geometric mean instead of arithmetic mean when detecting parameters
- GBA e-Reader: Disable strict mode when scanning cards
- GBA Memory: Improve VRAM access stall cycle estimation
Expand Down
6 changes: 4 additions & 2 deletions include/mgba/internal/gba/bios.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ CXX_GUARD_START

#include <mgba/core/log.h>

#define GBA_BIOS_CHECKSUM 0xBAAE187F
#define GBA_DS_BIOS_CHECKSUM 0xBAAE1880
#define GBA_DEBUG_BIOS_CHECKSUM 0x242CEF81

mLOG_DECLARE_CATEGORY(GBA_BIOS);

enum GBASwi {
Expand Down Expand Up @@ -65,8 +69,6 @@ void GBASwi16(struct ARMCore* cpu, int immediate);
void GBASwi32(struct ARMCore* cpu, int immediate);

uint32_t GBAChecksum(uint32_t* memory, size_t size);
extern const uint32_t GBA_BIOS_CHECKSUM;
extern const uint32_t GBA_DS_BIOS_CHECKSUM;

CXX_GUARD_END

Expand Down
22 changes: 22 additions & 0 deletions src/gb/gb.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ static const uint8_t _cgbBiosHram[GB_SIZE_HRAM] = {
#define AGB_BIOS_CHECKSUM 0xFFD6B0F1
#define AGB0_BIOS_CHECKSUM 0x570337EA

#define FORTUNE_BIOS_CHECKSUM 0x66CC6D94
#define GAMEFIGHTER_BIOS_CHECKSUM 0x908BA8DE
#define KONGFENG_GBBC_BIOS_CHECKSUM 0x69236128
#define MAXSTATION_BIOS_CHECKSUM 0x783E69C2

mLOG_DEFINE_CATEGORY(GB, "GB", "gb");

static void GBInit(void* cpu, struct mCPUComponent* component);
Expand Down Expand Up @@ -573,6 +578,11 @@ bool GBIsBIOS(struct VFile* vf) {
case CGBE_BIOS_CHECKSUM:
case AGB_BIOS_CHECKSUM:
case AGB0_BIOS_CHECKSUM:
// Bootleg consoles
case FORTUNE_BIOS_CHECKSUM:
case GAMEFIGHTER_BIOS_CHECKSUM:
case KONGFENG_GBBC_BIOS_CHECKSUM:
case MAXSTATION_BIOS_CHECKSUM:
return true;
default:
return false;
Expand All @@ -586,12 +596,18 @@ bool GBIsCompatibleBIOS(struct VFile* vf, enum GBModel model) {
case MGB_BIOS_CHECKSUM:
case SGB_BIOS_CHECKSUM:
case SGB2_BIOS_CHECKSUM:
// Bootleg consoles
case FORTUNE_BIOS_CHECKSUM:
case GAMEFIGHTER_BIOS_CHECKSUM:
case MAXSTATION_BIOS_CHECKSUM:
return model < GB_MODEL_CGB;
case CGB_BIOS_CHECKSUM:
case CGB0_BIOS_CHECKSUM:
case CGBE_BIOS_CHECKSUM:
case AGB_BIOS_CHECKSUM:
case AGB0_BIOS_CHECKSUM:
// Bootleg consoles
case KONGFENG_GBBC_BIOS_CHECKSUM:
return model >= GB_MODEL_CGB;
default:
return false;
Expand Down Expand Up @@ -874,6 +890,10 @@ void GBDetectModel(struct GB* gb) {
switch (_GBBiosCRC32(gb->biosVf)) {
case DMG_BIOS_CHECKSUM:
case DMG0_BIOS_CHECKSUM:
// Bootleg consoles
case FORTUNE_BIOS_CHECKSUM:
case GAMEFIGHTER_BIOS_CHECKSUM:
case MAXSTATION_BIOS_CHECKSUM:
gb->model = GB_MODEL_DMG;
break;
case MGB_BIOS_CHECKSUM:
Expand All @@ -888,6 +908,8 @@ void GBDetectModel(struct GB* gb) {
case CGB_BIOS_CHECKSUM:
case CGB0_BIOS_CHECKSUM:
case CGBE_BIOS_CHECKSUM:
// Bootleg consoles
case KONGFENG_GBBC_BIOS_CHECKSUM:
gb->model = GB_MODEL_CGB;
break;
case AGB_BIOS_CHECKSUM:
Expand Down
3 changes: 0 additions & 3 deletions src/gba/bios.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@
#include <mgba/internal/gba/memory.h>
#include <mgba-util/math.h>

const uint32_t GBA_BIOS_CHECKSUM = 0xBAAE187F;
const uint32_t GBA_DS_BIOS_CHECKSUM = 0xBAAE1880;

mLOG_DEFINE_CATEGORY(GBA_BIOS, "GBA BIOS", "gba.bios");

static void _unLz77(struct GBA* gba, int width);
Expand Down
28 changes: 18 additions & 10 deletions src/gba/gba.c
Original file line number Diff line number Diff line change
Expand Up @@ -523,27 +523,35 @@ void GBALoadBIOS(struct GBA* gba, struct VFile* vf) {
mLOG(GBA, WARN, "Couldn't map BIOS");
return;
}
uint32_t checksum = GBAChecksum(bios, GBA_SIZE_BIOS);
mLOG(GBA, DEBUG, "BIOS Checksum: 0x%X", checksum);
switch (checksum) {
case GBA_BIOS_CHECKSUM:
mLOG(GBA, INFO, "Official GBA BIOS detected");
break;
case GBA_DS_BIOS_CHECKSUM:
mLOG(GBA, INFO, "Official GBA (DS) BIOS detected");
break;
case GBA_DEBUG_BIOS_CHECKSUM:
mLOG(GBA, WARN, "Known broken GBA BIOS detected, disabling");
vf->unmap(vf, bios, GBA_SIZE_BIOS);
return;
default:
mLOG(GBA, WARN, "BIOS checksum incorrect");
break;
}

if (gba->biosVf) {
gba->biosVf->unmap(gba->biosVf, gba->memory.bios, GBA_SIZE_BIOS);
gba->biosVf->close(gba->biosVf);
}
gba->biosVf = vf;
gba->memory.bios = bios;
gba->memory.fullBios = 1;
uint32_t checksum = GBAChecksum(gba->memory.bios, GBA_SIZE_BIOS);
mLOG(GBA, DEBUG, "BIOS Checksum: 0x%X", checksum);
if (checksum == GBA_BIOS_CHECKSUM) {
mLOG(GBA, INFO, "Official GBA BIOS detected");
} else if (checksum == GBA_DS_BIOS_CHECKSUM) {
mLOG(GBA, INFO, "Official GBA (DS) BIOS detected");
} else {
mLOG(GBA, WARN, "BIOS checksum incorrect");
}
gba->biosChecksum = checksum;
if (gba->memory.activeRegion == GBA_REGION_BIOS) {
gba->cpu->memory.activeRegion = gba->memory.bios;
}
// TODO: error check
}

void GBAApplyPatch(struct GBA* gba, struct Patch* patch) {
Expand Down
73 changes: 73 additions & 0 deletions src/platform/qt/ReportView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include <QBuffer>
#include <QDesktopServices>
#include <QCryptographicHash>
#include <QOffscreenSurface>
#include <QScreen>
#include <QSysInfo>
Expand Down Expand Up @@ -62,6 +63,10 @@
#include <freetype/freetype.h>
#endif

#ifdef USE_JSON_C
#include <json.h>
#endif

#ifdef USE_LIBZIP
#include <zip.h>
#endif
Expand Down Expand Up @@ -98,6 +103,7 @@ static const QLatin1String yesNo[2] = {
unsigned ReportView::s_cpuidMax = 0xFFFFFFFF;
unsigned ReportView::s_cpuidExtMax = 0xFFFFFFFF;
#endif
QHash<QString, QHash<QByteArray, QString>> ReportView::s_bioses;

ReportView::ReportView(QWidget* parent)
: QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint)
Expand All @@ -109,6 +115,33 @@ ReportView::ReportView(QWidget* parent)
m_ui.description->setText(description);
m_ui.fileView->setFont(GBAApp::app()->monospaceFont());

if (s_bioses.isEmpty()) {
QHash<QByteArray, QString> gbaBioses;
gbaBioses.insert(QByteArray::fromHex("fd2547724b505f487e6dcb29ec2ecff3af35a841a77ab2e85fd87350abd36570"), QLatin1String("Official"));
gbaBioses.insert(QByteArray::fromHex("782eb3894237ec6aa411b78ffee19078bacf10413856d33cda10b44fd9c2856b"), QLatin1String("DS"));
gbaBioses.insert(QByteArray::fromHex("9758dbf0c4c5ffefa2a710405f4df7ddc7de0399b0975e85e12fb43d8843b63d"), QLatin1String("Debug"));
s_bioses.insert(QLatin1String("GBA BIOS"), gbaBioses);

QHash<QByteArray, QString> gbBioses;
gbBioses.insert(QByteArray::fromHex("3a307a41689bee99a9a32ea021bf45136906c86b2e4f06c806738398e4f92e45"), QLatin1String("CGB-0"));
gbBioses.insert(QByteArray::fromHex("b4f2e416a35eef52cba161b159c7c8523a92594facb924b3ede0d722867c50c7"), QLatin1String("CGB"));
gbBioses.insert(QByteArray::fromHex("fe2d45405531756d87622abde6127c804bd675cb968081b2c052497a470ffeb2"), QLatin1String("AGB-0"));
gbBioses.insert(QByteArray::fromHex("fe3cceb79930c4cb6c6f62f742c2562fd4c96b827584ef8ea89d49b387bd6860"), QLatin1String("AGB"));
gbBioses.insert(QByteArray::fromHex("c56299bedd56debdbf36442238636bf5887a65c5173b33995682052353804da9"), QLatin1String("CGB-E"));
gbBioses.insert(QByteArray::fromHex("26e71cf01e301e5dc40e987cd2ecbf6d0276245890ac829db2a25323da86818e"), QLatin1String("DMG-0"));
gbBioses.insert(QByteArray::fromHex("cf053eccb4ccafff9e67339d4e78e98dce7d1ed59be819d2a1ba2232c6fce1c7"), QLatin1String("DMG"));
gbBioses.insert(QByteArray::fromHex("9e328227920e86d5530f54efedb562e9ce5b6d32a4ecdee0a278a3d9c6a114b1"), QLatin1String("Fortune/Bitman 3000B"));
gbBioses.insert(QByteArray::fromHex("7abdaeea7ac2afd39d86a2ddf044fb978ccd4e65fa4ef15ffc8fcd19df71f254"), QLatin1String("Game Fighter"));
gbBioses.insert(QByteArray::fromHex("27e4bee8a8fddc80d48393a51fd9cdf33abc981a795f6aecc59a03a12daff881"), QLatin1String("Maxstation"));
gbBioses.insert(QByteArray::fromHex("371686262f845b109a180a27e8a2dfd2e7c76bb836a67e10531cf30aeb356f4a"), QLatin1String("Kongfeng GB Boy Colour"));
gbBioses.insert(QByteArray::fromHex("a8cb5f4f1f16f2573ed2ecd8daedb9c5d1dd2c30a481f9b179b5d725d95eafe2"), QLatin1String("MGB"));
gbBioses.insert(QByteArray::fromHex("fd243c4fb27008986316ce3df29e9cfbcdc0cd52704970555a8bb76edbec3988"), QLatin1String("SGB2"));
gbBioses.insert(QByteArray::fromHex("0e4ddff32fc9d1eeaae812a157dd246459b00c9e14f2f61751f661f32361e360"), QLatin1String("SGB"));
s_bioses.insert(QLatin1String("GB BIOS"), gbBioses);
s_bioses.insert(QLatin1String("GBC BIOS"), gbBioses);
s_bioses.insert(QLatin1String("SGB BIOS"), gbBioses);
}

connect(m_ui.fileList, &QListWidget::currentTextChanged, this, &ReportView::setShownReport);
}

Expand All @@ -129,6 +162,16 @@ void ReportView::generateReport() {
swReport << QString("Git commit: %1").arg(QLatin1String(gitCommit));
swReport << QString("Git revision: %1").arg(gitRevision);
swReport << QString("OS: %1").arg(QSysInfo::prettyProductName());
#ifdef M_CORE_GBA
swReport << QString("GBA core enabled");
#else
swReport << QString("GBA core disabled");
#endif
#ifdef M_CORE_GB
swReport << QString("GB core enabled");
#else
swReport << QString("GB core disabled");
#endif
swReport << QString("Build architecture: %1").arg(QSysInfo::buildCpuArchitecture());
swReport << QString("Run architecture: %1").arg(QSysInfo::currentCpuArchitecture());
swReport << QString("Qt version: %1").arg(QLatin1String(qVersion()));
Expand Down Expand Up @@ -159,6 +202,11 @@ void ReportView::generateReport() {
#else
swReport << QString("FreeType not linked");
#endif
#ifdef USE_JSON_C
swReport << QString("json-c version: %1.%2.%3").arg(JSON_C_MAJOR_VERSION).arg(JSON_C_MINOR_VERSION).arg(JSON_C_MICRO_VERSION);
#else
swReport << QString("json-c not linked");
#endif
#ifdef USE_EDITLINE
swReport << QString("libedit version: %1.%2").arg(LIBEDIT_MAJOR).arg(LIBEDIT_MINOR);
#else
Expand Down Expand Up @@ -332,6 +380,11 @@ void ReportView::generateReport() {
InputController* input = window->inputController();
windowReport << QString("Active gamepad: %1").arg(input->gamepadIndex());
windowReport << QString("Configuration: %1").arg(configs.indexOf(config) + 1);

addBios(windowReport, config->getOption("gba.bios", QString()), QLatin1String("GBA BIOS"));
addBios(windowReport, config->getOption("gb.bios", QString()), QLatin1String("GB BIOS"));
addBios(windowReport, config->getOption("gbc.bios", QString()), QLatin1String("GBC BIOS"));
addBios(windowReport, config->getOption("sgb.bios", QString()), QLatin1String("SGB BIOS"));
addReport(QString("Window %1").arg(winId), windowReport.join('\n'));
}
for (ConfigController* config : configs) {
Expand Down Expand Up @@ -562,6 +615,26 @@ void ReportView::addScreenInfo(QStringList& report, const QScreen* screen) {
report << QString("Physical DPI: %1x%2").arg(screen->physicalDotsPerInchX()).arg(screen->physicalDotsPerInchY());
}

void ReportView::addBios(QStringList& report, const QString& path, const QString& name) {
if (path.isEmpty()) {
return;
}

QFile bios(path);
if (!bios.open(QIODevice::ReadOnly)) {
return;
}
QByteArray data = bios.readAll();
QByteArray hash = QCryptographicHash::hash(data, QCryptographicHash::Sha256);
report << QString("%1 SHA-256: %2").arg(name).arg(QString::fromLatin1(hash.toHex()));
auto iter = s_bioses[name].constFind(hash);
if (iter != s_bioses[name].end()) {
report << QString("%1: %2").arg(name).arg(*iter);
} else {
report << QString("Unknown %1").arg(name);
}
}

void ReportView::addReport(const QString& filename, const QString& report) {
m_reports[filename] = report;
m_displayOrder.append(filename);
Expand Down
3 changes: 3 additions & 0 deletions src/platform/qt/ReportView.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ private slots:
void addGamepadInfo(QStringList&);
void addROMInfo(QStringList&, CoreController*);
void addScreenInfo(QStringList&, const QScreen*);
void addBios(QStringList&, const QString& path, const QString& name);

void addReport(const QString& filename, const QString& report);
void addBinary(const QString& filename, const QByteArray& report);
Expand All @@ -57,6 +58,8 @@ private slots:
static unsigned s_cpuidExtMax;
#endif

static QHash<QString, QHash<QByteArray, QString>> s_bioses;

ConfigController* m_config;

QStringList m_displayOrder;
Expand Down
5 changes: 3 additions & 2 deletions src/platform/sdl/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,9 @@ int main(int argc, char** argv) {
mCoreConfigSetDefaultIntValue(&renderer.core->config, "logToStdout", true);
mCoreConfigLoadDefaults(&renderer.core->config, &opts);
mCoreLoadConfig(renderer.core);
mStandardLoggerInit(&_logger);
mStandardLoggerConfig(&_logger, &renderer.core->config);
mLogSetDefaultLogger(&_logger.d);

renderer.viewportWidth = renderer.core->opts.width;
renderer.viewportHeight = renderer.core->opts.height;
Expand Down Expand Up @@ -163,8 +166,6 @@ int main(int argc, char** argv) {
int ret;

// TODO: Use opts and config
mStandardLoggerInit(&_logger);
mStandardLoggerConfig(&_logger, &renderer.core->config);
ret = mSDLRun(&renderer, &args);
mSDLDetachPlayer(&renderer.events, &renderer.player);
mInputMapDeinit(&renderer.core->inputMap);
Expand Down