mirror of https://github.com/mgba-emu/mgba.git
GBA Memory: Improve robustness of Matrix memory support
This commit is contained in:
parent
6e01765ed2
commit
65fb61d7e2
1
CHANGES
1
CHANGES
|
@ -33,6 +33,7 @@ Emulation fixes:
|
|||
- GBA Hardware: Fix GB Player detection on big endian platforms
|
||||
- GBA Memory: Improve gamepak prefetch timing
|
||||
- GBA Memory: Stall on VRAM access in mode 2 (fixes mgba.io/i/190)
|
||||
- GBA Memory: Improve robustness of Matrix memory support
|
||||
- GBA SIO: Fix copying Normal mode transfer values
|
||||
- GBA SIO: Fix Normal mode being totally broken (fixes mgba.io/i/1800)
|
||||
- GBA SIO: Fix deseralizing SIO registers
|
||||
|
|
|
@ -10,19 +10,26 @@
|
|||
|
||||
CXX_GUARD_START
|
||||
|
||||
#define GBA_MATRIX_MAPPINGS_MAX 16
|
||||
|
||||
struct GBAMatrix {
|
||||
uint32_t cmd;
|
||||
uint32_t paddr;
|
||||
uint32_t vaddr;
|
||||
uint32_t size;
|
||||
|
||||
uint32_t mappings[GBA_MATRIX_MAPPINGS_MAX];
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
struct GBASerializedState;
|
||||
void GBAMatrixSerialize(const struct GBA* memory, struct GBASerializedState* state);
|
||||
void GBAMatrixDeserialize(struct GBA* memory, const struct GBASerializedState* state);
|
||||
|
||||
CXX_GUARD_END
|
||||
|
||||
#endif
|
||||
|
|
|
@ -331,7 +331,12 @@ struct GBASerializedState {
|
|||
uint32_t dmaTransferRegister;
|
||||
uint32_t dmaBlockPC;
|
||||
|
||||
uint32_t reservedHardware[4];
|
||||
struct {
|
||||
uint32_t cmd;
|
||||
uint32_t paddr;
|
||||
uint32_t vaddr;
|
||||
uint32_t size;
|
||||
} matrix;
|
||||
|
||||
struct {
|
||||
uint8_t type;
|
||||
|
@ -356,7 +361,9 @@ struct GBASerializedState {
|
|||
uint32_t nextIrq;
|
||||
int32_t biosStall;
|
||||
|
||||
uint32_t reserved[54];
|
||||
uint32_t matrixMappings[16];
|
||||
|
||||
uint32_t reserved[38];
|
||||
|
||||
uint16_t io[SIZE_IO >> 1];
|
||||
uint16_t pram[SIZE_PALETTE_RAM >> 1];
|
||||
|
|
|
@ -8,25 +8,42 @@
|
|||
#include <mgba/internal/arm/macros.h>
|
||||
#include <mgba/internal/gba/gba.h>
|
||||
#include <mgba/internal/gba/memory.h>
|
||||
#include <mgba/internal/gba/serialize.h>
|
||||
#include <mgba-util/vfs.h>
|
||||
|
||||
static void _remapMatrix(struct GBA* gba) {
|
||||
if (gba->memory.matrix.vaddr & 0xFFFFE1FF) {
|
||||
mLOG(GBA_MEM, ERROR, "Invalid Matrix mapping: %08X", gba->memory.matrix.vaddr);
|
||||
return;
|
||||
}
|
||||
if (gba->memory.matrix.size & 0xFFFFE1FF) {
|
||||
mLOG(GBA_MEM, ERROR, "Invalid Matrix size: %08X", gba->memory.matrix.size);
|
||||
return;
|
||||
}
|
||||
if ((gba->memory.matrix.vaddr + gba->memory.matrix.size - 1) & 0xFFFFE000) {
|
||||
mLOG(GBA_MEM, ERROR, "Invalid Matrix mapping end: %08X", gba->memory.matrix.vaddr + gba->memory.matrix.size);
|
||||
return;
|
||||
}
|
||||
int start = (gba->memory.matrix.vaddr >> 9) & 0x1F;
|
||||
int size = (gba->memory.matrix.size >> 9) & 0x1F;
|
||||
int i;
|
||||
for (i = 0; i < size; ++i) {
|
||||
gba->memory.matrix.mappings[start + i] = gba->memory.matrix.paddr + (i << 9);
|
||||
}
|
||||
|
||||
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;
|
||||
memset(gba->memory.matrix.mappings, 0, sizeof(gba->memory.matrix.mappings));
|
||||
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);
|
||||
gba->memory.matrix.paddr = 0x200;
|
||||
gba->memory.matrix.vaddr = 0x1000;
|
||||
_remapMatrix(gba);
|
||||
}
|
||||
|
||||
|
@ -51,6 +68,10 @@ void GBAMatrixWrite(struct GBA* gba, uint32_t address, uint32_t value) {
|
|||
gba->memory.matrix.vaddr = value & 0x007FFFFF;
|
||||
return;
|
||||
case 0xC:
|
||||
if (value == 0) {
|
||||
mLOG(GBA_MEM, ERROR, "Rejecting Matrix write for size 0");
|
||||
return;
|
||||
}
|
||||
gba->memory.matrix.size = value << 9;
|
||||
return;
|
||||
}
|
||||
|
@ -73,3 +94,39 @@ void GBAMatrixWrite16(struct GBA* gba, uint32_t address, uint16_t value) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void GBAMatrixSerialize(const struct GBA* gba, struct GBASerializedState* state) {
|
||||
STORE_32(gba->memory.matrix.cmd, 0, &state->matrix.cmd);
|
||||
STORE_32(gba->memory.matrix.paddr, 0, &state->matrix.paddr);
|
||||
STORE_32(gba->memory.matrix.vaddr, 0, &state->matrix.vaddr);
|
||||
STORE_32(gba->memory.matrix.size, 0, &state->matrix.size);
|
||||
|
||||
if (GBA_MATRIX_MAPPINGS_MAX != 16) {
|
||||
mLOG(GBA_MEM, ERROR, "Matrix memory serialization is broken!");
|
||||
}
|
||||
|
||||
int i;
|
||||
for (i = 0; i < 16; ++i) {
|
||||
STORE_32(gba->memory.matrix.mappings[i], i << 2, state->matrixMappings);
|
||||
}
|
||||
}
|
||||
|
||||
void GBAMatrixDeserialize(struct GBA* gba, const struct GBASerializedState* state) {
|
||||
if (GBA_MATRIX_MAPPINGS_MAX != 16) {
|
||||
mLOG(GBA_MEM, ERROR, "Matrix memory deserialization is broken!");
|
||||
}
|
||||
gba->memory.matrix.size = 0x200;
|
||||
|
||||
int i;
|
||||
for (i = 0; i < 16; ++i) {
|
||||
LOAD_32(gba->memory.matrix.mappings[i], i << 2, state->matrixMappings);
|
||||
gba->memory.matrix.paddr = gba->memory.matrix.mappings[i];
|
||||
gba->memory.matrix.vaddr = i << 9;
|
||||
_remapMatrix(gba);
|
||||
}
|
||||
|
||||
LOAD_32(gba->memory.matrix.cmd, 0, &state->matrix.cmd);
|
||||
LOAD_32(gba->memory.matrix.paddr, 0, &state->matrix.paddr);
|
||||
LOAD_32(gba->memory.matrix.vaddr, 0, &state->matrix.vaddr);
|
||||
LOAD_32(gba->memory.matrix.size, 0, &state->matrix.size);
|
||||
}
|
||||
|
|
|
@ -76,6 +76,10 @@ void GBASerialize(struct GBA* gba, struct GBASerializedState* state) {
|
|||
GBAVideoSerialize(&gba->video, state);
|
||||
GBAAudioSerialize(&gba->audio, state);
|
||||
GBASavedataSerialize(&gba->memory.savedata, state);
|
||||
|
||||
if (gba->memory.matrix.size) {
|
||||
GBAMatrixSerialize(gba, state);
|
||||
}
|
||||
}
|
||||
|
||||
bool GBADeserialize(struct GBA* gba, const struct GBASerializedState* state) {
|
||||
|
@ -196,6 +200,10 @@ bool GBADeserialize(struct GBA* gba, const struct GBASerializedState* state) {
|
|||
GBAAudioDeserialize(&gba->audio, state);
|
||||
GBASavedataDeserialize(&gba->memory.savedata, state);
|
||||
|
||||
if (gba->memory.matrix.size) {
|
||||
GBAMatrixDeserialize(gba, state);
|
||||
}
|
||||
|
||||
gba->timing.reroot = gba->timing.root;
|
||||
gba->timing.root = NULL;
|
||||
|
||||
|
|
Loading…
Reference in New Issue