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) {
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 // TODO: Check if the SIO driver is actually used first
557 GBASIOSetDriver(&gba->sio, &gba->memory.hw.gbpDriver.d, SIO_NORMAL_32);
558 }
559}
560
561uint16_t _gbpRead(struct mKeyCallback* callback) {
562 struct GBAGBPKeyCallback* gbpCallback = (struct GBAGBPKeyCallback*) callback;
563 if (gbpCallback->p->gbpInputsPosted == 2) {
564 return 0xF0;
565 }
566 return 0;
567}
568
569uint16_t _gbpSioWriteRegister(struct GBASIODriver* driver, uint32_t address, uint16_t value) {
570 struct GBAGBPSIODriver* gbp = (struct GBAGBPSIODriver*) driver;
571 if (address == REG_SIOCNT) {
572 if (value & 0x0080) {
573 uint32_t rx = gbp->p->p->memory.io[REG_SIODATA32_LO >> 1] | (gbp->p->p->memory.io[REG_SIODATA32_HI >> 1] << 16);
574 if (gbp->p->gbpTxPosition < 12 && gbp->p->gbpTxPosition > 0) {
575 // TODO: Check expected
576 } else if (gbp->p->gbpTxPosition >= 12) {
577 uint32_t mask = 0x33;
578 // 0x00 = Stop
579 // 0x11 = Hard Stop
580 // 0x22 = Start
581 if (gbp->p->p->rumble) {
582 gbp->p->p->rumble->setRumble(gbp->p->p->rumble, (rx & mask) == 0x22);
583 }
584 }
585 mTimingDeschedule(&gbp->p->p->timing, &gbp->p->gbpNextEvent);
586 mTimingSchedule(&gbp->p->p->timing, &gbp->p->gbpNextEvent, 2048);
587 }
588 value &= 0x78FB;
589 }
590 return value;
591}
592
593void _gbpSioProcessEvents(struct mTiming* timing, void* user, uint32_t cyclesLate) {
594 UNUSED(timing);
595 UNUSED(cyclesLate);
596 struct GBAGBPSIODriver* gbp = user;
597 uint32_t tx = 0;
598 int txPosition = gbp->p->gbpTxPosition;
599 if (txPosition > 16) {
600 gbp->p->gbpTxPosition = 0;
601 txPosition = 0;
602 } else if (txPosition > 12) {
603 txPosition = 12;
604 }
605 tx = _gbpTxData[txPosition];
606 ++gbp->p->gbpTxPosition;
607 gbp->p->p->memory.io[REG_SIODATA32_LO >> 1] = tx;
608 gbp->p->p->memory.io[REG_SIODATA32_HI >> 1] = tx >> 16;
609 if (GBASIONormalIsIrq(gbp->d.p->siocnt)) {
610 GBARaiseIRQ(gbp->p->p, IRQ_SIO, cyclesLate);
611 }
612 gbp->d.p->siocnt = GBASIONormalClearStart(gbp->d.p->siocnt);
613 gbp->p->p->memory.io[REG_SIOCNT >> 1] = gbp->d.p->siocnt & ~0x0080;
614}
615
616// == Serialization
617
618void GBAHardwareSerialize(const struct GBACartridgeHardware* hw, struct GBASerializedState* state) {
619 GBASerializedHWFlags1 flags1 = 0;
620 GBASerializedHWFlags2 flags2 = 0;
621 flags1 = GBASerializedHWFlags1SetReadWrite(flags1, hw->readWrite);
622 STORE_16(hw->pinState, 0, &state->hw.pinState);
623 STORE_16(hw->direction, 0, &state->hw.pinDirection);
624 state->hw.devices = hw->devices;
625
626 STORE_32(hw->rtc.bytesRemaining, 0, &state->hw.rtc.bytesRemaining);
627 STORE_32(hw->rtc.transferStep, 0, &state->hw.rtc.transferStep);
628 STORE_32(hw->rtc.bitsRead, 0, &state->hw.rtc.bitsRead);
629 STORE_32(hw->rtc.bits, 0, &state->hw.rtc.bits);
630 STORE_32(hw->rtc.commandActive, 0, &state->hw.rtc.commandActive);
631 STORE_32(hw->rtc.command, 0, &state->hw.rtc.command);
632 STORE_32(hw->rtc.control, 0, &state->hw.rtc.control);
633 memcpy(state->hw.rtc.time, hw->rtc.time, sizeof(state->hw.rtc.time));
634
635 STORE_16(hw->gyroSample, 0, &state->hw.gyroSample);
636 flags1 = GBASerializedHWFlags1SetGyroEdge(flags1, hw->gyroEdge);
637 STORE_16(hw->tiltX, 0, &state->hw.tiltSampleX);
638 STORE_16(hw->tiltY, 0, &state->hw.tiltSampleY);
639 flags2 = GBASerializedHWFlags2SetTiltState(flags2, hw->tiltState);
640 flags2 = GBASerializedHWFlags1SetLightCounter(flags2, hw->lightCounter);
641 state->hw.lightSample = hw->lightSample;
642 flags1 = GBASerializedHWFlags1SetLightEdge(flags1, hw->lightEdge);
643 flags2 = GBASerializedHWFlags2SetGbpInputsPosted(flags2, hw->gbpInputsPosted);
644 flags2 = GBASerializedHWFlags2SetGbpTxPosition(flags2, hw->gbpTxPosition);
645 STORE_32(hw->gbpNextEvent.when - mTimingCurrentTime(&hw->p->timing), 0, &state->hw.gbpNextEvent);
646 STORE_16(flags1, 0, &state->hw.flags1);
647 state->hw.flags2 = flags2;
648}
649
650void GBAHardwareDeserialize(struct GBACartridgeHardware* hw, const struct GBASerializedState* state) {
651 GBASerializedHWFlags1 flags1;
652 LOAD_16(flags1, 0, &state->hw.flags1);
653 hw->readWrite = GBASerializedHWFlags1GetReadWrite(flags1);
654 LOAD_16(hw->pinState, 0, &state->hw.pinState);
655 LOAD_16(hw->direction, 0, &state->hw.pinDirection);
656 hw->devices = state->hw.devices;
657
658 LOAD_32(hw->rtc.bytesRemaining, 0, &state->hw.rtc.bytesRemaining);
659 LOAD_32(hw->rtc.transferStep, 0, &state->hw.rtc.transferStep);
660 LOAD_32(hw->rtc.bitsRead, 0, &state->hw.rtc.bitsRead);
661 LOAD_32(hw->rtc.bits, 0, &state->hw.rtc.bits);
662 LOAD_32(hw->rtc.commandActive, 0, &state->hw.rtc.commandActive);
663 LOAD_32(hw->rtc.command, 0, &state->hw.rtc.command);
664 LOAD_32(hw->rtc.control, 0, &state->hw.rtc.control);
665 memcpy(hw->rtc.time, state->hw.rtc.time, sizeof(hw->rtc.time));
666
667 LOAD_16(hw->gyroSample, 0, &state->hw.gyroSample);
668 hw->gyroEdge = GBASerializedHWFlags1GetGyroEdge(flags1);
669 LOAD_16(hw->tiltX, 0, &state->hw.tiltSampleX);
670 LOAD_16(hw->tiltY, 0, &state->hw.tiltSampleY);
671 hw->tiltState = GBASerializedHWFlags2GetTiltState(state->hw.flags2);
672 hw->lightCounter = GBASerializedHWFlags1GetLightCounter(flags1);
673 hw->lightSample = state->hw.lightSample;
674 hw->lightEdge = GBASerializedHWFlags1GetLightEdge(flags1);
675 hw->gbpInputsPosted = GBASerializedHWFlags2GetGbpInputsPosted(state->hw.flags2);
676 hw->gbpTxPosition = GBASerializedHWFlags2GetGbpTxPosition(state->hw.flags2);
677
678 uint32_t when;
679 LOAD_32(when, 0, &state->hw.gbpNextEvent);
680 if (hw->devices & HW_GB_PLAYER) {
681 GBASIOSetDriver(&hw->p->sio, &hw->gbpDriver.d, SIO_NORMAL_32);
682 if (hw->p->memory.io[REG_SIOCNT >> 1] & 0x0080) {
683 mTimingSchedule(&hw->p->timing, &hw->gbpNextEvent, when);
684 }
685 }
686}