all repos — mgba @ e0ca7c69a256b6085d658d81adf3a843b1b493f9

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