GB: Initial BIOS support
Jeffrey Pfau jeffrey@endrift.com
Thu, 19 May 2016 22:31:13 -0700
6 files changed,
93 insertions(+),
26 deletions(-)
M
src/gb/core.c
→
src/gb/core.c
@@ -13,6 +13,7 @@ #include "gb/renderers/software.h"
#include "lr35902/debugger/debugger.h" #include "util/memory.h" #include "util/patch.h" +#include "util/vfs.h" struct GBCore { struct mCore d;@@ -93,6 +94,16 @@ } else {
gb->audio.masterVolume = core->opts.volume; } 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) {@@ -148,11 +159,9 @@ return GBLoadROM(core->board, vf);
} static bool _GBCoreLoadBIOS(struct mCore* core, struct VFile* vf, int type) { - UNUSED(core); - UNUSED(vf); UNUSED(type); - // TODO - return false; + GBLoadBIOS(core->board, vf); + return true; } static bool _GBCoreLoadSave(struct mCore* core, struct VFile* vf) {
M
src/gb/gb.c
→
src/gb/gb.c
@@ -88,6 +88,7 @@ return false;
} gb->yankedRomSize = 0; gb->memory.rom = gb->pristineRom; + gb->memory.romBase = gb->memory.rom; gb->memory.romSize = gb->pristineRomSize; gb->romCrc32 = doCrc32(gb->memory.rom, gb->memory.romSize);@@ -109,6 +110,9 @@ }
void GBUnloadROM(struct GB* gb) { // 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->yankedRomSize) { gb->yankedRomSize = 0;@@ -135,6 +139,10 @@ }
gb->memory.sram = 0; } +void GBLoadBIOS(struct GB* gb, struct VFile* vf) { + gb->biosVf = vf; +} + void GBApplyPatch(struct GB* gb, struct Patch* patch) { size_t patchedSize = patch->outputSize(patch, gb->memory.romSize); if (!patchedSize) {@@ -171,31 +179,71 @@
void GBReset(struct LR35902Core* cpu) { struct GB* gb = (struct GB*) cpu->master; - 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; + if (gb->biosVf) { + gb->biosVf->seek(gb->biosVf, 0, SEEK_SET); + gb->memory.romBase = malloc(GB_SIZE_CART_BANK0); + ssize_t size = gb->biosVf->read(gb->biosVf, gb->memory.romBase, GB_SIZE_CART_BANK0); + uint32_t biosCrc = doCrc32(gb->memory.romBase, size); + 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->e = 0x08; + cpu->e = 0; 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->l = 0; + cpu->sp = 0; + cpu->pc = 0; } + 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->d = 0; - cpu->sp = 0xFFFE; - cpu->pc = 0x100; + cpu->memory.setActiveRegion(cpu, cpu->pc); if (gb->yankedRomSize) {
M
src/gb/gb.h
→
src/gb/gb.h
@@ -62,6 +62,7 @@ size_t pristineRomSize;
size_t yankedRomSize; uint32_t romCrc32; struct VFile* romVf; + struct VFile* biosVf; struct VFile* sramVf; struct mAVStream* stream;@@ -107,6 +108,8 @@ 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 GBLoadBIOS(struct GB* gb, struct VFile* vf); struct Patch; void GBApplyPatch(struct GB* gb, struct Patch* patch);
M
src/gb/io.c
→
src/gb/io.c
@@ -311,6 +311,12 @@ break;
case REG_STAT: GBVideoWriteSTAT(&gb->video, value); break; + case 0x50: + if (gb->memory.romBase != gb->memory.rom) { + free(gb->memory.romBase); + gb->memory.romBase = gb->memory.rom; + } + break; case REG_IE: gb->memory.ie = value; GBUpdateIRQs(gb);
M
src/gb/memory.c
→
src/gb/memory.c
@@ -52,7 +52,7 @@ case GB_REGION_CART_BANK0 + 1:
case GB_REGION_CART_BANK0 + 2: case GB_REGION_CART_BANK0 + 3: cpu->memory.cpuLoad8 = GBFastLoad8; - cpu->memory.activeRegion = memory->rom; + cpu->memory.activeRegion = memory->romBase; cpu->memory.activeRegionEnd = GB_BASE_CART_BANK1; cpu->memory.activeMask = GB_SIZE_CART_BANK0 - 1; break;@@ -211,7 +211,7 @@ case GB_REGION_CART_BANK0:
case GB_REGION_CART_BANK0 + 1: case GB_REGION_CART_BANK0 + 2: 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 + 1: case GB_REGION_CART_BANK1 + 2:
M
src/gb/memory.h
→
src/gb/memory.h
@@ -112,6 +112,7 @@
struct mRotationSource; struct GBMemory { uint8_t* rom; + uint8_t* romBase; uint8_t* romBank; enum GBMemoryBankControllerType mbcType; GBMemoryBankController mbc;