all repos — mgba @ 4ac4733cfd4c4524c6a56d0406ba138d173fad61

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