mirror of https://github.com/mgba-emu/mgba.git
GB Memory: Implement ROM patching
This commit is contained in:
parent
8768bc21a2
commit
7477c36cb5
|
@ -321,6 +321,25 @@ static uint32_t _GBCoreRawRead32(struct mCore* core, uint32_t address) {
|
|||
(GBLoad8(cpu, address + 2) << 16) | (GBLoad8(cpu, address + 3) << 24);
|
||||
}
|
||||
|
||||
static void _GBCoreRawWrite8(struct mCore* core, uint32_t address, uint8_t value) {
|
||||
struct LR35902Core* cpu = core->cpu;
|
||||
GBPatch8(cpu, address, value, NULL);
|
||||
}
|
||||
|
||||
static void _GBCoreRawWrite16(struct mCore* core, uint32_t address, uint16_t value) {
|
||||
struct LR35902Core* cpu = core->cpu;
|
||||
GBPatch8(cpu, address, value, NULL);
|
||||
GBPatch8(cpu, address + 1, value >> 8, NULL);
|
||||
}
|
||||
|
||||
static void _GBCoreRawWrite32(struct mCore* core, uint32_t address, uint32_t value) {
|
||||
struct LR35902Core* cpu = core->cpu;
|
||||
GBPatch8(cpu, address, value, NULL);
|
||||
GBPatch8(cpu, address + 1, value >> 8, NULL);
|
||||
GBPatch8(cpu, address + 2, value >> 16, NULL);
|
||||
GBPatch8(cpu, address + 3, value >> 24, NULL);
|
||||
}
|
||||
|
||||
static bool _GBCoreSupportsDebuggerType(struct mCore* core, enum mDebuggerType type) {
|
||||
UNUSED(core);
|
||||
switch (type) {
|
||||
|
@ -429,9 +448,9 @@ struct mCore* GBCoreCreate(void) {
|
|||
core->rawRead8 = _GBCoreRawRead8;
|
||||
core->rawRead16 = _GBCoreRawRead16;
|
||||
core->rawRead32 = _GBCoreRawRead32;
|
||||
core->rawWrite8 = NULL;
|
||||
core->rawWrite16 = NULL;
|
||||
core->rawWrite32 = NULL;
|
||||
core->rawWrite8 = _GBCoreRawWrite8;
|
||||
core->rawWrite16 = _GBCoreRawWrite16;
|
||||
core->rawWrite32 = _GBCoreRawWrite32;
|
||||
core->supportsDebuggerType = _GBCoreSupportsDebuggerType;
|
||||
core->debuggerPlatform = _GBCoreDebuggerPlatform;
|
||||
core->cliDebuggerSystem = _GBCoreCliDebuggerSystem;
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
mLOG_DEFINE_CATEGORY(GB_MBC, "GB MBC");
|
||||
mLOG_DEFINE_CATEGORY(GB_MEM, "GB Memory");
|
||||
|
||||
static void _pristineCow(struct GB* gba);
|
||||
|
||||
static void _GBMBCNone(struct GBMemory* memory, uint16_t address, uint8_t value) {
|
||||
UNUSED(memory);
|
||||
UNUSED(address);
|
||||
|
@ -467,7 +469,68 @@ void GBDMAStore8(struct LR35902Core* cpu, uint16_t address, int8_t value) {
|
|||
GBStore8(cpu, address, value);
|
||||
}
|
||||
|
||||
void GBPatch8(struct LR35902Core* cpu, uint16_t address, int8_t value, int8_t* old);
|
||||
void GBPatch8(struct LR35902Core* cpu, uint16_t address, int8_t value, int8_t* old) {
|
||||
struct GB* gb = (struct GB*) cpu->master;
|
||||
struct GBMemory* memory = &gb->memory;
|
||||
int8_t oldValue = -1;
|
||||
|
||||
switch (address >> 12) {
|
||||
case GB_REGION_CART_BANK0:
|
||||
case GB_REGION_CART_BANK0 + 1:
|
||||
case GB_REGION_CART_BANK0 + 2:
|
||||
case GB_REGION_CART_BANK0 + 3:
|
||||
_pristineCow(gb);
|
||||
oldValue = memory->rom[address & (GB_SIZE_CART_BANK0 - 1)];
|
||||
memory->rom[address & (GB_SIZE_CART_BANK0 - 1)] = value;
|
||||
break;
|
||||
case GB_REGION_CART_BANK1:
|
||||
case GB_REGION_CART_BANK1 + 1:
|
||||
case GB_REGION_CART_BANK1 + 2:
|
||||
case GB_REGION_CART_BANK1 + 3:
|
||||
_pristineCow(gb);
|
||||
oldValue = memory->romBank[address & (GB_SIZE_CART_BANK0 - 1)];
|
||||
memory->romBank[address & (GB_SIZE_CART_BANK0 - 1)] = value;
|
||||
break;
|
||||
case GB_REGION_VRAM:
|
||||
case GB_REGION_VRAM + 1:
|
||||
oldValue = gb->video.vramBank[address & (GB_SIZE_VRAM_BANK0 - 1)];
|
||||
gb->video.vramBank[address & (GB_SIZE_VRAM_BANK0 - 1)] = value;
|
||||
break;
|
||||
case GB_REGION_EXTERNAL_RAM:
|
||||
case GB_REGION_EXTERNAL_RAM + 1:
|
||||
mLOG(GB_MEM, STUB, "Unimplemented memory Patch8: 0x%08X", address);
|
||||
return;
|
||||
case GB_REGION_WORKING_RAM_BANK0:
|
||||
case GB_REGION_WORKING_RAM_BANK0 + 2:
|
||||
oldValue = memory->wram[address & (GB_SIZE_WORKING_RAM_BANK0 - 1)];
|
||||
memory->wram[address & (GB_SIZE_WORKING_RAM_BANK0 - 1)] = value;
|
||||
break;
|
||||
case GB_REGION_WORKING_RAM_BANK1:
|
||||
oldValue = memory->wramBank[address & (GB_SIZE_WORKING_RAM_BANK0 - 1)];
|
||||
memory->wramBank[address & (GB_SIZE_WORKING_RAM_BANK0 - 1)] = value;
|
||||
break;
|
||||
default:
|
||||
if (address < GB_BASE_OAM) {
|
||||
oldValue = memory->wramBank[address & (GB_SIZE_WORKING_RAM_BANK0 - 1)];
|
||||
memory->wramBank[address & (GB_SIZE_WORKING_RAM_BANK0 - 1)] = value;
|
||||
} else if (address < GB_BASE_UNUSABLE) {
|
||||
oldValue = gb->video.oam.raw[address & 0xFF];
|
||||
gb->video.oam.raw[address & 0xFF] = value;
|
||||
} else if (address < GB_BASE_HRAM) {
|
||||
mLOG(GB_MEM, STUB, "Unimplemented memory Patch8: 0x%08X", address);
|
||||
return;
|
||||
} else if (address < GB_BASE_IE) {
|
||||
oldValue = memory->hram[address & GB_SIZE_HRAM];
|
||||
memory->hram[address & GB_SIZE_HRAM] = value;
|
||||
} else {
|
||||
mLOG(GB_MEM, STUB, "Unimplemented memory Patch8: 0x%08X", address);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (old) {
|
||||
*old = oldValue;
|
||||
}
|
||||
}
|
||||
|
||||
static void _switchBank(struct GBMemory* memory, int bank) {
|
||||
size_t bankStart = bank * GB_SIZE_CART_BANK0;
|
||||
|
@ -867,3 +930,13 @@ void _GBMBC7Write(struct GBMemory* memory, uint16_t address, uint8_t value) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _pristineCow(struct GB* gb) {
|
||||
if (gb->memory.rom != gb->pristineRom) {
|
||||
return;
|
||||
}
|
||||
gb->memory.rom = anonymousMemoryMap(GB_SIZE_CART_MAX);
|
||||
memcpy(gb->memory.rom, gb->pristineRom, gb->memory.romSize);
|
||||
memset(((uint8_t*) gb->memory.rom) + gb->memory.romSize, 0xFF, GB_SIZE_CART_MAX - gb->memory.romSize);
|
||||
_switchBank(&gb->memory, gb->memory.currentBank);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue