all repos — mgba @ 1838cc0597ed00d5293134eb6af64f83493c889c

mGBA Game Boy Advance Emulator

src/gba/gba-memory.c (view raw)

  1#include "gba-memory.h"
  2
  3#include "gba-io.h"
  4
  5#include <string.h>
  6#include <sys/mman.h>
  7
  8static const char* GBA_CANNOT_MMAP = "Could not map memory";
  9
 10static void GBASetActiveRegion(struct ARMMemory* memory, uint32_t region);
 11
 12static const char GBA_BASE_WAITSTATES[16] = { 0, 0, 2, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4 };
 13static const char GBA_BASE_WAITSTATES_SEQ[16] = { 0, 0, 2, 0, 0, 0, 0, 0, 2, 2, 4, 4, 8, 8, 4 };
 14static const char GBA_ROM_WAITSTATES[] = { 4, 3, 2, 8 };
 15static const char GBA_ROM_WAITSTATES_SEQ[] = { 2, 1, 4, 1, 8, 1 };
 16
 17void GBAMemoryInit(struct GBAMemory* memory) {
 18	memory->d.load32 = GBALoad32;
 19	memory->d.load16 = GBALoad16;
 20	memory->d.loadU16 = GBALoadU16;
 21	memory->d.load8 = GBALoad8;
 22	memory->d.loadU8 = GBALoadU8;
 23	memory->d.store32 = GBAStore32;
 24	memory->d.store16 = GBAStore16;
 25	memory->d.store8 = GBAStore8;
 26
 27	memory->bios = 0;
 28	memory->wram = mmap(0, SIZE_WORKING_RAM, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
 29	memory->iwram = mmap(0, SIZE_WORKING_IRAM, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
 30	memory->rom = 0;
 31	memset(memory->io, 0, sizeof(memory->io));
 32
 33	if (!memory->wram || !memory->iwram) {
 34		GBAMemoryDeinit(memory);
 35		memory->p->errno = GBA_OUT_OF_MEMORY;
 36		memory->p->errstr = GBA_CANNOT_MMAP;
 37	}
 38
 39	int i;
 40	for (i = 0; i < 16; ++i) {
 41		memory->waitstates16[i] = GBA_BASE_WAITSTATES[i];
 42		memory->waitstatesSeq16[i] = GBA_BASE_WAITSTATES_SEQ[i];
 43		memory->waitstates32[i] = GBA_BASE_WAITSTATES[i] + GBA_BASE_WAITSTATES_SEQ[i] + 1;
 44		memory->waitstatesSeq32[i] = GBA_BASE_WAITSTATES_SEQ[i] + GBA_BASE_WAITSTATES_SEQ[i] + 1;
 45	}
 46	for (; i < 256; ++i) {
 47		memory->waitstates16[i] = 0;
 48		memory->waitstatesSeq16[i] = 0;
 49		memory->waitstates32[i] = 0;
 50		memory->waitstatesSeq32[i] = 0;
 51	}
 52
 53	memory->activeRegion = 0;
 54	memory->d.activeRegion = 0;
 55	memory->d.activeMask = 0;
 56	memory->d.setActiveRegion = GBASetActiveRegion;
 57	memory->d.activePrefetchCycles32 = 0;
 58	memory->d.activePrefetchCycles16 = 0;
 59}
 60
 61void GBAMemoryDeinit(struct GBAMemory* memory) {
 62	munmap(memory->wram, SIZE_WORKING_RAM);
 63	munmap(memory->iwram, SIZE_WORKING_IRAM);
 64}
 65
 66static void GBASetActiveRegion(struct ARMMemory* memory, uint32_t address) {
 67	struct GBAMemory* gbaMemory = (struct GBAMemory*) memory;
 68
 69	memory->activePrefetchCycles32 = gbaMemory->waitstates32[address >> BASE_OFFSET];
 70	memory->activePrefetchCycles16 = gbaMemory->waitstates16[address >> BASE_OFFSET];
 71	gbaMemory->activeRegion = address >> BASE_OFFSET;
 72	switch (address & ~OFFSET_MASK) {
 73	case BASE_BIOS:
 74		memory->activeRegion = gbaMemory->bios;
 75		memory->activeMask = 0;
 76		break;
 77	case BASE_WORKING_RAM:
 78		memory->activeRegion = gbaMemory->wram;
 79		memory->activeMask = SIZE_WORKING_RAM - 1;
 80		break;
 81	case BASE_WORKING_IRAM:
 82		memory->activeRegion = gbaMemory->iwram;
 83		memory->activeMask = SIZE_WORKING_IRAM - 1;
 84		break;
 85	case BASE_CART0:
 86	case BASE_CART0_EX:
 87	case BASE_CART1:
 88	case BASE_CART1_EX:
 89	case BASE_CART2:
 90	case BASE_CART2_EX:
 91		memory->activeRegion = gbaMemory->rom;
 92		memory->activeMask = SIZE_CART0 - 1;
 93		break;
 94	default:
 95		memory->activeRegion = 0;
 96		memory->activeMask = 0;
 97		break;
 98	}
 99}
100
101int32_t GBALoad32(struct ARMMemory* memory, uint32_t address) {
102	struct GBAMemory* gbaMemory = (struct GBAMemory*) memory;
103
104	switch (address & ~OFFSET_MASK) {
105	case BASE_BIOS:
106		break;
107	case BASE_WORKING_RAM:
108		return gbaMemory->wram[(address & (SIZE_WORKING_RAM - 1)) >> 2];
109	case BASE_WORKING_IRAM:
110		return gbaMemory->iwram[(address & (SIZE_WORKING_IRAM - 1)) >> 2];
111	case BASE_IO:
112		break;
113	case BASE_PALETTE_RAM:
114		break;
115	case BASE_VRAM:
116		break;
117	case BASE_OAM:
118		break;
119	case BASE_CART0:
120	case BASE_CART0_EX:
121	case BASE_CART1:
122	case BASE_CART1_EX:
123	case BASE_CART2:
124	case BASE_CART2_EX:
125		return gbaMemory->rom[(address & (SIZE_CART0 - 1)) >> 2];
126	case BASE_CART_SRAM:
127		break;
128	default:
129		break;
130	}
131
132	return 0;
133}
134
135int16_t GBALoad16(struct ARMMemory* memory, uint32_t address) {
136	struct GBAMemory* gbaMemory = (struct GBAMemory*) memory;
137
138	switch (address & ~OFFSET_MASK) {
139	case BASE_BIOS:
140		break;
141	case BASE_WORKING_RAM:
142		return ((int16_t*) gbaMemory->wram)[(address & (SIZE_WORKING_RAM - 1)) >> 1];
143	case BASE_WORKING_IRAM:
144		return ((int16_t*) gbaMemory->iwram)[(address & (SIZE_WORKING_IRAM - 1)) >> 1];
145	case BASE_IO:
146		return GBAIORead(gbaMemory->p, address & (SIZE_IO - 1));
147	case BASE_PALETTE_RAM:
148		break;
149	case BASE_VRAM:
150		break;
151	case BASE_OAM:
152		break;
153	case BASE_CART0:
154	case BASE_CART0_EX:
155	case BASE_CART1:
156	case BASE_CART1_EX:
157	case BASE_CART2:
158	case BASE_CART2_EX:
159		return ((int16_t*) gbaMemory->rom)[(address & (SIZE_CART0 - 1)) >> 1];
160	case BASE_CART_SRAM:
161		break;
162	default:
163		break;
164	}
165
166	return 0;
167}
168
169uint16_t GBALoadU16(struct ARMMemory* memory, uint32_t address) {
170	struct GBAMemory* gbaMemory = (struct GBAMemory*) memory;
171
172	switch (address & ~OFFSET_MASK) {
173	case BASE_BIOS:
174		break;
175	case BASE_WORKING_RAM:
176		return ((uint16_t*) gbaMemory->wram)[(address & (SIZE_WORKING_RAM - 1)) >> 1];
177	case BASE_WORKING_IRAM:
178		return ((uint16_t*) gbaMemory->iwram)[(address & (SIZE_WORKING_IRAM - 1)) >> 1];
179	case BASE_IO:
180		return GBAIORead(gbaMemory->p, address & (SIZE_IO - 1));
181	case BASE_PALETTE_RAM:
182		break;
183	case BASE_VRAM:
184		break;
185	case BASE_OAM:
186		break;
187	case BASE_CART0:
188	case BASE_CART0_EX:
189	case BASE_CART1:
190	case BASE_CART1_EX:
191	case BASE_CART2:
192	case BASE_CART2_EX:
193		return ((uint16_t*) gbaMemory->rom)[(address & (SIZE_CART0 - 1)) >> 1];
194	case BASE_CART_SRAM:
195		break;
196	default:
197		break;
198	}
199
200	return 0;
201}
202
203int8_t GBALoad8(struct ARMMemory* memory, uint32_t address) {
204	struct GBAMemory* gbaMemory = (struct GBAMemory*) memory;
205
206	switch (address & ~OFFSET_MASK) {
207	case BASE_BIOS:
208		break;
209	case BASE_WORKING_RAM:
210		return ((int8_t*) gbaMemory->wram)[address & (SIZE_WORKING_RAM - 1)];
211	case BASE_WORKING_IRAM:
212		return ((int8_t*) gbaMemory->iwram)[address & (SIZE_WORKING_IRAM - 1)];
213	case BASE_IO:
214		break;
215	case BASE_PALETTE_RAM:
216		break;
217	case BASE_VRAM:
218		break;
219	case BASE_OAM:
220		break;
221	case BASE_CART0:
222	case BASE_CART0_EX:
223	case BASE_CART1:
224	case BASE_CART1_EX:
225	case BASE_CART2:
226	case BASE_CART2_EX:
227		return ((int8_t*) gbaMemory->rom)[address & (SIZE_CART0 - 1)];
228	case BASE_CART_SRAM:
229		break;
230	default:
231		break;
232	}
233
234	return 0;
235}
236
237uint8_t GBALoadU8(struct ARMMemory* memory, uint32_t address) {
238	struct GBAMemory* gbaMemory = (struct GBAMemory*) memory;
239
240	switch (address & ~OFFSET_MASK) {
241	case BASE_BIOS:
242		break;
243	case BASE_WORKING_RAM:
244		return ((uint8_t*) gbaMemory->wram)[address & (SIZE_WORKING_RAM - 1)];
245		break;
246	case BASE_WORKING_IRAM:
247		return ((uint8_t*) gbaMemory->iwram)[address & (SIZE_WORKING_IRAM - 1)];
248		break;
249	case BASE_IO:
250		break;
251	case BASE_PALETTE_RAM:
252		break;
253	case BASE_VRAM:
254		break;
255	case BASE_OAM:
256		break;
257	case BASE_CART0:
258	case BASE_CART0_EX:
259	case BASE_CART1:
260	case BASE_CART1_EX:
261	case BASE_CART2:
262	case BASE_CART2_EX:
263		return ((uint8_t*) gbaMemory->rom)[address & (SIZE_CART0 - 1)];
264	case BASE_CART_SRAM:
265		break;
266	default:
267		break;
268	}
269
270	return 0;
271}
272
273void GBAStore32(struct ARMMemory* memory, uint32_t address, int32_t value) {
274	struct GBAMemory* gbaMemory = (struct GBAMemory*) memory;
275
276	switch (address & ~OFFSET_MASK) {
277	case BASE_WORKING_RAM:
278		gbaMemory->wram[(address & (SIZE_WORKING_RAM - 1)) >> 2] = value;
279		break;
280	case BASE_WORKING_IRAM:
281		gbaMemory->iwram[(address & (SIZE_WORKING_IRAM - 1)) >> 2] = value;
282		break;
283	case BASE_IO:
284		break;
285	case BASE_PALETTE_RAM:
286		break;
287	case BASE_VRAM:
288		break;
289	case BASE_OAM:
290		break;
291	case BASE_CART0:
292		break;
293	case BASE_CART2_EX:
294		break;
295	case BASE_CART_SRAM:
296		break;
297	default:
298		break;
299	}
300}
301
302void GBAStore16(struct ARMMemory* memory, uint32_t address, int16_t value) {
303	struct GBAMemory* gbaMemory = (struct GBAMemory*) memory;
304
305	switch (address & ~OFFSET_MASK) {
306	case BASE_WORKING_RAM:
307		((int16_t*) gbaMemory->wram)[(address & (SIZE_WORKING_RAM - 1)) >> 1] = value;
308		break;
309	case BASE_WORKING_IRAM:
310		((int16_t*) gbaMemory->iwram)[(address & (SIZE_WORKING_IRAM - 1)) >> 1] = value;
311		break;
312	case BASE_IO:
313		GBAIOWrite(gbaMemory->p, address & (SIZE_IO - 1), value);
314		break;
315	case BASE_PALETTE_RAM:
316		break;
317	case BASE_VRAM:
318		break;
319	case BASE_OAM:
320		break;
321	case BASE_CART0:
322		break;
323	case BASE_CART2_EX:
324		break;
325	case BASE_CART_SRAM:
326		break;
327	default:
328		break;
329	}
330}
331
332void GBAStore8(struct ARMMemory* memory, uint32_t address, int8_t value) {
333	struct GBAMemory* gbaMemory = (struct GBAMemory*) memory;
334
335	switch (address & ~OFFSET_MASK) {
336	case BASE_WORKING_RAM:
337		((int8_t*) gbaMemory->wram)[address & (SIZE_WORKING_RAM - 1)] = value;
338		break;
339	case BASE_WORKING_IRAM:
340		((int8_t*) gbaMemory->iwram)[address & (SIZE_WORKING_IRAM - 1)] = value;
341		break;
342	case BASE_IO:
343		break;
344	case BASE_PALETTE_RAM:
345		break;
346	case BASE_VRAM:
347		break;
348	case BASE_OAM:
349		break;
350	case BASE_CART0:
351		break;
352	case BASE_CART2_EX:
353		break;
354	case BASE_CART_SRAM:
355		break;
356	default:
357		break;
358	}
359}
360
361void GBAAdjustWaitstates(struct GBAMemory* memory, uint16_t parameters) {
362	int sram = parameters & 0x0003;
363	int ws0 = (parameters & 0x000C) >> 2;
364	int ws0seq = (parameters & 0x0010) >> 4;
365	int ws1 = (parameters & 0x0060) >> 5;
366	int ws1seq = (parameters & 0x0080) >> 7;
367	int ws2 = (parameters & 0x0300) >> 8;
368	int ws2seq = (parameters & 0x0400) >> 10;
369	int prefetch = parameters & 0x4000;
370
371	memory->waitstates16[REGION_CART_SRAM] =  GBA_ROM_WAITSTATES[sram];
372	memory->waitstatesSeq16[REGION_CART_SRAM] = GBA_ROM_WAITSTATES[sram];
373	memory->waitstates32[REGION_CART_SRAM] = 2 * GBA_ROM_WAITSTATES[sram] + 1;
374	memory->waitstatesSeq32[REGION_CART_SRAM] = 2 * GBA_ROM_WAITSTATES[sram] + 1;
375
376	memory->waitstates16[REGION_CART0] = memory->waitstates16[REGION_CART0_EX] = GBA_ROM_WAITSTATES[ws0];
377	memory->waitstates16[REGION_CART1] = memory->waitstates16[REGION_CART1_EX] = GBA_ROM_WAITSTATES[ws1];
378	memory->waitstates16[REGION_CART2] = memory->waitstates16[REGION_CART2_EX] = GBA_ROM_WAITSTATES[ws2];
379
380	memory->waitstatesSeq16[REGION_CART0] = memory->waitstatesSeq16[REGION_CART0_EX] = GBA_ROM_WAITSTATES_SEQ[ws0seq];
381	memory->waitstatesSeq16[REGION_CART1] = memory->waitstatesSeq16[REGION_CART1_EX] = GBA_ROM_WAITSTATES_SEQ[ws1seq + 2];
382	memory->waitstatesSeq16[REGION_CART2] = memory->waitstatesSeq16[REGION_CART2_EX] = GBA_ROM_WAITSTATES_SEQ[ws2seq + 4];
383
384	memory->waitstates32[REGION_CART0] = memory->waitstates32[REGION_CART0_EX] = memory->waitstates16[REGION_CART0] + 1 + memory->waitstatesSeq16[REGION_CART0];
385	memory->waitstates32[REGION_CART1] = memory->waitstates32[REGION_CART1_EX] = memory->waitstates16[REGION_CART1] + 1 + memory->waitstatesSeq16[REGION_CART1];
386	memory->waitstates32[REGION_CART2] = memory->waitstates32[REGION_CART2_EX] = memory->waitstates16[REGION_CART2] + 1 + memory->waitstatesSeq16[REGION_CART2];
387
388	memory->waitstatesSeq32[REGION_CART0] = memory->waitstatesSeq32[REGION_CART0 + 1] = 2 * memory->waitstatesSeq16[REGION_CART0] + 1;
389	memory->waitstatesSeq32[REGION_CART1] = memory->waitstatesSeq32[REGION_CART1 + 1] = 2 * memory->waitstatesSeq16[REGION_CART1] + 1;
390	memory->waitstatesSeq32[REGION_CART2] = memory->waitstatesSeq32[REGION_CART2 + 1] = 2 * memory->waitstatesSeq16[REGION_CART2] + 1;
391
392	memory->d.activePrefetchCycles32 = memory->waitstates32[memory->activeRegion];
393	memory->d.activePrefetchCycles16 = memory->waitstates16[memory->activeRegion];
394}