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 case REG_JOY_TRANS_LO:
28 case REG_JOY_TRANS_HI:
29 sio->p->p->memory.io[REG_JOYSTAT >> 1] |= 8;
30 break;
31 }
32 return value;
33}
34
35int GBASIOJOYSendCommand(struct GBASIODriver* sio, enum GBASIOJOYCommand command, uint8_t* data) {
36 switch (command) {
37 case JOY_RESET:
38 sio->p->p->memory.io[REG_JOYCNT >> 1] |= 1;
39 if (sio->p->p->memory.io[REG_JOYCNT >> 1] & 0x40) {
40 GBARaiseIRQ(sio->p->p, IRQ_SIO);
41 }
42 // Fall through
43 case JOY_POLL:
44 data[0] = 0x00;
45 data[1] = 0x04;
46 data[2] = sio->p->p->memory.io[REG_JOYSTAT >> 1];
47 return 3;
48 case JOY_RECV:
49 sio->p->p->memory.io[REG_JOYCNT >> 1] |= 2;
50 sio->p->p->memory.io[REG_JOYSTAT >> 1] |= 2;
51
52 sio->p->p->memory.io[REG_JOY_RECV_LO >> 1] = data[0] | (data[1] << 8);
53 sio->p->p->memory.io[REG_JOY_RECV_HI >> 1] = data[2] | (data[3] << 8);
54
55 data[0] = sio->p->p->memory.io[REG_JOYSTAT >> 1];
56
57 if (sio->p->p->memory.io[REG_JOYCNT >> 1] & 0x40) {
58 GBARaiseIRQ(sio->p->p, IRQ_SIO);
59 }
60 return 1;
61 case JOY_TRANS:
62 sio->p->p->memory.io[REG_JOYCNT >> 1] |= 4;
63 sio->p->p->memory.io[REG_JOYSTAT >> 1] &= ~8;
64 data[0] = sio->p->p->memory.io[REG_JOY_TRANS_LO >> 1];
65 data[1] = sio->p->p->memory.io[REG_JOY_TRANS_LO >> 1] >> 8;
66 data[2] = sio->p->p->memory.io[REG_JOY_TRANS_HI >> 1];
67 data[3] = sio->p->p->memory.io[REG_JOY_TRANS_HI >> 1] >> 8;
68 data[4] = sio->p->p->memory.io[REG_JOYSTAT >> 1];
69
70 if (sio->p->p->memory.io[REG_JOYCNT >> 1] & 0x40) {
71 GBARaiseIRQ(sio->p->p, IRQ_SIO);
72 }
73 return 5;
74 }
75 return 0;
76}