all repos — mgba @ aefb4b62a16943f090c72262fe8a41edf88a0397

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