mirror of https://github.com/mgba-emu/mgba.git
GB: Initial BIOS support
This commit is contained in:
parent
2f33cd70f6
commit
eb4b53a7c4
|
@ -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) {
|
||||||
|
|
88
src/gb/gb.c
88
src/gb/gb.c
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue