all repos — mgba @ 2c3a1c6f7177a1f99c475ec4fe53a9f55b2d9658

mGBA Game Boy Advance Emulator

DS Memory: Add WRAM
Vicki Pfau vi@endrift.com
Mon, 20 Feb 2017 17:51:33 -0800
commit

2c3a1c6f7177a1f99c475ec4fe53a9f55b2d9658

parent

7b13335cafa89deec85a32f58d81732c522895e5

3 files changed, 115 insertions(+), 19 deletions(-)

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

@@ -78,6 +78,8 @@ uint32_t* itcm;

uint32_t* dtcm; uint32_t* ram; uint32_t* wram; + uint32_t* wramBase7; + uint32_t* wramBase9; uint32_t* wram7; uint32_t* rom; uint16_t io7[DS7_REG_MAX >> 1];

@@ -145,5 +147,7 @@ uint32_t DS9LoadMultiple(struct ARMCore*, uint32_t baseAddress, int mask, enum LSMDirection direction,

int* cycleCounter); uint32_t DS9StoreMultiple(struct ARMCore*, uint32_t baseAddress, int mask, enum LSMDirection direction, int* cycleCounter); + +void DSConfigureWRAM(struct DSMemory*, uint8_t config); #endif
M src/ds/io.csrc/ds/io.c

