forked from sin365/AxibugEmuOnline
481 lines
26 KiB
C++
481 lines
26 KiB
C++
//
|
||
// DirectInput class
|
||
//
|
||
#include "DebugOut.h"
|
||
#include "DirectInput.h"
|
||
#include "COM.h"
|
||
#include "Config.h"
|
||
|
||
CDirectInput DirectInput;
|
||
|
||
#define COMUSE TRUE
|
||
|
||
//
|
||
// Table
|
||
//
|
||
CDirectInput::DIKEYTBL CDirectInput::DIKeyTable[] = {
|
||
DIK_ESCAPE, "ESC", DIK_1, "1",
|
||
DIK_2, "2", DIK_3, "3",
|
||
DIK_4, "4", DIK_5, "5",
|
||
DIK_6, "6", DIK_7, "7",
|
||
DIK_8, "8", DIK_9, "9",
|
||
DIK_0, "0", DIK_MINUS, "-",
|
||
DIK_EQUALS, "=", DIK_BACK, "BackSpace",
|
||
DIK_TAB, "TAB", DIK_Q, "Q",
|
||
DIK_W, "W", DIK_E, "E",
|
||
DIK_R, "R", DIK_T, "T",
|
||
DIK_Y, "Y", DIK_U, "U",
|
||
DIK_I, "I", DIK_O, "O",
|
||
DIK_P, "P", DIK_LBRACKET, "[",
|
||
DIK_RBRACKET, "]", DIK_RETURN, "Enter",
|
||
DIK_LCONTROL, "L Ctrl", DIK_A, "A",
|
||
DIK_S, "S", DIK_D, "D",
|
||
DIK_F, "F", DIK_G, "G",
|
||
DIK_H, "H", DIK_J, "J",
|
||
DIK_K, "K", DIK_L, "L",
|
||
DIK_SEMICOLON, ";", DIK_APOSTROPHE, "'",
|
||
DIK_GRAVE, "`", DIK_LSHIFT, "L Shift",
|
||
DIK_BACKSLASH, "\\", DIK_Z, "Z",
|
||
DIK_X, "X", DIK_C, "C",
|
||
DIK_V, "V", DIK_B, "B",
|
||
DIK_N, "N", DIK_M, "M",
|
||
DIK_COMMA, ",", DIK_PERIOD, ".",
|
||
DIK_SLASH, "/", DIK_RSHIFT, "R Shift",
|
||
DIK_MULTIPLY, "*", DIK_LMENU, "L Alt",
|
||
DIK_SPACE, "Space",
|
||
DIK_F1, "F1", DIK_F2, "F2",
|
||
DIK_F3, "F3", DIK_F4, "F4",
|
||
DIK_F5, "F5", DIK_F6, "F6",
|
||
DIK_F7, "F7", DIK_F8, "F8",
|
||
DIK_F9, "F9", DIK_F10, "F10",
|
||
|
||
DIK_NUMPAD7, "Num 7", DIK_NUMPAD8, "Num 8",
|
||
DIK_NUMPAD9, "Num 9", DIK_SUBTRACT, "Num -",
|
||
DIK_NUMPAD4, "Num 4", DIK_NUMPAD5, "Num 5",
|
||
DIK_NUMPAD6, "Num 6", DIK_ADD, "Num +",
|
||
DIK_NUMPAD1, "Num 1", DIK_NUMPAD2, "Num 2",
|
||
DIK_NUMPAD3, "Num 3", DIK_NUMPAD0, "Num 0",
|
||
DIK_DECIMAL, "Num .", DIK_F11, "F11",
|
||
DIK_F12, "F12", DIK_F13, "F13",
|
||
DIK_F14, "F14", DIK_F15, "F15",
|
||
DIK_CONVERT, "変換",
|
||
DIK_NOCONVERT, "無変換", DIK_YEN, "\\",
|
||
DIK_NUMPADEQUALS,"Num =", DIK_CIRCUMFLEX, "^",
|
||
DIK_AT, "@", DIK_COLON, ":",
|
||
DIK_UNDERLINE, "_",
|
||
DIK_STOP, "Stop", DIK_NUMPADENTER,"Num Enter",
|
||
DIK_RCONTROL, "R Ctrl", DIK_NUMPADCOMMA,"Num ,",
|
||
DIK_DIVIDE, "Num /", DIK_SYSRQ, "SysRq",
|
||
DIK_RMENU, "R Alt", DIK_PAUSE, "Pause",
|
||
DIK_HOME, "Home", DIK_UP, "Up",
|
||
DIK_PRIOR, "Page Up", DIK_LEFT, "Left",
|
||
DIK_RIGHT, "Right", DIK_END, "End",
|
||
DIK_DOWN, "Down", DIK_NEXT, "Page Down",
|
||
DIK_INSERT, "Insert", DIK_DELETE, "Delete",
|
||
DIK_LWIN, "L Windows", DIK_LWIN, "R Windows",
|
||
DIK_APPS, "AppMenu",
|
||
|
||
#if 0
|
||
// トグル系キーなので使えない
|
||
DIK_CAPITAL, "Caps Lock",
|
||
DIK_NUMLOCK, "NumLock",
|
||
DIK_SCROLL, "ScrollLock",
|
||
DIK_KANA, "カナ",
|
||
DIK_KANJI, "漢字",
|
||
#endif
|
||
0x00, NULL
|
||
};
|
||
|
||
LPSTR CDirectInput::DIKeyDirTable[] = {
|
||
"X+", "X-", "Y+", "Y-", "Z+", "Z-",
|
||
"RX+", "RX-", "RY+", "RY-", "RZ+", "RZ-",
|
||
"S0+", "S0-", "S1+", "S1-",
|
||
};
|
||
|
||
LPSTR CDirectInput::DIKeyDirTable2[] = {
|
||
"P0 Up", "P0 Down", "P0 Left", "P0 Right",
|
||
"P1 Up", "P1 Down", "P1 Left", "P1 Right",
|
||
"P2 Up", "P2 Down", "P2 Left", "P2 Right",
|
||
"P3 Up", "P3 Down", "P3 Left", "P3 Right",
|
||
};
|
||
|
||
//////////////////////////////////////////////////////////////////////
|
||
// 構築/消滅
|
||
//////////////////////////////////////////////////////////////////////
|
||
|
||
CDirectInput::CDirectInput()
|
||
{
|
||
m_lpDI = NULL;
|
||
m_lpKeyboard = NULL;
|
||
|
||
m_nJoystickNum = 0;
|
||
|
||
ZEROMEMORY( m_lpJoystick, sizeof(m_lpJoystick) );
|
||
ZEROMEMORY( m_Sw, sizeof(m_Sw) );
|
||
|
||
ZEROMEMORY( m_JoyAxisMode, sizeof(m_JoyAxisMode) );
|
||
|
||
#if COMUSE
|
||
COM::AddRef();
|
||
#endif
|
||
}
|
||
|
||
CDirectInput::~CDirectInput()
|
||
{
|
||
ReleaseDInput();
|
||
|
||
#if COMUSE
|
||
COM::AddRef();
|
||
#endif
|
||
}
|
||
|
||
//////////////////////////////////////////////////////////////////////
|
||
// メンバ関数
|
||
//////////////////////////////////////////////////////////////////////
|
||
// デバイスオブジェクト列挙コールバック
|
||
BOOL CALLBACK CDirectInput::DIEnumDevicesCallback( LPDIDEVICEINSTANCE lpddi, LPVOID pvRef )
|
||
{
|
||
CDirectInput* pCDi = (CDirectInput*)pvRef;
|
||
|
||
// DEBUGOUT( "dwDevType=%08X IName:%s PName:%s\n", lpddi->dwDevType, lpddi->tszInstanceName, lpddi->tszProductName );
|
||
|
||
if( pCDi->AddJoystickDevice( lpddi->guidInstance ) )
|
||
return DIENUM_CONTINUE;
|
||
|
||
return DIENUM_STOP;
|
||
}
|
||
|
||
// ジョイスティックデバイスオブジェクトの作成
|
||
BOOL CDirectInput::AddJoystickDevice( GUID deviceguid )
|
||
{
|
||
LPDIRECTINPUTDEVICE7 lpDIDev;
|
||
|
||
if( m_lpDI->CreateDeviceEx( deviceguid, IID_IDirectInputDevice7,
|
||
(LPVOID*)&lpDIDev, NULL ) != DI_OK ) {
|
||
return FALSE;
|
||
}
|
||
|
||
if( lpDIDev->SetDataFormat( &c_dfDIJoystick ) != DI_OK ) {
|
||
DEBUGOUT( "CDirectInput:SetDataFormat failed.\n" );
|
||
RELEASE( lpDIDev );
|
||
return FALSE;
|
||
}
|
||
|
||
INT nID = m_nJoystickNum;
|
||
|
||
if( !Config.general.bNoJoystickID ) {
|
||
// DX7では隠し要素のジョイスティックIDの取得(DX8からはマニュアルに記載されている)
|
||
DIPROPDWORD diprp_dw;
|
||
ZEROMEMORY( &diprp_dw, sizeof(diprp_dw) );
|
||
diprp_dw.diph.dwSize = sizeof(DIPROPDWORD);
|
||
diprp_dw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
|
||
diprp_dw.diph.dwHow = DIPH_DEVICE;
|
||
diprp_dw.diph.dwObj = 0;
|
||
|
||
if( lpDIDev->GetProperty( DIPROP_JOYSTICKID, &diprp_dw.diph ) != DI_OK ) {
|
||
DEBUGOUT( "CDirectInput:GetProperty failed.\n" );
|
||
RELEASE( lpDIDev );
|
||
return FALSE;
|
||
}
|
||
DEBUGOUT( "ID:%d\n", diprp_dw.dwData );
|
||
|
||
nID = diprp_dw.dwData;
|
||
}
|
||
|
||
if( nID < DIJOYSTICK_MAX ) {
|
||
m_lpJoystick[ nID ] = lpDIDev;
|
||
|
||
// 各軸のレンジを設定
|
||
DIPROPRANGE diprg;
|
||
diprg.diph.dwSize = sizeof(DIPROPRANGE);
|
||
diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER);
|
||
diprg.diph.dwHow = DIPH_BYOFFSET;
|
||
diprg.diph.dwObj = DIJOFS_X;
|
||
diprg.lMin = -10000;
|
||
diprg.lMax = +10000;
|
||
lpDIDev->SetProperty( DIPROP_RANGE, &diprg.diph );
|
||
diprg.diph.dwObj = DIJOFS_Y;
|
||
lpDIDev->SetProperty( DIPROP_RANGE, &diprg.diph );
|
||
diprg.diph.dwObj = DIJOFS_Z;
|
||
lpDIDev->SetProperty( DIPROP_RANGE, &diprg.diph );
|
||
diprg.diph.dwObj = DIJOFS_RX;
|
||
lpDIDev->SetProperty( DIPROP_RANGE, &diprg.diph );
|
||
diprg.diph.dwObj = DIJOFS_RY;
|
||
lpDIDev->SetProperty( DIPROP_RANGE, &diprg.diph );
|
||
diprg.diph.dwObj = DIJOFS_RZ;
|
||
lpDIDev->SetProperty( DIPROP_RANGE, &diprg.diph );
|
||
|
||
diprg.diph.dwObj = DIJOFS_SLIDER(0);
|
||
lpDIDev->SetProperty( DIPROP_RANGE, &diprg.diph );
|
||
diprg.diph.dwObj = DIJOFS_SLIDER(1);
|
||
lpDIDev->SetProperty( DIPROP_RANGE, &diprg.diph );
|
||
|
||
// 名称の取得
|
||
DIDEVICEINSTANCE didins;
|
||
ZEROMEMORY( &didins, sizeof(didins) );
|
||
didins.dwSize = sizeof( didins );
|
||
lpDIDev->GetDeviceInfo( &didins );
|
||
|
||
m_JoyName[ nID ] = didins.tszInstanceName;
|
||
DEBUGOUT( "Instance Name:%s\n", didins.tszInstanceName );
|
||
//DEBUGOUT( "Product Name:%s\n", didins.tszProductName );
|
||
} else {
|
||
m_lpJoystick[ nID ] = NULL;
|
||
RELEASE( lpDIDev );
|
||
}
|
||
|
||
m_nJoystickNum++;
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
// DirectInputオブジェクト/デバイスオブジェクトの構築
|
||
BOOL CDirectInput::InitialDInput(HWND hWnd, HINSTANCE hInst)
|
||
{
|
||
try {
|
||
// CDirectInputオブジェクトの作成
|
||
#if !COMUSE
|
||
if( DirectInputCreateEx( hInst, DIRECTINPUT_VERSION, IID_IDirectInput7, (LPVOID*)&m_lpDI, NULL ) != DI_OK ) {
|
||
m_lpDI = NULL;
|
||
throw "CDirectInput:DirectInputCreateEx failed.";
|
||
}
|
||
#else
|
||
// COM的利用
|
||
// COM::AddRef();
|
||
if( FAILED(CoCreateInstance( CLSID_DirectInput, NULL, CLSCTX_INPROC_SERVER, IID_IDirectInput7, (VOID**)&m_lpDI )) ) {
|
||
m_lpDI = NULL;
|
||
throw "CDirectInput:CoCreateInstance failed.";
|
||
}
|
||
if( m_lpDI->Initialize( hInst, DIRECTINPUT_VERSION ) != DI_OK )
|
||
throw "CDirectInput:IDirectInput7->Initialize failed.";
|
||
#endif
|
||
|
||
if( m_lpDI->CreateDevice( GUID_SysKeyboard, &m_lpKeyboard, NULL ) != DI_OK )
|
||
throw "CDirectInput:CreateDevice failed.";
|
||
|
||
if( m_lpKeyboard ) {
|
||
if( m_lpKeyboard->SetDataFormat( &c_dfDIKeyboard ) != DI_OK )
|
||
throw "CDirectInput:SetDataFormat failed.";
|
||
if( m_lpKeyboard->SetCooperativeLevel( hWnd, DISCL_NONEXCLUSIVE|DISCL_BACKGROUND) != DI_OK )
|
||
throw "CDirectInput:SetCooperativeLevel failed.";
|
||
if( m_lpKeyboard->Acquire() != DI_OK ) {
|
||
// DEBUGOUT( "CDirectInput:Acquire failed.\n" );
|
||
}
|
||
}
|
||
|
||
m_nJoystickNum = 0;
|
||
if( m_lpDI->EnumDevices( DIDEVTYPE_JOYSTICK, (LPDIENUMDEVICESCALLBACK)DIEnumDevicesCallback,
|
||
(LPVOID)this, DIEDFL_ATTACHEDONLY ) != DI_OK ) {
|
||
DEBUGOUT( "CDirectInput:EnumDevices failed.\n" );
|
||
}
|
||
|
||
if( !m_nJoystickNum ) {
|
||
DEBUGOUT( "CDirectInput:No Joystick device available.\n" );
|
||
} else {
|
||
for( INT i = 0; i < DIJOYSTICK_MAX; i++ ) {
|
||
if( m_lpJoystick[i] ) {
|
||
if( m_lpJoystick[i]->SetCooperativeLevel( hWnd, DISCL_NONEXCLUSIVE|DISCL_BACKGROUND) != DI_OK ) {
|
||
DEBUGOUT( "CDirectInput:SetCooperativeLevel failed.\n" );
|
||
throw "CDirectInput:SetCooperativeLevel failed.";
|
||
}
|
||
}
|
||
}
|
||
|
||
DEBUGOUT( "CDirectInput:Can use %d Joystick(s)\n", m_nJoystickNum );
|
||
}
|
||
} catch( char *str ) {
|
||
ReleaseDInput();
|
||
|
||
MessageBox( hWnd, str, "ERROR", MB_ICONERROR|MB_OK );
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
void CDirectInput::ReleaseDInput()
|
||
{
|
||
for( INT i = 0; i < DIJOYSTICK_MAX; i++ ) {
|
||
RELEASE( m_lpJoystick[i] );
|
||
}
|
||
|
||
if( m_lpKeyboard ) {
|
||
// m_lpKeyboard->Unacquire();
|
||
RELEASE( m_lpKeyboard );
|
||
}
|
||
|
||
if( m_lpDI ) {
|
||
RELEASE( m_lpDI );
|
||
#if COMUSE
|
||
// COM::Release();
|
||
#endif
|
||
}
|
||
}
|
||
|
||
// 入力フォーカスを取得
|
||
void CDirectInput::Acquire()
|
||
{
|
||
if( !m_lpDI )
|
||
return;
|
||
if( m_lpKeyboard )
|
||
m_lpKeyboard->Acquire();
|
||
for( INT i = 0; i < DIJOYSTICK_MAX; i++ ) {
|
||
if( m_lpJoystick[i] ) {
|
||
m_lpJoystick[i]->Acquire();
|
||
}
|
||
}
|
||
}
|
||
|
||
// 入力フォーカスを開放
|
||
void CDirectInput::Unacquire()
|
||
{
|
||
if( !m_lpDI )
|
||
return;
|
||
if( m_lpKeyboard )
|
||
m_lpKeyboard->Unacquire();
|
||
for( INT i = 0; i < DIJOYSTICK_MAX; i++ ) {
|
||
if( m_lpJoystick[i] ) {
|
||
m_lpJoystick[i]->Unacquire();
|
||
}
|
||
}
|
||
}
|
||
|
||
// データポーリング
|
||
void CDirectInput::Poll()
|
||
{
|
||
DIJOYSTATE js;
|
||
|
||
ZEROMEMORY( m_Sw, sizeof(m_Sw) );
|
||
|
||
if( !m_lpDI ) {
|
||
return;
|
||
}
|
||
|
||
if( m_lpKeyboard ) {
|
||
if( m_lpKeyboard->GetDeviceState( 256, &m_Sw ) == DIERR_INPUTLOST ) {
|
||
m_lpKeyboard->Acquire();
|
||
m_lpKeyboard->GetDeviceState( 256, &m_Sw );
|
||
}
|
||
|
||
m_Sw[DIK_LCONTROL] =
|
||
m_Sw[DIK_RCONTROL] = (GetAsyncKeyState( VK_CONTROL ) < 0) ? 0x80 : 0;
|
||
}
|
||
|
||
INT idx;
|
||
for( INT i = 0; i < DIJOYSTICK_MAX; i++ ) {
|
||
if( !m_lpJoystick[i] )
|
||
continue;
|
||
|
||
idx = 256+i*64;
|
||
|
||
if( m_lpJoystick[i]->Poll() == DIERR_INPUTLOST ) {
|
||
m_lpJoystick[i]->Acquire();
|
||
m_lpJoystick[i]->Poll();
|
||
}
|
||
if( m_lpJoystick[i]->GetDeviceState( sizeof(DIJOYSTATE), &js ) != DI_OK ) {
|
||
ZEROMEMORY( &js, sizeof(DIJOYSTATE) );
|
||
}
|
||
|
||
m_JoyAxis[i][0] = js.lX;
|
||
m_JoyAxis[i][1] = js.lY;
|
||
m_JoyAxis[i][2] = js.lZ;
|
||
m_JoyAxis[i][3] = js.lRx;
|
||
m_JoyAxis[i][4] = js.lRy;
|
||
m_JoyAxis[i][5] = js.lRz;
|
||
|
||
if( !(m_JoyAxisMode[i] & (1<<0)) ) {
|
||
if( js.lX > 8000 ) m_Sw[idx + DI_XAXIS+0] = 0x80;
|
||
if( js.lX < -8000 ) m_Sw[idx + DI_XAXIS+1] = 0x80;
|
||
}
|
||
if( !(m_JoyAxisMode[i] & (1<<1)) ) {
|
||
if( js.lY > 8000 ) m_Sw[idx + DI_YAXIS+0] = 0x80;
|
||
if( js.lY < -8000 ) m_Sw[idx + DI_YAXIS+1] = 0x80;
|
||
}
|
||
if( !(m_JoyAxisMode[i] & (1<<2)) ) {
|
||
if( js.lZ > 8000 ) m_Sw[idx + DI_ZAXIS+0] = 0x80;
|
||
if( js.lZ < -8000 ) m_Sw[idx + DI_ZAXIS+1] = 0x80;
|
||
}
|
||
if( !(m_JoyAxisMode[i] & (1<<3)) ) {
|
||
if( js.lRx > 8000 ) m_Sw[idx + DI_RXAXIS+0] = 0x80;
|
||
if( js.lRx < -8000 ) m_Sw[idx + DI_RXAXIS+1] = 0x80;
|
||
}
|
||
if( !(m_JoyAxisMode[i] & (1<<4)) ) {
|
||
if( js.lRy > 8000 ) m_Sw[idx + DI_RYAXIS+0] = 0x80;
|
||
if( js.lRy < -8000 ) m_Sw[idx + DI_RYAXIS+1] = 0x80;
|
||
}
|
||
if( !(m_JoyAxisMode[i] & (1<<5)) ) {
|
||
if( js.lRz > 8000 ) m_Sw[idx + DI_RZAXIS+0] = 0x80;
|
||
if( js.lRz < -8000 ) m_Sw[idx + DI_RZAXIS+1] = 0x80;
|
||
}
|
||
|
||
#if 0
|
||
// 2003/11/3 とりあえず無効化
|
||
if( js.rglSlider[0] > 8000 ) m_Sw[idx + DI_SLIDER0+0] = 0x80;
|
||
if( js.rglSlider[0] < -8000 ) m_Sw[idx + DI_SLIDER0+1] = 0x80;
|
||
if( js.rglSlider[1] > 8000 ) m_Sw[idx + DI_SLIDER1+0] = 0x80;
|
||
if( js.rglSlider[1] < -8000 ) m_Sw[idx + DI_SLIDER1+1] = 0x80;
|
||
#endif
|
||
|
||
for( INT j = 0; j < 32; j++ ) {
|
||
m_Sw[idx + DI_BUTTON + j] = js.rgbButtons[j];
|
||
}
|
||
|
||
// POV
|
||
for( INT pov = 0; pov < 4; pov++ ) {
|
||
DWORD dwPOV = js.rgdwPOV[pov];
|
||
BOOL bPOVcenter = (LOWORD(dwPOV) == 0xFFFF);
|
||
|
||
BYTE data = 0;
|
||
if( !bPOVcenter ) {
|
||
static const BYTE dirtbl[] = {
|
||
(1<<0), (1<<0)|(1<<3), (1<<3), (1<<1)|(1<<3),
|
||
(1<<1), (1<<1)|(1<<2), (1<<2), (1<<0)|(1<<2),
|
||
};
|
||
|
||
data = dirtbl[ ((dwPOV+(DWORD)(22.5*DI_DEGREES)) % (360*DI_DEGREES))/(45*DI_DEGREES) ];
|
||
}
|
||
|
||
// Up/Down
|
||
if( data & (1<<0) ) m_Sw[idx + DI_POV0_UD+i*4+0] = 0x80;
|
||
if( data & (1<<1) ) m_Sw[idx + DI_POV0_UD+i*4+1] = 0x80;
|
||
// Left/Right
|
||
if( data & (1<<2) ) m_Sw[idx + DI_POV0_LR+i*4+0] = 0x80;
|
||
if( data & (1<<3) ) m_Sw[idx + DI_POV0_LR+i*4+1] = 0x80;
|
||
}
|
||
}
|
||
}
|
||
|
||
LPCSTR CDirectInput::SearchKeyName( INT key )
|
||
{
|
||
LPDIKEYTBL kt = DIKeyTable;
|
||
static CHAR KeyStr[256];
|
||
|
||
if( key == 0x00 )
|
||
return NULL;
|
||
|
||
if( key < 0x100 ) {
|
||
while( kt->name != NULL ) {
|
||
if( kt->key == key )
|
||
return kt->name;
|
||
kt++;
|
||
}
|
||
} else {
|
||
INT no = (key-256)>>6;
|
||
INT idx = key & 0x3F;
|
||
if( idx < DI_MAXAXIS ) {
|
||
::wsprintf( KeyStr, "J:%d %s", no, DIKeyDirTable[idx] );
|
||
return KeyStr;
|
||
} else if( idx >= DI_BUTTON && idx < DI_BUTTON_END ) {
|
||
::wsprintf( KeyStr, "J:%d B:%02d", no, idx-DI_BUTTON );
|
||
return KeyStr;
|
||
} else if( idx >= DI_EXT && idx < DI_EXT_END ) {
|
||
::wsprintf( KeyStr, "J:%d %s", no, DIKeyDirTable2[idx-DI_EXT] );
|
||
return KeyStr;
|
||
}
|
||
}
|
||
|
||
return NULL;
|
||
}
|
||
|