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