all repos — mgba @ 1838cc0597ed00d5293134eb6af64f83493c889c

mGBA Game Boy Advance Emulator

Implement waitstate adjusting
Jeffrey Pfau jeffrey@endrift.com
Mon, 15 Apr 2013 01:10:53 -0700
commit

1838cc0597ed00d5293134eb6af64f83493c889c

parent

fe5a8d62544784df009447cac69519e869025b7d

4 files changed, 52 insertions(+), 3 deletions(-)

jump to
M src/gba/gba-io.csrc/gba/gba-io.c

@@ -2,17 +2,24 @@ #include "gba-io.h"

void GBAIOWrite(struct GBA* gba, uint32_t address, uint16_t value) { switch (address) { + case REG_WAITCNT: + GBAAdjustWaitstates(&gba->memory, value); + break; default: GBALog(GBA_LOG_STUB, "Stub I/O register write: %03x", address); break; } + gba->memory.io[address >> 1] = value; } uint16_t GBAIORead(struct GBA* gba, uint32_t address) { switch (address) { + case REG_WAITCNT: + // Handled transparently by registers + break; default: GBALog(GBA_LOG_STUB, "Stub I/O register read: %03x", address); break; } - return 0; + return gba->memory.io[address >> 1]; }
M src/gba/gba-memory.csrc/gba/gba-memory.c

@@ -11,6 +11,8 @@ static void GBASetActiveRegion(struct ARMMemory* memory, uint32_t region);

static const char GBA_BASE_WAITSTATES[16] = { 0, 0, 2, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4 }; static const char GBA_BASE_WAITSTATES_SEQ[16] = { 0, 0, 2, 0, 0, 0, 0, 0, 2, 2, 4, 4, 8, 8, 4 }; +static const char GBA_ROM_WAITSTATES[] = { 4, 3, 2, 8 }; +static const char GBA_ROM_WAITSTATES_SEQ[] = { 2, 1, 4, 1, 8, 1 }; void GBAMemoryInit(struct GBAMemory* memory) { memory->d.load32 = GBALoad32;

@@ -48,9 +50,12 @@ memory->waitstates32[i] = 0;

memory->waitstatesSeq32[i] = 0; } + memory->activeRegion = 0; memory->d.activeRegion = 0; memory->d.activeMask = 0; memory->d.setActiveRegion = GBASetActiveRegion; + memory->d.activePrefetchCycles32 = 0; + memory->d.activePrefetchCycles16 = 0; } void GBAMemoryDeinit(struct GBAMemory* memory) {

@@ -63,6 +68,7 @@ struct GBAMemory* gbaMemory = (struct GBAMemory*) memory;

memory->activePrefetchCycles32 = gbaMemory->waitstates32[address >> BASE_OFFSET]; memory->activePrefetchCycles16 = gbaMemory->waitstates16[address >> BASE_OFFSET]; + gbaMemory->activeRegion = address >> BASE_OFFSET; switch (address & ~OFFSET_MASK) { case BASE_BIOS: memory->activeRegion = gbaMemory->bios;

@@ -351,3 +357,38 @@ default:

break; } } + +void GBAAdjustWaitstates(struct GBAMemory* memory, uint16_t parameters) { + int sram = parameters & 0x0003; + int ws0 = (parameters & 0x000C) >> 2; + int ws0seq = (parameters & 0x0010) >> 4; + int ws1 = (parameters & 0x0060) >> 5; + int ws1seq = (parameters & 0x0080) >> 7; + int ws2 = (parameters & 0x0300) >> 8; + int ws2seq = (parameters & 0x0400) >> 10; + int prefetch = parameters & 0x4000; + + memory->waitstates16[REGION_CART_SRAM] = GBA_ROM_WAITSTATES[sram]; + memory->waitstatesSeq16[REGION_CART_SRAM] = GBA_ROM_WAITSTATES[sram]; + memory->waitstates32[REGION_CART_SRAM] = 2 * GBA_ROM_WAITSTATES[sram] + 1; + memory->waitstatesSeq32[REGION_CART_SRAM] = 2 * GBA_ROM_WAITSTATES[sram] + 1; + + memory->waitstates16[REGION_CART0] = memory->waitstates16[REGION_CART0_EX] = GBA_ROM_WAITSTATES[ws0]; + memory->waitstates16[REGION_CART1] = memory->waitstates16[REGION_CART1_EX] = GBA_ROM_WAITSTATES[ws1]; + memory->waitstates16[REGION_CART2] = memory->waitstates16[REGION_CART2_EX] = GBA_ROM_WAITSTATES[ws2]; + + memory->waitstatesSeq16[REGION_CART0] = memory->waitstatesSeq16[REGION_CART0_EX] = GBA_ROM_WAITSTATES_SEQ[ws0seq]; + memory->waitstatesSeq16[REGION_CART1] = memory->waitstatesSeq16[REGION_CART1_EX] = GBA_ROM_WAITSTATES_SEQ[ws1seq + 2]; + memory->waitstatesSeq16[REGION_CART2] = memory->waitstatesSeq16[REGION_CART2_EX] = GBA_ROM_WAITSTATES_SEQ[ws2seq + 4]; + + memory->waitstates32[REGION_CART0] = memory->waitstates32[REGION_CART0_EX] = memory->waitstates16[REGION_CART0] + 1 + memory->waitstatesSeq16[REGION_CART0]; + memory->waitstates32[REGION_CART1] = memory->waitstates32[REGION_CART1_EX] = memory->waitstates16[REGION_CART1] + 1 + memory->waitstatesSeq16[REGION_CART1]; + memory->waitstates32[REGION_CART2] = memory->waitstates32[REGION_CART2_EX] = memory->waitstates16[REGION_CART2] + 1 + memory->waitstatesSeq16[REGION_CART2]; + + memory->waitstatesSeq32[REGION_CART0] = memory->waitstatesSeq32[REGION_CART0 + 1] = 2 * memory->waitstatesSeq16[REGION_CART0] + 1; + memory->waitstatesSeq32[REGION_CART1] = memory->waitstatesSeq32[REGION_CART1 + 1] = 2 * memory->waitstatesSeq16[REGION_CART1] + 1; + memory->waitstatesSeq32[REGION_CART2] = memory->waitstatesSeq32[REGION_CART2 + 1] = 2 * memory->waitstatesSeq16[REGION_CART2] + 1; + + memory->d.activePrefetchCycles32 = memory->waitstates32[memory->activeRegion]; + memory->d.activePrefetchCycles16 = memory->waitstates16[memory->activeRegion]; +}
M src/gba/gba-memory.hsrc/gba/gba-memory.h

@@ -73,6 +73,7 @@ char waitstates32[256];

char waitstates16[256]; char waitstatesSeq32[256]; char waitstatesSeq16[256]; + int activeRegion; }; int32_t GBALoad32(struct ARMMemory* memory, uint32_t address);

@@ -84,5 +85,7 @@

void GBAStore32(struct ARMMemory* memory, uint32_t address, int32_t value); void GBAStore16(struct ARMMemory* memory, uint32_t address, int16_t value); void GBAStore8(struct ARMMemory* memory, uint32_t address, int8_t value); + +void GBAAdjustWaitstates(struct GBAMemory* memory, uint16_t parameters); #endif
M src/gba/gba.csrc/gba/gba.c

@@ -17,8 +17,6 @@ };

static void GBAHitStub(struct ARMBoard* board, uint32_t opcode); -static void _GBAIOWrite(struct GBA* gba, uint32_t address, uint16_t value); - void GBAInit(struct GBA* gba) { gba->errno = GBA_NO_ERROR; gba->errstr = 0;