@@ -324,6 +324,7 @@ void DS9IOInit(struct DS* ds) {

memset(ds->memory.io9, 0, sizeof(ds->memory.io9)); ds->memory.io9[DS_REG_IPCFIFOCNT >> 1] = 0x0101; ds->memory.io9[DS_REG_POSTFLG >> 1] = 0x0001; + ds->memory.io9[DS9_REG_VRAMCNT_G >> 1] = 0x0300; } void DS9IOWrite(struct DS* ds, uint32_t address, uint16_t value) {

@@ -332,16 +333,19 @@ // VRAM control

case DS9_REG_VRAMCNT_A: case DS9_REG_VRAMCNT_C: case DS9_REG_VRAMCNT_E: - DSVideoConfigureVRAM(&ds->memory, address - DS9_REG_VRAMCNT_A + 1, value & 0xFF); - DSVideoConfigureVRAM(&ds->memory, address - DS9_REG_VRAMCNT_A, value >> 8); + value &= 0x9F9F; + DSVideoConfigureVRAM(&ds->memory, address - DS9_REG_VRAMCNT_A, value & 0xFF); + DSVideoConfigureVRAM(&ds->memory, address - DS9_REG_VRAMCNT_A + 1, value >> 8); break; case DS9_REG_VRAMCNT_G: - DSVideoConfigureVRAM(&ds->memory, 6, value >> 8); - mLOG(DS_IO, STUB, "Stub DS9 I/O register write: %06X:%04X", address + 1, value); + value &= 0x9F03; + DSVideoConfigureVRAM(&ds->memory, 6, value & 0xFF); + DSConfigureWRAM(&ds->memory, value >> 8); break; case DS9_REG_VRAMCNT_H: - DSVideoConfigureVRAM(&ds->memory, 7, value >> 8); - DSVideoConfigureVRAM(&ds->memory, 8, value & 0xFF); + value &= 0x9F9F; + DSVideoConfigureVRAM(&ds->memory, 7, value & 0xFF); + DSVideoConfigureVRAM(&ds->memory, 8, value >> 8); break; // Math
M src/ds/memory.csrc/ds/memory.c

@@ -172,7 +172,9 @@ ds->ds9.memory.activeDMA = -1;

// TODO: Correct size ds->memory.wramSize7 = 0x8000; + ds->memory.wramBase7 = ds->memory.wram; ds->memory.wramSize9 = 0; + ds->memory.wramBase9 = NULL; DSVideoConfigureVRAM(&ds->memory, 0, 0); DSVideoConfigureVRAM(&ds->memory, 1, 0);

@@ -183,6 +185,7 @@ DSVideoConfigureVRAM(&ds->memory, 5, 0);

DSVideoConfigureVRAM(&ds->memory, 6, 0); DSVideoConfigureVRAM(&ds->memory, 7, 0); DSVideoConfigureVRAM(&ds->memory, 8, 0); + DSConfigureWRAM(&ds->memory, 3); if (!ds->memory.wram || !ds->memory.wram7 || !ds->memory.ram || !ds->memory.itcm || !ds->memory.dtcm) { DSMemoryDeinit(ds);

@@ -250,7 +253,7 @@ case DS_REGION_WORKING_RAM:

if (address >= DS7_BASE_WORKING_RAM || !ds->memory.wramSize7) { LOAD_32(value, address & (DS7_SIZE_WORKING_RAM - 4), memory->wram7); } else { - LOAD_32(value, address & (ds->memory.wramSize7 - 4), memory->wram); + LOAD_32(value, address & (ds->memory.wramSize7 - 4), memory->wramBase7); } break; case DS_REGION_RAM:

@@ -291,7 +294,7 @@ case DS_REGION_WORKING_RAM:

if (address >= DS7_BASE_WORKING_RAM || !ds->memory.wramSize7) { LOAD_16(value, address & (DS7_SIZE_WORKING_RAM - 2), memory->wram7); } else { - LOAD_16(value, address & (ds->memory.wramSize7 - 2), memory->wram); + LOAD_16(value, address & (ds->memory.wramSize7 - 2), memory->wramBase7); } break; case DS_REGION_RAM:

@@ -328,7 +331,7 @@ case DS_REGION_WORKING_RAM:

if (address >= DS7_BASE_WORKING_RAM || !ds->memory.wramSize7) { value = ((uint8_t*) memory->wram7)[address & (DS7_SIZE_WORKING_RAM - 1)]; } else { - value = ((uint8_t*) memory->wram)[address & (ds->memory.wramSize7 - 1)]; + value = ((uint8_t*) memory->wramBase7)[address & (ds->memory.wramSize7 - 1)]; } break; case DS_REGION_RAM:

@@ -359,7 +362,7 @@ case DS_REGION_WORKING_RAM:

if (address >= DS7_BASE_WORKING_RAM || !ds->memory.wramSize7) { STORE_32(value, address & (DS7_SIZE_WORKING_RAM - 4), memory->wram7); } else { - STORE_32(value, address & (ds->memory.wramSize7 - 4), memory->wram); + STORE_32(value, address & (ds->memory.wramSize7 - 4), memory->wramBase7); } break; case DS_REGION_RAM:

@@ -393,7 +396,7 @@ case DS_REGION_WORKING_RAM:

if (address >= DS7_BASE_WORKING_RAM || !ds->memory.wramSize7) { STORE_16(value, address & (DS7_SIZE_WORKING_RAM - 2), memory->wram7); } else { - STORE_16(value, address & (ds->memory.wramSize7 - 2), memory->wram); + STORE_16(value, address & (ds->memory.wramSize7 - 2), memory->wramBase7); } break; case DS_REGION_RAM:

@@ -427,7 +430,7 @@ case DS_REGION_WORKING_RAM:

if (address >= DS7_BASE_WORKING_RAM || !ds->memory.wramSize7) { ((uint8_t*) memory->wram7)[address & (DS7_SIZE_WORKING_RAM - 1)] = value; } else { - ((uint8_t*) memory->wram)[address & (ds->memory.wramSize7 - 1)] = value; + ((uint8_t*) memory->wramBase7)[address & (ds->memory.wramSize7 - 1)] = value; } break; case DS_REGION_RAM:

@@ -544,7 +547,7 @@ case DS_REGION_WORKING_RAM:

LDM_LOOP(if (address >= DS7_BASE_WORKING_RAM || !ds->memory.wramSize7) { LOAD_32(value, address & (DS7_SIZE_WORKING_RAM - 1), memory->wram7); } else { - LOAD_32(value, address & (ds->memory.wramSize7 - 1), memory->wram); + LOAD_32(value, address & (ds->memory.wramSize7 - 1), memory->wramBase7); }); break; case DS_REGION_RAM:

@@ -607,7 +610,7 @@ case DS_REGION_WORKING_RAM:

STM_LOOP(if (address >= DS7_BASE_WORKING_RAM || !ds->memory.wramSize7) { STORE_32(value, address & (DS7_SIZE_WORKING_RAM - 1), memory->wram7); } else { - STORE_32(value, address & (ds->memory.wramSize7 - 1), memory->wram); + STORE_32(value, address & (ds->memory.wramSize7 - 1), memory->wramBase7); }); break; case DS_REGION_RAM:

@@ -698,7 +701,14 @@ if (address < memory->itcmSize) {

LOAD_32(value, address & (DS9_SIZE_ITCM - 4), memory->itcm); break; } - mLOG(DS_MEM, STUB, "Bad DS9 Load32: %08X:%08X", address, value); + mLOG(DS_MEM, STUB, "Bad DS9 Load32: %08X", address); + break; + case DS_REGION_WORKING_RAM: + if (ds->memory.wramSize9) { + LOAD_32(value, address & (ds->memory.wramSize9 - 4), memory->wramBase9); + break; + } + mLOG(DS_MEM, STUB, "Bad DS9 Load32: %08X", address); break; case DS_REGION_RAM: if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) {

@@ -762,7 +772,14 @@ if (address < memory->itcmSize) {

LOAD_16(value, address & (DS9_SIZE_ITCM - 2), memory->itcm); break; } - mLOG(DS_MEM, STUB, "Bad DS9 Load16: %08X:%08X", address, value); + mLOG(DS_MEM, STUB, "Bad DS9 Load16: %08X", address); + break; + case DS_REGION_WORKING_RAM: + if (ds->memory.wramSize9) { + LOAD_16(value, address & (ds->memory.wramSize9 - 2), memory->wramBase9); + break; + } + mLOG(DS_MEM, STUB, "Bad DS9 Load16: %08X", address); break; case DS_REGION_RAM: if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) {

@@ -825,11 +842,18 @@ if (address < memory->itcmSize) {

value = ((uint8_t*) memory->itcm)[address & (DS9_SIZE_ITCM - 1)]; break; } - mLOG(DS_MEM, STUB, "Bad DS9 Load8: %08X:%08X", address, value); + mLOG(DS_MEM, STUB, "Bad DS9 Load8: %08X", address); + break; + case DS_REGION_WORKING_RAM: + if (ds->memory.wramSize9) { + value = ((uint8_t*) memory->wramBase9)[address & (memory->wramSize9 - 1)]; + break; + } + mLOG(DS_MEM, STUB, "Bad DS9 Load8: %08X", address); break; case DS_REGION_RAM: if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) { - value = ((uint8_t*) memory->dtcm)[address & (DS9_SIZE_DTCM- 1)]; + value = ((uint8_t*) memory->dtcm)[address & (DS9_SIZE_DTCM - 1)]; break; } if ((address & (DS_SIZE_RAM - 1)) < DS_SIZE_RAM) {

@@ -868,6 +892,13 @@ case DS9_REGION_ITCM:

case DS9_REGION_ITCM_MIRROR: if (address < memory->itcmSize) { STORE_32(value, address & (DS9_SIZE_ITCM - 4), memory->itcm); + break; + } + mLOG(DS_MEM, STUB, "Bad DS9 Store32: %08X:%08X", address, value); + break; + case DS_REGION_WORKING_RAM: + if (ds->memory.wramSize9) { + STORE_32(value, address & (ds->memory.wramSize9 - 4), memory->wramBase9); break; } mLOG(DS_MEM, STUB, "Bad DS9 Store32: %08X:%08X", address, value);

@@ -925,6 +956,13 @@ break;

} mLOG(DS_MEM, STUB, "Bad DS9 Store16: %08X:%04X", address, value); break; + case DS_REGION_WORKING_RAM: + if (ds->memory.wramSize9) { + STORE_16(value, address & (ds->memory.wramSize9 - 2), memory->wramBase9); + break; + } + mLOG(DS_MEM, STUB, "Bad DS9 Store16: %08X:%04X", address, value); + break; case DS_REGION_RAM: if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) { STORE_16(value, address & (DS9_SIZE_DTCM - 2), memory->dtcm);

@@ -974,6 +1012,13 @@ case DS9_REGION_ITCM:

case DS9_REGION_ITCM_MIRROR: if (address < memory->itcmSize) { ((uint8_t*) memory->itcm)[address & (DS9_SIZE_ITCM - 1)] = value; + break; + } + mLOG(DS_MEM, STUB, "Bad DS9 Store8: %08X:%02X", address, value); + break; + case DS_REGION_WORKING_RAM: + if (ds->memory.wramSize9) { + ((uint8_t*) memory->wramBase9)[address & (ds->memory.wramSize9 - 1)] = value; break; } mLOG(DS_MEM, STUB, "Bad DS9 Store8: %08X:%02X", address, value);

@@ -1038,6 +1083,13 @@ } else {

mLOG(DS_MEM, STUB, "Bad DS9 LDM: %08X:%08X", address, value); }); break; + case DS_REGION_WORKING_RAM: + LDM_LOOP(if (ds->memory.wramSize9) { + LOAD_32(value, address & (ds->memory.wramSize9 - 4), memory->wramBase9); + } else { + mLOG(DS_MEM, STUB, "Bad DS9 STM: %08X", address); + }); + break; case DS_REGION_RAM: LDM_LOOP(if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) { LOAD_32(value, address & (DS9_SIZE_DTCM - 1), memory->dtcm);

@@ -1117,7 +1169,14 @@ case DS9_REGION_ITCM_MIRROR:

STM_LOOP(if (address < memory->itcmSize) { STORE_32(value, address & (DS9_SIZE_ITCM - 1), memory->itcm); } else { - mLOG(DS_MEM, STUB, "Bad DS9 Store32: %08X:%08X", address, value); + mLOG(DS_MEM, STUB, "Bad DS9 STM: %08X:%08X", address, value); + }); + break; + case DS_REGION_WORKING_RAM: + STM_LOOP(if (ds->memory.wramSize9) { + STORE_32(value, address & (ds->memory.wramSize9 - 4), memory->wramBase9); + } else { + mLOG(DS_MEM, STUB, "Bad DS9 STM: %08X", address); }); break; case DS_REGION_RAM:

@@ -1164,6 +1223,35 @@ }

