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