all repos — mgba @ 045417b5096f12301657f5c5d24ccd5769b36551

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