all repos — mgba @ f0f12fec1ad56da2d12ea8a538fc8a9e992fe4ea

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