all repos — mgba @ 0b28dad51c16655cd2293e049be03701bfac8ca1

mGBA Game Boy Advance Emulator

GB Memory: Simplify DMA memory accesses
Vicki Pfau vi@endrift.com
Mon, 22 May 2017 19:49:48 -0700
commit

0b28dad51c16655cd2293e049be03701bfac8ca1

parent

fcc8b5c8052ae6bd4b4e7931ceb60461cee69605

2 files changed, 50 insertions(+), 65 deletions(-)

jump to
M include/mgba/internal/gb/memory.hinclude/mgba/internal/gb/memory.h

@@ -168,9 +168,6 @@

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;
M src/gb/memory.csrc/gb/memory.c

@@ -16,6 +16,33 @@ #include <mgba-util/memory.h>

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 @@

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 @@

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 _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; } }

@@ -466,61 +509,6 @@ } else {

gb->memory.io[REG_HDMA5] = 0xFF; } } -} - -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) {