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