all repos — mgba @ 56722324efdf8d5c9675f7658a35b0d05e9f8594

mGBA Game Boy Advance Emulator

src/gb/memory.c (view raw)

   1/* Copyright (c) 2013-2016 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 "core/interface.h"
   9#include "gb/gb.h"
  10#include "gb/io.h"
  11#include "gb/serialize.h"
  12
  13#include "util/memory.h"
  14
  15#include <time.h>
  16
  17mLOG_DEFINE_CATEGORY(GB_MBC, "GB MBC");
  18mLOG_DEFINE_CATEGORY(GB_MEM, "GB Memory");
  19
  20static void _pristineCow(struct GB* gba);
  21
  22static void _GBMBCNone(struct GBMemory* memory, uint16_t address, uint8_t value) {
  23	UNUSED(memory);
  24	UNUSED(address);
  25	UNUSED(value);
  26
  27	mLOG(GB_MBC, GAME_ERROR, "Wrote to invalid MBC");
  28}
  29
  30static void _GBMBC1(struct GBMemory*, uint16_t address, uint8_t value);
  31static void _GBMBC2(struct GBMemory*, uint16_t address, uint8_t value);
  32static void _GBMBC3(struct GBMemory*, uint16_t address, uint8_t value);
  33static void _GBMBC5(struct GBMemory*, uint16_t address, uint8_t value);
  34static void _GBMBC6(struct GBMemory*, uint16_t address, uint8_t value);
  35static void _GBMBC7(struct GBMemory*, uint16_t address, uint8_t value);
  36static uint8_t _GBMBC7Read(struct GBMemory*, uint16_t address);
  37static void _GBMBC7Write(struct GBMemory*, uint16_t address, uint8_t value);
  38static void _GBHuC3(struct GBMemory*, uint16_t address, uint8_t value);
  39
  40static uint8_t GBFastLoad8(struct LR35902Core* cpu, uint16_t address) {
  41	if (UNLIKELY(address > cpu->memory.activeRegionEnd)) {
  42		cpu->memory.setActiveRegion(cpu, address);
  43		return cpu->memory.cpuLoad8(cpu, address);
  44	}
  45	return cpu->memory.activeRegion[address & cpu->memory.activeMask];
  46}
  47
  48static void GBSetActiveRegion(struct LR35902Core* cpu, uint16_t address) {
  49	struct GB* gb = (struct GB*) cpu->master;
  50	struct GBMemory* memory = &gb->memory;
  51	switch (address >> 12) {
  52	case GB_REGION_CART_BANK0:
  53	case GB_REGION_CART_BANK0 + 1:
  54	case GB_REGION_CART_BANK0 + 2:
  55	case GB_REGION_CART_BANK0 + 3:
  56		cpu->memory.cpuLoad8 = GBFastLoad8;
  57		cpu->memory.activeRegion = memory->romBase;
  58		cpu->memory.activeRegionEnd = GB_BASE_CART_BANK1;
  59		cpu->memory.activeMask = GB_SIZE_CART_BANK0 - 1;
  60		break;
  61	case GB_REGION_CART_BANK1:
  62	case GB_REGION_CART_BANK1 + 1:
  63	case GB_REGION_CART_BANK1 + 2:
  64	case GB_REGION_CART_BANK1 + 3:
  65		cpu->memory.cpuLoad8 = GBFastLoad8;
  66		cpu->memory.activeRegion = memory->romBank;
  67		cpu->memory.activeRegionEnd = GB_BASE_VRAM;
  68		cpu->memory.activeMask = GB_SIZE_CART_BANK0 - 1;
  69		break;
  70	default:
  71		cpu->memory.cpuLoad8 = GBLoad8;
  72		break;
  73	}
  74}
  75
  76static void _GBMemoryDMAService(struct GB* gb);
  77static void _GBMemoryHDMAService(struct GB* gb);
  78
  79void GBMemoryInit(struct GB* gb) {
  80	struct LR35902Core* cpu = gb->cpu;
  81	cpu->memory.cpuLoad8 = GBLoad8;
  82	cpu->memory.load8 = GBLoad8;
  83	cpu->memory.store8 = GBStore8;
  84	cpu->memory.setActiveRegion = GBSetActiveRegion;
  85
  86	gb->memory.wram = 0;
  87	gb->memory.wramBank = 0;
  88	gb->memory.rom = 0;
  89	gb->memory.romBank = 0;
  90	gb->memory.romSize = 0;
  91	gb->memory.sram = 0;
  92	gb->memory.mbcType = GB_MBC_NONE;
  93	gb->memory.mbc = 0;
  94
  95	gb->memory.rtc = NULL;
  96
  97	GBIOInit(gb);
  98}
  99
 100void GBMemoryDeinit(struct GB* gb) {
 101	mappedMemoryFree(gb->memory.wram, GB_SIZE_WORKING_RAM);
 102	if (gb->memory.rom) {
 103		mappedMemoryFree(gb->memory.rom, gb->memory.romSize);
 104	}
 105}
 106
 107void GBMemoryReset(struct GB* gb) {
 108	if (gb->memory.wram) {
 109		mappedMemoryFree(gb->memory.wram, GB_SIZE_WORKING_RAM);
 110	}
 111	gb->memory.wram = anonymousMemoryMap(GB_SIZE_WORKING_RAM);
 112	GBMemorySwitchWramBank(&gb->memory, 1);
 113	gb->memory.romBank = &gb->memory.rom[GB_SIZE_CART_BANK0];
 114	gb->memory.currentBank = 1;
 115	if (!gb->memory.sram) {
 116		gb->memory.sram = anonymousMemoryMap(0x20000);
 117	}
 118	gb->memory.sramCurrentBank = 0;
 119	gb->memory.sramBank = gb->memory.sram;
 120
 121	gb->memory.ime = false;
 122	gb->memory.ie = 0;
 123
 124	gb->memory.dmaNext = INT_MAX;
 125	gb->memory.dmaRemaining = 0;
 126	gb->memory.dmaSource = 0;
 127	gb->memory.dmaDest = 0;
 128	gb->memory.hdmaNext = INT_MAX;
 129	gb->memory.hdmaRemaining = 0;
 130	gb->memory.hdmaSource = 0;
 131	gb->memory.hdmaDest = 0;
 132	gb->memory.isHdma = false;
 133
 134	gb->memory.sramAccess = false;
 135	gb->memory.rtcAccess = false;
 136	gb->memory.activeRtcReg = 0;
 137	gb->memory.rtcLatched = false;
 138	memset(&gb->memory.rtcRegs, 0, sizeof(gb->memory.rtcRegs));
 139
 140	memset(&gb->memory.hram, 0, sizeof(gb->memory.hram));
 141	memset(&gb->memory.mbcState, 0, sizeof(gb->memory.mbcState));
 142
 143	const struct GBCartridge* cart = (const struct GBCartridge*) &gb->memory.rom[0x100];
 144	switch (cart->type) {
 145	case 0:
 146	case 8:
 147	case 9:
 148		gb->memory.mbc = _GBMBCNone;
 149		gb->memory.mbcType = GB_MBC_NONE;
 150		break;
 151	case 1:
 152	case 2:
 153	case 3:
 154		gb->memory.mbc = _GBMBC1;
 155		gb->memory.mbcType = GB_MBC1;
 156		break;
 157	case 5:
 158	case 6:
 159		gb->memory.mbc = _GBMBC2;
 160		gb->memory.mbcType = GB_MBC2;
 161		break;
 162	case 0x0F:
 163	case 0x10:
 164	case 0x11:
 165	case 0x12:
 166	case 0x13:
 167		gb->memory.mbc = _GBMBC3;
 168		gb->memory.mbcType = GB_MBC3;
 169		break;
 170	default:
 171		mLOG(GB_MBC, WARN, "Unknown MBC type: %02X", cart->type);
 172	case 0x19:
 173	case 0x1A:
 174	case 0x1B:
 175		gb->memory.mbc = _GBMBC5;
 176		gb->memory.mbcType = GB_MBC5;
 177		break;
 178	case 0x1C:
 179	case 0x1D:
 180	case 0x1E:
 181		gb->memory.mbc = _GBMBC5;
 182		gb->memory.mbcType = GB_MBC5_RUMBLE;
 183		break;
 184	case 0x20:
 185		gb->memory.mbc = _GBMBC6;
 186		gb->memory.mbcType = GB_MBC6;
 187		break;
 188	case 0x22:
 189		gb->memory.mbc = _GBMBC7;
 190		gb->memory.mbcType = GB_MBC7;
 191		break;
 192	case 0xFE:
 193		gb->memory.mbc = _GBHuC3;
 194		gb->memory.mbcType = GB_HuC3;
 195		break;
 196	}
 197
 198	if (!gb->memory.wram) {
 199		GBMemoryDeinit(gb);
 200	}
 201}
 202
 203void GBMemorySwitchWramBank(struct GBMemory* memory, int bank) {
 204	bank &= 7;
 205	if (!bank) {
 206		bank = 1;
 207	}
 208	memory->wramBank = &memory->wram[GB_SIZE_WORKING_RAM_BANK0 * bank];
 209	memory->wramCurrentBank = bank;
 210}
 211
 212uint8_t GBLoad8(struct LR35902Core* cpu, uint16_t address) {
 213	struct GB* gb = (struct GB*) cpu->master;
 214	struct GBMemory* memory = &gb->memory;
 215	switch (address >> 12) {
 216	case GB_REGION_CART_BANK0:
 217	case GB_REGION_CART_BANK0 + 1:
 218	case GB_REGION_CART_BANK0 + 2:
 219	case GB_REGION_CART_BANK0 + 3:
 220		return memory->romBase[address & (GB_SIZE_CART_BANK0 - 1)];
 221	case GB_REGION_CART_BANK1:
 222	case GB_REGION_CART_BANK1 + 1:
 223	case GB_REGION_CART_BANK1 + 2:
 224	case GB_REGION_CART_BANK1 + 3:
 225		return memory->romBank[address & (GB_SIZE_CART_BANK0 - 1)];
 226	case GB_REGION_VRAM:
 227	case GB_REGION_VRAM + 1:
 228		return gb->video.vramBank[address & (GB_SIZE_VRAM_BANK0 - 1)];
 229	case GB_REGION_EXTERNAL_RAM:
 230	case GB_REGION_EXTERNAL_RAM + 1:
 231		if (memory->rtcAccess) {
 232			return memory->rtcRegs[memory->activeRtcReg];
 233		} else if (memory->sramAccess) {
 234			return memory->sramBank[address & (GB_SIZE_EXTERNAL_RAM - 1)];
 235		} else if (memory->mbcType == GB_MBC7) {
 236			return _GBMBC7Read(memory, address);
 237		} else if (memory->mbcType == GB_HuC3) {
 238			return 0x01; // TODO: Is this supposed to be the current SRAM bank?
 239		}
 240		return 0xFF;
 241	case GB_REGION_WORKING_RAM_BANK0:
 242	case GB_REGION_WORKING_RAM_BANK0 + 2:
 243		return memory->wram[address & (GB_SIZE_WORKING_RAM_BANK0 - 1)];
 244	case GB_REGION_WORKING_RAM_BANK1:
 245		return memory->wramBank[address & (GB_SIZE_WORKING_RAM_BANK0 - 1)];
 246	default:
 247		if (address < GB_BASE_OAM) {
 248			return memory->wramBank[address & (GB_SIZE_WORKING_RAM_BANK0 - 1)];
 249		}
 250		if (address < GB_BASE_UNUSABLE) {
 251			if (gb->video.mode < 2) {
 252				return gb->video.oam.raw[address & 0xFF];
 253			}
 254			return 0xFF;
 255		}
 256		if (address < GB_BASE_IO) {
 257			mLOG(GB_MEM, GAME_ERROR, "Attempt to read from unusable memory: %04X", address);
 258			return 0xFF;
 259		}
 260		if (address < GB_BASE_HRAM) {
 261			return GBIORead(gb, address & (GB_SIZE_IO - 1));
 262		}
 263		if (address < GB_BASE_IE) {
 264			return memory->hram[address & GB_SIZE_HRAM];
 265		}
 266		return GBIORead(gb, REG_IE);
 267	}
 268}
 269
 270void GBStore8(struct LR35902Core* cpu, uint16_t address, int8_t value) {
 271	struct GB* gb = (struct GB*) cpu->master;
 272	struct GBMemory* memory = &gb->memory;
 273	switch (address >> 12) {
 274	case GB_REGION_CART_BANK0:
 275	case GB_REGION_CART_BANK0 + 1:
 276	case GB_REGION_CART_BANK0 + 2:
 277	case GB_REGION_CART_BANK0 + 3:
 278	case GB_REGION_CART_BANK1:
 279	case GB_REGION_CART_BANK1 + 1:
 280	case GB_REGION_CART_BANK1 + 2:
 281	case GB_REGION_CART_BANK1 + 3:
 282		memory->mbc(memory, address, value);
 283		cpu->memory.setActiveRegion(cpu, cpu->pc);
 284		return;
 285	case GB_REGION_VRAM:
 286	case GB_REGION_VRAM + 1:
 287		// TODO: Block access in wrong modes
 288		gb->video.vramBank[address & (GB_SIZE_VRAM_BANK0 - 1)] = value;
 289		return;
 290	case GB_REGION_EXTERNAL_RAM:
 291	case GB_REGION_EXTERNAL_RAM + 1:
 292		if (memory->rtcAccess) {
 293			memory->rtcRegs[memory->activeRtcReg] = value;
 294		} else if (memory->sramAccess) {
 295			memory->sramBank[address & (GB_SIZE_EXTERNAL_RAM - 1)] = value;
 296		} else if (memory->mbcType == GB_MBC7) {
 297			_GBMBC7Write(memory, address, value);
 298		}
 299		return;
 300	case GB_REGION_WORKING_RAM_BANK0:
 301	case GB_REGION_WORKING_RAM_BANK0 + 2:
 302		memory->wram[address & (GB_SIZE_WORKING_RAM_BANK0 - 1)] = value;
 303		return;
 304	case GB_REGION_WORKING_RAM_BANK1:
 305		memory->wramBank[address & (GB_SIZE_WORKING_RAM_BANK0 - 1)] = value;
 306		return;
 307	default:
 308		if (address < GB_BASE_OAM) {
 309			memory->wramBank[address & (GB_SIZE_WORKING_RAM_BANK0 - 1)] = value;
 310		} else if (address < GB_BASE_UNUSABLE) {
 311			if (gb->video.mode < 2) {
 312				gb->video.oam.raw[address & 0xFF] = value;
 313			}
 314		} else if (address < GB_BASE_IO) {
 315			mLOG(GB_MEM, GAME_ERROR, "Attempt to write to unusable memory: %04X:%02X", address, value);
 316		} else if (address < GB_BASE_HRAM) {
 317			GBIOWrite(gb, address & (GB_SIZE_IO - 1), value);
 318		} else if (address < GB_BASE_IE) {
 319			memory->hram[address & GB_SIZE_HRAM] = value;
 320		} else {
 321			GBIOWrite(gb, REG_IE, value);
 322		}
 323	}
 324}
 325uint8_t GBView8(struct LR35902Core* cpu, uint16_t address, int segment) {
 326	struct GB* gb = (struct GB*) cpu->master;
 327	struct GBMemory* memory = &gb->memory;
 328	switch (address >> 12) {
 329	case GB_REGION_CART_BANK0:
 330	case GB_REGION_CART_BANK0 + 1:
 331	case GB_REGION_CART_BANK0 + 2:
 332	case GB_REGION_CART_BANK0 + 3:
 333		return memory->romBase[address & (GB_SIZE_CART_BANK0 - 1)];
 334	case GB_REGION_CART_BANK1:
 335	case GB_REGION_CART_BANK1 + 1:
 336	case GB_REGION_CART_BANK1 + 2:
 337	case GB_REGION_CART_BANK1 + 3:
 338		if (segment < 0) {
 339			return memory->romBank[address & (GB_SIZE_CART_BANK0 - 1)];
 340		} else {
 341			if ((size_t) segment * GB_SIZE_CART_BANK0 > memory->romSize) {
 342				return 0xFF;
 343			}
 344			return memory->rom[(address & (GB_SIZE_CART_BANK0 - 1)) + segment * GB_SIZE_CART_BANK0];
 345		}
 346	case GB_REGION_VRAM:
 347	case GB_REGION_VRAM + 1:
 348		if (segment < 0) {
 349			return gb->video.vramBank[address & (GB_SIZE_VRAM_BANK0 - 1)];
 350		} else {
 351			return gb->video.vram[(address & (GB_SIZE_VRAM_BANK0 - 1)) + segment *GB_SIZE_VRAM_BANK0];
 352		}
 353	case GB_REGION_EXTERNAL_RAM:
 354	case GB_REGION_EXTERNAL_RAM + 1:
 355		if (memory->rtcAccess) {
 356			return memory->rtcRegs[memory->activeRtcReg];
 357		} else if (memory->sramAccess) {
 358			if (segment < 0) {
 359				return memory->sramBank[address & (GB_SIZE_EXTERNAL_RAM - 1)];
 360			} else {
 361				return memory->sram[(address & (GB_SIZE_EXTERNAL_RAM - 1)) + segment *GB_SIZE_EXTERNAL_RAM];
 362			}
 363		} else if (memory->mbcType == GB_MBC7) {
 364			return _GBMBC7Read(memory, address);
 365		} else if (memory->mbcType == GB_HuC3) {
 366			return 0x01; // TODO: Is this supposed to be the current SRAM bank?
 367		}
 368		return 0xFF;
 369	case GB_REGION_WORKING_RAM_BANK0:
 370	case GB_REGION_WORKING_RAM_BANK0 + 2:
 371		return memory->wram[address & (GB_SIZE_WORKING_RAM_BANK0 - 1)];
 372	case GB_REGION_WORKING_RAM_BANK1:
 373		if (segment < 0) {
 374			return memory->wramBank[address & (GB_SIZE_WORKING_RAM_BANK0 - 1)];
 375		} else {
 376			return memory->wram[(address & (GB_SIZE_WORKING_RAM_BANK0 - 1)) + segment *GB_SIZE_WORKING_RAM_BANK0];
 377		}
 378	default:
 379		if (address < GB_BASE_OAM) {
 380			return memory->wramBank[address & (GB_SIZE_WORKING_RAM_BANK0 - 1)];
 381		}
 382		if (address < GB_BASE_UNUSABLE) {
 383			if (gb->video.mode < 2) {
 384				return gb->video.oam.raw[address & 0xFF];
 385			}
 386			return 0xFF;
 387		}
 388		if (address < GB_BASE_IO) {
 389			mLOG(GB_MEM, GAME_ERROR, "Attempt to read from unusable memory: %04X", address);
 390			return 0xFF;
 391		}
 392		if (address < GB_BASE_HRAM) {
 393			return GBIORead(gb, address & (GB_SIZE_IO - 1));
 394		}
 395		if (address < GB_BASE_IE) {
 396			return memory->hram[address & GB_SIZE_HRAM];
 397		}
 398		return GBIORead(gb, REG_IE);
 399	}
 400}
 401
 402int32_t GBMemoryProcessEvents(struct GB* gb, int32_t cycles) {
 403	int nextEvent = INT_MAX;
 404	if (gb->memory.dmaRemaining) {
 405		gb->memory.dmaNext -= cycles;
 406		if (gb->memory.dmaNext <= 0) {
 407			_GBMemoryDMAService(gb);
 408		}
 409		nextEvent = gb->memory.dmaNext;
 410	}
 411	if (gb->memory.hdmaRemaining) {
 412		gb->memory.hdmaNext -= cycles;
 413		if (gb->memory.hdmaNext <= 0) {
 414			_GBMemoryHDMAService(gb);
 415		}
 416		if (gb->memory.hdmaNext < nextEvent) {
 417			nextEvent = gb->memory.hdmaNext;
 418		}
 419	}
 420	return nextEvent;
 421}
 422
 423void GBMemoryDMA(struct GB* gb, uint16_t base) {
 424	if (base > 0xF100) {
 425		return;
 426	}
 427	gb->cpu->memory.store8 = GBDMAStore8;
 428	gb->cpu->memory.load8 = GBDMALoad8;
 429	gb->cpu->memory.cpuLoad8 = GBDMALoad8;
 430	gb->memory.dmaNext = gb->cpu->cycles + 8;
 431	if (gb->memory.dmaNext < gb->cpu->nextEvent) {
 432		gb->cpu->nextEvent = gb->memory.dmaNext;
 433	}
 434	gb->memory.dmaSource = base;
 435	gb->memory.dmaDest = 0;
 436	gb->memory.dmaRemaining = 0xA0;
 437}
 438
 439void GBMemoryWriteHDMA5(struct GB* gb, uint8_t value) {
 440	gb->memory.hdmaSource = gb->memory.io[REG_HDMA1] << 8;
 441	gb->memory.hdmaSource |= gb->memory.io[REG_HDMA2];
 442	gb->memory.hdmaDest = gb->memory.io[REG_HDMA3] << 8;
 443	gb->memory.hdmaDest |= gb->memory.io[REG_HDMA4];
 444	gb->memory.hdmaSource &= 0xFFF0;
 445	if (gb->memory.hdmaSource >= 0x8000 && gb->memory.hdmaSource < 0xA000) {
 446		mLOG(GB_MEM, GAME_ERROR, "Invalid HDMA source: %04X", gb->memory.hdmaSource);
 447		return;
 448	}
 449	gb->memory.hdmaDest &= 0x1FF0;
 450	gb->memory.hdmaDest |= 0x8000;
 451	bool wasHdma = gb->memory.isHdma;
 452	gb->memory.isHdma = value & 0x80;
 453	if (!wasHdma && !gb->memory.isHdma) {
 454		gb->memory.hdmaRemaining = ((value & 0x7F) + 1) * 0x10;
 455		gb->memory.hdmaNext = gb->cpu->cycles;
 456		gb->cpu->nextEvent = gb->cpu->cycles;
 457	}
 458}
 459
 460void _GBMemoryDMAService(struct GB* gb) {
 461	uint8_t b = GBLoad8(gb->cpu, gb->memory.dmaSource);
 462	// TODO: Can DMA write OAM during modes 2-3?
 463	gb->video.oam.raw[gb->memory.dmaDest] = b;
 464	++gb->memory.dmaSource;
 465	++gb->memory.dmaDest;
 466	--gb->memory.dmaRemaining;
 467	if (gb->memory.dmaRemaining) {
 468		gb->memory.dmaNext += 4;
 469	} else {
 470		gb->memory.dmaNext = INT_MAX;
 471		gb->cpu->memory.store8 = GBStore8;
 472		gb->cpu->memory.load8 = GBLoad8;
 473	}
 474}
 475
 476void _GBMemoryHDMAService(struct GB* gb) {
 477	uint8_t b = gb->cpu->memory.load8(gb->cpu, gb->memory.hdmaSource);
 478	gb->cpu->memory.store8(gb->cpu, gb->memory.hdmaDest, b);
 479	++gb->memory.hdmaSource;
 480	++gb->memory.hdmaDest;
 481	--gb->memory.hdmaRemaining;
 482	gb->cpu->cycles += 2;
 483	if (gb->memory.hdmaRemaining) {
 484		gb->memory.hdmaNext += 2;
 485	} else {
 486		gb->memory.io[REG_HDMA1] = gb->memory.hdmaSource >> 8;
 487		gb->memory.io[REG_HDMA2] = gb->memory.hdmaSource;
 488		gb->memory.io[REG_HDMA3] = gb->memory.hdmaDest >> 8;
 489		gb->memory.io[REG_HDMA4] = gb->memory.hdmaDest;
 490		if (gb->memory.isHdma) {
 491			--gb->memory.io[REG_HDMA5];
 492			if (gb->memory.io[REG_HDMA5] == 0xFF) {
 493				gb->memory.isHdma = false;
 494			}
 495		} else {
 496			gb->memory.io[REG_HDMA5] |= 0x80;
 497		}
 498	}
 499}
 500
 501struct OAMBlock {
 502	uint16_t low;
 503	uint16_t high;
 504};
 505
 506static const struct OAMBlock _oamBlockDMG[] = {
 507	{ 0xA000, 0xFE00 },
 508	{ 0xA000, 0xFE00 },
 509	{ 0xA000, 0xFE00 },
 510	{ 0xA000, 0xFE00 },
 511	{ 0x8000, 0xA000 },
 512	{ 0xA000, 0xFE00 },
 513	{ 0xA000, 0xFE00 },
 514	{ 0xA000, 0xFE00 },
 515};
 516
 517static const struct OAMBlock _oamBlockCGB[] = {
 518	{ 0xA000, 0xC000 },
 519	{ 0xA000, 0xC000 },
 520	{ 0xA000, 0xC000 },
 521	{ 0xA000, 0xC000 },
 522	{ 0x8000, 0xA000 },
 523	{ 0xA000, 0xC000 },
 524	{ 0xC000, 0xFE00 },
 525	{ 0xA000, 0xC000 },
 526};
 527
 528uint8_t GBDMALoad8(struct LR35902Core* cpu, uint16_t address) {
 529	struct GB* gb = (struct GB*) cpu->master;
 530	struct GBMemory* memory = &gb->memory;
 531	const struct OAMBlock* block = gb->model < GB_MODEL_CGB ? _oamBlockDMG : _oamBlockCGB;
 532	block = &block[memory->dmaSource >> 13];
 533	if (address >= block->low && address < block->high) {
 534		return 0xFF;
 535	}
 536	if (address >= GB_BASE_OAM && address < GB_BASE_UNUSABLE) {
 537		return 0xFF;
 538	}
 539	return GBLoad8(cpu, address);
 540}
 541
 542void GBDMAStore8(struct LR35902Core* cpu, uint16_t address, int8_t value) {
 543	struct GB* gb = (struct GB*) cpu->master;
 544	struct GBMemory* memory = &gb->memory;
 545	const struct OAMBlock* block = gb->model < GB_MODEL_CGB ? _oamBlockDMG : _oamBlockCGB;
 546	block = &block[memory->dmaSource >> 13];
 547	if (address >= block->low && address < block->high) {
 548		return;
 549	}
 550	if (address >= GB_BASE_OAM && address < GB_BASE_UNUSABLE) {
 551		return;
 552	}
 553	GBStore8(cpu, address, value);
 554}
 555
 556void GBPatch8(struct LR35902Core* cpu, uint16_t address, int8_t value, int8_t* old) {
 557	struct GB* gb = (struct GB*) cpu->master;
 558	struct GBMemory* memory = &gb->memory;
 559	int8_t oldValue = -1;
 560
 561	switch (address >> 12) {
 562	case GB_REGION_CART_BANK0:
 563	case GB_REGION_CART_BANK0 + 1:
 564	case GB_REGION_CART_BANK0 + 2:
 565	case GB_REGION_CART_BANK0 + 3:
 566		_pristineCow(gb);
 567		oldValue = memory->rom[address & (GB_SIZE_CART_BANK0 - 1)];
 568		memory->rom[address & (GB_SIZE_CART_BANK0 - 1)] =  value;
 569		break;
 570	case GB_REGION_CART_BANK1:
 571	case GB_REGION_CART_BANK1 + 1:
 572	case GB_REGION_CART_BANK1 + 2:
 573	case GB_REGION_CART_BANK1 + 3:
 574		_pristineCow(gb);
 575		oldValue = memory->romBank[address & (GB_SIZE_CART_BANK0 - 1)];
 576		memory->romBank[address & (GB_SIZE_CART_BANK0 - 1)] =  value;
 577		break;
 578	case GB_REGION_VRAM:
 579	case GB_REGION_VRAM + 1:
 580		oldValue = gb->video.vramBank[address & (GB_SIZE_VRAM_BANK0 - 1)];
 581		gb->video.vramBank[address & (GB_SIZE_VRAM_BANK0 - 1)] = value;
 582		break;
 583	case GB_REGION_EXTERNAL_RAM:
 584	case GB_REGION_EXTERNAL_RAM + 1:
 585		mLOG(GB_MEM, STUB, "Unimplemented memory Patch8: 0x%08X", address);
 586		return;
 587	case GB_REGION_WORKING_RAM_BANK0:
 588	case GB_REGION_WORKING_RAM_BANK0 + 2:
 589		oldValue = memory->wram[address & (GB_SIZE_WORKING_RAM_BANK0 - 1)];
 590		memory->wram[address & (GB_SIZE_WORKING_RAM_BANK0 - 1)] = value;
 591		break;
 592	case GB_REGION_WORKING_RAM_BANK1:
 593		oldValue = memory->wramBank[address & (GB_SIZE_WORKING_RAM_BANK0 - 1)];
 594		memory->wramBank[address & (GB_SIZE_WORKING_RAM_BANK0 - 1)] = value;
 595		break;
 596	default:
 597		if (address < GB_BASE_OAM) {
 598			oldValue = memory->wramBank[address & (GB_SIZE_WORKING_RAM_BANK0 - 1)];
 599			memory->wramBank[address & (GB_SIZE_WORKING_RAM_BANK0 - 1)] = value;
 600		} else if (address < GB_BASE_UNUSABLE) {
 601			oldValue = gb->video.oam.raw[address & 0xFF];
 602			gb->video.oam.raw[address & 0xFF] = value;
 603		} else if (address < GB_BASE_HRAM) {
 604			mLOG(GB_MEM, STUB, "Unimplemented memory Patch8: 0x%08X", address);
 605			return;
 606		} else if (address < GB_BASE_IE) {
 607			oldValue = memory->hram[address & GB_SIZE_HRAM];
 608			memory->hram[address & GB_SIZE_HRAM] = value;
 609		} else {
 610			mLOG(GB_MEM, STUB, "Unimplemented memory Patch8: 0x%08X", address);
 611			return;
 612		}
 613	}
 614	if (old) {
 615		*old = oldValue;
 616	}
 617}
 618
 619static void _switchBank(struct GBMemory* memory, int bank) {
 620	size_t bankStart = bank * GB_SIZE_CART_BANK0;
 621	if (bankStart + GB_SIZE_CART_BANK0 > memory->romSize) {
 622		mLOG(GB_MBC, GAME_ERROR, "Attempting to switch to an invalid ROM bank: %0X", bank);
 623		bankStart &= (memory->romSize - 1);
 624		bank = bankStart / GB_SIZE_CART_BANK0;
 625	}
 626	memory->romBank = &memory->rom[bankStart];
 627	memory->currentBank = bank;
 628}
 629
 630static void _switchSramBank(struct GBMemory* memory, int bank) {
 631	size_t bankStart = bank * GB_SIZE_EXTERNAL_RAM;
 632	memory->sramBank = &memory->sram[bankStart];
 633	memory->sramCurrentBank = bank;
 634}
 635
 636static void _latchRtc(struct GBMemory* memory) {
 637	time_t t;
 638	struct mRTCSource* rtc = memory->rtc;
 639	if (rtc) {
 640		if (rtc->sample) {
 641			rtc->sample(rtc);
 642		}
 643		t = rtc->unixTime(rtc);
 644	} else {
 645		t = time(0);
 646	}
 647	struct tm date;
 648	localtime_r(&t, &date);
 649	memory->rtcRegs[0] = date.tm_sec;
 650	memory->rtcRegs[1] = date.tm_min;
 651	memory->rtcRegs[2] = date.tm_hour;
 652	memory->rtcRegs[3] = date.tm_yday; // TODO: Persist day counter
 653	memory->rtcRegs[4] &= 0xF0;
 654	memory->rtcRegs[4] |= date.tm_yday >> 8;
 655}
 656
 657void _GBMBC1(struct GBMemory* memory, uint16_t address, uint8_t value) {
 658	int bank = value & 0x1F;
 659	switch (address >> 13) {
 660	case 0x0:
 661		switch (value) {
 662		case 0:
 663			memory->sramAccess = false;
 664			break;
 665		case 0xA:
 666			memory->sramAccess = true;
 667			_switchSramBank(memory, memory->sramCurrentBank);
 668			break;
 669		default:
 670			// TODO
 671			mLOG(GB_MBC, STUB, "MBC1 unknown value %02X", value);
 672			break;
 673		}
 674		break;
 675	case 0x1:
 676		if (!bank) {
 677			++bank;
 678		}
 679		_switchBank(memory, bank | (memory->currentBank & 0x60));
 680		break;
 681	case 0x2:
 682		bank &= 3;
 683		if (!memory->mbcState.mbc1.mode) {
 684			_switchBank(memory, (bank << 5) | (memory->currentBank & 0x1F));
 685		} else {
 686			_switchSramBank(memory, bank);
 687		}
 688		break;
 689	case 0x3:
 690		memory->mbcState.mbc1.mode = value & 1;
 691		if (memory->mbcState.mbc1.mode) {
 692			_switchBank(memory, memory->currentBank & 0x1F);
 693		} else {
 694			_switchSramBank(memory, 0);
 695		}
 696		break;
 697	default:
 698		// TODO
 699		mLOG(GB_MBC, STUB, "MBC1 unknown address: %04X:%02X", address, value);
 700		break;
 701	}
 702}
 703
 704void _GBMBC2(struct GBMemory* memory, uint16_t address, uint8_t value) {
 705	int bank = value & 0xF;
 706	switch (address >> 13) {
 707	case 0x0:
 708		switch (value) {
 709		case 0:
 710			memory->sramAccess = false;
 711			break;
 712		case 0xA:
 713			memory->sramAccess = true;
 714			_switchSramBank(memory, memory->sramCurrentBank);
 715			break;
 716		default:
 717			// TODO
 718			mLOG(GB_MBC, STUB, "MBC1 unknown value %02X", value);
 719			break;
 720		}
 721		break;
 722	case 0x1:
 723		if (!bank) {
 724			++bank;
 725		}
 726		_switchBank(memory, bank);
 727		break;
 728	default:
 729		// TODO
 730		mLOG(GB_MBC, STUB, "MBC2 unknown address: %04X:%02X", address, value);
 731		break;
 732	}}
 733
 734void _GBMBC3(struct GBMemory* memory, uint16_t address, uint8_t value) {
 735	int bank = value & 0x7F;
 736	switch (address >> 13) {
 737	case 0x0:
 738		switch (value) {
 739		case 0:
 740			memory->sramAccess = false;
 741			break;
 742		case 0xA:
 743			memory->sramAccess = true;
 744			_switchSramBank(memory, memory->sramCurrentBank);
 745			break;
 746		default:
 747			// TODO
 748			mLOG(GB_MBC, STUB, "MBC3 unknown value %02X", value);
 749			break;
 750		}
 751		break;
 752	case 0x1:
 753		if (!bank) {
 754			++bank;
 755		}
 756		_switchBank(memory, bank);
 757		break;
 758	case 0x2:
 759		if (value < 4) {
 760			_switchSramBank(memory, value);
 761			memory->rtcAccess = false;
 762		} else if (value >= 8 && value <= 0xC) {
 763			memory->activeRtcReg = value - 8;
 764			memory->rtcAccess = true;
 765		}
 766		break;
 767	case 0x3:
 768		if (memory->rtcLatched && value == 0) {
 769			memory->rtcLatched = false;
 770		} else if (!memory->rtcLatched && value == 1) {
 771			_latchRtc(memory);
 772			memory->rtcLatched = true;
 773		}
 774		break;
 775	}
 776}
 777
 778void _GBMBC5(struct GBMemory* memory, uint16_t address, uint8_t value) {
 779	int bank;
 780	switch (address >> 12) {
 781	case 0x0:
 782	case 0x1:
 783		switch (value) {
 784		case 0:
 785			memory->sramAccess = false;
 786			break;
 787		case 0xA:
 788			memory->sramAccess = true;
 789			_switchSramBank(memory, memory->sramCurrentBank);
 790			break;
 791		default:
 792			// TODO
 793			mLOG(GB_MBC, STUB, "MBC5 unknown value %02X", value);
 794			break;
 795		}
 796		break;
 797	case 0x2:
 798		bank = (memory->currentBank & 0x100) | value;
 799		_switchBank(memory, bank);
 800		break;
 801	case 0x3:
 802		bank = (memory->currentBank & 0xFF) | ((value & 1) << 8);
 803		_switchBank(memory, bank);
 804		break;
 805	case 0x4:
 806	case 0x5:
 807		if (memory->mbcType == GB_MBC5_RUMBLE && memory->rumble) {
 808			memory->rumble->setRumble(memory->rumble, (value >> 3) & 1);
 809			value &= ~8;
 810		}
 811		_switchSramBank(memory, value & 0xF);
 812		break;
 813	default:
 814		// TODO
 815		mLOG(GB_MBC, STUB, "MBC5 unknown address: %04X:%02X", address, value);
 816		break;
 817	}
 818}
 819
 820void _GBMBC6(struct GBMemory* memory, uint16_t address, uint8_t value) {
 821	// TODO
 822	mLOG(GB_MBC, STUB, "MBC6 unimplemented");
 823}
 824
 825void _GBMBC7(struct GBMemory* memory, uint16_t address, uint8_t value) {
 826	int bank = value & 0x7F;
 827	switch (address >> 13) {
 828	case 0x1:
 829		_switchBank(memory, bank);
 830		break;
 831	case 0x2:
 832		if (value < 0x10) {
 833			_switchSramBank(memory, value);
 834		}
 835		break;
 836	default:
 837		// TODO
 838		mLOG(GB_MBC, STUB, "MBC7 unknown address: %04X:%02X", address, value);
 839		break;
 840	}
 841}
 842
 843uint8_t _GBMBC7Read(struct GBMemory* memory, uint16_t address) {
 844	struct GBMBC7State* mbc7 = &memory->mbcState.mbc7;
 845	switch (address & 0xF0) {
 846	case 0x00:
 847	case 0x10:
 848	case 0x60:
 849	case 0x70:
 850		return 0;
 851	case 0x20:
 852		if (memory->rotation && memory->rotation->readTiltX) {
 853			int32_t x = -memory->rotation->readTiltX(memory->rotation);
 854			x >>= 21;
 855			x += 2047;
 856			return x;
 857		}
 858		return 0xFF;
 859	case 0x30:
 860		if (memory->rotation && memory->rotation->readTiltX) {
 861			int32_t x = -memory->rotation->readTiltX(memory->rotation);
 862			x >>= 21;
 863			x += 2047;
 864			return x >> 8;
 865		}
 866		return 7;
 867	case 0x40:
 868		if (memory->rotation && memory->rotation->readTiltY) {
 869			int32_t y = -memory->rotation->readTiltY(memory->rotation);
 870			y >>= 21;
 871			y += 2047;
 872			return y;
 873		}
 874		return 0xFF;
 875	case 0x50:
 876		if (memory->rotation && memory->rotation->readTiltY) {
 877			int32_t y = -memory->rotation->readTiltY(memory->rotation);
 878			y >>= 21;
 879			y += 2047;
 880			return y >> 8;
 881		}
 882		return 7;
 883	case 0x80:
 884		return (mbc7->sr >> 16) & 1;
 885	default:
 886		return 0xFF;
 887	}
 888}
 889
 890void _GBMBC7Write(struct GBMemory* memory, uint16_t address, uint8_t value) {
 891	if ((address & 0xF0) != 0x80) {
 892		return;
 893	}
 894	struct GBMBC7State* mbc7 = &memory->mbcState.mbc7;
 895	GBMBC7Field old = memory->mbcState.mbc7.field;
 896	mbc7->field = GBMBC7FieldClearIO(value);
 897	if (!GBMBC7FieldIsCS(old) && GBMBC7FieldIsCS(value)) {
 898		if (mbc7->state == GBMBC7_STATE_WRITE) {
 899			if (mbc7->writable) {
 900				memory->sramBank[mbc7->address * 2] = mbc7->sr >> 8;
 901				memory->sramBank[mbc7->address * 2 + 1] = mbc7->sr;
 902			}
 903			mbc7->sr = 0x1FFFF;
 904			mbc7->state = GBMBC7_STATE_NULL;
 905		} else {
 906			mbc7->state = GBMBC7_STATE_IDLE;
 907		}
 908	}
 909	if (!GBMBC7FieldIsSK(old) && GBMBC7FieldIsSK(value)) {
 910		if (mbc7->state > GBMBC7_STATE_IDLE && mbc7->state != GBMBC7_STATE_READ) {
 911			mbc7->sr <<= 1;
 912			mbc7->sr |= GBMBC7FieldGetIO(value);
 913			++mbc7->srBits;
 914		}
 915		switch (mbc7->state) {
 916		case GBMBC7_STATE_IDLE:
 917			if (GBMBC7FieldIsIO(value)) {
 918				mbc7->state = GBMBC7_STATE_READ_COMMAND;
 919				mbc7->srBits = 0;
 920				mbc7->sr = 0;
 921			}
 922			break;
 923		case GBMBC7_STATE_READ_COMMAND:
 924			if (mbc7->srBits == 2) {
 925				mbc7->state = GBMBC7_STATE_READ_ADDRESS;
 926				mbc7->srBits = 0;
 927				mbc7->command = mbc7->sr;
 928			}
 929			break;
 930		case GBMBC7_STATE_READ_ADDRESS:
 931			if (mbc7->srBits == 8) {
 932				mbc7->state = GBMBC7_STATE_COMMAND_0 + mbc7->command;
 933				mbc7->srBits = 0;
 934				mbc7->address = mbc7->sr;
 935				if (mbc7->state == GBMBC7_STATE_COMMAND_0) {
 936					switch (mbc7->address >> 6) {
 937					case 0:
 938						mbc7->writable = false;
 939						mbc7->state = GBMBC7_STATE_NULL;
 940						break;
 941					case 3:
 942						mbc7->writable = true;
 943						mbc7->state = GBMBC7_STATE_NULL;
 944						break;
 945					}
 946				}
 947			}
 948			break;
 949		case GBMBC7_STATE_COMMAND_0:
 950			if (mbc7->srBits == 16) {
 951				switch (mbc7->address >> 6) {
 952				case 0:
 953					mbc7->writable = false;
 954					mbc7->state = GBMBC7_STATE_NULL;
 955					break;
 956				case 1:
 957					mbc7->state = GBMBC7_STATE_WRITE;
 958					if (mbc7->writable) {
 959						int i;
 960						for (i = 0; i < 256; ++i) {
 961							memory->sramBank[i * 2] = mbc7->sr >> 8;
 962							memory->sramBank[i * 2 + 1] = mbc7->sr;
 963						}
 964					}
 965					break;
 966				case 2:
 967					mbc7->state = GBMBC7_STATE_WRITE;
 968					if (mbc7->writable) {
 969						int i;
 970						for (i = 0; i < 256; ++i) {
 971							memory->sramBank[i * 2] = 0xFF;
 972							memory->sramBank[i * 2 + 1] = 0xFF;
 973						}
 974					}
 975					break;
 976				case 3:
 977					mbc7->writable = true;
 978					mbc7->state = GBMBC7_STATE_NULL;
 979					break;
 980				}
 981			}
 982			break;
 983		case GBMBC7_STATE_COMMAND_SR_WRITE:
 984			if (mbc7->srBits == 16) {
 985				mbc7->srBits = 0;
 986				mbc7->state = GBMBC7_STATE_WRITE;
 987			}
 988			break;
 989		case GBMBC7_STATE_COMMAND_SR_READ:
 990			if (mbc7->srBits == 1) {
 991				mbc7->sr = memory->sramBank[mbc7->address * 2] << 8;
 992				mbc7->sr |= memory->sramBank[mbc7->address * 2 + 1];
 993				mbc7->srBits = 0;
 994				mbc7->state = GBMBC7_STATE_READ;
 995			}
 996			break;
 997		case GBMBC7_STATE_COMMAND_SR_FILL:
 998			if (mbc7->srBits == 16) {
 999				mbc7->sr = 0xFFFF;
1000				mbc7->srBits = 0;
1001				mbc7->state = GBMBC7_STATE_WRITE;
1002			}
1003			break;
1004		default:
1005			break;
1006		}
1007	} else if (GBMBC7FieldIsSK(old) && !GBMBC7FieldIsSK(value)) {
1008		if (mbc7->state == GBMBC7_STATE_READ) {
1009			mbc7->sr <<= 1;
1010			++mbc7->srBits;
1011			if (mbc7->srBits == 16) {
1012				mbc7->srBits = 0;
1013				mbc7->state = GBMBC7_STATE_NULL;
1014			}
1015		}
1016	}
1017}
1018
1019void _GBHuC3(struct GBMemory* memory, uint16_t address, uint8_t value) {
1020	int bank = value & 0x3F;
1021	if (address & 0x1FFF) {
1022		mLOG(GB_MBC, STUB, "HuC-3 unknown value %04X:%02X", address, value);
1023	}
1024
1025	switch (address >> 13) {
1026	case 0x0:
1027		switch (value) {
1028		case 0xA:
1029			memory->sramAccess = true;
1030			_switchSramBank(memory, memory->sramCurrentBank);
1031			break;
1032		default:
1033			memory->sramAccess = false;
1034			break;
1035		}
1036		break;
1037	case 0x1:
1038		_switchBank(memory, bank);
1039		break;
1040	case 0x2:
1041		_switchSramBank(memory, bank);
1042		break;
1043	default:
1044		// TODO
1045		mLOG(GB_MBC, STUB, "HuC-3 unknown address: %04X:%02X", address, value);
1046		break;
1047	}
1048}
1049
1050void GBMemorySerialize(const struct GBMemory* memory, struct GBSerializedState* state) {
1051	memcpy(state->wram, memory->wram, GB_SIZE_WORKING_RAM);
1052	memcpy(state->hram, memory->hram, GB_SIZE_HRAM);
1053	STORE_16LE(memory->currentBank, 0, &state->memory.currentBank);
1054	state->memory.wramCurrentBank = memory->wramCurrentBank;
1055	state->memory.sramCurrentBank = memory->sramCurrentBank;
1056
1057	STORE_32LE(memory->dmaNext, 0, &state->memory.dmaNext);
1058	STORE_16LE(memory->dmaSource, 0, &state->memory.dmaSource);
1059	STORE_16LE(memory->dmaDest, 0, &state->memory.dmaDest);
1060
1061	STORE_32LE(memory->hdmaNext, 0, &state->memory.hdmaNext);
1062	STORE_16LE(memory->hdmaSource, 0, &state->memory.hdmaSource);
1063	STORE_16LE(memory->hdmaDest, 0, &state->memory.hdmaDest);
1064
1065	STORE_16LE(memory->hdmaRemaining, 0, &state->memory.hdmaRemaining);
1066	state->memory.dmaRemaining = memory->dmaRemaining;
1067	memcpy(state->memory.rtcRegs, memory->rtcRegs, sizeof(state->memory.rtcRegs));
1068
1069	GBSerializedMemoryFlags flags = 0;
1070	flags = GBSerializedMemoryFlagsSetSramAccess(flags, memory->sramAccess);
1071	flags = GBSerializedMemoryFlagsSetRtcAccess(flags, memory->rtcAccess);
1072	flags = GBSerializedMemoryFlagsSetRtcLatched(flags, memory->rtcLatched);
1073	flags = GBSerializedMemoryFlagsSetIme(flags, memory->ime);
1074	flags = GBSerializedMemoryFlagsSetIsHdma(flags, memory->isHdma);
1075	flags = GBSerializedMemoryFlagsSetActiveRtcReg(flags, memory->activeRtcReg);
1076	STORE_16LE(flags, 0, &state->memory.flags);
1077}
1078
1079void GBMemoryDeserialize(struct GBMemory* memory, const struct GBSerializedState* state) {
1080	memcpy(memory->wram, state->wram, GB_SIZE_WORKING_RAM);
1081	memcpy(memory->hram, state->hram, GB_SIZE_HRAM);
1082	LOAD_16LE(memory->currentBank, 0, &state->memory.currentBank);
1083	memory->wramCurrentBank = state->memory.wramCurrentBank;
1084	memory->sramCurrentBank = state->memory.sramCurrentBank;
1085
1086	_switchBank(memory, memory->currentBank);
1087	GBMemorySwitchWramBank(memory, memory->wramCurrentBank);
1088	_switchSramBank(memory, memory->sramCurrentBank);
1089
1090	LOAD_32LE(memory->dmaNext, 0, &state->memory.dmaNext);
1091	LOAD_16LE(memory->dmaSource, 0, &state->memory.dmaSource);
1092	LOAD_16LE(memory->dmaDest, 0, &state->memory.dmaDest);
1093
1094	LOAD_32LE(memory->hdmaNext, 0, &state->memory.hdmaNext);
1095	LOAD_16LE(memory->hdmaSource, 0, &state->memory.hdmaSource);
1096	LOAD_16LE(memory->hdmaDest, 0, &state->memory.hdmaDest);
1097
1098	LOAD_16LE(memory->hdmaRemaining, 0, &state->memory.hdmaRemaining);
1099	memory->dmaRemaining = state->memory.dmaRemaining;
1100	memcpy(memory->rtcRegs, state->memory.rtcRegs, sizeof(state->memory.rtcRegs));
1101
1102	GBSerializedMemoryFlags flags;
1103	LOAD_16LE(flags, 0, &state->memory.flags);
1104	memory->sramAccess = GBSerializedMemoryFlagsGetSramAccess(flags);
1105	memory->rtcAccess = GBSerializedMemoryFlagsGetRtcAccess(flags);
1106	memory->rtcLatched = GBSerializedMemoryFlagsGetRtcLatched(flags);
1107	memory->ime = GBSerializedMemoryFlagsGetIme(flags);
1108	memory->isHdma = GBSerializedMemoryFlagsGetIsHdma(flags);
1109	memory->activeRtcReg = GBSerializedMemoryFlagsGetActiveRtcReg(flags);
1110}
1111
1112void _pristineCow(struct GB* gb) {
1113	if (gb->memory.rom != gb->pristineRom) {
1114		return;
1115	}
1116	gb->memory.rom = anonymousMemoryMap(GB_SIZE_CART_MAX);
1117	memcpy(gb->memory.rom, gb->pristineRom, gb->memory.romSize);
1118	memset(((uint8_t*) gb->memory.rom) + gb->memory.romSize, 0xFF, GB_SIZE_CART_MAX - gb->memory.romSize);
1119	_switchBank(&gb->memory, gb->memory.currentBank);
1120}