1 /*
2 * joyport.c - control port handling.
3 *
4 * Written by
5 * Marco van den Heuvel <blackystardust68@yahoo.com>
6 *
7 * This file is part of VICE, the Versatile Commodore Emulator.
8 * See README for copyright notice.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
23 * 02111-1307 USA.
24 *
25 */
26
27 #include "vice.h"
28
29 #include <string.h>
30
31 #include "cmdline.h"
32 #include "joyport.h"
33 #include "lib.h"
34 #include "resources.h"
35 #include "uiapi.h"
36 #include "util.h"
37
38 static joyport_t joyport_device[JOYPORT_MAX_DEVICES];
39 static uint8_t joyport_display[6] = { 0, 0, 0, 0, 0, 0};
40
41 static int joy_port[JOYPORT_MAX_PORTS];
42 static joyport_port_props_t port_props[JOYPORT_MAX_PORTS];
43 static int pot_port_mask = 1;
44
45 static uint8_t joyport_dig_stored[JOYPORT_MAX_PORTS];
46
47 typedef struct resid2text_s {
48 int resid;
49 char *text;
50 } resid2text_t;
51
52 static resid2text_t ids[] = {
53 { JOYPORT_RES_ID_MOUSE, "host mouse" },
54 { JOYPORT_RES_ID_SAMPLER, "host sampler (audio input device)" },
55 { -1, NULL }
56 };
57
res2text(int joyport_id)58 static char *res2text(int joyport_id)
59 {
60 int i;
61 char *retval = "Unknown joyport resource";
62
63 for (i = 0; ids[i].resid != -1; ++i) {
64 if (ids[i].resid == joyport_id) {
65 retval = ids[i].text;
66 }
67 }
68 return retval;
69 }
70
set_joyport_pot_mask(int mask)71 void set_joyport_pot_mask(int mask)
72 {
73 pot_port_mask = mask;
74 }
75
joyport_set_device(int port,int id)76 static int joyport_set_device(int port, int id)
77 {
78 int i;
79
80 /* 1st some sanity checks */
81 if (id < JOYPORT_ID_NONE || id >= JOYPORT_MAX_DEVICES) {
82 return -1;
83 }
84 if (port < 0 || port >= JOYPORT_MAX_PORTS) {
85 return -1;
86 }
87
88 /* Nothing changes */
89 if (id == joy_port[port]) {
90 return 0;
91 }
92
93 /* check if port is present */
94 if (!port_props[port].name) {
95 ui_error("Selected port (%d) is not present on this emulator", port);
96 return -1;
97 }
98
99 /* check if id is registered */
100 if (id != JOYPORT_ID_NONE && !joyport_device[id].name) {
101 ui_error("Selected control port device %d is not registered", id);
102 return -1;
103 }
104
105 /* check if id conflicts with devices on other ports */
106 if (id != JOYPORT_ID_NONE && id != JOYPORT_ID_JOYSTICK) {
107 for (i = 0; i < JOYPORT_MAX_PORTS; ++i) {
108 if (port != i && joy_port[i] == id) {
109 ui_error("Selected control port device %s on %s is already attached to %s", joyport_device[id].name, port_props[port].name, port_props[i].name);
110 return -1;
111 }
112 }
113 }
114
115 /* check if input resource conflicts with device on the other port */
116 if (id != JOYPORT_ID_NONE && id != JOYPORT_ID_JOYSTICK && joyport_device[id].resource_id != JOYPORT_RES_ID_NONE) {
117 for (i = 0; i < JOYPORT_MAX_PORTS; ++i) {
118 if (port != i && joyport_device[id].resource_id == joyport_device[joy_port[i]].resource_id) {
119 ui_error("Selected control port device %s on %s uses same host input resource (%s) as the device attached to %s", joyport_device[id].name, port_props[port].name, res2text(joyport_device[id].resource_id), port_props[i].name);
120 return -1;
121 }
122 }
123 }
124
125 /* check if device can be connected to this port */
126 if (id != JOYPORT_ID_NONE && id != JOYPORT_ID_JOYSTICK && joyport_device[id].is_lp && !port_props[port].has_lp_support) {
127 ui_error("Selected control port device %s cannot be attached to %s", joyport_device[id].name, port_props[port].name);
128 return -1;
129 }
130
131 /* all checks done, now disable the current device and enable the new device */
132 if (joyport_device[joy_port[port]].enable) {
133 joyport_device[joy_port[port]].enable(port, 0);
134 }
135 if (joyport_device[id].enable) {
136 joyport_device[id].enable(port, id);
137 }
138 joy_port[port] = id;
139
140 return 0;
141 }
142
joyport_clear_devices(void)143 void joyport_clear_devices(void)
144 {
145 int i;
146
147 for (i = 0; i < JOYPORT_MAX_PORTS; ++i) {
148 if (port_props[i].name) {
149 joyport_set_device(i, JOYPORT_ID_NONE);
150 }
151 }
152 }
153
read_joyport_dig(int port)154 uint8_t read_joyport_dig(int port)
155 {
156 int id = joy_port[port];
157
158 if (id == JOYPORT_ID_NONE) {
159 return 0xff;
160 }
161
162 if (!joyport_device[id].read_digital) {
163 return 0xff;
164 }
165 return joyport_device[id].read_digital(port);
166 }
167
store_joyport_dig(int port,uint8_t val,uint8_t mask)168 void store_joyport_dig(int port, uint8_t val, uint8_t mask)
169 {
170 int id = joy_port[port];
171 uint8_t store_val;
172
173 if (id == JOYPORT_ID_NONE) {
174 return;
175 }
176
177 if (!joyport_device[id].store_digital) {
178 return;
179 }
180
181 store_val = joyport_dig_stored[port];
182
183 store_val &= (uint8_t)~mask;
184 store_val |= val;
185
186 joyport_device[id].store_digital(store_val);
187
188 joyport_dig_stored[port] = store_val;
189 }
190
191 static int pot_port1 = -1;
192 static int pot_port2 = -1;
193
find_pot_ports(void)194 static void find_pot_ports(void)
195 {
196 int i;
197
198 for (i = 0; i < JOYPORT_MAX_PORTS; ++i) {
199 if (port_props[i].has_pot) {
200 if (pot_port1 == -1) {
201 pot_port1 = i;
202 } else {
203 pot_port2 = i;
204 }
205 }
206 }
207 if (pot_port1 == -1) {
208 pot_port1 = -2;
209 }
210 if (pot_port2 == -1) {
211 pot_port2 = -2;
212 }
213 }
214
read_joyport_potx(void)215 uint8_t read_joyport_potx(void)
216 {
217 int id1 = JOYPORT_ID_NONE;
218 int id2 = JOYPORT_ID_NONE;
219 uint8_t ret1 = 0xff;
220 uint8_t ret2 = 0xff;
221
222 /* first find the pot ports if needed */
223 if (pot_port1 == -1 || pot_port2 == -1) {
224 find_pot_ports();
225 }
226
227 if (pot_port_mask == 1 || pot_port_mask == 3) {
228 if (pot_port1 != -2) {
229 id1 = joy_port[pot_port1];
230 }
231 }
232
233 if (pot_port_mask == 2 || pot_port_mask == 3) {
234 if (pot_port2 != -2) {
235 id2 = joy_port[pot_port2];
236 }
237 }
238
239 if (id1 != JOYPORT_ID_NONE) {
240 if (joyport_device[id1].read_potx) {
241 ret1 = joyport_device[id1].read_potx();
242 }
243 }
244
245 if (id2 != JOYPORT_ID_NONE) {
246 if (joyport_device[id2].read_potx) {
247 ret2 = joyport_device[id2].read_potx();
248 }
249 }
250
251 switch (pot_port_mask) {
252 case 1:
253 return ret1;
254 case 2:
255 return ret2;
256 case 3:
257 return ret1 & ret2;
258 default:
259 return 0xff;
260 }
261 }
262
read_joyport_poty(void)263 uint8_t read_joyport_poty(void)
264 {
265 int id1 = JOYPORT_ID_NONE;
266 int id2 = JOYPORT_ID_NONE;
267 uint8_t ret1 = 0xff;
268 uint8_t ret2 = 0xff;
269
270 /* first find the pot ports if needed */
271 if (pot_port1 == -1 || pot_port2 == -1) {
272 find_pot_ports();
273 }
274
275 if (pot_port_mask == 1 || pot_port_mask == 3) {
276 if (pot_port1 != -2) {
277 id1 = joy_port[pot_port1];
278 }
279 }
280
281 if (pot_port_mask == 2 || pot_port_mask == 3) {
282 if (pot_port2 != -2) {
283 id2 = joy_port[pot_port2];
284 }
285 }
286
287 if (id1 != JOYPORT_ID_NONE) {
288 if (joyport_device[id1].read_poty) {
289 ret1 = joyport_device[id1].read_poty();
290 }
291 }
292
293 if (id2 != JOYPORT_ID_NONE) {
294 if (joyport_device[id2].read_poty) {
295 ret2 = joyport_device[id2].read_poty();
296 }
297 }
298
299 switch (pot_port_mask) {
300 case 1:
301 return ret1;
302 case 2:
303 return ret2;
304 case 3:
305 return ret1 & ret2;
306 default:
307 return 0xff;
308 }
309 }
310
311 static int pot_present = -1;
312
joyport_device_register(int id,joyport_t * device)313 int joyport_device_register(int id, joyport_t *device)
314 {
315 int i;
316
317 if (id < 1 || id > JOYPORT_MAX_DEVICES) {
318 return -1;
319 }
320
321 /* check for pot ports if needed */
322 if (pot_present == -1) {
323 for (i = 0; i < JOYPORT_MAX_PORTS && pot_present == -1; ++i) {
324 if (port_props[i].has_pot) {
325 pot_present = 1;
326 }
327 }
328 if (pot_present == -1) {
329 pot_present = 0;
330 }
331 }
332
333 /* skip pot devices if no pot is present */
334 if ((device->read_potx || device->read_poty) && !pot_present && !device->pot_optional) {
335 return 0;
336 }
337
338 joyport_device[id].name = device->name;
339 joyport_device[id].resource_id = device->resource_id;
340 joyport_device[id].is_lp = device->is_lp;
341 joyport_device[id].pot_optional = device->pot_optional;
342 joyport_device[id].enable = device->enable;
343 joyport_device[id].read_digital = device->read_digital;
344 joyport_device[id].store_digital = device->store_digital;
345 joyport_device[id].read_potx = device->read_potx;
346 joyport_device[id].read_poty = device->read_poty;
347 joyport_device[id].write_snapshot = device->write_snapshot;
348 joyport_device[id].read_snapshot = device->read_snapshot;
349 return 0;
350 }
351
joyport_port_register(int port,joyport_port_props_t * props)352 int joyport_port_register(int port, joyport_port_props_t *props)
353 {
354 if (port < 0 || port >= JOYPORT_MAX_PORTS) {
355 return -1;
356 }
357
358 if (!port) {
359 memset(port_props, 0, sizeof(port_props));
360 }
361
362 port_props[port].name = props->name;
363 port_props[port].has_pot = props->has_pot;
364 port_props[port].has_lp_support = props->has_lp_support;
365 port_props[port].active = props->active;
366
367 return 0;
368 }
369
check_valid_lightpen(int port,int index)370 static int check_valid_lightpen(int port, int index)
371 {
372 if (!joyport_device[index].is_lp) {
373 return 1;
374 }
375 if (port_props[port].has_lp_support) {
376 return 1;
377 }
378 return 0;
379 }
380
check_valid_pot(int port,int index)381 static int check_valid_pot(int port, int index)
382 {
383 if (!joyport_device[index].read_potx && !joyport_device[index].read_poty) {
384 return 1;
385 }
386 if (port_props[port].has_pot || joyport_device[index].pot_optional) {
387 return 1;
388 }
389 return 0;
390 }
391
joyport_get_valid_devices(int port)392 joyport_desc_t *joyport_get_valid_devices(int port)
393 {
394 joyport_desc_t *retval = NULL;
395 int i;
396 int valid = 0;
397 int j = 0;
398
399 for (i = 0; i < JOYPORT_MAX_DEVICES; ++i) {
400 if (joyport_device[i].name) {
401 if (check_valid_lightpen(port, i) && check_valid_pot(port, i)) {
402 ++valid;
403 }
404 }
405 }
406
407 retval = lib_malloc(((size_t)valid + 1) * sizeof(joyport_desc_t));
408 for (i = 0; i < JOYPORT_MAX_DEVICES; ++i) {
409 if (joyport_device[i].name) {
410 if (check_valid_lightpen(port, i) && check_valid_pot(port, i)) {
411 retval[j].name = joyport_device[i].name;
412 retval[j].id = i;
413 ++j;
414 }
415 }
416 }
417 retval[j].name = NULL;
418
419 return retval;
420 }
421
joyport_display_joyport(int id,uint8_t status)422 void joyport_display_joyport(int id, uint8_t status)
423 {
424 if (id == JOYPORT_ID_JOY1 || id == JOYPORT_ID_JOY2 || id == JOYPORT_ID_JOY3 || id == JOYPORT_ID_JOY4 || id == JOYPORT_ID_JOY5) {
425 if (id == JOYPORT_ID_JOY1 && joy_port[0] == JOYPORT_ID_JOYSTICK) {
426 joyport_display[1] = status;
427 }
428 if (id == JOYPORT_ID_JOY2 && joy_port[1] == JOYPORT_ID_JOYSTICK) {
429 joyport_display[2] = status;
430 }
431 if (id == JOYPORT_ID_JOY3 && joy_port[2] == JOYPORT_ID_JOYSTICK) {
432 joyport_display[3] = status;
433 }
434 if (id == JOYPORT_ID_JOY4 && joy_port[3] == JOYPORT_ID_JOYSTICK) {
435 joyport_display[4] = status;
436 }
437 if (id == JOYPORT_ID_JOY5 && joy_port[4] == JOYPORT_ID_JOYSTICK) {
438 joyport_display[5] = status;
439 }
440 } else {
441 if (id != joy_port[0] && id != joy_port[1] && id != joy_port[2] && id != joy_port[3] && id != joy_port[4]) {
442 return;
443 }
444
445 if (id == joy_port[0]) {
446 joyport_display[1] = status;
447 }
448
449 if (id == joy_port[1]) {
450 joyport_display[2] = status;
451 }
452
453 if (id == joy_port[2]) {
454 joyport_display[3] = status;
455 }
456
457 if (id == joy_port[3]) {
458 joyport_display[4] = status;
459 }
460
461 if (id == joy_port[4]) {
462 joyport_display[5] = status;
463 }
464 }
465 ui_display_joyport(joyport_display);
466 }
467
joyport_get_port_name(int port)468 char *joyport_get_port_name(int port)
469 {
470 return port_props[port].name;
471 }
472
473 /* ------------------------------------------------------------------------- */
474
set_joyport_device(int val,void * param)475 static int set_joyport_device(int val, void *param)
476 {
477 int port = vice_ptr_to_int(param);
478
479 return joyport_set_device(port, val);
480 }
481
482 static const resource_int_t resources_int_port1[] = {
483 { "JoyPort1Device", JOYPORT_ID_JOYSTICK, RES_EVENT_NO, NULL,
484 &joy_port[JOYPORT_1], set_joyport_device, (void *)JOYPORT_1 },
485 RESOURCE_INT_LIST_END
486 };
487
488 static const resource_int_t resources_int_port2[] = {
489 { "JoyPort2Device", JOYPORT_ID_JOYSTICK, RES_EVENT_NO, NULL,
490 &joy_port[JOYPORT_2], set_joyport_device, (void *)JOYPORT_2 },
491 RESOURCE_INT_LIST_END
492 };
493
494 static const resource_int_t resources_int_port3[] = {
495 { "JoyPort3Device", JOYPORT_ID_JOYSTICK, RES_EVENT_NO, NULL,
496 &joy_port[JOYPORT_3], set_joyport_device, (void *)JOYPORT_3 },
497 RESOURCE_INT_LIST_END
498 };
499
500 static const resource_int_t resources_int_port4[] = {
501 { "JoyPort4Device", JOYPORT_ID_JOYSTICK, RES_EVENT_NO, NULL,
502 &joy_port[JOYPORT_4], set_joyport_device, (void *)JOYPORT_4 },
503 RESOURCE_INT_LIST_END
504 };
505
506 static const resource_int_t resources_int_port5[] = {
507 { "JoyPort5Device", JOYPORT_ID_JOYSTICK, RES_EVENT_NO, NULL,
508 &joy_port[JOYPORT_5], set_joyport_device, (void *)JOYPORT_5 },
509 RESOURCE_INT_LIST_END
510 };
511
joyport_resources_init(void)512 int joyport_resources_init(void)
513 {
514 int i;
515
516 memset(joyport_device, 0, sizeof(joyport_device));
517 joyport_device[0].name = "None";
518 joyport_device[0].is_lp = JOYPORT_IS_NOT_LIGHTPEN;
519 for (i = 0; i < JOYPORT_MAX_PORTS; ++i) {
520 joy_port[i] = JOYPORT_ID_NONE;
521 }
522
523 if (port_props[JOYPORT_5].name) {
524 if (resources_register_int(resources_int_port5) < 0) {
525 return -1;
526 }
527 }
528
529 if (port_props[JOYPORT_4].name) {
530 if (resources_register_int(resources_int_port4) < 0) {
531 return -1;
532 }
533 }
534
535 if (port_props[JOYPORT_3].name) {
536 if (resources_register_int(resources_int_port3) < 0) {
537 return -1;
538 }
539 }
540
541 if (port_props[JOYPORT_2].name) {
542 if (resources_register_int(resources_int_port2) < 0) {
543 return -1;
544 }
545 }
546
547 if (port_props[JOYPORT_1].name) {
548 if (resources_register_int(resources_int_port1) < 0) {
549 return -1;
550 }
551 }
552
553 return 0;
554 }
555
556 /* ------------------------------------------------------------------------- */
557
558 struct joyport_opt_s {
559 const char *name;
560 int id;
561 };
562
563 static struct joyport_opt_s id_match[] = {
564 { "0", JOYPORT_ID_NONE },
565 { "none", JOYPORT_ID_NONE },
566 { "1", JOYPORT_ID_JOYSTICK },
567 { "joy", JOYPORT_ID_JOYSTICK },
568 { "joystick", JOYPORT_ID_JOYSTICK },
569 { "2", JOYPORT_ID_PADDLES },
570 { "paddles", JOYPORT_ID_PADDLES },
571 { "3", JOYPORT_ID_MOUSE_1351 },
572 { "1351", JOYPORT_ID_MOUSE_1351 },
573 { "1351mouse", JOYPORT_ID_MOUSE_1351 },
574 { "4", JOYPORT_ID_MOUSE_NEOS },
575 { "neos", JOYPORT_ID_MOUSE_NEOS },
576 { "neosmouse", JOYPORT_ID_MOUSE_NEOS },
577 { "5", JOYPORT_ID_MOUSE_AMIGA },
578 { "amiga", JOYPORT_ID_MOUSE_AMIGA },
579 { "amigamouse", JOYPORT_ID_MOUSE_AMIGA },
580 { "6", JOYPORT_ID_MOUSE_CX22 },
581 { "cx22", JOYPORT_ID_MOUSE_CX22 },
582 { "cx22mouse", JOYPORT_ID_MOUSE_CX22 },
583 { "7", JOYPORT_ID_MOUSE_ST },
584 { "st", JOYPORT_ID_MOUSE_ST },
585 { "atarist", JOYPORT_ID_MOUSE_ST },
586 { "stmouse", JOYPORT_ID_MOUSE_ST },
587 { "ataristmouse", JOYPORT_ID_MOUSE_ST },
588 { "8", JOYPORT_ID_MOUSE_SMART },
589 { "smart", JOYPORT_ID_MOUSE_SMART },
590 { "smartmouse", JOYPORT_ID_MOUSE_SMART },
591 { "9", JOYPORT_ID_MOUSE_MICROMYS },
592 { "micromys", JOYPORT_ID_MOUSE_MICROMYS },
593 { "micromysmouse", JOYPORT_ID_MOUSE_MICROMYS },
594 { "10", JOYPORT_ID_KOALAPAD },
595 { "koalapad", JOYPORT_ID_KOALAPAD },
596 { "11", JOYPORT_ID_LIGHTPEN_U },
597 { "lpup", JOYPORT_ID_LIGHTPEN_U },
598 { "lightpenup", JOYPORT_ID_LIGHTPEN_U },
599 { "12", JOYPORT_ID_LIGHTPEN_L },
600 { "lpleft", JOYPORT_ID_LIGHTPEN_L },
601 { "lightpenleft", JOYPORT_ID_LIGHTPEN_L },
602 { "13", JOYPORT_ID_LIGHTPEN_DATEL },
603 { "lpdatel", JOYPORT_ID_LIGHTPEN_DATEL },
604 { "lightpendatel", JOYPORT_ID_LIGHTPEN_DATEL },
605 { "datellightpen", JOYPORT_ID_LIGHTPEN_DATEL },
606 { "14", JOYPORT_ID_LIGHTGUN_Y },
607 { "magnum", JOYPORT_ID_LIGHTGUN_Y },
608 { "15", JOYPORT_ID_LIGHTGUN_L },
609 { "stack", JOYPORT_ID_LIGHTGUN_L },
610 { "slr", JOYPORT_ID_LIGHTGUN_L },
611 { "16", JOYPORT_ID_LIGHTPEN_INKWELL },
612 { "lpinkwell", JOYPORT_ID_LIGHTPEN_INKWELL },
613 { "lightpeninkwell", JOYPORT_ID_LIGHTPEN_INKWELL },
614 { "inkwelllightpen", JOYPORT_ID_LIGHTPEN_INKWELL },
615 { "17", JOYPORT_ID_SAMPLER_2BIT },
616 { "2bitsampler", JOYPORT_ID_SAMPLER_2BIT },
617 { "18", JOYPORT_ID_SAMPLER_4BIT },
618 { "4bitsampler", JOYPORT_ID_SAMPLER_4BIT },
619 { "19", JOYPORT_ID_BBRTC },
620 { "bbrtc", JOYPORT_ID_BBRTC },
621 { "20", JOYPORT_ID_PAPERCLIP64 },
622 { "paperclip64", JOYPORT_ID_PAPERCLIP64 },
623 { "paperclip", JOYPORT_ID_PAPERCLIP64 },
624 { "pc64", JOYPORT_ID_PAPERCLIP64 },
625 { "snespad", JOYPORT_ID_SNESPAD },
626 { NULL, -1 }
627 };
628
set_joyport_cmdline_device(const char * param,void * extra_param)629 static int set_joyport_cmdline_device(const char *param, void *extra_param)
630 {
631 int temp = -1;
632 int i = 0;
633 int port = vice_ptr_to_int(extra_param);
634
635 if (!param) {
636 return -1;
637 }
638
639 do {
640 if (strcmp(id_match[i].name, param) == 0) {
641 temp = id_match[i].id;
642 }
643 i++;
644 } while ((temp == -1) && (id_match[i].name != NULL));
645
646 if (temp == -1) {
647 return -1;
648 }
649
650 return set_joyport_device(temp, int_to_void_ptr(port));
651 }
652
653 /* ------------------------------------------------------------------------- */
654
build_joyport_string(int port)655 static char *build_joyport_string(int port)
656 {
657 int i = 0;
658 char *tmp1;
659 char *tmp2;
660 char number[4];
661 joyport_desc_t *devices = joyport_get_valid_devices(port);
662
663 tmp1 = lib_msprintf("Set %s device (0: None", port_props[port].name);
664
665 for (i = 1; devices[i].name; ++i) {
666 sprintf(number, "%d", devices[i].id);
667 tmp2 = util_concat(tmp1, ", ", number, ": ", devices[i].name, NULL);
668 lib_free(tmp1);
669 tmp1 = tmp2;
670 }
671 tmp2 = util_concat(tmp1, ")", NULL);
672 lib_free(tmp1);
673 lib_free(devices);
674 return tmp2;
675 }
676
677 static cmdline_option_t cmdline_options_port1[] =
678 {
679 { "-controlport1device", CALL_FUNCTION, CMDLINE_ATTRIB_NEED_ARGS | CMDLINE_ATTRIB_DYNAMIC_DESCRIPTION,
680 set_joyport_cmdline_device, (void *)JOYPORT_1, NULL, NULL,
681 "Device", NULL },
682 CMDLINE_LIST_END
683 };
684
685 static cmdline_option_t cmdline_options_port2[] =
686 {
687 { "-controlport2device", CALL_FUNCTION, CMDLINE_ATTRIB_NEED_ARGS | CMDLINE_ATTRIB_DYNAMIC_DESCRIPTION,
688 set_joyport_cmdline_device, (void *)JOYPORT_2, NULL, NULL,
689 "Device", NULL },
690 CMDLINE_LIST_END
691 };
692
693 static cmdline_option_t cmdline_options_port3[] =
694 {
695 { "-controlport3device", CALL_FUNCTION, CMDLINE_ATTRIB_NEED_ARGS | CMDLINE_ATTRIB_DYNAMIC_DESCRIPTION,
696 set_joyport_cmdline_device, (void *)JOYPORT_3, NULL, NULL,
697 "Device", NULL },
698 CMDLINE_LIST_END
699 };
700
701 static cmdline_option_t cmdline_options_port4[] =
702 {
703 { "-controlport4device", CALL_FUNCTION, CMDLINE_ATTRIB_NEED_ARGS | CMDLINE_ATTRIB_DYNAMIC_DESCRIPTION,
704 set_joyport_cmdline_device, (void *)JOYPORT_4, NULL, NULL,
705 "Device", NULL },
706 CMDLINE_LIST_END
707 };
708
709 static cmdline_option_t cmdline_options_port5[] =
710 {
711 { "-controlport5device", CALL_FUNCTION, CMDLINE_ATTRIB_NEED_ARGS | CMDLINE_ATTRIB_DYNAMIC_DESCRIPTION,
712 set_joyport_cmdline_device, (void *)JOYPORT_5, NULL, NULL,
713 "Device", NULL },
714 CMDLINE_LIST_END
715 };
716
joyport_cmdline_options_init(void)717 int joyport_cmdline_options_init(void)
718 {
719 union char_func cf;
720
721 if (port_props[JOYPORT_1].name) {
722 cf.f = build_joyport_string;
723 cmdline_options_port1[0].description = cf.c;
724 cmdline_options_port1[0].attributes |= (JOYPORT_1 << 8);
725 if (cmdline_register_options(cmdline_options_port1) < 0) {
726 return -1;
727 }
728 }
729
730 if (port_props[JOYPORT_2].name) {
731 cf.f = build_joyport_string;
732 cmdline_options_port2[0].description = cf.c;
733 cmdline_options_port2[0].attributes |= (JOYPORT_2 << 8);
734 if (cmdline_register_options(cmdline_options_port2) < 0) {
735 return -1;
736 }
737 }
738
739 if (port_props[JOYPORT_3].name) {
740 cf.f = build_joyport_string;
741 cmdline_options_port3[0].description = cf.c;
742 cmdline_options_port3[0].attributes |= (JOYPORT_3 << 8);
743 if (cmdline_register_options(cmdline_options_port3) < 0) {
744 return -1;
745 }
746 }
747
748 if (port_props[JOYPORT_4].name) {
749 cf.f = build_joyport_string;
750 cmdline_options_port4[0].description = cf.c;
751 cmdline_options_port4[0].attributes |= (JOYPORT_4 << 8);
752 if (cmdline_register_options(cmdline_options_port4) < 0) {
753 return -1;
754 }
755 }
756
757 if (port_props[JOYPORT_5].name) {
758 cf.f = build_joyport_string;
759 cmdline_options_port5[0].description = cf.c;
760 cmdline_options_port5[0].attributes |= (JOYPORT_5 << 8);
761 if (cmdline_register_options(cmdline_options_port5) < 0) {
762 return -1;
763 }
764 }
765 return 0;
766 }
767
768 /* ------------------------------------------------------------------------- */
769
770 #define DUMP_VER_MAJOR 0
771 #define DUMP_VER_MINOR 0
772
joyport_snapshot_write_module(struct snapshot_s * s,int port)773 int joyport_snapshot_write_module(struct snapshot_s *s, int port)
774 {
775 snapshot_module_t *m;
776 char snapshot_name[16];
777
778 sprintf(snapshot_name, "JOYPORT%d", port);
779
780 m = snapshot_module_create(s, snapshot_name, DUMP_VER_MAJOR, DUMP_VER_MINOR);
781
782 if (m == NULL) {
783 return -1;
784 }
785
786 /* save device id */
787 if (SMW_B(m, (uint8_t)joy_port[port]) < 0) {
788 snapshot_module_close(m);
789 return -1;
790 }
791
792 snapshot_module_close(m);
793
794 /* save seperate joyport device module */
795 switch (joy_port[port]) {
796 case JOYPORT_ID_NONE:
797 break;
798 default:
799 if (joyport_device[joy_port[port]].write_snapshot) {
800 if (joyport_device[joy_port[port]].write_snapshot(s, port) < 0) {
801 return -1;
802 }
803 }
804 break;
805 }
806
807 return 0;
808 }
809
joyport_snapshot_read_module(struct snapshot_s * s,int port)810 int joyport_snapshot_read_module(struct snapshot_s *s, int port)
811 {
812 uint8_t major_version, minor_version;
813 snapshot_module_t *m;
814 int temp_joy_port;
815 char snapshot_name[16];
816
817 sprintf(snapshot_name, "JOYPORT%d", port);
818
819 m = snapshot_module_open(s, snapshot_name, &major_version, &minor_version);
820 if (m == NULL) {
821 return -1;
822 }
823
824 if (major_version != DUMP_VER_MAJOR || minor_version != DUMP_VER_MINOR) {
825 snapshot_module_close(m);
826 return -1;
827 }
828
829 /* load device id */
830 if (SMR_B_INT(m, &temp_joy_port) < 0) {
831 snapshot_module_close(m);
832 return -1;
833 }
834
835 snapshot_module_close(m);
836
837 /* enable device */
838 joyport_set_device(port, temp_joy_port);
839
840 /* load device snapshot */
841 switch (joy_port[port]) {
842 case JOYPORT_ID_NONE:
843 break;
844 default:
845 if (joyport_device[joy_port[port]].read_snapshot) {
846 if (joyport_device[joy_port[port]].read_snapshot(s, port) < 0) {
847 return -1;
848 }
849 }
850 break;
851 }
852
853 return 0;
854 }
855