⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 win_sys.c

📁 The source code of Doom legacy for windows
💻 C
📖 第 1 页 / 共 5 页
字号:
    //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 + -