all repos — mgba @ 5340cb300b36d245949b7c389f11865ff4e122c7

mGBA Game Boy Advance Emulator

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

   1#include "gba-memory.h"
   2
   3#include "macros.h"
   4
   5#include "gba-gpio.h"
   6#include "gba-io.h"
   7#include "gba-serialize.h"
   8#include "hle-bios.h"
   9#include "util/memory.h"
  10
  11static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t region);
  12static void GBAMemoryServiceDMA(struct GBA* gba, int number, struct GBADMA* info);
  13
  14static const char GBA_BASE_WAITSTATES[16] = { 0, 0, 2, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4 };
  15static const char GBA_BASE_WAITSTATES_32[16] = { 0, 0, 5, 0, 0, 0, 0, 0, 7, 7, 9, 9, 13, 13, 9 };
  16static const char GBA_BASE_WAITSTATES_SEQ[16] = { 0, 0, 2, 0, 0, 0, 0, 0, 2, 2, 4, 4, 8, 8, 4 };
  17static const char GBA_BASE_WAITSTATES_SEQ_32[16] = { 0, 0, 5, 0, 0, 0, 0, 0, 5, 5, 9, 9, 17, 17, 9 };
  18static const char GBA_ROM_WAITSTATES[] = { 4, 3, 2, 8 };
  19static const char GBA_ROM_WAITSTATES_SEQ[] = { 2, 1, 4, 1, 8, 1 };
  20static const int DMA_OFFSET[] = { 1, -1, 0, 1 };
  21
  22void GBAMemoryInit(struct GBA* gba) {
  23	struct ARMCore* cpu = gba->cpu;
  24	cpu->memory.load32 = GBALoad32;
  25	cpu->memory.load16 = GBALoad16;
  26	cpu->memory.loadU16 = GBALoadU16;
  27	cpu->memory.load8 = GBALoad8;
  28	cpu->memory.loadU8 = GBALoadU8;
  29	cpu->memory.loadMultiple = GBALoadMultiple;
  30	cpu->memory.store32 = GBAStore32;
  31	cpu->memory.store16 = GBAStore16;
  32	cpu->memory.store8 = GBAStore8;
  33	cpu->memory.storeMultiple = GBAStoreMultiple;
  34
  35	gba->memory.bios = (uint32_t*) hleBios;
  36	gba->memory.fullBios = 0;
  37	gba->memory.wram = 0;
  38	gba->memory.iwram = 0;
  39	gba->memory.rom = 0;
  40	gba->memory.gpio.p = gba;
  41
  42	int i;
  43	for (i = 0; i < 16; ++i) {
  44		gba->memory.waitstatesNonseq16[i] = GBA_BASE_WAITSTATES[i];
  45		gba->memory.waitstatesSeq16[i] = GBA_BASE_WAITSTATES_SEQ[i];
  46		gba->memory.waitstatesPrefetchNonseq16[i] = GBA_BASE_WAITSTATES[i];
  47		gba->memory.waitstatesPrefetchSeq16[i] = GBA_BASE_WAITSTATES_SEQ[i];
  48		gba->memory.waitstatesNonseq32[i] = GBA_BASE_WAITSTATES_32[i];
  49		gba->memory.waitstatesSeq32[i] = GBA_BASE_WAITSTATES_SEQ_32[i];
  50		gba->memory.waitstatesPrefetchNonseq32[i] = GBA_BASE_WAITSTATES_32[i];
  51		gba->memory.waitstatesPrefetchSeq32[i] = GBA_BASE_WAITSTATES_SEQ_32[i];
  52	}
  53	for (; i < 256; ++i) {
  54		gba->memory.waitstatesNonseq16[i] = 0;
  55		gba->memory.waitstatesSeq16[i] = 0;
  56		gba->memory.waitstatesNonseq32[i] = 0;
  57		gba->memory.waitstatesSeq32[i] = 0;
  58	}
  59
  60	gba->memory.activeRegion = -1;
  61	cpu->memory.activeRegion = 0;
  62	cpu->memory.activeMask = 0;
  63	cpu->memory.setActiveRegion = GBASetActiveRegion;
  64	cpu->memory.activeSeqCycles32 = 0;
  65	cpu->memory.activeSeqCycles16 = 0;
  66	cpu->memory.activeNonseqCycles32 = 0;
  67	cpu->memory.activeNonseqCycles16 = 0;
  68	cpu->memory.activeUncachedCycles32 = 0;
  69	cpu->memory.activeUncachedCycles16 = 0;
  70	gba->memory.biosPrefetch = 0;
  71}
  72
  73void GBAMemoryDeinit(struct GBA* gba) {
  74	mappedMemoryFree(gba->memory.wram, SIZE_WORKING_RAM);
  75	mappedMemoryFree(gba->memory.iwram, SIZE_WORKING_IRAM);
  76	if (gba->memory.rom) {
  77		mappedMemoryFree(gba->memory.rom, gba->memory.romSize);
  78	}
  79	GBASavedataDeinit(&gba->memory.savedata);
  80}
  81
  82void GBAMemoryReset(struct GBA* gba) {
  83	if (gba->memory.wram) {
  84		mappedMemoryFree(gba->memory.wram, SIZE_WORKING_RAM);
  85	}
  86	gba->memory.wram = anonymousMemoryMap(SIZE_WORKING_RAM);
  87
  88	if (gba->memory.iwram) {
  89		mappedMemoryFree(gba->memory.iwram, SIZE_WORKING_IRAM);
  90	}
  91	gba->memory.iwram = anonymousMemoryMap(SIZE_WORKING_IRAM);
  92
  93	memset(gba->memory.io, 0, sizeof(gba->memory.io));
  94	memset(gba->memory.dma, 0, sizeof(gba->memory.dma));
  95	int i;
  96	for (i = 0; i < 4; ++i) {
  97		gba->memory.dma[i].count = 0x10000;
  98		gba->memory.dma[i].nextEvent = INT_MAX;
  99	}
 100	gba->memory.activeDMA = -1;
 101	gba->memory.nextDMA = INT_MAX;
 102	gba->memory.eventDiff = 0;
 103
 104	if (!gba->memory.wram || !gba->memory.iwram) {
 105		GBAMemoryDeinit(gba);
 106		GBALog(gba, GBA_LOG_FATAL, "Could not map memory");
 107	}
 108}
 109
 110static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) {
 111	struct GBA* gba = (struct GBA*) cpu->master;
 112	struct GBAMemory* memory = &gba->memory;
 113
 114	if (address == gba->busyLoop && memory->activeRegion != REGION_BIOS) {
 115		GBAHalt(gba);
 116	}
 117
 118	int newRegion = address >> BASE_OFFSET;
 119	if (newRegion == memory->activeRegion) {
 120		return;
 121	}
 122	if (memory->activeRegion == REGION_BIOS) {
 123		memory->biosPrefetch = cpu->prefetch;
 124	}
 125	memory->activeRegion = newRegion;
 126	switch (address & ~OFFSET_MASK) {
 127	case BASE_BIOS:
 128		cpu->memory.activeRegion = memory->bios;
 129		cpu->memory.activeMask = SIZE_BIOS - 1;
 130		break;
 131	case BASE_WORKING_RAM:
 132		cpu->memory.activeRegion = memory->wram;
 133		cpu->memory.activeMask = SIZE_WORKING_RAM - 1;
 134		break;
 135	case BASE_WORKING_IRAM:
 136		cpu->memory.activeRegion = memory->iwram;
 137		cpu->memory.activeMask = SIZE_WORKING_IRAM - 1;
 138		break;
 139	case BASE_VRAM:
 140		cpu->memory.activeRegion = (uint32_t*) gba->video.renderer->vram;
 141		cpu->memory.activeMask = 0x0000FFFF;
 142		break;
 143	case BASE_CART0:
 144	case BASE_CART0_EX:
 145	case BASE_CART1:
 146	case BASE_CART1_EX:
 147	case BASE_CART2:
 148	case BASE_CART2_EX:
 149		cpu->memory.activeRegion = memory->rom;
 150		cpu->memory.activeMask = SIZE_CART0 - 1;
 151		break;
 152	default:
 153		cpu->memory.activeRegion = 0;
 154		cpu->memory.activeMask = 0;
 155		GBALog(gba, GBA_LOG_FATAL, "Jumped to invalid address");
 156		break;
 157	}
 158	cpu->memory.activeSeqCycles32 = memory->waitstatesPrefetchSeq32[memory->activeRegion];
 159	cpu->memory.activeSeqCycles16 = memory->waitstatesPrefetchSeq16[memory->activeRegion];
 160	cpu->memory.activeNonseqCycles32 = memory->waitstatesPrefetchNonseq32[memory->activeRegion];
 161	cpu->memory.activeNonseqCycles16 = memory->waitstatesPrefetchNonseq16[memory->activeRegion];
 162	cpu->memory.activeUncachedCycles32 = memory->waitstatesNonseq32[memory->activeRegion];
 163	cpu->memory.activeUncachedCycles16 = memory->waitstatesNonseq16[memory->activeRegion];
 164}
 165
 166#define LOAD_BIOS \
 167	if (memory->activeRegion == REGION_BIOS) { \
 168		if (address < SIZE_BIOS) { \
 169			LOAD_32(value, address, memory->bios); \
 170		} else { \
 171			value = 0; \
 172		} \
 173	} else { \
 174		value = memory->biosPrefetch; \
 175	}
 176
 177#define LOAD_WORKING_RAM \
 178	LOAD_32(value, address & (SIZE_WORKING_RAM - 1), memory->wram); \
 179	wait += waitstatesRegion[REGION_WORKING_RAM];
 180
 181#define LOAD_WORKING_IRAM LOAD_32(value, address & (SIZE_WORKING_IRAM - 1), memory->iwram);
 182#define LOAD_IO value = GBAIORead(gba, (address & (SIZE_IO - 1)) & ~2) | (GBAIORead(gba, (address & (SIZE_IO - 1)) | 2) << 16);
 183
 184#define LOAD_PALETTE_RAM \
 185	LOAD_32(value, address & (SIZE_PALETTE_RAM - 1), gba->video.palette); \
 186	++wait;
 187
 188#define LOAD_VRAM \
 189	LOAD_32(value, address & 0x0001FFFF, gba->video.renderer->vram); \
 190	++wait;
 191
 192#define LOAD_OAM LOAD_32(value, address & (SIZE_OAM - 1), gba->video.oam.raw);
 193
 194#define LOAD_CART \
 195	wait += waitstatesRegion[address >> BASE_OFFSET]; \
 196	if ((address & (SIZE_CART0 - 1)) < memory->romSize) { \
 197		LOAD_32(value, address & (SIZE_CART0 - 1), memory->rom); \
 198	} else { \
 199		value = (address >> 1) & 0xFFFF; \
 200	}
 201
 202#define LOAD_SRAM \
 203	GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Load32: 0x%08X", address); \
 204	value = 0xDEADBEEF;
 205
 206#define LOAD_BAD \
 207	GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load32: 0x%08X", address); \
 208	value = cpu->prefetch; \
 209	if (cpu->executionMode == MODE_THUMB) { \
 210		value |= value << 16; \
 211	}
 212
 213int32_t GBALoad32(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
 214	struct GBA* gba = (struct GBA*) cpu->master;
 215	struct GBAMemory* memory = &gba->memory;
 216	uint32_t value = 0;
 217	int wait = 0;
 218	char* waitstatesRegion = memory->waitstatesNonseq32;
 219
 220	switch (address >> BASE_OFFSET) {
 221	case REGION_BIOS:
 222		LOAD_BIOS;
 223		break;
 224	case REGION_WORKING_RAM:
 225		LOAD_WORKING_RAM;
 226		break;
 227	case REGION_WORKING_IRAM:
 228		LOAD_WORKING_IRAM;
 229		break;
 230	case REGION_IO:
 231		LOAD_IO;
 232		break;
 233	case REGION_PALETTE_RAM:
 234		LOAD_PALETTE_RAM;
 235		break;
 236	case REGION_VRAM:
 237		LOAD_VRAM;
 238		break;
 239	case REGION_OAM:
 240		LOAD_OAM;
 241		break;
 242	case REGION_CART0:
 243	case REGION_CART0_EX:
 244	case REGION_CART1:
 245	case REGION_CART1_EX:
 246	case REGION_CART2:
 247	case REGION_CART2_EX:
 248		LOAD_CART;
 249		break;
 250	case REGION_CART_SRAM:
 251	case REGION_CART_SRAM_MIRROR:
 252		LOAD_SRAM;
 253		break;
 254	default:
 255		LOAD_BAD;
 256		break;
 257	}
 258
 259	if (cycleCounter) {
 260		*cycleCounter += 2 + wait;
 261	}
 262	// Unaligned 32-bit loads are "rotated" so they make some semblance of sense
 263	int rotate = (address & 3) << 3;
 264	return (value >> rotate) | (value << (32 - rotate));
 265}
 266
 267uint16_t GBALoadU16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
 268	return GBALoad16(cpu, address, cycleCounter);
 269}
 270
 271int16_t GBALoad16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
 272	struct GBA* gba = (struct GBA*) cpu->master;
 273	struct GBAMemory* memory = &gba->memory;
 274	uint16_t value = 0;
 275	int wait = 0;
 276
 277	switch (address >> BASE_OFFSET) {
 278	case REGION_BIOS:
 279		if (memory->activeRegion == REGION_BIOS) {
 280			if (address < SIZE_BIOS) {
 281				LOAD_16(value, address, memory->bios);
 282			} else {
 283				value = 0;
 284			}
 285		} else {
 286			value = memory->biosPrefetch;
 287		}
 288		break;
 289	case REGION_WORKING_RAM:
 290		LOAD_16(value, address & (SIZE_WORKING_RAM - 1), memory->wram);
 291		wait = memory->waitstatesNonseq16[REGION_WORKING_RAM];
 292		break;
 293	case REGION_WORKING_IRAM:
 294		LOAD_16(value, address & (SIZE_WORKING_IRAM - 1), memory->iwram);
 295		break;
 296	case REGION_IO:
 297		value = GBAIORead(gba, address & (SIZE_IO - 1));
 298		break;
 299	case REGION_PALETTE_RAM:
 300		LOAD_16(value, address & (SIZE_PALETTE_RAM - 1), gba->video.palette);
 301		break;
 302	case REGION_VRAM:
 303		LOAD_16(value, address & 0x0001FFFF, gba->video.renderer->vram);
 304		break;
 305	case REGION_OAM:
 306		LOAD_16(value, address & (SIZE_OAM - 1), gba->video.oam.raw);
 307		break;
 308	case REGION_CART0:
 309	case REGION_CART0_EX:
 310	case REGION_CART1:
 311	case REGION_CART1_EX:
 312	case REGION_CART2:
 313		wait = memory->waitstatesNonseq16[address >> BASE_OFFSET];
 314		if ((address & (SIZE_CART0 - 1)) < memory->romSize) {
 315			LOAD_16(value, address & (SIZE_CART0 - 1), memory->rom);
 316		}
 317		break;
 318	case REGION_CART2_EX:
 319		wait = memory->waitstatesNonseq16[address >> BASE_OFFSET];
 320		if (memory->savedata.type == SAVEDATA_EEPROM) {
 321			value = GBASavedataReadEEPROM(&memory->savedata);
 322		} else if ((address & (SIZE_CART0 - 1)) < memory->romSize) {
 323			LOAD_16(value, address & (SIZE_CART0 - 1), memory->rom);
 324		}
 325		break;
 326	case REGION_CART_SRAM:
 327	case REGION_CART_SRAM_MIRROR:
 328		GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Load16: 0x%08X", address);
 329		break;
 330	default:
 331		GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load16: 0x%08X", address);
 332		value = cpu->prefetch;
 333		break;
 334	}
 335
 336	if (cycleCounter) {
 337		*cycleCounter += 2 + wait;
 338	}
 339	// Unaligned 16-bit loads are "unpredictable", but the GBA rotates them, so we have to, too.
 340	int rotate = (address & 1) << 3;
 341	return (value >> rotate) | (value << (16 - rotate));
 342}
 343
 344uint8_t GBALoadU8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
 345	return GBALoad8(cpu, address, cycleCounter);
 346}
 347
 348int8_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
 349	struct GBA* gba = (struct GBA*) cpu->master;
 350	struct GBAMemory* memory = &gba->memory;
 351	int8_t value = 0;
 352	int wait = 0;
 353
 354	switch (address >> BASE_OFFSET) {
 355	case REGION_BIOS:
 356		if (memory->activeRegion == REGION_BIOS) {
 357			if (address < SIZE_BIOS) {
 358				value = ((int8_t*) memory->bios)[address];
 359			} else {
 360				value = 0;
 361			}
 362		} else {
 363			value = memory->biosPrefetch;
 364		}
 365		break;
 366	case REGION_WORKING_RAM:
 367		value = ((int8_t*) memory->wram)[address & (SIZE_WORKING_RAM - 1)];
 368		wait = memory->waitstatesNonseq16[REGION_WORKING_RAM];
 369		break;
 370	case REGION_WORKING_IRAM:
 371		value = ((int8_t*) memory->iwram)[address & (SIZE_WORKING_IRAM - 1)];
 372		break;
 373	case REGION_IO:
 374		value = (GBAIORead(gba, address & 0xFFFE) >> ((address & 0x0001) << 3)) & 0xFF;
 375		break;
 376	case REGION_PALETTE_RAM:
 377		value = ((int8_t*) gba->video.palette)[address & (SIZE_PALETTE_RAM - 1)];
 378		break;
 379	case REGION_VRAM:
 380		value = ((int8_t*) gba->video.renderer->vram)[address & 0x0001FFFF];
 381		break;
 382	case REGION_OAM:
 383		GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Load8: 0x%08X", address);
 384		break;
 385	case REGION_CART0:
 386	case REGION_CART0_EX:
 387	case REGION_CART1:
 388	case REGION_CART1_EX:
 389	case REGION_CART2:
 390	case REGION_CART2_EX:
 391		wait = memory->waitstatesNonseq16[address >> BASE_OFFSET];
 392		if ((address & (SIZE_CART0 - 1)) < memory->romSize) {
 393			value = ((int8_t*) memory->rom)[address & (SIZE_CART0 - 1)];
 394		}
 395		break;
 396	case REGION_CART_SRAM:
 397	case REGION_CART_SRAM_MIRROR:
 398		wait = memory->waitstatesNonseq16[address >> BASE_OFFSET];
 399		if (memory->savedata.type == SAVEDATA_NONE) {
 400			GBALog(gba, GBA_LOG_INFO, "Detected SRAM savegame");
 401			GBASavedataInitSRAM(&memory->savedata);
 402		}
 403		if (memory->savedata.type == SAVEDATA_SRAM) {
 404			value = memory->savedata.data[address & (SIZE_CART_SRAM - 1)];
 405		} else if (memory->savedata.type == SAVEDATA_FLASH512 || memory->savedata.type == SAVEDATA_FLASH1M) {
 406			value = GBASavedataReadFlash(&memory->savedata, address);
 407		}
 408		break;
 409	default:
 410		GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load8: 0x%08x", address);
 411		value = cpu->prefetch & 0xFF;
 412		break;
 413	}
 414
 415	if (cycleCounter) {
 416		*cycleCounter += 2 + wait;
 417	}
 418	return value;
 419}
 420
 421#define STORE_WORKING_RAM \
 422	STORE_32(value, address & (SIZE_WORKING_RAM - 1), memory->wram); \
 423	wait += waitstatesRegion[REGION_WORKING_RAM];
 424
 425#define STORE_WORKING_IRAM \
 426	STORE_32(value, address & (SIZE_WORKING_IRAM - 1), memory->iwram);
 427
 428#define STORE_IO \
 429	GBAIOWrite32(gba, address & (SIZE_IO - 1), value);
 430
 431#define STORE_PALETTE_RAM \
 432	STORE_32(value, address & (SIZE_PALETTE_RAM - 1), gba->video.palette); \
 433	gba->video.renderer->writePalette(gba->video.renderer, (address & (SIZE_PALETTE_RAM - 1)) + 2, value >> 16); \
 434	++wait; \
 435	gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 1), value);
 436
 437#define STORE_VRAM \
 438	if ((address & OFFSET_MASK) < SIZE_VRAM) { \
 439		STORE_32(value, address & 0x0001FFFF, gba->video.renderer->vram); \
 440	} else if ((address & OFFSET_MASK) < 0x00020000) { \
 441		STORE_32(value, address & 0x00017FFF, gba->video.renderer->vram); \
 442	} \
 443	++wait;
 444
 445#define STORE_OAM \
 446	STORE_32(value, address & (SIZE_OAM - 1), gba->video.oam.raw); \
 447	gba->video.renderer->writeOAM(gba->video.renderer, (address & (SIZE_OAM - 4)) >> 1); \
 448	gba->video.renderer->writeOAM(gba->video.renderer, ((address & (SIZE_OAM - 4)) >> 1) + 1);
 449
 450#define STORE_CART \
 451	GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Store32: 0x%08X", address);
 452
 453#define STORE_SRAM \
 454	GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Store32: 0x%08X", address);
 455
 456#define STORE_BAD \
 457	GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Store32: 0x%08X", address);
 458
 459void GBAStore32(struct ARMCore* cpu, uint32_t address, int32_t value, int* cycleCounter) {
 460	struct GBA* gba = (struct GBA*) cpu->master;
 461	struct GBAMemory* memory = &gba->memory;
 462	int wait = 0;
 463	char* waitstatesRegion = memory->waitstatesNonseq32;
 464
 465	switch (address >> BASE_OFFSET) {
 466	case REGION_WORKING_RAM:
 467		STORE_WORKING_RAM;
 468		break;
 469	case REGION_WORKING_IRAM:
 470		STORE_WORKING_IRAM
 471		break;
 472	case REGION_IO:
 473		STORE_IO;
 474		break;
 475	case REGION_PALETTE_RAM:
 476		STORE_PALETTE_RAM;
 477		break;
 478	case REGION_VRAM:
 479		STORE_VRAM;
 480		break;
 481	case REGION_OAM:
 482		STORE_OAM;
 483		break;
 484	case REGION_CART0:
 485	case REGION_CART0_EX:
 486	case REGION_CART1:
 487	case REGION_CART1_EX:
 488	case REGION_CART2:
 489	case REGION_CART2_EX:
 490		STORE_CART;
 491		break;
 492	case REGION_CART_SRAM:
 493	case REGION_CART_SRAM_MIRROR:
 494		STORE_SRAM;
 495		break;
 496	default:
 497		STORE_BAD;
 498		break;
 499	}
 500
 501	if (cycleCounter) {
 502		*cycleCounter += 1 + wait;
 503	}
 504}
 505
 506void GBAStore16(struct ARMCore* cpu, uint32_t address, int16_t value, int* cycleCounter) {
 507	struct GBA* gba = (struct GBA*) cpu->master;
 508	struct GBAMemory* memory = &gba->memory;
 509	int wait = 0;
 510
 511	switch (address >> BASE_OFFSET) {
 512	case REGION_WORKING_RAM:
 513		STORE_16(value, address & (SIZE_WORKING_RAM - 1), memory->wram);
 514		wait = memory->waitstatesNonseq16[REGION_WORKING_RAM];
 515		break;
 516	case REGION_WORKING_IRAM:
 517		STORE_16(value, address & (SIZE_WORKING_IRAM - 1), memory->iwram);
 518		break;
 519	case REGION_IO:
 520		GBAIOWrite(gba, address & (SIZE_IO - 1), value);
 521		break;
 522	case REGION_PALETTE_RAM:
 523		STORE_16(value, address & (SIZE_PALETTE_RAM - 1), gba->video.palette);
 524		gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 1), value);
 525		break;
 526	case REGION_VRAM:
 527		if ((address & OFFSET_MASK) < SIZE_VRAM) {
 528			STORE_16(value, address & 0x0001FFFF, gba->video.renderer->vram);
 529		} else if ((address & OFFSET_MASK) < 0x00020000) {
 530			STORE_16(value, address & 0x00017FFF, gba->video.renderer->vram);
 531		}
 532		break;
 533	case REGION_OAM:
 534		STORE_16(value, address & (SIZE_OAM - 1), gba->video.oam.raw);
 535		gba->video.renderer->writeOAM(gba->video.renderer, (address & (SIZE_OAM - 1)) >> 1);
 536		break;
 537	case REGION_CART0:
 538		if (IS_GPIO_REGISTER(address & 0xFFFFFF)) {
 539			uint32_t reg = address & 0xFFFFFF;
 540			GBAGPIOWrite(&memory->gpio, reg, value);
 541		} else {
 542			GBALog(gba, GBA_LOG_GAME_ERROR, "Bad cartridge Store16: 0x%08X", address);
 543		}
 544		break;
 545	case REGION_CART2_EX:
 546		if (memory->savedata.type == SAVEDATA_NONE) {
 547			GBALog(gba, GBA_LOG_INFO, "Detected EEPROM savegame");
 548			GBASavedataInitEEPROM(&memory->savedata);
 549		}
 550		GBASavedataWriteEEPROM(&memory->savedata, value, 1);
 551		break;
 552	case REGION_CART_SRAM:
 553	case REGION_CART_SRAM_MIRROR:
 554		GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Store16: 0x%08X", address);
 555		break;
 556	default:
 557		GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Store16: 0x%08X", address);
 558		break;
 559	}
 560
 561	if (cycleCounter) {
 562		*cycleCounter += 1 + wait;
 563	}
 564}
 565
 566void GBAStore8(struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCounter) {
 567	struct GBA* gba = (struct GBA*) cpu->master;
 568	struct GBAMemory* memory = &gba->memory;
 569	int wait = 0;
 570
 571	switch (address >> BASE_OFFSET) {
 572	case REGION_WORKING_RAM:
 573		((int8_t*) memory->wram)[address & (SIZE_WORKING_RAM - 1)] = value;
 574		wait = memory->waitstatesNonseq16[REGION_WORKING_RAM];
 575		break;
 576	case REGION_WORKING_IRAM:
 577		((int8_t*) memory->iwram)[address & (SIZE_WORKING_IRAM - 1)] = value;
 578		break;
 579	case REGION_IO:
 580		GBAIOWrite8(gba, address & (SIZE_IO - 1), value);
 581		break;
 582	case REGION_PALETTE_RAM:
 583		GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Store8: 0x%08X", address);
 584		break;
 585	case REGION_VRAM:
 586		if (address >= 0x06018000) {
 587			// TODO: check BG mode
 588			GBALog(gba, GBA_LOG_GAME_ERROR, "Cannot Store8 to OBJ: 0x%08X", address);
 589			break;
 590		}
 591		((int8_t*) gba->video.renderer->vram)[address & 0x1FFFE] = value;
 592		((int8_t*) gba->video.renderer->vram)[(address & 0x1FFFE) | 1] = value;
 593		break;
 594	case REGION_OAM:
 595		GBALog(gba, GBA_LOG_GAME_ERROR, "Cannot Store8 to OAM: 0x%08X", address);
 596		break;
 597	case REGION_CART0:
 598		GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Store8: 0x%08X", address);
 599		break;
 600	case REGION_CART_SRAM:
 601	case REGION_CART_SRAM_MIRROR:
 602		if (memory->savedata.type == SAVEDATA_NONE) {
 603			if (address == SAVEDATA_FLASH_BASE) {
 604				GBALog(gba, GBA_LOG_INFO, "Detected Flash savegame");
 605				GBASavedataInitFlash(&memory->savedata);
 606			} else {
 607				GBALog(gba, GBA_LOG_INFO, "Detected SRAM savegame");
 608				GBASavedataInitSRAM(&memory->savedata);
 609			}
 610		}
 611		if (memory->savedata.type == SAVEDATA_FLASH512 || memory->savedata.type == SAVEDATA_FLASH1M) {
 612			GBASavedataWriteFlash(&memory->savedata, address, value);
 613		} else if (memory->savedata.type == SAVEDATA_SRAM) {
 614			memory->savedata.data[address & (SIZE_CART_SRAM - 1)] = value;
 615		}
 616		wait = memory->waitstatesNonseq16[REGION_CART_SRAM];
 617		break;
 618	default:
 619		GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Store8: 0x%08X", address);
 620		break;
 621	}
 622
 623	if (cycleCounter) {
 624		*cycleCounter += 1 + wait;
 625	}
 626}
 627
 628#define LDM_LOOP_BEGIN \
 629	for (i = 0; i < 16; ++i) { \
 630		if (~mask & (1 << i)) { \
 631			continue; \
 632		}
 633
 634#define LDM_LOOP_END \
 635		waitstatesRegion = memory->waitstatesSeq32; \
 636		cpu->gprs[i] = value; \
 637		++wait; \
 638		address += 4; \
 639	}
 640
 641uint32_t GBALoadMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum LSMDirection direction, int* cycleCounter) {
 642	struct GBA* gba = (struct GBA*) cpu->master;
 643	struct GBAMemory* memory = &gba->memory;
 644	uint32_t value;
 645	int wait = 0;
 646	char* waitstatesRegion = memory->waitstatesNonseq32;
 647
 648	int i;
 649	int offset = 4;
 650	int popcount = 0;
 651	if (direction & LSM_D) {
 652		offset = -4;
 653		popcount = __builtin_popcount(mask);
 654		address -= (popcount << 2) - 4;
 655	}
 656
 657	if (direction & LSM_B) {
 658		address += offset;
 659	}
 660
 661	address &= 0xFFFFFFFC;
 662
 663	switch (address >> BASE_OFFSET) {
 664	case REGION_WORKING_RAM:
 665		LDM_LOOP_BEGIN;
 666		LOAD_WORKING_RAM;
 667		LDM_LOOP_END;
 668		break;
 669	case REGION_WORKING_IRAM:
 670		LDM_LOOP_BEGIN;
 671		LOAD_WORKING_IRAM;
 672		LDM_LOOP_END;
 673		break;
 674	case REGION_IO:
 675		LDM_LOOP_BEGIN;
 676		LOAD_IO;
 677		LDM_LOOP_END;
 678		break;
 679	case REGION_PALETTE_RAM:
 680		LDM_LOOP_BEGIN;
 681		LOAD_PALETTE_RAM;
 682		LDM_LOOP_END;
 683		break;
 684	case REGION_VRAM:
 685		LDM_LOOP_BEGIN;
 686		LOAD_VRAM;
 687		LDM_LOOP_END;
 688		break;
 689	case REGION_OAM:
 690		LDM_LOOP_BEGIN;
 691		LOAD_OAM;
 692		LDM_LOOP_END;
 693		break;
 694	case REGION_CART0:
 695	case REGION_CART0_EX:
 696	case REGION_CART1:
 697	case REGION_CART1_EX:
 698	case REGION_CART2:
 699	case REGION_CART2_EX:
 700		LDM_LOOP_BEGIN;
 701		LOAD_CART;
 702		LDM_LOOP_END;
 703		break;
 704	case REGION_CART_SRAM:
 705	case REGION_CART_SRAM_MIRROR:
 706		LDM_LOOP_BEGIN;
 707		LOAD_SRAM;
 708		LDM_LOOP_END;
 709		break;
 710	default:
 711		LDM_LOOP_BEGIN;
 712		LOAD_BAD;
 713		LDM_LOOP_END;
 714		break;
 715	}
 716
 717	if (cycleCounter) {
 718		*cycleCounter += wait;
 719	}
 720
 721	if (direction & LSM_B) {
 722		address -= offset;
 723	}
 724
 725	if (direction & LSM_D) {
 726		address -= (popcount << 2) + 4;
 727	}
 728
 729	return address;
 730}
 731
 732#define STM_LOOP_BEGIN \
 733	for (i = 0; i < 16; ++i) { \
 734		if (~mask & (1 << i)) { \
 735			continue; \
 736		} \
 737		value = cpu->gprs[i];
 738
 739#define STM_LOOP_END \
 740		waitstatesRegion = memory->waitstatesSeq32; \
 741		++wait; \
 742		address += 4; \
 743	}
 744
 745uint32_t GBAStoreMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum LSMDirection direction, int* cycleCounter) {
 746	struct GBA* gba = (struct GBA*) cpu->master;
 747	struct GBAMemory* memory = &gba->memory;
 748	uint32_t value;
 749	int wait = 0;
 750	char* waitstatesRegion = memory->waitstatesNonseq32;
 751
 752	int i;
 753	int offset = 4;
 754	int popcount = 0;
 755	if (direction & LSM_D) {
 756		offset = -4;
 757		popcount = __builtin_popcount(mask);
 758		address -= (popcount << 2) - 4;
 759	}
 760
 761	if (direction & LSM_B) {
 762		address += offset;
 763	}
 764
 765	address &= 0xFFFFFFFC;
 766
 767	switch (address >> BASE_OFFSET) {
 768	case REGION_WORKING_RAM:
 769		STM_LOOP_BEGIN;
 770		STORE_WORKING_RAM;
 771		STM_LOOP_END;
 772		break;
 773	case REGION_WORKING_IRAM:
 774		STM_LOOP_BEGIN;
 775		STORE_WORKING_IRAM;
 776		STM_LOOP_END;
 777		break;
 778	case REGION_IO:
 779		STM_LOOP_BEGIN;
 780		STORE_IO;
 781		STM_LOOP_END;
 782		break;
 783	case REGION_PALETTE_RAM:
 784		STM_LOOP_BEGIN;
 785		STORE_PALETTE_RAM;
 786		STM_LOOP_END;
 787		break;
 788	case REGION_VRAM:
 789		STM_LOOP_BEGIN;
 790		STORE_VRAM;
 791		STM_LOOP_END;
 792		break;
 793	case REGION_OAM:
 794		STM_LOOP_BEGIN;
 795		STORE_OAM;
 796		STM_LOOP_END;
 797		break;
 798	case REGION_CART0:
 799	case REGION_CART0_EX:
 800	case REGION_CART1:
 801	case REGION_CART1_EX:
 802	case REGION_CART2:
 803	case REGION_CART2_EX:
 804		STM_LOOP_BEGIN;
 805		STORE_CART;
 806		STM_LOOP_END;
 807		break;
 808	case REGION_CART_SRAM:
 809	case REGION_CART_SRAM_MIRROR:
 810		STM_LOOP_BEGIN;
 811		STORE_SRAM;
 812		STM_LOOP_END;
 813		break;
 814	default:
 815		STM_LOOP_BEGIN;
 816		STORE_BAD;
 817		STM_LOOP_END;
 818		break;
 819	}
 820
 821	if (cycleCounter) {
 822		*cycleCounter += wait;
 823	}
 824
 825	if (direction & LSM_B) {
 826		address -= offset;
 827	}
 828
 829	if (direction & LSM_D) {
 830		address -= (popcount << 2) + 4;
 831	}
 832
 833	return address;
 834}
 835
 836void GBAAdjustWaitstates(struct GBA* gba, uint16_t parameters) {
 837	struct GBAMemory* memory = &gba->memory;
 838	struct ARMCore* cpu = gba->cpu;
 839	int sram = parameters & 0x0003;
 840	int ws0 = (parameters & 0x000C) >> 2;
 841	int ws0seq = (parameters & 0x0010) >> 4;
 842	int ws1 = (parameters & 0x0060) >> 5;
 843	int ws1seq = (parameters & 0x0080) >> 7;
 844	int ws2 = (parameters & 0x0300) >> 8;
 845	int ws2seq = (parameters & 0x0400) >> 10;
 846	int prefetch = parameters & 0x4000;
 847
 848	memory->waitstatesNonseq16[REGION_CART_SRAM] = memory->waitstatesNonseq16[REGION_CART_SRAM_MIRROR] =  GBA_ROM_WAITSTATES[sram];
 849	memory->waitstatesSeq16[REGION_CART_SRAM] = memory->waitstatesSeq16[REGION_CART_SRAM_MIRROR] = GBA_ROM_WAITSTATES[sram];
 850	memory->waitstatesNonseq32[REGION_CART_SRAM] = memory->waitstatesNonseq32[REGION_CART_SRAM_MIRROR] = 2 * GBA_ROM_WAITSTATES[sram] + 1;
 851	memory->waitstatesSeq32[REGION_CART_SRAM] = memory->waitstatesSeq32[REGION_CART_SRAM_MIRROR] = 2 * GBA_ROM_WAITSTATES[sram] + 1;
 852
 853	memory->waitstatesNonseq16[REGION_CART0] = memory->waitstatesNonseq16[REGION_CART0_EX] = GBA_ROM_WAITSTATES[ws0];
 854	memory->waitstatesNonseq16[REGION_CART1] = memory->waitstatesNonseq16[REGION_CART1_EX] = GBA_ROM_WAITSTATES[ws1];
 855	memory->waitstatesNonseq16[REGION_CART2] = memory->waitstatesNonseq16[REGION_CART2_EX] = GBA_ROM_WAITSTATES[ws2];
 856
 857	memory->waitstatesSeq16[REGION_CART0] = memory->waitstatesSeq16[REGION_CART0_EX] = GBA_ROM_WAITSTATES_SEQ[ws0seq];
 858	memory->waitstatesSeq16[REGION_CART1] = memory->waitstatesSeq16[REGION_CART1_EX] = GBA_ROM_WAITSTATES_SEQ[ws1seq + 2];
 859	memory->waitstatesSeq16[REGION_CART2] = memory->waitstatesSeq16[REGION_CART2_EX] = GBA_ROM_WAITSTATES_SEQ[ws2seq + 4];
 860
 861	memory->waitstatesNonseq32[REGION_CART0] = memory->waitstatesNonseq32[REGION_CART0_EX] = memory->waitstatesSeq16[REGION_CART0] + 1 + memory->waitstatesSeq16[REGION_CART0];
 862	memory->waitstatesNonseq32[REGION_CART1] = memory->waitstatesNonseq32[REGION_CART1_EX] = memory->waitstatesSeq16[REGION_CART1] + 1 + memory->waitstatesSeq16[REGION_CART1];
 863	memory->waitstatesNonseq32[REGION_CART2] = memory->waitstatesNonseq32[REGION_CART2_EX] = memory->waitstatesSeq16[REGION_CART2] + 1 + memory->waitstatesSeq16[REGION_CART2];
 864
 865	memory->waitstatesSeq32[REGION_CART0] = memory->waitstatesSeq32[REGION_CART0_EX] = 2 * memory->waitstatesSeq16[REGION_CART0] + 1;
 866	memory->waitstatesSeq32[REGION_CART1] = memory->waitstatesSeq32[REGION_CART1_EX] = 2 * memory->waitstatesSeq16[REGION_CART1] + 1;
 867	memory->waitstatesSeq32[REGION_CART2] = memory->waitstatesSeq32[REGION_CART2_EX] = 2 * memory->waitstatesSeq16[REGION_CART2] + 1;
 868
 869	if (!prefetch) {
 870		memory->waitstatesPrefetchSeq16[REGION_CART0] = memory->waitstatesPrefetchSeq16[REGION_CART0_EX] = memory->waitstatesSeq16[REGION_CART0];
 871		memory->waitstatesPrefetchSeq16[REGION_CART1] = memory->waitstatesPrefetchSeq16[REGION_CART1_EX] = memory->waitstatesSeq16[REGION_CART1];
 872		memory->waitstatesPrefetchSeq16[REGION_CART2] = memory->waitstatesPrefetchSeq16[REGION_CART2_EX] = memory->waitstatesSeq16[REGION_CART2];
 873
 874		memory->waitstatesPrefetchSeq32[REGION_CART0] = memory->waitstatesPrefetchSeq32[REGION_CART0_EX] = memory->waitstatesSeq32[REGION_CART0];
 875		memory->waitstatesPrefetchSeq32[REGION_CART1] = memory->waitstatesPrefetchSeq32[REGION_CART1_EX] = memory->waitstatesSeq32[REGION_CART1];
 876		memory->waitstatesPrefetchSeq32[REGION_CART2] = memory->waitstatesPrefetchSeq32[REGION_CART2_EX] = memory->waitstatesSeq32[REGION_CART2];
 877
 878		memory->waitstatesPrefetchNonseq16[REGION_CART0] = memory->waitstatesPrefetchNonseq16[REGION_CART0_EX] = memory->waitstatesNonseq16[REGION_CART0];
 879		memory->waitstatesPrefetchNonseq16[REGION_CART1] = memory->waitstatesPrefetchNonseq16[REGION_CART1_EX] = memory->waitstatesNonseq16[REGION_CART1];
 880		memory->waitstatesPrefetchNonseq16[REGION_CART2] = memory->waitstatesPrefetchNonseq16[REGION_CART2_EX] = memory->waitstatesNonseq16[REGION_CART2];
 881
 882		memory->waitstatesPrefetchNonseq32[REGION_CART0] = memory->waitstatesPrefetchNonseq32[REGION_CART0_EX] = memory->waitstatesNonseq32[REGION_CART0];
 883		memory->waitstatesPrefetchNonseq32[REGION_CART1] = memory->waitstatesPrefetchNonseq32[REGION_CART1_EX] = memory->waitstatesNonseq32[REGION_CART1];
 884		memory->waitstatesPrefetchNonseq32[REGION_CART2] = memory->waitstatesPrefetchNonseq32[REGION_CART2_EX] = memory->waitstatesNonseq32[REGION_CART2];
 885	} else {
 886		memory->waitstatesPrefetchSeq16[REGION_CART0] = memory->waitstatesPrefetchSeq16[REGION_CART0_EX] = 0;
 887		memory->waitstatesPrefetchSeq16[REGION_CART1] = memory->waitstatesPrefetchSeq16[REGION_CART1_EX] = 0;
 888		memory->waitstatesPrefetchSeq16[REGION_CART2] = memory->waitstatesPrefetchSeq16[REGION_CART2_EX] = 0;
 889
 890		memory->waitstatesPrefetchSeq32[REGION_CART0] = memory->waitstatesPrefetchSeq32[REGION_CART0_EX] = 0;
 891		memory->waitstatesPrefetchSeq32[REGION_CART1] = memory->waitstatesPrefetchSeq32[REGION_CART1_EX] = 0;
 892		memory->waitstatesPrefetchSeq32[REGION_CART2] = memory->waitstatesPrefetchSeq32[REGION_CART2_EX] = 0;
 893
 894		memory->waitstatesPrefetchNonseq16[REGION_CART0] = memory->waitstatesPrefetchNonseq16[REGION_CART0_EX] = 0;
 895		memory->waitstatesPrefetchNonseq16[REGION_CART1] = memory->waitstatesPrefetchNonseq16[REGION_CART1_EX] = 0;
 896		memory->waitstatesPrefetchNonseq16[REGION_CART2] = memory->waitstatesPrefetchNonseq16[REGION_CART2_EX] = 0;
 897
 898		memory->waitstatesPrefetchNonseq32[REGION_CART0] = memory->waitstatesPrefetchNonseq32[REGION_CART0_EX] = 0;
 899		memory->waitstatesPrefetchNonseq32[REGION_CART1] = memory->waitstatesPrefetchNonseq32[REGION_CART1_EX] = 0;
 900		memory->waitstatesPrefetchNonseq32[REGION_CART2] = memory->waitstatesPrefetchNonseq32[REGION_CART2_EX] = 0;
 901	}
 902
 903	cpu->memory.activeSeqCycles32 = memory->waitstatesPrefetchSeq32[memory->activeRegion];
 904	cpu->memory.activeSeqCycles16 = memory->waitstatesPrefetchSeq16[memory->activeRegion];
 905
 906	cpu->memory.activeNonseqCycles32 = memory->waitstatesPrefetchNonseq32[memory->activeRegion];
 907	cpu->memory.activeNonseqCycles16 = memory->waitstatesPrefetchNonseq16[memory->activeRegion];
 908
 909	cpu->memory.activeUncachedCycles32 = memory->waitstatesNonseq32[memory->activeRegion];
 910	cpu->memory.activeUncachedCycles16 = memory->waitstatesNonseq16[memory->activeRegion];
 911}
 912
 913void GBAMemoryWriteDMASAD(struct GBA* gba, int dma, uint32_t address) {
 914	struct GBAMemory* memory = &gba->memory;
 915	memory->dma[dma].source = address & 0xFFFFFFFE;
 916}
 917
 918void GBAMemoryWriteDMADAD(struct GBA* gba, int dma, uint32_t address) {
 919	struct GBAMemory* memory = &gba->memory;
 920	memory->dma[dma].dest = address & 0xFFFFFFFE;
 921}
 922
 923void GBAMemoryWriteDMACNT_LO(struct GBA* gba, int dma, uint16_t count) {
 924	struct GBAMemory* memory = &gba->memory;
 925	memory->dma[dma].count = count ? count : (dma == 3 ? 0x10000 : 0x4000);
 926}
 927
 928uint16_t GBAMemoryWriteDMACNT_HI(struct GBA* gba, int dma, uint16_t control) {
 929	struct GBAMemory* memory = &gba->memory;
 930	struct GBADMA* currentDma = &memory->dma[dma];
 931	int wasEnabled = GBADMARegisterIsEnable(currentDma->reg);
 932	currentDma->reg = control;
 933
 934	if (GBADMARegisterIsDRQ(currentDma->reg)) {
 935		GBALog(gba, GBA_LOG_STUB, "DRQ not implemented");
 936	}
 937
 938	if (!wasEnabled && GBADMARegisterIsEnable(currentDma->reg)) {
 939		currentDma->nextSource = currentDma->source;
 940		currentDma->nextDest = currentDma->dest;
 941		currentDma->nextCount = currentDma->count;
 942		GBAMemoryScheduleDMA(gba, dma, currentDma);
 943	}
 944	// If the DMA has already occurred, this value might have changed since the function started
 945	return currentDma->reg;
 946};
 947
 948void GBAMemoryScheduleDMA(struct GBA* gba, int number, struct GBADMA* info) {
 949	struct ARMCore* cpu = gba->cpu;
 950	switch (GBADMARegisterGetTiming(info->reg)) {
 951	case DMA_TIMING_NOW:
 952		info->nextEvent = cpu->cycles;
 953		GBAMemoryUpdateDMAs(gba, 0);
 954		break;
 955	case DMA_TIMING_HBLANK:
 956		// Handled implicitly
 957		info->nextEvent = INT_MAX;
 958		break;
 959	case DMA_TIMING_VBLANK:
 960		// Handled implicitly
 961		info->nextEvent = INT_MAX;
 962		break;
 963	case DMA_TIMING_CUSTOM:
 964		info->nextEvent = INT_MAX;
 965		switch (number) {
 966		case 0:
 967			GBALog(gba, GBA_LOG_WARN, "Discarding invalid DMA0 scheduling");
 968			break;
 969		case 1:
 970		case 2:
 971			GBAAudioScheduleFifoDma(&gba->audio, number, info);
 972			break;
 973		case 3:
 974			// GBAVideoScheduleVCaptureDma(dma, info);
 975			break;
 976		}
 977	}
 978}
 979
 980void GBAMemoryRunHblankDMAs(struct GBA* gba, int32_t cycles) {
 981	struct GBAMemory* memory = &gba->memory;
 982	struct GBADMA* dma;
 983	int i;
 984	for (i = 0; i < 4; ++i) {
 985		dma = &memory->dma[i];
 986		if (GBADMARegisterIsEnable(dma->reg) && GBADMARegisterGetTiming(dma->reg) == DMA_TIMING_HBLANK) {
 987			dma->nextEvent = cycles;
 988		}
 989	}
 990	GBAMemoryUpdateDMAs(gba, 0);
 991}
 992
 993void GBAMemoryRunVblankDMAs(struct GBA* gba, int32_t cycles) {
 994	struct GBAMemory* memory = &gba->memory;
 995	struct GBADMA* dma;
 996	int i;
 997	for (i = 0; i < 4; ++i) {
 998		dma = &memory->dma[i];
 999		if (GBADMARegisterIsEnable(dma->reg) && GBADMARegisterGetTiming(dma->reg) == DMA_TIMING_VBLANK) {
1000			dma->nextEvent = cycles;
1001		}
1002	}
1003	GBAMemoryUpdateDMAs(gba, 0);
1004}
1005
1006int32_t GBAMemoryRunDMAs(struct GBA* gba, int32_t cycles) {
1007	struct GBAMemory* memory = &gba->memory;
1008	if (memory->nextDMA == INT_MAX) {
1009		return INT_MAX;
1010	}
1011	memory->nextDMA -= cycles;
1012	memory->eventDiff += cycles;
1013	if (memory->nextDMA <= 0) {
1014		struct GBADMA* dma = &memory->dma[memory->activeDMA];
1015		GBAMemoryServiceDMA(gba, memory->activeDMA, dma);
1016		GBAMemoryUpdateDMAs(gba, memory->eventDiff);
1017		memory->eventDiff = 0;
1018	}
1019	return memory->nextDMA;
1020}
1021
1022void GBAMemoryUpdateDMAs(struct GBA* gba, int32_t cycles) {
1023	int i;
1024	struct GBAMemory* memory = &gba->memory;
1025	struct ARMCore* cpu = gba->cpu;
1026	memory->activeDMA = -1;
1027	memory->nextDMA = INT_MAX;
1028	for (i = 3; i >= 0; --i) {
1029		struct GBADMA* dma = &memory->dma[i];
1030		if (dma->nextEvent != INT_MAX) {
1031			dma->nextEvent -= cycles;
1032			if (GBADMARegisterIsEnable(dma->reg)) {
1033				memory->activeDMA = i;
1034				memory->nextDMA = dma->nextEvent;
1035			}
1036		}
1037	}
1038	if (memory->nextDMA < cpu->nextEvent) {
1039		cpu->nextEvent = memory->nextDMA;
1040	}
1041}
1042
1043void GBAMemoryServiceDMA(struct GBA* gba, int number, struct GBADMA* info) {
1044	struct GBAMemory* memory = &gba->memory;
1045	struct ARMCore* cpu = gba->cpu;
1046	uint32_t width = GBADMARegisterGetWidth(info->reg) ? 4 : 2;
1047	int sourceOffset = DMA_OFFSET[GBADMARegisterGetSrcControl(info->reg)] * width;
1048	int destOffset = DMA_OFFSET[GBADMARegisterGetDestControl(info->reg)] * width;
1049	int32_t wordsRemaining = info->nextCount;
1050	uint32_t source = info->nextSource;
1051	uint32_t dest = info->nextDest;
1052	uint32_t sourceRegion = source >> BASE_OFFSET;
1053	uint32_t destRegion = dest >> BASE_OFFSET;
1054	int32_t cycles = 0;
1055
1056	if (source == info->source) {
1057		// TODO: support 4 cycles for ROM access
1058		cycles += 2;
1059		if (width == 4) {
1060			cycles += memory->waitstatesNonseq32[sourceRegion] + memory->waitstatesNonseq32[destRegion];
1061			source &= 0xFFFFFFFC;
1062			dest &= 0xFFFFFFFC;
1063		} else {
1064			cycles += memory->waitstatesNonseq16[sourceRegion] + memory->waitstatesNonseq16[destRegion];
1065		}
1066	} else {
1067		if (width == 4) {
1068			cycles += memory->waitstatesSeq32[sourceRegion] + memory->waitstatesSeq32[destRegion];
1069		} else {
1070			cycles += memory->waitstatesSeq16[sourceRegion] + memory->waitstatesSeq16[destRegion];
1071		}
1072	}
1073
1074	if (width == 4) {
1075		int32_t word;
1076		word = cpu->memory.load32(cpu, source, 0);
1077		cpu->memory.store32(cpu, dest, word, 0);
1078		source += sourceOffset;
1079		dest += destOffset;
1080		--wordsRemaining;
1081	} else {
1082		uint16_t word;
1083		if (sourceRegion == REGION_CART2_EX && memory->savedata.type == SAVEDATA_EEPROM) {
1084			word = GBASavedataReadEEPROM(&memory->savedata);
1085			cpu->memory.store16(cpu, dest, word, 0);
1086			source += sourceOffset;
1087			dest += destOffset;
1088			--wordsRemaining;
1089		} else if (destRegion == REGION_CART2_EX) {
1090			if (memory->savedata.type == SAVEDATA_NONE) {
1091				GBALog(gba, GBA_LOG_INFO, "Detected EEPROM savegame");
1092				GBASavedataInitEEPROM(&memory->savedata);
1093			}
1094			word = cpu->memory.load16(cpu, source, 0);
1095			GBASavedataWriteEEPROM(&memory->savedata, word, wordsRemaining);
1096			source += sourceOffset;
1097			dest += destOffset;
1098			--wordsRemaining;
1099		} else {
1100			word = cpu->memory.load16(cpu, source, 0);
1101			cpu->memory.store16(cpu, dest, word, 0);
1102			source += sourceOffset;
1103			dest += destOffset;
1104			--wordsRemaining;
1105		}
1106	}
1107
1108	if (!wordsRemaining) {
1109		if (!GBADMARegisterIsRepeat(info->reg)) {
1110			info->reg = GBADMARegisterClearEnable(info->reg);
1111			info->nextEvent = INT_MAX;
1112
1113			// Clear the enable bit in memory
1114			memory->io[(REG_DMA0CNT_HI + number * (REG_DMA1CNT_HI - REG_DMA0CNT_HI)) >> 1] &= 0x7FE0;
1115		} else {
1116			info->nextCount = info->count;
1117			if (GBADMARegisterGetDestControl(info->reg) == DMA_INCREMENT_RELOAD) {
1118				info->nextDest = info->dest;
1119			}
1120			GBAMemoryScheduleDMA(gba, number, info);
1121		}
1122		if (GBADMARegisterIsDoIRQ(info->reg)) {
1123			GBARaiseIRQ(gba, IRQ_DMA0 + number);
1124		}
1125	} else {
1126		info->nextDest = dest;
1127		info->nextCount = wordsRemaining;
1128	}
1129	info->nextSource = source;
1130
1131	if (info->nextEvent != INT_MAX) {
1132		info->nextEvent += cycles;
1133	}
1134	cpu->cycles += cycles;
1135}
1136
1137void GBAMemorySerialize(struct GBAMemory* memory, struct GBASerializedState* state) {
1138	memcpy(state->wram, memory->wram, SIZE_WORKING_RAM);
1139	memcpy(state->iwram, memory->iwram, SIZE_WORKING_IRAM);
1140}
1141
1142void GBAMemoryDeserialize(struct GBAMemory* memory, struct GBASerializedState* state) {
1143	memcpy(memory->wram, state->wram, SIZE_WORKING_RAM);
1144	memcpy(memory->iwram, state->iwram, SIZE_WORKING_IRAM);
1145}