all repos — mgba @ f6523e2c0111710fa79823331eff360f73f5641e

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