all repos — mgba @ 65fb61d7e2f5848aac38a12d4042419bb4e537c9

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
 14static void _remapMatrix(struct GBA* gba) {
 15	if (gba->memory.matrix.vaddr & 0xFFFFE1FF) {
 16		mLOG(GBA_MEM, ERROR, "Invalid Matrix mapping: %08X", gba->memory.matrix.vaddr);
 17		return;
 18	}
 19	if (gba->memory.matrix.size & 0xFFFFE1FF) {
 20		mLOG(GBA_MEM, ERROR, "Invalid Matrix size: %08X", gba->memory.matrix.size);
 21		return;
 22	}
 23	if ((gba->memory.matrix.vaddr + gba->memory.matrix.size - 1) & 0xFFFFE000) {
 24		mLOG(GBA_MEM, ERROR, "Invalid Matrix mapping end: %08X", gba->memory.matrix.vaddr + gba->memory.matrix.size);
 25		return;
 26	}
 27	int start = (gba->memory.matrix.vaddr >> 9) & 0x1F;
 28	int size = (gba->memory.matrix.size >> 9) & 0x1F;
 29	int i;
 30	for (i = 0; i < size; ++i) {
 31		gba->memory.matrix.mappings[start + i] = gba->memory.matrix.paddr + (i << 9);
 32	}
 33
 34	gba->romVf->seek(gba->romVf, gba->memory.matrix.paddr, SEEK_SET);
 35	gba->romVf->read(gba->romVf, &gba->memory.rom[gba->memory.matrix.vaddr >> 2], gba->memory.matrix.size);
 36}
 37
 38void GBAMatrixReset(struct GBA* gba) {
 39	memset(gba->memory.matrix.mappings, 0, sizeof(gba->memory.matrix.mappings));
 40	gba->memory.matrix.size = 0x1000;
 41
 42	gba->memory.matrix.paddr = 0;
 43	gba->memory.matrix.vaddr = 0;
 44	_remapMatrix(gba);
 45	gba->memory.matrix.paddr = 0x200;
 46	gba->memory.matrix.vaddr = 0x1000;
 47	_remapMatrix(gba);
 48}
 49
 50void GBAMatrixWrite(struct GBA* gba, uint32_t address, uint32_t value) {
 51	switch (address) {
 52	case 0x0:
 53		gba->memory.matrix.cmd = value;
 54		switch (value) {
 55		case 0x01:
 56		case 0x11:
 57			_remapMatrix(gba);
 58			break;
 59		default:
 60			mLOG(GBA_MEM, STUB, "Unknown Matrix command: %08X", value);
 61			break;
 62		}
 63		return;
 64	case 0x4:
 65		gba->memory.matrix.paddr = value & 0x03FFFFFF;
 66		return;
 67	case 0x8:
 68		gba->memory.matrix.vaddr = value & 0x007FFFFF;
 69		return;
 70	case 0xC:
 71		if (value == 0) {
 72			mLOG(GBA_MEM, ERROR, "Rejecting Matrix write for size 0");
 73			return;
 74		}
 75		gba->memory.matrix.size = value << 9;
 76		return;
 77	}
 78	mLOG(GBA_MEM, STUB, "Unknown Matrix write: %08X:%04X", address, value);
 79}
 80
 81void GBAMatrixWrite16(struct GBA* gba, uint32_t address, uint16_t value) {
 82	switch (address) {
 83	case 0x0:
 84		GBAMatrixWrite(gba, address, value | (gba->memory.matrix.cmd & 0xFFFF0000));
 85		break;
 86	case 0x4:
 87		GBAMatrixWrite(gba, address, value | (gba->memory.matrix.paddr & 0xFFFF0000));
 88		break;
 89	case 0x8:
 90		GBAMatrixWrite(gba, address, value | (gba->memory.matrix.vaddr & 0xFFFF0000));
 91		break;
 92	case 0xC:
 93		GBAMatrixWrite(gba, address, value | (gba->memory.matrix.size & 0xFFFF0000));
 94		break;
 95	}
 96}
 97
 98void GBAMatrixSerialize(const struct GBA* gba, struct GBASerializedState* state) {
 99	STORE_32(gba->memory.matrix.cmd, 0, &state->matrix.cmd);
100	STORE_32(gba->memory.matrix.paddr, 0, &state->matrix.paddr);
101	STORE_32(gba->memory.matrix.vaddr, 0, &state->matrix.vaddr);
102	STORE_32(gba->memory.matrix.size, 0, &state->matrix.size);
103
104	if (GBA_MATRIX_MAPPINGS_MAX != 16) {
105		mLOG(GBA_MEM, ERROR, "Matrix memory serialization is broken!");
106	}
107
108	int i;
109	for (i = 0; i < 16; ++i) {
110		STORE_32(gba->memory.matrix.mappings[i], i << 2, state->matrixMappings);
111	}
112}
113
114void GBAMatrixDeserialize(struct GBA* gba, const struct GBASerializedState* state) {
115	if (GBA_MATRIX_MAPPINGS_MAX != 16) {
116		mLOG(GBA_MEM, ERROR, "Matrix memory deserialization is broken!");
117	}
118	gba->memory.matrix.size = 0x200;
119
120	int i;
121	for (i = 0; i < 16; ++i) {
122		LOAD_32(gba->memory.matrix.mappings[i], i << 2, state->matrixMappings);
123		gba->memory.matrix.paddr = gba->memory.matrix.mappings[i];
124		gba->memory.matrix.vaddr = i << 9;
125		_remapMatrix(gba);
126	}
127
128	LOAD_32(gba->memory.matrix.cmd, 0, &state->matrix.cmd);
129	LOAD_32(gba->memory.matrix.paddr, 0, &state->matrix.paddr);
130	LOAD_32(gba->memory.matrix.vaddr, 0, &state->matrix.vaddr);
131	LOAD_32(gba->memory.matrix.size, 0, &state->matrix.size);
132}