all repos — mgba @ 67905d281bfecbb06f51f2ca5ac939df378734a5

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