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
490};
491
492static const uint32_t _gbpRxData[] = {
493 0x00000000, 0x494EB6B1,
494 0x494EB6B1, 0x544EB6B1,
495 0x544EABB1, 0x4E45ABB1,
496 0x4E45B1BA, 0x4F44B1BA,
497 0x4F44B0BB, 0x8000B0BB,
498 0x10000010, 0x20000013,
499 0x40000004
500};
501
502bool GBAHardwarePlayerCheckScreen(const struct GBAVideo* video) {
503 if (memcmp(video->palette, _logoPalette, sizeof(_logoPalette)) != 0) {
504 return false;
505 }
506 uint32_t hash = hash32(&video->renderer->vram[0x4000], 0x4000, 0);
507 return hash == _logoHash;
508}
509
510void GBAHardwarePlayerUpdate(struct GBA* gba) {
511 if (gba->memory.hw.devices & HW_GB_PLAYER) {
512 if (GBAHardwarePlayerCheckScreen(&gba->video)) {
513 ++gba->memory.hw.gbpInputsPosted;
514 gba->memory.hw.gbpInputsPosted %= 3;
515 gba->keyCallback = &gba->memory.hw.gbpCallback.d;
516 } else {
517 // TODO: Save and restore
518 gba->keyCallback = 0;
519 }
520 gba->memory.hw.gbpTxPosition = 0;
521 return;
522 }
523 if (gba->keyCallback || gba->sio.drivers.normal) {
524 return;
525 }
526 if (GBAHardwarePlayerCheckScreen(&gba->video)) {
527 gba->memory.hw.devices |= HW_GB_PLAYER;
528 gba->memory.hw.gbpInputsPosted = 0;
529 gba->memory.hw.gbpNextEvent = INT_MAX;
530 gba->keyCallback = &gba->memory.hw.gbpCallback.d;
531 GBASIOSetDriver(&gba->sio, &gba->memory.hw.gbpDriver.d, SIO_NORMAL_32);
532 }
533}
534
535uint16_t _gbpRead(struct GBAKeyCallback* callback) {
536 struct GBAGBPKeyCallback* gbpCallback = (struct GBAGBPKeyCallback*) callback;
537 if (gbpCallback->p->gbpInputsPosted == 2) {
538 return 0x30F;
539 }
540 return 0x3FF;
541}
542
543uint16_t _gbpSioWriteRegister(struct GBASIODriver* driver, uint32_t address, uint16_t value) {
544 struct GBAGBPSIODriver* gbp = (struct GBAGBPSIODriver*) driver;
545 if (address == REG_SIOCNT) {
546 if (value & 0x0080) {
547 uint32_t rx = gbp->p->p->memory.io[REG_SIODATA32_LO >> 1] | (gbp->p->p->memory.io[REG_SIODATA32_HI >> 1] << 16);
548 if (gbp->p->gbpTxPosition < 12 && gbp->p->gbpTxPosition > 0) {
549 uint32_t expected = _gbpRxData[gbp->p->gbpTxPosition];
550 // TODO: Check expected
551 } else if (gbp->p->gbpTxPosition >= 12) {
552 uint32_t mask = 0x33;
553 // 0x00 = Stop
554 // 0x11 = Hard Stop
555 // 0x22 = Start
556 if (gbp->p->p->rumble) {
557 gbp->p->p->rumble->setRumble(gbp->p->p->rumble, (rx & mask) == 0x22);
558 }
559 }
560 gbp->p->gbpNextEvent = 2048;
561 }
562 value &= 0x78FB;
563 }
564 return value;
565}
566
567int32_t _gbpSioProcessEvents(struct GBASIODriver* driver, int32_t cycles) {
568 struct GBAGBPSIODriver* gbp = (struct GBAGBPSIODriver*) driver;
569 gbp->p->gbpNextEvent -= cycles;
570 if (gbp->p->gbpNextEvent <= 0) {
571 uint32_t tx = 0;
572 if (gbp->p->gbpTxPosition <= 12) {
573 tx = _gbpTxData[gbp->p->gbpTxPosition];
574 if (gbp->p->gbpTxPosition < 12) {
575 ++gbp->p->gbpTxPosition;
576 }
577 }
578 gbp->p->p->memory.io[REG_SIODATA32_LO >> 1] = tx;
579 gbp->p->p->memory.io[REG_SIODATA32_HI >> 1] = tx >> 16;
580 if (gbp->d.p->normalControl.irq) {
581 GBARaiseIRQ(gbp->p->p, IRQ_SIO);
582 }
583 gbp->d.p->normalControl.start = 0;
584 gbp->p->p->memory.io[REG_SIOCNT >> 1] = gbp->d.p->siocnt;
585 gbp->p->gbpNextEvent = INT_MAX;
586 }
587 return gbp->p->gbpNextEvent;
588}
589
590// == Serialization
591
592void GBAHardwareSerialize(const struct GBACartridgeHardware* hw, struct GBASerializedState* state) {
593 GBASerializedHWFlags1 flags1 = 0;
594 GBASerializedHWFlags2 flags2 = 0;
595 flags1 = GBASerializedHWFlags1SetReadWrite(flags1, hw->readWrite);
596 STORE_16(hw->pinState, 0, &state->hw.pinState);
597 STORE_16(hw->direction, 0, &state->hw.pinDirection);
598 state->hw.devices = hw->devices;
599
600 STORE_32(hw->rtc.bytesRemaining, 0, &state->hw.rtc.bytesRemaining);
601 STORE_32(hw->rtc.transferStep, 0, &state->hw.rtc.transferStep);
602 STORE_32(hw->rtc.bitsRead, 0, &state->hw.rtc.bitsRead);
603 STORE_32(hw->rtc.bits, 0, &state->hw.rtc.bits);
604 STORE_32(hw->rtc.commandActive, 0, &state->hw.rtc.commandActive);
605 STORE_32(hw->rtc.command, 0, &state->hw.rtc.command);
606 STORE_32(hw->rtc.control, 0, &state->hw.rtc.control);
607 memcpy(state->hw.rtc.time, hw->rtc.time, sizeof(state->hw.rtc.time));
608
609 STORE_16(hw->gyroSample, 0, &state->hw.gyroSample);
610 flags1 = GBASerializedHWFlags1SetGyroEdge(flags1, hw->gyroEdge);
611 STORE_16(hw->tiltX, 0, &state->hw.tiltSampleX);
612 STORE_16(hw->tiltY, 0, &state->hw.tiltSampleY);
613 flags2 = GBASerializedHWFlags2SetTiltState(flags2, hw->tiltState);
614 flags2 = GBASerializedHWFlags1SetLightCounter(flags2, hw->lightCounter);
615 state->hw.lightSample = hw->lightSample;
616 flags1 = GBASerializedHWFlags1SetLightEdge(flags1, hw->lightEdge);
617 flags2 = GBASerializedHWFlags2SetGbpInputsPosted(flags2, hw->gbpInputsPosted);
618 flags2 = GBASerializedHWFlags2SetGbpTxPosition(flags2, hw->gbpTxPosition);
619 STORE_32(hw->gbpNextEvent, 0, &state->hw.gbpNextEvent);
620 STORE_16(flags1, 0, &state->hw.flags1);
621 state->hw.flags2 = flags2;
622}
623
624void GBAHardwareDeserialize(struct GBACartridgeHardware* hw, const struct GBASerializedState* state) {
625 GBASerializedHWFlags1 flags1;
626 LOAD_16(flags1, 0, &state->hw.flags1);
627 hw->readWrite = GBASerializedHWFlags1GetReadWrite(flags1);
628 LOAD_16(hw->pinState, 0, &state->hw.pinState);
629 LOAD_16(hw->direction, 0, &state->hw.pinDirection);
630 hw->devices = state->hw.devices;
631
632 LOAD_32(hw->rtc.bytesRemaining, 0, &state->hw.rtc.bytesRemaining);
633 LOAD_32(hw->rtc.transferStep, 0, &state->hw.rtc.transferStep);
634 LOAD_32(hw->rtc.bitsRead, 0, &state->hw.rtc.bitsRead);
635 LOAD_32(hw->rtc.bits, 0, &state->hw.rtc.bits);
636 LOAD_32(hw->rtc.commandActive, 0, &state->hw.rtc.commandActive);
637 LOAD_32(hw->rtc.command, 0, &state->hw.rtc.command);
638 LOAD_32(hw->rtc.control, 0, &state->hw.rtc.control);
639 memcpy(hw->rtc.time, state->hw.rtc.time, sizeof(hw->rtc.time));
640
641 LOAD_16(hw->gyroSample, 0, &state->hw.gyroSample);
642 hw->gyroEdge = GBASerializedHWFlags1GetGyroEdge(flags1);
643 LOAD_16(hw->tiltX, 0, &state->hw.tiltSampleX);
644 LOAD_16(hw->tiltY, 0, &state->hw.tiltSampleY);
645 hw->tiltState = GBASerializedHWFlags2GetTiltState(state->hw.flags2);
646 hw->lightCounter = GBASerializedHWFlags1GetLightCounter(flags1);
647 hw->lightSample = state->hw.lightSample;
648 hw->lightEdge = GBASerializedHWFlags1GetLightEdge(flags1);
649 hw->gbpInputsPosted = GBASerializedHWFlags2GetGbpInputsPosted(state->hw.flags2);
650 hw->gbpTxPosition = GBASerializedHWFlags2GetGbpTxPosition(state->hw.flags2);
651 LOAD_32(hw->gbpNextEvent, 0, &state->hw.gbpNextEvent);
652 if (hw->devices & HW_GB_PLAYER) {
653 GBASIOSetDriver(&hw->p->sio, &hw->gbpDriver.d, SIO_NORMAL_32);
654 }
655}