Relative mouse motion interface for SNES and Subor mouse; this allows fullscreen mode to keep the mouse fixed in the centre of the screen, permitting infinite motion.

This commit is contained in:
rainwarrior 2016-08-25 07:24:08 +00:00
parent 89a75e28fc
commit b632b1d7a5
6 changed files with 128 additions and 42 deletions

View File

@ -894,10 +894,6 @@ GetMouseData (uint32 (&d)[3])
int x, y;
uint32 t;
// Don't get input when a movie is playing back
if (FCEUMOV_Mode (MOVIEMODE_PLAY))
return;
// retrieve the state of the mouse from SDL
t = SDL_GetMouseState (&x, &y);
#ifdef _GTK
@ -934,6 +930,35 @@ GetMouseData (uint32 (&d)[3])
// printf("mouse %d %d %d\n", d[0], d[1], d[2]);
}
void GetMouseRelative (int32 (&d)[3])
{
// converts absolute mouse positions to relative ones for input devices that require this
// The windows version additionally in fullscreen will constantly return the mouse to center screen
// after reading it, so that the user can endlessly keep moving the mouse.
// The same should eventually be implemented here, but this version should minimally provide
// the necessary relative input, piggybacking on the already implemented GetMouseData.
static int cx = -1;
static int cy = -1;
uint32 md[3];
GetMouseData (md);
if (cx < 0 || cy < 0)
{
cx = md[0];
cy = md[1];
}
int dx = md[0] - cx;
int dy = md[1] - cy;
d[0] = dx;
d[1] = dy;
d[2] = md[2]; // buttons
}
/**
* Handles outstanding SDL events.
*/
@ -1259,6 +1284,7 @@ UpdatePPadData (int w)
}
static uint32 MouseData[3] = { 0, 0, 0 };
static int32 MouseRelative[3] = { 0, 0, 0 };
static uint8 fkbkeys[0x48];
@ -1293,7 +1319,7 @@ void FCEUD_UpdateInput ()
break;
case SI_MOUSE:
case SI_SNES_MOUSE:
t |= 2;
t |= 4;
break;
}
}
@ -1338,9 +1364,17 @@ void FCEUD_UpdateInput ()
UpdateGamepad ();
}
if (t & 2)
// Don't get input when a movie is playing back
if (!FCEUMOV_Mode (MOVIEMODE_PLAY))
{
GetMouseData (MouseData);
if (t & 2)
{
GetMouseData (MouseData);
}
if (t & 4)
{
GetMouseRelative (MouseRelative);
}
}
}
@ -1405,7 +1439,7 @@ void InitInputInterface ()
break;
case SI_MOUSE:
case SI_SNES_MOUSE:
InputDPtr = MouseData;
InputDPtr = MouseRelative;
t |= 1;
break;
}

View File

@ -69,6 +69,7 @@ static void PresetExport(int preset);
static void PresetImport(int preset);
static uint32 MouseData[3];
static int32 MouseRelative[3];
//force the input types suggested by the game
void ParseGIInput(FCEUGI *gi)
@ -418,7 +419,9 @@ void UpdateRawInputAndHotkeys()
void FCEUD_UpdateInput()
{
bool joy=false,mouse=false;
bool joy=false;
bool mouse=false;
bool mouse_relative=false;
EMOVIEMODE FCEUMOVState = FCEUMOV_Mode();
UpdateRawInputAndHotkeys();
@ -431,8 +434,8 @@ void FCEUD_UpdateInput()
case SI_SNES:
UpdateGamepad(true);
break;
case SI_MOUSE: mouse=true; break;
case SI_SNES_MOUSE: mouse=true; break;
case SI_MOUSE: mouse_relative=true; break;
case SI_SNES_MOUSE: mouse_relative=true; break;
case SI_ARKANOID: mouse=true; break;
case SI_ZAPPER: mouse=true; break;
case SI_POWERPADA:
@ -466,9 +469,11 @@ void FCEUD_UpdateInput()
if(joy)
UpdateGamepad(false);
if(mouse)
if(FCEUMOVState != MOVIEMODE_PLAY) //FatRatKnight: Moved this if out of the function
GetMouseData(MouseData); //A more concise fix may be desired.
if (FCEUMOVState != MOVIEMODE_PLAY) //FatRatKnight: Moved this if out of the function, a more concise fix may be desired.
{
if (mouse) GetMouseData(MouseData);
if (mouse_relative) GetMouseRelative(MouseRelative);
}
}
}
@ -518,10 +523,10 @@ void InitInputPorts(bool fourscore)
InputDPtr=MouseData;
break;
case SI_MOUSE:
InputDPtr=MouseData;
InputDPtr=MouseRelative;
break;
case SI_SNES_MOUSE:
InputDPtr=MouseData;
InputDPtr=MouseRelative;
break;
case SI_SNES:
InputDPtr=snespad_return;

View File

