all repos — mgba @ 7736e72b3841d060d320836781c9f078ee8434e2

mGBA Game Boy Advance Emulator

src/gba/matrix.c (view raw)

  1/* Copyright (c) 2013-2018 Jeffrey Pfau
  2 *
  3 * This Source Code Form is subject to the terms of the Mozilla Public
  4 * License, v. 2.0. If a copy of the MPL was not distributed with this
  5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  6#include <mgba/internal/gba/matrix.h>
  7
  8#include <mgba/internal/arm/macros.h>
  9#include <mgba/internal/gba/gba.h>
 10#include <mgba/internal/gba/memory.h>
 11#include <mgba/internal/gba/serialize.h>
 12#include <mgba-util/vfs.h>
 13
 14#define MAPPING_MASK (GBA_MATRIX_MAPPINGS_MAX - 1)
 15
 16static void _remapMatrix(struct GBA* gba) {
 17	if (gba->memory.matrix.vaddr & 0xFFFFE1FF) {
 18		mLOG(GBA_MEM, ERROR, "Invalid Matrix mapping: %08X", gba->memory.matrix.vaddr);
 19		return;
 20	}
 21	if (gba->memory.matrix.size & 0xFFFFE1FF) {
 22		mLOG(GBA_MEM, ERROR, "Invalid Matrix size: %08X", gba->memory.matrix.size);
 23		return;
 24	}
 25	if ((gba->memory.matrix.vaddr + gba->memory.matrix.size - 1) & 0xFFFFE000) {
 26		mLOG(GBA_MEM, ERROR, "Invalid Matrix mapping end: %08X", gba->memory.matrix.vaddr + gba->memory.matrix.size);
 27		return;
 28	}
 29	int start = gba->memory.matrix.vaddr >> 9;
 30	int size = (gba->memory.matrix.size >> 9) & MAPPING_MASK;
 31	int i;
 32	for (i = 0; i < size; ++i) {
 33		gba->memory.matrix.mappings[(start + i) & MAPPING_MASK] = gba->memory.matrix.paddr + (i << 9);
 34	}
 35
 36	gba->romVf->seek(gba->romVf, gba->memory.matrix.paddr, SEEK_SET);
 37	gba->romVf->read(gba->romVf, &gba->memory.rom[gba->memory.matrix.vaddr >> 2], gba->memory.matrix.size);
 38}
 39
 40void GBAMatrixReset(struct GBA* gba) {
 41	memset(gba->memory.matrix.mappings, 0, sizeof(gba->memory.matrix.mappings));
 42	gba->memory.matrix.size = 0x1000;
 43
 44	gba->memory.matrix.paddr = 0;
 45	gba->memory.matrix.vaddr = 0;
 46	_remapMatrix(gba);
 47	gba->memory.matrix.paddr = 0x200;
 48	gba->memory.matrix.vaddr = 0x1000;
 49	_remapMatrix(gba);
 50}
 51
 52void GBAMatrixWrite(struct GBA* gba, uint32_t address, uint32_t value) {
 53	switch (address) {
 54	case 0x0:
 55		gba->memory.matrix.cmd = value;
 56		switch (value) {
 57		case 0x01:
 58		case 0x11:
 59			_remapMatrix(gba);
 60			break;
 61		default:
 62			mLOG(GBA_MEM, STUB, "Unknown Matrix command: %08X", value);
 63			break;
 64		}
 65		return;
 66	case 0x4:
 67		gba->memory.matrix.paddr = value & 0x03FFFFFF;
 68		return;
 69	case 0x8:
 70		gba->memory.matrix.vaddr = value & 0x007FFFFF;
 71		return;
 72	case 0xC:
 73		if (value == 0) {
 74			mLOG(GBA_MEM, ERROR, "Rejecting Matrix write for size 0");
 75			return;
 76		}
 77		gba->memory.matrix.size = value << 9;
 78		return;
 79	}
 80	mLOG(GBA_MEM, STUB, "Unknown Matrix write: %08X:%04X", address, value);
 81}
 82
 83void GBAMatrixWrite16(struct GBA* gba, uint32_t address, uint16_t value) {
 84	switch (address) {
 85	case 0x0:
 86		GBAMatrixWrite(gba, address, value | (gba->memory.matrix.cmd & 0xFFFF0000));
 87		break;
 88	case 0x4:
 89		GBAMatrixWrite(gba, address, value | (gba->memory.matrix.paddr & 0xFFFF0000));
 90		break;
 91	case 0x8:
 92		GBAMatrixWrite(gba, address, value | (gba->memory.matrix.vaddr & 0xFFFF0000));
 93		break;
 94	case 0xC:
 95		GBAMatrixWrite(gba, address, value | (gba->memory.matrix.size & 0xFFFF0000));
 96		break;
 97	}
 98}
 99
100void GBAMatrixSerialize(const struct GBA* gba, struct GBASerializedState* state) {
101	STORE_32(gba->memory.matrix.cmd, 0, &state->matrix.cmd);
102	STORE_32(gba->memory.matrix.paddr, 0, &state->matrix.paddr);
103	STORE_32(gba->memory.matrix.vaddr, 0, &state->matrix.vaddr);
104	STORE_32(gba->memory.matrix.size, 0, &state->matrix.size);
105
106	if (GBA_MATRIX_MAPPINGS_MAX != 16) {
107		mLOG(GBA_MEM, ERROR, "Matrix memory serialization is broken!");
108	}
109
110	int i;
111	for (i = 0; i < 16; ++i) {
112		STORE_32(gba->memory.matrix.mappings[i], i << 2, state->matrixMappings);
113	}
114}
115
116void GBAMatrixDeserialize(struct GBA* gba, const struct GBASerializedState* state) {
117	if (GBA_MATRIX_MAPPINGS_MAX != 16) {
118		mLOG(GBA_MEM, ERROR, "Matrix memory deserialization is broken!");
119	}
120	gba->memory.matrix.size = 0x200;
121
122	int i;
123	for (i = 0; i < 16; ++i) {
124		LOAD_32(gba->memory.matrix.mappings[i], i << 2, state->matrixMappings);
125		gba->memory.matrix.paddr = gba->memory.matrix.mappings[i];
126		gba->memory.matrix.vaddr = i << 9;
127		_remapMatrix(gba);
128	}
129
130	LOAD_32(gba->memory.matrix.cmd, 0, &state->matrix.cmd);
131	LOAD_32(gba->memory.matrix.paddr, 0, &state->matrix.paddr);
132	LOAD_32(gba->memory.matrix.vaddr, 0, &state->matrix.vaddr);
133	LOAD_32(gba->memory.matrix.size, 0, &state->matrix.size);
134}