all repos — mgba @ a6ce525da1ed0f7e14e8db927871d2127681fc95

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