all repos — mgba @ 8ad2e89cfce6f46f4dd630e6c43ee91afb7feada

mGBA Game Boy Advance Emulator

src/gba/sio/joybus.c (view raw)

 1/* Copyright (c) 2013-2017 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/sio.h>
 7
 8#include <mgba/internal/gba/gba.h>
 9#include <mgba/internal/gba/io.h>
10
11static uint16_t GBASIOJOYWriteRegister(struct GBASIODriver* sio, uint32_t address, uint16_t value);
12
13void GBASIOJOYCreate(struct GBASIODriver* sio) {
14	sio->init = NULL;
15	sio->deinit = NULL;
16	sio->load = NULL;
17	sio->unload = NULL;
18	sio->writeRegister = GBASIOJOYWriteRegister;
19}
20
21uint16_t GBASIOJOYWriteRegister(struct GBASIODriver* sio, uint32_t address, uint16_t value) {
22	switch (address) {
23	case REG_JOYCNT:
24		return (value & 0x0040) | (sio->p->p->memory.io[REG_JOYCNT >> 1] & ~(value & 0x7) & ~0x0040);
25	case REG_JOYSTAT:
26		return (value & 0x0030) | (sio->p->p->memory.io[REG_JOYSTAT >> 1] & ~0x30);
27	}
28	return value;
29}
30
31int GBASIOJOYSendCommand(struct GBASIODriver* sio, enum GBASIOJOYCommand command, uint8_t* data) {
32	switch (command) {
33	case JOY_RESET:
34		sio->p->p->memory.io[REG_JOYCNT >> 1] |= 1;
35		if (sio->p->p->memory.io[REG_JOYCNT >> 1] & 0x40) {
36			GBARaiseIRQ(sio->p->p, IRQ_SIO, 0);
37		}
38		// Fall through
39	case JOY_POLL:
40		data[0] = 0x00;
41		data[1] = 0x04;
42		data[2] = sio->p->p->memory.io[REG_JOYSTAT >> 1];
43		mLOG(GBA_SIO, DEBUG, "JOY %s: %02X (%02X)", command == JOY_POLL ? "poll" : "reset", data[2], sio->p->p->memory.io[REG_JOYCNT >> 1]);
44		return 3;
45	case JOY_RECV:
46		sio->p->p->memory.io[REG_JOYCNT >> 1] |= 2;
47		sio->p->p->memory.io[REG_JOYSTAT >> 1] |= 2;
48
49		sio->p->p->memory.io[REG_JOY_RECV_LO >> 1] = data[0] | (data[1] << 8);
50		sio->p->p->memory.io[REG_JOY_RECV_HI >> 1] = data[2] | (data[3] << 8);
51
52		data[0] = sio->p->p->memory.io[REG_JOYSTAT >> 1];
53		mLOG(GBA_SIO, DEBUG, "JOY recv: %02X (%02X)", data[0], sio->p->p->memory.io[REG_JOYCNT >> 1]);
54
55		if (sio->p->p->memory.io[REG_JOYCNT >> 1] & 0x40) {
56			GBARaiseIRQ(sio->p->p, IRQ_SIO, 0);
57		}
58		return 1;
59	case JOY_TRANS:
60		sio->p->p->memory.io[REG_JOYCNT >> 1] |= 4;
61		sio->p->p->memory.io[REG_JOYSTAT >> 1] &= ~JOYSTAT_TRANS_BIT;
62		data[0] = sio->p->p->memory.io[REG_JOY_TRANS_LO >> 1];
63		data[1] = sio->p->p->memory.io[REG_JOY_TRANS_LO >> 1] >> 8;
64		data[2] = sio->p->p->memory.io[REG_JOY_TRANS_HI >> 1];
65		data[3] = sio->p->p->memory.io[REG_JOY_TRANS_HI >> 1] >> 8;
66		data[4] = sio->p->p->memory.io[REG_JOYSTAT >> 1];
67		mLOG(GBA_SIO, DEBUG, "JOY trans: %02X%02X%02X%02X:%02X (%02X)", data[0], data[1], data[2], data[3], data[4], sio->p->p->memory.io[REG_JOYCNT >> 1]);
68
69		if (sio->p->p->memory.io[REG_JOYCNT >> 1] & 0x40) {
70			GBARaiseIRQ(sio->p->p, IRQ_SIO, 0);
71		}
72		return 5;
73	}
74	return 0;
75}