Import of ManyMouse library
This commit is contained in:
@@ -51,10 +51,11 @@ JMAOBJ=${JMADIR}/7zlzma.o ${JMADIR}/crc32.o ${JMADIR}/iiostrm.o\
|
|||||||
${JMADIR}/winout.o ${JMADIR}/zsnesjma.o
|
${JMADIR}/winout.o ${JMADIR}/zsnesjma.o
|
||||||
|
|
||||||
MAINOBJ=cfgload.o cfg.o endmem.o init.o initc.o md.o uic.o patch.o ui.o\
|
MAINOBJ=cfgload.o cfg.o endmem.o init.o initc.o md.o uic.o patch.o ui.o\
|
||||||
vcache.o version.o zmovie.o zstate.o debug.o zloader.o
|
vcache.o version.o zmovie.o zstate.o debug.o zloader.o manymouse.o\
|
||||||
|
linux_evdev.o
|
||||||
|
|
||||||
NETOBJ=
|
NETOBJ=
|
||||||
#${NETDIR}/ztcp.o
|
#${NETDIR}/ztcp.os
|
||||||
|
|
||||||
TOOLSOBJ=${TOOLSDIR}/fileutil.o ${TOOLSDIR}/strutil.o
|
TOOLSOBJ=${TOOLSDIR}/fileutil.o ${TOOLSDIR}/strutil.o
|
||||||
|
|
||||||
@@ -154,6 +155,8 @@ version.o: version.c
|
|||||||
zloader.o: zloader.c gblhdr.h
|
zloader.o: zloader.c gblhdr.h
|
||||||
zmovie.o: zmovie.c asm_call.h gblhdr.h gblvars.h numconv.h ${WINDIR}/safelib.h md.o
|
zmovie.o: zmovie.c asm_call.h gblhdr.h gblvars.h numconv.h ${WINDIR}/safelib.h md.o
|
||||||
zstate.o: zstate.c asm_call.h gblhdr.h gblvars.h numconv.h
|
zstate.o: zstate.c asm_call.h gblhdr.h gblvars.h numconv.h
|
||||||
|
manymouse.o: manymouse.c
|
||||||
|
linux_evdev.o: linux_evdev.c
|
||||||
|
|
||||||
${CHIPDIR}/c4emu.o: ${CHIPDIR}/c4emu.c gblhdr.h
|
${CHIPDIR}/c4emu.o: ${CHIPDIR}/c4emu.c gblhdr.h
|
||||||
${CHIPDIR}/dsp1emu.o: ${CHIPDIR}/dsp1emu.c gblhdr.h
|
${CHIPDIR}/dsp1emu.o: ${CHIPDIR}/dsp1emu.c gblhdr.h
|
||||||
|
|||||||
5187
zsnes/src/init.asm
5187
zsnes/src/init.asm
File diff suppressed because it is too large
Load Diff
337
zsnes/src/linux_evdev.c
Normal file
337
zsnes/src/linux_evdev.c
Normal file
@@ -0,0 +1,337 @@
|
|||||||
|
/*
|
||||||
|
* Support for Linux evdevs...the /dev/input/event* devices.
|
||||||
|
*
|
||||||
|
* Please see the file LICENSE in the source's root directory.
|
||||||
|
*
|
||||||
|
* This file written by Ryan C. Gordon.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#include <linux/input.h> /* evdev interface... */
|
||||||
|
|
||||||
|
#include "manymouse.h"
|
||||||
|
|
||||||
|
#define test_bit(array, bit) (array[bit/8] & (1<<(bit%8)))
|
||||||
|
|
||||||
|
/* linux allows 32 evdev nodes currently. */
|
||||||
|
#define MAX_MICE 32
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
int min_x;
|
||||||
|
int min_y;
|
||||||
|
int max_x;
|
||||||
|
int max_y;
|
||||||
|
char name[64];
|
||||||
|
} MouseStruct;
|
||||||
|
|
||||||
|
static MouseStruct mice[MAX_MICE];
|
||||||
|
static unsigned int available_mice = 0;
|
||||||
|
|
||||||
|
|
||||||
|
static int poll_mouse(MouseStruct *mouse, ManyMouseEvent *outevent)
|
||||||
|
{
|
||||||
|
int unhandled = 1;
|
||||||
|
while (unhandled) /* read until failure or valid event. */
|
||||||
|
{
|
||||||
|
struct input_event event;
|
||||||
|
int br = read(mouse->fd, &event, sizeof (event));
|
||||||
|
if (br == -1)
|
||||||
|
{
|
||||||
|
if (errno == EAGAIN)
|
||||||
|
return(0); /* just no new data at the moment. */
|
||||||
|
|
||||||
|
/* mouse was unplugged? */
|
||||||
|
close(mouse->fd); /* stop reading from this mouse. */
|
||||||
|
mouse->fd = -1;
|
||||||
|
outevent->type = MANYMOUSE_EVENT_DISCONNECT;
|
||||||
|
return(1);
|
||||||
|
} /* if */
|
||||||
|
|
||||||
|
if (br != sizeof (event))
|
||||||
|
return(0); /* oh well. */
|
||||||
|
|
||||||
|
unhandled = 0; /* will reset if necessary. */
|
||||||
|
outevent->value = event.value;
|
||||||
|
if (event.type == EV_REL)
|
||||||
|
{
|
||||||
|
outevent->type = MANYMOUSE_EVENT_RELMOTION;
|
||||||
|
if ((event.code == REL_X) || (event.code == REL_DIAL))
|
||||||
|
outevent->item = 0;
|
||||||
|
else if (event.code == REL_Y)
|
||||||
|
outevent->item = 1;
|
||||||
|
|
||||||
|
else if (event.code == REL_WHEEL)
|
||||||
|
{
|
||||||
|
outevent->type = MANYMOUSE_EVENT_SCROLL;
|
||||||
|
outevent->item = 0;
|
||||||
|
} /* else if */
|
||||||
|
|
||||||
|
else if (event.code == REL_HWHEEL)
|
||||||
|
{
|
||||||
|
outevent->type = MANYMOUSE_EVENT_SCROLL;
|
||||||
|
outevent->item = 1;
|
||||||
|
} /* else if */
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unhandled = 1;
|
||||||
|
} /* else */
|
||||||
|
} /* if */
|
||||||
|
|
||||||
|
else if (event.type == EV_ABS)
|
||||||
|
{
|
||||||
|
outevent->type = MANYMOUSE_EVENT_ABSMOTION;
|
||||||
|
if (event.code == ABS_X)
|
||||||
|
{
|
||||||
|
outevent->item = 0;
|
||||||
|
outevent->minval = mouse->min_x;
|
||||||
|
outevent->maxval = mouse->max_x;
|
||||||
|
} /* if */
|
||||||
|
else if (event.code == ABS_Y)
|
||||||
|
{
|
||||||
|
outevent->item = 1;
|
||||||
|
outevent->minval = mouse->min_y;
|
||||||
|
outevent->maxval = mouse->max_y;
|
||||||
|
} /* if */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unhandled = 1;
|
||||||
|
} /* else */
|
||||||
|
} /* else if */
|
||||||
|
|
||||||
|
else if (event.type == EV_KEY)
|
||||||
|
{
|
||||||
|
outevent->type = MANYMOUSE_EVENT_BUTTON;
|
||||||
|
if ((event.code >= BTN_LEFT) && (event.code <= BTN_BACK))
|
||||||
|
outevent->item = event.code - BTN_MOUSE;
|
||||||
|
|
||||||
|
/* just in case some device uses this block of events instead... */
|
||||||
|
else if ((event.code >= BTN_MISC) && (event.code <= BTN_LEFT))
|
||||||
|
outevent->item = (event.code - BTN_MISC);
|
||||||
|
|
||||||
|
else if (event.code == BTN_TOUCH) /* tablet... */
|
||||||
|
outevent->item = 0;
|
||||||
|
else if (event.code == BTN_STYLUS) /* tablet... */
|
||||||
|
outevent->item = 1;
|
||||||
|
else if (event.code == BTN_STYLUS2) /* tablet... */
|
||||||
|
outevent->item = 2;
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*printf("unhandled mouse button: 0x%X\n", event.code);*/
|
||||||
|
unhandled = 1;
|
||||||
|
} /* else */
|
||||||
|
} /* else if */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unhandled = 1;
|
||||||
|
} /* else */
|
||||||
|
} /* while */
|
||||||
|
|
||||||
|
return(1); /* got a valid event */
|
||||||
|
} /* poll_mouse */
|
||||||
|
|
||||||
|
|
||||||
|
static int init_mouse(const char *fname, int fd)
|
||||||
|
{
|
||||||
|
MouseStruct *mouse = &mice[available_mice];
|
||||||
|
int has_absolutes = 0;
|
||||||
|
int is_mouse = 0;
|
||||||
|
unsigned char relcaps[(REL_MAX / 8) + 1];
|
||||||
|
unsigned char abscaps[(ABS_MAX / 8) + 1];
|
||||||
|
unsigned char keycaps[(KEY_MAX / 8) + 1];
|
||||||
|
|
||||||
|
memset(relcaps, '\0', sizeof (relcaps));
|
||||||
|
memset(abscaps, '\0', sizeof (abscaps));
|
||||||
|
memset(keycaps, '\0', sizeof (keycaps));
|
||||||
|
|
||||||
|
if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof (keycaps)), keycaps) == -1)
|
||||||
|
return 0; /* gotta have some buttons! :) */
|
||||||
|
|
||||||
|
if (ioctl(fd, EVIOCGBIT(EV_REL, sizeof (relcaps)), relcaps) != -1)
|
||||||
|
{
|
||||||
|
if ( (test_bit(relcaps, REL_X)) && (test_bit(relcaps, REL_Y)) )
|
||||||
|
{
|
||||||
|
if (test_bit(keycaps, BTN_MOUSE))
|
||||||
|
is_mouse = 1;
|
||||||
|
} /* if */
|
||||||
|
|
||||||
|
#if ALLOW_DIALS_TO_BE_MICE
|
||||||
|
if (test_bit(relcaps, REL_DIAL))
|
||||||
|
is_mouse = 1; // griffin powermate?
|
||||||
|
#endif
|
||||||
|
} /* if */
|
||||||
|
|
||||||
|
if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof (abscaps)), abscaps) != -1)
|
||||||
|
{
|
||||||
|
if ( (test_bit(abscaps, ABS_X)) && (test_bit(abscaps, ABS_Y)) )
|
||||||
|
{
|
||||||
|
/* might be a touchpad... */
|
||||||
|
if (test_bit(keycaps, BTN_TOUCH))
|
||||||
|
{
|
||||||
|
is_mouse = 1; /* touchpad, touchscreen, or tablet. */
|
||||||
|
has_absolutes = 1;
|
||||||
|
} /* if */
|
||||||
|
} /* if */
|
||||||
|
} /* if */
|
||||||
|
|
||||||
|
if (!is_mouse)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
mouse->min_x = mouse->min_y = mouse->max_x = mouse->max_y = 0;
|
||||||
|
if (has_absolutes)
|
||||||
|
{
|
||||||
|
struct input_absinfo absinfo;
|
||||||
|
if (ioctl(fd, EVIOCGABS(ABS_X), &absinfo) == -1)
|
||||||
|
return 0;
|
||||||
|
mouse->min_x = absinfo.minimum;
|
||||||
|
mouse->max_x = absinfo.maximum;
|
||||||
|
|
||||||
|
if (ioctl(fd, EVIOCGABS(ABS_Y), &absinfo) == -1)
|
||||||
|
return 0;
|
||||||
|
mouse->min_y = absinfo.minimum;
|
||||||
|
mouse->max_y = absinfo.maximum;
|
||||||
|
} /* if */
|
||||||
|
|
||||||
|
if (ioctl(fd, EVIOCGNAME(sizeof (mouse->name)), mouse->name) == -1)
|
||||||
|
snprintf(mouse->name, sizeof (mouse->name), "Unknown device");
|
||||||
|
|
||||||
|
mouse->fd = fd;
|
||||||
|
|
||||||
|
return 1; /* we're golden. */
|
||||||
|
} /* init_mouse */
|
||||||
|
|
||||||
|
|
||||||
|
/* Return a file descriptor if this is really a mouse, -1 otherwise. */
|
||||||
|
static int open_if_mouse(const char *fname)
|
||||||
|
{
|
||||||
|
struct stat statbuf;
|
||||||
|
int fd;
|
||||||
|
int devmajor, devminor;
|
||||||
|
|
||||||
|
if (stat(fname, &statbuf) == -1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (S_ISCHR(statbuf.st_mode) == 0)
|
||||||
|
return 0; /* not a character device... */
|
||||||
|
|
||||||
|
/* evdev node ids are major 13, minor 64-96. Is this safe to check? */
|
||||||
|
devmajor = (statbuf.st_rdev & 0xFF00) >> 8;
|
||||||
|
devminor = (statbuf.st_rdev & 0x00FF);
|
||||||
|
if ( (devmajor != 13) || (devminor < 64) || (devminor > 96) )
|
||||||
|
return 0; /* not an evdev. */
|
||||||
|
|
||||||
|
if ((fd = open(fname, O_RDONLY | O_NONBLOCK)) == -1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (init_mouse(fname, fd))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
return 0;
|
||||||
|
} /* open_if_mouse */
|
||||||
|
|
||||||
|
|
||||||
|
static int linux_evdev_init(void)
|
||||||
|
{
|
||||||
|
DIR *dirp;
|
||||||
|
struct dirent *dent;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_MICE; i++)
|
||||||
|
mice[i].fd = -1;
|
||||||
|
|
||||||
|
dirp = opendir("/dev/input");
|
||||||
|
if (!dirp)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
while ((dent = readdir(dirp)) != NULL)
|
||||||
|
{
|
||||||
|
char fname[128];
|
||||||
|
snprintf(fname, sizeof (fname), "/dev/input/%s", dent->d_name);
|
||||||
|
if (open_if_mouse(fname))
|
||||||
|
available_mice++;
|
||||||
|
} /* while */
|
||||||
|
|
||||||
|
closedir(dirp);
|
||||||
|
|
||||||
|
return available_mice;
|
||||||
|
} /* linux_evdev_init */
|
||||||
|
|
||||||
|
|
||||||
|
static void linux_evdev_quit(void)
|
||||||
|
{
|
||||||
|
while (available_mice)
|
||||||
|
{
|
||||||
|
int fd = mice[available_mice--].fd;
|
||||||
|
if (fd != -1)
|
||||||
|
close(fd);
|
||||||
|
} /* while */
|
||||||
|
} /* linux_evdev_quit */
|
||||||
|
|
||||||
|
|
||||||
|
static const char *linux_evdev_name(unsigned int index)
|
||||||
|
{
|
||||||
|
if (index < available_mice)
|
||||||
|
return(mice[index].name);
|
||||||
|
return(NULL);
|
||||||
|
} /* linux_evdev_name */
|
||||||
|
|
||||||
|
|
||||||
|
static int linux_evdev_poll(ManyMouseEvent *event)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* (i) is static so we iterate through all mice round-robin. This
|
||||||
|
* prevents a chatty mouse from dominating the queue.
|
||||||
|
*/
|
||||||
|
static unsigned int i = 0;
|
||||||
|
|
||||||
|
if (i >= available_mice)
|
||||||
|
i = 0; /* handle reset condition. */
|
||||||
|
|
||||||
|
if (event != NULL)
|
||||||
|
{
|
||||||
|
while (i < available_mice)
|
||||||
|
{
|
||||||
|
MouseStruct *mouse = &mice[i];
|
||||||
|
if (mouse->fd != -1)
|
||||||
|
{
|
||||||
|
if (poll_mouse(mouse, event))
|
||||||
|
{
|
||||||
|
event->device = i;
|
||||||
|
return(1);
|
||||||
|
} /* if */
|
||||||
|
} /* if */
|
||||||
|
i++;
|
||||||
|
} /* while */
|
||||||
|
} /* if */
|
||||||
|
|
||||||
|
return(0); /* no new events */
|
||||||
|
} /* linux_evdev_poll */
|
||||||
|
|
||||||
|
|
||||||
|
ManyMouseDriver ManyMouseDriver_evdev =
|
||||||
|
{
|
||||||
|
linux_evdev_init,
|
||||||
|
linux_evdev_quit,
|
||||||
|
linux_evdev_name,
|
||||||
|
linux_evdev_poll
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* defined __linux__ */
|
||||||
|
|
||||||
|
/* end of linux_evdev.c ... */
|
||||||
|
|
||||||
92
zsnes/src/manymouse.c
Normal file
92
zsnes/src/manymouse.c
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* ManyMouse foundation code; apps talks to this and it talks to the lowlevel
|
||||||
|
* code for various platforms.
|
||||||
|
*
|
||||||
|
* Please see the file LICENSE in the source's root directory.
|
||||||
|
*
|
||||||
|
* This file written by Ryan C. Gordon.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "manymouse.h"
|
||||||
|
|
||||||
|
static const char *manymouse_copyright =
|
||||||
|
"ManyMouse " MANYMOUSE_VERSION " (c) 2005 Ryan C. Gordon.";
|
||||||
|
|
||||||
|
extern const ManyMouseDriver ManyMouseDriver_windows;
|
||||||
|
extern const ManyMouseDriver ManyMouseDriver_evdev;
|
||||||
|
extern const ManyMouseDriver ManyMouseDriver_mousedev;
|
||||||
|
extern const ManyMouseDriver ManyMouseDriver_hidmanager;
|
||||||
|
extern const ManyMouseDriver ManyMouseDriver_xinput;
|
||||||
|
|
||||||
|
static const ManyMouseDriver *mice_drivers[] =
|
||||||
|
{
|
||||||
|
#if SUPPORT_XINPUT
|
||||||
|
&ManyMouseDriver_xinput,
|
||||||
|
#endif
|
||||||
|
#if ((defined _WIN32) || defined(__CYGWIN__))
|
||||||
|
&ManyMouseDriver_windows,
|
||||||
|
#endif
|
||||||
|
#ifdef __linux__
|
||||||
|
&ManyMouseDriver_evdev,
|
||||||
|
/*&ManyMouseDriver_mousedev,*/
|
||||||
|
#endif
|
||||||
|
#if ( (defined(__MACH__)) && (defined(__APPLE__)) )
|
||||||
|
&ManyMouseDriver_hidmanager,
|
||||||
|
#endif
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static const ManyMouseDriver *driver = NULL;
|
||||||
|
|
||||||
|
int ManyMouse_Init(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* impossible test to keep manymouse_copyright linked into the binary. */
|
||||||
|
if ((char *) driver == (const char *) manymouse_copyright)
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
if (driver != NULL)
|
||||||
|
return(-1);
|
||||||
|
|
||||||
|
for (i = 0; mice_drivers[i]; i++)
|
||||||
|
{
|
||||||
|
int mice = mice_drivers[i]->init();
|
||||||
|
if (mice >= 0)
|
||||||
|
{
|
||||||
|
driver = mice_drivers[i];
|
||||||
|
return(mice);
|
||||||
|
} /* if */
|
||||||
|
} /* for */
|
||||||
|
|
||||||
|
return(-1);
|
||||||
|
} /* ManyMouse_Init */
|
||||||
|
|
||||||
|
|
||||||
|
void ManyMouse_Quit(void)
|
||||||
|
{
|
||||||
|
if (driver != NULL)
|
||||||
|
driver->quit();
|
||||||
|
driver = NULL;
|
||||||
|
} /* ManyMouse_Quit */
|
||||||
|
|
||||||
|
|
||||||
|
const char *ManyMouse_DeviceName(unsigned int index)
|
||||||
|
{
|
||||||
|
if (driver != NULL)
|
||||||
|
return(driver->name(index));
|
||||||
|
return(NULL);
|
||||||
|
} /* ManyMouse_PollEvent */
|
||||||
|
|
||||||
|
|
||||||
|
int ManyMouse_PollEvent(ManyMouseEvent *event)
|
||||||
|
{
|
||||||
|
if (driver != NULL)
|
||||||
|
return(driver->poll(event));
|
||||||
|
return(0);
|
||||||
|
} /* ManyMouse_PollEvent */
|
||||||
|
|
||||||
|
/* end of manymouse.c ... */
|
||||||
|
|
||||||
61
zsnes/src/manymouse.h
Normal file
61
zsnes/src/manymouse.h
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* ManyMouse main header. Include this from your app.
|
||||||
|
*
|
||||||
|
* Please see the file LICENSE in the source's root directory.
|
||||||
|
*
|
||||||
|
* This file written by Ryan C. Gordon.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _INCLUDE_MANYMOUSE_H_
|
||||||
|
#define _INCLUDE_MANYMOUSE_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MANYMOUSE_VERSION "0.0.1"
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
MANYMOUSE_EVENT_ABSMOTION = 0,
|
||||||
|
MANYMOUSE_EVENT_RELMOTION,
|
||||||
|
MANYMOUSE_EVENT_BUTTON,
|
||||||
|
MANYMOUSE_EVENT_SCROLL,
|
||||||
|
MANYMOUSE_EVENT_DISCONNECT,
|
||||||
|
MANYMOUSE_EVENT_MAX
|
||||||
|
} ManyMouseEventType;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
ManyMouseEventType type;
|
||||||
|
unsigned int device;
|
||||||
|
unsigned int item;
|
||||||
|
int value;
|
||||||
|
int minval;
|
||||||
|
int maxval;
|
||||||
|
} ManyMouseEvent;
|
||||||
|
|
||||||
|
|
||||||
|
/* internal use only. */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int (*init)(void);
|
||||||
|
void (*quit)(void);
|
||||||
|
const char *(*name)(unsigned int index);
|
||||||
|
int (*poll)(ManyMouseEvent *event);
|
||||||
|
} ManyMouseDriver;
|
||||||
|
|
||||||
|
|
||||||
|
int ManyMouse_Init(void);
|
||||||
|
void ManyMouse_Quit(void);
|
||||||
|
const char *ManyMouse_DeviceName(unsigned int index);
|
||||||
|
int ManyMouse_PollEvent(ManyMouseEvent *event);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* !defined _INCLUDE_MANYMOUSE_H_ */
|
||||||
|
|
||||||
|
/* end of manymouse.h ... */
|
||||||
|
|
||||||
884
zsnes/src/uic.c
884
zsnes/src/uic.c
@@ -1,417 +1,467 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (C) 1997-2005 ZSNES Team ( zsKnight, _Demo_, pagefault, Nach )
|
Copyright (C) 1997-2005 ZSNES Team ( zsKnight, _Demo_, pagefault, Nach )
|
||||||
|
|
||||||
http://www.zsnes.com
|
http://www.zsnes.com
|
||||||
http://sourceforge.net/projects/zsnes
|
http://sourceforge.net/projects/zsnes
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License
|
modify it under the terms of the GNU General Public License
|
||||||
as published by the Free Software Foundation; either
|
as published by the Free Software Foundation; either
|
||||||
version 2 of the License, or (at your option) any later
|
version 2 of the License, or (at your option) any later
|
||||||
version.
|
version.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#ifdef __UNIXSDL__
|
#ifdef __UNIXSDL__
|
||||||
#include "gblhdr.h"
|
#include "gblhdr.h"
|
||||||
#else
|
#else
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "asm_call.h"
|
#include "asm_call.h"
|
||||||
|
#include "manymouse.h"
|
||||||
//C++ style code in C
|
|
||||||
#define bool unsigned char
|
//C++ style code in C
|
||||||
#define true 1
|
#define bool unsigned char
|
||||||
#define false 0
|
#define true 1
|
||||||
|
#define false 0
|
||||||
extern unsigned char *vbufaptr;
|
|
||||||
extern unsigned char *vbufeptr;
|
extern unsigned char *vbufaptr;
|
||||||
extern unsigned char *ngwinptrb;
|
extern unsigned char *vbufeptr;
|
||||||
extern unsigned char *vbufdptr;
|
extern unsigned char *ngwinptrb;
|
||||||
extern unsigned char *romaptr;
|
extern unsigned char *vbufdptr;
|
||||||
extern unsigned char mydebug[2];
|
extern unsigned char *romaptr;
|
||||||
extern unsigned char outofmem[51];
|
extern unsigned char mydebug[2];
|
||||||
extern unsigned char YesMMX[34];
|
extern unsigned char outofmem[51];
|
||||||
|
extern unsigned char YesMMX[34];
|
||||||
// Global Variables ported from ASM
|
|
||||||
|
// Global Variables ported from ASM
|
||||||
unsigned int per2exec = 100; // percentage of opcodes to execute
|
|
||||||
|
unsigned int per2exec = 100; // percentage of opcodes to execute
|
||||||
#ifdef __MSDOS__
|
|
||||||
unsigned char cvidmode = 4; // video mode
|
#ifdef __MSDOS__
|
||||||
#else
|
unsigned char cvidmode = 4; // video mode
|
||||||
unsigned char cvidmode = 1;
|
#else
|
||||||
#endif
|
unsigned char cvidmode = 1;
|
||||||
|
#endif
|
||||||
unsigned char string[512];
|
|
||||||
unsigned char fname[512];
|
unsigned char string[512];
|
||||||
unsigned char fnames[512]; // sram filename
|
unsigned char fname[512];
|
||||||
unsigned char fnamest[512]; // state filename
|
unsigned char fnames[512]; // sram filename
|
||||||
|
unsigned char fnamest[512]; // state filename
|
||||||
unsigned short selc0040;
|
|
||||||
unsigned short selcA000;
|
unsigned short selc0040;
|
||||||
unsigned short selcB800;
|
unsigned short selcA000;
|
||||||
unsigned char filefound; // Parameter String Found
|
unsigned short selcB800;
|
||||||
unsigned char frameskip; // 0 = Auto, 1-10 = Skip 0 .. 9
|
unsigned char filefound; // Parameter String Found
|
||||||
unsigned char *vidbuffer; // video buffer (1024x239 = 244736)
|
unsigned char frameskip; // 0 = Auto, 1-10 = Skip 0 .. 9
|
||||||
unsigned char *ngwinptr;
|
unsigned char *vidbuffer; // video buffer (1024x239 = 244736)
|
||||||
unsigned char *vidbufferm; // video buffer mirror
|
unsigned char *ngwinptr;
|
||||||
unsigned char *vidbufferofsa; // offset 1
|
unsigned char *vidbufferm; // video buffer mirror
|
||||||
unsigned char *vidbufferofsb; // offset 2
|
unsigned char *vidbufferofsa; // offset 1
|
||||||
unsigned char *vidbufferofsc; // offset 3
|
unsigned char *vidbufferofsb; // offset 2
|
||||||
unsigned char *vidbufferofsmos; // mosaic offset for new graphics engine
|
unsigned char *vidbufferofsc; // offset 3
|
||||||
unsigned char *headdata;
|
unsigned char *vidbufferofsmos; // mosaic offset for new graphics engine
|
||||||
unsigned char *romdata; // rom data (4MB = 4194304)
|
unsigned char *headdata;
|
||||||
unsigned char *sfxramdata; // SuperFX Ram Data
|
unsigned char *romdata; // rom data (4MB = 4194304)
|
||||||
unsigned char *setaramdata; // Seta ST010/ST011 SRam Data
|
unsigned char *sfxramdata; // SuperFX Ram Data
|
||||||
unsigned char *wramdata; // stack (64K = 32768)
|
unsigned char *setaramdata; // Seta ST010/ST011 SRam Data
|
||||||
unsigned char *ram7f; // ram @ 7f = 65536
|
unsigned char *wramdata; // stack (64K = 32768)
|
||||||
unsigned char *vram; // vram = 65536
|
unsigned char *ram7f; // ram @ 7f = 65536
|
||||||
unsigned char *sram; // sram = 32768
|
unsigned char *vram; // vram = 65536
|
||||||
unsigned char *spritetablea;
|
unsigned char *sram; // sram = 32768
|
||||||
unsigned char *spcBuffera;
|
unsigned char *spritetablea;
|
||||||
unsigned char *debugbuf; // debug buffer = 38x1000 = 38000
|
unsigned char *spcBuffera;
|
||||||
void (**regptr)(); // pointer to registers
|
unsigned char *debugbuf; // debug buffer = 38x1000 = 38000
|
||||||
void (**regptw)(); // pointer to registers
|
void (**regptr)(); // pointer to registers
|
||||||
unsigned char *vcache2b; // 2-bit video cache
|
void (**regptw)(); // pointer to registers
|
||||||
unsigned char *vcache4b; // 4-bit video cache
|
unsigned char *vcache2b; // 2-bit video cache
|
||||||
unsigned char *vcache8b; // 8-bit video cache
|
unsigned char *vcache4b; // 4-bit video cache
|
||||||
unsigned char *vcache2bs; // 2-bit video secondary cache
|
unsigned char *vcache8b; // 8-bit video cache
|
||||||
unsigned char *vcache4bs; // 4-bit video secondary cache
|
unsigned char *vcache2bs; // 2-bit video secondary cache
|
||||||
unsigned char *vcache8bs; // 8-bit video secondary cache
|
unsigned char *vcache4bs; // 4-bit video secondary cache
|
||||||
unsigned char romispal; // 0 = NTSC, 1 = PAL
|
unsigned char *vcache8bs; // 8-bit video secondary cache
|
||||||
unsigned char enterpress; // if enter is to be issued (0 = yes)
|
unsigned char romispal; // 0 = NTSC, 1 = PAL
|
||||||
unsigned char newgfx16b;
|
unsigned char enterpress; // if enter is to be issued (0 = yes)
|
||||||
unsigned char *BitConv32Ptr;
|
unsigned char newgfx16b;
|
||||||
unsigned char *RGBtoYUVPtr;
|
unsigned char *BitConv32Ptr;
|
||||||
|
unsigned char *RGBtoYUVPtr;
|
||||||
unsigned char previdmode; // previous video mode
|
|
||||||
unsigned char cbitmode; // bit mode, 0=8bit, 1=16bit
|
unsigned char previdmode; // previous video mode
|
||||||
|
unsigned char cbitmode; // bit mode, 0=8bit, 1=16bit
|
||||||
unsigned char opexec268 = 155; // # of opcodes/scanline in 2.68Mhz mode
|
|
||||||
unsigned char opexec358 = 172; // # of opcodes/scanline in 3.58Mhz mode (228/180)
|
unsigned char opexec268 = 155; // # of opcodes/scanline in 2.68Mhz mode
|
||||||
unsigned char opexec268cph = 42; // # of opcodes/hblank in 2.68Mhz mode
|
unsigned char opexec358 = 142; // # of opcodes/scanline in 3.58Mhz mode (228/180)
|
||||||
unsigned char opexec358cph = 45; // # of opcodes/hblank in 3.58Mhz mode (56/50)
|
unsigned char opexec268cph = 42; // # of opcodes/hblank in 2.68Mhz mode
|
||||||
unsigned char opexec268b = 155; // # of opcodes/scanline in 2.68Mhz mode
|
unsigned char opexec358cph = 45; // # of opcodes/hblank in 3.58Mhz mode (56/50)
|
||||||
unsigned char opexec358b = 172; // # of opcodes/scanline in 3.58Mhz mode (228/180)
|
unsigned char opexec268b = 142; // # of opcodes/scanline in 2.68Mhz mode
|
||||||
unsigned char opexec268cphb = 42; // # of opcodes/hblank in 2.68Mhz mode
|
unsigned char opexec358b = 155; // # of opcodes/scanline in 3.58Mhz mode (228/180)
|
||||||
unsigned char opexec358cphb = 45; // # of opcodes/hblank in 3.58Mhz mode (56/50)
|
unsigned char opexec268cphb = 42; // # of opcodes/hblank in 2.68Mhz mode
|
||||||
unsigned char debugdisble = 1; // debugger disable. 0 = no, 1 = yes
|
unsigned char opexec358cphb = 45; // # of opcodes/hblank in 3.58Mhz mode (56/50)
|
||||||
unsigned char gammalevel = 0; // gamma level (8-bit engine)
|
unsigned char debugdisble = 1; // debugger disable. 0 = no, 1 = yes
|
||||||
unsigned char gammalevel16b = 0; // gamma level (16-bit engine)
|
unsigned char gammalevel = 0; // gamma level (8-bit engine)
|
||||||
unsigned char scanlines = 0; // scanlines on/off
|
unsigned char gammalevel16b = 0; // gamma level (16-bit engine)
|
||||||
unsigned char vsyncon = 0; // vsync on/off
|
unsigned char scanlines = 0; // scanlines on/off
|
||||||
unsigned char guioff = 0; // gui on/off (1 = off)
|
unsigned char vsyncon = 0; // vsync on/off
|
||||||
unsigned char AddSub256 = 0; // screen add/sub in 256 colors
|
unsigned char guioff = 0; // gui on/off (1 = off)
|
||||||
unsigned char Sup48mbit = 1; // Support 48mbit roms
|
unsigned char AddSub256 = 0; // screen add/sub in 256 colors
|
||||||
unsigned char Sup16mbit = 0; // Support 16mbit roms
|
unsigned char Sup48mbit = 1; // Support 48mbit roms
|
||||||
unsigned char dmadeddis = 0; // DMA deduction
|
unsigned char Sup16mbit = 0; // Support 16mbit roms
|
||||||
unsigned char antienab = 0; // Interpolation Enabled
|
unsigned char dmadeddis = 0; // DMA deduction
|
||||||
unsigned char snesmouse = 0; // Mouse status (1 = enabled)
|
unsigned char antienab = 0; // Interpolation Enabled
|
||||||
unsigned char OldStyle = 1; // Old style joystick on
|
unsigned char snesmouse = 0; // Mouse status (1 = enabled)
|
||||||
unsigned char SecondPort = 0; // Secondary Joystick Port Enabled (209h) (DOS port only)
|
unsigned char OldStyle = 1; // Old style joystick on
|
||||||
|
unsigned char SecondPort = 0; // Secondary Joystick Port Enabled (209h) (DOS port only)
|
||||||
// New Variables
|
|
||||||
unsigned char ForcePal = 0; // 1 = NTSC, 2 = PAL
|
// New Variables
|
||||||
unsigned char Force8b = 0; // Force 8-bit sound on
|
unsigned char ForcePal = 0; // 1 = NTSC, 2 = PAL
|
||||||
unsigned char Doublevbuf = 1; // Double video buffer
|
unsigned char Force8b = 0; // Force 8-bit sound on
|
||||||
unsigned char V8Mode = 0; // Vegetable mode! =) (Greyscale mode)
|
unsigned char Doublevbuf = 1; // Double video buffer
|
||||||
unsigned char fastmemptr = 0;
|
unsigned char V8Mode = 0; // Vegetable mode! =) (Greyscale mode)
|
||||||
unsigned char showallext = 0; // Show all extensions in GUI load dialog
|
unsigned char fastmemptr = 0;
|
||||||
unsigned char finterleave = 0;
|
unsigned char showallext = 0; // Show all extensions in GUI load dialog
|
||||||
unsigned char DSPDisable = 0; // Disable DSP emulation
|
unsigned char finterleave = 0;
|
||||||
unsigned char Palette0 = 0;
|
unsigned char DSPDisable = 0; // Disable DSP emulation
|
||||||
unsigned char DisplayS = 0;
|
unsigned char Palette0 = 0;
|
||||||
unsigned char *spc7110romptr;
|
unsigned char DisplayS = 0;
|
||||||
|
unsigned char *spc7110romptr;
|
||||||
unsigned char MusicRelVol = 75;
|
|
||||||
unsigned char MusicVol = 0;
|
unsigned char MusicRelVol = 75;
|
||||||
unsigned char MMXextSupport = 0;
|
unsigned char MusicVol = 0;
|
||||||
extern char *Msgptr;
|
unsigned char MMXextSupport = 0;
|
||||||
|
extern char *Msgptr;
|
||||||
void outofmemory();
|
|
||||||
void init();
|
void outofmemory();
|
||||||
void WaitForKey();
|
void init();
|
||||||
void MMXCheck();
|
void WaitForKey();
|
||||||
void allocmem();
|
void MMXCheck();
|
||||||
void InitSPC();
|
void allocmem();
|
||||||
void SystemInit();
|
void InitSPC();
|
||||||
void StartUp();
|
void SystemInit();
|
||||||
|
void StartUp();
|
||||||
void *doMemAlloc(size_t size)
|
void MultiMouseInit();
|
||||||
{
|
|
||||||
void *ptr = NULL;
|
void *doMemAlloc(size_t size)
|
||||||
ptr = malloc(size);
|
{
|
||||||
if (!ptr)
|
void *ptr = NULL;
|
||||||
{
|
ptr = malloc(size);
|
||||||
asm_call(outofmemory);
|
if (!ptr)
|
||||||
}
|
{
|
||||||
return(ptr);
|
asm_call(outofmemory);
|
||||||
}
|
}
|
||||||
|
return(ptr);
|
||||||
void allocspc7110()
|
}
|
||||||
{
|
|
||||||
spc7110romptr = (unsigned char *)doMemAlloc(8192*1024+4096);
|
void allocspc7110()
|
||||||
}
|
{
|
||||||
|
spc7110romptr = (unsigned char *)doMemAlloc(8192*1024+4096);
|
||||||
extern bool input1gp;
|
}
|
||||||
extern bool input1mouse;
|
|
||||||
extern bool input2gp;
|
extern bool input1gp;
|
||||||
extern bool input2mouse;
|
extern bool input1mouse;
|
||||||
extern bool input2scope;
|
extern bool input2gp;
|
||||||
extern bool input2just;
|
extern bool input2mouse;
|
||||||
extern unsigned char snesmouse;
|
extern bool input2scope;
|
||||||
void cycleinputdevice()
|
extern bool input2just;
|
||||||
{
|
extern unsigned char snesmouse;
|
||||||
for (;;)
|
void cycleinputdevice()
|
||||||
{
|
{
|
||||||
snesmouse++;
|
for (;;)
|
||||||
if (snesmouse >= 5)
|
{
|
||||||
{
|
snesmouse++;
|
||||||
snesmouse = 0;
|
if (snesmouse >= 5)
|
||||||
}
|
{
|
||||||
if (snesmouse == 0)
|
snesmouse = 0;
|
||||||
{
|
}
|
||||||
if (input1gp && input2gp) { return; }
|
if (snesmouse == 0)
|
||||||
snesmouse++;
|
{
|
||||||
}
|
if (input1gp && input2gp) { return; }
|
||||||
if (snesmouse == 1)
|
snesmouse++;
|
||||||
{
|
}
|
||||||
if (input1mouse) { return; }
|
if (snesmouse == 1)
|
||||||
snesmouse++;
|
{
|
||||||
}
|
if (input1mouse) { return; }
|
||||||
if (snesmouse == 2)
|
snesmouse++;
|
||||||
{
|
}
|
||||||
if (input2mouse) { return; }
|
if (snesmouse == 2)
|
||||||
snesmouse++;
|
{
|
||||||
}
|
if (input2mouse) { return; }
|
||||||
if (snesmouse == 3)
|
snesmouse++;
|
||||||
{
|
}
|
||||||
if (input2scope) { return; }
|
if (snesmouse == 3)
|
||||||
snesmouse++;
|
{
|
||||||
}
|
if (input2scope) { return; }
|
||||||
if (snesmouse == 4)
|
snesmouse++;
|
||||||
{
|
}
|
||||||
if (input2just) { return; }
|
if (snesmouse == 4)
|
||||||
}
|
{
|
||||||
}
|
if (input2just) { return; }
|
||||||
}
|
}
|
||||||
|
}
|
||||||
unsigned char NoiseData[32768];
|
}
|
||||||
const unsigned char samplenoise[128] = {
|
|
||||||
27,232,234,138,187,246,176, 81, 25,241, 1,127,154,190,195,103,
|
unsigned char NoiseData[32768];
|
||||||
231,165,220,238,232,189, 57,201,123, 75, 63,143,145,159, 13,236,
|
const unsigned char samplenoise[128] = {
|
||||||
191,142, 56,164,222, 80, 88, 13,148,118,162,212,157,146,176, 0,
|
27,232,234,138,187,246,176, 81, 25,241, 1,127,154,190,195,103,
|
||||||
241, 88,244,238, 51,235,149, 50, 77,212,186,241, 88, 32, 23,206,
|
231,165,220,238,232,189, 57,201,123, 75, 63,143,145,159, 13,236,
|
||||||
1, 24, 48,244,248,210,253, 77, 19,100, 83,222,108, 68, 11, 58,
|
191,142, 56,164,222, 80, 88, 13,148,118,162,212,157,146,176, 0,
|
||||||
152,161,223,245, 4,105, 3, 82, 15,130,171,242,141, 2,172,218,
|
241, 88,244,238, 51,235,149, 50, 77,212,186,241, 88, 32, 23,206,
|
||||||
152, 97,223,157, 93, 75, 83,238,104,238,131, 70, 22,252,180, 82,
|
1, 24, 48,244,248,210,253, 77, 19,100, 83,222,108, 68, 11, 58,
|
||||||
110,123,106,133,183,209, 48,230,157,205, 27, 21,107, 63, 85,164};
|
152,161,223,245, 4,105, 3, 82, 15,130,171,242,141, 2,172,218,
|
||||||
|
152, 97,223,157, 93, 75, 83,238,104,238,131, 70, 22,252,180, 82,
|
||||||
void setnoise()
|
110,123,106,133,183,209, 48,230,157,205, 27, 21,107, 63, 85,164};
|
||||||
{
|
|
||||||
unsigned short ctr1, ctr2, ptr1=0;
|
void setnoise()
|
||||||
unsigned char ptr2=0, ptr3=0;
|
{
|
||||||
|
unsigned short ctr1, ctr2, ptr1=0;
|
||||||
for(ctr1=256;ctr1>0;ctr1--)
|
unsigned char ptr2=0, ptr3=0;
|
||||||
{
|
|
||||||
for(ctr2=128;ctr2>0;ctr2--,ptr1++)
|
for(ctr1=256;ctr1>0;ctr1--)
|
||||||
{
|
{
|
||||||
NoiseData[ptr1] = (samplenoise[ptr2] + samplenoise[ptr3]);
|
for(ctr2=128;ctr2>0;ctr2--,ptr1++)
|
||||||
ptr2=(ptr2+1)&0x7f;
|
{
|
||||||
ptr3=(ptr3-1)&0x7f;
|
NoiseData[ptr1] = (samplenoise[ptr2] + samplenoise[ptr3]);
|
||||||
}
|
ptr2=(ptr2+1)&0x7f;
|
||||||
ptr3=(ptr3-1)&0x7f;
|
ptr3=(ptr3-1)&0x7f;
|
||||||
}
|
}
|
||||||
}
|
ptr3=(ptr3-1)&0x7f;
|
||||||
|
}
|
||||||
|
}
|
||||||
extern unsigned int xa;
|
|
||||||
extern unsigned char soundon, SPCDisable, spcon, FPSOn, FPSAtStart;
|
|
||||||
|
extern unsigned int xa;
|
||||||
const unsigned int versionNumber = 0x0000008F; // 1.43
|
extern unsigned char soundon, SPCDisable, spcon, FPSOn, FPSAtStart;
|
||||||
char *ZVERSION = "Pre 1.43";
|
|
||||||
unsigned char txtfailedalignd[25] = "Data Alignment Failure : ";
|
const unsigned int versionNumber = 0x0000008F; // 1.43
|
||||||
unsigned char txtfailedalignc[25] = "Code Alignment Failure : ";
|
char *ZVERSION = "Pre 1.43";
|
||||||
|
unsigned char txtfailedalignd[25] = "Data Alignment Failure : ";
|
||||||
void zstart ()
|
unsigned char txtfailedalignc[25] = "Code Alignment Failure : ";
|
||||||
{
|
|
||||||
unsigned int ptr;
|
void zstart ()
|
||||||
|
{
|
||||||
asm_call(StartUp);
|
unsigned int ptr;
|
||||||
|
|
||||||
printf("%s", mydebug);
|
asm_call(StartUp);
|
||||||
|
|
||||||
// Print welcome message.
|
printf("%s", mydebug);
|
||||||
printf("ZSNES v%s, (c) 1997-2005, ZSNES Team\n", ZVERSION);
|
|
||||||
puts("Be sure to check http://www.zsnes.com/ for the latest version.");
|
// Print welcome message.
|
||||||
puts("Please report crashes to zsnes-devel@lists.sourceforge.net.\n");
|
printf("ZSNES v%s, (c) 1997-2005, ZSNES Team\n", ZVERSION);
|
||||||
puts("ZSNES is written by the ZSNES Team (See AUTHORS.TXT)");
|
puts("Be sure to check http://www.zsnes.com/ for the latest version.");
|
||||||
puts("ZSNES comes with ABSOLUTELY NO WARRANTY. This is free software,");
|
puts("Please report crashes to zsnes-devel@lists.sourceforge.net.\n");
|
||||||
puts("and you are welcome to redistribute it under certain conditions;");
|
puts("ZSNES is written by the ZSNES Team (See AUTHORS.TXT)");
|
||||||
puts("please read 'LICENSE.TXT' thoroughly before doing so.\n");
|
puts("ZSNES comes with ABSOLUTELY NO WARRANTY. This is free software,");
|
||||||
puts("Use ZSNES -? for command line definitions.\n");
|
puts("and you are welcome to redistribute it under certain conditions;");
|
||||||
|
puts("please read 'LICENSE.TXT' thoroughly before doing so.\n");
|
||||||
#ifndef __RELEASE__
|
puts("Use ZSNES -? for command line definitions.\n");
|
||||||
puts("This is a work in progress build. It contains code which");
|
|
||||||
puts("May or may not be complete");
|
#ifndef __RELEASE__
|
||||||
#endif
|
puts("This is a work in progress build. It contains code which");
|
||||||
|
puts("May or may not be complete");
|
||||||
asm_call(SystemInit);
|
#endif
|
||||||
|
|
||||||
|
#ifndef __MSDOS__
|
||||||
#ifdef OPENSPC
|
MultiMouseInit();
|
||||||
OSPC_Init();
|
#endif
|
||||||
#else
|
|
||||||
setnoise();
|
asm_call(SystemInit);
|
||||||
asm_call(InitSPC);
|
|
||||||
#endif
|
|
||||||
|
#ifdef OPENSPC
|
||||||
asm_call(allocmem);
|
OSPC_Init();
|
||||||
|
#else
|
||||||
if (!soundon && (SPCDisable != 1))
|
setnoise();
|
||||||
{
|
asm_call(InitSPC);
|
||||||
soundon = 1;
|
#endif
|
||||||
spcon = 1;
|
|
||||||
DSPDisable = 1;
|
asm_call(allocmem);
|
||||||
}
|
|
||||||
|
if (!soundon && (SPCDisable != 1))
|
||||||
if (SPCDisable)
|
{
|
||||||
{
|
soundon = 1;
|
||||||
soundon = 0;
|
spcon = 1;
|
||||||
spcon = 0;
|
DSPDisable = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!frameskip)
|
if (SPCDisable)
|
||||||
{
|
{
|
||||||
FPSOn = FPSAtStart;
|
soundon = 0;
|
||||||
}
|
spcon = 0;
|
||||||
|
}
|
||||||
gammalevel16b = gammalevel >> 1;
|
|
||||||
|
if (!frameskip)
|
||||||
asm_call(MMXCheck);
|
{
|
||||||
|
FPSOn = FPSAtStart;
|
||||||
ptr = (unsigned int)&outofmemory;
|
}
|
||||||
|
|
||||||
if ((ptr & 3))
|
gammalevel16b = gammalevel >> 1;
|
||||||
{
|
|
||||||
printf("%s%d", txtfailedalignc, (ptr & 0x1F));
|
asm_call(MMXCheck);
|
||||||
|
|
||||||
asm_call(WaitForKey);
|
ptr = (unsigned int)&outofmemory;
|
||||||
}
|
|
||||||
|
if ((ptr & 3))
|
||||||
ptr = (unsigned int)&xa;
|
{
|
||||||
|
printf("%s%d", txtfailedalignc, (ptr & 0x1F));
|
||||||
if ((ptr & 3))
|
|
||||||
{
|
asm_call(WaitForKey);
|
||||||
printf("%s%d", txtfailedalignd, (ptr & 0x1F));
|
}
|
||||||
|
|
||||||
asm_call(WaitForKey);
|
ptr = (unsigned int)&xa;
|
||||||
}
|
|
||||||
|
if ((ptr & 3))
|
||||||
asm_call(init);
|
{
|
||||||
}
|
printf("%s%d", txtfailedalignd, (ptr & 0x1F));
|
||||||
|
|
||||||
static char *seconds_to_asc(unsigned int seconds)
|
asm_call(WaitForKey);
|
||||||
{
|
}
|
||||||
static char buffer[50];
|
|
||||||
char *p = buffer;
|
asm_call(init);
|
||||||
unsigned int hours, minutes;
|
}
|
||||||
|
|
||||||
hours = seconds/3600;
|
static char *seconds_to_asc(unsigned int seconds)
|
||||||
seconds -= hours*3600;
|
{
|
||||||
minutes = seconds/60;
|
static char buffer[50];
|
||||||
seconds -= minutes*60;
|
char *p = buffer;
|
||||||
*buffer = 0;
|
unsigned int hours, minutes;
|
||||||
|
|
||||||
if (hours)
|
hours = seconds/3600;
|
||||||
{
|
seconds -= hours*3600;
|
||||||
sprintf(p, "%u hours ", hours);
|
minutes = seconds/60;
|
||||||
p += strlen(p);
|
seconds -= minutes*60;
|
||||||
}
|
*buffer = 0;
|
||||||
if (minutes)
|
|
||||||
{
|
if (hours)
|
||||||
sprintf(p, "%u min ", minutes);
|
{
|
||||||
p += strlen(p);
|
sprintf(p, "%u hours ", hours);
|
||||||
}
|
p += strlen(p);
|
||||||
if (seconds)
|
}
|
||||||
{
|
if (minutes)
|
||||||
sprintf(p, "%u sec", seconds);
|
{
|
||||||
p += strlen(p);
|
sprintf(p, "%u min ", minutes);
|
||||||
}
|
p += strlen(p);
|
||||||
if (!*buffer)
|
}
|
||||||
{
|
if (seconds)
|
||||||
strcpy(buffer, "0 sec");
|
{
|
||||||
}
|
sprintf(p, "%u sec", seconds);
|
||||||
return(buffer);
|
p += strlen(p);
|
||||||
}
|
}
|
||||||
|
if (!*buffer)
|
||||||
extern unsigned int MessageOn;
|
{
|
||||||
extern unsigned int MsgCount;
|
strcpy(buffer, "0 sec");
|
||||||
extern char CSStatus[70];
|
}
|
||||||
extern char CSStatus2[70];
|
return(buffer);
|
||||||
extern char CSStatus3[70];
|
}
|
||||||
|
|
||||||
void DisplayBatteryStatus()
|
unsigned char multiMouseMode = 0;
|
||||||
{
|
|
||||||
#ifndef __MSDOS__
|
extern unsigned int MessageOn;
|
||||||
int CheckBattery();
|
extern unsigned int MsgCount;
|
||||||
int CheckBatteryTime();
|
extern char CSStatus[70];
|
||||||
int CheckBatteryPercent();
|
extern char CSStatus2[70];
|
||||||
|
extern char CSStatus3[70];
|
||||||
*CSStatus2 = 0;
|
|
||||||
*CSStatus3 = 0;
|
void DisplayBatteryStatus()
|
||||||
|
{
|
||||||
switch (CheckBattery())
|
#ifndef __MSDOS__
|
||||||
{
|
int CheckBattery();
|
||||||
case -1: //No battery
|
int CheckBatteryTime();
|
||||||
strcpy(CSStatus, "No battery present");
|
int CheckBatteryPercent();
|
||||||
break;
|
|
||||||
|
*CSStatus2 = 0;
|
||||||
case 0: //Plugged in
|
*CSStatus3 = 0;
|
||||||
{
|
|
||||||
int percent = CheckBatteryPercent();
|
switch (CheckBattery())
|
||||||
|
{
|
||||||
strcpy(CSStatus, "PC is plugged in");
|
case -1: //No battery
|
||||||
if (percent > 0)
|
strcpy(CSStatus, "No battery present");
|
||||||
{
|
break;
|
||||||
sprintf(CSStatus2, "%d%% charged", percent);
|
|
||||||
}
|
case 0: //Plugged in
|
||||||
}
|
{
|
||||||
break;
|
int percent = CheckBatteryPercent();
|
||||||
|
|
||||||
case 1: //Not plugged in
|
strcpy(CSStatus, "PC is plugged in");
|
||||||
{
|
if (percent > 0)
|
||||||
int percent = CheckBatteryPercent();
|
{
|
||||||
int battery_time = CheckBatteryTime();
|
sprintf(CSStatus2, "%d%% charged", percent);
|
||||||
|
}
|
||||||
strcpy(CSStatus, "PC is running off of battery");
|
}
|
||||||
if (battery_time > 0)
|
break;
|
||||||
{
|
|
||||||
sprintf(CSStatus2, "Time remaining: %s", seconds_to_asc(battery_time));
|
case 1: //Not plugged in
|
||||||
}
|
{
|
||||||
if (percent > 0)
|
int percent = CheckBatteryPercent();
|
||||||
{
|
int battery_time = CheckBatteryTime();
|
||||||
sprintf(CSStatus3, "%d%% remaining", percent);
|
|
||||||
}
|
strcpy(CSStatus, "PC is running off of battery");
|
||||||
}
|
if (battery_time > 0)
|
||||||
break;
|
{
|
||||||
}
|
sprintf(CSStatus2, "Time remaining: %s", seconds_to_asc(battery_time));
|
||||||
|
}
|
||||||
Msgptr = CSStatus;
|
if (percent > 0)
|
||||||
MessageOn = 100;
|
{
|
||||||
|
sprintf(CSStatus3, "%d%% remaining", percent);
|
||||||
#endif
|
}
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Msgptr = CSStatus;
|
||||||
|
MessageOn = 100;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void MultiMouseShutdown()
|
||||||
|
{
|
||||||
|
multiMouseMode = 0;
|
||||||
|
ManyMouse_Quit();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make use of multiple mice.
|
||||||
|
|
||||||
|
int numMice = 0;
|
||||||
|
int Mouse1MoveX = 0;
|
||||||
|
int Mouse2MoveX = 0;
|
||||||
|
int Mouse1MoveY = 0;
|
||||||
|
int Mouse2MoveY = 0;
|
||||||
|
unsigned char MouseToRead = 0;
|
||||||
|
unsigned char multimouse = 1; // Enabled
|
||||||
|
|
||||||
|
extern void WriteLine();
|
||||||
|
|
||||||
|
void MultiMouseInit()
|
||||||
|
{
|
||||||
|
int mice = ManyMouse_Init();
|
||||||
|
printf("ManyMouse: %d mice detected.", mice);
|
||||||
|
multiMouseMode = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MultiMouseProcess()
|
||||||
|
{
|
||||||
|
ManyMouseEvent event;
|
||||||
|
|
||||||
|
ManyMouse_PollEvent(&event);
|
||||||
|
|
||||||
|
if (event.type == MANYMOUSE_EVENT_RELMOTION)
|
||||||
|
{
|
||||||
|
if (event.device == 0)
|
||||||
|
if (event.item == 0) { Mouse1MoveX = event.value; } else { Mouse1MoveY = event.value; }
|
||||||
|
else
|
||||||
|
if (event.item == 0) { Mouse2MoveX = event.value; } else { Mouse2MoveY = event.value; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
734
zsnes/src/windows_wminput.c
Normal file
734
zsnes/src/windows_wminput.c
Normal file
@@ -0,0 +1,734 @@
|
|||||||
|
/*
|
||||||
|
* Support for Windows via the WM_INPUT message.
|
||||||
|
*
|
||||||
|
* Please see the file LICENSE in the source's root directory.
|
||||||
|
*
|
||||||
|
* This file written by Ryan C. Gordon.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if (defined(_WIN32) || defined(__CYGWIN__))
|
||||||
|
|
||||||
|
/* WinUser.h won't include rawinput stuff without this... */
|
||||||
|
#if (_WIN32_WINNT < 0x0501)
|
||||||
|
#undef _WIN32_WINNT
|
||||||
|
#define _WIN32_WINNT 0x0501
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <malloc.h> /* needed for alloca(). */
|
||||||
|
|
||||||
|
/* Cygwin's headers don't have WM_INPUT right now... */
|
||||||
|
#ifndef WM_INPUT
|
||||||
|
#define WM_INPUT 0x00FF
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "manymouse.h"
|
||||||
|
|
||||||
|
/* that should be enough, knock on wood. */
|
||||||
|
#define MAX_MICE 32
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Just trying to avoid malloc() here...we statically allocate a buffer
|
||||||
|
* for events and treat it as a ring buffer.
|
||||||
|
*/
|
||||||
|
/* !!! FIXME: tweak this? */
|
||||||
|
#define MAX_EVENTS 1024
|
||||||
|
static ManyMouseEvent input_events[MAX_EVENTS];
|
||||||
|
static volatile int input_events_read = 0;
|
||||||
|
static volatile int input_events_write = 0;
|
||||||
|
static int available_mice = 0;
|
||||||
|
static int did_api_lookup = 0;
|
||||||
|
static HWND raw_hwnd = NULL;
|
||||||
|
static const char *class_name = "ManyMouseRawInputCatcher";
|
||||||
|
static const char *win_name = "ManyMouseRawInputMsgWindow";
|
||||||
|
static ATOM class_atom = 0;
|
||||||
|
static CRITICAL_SECTION mutex;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
HANDLE handle;
|
||||||
|
char name[256];
|
||||||
|
} MouseStruct;
|
||||||
|
static MouseStruct mice[MAX_MICE];
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The RawInput APIs only exist in Windows XP and later, so you want this
|
||||||
|
* to fail gracefully on earlier systems instead of refusing to start the
|
||||||
|
* process due to missing symbols. To this end, we do a symbol lookup on
|
||||||
|
* User32.dll, etc to get the entry points.
|
||||||
|
*
|
||||||
|
* A lot of these are available all the way back to the start of win32 in
|
||||||
|
* Windows 95 and WinNT 3.1, but just so you don't have to track down any
|
||||||
|
* import libraries, I've added those here, too. That fits well with the
|
||||||
|
* idea of just adding the sources to your build and going forward.
|
||||||
|
*/
|
||||||
|
static UINT (WINAPI *pGetRawInputDeviceList)(
|
||||||
|
PRAWINPUTDEVICELIST pRawInputDeviceList,
|
||||||
|
PUINT puiNumDevices,
|
||||||
|
UINT cbSize
|
||||||
|
);
|
||||||
|
/* !!! FIXME: use unicode version */
|
||||||
|
static UINT (WINAPI *pGetRawInputDeviceInfoA)(
|
||||||
|
HANDLE hDevice,
|
||||||
|
UINT uiCommand,
|
||||||
|
LPVOID pData,
|
||||||
|
PUINT pcbSize
|
||||||
|
);
|
||||||
|
static BOOL (WINAPI *pRegisterRawInputDevices)(
|
||||||
|
PCRAWINPUTDEVICE pRawInputDevices,
|
||||||
|
UINT uiNumDevices,
|
||||||
|
UINT cbSize
|
||||||
|
);
|
||||||
|
static LRESULT (WINAPI *pDefRawInputProc)(
|
||||||
|
PRAWINPUT *paRawInput,
|
||||||
|
INT nInput,
|
||||||
|
UINT cbSizeHeader
|
||||||
|
);
|
||||||
|
static UINT (WINAPI *pGetRawInputBuffer)(
|
||||||
|
PRAWINPUT pData,
|
||||||
|
PUINT pcbSize,
|
||||||
|
UINT cbSizeHeader
|
||||||
|
);
|
||||||
|
static UINT (WINAPI *pGetRawInputData)(
|
||||||
|
HRAWINPUT hRawInput,
|
||||||
|
UINT uiCommand,
|
||||||
|
LPVOID pData,
|
||||||
|
PUINT pcbSize,
|
||||||
|
UINT cbSizeHeader
|
||||||
|
);
|
||||||
|
static LONG (WINAPI *pRegQueryValueExA)(
|
||||||
|
HKEY hKey,
|
||||||
|
LPCTSTR lpValueName,
|
||||||
|
LPDWORD lpReserved,
|
||||||
|
LPDWORD lpType,
|
||||||
|
LPBYTE lpData,
|
||||||
|
LPDWORD lpcbData
|
||||||
|
);
|
||||||
|
static LONG (WINAPI *pRegOpenKeyExA)(
|
||||||
|
HKEY hKey,
|
||||||
|
LPCTSTR lpSubKey,
|
||||||
|
DWORD ulOptions,
|
||||||
|
REGSAM samDesired,
|
||||||
|
PHKEY phkResult
|
||||||
|
);
|
||||||
|
static LONG (WINAPI *pRegCloseKey)(
|
||||||
|
HKEY hKey
|
||||||
|
);
|
||||||
|
static HWND (WINAPI *pCreateWindowExA)(
|
||||||
|
DWORD dwExStyle,
|
||||||
|
LPCTSTR lpClassName,
|
||||||
|
LPCTSTR lpWindowName,
|
||||||
|
DWORD dwStyle,
|
||||||
|
int x,
|
||||||
|
int y,
|
||||||
|
int nWidth,
|
||||||
|
int nHeight,
|
||||||
|
HWND hWndParent,
|
||||||
|
HMENU hMenu,
|
||||||
|
HINSTANCE hInstance,
|
||||||
|
LPVOID lpParam
|
||||||
|
);
|
||||||
|
static ATOM (WINAPI *pRegisterClassExA)(
|
||||||
|
CONST WNDCLASSEX *lpwcx
|
||||||
|
);
|
||||||
|
static LRESULT (WINAPI *pDefWindowProcA)(
|
||||||
|
HWND hWnd,
|
||||||
|
UINT Msg,
|
||||||
|
WPARAM wParam,
|
||||||
|
LPARAM lParam
|
||||||
|
);
|
||||||
|
static BOOL (WINAPI *pUnregisterClassA)(
|
||||||
|
LPCTSTR lpClassName,
|
||||||
|
HINSTANCE hInstance
|
||||||
|
);
|
||||||
|
static HMODULE (WINAPI *pGetModuleHandleA)(
|
||||||
|
LPCTSTR lpModuleName
|
||||||
|
);
|
||||||
|
static BOOL (WINAPI *pPeekMessageA)(
|
||||||
|
LPMSG lpMsg,
|
||||||
|
HWND hWnd,
|
||||||
|
UINT wMsgFilterMin,
|
||||||
|
UINT wMsgFilterMax,
|
||||||
|
UINT wRemoveMsg
|
||||||
|
);
|
||||||
|
static BOOL (WINAPI *pTranslateMessage)(
|
||||||
|
const MSG *lpMsg
|
||||||
|
);
|
||||||
|
static LRESULT (WINAPI *pDispatchMessageA)(
|
||||||
|
const MSG *lpmsg
|
||||||
|
);
|
||||||
|
static BOOL (WINAPI *pDestroyWindow)(
|
||||||
|
HWND hWnd
|
||||||
|
);
|
||||||
|
static void (WINAPI *pInitializeCriticalSection)(
|
||||||
|
LPCRITICAL_SECTION lpCriticalSection
|
||||||
|
);
|
||||||
|
static void (WINAPI *pEnterCriticalSection)(
|
||||||
|
LPCRITICAL_SECTION lpCriticalSection
|
||||||
|
);
|
||||||
|
static void (WINAPI *pLeaveCriticalSection)(
|
||||||
|
LPCRITICAL_SECTION lpCriticalSection
|
||||||
|
);
|
||||||
|
static void (WINAPI *pDeleteCriticalSection)(
|
||||||
|
LPCRITICAL_SECTION lpCriticalSection
|
||||||
|
);
|
||||||
|
|
||||||
|
static int symlookup(HMODULE dll, void **addr, const char *sym)
|
||||||
|
{
|
||||||
|
*addr = GetProcAddress(dll, sym);
|
||||||
|
if (*addr == NULL)
|
||||||
|
{
|
||||||
|
FreeLibrary(dll);
|
||||||
|
return(0);
|
||||||
|
} /* if */
|
||||||
|
|
||||||
|
return(1);
|
||||||
|
} /* symlookup */
|
||||||
|
|
||||||
|
static int find_api_symbols(void)
|
||||||
|
{
|
||||||
|
HMODULE dll;
|
||||||
|
|
||||||
|
if (did_api_lookup)
|
||||||
|
return(1);
|
||||||
|
|
||||||
|
#define LOOKUP(x) { if (!symlookup(dll, (void **) &p##x, #x)) return(0); }
|
||||||
|
dll = LoadLibrary("user32.dll");
|
||||||
|
if (dll == NULL)
|
||||||
|
return(0);
|
||||||
|
|
||||||
|
LOOKUP(GetRawInputDeviceInfoA);
|
||||||
|
LOOKUP(RegisterRawInputDevices);
|
||||||
|
LOOKUP(GetRawInputDeviceList);
|
||||||
|
LOOKUP(DefRawInputProc);
|
||||||
|
LOOKUP(GetRawInputBuffer);
|
||||||
|
LOOKUP(GetRawInputData);
|
||||||
|
LOOKUP(CreateWindowExA);
|
||||||
|
LOOKUP(RegisterClassExA);
|
||||||
|
LOOKUP(UnregisterClassA);
|
||||||
|
LOOKUP(DefWindowProcA);
|
||||||
|
LOOKUP(PeekMessageA);
|
||||||
|
LOOKUP(TranslateMessage);
|
||||||
|
LOOKUP(DispatchMessageA);
|
||||||
|
LOOKUP(DestroyWindow);
|
||||||
|
|
||||||
|
dll = LoadLibrary("advapi32.dll");
|
||||||
|
if (dll == NULL)
|
||||||
|
return(0);
|
||||||
|
|
||||||
|
LOOKUP(RegOpenKeyExA);
|
||||||
|
LOOKUP(RegQueryValueExA);
|
||||||
|
LOOKUP(RegCloseKey);
|
||||||
|
|
||||||
|
dll = LoadLibrary("kernel32.dll");
|
||||||
|
if (dll == NULL)
|
||||||
|
return(0);
|
||||||
|
|
||||||
|
LOOKUP(GetModuleHandleA);
|
||||||
|
LOOKUP(InitializeCriticalSection);
|
||||||
|
LOOKUP(EnterCriticalSection);
|
||||||
|
LOOKUP(LeaveCriticalSection);
|
||||||
|
LOOKUP(DeleteCriticalSection);
|
||||||
|
|
||||||
|
#undef LOOKUP
|
||||||
|
|
||||||
|
did_api_lookup = 1;
|
||||||
|
return(1);
|
||||||
|
} /* find_api_symbols */
|
||||||
|
|
||||||
|
|
||||||
|
static void queue_event(const ManyMouseEvent *event)
|
||||||
|
{
|
||||||
|
/* copy the event info. We'll process it in ManyMouse_PollEvent(). */
|
||||||
|
CopyMemory(&input_events[input_events_write], event, sizeof (ManyMouseEvent));
|
||||||
|
|
||||||
|
input_events_write = ((input_events_write + 1) % MAX_EVENTS);
|
||||||
|
|
||||||
|
/* Ring buffer full? Lose oldest event. */
|
||||||
|
if (input_events_write == input_events_read)
|
||||||
|
{
|
||||||
|
/* !!! FIXME: we need to not lose mouse buttons here. */
|
||||||
|
input_events_read = ((input_events_read + 1) % MAX_EVENTS);
|
||||||
|
} /* if */
|
||||||
|
} /* queue_event */
|
||||||
|
|
||||||
|
|
||||||
|
static void queue_from_rawinput(const RAWINPUT *raw)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
const RAWINPUTHEADER *header = &raw->header;
|
||||||
|
const RAWMOUSE *mouse = &raw->data.mouse;
|
||||||
|
ManyMouseEvent event;
|
||||||
|
|
||||||
|
if (raw->header.dwType != RIM_TYPEMOUSE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i = 0; i < available_mice; i++) /* find the device for event. */
|
||||||
|
{
|
||||||
|
if (mice[i].handle == header->hDevice)
|
||||||
|
break;
|
||||||
|
} /* for */
|
||||||
|
|
||||||
|
if (i == available_mice)
|
||||||
|
return; /* not found?! */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* RAWINPUT packs a bunch of events into one, so we split it up into
|
||||||
|
* a bunch of ManyMouseEvents here and store them in an internal queue.
|
||||||
|
* Then ManyMouse_PollEvent() just shuffles items off that queue
|
||||||
|
* without any complicated processing.
|
||||||
|
*/
|
||||||
|
|
||||||
|
event.device = i;
|
||||||
|
|
||||||
|
pEnterCriticalSection(&mutex);
|
||||||
|
|
||||||
|
if (mouse->usFlags & MOUSE_MOVE_ABSOLUTE)
|
||||||
|
{
|
||||||
|
/* !!! FIXME: How do we get the min and max values for absmotion? */
|
||||||
|
event.type = MANYMOUSE_EVENT_ABSMOTION;
|
||||||
|
event.item = 0;
|
||||||
|
event.value = mouse->lLastX;
|
||||||
|
queue_event(&event);
|
||||||
|
event.item = 1;
|
||||||
|
event.value = mouse->lLastY;
|
||||||
|
queue_event(&event);
|
||||||
|
} /* if */
|
||||||
|
|
||||||
|
else /*if (mouse->usFlags & MOUSE_MOVE_RELATIVE)*/
|
||||||
|
{
|
||||||
|
event.type = MANYMOUSE_EVENT_RELMOTION;
|
||||||
|
if (mouse->lLastX != 0)
|
||||||
|
{
|
||||||
|
event.item = 0;
|
||||||
|
event.value = mouse->lLastX;
|
||||||
|
queue_event(&event);
|
||||||
|
} /* if */
|
||||||
|
|
||||||
|
if (mouse->lLastY != 0)
|
||||||
|
{
|
||||||
|
event.item = 1;
|
||||||
|
event.value = mouse->lLastY;
|
||||||
|
queue_event(&event);
|
||||||
|
} /* if */
|
||||||
|
} /* else if */
|
||||||
|
|
||||||
|
event.type = MANYMOUSE_EVENT_BUTTON;
|
||||||
|
|
||||||
|
#define QUEUE_BUTTON(x) { \
|
||||||
|
if (mouse->usButtonFlags & RI_MOUSE_BUTTON_##x##_DOWN) { \
|
||||||
|
event.item = x-1; \
|
||||||
|
event.value = 1; \
|
||||||
|
queue_event(&event); \
|
||||||
|
} \
|
||||||
|
if (mouse->usButtonFlags & RI_MOUSE_BUTTON_##x##_UP) { \
|
||||||
|
event.item = x-1; \
|
||||||
|
event.value = 0; \
|
||||||
|
queue_event(&event); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
QUEUE_BUTTON(1);
|
||||||
|
QUEUE_BUTTON(2);
|
||||||
|
QUEUE_BUTTON(3);
|
||||||
|
QUEUE_BUTTON(4);
|
||||||
|
QUEUE_BUTTON(5);
|
||||||
|
|
||||||
|
#undef QUEUE_BUTTON
|
||||||
|
|
||||||
|
if (mouse->usButtonFlags & RI_MOUSE_WHEEL)
|
||||||
|
{
|
||||||
|
if (mouse->usButtonData != 0) /* !!! FIXME: can this ever be zero? */
|
||||||
|
{
|
||||||
|
event.type = MANYMOUSE_EVENT_SCROLL;
|
||||||
|
event.item = 0; /* !!! FIXME: horizontal wheel? */
|
||||||
|
event.value = (mouse->usButtonData > 0) ? 1 : -1;
|
||||||
|
queue_event(&event);
|
||||||
|
} /* if */
|
||||||
|
} /* if */
|
||||||
|
|
||||||
|
pLeaveCriticalSection(&mutex);
|
||||||
|
} /* queue_from_rawinput */
|
||||||
|
|
||||||
|
|
||||||
|
static void wminput_handler(WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
UINT dwSize = 0;
|
||||||
|
LPBYTE lpb;
|
||||||
|
|
||||||
|
pGetRawInputData((HRAWINPUT) lParam, RID_INPUT, NULL, &dwSize,
|
||||||
|
sizeof (RAWINPUTHEADER));
|
||||||
|
|
||||||
|
if (dwSize < sizeof (RAWINPUT))
|
||||||
|
return; /* unexpected packet? */
|
||||||
|
|
||||||
|
lpb = (LPBYTE) alloca(dwSize);
|
||||||
|
if (lpb == NULL)
|
||||||
|
return;
|
||||||
|
if (pGetRawInputData((HRAWINPUT) lParam, RID_INPUT, lpb, &dwSize,
|
||||||
|
sizeof (RAWINPUTHEADER)) != dwSize)
|
||||||
|
return;
|
||||||
|
|
||||||
|
queue_from_rawinput((RAWINPUT *) lpb);
|
||||||
|
} /* wminput_handler */
|
||||||
|
|
||||||
|
|
||||||
|
static LRESULT CALLBACK RawWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
if (Msg == WM_INPUT)
|
||||||
|
wminput_handler(wParam, lParam);
|
||||||
|
|
||||||
|
else if (Msg == WM_DESTROY)
|
||||||
|
return(0);
|
||||||
|
|
||||||
|
return pDefWindowProcA(hWnd, Msg, wParam, lParam);
|
||||||
|
} /* RawWndProc */
|
||||||
|
|
||||||
|
|
||||||
|
static int init_event_queue(void)
|
||||||
|
{
|
||||||
|
HINSTANCE hInstance = pGetModuleHandleA(NULL);
|
||||||
|
WNDCLASSEX wce;
|
||||||
|
RAWINPUTDEVICE rid;
|
||||||
|
|
||||||
|
ZeroMemory(input_events, sizeof (input_events));
|
||||||
|
input_events_read = input_events_write = 0;
|
||||||
|
|
||||||
|
ZeroMemory(&wce, sizeof (wce));
|
||||||
|
wce.cbSize = sizeof(WNDCLASSEX);
|
||||||
|
wce.lpfnWndProc = RawWndProc;
|
||||||
|
wce.lpszClassName = class_name;
|
||||||
|
wce.hInstance = hInstance;
|
||||||
|
class_atom = pRegisterClassExA(&wce);
|
||||||
|
if (class_atom == 0)
|
||||||
|
return(0);
|
||||||
|
|
||||||
|
raw_hwnd = pCreateWindowExA(0, class_name, win_name, WS_OVERLAPPEDWINDOW,
|
||||||
|
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
|
||||||
|
CW_USEDEFAULT, HWND_MESSAGE, NULL, hInstance, NULL);
|
||||||
|
|
||||||
|
if (raw_hwnd == NULL)
|
||||||
|
return(0);
|
||||||
|
|
||||||
|
pInitializeCriticalSection(&mutex);
|
||||||
|
|
||||||
|
ZeroMemory(&rid, sizeof (rid));
|
||||||
|
rid.usUsagePage = 1; /* GenericDesktop page */
|
||||||
|
rid.usUsage = 2; /* GeneralDestop Mouse usage. */
|
||||||
|
rid.dwFlags = RIDEV_INPUTSINK;
|
||||||
|
rid.hwndTarget = raw_hwnd;
|
||||||
|
if (!pRegisterRawInputDevices(&rid, 1, sizeof (rid)))
|
||||||
|
{
|
||||||
|
pDeleteCriticalSection(&mutex);
|
||||||
|
return(0);
|
||||||
|
} /* if */
|
||||||
|
|
||||||
|
return(1);
|
||||||
|
} /* init_event_queue */
|
||||||
|
|
||||||
|
|
||||||
|
static void cleanup_window(void)
|
||||||
|
{
|
||||||
|
if (raw_hwnd)
|
||||||
|
{
|
||||||
|
MSG Msg;
|
||||||
|
pDestroyWindow(raw_hwnd);
|
||||||
|
while (pPeekMessageA(&Msg, raw_hwnd, 0, 0, PM_REMOVE))
|
||||||
|
{
|
||||||
|
pTranslateMessage(&Msg);
|
||||||
|
pDispatchMessageA(&Msg);
|
||||||
|
} /* while */
|
||||||
|
raw_hwnd = 0;
|
||||||
|
} /* if */
|
||||||
|
|
||||||
|
if (class_atom)
|
||||||
|
{
|
||||||
|
pUnregisterClassA(class_name, pGetModuleHandleA(NULL));
|
||||||
|
class_atom = 0;
|
||||||
|
} /* if */
|
||||||
|
} /* cleanup_window */
|
||||||
|
|
||||||
|
|
||||||
|
static int accept_device(const RAWINPUTDEVICELIST *dev)
|
||||||
|
{
|
||||||
|
const char rdp_ident[] = "\\??\\Root#RDP_MOU#0000#";
|
||||||
|
char *buf = NULL;
|
||||||
|
UINT ct = 0;
|
||||||
|
|
||||||
|
if (dev->dwType != RIM_TYPEMOUSE)
|
||||||
|
return(0); /* keyboard or some other fruity thing. */
|
||||||
|
|
||||||
|
if (pGetRawInputDeviceInfoA(dev->hDevice, RIDI_DEVICENAME, NULL, &ct) < 0)
|
||||||
|
return(0);
|
||||||
|
|
||||||
|
/* ct == is chars, not bytes, but we used the ASCII version. */
|
||||||
|
buf = (char *) alloca(ct);
|
||||||
|
if (buf == NULL)
|
||||||
|
return(0);
|
||||||
|
|
||||||
|
if (pGetRawInputDeviceInfoA(dev->hDevice, RIDI_DEVICENAME, buf, &ct) < 0)
|
||||||
|
return(0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Apparently there's a fake "RDP" device...I guess this is
|
||||||
|
* "Remote Desktop Protocol" for controlling the system pointer
|
||||||
|
* remotely via Windows Remote Desktop, but that's just a guess.
|
||||||
|
* At any rate, we don't want that device, so skip it if detected.
|
||||||
|
*
|
||||||
|
* Idea for this found here:
|
||||||
|
* http://link.mywwwserver.com/~jstookey/arcade/rawmouse/raw_mouse.c
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* avoiding memcmp here so we don't get a C runtime dependency... */
|
||||||
|
if (ct >= sizeof (rdp_ident) - 1)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < sizeof (rdp_ident) - 1; i++)
|
||||||
|
{
|
||||||
|
if (buf[i] != rdp_ident[i])
|
||||||
|
break;
|
||||||
|
} /* for */
|
||||||
|
|
||||||
|
if (i == sizeof (rdp_ident) - 1)
|
||||||
|
return(0); /* this is an RDP thing. Skip this device. */
|
||||||
|
} /* if */
|
||||||
|
|
||||||
|
return(1); /* we want this device. */
|
||||||
|
} /* accept_device */
|
||||||
|
|
||||||
|
|
||||||
|
/* !!! FIXME: this code sucks. */
|
||||||
|
static void get_device_product_name(char *name, size_t namesize,
|
||||||
|
const RAWINPUTDEVICELIST *dev)
|
||||||
|
{
|
||||||
|
const char regkeyroot[] = "System\\CurrentControlSet\\Enum\\";
|
||||||
|
const char default_device_name[] = "Unidentified input device";
|
||||||
|
DWORD outsize = namesize;
|
||||||
|
DWORD regtype = REG_SZ;
|
||||||
|
char *buf = NULL;
|
||||||
|
char *ptr = NULL;
|
||||||
|
char *keyname = NULL;
|
||||||
|
UINT i = 0;
|
||||||
|
UINT ct = 0;
|
||||||
|
LONG rc = 0;
|
||||||
|
HKEY hkey;
|
||||||
|
|
||||||
|
*name = '\0'; /* really insane default. */
|
||||||
|
if (sizeof (default_device_name) >= namesize)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* in case we can't stumble upon something better... */
|
||||||
|
CopyMemory(name, default_device_name, sizeof (default_device_name));
|
||||||
|
|
||||||
|
if (pGetRawInputDeviceInfoA(dev->hDevice, RIDI_DEVICENAME, NULL, &ct) < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* ct == is chars, not bytes, but we used the ASCII version. */
|
||||||
|
buf = (char *) alloca(ct+1);
|
||||||
|
keyname = (char *) alloca(ct + sizeof (regkeyroot));
|
||||||
|
if ((buf == NULL) || (keyname == NULL))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (pGetRawInputDeviceInfoA(dev->hDevice, RIDI_DEVICENAME, buf, &ct) < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This string tap dancing gets us a registry keyname in this form:
|
||||||
|
* SYSTEM\CurrentControlSet\Enum\BUSTYPE\DEVICECLASS\DEVICEID
|
||||||
|
* (those are my best-guess for the actual elements, but the format
|
||||||
|
* appears to be sound.)
|
||||||
|
*/
|
||||||
|
ct -= 4;
|
||||||
|
buf += 4; /* skip the "\\??\\" on the front of the string. */
|
||||||
|
for (i = 0, ptr = buf; i < ct; i++, ptr++) /* convert '#' to '\\' ... */
|
||||||
|
{
|
||||||
|
if (*ptr == '#')
|
||||||
|
*ptr = '\\';
|
||||||
|
else if (*ptr == '{') /* hit the GUID part of the string. */
|
||||||
|
break;
|
||||||
|
} /* for */
|
||||||
|
|
||||||
|
*ptr = '\0';
|
||||||
|
CopyMemory(keyname, regkeyroot, sizeof (regkeyroot) - 1);
|
||||||
|
CopyMemory(keyname + (sizeof (regkeyroot) - 1), buf, i + 1);
|
||||||
|
rc = pRegOpenKeyExA(HKEY_LOCAL_MACHINE, keyname, 0, KEY_READ, &hkey);
|
||||||
|
if (rc != ERROR_SUCCESS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
rc = pRegQueryValueExA(hkey, "DeviceDesc", NULL, ®type, name, &outsize);
|
||||||
|
pRegCloseKey(hkey);
|
||||||
|
if (rc != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
/* msdn says failure may mangle the buffer, so default it again. */
|
||||||
|
CopyMemory(name, default_device_name, sizeof (default_device_name));
|
||||||
|
return;
|
||||||
|
} /* if */
|
||||||
|
name[namesize-1] = '\0'; /* just in case. */
|
||||||
|
} /* get_device_product_name */
|
||||||
|
|
||||||
|
|
||||||
|
static void init_mouse(const RAWINPUTDEVICELIST *dev)
|
||||||
|
{
|
||||||
|
MouseStruct *mouse = &mice[available_mice];
|
||||||
|
|
||||||
|
if (accept_device(dev))
|
||||||
|
{
|
||||||
|
ZeroMemory(mouse, sizeof (MouseStruct));
|
||||||
|
get_device_product_name(mouse->name, sizeof (mouse->name), dev);
|
||||||
|
mouse->handle = dev->hDevice;
|
||||||
|
available_mice++; /* we're good. */
|
||||||
|
} /* if */
|
||||||
|
} /* init_mouse */
|
||||||
|
|
||||||
|
|
||||||
|
static int windows_wminput_init(void)
|
||||||
|
{
|
||||||
|
RAWINPUTDEVICELIST *devlist = NULL;
|
||||||
|
UINT ct = 0;
|
||||||
|
UINT i;
|
||||||
|
|
||||||
|
available_mice = 0;
|
||||||
|
|
||||||
|
if (!find_api_symbols()) /* only supported on WinXP and later. */
|
||||||
|
return(0);
|
||||||
|
|
||||||
|
pGetRawInputDeviceList(NULL, &ct, sizeof (RAWINPUTDEVICELIST));
|
||||||
|
if (ct == 0) /* no devices. */
|
||||||
|
return(0);
|
||||||
|
|
||||||
|
devlist = (PRAWINPUTDEVICELIST) alloca(sizeof (RAWINPUTDEVICELIST) * ct);
|
||||||
|
pGetRawInputDeviceList(devlist, &ct, sizeof (RAWINPUTDEVICELIST));
|
||||||
|
for (i = 0; i < ct; i++)
|
||||||
|
init_mouse(&devlist[i]);
|
||||||
|
|
||||||
|
if (!init_event_queue())
|
||||||
|
{
|
||||||
|
cleanup_window();
|
||||||
|
available_mice = 0;
|
||||||
|
} /* if */
|
||||||
|
|
||||||
|
return(available_mice);
|
||||||
|
} /* windows_wminput_init */
|
||||||
|
|
||||||
|
|
||||||
|
static void windows_wminput_quit(void)
|
||||||
|
{
|
||||||
|
/* unregister WM_INPUT devices... */
|
||||||
|
RAWINPUTDEVICE rid;
|
||||||
|
ZeroMemory(&rid, sizeof (rid));
|
||||||
|
rid.usUsagePage = 1; /* GenericDesktop page */
|
||||||
|
rid.usUsage = 2; /* GeneralDestop Mouse usage. */
|
||||||
|
rid.dwFlags |= RIDEV_REMOVE;
|
||||||
|
pRegisterRawInputDevices(&rid, 1, sizeof (rid));
|
||||||
|
cleanup_window();
|
||||||
|
available_mice = 0;
|
||||||
|
pDeleteCriticalSection(&mutex);
|
||||||
|
} /* windows_wminput_quit */
|
||||||
|
|
||||||
|
|
||||||
|
static const char *windows_wminput_name(unsigned int index)
|
||||||
|
{
|
||||||
|
if (index < available_mice)
|
||||||
|
return(mice[index].name);
|
||||||
|
return(NULL);
|
||||||
|
} /* windows_wminput_name */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Windows doesn't send a WM_INPUT event when you unplug a mouse,
|
||||||
|
* so we try to do a basic query by device handle here; if the
|
||||||
|
* query fails, we assume the device has vanished and generate a
|
||||||
|
* disconnect.
|
||||||
|
*/
|
||||||
|
static int check_for_disconnects(ManyMouseEvent *ev)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* (i) is static so we iterate through all mice round-robin and check
|
||||||
|
* one mouse per call to ManyMouse_PollEvent(). This makes this test O(1).
|
||||||
|
*/
|
||||||
|
static unsigned int i = 0;
|
||||||
|
MouseStruct *mouse = NULL;
|
||||||
|
|
||||||
|
if (++i >= available_mice) /* check first in case of redetect */
|
||||||
|
i = 0;
|
||||||
|
|
||||||
|
mouse = &mice[i];
|
||||||
|
if (mouse->handle != NULL) /* not NULL == still plugged in. */
|
||||||
|
{
|
||||||
|
UINT size = 0;
|
||||||
|
UINT rc = pGetRawInputDeviceInfoA(mouse->handle, RIDI_DEVICEINFO,
|
||||||
|
NULL, &size);
|
||||||
|
if (rc == (UINT) -1) /* failed...probably unplugged... */
|
||||||
|
{
|
||||||
|
mouse->handle = NULL;
|
||||||
|
ev->type = MANYMOUSE_EVENT_DISCONNECT;
|
||||||
|
ev->device = i;
|
||||||
|
return(1);
|
||||||
|
} /* if */
|
||||||
|
} /* if */
|
||||||
|
|
||||||
|
return(0); /* no disconnect event this time. */
|
||||||
|
} /* check_for_disconnects */
|
||||||
|
|
||||||
|
|
||||||
|
static int windows_wminput_poll(ManyMouseEvent *ev)
|
||||||
|
{
|
||||||
|
MSG Msg; /* run the queue for WM_INPUT messages, etc ... */
|
||||||
|
int found = 0;
|
||||||
|
|
||||||
|
/* ...favor existing events in the queue... */
|
||||||
|
pEnterCriticalSection(&mutex);
|
||||||
|
if (input_events_read != input_events_write) /* no events if equal. */
|
||||||
|
{
|
||||||
|
CopyMemory(ev, &input_events[input_events_read], sizeof (*ev));
|
||||||
|
input_events_read = ((input_events_read + 1) % MAX_EVENTS);
|
||||||
|
found = 1;
|
||||||
|
} /* if */
|
||||||
|
pLeaveCriticalSection(&mutex);
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
/* pump Windows for new hardware events... */
|
||||||
|
while (pPeekMessageA(&Msg, raw_hwnd, 0, 0, PM_REMOVE))
|
||||||
|
{
|
||||||
|
pTranslateMessage(&Msg);
|
||||||
|
pDispatchMessageA(&Msg);
|
||||||
|
} /* while */
|
||||||
|
|
||||||
|
/* In case something new came in, give it to the app... */
|
||||||
|
pEnterCriticalSection(&mutex);
|
||||||
|
if (input_events_read != input_events_write) /* no events if equal. */
|
||||||
|
{
|
||||||
|
CopyMemory(ev, &input_events[input_events_read], sizeof (*ev));
|
||||||
|
input_events_read = ((input_events_read + 1) % MAX_EVENTS);
|
||||||
|
found = 1;
|
||||||
|
} /* if */
|
||||||
|
pLeaveCriticalSection(&mutex);
|
||||||
|
} /* if */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check for disconnects if queue is totally empty and Windows didn't
|
||||||
|
* report anything new at this time. This ensures that we don't send a
|
||||||
|
* disconnect event through ManyMouse and then later give a valid
|
||||||
|
* event to the app for a device that is now missing.
|
||||||
|
*/
|
||||||
|
if (!found)
|
||||||
|
found = check_for_disconnects(ev);
|
||||||
|
|
||||||
|
return(found);
|
||||||
|
} /* windows_wminput_poll */
|
||||||
|
|
||||||
|
|
||||||
|
ManyMouseDriver ManyMouseDriver_windows =
|
||||||
|
{
|
||||||
|
windows_wminput_init,
|
||||||
|
windows_wminput_quit,
|
||||||
|
windows_wminput_name,
|
||||||
|
windows_wminput_poll
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* ifdef WINDOWS blocker */
|
||||||
|
|
||||||
|
/* end of windows_wminput.c ... */
|
||||||
|
|
||||||
Reference in New Issue
Block a user