all repos — mgba @ 4b5efa2365db0eaf537b6ba8ff70e588f4213cc3

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 = false;
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	++hw->eReaderDelay;
693	// Huge hack to prevent having to do cycle counting for the delay
694	// This is the timing the e-Reader uses
695	if (hw->eReaderDelay > 6) {
696		// Timed out
697		hw->eReaderState = EREADER_SERIAL_INACTIVE;
698	}
699	if (hw->eReaderState == EREADER_SERIAL_INACTIVE) {
700		if (EReaderControl0IsClock(oldControl) && EReaderControl0IsData(oldControl) && !EReaderControl0IsData(control)) {
701			hw->eReaderState = EREADER_SERIAL_STARTING;
702			hw->eReaderDelay = 0;
703		}
704	} else if (hw->eReaderState == EREADER_SERIAL_STARTING) {
705		if (EReaderControl0IsClock(oldControl) && !EReaderControl0IsData(oldControl) && !EReaderControl0IsClock(control)) {
706			hw->eReaderState = EREADER_SERIAL_BIT_0;
707			hw->eReaderCommand = EREADER_COMMAND_IDLE;
708			hw->eReaderDelay = 0;
709		}
710	} else if (EReaderControl0IsClock(oldControl) && !EReaderControl0IsClock(control)) {
711		mLOG(GBA_HW, DEBUG, "[e-Reader] Serial falling edge: %c %i", EReaderControl0IsDirection(control) ? '>' : '<', EReaderControl0GetData(control));
712		// TODO: Improve direction control
713		if (hw->eReaderState == EREADER_SERIAL_BIT_0 && hw->eReaderDelay > 5) {
714			// This is 4 for an actual write, and 6 an SioBegin delay
715			hw->eReaderCommand = EREADER_COMMAND_IDLE;
716		} else if (EReaderControl0IsDirection(control)) {
717			hw->eReaderByte |= EReaderControl0GetData(control) << (7 - (hw->eReaderState - EREADER_SERIAL_BIT_0));
718			++hw->eReaderState;
719			if (hw->eReaderState == EREADER_SERIAL_END_BIT) {
720				mLOG(GBA_HW, DEBUG, "[e-Reader] Wrote serial byte: %02x", hw->eReaderByte);
721				switch (hw->eReaderCommand) {
722				case EREADER_COMMAND_IDLE:
723					hw->eReaderCommand = hw->eReaderByte;
724					break;
725				case EREADER_COMMAND_SET_INDEX:
726					hw->eReaderActiveRegister = hw->eReaderByte;
727					hw->eReaderCommand = EREADER_COMMAND_WRITE_DATA;
728					break;
729				case EREADER_COMMAND_WRITE_DATA:
730					switch (hw->eReaderActiveRegister & 0x7F) {
731					case 0:
732					case 0x57:
733					case 0x58:
734					case 0x59:
735					case 0x5A:
736						// Read-only
737						mLOG(GBA_HW, GAME_ERROR, "Writing to read-only e-Reader serial register: %02X", hw->eReaderActiveRegister);
738						break;
739					default:
740						if ((hw->eReaderActiveRegister & 0x7F) > 0x5A) {
741							mLOG(GBA_HW, GAME_ERROR, "Writing to non-existent e-Reader serial register: %02X", hw->eReaderActiveRegister);
742							break;
743						}
744						hw->eReaderSerial[hw->eReaderActiveRegister & 0x7F] = hw->eReaderByte;
745						break;
746					}
747					++hw->eReaderActiveRegister;
748					break;
749				default:
750					mLOG(GBA_HW, ERROR, "Hit undefined state in e-Reader state machine");
751					break;
752				}
753				hw->eReaderState = EREADER_SERIAL_BIT_0;
754				hw->eReaderByte = 0;
755			}
756		} else if (hw->eReaderCommand == EREADER_COMMAND_READ_DATA) {
757			int bit = hw->eReaderSerial[hw->eReaderActiveRegister & 0x7F] >> (7 - (hw->eReaderState - EREADER_SERIAL_BIT_0));
758			control = EReaderControl0SetData(control, bit);
759			++hw->eReaderState;
760			if (hw->eReaderState == EREADER_SERIAL_END_BIT) {
761				++hw->eReaderActiveRegister;
762				mLOG(GBA_HW, DEBUG, "[e-Reader] Read serial byte: %02x", hw->eReaderSerial[hw->eReaderActiveRegister & 0x7F]);
763			}
764		}
765		hw->eReaderDelay = 0;
766	} else if (!EReaderControl0IsDirection(control)) {
767		// Clear the error bit
768		control = EReaderControl0ClearData(control);
769	}
770	hw->eReaderRegisterControl0 = control;
771	if (!EReaderControl0IsScan(oldControl) && EReaderControl0IsScan(control)) {
772		_eReaderReadData(hw);
773	}
774	mLOG(GBA_HW, STUB, "Unimplemented e-Reader Control0 write: %02X", value);
775}
776
777void _eReaderWriteControl1(struct GBACartridgeHardware* hw, uint8_t value) {
778	EReaderControl1 control = (value & 0x32) | 0x80;
779	hw->eReaderRegisterControl1 = control;
780	if (EReaderControl0IsScan(hw->eReaderRegisterControl0) && !EReaderControl1IsScanline(control)) {
781		_eReaderReadData(hw);
782	}
783	mLOG(GBA_HW, STUB, "Unimplemented e-Reader Control1 write: %02X", value);
784}
785
786void _eReaderReadData(struct GBACartridgeHardware* hw) {
787	if (!hw->eReaderSource) {
788		return;
789	}
790	memset(hw->eReaderData, 0, EREADER_BLOCK_SIZE);
791	hw->eReaderSource->readBlock(hw->eReaderSource, hw->eReaderData);
792	hw->eReaderRegisterControl1 = EReaderControl1FillScanline(hw->eReaderRegisterControl1);
793	if (EReaderControl0IsLedEnable(hw->eReaderRegisterControl0)) {
794		GBARaiseIRQ(hw->p, IRQ_GAMEPAK, 0);
795	}
796}
797
798// == Serialization
799
800void GBAHardwareSerialize(const struct GBACartridgeHardware* hw, struct GBASerializedState* state) {
801	GBASerializedHWFlags1 flags1 = 0;
802	GBASerializedHWFlags2 flags2 = 0;
803	flags1 = GBASerializedHWFlags1SetReadWrite(flags1, hw->readWrite);
804	STORE_16(hw->pinState, 0, &state->hw.pinState);
805	STORE_16(hw->direction, 0, &state->hw.pinDirection);
806	state->hw.devices = hw->devices;
807
808	STORE_32(hw->rtc.bytesRemaining, 0, &state->hw.rtc.bytesRemaining);
809	STORE_32(hw->rtc.transferStep, 0, &state->hw.rtc.transferStep);
810	STORE_32(hw->rtc.bitsRead, 0, &state->hw.rtc.bitsRead);
811	STORE_32(hw->rtc.bits, 0, &state->hw.rtc.bits);
812	STORE_32(hw->rtc.commandActive, 0, &state->hw.rtc.commandActive);
813	STORE_32(hw->rtc.command, 0, &state->hw.rtc.command);
814	STORE_32(hw->rtc.control, 0, &state->hw.rtc.control);
815	memcpy(state->hw.rtc.time, hw->rtc.time, sizeof(state->hw.rtc.time));
816
817	STORE_16(hw->gyroSample, 0, &state->hw.gyroSample);
818	flags1 = GBASerializedHWFlags1SetGyroEdge(flags1, hw->gyroEdge);
819	STORE_16(hw->tiltX, 0, &state->hw.tiltSampleX);
820	STORE_16(hw->tiltY, 0, &state->hw.tiltSampleY);
821	flags2 = GBASerializedHWFlags2SetTiltState(flags2, hw->tiltState);
822	flags2 = GBASerializedHWFlags1SetLightCounter(flags2, hw->lightCounter);
823	state->hw.lightSample = hw->lightSample;
824	flags1 = GBASerializedHWFlags1SetLightEdge(flags1, hw->lightEdge);
825	flags2 = GBASerializedHWFlags2SetGbpInputsPosted(flags2, hw->gbpInputsPosted);
826	flags2 = GBASerializedHWFlags2SetGbpTxPosition(flags2, hw->gbpTxPosition);
827	STORE_32(hw->gbpNextEvent.when - mTimingCurrentTime(&hw->p->timing), 0, &state->hw.gbpNextEvent);
828	STORE_16(flags1, 0, &state->hw.flags1);
829	state->hw.flags2 = flags2;
830}
831
832void GBAHardwareDeserialize(struct GBACartridgeHardware* hw, const struct GBASerializedState* state) {
833	GBASerializedHWFlags1 flags1;
834	LOAD_16(flags1, 0, &state->hw.flags1);
835	hw->readWrite = GBASerializedHWFlags1GetReadWrite(flags1);
836	LOAD_16(hw->pinState, 0, &state->hw.pinState);
837	LOAD_16(hw->direction, 0, &state->hw.pinDirection);
838	hw->devices = state->hw.devices;
839
840	LOAD_32(hw->rtc.bytesRemaining, 0, &state->hw.rtc.bytesRemaining);
841	LOAD_32(hw->rtc.transferStep, 0, &state->hw.rtc.transferStep);
842	LOAD_32(hw->rtc.bitsRead, 0, &state->hw.rtc.bitsRead);
843	LOAD_32(hw->rtc.bits, 0, &state->hw.rtc.bits);
844	LOAD_32(hw->rtc.commandActive, 0, &state->hw.rtc.commandActive);
845	LOAD_32(hw->rtc.command, 0, &state->hw.rtc.command);
846	LOAD_32(hw->rtc.control, 0, &state->hw.rtc.control);
847	memcpy(hw->rtc.time, state->hw.rtc.time, sizeof(hw->rtc.time));
848
849	LOAD_16(hw->gyroSample, 0, &state->hw.gyroSample);
850	hw->gyroEdge = GBASerializedHWFlags1GetGyroEdge(flags1);
851	LOAD_16(hw->tiltX, 0, &state->hw.tiltSampleX);
852	LOAD_16(hw->tiltY, 0, &state->hw.tiltSampleY);
853	hw->tiltState = GBASerializedHWFlags2GetTiltState(state->hw.flags2);
854	hw->lightCounter = GBASerializedHWFlags1GetLightCounter(flags1);
855	hw->lightSample = state->hw.lightSample;
856	hw->lightEdge = GBASerializedHWFlags1GetLightEdge(flags1);
857	hw->gbpInputsPosted = GBASerializedHWFlags2GetGbpInputsPosted(state->hw.flags2);
858	hw->gbpTxPosition = GBASerializedHWFlags2GetGbpTxPosition(state->hw.flags2);
859
860	uint32_t when;
861	LOAD_32(when, 0, &state->hw.gbpNextEvent);
862	if (hw->devices & HW_GB_PLAYER) {
863		GBASIOSetDriver(&hw->p->sio, &hw->gbpDriver.d, SIO_NORMAL_32);
864		if (hw->p->memory.io[REG_SIOCNT >> 1] & 0x0080) {
865			mTimingSchedule(&hw->p->timing, &hw->gbpNextEvent, when);
866		}
867	}
868}