From 2c3a1c6f7177a1f99c475ec4fe53a9f55b2d9658 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 20 Feb 2017 17:51:33 -0800 Subject: [PATCH] DS Memory: Add WRAM --- include/mgba/internal/ds/memory.h | 4 ++ src/ds/io.c | 16 +++-- src/ds/memory.c | 114 ++++++++++++++++++++++++++---- 3 files changed, 115 insertions(+), 19 deletions(-) diff --git a/include/mgba/internal/ds/memory.h b/include/mgba/internal/ds/memory.h index f426ab66c..f1568f936 100644 --- a/include/mgba/internal/ds/memory.h +++ b/include/mgba/internal/ds/memory.h @@ -78,6 +78,8 @@ struct DSMemory { 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]; @@ -146,4 +148,6 @@ uint32_t DS9LoadMultiple(struct ARMCore*, uint32_t baseAddress, int mask, enum L uint32_t DS9StoreMultiple(struct ARMCore*, uint32_t baseAddress, int mask, enum LSMDirection direction, int* cycleCounter); +void DSConfigureWRAM(struct DSMemory*, uint8_t config); + #endif diff --git a/src/ds/io.c b/src/ds/io.c index 6ccd0ea97..bde5d70c9 100644 --- a/src/ds/io.c +++ b/src/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 @@ void DS9IOWrite(struct DS* ds, uint32_t address, uint16_t value) { 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 diff --git a/src/ds/memory.c b/src/ds/memory.c index 513c6e4d2..17e3487db 100644 --- a/src/ds/memory.c +++ b/src/ds/memory.c @@ -172,7 +172,9 @@ void DSMemoryReset(struct DS* ds) { // 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 @@ void DSMemoryReset(struct DS* ds) { 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 @@ uint32_t DS7Load32(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { 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 @@ uint32_t DS7Load16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { 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 @@ uint32_t DS7Load8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { 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 @@ void DS7Store32(struct ARMCore* cpu, uint32_t address, int32_t value, int* cycle 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 @@ void DS7Store16(struct ARMCore* cpu, uint32_t address, int16_t value, int* cycle 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 @@ void DS7Store8(struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCo 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 @@ uint32_t DS7LoadMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum L 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 @@ uint32_t DS7StoreMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum 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 @@ uint32_t DS9Load32(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { 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 @@ uint32_t DS9Load16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { 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 @@ uint32_t DS9Load8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { 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) { @@ -872,6 +896,13 @@ void DS9Store32(struct ARMCore* cpu, uint32_t address, int32_t value, int* cycle } 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); + break; case DS_REGION_RAM: if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) { STORE_32(value, address & (DS9_SIZE_DTCM - 4), memory->dtcm); @@ -925,6 +956,13 @@ void DS9Store16(struct ARMCore* cpu, uint32_t address, int16_t value, int* cycle } 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); @@ -978,6 +1016,13 @@ void DS9Store8(struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCo } 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); + break; case DS_REGION_RAM: if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) { ((uint8_t*) memory->dtcm)[address & (DS9_SIZE_DTCM - 1)] = value; @@ -1038,6 +1083,13 @@ uint32_t DS9LoadMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum L 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 @@ uint32_t DS9StoreMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum 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: @@ -1166,6 +1225,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) { unsigned mask = 0; offset &= 0x3FF;