all repos — mgba @ 2222010107fa367af94450dffd71d350d1fde96f

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
 14mLOG_DEFINE_CATEGORY(GBA_HW, "GBA Pak Hardware", "gba.hardware");
 15
 16const int GBA_LUX_LEVELS[10] = { 5, 11, 18, 27, 42, 62, 84, 109, 139, 183 };
 17
 18static void _readPins(struct GBACartridgeHardware* hw);
 19static void _outputPins(struct GBACartridgeHardware* hw, unsigned pins);
 20
 21static void _rtcReadPins(struct GBACartridgeHardware* hw);
 22static void _rtcUpdateClock(struct GBARTC* rtc, struct mRTCSource*);
 23static unsigned _rtcBCD(unsigned value);
 24
 25static void _gyroReadPins(struct GBACartridgeHardware* hw);
 26
 27static void _rumbleReadPins(struct GBACartridgeHardware* hw);
 28
 29static void _lightReadPins(struct GBACartridgeHardware* hw);
 30
 31static uint16_t _gbpRead(struct mKeyCallback*);
 32static uint16_t _gbpSioWriteRegister(struct GBASIODriver* driver, uint32_t address, uint16_t value);
 33static void _gbpSioProcessEvents(struct mTiming* timing, void* user, uint32_t cyclesLate);
 34
 35static const int RTC_BYTES[8] = {
 36	0, // Force reset
 37	0, // Empty
 38	7, // Date/Time
 39	0, // Force IRQ
 40	1, // Control register
 41	0, // Empty
 42	3, // Time
 43	0 // Empty
 44};
 45
 46void GBAHardwareInit(struct GBACartridgeHardware* hw, uint16_t* base) {
 47	hw->gpioBase = base;
 48	GBAHardwareClear(hw);
 49
 50	hw->gbpCallback.d.readKeys = _gbpRead;
 51	hw->gbpCallback.p = hw;
 52	hw->gbpDriver.d.init = 0;
 53	hw->gbpDriver.d.deinit = 0;
 54	hw->gbpDriver.d.load = 0;
 55	hw->gbpDriver.d.unload = 0;
 56	hw->gbpDriver.d.writeRegister = _gbpSioWriteRegister;
 57	hw->gbpDriver.p = hw;
 58	hw->gbpNextEvent.context = &hw->gbpDriver;
 59	hw->gbpNextEvent.name = "GBA SIO Game Boy Player";
 60	hw->gbpNextEvent.callback = _gbpSioProcessEvents;
 61	hw->gbpNextEvent.priority = 0x80;
 62}
 63
 64void GBAHardwareClear(struct GBACartridgeHardware* hw) {
 65	hw->devices = HW_NONE | (hw->devices & HW_GB_PLAYER_DETECTION);
 66	hw->direction = GPIO_WRITE_ONLY;
 67	hw->pinState = 0;
 68	hw->direction = 0;
 69
 70	if (hw->p->sio.drivers.normal == &hw->gbpDriver.d) {
 71		GBASIOSetDriver(&hw->p->sio, 0, SIO_NORMAL_32);
 72	}
 73}
 74
 75void GBAHardwareGPIOWrite(struct GBACartridgeHardware* hw, uint32_t address, uint16_t value) {
 76	switch (address) {
 77	case GPIO_REG_DATA:
 78		hw->pinState &= ~hw->direction;
 79		hw->pinState |= value;
 80		_readPins(hw);
 81		break;
 82	case GPIO_REG_DIRECTION:
 83		hw->direction = value;
 84		break;
 85	case GPIO_REG_CONTROL:
 86		hw->readWrite = value;
 87		break;
 88	default:
 89		mLOG(GBA_HW, WARN, "Invalid GPIO address");
 90	}
 91	if (hw->readWrite) {
 92		uint16_t old;
 93		LOAD_16(old, 0, hw->gpioBase);
 94		old &= ~hw->direction;
 95		old |= hw->pinState;
 96		STORE_16(old, 0, hw->gpioBase);
 97	} else {
 98		hw->gpioBase[0] = 0;
 99	}
100}
101
102void GBAHardwareInitRTC(struct GBACartridgeHardware* hw) {
103	hw->devices |= HW_RTC;
104	hw->rtc.bytesRemaining = 0;
105
106	hw->rtc.transferStep = 0;
107
108	hw->rtc.bitsRead = 0;
109	hw->rtc.bits = 0;
110	hw->rtc.commandActive = 0;
111	hw->rtc.command = 0;
112	hw->rtc.control = 0x40;
113	memset(hw->rtc.time, 0, sizeof(hw->rtc.time));
114}
115
116void _readPins(struct GBACartridgeHardware* hw) {
117	if (hw->devices & HW_RTC) {
118		_rtcReadPins(hw);
119	}
120
121	if (hw->devices & HW_GYRO) {
122		_gyroReadPins(hw);
123	}
124
125	if (hw->devices & HW_RUMBLE) {
126		_rumbleReadPins(hw);
127	}
128
129	if (hw->devices & HW_LIGHT_SENSOR) {
130		_lightReadPins(hw);
131	}
132}
133
134void _outputPins(struct GBACartridgeHardware* hw, unsigned pins) {
135	if (hw->readWrite) {
136		uint16_t old;
137		LOAD_16(old, 0, hw->gpioBase);
138		old &= hw->direction;
139		hw->pinState = old | (pins & ~hw->direction & 0xF);
140		STORE_16(hw->pinState, 0, hw->gpioBase);
141	}
142}
143
144// == RTC
145
146void _rtcReadPins(struct GBACartridgeHardware* hw) {
147	// Transfer sequence:
148	// P: 0 | 1 |  2 | 3
149	// == Initiate
150	// > HI | - | LO | -
151	// > HI | - | HI | -
152	// == Transfer bit (x8)
153	// > LO | x | HI | -
154	// > HI | - | HI | -
155	// < ?? | x | ?? | -
156	// == Terminate
157	// >  - | - | LO | -
158	switch (hw->rtc.transferStep) {
159	case 0:
160		if ((hw->pinState & 5) == 1) {
161			hw->rtc.transferStep = 1;
162		}
163		break;
164	case 1:
165		if ((hw->pinState & 5) == 5) {
166			hw->rtc.transferStep = 2;
167		}
168		break;
169	case 2:
170		if (!(hw->pinState & 1)) {
171			hw->rtc.bits &= ~(1 << hw->rtc.bitsRead);
172			hw->rtc.bits |= ((hw->pinState & 2) >> 1) << hw->rtc.bitsRead;
173		} else {
174			if (hw->pinState & 4) {
175				// GPIO direction should always != reading
176				if (hw->direction & 2) {
177					if (RTCCommandDataIsReading(hw->rtc.command)) {
178						mLOG(GBA_HW, GAME_ERROR, "Attempting to write to RTC while in read mode");
179					}
180					++hw->rtc.bitsRead;
181					if (hw->rtc.bitsRead == 8) {
182						GBARTCProcessByte(&hw->rtc, hw->p->rtcSource);
183					}
184				} else {
185					_outputPins(hw, 5 | (GBARTCOutput(&hw->rtc) << 1));
186					++hw->rtc.bitsRead;
187					if (hw->rtc.bitsRead == 8) {
188						--hw->rtc.bytesRemaining;
189						if (hw->rtc.bytesRemaining <= 0) {
190							hw->rtc.commandActive = 0;
191							hw->rtc.command = RTCCommandDataClearReading(hw->rtc.command);
192						}
193						hw->rtc.bitsRead = 0;
194					}
195				}
196			} else {
197				hw->rtc.bitsRead = 0;
198				hw->rtc.bytesRemaining = 0;
199				hw->rtc.commandActive = 0;
200				hw->rtc.command = RTCCommandDataClearReading(hw->rtc.command);
201				hw->rtc.transferStep = 0;
202			}
203		}
204		break;
205	}
206}
207
208void GBARTCProcessByte(struct GBARTC* rtc, struct mRTCSource* source) {
209	--rtc->bytesRemaining;
210	if (!rtc->commandActive) {
211		RTCCommandData command;
212		command = rtc->bits;
213		if (RTCCommandDataGetMagic(command) == 0x06) {
214			rtc->command = command;
215
216			rtc->bytesRemaining = RTC_BYTES[RTCCommandDataGetCommand(command)];
217			rtc->commandActive = rtc->bytesRemaining > 0;
218			switch (RTCCommandDataGetCommand(command)) {
219			case RTC_RESET:
220				rtc->control = 0;
221				break;
222			case RTC_DATETIME:
223			case RTC_TIME:
224				_rtcUpdateClock(rtc, source);
225				break;
226			case RTC_FORCE_IRQ:
227			case RTC_CONTROL:
228				break;
229			}
230		} else {
231			mLOG(GBA_HW, WARN, "Invalid RTC command byte: %02X", rtc->bits);
232		}
233	} else {
234		switch (RTCCommandDataGetCommand(rtc->command)) {
235		case RTC_CONTROL:
236			rtc->control = rtc->bits;
237			break;
238		case RTC_FORCE_IRQ:
239			mLOG(GBA_HW, STUB, "Unimplemented RTC command %u", RTCCommandDataGetCommand(rtc->command));
240			break;
241		case RTC_RESET:
242		case RTC_DATETIME:
243		case RTC_TIME:
244			break;
245		}
246	}
247
248	rtc->bits = 0;
249	rtc->bitsRead = 0;
250	if (!rtc->bytesRemaining) {
251		rtc->commandActive = 0;
252		rtc->command = RTCCommandDataClearReading(rtc->command);
253	}
254}
255
256unsigned GBARTCOutput(struct GBARTC* rtc) {
257	uint8_t outputByte = 0;
258	switch (RTCCommandDataGetCommand(rtc->command)) {
259	case RTC_CONTROL:
260		outputByte = rtc->control;
261		break;
262	case RTC_DATETIME:
263	case RTC_TIME:
264		outputByte = rtc->time[7 - rtc->bytesRemaining];
265		break;
266	case RTC_FORCE_IRQ:
267	case RTC_RESET:
268		break;
269	}
270	unsigned output = (outputByte >> rtc->bitsRead) & 1;
271	return output;
272}
273
274void _rtcUpdateClock(struct GBARTC* rtc, struct mRTCSource* source) {
275	time_t t;
276	if (source) {
277		if (source->sample) {
278			source->sample(source);
279		}
280		t = source->unixTime(source);
281	} else {
282		t = time(0);
283	}
284	struct tm date;
285	localtime_r(&t, &date);
286	rtc->time[0] = _rtcBCD(date.tm_year - 100);
287	rtc->time[1] = _rtcBCD(date.tm_mon + 1);
288	rtc->time[2] = _rtcBCD(date.tm_mday);
289	rtc->time[3] = _rtcBCD(date.tm_wday);
290	if (RTCControlIsHour24(rtc->control)) {
291		rtc->time[4] = _rtcBCD(date.tm_hour);
292	} else {
293		rtc->time[4] = _rtcBCD(date.tm_hour % 12);
294	}
295	rtc->time[5] = _rtcBCD(date.tm_min);
296	rtc->time[6] = _rtcBCD(date.tm_sec);
297}
298
299unsigned _rtcBCD(unsigned value) {
300	int counter = value % 10;
301	value /= 10;
302	counter += (value % 10) << 4;
303	return counter;
304}
305
306// == Gyro
307
308void GBAHardwareInitGyro(struct GBACartridgeHardware* hw) {
309	hw->devices |= HW_GYRO;
310	hw->gyroSample = 0;
311	hw->gyroEdge = 0;
312}
313
314void _gyroReadPins(struct GBACartridgeHardware* hw) {
315	struct mRotationSource* gyro = hw->p->rotationSource;
316	if (!gyro || !gyro->readGyroZ) {
317		return;
318	}
319
320	if (hw->pinState & 1) {
321		if (gyro->sample) {
322			gyro->sample(gyro);
323		}
324		int32_t sample = gyro->readGyroZ(gyro);
325
326		// Normalize to ~12 bits, focused on 0x6C0
327		hw->gyroSample = (sample >> 21) + 0x6C0; // Crop off an extra bit so that we can't go negative
328	}
329
330	if (hw->gyroEdge && !(hw->pinState & 2)) {
331		// Write bit on falling edge
332		unsigned bit = hw->gyroSample >> 15;
333		hw->gyroSample <<= 1;
334		_outputPins(hw, bit << 2);
335	}
336
337	hw->gyroEdge = !!(hw->pinState & 2);
338}
339
340// == Rumble
341
342void GBAHardwareInitRumble(struct GBACartridgeHardware* hw) {
343	hw->devices |= HW_RUMBLE;
344}
345
346void _rumbleReadPins(struct GBACartridgeHardware* hw) {
347	struct mRumble* rumble = hw->p->rumble;
348	if (!rumble) {
349		return;
350	}
351
352	rumble->setRumble(rumble, !!(hw->pinState & 8));
353}
354
355// == Light sensor
356
357void GBAHardwareInitLight(struct GBACartridgeHardware* hw) {
358	hw->devices |= HW_LIGHT_SENSOR;
359	hw->lightCounter = 0;
360	hw->lightEdge = false;
361	hw->lightSample = 0xFF;
362}
363
364void _lightReadPins(struct GBACartridgeHardware* hw) {
365	if (hw->pinState & 4) {
366		// Boktai chip select
367		return;
368	}
369	if (hw->pinState & 2) {
370		struct GBALuminanceSource* lux = hw->p->luminanceSource;
371		mLOG(GBA_HW, DEBUG, "[SOLAR] Got reset");
372		hw->lightCounter = 0;
373		if (lux) {
374			lux->sample(lux);
375			hw->lightSample = lux->readLuminance(lux);
376		} else {
377			hw->lightSample = 0xFF;
378		}
379	}
380	if ((hw->pinState & 1) && hw->lightEdge) {
381		++hw->lightCounter;
382	}
383	hw->lightEdge = !(hw->pinState & 1);
384
385	bool sendBit = hw->lightCounter >= hw->lightSample;
386	_outputPins(hw, sendBit << 3);
387	mLOG(GBA_HW, DEBUG, "[SOLAR] Output %u with pins %u", hw->lightCounter, hw->pinState);
388}
389
390// == Tilt
391
392void GBAHardwareInitTilt(struct GBACartridgeHardware* hw) {
393	hw->devices |= HW_TILT;
394	hw->tiltX = 0xFFF;
395	hw->tiltY = 0xFFF;
396	hw->tiltState = 0;
397}
398
399void GBAHardwareTiltWrite(struct GBACartridgeHardware* hw, uint32_t address, uint8_t value) {
400	switch (address) {
401	case 0x8000:
402		if (value == 0x55) {
403			hw->tiltState = 1;
404		} else {
405			mLOG(GBA_HW, GAME_ERROR, "Tilt sensor wrote wrong byte to %04x: %02x", address, value);
406		}
407		break;
408	case 0x8100:
409		if (value == 0xAA && hw->tiltState == 1) {
410			hw->tiltState = 0;
411			struct mRotationSource* rotationSource = hw->p->rotationSource;
412			if (!rotationSource || !rotationSource->readTiltX || !rotationSource->readTiltY) {
413				return;
414			}
415			if (rotationSource->sample) {
416				rotationSource->sample(rotationSource);
417			}
418			int32_t x = rotationSource->readTiltX(rotationSource);
419			int32_t y = rotationSource->readTiltY(rotationSource);
420			// Normalize to ~12 bits, focused on 0x3A0
421			hw->tiltX = (x >> 21) + 0x3A0; // Crop off an extra bit so that we can't go negative
422			hw->tiltY = (y >> 21) + 0x3A0;
423		} else {
424			mLOG(GBA_HW, GAME_ERROR, "Tilt sensor wrote wrong byte to %04x: %02x", address, value);
425		}
426		break;
427	default:
428		mLOG(GBA_HW, GAME_ERROR, "Invalid tilt sensor write to %04x: %02x", address, value);
429		break;
430	}
431}
432
433uint8_t GBAHardwareTiltRead(struct GBACartridgeHardware* hw, uint32_t address) {
434	switch (address) {
435	case 0x8200:
436		return hw->tiltX & 0xFF;
437	case 0x8300:
438		return ((hw->tiltX >> 8) & 0xF) | 0x80;
439	case 0x8400:
440		return hw->tiltY & 0xFF;
441	case 0x8500:
442		return (hw->tiltY >> 8) & 0xF;
443	default:
444		mLOG(GBA_HW, GAME_ERROR, "Invalid tilt sensor read from %04x", address);
445		break;
446	}
447	return 0xFF;
448}
449
450// == Game Boy Player
451
452static const uint16_t _logoPalette[] = {
453	0xFFDF, 0x640C, 0xE40C, 0xE42D, 0x644E, 0xE44E, 0xE46E, 0x68AF,
454	0xE8B0, 0x68D0, 0x68F0, 0x6911, 0xE911, 0x6D32, 0xED32, 0xED73,
455	0x6D93, 0xED94, 0x6DB4, 0xF1D5, 0x71F5, 0xF1F6, 0x7216, 0x7257,
456	0xF657, 0x7678, 0xF678, 0xF699, 0xF6B9, 0x76D9, 0xF6DA, 0x7B1B,
457	0xFB1B, 0xFB3C, 0x7B5C, 0x7B7D, 0xFF7D, 0x7F9D, 0x7FBE, 0x7FFF,
458	0x642D, 0x648E, 0xE88F, 0xE8F1, 0x6D52, 0x6D73, 0xF1B4, 0xF216,
459	0x7237, 0x7698, 0x7AFA, 0xFAFA, 0xFB5C, 0xFFBE, 0x7FDE, 0xFFFF,
460	0xFFFF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
461};
462
463static const uint32_t _logoHash = 0xEEDA6963;
464
465static const uint32_t _gbpTxData[] = {
466	0x0000494E, 0x0000494E,
467	0xB6B1494E, 0xB6B1544E,
468	0xABB1544E, 0xABB14E45,
469	0xB1BA4E45, 0xB1BA4F44,
470	0xB0BB4F44, 0xB0BB8002,
471	0x10000010, 0x20000013,
472	0x30000003
473};
474
475bool GBAHardwarePlayerCheckScreen(const struct GBAVideo* video) {
476	if (memcmp(video->palette, _logoPalette, sizeof(_logoPalette)) != 0) {
477		return false;
478	}
479	uint32_t hash = hash32(&video->vram[0x4000], 0x4000, 0);
480	return hash == _logoHash;
481}
482
483void GBAHardwarePlayerUpdate(struct GBA* gba) {
484	if (gba->memory.hw.devices & HW_GB_PLAYER) {
485		if (GBAHardwarePlayerCheckScreen(&gba->video)) {
486			++gba->memory.hw.gbpInputsPosted;
487			gba->memory.hw.gbpInputsPosted %= 3;
488			gba->keyCallback = &gba->memory.hw.gbpCallback.d;
489		} else {
490			// TODO: Save and restore
491			gba->keyCallback = 0;
492		}
493		gba->memory.hw.gbpTxPosition = 0;
494		return;
495	}
496	if (gba->keyCallback || gba->sio.drivers.normal) {
497		return;
498	}
499	if (GBAHardwarePlayerCheckScreen(&gba->video)) {
500		gba->memory.hw.devices |= HW_GB_PLAYER;
501		gba->memory.hw.gbpInputsPosted = 0;
502		gba->keyCallback = &gba->memory.hw.gbpCallback.d;
503		GBASIOSetDriver(&gba->sio, &gba->memory.hw.gbpDriver.d, SIO_NORMAL_32);
504	}
505}
506
507uint16_t _gbpRead(struct mKeyCallback* callback) {
508	struct GBAGBPKeyCallback* gbpCallback = (struct GBAGBPKeyCallback*) callback;
509	if (gbpCallback->p->gbpInputsPosted == 2) {
510		return 0x30F;
511	}
512	return 0x3FF;
513}
514
515uint16_t _gbpSioWriteRegister(struct GBASIODriver* driver, uint32_t address, uint16_t value) {
516	struct GBAGBPSIODriver* gbp = (struct GBAGBPSIODriver*) driver;
517	if (address == REG_SIOCNT) {
518		if (value & 0x0080) {
519			uint32_t rx = gbp->p->p->memory.io[REG_SIODATA32_LO >> 1] | (gbp->p->p->memory.io[REG_SIODATA32_HI >> 1] << 16);
520			if (gbp->p->gbpTxPosition < 12 && gbp->p->gbpTxPosition > 0) {
521				// TODO: Check expected
522			} else if (gbp->p->gbpTxPosition >= 12) {
523				uint32_t mask = 0x33;
524				// 0x00 = Stop
525				// 0x11 = Hard Stop
526				// 0x22 = Start
527				if (gbp->p->p->rumble) {
528					gbp->p->p->rumble->setRumble(gbp->p->p->rumble, (rx & mask) == 0x22);
529				}
530			}
531			mTimingDeschedule(&gbp->p->p->timing, &gbp->p->gbpNextEvent);
532			mTimingSchedule(&gbp->p->p->timing, &gbp->p->gbpNextEvent, 2048);
533		}
534		value &= 0x78FB;
535	}
536	return value;
537}
538
539void _gbpSioProcessEvents(struct mTiming* timing, void* user, uint32_t cyclesLate) {
540	UNUSED(timing);
541	UNUSED(cyclesLate);
542	struct GBAGBPSIODriver* gbp = user;
543	uint32_t tx = 0;
544	int txPosition = gbp->p->gbpTxPosition;
545	if (txPosition > 16) {
546		gbp->p->gbpTxPosition = 0;
547		txPosition = 0;
548	} else if (txPosition > 12) {
549		txPosition = 12;
550	}
551	tx = _gbpTxData[txPosition];
552	++gbp->p->gbpTxPosition;
553	gbp->p->p->memory.io[REG_SIODATA32_LO >> 1] = tx;
554	gbp->p->p->memory.io[REG_SIODATA32_HI >> 1] = tx >> 16;
555	if (gbp->d.p->normalControl.irq) {
556		GBARaiseIRQ(gbp->p->p, IRQ_SIO);
557	}
558	gbp->d.p->normalControl.start = 0;
559	gbp->p->p->memory.io[REG_SIOCNT >> 1] = gbp->d.p->siocnt & ~0x0080;
560}
561
562// == Serialization
563
564void GBAHardwareSerialize(const struct GBACartridgeHardware* hw, struct GBASerializedState* state) {
565	GBASerializedHWFlags1 flags1 = 0;
566	GBASerializedHWFlags2 flags2 = 0;
567	flags1 = GBASerializedHWFlags1SetReadWrite(flags1, hw->readWrite);
568	STORE_16(hw->pinState, 0, &state->hw.pinState);
569	STORE_16(hw->direction, 0, &state->hw.pinDirection);
570	state->hw.devices = hw->devices;
571
572	STORE_32(hw->rtc.bytesRemaining, 0, &state->hw.rtc.bytesRemaining);
573	STORE_32(hw->rtc.transferStep, 0, &state->hw.rtc.transferStep);
574	STORE_32(hw->rtc.bitsRead, 0, &state->hw.rtc.bitsRead);
575	STORE_32(hw->rtc.bits, 0, &state->hw.rtc.bits);
576	STORE_32(hw->rtc.commandActive, 0, &state->hw.rtc.commandActive);
577	STORE_32(hw->rtc.command, 0, &state->hw.rtc.command);
578	STORE_32(hw->rtc.control, 0, &state->hw.rtc.control);
579	memcpy(state->hw.rtc.time, hw->rtc.time, sizeof(state->hw.rtc.time));
580
581	STORE_16(hw->gyroSample, 0, &state->hw.gyroSample);
582	flags1 = GBASerializedHWFlags1SetGyroEdge(flags1, hw->gyroEdge);
583	STORE_16(hw->tiltX, 0, &state->hw.tiltSampleX);
584	STORE_16(hw->tiltY, 0, &state->hw.tiltSampleY);
585	flags2 = GBASerializedHWFlags2SetTiltState(flags2, hw->tiltState);
586	flags2 = GBASerializedHWFlags1SetLightCounter(flags2, hw->lightCounter);
587	state->hw.lightSample = hw->lightSample;
588	flags1 = GBASerializedHWFlags1SetLightEdge(flags1, hw->lightEdge);
589	flags2 = GBASerializedHWFlags2SetGbpInputsPosted(flags2, hw->gbpInputsPosted);
590	flags2 = GBASerializedHWFlags2SetGbpTxPosition(flags2, hw->gbpTxPosition);
591	STORE_32(hw->gbpNextEvent.when - mTimingCurrentTime(&hw->p->timing), 0, &state->hw.gbpNextEvent);
592	STORE_16(flags1, 0, &state->hw.flags1);
593	state->hw.flags2 = flags2;
594}
595
596void GBAHardwareDeserialize(struct GBACartridgeHardware* hw, const struct GBASerializedState* state) {
597	GBASerializedHWFlags1 flags1;
598	LOAD_16(flags1, 0, &state->hw.flags1);
599	hw->readWrite = GBASerializedHWFlags1GetReadWrite(flags1);
600	LOAD_16(hw->pinState, 0, &state->hw.pinState);
601	LOAD_16(hw->direction, 0, &state->hw.pinDirection);
602	hw->devices = state->hw.devices;
603
604	LOAD_32(hw->rtc.bytesRemaining, 0, &state->hw.rtc.bytesRemaining);
605	LOAD_32(hw->rtc.transferStep, 0, &state->hw.rtc.transferStep);
606	LOAD_32(hw->rtc.bitsRead, 0, &state->hw.rtc.bitsRead);
607	LOAD_32(hw->rtc.bits, 0, &state->hw.rtc.bits);
608	LOAD_32(hw->rtc.commandActive, 0, &state->hw.rtc.commandActive);
609	LOAD_32(hw->rtc.command, 0, &state->hw.rtc.command);
610	LOAD_32(hw->rtc.control, 0, &state->hw.rtc.control);
611	memcpy(hw->rtc.time, state->hw.rtc.time, sizeof(hw->rtc.time));
612
613	LOAD_16(hw->gyroSample, 0, &state->hw.gyroSample);
614	hw->gyroEdge = GBASerializedHWFlags1GetGyroEdge(flags1);
615	LOAD_16(hw->tiltX, 0, &state->hw.tiltSampleX);
616	LOAD_16(hw->tiltY, 0, &state->hw.tiltSampleY);
617	hw->tiltState = GBASerializedHWFlags2GetTiltState(state->hw.flags2);
618	hw->lightCounter = GBASerializedHWFlags1GetLightCounter(flags1);
619	hw->lightSample = state->hw.lightSample;
620	hw->lightEdge = GBASerializedHWFlags1GetLightEdge(flags1);
621	hw->gbpInputsPosted = GBASerializedHWFlags2GetGbpInputsPosted(state->hw.flags2);
622	hw->gbpTxPosition = GBASerializedHWFlags2GetGbpTxPosition(state->hw.flags2);
623
624	uint32_t when;
625	LOAD_32(when, 0, &state->hw.gbpNextEvent);
626	if (hw->devices & HW_GB_PLAYER) {
627		GBASIOSetDriver(&hw->p->sio, &hw->gbpDriver.d, SIO_NORMAL_32);
628		if (hw->p->memory.io[REG_SIOCNT >> 1] & 0x0080) {
629			mTimingSchedule(&hw->p->timing, &hw->gbpNextEvent, when);
630		}
631	}
632}