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
|
- 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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
14
src/gb/gb.c
14
src/gb/gb.c
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Reference in New Issue