📄 win_sys.c
字号:
//CONS_Printf (" cv joy is %s\n", ((consvar_t *)pvRef)->string);
// print out device name
CONS_Printf ("%c%d: %s\n",
( bUseThisOne ) ? '\2' : ' ', // show name in white if this is the one we will use
iJoyNum,
//( GET_DIDEVICE_SUBTYPE(lpddi->dwDevType) == DIDEVTYPEJOYSTICK_GAMEPAD ) ? "Gamepad " : "Joystick",
lpddi->tszProductName ); // , lpddi->tszInstanceName );
// use specified joystick (cv_usejoystick.value in pvRef)
if ( !bUseThisOne )
return DIENUM_CONTINUE;
((consvar_t *)pvRef)->value = iJoyNum;
if (lpDI->lpVtbl->CreateDevice (lpDI, &lpddi->guidInstance,
&pdev, NULL) != DI_OK)
{
// if it failed, then we can't use this joystick for some
// bizarre reason. (Maybe the user unplugged it while we
// were in the middle of enumerating it.) So continue enumerating
CONS_Printf ("DIEnumJoysticks(): CreateDevice FAILED\n");
return DIENUM_CONTINUE;
}
// get the Device capabilities
//
caps.dwSize = sizeof(DIDEVCAPS_DX3);
if ( FAILED( pdev->lpVtbl->GetCapabilities ( pdev, (DIDEVCAPS*)&caps ) ) )
{
CONS_Printf ("DIEnumJoysticks(): GetCapabilities FAILED\n");
pdev->lpVtbl->Release (pdev);
return DIENUM_CONTINUE;
}
if ( !(caps.dwFlags & DIDC_ATTACHED) ) // should be, since we enumerate only attached devices
return DIENUM_CONTINUE;
Joystick.bJoyNeedPoll = (( caps.dwFlags & DIDC_POLLEDDATAFORMAT ) != 0);
if ( caps.dwFlags & DIDC_FORCEFEEDBACK )
CONS_Printf ("Sorry, force feedback is not yet supported\n");
Joystick.bGamepadStyle = ( GET_DIDEVICE_SUBTYPE( caps.dwDevType ) == DIDEVTYPEJOYSTICK_GAMEPAD );
//DEBUG CONS_Printf ("Gamepad: %d\n", Joystick.bGamepadStyle);
CONS_Printf ("Capabilities: %d axes, %d buttons, %d POVs, poll %d, Gamepad %d\n",
caps.dwAxes, caps.dwButtons, caps.dwPOVs, Joystick.bJoyNeedPoll, Joystick.bGamepadStyle);
// Set the data format to "simple joystick" - a predefined data format
//
// A data format specifies which controls on a device we
// are interested in, and how they should be reported.
//
// This tells DirectInput that we will be passing a
// DIJOYSTATE structure to IDirectInputDevice::GetDeviceState.
if (pdev->lpVtbl->SetDataFormat (pdev, &c_dfDIJoystick) != DI_OK)
{
CONS_Printf ("DIEnumJoysticks(): SetDataFormat FAILED\n");
pdev->lpVtbl->Release (pdev);
return DIENUM_CONTINUE;
}
// Set the cooperativity level to let DirectInput know how
// this device should interact with the system and with other
// DirectInput applications.
if (pdev->lpVtbl->SetCooperativeLevel (pdev, hWndMain,
DISCL_EXCLUSIVE | DISCL_FOREGROUND) != DI_OK)
{
CONS_Printf ("DIEnumJoysticks(): SetCooperativeLevel FAILED\n");
pdev->lpVtbl->Release (pdev);
return DIENUM_CONTINUE;
}
// set the range of the joystick axis
diprg.diph.dwSize = sizeof(DIPROPRANGE);
diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER);
diprg.diph.dwHow = DIPH_BYOFFSET;
diprg.lMin = -JOYAXISRANGE; // value for extreme left
diprg.lMax = +JOYAXISRANGE; // value for extreme right
diprg.diph.dwObj = DIJOFS_X; // set the x-axis range
if (FAILED( pdev->lpVtbl->SetProperty( pdev, DIPROP_RANGE, &diprg.diph ) ) ) {
goto SetPropFail;
}
diprg.diph.dwObj = DIJOFS_Y; // set the y-axis range
if (FAILED( pdev->lpVtbl->SetProperty( pdev, DIPROP_RANGE, &diprg.diph ) ) ) {
SetPropFail:
CONS_Printf ("DIEnumJoysticks(): SetProperty FAILED\n");
pdev->lpVtbl->Release (pdev);
return DIENUM_CONTINUE;
}
diprg.diph.dwObj = DIJOFS_Z; // set the z-axis range
if (FAILED( pdev->lpVtbl->SetProperty( pdev, DIPROP_RANGE, &diprg.diph ) ) ) {
CONS_Printf ("DIJOFS_Z not found\n");
// set a flag here..
}
diprg.diph.dwObj = DIJOFS_RZ; // set the rudder range
if (FAILED( pdev->lpVtbl->SetProperty( pdev, DIPROP_RANGE, &diprg.diph ) ) )
{
CONS_Printf ("DIJOFS_RZ (rudder) not found\n");
// set a flag here..
}
// set X axis dead zone to 25% (to avoid accidental turning)
if ( !Joystick.bGamepadStyle ) {
if ( FAILED( SetDIDwordProperty (pdev, DIPROP_DEADZONE, DIJOFS_X,
DIPH_BYOFFSET, 2500) ) )
{
CONS_Printf ("DIEnumJoysticks(): couldn't SetProperty for DEAD ZONE\n");
//pdev->lpVtbl->Release (pdev);
//return DIENUM_CONTINUE;
}
if (FAILED( SetDIDwordProperty (pdev, DIPROP_DEADZONE, DIJOFS_Y,
DIPH_BYOFFSET, 2500) ) )
{
CONS_Printf ("DIEnumJoysticks(): couldn't SetProperty for DEAD ZONE\n");
//pdev->lpVtbl->Release (pdev);
//return DIENUM_CONTINUE;
}
}
// query for IDirectInputDevice2 - we need this to poll the joystick
if ( bDX0300 ) {
// we won't use the poll
lpDIJ2 = NULL;
}
else
{
if (FAILED( pdev->lpVtbl->QueryInterface(pdev, &IID_IDirectInputDevice2,
(LPVOID *)&lpDIJ2) ) )
{
CONS_Printf ("DIEnumJoysticks(): QueryInterface FAILED\n");
pdev->lpVtbl->Release (pdev);
return DIENUM_CONTINUE;
}
}
// we successfully created an IDirectInputDevice. So stop looking
// for another one.
lpDIJ = pdev;
return DIENUM_STOP;
}
// --------------
// I_InitJoystick
// This is called everytime the 'use_joystick' variable changes
// It is normally called at least once at startup when the config is loaded
// --------------
static void I_ShutdownJoystick (void);
void I_InitJoystick (void)
{
HRESULT hr;
// cleanup
I_ShutdownJoystick ();
joystick_detected = false;
// joystick detection can be skipped by setting use_joystick to 0
if ( M_CheckParm("-nojoy") ) {
CONS_Printf ("Joystick disabled\n");
return;
}
else
// don't do anything at the registration of the joystick cvar,
// until config is loaded
if ( !lstrcmp( cv_usejoystick.string, "0" ) )
return;
// acquire the joystick only once
if (lpDIJ==NULL)
{
joystick_detected = false;
CONS_Printf ("Looking for joystick devices:\n");
iJoyNum = 0;
hr = lpDI->lpVtbl->EnumDevices( lpDI, DIDEVTYPE_JOYSTICK,
DIEnumJoysticks,
(void*)&cv_usejoystick, // our user parameter is joystick number
DIEDFL_ATTACHEDONLY );
if (FAILED(hr)) {
CONS_Printf ("\nI_InitJoystick(): EnumDevices FAILED\n");
return;
}
if (lpDIJ == NULL)
{
if (iJoyNum == 0)
CONS_Printf ("none found\n");
else
{
CONS_Printf ("none used\n");
if ( cv_usejoystick.value > 0 &&
cv_usejoystick.value > iJoyNum )
{
CONS_Printf ("\2Set the use_joystick variable to one of the"
" enumerated joysticks number\n");
}
}
return;
}
I_AddExitFunc (I_ShutdownJoystick);
// set coop level
if ( FAILED( lpDIJ->lpVtbl->SetCooperativeLevel (lpDIJ, hWndMain, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND) ))
I_Error ("I_InitJoystick: SetCooperativeLevel FAILED");
// later
//if ( FAILED( lpDIJ->lpVtbl->Acquire (lpDIJ) ))
// I_Error ("Couldn't acquire Joystick");
joystick_detected = true;
}
else
CONS_Printf ("Joystick already initialized\n");
//faB: we don't unacquire joystick, so let's just pretend we re-acquired it
joystick_detected = true;
}
static void I_ShutdownJoystick (void)
{
int i;
event_t event;
// emulate the up of all joystick buttons
for(i=0;i<JOYBUTTONS;i++)
{
event.type=ev_keyup;
event.data1=KEY_JOY1+i;
D_PostEvent(&event);
}
// reset joystick position
event.type = ev_joystick;
event.data1 = 0;
event.data2 = 0;
event.data3 = 0;
D_PostEvent(&event);
if ( joystick_detected )
CONS_Printf ("I_ShutdownJoystick()\n");
if (lpDIJ)
{
lpDIJ->lpVtbl->Unacquire (lpDIJ);
lpDIJ->lpVtbl->Release (lpDIJ);
lpDIJ = NULL;
}
if (lpDIJ2)
{
lpDIJ2->lpVtbl->Release(lpDIJ2);
lpDIJ2 = NULL;
}
joystick_detected = false;
}
// -------------------
// I_GetJoystickEvents
// Get current joystick axis and button states
// -------------------
static void I_GetJoystickEvents (void)
{
HRESULT hr;
DIJOYSTATE js; // DirectInput joystick state
int i;
static DWORD lastjoybuttons = 0;
DWORD joybuttons;
event_t event;
if (lpDIJ==NULL)
return;
// if input is lost then acquire and keep trying
while( 1 )
{
// poll the joystick to read the current state
//faB: if the device doesn't require polling, this function returns
// almost instantly
if ( lpDIJ2 ) {
hr = lpDIJ2->lpVtbl->Poll(lpDIJ2);
if ( hr == DIERR_INPUTLOST || hr==DIERR_NOTACQUIRED )
goto acquire;
else
if ( FAILED(hr) )
{
CONS_Printf ("I_GetJoystickEvents(): Poll FAILED\n");
return;
}
}
// get the input's device state, and put the state in dims
hr = lpDIJ->lpVtbl->GetDeviceState( lpDIJ, sizeof(DIJOYSTATE), &js );
if ( hr == DIERR_INPUTLOST || hr==DIERR_NOTACQUIRED )
{
// DirectInput is telling us that the input stream has
// been interrupted. We aren't tracking any state
// between polls, so we don't have any special reset
// that needs to be done. We just re-acquire and
// try again.
goto acquire;
}
else
if( FAILED(hr) )
{
CONS_Printf ("I_GetJoystickEvents(): GetDeviceState FAILED\n");
return;
}
break;
acquire:
//CONS_Printf ("I_GetJoystickEvents(): Acquire\n");
if ( FAILED(lpDIJ->lpVtbl->Acquire( lpDIJ )) )
return;
}
// post virtual key events for buttons
//
joybuttons = 0;
//faB: look for as much buttons as g_input code supports,
// we don't use the others
for (i = JOYBUTTONS-1; i >= 0; i--)
{
joybuttons <<= 1;
if ( js.rgbButtons[i] )
joybuttons |= 1;
}
if(js.rgdwPOV[0]>=0 && js.rgdwPOV[0]!=0xffff && js.rgdwPOV[0]!=0xffFFffFF)
{
if((js.rgdwPOV[0]>=000 && js.rgdwPOV[0]<=4500) || (js.rgdwPOV[0]>31500 && js.rgdwPOV[0]<=36000))
joybuttons|=1<<10;
else
if(js.rgdwPOV[0]>04500 && js.rgdwPOV[0]<=13500)
joybuttons|=1<<13;
else
if(js.rgdwPOV[0]>13500 && js.rgdwPOV[0]<=22500)
joybuttons|=1<<11;
else
if(js.rgdwPOV[0]>22500 && js.rgdwPOV[0]<=31500)
joybuttons|=1<<12;
}
if ( joybuttons != lastjoybuttons )
{
DWORD j = 1;
DWORD newbuttons;
// keep only bits that changed since last time
newbuttons = joybuttons ^ lastjoybuttons;
lastjoybuttons = joybuttons;
for( i=0; i < JOYBUTTONS; i++, j<<=1 )
{
if ( newbuttons & j ) // button changed state ?
{
if ( joybuttons & j )
event.type = ev_keydown;
else
event.type = ev_keyup;
event.data1 = KEY_JOY1 + i;
D_PostEvent (&event);
}
}
}
// send joystick axis positions
//
event.type = ev_joystick;
event.data1 = 0;
event.data2 = 0;
event.data3 = 0;
if ( Joystick.bGamepadStyle )
{
// gamepad control type, on or off, live or die
if ( js.lX < -(JOYAXISRANGE/2) )
event.data2 = -1;
else if ( js.lX > (JOYAXISRANGE/2) )
event.data2 = 1;
if ( js.lY < -(JOYAXISRANGE/2) )
event.data3 = -1;
else if ( js.lY > (JOYAXISRANGE/2) )
event.data3 = 1;
}
else
{
// analog control style , just send the raw data
event.data2 = js.lX; // x axis
event.data3 = js.lY; // y axis
}
D_PostEvent(&event);
}
// ===========================================================================================
// DIRECT INPUT KEYBOARD
// ===========================================================================================
byte ASCIINames[256] = {
// 0 1 2 3 4 5 6 7
// 8 9 A B C D E F
0 , 27, '1', '2', '3', '4', '5', '6',
'7', '8', '9', '0', KEY_MINUS,KEY_EQUALS,KEY_BACKSPACE, KEY_TAB,
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
'o', 'p', '[', ']', KEY_ENTER,KEY_CTRL,'a', 's',
'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
'\'', '`', KEY_SHIFT, '\\', 'z', 'x', 'c', 'v',
'b', 'n', 'm', ',', '.', '/', KEY_SHIFT, '*',
KEY_ALT,KEY_SPACE,KEY_CAPSLOCK, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -