Import of ManyMouse library

This commit is contained in:
pagefault
2006-03-23 20:45:51 +00:00
parent 2219632c9e
commit 29637130ff
8 changed files with 7745 additions and 6439 deletions

View File

@@ -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

File diff suppressed because it is too large Load Diff

337
zsnes/src/linux_evdev.c Normal file
View 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
View 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
View 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 ... */

View File

@@ -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
View 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, &regtype, 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 ... */