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