all repos — mgba @ e5ee1aa07f0f7bffe86ddda36747b5480964e9fe

mGBA Game Boy Advance Emulator

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}