GBA Memory: Matrix Memory support
Vicki Pfau vi@endrift.com
Sun, 14 Jan 2018 10:38:47 -0800
6 files changed,
136 insertions(+),
9 deletions(-)
A
include/mgba/internal/gba/matrix.h
@@ -0,0 +1,28 @@
+/* Copyright (c) 2013-2018 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef GBA_MATRIX_H +#define GBA_MATRIX_H + +#include <mgba-util/common.h> + +CXX_GUARD_START + +struct GBAMatrix { + uint32_t cmd; + uint32_t paddr; + uint32_t vaddr; + uint32_t size; +}; + +struct GBA; +struct GBAMemory; +void GBAMatrixReset(struct GBA*); +void GBAMatrixWrite(struct GBA*, uint32_t address, uint32_t value); +void GBAMatrixWrite16(struct GBA*, uint32_t address, uint16_t value); + +CXX_GUARD_END + +#endif
M
include/mgba/internal/gba/memory.h
→
include/mgba/internal/gba/memory.h
@@ -17,6 +17,7 @@ #include <mgba/internal/gba/dma.h>
#include <mgba/internal/gba/hardware.h> #include <mgba/internal/gba/savedata.h> #include <mgba/internal/gba/vfame.h> +#include <mgba/internal/gba/matrix.h> enum GBAMemoryRegion { REGION_BIOS = 0x0,@@ -106,6 +107,7 @@
struct GBACartridgeHardware hw; struct GBASavedata savedata; struct GBAVFameCart vfame; + struct GBAMatrix matrix; size_t romSize; uint32_t romMask; uint16_t romID;
M
src/gba/gba.c
→
src/gba/gba.c
@@ -125,7 +125,9 @@ }
if (gba->romVf) { #ifndef FIXED_ROM_BUFFER - gba->romVf->unmap(gba->romVf, gba->memory.rom, gba->pristineRomSize); + if (gba->isPristine) { + gba->romVf->unmap(gba->romVf, gba->memory.rom, gba->pristineRomSize); + } #endif gba->romVf->close(gba->romVf); gba->romVf = NULL;@@ -207,6 +209,9 @@ gba->idleDetectionFailures = 0;
gba->debug = false; memset(gba->debugString, 0, sizeof(gba->debugString)); + if (gba->pristineRomSize > SIZE_CART0) { + GBAMatrixReset(gba); + } if (!gba->romVf && gba->memory.rom) { GBASkipBIOS(gba);@@ -355,23 +360,30 @@ gba->romVf = vf;
gba->pristineRomSize = vf->size(vf); vf->seek(vf, 0, SEEK_SET); if (gba->pristineRomSize > SIZE_CART0) { - gba->pristineRomSize = SIZE_CART0; - } - gba->isPristine = true; + gba->isPristine = false; + gba->memory.romSize = 0x01000000; #ifdef FIXED_ROM_BUFFER - if (gba->pristineRomSize <= romBufferSize) { gba->memory.rom = romBuffer; - vf->read(vf, romBuffer, gba->pristineRomSize); - } +#else + gba->memory.rom = anonymousMemoryMap(SIZE_CART0); +#endif + } else { + gba->isPristine = true; +#ifdef FIXED_ROM_BUFFER + if (gba->pristineRomSize <= romBufferSize) { + gba->memory.rom = romBuffer; + vf->read(vf, romBuffer, gba->pristineRomSize); + } #else - gba->memory.rom = vf->map(vf, gba->pristineRomSize, MAP_READ); + gba->memory.rom = vf->map(vf, gba->pristineRomSize, MAP_READ); #endif + gba->memory.romSize = gba->pristineRomSize; + } if (!gba->memory.rom) { mLOG(GBA, WARN, "Couldn't map ROM"); return false; } gba->yankedRomSize = 0; - gba->memory.romSize = gba->pristineRomSize; gba->memory.romMask = toPow2(gba->memory.romSize) - 1; gba->memory.mirroring = false; gba->romCrc32 = doCrc32(gba->memory.rom, gba->memory.romSize);
A
src/gba/matrix.c
@@ -0,0 +1,75 @@
+/* Copyright (c) 2013-2018 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include <mgba/internal/gba/matrix.h> + +#include <mgba/internal/arm/macros.h> +#include <mgba/internal/gba/gba.h> +#include <mgba/internal/gba/memory.h> +#include <mgba-util/vfs.h> + +static void _remapMatrix(struct GBA* gba) { + gba->romVf->seek(gba->romVf, gba->memory.matrix.paddr, SEEK_SET); + gba->romVf->read(gba->romVf, &gba->memory.rom[gba->memory.matrix.vaddr >> 2], gba->memory.matrix.size); +} + +void GBAMatrixReset(struct GBA* gba) { + gba->memory.matrix.paddr = 0x200; + gba->memory.matrix.size = 0x1000; + + gba->memory.matrix.vaddr = 0; + _remapMatrix(gba); + gba->memory.matrix.vaddr = 0x1000; + _remapMatrix(gba); + + gba->memory.matrix.paddr = 0; + gba->memory.matrix.vaddr = 0; + gba->memory.matrix.size = 0x100; + _remapMatrix(gba); +} + +void GBAMatrixWrite(struct GBA* gba, uint32_t address, uint32_t value) { + switch (address) { + case 0x0: + gba->memory.matrix.cmd = value; + switch (value) { + case 0x01: + case 0x11: + _remapMatrix(gba); + break; + default: + mLOG(GBA_MEM, STUB, "Unknown Matrix command: %08X", value); + break; + } + return; + case 0x4: + gba->memory.matrix.paddr = value & 0x03FFFFFF; + return; + case 0x8: + gba->memory.matrix.vaddr = value & 0x007FFFFF; + return; + case 0xC: + gba->memory.matrix.size = value << 9; + return; + } + mLOG(GBA_MEM, STUB, "Unknown Matrix write: %08X:%04X", address, value); +} + +void GBAMatrixWrite16(struct GBA* gba, uint32_t address, uint16_t value) { + switch (address) { + case 0x0: + GBAMatrixWrite(gba, address, value | (gba->memory.matrix.cmd & 0xFFFF0000)); + break; + case 0x4: + GBAMatrixWrite(gba, address, value | (gba->memory.matrix.paddr & 0xFFFF0000)); + break; + case 0x8: + GBAMatrixWrite(gba, address, value | (gba->memory.matrix.vaddr & 0xFFFF0000)); + break; + case 0xC: + GBAMatrixWrite(gba, address, value | (gba->memory.matrix.size & 0xFFFF0000)); + break; + } +}
M
src/gba/memory.c
→
src/gba/memory.c
@@ -137,6 +137,7 @@ mLOG(GBA_MEM, FATAL, "Could not map memory");
} GBADMAReset(gba); + memset(&gba->memory.matrix, 0, sizeof(gba->memory.matrix)); } static void _analyzeForIdleLoop(struct GBA* gba, struct ARMCore* cpu, uint32_t address) {@@ -748,6 +749,10 @@ }
#define STORE_CART \ wait += waitstatesRegion[address >> BASE_OFFSET]; \ + if (memory->matrix.size && (address & 0x01FFFF00) == 0x00800100) { \ + GBAMatrixWrite(gba, address & 0x3C, value); \ + break; \ + } \ mLOG(GBA_MEM, STUB, "Unimplemented memory Store32: 0x%08X", address); #define STORE_SRAM \@@ -865,6 +870,10 @@ case REGION_CART0:
if (memory->hw.devices != HW_NONE && IS_GPIO_REGISTER(address & 0xFFFFFE)) { uint32_t reg = address & 0xFFFFFE; GBAHardwareGPIOWrite(&memory->hw, reg, value); + break; + } + if (memory->matrix.size && (address & 0x01FFFF00) == 0x00800100) { + GBAMatrixWrite16(gba, address & 0x3C, value); break; } // Fall through