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}