Mercurial > repos > blastem
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 |