mirror of https://github.com/mgba-emu/mgba.git
GB Test: MBC detection tests
This commit is contained in:
parent
287ab91739
commit
bdfb1b72be
17
src/gb/gb.c
17
src/gb/gb.c
|
@ -23,6 +23,8 @@ const uint32_t SGB_LR35902_FREQUENCY = 0x418B1E;
|
|||
|
||||
const uint32_t GB_COMPONENT_MAGIC = 0x400000;
|
||||
|
||||
static const uint8_t _knownHeader[4] = { 0xCE, 0xED, 0x66, 0x66};
|
||||
|
||||
#define DMG_BIOS_CHECKSUM 0xC2F5CC97
|
||||
#define DMG_2_BIOS_CHECKSUM 0x59C8598E
|
||||
#define CGB_BIOS_CHECKSUM 0x41884E46
|
||||
|
@ -271,6 +273,18 @@ void GBUnloadROM(struct GB* gb) {
|
|||
gb->sramVf = NULL;
|
||||
}
|
||||
|
||||
void GBSynthesizeROM(struct VFile* vf) {
|
||||
if (!vf) {
|
||||
return;
|
||||
}
|
||||
const struct GBCartridge cart = {
|
||||
.logo = { _knownHeader[0], _knownHeader[1], _knownHeader[2], _knownHeader[3]}
|
||||
};
|
||||
|
||||
vf->seek(vf, 0x100, SEEK_SET);
|
||||
vf->write(vf, &cart, sizeof(cart));
|
||||
}
|
||||
|
||||
void GBLoadBIOS(struct GB* gb, struct VFile* vf) {
|
||||
gb->biosVf = vf;
|
||||
}
|
||||
|
@ -618,12 +632,11 @@ void GBIllegal(struct LR35902Core* cpu) {
|
|||
bool GBIsROM(struct VFile* vf) {
|
||||
vf->seek(vf, 0x104, SEEK_SET);
|
||||
uint8_t header[4];
|
||||
static const uint8_t knownHeader[4] = { 0xCE, 0xED, 0x66, 0x66};
|
||||
|
||||
if (vf->read(vf, &header, sizeof(header)) < (ssize_t) sizeof(header)) {
|
||||
return false;
|
||||
}
|
||||
if (memcmp(header, knownHeader, sizeof(header))) {
|
||||
if (memcmp(header, _knownHeader, sizeof(header))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -118,6 +118,7 @@ bool GBLoadROM(struct GB* gb, struct VFile* vf);
|
|||
bool GBLoadSave(struct GB* gb, struct VFile* vf);
|
||||
void GBYankROM(struct GB* gb);
|
||||
void GBUnloadROM(struct GB* gb);
|
||||
void GBSynthesizeROM(struct VFile* vf);
|
||||
|
||||
bool GBIsBIOS(struct VFile* vf);
|
||||
void GBLoadBIOS(struct GB* gb, struct VFile* vf);
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
#include "core/core.h"
|
||||
#include "gb/core.h"
|
||||
#include "gb/gb.h"
|
||||
#include "util/vfs.h"
|
||||
|
||||
M_TEST_DEFINE(create) {
|
||||
struct mCore* core = GBCoreCreate();
|
||||
|
@ -18,7 +20,7 @@ M_TEST_DEFINE(create) {
|
|||
M_TEST_DEFINE(platform) {
|
||||
struct mCore* core = GBCoreCreate();
|
||||
assert_non_null(core);
|
||||
assert_true(core->platform(core) == PLATFORM_GB);
|
||||
assert_int_equal(core->platform(core), PLATFORM_GB);
|
||||
assert_true(core->init(core));
|
||||
core->deinit(core);
|
||||
}
|
||||
|
@ -40,8 +42,20 @@ M_TEST_DEFINE(loadNullROM) {
|
|||
core->deinit(core);
|
||||
}
|
||||
|
||||
M_TEST_DEFINE(isROM) {
|
||||
struct VFile* vf = VFileMemChunk(NULL, 2048);
|
||||
GBSynthesizeROM(vf);
|
||||
assert_true(GBIsROM(vf));
|
||||
struct mCore* core = mCoreFindVF(vf);
|
||||
assert_non_null(core);
|
||||
assert_int_equal(core->platform(core), PLATFORM_GB);
|
||||
assert_true(core->init(core));
|
||||
core->deinit(core);
|
||||
}
|
||||
|
||||
M_TEST_SUITE_DEFINE(GBCore,
|
||||
cmocka_unit_test(create),
|
||||
cmocka_unit_test(platform),
|
||||
cmocka_unit_test(reset),
|
||||
cmocka_unit_test(loadNullROM))
|
||||
cmocka_unit_test(loadNullROM),
|
||||
cmocka_unit_test(isROM))
|
||||
|
|
|
@ -6,9 +6,11 @@
|
|||
#include "util/test/suite.h"
|
||||
|
||||
M_TEST_SUITE_DECLARE(GBCore);
|
||||
M_TEST_SUITE_DECLARE(GBMBC);
|
||||
|
||||
int TestRunGB(void) {
|
||||
int failures = 0;
|
||||
failures += M_TEST_SUITE_RUN(GBCore);
|
||||
failures += M_TEST_SUITE_RUN(GBMBC);
|
||||
return failures;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,245 @@
|
|||
/* Copyright (c) 2013-2016 Jeffrey Pfau
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include "util/test/suite.h"
|
||||
|
||||
#include "core/core.h"
|
||||
#include "gb/core.h"
|
||||
#include "gb/gb.h"
|
||||
#include "gb/mbc.h"
|
||||
#include "util/vfs.h"
|
||||
|
||||
M_TEST_SUITE_SETUP(GBMBC) {
|
||||
struct VFile* vf = VFileMemChunk(NULL, 2048);
|
||||
GBSynthesizeROM(vf);
|
||||
struct mCore* core = GBCoreCreate();
|
||||
core->init(core);
|
||||
core->loadROM(core, vf);
|
||||
*state = core;
|
||||
return 0;
|
||||
}
|
||||
|
||||
M_TEST_SUITE_TEARDOWN(GBMBC) {
|
||||
if (!*state) {
|
||||
return 0;
|
||||
}
|
||||
struct mCore* core = *state;
|
||||
core->deinit(core);
|
||||
return 0;
|
||||
}
|
||||
M_TEST_DEFINE(detectNone) {
|
||||
struct mCore* core = *state;
|
||||
struct GB* gb = core->board;
|
||||
struct GBCartridge* cart = (struct GBCartridge*) &gb->memory.rom[0x100];
|
||||
|
||||
gb->memory.mbcType = GB_MBC_AUTODETECT;
|
||||
cart->type = 0x00;
|
||||
core->reset(core);
|
||||
assert_int_equal(gb->memory.mbcType, GB_MBC_NONE);
|
||||
|
||||
gb->memory.mbcType = GB_MBC_AUTODETECT;
|
||||
cart->type = 0x08;
|
||||
core->reset(core);
|
||||
assert_int_equal(gb->memory.mbcType, GB_MBC_NONE);
|
||||
|
||||
|
||||
gb->memory.mbcType = GB_MBC_AUTODETECT;
|
||||
cart->type = 0x09;
|
||||
core->reset(core);
|
||||
assert_int_equal(gb->memory.mbcType, GB_MBC_NONE);
|
||||
|
||||
|
||||
gb->memory.mbcType = GB_MBC_AUTODETECT;
|
||||
cart->type = 0x0A;
|
||||
core->reset(core);
|
||||
assert_int_not_equal(gb->memory.mbcType, GB_MBC_NONE);
|
||||
}
|
||||
|
||||
M_TEST_DEFINE(detect1) {
|
||||
struct mCore* core = *state;
|
||||
struct GB* gb = core->board;
|
||||
struct GBCartridge* cart = (struct GBCartridge*) &gb->memory.rom[0x100];
|
||||
|
||||
gb->memory.mbcType = GB_MBC_AUTODETECT;
|
||||
cart->type = 0x00;
|
||||
core->reset(core);
|
||||
assert_int_not_equal(gb->memory.mbcType, GB_MBC1);
|
||||
|
||||
gb->memory.mbcType = GB_MBC_AUTODETECT;
|
||||
cart->type = 0x01;
|
||||
core->reset(core);
|
||||
assert_int_equal(gb->memory.mbcType, GB_MBC1);
|
||||
|
||||
gb->memory.mbcType = GB_MBC_AUTODETECT;
|
||||
cart->type = 0x02;
|
||||
core->reset(core);
|
||||
assert_int_equal(gb->memory.mbcType, GB_MBC1);
|
||||
|
||||
gb->memory.mbcType = GB_MBC_AUTODETECT;
|
||||
cart->type = 0x03;
|
||||
core->reset(core);
|
||||
assert_int_equal(gb->memory.mbcType, GB_MBC1);
|
||||
|
||||
gb->memory.mbcType = GB_MBC_AUTODETECT;
|
||||
cart->type = 0x04;
|
||||
core->reset(core);
|
||||
assert_int_not_equal(gb->memory.mbcType, GB_MBC1);
|
||||
}
|
||||
|
||||
M_TEST_DEFINE(detect2) {
|
||||
struct mCore* core = *state;
|
||||
struct GB* gb = core->board;
|
||||
struct GBCartridge* cart = (struct GBCartridge*) &gb->memory.rom[0x100];
|
||||
|
||||
gb->memory.mbcType = GB_MBC_AUTODETECT;
|
||||
cart->type = 0x04;
|
||||
core->reset(core);
|
||||
assert_int_not_equal(gb->memory.mbcType, GB_MBC2);
|
||||
|
||||
gb->memory.mbcType = GB_MBC_AUTODETECT;
|
||||
cart->type = 0x05;
|
||||
core->reset(core);
|
||||
assert_int_equal(gb->memory.mbcType, GB_MBC2);
|
||||
|
||||
gb->memory.mbcType = GB_MBC_AUTODETECT;
|
||||
cart->type = 0x06;
|
||||
core->reset(core);
|
||||
assert_int_equal(gb->memory.mbcType, GB_MBC2);
|
||||
|
||||
gb->memory.mbcType = GB_MBC_AUTODETECT;
|
||||
cart->type = 0x07;
|
||||
core->reset(core);
|
||||
assert_int_not_equal(gb->memory.mbcType, GB_MBC2);
|
||||
}
|
||||
|
||||
M_TEST_DEFINE(detect3) {
|
||||
struct mCore* core = *state;
|
||||
struct GB* gb = core->board;
|
||||
struct GBCartridge* cart = (struct GBCartridge*) &gb->memory.rom[0x100];
|
||||
|
||||
gb->memory.mbcType = GB_MBC_AUTODETECT;
|
||||
cart->type = 0x0E;
|
||||
core->reset(core);
|
||||
assert_int_not_equal(gb->memory.mbcType, GB_MBC3);
|
||||
assert_int_not_equal(gb->memory.mbcType, GB_MBC3_RTC);
|
||||
|
||||
gb->memory.mbcType = GB_MBC_AUTODETECT;
|
||||
cart->type = 0x0F;
|
||||
core->reset(core);
|
||||
assert_int_equal(gb->memory.mbcType, GB_MBC3_RTC);
|
||||
|
||||
gb->memory.mbcType = GB_MBC_AUTODETECT;
|
||||
cart->type = 0x10;
|
||||
core->reset(core);
|
||||
assert_int_equal(gb->memory.mbcType, GB_MBC3_RTC);
|
||||
|
||||
gb->memory.mbcType = GB_MBC_AUTODETECT;
|
||||
cart->type = 0x11;
|
||||
core->reset(core);
|
||||
assert_int_equal(gb->memory.mbcType, GB_MBC3);
|
||||
|
||||
gb->memory.mbcType = GB_MBC_AUTODETECT;
|
||||
cart->type = 0x12;
|
||||
core->reset(core);
|
||||
assert_int_equal(gb->memory.mbcType, GB_MBC3);
|
||||
|
||||
gb->memory.mbcType = GB_MBC_AUTODETECT;
|
||||
cart->type = 0x13;
|
||||
core->reset(core);
|
||||
assert_int_equal(gb->memory.mbcType, GB_MBC3);
|
||||
|
||||
gb->memory.mbcType = GB_MBC_AUTODETECT;
|
||||
cart->type = 0x14;
|
||||
core->reset(core);
|
||||
assert_int_not_equal(gb->memory.mbcType, GB_MBC3);
|
||||
assert_int_not_equal(gb->memory.mbcType, GB_MBC3_RTC);
|
||||
}
|
||||
|
||||
M_TEST_DEFINE(detect5) {
|
||||
struct mCore* core = *state;
|
||||
struct GB* gb = core->board;
|
||||
struct GBCartridge* cart = (struct GBCartridge*) &gb->memory.rom[0x100];
|
||||
|
||||
gb->memory.mbcType = GB_MBC_AUTODETECT;
|
||||
cart->type = 0x19;
|
||||
core->reset(core);
|
||||
assert_int_equal(gb->memory.mbcType, GB_MBC5);
|
||||
|
||||
gb->memory.mbcType = GB_MBC_AUTODETECT;
|
||||
cart->type = 0x1A;
|
||||
core->reset(core);
|
||||
assert_int_equal(gb->memory.mbcType, GB_MBC5);
|
||||
|
||||
gb->memory.mbcType = GB_MBC_AUTODETECT;
|
||||
cart->type = 0x1B;
|
||||
core->reset(core);
|
||||
assert_int_equal(gb->memory.mbcType, GB_MBC5);
|
||||
|
||||
gb->memory.mbcType = GB_MBC_AUTODETECT;
|
||||
cart->type = 0x1C;
|
||||
core->reset(core);
|
||||
assert_int_equal(gb->memory.mbcType, GB_MBC5_RUMBLE);
|
||||
|
||||
gb->memory.mbcType = GB_MBC_AUTODETECT;
|
||||
cart->type = 0x1D;
|
||||
core->reset(core);
|
||||
assert_int_equal(gb->memory.mbcType, GB_MBC5_RUMBLE);
|
||||
|
||||
gb->memory.mbcType = GB_MBC_AUTODETECT;
|
||||
cart->type = 0x1E;
|
||||
core->reset(core);
|
||||
assert_int_equal(gb->memory.mbcType, GB_MBC5_RUMBLE);
|
||||
}
|
||||
|
||||
M_TEST_DEFINE(detect6) {
|
||||
struct mCore* core = *state;
|
||||
struct GB* gb = core->board;
|
||||
struct GBCartridge* cart = (struct GBCartridge*) &gb->memory.rom[0x100];
|
||||
|
||||
gb->memory.mbcType = GB_MBC_AUTODETECT;
|
||||
cart->type = 0x1F;
|
||||
core->reset(core);
|
||||
assert_int_not_equal(gb->memory.mbcType, GB_MBC6);
|
||||
|
||||
gb->memory.mbcType = GB_MBC_AUTODETECT;
|
||||
cart->type = 0x20;
|
||||
core->reset(core);
|
||||
assert_int_equal(gb->memory.mbcType, GB_MBC6);
|
||||
|
||||
gb->memory.mbcType = GB_MBC_AUTODETECT;
|
||||
cart->type = 0x21;
|
||||
core->reset(core);
|
||||
assert_int_not_equal(gb->memory.mbcType, GB_MBC6);
|
||||
}
|
||||
|
||||
M_TEST_DEFINE(detect7) {
|
||||
struct mCore* core = *state;
|
||||
struct GB* gb = core->board;
|
||||
struct GBCartridge* cart = (struct GBCartridge*) &gb->memory.rom[0x100];
|
||||
|
||||
gb->memory.mbcType = GB_MBC_AUTODETECT;
|
||||
cart->type = 0x21;
|
||||
core->reset(core);
|
||||
assert_int_not_equal(gb->memory.mbcType, GB_MBC7);
|
||||
|
||||
gb->memory.mbcType = GB_MBC_AUTODETECT;
|
||||
cart->type = 0x22;
|
||||
core->reset(core);
|
||||
assert_int_equal(gb->memory.mbcType, GB_MBC7);
|
||||
|
||||
gb->memory.mbcType = GB_MBC_AUTODETECT;
|
||||
cart->type = 0x23;
|
||||
core->reset(core);
|
||||
assert_int_not_equal(gb->memory.mbcType, GB_MBC7);
|
||||
}
|
||||
|
||||
M_TEST_SUITE_DEFINE_SETUP_TEARDOWN(GBMBC,
|
||||
cmocka_unit_test(detectNone),
|
||||
cmocka_unit_test(detect1),
|
||||
cmocka_unit_test(detect2),
|
||||
cmocka_unit_test(detect3),
|
||||
cmocka_unit_test(detect5),
|
||||
cmocka_unit_test(detect6),
|
||||
cmocka_unit_test(detect7))
|
|
@ -14,14 +14,21 @@
|
|||
|
||||
#define M_TEST_SUITE(NAME) _testSuite_ ## NAME
|
||||
#define M_TEST_SUITE_RUN(NAME) printf("\nRunning suite %s\n", # NAME), M_TEST_SUITE(NAME)()
|
||||
#define M_TEST_SUITE_DEFINE(NAME, ...) \
|
||||
#define M_TEST_SUITE_DEFINE(NAME, ...) M_TEST_SUITE_DEFINE_EX(NAME, NULL, NULL, __VA_ARGS__)
|
||||
#define M_TEST_SUITE_DEFINE_SETUP(NAME, ...) M_TEST_SUITE_DEFINE_EX(NAME, _testSuite_setup_ ## NAME, NULL, __VA_ARGS__)
|
||||
#define M_TEST_SUITE_DEFINE_TEARDOWN(NAME, ...) M_TEST_SUITE_DEFINE_EX(NAME, NULL, _testSuite_teardown_ ## NAME, __VA_ARGS__)
|
||||
#define M_TEST_SUITE_DEFINE_SETUP_TEARDOWN(NAME, ...) M_TEST_SUITE_DEFINE_EX(NAME, _testSuite_setup_ ## NAME, _testSuite_teardown_ ## NAME, __VA_ARGS__)
|
||||
#define M_TEST_SUITE_DEFINE_EX(NAME, SETUP, TEARDOWN, ...) \
|
||||
int M_TEST_SUITE(NAME) (void) { \
|
||||
const static struct CMUnitTest tests[] = { \
|
||||
__VA_ARGS__ \
|
||||
}; \
|
||||
return cmocka_run_group_tests_name(# NAME, tests, NULL, NULL); \
|
||||
return cmocka_run_group_tests_name(# NAME, tests, SETUP, TEARDOWN); \
|
||||
}
|
||||
|
||||
#define M_TEST_SUITE_SETUP(NAME) static int _testSuite_setup_ ## NAME (void **state ATTRIBUTE_UNUSED)
|
||||
#define M_TEST_SUITE_TEARDOWN(NAME) static int _testSuite_teardown_ ## NAME (void **state ATTRIBUTE_UNUSED)
|
||||
|
||||
#define M_TEST_SUITE_DECLARE(NAME) extern int M_TEST_SUITE(NAME) (void)
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue