all repos — mgba @ 5b8d64b0b5e5b3aa1edac7a98be6cbf471869dd0

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