2358 lines
62 KiB
C
2358 lines
62 KiB
C
/*
|
|
* UAE - The Un*x Amiga Emulator
|
|
*
|
|
* joystick/mouse emulation
|
|
*
|
|
* Copyright 2001-2006 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 "keybuf.h"
|
|
#include "custom.h"
|
|
#include "xwin.h"
|
|
#include "drawing.h"
|
|
#include "memory.h"
|
|
#include "events.h"
|
|
#include "newcpu.h"
|
|
#include "autoconf.h"
|
|
#include "inputdevice.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 "savestate.h"
|
|
|
|
#include <ctype.h>
|
|
|
|
#define DIR_LEFT 1
|
|
#define DIR_RIGHT 2
|
|
#define DIR_UP 4
|
|
#define DIR_DOWN 8
|
|
|
|
struct inputevent {
|
|
const char *confname;
|
|
const char *name;
|
|
int allow_mask;
|
|
int type;
|
|
int unit;
|
|
int data;
|
|
};
|
|
|
|
#define JOYBUTTON_1 0 /* fire/left mousebutton */
|
|
#define JOYBUTTON_2 1 /* 2nd/right mousebutton */
|
|
#define JOYBUTTON_3 2 /* 3rd/middle mousebutton */
|
|
#define JOYBUTTON_CD32_PLAY 3
|
|
#define JOYBUTTON_CD32_RWD 4
|
|
#define JOYBUTTON_CD32_FFW 5
|
|
#define JOYBUTTON_CD32_GREEN 6
|
|
#define JOYBUTTON_CD32_YELLOW 7
|
|
#define JOYBUTTON_CD32_RED 8
|
|
#define JOYBUTTON_CD32_BLUE 9
|
|
|
|
#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_K (AM_KEY|AM_JOY_BUT|AM_MOUSE_BUT|AM_AF) /* generic button/switch */
|
|
|
|
/* event flags */
|
|
#define ID_FLAG_AUTOFIRE 1
|
|
|
|
#define DEFEVENT(A, B, C, D, E, F) {#A, B, C, D, E, F },
|
|
const struct inputevent events[] = {
|
|
{0, 0, AM_K, 0, 0, 0},
|
|
#include "inputevents.def"
|
|
{0, 0, 0, 0, 0, 0}
|
|
};
|
|
#undef DEFEVENT
|
|
|
|
static struct inputdevice_functions idev[3];
|
|
|
|
static int sublevdir[2][MAX_INPUT_SUB_EVENT];
|
|
|
|
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 mouse_settings_reset[MAX_INPUT_SETTINGS][MAX_INPUT_DEVICES];
|
|
static uae_u8 joystick_settings_reset[MAX_INPUT_SETTINGS][MAX_INPUT_DEVICES];
|
|
|
|
static int isdevice (const 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 char *s, const char *parm)
|
|
{
|
|
int i;
|
|
|
|
for (i = 1; events[i].name; i++) {
|
|
if (!strcmp (s, events[i].confname)) {
|
|
handle_input_event (i, atol (parm), 1, 0);
|
|
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_kbr_default *keyboard_default;
|
|
|
|
static double mouse_axis[MAX_INPUT_DEVICES][MAX_INPUT_DEVICE_EVENTS];
|
|
static double oldm_axis[MAX_INPUT_DEVICES][MAX_INPUT_DEVICE_EVENTS];
|
|
|
|
static int mouse_x[MAX_INPUT_DEVICES], mouse_y[MAX_INPUT_DEVICE_EVENTS];
|
|
static int mouse_delta[MAX_INPUT_DEVICES][MAX_INPUT_DEVICE_EVENTS];
|
|
static int mouse_deltanoreset[MAX_INPUT_DEVICES][MAX_INPUT_DEVICE_EVENTS];
|
|
static int joybutton[MAX_INPUT_DEVICES];
|
|
static unsigned int joydir[MAX_INPUT_DEVICE_EVENTS];
|
|
static int joydirpot[MAX_INPUT_DEVICE_EVENTS][2];
|
|
static int mouse_frame_x[2], mouse_frame_y[2];
|
|
|
|
static int mouse_port[2];
|
|
static int cd32_shifter[2];
|
|
static int cd32_pad_enabled[2];
|
|
static int parport_joystick_enabled;
|
|
static int oldmx[4], oldmy[4];
|
|
static int oleft[4], oright[4], otop[4], obot[4];
|
|
static int potgo_hsync;
|
|
|
|
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 event, storedstate, state, max, framecnt, nextframecnt;
|
|
};
|
|
static struct input_queue_struct input_queue[INPUT_QUEUE_SIZE];
|
|
|
|
static void out_config (FILE *f, int id, int num, const char *s1, const char *s2)
|
|
{
|
|
cfgfile_write (f, "input.%d.%s%d=%s\n", id, s1, num, s2);
|
|
}
|
|
|
|
static void write_config2 (FILE *f, int idnum, int i, int offset, const char *tmp1, const struct uae_input_device *id)
|
|
{
|
|
char tmp2[200], *p;
|
|
int event, got, j, k;
|
|
const char *custom;
|
|
|
|
p = tmp2;
|
|
got = 0;
|
|
for (j = 0; j < MAX_INPUT_SUB_EVENT; j++) {
|
|
event = id->eventid[i + offset][j];
|
|
custom = id->custom[i + offset][j];
|
|
if (custom == NULL && event <= 0) {
|
|
for (k = j + 1; k < MAX_INPUT_SUB_EVENT; k++) {
|
|
if (id->eventid[i + offset][k] > 0) break;
|
|
}
|
|
if (k == MAX_INPUT_SUB_EVENT)
|
|
break;
|
|
}
|
|
if (p > tmp2) {
|
|
*p++ = ',';
|
|
*p = 0;
|
|
}
|
|
if (custom)
|
|
sprintf (p, "'%s'.%d", custom, id->flags[i + offset][j]);
|
|
else if (event <= 0)
|
|
sprintf (p, "NULL");
|
|
else
|
|
sprintf (p, "%s.%d", events[event].confname, id->flags[i + offset][j]);
|
|
p += strlen (p);
|
|
}
|
|
if (p > tmp2)
|
|
out_config (f, idnum, i, tmp1, tmp2);
|
|
}
|
|
|
|
static void write_config (FILE *f, int idnum, int devnum, const char *name, const struct uae_input_device *id, const struct uae_input_device2 *id2)
|
|
{
|
|
char tmp1[100];
|
|
int i;
|
|
|
|
if (!isdevice (id))
|
|
return;
|
|
cfgfile_write (f, "input.%d.%s.%d.disabled=%d\n", idnum, name, devnum, id->enabled ? 0 : 1);
|
|
sprintf (tmp1, "%s.%d.axis.", name, devnum);
|
|
for (i = 0; i < ID_AXIS_TOTAL; i++)
|
|
write_config2 (f, idnum, i, ID_AXIS_OFFSET, tmp1, id);
|
|
sprintf (tmp1, "%s.%d.button." ,name, devnum);
|
|
for (i = 0; i < ID_BUTTON_TOTAL; i++)
|
|
write_config2 (f, idnum, i, ID_BUTTON_OFFSET, tmp1, id);
|
|
}
|
|
|
|
static void kbrlabel (char *s)
|
|
{
|
|
while (*s) {
|
|
*s = toupper(*s);
|
|
if (*s == ' ') *s = '_';
|
|
s++;
|
|
}
|
|
}
|
|
|
|
static void write_kbr_config (FILE *f, int idnum, int devnum, const struct uae_input_device *kbr)
|
|
{
|
|
char tmp1[200], tmp2[200], tmp3[200], *p;
|
|
int i, j, k, evt, skip;
|
|
|
|
if (!keyboard_default)
|
|
return;
|
|
i = 0;
|
|
while (i < MAX_INPUT_DEVICE_EVENTS && kbr->extra[i][0] >= 0) {
|
|
skip = 0;
|
|
k = 0;
|
|
while (keyboard_default[k].scancode >= 0) {
|
|
if (keyboard_default[k].scancode == kbr->extra[i][0]) {
|
|
skip = 1;
|
|
for (j = 1; j < MAX_INPUT_SUB_EVENT; j++) {
|
|
if (kbr->flags[i][j] || kbr->eventid[i][j] > 0)
|
|
skip = 0;
|
|
}
|
|
if (keyboard_default[k].event != kbr->eventid[i][0] || kbr->flags[i][0] != 0)
|
|
skip = 0;
|
|
break;
|
|
}
|
|
k++;
|
|
}
|
|
if (kbr->eventid[i][0] == 0 && kbr->flags[i][0] == 0 && keyboard_default[k].scancode < 0)
|
|
skip = 1;
|
|
if (skip) {
|
|
i++;
|
|
continue;
|
|
}
|
|
p = tmp2;
|
|
p[0] = 0;
|
|
for (j = 0; j < MAX_INPUT_SUB_EVENT; j++) {
|
|
const char *custom = kbr->custom[i][j];
|
|
evt = kbr->eventid[i][j];
|
|
if (custom == NULL && evt <= 0) {
|
|
for (k = j + 1; k < MAX_INPUT_SUB_EVENT; k++) {
|
|
if (kbr->eventid[i][k] > 0) break;
|
|
}
|
|
if (k == MAX_INPUT_SUB_EVENT)
|
|
break;
|
|
}
|
|
if (p > tmp2) {
|
|
*p++ = ',';
|
|
*p = 0;
|
|
}
|
|
if (custom)
|
|
sprintf (p, "'%s'.%d", custom, kbr->flags[i][j]);
|
|
else if (evt > 0)
|
|
sprintf (p, "%s.%d", events[evt].confname, kbr->flags[i][j]);
|
|
else
|
|
strcat (p, "NULL");
|
|
p += strlen(p);
|
|
}
|
|
sprintf (tmp3, "%d", kbr->extra[i][0]);
|
|
kbrlabel (tmp3);
|
|
sprintf (tmp1, "keyboard.%d.button.%s", devnum, tmp3);
|
|
cfgfile_write (f, "input.%d.%s=%s\n", idnum, tmp1, tmp2[0] ? tmp2 : "NULL");
|
|
i++;
|
|
}
|
|
}
|
|
|
|
void write_inputdevice_config (const struct uae_prefs *p, FILE *f)
|
|
{
|
|
int i, id;
|
|
|
|
cfgfile_write (f, "input.config=%d\n", p->input_selected_setting);
|
|
cfgfile_write (f, "input.joymouse_speed_analog=%d\n", p->input_joymouse_multiplier);
|
|
cfgfile_write (f, "input.joymouse_speed_digital=%d\n", p->input_joymouse_speed);
|
|
cfgfile_write (f, "input.joymouse_deadzone=%d\n", p->input_joymouse_deadzone);
|
|
cfgfile_write (f, "input.joystick_deadzone=%d\n", p->input_joystick_deadzone);
|
|
cfgfile_write (f, "input.mouse_speed=%d\n", p->input_mouse_speed);
|
|
cfgfile_write (f, "input.autofire=%d\n", p->input_autofire_framecnt);
|
|
for (id = 1; id <= MAX_INPUT_SETTINGS; id++) {
|
|
for (i = 0; i < MAX_INPUT_DEVICES; i++)
|
|
write_config (f, id, i, "joystick", &p->joystick_settings[id][i], &joysticks2[i]);
|
|
for (i = 0; i < MAX_INPUT_DEVICES; i++)
|
|
write_config (f, id, i, "mouse", &p->mouse_settings[id][i], &mice2[i]);
|
|
for (i = 0; i < MAX_INPUT_DEVICES; i++)
|
|
write_kbr_config (f, id, i, &p->keyboard_settings[id][i]);
|
|
}
|
|
}
|
|
|
|
static int getnum (const char **pp)
|
|
{
|
|
const char *p = *pp;
|
|
int v = atol (p);
|
|
|
|
while (*p != 0 && *p !='.' && *p != ',') p++;
|
|
if (*p == '.' || *p == ',') p++;
|
|
*pp = p;
|
|
return v;
|
|
}
|
|
|
|
static char *getstring (const char **pp)
|
|
{
|
|
int i;
|
|
static char str[1000];
|
|
const char *p = *pp;
|
|
|
|
if (*p == 0)
|
|
return 0;
|
|
i = 0;
|
|
while (*p != 0 && *p !='.' && *p != ',')
|
|
str[i++] = *p++;
|
|
if (*p == '.' || *p == ',')
|
|
p++;
|
|
str[i] = 0;
|
|
*pp = p;
|
|
return str;
|
|
}
|
|
|
|
void reset_inputdevice_config (struct uae_prefs *pr)
|
|
{
|
|
memset (joystick_settings_reset, 0, sizeof (joystick_settings_reset));
|
|
memset (mouse_settings_reset, 0, sizeof (mouse_settings_reset));
|
|
}
|
|
|
|
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; j++)
|
|
free (id->custom[i][j]);
|
|
}
|
|
#endif
|
|
memset (id, 0, sizeof (struct uae_input_device));
|
|
id->enabled = 1;
|
|
}
|
|
|
|
void read_inputdevice_config (struct uae_prefs *pr, const char *option, const char *value)
|
|
{
|
|
struct uae_input_device *id = 0;
|
|
const struct inputevent *ie;
|
|
int devnum, num, button = 0, joystick, flags, i, subnum, idnum, keynum = 0;
|
|
int mask;
|
|
const char *p, *p2;
|
|
char *custom;
|
|
|
|
option += 6; /* "input." */
|
|
p = getstring (&option);
|
|
if (!strcasecmp (p, "config"))
|
|
pr->input_selected_setting = atol (value);
|
|
if (!strcasecmp (p, "joymouse_speed_analog"))
|
|
pr->input_joymouse_multiplier = atol (value);
|
|
if (!strcasecmp (p, "joymouse_speed_digital"))
|
|
pr->input_joymouse_speed = atol (value);
|
|
if (!strcasecmp (p, "joystick_deadzone"))
|
|
pr->input_joystick_deadzone = atol (value);
|
|
if (!strcasecmp (p, "joymouse_deadzone"))
|
|
pr->input_joymouse_deadzone = atol (value);
|
|
if (!strcasecmp (p, "mouse_speed"))
|
|
pr->input_mouse_speed = atol (value);
|
|
if (!strcasecmp (p, "autofire"))
|
|
pr->input_autofire_framecnt = atol (value);
|
|
idnum = atol (p);
|
|
if (idnum <= 0 || idnum > MAX_INPUT_SETTINGS)
|
|
return;
|
|
if (memcmp (option, "mouse.", 6) == 0) {
|
|
p = option + 6;
|
|
devnum = getnum (&p);
|
|
if (devnum < 0 || devnum >= MAX_INPUT_DEVICES)
|
|
return;
|
|
id = &pr->mouse_settings[idnum][devnum];
|
|
if (!mouse_settings_reset[idnum][devnum])
|
|
clear_id (id);
|
|
mouse_settings_reset[idnum][devnum] = 1;
|
|
joystick = 0;
|
|
} else if (memcmp (option, "joystick.", 9) == 0) {
|
|
p = option + 9;
|
|
devnum = getnum (&p);
|
|
if (devnum < 0 || devnum >= MAX_INPUT_DEVICES)
|
|
return;
|
|
id = &pr->joystick_settings[idnum][devnum];
|
|
if (!joystick_settings_reset[idnum][devnum])
|
|
clear_id (id);
|
|
joystick_settings_reset[idnum][devnum] = 1;
|
|
joystick = 1;
|
|
} else if (memcmp (option, "keyboard.", 9) == 0) {
|
|
joystick = -1;
|
|
p = option + 9;
|
|
devnum = getnum (&p);
|
|
if (devnum < 0 || devnum >= MAX_INPUT_DEVICES)
|
|
return;
|
|
id = &pr->keyboard_settings[idnum][devnum];
|
|
}
|
|
if (!id)
|
|
return;
|
|
p2 = getstring (&p);
|
|
if (!p2)
|
|
return;
|
|
if (!strcmp (p2, "disabled")) {
|
|
int disabled;
|
|
p = value;
|
|
disabled = getnum (&p);
|
|
id->enabled = disabled == 0 ? 1 : 0;
|
|
return;
|
|
}
|
|
|
|
if (joystick < 0) {
|
|
num = getnum (&p);
|
|
keynum = 0;
|
|
while (id->extra[keynum][0] >= 0) {
|
|
if (id->extra[keynum][0] == num)
|
|
break;
|
|
keynum++;
|
|
}
|
|
if (id->extra[keynum][0] < 0)
|
|
return;
|
|
} else {
|
|
button = -1;
|
|
if (!strcmp (p2, "axis"))
|
|
button = 0;
|
|
else if(!strcmp (p2, "button"))
|
|
button = 1;
|
|
if (button < 0)
|
|
return;
|
|
num = getnum (&p);
|
|
}
|
|
p = value;
|
|
|
|
custom = NULL;
|
|
for (subnum = 0; subnum < MAX_INPUT_SUB_EVENT; subnum++) {
|
|
free (custom);
|
|
custom = NULL;
|
|
p2 = getstring (&p);
|
|
if (!p2)
|
|
break;
|
|
i = 1;
|
|
while (events[i].name) {
|
|
if (!strcmp (events[i].confname, p2))
|
|
break;
|
|
i++;
|
|
}
|
|
ie = &events[i];
|
|
if (!ie->name) {
|
|
ie = &events[0];
|
|
if (strlen (p2) > 2 && p2[0] == '\'' && p2[strlen (p2) - 1] == '\'') {
|
|
custom = my_strdup (p2 + 1);
|
|
custom[strlen (custom) - 1] = 0;
|
|
}
|
|
}
|
|
flags = getnum (&p);
|
|
if (custom == NULL && ie->name == NULL) {
|
|
if (!strcmp(p2, "NULL")) {
|
|
id->eventid[keynum][subnum] = 0;
|
|
id->flags[keynum][subnum] = 0;
|
|
}
|
|
continue;
|
|
}
|
|
if (joystick < 0) {
|
|
if (!(ie->allow_mask & AM_K))
|
|
continue;
|
|
id->eventid[keynum][subnum] = ie - events;
|
|
id->flags[keynum][subnum] = flags;
|
|
free (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))
|
|
continue;
|
|
id->eventid[num + ID_BUTTON_OFFSET][subnum] = ie - events;
|
|
id->flags[num + ID_BUTTON_OFFSET][subnum] = flags;
|
|
free (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))
|
|
continue;
|
|
id->eventid[num + ID_AXIS_OFFSET][subnum] = ie - events;
|
|
id->flags[num + ID_AXIS_OFFSET][subnum] = flags;
|
|
free (id->custom[num + ID_AXIS_OFFSET][subnum]);
|
|
id->custom[num + ID_AXIS_OFFSET][subnum] = custom;
|
|
}
|
|
custom = NULL;
|
|
}
|
|
free (custom);
|
|
}
|
|
|
|
static int ievent_alive = 0;
|
|
static int lastmx, lastmy;
|
|
|
|
int mousehack_alive (void)
|
|
{
|
|
return ievent_alive > 0;
|
|
}
|
|
|
|
static void mousehack_enable (void)
|
|
{
|
|
#ifdef FILESYS /* Internal mousehack depends on filesys boot-rom */
|
|
if (!mousehack_allowed ())
|
|
return;
|
|
if (rtarea[get_long (RTAREA_BASE + 40) + 12 - 1])
|
|
return;
|
|
rtarea[get_long (RTAREA_BASE + 40) + 12 - 1] = 1;
|
|
#endif
|
|
}
|
|
|
|
static void mousehack_helper (void)
|
|
{
|
|
#ifdef FILESYS /* Internal mousehack depends on filesys boot-rom */
|
|
int mousexpos, mouseypos;
|
|
uae_u8 *p;
|
|
|
|
if (!mousehack_allowed ())
|
|
return;
|
|
#ifdef PICASSO96
|
|
if (picasso_on) {
|
|
mousexpos = lastmx - picasso96_state.XOffset;
|
|
mouseypos = lastmy - picasso96_state.YOffset;
|
|
} else
|
|
#endif
|
|
{
|
|
mouseypos = coord_native_to_amiga_y (lastmy) << 1;
|
|
mousexpos = coord_native_to_amiga_x (lastmx);
|
|
}
|
|
if (!mousehack_allowed ())
|
|
mousexpos = mouseypos = 0;
|
|
p = rtarea + get_long (RTAREA_BASE + 40) + 12;
|
|
p[0] = mousexpos >> 8;
|
|
p[1] = mousexpos;
|
|
p[2] = mouseypos >> 8;
|
|
p[3] = mouseypos;
|
|
#endif
|
|
}
|
|
|
|
STATIC_INLINE int adjust (int val)
|
|
{
|
|
if (val > 127)
|
|
return 127;
|
|
else if (val < -127)
|
|
return -127;
|
|
return val;
|
|
}
|
|
|
|
int getbuttonstate (int joy, int button)
|
|
{
|
|
return joybutton[joy] & (1 << button);
|
|
}
|
|
|
|
static void mouseupdate (int pct)
|
|
{
|
|
int v, i;
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
|
|
v = mouse_delta[i][0] * pct / 100;
|
|
mouse_x[i] += v;
|
|
if (!mouse_deltanoreset[i][0])
|
|
mouse_delta[i][0] -= v;
|
|
|
|
v = mouse_delta[i][1] * pct / 100;
|
|
mouse_y[i] += v;
|
|
if (!mouse_deltanoreset[i][1])
|
|
mouse_delta[i][1] -= v;
|
|
|
|
v = mouse_delta[i][2] * pct / 100;
|
|
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] > 127)
|
|
mouse_x[i] = mouse_frame_x[i] - 127;
|
|
if (mouse_frame_x[i] - mouse_x[i] < -127)
|
|
mouse_x[i] = mouse_frame_x[i] + 127;
|
|
|
|
if (mouse_frame_y[i] - mouse_y[i] > 127)
|
|
mouse_y[i] = mouse_frame_y[i] - 127;
|
|
if (mouse_frame_y[i] - mouse_y[i] < -127)
|
|
mouse_y[i] = mouse_frame_y[i] + 127;
|
|
|
|
if (pct == 100) {
|
|
if (!mouse_deltanoreset[i][0])
|
|
mouse_delta[i][0] = 0;
|
|
if (!mouse_deltanoreset[i][1])
|
|
mouse_delta[i][1] = 0;
|
|
if (!mouse_deltanoreset[i][2])
|
|
mouse_delta[i][2] = 0;
|
|
mouse_frame_x[i] = mouse_x[i];
|
|
mouse_frame_y[i] = mouse_y[i];
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
static unsigned int input_read, input_vpos;
|
|
|
|
static void readinput (void)
|
|
{
|
|
if (!input_read && (vpos & ~31) != (input_vpos & ~31)) {
|
|
idev[IDTYPE_JOYSTICK].read ();
|
|
idev[IDTYPE_MOUSE].read ();
|
|
mouseupdate ((vpos - input_vpos) * 100 / maxvpos);
|
|
input_vpos = vpos;
|
|
}
|
|
if (input_read) {
|
|
input_vpos = vpos;
|
|
input_read = 0;
|
|
}
|
|
}
|
|
|
|
int getjoystate (int joy)
|
|
{
|
|
int left = 0, right = 0, top = 0, bot = 0;
|
|
uae_u16 v = 0;
|
|
|
|
readinput ();
|
|
if (joydir[joy] & DIR_LEFT)
|
|
left = 1;
|
|
if (joydir[joy] & DIR_RIGHT)
|
|
right = 1;
|
|
if (joydir[joy] & DIR_UP)
|
|
top = 1;
|
|
if (joydir[joy] & DIR_DOWN)
|
|
bot = 1;
|
|
v = (uae_u8)mouse_x[joy] | (mouse_y[joy] << 8);
|
|
if (left || right || top || bot || !mouse_port[joy]) {
|
|
if (left)
|
|
top = !top;
|
|
if (right)
|
|
bot = !bot;
|
|
v &= ~0x0303;
|
|
v |= bot | (right << 1) | (top << 8) | (left << 9);
|
|
}
|
|
#ifdef DONGLE_DEBUG
|
|
if (notinrom ())
|
|
write_log ("JOY%dDAT %04.4X %s\n", joy, v, debuginfo (0));
|
|
#endif
|
|
return v;
|
|
}
|
|
|
|
uae_u16 JOY0DAT (void)
|
|
{
|
|
return getjoystate (0);
|
|
}
|
|
|
|
uae_u16 JOY1DAT (void)
|
|
{
|
|
return getjoystate (1);
|
|
}
|
|
|
|
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];
|
|
}
|
|
|
|
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;
|
|
}
|
|
return v;
|
|
default:
|
|
abort ();
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
uae_u8 handle_joystick_buttons (uae_u8 dra)
|
|
{
|
|
uae_u8 but = 0;
|
|
int i;
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
if (cd32_pad_enabled[i]) {
|
|
uae_u16 p5dir = 0x0200 << (i * 4);
|
|
uae_u16 p5dat = 0x0100 << (i * 4);
|
|
but |= 0x40 << i;
|
|
/* Red button is connected to fire when p5 is 1 or floating */
|
|
if (!(potgo_value & p5dir) || ((potgo_value & p5dat) && (potgo_value & p5dir))) {
|
|
if (getbuttonstate (i, JOYBUTTON_CD32_RED))
|
|
but &= ~(0x40 << i);
|
|
}
|
|
} else if (!getbuttonstate (i, JOYBUTTON_1)) {
|
|
but |= 0x40 << i;
|
|
}
|
|
}
|
|
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;
|
|
|
|
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 (!(potgo_value & p5dir) || !(potgo_value & 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;
|
|
|
|
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 (mouse_port[i]) {
|
|
/* official Commodore mouse has pull-up resistors in button lines
|
|
* NOTE: 3rd party mice may not have pullups! */
|
|
if (!(potgo_value & p5dir))
|
|
potgor |= p5dat;
|
|
if (!(potgo_value & p9dir))
|
|
potgor |= p9dat;
|
|
}
|
|
if (potgo_hsync < 0) {
|
|
/* first 10 or so lines after potgo has started
|
|
* forces input-lines to zero
|
|
*/
|
|
if (!(potgo_value & p5dir))
|
|
potgor &= ~p5dat;
|
|
if (!(potgo_value & p9dir))
|
|
potgor &= ~p9dat;
|
|
}
|
|
|
|
if (cd32_pad_enabled[i]) {
|
|
/* p5 is floating in input-mode */
|
|
potgor &= ~p5dat;
|
|
potgor |= potgo_value & p5dat;
|
|
if (!(potgo_value & p9dir))
|
|
potgor |= p9dat;
|
|
/* P5 output and 1 -> shift register is kept reset (Blue button) */
|
|
if ((potgo_value & p5dir) && (potgo_value & p5dat))
|
|
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 {
|
|
if (getbuttonstate (i, JOYBUTTON_3))
|
|
potgor &= ~p5dat;
|
|
if (getbuttonstate (i, JOYBUTTON_2))
|
|
potgor &= ~p9dat;
|
|
}
|
|
}
|
|
return potgor;
|
|
}
|
|
|
|
uae_u16 potgo_value;
|
|
static uae_u16 potdats[2];
|
|
static int inputdelay;
|
|
|
|
void inputdevice_hsync (void)
|
|
{
|
|
int joy;
|
|
|
|
for (joy = 0; joy < 2; joy++) {
|
|
if (potgo_hsync >= 0) {
|
|
int active;
|
|
|
|
active = 0;
|
|
if ((potgo_value >> 9) & 1) /* output? */
|
|
active = ((potgo_value >> 8) & 1) ? 0 : 1;
|
|
if (potgo_hsync < joydirpot[joy][0])
|
|
active = 1;
|
|
if (getbuttonstate (joy, JOYBUTTON_3))
|
|
active = 1;
|
|
if (active)
|
|
potdats[joy] = ((potdats[joy] + 1) & 0xFF) | (potdats[joy] & 0xFF00);
|
|
|
|
active = 0;
|
|
if ((potgo_value >> 11) & 1) /* output? */
|
|
active = ((potgo_value >> 10) & 1) ? 0 : 1;
|
|
if (potgo_hsync < joydirpot[joy][1])
|
|
active = 1;
|
|
if (getbuttonstate (joy, JOYBUTTON_2))
|
|
active = 1;
|
|
if (active)
|
|
potdats[joy] += 0x100;
|
|
}
|
|
}
|
|
potgo_hsync++;
|
|
if (potgo_hsync > 255)
|
|
potgo_hsync = 255;
|
|
|
|
|
|
#ifdef CATWEASEL
|
|
catweasel_hsync ();
|
|
#endif
|
|
if (inputdelay > 0) {
|
|
inputdelay--;
|
|
if (inputdelay == 0) {
|
|
idev[IDTYPE_JOYSTICK].read ();
|
|
idev[IDTYPE_KEYBOARD].read ();
|
|
}
|
|
}
|
|
}
|
|
|
|
uae_u16 POT0DAT (void)
|
|
{
|
|
return potdats[0];
|
|
}
|
|
uae_u16 POT1DAT (void)
|
|
{
|
|
return potdats[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;
|
|
|
|
#ifdef DONGLE_DEBUG
|
|
if (notinrom ())
|
|
write_log ("POTGO %04.4X %s\n", v, debuginfo(0));
|
|
#endif
|
|
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))
|
|
cd32_shifter[i] = 8;
|
|
}
|
|
}
|
|
if (v & 1) {
|
|
potdats[0] = potdats[1] = 0;
|
|
potgo_hsync = -15;
|
|
}
|
|
}
|
|
|
|
uae_u16 POTGOR (void)
|
|
{
|
|
uae_u16 v = handle_joystick_potgor (potgo_value) & 0x5500;
|
|
#ifdef DONGLE_DEBUG
|
|
if (notinrom ())
|
|
write_log ("POTGOR %04.4X %s\n", v, debuginfo(0));
|
|
#endif
|
|
return v;
|
|
}
|
|
|
|
static int check_input_queue (int event)
|
|
{
|
|
const struct input_queue_struct *iq;
|
|
int i;
|
|
for (i = 0; i < INPUT_QUEUE_SIZE; i++) {
|
|
iq = &input_queue[i];
|
|
if (iq->event == event)
|
|
return i;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
static void queue_input_event (int event, int state, int max, int framecnt, int autofire)
|
|
{
|
|
struct input_queue_struct *iq;
|
|
int i = check_input_queue (event);
|
|
|
|
if (event <= 0)
|
|
return;
|
|
if (state < 0 && i >= 0) {
|
|
iq = &input_queue[i];
|
|
iq->nextframecnt = -1;
|
|
iq->framecnt = -1;
|
|
iq->event = 0;
|
|
if (iq->state == 0)
|
|
handle_input_event (event, 0, 1, 0);
|
|
} else if (i < 0) {
|
|
for (i = 0; i < INPUT_QUEUE_SIZE; i++) {
|
|
iq = &input_queue[i];
|
|
if (iq->framecnt < 0) break;
|
|
}
|
|
if (i == INPUT_QUEUE_SIZE) {
|
|
write_log ("input queue overflow\n");
|
|
return;
|
|
}
|
|
iq->event = event;
|
|
iq->state = iq->storedstate = state;
|
|
iq->max = max;
|
|
iq->framecnt = framecnt;
|
|
iq->nextframecnt = autofire > 0 ? framecnt : -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)
|
|
{
|
|
if (code < 0x80) {
|
|
uae_u8 key = code | (state ? 0x00 : 0x80);
|
|
keybuf[key & 0x7f] = (key & 0x80) ? 0 : 1;
|
|
if (((keybuf[AK_CTRL] || keybuf[AK_RCTRL]) && keybuf[AK_LAMI] && keybuf[AK_RAMI]) || key == AK_RESETWARNING) {
|
|
int r = keybuf[AK_LALT] | keybuf[AK_RALT];
|
|
memset (keybuf, 0, sizeof (keybuf));
|
|
uae_reset (r);
|
|
}
|
|
record_key ((uae_u8)((key << 1) | (key >> 7)));
|
|
return;
|
|
}
|
|
inputdevice_add_inputcode (code, state);
|
|
}
|
|
|
|
void inputdevice_handle_inputcode (void)
|
|
{
|
|
int code = inputcode_pending;
|
|
int state = inputcode_pending_state;
|
|
inputcode_pending = 0;
|
|
if (code == 0)
|
|
return;
|
|
if (vpos != 0)
|
|
write_log ("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);
|
|
break;
|
|
case AKS_SCREENSHOT:
|
|
screenshot (1);
|
|
break;
|
|
#ifdef ACTION_REPLAY
|
|
case AKS_FREEZEBUTTON:
|
|
action_replay_freeze ();
|
|
break;
|
|
#endif
|
|
case AKS_FLOPPY0:
|
|
gui_display (0);
|
|
break;
|
|
case AKS_FLOPPY1:
|
|
gui_display (1);
|
|
break;
|
|
case AKS_FLOPPY2:
|
|
gui_display (2);
|
|
break;
|
|
case AKS_FLOPPY3:
|
|
gui_display (3);
|
|
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:
|
|
Interrupt (7);
|
|
break;
|
|
case AKS_PAUSE:
|
|
if (uae_get_state () == UAE_STATE_PAUSED)
|
|
uae_resume ();
|
|
else
|
|
uae_pause ();
|
|
break;
|
|
case AKS_WARP:
|
|
warpmode (-1);
|
|
break;
|
|
case AKS_INHIBITSCREEN:
|
|
toggle_inhibit_frame (IHF_SCROLLLOCK);
|
|
break;
|
|
#ifdef SAVESTATE
|
|
case AKS_STATEREWIND:
|
|
savestate_dorewind(1);
|
|
#endif
|
|
break;
|
|
case AKS_VOLDOWN:
|
|
audio_volume (-1);
|
|
break;
|
|
case AKS_VOLUP:
|
|
audio_volume (1);
|
|
break;
|
|
case AKS_VOLMUTE:
|
|
audio_volume (0);
|
|
break;
|
|
case AKS_QUIT:
|
|
uae_quit ();
|
|
break;
|
|
case AKS_SOFTRESET:
|
|
uae_reset (0);
|
|
break;
|
|
case AKS_HARDRESET:
|
|
uae_reset (1);
|
|
break;
|
|
#ifdef SAVESTATE
|
|
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;
|
|
#endif
|
|
case AKS_TOGGLEFULLSCREEN:
|
|
toggle_fullscreen ();
|
|
break;
|
|
case AKS_TOGGLEMOUSEGRAB:
|
|
toggle_mousegrab ();
|
|
break;
|
|
#ifdef DEBUGGER
|
|
case AKS_ENTERDEBUGGER:
|
|
activate_debugger ();
|
|
break;
|
|
#endif
|
|
case AKS_STATESAVEDIALOG:
|
|
gui_display (5);
|
|
break;
|
|
case AKS_STATERESTOREDIALOG:
|
|
gui_display (4);
|
|
break;
|
|
case AKS_INCRFRAMERATE:
|
|
if (currprefs.gfx_framerate < 20)
|
|
changed_prefs.gfx_framerate = currprefs.gfx_framerate + 1;
|
|
break;
|
|
case AKS_DECRFRAMERATE:
|
|
if (currprefs.gfx_framerate > 1)
|
|
changed_prefs.gfx_framerate = currprefs.gfx_framerate - 1;
|
|
break;
|
|
case AKS_SWITCHINTERPOL:
|
|
switch_audio_interpol ();
|
|
break;
|
|
case AKS_VIRTUAL_KEYBOARD:
|
|
gui_display (6);
|
|
break;
|
|
}
|
|
}
|
|
|
|
int handle_input_event (int nr, int state, int max, int autofire)
|
|
{
|
|
const struct inputevent *ie;
|
|
int joy;
|
|
|
|
if (nr <= 0)
|
|
return 0;
|
|
ie = &events[nr];
|
|
if (autofire) {
|
|
if (state)
|
|
queue_input_event (nr, state, max, currprefs.input_autofire_framecnt, 1);
|
|
else
|
|
queue_input_event (nr, -1, 0, 0, 1);
|
|
}
|
|
switch (ie->unit)
|
|
{
|
|
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) {
|
|
if (state)
|
|
joybutton[joy] |= 1 << ie->data;
|
|
else
|
|
joybutton[joy] &= ~(1 << ie->data);
|
|
} else if (ie->type & 8) {
|
|
/* real mouse / analog stick mouse emulation */
|
|
int delta;
|
|
int deadzone = currprefs.input_joymouse_deadzone * max / 100;
|
|
if (max) {
|
|
if (state < deadzone && state > -deadzone) {
|
|
state = 0;
|
|
} else if (state < 0) {
|
|
state += deadzone;
|
|
} else {
|
|
state -= deadzone;
|
|
}
|
|
max -= deadzone;
|
|
delta = state * currprefs.input_joymouse_multiplier / max;
|
|
} else {
|
|
delta = state;
|
|
}
|
|
mouse_delta[joy][ie->data] += delta;
|
|
|
|
} else if (ie->type & 32) { /* button mouse emulation vertical */
|
|
|
|
int speed = 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 = 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 (paddle) */
|
|
int deadzone = currprefs.input_joymouse_deadzone * max / 100;
|
|
if (max) {
|
|
if (state < deadzone && state > -deadzone) {
|
|
state = 0;
|
|
} else if (state < 0) {
|
|
state += deadzone;
|
|
} else {
|
|
state -= deadzone;
|
|
}
|
|
state = state * max / (max - deadzone);
|
|
}
|
|
state = state / 256 + 128;
|
|
joydirpot[joy][ie->data] = state;
|
|
} 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 (ie->data & DIR_RIGHT) right = oright[joy] = state ? 1 : 0;
|
|
if (ie->data & DIR_UP) top = otop[joy] = state ? 1 : 0;
|
|
if (ie->data & DIR_DOWN) bot = obot[joy] = state ? 1 : 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 (ie->data & DIR_RIGHT) right = oright[joy] = pos;
|
|
if (ie->data & DIR_UP) top = otop[joy] = neg;
|
|
if (ie->data & DIR_DOWN) bot = obot[joy] = pos;
|
|
}
|
|
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;
|
|
}
|
|
break;
|
|
case 0: /* ->KEY */
|
|
inputdevice_do_keyboard (ie->data, state);
|
|
break;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
void inputdevice_vsync (void)
|
|
{
|
|
struct input_queue_struct *iq;
|
|
int i;
|
|
|
|
for (i = 0; i < INPUT_QUEUE_SIZE; i++) {
|
|
iq = &input_queue[i];
|
|
if (iq->framecnt > 0) {
|
|
iq->framecnt--;
|
|
if (iq->framecnt == 0) {
|
|
if (iq->state) iq->state = 0; else iq->state = iq->storedstate;
|
|
handle_input_event (iq->event, iq->state, iq->max, 0);
|
|
iq->framecnt = iq->nextframecnt;
|
|
}
|
|
}
|
|
}
|
|
mouseupdate (100);
|
|
inputdelay = rand () % (maxvpos == 0 ? 1 : maxvpos - 1);
|
|
idev[IDTYPE_MOUSE].read ();
|
|
input_read = 1;
|
|
input_vpos = 0;
|
|
inputdevice_handle_inputcode ();
|
|
if (ievent_alive > 0)
|
|
ievent_alive--;
|
|
#ifdef ARCADIA
|
|
if (arcadia_rom)
|
|
arcadia_vsync ();
|
|
#endif
|
|
}
|
|
|
|
void inputdevice_reset (void)
|
|
{
|
|
ievent_alive = 0;
|
|
}
|
|
|
|
static void setbuttonstateall (struct uae_input_device *id, struct uae_input_device2 *id2, int button, int state)
|
|
{
|
|
int event, autofire, i;
|
|
uae_u32 mask = 1 << button;
|
|
uae_u32 omask = id2->buttonmask & mask;
|
|
uae_u32 nmask = (state ? 1 : 0) << button;
|
|
char *custom;
|
|
|
|
if (button >= ID_BUTTON_TOTAL)
|
|
return;
|
|
for (i = 0; i < MAX_INPUT_SUB_EVENT; i++) {
|
|
event = id->eventid[ID_BUTTON_OFFSET + button][sublevdir[state <= 0 ? 1 : 0][i]];
|
|
custom = id->custom[ID_BUTTON_OFFSET + button][sublevdir[state <= 0 ? 1 : 0][i]];
|
|
if (event <= 0 && custom == NULL)
|
|
continue;
|
|
autofire = (id->flags[ID_BUTTON_OFFSET + button][sublevdir[state <= 0 ? 1 : 0][i]] & ID_FLAG_AUTOFIRE) ? 1 : 0;
|
|
if (state < 0) {
|
|
handle_input_event (event, 1, 1, 0);
|
|
queue_input_event (event, 0, 1, 1, 0); /* send release event next frame */
|
|
} else {
|
|
if ((omask ^ nmask) & mask)
|
|
handle_input_event (event, state, 1, autofire);
|
|
}
|
|
}
|
|
if ((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;
|
|
}
|
|
|
|
#ifdef CD32
|
|
extern int cd32_enabled;
|
|
#endif
|
|
|
|
static void scanevents (struct uae_prefs *p)
|
|
{
|
|
unsigned int i;
|
|
int j, k, ei;
|
|
const struct inputevent *e;
|
|
unsigned int n_joy = idev[IDTYPE_JOYSTICK].get_num();
|
|
unsigned 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;
|
|
for (i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++)
|
|
joydir[i] = 0;
|
|
|
|
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) {
|
|
ei = joysticks[i].eventid[ID_BUTTON_OFFSET + j][k];
|
|
e = &events[ei];
|
|
iscd32 (ei);
|
|
isparport (ei);
|
|
ismouse (ei);
|
|
if (joysticks[i].eventid[ID_BUTTON_OFFSET + j][k] > 0)
|
|
use_joysticks[i] = 1;
|
|
}
|
|
if (mice[i].enabled && i < n_mouse) {
|
|
ei = mice[i].eventid[ID_BUTTON_OFFSET + j][k];
|
|
e = &events[ei];
|
|
iscd32 (ei);
|
|
isparport (ei);
|
|
ismouse (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) {
|
|
ei = joysticks[i].eventid[ID_AXIS_OFFSET + j][k];
|
|
iscd32 (ei);
|
|
isparport (ei);
|
|
ismouse (ei);
|
|
if (ei > 0)
|
|
use_joysticks[i] = 1;
|
|
}
|
|
if (mice[i].enabled && i < n_mouse) {
|
|
ei = mice[i].eventid[ID_AXIS_OFFSET + j][k];
|
|
iscd32 (ei);
|
|
isparport (ei);
|
|
ismouse (ei);
|
|
if (ei > 0)
|
|
use_mice[i] = 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
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 (keyboards[i].extra[j][0] >= 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);
|
|
}
|
|
j++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef CD32
|
|
static void setcd32 (int joy, int n)
|
|
{
|
|
joysticks[joy].eventid[ID_BUTTON_OFFSET + 0][0] = n ? INPUTEVENT_JOY2_CD32_RED : INPUTEVENT_JOY1_CD32_RED;
|
|
joysticks[joy].eventid[ID_BUTTON_OFFSET + 1][0] = n ? INPUTEVENT_JOY2_CD32_BLUE : INPUTEVENT_JOY1_CD32_BLUE;
|
|
joysticks[joy].eventid[ID_BUTTON_OFFSET + 2][0] = n ? INPUTEVENT_JOY2_CD32_YELLOW : INPUTEVENT_JOY1_CD32_YELLOW;
|
|
joysticks[joy].eventid[ID_BUTTON_OFFSET + 3][0] = n ? INPUTEVENT_JOY2_CD32_GREEN : INPUTEVENT_JOY1_CD32_GREEN;
|
|
joysticks[joy].eventid[ID_BUTTON_OFFSET + 4][0] = n ? INPUTEVENT_JOY2_CD32_FFW : INPUTEVENT_JOY1_CD32_FFW;
|
|
joysticks[joy].eventid[ID_BUTTON_OFFSET + 5][0] = n ? INPUTEVENT_JOY2_CD32_RWD : INPUTEVENT_JOY1_CD32_RWD;
|
|
joysticks[joy].eventid[ID_BUTTON_OFFSET + 6][0] = n ? INPUTEVENT_JOY2_CD32_PLAY : INPUTEVENT_JOY1_CD32_PLAY;
|
|
}
|
|
#endif
|
|
|
|
int compatibility_device[2];
|
|
|
|
static void compatibility_mode (struct uae_prefs *prefs)
|
|
{
|
|
int joy, i;
|
|
int used[4] = { 0, 0, 0, 0};
|
|
|
|
compatibility_device[0] = -1;
|
|
compatibility_device[1] = -1;
|
|
for (i = 0; i < MAX_INPUT_DEVICES; i++) {
|
|
memset (&mice[i], 0, sizeof (*mice));
|
|
memset (&joysticks[i], 0, sizeof (*joysticks));
|
|
}
|
|
|
|
if ((joy = jsem_ismouse (0, prefs)) >= 0) {
|
|
mice[joy].eventid[ID_AXIS_OFFSET + 0][0] = INPUTEVENT_MOUSE1_HORIZ;
|
|
mice[joy].eventid[ID_AXIS_OFFSET + 1][0] = INPUTEVENT_MOUSE1_VERT;
|
|
mice[joy].eventid[ID_AXIS_OFFSET + 2][0] = INPUTEVENT_MOUSE1_WHEEL;
|
|
mice[joy].eventid[ID_BUTTON_OFFSET + 0][0] = INPUTEVENT_JOY1_FIRE_BUTTON;
|
|
mice[joy].eventid[ID_BUTTON_OFFSET + 1][0] = INPUTEVENT_JOY1_2ND_BUTTON;
|
|
mice[joy].eventid[ID_BUTTON_OFFSET + 2][0] = INPUTEVENT_JOY1_3RD_BUTTON;
|
|
mice[joy].eventid[ID_BUTTON_OFFSET + 3][0] = INPUTEVENT_KEY_ALT_LEFT;
|
|
mice[joy].eventid[ID_BUTTON_OFFSET + 3][1] = INPUTEVENT_KEY_CURSOR_LEFT;
|
|
mice[joy].eventid[ID_BUTTON_OFFSET + 4][0] = INPUTEVENT_KEY_ALT_LEFT;
|
|
mice[joy].eventid[ID_BUTTON_OFFSET + 4][1] = INPUTEVENT_KEY_CURSOR_RIGHT;
|
|
mice[joy].enabled = 1;
|
|
}
|
|
if ((joy = jsem_ismouse (1, prefs)) >= 0) {
|
|
mice[joy].eventid[ID_AXIS_OFFSET + 0][0] = INPUTEVENT_MOUSE2_HORIZ;
|
|
mice[joy].eventid[ID_AXIS_OFFSET + 1][0] = INPUTEVENT_MOUSE2_VERT;
|
|
mice[joy].eventid[ID_BUTTON_OFFSET + 0][0] = INPUTEVENT_JOY2_FIRE_BUTTON;
|
|
mice[joy].eventid[ID_BUTTON_OFFSET + 1][0] = INPUTEVENT_JOY2_2ND_BUTTON;
|
|
mice[joy].eventid[ID_BUTTON_OFFSET + 2][0] = INPUTEVENT_JOY2_3RD_BUTTON;
|
|
mice[joy].enabled = 1;
|
|
}
|
|
|
|
joy = jsem_isjoy (1, prefs);
|
|
if (joy >= 0) {
|
|
joysticks[joy].eventid[ID_AXIS_OFFSET + 0][0] = INPUTEVENT_JOY2_HORIZ;
|
|
joysticks[joy].eventid[ID_AXIS_OFFSET + 1][0] = INPUTEVENT_JOY2_VERT;
|
|
used[joy] = 1;
|
|
joysticks[joy].eventid[ID_BUTTON_OFFSET + 0][0] = INPUTEVENT_JOY2_FIRE_BUTTON;
|
|
joysticks[joy].eventid[ID_BUTTON_OFFSET + 1][0] = INPUTEVENT_JOY2_2ND_BUTTON;
|
|
joysticks[joy].eventid[ID_BUTTON_OFFSET + 2][0] = INPUTEVENT_JOY2_3RD_BUTTON;
|
|
#ifdef CD32
|
|
if (cd32_enabled)
|
|
setcd32 (joy, 1);
|
|
#endif
|
|
joysticks[joy].enabled = 1;
|
|
}
|
|
|
|
joy = jsem_isjoy (0, prefs);
|
|
if (joy >= 0) {
|
|
used[joy] = 1;
|
|
joysticks[joy].eventid[ID_AXIS_OFFSET + 0][0] = INPUTEVENT_JOY1_HORIZ;
|
|
joysticks[joy].eventid[ID_AXIS_OFFSET + 1][0] = INPUTEVENT_JOY1_VERT;
|
|
joysticks[joy].eventid[ID_BUTTON_OFFSET + 0][0] = INPUTEVENT_JOY1_FIRE_BUTTON;
|
|
joysticks[joy].eventid[ID_BUTTON_OFFSET + 1][0] = INPUTEVENT_JOY1_2ND_BUTTON;
|
|
joysticks[joy].eventid[ID_BUTTON_OFFSET + 2][0] = INPUTEVENT_JOY1_3RD_BUTTON;
|
|
joysticks[joy].enabled = 1;
|
|
}
|
|
|
|
for (joy = 0; used[joy]; joy++);
|
|
if (JSEM_ISANYKBD (0, prefs)) {
|
|
joysticks[joy].eventid[ID_AXIS_OFFSET + 0][0] = INPUTEVENT_JOY1_HORIZ;
|
|
joysticks[joy].eventid[ID_AXIS_OFFSET + 1][0] = INPUTEVENT_JOY1_VERT;
|
|
joysticks[joy].eventid[ID_BUTTON_OFFSET + 0][0] = INPUTEVENT_JOY1_FIRE_BUTTON;
|
|
joysticks[joy].eventid[ID_BUTTON_OFFSET + 1][0] = INPUTEVENT_JOY1_2ND_BUTTON;
|
|
joysticks[joy].eventid[ID_BUTTON_OFFSET + 2][0] = INPUTEVENT_JOY1_3RD_BUTTON;
|
|
joysticks[joy].enabled = 1;
|
|
used[joy] = 1;
|
|
compatibility_device[0] = joy;
|
|
}
|
|
for (joy = 0; used[joy]; joy++);
|
|
if (JSEM_ISANYKBD (1, prefs)) {
|
|
joysticks[joy].eventid[ID_AXIS_OFFSET + 0][0] = INPUTEVENT_JOY2_HORIZ;
|
|
joysticks[joy].eventid[ID_AXIS_OFFSET + 1][0] = INPUTEVENT_JOY2_VERT;
|
|
joysticks[joy].eventid[ID_BUTTON_OFFSET + 0][0] = INPUTEVENT_JOY2_FIRE_BUTTON;
|
|
joysticks[joy].eventid[ID_BUTTON_OFFSET + 1][0] = INPUTEVENT_JOY2_2ND_BUTTON;
|
|
joysticks[joy].eventid[ID_BUTTON_OFFSET + 2][0] = INPUTEVENT_JOY2_3RD_BUTTON;
|
|
#ifdef CD32
|
|
if (cd32_enabled)
|
|
setcd32 (joy, 1);
|
|
#endif
|
|
joysticks[joy].enabled = 1;
|
|
used[joy] = 1;
|
|
compatibility_device[1] = joy;
|
|
}
|
|
}
|
|
|
|
void inputdevice_updateconfig (struct uae_prefs *prefs)
|
|
{
|
|
int i;
|
|
|
|
if (currprefs.jport0 != changed_prefs.jport0
|
|
|| currprefs.jport1 != changed_prefs.jport1) {
|
|
currprefs.jport0 = changed_prefs.jport0;
|
|
currprefs.jport1 = changed_prefs.jport1;
|
|
}
|
|
joybutton[0] = joybutton[1] = 0;
|
|
joydir[0] = joydir[1] = 0;
|
|
oldmx[0] = oldmx[1] = -1;
|
|
oldmy[0] = oldmy[1] = -1;
|
|
cd32_shifter[0] = cd32_shifter[1] = 8;
|
|
oleft[0] = oleft[1] = 0;
|
|
oright[0] = oright[1] = 0;
|
|
otop[0] = otop[1] = 0;
|
|
obot[0] = obot[1] = 0;
|
|
for (i = 0; i < 2; i++) {
|
|
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 (i = 0; i < INPUT_QUEUE_SIZE; i++)
|
|
input_queue[i].framecnt = input_queue[i].nextframecnt = -1;
|
|
|
|
for (i = 0; i < MAX_INPUT_SUB_EVENT; i++) {
|
|
sublevdir[0][i] = i;
|
|
sublevdir[1][i] = MAX_INPUT_SUB_EVENT - i - 1;
|
|
}
|
|
|
|
joysticks = prefs->joystick_settings[prefs->input_selected_setting];
|
|
mice = prefs->mouse_settings[prefs->input_selected_setting];
|
|
keyboards = prefs->keyboard_settings[prefs->input_selected_setting];
|
|
|
|
memset (joysticks2, 0, sizeof (joysticks2));
|
|
memset (mice2, 0, sizeof (mice2));
|
|
if (prefs->input_selected_setting == 0)
|
|
compatibility_mode (prefs);
|
|
|
|
joystick_setting_changed ();
|
|
|
|
scanevents (prefs);
|
|
|
|
#ifdef CD32
|
|
if (currprefs.input_selected_setting == 0 && cd32_enabled)
|
|
cd32_pad_enabled[1] = 1;
|
|
#endif
|
|
|
|
mousehack_enable ();
|
|
}
|
|
|
|
static void set_kbr_default (struct uae_prefs *p, int index, int num)
|
|
{
|
|
int k, l;
|
|
unsigned int i, j;
|
|
struct uae_input_device_kbr_default *trans = keyboard_default;
|
|
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++) {
|
|
kbr = &p->keyboard_settings[index][j];
|
|
for (i = 0; i < MAX_INPUT_DEVICE_EVENTS; i++) {
|
|
memset (kbr, 0, sizeof (struct uae_input_device));
|
|
kbr->extra[i][0] = -1;
|
|
}
|
|
if (j < id->get_num ()) {
|
|
if (j == 0)
|
|
kbr->enabled = 1;
|
|
for (i = 0; i < id->get_widget_num (num); i++) {
|
|
id->get_widget_type (num, i, 0, &scancode);
|
|
kbr->extra[i][0] = scancode;
|
|
l = 0;
|
|
while (trans[l].scancode >= 0) {
|
|
if (kbr->extra[i][0] == trans[l].scancode) {
|
|
for (k = 0; k < MAX_INPUT_SUB_EVENT; k++) {
|
|
if (kbr->eventid[i][k] == 0) break;
|
|
}
|
|
if (k == MAX_INPUT_SUB_EVENT) {
|
|
write_log ("corrupt default keyboard mappings\n");
|
|
return;
|
|
}
|
|
kbr->eventid[i][k] = trans[l].event;
|
|
break;
|
|
}
|
|
l++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void inputdevice_default_prefs (struct uae_prefs *p)
|
|
{
|
|
int i;
|
|
|
|
inputdevice_init ();
|
|
p->input_joymouse_multiplier = 20;
|
|
p->input_joymouse_deadzone = 33;
|
|
p->input_joystick_deadzone = 33;
|
|
p->input_joymouse_speed = 10;
|
|
p->input_mouse_speed = 100;
|
|
p->input_autofire_framecnt = 10;
|
|
for (i = 0; i <= MAX_INPUT_SETTINGS; i++) {
|
|
set_kbr_default (p, i, 0);
|
|
input_get_default_mouse (p->mouse_settings[i]);
|
|
input_get_default_joystick (p->joystick_settings[i]);
|
|
}
|
|
}
|
|
|
|
void inputdevice_setkeytranslation (struct uae_input_device_kbr_default *trans)
|
|
{
|
|
keyboard_default = trans;
|
|
}
|
|
|
|
int inputdevice_translatekeycode (int keyboard, int scancode, int state)
|
|
{
|
|
struct uae_input_device *na = &keyboards[keyboard];
|
|
int j, k;
|
|
|
|
if (!keyboards || scancode < 0)
|
|
return 0;
|
|
j = 0;
|
|
while (na->extra[j][0] >= 0) {
|
|
if (na->extra[j][0] == scancode) {
|
|
for (k = 0; k < MAX_INPUT_SUB_EVENT; k++) {/* send key release events in reverse order */
|
|
int autofire = (na->flags[j][sublevdir[state == 0 ? 1 : 0][k]] & ID_FLAG_AUTOFIRE) ? 1 : 0;
|
|
int event = na->eventid[j][sublevdir[state == 0 ? 1 : 0][k]];
|
|
handle_input_event (event, state, 1, autofire);
|
|
}
|
|
return 1;
|
|
}
|
|
j++;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
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 ();
|
|
}
|
|
|
|
void inputdevice_close (void)
|
|
{
|
|
idev[IDTYPE_JOYSTICK].close ();
|
|
idev[IDTYPE_MOUSE].close ();
|
|
idev[IDTYPE_KEYBOARD].close ();
|
|
}
|
|
|
|
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];
|
|
}
|
|
return uid;
|
|
}
|
|
|
|
static int get_event_data (const struct inputdevice_functions *id, int devnum, int num, int *eventid, char **custom, int *flags, 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) {
|
|
i = num - id->get_widget_first (devnum, type) + ID_BUTTON_OFFSET;
|
|
*eventid = uid->eventid[i][sub];
|
|
*flags = uid->flags[i][sub];
|
|
*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];
|
|
*flags = uid->flags[i][sub];
|
|
*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];
|
|
*flags = uid->flags[i][sub];
|
|
*custom = uid->custom[i][sub];
|
|
return i;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
static int put_event_data (const struct inputdevice_functions *id, int devnum, int num, int eventid, const char *custom, int flags, int sub)
|
|
{
|
|
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) {
|
|
i = num - id->get_widget_first (devnum, type) + ID_BUTTON_OFFSET;
|
|
free (uid->custom[i][sub]);
|
|
uid->eventid[i][sub] = eventid;
|
|
uid->flags[i][sub] = flags;
|
|
uid->custom[i][sub] = custom ? my_strdup (custom) : NULL;
|
|
return i;
|
|
} else if (type == IDEV_WIDGET_AXIS) {
|
|
i = num - id->get_widget_first (devnum, type) + ID_AXIS_OFFSET;
|
|
free (uid->custom[i][sub]);
|
|
uid->eventid[i][sub] = eventid;
|
|
uid->flags[i][sub] = flags;
|
|
uid->custom[i][sub] = custom ? my_strdup (custom) : NULL;
|
|
return i;
|
|
} else if (type == IDEV_WIDGET_KEY) {
|
|
i = num - id->get_widget_first (devnum, type);
|
|
free (uid->custom[i][sub]);
|
|
uid->eventid[i][sub] = eventid;
|
|
uid->flags[i][sub] = flags;
|
|
uid->custom[i][sub] = custom ? my_strdup (custom) : NULL;
|
|
return i;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
static int is_event_used (const struct inputdevice_functions *id, int devnum, unsigned int isnum, int isevent)
|
|
{
|
|
unsigned int num;
|
|
int event, flag, sub;
|
|
char *custom;
|
|
|
|
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, &event, &custom, &flag, sub) >= 0) {
|
|
if (event == isevent && isnum != num)
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int inputdevice_get_device_index (unsigned int devnum)
|
|
{
|
|
if (devnum < idev[IDTYPE_JOYSTICK].get_num())
|
|
return devnum;
|
|
else if (devnum < idev[IDTYPE_JOYSTICK].get_num() + idev[IDTYPE_MOUSE].get_num())
|
|
return devnum - idev[IDTYPE_JOYSTICK].get_num();
|
|
else if (devnum < idev[IDTYPE_JOYSTICK].get_num() + idev[IDTYPE_MOUSE].get_num() + idev[IDTYPE_KEYBOARD].get_num())
|
|
return devnum - idev[IDTYPE_JOYSTICK].get_num() - idev[IDTYPE_MOUSE].get_num();
|
|
else
|
|
return -1;
|
|
}
|
|
|
|
static int gettype (unsigned int devnum)
|
|
{
|
|
if (devnum < idev[IDTYPE_JOYSTICK].get_num())
|
|
return IDTYPE_JOYSTICK;
|
|
else if (devnum < idev[IDTYPE_JOYSTICK].get_num() + idev[IDTYPE_MOUSE].get_num())
|
|
return IDTYPE_MOUSE;
|
|
else if (devnum < idev[IDTYPE_JOYSTICK].get_num() + idev[IDTYPE_MOUSE].get_num() + idev[IDTYPE_KEYBOARD].get_num())
|
|
return IDTYPE_KEYBOARD;
|
|
else
|
|
return -1;
|
|
}
|
|
|
|
static struct inputdevice_functions *getidf (int devnum)
|
|
{
|
|
return &idev[gettype (devnum)];
|
|
}
|
|
|
|
|
|
/* returns number of devices of type "type" */
|
|
int inputdevice_get_device_total (int type)
|
|
{
|
|
return idev[type].get_num ();
|
|
}
|
|
/* returns the name of device */
|
|
const char *inputdevice_get_device_name (int type, int devnum)
|
|
{
|
|
return idev[type].get_name (devnum);
|
|
}
|
|
/* returns state (enabled/disabled) */
|
|
int inputdevice_get_device_status (int devnum)
|
|
{
|
|
const struct inputdevice_functions *idf = getidf (devnum);
|
|
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);
|
|
struct uae_input_device *uid = get_uid (idf, inputdevice_get_device_index (devnum));
|
|
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));
|
|
}
|
|
|
|
static void get_ename (const struct inputevent *ie, char *out)
|
|
{
|
|
if (!out)
|
|
return;
|
|
if (ie->allow_mask == AM_K)
|
|
sprintf (out, "%s (0x%02.2X)", ie->name, ie->data);
|
|
else
|
|
strcpy (out, ie->name);
|
|
}
|
|
|
|
int inputdevice_iterate (int devnum, int num, char *name, int *af)
|
|
{
|
|
const struct inputdevice_functions *idf = getidf (devnum);
|
|
static int id_iterator;
|
|
const struct inputevent *ie;
|
|
int mask, data, flags, type;
|
|
int devindex = inputdevice_get_device_index (devnum);
|
|
char *custom;
|
|
|
|
*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, 0, 0);
|
|
if (type == IDEV_WIDGET_BUTTON) {
|
|
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) {
|
|
const 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, &custom, &flags, 0);
|
|
get_ename (ie, name);
|
|
*af = (flags & ID_FLAG_AUTOFIRE) ? 1 : 0;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
int inputdevice_get_mapped_name (int devnum, int num, int *pflags, char *name, char *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 flags = 0, flag, data;
|
|
int devindex = inputdevice_get_device_index (devnum);
|
|
char *customp = NULL;
|
|
|
|
if (name)
|
|
strcpy (name, "<none>");
|
|
if (custom)
|
|
custom[0] = 0;
|
|
if (pflags)
|
|
*pflags = 0;
|
|
if (uid == 0 || num < 0)
|
|
return 0;
|
|
if (get_event_data (idf, devindex, num, &data, &customp, &flag, sub) < 0)
|
|
return 0;
|
|
if (customp && custom)
|
|
sprintf (custom, "\"%s\"", customp);
|
|
if (flag & ID_FLAG_AUTOFIRE)
|
|
flags |= IDEV_MAPPED_AUTOFIRE_SET;
|
|
if (!data)
|
|
return 0;
|
|
if (events[data].allow_mask & AM_AF)
|
|
flags |= IDEV_MAPPED_AUTOFIRE_POSSIBLE;
|
|
if (pflags)
|
|
*pflags = flags;
|
|
get_ename (&events[data], name);
|
|
return data;
|
|
}
|
|
|
|
int inputdevice_set_mapping (int devnum, int num, const char *name, char *custom, int af, 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, flag, amask;
|
|
char ename[256];
|
|
int devindex = inputdevice_get_device_index (devnum);
|
|
|
|
if (uid == 0 || num < 0)
|
|
return 0;
|
|
if (name) {
|
|
eid = 1;
|
|
while (events[eid].name) {
|
|
get_ename (&events[eid], ename);
|
|
if (!strcmp(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, &custom, &flag, sub) < 0)
|
|
return 0;
|
|
if (data >= 0) {
|
|
amask = events[eid].allow_mask;
|
|
flag &= ~ID_FLAG_AUTOFIRE;
|
|
if (amask & AM_AF)
|
|
flag |= af ? ID_FLAG_AUTOFIRE : 0;
|
|
put_event_data (idf, devindex, num, eid, custom, flag, sub);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int inputdevice_get_widget_type (int devnum, int num, char *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;
|
|
}
|
|
|
|
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_framecnt = src->input_autofire_framecnt;
|
|
dst->jport0 = src->jport0;
|
|
dst->jport1 = src->jport1;
|
|
|
|
for (i = 0; i < MAX_INPUT_SETTINGS + 1; 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);
|
|
}
|
|
|
|
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->eventid[i][j] = k;
|
|
break;
|
|
}
|
|
k++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void inputdevice_copy_single_config (struct uae_prefs *p, int src, int dst, int devnum)
|
|
{
|
|
if (src == dst)
|
|
return;
|
|
if (devnum < 0 || gettype (devnum) == IDTYPE_JOYSTICK)
|
|
memcpy (p->joystick_settings[dst], p->joystick_settings[src], sizeof (struct uae_input_device) * MAX_INPUT_DEVICES);
|
|
if (devnum < 0 || gettype (devnum) == IDTYPE_MOUSE)
|
|
memcpy (p->mouse_settings[dst], p->mouse_settings[src], sizeof (struct uae_input_device) * MAX_INPUT_DEVICES);
|
|
if (devnum < 0 || gettype (devnum) == IDTYPE_KEYBOARD)
|
|
memcpy (p->keyboard_settings[dst], p->keyboard_settings[src], sizeof (struct uae_input_device) * MAX_INPUT_DEVICES);
|
|
}
|
|
|
|
void inputdevice_acquire (void)
|
|
{
|
|
int i;
|
|
|
|
inputdevice_unacquire ();
|
|
for (i = 0; i < MAX_INPUT_DEVICES; i++) {
|
|
if (use_joysticks[i])
|
|
idev[IDTYPE_JOYSTICK].acquire (i, 0);
|
|
}
|
|
for (i = 0; i < MAX_INPUT_DEVICES; i++) {
|
|
if (use_mice[i])
|
|
idev[IDTYPE_MOUSE].acquire (i, 0);
|
|
}
|
|
for (i = 0; i < MAX_INPUT_DEVICES; i++) {
|
|
if (use_keyboards[i])
|
|
idev[IDTYPE_KEYBOARD].acquire (i, 0);
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
/* 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 (!joysticks[joy].enabled)
|
|
return;
|
|
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 (!joysticks[joy].enabled)
|
|
return;
|
|
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;
|
|
|
|
if (!mice[mouse].enabled)
|
|
return;
|
|
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 (!mice[mouse].enabled)
|
|
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 (!joysticks[joy].enabled)
|
|
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;
|
|
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]);
|
|
id2->states[axis] = state;
|
|
}
|
|
|
|
void setmousestate (int mouse, int axis, int data, int isabs)
|
|
{
|
|
int i, v;
|
|
double *mouse_p, *oldm_p, d, diff;
|
|
struct uae_input_device *id = &mice[mouse];
|
|
static double fract1[MAX_INPUT_DEVICES][MAX_INPUT_DEVICE_EVENTS];
|
|
static double fract2[MAX_INPUT_DEVICES][MAX_INPUT_DEVICE_EVENTS];
|
|
|
|
if (!mice[mouse].enabled)
|
|
return;
|
|
d = 0;
|
|
mouse_p = &mouse_axis[mouse][axis];
|
|
oldm_p = &oldm_axis[mouse][axis];
|
|
if (!isabs) {
|
|
*oldm_p = *mouse_p;
|
|
*mouse_p += data;
|
|
d = (*mouse_p - *oldm_p) * currprefs.input_mouse_speed / 100.0;
|
|
} else {
|
|
d = data - (int)(*oldm_p);
|
|
*oldm_p = data;
|
|
*mouse_p += d;
|
|
if (axis == 0)
|
|
lastmx = data;
|
|
else
|
|
lastmy = data;
|
|
}
|
|
v = (int)(d > 0 ? d + 0.5 : d - 0.5);
|
|
fract1[mouse][axis] += d;
|
|
fract2[mouse][axis] += v;
|
|
diff = fract2[mouse][axis] - fract1[mouse][axis];
|
|
if (diff > 1 || diff < -1) {
|
|
v -= (int)diff;
|
|
fract2[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);
|
|
mousehack_helper ();
|
|
}
|
|
|
|
void warpmode (int mode)
|
|
{
|
|
if (mode < 0) {
|
|
if (turbo_emulation) {
|
|
changed_prefs.gfx_framerate = currprefs.gfx_framerate = turbo_emulation;
|
|
turbo_emulation = 0;
|
|
} else {
|
|
turbo_emulation = currprefs.gfx_framerate;
|
|
}
|
|
} else if (mode == 0 && turbo_emulation > 0) {
|
|
changed_prefs.gfx_framerate = currprefs.gfx_framerate = turbo_emulation;
|
|
turbo_emulation = 0;
|
|
} else if (mode > 0 && !turbo_emulation) {
|
|
turbo_emulation = currprefs.gfx_framerate;
|
|
}
|
|
if (turbo_emulation) {
|
|
if (!currprefs.cpu_cycle_exact && !currprefs.blitter_cycle_exact)
|
|
changed_prefs.gfx_framerate = currprefs.gfx_framerate = 10;
|
|
audio_pause ();
|
|
} else {
|
|
audio_resume ();
|
|
}
|
|
compute_vsynctime ();
|
|
}
|
|
|
|
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;
|
|
}
|