GB Memory: Simplify DMA memory accesses

This commit is contained in:
Vicki Pfau 2017-05-22 19:49:48 -07:00
parent fcc8b5c805
commit 0b28dad51c
2 changed files with 50 additions and 65 deletions

View File

@ -168,9 +168,6 @@ uint8_t GBView8(struct LR35902Core* cpu, uint16_t address, int segment);
void GBMemoryDMA(struct GB* gb, uint16_t base);
void GBMemoryWriteHDMA5(struct GB* gb, uint8_t value);
uint8_t GBDMALoad8(struct LR35902Core* cpu, uint16_t address);
void GBDMAStore8(struct LR35902Core* cpu, uint16_t address, int8_t value);
void GBPatch8(struct LR35902Core* cpu, uint16_t address, int8_t value, int8_t* old, int segment);
struct GBSerializedState;

View File

@ -16,6 +16,33 @@
mLOG_DEFINE_CATEGORY(GB_MEM, "GB Memory", "gb.memory");
struct OAMBlock {
uint16_t low;
uint16_t high;
};
static const struct OAMBlock _oamBlockDMG[] = {
{ 0xA000, 0xFE00 },
{ 0xA000, 0xFE00 },
{ 0xA000, 0xFE00 },
{ 0xA000, 0xFE00 },
{ 0x8000, 0xA000 },
{ 0xA000, 0xFE00 },
{ 0xA000, 0xFE00 },
{ 0xA000, 0xFE00 },
};
static const struct OAMBlock _oamBlockCGB[] = {
{ 0xA000, 0xC000 },
{ 0xA000, 0xC000 },
{ 0xA000, 0xC000 },
{ 0xA000, 0xC000 },
{ 0x8000, 0xA000 },
{ 0xA000, 0xC000 },
{ 0xC000, 0xFE00 },
{ 0xA000, 0xC000 },
};
static void _pristineCow(struct GB* gba);
static uint8_t GBFastLoad8(struct LR35902Core* cpu, uint16_t address) {
@ -160,6 +187,16 @@ void GBMemorySwitchWramBank(struct GBMemory* memory, int bank) {
uint8_t GBLoad8(struct LR35902Core* cpu, uint16_t address) {
struct GB* gb = (struct GB*) cpu->master;
struct GBMemory* memory = &gb->memory;
if (gb->memory.dmaRemaining) {
const struct OAMBlock* block = gb->model < GB_MODEL_CGB ? _oamBlockDMG : _oamBlockCGB;
block = &block[memory->dmaSource >> 13];
if (address >= block->low && address < block->high) {
return 0xFF;
}
if (address >= GB_BASE_OAM && address < GB_BASE_UNUSABLE) {
return 0xFF;
}
}
switch (address >> 12) {
case GB_REGION_CART_BANK0:
case GB_REGION_CART_BANK0 + 1:
@ -218,6 +255,16 @@ uint8_t GBLoad8(struct LR35902Core* cpu, uint16_t address) {
void GBStore8(struct LR35902Core* cpu, uint16_t address, int8_t value) {
struct GB* gb = (struct GB*) cpu->master;
struct GBMemory* memory = &gb->memory;
if (gb->memory.dmaRemaining) {
const struct OAMBlock* block = gb->model < GB_MODEL_CGB ? _oamBlockDMG : _oamBlockCGB;
block = &block[memory->dmaSource >> 13];
if (address >= block->low && address < block->high) {
return;
}
if (address >= GB_BASE_OAM && address < GB_BASE_UNUSABLE) {
return;
}
}
switch (address >> 12) {
case GB_REGION_CART_BANK0:
case GB_REGION_CART_BANK0 + 1:
@ -389,9 +436,6 @@ void GBMemoryDMA(struct GB* gb, uint16_t base) {
if (base > 0xF100) {
return;
}
gb->cpu->memory.store8 = GBDMAStore8;
gb->cpu->memory.load8 = GBDMALoad8;
gb->cpu->memory.cpuLoad8 = GBDMALoad8;
mTimingSchedule(&gb->timing, &gb->memory.dmaEvent, 8);
if (gb->cpu->cycles + 8 < gb->cpu->nextEvent) {
gb->cpu->nextEvent = gb->cpu->cycles + 8;
@ -425,18 +469,17 @@ void GBMemoryWriteHDMA5(struct GB* gb, uint8_t value) {
void _GBMemoryDMAService(struct mTiming* timing, void* context, uint32_t cyclesLate) {
struct GB* gb = context;
int dmaRemaining = gb->memory.dmaRemaining;
gb->memory.dmaRemaining = 0;
uint8_t b = GBLoad8(gb->cpu, gb->memory.dmaSource);
// TODO: Can DMA write OAM during modes 2-3?
gb->video.oam.raw[gb->memory.dmaDest] = b;
gb->video.renderer->writeOAM(gb->video.renderer, gb->memory.dmaDest);
++gb->memory.dmaSource;
++gb->memory.dmaDest;
--gb->memory.dmaRemaining;
gb->memory.dmaRemaining = dmaRemaining - 1;
if (gb->memory.dmaRemaining) {
mTimingSchedule(timing, &gb->memory.dmaEvent, 4 - cyclesLate);
} else {
gb->cpu->memory.store8 = GBStore8;
gb->cpu->memory.load8 = GBLoad8;
}
}
@ -468,61 +511,6 @@ void _GBMemoryHDMAService(struct mTiming* timing, void* context, uint32_t cycles
}
}
struct OAMBlock {
uint16_t low;
uint16_t high;
};
static const struct OAMBlock _oamBlockDMG[] = {
{ 0xA000, 0xFE00 },
{ 0xA000, 0xFE00 },
{ 0xA000, 0xFE00 },
{ 0xA000, 0xFE00 },
{ 0x8000, 0xA000 },
{ 0xA000, 0xFE00 },
{ 0xA000, 0xFE00 },
{ 0xA000, 0xFE00 },
};
static const struct OAMBlock _oamBlockCGB[] = {
{ 0xA000, 0xC000 },
{ 0xA000, 0xC000 },
{ 0xA000, 0xC000 },
{ 0xA000, 0xC000 },
{ 0x8000, 0xA000 },
{ 0xA000, 0xC000 },
{ 0xC000, 0xFE00 },
{ 0xA000, 0xC000 },
};
uint8_t GBDMALoad8(struct LR35902Core* cpu, uint16_t address) {
struct GB* gb = (struct GB*) cpu->master;
struct GBMemory* memory = &gb->memory;
const struct OAMBlock* block = gb->model < GB_MODEL_CGB ? _oamBlockDMG : _oamBlockCGB;
block = &block[memory->dmaSource >> 13];
if (address >= block->low && address < block->high) {
return 0xFF;
}
if (address >= GB_BASE_OAM && address < GB_BASE_UNUSABLE) {
return 0xFF;
}
return GBLoad8(cpu, address);
}
void GBDMAStore8(struct LR35902Core* cpu, uint16_t address, int8_t value) {
struct GB* gb = (struct GB*) cpu->master;
struct GBMemory* memory = &gb->memory;
const struct OAMBlock* block = gb->model < GB_MODEL_CGB ? _oamBlockDMG : _oamBlockCGB;
block = &block[memory->dmaSource >> 13];
if (address >= block->low && address < block->high) {
return;
}
if (address >= GB_BASE_OAM && address < GB_BASE_UNUSABLE) {
return;
}
GBStore8(cpu, address, value);
}
void GBPatch8(struct LR35902Core* cpu, uint16_t address, int8_t value, int8_t* old, int segment) {
struct GB* gb = (struct GB*) cpu->master;
struct GBMemory* memory = &gb->memory;