/* MainFrm.cpp ****************************************************************
Author: Paul Watt, Copyright (c) 2002
Date: 5/4/2002
Purpose: The main frame for the Quadrino game.
******************************************************************************/
#include "stdafx.h"
#include "DDUtil.h"
#include "DInput.h"
#include "mainfrm.h"
/* Global Variables **********************************************************/
LPDIRECTINPUT8 g_pDI;
LPDIRECTINPUTDEVICE8 g_pdidKeyboard;
DIDEVICEOBJECTDATA g_dodBuffer[KEYBOARD_BUFFERSIZE];
#define BITDEPTH_32 32
#define BITDEPTH_24 24
/* Public *********************************************************************
Author: Paul Watt
Date: 4/16/2002
Purpose: Updates the current frame of the game.
Parameters: NONE
Return: HRESULT returns the state of this function call.
******************************************************************************/
HRESULT CMainFrame::OnUpdateFrame ()
{
//C: Only continue if the window actually exists.
if (!m_hWnd)
{
return E_FAIL;
}
//C: Check the users input in order to manipulate the pieces.
//C: Only chrck if the input device is properly initialized, and this app has focus.
if (g_pdidKeyboard && ::GetFocus())
{
//C: Keyboard state buffer.
DWORD dwCount = KEYBOARD_BUFFERSIZE;
HRESULT hr = GetDeviceData(dwCount);
if (SUCCEEDED(hr))
{
//C: Cycle through each of the command events until the buffer is empty.
for (DWORD index = 0; index < dwCount; ++index)
{
//C: Update the state of the key that was just pressed.
DIDEVICEOBJECTDATA *data = &g_dodBuffer[index];
//C: Get the latest timestamp for a key.
m_dwTimeStamps[data->dwOfs] = data->dwTimeStamp;
m_bKBState[data->dwOfs] = (BYTE)data->dwData;
//C: The way that input is handled depends on the current mode of the game.
if (!m_game.IsInit())
{
if (CQuadrinoView::OPTIONS == m_view.GetState())
{
hr = HandleOptionsScreenInput(*data);
}
else
{
//C: The main screen is displayed.
hr = HandleMainScreenInput(*data);
}
}
else if (m_game.IsPaused())
{
//C: The game is paused.
hr = HandlePauseScreenInput(*data);
}
else
{
//C: The user is currently playing the game.
hr = HandleGameInput(*data);
}
//C: Verify that input was processed successfully.
if (FAILED(hr))
{
ATLASSERT(0);
}
}
//C: Process any of the commands that function while the user holds down the key.
hr = HandleContinuousInput (GetTickCount());
}
else
{
ATLTRACE("The data for the input device could not be retrieved.\n");
}
}
//C: Refresh the display of the game.
if (m_view.IsWindow())
{
return m_view.UpdateFrame();
}
return S_OK;
}
/* Public *********************************************************************
Author: Paul Watt
Date: 5/5/2002
Purpose: Handles the WM_CREATE message.
******************************************************************************/
LRESULT CMainFrame::OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
//C: Load the users settings from a file.
if (0)
{
#pragma message( REMIND( "PMW: Read the settings from a file." ) )
}
else
{
//C: Set the default values.
SetDefaultSettings ();
}
InitializeQuadrinoModule ();
//C: Create and initialize the view window that will display the game.
m_hWndClient = m_view.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 0);
m_view.SetGame(&m_game);
//C: Get the current working directory.
TCHAR szDir[_MAX_PATH];
USES_CONVERSION;
//C: Get the directory where the current program is running.
if (0 == ::GetModuleFileName(NULL, szDir, _MAX_PATH))
{
::MessageBox(m_hWnd, _T("Could not identify application resources. Quadrino will now exit."), _T("Error"), MB_OK | MB_ICONSTOP);
return -1;
}
TCHAR *szFileName = ::_tcsrchr(szDir, '\\');
if (szFileName)
{
*szFileName = NULL;
}
//C: Initialize the Music Player.
CComBSTR bstrMusic = T2W(szDir);
bstrMusic += _T("\\Sounds\\Quadrino.mp3");
m_MusicPlayer.SetCurrentFile(bstrMusic);
m_MusicPlayer.Repeat(true);
m_MusicPlayer.SetNotifyWindow(m_hWnd, WM_GRAPHNOTIFY, 0);
//C: Initialize Sounds.
m_SoundManager.Initialize(m_hWnd);
TCHAR szSound[_MAX_PATH];
::_tcscpy_s(szSound, szDir);
::_tcscat_s(szSound, _T("\\Sounds\\rotate.wav"));
m_SoundManager.CreateSound(&m_pSoundRotate, szSound, 0, 5);
::_tcscpy_s(szSound, szDir);
::_tcscat_s(szSound, _T("\\Sounds\\move.wav"));
m_SoundManager.CreateSound(&m_pSoundMove, szSound, 0, 10);
::_tcscpy_s(szSound, szDir);
::_tcscat_s(szSound, _T("\\Sounds\\state.wav"));
m_SoundManager.CreateSound(&m_pSoundState, szSound, 0, 4);
//C: Set the sound levels.
SetMusicVolume(100);
SetSoundFXVolume(50);
CMessageLoop* pLoop = _Module.GetMessageLoop();
if (pLoop)
{
//C: Add a this window as a message filter.
pLoop->AddMessageFilter(this);
//C: Verify that the message loop is a game loop.
CGameLoop *pGameLoop = dynamic_cast<CGameLoop*>(pLoop);
if (!pGameLoop)
{
//C: This window requires the loop to be a game loop for the
ATLTRACE2(atlTraceUI, 0, _T("The MessageLoop is not a CGameLoop. This window cannot proceed.\n"));
return -1;
}
else
{
//C: Add this window as the UpdateFrame window.
pGameLoop->SetGameHandler(this);
}
}
//C: Initialize the keyboard state.
ZeroMemory(m_bKBState, sizeof(m_bKBState));
//C: Initialize the Direct Input buffers.
CreateDInput(m_hWnd);
m_view.SetWindowedDisplay();
/* //C: Set the final display mode of the window.
if (FAILED(m_view.SetFullScreenDisplay(800, 600, BITDEPTH_32)))
{
//C: If 32 bits failed, then try 24.
if (FAILED(m_view.SetFullScreenDisplay(800, 600, BITDEPTH_24)))
{
//C: If 24 failed, then let the user know.
::MessageBox(m_hWnd, "Quadrino could not find a compatible video mode to run the game. This game will now exit.", "Error", MB_OK | MB_ICONSTOP);
return -1;
}
}*/
return 0;
}
/* Public *********************************************************************
Author: Paul Watt
Date: 5/5/2002
Purpose: Handles the WM_DESTROY message.
******************************************************************************/
LRESULT CMainFrame::OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
bHandled = false;
//C: Free sound objects.
delete m_pSoundRotate;
m_pSoundRotate = NULL;
delete m_pSoundMove;
m_pSoundMove = NULL;
delete m_pSoundState;
m_pSoundState = NULL;
//C: Free the Direct Input buffers.
DestroyDInput();
return 0;
}
/* Public *********************************************************************
Author: Paul Watt
Date: 5/5/2002
Purpose: Handles the WM_ACTIVATE message. THis function will insure that
this app properly aquires the keyboard when the app has the focus.
******************************************************************************/
LRESULT CMainFrame::OnActivate(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
//C: Pause or resume the game based on the activation mode.
if (wParam == WA_INACTIVE)
{
Pause();
}
else
{
Resume();
}
//C: Synchronize access to the keyboard for this window.
SyncAcquire();
return 0;
}
/* Public *********************************************************************
Author: Paul Watt
Date: 5/4/2002
Purpose: Command handler that will toggle the application in between windowed
and full screen mode.
******************************************************************************/
LRESULT CMainFrame::OnToggleFullScreen(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
//C: Properly set the TOP MOST style for this window when in full screen mode.
LONG lStyleEx = GetWindowLong(GWL_EXSTYLE);
if (!m_view.IsWindowed())
{
SetWindowLong(GWL_EXSTYLE, lStyleEx & ~WS_EX_TOPMOST);
m_view.SetWindowedDisplay();
}
else
{
SetWindowLong(GWL_EXSTYLE, lStyleEx | WS_EX_TOPMOST);
if (FAILED(m_view.SetFullScreenDisplay(800, 600, BITDEPTH_32)))
{
//C: If 32 bits failed, then try 24.
if (FAILED(m_view.SetFullScreenDisplay(800, 600, BITDEPTH_24)))
{
//C: If 24 failed, then let the user know.
::MessageBox(m_hWnd, _T("Quadrino could not find a compatible video mode to run the game. This game will now exit."), _T("Error"), MB_OK | MB_ICONSTOP);
PostQuitMessage(0);
}
}
}
return 0;
}
/* Public *********************************************************************
Author: Paul Watt
Date: 10/21/2002
Purpose: Handles the case when a music Player feedback event occurs.
Parameters:
Return: 0
******************************************************************************/
LRESULT CMainFrame::OnGraphNotify(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
m_MusicPlayer.HandleEvents();
return 0;
}
/* Private ********************************************************************
Author: Paul Watt
Date: 5/4/2002
Purpose: Retireves the data from the keyboard to process as input to the game.
Parameters: dwCount[in/out]: The number of buffer items to retrieve, and the
number of items that were retrieved.
Return: HRESULT indiating the status of the function.
******************************************************************************/
HRESULT CMainFrame::GetDeviceData (DWORD &dwCount)
{
HRESULT hr;
hr = g_pdidKeyboard->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), g_dodBuffer, &dwCount, 0);
if( FAILED( hr ) )
{
//C: Either an error or a DI_BUFFEROVERFLOW occurred. Continuous
// contact with the device has been lost, there fore it is possible
// that some events were lost.
//C: First verify that we have contact with the input device.
if(hr == DIERR_INPUTLOST)
{
//C: This app no longer has control of the keyboard, The keyboard
// will need to be re-acquired before we can continue.
hr = g_pdidKeyboard->Acquire();
if (FAILED(hr))
{
ATLTRACE("Could not aquire the keyboard focus.");
ATLASSERT(0);
return hr;
}
//C: The state of all of the buttons will now need to be synchronized.
hr = g_pdidKeyboard->GetDeviceState(sizeof(m_bKBState), &m_bKBState);
if (FAILED(hr))
{
ATLTRACE("Could not synchronize the state of the keyboard.");
return hr;
}
//C: The state for the keyboard will need to be retrieved again.
return GetDeviceData(dwCount);
}
}
return hr;
}
/* Private ********************************************************************
Author: Paul Watt
Date: 4/16/2002
Purpose: Manages the input for all of the main start screen.
Parameters: dData[in]: A structure that indicates an event for one of the
input devices.
Return: HRESULT indicates the status of this function.
******************************************************************************/
HRESULT CMainFrame::HandleMainScreenInput (DIDEVICEOBJECTDATA &dData)
{
//C: Only process the keystroke if the state of the key is down.
if (!dData.dwData)
{
return S_OK;
}
//C: Switch on the input data button that is passed in.
bool isCommand = false;
if (dData.dwOfs == m_bCommands[GAME_START])
{
//C: Start the game.
m_view.OnStartGame();
m_MusicPlayer.SetVolume(m_musicLevel);
m_MusicPlayer.Play();
//C: This will refresh the controls to prevent the rotate button from sticking.
UpdateCC();
isCommand = true;
}
else if (dData.dwOfs == m_bCommands[GAME_OPTIONS])
{
//C: Set the view into options mode.
m_view.SetState(CQuadrinoView::OPTIONS);
//C: Make sure the music is not playing.
m_MusicPlayer.Stop();
m_MusicPlayer.Rewind();
isCommand = true;
}
else if (dData.dwOfs == m_bCommands[GAME_EXIT])
{
//C: Exit the program.
End();
SendMessage(WM_CLOSE, 0, 0);
isCommand = true;
}
//C: Play a sound if a valid command was set.
if (isCommand && m_pSoundState)
{
m_pSoundState->Play();
}
return S_OK;
}
/* Private ********************************************************************
Author: Paul Watt
Date: 4/16/2002
Purpose: Manages the input for all of the options screen.
Parameters: dData[in]: A structure that indicates an event for one of the
input devices.
Return: HRESULT indicates the status of this function.
******************************************************************************/
HRESULT CMainFrame::HandleOptionsScreenInput (DIDEVICEOBJECTDATA &dData)
{
//C: Only process the keystroke if the state of the key is down.
if (!dData.dwData)
{
return S_OK;
}
//C: Switch on the input data button that is passed in.
m_view.SetState(CQuadrinoView::NORMAL);
if (m_pSoundState)
{
m_pSoundState->Play();
}
return S_OK;
}
/* Private ********************************************************************
Author: Paul Watt
Date: 4/16/2002
Purpose: Manages the input for the pause screen.
Parameters: dData[in]: A structure that indicates an event for one of the
input devices.
Return: HRESULT indicates the status of this function.
******************************************************************************/
HRESULT CMainFrame::HandlePauseScreenInput (DIDEVICEOBJECTDATA &dData)
{
//C: Only process the keystroke if the state of the key is down.
if (!dData.dwData)
{
return S_OK;
}
//C: Switch on the input data button that is passed in.
bool isCommand = false;
if (dData.dwOfs == m_bCommands[GAME_CONTINUE])
{
//C: Resume the game.
Resume();
isCommand = true;
}
else if (dData.dwOfs == m_bCommands[GAME_QUIT])
{
//C: Quit the game.
End();
isCommand = true;
}
else if (dData.dwOfs == m_bCommands[GAME_EXIT])
{
//C: Exit the program.
End();
SendMessage(WM_CLOSE, 0, 0);
isCommand = true;
}
//C: Play a sound if a valid command was set.
if (isCommand && m_pSoundState)
{
m_pSoundState->Play();
}
return S_OK;
}
/* Private ********************************************************************
Author: Paul Watt
Date: 4/16/2002
Purpose: Manages the input for the game.
Parameters: dData[in]: A structure that indicates an event for one of the
input devices.
Return: HRESULT indicates the status of this function.
******************************************************************************/
HRESULT CMainFrame::HandleGameInput (DIDEVICEOBJECTDATA &dData)
{
//C: Only process the keystroke if the state of the key is down.
if (!dData.dwData)
{
return S_OK;
}
//C: Switch on the input data button that is passed in.
if (dData.dwOfs == m_bCommands[ROTATE_PIECE_CCW])
{
int result = m_game.Rotate(false);
if (SUCCESS == result && m_pSoundRotate)
{
m_pSoundRotate->Play();
}
}
else if (dData.dwOfs == m_bCommands[ROTATE_PIECE_CW])
{
int result = m_game.Rotate(true);
if (SUCCESS == result && m_pSoundRotate)
{
m_pSoundRotate->Play();
}
}
else if (dData.dwOfs == m_bCommands[MOVE_PIECE_RIGHT])
{
int result = m_game.Move(1, MOVE_RIGHT);
if (SUCCESS == result && m_pSoundMove)
{
m_pSoundMove->Play();
}
}
else if (dData.dwOfs == m_bCommands[MOVE_PIECE_LEFT])
{
int result = m_game.Move(1, MOVE_LEFT);
if (SUCCESS == result && m_pSoundMove)
{
m_pSoundMove->Play();
}
}
else if (dData.dwOfs == m_bCommands[MOVE_PIECE_DOWN])
{
int result = m_game.Move(1, MOVE_DOWN);
if (SUCCESS == result && m_pSoundMove)
{
m_pSoundMove->Play();
}
}
else if (dData.dwOfs == m_bCommands[MOVE_PIECE_DROP])
{
int result = m_game.Move(1, MOVE_DROP);
#pragma message( REMIND( "PMW: Find a sound for the drop event." ) )
/* if (SUCCESS == result && m_pSoundDrop)
{
m_pSoundDrop->Play();
}
*/ }
else if (dData.dwOfs == m_bCommands[SWAP_PIECE])
{
//C: If the current game piece can be swapped, activate the
// swap animation.
m_view.OnSwap();
}
else if (dData.dwOfs == m_bCommands[GAME_PAUSE])
{
//C: Pause the game.
Pause();
//C: Play a sound if a valid command was set.
if (m_pSoundState)
{
m_pSoundState->Play();
}
}
return S_OK;
}
/* Private ********************************************************************
Author: Paul Watt
Date: 4/16/2002
Purpose: Manages the input for commands that function when a key is
continuously held down.
Parameters: dwTimeStamp[in]: The time stamp for which the input test is to
be performed.
Return: HRESULT indicates the status of this function.
******************************************************************************/
HRESULT CMainFrame::HandleContinuousInput (DWORD dwTimeStamp)
{
//C: There is currently only commands in the game mode that respond
// to continuous input.
if (!m_game.IsInit() || m_game.IsPaused())
{
return S_OK;
}
//C: Cycle through all of the input items, and generate events if the
// required time has elaspsed.
for (int index = 0; index < 5; ++index)
{
DWORD dwCommand = m_cc[index].dwCommand;
if (m_bKBState[dwCommand] & 0x80)
{
//C: Calculate the length of time that the current command key has
// been held down.
DWORD dwTime = dwTimeStamp - m_dwTimeStamps[dwCommand];
//C: Check if the current key is in its initial state.
if (true == m_cc[index].isInitial)
{
//C: This is the first event for the current key press, check if the
// time has exceeded, the initial event time.
if (dwTime > INITIAL_EVENT_TIME)
{
m_cc[index].isInitial = false;
m_cc[index].isFire = true;
}
}
else
{
//C: Determine how many EVENT periods the current key has been held
// down for.
DWORD count = ((dwTime - INITIAL_EVENT_TIME) / m_cc[index].dwEventTime) + 1;
//C: If the count is greater than the number of events that have been fired,
// then another event must be fired.
if (count > m_cc[index].dwEventCount)
{
m_cc[index].isFire = true;
}
}
}
else
{
//C: The key is up. Set the command to its initial state.
m_cc[index].isInitial = true;
m_cc[index].dwEventCount = 0;
}
//C: Fire the event.
if (true == m_cc[index].isFire)
{
m_cc[index].isFire = false;
m_cc[index].dwEventCount++;
int result;
switch (index)
{
case 0:
result = m_game.Move(1, MOVE_LEFT);
if (SUCCESS == result && m_pSoundMove)
{
m_pSoundMove->Play();
}
break;
case 1:
result = m_game.Move(1, MOVE_RIGHT);
if (SUCCESS == result && m_pSoundMove)
{
m_pSoundMove->Play();
}
break;
case 2:
result = m_game.Move(1, MOVE_DOWN);
if (SUCCESS == result && m_pSoundMove)
{
m_pSoundMove->Play();
}
break;
case 3:
result = m_game.Rotate(false);
if (SUCCESS == result && m_pSoundRotate)
{
m_pSoundRotate->Play();
}
break;
case 4:
result = m_game.Rotate(true);
if (SUCCESS == result && m_pSoundRotate)
{
m_pSoundRotate->Play();
}
break;
}
}
}
//C: Done.
return S_OK;
}
/* Private ********************************************************************
Author: Paul Watt
Date: 5/4/2002
Purpose: Set all of the user options to the default settings.
Parameters: NONE
Return: -
******************************************************************************/
void CMainFrame::SetDefaultSettings ()
{
//C: The default game display mode is windowed.
m_isWindowed = true;
//C: Set the keyboard commands.
m_bCommands[GAME_CONTINUE] = DIK_C;
m_bCommands[GAME_EXIT] = DIK_X;
m_bCommands[GAME_OPTIONS] = DIK_O;
m_bCommands[GAME_PAUSE] = DIK_P;
m_bCommands[GAME_QUIT] = DIK_Q;
m_bCommands[GAME_START] = DIK_S;
m_bCommands[MOVE_PIECE_LEFT] = DIK_LEFT;
m_bCommands[MOVE_PIECE_RIGHT] = DIK_RIGHT;
m_bCommands[MOVE_PIECE_DOWN] = DIK_DOWN;
m_bCommands[MOVE_PIECE_DROP] = DIK_UP;
m_bCommands[ROTATE_PIECE_CCW] = DIK_A;
m_bCommands[ROTATE_PIECE_CW] = DIK_S;
m_bCommands[SWAP_PIECE] = DIK_SPACE;
m_musicLevel = 100;
m_soundLevel = 75;
//C: Update the CC structures for continuous input processing.
UpdateCC();
}
/* Public *********************************************************************
Author: Paul Watt
Date: 5/5/2002
Purpose: Updates the continuous input items structure. This is neccesary
in order to process the commands that generate events when the
keys are held down.
Parameters: NONE
Return: -
******************************************************************************/
void CMainFrame::UpdateCC()
{
m_cc[0].dwCommand = m_bCommands[MOVE_PIECE_LEFT];
m_cc[0].dwTimeStamp = 0;
m_cc[0].dwEventCount = 0;
m_cc[0].dwEventTime = CONTINUOUS_MOVE_TIME;
m_cc[0].isInitial = true;
m_cc[0].isFire = false;
m_cc[1].dwCommand = m_bCommands[MOVE_PIECE_RIGHT];
m_cc[1].dwTimeStamp = 0;
m_cc[1].dwEventCount = 0;
m_cc[1].dwEventTime = CONTINUOUS_MOVE_TIME;
m_cc[1].isInitial = true;
m_cc[1].isFire = false;
m_cc[2].dwCommand = m_bCommands[MOVE_PIECE_DOWN];
m_cc[2].dwTimeStamp = 0;
m_cc[2].dwEventCount = 0;
m_cc[2].dwEventTime = CONTINUOUS_MOVE_TIME;
m_cc[2].isInitial = true;
m_cc[2].isFire = false;
m_cc[3].dwCommand = m_bCommands[ROTATE_PIECE_CCW];
m_cc[3].dwTimeStamp = 0;
m_cc[3].dwEventCount = 0;
m_cc[3].dwEventTime = CONTINUOUS_ROTATE_TIME;
m_cc[3].isInitial = true;
m_cc[3].isFire = false;
m_cc[4].dwCommand = m_bCommands[ROTATE_PIECE_CW];
m_cc[4].dwTimeStamp = 0;
m_cc[4].dwEventCount = 0;
m_cc[4].dwEventTime = CONTINUOUS_ROTATE_TIME;
m_cc[4].isInitial = true;
m_cc[4].isFire = false;
}
/* Global Functions **********************************************************/
/* Global *********************************************************************
Author: Paul Watt
Date: 4/16/2002
Purpose:
Parameters:
Return:
******************************************************************************/
BOOL CreateDInput( HWND hWnd )
{
HINSTANCE hInst = (HINSTANCE)GetWindowLongPtr( hWnd, GWLP_HINSTANCE );
HRESULT hr;
//C: Register with the DirectInput subsystem.
if (FAILED(hr = DirectInput8Create( hInst, DIRECTINPUT_VERSION, IID_IDirectInput8, (LPVOID*)&g_pDI, NULL)))
{
return hr;
}
g_pDI->Initialize(hInst, DIRECTINPUT_VERSION);
//C: Obtain an interface to the keybord device
if (FAILED(hr = g_pDI->CreateDevice( GUID_SysKeyboard, &g_pdidKeyboard, NULL)))
{
return hr;
}
#pragma message( REMIND( "PMW: Possibly add support for other input devices." ) )
//C: Set the data format to keyboard.
if (FAILED(hr = g_pdidKeyboard->SetDataFormat(&c_dfDIKeyboard)))
{
return hr;
}
//C: Set the cooperative level for the keyboard. For now
// DISCL_NONEXCLUSIVE | DISCL_FOREGROUND mode will be chosen
// because it will be the easiest to debug.
if (FAILED(hr = g_pdidKeyboard->SetCooperativeLevel(hWnd, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND)))
{
return hr;
}
//C: Set the buffer size for the input device[s].
DIPROPDWORD dipdw =
{
{
sizeof(DIPROPDWORD),
sizeof(DIPROPHEADER),
0,
DIPH_DEVICE,
},
KEYBOARD_BUFFERSIZE,
};
if (FAILED(hr = g_pdidKeyboard->SetProperty( DIPROP_BUFFERSIZE, &dipdw.diph)))
{
return hr;
}
return S_OK;
}
/* Global *********************************************************************
Author: Paul Watt
Date: 4/16/2002
Purpose: Destroys all of the resources that were aquired for processing this
game.
Parameters: NONE
Return: -
******************************************************************************/
VOID DestroyDInput()
{
//C: Destroy the keyboard object.
if (g_pdidKeyboard)
{
//C: Unacquire the device (just in case) before exitting.
g_pdidKeyboard->Unacquire();
g_pdidKeyboard->Release();
g_pdidKeyboard = NULL;
}
//C: Destroy the DInput object
if (g_pDI)
{
g_pDI->Release();
g_pDI = NULL;
}
}