BizHawk/yabause/src/perdx.c

1302 lines
41 KiB
C

/* Copyright 2006 Theo Berkau
This file is part of Yabause.
Yabause 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.
Yabause 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 Yabause; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <windows.h>
#include "debug.h"
#include "peripheral.h"
#include "perdx.h"
#include "vdp1.h"
#include "vdp2.h"
#include "yui.h"
#include "movie.h"
#define IDD_BUTTONCONFIG 123
#define IDC_WAITINPUT 1001
#define IDC_DXDEVICECB 1010
#define IDC_UPTEXT 1024
#define IDC_RIGHTTEXT 1025
#define IDC_DOWNTEXT 1026
#define IDC_LEFTTEXT 1027
#define IDC_RTEXT 1028
#define IDC_LTEXT 1029
#define IDC_STARTTEXT 1030
#define IDC_ATEXT 1031
#define IDC_BTEXT 1032
#define IDC_CTEXT 1033
#define IDC_XTEXT 1034
#define IDC_YTEXT 1035
#define IDC_ZTEXT 1036
#define IDC_CUSTOMCANCEL 1037
enum {
EMUTYPE_NONE=0,
EMUTYPE_STANDARDPAD,
EMUTYPE_ANALOGPAD,
EMUTYPE_STUNNER,
EMUTYPE_MOUSE,
EMUTYPE_KEYBOARD
};
int PERDXInit(void);
void PERDXDeInit(void);
int PERDXHandleEvents(void);
int Check_Skip_Key();
PerInterface_struct PERDIRECTX = {
PERCORE_DIRECTX,
"DirectX Input Interface",
PERDXInit,
PERDXDeInit,
PERDXHandleEvents
};
LPDIRECTINPUT8 lpDI8 = NULL;
LPDIRECTINPUTDEVICE8 lpDIDevice[256]; // I hope that's enough
GUID GUIDDevice[256]; // I hope that's enough
u32 numguids=0;
u32 numdevices=0;
u32 numpads=12;
PerPad_struct *pad[12];
padconf_struct paddevice[12];
int porttype[2];
const char *mouse_names[] = {
"A",
"B",
"C",
"Start",
NULL
};
#define TYPE_KEYBOARD 0
#define TYPE_JOYSTICK 1
#define TYPE_MOUSE 2
#define PAD_DIR_AXISLEFT 0
#define PAD_DIR_AXISRIGHT 1
#define PAD_DIR_AXISUP 2
#define PAD_DIR_AXISDOWN 3
#define PAD_DIR_POVUP 4
#define PAD_DIR_POVRIGHT 5
#define PAD_DIR_POVDOWN 6
#define PAD_DIR_POVLEFT 7
HWND DXGetWindow ();
//////////////////////////////////////////////////////////////////////////////
BOOL CALLBACK EnumPeripheralsCallback (LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef)
{
if (GET_DIDEVICE_TYPE(lpddi->dwDevType) == DI8DEVTYPE_GAMEPAD ||
GET_DIDEVICE_TYPE(lpddi->dwDevType) == DI8DEVTYPE_JOYSTICK ||
GET_DIDEVICE_TYPE(lpddi->dwDevType) == DI8DEVTYPE_KEYBOARD)
{
if (SUCCEEDED(IDirectInput8_CreateDevice(lpDI8, &lpddi->guidInstance, &lpDIDevice[numdevices],
NULL) ))
numdevices++;
}
return DIENUM_CONTINUE;
}
//////////////////////////////////////////////////////////////////////////////
void LoadDefaultPort1A(void)
{
porttype[0] = 1;
porttype[1] = 0;
pad[0] = PerPadAdd(&PORTDATA1);
PerSetKey(DIK_UP, PERPAD_UP, pad[0]);
PerSetKey(DIK_DOWN, PERPAD_DOWN, pad[0]);
PerSetKey(DIK_LEFT, PERPAD_LEFT, pad[0]);
PerSetKey(DIK_RIGHT, PERPAD_RIGHT, pad[0]);
PerSetKey(DIK_K, PERPAD_A, pad[0]);
PerSetKey(DIK_L, PERPAD_B, pad[0]);
PerSetKey(DIK_M, PERPAD_C, pad[0]);
PerSetKey(DIK_U, PERPAD_X, pad[0]);
PerSetKey(DIK_I, PERPAD_Y, pad[0]);
PerSetKey(DIK_O, PERPAD_Z, pad[0]);
PerSetKey(DIK_X, PERPAD_LEFT_TRIGGER, pad[0]);
PerSetKey(DIK_Z, PERPAD_RIGHT_TRIGGER, pad[0]);
PerSetKey(DIK_J, PERPAD_START, pad[0]);
}
//////////////////////////////////////////////////////////////////////////////
int PERDXInit(void)
{
DIPROPDWORD dipdw;
char tempstr[512];
HRESULT ret;
memset(pad, 0, sizeof(pad));
memset(paddevice, 0, sizeof(paddevice));
if (FAILED((ret = DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION,
&IID_IDirectInput8, (LPVOID *)&lpDI8, NULL)) ))
{
sprintf(tempstr, "DirectInput8Create error: %s - %s", DXGetErrorString8(ret), DXGetErrorDescription8(ret));
MessageBox (NULL, _16(tempstr), _16("Error"), MB_OK | MB_ICONINFORMATION);
return -1;
}
IDirectInput8_EnumDevices(lpDI8, DI8DEVCLASS_ALL, EnumPeripheralsCallback,
NULL, DIEDFL_ATTACHEDONLY);
if (FAILED((ret = IDirectInput8_CreateDevice(lpDI8, &GUID_SysKeyboard, &lpDIDevice[0],
NULL)) ))
{
sprintf(tempstr, "IDirectInput8_CreateDevice error: %s - %s", DXGetErrorString8(ret), DXGetErrorDescription8(ret));
MessageBox (NULL, _16(tempstr), _16("Error"), MB_OK | MB_ICONINFORMATION);
return -1;
}
if (FAILED((ret = IDirectInputDevice8_SetDataFormat(lpDIDevice[0], &c_dfDIKeyboard)) ))
{
sprintf(tempstr, "IDirectInputDevice8_SetDataFormat error: %s - %s", DXGetErrorString8(ret), DXGetErrorDescription8(ret));
MessageBox (NULL, _16(tempstr), _16("Error"), MB_OK | MB_ICONINFORMATION);
return -1;
}
if (FAILED((ret = IDirectInputDevice8_SetCooperativeLevel(lpDIDevice[0], DXGetWindow(),
DISCL_FOREGROUND | DISCL_NONEXCLUSIVE | DISCL_NOWINKEY)) ))
{
sprintf(tempstr, "IDirectInputDevice8_SetCooperativeLevel error: %s - %s", DXGetErrorString8(ret), DXGetErrorDescription8(ret));
MessageBox (NULL, _16(tempstr), _16("Error"), MB_OK | MB_ICONINFORMATION);
return -1;
}
dipdw.diph.dwSize = sizeof(DIPROPDWORD);
dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
dipdw.diph.dwObj = 0;
dipdw.diph.dwHow = DIPH_DEVICE;
dipdw.dwData = 8; // should be enough
// Setup Buffered input
if (FAILED((ret = IDirectInputDevice8_SetProperty(lpDIDevice[0], DIPROP_BUFFERSIZE, &dipdw.diph)) ))
{
sprintf(tempstr, "IDirectInputDevice8_SetProperty error: %s - %s", DXGetErrorString8(ret), DXGetErrorDescription8(ret));
MessageBox (NULL, _16(tempstr), _16("Error"), MB_OK | MB_ICONINFORMATION);
return -1;
}
// Make sure Keyboard is acquired already
IDirectInputDevice8_Acquire(lpDIDevice[0]);
paddevice[0].lpDIDevice = lpDIDevice[0];
paddevice[0].type = TYPE_KEYBOARD;
paddevice[0].emulatetype = 1;
PerPortReset();
LoadDefaultPort1A();
return 0;
}
//////////////////////////////////////////////////////////////////////////////
void StringToGUID(const char *string, GUID *guid)
{
int data4[8];
int i;
sscanf(string, "%08lX-%04hX-%04hX-%02X%02X%02X%02X%02X%02X%02X%02X", (int *)&guid->Data1, (int *)&guid->Data2, (int *)&guid->Data3, &data4[0], &data4[1], &data4[2], &data4[3], &data4[4], &data4[5], &data4[6], &data4[7]);
for (i = 0; i < 8; i++)
guid->Data4[i] = (BYTE)data4[i];
}
//////////////////////////////////////////////////////////////////////////////
void PERDXLoadDevices(char *inifilename)
{
char tempstr[MAX_PATH];
char string1[20];
char string2[20];
GUID guid;
DIDEVCAPS didc;
u32 i;
int j, i2;
int buttonid;
DIPROPDWORD dipdw;
int id;
DWORD coopflags=DISCL_FOREGROUND | DISCL_NONEXCLUSIVE;
BOOL loaddefault=TRUE;
int numpads;
HRESULT hr;
if (!PERCore)
return;
PerPortReset();
memset(pad, 0, sizeof(pad));
// Check Connection Type
if (GetPrivateProfileStringA("Input", "Port1Type", "", tempstr, MAX_PATH, inifilename) == 0)
{
// Check if it's using the old ini settings for peripherals
if (GetPrivateProfileStringA("Peripheral1", "GUID", "", tempstr, MAX_PATH, inifilename) != 0)
{
// Convert to the newer type of settings
for (i = 0; i < 2; i++)
{
sprintf(string1, "Port%dType", (int)i+1);
WritePrivateProfileStringA("Input", string1, "1", inifilename);
sprintf(string1, "Peripheral%d", (int)i+1);
sprintf(string2, "Peripheral%dA", (int)i+1);
if (GetPrivateProfileStringA(string1, "GUID", "", tempstr, MAX_PATH, inifilename))
WritePrivateProfileStringA(string2, "GUID", tempstr, inifilename);
if (GetPrivateProfileStringA(string1, "EmulateType", "", tempstr, MAX_PATH, inifilename))
WritePrivateProfileStringA(string2, "EmulateType", tempstr, inifilename);
for (i2 = 0; i2 < 13; i2++)
{
if (GetPrivateProfileStringA(string1, PerPadNames[i2], "", tempstr, MAX_PATH, inifilename))
WritePrivateProfileStringA(string2, PerPadNames[i2], tempstr, inifilename);
}
}
// Remove old ini entries
for (i = 0; i < 12; i++)
{
sprintf(string1, "Peripheral%d", (int)i+1);
WritePrivateProfileStringA(string1, NULL, NULL, inifilename);
}
loaddefault = FALSE;
}
}
else
loaddefault = FALSE;
if (loaddefault)
{
LoadDefaultPort1A();
return;
}
// Load new type settings
for (i = 0; i < 2; i++)
{
sprintf(string1, "Port%dType", (int)i+1);
if (GetPrivateProfileStringA("Input", string1, "", tempstr, MAX_PATH, inifilename) != 0)
{
porttype[i] = atoi(tempstr);
switch(porttype[i])
{
case 1:
numpads = 1;
break;
case 2:
numpads = 6;
break;
default:
numpads = 0;
break;
}
// Load new type settings
for (j = 0; j < numpads; j++)
{
int padindex=(6*i)+j;
padconf_struct *curdevice=&paddevice[padindex];
sprintf(string1, "Peripheral%d%C", (int)i+1, 'A' + j);
// Let's first fetch the guid of the device
if (GetPrivateProfileStringA(string1, "GUID", "", tempstr, MAX_PATH, inifilename) == 0)
continue;
if (GetPrivateProfileStringA(string1, "EmulateType", "0", string2, MAX_PATH, inifilename))
{
curdevice->emulatetype = atoi(string2);
if (curdevice->emulatetype == 0)
continue;
}
if (curdevice->lpDIDevice)
{
// Free the default keyboard, etc.
IDirectInputDevice8_Unacquire(curdevice->lpDIDevice);
IDirectInputDevice8_Release(curdevice->lpDIDevice);
}
StringToGUID(tempstr, &guid);
// Ok, now that we've got the GUID of the device, let's set it up
if (FAILED(IDirectInput8_CreateDevice(lpDI8, &guid, &lpDIDevice[padindex],
NULL) ))
{
curdevice->lpDIDevice = NULL;
curdevice->emulatetype = 0;
continue;
}
curdevice->lpDIDevice = lpDIDevice[padindex];
didc.dwSize = sizeof(DIDEVCAPS);
if (FAILED(IDirectInputDevice8_GetCapabilities(lpDIDevice[padindex], &didc) ))
continue;
if (GET_DIDEVICE_TYPE(didc.dwDevType) == DI8DEVTYPE_KEYBOARD)
{
if (FAILED(IDirectInputDevice8_SetDataFormat(lpDIDevice[padindex], &c_dfDIKeyboard) ))
continue;
curdevice->type = TYPE_KEYBOARD;
coopflags |= DISCL_NOWINKEY;
}
else if (GET_DIDEVICE_TYPE(didc.dwDevType) == DI8DEVTYPE_GAMEPAD ||
GET_DIDEVICE_TYPE(didc.dwDevType) == DI8DEVTYPE_JOYSTICK)
{
if (FAILED(IDirectInputDevice8_SetDataFormat(lpDIDevice[padindex], &c_dfDIJoystick2) ))
continue;
curdevice->type = TYPE_JOYSTICK;
}
else if (GET_DIDEVICE_TYPE(didc.dwDevType) == DI8DEVTYPE_MOUSE)
{
if (FAILED(IDirectInputDevice8_SetDataFormat(lpDIDevice[padindex], &c_dfDIMouse2) ))
continue;
curdevice->type = TYPE_MOUSE;
coopflags = DISCL_FOREGROUND | DISCL_EXCLUSIVE;
}
hr = IDirectInputDevice8_SetCooperativeLevel(lpDIDevice[i], DXGetWindow(), coopflags);
if (FAILED(hr))
continue;
dipdw.diph.dwSize = sizeof(DIPROPDWORD);
dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
dipdw.diph.dwObj = 0;
dipdw.diph.dwHow = DIPH_DEVICE;
dipdw.dwData = 8; // should be enough
// Setup Buffered input
if (FAILED(IDirectInputDevice8_SetProperty(lpDIDevice[padindex], DIPROP_BUFFERSIZE, &dipdw.diph)))
continue;
IDirectInputDevice8_Acquire(lpDIDevice[padindex]);
switch(curdevice->emulatetype)
{
case 1: // Standard Pad
id = PERPAD;
break;
case 2: // Analog Pad
case 3: // Stunner
case 5: // Keyboard
id = 0;
break;
case 4: // Mouse
id = PERMOUSE;
break;
default: break;
}
// Make sure we're added to the smpc list
if (i == 0)
pad[padindex] = PerAddPeripheral(&PORTDATA1, id);
else
pad[padindex] = PerAddPeripheral(&PORTDATA2, id);
// Now that we're all setup, let's fetch the controls from the ini
if (curdevice->emulatetype != 3 &&
curdevice->emulatetype != 4)
{
for (i2 = 0; i2 < 13; i2++)
{
buttonid = GetPrivateProfileIntA(string1, PerPadNames[i2], 0, inifilename);
PerSetKey(buttonid, i2, pad[padindex]);
}
}
else if (curdevice->emulatetype == 4)
{
for (i2 = 0; i2 < 4; i2++)
{
buttonid = GetPrivateProfileIntA(string1, mouse_names[i2], 0, inifilename);
PerSetKey(buttonid, PERMOUSE_LEFT+i2, pad[padindex]);
}
}
}
}
}
}
//////////////////////////////////////////////////////////////////////////////
void PERDXDeInit(void)
{
u32 i;
for (i = 0; i < numdevices; i++)
{
if (lpDIDevice[i])
{
IDirectInputDevice8_Unacquire(lpDIDevice[i]);
IDirectInputDevice8_Release(lpDIDevice[i]);
lpDIDevice[i] = NULL;
}
}
if (lpDI8)
{
IDirectInput8_Release(lpDI8);
lpDI8 = NULL;
}
}
//////////////////////////////////////////////////////////////////////////////
void PollKeys(void)
{
u32 i;
DWORD i2;
DWORD size=8;
DIDEVICEOBJECTDATA didod[8];
HRESULT hr;
for (i = 0; i < numpads; i++)
{
if (paddevice[i].lpDIDevice == NULL)
continue;
hr = IDirectInputDevice8_Poll(paddevice[i].lpDIDevice);
if (FAILED(hr))
{
if (hr == DIERR_INPUTLOST || hr == DIERR_NOTACQUIRED)
{
// Make sure device is acquired
while(IDirectInputDevice8_Acquire(paddevice[i].lpDIDevice) == DIERR_INPUTLOST) {}
continue;
}
}
size = 8;
// Poll events
if (FAILED(IDirectInputDevice8_GetDeviceData(paddevice[i].lpDIDevice,
sizeof(DIDEVICEOBJECTDATA), didod, &size, 0)))
{
if (hr == DIERR_INPUTLOST || hr == DIERR_NOTACQUIRED)
{
// Make sure device is acquired
while(IDirectInputDevice8_Acquire(paddevice[i].lpDIDevice) == DIERR_INPUTLOST) {}
continue;
}
}
if (size == 0)
continue;
switch (paddevice[i].type)
{
case TYPE_KEYBOARD:
// This probably could be optimized
for (i2 = 0; i2 < size; i2++)
{
if (didod[i2].dwData & 0x80)
PerKeyDown(didod[i2].dwOfs);
else
PerKeyUp(didod[i2].dwOfs);
}
break;
case TYPE_JOYSTICK:
{
// This probably could be optimized
for (i2 = 0; i2 < size; i2++)
{
// X Axis
if (didod[i2].dwOfs == DIJOFS_X)
{
if (didod[i2].dwData < 0x3FFF)
{
PerKeyDown(PAD_DIR_AXISLEFT);
PerKeyUp(PAD_DIR_AXISRIGHT);
}
else if (didod[i2].dwData > 0xBFFF)
{
PerKeyDown(PAD_DIR_AXISRIGHT);
PerKeyUp(PAD_DIR_AXISLEFT);
}
else
{
PerKeyUp(PAD_DIR_AXISLEFT);
PerKeyUp(PAD_DIR_AXISRIGHT);
}
}
// Y Axis
else if (didod[i2].dwOfs == DIJOFS_Y)
{
if (didod[i2].dwData < 0x3FFF)
{
PerKeyDown(PAD_DIR_AXISUP);
PerKeyUp(PAD_DIR_AXISDOWN);
}
else if (didod[i2].dwData > 0xBFFF)
{
PerKeyDown(PAD_DIR_AXISDOWN);
PerKeyUp(PAD_DIR_AXISUP);
}
else
{
PerKeyUp(PAD_DIR_AXISUP);
PerKeyUp(PAD_DIR_AXISDOWN);
}
}
else if (didod[i2].dwOfs == DIJOFS_POV(0))
{
// POV Center
if (LOWORD(didod[i2].dwData) == 0xFFFF)
{
PerKeyUp(PAD_DIR_POVUP);
PerKeyUp(PAD_DIR_POVRIGHT);
PerKeyUp(PAD_DIR_POVDOWN);
PerKeyUp(PAD_DIR_POVLEFT);
}
// POV Up
else if (didod[i2].dwData < 4500)
{
PerKeyDown(PAD_DIR_POVUP);
PerKeyUp(PAD_DIR_POVRIGHT);
PerKeyUp(PAD_DIR_POVLEFT);
}
// POV Up-right
else if (didod[i2].dwData < 9000)
{
PerKeyDown(PAD_DIR_POVUP);
PerKeyDown(PAD_DIR_POVRIGHT);
}
// POV Right
else if (didod[i2].dwData < 13500)
{
PerKeyDown(PAD_DIR_POVRIGHT);
PerKeyUp(PAD_DIR_POVDOWN);
PerKeyUp(PAD_DIR_POVUP);
}
// POV Right-down
else if (didod[i2].dwData < 18000)
{
PerKeyDown(PAD_DIR_POVRIGHT);
PerKeyDown(PAD_DIR_POVDOWN);
}
// POV Down
else if (didod[i2].dwData < 22500)
{
PerKeyDown(PAD_DIR_POVDOWN);
PerKeyUp(PAD_DIR_POVLEFT);
PerKeyUp(PAD_DIR_POVRIGHT);
}
// POV Down-left
else if (didod[i2].dwData < 27000)
{
PerKeyDown(PAD_DIR_POVDOWN);
PerKeyDown(PAD_DIR_POVLEFT);
}
// POV Left
else if (didod[i2].dwData < 31500)
{
PerKeyDown(PAD_DIR_POVLEFT);
PerKeyUp(PAD_DIR_POVUP);
PerKeyUp(PAD_DIR_POVDOWN);
}
// POV Left-up
else if (didod[i2].dwData < 36000)
{
PerKeyDown(PAD_DIR_POVLEFT);
PerKeyDown(PAD_DIR_POVUP);
}
}
else if (didod[i2].dwOfs >= DIJOFS_BUTTON(0) && didod[i2].dwOfs <= DIJOFS_BUTTON(127))
{
if (didod[i2].dwData & 0x80)
PerKeyDown(didod[i2].dwOfs);
else
PerKeyUp(didod[i2].dwOfs);
}
}
break;
}
case TYPE_MOUSE:
for (i2 = 0; i2 < size; i2++)
{
if (didod[i2].dwOfs == DIMOFS_X)
// X Axis
PerMouseMove((PerMouse_struct *)pad[i], (s32)didod[i2].dwData, 0);
else if (didod[i2].dwOfs == DIMOFS_Y)
// Y Axis
PerMouseMove((PerMouse_struct *)pad[i], 0, 0-(s32)didod[i2].dwData);
else if (didod[i2].dwOfs >= DIMOFS_BUTTON0 && didod[i2].dwOfs <= DIMOFS_BUTTON7)
{
// Mouse Buttons
if (didod[i2].dwData & 0x80)
PerKeyDown(didod[i2].dwOfs-DIMOFS_BUTTON0);
else
PerKeyUp(didod[i2].dwOfs-DIMOFS_BUTTON0);
}
}
break;
default: break;
}
}
}
//////////////////////////////////////////////////////////////////////////////
int PERDXHandleEvents(void)
{
PollKeys();
if (YabauseExec() != 0)
return -1;
return 0;
}
//////////////////////////////////////////////////////////////////////////////
BOOL CALLBACK EnumPeripheralsCallbackGamepad (LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef)
{
if (GET_DIDEVICE_TYPE(lpddi->dwDevType) == DI8DEVTYPE_GAMEPAD ||
GET_DIDEVICE_TYPE(lpddi->dwDevType) == DI8DEVTYPE_JOYSTICK ||
GET_DIDEVICE_TYPE(lpddi->dwDevType) == DI8DEVTYPE_KEYBOARD)
{
SendMessage((HWND)pvRef, CB_ADDSTRING, 0, (LPARAM)lpddi->tszInstanceName);
memcpy(&GUIDDevice[numguids], &lpddi->guidInstance, sizeof(GUID));
numguids++;
}
return DIENUM_CONTINUE;
}
//////////////////////////////////////////////////////////////////////////////
BOOL CALLBACK EnumPeripheralsCallbackKeyboard (LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef)
{
if (GET_DIDEVICE_TYPE(lpddi->dwDevType) == DI8DEVTYPE_KEYBOARD)
{
SendMessage((HWND)pvRef, CB_ADDSTRING, 0, (LPARAM)lpddi->tszInstanceName);
memcpy(&GUIDDevice[numguids], &lpddi->guidInstance, sizeof(GUID));
numguids++;
}
return DIENUM_CONTINUE;
}
//////////////////////////////////////////////////////////////////////////////
BOOL CALLBACK EnumPeripheralsCallbackMouse (LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef)
{
if (GET_DIDEVICE_TYPE(lpddi->dwDevType) == DI8DEVTYPE_MOUSE)
{
SendMessage((HWND)pvRef, CB_ADDSTRING, 0, (LPARAM)lpddi->tszInstanceName);
memcpy(&GUIDDevice[numguids], &lpddi->guidInstance, sizeof(GUID));
numguids++;
}
return DIENUM_CONTINUE;
}
//////////////////////////////////////////////////////////////////////////////
void PERDXListDevices(HWND control, int emulatetype)
{
LPDIRECTINPUT8 lpDI8temp = NULL;
if (FAILED(DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION,
&IID_IDirectInput8, (LPVOID *)&lpDI8temp, NULL)))
return;
numguids = 0;
SendMessage(control, CB_RESETCONTENT, 0, 0);
SendMessage(control, CB_ADDSTRING, 0, (LPARAM)_16("None"));
switch(emulatetype)
{
case EMUTYPE_STANDARDPAD:
case EMUTYPE_ANALOGPAD:
IDirectInput8_EnumDevices(lpDI8temp, DI8DEVCLASS_ALL, EnumPeripheralsCallbackGamepad,
(LPVOID)control, DIEDFL_ATTACHEDONLY);
break;
case EMUTYPE_STUNNER:
case EMUTYPE_MOUSE:
IDirectInput8_EnumDevices(lpDI8temp, DI8DEVCLASS_ALL, EnumPeripheralsCallbackMouse,
(LPVOID)control, DIEDFL_ATTACHEDONLY);
break;
case EMUTYPE_KEYBOARD:
IDirectInput8_EnumDevices(lpDI8temp, DI8DEVCLASS_ALL, EnumPeripheralsCallbackKeyboard,
(LPVOID)control, DIEDFL_ATTACHEDONLY);
break;
default: break;
}
IDirectInput8_Release(lpDI8temp);
}
//////////////////////////////////////////////////////////////////////////////
void ConvertKBIDToName(int buttonid, char *string)
{
memset(string, 0, MAX_PATH);
// This fixes some strange inconsistencies
if (buttonid == DIK_PAUSE)
buttonid = DIK_NUMLOCK;
else if (buttonid == DIK_NUMLOCK)
buttonid = DIK_PAUSE;
if (buttonid & 0x80)
buttonid += 0x80;
GetKeyNameTextA(buttonid << 16, string, MAX_PATH);
}
//////////////////////////////////////////////////////////////////////////////
void ConvertJoyIDToName(int buttonid, char *string)
{
switch (buttonid)
{
case 0x00:
sprintf(string, "Axis Left");
break;
case 0x01:
sprintf(string, "Axis Right");
break;
case 0x02:
sprintf(string, "Axis Up");
break;
case 0x03:
sprintf(string, "Axis Down");
break;
case 0x04:
sprintf(string, "POV Up");
break;
case 0x05:
sprintf(string, "POV Right");
break;
case 0x06:
sprintf(string, "POV Down");
break;
case 0x07:
sprintf(string, "POV Left");
break;
default:
if (buttonid >= 0x30)
sprintf(string, "Button %d", buttonid - 0x2F);
break;
}
}
//////////////////////////////////////////////////////////////////////////////
void ConvertMouseIDToName(int buttonid, char *string)
{
sprintf(string, "Button %d", buttonid+1);
}
//////////////////////////////////////////////////////////////////////////////
int PERDXInitControlConfig(HWND hWnd, u8 padnum, int *controlmap, const char *inifilename)
{
char tempstr[MAX_PATH];
char string1[20];
GUID guid;
u32 i;
int idlist[] = { IDC_UPTEXT, IDC_RIGHTTEXT, IDC_DOWNTEXT, IDC_LEFTTEXT,
IDC_RTEXT, IDC_LTEXT, IDC_STARTTEXT,
IDC_ATEXT, IDC_BTEXT, IDC_CTEXT,
IDC_XTEXT, IDC_YTEXT, IDC_ZTEXT
};
sprintf(string1, "Peripheral%d%C", ((padnum/6)+1), 'A'+(padnum%6));
// Let's first fetch the guid of the device and see if we can get a match
if (GetPrivateProfileStringA(string1, "GUID", "", tempstr, MAX_PATH, inifilename) == 0)
{
if (padnum == 0)
{
// Let's use default values
SendDlgItemMessage(hWnd, IDC_DXDEVICECB, CB_SETCURSEL, 1, 0);
controlmap[0] = DIK_UP;
controlmap[1] = DIK_RIGHT;
controlmap[2] = DIK_DOWN;
controlmap[3] = DIK_LEFT;
controlmap[4] = DIK_Z;
controlmap[5] = DIK_X;
controlmap[6] = DIK_J;
controlmap[7] = DIK_K;
controlmap[8] = DIK_L;
controlmap[9] = DIK_M;
controlmap[10] = DIK_U;
controlmap[11] = DIK_I;
controlmap[12] = DIK_O;
for (i = 0; i < 13; i++)
{
ConvertKBIDToName(controlmap[i], tempstr);
SetDlgItemText(hWnd, idlist[i], _16(tempstr));
}
}
else
{
SendDlgItemMessage(hWnd, IDC_DXDEVICECB, CB_SETCURSEL, 0, 0);
return -1;
}
}
else
{
LPDIRECTINPUT8 lpDI8temp = NULL;
LPDIRECTINPUTDEVICE8 lpDIDevicetemp;
DIDEVCAPS didc;
int buttonid;
StringToGUID(tempstr, &guid);
// Let's find a match
for (i = 0; i < numguids; i++)
{
if (memcmp(&guid, &GUIDDevice[i], sizeof(GUID)) == 0)
{
SendDlgItemMessage(hWnd, IDC_DXDEVICECB, CB_SETCURSEL, i+1, 0);
break;
}
}
if (FAILED(DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION,
&IID_IDirectInput8, (LPVOID *)&lpDI8temp, NULL)))
return -1;
if (FAILED(IDirectInput8_CreateDevice(lpDI8temp, &GUIDDevice[i], &lpDIDevicetemp,
NULL)))
{
IDirectInput8_Release(lpDI8temp);
return -1;
}
didc.dwSize = sizeof(DIDEVCAPS);
if (FAILED(IDirectInputDevice8_GetCapabilities(lpDIDevicetemp, &didc)))
{
IDirectInputDevice8_Release(lpDIDevicetemp);
IDirectInput8_Release(lpDI8temp);
return -1;
}
if (GET_DIDEVICE_TYPE(didc.dwDevType) == DI8DEVTYPE_KEYBOARD)
{
sprintf(string1, "Peripheral%d%C", ((padnum/6)+1), 'A'+(padnum%6));
for (i = 0; i < 13; i++)
{
buttonid = GetPrivateProfileIntA(string1, PerPadNames[i], 0, inifilename);
printf("%2d: %d\n", i, buttonid);
controlmap[i] = buttonid;
ConvertKBIDToName(buttonid, tempstr);
SetDlgItemText(hWnd, idlist[i], _16(tempstr));
}
}
else if (GET_DIDEVICE_TYPE(didc.dwDevType) == DI8DEVTYPE_GAMEPAD ||
GET_DIDEVICE_TYPE(didc.dwDevType) == DI8DEVTYPE_JOYSTICK)
{
sprintf(string1, "Peripheral%d%C", ((padnum/6)+1), 'A'+(padnum%6));
for (i = 0; i < 13; i++)
{
buttonid = GetPrivateProfileIntA(string1, PerPadNames[i], 0, inifilename);
controlmap[i] = buttonid;
ConvertJoyIDToName(buttonid, tempstr);
SetDlgItemText(hWnd, idlist[i], _16(tempstr));
}
}
else if (GET_DIDEVICE_TYPE(didc.dwDevType) == DI8DEVTYPE_MOUSE)
{
for (i = 0; i < 13; i++)
{
buttonid = GetPrivateProfileIntA(string1, PerPadNames[i], 0, inifilename);
controlmap[i] = buttonid;
ConvertMouseIDToName(buttonid, tempstr);
SetDlgItemText(hWnd, idlist[i], _16(tempstr));
}
}
IDirectInputDevice8_Release(lpDIDevicetemp);
IDirectInput8_Release(lpDI8temp);
}
return 0;
}
//////////////////////////////////////////////////////////////////////////////
DIDEVICEOBJECTDATA nextpress;
int PERDXFetchNextPress(HWND hWnd, u32 guidnum, char *buttonname)
{
LPDIRECTINPUT8 lpDI8temp = NULL;
LPDIRECTINPUTDEVICE8 lpDIDevicetemp;
DIDEVCAPS didc;
int buttonid=-1;
if (FAILED(DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION,
&IID_IDirectInput8, (LPVOID *)&lpDI8temp, NULL)))
return -1;
if (FAILED(IDirectInput8_CreateDevice(lpDI8temp, &GUIDDevice[guidnum], &lpDIDevicetemp,
NULL)))
{
IDirectInput8_Release(lpDI8temp);
return -1;
}
didc.dwSize = sizeof(DIDEVCAPS);
if (FAILED(IDirectInputDevice8_GetCapabilities(lpDIDevicetemp, &didc)))
{
IDirectInputDevice8_Release(lpDIDevicetemp);
IDirectInput8_Release(lpDI8temp);
return -1;
}
if (GET_DIDEVICE_TYPE(didc.dwDevType) == DI8DEVTYPE_KEYBOARD)
{
if (FAILED(IDirectInputDevice8_SetDataFormat(lpDIDevicetemp, &c_dfDIKeyboard)))
{
IDirectInputDevice8_Release(lpDIDevicetemp);
IDirectInput8_Release(lpDI8temp);
return -1;
}
}
else if (GET_DIDEVICE_TYPE(didc.dwDevType) == DI8DEVTYPE_GAMEPAD ||
GET_DIDEVICE_TYPE(didc.dwDevType) == DI8DEVTYPE_JOYSTICK)
{
if (FAILED(IDirectInputDevice8_SetDataFormat(lpDIDevicetemp, &c_dfDIJoystick)))
{
IDirectInputDevice8_Release(lpDIDevicetemp);
IDirectInput8_Release(lpDI8temp);
return -1;
}
}
else if (GET_DIDEVICE_TYPE(didc.dwDevType) == DI8DEVTYPE_MOUSE)
{
if (FAILED(IDirectInputDevice8_SetDataFormat(lpDIDevicetemp, &c_dfDIMouse2)))
{
IDirectInputDevice8_Release(lpDIDevicetemp);
IDirectInput8_Release(lpDI8temp);
return -1;
}
}
if (DialogBoxParam(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_BUTTONCONFIG), hWnd, (DLGPROC)ButtonConfigDlgProc, (LPARAM)lpDIDevicetemp) == TRUE)
{
// Figure out what kind of code to generate
if (GET_DIDEVICE_TYPE(didc.dwDevType) == DI8DEVTYPE_KEYBOARD)
{
memset(buttonname, 0, MAX_PATH);
buttonid = nextpress.dwOfs;
// This fixes some strange inconsistencies
if (buttonid == DIK_PAUSE)
buttonid = DIK_NUMLOCK;
else if (buttonid == DIK_NUMLOCK)
buttonid = DIK_PAUSE;
if (buttonid & 0x80)
buttonid += 0x80;
GetKeyNameTextA(buttonid << 16, buttonname, MAX_PATH);
buttonid = nextpress.dwOfs;
}
else if (GET_DIDEVICE_TYPE(didc.dwDevType) == DI8DEVTYPE_GAMEPAD ||
GET_DIDEVICE_TYPE(didc.dwDevType) == DI8DEVTYPE_JOYSTICK)
{
if (nextpress.dwOfs == DIJOFS_X)
{
if (nextpress.dwData <= 0x8000)
{
sprintf(buttonname, "Axis Left");
buttonid = 0x00;
}
else
{
sprintf(buttonname, "Axis Right");
buttonid = 0x01;
}
}
else if (nextpress.dwOfs == DIJOFS_Y)
{
if (nextpress.dwData <= 0x8000)
{
sprintf(buttonname, "Axis Up");
buttonid = 0x02;
}
else
{
sprintf(buttonname, "Axis Down");
buttonid = 0x03;
}
}
else if (nextpress.dwOfs == DIJOFS_POV(0))
{
if (nextpress.dwData < 9000)
{
sprintf(buttonname, "POV Up");
buttonid = 0x04;
}
else if (nextpress.dwData < 18000)
{
sprintf(buttonname, "POV Right");
buttonid = 0x05;
}
else if (nextpress.dwData < 27000)
{
sprintf(buttonname, "POV Down");
buttonid = 0x06;
}
else
{
sprintf(buttonname, "POV Left");
buttonid = 0x07;
}
}
else if (nextpress.dwOfs >= DIJOFS_BUTTON(0) && nextpress.dwOfs <= DIJOFS_BUTTON(127))
{
sprintf(buttonname, "Button %d", (int)(nextpress.dwOfs - 0x2F));
buttonid = nextpress.dwOfs;
}
}
else if (GET_DIDEVICE_TYPE(didc.dwDevType) == DI8DEVTYPE_MOUSE)
{
buttonid = nextpress.dwOfs-DIMOFS_BUTTON0;
sprintf(buttonname, "Button %d", buttonid+1);
}
}
IDirectInputDevice8_Unacquire(lpDIDevicetemp);
IDirectInputDevice8_Release(lpDIDevicetemp);
IDirectInput8_Release(lpDI8temp);
return buttonid;
}
//////////////////////////////////////////////////////////////////////////////
HHOOK hook;
LRESULT CALLBACK KeyboardHook(int code, WPARAM wParam, LPARAM lParam)
{
if (code >= HC_ACTION)
return TRUE;
return CallNextHookEx(hook, code, wParam, lParam);
}
//////////////////////////////////////////////////////////////////////////////
LRESULT CALLBACK ButtonConfigDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam,
LPARAM lParam)
{
static LPDIRECTINPUTDEVICE8 lpDIDevicetemp;
DIPROPDWORD dipdw;
HRESULT hr;
DWORD size;
DIDEVICEOBJECTDATA didod[8];
DWORD i;
DIDEVCAPS didc;
switch (uMsg)
{
case WM_INITDIALOG:
{
lpDIDevicetemp = (LPDIRECTINPUTDEVICE8)lParam;
if (FAILED(IDirectInputDevice8_SetCooperativeLevel(lpDIDevicetemp, hDlg,
DISCL_FOREGROUND | DISCL_NONEXCLUSIVE | DISCL_NOWINKEY)))
return FALSE;
dipdw.diph.dwSize = sizeof(DIPROPDWORD);
dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
dipdw.diph.dwObj = 0;
dipdw.diph.dwHow = DIPH_DEVICE;
dipdw.dwData = 8; // should be enough
// Setup Buffered input
if (FAILED((hr = IDirectInputDevice8_SetProperty(lpDIDevicetemp, DIPROP_BUFFERSIZE, &dipdw.diph))))
return FALSE;
if (!SetTimer(hDlg, 1, 100, NULL))
return FALSE;
PostMessage(hDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hDlg, IDC_WAITINPUT), TRUE);
hook = SetWindowsHookEx(WH_KEYBOARD, KeyboardHook, GetModuleHandle(NULL), GetCurrentThreadId());
return TRUE;
}
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case IDC_CUSTOMCANCEL:
{
EndDialog(hDlg, FALSE);
return TRUE;
}
default: break;
}
break;
}
case WM_TIMER:
{
size = 8;
if (wParam == 1)
{
memset(&didod, 0, sizeof(DIDEVICEOBJECTDATA) * 8);
// Let's see if there's any data waiting
hr = IDirectInputDevice8_Poll(lpDIDevicetemp);
if (FAILED(hr))
{
if (hr == DIERR_INPUTLOST || hr == DIERR_NOTACQUIRED)
{
// Make sure device is acquired
while(IDirectInputDevice8_Acquire(lpDIDevicetemp) == DIERR_INPUTLOST) {}
return TRUE;
}
}
// Poll events
if (FAILED(IDirectInputDevice8_GetDeviceData(lpDIDevicetemp,
sizeof(DIDEVICEOBJECTDATA), didod, &size, 0)))
{
if (hr == DIERR_INPUTLOST || hr == DIERR_NOTACQUIRED)
{
// Make sure device is acquired
while(IDirectInputDevice8_Acquire(lpDIDevicetemp) == DIERR_INPUTLOST) {}
return TRUE;
}
}
didc.dwSize = sizeof(DIDEVCAPS);
if (FAILED(IDirectInputDevice8_GetCapabilities(lpDIDevicetemp, &didc)))
return TRUE;
if (GET_DIDEVICE_TYPE(didc.dwDevType) == DI8DEVTYPE_KEYBOARD)
{
for (i = 0; i < size; i++)
{
if (didod[i].dwData & 0x80)
{
// We're done. time to bail
EndDialog(hDlg, TRUE);
memcpy(&nextpress, &didod[i], sizeof(DIDEVICEOBJECTDATA));
break;
}
}
}
else if (GET_DIDEVICE_TYPE(didc.dwDevType) == DI8DEVTYPE_GAMEPAD ||
GET_DIDEVICE_TYPE(didc.dwDevType) == DI8DEVTYPE_JOYSTICK)
{
for (i = 0; i < size; i++)
{
if (didod[i].dwOfs == 0 ||
didod[i].dwOfs == 4)
{
if (didod[i].dwData <= 0x1000 ||
didod[i].dwData >= 0xF000)
{
// We're done. time to bail
EndDialog(hDlg, TRUE);
memcpy(&nextpress, &didod[i], sizeof(DIDEVICEOBJECTDATA));
break;
}
}
else if (didod[i].dwOfs == 0x20)
{
if (((int)didod[i].dwData) >= 0)
{
// We're done. time to bail
EndDialog(hDlg, TRUE);
memcpy(&nextpress, &didod[i], sizeof(DIDEVICEOBJECTDATA));
}
}
else if (didod[i].dwOfs >= 0x30)
{
if (didod[i].dwData & 0x80)
{
// We're done. time to bail
EndDialog(hDlg, TRUE);
memcpy(&nextpress, &didod[i], sizeof(DIDEVICEOBJECTDATA));
break;
}
}
}
}
else if (GET_DIDEVICE_TYPE(didc.dwDevType) == DI8DEVTYPE_MOUSE)
{
for (i = 0; i < size; i++)
{
// Make sure it's a button press
if (didod[i].dwOfs >= DIMOFS_BUTTON0 && didod[i].dwOfs <= DIMOFS_BUTTON7)
{
if (didod[i].dwData & 0x80)
{
EndDialog(hDlg, TRUE);
memcpy(&nextpress, &didod[i], sizeof(DIDEVICEOBJECTDATA));
break;
}
}
}
}
return TRUE;
}
return FALSE;
}
case WM_DESTROY:
{
KillTimer(hDlg, 1);
UnhookWindowsHookEx(hook);
break;
}
}
return FALSE;
}
//////////////////////////////////////////////////////////////////////////////
BOOL PERDXWriteGUID(u32 guidnum, u8 padnum, LPCSTR inifilename)
{
char string1[20];
char string2[40];
sprintf(string1, "Peripheral%d%C", ((padnum/6)+1), 'A'+(padnum%6));
sprintf(string2, "%08X-%04X-%04X-%02X%02X%02X%02X%02X%02X%02X%02X", (int)GUIDDevice[guidnum].Data1, (int)GUIDDevice[guidnum].Data2, (int)GUIDDevice[guidnum].Data3, (int)GUIDDevice[guidnum].Data4[0], (int)GUIDDevice[guidnum].Data4[1], (int)GUIDDevice[guidnum].Data4[2], (int)GUIDDevice[guidnum].Data4[3], (int)GUIDDevice[guidnum].Data4[4], (int)GUIDDevice[guidnum].Data4[5], (int)GUIDDevice[guidnum].Data4[6], (int)GUIDDevice[guidnum].Data4[7]);
return WritePrivateProfileStringA(string1, "GUID", string2, inifilename);
}
//////////////////////////////////////////////////////////////////////////////