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