mirror of https://github.com/mgba-emu/mgba.git
GB: Add yanking
This commit is contained in:
parent
7c8d253123
commit
a44a8f668f
1
CHANGES
1
CHANGES
|
@ -20,6 +20,7 @@ Features:
|
|||
- Support for unlicensed Wisdom Tree Game Boy mapper
|
||||
- Qt: Add export button for tile view (closes mgba.io/i/1507)
|
||||
- Qt: Add recent game list clearing (closes mgba.io/i/1380)
|
||||
- GB: Yanking gamepak now supported
|
||||
Emulation fixes:
|
||||
- GBA: All IRQs have 7 cycle delay (fixes mgba.io/i/539, mgba.io/i/1208)
|
||||
- GBA: Reset now reloads multiboot ROMs
|
||||
|
|
|
@ -94,6 +94,7 @@ struct GB {
|
|||
bool isPristine;
|
||||
size_t pristineRomSize;
|
||||
size_t yankedRomSize;
|
||||
enum GBMemoryBankControllerType yankedMbc;
|
||||
uint32_t romCrc32;
|
||||
struct VFile* romVf;
|
||||
struct VFile* biosVf;
|
||||
|
@ -163,6 +164,7 @@ bool GBLoadROM(struct GB* gb, struct VFile* vf);
|
|||
bool GBLoadSave(struct GB* gb, struct VFile* vf);
|
||||
void GBUnloadROM(struct GB* gb);
|
||||
void GBSynthesizeROM(struct VFile* vf);
|
||||
void GBYankROM(struct GB* gb);
|
||||
|
||||
void GBLoadBIOS(struct GB* gb, struct VFile* vf);
|
||||
|
||||
|
|
14
src/gb/gb.c
14
src/gb/gb.c
|
@ -127,6 +127,19 @@ bool GBLoadROM(struct GB* gb, struct VFile* vf) {
|
|||
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) {
|
||||
if (gb->sramVf) {
|
||||
gb->sramVf->unmap(gb->sramVf, gb->memory.sram, gb->sramSize);
|
||||
|
@ -430,6 +443,7 @@ void GBReset(struct LR35902Core* cpu) {
|
|||
|
||||
if (gb->yankedRomSize) {
|
||||
gb->memory.romSize = gb->yankedRomSize;
|
||||
gb->memory.mbcType = gb->yankedMbc;
|
||||
gb->yankedRomSize = 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -458,6 +458,9 @@ void GBIOWrite(struct GB* gb, unsigned address, uint8_t value) {
|
|||
value = gb->video.stat;
|
||||
break;
|
||||
case 0x50:
|
||||
if (gb->memory.io[0x50] != 0xFF) {
|
||||
break;
|
||||
}
|
||||
GBUnmapBIOS(gb);
|
||||
if (gb->model >= GB_MODEL_CGB && gb->memory.io[REG_UNK4C] < 0x80) {
|
||||
gb->model = GB_MODEL_DMG;
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
mLOG_DEFINE_CATEGORY(GB_MEM, "GB Memory", "gb.memory");
|
||||
|
||||
static const uint8_t _yankBuffer[] = { 0xFF };
|
||||
|
||||
enum GBBus {
|
||||
GB_BUS_CPU,
|
||||
GB_BUS_MAIN,
|
||||
|
@ -69,6 +71,14 @@ static void GBSetActiveRegion(struct LR35902Core* cpu, uint16_t address) {
|
|||
cpu->memory.activeRegion = memory->romBase;
|
||||
cpu->memory.activeRegionEnd = GB_BASE_CART_BANK1;
|
||||
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;
|
||||
case GB_REGION_CART_BANK1:
|
||||
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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
default:
|
||||
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 + 2:
|
||||
case GB_REGION_CART_BANK0 + 3:
|
||||
if (address >= memory->romSize) {
|
||||
return 0xFF;
|
||||
}
|
||||
return memory->romBase[address & (GB_SIZE_CART_BANK0 - 1)];
|
||||
case GB_REGION_CART_BANK1 + 2:
|
||||
case GB_REGION_CART_BANK1 + 3:
|
||||
|
@ -252,6 +273,9 @@ uint8_t GBLoad8(struct LR35902Core* cpu, uint16_t address) {
|
|||
// Fall through
|
||||
case GB_REGION_CART_BANK1:
|
||||
case GB_REGION_CART_BANK1 + 1:
|
||||
if (address >= memory->romSize) {
|
||||
return 0xFF;
|
||||
}
|
||||
return memory->romBank[address & (GB_SIZE_CART_BANK0 - 1)];
|
||||
case GB_REGION_VRAM:
|
||||
case GB_REGION_VRAM + 1:
|
||||
|
|
|
@ -628,13 +628,16 @@ void CoreController::replaceGame(const QString& path) {
|
|||
}
|
||||
|
||||
void CoreController::yankPak() {
|
||||
#ifdef M_CORE_GBA
|
||||
if (platform() != PLATFORM_GBA) {
|
||||
return;
|
||||
}
|
||||
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) {
|
||||
|
|
|
@ -1212,12 +1212,10 @@ void Window::setupMenu(QMenuBar* menubar) {
|
|||
m_controller->stop();
|
||||
}, "emu");
|
||||
|
||||
#ifdef M_CORE_GBA
|
||||
Action* yank = addGameAction(tr("Yank game pak"), "yank", [this]() {
|
||||
m_controller->yankPak();
|
||||
}, "emu");
|
||||
m_platformActions.insert(PLATFORM_GBA, yank);
|
||||
#endif
|
||||
|
||||
m_actions.addSeparator("emu");
|
||||
|
||||
Action* pause = m_actions.addBooleanAction(tr("&Pause"), "pause", [this](bool paused) {
|
||||
|
|
Loading…
Reference in New Issue