all repos — mgba @ 39e4a8a156fb5fd35a89f81cc7b63caea2a8edb3

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	}
 172
 173	if (hw->p->sio.drivers.normal == &hw->gbpDriver.d) {
 174		GBASIOSetDriver(&hw->p->sio, 0, SIO_NORMAL_32);
 175	}
 176}
 177
 178void GBAHardwareGPIOWrite(struct GBACartridgeHardware* hw, uint32_t address, uint16_t value) {
 179	if (!hw->gpioBase) {
 180		return;
 181	}
 182	switch (address) {
 183	case GPIO_REG_DATA:
 184		hw->pinState &= ~hw->direction;
 185		hw->pinState |= value & hw->direction;
 186		_readPins(hw);
 187		break;
 188	case GPIO_REG_DIRECTION:
 189		hw->direction = value;
 190		break;
 191	case GPIO_REG_CONTROL:
 192		hw->readWrite = value;
 193		break;
 194	default:
 195		mLOG(GBA_HW, WARN, "Invalid GPIO address");
 196	}
 197	if (hw->readWrite) {
 198		STORE_16(hw->pinState, 0, hw->gpioBase);
 199		STORE_16(hw->direction, 2, hw->gpioBase);
 200		STORE_16(hw->readWrite, 4, hw->gpioBase);
 201	} else {
 202		hw->gpioBase[0] = 0;
 203		hw->gpioBase[1] = 0;
 204		hw->gpioBase[2] = 0;
 205	}
 206}
 207
 208void GBAHardwareInitRTC(struct GBACartridgeHardware* hw) {
 209	hw->devices |= HW_RTC;
 210	hw->rtc.bytesRemaining = 0;
 211
 212	hw->rtc.transferStep = 0;
 213
 214	hw->rtc.bitsRead = 0;
 215	hw->rtc.bits = 0;
 216	hw->rtc.commandActive = 0;
 217	hw->rtc.command = 0;
 218	hw->rtc.control = 0x40;
 219	memset(hw->rtc.time, 0, sizeof(hw->rtc.time));
 220}
 221
 222void _readPins(struct GBACartridgeHardware* hw) {
 223	if (hw->devices & HW_RTC) {
 224		_rtcReadPins(hw);
 225	}
 226
 227	if (hw->devices & HW_GYRO) {
 228		_gyroReadPins(hw);
 229	}
 230
 231	if (hw->devices & HW_RUMBLE) {
 232		_rumbleReadPins(hw);
 233	}
 234
 235	if (hw->devices & HW_LIGHT_SENSOR) {
 236		_lightReadPins(hw);
 237	}
 238}
 239
 240void _outputPins(struct GBACartridgeHardware* hw, unsigned pins) {
 241	if (hw->readWrite) {
 242		uint16_t old;
 243		LOAD_16(old, 0, hw->gpioBase);
 244		old &= hw->direction;
 245		hw->pinState = old | (pins & ~hw->direction & 0xF);
 246		STORE_16(hw->pinState, 0, hw->gpioBase);
 247	}
 248}
 249
 250// == RTC
 251
 252void _rtcReadPins(struct GBACartridgeHardware* hw) {
 253	// Transfer sequence:
 254	// P: 0 | 1 |  2 | 3
 255	// == Initiate
 256	// > HI | - | LO | -
 257	// > HI | - | HI | -
 258	// == Transfer bit (x8)
 259	// > LO | x | HI | -
 260	// > HI | - | HI | -
 261	// < ?? | x | ?? | -
 262	// == Terminate
 263	// >  - | - | LO | -
 264	switch (hw->rtc.transferStep) {
 265	case 0:
 266		if ((hw->pinState & 5) == 1) {
 267			hw->rtc.transferStep = 1;
 268		}
 269		break;
 270	case 1:
 271		if ((hw->pinState & 5) == 5) {
 272			hw->rtc.transferStep = 2;
 273		} else if ((hw->pinState & 5) != 1) {
 274			hw->rtc.transferStep = 0;
 275		}
 276		break;
 277	case 2:
 278		if (!(hw->pinState & 1)) {
 279			hw->rtc.bits &= ~(1 << hw->rtc.bitsRead);
 280			hw->rtc.bits |= ((hw->pinState & 2) >> 1) << hw->rtc.bitsRead;
 281		} else {
 282			if (hw->pinState & 4) {
 283				if (!RTCCommandDataIsReading(hw->rtc.command)) {
 284					++hw->rtc.bitsRead;
 285					if (hw->rtc.bitsRead == 8) {
 286						_rtcProcessByte(hw);
 287					}
 288				} else {
 289					_outputPins(hw, 5 | (_rtcOutput(hw) << 1));
 290					++hw->rtc.bitsRead;
 291					if (hw->rtc.bitsRead == 8) {
 292						--hw->rtc.bytesRemaining;
 293						if (hw->rtc.bytesRemaining <= 0) {
 294							hw->rtc.commandActive = 0;
 295							hw->rtc.command = 0;
 296						}
 297						hw->rtc.bitsRead = 0;
 298					}
 299				}
 300			} else {
 301				hw->rtc.bitsRead = 0;
 302				hw->rtc.bytesRemaining = 0;
 303				hw->rtc.commandActive = 0;
 304				hw->rtc.command = 0;
 305				hw->rtc.transferStep = hw->pinState & 1;
 306				_outputPins(hw, 1);
 307			}
 308		}
 309		break;
 310	}
 311}
 312
 313void _rtcProcessByte(struct GBACartridgeHardware* hw) {
 314	--hw->rtc.bytesRemaining;
 315	if (!hw->rtc.commandActive) {
 316		RTCCommandData command;
 317		command = hw->rtc.bits;
 318		if (RTCCommandDataGetMagic(command) == 0x06) {
 319			hw->rtc.command = command;
 320
 321			hw->rtc.bytesRemaining = RTC_BYTES[RTCCommandDataGetCommand(command)];
 322			hw->rtc.commandActive = hw->rtc.bytesRemaining > 0;
 323			switch (RTCCommandDataGetCommand(command)) {
 324			case RTC_RESET:
 325				hw->rtc.control = 0;
 326				break;
 327			case RTC_DATETIME:
 328			case RTC_TIME:
 329				_rtcUpdateClock(hw);
 330				break;
 331			case RTC_FORCE_IRQ:
 332			case RTC_CONTROL:
 333				break;
 334			}
 335		} else {
 336			mLOG(GBA_HW, WARN, "Invalid RTC command byte: %02X", hw->rtc.bits);
 337		}
 338	} else {
 339		switch (RTCCommandDataGetCommand(hw->rtc.command)) {
 340		case RTC_CONTROL:
 341			hw->rtc.control = hw->rtc.bits;
 342			break;
 343		case RTC_FORCE_IRQ:
 344			mLOG(GBA_HW, STUB, "Unimplemented RTC command %u", RTCCommandDataGetCommand(hw->rtc.command));
 345			break;
 346		case RTC_RESET:
 347		case RTC_DATETIME:
 348		case RTC_TIME:
 349			break;
 350		}
 351	}
 352
 353	hw->rtc.bits = 0;
 354	hw->rtc.bitsRead = 0;
 355	if (!hw->rtc.bytesRemaining) {
 356		hw->rtc.commandActive = 0;
 357		hw->rtc.command = 0;
 358	}
 359}
 360
 361unsigned _rtcOutput(struct GBACartridgeHardware* hw) {
 362	uint8_t outputByte = 0;
 363	if (!hw->rtc.commandActive) {
 364		mLOG(GBA_HW, GAME_ERROR, "Attempting to use RTC without an active command");
 365		return 0;
 366	}
 367	switch (RTCCommandDataGetCommand(hw->rtc.command)) {
 368	case RTC_CONTROL:
 369		outputByte = hw->rtc.control;
 370		break;
 371	case RTC_DATETIME:
 372	case RTC_TIME:
 373		outputByte = hw->rtc.time[7 - hw->rtc.bytesRemaining];
 374		break;
 375	case RTC_FORCE_IRQ:
 376	case RTC_RESET:
 377		break;
 378	}
 379	unsigned output = (outputByte >> hw->rtc.bitsRead) & 1;
 380	return output;
 381}
 382
 383void _rtcUpdateClock(struct GBACartridgeHardware* hw) {
 384	time_t t;
 385	struct mRTCSource* rtc = hw->p->rtcSource;
 386	if (rtc) {
 387		if (rtc->sample) {
 388			rtc->sample(rtc);
 389		}
 390		t = rtc->unixTime(rtc);
 391	} else {
 392		t = time(0);
 393	}
 394	struct tm date;
 395	localtime_r(&t, &date);
 396	hw->rtc.time[0] = _rtcBCD(date.tm_year - 100);
 397	hw->rtc.time[1] = _rtcBCD(date.tm_mon + 1);
 398	hw->rtc.time[2] = _rtcBCD(date.tm_mday);
 399	hw->rtc.time[3] = _rtcBCD(date.tm_wday);
 400	if (RTCControlIsHour24(hw->rtc.control)) {
 401		hw->rtc.time[4] = _rtcBCD(date.tm_hour);
 402	} else {
 403		hw->rtc.time[4] = _rtcBCD(date.tm_hour % 12);
 404	}
 405	hw->rtc.time[5] = _rtcBCD(date.tm_min);
 406	hw->rtc.time[6] = _rtcBCD(date.tm_sec);
 407}
 408
 409unsigned _rtcBCD(unsigned value) {
 410	int counter = value % 10;
 411	value /= 10;
 412	counter += (value % 10) << 4;
 413	return counter;
 414}
 415
 416time_t _rtcGenericCallback(struct mRTCSource* source) {
 417	struct GBARTCGenericSource* rtc = (struct GBARTCGenericSource*) source;
 418	switch (rtc->override) {
 419	case RTC_NO_OVERRIDE:
 420	default:
 421		return time(0);
 422	case RTC_FIXED:
 423		return rtc->value;
 424	case RTC_FAKE_EPOCH:
 425		return rtc->value + rtc->p->video.frameCounter * (int64_t) VIDEO_TOTAL_LENGTH / GBA_ARM7TDMI_FREQUENCY;
 426	}
 427}
 428
 429void GBARTCGenericSourceInit(struct GBARTCGenericSource* rtc, struct GBA* gba) {
 430	rtc->p = gba;
 431	rtc->override = RTC_NO_OVERRIDE;
 432	rtc->value = 0;
 433	rtc->d.sample = 0;
 434	rtc->d.unixTime = _rtcGenericCallback;
 435}
 436
 437// == Gyro
 438
 439void GBAHardwareInitGyro(struct GBACartridgeHardware* hw) {
 440	hw->devices |= HW_GYRO;
 441	hw->gyroSample = 0;
 442	hw->gyroEdge = 0;
 443}
 444
 445void _gyroReadPins(struct GBACartridgeHardware* hw) {
 446	struct mRotationSource* gyro = hw->p->rotationSource;
 447	if (!gyro || !gyro->readGyroZ) {
 448		return;
 449	}
 450
 451	if (hw->pinState & 1) {
 452		if (gyro->sample) {
 453			gyro->sample(gyro);
 454		}
 455		int32_t sample = gyro->readGyroZ(gyro);
 456
 457		// Normalize to ~12 bits, focused on 0x6C0
 458		hw->gyroSample = (sample >> 21) + 0x6C0; // Crop off an extra bit so that we can't go negative
 459	}
 460
 461	if (hw->gyroEdge && !(hw->pinState & 2)) {
 462		// Write bit on falling edge
 463		unsigned bit = hw->gyroSample >> 15;
 464		hw->gyroSample <<= 1;
 465		_outputPins(hw, bit << 2);
 466	}
 467
 468	hw->gyroEdge = !!(hw->pinState & 2);
 469}
 470
 471// == Rumble
 472
 473void GBAHardwareInitRumble(struct GBACartridgeHardware* hw) {
 474	hw->devices |= HW_RUMBLE;
 475}
 476
 477void _rumbleReadPins(struct GBACartridgeHardware* hw) {
 478	struct mRumble* rumble = hw->p->rumble;
 479	if (!rumble) {
 480		return;
 481	}
 482
 483	rumble->setRumble(rumble, !!(hw->pinState & 8));
 484}
 485
 486// == Light sensor
 487
 488void GBAHardwareInitLight(struct GBACartridgeHardware* hw) {
 489	hw->devices |= HW_LIGHT_SENSOR;
 490	hw->lightCounter = 0;
 491	hw->lightEdge = false;
 492	hw->lightSample = 0xFF;
 493}
 494
 495void _lightReadPins(struct GBACartridgeHardware* hw) {
 496	if (hw->pinState & 4) {
 497		// Boktai chip select
 498		return;
 499	}
 500	if (hw->pinState & 2) {
 501		struct GBALuminanceSource* lux = hw->p->luminanceSource;
 502		mLOG(GBA_HW, DEBUG, "[SOLAR] Got reset");
 503		hw->lightCounter = 0;
 504		if (lux) {
 505			lux->sample(lux);
 506			hw->lightSample = lux->readLuminance(lux);
 507		} else {
 508			hw->lightSample = 0xFF;
 509		}
 510	}
 511	if ((hw->pinState & 1) && hw->lightEdge) {
 512		++hw->lightCounter;
 513	}
 514	hw->lightEdge = !(hw->pinState & 1);
 515
 516	bool sendBit = hw->lightCounter >= hw->lightSample;
 517	_outputPins(hw, sendBit << 3);
 518	mLOG(GBA_HW, DEBUG, "[SOLAR] Output %u with pins %u", hw->lightCounter, hw->pinState);
 519}
 520
 521// == Tilt
 522
 523void GBAHardwareInitTilt(struct GBACartridgeHardware* hw) {
 524	hw->devices |= HW_TILT;
 525	hw->tiltX = 0xFFF;
 526	hw->tiltY = 0xFFF;
 527	hw->tiltState = 0;
 528}
 529
 530void GBAHardwareTiltWrite(struct GBACartridgeHardware* hw, uint32_t address, uint8_t value) {
 531	switch (address) {
 532	case 0x8000:
 533		if (value == 0x55) {
 534			hw->tiltState = 1;
 535		} else {
 536			mLOG(GBA_HW, GAME_ERROR, "Tilt sensor wrote wrong byte to %04x: %02x", address, value);
 537		}
 538		break;
 539	case 0x8100:
 540		if (value == 0xAA && hw->tiltState == 1) {
 541			hw->tiltState = 0;
 542			struct mRotationSource* rotationSource = hw->p->rotationSource;
 543			if (!rotationSource || !rotationSource->readTiltX || !rotationSource->readTiltY) {
 544				return;
 545			}
 546			if (rotationSource->sample) {
 547				rotationSource->sample(rotationSource);
 548			}
 549			int32_t x = rotationSource->readTiltX(rotationSource);
 550			int32_t y = rotationSource->readTiltY(rotationSource);
 551			// Normalize to ~12 bits, focused on 0x3A0
 552			hw->tiltX = (x >> 21) + 0x3A0; // Crop off an extra bit so that we can't go negative
 553			hw->tiltY = (y >> 21) + 0x3A0;
 554		} else {
 555			mLOG(GBA_HW, GAME_ERROR, "Tilt sensor wrote wrong byte to %04x: %02x", address, value);
 556		}
 557		break;
 558	default:
 559		mLOG(GBA_HW, GAME_ERROR, "Invalid tilt sensor write to %04x: %02x", address, value);
 560		break;
 561	}
 562}
 563
 564uint8_t GBAHardwareTiltRead(struct GBACartridgeHardware* hw, uint32_t address) {
 565	switch (address) {
 566	case 0x8200:
 567		return hw->tiltX & 0xFF;
 568	case 0x8300:
 569		return ((hw->tiltX >> 8) & 0xF) | 0x80;
 570	case 0x8400:
 571		return hw->tiltY & 0xFF;
 572	case 0x8500:
 573		return (hw->tiltY >> 8) & 0xF;
 574	default:
 575		mLOG(GBA_HW, GAME_ERROR, "Invalid tilt sensor read from %04x", address);
 576		break;
 577	}
 578	return 0xFF;
 579}
 580
 581// == Game Boy Player
 582
 583static const uint16_t _logoPalette[] = {
 584	0xFFDF, 0x640C, 0xE40C, 0xE42D, 0x644E, 0xE44E, 0xE46E, 0x68AF,
 585	0xE8B0, 0x68D0, 0x68F0, 0x6911, 0xE911, 0x6D32, 0xED32, 0xED73,
 586	0x6D93, 0xED94, 0x6DB4, 0xF1D5, 0x71F5, 0xF1F6, 0x7216, 0x7257,
 587	0xF657, 0x7678, 0xF678, 0xF699, 0xF6B9, 0x76D9, 0xF6DA, 0x7B1B,
 588	0xFB1B, 0xFB3C, 0x7B5C, 0x7B7D, 0xFF7D, 0x7F9D, 0x7FBE, 0x7FFF,
 589	0x642D, 0x648E, 0xE88F, 0xE8F1, 0x6D52, 0x6D73, 0xF1B4, 0xF216,
 590	0x7237, 0x7698, 0x7AFA, 0xFAFA, 0xFB5C, 0xFFBE, 0x7FDE, 0xFFFF,
 591	0xFFFF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
 592};
 593
 594static const uint32_t _logoHash = 0xEEDA6963;
 595
 596static const uint32_t _gbpTxData[] = {
 597	0x0000494E, 0x0000494E,
 598	0xB6B1494E, 0xB6B1544E,
 599	0xABB1544E, 0xABB14E45,
 600	0xB1BA4E45, 0xB1BA4F44,
 601	0xB0BB4F44, 0xB0BB8002,
 602	0x10000010, 0x20000013,
 603	0x30000003
 604};
 605
 606bool GBAHardwarePlayerCheckScreen(const struct GBAVideo* video) {
 607	if (memcmp(video->palette, _logoPalette, sizeof(_logoPalette)) != 0) {
 608		return false;
 609	}
 610	uint32_t hash = hash32(&video->renderer->vram[0x4000], 0x4000, 0);
 611	return hash == _logoHash;
 612}
 613
 614void GBAHardwarePlayerUpdate(struct GBA* gba) {
 615	if (gba->memory.hw.devices & HW_GB_PLAYER) {
 616		if (GBAHardwarePlayerCheckScreen(&gba->video)) {
 617			++gba->memory.hw.gbpInputsPosted;
 618			gba->memory.hw.gbpInputsPosted %= 3;
 619			gba->keyCallback = &gba->memory.hw.gbpCallback.d;
 620		} else {
 621			// TODO: Save and restore
 622			gba->keyCallback = 0;
 623		}
 624		gba->memory.hw.gbpTxPosition = 0;
 625		return;
 626	}
 627	if (gba->keyCallback || gba->sio.drivers.normal) {
 628		return;
 629	}
 630	if (GBAHardwarePlayerCheckScreen(&gba->video)) {
 631		gba->memory.hw.devices |= HW_GB_PLAYER;
 632		gba->memory.hw.gbpInputsPosted = 0;
 633		gba->keyCallback = &gba->memory.hw.gbpCallback.d;
 634		GBASIOSetDriver(&gba->sio, &gba->memory.hw.gbpDriver.d, SIO_NORMAL_32);
 635	}
 636}
 637
 638uint16_t _gbpRead(struct mKeyCallback* callback) {
 639	struct GBAGBPKeyCallback* gbpCallback = (struct GBAGBPKeyCallback*) callback;
 640	if (gbpCallback->p->gbpInputsPosted == 2) {
 641		return 0xF0;
 642	}
 643	return 0;
 644}
 645
 646uint16_t _gbpSioWriteRegister(struct GBASIODriver* driver, uint32_t address, uint16_t value) {
 647	struct GBAGBPSIODriver* gbp = (struct GBAGBPSIODriver*) driver;
 648	if (address == REG_SIOCNT) {
 649		if (value & 0x0080) {
 650			uint32_t rx = gbp->p->p->memory.io[REG_SIODATA32_LO >> 1] | (gbp->p->p->memory.io[REG_SIODATA32_HI >> 1] << 16);
 651			if (gbp->p->gbpTxPosition < 12 && gbp->p->gbpTxPosition > 0) {
 652				// TODO: Check expected
 653			} else if (gbp->p->gbpTxPosition >= 12) {
 654				uint32_t mask = 0x33;
 655				// 0x00 = Stop
 656				// 0x11 = Hard Stop
 657				// 0x22 = Start
 658				if (gbp->p->p->rumble) {
 659					gbp->p->p->rumble->setRumble(gbp->p->p->rumble, (rx & mask) == 0x22);
 660				}
 661			}
 662			mTimingDeschedule(&gbp->p->p->timing, &gbp->p->gbpNextEvent);
 663			mTimingSchedule(&gbp->p->p->timing, &gbp->p->gbpNextEvent, 2048);
 664		}
 665		value &= 0x78FB;
 666	}
 667	return value;
 668}
 669
 670void _gbpSioProcessEvents(struct mTiming* timing, void* user, uint32_t cyclesLate) {
 671	UNUSED(timing);
 672	UNUSED(cyclesLate);
 673	struct GBAGBPSIODriver* gbp = user;
 674	uint32_t tx = 0;
 675	int txPosition = gbp->p->gbpTxPosition;
 676	if (txPosition > 16) {
 677		gbp->p->gbpTxPosition = 0;
 678		txPosition = 0;
 679	} else if (txPosition > 12) {
 680		txPosition = 12;
 681	}
 682	tx = _gbpTxData[txPosition];
 683	++gbp->p->gbpTxPosition;
 684	gbp->p->p->memory.io[REG_SIODATA32_LO >> 1] = tx;
 685	gbp->p->p->memory.io[REG_SIODATA32_HI >> 1] = tx >> 16;
 686	if (GBASIONormalIsIrq(gbp->d.p->siocnt)) {
 687		GBARaiseIRQ(gbp->p->p, IRQ_SIO, cyclesLate);
 688	}
 689	gbp->d.p->siocnt = GBASIONormalClearStart(gbp->d.p->siocnt);
 690	gbp->p->p->memory.io[REG_SIOCNT >> 1] = gbp->d.p->siocnt & ~0x0080;
 691}
 692
 693// == e-Reader
 694
 695void GBAHardwareInitEReader(struct GBACartridgeHardware* hw) {
 696	hw->devices |= HW_EREADER;
 697	_eReaderReset(hw);
 698
 699	if (hw->p->memory.savedata.data[0xD000] == 0xFF) {
 700		memset(&hw->p->memory.savedata.data[0xD000], 0, 0x1000);
 701		memcpy(&hw->p->memory.savedata.data[0xD000], EREADER_CALIBRATION_TEMPLATE, sizeof(EREADER_CALIBRATION_TEMPLATE));
 702	}
 703	if (hw->p->memory.savedata.data[0xE000] == 0xFF) {
 704		memset(&hw->p->memory.savedata.data[0xE000], 0, 0x1000);
 705		memcpy(&hw->p->memory.savedata.data[0xE000], EREADER_CALIBRATION_TEMPLATE, sizeof(EREADER_CALIBRATION_TEMPLATE));
 706	}
 707}
 708
 709void GBAHardwareEReaderWrite(struct GBACartridgeHardware* hw, uint32_t address, uint16_t value) {
 710	address &= 0x700FF;
 711	switch (address >> 17) {
 712	case 0:
 713		hw->eReaderRegisterUnk = value & 0xF;
 714		break;
 715	case 1:
 716		hw->eReaderRegisterReset = (value & 0x8A) | 4;
 717		if (value & 2) {
 718			_eReaderReset(hw);
 719		}
 720		break;
 721	case 2:
 722		mLOG(GBA_HW, GAME_ERROR, "e-Reader write to read-only registers: %05X:%04X", address, value);
 723		break;
 724	default:
 725		mLOG(GBA_HW, STUB, "Unimplemented e-Reader write: %05X:%04X", address, value);
 726	}
 727}
 728
 729void GBAHardwareEReaderWriteFlash(struct GBACartridgeHardware* hw, uint32_t address, uint8_t value) {
 730	address &= 0xFFFF;
 731	switch (address) {
 732	case 0xFFB0:
 733		_eReaderWriteControl0(hw, value);
 734		break;
 735	case 0xFFB1:
 736		_eReaderWriteControl1(hw, value);
 737		break;
 738	case 0xFFB2:
 739		hw->eReaderRegisterLed &= 0xFF00;
 740		hw->eReaderRegisterLed |= value;
 741		break;
 742	case 0xFFB3:
 743		hw->eReaderRegisterLed &= 0x00FF;
 744		hw->eReaderRegisterLed |= value << 8;
 745		break;
 746	default:
 747		mLOG(GBA_HW, STUB, "Unimplemented e-Reader write to flash: %04X:%02X", address, value);
 748	}
 749}
 750
 751uint16_t GBAHardwareEReaderRead(struct GBACartridgeHardware* hw, uint32_t address) {
 752	address &= 0x700FF;
 753	uint16_t value;
 754	switch (address >> 17) {
 755	case 0:
 756		return hw->eReaderRegisterUnk;
 757	case 1:
 758		return hw->eReaderRegisterReset;
 759	case 2:
 760		if (address > 0x40088) {
 761			return 0;
 762		}
 763		LOAD_16(value, address & 0xFE, hw->eReaderData);
 764		return value;
 765	}
 766	mLOG(GBA_HW, STUB, "Unimplemented e-Reader read: %05X", address);
 767	return 0;
 768}
 769
 770uint8_t GBAHardwareEReaderReadFlash(struct GBACartridgeHardware* hw, uint32_t address) {
 771	address &= 0xFFFF;
 772	switch (address) {
 773	case 0xFFB0:
 774		return hw->eReaderRegisterControl0;
 775	case 0xFFB1:
 776		return hw->eReaderRegisterControl1;
 777	default:
 778		mLOG(GBA_HW, STUB, "Unimplemented e-Reader read from flash: %04X", address);
 779		return 0;
 780	}
 781}
 782
 783static void _eReaderAnchor(uint8_t* origin) {
 784	origin[EREADER_DOTCODE_STRIDE * 0 + 1] = 1;
 785	origin[EREADER_DOTCODE_STRIDE * 0 + 2] = 1;
 786	origin[EREADER_DOTCODE_STRIDE * 0 + 3] = 1;
 787	origin[EREADER_DOTCODE_STRIDE * 1 + 0] = 1;
 788	origin[EREADER_DOTCODE_STRIDE * 1 + 1] = 1;
 789	origin[EREADER_DOTCODE_STRIDE * 1 + 2] = 1;
 790	origin[EREADER_DOTCODE_STRIDE * 1 + 3] = 1;
 791	origin[EREADER_DOTCODE_STRIDE * 1 + 4] = 1;
 792	origin[EREADER_DOTCODE_STRIDE * 2 + 0] = 1;
 793	origin[EREADER_DOTCODE_STRIDE * 2 + 1] = 1;
 794	origin[EREADER_DOTCODE_STRIDE * 2 + 2] = 1;
 795	origin[EREADER_DOTCODE_STRIDE * 2 + 3] = 1;
 796	origin[EREADER_DOTCODE_STRIDE * 2 + 4] = 1;
 797	origin[EREADER_DOTCODE_STRIDE * 3 + 0] = 1;
 798	origin[EREADER_DOTCODE_STRIDE * 3 + 1] = 1;
 799	origin[EREADER_DOTCODE_STRIDE * 3 + 2] = 1;
 800	origin[EREADER_DOTCODE_STRIDE * 3 + 3] = 1;
 801	origin[EREADER_DOTCODE_STRIDE * 3 + 4] = 1;
 802	origin[EREADER_DOTCODE_STRIDE * 4 + 1] = 1;
 803	origin[EREADER_DOTCODE_STRIDE * 4 + 2] = 1;
 804	origin[EREADER_DOTCODE_STRIDE * 4 + 3] = 1;
 805}
 806
 807static void _eReaderAlignment(uint8_t* origin) {
 808	origin[8] = 1;
 809	origin[10] = 1;
 810	origin[12] = 1;
 811	origin[14] = 1;
 812	origin[16] = 1;
 813	origin[18] = 1;
 814	origin[21] = 1;
 815	origin[23] = 1;
 816	origin[25] = 1;
 817	origin[27] = 1;
 818	origin[29] = 1;
 819	origin[31] = 1;
 820}
 821
 822static void _eReaderAddress(uint8_t* origin, int a) {
 823	origin[EREADER_DOTCODE_STRIDE * 7 + 2] = 1;
 824	uint16_t addr = EREADER_ADDRESS_CODES[a];
 825	int i;
 826	for (i = 0; i < 16; ++i) {
 827		origin[EREADER_DOTCODE_STRIDE * (16 + i) + 2] = (addr >> (15 - i)) & 1;
 828	}
 829}
 830
 831void GBAHardwareEReaderScan(struct GBACartridgeHardware* hw, const void* data, size_t size) {
 832	if (!hw->eReaderDots) {
 833		hw->eReaderDots = anonymousMemoryMap(EREADER_DOTCODE_SIZE);
 834	}
 835	memset(hw->eReaderDots, 0, EREADER_DOTCODE_SIZE);
 836
 837	int base;
 838	switch (size) {
 839	case 2912:
 840		base = 25;
 841		break;
 842	case 1872:
 843		base = 1;
 844		break;
 845	default:
 846		return;
 847	}
 848
 849	size_t i;
 850	for (i = 0; i < (size / 104) + 1; ++i) {
 851		uint8_t* origin = &hw->eReaderDots[35 * i + 200];
 852		_eReaderAnchor(&origin[EREADER_DOTCODE_STRIDE * 0]);
 853		_eReaderAnchor(&origin[EREADER_DOTCODE_STRIDE * 35]);
 854		_eReaderAddress(origin, base + i);
 855	}
 856	for (i = 0; i < size / 104; ++i) {
 857		uint8_t block[1040];
 858		uint8_t* origin = &hw->eReaderDots[35 * i + 200];
 859		_eReaderAlignment(&origin[EREADER_DOTCODE_STRIDE * 2]);
 860		_eReaderAlignment(&origin[EREADER_DOTCODE_STRIDE * 37]);
 861
 862		int b;
 863		for (b = 0; b < 104; ++b) {
 864			const int* nybble5;
 865			nybble5 = EREADER_NYBBLE_5BIT[((const uint8_t*) data)[i * 104 + b] >> 4];
 866			block[b * 10 + 0] = nybble5[0];
 867			block[b * 10 + 1] = nybble5[1];
 868			block[b * 10 + 2] = nybble5[2];
 869			block[b * 10 + 3] = nybble5[3];
 870			block[b * 10 + 4] = nybble5[4];
 871			nybble5 = EREADER_NYBBLE_5BIT[((const uint8_t*) data)[i * 104 + b] & 0xF];
 872			block[b * 10 + 5] = nybble5[0];
 873			block[b * 10 + 6] = nybble5[1];
 874			block[b * 10 + 7] = nybble5[2];
 875			block[b * 10 + 8] = nybble5[3];
 876			block[b * 10 + 9] = nybble5[4];
 877		}
 878
 879		b = 0;
 880		int y;
 881		for (y = 0; y < 3; ++y) {
 882			memcpy(&origin[EREADER_DOTCODE_STRIDE * (4 + y) + 7], &block[b], 26);
 883			b += 26;
 884		}
 885		for (y = 0; y < 26; ++y) {
 886			memcpy(&origin[EREADER_DOTCODE_STRIDE * (7 + y) + 3], &block[b], 34);
 887			b += 34;
 888		}
 889		for (y = 0; y < 3; ++y) {
 890			memcpy(&origin[EREADER_DOTCODE_STRIDE * (33 + y) + 7], &block[b], 26);
 891			b += 26;
 892		}
 893	}
 894	hw->eReaderX = -24;
 895}
 896
 897void _eReaderReset(struct GBACartridgeHardware* hw) {
 898	memset(hw->eReaderData, 0, sizeof(hw->eReaderData));
 899	hw->eReaderRegisterUnk = 0;
 900	hw->eReaderRegisterReset = 4;
 901	hw->eReaderRegisterControl0 = 0;
 902	hw->eReaderRegisterControl1 = 0x80;
 903	hw->eReaderRegisterLed = 0;
 904	hw->eReaderState = 0;
 905	hw->eReaderActiveRegister = 0;
 906}
 907
 908void _eReaderWriteControl0(struct GBACartridgeHardware* hw, uint8_t value) {
 909	EReaderControl0 control = value & 0x7F;
 910	EReaderControl0 oldControl = hw->eReaderRegisterControl0;
 911	if (hw->eReaderState == EREADER_SERIAL_INACTIVE) {
 912		if (EReaderControl0IsClock(oldControl) && EReaderControl0IsData(oldControl) && !EReaderControl0IsData(control)) {
 913			hw->eReaderState = EREADER_SERIAL_STARTING;
 914		}
 915	} else if (EReaderControl0IsClock(oldControl) && !EReaderControl0IsData(oldControl) && EReaderControl0IsData(control)) {
 916		hw->eReaderState = EREADER_SERIAL_INACTIVE;
 917
 918	} else if (hw->eReaderState == EREADER_SERIAL_STARTING) {
 919		if (EReaderControl0IsClock(oldControl) && !EReaderControl0IsData(oldControl) && !EReaderControl0IsClock(control)) {
 920			hw->eReaderState = EREADER_SERIAL_BIT_0;
 921			hw->eReaderCommand = EREADER_COMMAND_IDLE;
 922		}
 923	} else if (EReaderControl0IsClock(oldControl) && !EReaderControl0IsClock(control)) {
 924		mLOG(GBA_HW, DEBUG, "[e-Reader] Serial falling edge: %c %i", EReaderControl0IsDirection(control) ? '>' : '<', EReaderControl0GetData(control));
 925		// TODO: Improve direction control
 926		if (EReaderControl0IsDirection(control)) {
 927			hw->eReaderByte |= EReaderControl0GetData(control) << (7 - (hw->eReaderState - EREADER_SERIAL_BIT_0));
 928			++hw->eReaderState;
 929			if (hw->eReaderState == EREADER_SERIAL_END_BIT) {
 930				mLOG(GBA_HW, DEBUG, "[e-Reader] Wrote serial byte: %02x", hw->eReaderByte);
 931				switch (hw->eReaderCommand) {
 932				case EREADER_COMMAND_IDLE:
 933					hw->eReaderCommand = hw->eReaderByte;
 934					break;
 935				case EREADER_COMMAND_SET_INDEX:
 936					hw->eReaderActiveRegister = hw->eReaderByte;
 937					hw->eReaderCommand = EREADER_COMMAND_WRITE_DATA;
 938					break;
 939				case EREADER_COMMAND_WRITE_DATA:
 940					switch (hw->eReaderActiveRegister & 0x7F) {
 941					case 0:
 942					case 0x57:
 943					case 0x58:
 944					case 0x59:
 945					case 0x5A:
 946						// Read-only
 947						mLOG(GBA_HW, GAME_ERROR, "Writing to read-only e-Reader serial register: %02X", hw->eReaderActiveRegister);
 948						break;
 949					default:
 950						if ((hw->eReaderActiveRegister & 0x7F) > 0x5A) {
 951							mLOG(GBA_HW, GAME_ERROR, "Writing to non-existent e-Reader serial register: %02X", hw->eReaderActiveRegister);
 952							break;
 953						}
 954						hw->eReaderSerial[hw->eReaderActiveRegister & 0x7F] = hw->eReaderByte;
 955						break;
 956					}
 957					++hw->eReaderActiveRegister;
 958					break;
 959				default:
 960					mLOG(GBA_HW, ERROR, "Hit undefined state %02X in e-Reader state machine", hw->eReaderCommand);
 961					break;
 962				}
 963				hw->eReaderState = EREADER_SERIAL_BIT_0;
 964				hw->eReaderByte = 0;
 965			}
 966		} else if (hw->eReaderCommand == EREADER_COMMAND_READ_DATA) {
 967			int bit = hw->eReaderSerial[hw->eReaderActiveRegister & 0x7F] >> (7 - (hw->eReaderState - EREADER_SERIAL_BIT_0));
 968			control = EReaderControl0SetData(control, bit);
 969			++hw->eReaderState;
 970			if (hw->eReaderState == EREADER_SERIAL_END_BIT) {
 971				++hw->eReaderActiveRegister;
 972				mLOG(GBA_HW, DEBUG, "[e-Reader] Read serial byte: %02x", hw->eReaderSerial[hw->eReaderActiveRegister & 0x7F]);
 973			}
 974		}
 975	} else if (!EReaderControl0IsDirection(control)) {
 976		// Clear the error bit
 977		control = EReaderControl0ClearData(control);
 978	}
 979	hw->eReaderRegisterControl0 = control;
 980	if (!EReaderControl0IsScan(oldControl) && EReaderControl0IsScan(control)) {
 981		hw->eReaderX = 0;
 982		hw->eReaderY = 0;
 983		_eReaderReadData(hw);
 984	} else if (EReaderControl0IsLedEnable(control) && EReaderControl1IsScanline(hw->eReaderRegisterControl1)) {
 985		GBARaiseIRQ(hw->p, IRQ_GAMEPAK, 0);
 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 += 225;
 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}