int32_t DSMemoryStall(struct ARMCore* cpu, int32_t wait) { return wait; +} + +void DSConfigureWRAM(struct DSMemory* memory, uint8_t config) { + switch (config & 3) { + case 0: + memory->wramSize7 = 0; + memory->wramBase7 = NULL; + memory->wramSize9 = DS_SIZE_WORKING_RAM; + memory->wramBase9 = memory->wram; + break; + case 1: + memory->wramSize7 = DS_SIZE_WORKING_RAM >> 1; + memory->wramBase7 = memory->wram; + memory->wramSize9 = DS_SIZE_WORKING_RAM >> 1; + memory->wramBase9 = &memory->wram[DS_SIZE_WORKING_RAM >> 3]; + break; + case 2: + memory->wramSize7 = DS_SIZE_WORKING_RAM >> 1; + memory->wramBase7 = &memory->wram[DS_SIZE_WORKING_RAM >> 3]; + memory->wramSize9 = DS_SIZE_WORKING_RAM >> 1; + memory->wramBase9 = memory->wram; + break; + case 3: + memory->wramSize7 = DS_SIZE_WORKING_RAM; + memory->wramBase7 = memory->wram; + memory->wramSize9 = 0; + memory->wramBase9 = NULL; + break; + } } static unsigned _selectVRAM(struct DSMemory* memory, uint32_t offset) {