all repos — mgba @ 2ff580925222a8cc8012b641a0d4193986664257

mGBA Game Boy Advance Emulator

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

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