1 /* joystick.c: Joystick emulation support
2    Copyright (c) 2001-2016 Russell Marks, Darren Salt, Philip Kendall
3    Copyright (c) 2015 Stuart Brady
4 
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9 
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14 
15    You should have received a copy of the GNU General Public License along
16    with this program; if not, write to the Free Software Foundation, Inc.,
17    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 
19    Author contact information:
20 
21    E-mail: philip-fuse@shadowmagic.org.uk
22 
23 */
24 
25 #include <config.h>
26 
27 #include <libspectrum.h>
28 
29 #include "fuse.h"
30 #include "infrastructure/startup_manager.h"
31 #include "joystick.h"
32 #include "keyboard.h"
33 #include "module.h"
34 #include "periph.h"
35 #include "rzx.h"
36 #include "settings.h"
37 #include "spectrum.h"
38 #include "machine.h"
39 #include "ui/ui.h"
40 #include "ui/uijoystick.h"
41 
42 /* Number of joysticks known about & initialised */
43 int joysticks_supported = 0;
44 
45 /* The bit masks used by the various joysticks. The order is the same
46    as the ordering of buttons in joystick.h:joystick_button (left,
47    right, up, down, fire ) */
48 static const libspectrum_byte kempston_mask[5] =
49   { 0x02, 0x01, 0x08, 0x04, 0x10 };
50 static const libspectrum_byte timex_mask[5] =
51   { 0x04, 0x08, 0x01, 0x02, 0x80 };
52 
53 /* The keys used by the Cursor joystick */
54 static const keyboard_key_name cursor_key[5] =
55   { KEYBOARD_5, KEYBOARD_8, KEYBOARD_7, KEYBOARD_6, KEYBOARD_0 };
56 
57 /* The keys used by the two Sinclair joysticks */
58 static const keyboard_key_name sinclair1_key[5] =
59   { KEYBOARD_6, KEYBOARD_7, KEYBOARD_9, KEYBOARD_8, KEYBOARD_0 };
60 static const keyboard_key_name sinclair2_key[5] =
61   { KEYBOARD_1, KEYBOARD_2, KEYBOARD_4, KEYBOARD_3, KEYBOARD_5 };
62 
63 /* The current values for the joysticks we can emulate */
64 static libspectrum_byte kempston_value;
65 static libspectrum_byte timex1_value;
66 static libspectrum_byte timex2_value;
67 static libspectrum_byte fuller_value;
68 
69 /* The names of the joysticks we can emulate. Order must correspond to
70    that of joystick.h:joystick_type_t */
71 const char *joystick_name[ JOYSTICK_TYPE_COUNT ] = {
72   "None",
73   "Cursor",
74   "Kempston",
75   "Sinclair 1", "Sinclair 2",
76   "Timex 1", "Timex 2",
77   "Fuller"
78 };
79 
80 const char *joystick_connection[ JOYSTICK_CONN_COUNT ] = {
81   "None",
82   "Keyboard",
83   "Joystick 1",
84   "Joystick 2",
85 };
86 
87 static void joystick_enabled_snapshot( libspectrum_snap *snap );
88 static void joystick_to_snapshot( libspectrum_snap *snap );
89 
90 static module_info_t joystick_module_info = {
91 
92   /* .reset = */ NULL,
93   /* .romcs = */ NULL,
94   /* .snapshot_enabled = */ joystick_enabled_snapshot,
95   /* .snapshot_from = */ NULL,
96   /* .snapshot_to = */ joystick_to_snapshot,
97 
98 };
99 
100 static const periph_port_t kempston_strict_decoding[] = {
101   { 0x00e0, 0x0000, joystick_kempston_read, NULL },
102   { 0, 0, NULL, NULL }
103 };
104 
105 static const periph_t kempston_strict_periph = {
106   /* .option = */ &settings_current.joy_kempston,
107   /* .ports = */ kempston_strict_decoding,
108   /* .hard_reset = */ 0,
109   /* .activate = */ NULL,
110 };
111 
112 static const periph_port_t kempston_loose_decoding[] = {
113   { 0x0020, 0x0000, joystick_kempston_read, NULL },
114   { 0, 0, NULL, NULL }
115 };
116 
117 static const periph_t kempston_loose_periph = {
118   /* .option = */ &settings_current.joy_kempston,
119   /* .ports = */ kempston_loose_decoding,
120   /* .hard_reset = */ 0,
121   /* .activate = */ NULL,
122 };
123 
124 /* Init/shutdown functions. Errors aren't important here */
125 
126 int
joystick_init(void * context)127 joystick_init( void *context )
128 {
129   joysticks_supported = ui_joystick_init();
130   kempston_value = timex1_value = timex2_value = 0x00;
131   fuller_value = 0xff;
132 
133   module_register( &joystick_module_info );
134   periph_register( PERIPH_TYPE_KEMPSTON, &kempston_strict_periph );
135   periph_register( PERIPH_TYPE_KEMPSTON_LOOSE, &kempston_loose_periph );
136 
137   return 0;
138 }
139 
140 void
joystick_end(void)141 joystick_end( void )
142 {
143   ui_joystick_end();
144 }
145 
146 void
joystick_register_startup(void)147 joystick_register_startup( void )
148 {
149   startup_manager_module dependencies[] = {
150     STARTUP_MANAGER_MODULE_LIBSPECTRUM,
151     STARTUP_MANAGER_MODULE_SETUID
152   };
153   startup_manager_register( STARTUP_MANAGER_MODULE_JOYSTICK, dependencies,
154                             ARRAY_SIZE( dependencies ), joystick_init,
155                             joystick_end, NULL );
156 }
157 
158 int
joystick_press(int which,joystick_button button,int press)159 joystick_press( int which, joystick_button button, int press )
160 {
161   joystick_type_t type;
162 
163   switch( which ) {
164   case 0: type = settings_current.joystick_1_output; break;
165   case 1: type = settings_current.joystick_2_output; break;
166 
167   case JOYSTICK_KEYBOARD:
168     type = settings_current.joystick_keyboard_output; break;
169 
170   default:
171     return 0;
172   }
173 
174   switch( type ) {
175 
176   case JOYSTICK_TYPE_CURSOR:
177     if( press ) {
178       keyboard_press( cursor_key[ button ] );
179     } else {
180       keyboard_release( cursor_key[ button ] );
181     }
182     return 1;
183 
184   case JOYSTICK_TYPE_KEMPSTON:
185     if( press ) {
186       kempston_value |=  kempston_mask[ button ];
187     } else {
188       kempston_value &= ~kempston_mask[ button ];
189     }
190     return 1;
191 
192   case JOYSTICK_TYPE_SINCLAIR_1:
193     if( press ) {
194       keyboard_press( sinclair1_key[ button ] );
195     } else {
196       keyboard_release( sinclair1_key[ button ] );
197     }
198     return 1;
199 
200   case JOYSTICK_TYPE_SINCLAIR_2:
201     if( press ) {
202       keyboard_press( sinclair2_key[ button ] );
203     } else {
204       keyboard_release( sinclair2_key[ button ] );
205     }
206     return 1;
207 
208   case JOYSTICK_TYPE_TIMEX_1:
209     if( press ) {
210       timex1_value |=  timex_mask[ button ];
211     } else {
212       timex1_value &= ~timex_mask[ button ];
213     }
214     return 1;
215 
216   case JOYSTICK_TYPE_TIMEX_2:
217     if( press ) {
218       timex2_value |=  timex_mask[ button ];
219     } else {
220       timex2_value &= ~timex_mask[ button ];
221     }
222     return 1;
223 
224   case JOYSTICK_TYPE_FULLER:
225     if( press ) {
226       fuller_value &= ~timex_mask[ button ];
227     } else {
228       fuller_value |=  timex_mask[ button ];
229     }
230     return 1;
231 
232   case JOYSTICK_TYPE_NONE: return 0;
233   }
234 
235   ui_error( UI_ERROR_ERROR, "%s:joystick_press:unknown joystick type %d",
236 	    __FILE__, type );
237   fuse_abort();
238 }
239 
240 /* Read functions for specific interfaces */
241 
242 libspectrum_byte
joystick_kempston_read(libspectrum_word port GCC_UNUSED,libspectrum_byte * attached)243 joystick_kempston_read( libspectrum_word port GCC_UNUSED, libspectrum_byte *attached )
244 {
245   *attached = 0xff; /* TODO: check this */
246   return kempston_value;
247 }
248 
249 libspectrum_byte
joystick_timex_read(libspectrum_word port GCC_UNUSED,libspectrum_byte which)250 joystick_timex_read( libspectrum_word port GCC_UNUSED, libspectrum_byte which )
251 {
252   return which ? timex2_value : timex1_value;
253 }
254 
255 libspectrum_byte
joystick_fuller_read(libspectrum_word port GCC_UNUSED,libspectrum_byte * attached)256 joystick_fuller_read( libspectrum_word port GCC_UNUSED, libspectrum_byte *attached )
257 {
258   *attached = 0xff; /* TODO: check this */
259   return fuller_value;
260 }
261 
262 static void
joystick_enabled_snapshot(libspectrum_snap * snap)263 joystick_enabled_snapshot( libspectrum_snap *snap )
264 {
265   size_t i;
266   size_t num_joysticks = libspectrum_snap_joystick_active_count( snap );
267   joystick_type_t fuse_type;
268 
269   for( i = 0; i < num_joysticks; i++ ) {
270     switch( libspectrum_snap_joystick_list( snap, i ) ) {
271     case LIBSPECTRUM_JOYSTICK_CURSOR:
272       fuse_type = JOYSTICK_TYPE_CURSOR;
273       break;
274     case LIBSPECTRUM_JOYSTICK_KEMPSTON:
275       fuse_type = JOYSTICK_TYPE_KEMPSTON;
276       break;
277     case LIBSPECTRUM_JOYSTICK_SINCLAIR_1:
278       fuse_type = JOYSTICK_TYPE_SINCLAIR_1;
279       break;
280     case LIBSPECTRUM_JOYSTICK_SINCLAIR_2:
281       fuse_type = JOYSTICK_TYPE_SINCLAIR_2;
282       break;
283     case LIBSPECTRUM_JOYSTICK_TIMEX_1:
284       fuse_type = JOYSTICK_TYPE_TIMEX_1;
285       break;
286     case LIBSPECTRUM_JOYSTICK_TIMEX_2:
287       fuse_type = JOYSTICK_TYPE_TIMEX_2;
288       break;
289     case LIBSPECTRUM_JOYSTICK_FULLER:
290       fuse_type = JOYSTICK_TYPE_FULLER;
291       break;
292     default:
293       ui_error( UI_ERROR_INFO, "Ignoring unsupported joystick in snapshot %s",
294         libspectrum_joystick_name( libspectrum_snap_joystick_list( snap, i ) ));
295       continue;
296     }
297 
298     if( settings_current.joystick_keyboard_output != fuse_type &&
299         settings_current.joystick_1_output != fuse_type &&
300         settings_current.joystick_2_output != fuse_type &&
301         !rzx_playback ) {
302       switch( ui_confirm_joystick( libspectrum_snap_joystick_list(snap,i),
303                                    libspectrum_snap_joystick_inputs(snap,i)) ) {
304       case UI_CONFIRM_JOYSTICK_KEYBOARD:
305         settings_current.joystick_keyboard_output = fuse_type;
306         break;
307       case UI_CONFIRM_JOYSTICK_JOYSTICK_1:
308         settings_current.joystick_1_output = fuse_type;
309         break;
310       case UI_CONFIRM_JOYSTICK_JOYSTICK_2:
311         settings_current.joystick_2_output = fuse_type;
312         break;
313       case UI_CONFIRM_JOYSTICK_NONE:
314         break;
315       }
316     }
317 
318     /* If the snap was configured for a Kempston joystick, enable
319        our Kempston emulation in case the snap was reading from
320        the joystick to prevent things going haywire */
321     if( fuse_type == JOYSTICK_TYPE_KEMPSTON )
322       settings_current.joy_kempston = 1;
323   }
324 }
325 
326 static void
add_joystick(libspectrum_snap * snap,joystick_type_t fuse_type,int inputs)327 add_joystick( libspectrum_snap *snap, joystick_type_t fuse_type, int inputs )
328 {
329   size_t i;
330   size_t num_joysticks = libspectrum_snap_joystick_active_count( snap );
331   libspectrum_joystick libspectrum_type;
332 
333   switch( fuse_type ) {
334   case JOYSTICK_TYPE_CURSOR:
335     libspectrum_type = LIBSPECTRUM_JOYSTICK_CURSOR;
336     break;
337   case JOYSTICK_TYPE_KEMPSTON:
338     libspectrum_type = LIBSPECTRUM_JOYSTICK_KEMPSTON;
339     break;
340   case JOYSTICK_TYPE_SINCLAIR_1:
341     libspectrum_type = LIBSPECTRUM_JOYSTICK_SINCLAIR_1;
342     break;
343   case JOYSTICK_TYPE_SINCLAIR_2:
344     libspectrum_type = LIBSPECTRUM_JOYSTICK_SINCLAIR_2;
345     break;
346   case JOYSTICK_TYPE_TIMEX_1:
347     libspectrum_type = LIBSPECTRUM_JOYSTICK_TIMEX_1;
348     break;
349   case JOYSTICK_TYPE_TIMEX_2:
350     libspectrum_type = LIBSPECTRUM_JOYSTICK_TIMEX_2;
351     break;
352   case JOYSTICK_TYPE_FULLER:
353     libspectrum_type = LIBSPECTRUM_JOYSTICK_FULLER;
354     break;
355 
356   case JOYSTICK_TYPE_NONE:
357   default:
358     return;
359   }
360 
361   for( i = 0; i < num_joysticks; i++ ) {
362     if( libspectrum_snap_joystick_list( snap, i ) == libspectrum_type ) {
363       libspectrum_snap_set_joystick_inputs( snap, i, inputs |
364                                   libspectrum_snap_joystick_inputs( snap, i ) );
365       return;
366     }
367   }
368 
369   libspectrum_snap_set_joystick_list( snap, num_joysticks, libspectrum_type );
370   libspectrum_snap_set_joystick_inputs( snap, num_joysticks, inputs );
371   libspectrum_snap_set_joystick_active_count( snap, num_joysticks + 1 );
372 }
373 
374 static void
joystick_to_snapshot(libspectrum_snap * snap)375 joystick_to_snapshot( libspectrum_snap *snap )
376 {
377   if( settings_current.joy_kempston ) {
378     add_joystick( snap, JOYSTICK_TYPE_KEMPSTON,
379                   LIBSPECTRUM_JOYSTICK_INPUT_NONE );
380   }
381   add_joystick( snap, settings_current.joystick_keyboard_output,
382                 LIBSPECTRUM_JOYSTICK_INPUT_KEYBOARD );
383   add_joystick( snap, settings_current.joystick_1_output,
384                 LIBSPECTRUM_JOYSTICK_INPUT_JOYSTICK_1 );
385   add_joystick( snap, settings_current.joystick_2_output,
386                 LIBSPECTRUM_JOYSTICK_INPUT_JOYSTICK_2 );
387 }
388