visualboyadvance-m/src/win32/DirectInput.cpp

947 lines
26 KiB
C++

/* VisualBoyAdvance S - GB & GBA emulator
Copyright (C) 2006 Spacy
Original VBA Credits:
Copyright (C) 1999-2003 Forgotten
Copyright (C) 2004-2006 VBA development team
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "stdafx.h"
#include "VBA.h"
#include "Input.h"
#include "Reg.h"
#include "WinResUtil.h"
#define DIRECTINPUT_VERSION 0x0800
#include <Dinput.h>
#pragma comment(lib, "Dinput8")
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
extern void directXMessage(const char *);
extern void winlog(const char *msg,...);
#define POV_UP 1
#define POV_DOWN 2
#define POV_RIGHT 4
#define POV_LEFT 8
class DirectInput : public Input {
public:
virtual void checkDevices();
DirectInput();
virtual ~DirectInput();
virtual bool initialize();
virtual bool readDevices();
virtual u32 readDevice(int which);
virtual CString getKeyName(LONG_PTR key);
virtual void checkKeys();
virtual void checkMotionKeys();
virtual void activate();
virtual void loadSettings();
virtual void saveSettings();
};
struct deviceInfo {
LPDIRECTINPUTDEVICE8 device;
BOOL isPolled;
int nButtons;
int nAxes;
int nPovs;
BOOL first;
struct {
DWORD offset;
LONG center;
LONG negative;
LONG positive;
} axis[8];
int needed;
union {
UCHAR data[256];
DIJOYSTATE state;
};
};
static deviceInfo *currentDevice = NULL;
static int numDevices = 1;
static deviceInfo *pDevices = NULL;
static LPDIRECTINPUT8 pDirectInput = NULL;
static int axisNumber = 0;
LONG_PTR defvalues[JOYPADS * KEYS_PER_PAD + MOTION_KEYS] =
{
DIK_LEFT, DIK_RIGHT,
DIK_UP, DIK_DOWN,
DIK_Z, DIK_X,
DIK_RETURN,DIK_BACK,
DIK_A, DIK_S,
DIK_SPACE, DIK_F12,
DIK_C,
0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,
DIK_NUMPAD4, DIK_NUMPAD6, DIK_NUMPAD8, DIK_NUMPAD2
};
void winReadKey(const char *name, KeyList& Keys)
{
CString TxtKeyList = regQueryStringValue(name, "");
int curPos= 0;
CString resToken=TxtKeyList.Tokenize(",",curPos);
while (resToken != "")
{
Keys.AddTail(atoi(resToken));
resToken= TxtKeyList.Tokenize(",",curPos);
};
}
void winReadKey(const char *name, int num, KeyList& Keys)
{
char buffer[80];
sprintf(buffer, "Joy%d_%s", num, name);
winReadKey(buffer, Keys);
}
void winReadKeys()
{
for(int i = 0; i < JOYPADS; i++) {
winReadKey("Left", i, theApp.input->joypaddata[JOYPAD(i,KEY_LEFT)]);
winReadKey("Right", i, theApp.input->joypaddata[JOYPAD(i, KEY_RIGHT)]);
winReadKey("Up", i, theApp.input->joypaddata[JOYPAD(i,KEY_UP)]);
winReadKey("Down", i, theApp.input->joypaddata[JOYPAD(i,KEY_DOWN)]);
winReadKey("A", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_A)]);
winReadKey("B", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_B)]);
winReadKey("L", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_L)]);
winReadKey("R", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_R)]);
winReadKey("Start", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_START)]);
winReadKey("Select", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_SELECT)]);
winReadKey("Speed", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_SPEED)]);
winReadKey("Capture", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_CAPTURE)]);
winReadKey("GS", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_GS)]);
}
winReadKey("Motion_Left", theApp.input->joypaddata[MOTION(KEY_LEFT)]);
winReadKey("Motion_Right", theApp.input->joypaddata[MOTION(KEY_RIGHT)]);
winReadKey("Motion_Up", theApp.input->joypaddata[MOTION(KEY_UP)]);
winReadKey("Motion_Down", theApp.input->joypaddata[MOTION(KEY_DOWN)]);
}
void winSaveKey(char *name, KeyList& value)
{
CString txtKeys;
POSITION p = value.GetHeadPosition();
while(p!=NULL)
{
CString tmp;
tmp.Format("%d", value.GetNext(p));
txtKeys+=tmp;
if (p!=NULL)
txtKeys+=",";
}
regSetStringValue(name, txtKeys);
}
static void winSaveKey(char *name, int num, KeyList& value)
{
char buffer[80];
sprintf(buffer, "Joy%d_%s", num, name);
winSaveKey(buffer, value);
}
void winSaveKeys()
{
for(int i = 0; i < JOYPADS; i++) {
winSaveKey("Left", i, theApp.input->joypaddata[JOYPAD(i,KEY_LEFT)]);
winSaveKey("Right", i, theApp.input->joypaddata[JOYPAD(i,KEY_RIGHT)]);
winSaveKey("Up", i, theApp.input->joypaddata[JOYPAD(i,KEY_UP)]);
winSaveKey("Speed", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_SPEED)]);
winSaveKey("Capture", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_CAPTURE)]);
winSaveKey("GS", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_GS)]);
winSaveKey("Down", i, theApp.input->joypaddata[JOYPAD(i,KEY_DOWN)]);
winSaveKey("A", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_A)]);
winSaveKey("B", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_B)]);
winSaveKey("L", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_L)]);
winSaveKey("R", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_R)]);
winSaveKey("Start", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_START)]);
winSaveKey("Select", i, theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_SELECT)]);
}
regSetDwordValue("joyVersion", 1);
winSaveKey("Motion_Left",
theApp.input->joypaddata[MOTION(KEY_LEFT)]);
winSaveKey("Motion_Right",
theApp.input->joypaddata[MOTION(KEY_RIGHT)]);
winSaveKey("Motion_Up",
theApp.input->joypaddata[MOTION(KEY_UP)]);
winSaveKey("Motion_Down",
theApp.input->joypaddata[MOTION(KEY_DOWN)]);
}
static BOOL CALLBACK EnumAxesCallback( const DIDEVICEOBJECTINSTANCE* pdidoi,
VOID* pContext )
{
DIPROPRANGE diprg;
diprg.diph.dwSize = sizeof(DIPROPRANGE);
diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER);
diprg.diph.dwHow = DIPH_BYOFFSET;
diprg.diph.dwObj = pdidoi->dwOfs; // Specify the enumerated axis
diprg.lMin = -32768;
diprg.lMax = 32767;
// try to set the range
if (FAILED(currentDevice->device->SetProperty(DIPROP_RANGE, &diprg.diph))) {
// Get the range for the axis
if ( FAILED(currentDevice->device->
GetProperty( DIPROP_RANGE, &diprg.diph ) ) ) {
return DIENUM_STOP;
}
}
DIPROPDWORD didz;
didz.diph.dwSize = sizeof(didz);
didz.diph.dwHeaderSize = sizeof(DIPROPHEADER);
didz.diph.dwHow = DIPH_BYOFFSET;
didz.diph.dwObj = pdidoi->dwOfs;
didz.dwData = 5000;
currentDevice->device->SetProperty(DIPROP_DEADZONE, &didz.diph);
LONG center = (diprg.lMin + diprg.lMax)/2;
LONG threshold = (diprg.lMax - center)/2;
// only 8 axis supported
if (axisNumber < 8) {
currentDevice->axis[axisNumber].center = center;
currentDevice->axis[axisNumber].negative = center - threshold;
currentDevice->axis[axisNumber].positive = center + threshold;
currentDevice->axis[axisNumber].offset = pdidoi->dwOfs;
}
axisNumber++;
return DIENUM_CONTINUE;
}
static BOOL CALLBACK EnumPovsCallback( const DIDEVICEOBJECTINSTANCE* pdidoi,
VOID* pContext )
{
return DIENUM_CONTINUE;
}
static BOOL CALLBACK DIEnumDevicesCallback(LPCDIDEVICEINSTANCE pInst,
LPVOID lpvContext)
{
ZeroMemory(&pDevices[numDevices],sizeof(deviceInfo));
HRESULT hRet = pDirectInput->CreateDevice(pInst->guidInstance,
&pDevices[numDevices].device,
NULL);
if (hRet != DI_OK)
return DIENUM_STOP;
DIDEVCAPS caps;
caps.dwSize=sizeof(DIDEVCAPS);
hRet = pDevices[numDevices].device->GetCapabilities(&caps);
if (hRet == DI_OK) {
if (caps.dwFlags & DIDC_POLLEDDATAFORMAT ||
caps.dwFlags & DIDC_POLLEDDEVICE)
pDevices[numDevices].isPolled = TRUE;
pDevices[numDevices].nButtons = caps.dwButtons;
pDevices[numDevices].nAxes = caps.dwAxes;
pDevices[numDevices].nPovs = caps.dwPOVs;
for (int i = 0; i < 6; i++) {
pDevices[numDevices].axis[i].center = 0x8000;
pDevices[numDevices].axis[i].negative = 0x4000;
pDevices[numDevices].axis[i].positive = 0xc000;
}
}
numDevices++;
return DIENUM_CONTINUE;
}
BOOL CALLBACK DIEnumDevicesCallback2(LPCDIDEVICEINSTANCE pInst,
LPVOID lpvContext)
{
numDevices++;
return DIENUM_CONTINUE;
}
static int getPovState(DWORD value)
{
int state = 0;
if (LOWORD(value) != 0xFFFF) {
if (value < 9000 || value > 27000)
state |= POV_UP;
if (value > 0 && value < 18000)
state |= POV_RIGHT;
if (value > 9000 && value < 27000)
state |= POV_DOWN;
if (value > 18000)
state |= POV_LEFT;
}
return state;
}
static void checkKeys()
{
LONG_PTR dev = 0;
int i;
for(i = 0; i < (sizeof(theApp.input->joypaddata) / sizeof(theApp.input->joypaddata[0])); i++)
{
if (theApp.input->joypaddata[i].IsEmpty() && defvalues[i])
theApp.input->joypaddata[i].AddTail(defvalues[i]);
POSITION p = theApp.input->joypaddata[i].GetHeadPosition();
while(p!=NULL)
{
LONG_PTR k = theApp.input->joypaddata[i].GetNext(p);
if (k > 0 && DEVICEOF(k) < numDevices)
pDevices[DEVICEOF(k)].needed = true;
}
}
}
#define KEYDOWN(buffer,key) (buffer[key] & 0x80)
static bool readKeyboard()
{
if (pDevices[0].needed) {
HRESULT hret = pDevices[0].device->
GetDeviceState(256,
(LPVOID)pDevices[0].data);
if (hret == DIERR_INPUTLOST || hret == DIERR_NOTACQUIRED) {
hret = pDevices[0].device->Acquire();
if (hret != DI_OK)
return false;
hret = pDevices[0].device->GetDeviceState(256,(LPVOID)pDevices[0].data);
}
return hret == DI_OK;
}
return true;
}
static bool readJoystick(int joy)
{
if (pDevices[joy].needed) {
if (pDevices[joy].isPolled)
((LPDIRECTINPUTDEVICE2)pDevices[joy].device)->Poll();
HRESULT hret = pDevices[joy].device->
GetDeviceState(sizeof(DIJOYSTATE),
(LPVOID)&pDevices[joy].state);
if (hret == DIERR_INPUTLOST || hret == DIERR_NOTACQUIRED) {
hret = pDevices[joy].device->Acquire();
if (hret == DI_OK) {
if (pDevices[joy].isPolled)
((LPDIRECTINPUTDEVICE2)pDevices[joy].device)->Poll();
hret = pDevices[joy].device->
GetDeviceState(sizeof(DIJOYSTATE),
(LPVOID)&pDevices[joy].state);
}
}
return hret == DI_OK;
}
return true;
}
static void checkKeyboard()
{
// mham fix. Patch #1378104
UCHAR keystate[256];
HRESULT hret = pDevices[0].device->Acquire();
if (pDevices[0].first) {
pDevices[0].device->GetDeviceState(256, (LPVOID)pDevices[0].data);
pDevices[0].first = FALSE;
return;
}
hret = pDevices[0].device->
GetDeviceState(256, (LPVOID)keystate);
if (hret == DIERR_INPUTLOST || hret == DIERR_NOTACQUIRED) {
return;
}
if (hret == DI_OK) {
for (int i = 0; i < 256; i++) {
if (keystate[i] == pDevices[0].data[i]) continue;
if (KEYDOWN(keystate, i)) {
SendMessage(GetFocus(), JOYCONFIG_MESSAGE,0,i);
break;
}
}
}
memcpy(pDevices[0].data, keystate, sizeof(UCHAR) * 256);
}
static void checkJoypads()
{
DIDEVICEOBJECTINSTANCE di;
ZeroMemory(&di,sizeof(DIDEVICEOBJECTINSTANCE));
di.dwSize = sizeof(DIDEVICEOBJECTINSTANCE);
int i =0;
DIJOYSTATE joystick;
for (i = 1; i < numDevices; i++) {
HRESULT hret = pDevices[i].device->Acquire();
if (pDevices[i].isPolled)
((LPDIRECTINPUTDEVICE2)pDevices[i].device)->Poll();
hret = pDevices[i].device->GetDeviceState(sizeof(joystick), &joystick);
int j;
if (pDevices[i].first) {
memcpy(&pDevices[i].state, &joystick, sizeof(joystick));
pDevices[i].first = FALSE;
continue;
}
for (j = 0; j < pDevices[i].nButtons; j++) {
if (((pDevices[i].state.rgbButtons[j] ^ joystick.rgbButtons[j])
& joystick.rgbButtons[j]) & 0x80) {
HWND focus = GetFocus();
SendMessage(focus, JOYCONFIG_MESSAGE, i,j+128);
}
}
for (j = 0; j < pDevices[i].nAxes && j < 8; j++) {
LONG value = pDevices[i].axis[j].center;
LONG old = 0;
switch (pDevices[i].axis[j].offset) {
case DIJOFS_X:
value = joystick.lX;
old = pDevices[i].state.lX;
break;
case DIJOFS_Y:
value = joystick.lY;
old = pDevices[i].state.lY;
break;
case DIJOFS_Z:
value = joystick.lZ;
old = pDevices[i].state.lZ;
break;
case DIJOFS_RX:
value = joystick.lRx;
old = pDevices[i].state.lRx;
break;
case DIJOFS_RY:
value = joystick.lRy;
old = pDevices[i].state.lRy;
break;
case DIJOFS_RZ:
value = joystick.lRz;
old = pDevices[i].state.lRz;
break;
case DIJOFS_SLIDER(0):
value = joystick.rglSlider[0];
old = pDevices[i].state.rglSlider[0];
break;
case DIJOFS_SLIDER(1):
value = joystick.rglSlider[1];
old = pDevices[i].state.rglSlider[1];
break;
}
if (value != old) {
if (value < pDevices[i].axis[j].negative)
SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<1));
else if (value > pDevices[i].axis[j].positive)
SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<1)+1);
}
}
for (j = 0;j < 4 && j < pDevices[i].nPovs; j++) {
if (LOWORD(pDevices[i].state.rgdwPOV[j]) != LOWORD(joystick.rgdwPOV[j])) {
int state = getPovState(joystick.rgdwPOV[j]);
if (state & POV_UP)
SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<2)+0x20);
else if (state & POV_DOWN)
SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<2)+0x21);
else if (state & POV_RIGHT)
SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<2)+0x22);
else if (state & POV_LEFT)
SendMessage(GetFocus(), JOYCONFIG_MESSAGE, i, (j<<2)+0x23);
}
}
memcpy(&pDevices[i].state, &joystick, sizeof(joystick));
}
}
BOOL checkKey(LONG_PTR key)
{
LONG_PTR dev = (key >> 8);
LONG_PTR k = (key & 255);
if (dev == 0) {
return KEYDOWN(pDevices[0].data,k);
} else if (dev >= numDevices) {
return FALSE;
} else {
if (k < 16) {
LONG_PTR axis = k >> 1;
LONG value = pDevices[dev].axis[axis].center;
switch (pDevices[dev].axis[axis].offset) {
case DIJOFS_X:
value = pDevices[dev].state.lX;
break;
case DIJOFS_Y:
value = pDevices[dev].state.lY;
break;
case DIJOFS_Z:
value = pDevices[dev].state.lZ;
break;
case DIJOFS_RX:
value = pDevices[dev].state.lRx;
break;
case DIJOFS_RY:
value = pDevices[dev].state.lRy;
break;
case DIJOFS_RZ:
value = pDevices[dev].state.lRz;
break;
case DIJOFS_SLIDER(0):
value = pDevices[dev].state.rglSlider[0];
break;
case DIJOFS_SLIDER(1):
value = pDevices[dev].state.rglSlider[1];
break;
}
if (k & 1)
return value > pDevices[dev].axis[axis].positive;
return value < pDevices[dev].axis[axis].negative;
} else if (k < 48) {
LONG_PTR hat = (k >> 2) & 3;
int state = getPovState(pDevices[dev].state.rgdwPOV[hat]);
BOOL res = FALSE;
switch (k & 3) {
case 0:
res = state & POV_UP;
break;
case 1:
res = state & POV_DOWN;
break;
case 2:
res = state & POV_RIGHT;
break;
case 3:
res = state & POV_LEFT;
break;
}
return res;
} else if (k >= 128) {
return pDevices[dev].state.rgbButtons[k-128] & 0x80;
}
}
return FALSE;
}
BOOL checkKey(KeyList &k)
{
POSITION p = k.GetHeadPosition();
while(p!=NULL)
{
if (checkKey(k.GetNext(p)))
return TRUE;
}
return FALSE;
}
DirectInput::DirectInput()
{}
DirectInput::~DirectInput()
{
saveSettings();
if (pDirectInput != NULL) {
if (pDevices) {
for (int i = 0; i < numDevices ; i++) {
if (pDevices[i].device) {
pDevices[i].device->Unacquire();
pDevices[i].device->Release();
pDevices[i].device = NULL;
}
}
free(pDevices);
pDevices = NULL;
}
pDirectInput->Release();
pDirectInput = NULL;
}
}
bool DirectInput::initialize()
{
HRESULT hr;
hr = DirectInput8Create(
AfxGetInstanceHandle(),
DIRECTINPUT_VERSION,
IID_IDirectInput8,
(LPVOID*)&pDirectInput,
NULL );
if ( hr != DI_OK ) {
return false;
}
hr = pDirectInput->EnumDevices(DI8DEVCLASS_GAMECTRL,
DIEnumDevicesCallback2,
NULL,
DIEDFL_ATTACHEDONLY);
pDevices = (deviceInfo *)calloc(numDevices, sizeof(deviceInfo));
hr = pDirectInput->CreateDevice(GUID_SysKeyboard,&pDevices[0].device,NULL);
pDevices[0].isPolled = false;
pDevices[0].needed = true;
pDevices[0].first = true;
if (hr != DI_OK) {
return false;
}
numDevices = 1;
hr = pDirectInput->EnumDevices(DI8DEVCLASS_GAMECTRL,
DIEnumDevicesCallback,
NULL,
DIEDFL_ATTACHEDONLY);
if (hr != DI_OK) {
return false;
}
hr = pDevices[0].device->SetDataFormat(&c_dfDIKeyboard);
if (hr != DI_OK) {
return false;
}
int i;
for (i = 1; i < numDevices; i++) {
pDevices[i].device->SetDataFormat(&c_dfDIJoystick);
pDevices[i].needed = false;
pDevices[i].first = true;
currentDevice = &pDevices[i];
axisNumber = 0;
currentDevice->device->EnumObjects(EnumAxesCallback, NULL, DIDFT_AXIS);
currentDevice->device->EnumObjects(EnumPovsCallback, NULL, DIDFT_POV);
currentDevice = NULL;
}
for (i = 0; i < numDevices; i++)
pDevices[i].device->Acquire();
return true;
}
bool DirectInput::readDevices()
{
bool ok = true;
for (int i = 0; i < numDevices; i++) {
if (pDevices[i].needed) {
if (i) {
ok = readJoystick(i);
} else
ok = readKeyboard();
}
}
return ok;
}
u32 DirectInput::readDevice(int which)
{
u32 res = 0;
int i = theApp.joypadDefault;
if(which >= 0 && which <= 3)
i = which;
if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_A)]))
res |= 1;
if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_B)]))
res |= 2;
if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_SELECT)]))
res |= 4;
if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_START)]))
res |= 8;
if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_RIGHT)]))
res |= 16;
if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_LEFT)]))
res |= 32;
if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_UP)]))
res |= 64;
if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_DOWN)]))
res |= 128;
if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_R)]))
res |= 256;
if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_L)]))
res |= 512;
if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_GS)]))
res |= 4096;
if(theApp.autoFire) {
res &= (~theApp.autoFire);
if(theApp.autoFireToggle)
res |= theApp.autoFire;
theApp.autoFireToggle = !theApp.autoFireToggle;
}
// disallow L+R or U+D of being pressed at the same time
if((res & 48) == 48)
res &= ~16;
if((res & 192) == 192)
res &= ~128;
if(theApp.movieRecording) {
if(i == theApp.joypadDefault) {
if(res != theApp.movieLastJoypad) {
fwrite(&theApp.movieFrame, 1, sizeof(theApp.movieFrame), theApp.movieFile);
fwrite(&res, 1, sizeof(res), theApp.movieFile);
theApp.movieLastJoypad = res;
}
}
}
if(theApp.moviePlaying) {
if(theApp.movieFrame == theApp.moviePlayFrame) {
theApp.movieLastJoypad = theApp.movieNextJoypad;
theApp.movieReadNext();
}
res = theApp.movieLastJoypad;
}
// we don't record speed up or screen capture buttons
if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_SPEED)]) || theApp.speedupToggle)
res |= 1024;
if(checkKey(theApp.input->joypaddata[JOYPAD(i,KEY_BUTTON_CAPTURE)]))
res |= 2048;
return res;
}
CString DirectInput::getKeyName(LONG_PTR key)
{
LONG_PTR d = (key >> 8);
LONG_PTR k = key & 255;
DIDEVICEOBJECTINSTANCE di;
ZeroMemory(&di,sizeof(DIDEVICEOBJECTINSTANCE));
di.dwSize = sizeof(DIDEVICEOBJECTINSTANCE);
CString winBuffer = winResLoadString(IDS_ERROR);
if (d == 0) {
pDevices[0].device->GetObjectInfo( &di, (DWORD)key, DIPH_BYOFFSET );
winBuffer = di.tszName;
} else if (d < numDevices) {
if (k < 16) {
if (k < 4) {
switch (k) {
case 0:
winBuffer.Format(winResLoadString(IDS_JOY_LEFT), d);
break;
case 1:
winBuffer.Format(winResLoadString(IDS_JOY_RIGHT), d);
break;
case 2:
winBuffer.Format(winResLoadString(IDS_JOY_UP), d);
break;
case 3:
winBuffer.Format(winResLoadString(IDS_JOY_DOWN), d);
break;
}
} else {
pDevices[d].device->GetObjectInfo(&di,
pDevices[d].axis[k>>1].offset,
DIPH_BYOFFSET);
if (k & 1)
winBuffer.Format("Joy %d %s +", d, di.tszName);
else
winBuffer.Format("Joy %d %s -", d, di.tszName);
}
} else if (k < 48) {
LONG_PTR hat = (k >> 2) & 3;
pDevices[d].device->GetObjectInfo(&di,
(DWORD)DIJOFS_POV(hat),
DIPH_BYOFFSET);
char *dir = "up";
LONG_PTR dd = k & 3;
if (dd == 1)
dir = "down";
else if (dd == 2)
dir = "right";
else if (dd == 3)
dir = "left";
winBuffer.Format("Joy %d %s %s", d, di.tszName, dir);
} else {
pDevices[d].device->GetObjectInfo(&di,
(DWORD)DIJOFS_BUTTON(k-128),
DIPH_BYOFFSET);
winBuffer.Format(winResLoadString(IDS_JOY_BUTTON),d,di.tszName);
}
}
else
{
// Joystick isn't plugged in. We can't decipher k, so just show its value.
winBuffer.Format("Joy %d (%d)", d, k);
}
return winBuffer;
}
void DirectInput::checkKeys()
{
::checkKeys();
}
void DirectInput::checkMotionKeys()
{
if(checkKey(theApp.input->joypaddata[MOTION(KEY_LEFT)])) {
theApp.sensorX += 3;
if(theApp.sensorX > 2197)
theApp.sensorX = 2197;
if(theApp.sensorX < 2047)
theApp.sensorX = 2057;
} else if(checkKey(theApp.input->joypaddata[MOTION(KEY_RIGHT)])) {
theApp.sensorX -= 3;
if(theApp.sensorX < 1897)
theApp.sensorX = 1897;
if(theApp.sensorX > 2047)
theApp.sensorX = 2037;
} else if(theApp.sensorX > 2047) {
theApp.sensorX -= 2;
if(theApp.sensorX < 2047)
theApp.sensorX = 2047;
} else {
theApp.sensorX += 2;
if(theApp.sensorX > 2047)
theApp.sensorX = 2047;
}
if(checkKey(theApp.input->joypaddata[MOTION(KEY_UP)])) {
theApp.sensorY += 3;
if(theApp.sensorY > 2197)
theApp.sensorY = 2197;
if(theApp.sensorY < 2047)
theApp.sensorY = 2057;
} else if(checkKey(theApp.input->joypaddata[MOTION(KEY_DOWN)])) {
theApp.sensorY -= 3;
if(theApp.sensorY < 1897)
theApp.sensorY = 1897;
if(theApp.sensorY > 2047)
theApp.sensorY = 2037;
} else if(theApp.sensorY > 2047) {
theApp.sensorY -= 2;
if(theApp.sensorY < 2047)
theApp.sensorY = 2047;
} else {
theApp.sensorY += 2;
if(theApp.sensorY > 2047)
theApp.sensorY = 2047;
}
}
Input *newDirectInput()
{
return new DirectInput;
}
void DirectInput::checkDevices()
{
checkJoypads();
checkKeyboard();
}
void DirectInput::activate()
{
for (int i = 0; i < numDevices; i++) {
if (pDevices != NULL && pDevices[i].device != NULL)
pDevices[i].device->Acquire();
}
}
void DirectInput::loadSettings()
{
winReadKeys();
}
void DirectInput::saveSettings()
{
winSaveKeys();
}