all repos — mgba @ 0ce3b9a2b7ae866a850d5bae19de5fe67d2ca628

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