mirror of
https://github.com/LIV2/WinUAE.git
synced 2025-12-06 00:12:52 +00:00
6603 lines
174 KiB
C++
6603 lines
174 KiB
C++
/*
|
|
* UAE - The Un*x Amiga Emulator
|
|
*
|
|
* joystick/mouse emulation
|
|
*
|
|
* Copyright 2001-2012 Toni Wilen
|
|
*
|
|
* new fetures:
|
|
* - very configurable (and very complex to configure :)
|
|
* - supports multiple native input devices (joysticks and mice)
|
|
* - supports mapping joystick/mouse buttons to keys and vice versa
|
|
* - joystick mouse emulation (supports both ports)
|
|
* - supports parallel port joystick adapter
|
|
* - full cd32 pad support (supports both ports)
|
|
* - fully backward compatible with old joystick/mouse configuration
|
|
*
|
|
*/
|
|
|
|
//#define DONGLE_DEBUG
|
|
|
|
#include "sysconfig.h"
|
|
#include "sysdeps.h"
|
|
|
|
#include "options.h"
|
|
#include "keyboard.h"
|
|
#include "inputdevice.h"
|
|
#include "inputrecord.h"
|
|
#include "keybuf.h"
|
|
#include "custom.h"
|
|
#include "xwin.h"
|
|
#include "drawing.h"
|
|
#include "memory.h"
|
|
#include "events.h"
|
|
#include "newcpu.h"
|
|
#include "uae.h"
|
|
#include "picasso96.h"
|
|
#include "catweasel.h"
|
|
#include "debug.h"
|
|
#include "ar.h"
|
|
#include "gui.h"
|
|
#include "disk.h"
|
|
#include "audio.h"
|
|
#include "sound.h"
|
|
#include "savestate.h"
|
|
#include "arcadia.h"
|
|
#include "zfile.h"
|
|
#include "cia.h"
|
|
#include "autoconf.h"
|
|
#ifdef RETROPLATFORM
|
|
#include "rp.h"
|
|
#endif
|
|
#include "dongle.h"
|
|
#include "cdtv.h"
|
|
|
|
extern int bootrom_header, bootrom_items;
|
|
|
|
// 01 = host events
|
|
// 02 = joystick
|
|
// 04 = cia buttons
|
|
// 16 = potgo
|
|
// 32 = vsync
|
|
|
|
int inputdevice_logging = 0;
|
|
|
|
|
|
#define ID_FLAG_CANRELEASE 0x1000
|
|
#define ID_FLAG_TOGGLED 0x2000
|
|
#define ID_FLAG_CUSTOMEVENT_TOGGLED1 0x4000
|
|
#define ID_FLAG_CUSTOMEVENT_TOGGLED2 0x8000
|
|
|
|
#define ID_FLAG_SAVE_MASK_CONFIG 0x000000ff
|
|
#define ID_FLAG_SAVE_MASK_QUALIFIERS ID_FLAG_QUALIFIER_MASK
|
|
#define ID_FLAG_SAVE_MASK_FULL (ID_FLAG_SAVE_MASK_CONFIG | ID_FLAG_SAVE_MASK_QUALIFIERS)
|
|
|
|
#define IE_INVERT 0x80
|
|
#define IE_CDTV 0x100
|
|
|
|
#define INPUTEVENT_JOY1_CD32_FIRST INPUTEVENT_JOY1_CD32_PLAY
|
|
#define INPUTEVENT_JOY2_CD32_FIRST INPUTEVENT_JOY2_CD32_PLAY
|
|
#define INPUTEVENT_JOY1_CD32_LAST INPUTEVENT_JOY1_CD32_BLUE
|
|
#define INPUTEVENT_JOY2_CD32_LAST INPUTEVENT_JOY2_CD32_BLUE
|
|
|
|
/* event masks */
|
|
#define AM_KEY 1 /* keyboard allowed */
|
|
#define AM_JOY_BUT 2 /* joystick buttons allowed */
|
|
#define AM_JOY_AXIS 4 /* joystick axis allowed */
|
|
#define AM_MOUSE_BUT 8 /* mouse buttons allowed */
|
|
#define AM_MOUSE_AXIS 16 /* mouse direction allowed */
|
|
#define AM_AF 32 /* supports autofire */
|
|
#define AM_INFO 64 /* information data for gui */
|
|
#define AM_DUMMY 128 /* placeholder */
|
|
#define AM_CUSTOM 256 /* custom event */
|
|
#define AM_K (AM_KEY|AM_JOY_BUT|AM_MOUSE_BUT|AM_AF) /* generic button/switch */
|
|
#define AM_KK (AM_KEY|AM_JOY_BUT|AM_MOUSE_BUT)
|
|
|
|
#define JOYMOUSE_CDTV 8
|
|
|
|
#define DEFEVENT(A, B, C, D, E, F) {_T(#A), B, C, D, E, F },
|
|
static struct inputevent events[] = {
|
|
{0, 0, AM_K,0,0,0},
|
|
#include "inputevents.def"
|
|
{0, 0, 0, 0, 0, 0}
|
|
};
|
|
#undef DEFEVENT
|
|
|
|
static int sublevdir[2][MAX_INPUT_SUB_EVENT];
|
|
|
|
static const int slotorder1[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
|
|
static const int slotorder2[] = { 8, 1, 2, 3, 4, 5, 6, 7 };
|
|
|
|
struct uae_input_device2 {
|
|
uae_u32 buttonmask;
|
|
int states[MAX_INPUT_DEVICE_EVENTS / 2];
|
|
};
|
|
|
|
static struct uae_input_device2 joysticks2[MAX_INPUT_DEVICES];
|
|
static struct uae_input_device2 mice2[MAX_INPUT_DEVICES];
|
|
static uae_u8 scancodeused[MAX_INPUT_DEVICES][256];
|
|
static uae_u64 qualifiers, qualifiers_r;
|
|
static uae_s16 *qualifiers_evt[MAX_INPUT_QUALIFIERS];
|
|
|
|
// fire/left mouse button pullup resistors enabled?
|
|
static bool mouse_pullup = true;
|
|
|
|
static int joymodes[MAX_JPORTS];
|
|
static int *joyinputs[MAX_JPORTS];
|
|
|
|
static int input_acquired;
|
|
static int testmode, testmode_read, testmode_toggle;
|
|
struct teststore
|
|
{
|
|
int testmode_type;
|
|
int testmode_num;
|
|
int testmode_wtype;
|
|
int testmode_wnum;
|
|
int testmode_state;
|
|
};
|
|
#define TESTMODE_MAX 2
|
|
static int testmode_count;
|
|
static struct teststore testmode_data[TESTMODE_MAX];
|
|
static struct teststore testmode_wait[TESTMODE_MAX];
|
|
|
|
static int bouncy;
|
|
static signed long bouncy_cycles;
|
|
|
|
static int handle_input_event (int nr, int state, int max, int autofire, bool canstoprecord, bool playbackevent);
|
|
|
|
static struct inputdevice_functions idev[IDTYPE_MAX];
|
|
|
|
static int isdevice (struct uae_input_device *id)
|
|
{
|
|
int i, j;
|
|
for (i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++) {
|
|
for (j = 0; j < MAX_INPUT_SUB_EVENT; j++) {
|
|
if (id->eventid[i][j] > 0)
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int inputdevice_uaelib (const TCHAR *s, const TCHAR *parm)
|
|
{
|
|
int i;
|
|
|
|
for (i = 1; events[i].name; i++) {
|
|
if (!_tcscmp (s, events[i].confname)) {
|
|
handle_input_event (i, _tstol (parm), 1, 0, false, false);
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static struct uae_input_device *joysticks;
|
|
static struct uae_input_device *mice;
|
|
static struct uae_input_device *keyboards;
|
|
static struct uae_input_device *internalevents;
|
|
static struct uae_input_device_kbr_default *keyboard_default, **keyboard_default_table;
|
|
|
|
#define KBR_DEFAULT_MAP_FIRST 0
|
|
#define KBR_DEFAULT_MAP_LAST 5
|
|
#define KBR_DEFAULT_MAP_CD32_FIRST 6
|
|
#define KBR_DEFAULT_MAP_CD32_LAST 8
|
|
|
|
#define KBR_DEFAULT_MAP_NP 0
|
|
#define KBR_DEFAULT_MAP_CK 1
|
|
#define KBR_DEFAULT_MAP_SE 2
|
|
#define KBR_DEFAULT_MAP_NP3 3
|
|
#define KBR_DEFAULT_MAP_CK3 4
|
|
#define KBR_DEFAULT_MAP_SE3 5
|
|
#define KBR_DEFAULT_MAP_CD32_NP 6
|
|
#define KBR_DEFAULT_MAP_CD32_CK 7
|
|
#define KBR_DEFAULT_MAP_CD32_SE 8
|
|
#define KBR_DEFAULT_MAP_XA1 9
|
|
#define KBR_DEFAULT_MAP_XA2 10
|
|
#define KBR_DEFAULT_MAP_ARCADIA 11
|
|
#define KBR_DEFAULT_MAP_ARCADIA_XA 12
|
|
#define KBR_DEFAULT_MAP_CDTV 13
|
|
static int **keyboard_default_kbmaps;
|
|
|
|
static int mouse_axis[MAX_INPUT_DEVICES][MAX_INPUT_DEVICE_EVENTS];
|
|
static int oldm_axis[MAX_INPUT_DEVICES][MAX_INPUT_DEVICE_EVENTS];
|
|
|
|
#define MOUSE_AXIS_TOTAL 4
|
|
|
|
static uae_s16 mouse_x[MAX_JPORTS], mouse_y[MAX_JPORTS];
|
|
static uae_s16 mouse_delta[MAX_JPORTS][MOUSE_AXIS_TOTAL];
|
|
static uae_s16 mouse_deltanoreset[MAX_JPORTS][MOUSE_AXIS_TOTAL];
|
|
static int joybutton[MAX_JPORTS];
|
|
static int joydir[MAX_JPORTS];
|
|
static int joydirpot[MAX_JPORTS][2];
|
|
static uae_s16 mouse_frame_x[MAX_JPORTS], mouse_frame_y[MAX_JPORTS];
|
|
|
|
static int mouse_port[NORMAL_JPORTS];
|
|
static int cd32_shifter[NORMAL_JPORTS];
|
|
static int cd32_pad_enabled[NORMAL_JPORTS];
|
|
static int parport_joystick_enabled;
|
|
static int oldmx[MAX_JPORTS], oldmy[MAX_JPORTS];
|
|
static int oleft[MAX_JPORTS], oright[MAX_JPORTS], otop[MAX_JPORTS], obot[MAX_JPORTS];
|
|
static int horizclear[MAX_JPORTS], vertclear[MAX_JPORTS];
|
|
|
|
uae_u16 potgo_value;
|
|
static int pot_cap[NORMAL_JPORTS][2];
|
|
static uae_u8 pot_dat[NORMAL_JPORTS][2];
|
|
static int pot_dat_act[NORMAL_JPORTS][2];
|
|
static int analog_port[NORMAL_JPORTS][2];
|
|
static int digital_port[NORMAL_JPORTS][2];
|
|
#define POTDAT_DELAY_PAL 8
|
|
#define POTDAT_DELAY_NTSC 7
|
|
|
|
static int use_joysticks[MAX_INPUT_DEVICES];
|
|
static int use_mice[MAX_INPUT_DEVICES];
|
|
static int use_keyboards[MAX_INPUT_DEVICES];
|
|
|
|
#define INPUT_QUEUE_SIZE 16
|
|
struct input_queue_struct {
|
|
int evt, storedstate, state, max, linecnt, nextlinecnt;
|
|
TCHAR *custom;
|
|
};
|
|
static struct input_queue_struct input_queue[INPUT_QUEUE_SIZE];
|
|
|
|
uae_u8 *restore_input (uae_u8 *src)
|
|
{
|
|
restore_u32 ();
|
|
for (int i = 0; i < 2; i++) {
|
|
for (int j = 0; j < 2; j++) {
|
|
pot_cap[i][j] = restore_u16 ();
|
|
}
|
|
}
|
|
return src;
|
|
}
|
|
uae_u8 *save_input (int *len, uae_u8 *dstptr)
|
|
{
|
|
uae_u8 *dstbak, *dst;
|
|
|
|
if (dstptr)
|
|
dstbak = dst = dstptr;
|
|
else
|
|
dstbak = dst = xmalloc (uae_u8, 1000);
|
|
save_u32 (0);
|
|
for (int i = 0; i < 2; i++) {
|
|
for (int j = 0; j < 2; j++) {
|
|
save_u16 (pot_cap[i][j]);
|
|
}
|
|
}
|
|
*len = dst - dstbak;
|
|
return dstbak;
|
|
}
|
|
|
|
static void freejport (struct uae_prefs *dst, int num)
|
|
{
|
|
memset (&dst->jports[num], 0, sizeof (struct jport));
|
|
dst->jports[num].id = -1;
|
|
}
|
|
static void copyjport (const struct uae_prefs *src, struct uae_prefs *dst, int num)
|
|
{
|
|
freejport (dst, num);
|
|
_tcscpy (dst->jports[num].configname, src->jports[num].configname);
|
|
_tcscpy (dst->jports[num].name, src->jports[num].name);
|
|
dst->jports[num].id = src->jports[num].id;
|
|
dst->jports[num].mode = src->jports[num].mode;
|
|
dst->jports[num].autofire = src->jports[num].autofire;
|
|
}
|
|
|
|
static void out_config (struct zfile *f, int id, int num, TCHAR *s1, TCHAR *s2)
|
|
{
|
|
TCHAR tmp[MAX_DPATH];
|
|
_stprintf (tmp, _T("input.%d.%s%d"), id, s1, num);
|
|
cfgfile_write_str (f, tmp, s2);
|
|
}
|
|
|
|
static bool write_config_head (struct zfile *f, int idnum, int devnum, TCHAR *name, struct uae_input_device *id, struct inputdevice_functions *idf)
|
|
{
|
|
TCHAR tmp2[CONFIG_BLEN];
|
|
|
|
if (idnum == GAMEPORT_INPUT_SETTINGS) {
|
|
if (!isdevice (id))
|
|
return false;
|
|
if (!id->enabled)
|
|
return false;
|
|
}
|
|
|
|
TCHAR *s = NULL;
|
|
if (id->name)
|
|
s = id->name;
|
|
else if (devnum < idf->get_num ())
|
|
s = idf->get_friendlyname (devnum);
|
|
if (s) {
|
|
_stprintf (tmp2, _T("input.%d.%s.%d.friendlyname"), idnum + 1, name, devnum);
|
|
cfgfile_write_str (f, tmp2, s);
|
|
}
|
|
|
|
s = NULL;
|
|
if (id->configname)
|
|
s = id->configname;
|
|
else if (devnum < idf->get_num ())
|
|
s = idf->get_uniquename (devnum);
|
|
if (s) {
|
|
_stprintf (tmp2, _T("input.%d.%s.%d.name"), idnum + 1, name, devnum);
|
|
cfgfile_write_str (f, tmp2, s);
|
|
}
|
|
|
|
if (!isdevice (id)) {
|
|
_stprintf (tmp2, _T("input.%d.%s.%d.empty"), idnum + 1, name, devnum);
|
|
cfgfile_write_bool (f, tmp2, true);
|
|
if (id->enabled) {
|
|
_stprintf (tmp2, _T("input.%d.%s.%d.disabled"), idnum + 1, name, devnum);
|
|
cfgfile_write (f, tmp2, _T("%d"), id->enabled ? 0 : 1);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
if (idnum == GAMEPORT_INPUT_SETTINGS) {
|
|
_stprintf (tmp2, _T("input.%d.%s.%d.custom"), idnum + 1, name, devnum);
|
|
cfgfile_write_bool (f, tmp2, true);
|
|
} else {
|
|
_stprintf (tmp2, _T("input.%d.%s.%d.empty"), idnum + 1, name, devnum);
|
|
cfgfile_write_bool (f, tmp2, false);
|
|
_stprintf (tmp2, _T("input.%d.%s.%d.disabled"), idnum + 1, name, devnum);
|
|
cfgfile_write_bool (f, tmp2, id->enabled ? false : true);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool write_slot (TCHAR *p, struct uae_input_device *uid, int i, int j)
|
|
{
|
|
bool ok = false;
|
|
uae_u64 flags = uid->flags[i][j];
|
|
if (uid->custom[i][j] && _tcslen (uid->custom[i][j]) > 0) {
|
|
_stprintf (p, _T("'%s'.%d"), uid->custom[i][j], flags & ID_FLAG_SAVE_MASK_CONFIG);
|
|
ok = true;
|
|
} else if (uid->eventid[i][j] > 0) {
|
|
_stprintf (p, _T("%s.%d"), events[uid->eventid[i][j]].confname, flags & ID_FLAG_SAVE_MASK_CONFIG);
|
|
ok = true;
|
|
} else {
|
|
_tcscpy (p, _T("NULL"));
|
|
}
|
|
if (ok && (flags & ID_FLAG_SAVE_MASK_QUALIFIERS)) {
|
|
TCHAR *p2 = p + _tcslen (p);
|
|
*p2++ = '.';
|
|
for (int i = 0; i < MAX_INPUT_QUALIFIERS * 2; i++) {
|
|
if ((ID_FLAG_QUALIFIER1 << i) & flags) {
|
|
if (i & 1)
|
|
_stprintf (p2, _T("%c"), 'a' + i / 2);
|
|
else
|
|
_stprintf (p2, _T("%c"), 'A' + i / 2);
|
|
p2++;
|
|
}
|
|
}
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
static struct inputdevice_functions *getidf (int devnum);
|
|
|
|
static void kbrlabel (TCHAR *s)
|
|
{
|
|
while (*s) {
|
|
*s = _totupper (*s);
|
|
if (*s == ' ')
|
|
*s = '_';
|
|
s++;
|
|
}
|
|
}
|
|
|
|
static void write_config2 (struct zfile *f, int idnum, int i, int offset, const TCHAR *extra, struct uae_input_device *id)
|
|
{
|
|
TCHAR tmp2[CONFIG_BLEN], tmp3[CONFIG_BLEN], *p;
|
|
int evt, got, j, k;
|
|
TCHAR *custom;
|
|
const int *slotorder;
|
|
int io = i + offset;
|
|
|
|
tmp2[0] = 0;
|
|
p = tmp2;
|
|
got = 0;
|
|
|
|
slotorder = slotorder1;
|
|
// if gameports non-custom mapping in slot0 -> save slot4 as slot0
|
|
if (id->port[io][0] && !(id->flags[io][0] & ID_FLAG_GAMEPORTSCUSTOM_MASK))
|
|
slotorder = slotorder2;
|
|
|
|
for (j = 0; j < MAX_INPUT_SUB_EVENT; j++) {
|
|
|
|
evt = id->eventid[io][slotorder[j]];
|
|
custom = id->custom[io][slotorder[j]];
|
|
if (custom == NULL && evt <= 0) {
|
|
for (k = j + 1; k < MAX_INPUT_SUB_EVENT; k++) {
|
|
if (id->eventid[io][slotorder[k]] > 0 || id->custom[io][slotorder[k]] != NULL)
|
|
break;
|
|
}
|
|
if (k == MAX_INPUT_SUB_EVENT)
|
|
break;
|
|
}
|
|
if (id->port[io][0] > 0) {
|
|
if (!(id->flags[io][0] & ID_FLAG_GAMEPORTSCUSTOM_MASK) && id->port[io][SPARE_SUB_EVENT] == 0)
|
|
break;
|
|
}
|
|
|
|
if (p > tmp2) {
|
|
*p++ = ',';
|
|
*p = 0;
|
|
}
|
|
bool ok = write_slot (p, id, io, slotorder[j]);
|
|
p += _tcslen (p);
|
|
if (ok) {
|
|
if (id->port[io][slotorder[j]] > 0) {
|
|
_stprintf (p, _T(".%d"), id->port[io][slotorder[j]] - 1);
|
|
p += _tcslen (p);
|
|
if (idnum != GAMEPORT_INPUT_SETTINGS && j == 0 && id->port[io][SPARE_SUB_EVENT] && slotorder == slotorder1) {
|
|
*p++ = '.';
|
|
write_slot (p, id, io, SPARE_SUB_EVENT);
|
|
p += _tcslen (p);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (p > tmp2) {
|
|
_stprintf (tmp3, _T("input.%d.%s%d"), idnum + 1, extra, i);
|
|
cfgfile_write_str (f, tmp3, tmp2);
|
|
}
|
|
}
|
|
|
|
static void write_kbr_config (struct zfile *f, int idnum, int devnum, struct uae_input_device *kbr, struct inputdevice_functions *idf)
|
|
{
|
|
TCHAR tmp1[CONFIG_BLEN], tmp2[CONFIG_BLEN], tmp3[CONFIG_BLEN], tmp4[CONFIG_BLEN], tmp5[CONFIG_BLEN], *p;
|
|
int i, j, k, evt, skip;
|
|
const int *slotorder;
|
|
|
|
if (!keyboard_default)
|
|
return;
|
|
|
|
if (!write_config_head (f, idnum, devnum, _T("keyboard"), kbr, idf))
|
|
return;
|
|
|
|
i = 0;
|
|
while (i < MAX_INPUT_DEVICE_EVENTS && kbr->extra[i] >= 0) {
|
|
|
|
slotorder = slotorder1;
|
|
// if gameports non-custom mapping in slot0 -> save slot4 as slot0
|
|
if (kbr->port[i][0] && !(kbr->flags[i][0] & ID_FLAG_GAMEPORTSCUSTOM_MASK))
|
|
slotorder = slotorder2;
|
|
|
|
skip = 0;
|
|
k = 0;
|
|
while (keyboard_default[k].scancode >= 0) {
|
|
if (keyboard_default[k].scancode == kbr->extra[i]) {
|
|
skip = 1;
|
|
for (j = 0; j < MAX_INPUT_SUB_EVENT; j++) {
|
|
if (keyboard_default[k].node[j].evt != 0) {
|
|
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))
|
|
skip = 0;
|
|
} else if ((kbr->flags[i][slotorder[j]] & ID_FLAG_SAVE_MASK_FULL) != 0 || kbr->eventid[i][slotorder[j]] > 0) {
|
|
skip = 0;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
k++;
|
|
}
|
|
bool isdefaultspare =
|
|
kbr->port[i][SPARE_SUB_EVENT] &&
|
|
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);
|
|
|
|
if (kbr->port[i][0] > 0 && !(kbr->flags[i][0] & ID_FLAG_GAMEPORTSCUSTOM_MASK) &&
|
|
(kbr->eventid[i][1] <= 0 && kbr->eventid[i][2] <= 0 && kbr->eventid[i][3] <= 0) &&
|
|
(kbr->port[i][SPARE_SUB_EVENT] == 0 || isdefaultspare))
|
|
skip = 1;
|
|
if (kbr->eventid[i][0] == 0 && (kbr->flags[i][0] & ID_FLAG_SAVE_MASK_FULL) == 0 && keyboard_default[k].scancode < 0)
|
|
skip = 1;
|
|
if (skip) {
|
|
i++;
|
|
continue;
|
|
}
|
|
tmp2[0] = 0;
|
|
p = tmp2;
|
|
for (j = 0; j < MAX_INPUT_SUB_EVENT; j++) {
|
|
TCHAR *custom = kbr->custom[i][slotorder[j]];
|
|
evt = kbr->eventid[i][slotorder[j]];
|
|
if (custom == NULL && evt <= 0) {
|
|
for (k = j + 1; k < MAX_INPUT_SUB_EVENT; k++) {
|
|
if (kbr->eventid[i][slotorder[k]] > 0 || kbr->custom[i][slotorder[k]] != NULL)
|
|
break;
|
|
}
|
|
if (k == MAX_INPUT_SUB_EVENT)
|
|
break;
|
|
}
|
|
if (p > tmp2) {
|
|
*p++ = ',';
|
|
*p = 0;
|
|
}
|
|
bool ok = write_slot (p, kbr, i, slotorder[j]);
|
|
p += _tcslen (p);
|
|
if (ok) {
|
|
// save port number + SPARE SLOT if needed
|
|
if (kbr->port[i][slotorder[j]] > 0 && (kbr->flags[i][slotorder[j]] & ID_FLAG_GAMEPORTSCUSTOM_MASK)) {
|
|
_stprintf (p, _T(".%d"), kbr->port[i][slotorder[j]] - 1);
|
|
p += _tcslen (p);
|
|
if (idnum != GAMEPORT_INPUT_SETTINGS && j == 0 && kbr->port[i][SPARE_SUB_EVENT] && !isdefaultspare && slotorder == slotorder1) {
|
|
*p++ = '.';
|
|
write_slot (p, kbr, i, SPARE_SUB_EVENT);
|
|
p += _tcslen (p);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
idf->get_widget_type (devnum, i, tmp5, NULL);
|
|
_stprintf (tmp3, _T("%d%s%s"), kbr->extra[i], tmp5[0] ? _T(".") : _T(""), tmp5[0] ? tmp5 : _T(""));
|
|
kbrlabel (tmp3);
|
|
_stprintf (tmp1, _T("keyboard.%d.button.%s"), devnum, tmp3);
|
|
_stprintf (tmp4, _T("input.%d.%s"), idnum + 1, tmp1);
|
|
cfgfile_write_str (f, tmp4, tmp2[0] ? tmp2 : _T("NULL"));
|
|
i++;
|
|
}
|
|
}
|
|
|
|
static void write_config (struct zfile *f, int idnum, int devnum, TCHAR *name, struct uae_input_device *id, struct inputdevice_functions *idf)
|
|
{
|
|
TCHAR tmp1[MAX_DPATH];
|
|
int i;
|
|
|
|
if (!write_config_head (f, idnum, devnum, name, id, idf))
|
|
return;
|
|
|
|
_stprintf (tmp1, _T("%s.%d.axis."), name, devnum);
|
|
for (i = 0; i < ID_AXIS_TOTAL; i++)
|
|
write_config2 (f, idnum, i, ID_AXIS_OFFSET, tmp1, id);
|
|
_stprintf (tmp1, _T("%s.%d.button.") ,name, devnum);
|
|
for (i = 0; i < ID_BUTTON_TOTAL; i++)
|
|
write_config2 (f, idnum, i, ID_BUTTON_OFFSET, tmp1, id);
|
|
}
|
|
|
|
static const TCHAR *kbtypes[] = { _T("amiga"), _T("pc"), NULL };
|
|
|
|
void write_inputdevice_config (struct uae_prefs *p, struct zfile *f)
|
|
{
|
|
int i, id;
|
|
|
|
cfgfile_write (f, _T("input.config"), _T("%d"), p->input_selected_setting == GAMEPORT_INPUT_SETTINGS ? 0 : p->input_selected_setting + 1);
|
|
cfgfile_write (f, _T("input.joymouse_speed_analog"), _T("%d"), p->input_joymouse_multiplier);
|
|
cfgfile_write (f, _T("input.joymouse_speed_digital"), _T("%d"), p->input_joymouse_speed);
|
|
cfgfile_write (f, _T("input.joymouse_deadzone"), _T("%d"), p->input_joymouse_deadzone);
|
|
cfgfile_write (f, _T("input.joystick_deadzone"), _T("%d"), p->input_joystick_deadzone);
|
|
cfgfile_write (f, _T("input.analog_joystick_multiplier"), _T("%d"), p->input_analog_joystick_mult);
|
|
cfgfile_write (f, _T("input.analog_joystick_offset"), _T("%d"), p->input_analog_joystick_offset);
|
|
cfgfile_write (f, _T("input.mouse_speed"), _T("%d"), p->input_mouse_speed);
|
|
cfgfile_write (f, _T("input.autofire_speed"), _T("%d"), p->input_autofire_linecnt);
|
|
cfgfile_dwrite_str (f, _T("input.keyboard_type"), kbtypes[p->input_keyboard_type]);
|
|
cfgfile_dwrite (f, _T("input.contact_bounce"), _T("%d"), p->input_contact_bounce);
|
|
for (id = 0; id < MAX_INPUT_SETTINGS; id++) {
|
|
TCHAR tmp[MAX_DPATH];
|
|
if (id < GAMEPORT_INPUT_SETTINGS) {
|
|
_stprintf (tmp, _T("input.%d.name"), id + 1);
|
|
cfgfile_dwrite_str (f, tmp, p->input_config_name[id]);
|
|
}
|
|
for (i = 0; i < MAX_INPUT_DEVICES; i++)
|
|
write_config (f, id, i, _T("joystick"), &p->joystick_settings[id][i], &idev[IDTYPE_JOYSTICK]);
|
|
for (i = 0; i < MAX_INPUT_DEVICES; i++)
|
|
write_config (f, id, i, _T("mouse"), &p->mouse_settings[id][i], &idev[IDTYPE_MOUSE]);
|
|
for (i = 0; i < MAX_INPUT_DEVICES; i++)
|
|
write_kbr_config (f, id, i, &p->keyboard_settings[id][i], &idev[IDTYPE_KEYBOARD]);
|
|
write_config (f, id, 0, _T("internal"), &p->internalevent_settings[id][0], &idev[IDTYPE_INTERNALEVENT]);
|
|
}
|
|
}
|
|
|
|
static uae_u64 getqual (const TCHAR **pp)
|
|
{
|
|
const TCHAR *p = *pp;
|
|
uae_u64 mask = 0;
|
|
|
|
while ((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z')) {
|
|
bool press = (*p >= 'A' && *p <= 'Z');
|
|
int shift, inc;
|
|
|
|
if (press) {
|
|
shift = *p - 'A';
|
|
inc = 0;
|
|
} else {
|
|
shift = *p - 'a';
|
|
inc = 1;
|
|
}
|
|
mask |= ID_FLAG_QUALIFIER1 << (shift * 2 + inc);
|
|
p++;
|
|
}
|
|
while (*p != 0 && *p !='.' && *p != ',')
|
|
p++;
|
|
if (*p == '.' || *p == ',')
|
|
p++;
|
|
*pp = p;
|
|
return mask;
|
|
}
|
|
|
|
static int getnum (const TCHAR **pp)
|
|
{
|
|
const TCHAR *p = *pp;
|
|
int v;
|
|
|
|
if (!_tcsnicmp (p, _T("false"), 5))
|
|
v = 0;
|
|
if (!_tcsnicmp (p, _T("true"), 4))
|
|
v = 1;
|
|
else
|
|
v = _tstol (p);
|
|
|
|
while (*p != 0 && *p !='.' && *p != ',')
|
|
p++;
|
|
if (*p == '.' || *p == ',')
|
|
p++;
|
|
*pp = p;
|
|
return v;
|
|
}
|
|
static TCHAR *getstring (const TCHAR **pp)
|
|
{
|
|
int i;
|
|
static TCHAR str[CONFIG_BLEN];
|
|
const TCHAR *p = *pp;
|
|
bool quoteds = false;
|
|
bool quotedd = false;
|
|
|
|
if (*p == 0)
|
|
return 0;
|
|
i = 0;
|
|
while (*p != 0 && i < 1000 - 1) {
|
|
if (*p == '\"')
|
|
quotedd = quotedd ? false : true;
|
|
if (*p == '\'')
|
|
quoteds = quoteds ? false : true;
|
|
if (!quotedd && !quoteds) {
|
|
if (*p == '.' || *p == ',')
|
|
break;
|
|
}
|
|
str[i++] = *p++;
|
|
}
|
|
if (*p == '.' || *p == ',')
|
|
p++;
|
|
str[i] = 0;
|
|
*pp = p;
|
|
return str;
|
|
}
|
|
|
|
static void reset_inputdevice_settings (struct uae_input_device *uid)
|
|
{
|
|
for (int l = 0; l < MAX_INPUT_DEVICE_EVENTS; l++) {
|
|
for (int i = 0; i < MAX_INPUT_SUB_EVENT_ALL; i++) {
|
|
uid->eventid[l][i] = 0;
|
|
uid->flags[l][i] = 0;
|
|
xfree (uid->custom[l][i]);
|
|
uid->custom[l][i] = NULL;
|
|
}
|
|
}
|
|
}
|
|
static void reset_inputdevice_slot (struct uae_prefs *prefs, int slot)
|
|
{
|
|
for (int m = 0; m < MAX_INPUT_DEVICES; m++) {
|
|
reset_inputdevice_settings (&prefs->joystick_settings[slot][m]);
|
|
reset_inputdevice_settings (&prefs->mouse_settings[slot][m]);
|
|
reset_inputdevice_settings (&prefs->keyboard_settings[slot][m]);
|
|
}
|
|
}
|
|
void reset_inputdevice_config (struct uae_prefs *prefs)
|
|
{
|
|
for (int i = 0; i< MAX_INPUT_SETTINGS; i++)
|
|
reset_inputdevice_slot (prefs, i);
|
|
}
|
|
|
|
|
|
static void set_kbr_default_event (struct uae_input_device *kbr, struct uae_input_device_kbr_default *trans, int num)
|
|
{
|
|
for (int i = 0; trans[i].scancode >= 0; i++) {
|
|
if (kbr->extra[num] == trans[i].scancode) {
|
|
int k;
|
|
for (k = 0; k < MAX_INPUT_SUB_EVENT; k++) {
|
|
if (kbr->eventid[num][k] == 0)
|
|
break;
|
|
}
|
|
if (k == MAX_INPUT_SUB_EVENT) {
|
|
write_log (_T("corrupt default keyboard mappings\n"));
|
|
return;
|
|
}
|
|
int l = 0;
|
|
while (k < MAX_INPUT_SUB_EVENT && trans[i].node[l].evt) {
|
|
int evt = trans[i].node[l].evt;
|
|
if (evt < 0 || evt >= INPUTEVENT_SPC_LAST)
|
|
gui_message(_T("invalid event in default keyboard table!"));
|
|
kbr->eventid[num][k] = evt;
|
|
kbr->flags[num][k] = trans[i].node[l].flags;
|
|
l++;
|
|
k++;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void clear_id (struct uae_input_device *id)
|
|
{
|
|
#ifndef _DEBUG
|
|
int i, j;
|
|
for (i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++) {
|
|
for (j = 0; j < MAX_INPUT_SUB_EVENT_ALL; j++)
|
|
xfree (id->custom[i][j]);
|
|
}
|
|
#endif
|
|
TCHAR *cn = id->configname;
|
|
TCHAR *n = id->name;
|
|
memset (id, 0, sizeof (struct uae_input_device));
|
|
id->configname = cn;
|
|
id->name = n;
|
|
}
|
|
|
|
static void set_kbr_default (struct uae_prefs *p, int index, int devnum, struct uae_input_device_kbr_default *trans)
|
|
{
|
|
int i, j;
|
|
struct uae_input_device *kbr;
|
|
struct inputdevice_functions *id = &idev[IDTYPE_KEYBOARD];
|
|
uae_u32 scancode;
|
|
|
|
if (!trans)
|
|
return;
|
|
for (j = 0; j < MAX_INPUT_DEVICES; j++) {
|
|
if (devnum >= 0 && devnum != j)
|
|
continue;
|
|
kbr = &p->keyboard_settings[index][j];
|
|
for (i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++) {
|
|
clear_id (kbr);
|
|
kbr->extra[i] = -1;
|
|
}
|
|
if (j < id->get_num ()) {
|
|
if (input_get_default_keyboard (j))
|
|
kbr->enabled = 1;
|
|
for (i = 0; i < id->get_widget_num (j); i++) {
|
|
id->get_widget_type (j, i, 0, &scancode);
|
|
kbr->extra[i] = scancode;
|
|
set_kbr_default_event (kbr, trans, i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void inputdevice_default_kb (struct uae_prefs *p, int num)
|
|
{
|
|
if (num == GAMEPORT_INPUT_SETTINGS) {
|
|
if (p->jports[0].id != JPORT_CUSTOM || p->jports[1].id != JPORT_CUSTOM)
|
|
reset_inputdevice_slot (p, num);
|
|
}
|
|
set_kbr_default (p, num, -1, keyboard_default);
|
|
}
|
|
static void inputdevice_default_kb_all (struct uae_prefs *p)
|
|
{
|
|
for (int i = 0; i < MAX_INPUT_SETTINGS; i++)
|
|
inputdevice_default_kb (p, i);
|
|
}
|
|
|
|
static bool read_slot (TCHAR *parm, int num, int joystick, int button, struct uae_input_device *id, int keynum, int subnum, struct inputevent *ie, uae_u64 flags, int port, TCHAR *custom)
|
|
{
|
|
int mask;
|
|
|
|
if (custom == NULL && ie->name == NULL) {
|
|
if (!_tcscmp (parm, _T("NULL"))) {
|
|
if (joystick < 0) {
|
|
id->eventid[keynum][subnum] = 0;
|
|
id->flags[keynum][subnum] = 0;
|
|
} else if (button) {
|
|
id->eventid[num + ID_BUTTON_OFFSET][subnum] = 0;
|
|
id->flags[num + ID_BUTTON_OFFSET][subnum] = 0;
|
|
} else {
|
|
id->eventid[num + ID_AXIS_OFFSET][subnum] = 0;
|
|
id->flags[num + ID_AXIS_OFFSET][subnum] = 0;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
if (custom)
|
|
ie = &events[INPUTEVENT_SPC_CUSTOM_EVENT];
|
|
|
|
if (joystick < 0) {
|
|
if (!(ie->allow_mask & AM_K))
|
|
return false;
|
|
id->eventid[keynum][subnum] = ie - events;
|
|
id->flags[keynum][subnum] = flags;
|
|
id->port[keynum][subnum] = port;
|
|
xfree (id->custom[keynum][subnum]);
|
|
id->custom[keynum][subnum] = custom;
|
|
} else if (button) {
|
|
if (joystick)
|
|
mask = AM_JOY_BUT;
|
|
else
|
|
mask = AM_MOUSE_BUT;
|
|
if (!(ie->allow_mask & mask))
|
|
return false;
|
|
id->eventid[num + ID_BUTTON_OFFSET][subnum] = ie - events;
|
|
id->flags[num + ID_BUTTON_OFFSET][subnum] = flags;
|
|
id->port[num + ID_BUTTON_OFFSET][subnum] = port;
|
|
xfree (id->custom[num + ID_BUTTON_OFFSET][subnum]);
|
|
id->custom[num + ID_BUTTON_OFFSET][subnum] = custom;
|
|
} else {
|
|
if (joystick)
|
|
mask = AM_JOY_AXIS;
|
|
else
|
|
mask = AM_MOUSE_AXIS;
|
|
if (!(ie->allow_mask & mask))
|
|
return false;
|
|
id->eventid[num + ID_AXIS_OFFSET][subnum] = ie - events;
|
|
id->flags[num + ID_AXIS_OFFSET][subnum] = flags;
|
|
id->port[num + ID_AXIS_OFFSET][subnum] = port;
|
|
xfree (id->custom[num + ID_AXIS_OFFSET][subnum]);
|
|
id->custom[num + ID_AXIS_OFFSET][subnum] = custom;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static struct inputevent *readevent (const TCHAR *name, TCHAR **customp)
|
|
{
|
|
int i = 1;
|
|
while (events[i].name) {
|
|
if (!_tcscmp (events[i].confname, name))
|
|
return &events[i];
|
|
i++;
|
|
}
|
|
if (_tcslen (name) > 2 && name[0] == '\'' && name[_tcslen (name) - 1] == '\'') {
|
|
TCHAR *custom = my_strdup (name + 1);
|
|
custom[_tcslen (custom) - 1] = 0;
|
|
*customp = custom;
|
|
}
|
|
return &events[0];
|
|
}
|
|
|
|
void read_inputdevice_config (struct uae_prefs *pr, const TCHAR *option, TCHAR *value)
|
|
{
|
|
struct uae_input_device *id = 0;
|
|
struct inputevent *ie;
|
|
int devnum, num, button, joystick, subnum, idnum, keynum;
|
|
const TCHAR *p;
|
|
TCHAR *p2, *custom;
|
|
|
|
option += 6; /* "input." */
|
|
p = getstring (&option);
|
|
if (!strcasecmp (p, _T("config"))) {
|
|
pr->input_selected_setting = _tstol (value) - 1;
|
|
if (pr->input_selected_setting == -1)
|
|
pr->input_selected_setting = GAMEPORT_INPUT_SETTINGS;
|
|
if (pr->input_selected_setting < 0 || pr->input_selected_setting > MAX_INPUT_SETTINGS)
|
|
pr->input_selected_setting = 0;
|
|
}
|
|
if (!strcasecmp (p, _T("joymouse_speed_analog")))
|
|
pr->input_joymouse_multiplier = _tstol (value);
|
|
if (!strcasecmp (p, _T("joymouse_speed_digital")))
|
|
pr->input_joymouse_speed = _tstol (value);
|
|
if (!strcasecmp (p, _T("joystick_deadzone")))
|
|
pr->input_joystick_deadzone = _tstol (value);
|
|
if (!strcasecmp (p, _T("joymouse_deadzone")))
|
|
pr->input_joymouse_deadzone = _tstol (value);
|
|
if (!strcasecmp (p, _T("mouse_speed")))
|
|
pr->input_mouse_speed = _tstol (value);
|
|
if (!strcasecmp (p, _T("autofire_speed")))
|
|
pr->input_autofire_linecnt = _tstol (value);
|
|
if (!strcasecmp (p, _T("analog_joystick_multiplier")))
|
|
pr->input_analog_joystick_mult = _tstol (value);
|
|
if (!strcasecmp (p, _T("analog_joystick_offset")))
|
|
pr->input_analog_joystick_offset = _tstol (value);
|
|
if (!strcasecmp (p, _T("keyboard_type"))) {
|
|
cfgfile_strval (option, value, NULL, &pr->input_analog_joystick_offset, kbtypes, 0);
|
|
keyboard_default = keyboard_default_table[pr->input_keyboard_type];
|
|
inputdevice_default_kb_all (pr);
|
|
}
|
|
|
|
if (!strcasecmp (p, _T("contact_bounce")))
|
|
pr->input_contact_bounce = _tstol (value);
|
|
|
|
idnum = _tstol (p);
|
|
if (idnum <= 0 || idnum > MAX_INPUT_SETTINGS)
|
|
return;
|
|
idnum--;
|
|
|
|
if (!_tcscmp (option, _T("name"))) {
|
|
if (idnum < GAMEPORT_INPUT_SETTINGS)
|
|
_tcscpy (pr->input_config_name[idnum], value);
|
|
return;
|
|
}
|
|
|
|
if (_tcsncmp (option, _T("mouse."), 6) == 0) {
|
|
p = option + 6;
|
|
} else if (_tcsncmp (option, _T("joystick."), 9) == 0) {
|
|
p = option + 9;
|
|
} else if (_tcsncmp (option, _T("keyboard."), 9) == 0) {
|
|
p = option + 9;
|
|
} else if (_tcsncmp (option, _T("internal."), 9) == 0) {
|
|
p = option + 9;
|
|
} else
|
|
return;
|
|
|
|
devnum = getnum (&p);
|
|
if (devnum < 0 || devnum >= MAX_INPUT_DEVICES)
|
|
return;
|
|
|
|
p2 = getstring (&p);
|
|
if (!p2)
|
|
return;
|
|
|
|
if (_tcsncmp (option, _T("mouse."), 6) == 0) {
|
|
id = &pr->mouse_settings[idnum][devnum];
|
|
joystick = 0;
|
|
} else if (_tcsncmp (option, _T("joystick."), 9) == 0) {
|
|
id = &pr->joystick_settings[idnum][devnum];
|
|
joystick = 1;
|
|
} else if (_tcsncmp (option, _T("keyboard."), 9) == 0) {
|
|
id = &pr->keyboard_settings[idnum][devnum];
|
|
joystick = -1;
|
|
} else if (_tcsncmp (option, _T("internal."), 9) == 0) {
|
|
if (devnum > 0)
|
|
return;
|
|
id = &pr->internalevent_settings[idnum][devnum];
|
|
joystick = 1;
|
|
}
|
|
if (!id)
|
|
return;
|
|
|
|
if (!_tcscmp (p2, _T("name"))) {
|
|
xfree (id->configname);
|
|
id->configname = my_strdup (value);
|
|
return;
|
|
}
|
|
if (!_tcscmp (p2, _T("friendlyname"))) {
|
|
xfree (id->name);
|
|
id->name = my_strdup (value);
|
|
return;
|
|
}
|
|
|
|
if (!_tcscmp (p2, _T("custom"))) {
|
|
int iscustom;
|
|
p = value;
|
|
iscustom = getnum (&p);
|
|
if (idnum == GAMEPORT_INPUT_SETTINGS) {
|
|
clear_id (id);
|
|
if (joystick < 0)
|
|
set_kbr_default (pr, idnum, devnum, keyboard_default);
|
|
id->enabled = iscustom;
|
|
} else {
|
|
id->enabled = false;
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (!_tcscmp (p2, _T("empty"))) {
|
|
int empty;
|
|
p = value;
|
|
empty = getnum (&p);
|
|
clear_id (id);
|
|
if (!empty) {
|
|
if (joystick < 0)
|
|
set_kbr_default (pr, idnum, devnum, keyboard_default);
|
|
}
|
|
id->enabled = 1;
|
|
if (idnum == GAMEPORT_INPUT_SETTINGS)
|
|
id->enabled = 0;
|
|
return;
|
|
}
|
|
|
|
if (!_tcscmp (p2, _T("disabled"))) {
|
|
int disabled;
|
|
p = value;
|
|
disabled = getnum (&p);
|
|
id->enabled = disabled == 0 ? 1 : 0;
|
|
if (idnum == GAMEPORT_INPUT_SETTINGS)
|
|
id->enabled = 0;
|
|
return;
|
|
}
|
|
|
|
if (idnum == GAMEPORT_INPUT_SETTINGS && id->enabled == 0)
|
|
return;
|
|
|
|
button = 0;
|
|
keynum = 0;
|
|
if (joystick < 0) {
|
|
num = getnum (&p);
|
|
for (keynum = 0; keynum < MAX_INPUT_DEVICE_EVENTS; keynum++) {
|
|
if (id->extra[keynum] == num)
|
|
break;
|
|
}
|
|
if (keynum >= MAX_INPUT_DEVICE_EVENTS)
|
|
return;
|
|
} else {
|
|
button = -1;
|
|
if (!_tcscmp (p2, _T("axis")))
|
|
button = 0;
|
|
else if(!_tcscmp (p2, _T("button")))
|
|
button = 1;
|
|
if (button < 0)
|
|
return;
|
|
num = getnum (&p);
|
|
}
|
|
p = value;
|
|
|
|
custom = NULL;
|
|
for (subnum = 0; subnum < MAX_INPUT_SUB_EVENT; subnum++) {
|
|
uae_u64 flags;
|
|
int port;
|
|
xfree (custom);
|
|
custom = NULL;
|
|
p2 = getstring (&p);
|
|
if (!p2)
|
|
break;
|
|
ie = readevent (p2, &custom);
|
|
flags = 0;
|
|
port = 0;
|
|
if (p[-1] == '.')
|
|
flags = getnum (&p) & ID_FLAG_SAVE_MASK_CONFIG;
|
|
if (p[-1] == '.') {
|
|
if ((p[0] >= 'A' && p[0] <= 'Z') || (p[0] >= 'a' && p[0] <= 'z'))
|
|
flags |= getqual (&p);
|
|
if (p[-1] == '.')
|
|
port = getnum (&p) + 1;
|
|
}
|
|
if (idnum == GAMEPORT_INPUT_SETTINGS && port == 0)
|
|
continue;
|
|
if (p[-1] == '.' && idnum != GAMEPORT_INPUT_SETTINGS) {
|
|
p2 = getstring (&p);
|
|
if (p2) {
|
|
int flags2 = 0;
|
|
if (p[-1] == '.')
|
|
flags2 = getnum (&p) & ID_FLAG_SAVE_MASK_CONFIG;
|
|
if (p[-1] == '.' && (p[0] >= 'A' && p[0] <= 'Z') || (p[0] >= 'a' && p[0] <= 'z'))
|
|
flags |= getqual (&p);
|
|
TCHAR *custom2 = NULL;
|
|
struct inputevent *ie2 = readevent (p2, &custom2);
|
|
read_slot (p2, num, joystick, button, id, keynum, SPARE_SUB_EVENT, ie2, flags2, MAX_JPORTS + 1, custom2);
|
|
}
|
|
}
|
|
|
|
while (*p != 0) {
|
|
if (p[-1] == ',')
|
|
break;
|
|
p++;
|
|
}
|
|
if (!read_slot (p2, num, joystick, button, id, keynum, subnum, ie, flags, port, custom))
|
|
continue;
|
|
custom = NULL;
|
|
}
|
|
xfree (custom);
|
|
}
|
|
|
|
static int mouseedge_alive, mousehack_alive_cnt;
|
|
static int lastmx, lastmy;
|
|
static uaecptr magicmouse_ibase, magicmouse_gfxbase;
|
|
static int dimensioninfo_width, dimensioninfo_height, dimensioninfo_dbl;
|
|
static int vp_xoffset, vp_yoffset, mouseoffset_x, mouseoffset_y;
|
|
static int tablet_maxx, tablet_maxy, tablet_data;
|
|
|
|
int mousehack_alive (void)
|
|
{
|
|
return mousehack_alive_cnt > 0 ? mousehack_alive_cnt : 0;
|
|
}
|
|
|
|
static uaecptr get_base (const uae_char *name)
|
|
{
|
|
uaecptr v = get_long (4);
|
|
addrbank *b = &get_mem_bank(v);
|
|
|
|
if (!b || !b->check (v, 400) || b->flags != ABFLAG_RAM)
|
|
return 0;
|
|
v += 378; // liblist
|
|
while (v = get_long (v)) {
|
|
uae_u32 v2;
|
|
uae_u8 *p;
|
|
b = &get_mem_bank (v);
|
|
if (!b || !b->check (v, 32) || b->flags != ABFLAG_RAM)
|
|
goto fail;
|
|
v2 = get_long (v + 10); // name
|
|
b = &get_mem_bank (v2);
|
|
if (!b || !b->check (v2, 20))
|
|
goto fail;
|
|
if (b->flags != ABFLAG_ROM && b->flags != ABFLAG_RAM)
|
|
return 0;
|
|
p = b->xlateaddr (v2);
|
|
if (!memcmp (p, name, strlen (name) + 1)) {
|
|
TCHAR *s = au (name);
|
|
write_log (_T("get_base('%s')=%08x\n"), s, v);
|
|
xfree (s);
|
|
return v;
|
|
}
|
|
}
|
|
return 0;
|
|
fail:
|
|
{
|
|
TCHAR *s = au (name);
|
|
write_log (_T("get_base('%s') failed, invalid library list\n"), s);
|
|
xfree (s);
|
|
}
|
|
return 0xffffffff;
|
|
}
|
|
|
|
static uaecptr get_intuitionbase (void)
|
|
{
|
|
if (magicmouse_ibase == 0xffffffff)
|
|
return 0;
|
|
if (magicmouse_ibase)
|
|
return magicmouse_ibase;
|
|
magicmouse_ibase = get_base ("intuition.library");
|
|
return magicmouse_ibase;
|
|
}
|
|
static uaecptr get_gfxbase (void)
|
|
{
|
|
if (magicmouse_gfxbase == 0xffffffff)
|
|
return 0;
|
|
if (magicmouse_gfxbase)
|
|
return magicmouse_gfxbase;
|
|
magicmouse_gfxbase = get_base ("graphics.library");
|
|
return magicmouse_gfxbase;
|
|
}
|
|
|
|
#define MH_E 0
|
|
#define MH_CNT 2
|
|
#define MH_MAXX 4
|
|
#define MH_MAXY 6
|
|
#define MH_MAXZ 8
|
|
#define MH_X 10
|
|
#define MH_Y 12
|
|
#define MH_Z 14
|
|
#define MH_RESX 16
|
|
#define MH_RESY 18
|
|
#define MH_MAXAX 20
|
|
#define MH_MAXAY 22
|
|
#define MH_MAXAZ 24
|
|
#define MH_AX 26
|
|
#define MH_AY 28
|
|
#define MH_AZ 30
|
|
#define MH_PRESSURE 32
|
|
#define MH_BUTTONBITS 34
|
|
#define MH_INPROXIMITY 38
|
|
#define MH_ABSX 40
|
|
#define MH_ABSY 42
|
|
|
|
#define MH_END 44
|
|
#define MH_START 4
|
|
|
|
int inputdevice_is_tablet (void)
|
|
{
|
|
int v;
|
|
if (!uae_boot_rom)
|
|
return 0;
|
|
if (currprefs.input_tablet == TABLET_OFF)
|
|
return 0;
|
|
if (currprefs.input_tablet == TABLET_MOUSEHACK)
|
|
return -1;
|
|
v = is_tablet ();
|
|
if (!v)
|
|
return 0;
|
|
if (kickstart_version < 37)
|
|
return v ? -1 : 0;
|
|
return v ? 1 : 0;
|
|
}
|
|
|
|
static uaecptr mousehack_address;
|
|
static bool mousehack_enabled;
|
|
|
|
static void mousehack_reset (void)
|
|
{
|
|
dimensioninfo_width = dimensioninfo_height = 0;
|
|
mouseoffset_x = mouseoffset_y = 0;
|
|
dimensioninfo_dbl = 0;
|
|
mousehack_alive_cnt = 0;
|
|
vp_xoffset = vp_yoffset = 0;
|
|
tablet_data = 0;
|
|
if (mousehack_address)
|
|
put_byte (mousehack_address + MH_E, 0);
|
|
mousehack_address = 0;
|
|
mousehack_enabled = false;
|
|
}
|
|
|
|
static bool mousehack_enable (void)
|
|
{
|
|
int mode;
|
|
|
|
if (!uae_boot_rom || currprefs.input_tablet == TABLET_OFF)
|
|
return false;
|
|
if (mousehack_address && mousehack_enabled)
|
|
return true;
|
|
mode = 0x80;
|
|
if (currprefs.input_tablet == TABLET_MOUSEHACK)
|
|
mode |= 1;
|
|
if (inputdevice_is_tablet () > 0)
|
|
mode |= 2;
|
|
if (mousehack_address) {
|
|
write_log (_T("Mouse driver enabled (%s)\n"), ((mode & 3) == 3 ? _T("tablet+mousehack") : ((mode & 3) == 2) ? _T("tablet") : _T("mousehack")));
|
|
put_byte (mousehack_address + MH_E, mode);
|
|
mousehack_enabled = true;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void input_mousehack_mouseoffset (uaecptr pointerprefs)
|
|
{
|
|
mouseoffset_x = (uae_s16)get_word (pointerprefs + 28);
|
|
mouseoffset_y = (uae_s16)get_word (pointerprefs + 30);
|
|
}
|
|
|
|
int input_mousehack_status (int mode, uaecptr diminfo, uaecptr dispinfo, uaecptr vp, uae_u32 moffset)
|
|
{
|
|
if (mode == 4) {
|
|
return mousehack_enable () ? 1 : 0;
|
|
} else if (mode == 5) {
|
|
mousehack_address = m68k_dreg (regs, 0);
|
|
mousehack_enable ();
|
|
} else if (mode == 0) {
|
|
uae_u8 v = get_byte (mousehack_address + MH_E);
|
|
v |= 0x40;
|
|
put_byte (mousehack_address + MH_E, v);
|
|
write_log (_T("Tablet driver running (%08x,%02x)\n"), mousehack_address, v);
|
|
} else if (mode == 1) {
|
|
int x1 = -1, y1 = -1, x2 = -1, y2 = -1;
|
|
uae_u32 props = 0;
|
|
dimensioninfo_width = -1;
|
|
dimensioninfo_height = -1;
|
|
vp_xoffset = 0;
|
|
vp_yoffset = 0;
|
|
if (diminfo) {
|
|
x1 = get_word (diminfo + 50);
|
|
y1 = get_word (diminfo + 52);
|
|
x2 = get_word (diminfo + 54);
|
|
y2 = get_word (diminfo + 56);
|
|
dimensioninfo_width = x2 - x1 + 1;
|
|
dimensioninfo_height = y2 - y1 + 1;
|
|
}
|
|
if (vp) {
|
|
vp_xoffset = get_word (vp + 28);
|
|
vp_yoffset = get_word (vp + 30);
|
|
}
|
|
if (dispinfo)
|
|
props = get_long (dispinfo + 18);
|
|
dimensioninfo_dbl = (props & 0x00020000) ? 1 : 0;
|
|
write_log (_T("%08x %08x %08x (%dx%d)-(%dx%d) d=%dx%d %s\n"),
|
|
diminfo, props, vp, x1, y1, x2, y2, vp_xoffset, vp_yoffset,
|
|
(props & 0x00020000) ? _T("dbl") : _T(""));
|
|
} else if (mode == 2) {
|
|
if (mousehack_alive_cnt == 0)
|
|
mousehack_alive_cnt = -100;
|
|
else if (mousehack_alive_cnt > 0)
|
|
mousehack_alive_cnt = 100;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
void get_custom_mouse_limits (int *w, int *h, int *dx, int *dy, int dbl);
|
|
|
|
void inputdevice_tablet_strobe (void)
|
|
{
|
|
mousehack_enable ();
|
|
if (!uae_boot_rom)
|
|
return;
|
|
if (!tablet_data)
|
|
return;
|
|
if (mousehack_address)
|
|
put_byte (mousehack_address + MH_CNT, get_byte (mousehack_address + MH_CNT) + 1);
|
|
}
|
|
|
|
void inputdevice_tablet (int x, int y, int z, int pressure, uae_u32 buttonbits, int inproximity, int ax, int ay, int az)
|
|
{
|
|
uae_u8 *p;
|
|
uae_u8 tmp[MH_END];
|
|
|
|
mousehack_enable ();
|
|
if (inputdevice_is_tablet () <= 0)
|
|
return;
|
|
//write_log (_T("%d %d %d %d %08X %d %d %d %d\n"), x, y, z, pressure, buttonbits, inproximity, ax, ay, az);
|
|
p = get_real_address (mousehack_address);
|
|
|
|
memcpy (tmp, p + MH_START, MH_END - MH_START);
|
|
#if 0
|
|
if (currprefs.input_magic_mouse) {
|
|
int maxx, maxy, diffx, diffy;
|
|
int dw, dh, ax, ay, aw, ah;
|
|
float xmult, ymult;
|
|
float fx, fy;
|
|
|
|
fx = (float)x;
|
|
fy = (float)y;
|
|
desktop_coords (&dw, &dh, &ax, &ay, &aw, &ah);
|
|
xmult = (float)tablet_maxx / dw;
|
|
ymult = (float)tablet_maxy / dh;
|
|
|
|
diffx = 0;
|
|
diffy = 0;
|
|
if (picasso_on) {
|
|
maxx = gfxvidinfo.width;
|
|
maxy = gfxvidinfo.height;
|
|
} else {
|
|
get_custom_mouse_limits (&maxx, &maxy, &diffx, &diffy);
|
|
}
|
|
diffx += ax;
|
|
diffy += ah;
|
|
|
|
fx -= diffx * xmult;
|
|
if (fx < 0)
|
|
fx = 0;
|
|
if (fx >= aw * xmult)
|
|
fx = aw * xmult - 1;
|
|
fy -= diffy * ymult;
|
|
if (fy < 0)
|
|
fy = 0;
|
|
if (fy >= ah * ymult)
|
|
fy = ah * ymult - 1;
|
|
|
|
x = (int)(fx * (aw * xmult) / tablet_maxx + 0.5);
|
|
y = (int)(fy * (ah * ymult) / tablet_maxy + 0.5);
|
|
|
|
}
|
|
#endif
|
|
p[MH_X] = x >> 8;
|
|
p[MH_X + 1] = x;
|
|
p[MH_Y] = y >> 8;
|
|
p[MH_Y + 1] = y;
|
|
p[MH_Z] = z >> 8;
|
|
p[MH_Z + 1] = z;
|
|
|
|
p[MH_AX] = ax >> 8;
|
|
p[MH_AX + 1] = ax;
|
|
p[MH_AY] = ay >> 8;
|
|
p[MH_AY + 1] = ay;
|
|
p[MH_AZ] = az >> 8;
|
|
p[MH_AZ + 1] = az;
|
|
|
|
p[MH_MAXX] = tablet_maxx >> 8;
|
|
p[MH_MAXX + 1] = tablet_maxx;
|
|
p[MH_MAXY] = tablet_maxy >> 8;
|
|
p[MH_MAXY + 1] = tablet_maxy;
|
|
|
|
p[MH_PRESSURE] = pressure >> 8;
|
|
p[MH_PRESSURE + 1] = pressure;
|
|
|
|
p[MH_BUTTONBITS + 0] = buttonbits >> 24;
|
|
p[MH_BUTTONBITS + 1] = buttonbits >> 16;
|
|
p[MH_BUTTONBITS + 2] = buttonbits >> 8;
|
|
p[MH_BUTTONBITS + 3] = buttonbits >> 0;
|
|
|
|
if (inproximity < 0) {
|
|
p[MH_INPROXIMITY] = p[MH_INPROXIMITY + 1] = 0xff;
|
|
} else {
|
|
p[MH_INPROXIMITY] = 0;
|
|
p[MH_INPROXIMITY + 1] = inproximity ? 1 : 0;
|
|
}
|
|
|
|
if (!memcmp (tmp, p + MH_START, MH_END - MH_START))
|
|
return;
|
|
p[MH_E] = 0xc0 | 2;
|
|
p[MH_CNT]++;
|
|
}
|
|
|
|
void inputdevice_tablet_info (int maxx, int maxy, int maxz, int maxax, int maxay, int maxaz, int xres, int yres)
|
|
{
|
|
uae_u8 *p;
|
|
|
|
if (!uae_boot_rom)
|
|
return;
|
|
p = get_real_address (mousehack_address);
|
|
|
|
tablet_maxx = maxx;
|
|
tablet_maxy = maxy;
|
|
p[MH_MAXX] = maxx >> 8;
|
|
p[MH_MAXX + 1] = maxx;
|
|
p[MH_MAXY] = maxy >> 8;
|
|
p[MH_MAXY + 1] = maxy;
|
|
p[MH_MAXZ] = maxz >> 8;
|
|
p[MH_MAXZ + 1] = maxz;
|
|
|
|
p[MH_RESX] = xres >> 8;
|
|
p[MH_RESX + 1] = xres;
|
|
p[MH_RESY] = yres >> 8;
|
|
p[MH_RESY + 1] = yres;
|
|
|
|
p[MH_MAXAX] = maxax >> 8;
|
|
p[MH_MAXAX + 1] = maxax;
|
|
p[MH_MAXAY] = maxay >> 8;
|
|
p[MH_MAXAY + 1] = maxay;
|
|
p[MH_MAXAZ] = maxaz >> 8;
|
|
p[MH_MAXAZ + 1] = maxaz;
|
|
}
|
|
|
|
|
|
void getgfxoffset (int *dx, int *dy, int*,int*);
|
|
|
|
static void inputdevice_mh_abs (int x, int y)
|
|
{
|
|
uae_u8 *p;
|
|
uae_u8 tmp[4];
|
|
|
|
mousehack_enable ();
|
|
if (!mousehack_address)
|
|
return;
|
|
p = get_real_address (mousehack_address);
|
|
|
|
memcpy (tmp, p + MH_ABSX, sizeof tmp);
|
|
|
|
x -= mouseoffset_x + 1;
|
|
y -= mouseoffset_y + 2;
|
|
|
|
p[MH_ABSX] = x >> 8;
|
|
p[MH_ABSX + 1] = x;
|
|
p[MH_ABSY] = y >> 8;
|
|
p[MH_ABSY + 1] = y;
|
|
|
|
if (!memcmp (tmp, p + MH_ABSX, sizeof tmp))
|
|
return;
|
|
p[MH_E] = 0xc0 | 1;
|
|
p[MH_CNT]++;
|
|
tablet_data = 1;
|
|
}
|
|
|
|
#if 0
|
|
static void inputdevice_mh_abs_v36 (int x, int y)
|
|
{
|
|
uae_u8 *p;
|
|
uae_u8 tmp[MH_END];
|
|
uae_u32 off;
|
|
int maxx, maxy, diffx, diffy;
|
|
int fdy, fdx, fmx, fmy;
|
|
|
|
mousehack_enable ();
|
|
off = getmhoffset ();
|
|
p = rtarea + off;
|
|
|
|
memcpy (tmp, p + MH_START, MH_END - MH_START);
|
|
|
|
getgfxoffset (&fdx, &fdy, &fmx, &fmy);
|
|
x -= fdx;
|
|
y -= fdy;
|
|
x += vp_xoffset;
|
|
y += vp_yoffset;
|
|
|
|
diffx = diffy = 0;
|
|
maxx = maxy = 0;
|
|
|
|
if (picasso_on) {
|
|
maxx = picasso96_state.Width;
|
|
maxy = picasso96_state.Height;
|
|
} else if (dimensioninfo_width > 0 && dimensioninfo_height > 0) {
|
|
maxx = dimensioninfo_width;
|
|
maxy = dimensioninfo_height;
|
|
get_custom_mouse_limits (&maxx, &maxy, &diffx, &diffy, dimensioninfo_dbl);
|
|
} else {
|
|
uaecptr gb = get_gfxbase ();
|
|
maxx = 0; maxy = 0;
|
|
if (gb) {
|
|
maxy = get_word (gb + 216);
|
|
maxx = get_word (gb + 218);
|
|
}
|
|
get_custom_mouse_limits (&maxx, &maxy, &diffx, &diffy, 0);
|
|
}
|
|
#if 0
|
|
{
|
|
uaecptr gb = get_intuitionbase ();
|
|
maxy = get_word (gb + 1344 + 2);
|
|
maxx = get_word (gb + 1348 + 2);
|
|
write_log (_T("%d %d\n"), maxx, maxy);
|
|
}
|
|
#endif
|
|
#if 1
|
|
{
|
|
uaecptr gb = get_gfxbase ();
|
|
uaecptr view = get_long (gb + 34);
|
|
if (view) {
|
|
uaecptr vp = get_long (view);
|
|
if (vp) {
|
|
int w, h, dw, dh;
|
|
w = get_word (vp + 24);
|
|
h = get_word (vp + 26) * 2;
|
|
dw = get_word (vp + 28);
|
|
dh = get_word (vp + 30);
|
|
//write_log (_T("%d %d %d %d\n"), w, h, dw, dh);
|
|
if (w < maxx)
|
|
maxx = w;
|
|
if (h < maxy)
|
|
maxy = h;
|
|
x -= dw;
|
|
y -= dh;
|
|
}
|
|
}
|
|
//write_log (_T("* %d %d\n"), get_word (gb + 218), get_word (gb + 216));
|
|
}
|
|
//write_log (_T("%d %d\n"), maxx, maxy);
|
|
#endif
|
|
|
|
maxx = maxx * 1000 / fmx;
|
|
maxy = maxy * 1000 / fmy;
|
|
|
|
if (maxx <= 0)
|
|
maxx = 1;
|
|
if (maxy <= 0)
|
|
maxy = 1;
|
|
|
|
x -= diffx;
|
|
if (x < 0)
|
|
x = 0;
|
|
if (x >= maxx)
|
|
x = maxx - 1;
|
|
|
|
y -= diffy;
|
|
if (y < 0)
|
|
y = 0;
|
|
if (y >= maxy)
|
|
y = maxy - 1;
|
|
|
|
//write_log (_T("%d %d %d %d\n"), x, y, maxx, maxy);
|
|
|
|
p[MH_X] = x >> 8;
|
|
p[MH_X + 1] = x;
|
|
p[MH_Y] = y >> 8;
|
|
p[MH_Y + 1] = y;
|
|
p[MH_MAXX] = maxx >> 8;
|
|
p[MH_MAXX + 1] = maxx;
|
|
p[MH_MAXY] = maxy >> 8;
|
|
p[MH_MAXY + 1] = maxy;
|
|
|
|
p[MH_Z] = p[MH_Z + 1] = 0;
|
|
p[MH_MAXZ] = p[MH_MAXZ + 1] = 0;
|
|
p[MH_AX] = p[MH_AX + 1] = 0;
|
|
p[MH_AY] = p[MH_AY + 1] = 0;
|
|
p[MH_AZ] = p[MH_AZ + 1] = 0;
|
|
p[MH_PRESSURE] = p[MH_PRESSURE + 1] = 0;
|
|
p[MH_INPROXIMITY] = p[MH_INPROXIMITY + 1] = 0xff;
|
|
|
|
if (!memcmp (tmp, p + MH_START, MH_END - MH_START))
|
|
return;
|
|
p[MH_CNT]++;
|
|
tablet_data = 1;
|
|
}
|
|
#endif
|
|
|
|
static void mousehack_helper (void)
|
|
{
|
|
int x, y;
|
|
int fdy, fdx, fmx, fmy;
|
|
|
|
if (currprefs.input_magic_mouse == 0 && currprefs.input_tablet < TABLET_MOUSEHACK)
|
|
return;
|
|
#if 0
|
|
if (kickstart_version >= 36) {
|
|
inputdevice_mh_abs_v36 (lastmx, lastmy);
|
|
return;
|
|
}
|
|
#endif
|
|
x = lastmx;
|
|
y = lastmy;
|
|
getgfxoffset (&fdx, &fdy, &fmx, &fmy);
|
|
|
|
|
|
#ifdef PICASSO96
|
|
if (picasso_on) {
|
|
x -= picasso96_state.XOffset;
|
|
y -= picasso96_state.YOffset;
|
|
x = x * fmx / 1000;
|
|
y = y * fmy / 1000;
|
|
x -= fdx * fmx / 1000;
|
|
y -= fdy * fmy / 1000;
|
|
} else
|
|
#endif
|
|
{
|
|
x = x * fmx / 1000;
|
|
y = y * fmy / 1000;
|
|
x -= fdx * fmx / 1000 - 1;
|
|
y -= fdy * fmy / 1000 - 2;
|
|
if (x < 0)
|
|
x = 0;
|
|
if (x >= gfxvidinfo.outbuffer->outwidth)
|
|
x = gfxvidinfo.outbuffer->outwidth - 1;
|
|
if (y < 0)
|
|
y = 0;
|
|
if (y >= gfxvidinfo.outbuffer->outheight)
|
|
y = gfxvidinfo.outbuffer->outheight - 1;
|
|
x = coord_native_to_amiga_x (x);
|
|
y = coord_native_to_amiga_y (y) << 1;
|
|
}
|
|
inputdevice_mh_abs (x, y);
|
|
}
|
|
|
|
static int mouseedge_x, mouseedge_y, mouseedge_time;
|
|
#define MOUSEEDGE_RANGE 100
|
|
#define MOUSEEDGE_TIME 2
|
|
|
|
extern void setmouseactivexy (int,int,int);
|
|
|
|
static int mouseedge (void)
|
|
{
|
|
int x, y, dir;
|
|
uaecptr ib;
|
|
static int melast_x, melast_y;
|
|
static int isnonzero;
|
|
|
|
if (currprefs.input_magic_mouse == 0 || currprefs.input_tablet > 0)
|
|
return 0;
|
|
if (magicmouse_ibase == 0xffffffff)
|
|
return 0;
|
|
dir = 0;
|
|
if (!mouseedge_time) {
|
|
isnonzero = 0;
|
|
goto end;
|
|
}
|
|
ib = get_intuitionbase ();
|
|
if (!ib || get_word (ib + 20) < 31) // version < 31
|
|
return 0;
|
|
x = get_word (ib + 70);
|
|
y = get_word (ib + 68);
|
|
if (x || y)
|
|
isnonzero = 1;
|
|
if (!isnonzero)
|
|
return 0;
|
|
if (melast_x == x) {
|
|
if (mouseedge_x < -MOUSEEDGE_RANGE) {
|
|
mouseedge_x = 0;
|
|
dir |= 1;
|
|
goto end;
|
|
}
|
|
if (mouseedge_x > MOUSEEDGE_RANGE) {
|
|
mouseedge_x = 0;
|
|
dir |= 2;
|
|
goto end;
|
|
}
|
|
} else {
|
|
mouseedge_x = 0;
|
|
melast_x = x;
|
|
}
|
|
if (melast_y == y) {
|
|
if (mouseedge_y < -MOUSEEDGE_RANGE) {
|
|
mouseedge_y = 0;
|
|
dir |= 4;
|
|
goto end;
|
|
}
|
|
if (mouseedge_y > MOUSEEDGE_RANGE) {
|
|
mouseedge_y = 0;
|
|
dir |= 8;
|
|
goto end;
|
|
}
|
|
} else {
|
|
mouseedge_y = 0;
|
|
melast_y = y;
|
|
}
|
|
return 1;
|
|
|
|
end:
|
|
mouseedge_time = 0;
|
|
if (dir) {
|
|
if (!picasso_on) {
|
|
int aw = 0, ah = 0, dx, dy;
|
|
get_custom_mouse_limits (&aw, &ah, &dx, &dy, dimensioninfo_dbl);
|
|
x += dx;
|
|
y += dy;
|
|
}
|
|
if (!dmaen (DMA_SPRITE))
|
|
setmouseactivexy (x, y, 0);
|
|
else
|
|
setmouseactivexy (x, y, dir);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
int magicmouse_alive (void)
|
|
{
|
|
return mouseedge_alive > 0;
|
|
}
|
|
|
|
STATIC_INLINE int adjust (int val)
|
|
{
|
|
if (val > 127)
|
|
return 127;
|
|
else if (val < -127)
|
|
return -127;
|
|
return val;
|
|
}
|
|
|
|
static int getbuttonstate (int joy, int button)
|
|
{
|
|
return (joybutton[joy] & (1 << button)) ? 1 : 0;
|
|
}
|
|
|
|
static int getvelocity (int num, int subnum, int pct)
|
|
{
|
|
int val;
|
|
int v;
|
|
|
|
if (pct > 1000)
|
|
pct = 1000;
|
|
val = mouse_delta[num][subnum];
|
|
v = val * pct / 1000;
|
|
if (!v) {
|
|
if (val < -maxvpos / 2)
|
|
v = -2;
|
|
else if (val < 0)
|
|
v = -1;
|
|
else if (val > maxvpos / 2)
|
|
v = 2;
|
|
else if (val > 0)
|
|
v = 1;
|
|
}
|
|
if (!mouse_deltanoreset[num][subnum]) {
|
|
mouse_delta[num][subnum] -= v;
|
|
gui_gameport_axis_change (num, subnum * 2 + 0, 0, -1);
|
|
gui_gameport_axis_change (num, subnum * 2 + 1, 0, -1);
|
|
}
|
|
return v;
|
|
}
|
|
|
|
static void mouseupdate (int pct, int vsync)
|
|
{
|
|
int v, i;
|
|
int max = 120;
|
|
static int mxd, myd;
|
|
|
|
if (vsync) {
|
|
if (mxd < 0) {
|
|
if (mouseedge_x > 0)
|
|
mouseedge_x = 0;
|
|
else
|
|
mouseedge_x += mxd;
|
|
mouseedge_time = MOUSEEDGE_TIME;
|
|
}
|
|
if (mxd > 0) {
|
|
if (mouseedge_x < 0)
|
|
mouseedge_x = 0;
|
|
else
|
|
mouseedge_x += mxd;
|
|
mouseedge_time = MOUSEEDGE_TIME;
|
|
}
|
|
if (myd < 0) {
|
|
if (mouseedge_y > 0)
|
|
mouseedge_y = 0;
|
|
else
|
|
mouseedge_y += myd;
|
|
mouseedge_time = MOUSEEDGE_TIME;
|
|
}
|
|
if (myd > 0) {
|
|
if (mouseedge_y < 0)
|
|
mouseedge_y = 0;
|
|
else
|
|
mouseedge_y += myd;
|
|
mouseedge_time = MOUSEEDGE_TIME;
|
|
}
|
|
if (mouseedge_time > 0) {
|
|
mouseedge_time--;
|
|
if (mouseedge_time == 0) {
|
|
mouseedge_x = 0;
|
|
mouseedge_y = 0;
|
|
}
|
|
}
|
|
mxd = 0;
|
|
myd = 0;
|
|
}
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
|
|
if (mouse_port[i]) {
|
|
|
|
v = getvelocity (i, 0, pct);
|
|
mxd += v;
|
|
mouse_x[i] += v;
|
|
|
|
v = getvelocity (i, 1, pct);
|
|
myd += v;
|
|
mouse_y[i] += v;
|
|
|
|
v = getvelocity (i, 2, pct);
|
|
if (v > 0)
|
|
record_key (0x7a << 1);
|
|
else if (v < 0)
|
|
record_key (0x7b << 1);
|
|
if (!mouse_deltanoreset[i][2])
|
|
mouse_delta[i][2] = 0;
|
|
|
|
if (mouse_frame_x[i] - mouse_x[i] > max)
|
|
mouse_x[i] = mouse_frame_x[i] - max;
|
|
if (mouse_frame_x[i] - mouse_x[i] < -max)
|
|
mouse_x[i] = mouse_frame_x[i] + max;
|
|
|
|
if (mouse_frame_y[i] - mouse_y[i] > max)
|
|
mouse_y[i] = mouse_frame_y[i] - max;
|
|
if (mouse_frame_y[i] - mouse_y[i] < -max)
|
|
mouse_y[i] = mouse_frame_y[i] + max;
|
|
}
|
|
|
|
if (!vsync) {
|
|
mouse_frame_x[i] = mouse_x[i];
|
|
mouse_frame_y[i] = mouse_y[i];
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
static int input_vpos, input_frame;
|
|
extern int vpos;
|
|
static void readinput (void)
|
|
{
|
|
uae_u32 totalvpos;
|
|
int diff;
|
|
|
|
totalvpos = input_frame * current_maxvpos () + vpos;
|
|
diff = totalvpos - input_vpos;
|
|
if (diff > 0) {
|
|
if (diff < 10) {
|
|
mouseupdate (0, 0);
|
|
} else {
|
|
mouseupdate (diff * 1000 / current_maxvpos (), 0);
|
|
}
|
|
}
|
|
input_vpos = totalvpos;
|
|
|
|
}
|
|
|
|
static void joymousecounter (int joy)
|
|
{
|
|
int left = 1, right = 1, top = 1, bot = 1;
|
|
int b9, b8, b1, b0;
|
|
int cntx, cnty, ocntx, ocnty;
|
|
|
|
if (joydir[joy] & DIR_LEFT)
|
|
left = 0;
|
|
if (joydir[joy] & DIR_RIGHT)
|
|
right = 0;
|
|
if (joydir[joy] & DIR_UP)
|
|
top = 0;
|
|
if (joydir[joy] & DIR_DOWN)
|
|
bot = 0;
|
|
|
|
b0 = (bot ^ right) ? 1 : 0;
|
|
b1 = (right ^ 1) ? 2 : 0;
|
|
b8 = (top ^ left) ? 1 : 0;
|
|
b9 = (left ^ 1) ? 2 : 0;
|
|
|
|
cntx = b0 | b1;
|
|
cnty = b8 | b9;
|
|
ocntx = mouse_x[joy] & 3;
|
|
ocnty = mouse_y[joy] & 3;
|
|
|
|
if (cntx == 3 && ocntx == 0)
|
|
mouse_x[joy] -= 4;
|
|
else if (cntx == 0 && ocntx == 3)
|
|
mouse_x[joy] += 4;
|
|
mouse_x[joy] = (mouse_x[joy] & 0xfc) | cntx;
|
|
|
|
if (cnty == 3 && ocnty == 0)
|
|
mouse_y[joy] -= 4;
|
|
else if (cnty == 0 && ocnty == 3)
|
|
mouse_y[joy] += 4;
|
|
mouse_y[joy] = (mouse_y[joy] & 0xfc) | cnty;
|
|
|
|
if (!left || !right || !top || !bot) {
|
|
mouse_frame_x[joy] = mouse_x[joy];
|
|
mouse_frame_y[joy] = mouse_y[joy];
|
|
}
|
|
}
|
|
|
|
static uae_u16 getjoystate (int joy)
|
|
{
|
|
uae_u16 v;
|
|
|
|
v = (uae_u8)mouse_x[joy] | (mouse_y[joy] << 8);
|
|
#ifdef DONGLE_DEBUG
|
|
if (notinrom ())
|
|
write_log (_T("JOY%dDAT %04X %s\n"), joy, v, debuginfo (0));
|
|
#endif
|
|
if (inputdevice_logging & 2)
|
|
write_log (_T("JOY%dDAT=%04x %08x\n"), joy, v, M68K_GETPC);
|
|
return v;
|
|
}
|
|
|
|
uae_u16 JOY0DAT (void)
|
|
{
|
|
uae_u16 v;
|
|
readinput ();
|
|
v = getjoystate (0);
|
|
v = dongle_joydat (0, v);
|
|
return v;
|
|
}
|
|
|
|
uae_u16 JOY1DAT (void)
|
|
{
|
|
uae_u16 v;
|
|
readinput ();
|
|
v = getjoystate (1);
|
|
v = dongle_joydat (1, v);
|
|
|
|
if (inputrecord_debug & 2) {
|
|
if (input_record > 0)
|
|
inprec_recorddebug_cia (v, -1, m68k_getpc ());
|
|
else if (input_play > 0)
|
|
inprec_playdebug_cia (v, -1, m68k_getpc ());
|
|
}
|
|
|
|
return v;
|
|
}
|
|
|
|
uae_u16 JOYGET (int num)
|
|
{
|
|
uae_u16 v;
|
|
v = getjoystate (num);
|
|
v = dongle_joydat (num, v);
|
|
return v;
|
|
}
|
|
|
|
void JOYSET (int num, uae_u16 dat)
|
|
{
|
|
mouse_x[num] = dat & 0xff;
|
|
mouse_y[num] = (dat >> 8) & 0xff;
|
|
mouse_frame_x[num] = mouse_x[num];
|
|
mouse_frame_y[num] = mouse_y[num];
|
|
}
|
|
|
|
void JOYTEST (uae_u16 v)
|
|
{
|
|
mouse_x[0] &= 3;
|
|
mouse_y[0] &= 3;
|
|
mouse_x[1] &= 3;
|
|
mouse_y[1] &= 3;
|
|
mouse_x[0] |= v & 0xFC;
|
|
mouse_x[1] |= v & 0xFC;
|
|
mouse_y[0] |= (v >> 8) & 0xFC;
|
|
mouse_y[1] |= (v >> 8) & 0xFC;
|
|
mouse_frame_x[0] = mouse_x[0];
|
|
mouse_frame_y[0] = mouse_y[0];
|
|
mouse_frame_x[1] = mouse_x[1];
|
|
mouse_frame_y[1] = mouse_y[1];
|
|
dongle_joytest (v);
|
|
if (inputdevice_logging & 2)
|
|
write_log (_T("JOYTEST: %04X PC=%x\n"), v , M68K_GETPC);
|
|
}
|
|
|
|
static uae_u8 parconvert (uae_u8 v, int jd, int shift)
|
|
{
|
|
if (jd & DIR_UP)
|
|
v &= ~(1 << shift);
|
|
if (jd & DIR_DOWN)
|
|
v &= ~(2 << shift);
|
|
if (jd & DIR_LEFT)
|
|
v &= ~(4 << shift);
|
|
if (jd & DIR_RIGHT)
|
|
v &= ~(8 << shift);
|
|
return v;
|
|
}
|
|
|
|
/* io-pins floating: dir=1 -> return data, dir=0 -> always return 1 */
|
|
uae_u8 handle_parport_joystick (int port, uae_u8 pra, uae_u8 dra)
|
|
{
|
|
uae_u8 v;
|
|
switch (port)
|
|
{
|
|
case 0:
|
|
v = (pra & dra) | (dra ^ 0xff);
|
|
if (parport_joystick_enabled) {
|
|
v = parconvert (v, joydir[2], 0);
|
|
v = parconvert (v, joydir[3], 4);
|
|
}
|
|
return v;
|
|
case 1:
|
|
v = ((pra & dra) | (dra ^ 0xff)) & 0x7;
|
|
if (parport_joystick_enabled) {
|
|
if (getbuttonstate (2, 0))
|
|
v &= ~4;
|
|
if (getbuttonstate (3, 0))
|
|
v &= ~1;
|
|
if (getbuttonstate (2, 1) || getbuttonstate (3, 1))
|
|
v &= ~2; /* spare */
|
|
}
|
|
return v;
|
|
default:
|
|
abort ();
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/* p5 is 1 or floating = cd32 2-button mode */
|
|
static bool cd32padmode (uae_u16 p5dir, uae_u16 p5dat)
|
|
{
|
|
if (!(potgo_value & p5dir) || ((potgo_value & p5dat) && (potgo_value & p5dir)))
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
static bool is_joystick_pullup (int joy)
|
|
{
|
|
return joymodes[joy] == JSEM_MODE_GAMEPAD;
|
|
}
|
|
static bool is_mouse_pullup (int joy)
|
|
{
|
|
return mouse_pullup;
|
|
}
|
|
|
|
static void charge_cap (int joy, int idx, int charge)
|
|
{
|
|
if (charge < -1 || charge > 1)
|
|
charge = charge * 80;
|
|
pot_cap[joy][idx] += charge;
|
|
if (pot_cap[joy][idx] < 0)
|
|
pot_cap[joy][idx] = 0;
|
|
if (pot_cap[joy][idx] > 511)
|
|
pot_cap[joy][idx] = 511;
|
|
}
|
|
|
|
static void cap_check (void)
|
|
{
|
|
int joy, i;
|
|
|
|
for (joy = 0; joy < 2; joy++) {
|
|
for (i = 0; i < 2; i++) {
|
|
int charge = 0, dong, joypot;
|
|
uae_u16 pdir = 0x0200 << (joy * 4 + i * 2); /* output enable */
|
|
uae_u16 pdat = 0x0100 << (joy * 4 + i * 2); /* data */
|
|
uae_u16 p5dir = 0x0200 << (joy * 4);
|
|
uae_u16 p5dat = 0x0100 << (joy * 4);
|
|
int isbutton = getbuttonstate (joy, i == 0 ? JOYBUTTON_3 : JOYBUTTON_2);
|
|
|
|
if (cd32_pad_enabled[joy]) {
|
|
// only red and blue can be read if CD32 pad and only if it is in normal pad mode
|
|
isbutton |= getbuttonstate (joy, JOYBUTTON_CD32_BLUE);
|
|
// CD32 pad 3rd button line (P5) is always floating
|
|
if (i == 0)
|
|
isbutton = 0;
|
|
if (cd32padmode (p5dir, p5dat))
|
|
continue;
|
|
}
|
|
|
|
dong = dongle_analogjoy (joy, i);
|
|
if (dong >= 0) {
|
|
isbutton = 0;
|
|
joypot = dong;
|
|
if (pot_cap[joy][i] < joypot)
|
|
charge = 1; // slow charge via dongle resistor
|
|
} else {
|
|
joypot = joydirpot[joy][i];
|
|
if (analog_port[joy][i] && pot_cap[joy][i] < joypot)
|
|
charge = 1; // slow charge via pot variable resistor
|
|
if ((is_joystick_pullup (joy) && digital_port[joy][i]) || (is_mouse_pullup (joy) && mouse_port[joy]))
|
|
charge = 1; // slow charge via pull-up resistor
|
|
}
|
|
if (!(potgo_value & pdir)) { // input?
|
|
if (pot_dat_act[joy][i])
|
|
pot_dat[joy][i]++;
|
|
/* first 7 or 8 lines after potgo has been started = discharge cap */
|
|
if (pot_dat_act[joy][i] == 1) {
|
|
if (pot_dat[joy][i] < (currprefs.ntscmode ? POTDAT_DELAY_NTSC : POTDAT_DELAY_PAL)) {
|
|
charge = -2; /* fast discharge delay */
|
|
} else {
|
|
pot_dat_act[joy][i] = 2;
|
|
pot_dat[joy][i] = 0;
|
|
}
|
|
}
|
|
if (dong >= 0) {
|
|
if (pot_dat_act[joy][i] == 2 && pot_cap[joy][i] >= joypot)
|
|
pot_dat_act[joy][i] = 0;
|
|
} else {
|
|
if (analog_port[joy][i] && pot_dat_act[joy][i] == 2 && pot_cap[joy][i] >= joypot)
|
|
pot_dat_act[joy][i] = 0;
|
|
if ((digital_port[joy][i] || mouse_port[joy]) && pot_dat_act[joy][i] == 2) {
|
|
if (pot_cap[joy][i] >= 10 && !isbutton)
|
|
pot_dat_act[joy][i] = 0;
|
|
}
|
|
}
|
|
} else { // output?
|
|
charge = (potgo_value & pdat) ? 2 : -2; /* fast (dis)charge if output */
|
|
if (potgo_value & pdat)
|
|
pot_dat_act[joy][i] = 0; // instant stop if output+high
|
|
if (isbutton)
|
|
pot_dat[joy][i]++; // "free running" if output+low
|
|
}
|
|
|
|
if (isbutton)
|
|
charge = -2; // button press overrides everything
|
|
|
|
if (currprefs.cs_cdtvcd) {
|
|
/* CDTV P9 is not floating */
|
|
if (!(potgo_value & pdir) && i == 1 && charge == 0)
|
|
charge = 2;
|
|
}
|
|
// CD32 pad in 2-button mode: blue button is not floating
|
|
if (cd32_pad_enabled[joy] && i == 1 && charge == 0)
|
|
charge = 2;
|
|
|
|
/* official Commodore mouse has pull-up resistors in button lines
|
|
* NOTE: 3rd party mice may not have pullups! */
|
|
if (dong < 0 && (is_mouse_pullup (joy) && mouse_port[joy] && digital_port[joy][i]) && charge == 0)
|
|
charge = 2;
|
|
/* emulate pullup resistor if button mapped because there too many broken
|
|
* programs that read second button in input-mode (and most 2+ button pads have
|
|
* pullups)
|
|
*/
|
|
if (dong < 0 && (is_joystick_pullup (joy) && digital_port[joy][i]) && charge == 0)
|
|
charge = 2;
|
|
|
|
charge_cap (joy, i, charge);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
uae_u8 handle_joystick_buttons (uae_u8 pra, uae_u8 dra)
|
|
{
|
|
uae_u8 but = 0;
|
|
int i;
|
|
|
|
cap_check ();
|
|
for (i = 0; i < 2; i++) {
|
|
int mask = 0x40 << i;
|
|
if (cd32_pad_enabled[i]) {
|
|
uae_u16 p5dir = 0x0200 << (i * 4);
|
|
uae_u16 p5dat = 0x0100 << (i * 4);
|
|
but |= mask;
|
|
if (!cd32padmode (p5dir, p5dat)) {
|
|
if (getbuttonstate (i, JOYBUTTON_CD32_RED) || getbuttonstate (i, JOYBUTTON_1))
|
|
but &= ~mask;
|
|
}
|
|
} else {
|
|
if (!getbuttonstate (i, JOYBUTTON_1))
|
|
but |= mask;
|
|
if (bouncy && cycles_in_range (bouncy_cycles)) {
|
|
but &= ~mask;
|
|
if (uaerand () & 1)
|
|
but |= mask;
|
|
}
|
|
if (dra & mask)
|
|
but = (but & ~mask) | (pra & mask);
|
|
}
|
|
}
|
|
|
|
if (inputdevice_logging & 4) {
|
|
static uae_u8 old;
|
|
if (but != old)
|
|
write_log (_T("BFE001: %02X:%02X %x\n"), dra, but, M68K_GETPC);
|
|
old = but;
|
|
}
|
|
return but;
|
|
}
|
|
|
|
/* joystick 1 button 1 is used as a output for incrementing shift register */
|
|
void handle_cd32_joystick_cia (uae_u8 pra, uae_u8 dra)
|
|
{
|
|
static int oldstate[2];
|
|
int i;
|
|
|
|
cap_check ();
|
|
for (i = 0; i < 2; i++) {
|
|
uae_u8 but = 0x40 << i;
|
|
uae_u16 p5dir = 0x0200 << (i * 4); /* output enable P5 */
|
|
uae_u16 p5dat = 0x0100 << (i * 4); /* data P5 */
|
|
if (cd32padmode (p5dir, p5dat)) {
|
|
if ((dra & but) && (pra & but) != oldstate[i]) {
|
|
if (!(pra & but)) {
|
|
cd32_shifter[i]--;
|
|
if (cd32_shifter[i] < 0)
|
|
cd32_shifter[i] = 0;
|
|
}
|
|
}
|
|
}
|
|
oldstate[i] = pra & but;
|
|
}
|
|
}
|
|
|
|
/* joystick port 1 button 2 is input for button state */
|
|
static uae_u16 handle_joystick_potgor (uae_u16 potgor)
|
|
{
|
|
int i;
|
|
|
|
cap_check ();
|
|
for (i = 0; i < 2; i++) {
|
|
uae_u16 p9dir = 0x0800 << (i * 4); /* output enable P9 */
|
|
uae_u16 p9dat = 0x0400 << (i * 4); /* data P9 */
|
|
uae_u16 p5dir = 0x0200 << (i * 4); /* output enable P5 */
|
|
uae_u16 p5dat = 0x0100 << (i * 4); /* data P5 */
|
|
|
|
if (cd32_pad_enabled[i] && cd32padmode (p5dir, p5dat)) {
|
|
|
|
/* p5 is floating in input-mode */
|
|
potgor &= ~p5dat;
|
|
potgor |= potgo_value & p5dat;
|
|
if (!(potgo_value & p9dir))
|
|
potgor |= p9dat;
|
|
/* (P5 output and 1) or floating -> shift register is kept reset (Blue button) */
|
|
if (!(potgo_value & p5dir) || ((potgo_value & p5dat) && (potgo_value & p5dir)))
|
|
cd32_shifter[i] = 8;
|
|
/* shift at 1 == return one, >1 = return button states */
|
|
if (cd32_shifter[i] == 0)
|
|
potgor &= ~p9dat; /* shift at zero == return zero */
|
|
if (cd32_shifter[i] >= 2 && (joybutton[i] & ((1 << JOYBUTTON_CD32_PLAY) << (cd32_shifter[i] - 2))))
|
|
potgor &= ~p9dat;
|
|
|
|
} else {
|
|
|
|
potgor &= ~p5dat;
|
|
if (pot_cap[i][0] > 100)
|
|
potgor |= p5dat;
|
|
|
|
|
|
if (!cd32_pad_enabled[i] || !cd32padmode (p5dir, p5dat)) {
|
|
potgor &= ~p9dat;
|
|
if (pot_cap[i][1] > 100)
|
|
potgor |= p9dat;
|
|
}
|
|
|
|
}
|
|
}
|
|
return potgor;
|
|
}
|
|
|
|
|
|
static int inputdelay;
|
|
|
|
void inputdevice_read (void)
|
|
{
|
|
do {
|
|
handle_msgpump ();
|
|
idev[IDTYPE_MOUSE].read ();
|
|
idev[IDTYPE_JOYSTICK].read ();
|
|
idev[IDTYPE_KEYBOARD].read ();
|
|
} while (handle_msgpump ());
|
|
}
|
|
|
|
static int handle_custom_event (const TCHAR *custom)
|
|
{
|
|
TCHAR *p, *buf, *nextp;
|
|
|
|
if (custom == NULL)
|
|
return 0;
|
|
write_log (_T("%s\n"), custom);
|
|
p = buf = my_strdup (custom);
|
|
while (p && *p) {
|
|
TCHAR *p2;
|
|
if (*p != '\"')
|
|
break;
|
|
p++;
|
|
p2 = p;
|
|
while (*p2 != '\"' && *p2 != 0)
|
|
p2++;
|
|
if (*p2 == '\"') {
|
|
*p2++ = 0;
|
|
nextp = p2 + 1;
|
|
while (*nextp == ' ')
|
|
nextp++;
|
|
}
|
|
//write_log (L"-> '%s'\n", p);
|
|
cfgfile_parse_line (&changed_prefs, p, 0);
|
|
p = nextp;
|
|
}
|
|
xfree (buf);
|
|
config_changed = 1;
|
|
return 0;
|
|
}
|
|
|
|
void inputdevice_hsync (void)
|
|
{
|
|
static int cnt;
|
|
cap_check ();
|
|
|
|
#ifdef CATWEASEL
|
|
catweasel_hsync ();
|
|
#endif
|
|
|
|
for (int i = 0; i < INPUT_QUEUE_SIZE; i++) {
|
|
struct input_queue_struct *iq = &input_queue[i];
|
|
if (iq->linecnt > 0) {
|
|
iq->linecnt--;
|
|
if (iq->linecnt == 0) {
|
|
if (iq->state)
|
|
iq->state = 0;
|
|
else
|
|
iq->state = iq->storedstate;
|
|
if (iq->custom)
|
|
handle_custom_event (iq->custom);
|
|
if (iq->evt)
|
|
handle_input_event (iq->evt, iq->state, iq->max, 0, false, true);
|
|
iq->linecnt = iq->nextlinecnt;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (bouncy && get_cycles () > bouncy_cycles)
|
|
bouncy = 0;
|
|
|
|
if (input_record && input_record != INPREC_RECORD_PLAYING) {
|
|
if (vpos == 0)
|
|
inputdevice_read ();
|
|
inputdelay = 0;
|
|
}
|
|
if (input_play) {
|
|
inprec_playdiskchange ();
|
|
int nr, state, max, autofire;
|
|
while (inprec_playevent (&nr, &state, &max, &autofire))
|
|
handle_input_event (nr, state, max, autofire, false, true);
|
|
if (vpos == 0)
|
|
handle_msgpump ();
|
|
}
|
|
if (!input_record && !input_play) {
|
|
if ((++cnt & 63) == 63 ) {
|
|
inputdevice_read ();
|
|
} else if (inputdelay > 0) {
|
|
inputdelay--;
|
|
if (inputdelay == 0)
|
|
inputdevice_read ();
|
|
}
|
|
}
|
|
}
|
|
|
|
static uae_u16 POTDAT (int joy)
|
|
{
|
|
uae_u16 v = (pot_dat[joy][1] << 8) | pot_dat[joy][0];
|
|
if (inputdevice_logging & 16)
|
|
write_log (_T("POTDAT%d: %04X %08X\n"), joy, v, M68K_GETPC);
|
|
return v;
|
|
}
|
|
|
|
uae_u16 POT0DAT (void)
|
|
{
|
|
return POTDAT (0);
|
|
}
|
|
uae_u16 POT1DAT (void)
|
|
{
|
|
return POTDAT (1);
|
|
}
|
|
|
|
/* direction=input, data pin floating, last connected logic level or previous status
|
|
* written when direction was ouput
|
|
* otherwise it is currently connected logic level.
|
|
* direction=output, data pin is current value, forced to zero if joystick button is pressed
|
|
* it takes some tens of microseconds before data pin changes state
|
|
*/
|
|
|
|
void POTGO (uae_u16 v)
|
|
{
|
|
int i, j;
|
|
|
|
if (inputdevice_logging & 16)
|
|
write_log (_T("POTGO_W: %04X %08X\n"), v, M68K_GETPC);
|
|
#ifdef DONGLE_DEBUG
|
|
if (notinrom ())
|
|
write_log (_T("POTGO %04X %s\n"), v, debuginfo(0));
|
|
#endif
|
|
dongle_potgo (v);
|
|
potgo_value = potgo_value & 0x5500; /* keep state of data bits */
|
|
potgo_value |= v & 0xaa00; /* get new direction bits */
|
|
for (i = 0; i < 8; i += 2) {
|
|
uae_u16 dir = 0x0200 << i;
|
|
if (v & dir) {
|
|
uae_u16 data = 0x0100 << i;
|
|
potgo_value &= ~data;
|
|
potgo_value |= v & data;
|
|
}
|
|
}
|
|
for (i = 0; i < 2; i++) {
|
|
if (cd32_pad_enabled[i]) {
|
|
uae_u16 p5dir = 0x0200 << (i * 4); /* output enable P5 */
|
|
uae_u16 p5dat = 0x0100 << (i * 4); /* data P5 */
|
|
if (!(potgo_value & p5dir) || ((potgo_value & p5dat) && (potgo_value & p5dir)))
|
|
cd32_shifter[i] = 8;
|
|
}
|
|
}
|
|
if (v & 1) {
|
|
for (i = 0; i < 2; i++) {
|
|
for (j = 0; j < 2; j++) {
|
|
pot_dat_act[i][j] = 1;
|
|
pot_dat[i][j] = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
uae_u16 POTGOR (void)
|
|
{
|
|
uae_u16 v;
|
|
|
|
v = handle_joystick_potgor (potgo_value) & 0x5500;
|
|
v = dongle_potgor (v);
|
|
#ifdef DONGLE_DEBUG
|
|
if (notinrom ())
|
|
write_log (_T("POTGOR %04X %s\n"), v, debuginfo(0));
|
|
#endif
|
|
if (inputdevice_logging & 16)
|
|
write_log (_T("POTGO_R: %04X %08X %d\n"), v, M68K_GETPC, cd32_shifter[1]);
|
|
return v;
|
|
}
|
|
|
|
static int check_input_queue (int evt)
|
|
{
|
|
struct input_queue_struct *iq;
|
|
int i;
|
|
for (i = 0; i < INPUT_QUEUE_SIZE; i++) {
|
|
iq = &input_queue[i];
|
|
if (iq->evt == evt)
|
|
return i;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
static void queue_input_event (int evt, const TCHAR *custom, int state, int max, int linecnt, int autofire)
|
|
{
|
|
struct input_queue_struct *iq;
|
|
int idx = check_input_queue (evt);
|
|
|
|
if (state < 0 && idx >= 0) {
|
|
iq = &input_queue[idx];
|
|
iq->nextlinecnt = -1;
|
|
iq->linecnt = -1;
|
|
iq->evt = 0;
|
|
if (iq->state == 0 && evt > 0)
|
|
handle_input_event (evt, 0, 1, 0, false, false);
|
|
} else if (state >= 0 && idx < 0) {
|
|
if (evt == 0 && custom == NULL)
|
|
return;
|
|
for (idx = 0; idx < INPUT_QUEUE_SIZE; idx++) {
|
|
iq = &input_queue[idx];
|
|
if (iq->linecnt < 0)
|
|
break;
|
|
}
|
|
if (idx == INPUT_QUEUE_SIZE) {
|
|
write_log (_T("input queue overflow\n"));
|
|
return;
|
|
}
|
|
xfree (iq->custom);
|
|
iq->custom = NULL;
|
|
if (custom)
|
|
iq->custom = my_strdup (custom);
|
|
iq->evt = evt;
|
|
iq->state = iq->storedstate = state;
|
|
iq->max = max;
|
|
iq->linecnt = linecnt;
|
|
iq->nextlinecnt = autofire > 0 ? linecnt : -1;
|
|
}
|
|
}
|
|
|
|
static uae_u8 keybuf[256];
|
|
static int inputcode_pending, inputcode_pending_state;
|
|
|
|
void inputdevice_release_all_keys (void)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 0x80; i++) {
|
|
if (keybuf[i] != 0) {
|
|
keybuf[i] = 0;
|
|
record_key (i << 1|1);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void inputdevice_add_inputcode (int code, int state)
|
|
{
|
|
inputcode_pending = code;
|
|
inputcode_pending_state = state;
|
|
}
|
|
|
|
void inputdevice_do_keyboard (int code, int state)
|
|
{
|
|
#ifdef CDTV
|
|
if (code >= 0x72 && code <= 0x77) { // CDTV keys
|
|
if (cdtv_front_panel (-1)) {
|
|
// front panel active
|
|
if (!state)
|
|
return;
|
|
cdtv_front_panel (code - 0x72);
|
|
return;
|
|
}
|
|
}
|
|
#endif
|
|
if (code < 0x80) {
|
|
uae_u8 key = code | (state ? 0x00 : 0x80);
|
|
keybuf[key & 0x7f] = (key & 0x80) ? 0 : 1;
|
|
if (key == AK_RESETWARNING) {
|
|
resetwarning_do (0);
|
|
return;
|
|
} else if ((keybuf[AK_CTRL] || keybuf[AK_RCTRL]) && keybuf[AK_LAMI] && keybuf[AK_RAMI]) {
|
|
int r = keybuf[AK_LALT] | keybuf[AK_RALT];
|
|
if (!r && currprefs.cs_resetwarning && resetwarning_do (1))
|
|
return;
|
|
memset (keybuf, 0, sizeof (keybuf));
|
|
send_internalevent (INTERNALEVENT_KBRESET);
|
|
uae_reset (r);
|
|
}
|
|
if (record_key ((uae_u8)((key << 1) | (key >> 7)))) {
|
|
if (inputdevice_logging & 1)
|
|
write_log (_T("Amiga key %02X %d\n"), key & 0x7f, key >> 7);
|
|
}
|
|
return;
|
|
}
|
|
inputdevice_add_inputcode (code, state);
|
|
}
|
|
|
|
// these need cpu trace data
|
|
static bool needcputrace (int code)
|
|
{
|
|
switch (code)
|
|
{
|
|
case AKS_ENTERGUI:
|
|
case AKS_STATECAPTURE:
|
|
case AKS_STATESAVEQUICK:
|
|
case AKS_STATESAVEQUICK1:
|
|
case AKS_STATESAVEQUICK2:
|
|
case AKS_STATESAVEQUICK3:
|
|
case AKS_STATESAVEQUICK4:
|
|
case AKS_STATESAVEQUICK5:
|
|
case AKS_STATESAVEQUICK6:
|
|
case AKS_STATESAVEQUICK7:
|
|
case AKS_STATESAVEQUICK8:
|
|
case AKS_STATESAVEQUICK9:
|
|
case AKS_STATESAVEDIALOG:
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void inputdevice_handle_inputcode (void)
|
|
{
|
|
static int swapperslot;
|
|
int code = inputcode_pending;
|
|
int state = inputcode_pending_state;
|
|
static int tracer_enable;
|
|
|
|
if (code == 0)
|
|
goto end;
|
|
if (needcputrace (code) && can_cpu_tracer () == true && is_cpu_tracer () == false && !input_play && !input_record && !debugging) {
|
|
if (set_cpu_tracer (true)) {
|
|
tracer_enable = 1;
|
|
return; // wait for next frame
|
|
}
|
|
}
|
|
|
|
inputcode_pending = 0;
|
|
|
|
if (vpos != 0)
|
|
write_log (_T("inputcode=%d but vpos = %d"), code, vpos);
|
|
|
|
#ifdef ARCADIA
|
|
switch (code)
|
|
{
|
|
case AKS_ARCADIADIAGNOSTICS:
|
|
arcadia_flag &= ~1;
|
|
arcadia_flag |= state ? 1 : 0;
|
|
break;
|
|
case AKS_ARCADIAPLY1:
|
|
arcadia_flag &= ~4;
|
|
arcadia_flag |= state ? 4 : 0;
|
|
break;
|
|
case AKS_ARCADIAPLY2:
|
|
arcadia_flag &= ~2;
|
|
arcadia_flag |= state ? 2 : 0;
|
|
break;
|
|
case AKS_ARCADIACOIN1:
|
|
if (state)
|
|
arcadia_coin[0]++;
|
|
break;
|
|
case AKS_ARCADIACOIN2:
|
|
if (state)
|
|
arcadia_coin[1]++;
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
if (!state)
|
|
return;
|
|
switch (code)
|
|
{
|
|
case AKS_ENTERGUI:
|
|
gui_display (-1);
|
|
setsystime ();
|
|
break;
|
|
case AKS_SCREENSHOT_FILE:
|
|
screenshot (1, 1);
|
|
break;
|
|
case AKS_SCREENSHOT_CLIPBOARD:
|
|
screenshot (0, 1);
|
|
break;
|
|
#ifdef ACTION_REPLAY
|
|
case AKS_FREEZEBUTTON:
|
|
action_replay_freeze ();
|
|
break;
|
|
#endif
|
|
case AKS_FLOPPY0:
|
|
gui_display (0);
|
|
setsystime ();
|
|
break;
|
|
case AKS_FLOPPY1:
|
|
gui_display (1);
|
|
setsystime ();
|
|
break;
|
|
case AKS_FLOPPY2:
|
|
gui_display (2);
|
|
setsystime ();
|
|
break;
|
|
case AKS_FLOPPY3:
|
|
gui_display (3);
|
|
setsystime ();
|
|
break;
|
|
case AKS_EFLOPPY0:
|
|
disk_eject (0);
|
|
break;
|
|
case AKS_EFLOPPY1:
|
|
disk_eject (1);
|
|
break;
|
|
case AKS_EFLOPPY2:
|
|
disk_eject (2);
|
|
break;
|
|
case AKS_EFLOPPY3:
|
|
disk_eject (3);
|
|
break;
|
|
case AKS_IRQ7:
|
|
NMI_delayed ();
|
|
break;
|
|
case AKS_PAUSE:
|
|
pausemode (-1);
|
|
break;
|
|
case AKS_WARP:
|
|
warpmode (-1);
|
|
break;
|
|
case AKS_INHIBITSCREEN:
|
|
toggle_inhibit_frame (IHF_SCROLLLOCK);
|
|
break;
|
|
case AKS_STATEREWIND:
|
|
savestate_dorewind (-2);
|
|
break;
|
|
case AKS_STATECURRENT:
|
|
savestate_dorewind (-1);
|
|
break;
|
|
case AKS_STATECAPTURE:
|
|
savestate_capture (1);
|
|
break;
|
|
case AKS_VOLDOWN:
|
|
sound_volume (-1);
|
|
break;
|
|
case AKS_VOLUP:
|
|
sound_volume (1);
|
|
break;
|
|
case AKS_VOLMUTE:
|
|
sound_mute (-1);
|
|
break;
|
|
case AKS_MVOLDOWN:
|
|
master_sound_volume (-1);
|
|
break;
|
|
case AKS_MVOLUP:
|
|
master_sound_volume (1);
|
|
break;
|
|
case AKS_MVOLMUTE:
|
|
master_sound_volume (0);
|
|
break;
|
|
case AKS_QUIT:
|
|
uae_quit ();
|
|
break;
|
|
case AKS_SOFTRESET:
|
|
uae_reset (0);
|
|
break;
|
|
case AKS_HARDRESET:
|
|
uae_reset (1);
|
|
break;
|
|
case AKS_STATESAVEQUICK:
|
|
case AKS_STATESAVEQUICK1:
|
|
case AKS_STATESAVEQUICK2:
|
|
case AKS_STATESAVEQUICK3:
|
|
case AKS_STATESAVEQUICK4:
|
|
case AKS_STATESAVEQUICK5:
|
|
case AKS_STATESAVEQUICK6:
|
|
case AKS_STATESAVEQUICK7:
|
|
case AKS_STATESAVEQUICK8:
|
|
case AKS_STATESAVEQUICK9:
|
|
savestate_quick ((code - AKS_STATESAVEQUICK) / 2, 1);
|
|
break;
|
|
case AKS_STATERESTOREQUICK:
|
|
case AKS_STATERESTOREQUICK1:
|
|
case AKS_STATERESTOREQUICK2:
|
|
case AKS_STATERESTOREQUICK3:
|
|
case AKS_STATERESTOREQUICK4:
|
|
case AKS_STATERESTOREQUICK5:
|
|
case AKS_STATERESTOREQUICK6:
|
|
case AKS_STATERESTOREQUICK7:
|
|
case AKS_STATERESTOREQUICK8:
|
|
case AKS_STATERESTOREQUICK9:
|
|
savestate_quick ((code - AKS_STATERESTOREQUICK) / 2, 0);
|
|
break;
|
|
case AKS_TOGGLEDEFAULTSCREEN:
|
|
toggle_fullscreen (-1);
|
|
break;
|
|
case AKS_TOGGLEWINDOWEDFULLSCREEN:
|
|
toggle_fullscreen (0);
|
|
break;
|
|
case AKS_TOGGLEFULLWINDOWFULLSCREEN:
|
|
toggle_fullscreen (1);
|
|
break;
|
|
case AKS_TOGGLEWINDOWFULLWINDOW:
|
|
toggle_fullscreen (2);
|
|
break;
|
|
case AKS_TOGGLEMOUSEGRAB:
|
|
toggle_mousegrab ();
|
|
break;
|
|
case AKS_ENTERDEBUGGER:
|
|
activate_debugger ();
|
|
break;
|
|
case AKS_STATESAVEDIALOG:
|
|
gui_display (5);
|
|
break;
|
|
case AKS_STATERESTOREDIALOG:
|
|
gui_display (4);
|
|
break;
|
|
case AKS_DECREASEREFRESHRATE:
|
|
case AKS_INCREASEREFRESHRATE:
|
|
{
|
|
int dir = code == AKS_INCREASEREFRESHRATE ? 5 : -5;
|
|
if (currprefs.chipset_refreshrate == 0)
|
|
currprefs.chipset_refreshrate = currprefs.ntscmode ? 60 : 50;
|
|
changed_prefs.chipset_refreshrate = currprefs.chipset_refreshrate + dir;
|
|
if (changed_prefs.chipset_refreshrate < 10.0)
|
|
changed_prefs.chipset_refreshrate = 10.0;
|
|
if (changed_prefs.chipset_refreshrate > 900.0)
|
|
changed_prefs.chipset_refreshrate = 900.0;
|
|
config_changed = 1;
|
|
}
|
|
break;
|
|
case AKS_DISKSWAPPER_NEXT:
|
|
swapperslot++;
|
|
if (swapperslot >= MAX_SPARE_DRIVES || currprefs.dfxlist[swapperslot][0] == 0)
|
|
swapperslot = 0;
|
|
break;
|
|
case AKS_DISKSWAPPER_PREV:
|
|
swapperslot--;
|
|
if (swapperslot < 0)
|
|
swapperslot = MAX_SPARE_DRIVES - 1;
|
|
while (swapperslot > 0) {
|
|
if (currprefs.dfxlist[swapperslot][0])
|
|
break;
|
|
swapperslot--;
|
|
}
|
|
break;
|
|
case AKS_DISKSWAPPER_INSERT0:
|
|
case AKS_DISKSWAPPER_INSERT1:
|
|
case AKS_DISKSWAPPER_INSERT2:
|
|
case AKS_DISKSWAPPER_INSERT3:
|
|
_tcscpy (changed_prefs.floppyslots[code - AKS_DISKSWAPPER_INSERT0].df, currprefs.dfxlist[swapperslot]);
|
|
config_changed = 1;
|
|
break;
|
|
|
|
break;
|
|
case AKS_INPUT_CONFIG_1:
|
|
case AKS_INPUT_CONFIG_2:
|
|
case AKS_INPUT_CONFIG_3:
|
|
case AKS_INPUT_CONFIG_4:
|
|
changed_prefs.input_selected_setting = currprefs.input_selected_setting = code - AKS_INPUT_CONFIG_1;
|
|
inputdevice_updateconfig (&currprefs);
|
|
break;
|
|
case AKS_DISK_PREV0:
|
|
case AKS_DISK_PREV1:
|
|
case AKS_DISK_PREV2:
|
|
case AKS_DISK_PREV3:
|
|
disk_prevnext (code - AKS_DISK_PREV0, -1);
|
|
break;
|
|
case AKS_DISK_NEXT0:
|
|
case AKS_DISK_NEXT1:
|
|
case AKS_DISK_NEXT2:
|
|
case AKS_DISK_NEXT3:
|
|
disk_prevnext (code - AKS_DISK_NEXT0, 1);
|
|
break;
|
|
#ifdef CDTV
|
|
case AKS_CDTV_FRONT_PANEL_STOP:
|
|
case AKS_CDTV_FRONT_PANEL_PLAYPAUSE:
|
|
case AKS_CDTV_FRONT_PANEL_PREV:
|
|
case AKS_CDTV_FRONT_PANEL_NEXT:
|
|
case AKS_CDTV_FRONT_PANEL_REW:
|
|
case AKS_CDTV_FRONT_PANEL_FF:
|
|
cdtv_front_panel (code - AKS_CDTV_FRONT_PANEL_STOP);
|
|
break;
|
|
#endif
|
|
}
|
|
end:
|
|
if (tracer_enable) {
|
|
set_cpu_tracer (false);
|
|
tracer_enable = 0;
|
|
}
|
|
}
|
|
|
|
static int getqualid (int evt)
|
|
{
|
|
if (evt > INPUTEVENT_SPC_QUALIFIER_START && evt < INPUTEVENT_SPC_QUALIFIER_END)
|
|
return evt - INPUTEVENT_SPC_QUALIFIER1;
|
|
return -1;
|
|
}
|
|
|
|
static uae_u64 isqual (int evt)
|
|
{
|
|
int num = getqualid (evt);
|
|
if (num < 0)
|
|
return 0;
|
|
return ID_FLAG_QUALIFIER1 << (num * 2);
|
|
}
|
|
|
|
static int handle_input_event (int nr, int state, int max, int autofire, bool canstopplayback, bool playbackevent)
|
|
{
|
|
struct inputevent *ie;
|
|
int joy;
|
|
bool isaks = false;
|
|
|
|
if (nr <= 0 || nr == INPUTEVENT_SPC_CUSTOM_EVENT)
|
|
return 0;
|
|
ie = &events[nr];
|
|
if (isqual (nr))
|
|
return 0; // qualifiers do nothing
|
|
if (ie->unit == 0 && ie->data >= AKS_FIRST) {
|
|
isaks = true;
|
|
if (!state) // release AKS_ does nothing
|
|
return 0;
|
|
}
|
|
|
|
if (!isaks) {
|
|
if (input_record && input_record != INPREC_RECORD_PLAYING)
|
|
inprec_recordevent (nr, state, max, autofire);
|
|
if (input_play && state && canstopplayback) {
|
|
if (inprec_realtime ()) {
|
|
if (input_record && input_record != INPREC_RECORD_PLAYING)
|
|
inprec_recordevent (nr, state, max, autofire);
|
|
}
|
|
}
|
|
if (!playbackevent && input_play)
|
|
return 0;
|
|
}
|
|
|
|
if ((inputdevice_logging & 1) || input_record || input_play)
|
|
write_log (_T("STATE=%05d MAX=%05d AF=%d QUAL=%06x '%s' \n"), state, max, autofire, (uae_u32)(qualifiers >> 32), ie->name);
|
|
if (autofire) {
|
|
if (state)
|
|
queue_input_event (nr, NULL, state, max, currprefs.input_autofire_linecnt, 1);
|
|
else
|
|
queue_input_event (nr, NULL, -1, 0, 0, 1);
|
|
}
|
|
switch (ie->unit)
|
|
{
|
|
case 5: /* lightpen/gun */
|
|
{
|
|
if (lightpen_x < 0 && lightpen_y < 0) {
|
|
lightpen_x = gfxvidinfo.outbuffer->outwidth / 2;
|
|
lightpen_y = gfxvidinfo.outbuffer->outheight / 2;
|
|
}
|
|
if (ie->type == 0) {
|
|
int delta = 0;
|
|
if (max == 0)
|
|
delta = state * currprefs.input_mouse_speed / 100;
|
|
else if (state > 0)
|
|
delta = currprefs.input_joymouse_speed;
|
|
else if (state < 0)
|
|
delta = -currprefs.input_joymouse_speed;
|
|
if (ie->data)
|
|
lightpen_y += delta;
|
|
else
|
|
lightpen_x += delta;
|
|
} else {
|
|
int delta = currprefs.input_joymouse_speed;
|
|
if (ie->data & DIR_LEFT)
|
|
lightpen_x -= delta;
|
|
if (ie->data & DIR_RIGHT)
|
|
lightpen_x += delta;
|
|
if (ie->data & DIR_UP)
|
|
lightpen_y -= delta;
|
|
if (ie->data & DIR_DOWN)
|
|
lightpen_y += delta;
|
|
}
|
|
}
|
|
break;
|
|
case 1: /* ->JOY1 */
|
|
case 2: /* ->JOY2 */
|
|
case 3: /* ->Parallel port joystick adapter port #1 */
|
|
case 4: /* ->Parallel port joystick adapter port #2 */
|
|
joy = ie->unit - 1;
|
|
if (ie->type & 4) {
|
|
int old = joybutton[joy] & (1 << ie->data);
|
|
|
|
if (state) {
|
|
joybutton[joy] |= 1 << ie->data;
|
|
gui_gameport_button_change (joy, ie->data, 1);
|
|
} else {
|
|
joybutton[joy] &= ~(1 << ie->data);
|
|
gui_gameport_button_change (joy, ie->data, 0);
|
|
}
|
|
|
|
if (ie->data == 0 && old != (joybutton[joy] & (1 << ie->data)) && currprefs.cpu_cycle_exact) {
|
|
if (!input_record && !input_play && currprefs.input_contact_bounce) {
|
|
// emulate contact bounce, 1st button only, others have capacitors
|
|
bouncy = 1;
|
|
bouncy_cycles = get_cycles () + CYCLE_UNIT * currprefs.input_contact_bounce;
|
|
}
|
|
}
|
|
|
|
|
|
} else if (ie->type & 8) {
|
|
|
|
/* real mouse / analog stick mouse emulation */
|
|
int delta;
|
|
int deadzone = currprefs.input_joymouse_deadzone * max / 100;
|
|
int unit = ie->data & 0x7f;
|
|
|
|
if (max) {
|
|
if (state <= deadzone && state >= -deadzone) {
|
|
state = 0;
|
|
mouse_deltanoreset[joy][unit] = 0;
|
|
} else if (state < 0) {
|
|
state += deadzone;
|
|
mouse_deltanoreset[joy][unit] = 1;
|
|
} else {
|
|
state -= deadzone;
|
|
mouse_deltanoreset[joy][unit] = 1;
|
|
}
|
|
max -= deadzone;
|
|
delta = state * currprefs.input_joymouse_multiplier / max;
|
|
} else {
|
|
delta = state;
|
|
mouse_deltanoreset[joy][unit] = 0;
|
|
}
|
|
if (ie->data & IE_CDTV) {
|
|
delta = 0;
|
|
if (state > 0)
|
|
delta = JOYMOUSE_CDTV;
|
|
else if (state < 0)
|
|
delta = -JOYMOUSE_CDTV;
|
|
}
|
|
|
|
if (ie->data & IE_INVERT)
|
|
delta = -delta;
|
|
|
|
if (max)
|
|
mouse_delta[joy][unit] = delta;
|
|
else
|
|
mouse_delta[joy][unit] += delta;
|
|
|
|
max = 32;
|
|
if (unit) {
|
|
if (delta < 0) {
|
|
gui_gameport_axis_change (joy, DIR_UP_BIT, abs (delta), max);
|
|
gui_gameport_axis_change (joy, DIR_DOWN_BIT, 0, max);
|
|
}
|
|
if (delta > 0) {
|
|
gui_gameport_axis_change (joy, DIR_DOWN_BIT, abs (delta), max);
|
|
gui_gameport_axis_change (joy, DIR_UP_BIT, 0, max);
|
|
}
|
|
} else {
|
|
if (delta < 0) {
|
|
gui_gameport_axis_change (joy, DIR_LEFT_BIT, abs (delta), max);
|
|
gui_gameport_axis_change (joy, DIR_RIGHT_BIT, 0, max);
|
|
}
|
|
if (delta > 0) {
|
|
gui_gameport_axis_change (joy, DIR_RIGHT_BIT, abs (delta), max);
|
|
gui_gameport_axis_change (joy, DIR_LEFT_BIT, 0, max);
|
|
}
|
|
}
|
|
|
|
} else if (ie->type & 32) { /* button mouse emulation vertical */
|
|
|
|
int speed = (ie->data & IE_CDTV) ? JOYMOUSE_CDTV : currprefs.input_joymouse_speed;
|
|
|
|
if (state && (ie->data & DIR_UP)) {
|
|
mouse_delta[joy][1] = -speed;
|
|
mouse_deltanoreset[joy][1] = 1;
|
|
} else if (state && (ie->data & DIR_DOWN)) {
|
|
mouse_delta[joy][1] = speed;
|
|
mouse_deltanoreset[joy][1] = 1;
|
|
} else
|
|
mouse_deltanoreset[joy][1] = 0;
|
|
|
|
} else if (ie->type & 64) { /* button mouse emulation horizontal */
|
|
|
|
int speed = (ie->data & IE_CDTV) ? JOYMOUSE_CDTV : currprefs.input_joymouse_speed;
|
|
|
|
if (state && (ie->data & DIR_LEFT)) {
|
|
mouse_delta[joy][0] = -speed;
|
|
mouse_deltanoreset[joy][0] = 1;
|
|
} else if (state && (ie->data & DIR_RIGHT)) {
|
|
mouse_delta[joy][0] = speed;
|
|
mouse_deltanoreset[joy][0] = 1;
|
|
} else
|
|
mouse_deltanoreset[joy][0] = 0;
|
|
|
|
} else if (ie->type & 128) { /* analog joystick / paddle */
|
|
|
|
int deadzone = currprefs.input_joymouse_deadzone * max / 100;
|
|
int unit = ie->data & 0x7f;
|
|
if (max) {
|
|
if (state <= deadzone && state >= -deadzone) {
|
|
state = 0;
|
|
} else if (state < 0) {
|
|
state += deadzone;
|
|
} else {
|
|
state -= deadzone;
|
|
}
|
|
state = state * max / (max - deadzone);
|
|
}
|
|
if (ie->data & IE_INVERT)
|
|
state = -state;
|
|
|
|
if (!unit) {
|
|
if (state <= 0)
|
|
gui_gameport_axis_change (joy, DIR_UP_BIT, abs (state), max);
|
|
if (state >= 0)
|
|
gui_gameport_axis_change (joy, DIR_DOWN_BIT, abs (state), max);
|
|
} else {
|
|
if (state <= 0)
|
|
gui_gameport_axis_change (joy, DIR_LEFT_BIT, abs (state), max);
|
|
if (state >= 0)
|
|
gui_gameport_axis_change (joy, DIR_RIGHT_BIT, abs (state), max);
|
|
}
|
|
|
|
state = state * currprefs.input_analog_joystick_mult / max;
|
|
state += (128 * currprefs.input_analog_joystick_mult / 100) + currprefs.input_analog_joystick_offset;
|
|
if (state < 0)
|
|
state = 0;
|
|
if (state > 255)
|
|
state = 255;
|
|
joydirpot[joy][unit] = state;
|
|
mouse_deltanoreset[joy][0] = 1;
|
|
mouse_deltanoreset[joy][1] = 1;
|
|
|
|
} else {
|
|
|
|
int left = oleft[joy], right = oright[joy], top = otop[joy], bot = obot[joy];
|
|
if (ie->type & 16) {
|
|
/* button to axis mapping */
|
|
if (ie->data & DIR_LEFT) {
|
|
left = oleft[joy] = state ? 1 : 0;
|
|
if (horizclear[joy] && left) {
|
|
horizclear[joy] = 0;
|
|
right = oright[joy] = 0;
|
|
}
|
|
}
|
|
if (ie->data & DIR_RIGHT) {
|
|
right = oright[joy] = state ? 1 : 0;
|
|
if (horizclear[joy] && right) {
|
|
horizclear[joy] = 0;
|
|
left = oleft[joy] = 0;
|
|
}
|
|
}
|
|
if (ie->data & DIR_UP) {
|
|
top = otop[joy] = state ? 1 : 0;
|
|
if (vertclear[joy] && top) {
|
|
vertclear[joy] = 0;
|
|
bot = obot[joy] = 0;
|
|
}
|
|
}
|
|
if (ie->data & DIR_DOWN) {
|
|
bot = obot[joy] = state ? 1 : 0;
|
|
if (vertclear[joy] && bot) {
|
|
vertclear[joy] = 0;
|
|
top = otop[joy] = 0;
|
|
}
|
|
}
|
|
} else {
|
|
/* "normal" joystick axis */
|
|
int deadzone = currprefs.input_joystick_deadzone * max / 100;
|
|
int neg, pos;
|
|
if (state < deadzone && state > -deadzone)
|
|
state = 0;
|
|
neg = state < 0 ? 1 : 0;
|
|
pos = state > 0 ? 1 : 0;
|
|
if (ie->data & DIR_LEFT) {
|
|
left = oleft[joy] = neg;
|
|
if (horizclear[joy] && left) {
|
|
horizclear[joy] = 0;
|
|
right = oright[joy] = 0;
|
|
}
|
|
}
|
|
if (ie->data & DIR_RIGHT) {
|
|
right = oright[joy] = pos;
|
|
if (horizclear[joy] && right) {
|
|
horizclear[joy] = 0;
|
|
left = oleft[joy] = 0;
|
|
}
|
|
}
|
|
if (ie->data & DIR_UP) {
|
|
top = otop[joy] = neg;
|
|
if (vertclear[joy] && top) {
|
|
vertclear[joy] = 0;
|
|
bot = obot[joy] = 0;
|
|
}
|
|
}
|
|
if (ie->data & DIR_DOWN) {
|
|
bot = obot[joy] = pos;
|
|
if (vertclear[joy] && bot) {
|
|
vertclear[joy] = 0;
|
|
top = otop[joy] = 0;
|
|
}
|
|
}
|
|
}
|
|
mouse_deltanoreset[joy][0] = 1;
|
|
mouse_deltanoreset[joy][1] = 1;
|
|
joydir[joy] = 0;
|
|
if (left)
|
|
joydir[joy] |= DIR_LEFT;
|
|
if (right)
|
|
joydir[joy] |= DIR_RIGHT;
|
|
if (top)
|
|
joydir[joy] |= DIR_UP;
|
|
if (bot)
|
|
joydir[joy] |= DIR_DOWN;
|
|
if (joy == 0 || joy == 1)
|
|
joymousecounter (joy);
|
|
|
|
gui_gameport_axis_change (joy, DIR_LEFT_BIT, left, 0);
|
|
gui_gameport_axis_change (joy, DIR_RIGHT_BIT, right, 0);
|
|
gui_gameport_axis_change (joy, DIR_UP_BIT, top, 0);
|
|
gui_gameport_axis_change (joy, DIR_DOWN_BIT, bot, 0);
|
|
}
|
|
break;
|
|
case 0: /* ->KEY */
|
|
inputdevice_do_keyboard (ie->data, state);
|
|
break;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
static void inputdevice_checkconfig (void)
|
|
{
|
|
if (
|
|
currprefs.jports[0].id != changed_prefs.jports[0].id ||
|
|
currprefs.jports[1].id != changed_prefs.jports[1].id ||
|
|
currprefs.jports[2].id != changed_prefs.jports[2].id ||
|
|
currprefs.jports[3].id != changed_prefs.jports[3].id ||
|
|
currprefs.jports[0].mode != changed_prefs.jports[0].mode ||
|
|
currprefs.jports[1].mode != changed_prefs.jports[1].mode ||
|
|
currprefs.jports[2].mode != changed_prefs.jports[2].mode ||
|
|
currprefs.jports[3].mode != changed_prefs.jports[3].mode ||
|
|
currprefs.input_selected_setting != changed_prefs.input_selected_setting ||
|
|
currprefs.input_joymouse_multiplier != changed_prefs.input_joymouse_multiplier ||
|
|
currprefs.input_joymouse_deadzone != changed_prefs.input_joymouse_deadzone ||
|
|
currprefs.input_joystick_deadzone != changed_prefs.input_joystick_deadzone ||
|
|
currprefs.input_joymouse_speed != changed_prefs.input_joymouse_speed ||
|
|
currprefs.input_autofire_linecnt != changed_prefs.input_autofire_linecnt ||
|
|
currprefs.input_mouse_speed != changed_prefs.input_mouse_speed) {
|
|
|
|
currprefs.input_selected_setting = changed_prefs.input_selected_setting;
|
|
currprefs.input_joymouse_multiplier = changed_prefs.input_joymouse_multiplier;
|
|
currprefs.input_joymouse_deadzone = changed_prefs.input_joymouse_deadzone;
|
|
currprefs.input_joystick_deadzone = changed_prefs.input_joystick_deadzone;
|
|
currprefs.input_joymouse_speed = changed_prefs.input_joymouse_speed;
|
|
currprefs.input_autofire_linecnt = changed_prefs.input_autofire_linecnt;
|
|
currprefs.input_mouse_speed = changed_prefs.input_mouse_speed;
|
|
|
|
inputdevice_updateconfig (&currprefs);
|
|
}
|
|
if (currprefs.dongle != changed_prefs.dongle) {
|
|
currprefs.dongle = changed_prefs.dongle;
|
|
dongle_reset ();
|
|
}
|
|
}
|
|
|
|
void inputdevice_vsync (void)
|
|
{
|
|
if (inputdevice_logging & 32)
|
|
write_log (_T("*\n"));
|
|
|
|
input_frame++;
|
|
mouseupdate (0, 1);
|
|
|
|
if (!input_record) {
|
|
inputdevice_read ();
|
|
if (!input_play)
|
|
inputdelay = uaerand () % (maxvpos <= 1 ? 1 : maxvpos - 1);
|
|
}
|
|
|
|
inputdevice_handle_inputcode ();
|
|
if (mouseedge_alive > 0)
|
|
mouseedge_alive--;
|
|
#ifdef ARCADIA
|
|
if (arcadia_bios)
|
|
arcadia_vsync ();
|
|
#endif
|
|
if (mouseedge ())
|
|
mouseedge_alive = 10;
|
|
if (mousehack_alive_cnt > 0) {
|
|
mousehack_alive_cnt--;
|
|
if (mousehack_alive_cnt == 0)
|
|
setmouseactive (-1);
|
|
} else if (mousehack_alive_cnt < 0) {
|
|
mousehack_alive_cnt++;
|
|
if (mousehack_alive_cnt == 0) {
|
|
mousehack_alive_cnt = 100;
|
|
setmouseactive (0);
|
|
setmouseactive (1);
|
|
}
|
|
}
|
|
inputdevice_checkconfig ();
|
|
}
|
|
|
|
void inputdevice_reset (void)
|
|
{
|
|
magicmouse_ibase = 0;
|
|
magicmouse_gfxbase = 0;
|
|
mousehack_reset ();
|
|
if (inputdevice_is_tablet ())
|
|
mousehack_enable ();
|
|
bouncy = 0;
|
|
potgo_value = 0;
|
|
}
|
|
|
|
static int getoldport (struct uae_input_device *id)
|
|
{
|
|
int i, j;
|
|
|
|
for (i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++) {
|
|
for (j = 0; j < MAX_INPUT_SUB_EVENT; j++) {
|
|
int evt = id->eventid[i][j];
|
|
if (evt > 0) {
|
|
int unit = events[evt].unit;
|
|
if (unit >= 1 && unit <= 4)
|
|
return unit;
|
|
}
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
static int switchdevice (struct uae_input_device *id, int num, bool buttonmode)
|
|
{
|
|
int i, j;
|
|
int ismouse = 0;
|
|
int newport = 0;
|
|
int flags = 0;
|
|
TCHAR *name = NULL;
|
|
int otherbuttonpressed = 0;
|
|
|
|
if (num >= 4)
|
|
return 0;
|
|
#ifdef RETROPLATFORM
|
|
if (rp_isactive ())
|
|
return 0;
|
|
#endif
|
|
for (i = 0; i < MAX_INPUT_DEVICES; i++) {
|
|
if (id == &joysticks[i]) {
|
|
name = idev[IDTYPE_JOYSTICK].get_uniquename (i);
|
|
newport = num == 0 ? 1 : 0;
|
|
flags = idev[IDTYPE_JOYSTICK].get_flags (i);
|
|
for (j = 0; j < MAX_INPUT_DEVICES; j++) {
|
|
if (j != i) {
|
|
struct uae_input_device2 *id2 = &joysticks2[j];
|
|
if (id2->buttonmask)
|
|
otherbuttonpressed = 1;
|
|
}
|
|
}
|
|
}
|
|
if (id == &mice[i]) {
|
|
ismouse = 1;
|
|
name = idev[IDTYPE_MOUSE].get_uniquename (i);
|
|
newport = num == 0 ? 0 : 1;
|
|
flags = idev[IDTYPE_MOUSE].get_flags (i);
|
|
}
|
|
}
|
|
if (!name)
|
|
return 0;
|
|
if (buttonmode) {
|
|
if (num == 0 && otherbuttonpressed)
|
|
newport = newport ? 0 : 1;
|
|
} else {
|
|
newport = num ? 1 : 0;
|
|
}
|
|
/* "GamePorts" switch if in GamePorts mode or Input mode and GamePorts port was not NONE */
|
|
if (currprefs.input_selected_setting == GAMEPORT_INPUT_SETTINGS || currprefs.jports[newport].id != JPORT_NONE) {
|
|
if ((num == 0 || num == 1) && currprefs.jports[newport].id != JPORT_CUSTOM) {
|
|
int om = jsem_ismouse (num, &currprefs);
|
|
int om1 = jsem_ismouse (0, &currprefs);
|
|
int om2 = jsem_ismouse (1, &currprefs);
|
|
if ((om1 >= 0 || om2 >= 0) && ismouse)
|
|
return 0;
|
|
if (flags)
|
|
return 0;
|
|
if (name) {
|
|
write_log (_T("inputdevice change '%s':%d->%d\n"), name, num, newport);
|
|
inputdevice_joyport_config (&changed_prefs, name, newport, -1, 2);
|
|
inputdevice_copyconfig (&changed_prefs, &currprefs);
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
} else {
|
|
int oldport = getoldport (id);
|
|
int k, evt;
|
|
struct inputevent *ie, *ie2;
|
|
|
|
if (flags)
|
|
return 0;
|
|
if (oldport <= 0)
|
|
return 0;
|
|
newport++;
|
|
/* do not switch if switching mouse and any "supermouse" mouse enabled */
|
|
if (ismouse) {
|
|
for (i = 0; i < MAX_INPUT_SETTINGS; i++) {
|
|
if (mice[i].enabled && idev[IDTYPE_MOUSE].get_flags (i))
|
|
return 0;
|
|
}
|
|
}
|
|
for (i = 0; i < MAX_INPUT_SETTINGS; i++) {
|
|
if (getoldport (&joysticks[i]) == newport)
|
|
joysticks[i].enabled = 0;
|
|
if (getoldport (&mice[i]) == newport)
|
|
mice[i].enabled = 0;
|
|
}
|
|
id->enabled = 1;
|
|
for (i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++) {
|
|
for (j = 0; j < MAX_INPUT_SUB_EVENT; j++) {
|
|
evt = id->eventid[i][j];
|
|
if (evt <= 0)
|
|
continue;
|
|
ie = &events[evt];
|
|
if (ie->unit == oldport) {
|
|
k = 1;
|
|
while (events[k].confname) {
|
|
ie2 = &events[k];
|
|
if (ie2->type == ie->type && ie2->data == ie->data && ie2->allow_mask == ie->allow_mask && ie2->unit == newport) {
|
|
id->eventid[i][j] = k;
|
|
break;
|
|
}
|
|
k++;
|
|
}
|
|
} else if (ie->unit == newport) {
|
|
k = 1;
|
|
while (events[k].confname) {
|
|
ie2 = &events[k];
|
|
if (ie2->type == ie->type && ie2->data == ie->data && ie2->allow_mask == ie->allow_mask && ie2->unit == oldport) {
|
|
id->eventid[i][j] = k;
|
|
break;
|
|
}
|
|
k++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
write_log (_T("inputdevice change '%s':%d->%d\n"), name, num, newport);
|
|
inputdevice_copyconfig (&currprefs, &changed_prefs);
|
|
inputdevice_copyconfig (&changed_prefs, &currprefs);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
uae_u64 input_getqualifiers (void)
|
|
{
|
|
return qualifiers;
|
|
}
|
|
|
|
static bool checkqualifiers (int evt, uae_u64 flags, uae_u64 *qualmask, uae_s16 events[MAX_INPUT_SUB_EVENT_ALL])
|
|
{
|
|
int i, j;
|
|
int qualid = getqualid (evt);
|
|
int nomatch = 0;
|
|
bool isspecial = (qualifiers & (ID_FLAG_QUALIFIER_SPECIAL | ID_FLAG_QUALIFIER_SPECIAL_R)) != 0;
|
|
|
|
flags &= ID_FLAG_QUALIFIER_MASK;
|
|
if (qualid >= 0 && events)
|
|
qualifiers_evt[qualid] = events;
|
|
/* special set and new qualifier pressed? do not sent it to Amiga-side */
|
|
if ((qualifiers & (ID_FLAG_QUALIFIER_SPECIAL | ID_FLAG_QUALIFIER_SPECIAL_R)) && qualid >= 0)
|
|
return false;
|
|
|
|
for (i = 0; i < MAX_INPUT_SUB_EVENT; i++) {
|
|
if (qualmask[i])
|
|
break;
|
|
}
|
|
if (i == MAX_INPUT_SUB_EVENT) {
|
|
// no qualifiers in any slot and no special = always match
|
|
return isspecial == false;
|
|
}
|
|
|
|
for (i = 0; i < MAX_INPUT_SUB_EVENT; i++) {
|
|
for (j = 0; j < MAX_INPUT_QUALIFIERS; j++) {
|
|
uae_u64 mask = (ID_FLAG_QUALIFIER1 | ID_FLAG_QUALIFIER1_R) << (j * 2);
|
|
bool isqualmask = (qualmask[i] & mask) != 0;
|
|
bool isqual = (qualifiers & mask) != 0;
|
|
if (isqualmask != isqual) {
|
|
nomatch++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (nomatch == MAX_INPUT_SUB_EVENT) {
|
|
// no matched qualifiers in any slot
|
|
// allow all slots without qualifiers
|
|
// special = never accept
|
|
if (isspecial)
|
|
return false;
|
|
return flags ? false : true;
|
|
}
|
|
|
|
for (i = 0; i < MAX_INPUT_QUALIFIERS; i++) {
|
|
uae_u64 mask = (ID_FLAG_QUALIFIER1 | ID_FLAG_QUALIFIER1_R) << (i * 2);
|
|
bool isflags = (flags & mask) != 0;
|
|
bool isqual = (qualifiers & mask) != 0;
|
|
if (isflags != isqual)
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static void setqualifiers (int evt, int state)
|
|
{
|
|
uae_u64 mask = isqual (evt);
|
|
if (!mask)
|
|
return;
|
|
if (state)
|
|
qualifiers |= mask;
|
|
else
|
|
qualifiers &= ~mask;
|
|
//write_log (_T("%llx\n"), qualifiers);
|
|
}
|
|
|
|
static uae_u64 getqualmask (uae_u64 *qualmask, struct uae_input_device *id, int num, bool *qualonly)
|
|
{
|
|
uae_u64 mask = 0, mask2 = 0;
|
|
for (int i = 0; i < MAX_INPUT_SUB_EVENT; i++) {
|
|
int evt = id->eventid[num][i];
|
|
mask |= id->flags[num][i];
|
|
qualmask[i] = id->flags[num][i] & ID_FLAG_QUALIFIER_MASK;
|
|
mask2 |= isqual (evt);
|
|
}
|
|
mask &= ID_FLAG_QUALIFIER_MASK;
|
|
*qualonly = false;
|
|
if (qualifiers & ID_FLAG_QUALIFIER_SPECIAL) {
|
|
// ID_FLAG_QUALIFIER_SPECIAL already active and this event has one or more qualifiers configured
|
|
*qualonly = mask2 != 0;
|
|
}
|
|
return mask;
|
|
}
|
|
|
|
|
|
static bool process_custom_event (struct uae_input_device *id, int offset, int state, uae_u64 *qualmask, int autofire, int sub)
|
|
{
|
|
int idx, slotoffset, custompos;
|
|
TCHAR *custom;
|
|
uae_u64 flags, qual;
|
|
|
|
if (!id)
|
|
return false;
|
|
|
|
slotoffset = sub & ~3;
|
|
sub &= 3;
|
|
flags = id->flags[offset][slotoffset];
|
|
qual = flags & ID_FLAG_QUALIFIER_MASK;
|
|
custom = id->custom[offset][slotoffset];
|
|
int af = flags & ID_FLAG_AUTOFIRE_MASK;
|
|
|
|
for (idx = 1; idx < 4; idx++) {
|
|
uae_u64 flags2 = id->flags[offset][slotoffset + idx];
|
|
TCHAR *custom2 = id->custom[offset][slotoffset + idx];
|
|
|
|
// all slots must have same qualifier
|
|
if ((flags2 & ID_FLAG_QUALIFIER_MASK) != qual)
|
|
break;
|
|
// no slot must have autofire
|
|
if ((flags2 & ID_FLAG_AUTOFIRE_MASK) || (flags & ID_FLAG_AUTOFIRE_MASK))
|
|
break;
|
|
}
|
|
// at least slot 0 and 2 must have custom
|
|
if (custom == NULL || id->custom[offset][slotoffset + 2] == NULL)
|
|
idx = -1;
|
|
|
|
if (idx < 4) {
|
|
id->flags[offset][slotoffset] &= ~(ID_FLAG_CUSTOMEVENT_TOGGLED1 | ID_FLAG_CUSTOMEVENT_TOGGLED2);
|
|
int evt2 = id->eventid[offset][slotoffset + sub];
|
|
uae_u64 flags2 = id->flags[offset][slotoffset + sub];
|
|
if (checkqualifiers (evt2, flags2, qualmask, NULL)) {
|
|
custom = id->custom[offset][slotoffset + sub];
|
|
if (state && custom) {
|
|
if (autofire)
|
|
queue_input_event (-1, custom, 1, 1, currprefs.input_autofire_linecnt, 1);
|
|
handle_custom_event (custom);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
if (sub != 0)
|
|
return false;
|
|
|
|
slotoffset = 0;
|
|
if (!checkqualifiers (id->eventid[offset][slotoffset], id->flags[offset][slotoffset], qualmask, NULL)) {
|
|
slotoffset = 4;
|
|
if (!checkqualifiers (id->eventid[offset][slotoffset], id->flags[offset][slotoffset], qualmask, NULL))
|
|
return false;
|
|
}
|
|
|
|
flags = id->flags[offset][slotoffset];
|
|
custompos = (flags & ID_FLAG_CUSTOMEVENT_TOGGLED1) ? 1 : 0;
|
|
custompos |= (flags & ID_FLAG_CUSTOMEVENT_TOGGLED2) ? 2 : 0;
|
|
|
|
if (state < 0) {
|
|
idx = 0;
|
|
custompos = 0;
|
|
} else {
|
|
if (state > 0) {
|
|
if (custompos & 1)
|
|
return false; // waiting for release
|
|
} else {
|
|
if (!(custompos & 1))
|
|
return false; // waiting for press
|
|
}
|
|
idx = custompos;
|
|
custompos++;
|
|
}
|
|
|
|
queue_input_event (-1, NULL, -1, 0, 0, 1);
|
|
|
|
if ((id->flags[offset][slotoffset + idx] & ID_FLAG_QUALIFIER_MASK) == qual) {
|
|
custom = id->custom[offset][slotoffset + idx];
|
|
if (autofire)
|
|
queue_input_event (-1, custom, 1, 1, currprefs.input_autofire_linecnt, 1);
|
|
if (custom)
|
|
handle_custom_event (custom);
|
|
}
|
|
|
|
id->flags[offset][slotoffset] &= ~(ID_FLAG_CUSTOMEVENT_TOGGLED1 | ID_FLAG_CUSTOMEVENT_TOGGLED2);
|
|
id->flags[offset][slotoffset] |= (custompos & 1) ? ID_FLAG_CUSTOMEVENT_TOGGLED1 : 0;
|
|
id->flags[offset][slotoffset] |= (custompos & 2) ? ID_FLAG_CUSTOMEVENT_TOGGLED2 : 0;
|
|
|
|
return true;
|
|
}
|
|
|
|
static void setbuttonstateall (struct uae_input_device *id, struct uae_input_device2 *id2, int button, int state)
|
|
{
|
|
static frame_time_t switchdevice_timeout;
|
|
int i;
|
|
uae_u32 mask = 1 << button;
|
|
uae_u32 omask = id2 ? id2->buttonmask & mask : 0;
|
|
uae_u32 nmask = (state ? 1 : 0) << button;
|
|
uae_u64 qualmask[MAX_INPUT_SUB_EVENT];
|
|
bool qualonly;
|
|
|
|
if (input_play && state)
|
|
inprec_realtime ();
|
|
if (input_play)
|
|
return;
|
|
if (!id->enabled) {
|
|
frame_time_t t = read_processor_time ();
|
|
if (state) {
|
|
switchdevice_timeout = t;
|
|
} else {
|
|
int port = button;
|
|
if (t - switchdevice_timeout >= syncbase) // 1s
|
|
port ^= 1;
|
|
switchdevice (id, port, true);
|
|
}
|
|
return;
|
|
}
|
|
if (button >= ID_BUTTON_TOTAL)
|
|
return;
|
|
|
|
getqualmask (qualmask, id, ID_BUTTON_OFFSET + button, &qualonly);
|
|
|
|
bool didcustom = false;
|
|
|
|
for (i = 0; i < MAX_INPUT_SUB_EVENT; i++) {
|
|
uae_u64 *flagsp = &id->flags[ID_BUTTON_OFFSET + button][sublevdir[state <= 0 ? 1 : 0][i]];
|
|
int evt = id->eventid[ID_BUTTON_OFFSET + button][sublevdir[state <= 0 ? 1 : 0][i]];
|
|
uae_u64 flags = flagsp[0];
|
|
int autofire = (flags & ID_FLAG_AUTOFIRE) ? 1 : 0;
|
|
int toggle = (flags & ID_FLAG_TOGGLE) ? 1 : 0;
|
|
int inverttoggle = (flags & ID_FLAG_INVERTTOGGLE) ? 1 : 0;
|
|
|
|
if (!state) {
|
|
didcustom |= process_custom_event (id, ID_BUTTON_OFFSET + button, state, qualmask, autofire, i);
|
|
}
|
|
|
|
setqualifiers (evt, state > 0);
|
|
|
|
if (qualonly)
|
|
continue;
|
|
|
|
if (state < 0) {
|
|
if (!checkqualifiers (evt, flags, qualmask, NULL))
|
|
continue;
|
|
handle_input_event (evt, 1, 1, 0, true, false);
|
|
queue_input_event (evt, NULL, 0, 1, 1, 0); /* send release event next frame */
|
|
didcustom |= process_custom_event (id, ID_BUTTON_OFFSET + button, state, qualmask, 0, i);
|
|
} else if (inverttoggle) {
|
|
/* pressed = firebutton, not pressed = autofire */
|
|
if (state) {
|
|
queue_input_event (evt, NULL, -1, 0, 0, 1);
|
|
handle_input_event (evt, 1, 1, 0, true, false);
|
|
} else {
|
|
handle_input_event (evt, 1, 1, autofire, true, false);
|
|
}
|
|
didcustom |= process_custom_event (id, ID_BUTTON_OFFSET + button, state, qualmask, autofire, i);
|
|
} else if (toggle) {
|
|
if (!state)
|
|
continue;
|
|
if (omask & mask)
|
|
continue;
|
|
if (!checkqualifiers (evt, flags, qualmask, NULL))
|
|
continue;
|
|
*flagsp ^= ID_FLAG_TOGGLED;
|
|
int toggled = (*flagsp & ID_FLAG_TOGGLED) ? 1 : 0;
|
|
handle_input_event (evt, toggled, 1, autofire, true, false);
|
|
didcustom |= process_custom_event (id, ID_BUTTON_OFFSET + button, toggled, qualmask, autofire, i);
|
|
} else {
|
|
if (!checkqualifiers (evt, flags, qualmask, NULL)) {
|
|
if (!state && !(flags & ID_FLAG_CANRELEASE)) {
|
|
continue;
|
|
} else if (state) {
|
|
continue;
|
|
}
|
|
}
|
|
if (!state)
|
|
*flagsp &= ~ID_FLAG_CANRELEASE;
|
|
else
|
|
*flagsp |= ID_FLAG_CANRELEASE;
|
|
if ((omask ^ nmask) & mask) {
|
|
handle_input_event (evt, state, 1, autofire, true, false);
|
|
if (state)
|
|
didcustom |= process_custom_event (id, ID_BUTTON_OFFSET + button, state, qualmask, autofire, i);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!didcustom)
|
|
queue_input_event (-1, NULL, -1, 0, 0, 1);
|
|
|
|
if (id2 && ((omask ^ nmask) & mask)) {
|
|
if (state)
|
|
id2->buttonmask |= mask;
|
|
else
|
|
id2->buttonmask &= ~mask;
|
|
}
|
|
}
|
|
|
|
|
|
/* - detect required number of joysticks and mice from configuration data
|
|
* - detect if CD32 pad emulation is needed
|
|
* - detect device type in ports (mouse or joystick)
|
|
*/
|
|
|
|
static int iscd32 (int ei)
|
|
{
|
|
if (ei >= INPUTEVENT_JOY1_CD32_FIRST && ei <= INPUTEVENT_JOY1_CD32_LAST) {
|
|
cd32_pad_enabled[0] = 1;
|
|
return 1;
|
|
}
|
|
if (ei >= INPUTEVENT_JOY2_CD32_FIRST && ei <= INPUTEVENT_JOY2_CD32_LAST) {
|
|
cd32_pad_enabled[1] = 1;
|
|
return 2;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int isparport (int ei)
|
|
{
|
|
if (ei > INPUTEVENT_PAR_JOY1_START && ei < INPUTEVENT_PAR_JOY_END) {
|
|
parport_joystick_enabled = 1;
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int ismouse (int ei)
|
|
{
|
|
if (ei >= INPUTEVENT_MOUSE1_FIRST && ei <= INPUTEVENT_MOUSE1_LAST) {
|
|
mouse_port[0] = 1;
|
|
return 1;
|
|
}
|
|
if (ei >= INPUTEVENT_MOUSE2_FIRST && ei <= INPUTEVENT_MOUSE2_LAST) {
|
|
mouse_port[1] = 1;
|
|
return 2;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int isanalog (int ei)
|
|
{
|
|
if (ei == INPUTEVENT_JOY1_HORIZ_POT || ei == INPUTEVENT_JOY1_HORIZ_POT_INV) {
|
|
analog_port[0][0] = 1;
|
|
return 1;
|
|
}
|
|
if (ei == INPUTEVENT_JOY1_VERT_POT || ei == INPUTEVENT_JOY1_VERT_POT_INV) {
|
|
analog_port[0][1] = 1;
|
|
return 1;
|
|
}
|
|
if (ei == INPUTEVENT_JOY2_HORIZ_POT || ei == INPUTEVENT_JOY2_HORIZ_POT_INV) {
|
|
analog_port[1][0] = 1;
|
|
return 1;
|
|
}
|
|
if (ei == INPUTEVENT_JOY2_VERT_POT || ei == INPUTEVENT_JOY2_VERT_POT_INV) {
|
|
analog_port[1][1] = 1;
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int isdigitalbutton (int ei)
|
|
{
|
|
if (ei == INPUTEVENT_JOY1_2ND_BUTTON) {
|
|
digital_port[0][1] = 1;
|
|
return 1;
|
|
}
|
|
if (ei == INPUTEVENT_JOY1_3RD_BUTTON) {
|
|
digital_port[0][0] = 1;
|
|
return 1;
|
|
}
|
|
if (ei == INPUTEVENT_JOY2_2ND_BUTTON) {
|
|
digital_port[1][1] = 1;
|
|
return 1;
|
|
}
|
|
if (ei == INPUTEVENT_JOY2_3RD_BUTTON) {
|
|
digital_port[1][0] = 1;
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void isqualifier (int ei)
|
|
{
|
|
}
|
|
|
|
static void scanevents (struct uae_prefs *p)
|
|
{
|
|
int i, j, k, ei;
|
|
const struct inputevent *e;
|
|
int n_joy = idev[IDTYPE_JOYSTICK].get_num ();
|
|
int n_mouse = idev[IDTYPE_MOUSE].get_num ();
|
|
|
|
cd32_pad_enabled[0] = cd32_pad_enabled[1] = 0;
|
|
parport_joystick_enabled = 0;
|
|
mouse_port[0] = mouse_port[1] = 0;
|
|
qualifiers = 0;
|
|
|
|
for (i = 0; i < NORMAL_JPORTS; i++) {
|
|
for (j = 0; j < 2; j++) {
|
|
digital_port[i][j] = 0;
|
|
analog_port[i][j] = 0;
|
|
joydirpot[i][j] = 128 / (312 * 100 / currprefs.input_analog_joystick_mult) + (128 * currprefs.input_analog_joystick_mult / 100) + currprefs.input_analog_joystick_offset;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < MAX_INPUT_DEVICES; i++) {
|
|
use_joysticks[i] = 0;
|
|
use_mice[i] = 0;
|
|
for (k = 0; k < MAX_INPUT_SUB_EVENT; k++) {
|
|
for (j = 0; j < ID_BUTTON_TOTAL; j++) {
|
|
|
|
if ((joysticks[i].enabled && i < n_joy) || joysticks[i].enabled < 0) {
|
|
ei = joysticks[i].eventid[ID_BUTTON_OFFSET + j][k];
|
|
e = &events[ei];
|
|
iscd32 (ei);
|
|
isparport (ei);
|
|
ismouse (ei);
|
|
isdigitalbutton (ei);
|
|
isqualifier (ei);
|
|
if (joysticks[i].eventid[ID_BUTTON_OFFSET + j][k] > 0)
|
|
use_joysticks[i] = 1;
|
|
}
|
|
if ((mice[i].enabled && i < n_mouse) || mice[i].enabled < 0) {
|
|
ei = mice[i].eventid[ID_BUTTON_OFFSET + j][k];
|
|
e = &events[ei];
|
|
iscd32 (ei);
|
|
isparport (ei);
|
|
ismouse (ei);
|
|
isdigitalbutton (ei);
|
|
isqualifier (ei);
|
|
if (mice[i].eventid[ID_BUTTON_OFFSET + j][k] > 0)
|
|
use_mice[i] = 1;
|
|
}
|
|
|
|
}
|
|
|
|
for (j = 0; j < ID_AXIS_TOTAL; j++) {
|
|
|
|
if ((joysticks[i].enabled && i < n_joy) || joysticks[i].enabled < 0) {
|
|
ei = joysticks[i].eventid[ID_AXIS_OFFSET + j][k];
|
|
iscd32 (ei);
|
|
isparport (ei);
|
|
ismouse (ei);
|
|
isanalog (ei);
|
|
isdigitalbutton (ei);
|
|
isqualifier (ei);
|
|
if (ei > 0)
|
|
use_joysticks[i] = 1;
|
|
}
|
|
if ((mice[i].enabled && i < n_mouse) || mice[i].enabled < 0) {
|
|
ei = mice[i].eventid[ID_AXIS_OFFSET + j][k];
|
|
iscd32 (ei);
|
|
isparport (ei);
|
|
ismouse (ei);
|
|
isanalog (ei);
|
|
isdigitalbutton (ei);
|
|
isqualifier (ei);
|
|
if (ei > 0)
|
|
use_mice[i] = 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
memset (scancodeused, 0, sizeof scancodeused);
|
|
for (i = 0; i < MAX_INPUT_DEVICES; i++) {
|
|
use_keyboards[i] = 0;
|
|
if (keyboards[i].enabled && i < idev[IDTYPE_KEYBOARD].get_num ()) {
|
|
j = 0;
|
|
while (j < MAX_INPUT_DEVICE_EVENTS && keyboards[i].extra[j] >= 0) {
|
|
use_keyboards[i] = 1;
|
|
for (k = 0; k < MAX_INPUT_SUB_EVENT; k++) {
|
|
ei = keyboards[i].eventid[j][k];
|
|
iscd32 (ei);
|
|
isparport (ei);
|
|
ismouse (ei);
|
|
isdigitalbutton (ei);
|
|
isqualifier (ei);
|
|
if (ei > 0)
|
|
scancodeused[i][keyboards[i].extra[j]] = ei;
|
|
}
|
|
j++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static int axistable[] = {
|
|
INPUTEVENT_MOUSE1_HORIZ, INPUTEVENT_MOUSE1_LEFT, INPUTEVENT_MOUSE1_RIGHT,
|
|
INPUTEVENT_MOUSE1_VERT, INPUTEVENT_MOUSE1_UP, INPUTEVENT_MOUSE1_DOWN,
|
|
INPUTEVENT_MOUSE2_HORIZ, INPUTEVENT_MOUSE2_LEFT, INPUTEVENT_MOUSE2_RIGHT,
|
|
INPUTEVENT_MOUSE2_VERT, INPUTEVENT_MOUSE2_UP, INPUTEVENT_MOUSE2_DOWN,
|
|
INPUTEVENT_JOY1_HORIZ, INPUTEVENT_JOY1_LEFT, INPUTEVENT_JOY1_RIGHT,
|
|
INPUTEVENT_JOY1_VERT, INPUTEVENT_JOY1_UP, INPUTEVENT_JOY1_DOWN,
|
|
INPUTEVENT_JOY2_HORIZ, INPUTEVENT_JOY2_LEFT, INPUTEVENT_JOY2_RIGHT,
|
|
INPUTEVENT_JOY2_VERT, INPUTEVENT_JOY2_UP, INPUTEVENT_JOY2_DOWN,
|
|
INPUTEVENT_LIGHTPEN_HORIZ, INPUTEVENT_LIGHTPEN_LEFT, INPUTEVENT_LIGHTPEN_RIGHT,
|
|
INPUTEVENT_LIGHTPEN_VERT, INPUTEVENT_LIGHTPEN_UP, INPUTEVENT_LIGHTPEN_DOWN,
|
|
INPUTEVENT_PAR_JOY1_HORIZ, INPUTEVENT_PAR_JOY1_LEFT, INPUTEVENT_PAR_JOY1_RIGHT,
|
|
INPUTEVENT_PAR_JOY1_VERT, INPUTEVENT_PAR_JOY1_UP, INPUTEVENT_PAR_JOY1_DOWN,
|
|
INPUTEVENT_PAR_JOY2_HORIZ, INPUTEVENT_PAR_JOY2_LEFT, INPUTEVENT_PAR_JOY2_RIGHT,
|
|
INPUTEVENT_PAR_JOY2_VERT, INPUTEVENT_PAR_JOY2_UP, INPUTEVENT_PAR_JOY2_DOWN,
|
|
INPUTEVENT_MOUSE_CDTV_HORIZ, INPUTEVENT_MOUSE_CDTV_LEFT, INPUTEVENT_MOUSE_CDTV_RIGHT,
|
|
INPUTEVENT_MOUSE_CDTV_VERT, INPUTEVENT_MOUSE_CDTV_UP, INPUTEVENT_MOUSE_CDTV_DOWN,
|
|
-1
|
|
};
|
|
|
|
int intputdevice_compa_get_eventtype (int evt, int **axistablep)
|
|
{
|
|
for (int i = 0; axistable[i] >= 0; i += 3) {
|
|
*axistablep = &axistable[i];
|
|
if (axistable[i] == evt)
|
|
return IDEV_WIDGET_AXIS;
|
|
if (axistable[i + 1] == evt)
|
|
return IDEV_WIDGET_BUTTONAXIS;
|
|
if (axistable[i + 2] == evt)
|
|
return IDEV_WIDGET_BUTTONAXIS;
|
|
}
|
|
*axistablep = NULL;
|
|
return IDEV_WIDGET_BUTTON;
|
|
}
|
|
|
|
static int rem_port1[] = {
|
|
INPUTEVENT_MOUSE1_HORIZ, INPUTEVENT_MOUSE1_VERT,
|
|
INPUTEVENT_JOY1_HORIZ, INPUTEVENT_JOY1_VERT,
|
|
INPUTEVENT_JOY1_HORIZ_POT, INPUTEVENT_JOY1_VERT_POT,
|
|
INPUTEVENT_JOY1_FIRE_BUTTON, INPUTEVENT_JOY1_2ND_BUTTON, INPUTEVENT_JOY1_3RD_BUTTON,
|
|
INPUTEVENT_JOY1_CD32_RED, INPUTEVENT_JOY1_CD32_BLUE, INPUTEVENT_JOY1_CD32_GREEN, INPUTEVENT_JOY1_CD32_YELLOW,
|
|
INPUTEVENT_JOY1_CD32_RWD, INPUTEVENT_JOY1_CD32_FFW, INPUTEVENT_JOY1_CD32_PLAY,
|
|
INPUTEVENT_MOUSE_CDTV_HORIZ, INPUTEVENT_MOUSE_CDTV_VERT,
|
|
INPUTEVENT_LIGHTPEN_HORIZ, INPUTEVENT_LIGHTPEN_VERT,
|
|
-1
|
|
};
|
|
static int rem_port2[] = {
|
|
INPUTEVENT_MOUSE2_HORIZ, INPUTEVENT_MOUSE2_VERT,
|
|
INPUTEVENT_JOY2_HORIZ, INPUTEVENT_JOY2_VERT,
|
|
INPUTEVENT_JOY2_HORIZ_POT, INPUTEVENT_JOY2_VERT_POT,
|
|
INPUTEVENT_JOY2_FIRE_BUTTON, INPUTEVENT_JOY2_2ND_BUTTON, INPUTEVENT_JOY2_3RD_BUTTON,
|
|
INPUTEVENT_JOY2_CD32_RED, INPUTEVENT_JOY2_CD32_BLUE, INPUTEVENT_JOY2_CD32_GREEN, INPUTEVENT_JOY2_CD32_YELLOW,
|
|
INPUTEVENT_JOY2_CD32_RWD, INPUTEVENT_JOY2_CD32_FFW, INPUTEVENT_JOY2_CD32_PLAY,
|
|
-1, -1,
|
|
-1, -1,
|
|
-1
|
|
};
|
|
static int rem_port3[] = {
|
|
INPUTEVENT_PAR_JOY1_LEFT, INPUTEVENT_PAR_JOY1_RIGHT, INPUTEVENT_PAR_JOY1_UP, INPUTEVENT_PAR_JOY1_DOWN,
|
|
INPUTEVENT_PAR_JOY1_FIRE_BUTTON, INPUTEVENT_PAR_JOY1_2ND_BUTTON,
|
|
-1
|
|
};
|
|
static int rem_port4[] = {
|
|
INPUTEVENT_PAR_JOY2_LEFT, INPUTEVENT_PAR_JOY2_RIGHT, INPUTEVENT_PAR_JOY2_UP, INPUTEVENT_PAR_JOY2_DOWN,
|
|
INPUTEVENT_PAR_JOY2_FIRE_BUTTON, INPUTEVENT_PAR_JOY2_2ND_BUTTON,
|
|
-1
|
|
};
|
|
|
|
static int *rem_ports[] = { rem_port1, rem_port2, rem_port3, rem_port4 };
|
|
static int af_port1[] = {
|
|
INPUTEVENT_JOY1_FIRE_BUTTON, INPUTEVENT_JOY1_CD32_RED,
|
|
-1
|
|
};
|
|
static int af_port2[] = {
|
|
INPUTEVENT_JOY2_FIRE_BUTTON, INPUTEVENT_JOY2_CD32_RED,
|
|
-1
|
|
};
|
|
static int af_port3[] = {
|
|
INPUTEVENT_PAR_JOY1_FIRE_BUTTON, INPUTEVENT_PAR_JOY1_2ND_BUTTON,
|
|
-1
|
|
};
|
|
static int af_port4[] = {
|
|
INPUTEVENT_PAR_JOY2_FIRE_BUTTON, INPUTEVENT_PAR_JOY2_2ND_BUTTON,
|
|
-1
|
|
};
|
|
static int *af_ports[] = { af_port1, af_port2, af_port3, af_port4 };
|
|
static int ip_joy1[] = {
|
|
INPUTEVENT_JOY1_LEFT, INPUTEVENT_JOY1_RIGHT, INPUTEVENT_JOY1_UP, INPUTEVENT_JOY1_DOWN,
|
|
INPUTEVENT_JOY1_FIRE_BUTTON, INPUTEVENT_JOY1_2ND_BUTTON,
|
|
-1
|
|
};
|
|
static int ip_joy2[] = {
|
|
INPUTEVENT_JOY2_LEFT, INPUTEVENT_JOY2_RIGHT, INPUTEVENT_JOY2_UP, INPUTEVENT_JOY2_DOWN,
|
|
INPUTEVENT_JOY2_FIRE_BUTTON, INPUTEVENT_JOY2_2ND_BUTTON,
|
|
-1
|
|
};
|
|
static int ip_joypad1[] = {
|
|
INPUTEVENT_JOY1_LEFT, INPUTEVENT_JOY1_RIGHT, INPUTEVENT_JOY1_UP, INPUTEVENT_JOY1_DOWN,
|
|
INPUTEVENT_JOY1_FIRE_BUTTON, INPUTEVENT_JOY1_2ND_BUTTON, INPUTEVENT_JOY1_3RD_BUTTON,
|
|
-1
|
|
};
|
|
static int ip_joypad2[] = {
|
|
INPUTEVENT_JOY2_LEFT, INPUTEVENT_JOY2_RIGHT, INPUTEVENT_JOY2_UP, INPUTEVENT_JOY2_DOWN,
|
|
INPUTEVENT_JOY2_FIRE_BUTTON, INPUTEVENT_JOY2_2ND_BUTTON, INPUTEVENT_JOY2_3RD_BUTTON,
|
|
-1
|
|
};
|
|
static int ip_joycd321[] = {
|
|
INPUTEVENT_JOY1_LEFT, INPUTEVENT_JOY1_RIGHT, INPUTEVENT_JOY1_UP, INPUTEVENT_JOY1_DOWN,
|
|
INPUTEVENT_JOY1_CD32_RED, INPUTEVENT_JOY1_CD32_BLUE, INPUTEVENT_JOY1_CD32_GREEN, INPUTEVENT_JOY1_CD32_YELLOW,
|
|
INPUTEVENT_JOY1_CD32_RWD, INPUTEVENT_JOY1_CD32_FFW, INPUTEVENT_JOY1_CD32_PLAY,
|
|
-1
|
|
};
|
|
static int ip_joycd322[] = {
|
|
INPUTEVENT_JOY2_LEFT, INPUTEVENT_JOY2_RIGHT, INPUTEVENT_JOY2_UP, INPUTEVENT_JOY2_DOWN,
|
|
INPUTEVENT_JOY2_CD32_RED, INPUTEVENT_JOY2_CD32_BLUE, INPUTEVENT_JOY2_CD32_GREEN, INPUTEVENT_JOY2_CD32_YELLOW,
|
|
INPUTEVENT_JOY2_CD32_RWD, INPUTEVENT_JOY2_CD32_FFW, INPUTEVENT_JOY2_CD32_PLAY,
|
|
-1
|
|
};
|
|
static int ip_parjoy1[] = {
|
|
INPUTEVENT_PAR_JOY1_LEFT, INPUTEVENT_PAR_JOY1_RIGHT, INPUTEVENT_PAR_JOY1_UP, INPUTEVENT_PAR_JOY1_DOWN,
|
|
INPUTEVENT_PAR_JOY1_FIRE_BUTTON, INPUTEVENT_PAR_JOY1_2ND_BUTTON,
|
|
-1
|
|
};
|
|
static int ip_parjoy2[] = {
|
|
INPUTEVENT_PAR_JOY2_LEFT, INPUTEVENT_PAR_JOY2_RIGHT, INPUTEVENT_PAR_JOY2_UP, INPUTEVENT_PAR_JOY2_DOWN,
|
|
INPUTEVENT_PAR_JOY2_FIRE_BUTTON, INPUTEVENT_PAR_JOY2_2ND_BUTTON,
|
|
-1
|
|
};
|
|
static int ip_parjoy1default[] = {
|
|
INPUTEVENT_PAR_JOY1_LEFT, INPUTEVENT_PAR_JOY1_RIGHT, INPUTEVENT_PAR_JOY1_UP, INPUTEVENT_PAR_JOY1_DOWN,
|
|
INPUTEVENT_PAR_JOY1_FIRE_BUTTON,
|
|
-1
|
|
};
|
|
static int ip_parjoy2default[] = {
|
|
INPUTEVENT_PAR_JOY2_LEFT, INPUTEVENT_PAR_JOY2_RIGHT, INPUTEVENT_PAR_JOY2_UP, INPUTEVENT_PAR_JOY2_DOWN,
|
|
INPUTEVENT_PAR_JOY2_FIRE_BUTTON,
|
|
-1
|
|
};
|
|
static int ip_mouse1[] = {
|
|
INPUTEVENT_MOUSE1_LEFT, INPUTEVENT_MOUSE1_RIGHT, INPUTEVENT_MOUSE1_UP, INPUTEVENT_MOUSE1_DOWN,
|
|
INPUTEVENT_JOY1_FIRE_BUTTON, INPUTEVENT_JOY1_2ND_BUTTON,
|
|
-1
|
|
};
|
|
static int ip_mouse2[] = {
|
|
INPUTEVENT_MOUSE2_LEFT, INPUTEVENT_MOUSE2_RIGHT, INPUTEVENT_MOUSE2_UP, INPUTEVENT_MOUSE2_DOWN,
|
|
INPUTEVENT_JOY2_FIRE_BUTTON, INPUTEVENT_JOY2_2ND_BUTTON,
|
|
-1
|
|
};
|
|
static int ip_mousecdtv[] =
|
|
{
|
|
INPUTEVENT_MOUSE_CDTV_LEFT, INPUTEVENT_MOUSE_CDTV_RIGHT, INPUTEVENT_MOUSE_CDTV_UP, INPUTEVENT_MOUSE_CDTV_DOWN,
|
|
INPUTEVENT_JOY1_FIRE_BUTTON, INPUTEVENT_JOY1_2ND_BUTTON,
|
|
-1
|
|
};
|
|
static int ip_mediacdtv[] =
|
|
{
|
|
INPUTEVENT_KEY_CDTV_PLAYPAUSE, INPUTEVENT_KEY_CDTV_STOP, INPUTEVENT_KEY_CDTV_PREV, INPUTEVENT_KEY_CDTV_NEXT,
|
|
-1
|
|
};
|
|
static int ip_arcadia[] = {
|
|
INPUTEVENT_SPC_ARCADIA_DIAGNOSTICS, INPUTEVENT_SPC_ARCADIA_PLAYER1, INPUTEVENT_SPC_ARCADIA_PLAYER2,
|
|
INPUTEVENT_SPC_ARCADIA_COIN1, INPUTEVENT_SPC_ARCADIA_COIN2,
|
|
-1
|
|
};
|
|
static int ip_lightpen1[] = {
|
|
INPUTEVENT_LIGHTPEN_HORIZ, INPUTEVENT_LIGHTPEN_VERT, INPUTEVENT_JOY1_3RD_BUTTON,
|
|
-1
|
|
};
|
|
static int ip_lightpen2[] = {
|
|
INPUTEVENT_LIGHTPEN_HORIZ, INPUTEVENT_LIGHTPEN_VERT, INPUTEVENT_JOY2_3RD_BUTTON,
|
|
-1
|
|
};
|
|
static int ip_analog1[] = {
|
|
INPUTEVENT_JOY1_HORIZ_POT, INPUTEVENT_JOY1_VERT_POT, INPUTEVENT_JOY1_LEFT, INPUTEVENT_JOY1_RIGHT,
|
|
-1
|
|
};
|
|
static int ip_analog2[] = {
|
|
INPUTEVENT_JOY2_HORIZ_POT, INPUTEVENT_JOY2_VERT_POT, INPUTEVENT_JOY2_LEFT, INPUTEVENT_JOY2_RIGHT,
|
|
-1
|
|
};
|
|
|
|
static int ip_arcadiaxa[] = {
|
|
-1
|
|
};
|
|
|
|
static void checkcompakb (int *kb, int *srcmap)
|
|
{
|
|
int found = 0, avail = 0;
|
|
int j, k;
|
|
|
|
k = j = 0;
|
|
while (kb[j] >= 0) {
|
|
struct uae_input_device *uid = &keyboards[0];
|
|
while (kb[j] >= 0 && srcmap[k] >= 0) {
|
|
int id = kb[j];
|
|
for (int l = 0; l < MAX_INPUT_DEVICE_EVENTS; l++) {
|
|
if (uid->extra[l] == id) {
|
|
avail++;
|
|
if (uid->eventid[l][0] == srcmap[k])
|
|
found++;
|
|
break;
|
|
}
|
|
}
|
|
j++;
|
|
}
|
|
if (srcmap[k] < 0)
|
|
break;
|
|
j++;
|
|
k++;
|
|
}
|
|
if (avail != found || avail == 0)
|
|
return;
|
|
k = j = 0;
|
|
while (kb[j] >= 0) {
|
|
struct uae_input_device *uid = &keyboards[0];
|
|
while (kb[j] >= 0) {
|
|
int id = kb[j];
|
|
int evt0 = 0, evt1 = 0;
|
|
k = 0;
|
|
while (keyboard_default[k].scancode >= 0) {
|
|
if (keyboard_default[k].scancode == kb[j]) {
|
|
for (int l = 0; l < MAX_INPUT_DEVICE_EVENTS; l++) {
|
|
if (uid->extra[l] == id) {
|
|
for (int m = 0; m < MAX_INPUT_SUB_EVENT && keyboard_default[k].node[m].evt; m++) {
|
|
uid->eventid[l][m] = keyboard_default[k].node[m].evt;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
k++;
|
|
}
|
|
j++;
|
|
}
|
|
j++;
|
|
}
|
|
}
|
|
|
|
static void setautofireevent (struct uae_input_device *uid, int num, int sub, int af, int index)
|
|
{
|
|
if (!af)
|
|
return;
|
|
#ifdef RETROPLATFORM
|
|
// don't override custom AF autofire mappings
|
|
if (rp_isactive ())
|
|
return;
|
|
#endif
|
|
int *afp = af_ports[index];
|
|
for (int k = 0; afp[k] >= 0; k++) {
|
|
if (afp[k] == uid->eventid[num][sub]) {
|
|
uid->flags[num][sub] &= ~ID_FLAG_AUTOFIRE_MASK;
|
|
if (af >= JPORT_AF_NORMAL)
|
|
uid->flags[num][sub] |= ID_FLAG_AUTOFIRE;
|
|
if (af == JPORT_AF_TOGGLE)
|
|
uid->flags[num][sub] |= ID_FLAG_TOGGLE;
|
|
if (af == JPORT_AF_ALWAYS)
|
|
uid->flags[num][sub] |= ID_FLAG_INVERTTOGGLE;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void sparerestore (struct uae_input_device *uid, int num, int sub)
|
|
{
|
|
uid->eventid[num][sub] = uid->eventid[num][SPARE_SUB_EVENT];
|
|
uid->flags[num][sub] = uid->flags[num][SPARE_SUB_EVENT];
|
|
uid->custom[num][sub] = uid->custom[num][SPARE_SUB_EVENT];
|
|
uid->eventid[num][SPARE_SUB_EVENT] = 0;
|
|
uid->flags[num][SPARE_SUB_EVENT] = 0;
|
|
uid->port[num][SPARE_SUB_EVENT] = 0;
|
|
uid->custom[num][SPARE_SUB_EVENT] = 0;
|
|
}
|
|
|
|
static void sparecopy (struct uae_input_device *uid, int num, int sub)
|
|
{
|
|
uid->eventid[num][SPARE_SUB_EVENT] = uid->eventid[num][sub];
|
|
uid->flags[num][SPARE_SUB_EVENT] = uid->flags[num][sub];
|
|
uid->port[num][SPARE_SUB_EVENT] = MAX_JPORTS + 1;
|
|
xfree (uid->custom[num][SPARE_SUB_EVENT]);
|
|
uid->custom[num][SPARE_SUB_EVENT] = uid->custom[num][sub];
|
|
uid->custom[num][sub] = NULL;
|
|
}
|
|
|
|
static void setcompakb (int *kb, int *srcmap, int index, int af)
|
|
{
|
|
int j, k;
|
|
k = j = 0;
|
|
while (kb[j] >= 0 && srcmap[k] >= 0) {
|
|
while (kb[j] >= 0) {
|
|
int id = kb[j];
|
|
for (int m = 0; m < MAX_INPUT_DEVICES; m++) {
|
|
struct uae_input_device *uid = &keyboards[m];
|
|
for (int l = 0; l < MAX_INPUT_DEVICE_EVENTS; l++) {
|
|
if (uid->extra[l] == id) {
|
|
sparecopy (uid, l, 0);
|
|
uid->eventid[l][0] = srcmap[k];
|
|
uid->flags[l][0] = 0;
|
|
uid->port[l][0] = index + 1;
|
|
xfree (uid->custom[l][0]);
|
|
uid->custom[l][0] = NULL;
|
|
setautofireevent (uid, l, 0, af, index);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
j++;
|
|
}
|
|
j++;
|
|
k++;
|
|
}
|
|
}
|
|
|
|
int inputdevice_get_compatibility_input (struct uae_prefs *prefs, int index, int *typelist, int **inputlist, int **at)
|
|
{
|
|
if (index >= MAX_JPORTS || joymodes[index] < 0)
|
|
return 0;
|
|
*typelist = joymodes[index];
|
|
*inputlist = joyinputs[index];
|
|
*at = axistable;
|
|
int cnt = 0;
|
|
for (int i = 0; joyinputs[index] && joyinputs[index][i] >= 0; i++, cnt++);
|
|
return cnt;
|
|
}
|
|
|
|
static void clearevent (struct uae_input_device *uid, int evt)
|
|
{
|
|
for (int i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++) {
|
|
for (int j = 0; j < MAX_INPUT_SUB_EVENT; j++) {
|
|
if (uid->eventid[i][j] == evt) {
|
|
uid->eventid[i][j] = 0;
|
|
uid->flags[i][j] = 0;
|
|
xfree (uid->custom[i][j]);
|
|
uid->custom[i][j] = NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
static void clearkbrevent (struct uae_input_device *uid, int evt)
|
|
{
|
|
for (int i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++) {
|
|
for (int j = 0; j < MAX_INPUT_SUB_EVENT; j++) {
|
|
if (uid->eventid[i][j] == evt) {
|
|
uid->eventid[i][j] = 0;
|
|
uid->flags[i][j] = 0;
|
|
xfree (uid->custom[i][j]);
|
|
uid->custom[i][j] = NULL;
|
|
if (j == 0)
|
|
set_kbr_default_event (uid, keyboard_default, i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void resetjport (struct uae_prefs *prefs, int index)
|
|
{
|
|
int *p = rem_ports[index];
|
|
while (*p >= 0) {
|
|
int evtnum = *p++;
|
|
for (int l = 0; l < MAX_INPUT_DEVICES; l++) {
|
|
clearevent (&prefs->joystick_settings[GAMEPORT_INPUT_SETTINGS][l], evtnum);
|
|
clearevent (&prefs->mouse_settings[GAMEPORT_INPUT_SETTINGS][l], evtnum);
|
|
clearkbrevent (&prefs->keyboard_settings[GAMEPORT_INPUT_SETTINGS][l], evtnum);
|
|
}
|
|
for (int i = 0; axistable[i] >= 0; i += 3) {
|
|
if (evtnum == axistable[i] || evtnum == axistable[i + 1] || evtnum == axistable[i + 2]) {
|
|
for (int j = 0; j < 3; j++) {
|
|
int evtnum2 = axistable[i + j];
|
|
for (int l = 0; l < MAX_INPUT_DEVICES; l++) {
|
|
clearevent (&prefs->joystick_settings[GAMEPORT_INPUT_SETTINGS][l], evtnum2);
|
|
clearevent (&prefs->mouse_settings[GAMEPORT_INPUT_SETTINGS][l], evtnum2);
|
|
clearkbrevent (&prefs->keyboard_settings[GAMEPORT_INPUT_SETTINGS][l], evtnum2);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void remove_compa_config (struct uae_prefs *prefs, int index)
|
|
{
|
|
int typelist, *inputlist, *atp;
|
|
|
|
if (!inputdevice_get_compatibility_input (prefs, index, &typelist, &inputlist, &atp))
|
|
return;
|
|
for (int i = 0; inputlist[i] >= 0; i++) {
|
|
int evtnum = inputlist[i];
|
|
|
|
int atpidx = 0;
|
|
while (*atp >= 0) {
|
|
if (*atp == evtnum) {
|
|
atp++;
|
|
atpidx = 2;
|
|
break;
|
|
}
|
|
if (atp[1] == evtnum || atp[2] == evtnum) {
|
|
atpidx = 1;
|
|
break;
|
|
}
|
|
atp += 3;
|
|
}
|
|
while (atpidx >= 0) {
|
|
for (int l = 0; l < MAX_INPUT_DEVICES; l++) {
|
|
clearevent (&prefs->joystick_settings[GAMEPORT_INPUT_SETTINGS][l], evtnum);
|
|
clearevent (&prefs->mouse_settings[GAMEPORT_INPUT_SETTINGS][l], evtnum);
|
|
clearkbrevent (&prefs->keyboard_settings[GAMEPORT_INPUT_SETTINGS][l], evtnum);
|
|
}
|
|
evtnum = *atp++;
|
|
atpidx--;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void cleardevgp (struct uae_input_device *uid, int num, bool nocustom, int index)
|
|
{
|
|
for (int i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++) {
|
|
for (int j = 0; j < MAX_INPUT_SUB_EVENT; j++) {
|
|
if (uid[num].port[i][j] == index + 1) {
|
|
if (nocustom && (uid[num].flags[i][j] & ID_FLAG_GAMEPORTSCUSTOM_MASK))
|
|
continue;
|
|
uid[num].eventid[i][j] = 0;
|
|
uid[num].flags[i][j] = 0;
|
|
xfree (uid[num].custom[i][j]);
|
|
uid[num].custom[i][j] = NULL;
|
|
uid[num].port[i][j] = 0;
|
|
if (uid[num].port[i][SPARE_SUB_EVENT])
|
|
sparerestore (&uid[num], i, j);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
static void cleardevkbrgp (struct uae_input_device *uid, int num, bool nocustom, int index)
|
|
{
|
|
for (int i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++) {
|
|
for (int j = 0; j < MAX_INPUT_SUB_EVENT; j++) {
|
|
if (uid[num].port[i][j] == index + 1) {
|
|
if (nocustom && (uid[num].flags[i][j] & ID_FLAG_GAMEPORTSCUSTOM_MASK))
|
|
continue;
|
|
uid[num].eventid[i][j] = 0;
|
|
uid[num].flags[i][j] = 0;
|
|
xfree (uid[num].custom[i][j]);
|
|
uid[num].custom[i][j] = NULL;
|
|
uid[num].port[i][j] = 0;
|
|
if (uid[num].port[i][SPARE_SUB_EVENT]) {
|
|
sparerestore (&uid[num], i, j);
|
|
} else if (j == 0) {
|
|
set_kbr_default_event (&uid[num], keyboard_default, i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// remove all gameports mappings mapped to port 'index'
|
|
static void remove_custom_config (struct uae_prefs *prefs, bool nocustom, int index)
|
|
{
|
|
for (int l = 0; l < MAX_INPUT_DEVICES; l++) {
|
|
cleardevgp (joysticks, l, nocustom, index);
|
|
cleardevgp (mice, l, nocustom, index);
|
|
cleardevkbrgp (keyboards, l, nocustom, index);
|
|
}
|
|
}
|
|
|
|
// prepare port for custom mapping, remove all current Amiga side device mappings
|
|
void inputdevice_compa_prepare_custom (struct uae_prefs *prefs, int index, int newmode)
|
|
{
|
|
int mode = prefs->jports[index].mode;
|
|
freejport (prefs, index);
|
|
resetjport (prefs, index);
|
|
if (newmode >= 0) {
|
|
mode = newmode;
|
|
} else if (mode == 0) {
|
|
mode = index == 0 ? JSEM_MODE_MOUSE : (prefs->cs_cd32cd ? JSEM_MODE_JOYSTICK_CD32 : JSEM_MODE_JOYSTICK);
|
|
}
|
|
prefs->jports[index].mode = mode;
|
|
prefs->jports[index].id = -2;
|
|
|
|
remove_compa_config (prefs, index);
|
|
remove_custom_config (prefs, false, index);
|
|
}
|
|
// clear device before switching to new one
|
|
void inputdevice_compa_clear (struct uae_prefs *prefs, int index)
|
|
{
|
|
freejport (prefs, index);
|
|
resetjport (prefs, index);
|
|
remove_compa_config (prefs, index);
|
|
}
|
|
|
|
static void cleardev (struct uae_input_device *uid, int num)
|
|
{
|
|
for (int i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++) {
|
|
for (int j = 0; j < MAX_INPUT_SUB_EVENT; j++) {
|
|
uid[num].eventid[i][j] = 0;
|
|
uid[num].flags[i][j] = 0;
|
|
xfree (uid[num].custom[i][j]);
|
|
uid[num].custom[i][j] = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void enablejoydevice (struct uae_input_device *uid, bool gameportsmode, int evtnum)
|
|
{
|
|
for (int i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++) {
|
|
for (int j = 0; j < MAX_INPUT_SUB_EVENT; j++) {
|
|
if ((gameportsmode && uid->eventid[i][j] == evtnum) || uid->port[i][j] > 0) {
|
|
uid->enabled = 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void setjoydevices (struct uae_prefs *prefs, bool gameportsmode, int port)
|
|
{
|
|
for (int i = 0; joyinputs[port] && joyinputs[port][i] >= 0; i++) {
|
|
int evtnum = joyinputs[port][i];
|
|
for (int l = 0; l < MAX_INPUT_DEVICES; l++) {
|
|
enablejoydevice (&joysticks[l], gameportsmode, evtnum);
|
|
enablejoydevice (&mice[l], gameportsmode, evtnum);
|
|
enablejoydevice (&keyboards[l], gameportsmode, evtnum);
|
|
}
|
|
for (int k = 0; axistable[k] >= 0; k += 3) {
|
|
if (evtnum == axistable[k] || evtnum == axistable[k + 1] || evtnum == axistable[k + 2]) {
|
|
for (int j = 0; j < 3; j++) {
|
|
int evtnum2 = axistable[k + j];
|
|
for (int l = 0; l < MAX_INPUT_DEVICES; l++) {
|
|
enablejoydevice (&joysticks[l], gameportsmode, evtnum2);
|
|
enablejoydevice (&mice[l], gameportsmode, evtnum2);
|
|
enablejoydevice (&keyboards[l], gameportsmode, evtnum2);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
static void setjoyinputs (struct uae_prefs *prefs, int port)
|
|
{
|
|
joyinputs[port] = NULL;
|
|
switch (joymodes[port])
|
|
{
|
|
case JSEM_MODE_JOYSTICK:
|
|
if (port >= 2)
|
|
joyinputs[port] = port == 3 ? ip_parjoy2 : ip_parjoy1;
|
|
else
|
|
joyinputs[port] = port == 1 ? ip_joy2 : ip_joy1;
|
|
break;
|
|
case JSEM_MODE_GAMEPAD:
|
|
joyinputs[port] = port ? ip_joypad2 : ip_joypad1;
|
|
break;
|
|
case JSEM_MODE_JOYSTICK_CD32:
|
|
joyinputs[port] = port ? ip_joycd322 : ip_joycd321;
|
|
break;
|
|
case JSEM_MODE_JOYSTICK_ANALOG:
|
|
joyinputs[port] = port ? ip_analog2 : ip_analog1;
|
|
break;
|
|
case JSEM_MODE_MOUSE:
|
|
joyinputs[port] = port ? ip_mouse2 : ip_mouse1;
|
|
break;
|
|
case JSEM_MODE_LIGHTPEN:
|
|
joyinputs[port] = port ? ip_lightpen2 : ip_lightpen1;
|
|
break;
|
|
case JSEM_MODE_MOUSE_CDTV:
|
|
joyinputs[port] = ip_mousecdtv;
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void setautofire (struct uae_input_device *uid, int port, int af)
|
|
{
|
|
int *afp = af_ports[port];
|
|
for (int k = 0; afp[k] >= 0; k++) {
|
|
for (int i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++) {
|
|
for (int j = 0; j < MAX_INPUT_SUB_EVENT; j++) {
|
|
if (uid->eventid[i][j] == afp[k]) {
|
|
uid->flags[i][j] &= ~ID_FLAG_AUTOFIRE_MASK;
|
|
if (af >= JPORT_AF_NORMAL)
|
|
uid->flags[i][j] |= ID_FLAG_AUTOFIRE;
|
|
if (af == JPORT_AF_TOGGLE)
|
|
uid->flags[i][j] |= ID_FLAG_TOGGLE;
|
|
if (af == JPORT_AF_ALWAYS)
|
|
uid->flags[i][j] |= ID_FLAG_INVERTTOGGLE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void setautofires (struct uae_prefs *prefs, int port, int af)
|
|
{
|
|
#ifdef RETROPLATFORM
|
|
// don't override custom AF autofire mappings
|
|
if (rp_isactive ())
|
|
return;
|
|
#endif
|
|
for (int l = 0; l < MAX_INPUT_DEVICES; l++) {
|
|
setautofire (&joysticks[l], port, af);
|
|
setautofire (&mice[l], port, af);
|
|
setautofire (&keyboards[l], port, af);
|
|
}
|
|
}
|
|
|
|
// merge gameport settings with current input configuration
|
|
static void compatibility_copy (struct uae_prefs *prefs, bool gameports)
|
|
{
|
|
int used[MAX_INPUT_DEVICES] = { 0 };
|
|
int i, joy;
|
|
|
|
for (i = 0; i < MAX_JPORTS; i++) {
|
|
joymodes[i] = prefs->jports[i].mode;
|
|
joyinputs[i]= NULL;
|
|
// remove all mappings from this port, except if custom
|
|
if (prefs->jports[i].id != JPORT_CUSTOM) {
|
|
if (gameports)
|
|
remove_compa_config (prefs, i);
|
|
}
|
|
remove_custom_config (prefs, prefs->jports[i].id == JPORT_CUSTOM, i);
|
|
setjoyinputs (prefs, i);
|
|
}
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
int af = prefs->jports[i].autofire;
|
|
if (prefs->jports[i].id >= 0 && joymodes[i] <= 0) {
|
|
int mode = prefs->jports[i].mode;
|
|
if (jsem_ismouse (i, prefs) >= 0) {
|
|
switch (mode)
|
|
{
|
|
case JSEM_MODE_DEFAULT:
|
|
case JSEM_MODE_MOUSE:
|
|
default:
|
|
joymodes[i] = JSEM_MODE_MOUSE;
|
|
joyinputs[i] = i ? ip_mouse2 : ip_mouse1;
|
|
break;
|
|
case JSEM_MODE_LIGHTPEN:
|
|
joymodes[i] = JSEM_MODE_LIGHTPEN;
|
|
joyinputs[i] = i ? ip_lightpen2 : ip_lightpen1;
|
|
break;
|
|
case JSEM_MODE_MOUSE_CDTV:
|
|
joymodes[i] = JSEM_MODE_MOUSE_CDTV;
|
|
joyinputs[i] = ip_mousecdtv;
|
|
break;
|
|
}
|
|
} else if (jsem_isjoy (i, prefs) >= 0) {
|
|
switch (mode)
|
|
{
|
|
case JSEM_MODE_DEFAULT:
|
|
case JSEM_MODE_JOYSTICK:
|
|
case JSEM_MODE_GAMEPAD:
|
|
case JSEM_MODE_JOYSTICK_CD32:
|
|
default:
|
|
{
|
|
bool iscd32 = mode == JSEM_MODE_JOYSTICK_CD32 || (mode == JSEM_MODE_DEFAULT && prefs->cs_cd32cd);
|
|
if (iscd32) {
|
|
joymodes[i] = JSEM_MODE_JOYSTICK_CD32;
|
|
joyinputs[i] = i ? ip_joycd322 : ip_joycd321;
|
|
} else if (mode == JSEM_MODE_GAMEPAD) {
|
|
joymodes[i] = JSEM_MODE_GAMEPAD;
|
|
joyinputs[i] = i ? ip_joypad2 : ip_joypad1;
|
|
} else {
|
|
joymodes[i] = JSEM_MODE_JOYSTICK;
|
|
joyinputs[i] = i ? ip_joy2 : ip_joy1;
|
|
}
|
|
break;
|
|
}
|
|
case JSEM_MODE_JOYSTICK_ANALOG:
|
|
joymodes[i] = JSEM_MODE_JOYSTICK_ANALOG;
|
|
joyinputs[i] = i ? ip_analog2 : ip_analog1;
|
|
break;
|
|
case JSEM_MODE_MOUSE:
|
|
joymodes[i] = JSEM_MODE_MOUSE;
|
|
joyinputs[i] = i ? ip_mouse2 : ip_mouse1;
|
|
break;
|
|
case JSEM_MODE_LIGHTPEN:
|
|
joymodes[i] = JSEM_MODE_LIGHTPEN;
|
|
joyinputs[i] = i ? ip_lightpen2 : ip_lightpen1;
|
|
break;
|
|
case JSEM_MODE_MOUSE_CDTV:
|
|
joymodes[i] = JSEM_MODE_MOUSE_CDTV;
|
|
joyinputs[i] = ip_mousecdtv;
|
|
break;
|
|
}
|
|
} else if (prefs->jports[i].id >= 0) {
|
|
joymodes[i] = i ? JSEM_MODE_JOYSTICK : JSEM_MODE_MOUSE;
|
|
joyinputs[i] = i ? ip_joy2 : ip_mouse1;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (i = 2; i < MAX_JPORTS; i++) {
|
|
if (prefs->jports[i].id >= 0 && joymodes[i] <= 0) {
|
|
int mode = prefs->jports[i].mode;
|
|
if (jsem_isjoy (i, prefs) >= 0) {
|
|
joymodes[i] = JSEM_MODE_JOYSTICK;
|
|
joyinputs[i] = i == 3 ? ip_parjoy2 : ip_parjoy1;
|
|
} else if (prefs->jports[i].id >= 0) {
|
|
prefs->jports[i].mode = joymodes[i] = JSEM_MODE_JOYSTICK;
|
|
joyinputs[i] = i == 3 ? ip_parjoy2 : ip_parjoy1;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
int af = prefs->jports[i].autofire;
|
|
if (prefs->jports[i].id >= 0) {
|
|
int mode = prefs->jports[i].mode;
|
|
if ((joy = jsem_ismouse (i, prefs)) >= 0) {
|
|
if (gameports)
|
|
cleardev (mice, joy);
|
|
switch (mode)
|
|
{
|
|
case JSEM_MODE_DEFAULT:
|
|
case JSEM_MODE_MOUSE:
|
|
default:
|
|
input_get_default_mouse (mice, joy, i, af);
|
|
joymodes[i] = JSEM_MODE_MOUSE;
|
|
break;
|
|
case JSEM_MODE_LIGHTPEN:
|
|
input_get_default_lightpen (mice, joy, i, af);
|
|
joymodes[i] = JSEM_MODE_LIGHTPEN;
|
|
break;
|
|
}
|
|
_tcsncpy (prefs->jports[i].name, idev[IDTYPE_MOUSE].get_friendlyname (joy), MAX_JPORTNAME - 1);
|
|
_tcsncpy (prefs->jports[i].configname, idev[IDTYPE_MOUSE].get_uniquename (joy), MAX_JPORTNAME - 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
for (i = 1; i >= 0; i--) {
|
|
int af = prefs->jports[i].autofire;
|
|
if (prefs->jports[i].id >= 0) {
|
|
int mode = prefs->jports[i].mode;
|
|
joy = jsem_isjoy (i, prefs);
|
|
if (joy >= 0) {
|
|
if (gameports)
|
|
cleardev (joysticks, joy);
|
|
switch (mode)
|
|
{
|
|
case JSEM_MODE_DEFAULT:
|
|
case JSEM_MODE_JOYSTICK:
|
|
case JSEM_MODE_GAMEPAD:
|
|
case JSEM_MODE_JOYSTICK_CD32:
|
|
default:
|
|
{
|
|
bool iscd32 = mode == JSEM_MODE_JOYSTICK_CD32 || (mode == JSEM_MODE_DEFAULT && prefs->cs_cd32cd);
|
|
input_get_default_joystick (joysticks, joy, i, af, mode);
|
|
if (iscd32)
|
|
joymodes[i] = JSEM_MODE_JOYSTICK_CD32;
|
|
else if (mode == JSEM_MODE_GAMEPAD)
|
|
joymodes[i] = JSEM_MODE_GAMEPAD;
|
|
else
|
|
joymodes[i] = JSEM_MODE_JOYSTICK;
|
|
break;
|
|
}
|
|
case JSEM_MODE_JOYSTICK_ANALOG:
|
|
input_get_default_joystick_analog (joysticks, joy, i, af);
|
|
joymodes[i] = JSEM_MODE_JOYSTICK_ANALOG;
|
|
break;
|
|
case JSEM_MODE_MOUSE:
|
|
input_get_default_mouse (joysticks, joy, i, af);
|
|
joymodes[i] = JSEM_MODE_MOUSE;
|
|
break;
|
|
case JSEM_MODE_LIGHTPEN:
|
|
input_get_default_lightpen (joysticks, joy, i, af);
|
|
joymodes[i] = JSEM_MODE_LIGHTPEN;
|
|
break;
|
|
case JSEM_MODE_MOUSE_CDTV:
|
|
joymodes[i] = JSEM_MODE_MOUSE_CDTV;
|
|
input_get_default_joystick (joysticks, joy, i, af, mode);
|
|
break;
|
|
|
|
}
|
|
_tcsncpy (prefs->jports[i].name, idev[IDTYPE_JOYSTICK].get_friendlyname (joy), MAX_JPORTNAME - 1);
|
|
_tcsncpy (prefs->jports[i].configname, idev[IDTYPE_JOYSTICK].get_uniquename (joy), MAX_JPORTNAME - 1);
|
|
used[joy] = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (gameports) {
|
|
// replace possible old mappings with default keyboard mapping
|
|
for (i = KBR_DEFAULT_MAP_FIRST; i <= KBR_DEFAULT_MAP_LAST; i++) {
|
|
checkcompakb (keyboard_default_kbmaps[i], ip_joy2);
|
|
checkcompakb (keyboard_default_kbmaps[i], ip_joy1);
|
|
checkcompakb (keyboard_default_kbmaps[i], ip_joypad2);
|
|
checkcompakb (keyboard_default_kbmaps[i], ip_joypad1);
|
|
checkcompakb (keyboard_default_kbmaps[i], ip_parjoy2);
|
|
checkcompakb (keyboard_default_kbmaps[i], ip_parjoy1);
|
|
checkcompakb (keyboard_default_kbmaps[i], ip_mouse2);
|
|
checkcompakb (keyboard_default_kbmaps[i], ip_mouse1);
|
|
}
|
|
for (i = KBR_DEFAULT_MAP_CD32_FIRST; i <= KBR_DEFAULT_MAP_CD32_LAST; i++) {
|
|
checkcompakb (keyboard_default_kbmaps[i], ip_joycd321);
|
|
checkcompakb (keyboard_default_kbmaps[i], ip_joycd322);
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
if (prefs->jports[i].id >= 0) {
|
|
int *kb = NULL;
|
|
int mode = prefs->jports[i].mode;
|
|
int af = prefs->jports[i].autofire;
|
|
for (joy = 0; used[joy]; joy++);
|
|
if (JSEM_ISANYKBD (i, prefs)) {
|
|
bool cd32 = mode == JSEM_MODE_JOYSTICK_CD32 || (mode == JSEM_MODE_DEFAULT && prefs->cs_cd32cd);
|
|
if (JSEM_ISNUMPAD (i, prefs)) {
|
|
if (cd32)
|
|
kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_CD32_NP];
|
|
else if (mode == JSEM_MODE_GAMEPAD)
|
|
kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_NP3];
|
|
else
|
|
kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_NP];
|
|
} else if (JSEM_ISCURSOR (i, prefs)) {
|
|
if (cd32)
|
|
kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_CD32_CK];
|
|
else if (mode == JSEM_MODE_GAMEPAD)
|
|
kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_CK3];
|
|
else
|
|
kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_CK];
|
|
} else if (JSEM_ISSOMEWHEREELSE (i, prefs)) {
|
|
if (cd32)
|
|
kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_CD32_SE];
|
|
else if (mode == JSEM_MODE_GAMEPAD)
|
|
kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_SE3];
|
|
else
|
|
kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_SE];
|
|
} else if (JSEM_ISXARCADE1 (i, prefs)) {
|
|
kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_XA1];
|
|
} else if (JSEM_ISXARCADE2 (i, prefs)) {
|
|
kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_XA2];
|
|
}
|
|
if (kb) {
|
|
switch (mode)
|
|
{
|
|
case JSEM_MODE_JOYSTICK:
|
|
case JSEM_MODE_GAMEPAD:
|
|
case JSEM_MODE_JOYSTICK_CD32:
|
|
case JSEM_MODE_DEFAULT:
|
|
if (cd32) {
|
|
setcompakb (kb, i ? ip_joycd322 : ip_joycd321, i, af);
|
|
joymodes[i] = JSEM_MODE_JOYSTICK_CD32;
|
|
} else if (mode == JSEM_MODE_GAMEPAD) {
|
|
setcompakb (kb, i ? ip_joypad2 : ip_joypad1, i, af);
|
|
joymodes[i] = JSEM_MODE_GAMEPAD;
|
|
} else {
|
|
setcompakb (kb, i ? ip_joy2 : ip_joy1, i, af);
|
|
joymodes[i] = JSEM_MODE_JOYSTICK;
|
|
}
|
|
break;
|
|
case JSEM_MODE_MOUSE:
|
|
setcompakb (kb, i ? ip_mouse2 : ip_mouse1, i, af);
|
|
joymodes[i] = JSEM_MODE_MOUSE;
|
|
break;
|
|
}
|
|
used[joy] = 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (arcadia_bios) {
|
|
setcompakb (keyboard_default_kbmaps[KBR_DEFAULT_MAP_ARCADIA], ip_arcadia, 0, 0);
|
|
if (JSEM_ISXARCADE1 (i, prefs) || JSEM_ISXARCADE2 (i, prefs))
|
|
setcompakb (keyboard_default_kbmaps[KBR_DEFAULT_MAP_ARCADIA_XA], ip_arcadiaxa, JSEM_ISXARCADE2 (i, prefs) ? 1 : 0, prefs->jports[i].autofire);
|
|
}
|
|
if (0 && currprefs.cs_cdtvcd) {
|
|
setcompakb (keyboard_default_kbmaps[KBR_DEFAULT_MAP_CDTV], ip_mediacdtv, 0, 0);
|
|
}
|
|
|
|
// parport
|
|
for (i = 2; i < MAX_JPORTS; i++) {
|
|
int af = prefs->jports[i].autofire;
|
|
if (prefs->jports[i].id >= 0) {
|
|
int *kb = NULL;
|
|
joy = jsem_isjoy (i, prefs);
|
|
if (joy >= 0) {
|
|
if (gameports)
|
|
cleardev (joysticks, joy);
|
|
input_get_default_joystick (joysticks, joy, i, af, 0);
|
|
_tcsncpy (prefs->jports[i].name, idev[IDTYPE_JOYSTICK].get_friendlyname (joy), MAX_JPORTNAME - 1);
|
|
_tcsncpy (prefs->jports[i].configname, idev[IDTYPE_JOYSTICK].get_uniquename (joy), MAX_JPORTNAME - 1);
|
|
used[joy] = 1;
|
|
joymodes[i] = JSEM_MODE_JOYSTICK;
|
|
}
|
|
}
|
|
}
|
|
for (i = 2; i < MAX_JPORTS; i++) {
|
|
if (prefs->jports[i].id >= 0) {
|
|
int *kb = NULL;
|
|
for (joy = 0; used[joy]; joy++);
|
|
if (JSEM_ISANYKBD (i, prefs)) {
|
|
if (JSEM_ISNUMPAD (i, prefs))
|
|
kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_NP];
|
|
else if (JSEM_ISCURSOR (i, prefs))
|
|
kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_CK];
|
|
else if (JSEM_ISSOMEWHEREELSE (i, prefs))
|
|
kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_SE];
|
|
else if (JSEM_ISXARCADE1 (i, prefs))
|
|
kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_XA1];
|
|
else if (JSEM_ISXARCADE2 (i, prefs))
|
|
kb = keyboard_default_kbmaps[KBR_DEFAULT_MAP_XA2];
|
|
if (kb) {
|
|
setcompakb (kb, i == 3 ? ip_parjoy2default : ip_parjoy1default, i, prefs->jports[i].autofire);
|
|
used[joy] = 1;
|
|
joymodes[i] = JSEM_MODE_JOYSTICK;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < MAX_JPORTS; i++) {
|
|
if (gameports)
|
|
setautofires (prefs, i, prefs->jports[i].autofire);
|
|
}
|
|
|
|
for (i = 0; i < MAX_JPORTS; i++) {
|
|
setjoyinputs (prefs, i);
|
|
setjoydevices (prefs, gameports, i);
|
|
}
|
|
}
|
|
|
|
static void disableifempty2 (struct uae_input_device *uid)
|
|
{
|
|
for (int i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++) {
|
|
for (int j = 0; j < MAX_INPUT_SUB_EVENT; j++) {
|
|
if (uid->eventid[i][j] > 0 || uid->custom[i][j] != NULL)
|
|
return;
|
|
}
|
|
}
|
|
uid->enabled = false;
|
|
}
|
|
static void disableifempty (struct uae_prefs *prefs)
|
|
{
|
|
for (int l = 0; l < MAX_INPUT_DEVICES; l++) {
|
|
disableifempty2 (&joysticks[l]);
|
|
disableifempty2 (&mice[l]);
|
|
disableifempty2 (&keyboards[l]);
|
|
}
|
|
prefs->internalevent_settings[0]->enabled = true;
|
|
}
|
|
|
|
static void matchdevices (struct inputdevice_functions *inf, struct uae_input_device *uid)
|
|
{
|
|
int i, j;
|
|
|
|
for (i = 0; i < inf->get_num (); i++) {
|
|
TCHAR *aname1 = inf->get_friendlyname (i);
|
|
TCHAR *aname2 = inf->get_uniquename (i);
|
|
int match = -1;
|
|
for (j = 0; j < MAX_INPUT_DEVICES; j++) {
|
|
if (aname2 && uid[j].configname) {
|
|
bool matched = false;
|
|
TCHAR bname[MAX_DPATH];
|
|
TCHAR bname2[MAX_DPATH];
|
|
TCHAR *p1 ,*p2;
|
|
_tcscpy (bname, uid[j].configname);
|
|
_tcscpy (bname2, aname2);
|
|
// strip possible local guid part
|
|
p1 = _tcschr (bname, '{');
|
|
p2 = _tcschr (bname2, '{');
|
|
if (!p1 && !p2) {
|
|
// check possible directinput names too
|
|
p1 = _tcschr (bname, ' ');
|
|
p2 = _tcschr (bname2, ' ');
|
|
}
|
|
if (!_tcscmp (bname, bname2)) {
|
|
matched = true;
|
|
} else if (p1 && p2 && p1 - bname == p2 - bname2) {
|
|
*p1 = 0;
|
|
*p2 = 0;
|
|
if (bname && !_tcscmp (bname2, bname))
|
|
matched = true;
|
|
}
|
|
if (matched) {
|
|
if (match >= 0)
|
|
match = -2;
|
|
else
|
|
match = j;
|
|
}
|
|
if (match == -2)
|
|
break;
|
|
}
|
|
}
|
|
// multiple matches -> use complete local-only id string for comparisons
|
|
if (match == -2) {
|
|
for (j = 0; j < MAX_INPUT_DEVICES; j++) {
|
|
TCHAR *bname2 = uid[j].configname;
|
|
if (aname2 && bname2 && !_tcscmp (aname2, bname2)) {
|
|
match = j;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (match < 0) {
|
|
// no match, try friend names
|
|
for (j = 0; j < MAX_INPUT_DEVICES; j++) {
|
|
TCHAR *bname1 = uid[j].name;
|
|
if (aname1 && bname1 && !_tcscmp (aname1, bname1)) {
|
|
match = j;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (match >= 0) {
|
|
j = match;
|
|
if (j != i) {
|
|
struct uae_input_device *tmp = xmalloc (struct uae_input_device, 1);
|
|
memcpy (tmp, &uid[j], sizeof (struct uae_input_device));
|
|
memcpy (&uid[j], &uid[i], sizeof (struct uae_input_device));
|
|
memcpy (&uid[i], tmp, sizeof (struct uae_input_device));
|
|
xfree (tmp);
|
|
}
|
|
}
|
|
}
|
|
for (i = 0; i < inf->get_num (); i++) {
|
|
if (uid[i].name == NULL)
|
|
uid[i].name = my_strdup (inf->get_friendlyname (i));
|
|
if (uid[i].configname == NULL)
|
|
uid[i].configname = my_strdup (inf->get_uniquename (i));
|
|
}
|
|
}
|
|
|
|
static void matchdevices_all (struct uae_prefs *prefs)
|
|
{
|
|
int i;
|
|
for (i = 0; i < MAX_INPUT_SETTINGS; i++) {
|
|
matchdevices (&idev[IDTYPE_MOUSE], prefs->mouse_settings[i]);
|
|
matchdevices (&idev[IDTYPE_JOYSTICK], prefs->joystick_settings[i]);
|
|
matchdevices (&idev[IDTYPE_KEYBOARD], prefs->keyboard_settings[i]);
|
|
}
|
|
}
|
|
|
|
bool inputdevice_set_gameports_mapping (struct uae_prefs *prefs, int devnum, int num, int evtnum, uae_u64 flags, int port)
|
|
{
|
|
TCHAR name[256];
|
|
struct inputevent *ie;
|
|
|
|
ie = inputdevice_get_eventinfo (evtnum);
|
|
if (!inputdevice_get_eventname (ie, name))
|
|
return false;
|
|
joysticks = prefs->joystick_settings[GAMEPORT_INPUT_SETTINGS];
|
|
mice = prefs->mouse_settings[GAMEPORT_INPUT_SETTINGS];
|
|
keyboards = prefs->keyboard_settings[GAMEPORT_INPUT_SETTINGS];
|
|
|
|
int sub = 0;
|
|
if (inputdevice_get_widget_type (devnum, num, NULL) != IDEV_WIDGET_KEY) {
|
|
for (sub = 0; sub < MAX_INPUT_SUB_EVENT; sub++) {
|
|
if (!inputdevice_get_mapping (devnum, num, NULL, NULL, NULL, NULL, sub))
|
|
break;
|
|
}
|
|
}
|
|
if (sub >= MAX_INPUT_SUB_EVENT)
|
|
sub = MAX_INPUT_SUB_EVENT - 1;
|
|
inputdevice_set_mapping (devnum, num, name, NULL, IDEV_MAPPED_GAMEPORTSCUSTOM1 | flags, port + 1, sub);
|
|
|
|
joysticks = prefs->joystick_settings[prefs->input_selected_setting];
|
|
mice = prefs->mouse_settings[prefs->input_selected_setting];
|
|
keyboards = prefs->keyboard_settings[prefs->input_selected_setting];
|
|
|
|
if (prefs->input_selected_setting != GAMEPORT_INPUT_SETTINGS) {
|
|
int xport;
|
|
uae_u64 xflags;
|
|
TCHAR xname[MAX_DPATH], xcustom[MAX_DPATH];
|
|
inputdevice_get_mapping (devnum, num, &xflags, &xport, xname, xcustom, 0);
|
|
if (xport == 0)
|
|
inputdevice_set_mapping (devnum, num, xname, xcustom, xflags, MAX_JPORTS + 1, SPARE_SUB_EVENT);
|
|
inputdevice_set_mapping (devnum, num, name, NULL, IDEV_MAPPED_GAMEPORTSCUSTOM1 | flags, port + 1, 0);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static void resetinput (void)
|
|
{
|
|
if ((input_play || input_record) && hsync_counter > 0)
|
|
return;
|
|
cd32_shifter[0] = cd32_shifter[1] = 8;
|
|
for (int i = 0; i < MAX_JPORTS; i++) {
|
|
oleft[i] = 0;
|
|
oright[i] = 0;
|
|
otop[i] = 0;
|
|
obot[i] = 0;
|
|
oldmx[i] = -1;
|
|
oldmy[i] = -1;
|
|
joybutton[i] = 0;
|
|
joydir[i] = 0;
|
|
mouse_deltanoreset[i][0] = 0;
|
|
mouse_delta[i][0] = 0;
|
|
mouse_deltanoreset[i][1] = 0;
|
|
mouse_delta[i][1] = 0;
|
|
mouse_deltanoreset[i][2] = 0;
|
|
mouse_delta[i][2] = 0;
|
|
}
|
|
memset (keybuf, 0, sizeof keybuf);
|
|
for (int i = 0; i < INPUT_QUEUE_SIZE; i++)
|
|
input_queue[i].linecnt = input_queue[i].nextlinecnt = -1;
|
|
|
|
for (int i = 0; i < MAX_INPUT_SUB_EVENT; i++) {
|
|
sublevdir[0][i] = i;
|
|
sublevdir[1][i] = MAX_INPUT_SUB_EVENT - i - 1;
|
|
}
|
|
}
|
|
|
|
|
|
void inputdevice_updateconfig_internal (struct uae_prefs *prefs)
|
|
{
|
|
int i;
|
|
|
|
keyboard_default = keyboard_default_table[currprefs.input_keyboard_type];
|
|
|
|
copyjport (&changed_prefs, &currprefs, 0);
|
|
copyjport (&changed_prefs, &currprefs, 1);
|
|
copyjport (&changed_prefs, &currprefs, 2);
|
|
copyjport (&changed_prefs, &currprefs, 3);
|
|
|
|
resetinput ();
|
|
|
|
joysticks = prefs->joystick_settings[prefs->input_selected_setting];
|
|
mice = prefs->mouse_settings[prefs->input_selected_setting];
|
|
keyboards = prefs->keyboard_settings[prefs->input_selected_setting];
|
|
internalevents = prefs->internalevent_settings[prefs->input_selected_setting];
|
|
|
|
matchdevices_all (prefs);
|
|
|
|
memset (joysticks2, 0, sizeof joysticks2);
|
|
memset (mice2, 0, sizeof mice2);
|
|
|
|
joysticks = prefs->joystick_settings[GAMEPORT_INPUT_SETTINGS];
|
|
mice = prefs->mouse_settings[GAMEPORT_INPUT_SETTINGS];
|
|
keyboards = prefs->keyboard_settings[GAMEPORT_INPUT_SETTINGS];
|
|
internalevents = prefs->internalevent_settings[GAMEPORT_INPUT_SETTINGS];
|
|
|
|
for (i = 0; i < MAX_INPUT_SETTINGS; i++) {
|
|
joysticks[i].enabled = 0;
|
|
mice[i].enabled = 0;
|
|
}
|
|
|
|
compatibility_copy (prefs, true);
|
|
joysticks = prefs->joystick_settings[prefs->input_selected_setting];
|
|
mice = prefs->mouse_settings[prefs->input_selected_setting];
|
|
keyboards = prefs->keyboard_settings[prefs->input_selected_setting];
|
|
internalevents = prefs->internalevent_settings[prefs->input_selected_setting];
|
|
|
|
if (prefs->input_selected_setting != GAMEPORT_INPUT_SETTINGS) {
|
|
compatibility_copy (prefs, false);
|
|
}
|
|
|
|
disableifempty (prefs);
|
|
scanevents (prefs);
|
|
}
|
|
|
|
void inputdevice_updateconfig (struct uae_prefs *prefs)
|
|
{
|
|
inputdevice_updateconfig_internal (prefs);
|
|
|
|
config_changed = 1;
|
|
|
|
#ifdef RETROPLATFORM
|
|
rp_input_change (0);
|
|
rp_input_change (1);
|
|
rp_input_change (2);
|
|
rp_input_change (3);
|
|
for (int i = 0; i < MAX_JPORTS; i++)
|
|
rp_update_gameport (i, -1, 0);
|
|
#endif
|
|
}
|
|
|
|
/* called when devices get inserted or removed
|
|
* store old devices temporarily, enumerate all devices
|
|
* restore old devices back (order may have changed)
|
|
*/
|
|
void inputdevice_devicechange (struct uae_prefs *prefs)
|
|
{
|
|
int acc = input_acquired;
|
|
int i, idx;
|
|
TCHAR *jports[MAX_JPORTS];
|
|
int jportskb[MAX_JPORTS], jportsmode[MAX_JPORTS];
|
|
|
|
for (i = 0; i < MAX_JPORTS; i++) {
|
|
jports[i] = NULL;
|
|
jportskb[i] = -1;
|
|
idx = inputdevice_getjoyportdevice (i, prefs->jports[i].id);
|
|
if (idx >= JSEM_LASTKBD) {
|
|
struct inputdevice_functions *idf;
|
|
int devidx;
|
|
idx -= JSEM_LASTKBD;
|
|
idf = getidf (idx);
|
|
devidx = inputdevice_get_device_index (idx);
|
|
jports[i] = my_strdup (idf->get_uniquename (devidx));
|
|
} else {
|
|
jportskb[i] = idx;
|
|
}
|
|
jportsmode[i] = prefs->jports[i].mode;
|
|
}
|
|
|
|
inputdevice_unacquire ();
|
|
idev[IDTYPE_JOYSTICK].close ();
|
|
idev[IDTYPE_MOUSE].close ();
|
|
idev[IDTYPE_KEYBOARD].close ();
|
|
idev[IDTYPE_JOYSTICK].init ();
|
|
idev[IDTYPE_MOUSE].init ();
|
|
idev[IDTYPE_KEYBOARD].init ();
|
|
matchdevices (&idev[IDTYPE_MOUSE], mice);
|
|
matchdevices (&idev[IDTYPE_JOYSTICK], joysticks);
|
|
matchdevices (&idev[IDTYPE_KEYBOARD], keyboards);
|
|
|
|
for (i = 0; i < MAX_JPORTS; i++) {
|
|
freejport (prefs, i);
|
|
if (jports[i]) {
|
|
inputdevice_joyport_config (prefs, jports[i], i, jportsmode[i], 2);
|
|
xfree (jports[i]);
|
|
} else if (jportskb[i] >= 0) {
|
|
TCHAR tmp[10];
|
|
_stprintf (tmp, _T("kbd%d"), jportskb[i]);
|
|
inputdevice_joyport_config (prefs, tmp, i, jportsmode[i], 0);
|
|
}
|
|
}
|
|
|
|
if (prefs == &changed_prefs)
|
|
inputdevice_copyconfig (&changed_prefs, &currprefs);
|
|
if (acc)
|
|
inputdevice_acquire (TRUE);
|
|
config_changed = 1;
|
|
}
|
|
|
|
|
|
// set default prefs to all input configuration settings
|
|
void inputdevice_default_prefs (struct uae_prefs *p)
|
|
{
|
|
inputdevice_init ();
|
|
|
|
p->input_selected_setting = GAMEPORT_INPUT_SETTINGS;
|
|
p->input_joymouse_multiplier = 100;
|
|
p->input_joymouse_deadzone = 33;
|
|
p->input_joystick_deadzone = 33;
|
|
p->input_joymouse_speed = 10;
|
|
p->input_analog_joystick_mult = 15;
|
|
p->input_analog_joystick_offset = -1;
|
|
p->input_mouse_speed = 100;
|
|
p->input_autofire_linecnt = 600;
|
|
p->input_keyboard_type = 0;
|
|
keyboard_default = keyboard_default_table[p->input_keyboard_type];
|
|
inputdevice_default_kb_all (p);
|
|
}
|
|
|
|
// set default keyboard and keyboard>joystick layouts
|
|
void inputdevice_setkeytranslation (struct uae_input_device_kbr_default **trans, int **kbmaps)
|
|
{
|
|
keyboard_default_table = trans;
|
|
keyboard_default_kbmaps = kbmaps;
|
|
}
|
|
|
|
// return true if keyboard/scancode pair is mapped
|
|
int inputdevice_iskeymapped (int keyboard, int scancode)
|
|
{
|
|
struct uae_input_device *na = &keyboards[keyboard];
|
|
|
|
if (!keyboards || scancode < 0)
|
|
return 0;
|
|
return scancodeused[keyboard][scancode];
|
|
}
|
|
|
|
int inputdevice_synccapslock (int oldcaps, int *capstable)
|
|
{
|
|
struct uae_input_device *na = &keyboards[0];
|
|
int j, i;
|
|
|
|
if (!keyboards)
|
|
return -1;
|
|
for (j = 0; na->extra[j]; j++) {
|
|
if (na->extra[j] == INPUTEVENT_KEY_CAPS_LOCK) {
|
|
for (i = 0; capstable[i]; i += 2) {
|
|
if (na->extra[j] == capstable[i]) {
|
|
if (oldcaps != capstable[i + 1]) {
|
|
oldcaps = capstable[i + 1];
|
|
inputdevice_translatekeycode (0, capstable[i], oldcaps ? -1 : 0);
|
|
}
|
|
return i;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
static void rqualifiers (uae_u64 flags, bool release)
|
|
{
|
|
uae_u64 mask = ID_FLAG_QUALIFIER1 << 1;
|
|
for (int i = 0; i < MAX_INPUT_QUALIFIERS; i++) {
|
|
if ((flags & mask) && (mask & (qualifiers << 1))) {
|
|
if (release) {
|
|
if (!(mask & qualifiers_r)) {
|
|
qualifiers_r |= mask;
|
|
for (int ii = 0; ii < MAX_INPUT_SUB_EVENT; ii++) {
|
|
int qevt = qualifiers_evt[i][ii];
|
|
if (qevt > 0) {
|
|
write_log (_T("Released %d '%s'\n"), qevt, events[qevt].name);
|
|
inputdevice_do_keyboard (events[qevt].data, 0);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
if ((mask & qualifiers_r)) {
|
|
qualifiers_r &= ~mask;
|
|
for (int ii = 0; ii < MAX_INPUT_SUB_EVENT; ii++) {
|
|
int qevt = qualifiers_evt[i][ii];
|
|
if (qevt > 0) {
|
|
write_log (_T("Pressed %d '%s'\n"), qevt, events[qevt].name);
|
|
inputdevice_do_keyboard (events[qevt].data, 1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
mask <<= 2;
|
|
}
|
|
}
|
|
|
|
static int inputdevice_translatekeycode_2 (int keyboard, int scancode, int state, bool qualifiercheckonly)
|
|
{
|
|
struct uae_input_device *na = &keyboards[keyboard];
|
|
int j, k;
|
|
int handled = 0;
|
|
bool didcustom = false;
|
|
|
|
if (!keyboards || scancode < 0)
|
|
return handled;
|
|
|
|
// if (!state)
|
|
// process_custom_event (NULL, 0, 0, 0, 0, 0);
|
|
|
|
j = 0;
|
|
while (j < MAX_INPUT_DEVICE_EVENTS && na->extra[j] >= 0) {
|
|
if (na->extra[j] == scancode) {
|
|
bool qualonly;
|
|
uae_u64 qualmask[MAX_INPUT_SUB_EVENT];
|
|
getqualmask (qualmask, na, j, &qualonly);
|
|
|
|
if (qualonly)
|
|
qualifiercheckonly = true;
|
|
for (k = 0; k < MAX_INPUT_SUB_EVENT; k++) {/* send key release events in reverse order */
|
|
uae_u64 *flagsp = &na->flags[j][sublevdir[state == 0 ? 1 : 0][k]];
|
|
int evt = na->eventid[j][sublevdir[state == 0 ? 1 : 0][k]];
|
|
uae_u64 flags = *flagsp;
|
|
int autofire = (flags & ID_FLAG_AUTOFIRE) ? 1 : 0;
|
|
int toggle = (flags & ID_FLAG_TOGGLE) ? 1 : 0;
|
|
int inverttoggle = (flags & ID_FLAG_INVERTTOGGLE) ? 1 : 0;
|
|
int toggled;
|
|
|
|
setqualifiers (evt, state > 0);
|
|
|
|
if (qualifiercheckonly) {
|
|
if (!state && (flags & ID_FLAG_CANRELEASE)) {
|
|
*flagsp &= ~ID_FLAG_CANRELEASE;
|
|
handle_input_event (evt, state, 1, autofire, true, false);
|
|
if (k == 0) {
|
|
process_custom_event (na, j, state, qualmask, autofire, k);
|
|
}
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if (!state) {
|
|
didcustom |= process_custom_event (na, j, state, qualmask, autofire, k);
|
|
}
|
|
|
|
// if evt == caps and scan == caps: sync with native caps led
|
|
if (evt == INPUTEVENT_KEY_CAPS_LOCK) {
|
|
int v;
|
|
if (state < 0)
|
|
state = 1;
|
|
v = target_checkcapslock (scancode, &state);
|
|
if (v < 0)
|
|
continue;
|
|
if (v > 0)
|
|
toggle = 0;
|
|
} else if (state < 0) {
|
|
// it was caps lock resync, ignore, not mapped to caps
|
|
continue;
|
|
}
|
|
|
|
if (inverttoggle) {
|
|
na->flags[j][sublevdir[state == 0 ? 1 : 0][k]] &= ~ID_FLAG_TOGGLED;
|
|
if (state) {
|
|
queue_input_event (evt, NULL, -1, 0, 0, 1);
|
|
handled |= handle_input_event (evt, 1, 1, 0, true, false);
|
|
} else {
|
|
handled |= handle_input_event (evt, 1, 1, autofire, true, false);
|
|
}
|
|
didcustom |= process_custom_event (na, j, state, qualmask, autofire, k);
|
|
} else if (toggle) {
|
|
if (!state)
|
|
continue;
|
|
if (!checkqualifiers (evt, flags, qualmask, na->eventid[j]))
|
|
continue;
|
|
*flagsp ^= ID_FLAG_TOGGLED;
|
|
toggled = (*flagsp & ID_FLAG_TOGGLED) ? 1 : 0;
|
|
handled |= handle_input_event (evt, toggled, 1, autofire, true, false);
|
|
if (k == 0)
|
|
didcustom |= process_custom_event (na, j, state, qualmask, autofire, k);
|
|
} else {
|
|
rqualifiers (flags, state ? true : false);
|
|
if (!checkqualifiers (evt, flags, qualmask, na->eventid[j])) {
|
|
if (!state && !(flags & ID_FLAG_CANRELEASE))
|
|
continue;
|
|
else if (state)
|
|
continue;
|
|
}
|
|
|
|
if (state) {
|
|
*flagsp |= ID_FLAG_CANRELEASE;
|
|
} else {
|
|
if (!(flags & ID_FLAG_CANRELEASE))
|
|
continue;
|
|
*flagsp &= ~ID_FLAG_CANRELEASE;
|
|
}
|
|
handled |= handle_input_event (evt, state, 1, autofire, true, false);
|
|
didcustom |= process_custom_event (na, j, state, qualmask, autofire, k);
|
|
}
|
|
}
|
|
if (!didcustom)
|
|
queue_input_event (-1, NULL, -1, 0, 0, 1);
|
|
return handled;
|
|
}
|
|
j++;
|
|
}
|
|
return handled;
|
|
}
|
|
|
|
#define IECODE_UP_PREFIX 0x80
|
|
#define RAW_STEALTH 0x68
|
|
#define STEALTHF_E0KEY 0x08
|
|
#define STEALTHF_UPSTROKE 0x04
|
|
#define STEALTHF_SPECIAL 0x02
|
|
#define STEALTHF_E1KEY 0x01
|
|
|
|
static void sendmmcodes (int code, int newstate)
|
|
{
|
|
uae_u8 b;
|
|
|
|
b = RAW_STEALTH | IECODE_UP_PREFIX;
|
|
record_key (((b << 1) | (b >> 7)) & 0xff);
|
|
b = IECODE_UP_PREFIX;
|
|
if ((code >> 8) == 0x01)
|
|
b |= STEALTHF_E0KEY;
|
|
if ((code >> 8) == 0x02)
|
|
b |= STEALTHF_E1KEY;
|
|
if (!newstate)
|
|
b |= STEALTHF_UPSTROKE;
|
|
record_key(((b << 1) | (b >> 7)) & 0xff);
|
|
b = ((code >> 4) & 0x0f) | IECODE_UP_PREFIX;
|
|
record_key(((b << 1) | (b >> 7)) & 0xff);
|
|
b = (code & 0x0f) | IECODE_UP_PREFIX;
|
|
record_key(((b << 1) | (b >> 7)) & 0xff);
|
|
}
|
|
|
|
// main keyboard press/release entry point
|
|
int inputdevice_translatekeycode (int keyboard, int scancode, int state)
|
|
{
|
|
if (inputdevice_translatekeycode_2 (keyboard, scancode, state, false))
|
|
return 1;
|
|
if (currprefs.mmkeyboard && scancode > 0)
|
|
sendmmcodes (scancode, state);
|
|
return 0;
|
|
}
|
|
void inputdevice_checkqualifierkeycode (int keyboard, int scancode, int state)
|
|
{
|
|
inputdevice_translatekeycode_2 (keyboard, scancode, state, true);
|
|
}
|
|
|
|
static const TCHAR *internaleventlabels[] = {
|
|
_T("CPU reset"),
|
|
_T("Keyboard reset"),
|
|
NULL
|
|
};
|
|
static int init_int (void)
|
|
{
|
|
return 1;
|
|
}
|
|
static void close_int (void)
|
|
{
|
|
}
|
|
static int acquire_int (int num, int flags)
|
|
{
|
|
return 1;
|
|
}
|
|
static void unacquire_int (int num)
|
|
{
|
|
}
|
|
static void read_int (void)
|
|
{
|
|
}
|
|
static int get_int_num (void)
|
|
{
|
|
return 1;
|
|
}
|
|
static TCHAR *get_int_friendlyname (int num)
|
|
{
|
|
return _T("Internal events");
|
|
}
|
|
static TCHAR *get_int_uniquename (int num)
|
|
{
|
|
return _T("INTERNALEVENTS1");
|
|
}
|
|
static int get_int_widget_num (int num)
|
|
{
|
|
int i;
|
|
for (i = 0; internaleventlabels[i]; i++);
|
|
return i;
|
|
}
|
|
static int get_int_widget_type (int kb, int num, TCHAR *name, uae_u32 *code)
|
|
{
|
|
if (code)
|
|
*code = num;
|
|
if (name)
|
|
_tcscpy (name, internaleventlabels[num]);
|
|
return IDEV_WIDGET_BUTTON;
|
|
}
|
|
static int get_int_widget_first (int kb, int type)
|
|
{
|
|
return 0;
|
|
}
|
|
static int get_int_flags (int num)
|
|
{
|
|
return 0;
|
|
}
|
|
static struct inputdevice_functions inputdevicefunc_internalevent = {
|
|
init_int, close_int, acquire_int, unacquire_int, read_int,
|
|
get_int_num, get_int_friendlyname, get_int_uniquename,
|
|
get_int_widget_num, get_int_widget_type,
|
|
get_int_widget_first,
|
|
get_int_flags
|
|
};
|
|
|
|
void send_internalevent (int eventid)
|
|
{
|
|
setbuttonstateall (&internalevents[0], NULL, eventid, -1);
|
|
}
|
|
|
|
|
|
void inputdevice_init (void)
|
|
{
|
|
idev[IDTYPE_JOYSTICK] = inputdevicefunc_joystick;
|
|
idev[IDTYPE_JOYSTICK].init ();
|
|
idev[IDTYPE_MOUSE] = inputdevicefunc_mouse;
|
|
idev[IDTYPE_MOUSE].init ();
|
|
idev[IDTYPE_KEYBOARD] = inputdevicefunc_keyboard;
|
|
idev[IDTYPE_KEYBOARD].init ();
|
|
idev[IDTYPE_INTERNALEVENT] = inputdevicefunc_internalevent;
|
|
idev[IDTYPE_INTERNALEVENT].init ();
|
|
}
|
|
|
|
void inputdevice_close (void)
|
|
{
|
|
idev[IDTYPE_JOYSTICK].close ();
|
|
idev[IDTYPE_MOUSE].close ();
|
|
idev[IDTYPE_KEYBOARD].close ();
|
|
idev[IDTYPE_INTERNALEVENT].close ();
|
|
inprec_close (true);
|
|
}
|
|
|
|
static struct uae_input_device *get_uid (const struct inputdevice_functions *id, int devnum)
|
|
{
|
|
struct uae_input_device *uid = 0;
|
|
if (id == &idev[IDTYPE_JOYSTICK]) {
|
|
uid = &joysticks[devnum];
|
|
} else if (id == &idev[IDTYPE_MOUSE]) {
|
|
uid = &mice[devnum];
|
|
} else if (id == &idev[IDTYPE_KEYBOARD]) {
|
|
uid = &keyboards[devnum];
|
|
} else if (id == &idev[IDTYPE_INTERNALEVENT]) {
|
|
uid = &internalevents[devnum];
|
|
}
|
|
return uid;
|
|
}
|
|
|
|
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)
|
|
{
|
|
const struct uae_input_device *uid = get_uid (id, devnum);
|
|
int type = id->get_widget_type (devnum, num, 0, 0);
|
|
int i;
|
|
if (type == IDEV_WIDGET_BUTTON || type == IDEV_WIDGET_BUTTONAXIS) {
|
|
i = num - id->get_widget_first (devnum, IDEV_WIDGET_BUTTON) + ID_BUTTON_OFFSET;
|
|
*eventid = uid->eventid[i][sub];
|
|
if (flags)
|
|
*flags = uid->flags[i][sub];
|
|
if (port)
|
|
*port = uid->port[i][sub];
|
|
if (custom)
|
|
*custom = uid->custom[i][sub];
|
|
return i;
|
|
} else if (type == IDEV_WIDGET_AXIS) {
|
|
i = num - id->get_widget_first (devnum, type) + ID_AXIS_OFFSET;
|
|
*eventid = uid->eventid[i][sub];
|
|
if (flags)
|
|
*flags = uid->flags[i][sub];
|
|
if (port)
|
|
*port = uid->port[i][sub];
|
|
if (custom)
|
|
*custom = uid->custom[i][sub];
|
|
return i;
|
|
} else if (type == IDEV_WIDGET_KEY) {
|
|
i = num - id->get_widget_first (devnum, type);
|
|
*eventid = uid->eventid[i][sub];
|
|
if (flags)
|
|
*flags = uid->flags[i][sub];
|
|
if (port)
|
|
*port = uid->port[i][sub];
|
|
if (custom)
|
|
*custom = uid->custom[i][sub];
|
|
return i;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
static TCHAR *stripstrdup (const TCHAR *s)
|
|
{
|
|
TCHAR *out = my_strdup (s);
|
|
if (!out)
|
|
return NULL;
|
|
for (int i = 0; out[i]; i++) {
|
|
if (out[i] < ' ')
|
|
out[i] = ' ';
|
|
}
|
|
return out;
|
|
}
|
|
|
|
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)
|
|
{
|
|
struct uae_input_device *uid = get_uid (id, devnum);
|
|
int type = id->get_widget_type (devnum, num, 0, 0);
|
|
int i, ret;
|
|
|
|
for (i = 0; i < MAX_INPUT_QUALIFIERS; i++) {
|
|
uae_u64 mask1 = ID_FLAG_QUALIFIER1 << (i * 2);
|
|
uae_u64 mask2 = mask1 << 1;
|
|
if ((flags & (mask1 | mask2)) == (mask1 | mask2))
|
|
flags &= ~mask2;
|
|
}
|
|
if (custom && custom[0] == 0) {
|
|
custom = NULL;
|
|
eventid = 0;
|
|
}
|
|
if (eventid <= 0 && !custom) {
|
|
flags = 0;
|
|
}
|
|
|
|
ret = -1;
|
|
if (type == IDEV_WIDGET_BUTTON || type == IDEV_WIDGET_BUTTONAXIS) {
|
|
i = num - id->get_widget_first (devnum, IDEV_WIDGET_BUTTON) + ID_BUTTON_OFFSET;
|
|
uid->eventid[i][sub] = eventid;
|
|
uid->flags[i][sub] = flags;
|
|
uid->port[i][sub] = port;
|
|
xfree (uid->custom[i][sub]);
|
|
uid->custom[i][sub] = custom && _tcslen (custom) > 0 ? stripstrdup (custom) : NULL;
|
|
ret = i;
|
|
} else if (type == IDEV_WIDGET_AXIS) {
|
|
i = num - id->get_widget_first (devnum, type) + ID_AXIS_OFFSET;
|
|
uid->eventid[i][sub] = eventid;
|
|
uid->flags[i][sub] = flags;
|
|
uid->port[i][sub] = port;
|
|
xfree (uid->custom[i][sub]);
|
|
uid->custom[i][sub] = custom && _tcslen (custom) > 0 ? stripstrdup (custom) : NULL;
|
|
ret = i;
|
|
} else if (type == IDEV_WIDGET_KEY) {
|
|
i = num - id->get_widget_first (devnum, type);
|
|
uid->eventid[i][sub] = eventid;
|
|
uid->flags[i][sub] = flags;
|
|
uid->port[i][sub] = port;
|
|
xfree (uid->custom[i][sub]);
|
|
uid->custom[i][sub] = custom && _tcslen (custom) > 0 ? stripstrdup (custom) : NULL;
|
|
ret = i;
|
|
}
|
|
if (ret < 0)
|
|
return -1;
|
|
if (uid->custom[i][sub])
|
|
uid->eventid[i][sub] = INPUTEVENT_SPC_CUSTOM_EVENT;
|
|
return ret;
|
|
}
|
|
|
|
static int is_event_used (const struct inputdevice_functions *id, int devnum, int isnum, int isevent)
|
|
{
|
|
struct uae_input_device *uid = get_uid (id, devnum);
|
|
int num, evt, sub;
|
|
|
|
for (num = 0; num < id->get_widget_num (devnum); num++) {
|
|
for (sub = 0; sub < MAX_INPUT_SUB_EVENT; sub++) {
|
|
if (get_event_data (id, devnum, num, &evt, NULL, NULL, NULL, sub) >= 0) {
|
|
if (evt == isevent && isnum != num)
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// device based index from global device index
|
|
int inputdevice_get_device_index (int devnum)
|
|
{
|
|
int jcnt = idev[IDTYPE_JOYSTICK].get_num ();
|
|
int mcnt = idev[IDTYPE_MOUSE].get_num ();
|
|
int kcnt = idev[IDTYPE_KEYBOARD].get_num ();
|
|
|
|
if (devnum < jcnt)
|
|
return devnum;
|
|
else if (devnum < jcnt + mcnt)
|
|
return devnum - jcnt;
|
|
else if (devnum < jcnt + mcnt + kcnt)
|
|
return devnum - (jcnt + mcnt);
|
|
else if (devnum < jcnt + mcnt + kcnt + INTERNALEVENT_COUNT)
|
|
return devnum - (jcnt + mcnt + kcnt);
|
|
return -1;
|
|
}
|
|
|
|
static int getdevnum (int type, int devnum)
|
|
{
|
|
int jcnt = idev[IDTYPE_JOYSTICK].get_num ();
|
|
int mcnt = idev[IDTYPE_MOUSE].get_num ();
|
|
int kcnt = idev[IDTYPE_KEYBOARD].get_num ();
|
|
|
|
if (type == IDTYPE_JOYSTICK)
|
|
return devnum;
|
|
else if (type == IDTYPE_MOUSE)
|
|
return jcnt + devnum;
|
|
else if (type == IDTYPE_KEYBOARD)
|
|
return jcnt + mcnt + devnum;
|
|
else if (type == IDTYPE_INTERNALEVENT)
|
|
return jcnt + mcnt + kcnt + devnum;
|
|
return -1;
|
|
}
|
|
|
|
static int gettype (int devnum)
|
|
{
|
|
int jcnt = idev[IDTYPE_JOYSTICK].get_num ();
|
|
int mcnt = idev[IDTYPE_MOUSE].get_num ();
|
|
int kcnt = idev[IDTYPE_KEYBOARD].get_num ();
|
|
|
|
if (devnum < jcnt)
|
|
return IDTYPE_JOYSTICK;
|
|
else if (devnum < jcnt + mcnt)
|
|
return IDTYPE_MOUSE;
|
|
else if (devnum < jcnt + mcnt + kcnt)
|
|
return IDTYPE_KEYBOARD;
|
|
else if (devnum < jcnt + mcnt + kcnt + INTERNALEVENT_COUNT)
|
|
return IDTYPE_INTERNALEVENT;
|
|
return -1;
|
|
}
|
|
|
|
static struct inputdevice_functions *getidf (int devnum)
|
|
{
|
|
int type = gettype (devnum);
|
|
if (type < 0)
|
|
return NULL;
|
|
return &idev[type];
|
|
}
|
|
|
|
struct inputevent *inputdevice_get_eventinfo (int evt)
|
|
{
|
|
return &events[evt];
|
|
}
|
|
|
|
|
|
/* returns number of devices of type "type" */
|
|
int inputdevice_get_device_total (int type)
|
|
{
|
|
return idev[type].get_num ();
|
|
}
|
|
/* returns the name of device */
|
|
TCHAR *inputdevice_get_device_name (int type, int devnum)
|
|
{
|
|
return idev[type].get_friendlyname (devnum);
|
|
}
|
|
/* returns the name of device */
|
|
TCHAR *inputdevice_get_device_name2 (int devnum)
|
|
{
|
|
return getidf (devnum)->get_friendlyname (inputdevice_get_device_index (devnum));
|
|
}
|
|
/* returns machine readable name of device */
|
|
TCHAR *inputdevice_get_device_unique_name (int type, int devnum)
|
|
{
|
|
return idev[type].get_uniquename (devnum);
|
|
}
|
|
/* returns state (enabled/disabled) */
|
|
int inputdevice_get_device_status (int devnum)
|
|
{
|
|
const struct inputdevice_functions *idf = getidf (devnum);
|
|
if (idf == NULL)
|
|
return -1;
|
|
struct uae_input_device *uid = get_uid (idf, inputdevice_get_device_index (devnum));
|
|
return uid->enabled;
|
|
}
|
|
|
|
/* set state (enabled/disabled) */
|
|
void inputdevice_set_device_status (int devnum, int enabled)
|
|
{
|
|
const struct inputdevice_functions *idf = getidf (devnum);
|
|
int num = inputdevice_get_device_index (devnum);
|
|
struct uae_input_device *uid = get_uid (idf, num);
|
|
if (enabled) { // disable incompatible devices ("super device" vs "raw device")
|
|
for (int i = 0; i < idf->get_num (); i++) {
|
|
if (idf->get_flags (i) != idf->get_flags (num)) {
|
|
struct uae_input_device *uid2 = get_uid (idf, i);
|
|
uid2->enabled = 0;
|
|
}
|
|
}
|
|
}
|
|
uid->enabled = enabled;
|
|
}
|
|
|
|
/* returns number of axis/buttons and keys from selected device */
|
|
int inputdevice_get_widget_num (int devnum)
|
|
{
|
|
const struct inputdevice_functions *idf = getidf (devnum);
|
|
return idf->get_widget_num (inputdevice_get_device_index (devnum));
|
|
}
|
|
|
|
// return name of event, do not use ie->name directly
|
|
bool inputdevice_get_eventname (const struct inputevent *ie, TCHAR *out)
|
|
{
|
|
if (!out)
|
|
return false;
|
|
_tcscpy (out, ie->name);
|
|
return true;
|
|
}
|
|
|
|
int inputdevice_iterate (int devnum, int num, TCHAR *name, int *af)
|
|
{
|
|
const struct inputdevice_functions *idf = getidf (devnum);
|
|
static int id_iterator;
|
|
struct inputevent *ie;
|
|
int mask, data, type;
|
|
uae_u64 flags;
|
|
int devindex = inputdevice_get_device_index (devnum);
|
|
|
|
*af = 0;
|
|
*name = 0;
|
|
for (;;) {
|
|
ie = &events[++id_iterator];
|
|
if (!ie->confname) {
|
|
id_iterator = 0;
|
|
return 0;
|
|
}
|
|
mask = 0;
|
|
type = idf->get_widget_type (devindex, num, NULL, NULL);
|
|
if (type == IDEV_WIDGET_BUTTON || type == IDEV_WIDGET_BUTTONAXIS) {
|
|
if (idf == &idev[IDTYPE_JOYSTICK]) {
|
|
mask |= AM_JOY_BUT;
|
|
} else {
|
|
mask |= AM_MOUSE_BUT;
|
|
}
|
|
} else if (type == IDEV_WIDGET_AXIS) {
|
|
if (idf == &idev[IDTYPE_JOYSTICK]) {
|
|
mask |= AM_JOY_AXIS;
|
|
} else {
|
|
mask |= AM_MOUSE_AXIS;
|
|
}
|
|
} else if (type == IDEV_WIDGET_KEY) {
|
|
mask |= AM_K;
|
|
}
|
|
if (ie->allow_mask & AM_INFO) {
|
|
struct inputevent *ie2 = ie + 1;
|
|
while (!(ie2->allow_mask & AM_INFO)) {
|
|
if (is_event_used (idf, devindex, ie2 - ie, -1)) {
|
|
ie2++;
|
|
continue;
|
|
}
|
|
if (ie2->allow_mask & mask)
|
|
break;
|
|
ie2++;
|
|
}
|
|
if (!(ie2->allow_mask & AM_INFO))
|
|
mask |= AM_INFO;
|
|
}
|
|
if (!(ie->allow_mask & mask))
|
|
continue;
|
|
get_event_data (idf, devindex, num, &data, NULL, &flags, NULL, 0);
|
|
inputdevice_get_eventname (ie, name);
|
|
*af = (flags & ID_FLAG_AUTOFIRE) ? 1 : 0;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
// return mapped event from devnum/num/sub
|
|
int inputdevice_get_mapping (int devnum, int num, uae_u64 *pflags, int *pport, TCHAR *name, TCHAR *custom, int sub)
|
|
{
|
|
const struct inputdevice_functions *idf = getidf (devnum);
|
|
const struct uae_input_device *uid = get_uid (idf, inputdevice_get_device_index (devnum));
|
|
int port, data;
|
|
uae_u64 flags = 0, flag;
|
|
int devindex = inputdevice_get_device_index (devnum);
|
|
TCHAR *customp = NULL;
|
|
|
|
if (name)
|
|
_tcscpy (name, _T("<none>"));
|
|
if (custom)
|
|
custom[0] = 0;
|
|
if (pflags)
|
|
*pflags = 0;
|
|
if (pport)
|
|
*pport = 0;
|
|
if (uid == 0 || num < 0)
|
|
return 0;
|
|
if (get_event_data (idf, devindex, num, &data, &customp, &flag, &port, sub) < 0)
|
|
return 0;
|
|
if (customp && custom)
|
|
_tcscpy (custom, customp);
|
|
if (flag & ID_FLAG_AUTOFIRE)
|
|
flags |= IDEV_MAPPED_AUTOFIRE_SET;
|
|
if (flag & ID_FLAG_TOGGLE)
|
|
flags |= IDEV_MAPPED_TOGGLE;
|
|
if (flag & ID_FLAG_INVERTTOGGLE)
|
|
flags |= IDEV_MAPPED_INVERTTOGGLE;
|
|
if (flag & ID_FLAG_GAMEPORTSCUSTOM1)
|
|
flags |= IDEV_MAPPED_GAMEPORTSCUSTOM1;
|
|
if (flag & ID_FLAG_GAMEPORTSCUSTOM2)
|
|
flags |= IDEV_MAPPED_GAMEPORTSCUSTOM2;
|
|
if (flag & ID_FLAG_QUALIFIER_MASK)
|
|
flags |= flag & ID_FLAG_QUALIFIER_MASK;
|
|
if (pflags)
|
|
*pflags = flags;
|
|
if (pport)
|
|
*pport = port;
|
|
if (!data)
|
|
return 0;
|
|
if (events[data].allow_mask & AM_AF)
|
|
flags |= IDEV_MAPPED_AUTOFIRE_POSSIBLE;
|
|
if (pflags)
|
|
*pflags = flags;
|
|
inputdevice_get_eventname (&events[data], name);
|
|
return data;
|
|
}
|
|
|
|
// set event name/custom/flags to devnum/num/sub
|
|
int inputdevice_set_mapping (int devnum, int num, const TCHAR *name, TCHAR *custom, uae_u64 flags, int port, int sub)
|
|
{
|
|
const struct inputdevice_functions *idf = getidf (devnum);
|
|
const struct uae_input_device *uid = get_uid (idf, inputdevice_get_device_index (devnum));
|
|
int eid, data, portp, amask;
|
|
uae_u64 flag;
|
|
TCHAR ename[256];
|
|
int devindex = inputdevice_get_device_index (devnum);
|
|
TCHAR *customp = NULL;
|
|
|
|
if (uid == 0 || num < 0)
|
|
return 0;
|
|
if (name) {
|
|
eid = 1;
|
|
while (events[eid].name) {
|
|
inputdevice_get_eventname (&events[eid], ename);
|
|
if (!_tcscmp(ename, name))
|
|
break;
|
|
eid++;
|
|
}
|
|
if (!events[eid].name)
|
|
return 0;
|
|
if (events[eid].allow_mask & AM_INFO)
|
|
return 0;
|
|
} else {
|
|
eid = 0;
|
|
}
|
|
if (get_event_data (idf, devindex, num, &data, &customp, &flag, &portp, sub) < 0)
|
|
return 0;
|
|
if (data >= 0) {
|
|
amask = events[eid].allow_mask;
|
|
flag &= ~(ID_FLAG_AUTOFIRE_MASK | ID_FLAG_GAMEPORTSCUSTOM_MASK | IDEV_MAPPED_QUALIFIER_MASK);
|
|
if (amask & AM_AF) {
|
|
flag |= (flags & IDEV_MAPPED_AUTOFIRE_SET) ? ID_FLAG_AUTOFIRE : 0;
|
|
flag |= (flags & IDEV_MAPPED_TOGGLE) ? ID_FLAG_TOGGLE : 0;
|
|
flag |= (flags & IDEV_MAPPED_INVERTTOGGLE) ? ID_FLAG_INVERTTOGGLE : 0;
|
|
}
|
|
flag |= (flags & IDEV_MAPPED_GAMEPORTSCUSTOM1) ? ID_FLAG_GAMEPORTSCUSTOM1 : 0;
|
|
flag |= (flags & IDEV_MAPPED_GAMEPORTSCUSTOM2) ? ID_FLAG_GAMEPORTSCUSTOM2 : 0;
|
|
flag |= flags & IDEV_MAPPED_QUALIFIER_MASK;
|
|
if (port >= 0)
|
|
portp = port;
|
|
put_event_data (idf, devindex, num, eid, custom, flag, portp, sub);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int inputdevice_get_widget_type (int devnum, int num, TCHAR *name)
|
|
{
|
|
const struct inputdevice_functions *idf = getidf (devnum);
|
|
return idf->get_widget_type (inputdevice_get_device_index (devnum), num, name, 0);
|
|
}
|
|
|
|
static int config_change;
|
|
|
|
void inputdevice_config_change (void)
|
|
{
|
|
config_change = 1;
|
|
}
|
|
|
|
int inputdevice_config_change_test (void)
|
|
{
|
|
int v = config_change;
|
|
config_change = 0;
|
|
return v;
|
|
}
|
|
|
|
// copy configuration #src to configuration #dst
|
|
void inputdevice_copyconfig (const struct uae_prefs *src, struct uae_prefs *dst)
|
|
{
|
|
int i, j;
|
|
|
|
dst->input_selected_setting = src->input_selected_setting;
|
|
dst->input_joymouse_multiplier = src->input_joymouse_multiplier;
|
|
dst->input_joymouse_deadzone = src->input_joymouse_deadzone;
|
|
dst->input_joystick_deadzone = src->input_joystick_deadzone;
|
|
dst->input_joymouse_speed = src->input_joymouse_speed;
|
|
dst->input_mouse_speed = src->input_mouse_speed;
|
|
dst->input_autofire_linecnt = src->input_autofire_linecnt;
|
|
copyjport (src, dst, 0);
|
|
copyjport (src, dst, 1);
|
|
copyjport (src, dst, 2);
|
|
copyjport (src, dst, 3);
|
|
|
|
for (i = 0; i < MAX_INPUT_SETTINGS; i++) {
|
|
for (j = 0; j < MAX_INPUT_DEVICES; j++) {
|
|
memcpy (&dst->joystick_settings[i][j], &src->joystick_settings[i][j], sizeof (struct uae_input_device));
|
|
memcpy (&dst->mouse_settings[i][j], &src->mouse_settings[i][j], sizeof (struct uae_input_device));
|
|
memcpy (&dst->keyboard_settings[i][j], &src->keyboard_settings[i][j], sizeof (struct uae_input_device));
|
|
}
|
|
}
|
|
|
|
inputdevice_updateconfig (dst);
|
|
}
|
|
|
|
static void swapjoydevice (struct uae_input_device *uid, int **swaps)
|
|
{
|
|
for (int i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++) {
|
|
for (int j = 0; j < MAX_INPUT_SUB_EVENT; j++) {
|
|
bool found = false;
|
|
for (int k = 0; k < 2 && !found; k++) {
|
|
int evtnum;
|
|
for (int kk = 0; (evtnum = swaps[k][kk]) >= 0 && !found; kk++) {
|
|
if (uid->eventid[i][j] == evtnum) {
|
|
uid->eventid[i][j] = swaps[1 - k][kk];
|
|
found = true;
|
|
} else {
|
|
for (int jj = 0; axistable[jj] >= 0; jj += 3) {
|
|
if (evtnum == axistable[jj] || evtnum == axistable[jj + 1] || evtnum == axistable[jj + 2]) {
|
|
for (int ii = 0; ii < 3; ii++) {
|
|
if (uid->eventid[i][j] == axistable[jj + ii]) {
|
|
int evtnum2 = swaps[1 - k][kk];
|
|
for (int m = 0; axistable[m] >= 0; m += 3) {
|
|
if (evtnum2 == axistable[m] || evtnum2 == axistable[m + 1] || evtnum2 == axistable[m + 2]) {
|
|
uid->eventid[i][j] = axistable[m + ii];
|
|
found = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// swap gameports ports, remember to handle customized ports too
|
|
void inputdevice_swap_compa_ports (struct uae_prefs *prefs, int portswap)
|
|
{
|
|
struct jport tmp;
|
|
if ((prefs->jports[portswap].id == JPORT_CUSTOM || prefs->jports[portswap + 1].id == JPORT_CUSTOM)) {
|
|
int *swaps[2];
|
|
swaps[0] = rem_ports[portswap];
|
|
swaps[1] = rem_ports[portswap + 1];
|
|
for (int l = 0; l < MAX_INPUT_DEVICES; l++) {
|
|
swapjoydevice (&prefs->joystick_settings[GAMEPORT_INPUT_SETTINGS][l], swaps);
|
|
swapjoydevice (&prefs->mouse_settings[GAMEPORT_INPUT_SETTINGS][l], swaps);
|
|
swapjoydevice (&prefs->keyboard_settings[GAMEPORT_INPUT_SETTINGS][l], swaps);
|
|
}
|
|
}
|
|
memcpy (&tmp, &prefs->jports[portswap], sizeof (struct jport));
|
|
memcpy (&prefs->jports[portswap], &prefs->jports[portswap + 1], sizeof (struct jport));
|
|
memcpy (&prefs->jports[portswap + 1], &tmp, sizeof (struct jport));
|
|
inputdevice_updateconfig (prefs);
|
|
}
|
|
|
|
// swap device "devnum" ports 0<>1 and 2<>3
|
|
void inputdevice_swap_ports (struct uae_prefs *p, int devnum)
|
|
{
|
|
const struct inputdevice_functions *idf = getidf (devnum);
|
|
struct uae_input_device *uid = get_uid (idf, inputdevice_get_device_index (devnum));
|
|
int i, j, k, event, unit;
|
|
const struct inputevent *ie, *ie2;
|
|
|
|
for (i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++) {
|
|
for (j = 0; j < MAX_INPUT_SUB_EVENT; j++) {
|
|
event = uid->eventid[i][j];
|
|
if (event <= 0)
|
|
continue;
|
|
ie = &events[event];
|
|
if (ie->unit <= 0)
|
|
continue;
|
|
unit = ie->unit;
|
|
k = 1;
|
|
while (events[k].confname) {
|
|
ie2 = &events[k];
|
|
if (ie2->type == ie->type && ie2->data == ie->data && ie2->unit - 1 == ((ie->unit - 1) ^ 1) &&
|
|
ie2->allow_mask == ie->allow_mask && uid->port[i][j] == 0) {
|
|
uid->eventid[i][j] = k;
|
|
break;
|
|
}
|
|
k++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//memcpy (p->joystick_settings[dst], p->joystick_settings[src], sizeof (struct uae_input_device) * MAX_INPUT_DEVICES);
|
|
static void copydev (struct uae_input_device *dst, struct uae_input_device *src, int selectedwidget)
|
|
{
|
|
for (int i = 0; i < MAX_INPUT_DEVICES; i++) {
|
|
for (int j = 0; j < MAX_INPUT_DEVICE_EVENTS; j++) {
|
|
if (j == selectedwidget || selectedwidget < 0) {
|
|
for (int k = 0; k < MAX_INPUT_SUB_EVENT_ALL; k++) {
|
|
xfree (dst[i].custom[j][k]);
|
|
}
|
|
}
|
|
}
|
|
if (selectedwidget < 0) {
|
|
xfree (dst[i].configname);
|
|
xfree (dst[i].name);
|
|
}
|
|
}
|
|
if (selectedwidget < 0) {
|
|
memcpy (dst, src, sizeof (struct uae_input_device) * MAX_INPUT_DEVICES);
|
|
} else {
|
|
int j = selectedwidget;
|
|
for (int i = 0; i < MAX_INPUT_DEVICES; i++) {
|
|
for (int k = 0; k < MAX_INPUT_SUB_EVENT_ALL; k++) {
|
|
dst[i].eventid[j][k] = src[i].eventid[j][k];
|
|
dst[i].custom[j][k] = src[i].custom[j][k];
|
|
dst[i].flags[j][k] = src[i].flags[j][k];
|
|
dst[i].port[j][k] = src[i].port[j][k];
|
|
}
|
|
dst[i].extra[j] = src[i].extra[j];
|
|
}
|
|
}
|
|
for (int i = 0; i < MAX_INPUT_DEVICES; i++) {
|
|
for (int j = 0; j < MAX_INPUT_DEVICE_EVENTS; j++) {
|
|
if (j == selectedwidget || selectedwidget < 0) {
|
|
for (int k = 0; k < MAX_INPUT_SUB_EVENT_ALL; k++) {
|
|
if (dst[i].custom)
|
|
dst[i].custom[j][k] = my_strdup (dst[i].custom[j][k]);
|
|
}
|
|
}
|
|
}
|
|
if (selectedwidget < 0) {
|
|
dst[i].configname = my_strdup (dst[i].configname);
|
|
dst[i].name = my_strdup (dst[i].name);
|
|
}
|
|
}
|
|
}
|
|
|
|
// copy whole configuration #x-slot to another
|
|
// +1 = default
|
|
// +2 = default (pc keyboard)
|
|
void inputdevice_copy_single_config (struct uae_prefs *p, int src, int dst, int devnum, int selectedwidget)
|
|
{
|
|
if (selectedwidget >= 0) {
|
|
if (devnum < 0)
|
|
return;
|
|
if (gettype (devnum) != IDTYPE_KEYBOARD)
|
|
return;
|
|
}
|
|
if (src >= MAX_INPUT_SETTINGS) {
|
|
if (gettype (devnum) == IDTYPE_KEYBOARD) {
|
|
p->input_keyboard_type = src > MAX_INPUT_SETTINGS ? 1 : 0;
|
|
keyboard_default = keyboard_default_table[p->input_keyboard_type];
|
|
inputdevice_default_kb (p, dst);
|
|
}
|
|
}
|
|
if (src == dst)
|
|
return;
|
|
if (src < MAX_INPUT_SETTINGS) {
|
|
if (devnum < 0 || gettype (devnum) == IDTYPE_JOYSTICK)
|
|
copydev (p->joystick_settings[dst], p->joystick_settings[src], selectedwidget);
|
|
if (devnum < 0 || gettype (devnum) == IDTYPE_MOUSE)
|
|
copydev (p->mouse_settings[dst], p->mouse_settings[src], selectedwidget);
|
|
if (devnum < 0 || gettype (devnum) == IDTYPE_KEYBOARD)
|
|
copydev (p->keyboard_settings[dst], p->keyboard_settings[src], selectedwidget);
|
|
}
|
|
}
|
|
|
|
void inputdevice_acquire (int allmode)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < MAX_INPUT_DEVICES; i++)
|
|
idev[IDTYPE_JOYSTICK].unacquire (i);
|
|
for (i = 0; i < MAX_INPUT_DEVICES; i++)
|
|
idev[IDTYPE_MOUSE].unacquire (i);
|
|
for (i = 0; i < MAX_INPUT_DEVICES; i++)
|
|
idev[IDTYPE_KEYBOARD].unacquire (i);
|
|
|
|
for (i = 0; i < MAX_INPUT_DEVICES; i++) {
|
|
if ((use_joysticks[i] && allmode >= 0) || (allmode && !idev[IDTYPE_JOYSTICK].get_flags (i)))
|
|
idev[IDTYPE_JOYSTICK].acquire (i, 0);
|
|
}
|
|
for (i = 0; i < MAX_INPUT_DEVICES; i++) {
|
|
if ((use_mice[i] && allmode >= 0) || (allmode && !idev[IDTYPE_MOUSE].get_flags (i)))
|
|
idev[IDTYPE_MOUSE].acquire (i, allmode < 0);
|
|
}
|
|
for (i = 0; i < MAX_INPUT_DEVICES; i++) {
|
|
if ((use_keyboards[i] && allmode >= 0) || (allmode < 0 && !idev[IDTYPE_KEYBOARD].get_flags (i)))
|
|
idev[IDTYPE_KEYBOARD].acquire (i, allmode < 0);
|
|
}
|
|
|
|
if (input_acquired)
|
|
return;
|
|
|
|
idev[IDTYPE_JOYSTICK].acquire (-1, 0);
|
|
idev[IDTYPE_MOUSE].acquire (-1, 0);
|
|
idev[IDTYPE_KEYBOARD].acquire (-1, 0);
|
|
// if (!input_acquired)
|
|
// write_log (_T("input devices acquired (%s)\n"), allmode ? "all" : "selected only");
|
|
input_acquired = 1;
|
|
}
|
|
|
|
void inputdevice_unacquire (void)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < MAX_INPUT_DEVICES; i++)
|
|
idev[IDTYPE_JOYSTICK].unacquire (i);
|
|
for (i = 0; i < MAX_INPUT_DEVICES; i++)
|
|
idev[IDTYPE_MOUSE].unacquire (i);
|
|
for (i = 0; i < MAX_INPUT_DEVICES; i++)
|
|
idev[IDTYPE_KEYBOARD].unacquire (i);
|
|
|
|
if (!input_acquired)
|
|
return;
|
|
|
|
input_acquired = 0;
|
|
idev[IDTYPE_JOYSTICK].unacquire (-1);
|
|
idev[IDTYPE_MOUSE].unacquire (-1);
|
|
idev[IDTYPE_KEYBOARD].unacquire (-1);
|
|
}
|
|
|
|
void inputdevice_testrecord (int type, int num, int wtype, int wnum, int state)
|
|
{
|
|
if (wnum < 0) {
|
|
testmode = -1;
|
|
return;
|
|
}
|
|
if (testmode_count >= TESTMODE_MAX)
|
|
return;
|
|
if (type == IDTYPE_KEYBOARD) {
|
|
if (wnum == 0x100) {
|
|
wnum = -1;
|
|
} else {
|
|
struct uae_input_device *na = &keyboards[num];
|
|
int j = 0;
|
|
while (j < MAX_INPUT_DEVICE_EVENTS && na->extra[j] >= 0) {
|
|
if (na->extra[j] == wnum) {
|
|
wnum = j;
|
|
break;
|
|
}
|
|
j++;
|
|
}
|
|
if (j >= MAX_INPUT_DEVICE_EVENTS || na->extra[j] < 0)
|
|
type = -1;
|
|
}
|
|
}
|
|
// wait until previous event is released before accepting new ones
|
|
for (int i = 0; i < TESTMODE_MAX; i++) {
|
|
struct teststore *ts2 = &testmode_wait[i];
|
|
if (ts2->testmode_num < 0)
|
|
continue;
|
|
if (ts2->testmode_num != num || ts2->testmode_type != type || ts2->testmode_wtype != wtype || ts2->testmode_wnum != wnum)
|
|
continue;
|
|
if (state)
|
|
continue;
|
|
ts2->testmode_num = -1;
|
|
}
|
|
if (!state)
|
|
return;
|
|
|
|
//write_log (_T("%d %d %d %d %d\n"), type, num, wtype, wnum, state);
|
|
struct teststore *ts = &testmode_data[testmode_count];
|
|
ts->testmode_type = type;
|
|
ts->testmode_num = num;
|
|
ts->testmode_wtype = wtype;
|
|
ts->testmode_wnum = wnum;
|
|
ts->testmode_state = state;
|
|
testmode_count++;
|
|
}
|
|
|
|
int inputdevice_istest (void)
|
|
{
|
|
return testmode;
|
|
}
|
|
void inputdevice_settest (int set)
|
|
{
|
|
testmode = set;
|
|
testmode_count = 0;
|
|
testmode_wait[0].testmode_num = -1;
|
|
testmode_wait[1].testmode_num = -1;
|
|
}
|
|
|
|
int inputdevice_testread_count (void)
|
|
{
|
|
inputdevice_read ();
|
|
if (testmode != 1) {
|
|
testmode = 0;
|
|
return -1;
|
|
}
|
|
return testmode_count;
|
|
}
|
|
|
|
int inputdevice_testread (int *devnum, int *wtype, int *state)
|
|
{
|
|
inputdevice_read ();
|
|
if (testmode != 1) {
|
|
testmode = 0;
|
|
return -1;
|
|
}
|
|
if (testmode_count > 0) {
|
|
testmode_count--;
|
|
struct teststore *ts = &testmode_data[testmode_count];
|
|
*devnum = getdevnum (ts->testmode_type, ts->testmode_num);
|
|
*wtype = idev[ts->testmode_type].get_widget_first (ts->testmode_num, ts->testmode_wtype) + ts->testmode_wnum;
|
|
*state = ts->testmode_state;
|
|
if (ts->testmode_state)
|
|
memcpy (&testmode_wait[testmode_count], ts, sizeof (struct teststore));
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* Call this function when host machine's joystick/joypad/etc button state changes
|
|
* This function translates button events to Amiga joybutton/joyaxis/keyboard events
|
|
*/
|
|
|
|
/* button states:
|
|
* state = -1 -> mouse wheel turned or similar (button without release)
|
|
* state = 1 -> button pressed
|
|
* state = 0 -> button released
|
|
*/
|
|
|
|
void setjoybuttonstate (int joy, int button, int state)
|
|
{
|
|
if (testmode) {
|
|
inputdevice_testrecord (IDTYPE_JOYSTICK, joy, IDEV_WIDGET_BUTTON, button, state);
|
|
if (state < 0)
|
|
inputdevice_testrecord (IDTYPE_JOYSTICK, joy, IDEV_WIDGET_BUTTON, button, 0);
|
|
return;
|
|
}
|
|
#if 0
|
|
if (ignoreoldinput (joy)) {
|
|
if (state)
|
|
switchdevice (&joysticks[joy], button, 1);
|
|
return;
|
|
}
|
|
#endif
|
|
setbuttonstateall (&joysticks[joy], &joysticks2[joy], button, state ? 1 : 0);
|
|
}
|
|
|
|
/* buttonmask = 1 = normal toggle button, 0 = mouse wheel turn or similar
|
|
*/
|
|
void setjoybuttonstateall (int joy, uae_u32 buttonbits, uae_u32 buttonmask)
|
|
{
|
|
int i;
|
|
|
|
#if 0
|
|
if (ignoreoldinput (joy))
|
|
return;
|
|
#endif
|
|
for (i = 0; i < ID_BUTTON_TOTAL; i++) {
|
|
if (buttonmask & (1 << i))
|
|
setbuttonstateall (&joysticks[joy], &joysticks2[joy], i, (buttonbits & (1 << i)) ? 1 : 0);
|
|
else if (buttonbits & (1 << i))
|
|
setbuttonstateall (&joysticks[joy], &joysticks2[joy], i, -1);
|
|
}
|
|
}
|
|
/* mouse buttons (just like joystick buttons)
|
|
*/
|
|
void setmousebuttonstateall (int mouse, uae_u32 buttonbits, uae_u32 buttonmask)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < ID_BUTTON_TOTAL; i++) {
|
|
if (buttonmask & (1 << i))
|
|
setbuttonstateall (&mice[mouse], &mice2[mouse], i, (buttonbits & (1 << i)) ? 1 : 0);
|
|
else if (buttonbits & (1 << i))
|
|
setbuttonstateall (&mice[mouse], &mice2[mouse], i, -1);
|
|
}
|
|
}
|
|
|
|
void setmousebuttonstate (int mouse, int button, int state)
|
|
{
|
|
if (testmode) {
|
|
inputdevice_testrecord (IDTYPE_MOUSE, mouse, IDEV_WIDGET_BUTTON, button, state);
|
|
return;
|
|
}
|
|
setbuttonstateall (&mice[mouse], &mice2[mouse], button, state);
|
|
}
|
|
|
|
/* same for joystick axis (analog or digital)
|
|
* (0 = center, -max = full left/top, max = full right/bottom)
|
|
*/
|
|
void setjoystickstate (int joy, int axis, int state, int max)
|
|
{
|
|
struct uae_input_device *id = &joysticks[joy];
|
|
struct uae_input_device2 *id2 = &joysticks2[joy];
|
|
int deadzone = currprefs.input_joymouse_deadzone * max / 100;
|
|
int i, v1, v2;
|
|
|
|
if (testmode) {
|
|
inputdevice_testrecord (IDTYPE_JOYSTICK, joy, IDEV_WIDGET_AXIS, axis, state);
|
|
return;
|
|
}
|
|
v1 = state;
|
|
v2 = id2->states[axis];
|
|
if (v1 < deadzone && v1 > -deadzone)
|
|
v1 = 0;
|
|
if (v2 < deadzone && v2 > -deadzone)
|
|
v2 = 0;
|
|
if (v1 == v2)
|
|
return;
|
|
if (input_play && state)
|
|
inprec_realtime ();
|
|
if (input_play)
|
|
return;
|
|
if (!joysticks[joy].enabled) {
|
|
if (v1)
|
|
switchdevice (&joysticks[joy], axis * 2 + (v1 < 0 ? 0 : 1), false);
|
|
return;
|
|
}
|
|
for (i = 0; i < MAX_INPUT_SUB_EVENT; i++)
|
|
handle_input_event (id->eventid[ID_AXIS_OFFSET + axis][i], state, max, id->flags[ID_AXIS_OFFSET + axis][i] & ID_FLAG_AUTOFIRE, true, false);
|
|
id2->states[axis] = state;
|
|
}
|
|
int getjoystickstate (int joy)
|
|
{
|
|
if (testmode)
|
|
return 1;
|
|
return joysticks[joy].enabled;
|
|
}
|
|
|
|
void setmousestate (int mouse, int axis, int data, int isabs)
|
|
{
|
|
int i, v, diff;
|
|
int *mouse_p, *oldm_p;
|
|
double d;
|
|
struct uae_input_device *id = &mice[mouse];
|
|
static double fract[MAX_INPUT_DEVICES][MAX_INPUT_DEVICE_EVENTS];
|
|
|
|
if (testmode) {
|
|
inputdevice_testrecord (IDTYPE_MOUSE, mouse, IDEV_WIDGET_AXIS, axis, data);
|
|
// fake "release" event
|
|
inputdevice_testrecord (IDTYPE_MOUSE, mouse, IDEV_WIDGET_AXIS, axis, 0);
|
|
return;
|
|
}
|
|
if (input_play)
|
|
return;
|
|
if (!mice[mouse].enabled) {
|
|
if (isabs && currprefs.input_tablet > 0) {
|
|
if (axis == 0)
|
|
lastmx = data;
|
|
else
|
|
lastmy = data;
|
|
if (axis)
|
|
mousehack_helper ();
|
|
}
|
|
return;
|
|
}
|
|
d = 0;
|
|
mouse_p = &mouse_axis[mouse][axis];
|
|
oldm_p = &oldm_axis[mouse][axis];
|
|
if (!isabs) {
|
|
// eat relative movements while in mousehack mode
|
|
if (currprefs.input_tablet == TABLET_MOUSEHACK && mousehack_alive ())
|
|
return;
|
|
*oldm_p = *mouse_p;
|
|
*mouse_p += data;
|
|
d = (*mouse_p - *oldm_p) * currprefs.input_mouse_speed / 100.0;
|
|
} else {
|
|
d = data - *oldm_p;
|
|
*oldm_p = data;
|
|
*mouse_p += d;
|
|
if (axis == 0)
|
|
lastmx = data;
|
|
else
|
|
lastmy = data;
|
|
if (axis)
|
|
mousehack_helper ();
|
|
if (currprefs.input_tablet == TABLET_MOUSEHACK && mousehack_alive ())
|
|
return;
|
|
}
|
|
v = (int)d;
|
|
fract[mouse][axis] += d - v;
|
|
diff = (int)fract[mouse][axis];
|
|
v += diff;
|
|
fract[mouse][axis] -= diff;
|
|
for (i = 0; i < MAX_INPUT_SUB_EVENT; i++)
|
|
handle_input_event (id->eventid[ID_AXIS_OFFSET + axis][i], v, 0, 0, true, false);
|
|
}
|
|
|
|
int getmousestate (int joy)
|
|
{
|
|
if (testmode)
|
|
return 1;
|
|
return mice[joy].enabled;
|
|
}
|
|
|
|
void warpmode (int mode)
|
|
{
|
|
int fr, fr2;
|
|
|
|
fr = currprefs.gfx_framerate;
|
|
if (fr == 0)
|
|
fr = -1;
|
|
fr2 = currprefs.turbo_emulation;
|
|
if (fr2 == -1)
|
|
fr2 = 0;
|
|
|
|
if (mode < 0) {
|
|
if (currprefs.turbo_emulation) {
|
|
changed_prefs.gfx_framerate = currprefs.gfx_framerate = fr2;
|
|
currprefs.turbo_emulation = 0;
|
|
} else {
|
|
currprefs.turbo_emulation = fr;
|
|
}
|
|
} else if (mode == 0 && currprefs.turbo_emulation) {
|
|
if (currprefs.turbo_emulation > 0)
|
|
changed_prefs.gfx_framerate = currprefs.gfx_framerate = fr2;
|
|
currprefs.turbo_emulation = 0;
|
|
} else if (mode > 0 && !currprefs.turbo_emulation) {
|
|
currprefs.turbo_emulation = fr;
|
|
}
|
|
if (currprefs.turbo_emulation) {
|
|
if (!currprefs.cpu_cycle_exact && !currprefs.blitter_cycle_exact)
|
|
changed_prefs.gfx_framerate = currprefs.gfx_framerate = 10;
|
|
pause_sound ();
|
|
} else {
|
|
resume_sound ();
|
|
}
|
|
compute_vsynctime ();
|
|
#ifdef RETROPLATFORM
|
|
rp_turbo_cpu (currprefs.turbo_emulation);
|
|
#endif
|
|
changed_prefs.turbo_emulation = currprefs.turbo_emulation;
|
|
config_changed = 1;
|
|
setsystime ();
|
|
}
|
|
|
|
void pausemode (int mode)
|
|
{
|
|
if (mode < 0)
|
|
pause_emulation = pause_emulation ? 0 : 9;
|
|
else
|
|
pause_emulation = mode;
|
|
config_changed = 1;
|
|
setsystime ();
|
|
}
|
|
|
|
int jsem_isjoy (int port, const struct uae_prefs *p)
|
|
{
|
|
int v = JSEM_DECODEVAL (port, p);
|
|
if (v < JSEM_JOYS)
|
|
return -1;
|
|
v -= JSEM_JOYS;
|
|
if (v >= inputdevice_get_device_total (IDTYPE_JOYSTICK))
|
|
return -1;
|
|
return v;
|
|
}
|
|
|
|
int jsem_ismouse (int port, const struct uae_prefs *p)
|
|
{
|
|
int v = JSEM_DECODEVAL (port, p);
|
|
if (v < JSEM_MICE)
|
|
return -1;
|
|
v -= JSEM_MICE;
|
|
if (v >= inputdevice_get_device_total (IDTYPE_MOUSE))
|
|
return -1;
|
|
return v;
|
|
}
|
|
|
|
int jsem_iskbdjoy (int port, const struct uae_prefs *p)
|
|
{
|
|
int v = JSEM_DECODEVAL (port, p);
|
|
if (v < JSEM_KBDLAYOUT)
|
|
return -1;
|
|
v -= JSEM_KBDLAYOUT;
|
|
if (v >= JSEM_LASTKBD)
|
|
return -1;
|
|
return v;
|
|
}
|
|
|
|
int inputdevice_joyport_config (struct uae_prefs *p, const TCHAR *value, int portnum, int mode, int type)
|
|
{
|
|
switch (type)
|
|
{
|
|
case 1:
|
|
case 2:
|
|
{
|
|
int i, j;
|
|
for (j = 0; j < MAX_JPORTS; j++) {
|
|
struct inputdevice_functions *idf;
|
|
int type = IDTYPE_MOUSE;
|
|
int idnum = JSEM_MICE;
|
|
if (j > 0) {
|
|
type = IDTYPE_JOYSTICK;
|
|
idnum = JSEM_JOYS;
|
|
}
|
|
idf = &idev[type];
|
|
for (i = 0; i < idf->get_num (); i++) {
|
|
TCHAR *name1 = idf->get_friendlyname (i);
|
|
TCHAR *name2 = idf->get_uniquename (i);
|
|
if ((name1 && !_tcscmp (name1, value)) || (name2 && !_tcscmp (name2, value))) {
|
|
p->jports[portnum].id = idnum + i;
|
|
if (mode >= 0)
|
|
p->jports[portnum].mode = mode;
|
|
config_changed = 1;
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case 0:
|
|
{
|
|
int start = JPORT_NONE, got = 0, max = -1;
|
|
const TCHAR *pp = 0;
|
|
if (_tcsncmp (value, _T("kbd"), 3) == 0) {
|
|
start = JSEM_KBDLAYOUT;
|
|
pp = value + 3;
|
|
got = 1;
|
|
max = JSEM_LASTKBD;
|
|
} else if (_tcsncmp (value, _T("joy"), 3) == 0) {
|
|
start = JSEM_JOYS;
|
|
pp = value + 3;
|
|
got = 1;
|
|
max = idev[IDTYPE_JOYSTICK].get_num ();
|
|
} else if (_tcsncmp (value, _T("mouse"), 5) == 0) {
|
|
start = JSEM_MICE;
|
|
pp = value + 5;
|
|
got = 1;
|
|
max = idev[IDTYPE_MOUSE].get_num ();
|
|
} else if (_tcscmp (value, _T("none")) == 0) {
|
|
got = 2;
|
|
} else if (_tcscmp (value, _T("custom")) == 0) {
|
|
got = 2;
|
|
start = JPORT_CUSTOM;
|
|
}
|
|
if (got) {
|
|
if (pp && max != 0) {
|
|
int v = _tstol (pp);
|
|
if (start >= 0) {
|
|
if (start == JSEM_KBDLAYOUT && v > 0)
|
|
v--;
|
|
if (v >= 0) {
|
|
if (v >= max)
|
|
v = 0;
|
|
start += v;
|
|
got = 2;
|
|
}
|
|
}
|
|
}
|
|
if (got == 2) {
|
|
p->jports[portnum].id = start;
|
|
if (mode >= 0)
|
|
p->jports[portnum].mode = mode;
|
|
config_changed = 1;
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int inputdevice_getjoyportdevice (int port, int val)
|
|
{
|
|
int idx;
|
|
if (val == JPORT_CUSTOM) {
|
|
idx = inputdevice_get_device_total (IDTYPE_JOYSTICK) + JSEM_LASTKBD;
|
|
if (port < 2)
|
|
idx += inputdevice_get_device_total (IDTYPE_MOUSE);
|
|
} else if (val < 0) {
|
|
idx = -1;
|
|
} else if (val >= JSEM_MICE) {
|
|
idx = val - JSEM_MICE;
|
|
if (idx >= inputdevice_get_device_total (IDTYPE_MOUSE))
|
|
idx = 0;
|
|
else
|
|
idx += inputdevice_get_device_total (IDTYPE_JOYSTICK);
|
|
idx += JSEM_LASTKBD;
|
|
} else if (val >= JSEM_JOYS) {
|
|
idx = val - JSEM_JOYS;
|
|
if (idx >= inputdevice_get_device_total (IDTYPE_JOYSTICK))
|
|
idx = 0;
|
|
idx += JSEM_LASTKBD;
|
|
} else {
|
|
idx = val - JSEM_KBDLAYOUT;
|
|
}
|
|
return idx;
|
|
}
|
|
|
|
// for state recorder use only!
|
|
|
|
uae_u8 *save_inputstate (int *len, uae_u8 *dstptr)
|
|
{
|
|
uae_u8 *dstbak, *dst;
|
|
|
|
if (dstptr)
|
|
dstbak = dst = dstptr;
|
|
else
|
|
dstbak = dst = xmalloc (uae_u8, 1000);
|
|
for (int i = 0; i < MAX_JPORTS; i++) {
|
|
save_u16 (joydir[i]);
|
|
save_u16 (joybutton[i]);
|
|
save_u16 (otop[i]);
|
|
save_u16 (obot[i]);
|
|
save_u16 (oleft[i]);
|
|
save_u16 (oright[i]);
|
|
}
|
|
for (int i = 0; i < NORMAL_JPORTS; i++) {
|
|
save_u16 (cd32_shifter[i]);
|
|
for (int j = 0; j < 2; j++) {
|
|
save_u16 (pot_cap[i][j]);
|
|
save_u16 (joydirpot[i][j]);
|
|
}
|
|
}
|
|
for (int i = 0; i < NORMAL_JPORTS; i++) {
|
|
for (int j = 0; j < MOUSE_AXIS_TOTAL; j++) {
|
|
save_u16 (mouse_delta[i][j]);
|
|
save_u16 (mouse_deltanoreset[i][j]);
|
|
}
|
|
save_u16 (mouse_frame_x[i]);
|
|
save_u16 (mouse_frame_y[i]);
|
|
}
|
|
*len = dst - dstbak;
|
|
return dstbak;
|
|
}
|
|
|
|
uae_u8 *restore_inputstate (uae_u8 *src)
|
|
{
|
|
for (int i = 0; i < MAX_JPORTS; i++) {
|
|
joydir[i] = restore_u16 ();
|
|
joybutton[i] = restore_u16 ();
|
|
otop[i] = restore_u16 ();
|
|
obot[i] = restore_u16 ();
|
|
oleft[i] = restore_u16 ();
|
|
oright[i] = restore_u16 ();
|
|
}
|
|
for (int i = 0; i < NORMAL_JPORTS; i++) {
|
|
cd32_shifter[i] = restore_u16 ();
|
|
for (int j = 0; j < 2; j++) {
|
|
pot_cap[i][j] = restore_u16 ();
|
|
joydirpot[i][j] = restore_u16 ();
|
|
}
|
|
}
|
|
for (int i = 0; i < NORMAL_JPORTS; i++) {
|
|
for (int j = 0; j < MOUSE_AXIS_TOTAL; j++) {
|
|
mouse_delta[i][j] = restore_u16 ();
|
|
mouse_deltanoreset[i][j] = restore_u16 ();
|
|
}
|
|
mouse_frame_x[i] = restore_u16 ();
|
|
mouse_frame_y[i] = restore_u16 ();
|
|
}
|
|
return src;
|
|
}
|
|
|
|
void clear_inputstate (void)
|
|
{
|
|
return;
|
|
for (int i = 0; i < MAX_JPORTS; i++) {
|
|
horizclear[i] = 1;
|
|
vertclear[i] = 1;
|
|
}
|
|
}
|