all repos — mgba @ 270c09c26e2b37c180fb60ceba094488230e12fd

mGBA Game Boy Advance Emulator

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

  1#include "gba-memory.h"
  2
  3#include "gba-gpio.h"
  4#include "gba-io.h"
  5#include "gba-serialize.h"
  6#include "hle-bios.h"
  7#include "util/memory.h"
  8
  9static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t region);
 10static int GBAWaitMultiple(struct ARMCore* cpu, uint32_t startAddress, int count);
 11static void GBAMemoryServiceDMA(struct GBA* gba, int number, struct GBADMA* info);
 12
 13static const char GBA_BASE_WAITSTATES[16] = { 0, 0, 2, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4 };
 14static const char GBA_BASE_WAITSTATES_32[16] = { 0, 0, 5, 0, 0, 0, 0, 0, 7, 7, 9, 9, 13, 13, 9 };
 15static const char GBA_BASE_WAITSTATES_SEQ[16] = { 0, 0, 2, 0, 0, 0, 0, 0, 2, 2, 4, 4, 8, 8, 4 };
 16static const char GBA_BASE_WAITSTATES_SEQ_32[16] = { 0, 0, 5, 0, 0, 0, 0, 0, 5, 5, 9, 9, 17, 17, 9 };
 17static const char GBA_ROM_WAITSTATES[] = { 4, 3, 2, 8 };
 18static const char GBA_ROM_WAITSTATES_SEQ[] = { 2, 1, 4, 1, 8, 1 };
 19static const int DMA_OFFSET[] = { 1, -1, 0, 1 };
 20
 21void GBAMemoryInit(struct GBA* gba) {
 22	struct ARMCore* cpu = gba->cpu;
 23	cpu->memory.load32 = GBALoad32;
 24	cpu->memory.load16 = GBALoad16;
 25	cpu->memory.loadU16 = GBALoadU16;
 26	cpu->memory.load8 = GBALoad8;
 27	cpu->memory.loadU8 = GBALoadU8;
 28	cpu->memory.store32 = GBAStore32;
 29	cpu->memory.store16 = GBAStore16;
 30	cpu->memory.store8 = GBAStore8;
 31
 32	gba->memory.bios = (uint32_t*) hleBios;
 33	gba->memory.fullBios = 0;
 34	gba->memory.wram = 0;
 35	gba->memory.iwram = 0;
 36	gba->memory.rom = 0;
 37	gba->memory.gpio.p = gba;
 38
 39	int i;
 40	for (i = 0; i < 16; ++i) {
 41		gba->memory.waitstatesNonseq16[i] = GBA_BASE_WAITSTATES[i];
 42		gba->memory.waitstatesSeq16[i] = GBA_BASE_WAITSTATES_SEQ[i];
 43		gba->memory.waitstatesPrefetchNonseq16[i] = GBA_BASE_WAITSTATES[i];
 44		gba->memory.waitstatesPrefetchSeq16[i] = GBA_BASE_WAITSTATES_SEQ[i];
 45		gba->memory.waitstatesNonseq32[i] = GBA_BASE_WAITSTATES_32[i];
 46		gba->memory.waitstatesSeq32[i] = GBA_BASE_WAITSTATES_SEQ_32[i];
 47		gba->memory.waitstatesPrefetchNonseq32[i] = GBA_BASE_WAITSTATES_32[i];
 48		gba->memory.waitstatesPrefetchSeq32[i] = GBA_BASE_WAITSTATES_SEQ_32[i];
 49	}
 50	for (; i < 256; ++i) {
 51		gba->memory.waitstatesNonseq16[i] = 0;
 52		gba->memory.waitstatesSeq16[i] = 0;
 53		gba->memory.waitstatesNonseq32[i] = 0;
 54		gba->memory.waitstatesSeq32[i] = 0;
 55	}
 56
 57	gba->memory.activeRegion = -1;
 58	cpu->memory.activeRegion = 0;
 59	cpu->memory.activeMask = 0;
 60	cpu->memory.setActiveRegion = GBASetActiveRegion;
 61	cpu->memory.activeSeqCycles32 = 0;
 62	cpu->memory.activeSeqCycles16 = 0;
 63	cpu->memory.activeNonseqCycles32 = 0;
 64	cpu->memory.activeNonseqCycles16 = 0;
 65	cpu->memory.activeUncachedCycles32 = 0;
 66	cpu->memory.activeUncachedCycles16 = 0;
 67	gba->memory.biosPrefetch = 0;
 68	cpu->memory.waitMultiple = GBAWaitMultiple;
 69}
 70
 71void GBAMemoryDeinit(struct GBA* gba) {
 72	mappedMemoryFree(gba->memory.wram, SIZE_WORKING_RAM);
 73	mappedMemoryFree(gba->memory.iwram, SIZE_WORKING_IRAM);
 74	if (gba->memory.rom) {
 75		mappedMemoryFree(gba->memory.rom, gba->memory.romSize);
 76	}
 77	GBASavedataDeinit(&gba->memory.savedata);
 78}
 79
 80void GBAMemoryReset(struct GBA* gba) {
 81	if (gba->memory.wram) {
 82		mappedMemoryFree(gba->memory.wram, SIZE_WORKING_RAM);
 83	}
 84	gba->memory.wram = anonymousMemoryMap(SIZE_WORKING_RAM);
 85
 86	if (gba->memory.iwram) {
 87		mappedMemoryFree(gba->memory.iwram, SIZE_WORKING_IRAM);
 88	}
 89	gba->memory.iwram = anonymousMemoryMap(SIZE_WORKING_IRAM);
 90
 91	memset(gba->memory.io, 0, sizeof(gba->memory.io));
 92	memset(gba->memory.dma, 0, sizeof(gba->memory.dma));
 93	int i;
 94	for (i = 0; i < 4; ++i) {
 95		gba->memory.dma[i].count = 0x10000;
 96		gba->memory.dma[i].nextEvent = INT_MAX;
 97	}
 98	gba->memory.activeDMA = -1;
 99	gba->memory.nextDMA = INT_MAX;
100	gba->memory.eventDiff = 0;
101
102	if (!gba->memory.wram || !gba->memory.iwram) {
103		GBAMemoryDeinit(gba);
104		GBALog(gba, GBA_LOG_FATAL, "Could not map memory");
105	}
106}
107
108static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) {
109	struct GBA* gba = (struct GBA*) cpu->master;
110	struct GBAMemory* memory = &gba->memory;
111
112	if (address == gba->busyLoop && memory->activeRegion != REGION_BIOS) {
113		GBAHalt(gba);
114	}
115
116	int newRegion = address >> BASE_OFFSET;
117	if (newRegion == memory->activeRegion) {
118		return;
119	}
120	if (memory->activeRegion == REGION_BIOS) {
121		memory->biosPrefetch = cpu->prefetch;
122	}
123	memory->activeRegion = newRegion;
124	switch (address & ~OFFSET_MASK) {
125	case BASE_BIOS:
126		cpu->memory.activeRegion = memory->bios;
127		cpu->memory.activeMask = SIZE_BIOS - 1;
128		break;
129	case BASE_WORKING_RAM:
130		cpu->memory.activeRegion = memory->wram;
131		cpu->memory.activeMask = SIZE_WORKING_RAM - 1;
132		break;
133	case BASE_WORKING_IRAM:
134		cpu->memory.activeRegion = memory->iwram;
135		cpu->memory.activeMask = SIZE_WORKING_IRAM - 1;
136		break;
137	case BASE_CART0:
138	case BASE_CART0_EX:
139	case BASE_CART1:
140	case BASE_CART1_EX:
141	case BASE_CART2:
142	case BASE_CART2_EX:
143		cpu->memory.activeRegion = memory->rom;
144		cpu->memory.activeMask = SIZE_CART0 - 1;
145		break;
146	default:
147		cpu->memory.activeRegion = 0;
148		cpu->memory.activeMask = 0;
149		GBALog(gba, GBA_LOG_FATAL, "Jumped to invalid address");
150		break;
151	}
152	cpu->memory.activeSeqCycles32 = memory->waitstatesPrefetchSeq32[memory->activeRegion];
153	cpu->memory.activeSeqCycles16 = memory->waitstatesPrefetchSeq16[memory->activeRegion];
154	cpu->memory.activeNonseqCycles32 = memory->waitstatesPrefetchNonseq32[memory->activeRegion];
155	cpu->memory.activeNonseqCycles16 = memory->waitstatesPrefetchNonseq16[memory->activeRegion];
156	cpu->memory.activeUncachedCycles32 = memory->waitstatesNonseq32[memory->activeRegion];
157	cpu->memory.activeUncachedCycles16 = memory->waitstatesNonseq16[memory->activeRegion];
158}
159
160int32_t GBALoad32(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
161	struct GBA* gba = (struct GBA*) cpu->master;
162	struct GBAMemory* memory = &gba->memory;
163	uint32_t value = 0;
164	int wait = 0;
165
166	switch (address >> BASE_OFFSET) {
167	case REGION_BIOS:
168		if (memory->activeRegion == REGION_BIOS) {
169			if (address < SIZE_BIOS) {
170				LOAD_32(value, address, memory->bios);
171			} else {
172				value = 0;
173			}
174		} else {
175			value = memory->biosPrefetch;
176		}
177		break;
178	case REGION_WORKING_RAM:
179		LOAD_32(value, address & (SIZE_WORKING_RAM - 1), memory->wram);
180		wait = memory->waitstatesNonseq32[REGION_WORKING_RAM];
181		break;
182	case REGION_WORKING_IRAM:
183		LOAD_32(value, address & (SIZE_WORKING_IRAM - 1), memory->iwram);
184		break;
185	case REGION_IO:
186		value = GBAIORead(gba, (address & (SIZE_IO - 1)) & ~2) | (GBAIORead(gba, (address & (SIZE_IO - 1)) | 2) << 16);
187		break;
188	case REGION_PALETTE_RAM:
189		LOAD_32(value, address & (SIZE_PALETTE_RAM - 1), gba->video.palette);
190		break;
191	case REGION_VRAM:
192		LOAD_32(value, address & 0x0001FFFF, gba->video.renderer->vram);
193		break;
194	case REGION_OAM:
195		LOAD_32(value, address & (SIZE_OAM - 1), gba->video.oam.raw);
196		break;
197	case REGION_CART0:
198	case REGION_CART0_EX:
199	case REGION_CART1:
200	case REGION_CART1_EX:
201	case REGION_CART2:
202	case REGION_CART2_EX:
203		wait = memory->waitstatesNonseq32[address >> BASE_OFFSET];
204		if ((address & (SIZE_CART0 - 1)) < memory->romSize) {
205			LOAD_32(value, address & (SIZE_CART0 - 1), memory->rom);
206		}
207		break;
208	case REGION_CART_SRAM:
209	case REGION_CART_SRAM_MIRROR:
210		GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Load32: 0x%08X", address);
211		break;
212	default:
213		GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load32: 0x%08X", address);
214		value = cpu->prefetch;
215		if (cpu->executionMode == MODE_THUMB) {
216			value |= value << 16;
217		}
218		break;
219	}
220
221	if (cycleCounter) {
222		*cycleCounter += 2 + wait;
223	}
224	// Unaligned 32-bit loads are "rotated" so they make some semblance of sense
225	int rotate = (address & 3) << 3;
226	return (value >> rotate) | (value << (32 - rotate));
227}
228
229uint16_t GBALoadU16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
230	return GBALoad16(cpu, address, cycleCounter);
231}
232
233int16_t GBALoad16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
234	struct GBA* gba = (struct GBA*) cpu->master;
235	struct GBAMemory* memory = &gba->memory;
236	uint16_t value = 0;
237	int wait = 0;
238
239	switch (address >> BASE_OFFSET) {
240	case REGION_BIOS:
241		if (memory->activeRegion == REGION_BIOS) {
242			if (address < SIZE_BIOS) {
243				LOAD_16(value, address, memory->bios);
244			} else {
245				value = 0;
246			}
247		} else {
248			value = memory->biosPrefetch;
249		}
250		break;
251	case REGION_WORKING_RAM:
252		LOAD_16(value, address & (SIZE_WORKING_RAM - 1), memory->wram);
253		wait = memory->waitstatesNonseq16[REGION_WORKING_RAM];
254		break;
255	case REGION_WORKING_IRAM:
256		LOAD_16(value, address & (SIZE_WORKING_IRAM - 1), memory->iwram);
257		break;
258	case REGION_IO:
259		value = GBAIORead(gba, address & (SIZE_IO - 1));
260		break;
261	case REGION_PALETTE_RAM:
262		LOAD_16(value, address & (SIZE_PALETTE_RAM - 1), gba->video.palette);
263		break;
264	case REGION_VRAM:
265		LOAD_16(value, address & 0x0001FFFF, gba->video.renderer->vram);
266		break;
267	case REGION_OAM:
268		LOAD_16(value, address & (SIZE_OAM - 1), gba->video.oam.raw);
269		break;
270	case REGION_CART0:
271	case REGION_CART0_EX:
272	case REGION_CART1:
273	case REGION_CART1_EX:
274	case REGION_CART2:
275		wait = memory->waitstatesNonseq16[address >> BASE_OFFSET];
276		if ((address & (SIZE_CART0 - 1)) < memory->romSize) {
277			LOAD_16(value, address & (SIZE_CART0 - 1), memory->rom);
278		}
279		break;
280	case REGION_CART2_EX:
281		wait = memory->waitstatesNonseq16[address >> BASE_OFFSET];
282		if (memory->savedata.type == SAVEDATA_EEPROM) {
283			value = GBASavedataReadEEPROM(&memory->savedata);
284		} else if ((address & (SIZE_CART0 - 1)) < memory->romSize) {
285			LOAD_16(value, address & (SIZE_CART0 - 1), memory->rom);
286		}
287		break;
288	case REGION_CART_SRAM:
289	case REGION_CART_SRAM_MIRROR:
290		GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Load16: 0x%08X", address);
291		break;
292	default:
293		GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load16: 0x%08X", address);
294		value = cpu->prefetch;
295		break;
296	}
297
298	if (cycleCounter) {
299		*cycleCounter += 2 + wait;
300	}
301	// Unaligned 16-bit loads are "unpredictable", but the GBA rotates them, so we have to, too.
302	int rotate = (address & 1) << 3;
303	return (value >> rotate) | (value << (16 - rotate));
304}
305
306uint8_t GBALoadU8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
307	return GBALoad8(cpu, address, cycleCounter);
308}
309
310int8_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
311	struct GBA* gba = (struct GBA*) cpu->master;
312	struct GBAMemory* memory = &gba->memory;
313	int8_t value = 0;
314	int wait = 0;
315
316	switch (address >> BASE_OFFSET) {
317	case REGION_BIOS:
318		if (memory->activeRegion == REGION_BIOS) {
319			if (address < SIZE_BIOS) {
320				value = ((int8_t*) memory->bios)[address];
321			} else {
322				value = 0;
323			}
324		} else {
325			value = memory->biosPrefetch;
326		}
327		break;
328	case REGION_WORKING_RAM:
329		value = ((int8_t*) memory->wram)[address & (SIZE_WORKING_RAM - 1)];
330		wait = memory->waitstatesNonseq16[REGION_WORKING_RAM];
331		break;
332	case REGION_WORKING_IRAM:
333		value = ((int8_t*) memory->iwram)[address & (SIZE_WORKING_IRAM - 1)];
334		break;
335	case REGION_IO:
336		value = (GBAIORead(gba, address & 0xFFFE) >> ((address & 0x0001) << 3)) & 0xFF;
337		break;
338	case REGION_PALETTE_RAM:
339		value = ((int8_t*) gba->video.palette)[address & (SIZE_PALETTE_RAM - 1)];
340		break;
341	case REGION_VRAM:
342		value = ((int8_t*) gba->video.renderer->vram)[address & 0x0001FFFF];
343		break;
344	case REGION_OAM:
345		GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Load8: 0x%08X", address);
346		break;
347	case REGION_CART0:
348	case REGION_CART0_EX:
349	case REGION_CART1:
350	case REGION_CART1_EX:
351	case REGION_CART2:
352	case REGION_CART2_EX:
353		wait = memory->waitstatesNonseq16[address >> BASE_OFFSET];
354		if ((address & (SIZE_CART0 - 1)) < memory->romSize) {
355			value = ((int8_t*) memory->rom)[address & (SIZE_CART0 - 1)];
356		}
357		break;
358	case REGION_CART_SRAM:
359	case REGION_CART_SRAM_MIRROR:
360		wait = memory->waitstatesNonseq16[address >> BASE_OFFSET];
361		if (memory->savedata.type == SAVEDATA_NONE) {
362			GBASavedataInitSRAM(&memory->savedata);
363		}
364		if (memory->savedata.type == SAVEDATA_SRAM) {
365			value = memory->savedata.data[address & (SIZE_CART_SRAM - 1)];
366		} else if (memory->savedata.type == SAVEDATA_FLASH512 || memory->savedata.type == SAVEDATA_FLASH1M) {
367			value = GBASavedataReadFlash(&memory->savedata, address);
368		}
369		break;
370	default:
371		GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load8: 0x%08x", address);
372		value = cpu->prefetch & 0xFF;
373		break;
374	}
375
376	if (cycleCounter) {
377		*cycleCounter += 2 + wait;
378	}
379	return value;
380}
381
382void GBAStore32(struct ARMCore* cpu, uint32_t address, int32_t value, int* cycleCounter) {
383	struct GBA* gba = (struct GBA*) cpu->master;
384	struct GBAMemory* memory = &gba->memory;
385	int wait = 0;
386
387	switch (address >> BASE_OFFSET) {
388	case REGION_WORKING_RAM:
389		STORE_32(value, address & (SIZE_WORKING_RAM - 1), memory->wram);
390		wait = memory->waitstatesNonseq32[REGION_WORKING_RAM];
391		break;
392	case REGION_WORKING_IRAM:
393		STORE_32(value, address & (SIZE_WORKING_IRAM - 1), memory->iwram);
394		break;
395	case REGION_IO:
396		GBAIOWrite32(gba, address & (SIZE_IO - 1), value);
397		break;
398	case REGION_PALETTE_RAM:
399		STORE_32(value, address & (SIZE_PALETTE_RAM - 1), gba->video.palette);
400		gba->video.renderer->writePalette(gba->video.renderer, (address & (SIZE_PALETTE_RAM - 1)) + 2, value >> 16);
401		gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 1), value);
402		break;
403	case REGION_VRAM:
404		if ((address & OFFSET_MASK) < SIZE_VRAM) {
405			STORE_32(value, address & 0x0001FFFF, gba->video.renderer->vram);
406		} else if ((address & OFFSET_MASK) < 0x00020000) {
407			STORE_32(value, address & 0x00017FFF, gba->video.renderer->vram);
408		}
409		break;
410	case REGION_OAM:
411		STORE_32(value, address & (SIZE_OAM - 1), gba->video.oam.raw);
412		gba->video.renderer->writeOAM(gba->video.renderer, (address & (SIZE_OAM - 4)) >> 1);
413		gba->video.renderer->writeOAM(gba->video.renderer, ((address & (SIZE_OAM - 4)) >> 1) + 1);
414		break;
415	case REGION_CART0:
416		GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Store32: 0x%08X", address);
417		break;
418	case REGION_CART_SRAM:
419	case REGION_CART_SRAM_MIRROR:
420		GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Store32: 0x%08X", address);
421		break;
422	default:
423		GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Store32: 0x%08X", address);
424		break;
425	}
426
427	if (cycleCounter) {
428		*cycleCounter += 1 + wait;
429	}
430}
431
432void GBAStore16(struct ARMCore* cpu, uint32_t address, int16_t value, int* cycleCounter) {
433	struct GBA* gba = (struct GBA*) cpu->master;
434	struct GBAMemory* memory = &gba->memory;
435	int wait = 0;
436
437	switch (address >> BASE_OFFSET) {
438	case REGION_WORKING_RAM:
439		STORE_16(value, address & (SIZE_WORKING_RAM - 1), memory->wram);
440		wait = memory->waitstatesNonseq16[REGION_WORKING_RAM];
441		break;
442	case REGION_WORKING_IRAM:
443		STORE_16(value, address & (SIZE_WORKING_IRAM - 1), memory->iwram);
444		break;
445	case REGION_IO:
446		GBAIOWrite(gba, address & (SIZE_IO - 1), value);
447		break;
448	case REGION_PALETTE_RAM:
449		STORE_16(value, address & (SIZE_PALETTE_RAM - 1), gba->video.palette);
450		gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 1), value);
451		break;
452	case REGION_VRAM:
453		if ((address & OFFSET_MASK) < SIZE_VRAM) {
454			STORE_16(value, address & 0x0001FFFF, gba->video.renderer->vram);
455		} else if ((address & OFFSET_MASK) < 0x00020000) {
456			STORE_16(value, address & 0x00017FFF, gba->video.renderer->vram);
457		}
458		break;
459	case REGION_OAM:
460		STORE_16(value, address & (SIZE_OAM - 1), gba->video.oam.raw);
461		gba->video.renderer->writeOAM(gba->video.renderer, (address & (SIZE_OAM - 1)) >> 1);
462		break;
463	case REGION_CART0:
464		if (IS_GPIO_REGISTER(address & 0xFFFFFF)) {
465			uint32_t reg = address & 0xFFFFFF;
466			GBAGPIOWrite(&memory->gpio, reg, value);
467		} else {
468			GBALog(gba, GBA_LOG_GAME_ERROR, "Bad cartridge Store16: 0x%08X", address);
469		}
470		break;
471	case REGION_CART2_EX:
472		if (memory->savedata.type == SAVEDATA_NONE) {
473			GBASavedataInitEEPROM(&memory->savedata);
474		}
475		GBASavedataWriteEEPROM(&memory->savedata, value, 1);
476		break;
477	case REGION_CART_SRAM:
478	case REGION_CART_SRAM_MIRROR:
479		GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Store16: 0x%08X", address);
480		break;
481	default:
482		GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Store16: 0x%08X", address);
483		break;
484	}
485
486	if (cycleCounter) {
487		*cycleCounter += 1 + wait;
488	}
489}
490
491void GBAStore8(struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCounter) {
492	struct GBA* gba = (struct GBA*) cpu->master;
493	struct GBAMemory* memory = &gba->memory;
494	int wait = 0;
495
496	switch (address >> BASE_OFFSET) {
497	case REGION_WORKING_RAM:
498		((int8_t*) memory->wram)[address & (SIZE_WORKING_RAM - 1)] = value;
499		wait = memory->waitstatesNonseq16[REGION_WORKING_RAM];
500		break;
501	case REGION_WORKING_IRAM:
502		((int8_t*) memory->iwram)[address & (SIZE_WORKING_IRAM - 1)] = value;
503		break;
504	case REGION_IO:
505		GBAIOWrite8(gba, address & (SIZE_IO - 1), value);
506		break;
507	case REGION_PALETTE_RAM:
508		GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Store8: 0x%08X", address);
509		break;
510	case REGION_VRAM:
511		if (address >= 0x06018000) {
512			// TODO: check BG mode
513			GBALog(gba, GBA_LOG_GAME_ERROR, "Cannot Store8 to OBJ: 0x%08X", address);
514			break;
515		}
516		((int8_t*) gba->video.renderer->vram)[address & 0x1FFFE] = value;
517		((int8_t*) gba->video.renderer->vram)[(address & 0x1FFFE) | 1] = value;
518		break;
519	case REGION_OAM:
520		GBALog(gba, GBA_LOG_GAME_ERROR, "Cannot Store8 to OAM: 0x%08X", address);
521		break;
522	case REGION_CART0:
523		GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Store8: 0x%08X", address);
524		break;
525	case REGION_CART_SRAM:
526	case REGION_CART_SRAM_MIRROR:
527		if (memory->savedata.type == SAVEDATA_NONE) {
528			if (address == SAVEDATA_FLASH_BASE) {
529				GBASavedataInitFlash(&memory->savedata);
530			} else {
531				GBASavedataInitSRAM(&memory->savedata);
532			}
533		}
534		if (memory->savedata.type == SAVEDATA_FLASH512 || memory->savedata.type == SAVEDATA_FLASH1M) {
535			GBASavedataWriteFlash(&memory->savedata, address, value);
536		} else if (memory->savedata.type == SAVEDATA_SRAM) {
537			memory->savedata.data[address & (SIZE_CART_SRAM - 1)] = value;
538		}
539		wait = memory->waitstatesNonseq16[REGION_CART_SRAM];
540		break;
541	default:
542		GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Store8: 0x%08X", address);
543		break;
544	}
545
546	if (cycleCounter) {
547		*cycleCounter += 1 + wait;
548	}
549}
550
551static int GBAWaitMultiple(struct ARMCore* cpu, uint32_t startAddress, int count) {
552	struct GBA* gba = (struct GBA*) cpu->master;
553	struct GBAMemory* memory = &gba->memory;
554	int wait = 1 + memory->waitstatesNonseq32[startAddress >> BASE_OFFSET];
555	wait += (1 + memory->waitstatesSeq32[startAddress >> BASE_OFFSET]) * (count - 1);
556	return wait;
557}
558
559void GBAAdjustWaitstates(struct GBA* gba, uint16_t parameters) {
560	struct GBAMemory* memory = &gba->memory;
561	struct ARMCore* cpu = gba->cpu;
562	int sram = parameters & 0x0003;
563	int ws0 = (parameters & 0x000C) >> 2;
564	int ws0seq = (parameters & 0x0010) >> 4;
565	int ws1 = (parameters & 0x0060) >> 5;
566	int ws1seq = (parameters & 0x0080) >> 7;
567	int ws2 = (parameters & 0x0300) >> 8;
568	int ws2seq = (parameters & 0x0400) >> 10;
569	int prefetch = parameters & 0x4000;
570
571	memory->waitstatesNonseq16[REGION_CART_SRAM] = memory->waitstatesNonseq16[REGION_CART_SRAM_MIRROR] =  GBA_ROM_WAITSTATES[sram];
572	memory->waitstatesSeq16[REGION_CART_SRAM] = memory->waitstatesSeq16[REGION_CART_SRAM_MIRROR] = GBA_ROM_WAITSTATES[sram];
573	memory->waitstatesNonseq32[REGION_CART_SRAM] = memory->waitstatesNonseq32[REGION_CART_SRAM_MIRROR] = 2 * GBA_ROM_WAITSTATES[sram] + 1;
574	memory->waitstatesSeq32[REGION_CART_SRAM] = memory->waitstatesSeq32[REGION_CART_SRAM_MIRROR] = 2 * GBA_ROM_WAITSTATES[sram] + 1;
575
576	memory->waitstatesNonseq16[REGION_CART0] = memory->waitstatesNonseq16[REGION_CART0_EX] = GBA_ROM_WAITSTATES[ws0];
577	memory->waitstatesNonseq16[REGION_CART1] = memory->waitstatesNonseq16[REGION_CART1_EX] = GBA_ROM_WAITSTATES[ws1];
578	memory->waitstatesNonseq16[REGION_CART2] = memory->waitstatesNonseq16[REGION_CART2_EX] = GBA_ROM_WAITSTATES[ws2];
579
580	memory->waitstatesSeq16[REGION_CART0] = memory->waitstatesSeq16[REGION_CART0_EX] = GBA_ROM_WAITSTATES_SEQ[ws0seq];
581	memory->waitstatesSeq16[REGION_CART1] = memory->waitstatesSeq16[REGION_CART1_EX] = GBA_ROM_WAITSTATES_SEQ[ws1seq + 2];
582	memory->waitstatesSeq16[REGION_CART2] = memory->waitstatesSeq16[REGION_CART2_EX] = GBA_ROM_WAITSTATES_SEQ[ws2seq + 4];
583
584	memory->waitstatesNonseq32[REGION_CART0] = memory->waitstatesNonseq32[REGION_CART0_EX] = memory->waitstatesSeq16[REGION_CART0] + 1 + memory->waitstatesSeq16[REGION_CART0];
585	memory->waitstatesNonseq32[REGION_CART1] = memory->waitstatesNonseq32[REGION_CART1_EX] = memory->waitstatesSeq16[REGION_CART1] + 1 + memory->waitstatesSeq16[REGION_CART1];
586	memory->waitstatesNonseq32[REGION_CART2] = memory->waitstatesNonseq32[REGION_CART2_EX] = memory->waitstatesSeq16[REGION_CART2] + 1 + memory->waitstatesSeq16[REGION_CART2];
587
588	memory->waitstatesSeq32[REGION_CART0] = memory->waitstatesSeq32[REGION_CART0_EX] = 2 * memory->waitstatesSeq16[REGION_CART0] + 1;
589	memory->waitstatesSeq32[REGION_CART1] = memory->waitstatesSeq32[REGION_CART1_EX] = 2 * memory->waitstatesSeq16[REGION_CART1] + 1;
590	memory->waitstatesSeq32[REGION_CART2] = memory->waitstatesSeq32[REGION_CART2_EX] = 2 * memory->waitstatesSeq16[REGION_CART2] + 1;
591
592	if (!prefetch) {
593		memory->waitstatesPrefetchSeq16[REGION_CART0] = memory->waitstatesPrefetchSeq16[REGION_CART0_EX] = memory->waitstatesSeq16[REGION_CART0];
594		memory->waitstatesPrefetchSeq16[REGION_CART1] = memory->waitstatesPrefetchSeq16[REGION_CART1_EX] = memory->waitstatesSeq16[REGION_CART1];
595		memory->waitstatesPrefetchSeq16[REGION_CART2] = memory->waitstatesPrefetchSeq16[REGION_CART2_EX] = memory->waitstatesSeq16[REGION_CART2];
596
597		memory->waitstatesPrefetchSeq32[REGION_CART0] = memory->waitstatesPrefetchSeq32[REGION_CART0_EX] = memory->waitstatesSeq32[REGION_CART0];
598		memory->waitstatesPrefetchSeq32[REGION_CART1] = memory->waitstatesPrefetchSeq32[REGION_CART1_EX] = memory->waitstatesSeq32[REGION_CART1];
599		memory->waitstatesPrefetchSeq32[REGION_CART2] = memory->waitstatesPrefetchSeq32[REGION_CART2_EX] = memory->waitstatesSeq32[REGION_CART2];
600
601		memory->waitstatesPrefetchNonseq16[REGION_CART0] = memory->waitstatesPrefetchNonseq16[REGION_CART0_EX] = memory->waitstatesNonseq16[REGION_CART0];
602		memory->waitstatesPrefetchNonseq16[REGION_CART1] = memory->waitstatesPrefetchNonseq16[REGION_CART1_EX] = memory->waitstatesNonseq16[REGION_CART1];
603		memory->waitstatesPrefetchNonseq16[REGION_CART2] = memory->waitstatesPrefetchNonseq16[REGION_CART2_EX] = memory->waitstatesNonseq16[REGION_CART2];
604
605		memory->waitstatesPrefetchNonseq32[REGION_CART0] = memory->waitstatesPrefetchNonseq32[REGION_CART0_EX] = memory->waitstatesNonseq32[REGION_CART0];
606		memory->waitstatesPrefetchNonseq32[REGION_CART1] = memory->waitstatesPrefetchNonseq32[REGION_CART1_EX] = memory->waitstatesNonseq32[REGION_CART1];
607		memory->waitstatesPrefetchNonseq32[REGION_CART2] = memory->waitstatesPrefetchNonseq32[REGION_CART2_EX] = memory->waitstatesNonseq32[REGION_CART2];
608	} else {
609		memory->waitstatesPrefetchSeq16[REGION_CART0] = memory->waitstatesPrefetchSeq16[REGION_CART0_EX] = 0;
610		memory->waitstatesPrefetchSeq16[REGION_CART1] = memory->waitstatesPrefetchSeq16[REGION_CART1_EX] = 0;
611		memory->waitstatesPrefetchSeq16[REGION_CART2] = memory->waitstatesPrefetchSeq16[REGION_CART2_EX] = 0;
612
613		memory->waitstatesPrefetchSeq32[REGION_CART0] = memory->waitstatesPrefetchSeq32[REGION_CART0_EX] = 0;
614		memory->waitstatesPrefetchSeq32[REGION_CART1] = memory->waitstatesPrefetchSeq32[REGION_CART1_EX] = 0;
615		memory->waitstatesPrefetchSeq32[REGION_CART2] = memory->waitstatesPrefetchSeq32[REGION_CART2_EX] = 0;
616
617		memory->waitstatesPrefetchNonseq16[REGION_CART0] = memory->waitstatesPrefetchNonseq16[REGION_CART0_EX] = 0;
618		memory->waitstatesPrefetchNonseq16[REGION_CART1] = memory->waitstatesPrefetchNonseq16[REGION_CART1_EX] = 0;
619		memory->waitstatesPrefetchNonseq16[REGION_CART2] = memory->waitstatesPrefetchNonseq16[REGION_CART2_EX] = 0;
620
621		memory->waitstatesPrefetchNonseq32[REGION_CART0] = memory->waitstatesPrefetchNonseq32[REGION_CART0_EX] = 0;
622		memory->waitstatesPrefetchNonseq32[REGION_CART1] = memory->waitstatesPrefetchNonseq32[REGION_CART1_EX] = 0;
623		memory->waitstatesPrefetchNonseq32[REGION_CART2] = memory->waitstatesPrefetchNonseq32[REGION_CART2_EX] = 0;
624	}
625
626	cpu->memory.activeSeqCycles32 = memory->waitstatesPrefetchSeq32[memory->activeRegion];
627	cpu->memory.activeSeqCycles16 = memory->waitstatesPrefetchSeq16[memory->activeRegion];
628
629	cpu->memory.activeNonseqCycles32 = memory->waitstatesPrefetchNonseq32[memory->activeRegion];
630	cpu->memory.activeNonseqCycles16 = memory->waitstatesPrefetchNonseq16[memory->activeRegion];
631
632	cpu->memory.activeUncachedCycles32 = memory->waitstatesNonseq32[memory->activeRegion];
633	cpu->memory.activeUncachedCycles16 = memory->waitstatesNonseq16[memory->activeRegion];
634}
635
636void GBAMemoryWriteDMASAD(struct GBA* gba, int dma, uint32_t address) {
637	struct GBAMemory* memory = &gba->memory;
638	memory->dma[dma].source = address & 0xFFFFFFFE;
639}
640
641void GBAMemoryWriteDMADAD(struct GBA* gba, int dma, uint32_t address) {
642	struct GBAMemory* memory = &gba->memory;
643	memory->dma[dma].dest = address & 0xFFFFFFFE;
644}
645
646void GBAMemoryWriteDMACNT_LO(struct GBA* gba, int dma, uint16_t count) {
647	struct GBAMemory* memory = &gba->memory;
648	memory->dma[dma].count = count ? count : (dma == 3 ? 0x10000 : 0x4000);
649}
650
651uint16_t GBAMemoryWriteDMACNT_HI(struct GBA* gba, int dma, uint16_t control) {
652	struct GBAMemory* memory = &gba->memory;
653	struct GBADMA* currentDma = &memory->dma[dma];
654	int wasEnabled = currentDma->enable;
655	currentDma->packed = control;
656
657	if (currentDma->drq) {
658		GBALog(gba, GBA_LOG_STUB, "DRQ not implemented");
659	}
660
661	if (!wasEnabled && currentDma->enable) {
662		currentDma->nextSource = currentDma->source;
663		currentDma->nextDest = currentDma->dest;
664		currentDma->nextCount = currentDma->count;
665		GBAMemoryScheduleDMA(gba, dma, currentDma);
666	}
667	// If the DMA has already occurred, this value might have changed since the function started
668	return currentDma->packed;
669};
670
671void GBAMemoryScheduleDMA(struct GBA* gba, int number, struct GBADMA* info) {
672	struct ARMCore* cpu = gba->cpu;
673	switch (info->timing) {
674	case DMA_TIMING_NOW:
675		info->nextEvent = cpu->cycles;
676		GBAMemoryUpdateDMAs(gba, 0);
677		break;
678	case DMA_TIMING_HBLANK:
679		// Handled implicitly
680		info->nextEvent = INT_MAX;
681		break;
682	case DMA_TIMING_VBLANK:
683		// Handled implicitly
684		info->nextEvent = INT_MAX;
685		break;
686	case DMA_TIMING_CUSTOM:
687		info->nextEvent = INT_MAX;
688		switch (number) {
689		case 0:
690			GBALog(gba, GBA_LOG_WARN, "Discarding invalid DMA0 scheduling");
691			break;
692		case 1:
693		case 2:
694			GBAAudioScheduleFifoDma(&gba->audio, number, info);
695			break;
696		case 3:
697			// GBAVideoScheduleVCaptureDma(dma, info);
698			break;
699		}
700	}
701}
702
703void GBAMemoryRunHblankDMAs(struct GBA* gba, int32_t cycles) {
704	struct GBAMemory* memory = &gba->memory;
705	struct GBADMA* dma;
706	int i;
707	for (i = 0; i < 4; ++i) {
708		dma = &memory->dma[i];
709		if (dma->enable && dma->timing == DMA_TIMING_HBLANK) {
710			dma->nextEvent = cycles;
711		}
712	}
713	GBAMemoryUpdateDMAs(gba, 0);
714}
715
716void GBAMemoryRunVblankDMAs(struct GBA* gba, int32_t cycles) {
717	struct GBAMemory* memory = &gba->memory;
718	struct GBADMA* dma;
719	int i;
720	for (i = 0; i < 4; ++i) {
721		dma = &memory->dma[i];
722		if (dma->enable && dma->timing == DMA_TIMING_VBLANK) {
723			dma->nextEvent = cycles;
724		}
725	}
726	GBAMemoryUpdateDMAs(gba, 0);
727}
728
729int32_t GBAMemoryRunDMAs(struct GBA* gba, int32_t cycles) {
730	struct GBAMemory* memory = &gba->memory;
731	if (memory->nextDMA == INT_MAX) {
732		return INT_MAX;
733	}
734	memory->nextDMA -= cycles;
735	memory->eventDiff += cycles;
736	if (memory->nextDMA <= 0) {
737		struct GBADMA* dma = &memory->dma[memory->activeDMA];
738		GBAMemoryServiceDMA(gba, memory->activeDMA, dma);
739		GBAMemoryUpdateDMAs(gba, memory->eventDiff);
740		memory->eventDiff = 0;
741	}
742	return memory->nextDMA;
743}
744
745void GBAMemoryUpdateDMAs(struct GBA* gba, int32_t cycles) {
746	int i;
747	struct GBAMemory* memory = &gba->memory;
748	struct ARMCore* cpu = gba->cpu;
749	memory->activeDMA = -1;
750	memory->nextDMA = INT_MAX;
751	for (i = 3; i >= 0; --i) {
752		struct GBADMA* dma = &memory->dma[i];
753		if (dma->nextEvent != INT_MAX) {
754			dma->nextEvent -= cycles;
755			if (dma->enable) {
756				memory->activeDMA = i;
757				memory->nextDMA = dma->nextEvent;
758			}
759		}
760	}
761	if (memory->nextDMA < cpu->nextEvent) {
762		cpu->nextEvent = memory->nextDMA;
763	}
764}
765
766void GBAMemoryServiceDMA(struct GBA* gba, int number, struct GBADMA* info) {
767	struct GBAMemory* memory = &gba->memory;
768	struct ARMCore* cpu = gba->cpu;
769	uint32_t width = info->width ? 4 : 2;
770	int sourceOffset = DMA_OFFSET[info->srcControl] * width;
771	int destOffset = DMA_OFFSET[info->dstControl] * width;
772	int32_t wordsRemaining = info->nextCount;
773	uint32_t source = info->nextSource;
774	uint32_t dest = info->nextDest;
775	uint32_t sourceRegion = source >> BASE_OFFSET;
776	uint32_t destRegion = dest >> BASE_OFFSET;
777	int32_t cycles = 0;
778
779	if (source == info->source) {
780		// TODO: support 4 cycles for ROM access
781		cycles += 2;
782		if (width == 4) {
783			cycles += memory->waitstatesNonseq32[sourceRegion] + memory->waitstatesNonseq32[destRegion];
784			source &= 0xFFFFFFFC;
785			dest &= 0xFFFFFFFC;
786		} else {
787			cycles += memory->waitstatesNonseq16[sourceRegion] + memory->waitstatesNonseq16[destRegion];
788		}
789	} else {
790		if (width == 4) {
791			cycles += memory->waitstatesSeq32[sourceRegion] + memory->waitstatesSeq32[destRegion];
792		} else {
793			cycles += memory->waitstatesSeq16[sourceRegion] + memory->waitstatesSeq16[destRegion];
794		}
795	}
796
797	if (width == 4) {
798		int32_t word;
799		word = cpu->memory.load32(cpu, source, 0);
800		cpu->memory.store32(cpu, dest, word, 0);
801		source += sourceOffset;
802		dest += destOffset;
803		--wordsRemaining;
804	} else {
805		uint16_t word;
806		if (sourceRegion == REGION_CART2_EX && memory->savedata.type == SAVEDATA_EEPROM) {
807			word = GBASavedataReadEEPROM(&memory->savedata);
808			cpu->memory.store16(cpu, dest, word, 0);
809			source += sourceOffset;
810			dest += destOffset;
811			--wordsRemaining;
812		} else if (destRegion == REGION_CART2_EX) {
813			if (memory->savedata.type == SAVEDATA_NONE) {
814				GBASavedataInitEEPROM(&memory->savedata);
815			}
816			word = cpu->memory.load16(cpu, source, 0);
817			GBASavedataWriteEEPROM(&memory->savedata, word, wordsRemaining);
818			source += sourceOffset;
819			dest += destOffset;
820			--wordsRemaining;
821		} else {
822			word = cpu->memory.load16(cpu, source, 0);
823			cpu->memory.store16(cpu, dest, word, 0);
824			source += sourceOffset;
825			dest += destOffset;
826			--wordsRemaining;
827		}
828	}
829
830	if (!wordsRemaining) {
831		if (!info->repeat) {
832			info->enable = 0;
833			info->nextEvent = INT_MAX;
834
835			// Clear the enable bit in memory
836			memory->io[(REG_DMA0CNT_HI + number * (REG_DMA1CNT_HI - REG_DMA0CNT_HI)) >> 1] &= 0x7FE0;
837		} else {
838			info->nextCount = info->count;
839			if (info->dstControl == DMA_INCREMENT_RELOAD) {
840				info->nextDest = info->dest;
841			}
842			GBAMemoryScheduleDMA(gba, number, info);
843		}
844		if (info->doIrq) {
845			GBARaiseIRQ(gba, IRQ_DMA0 + number);
846		}
847	} else {
848		info->nextDest = dest;
849		info->nextCount = wordsRemaining;
850	}
851	info->nextSource = source;
852
853	int i;
854	for (i = 0; i < 4; ++i) {
855		if (memory->dma[i].nextEvent != INT_MAX) {
856			memory->dma[i].nextEvent += cycles;
857		}
858	}
859	cpu->cycles += cycles;
860}
861
862void GBAMemorySerialize(struct GBAMemory* memory, struct GBASerializedState* state) {
863	memcpy(state->wram, memory->wram, SIZE_WORKING_RAM);
864	memcpy(state->iwram, memory->iwram, SIZE_WORKING_IRAM);
865}
866
867void GBAMemoryDeserialize(struct GBAMemory* memory, struct GBASerializedState* state) {
868	memcpy(memory->wram, state->wram, SIZE_WORKING_RAM);
869	memcpy(memory->iwram, state->iwram, SIZE_WORKING_IRAM);
870}