mirror of https://github.com/mgba-emu/mgba.git
GB Memory: Implement DMA
This commit is contained in:
parent
52adcb68db
commit
d2867c26a0
|
@ -184,6 +184,11 @@ void GBProcessEvents(struct LR35902Core* cpu) {
|
|||
nextEvent = testEvent;
|
||||
}
|
||||
|
||||
testEvent = GBMemoryProcessEvents(gb, cycles);
|
||||
if (testEvent < nextEvent) {
|
||||
nextEvent = testEvent;
|
||||
}
|
||||
|
||||
cpu->cycles -= cycles;
|
||||
cpu->nextEvent = nextEvent;
|
||||
}
|
||||
|
|
|
@ -71,6 +71,9 @@ void GBIOWrite(struct GB* gb, unsigned address, uint8_t value) {
|
|||
value = gb->video.renderer->writeVideoRegister(gb->video.renderer, address, value);
|
||||
GBVideoWriteLCDC(&gb->video, value);
|
||||
break;
|
||||
case REG_DMA:
|
||||
GBMemoryDMA(gb, value << 8);
|
||||
break;
|
||||
case REG_SCY:
|
||||
case REG_SCX:
|
||||
case REG_WY:
|
||||
|
|
|
@ -27,11 +27,12 @@ static void GBSetActiveRegion(struct LR35902Core* cpu, uint16_t address) {
|
|||
// TODO
|
||||
}
|
||||
|
||||
static void _GBMemoryDMAService(struct GB* gb);
|
||||
|
||||
|
||||
void GBMemoryInit(struct GB* gb) {
|
||||
struct LR35902Core* cpu = gb->cpu;
|
||||
cpu->memory.load16 = GBLoad16;
|
||||
cpu->memory.load8 = GBLoad8;
|
||||
cpu->memory.store16 = GBStore16;
|
||||
cpu->memory.store8 = GBStore8;
|
||||
cpu->memory.setActiveRegion = GBSetActiveRegion;
|
||||
|
||||
|
@ -43,6 +44,9 @@ void GBMemoryInit(struct GB* gb) {
|
|||
gb->memory.mbcType = GB_MBC_NONE;
|
||||
gb->memory.mbc = 0;
|
||||
|
||||
gb->memory.dmaNext = INT_MAX;
|
||||
gb->memory.dmaRemaining = 0;
|
||||
|
||||
memset(gb->memory.hram, 0, sizeof(gb->memory.hram));
|
||||
|
||||
GBIOInit(gb);
|
||||
|
@ -115,10 +119,6 @@ void GBMemoryReset(struct GB* gb) {
|
|||
}
|
||||
}
|
||||
|
||||
uint16_t GBLoad16(struct LR35902Core* cpu, uint16_t address) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
uint8_t GBLoad8(struct LR35902Core* cpu, uint16_t address) {
|
||||
struct GB* gb = (struct GB*) cpu->master;
|
||||
struct GBMemory* memory = &gb->memory;
|
||||
|
@ -163,10 +163,6 @@ uint8_t GBLoad8(struct LR35902Core* cpu, uint16_t address) {
|
|||
}
|
||||
}
|
||||
|
||||
void GBStore16(struct LR35902Core* cpu, uint16_t address, int16_t value) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void GBStore8(struct LR35902Core* cpu, uint16_t address, int8_t value) {
|
||||
struct GB* gb = (struct GB*) cpu->master;
|
||||
struct GBMemory* memory = &gb->memory;
|
||||
|
@ -213,10 +209,67 @@ void GBStore8(struct LR35902Core* cpu, uint16_t address, int8_t value) {
|
|||
}
|
||||
}
|
||||
|
||||
uint16_t GBView16(struct LR35902Core* cpu, uint16_t address);
|
||||
int32_t GBMemoryProcessEvents(struct GB* gb, int32_t cycles) {
|
||||
if (!gb->memory.dmaRemaining) {
|
||||
return INT_MAX;
|
||||
}
|
||||
gb->memory.dmaNext -= cycles;
|
||||
if (gb->memory.dmaNext <= 0) {
|
||||
_GBMemoryDMAService(gb);
|
||||
}
|
||||
return gb->memory.dmaNext;
|
||||
}
|
||||
|
||||
void GBMemoryDMA(struct GB* gb, uint16_t base) {
|
||||
if (base > 0xF100) {
|
||||
return;
|
||||
}
|
||||
gb->cpu->memory.store8 = GBDMAStore8;
|
||||
gb->cpu->memory.load8 = GBDMALoad8;
|
||||
gb->memory.dmaNext = gb->cpu->cycles + 4;
|
||||
if (gb->memory.dmaNext < gb->cpu->nextEvent) {
|
||||
gb->cpu->nextEvent = gb->memory.dmaNext;
|
||||
}
|
||||
gb->memory.dmaSource = base;
|
||||
gb->memory.dmaDest = GB_BASE_OAM;
|
||||
gb->memory.dmaRemaining = 0xA0;
|
||||
}
|
||||
|
||||
void _GBMemoryDMAService(struct GB* gb) {
|
||||
uint8_t b = GBLoad8(gb->cpu, gb->memory.dmaSource);
|
||||
GBStore8(gb->cpu, gb->memory.dmaDest, b);
|
||||
++gb->memory.dmaSource;
|
||||
++gb->memory.dmaDest;
|
||||
--gb->memory.dmaRemaining;
|
||||
if (gb->memory.dmaRemaining) {
|
||||
gb->memory.dmaNext += 4;
|
||||
} else {
|
||||
gb->memory.dmaNext = INT_MAX;
|
||||
gb->cpu->memory.store8 = GBStore8;
|
||||
gb->cpu->memory.load8 = GBLoad8;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t GBDMALoad8(struct LR35902Core* cpu, uint16_t address) {
|
||||
struct GB* gb = (struct GB*) cpu->master;
|
||||
struct GBMemory* memory = &gb->memory;
|
||||
if (address < 0xFF80 || address == 0xFFFF) {
|
||||
return 0xFF;
|
||||
}
|
||||
return memory->hram[address & GB_SIZE_HRAM];
|
||||
}
|
||||
|
||||
void GBDMAStore8(struct LR35902Core* cpu, uint16_t address, int8_t value) {
|
||||
struct GB* gb = (struct GB*) cpu->master;
|
||||
struct GBMemory* memory = &gb->memory;
|
||||
if (address < 0xFF80 || address == 0xFFFF) {
|
||||
return;
|
||||
}
|
||||
memory->hram[address & GB_SIZE_HRAM] = value;
|
||||
}
|
||||
|
||||
uint8_t GBView8(struct LR35902Core* cpu, uint16_t address);
|
||||
|
||||
void GBPatch16(struct LR35902Core* cpu, uint16_t address, int16_t value, int16_t* old);
|
||||
void GBPatch8(struct LR35902Core* cpu, uint16_t address, int8_t value, int8_t* old);
|
||||
|
||||
static void _switchBank(struct GBMemory* memory, int bank) {
|
||||
|
|
|
@ -71,12 +71,22 @@ struct GBMemory {
|
|||
uint8_t* wram;
|
||||
uint8_t* wramBank;
|
||||
|
||||
bool sramAccess;
|
||||
uint8_t* sram;
|
||||
uint8_t* sramBank;
|
||||
int sramCurrentBank;
|
||||
|
||||
uint8_t io[GB_SIZE_IO];
|
||||
bool ime;
|
||||
uint8_t ie;
|
||||
|
||||
uint8_t hram[GB_SIZE_HRAM];
|
||||
|
||||
int32_t dmaNext;
|
||||
uint16_t dmaSource;
|
||||
uint16_t dmaDest;
|
||||
int dmaRemaining;
|
||||
|
||||
size_t romSize;
|
||||
};
|
||||
|
||||
|
@ -85,12 +95,15 @@ void GBMemoryDeinit(struct GB* gb);
|
|||
|
||||
void GBMemoryReset(struct GB* gb);
|
||||
|
||||
uint16_t GBLoad16(struct LR35902Core* cpu, uint16_t address);
|
||||
uint8_t GBLoad8(struct LR35902Core* cpu, uint16_t address);
|
||||
|
||||
void GBStore16(struct LR35902Core* cpu, uint16_t address, int16_t value);
|
||||
void GBStore8(struct LR35902Core* cpu, uint16_t address, int8_t value);
|
||||
|
||||
int32_t GBMemoryProcessEvents(struct GB* gb, int32_t cycles);
|
||||
void GBMemoryDMA(struct GB* gb, uint16_t base);
|
||||
|
||||
uint8_t GBDMALoad8(struct LR35902Core* cpu, uint16_t address);
|
||||
void GBDMAStore8(struct LR35902Core* cpu, uint16_t address, int8_t value);
|
||||
|
||||
uint16_t GBView16(struct LR35902Core* cpu, uint16_t address);
|
||||
uint8_t GBView8(struct LR35902Core* cpu, uint16_t address);
|
||||
|
||||
|
|
Loading…
Reference in New Issue