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}