forked from daitangio/x16-emulator
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathjoystick.c
175 lines (155 loc) · 5.47 KB
/
joystick.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
/**********************************************/
// File : joystick.c
// Author : John Bliss
// Date : September 27th 2019
/**********************************************/
#include "joystick.h"
enum joy_status joy1_mode = NONE;
enum joy_status joy2_mode = NONE;
static SDL_GameController *joystick1 = NULL;
static SDL_GameController *joystick2 = NULL;
static bool old_clock = false;
static bool writing = false;
static uint32_t joystick1_state = 0;
static uint32_t joystick2_state = 0;
static uint8_t clock_count = 0;
bool joystick_latch, joystick_clock;
bool joystick1_data, joystick2_data;
bool joystick_init()
{
int joystick1_number = -1;
//Try to get first controller, if it is not set to 1
if (joy1_mode != NONE) {
for (int i = 0; i < SDL_NumJoysticks(); i++) {
if (SDL_IsGameController(i)) {
joystick1 = SDL_GameControllerOpen(i);
if (joystick1) {
joystick1_number = i;
break;
} else {
fprintf(stderr, "Could not open gamecontroller %i: %s\n", i, SDL_GetError());
}
}
}
}
if (joy2_mode != NONE) {
for (int i=0; i < SDL_NumJoysticks(); i++) {
if (SDL_IsGameController(i) && joystick1_number != i) {
joystick2 = SDL_GameControllerOpen(i);
if (joystick2) {
break;
} else {
fprintf(stderr, "Could not open gamecontroller %i: %s\n", i, SDL_GetError());
}
}
}
}
writing = false;
return true;
}
void joystick_step()
{
if (!writing) { //if we are not already writing, check latch to
//see if we need to start
handle_latch(joystick_latch, joystick_clock);
return;
}
//if we have started writing controller data and the latch has dropped,
// we need to start the next bit
if (!joystick_latch) {
//check if clock has changed
if (joystick_clock != old_clock) {
if (old_clock) {
old_clock = joystick_clock;
} else { //only write next bit when the new clock is high
clock_count +=1;
old_clock = joystick_clock;
if (clock_count < 24) { // write out the next 15 bits
joystick1_data = joystick1_state & 1;
joystick2_data = joystick2_state & 1;
joystick1_state = joystick1_state >> 1;
joystick2_state = joystick2_state >> 1;
} else {
//Done writing controller data
//reset flag and set count to 0
writing = false;
clock_count = 0;
joystick1_data = 1;
joystick2_data = 1;
}
}
}
}
}
bool handle_latch(bool latch, bool clock)
{
if (latch){
clock_count = 0;
//get the 16-representation to put to the VIA
joystick1_state = (joy1_mode != NONE) ? get_joystick_state(joystick1, joy1_mode) : 0xFFFFFF;
joystick2_state = (joy2_mode != NONE) ? get_joystick_state(joystick2, joy2_mode) : 0xFFFFFF;
//set writing flag to true to signal we will start writing controller data
writing = true;
old_clock = clock;
//preload the first bit onto VIA
joystick1_data = joystick1_state & 1;
joystick2_data = joystick2_state & 1;
joystick1_state = joystick1_state >> 1;
joystick2_state = joystick2_state >> 1;
}
return latch;
}
//get current state from SDL controller
//Should replace this with SDL events, so we do not miss inputs when polling
uint32_t get_joystick_state(SDL_GameController *control, enum joy_status mode)
{
if (mode == NES) {
bool a_pressed = SDL_GameControllerGetButton(control, SDL_CONTROLLER_BUTTON_A);
bool b_pressed = SDL_GameControllerGetButton(control, SDL_CONTROLLER_BUTTON_X);
bool select_pressed = SDL_GameControllerGetButton(control, SDL_CONTROLLER_BUTTON_BACK);
bool start_pressed = SDL_GameControllerGetButton(control, SDL_CONTROLLER_BUTTON_START);
bool up_pressed = SDL_GameControllerGetButton(control, SDL_CONTROLLER_BUTTON_DPAD_UP);
bool down_pressed = SDL_GameControllerGetButton(control, SDL_CONTROLLER_BUTTON_DPAD_DOWN);
bool left_pressed = SDL_GameControllerGetButton(control, SDL_CONTROLLER_BUTTON_DPAD_LEFT);
bool right_pressed = SDL_GameControllerGetButton(control, SDL_CONTROLLER_BUTTON_DPAD_RIGHT);
return
(!a_pressed) |
(!b_pressed) << 1 |
(!select_pressed) << 2 |
(!start_pressed) << 3 |
(!up_pressed) << 4 |
(!down_pressed) << 5 |
(!left_pressed) << 6 |
(!right_pressed) << 7 |
0x000000;
}
if (mode == SNES) {
bool b_pressed = SDL_GameControllerGetButton(control, SDL_CONTROLLER_BUTTON_A);
bool y_pressed = SDL_GameControllerGetButton(control, SDL_CONTROLLER_BUTTON_X);
bool select_pressed = SDL_GameControllerGetButton(control, SDL_CONTROLLER_BUTTON_BACK);
bool start_pressed = SDL_GameControllerGetButton(control, SDL_CONTROLLER_BUTTON_START);
bool up_pressed = SDL_GameControllerGetButton(control, SDL_CONTROLLER_BUTTON_DPAD_UP);
bool down_pressed = SDL_GameControllerGetButton(control, SDL_CONTROLLER_BUTTON_DPAD_DOWN);
bool left_pressed = SDL_GameControllerGetButton(control, SDL_CONTROLLER_BUTTON_DPAD_LEFT);
bool right_pressed = SDL_GameControllerGetButton(control, SDL_CONTROLLER_BUTTON_DPAD_RIGHT);
bool a_pressed = SDL_GameControllerGetButton(control, SDL_CONTROLLER_BUTTON_B);
bool x_pressed = SDL_GameControllerGetButton(control, SDL_CONTROLLER_BUTTON_Y);
bool l_pressed = SDL_GameControllerGetButton(control, SDL_CONTROLLER_BUTTON_LEFTSHOULDER);
bool r_pressed = SDL_GameControllerGetButton(control, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER);
return
(!b_pressed) |
(!y_pressed) << 1 |
(!select_pressed) << 2 |
(!start_pressed) << 3 |
(!up_pressed) << 4 |
(!down_pressed) << 5 |
(!left_pressed) << 6 |
(!right_pressed) << 7 |
(!a_pressed) << 8 |
(!x_pressed) << 9 |
(!l_pressed) << 10 |
(!r_pressed) << 11 |
0x00F000;
}
return 0x8FFF;
}