all repos — mgba @ ea8561347c6e1f2ee0fc195e24f8e624b520f423

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