comparison io.c @ 421:d0cacb4ade0b

Move IO code to a separate file and do a tiny bit of refactoring
author Mike Pavone <pavone@retrodev.com>
date Tue, 25 Jun 2013 19:20:39 -0700
parents
children 440efd7d27a9
comparison
equal deleted inserted replaced
420:9fb111b5641f 421:d0cacb4ade0b
1 #include "io.h"
2 #include "blastem.h"
3 #include "render.h"
4
5 enum {
6 BIND_NONE,
7 BIND_GAMEPAD1,
8 BIND_GAMEPAD2,
9 BIND_UI
10 };
11
12 typedef enum {
13 UI_DEBUG_MODE_INC,
14 UI_DEBUG_PAL_INC,
15 UI_ENTER_DEBUGGER
16 } ui_action;
17
18 typedef struct {
19 uint8_t bind_type;
20 uint8_t subtype_a;
21 uint8_t subtype_b;
22 uint8_t value;
23 } keybinding;
24
25 typedef struct {
26 keybinding bindings[4];
27 uint8_t state;
28 } joydpad;
29
30 keybinding * bindings[256];
31 keybinding * joybindings[MAX_JOYSTICKS];
32 joydpad * joydpads[MAX_JOYSTICKS];
33 const uint8_t dpadbits[] = {RENDER_DPAD_UP, RENDER_DPAD_DOWN, RENDER_DPAD_LEFT, RENDER_DPAD_RIGHT};
34
35 void bind_key(int keycode, uint8_t bind_type, uint8_t subtype_a, uint8_t subtype_b, uint8_t value)
36 {
37 int bucket = keycode >> 8 & 0xFF;
38 if (!bindings[bucket]) {
39 bindings[bucket] = malloc(sizeof(keybinding) * 256);
40 memset(bindings[bucket], 0, sizeof(keybinding) * 256);
41 }
42 int idx = keycode & 0xFF;
43 bindings[bucket][idx].bind_type = bind_type;
44 bindings[bucket][idx].subtype_a = subtype_a;
45 bindings[bucket][idx].subtype_b = subtype_b;
46 bindings[bucket][idx].value = value;
47 }
48
49 void bind_button(int joystick, int button, uint8_t bind_type, uint8_t subtype_a, uint8_t subtype_b, uint8_t value)
50 {
51 if (joystick >= MAX_JOYSTICKS) {
52 return;
53 }
54 if (!joybindings[joystick]) {
55 int num = render_joystick_num_buttons(joystick);
56 if (!num) {
57 return;
58 }
59 joybindings[joystick] = malloc(sizeof(keybinding)*num);
60 memset(joybindings[joystick], 0, sizeof(keybinding)*num);
61 }
62 joybindings[joystick][button].bind_type = bind_type;
63 joybindings[joystick][button].subtype_a = subtype_a;
64 joybindings[joystick][button].subtype_b = subtype_b;
65 joybindings[joystick][button].value = value;
66 }
67
68 void bind_dpad(int joystick, int dpad, int direction, uint8_t bind_type, uint8_t subtype_a, uint8_t subtype_b, uint8_t value)
69 {
70 if (joystick >= MAX_JOYSTICKS) {
71 return;
72 }
73 if (!joydpads[joystick]) {
74 int num = render_joystick_num_hats(joystick);
75 if (!num) {
76 return;
77 }
78 joydpads[joystick] = malloc(sizeof(joydpad)*num);
79 memset(joydpads[joystick], 0, sizeof(joydpad)*num);
80 }
81 for (int i = 0; i < 4; i ++) {
82 if (dpadbits[i] & direction) {
83 joydpads[joystick][dpad].bindings[i].bind_type = bind_type;
84 joydpads[joystick][dpad].bindings[i].subtype_a = subtype_a;
85 joydpads[joystick][dpad].bindings[i].subtype_b = subtype_b;
86 joydpads[joystick][dpad].bindings[i].value = value;
87 break;
88 }
89 }
90 }
91
92 #define GAMEPAD_BUTTON(PRI_SLOT, SEC_SLOT, VALUE) (PRI_SLOT << 12 | SEC_SLOT << 8 | VALUE)
93
94 #define DPAD_UP GAMEPAD_BUTTON(GAMEPAD_TH0, GAMEPAD_TH1, 0x01)
95 #define BUTTON_Z GAMEPAD_BUTTON(GAMEPAD_EXTRA, GAMEPAD_NONE, 0x01)
96 #define DPAD_DOWN GAMEPAD_BUTTON(GAMEPAD_TH0, GAMEPAD_TH1, 0x02)
97 #define BUTTON_Y GAMEPAD_BUTTON(GAMEPAD_EXTRA, GAMEPAD_NONE, 0x02)
98 #define DPAD_LEFT GAMEPAD_BUTTON(GAMEPAD_TH1, GAMEPAD_NONE, 0x04)
99 #define BUTTON_X GAMEPAD_BUTTON(GAMEPAD_EXTRA, GAMEPAD_NONE, 0x04)
100 #define DPAD_RIGHT GAMEPAD_BUTTON(GAMEPAD_TH1, GAMEPAD_NONE, 0x08)
101 #define BUTTON_MODE GAMEPAD_BUTTON(GAMEPAD_EXTRA, GAMEPAD_NONE, 0x08)
102 #define BUTTON_A GAMEPAD_BUTTON(GAMEPAD_TH0, GAMEPAD_NONE, 0x10)
103 #define BUTTON_B GAMEPAD_BUTTON(GAMEPAD_TH1, GAMEPAD_NONE, 0x10)
104 #define BUTTON_START GAMEPAD_BUTTON(GAMEPAD_TH0, GAMEPAD_NONE, 0x20)
105 #define BUTTON_C GAMEPAD_BUTTON(GAMEPAD_TH1, GAMEPAD_NONE, 0x20)
106
107 void bind_gamepad(int keycode, int gamepadnum, int button)
108 {
109
110 if (gamepadnum < 1 || gamepadnum > 2) {
111 return;
112 }
113 uint8_t bind_type = gamepadnum - 1 + BIND_GAMEPAD1;
114 bind_key(keycode, bind_type, button >> 12, button >> 8 & 0xF, button & 0xFF);
115 }
116
117 void bind_button_gamepad(int joystick, int joybutton, int gamepadnum, int padbutton)
118 {
119 if (gamepadnum < 1 || gamepadnum > 2) {
120 return;
121 }
122 uint8_t bind_type = gamepadnum - 1 + BIND_GAMEPAD1;
123 bind_button(joystick, joybutton, bind_type, padbutton >> 12, padbutton >> 8 & 0xF, padbutton & 0xFF);
124 }
125
126 void bind_dpad_gamepad(int joystick, int dpad, uint8_t direction, int gamepadnum, int button)
127 {
128 if (gamepadnum < 1 || gamepadnum > 2) {
129 return;
130 }
131 uint8_t bind_type = gamepadnum - 1 + BIND_GAMEPAD1;
132 bind_dpad(joystick, dpad, direction, bind_type, button >> 12, button >> 8 & 0xF, button & 0xFF);
133 }
134
135 void bind_ui(int keycode, ui_action action)
136 {
137 bind_key(keycode, BIND_UI, action, 0, 0);
138 }
139
140 void handle_binding_down(keybinding * binding)
141 {
142 switch(binding->bind_type)
143 {
144 case BIND_GAMEPAD1:
145 case BIND_GAMEPAD2:
146 if (binding->subtype_a <= GAMEPAD_EXTRA) {
147 genesis->ports[binding->bind_type - BIND_GAMEPAD1].input[binding->subtype_a] |= binding->value;
148 }
149 if (binding->subtype_b <= GAMEPAD_EXTRA) {
150 genesis->ports[binding->bind_type - BIND_GAMEPAD1].input[binding->subtype_b] |= binding->value;
151 }
152 break;
153 }
154 }
155
156 void handle_keydown(int keycode)
157 {
158 int bucket = keycode >> 8 & 0xFF;
159 if (!bindings[bucket]) {
160 return;
161 }
162 int idx = keycode & 0xFF;
163 keybinding * binding = bindings[bucket] + idx;
164 handle_binding_down(binding);
165 }
166
167 void handle_joydown(int joystick, int button)
168 {
169 if (!joybindings[joystick]) {
170 return;
171 }
172 keybinding * binding = joybindings[joystick] + button;
173 handle_binding_down(binding);
174 }
175
176 uint8_t ui_debug_mode = 0;
177 uint8_t ui_debug_pal = 0;
178
179 void handle_binding_up(keybinding * binding)
180 {
181 switch(binding->bind_type)
182 {
183 case BIND_GAMEPAD1:
184 case BIND_GAMEPAD2:
185 if (binding->subtype_a <= GAMEPAD_EXTRA) {
186 genesis->ports[binding->bind_type - BIND_GAMEPAD1].input[binding->subtype_a] &= ~binding->value;
187 }
188 if (binding->subtype_b <= GAMEPAD_EXTRA) {
189 genesis->ports[binding->bind_type - BIND_GAMEPAD1].input[binding->subtype_b] &= ~binding->value;
190 }
191 break;
192 case BIND_UI:
193 switch (binding->subtype_a)
194 {
195 case UI_DEBUG_MODE_INC:
196 ui_debug_mode++;
197 if (ui_debug_mode == 4) {
198 ui_debug_mode = 0;
199 }
200 render_debug_mode(ui_debug_mode);
201 break;
202 case UI_DEBUG_PAL_INC:
203 ui_debug_pal++;
204 if (ui_debug_pal == 4) {
205 ui_debug_pal = 0;
206 }
207 render_debug_pal(ui_debug_pal);
208 break;
209 case UI_ENTER_DEBUGGER:
210 break_on_sync = 1;
211 break;
212 }
213 break;
214 }
215 }
216
217 void handle_keyup(int keycode)
218 {
219 int bucket = keycode >> 8 & 0xFF;
220 if (!bindings[bucket]) {
221 return;
222 }
223 int idx = keycode & 0xFF;
224 keybinding * binding = bindings[bucket] + idx;
225 handle_binding_up(binding);
226 }
227
228 void handle_joyup(int joystick, int button)
229 {
230 if (!joybindings[joystick]) {
231 return;
232 }
233 keybinding * binding = joybindings[joystick] + button;
234 handle_binding_up(binding);
235 }
236
237 void handle_joy_dpad(int joystick, int dpadnum, uint8_t value)
238 {
239 if (!joydpads[joystick]) {
240 return;
241 }
242 joydpad * dpad = joydpads[joystick] + dpadnum;
243 uint8_t newdown = (value ^ dpad->state) & value;
244 uint8_t newup = ((~value) ^ (~dpad->state)) & (~value);
245 dpad->state = value;
246 for (int i = 0; i < 4; i++) {
247 if (newdown & dpadbits[i]) {
248 handle_binding_down(dpad->bindings + i);
249 } else if(newup & dpadbits[i]) {
250 handle_binding_up(dpad->bindings + i);
251 }
252 }
253 }
254
255 void set_keybindings()
256 {
257 bind_gamepad(RENDERKEY_UP, 1, DPAD_UP);
258 bind_gamepad(RENDERKEY_DOWN, 1, DPAD_DOWN);
259 bind_gamepad(RENDERKEY_LEFT, 1, DPAD_LEFT);
260 bind_gamepad(RENDERKEY_RIGHT, 1, DPAD_RIGHT);
261 bind_gamepad('a', 1, BUTTON_A);
262 bind_gamepad('s', 1, BUTTON_B);
263 bind_gamepad('d', 1, BUTTON_C);
264 bind_gamepad('q', 1, BUTTON_X);
265 bind_gamepad('w', 1, BUTTON_Y);
266 bind_gamepad('e', 1, BUTTON_Z);
267 bind_gamepad('\r', 1, BUTTON_START);
268 bind_gamepad('f', 1, BUTTON_MODE);
269 bind_ui('[', UI_DEBUG_MODE_INC);
270 bind_ui(']', UI_DEBUG_PAL_INC);
271 bind_ui('u', UI_ENTER_DEBUGGER);
272
273 bind_dpad_gamepad(0, 0, RENDER_DPAD_UP, 2, DPAD_UP);
274 bind_dpad_gamepad(0, 0, RENDER_DPAD_DOWN, 2, DPAD_DOWN);
275 bind_dpad_gamepad(0, 0, RENDER_DPAD_LEFT, 2, DPAD_LEFT);
276 bind_dpad_gamepad(0, 0, RENDER_DPAD_RIGHT, 2, DPAD_RIGHT);
277 bind_button_gamepad(0, 0, 2, BUTTON_A);
278 bind_button_gamepad(0, 1, 2, BUTTON_B);
279 bind_button_gamepad(0, 2, 2, BUTTON_C);
280 bind_button_gamepad(0, 3, 2, BUTTON_X);
281 bind_button_gamepad(0, 4, 2, BUTTON_Y);
282 bind_button_gamepad(0, 5, 2, BUTTON_Z);
283 bind_button_gamepad(0, 6, 2, BUTTON_START);
284 bind_button_gamepad(0, 7, 2, BUTTON_MODE);
285 }
286
287 #define TH 0x40
288 #define TH_TIMEOUT 8000
289
290 void io_adjust_cycles(io_port * pad, uint32_t current_cycle, uint32_t deduction)
291 {
292 /*uint8_t control = pad->control | 0x80;
293 uint8_t th = control & pad->output;
294 if (pad->input[GAMEPAD_TH0] || pad->input[GAMEPAD_TH1]) {
295 printf("adjust_cycles | control: %X, TH: %X, GAMEPAD_TH0: %X, GAMEPAD_TH1: %X, TH Counter: %d, Timeout: %d, Cycle: %d\n", control, th, pad->input[GAMEPAD_TH0], pad->input[GAMEPAD_TH1], pad->th_counter,pad->timeout_cycle, current_cycle);
296 }*/
297 if (current_cycle >= pad->timeout_cycle) {
298 pad->th_counter = 0;
299 } else {
300 pad->timeout_cycle -= deduction;
301 }
302 }
303
304 void io_data_write(io_port * pad, uint8_t value, uint32_t current_cycle)
305 {
306 if (pad->control & TH) {
307 //check if TH has changed
308 if ((pad->output & TH) ^ (value & TH)) {
309 if (current_cycle >= pad->timeout_cycle) {
310 pad->th_counter = 0;
311 }
312 if (!(value & TH)) {
313 pad->th_counter++;
314 }
315 pad->timeout_cycle = current_cycle + TH_TIMEOUT;
316 }
317 }
318 pad->output = value;
319 }
320
321 uint8_t io_data_read(io_port * pad, uint32_t current_cycle)
322 {
323 uint8_t control = pad->control | 0x80;
324 uint8_t th = control & pad->output;
325 uint8_t input;
326 if (current_cycle >= pad->timeout_cycle) {
327 pad->th_counter = 0;
328 }
329 /*if (pad->input[GAMEPAD_TH0] || pad->input[GAMEPAD_TH1]) {
330 printf("io_data_read | control: %X, TH: %X, GAMEPAD_TH0: %X, GAMEPAD_TH1: %X, TH Counter: %d, Timeout: %d, Cycle: %d\n", control, th, pad->input[GAMEPAD_TH0], pad->input[GAMEPAD_TH1], pad->th_counter,pad->timeout_cycle, context->current_cycle);
331 }*/
332 if (th) {
333 if (pad->th_counter == 3) {
334 input = pad->input[GAMEPAD_EXTRA];
335 } else {
336 input = pad->input[GAMEPAD_TH1];
337 }
338 } else {
339 if (pad->th_counter == 3) {
340 input = pad->input[GAMEPAD_TH0] | 0xF;
341 } else if(pad->th_counter == 4) {
342 input = pad->input[GAMEPAD_TH0] & 0x30;
343 } else {
344 input = pad->input[GAMEPAD_TH0] | 0xC;
345 }
346 }
347 uint8_t value = ((~input) & (~control)) | (pad->output & control);
348 /*if (pad->input[GAMEPAD_TH0] || pad->input[GAMEPAD_TH1]) {
349 printf ("value: %X\n", value);
350 }*/
351 return value;
352 }
353
354