GB Test: MBC detection tests

This commit is contained in:
Jeffrey Pfau 2016-10-22 15:57:04 -07:00
parent 287ab91739
commit bdfb1b72be
6 changed files with 288 additions and 6 deletions

View File

@ -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;

View File

@ -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);

View File

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

View File

@ -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;
}

245
src/gb/test/mbc.c Normal file
View File

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

View File

@ -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