GB: Initial BIOS support

This commit is contained in:
Jeffrey Pfau 2016-05-19 22:31:13 -07:00
parent 2f33cd70f6
commit eb4b53a7c4
6 changed files with 93 additions and 26 deletions

View File

@ -13,6 +13,7 @@
#include "lr35902/debugger/debugger.h" #include "lr35902/debugger/debugger.h"
#include "util/memory.h" #include "util/memory.h"
#include "util/patch.h" #include "util/patch.h"
#include "util/vfs.h"
struct GBCore { struct GBCore {
struct mCore d; struct mCore d;
@ -93,6 +94,16 @@ static void _GBCoreLoadConfig(struct mCore* core, const struct mCoreConfig* conf
gb->audio.masterVolume = core->opts.volume; gb->audio.masterVolume = core->opts.volume;
} }
gb->video.frameskip = core->opts.frameskip; gb->video.frameskip = core->opts.frameskip;
#if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2
struct VFile* bios = 0;
if (core->opts.useBios && core->opts.bios) {
bios = VFileOpen(core->opts.bios, O_RDONLY);
}
if (bios) {
GBLoadBIOS(gb, bios);
}
#endif
} }
static void _GBCoreDesiredVideoDimensions(struct mCore* core, unsigned* width, unsigned* height) { static void _GBCoreDesiredVideoDimensions(struct mCore* core, unsigned* width, unsigned* height) {
@ -148,11 +159,9 @@ static bool _GBCoreLoadROM(struct mCore* core, struct VFile* vf) {
} }
static bool _GBCoreLoadBIOS(struct mCore* core, struct VFile* vf, int type) { static bool _GBCoreLoadBIOS(struct mCore* core, struct VFile* vf, int type) {
UNUSED(core);
UNUSED(vf);
UNUSED(type); UNUSED(type);
// TODO GBLoadBIOS(core->board, vf);
return false; return true;
} }
static bool _GBCoreLoadSave(struct mCore* core, struct VFile* vf) { static bool _GBCoreLoadSave(struct mCore* core, struct VFile* vf) {

View File

@ -88,6 +88,7 @@ bool GBLoadROM(struct GB* gb, struct VFile* vf) {
} }
gb->yankedRomSize = 0; gb->yankedRomSize = 0;
gb->memory.rom = gb->pristineRom; gb->memory.rom = gb->pristineRom;
gb->memory.romBase = gb->memory.rom;
gb->memory.romSize = gb->pristineRomSize; gb->memory.romSize = gb->pristineRomSize;
gb->romCrc32 = doCrc32(gb->memory.rom, gb->memory.romSize); gb->romCrc32 = doCrc32(gb->memory.rom, gb->memory.romSize);
@ -109,6 +110,9 @@ bool GBLoadSave(struct GB* gb, struct VFile* vf) {
void GBUnloadROM(struct GB* gb) { void GBUnloadROM(struct GB* gb) {
// TODO: Share with GBAUnloadROM // TODO: Share with GBAUnloadROM
if (gb->memory.rom && gb->memory.romBase != gb->memory.rom) {
free(gb->memory.romBase);
}
if (gb->memory.rom && gb->pristineRom != gb->memory.rom) { if (gb->memory.rom && gb->pristineRom != gb->memory.rom) {
if (gb->yankedRomSize) { if (gb->yankedRomSize) {
gb->yankedRomSize = 0; gb->yankedRomSize = 0;
@ -135,6 +139,10 @@ void GBUnloadROM(struct GB* gb) {
gb->memory.sram = 0; gb->memory.sram = 0;
} }
void GBLoadBIOS(struct GB* gb, struct VFile* vf) {
gb->biosVf = vf;
}
void GBApplyPatch(struct GB* gb, struct Patch* patch) { void GBApplyPatch(struct GB* gb, struct Patch* patch) {
size_t patchedSize = patch->outputSize(patch, gb->memory.romSize); size_t patchedSize = patch->outputSize(patch, gb->memory.romSize);
if (!patchedSize) { if (!patchedSize) {
@ -171,31 +179,71 @@ void GBInterruptHandlerInit(struct LR35902InterruptHandler* irqh) {
void GBReset(struct LR35902Core* cpu) { void GBReset(struct LR35902Core* cpu) {
struct GB* gb = (struct GB*) cpu->master; struct GB* gb = (struct GB*) cpu->master;
const struct GBCartridge* cart = (const struct GBCartridge*) &gb->memory.rom[0x100]; if (gb->biosVf) {
if (cart->cgb & 0x80) { gb->biosVf->seek(gb->biosVf, 0, SEEK_SET);
gb->model = GB_MODEL_CGB; gb->memory.romBase = malloc(GB_SIZE_CART_BANK0);
gb->audio.style = GB_AUDIO_CGB; ssize_t size = gb->biosVf->read(gb->biosVf, gb->memory.romBase, GB_SIZE_CART_BANK0);
cpu->a = 0x11; uint32_t biosCrc = doCrc32(gb->memory.romBase, size);
cpu->f.packed = 0x80; switch (biosCrc) {
case 0x59C8598E:
gb->model = GB_MODEL_DMG;
gb->audio.style = GB_AUDIO_DMG;
break;
case 0x41884E46:
gb->model = GB_MODEL_CGB;
gb->audio.style = GB_AUDIO_CGB;
break;
default:
free(gb->memory.romBase);
gb->memory.romBase = gb->memory.rom;
gb->biosVf = NULL;
break;
}
memcpy(&gb->memory.romBase[size], &gb->memory.rom[size], GB_SIZE_CART_BANK0 - size);
if (size > 0x100) {
memcpy(&gb->memory.romBase[0x100], &gb->memory.rom[0x100], sizeof(struct GBCartridge));
}
cpu->a = 0;
cpu->f.packed = 0;
cpu->c = 0; cpu->c = 0;
cpu->e = 0x08; cpu->e = 0;
cpu->h = 0; cpu->h = 0;
cpu->l = 0x7C; cpu->l = 0;
} else { cpu->sp = 0;
// TODO: SGB cpu->pc = 0;
gb->model = GB_MODEL_DMG;
gb->audio.style = GB_AUDIO_DMG;
cpu->a = 1;
cpu->f.packed = 0xB0;
cpu->c = 0x13;
cpu->e = 0xD8;
cpu->h = 1;
cpu->l = 0x4D;
} }
if (!gb->biosVf) {
const struct GBCartridge* cart = (const struct GBCartridge*) &gb->memory.rom[0x100];
if (cart->cgb & 0x80) {
gb->model = GB_MODEL_CGB;
gb->audio.style = GB_AUDIO_CGB;
cpu->a = 0x11;
cpu->f.packed = 0x80;
cpu->c = 0;
cpu->e = 0x08;
cpu->h = 0;
cpu->l = 0x7C;
} else {
// TODO: SGB
gb->model = GB_MODEL_DMG;
gb->audio.style = GB_AUDIO_DMG;
cpu->a = 1;
cpu->f.packed = 0xB0;
cpu->c = 0x13;
cpu->e = 0xD8;
cpu->h = 1;
cpu->l = 0x4D;
}
cpu->sp = 0xFFFE;
cpu->pc = 0x100;
}
cpu->b = 0; cpu->b = 0;
cpu->d = 0; cpu->d = 0;
cpu->sp = 0xFFFE;
cpu->pc = 0x100;
cpu->memory.setActiveRegion(cpu, cpu->pc); cpu->memory.setActiveRegion(cpu, cpu->pc);
if (gb->yankedRomSize) { if (gb->yankedRomSize) {

View File

@ -62,6 +62,7 @@ struct GB {
size_t yankedRomSize; size_t yankedRomSize;
uint32_t romCrc32; uint32_t romCrc32;
struct VFile* romVf; struct VFile* romVf;
struct VFile* biosVf;
struct VFile* sramVf; struct VFile* sramVf;
struct mAVStream* stream; struct mAVStream* stream;
@ -108,6 +109,8 @@ bool GBLoadSave(struct GB* gb, struct VFile* vf);
void GBYankROM(struct GB* gb); void GBYankROM(struct GB* gb);
void GBUnloadROM(struct GB* gb); void GBUnloadROM(struct GB* gb);
void GBLoadBIOS(struct GB* gb, struct VFile* vf);
struct Patch; struct Patch;
void GBApplyPatch(struct GB* gb, struct Patch* patch); void GBApplyPatch(struct GB* gb, struct Patch* patch);

View File

@ -311,6 +311,12 @@ void GBIOWrite(struct GB* gb, unsigned address, uint8_t value) {
case REG_STAT: case REG_STAT:
GBVideoWriteSTAT(&gb->video, value); GBVideoWriteSTAT(&gb->video, value);
break; break;
case 0x50:
if (gb->memory.romBase != gb->memory.rom) {
free(gb->memory.romBase);
gb->memory.romBase = gb->memory.rom;
}
break;
case REG_IE: case REG_IE:
gb->memory.ie = value; gb->memory.ie = value;
GBUpdateIRQs(gb); GBUpdateIRQs(gb);

View File

@ -52,7 +52,7 @@ static void GBSetActiveRegion(struct LR35902Core* cpu, uint16_t address) {
case GB_REGION_CART_BANK0 + 2: case GB_REGION_CART_BANK0 + 2:
case GB_REGION_CART_BANK0 + 3: case GB_REGION_CART_BANK0 + 3:
cpu->memory.cpuLoad8 = GBFastLoad8; cpu->memory.cpuLoad8 = GBFastLoad8;
cpu->memory.activeRegion = memory->rom; cpu->memory.activeRegion = memory->romBase;
cpu->memory.activeRegionEnd = GB_BASE_CART_BANK1; cpu->memory.activeRegionEnd = GB_BASE_CART_BANK1;
cpu->memory.activeMask = GB_SIZE_CART_BANK0 - 1; cpu->memory.activeMask = GB_SIZE_CART_BANK0 - 1;
break; break;
@ -211,7 +211,7 @@ uint8_t GBLoad8(struct LR35902Core* cpu, uint16_t address) {
case GB_REGION_CART_BANK0 + 1: case GB_REGION_CART_BANK0 + 1:
case GB_REGION_CART_BANK0 + 2: case GB_REGION_CART_BANK0 + 2:
case GB_REGION_CART_BANK0 + 3: case GB_REGION_CART_BANK0 + 3:
return memory->rom[address & (GB_SIZE_CART_BANK0 - 1)]; return memory->romBase[address & (GB_SIZE_CART_BANK0 - 1)];
case GB_REGION_CART_BANK1: case GB_REGION_CART_BANK1:
case GB_REGION_CART_BANK1 + 1: case GB_REGION_CART_BANK1 + 1:
case GB_REGION_CART_BANK1 + 2: case GB_REGION_CART_BANK1 + 2:

View File

@ -112,6 +112,7 @@ union GBMBCState {
struct mRotationSource; struct mRotationSource;
struct GBMemory { struct GBMemory {
uint8_t* rom; uint8_t* rom;
uint8_t* romBase;
uint8_t* romBank; uint8_t* romBank;
enum GBMemoryBankControllerType mbcType; enum GBMemoryBankControllerType mbcType;
GBMemoryBankController mbc; GBMemoryBankController mbc;