all repos — mgba @ 5e2e3864b7ecfc308f0f390dbb8b2f9f9aa16199

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
490};
491
492static const uint32_t _gbpRxData[] = {
493	0x00000000, 0x494EB6B1,
494	0x494EB6B1, 0x544EB6B1,
495	0x544EABB1, 0x4E45ABB1,
496	0x4E45B1BA, 0x4F44B1BA,
497	0x4F44B0BB, 0x8000B0BB,
498	0x10000010, 0x20000013,
499	0x40000004
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->renderer->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->memory.hw.gbpNextEvent = INT_MAX;
530		gba->keyCallback = &gba->memory.hw.gbpCallback.d;
531		GBASIOSetDriver(&gba->sio, &gba->memory.hw.gbpDriver.d, SIO_NORMAL_32);
532	}
533}
534
535uint16_t _gbpRead(struct GBAKeyCallback* callback) {
536	struct GBAGBPKeyCallback* gbpCallback = (struct GBAGBPKeyCallback*) callback;
537	if (gbpCallback->p->gbpInputsPosted == 2) {
538		return 0x30F;
539	}
540	return 0x3FF;
541}
542
543uint16_t _gbpSioWriteRegister(struct GBASIODriver* driver, uint32_t address, uint16_t value) {
544	struct GBAGBPSIODriver* gbp = (struct GBAGBPSIODriver*) driver;
545	if (address == REG_SIOCNT) {
546		if (value & 0x0080) {
547			uint32_t rx = gbp->p->p->memory.io[REG_SIODATA32_LO >> 1] | (gbp->p->p->memory.io[REG_SIODATA32_HI >> 1] << 16);
548			if (gbp->p->gbpTxPosition < 12 && gbp->p->gbpTxPosition > 0) {
549				uint32_t expected = _gbpRxData[gbp->p->gbpTxPosition];
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			gbp->p->gbpNextEvent = 2048;
561		}
562		value &= 0x78FB;
563	}
564	return value;
565}
566
567int32_t _gbpSioProcessEvents(struct GBASIODriver* driver, int32_t cycles) {
568	struct GBAGBPSIODriver* gbp = (struct GBAGBPSIODriver*) driver;
569	gbp->p->gbpNextEvent -= cycles;
570	if (gbp->p->gbpNextEvent <= 0) {
571		uint32_t tx = 0;
572		if (gbp->p->gbpTxPosition <= 12) {
573			tx = _gbpTxData[gbp->p->gbpTxPosition];
574			if (gbp->p->gbpTxPosition < 12) {
575				++gbp->p->gbpTxPosition;
576			}
577		}
578		gbp->p->p->memory.io[REG_SIODATA32_LO >> 1] = tx;
579		gbp->p->p->memory.io[REG_SIODATA32_HI >> 1] = tx >> 16;
580		if (gbp->d.p->normalControl.irq) {
581			GBARaiseIRQ(gbp->p->p, IRQ_SIO);
582		}
583		gbp->d.p->normalControl.start = 0;
584		gbp->p->p->memory.io[REG_SIOCNT >> 1] = gbp->d.p->siocnt;
585		gbp->p->gbpNextEvent = INT_MAX;
586	}
587	return gbp->p->gbpNextEvent;
588}
589
590// == Serialization
591
592void GBAHardwareSerialize(const struct GBACartridgeHardware* hw, struct GBASerializedState* state) {
593	GBASerializedHWFlags1 flags1 = 0;
594	GBASerializedHWFlags2 flags2 = 0;
595	flags1 = GBASerializedHWFlags1SetReadWrite(flags1, hw->readWrite);
596	STORE_16(hw->pinState, 0, &state->hw.pinState);
597	STORE_16(hw->direction, 0, &state->hw.pinDirection);
598	state->hw.devices = hw->devices;
599
600	STORE_32(hw->rtc.bytesRemaining, 0, &state->hw.rtc.bytesRemaining);
601	STORE_32(hw->rtc.transferStep, 0, &state->hw.rtc.transferStep);
602	STORE_32(hw->rtc.bitsRead, 0, &state->hw.rtc.bitsRead);
603	STORE_32(hw->rtc.bits, 0, &state->hw.rtc.bits);
604	STORE_32(hw->rtc.commandActive, 0, &state->hw.rtc.commandActive);
605	STORE_32(hw->rtc.command, 0, &state->hw.rtc.command);
606	STORE_32(hw->rtc.control, 0, &state->hw.rtc.control);
607	memcpy(state->hw.rtc.time, hw->rtc.time, sizeof(state->hw.rtc.time));
608
609	STORE_16(hw->gyroSample, 0, &state->hw.gyroSample);
610	flags1 = GBASerializedHWFlags1SetGyroEdge(flags1, hw->gyroEdge);
611	STORE_16(hw->tiltX, 0, &state->hw.tiltSampleX);
612	STORE_16(hw->tiltY, 0, &state->hw.tiltSampleY);
613	flags2 = GBASerializedHWFlags2SetTiltState(flags2, hw->tiltState);
614	flags2 = GBASerializedHWFlags1SetLightCounter(flags2, hw->lightCounter);
615	state->hw.lightSample = hw->lightSample;
616	flags1 = GBASerializedHWFlags1SetLightEdge(flags1, hw->lightEdge);
617	flags2 = GBASerializedHWFlags2SetGbpInputsPosted(flags2, hw->gbpInputsPosted);
618	flags2 = GBASerializedHWFlags2SetGbpTxPosition(flags2, hw->gbpTxPosition);
619	STORE_32(hw->gbpNextEvent, 0, &state->hw.gbpNextEvent);
620	STORE_16(flags1, 0, &state->hw.flags1);
621	state->hw.flags2 = flags2;
622}
623
624void GBAHardwareDeserialize(struct GBACartridgeHardware* hw, const struct GBASerializedState* state) {
625	GBASerializedHWFlags1 flags1;
626	LOAD_16(flags1, 0, &state->hw.flags1);
627	hw->readWrite = GBASerializedHWFlags1GetReadWrite(flags1);
628	LOAD_16(hw->pinState, 0, &state->hw.pinState);
629	LOAD_16(hw->direction, 0, &state->hw.pinDirection);
630	hw->devices = state->hw.devices;
631
632	LOAD_32(hw->rtc.bytesRemaining, 0, &state->hw.rtc.bytesRemaining);
633	LOAD_32(hw->rtc.transferStep, 0, &state->hw.rtc.transferStep);
634	LOAD_32(hw->rtc.bitsRead, 0, &state->hw.rtc.bitsRead);
635	LOAD_32(hw->rtc.bits, 0, &state->hw.rtc.bits);
636	LOAD_32(hw->rtc.commandActive, 0, &state->hw.rtc.commandActive);
637	LOAD_32(hw->rtc.command, 0, &state->hw.rtc.command);
638	LOAD_32(hw->rtc.control, 0, &state->hw.rtc.control);
639	memcpy(hw->rtc.time, state->hw.rtc.time, sizeof(hw->rtc.time));
640
641	LOAD_16(hw->gyroSample, 0, &state->hw.gyroSample);
642	hw->gyroEdge = GBASerializedHWFlags1GetGyroEdge(flags1);
643	LOAD_16(hw->tiltX, 0, &state->hw.tiltSampleX);
644	LOAD_16(hw->tiltY, 0, &state->hw.tiltSampleY);
645	hw->tiltState = GBASerializedHWFlags2GetTiltState(state->hw.flags2);
646	hw->lightCounter = GBASerializedHWFlags1GetLightCounter(flags1);
647	hw->lightSample = state->hw.lightSample;
648	hw->lightEdge = GBASerializedHWFlags1GetLightEdge(flags1);
649	hw->gbpInputsPosted = GBASerializedHWFlags2GetGbpInputsPosted(state->hw.flags2);
650	hw->gbpTxPosition = GBASerializedHWFlags2GetGbpTxPosition(state->hw.flags2);
651	LOAD_32(hw->gbpNextEvent, 0, &state->hw.gbpNextEvent);
652	if (hw->devices & HW_GB_PLAYER) {
653		GBASIOSetDriver(&hw->p->sio, &hw->gbpDriver.d, SIO_NORMAL_32);
654	}
655}