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