all repos — mgba @ 74bb02065d232108192b41eb80e2889e000457bf

mGBA Game Boy Advance Emulator

src/gba/memory.c (view raw)

   1/* Copyright (c) 2013-2015 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 "memory.h"
   7
   8#include "arm/decoder.h"
   9#include "gba/hardware.h"
  10#include "gba/io.h"
  11#include "gba/serialize.h"
  12#include "gba/hle-bios.h"
  13#include "util/math.h"
  14#include "util/memory.h"
  15#include "util/vfs.h"
  16
  17#define IDLE_LOOP_THRESHOLD 10000
  18
  19mLOG_DEFINE_CATEGORY(GBA_MEM, "GBA Memory");
  20
  21static void _pristineCow(struct GBA* gba);
  22static uint32_t _deadbeef[1] = { 0xE710B710 }; // Illegal instruction on both ARM and Thumb
  23
  24static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t region);
  25static void GBAMemoryServiceDMA(struct GBA* gba, int number, struct GBADMA* info);
  26static int32_t GBAMemoryStall(struct ARMCore* cpu, int32_t wait);
  27
  28static const char GBA_BASE_WAITSTATES[16] = { 0, 0, 2, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4 };
  29static const char GBA_BASE_WAITSTATES_32[16] = { 0, 0, 5, 0, 0, 1, 1, 0, 7, 7, 9, 9, 13, 13, 9 };
  30static const char GBA_BASE_WAITSTATES_SEQ[16] = { 0, 0, 2, 0, 0, 0, 0, 0, 2, 2, 4, 4, 8, 8, 4 };
  31static const char GBA_BASE_WAITSTATES_SEQ_32[16] = { 0, 0, 5, 0, 0, 1, 1, 0, 5, 5, 9, 9, 17, 17, 9 };
  32static const char GBA_ROM_WAITSTATES[] = { 4, 3, 2, 8 };
  33static const char GBA_ROM_WAITSTATES_SEQ[] = { 2, 1, 4, 1, 8, 1 };
  34static const int DMA_OFFSET[] = { 1, -1, 0, 1 };
  35
  36void GBAMemoryInit(struct GBA* gba) {
  37	struct ARMCore* cpu = gba->cpu;
  38	cpu->memory.load32 = GBALoad32;
  39	cpu->memory.load16 = GBALoad16;
  40	cpu->memory.load8 = GBALoad8;
  41	cpu->memory.loadMultiple = GBALoadMultiple;
  42	cpu->memory.store32 = GBAStore32;
  43	cpu->memory.store16 = GBAStore16;
  44	cpu->memory.store8 = GBAStore8;
  45	cpu->memory.storeMultiple = GBAStoreMultiple;
  46	cpu->memory.stall = GBAMemoryStall;
  47
  48	gba->memory.bios = (uint32_t*) hleBios;
  49	gba->memory.fullBios = 0;
  50	gba->memory.wram = 0;
  51	gba->memory.iwram = 0;
  52	gba->memory.rom = 0;
  53	gba->memory.romSize = 0;
  54	gba->memory.romMask = 0;
  55	gba->memory.hw.p = gba;
  56
  57	int i;
  58	for (i = 0; i < 16; ++i) {
  59		gba->memory.waitstatesNonseq16[i] = GBA_BASE_WAITSTATES[i];
  60		gba->memory.waitstatesSeq16[i] = GBA_BASE_WAITSTATES_SEQ[i];
  61		gba->memory.waitstatesPrefetchNonseq16[i] = GBA_BASE_WAITSTATES[i];
  62		gba->memory.waitstatesPrefetchSeq16[i] = GBA_BASE_WAITSTATES_SEQ[i];
  63		gba->memory.waitstatesNonseq32[i] = GBA_BASE_WAITSTATES_32[i];
  64		gba->memory.waitstatesSeq32[i] = GBA_BASE_WAITSTATES_SEQ_32[i];
  65		gba->memory.waitstatesPrefetchNonseq32[i] = GBA_BASE_WAITSTATES_32[i];
  66		gba->memory.waitstatesPrefetchSeq32[i] = GBA_BASE_WAITSTATES_SEQ_32[i];
  67	}
  68	for (; i < 256; ++i) {
  69		gba->memory.waitstatesNonseq16[i] = 0;
  70		gba->memory.waitstatesSeq16[i] = 0;
  71		gba->memory.waitstatesNonseq32[i] = 0;
  72		gba->memory.waitstatesSeq32[i] = 0;
  73	}
  74
  75	gba->memory.activeRegion = -1;
  76	cpu->memory.activeRegion = 0;
  77	cpu->memory.activeMask = 0;
  78	cpu->memory.setActiveRegion = GBASetActiveRegion;
  79	cpu->memory.activeSeqCycles32 = 0;
  80	cpu->memory.activeSeqCycles16 = 0;
  81	cpu->memory.activeNonseqCycles32 = 0;
  82	cpu->memory.activeNonseqCycles16 = 0;
  83	gba->memory.biosPrefetch = 0;
  84	gba->memory.mirroring = false;
  85
  86	GBAVFameInit(&gba->memory.vfame);
  87}
  88
  89void GBAMemoryDeinit(struct GBA* gba) {
  90	mappedMemoryFree(gba->memory.wram, SIZE_WORKING_RAM);
  91	mappedMemoryFree(gba->memory.iwram, SIZE_WORKING_IRAM);
  92	if (gba->memory.rom) {
  93		mappedMemoryFree(gba->memory.rom, gba->memory.romSize);
  94	}
  95	GBASavedataUnmask(&gba->memory.savedata);
  96	GBASavedataDeinit(&gba->memory.savedata);
  97	if (gba->memory.savedata.realVf) {
  98		gba->memory.savedata.realVf->close(gba->memory.savedata.realVf);
  99	}
 100}
 101
 102void GBAMemoryReset(struct GBA* gba) {
 103	if (gba->memory.wram) {
 104		mappedMemoryFree(gba->memory.wram, SIZE_WORKING_RAM);
 105	}
 106	gba->memory.wram = anonymousMemoryMap(SIZE_WORKING_RAM);
 107	if (gba->pristineRom && !gba->memory.rom) {
 108		// Multiboot
 109		memcpy(gba->memory.wram, gba->pristineRom, gba->pristineRomSize);
 110	}
 111
 112	if (gba->memory.iwram) {
 113		mappedMemoryFree(gba->memory.iwram, SIZE_WORKING_IRAM);
 114	}
 115	gba->memory.iwram = anonymousMemoryMap(SIZE_WORKING_IRAM);
 116
 117	memset(gba->memory.io, 0, sizeof(gba->memory.io));
 118	memset(gba->memory.dma, 0, sizeof(gba->memory.dma));
 119	int i;
 120	for (i = 0; i < 4; ++i) {
 121		gba->memory.dma[i].count = 0x4000;
 122		gba->memory.dma[i].nextEvent = INT_MAX;
 123	}
 124	gba->memory.dma[3].count = 0x10000;
 125	gba->memory.activeDMA = -1;
 126	gba->memory.nextDMA = INT_MAX;
 127	gba->memory.eventDiff = 0;
 128
 129	gba->memory.prefetch = false;
 130	gba->memory.lastPrefetchedPc = 0;
 131
 132	if (!gba->memory.wram || !gba->memory.iwram) {
 133		GBAMemoryDeinit(gba);
 134		mLOG(GBA_MEM, FATAL, "Could not map memory");
 135	}
 136}
 137
 138static void _analyzeForIdleLoop(struct GBA* gba, struct ARMCore* cpu, uint32_t address) {
 139	struct ARMInstructionInfo info;
 140	uint32_t nextAddress = address;
 141	memset(gba->taintedRegisters, 0, sizeof(gba->taintedRegisters));
 142	if (cpu->executionMode == MODE_THUMB) {
 143		while (true) {
 144			uint16_t opcode;
 145			LOAD_16(opcode, nextAddress & cpu->memory.activeMask, cpu->memory.activeRegion);
 146			ARMDecodeThumb(opcode, &info);
 147			switch (info.branchType) {
 148			case ARM_BRANCH_NONE:
 149				if (info.operandFormat & ARM_OPERAND_MEMORY_2) {
 150					if (info.mnemonic == ARM_MN_STR || gba->taintedRegisters[info.memory.baseReg]) {
 151						gba->idleDetectionStep = -1;
 152						return;
 153					}
 154					uint32_t loadAddress = gba->cachedRegisters[info.memory.baseReg];
 155					uint32_t offset = 0;
 156					if (info.memory.format & ARM_MEMORY_IMMEDIATE_OFFSET) {
 157						offset = info.memory.offset.immediate;
 158					} else if (info.memory.format & ARM_MEMORY_REGISTER_OFFSET) {
 159						int reg = info.memory.offset.reg;
 160						if (gba->cachedRegisters[reg]) {
 161							gba->idleDetectionStep = -1;
 162							return;
 163						}
 164						offset = gba->cachedRegisters[reg];
 165					}
 166					if (info.memory.format & ARM_MEMORY_OFFSET_SUBTRACT) {
 167						loadAddress -= offset;
 168					} else {
 169						loadAddress += offset;
 170					}
 171					if ((loadAddress >> BASE_OFFSET) == REGION_IO && !GBAIOIsReadConstant(loadAddress)) {
 172						gba->idleDetectionStep = -1;
 173						return;
 174					}
 175					if ((loadAddress >> BASE_OFFSET) < REGION_CART0 || (loadAddress >> BASE_OFFSET) > REGION_CART2_EX) {
 176						gba->taintedRegisters[info.op1.reg] = true;
 177					} else {
 178						switch (info.memory.width) {
 179						case 1:
 180							gba->cachedRegisters[info.op1.reg] = GBALoad8(cpu, loadAddress, 0);
 181							break;
 182						case 2:
 183							gba->cachedRegisters[info.op1.reg] = GBALoad16(cpu, loadAddress, 0);
 184							break;
 185						case 4:
 186							gba->cachedRegisters[info.op1.reg] = GBALoad32(cpu, loadAddress, 0);
 187							break;
 188						}
 189					}
 190				} else if (info.operandFormat & ARM_OPERAND_AFFECTED_1) {
 191					gba->taintedRegisters[info.op1.reg] = true;
 192				}
 193				nextAddress += WORD_SIZE_THUMB;
 194				break;
 195			case ARM_BRANCH:
 196				if ((uint32_t) info.op1.immediate + nextAddress + WORD_SIZE_THUMB * 2 == address) {
 197					gba->idleLoop = address;
 198					gba->idleOptimization = IDLE_LOOP_REMOVE;
 199				}
 200				gba->idleDetectionStep = -1;
 201				return;
 202			default:
 203				gba->idleDetectionStep = -1;
 204				return;
 205			}
 206		}
 207	} else {
 208		gba->idleDetectionStep = -1;
 209	}
 210}
 211
 212static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) {
 213	struct GBA* gba = (struct GBA*) cpu->master;
 214	struct GBAMemory* memory = &gba->memory;
 215
 216	int newRegion = address >> BASE_OFFSET;
 217	if (gba->idleOptimization >= IDLE_LOOP_REMOVE && memory->activeRegion != REGION_BIOS) {
 218		if (address == gba->idleLoop) {
 219			if (gba->haltPending) {
 220				gba->haltPending = false;
 221				GBAHalt(gba);
 222			} else {
 223				gba->haltPending = true;
 224			}
 225		} else if (gba->idleOptimization >= IDLE_LOOP_DETECT && newRegion == memory->activeRegion) {
 226			if (address == gba->lastJump) {
 227				switch (gba->idleDetectionStep) {
 228				case 0:
 229					memcpy(gba->cachedRegisters, cpu->gprs, sizeof(gba->cachedRegisters));
 230					++gba->idleDetectionStep;
 231					break;
 232				case 1:
 233					if (memcmp(gba->cachedRegisters, cpu->gprs, sizeof(gba->cachedRegisters))) {
 234						gba->idleDetectionStep = -1;
 235						++gba->idleDetectionFailures;
 236						if (gba->idleDetectionFailures > IDLE_LOOP_THRESHOLD) {
 237							gba->idleOptimization = IDLE_LOOP_IGNORE;
 238						}
 239						break;
 240					}
 241					_analyzeForIdleLoop(gba, cpu, address);
 242					break;
 243				}
 244			} else {
 245				gba->idleDetectionStep = 0;
 246			}
 247		}
 248	}
 249
 250	gba->lastJump = address;
 251	memory->lastPrefetchedPc = 0;
 252	if (newRegion == memory->activeRegion) {
 253		if (newRegion < REGION_CART0 || (address & (SIZE_CART0 - 1)) < memory->romSize) {
 254			return;
 255		}
 256		if (memory->mirroring && (address & memory->romMask) < memory->romSize) {
 257			return;
 258		}
 259	}
 260
 261	if (memory->activeRegion == REGION_BIOS) {
 262		memory->biosPrefetch = cpu->prefetch[1];
 263	}
 264	memory->activeRegion = newRegion;
 265	switch (newRegion) {
 266	case REGION_BIOS:
 267		cpu->memory.activeRegion = memory->bios;
 268		cpu->memory.activeMask = SIZE_BIOS - 1;
 269		break;
 270	case REGION_WORKING_RAM:
 271		cpu->memory.activeRegion = memory->wram;
 272		cpu->memory.activeMask = SIZE_WORKING_RAM - 1;
 273		break;
 274	case REGION_WORKING_IRAM:
 275		cpu->memory.activeRegion = memory->iwram;
 276		cpu->memory.activeMask = SIZE_WORKING_IRAM - 1;
 277		break;
 278	case REGION_PALETTE_RAM:
 279		cpu->memory.activeRegion = (uint32_t*) gba->video.palette;
 280		cpu->memory.activeMask = SIZE_PALETTE_RAM - 1;
 281		break;
 282	case REGION_VRAM:
 283		if (address & 0x10000) {
 284			cpu->memory.activeRegion = (uint32_t*) &gba->video.renderer->vram[0x8000];
 285			cpu->memory.activeMask = 0x00007FFF;
 286		} else {
 287			cpu->memory.activeRegion = (uint32_t*) gba->video.renderer->vram;
 288			cpu->memory.activeMask = 0x0000FFFF;
 289		}
 290		break;
 291	case REGION_OAM:
 292		cpu->memory.activeRegion = (uint32_t*) gba->video.oam.raw;
 293		cpu->memory.activeMask = SIZE_OAM - 1;
 294		break;
 295	case REGION_CART0:
 296	case REGION_CART0_EX:
 297	case REGION_CART1:
 298	case REGION_CART1_EX:
 299	case REGION_CART2:
 300	case REGION_CART2_EX:
 301		cpu->memory.activeRegion = memory->rom;
 302		cpu->memory.activeMask = memory->romMask;
 303		if ((address & (SIZE_CART0 - 1)) < memory->romSize) {
 304			break;
 305		}
 306	// Fall through
 307	default:
 308		memory->activeRegion = -1;
 309		cpu->memory.activeRegion = _deadbeef;
 310		cpu->memory.activeMask = 0;
 311		if (gba->yankedRomSize || !gba->hardCrash) {
 312			mLOG(GBA_MEM, GAME_ERROR, "Jumped to invalid address: %08X", address);
 313		} else if (gba->coreCallbacks && gba->coreCallbacks->coreCrashed) {
 314			mLOG(GBA_MEM, GAME_ERROR, "Jumped to invalid address: %08X", address);
 315			gba->coreCallbacks->coreCrashed(gba->coreCallbacks->context);
 316		} else {
 317			mLOG(GBA_MEM, FATAL, "Jumped to invalid address: %08X", address);
 318		}
 319		return;
 320	}
 321	cpu->memory.activeSeqCycles32 = memory->waitstatesSeq32[memory->activeRegion];
 322	cpu->memory.activeSeqCycles16 = memory->waitstatesSeq16[memory->activeRegion];
 323	cpu->memory.activeNonseqCycles32 = memory->waitstatesNonseq32[memory->activeRegion];
 324	cpu->memory.activeNonseqCycles16 = memory->waitstatesNonseq16[memory->activeRegion];
 325}
 326
 327#define LOAD_BAD \
 328	if (gba->performingDMA) { \
 329		value = gba->bus; \
 330	} else { \
 331		value = cpu->prefetch[1]; \
 332		if (cpu->executionMode == MODE_THUMB) { \
 333			/* http://ngemu.com/threads/gba-open-bus.170809/ */ \
 334			switch (cpu->gprs[ARM_PC] >> BASE_OFFSET) { \
 335			case REGION_BIOS: \
 336			case REGION_OAM: \
 337				/* This isn't right half the time, but we don't have $+6 handy */ \
 338				value <<= 16; \
 339				value |= cpu->prefetch[0]; \
 340				break; \
 341			case REGION_WORKING_IRAM: \
 342				/* This doesn't handle prefetch clobbering */ \
 343				if (cpu->gprs[ARM_PC] & 2) { \
 344					value |= cpu->prefetch[0] << 16; \
 345				} else { \
 346					value <<= 16; \
 347					value |= cpu->prefetch[0]; \
 348				} \
 349			default: \
 350				value |= value << 16; \
 351			} \
 352		} \
 353	}
 354
 355#define LOAD_BIOS \
 356	if (address < SIZE_BIOS) { \
 357		if (memory->activeRegion == REGION_BIOS) { \
 358			LOAD_32(value, address & -4, memory->bios); \
 359		} else { \
 360			mLOG(GBA_MEM, GAME_ERROR, "Bad BIOS Load32: 0x%08X", address); \
 361			value = memory->biosPrefetch; \
 362		} \
 363	} else { \
 364		mLOG(GBA_MEM, GAME_ERROR, "Bad memory Load32: 0x%08X", address); \
 365		LOAD_BAD; \
 366	}
 367
 368#define LOAD_WORKING_RAM \
 369	LOAD_32(value, address & (SIZE_WORKING_RAM - 4), memory->wram); \
 370	wait += waitstatesRegion[REGION_WORKING_RAM];
 371
 372#define LOAD_WORKING_IRAM LOAD_32(value, address & (SIZE_WORKING_IRAM - 4), memory->iwram);
 373#define LOAD_IO value = GBAIORead(gba, address & OFFSET_MASK & ~2) | (GBAIORead(gba, (address & OFFSET_MASK) | 2) << 16);
 374
 375#define LOAD_PALETTE_RAM \
 376	LOAD_32(value, address & (SIZE_PALETTE_RAM - 4), gba->video.palette); \
 377	wait += waitstatesRegion[REGION_PALETTE_RAM];
 378
 379#define LOAD_VRAM \
 380	if ((address & 0x0001FFFF) < SIZE_VRAM) { \
 381		LOAD_32(value, address & 0x0001FFFC, gba->video.renderer->vram); \
 382	} else { \
 383		LOAD_32(value, address & 0x00017FFC, gba->video.renderer->vram); \
 384	} \
 385	wait += waitstatesRegion[REGION_VRAM];
 386
 387#define LOAD_OAM LOAD_32(value, address & (SIZE_OAM - 4), gba->video.oam.raw);
 388
 389#define LOAD_CART \
 390	wait += waitstatesRegion[address >> BASE_OFFSET]; \
 391	if ((address & (SIZE_CART0 - 1)) < memory->romSize) { \
 392		LOAD_32(value, address & (SIZE_CART0 - 4), memory->rom); \
 393	} else if (memory->mirroring && (address & memory->romMask) < memory->romSize) { \
 394		LOAD_32(value, address & memory->romMask & -4, memory->rom); \
 395	} else if (memory->vfame.cartType) { \
 396		value = GBAVFameGetPatternValue(address, 32); \
 397	} else { \
 398		mLOG(GBA_MEM, GAME_ERROR, "Out of bounds ROM Load32: 0x%08X", address); \
 399		value = ((address & ~3) >> 1) & 0xFFFF; \
 400		value |= (((address & ~3) + 2) >> 1) << 16; \
 401	}
 402
 403#define LOAD_SRAM \
 404	wait = memory->waitstatesNonseq16[address >> BASE_OFFSET]; \
 405	value = GBALoad8(cpu, address, 0); \
 406	value |= value << 8; \
 407	value |= value << 16;
 408
 409uint32_t GBALoadBad(struct ARMCore* cpu) {
 410	struct GBA* gba = (struct GBA*) cpu->master;
 411	uint32_t value = 0;
 412	LOAD_BAD;
 413	return value;
 414}
 415
 416uint32_t GBALoad32(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
 417	struct GBA* gba = (struct GBA*) cpu->master;
 418	struct GBAMemory* memory = &gba->memory;
 419	uint32_t value = 0;
 420	int wait = 0;
 421	char* waitstatesRegion = memory->waitstatesNonseq32;
 422
 423	switch (address >> BASE_OFFSET) {
 424	case REGION_BIOS:
 425		LOAD_BIOS;
 426		break;
 427	case REGION_WORKING_RAM:
 428		LOAD_WORKING_RAM;
 429		break;
 430	case REGION_WORKING_IRAM:
 431		LOAD_WORKING_IRAM;
 432		break;
 433	case REGION_IO:
 434		LOAD_IO;
 435		break;
 436	case REGION_PALETTE_RAM:
 437		LOAD_PALETTE_RAM;
 438		break;
 439	case REGION_VRAM:
 440		LOAD_VRAM;
 441		break;
 442	case REGION_OAM:
 443		LOAD_OAM;
 444		break;
 445	case REGION_CART0:
 446	case REGION_CART0_EX:
 447	case REGION_CART1:
 448	case REGION_CART1_EX:
 449	case REGION_CART2:
 450	case REGION_CART2_EX:
 451		LOAD_CART;
 452		break;
 453	case REGION_CART_SRAM:
 454	case REGION_CART_SRAM_MIRROR:
 455		LOAD_SRAM;
 456		break;
 457	default:
 458		mLOG(GBA_MEM, GAME_ERROR, "Bad memory Load32: 0x%08X", address);
 459		LOAD_BAD;
 460		break;
 461	}
 462
 463	if (cycleCounter) {
 464		wait += 2;
 465		if (address >> BASE_OFFSET < REGION_CART0) {
 466			wait = GBAMemoryStall(cpu, wait);
 467		}
 468		*cycleCounter += wait;
 469	}
 470	// Unaligned 32-bit loads are "rotated" so they make some semblance of sense
 471	int rotate = (address & 3) << 3;
 472	return ROR(value, rotate);
 473}
 474
 475uint32_t GBALoad16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
 476	struct GBA* gba = (struct GBA*) cpu->master;
 477	struct GBAMemory* memory = &gba->memory;
 478	uint32_t value = 0;
 479	int wait = 0;
 480
 481	switch (address >> BASE_OFFSET) {
 482	case REGION_BIOS:
 483		if (address < SIZE_BIOS) {
 484			if (memory->activeRegion == REGION_BIOS) {
 485				LOAD_16(value, address & -2, memory->bios);
 486			} else {
 487				mLOG(GBA_MEM, GAME_ERROR, "Bad BIOS Load16: 0x%08X", address);
 488				value = (memory->biosPrefetch >> ((address & 2) * 8)) & 0xFFFF;
 489			}
 490		} else {
 491			mLOG(GBA_MEM, GAME_ERROR, "Bad memory Load16: 0x%08X", address);
 492			LOAD_BAD;
 493			value = (value >> ((address & 2) * 8)) & 0xFFFF;
 494		}
 495		break;
 496	case REGION_WORKING_RAM:
 497		LOAD_16(value, address & (SIZE_WORKING_RAM - 2), memory->wram);
 498		wait = memory->waitstatesNonseq16[REGION_WORKING_RAM];
 499		break;
 500	case REGION_WORKING_IRAM:
 501		LOAD_16(value, address & (SIZE_WORKING_IRAM - 2), memory->iwram);
 502		break;
 503	case REGION_IO:
 504		value = GBAIORead(gba, address & (OFFSET_MASK - 1));
 505		break;
 506	case REGION_PALETTE_RAM:
 507		LOAD_16(value, address & (SIZE_PALETTE_RAM - 2), gba->video.palette);
 508		break;
 509	case REGION_VRAM:
 510		if ((address & 0x0001FFFF) < SIZE_VRAM) {
 511			LOAD_16(value, address & 0x0001FFFE, gba->video.renderer->vram);
 512		} else {
 513			LOAD_16(value, address & 0x00017FFE, gba->video.renderer->vram);
 514		}
 515		break;
 516	case REGION_OAM:
 517		LOAD_16(value, address & (SIZE_OAM - 2), gba->video.oam.raw);
 518		break;
 519	case REGION_CART0:
 520	case REGION_CART0_EX:
 521	case REGION_CART1:
 522	case REGION_CART1_EX:
 523	case REGION_CART2:
 524		wait = memory->waitstatesNonseq16[address >> BASE_OFFSET];
 525		if ((address & (SIZE_CART0 - 1)) < memory->romSize) {
 526			LOAD_16(value, address & (SIZE_CART0 - 2), memory->rom);
 527		} else if (memory->mirroring && (address & memory->romMask) < memory->romSize) {
 528			LOAD_16(value, address & memory->romMask, memory->rom);
 529		} else if (memory->vfame.cartType) {
 530			value = GBAVFameGetPatternValue(address, 16);
 531		} else {
 532			mLOG(GBA_MEM, GAME_ERROR, "Out of bounds ROM Load16: 0x%08X", address);
 533			value = (address >> 1) & 0xFFFF;
 534		}
 535		break;
 536	case REGION_CART2_EX:
 537		wait = memory->waitstatesNonseq16[address >> BASE_OFFSET];
 538		if (memory->savedata.type == SAVEDATA_EEPROM) {
 539			value = GBASavedataReadEEPROM(&memory->savedata);
 540		} else if ((address & (SIZE_CART0 - 1)) < memory->romSize) {
 541			LOAD_16(value, address & (SIZE_CART0 - 2), memory->rom);
 542		} else if (memory->mirroring && (address & memory->romMask) < memory->romSize) {
 543			LOAD_16(value, address & memory->romMask, memory->rom);
 544		} else if (memory->vfame.cartType) {
 545			value = GBAVFameGetPatternValue(address, 16);
 546		} else {
 547			mLOG(GBA_MEM, GAME_ERROR, "Out of bounds ROM Load16: 0x%08X", address);
 548			value = (address >> 1) & 0xFFFF;
 549		}
 550		break;
 551	case REGION_CART_SRAM:
 552	case REGION_CART_SRAM_MIRROR:
 553		wait = memory->waitstatesNonseq16[address >> BASE_OFFSET];
 554		value = GBALoad8(cpu, address, 0);
 555		value |= value << 8;
 556		break;
 557	default:
 558		mLOG(GBA_MEM, GAME_ERROR, "Bad memory Load16: 0x%08X", address);
 559		LOAD_BAD;
 560		value = (value >> ((address & 2) * 8)) & 0xFFFF;
 561		break;
 562	}
 563
 564	if (cycleCounter) {
 565		wait += 2;
 566		if (address >> BASE_OFFSET < REGION_CART0) {
 567			wait = GBAMemoryStall(cpu, wait);
 568		}
 569		*cycleCounter += wait;
 570	}
 571	// Unaligned 16-bit loads are "unpredictable", but the GBA rotates them, so we have to, too.
 572	int rotate = (address & 1) << 3;
 573	return ROR(value, rotate);
 574}
 575
 576uint32_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
 577	struct GBA* gba = (struct GBA*) cpu->master;
 578	struct GBAMemory* memory = &gba->memory;
 579	uint32_t value = 0;
 580	int wait = 0;
 581
 582	switch (address >> BASE_OFFSET) {
 583	case REGION_BIOS:
 584		if (address < SIZE_BIOS) {
 585			if (memory->activeRegion == REGION_BIOS) {
 586				value = ((uint8_t*) memory->bios)[address];
 587			} else {
 588				mLOG(GBA_MEM, GAME_ERROR, "Bad BIOS Load8: 0x%08X", address);
 589				value = (memory->biosPrefetch >> ((address & 3) * 8)) & 0xFF;
 590			}
 591		} else {
 592			mLOG(GBA_MEM, GAME_ERROR, "Bad memory Load8: 0x%08x", address);
 593			LOAD_BAD;
 594			value = (value >> ((address & 3) * 8)) & 0xFF;
 595		}
 596		break;
 597	case REGION_WORKING_RAM:
 598		value = ((uint8_t*) memory->wram)[address & (SIZE_WORKING_RAM - 1)];
 599		wait = memory->waitstatesNonseq16[REGION_WORKING_RAM];
 600		break;
 601	case REGION_WORKING_IRAM:
 602		value = ((uint8_t*) memory->iwram)[address & (SIZE_WORKING_IRAM - 1)];
 603		break;
 604	case REGION_IO:
 605		value = (GBAIORead(gba, address & 0xFFFE) >> ((address & 0x0001) << 3)) & 0xFF;
 606		break;
 607	case REGION_PALETTE_RAM:
 608		value = ((uint8_t*) gba->video.palette)[address & (SIZE_PALETTE_RAM - 1)];
 609		break;
 610	case REGION_VRAM:
 611		if ((address & 0x0001FFFF) < SIZE_VRAM) {
 612			value = ((uint8_t*) gba->video.renderer->vram)[address & 0x0001FFFF];
 613		} else {
 614			value = ((uint8_t*) gba->video.renderer->vram)[address & 0x00017FFF];
 615		}
 616		break;
 617	case REGION_OAM:
 618		value = ((uint8_t*) gba->video.oam.raw)[address & (SIZE_OAM - 1)];
 619		break;
 620	case REGION_CART0:
 621	case REGION_CART0_EX:
 622	case REGION_CART1:
 623	case REGION_CART1_EX:
 624	case REGION_CART2:
 625	case REGION_CART2_EX:
 626		wait = memory->waitstatesNonseq16[address >> BASE_OFFSET];
 627		if ((address & (SIZE_CART0 - 1)) < memory->romSize) {
 628			value = ((uint8_t*) memory->rom)[address & (SIZE_CART0 - 1)];
 629		} else if (memory->mirroring && (address & memory->romMask) < memory->romSize) {
 630			value = ((uint8_t*) memory->rom)[address & memory->romMask];
 631		} else if (memory->vfame.cartType) {
 632			value = GBAVFameGetPatternValue(address, 8);
 633		} else {
 634			mLOG(GBA_MEM, GAME_ERROR, "Out of bounds ROM Load8: 0x%08X", address);
 635			value = (address >> 1) & 0xFF;
 636		}
 637		break;
 638	case REGION_CART_SRAM:
 639	case REGION_CART_SRAM_MIRROR:
 640		wait = memory->waitstatesNonseq16[address >> BASE_OFFSET];
 641		if (memory->savedata.type == SAVEDATA_AUTODETECT) {
 642			mLOG(GBA_MEM, INFO, "Detected SRAM savegame");
 643			GBASavedataInitSRAM(&memory->savedata);
 644		}
 645		if (gba->performingDMA == 1) {
 646			break;
 647		}
 648		if (memory->savedata.type == SAVEDATA_SRAM) {
 649			value = memory->savedata.data[address & (SIZE_CART_SRAM - 1)];
 650		} else if (memory->savedata.type == SAVEDATA_FLASH512 || memory->savedata.type == SAVEDATA_FLASH1M) {
 651			value = GBASavedataReadFlash(&memory->savedata, address);
 652		} else if (memory->hw.devices & HW_TILT) {
 653			value = GBAHardwareTiltRead(&memory->hw, address & OFFSET_MASK);
 654		} else {
 655			mLOG(GBA_MEM, GAME_ERROR, "Reading from non-existent SRAM: 0x%08X", address);
 656			value = 0xFF;
 657		}
 658		value &= 0xFF;
 659		break;
 660	default:
 661		mLOG(GBA_MEM, GAME_ERROR, "Bad memory Load8: 0x%08x", address);
 662		LOAD_BAD;
 663		value = (value >> ((address & 3) * 8)) & 0xFF;
 664		break;
 665	}
 666
 667	if (cycleCounter) {
 668		wait += 2;
 669		if (address >> BASE_OFFSET < REGION_CART0) {
 670			wait = GBAMemoryStall(cpu, wait);
 671		}
 672		*cycleCounter += wait;
 673	}
 674	return value;
 675}
 676
 677#define STORE_WORKING_RAM \
 678	STORE_32(value, address & (SIZE_WORKING_RAM - 4), memory->wram); \
 679	wait += waitstatesRegion[REGION_WORKING_RAM];
 680
 681#define STORE_WORKING_IRAM \
 682	STORE_32(value, address & (SIZE_WORKING_IRAM - 4), memory->iwram);
 683
 684#define STORE_IO \
 685	GBAIOWrite32(gba, address & (OFFSET_MASK - 3), value);
 686
 687#define STORE_PALETTE_RAM \
 688	STORE_32(value, address & (SIZE_PALETTE_RAM - 4), gba->video.palette); \
 689	gba->video.renderer->writePalette(gba->video.renderer, (address & (SIZE_PALETTE_RAM - 4)) + 2, value >> 16); \
 690	wait += waitstatesRegion[REGION_PALETTE_RAM]; \
 691	gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 4), value);
 692
 693#define STORE_VRAM \
 694	if ((address & 0x0001FFFF) < SIZE_VRAM) { \
 695		STORE_32(value, address & 0x0001FFFC, gba->video.renderer->vram); \
 696		gba->video.renderer->writeVRAM(gba->video.renderer, (address & 0x0001FFFC) + 2); \
 697		gba->video.renderer->writeVRAM(gba->video.renderer, (address & 0x0001FFFC)); \
 698	} else { \
 699		STORE_32(value, address & 0x00017FFC, gba->video.renderer->vram); \
 700		gba->video.renderer->writeVRAM(gba->video.renderer, (address & 0x00017FFC) + 2); \
 701		gba->video.renderer->writeVRAM(gba->video.renderer, (address & 0x00017FFC)); \
 702	} \
 703	wait += waitstatesRegion[REGION_VRAM];
 704
 705#define STORE_OAM \
 706	STORE_32(value, address & (SIZE_OAM - 4), gba->video.oam.raw); \
 707	gba->video.renderer->writeOAM(gba->video.renderer, (address & (SIZE_OAM - 4)) >> 1); \
 708	gba->video.renderer->writeOAM(gba->video.renderer, ((address & (SIZE_OAM - 4)) >> 1) + 1);
 709
 710#define STORE_CART \
 711	wait += waitstatesRegion[address >> BASE_OFFSET]; \
 712	mLOG(GBA_MEM, STUB, "Unimplemented memory Store32: 0x%08X", address);
 713
 714#define STORE_SRAM \
 715	if (address & 0x3) { \
 716		mLOG(GBA_MEM, GAME_ERROR, "Unaligned SRAM Store32: 0x%08X", address); \
 717		value = 0; \
 718	} \
 719	GBAStore8(cpu, address & ~0x3, value, cycleCounter); \
 720	GBAStore8(cpu, (address & ~0x3) | 1, value, cycleCounter); \
 721	GBAStore8(cpu, (address & ~0x3) | 2, value, cycleCounter); \
 722	GBAStore8(cpu, (address & ~0x3) | 3, value, cycleCounter);
 723
 724#define STORE_BAD \
 725	mLOG(GBA_MEM, GAME_ERROR, "Bad memory Store32: 0x%08X", address);
 726
 727void GBAStore32(struct ARMCore* cpu, uint32_t address, int32_t value, int* cycleCounter) {
 728	struct GBA* gba = (struct GBA*) cpu->master;
 729	struct GBAMemory* memory = &gba->memory;
 730	int wait = 0;
 731	char* waitstatesRegion = memory->waitstatesNonseq32;
 732
 733	switch (address >> BASE_OFFSET) {
 734	case REGION_WORKING_RAM:
 735		STORE_WORKING_RAM;
 736		break;
 737	case REGION_WORKING_IRAM:
 738		STORE_WORKING_IRAM
 739		break;
 740	case REGION_IO:
 741		STORE_IO;
 742		break;
 743	case REGION_PALETTE_RAM:
 744		STORE_PALETTE_RAM;
 745		break;
 746	case REGION_VRAM:
 747		STORE_VRAM;
 748		break;
 749	case REGION_OAM:
 750		STORE_OAM;
 751		break;
 752	case REGION_CART0:
 753	case REGION_CART0_EX:
 754	case REGION_CART1:
 755	case REGION_CART1_EX:
 756	case REGION_CART2:
 757	case REGION_CART2_EX:
 758		STORE_CART;
 759		break;
 760	case REGION_CART_SRAM:
 761	case REGION_CART_SRAM_MIRROR:
 762		STORE_SRAM;
 763		break;
 764	default:
 765		STORE_BAD;
 766		break;
 767	}
 768
 769	if (cycleCounter) {
 770		++wait;
 771		if (address >> BASE_OFFSET < REGION_CART0) {
 772			wait = GBAMemoryStall(cpu, wait);
 773		}
 774		*cycleCounter += wait;
 775	}
 776}
 777
 778void GBAStore16(struct ARMCore* cpu, uint32_t address, int16_t value, int* cycleCounter) {
 779	struct GBA* gba = (struct GBA*) cpu->master;
 780	struct GBAMemory* memory = &gba->memory;
 781	int wait = 0;
 782
 783	switch (address >> BASE_OFFSET) {
 784	case REGION_WORKING_RAM:
 785		STORE_16(value, address & (SIZE_WORKING_RAM - 2), memory->wram);
 786		wait = memory->waitstatesNonseq16[REGION_WORKING_RAM];
 787		break;
 788	case REGION_WORKING_IRAM:
 789		STORE_16(value, address & (SIZE_WORKING_IRAM - 2), memory->iwram);
 790		break;
 791	case REGION_IO:
 792		GBAIOWrite(gba, address & (OFFSET_MASK - 1), value);
 793		break;
 794	case REGION_PALETTE_RAM:
 795		STORE_16(value, address & (SIZE_PALETTE_RAM - 2), gba->video.palette);
 796		gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 2), value);
 797		break;
 798	case REGION_VRAM:
 799		if ((address & 0x0001FFFF) < SIZE_VRAM) {
 800			STORE_16(value, address & 0x0001FFFE, gba->video.renderer->vram);
 801			gba->video.renderer->writeVRAM(gba->video.renderer, address & 0x0001FFFE);
 802		} else {
 803			STORE_16(value, address & 0x00017FFE, gba->video.renderer->vram);
 804			gba->video.renderer->writeVRAM(gba->video.renderer, address & 0x00017FFE);
 805		}
 806		break;
 807	case REGION_OAM:
 808		STORE_16(value, address & (SIZE_OAM - 2), gba->video.oam.raw);
 809		gba->video.renderer->writeOAM(gba->video.renderer, (address & (SIZE_OAM - 2)) >> 1);
 810		break;
 811	case REGION_CART0:
 812		if (memory->hw.devices != HW_NONE && IS_GPIO_REGISTER(address & 0xFFFFFE)) {
 813			uint32_t reg = address & 0xFFFFFE;
 814			GBAHardwareGPIOWrite(&memory->hw, reg, value);
 815		} else {
 816			mLOG(GBA_MEM, GAME_ERROR, "Bad cartridge Store16: 0x%08X", address);
 817		}
 818		break;
 819	case REGION_CART2_EX:
 820		if (memory->savedata.type == SAVEDATA_AUTODETECT) {
 821			mLOG(GBA_MEM, INFO, "Detected EEPROM savegame");
 822			GBASavedataInitEEPROM(&memory->savedata, gba->realisticTiming);
 823		}
 824		GBASavedataWriteEEPROM(&memory->savedata, value, 1);
 825		break;
 826	case REGION_CART_SRAM:
 827	case REGION_CART_SRAM_MIRROR:
 828		GBAStore8(cpu, (address & ~0x1), value, cycleCounter);
 829		GBAStore8(cpu, (address & ~0x1) | 1, value, cycleCounter);
 830		break;
 831	default:
 832		mLOG(GBA_MEM, GAME_ERROR, "Bad memory Store16: 0x%08X", address);
 833		break;
 834	}
 835
 836	if (cycleCounter) {
 837		++wait;
 838		if (address >> BASE_OFFSET < REGION_CART0) {
 839			wait = GBAMemoryStall(cpu, wait);
 840		}
 841		*cycleCounter += wait;
 842	}
 843}
 844
 845void GBAStore8(struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCounter) {
 846	struct GBA* gba = (struct GBA*) cpu->master;
 847	struct GBAMemory* memory = &gba->memory;
 848	int wait = 0;
 849
 850	switch (address >> BASE_OFFSET) {
 851	case REGION_WORKING_RAM:
 852		((int8_t*) memory->wram)[address & (SIZE_WORKING_RAM - 1)] = value;
 853		wait = memory->waitstatesNonseq16[REGION_WORKING_RAM];
 854		break;
 855	case REGION_WORKING_IRAM:
 856		((int8_t*) memory->iwram)[address & (SIZE_WORKING_IRAM - 1)] = value;
 857		break;
 858	case REGION_IO:
 859		GBAIOWrite8(gba, address & OFFSET_MASK, value);
 860		break;
 861	case REGION_PALETTE_RAM:
 862		GBAStore16(cpu, address & ~1, ((uint8_t) value) | ((uint8_t) value << 8), cycleCounter);
 863		break;
 864	case REGION_VRAM:
 865		if ((address & 0x0001FFFF) >= ((GBARegisterDISPCNTGetMode(gba->memory.io[REG_DISPCNT >> 1]) == 4) ? 0x00014000 : 0x00010000)) {
 866			// TODO: check BG mode
 867			mLOG(GBA_MEM, GAME_ERROR, "Cannot Store8 to OBJ: 0x%08X", address);
 868			break;
 869		}
 870		gba->video.renderer->vram[(address & 0x1FFFE) >> 1] = ((uint8_t) value) | (value << 8);
 871		gba->video.renderer->writeVRAM(gba->video.renderer, address & 0x0001FFFE);
 872		break;
 873	case REGION_OAM:
 874		mLOG(GBA_MEM, GAME_ERROR, "Cannot Store8 to OAM: 0x%08X", address);
 875		break;
 876	case REGION_CART0:
 877		mLOG(GBA_MEM, STUB, "Unimplemented memory Store8: 0x%08X", address);
 878		break;
 879	case REGION_CART_SRAM:
 880	case REGION_CART_SRAM_MIRROR:
 881		if (memory->savedata.type == SAVEDATA_AUTODETECT) {
 882			if (address == SAVEDATA_FLASH_BASE) {
 883				mLOG(GBA_MEM, INFO, "Detected Flash savegame");
 884				GBASavedataInitFlash(&memory->savedata, gba->realisticTiming);
 885			} else {
 886				mLOG(GBA_MEM, INFO, "Detected SRAM savegame");
 887				GBASavedataInitSRAM(&memory->savedata);
 888			}
 889		}
 890		if (memory->savedata.type == SAVEDATA_FLASH512 || memory->savedata.type == SAVEDATA_FLASH1M) {
 891			GBASavedataWriteFlash(&memory->savedata, address, value);
 892		} else if (memory->savedata.type == SAVEDATA_SRAM) {
 893			if (memory->vfame.cartType) {
 894				GBAVFameSramWrite(&memory->vfame, address, value, memory->savedata.data);
 895			} else {
 896				memory->savedata.data[address & (SIZE_CART_SRAM - 1)] = value;
 897			}
 898			memory->savedata.dirty |= SAVEDATA_DIRT_NEW;
 899		} else if (memory->hw.devices & HW_TILT) {
 900			GBAHardwareTiltWrite(&memory->hw, address & OFFSET_MASK, value);
 901		} else {
 902			mLOG(GBA_MEM, GAME_ERROR, "Writing to non-existent SRAM: 0x%08X", address);
 903		}
 904		wait = memory->waitstatesNonseq16[REGION_CART_SRAM];
 905		break;
 906	default:
 907		mLOG(GBA_MEM, GAME_ERROR, "Bad memory Store8: 0x%08X", address);
 908		break;
 909	}
 910
 911	if (cycleCounter) {
 912		++wait;
 913		if (address >> BASE_OFFSET < REGION_CART0) {
 914			wait = GBAMemoryStall(cpu, wait);
 915		}
 916		*cycleCounter += wait;
 917	}
 918}
 919
 920uint32_t GBAView32(struct ARMCore* cpu, uint32_t address) {
 921	struct GBA* gba = (struct GBA*) cpu->master;
 922	uint32_t value = 0;
 923	address &= ~3;
 924	switch (address >> BASE_OFFSET) {
 925	case REGION_BIOS:
 926		if (address < SIZE_BIOS) {
 927			LOAD_32(value, address, gba->memory.bios);
 928		}
 929		break;
 930	case REGION_WORKING_RAM:
 931	case REGION_WORKING_IRAM:
 932	case REGION_PALETTE_RAM:
 933	case REGION_VRAM:
 934	case REGION_OAM:
 935	case REGION_CART0:
 936	case REGION_CART0_EX:
 937	case REGION_CART1:
 938	case REGION_CART1_EX:
 939	case REGION_CART2:
 940	case REGION_CART2_EX:
 941		value = GBALoad32(cpu, address, 0);
 942		break;
 943	case REGION_IO:
 944		if ((address & OFFSET_MASK) < REG_MAX) {
 945			value = gba->memory.io[(address & OFFSET_MASK) >> 1];
 946			value |= gba->memory.io[((address & OFFSET_MASK) >> 1) + 1] << 16;
 947		}
 948		break;
 949	case REGION_CART_SRAM:
 950		value = GBALoad8(cpu, address, 0);
 951		value |= GBALoad8(cpu, address + 1, 0) << 8;
 952		value |= GBALoad8(cpu, address + 2, 0) << 16;
 953		value |= GBALoad8(cpu, address + 3, 0) << 24;
 954		break;
 955	default:
 956		break;
 957	}
 958	return value;
 959}
 960
 961uint16_t GBAView16(struct ARMCore* cpu, uint32_t address) {
 962	struct GBA* gba = (struct GBA*) cpu->master;
 963	uint16_t value = 0;
 964	address &= ~1;
 965	switch (address >> BASE_OFFSET) {
 966	case REGION_BIOS:
 967		if (address < SIZE_BIOS) {
 968			LOAD_16(value, address, gba->memory.bios);
 969		}
 970		break;
 971	case REGION_WORKING_RAM:
 972	case REGION_WORKING_IRAM:
 973	case REGION_PALETTE_RAM:
 974	case REGION_VRAM:
 975	case REGION_OAM:
 976	case REGION_CART0:
 977	case REGION_CART0_EX:
 978	case REGION_CART1:
 979	case REGION_CART1_EX:
 980	case REGION_CART2:
 981	case REGION_CART2_EX:
 982		value = GBALoad16(cpu, address, 0);
 983		break;
 984	case REGION_IO:
 985		if ((address & OFFSET_MASK) < REG_MAX) {
 986			value = gba->memory.io[(address & OFFSET_MASK) >> 1];
 987		}
 988		break;
 989	case REGION_CART_SRAM:
 990		value = GBALoad8(cpu, address, 0);
 991		value |= GBALoad8(cpu, address + 1, 0) << 8;
 992		break;
 993	default:
 994		break;
 995	}
 996	return value;
 997}
 998
 999uint8_t GBAView8(struct ARMCore* cpu, uint32_t address) {
1000	struct GBA* gba = (struct GBA*) cpu->master;
1001	uint8_t value = 0;
1002	switch (address >> BASE_OFFSET) {
1003	case REGION_BIOS:
1004		if (address < SIZE_BIOS) {
1005			value = ((uint8_t*) gba->memory.bios)[address];
1006		}
1007		break;
1008	case REGION_WORKING_RAM:
1009	case REGION_WORKING_IRAM:
1010	case REGION_CART0:
1011	case REGION_CART0_EX:
1012	case REGION_CART1:
1013	case REGION_CART1_EX:
1014	case REGION_CART2:
1015	case REGION_CART2_EX:
1016	case REGION_CART_SRAM:
1017		value = GBALoad8(cpu, address, 0);
1018		break;
1019	case REGION_IO:
1020	case REGION_PALETTE_RAM:
1021	case REGION_VRAM:
1022	case REGION_OAM:
1023		value = GBAView16(cpu, address) >> ((address & 1) * 8);
1024		break;
1025	default:
1026		break;
1027	}
1028	return value;
1029}
1030
1031void GBAPatch32(struct ARMCore* cpu, uint32_t address, int32_t value, int32_t* old) {
1032	struct GBA* gba = (struct GBA*) cpu->master;
1033	struct GBAMemory* memory = &gba->memory;
1034	int32_t oldValue = -1;
1035
1036	switch (address >> BASE_OFFSET) {
1037	case REGION_WORKING_RAM:
1038		LOAD_32(oldValue, address & (SIZE_WORKING_RAM - 4), memory->wram);
1039		STORE_32(value, address & (SIZE_WORKING_RAM - 4), memory->wram);
1040		break;
1041	case REGION_WORKING_IRAM:
1042		LOAD_32(oldValue, address & (SIZE_WORKING_IRAM - 4), memory->iwram);
1043		STORE_32(value, address & (SIZE_WORKING_IRAM - 4), memory->iwram);
1044		break;
1045	case REGION_IO:
1046		mLOG(GBA_MEM, STUB, "Unimplemented memory Patch32: 0x%08X", address);
1047		break;
1048	case REGION_PALETTE_RAM:
1049		LOAD_32(oldValue, address & (SIZE_PALETTE_RAM - 1), gba->video.palette);
1050		STORE_32(value, address & (SIZE_PALETTE_RAM - 4), gba->video.palette);
1051		gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 4), value);
1052		gba->video.renderer->writePalette(gba->video.renderer, (address & (SIZE_PALETTE_RAM - 4)) + 2, value >> 16);
1053		break;
1054	case REGION_VRAM:
1055		if ((address & 0x0001FFFF) < SIZE_VRAM) {
1056			LOAD_32(oldValue, address & 0x0001FFFC, gba->video.renderer->vram);
1057			STORE_32(value, address & 0x0001FFFC, gba->video.renderer->vram);
1058		} else {
1059			LOAD_32(oldValue, address & 0x00017FFC, gba->video.renderer->vram);
1060			STORE_32(value, address & 0x00017FFC, gba->video.renderer->vram);
1061		}
1062		break;
1063	case REGION_OAM:
1064		LOAD_32(oldValue, address & (SIZE_OAM - 4), gba->video.oam.raw);
1065		STORE_32(value, address & (SIZE_OAM - 4), gba->video.oam.raw);
1066		gba->video.renderer->writeOAM(gba->video.renderer, (address & (SIZE_OAM - 4)) >> 1);
1067		gba->video.renderer->writeOAM(gba->video.renderer, ((address & (SIZE_OAM - 4)) + 2) >> 1);
1068		break;
1069	case REGION_CART0:
1070	case REGION_CART0_EX:
1071	case REGION_CART1:
1072	case REGION_CART1_EX:
1073	case REGION_CART2:
1074	case REGION_CART2_EX:
1075		_pristineCow(gba);
1076		if ((address & (SIZE_CART0 - 4)) >= gba->memory.romSize) {
1077			gba->memory.romSize = (address & (SIZE_CART0 - 4)) + 4;
1078			gba->memory.romMask = toPow2(gba->memory.romSize) - 1;
1079		}
1080		LOAD_32(oldValue, address & (SIZE_CART0 - 4), gba->memory.rom);
1081		STORE_32(value, address & (SIZE_CART0 - 4), gba->memory.rom);
1082		break;
1083	case REGION_CART_SRAM:
1084	case REGION_CART_SRAM_MIRROR:
1085		if (memory->savedata.type == SAVEDATA_SRAM) {
1086			LOAD_32(oldValue, address & (SIZE_CART_SRAM - 4), memory->savedata.data);
1087			STORE_32(value, address & (SIZE_CART_SRAM - 4), memory->savedata.data);
1088		} else {
1089			mLOG(GBA_MEM, GAME_ERROR, "Writing to non-existent SRAM: 0x%08X", address);
1090		}
1091		break;
1092	default:
1093		mLOG(GBA_MEM, WARN, "Bad memory Patch16: 0x%08X", address);
1094		break;
1095	}
1096	if (old) {
1097		*old = oldValue;
1098	}
1099}
1100
1101void GBAPatch16(struct ARMCore* cpu, uint32_t address, int16_t value, int16_t* old) {
1102	struct GBA* gba = (struct GBA*) cpu->master;
1103	struct GBAMemory* memory = &gba->memory;
1104	int16_t oldValue = -1;
1105
1106	switch (address >> BASE_OFFSET) {
1107	case REGION_WORKING_RAM:
1108		LOAD_16(oldValue, address & (SIZE_WORKING_RAM - 2), memory->wram);
1109		STORE_16(value, address & (SIZE_WORKING_RAM - 2), memory->wram);
1110		break;
1111	case REGION_WORKING_IRAM:
1112		LOAD_16(oldValue, address & (SIZE_WORKING_IRAM - 2), memory->iwram);
1113		STORE_16(value, address & (SIZE_WORKING_IRAM - 2), memory->iwram);
1114		break;
1115	case REGION_IO:
1116		mLOG(GBA_MEM, STUB, "Unimplemented memory Patch16: 0x%08X", address);
1117		break;
1118	case REGION_PALETTE_RAM:
1119		LOAD_16(oldValue, address & (SIZE_PALETTE_RAM - 2), gba->video.palette);
1120		STORE_16(value, address & (SIZE_PALETTE_RAM - 2), gba->video.palette);
1121		gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 2), value);
1122		break;
1123	case REGION_VRAM:
1124		if ((address & 0x0001FFFF) < SIZE_VRAM) {
1125			LOAD_16(oldValue, address & 0x0001FFFE, gba->video.renderer->vram);
1126			STORE_16(value, address & 0x0001FFFE, gba->video.renderer->vram);
1127		} else {
1128			LOAD_16(oldValue, address & 0x00017FFE, gba->video.renderer->vram);
1129			STORE_16(value, address & 0x00017FFE, gba->video.renderer->vram);
1130		}
1131		break;
1132	case REGION_OAM:
1133		LOAD_16(oldValue, address & (SIZE_OAM - 2), gba->video.oam.raw);
1134		STORE_16(value, address & (SIZE_OAM - 2), gba->video.oam.raw);
1135		gba->video.renderer->writeOAM(gba->video.renderer, (address & (SIZE_OAM - 2)) >> 1);
1136		break;
1137	case REGION_CART0:
1138	case REGION_CART0_EX:
1139	case REGION_CART1:
1140	case REGION_CART1_EX:
1141	case REGION_CART2:
1142	case REGION_CART2_EX:
1143		_pristineCow(gba);
1144		if ((address & (SIZE_CART0 - 1)) >= gba->memory.romSize) {
1145			gba->memory.romSize = (address & (SIZE_CART0 - 2)) + 2;
1146			gba->memory.romMask = toPow2(gba->memory.romSize) - 1;
1147		}
1148		LOAD_16(oldValue, address & (SIZE_CART0 - 2), gba->memory.rom);
1149		STORE_16(value, address & (SIZE_CART0 - 2), gba->memory.rom);
1150		break;
1151	case REGION_CART_SRAM:
1152	case REGION_CART_SRAM_MIRROR:
1153		if (memory->savedata.type == SAVEDATA_SRAM) {
1154			LOAD_16(oldValue, address & (SIZE_CART_SRAM - 2), memory->savedata.data);
1155			STORE_16(value, address & (SIZE_CART_SRAM - 2), memory->savedata.data);
1156		} else {
1157			mLOG(GBA_MEM, GAME_ERROR, "Writing to non-existent SRAM: 0x%08X", address);
1158		}
1159		break;
1160	default:
1161		mLOG(GBA_MEM, WARN, "Bad memory Patch16: 0x%08X", address);
1162		break;
1163	}
1164	if (old) {
1165		*old = oldValue;
1166	}
1167}
1168
1169void GBAPatch8(struct ARMCore* cpu, uint32_t address, int8_t value, int8_t* old) {
1170	struct GBA* gba = (struct GBA*) cpu->master;
1171	struct GBAMemory* memory = &gba->memory;
1172	int8_t oldValue = -1;
1173
1174	switch (address >> BASE_OFFSET) {
1175	case REGION_WORKING_RAM:
1176		oldValue = ((int8_t*) memory->wram)[address & (SIZE_WORKING_RAM - 1)];
1177		((int8_t*) memory->wram)[address & (SIZE_WORKING_RAM - 1)] = value;
1178		break;
1179	case REGION_WORKING_IRAM:
1180		oldValue = ((int8_t*) memory->iwram)[address & (SIZE_WORKING_IRAM - 1)];
1181		((int8_t*) memory->iwram)[address & (SIZE_WORKING_IRAM - 1)] = value;
1182		break;
1183	case REGION_IO:
1184		mLOG(GBA_MEM, STUB, "Unimplemented memory Patch8: 0x%08X", address);
1185		break;
1186	case REGION_PALETTE_RAM:
1187		mLOG(GBA_MEM, STUB, "Unimplemented memory Patch8: 0x%08X", address);
1188		break;
1189	case REGION_VRAM:
1190		mLOG(GBA_MEM, STUB, "Unimplemented memory Patch8: 0x%08X", address);
1191		break;
1192	case REGION_OAM:
1193		mLOG(GBA_MEM, STUB, "Unimplemented memory Patch8: 0x%08X", address);
1194		break;
1195	case REGION_CART0:
1196	case REGION_CART0_EX:
1197	case REGION_CART1:
1198	case REGION_CART1_EX:
1199	case REGION_CART2:
1200	case REGION_CART2_EX:
1201		_pristineCow(gba);
1202		if ((address & (SIZE_CART0 - 1)) >= gba->memory.romSize) {
1203			gba->memory.romSize = (address & (SIZE_CART0 - 2)) + 2;
1204			gba->memory.romMask = toPow2(gba->memory.romSize) - 1;
1205		}
1206		oldValue = ((int8_t*) memory->rom)[address & (SIZE_CART0 - 1)];
1207		((int8_t*) memory->rom)[address & (SIZE_CART0 - 1)] = value;
1208		break;
1209	case REGION_CART_SRAM:
1210	case REGION_CART_SRAM_MIRROR:
1211		if (memory->savedata.type == SAVEDATA_SRAM) {
1212			oldValue = ((int8_t*) memory->savedata.data)[address & (SIZE_CART_SRAM - 1)];
1213			((int8_t*) memory->savedata.data)[address & (SIZE_CART_SRAM - 1)] = value;
1214		} else {
1215			mLOG(GBA_MEM, GAME_ERROR, "Writing to non-existent SRAM: 0x%08X", address);
1216		}
1217		break;
1218	default:
1219		mLOG(GBA_MEM, WARN, "Bad memory Patch8: 0x%08X", address);
1220		break;
1221	}
1222	if (old) {
1223		*old = oldValue;
1224	}
1225}
1226
1227#define LDM_LOOP(LDM) \
1228	for (i = 0; i < 16; i += 4) { \
1229		if (UNLIKELY(mask & (1 << i))) { \
1230			LDM; \
1231			cpu->gprs[i] = value; \
1232			++wait; \
1233			address += 4; \
1234		} \
1235		if (UNLIKELY(mask & (2 << i))) { \
1236			LDM; \
1237			cpu->gprs[i + 1] = value; \
1238			++wait; \
1239			address += 4; \
1240		} \
1241		if (UNLIKELY(mask & (4 << i))) { \
1242			LDM; \
1243			cpu->gprs[i + 2] = value; \
1244			++wait; \
1245			address += 4; \
1246		} \
1247		if (UNLIKELY(mask & (8 << i))) { \
1248			LDM; \
1249			cpu->gprs[i + 3] = value; \
1250			++wait; \
1251			address += 4; \
1252		} \
1253	}
1254
1255uint32_t GBALoadMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum LSMDirection direction, int* cycleCounter) {
1256	struct GBA* gba = (struct GBA*) cpu->master;
1257	struct GBAMemory* memory = &gba->memory;
1258	uint32_t value;
1259	char* waitstatesRegion = memory->waitstatesSeq32;
1260
1261	int i;
1262	int offset = 4;
1263	int popcount = 0;
1264	if (direction & LSM_D) {
1265		offset = -4;
1266		popcount = popcount32(mask);
1267		address -= (popcount << 2) - 4;
1268	}
1269
1270	if (direction & LSM_B) {
1271		address += offset;
1272	}
1273
1274	uint32_t addressMisalign = address & 0x3;
1275	int region = address >> BASE_OFFSET;
1276	if (region < REGION_CART_SRAM) {
1277		address &= 0xFFFFFFFC;
1278	}
1279	int wait = memory->waitstatesSeq32[region] - memory->waitstatesNonseq32[region];
1280
1281	switch (region) {
1282	case REGION_BIOS:
1283		LDM_LOOP(LOAD_BIOS);
1284		break;
1285	case REGION_WORKING_RAM:
1286		LDM_LOOP(LOAD_WORKING_RAM);
1287		break;
1288	case REGION_WORKING_IRAM:
1289		LDM_LOOP(LOAD_WORKING_IRAM);
1290		break;
1291	case REGION_IO:
1292		LDM_LOOP(LOAD_IO);
1293		break;
1294	case REGION_PALETTE_RAM:
1295		LDM_LOOP(LOAD_PALETTE_RAM);
1296		break;
1297	case REGION_VRAM:
1298		LDM_LOOP(LOAD_VRAM);
1299		break;
1300	case REGION_OAM:
1301		LDM_LOOP(LOAD_OAM);
1302		break;
1303	case REGION_CART0:
1304	case REGION_CART0_EX:
1305	case REGION_CART1:
1306	case REGION_CART1_EX:
1307	case REGION_CART2:
1308	case REGION_CART2_EX:
1309		LDM_LOOP(LOAD_CART);
1310		break;
1311	case REGION_CART_SRAM:
1312	case REGION_CART_SRAM_MIRROR:
1313		LDM_LOOP(LOAD_SRAM);
1314		break;
1315	default:
1316		LDM_LOOP(LOAD_BAD);
1317		break;
1318	}
1319
1320	if (cycleCounter) {
1321		++wait;
1322		if (address >> BASE_OFFSET < REGION_CART0) {
1323			wait = GBAMemoryStall(cpu, wait);
1324		}
1325		*cycleCounter += wait;
1326	}
1327
1328	if (direction & LSM_B) {
1329		address -= offset;
1330	}
1331
1332	if (direction & LSM_D) {
1333		address -= (popcount << 2) + 4;
1334	}
1335
1336	return address | addressMisalign;
1337}
1338
1339#define STM_LOOP(STM) \
1340	for (i = 0; i < 16; i += 4) { \
1341		if (UNLIKELY(mask & (1 << i))) { \
1342			value = cpu->gprs[i]; \
1343			STM; \
1344			++wait; \
1345			address += 4; \
1346		} \
1347		if (UNLIKELY(mask & (2 << i))) { \
1348			value = cpu->gprs[i + 1]; \
1349			STM; \
1350			++wait; \
1351			address += 4; \
1352		} \
1353		if (UNLIKELY(mask & (4 << i))) { \
1354			value = cpu->gprs[i + 2]; \
1355			STM; \
1356			++wait; \
1357			address += 4; \
1358		} \
1359		if (UNLIKELY(mask & (8 << i))) { \
1360			value = cpu->gprs[i + 3]; \
1361			if (i + 3 == ARM_PC) { \
1362				value += WORD_SIZE_ARM; \
1363			} \
1364			STM; \
1365			++wait; \
1366			address += 4; \
1367		} \
1368	}
1369
1370uint32_t GBAStoreMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum LSMDirection direction, int* cycleCounter) {
1371	struct GBA* gba = (struct GBA*) cpu->master;
1372	struct GBAMemory* memory = &gba->memory;
1373	uint32_t value;
1374	char* waitstatesRegion = memory->waitstatesSeq32;
1375
1376	int i;
1377	int offset = 4;
1378	int popcount = 0;
1379	if (direction & LSM_D) {
1380		offset = -4;
1381		popcount = popcount32(mask);
1382		address -= (popcount << 2) - 4;
1383	}
1384
1385	if (direction & LSM_B) {
1386		address += offset;
1387	}
1388
1389	uint32_t addressMisalign = address & 0x3;
1390	int region = address >> BASE_OFFSET;
1391	if (region < REGION_CART_SRAM) {
1392		address &= 0xFFFFFFFC;
1393	}
1394	int wait = memory->waitstatesSeq32[region] - memory->waitstatesNonseq32[region];
1395
1396	switch (region) {
1397	case REGION_WORKING_RAM:
1398		STM_LOOP(STORE_WORKING_RAM);
1399		break;
1400	case REGION_WORKING_IRAM:
1401		STM_LOOP(STORE_WORKING_IRAM);
1402		break;
1403	case REGION_IO:
1404		STM_LOOP(STORE_IO);
1405		break;
1406	case REGION_PALETTE_RAM:
1407		STM_LOOP(STORE_PALETTE_RAM);
1408		break;
1409	case REGION_VRAM:
1410		STM_LOOP(STORE_VRAM);
1411		break;
1412	case REGION_OAM:
1413		STM_LOOP(STORE_OAM);
1414		break;
1415	case REGION_CART0:
1416	case REGION_CART0_EX:
1417	case REGION_CART1:
1418	case REGION_CART1_EX:
1419	case REGION_CART2:
1420	case REGION_CART2_EX:
1421		STM_LOOP(STORE_CART);
1422		break;
1423	case REGION_CART_SRAM:
1424	case REGION_CART_SRAM_MIRROR:
1425		STM_LOOP(STORE_SRAM);
1426		break;
1427	default:
1428		STM_LOOP(STORE_BAD);
1429		break;
1430	}
1431
1432	if (cycleCounter) {
1433		if (address >> BASE_OFFSET < REGION_CART0) {
1434			wait = GBAMemoryStall(cpu, wait);
1435		}
1436		*cycleCounter += wait;
1437	}
1438
1439	if (direction & LSM_B) {
1440		address -= offset;
1441	}
1442
1443	if (direction & LSM_D) {
1444		address -= (popcount << 2) + 4;
1445	}
1446
1447	return address | addressMisalign;
1448}
1449
1450void GBAAdjustWaitstates(struct GBA* gba, uint16_t parameters) {
1451	struct GBAMemory* memory = &gba->memory;
1452	struct ARMCore* cpu = gba->cpu;
1453	int sram = parameters & 0x0003;
1454	int ws0 = (parameters & 0x000C) >> 2;
1455	int ws0seq = (parameters & 0x0010) >> 4;
1456	int ws1 = (parameters & 0x0060) >> 5;
1457	int ws1seq = (parameters & 0x0080) >> 7;
1458	int ws2 = (parameters & 0x0300) >> 8;
1459	int ws2seq = (parameters & 0x0400) >> 10;
1460	int prefetch = parameters & 0x4000;
1461
1462	memory->waitstatesNonseq16[REGION_CART_SRAM] = memory->waitstatesNonseq16[REGION_CART_SRAM_MIRROR] = GBA_ROM_WAITSTATES[sram];
1463	memory->waitstatesSeq16[REGION_CART_SRAM] = memory->waitstatesSeq16[REGION_CART_SRAM_MIRROR] = GBA_ROM_WAITSTATES[sram];
1464	memory->waitstatesNonseq32[REGION_CART_SRAM] = memory->waitstatesNonseq32[REGION_CART_SRAM_MIRROR] = 2 * GBA_ROM_WAITSTATES[sram] + 1;
1465	memory->waitstatesSeq32[REGION_CART_SRAM] = memory->waitstatesSeq32[REGION_CART_SRAM_MIRROR] = 2 * GBA_ROM_WAITSTATES[sram] + 1;
1466
1467	memory->waitstatesNonseq16[REGION_CART0] = memory->waitstatesNonseq16[REGION_CART0_EX] = GBA_ROM_WAITSTATES[ws0];
1468	memory->waitstatesNonseq16[REGION_CART1] = memory->waitstatesNonseq16[REGION_CART1_EX] = GBA_ROM_WAITSTATES[ws1];
1469	memory->waitstatesNonseq16[REGION_CART2] = memory->waitstatesNonseq16[REGION_CART2_EX] = GBA_ROM_WAITSTATES[ws2];
1470
1471	memory->waitstatesSeq16[REGION_CART0] = memory->waitstatesSeq16[REGION_CART0_EX] = GBA_ROM_WAITSTATES_SEQ[ws0seq];
1472	memory->waitstatesSeq16[REGION_CART1] = memory->waitstatesSeq16[REGION_CART1_EX] = GBA_ROM_WAITSTATES_SEQ[ws1seq + 2];
1473	memory->waitstatesSeq16[REGION_CART2] = memory->waitstatesSeq16[REGION_CART2_EX] = GBA_ROM_WAITSTATES_SEQ[ws2seq + 4];
1474
1475	memory->waitstatesNonseq32[REGION_CART0] = memory->waitstatesNonseq32[REGION_CART0_EX] = memory->waitstatesNonseq16[REGION_CART0] + 1 + memory->waitstatesSeq16[REGION_CART0];
1476	memory->waitstatesNonseq32[REGION_CART1] = memory->waitstatesNonseq32[REGION_CART1_EX] = memory->waitstatesNonseq16[REGION_CART1] + 1 + memory->waitstatesSeq16[REGION_CART1];
1477	memory->waitstatesNonseq32[REGION_CART2] = memory->waitstatesNonseq32[REGION_CART2_EX] = memory->waitstatesNonseq16[REGION_CART2] + 1 + memory->waitstatesSeq16[REGION_CART2];
1478
1479	memory->waitstatesSeq32[REGION_CART0] = memory->waitstatesSeq32[REGION_CART0_EX] = 2 * memory->waitstatesSeq16[REGION_CART0] + 1;
1480	memory->waitstatesSeq32[REGION_CART1] = memory->waitstatesSeq32[REGION_CART1_EX] = 2 * memory->waitstatesSeq16[REGION_CART1] + 1;
1481	memory->waitstatesSeq32[REGION_CART2] = memory->waitstatesSeq32[REGION_CART2_EX] = 2 * memory->waitstatesSeq16[REGION_CART2] + 1;
1482
1483	memory->prefetch = prefetch;
1484
1485	cpu->memory.activeSeqCycles32 = memory->waitstatesSeq32[memory->activeRegion];
1486	cpu->memory.activeSeqCycles16 = memory->waitstatesSeq16[memory->activeRegion];
1487
1488	cpu->memory.activeNonseqCycles32 = memory->waitstatesNonseq32[memory->activeRegion];
1489	cpu->memory.activeNonseqCycles16 = memory->waitstatesNonseq16[memory->activeRegion];
1490}
1491
1492static bool _isValidDMASAD(int dma, uint32_t address) {
1493	if (dma == 0 && address >= BASE_CART0 && address < BASE_CART_SRAM) {
1494		return false;
1495	}
1496	return address >= BASE_WORKING_RAM;
1497}
1498
1499static bool _isValidDMADAD(int dma, uint32_t address) {
1500	return dma == 3 || address < BASE_CART0;
1501}
1502
1503uint32_t GBAMemoryWriteDMASAD(struct GBA* gba, int dma, uint32_t address) {
1504	struct GBAMemory* memory = &gba->memory;
1505	address &= 0x0FFFFFFE;
1506	if (_isValidDMASAD(dma, address)) {
1507		memory->dma[dma].source = address;
1508	}
1509	return memory->dma[dma].source;
1510}
1511
1512uint32_t GBAMemoryWriteDMADAD(struct GBA* gba, int dma, uint32_t address) {
1513	struct GBAMemory* memory = &gba->memory;
1514	address &= 0x0FFFFFFE;
1515	if (_isValidDMADAD(dma, address)) {
1516		memory->dma[dma].dest = address;
1517	}
1518	return memory->dma[dma].dest;
1519}
1520
1521void GBAMemoryWriteDMACNT_LO(struct GBA* gba, int dma, uint16_t count) {
1522	struct GBAMemory* memory = &gba->memory;
1523	memory->dma[dma].count = count ? count : (dma == 3 ? 0x10000 : 0x4000);
1524}
1525
1526uint16_t GBAMemoryWriteDMACNT_HI(struct GBA* gba, int dma, uint16_t control) {
1527	struct GBAMemory* memory = &gba->memory;
1528	struct GBADMA* currentDma = &memory->dma[dma];
1529	int wasEnabled = GBADMARegisterIsEnable(currentDma->reg);
1530	if (dma < 3) {
1531		control &= 0xF7E0;
1532	} else {
1533		control &= 0xFFE0;
1534	}
1535	currentDma->reg = control;
1536
1537	if (GBADMARegisterIsDRQ(currentDma->reg)) {
1538		mLOG(GBA_MEM, STUB, "DRQ not implemented");
1539	}
1540
1541	if (!wasEnabled && GBADMARegisterIsEnable(currentDma->reg)) {
1542		currentDma->nextSource = currentDma->source;
1543		currentDma->nextDest = currentDma->dest;
1544		currentDma->nextCount = currentDma->count;
1545		GBAMemoryScheduleDMA(gba, dma, currentDma);
1546	}
1547	// If the DMA has already occurred, this value might have changed since the function started
1548	return currentDma->reg;
1549};
1550
1551void GBAMemoryScheduleDMA(struct GBA* gba, int number, struct GBADMA* info) {
1552	struct ARMCore* cpu = gba->cpu;
1553	switch (GBADMARegisterGetTiming(info->reg)) {
1554	case DMA_TIMING_NOW:
1555		info->nextEvent = cpu->cycles + 2;
1556		GBAMemoryUpdateDMAs(gba, -1);
1557		break;
1558	case DMA_TIMING_HBLANK:
1559		// Handled implicitly
1560		info->nextEvent = INT_MAX;
1561		break;
1562	case DMA_TIMING_VBLANK:
1563		// Handled implicitly
1564		info->nextEvent = INT_MAX;
1565		break;
1566	case DMA_TIMING_CUSTOM:
1567		info->nextEvent = INT_MAX;
1568		switch (number) {
1569		case 0:
1570			mLOG(GBA_MEM, WARN, "Discarding invalid DMA0 scheduling");
1571			break;
1572		case 1:
1573		case 2:
1574			GBAAudioScheduleFifoDma(&gba->audio, number, info);
1575			break;
1576		case 3:
1577			// GBAVideoScheduleVCaptureDma(dma, info);
1578			break;
1579		}
1580	}
1581}
1582
1583void GBAMemoryRunHblankDMAs(struct GBA* gba, int32_t cycles) {
1584	struct GBAMemory* memory = &gba->memory;
1585	struct GBADMA* dma;
1586	int i;
1587	for (i = 0; i < 4; ++i) {
1588		dma = &memory->dma[i];
1589		if (GBADMARegisterIsEnable(dma->reg) && GBADMARegisterGetTiming(dma->reg) == DMA_TIMING_HBLANK) {
1590			dma->nextEvent = cycles;
1591		}
1592	}
1593	GBAMemoryUpdateDMAs(gba, 0);
1594}
1595
1596void GBAMemoryRunVblankDMAs(struct GBA* gba, int32_t cycles) {
1597	struct GBAMemory* memory = &gba->memory;
1598	struct GBADMA* dma;
1599	int i;
1600	for (i = 0; i < 4; ++i) {
1601		dma = &memory->dma[i];
1602		if (GBADMARegisterIsEnable(dma->reg) && GBADMARegisterGetTiming(dma->reg) == DMA_TIMING_VBLANK) {
1603			dma->nextEvent = cycles;
1604		}
1605	}
1606	GBAMemoryUpdateDMAs(gba, 0);
1607}
1608
1609int32_t GBAMemoryRunDMAs(struct GBA* gba, int32_t cycles) {
1610	struct GBAMemory* memory = &gba->memory;
1611	if (memory->nextDMA == INT_MAX) {
1612		return INT_MAX;
1613	}
1614	memory->nextDMA -= cycles;
1615	memory->eventDiff += cycles;
1616	while (memory->nextDMA <= 0) {
1617		struct GBADMA* dma = &memory->dma[memory->activeDMA];
1618		GBAMemoryServiceDMA(gba, memory->activeDMA, dma);
1619		GBAMemoryUpdateDMAs(gba, memory->eventDiff);
1620		memory->eventDiff = 0;
1621	}
1622	return memory->nextDMA;
1623}
1624
1625void GBAMemoryUpdateDMAs(struct GBA* gba, int32_t cycles) {
1626	int i;
1627	struct GBAMemory* memory = &gba->memory;
1628	struct ARMCore* cpu = gba->cpu;
1629	memory->activeDMA = -1;
1630	memory->nextDMA = INT_MAX;
1631	for (i = 3; i >= 0; --i) {
1632		struct GBADMA* dma = &memory->dma[i];
1633		if (dma->nextEvent != INT_MAX) {
1634			dma->nextEvent -= cycles;
1635			if (GBADMARegisterIsEnable(dma->reg)) {
1636				memory->activeDMA = i;
1637				memory->nextDMA = dma->nextEvent;
1638			}
1639		}
1640	}
1641	if (memory->nextDMA < cpu->nextEvent) {
1642		cpu->nextEvent = memory->nextDMA;
1643	}
1644}
1645
1646void GBAMemoryServiceDMA(struct GBA* gba, int number, struct GBADMA* info) {
1647	struct GBAMemory* memory = &gba->memory;
1648	struct ARMCore* cpu = gba->cpu;
1649	uint32_t width = GBADMARegisterGetWidth(info->reg) ? 4 : 2;
1650	int sourceOffset = DMA_OFFSET[GBADMARegisterGetSrcControl(info->reg)] * width;
1651	int destOffset = DMA_OFFSET[GBADMARegisterGetDestControl(info->reg)] * width;
1652	int32_t wordsRemaining = info->nextCount;
1653	uint32_t source = info->nextSource;
1654	uint32_t dest = info->nextDest;
1655	uint32_t sourceRegion = source >> BASE_OFFSET;
1656	uint32_t destRegion = dest >> BASE_OFFSET;
1657	int32_t cycles = 2;
1658
1659	if (source == info->source && dest == info->dest && wordsRemaining == info->count) {
1660		if (sourceRegion < REGION_CART0 || destRegion < REGION_CART0) {
1661			cycles += 2;
1662		}
1663		if (width == 4) {
1664			cycles += memory->waitstatesNonseq32[sourceRegion] + memory->waitstatesNonseq32[destRegion];
1665			source &= 0xFFFFFFFC;
1666			dest &= 0xFFFFFFFC;
1667		} else {
1668			cycles += memory->waitstatesNonseq16[sourceRegion] + memory->waitstatesNonseq16[destRegion];
1669		}
1670	} else {
1671		if (width == 4) {
1672			cycles += memory->waitstatesSeq32[sourceRegion] + memory->waitstatesSeq32[destRegion];
1673		} else {
1674			cycles += memory->waitstatesSeq16[sourceRegion] + memory->waitstatesSeq16[destRegion];
1675		}
1676	}
1677
1678	gba->performingDMA = 1 | (number << 1);
1679	int32_t word;
1680	if (width == 4) {
1681		word = cpu->memory.load32(cpu, source, 0);
1682		gba->bus = word;
1683		cpu->memory.store32(cpu, dest, word, 0);
1684		source += sourceOffset;
1685		dest += destOffset;
1686		--wordsRemaining;
1687	} else {
1688		if (sourceRegion == REGION_CART2_EX && memory->savedata.type == SAVEDATA_EEPROM) {
1689			word = GBASavedataReadEEPROM(&memory->savedata);
1690			gba->bus = word | (word << 16);
1691			cpu->memory.store16(cpu, dest, word, 0);
1692			source += sourceOffset;
1693			dest += destOffset;
1694			--wordsRemaining;
1695		} else if (destRegion == REGION_CART2_EX) {
1696			if (memory->savedata.type == SAVEDATA_AUTODETECT) {
1697				mLOG(GBA_MEM, INFO, "Detected EEPROM savegame");
1698				GBASavedataInitEEPROM(&memory->savedata, gba->realisticTiming);
1699			}
1700			word = cpu->memory.load16(cpu, source, 0);
1701			gba->bus = word | (word << 16);
1702			GBASavedataWriteEEPROM(&memory->savedata, word, wordsRemaining);
1703			source += sourceOffset;
1704			dest += destOffset;
1705			--wordsRemaining;
1706		} else {
1707			word = cpu->memory.load16(cpu, source, 0);
1708			gba->bus = word | (word << 16);
1709			cpu->memory.store16(cpu, dest, word, 0);
1710			source += sourceOffset;
1711			dest += destOffset;
1712			--wordsRemaining;
1713		}
1714	}
1715	gba->performingDMA = 0;
1716
1717	if (!wordsRemaining) {
1718		if (!GBADMARegisterIsRepeat(info->reg) || GBADMARegisterGetTiming(info->reg) == DMA_TIMING_NOW) {
1719			info->reg = GBADMARegisterClearEnable(info->reg);
1720			info->nextEvent = INT_MAX;
1721
1722			// Clear the enable bit in memory
1723			memory->io[(REG_DMA0CNT_HI + number * (REG_DMA1CNT_HI - REG_DMA0CNT_HI)) >> 1] &= 0x7FE0;
1724		} else {
1725			info->nextCount = info->count;
1726			if (GBADMARegisterGetDestControl(info->reg) == DMA_INCREMENT_RELOAD) {
1727				info->nextDest = info->dest;
1728			}
1729			GBAMemoryScheduleDMA(gba, number, info);
1730		}
1731		if (GBADMARegisterIsDoIRQ(info->reg)) {
1732			GBARaiseIRQ(gba, IRQ_DMA0 + number);
1733		}
1734	} else {
1735		info->nextDest = dest;
1736		info->nextCount = wordsRemaining;
1737	}
1738	info->nextSource = source;
1739
1740	if (info->nextEvent != INT_MAX) {
1741		info->nextEvent += cycles;
1742	}
1743	cpu->cycles += cycles;
1744}
1745
1746int32_t GBAMemoryStall(struct ARMCore* cpu, int32_t wait) {
1747	struct GBA* gba = (struct GBA*) cpu->master;
1748	struct GBAMemory* memory = &gba->memory;
1749
1750	if (memory->activeRegion < REGION_CART0 || !memory->prefetch) {
1751		// The wait is the stall
1752		return wait;
1753	}
1754
1755	int32_t previousLoads = 0;
1756
1757	// Don't prefetch too much if we're overlapping with a previous prefetch
1758	uint32_t dist = (memory->lastPrefetchedPc - cpu->gprs[ARM_PC]) >> 1;
1759	if (dist < 8) {
1760		previousLoads = dist;
1761	}
1762
1763	int32_t s = cpu->memory.activeSeqCycles16 + 1;
1764	int32_t n2s = cpu->memory.activeNonseqCycles16 - cpu->memory.activeSeqCycles16 + 1;
1765
1766	// Figure out how many sequential loads we can jam in
1767	int32_t stall = s;
1768	int32_t loads = 1;
1769
1770	if (stall > wait && !previousLoads) {
1771		// We might need to stall a bit extra if we haven't finished the first S cycle
1772		wait = stall;
1773	} else {
1774		while (stall < wait) {
1775			stall += s;
1776			++loads;
1777		}
1778		if (loads + previousLoads > 8) {
1779			loads = 8 - previousLoads;
1780		}
1781	}
1782	// This instruction used to have an N, convert it to an S.
1783	wait -= n2s;
1784
1785	// TODO: Invalidate prefetch on branch
1786	memory->lastPrefetchedPc = cpu->gprs[ARM_PC] + WORD_SIZE_THUMB * loads;
1787
1788	// The next |loads|S waitstates disappear entirely, so long as they're all in a row
1789	cpu->cycles -= (s - 1) * loads;
1790	return wait;
1791}
1792
1793void GBAMemorySerialize(const struct GBAMemory* memory, struct GBASerializedState* state) {
1794	memcpy(state->wram, memory->wram, SIZE_WORKING_RAM);
1795	memcpy(state->iwram, memory->iwram, SIZE_WORKING_IRAM);
1796}
1797
1798void GBAMemoryDeserialize(struct GBAMemory* memory, const struct GBASerializedState* state) {
1799	memcpy(memory->wram, state->wram, SIZE_WORKING_RAM);
1800	memcpy(memory->iwram, state->iwram, SIZE_WORKING_IRAM);
1801}
1802
1803void _pristineCow(struct GBA* gba) {
1804	if (gba->memory.rom != gba->pristineRom) {
1805		return;
1806	}
1807	gba->memory.rom = anonymousMemoryMap(SIZE_CART0);
1808	memcpy(gba->memory.rom, gba->pristineRom, gba->memory.romSize);
1809	memset(((uint8_t*) gba->memory.rom) + gba->memory.romSize, 0xFF, SIZE_CART0 - gba->memory.romSize);
1810}