all repos — mgba @ 2e43210eac6e6b798180d480cd3c876939b840fb

mGBA Game Boy Advance Emulator

src/gba/hardware.c (view raw)

  1/* Copyright (c) 2013-2015 Jeffrey Pfau
  2 *
  3 * This Source Code Form is subject to the terms of the Mozilla Public
  4 * License, v. 2.0. If a copy of the MPL was not distributed with this
  5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  6#include "hardware.h"
  7
  8#include "gba/serialize.h"
  9#include "util/hash.h"
 10
 11#ifdef PSP2
 12#include <psp2/rtc.h>
 13#endif
 14
 15static void _readPins(struct GBACartridgeHardware* hw);
 16static void _outputPins(struct GBACartridgeHardware* hw, unsigned pins);
 17
 18static void _rtcReadPins(struct GBACartridgeHardware* hw);
 19static unsigned _rtcOutput(struct GBACartridgeHardware* hw);
 20static void _rtcProcessByte(struct GBACartridgeHardware* hw);
 21static void _rtcUpdateClock(struct GBACartridgeHardware* hw);
 22static unsigned _rtcBCD(unsigned value);
 23
 24static time_t _rtcGenericCallback(struct GBARTCSource* source);
 25
 26static void _gyroReadPins(struct GBACartridgeHardware* hw);
 27
 28static void _rumbleReadPins(struct GBACartridgeHardware* hw);
 29
 30static void _lightReadPins(struct GBACartridgeHardware* hw);
 31
 32static const int RTC_BYTES[8] = {
 33	0, // Force reset
 34	0, // Empty
 35	7, // Date/Time
 36	0, // Force IRQ
 37	1, // Control register
 38	0, // Empty
 39	3, // Time
 40	0 // Empty
 41};
 42
 43void GBAHardwareInit(struct GBACartridgeHardware* hw, uint16_t* base) {
 44	hw->gpioBase = base;
 45	GBAHardwareClear(hw);
 46}
 47
 48void GBAHardwareClear(struct GBACartridgeHardware* hw) {
 49	hw->devices = HW_NONE;
 50	hw->direction = GPIO_WRITE_ONLY;
 51	hw->pinState = 0;
 52	hw->direction = 0;
 53}
 54
 55void GBAHardwareGPIOWrite(struct GBACartridgeHardware* hw, uint32_t address, uint16_t value) {
 56	switch (address) {
 57	case GPIO_REG_DATA:
 58		hw->pinState &= ~hw->direction;
 59		hw->pinState |= value;
 60		_readPins(hw);
 61		break;
 62	case GPIO_REG_DIRECTION:
 63		hw->direction = value;
 64		break;
 65	case GPIO_REG_CONTROL:
 66		hw->readWrite = value;
 67		break;
 68	default:
 69		GBALog(hw->p, GBA_LOG_WARN, "Invalid GPIO address");
 70	}
 71	if (hw->readWrite) {
 72		uint16_t old = hw->gpioBase[0];
 73		old &= ~hw->direction;
 74		hw->gpioBase[0] = old | hw->pinState;
 75	} else {
 76		hw->gpioBase[0] = 0;
 77	}
 78}
 79
 80void GBAHardwareInitRTC(struct GBACartridgeHardware* hw) {
 81	hw->devices |= HW_RTC;
 82	hw->rtc.bytesRemaining = 0;
 83
 84	hw->rtc.transferStep = 0;
 85
 86	hw->rtc.bitsRead = 0;
 87	hw->rtc.bits = 0;
 88	hw->rtc.commandActive = 0;
 89	hw->rtc.command = 0;
 90	hw->rtc.control = 0x40;
 91	memset(hw->rtc.time, 0, sizeof(hw->rtc.time));
 92}
 93
 94void _readPins(struct GBACartridgeHardware* hw) {
 95	if (hw->devices & HW_RTC) {
 96		_rtcReadPins(hw);
 97	}
 98
 99	if (hw->devices & HW_GYRO) {
100		_gyroReadPins(hw);
101	}
102
103	if (hw->devices & HW_RUMBLE) {
104		_rumbleReadPins(hw);
105	}
106
107	if (hw->devices & HW_LIGHT_SENSOR) {
108		_lightReadPins(hw);
109	}
110}
111
112void _outputPins(struct GBACartridgeHardware* hw, unsigned pins) {
113	if (hw->readWrite) {
114		uint16_t old = hw->gpioBase[0];
115		old &= hw->direction;
116		hw->pinState = old | (pins & ~hw->direction & 0xF);
117		hw->gpioBase[0] = hw->pinState;
118	}
119}
120
121// == RTC
122
123void _rtcReadPins(struct GBACartridgeHardware* hw) {
124	// Transfer sequence:
125	// P: 0 | 1 |  2 | 3
126	// == Initiate
127	// > HI | - | LO | -
128	// > HI | - | HI | -
129	// == Transfer bit (x8)
130	// > LO | x | HI | -
131	// > HI | - | HI | -
132	// < ?? | x | ?? | -
133	// == Terminate
134	// >  - | - | LO | -
135	switch (hw->rtc.transferStep) {
136	case 0:
137		if ((hw->pinState & 5) == 1) {
138			hw->rtc.transferStep = 1;
139		}
140		break;
141	case 1:
142		if ((hw->pinState & 5) == 5) {
143			hw->rtc.transferStep = 2;
144		}
145		break;
146	case 2:
147		if (!(hw->pinState & 1)) {
148			hw->rtc.bits &= ~(1 << hw->rtc.bitsRead);
149			hw->rtc.bits |= ((hw->pinState & 2) >> 1) << hw->rtc.bitsRead;
150		} else {
151			if (hw->pinState & 4) {
152				// GPIO direction should always != reading
153				if (hw->direction & 2) {
154					if (RTCCommandDataIsReading(hw->rtc.command)) {
155						GBALog(hw->p, GBA_LOG_GAME_ERROR, "Attempting to write to RTC while in read mode");
156					}
157					++hw->rtc.bitsRead;
158					if (hw->rtc.bitsRead == 8) {
159						_rtcProcessByte(hw);
160					}
161				} else {
162					_outputPins(hw, 5 | (_rtcOutput(hw) << 1));
163					++hw->rtc.bitsRead;
164					if (hw->rtc.bitsRead == 8) {
165						--hw->rtc.bytesRemaining;
166						if (hw->rtc.bytesRemaining <= 0) {
167							hw->rtc.commandActive = 0;
168							hw->rtc.command = RTCCommandDataClearReading(hw->rtc.command);
169						}
170						hw->rtc.bitsRead = 0;
171					}
172				}
173			} else {
174				hw->rtc.bitsRead = 0;
175				hw->rtc.bytesRemaining = 0;
176				hw->rtc.commandActive = 0;
177				hw->rtc.command = RTCCommandDataClearReading(hw->rtc.command);
178				hw->rtc.transferStep = 0;
179			}
180		}
181		break;
182	}
183}
184
185void _rtcProcessByte(struct GBACartridgeHardware* hw) {
186	--hw->rtc.bytesRemaining;
187	if (!hw->rtc.commandActive) {
188		RTCCommandData command;
189		command = hw->rtc.bits;
190		if (RTCCommandDataGetMagic(command) == 0x06) {
191			hw->rtc.command = command;
192
193			hw->rtc.bytesRemaining = RTC_BYTES[RTCCommandDataGetCommand(command)];
194			hw->rtc.commandActive = hw->rtc.bytesRemaining > 0;
195			switch (RTCCommandDataGetCommand(command)) {
196			case RTC_RESET:
197				hw->rtc.control = 0;
198				break;
199			case RTC_DATETIME:
200			case RTC_TIME:
201				_rtcUpdateClock(hw);
202				break;
203			case RTC_FORCE_IRQ:
204			case RTC_CONTROL:
205				break;
206			}
207		} else {
208			GBALog(hw->p, GBA_LOG_WARN, "Invalid RTC command byte: %02X", hw->rtc.bits);
209		}
210	} else {
211		switch (RTCCommandDataGetCommand(hw->rtc.command)) {
212		case RTC_CONTROL:
213			hw->rtc.control = hw->rtc.bits;
214			break;
215		case RTC_FORCE_IRQ:
216			GBALog(hw->p, GBA_LOG_STUB, "Unimplemented RTC command %u", RTCCommandDataGetCommand(hw->rtc.command));
217			break;
218		case RTC_RESET:
219		case RTC_DATETIME:
220		case RTC_TIME:
221			break;
222		}
223	}
224
225	hw->rtc.bits = 0;
226	hw->rtc.bitsRead = 0;
227	if (!hw->rtc.bytesRemaining) {
228		hw->rtc.commandActive = 0;
229		hw->rtc.command = RTCCommandDataClearReading(hw->rtc.command);
230	}
231}
232
233unsigned _rtcOutput(struct GBACartridgeHardware* hw) {
234	uint8_t outputByte = 0;
235	switch (RTCCommandDataGetCommand(hw->rtc.command)) {
236	case RTC_CONTROL:
237		outputByte = hw->rtc.control;
238		break;
239	case RTC_DATETIME:
240	case RTC_TIME:
241		outputByte = hw->rtc.time[7 - hw->rtc.bytesRemaining];
242		break;
243	case RTC_FORCE_IRQ:
244	case RTC_RESET:
245		break;
246	}
247	unsigned output = (outputByte >> hw->rtc.bitsRead) & 1;
248	return output;
249}
250
251void _rtcUpdateClock(struct GBACartridgeHardware* hw) {
252	time_t t;
253	struct GBARTCSource* rtc = hw->p->rtcSource;
254	if (rtc) {
255		if (rtc->sample) {
256			rtc->sample(rtc);
257		}
258		t = rtc->unixTime(rtc);
259	} else {
260		t = time(0);
261	}
262	struct tm date;
263#ifdef _WIN32
264	date = *localtime(&t);
265#elif defined(PSP2)
266	SceRtcTime scertc;
267	sceRtcGetCurrentClockLocalTime(&scertc);
268	sceRtcGetTime_t(&scertc, &t);
269#else
270	localtime_r(&t, &date);
271#endif
272	hw->rtc.time[0] = _rtcBCD(date.tm_year - 100);
273	hw->rtc.time[1] = _rtcBCD(date.tm_mon + 1);
274	hw->rtc.time[2] = _rtcBCD(date.tm_mday);
275	hw->rtc.time[3] = _rtcBCD(date.tm_wday);
276	if (RTCControlIsHour24(hw->rtc.control)) {
277		hw->rtc.time[4] = _rtcBCD(date.tm_hour);
278	} else {
279		hw->rtc.time[4] = _rtcBCD(date.tm_hour % 12);
280	}
281	hw->rtc.time[5] = _rtcBCD(date.tm_min);
282	hw->rtc.time[6] = _rtcBCD(date.tm_sec);
283}
284
285unsigned _rtcBCD(unsigned value) {
286	int counter = value % 10;
287	value /= 10;
288	counter += (value % 10) << 4;
289	return counter;
290}
291
292time_t _rtcGenericCallback(struct GBARTCSource* source) {
293	struct GBARTCGenericSource* rtc = (struct GBARTCGenericSource*) source;
294	switch (rtc->override) {
295	case RTC_NO_OVERRIDE:
296	default:
297		return time(0);
298	case RTC_FIXED:
299		return rtc->value;
300	case RTC_FAKE_EPOCH:
301		return rtc->value + rtc->p->video.frameCounter * (int64_t) VIDEO_TOTAL_LENGTH / GBA_ARM7TDMI_FREQUENCY;
302	}
303}
304
305void GBARTCGenericSourceInit(struct GBARTCGenericSource* rtc, struct GBA* gba) {
306	rtc->p = gba;
307	rtc->override = RTC_NO_OVERRIDE;
308	rtc->value = 0;
309	rtc->d.sample = 0;
310	rtc->d.unixTime = _rtcGenericCallback;
311}
312
313// == Gyro
314
315void GBAHardwareInitGyro(struct GBACartridgeHardware* hw) {
316	hw->devices |= HW_GYRO;
317	hw->gyroSample = 0;
318	hw->gyroEdge = 0;
319}
320
321void _gyroReadPins(struct GBACartridgeHardware* hw) {
322	struct GBARotationSource* gyro = hw->p->rotationSource;
323	if (!gyro || !gyro->readGyroZ) {
324		return;
325	}
326
327	if (hw->pinState & 1) {
328		if (gyro->sample) {
329			gyro->sample(gyro);
330		}
331		int32_t sample = gyro->readGyroZ(gyro);
332
333		// Normalize to ~12 bits, focused on 0x6C0
334		hw->gyroSample = (sample >> 21) + 0x6C0; // Crop off an extra bit so that we can't go negative
335	}
336
337	if (hw->gyroEdge && !(hw->pinState & 2)) {
338		// Write bit on falling edge
339		unsigned bit = hw->gyroSample >> 15;
340		hw->gyroSample <<= 1;
341		_outputPins(hw, bit << 2);
342	}
343
344	hw->gyroEdge = !!(hw->pinState & 2);
345}
346
347// == Rumble
348
349void GBAHardwareInitRumble(struct GBACartridgeHardware* hw) {
350	hw->devices |= HW_RUMBLE;
351}
352
353void _rumbleReadPins(struct GBACartridgeHardware* hw) {
354	struct GBARumble* rumble = hw->p->rumble;
355	if (!rumble) {
356		return;
357	}
358
359	rumble->setRumble(rumble, !!(hw->pinState & 8));
360}
361
362// == Light sensor
363
364void GBAHardwareInitLight(struct GBACartridgeHardware* hw) {
365	hw->devices |= HW_LIGHT_SENSOR;
366	hw->lightCounter = 0;
367	hw->lightEdge = false;
368	hw->lightSample = 0xFF;
369}
370
371void _lightReadPins(struct GBACartridgeHardware* hw) {
372	if (hw->pinState & 4) {
373		// Boktai chip select
374		return;
375	}
376	if (hw->pinState & 2) {
377		struct GBALuminanceSource* lux = hw->p->luminanceSource;
378		GBALog(hw->p, GBA_LOG_DEBUG, "[SOLAR] Got reset");
379		hw->lightCounter = 0;
380		if (lux) {
381			lux->sample(lux);
382			hw->lightSample = lux->readLuminance(lux);
383		} else {
384			hw->lightSample = 0xFF;
385		}
386	}
387	if ((hw->pinState & 1) && hw->lightEdge) {
388		++hw->lightCounter;
389	}
390	hw->lightEdge = !(hw->pinState & 1);
391
392	bool sendBit = hw->lightCounter >= hw->lightSample;
393	_outputPins(hw, sendBit << 3);
394	GBALog(hw->p, GBA_LOG_DEBUG, "[SOLAR] Output %u with pins %u", hw->lightCounter, hw->pinState);
395}
396
397// == Tilt
398
399void GBAHardwareInitTilt(struct GBACartridgeHardware* hw) {
400	hw->devices |= HW_TILT;
401	hw->tiltX = 0xFFF;
402	hw->tiltY = 0xFFF;
403	hw->tiltState = 0;
404}
405
406void GBAHardwareTiltWrite(struct GBACartridgeHardware* hw, uint32_t address, uint8_t value) {
407	switch (address) {
408	case 0x8000:
409		if (value == 0x55) {
410			hw->tiltState = 1;
411		} else {
412			GBALog(hw->p, GBA_LOG_GAME_ERROR, "Tilt sensor wrote wrong byte to %04x: %02x", address, value);
413		}
414		break;
415	case 0x8100:
416		if (value == 0xAA && hw->tiltState == 1) {
417			hw->tiltState = 0;
418			struct GBARotationSource* rotationSource = hw->p->rotationSource;
419			if (!rotationSource || !rotationSource->readTiltX || !rotationSource->readTiltY) {
420				return;
421			}
422			if (rotationSource->sample) {
423				rotationSource->sample(rotationSource);
424			}
425			int32_t x = rotationSource->readTiltX(rotationSource);
426			int32_t y = rotationSource->readTiltY(rotationSource);
427			// Normalize to ~12 bits, focused on 0x3A0
428			hw->tiltX = (x >> 21) + 0x3A0; // Crop off an extra bit so that we can't go negative
429			hw->tiltY = (y >> 21) + 0x3A0;
430		} else {
431			GBALog(hw->p, GBA_LOG_GAME_ERROR, "Tilt sensor wrote wrong byte to %04x: %02x", address, value);
432		}
433		break;
434	default:
435		GBALog(hw->p, GBA_LOG_GAME_ERROR, "Invalid tilt sensor write to %04x: %02x", address, value);
436		break;
437	}
438}
439
440uint8_t GBAHardwareTiltRead(struct GBACartridgeHardware* hw, uint32_t address) {
441	switch (address) {
442	case 0x8200:
443		return hw->tiltX & 0xFF;
444	case 0x8300:
445		return ((hw->tiltX >> 8) & 0xF) | 0x80;
446	case 0x8400:
447		return hw->tiltY & 0xFF;
448	case 0x8500:
449		return (hw->tiltY >> 8) & 0xF;
450	default:
451		GBALog(hw->p, GBA_LOG_GAME_ERROR, "Invalid tilt sensor read from %04x", address);
452		break;
453	}
454	return 0xFF;
455}
456
457// == Game Boy Player
458
459static const uint16_t _logoPalette[] = {
460	0xFFDF, 0x640C, 0xE40C, 0xE42D, 0x644E, 0xE44E, 0xE46E, 0x68AF,
461	0xE8B0, 0x68D0, 0x68F0, 0x6911, 0xE911, 0x6D32, 0xED32, 0xED73,
462	0x6D93, 0xED94, 0x6DB4, 0xF1D5, 0x71F5, 0xF1F6, 0x7216, 0x7257,
463	0xF657, 0x7678, 0xF678, 0xF699, 0xF6B9, 0x76D9, 0xF6DA, 0x7B1B,
464	0xFB1B, 0xFB3C, 0x7B5C, 0x7B7D, 0xFF7D, 0x7F9D, 0x7FBE, 0x7FFF,
465	0x642D, 0x648E, 0xE88F, 0xE8F1, 0x6D52, 0x6D73, 0xF1B4, 0xF216,
466	0x7237, 0x7698, 0x7AFA, 0xFAFA, 0xFB5C, 0xFFBE, 0x7FDE, 0xFFFF,
467	0xFFFF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
468};
469
470static const uint32_t _logoHash = 0xEEDA6963;
471
472bool GBAHardwarePlayerCheckScreen(const struct GBAVideo* video) {
473	if (memcmp(video->palette, _logoPalette, sizeof(_logoPalette)) != 0) {
474		return false;
475	}
476	uint32_t hash = hash32(&video->renderer->vram[0x4000], 0x4000, 0);
477	return hash == _logoHash;
478}
479
480// == Serialization
481
482void GBAHardwareSerialize(const struct GBACartridgeHardware* hw, struct GBASerializedState* state) {
483	state->hw.readWrite = hw->readWrite;
484	state->hw.pinState = hw->pinState;
485	state->hw.pinDirection = hw->direction;
486	state->hw.devices = hw->devices;
487	state->hw.rtc = hw->rtc;
488	state->hw.gyroSample = hw->gyroSample;
489	state->hw.gyroEdge = hw->gyroEdge;
490	state->hw.tiltSampleX = hw->tiltX;
491	state->hw.tiltSampleY = hw->tiltY;
492	state->hw.tiltState = hw->tiltState;
493	state->hw.lightCounter = hw->lightCounter;
494	state->hw.lightSample = hw->lightSample;
495	state->hw.lightEdge = hw->lightEdge;
496}
497
498void GBAHardwareDeserialize(struct GBACartridgeHardware* hw, const struct GBASerializedState* state) {
499	hw->readWrite = state->hw.readWrite;
500	hw->pinState = state->hw.pinState;
501	hw->direction = state->hw.pinDirection;
502	hw->rtc = state->hw.rtc;
503	hw->gyroSample = state->hw.gyroSample;
504	hw->gyroEdge = state->hw.gyroEdge;
505	hw->tiltX = state->hw.tiltSampleX;
506	hw->tiltY = state->hw.tiltSampleY;
507	hw->tiltState = state->hw.tiltState;
508	hw->lightCounter = state->hw.lightCounter;
509	hw->lightSample = state->hw.lightSample;
510	hw->lightEdge = state->hw.lightEdge;
511}