GB: Add yanking

This commit is contained in:
Vicki Pfau 2019-09-07 18:32:37 -07:00
parent 7c8d253123
commit a44a8f668f
7 changed files with 54 additions and 9 deletions

View File

@ -20,6 +20,7 @@ Features:
- Support for unlicensed Wisdom Tree Game Boy mapper - Support for unlicensed Wisdom Tree Game Boy mapper
- Qt: Add export button for tile view (closes mgba.io/i/1507) - Qt: Add export button for tile view (closes mgba.io/i/1507)
- Qt: Add recent game list clearing (closes mgba.io/i/1380) - Qt: Add recent game list clearing (closes mgba.io/i/1380)
- GB: Yanking gamepak now supported
Emulation fixes: Emulation fixes:
- GBA: All IRQs have 7 cycle delay (fixes mgba.io/i/539, mgba.io/i/1208) - GBA: All IRQs have 7 cycle delay (fixes mgba.io/i/539, mgba.io/i/1208)
- GBA: Reset now reloads multiboot ROMs - GBA: Reset now reloads multiboot ROMs

View File

@ -94,6 +94,7 @@ struct GB {
bool isPristine; bool isPristine;
size_t pristineRomSize; size_t pristineRomSize;
size_t yankedRomSize; size_t yankedRomSize;
enum GBMemoryBankControllerType yankedMbc;
uint32_t romCrc32; uint32_t romCrc32;
struct VFile* romVf; struct VFile* romVf;
struct VFile* biosVf; struct VFile* biosVf;
@ -163,6 +164,7 @@ bool GBLoadROM(struct GB* gb, struct VFile* vf);
bool GBLoadSave(struct GB* gb, struct VFile* vf); bool GBLoadSave(struct GB* gb, struct VFile* vf);
void GBUnloadROM(struct GB* gb); void GBUnloadROM(struct GB* gb);
void GBSynthesizeROM(struct VFile* vf); void GBSynthesizeROM(struct VFile* vf);
void GBYankROM(struct GB* gb);
void GBLoadBIOS(struct GB* gb, struct VFile* vf); void GBLoadBIOS(struct GB* gb, struct VFile* vf);

View File

@ -127,6 +127,19 @@ bool GBLoadROM(struct GB* gb, struct VFile* vf) {
return true; return true;
} }
void GBYankROM(struct GB* gb) {
gb->yankedRomSize = gb->memory.romSize;
gb->yankedMbc = gb->memory.mbcType;
gb->memory.romSize = 0;
gb->memory.mbcType = GB_MBC_NONE;
gb->memory.sramAccess = false;
if (gb->cpu) {
struct LR35902Core* cpu = gb->cpu;
cpu->memory.setActiveRegion(cpu, cpu->pc);
}
}
static void GBSramDeinit(struct GB* gb) { static void GBSramDeinit(struct GB* gb) {
if (gb->sramVf) { if (gb->sramVf) {
gb->sramVf->unmap(gb->sramVf, gb->memory.sram, gb->sramSize); gb->sramVf->unmap(gb->sramVf, gb->memory.sram, gb->sramSize);
@ -430,6 +443,7 @@ void GBReset(struct LR35902Core* cpu) {
if (gb->yankedRomSize) { if (gb->yankedRomSize) {
gb->memory.romSize = gb->yankedRomSize; gb->memory.romSize = gb->yankedRomSize;
gb->memory.mbcType = gb->yankedMbc;
gb->yankedRomSize = 0; gb->yankedRomSize = 0;
} }

View File

@ -458,6 +458,9 @@ void GBIOWrite(struct GB* gb, unsigned address, uint8_t value) {
value = gb->video.stat; value = gb->video.stat;
break; break;
case 0x50: case 0x50:
if (gb->memory.io[0x50] != 0xFF) {
break;
}
GBUnmapBIOS(gb); GBUnmapBIOS(gb);
if (gb->model >= GB_MODEL_CGB && gb->memory.io[REG_UNK4C] < 0x80) { if (gb->model >= GB_MODEL_CGB && gb->memory.io[REG_UNK4C] < 0x80) {
gb->model = GB_MODEL_DMG; gb->model = GB_MODEL_DMG;

View File

@ -16,6 +16,8 @@
mLOG_DEFINE_CATEGORY(GB_MEM, "GB Memory", "gb.memory"); mLOG_DEFINE_CATEGORY(GB_MEM, "GB Memory", "gb.memory");
static const uint8_t _yankBuffer[] = { 0xFF };
enum GBBus { enum GBBus {
GB_BUS_CPU, GB_BUS_CPU,
GB_BUS_MAIN, GB_BUS_MAIN,
@ -69,6 +71,14 @@ static void GBSetActiveRegion(struct LR35902Core* cpu, uint16_t address) {
cpu->memory.activeRegion = memory->romBase; 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;
if (gb->memory.romSize < GB_SIZE_CART_BANK0) {
if (address >= gb->memory.romSize) {
cpu->memory.activeRegion = _yankBuffer;
cpu->memory.activeMask = 0;
} else {
cpu->memory.activeRegionEnd = gb->memory.romSize;
}
}
break; break;
case GB_REGION_CART_BANK1: case GB_REGION_CART_BANK1:
case GB_REGION_CART_BANK1 + 1: case GB_REGION_CART_BANK1 + 1:
@ -89,6 +99,14 @@ static void GBSetActiveRegion(struct LR35902Core* cpu, uint16_t address) {
cpu->memory.activeRegionEnd = GB_BASE_CART_BANK1 + 0x2000; cpu->memory.activeRegionEnd = GB_BASE_CART_BANK1 + 0x2000;
} }
} }
if (gb->memory.romSize < GB_SIZE_CART_BANK0 * 2) {
if (address >= gb->memory.romSize) {
cpu->memory.activeRegion = _yankBuffer;
cpu->memory.activeMask = 0;
} else {
cpu->memory.activeRegionEnd = gb->memory.romSize;
}
}
break; break;
default: default:
cpu->memory.cpuLoad8 = GBLoad8; cpu->memory.cpuLoad8 = GBLoad8;
@ -243,6 +261,9 @@ 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:
if (address >= memory->romSize) {
return 0xFF;
}
return memory->romBase[address & (GB_SIZE_CART_BANK0 - 1)]; return memory->romBase[address & (GB_SIZE_CART_BANK0 - 1)];
case GB_REGION_CART_BANK1 + 2: case GB_REGION_CART_BANK1 + 2:
case GB_REGION_CART_BANK1 + 3: case GB_REGION_CART_BANK1 + 3:
@ -252,6 +273,9 @@ uint8_t GBLoad8(struct LR35902Core* cpu, uint16_t address) {
// Fall through // Fall through
case GB_REGION_CART_BANK1: case GB_REGION_CART_BANK1:
case GB_REGION_CART_BANK1 + 1: case GB_REGION_CART_BANK1 + 1:
if (address >= memory->romSize) {
return 0xFF;
}
return memory->romBank[address & (GB_SIZE_CART_BANK0 - 1)]; return memory->romBank[address & (GB_SIZE_CART_BANK0 - 1)];
case GB_REGION_VRAM: case GB_REGION_VRAM:
case GB_REGION_VRAM + 1: case GB_REGION_VRAM + 1:

View File

@ -628,13 +628,16 @@ void CoreController::replaceGame(const QString& path) {
} }
void CoreController::yankPak() { void CoreController::yankPak() {
#ifdef M_CORE_GBA
if (platform() != PLATFORM_GBA) {
return;
}
Interrupter interrupter(this); Interrupter interrupter(this);
GBAYankROM(static_cast<GBA*>(m_threadContext.core->board));
#endif switch (platform()) {
case PLATFORM_GBA:
GBAYankROM(static_cast<GBA*>(m_threadContext.core->board));
break;
case PLATFORM_GB:
GBYankROM(static_cast<GB*>(m_threadContext.core->board));
break;
}
} }
void CoreController::addKey(int key) { void CoreController::addKey(int key) {

View File

@ -1212,12 +1212,10 @@ void Window::setupMenu(QMenuBar* menubar) {
m_controller->stop(); m_controller->stop();
}, "emu"); }, "emu");
#ifdef M_CORE_GBA
Action* yank = addGameAction(tr("Yank game pak"), "yank", [this]() { Action* yank = addGameAction(tr("Yank game pak"), "yank", [this]() {
m_controller->yankPak(); m_controller->yankPak();
}, "emu"); }, "emu");
m_platformActions.insert(PLATFORM_GBA, yank);
#endif
m_actions.addSeparator("emu"); m_actions.addSeparator("emu");
Action* pause = m_actions.addBooleanAction(tr("&Pause"), "pause", [this](bool paused) { Action* pause = m_actions.addBooleanAction(tr("&Pause"), "pause", [this](bool paused) {