GBA Memory: Matrix Memory support

This commit is contained in:
Vicki Pfau 2018-01-14 10:38:47 -08:00
parent cee6569bde
commit 38e3dbc0fc
6 changed files with 136 additions and 9 deletions

View File

@ -55,6 +55,7 @@ Misc:
- GBA Cheats: Allow multiple ROM patches in the same slot
- GB: Skip BIOS option now works
- Libretro: Add frameskip option
- GBA Memory: 64 MiB GBA Video cartridge support
0.6.1: (2017-10-01)
Bugfixes:

View File

@ -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

View File

@ -17,6 +17,7 @@ CXX_GUARD_START
#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 GBAMemory {
struct GBACartridgeHardware hw;
struct GBASavedata savedata;
struct GBAVFameCart vfame;
struct GBAMatrix matrix;
size_t romSize;
uint32_t romMask;
uint16_t romID;

View File

@ -125,7 +125,9 @@ void GBAUnloadROM(struct GBA* gba) {
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 @@ void GBAReset(struct ARMCore* cpu) {
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 @@ bool GBALoadROM(struct GBA* gba, struct VFile* 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 = vf->map(vf, gba->pristineRomSize, MAP_READ);
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);
#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);

75
src/gba/matrix.c Normal file
View File

@ -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;
}
}

View File

@ -137,6 +137,7 @@ void GBAMemoryReset(struct GBA* gba) {
}
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 @@ uint32_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
#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 \
@ -867,6 +872,10 @@ void GBAStore16(struct ARMCore* cpu, uint32_t address, int16_t value, int* cycle
GBAHardwareGPIOWrite(&memory->hw, reg, value);
break;
}
if (memory->matrix.size && (address & 0x01FFFF00) == 0x00800100) {
GBAMatrixWrite16(gba, address & 0x3C, value);
break;
}
// Fall through
case REGION_CART0_EX:
if ((address & 0x00FFFFFF) >= AGB_PRINT_BASE) {