1 /*
2  * UAE - The Un*x Amiga Emulator
3  *
4  * joystick/mouse emulation
5  *
6  * Copyright 2001-2012 Toni Wilen
7  *
8  * new fetures:
9  * - very configurable (and very complex to configure :)
10  * - supports multiple native input devices (joysticks and mice)
11  * - supports mapping joystick/mouse buttons to keys and vice versa
12  * - joystick mouse emulation (supports both ports)
13  * - supports parallel port joystick adapter
14  * - full cd32 pad support (supports both ports)
15  * - fully backward compatible with old joystick/mouse configuration
16  *
17  */
18 
19 //#define DONGLE_DEBUG
20 
21 #include "sysconfig.h"
22 #include "sysdeps.h"
23 
24 #include <ctype.h>
25 
26 #include "cfgfile.h"
27 #include "keyboard.h"
28 #include "inputdevice.h"
29 #include "inputrecord.h"
30 #include "keybuf.h"
31 #include "custom.h"
32 #include "xwin.h"
33 #include "drawing.h"
34 #include "memory_uae.h"
35 #include "events.h"
36 #include "newcpu.h"
37 #include "uae.h"
38 #include "picasso96.h"
39 #include "catweasel.h"
40 #include "debug.h"
41 #include "ar.h"
42 #include "gui.h"
43 #include "disk.h"
44 #include "audio.h"
45 #include "savestate.h"
46 #include "arcadia.h"
47 #include "zfile.h"
48 #include "cia.h"
49 #include "autoconf.h"
50 #include "filesys.h"
51 #ifdef RETROPLATFORM
52 #include "rp.h"
53 #endif
54 #include "dongle.h"
55 #include "cdtv.h"
56 #include "misc.h"
57 
58 /* external members */
59 extern int bootrom_header, bootrom_items;
60 
61 /* external functions */
62 extern void master_sound_volume (int);
63 extern void sound_mute (int);
64 extern void sound_volume (int dir);
65 extern uae_u32 uaerand (void);
66 extern TCHAR *my_strdup_trim (const TCHAR *s);
67 
68 // 01 = host events
69 // 02 = joystick
70 // 04 = cia buttons
71 // 16 = potgo
72 // 32 = vsync
73 
74 int inputdevice_logging = 0;
75 
76 #define COMPA_RESERVED_FLAGS ID_FLAG_INVERT
77 
78 #define ID_FLAG_CANRELEASE 0x1000
79 #define ID_FLAG_TOGGLED 0x2000
80 #define ID_FLAG_CUSTOMEVENT_TOGGLED1 0x4000
81 #define ID_FLAG_CUSTOMEVENT_TOGGLED2 0x8000
82 
83 #define ID_FLAG_SAVE_MASK_CONFIG 0x000000ff
84 #define ID_FLAG_SAVE_MASK_QUALIFIERS ID_FLAG_QUALIFIER_MASK
85 #define ID_FLAG_SAVE_MASK_FULL (ID_FLAG_SAVE_MASK_CONFIG | ID_FLAG_SAVE_MASK_QUALIFIERS)
86 
87 #define IE_INVERT 0x80
88 #define IE_CDTV 0x100
89 
90 #define INPUTEVENT_JOY1_CD32_FIRST INPUTEVENT_JOY1_CD32_PLAY
91 #define INPUTEVENT_JOY2_CD32_FIRST INPUTEVENT_JOY2_CD32_PLAY
92 #define INPUTEVENT_JOY1_CD32_LAST INPUTEVENT_JOY1_CD32_BLUE
93 #define INPUTEVENT_JOY2_CD32_LAST INPUTEVENT_JOY2_CD32_BLUE
94 
95 /* event masks */
96 #define AM_KEY 1 /* keyboard allowed */
97 #define AM_JOY_BUT 2 /* joystick buttons allowed */
98 #define AM_JOY_AXIS 4 /* joystick axis allowed */
99 #define AM_MOUSE_BUT 8 /* mouse buttons allowed */
100 #define AM_MOUSE_AXIS 16 /* mouse direction allowed */
101 #define AM_AF 32 /* supports autofire */
102 #define AM_INFO 64 /* information data for gui */
103 #define AM_DUMMY 128 /* placeholder */
104 #define AM_CUSTOM 256 /* custom event */
105 #define AM_K (AM_KEY|AM_JOY_BUT|AM_MOUSE_BUT|AM_AF) /* generic button/switch */
106 #define AM_KK (AM_KEY|AM_JOY_BUT|AM_MOUSE_BUT)
107 
108 #define JOYMOUSE_CDTV 8
109 
110 #define DEFEVENT(A, B, C, D, E, F) {_T(#A), B, C, D, E, F },
111 static struct inputevent events[] = {
112 	{0, 0, AM_K,0,0,0},
113 #include "inputevents.def"
114 	{0, 0, 0, 0, 0, 0}
115 };
116 #undef DEFEVENT
117 
118 static int sublevdir[2][MAX_INPUT_SUB_EVENT];
119 
120 static const int slotorder1[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
121 static const int slotorder2[] = { 8, 1, 2, 3, 4, 5, 6, 7 };
122 
123 struct uae_input_device2 {
124 	uae_u32 buttonmask;
125 	int states[MAX_INPUT_DEVICE_EVENTS / 2][MAX_INPUT_SUB_EVENT + 1];
126 };
127 
128 static struct uae_input_device2 joysticks2[MAX_INPUT_DEVICES];
129 static struct uae_input_device2 mice2[MAX_INPUT_DEVICES];
130 static uae_u8 scancodeused[MAX_INPUT_DEVICES][256];
131 static uae_u64 qualifiers, qualifiers_r;
132 static uae_s16 *qualifiers_evt[MAX_INPUT_QUALIFIERS];
133 
134 // fire/left mouse button pullup resistors enabled?
135 static bool mouse_pullup = true;
136 
137 static int joymodes[MAX_JPORTS];
138 static int *joyinputs[MAX_JPORTS];
139 
140 static int input_acquired;
141 static int testmode;
142 struct teststore
143 {
144 	int testmode_type;
145 	int testmode_num;
146 	int testmode_wtype;
147 	int testmode_wnum;
148 	int testmode_state;
149 	int testmode_max;
150 };
151 #define TESTMODE_MAX 2
152 static int testmode_count;
153 static struct teststore testmode_data[TESTMODE_MAX];
154 static struct teststore testmode_wait[TESTMODE_MAX];
155 
156 static int bouncy;
157 static unsigned long bouncy_cycles;
158 
159 int handle_input_event (int nr, int state, int max, int autofire, bool canstoprecord, bool playbackevent);
160 
161 static struct inputdevice_functions idev[IDTYPE_MAX];
162 
isdevice(struct uae_input_device * id)163 static int isdevice (struct uae_input_device *id)
164 {
165 	int i, j;
166 	for (i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++) {
167 		for (j = 0; j < MAX_INPUT_SUB_EVENT; j++) {
168 			if (id->eventid[i][j] > 0)
169 				return 1;
170 		}
171 	}
172 	return 0;
173 }
174 
inputdevice_uaelib(const TCHAR * s,const TCHAR * parm)175 int inputdevice_uaelib (const TCHAR *s, const TCHAR *parm)
176 {
177 	int i;
178 
179 	for (i = 1; events[i].name; i++) {
180 		if (!_tcscmp (s, events[i].confname)) {
181 			handle_input_event (i, _tstol (parm), 1, 0, false, false);
182 			return 1;
183 		}
184 	}
185 	return 0;
186 }
187 
188 static struct uae_input_device *joysticks;
189 static struct uae_input_device *mice;
190 static struct uae_input_device *keyboards;
191 static struct uae_input_device *internalevents;
192 static struct uae_input_device_kbr_default *keyboard_default, **keyboard_default_table;
193 static int default_keyboard_layout[MAX_JPORTS];
194 
195 #define KBR_DEFAULT_MAP_FIRST 0
196 #define KBR_DEFAULT_MAP_LAST 5
197 #define KBR_DEFAULT_MAP_CD32_FIRST 6
198 #define KBR_DEFAULT_MAP_CD32_LAST 8
199 
200 #define KBR_DEFAULT_MAP_NP 0
201 #define KBR_DEFAULT_MAP_CK 1
202 #define KBR_DEFAULT_MAP_SE 2
203 #define KBR_DEFAULT_MAP_NP3 3
204 #define KBR_DEFAULT_MAP_CK3 4
205 #define KBR_DEFAULT_MAP_SE3 5
206 #define KBR_DEFAULT_MAP_CD32_NP 6
207 #define KBR_DEFAULT_MAP_CD32_CK 7
208 #define KBR_DEFAULT_MAP_CD32_SE 8
209 #define KBR_DEFAULT_MAP_XA1 9
210 #define KBR_DEFAULT_MAP_XA2 10
211 #define KBR_DEFAULT_MAP_ARCADIA 11
212 #define KBR_DEFAULT_MAP_ARCADIA_XA 12
213 #define KBR_DEFAULT_MAP_CDTV 13
214 static int **keyboard_default_kbmaps;
215 
216 static int mouse_axis[MAX_INPUT_DEVICES][MAX_INPUT_DEVICE_EVENTS];
217 static int oldm_axis[MAX_INPUT_DEVICES][MAX_INPUT_DEVICE_EVENTS];
218 
219 #define MOUSE_AXIS_TOTAL 4
220 
221 static uae_s16 mouse_x[MAX_JPORTS], mouse_y[MAX_JPORTS];
222 static uae_s16 mouse_delta[MAX_JPORTS][MOUSE_AXIS_TOTAL];
223 static uae_s16 mouse_deltanoreset[MAX_JPORTS][MOUSE_AXIS_TOTAL];
224 static int joybutton[MAX_JPORTS];
225 static int joydir[MAX_JPORTS];
226 static int joydirpot[MAX_JPORTS][2];
227 static uae_s16 mouse_frame_x[MAX_JPORTS], mouse_frame_y[MAX_JPORTS];
228 
229 #ifdef __LIBRETRO__
230 int mouse_port[NORMAL_JPORTS];
231 #else
232 static int mouse_port[NORMAL_JPORTS];
233 #endif
234 static int cd32_shifter[NORMAL_JPORTS];
235 #ifdef __LIBRETRO__
236 int cd32_pad_enabled[NORMAL_JPORTS];
237 #else
238 static int cd32_pad_enabled[NORMAL_JPORTS];
239 #endif
240 static int parport_joystick_enabled;
241 static int oldmx[MAX_JPORTS], oldmy[MAX_JPORTS];
242 static int oleft[MAX_JPORTS], oright[MAX_JPORTS], otop[MAX_JPORTS], obot[MAX_JPORTS];
243 static int horizclear[MAX_JPORTS], vertclear[MAX_JPORTS];
244 
245 uae_u16 potgo_value;
246 static int pot_cap[NORMAL_JPORTS][2];
247 static uae_u8 pot_dat[NORMAL_JPORTS][2];
248 static int pot_dat_act[NORMAL_JPORTS][2];
249 static int analog_port[NORMAL_JPORTS][2];
250 static int digital_port[NORMAL_JPORTS][2];
251 static int lightpen;
252 #define POTDAT_DELAY_PAL 8
253 #define POTDAT_DELAY_NTSC 7
254 
255 static int use_joysticks[MAX_INPUT_DEVICES];
256 static int use_mice[MAX_INPUT_DEVICES];
257 static int use_keyboards[MAX_INPUT_DEVICES];
258 
259 #define INPUT_QUEUE_SIZE 16
260 struct input_queue_struct {
261 	int evt, storedstate, state, max, linecnt, nextlinecnt;
262 	TCHAR *custom;
263 };
264 static struct input_queue_struct input_queue[INPUT_QUEUE_SIZE];
265 
restore_input(uae_u8 * src)266 uae_u8 *restore_input (uae_u8 *src)
267 {
268 	restore_u32 ();
269 	for (int i = 0; i < 2; i++) {
270 		for (int j = 0; j < 2; j++) {
271 			pot_cap[i][j] = restore_u16 ();
272 		}
273 	}
274 	return src;
275 }
save_input(int * len,uae_u8 * dstptr)276 uae_u8 *save_input (int *len, uae_u8 *dstptr)
277 {
278 	uae_u8 *dstbak, *dst;
279 
280 	if (dstptr)
281 		dstbak = dst = dstptr;
282 	else
283 		dstbak = dst = xmalloc (uae_u8, 1000);
284 	save_u32 (0);
285 	for (int i = 0; i < 2; i++) {
286 		for (int j = 0; j < 2; j++) {
287 			save_u16 (pot_cap[i][j]);
288 		}
289 	}
290 	*len = dst - dstbak;
291 	return dstbak;
292 }
293 
freejport(struct uae_prefs * dst,int num)294 static void freejport (struct uae_prefs *dst, int num)
295 {
296 	memset (&dst->jports[num], 0, sizeof (struct jport));
297 	dst->jports[num].id = -1;
298 }
copyjport(const struct uae_prefs * src,struct uae_prefs * dst,int num)299 static void copyjport (const struct uae_prefs *src, struct uae_prefs *dst, int num)
300 {
301 	if (!src)
302 		return;
303 	freejport (dst, num);
304 	_tcscpy (dst->jports[num].configname, src->jports[num].configname);
305 	_tcscpy (dst->jports[num].name, src->jports[num].name);
306 	dst->jports[num].id = src->jports[num].id;
307 	dst->jports[num].mode = src->jports[num].mode;
308 	dst->jports[num].autofire = src->jports[num].autofire;
309 }
310 
311 /* REMOVEME:
312  * nowhere used
313  */
314 #if 0
315 static void out_config (struct zfile *f, int id, int num, TCHAR *s1, TCHAR *s2)
316 {
317 	TCHAR tmp[MAX_DPATH];
318 	_stprintf (tmp, _T("input.%d.%s%d"), id, s1, num);
319 	cfgfile_write_str (f, tmp, s2);
320 }
321 #endif
322 
write_config_head(struct zfile * f,int idnum,int devnum,TCHAR * name,struct uae_input_device * id,struct inputdevice_functions * idf)323 static bool write_config_head (struct zfile *f, int idnum, int devnum, TCHAR *name, struct uae_input_device *id,  struct inputdevice_functions *idf)
324 {
325 	TCHAR tmp2[CONFIG_BLEN];
326 
327 	if (idnum == GAMEPORT_INPUT_SETTINGS) {
328 		if (!isdevice (id))
329 			return false;
330 		if (!id->enabled)
331 			return false;
332 	}
333 
334 	TCHAR *s = NULL;
335 	if (id->name)
336 		s = id->name;
337 	else if (devnum < idf->get_num ())
338 		s = idf->get_friendlyname (devnum);
339 	if (s) {
340 		_stprintf (tmp2, _T("input.%d.%s.%d.friendlyname"), idnum + 1, name, devnum);
341 		cfgfile_write_str (f, tmp2, s);
342 	}
343 
344 	s = NULL;
345 	if (id->configname)
346 		s = id->configname;
347 	else if (devnum < idf->get_num ())
348 		s = idf->get_uniquename (devnum);
349 	if (s) {
350 		_stprintf (tmp2, _T("input.%d.%s.%d.name"), idnum + 1, name, devnum);
351 		cfgfile_write_str (f, tmp2, s);
352 	}
353 
354 	if (!isdevice (id)) {
355 		_stprintf (tmp2, _T("input.%d.%s.%d.empty"), idnum + 1, name, devnum);
356 		cfgfile_write_bool (f, tmp2, true);
357 		if (id->enabled) {
358 			_stprintf (tmp2, _T("input.%d.%s.%d.disabled"), idnum + 1, name, devnum);
359 			cfgfile_write (f, tmp2, _T("%d"), id->enabled ? 0 : 1);
360 		}
361 		return false;
362 	}
363 
364 	if (idnum == GAMEPORT_INPUT_SETTINGS) {
365 		_stprintf (tmp2, _T("input.%d.%s.%d.custom"), idnum + 1, name, devnum);
366 		cfgfile_write_bool (f, tmp2, true);
367 	} else {
368 		_stprintf (tmp2, _T("input.%d.%s.%d.empty"), idnum + 1, name, devnum);
369 		cfgfile_write_bool (f, tmp2, false);
370 		_stprintf (tmp2, _T("input.%d.%s.%d.disabled"), idnum + 1, name, devnum);
371 		cfgfile_write_bool (f, tmp2, id->enabled ? false : true);
372 	}
373 	return true;
374 }
375 
write_slot(TCHAR * p,struct uae_input_device * uid,int i,int j)376 static bool write_slot (TCHAR *p, struct uae_input_device *uid, int i, int j)
377 {
378 	bool ok = false;
379 	if (i < 0 || j < 0) {
380 		_tcscpy (p, _T("NULL"));
381 		return false;
382 	}
383 	uae_u64 flags = uid->flags[i][j];
384 	if (uid->custom[i][j] && _tcslen (uid->custom[i][j]) > 0) {
385 		_stprintf (p, _T("'%s'.%d"), uid->custom[i][j], flags & ID_FLAG_SAVE_MASK_CONFIG);
386 		ok = true;
387 	} else if (uid->eventid[i][j] > 0) {
388 		_stprintf (p, _T("%s.%d"), events[uid->eventid[i][j]].confname, flags & ID_FLAG_SAVE_MASK_CONFIG);
389 		ok = true;
390 	} else {
391 		_tcscpy (p, _T("NULL"));
392 	}
393 	if (ok && (flags & ID_FLAG_SAVE_MASK_QUALIFIERS)) {
394 		TCHAR *p2 = p + _tcslen (p);
395 		*p2++ = '.';
396 		for (int i = 0; i < MAX_INPUT_QUALIFIERS * 2; i++) {
397 			if ((ID_FLAG_QUALIFIER1 << i) & flags) {
398 				if (i & 1)
399 					_stprintf (p2, _T("%c"), 'a' + i / 2);
400 				else
401 					_stprintf (p2, _T("%c"), 'A' + i / 2);
402 				p2++;
403 			}
404 		}
405 	}
406 	return ok;
407 }
408 
409 static struct inputdevice_functions *getidf (int devnum);
410 
kbrlabel(TCHAR * s)411 static void kbrlabel (TCHAR *s)
412 {
413 	while (*s) {
414 		*s = _totupper (*s);
415 		if (*s == ' ')
416 			*s = '_';
417 		s++;
418 	}
419 }
420 
write_config2(struct zfile * f,int idnum,int i,int offset,const TCHAR * extra,struct uae_input_device * id)421 static void write_config2 (struct zfile *f, int idnum, int i, int offset, const TCHAR *extra, struct uae_input_device *id)
422 {
423 	TCHAR tmp2[CONFIG_BLEN], tmp3[CONFIG_BLEN], *p;
424 /* REMOVEME:
425  * nowhere used
426  */
427 #if 0
428 	int got;
429 #endif
430 	int evt, j, k;
431 	TCHAR *custom;
432 	const int *slotorder;
433 	int io = i + offset;
434 
435 	tmp2[0] = 0;
436 	p = tmp2;
437 
438 /* REMOVEME:
439  * nowhere used
440  */
441 #if 0
442 	got = 0;
443 #endif
444 
445 	slotorder = slotorder1;
446 	// if gameports non-custom mapping in slot0 -> save slot8 as slot0
447 	if (id->port[io][0] && !(id->flags[io][0] & ID_FLAG_GAMEPORTSCUSTOM_MASK))
448 		slotorder = slotorder2;
449 
450 	for (j = 0; j < MAX_INPUT_SUB_EVENT; j++) {
451 
452 		evt = id->eventid[io][slotorder[j]];
453 		custom = id->custom[io][slotorder[j]];
454 		if (custom == NULL && evt <= 0) {
455 			for (k = j + 1; k < MAX_INPUT_SUB_EVENT; k++) {
456 				if ((id->port[io][k] == 0 || id->port[io][k] == MAX_JPORTS + 1) && (id->eventid[io][slotorder[k]] > 0 || id->custom[io][slotorder[k]] != NULL))
457 					break;
458 			}
459 			if (k == MAX_INPUT_SUB_EVENT)
460 				break;
461 		}
462 
463 		if (p > tmp2) {
464 			*p++ = ',';
465 			*p = 0;
466 		}
467 		bool ok = write_slot (p, id, io, slotorder[j]);
468 		p += _tcslen (p);
469 		if (ok) {
470 			if (id->port[io][slotorder[j]] > 0 && id->port[io][slotorder[j]] < MAX_JPORTS + 1) {
471 				int pnum = id->port[io][slotorder[j]] - 1;
472 				_stprintf (p, _T(".%d"), pnum);
473 				p += _tcslen (p);
474 				if (idnum != GAMEPORT_INPUT_SETTINGS && j == 0 && id->port[io][SPARE_SUB_EVENT] && slotorder == slotorder1) {
475 					*p++ = '.';
476 					write_slot (p, id, io, SPARE_SUB_EVENT);
477 					p += _tcslen (p);
478 				}
479 			}
480 		}
481 	}
482 	if (p > tmp2) {
483 		_stprintf (tmp3, _T("input.%d.%s%d"), idnum + 1, extra, i);
484 		cfgfile_write_str (f, tmp3, tmp2);
485 	}
486 }
487 
write_kbr_config(struct zfile * f,int idnum,int devnum,struct uae_input_device * kbr,struct inputdevice_functions * idf)488 static void write_kbr_config (struct zfile *f, int idnum, int devnum, struct uae_input_device *kbr, struct inputdevice_functions *idf)
489 {
490 	TCHAR tmp1[CONFIG_BLEN], tmp2[CONFIG_BLEN], tmp3[CONFIG_BLEN], tmp4[CONFIG_BLEN], tmp5[CONFIG_BLEN], *p;
491 	int i, j, k, evt, skip;
492 	const int *slotorder;
493 
494 	if (!keyboard_default)
495 		return;
496 
497 	if (!write_config_head (f, idnum, devnum, _T("keyboard"), kbr, idf))
498 		return;
499 
500 	i = 0;
501 	while (i < MAX_INPUT_DEVICE_EVENTS && kbr->extra[i] >= 0) {
502 
503 		slotorder = slotorder1;
504 		// if gameports non-custom mapping in slot0 -> save slot4 as slot0
505 		if (kbr->port[i][0] && !(kbr->flags[i][0] & ID_FLAG_GAMEPORTSCUSTOM_MASK))
506 			slotorder = slotorder2;
507 
508 		skip = 0;
509 		k = 0;
510 		while (keyboard_default[k].scancode >= 0) {
511 			if (keyboard_default[k].scancode == kbr->extra[i]) {
512 				skip = 1;
513 				for (j = 0; j < MAX_INPUT_SUB_EVENT; j++) {
514 					if (keyboard_default[k].node[j].evt != 0) {
515 						if (keyboard_default[k].node[j].evt != kbr->eventid[i][slotorder[j]] || keyboard_default[k].node[j].flags != (kbr->flags[i][slotorder[j]] & ID_FLAG_SAVE_MASK_FULL))
516 						skip = 0;
517 					} else if ((kbr->flags[i][slotorder[j]] & ID_FLAG_SAVE_MASK_FULL) != 0 || kbr->eventid[i][slotorder[j]] > 0) {
518 					skip = 0;
519 					}
520 				}
521 				break;
522 			}
523 			k++;
524 		}
525 		bool isdefaultspare =
526 			kbr->port[i][SPARE_SUB_EVENT] &&
527 			keyboard_default[k].node[0].evt == kbr->eventid[i][SPARE_SUB_EVENT] && keyboard_default[k].node[0].flags == (kbr->flags[i][SPARE_SUB_EVENT] & ID_FLAG_SAVE_MASK_FULL);
528 
529 		if (kbr->port[i][0] > 0 && !(kbr->flags[i][0] & ID_FLAG_GAMEPORTSCUSTOM_MASK) &&
530 			(kbr->eventid[i][1] <= 0 && kbr->eventid[i][2] <= 0 && kbr->eventid[i][3] <= 0) &&
531 			(kbr->port[i][SPARE_SUB_EVENT] == 0 || isdefaultspare))
532 			skip = 1;
533 		if (kbr->eventid[i][0] == 0 && (kbr->flags[i][0] & ID_FLAG_SAVE_MASK_FULL) == 0 && keyboard_default[k].scancode < 0)
534 			skip = 1;
535 		if (skip) {
536 			i++;
537 			continue;
538 		}
539 		tmp2[0] = 0;
540 		p = tmp2;
541 		for (j = 0; j < MAX_INPUT_SUB_EVENT; j++) {
542 			TCHAR *custom = kbr->custom[i][slotorder[j]];
543 			evt = kbr->eventid[i][slotorder[j]];
544 			if (custom == NULL && evt <= 0) {
545 				for (k = j + 1; k < MAX_INPUT_SUB_EVENT; k++) {
546 					if (kbr->eventid[i][slotorder[k]] > 0 || kbr->custom[i][slotorder[k]] != NULL)
547 						break;
548 				}
549 				if (k == MAX_INPUT_SUB_EVENT)
550 					break;
551 			}
552 			if (p > tmp2) {
553 				*p++ = ',';
554 				*p = 0;
555 			}
556 			bool ok = write_slot (p, kbr, i, slotorder[j]);
557 			p += _tcslen (p);
558 			if (ok) {
559 				// save port number + SPARE SLOT if needed
560 				if (kbr->port[i][slotorder[j]] > 0 && (kbr->flags[i][slotorder[j]] & ID_FLAG_GAMEPORTSCUSTOM_MASK)) {
561 					_stprintf (p, _T(".%d"), kbr->port[i][slotorder[j]] - 1);
562 					p += _tcslen (p);
563 					if (idnum != GAMEPORT_INPUT_SETTINGS && j == 0 && kbr->port[i][SPARE_SUB_EVENT] && !isdefaultspare && slotorder == slotorder1) {
564 						*p++ = '.';
565 						write_slot (p, kbr, i, SPARE_SUB_EVENT);
566 						p += _tcslen (p);
567 					}
568 				}
569 			}
570 		}
571 		idf->get_widget_type (devnum, i, tmp5, NULL);
572 		_stprintf (tmp3, _T("%d%s%s"), kbr->extra[i], tmp5[0] ? _T(".") : _T(""), tmp5[0] ? tmp5 : _T(""));
573 		kbrlabel (tmp3);
574 		_stprintf (tmp1, _T("keyboard.%d.button.%s"), devnum, tmp3);
575 		_stprintf (tmp4, _T("input.%d.%s"), idnum + 1, tmp1);
576 		cfgfile_write_str (f, tmp4, tmp2[0] ? tmp2 : _T("NULL"));
577 		i++;
578 	}
579 }
580 
write_config(struct zfile * f,int idnum,int devnum,TCHAR * name,struct uae_input_device * id,struct inputdevice_functions * idf)581 static void write_config (struct zfile *f, int idnum, int devnum, TCHAR *name, struct uae_input_device *id, struct inputdevice_functions *idf)
582 {
583 	TCHAR tmp1[MAX_DPATH];
584 	int i;
585 
586 	if (!write_config_head (f, idnum, devnum, name, id, idf))
587 		return;
588 
589 	_stprintf (tmp1, _T("%s.%d.axis."), name, devnum);
590 	for (i = 0; i < ID_AXIS_TOTAL; i++)
591 		write_config2 (f, idnum, i, ID_AXIS_OFFSET, tmp1, id);
592 	_stprintf (tmp1, _T("%s.%d.button.") ,name, devnum);
593 	for (i = 0; i < ID_BUTTON_TOTAL; i++)
594 		write_config2 (f, idnum, i, ID_BUTTON_OFFSET, tmp1, id);
595 }
596 
597 static const TCHAR *kbtypes[] = { _T("amiga"), _T("pc"), NULL };
598 
write_inputdevice_config(struct uae_prefs * p,struct zfile * f)599 void write_inputdevice_config (struct uae_prefs *p, struct zfile *f)
600 {
601 	int i, id;
602 
603 	cfgfile_write (f, _T("input.config"), _T("%d"), p->input_selected_setting == GAMEPORT_INPUT_SETTINGS ? 0 : p->input_selected_setting + 1);
604 	cfgfile_write (f, _T("input.joymouse_speed_analog"), _T("%d"), p->input_joymouse_multiplier);
605 	cfgfile_write (f, _T("input.joymouse_speed_digital"), _T("%d"), p->input_joymouse_speed);
606 	cfgfile_write (f, _T("input.joymouse_deadzone"), _T("%d"), p->input_joymouse_deadzone);
607 	cfgfile_write (f, _T("input.joystick_deadzone"), _T("%d"), p->input_joystick_deadzone);
608 	cfgfile_write (f, _T("input.analog_joystick_multiplier"), _T("%d"), p->input_analog_joystick_mult);
609 	cfgfile_write (f, _T("input.analog_joystick_offset"), _T("%d"), p->input_analog_joystick_offset);
610 	cfgfile_write (f, _T("input.mouse_speed"), _T("%d"), p->input_mouse_speed);
611 	cfgfile_write (f, _T("input.autofire_speed"), _T("%d"), p->input_autofire_linecnt);
612 	cfgfile_dwrite_str (f, _T("input.keyboard_type"), kbtypes[p->input_keyboard_type]);
613 	cfgfile_dwrite (f, _T("input.contact_bounce"), _T("%d"), p->input_contact_bounce);
614 	for (id = 0; id < MAX_INPUT_SETTINGS; id++) {
615 		TCHAR tmp[MAX_DPATH];
616 		if (id < GAMEPORT_INPUT_SETTINGS) {
617 			_stprintf (tmp, _T("input.%d.name"), id + 1);
618 			cfgfile_dwrite_str (f, tmp, p->input_config_name[id]);
619 		}
620 		for (i = 0; i < MAX_INPUT_DEVICES; i++)
621 			write_config (f, id, i, _T("joystick"), &p->joystick_settings[id][i], &idev[IDTYPE_JOYSTICK]);
622 		for (i = 0; i < MAX_INPUT_DEVICES; i++)
623 			write_config (f, id, i, _T("mouse"), &p->mouse_settings[id][i], &idev[IDTYPE_MOUSE]);
624 		for (i = 0; i < MAX_INPUT_DEVICES; i++)
625 			write_kbr_config (f, id, i, &p->keyboard_settings[id][i], &idev[IDTYPE_KEYBOARD]);
626 		write_config (f, id, 0, _T("internal"), &p->internalevent_settings[id][0], &idev[IDTYPE_INTERNALEVENT]);
627 	}
628 }
629 
getqual(const TCHAR ** pp)630 static uae_u64 getqual (const TCHAR **pp)
631 {
632 	const TCHAR *p = *pp;
633 	uae_u64 mask = 0;
634 
635 	while ((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z')) {
636 		bool press = (*p >= 'A' && *p <= 'Z');
637 		int shift, inc;
638 
639 		if (press) {
640 			shift = *p - 'A';
641 			inc = 0;
642 		} else {
643 			shift = *p - 'a';
644 			inc = 1;
645 		}
646 		mask |= ID_FLAG_QUALIFIER1 << (shift * 2 + inc);
647 		p++;
648 	}
649 	while (*p != 0 && *p !='.' && *p != ',')
650 		p++;
651 	if (*p == '.' || *p == ',')
652 		p++;
653 	*pp = p;
654 	return mask;
655 }
656 
getnum(const TCHAR ** pp)657 static int getnum (const TCHAR **pp)
658 {
659 	const TCHAR *p = *pp;
660 	int v;
661 
662 	if (!_tcsnicmp (p, _T("false"), 5))
663 		v = 0;
664 	if (!_tcsnicmp (p, _T("true"), 4))
665 		v = 1;
666 	else
667 		v = _tstol (p);
668 
669 	while (*p != 0 && *p !='.' && *p != ',')
670 		p++;
671 	if (*p == '.' || *p == ',')
672 		p++;
673 	*pp = p;
674 	return v;
675 }
getstring(const TCHAR ** pp)676 static TCHAR *getstring (const TCHAR **pp)
677 {
678 	int i;
679 	static TCHAR str[CONFIG_BLEN];
680 	const TCHAR *p = *pp;
681 	bool quoteds = false;
682 	bool quotedd = false;
683 
684 	if (*p == 0)
685 		return 0;
686 	i = 0;
687 	while (*p != 0 && i < 1000 - 1) {
688 		if (*p == '\"')
689 			quotedd = quotedd ? false : true;
690 		if (*p == '\'')
691 			quoteds = quoteds ? false : true;
692 		if (!quotedd && !quoteds) {
693 			if (*p == '.' || *p == ',')
694 				break;
695 		}
696 		str[i++] = *p++;
697 	}
698 	if (*p == '.' || *p == ',')
699 		p++;
700 	str[i] = 0;
701 	*pp = p;
702 	return str;
703 }
704 
reset_inputdevice_settings(struct uae_input_device * uid)705 static void reset_inputdevice_settings (struct uae_input_device *uid)
706 {
707 	for (int l = 0; l < MAX_INPUT_DEVICE_EVENTS; l++) {
708 		for (int i = 0; i < MAX_INPUT_SUB_EVENT_ALL; i++) {
709 			uid->eventid[l][i] = 0;
710 			uid->flags[l][i] = 0;
711 			xfree (uid->custom[l][i]);
712 			uid->custom[l][i] = NULL;
713 		}
714 	}
715 }
reset_inputdevice_slot(struct uae_prefs * prefs,int slot)716 static void reset_inputdevice_slot (struct uae_prefs *prefs, int slot)
717 {
718 	for (int m = 0; m < MAX_INPUT_DEVICES; m++) {
719 		reset_inputdevice_settings (&prefs->joystick_settings[slot][m]);
720 		reset_inputdevice_settings (&prefs->mouse_settings[slot][m]);
721 		reset_inputdevice_settings (&prefs->keyboard_settings[slot][m]);
722 	}
723 }
reset_inputdevice_config(struct uae_prefs * prefs)724 void reset_inputdevice_config (struct uae_prefs *prefs)
725 {
726 	for (int i = 0; i< MAX_INPUT_SETTINGS; i++)
727 		reset_inputdevice_slot (prefs, i);
728 }
729 
730 
set_kbr_default_event(struct uae_input_device * kbr,struct uae_input_device_kbr_default * trans,int num)731 static void set_kbr_default_event (struct uae_input_device *kbr, struct uae_input_device_kbr_default *trans, int num)
732 {
733 	for (int i = 0; trans[i].scancode >= 0; i++) {
734 		if (kbr->extra[num] == trans[i].scancode) {
735 			int k;
736 			for (k = 0; k < MAX_INPUT_SUB_EVENT; k++) {
737 				if (kbr->eventid[num][k] == 0)
738 					break;
739 			}
740 			if (k == MAX_INPUT_SUB_EVENT) {
741 				write_log (_T("corrupt default keyboard mappings\n"));
742 				return;
743 			}
744 			int l = 0;
745 			while (k < MAX_INPUT_SUB_EVENT && trans[i].node[l].evt) {
746 				int evt = trans[i].node[l].evt;
747 				if (evt < 0 || evt >= INPUTEVENT_SPC_LAST)
748 					gui_message(_T("invalid event in default keyboard table!"));
749 				kbr->eventid[num][k] = evt;
750 				kbr->flags[num][k] = trans[i].node[l].flags;
751 				l++;
752 				k++;
753 			}
754 			break;
755 		}
756 	}
757 }
758 
clear_id(struct uae_input_device * id)759 static void clear_id (struct uae_input_device *id)
760 {
761 #ifndef	_DEBUG
762 	int i, j;
763 	for (i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++) {
764 		for (j = 0; j < MAX_INPUT_SUB_EVENT_ALL; j++)
765 			xfree (id->custom[i][j]);
766 	}
767 #endif
768 	TCHAR *cn = id->configname;
769 	TCHAR *n = id->name;
770 	memset (id, 0, sizeof (struct uae_input_device));
771 	id->configname = cn;
772 	id->name = n;
773 }
774 
set_kbr_default(struct uae_prefs * p,int index,int devnum,struct uae_input_device_kbr_default * trans)775 static void set_kbr_default (struct uae_prefs *p, int index, int devnum, struct uae_input_device_kbr_default *trans)
776 {
777 	int i, j;
778 	struct uae_input_device *kbr;
779 	struct inputdevice_functions *id = &idev[IDTYPE_KEYBOARD];
780 	uae_u32 scancode;
781 
782 	if (!trans)
783 		return;
784 	for (j = 0; j < MAX_INPUT_DEVICES; j++) {
785 		if (devnum >= 0 && devnum != j)
786 			continue;
787 		kbr = &p->keyboard_settings[index][j];
788 		for (i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++) {
789 			clear_id (kbr);
790 			kbr->extra[i] = -1;
791 		}
792 		if (j < id->get_num ()) {
793 			if (input_get_default_keyboard (j))
794 				kbr->enabled = 1;
795 			for (i = 0; i < id->get_widget_num (j); i++) {
796 				id->get_widget_type (j, i, 0, &scancode);
797 				kbr->extra[i] = scancode;
798 				set_kbr_default_event (kbr, trans, i);
799 			}
800 		}
801 	}
802 }
803 
inputdevice_default_kb(struct uae_prefs * p,int num)804 static void inputdevice_default_kb (struct uae_prefs *p, int num)
805 {
806 	if (num == GAMEPORT_INPUT_SETTINGS) {
807 		if (p->jports[0].id != JPORT_CUSTOM || p->jports[1].id != JPORT_CUSTOM)
808 			reset_inputdevice_slot (p, num);
809 	}
810 	set_kbr_default (p, num, -1, keyboard_default);
811 }
inputdevice_default_kb_all(struct uae_prefs * p)812 static void inputdevice_default_kb_all (struct uae_prefs *p)
813 {
814 	for (int i = 0; i < MAX_INPUT_SETTINGS; i++)
815 		inputdevice_default_kb (p, i);
816 }
817 
read_slot(const TCHAR * parm,int num,int joystick,int button,struct uae_input_device * id,int keynum,int subnum,struct inputevent * ie,uae_u64 flags,int port,TCHAR * custom)818 static bool read_slot (const TCHAR *parm, int num, int joystick, int button, struct uae_input_device *id, int keynum, int subnum, struct inputevent *ie, uae_u64 flags, int port, TCHAR *custom)
819 {
820 	int mask;
821 
822 	if (custom == NULL && ie->name == NULL) {
823 		if (!_tcscmp (parm, _T("NULL"))) {
824 			if (joystick < 0) {
825 				id->eventid[keynum][subnum] = 0;
826 				id->flags[keynum][subnum] = 0;
827 			} else if (button) {
828 				id->eventid[num + ID_BUTTON_OFFSET][subnum] = 0;
829 				id->flags[num + ID_BUTTON_OFFSET][subnum] = 0;
830 			} else {
831 				id->eventid[num + ID_AXIS_OFFSET][subnum] = 0;
832 				id->flags[num + ID_AXIS_OFFSET][subnum] = 0;
833 			}
834 		}
835 		return false;
836 	}
837 	if (custom)
838 		ie = &events[INPUTEVENT_SPC_CUSTOM_EVENT];
839 
840 	if (joystick < 0) {
841 		if (!(ie->allow_mask & AM_K))
842 			return false;
843 		id->eventid[keynum][subnum] = ie - events;
844 		id->flags[keynum][subnum] = flags;
845 		id->port[keynum][subnum] = port;
846 		xfree (id->custom[keynum][subnum]);
847 		id->custom[keynum][subnum] = custom;
848 	} else  if (button) {
849 		if (joystick)
850 			mask = AM_JOY_BUT;
851 		else
852 			mask = AM_MOUSE_BUT;
853 		if (!(ie->allow_mask & mask))
854 			return false;
855 		id->eventid[num + ID_BUTTON_OFFSET][subnum] = ie - events;
856 		id->flags[num + ID_BUTTON_OFFSET][subnum] = flags;
857 		id->port[num + ID_BUTTON_OFFSET][subnum] = port;
858 		xfree (id->custom[num + ID_BUTTON_OFFSET][subnum]);
859 		id->custom[num + ID_BUTTON_OFFSET][subnum] = custom;
860 	} else {
861 		if (joystick)
862 			mask = AM_JOY_AXIS;
863 		else
864 			mask = AM_MOUSE_AXIS;
865 		if (!(ie->allow_mask & mask))
866 			return false;
867 		id->eventid[num + ID_AXIS_OFFSET][subnum] = ie - events;
868 		id->flags[num + ID_AXIS_OFFSET][subnum] = flags;
869 		id->port[num + ID_AXIS_OFFSET][subnum] = port;
870 		xfree (id->custom[num + ID_AXIS_OFFSET][subnum]);
871 		id->custom[num + ID_AXIS_OFFSET][subnum] = custom;
872 	}
873 	return true;
874 }
875 
readevent(const TCHAR * name,TCHAR ** customp)876 static struct inputevent *readevent (const TCHAR *name, TCHAR **customp)
877 {
878 	int i = 1;
879 	while (events[i].name) {
880 		if (!_tcscmp (events[i].confname, name))
881 			return &events[i];
882 		i++;
883 	}
884 	if (_tcslen (name) > 2 && name[0] == '\'' && name[_tcslen (name) - 1] == '\'') {
885 		TCHAR *custom = my_strdup (name + 1);
886 		custom[_tcslen (custom) - 1] = 0;
887 		*customp = custom;
888 	}
889 	return &events[0];
890 }
891 
read_inputdevice_config(struct uae_prefs * pr,const TCHAR * option,TCHAR * value)892 void read_inputdevice_config (struct uae_prefs *pr, const TCHAR *option, TCHAR *value)
893 {
894 	struct uae_input_device *id = 0;
895 	struct inputevent *ie;
896 	int devnum, num, button, joystick, subnum, idnum, keynum;
897 	const TCHAR *p;
898 	TCHAR *p2, *custom;
899 
900 	option += 6; /* "input." */
901 	p = getstring (&option);
902 	if (!strcasecmp (p, _T("config"))) {
903 		pr->input_selected_setting = _tstol (value) - 1;
904 		if (pr->input_selected_setting == -1)
905 			pr->input_selected_setting = GAMEPORT_INPUT_SETTINGS;
906 		if (pr->input_selected_setting < 0 || pr->input_selected_setting > MAX_INPUT_SETTINGS)
907 			pr->input_selected_setting = 0;
908 	}
909 	if (!strcasecmp (p, _T("joymouse_speed_analog")))
910 		pr->input_joymouse_multiplier = _tstol (value);
911 	if (!strcasecmp (p, _T("joymouse_speed_digital")))
912 		pr->input_joymouse_speed = _tstol (value);
913 	if (!strcasecmp (p, _T("joystick_deadzone")))
914 		pr->input_joystick_deadzone = _tstol (value);
915 	if (!strcasecmp (p, _T("joymouse_deadzone")))
916 		pr->input_joymouse_deadzone = _tstol (value);
917 	if (!strcasecmp (p, _T("mouse_speed")))
918 		pr->input_mouse_speed = _tstol (value);
919 	if (!strcasecmp (p, _T("autofire_speed")))
920 		pr->input_autofire_linecnt = _tstol (value);
921 	if (!strcasecmp (p, _T("analog_joystick_multiplier")))
922 		pr->input_analog_joystick_mult = _tstol (value);
923 	if (!strcasecmp (p, _T("analog_joystick_offset")))
924 		pr->input_analog_joystick_offset = _tstol (value);
925 	if (!strcasecmp (p, _T("keyboard_type"))) {
926 		cfgfile_strval (option, value, NULL, &pr->input_analog_joystick_offset, kbtypes, 0);
927 		keyboard_default = keyboard_default_table[pr->input_keyboard_type];
928 		inputdevice_default_kb_all (pr);
929 	}
930 
931 	if (!strcasecmp (p, _T("contact_bounce")))
932 		pr->input_contact_bounce = _tstol (value);
933 
934 	idnum = _tstol (p);
935 	if (idnum <= 0 || idnum > MAX_INPUT_SETTINGS)
936 		return;
937 	idnum--;
938 
939 	if (!_tcscmp (option, _T("name"))) {
940 		if (idnum < GAMEPORT_INPUT_SETTINGS)
941 			_tcscpy (pr->input_config_name[idnum], value);
942 		return;
943 	}
944 
945 	if (_tcsncmp (option, _T("mouse."), 6) == 0) {
946 		p = option + 6;
947 	} else if (_tcsncmp (option, _T("joystick."), 9) == 0) {
948 		p = option + 9;
949 	} else if (_tcsncmp (option, _T("keyboard."), 9) == 0) {
950 		p = option + 9;
951 	} else if (_tcsncmp (option, _T("internal."), 9) == 0) {
952 		p = option + 9;
953 	} else
954 		return;
955 
956 	devnum = getnum (&p);
957 	if (devnum < 0 || devnum >= MAX_INPUT_DEVICES)
958 		return;
959 
960 	p2 = getstring (&p);
961 	if (!p2)
962 		return;
963 
964 	if (_tcsncmp (option, _T("mouse."), 6) == 0) {
965 		id = &pr->mouse_settings[idnum][devnum];
966 		joystick = 0;
967 	} else if (_tcsncmp (option, _T("joystick."), 9) == 0) {
968 		id = &pr->joystick_settings[idnum][devnum];
969 		joystick = 1;
970 	} else if (_tcsncmp (option, _T("keyboard."), 9) == 0) {
971 		id = &pr->keyboard_settings[idnum][devnum];
972 		joystick = -1;
973 	} else if (_tcsncmp (option, _T("internal."), 9) == 0) {
974 		if (devnum > 0)
975 			return;
976 		id = &pr->internalevent_settings[idnum][devnum];
977 		joystick = 1;
978 	}
979 	if (!id)
980 		return;
981 
982 	if (!_tcscmp (p2, _T("name"))) {
983 		xfree (id->configname);
984 		id->configname = my_strdup (value);
985 		return;
986 	}
987 	if (!_tcscmp (p2, _T("friendlyname"))) {
988 		xfree (id->name);
989 		id->name = my_strdup (value);
990 		return;
991 	}
992 
993 	if (!_tcscmp (p2, _T("custom"))) {
994 		int iscustom;
995 		p = value;
996 		iscustom = getnum (&p);
997 		if (idnum == GAMEPORT_INPUT_SETTINGS) {
998 			clear_id (id);
999 			if (joystick < 0)
1000 				set_kbr_default (pr, idnum, devnum, keyboard_default);
1001 			id->enabled = iscustom;
1002 		} else {
1003 			id->enabled = false;
1004 		}
1005 		return;
1006 	}
1007 
1008 	if (!_tcscmp (p2, _T("empty"))) {
1009 		int empty;
1010 		p = value;
1011 		empty = getnum (&p);
1012 		clear_id (id);
1013 		if (!empty) {
1014 			if (joystick < 0)
1015 				set_kbr_default (pr, idnum, devnum, keyboard_default);
1016 		}
1017 		id->enabled = 1;
1018 		if (idnum == GAMEPORT_INPUT_SETTINGS)
1019 			id->enabled = 0;
1020 		return;
1021 	}
1022 
1023 	if (!_tcscmp (p2, _T("disabled"))) {
1024 		int disabled;
1025 		p = value;
1026 		disabled = getnum (&p);
1027 		id->enabled = disabled == 0 ? 1 : 0;
1028 		if (idnum == GAMEPORT_INPUT_SETTINGS)
1029 			id->enabled = 0;
1030 		return;
1031 	}
1032 
1033 	if (idnum == GAMEPORT_INPUT_SETTINGS && id->enabled == 0)
1034 		return;
1035 
1036 	button = 0;
1037 	keynum = 0;
1038 	if (joystick < 0) {
1039 		num = getnum (&p);
1040 		for (keynum = 0; keynum < MAX_INPUT_DEVICE_EVENTS; keynum++) {
1041 			if (id->extra[keynum] == num)
1042 				break;
1043 		}
1044 		if (keynum >= MAX_INPUT_DEVICE_EVENTS)
1045 			return;
1046 	} else {
1047 		button = -1;
1048 		if (!_tcscmp (p2, _T("axis")))
1049 			button = 0;
1050 		else if(!_tcscmp (p2, _T("button")))
1051 			button = 1;
1052 		if (button < 0)
1053 			return;
1054 		num = getnum (&p);
1055 	}
1056 	p = value;
1057 
1058 	custom = NULL;
1059 	for (subnum = 0; subnum < MAX_INPUT_SUB_EVENT; subnum++) {
1060 		uae_u64 flags;
1061 		int port;
1062 		xfree (custom);
1063 		custom = NULL;
1064 		p2 = getstring (&p);
1065 		if (!p2)
1066 			break;
1067 		ie = readevent (p2, &custom);
1068 		flags = 0;
1069 		port = 0;
1070 		if (p[-1] == '.')
1071 			flags = getnum (&p) & ID_FLAG_SAVE_MASK_CONFIG;
1072 		if (p[-1] == '.') {
1073 			if ((p[0] >= 'A' && p[0] <= 'Z') || (p[0] >= 'a' && p[0] <= 'z'))
1074 				flags |= getqual (&p);
1075 			if (p[-1] == '.')
1076 			port = getnum (&p) + 1;
1077 		}
1078 		if (idnum == GAMEPORT_INPUT_SETTINGS && port == 0)
1079 			continue;
1080 		if (p[-1] == '.' && idnum != GAMEPORT_INPUT_SETTINGS) {
1081 			p2 = getstring (&p);
1082 			if (p2) {
1083 				int flags2 = 0;
1084 				if (p[-1] == '.')
1085 					flags2 = getnum (&p) & ID_FLAG_SAVE_MASK_CONFIG;
1086 				if (p[-1] == '.' && ( (p[0] >= 'A' && p[0] <= 'Z') || (p[0] >= 'a' && p[0] <= 'z') ) )
1087 					flags |= getqual (&p);
1088 				TCHAR *custom2 = NULL;
1089 				struct inputevent *ie2 = readevent (p2, &custom2);
1090 				read_slot (p2, num, joystick, button, id, keynum, SPARE_SUB_EVENT, ie2, flags2, MAX_JPORTS + 1, custom2);
1091 			}
1092 		}
1093 
1094 		while (*p != 0) {
1095 			if (p[-1] == ',')
1096 				break;
1097 			p++;
1098 		}
1099 		if (!read_slot (p2, num, joystick, button, id, keynum, subnum, ie, flags, port, custom))
1100 			continue;
1101 		custom = NULL;
1102 	}
1103 	xfree (custom);
1104 }
1105 
1106 static int mouseedge_alive, mousehack_alive_cnt;
1107 static int lastmx, lastmy;
1108 static uaecptr magicmouse_ibase, magicmouse_gfxbase;
1109 static int dimensioninfo_width, dimensioninfo_height, dimensioninfo_dbl;
1110 static int vp_xoffset, vp_yoffset, mouseoffset_x, mouseoffset_y;
1111 static int tablet_maxx, tablet_maxy, tablet_data;
1112 
mousehack_alive(void)1113 int mousehack_alive (void)
1114 {
1115 	return mousehack_alive_cnt > 0 ? mousehack_alive_cnt : 0;
1116 }
1117 
get_base(const uae_char * name)1118 static uaecptr get_base (const uae_char *name)
1119 {
1120 	uaecptr v = get_long (4);
1121 	addrbank *b = &get_mem_bank(v);
1122 
1123 	if (!b || !b->check (v, 400) || b->flags != ABFLAG_RAM)
1124 		return 0;
1125 	v += 378; // liblist
1126 	while ( (v = get_long (v)) ) {
1127 		uae_u32 v2;
1128 		uae_u8 *p;
1129 		b = &get_mem_bank (v);
1130 		if (!b || !b->check (v, 32) || b->flags != ABFLAG_RAM)
1131 			goto fail;
1132 		v2 = get_long (v + 10); // name
1133 		b = &get_mem_bank (v2);
1134 		if (!b || !b->check (v2, 20))
1135 			goto fail;
1136 		if (b->flags != ABFLAG_ROM && b->flags != ABFLAG_RAM)
1137 			return 0;
1138 		p = b->xlateaddr (v2);
1139 		if (!memcmp (p, name, strlen (name) + 1)) {
1140 			TCHAR *s = au (name);
1141 			write_log (_T("get_base('%s')=%08x\n"), s, v);
1142 			xfree (s);
1143 			return v;
1144 		}
1145 	}
1146 	return 0;
1147 fail:
1148 	{
1149 		TCHAR *s = au (name);
1150 		write_log (_T("get_base('%s') failed, invalid library list\n"), s);
1151 		xfree (s);
1152 	}
1153 	return 0xffffffff;
1154 }
1155 
get_intuitionbase(void)1156 static uaecptr get_intuitionbase (void)
1157 {
1158 	if (magicmouse_ibase == 0xffffffff)
1159 		return 0;
1160 	if (magicmouse_ibase)
1161 		return magicmouse_ibase;
1162 	magicmouse_ibase = get_base ("intuition.library");
1163 	return magicmouse_ibase;
1164 }
1165 
1166 /// REMOVEME: only use in inputdevice_mh_abs_v36() which is marked "#if 0"
1167 #if 0
1168 static uaecptr get_gfxbase (void)
1169 {
1170 	if (magicmouse_gfxbase == 0xffffffff)
1171 		return 0;
1172 	if (magicmouse_gfxbase)
1173 		return magicmouse_gfxbase;
1174 	magicmouse_gfxbase = get_base ("graphics.library");
1175 	return magicmouse_gfxbase;
1176 }
1177 #endif // 0
1178 
1179 #define MH_E 0
1180 #define MH_CNT 2
1181 #define MH_MAXX 4
1182 #define MH_MAXY 6
1183 #define MH_MAXZ 8
1184 #define MH_X 10
1185 #define MH_Y 12
1186 #define MH_Z 14
1187 #define MH_RESX 16
1188 #define MH_RESY 18
1189 #define MH_MAXAX 20
1190 #define MH_MAXAY 22
1191 #define MH_MAXAZ 24
1192 #define MH_AX 26
1193 #define MH_AY 28
1194 #define MH_AZ 30
1195 #define MH_PRESSURE 32
1196 #define MH_BUTTONBITS 34
1197 #define MH_INPROXIMITY 38
1198 #define MH_ABSX 40
1199 #define MH_ABSY 42
1200 
1201 #define MH_END 44
1202 #define MH_START 4
1203 
inputdevice_is_tablet(void)1204 int inputdevice_is_tablet (void)
1205 {
1206 /* REMOVEME:
1207  * nowhere used
1208  */
1209 #if 0
1210 	int v;
1211 #endif
1212 	if (!uae_boot_rom)
1213 		return 0;
1214 	if (currprefs.input_tablet == TABLET_OFF)
1215 		return 0;
1216 	if (currprefs.input_tablet == TABLET_MOUSEHACK)
1217 		return -1;
1218 	return 0;
1219 }
1220 
1221 static uaecptr mousehack_address;
1222 static bool mousehack_enabled;
1223 
mousehack_reset(void)1224 static void mousehack_reset (void)
1225 {
1226 	dimensioninfo_width = dimensioninfo_height = 0;
1227 	mouseoffset_x = mouseoffset_y = 0;
1228 	dimensioninfo_dbl = 0;
1229 	mousehack_alive_cnt = 0;
1230 	vp_xoffset = vp_yoffset = 0;
1231 	tablet_data = 0;
1232 	if (mousehack_address)
1233 		put_byte (mousehack_address + MH_E, 0);
1234 	mousehack_address = 0;
1235 	mousehack_enabled = false;
1236 }
1237 
mousehack_enable(void)1238 static bool mousehack_enable (void)
1239 {
1240 #ifdef FILESYS /* Internal mousehack depends on filesys boot-rom */
1241 	int mode;
1242 
1243 	if (!uae_boot_rom || currprefs.input_tablet == TABLET_OFF)
1244 		return false;
1245 	if (mousehack_address && mousehack_enabled)
1246 		return true;
1247 	mode = 0x80;
1248 	if (currprefs.input_tablet == TABLET_MOUSEHACK)
1249 		mode |= 1;
1250 	if (inputdevice_is_tablet () > 0)
1251 		mode |= 2;
1252 	if (mousehack_address) {
1253 	write_log (_T("Mouse driver enabled (%s)\n"), ((mode & 3) == 3 ? _T("tablet+mousehack") : ((mode & 3) == 2) ? _T("tablet") : _T("mousehack")));
1254 		put_byte (mousehack_address + MH_E, mode);
1255 		mousehack_enabled = true;
1256 	}
1257 	return true;
1258 #endif
1259 }
1260 
input_mousehack_mouseoffset(uaecptr pointerprefs)1261 void input_mousehack_mouseoffset (uaecptr pointerprefs)
1262 {
1263 	mouseoffset_x = (uae_s16)get_word (pointerprefs + 28);
1264 	mouseoffset_y = (uae_s16)get_word (pointerprefs + 30);
1265 }
1266 
input_mousehack_status(int mode,uaecptr diminfo,uaecptr dispinfo,uaecptr vp,uae_u32 moffset)1267 int input_mousehack_status (int mode, uaecptr diminfo, uaecptr dispinfo, uaecptr vp, uae_u32 moffset)
1268 {
1269 	if (mode == 4) {
1270 		return mousehack_enable () ? 1 : 0;
1271 	} else if (mode == 5) {
1272 		mousehack_address = m68k_dreg (regs, 0);
1273 		mousehack_enable ();
1274 	} else if (mode == 0) {
1275 		if (mousehack_address) {
1276 		uae_u8 v = get_byte (mousehack_address + MH_E);
1277 		v |= 0x40;
1278 		put_byte (mousehack_address + MH_E, v);
1279 		write_log (_T("Tablet driver running (%08x,%02x)\n"), mousehack_address, v);
1280 		}
1281 	} else if (mode == 1) {
1282 		int x1 = -1, y1 = -1, x2 = -1, y2 = -1;
1283 		uae_u32 props = 0;
1284 		dimensioninfo_width = -1;
1285 		dimensioninfo_height = -1;
1286 		vp_xoffset = 0;
1287 		vp_yoffset = 0;
1288 		if (diminfo) {
1289 			x1 = get_word (diminfo + 50);
1290 			y1 = get_word (diminfo + 52);
1291 			x2 = get_word (diminfo + 54);
1292 			y2 = get_word (diminfo + 56);
1293 			dimensioninfo_width = x2 - x1 + 1;
1294 			dimensioninfo_height = y2 - y1 + 1;
1295 		}
1296 		if (vp) {
1297 			vp_xoffset = get_word (vp + 28);
1298 			vp_yoffset = get_word (vp + 30);
1299 		}
1300 		if (dispinfo)
1301 			props = get_long (dispinfo + 18);
1302 		dimensioninfo_dbl = (props & 0x00020000) ? 1 : 0;
1303 		write_log (_T("%08x %08x %08x (%dx%d)-(%dx%d) d=%dx%d %s\n"),
1304 			diminfo, props, vp, x1, y1, x2, y2, vp_xoffset, vp_yoffset,
1305 			(props & 0x00020000) ? _T("dbl") : _T(""));
1306 	} else if (mode == 2) {
1307 		if (mousehack_alive_cnt == 0)
1308 			mousehack_alive_cnt = -100;
1309 		else if (mousehack_alive_cnt > 0)
1310 			mousehack_alive_cnt = 100;
1311 	}
1312 	return 1;
1313 }
1314 
1315 void get_custom_mouse_limits (int *w, int *h, int *dx, int *dy, int dbl);
1316 
inputdevice_tablet_strobe(void)1317 void inputdevice_tablet_strobe (void)
1318 {
1319 	mousehack_enable ();
1320 	if (!uae_boot_rom)
1321 		return;
1322 	if (!tablet_data)
1323 		return;
1324 	if (mousehack_address)
1325 		put_byte (mousehack_address + MH_CNT, get_byte (mousehack_address + MH_CNT) + 1);
1326 }
1327 
inputdevice_tablet(int x,int y,int z,int pressure,uae_u32 buttonbits,int inproximity,int ax,int ay,int az)1328 void inputdevice_tablet (int x, int y, int z, int pressure, uae_u32 buttonbits, int inproximity, int ax, int ay, int az)
1329 {
1330 	uae_u8 *p;
1331 	uae_u8 tmp[MH_END];
1332 
1333 	mousehack_enable ();
1334 	if (inputdevice_is_tablet () <= 0 || !mousehack_address)
1335 		return;
1336 	//write_log (_T("%d %d %d %d %08X %d %d %d %d\n"), x, y, z, pressure, buttonbits, inproximity, ax, ay, az);
1337 	p = get_real_address (mousehack_address);
1338 
1339 	memcpy (tmp, p + MH_START, MH_END - MH_START);
1340 #if 0
1341 	if (currprefs.input_magic_mouse) {
1342 		int maxx, maxy, diffx, diffy;
1343 		int dw, dh, ax, ay, aw, ah;
1344 		float xmult, ymult;
1345 		float fx, fy;
1346 
1347 		fx = (float)x;
1348 		fy = (float)y;
1349 		desktop_coords (&dw, &dh, &ax, &ay, &aw, &ah);
1350 		xmult = (float)tablet_maxx / dw;
1351 		ymult = (float)tablet_maxy / dh;
1352 
1353 		diffx = 0;
1354 		diffy = 0;
1355 		if (picasso_on) {
1356 			maxx = gfxvidinfo.width;
1357 			maxy = gfxvidinfo.height;
1358 		} else {
1359 			get_custom_mouse_limits (&maxx, &maxy, &diffx, &diffy);
1360 		}
1361 		diffx += ax;
1362 		diffy += ah;
1363 
1364 		fx -= diffx * xmult;
1365 		if (fx < 0)
1366 			fx = 0;
1367 		if (fx >= aw * xmult)
1368 			fx = aw * xmult - 1;
1369 		fy -= diffy * ymult;
1370 		if (fy < 0)
1371 			fy = 0;
1372 		if (fy >= ah * ymult)
1373 			fy = ah * ymult - 1;
1374 
1375 		x = (int)(fx * (aw * xmult) / tablet_maxx + 0.5);
1376 		y = (int)(fy * (ah * ymult) / tablet_maxy + 0.5);
1377 
1378 	}
1379 #endif
1380 	p[MH_X] = x >> 8;
1381 	p[MH_X + 1] = x;
1382 	p[MH_Y] = y >> 8;
1383 	p[MH_Y + 1] = y;
1384 	p[MH_Z] = z >> 8;
1385 	p[MH_Z + 1] = z;
1386 
1387 	p[MH_AX] = ax >> 8;
1388 	p[MH_AX + 1] = ax;
1389 	p[MH_AY] = ay >> 8;
1390 	p[MH_AY + 1] = ay;
1391 	p[MH_AZ] = az >> 8;
1392 	p[MH_AZ + 1] = az;
1393 
1394 	p[MH_MAXX] = tablet_maxx >> 8;
1395 	p[MH_MAXX + 1] = tablet_maxx;
1396 	p[MH_MAXY] = tablet_maxy >> 8;
1397 	p[MH_MAXY + 1] = tablet_maxy;
1398 
1399 	p[MH_PRESSURE] = pressure >> 8;
1400 	p[MH_PRESSURE + 1] = pressure;
1401 
1402 	p[MH_BUTTONBITS + 0] = buttonbits >> 24;
1403 	p[MH_BUTTONBITS + 1] = buttonbits >> 16;
1404 	p[MH_BUTTONBITS + 2] = buttonbits >>  8;
1405 	p[MH_BUTTONBITS + 3] = buttonbits >>  0;
1406 
1407 	if (inproximity < 0) {
1408 		p[MH_INPROXIMITY] = p[MH_INPROXIMITY + 1] = 0xff;
1409 	} else {
1410 		p[MH_INPROXIMITY] = 0;
1411 		p[MH_INPROXIMITY + 1] = inproximity ? 1 : 0;
1412 	}
1413 
1414 	if (!memcmp (tmp, p + MH_START, MH_END - MH_START))
1415 		return;
1416 
1417 	p[MH_E] = 0xc0 | 2;
1418 	p[MH_CNT]++;
1419 }
1420 
inputdevice_tablet_info(int maxx,int maxy,int maxz,int maxax,int maxay,int maxaz,int xres,int yres)1421 void inputdevice_tablet_info (int maxx, int maxy, int maxz, int maxax, int maxay, int maxaz, int xres, int yres)
1422 {
1423 	uae_u8 *p;
1424 
1425 	if (!uae_boot_rom || !mousehack_address)
1426 		return;
1427 	p = get_real_address (mousehack_address);
1428 
1429 	tablet_maxx = maxx;
1430 	tablet_maxy = maxy;
1431 	p[MH_MAXX] = maxx >> 8;
1432 	p[MH_MAXX + 1] = maxx;
1433 	p[MH_MAXY] = maxy >> 8;
1434 	p[MH_MAXY + 1] = maxy;
1435 	p[MH_MAXZ] = maxz >> 8;
1436 	p[MH_MAXZ + 1] = maxz;
1437 
1438 	p[MH_RESX] = xres >> 8;
1439 	p[MH_RESX + 1] = xres;
1440 	p[MH_RESY] = yres >> 8;
1441 	p[MH_RESY + 1] = yres;
1442 
1443 	p[MH_MAXAX] = maxax >> 8;
1444 	p[MH_MAXAX + 1] = maxax;
1445 	p[MH_MAXAY] = maxay >> 8;
1446 	p[MH_MAXAY + 1] = maxay;
1447 	p[MH_MAXAZ] = maxaz >> 8;
1448 	p[MH_MAXAZ + 1] = maxaz;
1449 }
1450 
1451 
inputdevice_mh_abs(int x,int y,uae_u32 buttonbits)1452 static void inputdevice_mh_abs (int x, int y, uae_u32 buttonbits)
1453 {
1454 	uae_u8 *p;
1455 	uae_u8 tmp1[4], tmp2[4];
1456 
1457 	mousehack_enable ();
1458 	if (!mousehack_address)
1459 		return;
1460 	p = get_real_address (mousehack_address);
1461 
1462 	memcpy (tmp1, p + MH_ABSX, sizeof tmp1);
1463 	memcpy (tmp2, p + MH_BUTTONBITS, sizeof tmp2);
1464 
1465 	x -= mouseoffset_x + 1;
1466 	y -= mouseoffset_y + 2;
1467 
1468 	//write_log (_T("%dx%d %08x\n"), x, y, buttonbits);
1469 
1470 	p[MH_ABSX] = x >> 8;
1471 	p[MH_ABSX + 1] = x;
1472 	p[MH_ABSY] = y >> 8;
1473 	p[MH_ABSY + 1] = y;
1474 
1475 	p[MH_BUTTONBITS + 0] = buttonbits >> 24;
1476 	p[MH_BUTTONBITS + 1] = buttonbits >> 16;
1477 	p[MH_BUTTONBITS + 2] = buttonbits >>  8;
1478 	p[MH_BUTTONBITS + 3] = buttonbits >>  0;
1479 
1480 	if (!memcmp (tmp1, p + MH_ABSX, sizeof tmp1) && !memcmp (tmp2, p + MH_BUTTONBITS, sizeof tmp2))
1481 		return;
1482 	p[MH_E] = 0xc0 | 1;
1483 	p[MH_CNT]++;
1484 	tablet_data = 1;
1485 }
1486 
1487 #ifdef FILESYS
1488 /* FIXME
1489  * Was "if 0" already, also in moushack_helper(). Why?
1490  */
1491 #if 0
1492 static void inputdevice_mh_abs_v36 (int x, int y)
1493 {
1494 	uae_u8 *p;
1495 	uae_u8 tmp[MH_END];
1496 	uae_u32 off;
1497 	int maxx, maxy, diffx, diffy;
1498 	int fdy, fdx, fmx, fmy;
1499 
1500 	mousehack_enable ();
1501 	off = getmhoffset ();
1502 	p = rtarea + off;
1503 
1504 	memcpy (tmp, p + MH_START, MH_END - MH_START);
1505 
1506 	getgfxoffset (&fdx, &fdy, &fmx, &fmy);
1507 	x -= fdx;
1508 	y -= fdy;
1509 	x += vp_xoffset;
1510 	y += vp_yoffset;
1511 
1512 	diffx = diffy = 0;
1513 	maxx = maxy = 0;
1514 
1515 	if (picasso_on) {
1516 		maxx = picasso96_state.Width;
1517 		maxy = picasso96_state.Height;
1518 	} else if (dimensioninfo_width > 0 && dimensioninfo_height > 0) {
1519 		maxx = dimensioninfo_width;
1520 		maxy = dimensioninfo_height;
1521 		get_custom_mouse_limits (&maxx, &maxy, &diffx, &diffy, dimensioninfo_dbl);
1522 	} else {
1523 		uaecptr gb = get_gfxbase ();
1524 		maxx = 0; maxy = 0;
1525 		if (gb) {
1526 			maxy = get_word (gb + 216);
1527 			maxx = get_word (gb + 218);
1528 		}
1529 		get_custom_mouse_limits (&maxx, &maxy, &diffx, &diffy, 0);
1530 	}
1531 #if 0
1532 	{
1533 		uaecptr gb = get_intuitionbase ();
1534 		maxy = get_word (gb + 1344 + 2);
1535 		maxx = get_word (gb + 1348 + 2);
1536 		write_log (_T("%d %d\n"), maxx, maxy);
1537 	}
1538 #endif
1539 #if 1
1540 	{
1541 		uaecptr gb = get_gfxbase ();
1542 		uaecptr view = get_long (gb + 34);
1543 		if (view) {
1544 			uaecptr vp = get_long (view);
1545 			if (vp) {
1546 				int w, h, dw, dh;
1547 				w = get_word (vp + 24);
1548 				h = get_word (vp + 26) * 2;
1549 				dw = get_word (vp + 28);
1550 				dh = get_word (vp + 30);
1551 				//write_log (_T("%d %d %d %d\n"), w, h, dw, dh);
1552 				if (w < maxx)
1553 					maxx = w;
1554 				if (h < maxy)
1555 					maxy = h;
1556 				x -= dw;
1557 				y -= dh;
1558 			}
1559 		}
1560 		//write_log (_T("* %d %d\n"), get_word (gb + 218), get_word (gb + 216));
1561 	}
1562 	//write_log (_T("%d %d\n"), maxx, maxy);
1563 #endif
1564 
1565 	maxx = maxx * 1000 / fmx;
1566 	maxy = maxy * 1000 / fmy;
1567 
1568 	if (maxx <= 0)
1569 		maxx = 1;
1570 	if (maxy <= 0)
1571 		maxy = 1;
1572 
1573 	x -= diffx;
1574 	if (x < 0)
1575 		x = 0;
1576 	if (x >= maxx)
1577 		x = maxx - 1;
1578 
1579 	y -= diffy;
1580 	if (y < 0)
1581 		y = 0;
1582 	if (y >= maxy)
1583 		y = maxy - 1;
1584 
1585 	//write_log (_T("%d %d %d %d\n"), x, y, maxx, maxy);
1586 
1587 	p[MH_X] = x >> 8;
1588 	p[MH_X + 1] = x;
1589 	p[MH_Y] = y >> 8;
1590 	p[MH_Y + 1] = y;
1591 	p[MH_MAXX] = maxx >> 8;
1592 	p[MH_MAXX + 1] = maxx;
1593 	p[MH_MAXY] = maxy >> 8;
1594 	p[MH_MAXY + 1] = maxy;
1595 
1596 	p[MH_Z] = p[MH_Z + 1] = 0;
1597 	p[MH_MAXZ] = p[MH_MAXZ + 1] = 0;
1598 	p[MH_AX] = p[MH_AX + 1] = 0;
1599 	p[MH_AY] = p[MH_AY + 1] = 0;
1600 	p[MH_AZ] = p[MH_AZ + 1] = 0;
1601 	p[MH_PRESSURE] = p[MH_PRESSURE + 1] = 0;
1602 	p[MH_INPROXIMITY] = p[MH_INPROXIMITY + 1] = 0xff;
1603 
1604 	if (!memcmp (tmp, p + MH_START, MH_END - MH_START))
1605 		return;
1606 	p[MH_CNT]++;
1607 	tablet_data = 1;
1608 }
1609 #endif // 0
1610 #endif // FILESYS
1611 
mousehack_helper(uae_u32 buttonmask)1612 static void mousehack_helper (uae_u32 buttonmask)
1613 {
1614 #ifdef FILESYS /* Internal mousehack depends on filesys boot-rom */
1615 	int x, y;
1616 	int fdy, fdx, fmx, fmy;
1617 
1618 	if (currprefs.input_magic_mouse == 0 && currprefs.input_tablet < TABLET_MOUSEHACK)
1619 		return;
1620 #if 0
1621 	if (kickstart_version >= 36) {
1622 		inputdevice_mh_abs_v36 (lastmx, lastmy);
1623 		return;
1624 	}
1625 #endif
1626 	x = lastmx;
1627 	y = lastmy;
1628 	getgfxoffset (&fdx, &fdy, &fmx, &fmy);
1629 
1630 #ifdef PICASSO96
1631 	if (picasso_on) {
1632 		x -= picasso96_state.XOffset;
1633 		y -= picasso96_state.YOffset;
1634 		x = (int)(x * fmx);
1635 		y = (int)(y * fmy);
1636 		x -= (int)(fdx * fmx);
1637 		y -= (int)(fdy * fmy);
1638 	} else
1639 #endif
1640 	{
1641 		x = (int)(x * fmx);
1642 		y = (int)(y * fmy);
1643 		x -= (int)(fdx * fmx) - 1;
1644 		y -= (int)(fdy * fmy) - 2;
1645 		if (x < 0)
1646 			x = 0;
1647 		if (x >= gfxvidinfo.outwidth)
1648 			x = gfxvidinfo.outwidth - 1;
1649 		if (y < 0)
1650 			y = 0;
1651 		if (y >= gfxvidinfo.outheight)
1652 			y = gfxvidinfo.outheight - 1;
1653 		x = coord_native_to_amiga_x (x);
1654 		y = coord_native_to_amiga_y (y) << 1;
1655 	}
1656 	inputdevice_mh_abs (x, y, buttonmask);
1657 #endif
1658 }
1659 
1660 static int mouseedge_x, mouseedge_y, mouseedge_time;
1661 #define MOUSEEDGE_RANGE 100
1662 #define MOUSEEDGE_TIME 2
1663 
1664 extern void setmouseactivexy (int,int,int);
1665 
mouseedge(void)1666 static int mouseedge (void)
1667 {
1668 	int x, y, dir;
1669 	uaecptr ib;
1670 	static int melast_x, melast_y;
1671 	static int isnonzero;
1672 
1673 	if (currprefs.input_magic_mouse == 0 || currprefs.input_tablet > 0)
1674 		return 0;
1675 	if (magicmouse_ibase == 0xffffffff)
1676 		return 0;
1677 	dir = 0;
1678 	if (!mouseedge_time) {
1679 		isnonzero = 0;
1680 		goto end;
1681 	}
1682 	ib = get_intuitionbase ();
1683 	if (!ib || get_word (ib + 20) < 31) // version < 31
1684 		return 0;
1685 	x = get_word (ib + 70);
1686 	y = get_word (ib + 68);
1687 	if (x || y)
1688 		isnonzero = 1;
1689 	if (!isnonzero)
1690 		return 0;
1691 	if (melast_x == x) {
1692 		if (mouseedge_x < -MOUSEEDGE_RANGE) {
1693 			mouseedge_x = 0;
1694 			dir |= 1;
1695 			goto end;
1696 		}
1697 		if (mouseedge_x > MOUSEEDGE_RANGE) {
1698 			mouseedge_x = 0;
1699 			dir |= 2;
1700 			goto end;
1701 		}
1702 	} else {
1703 		mouseedge_x = 0;
1704 		melast_x = x;
1705 	}
1706 	if (melast_y == y) {
1707 		if (mouseedge_y < -MOUSEEDGE_RANGE) {
1708 			mouseedge_y = 0;
1709 			dir |= 4;
1710 			goto end;
1711 		}
1712 		if (mouseedge_y > MOUSEEDGE_RANGE) {
1713 			mouseedge_y = 0;
1714 			dir |= 8;
1715 			goto end;
1716 		}
1717 	} else {
1718 		mouseedge_y = 0;
1719 		melast_y = y;
1720 	}
1721 	return 1;
1722 
1723 end:
1724 	mouseedge_time = 0;
1725 	if (dir) {
1726 		if (!picasso_on) {
1727 			int aw = 0, ah = 0, dx, dy;
1728 			get_custom_mouse_limits (&aw, &ah, &dx, &dy, dimensioninfo_dbl);
1729 			x += dx;
1730 			y += dy;
1731 		}
1732 		if (!dmaen (DMA_SPRITE))
1733 			setmouseactivexy (x, y, 0);
1734 		else
1735 			setmouseactivexy (x, y, dir);
1736 	}
1737 	return 1;
1738 }
1739 
magicmouse_alive(void)1740 int magicmouse_alive (void)
1741 {
1742 	return mouseedge_alive > 0;
1743 }
1744 
adjust(int val)1745 STATIC_INLINE int adjust (int val)
1746 {
1747 	if (val > 127)
1748 		return 127;
1749 	else if (val < -127)
1750 		return -127;
1751 	return val;
1752 }
1753 
getbuttonstate(int joy,int button)1754 static int getbuttonstate (int joy, int button)
1755 {
1756 	return (joybutton[joy] & (1 << button)) ? 1 : 0;
1757 }
1758 
getvelocity(int num,int subnum,int pct)1759 static int getvelocity (int num, int subnum, int pct)
1760 {
1761 	int val;
1762 	int v;
1763 
1764 	if (pct > 1000)
1765 		pct = 1000;
1766 	val = mouse_delta[num][subnum];
1767 	v = val * pct / 1000;
1768 	if (!v) {
1769 		if (val < -maxvpos / 2)
1770 			v = -2;
1771 		else if (val < 0)
1772 			v = -1;
1773 		else if (val > maxvpos / 2)
1774 			v = 2;
1775 		else if (val > 0)
1776 			v = 1;
1777 	}
1778 	if (!mouse_deltanoreset[num][subnum]) {
1779 		mouse_delta[num][subnum] -= v;
1780 		gui_gameport_axis_change (num, subnum * 2 + 0, 0, -1);
1781 		gui_gameport_axis_change (num, subnum * 2 + 1, 0, -1);
1782 	}
1783 	return v;
1784 }
1785 
1786 #define MOUSEXY_MAX 16384
1787 
mouseupdate(int pct,bool vsync)1788 static void mouseupdate (int pct, bool vsync)
1789 {
1790 	int v, i;
1791 	int max = 120;
1792 	static int mxd, myd;
1793 
1794 	if (vsync) {
1795 		if (mxd < 0) {
1796 			if (mouseedge_x > 0)
1797 				mouseedge_x = 0;
1798 			else
1799 				mouseedge_x += mxd;
1800 			mouseedge_time = MOUSEEDGE_TIME;
1801 		}
1802 		if (mxd > 0) {
1803 			if (mouseedge_x < 0)
1804 				mouseedge_x = 0;
1805 			else
1806 				mouseedge_x += mxd;
1807 			mouseedge_time = MOUSEEDGE_TIME;
1808 		}
1809 		if (myd < 0) {
1810 			if (mouseedge_y > 0)
1811 				mouseedge_y = 0;
1812 			else
1813 				mouseedge_y += myd;
1814 			mouseedge_time = MOUSEEDGE_TIME;
1815 		}
1816 		if (myd > 0) {
1817 			if (mouseedge_y < 0)
1818 				mouseedge_y = 0;
1819 			else
1820 				mouseedge_y += myd;
1821 			mouseedge_time = MOUSEEDGE_TIME;
1822 		}
1823 		if (mouseedge_time > 0) {
1824 			mouseedge_time--;
1825 			if (mouseedge_time == 0) {
1826 				mouseedge_x = 0;
1827 				mouseedge_y = 0;
1828 			}
1829 		}
1830 		mxd = 0;
1831 		myd = 0;
1832 	}
1833 
1834 	for (i = 0; i < 2; i++) {
1835 
1836 		if (mouse_port[i]) {
1837 
1838 			v = getvelocity (i, 0, pct);
1839 			mxd += v;
1840 			mouse_x[i] += v;
1841 			if (mouse_x[i] < 0) {
1842 				mouse_x[i] += MOUSEXY_MAX;
1843 				mouse_frame_x[i] = mouse_x[i] - v;
1844 			}
1845 			if (mouse_x[i] >= MOUSEXY_MAX) {
1846 				mouse_x[i] -= MOUSEXY_MAX;
1847 				mouse_frame_x[i] = mouse_x[i] - v;
1848 			}
1849 
1850 			v = getvelocity (i, 1, pct);
1851 			myd += v;
1852 			mouse_y[i] += v;
1853 			if (mouse_y[i] < 0) {
1854 				mouse_y[i] += MOUSEXY_MAX;
1855 				mouse_frame_y[i] = mouse_y[i] - v;
1856 			}
1857 			if (mouse_y[i] >= MOUSEXY_MAX) {
1858 				mouse_y[i] -= MOUSEXY_MAX;
1859 				mouse_frame_y[i] = mouse_y[i] - v;
1860 			}
1861 
1862 			v = getvelocity (i, 2, pct);
1863 			if (v > 0)
1864 				record_key (0x7a << 1);
1865 			else if (v < 0)
1866 				record_key (0x7b << 1);
1867 			if (!mouse_deltanoreset[i][2])
1868 				mouse_delta[i][2] = 0;
1869 
1870 			if (mouse_frame_x[i] - mouse_x[i] > max) {
1871 				mouse_x[i] = mouse_frame_x[i] - max;
1872 				mouse_x[i] &= MOUSEXY_MAX - 1;
1873 			}
1874 			if (mouse_frame_x[i] - mouse_x[i] < -max) {
1875 				mouse_x[i] = mouse_frame_x[i] + max;
1876 				mouse_x[i] &= MOUSEXY_MAX - 1;
1877 			}
1878 
1879 			if (mouse_frame_y[i] - mouse_y[i] > max)
1880 				mouse_y[i] = mouse_frame_y[i] - max;
1881 			if (mouse_frame_y[i] - mouse_y[i] < -max)
1882 				mouse_y[i] = mouse_frame_y[i] + max;
1883 		}
1884 
1885 		if (!vsync) {
1886 			mouse_frame_x[i] = mouse_x[i];
1887 			mouse_frame_y[i] = mouse_y[i];
1888 		}
1889 
1890 	}
1891 }
1892 
1893 static int input_vpos, input_frame;
1894 extern int vpos;
readinput(void)1895 static void readinput (void)
1896 {
1897 	uae_u32 totalvpos;
1898 	int diff;
1899 
1900 	totalvpos = input_frame * current_maxvpos () + vpos;
1901 	diff = totalvpos - input_vpos;
1902 	if (diff > 0) {
1903 		if (diff < 10) {
1904 			mouseupdate (0, false);
1905 		} else {
1906 			mouseupdate (diff * 1000 / current_maxvpos (), false);
1907 		}
1908 	}
1909 	input_vpos = totalvpos;
1910 
1911 }
1912 
joymousecounter(int joy)1913 static void joymousecounter (int joy)
1914 {
1915 	int left = 1, right = 1, top = 1, bot = 1;
1916 	int b9, b8, b1, b0;
1917 	int cntx, cnty, ocntx, ocnty;
1918 
1919 	if (joydir[joy] & DIR_LEFT)
1920 		left = 0;
1921 	if (joydir[joy] & DIR_RIGHT)
1922 		right = 0;
1923 	if (joydir[joy] & DIR_UP)
1924 		top = 0;
1925 	if (joydir[joy] & DIR_DOWN)
1926 		bot = 0;
1927 
1928 	b0 = (bot ^ right) ? 1 : 0;
1929 	b1 = (right ^ 1) ? 2 : 0;
1930 	b8 = (top ^ left) ? 1 : 0;
1931 	b9 = (left ^ 1) ? 2 : 0;
1932 
1933 	cntx = b0 | b1;
1934 	cnty = b8 | b9;
1935 	ocntx = mouse_x[joy] & 3;
1936 	ocnty = mouse_y[joy] & 3;
1937 
1938 	if (cntx == 3 && ocntx == 0)
1939 		mouse_x[joy] -= 4;
1940 	else if (cntx == 0 && ocntx == 3)
1941 		mouse_x[joy] += 4;
1942 	mouse_x[joy] = (mouse_x[joy] & 0xfc) | cntx;
1943 
1944 	if (cnty == 3 && ocnty == 0)
1945 		mouse_y[joy] -= 4;
1946 	else if (cnty == 0 && ocnty == 3)
1947 		mouse_y[joy] += 4;
1948 	mouse_y[joy] = (mouse_y[joy] & 0xfc) | cnty;
1949 
1950 	if (!left || !right || !top || !bot) {
1951 		mouse_frame_x[joy] = mouse_x[joy];
1952 		mouse_frame_y[joy] = mouse_y[joy];
1953 	}
1954 }
1955 
getjoystate(int joy)1956 static uae_u16 getjoystate (int joy)
1957 {
1958 	uae_u16 v;
1959 
1960 	v = (uae_u8)mouse_x[joy] | (mouse_y[joy] << 8);
1961 #ifdef DONGLE_DEBUG
1962 	if (notinrom ())
1963 		write_log (_T("JOY%dDAT %04X %s\n"), joy, v, debuginfo (0));
1964 #endif
1965 	if (inputdevice_logging & 2)
1966 		write_log (_T("JOY%dDAT=%04x %08x\n"), joy, v, M68K_GETPC);
1967 	return v;
1968 }
1969 
JOY0DAT(void)1970 uae_u16 JOY0DAT (void)
1971 {
1972 	uae_u16 v;
1973 	readinput ();
1974 	v = getjoystate (0);
1975 	v = dongle_joydat (0, v);
1976 	return v;
1977 }
1978 
JOY1DAT(void)1979 uae_u16 JOY1DAT (void)
1980 {
1981 	uae_u16 v;
1982 	readinput ();
1983 	v = getjoystate (1);
1984 	v = dongle_joydat (1, v);
1985 
1986 	if (inputrecord_debug & 2) {
1987 		if (input_record > 0)
1988 			inprec_recorddebug_cia (v, -1, m68k_getpc ());
1989 		else if (input_play > 0)
1990 			inprec_playdebug_cia (v, -1, m68k_getpc ());
1991 	}
1992 
1993 	return v;
1994 }
1995 
JOYGET(int num)1996 uae_u16 JOYGET (int num)
1997 {
1998 	uae_u16 v;
1999 	v = getjoystate (num);
2000 	v = dongle_joydat (num, v);
2001 	return v;
2002 }
2003 
JOYSET(int num,uae_u16 dat)2004 void JOYSET (int num, uae_u16 dat)
2005 {
2006 	mouse_x[num] = dat & 0xff;
2007 	mouse_y[num] = (dat >> 8) & 0xff;
2008 	mouse_frame_x[num] = mouse_x[num];
2009 	mouse_frame_y[num] = mouse_y[num];
2010 }
2011 
JOYTEST(uae_u16 v)2012 void JOYTEST (uae_u16 v)
2013 {
2014 	mouse_x[0] &= 3;
2015 	mouse_y[0] &= 3;
2016 	mouse_x[1] &= 3;
2017 	mouse_y[1] &= 3;
2018 	mouse_x[0] |= v & 0xFC;
2019 	mouse_x[1] |= v & 0xFC;
2020 	mouse_y[0] |= (v >> 8) & 0xFC;
2021 	mouse_y[1] |= (v >> 8) & 0xFC;
2022 	mouse_frame_x[0] = mouse_x[0];
2023 	mouse_frame_y[0] = mouse_y[0];
2024 	mouse_frame_x[1] = mouse_x[1];
2025 	mouse_frame_y[1] = mouse_y[1];
2026 	dongle_joytest (v);
2027 	if (inputdevice_logging & 2)
2028 		write_log (_T("JOYTEST: %04X PC=%x\n"), v , M68K_GETPC);
2029 }
2030 
parconvert(uae_u8 v,int jd,int shift)2031 static uae_u8 parconvert (uae_u8 v, int jd, int shift)
2032 {
2033 	if (jd & DIR_UP)
2034 		v &= ~(1 << shift);
2035 	if (jd & DIR_DOWN)
2036 		v &= ~(2 << shift);
2037 	if (jd & DIR_LEFT)
2038 		v &= ~(4 << shift);
2039 	if (jd & DIR_RIGHT)
2040 		v &= ~(8 << shift);
2041 	return v;
2042 }
2043 
2044 /* io-pins floating: dir=1 -> return data, dir=0 -> always return 1 */
handle_parport_joystick(int port,uae_u8 pra,uae_u8 dra)2045 uae_u8 handle_parport_joystick (int port, uae_u8 pra, uae_u8 dra)
2046 {
2047 	uae_u8 v;
2048 	switch (port)
2049 	{
2050 	case 0:
2051 		v = (pra & dra) | (dra ^ 0xff);
2052 		if (parport_joystick_enabled) {
2053 			v = parconvert (v, joydir[2], 0);
2054 			v = parconvert (v, joydir[3], 4);
2055 		}
2056 		return v;
2057 	case 1:
2058 		v = ((pra & dra) | (dra ^ 0xff)) & 0x7;
2059 		if (parport_joystick_enabled) {
2060 			if (getbuttonstate (2, 0))
2061 				v &= ~4;
2062 			if (getbuttonstate (3, 0))
2063 				v &= ~1;
2064 			if (getbuttonstate (2, 1) || getbuttonstate (3, 1))
2065 				v &= ~2; /* spare */
2066 		}
2067 		return v;
2068 	default:
2069 		abort ();
2070 		return 0;
2071 	}
2072 }
2073 
2074 /* p5 is 1 or floating = cd32 2-button mode */
cd32padmode(uae_u16 p5dir,uae_u16 p5dat)2075 static bool cd32padmode (uae_u16 p5dir, uae_u16 p5dat)
2076 {
2077 	if (!(potgo_value & p5dir) || ((potgo_value & p5dat) && (potgo_value & p5dir)))
2078 		return false;
2079 	return true;
2080 }
2081 
is_joystick_pullup(int joy)2082 static bool is_joystick_pullup (int joy)
2083 {
2084 	return joymodes[joy] == JSEM_MODE_GAMEPAD;
2085 }
is_mouse_pullup(int joy)2086 static bool is_mouse_pullup (int joy)
2087 {
2088 	return mouse_pullup;
2089 }
2090 
charge_cap(int joy,int idx,int charge)2091 static void charge_cap (int joy, int idx, int charge)
2092 {
2093 	if (charge < -1 || charge > 1)
2094 		charge = charge * 80;
2095 	pot_cap[joy][idx] += charge;
2096 	if (pot_cap[joy][idx] < 0)
2097 		pot_cap[joy][idx] = 0;
2098 	if (pot_cap[joy][idx] > 511)
2099 		pot_cap[joy][idx] = 511;
2100 }
2101 
cap_check(void)2102 static void cap_check (void)
2103 {
2104 	int joy, i;
2105 
2106 	for (joy = 0; joy < 2; joy++) {
2107 		for (i = 0; i < 2; i++) {
2108 			int charge = 0, dong, joypot;
2109 			uae_u16 pdir = 0x0200 << (joy * 4 + i * 2); /* output enable */
2110 			uae_u16 pdat = 0x0100 << (joy * 4 + i * 2); /* data */
2111 			uae_u16 p5dir = 0x0200 << (joy * 4);
2112 			uae_u16 p5dat = 0x0100 << (joy * 4);
2113 			int isbutton = getbuttonstate (joy, i == 0 ? JOYBUTTON_3 : JOYBUTTON_2);
2114 
2115 			if (cd32_pad_enabled[joy]) {
2116 				// only red and blue can be read if CD32 pad and only if it is in normal pad mode
2117 				isbutton |= getbuttonstate (joy, JOYBUTTON_CD32_BLUE);
2118 				// CD32 pad 3rd button line (P5) is always floating
2119 				if (i == 0)
2120 					isbutton = 0;
2121 				if (cd32padmode (p5dir, p5dat))
2122 					continue;
2123 			}
2124 
2125 			dong = dongle_analogjoy (joy, i);
2126 			if (dong >= 0) {
2127 				isbutton = 0;
2128 				joypot = dong;
2129 				if (pot_cap[joy][i] < joypot)
2130 					charge = 1; // slow charge via dongle resistor
2131 			} else {
2132 				joypot = joydirpot[joy][i];
2133 				if (analog_port[joy][i] && pot_cap[joy][i] < joypot)
2134 					charge = 1; // slow charge via pot variable resistor
2135 				if ((is_joystick_pullup (joy) && digital_port[joy][i]) || (is_mouse_pullup (joy) && mouse_port[joy]))
2136 					charge = 1; // slow charge via pull-up resistor
2137 			}
2138 			if (!(potgo_value & pdir)) { // input?
2139 				if (pot_dat_act[joy][i])
2140 					pot_dat[joy][i]++;
2141 				/* first 7 or 8 lines after potgo has been started = discharge cap */
2142 				if (pot_dat_act[joy][i] == 1) {
2143 					if (pot_dat[joy][i] < (currprefs.ntscmode ? POTDAT_DELAY_NTSC : POTDAT_DELAY_PAL)) {
2144 						charge = -2; /* fast discharge delay */
2145 					} else {
2146 						pot_dat_act[joy][i] = 2;
2147 						pot_dat[joy][i] = 0;
2148 					}
2149 				}
2150 				if (dong >= 0) {
2151 					if (pot_dat_act[joy][i] == 2 && pot_cap[joy][i] >= joypot)
2152 						pot_dat_act[joy][i] = 0;
2153 				} else {
2154 					if (analog_port[joy][i] && pot_dat_act[joy][i] == 2 && pot_cap[joy][i] >= joypot)
2155 						pot_dat_act[joy][i] = 0;
2156 					if ((digital_port[joy][i] || mouse_port[joy]) && pot_dat_act[joy][i] == 2) {
2157 						if (pot_cap[joy][i] >= 10 && !isbutton)
2158 							pot_dat_act[joy][i] = 0;
2159 					}
2160 				}
2161 			} else { // output?
2162 				charge = (potgo_value & pdat) ? 2 : -2; /* fast (dis)charge if output */
2163 				if (potgo_value & pdat)
2164 					pot_dat_act[joy][i] = 0; // instant stop if output+high
2165 				if (isbutton)
2166 					pot_dat[joy][i]++; // "free running" if output+low
2167 			}
2168 
2169 			if (isbutton)
2170 				charge = -2; // button press overrides everything
2171 
2172 			if (currprefs.cs_cdtvcd) {
2173 				/* CDTV P9 is not floating */
2174 				if (!(potgo_value & pdir) && i == 1 && charge == 0)
2175 					charge = 2;
2176 			}
2177 			// CD32 pad in 2-button mode: blue button is not floating
2178 #ifdef __LIBRETRO__
2179 			if (i == 1 && charge == 0)
2180 #else
2181 			if (cd32_pad_enabled[joy] && i == 1 && charge == 0)
2182 #endif
2183 				charge = 2;
2184 
2185 			/* official Commodore mouse has pull-up resistors in button lines
2186 			* NOTE: 3rd party mice may not have pullups! */
2187 			if (dong < 0 && (is_mouse_pullup (joy) && mouse_port[joy] && digital_port[joy][i]) && charge == 0)
2188 				charge = 2;
2189 			/* emulate pullup resistor if button mapped because there too many broken
2190 			* programs that read second button in input-mode (and most 2+ button pads have
2191 			* pullups)
2192 			*/
2193 			if (dong < 0 && (is_joystick_pullup (joy) && digital_port[joy][i]) && charge == 0)
2194 				charge = 2;
2195 
2196 			charge_cap (joy, i, charge);
2197 		}
2198 	}
2199 }
2200 
2201 
handle_joystick_buttons(uae_u8 pra,uae_u8 dra)2202 uae_u8 handle_joystick_buttons (uae_u8 pra, uae_u8 dra)
2203 {
2204 	uae_u8 but = 0;
2205 	int i;
2206 
2207 	cap_check ();
2208 	for (i = 0; i < 2; i++) {
2209 		int mask = 0x40 << i;
2210 		if (cd32_pad_enabled[i]) {
2211 			uae_u16 p5dir = 0x0200 << (i * 4);
2212 			uae_u16 p5dat = 0x0100 << (i * 4);
2213 			but |= mask;
2214 			if (!cd32padmode (p5dir, p5dat)) {
2215 				if (getbuttonstate (i, JOYBUTTON_CD32_RED) || getbuttonstate (i, JOYBUTTON_1))
2216 					but &= ~mask;
2217 			}
2218 		} else {
2219 			if (!getbuttonstate (i, JOYBUTTON_1))
2220 				but |= mask;
2221 			if (bouncy && cycles_in_range (bouncy_cycles)) {
2222 				but &= ~mask;
2223 				if (uaerand () & 1)
2224 					but |= mask;
2225 			}
2226 			if (dra & mask)
2227 				but = (but & ~mask) | (pra & mask);
2228 		}
2229 	}
2230 
2231 	if (inputdevice_logging & 4) {
2232 		static uae_u8 old;
2233 		if (but != old)
2234 			write_log (_T("BFE001 R: %02X:%02X %x\n"), dra, but, M68K_GETPC);
2235 		old = but;
2236 	}
2237 	return but;
2238 }
2239 
2240 /* joystick 1 button 1 is used as a output for incrementing shift register */
handle_cd32_joystick_cia(uae_u8 pra,uae_u8 dra)2241 void handle_cd32_joystick_cia (uae_u8 pra, uae_u8 dra)
2242 {
2243 	static int oldstate[2];
2244 	int i;
2245 
2246 	if (inputdevice_logging & 4) {
2247 		write_log (_T("BFE001 W: %02X:%02X %x\n"), dra, pra, M68K_GETPC);
2248 	}
2249 	cap_check ();
2250 	for (i = 0; i < 2; i++) {
2251 		uae_u8 but = 0x40 << i;
2252 		uae_u16 p5dir = 0x0200 << (i * 4); /* output enable P5 */
2253 		uae_u16 p5dat = 0x0100 << (i * 4); /* data P5 */
2254 		if (cd32padmode (p5dir, p5dat)) {
2255 			if ((dra & but) && (pra & but) != oldstate[i]) {
2256 				if (!(pra & but)) {
2257 					cd32_shifter[i]--;
2258 					if (cd32_shifter[i] < 0)
2259 						cd32_shifter[i] = 0;
2260 					if (inputdevice_logging & 4)
2261 						write_log (_T("CD32 %d shift: %d %08x\n"), i, cd32_shifter[i], M68K_GETPC);
2262 				}
2263 			}
2264 		}
2265 		oldstate[i] = dra & pra & but;
2266 	}
2267 }
2268 
2269 /* joystick port 1 button 2 is input for button state */
handle_joystick_potgor(uae_u16 potgor)2270 static uae_u16 handle_joystick_potgor (uae_u16 potgor)
2271 {
2272 	int i;
2273 
2274 	cap_check ();
2275 	for (i = 0; i < 2; i++) {
2276 		uae_u16 p9dir = 0x0800 << (i * 4); /* output enable P9 */
2277 		uae_u16 p9dat = 0x0400 << (i * 4); /* data P9 */
2278 		uae_u16 p5dir = 0x0200 << (i * 4); /* output enable P5 */
2279 		uae_u16 p5dat = 0x0100 << (i * 4); /* data P5 */
2280 
2281 		if (cd32_pad_enabled[i] && cd32padmode (p5dir, p5dat)) {
2282 
2283 			/* p5 is floating in input-mode */
2284 			potgor &= ~p5dat;
2285 			potgor |= potgo_value & p5dat;
2286 			if (!(potgo_value & p9dir))
2287 				potgor |= p9dat;
2288 			/* (P5 output and 1) or floating -> shift register is kept reset (Blue button) */
2289 			if (!(potgo_value & p5dir) || ((potgo_value & p5dat) && (potgo_value & p5dir)))
2290 				cd32_shifter[i] = 8;
2291 			/* shift at 1 == return one, >1 = return button states */
2292 			if (cd32_shifter[i] == 0)
2293 				potgor &= ~p9dat; /* shift at zero == return zero */
2294 			if (cd32_shifter[i] >= 2 && (joybutton[i] & ((1 << JOYBUTTON_CD32_PLAY) << (cd32_shifter[i] - 2))))
2295 				potgor &= ~p9dat;
2296 
2297 		} else {
2298 
2299 			potgor &= ~p5dat;
2300 			if (pot_cap[i][0] > 100)
2301 				potgor |= p5dat;
2302 
2303 
2304 			if (!cd32_pad_enabled[i] || !cd32padmode (p5dir, p5dat)) {
2305 				potgor &= ~p9dat;
2306 				if (pot_cap[i][1] > 100)
2307 					potgor |= p9dat;
2308 			}
2309 
2310 		}
2311 	}
2312 	return potgor;
2313 }
2314 
2315 
2316 static int inputdelay;
2317 
inputdevice_read(void)2318 static void inputdevice_read (void)
2319 {
2320 	//do {
2321 	//	handle_msgpump ();
2322 		idev[IDTYPE_MOUSE].read ();
2323 		idev[IDTYPE_JOYSTICK].read ();
2324 		idev[IDTYPE_KEYBOARD].read ();
2325 	//} while (handle_msgpump ());
2326 }
2327 
inject_events(const TCHAR * str)2328 static void inject_events (const TCHAR *str)
2329 {
2330 	bool quot = false;
2331 	bool first = true;
2332 	uae_u8 keys[300];
2333 	int keycnt = 0;
2334 
2335 	for (;;) {
2336 		TCHAR ch = *str++;
2337 		if (!ch)
2338 			break;
2339 
2340 		if (ch == '\'') {
2341 			first = false;
2342 			quot = !quot;
2343 			continue;
2344 		}
2345 
2346 		if (!quot && (ch == ' ' || first)) {
2347 			const TCHAR *s = str;
2348 			if (first)
2349 				s--;
2350 			while (*s == ' ')
2351 				s++;
2352 			const TCHAR *s2 = s;
2353 			while (*s && *s != ' ')
2354 				s++;
2355 			int s2len = s - s2;
2356 			if (!s2len)
2357 				break;
2358 			for (int i = 1; events[i].name; i++) {
2359 				const TCHAR *cf = events[i].confname;
2360 				if (!_tcsnicmp (cf, _T("KEY_"), 4))
2361 					cf += 4;
2362 				if (events[i].allow_mask == AM_K && !_tcsnicmp (cf, s2, _tcslen (cf)) && s2len == _tcslen (cf)) {
2363 					int j;
2364 					uae_u8 kc = events[i].data << 1;
2365 					TCHAR tch = _totupper (s2[0]);
2366 					if (tch != s2[0]) {
2367 						// release
2368 						for (j = 0; j < keycnt; j++) {
2369 							if (keys[j] == kc)
2370 								keys[j] = 0xff;
2371 						}
2372 						kc |= 0x01;
2373 					} else {
2374 						for (j = 0; j < keycnt; j++) {
2375 							if (keys[j] == kc) {
2376 								kc = 0xff;
2377 							}
2378 						}
2379 						if (kc != 0xff) {
2380 							for (j = 0; j < keycnt; j++) {
2381 								if (keys[j] == 0xff) {
2382 									keys[j] = kc;
2383 									break;
2384 								}
2385 							}
2386 							if (j == keycnt) {
2387 								if (keycnt < sizeof keys)
2388 									keys[keycnt++] = kc;
2389 							}
2390 						}
2391 					}
2392 					if (kc != 0xff) {
2393 						//write_log (_T("%s\n"), cf);
2394 						record_key (kc);
2395 					}
2396 				}
2397 			}
2398 		} else if (quot) {
2399 			ch = _totupper (ch);
2400 			if ((ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9')) {
2401 				for (int i = 1; events[i].name; i++) {
2402 					if (events[i].allow_mask == AM_K && events[i].name[1] == 0 && events[i].name[0] == ch) {
2403 						record_key (events[i].data << 1);
2404 						record_key ((events[i].data << 1) | 0x01);
2405 						//write_log (_T("%c\n"), ch);
2406 					}
2407 				}
2408 			}
2409 		}
2410 		first = false;
2411 	}
2412 	while (--keycnt >= 0) {
2413 		uae_u8 kc = keys[keycnt];
2414 		if (kc != 0xff)
2415 			record_key (kc | 0x01);
2416 	}
2417 }
2418 
handle_custom_event(const TCHAR * custom)2419 static int handle_custom_event (const TCHAR *custom)
2420 {
2421 	TCHAR *p = NULL, *buf = NULL, *nextp = NULL;
2422 	bool noquot = false;
2423 
2424 	if (custom == NULL)
2425 		return 0;
2426 	config_changed = 1;
2427 	write_log (_T("%s\n"), custom);
2428 	p = buf = my_strdup_trim (custom);
2429 	if (p[0] != '\"')
2430 		noquot = true;
2431 	while (p && *p) {
2432 		TCHAR *p2;
2433 		if (!noquot) {
2434 			if (*p != '\"')
2435 				break;
2436 			p++;
2437 			p2 = p;
2438 			while (*p2 != '\"' && *p2 != 0)
2439 				p2++;
2440 			if (*p2 == '\"') {
2441 				*p2++ = 0;
2442 				nextp = p2 + 1;
2443 				while (*nextp == ' ')
2444 					nextp++;
2445 			}
2446 		}
2447 		//write_log (L"-> '%s'\n", p);
2448 		if (!_tcsicmp (p, _T("no_config_check"))) {
2449 			config_changed = 0;
2450 		} else if (!_tcsicmp (p, _T("do_config_check"))) {
2451 			config_changed = 1;
2452 		} else if (!_tcsnicmp (p, _T("dbg "), 4)) {
2453 			debug_parser (p + 4, NULL, -1);
2454 		} else if (!_tcsnicmp (p, _T("kbr "), 4)) {
2455 			inject_events (p + 4);
2456 		} else {
2457 			cfgfile_parse_line (&changed_prefs, p, 0);
2458 		}
2459 		if (noquot)
2460 			break;
2461 		p = nextp;
2462 	}
2463 	xfree (buf);
2464 	return 0;
2465 }
2466 
inputdevice_hsync(void)2467 void inputdevice_hsync (void)
2468 {
2469 	static int cnt;
2470 	cap_check ();
2471 
2472 #ifdef CATWEASEL
2473 	catweasel_hsync ();
2474 #endif
2475 
2476 	for (int i = 0; i < INPUT_QUEUE_SIZE; i++) {
2477 		struct input_queue_struct *iq = &input_queue[i];
2478 		if (iq->linecnt > 0) {
2479 			iq->linecnt--;
2480 			if (iq->linecnt == 0) {
2481 				if (iq->state)
2482 					iq->state = 0;
2483 				else
2484 					iq->state = iq->storedstate;
2485 				if (iq->custom)
2486 					handle_custom_event (iq->custom);
2487 				if (iq->evt)
2488 					handle_input_event (iq->evt, iq->state, iq->max, 0, false, true);
2489 				iq->linecnt = iq->nextlinecnt;
2490 			}
2491 		}
2492 	}
2493 
2494 	if (bouncy && get_cycles () > bouncy_cycles)
2495 		bouncy = 0;
2496 
2497 	if (input_record && input_record != INPREC_RECORD_PLAYING) {
2498 		if (vpos == 0)
2499 			inputdevice_read ();
2500 		inputdelay = 0;
2501 	}
2502 	if (input_play) {
2503 		inprec_playdiskchange ();
2504 		int nr, state, max, autofire;
2505 		while (inprec_playevent (&nr, &state, &max, &autofire))
2506 			handle_input_event (nr, state, max, autofire, false, true);
2507 		//if (vpos == 0)
2508 			//handle_msgpump ();
2509 	}
2510 	if (!input_record && !input_play) {
2511 		if ((++cnt & 63) == 63 ) {
2512 			inputdevice_read ();
2513 		} else if (inputdelay > 0) {
2514 			inputdelay--;
2515 			if (inputdelay == 0)
2516 				inputdevice_read ();
2517 		}
2518 	}
2519 }
2520 
POTDAT(int joy)2521 static uae_u16 POTDAT (int joy)
2522 {
2523 	uae_u16 v = (pot_dat[joy][1] << 8) | pot_dat[joy][0];
2524 	if (inputdevice_logging & 16)
2525 		write_log (_T("POTDAT%d: %04X %08X\n"), joy, v, M68K_GETPC);
2526 	return v;
2527 }
2528 
POT0DAT(void)2529 uae_u16 POT0DAT (void)
2530 {
2531 	return POTDAT (0);
2532 }
POT1DAT(void)2533 uae_u16 POT1DAT (void)
2534 {
2535 	return POTDAT (1);
2536 }
2537 
2538 /* direction=input, data pin floating, last connected logic level or previous status
2539  *                  written when direction was ouput
2540  *                  otherwise it is currently connected logic level.
2541  * direction=output, data pin is current value, forced to zero if joystick button is pressed
2542  * it takes some tens of microseconds before data pin changes state
2543  */
2544 
POTGO(uae_u16 v)2545 void POTGO (uae_u16 v)
2546 {
2547 	int i, j;
2548 
2549 	if (inputdevice_logging & 16)
2550 		write_log (_T("POTGO_W: %04X %08X\n"), v, M68K_GETPC);
2551 #ifdef DONGLE_DEBUG
2552 	if (notinrom ())
2553 		write_log (_T("POTGO %04X %s\n"), v, debuginfo(0));
2554 #endif
2555 	dongle_potgo (v);
2556 	potgo_value = potgo_value & 0x5500; /* keep state of data bits */
2557 	potgo_value |= v & 0xaa00; /* get new direction bits */
2558 	for (i = 0; i < 8; i += 2) {
2559 		uae_u16 dir = 0x0200 << i;
2560 		if (v & dir) {
2561 			uae_u16 data = 0x0100 << i;
2562 			potgo_value &= ~data;
2563 			potgo_value |= v & data;
2564 		}
2565 	}
2566 	for (i = 0; i < 2; i++) {
2567 		if (cd32_pad_enabled[i]) {
2568 			uae_u16 p5dir = 0x0200 << (i * 4); /* output enable P5 */
2569 			uae_u16 p5dat = 0x0100 << (i * 4); /* data P5 */
2570 			if (!(potgo_value & p5dir) || ((potgo_value & p5dat) && (potgo_value & p5dir)))
2571 				cd32_shifter[i] = 8;
2572 		}
2573 	}
2574 	if (v & 1) {
2575 		for (i = 0; i < 2; i++) {
2576 			for (j = 0; j < 2; j++) {
2577 				pot_dat_act[i][j] = 1;
2578 				pot_dat[i][j] = 0;
2579 			}
2580 		}
2581 	}
2582 }
2583 
POTGOR(void)2584 uae_u16 POTGOR (void)
2585 {
2586 	uae_u16 v;
2587 
2588 	v = handle_joystick_potgor (potgo_value) & 0x5500;
2589 	v = dongle_potgor (v);
2590 #ifdef DONGLE_DEBUG
2591 	if (notinrom ())
2592 		write_log (_T("POTGOR %04X %s\n"), v, debuginfo(0));
2593 #endif
2594 	if (inputdevice_logging & 16)
2595 		write_log (_T("POTGO_R: %04X %08X %d %d\n"), v, M68K_GETPC, cd32_shifter[0], cd32_shifter[1]);
2596 	return v;
2597 }
2598 
check_input_queue(int evt)2599 static int check_input_queue (int evt)
2600 {
2601 	struct input_queue_struct *iq;
2602 	int i;
2603 	for (i = 0; i < INPUT_QUEUE_SIZE; i++) {
2604 		iq = &input_queue[i];
2605 		if (iq->evt == evt && iq->linecnt >= 0)
2606 			return i;
2607 	}
2608 	return -1;
2609 }
2610 
queue_input_event(int evt,const TCHAR * custom,int state,int max,int linecnt,int autofire)2611 static void queue_input_event (int evt, const TCHAR *custom, int state, int max, int linecnt, int autofire)
2612 {
2613 	struct input_queue_struct *iq;
2614 	int idx;
2615 
2616 	if (!evt)
2617 		return;
2618 	idx = check_input_queue (evt);
2619 	if (state < 0 && idx >= 0) {
2620 		iq = &input_queue[idx];
2621 		iq->nextlinecnt = -1;
2622 		iq->linecnt = -1;
2623 		iq->evt = 0;
2624 		if (iq->state == 0 && evt > 0)
2625 			handle_input_event (evt, 0, 1, 0, false, false);
2626 	} else if (state >= 0 && idx < 0) {
2627 		if (evt == 0 && custom == NULL)
2628 			return;
2629 		for (idx = 0; idx < INPUT_QUEUE_SIZE; idx++) {
2630 			iq = &input_queue[idx];
2631 			if (iq->linecnt < 0)
2632 				break;
2633 		}
2634 		if (idx == INPUT_QUEUE_SIZE) {
2635 			write_log (_T("input queue overflow\n"));
2636 			return;
2637 		}
2638 		xfree (iq->custom);
2639 		iq->custom = NULL;
2640 		if (custom)
2641 			iq->custom = my_strdup (custom);
2642 		iq->evt = evt;
2643 		iq->state = iq->storedstate = state;
2644 		iq->max = max;
2645 		iq->linecnt = linecnt < 0 ? maxvpos + maxvpos / 2 : linecnt;
2646 		iq->nextlinecnt = autofire > 0 ? linecnt : -1;
2647 	}
2648 }
2649 
2650 static uae_u8 keybuf[256];
2651 static int inputcode_pending, inputcode_pending_state;
2652 
inputdevice_release_all_keys(void)2653 void inputdevice_release_all_keys (void)
2654 {
2655 	int i;
2656 
2657 	for (i = 0; i < 0x80; i++) {
2658 		if (keybuf[i] != 0) {
2659 			keybuf[i] = 0;
2660 			record_key (i << 1|1);
2661 		}
2662 	}
2663 }
2664 
2665 
inputdevice_add_inputcode(int code,int state)2666 void inputdevice_add_inputcode (int code, int state)
2667 {
2668 	inputcode_pending = code;
2669 	inputcode_pending_state = state;
2670 }
2671 
inputdevice_do_keyboard(int code,int state)2672 void inputdevice_do_keyboard (int code, int state)
2673 {
2674 #ifdef CDTV
2675 	if (code >= 0x72 && code <= 0x77) { // CDTV keys
2676 		if (cdtv_front_panel (-1)) {
2677 			// front panel active
2678 			if (!state)
2679 				return;
2680 			cdtv_front_panel (code - 0x72);
2681 			return;
2682 		}
2683 	}
2684 #endif
2685 	if (code < 0x80) {
2686 		uae_u8 key = code | (state ? 0x00 : 0x80);
2687 		keybuf[key & 0x7f] = (key & 0x80) ? 0 : 1;
2688 		if (key == AK_RESETWARNING) {
2689 			resetwarning_do (0);
2690 			return;
2691 		} else if ((keybuf[AK_CTRL] || keybuf[AK_RCTRL]) && keybuf[AK_LAMI] && keybuf[AK_RAMI]) {
2692 			int r = keybuf[AK_LALT] | keybuf[AK_RALT];
2693 			if (!r && currprefs.cs_resetwarning && resetwarning_do (1))
2694 				return;
2695 			memset (keybuf, 0, sizeof (keybuf));
2696 			send_internalevent (INTERNALEVENT_KBRESET);
2697 			uae_reset (r, 1);
2698 		}
2699 		if (record_key ((uae_u8)((key << 1) | (key >> 7)))) {
2700 			if (inputdevice_logging & 1)
2701 				write_log (_T("Amiga key %02X %d\n"), key & 0x7f, key >> 7);
2702 		}
2703 		return;
2704 	}
2705 	inputdevice_add_inputcode (code, state);
2706 }
2707 
2708 // these need cpu trace data
needcputrace(int code)2709 static bool needcputrace (int code)
2710 {
2711 	switch (code)
2712 	{
2713 	case AKS_ENTERGUI:
2714 	case AKS_STATECAPTURE:
2715 	case AKS_STATESAVEQUICK:
2716 	case AKS_STATESAVEQUICK1:
2717 	case AKS_STATESAVEQUICK2:
2718 	case AKS_STATESAVEQUICK3:
2719 	case AKS_STATESAVEQUICK4:
2720 	case AKS_STATESAVEQUICK5:
2721 	case AKS_STATESAVEQUICK6:
2722 	case AKS_STATESAVEQUICK7:
2723 	case AKS_STATESAVEQUICK8:
2724 	case AKS_STATESAVEQUICK9:
2725 	case AKS_STATESAVEDIALOG:
2726 		return true;
2727 	}
2728 	return false;
2729 }
2730 
inputdevice_handle_inputcode(void)2731 void inputdevice_handle_inputcode (void)
2732 {
2733 	static int swapperslot;
2734 	int code = inputcode_pending;
2735 	int state = inputcode_pending_state;
2736 	static int tracer_enable;
2737 
2738 	if (code == 0)
2739 		goto end;
2740 	if (needcputrace (code) && can_cpu_tracer () == true && is_cpu_tracer () == false && !input_play && !input_record && !debugging) {
2741 		if (set_cpu_tracer (true)) {
2742 			tracer_enable = 1;
2743 			return; // wait for next frame
2744 		}
2745 	}
2746 
2747 	inputcode_pending = 0;
2748 
2749 	if (vpos != 0)
2750 		write_log (_T("inputcode=%d but vpos = %d"), code, vpos);
2751 
2752 #ifdef ARCADIA
2753 	switch (code)
2754 	{
2755 	case AKS_ARCADIADIAGNOSTICS:
2756 		arcadia_flag &= ~1;
2757 		arcadia_flag |= state ? 1 : 0;
2758 		break;
2759 	case AKS_ARCADIAPLY1:
2760 		arcadia_flag &= ~4;
2761 		arcadia_flag |= state ? 4 : 0;
2762 		break;
2763 	case AKS_ARCADIAPLY2:
2764 		arcadia_flag &= ~2;
2765 		arcadia_flag |= state ? 2 : 0;
2766 		break;
2767 	case AKS_ARCADIACOIN1:
2768 		if (state)
2769 			arcadia_coin[0]++;
2770 		break;
2771 	case AKS_ARCADIACOIN2:
2772 		if (state)
2773 			arcadia_coin[1]++;
2774 		break;
2775 	}
2776 #endif
2777 
2778 	if (!state)
2779 		return;
2780 	switch (code)
2781 	{
2782 	case AKS_ENTERGUI:
2783 		gui_display (-1);
2784 		setsystime ();
2785 		break;
2786 	case AKS_SCREENSHOT_FILE:
2787 		screenshot (1, 1);
2788 		break;
2789 	case AKS_SCREENSHOT_CLIPBOARD:
2790 		screenshot (0, 1);
2791 		break;
2792 #ifdef ACTION_REPLAY
2793 	case AKS_FREEZEBUTTON:
2794 		action_replay_freeze ();
2795 		break;
2796 #endif
2797 	case AKS_FLOPPY0:
2798 		gui_display (0);
2799 		setsystime ();
2800 		break;
2801 	case AKS_FLOPPY1:
2802 		gui_display (1);
2803 		setsystime ();
2804 		break;
2805 	case AKS_FLOPPY2:
2806 		gui_display (2);
2807 		setsystime ();
2808 		break;
2809 	case AKS_FLOPPY3:
2810 		gui_display (3);
2811 		setsystime ();
2812 		break;
2813 	case AKS_EFLOPPY0:
2814 		disk_eject (0);
2815 		break;
2816 	case AKS_EFLOPPY1:
2817 		disk_eject (1);
2818 		break;
2819 	case AKS_EFLOPPY2:
2820 		disk_eject (2);
2821 		break;
2822 	case AKS_EFLOPPY3:
2823 		disk_eject (3);
2824 		break;
2825 	case AKS_IRQ7:
2826 		NMI_delayed ();
2827 		break;
2828 	case AKS_PAUSE:
2829 		pausemode (-1);
2830 		break;
2831 	case AKS_WARP:
2832 		warpmode (-1);
2833 		break;
2834 	case AKS_INHIBITSCREEN:
2835 		toggle_inhibit_frame (IHF_SCROLLLOCK);
2836 		break;
2837 #ifdef SAVESTATE
2838 	case AKS_STATEREWIND:
2839 		savestate_dorewind (-2);
2840 		break;
2841 	case AKS_STATECURRENT:
2842 		savestate_dorewind (-1);
2843 		break;
2844 	case AKS_STATECAPTURE:
2845 		savestate_capture (1);
2846 		break;
2847 #endif
2848 	case AKS_VOLDOWN:
2849 		sound_volume (-1);
2850 		break;
2851 	case AKS_VOLUP:
2852 		sound_volume (1);
2853 		break;
2854 	case AKS_VOLMUTE:
2855 		sound_mute (-1);
2856 		break;
2857 	case AKS_MVOLDOWN:
2858 		master_sound_volume (-1);
2859 		break;
2860 	case AKS_MVOLUP:
2861 		master_sound_volume (1);
2862 		break;
2863 	case AKS_MVOLMUTE:
2864 		master_sound_volume (0);
2865 		break;
2866 	case AKS_QUIT:
2867 		uae_quit ();
2868 		break;
2869 	case AKS_SOFTRESET:
2870 		uae_reset (0, 0);
2871 		break;
2872 	case AKS_HARDRESET:
2873 		uae_reset (1, 1);
2874 		break;
2875 #ifdef SAVESTATE
2876 	case AKS_STATESAVEQUICK:
2877 	case AKS_STATESAVEQUICK1:
2878 	case AKS_STATESAVEQUICK2:
2879 	case AKS_STATESAVEQUICK3:
2880 	case AKS_STATESAVEQUICK4:
2881 	case AKS_STATESAVEQUICK5:
2882 	case AKS_STATESAVEQUICK6:
2883 	case AKS_STATESAVEQUICK7:
2884 	case AKS_STATESAVEQUICK8:
2885 	case AKS_STATESAVEQUICK9:
2886 		savestate_quick ((code - AKS_STATESAVEQUICK) / 2, 1);
2887 		break;
2888 	case AKS_STATERESTOREQUICK:
2889 	case AKS_STATERESTOREQUICK1:
2890 	case AKS_STATERESTOREQUICK2:
2891 	case AKS_STATERESTOREQUICK3:
2892 	case AKS_STATERESTOREQUICK4:
2893 	case AKS_STATERESTOREQUICK5:
2894 	case AKS_STATERESTOREQUICK6:
2895 	case AKS_STATERESTOREQUICK7:
2896 	case AKS_STATERESTOREQUICK8:
2897 	case AKS_STATERESTOREQUICK9:
2898 		savestate_quick ((code - AKS_STATERESTOREQUICK) / 2, 0);
2899 		break;
2900 #endif
2901 	case AKS_TOGGLEDEFAULTSCREEN:
2902 		toggle_fullscreen (-1);
2903 		break;
2904 	case AKS_TOGGLEWINDOWEDFULLSCREEN:
2905 		toggle_fullscreen (0);
2906 		break;
2907 	case AKS_TOGGLEFULLWINDOWFULLSCREEN:
2908 		toggle_fullscreen (1);
2909 		break;
2910 	case AKS_TOGGLEWINDOWFULLWINDOW:
2911 		toggle_fullscreen (2);
2912 		break;
2913 	case AKS_TOGGLEMOUSEGRAB:
2914 		toggle_mousegrab ();
2915 		break;
2916 #ifdef DEBUGGER
2917 	case AKS_ENTERDEBUGGER:
2918 		activate_debugger ();
2919 		break;
2920 #endif
2921 	case AKS_STATESAVEDIALOG:
2922 		gui_display (5);
2923 		break;
2924 	case AKS_STATERESTOREDIALOG:
2925 		gui_display (4);
2926 		break;
2927 	case AKS_DECREASEREFRESHRATE:
2928 	case AKS_INCREASEREFRESHRATE:
2929 		{
2930 			int dir = code == AKS_INCREASEREFRESHRATE ? 5 : -5;
2931 			if (currprefs.chipset_refreshrate == 0)
2932 				currprefs.chipset_refreshrate = currprefs.ntscmode ? 60 : 50;
2933 			changed_prefs.chipset_refreshrate = currprefs.chipset_refreshrate + dir;
2934 			if (changed_prefs.chipset_refreshrate < 10.0)
2935 				changed_prefs.chipset_refreshrate = 10.0;
2936 			if (changed_prefs.chipset_refreshrate > 900.0)
2937 				changed_prefs.chipset_refreshrate = 900.0;
2938 			config_changed = 1;
2939 		}
2940 		break;
2941 	case AKS_DISKSWAPPER_NEXT:
2942 		swapperslot++;
2943 		if (swapperslot >= MAX_SPARE_DRIVES || currprefs.dfxlist[swapperslot][0] == 0)
2944 			swapperslot = 0;
2945 		break;
2946 	case AKS_DISKSWAPPER_PREV:
2947 		swapperslot--;
2948 		if (swapperslot < 0)
2949 			swapperslot = MAX_SPARE_DRIVES - 1;
2950 		while (swapperslot > 0) {
2951 			if (currprefs.dfxlist[swapperslot][0])
2952 				break;
2953 			swapperslot--;
2954 		}
2955 		break;
2956 	case AKS_DISKSWAPPER_INSERT0:
2957 	case AKS_DISKSWAPPER_INSERT1:
2958 	case AKS_DISKSWAPPER_INSERT2:
2959 	case AKS_DISKSWAPPER_INSERT3:
2960 		_tcscpy (changed_prefs.floppyslots[code - AKS_DISKSWAPPER_INSERT0].df, currprefs.dfxlist[swapperslot]);
2961 		config_changed = 1;
2962 		break;
2963 
2964 		break;
2965 	case AKS_INPUT_CONFIG_1:
2966 	case AKS_INPUT_CONFIG_2:
2967 	case AKS_INPUT_CONFIG_3:
2968 	case AKS_INPUT_CONFIG_4:
2969 		changed_prefs.input_selected_setting = currprefs.input_selected_setting = code - AKS_INPUT_CONFIG_1;
2970 		inputdevice_updateconfig (&changed_prefs, &currprefs);
2971 		break;
2972 	case AKS_DISK_PREV0:
2973 	case AKS_DISK_PREV1:
2974 	case AKS_DISK_PREV2:
2975 	case AKS_DISK_PREV3:
2976 		disk_prevnext (code - AKS_DISK_PREV0, -1);
2977 		break;
2978 	case AKS_DISK_NEXT0:
2979 	case AKS_DISK_NEXT1:
2980 	case AKS_DISK_NEXT2:
2981 	case AKS_DISK_NEXT3:
2982 		disk_prevnext (code - AKS_DISK_NEXT0, 1);
2983 		break;
2984 #ifdef CDTV
2985 	case AKS_CDTV_FRONT_PANEL_STOP:
2986 	case AKS_CDTV_FRONT_PANEL_PLAYPAUSE:
2987 	case AKS_CDTV_FRONT_PANEL_PREV:
2988 	case AKS_CDTV_FRONT_PANEL_NEXT:
2989 	case AKS_CDTV_FRONT_PANEL_REW:
2990 	case AKS_CDTV_FRONT_PANEL_FF:
2991 		cdtv_front_panel (code - AKS_CDTV_FRONT_PANEL_STOP);
2992 	break;
2993 #endif
2994 	}
2995 end:
2996 	if (tracer_enable) {
2997 		set_cpu_tracer (false);
2998 		tracer_enable = 0;
2999 	}
3000 }
3001 
getqualid(int evt)3002 static int getqualid (int evt)
3003 {
3004 	if (evt > INPUTEVENT_SPC_QUALIFIER_START && evt < INPUTEVENT_SPC_QUALIFIER_END)
3005 		return evt - INPUTEVENT_SPC_QUALIFIER1;
3006 	return -1;
3007 }
3008 
isqual(int evt)3009 static uae_u64 isqual (int evt)
3010 {
3011 	int num = getqualid (evt);
3012 	if (num < 0)
3013 		return 0;
3014 	return ID_FLAG_QUALIFIER1 << (num * 2);
3015 }
3016 
handle_input_event(int nr,int state,int max,int autofire,bool canstopplayback,bool playbackevent)3017 int handle_input_event (int nr, int state, int max, int autofire, bool canstopplayback, bool playbackevent)
3018 {
3019 	struct inputevent *ie;
3020 	int joy;
3021 	bool isaks = false;
3022 
3023 	if (nr <= 0 || nr == INPUTEVENT_SPC_CUSTOM_EVENT)
3024 		return 0;
3025 	ie = &events[nr];
3026 	if (isqual (nr))
3027 		return 0; // qualifiers do nothing
3028 	if (ie->unit == 0 && ie->data >= AKS_FIRST) {
3029 		isaks = true;
3030 		if (!state) // release AKS_ does nothing
3031 			return 0;
3032 	}
3033 
3034 	if (!isaks) {
3035 		if (input_record && input_record != INPREC_RECORD_PLAYING)
3036 			inprec_recordevent (nr, state, max, autofire);
3037 		if (input_play && state && canstopplayback) {
3038 			if (inprec_realtimev ()) {
3039 				if (input_record && input_record != INPREC_RECORD_PLAYING)
3040 					inprec_recordevent (nr, state, max, autofire);
3041 			}
3042 		}
3043 		if (!playbackevent && input_play)
3044 			return 0;
3045 	}
3046 
3047 	if ((inputdevice_logging & 1) || input_record || input_play)
3048 		write_log (_T("STATE=%05d MAX=%05d AF=%d QUAL=%06x '%s' \n"), state, max, autofire, (uae_u32)(qualifiers >> 32), ie->name);
3049 	if (autofire) {
3050 		if (state)
3051 			queue_input_event (nr, NULL, state, max, currprefs.input_autofire_linecnt, 1);
3052 		else
3053 			queue_input_event (nr, NULL, -1, 0, 0, 1);
3054 	}
3055 	switch (ie->unit)
3056 	{
3057 	case 5: /* lightpen/gun */
3058 		{
3059 			if (!lightpen_active) {
3060 				lightpen_x = gfxvidinfo.outwidth / 2;
3061 				lightpen_y = gfxvidinfo.outheight / 2;
3062 			}
3063 			lightpen_active = true;
3064 			if (ie->type == 0) {
3065 				int delta = 0;
3066 				if (max == 0)
3067 					delta = state * currprefs.input_mouse_speed / 100;
3068 				else if (state > 0)
3069 					delta = currprefs.input_joymouse_speed;
3070 				else if (state < 0)
3071 					delta = -currprefs.input_joymouse_speed;
3072 				if (ie->data)
3073 					lightpen_y += delta;
3074 				else
3075 					lightpen_x += delta;
3076 			} else {
3077 				int delta = currprefs.input_joymouse_speed;
3078 				if (ie->data & DIR_LEFT)
3079 					lightpen_x -= delta;
3080 				if (ie->data & DIR_RIGHT)
3081 					lightpen_x += delta;
3082 				if (ie->data & DIR_UP)
3083 					lightpen_y -= delta;
3084 				if (ie->data & DIR_DOWN)
3085 					lightpen_y += delta;
3086 			}
3087 		}
3088 		break;
3089 	case 1: /* ->JOY1 */
3090 	case 2: /* ->JOY2 */
3091 	case 3: /* ->Parallel port joystick adapter port #1 */
3092 	case 4: /* ->Parallel port joystick adapter port #2 */
3093 		joy = ie->unit - 1;
3094 		if (ie->type & 4) {
3095 			int old = joybutton[joy] & (1 << ie->data);
3096 
3097 			if (state) {
3098 				joybutton[joy] |= 1 << ie->data;
3099 				gui_gameport_button_change (joy, ie->data, 1);
3100 			} else {
3101 				joybutton[joy] &= ~(1 << ie->data);
3102 				gui_gameport_button_change (joy, ie->data, 0);
3103 			}
3104 
3105 			if (ie->data == 0 && old != (joybutton[joy] & (1 << ie->data)) && currprefs.cpu_cycle_exact) {
3106 				if (!input_record && !input_play && currprefs.input_contact_bounce) {
3107 					// emulate contact bounce, 1st button only, others have capacitors
3108 					bouncy = 1;
3109 					bouncy_cycles = get_cycles () + CYCLE_UNIT * currprefs.input_contact_bounce;
3110 				}
3111 			}
3112 
3113 
3114 		} else if (ie->type & 8) {
3115 
3116 			/* real mouse / analog stick mouse emulation */
3117 			int delta;
3118 			int deadzone = currprefs.input_joymouse_deadzone * max / 100;
3119 			int unit = ie->data & 0x7f;
3120 
3121 			if (max) {
3122 				if (state <= deadzone && state >= -deadzone) {
3123 					state = 0;
3124 					mouse_deltanoreset[joy][unit] = 0;
3125 				} else if (state < 0) {
3126 					state += deadzone;
3127 					mouse_deltanoreset[joy][unit] = 1;
3128 				} else {
3129 					state -= deadzone;
3130 					mouse_deltanoreset[joy][unit] = 1;
3131 				}
3132 				max -= deadzone;
3133 				delta = state * currprefs.input_joymouse_multiplier / max;
3134 			} else {
3135 				delta = state;
3136 				mouse_deltanoreset[joy][unit] = 0;
3137 			}
3138 			if (ie->data & IE_CDTV) {
3139 				delta = 0;
3140 				if (state > 0)
3141 					delta = JOYMOUSE_CDTV;
3142 				else if (state < 0)
3143 					delta = -JOYMOUSE_CDTV;
3144 			}
3145 
3146 			if (ie->data & IE_INVERT)
3147 				delta = -delta;
3148 
3149 			if (max)
3150 				mouse_delta[joy][unit] = delta;
3151 			else
3152 				mouse_delta[joy][unit] += delta;
3153 
3154 			max = 32;
3155 			if (unit) {
3156 				if (delta < 0) {
3157 					gui_gameport_axis_change (joy, DIR_UP_BIT, abs (delta), max);
3158 					gui_gameport_axis_change (joy, DIR_DOWN_BIT, 0, max);
3159 				}
3160 				if (delta > 0) {
3161 					gui_gameport_axis_change (joy, DIR_DOWN_BIT, abs (delta), max);
3162 					gui_gameport_axis_change (joy, DIR_UP_BIT, 0, max);
3163 				}
3164 			} else {
3165 				if (delta < 0) {
3166 					gui_gameport_axis_change (joy, DIR_LEFT_BIT, abs (delta), max);
3167 					gui_gameport_axis_change (joy, DIR_RIGHT_BIT, 0, max);
3168 				}
3169 				if (delta > 0) {
3170 					gui_gameport_axis_change (joy, DIR_RIGHT_BIT, abs (delta), max);
3171 					gui_gameport_axis_change (joy, DIR_LEFT_BIT, 0, max);
3172 				}
3173 			}
3174 
3175 		} else if (ie->type & 32) { /* button mouse emulation vertical */
3176 
3177 			int speed = (ie->data & IE_CDTV) ? JOYMOUSE_CDTV : currprefs.input_joymouse_speed;
3178 
3179 			if (state && (ie->data & DIR_UP)) {
3180 				mouse_delta[joy][1] = -speed;
3181 				mouse_deltanoreset[joy][1] = 1;
3182 			} else if (state && (ie->data & DIR_DOWN)) {
3183 				mouse_delta[joy][1] = speed;
3184 				mouse_deltanoreset[joy][1] = 1;
3185 			} else
3186 				mouse_deltanoreset[joy][1] = 0;
3187 
3188 		} else if (ie->type & 64) { /* button mouse emulation horizontal */
3189 
3190 			int speed = (ie->data & IE_CDTV) ? JOYMOUSE_CDTV : currprefs.input_joymouse_speed;
3191 
3192 			if (state && (ie->data & DIR_LEFT)) {
3193 				mouse_delta[joy][0] = -speed;
3194 				mouse_deltanoreset[joy][0] = 1;
3195 			} else if (state && (ie->data & DIR_RIGHT)) {
3196 				mouse_delta[joy][0] = speed;
3197 				mouse_deltanoreset[joy][0] = 1;
3198 			} else
3199 				mouse_deltanoreset[joy][0] = 0;
3200 
3201 		} else if (ie->type & 128) { /* analog joystick / paddle */
3202 
3203 			int deadzone = currprefs.input_joymouse_deadzone * max / 100;
3204 			int unit = ie->data & 0x7f;
3205 			if (max) {
3206 				if (state <= deadzone && state >= -deadzone) {
3207 					state = 0;
3208 				} else if (state < 0) {
3209 					state += deadzone;
3210 				} else {
3211 					state -= deadzone;
3212 				}
3213 				state = state * max / (max - deadzone);
3214 			}
3215 			if (ie->data & IE_INVERT)
3216 				state = -state;
3217 
3218 			if (!unit) {
3219 				if (state <= 0)
3220 					gui_gameport_axis_change (joy, DIR_UP_BIT, abs (state), max);
3221 				if (state >= 0)
3222 					gui_gameport_axis_change (joy, DIR_DOWN_BIT, abs (state), max);
3223 			} else {
3224 				if (state <= 0)
3225 					gui_gameport_axis_change (joy, DIR_LEFT_BIT, abs (state), max);
3226 				if (state >= 0)
3227 					gui_gameport_axis_change (joy, DIR_RIGHT_BIT, abs (state), max);
3228 			}
3229 
3230 			state = state * currprefs.input_analog_joystick_mult / max;
3231 			state += (128 * currprefs.input_analog_joystick_mult / 100) + currprefs.input_analog_joystick_offset;
3232 			if (state < 0)
3233 				state = 0;
3234 			if (state > 255)
3235 				state = 255;
3236 			joydirpot[joy][unit] = state;
3237 			mouse_deltanoreset[joy][0] = 1;
3238 			mouse_deltanoreset[joy][1] = 1;
3239 
3240 		} else {
3241 
3242 			int left = oleft[joy], right = oright[joy], top = otop[joy], bot = obot[joy];
3243 			if (ie->type & 16) {
3244 				/* button to axis mapping */
3245 				if (ie->data & DIR_LEFT) {
3246 					left = oleft[joy] = state ? 1 : 0;
3247 					if (horizclear[joy] && left) {
3248 						horizclear[joy] = 0;
3249 						right = oright[joy] = 0;
3250 					}
3251 				}
3252 				if (ie->data & DIR_RIGHT) {
3253 					right = oright[joy] = state ? 1 : 0;
3254 					if (horizclear[joy] && right) {
3255 						horizclear[joy] = 0;
3256 						left = oleft[joy] = 0;
3257 					}
3258 				}
3259 				if (ie->data & DIR_UP) {
3260 					top = otop[joy] = state ? 1 : 0;
3261 					if (vertclear[joy] && top) {
3262 						vertclear[joy] = 0;
3263 						bot = obot[joy] = 0;
3264 					}
3265 				}
3266 				if (ie->data & DIR_DOWN) {
3267 					bot = obot[joy] = state ? 1 : 0;
3268 					if (vertclear[joy] && bot) {
3269 						vertclear[joy] = 0;
3270 						top = otop[joy] = 0;
3271 					}
3272 				}
3273 			} else {
3274 				/* "normal" joystick axis */
3275 				int deadzone = currprefs.input_joystick_deadzone * max / 100;
3276 				int neg, pos;
3277 				if (state < deadzone && state > -deadzone)
3278 					state = 0;
3279 				neg = state < 0 ? 1 : 0;
3280 				pos = state > 0 ? 1 : 0;
3281 				if (ie->data & DIR_LEFT) {
3282 					left = oleft[joy] = neg;
3283 					if (horizclear[joy] && left) {
3284 						horizclear[joy] = 0;
3285 						right = oright[joy] = 0;
3286 					}
3287 				}
3288 				if (ie->data & DIR_RIGHT) {
3289 					right = oright[joy] = pos;
3290 					if (horizclear[joy] && right) {
3291 						horizclear[joy] = 0;
3292 						left = oleft[joy] = 0;
3293 					}
3294 				}
3295 				if (ie->data & DIR_UP) {
3296 					top = otop[joy] = neg;
3297 					if (vertclear[joy] && top) {
3298 						vertclear[joy] = 0;
3299 						bot = obot[joy] = 0;
3300 					}
3301 				}
3302 				if (ie->data & DIR_DOWN) {
3303 					bot = obot[joy] = pos;
3304 					if (vertclear[joy] && bot) {
3305 						vertclear[joy] = 0;
3306 						top = otop[joy] = 0;
3307 					}
3308 				}
3309 			}
3310 			mouse_deltanoreset[joy][0] = 1;
3311 			mouse_deltanoreset[joy][1] = 1;
3312 			joydir[joy] = 0;
3313 			if (left)
3314 				joydir[joy] |= DIR_LEFT;
3315 			if (right)
3316 				joydir[joy] |= DIR_RIGHT;
3317 			if (top)
3318 				joydir[joy] |= DIR_UP;
3319 			if (bot)
3320 				joydir[joy] |= DIR_DOWN;
3321 			if (joy == 0 || joy == 1)
3322 				joymousecounter (joy);
3323 
3324 			gui_gameport_axis_change (joy, DIR_LEFT_BIT, left, 0);
3325 			gui_gameport_axis_change (joy, DIR_RIGHT_BIT, right, 0);
3326 			gui_gameport_axis_change (joy, DIR_UP_BIT, top, 0);
3327 			gui_gameport_axis_change (joy, DIR_DOWN_BIT, bot, 0);
3328 		}
3329 		break;
3330 	case 0: /* ->KEY */
3331 		inputdevice_do_keyboard (ie->data, state);
3332 		break;
3333 	}
3334 	return 1;
3335 }
3336 
inputdevice_checkconfig(void)3337 static void inputdevice_checkconfig (void)
3338 {
3339 	if (
3340 		currprefs.jports[0].id != changed_prefs.jports[0].id ||
3341 		currprefs.jports[1].id != changed_prefs.jports[1].id ||
3342 		currprefs.jports[2].id != changed_prefs.jports[2].id ||
3343 		currprefs.jports[3].id != changed_prefs.jports[3].id ||
3344 		currprefs.jports[0].mode != changed_prefs.jports[0].mode ||
3345 		currprefs.jports[1].mode != changed_prefs.jports[1].mode ||
3346 		currprefs.jports[2].mode != changed_prefs.jports[2].mode ||
3347 		currprefs.jports[3].mode != changed_prefs.jports[3].mode ||
3348 		currprefs.input_selected_setting != changed_prefs.input_selected_setting ||
3349 		currprefs.input_joymouse_multiplier != changed_prefs.input_joymouse_multiplier ||
3350 		currprefs.input_joymouse_deadzone != changed_prefs.input_joymouse_deadzone ||
3351 		currprefs.input_joystick_deadzone != changed_prefs.input_joystick_deadzone ||
3352 		currprefs.input_joymouse_speed != changed_prefs.input_joymouse_speed ||
3353 		currprefs.input_autofire_linecnt != changed_prefs.input_autofire_linecnt ||
3354 		currprefs.input_mouse_speed != changed_prefs.input_mouse_speed) {
3355 
3356 			currprefs.input_selected_setting = changed_prefs.input_selected_setting;
3357 			currprefs.input_joymouse_multiplier = changed_prefs.input_joymouse_multiplier;
3358 			currprefs.input_joymouse_deadzone = changed_prefs.input_joymouse_deadzone;
3359 			currprefs.input_joystick_deadzone = changed_prefs.input_joystick_deadzone;
3360 			currprefs.input_joymouse_speed = changed_prefs.input_joymouse_speed;
3361 			currprefs.input_autofire_linecnt = changed_prefs.input_autofire_linecnt;
3362 			currprefs.input_mouse_speed = changed_prefs.input_mouse_speed;
3363 
3364 			inputdevice_updateconfig (&changed_prefs, &currprefs);
3365 	}
3366 	if (currprefs.dongle != changed_prefs.dongle) {
3367 		currprefs.dongle = changed_prefs.dongle;
3368 		dongle_reset ();
3369 	}
3370 }
3371 
inputdevice_vsync(void)3372 void inputdevice_vsync (void)
3373 {
3374 	if (inputdevice_logging & 32)
3375 		write_log (_T("*\n"));
3376 
3377 	input_frame++;
3378 	mouseupdate (0, true);
3379 
3380 	if (!input_record) {
3381 		inputdevice_read ();
3382 		if (!input_play)
3383 			inputdelay = uaerand () % (maxvpos <= 1 ? 1 : maxvpos - 1);
3384 	}
3385 
3386 	inputdevice_handle_inputcode ();
3387 	if (mouseedge_alive > 0)
3388 		mouseedge_alive--;
3389 #ifdef ARCADIA
3390 	if (arcadia_bios)
3391 		arcadia_vsync ();
3392 #endif
3393 	if (mouseedge ())
3394 		mouseedge_alive = 10;
3395 	if (mousehack_alive_cnt > 0) {
3396 		mousehack_alive_cnt--;
3397 		if (mousehack_alive_cnt == 0)
3398 			setmouseactive (-1);
3399 	} else if (mousehack_alive_cnt < 0) {
3400 		mousehack_alive_cnt++;
3401 		if (mousehack_alive_cnt == 0) {
3402 			mousehack_alive_cnt = 100;
3403 			setmouseactive (0);
3404 			setmouseactive (1);
3405 		}
3406 	}
3407 	inputdevice_checkconfig ();
3408 }
3409 
inputdevice_reset(void)3410 void inputdevice_reset (void)
3411 {
3412 	magicmouse_ibase = 0;
3413 	magicmouse_gfxbase = 0;
3414 	mousehack_reset ();
3415 	if (inputdevice_is_tablet ())
3416 		mousehack_enable ();
3417 	bouncy = 0;
3418 }
3419 
getoldport(struct uae_input_device * id)3420 static int getoldport (struct uae_input_device *id)
3421 {
3422 	int i, j;
3423 
3424 	for (i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++) {
3425 		for (j = 0; j < MAX_INPUT_SUB_EVENT; j++) {
3426 			int evt = id->eventid[i][j];
3427 			if (evt > 0) {
3428 				int unit = events[evt].unit;
3429 				if (unit >= 1 && unit <= 4)
3430 					return unit;
3431 			}
3432 		}
3433 	}
3434 	return -1;
3435 }
3436 
switchdevice(struct uae_input_device * id,int num,bool buttonmode)3437 static int switchdevice (struct uae_input_device *id, int num, bool buttonmode)
3438 {
3439 	int i, j;
3440 	int ismouse = 0;
3441 	int newport = 0;
3442 	int flags = 0;
3443 	TCHAR *name = NULL;
3444 	int otherbuttonpressed = 0;
3445 
3446 	if (num >= 4)
3447 		return 0;
3448 #ifdef RETROPLATFORM
3449 	if (rp_isactive ())
3450 		return 0;
3451 #endif
3452 	for (i = 0; i < MAX_INPUT_DEVICES; i++) {
3453 		if (id == &joysticks[i]) {
3454 			name = idev[IDTYPE_JOYSTICK].get_uniquename (i);
3455 			newport = num == 0 ? 1 : 0;
3456 			flags = idev[IDTYPE_JOYSTICK].get_flags (i);
3457 			for (j = 0; j < MAX_INPUT_DEVICES; j++) {
3458 				if (j != i) {
3459 					struct uae_input_device2 *id2 = &joysticks2[j];
3460 					if (id2->buttonmask)
3461 						otherbuttonpressed = 1;
3462 				}
3463 			}
3464 		}
3465 		if (id == &mice[i]) {
3466 			ismouse = 1;
3467 			name = idev[IDTYPE_MOUSE].get_uniquename (i);
3468 			newport = num == 0 ? 0 : 1;
3469 			flags = idev[IDTYPE_MOUSE].get_flags (i);
3470 		}
3471 	}
3472 	if (!name)
3473 		return 0;
3474 	if (buttonmode) {
3475 		if (num == 0 && otherbuttonpressed)
3476 			newport = newport ? 0 : 1;
3477 	} else {
3478 		newport = num ? 1 : 0;
3479 	}
3480 	/* "GamePorts" switch if in GamePorts mode or Input mode and GamePorts port was not NONE */
3481 	if (currprefs.input_selected_setting == GAMEPORT_INPUT_SETTINGS || currprefs.jports[newport].id != JPORT_NONE) {
3482 		if ((num == 0 || num == 1) && currprefs.jports[newport].id != JPORT_CUSTOM) {
3483 /* REMOVEME:
3484  * nowhere used
3485  */
3486 #if 0
3487 			int om = jsem_ismouse (num, &currprefs);
3488 #endif
3489 			int om1 = jsem_ismouse (0, &currprefs);
3490 			int om2 = jsem_ismouse (1, &currprefs);
3491 			if ((om1 >= 0 || om2 >= 0) && ismouse)
3492 				return 0;
3493 			if (flags)
3494 				return 0;
3495 			if (name) {
3496 				write_log (_T("inputdevice change '%s':%d->%d\n"), name, num, newport);
3497 				inputdevice_joyport_config (&changed_prefs, name, newport, -1, 2);
3498 				inputdevice_copyconfig (&changed_prefs, &currprefs);
3499 				return 1;
3500 			}
3501 		}
3502 		return 0;
3503 	} else {
3504 		int oldport = getoldport (id);
3505 		int k, evt;
3506 		struct inputevent *ie, *ie2;
3507 
3508 		if (flags)
3509 			return 0;
3510 		if (oldport <= 0)
3511 			return 0;
3512 		newport++;
3513 		/* do not switch if switching mouse and any "supermouse" mouse enabled */
3514 		if (ismouse) {
3515 			for (i = 0; i < MAX_INPUT_SETTINGS; i++) {
3516 				if (mice[i].enabled && idev[IDTYPE_MOUSE].get_flags (i))
3517 					return 0;
3518 			}
3519 		}
3520 		for (i = 0; i < MAX_INPUT_SETTINGS; i++) {
3521 			if (getoldport (&joysticks[i]) == newport)
3522 				joysticks[i].enabled = 0;
3523 			if (getoldport (&mice[i]) == newport)
3524 				mice[i].enabled = 0;
3525 		}
3526 		id->enabled = 1;
3527 		for (i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++) {
3528 			for (j = 0; j < MAX_INPUT_SUB_EVENT; j++) {
3529 				evt = id->eventid[i][j];
3530 				if (evt <= 0)
3531 					continue;
3532 				ie = &events[evt];
3533 				if (ie->unit == oldport) {
3534 					k = 1;
3535 					while (events[k].confname) {
3536 						ie2 = &events[k];
3537 						if (ie2->type == ie->type && ie2->data == ie->data && ie2->allow_mask == ie->allow_mask && ie2->unit == newport) {
3538 							id->eventid[i][j] = k;
3539 							break;
3540 						}
3541 						k++;
3542 					}
3543 				} else if (ie->unit == newport) {
3544 					k = 1;
3545 					while (events[k].confname) {
3546 						ie2 = &events[k];
3547 						if (ie2->type == ie->type && ie2->data == ie->data && ie2->allow_mask == ie->allow_mask && ie2->unit == oldport) {
3548 							id->eventid[i][j] = k;
3549 							break;
3550 						}
3551 						k++;
3552 					}
3553 				}
3554 			}
3555 		}
3556 		write_log (_T("inputdevice change '%s':%d->%d\n"), name, num, newport);
3557 		inputdevice_copyconfig (&currprefs, &changed_prefs);
3558 		inputdevice_copyconfig (&changed_prefs, &currprefs);
3559 		return 1;
3560 	}
3561 	return 0;
3562 }
3563 
input_getqualifiers(void)3564 uae_u64 input_getqualifiers (void)
3565 {
3566 	return qualifiers;
3567 }
3568 
checkqualifiers(int evt,uae_u64 flags,uae_u64 * qualmask,uae_s16 events[MAX_INPUT_SUB_EVENT_ALL])3569 static bool checkqualifiers (int evt, uae_u64 flags, uae_u64 *qualmask, uae_s16 events[MAX_INPUT_SUB_EVENT_ALL])
3570 {
3571 	int i, j;
3572 	int qualid = getqualid (evt);
3573 	int nomatch = 0;
3574 	bool isspecial = (qualifiers & (ID_FLAG_QUALIFIER_SPECIAL | ID_FLAG_QUALIFIER_SPECIAL_R)) != 0;
3575 
3576 	flags &= ID_FLAG_QUALIFIER_MASK;
3577 	if (qualid >= 0 && events)
3578 		qualifiers_evt[qualid] = events;
3579 	/* special set and new qualifier pressed? do not sent it to Amiga-side */
3580 	if ((qualifiers & (ID_FLAG_QUALIFIER_SPECIAL | ID_FLAG_QUALIFIER_SPECIAL_R)) && qualid >= 0)
3581 		return false;
3582 
3583 	for (i = 0; i < MAX_INPUT_SUB_EVENT; i++) {
3584 		if (qualmask[i])
3585 			break;
3586 	}
3587 	if (i == MAX_INPUT_SUB_EVENT) {
3588 		 // no qualifiers in any slot and no special = always match
3589 		return isspecial == false;
3590 	}
3591 
3592 	for (i = 0; i < MAX_INPUT_SUB_EVENT; i++) {
3593 		for (j = 0; j < MAX_INPUT_QUALIFIERS; j++) {
3594 			uae_u64 mask = (ID_FLAG_QUALIFIER1 | ID_FLAG_QUALIFIER1_R) << (j * 2);
3595 			bool isqualmask = (qualmask[i] & mask) != 0;
3596 			bool isqual = (qualifiers & mask) != 0;
3597 			if (isqualmask != isqual) {
3598 				nomatch++;
3599 				break;
3600 			}
3601 		}
3602 	}
3603 	if (nomatch == MAX_INPUT_SUB_EVENT) {
3604 		// no matched qualifiers in any slot
3605 		// allow all slots without qualifiers
3606 		// special = never accept
3607 		if (isspecial)
3608 			return false;
3609 		return flags ? false : true;
3610 	}
3611 
3612 	for (i = 0; i < MAX_INPUT_QUALIFIERS; i++) {
3613 		uae_u64 mask = (ID_FLAG_QUALIFIER1 | ID_FLAG_QUALIFIER1_R) << (i * 2);
3614 		bool isflags = (flags & mask) != 0;
3615 		bool isqual = (qualifiers & mask) != 0;
3616 		if (isflags != isqual)
3617 	return false;
3618 }
3619 	return true;
3620 }
3621 
setqualifiers(int evt,int state)3622 static void setqualifiers (int evt, int state)
3623 {
3624 	uae_u64 mask = isqual (evt);
3625 	if (!mask)
3626 		return;
3627 	if (state)
3628 		qualifiers |= mask;
3629 	else
3630 		qualifiers &= ~mask;
3631 }
3632 
getqualmask(uae_u64 * qualmask,struct uae_input_device * id,int num,bool * qualonly)3633 static uae_u64 getqualmask (uae_u64 *qualmask, struct uae_input_device *id, int num, bool *qualonly)
3634 {
3635 	uae_u64 mask = 0, mask2 = 0;
3636 	for (int i = 0; i < MAX_INPUT_SUB_EVENT; i++) {
3637 		int evt = id->eventid[num][i];
3638 		mask |= id->flags[num][i];
3639 		qualmask[i] = id->flags[num][i] & ID_FLAG_QUALIFIER_MASK;
3640 		mask2 |= isqual (evt);
3641 	}
3642 	mask &= ID_FLAG_QUALIFIER_MASK;
3643 	*qualonly = false;
3644 	if (qualifiers & ID_FLAG_QUALIFIER_SPECIAL) {
3645 		// ID_FLAG_QUALIFIER_SPECIAL already active and this event has one or more qualifiers configured
3646 		*qualonly = mask2 != 0;
3647 	}
3648 	return mask;
3649 }
3650 
3651 
process_custom_event(struct uae_input_device * id,int offset,int state,uae_u64 * qualmask,int autofire,int sub)3652 static bool process_custom_event (struct uae_input_device *id, int offset, int state, uae_u64 *qualmask, int autofire, int sub)
3653 {
3654 	int idx, slotoffset, custompos;
3655 	TCHAR *custom;
3656 	uae_u64 flags, qual;
3657 
3658 	if (!id)
3659 		return false;
3660 
3661 	slotoffset = sub & ~3;
3662 	sub &= 3;
3663 	flags = id->flags[offset][slotoffset];
3664 	qual = flags & ID_FLAG_QUALIFIER_MASK;
3665 	custom = id->custom[offset][slotoffset];
3666 /* REMOVEME:
3667  * nowhere used
3668  */
3669 #if 0
3670 	int af = flags & ID_FLAG_AUTOFIRE_MASK;
3671 #endif
3672 
3673 	for (idx = 1; idx < 4; idx++) {
3674 		uae_u64 flags2 = id->flags[offset][slotoffset + idx];
3675 /* REMOVEME:
3676  * nowhere used
3677  */
3678 #if 0
3679 		TCHAR *custom2 = id->custom[offset][slotoffset + idx];
3680 #endif
3681 
3682 		// all slots must have same qualifier
3683 		if ((flags2 & ID_FLAG_QUALIFIER_MASK) != qual)
3684 			break;
3685 		// no slot must have autofire
3686 		if ((flags2 & ID_FLAG_AUTOFIRE_MASK) || (flags & ID_FLAG_AUTOFIRE_MASK))
3687 			break;
3688 	}
3689 	// at least slot 0 and 2 must have custom
3690 	if (custom == NULL || id->custom[offset][slotoffset + 2] == NULL)
3691 		idx = -1;
3692 
3693 	if (idx < 4) {
3694 		id->flags[offset][slotoffset] &= ~(ID_FLAG_CUSTOMEVENT_TOGGLED1 | ID_FLAG_CUSTOMEVENT_TOGGLED2);
3695 		int evt2 = id->eventid[offset][slotoffset + sub];
3696 		uae_u64 flags2 = id->flags[offset][slotoffset + sub];
3697 		if (checkqualifiers (evt2, flags2, qualmask, NULL)) {
3698 			custom = id->custom[offset][slotoffset + sub];
3699 			if (state && custom) {
3700 				if (autofire)
3701 					queue_input_event (-1, custom, 1, 1, currprefs.input_autofire_linecnt, 1);
3702 					handle_custom_event (custom);
3703 				return true;
3704 			}
3705 		}
3706 		return false;
3707 	}
3708 
3709 	if (sub != 0)
3710 		return false;
3711 
3712 	slotoffset = 0;
3713 	if (!checkqualifiers (id->eventid[offset][slotoffset], id->flags[offset][slotoffset], qualmask, NULL)) {
3714 		slotoffset = 4;
3715 		if (!checkqualifiers (id->eventid[offset][slotoffset], id->flags[offset][slotoffset], qualmask, NULL))
3716 			return false;
3717 	}
3718 
3719 	flags = id->flags[offset][slotoffset];
3720 	custompos = (flags & ID_FLAG_CUSTOMEVENT_TOGGLED1) ? 1 : 0;
3721 	custompos |= (flags & ID_FLAG_CUSTOMEVENT_TOGGLED2) ? 2 : 0;
3722 
3723 	if (state < 0) {
3724 		idx = 0;
3725 		custompos = 0;
3726 	} else {
3727 		if (state > 0) {
3728 			if (custompos & 1)
3729 				return false; // waiting for release
3730 		} else {
3731 			if (!(custompos & 1))
3732 				return false; // waiting for press
3733 	}
3734 		idx = custompos;
3735 		custompos++;
3736 	}
3737 
3738 	queue_input_event (-1, NULL, -1, 0, 0, 1);
3739 
3740 	if ((id->flags[offset][slotoffset + idx] & ID_FLAG_QUALIFIER_MASK) == qual) {
3741 		custom = id->custom[offset][slotoffset + idx];
3742 	if (autofire)
3743 		queue_input_event (-1, custom, 1, 1, currprefs.input_autofire_linecnt, 1);
3744 		if (custom)
3745 	handle_custom_event (custom);
3746 	}
3747 
3748 	id->flags[offset][slotoffset] &= ~(ID_FLAG_CUSTOMEVENT_TOGGLED1 | ID_FLAG_CUSTOMEVENT_TOGGLED2);
3749 	id->flags[offset][slotoffset] |= (custompos & 1) ? ID_FLAG_CUSTOMEVENT_TOGGLED1 : 0;
3750 	id->flags[offset][slotoffset] |= (custompos & 2) ? ID_FLAG_CUSTOMEVENT_TOGGLED2 : 0;
3751 
3752 	return true;
3753 }
3754 
setbuttonstateall(struct uae_input_device * id,struct uae_input_device2 * id2,int button,int buttonstate)3755 static void setbuttonstateall (struct uae_input_device *id, struct uae_input_device2 *id2, int button, int buttonstate)
3756 {
3757 	static frame_time_t switchdevice_timeout;
3758 	int i;
3759 	uae_u32 mask = 1 << button;
3760 	uae_u32 omask = id2 ? id2->buttonmask & mask : 0;
3761 	uae_u32 nmask = (buttonstate ? 1 : 0) << button;
3762 	uae_u64 qualmask[MAX_INPUT_SUB_EVENT];
3763 	bool qualonly;
3764 
3765 	if (input_play && buttonstate)
3766 		inprec_realtimev ();
3767 	if (input_play)
3768 		return;
3769 	if (!id->enabled) {
3770 		frame_time_t t = read_processor_time ();
3771 		if (buttonstate) {
3772 			switchdevice_timeout = t;
3773 		} else {
3774 			int port = button;
3775 			if (t - switchdevice_timeout >= syncbase) // 1s
3776 				port ^= 1;
3777 			switchdevice (id, port, true);
3778 		}
3779 		return;
3780 	}
3781 	if (button >= ID_BUTTON_TOTAL)
3782 		return;
3783 
3784 	getqualmask (qualmask, id, ID_BUTTON_OFFSET + button, &qualonly);
3785 
3786 	bool didcustom = false;
3787 
3788 	for (i = 0; i < MAX_INPUT_SUB_EVENT; i++) {
3789 		int sub = sublevdir[buttonstate == 0 ? 1 : 0][i];
3790 		uae_u64 *flagsp = &id->flags[ID_BUTTON_OFFSET + button][sub];
3791 		int evt = id->eventid[ID_BUTTON_OFFSET + button][sub];
3792 /* REMOVEME:
3793  * nowhere used
3794  */
3795 #if 0
3796 		TCHAR *custom = id->custom[ID_BUTTON_OFFSET + button][sub];
3797 #endif
3798 		uae_u64 flags = flagsp[0];
3799 		int autofire = (flags & ID_FLAG_AUTOFIRE) ? 1 : 0;
3800 		int toggle = (flags & ID_FLAG_TOGGLE) ? 1 : 0;
3801 		int inverttoggle = (flags & ID_FLAG_INVERTTOGGLE) ? 1 : 0;
3802 		int invert = (flags & ID_FLAG_INVERT) ? 1 : 0;
3803 		int state;
3804 
3805 		if (buttonstate < 0) {
3806 			state = buttonstate;
3807 		} else if (invert) {
3808 			state = buttonstate ? 0 : 1;
3809 		} else {
3810 			state = buttonstate;
3811 		}
3812 
3813 		if (!state) {
3814 			didcustom |= process_custom_event (id, ID_BUTTON_OFFSET + button, state, qualmask, autofire, i);
3815 		}
3816 
3817 		setqualifiers (evt, state > 0);
3818 
3819 		if (qualonly)
3820 			continue;
3821 
3822 		if (state < 0) {
3823 			if (!checkqualifiers (evt, flags, qualmask, NULL))
3824 				continue;
3825 			handle_input_event (evt, 1, 1, 0, true, false);
3826 			didcustom |= process_custom_event (id, ID_BUTTON_OFFSET + button, state, qualmask, 0, i);
3827 		} else if (inverttoggle) {
3828 			/* pressed = firebutton, not pressed = autofire */
3829 			if (state) {
3830 				queue_input_event (evt, NULL, -1, 0, 0, 1);
3831 				handle_input_event (evt, 1, 1, 0, true, false);
3832 			} else {
3833 				handle_input_event (evt, 1, 1, autofire, true, false);
3834 			}
3835 			didcustom |= process_custom_event (id, ID_BUTTON_OFFSET + button, state, qualmask, autofire, i);
3836 		} else if (toggle) {
3837 			if (!state)
3838 				continue;
3839 			if (omask & mask)
3840 				continue;
3841 			if (!checkqualifiers (evt, flags, qualmask, NULL))
3842 				continue;
3843 			*flagsp ^= ID_FLAG_TOGGLED;
3844 			int toggled = (*flagsp & ID_FLAG_TOGGLED) ? 1 : 0;
3845 			handle_input_event (evt, toggled, 1, autofire, true, false);
3846 			didcustom |= process_custom_event (id, ID_BUTTON_OFFSET + button, toggled, qualmask, autofire, i);
3847 		} else {
3848 			if (!checkqualifiers (evt, flags, qualmask, NULL)) {
3849 				if (!state && !(flags & ID_FLAG_CANRELEASE)) {
3850 					if (!invert)
3851 						continue;
3852 				} else if (state) {
3853 					continue;
3854 				}
3855 			}
3856 			if (!state)
3857 				*flagsp &= ~ID_FLAG_CANRELEASE;
3858 			else
3859 				*flagsp |= ID_FLAG_CANRELEASE;
3860 			if ((omask ^ nmask) & mask) {
3861 				handle_input_event (evt, state, 1, autofire, true, false);
3862 				if (state)
3863 					didcustom |= process_custom_event (id, ID_BUTTON_OFFSET + button, state, qualmask, autofire, i);
3864 			}
3865 		}
3866 	}
3867 
3868 	if (!didcustom)
3869 		queue_input_event (-1, NULL, -1, 0, 0, 1);
3870 
3871 	if (id2 && ((omask ^ nmask) & mask)) {
3872 		if (buttonstate)
3873 			id2->buttonmask |= mask;
3874 		else
3875 			id2->buttonmask &= ~mask;
3876 	}
3877 }
3878 
3879 
3880 /* - detect required number of joysticks and mice from configuration data
3881  * - detect if CD32 pad emulation is needed
3882  * - detect device type in ports (mouse or joystick)
3883  */
3884 
iscd32(int ei)3885 static int iscd32 (int ei)
3886 {
3887 	if (ei >= INPUTEVENT_JOY1_CD32_FIRST && ei <= INPUTEVENT_JOY1_CD32_LAST) {
3888 		cd32_pad_enabled[0] = 1;
3889 		return 1;
3890 	}
3891 	if (ei >= INPUTEVENT_JOY2_CD32_FIRST && ei <= INPUTEVENT_JOY2_CD32_LAST) {
3892 		cd32_pad_enabled[1] = 1;
3893 		return 2;
3894 	}
3895 	return 0;
3896 }
3897 
isparport(int ei)3898 static int isparport (int ei)
3899 {
3900 	if (ei > INPUTEVENT_PAR_JOY1_START && ei < INPUTEVENT_PAR_JOY_END) {
3901 		parport_joystick_enabled = 1;
3902 		return 1;
3903 	}
3904 	return 0;
3905 }
3906 
ismouse(int ei)3907 static int ismouse (int ei)
3908 {
3909 	if (ei >= INPUTEVENT_MOUSE1_FIRST && ei <= INPUTEVENT_MOUSE1_LAST) {
3910 		mouse_port[0] = 1;
3911 		return 1;
3912 	}
3913 	if (ei >= INPUTEVENT_MOUSE2_FIRST && ei <= INPUTEVENT_MOUSE2_LAST) {
3914 		mouse_port[1] = 1;
3915 		return 2;
3916 	}
3917 	return 0;
3918 }
3919 
isanalog(int ei)3920 static int isanalog (int ei)
3921 {
3922 	if (ei == INPUTEVENT_JOY1_HORIZ_POT || ei == INPUTEVENT_JOY1_HORIZ_POT_INV) {
3923 		analog_port[0][0] = 1;
3924 		return 1;
3925 	}
3926 	if (ei == INPUTEVENT_JOY1_VERT_POT || ei == INPUTEVENT_JOY1_VERT_POT_INV) {
3927 		analog_port[0][1] = 1;
3928 		return 1;
3929 	}
3930 	if (ei == INPUTEVENT_JOY2_HORIZ_POT || ei == INPUTEVENT_JOY2_HORIZ_POT_INV) {
3931 		analog_port[1][0] = 1;
3932 		return 1;
3933 	}
3934 	if (ei == INPUTEVENT_JOY2_VERT_POT || ei == INPUTEVENT_JOY2_VERT_POT_INV) {
3935 		analog_port[1][1] = 1;
3936 		return 1;
3937 	}
3938 	return 0;
3939 }
3940 
isdigitalbutton(int ei)3941 static int isdigitalbutton (int ei)
3942 {
3943 	if (ei == INPUTEVENT_JOY1_2ND_BUTTON) {
3944 		digital_port[0][1] = 1;
3945 		return 1;
3946 	}
3947 	if (ei == INPUTEVENT_JOY1_3RD_BUTTON) {
3948 		digital_port[0][0] = 1;
3949 		return 1;
3950 	}
3951 	if (ei == INPUTEVENT_JOY2_2ND_BUTTON) {
3952 		digital_port[1][1] = 1;
3953 		return 1;
3954 	}
3955 	if (ei == INPUTEVENT_JOY2_3RD_BUTTON) {
3956 		digital_port[1][0] = 1;
3957 		return 1;
3958 	}
3959 	return 0;
3960 }
3961 
islightpen(int ei)3962 static int islightpen (int ei)
3963 {
3964 	if (ei >= INPUTEVENT_LIGHTPEN_FIRST && ei < INPUTEVENT_LIGHTPEN_LAST) {
3965 		lightpen = 1;
3966 		return 1;
3967 	}
3968 	return 0;
3969 }
3970 
isqualifier(int ei)3971 static void isqualifier (int ei)
3972 {
3973 }
3974 
scanevents(struct uae_prefs * p)3975 static void scanevents (struct uae_prefs *p)
3976 {
3977 	int i, j, k, ei;
3978 /* REMOVEME:
3979  * nowhere used
3980  */
3981 #if 0
3982 	const struct inputevent *e;
3983 #endif
3984 	int n_joy = idev[IDTYPE_JOYSTICK].get_num();
3985 	int n_mouse = idev[IDTYPE_MOUSE].get_num();
3986 
3987 	cd32_pad_enabled[0] = cd32_pad_enabled[1] = 0;
3988 	parport_joystick_enabled = 0;
3989 	mouse_port[0] = mouse_port[1] = 0;
3990 	qualifiers = 0;
3991 
3992 	for (i = 0; i < NORMAL_JPORTS; i++) {
3993 		for (j = 0; j < 2; j++) {
3994 			digital_port[i][j] = 0;
3995 			analog_port[i][j] = 0;
3996 			joydirpot[i][j] = 128 / (312 * 100 / currprefs.input_analog_joystick_mult) + (128 * currprefs.input_analog_joystick_mult / 100) + currprefs.input_analog_joystick_offset;
3997 		}
3998 	}
3999 	lightpen = 0;
4000 	if (lightpen_active > 0)
4001 		lightpen_active = -1;
4002 
4003 	for (i = 0; i < MAX_INPUT_DEVICES; i++) {
4004 		use_joysticks[i] = 0;
4005 		use_mice[i] = 0;
4006 		for (k = 0; k < MAX_INPUT_SUB_EVENT; k++) {
4007 			for (j = 0; j < ID_BUTTON_TOTAL; j++) {
4008 
4009 				if ((joysticks[i].enabled && i < n_joy) || joysticks[i].enabled < 0) {
4010 					ei = joysticks[i].eventid[ID_BUTTON_OFFSET + j][k];
4011 /* REMOVEME:
4012  * nowhere used
4013  */
4014 #if 0
4015 					e = &events[ei];
4016 #endif
4017 					iscd32 (ei);
4018 					isparport (ei);
4019 					ismouse (ei);
4020 					isdigitalbutton (ei);
4021 					isqualifier (ei);
4022 					islightpen (ei);
4023 					if (joysticks[i].eventid[ID_BUTTON_OFFSET + j][k] > 0)
4024 						use_joysticks[i] = 1;
4025 				}
4026 				if ((mice[i].enabled && i < n_mouse) || mice[i].enabled < 0) {
4027 					ei = mice[i].eventid[ID_BUTTON_OFFSET + j][k];
4028 /* REMOVEME:
4029  * nowhere used
4030  */
4031 #if 0
4032 					e = &events[ei];
4033 #endif
4034 					iscd32 (ei);
4035 					isparport (ei);
4036 					ismouse (ei);
4037 					isdigitalbutton (ei);
4038 					isqualifier (ei);
4039 					islightpen (ei);
4040 					if (mice[i].eventid[ID_BUTTON_OFFSET + j][k] > 0)
4041 						use_mice[i] = 1;
4042 				}
4043 
4044 			}
4045 
4046 			for (j = 0; j < ID_AXIS_TOTAL; j++) {
4047 
4048 				if ((joysticks[i].enabled && i < n_joy) || joysticks[i].enabled < 0) {
4049 					ei = joysticks[i].eventid[ID_AXIS_OFFSET + j][k];
4050 					iscd32 (ei);
4051 					isparport (ei);
4052 					ismouse (ei);
4053 					isanalog (ei);
4054 					isdigitalbutton (ei);
4055 					isqualifier (ei);
4056 					islightpen (ei);
4057 					if (ei > 0)
4058 						use_joysticks[i] = 1;
4059 				}
4060 				if ((mice[i].enabled && i < n_mouse) || mice[i].enabled < 0) {
4061 					ei = mice[i].eventid[ID_AXIS_OFFSET + j][k];
4062 					iscd32 (ei);
4063 					isparport (ei);
4064 					ismouse (ei);
4065 					isanalog (ei);
4066 					isdigitalbutton (ei);
4067 					isqualifier (ei);
4068 					islightpen (ei);
4069 					if (ei > 0)
4070 						use_mice[i] = 1;
4071 				}
4072 			}
4073 		}
4074 	}
4075 	memset (scancodeused, 0, sizeof scancodeused);
4076 	for (i = 0; i < MAX_INPUT_DEVICES; i++) {
4077 		use_keyboards[i] = 0;
4078 		if (keyboards[i].enabled && i < idev[IDTYPE_KEYBOARD].get_num()) {
4079 			j = 0;
4080 			while (j < MAX_INPUT_DEVICE_EVENTS && keyboards[i].extra[j] >= 0) {
4081 				use_keyboards[i] = 1;
4082 				for (k = 0; k < MAX_INPUT_SUB_EVENT; k++) {
4083 					ei = keyboards[i].eventid[j][k];
4084 					iscd32 (ei);
4085 					isparport (ei);
4086 					ismouse (ei);
4087 					isdigitalbutton (ei);
4088 					isqualifier (ei);
4089 					islightpen (ei);
4090 					if (ei > 0)
4091 						scancodeused[i][keyboards[i].extra[j]] = ei;
4092 				}
4093 				j++;
4094 			}
4095 		}
4096 	}
4097 }
4098 
4099 static const int axistable[] = {
4100 	INPUTEVENT_MOUSE1_HORIZ, INPUTEVENT_MOUSE1_LEFT, INPUTEVENT_MOUSE1_RIGHT,
4101 	INPUTEVENT_MOUSE1_VERT, INPUTEVENT_MOUSE1_UP, INPUTEVENT_MOUSE1_DOWN,
4102 	INPUTEVENT_MOUSE2_HORIZ, INPUTEVENT_MOUSE2_LEFT, INPUTEVENT_MOUSE2_RIGHT,
4103 	INPUTEVENT_MOUSE2_VERT, INPUTEVENT_MOUSE2_UP, INPUTEVENT_MOUSE2_DOWN,
4104 	INPUTEVENT_JOY1_HORIZ, INPUTEVENT_JOY1_LEFT, INPUTEVENT_JOY1_RIGHT,
4105 	INPUTEVENT_JOY1_VERT, INPUTEVENT_JOY1_UP, INPUTEVENT_JOY1_DOWN,
4106 	INPUTEVENT_JOY2_HORIZ, INPUTEVENT_JOY2_LEFT, INPUTEVENT_JOY2_RIGHT,
4107 	INPUTEVENT_JOY2_VERT, INPUTEVENT_JOY2_UP, INPUTEVENT_JOY2_DOWN,
4108 	INPUTEVENT_LIGHTPEN_HORIZ, INPUTEVENT_LIGHTPEN_LEFT, INPUTEVENT_LIGHTPEN_RIGHT,
4109 	INPUTEVENT_LIGHTPEN_VERT, INPUTEVENT_LIGHTPEN_UP, INPUTEVENT_LIGHTPEN_DOWN,
4110 	INPUTEVENT_PAR_JOY1_HORIZ, INPUTEVENT_PAR_JOY1_LEFT, INPUTEVENT_PAR_JOY1_RIGHT,
4111 	INPUTEVENT_PAR_JOY1_VERT, INPUTEVENT_PAR_JOY1_UP, INPUTEVENT_PAR_JOY1_DOWN,
4112 	INPUTEVENT_PAR_JOY2_HORIZ, INPUTEVENT_PAR_JOY2_LEFT, INPUTEVENT_PAR_JOY2_RIGHT,
4113 	INPUTEVENT_PAR_JOY2_VERT, INPUTEVENT_PAR_JOY2_UP, INPUTEVENT_PAR_JOY2_DOWN,
4114 	INPUTEVENT_MOUSE_CDTV_HORIZ, INPUTEVENT_MOUSE_CDTV_LEFT, INPUTEVENT_MOUSE_CDTV_RIGHT,
4115 	INPUTEVENT_MOUSE_CDTV_VERT, INPUTEVENT_MOUSE_CDTV_UP, INPUTEVENT_MOUSE_CDTV_DOWN,
4116 	-1
4117 };
4118 
intputdevice_compa_get_eventtype(int evt,const int ** axistablep)4119 int intputdevice_compa_get_eventtype (int evt, const int **axistablep)
4120 {
4121 	for (int i = 0; axistable[i] >= 0; i += 3) {
4122 		*axistablep = &axistable[i];
4123 		if (axistable[i] == evt)
4124 			return IDEV_WIDGET_AXIS;
4125 		if (axistable[i + 1] == evt)
4126 			return IDEV_WIDGET_BUTTONAXIS;
4127 		if (axistable[i + 2] == evt)
4128 			return IDEV_WIDGET_BUTTONAXIS;
4129 	}
4130 	*axistablep = NULL;
4131 	return IDEV_WIDGET_BUTTON;
4132 }
4133 
4134 static int rem_port1[] = {
4135 	INPUTEVENT_MOUSE1_HORIZ, INPUTEVENT_MOUSE1_VERT,
4136 	INPUTEVENT_JOY1_HORIZ, INPUTEVENT_JOY1_VERT,
4137 	INPUTEVENT_JOY1_HORIZ_POT, INPUTEVENT_JOY1_VERT_POT,
4138 	INPUTEVENT_JOY1_FIRE_BUTTON, INPUTEVENT_JOY1_2ND_BUTTON, INPUTEVENT_JOY1_3RD_BUTTON,
4139 	INPUTEVENT_JOY1_CD32_RED, INPUTEVENT_JOY1_CD32_BLUE, INPUTEVENT_JOY1_CD32_GREEN, INPUTEVENT_JOY1_CD32_YELLOW,
4140 	INPUTEVENT_JOY1_CD32_RWD, INPUTEVENT_JOY1_CD32_FFW, INPUTEVENT_JOY1_CD32_PLAY,
4141 	INPUTEVENT_MOUSE_CDTV_HORIZ, INPUTEVENT_MOUSE_CDTV_VERT,
4142 	INPUTEVENT_LIGHTPEN_HORIZ, INPUTEVENT_LIGHTPEN_VERT,
4143 	-1
4144 };
4145 static int rem_port2[] = {
4146 	INPUTEVENT_MOUSE2_HORIZ, INPUTEVENT_MOUSE2_VERT,
4147 	INPUTEVENT_JOY2_HORIZ, INPUTEVENT_JOY2_VERT,
4148 	INPUTEVENT_JOY2_HORIZ_POT, INPUTEVENT_JOY2_VERT_POT,
4149 	INPUTEVENT_JOY2_FIRE_BUTTON, INPUTEVENT_JOY2_2ND_BUTTON, INPUTEVENT_JOY2_3RD_BUTTON,
4150 	INPUTEVENT_JOY2_CD32_RED, INPUTEVENT_JOY2_CD32_BLUE, INPUTEVENT_JOY2_CD32_GREEN, INPUTEVENT_JOY2_CD32_YELLOW,
4151 	INPUTEVENT_JOY2_CD32_RWD, INPUTEVENT_JOY2_CD32_FFW, INPUTEVENT_JOY2_CD32_PLAY,
4152 	-1, -1,
4153 	-1, -1,
4154 	-1
4155 };
4156 static int rem_port3[] = {
4157 	INPUTEVENT_PAR_JOY1_LEFT, INPUTEVENT_PAR_JOY1_RIGHT, INPUTEVENT_PAR_JOY1_UP, INPUTEVENT_PAR_JOY1_DOWN,
4158 	INPUTEVENT_PAR_JOY1_FIRE_BUTTON, INPUTEVENT_PAR_JOY1_2ND_BUTTON,
4159 	-1
4160 };
4161 static int rem_port4[] = {
4162 	INPUTEVENT_PAR_JOY2_LEFT, INPUTEVENT_PAR_JOY2_RIGHT, INPUTEVENT_PAR_JOY2_UP, INPUTEVENT_PAR_JOY2_DOWN,
4163 	INPUTEVENT_PAR_JOY2_FIRE_BUTTON, INPUTEVENT_PAR_JOY2_2ND_BUTTON,
4164 	-1
4165 };
4166 
4167 static int *rem_ports[] = { rem_port1, rem_port2, rem_port3, rem_port4 };
4168 static int af_port1[] = {
4169 	INPUTEVENT_JOY1_FIRE_BUTTON, INPUTEVENT_JOY1_CD32_RED,
4170 	-1
4171 };
4172 static int af_port2[] = {
4173 	INPUTEVENT_JOY2_FIRE_BUTTON, INPUTEVENT_JOY2_CD32_RED,
4174 	-1
4175 };
4176 static int af_port3[] = {
4177 	INPUTEVENT_PAR_JOY1_FIRE_BUTTON, INPUTEVENT_PAR_JOY1_2ND_BUTTON,
4178 	-1
4179 };
4180 static int af_port4[] = {
4181 	INPUTEVENT_PAR_JOY2_FIRE_BUTTON, INPUTEVENT_PAR_JOY2_2ND_BUTTON,
4182 	-1
4183 };
4184 static int *af_ports[] = { af_port1, af_port2, af_port3, af_port4 };
4185 static int ip_joy1[] = {
4186 	INPUTEVENT_JOY1_LEFT, INPUTEVENT_JOY1_RIGHT, INPUTEVENT_JOY1_UP, INPUTEVENT_JOY1_DOWN,
4187 	INPUTEVENT_JOY1_FIRE_BUTTON, INPUTEVENT_JOY1_2ND_BUTTON,
4188 	-1
4189 };
4190 static int ip_joy2[] = {
4191 	INPUTEVENT_JOY2_LEFT, INPUTEVENT_JOY2_RIGHT, INPUTEVENT_JOY2_UP, INPUTEVENT_JOY2_DOWN,
4192 	INPUTEVENT_JOY2_FIRE_BUTTON, INPUTEVENT_JOY2_2ND_BUTTON,
4193 	-1
4194 };
4195 static int ip_joypad1[] = {
4196 	INPUTEVENT_JOY1_LEFT, INPUTEVENT_JOY1_RIGHT, INPUTEVENT_JOY1_UP, INPUTEVENT_JOY1_DOWN,
4197 	INPUTEVENT_JOY1_FIRE_BUTTON, INPUTEVENT_JOY1_2ND_BUTTON, INPUTEVENT_JOY1_3RD_BUTTON,
4198 	-1
4199 };
4200 static int ip_joypad2[] = {
4201 	INPUTEVENT_JOY2_LEFT, INPUTEVENT_JOY2_RIGHT, INPUTEVENT_JOY2_UP, INPUTEVENT_JOY2_DOWN,
4202 	INPUTEVENT_JOY2_FIRE_BUTTON, INPUTEVENT_JOY2_2ND_BUTTON, INPUTEVENT_JOY2_3RD_BUTTON,
4203 	-1
4204 };
4205 static int ip_joycd321[] = {
4206 	INPUTEVENT_JOY1_LEFT, INPUTEVENT_JOY1_RIGHT, INPUTEVENT_JOY1_UP, INPUTEVENT_JOY1_DOWN,
4207 	INPUTEVENT_JOY1_CD32_RED, INPUTEVENT_JOY1_CD32_BLUE, INPUTEVENT_JOY1_CD32_GREEN, INPUTEVENT_JOY1_CD32_YELLOW,
4208 	INPUTEVENT_JOY1_CD32_RWD, INPUTEVENT_JOY1_CD32_FFW, INPUTEVENT_JOY1_CD32_PLAY,
4209 	-1
4210 };
4211 static int ip_joycd322[] = {
4212 	INPUTEVENT_JOY2_LEFT, INPUTEVENT_JOY2_RIGHT, INPUTEVENT_JOY2_UP, INPUTEVENT_JOY2_DOWN,
4213 	INPUTEVENT_JOY2_CD32_RED, INPUTEVENT_JOY2_CD32_BLUE, INPUTEVENT_JOY2_CD32_GREEN, INPUTEVENT_JOY2_CD32_YELLOW,
4214 	INPUTEVENT_JOY2_CD32_RWD, INPUTEVENT_JOY2_CD32_FFW, INPUTEVENT_JOY2_CD32_PLAY,
4215 	-1
4216 };
4217 static int ip_parjoy1[] = {
4218 	INPUTEVENT_PAR_JOY1_LEFT, INPUTEVENT_PAR_JOY1_RIGHT, INPUTEVENT_PAR_JOY1_UP, INPUTEVENT_PAR_JOY1_DOWN,
4219 	INPUTEVENT_PAR_JOY1_FIRE_BUTTON, INPUTEVENT_PAR_JOY1_2ND_BUTTON,
4220 	-1
4221 };
4222 static int ip_parjoy2[] = {
4223 	INPUTEVENT_PAR_JOY2_LEFT, INPUTEVENT_PAR_JOY2_RIGHT, INPUTEVENT_PAR_JOY2_UP, INPUTEVENT_PAR_JOY2_DOWN,
4224 	INPUTEVENT_PAR_JOY2_FIRE_BUTTON, INPUTEVENT_PAR_JOY2_2ND_BUTTON,
4225 	-1
4226 };
4227 static int ip_parjoy1default[] = {
4228 	INPUTEVENT_PAR_JOY1_LEFT, INPUTEVENT_PAR_JOY1_RIGHT, INPUTEVENT_PAR_JOY1_UP, INPUTEVENT_PAR_JOY1_DOWN,
4229 	INPUTEVENT_PAR_JOY1_FIRE_BUTTON,
4230 	-1
4231 };
4232 static int ip_parjoy2default[] = {
4233 	INPUTEVENT_PAR_JOY2_LEFT, INPUTEVENT_PAR_JOY2_RIGHT, INPUTEVENT_PAR_JOY2_UP, INPUTEVENT_PAR_JOY2_DOWN,
4234 	INPUTEVENT_PAR_JOY2_FIRE_BUTTON,
4235 	-1
4236 };
4237 static int ip_mouse1[] = {
4238 	INPUTEVENT_MOUSE1_LEFT, INPUTEVENT_MOUSE1_RIGHT, INPUTEVENT_MOUSE1_UP, INPUTEVENT_MOUSE1_DOWN,
4239 	INPUTEVENT_JOY1_FIRE_BUTTON, INPUTEVENT_JOY1_2ND_BUTTON,
4240 	-1
4241 };
4242 static int ip_mouse2[] = {
4243 	INPUTEVENT_MOUSE2_LEFT, INPUTEVENT_MOUSE2_RIGHT, INPUTEVENT_MOUSE2_UP, INPUTEVENT_MOUSE2_DOWN,
4244 	INPUTEVENT_JOY2_FIRE_BUTTON, INPUTEVENT_JOY2_2ND_BUTTON,
4245 	-1
4246 };
4247 static int ip_mousecdtv[] =
4248 {
4249 	INPUTEVENT_MOUSE_CDTV_LEFT, INPUTEVENT_MOUSE_CDTV_RIGHT, INPUTEVENT_MOUSE_CDTV_UP, INPUTEVENT_MOUSE_CDTV_DOWN,
4250 	INPUTEVENT_JOY1_FIRE_BUTTON, INPUTEVENT_JOY1_2ND_BUTTON,
4251 	-1
4252 };
4253 
4254 #ifdef CDTV
4255 static int ip_mediacdtv[] =
4256 {
4257 	INPUTEVENT_KEY_CDTV_PLAYPAUSE, INPUTEVENT_KEY_CDTV_STOP, INPUTEVENT_KEY_CDTV_PREV, INPUTEVENT_KEY_CDTV_NEXT,
4258 	-1
4259 };
4260 #endif
4261 
4262 #ifdef ARCADIA
4263 static int ip_arcadia[] = {
4264 	INPUTEVENT_SPC_ARCADIA_DIAGNOSTICS, INPUTEVENT_SPC_ARCADIA_PLAYER1, INPUTEVENT_SPC_ARCADIA_PLAYER2,
4265 	INPUTEVENT_SPC_ARCADIA_COIN1, INPUTEVENT_SPC_ARCADIA_COIN2,
4266 	-1
4267 };
4268 #endif
4269 
4270 static int ip_lightpen1[] = {
4271 	INPUTEVENT_LIGHTPEN_HORIZ, INPUTEVENT_LIGHTPEN_VERT, INPUTEVENT_JOY1_3RD_BUTTON,
4272 	-1
4273 };
4274 static int ip_lightpen2[] = {
4275 	INPUTEVENT_LIGHTPEN_HORIZ, INPUTEVENT_LIGHTPEN_VERT, INPUTEVENT_JOY2_3RD_BUTTON,
4276 	-1
4277 };
4278 static int ip_analog1[] = {
4279 	INPUTEVENT_JOY1_HORIZ_POT, INPUTEVENT_JOY1_VERT_POT, INPUTEVENT_JOY1_LEFT, INPUTEVENT_JOY1_RIGHT,
4280 	-1
4281 };
4282 static int ip_analog2[] = {
4283 	INPUTEVENT_JOY2_HORIZ_POT, INPUTEVENT_JOY2_VERT_POT, INPUTEVENT_JOY2_LEFT, INPUTEVENT_JOY2_RIGHT,
4284 	-1
4285 };
4286 
4287 #ifdef ARCADIA
4288 static int ip_arcadiaxa[] = {
4289 	-1
4290 };
4291 #endif
4292 
checkcompakb(int * kb,int * srcmap)4293 static void checkcompakb (int *kb, int *srcmap)
4294 {
4295 	int found = 0, avail = 0;
4296 	int j, k;
4297 
4298 	k = j = 0;
4299 	while (kb[j] >= 0) {
4300 		struct uae_input_device *uid = &keyboards[0];
4301 		while (kb[j] >= 0 && srcmap[k] >= 0) {
4302 			int id = kb[j];
4303 			for (int l = 0; l < MAX_INPUT_DEVICE_EVENTS; l++) {
4304 				if (uid->extra[l] == id) {
4305 					avail++;
4306 					if (uid->eventid[l][0] == srcmap[k])
4307 						found++;
4308 					break;
4309 				}
4310 			}
4311 			j++;
4312 		}
4313 		if (srcmap[k] < 0)
4314 			break;
4315 		j++;
4316 		k++;
4317 	}
4318 	if (avail != found || avail == 0)
4319 		return;
4320 	k = j = 0;
4321 	while (kb[j] >= 0) {
4322 		struct uae_input_device *uid = &keyboards[0];
4323 		while (kb[j] >= 0) {
4324 			int id = kb[j];
4325 /* REMOVEME:
4326  * nowhere used
4327  */
4328 #if 0
4329 			int evt0 = 0, evt1 = 0;
4330 #endif
4331 			k = 0;
4332 			while (keyboard_default[k].scancode >= 0) {
4333 				if (keyboard_default[k].scancode == kb[j]) {
4334 					for (int l = 0; l < MAX_INPUT_DEVICE_EVENTS; l++) {
4335 						if (uid->extra[l] == id && uid->port[l][0] == 0) {
4336 							for (int m = 0; m < MAX_INPUT_SUB_EVENT && keyboard_default[k].node[m].evt; m++) {
4337 								uid->eventid[l][m] = keyboard_default[k].node[m].evt;
4338 								uid->port[l][m] = 0;
4339 								uid->flags[l][m] = 0;
4340 							}
4341 					break;
4342 				}
4343 			}
4344 					break;
4345 				}
4346 				k++;
4347 			}
4348 			j++;
4349 		}
4350 		j++;
4351 	}
4352 }
4353 
setautofireevent(struct uae_input_device * uid,int num,int sub,int af,int index)4354 static void setautofireevent (struct uae_input_device *uid, int num, int sub, int af, int index)
4355 {
4356 	if (!af)
4357 		return;
4358 #ifdef RETROPLATFORM
4359 	// don't override custom AF autofire mappings
4360 	if (rp_isactive ())
4361 		return;
4362 #endif
4363 	int *afp = af_ports[index];
4364 	for (int k = 0; afp[k] >= 0; k++) {
4365 		if (afp[k] == uid->eventid[num][sub]) {
4366 			uid->flags[num][sub] &= ~ID_FLAG_AUTOFIRE_MASK;
4367 			if (af >= JPORT_AF_NORMAL)
4368 				uid->flags[num][sub] |= ID_FLAG_AUTOFIRE;
4369 			if (af == JPORT_AF_TOGGLE)
4370 				uid->flags[num][sub] |= ID_FLAG_TOGGLE;
4371 			if (af == JPORT_AF_ALWAYS)
4372 				uid->flags[num][sub] |= ID_FLAG_INVERTTOGGLE;
4373 			return;
4374 		}
4375 	}
4376 }
4377 
inputdevice_sparerestore(struct uae_input_device * uid,int num,int sub)4378 static void inputdevice_sparerestore (struct uae_input_device *uid, int num, int sub)
4379 {
4380 	if (uid->port[num][SPARE_SUB_EVENT]) {
4381 	uid->eventid[num][sub] = uid->eventid[num][SPARE_SUB_EVENT];
4382 	uid->flags[num][sub] = uid->flags[num][SPARE_SUB_EVENT];
4383 	uid->custom[num][sub] = uid->custom[num][SPARE_SUB_EVENT];
4384 	} else {
4385 		uid->eventid[num][sub] = 0;
4386 		uid->flags[num][sub] = 0;
4387 		xfree (uid->custom[num][sub]);
4388 		uid->custom[num][sub] = 0;
4389 	}
4390 	uid->eventid[num][SPARE_SUB_EVENT] = 0;
4391 	uid->flags[num][SPARE_SUB_EVENT] = 0;
4392 	uid->port[num][SPARE_SUB_EVENT] = 0;
4393 	uid->custom[num][SPARE_SUB_EVENT] = 0;
4394 }
4395 
inputdevice_sparecopy(struct uae_input_device * uid,int num,int sub)4396 void inputdevice_sparecopy (struct uae_input_device *uid, int num, int sub)
4397 {
4398 	if (uid->port[num][SPARE_SUB_EVENT] != 0)
4399 		return;
4400 	if (uid->eventid[num][sub] <= 0 && uid->custom[num][sub] == NULL) {
4401 		uid->eventid[num][SPARE_SUB_EVENT] = 0;
4402 		uid->flags[num][SPARE_SUB_EVENT] = 0;
4403 		uid->port[num][SPARE_SUB_EVENT] = 0;
4404 		xfree (uid->custom[num][SPARE_SUB_EVENT]);
4405 		uid->custom[num][SPARE_SUB_EVENT] = NULL;
4406 	} else {
4407 	uid->eventid[num][SPARE_SUB_EVENT] = uid->eventid[num][sub];
4408 	uid->flags[num][SPARE_SUB_EVENT] = uid->flags[num][sub];
4409 	uid->port[num][SPARE_SUB_EVENT] = MAX_JPORTS + 1;
4410 	xfree (uid->custom[num][SPARE_SUB_EVENT]);
4411 	uid->custom[num][SPARE_SUB_EVENT] = uid->custom[num][sub];
4412 	uid->custom[num][sub] = NULL;
4413 }
4414 }
4415 
setcompakb(int * kb,int * srcmap,int index,int af)4416 static void setcompakb (int *kb, int *srcmap, int index, int af)
4417 {
4418 	int j, k;
4419 	k = j = 0;
4420 	while (kb[j] >= 0 && srcmap[k] >= 0) {
4421 		while (kb[j] >= 0) {
4422 			int id = kb[j];
4423 			for (int m = 0; m < MAX_INPUT_DEVICES; m++) {
4424 				struct uae_input_device *uid = &keyboards[m];
4425 				for (int l = 0; l < MAX_INPUT_DEVICE_EVENTS; l++) {
4426 					if (uid->extra[l] == id) {
4427 						inputdevice_sparecopy (uid, l, 0);
4428 						uid->eventid[l][0] = srcmap[k];
4429 						uid->flags[l][0] &= COMPA_RESERVED_FLAGS;
4430 						uid->port[l][0] = index + 1;
4431 						xfree (uid->custom[l][0]);
4432 						uid->custom[l][0] = NULL;
4433 						setautofireevent (uid, l, 0, af, index);
4434 						break;
4435 					}
4436 				}
4437 			}
4438 			j++;
4439 		}
4440 		j++;
4441 		k++;
4442 	}
4443 }
4444 
inputdevice_get_compatibility_input(struct uae_prefs * prefs,int index,int * typelist,int * inputlist,const int ** at)4445 int inputdevice_get_compatibility_input (struct uae_prefs *prefs, int index, int *typelist, int *inputlist, const int **at)
4446 {
4447 	if (index >= MAX_JPORTS || joymodes[index] < 0)
4448 		return -1;
4449 	if (typelist != NULL)
4450 		*typelist = joymodes[index];
4451 	if (at != NULL)
4452 		*at = axistable;
4453 	if (inputlist == NULL)
4454 		return -1;
4455 
4456 	//write_log (_T("%d %p %p\n"), *typelist, *inputlist, *at);
4457 	int cnt;
4458 	for (cnt = 0; joyinputs[index] && joyinputs[index][cnt] >= 0; cnt++) {
4459 		inputlist[cnt] = joyinputs[index][cnt];
4460 	}
4461 	inputlist[cnt] = -1;
4462 
4463 	// find custom events (custom event = event that is mapped to same port but not included in joyinputs[]
4464 	int devnum = 0;
4465 	while (inputdevice_get_device_status (devnum) >= 0) {
4466 		for (int j = 0; j < inputdevice_get_widget_num (devnum); j++) {
4467 			for (int sub = 0; sub < MAX_INPUT_SUB_EVENT; sub++) {
4468 				int port, k, l;
4469 				uae_u64 flags;
4470 				bool ignore = false;
4471 				int evtnum2 = inputdevice_get_mapping (devnum, j, &flags, &port, NULL, NULL, sub);
4472 				if (port - 1 != index)
4473 					continue;
4474 				for (k = 0; axistable[k] >= 0; k += 3) {
4475 					if (evtnum2 == axistable[k] || evtnum2 == axistable[k + 1] || evtnum2 == axistable[k + 2]) {
4476 						for (l = 0; inputlist[l] >= 0; l++) {
4477 							if (inputlist[l] == axistable[k] || inputlist[l] == axistable[k + 1] || inputlist[l] == axistable[k + 1]) {
4478 								ignore = true;
4479 							}
4480 						}
4481 					}
4482 				}
4483 				if (!ignore) {
4484 					for (k = 0; inputlist[k] >= 0; k++) {
4485 						if (evtnum2 == inputlist[k])
4486 							break;
4487 					}
4488 					if (inputlist[k] < 0) {
4489 						inputlist[k] = evtnum2;
4490 						inputlist[k + 1] = -1;
4491 						cnt++;
4492 					}
4493 				}
4494 			}
4495 		}
4496 		devnum++;
4497 	}
4498 
4499 	//write_log (_T("%d\n"), cnt);
4500 	return cnt;
4501 }
4502 
clearevent(struct uae_input_device * uid,int evt)4503 static void clearevent (struct uae_input_device *uid, int evt)
4504 {
4505 	for (int i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++) {
4506 		for (int j = 0; j < MAX_INPUT_SUB_EVENT; j++) {
4507 			if (uid->eventid[i][j] == evt) {
4508 				uid->eventid[i][j] = 0;
4509 				uid->flags[i][j] &= COMPA_RESERVED_FLAGS;
4510 				xfree (uid->custom[i][j]);
4511 				uid->custom[i][j] = NULL;
4512 			}
4513 		}
4514 	}
4515 }
clearkbrevent(struct uae_input_device * uid,int evt)4516 static void clearkbrevent (struct uae_input_device *uid, int evt)
4517 {
4518 	for (int i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++) {
4519 		for (int j = 0; j < MAX_INPUT_SUB_EVENT; j++) {
4520 			if (uid->eventid[i][j] == evt) {
4521 				uid->eventid[i][j] = 0;
4522 				uid->flags[i][j] &= COMPA_RESERVED_FLAGS;
4523 				xfree (uid->custom[i][j]);
4524 				uid->custom[i][j] = NULL;
4525 				if (j == 0)
4526 					set_kbr_default_event (uid, keyboard_default, i);
4527 			}
4528 		}
4529 	}
4530 }
4531 
resetjport(struct uae_prefs * prefs,int index)4532 static void resetjport (struct uae_prefs *prefs, int index)
4533 {
4534 	int *p = rem_ports[index];
4535 	while (*p >= 0) {
4536 		int evtnum = *p++;
4537 		for (int l = 0; l < MAX_INPUT_DEVICES; l++) {
4538 			clearevent (&prefs->joystick_settings[GAMEPORT_INPUT_SETTINGS][l], evtnum);
4539 			clearevent (&prefs->mouse_settings[GAMEPORT_INPUT_SETTINGS][l], evtnum);
4540 			clearkbrevent (&prefs->keyboard_settings[GAMEPORT_INPUT_SETTINGS][l], evtnum);
4541 		}
4542 		for (int i = 0; axistable[i] >= 0; i += 3) {
4543 			if (evtnum == axistable[i] || evtnum == axistable[i + 1] || evtnum == axistable[i + 2]) {
4544 				for (int j = 0; j < 3; j++) {
4545 					int evtnum2 = axistable[i + j];
4546 					for (int l = 0; l < MAX_INPUT_DEVICES; l++) {
4547 						clearevent (&prefs->joystick_settings[GAMEPORT_INPUT_SETTINGS][l], evtnum2);
4548 						clearevent (&prefs->mouse_settings[GAMEPORT_INPUT_SETTINGS][l], evtnum2);
4549 						clearkbrevent (&prefs->keyboard_settings[GAMEPORT_INPUT_SETTINGS][l], evtnum2);
4550 					}
4551 				}
4552 				break;
4553 			}
4554 		}
4555 	}
4556 }
4557 
remove_compa_config(struct uae_prefs * prefs,int index)4558 static void remove_compa_config (struct uae_prefs *prefs, int index)
4559 {
4560 	int typelist;
4561 	const int *atp;
4562 	int inputlist[MAX_COMPA_INPUTLIST];
4563 
4564 	if (inputdevice_get_compatibility_input (prefs, index, &typelist, inputlist, &atp) <= 0)
4565 		return;
4566 	for (int i = 0; inputlist[i] >= 0; i++) {
4567 		int evtnum = inputlist[i];
4568 
4569 		int atpidx = 0;
4570 		while (*atp >= 0) {
4571 			if (*atp == evtnum) {
4572 				atp++;
4573 				atpidx = 2;
4574 				break;
4575 			}
4576 			if (atp[1] == evtnum || atp[2] == evtnum) {
4577 				atpidx = 1;
4578 				break;
4579 			}
4580 			atp += 3;
4581 		}
4582 		while (atpidx >= 0) {
4583 			for (int l = 0; l < MAX_INPUT_DEVICES; l++) {
4584 				clearevent (&prefs->joystick_settings[GAMEPORT_INPUT_SETTINGS][l], evtnum);
4585 				clearevent (&prefs->mouse_settings[GAMEPORT_INPUT_SETTINGS][l], evtnum);
4586 				clearkbrevent (&prefs->keyboard_settings[GAMEPORT_INPUT_SETTINGS][l], evtnum);
4587 			}
4588 			evtnum = *atp++;
4589 			atpidx--;
4590 		}
4591 	}
4592 }
4593 
cleardevgp(struct uae_input_device * uid,int num,bool nocustom,int index)4594 static void cleardevgp (struct uae_input_device *uid, int num, bool nocustom, int index)
4595 {
4596 	for (int i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++) {
4597 		for (int j = 0; j < MAX_INPUT_SUB_EVENT; j++) {
4598 			if (uid[num].port[i][j] == index + 1) {
4599 				if (nocustom && (uid[num].flags[i][j] & ID_FLAG_GAMEPORTSCUSTOM_MASK))
4600 					continue;
4601 				uid[num].eventid[i][j] = 0;
4602 				uid[num].flags[i][j] &= COMPA_RESERVED_FLAGS;
4603 				xfree (uid[num].custom[i][j]);
4604 				uid[num].custom[i][j] = NULL;
4605 				uid[num].port[i][j] = 0;
4606 				if (uid[num].port[i][SPARE_SUB_EVENT])
4607 					inputdevice_sparerestore (&uid[num], i, j);
4608 			}
4609 		}
4610 	}
4611 }
cleardevkbrgp(struct uae_input_device * uid,int num,bool nocustom,int index)4612 static void cleardevkbrgp (struct uae_input_device *uid, int num, bool nocustom, int index)
4613 {
4614 	for (int i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++) {
4615 		for (int j = 0; j < MAX_INPUT_SUB_EVENT; j++) {
4616 			if (uid[num].port[i][j] == index + 1) {
4617 				if (nocustom && (uid[num].flags[i][j] & ID_FLAG_GAMEPORTSCUSTOM_MASK))
4618 					continue;
4619 				uid[num].eventid[i][j] = 0;
4620 				uid[num].flags[i][j] &= COMPA_RESERVED_FLAGS;
4621 				xfree (uid[num].custom[i][j]);
4622 				uid[num].custom[i][j] = NULL;
4623 				uid[num].port[i][j] = 0;
4624 				if (uid[num].port[i][SPARE_SUB_EVENT]) {
4625 					inputdevice_sparerestore (&uid[num], i, j);
4626 				} else if (j == 0) {
4627 					set_kbr_default_event (&uid[num], keyboard_default, i);
4628 				}
4629 			}
4630 		}
4631 	}
4632 }
4633 
4634 // remove all gameports mappings mapped to port 'index'
remove_custom_config(struct uae_prefs * prefs,bool nocustom,int index)4635 static void remove_custom_config (struct uae_prefs *prefs, bool nocustom, int index)
4636 {
4637 	for (int l = 0; l < MAX_INPUT_DEVICES; l++) {
4638 		cleardevgp (joysticks, l, nocustom, index);
4639 		cleardevgp (mice, l, nocustom, index);
4640 		cleardevkbrgp (keyboards, l, nocustom, index);
4641 	}
4642 }
4643 
4644 // prepare port for custom mapping, remove all current Amiga side device mappings
inputdevice_compa_prepare_custom(struct uae_prefs * prefs,int index,int newmode,bool removeold)4645 void inputdevice_compa_prepare_custom (struct uae_prefs *prefs, int index, int newmode, bool removeold)
4646 {
4647 	int mode = prefs->jports[index].mode;
4648 	freejport (prefs, index);
4649 	resetjport (prefs, index);
4650 	if (newmode >= 0) {
4651 		mode = newmode;
4652 	} else if (mode == 0) {
4653 		mode = index == 0 ? JSEM_MODE_WHEELMOUSE : (prefs->cs_cd32cd ? JSEM_MODE_JOYSTICK_CD32 : JSEM_MODE_JOYSTICK);
4654 	}
4655 	prefs->jports[index].mode = mode;
4656 	prefs->jports[index].id = JPORT_CUSTOM;
4657 
4658 	if (removeold) {
4659 		remove_compa_config (prefs, index);
4660 		remove_custom_config (prefs, false, index);
4661 	}
4662 }
4663 // clear device before switching to new one
inputdevice_compa_clear(struct uae_prefs * prefs,int index)4664 void inputdevice_compa_clear (struct uae_prefs *prefs, int index)
4665 {
4666 	freejport (prefs, index);
4667 	resetjport (prefs, index);
4668 	remove_compa_config (prefs, index);
4669 }
4670 
cleardev(struct uae_input_device * uid,int num)4671 static void cleardev (struct uae_input_device *uid, int num)
4672 {
4673 	for (int i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++) {
4674 		inputdevice_sparecopy (&uid[num], i, 0);
4675 		for (int j = 0; j < MAX_INPUT_SUB_EVENT; j++) {
4676 			uid[num].eventid[i][j] = 0;
4677 			uid[num].flags[i][j] = 0;
4678 			xfree (uid[num].custom[i][j]);
4679 			uid[num].custom[i][j] = NULL;
4680 		}
4681 	}
4682 }
4683 
enablejoydevice(struct uae_input_device * uid,bool gameportsmode,int evtnum)4684 static void enablejoydevice (struct uae_input_device *uid, bool gameportsmode, int evtnum)
4685 {
4686 	for (int i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++) {
4687 		for (int j = 0; j < MAX_INPUT_SUB_EVENT; j++) {
4688 			if ((gameportsmode && uid->eventid[i][j] == evtnum) || uid->port[i][j] > 0) {
4689 				uid->enabled = 1;
4690 			}
4691 		}
4692 	}
4693 }
4694 
setjoydevices(struct uae_prefs * prefs,bool gameportsmode,int port)4695 static void setjoydevices (struct uae_prefs *prefs, bool gameportsmode, int port)
4696 {
4697 	for (int i = 0; joyinputs[port] && joyinputs[port][i] >= 0; i++) {
4698 		int evtnum = joyinputs[port][i];
4699 		for (int l = 0; l < MAX_INPUT_DEVICES; l++) {
4700 			enablejoydevice (&joysticks[l], gameportsmode, evtnum);
4701 			enablejoydevice (&mice[l], gameportsmode, evtnum);
4702 			enablejoydevice (&keyboards[l], gameportsmode, evtnum);
4703 		}
4704 		for (int k = 0; axistable[k] >= 0; k += 3) {
4705 			if (evtnum == axistable[k] || evtnum == axistable[k + 1] || evtnum == axistable[k + 2]) {
4706 				for (int j = 0; j < 3; j++) {
4707 					int evtnum2 = axistable[k + j];
4708 					for (int l = 0; l < MAX_INPUT_DEVICES; l++) {
4709 						enablejoydevice (&joysticks[l], gameportsmode, evtnum2);
4710 						enablejoydevice (&mice[l], gameportsmode, evtnum2);
4711 						enablejoydevice (&keyboards[l], gameportsmode, evtnum2);
4712 					}
4713 				}
4714 				break;
4715 			}
4716 		}
4717 
4718 	}
4719 }
4720 
setjoyinputs(struct uae_prefs * prefs,int port)4721 static void setjoyinputs (struct uae_prefs *prefs, int port)
4722 {
4723 	joyinputs[port] = NULL;
4724 	switch (joymodes[port])
4725 	{
4726 		case JSEM_MODE_JOYSTICK:
4727 			if (port >= 2)
4728 				joyinputs[port] = port == 3 ? ip_parjoy2 : ip_parjoy1;
4729 			else
4730 				joyinputs[port] = port == 1 ? ip_joy2 : ip_joy1;
4731 		break;
4732 		case JSEM_MODE_GAMEPAD:
4733 			joyinputs[port] = port ? ip_joypad2 : ip_joypad1;
4734 		break;
4735 		case JSEM_MODE_JOYSTICK_CD32:
4736 			joyinputs[port] = port ? ip_joycd322 : ip_joycd321;
4737 		break;
4738 		case JSEM_MODE_JOYSTICK_ANALOG:
4739 			joyinputs[port] = port ? ip_analog2 : ip_analog1;
4740 		break;
4741 		case JSEM_MODE_WHEELMOUSE:
4742 		case JSEM_MODE_MOUSE:
4743 			joyinputs[port] = port ? ip_mouse2 : ip_mouse1;
4744 		break;
4745 		case JSEM_MODE_LIGHTPEN:
4746 			joyinputs[port] = port ? ip_lightpen2 : ip_lightpen1;
4747 		break;
4748 		case JSEM_MODE_MOUSE_CDTV:
4749 			joyinputs[port] = ip_mousecdtv;
4750 		break;
4751 	}
4752 }
4753 
setautofire(struct uae_input_device * uid,int port,int af)4754 static void setautofire (struct uae_input_device *uid, int port, int af)
4755 {
4756 	int *afp = af_ports[port];
4757 	for (int k = 0; afp[k] >= 0; k++) {
4758 		for (int i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++) {
4759 			for (int j = 0; j < MAX_INPUT_SUB_EVENT; j++) {
4760 				if (uid->eventid[i][j] == afp[k]) {
4761 					uid->flags[i][j] &= ~ID_FLAG_AUTOFIRE_MASK;
4762 					if (af >= JPORT_AF_NORMAL)
4763 						uid->flags[i][j] |= ID_FLAG_AUTOFIRE;
4764 					if (af == JPORT_AF_TOGGLE)
4765 						uid->flags[i][j] |= ID_FLAG_TOGGLE;
4766 					if (af == JPORT_AF_ALWAYS)
4767 						uid->flags[i][j] |= ID_FLAG_INVERTTOGGLE;
4768 				}
4769 			}
4770 		}
4771 	}
4772 }
4773 
setautofires(struct uae_prefs * prefs,int port,int af)4774 static void setautofires (struct uae_prefs *prefs, int port, int af)
4775 {
4776 #ifdef RETROPLATFORM
4777 	// don't override custom AF autofire mappings
4778 	if (rp_isactive ())
4779 		return;
4780 #endif
4781 	for (int l = 0; l < MAX_INPUT_DEVICES; l++) {
4782 		setautofire (&joysticks[l], port, af);
4783 		setautofire (&mice[l], port, af);
4784 		setautofire (&keyboards[l], port, af);
4785 	}
4786 }
4787 
4788 // merge gameport settings with current input configuration
compatibility_copy(struct uae_prefs * prefs,bool gameports)4789 static void compatibility_copy (struct uae_prefs *prefs, bool gameports)
4790 {
4791 	int used[MAX_INPUT_DEVICES] = { 0 };
4792 	int i, joy;
4793 
4794 	for (i = 0; i < MAX_JPORTS; i++) {
4795 		joymodes[i] = prefs->jports[i].mode;
4796 		joyinputs[i]= NULL;
4797 		// remove all mappings from this port, except if custom
4798 		if (prefs->jports[i].id != JPORT_CUSTOM) {
4799 			if (gameports)
4800 				remove_compa_config (prefs, i);
4801 		}
4802 		remove_custom_config (prefs, prefs->jports[i].id == JPORT_CUSTOM, i);
4803 		setjoyinputs (prefs, i);
4804 	}
4805 
4806 	for (i = 0; i < 2; i++) {
4807 /* REMOVEME:
4808  * nowhere used
4809  */
4810 #if 0
4811 		int af = prefs->jports[i].autofire;
4812 #endif
4813 		if (prefs->jports[i].id >= 0 && joymodes[i] <= 0) {
4814 			int mode = prefs->jports[i].mode;
4815 			if (jsem_ismouse (i, prefs) >= 0) {
4816 				switch (mode)
4817 				{
4818 					case JSEM_MODE_DEFAULT:
4819 					case JSEM_MODE_MOUSE:
4820 					case JSEM_MODE_WHEELMOUSE:
4821 					default:
4822 					joymodes[i] = JSEM_MODE_WHEELMOUSE;
4823 					joyinputs[i] = i ? ip_mouse2 : ip_mouse1;
4824 					break;
4825 					case JSEM_MODE_LIGHTPEN:
4826 					joymodes[i] = JSEM_MODE_LIGHTPEN;
4827 					joyinputs[i] = i ? ip_lightpen2 : ip_lightpen1;
4828 					break;
4829 					case JSEM_MODE_MOUSE_CDTV:
4830 					joymodes[i] = JSEM_MODE_MOUSE_CDTV;
4831 					joyinputs[i] = ip_mousecdtv;
4832 					break;
4833 				}
4834 			} else if (jsem_isjoy (i, prefs) >= 0) {
4835 				switch (mode)
4836 				{
4837 					case JSEM_MODE_DEFAULT:
4838 					case JSEM_MODE_JOYSTICK:
4839 					case JSEM_MODE_GAMEPAD:
4840 					case JSEM_MODE_JOYSTICK_CD32:
4841 					default:
4842 					{
4843 						bool iscd32 = mode == JSEM_MODE_JOYSTICK_CD32 || (mode == JSEM_MODE_DEFAULT && prefs->cs_cd32cd);
4844 						if (iscd32) {
4845 							joymodes[i] = JSEM_MODE_JOYSTICK_CD32;
4846 							joyinputs[i] = i ? ip_joycd322 : ip_joycd321;
4847 						} else if (mode == JSEM_MODE_GAMEPAD) {
4848 							joymodes[i] = JSEM_MODE_GAMEPAD;
4849 							joyinputs[i] = i ? ip_joypad2 : ip_joypad1;
4850 						} else {
4851 							joymodes[i] = JSEM_MODE_JOYSTICK;
4852 							joyinputs[i] = i ? ip_joy2 : ip_joy1;
4853 						}
4854 						break;
4855 					}
4856 					case JSEM_MODE_JOYSTICK_ANALOG:
4857 						joymodes[i] = JSEM_MODE_JOYSTICK_ANALOG;
4858 						joyinputs[i] = i ? ip_analog2 : ip_analog1;
4859 						break;
4860 					case JSEM_MODE_MOUSE:
4861 					case JSEM_MODE_WHEELMOUSE:
4862 						joymodes[i] = JSEM_MODE_WHEELMOUSE;
4863 						joyinputs[i] = i ? ip_mouse2 : ip_mouse1;
4864 						break;
4865 					case JSEM_MODE_LIGHTPEN:
4866 						joymodes[i] = JSEM_MODE_LIGHTPEN;
4867 						joyinputs[i] = i ? ip_lightpen2 : ip_lightpen1;
4868 						break;
4869 					case JSEM_MODE_MOUSE_CDTV:
4870 						joymodes[i] = JSEM_MODE_MOUSE_CDTV;
4871 						joyinputs[i] = ip_mousecdtv;
4872 						break;
4873 				}
4874 			} else if (prefs->jports[i].id >= 0) {
4875 				joymodes[i] = i ? JSEM_MODE_JOYSTICK : JSEM_MODE_WHEELMOUSE;
4876 				joyinputs[i] = i ? ip_joy2 : ip_mouse1;
4877 			}
4878 		}
4879 	}
4880 
4881 	for (i = 2; i < MAX_JPORTS; i++) {
4882 		if (prefs->jports[i].id >= 0 && joymodes[i] <= 0) {
4883 /* REMOVEME:
4884  * nowhere used
4885  */
4886 #if 0
4887 			int mode = prefs->jports[i].mode;
4888 #endif
4889 			if (jsem_isjoy (i, prefs) >= 0) {
4890 				joymodes[i] = JSEM_MODE_JOYSTICK;
4891 				joyinputs[i] = i == 3 ? ip_parjoy2 : ip_parjoy1;
4892 			} else if (prefs->jports[i].id >= 0) {
4893 				prefs->jports[i].mode = joymodes[i] = JSEM_MODE_JOYSTICK;
4894 				joyinputs[i] = i == 3 ? ip_parjoy2 : ip_parjoy1;
4895 			}
4896 		}
4897 	}
4898 
4899 	for (i = 0; i < 2; i++) {
4900 		int af = prefs->jports[i].autofire;
4901 		if (prefs->jports[i].id >= 0) {
4902 			int mode = prefs->jports[i].mode;
4903 			if ((joy = jsem_ismouse (i, prefs)) >= 0) {
4904 				if (gameports)
4905 					cleardev (mice, joy);
4906 				switch (mode)
4907 				{
4908 				case JSEM_MODE_DEFAULT:
4909 				case JSEM_MODE_MOUSE:
4910 				case JSEM_MODE_WHEELMOUSE:
4911 				default:
4912 					input_get_default_mouse (mice, joy, i, af, !gameports, mode != JSEM_MODE_MOUSE);
4913 					joymodes[i] = JSEM_MODE_WHEELMOUSE;
4914 					break;
4915 				case JSEM_MODE_LIGHTPEN:
4916 					input_get_default_lightpen (mice, joy, i, af, !gameports);
4917 					joymodes[i] = JSEM_MODE_LIGHTPEN;
4918 					break;
4919 				}
4920 				_tcsncpy (prefs->jports[i].name, idev[IDTYPE_MOUSE].get_friendlyname (joy), MAX_JPORTNAME - 1);
4921 				_tcsncpy (prefs->jports[i].configname, idev[IDTYPE_MOUSE].get_uniquename (joy), MAX_JPORTNAME - 1);
4922 			}
4923 		}
4924 	}
4925 
4926 	for (i = 1; i >= 0; i--) {
4927 		int af = prefs->jports[i].autofire;
4928 		if (prefs->jports[i].id >= 0) {
4929 			int mode = prefs->jports[i].mode;
4930 			joy = jsem_isjoy (i, prefs);
4931 			if (joy >= 0) {
4932 				if (gameports)
4933 					cleardev (joysticks, joy);
4934 				switch (mode)
4935 				{
4936 				case JSEM_MODE_DEFAULT:
4937 				case JSEM_MODE_JOYSTICK:
4938 				case JSEM_MODE_GAMEPAD:
4939 				case JSEM_MODE_JOYSTICK_CD32:
4940 				default:
4941 				{
4942 					bool iscd32 = mode == JSEM_MODE_JOYSTICK_CD32 || (mode == JSEM_MODE_DEFAULT && prefs->cs_cd32cd);
4943 					input_get_default_joystick (joysticks, joy, i, af, mode, !gameports);
4944 					if (iscd32)
4945 						joymodes[i] = JSEM_MODE_JOYSTICK_CD32;
4946 					else if (mode == JSEM_MODE_GAMEPAD)
4947 						joymodes[i] = JSEM_MODE_GAMEPAD;
4948 					else
4949 						joymodes[i] = JSEM_MODE_JOYSTICK;
4950 					break;
4951 				}
4952 				case JSEM_MODE_JOYSTICK_ANALOG:
4953 					input_get_default_joystick_analog (joysticks, joy, i, af, !gameports);
4954 					joymodes[i] = JSEM_MODE_JOYSTICK_ANALOG;
4955 					break;
4956 				case JSEM_MODE_MOUSE:
4957 				case JSEM_MODE_WHEELMOUSE:
4958 					input_get_default_mouse (joysticks, joy, i, af, !gameports, mode == JSEM_MODE_WHEELMOUSE);
4959 					joymodes[i] = JSEM_MODE_WHEELMOUSE;
4960 					break;
4961 				case JSEM_MODE_LIGHTPEN:
4962 					input_get_default_lightpen (joysticks, joy, i, af, !gameports);
4963 					joymodes[i] = JSEM_MODE_LIGHTPEN;
4964 					break;
4965 				case JSEM_MODE_MOUSE_CDTV:
4966 					joymodes[i] = JSEM_MODE_MOUSE_CDTV;
4967 					input_get_default_joystick (joysticks, joy, i, af, mode, !gameports);
4968 					break;
4969 
4970 				}
4971 				_tcsncpy (prefs->jports[i].name, idev[IDTYPE_JOYSTICK].get_friendlyname (joy), MAX_JPORTNAME - 1);
4972 				_tcsncpy (prefs->jports[i].configname, idev[IDTYPE_JOYSTICK].get_uniquename (joy), MAX_JPORTNAME - 1);
4973 				used[joy] = 1;
4974 			}
4975 		}
4976 	}
4977 
4978 	if (gameports) {
4979 		// replace possible old mappings with default keyboard mapping
4980 		for (i = KBR_DEFAULT_MAP_FIRST; i <= KBR_DEFAULT_MAP_LAST; i++) {
4981 			checkcompakb (keyboard_default_kbmaps[i], ip_joy2);
4982 			checkcompakb (keyboard_default_kbmaps[i], ip_joy1);
4983 			checkcompakb (keyboard_default_kbmaps[i], ip_joypad2);
4984 			checkcompakb (keyboard_default_kbmaps[i], ip_joypad1);
4985 			checkcompakb (keyboard_default_kbmaps[i], ip_parjoy2);
4986 			checkcompakb (keyboard_default_kbmaps[i], ip_parjoy1);
4987 			checkcompakb (keyboard_default_kbmaps[i], ip_mouse2);
4988 			checkcompakb (keyboard_default_kbmaps[i], ip_mouse1);
4989 		}
4990 		for (i = KBR_DEFAULT_MAP_CD32_FIRST; i <= KBR_DEFAULT_MAP_CD32_LAST; i++) {
4991 			checkcompakb (keyboard_default_kbmaps[i], ip_joycd321);
4992 			checkcompakb (keyboard_default_kbmaps[i], ip_joycd322);
4993 		}
4994 	}
4995 
4996 	for (i = 0; i < 2; i++) {
4997 		if (prefs->jports[i].id >= 0) {
4998 			int *kb = NULL;
4999 			int mode = prefs->jports[i].mode;
5000 			int af = prefs->jports[i].autofire;
5001 			for (joy = 0; used[joy]; joy++);
5002 			if (JSEM_ISANYKBD (i, prefs)) {
5003 				bool cd32 = mode == JSEM_MODE_JOYSTICK_CD32 || (mode == JSEM_MODE_DEFAULT && prefs->cs_cd32cd);
5004 				if (JSEM_ISNUMPAD (i, prefs)) {
5005 					if (cd32)
5006 						kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_CD32_NP];
5007 					else if (mode == JSEM_MODE_GAMEPAD)
5008 						kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_NP3];
5009 					else
5010 						kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_NP];
5011 				} else if (JSEM_ISCURSOR (i, prefs)) {
5012 					if (cd32)
5013 						kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_CD32_CK];
5014 					else if (mode == JSEM_MODE_GAMEPAD)
5015 						kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_CK3];
5016 					else
5017 						kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_CK];
5018 				} else if (JSEM_ISSOMEWHEREELSE (i, prefs)) {
5019 					if (cd32)
5020 						kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_CD32_SE];
5021 					else if (mode == JSEM_MODE_GAMEPAD)
5022 						kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_SE3];
5023 					else
5024 						kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_SE];
5025 				} else if (JSEM_ISXARCADE1 (i, prefs)) {
5026 					kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_XA1];
5027 				} else if (JSEM_ISXARCADE2 (i, prefs)) {
5028 					kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_XA2];
5029 				}
5030 				if (kb) {
5031 					switch (mode)
5032 					{
5033 					case JSEM_MODE_JOYSTICK:
5034 					case JSEM_MODE_GAMEPAD:
5035 					case JSEM_MODE_JOYSTICK_CD32:
5036 					case JSEM_MODE_DEFAULT:
5037 						if (cd32) {
5038 							setcompakb (kb, i ? ip_joycd322 : ip_joycd321, i, af);
5039 							joymodes[i] = JSEM_MODE_JOYSTICK_CD32;
5040 						} else if (mode == JSEM_MODE_GAMEPAD) {
5041 							setcompakb (kb, i ? ip_joypad2 : ip_joypad1, i, af);
5042 							joymodes[i] = JSEM_MODE_GAMEPAD;
5043 						} else {
5044 							setcompakb (kb, i ? ip_joy2 : ip_joy1, i, af);
5045 							joymodes[i] = JSEM_MODE_JOYSTICK;
5046 						}
5047 						break;
5048 					case JSEM_MODE_MOUSE:
5049 					case JSEM_MODE_WHEELMOUSE:
5050 						setcompakb (kb, i ? ip_mouse2 : ip_mouse1, i, af);
5051 						joymodes[i] = JSEM_MODE_WHEELMOUSE;
5052 						break;
5053 					}
5054 					used[joy] = 1;
5055 				}
5056 			}
5057 		}
5058 	}
5059 #ifdef ARCADIA
5060 	if (arcadia_bios) {
5061 		setcompakb (keyboard_default_kbmaps[KBR_DEFAULT_MAP_ARCADIA], ip_arcadia, 0, 0);
5062 		if (JSEM_ISXARCADE1 (i, prefs) || JSEM_ISXARCADE2 (i, prefs))
5063 			setcompakb (keyboard_default_kbmaps[KBR_DEFAULT_MAP_ARCADIA_XA], ip_arcadiaxa, JSEM_ISXARCADE2 (i, prefs) ? 1 : 0, prefs->jports[i].autofire);
5064 	}
5065 #endif
5066 #ifdef CDTV
5067 	if (0 && currprefs.cs_cdtvcd) {
5068 		setcompakb (keyboard_default_kbmaps[KBR_DEFAULT_MAP_CDTV], ip_mediacdtv, 0, 0);
5069 	}
5070 #endif
5071 	// parport
5072 	for (i = 2; i < MAX_JPORTS; i++) {
5073 		int af = prefs->jports[i].autofire;
5074 		if (prefs->jports[i].id >= 0) {
5075 /* REMOVEME:
5076  * nowhere used
5077  */
5078 #if 0
5079 			int *kb = NULL;
5080 #endif
5081 			joy = jsem_isjoy (i, prefs);
5082 			if (joy >= 0) {
5083 				if (gameports)
5084 					cleardev (joysticks, joy);
5085 				input_get_default_joystick (joysticks, joy, i, af, 0, !gameports);
5086 				_tcsncpy (prefs->jports[i].name, idev[IDTYPE_JOYSTICK].get_friendlyname (joy), MAX_JPORTNAME - 1);
5087 				_tcsncpy (prefs->jports[i].configname, idev[IDTYPE_JOYSTICK].get_uniquename (joy), MAX_JPORTNAME - 1);
5088 				used[joy] = 1;
5089 				joymodes[i] = JSEM_MODE_JOYSTICK;
5090 			}
5091 		}
5092 	}
5093 	for (i = 2; i < MAX_JPORTS; i++) {
5094 		if (prefs->jports[i].id >= 0) {
5095 			int *kb = NULL;
5096 			for (joy = 0; used[joy]; joy++);
5097 			if (JSEM_ISANYKBD (i, prefs)) {
5098 				if (JSEM_ISNUMPAD (i, prefs))
5099 					kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_NP];
5100 				else if (JSEM_ISCURSOR (i, prefs))
5101 					kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_CK];
5102 				else if (JSEM_ISSOMEWHEREELSE (i, prefs))
5103 					kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_SE];
5104 				else if (JSEM_ISXARCADE1 (i, prefs))
5105 					kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_XA1];
5106 				else if (JSEM_ISXARCADE2 (i, prefs))
5107 					kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_XA2];
5108 				if (kb) {
5109 					setcompakb (kb, i == 3 ? ip_parjoy2default : ip_parjoy1default, i, prefs->jports[i].autofire);
5110 					used[joy] = 1;
5111 					joymodes[i] = JSEM_MODE_JOYSTICK;
5112 				}
5113 			}
5114 		}
5115 	}
5116 
5117 	for (i = 0; i < MAX_JPORTS; i++) {
5118 		if (gameports)
5119 			setautofires (prefs, i, prefs->jports[i].autofire);
5120 	}
5121 
5122 	for (i = 0; i < MAX_JPORTS; i++) {
5123 		setjoyinputs (prefs, i);
5124 		setjoydevices (prefs, gameports, i);
5125 	}
5126 }
5127 
disableifempty2(struct uae_input_device * uid)5128 static void disableifempty2 (struct uae_input_device *uid)
5129 {
5130 	for (int i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++) {
5131 		for (int j = 0; j < MAX_INPUT_SUB_EVENT; j++) {
5132 			if (uid->eventid[i][j] > 0 || uid->custom[i][j] != NULL)
5133 				return;
5134 		}
5135 	}
5136 	uid->enabled = false;
5137 }
disableifempty(struct uae_prefs * prefs)5138 static void disableifempty (struct uae_prefs *prefs)
5139 {
5140 	for (int l = 0; l < MAX_INPUT_DEVICES; l++) {
5141 		disableifempty2 (&joysticks[l]);
5142 		disableifempty2 (&mice[l]);
5143 		disableifempty2 (&keyboards[l]);
5144 	}
5145 	prefs->internalevent_settings[0]->enabled = true;
5146 }
5147 
matchdevices(struct inputdevice_functions * inf,struct uae_input_device * uid)5148 static void matchdevices (struct inputdevice_functions *inf, struct uae_input_device *uid)
5149 {
5150 	int i, j;
5151 
5152 	for (i = 0; i < inf->get_num (); i++) {
5153 		TCHAR *aname1 = inf->get_friendlyname (i);
5154 		TCHAR *aname2 = inf->get_uniquename (i);
5155 		int match = -1;
5156 		for (j = 0; j < MAX_INPUT_DEVICES; j++) {
5157 			if (aname2 && uid[j].configname) {
5158 				bool matched = false;
5159 				TCHAR bname[MAX_DPATH];
5160 				TCHAR bname2[MAX_DPATH];
5161 				TCHAR *p1 ,*p2;
5162 				_tcscpy (bname, uid[j].configname);
5163 				_tcscpy (bname2, aname2);
5164 				// strip possible local guid part
5165 				p1 = _tcschr (bname, '{');
5166 				p2 = _tcschr (bname2, '{');
5167 				if (!p1 && !p2) {
5168 					// check possible directinput names too
5169 				p1 = _tcschr (bname, ' ');
5170 				p2 = _tcschr (bname2, ' ');
5171 				}
5172 				if (!_tcscmp (bname, bname2)) {
5173 					matched = true;
5174 				} else if (p1 && p2 && p1 - bname == p2 - bname2) {
5175 					*p1 = 0;
5176 					*p2 = 0;
5177 					if (bname && !_tcscmp (bname2, bname))
5178 						matched = true;
5179 				}
5180 				if (matched) {
5181 						if (match >= 0)
5182 							match = -2;
5183 						else
5184 							match = j;
5185 					}
5186 				if (match == -2)
5187 					break;
5188 			}
5189 		}
5190 		// multiple matches -> use complete local-only id string for comparisons
5191 		if (match == -2) {
5192 			for (j = 0; j < MAX_INPUT_DEVICES; j++) {
5193 				TCHAR *bname2 = uid[j].configname;
5194 				if (aname2 && bname2 && !_tcscmp (aname2, bname2)) {
5195 					match = j;
5196 					break;
5197 				}
5198 			}
5199 		}
5200 		if (match < 0) {
5201 			// no match, try friend names
5202 			for (j = 0; j < MAX_INPUT_DEVICES; j++) {
5203 				TCHAR *bname1 = uid[j].name;
5204 				if (aname1 && bname1 && !_tcscmp (aname1, bname1)) {
5205 					match = j;
5206 					break;
5207 				}
5208 			}
5209 		}
5210 		if (match >= 0) {
5211 			j = match;
5212 			if (j != i) {
5213 				struct uae_input_device *tmp = xmalloc (struct uae_input_device, 1);
5214 				memcpy (tmp, &uid[j], sizeof (struct uae_input_device));
5215 				memcpy (&uid[j], &uid[i], sizeof (struct uae_input_device));
5216 				memcpy (&uid[i], tmp, sizeof (struct uae_input_device));
5217 				xfree (tmp);
5218 			}
5219 		}
5220 	}
5221 	for (i = 0; i < inf->get_num (); i++) {
5222 		if (uid[i].name == NULL)
5223 			uid[i].name = my_strdup (inf->get_friendlyname (i));
5224 		if (uid[i].configname == NULL)
5225 			uid[i].configname = my_strdup (inf->get_uniquename (i));
5226 	}
5227 }
5228 
matchdevices_all(struct uae_prefs * prefs)5229 static void matchdevices_all (struct uae_prefs *prefs)
5230 {
5231 	int i;
5232 	for (i = 0; i < MAX_INPUT_SETTINGS; i++) {
5233 		matchdevices (&idev[IDTYPE_MOUSE], prefs->mouse_settings[i]);
5234 		matchdevices (&idev[IDTYPE_JOYSTICK], prefs->joystick_settings[i]);
5235 		matchdevices (&idev[IDTYPE_KEYBOARD], prefs->keyboard_settings[i]);
5236 	}
5237 }
5238 
inputdevice_set_gameports_mapping(struct uae_prefs * prefs,int devnum,int num,int evtnum,uae_u64 flags,int port)5239 bool inputdevice_set_gameports_mapping (struct uae_prefs *prefs, int devnum, int num, int evtnum, uae_u64 flags, int port)
5240 {
5241 	TCHAR name[256];
5242 	struct inputevent *ie;
5243 	int sub;
5244 
5245 	if (evtnum < 0) {
5246 		joysticks = prefs->joystick_settings[GAMEPORT_INPUT_SETTINGS];
5247 		mice = prefs->mouse_settings[GAMEPORT_INPUT_SETTINGS];
5248 		keyboards = prefs->keyboard_settings[GAMEPORT_INPUT_SETTINGS];
5249 		for (sub = 0; sub < MAX_INPUT_SUB_EVENT; sub++) {
5250 			int port2 = 0;
5251 			inputdevice_get_mapping (devnum, num, NULL, &port2, NULL, NULL, sub);
5252 			if (port2 == port + 1) {
5253 				inputdevice_set_mapping (devnum, num, NULL, NULL, 0, 0, sub);
5254 			}
5255 		}
5256 		return true;
5257 	}
5258 	ie = inputdevice_get_eventinfo (evtnum);
5259 	if (!inputdevice_get_eventname (ie, name))
5260 		return false;
5261 	joysticks = prefs->joystick_settings[GAMEPORT_INPUT_SETTINGS];
5262 	mice = prefs->mouse_settings[GAMEPORT_INPUT_SETTINGS];
5263 	keyboards = prefs->keyboard_settings[GAMEPORT_INPUT_SETTINGS];
5264 
5265 	sub = 0;
5266 	if (inputdevice_get_widget_type (devnum, num, NULL) != IDEV_WIDGET_KEY) {
5267 		for (sub = 0; sub < MAX_INPUT_SUB_EVENT; sub++) {
5268 			int port2 = 0;
5269 			int evt = inputdevice_get_mapping (devnum, num, NULL, &port2, NULL, NULL, sub);
5270 			if (port2 == port + 1 && evt == evtnum)
5271 				break;
5272 			if (!inputdevice_get_mapping (devnum, num, NULL, NULL, NULL, NULL, sub))
5273 				break;
5274 		}
5275 	}
5276 	if (sub >= MAX_INPUT_SUB_EVENT)
5277 		sub = MAX_INPUT_SUB_EVENT - 1;
5278 	inputdevice_set_mapping (devnum, num, name, NULL, IDEV_MAPPED_GAMEPORTSCUSTOM1 | flags, port + 1, sub);
5279 
5280 	joysticks = prefs->joystick_settings[prefs->input_selected_setting];
5281 	mice = prefs->mouse_settings[prefs->input_selected_setting];
5282 	keyboards = prefs->keyboard_settings[prefs->input_selected_setting];
5283 
5284 	if (prefs->input_selected_setting != GAMEPORT_INPUT_SETTINGS) {
5285 		int xport;
5286 		uae_u64 xflags;
5287 		TCHAR xname[MAX_DPATH], xcustom[MAX_DPATH];
5288 		inputdevice_get_mapping (devnum, num, &xflags, &xport, xname, xcustom, 0);
5289 		if (xport == 0)
5290 			inputdevice_set_mapping (devnum, num, xname, xcustom, xflags, MAX_JPORTS + 1, SPARE_SUB_EVENT);
5291 		inputdevice_set_mapping (devnum, num, name, NULL, IDEV_MAPPED_GAMEPORTSCUSTOM1 | flags, port + 1, 0);
5292 	}
5293 	return true;
5294 }
5295 
resetinput(void)5296 static void resetinput (void)
5297 {
5298 	if ((input_play || input_record) && hsync_counter > 0)
5299 		return;
5300 	cd32_shifter[0] = cd32_shifter[1] = 8;
5301 	for (int i = 0; i < MAX_JPORTS; i++) {
5302 		oleft[i] = 0;
5303 		oright[i] = 0;
5304 		otop[i] = 0;
5305 		obot[i] = 0;
5306 		oldmx[i] = -1;
5307 		oldmy[i] = -1;
5308 		joybutton[i] = 0;
5309 		joydir[i] = 0;
5310 		mouse_deltanoreset[i][0] = 0;
5311 		mouse_delta[i][0] = 0;
5312 		mouse_deltanoreset[i][1] = 0;
5313 		mouse_delta[i][1] = 0;
5314 		mouse_deltanoreset[i][2] = 0;
5315 		mouse_delta[i][2] = 0;
5316 	}
5317 	memset (keybuf, 0, sizeof keybuf);
5318 	for (int i = 0; i < INPUT_QUEUE_SIZE; i++)
5319 		input_queue[i].linecnt = input_queue[i].nextlinecnt = -1;
5320 
5321 	for (int i = 0; i < MAX_INPUT_SUB_EVENT; i++) {
5322 		sublevdir[0][i] = i;
5323 		sublevdir[1][i] = MAX_INPUT_SUB_EVENT - i - 1;
5324 	}
5325 }
5326 
5327 
inputdevice_updateconfig_internal(const struct uae_prefs * srcprrefs,struct uae_prefs * dstprefs)5328 void inputdevice_updateconfig_internal (const struct uae_prefs *srcprrefs, struct uae_prefs *dstprefs)
5329 {
5330 	int i;
5331 
5332 	keyboard_default = keyboard_default_table[currprefs.input_keyboard_type];
5333 
5334 	copyjport (srcprrefs, dstprefs, 0);
5335 	copyjport (srcprrefs, dstprefs, 1);
5336 	copyjport (srcprrefs, dstprefs, 2);
5337 	copyjport (srcprrefs, dstprefs, 3);
5338 
5339 	resetinput ();
5340 
5341 	joysticks = dstprefs->joystick_settings[dstprefs->input_selected_setting];
5342 	mice = dstprefs->mouse_settings[dstprefs->input_selected_setting];
5343 	keyboards = dstprefs->keyboard_settings[dstprefs->input_selected_setting];
5344 	internalevents = dstprefs->internalevent_settings[dstprefs->input_selected_setting];
5345 
5346 	matchdevices_all (dstprefs);
5347 
5348 	memset (joysticks2, 0, sizeof joysticks2);
5349 	memset (mice2, 0, sizeof mice2);
5350 
5351 	joysticks = dstprefs->joystick_settings[GAMEPORT_INPUT_SETTINGS];
5352 	mice = dstprefs->mouse_settings[GAMEPORT_INPUT_SETTINGS];
5353 	keyboards = dstprefs->keyboard_settings[GAMEPORT_INPUT_SETTINGS];
5354 	internalevents = dstprefs->internalevent_settings[GAMEPORT_INPUT_SETTINGS];
5355 
5356 	for (i = 0; i < MAX_INPUT_SETTINGS; i++) {
5357 		joysticks[i].enabled = 0;
5358 		mice[i].enabled = 0;
5359 	}
5360 
5361 	compatibility_copy (dstprefs, true);
5362 	joysticks = dstprefs->joystick_settings[dstprefs->input_selected_setting];
5363 	mice = dstprefs->mouse_settings[dstprefs->input_selected_setting];
5364 	keyboards = dstprefs->keyboard_settings[dstprefs->input_selected_setting];
5365 	internalevents = dstprefs->internalevent_settings[dstprefs->input_selected_setting];
5366 
5367 	if (dstprefs->input_selected_setting != GAMEPORT_INPUT_SETTINGS) {
5368 		compatibility_copy (dstprefs, false);
5369 	}
5370 
5371 	disableifempty (dstprefs);
5372 	scanevents (dstprefs);
5373 }
5374 
inputdevice_updateconfig(const struct uae_prefs * srcprefs,struct uae_prefs * dstprefs)5375 void inputdevice_updateconfig (const struct uae_prefs *srcprefs, struct uae_prefs *dstprefs)
5376 {
5377 	inputdevice_updateconfig_internal (srcprefs, dstprefs);
5378 
5379 	config_changed = 1;
5380 
5381 #ifdef RETROPLATFORM
5382 	rp_input_change (0);
5383 	rp_input_change (1);
5384 	rp_input_change (2);
5385 	rp_input_change (3);
5386 	for (int i = 0; i < MAX_JPORTS; i++)
5387 		rp_update_gameport (i, -1, 0);
5388 #endif
5389 }
5390 
5391 /* called when devices get inserted or removed
5392 * store old devices temporarily, enumerate all devices
5393 * restore old devices back (order may have changed)
5394 */
inputdevice_devicechange(struct uae_prefs * prefs)5395 void inputdevice_devicechange (struct uae_prefs *prefs)
5396 {
5397 	int acc = input_acquired;
5398 	int i, idx;
5399 	TCHAR *jports[MAX_JPORTS];
5400 	int jportskb[MAX_JPORTS], jportsmode[MAX_JPORTS];
5401 	int jportid[MAX_JPORTS], jportaf[MAX_JPORTS];
5402 
5403 	for (i = 0; i < MAX_JPORTS; i++) {
5404 		jports[i] = NULL;
5405 		jportskb[i] = -1;
5406 		jportid[i] = prefs->jports[i].id;
5407 		jportaf[i] = prefs->jports[i].autofire;
5408 		idx = inputdevice_getjoyportdevice (i, prefs->jports[i].id);
5409 		if (idx >= JSEM_LASTKBD) {
5410 			struct inputdevice_functions *idf;
5411 			int devidx;
5412 			idx -= JSEM_LASTKBD;
5413 			idf = getidf (idx);
5414 			devidx = inputdevice_get_device_index (idx);
5415 			jports[i] = my_strdup (idf->get_uniquename (devidx));
5416 		} else {
5417 			jportskb[i] = idx;
5418 		}
5419 		jportsmode[i] = prefs->jports[i].mode;
5420 	}
5421 
5422 	inputdevice_unacquire ();
5423 	idev[IDTYPE_JOYSTICK].close ();
5424 	idev[IDTYPE_MOUSE].close ();
5425 	idev[IDTYPE_KEYBOARD].close ();
5426 	idev[IDTYPE_JOYSTICK].init ();
5427 	idev[IDTYPE_MOUSE].init ();
5428 	idev[IDTYPE_KEYBOARD].init ();
5429 	matchdevices (&idev[IDTYPE_MOUSE], mice);
5430 	matchdevices (&idev[IDTYPE_JOYSTICK], joysticks);
5431 	matchdevices (&idev[IDTYPE_KEYBOARD], keyboards);
5432 
5433 	for (i = 0; i < MAX_JPORTS; i++) {
5434 		freejport (prefs, i);
5435 		if (jportid[i] == JPORT_CUSTOM) {
5436 			inputdevice_joyport_config (prefs, _T("custom"), i, jportsmode[i], 0);
5437 		} else if (jports[i]) {
5438 			inputdevice_joyport_config (prefs, jports[i], i, jportsmode[i], 2);
5439 		} else if (jportskb[i] >= 0) {
5440 			TCHAR tmp[10];
5441 			_stprintf (tmp, _T("kbd%d"), jportskb[i]);
5442 			inputdevice_joyport_config (prefs, tmp, i, jportsmode[i], 0);
5443 		}
5444 		prefs->jports[i].autofire = jportaf[i];
5445 		xfree (jports[i]);
5446 	}
5447 
5448 	if (prefs == &changed_prefs)
5449 		inputdevice_copyconfig (&changed_prefs, &currprefs);
5450 	if (acc)
5451 		inputdevice_acquire (true);
5452 #ifdef RETROPLATFORM
5453 	rp_enumdevices ();
5454 #endif
5455 	config_changed = 1;
5456 }
5457 
5458 
5459 // set default prefs to all input configuration settings
inputdevice_default_prefs(struct uae_prefs * p)5460 void inputdevice_default_prefs (struct uae_prefs *p)
5461 {
5462 	inputdevice_init ();
5463 
5464 	p->input_selected_setting = GAMEPORT_INPUT_SETTINGS;
5465 	p->input_joymouse_multiplier = 100;
5466 	p->input_joymouse_deadzone = 33;
5467 	p->input_joystick_deadzone = 33;
5468 	p->input_joymouse_speed = 10;
5469 	p->input_analog_joystick_mult = 15;
5470 	p->input_analog_joystick_offset = -1;
5471 	p->input_mouse_speed = 100;
5472 	p->input_autofire_linecnt = 600;
5473 	p->input_keyboard_type = 0;
5474 	keyboard_default = keyboard_default_table[p->input_keyboard_type];
5475 	inputdevice_default_kb_all (p);
5476 }
5477 
5478 // set default keyboard and keyboard>joystick layouts
inputdevice_setkeytranslation(struct uae_input_device_kbr_default ** trans,int ** kbmaps)5479 void inputdevice_setkeytranslation (struct uae_input_device_kbr_default **trans, int **kbmaps)
5480 {
5481 	keyboard_default_table = trans;
5482 	keyboard_default_kbmaps = kbmaps;
5483 }
5484 
5485 // return true if keyboard/scancode pair is mapped
inputdevice_iskeymapped(int keyboard,int scancode)5486 int inputdevice_iskeymapped (int keyboard, int scancode)
5487 {
5488 /* REMOVEME:
5489  * nowhere used
5490  */
5491 #if 0
5492 	struct uae_input_device *na = &keyboards[keyboard];
5493 #endif
5494 	if (!keyboards || scancode < 0)
5495 		return 0;
5496 	return scancodeused[keyboard][scancode];
5497 }
5498 
inputdevice_synccapslock(int oldcaps,int * capstable)5499 int inputdevice_synccapslock (int oldcaps, int *capstable)
5500 {
5501 	struct uae_input_device *na = &keyboards[0];
5502 	int j, i;
5503 
5504 	if (!keyboards)
5505 		return -1;
5506 	for (j = 0; na->extra[j]; j++) {
5507 		if (na->extra[j] == INPUTEVENT_KEY_CAPS_LOCK) {
5508 			for (i = 0; capstable[i]; i += 2) {
5509 				if (na->extra[j] == capstable[i]) {
5510 					if (oldcaps != capstable[i + 1]) {
5511 						oldcaps = capstable[i + 1];
5512 						inputdevice_translatekeycode (0, capstable[i], oldcaps ? -1 : 0);
5513 					}
5514 					return i;
5515 				}
5516 			}
5517 		}
5518 	}
5519 	return -1;
5520 }
5521 
rqualifiers(uae_u64 flags,bool release)5522 static void rqualifiers (uae_u64 flags, bool release)
5523 {
5524 	uae_u64 mask = ID_FLAG_QUALIFIER1 << 1;
5525 	for (int i = 0; i < MAX_INPUT_QUALIFIERS; i++) {
5526 		if ((flags & mask) && (mask & (qualifiers << 1))) {
5527 			if (release) {
5528 				if (!(mask & qualifiers_r)) {
5529 					qualifiers_r |= mask;
5530 					for (int ii = 0; ii < MAX_INPUT_SUB_EVENT; ii++) {
5531 						int qevt = qualifiers_evt[i][ii];
5532 						if (qevt > 0) {
5533 							write_log (_T("Released %d '%s'\n"), qevt, events[qevt].name);
5534 							inputdevice_do_keyboard (events[qevt].data, 0);
5535 						}
5536 					}
5537 				}
5538 			} else {
5539 				if ((mask & qualifiers_r)) {
5540 					qualifiers_r &= ~mask;
5541 					for (int ii = 0; ii < MAX_INPUT_SUB_EVENT; ii++) {
5542 						int qevt = qualifiers_evt[i][ii];
5543 						if (qevt > 0) {
5544 							write_log (_T("Pressed %d '%s'\n"), qevt, events[qevt].name);
5545 							inputdevice_do_keyboard (events[qevt].data, 1);
5546 						}
5547 					}
5548 				}
5549 			}
5550 		}
5551 		mask <<= 2;
5552 	}
5553 }
5554 
inputdevice_translatekeycode_2(int keyboard,int scancode,int keystate,bool qualifiercheckonly)5555 static int inputdevice_translatekeycode_2 (int keyboard, int scancode, int keystate, bool qualifiercheckonly)
5556 {
5557 	struct uae_input_device *na = &keyboards[keyboard];
5558 	int j, k;
5559 	int handled = 0;
5560 	bool didcustom = false;
5561 
5562 	if (!keyboards || scancode < 0)
5563 		return handled;
5564 
5565 	j = 0;
5566 	while (j < MAX_INPUT_DEVICE_EVENTS && na->extra[j] >= 0) {
5567 		if (na->extra[j] == scancode) {
5568 			bool qualonly;
5569 			uae_u64 qualmask[MAX_INPUT_SUB_EVENT];
5570 			getqualmask (qualmask, na, j, &qualonly);
5571 
5572 			if (qualonly)
5573 				qualifiercheckonly = true;
5574 			for (k = 0; k < MAX_INPUT_SUB_EVENT; k++) {/* send key release events in reverse order */
5575 				uae_u64 *flagsp = &na->flags[j][sublevdir[keystate == 0 ? 1 : 0][k]];
5576 				int evt = na->eventid[j][sublevdir[keystate == 0 ? 1 : 0][k]];
5577 				uae_u64 flags = *flagsp;
5578 				int autofire = (flags & ID_FLAG_AUTOFIRE) ? 1 : 0;
5579 				int toggle = (flags & ID_FLAG_TOGGLE) ? 1 : 0;
5580 				int inverttoggle = (flags & ID_FLAG_INVERTTOGGLE) ? 1 : 0;
5581 				int invert = (flags & ID_FLAG_INVERT) ? 1 : 0;
5582 				int toggled;
5583 				int state;
5584 
5585 				if (keystate < 0) {
5586 					state = keystate;
5587 				} else if (invert) {
5588 					state = keystate ? 0 : 1;
5589 				} else {
5590 					state = keystate;
5591 				}
5592 
5593 				setqualifiers (evt, state > 0);
5594 
5595 				if (qualifiercheckonly) {
5596 					if (!state && (flags & ID_FLAG_CANRELEASE)) {
5597 						*flagsp &= ~ID_FLAG_CANRELEASE;
5598 						handle_input_event (evt, state, 1, autofire, true, false);
5599 						if (k == 0) {
5600 							process_custom_event (na, j, state, qualmask, autofire, k);
5601 						}
5602 					}
5603 					continue;
5604 				}
5605 
5606 				if (!state) {
5607 					didcustom |= process_custom_event (na, j, state, qualmask, autofire, k);
5608 				}
5609 
5610 				// if evt == caps and scan == caps: sync with native caps led
5611 				if (evt == INPUTEVENT_KEY_CAPS_LOCK) {
5612 					int v;
5613 					if (state < 0)
5614 						state = 1;
5615 					v = target_checkcapslock (scancode, &state);
5616 					if (v < 0)
5617 						continue;
5618 					if (v > 0)
5619 						toggle = 0;
5620 				} else if (state < 0) {
5621 					// it was caps lock resync, ignore, not mapped to caps
5622 					continue;
5623 				}
5624 
5625 				if (inverttoggle) {
5626 					na->flags[j][sublevdir[state == 0 ? 1 : 0][k]] &= ~ID_FLAG_TOGGLED;
5627 					if (state) {
5628 						queue_input_event (evt, NULL, -1, 0, 0, 1);
5629 						handled |= handle_input_event (evt, 1, 1, 0, true, false);
5630 					} else {
5631 						handled |= handle_input_event (evt, 1, 1, autofire, true, false);
5632 					}
5633 					didcustom |= process_custom_event (na, j, state, qualmask, autofire, k);
5634 				} else if (toggle) {
5635 					if (!state)
5636 						continue;
5637 					if (!checkqualifiers (evt, flags, qualmask, na->eventid[j]))
5638 						continue;
5639 					*flagsp ^= ID_FLAG_TOGGLED;
5640 					toggled = (*flagsp & ID_FLAG_TOGGLED) ? 1 : 0;
5641 					handled |= handle_input_event (evt, toggled, 1, autofire, true, false);
5642 					if (k == 0)
5643 						didcustom |= process_custom_event (na, j, state, qualmask, autofire, k);
5644 				} else {
5645 					rqualifiers (flags, state ? true : false);
5646 					if (!checkqualifiers (evt, flags, qualmask, na->eventid[j])) {
5647 						if (!state && !(flags & ID_FLAG_CANRELEASE)) {
5648 							if (!invert)
5649 								continue;
5650 						} else if (state) {
5651 							continue;
5652 						}
5653 					}
5654 
5655 					if (state) {
5656 						if (!invert)
5657 							*flagsp |= ID_FLAG_CANRELEASE;
5658 					} else {
5659 						if (!(flags & ID_FLAG_CANRELEASE) && !invert)
5660 							continue;
5661 						*flagsp &= ~ID_FLAG_CANRELEASE;
5662 					}
5663 					handled |= handle_input_event (evt, state, 1, autofire, true, false);
5664 					didcustom |= process_custom_event (na, j, state, qualmask, autofire, k);
5665 				}
5666 			}
5667 			if (!didcustom)
5668 				queue_input_event (-1, NULL, -1, 0, 0, 1);
5669 			return handled;
5670 		}
5671 		j++;
5672 	}
5673 	return handled;
5674 }
5675 
5676 #define IECODE_UP_PREFIX 0x80
5677 #define RAW_STEALTH 0x68
5678 #define STEALTHF_E0KEY 0x08
5679 #define STEALTHF_UPSTROKE 0x04
5680 #define STEALTHF_SPECIAL 0x02
5681 #define STEALTHF_E1KEY 0x01
5682 
sendmmcodes(int code,int newstate)5683 static void sendmmcodes (int code, int newstate)
5684 {
5685 	uae_u8 b;
5686 
5687 	b = RAW_STEALTH | IECODE_UP_PREFIX;
5688 	record_key(((b << 1) | (b >> 7)) & 0xff);
5689 	b = IECODE_UP_PREFIX;
5690 	if ((code >> 8) == 0x01)
5691 		b |= STEALTHF_E0KEY;
5692 	if ((code >> 8) == 0x02)
5693 		b |= STEALTHF_E1KEY;
5694 	if (!newstate)
5695 		b |= STEALTHF_UPSTROKE;
5696 	record_key(((b << 1) | (b >> 7)) & 0xff);
5697 	b = ((code >> 4) & 0x0f) | IECODE_UP_PREFIX;
5698 	record_key(((b << 1) | (b >> 7)) & 0xff);
5699 	b = (code & 0x0f) | IECODE_UP_PREFIX;
5700 	record_key(((b << 1) | (b >> 7)) & 0xff);
5701 }
5702 
5703 // main keyboard press/release entry point
inputdevice_translatekeycode(int keyboard,int scancode,int state)5704 int inputdevice_translatekeycode (int keyboard, int scancode, int state)
5705 {
5706 	if (inputdevice_translatekeycode_2 (keyboard, scancode, state, false))
5707 		return 1;
5708 	if (currprefs.mmkeyboard && scancode > 0)
5709 		sendmmcodes (scancode, state);
5710 	return 0;
5711 }
inputdevice_checkqualifierkeycode(int keyboard,int scancode,int state)5712 void inputdevice_checkqualifierkeycode (int keyboard, int scancode, int state)
5713 {
5714 	inputdevice_translatekeycode_2 (keyboard, scancode, state, true);
5715 }
5716 
5717 static const TCHAR *internaleventlabels[] = {
5718 	_T("CPU reset"),
5719 	_T("Keyboard reset"),
5720 	NULL
5721 };
init_int(void)5722 static int init_int (void)
5723 {
5724 	return 1;
5725 }
close_int(void)5726 static void close_int (void)
5727 {
5728 }
acquire_int(int num,int flags)5729 static int acquire_int (int num, int flags)
5730 {
5731 	return 1;
5732 }
unacquire_int(int num)5733 static void unacquire_int (int num)
5734 {
5735 }
read_int(void)5736 static void read_int (void)
5737 {
5738 }
get_int_num(void)5739 static int get_int_num (void)
5740 {
5741 	return 1;
5742 }
get_int_friendlyname(int num)5743 static TCHAR *get_int_friendlyname (int num)
5744 {
5745 	return _T("Internal events");
5746 }
get_int_uniquename(int num)5747 static TCHAR *get_int_uniquename (int num)
5748 {
5749 	return _T("INTERNALEVENTS1");
5750 }
get_int_widget_num(int num)5751 static int get_int_widget_num (int num)
5752 {
5753 	int i;
5754 	for (i = 0; internaleventlabels[i]; i++);
5755 	return i;
5756 }
get_int_widget_type(int kb,int num,TCHAR * name,uae_u32 * code)5757 static int get_int_widget_type (int kb, int num, TCHAR *name, uae_u32 *code)
5758 {
5759 	if (code)
5760 		*code = num;
5761 	if (name)
5762 		_tcscpy (name, internaleventlabels[num]);
5763 	return IDEV_WIDGET_BUTTON;
5764 }
get_int_widget_first(int kb,int type)5765 static int get_int_widget_first (int kb, int type)
5766 {
5767 	return 0;
5768 }
get_int_flags(int num)5769 static int get_int_flags (int num)
5770 {
5771 	return 0;
5772 }
5773 
5774 struct inputdevice_functions inputdevicefunc_internalevent = {
5775 	init_int, close_int, acquire_int, unacquire_int, read_int,
5776 	get_int_num, get_int_friendlyname, get_int_uniquename,
5777 	get_int_widget_num, get_int_widget_type,
5778 	get_int_widget_first,
5779 	get_int_flags
5780 };
5781 
send_internalevent(int eventid)5782 void send_internalevent (int eventid)
5783 {
5784 	setbuttonstateall (&internalevents[0], NULL, eventid, -1);
5785 }
5786 
5787 
inputdevice_init(void)5788 void inputdevice_init (void)
5789 {
5790 	idev[IDTYPE_JOYSTICK] = inputdevicefunc_joystick;
5791 	idev[IDTYPE_JOYSTICK].init ();
5792 	idev[IDTYPE_MOUSE] = inputdevicefunc_mouse;
5793 	idev[IDTYPE_MOUSE].init ();
5794 	idev[IDTYPE_KEYBOARD] = inputdevicefunc_keyboard;
5795 	idev[IDTYPE_KEYBOARD].init ();
5796 	idev[IDTYPE_INTERNALEVENT] = inputdevicefunc_internalevent;
5797 	idev[IDTYPE_INTERNALEVENT].init ();
5798 }
5799 
inputdevice_close(void)5800 void inputdevice_close (void)
5801 {
5802 	idev[IDTYPE_JOYSTICK].close ();
5803 	idev[IDTYPE_MOUSE].close ();
5804 	idev[IDTYPE_KEYBOARD].close ();
5805 	idev[IDTYPE_INTERNALEVENT].close ();
5806 	inprec_close (true);
5807 }
5808 
get_uid(const struct inputdevice_functions * id,int devnum)5809 static struct uae_input_device *get_uid (const struct inputdevice_functions *id, int devnum)
5810 {
5811 	struct uae_input_device *uid = 0;
5812 	if (id == &idev[IDTYPE_JOYSTICK]) {
5813 		uid = &joysticks[devnum];
5814 	} else if (id == &idev[IDTYPE_MOUSE]) {
5815 		uid = &mice[devnum];
5816 	} else if (id == &idev[IDTYPE_KEYBOARD]) {
5817 		uid = &keyboards[devnum];
5818 	} else if (id == &idev[IDTYPE_INTERNALEVENT]) {
5819 		uid = &internalevents[devnum];
5820 	}
5821 	return uid;
5822 }
5823 
get_event_data(const struct inputdevice_functions * id,int devnum,int num,int * eventid,TCHAR ** custom,uae_u64 * flags,int * port,int sub)5824 static int get_event_data (const struct inputdevice_functions *id, int devnum, int num, int *eventid, TCHAR **custom, uae_u64 *flags, int *port, int sub)
5825 {
5826 	const struct uae_input_device *uid = get_uid (id, devnum);
5827 	int type = id->get_widget_type (devnum, num, 0, 0);
5828 	int i;
5829 	if (type == IDEV_WIDGET_BUTTON || type == IDEV_WIDGET_BUTTONAXIS) {
5830 		i = num - id->get_widget_first (devnum, IDEV_WIDGET_BUTTON) + ID_BUTTON_OFFSET;
5831 		*eventid = uid->eventid[i][sub];
5832 		if (flags)
5833 			*flags = uid->flags[i][sub];
5834 		if (port)
5835 			*port = uid->port[i][sub];
5836 		if (custom)
5837 			*custom = uid->custom[i][sub];
5838 		return i;
5839 	} else if (type == IDEV_WIDGET_AXIS) {
5840 		i = num - id->get_widget_first (devnum, type) + ID_AXIS_OFFSET;
5841 		*eventid = uid->eventid[i][sub];
5842 		if (flags)
5843 			*flags = uid->flags[i][sub];
5844 		if (port)
5845 			*port = uid->port[i][sub];
5846 		if (custom)
5847 			*custom = uid->custom[i][sub];
5848 		return i;
5849 	} else if (type == IDEV_WIDGET_KEY) {
5850 		i = num - id->get_widget_first (devnum, type);
5851 		*eventid = uid->eventid[i][sub];
5852 		if (flags)
5853 			*flags = uid->flags[i][sub];
5854 		if (port)
5855 			*port = uid->port[i][sub];
5856 		if (custom)
5857 			*custom = uid->custom[i][sub];
5858 		return i;
5859 	}
5860 	return -1;
5861 }
5862 
stripstrdup(const TCHAR * s)5863 static TCHAR *stripstrdup (const TCHAR *s)
5864 {
5865 	TCHAR *out = my_strdup (s);
5866 	if (!out)
5867 		return NULL;
5868 	for (int i = 0; out[i]; i++) {
5869 		if (out[i] < ' ')
5870 			out[i] = ' ';
5871 	}
5872 	return out;
5873 }
5874 
put_event_data(const struct inputdevice_functions * id,int devnum,int num,int eventid,TCHAR * custom,uae_u64 flags,int port,int sub)5875 static int put_event_data (const struct inputdevice_functions *id, int devnum, int num, int eventid, TCHAR *custom, uae_u64 flags, int port, int sub)
5876 {
5877 	struct uae_input_device *uid = get_uid (id, devnum);
5878 	int type = id->get_widget_type (devnum, num, 0, 0);
5879 	int i, ret;
5880 
5881 	for (i = 0; i < MAX_INPUT_QUALIFIERS; i++) {
5882 		uae_u64 mask1 = ID_FLAG_QUALIFIER1 << (i * 2);
5883 		uae_u64 mask2 = mask1 << 1;
5884 		if ((flags & (mask1 | mask2)) == (mask1 | mask2))
5885 			flags &= ~mask2;
5886 	}
5887 	if (custom && custom[0] == 0)
5888 		custom = NULL;
5889 	if (custom)
5890 		eventid = 0;
5891 	if (eventid <= 0 && !custom)
5892 		flags = 0;
5893 
5894 	ret = -1;
5895 	if (type == IDEV_WIDGET_BUTTON || type == IDEV_WIDGET_BUTTONAXIS) {
5896 		i = num - id->get_widget_first (devnum, IDEV_WIDGET_BUTTON) + ID_BUTTON_OFFSET;
5897 		uid->eventid[i][sub] = eventid;
5898 		uid->flags[i][sub] = flags;
5899 		uid->port[i][sub] = port;
5900 		xfree (uid->custom[i][sub]);
5901 		uid->custom[i][sub] = custom && _tcslen (custom) > 0 ? stripstrdup (custom) : NULL;
5902 		ret = i;
5903 	} else if (type == IDEV_WIDGET_AXIS) {
5904 		i = num - id->get_widget_first (devnum, type) + ID_AXIS_OFFSET;
5905 		uid->eventid[i][sub] = eventid;
5906 		uid->flags[i][sub] = flags;
5907 		uid->port[i][sub] = port;
5908 		xfree (uid->custom[i][sub]);
5909 		uid->custom[i][sub] = custom && _tcslen (custom) > 0 ? stripstrdup (custom) : NULL;
5910 		ret = i;
5911 	} else if (type == IDEV_WIDGET_KEY) {
5912 		i = num - id->get_widget_first (devnum, type);
5913 		uid->eventid[i][sub] = eventid;
5914 		uid->flags[i][sub] = flags;
5915 		uid->port[i][sub] = port;
5916 		xfree (uid->custom[i][sub]);
5917 		uid->custom[i][sub] = custom && _tcslen (custom) > 0 ? stripstrdup (custom) : NULL;
5918 		ret = i;
5919 	}
5920 	if (ret < 0)
5921 	return -1;
5922 	if (uid->custom[i][sub])
5923 		uid->eventid[i][sub] = INPUTEVENT_SPC_CUSTOM_EVENT;
5924 	return ret;
5925 }
5926 
is_event_used(const struct inputdevice_functions * id,int devnum,int isnum,int isevent)5927 static int is_event_used (const struct inputdevice_functions *id, int devnum, int isnum, int isevent)
5928 {
5929 /* REMOVEME:
5930  * nowhere used
5931  */
5932 #if 0
5933 	struct uae_input_device *uid = get_uid (id, devnum);
5934 #endif
5935 	int num, evt, sub;
5936 
5937 	for (num = 0; num < id->get_widget_num (devnum); num++) {
5938 		for (sub = 0; sub < MAX_INPUT_SUB_EVENT; sub++) {
5939 			if (get_event_data (id, devnum, num, &evt, NULL, NULL, NULL, sub) >= 0) {
5940 				if (evt == isevent && isnum != num)
5941 					return 1;
5942 			}
5943 		}
5944 	}
5945 	return 0;
5946 }
5947 
5948 // device based index from global device index
inputdevice_get_device_index(int devnum)5949 int inputdevice_get_device_index (int devnum)
5950 {
5951 	int jcnt = idev[IDTYPE_JOYSTICK].get_num ();
5952 	int mcnt = idev[IDTYPE_MOUSE].get_num ();
5953 	int kcnt = idev[IDTYPE_KEYBOARD].get_num ();
5954 
5955 	if (devnum < jcnt)
5956 		return devnum;
5957 	else if (devnum < jcnt + mcnt)
5958 		return devnum - jcnt;
5959 	else if (devnum < jcnt + mcnt + kcnt)
5960 		return devnum - (jcnt + mcnt);
5961 	else if (devnum < jcnt + mcnt + kcnt + INTERNALEVENT_COUNT)
5962 		return devnum - (jcnt + mcnt + kcnt);
5963 		return -1;
5964 }
5965 
getdevnum(int type,int devnum)5966 static int getdevnum (int type, int devnum)
5967 {
5968 	int jcnt = idev[IDTYPE_JOYSTICK].get_num ();
5969 	int mcnt = idev[IDTYPE_MOUSE].get_num ();
5970 	int kcnt = idev[IDTYPE_KEYBOARD].get_num ();
5971 
5972 	if (type == IDTYPE_JOYSTICK)
5973 		return devnum;
5974 	else if (type == IDTYPE_MOUSE)
5975 		return jcnt + devnum;
5976 	else if (type == IDTYPE_KEYBOARD)
5977 		return jcnt + mcnt + devnum;
5978 	else if (type == IDTYPE_INTERNALEVENT)
5979 		return jcnt + mcnt + kcnt + devnum;
5980 	return -1;
5981 }
5982 
gettype(int devnum)5983 static int gettype (int devnum)
5984 {
5985 	int jcnt = idev[IDTYPE_JOYSTICK].get_num ();
5986 	int mcnt = idev[IDTYPE_MOUSE].get_num ();
5987 	int kcnt = idev[IDTYPE_KEYBOARD].get_num ();
5988 
5989 	if (devnum < jcnt)
5990 		return IDTYPE_JOYSTICK;
5991 	else if (devnum < jcnt + mcnt)
5992 		return IDTYPE_MOUSE;
5993 	else if (devnum < jcnt + mcnt + kcnt)
5994 		return IDTYPE_KEYBOARD;
5995 	else if (devnum < jcnt + mcnt + kcnt + INTERNALEVENT_COUNT)
5996 		return IDTYPE_INTERNALEVENT;
5997 		return -1;
5998 }
5999 
getidf(int devnum)6000 static struct inputdevice_functions *getidf (int devnum)
6001 {
6002 	int type = gettype (devnum);
6003 	if (type < 0)
6004 		return NULL;
6005 	return &idev[type];
6006 }
6007 
inputdevice_get_eventinfo(int evt)6008 struct inputevent *inputdevice_get_eventinfo (int evt)
6009 {
6010 	if (evt > 0 && !events[evt].name)
6011 		return NULL;
6012 	return &events[evt];
6013 }
6014 
6015 
6016 /* returns number of devices of type "type" */
inputdevice_get_device_total(int type)6017 int inputdevice_get_device_total (int type)
6018 {
6019 	return idev[type].get_num ();
6020 }
6021 /* returns the name of device */
inputdevice_get_device_name(int type,int devnum)6022 TCHAR *inputdevice_get_device_name (int type, int devnum)
6023 {
6024 	return idev[type].get_friendlyname (devnum);
6025 }
6026 /* returns the name of device */
inputdevice_get_device_name2(int devnum)6027 TCHAR *inputdevice_get_device_name2 (int devnum)
6028 {
6029 	return getidf (devnum)->get_friendlyname (inputdevice_get_device_index (devnum));
6030 }
6031 /* returns machine readable name of device */
inputdevice_get_device_unique_name(int type,int devnum)6032 TCHAR *inputdevice_get_device_unique_name (int type, int devnum)
6033 {
6034 	return idev[type].get_uniquename (devnum);
6035 }
6036 /* returns state (enabled/disabled) */
inputdevice_get_device_status(int devnum)6037 int inputdevice_get_device_status (int devnum)
6038 {
6039 	const struct inputdevice_functions *idf = getidf (devnum);
6040 	if (idf == NULL)
6041 		return -1;
6042 	struct uae_input_device *uid = get_uid (idf, inputdevice_get_device_index (devnum));
6043 	return uid->enabled;
6044 }
6045 
6046 /* set state (enabled/disabled) */
inputdevice_set_device_status(int devnum,int enabled)6047 void inputdevice_set_device_status (int devnum, int enabled)
6048 {
6049 	const struct inputdevice_functions *idf = getidf (devnum);
6050 	int num = inputdevice_get_device_index (devnum);
6051 	struct uae_input_device *uid = get_uid (idf, num);
6052 	if (enabled) { // disable incompatible devices ("super device" vs "raw device")
6053 		for (int i = 0; i < idf->get_num (); i++) {
6054 			if (idf->get_flags (i) != idf->get_flags (num)) {
6055 				struct uae_input_device *uid2 = get_uid (idf, i);
6056 				uid2->enabled = 0;
6057 			}
6058 		}
6059 	}
6060 	uid->enabled = enabled;
6061 }
6062 
6063 /* returns number of axis/buttons and keys from selected device */
inputdevice_get_widget_num(int devnum)6064 int inputdevice_get_widget_num (int devnum)
6065 {
6066 	const struct inputdevice_functions *idf = getidf (devnum);
6067 	return idf->get_widget_num (inputdevice_get_device_index (devnum));
6068 }
6069 
6070 // return name of event, do not use ie->name directly
inputdevice_get_eventname(const struct inputevent * ie,TCHAR * out)6071 bool inputdevice_get_eventname (const struct inputevent *ie, TCHAR *out)
6072 {
6073 	if (!out)
6074 		return false;
6075 	_tcscpy (out, ie->name);
6076 	return true;
6077 }
6078 
inputdevice_iterate(int devnum,int num,TCHAR * name,int * af)6079 int inputdevice_iterate (int devnum, int num, TCHAR *name, int *af)
6080 {
6081 	const struct inputdevice_functions *idf = getidf (devnum);
6082 	static int id_iterator;
6083 	struct inputevent *ie;
6084 	int mask, data, type;
6085 	uae_u64 flags;
6086 	int devindex = inputdevice_get_device_index (devnum);
6087 
6088 	*af = 0;
6089 	*name = 0;
6090 	for (;;) {
6091 		ie = &events[++id_iterator];
6092 		if (!ie->confname) {
6093 			id_iterator = 0;
6094 			return 0;
6095 		}
6096 		mask = 0;
6097 		type = idf->get_widget_type (devindex, num, NULL, NULL);
6098 		if (type == IDEV_WIDGET_BUTTON || type == IDEV_WIDGET_BUTTONAXIS) {
6099 			if (idf == &idev[IDTYPE_JOYSTICK]) {
6100 				mask |= AM_JOY_BUT;
6101 			} else {
6102 				mask |= AM_MOUSE_BUT;
6103 			}
6104 		} else if (type == IDEV_WIDGET_AXIS) {
6105 			if (idf == &idev[IDTYPE_JOYSTICK]) {
6106 				mask |= AM_JOY_AXIS;
6107 			} else {
6108 				mask |= AM_MOUSE_AXIS;
6109 			}
6110 		} else if (type == IDEV_WIDGET_KEY) {
6111 			mask |= AM_K;
6112 		}
6113 		if (ie->allow_mask & AM_INFO) {
6114 			struct inputevent *ie2 = ie + 1;
6115 			while (!(ie2->allow_mask & AM_INFO)) {
6116 				if (is_event_used (idf, devindex, ie2 - ie, -1)) {
6117 					ie2++;
6118 					continue;
6119 				}
6120 				if (ie2->allow_mask & mask)
6121 					break;
6122 				ie2++;
6123 			}
6124 			if (!(ie2->allow_mask & AM_INFO))
6125 				mask |= AM_INFO;
6126 		}
6127 		if (!(ie->allow_mask & mask))
6128 			continue;
6129 		get_event_data (idf, devindex, num, &data, NULL, &flags, NULL, 0);
6130 		inputdevice_get_eventname (ie, name);
6131 		*af = (flags & ID_FLAG_AUTOFIRE) ? 1 : 0;
6132 		return 1;
6133 	}
6134 }
6135 
6136 // return mapped event from devnum/num/sub
inputdevice_get_mapping(int devnum,int num,uae_u64 * pflags,int * pport,TCHAR * name,TCHAR * custom,int sub)6137 int inputdevice_get_mapping (int devnum, int num, uae_u64 *pflags, int *pport, TCHAR *name, TCHAR *custom, int sub)
6138 {
6139 	const struct inputdevice_functions *idf = getidf (devnum);
6140 	const struct uae_input_device *uid = get_uid (idf, inputdevice_get_device_index (devnum));
6141 	int port, data;
6142 	uae_u64 flags = 0, flag;
6143 	int devindex = inputdevice_get_device_index (devnum);
6144 	TCHAR *customp = NULL;
6145 
6146 	if (name)
6147 		_tcscpy (name, _T("<none>"));
6148 	if (custom)
6149 		custom[0] = 0;
6150 	if (pflags)
6151 		*pflags = 0;
6152 	if (pport)
6153 		*pport = 0;
6154 	if (uid == 0 || num < 0)
6155 		return 0;
6156 	if (get_event_data (idf, devindex, num, &data, &customp, &flag, &port, sub) < 0)
6157 		return 0;
6158 	if (customp && custom)
6159 		_tcscpy (custom, customp);
6160 	if (flag & ID_FLAG_AUTOFIRE)
6161 		flags |= IDEV_MAPPED_AUTOFIRE_SET;
6162 	if (flag & ID_FLAG_TOGGLE)
6163 		flags |= IDEV_MAPPED_TOGGLE;
6164 	if (flag & ID_FLAG_INVERTTOGGLE)
6165 		flags |= IDEV_MAPPED_INVERTTOGGLE;
6166 	if (flag & ID_FLAG_INVERT)
6167 		flags |= IDEV_MAPPED_INVERT;
6168 	if (flag & ID_FLAG_GAMEPORTSCUSTOM1)
6169 		flags |= IDEV_MAPPED_GAMEPORTSCUSTOM1;
6170 	if (flag & ID_FLAG_GAMEPORTSCUSTOM2)
6171 		flags |= IDEV_MAPPED_GAMEPORTSCUSTOM2;
6172 	if (flag & ID_FLAG_QUALIFIER_MASK)
6173 		flags |= flag & ID_FLAG_QUALIFIER_MASK;
6174 	if (pflags)
6175 		*pflags = flags;
6176 	if (pport)
6177 		*pport = port;
6178 	if (!data)
6179 		return 0;
6180 	if (events[data].allow_mask & AM_AF)
6181 		flags |= IDEV_MAPPED_AUTOFIRE_POSSIBLE;
6182 	if (pflags)
6183 		*pflags = flags;
6184 	inputdevice_get_eventname (&events[data], name);
6185 	return data;
6186 }
6187 
6188 // set event name/custom/flags to devnum/num/sub
inputdevice_set_mapping(int devnum,int num,const TCHAR * name,TCHAR * custom,uae_u64 flags,int port,int sub)6189 int inputdevice_set_mapping (int devnum, int num, const TCHAR *name, TCHAR *custom, uae_u64 flags, int port, int sub)
6190 {
6191 	const struct inputdevice_functions *idf = getidf (devnum);
6192 	const struct uae_input_device *uid = get_uid (idf, inputdevice_get_device_index (devnum));
6193 	int eid, data, portp, amask;
6194 	uae_u64 flag;
6195 	TCHAR ename[256];
6196 	int devindex = inputdevice_get_device_index (devnum);
6197 	TCHAR *customp = NULL;
6198 
6199 	if (uid == 0 || num < 0)
6200 		return 0;
6201 	if (name) {
6202 		eid = 1;
6203 		while (events[eid].name) {
6204 			inputdevice_get_eventname (&events[eid], ename);
6205 			if (!_tcscmp(ename, name))
6206 				break;
6207 			eid++;
6208 		}
6209 		if (!events[eid].name)
6210 			return 0;
6211 		if (events[eid].allow_mask & AM_INFO)
6212 			return 0;
6213 	} else {
6214 		eid = 0;
6215 	}
6216 	if (get_event_data (idf, devindex, num, &data, &customp, &flag, &portp, sub) < 0)
6217 		return 0;
6218 	if (data >= 0) {
6219 		amask = events[eid].allow_mask;
6220 		flag &= ~(ID_FLAG_AUTOFIRE_MASK | ID_FLAG_GAMEPORTSCUSTOM_MASK | IDEV_MAPPED_QUALIFIER_MASK | ID_FLAG_INVERT);
6221 		if (amask & AM_AF) {
6222 			flag |= (flags & IDEV_MAPPED_AUTOFIRE_SET) ? ID_FLAG_AUTOFIRE : 0;
6223 			flag |= (flags & IDEV_MAPPED_TOGGLE) ? ID_FLAG_TOGGLE : 0;
6224 			flag |= (flags & IDEV_MAPPED_INVERTTOGGLE) ? ID_FLAG_INVERTTOGGLE : 0;
6225 		}
6226 		flag |= (flags & IDEV_MAPPED_INVERT) ? ID_FLAG_INVERT : 0;
6227 		flag |= (flags & IDEV_MAPPED_GAMEPORTSCUSTOM1) ? ID_FLAG_GAMEPORTSCUSTOM1 : 0;
6228 		flag |= (flags & IDEV_MAPPED_GAMEPORTSCUSTOM2) ? ID_FLAG_GAMEPORTSCUSTOM2 : 0;
6229 		flag |= flags & IDEV_MAPPED_QUALIFIER_MASK;
6230 		if (port >= 0)
6231 			portp = port;
6232 		put_event_data (idf, devindex, num, eid, custom, flag, portp, sub);
6233 		return 1;
6234 	}
6235 	return 0;
6236 }
6237 
inputdevice_get_widget_type(int devnum,int num,TCHAR * name)6238 int inputdevice_get_widget_type (int devnum, int num, TCHAR *name)
6239 {
6240 	const struct inputdevice_functions *idf = getidf (devnum);
6241 	return idf->get_widget_type (inputdevice_get_device_index (devnum), num, name, 0);
6242 }
6243 
6244 static int config_change;
6245 
inputdevice_config_change(void)6246 void inputdevice_config_change (void)
6247 {
6248 	config_change = 1;
6249 }
6250 
inputdevice_config_change_test(void)6251 int inputdevice_config_change_test (void)
6252 {
6253 	int v = config_change;
6254 	config_change = 0;
6255 	return v;
6256 }
6257 
6258 // copy configuration #src to configuration #dst
inputdevice_copyconfig(const struct uae_prefs * src,struct uae_prefs * dst)6259 void inputdevice_copyconfig (const struct uae_prefs *src, struct uae_prefs *dst)
6260 {
6261 	int i, j;
6262 
6263 	dst->input_selected_setting = src->input_selected_setting;
6264 	dst->input_joymouse_multiplier = src->input_joymouse_multiplier;
6265 	dst->input_joymouse_deadzone = src->input_joymouse_deadzone;
6266 	dst->input_joystick_deadzone = src->input_joystick_deadzone;
6267 	dst->input_joymouse_speed = src->input_joymouse_speed;
6268 	dst->input_mouse_speed = src->input_mouse_speed;
6269 	dst->input_autofire_linecnt = src->input_autofire_linecnt;
6270 	copyjport (src, dst, 0);
6271 	copyjport (src, dst, 1);
6272 	copyjport (src, dst, 2);
6273 	copyjport (src, dst, 3);
6274 
6275 	for (i = 0; i < MAX_INPUT_SETTINGS; i++) {
6276 		for (j = 0; j < MAX_INPUT_DEVICES; j++) {
6277 			memcpy (&dst->joystick_settings[i][j], &src->joystick_settings[i][j], sizeof (struct uae_input_device));
6278 			memcpy (&dst->mouse_settings[i][j], &src->mouse_settings[i][j], sizeof (struct uae_input_device));
6279 			memcpy (&dst->keyboard_settings[i][j], &src->keyboard_settings[i][j], sizeof (struct uae_input_device));
6280 		}
6281 	}
6282 
6283 	inputdevice_updateconfig (src, dst);
6284 }
6285 
swapevent(struct uae_input_device * uid,int i,int j,int evt)6286 static void swapevent (struct uae_input_device *uid, int i, int j, int evt)
6287 {
6288 	uid->eventid[i][j] = evt;
6289 	int port = uid->port[i][j];
6290 	if (port == 1)
6291 		port = 2;
6292 	else if (port == 2)
6293 		port = 1;
6294 	else if (port == 3)
6295 		port = 4;
6296 	else if (port == 4)
6297 		port = 3;
6298 	uid->port[i][j] = port;
6299 }
6300 
swapjoydevice(struct uae_input_device * uid,int ** swaps)6301 static void swapjoydevice (struct uae_input_device *uid, int **swaps)
6302 {
6303 	for (int i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++) {
6304 		for (int j = 0; j < MAX_INPUT_SUB_EVENT; j++) {
6305 			bool found = false;
6306 			for (int k = 0; k < 2 && !found; k++) {
6307 				int evtnum;
6308 				for (int kk = 0; (evtnum = swaps[k][kk]) >= 0 && !found; kk++) {
6309 					if (uid->eventid[i][j] == evtnum) {
6310 						swapevent (uid, i, j, swaps[1 - k][kk]);
6311 						found = true;
6312 					} else {
6313 						for (int jj = 0; axistable[jj] >= 0; jj += 3) {
6314 							if (evtnum == axistable[jj] || evtnum == axistable[jj + 1] || evtnum == axistable[jj + 2]) {
6315 								for (int ii = 0; ii < 3; ii++) {
6316 									if (uid->eventid[i][j] == axistable[jj + ii]) {
6317 										int evtnum2 = swaps[1 - k][kk];
6318 										for (int m = 0; axistable[m] >= 0; m += 3) {
6319 											if (evtnum2 == axistable[m] || evtnum2 == axistable[m + 1] || evtnum2 == axistable[m + 2]) {
6320 												swapevent (uid, i, j, axistable[m + ii]);
6321 												found = true;
6322 											}
6323 										}
6324 									}
6325 								}
6326 							}
6327 						}
6328 					}
6329 				}
6330 			}
6331 		}
6332 	}
6333 }
6334 
6335 // swap gameports ports, remember to handle customized ports too
inputdevice_swap_compa_ports(struct uae_prefs * prefs,int portswap)6336 void inputdevice_swap_compa_ports (struct uae_prefs *prefs, int portswap)
6337 {
6338 	struct jport tmp;
6339 	if ((prefs->jports[portswap].id == JPORT_CUSTOM || prefs->jports[portswap + 1].id == JPORT_CUSTOM)) {
6340 		int *swaps[2];
6341 		swaps[0] = rem_ports[portswap];
6342 		swaps[1] = rem_ports[portswap + 1];
6343 		for (int l = 0; l < MAX_INPUT_DEVICES; l++) {
6344 			swapjoydevice (&prefs->joystick_settings[GAMEPORT_INPUT_SETTINGS][l], swaps);
6345 			swapjoydevice (&prefs->mouse_settings[GAMEPORT_INPUT_SETTINGS][l], swaps);
6346 			swapjoydevice (&prefs->keyboard_settings[GAMEPORT_INPUT_SETTINGS][l], swaps);
6347 		}
6348 	}
6349 	memcpy (&tmp, &prefs->jports[portswap], sizeof (struct jport));
6350 	memcpy (&prefs->jports[portswap], &prefs->jports[portswap + 1], sizeof (struct jport));
6351 	memcpy (&prefs->jports[portswap + 1], &tmp, sizeof (struct jport));
6352 	inputdevice_updateconfig (NULL, prefs);
6353 }
6354 
6355 // swap device "devnum" ports 0<>1 and 2<>3
inputdevice_swap_ports(struct uae_prefs * p,int devnum)6356 void inputdevice_swap_ports (struct uae_prefs *p, int devnum)
6357 {
6358 	const struct inputdevice_functions *idf = getidf (devnum);
6359 	struct uae_input_device *uid = get_uid (idf, inputdevice_get_device_index (devnum));
6360 	int i, j, k, event;
6361 /* REMOVEME:
6362  * nowhere used
6363  */
6364 #if 0
6365 	int unit;
6366 #endif
6367 	const struct inputevent *ie, *ie2;
6368 
6369 	for (i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++) {
6370 		for (j = 0; j < MAX_INPUT_SUB_EVENT; j++) {
6371 			event = uid->eventid[i][j];
6372 			if (event <= 0)
6373 				continue;
6374 			ie = &events[event];
6375 			if (ie->unit <= 0)
6376 				continue;
6377 /* REMOVEME:
6378  * nowhere used
6379  */
6380 #if 0
6381 			unit = ie->unit;
6382 #endif
6383 			k = 1;
6384 			while (events[k].confname) {
6385 				ie2 = &events[k];
6386 				if (ie2->type == ie->type && ie2->data == ie->data && ie2->unit - 1 == ((ie->unit - 1) ^ 1) &&
6387 					ie2->allow_mask == ie->allow_mask && uid->port[i][j] == 0) {
6388 					uid->eventid[i][j] = k;
6389 					break;
6390 				}
6391 				k++;
6392 			}
6393 		}
6394 	}
6395 }
6396 
6397 //memcpy (p->joystick_settings[dst], p->joystick_settings[src], sizeof (struct uae_input_device) * MAX_INPUT_DEVICES);
copydev(struct uae_input_device * dst,struct uae_input_device * src,int selectedwidget)6398 static void copydev (struct uae_input_device *dst, struct uae_input_device *src, int selectedwidget)
6399 {
6400 	for (int i = 0; i < MAX_INPUT_DEVICES; i++) {
6401 		for (int j = 0; j < MAX_INPUT_DEVICE_EVENTS; j++) {
6402 			if (j == selectedwidget || selectedwidget < 0) {
6403 				for (int k = 0; k < MAX_INPUT_SUB_EVENT_ALL; k++) {
6404 					xfree (dst[i].custom[j][k]);
6405 				}
6406 			}
6407 		}
6408 		if (selectedwidget < 0) {
6409 			xfree (dst[i].configname);
6410 			xfree (dst[i].name);
6411 		}
6412 	}
6413 	if (selectedwidget < 0) {
6414 		memcpy (dst, src, sizeof (struct uae_input_device) * MAX_INPUT_DEVICES);
6415 	} else {
6416 		int j = selectedwidget;
6417 		for (int i = 0; i < MAX_INPUT_DEVICES; i++) {
6418 			for (int k = 0; k < MAX_INPUT_SUB_EVENT_ALL; k++) {
6419 				dst[i].eventid[j][k] = src[i].eventid[j][k];
6420 				dst[i].custom[j][k] = src[i].custom[j][k];
6421 				dst[i].flags[j][k] = src[i].flags[j][k];
6422 				dst[i].port[j][k] = src[i].port[j][k];
6423 			}
6424 			dst[i].extra[j] = src[i].extra[j];
6425 		}
6426 	}
6427 	for (int i = 0; i < MAX_INPUT_DEVICES; i++) {
6428 		for (int j = 0; j < MAX_INPUT_DEVICE_EVENTS; j++) {
6429 			if (j == selectedwidget || selectedwidget < 0) {
6430 				for (int k = 0; k < MAX_INPUT_SUB_EVENT_ALL; k++) {
6431 					if (dst[i].custom)
6432 						dst[i].custom[j][k] = my_strdup (dst[i].custom[j][k]);
6433 				}
6434 			}
6435 		}
6436 		if (selectedwidget < 0) {
6437 			dst[i].configname = my_strdup (dst[i].configname);
6438 			dst[i].name = my_strdup (dst[i].name);
6439 		}
6440 	}
6441 }
6442 
6443 // copy whole configuration #x-slot to another
6444 // +1 = default
6445 // +2 = default (pc keyboard)
inputdevice_copy_single_config(struct uae_prefs * p,int src,int dst,int devnum,int selectedwidget)6446 void inputdevice_copy_single_config (struct uae_prefs *p, int src, int dst, int devnum, int selectedwidget)
6447 {
6448 	if (selectedwidget >= 0) {
6449 		if (devnum < 0)
6450 			return;
6451 		if (gettype (devnum) != IDTYPE_KEYBOARD)
6452 			return;
6453 	}
6454 	if (src >= MAX_INPUT_SETTINGS) {
6455 		if (gettype (devnum) == IDTYPE_KEYBOARD) {
6456 			p->input_keyboard_type = src > MAX_INPUT_SETTINGS ? 1 : 0;
6457 			keyboard_default = keyboard_default_table[p->input_keyboard_type];
6458 			inputdevice_default_kb (p, dst);
6459 		}
6460 	}
6461 	if (src == dst)
6462 		return;
6463 	if (src < MAX_INPUT_SETTINGS) {
6464 	if (devnum < 0 || gettype (devnum) == IDTYPE_JOYSTICK)
6465 			copydev (p->joystick_settings[dst], p->joystick_settings[src], selectedwidget);
6466 	if (devnum < 0 || gettype (devnum) == IDTYPE_MOUSE)
6467 			copydev (p->mouse_settings[dst], p->mouse_settings[src], selectedwidget);
6468 	if (devnum < 0 || gettype (devnum) == IDTYPE_KEYBOARD)
6469 			copydev (p->keyboard_settings[dst], p->keyboard_settings[src], selectedwidget);
6470 	}
6471 }
6472 
inputdevice_acquire(int allmode)6473 void inputdevice_acquire (int allmode)
6474 {
6475 	int i;
6476 
6477 	for (i = 0; i < MAX_INPUT_DEVICES; i++)
6478 		idev[IDTYPE_JOYSTICK].unacquire (i);
6479 	for (i = 0; i < MAX_INPUT_DEVICES; i++)
6480 		idev[IDTYPE_MOUSE].unacquire (i);
6481 	for (i = 0; i < MAX_INPUT_DEVICES; i++)
6482 		idev[IDTYPE_KEYBOARD].unacquire (i);
6483 
6484 	for (i = 0; i < MAX_INPUT_DEVICES; i++) {
6485 		if ((use_joysticks[i] && allmode >= 0) || (allmode && !idev[IDTYPE_JOYSTICK].get_flags (i)))
6486 			idev[IDTYPE_JOYSTICK].acquire (i, 0);
6487 	}
6488 	for (i = 0; i < MAX_INPUT_DEVICES; i++) {
6489 		if ((use_mice[i] && allmode >= 0) || (allmode && !idev[IDTYPE_MOUSE].get_flags (i)))
6490 			idev[IDTYPE_MOUSE].acquire (i, allmode < 0);
6491 	}
6492 	for (i = 0; i < MAX_INPUT_DEVICES; i++) {
6493 		if ((use_keyboards[i] && allmode >= 0) || (allmode <  0 && !idev[IDTYPE_KEYBOARD].get_flags (i)))
6494 			idev[IDTYPE_KEYBOARD].acquire (i, allmode < 0);
6495 	}
6496 
6497 	if (input_acquired)
6498 		return;
6499 
6500 	idev[IDTYPE_JOYSTICK].acquire (-1, 0);
6501 	idev[IDTYPE_MOUSE].acquire (-1, 0);
6502 	idev[IDTYPE_KEYBOARD].acquire (-1, 0);
6503 	//    if (!input_acquired)
6504 	//	write_log (_T("input devices acquired (%s)\n"), allmode ? "all" : "selected only");
6505 	input_acquired = 1;
6506 }
6507 
inputdevice_unacquire(void)6508 void inputdevice_unacquire (void)
6509 {
6510 	int i;
6511 
6512 	for (i = 0; i < MAX_INPUT_DEVICES; i++)
6513 		idev[IDTYPE_JOYSTICK].unacquire (i);
6514 	for (i = 0; i < MAX_INPUT_DEVICES; i++)
6515 		idev[IDTYPE_MOUSE].unacquire (i);
6516 	for (i = 0; i < MAX_INPUT_DEVICES; i++)
6517 		idev[IDTYPE_KEYBOARD].unacquire (i);
6518 
6519 	if (!input_acquired)
6520 		return;
6521 
6522 	input_acquired = 0;
6523 	idev[IDTYPE_JOYSTICK].unacquire (-1);
6524 	idev[IDTYPE_MOUSE].unacquire (-1);
6525 	idev[IDTYPE_KEYBOARD].unacquire (-1);
6526 }
6527 
inputdevice_testrecord(int type,int num,int wtype,int wnum,int state,int max)6528 void inputdevice_testrecord (int type, int num, int wtype, int wnum, int state, int max)
6529 {
6530 	if (wnum < 0) {
6531 		testmode = -1;
6532 		return;
6533 	}
6534 	if (testmode_count >= TESTMODE_MAX)
6535 		return;
6536 	if (type == IDTYPE_KEYBOARD) {
6537 		if (wnum >= 0x100) {
6538 			wnum = 0x100 - wnum;
6539 		} else {
6540 			struct uae_input_device *na = &keyboards[num];
6541 			int j = 0;
6542 			while (j < MAX_INPUT_DEVICE_EVENTS && na->extra[j] >= 0) {
6543 				if (na->extra[j] == wnum) {
6544 					wnum = j;
6545 					break;
6546 				}
6547 				j++;
6548 			}
6549 			if (j >= MAX_INPUT_DEVICE_EVENTS || na->extra[j] < 0)
6550 				return;
6551 		}
6552 	}
6553 	// wait until previous event is released before accepting new ones
6554 	for (int i = 0; i < TESTMODE_MAX; i++) {
6555 		struct teststore *ts2 = &testmode_wait[i];
6556 		if (ts2->testmode_num < 0)
6557 			continue;
6558 		if (ts2->testmode_num != num || ts2->testmode_type != type || ts2->testmode_wtype != wtype || ts2->testmode_wnum != wnum)
6559 			continue;
6560 		if (max <= 0) {
6561 			if (state)
6562 				continue;
6563 		} else {
6564 			if (state < -(max / 2) || state > (max / 2))
6565 				continue;
6566 		}
6567 		ts2->testmode_num = -1;
6568 	}
6569 	if (max <= 0) {
6570 		if (!state)
6571 			return;
6572 	} else {
6573 		if (state >= -(max / 2) && state <= (max / 2))
6574 			return;
6575 	}
6576 
6577 	//write_log (_T("%d %d %d %d %d/%d\n"), type, num, wtype, wnum, state, max);
6578 	struct teststore *ts = &testmode_data[testmode_count];
6579 	ts->testmode_type = type;
6580 	ts->testmode_num = num;
6581 	ts->testmode_wtype = wtype;
6582 	ts->testmode_wnum = wnum;
6583 	ts->testmode_state = state;
6584 	ts->testmode_max = max;
6585 	testmode_count++;
6586 }
6587 
inputdevice_istest(void)6588 int inputdevice_istest (void)
6589 {
6590 	return testmode;
6591 }
inputdevice_settest(int set)6592 void inputdevice_settest (int set)
6593 {
6594 	testmode = set;
6595 	testmode_count = 0;
6596 	testmode_wait[0].testmode_num = -1;
6597 	testmode_wait[1].testmode_num = -1;
6598 }
6599 
inputdevice_testread_count(void)6600 int inputdevice_testread_count (void)
6601 {
6602 	inputdevice_read ();
6603 	if (testmode != 1) {
6604 		testmode = 0;
6605 		return -1;
6606 	}
6607 	return testmode_count;
6608 }
6609 
inputdevice_testread(int * devnum,int * wtype,int * state,bool doread)6610 int inputdevice_testread (int *devnum, int *wtype, int *state, bool doread)
6611 {
6612 	if (doread) {
6613 		inputdevice_read ();
6614 		if (testmode != 1) {
6615 			testmode = 0;
6616 			return -1;
6617 		}
6618 	}
6619 	if (testmode_count > 0) {
6620 		testmode_count--;
6621 		struct teststore *ts = &testmode_data[testmode_count];
6622 		*devnum = getdevnum (ts->testmode_type, ts->testmode_num);
6623 		if (ts->testmode_wnum >= 0 && ts->testmode_wnum < MAX_INPUT_DEVICE_EVENTS)
6624 			*wtype = idev[ts->testmode_type].get_widget_first (ts->testmode_num, ts->testmode_wtype) + ts->testmode_wnum;
6625 		else
6626 			*wtype = ts->testmode_wnum;
6627 		*state = ts->testmode_state;
6628 		if (ts->testmode_state)
6629 			memcpy (&testmode_wait[testmode_count], ts, sizeof (struct teststore));
6630 		return 1;
6631 	}
6632 	return 0;
6633 }
6634 
6635 /* Call this function when host machine's joystick/joypad/etc button state changes
6636  * This function translates button events to Amiga joybutton/joyaxis/keyboard events
6637  */
6638 
6639 /* button states:
6640  * state = -1 -> mouse wheel turned or similar (button without release)
6641  * state = 1 -> button pressed
6642  * state = 0 -> button released
6643  */
6644 
setjoybuttonstate(int joy,int button,int state)6645 void setjoybuttonstate (int joy, int button, int state)
6646 {
6647 	if (testmode) {
6648 		inputdevice_testrecord (IDTYPE_JOYSTICK, joy, IDEV_WIDGET_BUTTON, button, state, -1);
6649 		if (state < 0)
6650 			inputdevice_testrecord (IDTYPE_JOYSTICK, joy, IDEV_WIDGET_BUTTON, button, 0, -1);
6651 		return;
6652 	}
6653 #if 0
6654 	if (ignoreoldinput (joy)) {
6655 		if (state)
6656 			switchdevice (&joysticks[joy], button, 1);
6657 		return;
6658 	}
6659 #endif
6660 	setbuttonstateall (&joysticks[joy], &joysticks2[joy], button, state ? 1 : 0);
6661 }
6662 
6663 /* buttonmask = 1 = normal toggle button, 0 = mouse wheel turn or similar
6664  */
setjoybuttonstateall(int joy,uae_u32 buttonbits,uae_u32 buttonmask)6665 void setjoybuttonstateall (int joy, uae_u32 buttonbits, uae_u32 buttonmask)
6666 {
6667 	int i;
6668 
6669 #if 0
6670 	if (ignoreoldinput (joy))
6671 		return;
6672 #endif
6673 	for (i = 0; i < ID_BUTTON_TOTAL; i++) {
6674 		if (buttonmask & (1 << i))
6675 			setbuttonstateall (&joysticks[joy], &joysticks2[joy], i, (buttonbits & (1 << i)) ? 1 : 0);
6676 		else if (buttonbits & (1 << i))
6677 			setbuttonstateall (&joysticks[joy], &joysticks2[joy], i, -1);
6678 	}
6679 }
6680 /* mouse buttons (just like joystick buttons)
6681  */
setmousebuttonstateall(int mouse,uae_u32 buttonbits,uae_u32 buttonmask)6682 void setmousebuttonstateall (int mouse, uae_u32 buttonbits, uae_u32 buttonmask)
6683 {
6684 	int i;
6685 	uae_u32 obuttonmask = mice2[mouse].buttonmask;
6686 
6687 	for (i = 0; i < ID_BUTTON_TOTAL; i++) {
6688 		if (buttonmask & (1 << i))
6689 			setbuttonstateall (&mice[mouse], &mice2[mouse], i, (buttonbits & (1 << i)) ? 1 : 0);
6690 		else if (buttonbits & (1 << i))
6691 			setbuttonstateall (&mice[mouse], &mice2[mouse], i, -1);
6692 	}
6693 	if (obuttonmask != mice2[mouse].buttonmask)
6694 		mousehack_helper (mice2[mouse].buttonmask);
6695 }
6696 
setmousebuttonstate(int mouse,int button,int state)6697 void setmousebuttonstate (int mouse, int button, int state)
6698 {
6699 	uae_u32 obuttonmask = mice2[mouse].buttonmask;
6700 	if (testmode) {
6701 		inputdevice_testrecord (IDTYPE_MOUSE, mouse, IDEV_WIDGET_BUTTON, button, state, -1);
6702 		return;
6703 	}
6704 	setbuttonstateall (&mice[mouse], &mice2[mouse], button, state);
6705 	if (obuttonmask != mice2[mouse].buttonmask)
6706 		mousehack_helper (mice2[mouse].buttonmask);
6707 }
6708 
6709 /* same for joystick axis (analog or digital)
6710  * (0 = center, -max = full left/top, max = full right/bottom)
6711  */
setjoystickstate(int joy,int axis,int state,int max)6712 void setjoystickstate (int joy, int axis, int state, int max)
6713 {
6714 	struct uae_input_device *id = &joysticks[joy];
6715 	struct uae_input_device2 *id2 = &joysticks2[joy];
6716 	int deadzone = currprefs.input_joymouse_deadzone * max / 100;
6717 	int i, v1, v2;
6718 
6719 	if (testmode) {
6720 		inputdevice_testrecord (IDTYPE_JOYSTICK, joy, IDEV_WIDGET_AXIS, axis, state, max);
6721 		return;
6722 	}
6723 	v1 = state;
6724 	v2 = id2->states[axis][MAX_INPUT_SUB_EVENT];
6725 
6726 	//write_log (_T("new=%d old=%d axis=%d state=%d max=%d\n"), v1, v2, axis, state, max);
6727 
6728 	if (v1 < deadzone && v1 > -deadzone)
6729 		v1 = 0;
6730 	if (v2 < deadzone && v2 > -deadzone)
6731 		v2 = 0;
6732 	if (input_play && state) {
6733 		if (v1 != v2)
6734 			inprec_realtimev ();
6735 	}
6736 	if (input_play)
6737 		return;
6738 	if (!joysticks[joy].enabled) {
6739 		if (v1 && v1 != v2)
6740 			switchdevice (&joysticks[joy], axis * 2 + (v1 < 0 ? 0 : 1), false);
6741 		return;
6742 	}
6743 	for (i = 0; i < MAX_INPUT_SUB_EVENT; i++) {
6744 		uae_u64 flags = id->flags[ID_AXIS_OFFSET + axis][i];
6745 		if (flags & ID_FLAG_INVERT)
6746 			state = -state;
6747 		if (state != id2->states[axis][i]) {
6748 			//write_log(_T("-> %d %d\n"), i, state);
6749 		handle_input_event (id->eventid[ID_AXIS_OFFSET + axis][i], state, max, flags & ID_FLAG_AUTOFIRE, true, false);
6750 			id2->states[axis][i] = state;
6751 		}
6752 	}
6753 	id2->states[axis][MAX_INPUT_SUB_EVENT] = v1;
6754 }
getjoystickstate(int joy)6755 int getjoystickstate (int joy)
6756 {
6757 	if (testmode)
6758 		return 1;
6759 	return joysticks[joy].enabled;
6760 }
6761 
setmousestate(int mouse,int axis,int data,int isabs)6762 void setmousestate (int mouse, int axis, int data, int isabs)
6763 {
6764 	int i, v, diff;
6765 	int *mouse_p, *oldm_p;
6766 	float d;
6767 	struct uae_input_device *id = &mice[mouse];
6768 	static float fract[MAX_INPUT_DEVICES][MAX_INPUT_DEVICE_EVENTS];
6769 
6770 	if (testmode) {
6771 		inputdevice_testrecord (IDTYPE_MOUSE, mouse, IDEV_WIDGET_AXIS, axis, data, -1);
6772 		// fake "release" event
6773 		inputdevice_testrecord (IDTYPE_MOUSE, mouse, IDEV_WIDGET_AXIS, axis, 0, -1);
6774 		return;
6775 	}
6776 	if (input_play)
6777 		return;
6778 	if (!mice[mouse].enabled) {
6779 		if (isabs && currprefs.input_tablet > 0) {
6780 			if (axis == 0)
6781 				lastmx = data;
6782 			else
6783 				lastmy = data;
6784 			if (axis)
6785 				mousehack_helper (mice2[mouse].buttonmask);
6786 		}
6787 		return;
6788 	}
6789 	d = 0;
6790 	mouse_p = &mouse_axis[mouse][axis];
6791 	oldm_p = &oldm_axis[mouse][axis];
6792 	if (!isabs) {
6793 		// eat relative movements while in mousehack mode
6794 /*		if (currprefs.input_tablet == TABLET_MOUSEHACK && mousehack_alive ())
6795 			return;*/
6796 		*oldm_p = *mouse_p;
6797 		*mouse_p += data;
6798 		d = (*mouse_p - *oldm_p) * currprefs.input_mouse_speed / 100.0f;
6799 	} else {
6800 		d = data - *oldm_p;
6801 		*oldm_p = data;
6802 		*mouse_p += d;
6803 		if (axis == 0)
6804 			lastmx = data;
6805 		else
6806 			lastmy = data;
6807 		if (axis)
6808 			mousehack_helper (mice2[mouse].buttonmask);
6809 		if (currprefs.input_tablet == TABLET_MOUSEHACK && mousehack_alive ())
6810 			return;
6811 	}
6812 	v = (int)d;
6813 	fract[mouse][axis] += d - v;
6814 	diff = (int)fract[mouse][axis];
6815 	v += diff;
6816 	fract[mouse][axis] -= diff;
6817 	for (i = 0; i < MAX_INPUT_SUB_EVENT; i++) {
6818 		uae_u64 flags = id->flags[ID_AXIS_OFFSET + axis][i];
6819 		if (!isabs && (flags & ID_FLAG_INVERT))
6820 			v = -v;
6821 		handle_input_event (id->eventid[ID_AXIS_OFFSET + axis][i], v, 0, 0, true, false);
6822 	}
6823 }
6824 
getmousestate(int joy)6825 int getmousestate (int joy)
6826 {
6827 	if (testmode)
6828 		return 1;
6829 	return mice[joy].enabled;
6830 }
6831 
warpmode(int mode)6832 void warpmode (int mode)
6833 {
6834 	int fr, fr2;
6835 
6836 	fr = currprefs.gfx_framerate;
6837 	if (fr == 0)
6838 		fr = -1;
6839 	fr2 = currprefs.turbo_emulation;
6840 	if (fr2 == -1)
6841 		fr2 = 0;
6842 
6843 	if (mode < 0) {
6844 		if (currprefs.turbo_emulation) {
6845 			changed_prefs.gfx_framerate = currprefs.gfx_framerate = fr2;
6846 			currprefs.turbo_emulation = 0;
6847 		} else {
6848 			currprefs.turbo_emulation = fr;
6849 		}
6850 	} else if (mode == 0 && currprefs.turbo_emulation) {
6851 		if (currprefs.turbo_emulation > 0)
6852 			changed_prefs.gfx_framerate = currprefs.gfx_framerate = fr2;
6853 		currprefs.turbo_emulation = 0;
6854 	} else if (mode > 0 && !currprefs.turbo_emulation) {
6855 		currprefs.turbo_emulation = fr;
6856 	}
6857 	if (currprefs.turbo_emulation) {
6858 		if (!currprefs.cpu_cycle_exact && !currprefs.blitter_cycle_exact)
6859 			changed_prefs.gfx_framerate = currprefs.gfx_framerate = 10;
6860 		pause_sound ();
6861 	} else {
6862 		resume_sound ();
6863 	}
6864 	compute_vsynctime ();
6865 #ifdef RETROPLATFORM
6866 	rp_turbo_cpu (currprefs.turbo_emulation);
6867 #endif
6868 	changed_prefs.turbo_emulation = currprefs.turbo_emulation;
6869 	config_changed = 1;
6870 	setsystime ();
6871 }
6872 
pausemode(int mode)6873 void pausemode (int mode)
6874 {
6875 	if (mode < 0)
6876 		pause_emulation = pause_emulation ? 0 : 9;
6877 	else
6878 		pause_emulation = mode;
6879 	config_changed = 1;
6880 	setsystime ();
6881 }
6882 
jsem_isjoy(int port,const struct uae_prefs * p)6883 int jsem_isjoy (int port, const struct uae_prefs *p)
6884 {
6885 	int v = JSEM_DECODEVAL (port, p);
6886 	if (v < JSEM_JOYS)
6887 		return -1;
6888 	v -= JSEM_JOYS;
6889 	if (v >= inputdevice_get_device_total (IDTYPE_JOYSTICK))
6890 		return -1;
6891 	return v;
6892 }
6893 
jsem_ismouse(int port,const struct uae_prefs * p)6894 int jsem_ismouse (int port, const struct uae_prefs *p)
6895 {
6896 	int v = JSEM_DECODEVAL (port, p);
6897 	if (v < JSEM_MICE)
6898 		return -1;
6899 	v -= JSEM_MICE;
6900 	if (v >= inputdevice_get_device_total (IDTYPE_MOUSE))
6901 		return -1;
6902 	return v;
6903 }
6904 
jsem_iskbdjoy(int port,const struct uae_prefs * p)6905 int jsem_iskbdjoy (int port, const struct uae_prefs *p)
6906 {
6907 	int v = JSEM_DECODEVAL (port, p);
6908 	if (v < JSEM_KBDLAYOUT)
6909 		return -1;
6910 	v -= JSEM_KBDLAYOUT;
6911 	if (v >= JSEM_LASTKBD)
6912 		return -1;
6913 	return v;
6914 }
6915 
inputdevice_joyport_config(struct uae_prefs * p,const TCHAR * value,int portnum,int mode,int type)6916 int inputdevice_joyport_config (struct uae_prefs *p, const TCHAR *value, int portnum, int mode, int type)
6917 {
6918 	switch (type)
6919 	{
6920 	case 1:
6921 	case 2:
6922 		{
6923 			int i, j;
6924 			for (j = 0; j < MAX_JPORTS; j++) {
6925 				struct inputdevice_functions *idf;
6926 				int type = IDTYPE_MOUSE;
6927 				int idnum = JSEM_MICE;
6928 				if (j > 0) {
6929 					type = IDTYPE_JOYSTICK;
6930 					idnum = JSEM_JOYS;
6931 				}
6932 				idf = &idev[type];
6933 				for (i = 0; i < idf->get_num (); i++) {
6934 					TCHAR *name1 = idf->get_friendlyname (i);
6935 					TCHAR *name2 = idf->get_uniquename (i);
6936 					if ((name1 && !_tcscmp (name1, value)) || (name2 && !_tcscmp (name2, value))) {
6937 						p->jports[portnum].id = idnum + i;
6938 						if (mode >= 0)
6939 							p->jports[portnum].mode = mode;
6940 						config_changed = 1;
6941 						return 1;
6942 					}
6943 				}
6944 			}
6945 		}
6946 		break;
6947 	case 0:
6948 		{
6949 			int start = JPORT_NONE, got = 0, max = -1;
6950 			const TCHAR *pp = 0;
6951 			if (_tcsncmp (value, _T("kbd"), 3) == 0) {
6952 				start = JSEM_KBDLAYOUT;
6953 				pp = value + 3;
6954 				got = 1;
6955 				max = JSEM_LASTKBD;
6956 			} else if (_tcsncmp (value, _T("joy"), 3) == 0) {
6957 				start = JSEM_JOYS;
6958 				pp = value + 3;
6959 				got = 1;
6960 				max = idev[IDTYPE_JOYSTICK].get_num ();
6961 			} else if (_tcsncmp (value, _T("mouse"), 5) == 0) {
6962 				start = JSEM_MICE;
6963 				pp = value + 5;
6964 				got = 1;
6965 				max = idev[IDTYPE_MOUSE].get_num ();
6966 			} else if (_tcscmp (value, _T("none")) == 0) {
6967 				got = 2;
6968 			} else if (_tcscmp (value, _T("custom")) == 0) {
6969 				got = 2;
6970 				start = JPORT_CUSTOM;
6971 			}
6972 			if (got) {
6973 				if (pp && max != 0) {
6974 					int v = _tstol (pp);
6975 					if (start >= 0) {
6976 						if (start == JSEM_KBDLAYOUT && v > 0)
6977 							v--;
6978 						if (v >= 0) {
6979 							if (v >= max)
6980 								v = 0;
6981 							start += v;
6982 							got = 2;
6983 						}
6984 					}
6985 				}
6986 				if (got == 2) {
6987 					p->jports[portnum].id = start;
6988 					if (mode >= 0)
6989 						p->jports[portnum].mode = mode;
6990 					if (start < JSEM_JOYS)
6991 						default_keyboard_layout[portnum] = start;
6992 					config_changed = 1;
6993 					return 1;
6994 				}
6995 				// joystick not found, select default
6996 				if (start == JSEM_JOYS && p->jports[portnum].id < JSEM_JOYS) {
6997 					p->jports[portnum].id = default_keyboard_layout[portnum];
6998 					config_changed = 1;
6999 					return 1;
7000 				}
7001 			}
7002 		}
7003 		break;
7004 	}
7005 	return 0;
7006 }
7007 
inputdevice_getjoyportdevice(int port,int val)7008 int inputdevice_getjoyportdevice (int port, int val)
7009 {
7010 	int idx;
7011 	if (val == JPORT_CUSTOM) {
7012 		idx = inputdevice_get_device_total (IDTYPE_JOYSTICK) + JSEM_LASTKBD;
7013 		if (port < 2)
7014 			idx += inputdevice_get_device_total (IDTYPE_MOUSE);
7015 	} else if (val < 0) {
7016 		idx = -1;
7017 	} else if (val >= JSEM_MICE) {
7018 		idx = val - JSEM_MICE;
7019 		if (idx >= inputdevice_get_device_total (IDTYPE_MOUSE))
7020 			idx = 0;
7021 		else
7022 			idx += inputdevice_get_device_total (IDTYPE_JOYSTICK);
7023 		idx += JSEM_LASTKBD;
7024 	} else if (val >= JSEM_JOYS) {
7025 		idx = val - JSEM_JOYS;
7026 		if (idx >= inputdevice_get_device_total (IDTYPE_JOYSTICK))
7027 			idx = 0;
7028 		idx += JSEM_LASTKBD;
7029 	} else {
7030 		idx = val - JSEM_KBDLAYOUT;
7031 	}
7032 	return idx;
7033 }
7034 
7035 #ifdef SAVESTATE
7036 // for state recorder use only!
7037 
save_inputstate(int * len,uae_u8 * dstptr)7038 uae_u8 *save_inputstate (int *len, uae_u8 *dstptr)
7039 {
7040 	uae_u8 *dstbak, *dst;
7041 
7042 	if (dstptr)
7043 		dstbak = dst = dstptr;
7044 	else
7045 		dstbak = dst = xmalloc (uae_u8, 1000);
7046 	for (int i = 0; i < MAX_JPORTS; i++) {
7047 		save_u16 (joydir[i]);
7048 		save_u16 (joybutton[i]);
7049 		save_u16 (otop[i]);
7050 		save_u16 (obot[i]);
7051 		save_u16 (oleft[i]);
7052 		save_u16 (oright[i]);
7053 	}
7054 	for (int i = 0; i < NORMAL_JPORTS; i++) {
7055 		save_u16 (cd32_shifter[i]);
7056 		for (int j = 0; j < 2; j++) {
7057 			save_u16 (pot_cap[i][j]);
7058 			save_u16 (joydirpot[i][j]);
7059 		}
7060 	}
7061 	for (int i = 0; i < NORMAL_JPORTS; i++) {
7062 		for (int j = 0; j < MOUSE_AXIS_TOTAL; j++) {
7063 			save_u16 (mouse_delta[i][j]);
7064 			save_u16 (mouse_deltanoreset[i][j]);
7065 		}
7066 		save_u16 (mouse_frame_x[i]);
7067 		save_u16 (mouse_frame_y[i]);
7068 	}
7069 	*len = dst - dstbak;
7070 	return dstbak;
7071 }
7072 
restore_inputstate(uae_u8 * src)7073 uae_u8 *restore_inputstate (uae_u8 *src)
7074 {
7075 	for (int i = 0; i < MAX_JPORTS; i++) {
7076 		joydir[i] = restore_u16 ();
7077 		joybutton[i] = restore_u16 ();
7078 		otop[i] = restore_u16 ();
7079 		obot[i] = restore_u16 ();
7080 		oleft[i] = restore_u16 ();
7081 		oright[i] = restore_u16 ();
7082 	}
7083 	for (int i = 0; i < NORMAL_JPORTS; i++) {
7084 		cd32_shifter[i] = restore_u16 ();
7085 		for (int j = 0; j < 2; j++) {
7086 			pot_cap[i][j] = restore_u16 ();
7087 			joydirpot[i][j] = restore_u16 ();
7088 		}
7089 	}
7090 	for (int i = 0; i < NORMAL_JPORTS; i++) {
7091 		for (int j = 0; j < MOUSE_AXIS_TOTAL; j++) {
7092 			mouse_delta[i][j] = restore_u16 ();
7093 			mouse_deltanoreset[i][j] = restore_u16 ();
7094 		}
7095 		mouse_frame_x[i] = restore_u16 ();
7096 		mouse_frame_y[i] = restore_u16 ();
7097 	}
7098 	return src;
7099 }
7100 
clear_inputstate(void)7101 void clear_inputstate (void)
7102 {
7103 	return;
7104 	for (int i = 0; i < MAX_JPORTS; i++) {
7105 		horizclear[i] = 1;
7106 		vertclear[i] = 1;
7107 	}
7108 }
7109 #endif
7110