AppleWin/source/DirectInput.cpp

259 lines
7.9 KiB
C++

/*
AppleWin : An Apple //e emulator for Windows
Copyright (C) 1994-1996, Michael O'Brien
Copyright (C) 1999-2001, Oliver Schmidt
Copyright (C) 2002-2005, Tom Charlesworth
Copyright (C) 2006-2010, Tom Charlesworth, Michael Pohoreski
AppleWin is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
AppleWin is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with AppleWin; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* Description: Disk Image
*
* Author: Various
*/
#include "StdAfx.h"
//=============================================================================
// DirectInput interface
//=============================================================================
//#define STRICT
#include "DirectInput.h"
#include "SoundCore.h" // SAFE_RELEASE()
#include "Log.h"
#include "Common.h"
#define DIRECTINPUT_VERSION 0x0800
#include <dinput.h>
extern bool g_bDisableDirectInput; // currently in AppleWin.h
namespace DIMouse
{
static LPDIRECTINPUT8 g_pDI = NULL;
static LPDIRECTINPUTDEVICE8 g_pMouse = NULL;
#define SAMPLE_BUFFER_SIZE 16 // arbitrary number of buffer elements
static UINT_PTR g_TimerIDEvent = 0;
//-----------------------------------------------------------------------------
// Name: OnCreateDevice()
// Desc: Sets up the mouse device using the flags from the dialog.
//-----------------------------------------------------------------------------
HRESULT DirectInputInit( HWND hDlg )
{
LogFileOutput("DirectInputInit: g_bDisableDirectInput=%d\n", g_bDisableDirectInput);
if (g_bDisableDirectInput)
return S_OK;
#ifdef NO_DIRECT_X
return E_FAIL;
#else // NO_DIRECT_X
HRESULT hr;
BOOL bExclusive;
BOOL bForeground;
BOOL bImmediate;
DWORD dwCoopFlags;
DirectInputUninit(hDlg);
LogFileOutput("DirectInputInit: DirectInputUninit()\n");
// Determine where the buffer would like to be allocated
bExclusive = FALSE;
bForeground = FALSE; // Otherwise get DIERR_OTHERAPPHASPRIO (== E_ACCESSDENIED) on Acquire()
bImmediate = TRUE;
if( bExclusive )
dwCoopFlags = DISCL_EXCLUSIVE;
else
dwCoopFlags = DISCL_NONEXCLUSIVE;
if( bForeground )
dwCoopFlags |= DISCL_FOREGROUND;
else
dwCoopFlags |= DISCL_BACKGROUND;
// Create a DInput object
hr = DirectInput8Create( GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (VOID**)&g_pDI, NULL );
LogFileOutput("DirectInputInit: DirectInput8Create(), hr=0x%08X\n", hr);
if (FAILED(hr))
return hr;
// Obtain an interface to the system mouse device.
hr = g_pDI->CreateDevice( GUID_SysMouse, &g_pMouse, NULL );
LogFileOutput("DirectInputInit: CreateDevice(), hr=0x%08X\n", hr);
if (FAILED(hr))
return hr;
// Set the data format to "mouse format" - 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
// DIMOUSESTATE2 structure to IDirectInputDevice::GetDeviceState.
hr = g_pMouse->SetDataFormat( &c_dfDIMouse2 );
LogFileOutput("DirectInputInit: SetDataFormat(), hr=0x%08X\n", hr);
if (FAILED(hr))
return hr;
// Set the cooperativity level to let DirectInput know how
// this device should interact with the system and with other
// DirectInput applications.
hr = g_pMouse->SetCooperativeLevel( hDlg, dwCoopFlags );
LogFileOutput("DirectInputInit: SetCooperativeLevel(), hr=0x%08X\n", hr);
if( hr == DIERR_UNSUPPORTED && !bForeground && bExclusive )
{
DirectInputUninit(hDlg);
LogFileOutput("DirectInputInit: DirectInputUninit()n");
//MessageBox( hDlg, _T("SetCooperativeLevel() returned DIERR_UNSUPPORTED.\n")
// _T("For security reasons, background exclusive mouse\n")
// _T("access is not allowed."),
// _T("Mouse"), MB_OK );
return S_OK;
}
if( FAILED(hr) )
return hr;
if( !bImmediate )
{
// IMPORTANT STEP TO USE BUFFERED DEVICE DATA!
//
// DirectInput uses unbuffered I/O (buffer size = 0) by default.
// If you want to read buffered data, you need to set a nonzero
// buffer size.
//
// Set the buffer size to SAMPLE_BUFFER_SIZE (defined above) elements.
//
// The buffer size is a DWORD property associated with the device.
DIPROPDWORD dipdw;
dipdw.diph.dwSize = sizeof(DIPROPDWORD);
dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
dipdw.diph.dwObj = 0;
dipdw.diph.dwHow = DIPH_DEVICE;
dipdw.dwData = SAMPLE_BUFFER_SIZE; // Arbitary buffer size
hr = g_pMouse->SetProperty( DIPROP_BUFFERSIZE, &dipdw.diph );
LogFileOutput("DirectInputInit: SetProperty(), hr=0x%08X\n", hr);
if (FAILED(hr))
return hr;
}
// Acquire the newly created device
hr = g_pMouse->Acquire();
LogFileOutput("DirectInputInit: Acquire(), hr=0x%08X\n", hr);
if (FAILED(hr))
return hr;
// Setup timer to read mouse position
_ASSERT(g_TimerIDEvent == 0);
g_TimerIDEvent = SetTimer(hDlg, IDEVENT_TIMER_MOUSE, 8, NULL); // 120Hz timer
LogFileOutput("DirectInputInit: SetTimer(), id=0x%08X\n", g_TimerIDEvent);
if (g_TimerIDEvent == 0)
return E_FAIL;
return S_OK;
#endif // NO_DIRECT_X
}
//-----------------------------------------------------------------------------
// Name: FreeDirectInput()
// Desc: Initialize the DirectInput variables.
//-----------------------------------------------------------------------------
void DirectInputUninit( HWND hDlg )
{
LogFileOutput("DirectInputUninit\n");
// Unacquire the device one last time just in case
// the app tried to exit while the device is still acquired.
if( g_pMouse )
{
HRESULT hr = g_pMouse->Unacquire();
LogFileOutput("DirectInputUninit: Unacquire(), hr=0x%08X\n", hr);
}
// Release any DirectInput objects.
SAFE_RELEASE( g_pMouse );
SAFE_RELEASE( g_pDI );
if (g_TimerIDEvent)
{
BOOL bRes = KillTimer(hDlg, g_TimerIDEvent);
LogFileOutput("DirectInputUninit: KillTimer(), res=%d\n", bRes ? 1 : 0);
g_TimerIDEvent = 0;
}
}
//-----------------------------------------------------------------------------
// Name: ReadImmediateData()
// Desc: Read the input device's state when in immediate mode and display it.
//-----------------------------------------------------------------------------
HRESULT ReadImmediateData( long* pX, long* pY )
{
HRESULT hr;
DIMOUSESTATE2 dims2; // DirectInput mouse state structure
if (pX) *pX = 0;
if (pY) *pY = 0;
if( NULL == g_pMouse )
return S_OK;
// Get the input's device state, and put the state in dims
ZeroMemory( &dims2, sizeof(dims2) );
hr = g_pMouse->GetDeviceState( sizeof(DIMOUSESTATE2), &dims2 );
if( FAILED(hr) )
{
// DirectInput may be 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.
// If input is lost then acquire and keep trying
hr = g_pMouse->Acquire();
while( hr == DIERR_INPUTLOST )
hr = g_pMouse->Acquire();
// Update the dialog text
if( hr == DIERR_OTHERAPPHASPRIO ||
hr == DIERR_NOTACQUIRED )
{
//SetDlgItemText( hDlg, IDC_DATA, TEXT("Unacquired") );
}
// hr may be DIERR_OTHERAPPHASPRIO or other errors. This
// may occur when the app is minimized or in the process of
// switching, so just try again later
return S_OK;
}
if (pX) *pX = dims2.lX;
if (pY) *pY = dims2.lY;
return S_OK;
}
}; // namespace DIMouse