home *** CD-ROM | disk | FTP | other *** search
- /*==========================================================================
- *
- * Copyright (C) 1995-1997 Microsoft Corporation. All Rights Reserved.
- *
- * File: input.c
- * Content: Input routines for Space Donuts game
- *
- *
- ***************************************************************************/
-
- #include <dinput.h>
- #include "input.h"
- #include "resource.h"
-
- extern HWND hWndMain;
- extern DWORD ReadKeyboardInput(void);
- extern DWORD ReadJoystickInput(void);
-
- // allocate external variables
- DWORD (*ReadGameInput)(void) = ReadKeyboardInput;
-
- /*
- * We'll use up to the first ten input devices.
- *
- * c_cpdiFound is the number of found devices.
- * g_rgpdiFound[0] is the array of found devices.
- * g_pdevCurrent is the device that we are using for input.
- */
- #define MAX_DINPUT_DEVICES 10
- int g_cpdevFound;
- LPDIRECTINPUTDEVICE2 g_rgpdevFound[MAX_DINPUT_DEVICES];
- LPDIRECTINPUTDEVICE2 g_pdevCurrent;
-
-
-
-
- /*--------------------------------------------------------------------------
- | AddInputDevice
- |
- | Records an input device in the array of found devices.
- |
- | In addition to stashing it in the array, we also add it to the device
- | menu so the user can pick it.
- |
- *-------------------------------------------------------------------------*/
-
- void AddInputDevice(LPDIRECTINPUTDEVICE pdev, LPCDIDEVICEINSTANCE pdi)
- {
-
- if (g_cpdevFound < MAX_DINPUT_DEVICES) {
-
- HRESULT hRes;
-
- /*
- * Convert it to a Device2 so we can Poll() it.
- */
-
- hRes = pdev->lpVtbl->QueryInterface(
- pdev, &IID_IDirectInputDevice2,
- (LPVOID *)&g_rgpdevFound[g_cpdevFound]);
-
- if (SUCCEEDED(hRes)) {
-
- HMENU hmenu;
-
- /*
- * Add its description to the menu.
- */
- hmenu = GetSubMenu(GetMenu(hWndMain), 0);
-
- InsertMenu(hmenu, g_cpdevFound, MF_BYPOSITION | MF_STRING,
- IDC_DEVICES + g_cpdevFound,
- pdi->tszInstanceName);
-
- g_cpdevFound++;
- }
- }
- }
-
- /*--------------------------------------------------------------------------
- |
- | SetDIDwordProperty
- |
- | Set a DWORD property on a DirectInputDevice.
- |
- *-------------------------------------------------------------------------*/
-
- HRESULT
- SetDIDwordProperty(LPDIRECTINPUTDEVICE pdev, REFGUID guidProperty,
- DWORD dwObject, DWORD dwHow, DWORD dwValue)
- {
- DIPROPDWORD dipdw;
-
- dipdw.diph.dwSize = sizeof(dipdw);
- dipdw.diph.dwHeaderSize = sizeof(dipdw.diph);
- dipdw.diph.dwObj = dwObject;
- dipdw.diph.dwHow = dwHow;
- dipdw.dwData = dwValue;
-
- return pdev->lpVtbl->SetProperty(pdev, guidProperty, &dipdw.diph);
-
- }
-
- /*--------------------------------------------------------------------------
- | InitKeyboardInput
- |
- | Initializes DirectInput for the keyboard. Creates a keyboard device,
- | sets the data format to our custom format, sets the cooperative level and
- | adds it to the menu.
- |
- *-------------------------------------------------------------------------*/
-
- BOOL InitKeyboardInput(LPDIRECTINPUT pdi)
- {
- LPDIRECTINPUTDEVICE pdev;
- DIDEVICEINSTANCE di;
-
- // create the DirectInput keyboard device
- if(pdi->lpVtbl->CreateDevice(pdi, &GUID_SysKeyboard, &pdev, NULL) != DI_OK)
- {
- OutputDebugString("IDirectInput::CreateDevice FAILED\n");
- return FALSE;
- }
-
- // set keyboard data format
- if(pdev->lpVtbl->SetDataFormat(pdev, &c_dfDIKeyboard) != DI_OK)
- {
- OutputDebugString("IDirectInputDevice::SetDataFormat FAILED\n");
- pdev->lpVtbl->Release(pdev);
- return FALSE;
- }
-
- // set the cooperative level
- if(pdev->lpVtbl->SetCooperativeLevel(pdev, hWndMain,
- DISCL_NONEXCLUSIVE | DISCL_FOREGROUND) != DI_OK)
- {
- OutputDebugString("IDirectInputDevice::SetCooperativeLevel FAILED\n");
- pdev->lpVtbl->Release(pdev);
- return FALSE;
- }
-
- // set buffer size
- if (SetDIDwordProperty(pdev, DIPROP_BUFFERSIZE, 0, DIPH_DEVICE, KEYBUFSIZE) != DI_OK)
- {
- OutputDebugString("IDirectInputDevice::SetProperty(DIPH_DEVICE) FAILED\n");
- pdev->lpVtbl->Release(pdev);
- return FALSE;
- }
-
- //
- // Get the name of the primary keyboard so we can add it to the menu.
- //
- di.dwSize = sizeof(di);
- if (pdev->lpVtbl->GetDeviceInfo(pdev, &di) != DI_OK)
- {
- OutputDebugString("IDirectInputDevice::GetDeviceInfo FAILED\n");
- pdev->lpVtbl->Release(pdev);
- return FALSE;
- }
-
- //
- // Add it to our list of devices. If AddInputDevice succeeds,
- // he will do an AddRef.
- //
- AddInputDevice(pdev, &di);
- pdev->lpVtbl->Release(pdev);
-
- return TRUE;
- }
-
- /*--------------------------------------------------------------------------
- | InitJoystickInput
- |
- | Initializes DirectInput for an enumerated joystick device.
- | Creates the device, device, sets the standard joystick data format,
- | sets the cooperative level and adds it to the menu.
- |
- | If any step fails, just skip the device and go on to the next one.
- |
- *-------------------------------------------------------------------------*/
-
- BOOL FAR PASCAL InitJoystickInput(LPCDIDEVICEINSTANCE pdinst, LPVOID pvRef)
- {
- LPDIRECTINPUT pdi = pvRef;
- LPDIRECTINPUTDEVICE pdev;
- DIPROPRANGE diprg;
-
- // create the DirectInput joystick device
- if(pdi->lpVtbl->CreateDevice(pdi, &pdinst->guidInstance, &pdev, NULL) != DI_OK)
- {
- OutputDebugString("IDirectInput::CreateDevice FAILED\n");
- return DIENUM_CONTINUE;
- }
-
- // set joystick data format
- if(pdev->lpVtbl->SetDataFormat(pdev, &c_dfDIJoystick) != DI_OK)
- {
- OutputDebugString("IDirectInputDevice::SetDataFormat FAILED\n");
- pdev->lpVtbl->Release(pdev);
- return DIENUM_CONTINUE;
- }
-
- // set the cooperative level
- if(pdev->lpVtbl->SetCooperativeLevel(pdev, hWndMain,
- DISCL_NONEXCLUSIVE | DISCL_FOREGROUND) != DI_OK)
- {
- OutputDebugString("IDirectInputDevice::SetCooperativeLevel FAILED\n");
- pdev->lpVtbl->Release(pdev);
- return DIENUM_CONTINUE;
- }
-
- // set X-axis range to (-1000 ... +1000)
- // This lets us test against 0 to see which way the stick is pointed.
-
- diprg.diph.dwSize = sizeof(diprg);
- diprg.diph.dwHeaderSize = sizeof(diprg.diph);
- diprg.diph.dwObj = DIJOFS_X;
- diprg.diph.dwHow = DIPH_BYOFFSET;
- diprg.lMin = -1000;
- diprg.lMax = +1000;
-
- if(pdev->lpVtbl->SetProperty(pdev, DIPROP_RANGE, &diprg.diph) != DI_OK)
- {
- OutputDebugString("IDirectInputDevice::SetProperty(DIPH_RANGE) FAILED\n");
- pdev->lpVtbl->Release(pdev);
- return FALSE;
- }
-
- //
- // And again for Y-axis range
- //
- diprg.diph.dwObj = DIJOFS_Y;
-
- if(pdev->lpVtbl->SetProperty(pdev, DIPROP_RANGE, &diprg.diph) != DI_OK)
- {
- OutputDebugString("IDirectInputDevice::SetProperty(DIPH_RANGE) FAILED\n");
- pdev->lpVtbl->Release(pdev);
- return FALSE;
- }
-
- // set X axis dead zone to 50% (to avoid accidental turning)
- // Units are ten thousandths, so 50% = 5000/10000.
- if (SetDIDwordProperty(pdev, DIPROP_DEADZONE, DIJOFS_X, DIPH_BYOFFSET, 5000) != DI_OK)
- {
- OutputDebugString("IDirectInputDevice::SetProperty(DIPH_DEADZONE) FAILED\n");
- pdev->lpVtbl->Release(pdev);
- return FALSE;
- }
-
-
- // set Y axis dead zone to 50% (to avoid accidental thrust)
- // Units are ten thousandths, so 50% = 5000/10000.
- if (SetDIDwordProperty(pdev, DIPROP_DEADZONE, DIJOFS_Y, DIPH_BYOFFSET, 5000) != DI_OK)
- {
- OutputDebugString("IDirectInputDevice::SetProperty(DIPH_DEADZONE) FAILED\n");
- pdev->lpVtbl->Release(pdev);
- return FALSE;
- }
-
-
- //
- // Add it to our list of devices. If AddInputDevice succeeds,
- // he will do an AddRef.
- //
- AddInputDevice(pdev, pdinst);
- pdev->lpVtbl->Release(pdev);
-
- return DIENUM_CONTINUE;
- }
-
- /*--------------------------------------------------------------------------
- | InitInput
- |
- | Initializes DirectInput for the keyboard and all joysticks.
- |
- | For each input device, add it to the menu.
- |
- *-------------------------------------------------------------------------*/
-
- BOOL InitInput(HINSTANCE hInst, HWND hWnd)
- {
- LPDIRECTINPUT pdi;
- BOOL fRc;
-
- // Note: Joystick support is a DirectX 5.0 feature.
- // Since we also want to run on DirectX 3.0, we will start out
- // with DirectX 3.0 to make sure that at least we get the keyboard.
-
- // create the DirectInput interface object
- if(DirectInputCreate(hInst, 0x0300, &pdi, NULL) != DI_OK)
- {
- OutputDebugString("DirectInputCreate 3.0 FAILED\n");
- return FALSE;
- }
-
- fRc = InitKeyboardInput(pdi);
- pdi->lpVtbl->Release(pdi); // Finished with DX 3.0
-
- if (!fRc) {
- return FALSE;
- }
-
- // create the DirectInput 5.0 interface object
- if(DirectInputCreate(hInst, DIRECTINPUT_VERSION, &pdi, NULL) == DI_OK)
- {
-
- //
- // Enumerate the joystick devices. If it doesn't work, oh well,
- // at least we got the keyboard.
- //
-
- pdi->lpVtbl->EnumDevices(pdi, DIDEVTYPE_JOYSTICK,
- InitJoystickInput, pdi, DIEDFL_ATTACHEDONLY);
-
- pdi->lpVtbl->Release(pdi); // Finished with DX 5.0.
-
- } else {
- OutputDebugString("DirectInputCreate 5.0 FAILED - no joystick support\n");
- }
-
- // Default device is the keyboard
- PickInputDevice(0);
-
- // if we get here, we were successful
- return TRUE;
- }
-
- /*--------------------------------------------------------------------------
- | CleanupInput
- |
- | Cleans up all DirectInput objects.
- *-------------------------------------------------------------------------*/
- void CleanupInput(void)
- {
- int idev;
-
- // make sure the device is unacquired
- // it doesn't harm to unacquire a device that isn't acquired
-
- if (g_pdevCurrent)
- {
- IDirectInputDevice_Unacquire(g_pdevCurrent);
- }
-
- // release all the devices we created
- for (idev = 0; idev < g_cpdevFound; idev++)
- {
- if (g_rgpdevFound[idev]) {
- IDirectInputDevice_Release(g_rgpdevFound[idev]);
- g_rgpdevFound[idev] = 0;
- }
- }
-
- }
-
-
- /*--------------------------------------------------------------------------
- | ReacquireInput
- |
- | Reacquires the current input device. If Acquire() returns S_FALSE,
- | that means
- | that we are already acquired and that DirectInput did nothing.
- *-------------------------------------------------------------------------*/
- BOOL ReacquireInput(void)
- {
- HRESULT hRes;
-
- // if we have a current device
- if(g_pdevCurrent)
- {
- // acquire the device
- hRes = IDirectInputDevice_Acquire(g_pdevCurrent);
- if(SUCCEEDED(hRes))
- {
- // acquisition successful
- return TRUE;
- }
- else
- {
- // acquisition failed
- return FALSE;
- }
- }
- else
- {
- // we don't have a current device
- return FALSE;
- }
-
- }
-
-
- /*--------------------------------------------------------------------------
- | ReadKeyboardInput
- |
- | Requests keyboard data and performs any needed processing.
- *-------------------------------------------------------------------------*/
- DWORD ReadKeyboardInput(void)
- {
- DIDEVICEOBJECTDATA rgKeyData[KEYBUFSIZE];
- DWORD dwEvents;
- DWORD dw;
- static DWORD dwKeyState = 0;
- HRESULT hRes;
-
- // get data from the keyboard
- dwEvents = KEYBUFSIZE;
- hRes = IDirectInputDevice_GetDeviceData(g_pdevCurrent,
- sizeof(DIDEVICEOBJECTDATA),
- rgKeyData, &dwEvents, 0);
-
- if(hRes != DI_OK)
- {
- // did the read fail because we lost input for some reason?
- // if so, then attempt to reacquire. If the second acquire
- // fails, then the error from GetDeviceData will be
- // DIERR_NOTACQUIRED, so we won't get stuck an infinite loop.
- if(hRes == DIERR_INPUTLOST)
- ReacquireInput();
-
- // return the fact that we did not read any data
- return 0;
- }
-
- // process the data
- for(dw = 0; dw < dwEvents; dw++)
- {
- switch(rgKeyData[dw].dwOfs)
- {
- // fire
- case DIK_SPACE:
- if(rgKeyData[dw].dwData & 0x80)
- dwKeyState |= KEY_FIRE;
- else
- dwKeyState &= (DWORD)~KEY_FIRE;
- break;
-
- // stop
- case DIK_NUMPAD5:
- if(rgKeyData[dw].dwData & 0x80)
- dwKeyState |= KEY_STOP;
- else
- dwKeyState &= ~KEY_STOP;
- break;
-
- // shield
- case DIK_NUMPAD7:
- if(rgKeyData[dw].dwData & 0x80)
- dwKeyState |= KEY_SHIELD;
- else
- dwKeyState &= ~KEY_SHIELD;
- break;
-
- // thrust
- case DIK_UP:
- case DIK_NUMPAD8:
- if(rgKeyData[dw].dwData & 0x80)
- dwKeyState |= KEY_UP;
- else
- dwKeyState &= ~KEY_UP;
- break;
-
- // reverse thrust
- case DIK_DOWN:
- case DIK_NUMPAD2:
- if(rgKeyData[dw].dwData & 0x80)
- dwKeyState |= KEY_DOWN;
- else
- dwKeyState &= ~KEY_DOWN;
- break;
-
- // rotate left
- case DIK_LEFT:
- case DIK_NUMPAD4:
- if(rgKeyData[dw].dwData & 0x80)
- dwKeyState |= KEY_LEFT;
- else
- dwKeyState &= ~KEY_LEFT;
- break;
-
- // rotate right
- case DIK_RIGHT:
- case DIK_NUMPAD6:
- if(rgKeyData[dw].dwData & 0x80)
- dwKeyState |= KEY_RIGHT;
- else
- dwKeyState &= ~KEY_RIGHT;
- break;
- }
-
- }
-
- // return the state of the keys to the caller
- return dwKeyState;
-
- }
-
- /*--------------------------------------------------------------------------
- | ReadJoystickInput
- |
- | Requests joystick data and performs any needed processing.
- |
- *-------------------------------------------------------------------------*/
- DWORD ReadJoystickInput(void)
- {
- DWORD dwKeyState;
- HRESULT hRes;
- DIJOYSTATE js;
-
- // poll the joystick to read the current state
- hRes = IDirectInputDevice2_Poll(g_pdevCurrent);
-
- // get data from the joystick
- hRes = IDirectInputDevice_GetDeviceState(g_pdevCurrent,
- sizeof(DIJOYSTATE), &js);
-
- if(hRes != DI_OK)
- {
- // did the read fail because we lost input for some reason?
- // if so, then attempt to reacquire. If the second acquire
- // fails, then the error from GetDeviceData will be
- // DIERR_NOTACQUIRED, so we won't get stuck an infinite loop.
- if(hRes == DIERR_INPUTLOST)
- ReacquireInput();
-
- // return the fact that we did not read any data
- return 0;
- }
-
- //
- // Now study the position of the stick and the buttons.
- //
-
- dwKeyState = 0;
-
- if (js.lX < 0) {
- dwKeyState |= KEY_LEFT;
- } else if (js.lX > 0) {
- dwKeyState |= KEY_RIGHT;
- }
-
- if (js.lY < 0) {
- dwKeyState |= KEY_UP;
- } else if (js.lY > 0) {
- dwKeyState |= KEY_DOWN;
- }
-
- if (js.rgbButtons[0] & 0x80) {
- dwKeyState |= KEY_FIRE;
- }
-
- if (js.rgbButtons[1] & 0x80) {
- dwKeyState |= KEY_SHIELD;
- }
-
- if (js.rgbButtons[2] & 0x80) {
- dwKeyState |= KEY_STOP;
- }
-
- return dwKeyState;
-
- }
-
- /*--------------------------------------------------------------------------
- | PickInputDevice
- |
- | Make the n'th input device the one that we will use for game play.
- |
- *-------------------------------------------------------------------------*/
-
- BOOL PickInputDevice(int n)
- {
- if (n < g_cpdevFound) {
-
- /*
- * Unacquire the old device.
- */
- if (g_pdevCurrent) {
- IDirectInputDevice_Unacquire(g_pdevCurrent);
- }
-
- /*
- * Move to the new device.
- */
- g_pdevCurrent = g_rgpdevFound[n];
-
- /*
- * Set ReadGameInput to the appropriate handler.
- */
- if (n == 0) {
- ReadGameInput = ReadKeyboardInput;
- } else {
- ReadGameInput = ReadJoystickInput;
- }
-
- CheckMenuRadioItem(GetSubMenu(GetMenu(hWndMain), 0),
- IDC_DEVICES, IDC_DEVICES + g_cpdevFound - 1,
- IDC_DEVICES + n, MF_BYCOMMAND);
-
- ReacquireInput();
-
- return TRUE;
- } else {
- return FALSE;
- }
- }
-