all repos — mgba @ ba49e9f1ce00cfb02703147a30051a873aefe572

mGBA Game Boy Advance Emulator

src/gba/hardware.c (view raw)

   1/* Copyright (c) 2013-2015 Jeffrey Pfau
   2 *
   3 * This Source Code Form is subject to the terms of the Mozilla Public
   4 * License, v. 2.0. If a copy of the MPL was not distributed with this
   5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
   6#include <mgba/internal/gba/hardware.h>
   7
   8#include <mgba/internal/arm/macros.h>
   9#include <mgba/internal/gba/io.h>
  10#include <mgba/internal/gba/serialize.h>
  11#include <mgba-util/formatting.h>
  12#include <mgba-util/hash.h>
  13#include <mgba-util/memory.h>
  14
  15#define EREADER_BLOCK_SIZE 40
  16#define EREADER_DOTCODE_STRIDE 1200
  17#define EREADER_DOTCODE_SIZE (EREADER_DOTCODE_STRIDE * 40 + 200)
  18
  19mLOG_DEFINE_CATEGORY(GBA_HW, "GBA Pak Hardware", "gba.hardware");
  20
  21MGBA_EXPORT const int GBA_LUX_LEVELS[10] = { 5, 11, 18, 27, 42, 62, 84, 109, 139, 183 };
  22const uint16_t EREADER_ADDRESS_CODES[] = {
  23	1023,
  24	1174,
  25	2628,
  26	3373,
  27	4233,
  28	6112,
  29	6450,
  30	7771,
  31	8826,
  32	9491,
  33	11201,
  34	11432,
  35	12556,
  36	13925,
  37	14519,
  38	16350,
  39	16629,
  40	18332,
  41	18766,
  42	20007,
  43	21379,
  44	21738,
  45	23096,
  46	23889,
  47	24944,
  48	26137,
  49	26827,
  50	28578,
  51	29190,
  52	30063,
  53	31677,
  54	31956,
  55	33410,
  56	34283,
  57	35641,
  58	35920,
  59	37364,
  60	38557,
  61	38991,
  62	40742,
  63	41735,
  64	42094,
  65	43708,
  66	44501,
  67	45169,
  68	46872,
  69	47562,
  70	48803,
  71	49544,
  72	50913,
  73	51251,
  74	53082,
  75	54014,
  76	54679
  77};
  78
  79const int EREADER_NYBBLE_5BIT[16][5] = {
  80	{ 0, 0, 0, 0, 0 },
  81	{ 0, 0, 0, 0, 1 },
  82	{ 0, 0, 0, 1, 0 },
  83	{ 1, 0, 0, 1, 0 },
  84	{ 0, 0, 1, 0, 0 },
  85	{ 0, 0, 1, 0, 1 },
  86	{ 0, 0, 1, 1, 0 },
  87	{ 1, 0, 1, 1, 0 },
  88	{ 0, 1, 0, 0, 0 },
  89	{ 0, 1, 0, 0, 1 },
  90	{ 0, 1, 0, 1, 0 },
  91	{ 1, 0, 1, 0, 0 },
  92	{ 0, 1, 1, 0, 0 },
  93	{ 0, 1, 1, 0, 1 },
  94	{ 1, 0, 0, 0, 1 },
  95	{ 1, 0, 0, 0, 0 }
  96};
  97
  98const uint8_t EREADER_CALIBRATION_TEMPLATE[] = {
  99	0x43, 0x61, 0x72, 0x64, 0x2d, 0x45, 0x20, 0x52, 0x65, 0x61, 0x64, 0x65, 0x72, 0x20, 0x32, 0x30,
 100	0x30, 0x31, 0x00, 0x00, 0xcf, 0x72, 0x2f, 0x37, 0x3a, 0x3a, 0x3a, 0x38, 0x33, 0x30, 0x30, 0x37,
 101	0x3a, 0x39, 0x37, 0x35, 0x33, 0x2f, 0x2f, 0x34, 0x36, 0x36, 0x37, 0x36, 0x34, 0x31, 0x2d, 0x30,
 102	0x32, 0x34, 0x35, 0x35, 0x34, 0x30, 0x2a, 0x2d, 0x2d, 0x2f, 0x31, 0x32, 0x31, 0x2f, 0x29, 0x2a,
 103	0x2c, 0x2b, 0x2c, 0x2e, 0x2e, 0x2d, 0x18, 0x2d, 0x8f, 0x03, 0x00, 0x00, 0xc0, 0xfd, 0x77, 0x00,
 104	0x00, 0x00, 0x01
 105};
 106
 107static void _readPins(struct GBACartridgeHardware* hw);
 108static void _outputPins(struct GBACartridgeHardware* hw, unsigned pins);
 109
 110static void _rtcReadPins(struct GBACartridgeHardware* hw);
 111static unsigned _rtcOutput(struct GBACartridgeHardware* hw);
 112static void _rtcProcessByte(struct GBACartridgeHardware* hw);
 113static void _rtcUpdateClock(struct GBACartridgeHardware* hw);
 114static unsigned _rtcBCD(unsigned value);
 115
 116static time_t _rtcGenericCallback(struct mRTCSource* source);
 117
 118static void _gyroReadPins(struct GBACartridgeHardware* hw);
 119
 120static void _rumbleReadPins(struct GBACartridgeHardware* hw);
 121
 122static void _lightReadPins(struct GBACartridgeHardware* hw);
 123
 124static uint16_t _gbpRead(struct mKeyCallback*);
 125static uint16_t _gbpSioWriteRegister(struct GBASIODriver* driver, uint32_t address, uint16_t value);
 126static void _gbpSioProcessEvents(struct mTiming* timing, void* user, uint32_t cyclesLate);
 127
 128static void _eReaderReset(struct GBACartridgeHardware* hw);
 129static void _eReaderWriteControl0(struct GBACartridgeHardware* hw, uint8_t value);
 130static void _eReaderWriteControl1(struct GBACartridgeHardware* hw, uint8_t value);
 131static void _eReaderReadData(struct GBACartridgeHardware* hw);
 132
 133static const int RTC_BYTES[8] = {
 134	0, // Force reset
 135	0, // Empty
 136	7, // Date/Time
 137	0, // Force IRQ
 138	1, // Control register
 139	0, // Empty
 140	3, // Time
 141	0 // Empty
 142};
 143
 144void GBAHardwareInit(struct GBACartridgeHardware* hw, uint16_t* base) {
 145	hw->gpioBase = base;
 146	hw->eReaderDots = NULL;
 147	GBAHardwareClear(hw);
 148
 149	hw->gbpCallback.d.readKeys = _gbpRead;
 150	hw->gbpCallback.p = hw;
 151	hw->gbpDriver.d.init = 0;
 152	hw->gbpDriver.d.deinit = 0;
 153	hw->gbpDriver.d.load = 0;
 154	hw->gbpDriver.d.unload = 0;
 155	hw->gbpDriver.d.writeRegister = _gbpSioWriteRegister;
 156	hw->gbpDriver.p = hw;
 157	hw->gbpNextEvent.context = &hw->gbpDriver;
 158	hw->gbpNextEvent.name = "GBA SIO Game Boy Player";
 159	hw->gbpNextEvent.callback = _gbpSioProcessEvents;
 160	hw->gbpNextEvent.priority = 0x80;
 161}
 162
 163void GBAHardwareClear(struct GBACartridgeHardware* hw) {
 164	hw->devices = HW_NONE | (hw->devices & HW_GB_PLAYER_DETECTION);
 165	hw->readWrite = GPIO_WRITE_ONLY;
 166	hw->pinState = 0;
 167	hw->direction = 0;
 168
 169	if (hw->eReaderDots) {
 170		mappedMemoryFree(hw->eReaderDots, EREADER_DOTCODE_SIZE);
 171		hw->eReaderDots = NULL;
 172	}
 173
 174	if (hw->p->sio.drivers.normal == &hw->gbpDriver.d) {
 175		GBASIOSetDriver(&hw->p->sio, 0, SIO_NORMAL_32);
 176	}
 177}
 178
 179void GBAHardwareGPIOWrite(struct GBACartridgeHardware* hw, uint32_t address, uint16_t value) {
 180	if (!hw->gpioBase) {
 181		return;
 182	}
 183	switch (address) {
 184	case GPIO_REG_DATA:
 185		hw->pinState &= ~hw->direction;
 186		hw->pinState |= value & hw->direction;
 187		_readPins(hw);
 188		break;
 189	case GPIO_REG_DIRECTION:
 190		hw->direction = value;
 191		break;
 192	case GPIO_REG_CONTROL:
 193		hw->readWrite = value;
 194		break;
 195	default:
 196		mLOG(GBA_HW, WARN, "Invalid GPIO address");
 197	}
 198	if (hw->readWrite) {
 199		STORE_16(hw->pinState, 0, hw->gpioBase);
 200		STORE_16(hw->direction, 2, hw->gpioBase);
 201		STORE_16(hw->readWrite, 4, hw->gpioBase);
 202	} else {
 203		hw->gpioBase[0] = 0;
 204		hw->gpioBase[1] = 0;
 205		hw->gpioBase[2] = 0;
 206	}
 207}
 208
 209void GBAHardwareInitRTC(struct GBACartridgeHardware* hw) {
 210	hw->devices |= HW_RTC;
 211	hw->rtc.bytesRemaining = 0;
 212
 213	hw->rtc.transferStep = 0;
 214
 215	hw->rtc.bitsRead = 0;
 216	hw->rtc.bits = 0;
 217	hw->rtc.commandActive = 0;
 218	hw->rtc.command = 0;
 219	hw->rtc.control = 0x40;
 220	memset(hw->rtc.time, 0, sizeof(hw->rtc.time));
 221}
 222
 223void _readPins(struct GBACartridgeHardware* hw) {
 224	if (hw->devices & HW_RTC) {
 225		_rtcReadPins(hw);
 226	}
 227
 228	if (hw->devices & HW_GYRO) {
 229		_gyroReadPins(hw);
 230	}
 231
 232	if (hw->devices & HW_RUMBLE) {
 233		_rumbleReadPins(hw);
 234	}
 235
 236	if (hw->devices & HW_LIGHT_SENSOR) {
 237		_lightReadPins(hw);
 238	}
 239}
 240
 241void _outputPins(struct GBACartridgeHardware* hw, unsigned pins) {
 242	if (hw->readWrite) {
 243		uint16_t old;
 244		LOAD_16(old, 0, hw->gpioBase);
 245		old &= hw->direction;
 246		hw->pinState = old | (pins & ~hw->direction & 0xF);
 247		STORE_16(hw->pinState, 0, hw->gpioBase);
 248	}
 249}
 250
 251// == RTC
 252
 253void _rtcReadPins(struct GBACartridgeHardware* hw) {
 254	// Transfer sequence:
 255	// P: 0 | 1 |  2 | 3
 256	// == Initiate
 257	// > HI | - | LO | -
 258	// > HI | - | HI | -
 259	// == Transfer bit (x8)
 260	// > LO | x | HI | -
 261	// > HI | - | HI | -
 262	// < ?? | x | ?? | -
 263	// == Terminate
 264	// >  - | - | LO | -
 265	switch (hw->rtc.transferStep) {
 266	case 0:
 267		if ((hw->pinState & 5) == 1) {
 268			hw->rtc.transferStep = 1;
 269		}
 270		break;
 271	case 1:
 272		if ((hw->pinState & 5) == 5) {
 273			hw->rtc.transferStep = 2;
 274		} else if ((hw->pinState & 5) != 1) {
 275			hw->rtc.transferStep = 0;
 276		}
 277		break;
 278	case 2:
 279		if (!(hw->pinState & 1)) {
 280			hw->rtc.bits &= ~(1 << hw->rtc.bitsRead);
 281			hw->rtc.bits |= ((hw->pinState & 2) >> 1) << hw->rtc.bitsRead;
 282		} else {
 283			if (hw->pinState & 4) {
 284				if (!RTCCommandDataIsReading(hw->rtc.command)) {
 285					++hw->rtc.bitsRead;
 286					if (hw->rtc.bitsRead == 8) {
 287						_rtcProcessByte(hw);
 288					}
 289				} else {
 290					_outputPins(hw, 5 | (_rtcOutput(hw) << 1));
 291					++hw->rtc.bitsRead;
 292					if (hw->rtc.bitsRead == 8) {
 293						--hw->rtc.bytesRemaining;
 294						if (hw->rtc.bytesRemaining <= 0) {
 295							hw->rtc.commandActive = 0;
 296							hw->rtc.command = 0;
 297						}
 298						hw->rtc.bitsRead = 0;
 299					}
 300				}
 301			} else {
 302				hw->rtc.bitsRead = 0;
 303				hw->rtc.bytesRemaining = 0;
 304				hw->rtc.commandActive = 0;
 305				hw->rtc.command = 0;
 306				hw->rtc.transferStep = hw->pinState & 1;
 307				_outputPins(hw, 1);
 308			}
 309		}
 310		break;
 311	}
 312}
 313
 314void _rtcProcessByte(struct GBACartridgeHardware* hw) {
 315	--hw->rtc.bytesRemaining;
 316	if (!hw->rtc.commandActive) {
 317		RTCCommandData command;
 318		command = hw->rtc.bits;
 319		if (RTCCommandDataGetMagic(command) == 0x06) {
 320			hw->rtc.command = command;
 321
 322			hw->rtc.bytesRemaining = RTC_BYTES[RTCCommandDataGetCommand(command)];
 323			hw->rtc.commandActive = hw->rtc.bytesRemaining > 0;
 324			switch (RTCCommandDataGetCommand(command)) {
 325			case RTC_RESET:
 326				hw->rtc.control = 0;
 327				break;
 328			case RTC_DATETIME:
 329			case RTC_TIME:
 330				_rtcUpdateClock(hw);
 331				break;
 332			case RTC_FORCE_IRQ:
 333			case RTC_CONTROL:
 334				break;
 335			}
 336		} else {
 337			mLOG(GBA_HW, WARN, "Invalid RTC command byte: %02X", hw->rtc.bits);
 338		}
 339	} else {
 340		switch (RTCCommandDataGetCommand(hw->rtc.command)) {
 341		case RTC_CONTROL:
 342			hw->rtc.control = hw->rtc.bits;
 343			break;
 344		case RTC_FORCE_IRQ:
 345			mLOG(GBA_HW, STUB, "Unimplemented RTC command %u", RTCCommandDataGetCommand(hw->rtc.command));
 346			break;
 347		case RTC_RESET:
 348		case RTC_DATETIME:
 349		case RTC_TIME:
 350			break;
 351		}
 352	}
 353
 354	hw->rtc.bits = 0;
 355	hw->rtc.bitsRead = 0;
 356	if (!hw->rtc.bytesRemaining) {
 357		hw->rtc.commandActive = 0;
 358		hw->rtc.command = 0;
 359	}
 360}
 361
 362unsigned _rtcOutput(struct GBACartridgeHardware* hw) {
 363	uint8_t outputByte = 0;
 364	if (!hw->rtc.commandActive) {
 365		mLOG(GBA_HW, GAME_ERROR, "Attempting to use RTC without an active command");
 366		return 0;
 367	}
 368	switch (RTCCommandDataGetCommand(hw->rtc.command)) {
 369	case RTC_CONTROL:
 370		outputByte = hw->rtc.control;
 371		break;
 372	case RTC_DATETIME:
 373	case RTC_TIME:
 374		outputByte = hw->rtc.time[7 - hw->rtc.bytesRemaining];
 375		break;
 376	case RTC_FORCE_IRQ:
 377	case RTC_RESET:
 378		break;
 379	}
 380	unsigned output = (outputByte >> hw->rtc.bitsRead) & 1;
 381	return output;
 382}
 383
 384void _rtcUpdateClock(struct GBACartridgeHardware* hw) {
 385	time_t t;
 386	struct mRTCSource* rtc = hw->p->rtcSource;
 387	if (rtc) {
 388		if (rtc->sample) {
 389			rtc->sample(rtc);
 390		}
 391		t = rtc->unixTime(rtc);
 392	} else {
 393		t = time(0);
 394	}
 395	struct tm date;
 396	localtime_r(&t, &date);
 397	hw->rtc.time[0] = _rtcBCD(date.tm_year - 100);
 398	hw->rtc.time[1] = _rtcBCD(date.tm_mon + 1);
 399	hw->rtc.time[2] = _rtcBCD(date.tm_mday);
 400	hw->rtc.time[3] = _rtcBCD(date.tm_wday);
 401	if (RTCControlIsHour24(hw->rtc.control)) {
 402		hw->rtc.time[4] = _rtcBCD(date.tm_hour);
 403	} else {
 404		hw->rtc.time[4] = _rtcBCD(date.tm_hour % 12);
 405	}
 406	hw->rtc.time[5] = _rtcBCD(date.tm_min);
 407	hw->rtc.time[6] = _rtcBCD(date.tm_sec);
 408}
 409
 410unsigned _rtcBCD(unsigned value) {
 411	int counter = value % 10;
 412	value /= 10;
 413	counter += (value % 10) << 4;
 414	return counter;
 415}
 416
 417time_t _rtcGenericCallback(struct mRTCSource* source) {
 418	struct GBARTCGenericSource* rtc = (struct GBARTCGenericSource*) source;
 419	switch (rtc->override) {
 420	case RTC_NO_OVERRIDE:
 421	default:
 422		return time(0);
 423	case RTC_FIXED:
 424		return rtc->value;
 425	case RTC_FAKE_EPOCH:
 426		return rtc->value + rtc->p->video.frameCounter * (int64_t) VIDEO_TOTAL_LENGTH / GBA_ARM7TDMI_FREQUENCY;
 427	}
 428}
 429
 430void GBARTCGenericSourceInit(struct GBARTCGenericSource* rtc, struct GBA* gba) {
 431	rtc->p = gba;
 432	rtc->override = RTC_NO_OVERRIDE;
 433	rtc->value = 0;
 434	rtc->d.sample = 0;
 435	rtc->d.unixTime = _rtcGenericCallback;
 436}
 437
 438// == Gyro
 439
 440void GBAHardwareInitGyro(struct GBACartridgeHardware* hw) {
 441	hw->devices |= HW_GYRO;
 442	hw->gyroSample = 0;
 443	hw->gyroEdge = 0;
 444}
 445
 446void _gyroReadPins(struct GBACartridgeHardware* hw) {
 447	struct mRotationSource* gyro = hw->p->rotationSource;
 448	if (!gyro || !gyro->readGyroZ) {
 449		return;
 450	}
 451
 452	if (hw->pinState & 1) {
 453		if (gyro->sample) {
 454			gyro->sample(gyro);
 455		}
 456		int32_t sample = gyro->readGyroZ(gyro);
 457
 458		// Normalize to ~12 bits, focused on 0x6C0
 459		hw->gyroSample = (sample >> 21) + 0x6C0; // Crop off an extra bit so that we can't go negative
 460	}
 461
 462	if (hw->gyroEdge && !(hw->pinState & 2)) {
 463		// Write bit on falling edge
 464		unsigned bit = hw->gyroSample >> 15;
 465		hw->gyroSample <<= 1;
 466		_outputPins(hw, bit << 2);
 467	}
 468
 469	hw->gyroEdge = !!(hw->pinState & 2);
 470}
 471
 472// == Rumble
 473
 474void GBAHardwareInitRumble(struct GBACartridgeHardware* hw) {
 475	hw->devices |= HW_RUMBLE;
 476}
 477
 478void _rumbleReadPins(struct GBACartridgeHardware* hw) {
 479	struct mRumble* rumble = hw->p->rumble;
 480	if (!rumble) {
 481		return;
 482	}
 483
 484	rumble->setRumble(rumble, !!(hw->pinState & 8));
 485}
 486
 487// == Light sensor
 488
 489void GBAHardwareInitLight(struct GBACartridgeHardware* hw) {
 490	hw->devices |= HW_LIGHT_SENSOR;
 491	hw->lightCounter = 0;
 492	hw->lightEdge = false;
 493	hw->lightSample = 0xFF;
 494}
 495
 496void _lightReadPins(struct GBACartridgeHardware* hw) {
 497	if (hw->pinState & 4) {
 498		// Boktai chip select
 499		return;
 500	}
 501	if (hw->pinState & 2) {
 502		struct GBALuminanceSource* lux = hw->p->luminanceSource;
 503		mLOG(GBA_HW, DEBUG, "[SOLAR] Got reset");
 504		hw->lightCounter = 0;
 505		if (lux) {
 506			lux->sample(lux);
 507			hw->lightSample = lux->readLuminance(lux);
 508		} else {
 509			hw->lightSample = 0xFF;
 510		}
 511	}
 512	if ((hw->pinState & 1) && hw->lightEdge) {
 513		++hw->lightCounter;
 514	}
 515	hw->lightEdge = !(hw->pinState & 1);
 516
 517	bool sendBit = hw->lightCounter >= hw->lightSample;
 518	_outputPins(hw, sendBit << 3);
 519	mLOG(GBA_HW, DEBUG, "[SOLAR] Output %u with pins %u", hw->lightCounter, hw->pinState);
 520}
 521
 522// == Tilt
 523
 524void GBAHardwareInitTilt(struct GBACartridgeHardware* hw) {
 525	hw->devices |= HW_TILT;
 526	hw->tiltX = 0xFFF;
 527	hw->tiltY = 0xFFF;
 528	hw->tiltState = 0;
 529}
 530
 531void GBAHardwareTiltWrite(struct GBACartridgeHardware* hw, uint32_t address, uint8_t value) {
 532	switch (address) {
 533	case 0x8000:
 534		if (value == 0x55) {
 535			hw->tiltState = 1;
 536		} else {
 537			mLOG(GBA_HW, GAME_ERROR, "Tilt sensor wrote wrong byte to %04x: %02x", address, value);
 538		}
 539		break;
 540	case 0x8100:
 541		if (value == 0xAA && hw->tiltState == 1) {
 542			hw->tiltState = 0;
 543			struct mRotationSource* rotationSource = hw->p->rotationSource;
 544			if (!rotationSource || !rotationSource->readTiltX || !rotationSource->readTiltY) {
 545				return;
 546			}
 547			if (rotationSource->sample) {
 548				rotationSource->sample(rotationSource);
 549			}
 550			int32_t x = rotationSource->readTiltX(rotationSource);
 551			int32_t y = rotationSource->readTiltY(rotationSource);
 552			// Normalize to ~12 bits, focused on 0x3A0
 553			hw->tiltX = (x >> 21) + 0x3A0; // Crop off an extra bit so that we can't go negative
 554			hw->tiltY = (y >> 21) + 0x3A0;
 555		} else {
 556			mLOG(GBA_HW, GAME_ERROR, "Tilt sensor wrote wrong byte to %04x: %02x", address, value);
 557		}
 558		break;
 559	default:
 560		mLOG(GBA_HW, GAME_ERROR, "Invalid tilt sensor write to %04x: %02x", address, value);
 561		break;
 562	}
 563}
 564
 565uint8_t GBAHardwareTiltRead(struct GBACartridgeHardware* hw, uint32_t address) {
 566	switch (address) {
 567	case 0x8200:
 568		return hw->tiltX & 0xFF;
 569	case 0x8300:
 570		return ((hw->tiltX >> 8) & 0xF) | 0x80;
 571	case 0x8400:
 572		return hw->tiltY & 0xFF;
 573	case 0x8500:
 574		return (hw->tiltY >> 8) & 0xF;
 575	default:
 576		mLOG(GBA_HW, GAME_ERROR, "Invalid tilt sensor read from %04x", address);
 577		break;
 578	}
 579	return 0xFF;
 580}
 581
 582// == Game Boy Player
 583
 584static const uint16_t _logoPalette[] = {
 585	0xFFDF, 0x640C, 0xE40C, 0xE42D, 0x644E, 0xE44E, 0xE46E, 0x68AF,
 586	0xE8B0, 0x68D0, 0x68F0, 0x6911, 0xE911, 0x6D32, 0xED32, 0xED73,
 587	0x6D93, 0xED94, 0x6DB4, 0xF1D5, 0x71F5, 0xF1F6, 0x7216, 0x7257,
 588	0xF657, 0x7678, 0xF678, 0xF699, 0xF6B9, 0x76D9, 0xF6DA, 0x7B1B,
 589	0xFB1B, 0xFB3C, 0x7B5C, 0x7B7D, 0xFF7D, 0x7F9D, 0x7FBE, 0x7FFF,
 590	0x642D, 0x648E, 0xE88F, 0xE8F1, 0x6D52, 0x6D73, 0xF1B4, 0xF216,
 591	0x7237, 0x7698, 0x7AFA, 0xFAFA, 0xFB5C, 0xFFBE, 0x7FDE, 0xFFFF,
 592	0xFFFF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
 593};
 594
 595static const uint32_t _logoHash = 0xEEDA6963;
 596
 597static const uint32_t _gbpTxData[] = {
 598	0x0000494E, 0x0000494E,
 599	0xB6B1494E, 0xB6B1544E,
 600	0xABB1544E, 0xABB14E45,
 601	0xB1BA4E45, 0xB1BA4F44,
 602	0xB0BB4F44, 0xB0BB8002,
 603	0x10000010, 0x20000013,
 604	0x30000003
 605};
 606
 607bool GBAHardwarePlayerCheckScreen(const struct GBAVideo* video) {
 608	if (memcmp(video->palette, _logoPalette, sizeof(_logoPalette)) != 0) {
 609		return false;
 610	}
 611	uint32_t hash = hash32(&video->renderer->vram[0x4000], 0x4000, 0);
 612	return hash == _logoHash;
 613}
 614
 615void GBAHardwarePlayerUpdate(struct GBA* gba) {
 616	if (gba->memory.hw.devices & HW_GB_PLAYER) {
 617		if (GBAHardwarePlayerCheckScreen(&gba->video)) {
 618			++gba->memory.hw.gbpInputsPosted;
 619			gba->memory.hw.gbpInputsPosted %= 3;
 620			gba->keyCallback = &gba->memory.hw.gbpCallback.d;
 621		} else {
 622			// TODO: Save and restore
 623			gba->keyCallback = 0;
 624		}
 625		gba->memory.hw.gbpTxPosition = 0;
 626		return;
 627	}
 628	if (gba->keyCallback || gba->sio.drivers.normal) {
 629		return;
 630	}
 631	if (GBAHardwarePlayerCheckScreen(&gba->video)) {
 632		gba->memory.hw.devices |= HW_GB_PLAYER;
 633		gba->memory.hw.gbpInputsPosted = 0;
 634		gba->keyCallback = &gba->memory.hw.gbpCallback.d;
 635		GBASIOSetDriver(&gba->sio, &gba->memory.hw.gbpDriver.d, SIO_NORMAL_32);
 636	}
 637}
 638
 639uint16_t _gbpRead(struct mKeyCallback* callback) {
 640	struct GBAGBPKeyCallback* gbpCallback = (struct GBAGBPKeyCallback*) callback;
 641	if (gbpCallback->p->gbpInputsPosted == 2) {
 642		return 0xF0;
 643	}
 644	return 0;
 645}
 646
 647uint16_t _gbpSioWriteRegister(struct GBASIODriver* driver, uint32_t address, uint16_t value) {
 648	struct GBAGBPSIODriver* gbp = (struct GBAGBPSIODriver*) driver;
 649	if (address == REG_SIOCNT) {
 650		if (value & 0x0080) {
 651			uint32_t rx = gbp->p->p->memory.io[REG_SIODATA32_LO >> 1] | (gbp->p->p->memory.io[REG_SIODATA32_HI >> 1] << 16);
 652			if (gbp->p->gbpTxPosition < 12 && gbp->p->gbpTxPosition > 0) {
 653				// TODO: Check expected
 654			} else if (gbp->p->gbpTxPosition >= 12) {
 655				uint32_t mask = 0x33;
 656				// 0x00 = Stop
 657				// 0x11 = Hard Stop
 658				// 0x22 = Start
 659				if (gbp->p->p->rumble) {
 660					gbp->p->p->rumble->setRumble(gbp->p->p->rumble, (rx & mask) == 0x22);
 661				}
 662			}
 663			mTimingDeschedule(&gbp->p->p->timing, &gbp->p->gbpNextEvent);
 664			mTimingSchedule(&gbp->p->p->timing, &gbp->p->gbpNextEvent, 2048);
 665		}
 666		value &= 0x78FB;
 667	}
 668	return value;
 669}
 670
 671void _gbpSioProcessEvents(struct mTiming* timing, void* user, uint32_t cyclesLate) {
 672	UNUSED(timing);
 673	UNUSED(cyclesLate);
 674	struct GBAGBPSIODriver* gbp = user;
 675	uint32_t tx = 0;
 676	int txPosition = gbp->p->gbpTxPosition;
 677	if (txPosition > 16) {
 678		gbp->p->gbpTxPosition = 0;
 679		txPosition = 0;
 680	} else if (txPosition > 12) {
 681		txPosition = 12;
 682	}
 683	tx = _gbpTxData[txPosition];
 684	++gbp->p->gbpTxPosition;
 685	gbp->p->p->memory.io[REG_SIODATA32_LO >> 1] = tx;
 686	gbp->p->p->memory.io[REG_SIODATA32_HI >> 1] = tx >> 16;
 687	if (GBASIONormalIsIrq(gbp->d.p->siocnt)) {
 688		GBARaiseIRQ(gbp->p->p, IRQ_SIO, cyclesLate);
 689	}
 690	gbp->d.p->siocnt = GBASIONormalClearStart(gbp->d.p->siocnt);
 691	gbp->p->p->memory.io[REG_SIOCNT >> 1] = gbp->d.p->siocnt & ~0x0080;
 692}
 693
 694// == e-Reader
 695
 696void GBAHardwareInitEReader(struct GBACartridgeHardware* hw) {
 697	hw->devices |= HW_EREADER;
 698	_eReaderReset(hw);
 699
 700	if (hw->p->memory.savedata.data[0xD000] == 0xFF) {
 701		memset(&hw->p->memory.savedata.data[0xD000], 0, 0x1000);
 702		memcpy(&hw->p->memory.savedata.data[0xD000], EREADER_CALIBRATION_TEMPLATE, sizeof(EREADER_CALIBRATION_TEMPLATE));
 703	}
 704	if (hw->p->memory.savedata.data[0xE000] == 0xFF) {
 705		memset(&hw->p->memory.savedata.data[0xE000], 0, 0x1000);
 706		memcpy(&hw->p->memory.savedata.data[0xE000], EREADER_CALIBRATION_TEMPLATE, sizeof(EREADER_CALIBRATION_TEMPLATE));
 707	}
 708}
 709
 710void GBAHardwareEReaderWrite(struct GBACartridgeHardware* hw, uint32_t address, uint16_t value) {
 711	address &= 0x700FF;
 712	switch (address >> 17) {
 713	case 0:
 714		hw->eReaderRegisterUnk = value & 0xF;
 715		break;
 716	case 1:
 717		hw->eReaderRegisterReset = (value & 0x8A) | 4;
 718		if (value & 2) {
 719			_eReaderReset(hw);
 720		}
 721		break;
 722	case 2:
 723		mLOG(GBA_HW, GAME_ERROR, "e-Reader write to read-only registers: %05X:%04X", address, value);
 724		break;
 725	default:
 726		mLOG(GBA_HW, STUB, "Unimplemented e-Reader write: %05X:%04X", address, value);
 727	}
 728}
 729
 730void GBAHardwareEReaderWriteFlash(struct GBACartridgeHardware* hw, uint32_t address, uint8_t value) {
 731	address &= 0xFFFF;
 732	switch (address) {
 733	case 0xFFB0:
 734		_eReaderWriteControl0(hw, value);
 735		break;
 736	case 0xFFB1:
 737		_eReaderWriteControl1(hw, value);
 738		break;
 739	case 0xFFB2:
 740		hw->eReaderRegisterLed &= 0xFF00;
 741		hw->eReaderRegisterLed |= value;
 742		break;
 743	case 0xFFB3:
 744		hw->eReaderRegisterLed &= 0x00FF;
 745		hw->eReaderRegisterLed |= value << 8;
 746		break;
 747	default:
 748		mLOG(GBA_HW, STUB, "Unimplemented e-Reader write to flash: %04X:%02X", address, value);
 749	}
 750}
 751
 752uint16_t GBAHardwareEReaderRead(struct GBACartridgeHardware* hw, uint32_t address) {
 753	address &= 0x700FF;
 754	uint16_t value;
 755	switch (address >> 17) {
 756	case 0:
 757		return hw->eReaderRegisterUnk;
 758	case 1:
 759		return hw->eReaderRegisterReset;
 760	case 2:
 761		if (address > 0x40088) {
 762			return 0;
 763		}
 764		LOAD_16(value, address & 0xFE, hw->eReaderData);
 765		return value;
 766	}
 767	mLOG(GBA_HW, STUB, "Unimplemented e-Reader read: %05X", address);
 768	return 0;
 769}
 770
 771uint8_t GBAHardwareEReaderReadFlash(struct GBACartridgeHardware* hw, uint32_t address) {
 772	address &= 0xFFFF;
 773	switch (address) {
 774	case 0xFFB0:
 775		return hw->eReaderRegisterControl0;
 776	case 0xFFB1:
 777		return hw->eReaderRegisterControl1;
 778	default:
 779		mLOG(GBA_HW, STUB, "Unimplemented e-Reader read from flash: %04X", address);
 780		return 0;
 781	}
 782}
 783
 784static void _eReaderAnchor(uint8_t* origin) {
 785	origin[EREADER_DOTCODE_STRIDE * 0 + 1] = 1;
 786	origin[EREADER_DOTCODE_STRIDE * 0 + 2] = 1;
 787	origin[EREADER_DOTCODE_STRIDE * 0 + 3] = 1;
 788	origin[EREADER_DOTCODE_STRIDE * 1 + 0] = 1;
 789	origin[EREADER_DOTCODE_STRIDE * 1 + 1] = 1;
 790	origin[EREADER_DOTCODE_STRIDE * 1 + 2] = 1;
 791	origin[EREADER_DOTCODE_STRIDE * 1 + 3] = 1;
 792	origin[EREADER_DOTCODE_STRIDE * 1 + 4] = 1;
 793	origin[EREADER_DOTCODE_STRIDE * 2 + 0] = 1;
 794	origin[EREADER_DOTCODE_STRIDE * 2 + 1] = 1;
 795	origin[EREADER_DOTCODE_STRIDE * 2 + 2] = 1;
 796	origin[EREADER_DOTCODE_STRIDE * 2 + 3] = 1;
 797	origin[EREADER_DOTCODE_STRIDE * 2 + 4] = 1;
 798	origin[EREADER_DOTCODE_STRIDE * 3 + 0] = 1;
 799	origin[EREADER_DOTCODE_STRIDE * 3 + 1] = 1;
 800	origin[EREADER_DOTCODE_STRIDE * 3 + 2] = 1;
 801	origin[EREADER_DOTCODE_STRIDE * 3 + 3] = 1;
 802	origin[EREADER_DOTCODE_STRIDE * 3 + 4] = 1;
 803	origin[EREADER_DOTCODE_STRIDE * 4 + 1] = 1;
 804	origin[EREADER_DOTCODE_STRIDE * 4 + 2] = 1;
 805	origin[EREADER_DOTCODE_STRIDE * 4 + 3] = 1;
 806}
 807
 808static void _eReaderAlignment(uint8_t* origin) {
 809	origin[8] = 1;
 810	origin[10] = 1;
 811	origin[12] = 1;
 812	origin[14] = 1;
 813	origin[16] = 1;
 814	origin[18] = 1;
 815	origin[21] = 1;
 816	origin[23] = 1;
 817	origin[25] = 1;
 818	origin[27] = 1;
 819	origin[29] = 1;
 820	origin[31] = 1;
 821}
 822
 823static void _eReaderAddress(uint8_t* origin, int a) {
 824	origin[EREADER_DOTCODE_STRIDE * 7 + 2] = 1;
 825	uint16_t addr = EREADER_ADDRESS_CODES[a];
 826	int i;
 827	for (i = 0; i < 16; ++i) {
 828		origin[EREADER_DOTCODE_STRIDE * (16 + i) + 2] = (addr >> (15 - i)) & 1;
 829	}
 830}
 831
 832void GBAHardwareEReaderScan(struct GBACartridgeHardware* hw, const void* data, size_t size) {
 833	if (!hw->eReaderDots) {
 834		hw->eReaderDots = anonymousMemoryMap(EREADER_DOTCODE_SIZE);
 835	}
 836	memset(hw->eReaderDots, 0, EREADER_DOTCODE_SIZE);
 837
 838	int base;
 839	switch (size) {
 840	case 2912:
 841		base = 25;
 842		break;
 843	case 1872:
 844		base = 1;
 845		break;
 846	default:
 847		return;
 848	}
 849
 850	size_t i;
 851	for (i = 0; i < (size / 104) + 1; ++i) {
 852		uint8_t* origin = &hw->eReaderDots[35 * i + 200];
 853		_eReaderAnchor(&origin[EREADER_DOTCODE_STRIDE * 0]);
 854		_eReaderAnchor(&origin[EREADER_DOTCODE_STRIDE * 35]);
 855		_eReaderAddress(origin, base + i);
 856	}
 857	for (i = 0; i < size / 104; ++i) {
 858		uint8_t block[1040];
 859		uint8_t* origin = &hw->eReaderDots[35 * i + 200];
 860		_eReaderAlignment(&origin[EREADER_DOTCODE_STRIDE * 2]);
 861		_eReaderAlignment(&origin[EREADER_DOTCODE_STRIDE * 37]);
 862
 863		int b;
 864		for (b = 0; b < 104; ++b) {
 865			const int* nybble5;
 866			nybble5 = EREADER_NYBBLE_5BIT[((const uint8_t*) data)[i * 104 + b] >> 4];
 867			block[b * 10 + 0] = nybble5[0];
 868			block[b * 10 + 1] = nybble5[1];
 869			block[b * 10 + 2] = nybble5[2];
 870			block[b * 10 + 3] = nybble5[3];
 871			block[b * 10 + 4] = nybble5[4];
 872			nybble5 = EREADER_NYBBLE_5BIT[((const uint8_t*) data)[i * 104 + b] & 0xF];
 873			block[b * 10 + 5] = nybble5[0];
 874			block[b * 10 + 6] = nybble5[1];
 875			block[b * 10 + 7] = nybble5[2];
 876			block[b * 10 + 8] = nybble5[3];
 877			block[b * 10 + 9] = nybble5[4];
 878		}
 879
 880		b = 0;
 881		int y;
 882		for (y = 0; y < 3; ++y) {
 883			memcpy(&origin[EREADER_DOTCODE_STRIDE * (4 + y) + 7], &block[b], 26);
 884			b += 26;
 885		}
 886		for (y = 0; y < 26; ++y) {
 887			memcpy(&origin[EREADER_DOTCODE_STRIDE * (7 + y) + 3], &block[b], 34);
 888			b += 34;
 889		}
 890		for (y = 0; y < 3; ++y) {
 891			memcpy(&origin[EREADER_DOTCODE_STRIDE * (33 + y) + 7], &block[b], 26);
 892			b += 26;
 893		}
 894	}
 895	hw->eReaderX = -24;
 896}
 897
 898void _eReaderReset(struct GBACartridgeHardware* hw) {
 899	memset(hw->eReaderData, 0, sizeof(hw->eReaderData));
 900	hw->eReaderRegisterUnk = 0;
 901	hw->eReaderRegisterReset = 4;
 902	hw->eReaderRegisterControl0 = 0;
 903	hw->eReaderRegisterControl1 = 0x80;
 904	hw->eReaderRegisterLed = 0;
 905	hw->eReaderState = 0;
 906	hw->eReaderActiveRegister = 0;
 907}
 908
 909void _eReaderWriteControl0(struct GBACartridgeHardware* hw, uint8_t value) {
 910	EReaderControl0 control = value & 0x7F;
 911	EReaderControl0 oldControl = hw->eReaderRegisterControl0;
 912	if (hw->eReaderState == EREADER_SERIAL_INACTIVE) {
 913		if (EReaderControl0IsClock(oldControl) && EReaderControl0IsData(oldControl) && !EReaderControl0IsData(control)) {
 914			hw->eReaderState = EREADER_SERIAL_STARTING;
 915		}
 916	} else if (EReaderControl0IsClock(oldControl) && !EReaderControl0IsData(oldControl) && EReaderControl0IsData(control)) {
 917		hw->eReaderState = EREADER_SERIAL_INACTIVE;
 918
 919	} else if (hw->eReaderState == EREADER_SERIAL_STARTING) {
 920		if (EReaderControl0IsClock(oldControl) && !EReaderControl0IsData(oldControl) && !EReaderControl0IsClock(control)) {
 921			hw->eReaderState = EREADER_SERIAL_BIT_0;
 922			hw->eReaderCommand = EREADER_COMMAND_IDLE;
 923		}
 924	} else if (EReaderControl0IsClock(oldControl) && !EReaderControl0IsClock(control)) {
 925		mLOG(GBA_HW, DEBUG, "[e-Reader] Serial falling edge: %c %i", EReaderControl0IsDirection(control) ? '>' : '<', EReaderControl0GetData(control));
 926		// TODO: Improve direction control
 927		if (EReaderControl0IsDirection(control)) {
 928			hw->eReaderByte |= EReaderControl0GetData(control) << (7 - (hw->eReaderState - EREADER_SERIAL_BIT_0));
 929			++hw->eReaderState;
 930			if (hw->eReaderState == EREADER_SERIAL_END_BIT) {
 931				mLOG(GBA_HW, DEBUG, "[e-Reader] Wrote serial byte: %02x", hw->eReaderByte);
 932				switch (hw->eReaderCommand) {
 933				case EREADER_COMMAND_IDLE:
 934					hw->eReaderCommand = hw->eReaderByte;
 935					break;
 936				case EREADER_COMMAND_SET_INDEX:
 937					hw->eReaderActiveRegister = hw->eReaderByte;
 938					hw->eReaderCommand = EREADER_COMMAND_WRITE_DATA;
 939					break;
 940				case EREADER_COMMAND_WRITE_DATA:
 941					switch (hw->eReaderActiveRegister & 0x7F) {
 942					case 0:
 943					case 0x57:
 944					case 0x58:
 945					case 0x59:
 946					case 0x5A:
 947						// Read-only
 948						mLOG(GBA_HW, GAME_ERROR, "Writing to read-only e-Reader serial register: %02X", hw->eReaderActiveRegister);
 949						break;
 950					default:
 951						if ((hw->eReaderActiveRegister & 0x7F) > 0x5A) {
 952							mLOG(GBA_HW, GAME_ERROR, "Writing to non-existent e-Reader serial register: %02X", hw->eReaderActiveRegister);
 953							break;
 954						}
 955						hw->eReaderSerial[hw->eReaderActiveRegister & 0x7F] = hw->eReaderByte;
 956						break;
 957					}
 958					++hw->eReaderActiveRegister;
 959					break;
 960				default:
 961					mLOG(GBA_HW, ERROR, "Hit undefined state %02X in e-Reader state machine", hw->eReaderCommand);
 962					break;
 963				}
 964				hw->eReaderState = EREADER_SERIAL_BIT_0;
 965				hw->eReaderByte = 0;
 966			}
 967		} else if (hw->eReaderCommand == EREADER_COMMAND_READ_DATA) {
 968			int bit = hw->eReaderSerial[hw->eReaderActiveRegister & 0x7F] >> (7 - (hw->eReaderState - EREADER_SERIAL_BIT_0));
 969			control = EReaderControl0SetData(control, bit);
 970			++hw->eReaderState;
 971			if (hw->eReaderState == EREADER_SERIAL_END_BIT) {
 972				++hw->eReaderActiveRegister;
 973				mLOG(GBA_HW, DEBUG, "[e-Reader] Read serial byte: %02x", hw->eReaderSerial[hw->eReaderActiveRegister & 0x7F]);
 974			}
 975		}
 976	} else if (!EReaderControl0IsDirection(control)) {
 977		// Clear the error bit
 978		control = EReaderControl0ClearData(control);
 979	}
 980	hw->eReaderRegisterControl0 = control;
 981	if (!EReaderControl0IsScan(oldControl) && EReaderControl0IsScan(control)) {
 982		hw->eReaderX = 0;
 983		hw->eReaderY = 0;
 984	} else if (EReaderControl0IsLedEnable(control) && EReaderControl0IsScan(control) && !EReaderControl1IsScanline(hw->eReaderRegisterControl1)) {
 985		_eReaderReadData(hw);
 986	}
 987	mLOG(GBA_HW, STUB, "Unimplemented e-Reader Control0 write: %02X", value);
 988}
 989
 990void _eReaderWriteControl1(struct GBACartridgeHardware* hw, uint8_t value) {
 991	EReaderControl1 control = (value & 0x32) | 0x80;
 992	hw->eReaderRegisterControl1 = control;
 993	if (EReaderControl0IsScan(hw->eReaderRegisterControl0) && !EReaderControl1IsScanline(control)) {
 994		++hw->eReaderY;
 995		if (hw->eReaderY == (hw->eReaderSerial[0x15] | (hw->eReaderSerial[0x14] << 8))) {
 996			hw->eReaderY = 0;
 997			if (hw->eReaderX < 3400) {
 998				hw->eReaderX += 220;
 999			}
1000		}
1001		_eReaderReadData(hw);
1002	}
1003	mLOG(GBA_HW, STUB, "Unimplemented e-Reader Control1 write: %02X", value);
1004}
1005
1006void _eReaderReadData(struct GBACartridgeHardware* hw) {
1007	memset(hw->eReaderData, 0, EREADER_BLOCK_SIZE);
1008	if (hw->eReaderDots) {
1009		int y = hw->eReaderY - 10;
1010		if (y < 0 || y >= 120) {
1011			memset(hw->eReaderData, 0, EREADER_BLOCK_SIZE);
1012		} else {
1013			int i;
1014			uint8_t* origin = &hw->eReaderDots[EREADER_DOTCODE_STRIDE * (y / 3) + 16];
1015			for (i = 0; i < 20; ++i) {
1016				uint16_t word = 0;
1017				int x = hw->eReaderX + i * 16;
1018				word |= origin[(x +  0) / 3] << 8;
1019				word |= origin[(x +  1) / 3] << 9;
1020				word |= origin[(x +  2) / 3] << 10;
1021				word |= origin[(x +  3) / 3] << 11;
1022				word |= origin[(x +  4) / 3] << 12;
1023				word |= origin[(x +  5) / 3] << 13;
1024				word |= origin[(x +  6) / 3] << 14;
1025				word |= origin[(x +  7) / 3] << 15;
1026				word |= origin[(x +  8) / 3];
1027				word |= origin[(x +  9) / 3] << 1;
1028				word |= origin[(x + 10) / 3] << 2;
1029				word |= origin[(x + 11) / 3] << 3;
1030				word |= origin[(x + 12) / 3] << 4;
1031				word |= origin[(x + 13) / 3] << 5;
1032				word |= origin[(x + 14) / 3] << 6;
1033				word |= origin[(x + 15) / 3] << 7;
1034				STORE_16(word, (19 - i) << 1, hw->eReaderData);
1035			}
1036		}
1037	}
1038	hw->eReaderRegisterControl1 = EReaderControl1FillScanline(hw->eReaderRegisterControl1);
1039	if (EReaderControl0IsLedEnable(hw->eReaderRegisterControl0)) {
1040		uint16_t led = 2754; // TODO: Figure out why this breaks if using the LED register
1041		GBARaiseIRQ(hw->p, IRQ_GAMEPAK, -led);
1042	}
1043}
1044
1045// == Serialization
1046
1047void GBAHardwareSerialize(const struct GBACartridgeHardware* hw, struct GBASerializedState* state) {
1048	GBASerializedHWFlags1 flags1 = 0;
1049	GBASerializedHWFlags2 flags2 = 0;
1050	flags1 = GBASerializedHWFlags1SetReadWrite(flags1, hw->readWrite);
1051	STORE_16(hw->pinState, 0, &state->hw.pinState);
1052	STORE_16(hw->direction, 0, &state->hw.pinDirection);
1053	state->hw.devices = hw->devices;
1054
1055	STORE_32(hw->rtc.bytesRemaining, 0, &state->hw.rtc.bytesRemaining);
1056	STORE_32(hw->rtc.transferStep, 0, &state->hw.rtc.transferStep);
1057	STORE_32(hw->rtc.bitsRead, 0, &state->hw.rtc.bitsRead);
1058	STORE_32(hw->rtc.bits, 0, &state->hw.rtc.bits);
1059	STORE_32(hw->rtc.commandActive, 0, &state->hw.rtc.commandActive);
1060	STORE_32(hw->rtc.command, 0, &state->hw.rtc.command);
1061	STORE_32(hw->rtc.control, 0, &state->hw.rtc.control);
1062	memcpy(state->hw.rtc.time, hw->rtc.time, sizeof(state->hw.rtc.time));
1063
1064	STORE_16(hw->gyroSample, 0, &state->hw.gyroSample);
1065	flags1 = GBASerializedHWFlags1SetGyroEdge(flags1, hw->gyroEdge);
1066	STORE_16(hw->tiltX, 0, &state->hw.tiltSampleX);
1067	STORE_16(hw->tiltY, 0, &state->hw.tiltSampleY);
1068	flags2 = GBASerializedHWFlags2SetTiltState(flags2, hw->tiltState);
1069	flags2 = GBASerializedHWFlags1SetLightCounter(flags2, hw->lightCounter);
1070	state->hw.lightSample = hw->lightSample;
1071	flags1 = GBASerializedHWFlags1SetLightEdge(flags1, hw->lightEdge);
1072	flags2 = GBASerializedHWFlags2SetGbpInputsPosted(flags2, hw->gbpInputsPosted);
1073	flags2 = GBASerializedHWFlags2SetGbpTxPosition(flags2, hw->gbpTxPosition);
1074	STORE_32(hw->gbpNextEvent.when - mTimingCurrentTime(&hw->p->timing), 0, &state->hw.gbpNextEvent);
1075	STORE_16(flags1, 0, &state->hw.flags1);
1076	state->hw.flags2 = flags2;
1077}
1078
1079void GBAHardwareDeserialize(struct GBACartridgeHardware* hw, const struct GBASerializedState* state) {
1080	GBASerializedHWFlags1 flags1;
1081	LOAD_16(flags1, 0, &state->hw.flags1);
1082	hw->readWrite = GBASerializedHWFlags1GetReadWrite(flags1);
1083	LOAD_16(hw->pinState, 0, &state->hw.pinState);
1084	LOAD_16(hw->direction, 0, &state->hw.pinDirection);
1085	hw->devices = state->hw.devices;
1086
1087	LOAD_32(hw->rtc.bytesRemaining, 0, &state->hw.rtc.bytesRemaining);
1088	LOAD_32(hw->rtc.transferStep, 0, &state->hw.rtc.transferStep);
1089	LOAD_32(hw->rtc.bitsRead, 0, &state->hw.rtc.bitsRead);
1090	LOAD_32(hw->rtc.bits, 0, &state->hw.rtc.bits);
1091	LOAD_32(hw->rtc.commandActive, 0, &state->hw.rtc.commandActive);
1092	LOAD_32(hw->rtc.command, 0, &state->hw.rtc.command);
1093	LOAD_32(hw->rtc.control, 0, &state->hw.rtc.control);
1094	memcpy(hw->rtc.time, state->hw.rtc.time, sizeof(hw->rtc.time));
1095
1096	LOAD_16(hw->gyroSample, 0, &state->hw.gyroSample);
1097	hw->gyroEdge = GBASerializedHWFlags1GetGyroEdge(flags1);
1098	LOAD_16(hw->tiltX, 0, &state->hw.tiltSampleX);
1099	LOAD_16(hw->tiltY, 0, &state->hw.tiltSampleY);
1100	hw->tiltState = GBASerializedHWFlags2GetTiltState(state->hw.flags2);
1101	hw->lightCounter = GBASerializedHWFlags1GetLightCounter(flags1);
1102	hw->lightSample = state->hw.lightSample;
1103	hw->lightEdge = GBASerializedHWFlags1GetLightEdge(flags1);
1104	hw->gbpInputsPosted = GBASerializedHWFlags2GetGbpInputsPosted(state->hw.flags2);
1105	hw->gbpTxPosition = GBASerializedHWFlags2GetGbpTxPosition(state->hw.flags2);
1106
1107	uint32_t when;
1108	LOAD_32(when, 0, &state->hw.gbpNextEvent);
1109	if (hw->devices & HW_GB_PLAYER) {
1110		GBASIOSetDriver(&hw->p->sio, &hw->gbpDriver.d, SIO_NORMAL_32);
1111		if (hw->p->memory.io[REG_SIOCNT >> 1] & 0x0080) {
1112			mTimingSchedule(&hw->p->timing, &hw->gbpNextEvent, when);
1113		}
1114	}
1115}