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