all repos — mgba @ 32bed3a06fd0d2207d7da50ee2b30ff96a034438

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
 16MGBA_EXPORT const 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 void _eReaderReset(struct GBACartridgeHardware* hw);
 40static void _eReaderWriteControl0(struct GBACartridgeHardware* hw, uint8_t value);
 41static void _eReaderWriteControl1(struct GBACartridgeHardware* hw, uint8_t value);
 42static void _eReaderReadData(struct GBACartridgeHardware* hw);
 43
 44static const int RTC_BYTES[8] = {
 45	0, // Force reset
 46	0, // Empty
 47	7, // Date/Time
 48	0, // Force IRQ
 49	1, // Control register
 50	0, // Empty
 51	3, // Time
 52	0 // Empty
 53};
 54
 55void GBAHardwareInit(struct GBACartridgeHardware* hw, uint16_t* base) {
 56	hw->gpioBase = base;
 57	GBAHardwareClear(hw);
 58
 59	hw->gbpCallback.d.readKeys = _gbpRead;
 60	hw->gbpCallback.p = hw;
 61	hw->gbpDriver.d.init = 0;
 62	hw->gbpDriver.d.deinit = 0;
 63	hw->gbpDriver.d.load = 0;
 64	hw->gbpDriver.d.unload = 0;
 65	hw->gbpDriver.d.writeRegister = _gbpSioWriteRegister;
 66	hw->gbpDriver.p = hw;
 67	hw->gbpNextEvent.context = &hw->gbpDriver;
 68	hw->gbpNextEvent.name = "GBA SIO Game Boy Player";
 69	hw->gbpNextEvent.callback = _gbpSioProcessEvents;
 70	hw->gbpNextEvent.priority = 0x80;
 71}
 72
 73void GBAHardwareClear(struct GBACartridgeHardware* hw) {
 74	hw->devices = HW_NONE | (hw->devices & HW_GB_PLAYER_DETECTION);
 75	hw->readWrite = GPIO_WRITE_ONLY;
 76	hw->pinState = 0;
 77	hw->direction = 0;
 78
 79	if (hw->p->sio.drivers.normal == &hw->gbpDriver.d) {
 80		GBASIOSetDriver(&hw->p->sio, 0, SIO_NORMAL_32);
 81	}
 82}
 83
 84void GBAHardwareGPIOWrite(struct GBACartridgeHardware* hw, uint32_t address, uint16_t value) {
 85	if (!hw->gpioBase) {
 86		return;
 87	}
 88	switch (address) {
 89	case GPIO_REG_DATA:
 90		hw->pinState &= ~hw->direction;
 91		hw->pinState |= value & hw->direction;
 92		_readPins(hw);
 93		break;
 94	case GPIO_REG_DIRECTION:
 95		hw->direction = value;
 96		break;
 97	case GPIO_REG_CONTROL:
 98		hw->readWrite = value;
 99		break;
100	default:
101		mLOG(GBA_HW, WARN, "Invalid GPIO address");
102	}
103	if (hw->readWrite) {
104		STORE_16(hw->pinState, 0, hw->gpioBase);
105		STORE_16(hw->direction, 2, hw->gpioBase);
106		STORE_16(hw->readWrite, 4, hw->gpioBase);
107	} else {
108		hw->gpioBase[0] = 0;
109		hw->gpioBase[1] = 0;
110		hw->gpioBase[2] = 0;
111	}
112}
113
114void GBAHardwareInitRTC(struct GBACartridgeHardware* hw) {
115	hw->devices |= HW_RTC;
116	hw->rtc.bytesRemaining = 0;
117
118	hw->rtc.transferStep = 0;
119
120	hw->rtc.bitsRead = 0;
121	hw->rtc.bits = 0;
122	hw->rtc.commandActive = 0;
123	hw->rtc.command = 0;
124	hw->rtc.control = 0x40;
125	memset(hw->rtc.time, 0, sizeof(hw->rtc.time));
126}
127
128void _readPins(struct GBACartridgeHardware* hw) {
129	if (hw->devices & HW_RTC) {
130		_rtcReadPins(hw);
131	}
132
133	if (hw->devices & HW_GYRO) {
134		_gyroReadPins(hw);
135	}
136
137	if (hw->devices & HW_RUMBLE) {
138		_rumbleReadPins(hw);
139	}
140
141	if (hw->devices & HW_LIGHT_SENSOR) {
142		_lightReadPins(hw);
143	}
144}
145
146void _outputPins(struct GBACartridgeHardware* hw, unsigned pins) {
147	if (hw->readWrite) {
148		uint16_t old;
149		LOAD_16(old, 0, hw->gpioBase);
150		old &= hw->direction;
151		hw->pinState = old | (pins & ~hw->direction & 0xF);
152		STORE_16(hw->pinState, 0, hw->gpioBase);
153	}
154}
155
156// == RTC
157
158void _rtcReadPins(struct GBACartridgeHardware* hw) {
159	// Transfer sequence:
160	// P: 0 | 1 |  2 | 3
161	// == Initiate
162	// > HI | - | LO | -
163	// > HI | - | HI | -
164	// == Transfer bit (x8)
165	// > LO | x | HI | -
166	// > HI | - | HI | -
167	// < ?? | x | ?? | -
168	// == Terminate
169	// >  - | - | LO | -
170	switch (hw->rtc.transferStep) {
171	case 0:
172		if ((hw->pinState & 5) == 1) {
173			hw->rtc.transferStep = 1;
174		}
175		break;
176	case 1:
177		if ((hw->pinState & 5) == 5) {
178			hw->rtc.transferStep = 2;
179		} else if ((hw->pinState & 5) != 1) {
180			hw->rtc.transferStep = 0;
181		}
182		break;
183	case 2:
184		if (!(hw->pinState & 1)) {
185			hw->rtc.bits &= ~(1 << hw->rtc.bitsRead);
186			hw->rtc.bits |= ((hw->pinState & 2) >> 1) << hw->rtc.bitsRead;
187		} else {
188			if (hw->pinState & 4) {
189				if (!RTCCommandDataIsReading(hw->rtc.command)) {
190					++hw->rtc.bitsRead;
191					if (hw->rtc.bitsRead == 8) {
192						_rtcProcessByte(hw);
193					}
194				} else {
195					_outputPins(hw, 5 | (_rtcOutput(hw) << 1));
196					++hw->rtc.bitsRead;
197					if (hw->rtc.bitsRead == 8) {
198						--hw->rtc.bytesRemaining;
199						if (hw->rtc.bytesRemaining <= 0) {
200							hw->rtc.commandActive = 0;
201							hw->rtc.command = 0;
202						}
203						hw->rtc.bitsRead = 0;
204					}
205				}
206			} else {
207				hw->rtc.bitsRead = 0;
208				hw->rtc.bytesRemaining = 0;
209				hw->rtc.commandActive = 0;
210				hw->rtc.command = 0;
211				hw->rtc.transferStep = hw->pinState & 1;
212				_outputPins(hw, 1);
213			}
214		}
215		break;
216	}
217}
218
219void _rtcProcessByte(struct GBACartridgeHardware* hw) {
220	--hw->rtc.bytesRemaining;
221	if (!hw->rtc.commandActive) {
222		RTCCommandData command;
223		command = hw->rtc.bits;
224		if (RTCCommandDataGetMagic(command) == 0x06) {
225			hw->rtc.command = command;
226
227			hw->rtc.bytesRemaining = RTC_BYTES[RTCCommandDataGetCommand(command)];
228			hw->rtc.commandActive = hw->rtc.bytesRemaining > 0;
229			switch (RTCCommandDataGetCommand(command)) {
230			case RTC_RESET:
231				hw->rtc.control = 0;
232				break;
233			case RTC_DATETIME:
234			case RTC_TIME:
235				_rtcUpdateClock(hw);
236				break;
237			case RTC_FORCE_IRQ:
238			case RTC_CONTROL:
239				break;
240			}
241		} else {
242			mLOG(GBA_HW, WARN, "Invalid RTC command byte: %02X", hw->rtc.bits);
243		}
244	} else {
245		switch (RTCCommandDataGetCommand(hw->rtc.command)) {
246		case RTC_CONTROL:
247			hw->rtc.control = hw->rtc.bits;
248			break;
249		case RTC_FORCE_IRQ:
250			mLOG(GBA_HW, STUB, "Unimplemented RTC command %u", RTCCommandDataGetCommand(hw->rtc.command));
251			break;
252		case RTC_RESET:
253		case RTC_DATETIME:
254		case RTC_TIME:
255			break;
256		}
257	}
258
259	hw->rtc.bits = 0;
260	hw->rtc.bitsRead = 0;
261	if (!hw->rtc.bytesRemaining) {
262		hw->rtc.commandActive = 0;
263		hw->rtc.command = 0;
264	}
265}
266
267unsigned _rtcOutput(struct GBACartridgeHardware* hw) {
268	uint8_t outputByte = 0;
269	if (!hw->rtc.commandActive) {
270		mLOG(GBA_HW, GAME_ERROR, "Attempting to use RTC without an active command");
271		return 0;
272	}
273	switch (RTCCommandDataGetCommand(hw->rtc.command)) {
274	case RTC_CONTROL:
275		outputByte = hw->rtc.control;
276		break;
277	case RTC_DATETIME:
278	case RTC_TIME:
279		outputByte = hw->rtc.time[7 - hw->rtc.bytesRemaining];
280		break;
281	case RTC_FORCE_IRQ:
282	case RTC_RESET:
283		break;
284	}
285	unsigned output = (outputByte >> hw->rtc.bitsRead) & 1;
286	return output;
287}
288
289void _rtcUpdateClock(struct GBACartridgeHardware* hw) {
290	time_t t;
291	struct mRTCSource* rtc = hw->p->rtcSource;
292	if (rtc) {
293		if (rtc->sample) {
294			rtc->sample(rtc);
295		}
296		t = rtc->unixTime(rtc);
297	} else {
298		t = time(0);
299	}
300	struct tm date;
301	localtime_r(&t, &date);
302	hw->rtc.time[0] = _rtcBCD(date.tm_year - 100);
303	hw->rtc.time[1] = _rtcBCD(date.tm_mon + 1);
304	hw->rtc.time[2] = _rtcBCD(date.tm_mday);
305	hw->rtc.time[3] = _rtcBCD(date.tm_wday);
306	if (RTCControlIsHour24(hw->rtc.control)) {
307		hw->rtc.time[4] = _rtcBCD(date.tm_hour);
308	} else {
309		hw->rtc.time[4] = _rtcBCD(date.tm_hour % 12);
310	}
311	hw->rtc.time[5] = _rtcBCD(date.tm_min);
312	hw->rtc.time[6] = _rtcBCD(date.tm_sec);
313}
314
315unsigned _rtcBCD(unsigned value) {
316	int counter = value % 10;
317	value /= 10;
318	counter += (value % 10) << 4;
319	return counter;
320}
321
322time_t _rtcGenericCallback(struct mRTCSource* source) {
323	struct GBARTCGenericSource* rtc = (struct GBARTCGenericSource*) source;
324	switch (rtc->override) {
325	case RTC_NO_OVERRIDE:
326	default:
327		return time(0);
328	case RTC_FIXED:
329		return rtc->value;
330	case RTC_FAKE_EPOCH:
331		return rtc->value + rtc->p->video.frameCounter * (int64_t) VIDEO_TOTAL_LENGTH / GBA_ARM7TDMI_FREQUENCY;
332	}
333}
334
335void GBARTCGenericSourceInit(struct GBARTCGenericSource* rtc, struct GBA* gba) {
336	rtc->p = gba;
337	rtc->override = RTC_NO_OVERRIDE;
338	rtc->value = 0;
339	rtc->d.sample = 0;
340	rtc->d.unixTime = _rtcGenericCallback;
341}
342
343// == Gyro
344
345void GBAHardwareInitGyro(struct GBACartridgeHardware* hw) {
346	hw->devices |= HW_GYRO;
347	hw->gyroSample = 0;
348	hw->gyroEdge = 0;
349}
350
351void _gyroReadPins(struct GBACartridgeHardware* hw) {
352	struct mRotationSource* gyro = hw->p->rotationSource;
353	if (!gyro || !gyro->readGyroZ) {
354		return;
355	}
356
357	if (hw->pinState & 1) {
358		if (gyro->sample) {
359			gyro->sample(gyro);
360		}
361		int32_t sample = gyro->readGyroZ(gyro);
362
363		// Normalize to ~12 bits, focused on 0x6C0
364		hw->gyroSample = (sample >> 21) + 0x6C0; // Crop off an extra bit so that we can't go negative
365	}
366
367	if (hw->gyroEdge && !(hw->pinState & 2)) {
368		// Write bit on falling edge
369		unsigned bit = hw->gyroSample >> 15;
370		hw->gyroSample <<= 1;
371		_outputPins(hw, bit << 2);
372	}
373
374	hw->gyroEdge = !!(hw->pinState & 2);
375}
376
377// == Rumble
378
379void GBAHardwareInitRumble(struct GBACartridgeHardware* hw) {
380	hw->devices |= HW_RUMBLE;
381}
382
383void _rumbleReadPins(struct GBACartridgeHardware* hw) {
384	struct mRumble* rumble = hw->p->rumble;
385	if (!rumble) {
386		return;
387	}
388
389	rumble->setRumble(rumble, !!(hw->pinState & 8));
390}
391
392// == Light sensor
393
394void GBAHardwareInitLight(struct GBACartridgeHardware* hw) {
395	hw->devices |= HW_LIGHT_SENSOR;
396	hw->lightCounter = 0;
397	hw->lightEdge = false;
398	hw->lightSample = 0xFF;
399}
400
401void _lightReadPins(struct GBACartridgeHardware* hw) {
402	if (hw->pinState & 4) {
403		// Boktai chip select
404		return;
405	}
406	if (hw->pinState & 2) {
407		struct GBALuminanceSource* lux = hw->p->luminanceSource;
408		mLOG(GBA_HW, DEBUG, "[SOLAR] Got reset");
409		hw->lightCounter = 0;
410		if (lux) {
411			lux->sample(lux);
412			hw->lightSample = lux->readLuminance(lux);
413		} else {
414			hw->lightSample = 0xFF;
415		}
416	}
417	if ((hw->pinState & 1) && hw->lightEdge) {
418		++hw->lightCounter;
419	}
420	hw->lightEdge = !(hw->pinState & 1);
421
422	bool sendBit = hw->lightCounter >= hw->lightSample;
423	_outputPins(hw, sendBit << 3);
424	mLOG(GBA_HW, DEBUG, "[SOLAR] Output %u with pins %u", hw->lightCounter, hw->pinState);
425}
426
427// == Tilt
428
429void GBAHardwareInitTilt(struct GBACartridgeHardware* hw) {
430	hw->devices |= HW_TILT;
431	hw->tiltX = 0xFFF;
432	hw->tiltY = 0xFFF;
433	hw->tiltState = 0;
434}
435
436void GBAHardwareTiltWrite(struct GBACartridgeHardware* hw, uint32_t address, uint8_t value) {
437	switch (address) {
438	case 0x8000:
439		if (value == 0x55) {
440			hw->tiltState = 1;
441		} else {
442			mLOG(GBA_HW, GAME_ERROR, "Tilt sensor wrote wrong byte to %04x: %02x", address, value);
443		}
444		break;
445	case 0x8100:
446		if (value == 0xAA && hw->tiltState == 1) {
447			hw->tiltState = 0;
448			struct mRotationSource* rotationSource = hw->p->rotationSource;
449			if (!rotationSource || !rotationSource->readTiltX || !rotationSource->readTiltY) {
450				return;
451			}
452			if (rotationSource->sample) {
453				rotationSource->sample(rotationSource);
454			}
455			int32_t x = rotationSource->readTiltX(rotationSource);
456			int32_t y = rotationSource->readTiltY(rotationSource);
457			// Normalize to ~12 bits, focused on 0x3A0
458			hw->tiltX = (x >> 21) + 0x3A0; // Crop off an extra bit so that we can't go negative
459			hw->tiltY = (y >> 21) + 0x3A0;
460		} else {
461			mLOG(GBA_HW, GAME_ERROR, "Tilt sensor wrote wrong byte to %04x: %02x", address, value);
462		}
463		break;
464	default:
465		mLOG(GBA_HW, GAME_ERROR, "Invalid tilt sensor write to %04x: %02x", address, value);
466		break;
467	}
468}
469
470uint8_t GBAHardwareTiltRead(struct GBACartridgeHardware* hw, uint32_t address) {
471	switch (address) {
472	case 0x8200:
473		return hw->tiltX & 0xFF;
474	case 0x8300:
475		return ((hw->tiltX >> 8) & 0xF) | 0x80;
476	case 0x8400:
477		return hw->tiltY & 0xFF;
478	case 0x8500:
479		return (hw->tiltY >> 8) & 0xF;
480	default:
481		mLOG(GBA_HW, GAME_ERROR, "Invalid tilt sensor read from %04x", address);
482		break;
483	}
484	return 0xFF;
485}
486
487// == Game Boy Player
488
489static const uint16_t _logoPalette[] = {
490	0xFFDF, 0x640C, 0xE40C, 0xE42D, 0x644E, 0xE44E, 0xE46E, 0x68AF,
491	0xE8B0, 0x68D0, 0x68F0, 0x6911, 0xE911, 0x6D32, 0xED32, 0xED73,
492	0x6D93, 0xED94, 0x6DB4, 0xF1D5, 0x71F5, 0xF1F6, 0x7216, 0x7257,
493	0xF657, 0x7678, 0xF678, 0xF699, 0xF6B9, 0x76D9, 0xF6DA, 0x7B1B,
494	0xFB1B, 0xFB3C, 0x7B5C, 0x7B7D, 0xFF7D, 0x7F9D, 0x7FBE, 0x7FFF,
495	0x642D, 0x648E, 0xE88F, 0xE8F1, 0x6D52, 0x6D73, 0xF1B4, 0xF216,
496	0x7237, 0x7698, 0x7AFA, 0xFAFA, 0xFB5C, 0xFFBE, 0x7FDE, 0xFFFF,
497	0xFFFF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
498};
499
500static const uint32_t _logoHash = 0xEEDA6963;
501
502static const uint32_t _gbpTxData[] = {
503	0x0000494E, 0x0000494E,
504	0xB6B1494E, 0xB6B1544E,
505	0xABB1544E, 0xABB14E45,
506	0xB1BA4E45, 0xB1BA4F44,
507	0xB0BB4F44, 0xB0BB8002,
508	0x10000010, 0x20000013,
509	0x30000003
510};
511
512bool GBAHardwarePlayerCheckScreen(const struct GBAVideo* video) {
513	if (memcmp(video->palette, _logoPalette, sizeof(_logoPalette)) != 0) {
514		return false;
515	}
516	uint32_t hash = hash32(&video->renderer->vram[0x4000], 0x4000, 0);
517	return hash == _logoHash;
518}
519
520void GBAHardwarePlayerUpdate(struct GBA* gba) {
521	if (gba->memory.hw.devices & HW_GB_PLAYER) {
522		if (GBAHardwarePlayerCheckScreen(&gba->video)) {
523			++gba->memory.hw.gbpInputsPosted;
524			gba->memory.hw.gbpInputsPosted %= 3;
525			gba->keyCallback = &gba->memory.hw.gbpCallback.d;
526		} else {
527			// TODO: Save and restore
528			gba->keyCallback = 0;
529		}
530		gba->memory.hw.gbpTxPosition = 0;
531		return;
532	}
533	if (gba->keyCallback || gba->sio.drivers.normal) {
534		return;
535	}
536	if (GBAHardwarePlayerCheckScreen(&gba->video)) {
537		gba->memory.hw.devices |= HW_GB_PLAYER;
538		gba->memory.hw.gbpInputsPosted = 0;
539		gba->keyCallback = &gba->memory.hw.gbpCallback.d;
540		GBASIOSetDriver(&gba->sio, &gba->memory.hw.gbpDriver.d, SIO_NORMAL_32);
541	}
542}
543
544uint16_t _gbpRead(struct mKeyCallback* callback) {
545	struct GBAGBPKeyCallback* gbpCallback = (struct GBAGBPKeyCallback*) callback;
546	if (gbpCallback->p->gbpInputsPosted == 2) {
547		return 0xF0;
548	}
549	return 0;
550}
551
552uint16_t _gbpSioWriteRegister(struct GBASIODriver* driver, uint32_t address, uint16_t value) {
553	struct GBAGBPSIODriver* gbp = (struct GBAGBPSIODriver*) driver;
554	if (address == REG_SIOCNT) {
555		if (value & 0x0080) {
556			uint32_t rx = gbp->p->p->memory.io[REG_SIODATA32_LO >> 1] | (gbp->p->p->memory.io[REG_SIODATA32_HI >> 1] << 16);
557			if (gbp->p->gbpTxPosition < 12 && gbp->p->gbpTxPosition > 0) {
558				// TODO: Check expected
559			} else if (gbp->p->gbpTxPosition >= 12) {
560				uint32_t mask = 0x33;
561				// 0x00 = Stop
562				// 0x11 = Hard Stop
563				// 0x22 = Start
564				if (gbp->p->p->rumble) {
565					gbp->p->p->rumble->setRumble(gbp->p->p->rumble, (rx & mask) == 0x22);
566				}
567			}
568			mTimingDeschedule(&gbp->p->p->timing, &gbp->p->gbpNextEvent);
569			mTimingSchedule(&gbp->p->p->timing, &gbp->p->gbpNextEvent, 2048);
570		}
571		value &= 0x78FB;
572	}
573	return value;
574}
575
576void _gbpSioProcessEvents(struct mTiming* timing, void* user, uint32_t cyclesLate) {
577	UNUSED(timing);
578	UNUSED(cyclesLate);
579	struct GBAGBPSIODriver* gbp = user;
580	uint32_t tx = 0;
581	int txPosition = gbp->p->gbpTxPosition;
582	if (txPosition > 16) {
583		gbp->p->gbpTxPosition = 0;
584		txPosition = 0;
585	} else if (txPosition > 12) {
586		txPosition = 12;
587	}
588	tx = _gbpTxData[txPosition];
589	++gbp->p->gbpTxPosition;
590	gbp->p->p->memory.io[REG_SIODATA32_LO >> 1] = tx;
591	gbp->p->p->memory.io[REG_SIODATA32_HI >> 1] = tx >> 16;
592	if (GBASIONormalIsIrq(gbp->d.p->siocnt)) {
593		GBARaiseIRQ(gbp->p->p, IRQ_SIO, cyclesLate);
594	}
595	gbp->d.p->siocnt = GBASIONormalClearStart(gbp->d.p->siocnt);
596	gbp->p->p->memory.io[REG_SIOCNT >> 1] = gbp->d.p->siocnt & ~0x0080;
597}
598
599// == e-Reader
600
601void GBAHardwareInitEReader(struct GBACartridgeHardware* hw) {
602	hw->devices |= HW_EREADER;
603	_eReaderReset(hw);
604}
605
606void GBAHardwareEReaderWrite(struct GBACartridgeHardware* hw, uint32_t address, uint16_t value) {
607	address &= 0x700FF;
608	switch (address >> 17) {
609	case 0:
610		hw->eReaderRegisterUnk = value & 0xF;
611		break;
612	case 1:
613		hw->eReaderRegisterReset = (value & 0x8A) | 4;
614		if (value & 2) {
615			_eReaderReset(hw);
616		}
617		break;
618	case 2:
619		mLOG(GBA_HW, GAME_ERROR, "e-Reader write to read-only registers: %05X:%04X", address, value);
620		break;
621	default:
622		mLOG(GBA_HW, STUB, "Unimplemented e-Reader write: %05X:%04X", address, value);
623	}
624}
625
626void GBAHardwareEReaderWriteFlash(struct GBACartridgeHardware* hw, uint32_t address, uint8_t value) {
627	address &= 0xFFFF;
628	switch (address) {
629	case 0xFFB0:
630		_eReaderWriteControl0(hw, value);
631		break;
632	case 0xFFB1:
633		_eReaderWriteControl1(hw, value);
634		break;
635	default:
636		mLOG(GBA_HW, STUB, "Unimplemented e-Reader write to flash: %04X:%02X", address, value);
637	}
638}
639
640uint16_t GBAHardwareEReaderRead(struct GBACartridgeHardware* hw, uint32_t address) {
641	address &= 0x700FF;
642	switch (address >> 17) {
643	case 0:
644		return hw->eReaderRegisterUnk;
645	case 1:
646		return hw->eReaderRegisterReset;
647	case 2:
648		if (address > 0x40088) {
649			return 0;
650		}
651		return hw->eReaderData[(address & 0xFE) >> 1];
652	}
653	mLOG(GBA_HW, STUB, "Unimplemented e-Reader read: %05X", address);
654	return 0;
655}
656
657uint8_t GBAHardwareEReaderReadFlash(struct GBACartridgeHardware* hw, uint32_t address) {
658	address &= 0xFFFF;
659	switch (address) {
660	case 0xFFB0:
661		return hw->eReaderRegisterControl0;
662	case 0xFFB1:
663		return hw->eReaderRegisterControl1;
664	default:
665		mLOG(GBA_HW, STUB, "Unimplemented e-Reader read from flash: %04X", address);
666		return 0;
667	}
668}
669
670void GBAHardwareEReaderScan(struct GBACartridgeHardware* hw, struct GBAEReaderDataSource* source) {
671	if (!EReaderControl0IsScan(hw->eReaderRegisterControl0)) {
672		return;
673	}
674	hw->eReaderSource = source;
675	_eReaderReadData(hw);
676}
677
678void _eReaderReset(struct GBACartridgeHardware* hw) {
679	memset(hw->eReaderData, 0, sizeof(hw->eReaderData));
680	hw->eReaderRegisterUnk = 0;
681	hw->eReaderRegisterReset = 4;
682	hw->eReaderRegisterControl0 = 0;
683	hw->eReaderRegisterControl1 = 0x80;
684	hw->eReaderRegisterLed = 0;
685	hw->eReaderState = 0;
686	hw->eReaderActiveRegister = 0;
687}
688
689void _eReaderWriteControl0(struct GBACartridgeHardware* hw, uint8_t value) {
690	EReaderControl0 control = value & 0x7F;
691	EReaderControl0 oldControl = hw->eReaderRegisterControl0;
692	if (hw->eReaderState == EREADER_SERIAL_INACTIVE) {
693		if (EReaderControl0IsClock(oldControl) && EReaderControl0IsData(oldControl) && !EReaderControl0IsData(control)) {
694			hw->eReaderState = EREADER_SERIAL_STARTING;
695		}
696	} else if (EReaderControl0IsClock(oldControl) && !EReaderControl0IsData(oldControl) && EReaderControl0IsData(control)) {
697		hw->eReaderState = EREADER_SERIAL_INACTIVE;
698
699	} else if (hw->eReaderState == EREADER_SERIAL_STARTING) {
700		if (EReaderControl0IsClock(oldControl) && !EReaderControl0IsData(oldControl) && !EReaderControl0IsClock(control)) {
701			hw->eReaderState = EREADER_SERIAL_BIT_0;
702			hw->eReaderCommand = EREADER_COMMAND_IDLE;
703		}
704	} else if (EReaderControl0IsClock(oldControl) && !EReaderControl0IsClock(control)) {
705		mLOG(GBA_HW, DEBUG, "[e-Reader] Serial falling edge: %c %i", EReaderControl0IsDirection(control) ? '>' : '<', EReaderControl0GetData(control));
706		// TODO: Improve direction control
707		if (EReaderControl0IsDirection(control)) {
708			hw->eReaderByte |= EReaderControl0GetData(control) << (7 - (hw->eReaderState - EREADER_SERIAL_BIT_0));
709			++hw->eReaderState;
710			if (hw->eReaderState == EREADER_SERIAL_END_BIT) {
711				mLOG(GBA_HW, DEBUG, "[e-Reader] Wrote serial byte: %02x", hw->eReaderByte);
712				switch (hw->eReaderCommand) {
713				case EREADER_COMMAND_IDLE:
714					hw->eReaderCommand = hw->eReaderByte;
715					break;
716				case EREADER_COMMAND_SET_INDEX:
717					hw->eReaderActiveRegister = hw->eReaderByte;
718					hw->eReaderCommand = EREADER_COMMAND_WRITE_DATA;
719					break;
720				case EREADER_COMMAND_WRITE_DATA:
721					switch (hw->eReaderActiveRegister & 0x7F) {
722					case 0:
723					case 0x57:
724					case 0x58:
725					case 0x59:
726					case 0x5A:
727						// Read-only
728						mLOG(GBA_HW, GAME_ERROR, "Writing to read-only e-Reader serial register: %02X", hw->eReaderActiveRegister);
729						break;
730					default:
731						if ((hw->eReaderActiveRegister & 0x7F) > 0x5A) {
732							mLOG(GBA_HW, GAME_ERROR, "Writing to non-existent e-Reader serial register: %02X", hw->eReaderActiveRegister);
733							break;
734						}
735						hw->eReaderSerial[hw->eReaderActiveRegister & 0x7F] = hw->eReaderByte;
736						break;
737					}
738					++hw->eReaderActiveRegister;
739					break;
740				default:
741					mLOG(GBA_HW, ERROR, "Hit undefined state %02X in e-Reader state machine", hw->eReaderCommand);
742					break;
743				}
744				hw->eReaderState = EREADER_SERIAL_BIT_0;
745				hw->eReaderByte = 0;
746			}
747		} else if (hw->eReaderCommand == EREADER_COMMAND_READ_DATA) {
748			int bit = hw->eReaderSerial[hw->eReaderActiveRegister & 0x7F] >> (7 - (hw->eReaderState - EREADER_SERIAL_BIT_0));
749			control = EReaderControl0SetData(control, bit);
750			++hw->eReaderState;
751			if (hw->eReaderState == EREADER_SERIAL_END_BIT) {
752				++hw->eReaderActiveRegister;
753				mLOG(GBA_HW, DEBUG, "[e-Reader] Read serial byte: %02x", hw->eReaderSerial[hw->eReaderActiveRegister & 0x7F]);
754			}
755		}
756		hw->eReaderDelay = 0;
757	} else if (!EReaderControl0IsDirection(control)) {
758		// Clear the error bit
759		control = EReaderControl0ClearData(control);
760	}
761	hw->eReaderRegisterControl0 = control;
762	if (!EReaderControl0IsScan(oldControl) && EReaderControl0IsScan(control)) {
763		_eReaderReadData(hw);
764	} else if (EReaderControl0IsLedEnable(control) && EReaderControl1IsScanline(hw->eReaderRegisterControl1)) {
765		GBARaiseIRQ(hw->p, IRQ_GAMEPAK, 0);
766	}
767	mLOG(GBA_HW, STUB, "Unimplemented e-Reader Control0 write: %02X", value);
768}
769
770void _eReaderWriteControl1(struct GBACartridgeHardware* hw, uint8_t value) {
771	EReaderControl1 control = (value & 0x32) | 0x80;
772	hw->eReaderRegisterControl1 = control;
773	if (EReaderControl0IsScan(hw->eReaderRegisterControl0) && !EReaderControl1IsScanline(control)) {
774		_eReaderReadData(hw);
775	}
776	mLOG(GBA_HW, STUB, "Unimplemented e-Reader Control1 write: %02X", value);
777}
778
779void _eReaderReadData(struct GBACartridgeHardware* hw) {
780	memset(hw->eReaderData, 0xFF, EREADER_BLOCK_SIZE);
781	if (hw->eReaderSource) {
782		hw->eReaderSource->readBlock(hw->eReaderSource, hw->eReaderData);
783	}
784	hw->eReaderRegisterControl1 = EReaderControl1FillScanline(hw->eReaderRegisterControl1);
785	if (EReaderControl0IsLedEnable(hw->eReaderRegisterControl0)) {
786		GBARaiseIRQ(hw->p, IRQ_GAMEPAK, -2754);
787	}
788}
789
790// == Serialization
791
792void GBAHardwareSerialize(const struct GBACartridgeHardware* hw, struct GBASerializedState* state) {
793	GBASerializedHWFlags1 flags1 = 0;
794	GBASerializedHWFlags2 flags2 = 0;
795	flags1 = GBASerializedHWFlags1SetReadWrite(flags1, hw->readWrite);
796	STORE_16(hw->pinState, 0, &state->hw.pinState);
797	STORE_16(hw->direction, 0, &state->hw.pinDirection);
798	state->hw.devices = hw->devices;
799
800	STORE_32(hw->rtc.bytesRemaining, 0, &state->hw.rtc.bytesRemaining);
801	STORE_32(hw->rtc.transferStep, 0, &state->hw.rtc.transferStep);
802	STORE_32(hw->rtc.bitsRead, 0, &state->hw.rtc.bitsRead);
803	STORE_32(hw->rtc.bits, 0, &state->hw.rtc.bits);
804	STORE_32(hw->rtc.commandActive, 0, &state->hw.rtc.commandActive);
805	STORE_32(hw->rtc.command, 0, &state->hw.rtc.command);
806	STORE_32(hw->rtc.control, 0, &state->hw.rtc.control);
807	memcpy(state->hw.rtc.time, hw->rtc.time, sizeof(state->hw.rtc.time));
808
809	STORE_16(hw->gyroSample, 0, &state->hw.gyroSample);
810	flags1 = GBASerializedHWFlags1SetGyroEdge(flags1, hw->gyroEdge);
811	STORE_16(hw->tiltX, 0, &state->hw.tiltSampleX);
812	STORE_16(hw->tiltY, 0, &state->hw.tiltSampleY);
813	flags2 = GBASerializedHWFlags2SetTiltState(flags2, hw->tiltState);
814	flags2 = GBASerializedHWFlags1SetLightCounter(flags2, hw->lightCounter);
815	state->hw.lightSample = hw->lightSample;
816	flags1 = GBASerializedHWFlags1SetLightEdge(flags1, hw->lightEdge);
817	flags2 = GBASerializedHWFlags2SetGbpInputsPosted(flags2, hw->gbpInputsPosted);
818	flags2 = GBASerializedHWFlags2SetGbpTxPosition(flags2, hw->gbpTxPosition);
819	STORE_32(hw->gbpNextEvent.when - mTimingCurrentTime(&hw->p->timing), 0, &state->hw.gbpNextEvent);
820	STORE_16(flags1, 0, &state->hw.flags1);
821	state->hw.flags2 = flags2;
822}
823
824void GBAHardwareDeserialize(struct GBACartridgeHardware* hw, const struct GBASerializedState* state) {
825	GBASerializedHWFlags1 flags1;
826	LOAD_16(flags1, 0, &state->hw.flags1);
827	hw->readWrite = GBASerializedHWFlags1GetReadWrite(flags1);
828	LOAD_16(hw->pinState, 0, &state->hw.pinState);
829	LOAD_16(hw->direction, 0, &state->hw.pinDirection);
830	hw->devices = state->hw.devices;
831
832	LOAD_32(hw->rtc.bytesRemaining, 0, &state->hw.rtc.bytesRemaining);
833	LOAD_32(hw->rtc.transferStep, 0, &state->hw.rtc.transferStep);
834	LOAD_32(hw->rtc.bitsRead, 0, &state->hw.rtc.bitsRead);
835	LOAD_32(hw->rtc.bits, 0, &state->hw.rtc.bits);
836	LOAD_32(hw->rtc.commandActive, 0, &state->hw.rtc.commandActive);
837	LOAD_32(hw->rtc.command, 0, &state->hw.rtc.command);
838	LOAD_32(hw->rtc.control, 0, &state->hw.rtc.control);
839	memcpy(hw->rtc.time, state->hw.rtc.time, sizeof(hw->rtc.time));
840
841	LOAD_16(hw->gyroSample, 0, &state->hw.gyroSample);
842	hw->gyroEdge = GBASerializedHWFlags1GetGyroEdge(flags1);
843	LOAD_16(hw->tiltX, 0, &state->hw.tiltSampleX);
844	LOAD_16(hw->tiltY, 0, &state->hw.tiltSampleY);
845	hw->tiltState = GBASerializedHWFlags2GetTiltState(state->hw.flags2);
846	hw->lightCounter = GBASerializedHWFlags1GetLightCounter(flags1);
847	hw->lightSample = state->hw.lightSample;
848	hw->lightEdge = GBASerializedHWFlags1GetLightEdge(flags1);
849	hw->gbpInputsPosted = GBASerializedHWFlags2GetGbpInputsPosted(state->hw.flags2);
850	hw->gbpTxPosition = GBASerializedHWFlags2GetGbpTxPosition(state->hw.flags2);
851
852	uint32_t when;
853	LOAD_32(when, 0, &state->hw.gbpNextEvent);
854	if (hw->devices & HW_GB_PLAYER) {
855		GBASIOSetDriver(&hw->p->sio, &hw->gbpDriver.d, SIO_NORMAL_32);
856		if (hw->p->memory.io[REG_SIOCNT >> 1] & 0x0080) {
857			mTimingSchedule(&hw->p->timing, &hw->gbpNextEvent, when);
858		}
859	}
860}