1 /*
2  * UAE - The Un*x Amiga Emulator
3  *
4  * SDL Joystick code
5  *
6  * Copyright 1997 Bernd Schmidt
7  * Copyright 1998 Krister Walfridsson
8  * Copyright 2003-2005 Richard Drummond
9  */
10 
11 #include "sysconfig.h"
12 #include "sysdeps.h"
13 
14 #include "options.h"
15 #include "inputdevice.h"
16 #include <SDL.h>
17 
18 #define MAX_MAPPINGS 256
19 
20 /* external prototypes */
21 extern void setid    (struct uae_input_device *uid, int i, int slot, int sub, int port, int evt);
22 extern void setid_af (struct uae_input_device *uid, int i, int slot, int sub, int port, int evt, int af);
23 
24 /* internal members */
25 static unsigned int nr_joysticks;
26 static int initialized;
27 
28 struct joyinfo {
29     SDL_Joystick *joy;
30     int axles;
31     int buttons;
32 };
33 
34 static struct joyinfo joys[MAX_INPUT_DEVICES];
35 
36 
read_joy(int nr)37 static void read_joy (int nr)
38 {
39     unsigned int num, i, axes, axis;
40     SDL_Joystick *joy;
41 
42     if (currprefs.input_selected_setting == 0) {
43 		if (jsem_isjoy (0, &currprefs) != (int)nr && jsem_isjoy (1, &currprefs) != (int)nr)
44 		    return;
45     }
46     joy = joys[nr].joy;
47     axes = SDL_JoystickNumAxes (joy);
48     for (i = 0; i < axes; i++) {
49 		axis = SDL_JoystickGetAxis (joy, i);
50 		setjoystickstate (nr, i, axis, 32767);
51     }
52 
53     num = SDL_JoystickNumButtons (joy);
54     for (i = 0; i < num; i++) {
55 		int bs = SDL_JoystickGetButton (joy, i) ? 1 : 0;
56 		setjoybuttonstate (nr, i, bs);
57     }
58 }
59 
get_joystick_num(void)60 static  int get_joystick_num (void)
61 {
62     return nr_joysticks;
63 }
64 
get_joystick_widget_num(int joy)65 static  int get_joystick_widget_num (int joy)
66 {
67     return joys[joy].axles + joys[joy].buttons;
68 }
69 
get_joystick_widget_type(int joy,int num,TCHAR * name,uae_u32 * code)70 static int get_joystick_widget_type (int joy, int num, TCHAR *name, uae_u32 *code)
71 {
72     if (num >= joys[joy].axles && num < joys[joy].axles + joys[joy].buttons) {
73 		if (name)
74 		    sprintf (name, "Button %d", num + 1 - joys[joy].axles);
75 		return IDEV_WIDGET_BUTTON;
76     } else if (num < joys[joy].axles) {
77 		if (name)
78 		    sprintf (name, "Axis %d", num + 1);
79 		return IDEV_WIDGET_AXIS;
80     }
81     return IDEV_WIDGET_NONE;
82 }
83 
get_joystick_widget_first(int joy,int type)84 static int get_joystick_widget_first (int joy, int type)
85 {
86     switch (type) {
87 	case IDEV_WIDGET_BUTTON:
88 	    return joys[joy].axles;
89 	case IDEV_WIDGET_AXIS:
90 	    return 0;
91     }
92     return -1;
93 }
94 
get_joystick_friendlyname(int joy)95 static TCHAR *get_joystick_friendlyname (int joy)
96 {
97     return (TCHAR*)SDL_JoystickName (joy);
98 }
99 
get_joystick_uniquename(int joy)100 static TCHAR *get_joystick_uniquename (int joy)
101 {
102     return (TCHAR*)SDL_JoystickName (joy);
103 }
104 
read_joystick(void)105 static void read_joystick (void)
106 {
107     if (get_joystick_num ()) {
108 		int i = 0;
109 		SDL_JoystickUpdate ();
110 		for ( ; i < get_joystick_num (); i++)
111 		    read_joy (i);
112     }
113 }
114 
init_joystick(void)115 static int init_joystick (void)
116 {
117     int success = 0;
118 
119     if (!initialized) {
120 		if (SDL_InitSubSystem (SDL_INIT_JOYSTICK) == 0) {
121 		    int i = 0;
122 
123 		    nr_joysticks = SDL_NumJoysticks ();
124 		    write_log ("Found %d joystick(s)\n", nr_joysticks);
125 
126 		    if (nr_joysticks > MAX_INPUT_DEVICES)
127 				nr_joysticks = MAX_INPUT_DEVICES;
128 
129 		    for ( ; i < get_joystick_num (); i++) {
130 				joys[i].joy     = SDL_JoystickOpen (i);
131 				joys[i].axles   = SDL_JoystickNumAxes (joys[i].joy);
132 				joys[i].buttons = SDL_JoystickNumButtons (joys[i].joy);
133 		    }
134 		    success = initialized = 1;
135 	} else
136 	    write_log ("Failed to initialize joysticks\n");
137     }
138 
139 	return success;
140 }
141 
close_joystick(void)142 static void close_joystick (void)
143 {
144 	unsigned int i;
145 	for (i = 0; i < nr_joysticks; i++) {
146 		SDL_JoystickClose (joys[i].joy);
147 		joys[i].joy = 0;
148 	}
149 	nr_joysticks = 0;
150 
151 	if (initialized) {
152 		SDL_QuitSubSystem (SDL_INIT_JOYSTICK);
153 		initialized = 0;
154 	}
155 }
156 
acquire_joystick(int num,int flags)157 static int acquire_joystick (int num, int flags)
158 {
159 	return num < get_joystick_num ();
160 }
161 
unacquire_joystick(int num)162 static void unacquire_joystick (int num)
163 {
164 }
165 
get_joystick_flags(int num)166 static int get_joystick_flags (int num)
167 {
168 	return 0;
169 }
170 
171 struct inputdevice_functions inputdevicefunc_joystick = {
172 	init_joystick,
173 	close_joystick,
174 	acquire_joystick,
175 	unacquire_joystick,
176 	read_joystick,
177 	get_joystick_num,
178 	get_joystick_friendlyname,
179 	get_joystick_uniquename,
180 	get_joystick_widget_num,
181 	get_joystick_widget_type,
182 	get_joystick_widget_first,
183 	get_joystick_flags
184 };
185 
186 /*
187  * Set default inputdevice config for SDL joysticks
188  */
input_get_default_joystick(struct uae_input_device * uid,int num,int port,int af,int mode,bool gp)189 int input_get_default_joystick (struct uae_input_device *uid, int num, int port, int af, int mode, bool gp)
190 {
191 	int h,v;
192 //	unsigned int j;
193 //	struct didata *did;
194 	SDL_Joystick *joy;
195 	joy = joys[num].joy;
196 
197 	if (num >= get_joystick_num ())
198 		return 0;
199 
200 	if (mode == JSEM_MODE_MOUSE_CDTV) {
201 		h = INPUTEVENT_MOUSE_CDTV_HORIZ;
202 		v = INPUTEVENT_MOUSE_CDTV_VERT;
203 	} else if (port >= 2) {
204 		h = port == 3 ? INPUTEVENT_PAR_JOY2_HORIZ : INPUTEVENT_PAR_JOY1_HORIZ;
205 		v = port == 3 ? INPUTEVENT_PAR_JOY2_VERT : INPUTEVENT_PAR_JOY1_VERT;
206 	} else {
207 		h = port ? INPUTEVENT_JOY2_HORIZ : INPUTEVENT_JOY1_HORIZ;;
208 		v = port ? INPUTEVENT_JOY2_VERT : INPUTEVENT_JOY1_VERT;
209 	}
210 	setid (uid, num, ID_AXIS_OFFSET + 0, 0, port, h);
211 	setid (uid, num, ID_AXIS_OFFSET + 1, 0, port, v);
212 
213 	if (port >= 2) {
214 		setid_af (uid, num, ID_BUTTON_OFFSET + 0, 0, port, port == 3 ? INPUTEVENT_PAR_JOY2_FIRE_BUTTON : INPUTEVENT_PAR_JOY1_FIRE_BUTTON, af);
215 	} else {
216 		setid_af (uid, num, ID_BUTTON_OFFSET + 0, 0, port, port ? INPUTEVENT_JOY2_FIRE_BUTTON : INPUTEVENT_JOY1_FIRE_BUTTON, af);
217 		if (SDL_JoystickNumButtons(joy) > 0)
218 			setid (uid, num, ID_BUTTON_OFFSET + 1, 0, port, port ? INPUTEVENT_JOY2_2ND_BUTTON : INPUTEVENT_JOY1_2ND_BUTTON);
219 		if (SDL_JoystickNumButtons(joy) > 1)
220 			setid (uid, num, ID_BUTTON_OFFSET + 2, 0, port, port ? INPUTEVENT_JOY2_3RD_BUTTON : INPUTEVENT_JOY1_3RD_BUTTON);
221 	}
222 
223 #if 0
224 	for (j = 2; j < MAX_MAPPINGS - 1; j++) {
225 		int am = did->axismappings[j];
226 		if (am == DIJOFS_POV(0) || am == DIJOFS_POV(1) || am == DIJOFS_POV(2) || am == DIJOFS_POV(3)) {
227 			setid (uid, num, ID_AXIS_OFFSET + j + 0, 0, port, h);
228 			setid (uid, num, ID_AXIS_OFFSET + j + 1, 0, port, v);
229 			j++;
230 		}
231 	}
232 #endif
233 
234 	if (mode == JSEM_MODE_JOYSTICK_CD32) {
235 		setid_af (uid, num, ID_BUTTON_OFFSET + 0, 0, port, port ? INPUTEVENT_JOY2_CD32_RED : INPUTEVENT_JOY1_CD32_RED, af);
236 		setid_af (uid, num, ID_BUTTON_OFFSET + 0, 1, port, port ? INPUTEVENT_JOY2_FIRE_BUTTON : INPUTEVENT_JOY1_FIRE_BUTTON, af);
237 		if (SDL_JoystickNumButtons(joy) > 0) {
238 			setid (uid, num, ID_BUTTON_OFFSET + 1, 0, port, port ? INPUTEVENT_JOY2_CD32_BLUE : INPUTEVENT_JOY1_CD32_BLUE);
239 			setid (uid, num, ID_BUTTON_OFFSET + 1, 1, port,  port ? INPUTEVENT_JOY2_2ND_BUTTON : INPUTEVENT_JOY1_2ND_BUTTON);
240 		}
241 		if (SDL_JoystickNumButtons(joy) > 1)
242 			setid (uid, num, ID_BUTTON_OFFSET + 2, 0, port, port ? INPUTEVENT_JOY2_CD32_GREEN : INPUTEVENT_JOY1_CD32_GREEN);
243 		if (SDL_JoystickNumButtons(joy) > 2)
244 			setid (uid, num, ID_BUTTON_OFFSET + 3, 0, port, port ? INPUTEVENT_JOY2_CD32_YELLOW : INPUTEVENT_JOY1_CD32_YELLOW);
245 		if (SDL_JoystickNumButtons(joy) > 3)
246 			setid (uid, num, ID_BUTTON_OFFSET + 4, 0, port, port ? INPUTEVENT_JOY2_CD32_RWD : INPUTEVENT_JOY1_CD32_RWD);
247 		if (SDL_JoystickNumButtons(joy) > 4)
248 			setid (uid, num, ID_BUTTON_OFFSET + 5, 0, port, port ? INPUTEVENT_JOY2_CD32_FFW : INPUTEVENT_JOY1_CD32_FFW);
249 		if (SDL_JoystickNumButtons(joy) > 5)
250 			setid (uid, num, ID_BUTTON_OFFSET + 6, 0, port, port ? INPUTEVENT_JOY2_CD32_PLAY :  INPUTEVENT_JOY1_CD32_PLAY);
251 	}
252 	if (num == 0)
253 		return 1;
254 	return 0;
255 }
256