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
13mLOG_DEFINE_CATEGORY(GBA_HW, "GBA Pak Hardware");
14
15const int GBA_LUX_LEVELS[10] = { 5, 11, 18, 27, 42, 62, 84, 109, 139, 183 };
16
17static void _readPins(struct GBACartridgeHardware* hw);
18static void _outputPins(struct GBACartridgeHardware* hw, unsigned pins);
19
20static void _rtcReadPins(struct GBACartridgeHardware* hw);
21static unsigned _rtcOutput(struct GBACartridgeHardware* hw);
22static void _rtcProcessByte(struct GBACartridgeHardware* hw);
23static void _rtcUpdateClock(struct GBACartridgeHardware* hw);
24static unsigned _rtcBCD(unsigned value);
25
26static time_t _rtcGenericCallback(struct mRTCSource* source);
27
28static void _gyroReadPins(struct GBACartridgeHardware* hw);
29
30static void _rumbleReadPins(struct GBACartridgeHardware* hw);
31
32static void _lightReadPins(struct GBACartridgeHardware* hw);
33
34static uint16_t _gbpRead(struct mKeyCallback*);
35static uint16_t _gbpSioWriteRegister(struct GBASIODriver* driver, uint32_t address, uint16_t value);
36static int32_t _gbpSioProcessEvents(struct GBASIODriver* driver, int32_t cycles);
37
38static const int RTC_BYTES[8] = {
39 0, // Force reset
40 0, // Empty
41 7, // Date/Time
42 0, // Force IRQ
43 1, // Control register
44 0, // Empty
45 3, // Time
46 0 // Empty
47};
48
49void GBAHardwareInit(struct GBACartridgeHardware* hw, uint16_t* base) {
50 hw->gpioBase = base;
51 GBAHardwareClear(hw);
52
53 hw->gbpCallback.d.readKeys = _gbpRead;
54 hw->gbpCallback.p = hw;
55 hw->gbpDriver.d.init = 0;
56 hw->gbpDriver.d.deinit = 0;
57 hw->gbpDriver.d.load = 0;
58 hw->gbpDriver.d.unload = 0;
59 hw->gbpDriver.d.writeRegister = _gbpSioWriteRegister;
60 hw->gbpDriver.d.processEvents = _gbpSioProcessEvents;
61 hw->gbpDriver.p = hw;
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 _rtcProcessByte(hw);
183 }
184 } else {
185 _outputPins(hw, 5 | (_rtcOutput(hw) << 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 _rtcProcessByte(struct GBACartridgeHardware* hw) {
209 --hw->rtc.bytesRemaining;
210 if (!hw->rtc.commandActive) {
211 RTCCommandData command;
212 command = hw->rtc.bits;
213 if (RTCCommandDataGetMagic(command) == 0x06) {
214 hw->rtc.command = command;
215
216 hw->rtc.bytesRemaining = RTC_BYTES[RTCCommandDataGetCommand(command)];
217 hw->rtc.commandActive = hw->rtc.bytesRemaining > 0;
218 switch (RTCCommandDataGetCommand(command)) {
219 case RTC_RESET:
220 hw->rtc.control = 0;
221 break;
222 case RTC_DATETIME:
223 case RTC_TIME:
224 _rtcUpdateClock(hw);
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", hw->rtc.bits);
232 }
233 } else {
234 switch (RTCCommandDataGetCommand(hw->rtc.command)) {
235 case RTC_CONTROL:
236 hw->rtc.control = hw->rtc.bits;
237 break;
238 case RTC_FORCE_IRQ:
239 mLOG(GBA_HW, STUB, "Unimplemented RTC command %u", RTCCommandDataGetCommand(hw->rtc.command));
240 break;
241 case RTC_RESET:
242 case RTC_DATETIME:
243 case RTC_TIME:
244 break;
245 }
246 }
247
248 hw->rtc.bits = 0;
249 hw->rtc.bitsRead = 0;
250 if (!hw->rtc.bytesRemaining) {
251 hw->rtc.commandActive = 0;
252 hw->rtc.command = RTCCommandDataClearReading(hw->rtc.command);
253 }
254}
255
256unsigned _rtcOutput(struct GBACartridgeHardware* hw) {
257 uint8_t outputByte = 0;
258 switch (RTCCommandDataGetCommand(hw->rtc.command)) {
259 case RTC_CONTROL:
260 outputByte = hw->rtc.control;
261 break;
262 case RTC_DATETIME:
263 case RTC_TIME:
264 outputByte = hw->rtc.time[7 - hw->rtc.bytesRemaining];
265 break;
266 case RTC_FORCE_IRQ:
267 case RTC_RESET:
268 break;
269 }
270 unsigned output = (outputByte >> hw->rtc.bitsRead) & 1;
271 return output;
272}
273
274void _rtcUpdateClock(struct GBACartridgeHardware* hw) {
275 time_t t;
276 struct mRTCSource* rtc = hw->p->rtcSource;
277 if (rtc) {
278 if (rtc->sample) {
279 rtc->sample(rtc);
280 }
281 t = rtc->unixTime(rtc);
282 } else {
283 t = time(0);
284 }
285 struct tm date;
286 localtime_r(&t, &date);
287 hw->rtc.time[0] = _rtcBCD(date.tm_year - 100);
288 hw->rtc.time[1] = _rtcBCD(date.tm_mon + 1);
289 hw->rtc.time[2] = _rtcBCD(date.tm_mday);
290 hw->rtc.time[3] = _rtcBCD(date.tm_wday);
291 if (RTCControlIsHour24(hw->rtc.control)) {
292 hw->rtc.time[4] = _rtcBCD(date.tm_hour);
293 } else {
294 hw->rtc.time[4] = _rtcBCD(date.tm_hour % 12);
295 }
296 hw->rtc.time[5] = _rtcBCD(date.tm_min);
297 hw->rtc.time[6] = _rtcBCD(date.tm_sec);
298}
299
300unsigned _rtcBCD(unsigned value) {
301 int counter = value % 10;
302 value /= 10;
303 counter += (value % 10) << 4;
304 return counter;
305}
306
307time_t _rtcGenericCallback(struct mRTCSource* source) {
308 struct GBARTCGenericSource* rtc = (struct GBARTCGenericSource*) source;
309 switch (rtc->override) {
310 case RTC_NO_OVERRIDE:
311 default:
312 return time(0);
313 case RTC_FIXED:
314 return rtc->value;
315 case RTC_FAKE_EPOCH:
316 return rtc->value + rtc->p->video.frameCounter * (int64_t) VIDEO_TOTAL_LENGTH / GBA_ARM7TDMI_FREQUENCY;
317 }
318}
319
320void GBARTCGenericSourceInit(struct GBARTCGenericSource* rtc, struct GBA* gba) {
321 rtc->p = gba;
322 rtc->override = RTC_NO_OVERRIDE;
323 rtc->value = 0;
324 rtc->d.sample = 0;
325 rtc->d.unixTime = _rtcGenericCallback;
326}
327
328// == Gyro
329
330void GBAHardwareInitGyro(struct GBACartridgeHardware* hw) {
331 hw->devices |= HW_GYRO;
332 hw->gyroSample = 0;
333 hw->gyroEdge = 0;
334}
335
336void _gyroReadPins(struct GBACartridgeHardware* hw) {
337 struct mRotationSource* gyro = hw->p->rotationSource;
338 if (!gyro || !gyro->readGyroZ) {
339 return;
340 }
341
342 if (hw->pinState & 1) {
343 if (gyro->sample) {
344 gyro->sample(gyro);
345 }
346 int32_t sample = gyro->readGyroZ(gyro);
347
348 // Normalize to ~12 bits, focused on 0x6C0
349 hw->gyroSample = (sample >> 21) + 0x6C0; // Crop off an extra bit so that we can't go negative
350 }
351
352 if (hw->gyroEdge && !(hw->pinState & 2)) {
353 // Write bit on falling edge
354 unsigned bit = hw->gyroSample >> 15;
355 hw->gyroSample <<= 1;
356 _outputPins(hw, bit << 2);
357 }
358
359 hw->gyroEdge = !!(hw->pinState & 2);
360}
361
362// == Rumble
363
364void GBAHardwareInitRumble(struct GBACartridgeHardware* hw) {
365 hw->devices |= HW_RUMBLE;
366}
367
368void _rumbleReadPins(struct GBACartridgeHardware* hw) {
369 struct mRumble* rumble = hw->p->rumble;
370 if (!rumble) {
371 return;
372 }
373
374 rumble->setRumble(rumble, !!(hw->pinState & 8));
375}
376
377// == Light sensor
378
379void GBAHardwareInitLight(struct GBACartridgeHardware* hw) {
380 hw->devices |= HW_LIGHT_SENSOR;
381 hw->lightCounter = 0;
382 hw->lightEdge = false;
383 hw->lightSample = 0xFF;
384}
385
386void _lightReadPins(struct GBACartridgeHardware* hw) {
387 if (hw->pinState & 4) {
388 // Boktai chip select
389 return;
390 }
391 if (hw->pinState & 2) {
392 struct GBALuminanceSource* lux = hw->p->luminanceSource;
393 mLOG(GBA_HW, DEBUG, "[SOLAR] Got reset");
394 hw->lightCounter = 0;
395 if (lux) {
396 lux->sample(lux);
397 hw->lightSample = lux->readLuminance(lux);
398 } else {
399 hw->lightSample = 0xFF;
400 }
401 }
402 if ((hw->pinState & 1) && hw->lightEdge) {
403 ++hw->lightCounter;
404 }
405 hw->lightEdge = !(hw->pinState & 1);
406
407 bool sendBit = hw->lightCounter >= hw->lightSample;
408 _outputPins(hw, sendBit << 3);
409 mLOG(GBA_HW, DEBUG, "[SOLAR] Output %u with pins %u", hw->lightCounter, hw->pinState);
410}
411
412// == Tilt
413
414void GBAHardwareInitTilt(struct GBACartridgeHardware* hw) {
415 hw->devices |= HW_TILT;
416 hw->tiltX = 0xFFF;
417 hw->tiltY = 0xFFF;
418 hw->tiltState = 0;
419}
420
421void GBAHardwareTiltWrite(struct GBACartridgeHardware* hw, uint32_t address, uint8_t value) {
422 switch (address) {
423 case 0x8000:
424 if (value == 0x55) {
425 hw->tiltState = 1;
426 } else {
427 mLOG(GBA_HW, GAME_ERROR, "Tilt sensor wrote wrong byte to %04x: %02x", address, value);
428 }
429 break;
430 case 0x8100:
431 if (value == 0xAA && hw->tiltState == 1) {
432 hw->tiltState = 0;
433 struct mRotationSource* rotationSource = hw->p->rotationSource;
434 if (!rotationSource || !rotationSource->readTiltX || !rotationSource->readTiltY) {
435 return;
436 }
437 if (rotationSource->sample) {
438 rotationSource->sample(rotationSource);
439 }
440 int32_t x = rotationSource->readTiltX(rotationSource);
441 int32_t y = rotationSource->readTiltY(rotationSource);
442 // Normalize to ~12 bits, focused on 0x3A0
443 hw->tiltX = (x >> 21) + 0x3A0; // Crop off an extra bit so that we can't go negative
444 hw->tiltY = (y >> 21) + 0x3A0;
445 } else {
446 mLOG(GBA_HW, GAME_ERROR, "Tilt sensor wrote wrong byte to %04x: %02x", address, value);
447 }
448 break;
449 default:
450 mLOG(GBA_HW, GAME_ERROR, "Invalid tilt sensor write to %04x: %02x", address, value);
451 break;
452 }
453}
454
455uint8_t GBAHardwareTiltRead(struct GBACartridgeHardware* hw, uint32_t address) {
456 switch (address) {
457 case 0x8200:
458 return hw->tiltX & 0xFF;
459 case 0x8300:
460 return ((hw->tiltX >> 8) & 0xF) | 0x80;
461 case 0x8400:
462 return hw->tiltY & 0xFF;
463 case 0x8500:
464 return (hw->tiltY >> 8) & 0xF;
465 default:
466 mLOG(GBA_HW, GAME_ERROR, "Invalid tilt sensor read from %04x", address);
467 break;
468 }
469 return 0xFF;
470}
471
472// == Game Boy Player
473
474static const uint16_t _logoPalette[] = {
475 0xFFDF, 0x640C, 0xE40C, 0xE42D, 0x644E, 0xE44E, 0xE46E, 0x68AF,
476 0xE8B0, 0x68D0, 0x68F0, 0x6911, 0xE911, 0x6D32, 0xED32, 0xED73,
477 0x6D93, 0xED94, 0x6DB4, 0xF1D5, 0x71F5, 0xF1F6, 0x7216, 0x7257,
478 0xF657, 0x7678, 0xF678, 0xF699, 0xF6B9, 0x76D9, 0xF6DA, 0x7B1B,
479 0xFB1B, 0xFB3C, 0x7B5C, 0x7B7D, 0xFF7D, 0x7F9D, 0x7FBE, 0x7FFF,
480 0x642D, 0x648E, 0xE88F, 0xE8F1, 0x6D52, 0x6D73, 0xF1B4, 0xF216,
481 0x7237, 0x7698, 0x7AFA, 0xFAFA, 0xFB5C, 0xFFBE, 0x7FDE, 0xFFFF,
482 0xFFFF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
483};
484
485static const uint32_t _logoHash = 0xEEDA6963;
486
487static const uint32_t _gbpTxData[] = {
488 0x0000494E, 0x0000494E,
489 0xB6B1494E, 0xB6B1544E,
490 0xABB1544E, 0xABB14E45,
491 0xB1BA4E45, 0xB1BA4F44,
492 0xB0BB4F44, 0xB0BB8002,
493 0x10000010, 0x20000013,
494 0x30000003
495};
496
497bool GBAHardwarePlayerCheckScreen(const struct GBAVideo* video) {
498 if (memcmp(video->palette, _logoPalette, sizeof(_logoPalette)) != 0) {
499 return false;
500 }
501 uint32_t hash = hash32(&video->renderer->vram[0x4000], 0x4000, 0);
502 return hash == _logoHash;
503}
504
505void GBAHardwarePlayerUpdate(struct GBA* gba) {
506 if (gba->memory.hw.devices & HW_GB_PLAYER) {
507 if (GBAHardwarePlayerCheckScreen(&gba->video)) {
508 ++gba->memory.hw.gbpInputsPosted;
509 gba->memory.hw.gbpInputsPosted %= 3;
510 gba->keyCallback = &gba->memory.hw.gbpCallback.d;
511 } else {
512 // TODO: Save and restore
513 gba->keyCallback = 0;
514 }
515 gba->memory.hw.gbpTxPosition = 0;
516 return;
517 }
518 if (gba->keyCallback || gba->sio.drivers.normal) {
519 return;
520 }
521 if (GBAHardwarePlayerCheckScreen(&gba->video)) {
522 gba->memory.hw.devices |= HW_GB_PLAYER;
523 gba->memory.hw.gbpInputsPosted = 0;
524 gba->memory.hw.gbpNextEvent = INT_MAX;
525 gba->keyCallback = &gba->memory.hw.gbpCallback.d;
526 GBASIOSetDriver(&gba->sio, &gba->memory.hw.gbpDriver.d, SIO_NORMAL_32);
527 }
528}
529
530uint16_t _gbpRead(struct mKeyCallback* callback) {
531 struct GBAGBPKeyCallback* gbpCallback = (struct GBAGBPKeyCallback*) callback;
532 if (gbpCallback->p->gbpInputsPosted == 2) {
533 return 0x30F;
534 }
535 return 0x3FF;
536}
537
538uint16_t _gbpSioWriteRegister(struct GBASIODriver* driver, uint32_t address, uint16_t value) {
539 struct GBAGBPSIODriver* gbp = (struct GBAGBPSIODriver*) driver;
540 if (address == REG_SIOCNT) {
541 if (value & 0x0080) {
542 uint32_t rx = gbp->p->p->memory.io[REG_SIODATA32_LO >> 1] | (gbp->p->p->memory.io[REG_SIODATA32_HI >> 1] << 16);
543 if (gbp->p->gbpTxPosition < 12 && gbp->p->gbpTxPosition > 0) {
544 // TODO: Check expected
545 } else if (gbp->p->gbpTxPosition >= 12) {
546 uint32_t mask = 0x33;
547 // 0x00 = Stop
548 // 0x11 = Hard Stop
549 // 0x22 = Start
550 if (gbp->p->p->rumble) {
551 gbp->p->p->rumble->setRumble(gbp->p->p->rumble, (rx & mask) == 0x22);
552 }
553 }
554 gbp->p->gbpNextEvent = 2048;
555 }
556 value &= 0x78FB;
557 }
558 return value;
559}
560
561int32_t _gbpSioProcessEvents(struct GBASIODriver* driver, int32_t cycles) {
562 struct GBAGBPSIODriver* gbp = (struct GBAGBPSIODriver*) driver;
563 gbp->p->gbpNextEvent -= cycles;
564 if (gbp->p->gbpNextEvent <= 0) {
565 uint32_t tx = 0;
566 int txPosition = gbp->p->gbpTxPosition;
567 if (txPosition > 16) {
568 gbp->p->gbpTxPosition = 0;
569 txPosition = 0;
570 } else if (txPosition > 12) {
571 txPosition = 12;
572 }
573 tx = _gbpTxData[txPosition];
574 ++gbp->p->gbpTxPosition;
575 gbp->p->p->memory.io[REG_SIODATA32_LO >> 1] = tx;
576 gbp->p->p->memory.io[REG_SIODATA32_HI >> 1] = tx >> 16;
577 if (gbp->d.p->normalControl.irq) {
578 GBARaiseIRQ(gbp->p->p, IRQ_SIO);
579 }
580 gbp->d.p->normalControl.start = 0;
581 gbp->p->p->memory.io[REG_SIOCNT >> 1] = gbp->d.p->siocnt;
582 gbp->p->gbpNextEvent = INT_MAX;
583 }
584 return gbp->p->gbpNextEvent;
585}
586
587// == Serialization
588
589void GBAHardwareSerialize(const struct GBACartridgeHardware* hw, struct GBASerializedState* state) {
590 GBASerializedHWFlags1 flags1 = 0;
591 GBASerializedHWFlags2 flags2 = 0;
592 flags1 = GBASerializedHWFlags1SetReadWrite(flags1, hw->readWrite);
593 STORE_16(hw->pinState, 0, &state->hw.pinState);
594 STORE_16(hw->direction, 0, &state->hw.pinDirection);
595 state->hw.devices = hw->devices;
596
597 STORE_32(hw->rtc.bytesRemaining, 0, &state->hw.rtc.bytesRemaining);
598 STORE_32(hw->rtc.transferStep, 0, &state->hw.rtc.transferStep);
599 STORE_32(hw->rtc.bitsRead, 0, &state->hw.rtc.bitsRead);
600 STORE_32(hw->rtc.bits, 0, &state->hw.rtc.bits);
601 STORE_32(hw->rtc.commandActive, 0, &state->hw.rtc.commandActive);
602 STORE_32(hw->rtc.command, 0, &state->hw.rtc.command);
603 STORE_32(hw->rtc.control, 0, &state->hw.rtc.control);
604 memcpy(state->hw.rtc.time, hw->rtc.time, sizeof(state->hw.rtc.time));
605
606 STORE_16(hw->gyroSample, 0, &state->hw.gyroSample);
607 flags1 = GBASerializedHWFlags1SetGyroEdge(flags1, hw->gyroEdge);
608 STORE_16(hw->tiltX, 0, &state->hw.tiltSampleX);
609 STORE_16(hw->tiltY, 0, &state->hw.tiltSampleY);
610 flags2 = GBASerializedHWFlags2SetTiltState(flags2, hw->tiltState);
611 flags2 = GBASerializedHWFlags1SetLightCounter(flags2, hw->lightCounter);
612 state->hw.lightSample = hw->lightSample;
613 flags1 = GBASerializedHWFlags1SetLightEdge(flags1, hw->lightEdge);
614 flags2 = GBASerializedHWFlags2SetGbpInputsPosted(flags2, hw->gbpInputsPosted);
615 flags2 = GBASerializedHWFlags2SetGbpTxPosition(flags2, hw->gbpTxPosition);
616 STORE_32(hw->gbpNextEvent, 0, &state->hw.gbpNextEvent);
617 STORE_16(flags1, 0, &state->hw.flags1);
618 state->hw.flags2 = flags2;
619}
620
621void GBAHardwareDeserialize(struct GBACartridgeHardware* hw, const struct GBASerializedState* state) {
622 GBASerializedHWFlags1 flags1;
623 LOAD_16(flags1, 0, &state->hw.flags1);
624 hw->readWrite = GBASerializedHWFlags1GetReadWrite(flags1);
625 LOAD_16(hw->pinState, 0, &state->hw.pinState);
626 LOAD_16(hw->direction, 0, &state->hw.pinDirection);
627 hw->devices = state->hw.devices;
628
629 LOAD_32(hw->rtc.bytesRemaining, 0, &state->hw.rtc.bytesRemaining);
630 LOAD_32(hw->rtc.transferStep, 0, &state->hw.rtc.transferStep);
631 LOAD_32(hw->rtc.bitsRead, 0, &state->hw.rtc.bitsRead);
632 LOAD_32(hw->rtc.bits, 0, &state->hw.rtc.bits);
633 LOAD_32(hw->rtc.commandActive, 0, &state->hw.rtc.commandActive);
634 LOAD_32(hw->rtc.command, 0, &state->hw.rtc.command);
635 LOAD_32(hw->rtc.control, 0, &state->hw.rtc.control);
636 memcpy(hw->rtc.time, state->hw.rtc.time, sizeof(hw->rtc.time));
637
638 LOAD_16(hw->gyroSample, 0, &state->hw.gyroSample);
639 hw->gyroEdge = GBASerializedHWFlags1GetGyroEdge(flags1);
640 LOAD_16(hw->tiltX, 0, &state->hw.tiltSampleX);
641 LOAD_16(hw->tiltY, 0, &state->hw.tiltSampleY);
642 hw->tiltState = GBASerializedHWFlags2GetTiltState(state->hw.flags2);
643 hw->lightCounter = GBASerializedHWFlags1GetLightCounter(flags1);
644 hw->lightSample = state->hw.lightSample;
645 hw->lightEdge = GBASerializedHWFlags1GetLightEdge(flags1);
646 hw->gbpInputsPosted = GBASerializedHWFlags2GetGbpInputsPosted(state->hw.flags2);
647 hw->gbpTxPosition = GBASerializedHWFlags2GetGbpTxPosition(state->hw.flags2);
648 LOAD_32(hw->gbpNextEvent, 0, &state->hw.gbpNextEvent);
649 if (hw->devices & HW_GB_PLAYER) {
650 GBASIOSetDriver(&hw->p->sio, &hw->gbpDriver.d, SIO_NORMAL_32);
651 }
652}