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}