uae-wii/src/inputdevice.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;
}