all repos — mgba @ bdfb1b72be8f2441c205856f614e6ce463cc7ced

mGBA Game Boy Advance Emulator

GB Test: MBC detection tests
Jeffrey Pfau jeffrey@endrift.com
Sat, 22 Oct 2016 15:57:04 -0700
commit

bdfb1b72be8f2441c205856f614e6ce463cc7ced

parent

287ab91739e5780834066f497db9b78755436912

6 files changed, 288 insertions(+), 6 deletions(-)

jump to
M src/gb/gb.csrc/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

@@ -269,6 +271,18 @@ gb->sramRealVf->close(gb->sramRealVf);

} gb->sramRealVf = NULL; 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) {

@@ -618,12 +632,11 @@

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;
M src/gb/gb.hsrc/gb/gb.h

@@ -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);
M src/gb/test/core.csrc/gb/test/core.c

@@ -7,6 +7,8 @@ #include "util/test/suite.h"

#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(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 @@ core->reset(core);

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))
M src/gb/test/gb.csrc/gb/test/gb.c

@@ -6,9 +6,11 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#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; }
A src/gb/test/mbc.c

@@ -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))
M src/util/test/suite.hsrc/util/test/suite.h

@@ -14,13 +14,20 @@ #define M_TEST_DEFINE(NAME) static void NAME (void **state ATTRIBUTE_UNUSED)

#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)