HRESULT Rayman2InputFix_DirectInputA::EnumDevices(DWORD dwDevType,
	LPDIENUMDEVICESCALLBACKA lpCallback, LPVOID pvRef, DWORD dwFlags)
{
	Debug("DI: EnumDevices called\n");
	Debug("dwDevType == %d\n", dwDevType);
#if 1
	HRESULT hr;

	// The bug: Rayman 2 expects EnumDevices to give results in a certain
	// order, where gamepads come before the keyboard. DirectInput makes
	// no guarantee about the order.
	// The fix: Call DirectInput's EnumDevices, then sort the results in
	// an order where gamepads come first, then give them to Rayman 2.

	typedef std::list<DIDEVICEINSTANCEA> DeviceInstanceList;
	struct DeviceEnumerator
	{
		DeviceInstanceList devices;

		static BOOL FAR PASCAL Callback(LPCDIDEVICEINSTANCEA lpddi, LPVOID pvRef)
		{
			DeviceEnumerator* self = (DeviceEnumerator*)pvRef;
			self->devices.push_back(*lpddi);
			return DIENUM_CONTINUE;
		}

		bool Contains(const GUID& guidInstance)
		{
			for (DeviceInstanceList::const_iterator it = devices.begin();
				it != devices.end(); ++it)
			{
				if (it->guidInstance == guidInstance) {
					return true;
				}
			}
			return false;
		}
	};

	DeviceEnumerator joystickDevices;
	hr = m_realDirectInput->EnumDevices(DIDEVTYPE_JOYSTICK, DeviceEnumerator::Callback, &joystickDevices, dwFlags);
	if (FAILED(hr)) {
		return hr;
	}

	DeviceEnumerator allDevices;
	hr = m_realDirectInput->EnumDevices(0, DeviceEnumerator::Callback, &allDevices, dwFlags);
	if (FAILED(hr)) {
		return hr;
	}

	DeviceInstanceList sortedDevices;

	if (dwDevType == 0 || dwDevType == DIDEVTYPE_JOYSTICK)
	{
		// Add all devices in gameDevices
		for (DeviceInstanceList::const_iterator it = joystickDevices.devices.begin();
			it != joystickDevices.devices.end(); ++it)
		{
			sortedDevices.push_back(*it);
		}
	}

	if (dwDevType == 0)
	{
		// Then, add all devices in allDevices that aren't in gameDevices
		for (DeviceInstanceList::const_iterator it = allDevices.devices.begin();
			it != allDevices.devices.end(); ++it)
		{
			if (!joystickDevices.Contains(it->guidInstance)) {
				sortedDevices.push_back(*it);
			}
		}
	}

	for (DeviceInstanceList::const_iterator it = sortedDevices.begin();
		it != sortedDevices.end(); ++it)
	{
		OutputDebugStringA("Enumerating Product: ");
		OutputDebugStringA(it->tszProductName);
		OutputDebugStringA(" Instance: ");
		OutputDebugStringA(it->tszInstanceName);
		OutputDebugStringA("\n");
		if (lpCallback(&*it, pvRef) == DIENUM_STOP) {
			break;
		}
	}

	return DI_OK;
#else
	return m_realDirectInput->EnumDevices(dwDevType, lpCallback, pvRef, dwFlags);
#endif
}
Exemplo n.º 2
0
BOOL DI_HID_WrapperBase::EnumDevicesCallback( LPCDIDEVICEINSTANCEA dev_inst, LPVOID cb_userdata ) {

	DeviceInstanceList * devices = ( DeviceInstanceList * )cb_userdata;
	devices->push_back( *dev_inst );
	return TRUE;
}