all repos — mgba @ f2dadbd8b1e577c379de5a583b223f257ad8e8bb

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
497bool GBAHardwarePlayerCheckScreen(const struct GBAVideo* video) {
498	if (memcmp(video->palette, _logoPalette, sizeof(_logoPalette)) != 0) {
499		return false;
500	}
501	uint32_t hash = hash32(&video->renderer->vram[0x4000], 0x4000, 0);
502	return hash == _logoHash;
503}
504
505void GBAHardwarePlayerUpdate(struct GBA* gba) {
506	if (gba->memory.hw.devices & HW_GB_PLAYER) {
507		if (GBAHardwarePlayerCheckScreen(&gba->video)) {
508			++gba->memory.hw.gbpInputsPosted;
509			gba->memory.hw.gbpInputsPosted %= 3;
510			gba->keyCallback = &gba->memory.hw.gbpCallback.d;
511		} else {
512			// TODO: Save and restore
513			gba->keyCallback = 0;
514		}
515		gba->memory.hw.gbpTxPosition = 0;
516		return;
517	}
518	if (gba->keyCallback || gba->sio.drivers.normal) {
519		return;
520	}
521	if (GBAHardwarePlayerCheckScreen(&gba->video)) {
522		gba->memory.hw.devices |= HW_GB_PLAYER;
523		gba->memory.hw.gbpInputsPosted = 0;
524		gba->memory.hw.gbpNextEvent = INT_MAX;
525		gba->keyCallback = &gba->memory.hw.gbpCallback.d;
526		GBASIOSetDriver(&gba->sio, &gba->memory.hw.gbpDriver.d, SIO_NORMAL_32);
527	}
528}
529
530uint16_t _gbpRead(struct mKeyCallback* callback) {
531	struct GBAGBPKeyCallback* gbpCallback = (struct GBAGBPKeyCallback*) callback;
532	if (gbpCallback->p->gbpInputsPosted == 2) {
533		return 0x30F;
534	}
535	return 0x3FF;
536}
537
538uint16_t _gbpSioWriteRegister(struct GBASIODriver* driver, uint32_t address, uint16_t value) {
539	struct GBAGBPSIODriver* gbp = (struct GBAGBPSIODriver*) driver;
540	if (address == REG_SIOCNT) {
541		if (value & 0x0080) {
542			uint32_t rx = gbp->p->p->memory.io[REG_SIODATA32_LO >> 1] | (gbp->p->p->memory.io[REG_SIODATA32_HI >> 1] << 16);
543			if (gbp->p->gbpTxPosition < 12 && gbp->p->gbpTxPosition > 0) {
544				// TODO: Check expected
545			} else if (gbp->p->gbpTxPosition >= 12) {
546				uint32_t mask = 0x33;
547				// 0x00 = Stop
548				// 0x11 = Hard Stop
549				// 0x22 = Start
550				if (gbp->p->p->rumble) {
551					gbp->p->p->rumble->setRumble(gbp->p->p->rumble, (rx & mask) == 0x22);
552				}
553			}
554			gbp->p->gbpNextEvent = 2048;
555		}
556		value &= 0x78FB;
557	}
558	return value;
559}
560
561int32_t _gbpSioProcessEvents(struct GBASIODriver* driver, int32_t cycles) {
562	struct GBAGBPSIODriver* gbp = (struct GBAGBPSIODriver*) driver;
563	gbp->p->gbpNextEvent -= cycles;
564	if (gbp->p->gbpNextEvent <= 0) {
565		uint32_t tx = 0;
566		int txPosition = gbp->p->gbpTxPosition;
567		if (txPosition > 16) {
568			gbp->p->gbpTxPosition = 0;
569			txPosition = 0;
570		} else if (txPosition > 12) {
571			txPosition = 12;
572		}
573		tx = _gbpTxData[txPosition];
574		++gbp->p->gbpTxPosition;
575		gbp->p->p->memory.io[REG_SIODATA32_LO >> 1] = tx;
576		gbp->p->p->memory.io[REG_SIODATA32_HI >> 1] = tx >> 16;
577		if (gbp->d.p->normalControl.irq) {
578			GBARaiseIRQ(gbp->p->p, IRQ_SIO);
579		}
580		gbp->d.p->normalControl.start = 0;
581		gbp->p->p->memory.io[REG_SIOCNT >> 1] = gbp->d.p->siocnt;
582		gbp->p->gbpNextEvent = INT_MAX;
583	}
584	return gbp->p->gbpNextEvent;
585}
586
587// == Serialization
588
589void GBAHardwareSerialize(const struct GBACartridgeHardware* hw, struct GBASerializedState* state) {
590	GBASerializedHWFlags1 flags1 = 0;
591	GBASerializedHWFlags2 flags2 = 0;
592	flags1 = GBASerializedHWFlags1SetReadWrite(flags1, hw->readWrite);
593	STORE_16(hw->pinState, 0, &state->hw.pinState);
594	STORE_16(hw->direction, 0, &state->hw.pinDirection);
595	state->hw.devices = hw->devices;
596
597	STORE_32(hw->rtc.bytesRemaining, 0, &state->hw.rtc.bytesRemaining);
598	STORE_32(hw->rtc.transferStep, 0, &state->hw.rtc.transferStep);
599	STORE_32(hw->rtc.bitsRead, 0, &state->hw.rtc.bitsRead);
600	STORE_32(hw->rtc.bits, 0, &state->hw.rtc.bits);
601	STORE_32(hw->rtc.commandActive, 0, &state->hw.rtc.commandActive);
602	STORE_32(hw->rtc.command, 0, &state->hw.rtc.command);
603	STORE_32(hw->rtc.control, 0, &state->hw.rtc.control);
604	memcpy(state->hw.rtc.time, hw->rtc.time, sizeof(state->hw.rtc.time));
605
606	STORE_16(hw->gyroSample, 0, &state->hw.gyroSample);
607	flags1 = GBASerializedHWFlags1SetGyroEdge(flags1, hw->gyroEdge);
608	STORE_16(hw->tiltX, 0, &state->hw.tiltSampleX);
609	STORE_16(hw->tiltY, 0, &state->hw.tiltSampleY);
610	flags2 = GBASerializedHWFlags2SetTiltState(flags2, hw->tiltState);
611	flags2 = GBASerializedHWFlags1SetLightCounter(flags2, hw->lightCounter);
612	state->hw.lightSample = hw->lightSample;
613	flags1 = GBASerializedHWFlags1SetLightEdge(flags1, hw->lightEdge);
614	flags2 = GBASerializedHWFlags2SetGbpInputsPosted(flags2, hw->gbpInputsPosted);
615	flags2 = GBASerializedHWFlags2SetGbpTxPosition(flags2, hw->gbpTxPosition);
616	STORE_32(hw->gbpNextEvent, 0, &state->hw.gbpNextEvent);
617	STORE_16(flags1, 0, &state->hw.flags1);
618	state->hw.flags2 = flags2;
619}
620
621void GBAHardwareDeserialize(struct GBACartridgeHardware* hw, const struct GBASerializedState* state) {
622	GBASerializedHWFlags1 flags1;
623	LOAD_16(flags1, 0, &state->hw.flags1);
624	hw->readWrite = GBASerializedHWFlags1GetReadWrite(flags1);
625	LOAD_16(hw->pinState, 0, &state->hw.pinState);
626	LOAD_16(hw->direction, 0, &state->hw.pinDirection);
627	hw->devices = state->hw.devices;
628
629	LOAD_32(hw->rtc.bytesRemaining, 0, &state->hw.rtc.bytesRemaining);
630	LOAD_32(hw->rtc.transferStep, 0, &state->hw.rtc.transferStep);
631	LOAD_32(hw->rtc.bitsRead, 0, &state->hw.rtc.bitsRead);
632	LOAD_32(hw->rtc.bits, 0, &state->hw.rtc.bits);
633	LOAD_32(hw->rtc.commandActive, 0, &state->hw.rtc.commandActive);
634	LOAD_32(hw->rtc.command, 0, &state->hw.rtc.command);
635	LOAD_32(hw->rtc.control, 0, &state->hw.rtc.control);
636	memcpy(hw->rtc.time, state->hw.rtc.time, sizeof(hw->rtc.time));
637
638	LOAD_16(hw->gyroSample, 0, &state->hw.gyroSample);
639	hw->gyroEdge = GBASerializedHWFlags1GetGyroEdge(flags1);
640	LOAD_16(hw->tiltX, 0, &state->hw.tiltSampleX);
641	LOAD_16(hw->tiltY, 0, &state->hw.tiltSampleY);
642	hw->tiltState = GBASerializedHWFlags2GetTiltState(state->hw.flags2);
643	hw->lightCounter = GBASerializedHWFlags1GetLightCounter(flags1);
644	hw->lightSample = state->hw.lightSample;
645	hw->lightEdge = GBASerializedHWFlags1GetLightEdge(flags1);
646	hw->gbpInputsPosted = GBASerializedHWFlags2GetGbpInputsPosted(state->hw.flags2);
647	hw->gbpTxPosition = GBASerializedHWFlags2GetGbpTxPosition(state->hw.flags2);
648	LOAD_32(hw->gbpNextEvent, 0, &state->hw.gbpNextEvent);
649	if (hw->devices & HW_GB_PLAYER) {
650		GBASIOSetDriver(&hw->p->sio, &hw->gbpDriver.d, SIO_NORMAL_32);
651	}
652}