@ -1200,6 +1200,46 @@ void GetMouseData(uint32 (&md)[3])
md[2] = ((mouseb == MK_LBUTTON) ? 1 : 0) | (( mouseb == MK_RBUTTON ) ? 2 : 0);
}
void GetMouseRelative(int32 (&md)[3])
{
static int cx = -1;
static int cy = -1;
int dx = 0;
int dy = 0;
bool constrain = (fullscreen != 0) && (nofocus == 0);
if (constrain || cx < 0 || cy < 0)
{
RECT window;
GetWindowRect(hAppWnd, &window);
cx = (window.left + window.right) / 2;
cy = (window.top + window.bottom) / 2;
}
POINT cursor;
if (GetCursorPos(&cursor))
{
dx = cursor.x - cx;
dy = cursor.y - cy;
if (constrain)
{
SetCursorPos(cx,cy);
}
else
{
cx = cursor.x;
cy = cursor.y;
}
}
md[0] = dx;
md[1] = dy;
md[2] = ((mouseb == MK_LBUTTON) ? 1 : 0) | (( mouseb == MK_RBUTTON ) ? 2 : 0);
}
void DumpSubtitles(HWND hWnd)
{
const char filter[]="Subtitles files (*.srt)\0*.srt\0All Files (*.*)\0*.*\0\0";
@ -2338,8 +2378,8 @@ LRESULT FAR PASCAL AppWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
break;
}
if(wParam==VK_F10)
break; // 11.12.08 CH4 Disable F10 as System Key dammit
if(wParam==VK_F10)
break; // 11.12.08 CH4 Disable F10 as System Key dammit
/*
if(wParam == VK_RETURN)
{

View File

@ -36,6 +36,7 @@ void LoadNewGamey(HWND hParent, const char *initialdir);
int BrowseForFolder(HWND hParent, const char *htext, char *buf);
void SetMainWindowStuff();
void GetMouseData(uint32 (&md)[3]);
void GetMouseRelative(int32 (&md)[3]);
//void ChangeMenuItemText(int menuitem, string text);
void UpdateMenuHotkeys();

View File

@ -27,27 +27,28 @@
typedef struct {
uint8 latch;
int32 mx,my;
int32 lmx,lmy;
int32 dx,dy;
uint32 mb;
} MOUSE;
static MOUSE Mouse;
// since this game only picks up 1 mickey per frame,
// allow a single delta to spread out over a few frames
// to make it easier to move.
const int INERTIA = 32;
static void StrobeMOUSE(int w)
{
Mouse.latch = Mouse.mb & 0x03;
int32 dx = Mouse.mx - Mouse.lmx;
int32 dy = Mouse.my - Mouse.lmy;
int32 dx = Mouse.dx;
int32 dy = Mouse.dy;
Mouse.lmx = Mouse.mx;
Mouse.lmy = Mouse.my;
if (dx > 0) Mouse.latch |= (0x2 << 2);
else if (dx < 0) Mouse.latch |= (0x3 << 2);
if (dy > 0) Mouse.latch |= (0x2 << 4);
else if (dy < 0) Mouse.latch |= (0x3 << 4);
if (dx > 0) { Mouse.latch |= (0x2 << 2); --Mouse.dx; }
else if (dx < 0) { Mouse.latch |= (0x3 << 2); ++Mouse.dx; }
if (dy > 0) { Mouse.latch |= (0x2 << 4); --Mouse.dy; }
else if (dy < 0) { Mouse.latch |= (0x3 << 4); ++Mouse.dy; }
//FCEU_printf("Subor Mouse: %02X\n",Mouse.latch);
}
@ -62,9 +63,15 @@ static uint8 ReadMOUSE(int w)
static void UpdateMOUSE(int w, void *data, int arg)
{
uint32 *ptr=(uint32*)data;
Mouse.mx = ptr[0];
Mouse.my = ptr[1];
Mouse.dx += ptr[0]; ptr[0] = 0;
Mouse.dy += ptr[1]; ptr[1] = 0;
Mouse.mb = ptr[2];
if (Mouse.dx > INERTIA) Mouse.dx = INERTIA;
else if (Mouse.dx < -INERTIA) Mouse.dx = -INERTIA;
if (Mouse.dy > INERTIA) Mouse.dy = INERTIA;
else if (Mouse.dy < -INERTIA) Mouse.dy = -INERTIA;
}
static INPUTC MOUSEC={ReadMOUSE,0,StrobeMOUSE,UpdateMOUSE,0,0};

View File

@ -26,9 +26,8 @@ typedef struct {
bool strobe;
uint32 latch; // latched data (read when strobe goes high to low)
uint32 sensitivity; // reading while strobe is high cycles sensitivity 0,1,2
int32 mx, my; // current screen location
int32 lmx, lmy; // last latched location
uint32 mb; // current buttons
int32 dx, dy; // relative position to communicate
int32 mb; // current buttons
} SNES_MOUSE;
static SNES_MOUSE SNESMouse;
@ -53,11 +52,10 @@ static void WriteSNESMouse(uint8 v)
if (SNESMouse.strobe && !strobing)
{
int dx = SNESMouse.mx - SNESMouse.lmx;
int dy = SNESMouse.my - SNESMouse.lmy;
SNESMouse.lmx = SNESMouse.mx;
SNESMouse.lmy = SNESMouse.my;
int dx = SNESMouse.dx;
int dy = SNESMouse.dy;
SNESMouse.dx = 0;
SNESMouse.dy = 0;
// convert to sign and magnitude
bool sx = (dx < 0);
@ -91,9 +89,10 @@ static void WriteSNESMouse(uint8 v)
static void UpdateSNESMouse(int w, void *data, int arg)
{
uint32 *ptr=(uint32*)data;
SNESMouse.mx = ptr[0]; // screen position
SNESMouse.my = ptr[1];
int32 *ptr=(int32*)data;
SNESMouse.dx += ptr[0]; ptr[0] = 0;
SNESMouse.dy += ptr[1]; ptr[1] = 0;
SNESMouse.mb = ptr[2] & 3; // bit 0 = left button, bit 1 = right button
}