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}