all repos — mgba @ b966d71a2cdd7343f4265c1cc60fe1324f046865

mGBA Game Boy Advance Emulator

src/gb/mbc.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 <mgba/internal/gb/mbc.h>
   7
   8#include <mgba/core/interface.h>
   9#include <mgba/internal/sm83/sm83.h>
  10#include <mgba/internal/gb/gb.h>
  11#include <mgba/internal/gb/memory.h>
  12#include <mgba-util/crc32.h>
  13#include <mgba-util/vfs.h>
  14
  15const uint32_t GB_LOGO_HASH = 0x46195417;
  16
  17mLOG_DEFINE_CATEGORY(GB_MBC, "GB MBC", "gb.mbc");
  18
  19static void _GBMBCNone(struct GB* gb, uint16_t address, uint8_t value) {
  20	UNUSED(gb);
  21	UNUSED(address);
  22	UNUSED(value);
  23
  24	mLOG(GB_MBC, GAME_ERROR, "Wrote to invalid MBC");
  25}
  26
  27static void _GBMBC1(struct GB*, uint16_t address, uint8_t value);
  28static void _GBMBC2(struct GB*, uint16_t address, uint8_t value);
  29static void _GBMBC3(struct GB*, uint16_t address, uint8_t value);
  30static void _GBMBC5(struct GB*, uint16_t address, uint8_t value);
  31static void _GBMBC6(struct GB*, uint16_t address, uint8_t value);
  32static void _GBMBC7(struct GB*, uint16_t address, uint8_t value);
  33static void _GBMMM01(struct GB*, uint16_t address, uint8_t value);
  34static void _GBHuC1(struct GB*, uint16_t address, uint8_t value);
  35static void _GBHuC3(struct GB*, uint16_t address, uint8_t value);
  36static void _GBPocketCam(struct GB* gb, uint16_t address, uint8_t value);
  37static void _GBTAMA5(struct GB* gb, uint16_t address, uint8_t value);
  38static void _GBWisdomTree(struct GB* gb, uint16_t address, uint8_t value);
  39static void _GBPKJD(struct GB* gb, uint16_t address, uint8_t value);
  40static void _GBBBD(struct GB* gb, uint16_t address, uint8_t value);
  41static void _GBHitek(struct GB* gb, uint16_t address, uint8_t value);
  42
  43static uint8_t _GBMBC2Read(struct GBMemory*, uint16_t address);
  44static uint8_t _GBMBC6Read(struct GBMemory*, uint16_t address);
  45static uint8_t _GBMBC7Read(struct GBMemory*, uint16_t address);
  46static void _GBMBC7Write(struct GBMemory* memory, uint16_t address, uint8_t value);
  47
  48static uint8_t _GBTAMA5Read(struct GBMemory*, uint16_t address);
  49static uint8_t _GBPKJDRead(struct GBMemory*, uint16_t address);
  50static uint8_t _GBBBDRead(struct GBMemory*, uint16_t address);
  51static uint8_t _GBHitekRead(struct GBMemory*, uint16_t address);
  52
  53static uint8_t _GBPocketCamRead(struct GBMemory*, uint16_t address);
  54static void _GBPocketCamCapture(struct GBMemory*);
  55
  56static void _GBMBC6MapChip(struct GB*, int half, uint8_t value);
  57
  58void GBMBCSwitchBank(struct GB* gb, int bank) {
  59	size_t bankStart = bank * GB_SIZE_CART_BANK0;
  60	if (bankStart + GB_SIZE_CART_BANK0 > gb->memory.romSize) {
  61		mLOG(GB_MBC, GAME_ERROR, "Attempting to switch to an invalid ROM bank: %0X", bank);
  62		bankStart &= (gb->memory.romSize - 1);
  63		bank = bankStart / GB_SIZE_CART_BANK0;
  64	}
  65	gb->memory.romBank = &gb->memory.rom[bankStart];
  66	gb->memory.currentBank = bank;
  67	if (gb->cpu->pc < GB_BASE_VRAM) {
  68		gb->cpu->memory.setActiveRegion(gb->cpu, gb->cpu->pc);
  69	}
  70}
  71
  72void GBMBCSwitchBank0(struct GB* gb, int bank) {
  73	size_t bankStart = bank * GB_SIZE_CART_BANK0;
  74	if (bankStart + GB_SIZE_CART_BANK0 > gb->memory.romSize) {
  75		mLOG(GB_MBC, GAME_ERROR, "Attempting to switch to an invalid ROM bank: %0X", bank);
  76		bankStart &= (gb->memory.romSize - 1);
  77	}
  78	gb->memory.romBase = &gb->memory.rom[bankStart];
  79	gb->memory.currentBank0 = bank;
  80	if (gb->cpu->pc < GB_SIZE_CART_BANK0) {
  81		gb->cpu->memory.setActiveRegion(gb->cpu, gb->cpu->pc);
  82	}
  83}
  84
  85void GBMBCSwitchHalfBank(struct GB* gb, int half, int bank) {
  86	size_t bankStart = bank * GB_SIZE_CART_HALFBANK;
  87	bool isFlash = half ? gb->memory.mbcState.mbc6.flashBank1 : gb->memory.mbcState.mbc6.flashBank0;
  88	if (isFlash) {
  89		if (bankStart + GB_SIZE_CART_HALFBANK > GB_SIZE_MBC6_FLASH) {
  90			mLOG(GB_MBC, GAME_ERROR, "Attempting to switch to an invalid Flash bank: %0X", bank);
  91			bankStart &= GB_SIZE_MBC6_FLASH - 1;
  92			bank = bankStart / GB_SIZE_CART_HALFBANK;
  93		}
  94		bankStart += gb->sramSize - GB_SIZE_MBC6_FLASH;
  95	} else {
  96		if (bankStart + GB_SIZE_CART_HALFBANK > gb->memory.romSize) {
  97			mLOG(GB_MBC, GAME_ERROR, "Attempting to switch to an invalid ROM bank: %0X", bank);
  98			bankStart &= gb->memory.romSize - 1;
  99			bank = bankStart / GB_SIZE_CART_HALFBANK;
 100			if (!bank) {
 101				++bank;
 102			}
 103		}
 104	}
 105	if (!half) {
 106		if (isFlash) {
 107			gb->memory.romBank = &gb->memory.sram[bankStart];
 108		} else {
 109			gb->memory.romBank = &gb->memory.rom[bankStart];
 110		}
 111		gb->memory.currentBank = bank;
 112	} else {
 113		if (isFlash) {
 114			gb->memory.mbcState.mbc6.romBank1 = &gb->memory.sram[bankStart];
 115		} else {
 116			gb->memory.mbcState.mbc6.romBank1 = &gb->memory.rom[bankStart];
 117		}
 118		gb->memory.mbcState.mbc6.currentBank1 = bank;
 119	}
 120	if (gb->cpu->pc < GB_BASE_VRAM) {
 121		gb->cpu->memory.setActiveRegion(gb->cpu, gb->cpu->pc);
 122	}
 123}
 124
 125static bool _isMulticart(const uint8_t* mem) {
 126	bool success;
 127	struct VFile* vf;
 128
 129	vf = VFileFromConstMemory(&mem[GB_SIZE_CART_BANK0 * 0x10], 1024);
 130	success = GBIsROM(vf);
 131	vf->close(vf);
 132
 133	if (!success) {
 134		return false;
 135	}
 136
 137	vf = VFileFromConstMemory(&mem[GB_SIZE_CART_BANK0 * 0x20], 1024);
 138	success = GBIsROM(vf);
 139	vf->close(vf);
 140
 141	if (!success) {
 142		vf = VFileFromConstMemory(&mem[GB_SIZE_CART_BANK0 * 0x30], 1024);
 143		success = GBIsROM(vf);
 144		vf->close(vf);
 145	}
 146	
 147	return success;
 148}
 149
 150static bool _isWisdomTree(const uint8_t* mem, size_t size) {
 151	size_t i;
 152	for (i = 0x134; i < 0x14C; i += 4) {
 153		if (*(uint32_t*) &mem[i] != 0) {
 154			return false;
 155		}
 156	}
 157	for (i = 0xF0; i < 0x100; i += 4) {
 158		if (*(uint32_t*) &mem[i] != 0) {
 159			return false;
 160		}
 161	}
 162	if (mem[0x14D] != 0xE7) {
 163		return false;
 164	}
 165	for (i = 0x300; i < size - 11; ++i) {
 166		if (memcmp(&mem[i], "WISDOM", 6) == 0 && memcmp(&mem[i + 7], "TREE", 4) == 0) {
 167			return true;
 168		}
 169	}
 170	return false;
 171}
 172
 173static enum GBMemoryBankControllerType _detectUnlMBC(const uint8_t* mem, size_t size) {
 174	const struct GBCartridge* cart = (const struct GBCartridge*) &mem[0x100];
 175
 176	switch (cart->type) {
 177		case 0:
 178		if (_isWisdomTree(mem, size)) {
 179			return GB_UNL_WISDOM_TREE;
 180		}
 181		break;
 182	}
 183
 184	uint32_t secondaryLogo = doCrc32(&mem[0x184], 0x30);
 185	switch (secondaryLogo) {
 186	case 0x4fdab691:
 187		return GB_UNL_HITEK;
 188	case 0xc7d8c1df:
 189	case 0x6d1ea662: // Garou
 190		if (mem[0x7FFF] != 0x01) { // Make sure we're not using a "fixed" version
 191			return GB_UNL_BBD;
 192		}
 193	}
 194
 195	return GB_MBC_AUTODETECT;
 196}
 197
 198void GBMBCSwitchSramBank(struct GB* gb, int bank) {
 199	size_t bankStart = bank * GB_SIZE_EXTERNAL_RAM;
 200	if (bankStart + GB_SIZE_EXTERNAL_RAM > gb->sramSize) {
 201		mLOG(GB_MBC, GAME_ERROR, "Attempting to switch to an invalid RAM bank: %0X", bank);
 202		bankStart &= (gb->sramSize - 1);
 203		bank = bankStart / GB_SIZE_EXTERNAL_RAM;
 204	}
 205	gb->memory.sramBank = &gb->memory.sram[bankStart];
 206	gb->memory.sramCurrentBank = bank;
 207}
 208
 209void GBMBCSwitchSramHalfBank(struct GB* gb, int half, int bank) {
 210	size_t bankStart = bank * GB_SIZE_EXTERNAL_RAM_HALFBANK;
 211	size_t sramSize = gb->sramSize - GB_SIZE_MBC6_FLASH;
 212	if (bankStart + GB_SIZE_EXTERNAL_RAM_HALFBANK > sramSize) {
 213		mLOG(GB_MBC, GAME_ERROR, "Attempting to switch to an invalid RAM bank: %0X", bank);
 214		bankStart &= (sramSize - 1);
 215		bank = bankStart / GB_SIZE_EXTERNAL_RAM_HALFBANK;
 216	}
 217	if (!half) {
 218		gb->memory.sramBank = &gb->memory.sram[bankStart];
 219		gb->memory.sramCurrentBank = bank;
 220	} else {
 221		gb->memory.mbcState.mbc6.sramBank1 = &gb->memory.sram[bankStart];
 222		gb->memory.mbcState.mbc6.currentSramBank1 = bank;
 223	}
 224}
 225
 226void GBMBCInit(struct GB* gb) {
 227	const struct GBCartridge* cart = (const struct GBCartridge*) &gb->memory.rom[0x100];
 228	if (gb->memory.rom && gb->memory.romSize) {
 229		if (gb->memory.romSize >= 0x8000) {
 230			const struct GBCartridge* cartFooter = (const struct GBCartridge*) &gb->memory.rom[gb->memory.romSize - 0x7F00];
 231			if (doCrc32(cartFooter->logo, sizeof(cartFooter->logo)) == GB_LOGO_HASH && cartFooter->type >= 0x0B && cartFooter->type <= 0x0D) {
 232				cart = cartFooter;
 233			}
 234		}
 235		switch (cart->ramSize) {
 236		case 0:
 237			gb->sramSize = 0;
 238			break;
 239		case 1:
 240			gb->sramSize = 0x800;
 241			break;
 242		default:
 243		case 2:
 244			gb->sramSize = 0x2000;
 245			break;
 246		case 3:
 247			gb->sramSize = 0x8000;
 248			break;
 249		case 4:
 250			gb->sramSize = 0x20000;
 251			break;
 252		case 5:
 253			gb->sramSize = 0x10000;
 254			break;
 255		}
 256		if (gb->memory.mbcType == GB_MBC_AUTODETECT) {
 257			gb->memory.mbcType = _detectUnlMBC(gb->memory.rom, gb->memory.romSize);
 258		}
 259
 260		if (gb->memory.mbcType == GB_MBC_AUTODETECT) {
 261			switch (cart->type) {
 262			case 0:
 263			case 8:
 264			case 9:
 265				gb->memory.mbcType = GB_MBC_NONE;
 266				break;
 267			case 1:
 268			case 2:
 269			case 3:
 270				gb->memory.mbcType = GB_MBC1;
 271				break;
 272			case 5:
 273			case 6:
 274				gb->memory.mbcType = GB_MBC2;
 275				break;
 276			case 0x0B:
 277			case 0x0C:
 278			case 0x0D:
 279				gb->memory.mbcType = GB_MMM01;
 280				break;
 281			case 0x0F:
 282			case 0x10:
 283				gb->memory.mbcType = GB_MBC3_RTC;
 284				break;
 285			case 0x11:
 286			case 0x12:
 287			case 0x13:
 288				gb->memory.mbcType = GB_MBC3;
 289				break;
 290			default:
 291				mLOG(GB_MBC, WARN, "Unknown MBC type: %02X", cart->type);
 292				// Fall through
 293			case 0x19:
 294			case 0x1A:
 295			case 0x1B:
 296				gb->memory.mbcType = GB_MBC5;
 297				break;
 298			case 0x1C:
 299			case 0x1D:
 300			case 0x1E:
 301				gb->memory.mbcType = GB_MBC5_RUMBLE;
 302				break;
 303			case 0x20:
 304				gb->memory.mbcType = GB_MBC6;
 305				break;
 306			case 0x22:
 307				gb->memory.mbcType = GB_MBC7;
 308				break;
 309			case 0xFC:
 310				gb->memory.mbcType = GB_POCKETCAM;
 311				break;
 312			case 0xFD:
 313				gb->memory.mbcType = GB_TAMA5;
 314				break;
 315			case 0xFE:
 316				gb->memory.mbcType = GB_HuC3;
 317				break;
 318			case 0xFF:
 319				gb->memory.mbcType = GB_HuC1;
 320				break;
 321			}
 322		}
 323	} else {
 324		gb->memory.mbcType = GB_MBC_NONE;
 325	}
 326	gb->memory.mbcRead = NULL;
 327	gb->memory.directSramAccess = true;
 328	switch (gb->memory.mbcType) {
 329	case GB_MBC_NONE:
 330		gb->memory.mbcWrite = _GBMBCNone;
 331		break;
 332	case GB_MBC1:
 333		gb->memory.mbcWrite = _GBMBC1;
 334		if (gb->memory.romSize >= GB_SIZE_CART_BANK0 * 0x31 && _isMulticart(gb->memory.rom)) {
 335			gb->memory.mbcState.mbc1.multicartStride = 4;
 336		} else {
 337			gb->memory.mbcState.mbc1.multicartStride = 5;
 338		}
 339		break;
 340	case GB_MBC2:
 341		gb->memory.mbcWrite = _GBMBC2;
 342		gb->memory.mbcRead = _GBMBC2Read;
 343		gb->memory.directSramAccess = false;
 344		gb->sramSize = 0x100;
 345		break;
 346	case GB_MBC3:
 347		gb->memory.mbcWrite = _GBMBC3;
 348		break;
 349	default:
 350		mLOG(GB_MBC, WARN, "Unknown MBC type: %02X", cart->type);
 351		// Fall through
 352	case GB_MBC5:
 353		gb->memory.mbcWrite = _GBMBC5;
 354		break;
 355	case GB_MBC6:
 356		gb->memory.mbcWrite = _GBMBC6;
 357		gb->memory.mbcRead = _GBMBC6Read;
 358		gb->memory.directSramAccess = false;
 359		gb->sramSize += GB_SIZE_MBC6_FLASH; // Flash is concatenated at the end
 360		break;
 361	case GB_MBC7:
 362		gb->memory.mbcWrite = _GBMBC7;
 363		gb->memory.mbcRead = _GBMBC7Read;
 364		gb->sramSize = 0x100;
 365		break;
 366	case GB_MMM01:
 367		gb->memory.mbcWrite = _GBMMM01;
 368		break;
 369	case GB_HuC1:
 370		gb->memory.mbcWrite = _GBHuC1;
 371		break;
 372	case GB_HuC3:
 373		gb->memory.mbcWrite = _GBHuC3;
 374		break;
 375	case GB_TAMA5:
 376		mLOG(GB_MBC, WARN, "unimplemented MBC: TAMA5");
 377		memset(gb->memory.rtcRegs, 0, sizeof(gb->memory.rtcRegs));
 378		gb->memory.mbcWrite = _GBTAMA5;
 379		gb->memory.mbcRead = _GBTAMA5Read;
 380		gb->sramSize = 0x20;
 381		break;
 382	case GB_MBC3_RTC:
 383		memset(gb->memory.rtcRegs, 0, sizeof(gb->memory.rtcRegs));
 384		gb->memory.mbcWrite = _GBMBC3;
 385		break;
 386	case GB_MBC5_RUMBLE:
 387		gb->memory.mbcWrite = _GBMBC5;
 388		break;
 389	case GB_POCKETCAM:
 390		gb->memory.mbcWrite = _GBPocketCam;
 391		gb->memory.mbcRead = _GBPocketCamRead;
 392		if (gb->memory.cam && gb->memory.cam->startRequestImage) {
 393			gb->memory.cam->startRequestImage(gb->memory.cam, GBCAM_WIDTH, GBCAM_HEIGHT, mCOLOR_ANY);
 394		}
 395		break;
 396	case GB_UNL_WISDOM_TREE:
 397		gb->memory.mbcWrite = _GBWisdomTree;
 398		break;
 399	case GB_UNL_BBD:
 400		gb->memory.mbcWrite = _GBBBD;
 401		gb->memory.mbcRead = _GBBBDRead;
 402		break;
 403	case GB_UNL_HITEK:
 404		gb->memory.mbcWrite = _GBHitek;
 405		gb->memory.mbcRead = _GBHitekRead;
 406		gb->memory.mbcState.bbd.dataSwapMode = 7;
 407		gb->memory.mbcState.bbd.bankSwapMode = 7;
 408		break;
 409	case GB_UNL_PKJD:
 410		gb->memory.mbcWrite = _GBPKJD;
 411		gb->memory.mbcRead = _GBPKJDRead;
 412		break;
 413	}
 414
 415	gb->memory.currentBank = 1;
 416	gb->memory.sramCurrentBank = 0;
 417	gb->memory.sramAccess = false;
 418	gb->memory.rtcAccess = false;
 419	gb->memory.activeRtcReg = 0;
 420	gb->memory.rtcLatched = false;
 421	gb->memory.rtcLastLatch = 0;
 422	if (gb->memory.rtc) {
 423		if (gb->memory.rtc->sample) {
 424			gb->memory.rtc->sample(gb->memory.rtc);
 425		}
 426		gb->memory.rtcLastLatch = gb->memory.rtc->unixTime(gb->memory.rtc);
 427	} else {
 428		gb->memory.rtcLastLatch = time(0);
 429	}
 430	memset(&gb->memory.rtcRegs, 0, sizeof(gb->memory.rtcRegs));
 431
 432	GBResizeSram(gb, gb->sramSize);
 433
 434	if (gb->memory.mbcType == GB_MBC3_RTC) {
 435		GBMBCRTCRead(gb);
 436	}
 437}
 438
 439void GBMBCReset(struct GB* gb) {
 440	gb->memory.currentBank0 = 0;
 441	gb->memory.romBank = &gb->memory.rom[GB_SIZE_CART_BANK0];
 442
 443	memset(&gb->memory.mbcState, 0, sizeof(gb->memory.mbcState));
 444	GBMBCInit(gb);
 445	switch (gb->memory.mbcType) {
 446	case GB_MBC1:
 447		gb->memory.mbcState.mbc1.mode = 0;
 448		gb->memory.mbcState.mbc1.bankLo = 1;
 449		break;
 450	case GB_MBC6:
 451		GBMBCSwitchHalfBank(gb, 0, 2);
 452		GBMBCSwitchHalfBank(gb, 1, 3);
 453		gb->memory.mbcState.mbc6.sramAccess = false;
 454		GBMBCSwitchSramHalfBank(gb, 0, 0);
 455		GBMBCSwitchSramHalfBank(gb, 0, 1);
 456		break;
 457	case GB_MMM01:
 458		GBMBCSwitchBank0(gb, gb->memory.romSize / GB_SIZE_CART_BANK0 - 2);
 459		GBMBCSwitchBank(gb, gb->memory.romSize / GB_SIZE_CART_BANK0 - 1);
 460		break;
 461	default:
 462		break;
 463	}
 464	gb->memory.sramBank = gb->memory.sram;
 465}
 466
 467static void _latchRtc(struct mRTCSource* rtc, uint8_t* rtcRegs, time_t* rtcLastLatch) {
 468	time_t t;
 469	if (rtc) {
 470		if (rtc->sample) {
 471			rtc->sample(rtc);
 472		}
 473		t = rtc->unixTime(rtc);
 474	} else {
 475		t = time(0);
 476	}
 477	time_t currentLatch = t;
 478	t -= *rtcLastLatch;
 479	*rtcLastLatch = currentLatch;
 480
 481	int64_t diff;
 482	diff = rtcRegs[0] + t % 60;
 483	if (diff < 0) {
 484		diff += 60;
 485		t -= 60;
 486	}
 487	rtcRegs[0] = diff % 60;
 488	t /= 60;
 489	t += diff / 60;
 490
 491	diff = rtcRegs[1] + t % 60;
 492	if (diff < 0) {
 493		diff += 60;
 494		t -= 60;
 495	}
 496	rtcRegs[1] = diff % 60;
 497	t /= 60;
 498	t += diff / 60;
 499
 500	diff = rtcRegs[2] + t % 24;
 501	if (diff < 0) {
 502		diff += 24;
 503		t -= 24;
 504	}
 505	rtcRegs[2] = diff % 24;
 506	t /= 24;
 507	t += diff / 24;
 508
 509	diff = rtcRegs[3] + ((rtcRegs[4] & 1) << 8) + (t & 0x1FF);
 510	rtcRegs[3] = diff;
 511	rtcRegs[4] &= 0xFE;
 512	rtcRegs[4] |= (diff >> 8) & 1;
 513	if (diff & 0x200) {
 514		rtcRegs[4] |= 0x80;
 515	}
 516}
 517
 518static void _GBMBC1Update(struct GB* gb) {
 519	struct GBMBC1State* state = &gb->memory.mbcState.mbc1;
 520	int bank = state->bankLo;
 521	bank &= (1 << state->multicartStride) - 1;
 522	bank |= state->bankHi << state->multicartStride;
 523	if (state->mode) {
 524		GBMBCSwitchBank0(gb, state->bankHi << state->multicartStride);
 525		GBMBCSwitchSramBank(gb, state->bankHi & 3);
 526	} else {
 527		GBMBCSwitchBank0(gb, 0);
 528		GBMBCSwitchSramBank(gb, 0);
 529	}
 530	if (!(state->bankLo & 0x1F)) {
 531		++state->bankLo;
 532		++bank;
 533	}
 534	GBMBCSwitchBank(gb, bank);
 535}
 536
 537void _GBMBC1(struct GB* gb, uint16_t address, uint8_t value) {
 538	struct GBMemory* memory = &gb->memory;
 539	int bank = value & 0x1F;
 540	switch (address >> 13) {
 541	case 0x0:
 542		switch (value & 0xF) {
 543		case 0:
 544			memory->sramAccess = false;
 545			break;
 546		case 0xA:
 547			memory->sramAccess = true;
 548			GBMBCSwitchSramBank(gb, memory->sramCurrentBank);
 549			break;
 550		default:
 551			// TODO
 552			mLOG(GB_MBC, STUB, "MBC1 unknown value %02X", value);
 553			break;
 554		}
 555		break;
 556	case 0x1:
 557		memory->mbcState.mbc1.bankLo = bank;
 558		_GBMBC1Update(gb);
 559		break;
 560	case 0x2:
 561		bank &= 3;
 562		memory->mbcState.mbc1.bankHi = bank;
 563		_GBMBC1Update(gb);
 564		break;
 565	case 0x3:
 566		memory->mbcState.mbc1.mode = value & 1;
 567		_GBMBC1Update(gb);
 568		break;
 569	default:
 570		// TODO
 571		mLOG(GB_MBC, STUB, "MBC1 unknown address: %04X:%02X", address, value);
 572		break;
 573	}
 574}
 575
 576void _GBMBC2(struct GB* gb, uint16_t address, uint8_t value) {
 577	struct GBMemory* memory = &gb->memory;
 578	int shift = (address & 1) * 4;
 579	int bank = value & 0xF;
 580	switch ((address & 0xC100) >> 8) {
 581	case 0x0:
 582		switch (value & 0x0F) {
 583		case 0:
 584			memory->sramAccess = false;
 585			break;
 586		case 0xA:
 587			memory->sramAccess = true;
 588			break;
 589		default:
 590			// TODO
 591			mLOG(GB_MBC, STUB, "MBC2 unknown value %02X", value);
 592			break;
 593		}
 594		break;
 595	case 0x1:
 596		if (!bank) {
 597			++bank;
 598		}
 599		GBMBCSwitchBank(gb, bank);
 600		break;
 601	case 0x80:
 602	case 0x81:
 603	case 0x82:
 604	case 0x83:
 605		if (!memory->sramAccess) {
 606			return;
 607		}
 608		address &= 0x1FF;
 609		memory->sramBank[(address >> 1)] &= 0xF0 >> shift;
 610		memory->sramBank[(address >> 1)] |= (value & 0xF) << shift;
 611		break;
 612	default:
 613		// TODO
 614		mLOG(GB_MBC, STUB, "MBC2 unknown address: %04X:%02X", address, value);
 615		break;
 616	}
 617}
 618
 619static uint8_t _GBMBC2Read(struct GBMemory* memory, uint16_t address) {
 620	if (!memory->sramAccess) {
 621		return 0xFF;
 622	}
 623	address &= 0x1FF;
 624	int shift = (address & 1) * 4;
 625	return (memory->sramBank[(address >> 1)] >> shift) | 0xF0;
 626}
 627
 628void _GBMBC3(struct GB* gb, uint16_t address, uint8_t value) {
 629	struct GBMemory* memory = &gb->memory;
 630	int bank = value;
 631	switch (address >> 13) {
 632	case 0x0:
 633		switch (value & 0xF) {
 634		case 0:
 635			memory->sramAccess = false;
 636			break;
 637		case 0xA:
 638			memory->sramAccess = true;
 639			GBMBCSwitchSramBank(gb, memory->sramCurrentBank);
 640			break;
 641		default:
 642			// TODO
 643			mLOG(GB_MBC, STUB, "MBC3 unknown value %02X", value);
 644			break;
 645		}
 646		break;
 647	case 0x1:
 648		if (gb->memory.romSize < GB_SIZE_CART_BANK0 * 0x80) {
 649			bank &= 0x7F;
 650		}
 651		if (!bank) {
 652			++bank;
 653		}
 654		GBMBCSwitchBank(gb, bank);
 655		break;
 656	case 0x2:
 657		bank &= 0xF;
 658		if (bank < 8) {
 659			GBMBCSwitchSramBank(gb, value);
 660			memory->rtcAccess = false;
 661		} else if (bank <= 0xC) {
 662			memory->activeRtcReg = bank - 8;
 663			memory->rtcAccess = true;
 664		}
 665		break;
 666	case 0x3:
 667		if (memory->rtcLatched && value == 0) {
 668			memory->rtcLatched = false;
 669		} else if (!memory->rtcLatched && value == 1) {
 670			_latchRtc(gb->memory.rtc, gb->memory.rtcRegs, &gb->memory.rtcLastLatch);
 671			memory->rtcLatched = true;
 672		}
 673		break;
 674	}
 675}
 676
 677void _GBMBC5(struct GB* gb, uint16_t address, uint8_t value) {
 678	struct GBMemory* memory = &gb->memory;
 679	int bank;
 680	switch (address >> 12) {
 681	case 0x0:
 682	case 0x1:
 683		switch (value) {
 684		case 0:
 685			memory->sramAccess = false;
 686			break;
 687		case 0xA:
 688			memory->sramAccess = true;
 689			GBMBCSwitchSramBank(gb, memory->sramCurrentBank);
 690			break;
 691		default:
 692			// TODO
 693			mLOG(GB_MBC, STUB, "MBC5 unknown value %02X", value);
 694			break;
 695		}
 696		break;
 697	case 0x2:
 698		bank = (memory->currentBank & 0x100) | value;
 699		GBMBCSwitchBank(gb, bank);
 700		break;
 701	case 0x3:
 702		bank = (memory->currentBank & 0xFF) | ((value & 1) << 8);
 703		GBMBCSwitchBank(gb, bank);
 704		break;
 705	case 0x4:
 706	case 0x5:
 707		if (memory->mbcType == GB_MBC5_RUMBLE && memory->rumble) {
 708			memory->rumble->setRumble(memory->rumble, (value >> 3) & 1);
 709			value &= ~8;
 710		}
 711		GBMBCSwitchSramBank(gb, value & 0xF);
 712		break;
 713	default:
 714		// TODO
 715		mLOG(GB_MBC, STUB, "MBC5 unknown address: %04X:%02X", address, value);
 716		break;
 717	}
 718}
 719
 720void _GBMBC6(struct GB* gb, uint16_t address, uint8_t value) {
 721	struct GBMemory* memory = &gb->memory;
 722	int bank = value;
 723	switch (address >> 10) {
 724	case 0:
 725		switch (value) {
 726		case 0:
 727			memory->sramAccess = false;
 728			break;
 729		case 0xA:
 730			memory->sramAccess = true;
 731			break;
 732		default:
 733			// TODO
 734			mLOG(GB_MBC, STUB, "MBC6 unknown value %02X", value);
 735			break;
 736		}
 737		break;
 738	case 0x1:
 739		GBMBCSwitchSramHalfBank(gb, 0, bank);
 740		break;
 741	case 0x2:
 742		GBMBCSwitchSramHalfBank(gb, 1, bank);
 743		break;
 744	case 0x3:
 745		mLOG(GB_MBC, STUB, "MBC6 unimplemented flash OE write: %04X:%02X", address, value);
 746		break;
 747	case 0x4:
 748		mLOG(GB_MBC, STUB, "MBC6 unimplemented flash WE write: %04X:%02X", address, value);
 749		break;
 750	case 0x8:
 751	case 0x9:
 752		GBMBCSwitchHalfBank(gb, 0, bank);
 753		break;
 754	case 0xA:
 755	case 0xB:
 756		_GBMBC6MapChip(gb, 0, value);
 757		break;
 758	case 0xC:
 759	case 0xD:
 760		GBMBCSwitchHalfBank(gb, 1, bank);
 761		break;
 762	case 0xE:
 763	case 0xF:
 764		_GBMBC6MapChip(gb, 1, value);
 765		break;
 766	case 0x28:
 767	case 0x29:
 768	case 0x2A:
 769	case 0x2B:
 770		if (memory->sramAccess) {
 771			memory->sramBank[address & (GB_SIZE_EXTERNAL_RAM_HALFBANK - 1)] = value;
 772		}
 773		break;
 774	case 0x2C:
 775	case 0x2D:
 776	case 0x2E:
 777	case 0x2F:
 778		if (memory->sramAccess) {
 779			memory->mbcState.mbc6.sramBank1[address & (GB_SIZE_EXTERNAL_RAM_HALFBANK - 1)] = value;
 780		}
 781		break;
 782	default:
 783		mLOG(GB_MBC, STUB, "MBC6 unknown address: %04X:%02X", address, value);
 784		break;
 785	}
 786}
 787
 788uint8_t _GBMBC6Read(struct GBMemory* memory, uint16_t address) {
 789	if (!memory->sramAccess) {
 790		return 0xFF;
 791	}
 792	switch (address >> 12) {
 793	case 0xA:
 794		return memory->sramBank[address & (GB_SIZE_EXTERNAL_RAM_HALFBANK - 1)];
 795	case 0xB:
 796		return memory->mbcState.mbc6.sramBank1[address & (GB_SIZE_EXTERNAL_RAM_HALFBANK - 1)];
 797	}
 798	return 0xFF;
 799}
 800
 801static void _GBMBC6MapChip(struct GB* gb, int half, uint8_t value) {
 802	if (!half) {
 803		gb->memory.mbcState.mbc6.flashBank0 = !!(value & 0x08);
 804		GBMBCSwitchHalfBank(gb, half, gb->memory.currentBank);
 805	} else {
 806		gb->memory.mbcState.mbc6.flashBank1 = !!(value & 0x08);
 807		GBMBCSwitchHalfBank(gb, half, gb->memory.mbcState.mbc6.currentBank1);
 808	}
 809}
 810
 811void _GBMBC7(struct GB* gb, uint16_t address, uint8_t value) {
 812	int bank = value & 0x7F;
 813	switch (address >> 13) {
 814	case 0x0:
 815		switch (value) {
 816		default:
 817		case 0:
 818			gb->memory.mbcState.mbc7.access = 0;
 819			break;
 820		case 0xA:
 821			gb->memory.mbcState.mbc7.access |= 1;
 822			break;
 823		}
 824		break;
 825	case 0x1:
 826		GBMBCSwitchBank(gb, bank);
 827		break;
 828	case 0x2:
 829		if (value == 0x40) {
 830			gb->memory.mbcState.mbc7.access |= 2;
 831		} else {
 832			gb->memory.mbcState.mbc7.access &= ~2;
 833		}
 834		break;
 835	case 0x5:
 836		_GBMBC7Write(&gb->memory, address, value);
 837		break;
 838	default:
 839		// TODO
 840		mLOG(GB_MBC, STUB, "MBC7 unknown address: %04X:%02X", address, value);
 841		break;
 842	}
 843}
 844
 845uint8_t _GBMBC7Read(struct GBMemory* memory, uint16_t address) {
 846	struct GBMBC7State* mbc7 = &memory->mbcState.mbc7;
 847	if (mbc7->access != 3) {
 848		return 0xFF;
 849	}
 850	switch (address & 0xF0) {
 851	case 0x20:
 852		if (memory->rotation && memory->rotation->readTiltX) {
 853			int32_t x = -memory->rotation->readTiltX(memory->rotation);
 854			x >>= 21;
 855			x += 0x81D0;
 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 += 0x81D0;
 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 += 0x81D0;
 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 += 0x81D0;
 880			return y >> 8;
 881		}
 882		return 7;
 883	case 0x60:
 884		return 0;
 885	case 0x80:
 886		return mbc7->eeprom;
 887	default:
 888		return 0xFF;
 889	}
 890}
 891
 892static void _GBMBC7Write(struct GBMemory* memory, uint16_t address, uint8_t value) {
 893	struct GBMBC7State* mbc7 = &memory->mbcState.mbc7;
 894	if (mbc7->access != 3) {
 895		return;
 896	}
 897	switch (address & 0xF0) {
 898	case 0x00:
 899		mbc7->latch = (value & 0x55) == 0x55;
 900		return;
 901	case 0x10:
 902		mbc7->latch |= (value & 0xAA);
 903		if (mbc7->latch == 0xAB && memory->rotation && memory->rotation->sample) {
 904			memory->rotation->sample(memory->rotation);
 905		}
 906		mbc7->latch = 0;
 907		return;
 908	default:
 909		mLOG(GB_MBC, STUB, "MBC7 unknown register: %04X:%02X", address, value);
 910		return;
 911	case 0x80:
 912		break;
 913	}
 914	GBMBC7Field old = memory->mbcState.mbc7.eeprom;
 915	value = GBMBC7FieldFillDO(value); // Hi-Z
 916	if (!GBMBC7FieldIsCS(old) && GBMBC7FieldIsCS(value)) {
 917		mbc7->state = GBMBC7_STATE_IDLE;
 918	}
 919	if (!GBMBC7FieldIsCLK(old) && GBMBC7FieldIsCLK(value)) {
 920		if (mbc7->state == GBMBC7_STATE_READ_COMMAND || mbc7->state == GBMBC7_STATE_EEPROM_WRITE || mbc7->state == GBMBC7_STATE_EEPROM_WRAL) {
 921			mbc7->sr <<= 1;
 922			mbc7->sr |= GBMBC7FieldGetDI(value);
 923			++mbc7->srBits;
 924		}
 925		switch (mbc7->state) {
 926		case GBMBC7_STATE_IDLE:
 927			if (GBMBC7FieldIsDI(value)) {
 928				mbc7->state = GBMBC7_STATE_READ_COMMAND;
 929				mbc7->srBits = 0;
 930				mbc7->sr = 0;
 931			}
 932			break;
 933		case GBMBC7_STATE_READ_COMMAND:
 934			if (mbc7->srBits == 10) {
 935				mbc7->state = 0x10 | (mbc7->sr >> 6);
 936				if (mbc7->state & 0xC) {
 937					mbc7->state &= ~0x3;
 938				}
 939				mbc7->srBits = 0;
 940				mbc7->address = mbc7->sr & 0x7F;
 941			}
 942			break;
 943		case GBMBC7_STATE_DO:
 944			value = GBMBC7FieldSetDO(value, mbc7->sr >> 15);
 945			mbc7->sr <<= 1;
 946			--mbc7->srBits;
 947			if (!mbc7->srBits) {
 948				mbc7->state = GBMBC7_STATE_IDLE;
 949			}
 950			break;
 951		default:
 952			break;
 953		}
 954		switch (mbc7->state) {
 955		case GBMBC7_STATE_EEPROM_EWEN:
 956			mbc7->writable = true;
 957			mbc7->state = GBMBC7_STATE_IDLE;
 958			break;
 959		case GBMBC7_STATE_EEPROM_EWDS:
 960			mbc7->writable = false;
 961			mbc7->state = GBMBC7_STATE_IDLE;
 962			break;
 963		case GBMBC7_STATE_EEPROM_WRITE:
 964			if (mbc7->srBits == 16) {
 965				if (mbc7->writable) {
 966					memory->sram[mbc7->address * 2] = mbc7->sr >> 8;
 967					memory->sram[mbc7->address * 2 + 1] = mbc7->sr;
 968				}
 969				mbc7->state = GBMBC7_STATE_IDLE;
 970			}
 971			break;
 972		case GBMBC7_STATE_EEPROM_ERASE:
 973			if (mbc7->writable) {
 974				memory->sram[mbc7->address * 2] = 0xFF;
 975				memory->sram[mbc7->address * 2 + 1] = 0xFF;
 976			}
 977			mbc7->state = GBMBC7_STATE_IDLE;
 978			break;
 979		case GBMBC7_STATE_EEPROM_READ:
 980			mbc7->srBits = 16;
 981			mbc7->sr = memory->sram[mbc7->address * 2] << 8;
 982			mbc7->sr |= memory->sram[mbc7->address * 2 + 1];
 983			mbc7->state = GBMBC7_STATE_DO;
 984			value = GBMBC7FieldClearDO(value);
 985			break;
 986		case GBMBC7_STATE_EEPROM_WRAL:
 987			if (mbc7->srBits == 16) {
 988				if (mbc7->writable) {
 989					int i;
 990					for (i = 0; i < 128; ++i) {
 991						memory->sram[i * 2] = mbc7->sr >> 8;
 992						memory->sram[i * 2 + 1] = mbc7->sr;
 993					}
 994				}
 995				mbc7->state = GBMBC7_STATE_IDLE;
 996			}
 997			break;
 998		case GBMBC7_STATE_EEPROM_ERAL:
 999			if (mbc7->writable) {
1000				int i;
1001				for (i = 0; i < 128; ++i) {
1002					memory->sram[i * 2] = 0xFF;
1003					memory->sram[i * 2 + 1] = 0xFF;
1004				}
1005			}
1006			mbc7->state = GBMBC7_STATE_IDLE;
1007			break;
1008		default:
1009			break;
1010		}
1011	} else if (GBMBC7FieldIsCS(value) && GBMBC7FieldIsCLK(old) && !GBMBC7FieldIsCLK(value)) {
1012		value = GBMBC7FieldSetDO(value, GBMBC7FieldGetDO(old));
1013	}
1014	mbc7->eeprom = value;
1015}
1016
1017void _GBMMM01(struct GB* gb, uint16_t address, uint8_t value) {
1018	struct GBMemory* memory = &gb->memory;
1019	if (!memory->mbcState.mmm01.locked) {
1020		switch (address >> 13) {
1021		case 0x0:
1022			memory->mbcState.mmm01.locked = true;
1023			GBMBCSwitchBank0(gb, memory->mbcState.mmm01.currentBank0);
1024			break;
1025		case 0x1:
1026			memory->mbcState.mmm01.currentBank0 &= ~0x7F;
1027			memory->mbcState.mmm01.currentBank0 |= value & 0x7F;
1028			break;
1029		case 0x2:
1030			memory->mbcState.mmm01.currentBank0 &= ~0x180;
1031			memory->mbcState.mmm01.currentBank0 |= (value & 0x30) << 3;
1032			break;
1033		default:
1034			// TODO
1035			mLOG(GB_MBC, STUB, "MMM01 unknown address: %04X:%02X", address, value);
1036			break;
1037		}
1038		return;
1039	}
1040	switch (address >> 13) {
1041	case 0x0:
1042		switch (value) {
1043		case 0xA:
1044			memory->sramAccess = true;
1045			GBMBCSwitchSramBank(gb, memory->sramCurrentBank);
1046			break;
1047		default:
1048			memory->sramAccess = false;
1049			break;
1050		}
1051		break;
1052	case 0x1:
1053		GBMBCSwitchBank(gb, value + memory->mbcState.mmm01.currentBank0);
1054		break;
1055	case 0x2:
1056		GBMBCSwitchSramBank(gb, value);
1057		break;
1058	default:
1059		// TODO
1060		mLOG(GB_MBC, STUB, "MMM01 unknown address: %04X:%02X", address, value);
1061		break;
1062	}
1063}
1064
1065void _GBHuC1(struct GB* gb, uint16_t address, uint8_t value) {
1066	struct GBMemory* memory = &gb->memory;
1067	int bank = value & 0x3F;
1068	switch (address >> 13) {
1069	case 0x0:
1070		switch (value) {
1071		case 0xE:
1072			memory->sramAccess = false;
1073			break;
1074		default:
1075			memory->sramAccess = true;
1076			GBMBCSwitchSramBank(gb, memory->sramCurrentBank);
1077			break;
1078		}
1079		break;
1080	case 0x1:
1081		GBMBCSwitchBank(gb, bank);
1082		break;
1083	case 0x2:
1084		GBMBCSwitchSramBank(gb, value);
1085		break;
1086	default:
1087		// TODO
1088		mLOG(GB_MBC, STUB, "HuC-1 unknown address: %04X:%02X", address, value);
1089		break;
1090	}
1091}
1092
1093void _GBHuC3(struct GB* gb, uint16_t address, uint8_t value) {
1094	struct GBMemory* memory = &gb->memory;
1095	int bank = value & 0x3F;
1096	if (address & 0x1FFF) {
1097		mLOG(GB_MBC, STUB, "HuC-3 unknown value %04X:%02X", address, value);
1098	}
1099
1100	switch (address >> 13) {
1101	case 0x0:
1102		switch (value) {
1103		case 0xA:
1104			memory->sramAccess = true;
1105			GBMBCSwitchSramBank(gb, memory->sramCurrentBank);
1106			break;
1107		default:
1108			memory->sramAccess = false;
1109			break;
1110		}
1111		break;
1112	case 0x1:
1113		GBMBCSwitchBank(gb, bank);
1114		break;
1115	case 0x2:
1116		GBMBCSwitchSramBank(gb, bank);
1117		break;
1118	default:
1119		// TODO
1120		mLOG(GB_MBC, STUB, "HuC-3 unknown address: %04X:%02X", address, value);
1121		break;
1122	}
1123}
1124
1125void _GBPocketCam(struct GB* gb, uint16_t address, uint8_t value) {
1126	struct GBMemory* memory = &gb->memory;
1127	int bank = value & 0x3F;
1128	switch (address >> 13) {
1129	case 0x0:
1130		switch (value) {
1131		case 0:
1132			memory->sramAccess = false;
1133			break;
1134		case 0xA:
1135			memory->sramAccess = true;
1136			GBMBCSwitchSramBank(gb, memory->sramCurrentBank);
1137			break;
1138		default:
1139			// TODO
1140			mLOG(GB_MBC, STUB, "Pocket Cam unknown value %02X", value);
1141			break;
1142		}
1143		break;
1144	case 0x1:
1145		GBMBCSwitchBank(gb, bank);
1146		break;
1147	case 0x2:
1148		if (value < 0x10) {
1149			GBMBCSwitchSramBank(gb, value);
1150			memory->mbcState.pocketCam.registersActive = false;
1151		} else {
1152			memory->mbcState.pocketCam.registersActive = true;
1153		}
1154		break;
1155	case 0x5:
1156		address &= 0x7F;
1157		if (address == 0 && value & 1) {
1158			value &= 6; // TODO: Timing
1159			_GBPocketCamCapture(memory);
1160		}
1161		if (address < sizeof(memory->mbcState.pocketCam.registers)) {
1162			memory->mbcState.pocketCam.registers[address] = value;
1163		}
1164		break;
1165	default:
1166		mLOG(GB_MBC, STUB, "Pocket Cam unknown address: %04X:%02X", address, value);
1167		break;
1168	}
1169}
1170
1171uint8_t _GBPocketCamRead(struct GBMemory* memory, uint16_t address) {
1172	if (memory->mbcState.pocketCam.registersActive) {
1173		if ((address & 0x7F) == 0) {
1174			return memory->mbcState.pocketCam.registers[0];
1175		}
1176		return 0;
1177	}
1178	return memory->sramBank[address & (GB_SIZE_EXTERNAL_RAM - 1)];
1179}
1180
1181void _GBPocketCamCapture(struct GBMemory* memory) {
1182	if (!memory->cam) {
1183		return;
1184	}
1185	const void* image = NULL;
1186	size_t stride;
1187	enum mColorFormat format;
1188	memory->cam->requestImage(memory->cam, &image, &stride, &format);
1189	if (!image) {
1190		return;
1191	}
1192	memset(&memory->sram[0x100], 0, GBCAM_HEIGHT * GBCAM_WIDTH / 4);
1193	struct GBPocketCamState* pocketCam = &memory->mbcState.pocketCam;
1194	size_t x, y;
1195	for (y = 0; y < GBCAM_HEIGHT; ++y) {
1196		for (x = 0; x < GBCAM_WIDTH; ++x) {
1197			uint32_t gray;
1198			uint32_t color;
1199			switch (format) {
1200			case mCOLOR_XBGR8:
1201			case mCOLOR_XRGB8:
1202			case mCOLOR_ARGB8:
1203			case mCOLOR_ABGR8:
1204				color = ((const uint32_t*) image)[y * stride + x];
1205				gray = (color & 0xFF) + ((color >> 8) & 0xFF) + ((color >> 16) & 0xFF);
1206				break;
1207			case mCOLOR_BGRX8:
1208			case mCOLOR_RGBX8:
1209			case mCOLOR_RGBA8:
1210			case mCOLOR_BGRA8:
1211				color = ((const uint32_t*) image)[y * stride + x];
1212				gray = ((color >> 8) & 0xFF) + ((color >> 16) & 0xFF) + ((color >> 24) & 0xFF);
1213				break;
1214			case mCOLOR_BGR5:
1215			case mCOLOR_RGB5:
1216			case mCOLOR_ARGB5:
1217			case mCOLOR_ABGR5:
1218				color = ((const uint16_t*) image)[y * stride + x];
1219				gray = ((color << 3) & 0xF8) + ((color >> 2) & 0xF8) + ((color >> 7) & 0xF8);
1220				break;
1221			case mCOLOR_BGR565:
1222			case mCOLOR_RGB565:
1223				color = ((const uint16_t*) image)[y * stride + x];
1224				gray = ((color << 3) & 0xF8) + ((color >> 3) & 0xFC) + ((color >> 8) & 0xF8);
1225				break;
1226			case mCOLOR_BGRA5:
1227			case mCOLOR_RGBA5:
1228				color = ((const uint16_t*) image)[y * stride + x];
1229				gray = ((color << 2) & 0xF8) + ((color >> 3) & 0xF8) + ((color >> 8) & 0xF8);
1230				break;
1231			default:
1232				mLOG(GB_MBC, WARN, "Unsupported pixel format: %X", format);
1233				return;
1234			}
1235			uint16_t exposure = (pocketCam->registers[2] << 8) | (pocketCam->registers[3]);
1236			gray = (gray + 1) * exposure / 0x300;
1237			// TODO: Additional processing
1238			int matrixEntry = 3 * ((x & 3) + 4 * (y & 3));
1239			if (gray < pocketCam->registers[matrixEntry + 6]) {
1240				gray = 0x101;
1241			} else if (gray < pocketCam->registers[matrixEntry + 7]) {
1242				gray = 0x100;
1243			} else if (gray < pocketCam->registers[matrixEntry + 8]) {
1244				gray = 0x001;
1245			} else {
1246				gray = 0;
1247			}
1248			int coord = (((x >> 3) & 0xF) * 8 + (y & 0x7)) * 2 + (y & ~0x7) * 0x20;
1249			uint16_t existing;
1250			LOAD_16LE(existing, coord + 0x100, memory->sram);
1251			existing |= gray << (7 - (x & 7));
1252			STORE_16LE(existing, coord + 0x100, memory->sram);
1253		}
1254	}
1255}
1256
1257void _GBTAMA5(struct GB* gb, uint16_t address, uint8_t value) {
1258	struct GBMemory* memory = &gb->memory;
1259	struct GBTAMA5State* tama5 = &memory->mbcState.tama5;
1260	switch (address >> 13) {
1261	case 0x5:
1262		if (address & 1) {
1263			tama5->reg = value;
1264		} else {
1265			value &= 0xF;
1266			if (tama5->reg < GBTAMA5_MAX) {
1267				tama5->registers[tama5->reg] = value;
1268				uint8_t address = ((tama5->registers[GBTAMA5_CS] << 4) & 0x10) | tama5->registers[GBTAMA5_ADDR_LO];
1269				uint8_t out = (tama5->registers[GBTAMA5_WRITE_HI] << 4) | tama5->registers[GBTAMA5_WRITE_LO];
1270				switch (tama5->reg) {
1271				case GBTAMA5_BANK_LO:
1272				case GBTAMA5_BANK_HI:
1273					GBMBCSwitchBank(gb, tama5->registers[GBTAMA5_BANK_LO] | (tama5->registers[GBTAMA5_BANK_HI] << 4));
1274					break;
1275				case GBTAMA5_WRITE_LO:
1276				case GBTAMA5_WRITE_HI:
1277				case GBTAMA5_CS:
1278					break;
1279				case GBTAMA5_ADDR_LO:
1280					switch (tama5->registers[GBTAMA5_CS] >> 1) {
1281					case 0x0: // RAM write
1282						memory->sram[address] = out;
1283						break;
1284					case 0x1: // RAM read
1285						break;
1286					default:
1287						mLOG(GB_MBC, STUB, "TAMA5 unknown address: %X-%02X:%02X", tama5->registers[GBTAMA5_CS] >> 1, address, out);
1288					}
1289					break;
1290				default:
1291					mLOG(GB_MBC, STUB, "TAMA5 unknown write: %02X:%X", tama5->reg, value);
1292					break;
1293				}
1294			} else {
1295				mLOG(GB_MBC, STUB, "TAMA5 unknown write: %02X", tama5->reg);
1296			}
1297		}
1298		break;
1299	default:
1300		mLOG(GB_MBC, STUB, "TAMA5 unknown address: %04X:%02X", address, value);
1301	}
1302}
1303
1304uint8_t _GBTAMA5Read(struct GBMemory* memory, uint16_t address) {
1305	struct GBTAMA5State* tama5 = &memory->mbcState.tama5;
1306	if ((address & 0x1FFF) > 1) {
1307		mLOG(GB_MBC, STUB, "TAMA5 unknown address: %04X", address);
1308	}
1309	if (address & 1) {
1310		return 0xFF;
1311	} else {
1312		uint8_t value = 0xF0;
1313		uint8_t address = ((tama5->registers[GBTAMA5_CS] << 4) & 0x10) | tama5->registers[GBTAMA5_ADDR_LO];
1314		switch (tama5->reg) {
1315		case GBTAMA5_ACTIVE:
1316			return 0xF1;
1317		case GBTAMA5_READ_LO:
1318		case GBTAMA5_READ_HI:
1319			switch (tama5->registers[GBTAMA5_CS] >> 1) {
1320			case 1:
1321				value = memory->sram[address];
1322				break;
1323			default:
1324				mLOG(GB_MBC, STUB, "TAMA5 unknown read: %02X", tama5->reg);
1325				break;
1326			}
1327			if (tama5->reg == GBTAMA5_READ_HI) {
1328				value >>= 4;
1329			}
1330			value |= 0xF0;
1331			return value;
1332		default:
1333			mLOG(GB_MBC, STUB, "TAMA5 unknown read: %02X", tama5->reg);
1334			return 0xF1;
1335		}
1336	}
1337}
1338
1339void _GBWisdomTree(struct GB* gb, uint16_t address, uint8_t value) {
1340	UNUSED(value);
1341	int bank = address & 0x3F;
1342	switch (address >> 14) {
1343	case 0x0:
1344		GBMBCSwitchBank0(gb, bank * 2);
1345		GBMBCSwitchBank(gb, bank * 2 + 1);
1346		break;
1347	default:
1348		// TODO
1349		mLOG(GB_MBC, STUB, "Wisdom Tree unknown address: %04X:%02X", address, value);
1350		break;
1351	}
1352}
1353
1354void _GBPKJD(struct GB* gb, uint16_t address, uint8_t value) {
1355	struct GBMemory* memory = &gb->memory;
1356	switch (address >> 13) {
1357	case 0x2:
1358		if (value < 8) {
1359			memory->directSramAccess = true;
1360			memory->activeRtcReg = 0;
1361		} else if (value >= 0xD && value <= 0xF) {
1362			memory->directSramAccess = false;
1363			memory->rtcAccess = false;
1364			memory->activeRtcReg = value - 8;
1365		}
1366		break;
1367	case 0x5:
1368		if (!memory->sramAccess) {
1369			return;
1370		}
1371		switch (memory->activeRtcReg) {
1372		case 0:
1373			memory->sramBank[address & (GB_SIZE_EXTERNAL_RAM - 1)] = value;
1374			break;
1375		case 5:
1376		case 6:
1377			memory->mbcState.pkjd.reg[memory->activeRtcReg - 5] = value;
1378			break;
1379		case 7:
1380			switch (value) {
1381			case 0x11:
1382				memory->mbcState.pkjd.reg[0]--;
1383				break;
1384			case 0x12:
1385				memory->mbcState.pkjd.reg[1]--;
1386				break;
1387			case 0x41:
1388				memory->mbcState.pkjd.reg[0] += memory->mbcState.pkjd.reg[1];
1389				break;
1390			case 0x42:
1391				memory->mbcState.pkjd.reg[1] += memory->mbcState.pkjd.reg[0];
1392				break;
1393			case 0x51:
1394				memory->mbcState.pkjd.reg[0]++;
1395				break;
1396			case 0x52:
1397				memory->mbcState.pkjd.reg[1]--;
1398				break;
1399			}
1400			break;
1401		}
1402		return;
1403	}
1404	_GBMBC3(gb, address, value);
1405}
1406
1407static uint8_t _GBPKJDRead(struct GBMemory* memory, uint16_t address) {
1408	if (!memory->sramAccess) {
1409		return 0xFF;
1410	}
1411	switch (memory->activeRtcReg) {
1412	case 0:
1413		return memory->sramBank[address & (GB_SIZE_EXTERNAL_RAM - 1)];
1414	case 5:
1415	case 6:
1416		return memory->mbcState.pkjd.reg[memory->activeRtcReg - 5];
1417	default:
1418		return 0;
1419	}
1420}
1421
1422static uint8_t _reorderBits(uint8_t input, const uint8_t* reorder) {
1423	uint8_t newbyte = 0;
1424	int i;
1425	for(i = 0; i < 8; ++i) {
1426		int oldbit = reorder[i];
1427		int newbit = i;
1428		newbyte += ((input >> oldbit) & 1) << newbit;
1429	}
1430
1431	return newbyte;
1432}
1433
1434static const uint8_t _bbdDataReordering[8][8] = {
1435	{ 0, 1, 2, 3, 4, 5, 6, 7 }, // 00 - Normal
1436	{ 0, 1, 2, 3, 4, 5, 6, 7 }, // 01 - NOT KNOWN YET
1437	{ 0, 1, 2, 3, 4, 5, 6, 7 }, // 02 - NOT KNOWN YET
1438	{ 0, 1, 2, 3, 4, 5, 6, 7 }, // 03 - NOT KNOWN YET
1439	{ 0, 5, 1, 3, 4, 2, 6, 7 }, // 04 - Garou
1440	{ 0, 4, 2, 3, 1, 5, 6, 7 }, // 05 - Harry
1441	{ 0, 1, 2, 3, 4, 5, 6, 7 }, // 06 - NOT KNOWN YET
1442	{ 0, 1, 5, 3, 4, 2, 6, 7 }, // 07 - Digimon
1443};
1444
1445static const uint8_t _bbdBankReordering[8][8] = {
1446	{ 0, 1, 2, 3, 4, 5, 6, 7 }, // 00 - Normal
1447	{ 0, 1, 2, 3, 4, 5, 6, 7 }, // 01 - NOT KNOWN YET
1448	{ 0, 1, 2, 3, 4, 5, 6, 7 }, // 02 - NOT KNOWN YET
1449	{ 3, 4, 2, 0, 1, 5, 6, 7 }, // 03 - 0,1 unconfirmed. Digimon/Garou
1450	{ 0, 1, 2, 3, 4, 5, 6, 7 }, // 04 - NOT KNOWN YET
1451	{ 1, 2, 3, 4, 0, 5, 6, 7 }, // 05 - 0,1 unconfirmed. Harry
1452	{ 0, 1, 2, 3, 4, 5, 6, 7 }, // 06 - NOT KNOWN YET
1453	{ 0, 1, 2, 3, 4, 5, 6, 7 }, // 07 - NOT KNOWN YET
1454};
1455
1456void  _GBBBD(struct GB* gb, uint16_t address, uint8_t value) {
1457	struct GBMemory* memory = &gb->memory;
1458	switch (address & 0xF0FF) {
1459	case 0x2000:
1460		value = _reorderBits(value, _bbdBankReordering[memory->mbcState.bbd.bankSwapMode]);
1461		break;
1462	case 0x2001:
1463		memory->mbcState.bbd.dataSwapMode = value & 0x07;
1464		if (!(memory->mbcState.bbd.dataSwapMode == 0x07 || memory->mbcState.bbd.dataSwapMode == 0x05 || memory->mbcState.bbd.dataSwapMode == 0x04 || memory->mbcState.bbd.dataSwapMode == 0x00)) {
1465			mLOG(GB_MBC, STUB, "Bitswap mode unsupported: %X", memory->mbcState.bbd.dataSwapMode);
1466		}
1467		break;
1468	case 0x2080:
1469		memory->mbcState.bbd.bankSwapMode = value & 0x07;
1470		if (!(memory->mbcState.bbd.bankSwapMode == 0x03 || memory->mbcState.bbd.bankSwapMode == 0x05 || memory->mbcState.bbd.bankSwapMode == 0x00)) {
1471			mLOG(GB_MBC, STUB, "Bankswap mode unsupported: %X", memory->mbcState.bbd.dataSwapMode);
1472		}
1473		break;
1474	}
1475	_GBMBC5(gb, address, value);
1476}
1477
1478uint8_t _GBBBDRead(struct GBMemory* memory, uint16_t address) {
1479	switch (address >> 14) {
1480	case 0:
1481	default:
1482		return memory->romBank[address & (GB_SIZE_CART_BANK0 - 1)];
1483	case 1:
1484		return _reorderBits(memory->romBank[address & (GB_SIZE_CART_BANK0 - 1)], _bbdDataReordering[memory->mbcState.bbd.dataSwapMode]);
1485	}
1486}
1487
1488static const uint8_t _hitekDataReordering[8][8] = {
1489	{ 0, 1, 2, 3, 4, 5, 6, 7 },
1490	{ 0, 6, 5, 3, 4, 1, 2, 7 },
1491	{ 0, 5, 6, 3, 4, 2, 1, 7 },
1492	{ 0, 6, 2, 3, 4, 5, 1, 7 },
1493	{ 0, 6, 1, 3, 4, 5, 2, 7 },
1494	{ 0, 1, 6, 3, 4, 5, 2, 7 },
1495	{ 0, 2, 6, 3, 4, 1, 5, 7 },
1496	{ 0, 6, 2, 3, 4, 1, 5, 7 },
1497};
1498
1499static const uint8_t _hitekBankReordering[8][8] = {
1500	{ 0, 1, 2, 3, 4, 5, 6, 7 },
1501	{ 3, 2, 1, 0, 4, 5, 6, 7 },
1502	{ 2, 1, 0, 3, 4, 5, 6, 7 },
1503	{ 1, 0, 3, 2, 4, 5, 6, 7 },
1504	{ 0, 3, 2, 1, 4, 5, 6, 7 },
1505	{ 2, 3, 0, 1, 4, 5, 6, 7 },
1506	{ 3, 0, 1, 2, 4, 5, 6, 7 },
1507	{ 2, 0, 3, 1, 4, 5, 6, 7 },
1508};
1509
1510void  _GBHitek(struct GB* gb, uint16_t address, uint8_t value) {
1511	struct GBMemory* memory = &gb->memory;
1512	switch (address & 0xF0FF) {
1513	case 0x2000:
1514		value = _reorderBits(value, _hitekBankReordering[memory->mbcState.bbd.bankSwapMode]);
1515		break;
1516	case 0x2001:
1517		memory->mbcState.bbd.dataSwapMode = value & 0x07;
1518		break;
1519	case 0x2080:
1520		memory->mbcState.bbd.bankSwapMode = value & 0x07;
1521		break;
1522	case 0x300:
1523		// See hhugboy src/memory/mbc/MbcUnlHitek.cpp for commentary on this return
1524		return;	
1525	}
1526	_GBMBC5(gb, address, value);
1527}
1528
1529uint8_t _GBHitekRead(struct GBMemory* memory, uint16_t address) {
1530	switch (address >> 14) {
1531	case 0:
1532	default:
1533		return memory->romBank[address & (GB_SIZE_CART_BANK0 - 1)];
1534	case 1:
1535		return _reorderBits(memory->romBank[address & (GB_SIZE_CART_BANK0 - 1)], _hitekDataReordering[memory->mbcState.bbd.dataSwapMode]);
1536	}
1537}
1538
1539void GBMBCRTCRead(struct GB* gb) {
1540	struct GBMBCRTCSaveBuffer rtcBuffer;
1541	struct VFile* vf = gb->sramVf;
1542	if (!vf) {
1543		return;
1544	}
1545	vf->seek(vf, gb->sramSize, SEEK_SET);
1546	if (vf->read(vf, &rtcBuffer, sizeof(rtcBuffer)) < (ssize_t) sizeof(rtcBuffer) - 4) {
1547		return;
1548	}
1549
1550	LOAD_32LE(gb->memory.rtcRegs[0], 0, &rtcBuffer.latchedSec);
1551	LOAD_32LE(gb->memory.rtcRegs[1], 0, &rtcBuffer.latchedMin);
1552	LOAD_32LE(gb->memory.rtcRegs[2], 0, &rtcBuffer.latchedHour);
1553	LOAD_32LE(gb->memory.rtcRegs[3], 0, &rtcBuffer.latchedDays);
1554	LOAD_32LE(gb->memory.rtcRegs[4], 0, &rtcBuffer.latchedDaysHi);
1555	LOAD_64LE(gb->memory.rtcLastLatch, 0, &rtcBuffer.unixTime);
1556}
1557
1558void GBMBCRTCWrite(struct GB* gb) {
1559	struct VFile* vf = gb->sramVf;
1560	if (!vf) {
1561		return;
1562	}
1563
1564	uint8_t rtcRegs[5];
1565	memcpy(rtcRegs, gb->memory.rtcRegs, sizeof(rtcRegs));
1566	time_t rtcLastLatch = gb->memory.rtcLastLatch;
1567	_latchRtc(gb->memory.rtc, rtcRegs, &rtcLastLatch);
1568
1569	struct GBMBCRTCSaveBuffer rtcBuffer;
1570	STORE_32LE(rtcRegs[0], 0, &rtcBuffer.sec);
1571	STORE_32LE(rtcRegs[1], 0, &rtcBuffer.min);
1572	STORE_32LE(rtcRegs[2], 0, &rtcBuffer.hour);
1573	STORE_32LE(rtcRegs[3], 0, &rtcBuffer.days);
1574	STORE_32LE(rtcRegs[4], 0, &rtcBuffer.daysHi);
1575	STORE_32LE(gb->memory.rtcRegs[0], 0, &rtcBuffer.latchedSec);
1576	STORE_32LE(gb->memory.rtcRegs[1], 0, &rtcBuffer.latchedMin);
1577	STORE_32LE(gb->memory.rtcRegs[2], 0, &rtcBuffer.latchedHour);
1578	STORE_32LE(gb->memory.rtcRegs[3], 0, &rtcBuffer.latchedDays);
1579	STORE_32LE(gb->memory.rtcRegs[4], 0, &rtcBuffer.latchedDaysHi);
1580	STORE_64LE(gb->memory.rtcLastLatch, 0, &rtcBuffer.unixTime);
1581
1582	if ((size_t) vf->size(vf) < gb->sramSize + sizeof(rtcBuffer)) {
1583		// Writing past the end of the file can invalidate the file mapping
1584		vf->unmap(vf, gb->memory.sram, gb->sramSize);
1585		gb->memory.sram = NULL;
1586	}
1587	vf->seek(vf, gb->sramSize, SEEK_SET);
1588	vf->write(vf, &rtcBuffer, sizeof(rtcBuffer));
1589	if (!gb->memory.sram) {
1590		gb->memory.sram = vf->map(vf, gb->sramSize, MAP_WRITE);
1591		GBMBCSwitchSramBank(gb, gb->memory.sramCurrentBank);
1592	}
1593}