src/gba/gba-sio.c (view raw)
1#include "gba-sio.h"
2
3#include "gba-io.h"
4
5static struct GBASIODriver* _lookupDriver(struct GBASIO* sio, enum GBASIOMode mode) {
6 switch (mode) {
7 case SIO_MULTI:
8 return sio->drivers.multiplayer;
9 case SIO_JOYBUS:
10 return sio->drivers.joybus;
11 default:
12 return 0;
13 }
14}
15
16static void _switchMode(struct GBASIO* sio) {
17 int mode = ((sio->rcnt >> 14) & 0xC) | ((sio->siocnt >> 12) & 0x3);
18 enum GBASIOMode oldMode = sio->mode;
19 if (mode < 8) {
20 sio->mode = (enum GBASIOMode) (mode & 0x3);
21 } else {
22 sio->mode = (enum GBASIOMode) (mode & 0xC);
23 }
24 if (oldMode != mode) {
25 if (sio->activeDriver && sio->activeDriver->detach) {
26 sio->activeDriver->detach(sio->activeDriver);
27 }
28 sio->activeDriver = _lookupDriver(sio, mode);
29 if (sio->activeDriver && sio->activeDriver->attach) {
30 sio->activeDriver->attach(sio->activeDriver);
31 }
32 }
33}
34
35void GBASIOInit(struct GBASIO* sio) {
36 sio->rcnt = RCNT_INITIAL;
37 sio->siocnt = 0;
38 _switchMode(sio);
39}
40
41void GBASIOSetDriverSet(struct GBASIO* sio, struct GBASIODriverSet* drivers) {
42 if (drivers->multiplayer) {
43 GBASIOSetDriver(sio, drivers->multiplayer, SIO_MULTI);
44 }
45 if (drivers->joybus) {
46 GBASIOSetDriver(sio, drivers->multiplayer, SIO_JOYBUS);
47 }
48}
49
50void GBASIOSetDriver(struct GBASIO* sio, struct GBASIODriver* driver, enum GBASIOMode mode) {
51 struct GBASIODriver** driverLoc;
52 switch (mode) {
53 case SIO_MULTI:
54 driverLoc = &sio->drivers.multiplayer;
55 break;
56 case SIO_JOYBUS:
57 driverLoc = &sio->drivers.joybus;
58 break;
59 default:
60 GBALog(sio->p, GBA_LOG_ERROR, "Setting an unsupported SIO driver: %x", mode);
61 return;
62 }
63 if (*driverLoc) {
64 if ((*driverLoc)->detach) {
65 (*driverLoc)->detach(*driverLoc);
66 }
67 if ((*driverLoc)->deinit) {
68 (*driverLoc)->deinit(*driverLoc);
69 }
70 }
71 if (*driverLoc == sio->activeDriver) {
72 sio->activeDriver = driver;
73 }
74 *driverLoc = driver;
75 if (driver && driver->init) {
76 driver->init(driver, sio);
77 }
78}
79
80void GBASIOWriteRCNT(struct GBASIO* sio, uint16_t value) {
81 sio->rcnt = value;
82 _switchMode(sio);
83 if (sio->activeDriver && sio->activeDriver->writeRegister) {
84 sio->activeDriver->writeRegister(sio->activeDriver, REG_RCNT, value);
85 }
86}
87
88void GBASIOWriteSIOCNT(struct GBASIO* sio, uint16_t value) {
89 sio->siocnt = value;
90 _switchMode(sio);
91 if (sio->activeDriver && sio->activeDriver->writeRegister) {
92 sio->activeDriver->writeRegister(sio->activeDriver, REG_SIOCNT, value);
93 }
94}
95
96void GBASIOWriteSIOMLT_SEND(struct GBASIO* sio, uint16_t value) {
97 if (sio->activeDriver && sio->activeDriver->writeRegister) {
98 sio->activeDriver->writeRegister(sio->activeDriver, REG_SIOMLT_SEND, value);
99 }
100}