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#include <mgba-util/memory.h>
14
15mLOG_DEFINE_CATEGORY(GBA_HW, "GBA Pak Hardware", "gba.hardware");
16
17MGBA_EXPORT const int GBA_LUX_LEVELS[10] = { 5, 11, 18, 27, 42, 62, 84, 109, 139, 183 };
18
19static void _readPins(struct GBACartridgeHardware* hw);
20static void _outputPins(struct GBACartridgeHardware* hw, unsigned pins);
21
22static void _rtcReadPins(struct GBACartridgeHardware* hw);
23static unsigned _rtcOutput(struct GBACartridgeHardware* hw);
24static void _rtcProcessByte(struct GBACartridgeHardware* hw);
25static void _rtcUpdateClock(struct GBACartridgeHardware* hw);
26static unsigned _rtcBCD(unsigned value);
27
28static time_t _rtcGenericCallback(struct mRTCSource* source);
29
30static void _gyroReadPins(struct GBACartridgeHardware* hw);
31
32static void _rumbleReadPins(struct GBACartridgeHardware* hw);
33
34static void _lightReadPins(struct GBACartridgeHardware* hw);
35
36static uint16_t _gbpRead(struct mKeyCallback*);
37static uint16_t _gbpSioWriteRegister(struct GBASIODriver* driver, uint32_t address, uint16_t value);
38static void _gbpSioProcessEvents(struct mTiming* timing, void* user, uint32_t cyclesLate);
39
40static const int RTC_BYTES[8] = {
41 0, // Force reset
42 0, // Empty
43 7, // Date/Time
44 0, // Force IRQ
45 1, // Control register
46 0, // Empty
47 3, // Time
48 0 // Empty
49};
50
51void GBAHardwareInit(struct GBACartridgeHardware* hw, uint16_t* base) {
52 hw->gpioBase = base;
53 hw->eReaderDots = NULL;
54 memset(hw->eReaderCards, 0, sizeof(hw->eReaderCards));
55 GBAHardwareClear(hw);
56
57 hw->gbpCallback.d.readKeys = _gbpRead;
58 hw->gbpCallback.p = hw;
59 hw->gbpDriver.d.init = 0;
60 hw->gbpDriver.d.deinit = 0;
61 hw->gbpDriver.d.load = 0;
62 hw->gbpDriver.d.unload = 0;
63 hw->gbpDriver.d.writeRegister = _gbpSioWriteRegister;
64 hw->gbpDriver.p = hw;
65 hw->gbpNextEvent.context = &hw->gbpDriver;
66 hw->gbpNextEvent.name = "GBA SIO Game Boy Player";
67 hw->gbpNextEvent.callback = _gbpSioProcessEvents;
68 hw->gbpNextEvent.priority = 0x80;
69}
70
71void GBAHardwareClear(struct GBACartridgeHardware* hw) {
72 hw->devices = HW_NONE | (hw->devices & HW_GB_PLAYER_DETECTION);
73 hw->readWrite = GPIO_WRITE_ONLY;
74 hw->pinState = 0;
75 hw->direction = 0;
76
77 if (hw->eReaderDots) {
78 mappedMemoryFree(hw->eReaderDots, EREADER_DOTCODE_SIZE);
79 hw->eReaderDots = NULL;
80 }
81 int i;
82 for (i = 0; i < EREADER_CARDS_MAX; ++i) {
83 if (!hw->eReaderCards[i].data) {
84 continue;
85 }
86 free(hw->eReaderCards[i].data);
87 hw->eReaderCards[i].data = NULL;
88 hw->eReaderCards[i].size = 0;
89 }
90
91 if (hw->p->sio.drivers.normal == &hw->gbpDriver.d) {
92 GBASIOSetDriver(&hw->p->sio, 0, SIO_NORMAL_32);
93 }
94}
95
96void GBAHardwareGPIOWrite(struct GBACartridgeHardware* hw, uint32_t address, uint16_t value) {
97 if (!hw->gpioBase) {
98 return;
99 }
100 switch (address) {
101 case GPIO_REG_DATA:
102 hw->pinState &= ~hw->direction;
103 hw->pinState |= value & hw->direction;
104 _readPins(hw);
105 break;
106 case GPIO_REG_DIRECTION:
107 hw->direction = value;
108 break;
109 case GPIO_REG_CONTROL:
110 hw->readWrite = value;
111 break;
112 default:
113 mLOG(GBA_HW, WARN, "Invalid GPIO address");
114 }
115 if (hw->readWrite) {
116 STORE_16(hw->pinState, 0, hw->gpioBase);
117 STORE_16(hw->direction, 2, hw->gpioBase);
118 STORE_16(hw->readWrite, 4, hw->gpioBase);
119 } else {
120 hw->gpioBase[0] = 0;
121 hw->gpioBase[1] = 0;
122 hw->gpioBase[2] = 0;
123 }
124}
125
126void GBAHardwareInitRTC(struct GBACartridgeHardware* hw) {
127 hw->devices |= HW_RTC;
128 hw->rtc.bytesRemaining = 0;
129
130 hw->rtc.transferStep = 0;
131
132 hw->rtc.bitsRead = 0;
133 hw->rtc.bits = 0;
134 hw->rtc.commandActive = 0;
135 hw->rtc.command = 0;
136 hw->rtc.control = 0x40;
137 memset(hw->rtc.time, 0, sizeof(hw->rtc.time));
138}
139
140void _readPins(struct GBACartridgeHardware* hw) {
141 if (hw->devices & HW_RTC) {
142 _rtcReadPins(hw);
143 }
144
145 if (hw->devices & HW_GYRO) {
146 _gyroReadPins(hw);
147 }
148
149 if (hw->devices & HW_RUMBLE) {
150 _rumbleReadPins(hw);
151 }
152
153 if (hw->devices & HW_LIGHT_SENSOR) {
154 _lightReadPins(hw);
155 }
156}
157
158void _outputPins(struct GBACartridgeHardware* hw, unsigned pins) {
159 if (hw->readWrite) {
160 uint16_t old;
161 LOAD_16(old, 0, hw->gpioBase);
162 old &= hw->direction;
163 hw->pinState = old | (pins & ~hw->direction & 0xF);
164 STORE_16(hw->pinState, 0, hw->gpioBase);
165 }
166}
167
168// == RTC
169
170void _rtcReadPins(struct GBACartridgeHardware* hw) {
171 // Transfer sequence:
172 // P: 0 | 1 | 2 | 3
173 // == Initiate
174 // > HI | - | LO | -
175 // > HI | - | HI | -
176 // == Transfer bit (x8)
177 // > LO | x | HI | -
178 // > HI | - | HI | -
179 // < ?? | x | ?? | -
180 // == Terminate
181 // > - | - | LO | -
182 switch (hw->rtc.transferStep) {
183 case 0:
184 if ((hw->pinState & 5) == 1) {
185 hw->rtc.transferStep = 1;
186 }
187 break;
188 case 1:
189 if ((hw->pinState & 5) == 5) {
190 hw->rtc.transferStep = 2;
191 } else if ((hw->pinState & 5) != 1) {
192 hw->rtc.transferStep = 0;
193 }
194 break;
195 case 2:
196 if (!(hw->pinState & 1)) {
197 hw->rtc.bits &= ~(1 << hw->rtc.bitsRead);
198 hw->rtc.bits |= ((hw->pinState & 2) >> 1) << hw->rtc.bitsRead;
199 } else {
200 if (hw->pinState & 4) {
201 if (!RTCCommandDataIsReading(hw->rtc.command)) {
202 ++hw->rtc.bitsRead;
203 if (hw->rtc.bitsRead == 8) {
204 _rtcProcessByte(hw);
205 }
206 } else {
207 _outputPins(hw, 5 | (_rtcOutput(hw) << 1));
208 ++hw->rtc.bitsRead;
209 if (hw->rtc.bitsRead == 8) {
210 --hw->rtc.bytesRemaining;
211 if (hw->rtc.bytesRemaining <= 0) {
212 hw->rtc.commandActive = 0;
213 hw->rtc.command = 0;
214 }
215 hw->rtc.bitsRead = 0;
216 }
217 }
218 } else {
219 hw->rtc.bitsRead = 0;
220 hw->rtc.bytesRemaining = 0;
221 hw->rtc.commandActive = 0;
222 hw->rtc.command = 0;
223 hw->rtc.transferStep = hw->pinState & 1;
224 _outputPins(hw, 1);
225 }
226 }
227 break;
228 }
229}
230
231void _rtcProcessByte(struct GBACartridgeHardware* hw) {
232 --hw->rtc.bytesRemaining;
233 if (!hw->rtc.commandActive) {
234 RTCCommandData command;
235 command = hw->rtc.bits;
236 if (RTCCommandDataGetMagic(command) == 0x06) {
237 hw->rtc.command = command;
238
239 hw->rtc.bytesRemaining = RTC_BYTES[RTCCommandDataGetCommand(command)];
240 hw->rtc.commandActive = hw->rtc.bytesRemaining > 0;
241 mLOG(GBA_HW, DEBUG, "Got RTC command %x", RTCCommandDataGetCommand(command));
242 switch (RTCCommandDataGetCommand(command)) {
243 case RTC_RESET:
244 hw->rtc.control = 0;
245 break;
246 case RTC_DATETIME:
247 case RTC_TIME:
248 _rtcUpdateClock(hw);
249 break;
250 case RTC_FORCE_IRQ:
251 case RTC_CONTROL:
252 break;
253 }
254 } else {
255 mLOG(GBA_HW, WARN, "Invalid RTC command byte: %02X", hw->rtc.bits);
256 }
257 } else {
258 switch (RTCCommandDataGetCommand(hw->rtc.command)) {
259 case RTC_CONTROL:
260 hw->rtc.control = hw->rtc.bits;
261 break;
262 case RTC_FORCE_IRQ:
263 mLOG(GBA_HW, STUB, "Unimplemented RTC command %u", RTCCommandDataGetCommand(hw->rtc.command));
264 break;
265 case RTC_RESET:
266 case RTC_DATETIME:
267 case RTC_TIME:
268 break;
269 }
270 }
271
272 hw->rtc.bits = 0;
273 hw->rtc.bitsRead = 0;
274 if (!hw->rtc.bytesRemaining) {
275 hw->rtc.commandActive = 0;
276 hw->rtc.command = 0;
277 }
278}
279
280unsigned _rtcOutput(struct GBACartridgeHardware* hw) {
281 uint8_t outputByte = 0;
282 if (!hw->rtc.commandActive) {
283 mLOG(GBA_HW, GAME_ERROR, "Attempting to use RTC without an active command");
284 return 0;
285 }
286 switch (RTCCommandDataGetCommand(hw->rtc.command)) {
287 case RTC_CONTROL:
288 outputByte = hw->rtc.control;
289 break;
290 case RTC_DATETIME:
291 case RTC_TIME:
292 outputByte = hw->rtc.time[7 - hw->rtc.bytesRemaining];
293 break;
294 case RTC_FORCE_IRQ:
295 case RTC_RESET:
296 break;
297 }
298 unsigned output = (outputByte >> hw->rtc.bitsRead) & 1;
299 if (hw->rtc.bitsRead == 0) {
300 mLOG(GBA_HW, DEBUG, "RTC output byte %02X", outputByte);
301 }
302 return output;
303}
304
305void _rtcUpdateClock(struct GBACartridgeHardware* hw) {
306 time_t t;
307 struct mRTCSource* rtc = hw->p->rtcSource;
308 if (rtc) {
309 if (rtc->sample) {
310 rtc->sample(rtc);
311 }
312 t = rtc->unixTime(rtc);
313 } else {
314 t = time(0);
315 }
316 struct tm date;
317 localtime_r(&t, &date);
318 hw->rtc.time[0] = _rtcBCD(date.tm_year - 100);
319 hw->rtc.time[1] = _rtcBCD(date.tm_mon + 1);
320 hw->rtc.time[2] = _rtcBCD(date.tm_mday);
321 hw->rtc.time[3] = _rtcBCD(date.tm_wday);
322 if (RTCControlIsHour24(hw->rtc.control)) {
323 hw->rtc.time[4] = _rtcBCD(date.tm_hour);
324 } else {
325 hw->rtc.time[4] = _rtcBCD(date.tm_hour % 12);
326 }
327 hw->rtc.time[5] = _rtcBCD(date.tm_min);
328 hw->rtc.time[6] = _rtcBCD(date.tm_sec);
329}
330
331unsigned _rtcBCD(unsigned value) {
332 int counter = value % 10;
333 value /= 10;
334 counter += (value % 10) << 4;
335 return counter;
336}
337
338time_t _rtcGenericCallback(struct mRTCSource* source) {
339 struct GBARTCGenericSource* rtc = (struct GBARTCGenericSource*) source;
340 switch (rtc->override) {
341 case RTC_NO_OVERRIDE:
342 default:
343 return time(0);
344 case RTC_FIXED:
345 return rtc->value;
346 case RTC_FAKE_EPOCH:
347 return rtc->value + rtc->p->video.frameCounter * (int64_t) VIDEO_TOTAL_LENGTH / GBA_ARM7TDMI_FREQUENCY;
348 }
349}
350
351void GBARTCGenericSourceInit(struct GBARTCGenericSource* rtc, struct GBA* gba) {
352 rtc->p = gba;
353 rtc->override = RTC_NO_OVERRIDE;
354 rtc->value = 0;
355 rtc->d.sample = 0;
356 rtc->d.unixTime = _rtcGenericCallback;
357}
358
359// == Gyro
360
361void GBAHardwareInitGyro(struct GBACartridgeHardware* hw) {
362 hw->devices |= HW_GYRO;
363 hw->gyroSample = 0;
364 hw->gyroEdge = 0;
365}
366
367void _gyroReadPins(struct GBACartridgeHardware* hw) {
368 struct mRotationSource* gyro = hw->p->rotationSource;
369 if (!gyro || !gyro->readGyroZ) {
370 return;
371 }
372
373 if (hw->pinState & 1) {
374 if (gyro->sample) {
375 gyro->sample(gyro);
376 }
377 int32_t sample = gyro->readGyroZ(gyro);
378
379 // Normalize to ~12 bits, focused on 0x6C0
380 hw->gyroSample = (sample >> 21) + 0x6C0; // Crop off an extra bit so that we can't go negative
381 }
382
383 if (hw->gyroEdge && !(hw->pinState & 2)) {
384 // Write bit on falling edge
385 unsigned bit = hw->gyroSample >> 15;
386 hw->gyroSample <<= 1;
387 _outputPins(hw, bit << 2);
388 }
389
390 hw->gyroEdge = !!(hw->pinState & 2);
391}
392
393// == Rumble
394
395void GBAHardwareInitRumble(struct GBACartridgeHardware* hw) {
396 hw->devices |= HW_RUMBLE;
397}
398
399void _rumbleReadPins(struct GBACartridgeHardware* hw) {
400 struct mRumble* rumble = hw->p->rumble;
401 if (!rumble) {
402 return;
403 }
404
405 rumble->setRumble(rumble, !!(hw->pinState & 8));
406}
407
408// == Light sensor
409
410void GBAHardwareInitLight(struct GBACartridgeHardware* hw) {
411 hw->devices |= HW_LIGHT_SENSOR;
412 hw->lightCounter = 0;
413 hw->lightEdge = false;
414 hw->lightSample = 0xFF;
415}
416
417void _lightReadPins(struct GBACartridgeHardware* hw) {
418 if (hw->pinState & 4) {
419 // Boktai chip select
420 return;
421 }
422 if (hw->pinState & 2) {
423 struct GBALuminanceSource* lux = hw->p->luminanceSource;
424 mLOG(GBA_HW, DEBUG, "[SOLAR] Got reset");
425 hw->lightCounter = 0;
426 if (lux) {
427 lux->sample(lux);
428 hw->lightSample = lux->readLuminance(lux);
429 } else {
430 hw->lightSample = 0xFF;
431 }
432 }
433 if ((hw->pinState & 1) && hw->lightEdge) {
434 ++hw->lightCounter;
435 }
436 hw->lightEdge = !(hw->pinState & 1);
437
438 bool sendBit = hw->lightCounter >= hw->lightSample;
439 _outputPins(hw, sendBit << 3);
440 mLOG(GBA_HW, DEBUG, "[SOLAR] Output %u with pins %u", hw->lightCounter, hw->pinState);
441}
442
443// == Tilt
444
445void GBAHardwareInitTilt(struct GBACartridgeHardware* hw) {
446 hw->devices |= HW_TILT;
447 hw->tiltX = 0xFFF;
448 hw->tiltY = 0xFFF;
449 hw->tiltState = 0;
450}
451
452void GBAHardwareTiltWrite(struct GBACartridgeHardware* hw, uint32_t address, uint8_t value) {
453 switch (address) {
454 case 0x8000:
455 if (value == 0x55) {
456 hw->tiltState = 1;
457 } else {
458 mLOG(GBA_HW, GAME_ERROR, "Tilt sensor wrote wrong byte to %04x: %02x", address, value);
459 }
460 break;
461 case 0x8100:
462 if (value == 0xAA && hw->tiltState == 1) {
463 hw->tiltState = 0;
464 struct mRotationSource* rotationSource = hw->p->rotationSource;
465 if (!rotationSource || !rotationSource->readTiltX || !rotationSource->readTiltY) {
466 return;
467 }
468 if (rotationSource->sample) {
469 rotationSource->sample(rotationSource);
470 }
471 int32_t x = rotationSource->readTiltX(rotationSource);
472 int32_t y = rotationSource->readTiltY(rotationSource);
473 // Normalize to ~12 bits, focused on 0x3A0
474 hw->tiltX = (x >> 21) + 0x3A0; // Crop off an extra bit so that we can't go negative
475 hw->tiltY = (y >> 21) + 0x3A0;
476 } else {
477 mLOG(GBA_HW, GAME_ERROR, "Tilt sensor wrote wrong byte to %04x: %02x", address, value);
478 }
479 break;
480 default:
481 mLOG(GBA_HW, GAME_ERROR, "Invalid tilt sensor write to %04x: %02x", address, value);
482 break;
483 }
484}
485
486uint8_t GBAHardwareTiltRead(struct GBACartridgeHardware* hw, uint32_t address) {
487 switch (address) {
488 case 0x8200:
489 return hw->tiltX & 0xFF;
490 case 0x8300:
491 return ((hw->tiltX >> 8) & 0xF) | 0x80;
492 case 0x8400:
493 return hw->tiltY & 0xFF;
494 case 0x8500:
495 return (hw->tiltY >> 8) & 0xF;
496 default:
497 mLOG(GBA_HW, GAME_ERROR, "Invalid tilt sensor read from %04x", address);
498 break;
499 }
500 return 0xFF;
501}
502
503// == Game Boy Player
504
505static const uint8_t _logoPalette[] = {
506 0xDF, 0xFF, 0x0C, 0x64, 0x0C, 0xE4, 0x2D, 0xE4, 0x4E, 0x64, 0x4E, 0xE4, 0x6E, 0xE4, 0xAF, 0x68,
507 0xB0, 0xE8, 0xD0, 0x68, 0xF0, 0x68, 0x11, 0x69, 0x11, 0xE9, 0x32, 0x6D, 0x32, 0xED, 0x73, 0xED,
508 0x93, 0x6D, 0x94, 0xED, 0xB4, 0x6D, 0xD5, 0xF1, 0xF5, 0x71, 0xF6, 0xF1, 0x16, 0x72, 0x57, 0x72,
509 0x57, 0xF6, 0x78, 0x76, 0x78, 0xF6, 0x99, 0xF6, 0xB9, 0xF6, 0xD9, 0x76, 0xDA, 0xF6, 0x1B, 0x7B,
510 0x1B, 0xFB, 0x3C, 0xFB, 0x5C, 0x7B, 0x7D, 0x7B, 0x7D, 0xFF, 0x9D, 0x7F, 0xBE, 0x7F, 0xFF, 0x7F,
511 0x2D, 0x64, 0x8E, 0x64, 0x8F, 0xE8, 0xF1, 0xE8, 0x52, 0x6D, 0x73, 0x6D, 0xB4, 0xF1, 0x16, 0xF2,
512 0x37, 0x72, 0x98, 0x76, 0xFA, 0x7A, 0xFA, 0xFA, 0x5C, 0xFB, 0xBE, 0xFF, 0xDE, 0x7F, 0xFF, 0xFF,
513 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
514};
515
516static const uint32_t _logoHash = 0xEEDA6963;
517
518static const uint32_t _gbpTxData[] = {
519 0x0000494E, 0x0000494E,
520 0xB6B1494E, 0xB6B1544E,
521 0xABB1544E, 0xABB14E45,
522 0xB1BA4E45, 0xB1BA4F44,
523 0xB0BB4F44, 0xB0BB8002,
524 0x10000010, 0x20000013,
525 0x30000003
526};
527
528bool GBAHardwarePlayerCheckScreen(const struct GBAVideo* video) {
529 if (memcmp(video->palette, _logoPalette, sizeof(_logoPalette)) != 0) {
530 return false;
531 }
532 uint32_t hash = hash32(&video->renderer->vram[0x4000], 0x4000, 0);
533 return hash == _logoHash;
534}
535
536void GBAHardwarePlayerUpdate(struct GBA* gba) {
537 if (gba->memory.hw.devices & HW_GB_PLAYER) {
538 if (GBAHardwarePlayerCheckScreen(&gba->video)) {
539 ++gba->memory.hw.gbpInputsPosted;
540 gba->memory.hw.gbpInputsPosted %= 3;
541 gba->keyCallback = &gba->memory.hw.gbpCallback.d;
542 } else {
543 // TODO: Save and restore
544 gba->keyCallback = 0;
545 }
546 gba->memory.hw.gbpTxPosition = 0;
547 return;
548 }
549 if (gba->keyCallback || gba->sio.drivers.normal) {
550 return;
551 }
552 if (GBAHardwarePlayerCheckScreen(&gba->video)) {
553 gba->memory.hw.devices |= HW_GB_PLAYER;
554 gba->memory.hw.gbpInputsPosted = 0;
555 gba->keyCallback = &gba->memory.hw.gbpCallback.d;
556 GBASIOSetDriver(&gba->sio, &gba->memory.hw.gbpDriver.d, SIO_NORMAL_32);
557 }
558}
559
560uint16_t _gbpRead(struct mKeyCallback* callback) {
561 struct GBAGBPKeyCallback* gbpCallback = (struct GBAGBPKeyCallback*) callback;
562 if (gbpCallback->p->gbpInputsPosted == 2) {
563 return 0xF0;
564 }
565 return 0;
566}
567
568uint16_t _gbpSioWriteRegister(struct GBASIODriver* driver, uint32_t address, uint16_t value) {
569 struct GBAGBPSIODriver* gbp = (struct GBAGBPSIODriver*) driver;
570 if (address == REG_SIOCNT) {
571 if (value & 0x0080) {
572 uint32_t rx = gbp->p->p->memory.io[REG_SIODATA32_LO >> 1] | (gbp->p->p->memory.io[REG_SIODATA32_HI >> 1] << 16);
573 if (gbp->p->gbpTxPosition < 12 && gbp->p->gbpTxPosition > 0) {
574 // TODO: Check expected
575 } else if (gbp->p->gbpTxPosition >= 12) {
576 uint32_t mask = 0x33;
577 // 0x00 = Stop
578 // 0x11 = Hard Stop
579 // 0x22 = Start
580 if (gbp->p->p->rumble) {
581 gbp->p->p->rumble->setRumble(gbp->p->p->rumble, (rx & mask) == 0x22);
582 }
583 }
584 mTimingDeschedule(&gbp->p->p->timing, &gbp->p->gbpNextEvent);
585 mTimingSchedule(&gbp->p->p->timing, &gbp->p->gbpNextEvent, 2048);
586 }
587 value &= 0x78FB;
588 }
589 return value;
590}
591
592void _gbpSioProcessEvents(struct mTiming* timing, void* user, uint32_t cyclesLate) {
593 UNUSED(timing);
594 UNUSED(cyclesLate);
595 struct GBAGBPSIODriver* gbp = user;
596 uint32_t tx = 0;
597 int txPosition = gbp->p->gbpTxPosition;
598 if (txPosition > 16) {
599 gbp->p->gbpTxPosition = 0;
600 txPosition = 0;
601 } else if (txPosition > 12) {
602 txPosition = 12;
603 }
604 tx = _gbpTxData[txPosition];
605 ++gbp->p->gbpTxPosition;
606 gbp->p->p->memory.io[REG_SIODATA32_LO >> 1] = tx;
607 gbp->p->p->memory.io[REG_SIODATA32_HI >> 1] = tx >> 16;
608 if (GBASIONormalIsIrq(gbp->d.p->siocnt)) {
609 GBARaiseIRQ(gbp->p->p, IRQ_SIO, cyclesLate);
610 }
611 gbp->d.p->siocnt = GBASIONormalClearStart(gbp->d.p->siocnt);
612 gbp->p->p->memory.io[REG_SIOCNT >> 1] = gbp->d.p->siocnt & ~0x0080;
613}
614
615// == Serialization
616
617void GBAHardwareSerialize(const struct GBACartridgeHardware* hw, struct GBASerializedState* state) {
618 GBASerializedHWFlags1 flags1 = 0;
619 GBASerializedHWFlags2 flags2 = 0;
620 flags1 = GBASerializedHWFlags1SetReadWrite(flags1, hw->readWrite);
621 STORE_16(hw->pinState, 0, &state->hw.pinState);
622 STORE_16(hw->direction, 0, &state->hw.pinDirection);
623 state->hw.devices = hw->devices;
624
625 STORE_32(hw->rtc.bytesRemaining, 0, &state->hw.rtc.bytesRemaining);
626 STORE_32(hw->rtc.transferStep, 0, &state->hw.rtc.transferStep);
627 STORE_32(hw->rtc.bitsRead, 0, &state->hw.rtc.bitsRead);
628 STORE_32(hw->rtc.bits, 0, &state->hw.rtc.bits);
629 STORE_32(hw->rtc.commandActive, 0, &state->hw.rtc.commandActive);
630 STORE_32(hw->rtc.command, 0, &state->hw.rtc.command);
631 STORE_32(hw->rtc.control, 0, &state->hw.rtc.control);
632 memcpy(state->hw.rtc.time, hw->rtc.time, sizeof(state->hw.rtc.time));
633
634 STORE_16(hw->gyroSample, 0, &state->hw.gyroSample);
635 flags1 = GBASerializedHWFlags1SetGyroEdge(flags1, hw->gyroEdge);
636 STORE_16(hw->tiltX, 0, &state->hw.tiltSampleX);
637 STORE_16(hw->tiltY, 0, &state->hw.tiltSampleY);
638 flags2 = GBASerializedHWFlags2SetTiltState(flags2, hw->tiltState);
639 flags2 = GBASerializedHWFlags1SetLightCounter(flags2, hw->lightCounter);
640 state->hw.lightSample = hw->lightSample;
641 flags1 = GBASerializedHWFlags1SetLightEdge(flags1, hw->lightEdge);
642 flags2 = GBASerializedHWFlags2SetGbpInputsPosted(flags2, hw->gbpInputsPosted);
643 flags2 = GBASerializedHWFlags2SetGbpTxPosition(flags2, hw->gbpTxPosition);
644 STORE_32(hw->gbpNextEvent.when - mTimingCurrentTime(&hw->p->timing), 0, &state->hw.gbpNextEvent);
645 STORE_16(flags1, 0, &state->hw.flags1);
646 state->hw.flags2 = flags2;
647}
648
649void GBAHardwareDeserialize(struct GBACartridgeHardware* hw, const struct GBASerializedState* state) {
650 GBASerializedHWFlags1 flags1;
651 LOAD_16(flags1, 0, &state->hw.flags1);
652 hw->readWrite = GBASerializedHWFlags1GetReadWrite(flags1);
653 LOAD_16(hw->pinState, 0, &state->hw.pinState);
654 LOAD_16(hw->direction, 0, &state->hw.pinDirection);
655 hw->devices = state->hw.devices;
656
657 LOAD_32(hw->rtc.bytesRemaining, 0, &state->hw.rtc.bytesRemaining);
658 LOAD_32(hw->rtc.transferStep, 0, &state->hw.rtc.transferStep);
659 LOAD_32(hw->rtc.bitsRead, 0, &state->hw.rtc.bitsRead);
660 LOAD_32(hw->rtc.bits, 0, &state->hw.rtc.bits);
661 LOAD_32(hw->rtc.commandActive, 0, &state->hw.rtc.commandActive);
662 LOAD_32(hw->rtc.command, 0, &state->hw.rtc.command);
663 LOAD_32(hw->rtc.control, 0, &state->hw.rtc.control);
664 memcpy(hw->rtc.time, state->hw.rtc.time, sizeof(hw->rtc.time));
665
666 LOAD_16(hw->gyroSample, 0, &state->hw.gyroSample);
667 hw->gyroEdge = GBASerializedHWFlags1GetGyroEdge(flags1);
668 LOAD_16(hw->tiltX, 0, &state->hw.tiltSampleX);
669 LOAD_16(hw->tiltY, 0, &state->hw.tiltSampleY);
670 hw->tiltState = GBASerializedHWFlags2GetTiltState(state->hw.flags2);
671 hw->lightCounter = GBASerializedHWFlags1GetLightCounter(flags1);
672 hw->lightSample = state->hw.lightSample;
673 hw->lightEdge = GBASerializedHWFlags1GetLightEdge(flags1);
674 hw->gbpInputsPosted = GBASerializedHWFlags2GetGbpInputsPosted(state->hw.flags2);
675 hw->gbpTxPosition = GBASerializedHWFlags2GetGbpTxPosition(state->hw.flags2);
676
677 uint32_t when;
678 LOAD_32(when, 0, &state->hw.gbpNextEvent);
679 if (hw->devices & HW_GB_PLAYER) {
680 GBASIOSetDriver(&hw->p->sio, &hw->gbpDriver.d, SIO_NORMAL_32);
681 if (hw->p->memory.io[REG_SIOCNT >> 1] & 0x0080) {
682 mTimingSchedule(&hw->p->timing, &hw->gbpNextEvent, when);
683 }
684 }
685}