XInput support

This commit is contained in:
elasota
2019-12-29 17:39:19 -05:00
parent 430842d17b
commit 77441c19fd
31 changed files with 856 additions and 76 deletions

View File

@@ -31,6 +31,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GpDisplayDriver_D3D11", "Gp
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ImportCharSet", "ImportCharSet\ImportCharSet.vcxproj", "{B3D152CB-CD52-4CD6-9213-710ADE1B8EB0}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GpInputDriver_XInput", "GpInputDriver_XInput\GpInputDriver_XInput.vcxproj", "{17B96F07-EF92-47CD-95A5-8E6EE38AB564}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@@ -151,6 +153,14 @@ Global
{B3D152CB-CD52-4CD6-9213-710ADE1B8EB0}.Release|x64.Build.0 = Release|x64
{B3D152CB-CD52-4CD6-9213-710ADE1B8EB0}.Release|x86.ActiveCfg = Release|Win32
{B3D152CB-CD52-4CD6-9213-710ADE1B8EB0}.Release|x86.Build.0 = Release|Win32
{17B96F07-EF92-47CD-95A5-8E6EE38AB564}.Debug|x64.ActiveCfg = Debug|x64
{17B96F07-EF92-47CD-95A5-8E6EE38AB564}.Debug|x64.Build.0 = Debug|x64
{17B96F07-EF92-47CD-95A5-8E6EE38AB564}.Debug|x86.ActiveCfg = Debug|Win32
{17B96F07-EF92-47CD-95A5-8E6EE38AB564}.Debug|x86.Build.0 = Debug|Win32
{17B96F07-EF92-47CD-95A5-8E6EE38AB564}.Release|x64.ActiveCfg = Release|x64
{17B96F07-EF92-47CD-95A5-8E6EE38AB564}.Release|x64.Build.0 = Release|x64
{17B96F07-EF92-47CD-95A5-8E6EE38AB564}.Release|x86.ActiveCfg = Release|Win32
{17B96F07-EF92-47CD-95A5-8E6EE38AB564}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@@ -89,6 +89,10 @@ typedef struct
// long encrypted, fakeLong;
long wasLeftMap, wasRightMap;
long wasBattMap, wasBandMap;
long wasGPLeftMap, wasGPRightMap;
long wasGPBattMap, wasGPBandMap;
long wasGPFlipMap;
long wasGPFaceLeftMap, wasGPFaceRightMap;
short wasVolume;
short prefVersion;
short wasMaxFiles;

View File

@@ -551,8 +551,8 @@
#define kGliderBurningHigh 26
#define kShadowHigh 9
#define kShadowTop 306
#define kFaceRight TRUE
#define kFaceLeft FALSE
static const Boolean kFaceRight = TRUE; // Conflicts with GP input driver
static const Boolean kFaceLeft = FALSE; // Conflicts with GP input driver
#define kPlayer1 TRUE
#define kPlayer2 FALSE
#define kNumGliderSrcRects 31
@@ -623,3 +623,5 @@
#define kScoreboardPictID 1997
#define kDemoLength 6702
#define kGamepadDeadzone 4096 // Out of 32768

View File

@@ -6,7 +6,7 @@
#include "PLQDOffscreen.h"
#include "GpVOSEvent.h"
typedef struct
{
@@ -208,6 +208,10 @@ typedef struct
Rect clip, enteredRect;
Int32 leftKey, rightKey;
Int32 battKey, bandKey;
Int32 gamepadLeftKey, gamepadRightKey;
Int32 gamepadBattKey, gamepadBandKey;
Int32 gamepadFlipKey;
Int32 gamepadFaceLeftKey, gamepadFaceRightKey;
short hVel, vVel;
short wasHVel, wasVVel;
short vDesiredVel, hDesiredVel;
@@ -215,7 +219,7 @@ typedef struct
Boolean facing, tipped;
Boolean sliding, ignoreLeft, ignoreRight;
Boolean fireHeld, which;
Boolean heldLeft, heldRight;
Boolean heldLeft, heldRight, heldFlip;
Boolean dontDraw, ignoreGround;
} gliderType, *gliderPtr;

View File

@@ -9,6 +9,7 @@
#include "PLDialogs.h"
#include "PLKeyEncoding.h"
#include "Externs.h"
#include "InputManager.h"
#include "MainWindow.h"
#include "RectUtils.h"
@@ -198,9 +199,13 @@ void DoHeliumEngaged (gliderPtr thisGlider)
#if BUILD_ARCADE_VERSION
if ((BitTst(theKeys, thisGlider->leftKey)) ||
(BitTst(theKeys, thisGlider->gamepadLeftKey)) ||
(BitTst(theKeys, thisGlider->rightKey)) ||
(BitTst(theKeys, thisGlider->gamepadRightKey)) ||
(BitTst(theKeys, thisGlider->battKey)) ||
(BitTst(theKeys, thisGlider->bandKey)))
(BitTst(theKeys, thisGlider->gamepadBattKey)) ||
(BitTst(theKeys, thisGlider->bandKey)) ||
(BitTst(theKeys, thisGlider->gamepadBandKey)))
{
playing = false;
paused = false;
@@ -302,38 +307,96 @@ void GetInput (gliderPtr thisGlider)
}
else
{
bool continuousFlipState = false;
bool holdFlipState = false;
bool leftState = false;
bool rightState = false;
if (BitTst(theKeys, thisGlider->rightKey) || BitTst(theKeys, thisGlider->gamepadRightKey)) // right key
{
PL_NotYetImplemented_TODO("FixDemo"); // Flips aren't recorded in the demo properly
if (BitTst(theKeys, thisGlider->leftKey) || BitTst(theKeys, thisGlider->gamepadLeftKey))
continuousFlipState = true;
else
rightState = true;
}
else if (BitTst(theKeys, thisGlider->leftKey) || BitTst(theKeys, thisGlider->gamepadLeftKey)) // left key
leftState = true;
else
thisGlider->tipped = false;
if (BitTst(theKeys, thisGlider->gamepadRightKey))
rightState = true;
if (BitTst(theKeys, thisGlider->gamepadLeftKey))
leftState = true;
if (BitTst(theKeys, thisGlider->gamepadFaceLeftKey) && thisGlider->facing == kFaceRight)
continuousFlipState = true;
if (BitTst(theKeys, thisGlider->gamepadFaceRightKey) && thisGlider->facing == kFaceLeft)
continuousFlipState = true;
if (BitTst(theKeys, thisGlider->gamepadFlipKey))
holdFlipState = true;
if (thisGlider->which == kPlayer1 || thisGlider->which == kPlayer2)
{
unsigned int playerNum = 0;
if (thisGlider->which == kPlayer1)
playerNum = 0;
else if (thisGlider->which == kPlayer2)
playerNum = 1;
int16_t inputAxis = PortabilityLayer::InputManager::GetInstance()->GetGamepadAxis(playerNum, GpGamepadAxes::kLeftStickX);
if (inputAxis <= -kGamepadDeadzone)
leftState = true;
else if (inputAxis >= kGamepadDeadzone)
rightState = true;
}
// gamepad flip key
//if (BitTst(theKeys, thisGlider->gamepadFlipKey))
// holdFlipState = true;
thisGlider->heldLeft = false;
thisGlider->heldRight = false;
if (BitTst(theKeys, thisGlider->rightKey)) // right key
if (continuousFlipState)
{
#ifdef CREATEDEMODATA
LogDemoKey(0);
#endif
if (BitTst(theKeys, thisGlider->leftKey))
leftState = false;
rightState = false;
ToggleGliderFacing(thisGlider);
}
else if (holdFlipState)
{
if (!thisGlider->heldFlip)
{
ToggleGliderFacing(thisGlider);
thisGlider->heldLeft = true;
}
else
{
thisGlider->hDesiredVel += kNormalThrust;
thisGlider->tipped = (thisGlider->facing == kFaceLeft);
thisGlider->heldRight = true;
thisGlider->heldFlip = true;
}
}
else if (BitTst(theKeys, thisGlider->leftKey)) // left key
else
thisGlider->heldFlip = false;
if (rightState && !leftState)
{
thisGlider->hDesiredVel += kNormalThrust;
thisGlider->tipped = (thisGlider->facing == kFaceLeft);
thisGlider->heldRight = true;
}
if (leftState && !rightState)
{
#ifdef CREATEDEMODATA
LogDemoKey(1);
#endif
thisGlider->hDesiredVel -= kNormalThrust;
thisGlider->tipped = (thisGlider->facing == kFaceRight);
thisGlider->heldLeft = true;
}
else
if (!leftState && !rightState)
thisGlider->tipped = false;
if ((BitTst(theKeys, thisGlider->battKey)) && (batteryTotal != 0) &&
if ((BitTst(theKeys, thisGlider->battKey) || BitTst(theKeys, thisGlider->gamepadBattKey)) && (batteryTotal != 0) &&
(thisGlider->mode == kGliderNormal))
{
#ifdef CREATEDEMODATA
@@ -347,7 +410,7 @@ void GetInput (gliderPtr thisGlider)
else
batteryWasEngaged = false;
if ((BitTst(theKeys, thisGlider->bandKey)) && (bandsTotal > 0) &&
if ((BitTst(theKeys, thisGlider->bandKey) || BitTst(theKeys, thisGlider->gamepadBandKey)) && (bandsTotal > 0) &&
(thisGlider->mode == kGliderNormal))
{
#ifdef CREATEDEMODATA

View File

@@ -140,6 +140,10 @@ void VariableInit (void)
theGlider2.rightKey = PL_KEY_ASCII('D');
theGlider2.battKey = PL_KEY_ASCII('S');
theGlider2.bandKey = PL_KEY_ASCII('W');
theGlider2.gamepadLeftKey = PL_KEY_GAMEPAD_BUTTON(kDPadLeft, 1);
theGlider2.gamepadRightKey = PL_KEY_GAMEPAD_BUTTON(kDPadRight, 1);
theGlider2.gamepadBandKey = PL_KEY_GAMEPAD_BUTTON(kFaceDown, 1);
theGlider2.gamepadBattKey = PL_KEY_GAMEPAD_BUTTON(kFaceLeft, 1);
theGlider2.which = kPlayer2;
theMode = kSplashMode;

View File

@@ -14,7 +14,7 @@
#include "House.h"
#define kPrefsVersion 0x0034
#define kPrefsVersion 0x0035
void ReadInPrefs (void);
@@ -72,6 +72,13 @@ void ReadInPrefs (void)
theGlider.rightKey = thePrefs.wasRightMap;
theGlider.battKey = thePrefs.wasBattMap;
theGlider.bandKey = thePrefs.wasBandMap;
theGlider.gamepadLeftKey = thePrefs.wasGPLeftMap;
theGlider.gamepadRightKey = thePrefs.wasGPRightMap;
theGlider.gamepadBandKey = thePrefs.wasGPBandMap;
theGlider.gamepadBattKey = thePrefs.wasGPBattMap;
theGlider.gamepadFlipKey = thePrefs.wasGPFlipMap;
theGlider.gamepadFaceRightKey = thePrefs.wasGPFaceRightMap;
theGlider.gamepadFaceLeftKey = thePrefs.wasGPFaceLeftMap;
#ifndef COMPILEDEMO
#ifndef COMPILENOCP
encryptedNumber = thePrefs.encrypted;
@@ -138,6 +145,13 @@ void ReadInPrefs (void)
theGlider.rightKey = PL_KEY_SPECIAL(kRightArrow);
theGlider.battKey = PL_KEY_SPECIAL(kDownArrow);
theGlider.bandKey = PL_KEY_SPECIAL(kUpArrow);
theGlider.gamepadLeftKey = PL_KEY_GAMEPAD_BUTTON(kDPadLeft, 0);
theGlider.gamepadRightKey = PL_KEY_GAMEPAD_BUTTON(kDPadRight, 0);
theGlider.gamepadBandKey = PL_KEY_GAMEPAD_BUTTON(kFaceDown, 0);
theGlider.gamepadBattKey = PL_KEY_GAMEPAD_BUTTON(kFaceLeft, 0);
theGlider.gamepadFlipKey = PL_KEY_GAMEPAD_BUTTON(kFaceUp, 0);
theGlider.gamepadFaceRightKey = PL_KEY_GAMEPAD_BUTTON(kRightBumper, 0);
theGlider.gamepadFaceLeftKey = PL_KEY_GAMEPAD_BUTTON(kLeftBumper, 0);
UnivGetSoundVolume(&isVolume, thisMac.hasSM3);
if (isVolume < 1)
@@ -228,6 +242,13 @@ void WriteOutPrefs (void)
thePrefs.wasRightMap = theGlider.rightKey;
thePrefs.wasBattMap = theGlider.battKey;
thePrefs.wasBandMap = theGlider.bandKey;
thePrefs.wasGPLeftMap = theGlider.gamepadLeftKey;
thePrefs.wasGPRightMap = theGlider.gamepadRightKey;
thePrefs.wasGPBattMap = theGlider.gamepadBattKey;
thePrefs.wasGPBandMap = theGlider.gamepadBandKey;
thePrefs.wasGPFlipMap = theGlider.gamepadFlipKey;
thePrefs.wasGPFaceLeftMap = theGlider.gamepadFaceLeftKey;
thePrefs.wasGPFaceRightMap = theGlider.gamepadFaceRightKey;
#ifndef COMPILEDEMO
#ifndef COMPILENOCP
thePrefs.encrypted = encryptedNumber;

View File

@@ -1225,6 +1225,13 @@ void SetAllDefaults (void)
theGlider.rightKey = PL_KEY_SPECIAL(kRightArrow);
theGlider.battKey = PL_KEY_SPECIAL(kDownArrow);
theGlider.bandKey = PL_KEY_SPECIAL(kUpArrow);
theGlider.gamepadLeftKey = PL_KEY_GAMEPAD_BUTTON(kDPadLeft, 0);
theGlider.gamepadRightKey = PL_KEY_GAMEPAD_BUTTON(kDPadRight, 0);
theGlider.gamepadBandKey = PL_KEY_GAMEPAD_BUTTON(kFaceDown, 0);
theGlider.gamepadBattKey = PL_KEY_GAMEPAD_BUTTON(kFaceLeft, 0);
theGlider.gamepadFlipKey = PL_KEY_GAMEPAD_BUTTON(kFaceUp, 0);
theGlider.gamepadFaceRightKey = PL_KEY_GAMEPAD_BUTTON(kRightBumper, 0);
theGlider.gamepadFaceLeftKey = PL_KEY_GAMEPAD_BUTTON(kLeftBumper, 0);
isEscPauseKey = false;
// Default sound settings
isPlayMusicIdle = true;

View File

@@ -0,0 +1,8 @@
#pragma once
enum EGpInputDriverType
{
EGpInputDriverType_XInput,
EGpInputDriverType_Count,
};

View File

@@ -0,0 +1,13 @@
#pragma once
#include "EGpInputDriverType.h"
struct IGpAudioDriver;
struct IGpVOSEventQueue;
struct GpInputDriverProperties
{
EGpInputDriverType m_type;
IGpVOSEventQueue *m_eventQueue;
};

View File

@@ -21,11 +21,62 @@ namespace GpKeyIDSubsets
kNumPadNumber,
kNumPadSpecial,
kFKey, // Key value is a raw F number
kGamepadButton,
kCount,
};
}
typedef GpKeyIDSubsets::GpKeyIDSubset GpKeyIDSubset_t;
namespace GpGamepadButtons
{
enum GpGamepadButton
{
kDPadUp,
kDPadDown,
kDPadLeft,
kDPadRight,
kFaceUp,
kFaceDown,
kFaceLeft,
kFaceRight,
kLeftStick,
kRightStick,
kLeftBumper,
kRightBumper,
kMisc1,
kMisc2,
kCount,
};
}
typedef GpGamepadButtons::GpGamepadButton GpGamepadButton_t;
namespace GpGamepadAxes
{
enum GpGamepadAxis
{
kLeftStickX,
kLeftStickY,
kRightStickX,
kRightStickY,
kLeftTrigger,
kRightTrigger,
kCount,
};
}
typedef GpGamepadAxes::GpGamepadAxis GpGamepadAxis_t;
namespace GpKeySpecials
{
enum GpKeySpecial
@@ -90,6 +141,22 @@ namespace GpKeyboardInputEventTypes
typedef GpKeyboardInputEventTypes::GpKeyboardInputEventType GpKeyboardInputEventType_t;
namespace GpGamepadInputEventTypes
{
enum GpGamepadInputEventType
{
kAnalogAxisChanged,
};
}
typedef GpGamepadInputEventTypes::GpGamepadInputEventType GpGamepadInputEventTypes_t;
struct GpGamepadButtonAndPlayer
{
GpGamepadButton_t m_button;
uint8_t m_player;
};
struct GpKeyboardInputEvent
{
union KeyUnion
@@ -100,6 +167,7 @@ struct GpKeyboardInputEvent
char m_asciiChar;
uint32_t m_unicodeChar;
unsigned char m_fKey;
GpGamepadButtonAndPlayer m_gamepadKey;
};
GpKeyboardInputEventType_t m_eventType;
@@ -107,6 +175,24 @@ struct GpKeyboardInputEvent
KeyUnion m_key;
};
struct GpGamepadAnalogAxisEvent
{
GpGamepadAxis_t m_axis;
int16_t m_state; // Ranges from -32767 to 32767, is never -32768
uint8_t m_player;
};
struct GpGamepadInputEvent
{
union EventUnion
{
GpGamepadAnalogAxisEvent m_analogAxisEvent;
};
GpGamepadInputEventTypes_t m_eventType;
EventUnion m_event;
};
namespace GpMouseEventTypes
{
enum GpMouseEventType
@@ -149,6 +235,7 @@ namespace GpVOSEventTypes
{
kKeyboardInput,
kMouseInput,
kGamepadInput,
};
}
@@ -160,6 +247,7 @@ struct GpVOSEvent
{
GpKeyboardInputEvent m_keyboardInputEvent;
GpMouseInputEvent m_mouseInputEvent;
GpGamepadInputEvent m_gamepadInputEvent;
};
EventUnion m_event;

View File

@@ -2,4 +2,6 @@
struct IGpInputDriver
{
virtual void ProcessInput() = 0;
virtual void Shutdown() = 0;
};

View File

@@ -6,6 +6,7 @@
#include "GpPLGlueDisplayDriver.h"
#include "HostSuspendCallArgument.h"
#include "IGpFiber.h"
#include "IGpInputDriver.h"
#include <assert.h>
@@ -13,6 +14,8 @@ GpAppEnvironment::GpAppEnvironment()
: m_applicationState(ApplicationState_NotStarted)
, m_displayDriver(nullptr)
, m_audioDriver(nullptr)
, m_inputDrivers(nullptr)
, m_numInputDrivers(0)
, m_fontHandler(nullptr)
, m_vosEventQueue(nullptr)
, m_applicationFiber(nullptr)
@@ -53,6 +56,7 @@ void GpAppEnvironment::Tick(IGpFiber *vosFiber)
case ApplicationState_WaitingForEvents:
return;
case ApplicationState_Running:
SynchronizeState();
m_applicationFiber->YieldTo();
break;
case ApplicationState_SystemCall:
@@ -96,6 +100,12 @@ void GpAppEnvironment::SetAudioDriver(IGpAudioDriver *audioDriver)
m_audioDriver = audioDriver;
}
void GpAppEnvironment::SetInputDrivers(IGpInputDriver *const* inputDrivers, size_t numDrivers)
{
m_inputDrivers = inputDrivers;
m_numInputDrivers = numDrivers;
}
void GpAppEnvironment::SetFontHandler(PortabilityLayer::HostFontHandler *fontHandler)
{
m_fontHandler = fontHandler;
@@ -125,13 +135,15 @@ void GpAppEnvironment::InitializeApplicationState()
GpAppInterface_Get()->PL_HostFontHandler_SetInstance(m_fontHandler);
GpAppInterface_Get()->PL_HostVOSEventQueue_SetInstance(m_vosEventQueue);
SynchronizeState();
GpPLGlueDisplayDriver::GetInstance()->SetGpDisplayDriver(m_displayDriver);
GpPLGlueAudioDriver::GetInstance()->SetGpAudioDriver(m_audioDriver);
}
void GpAppEnvironment::SynchronizeState()
{
GpPLGlueDisplayDriver::GetInstance()->SetGpDisplayDriver(m_displayDriver);
GpPLGlueAudioDriver::GetInstance()->SetGpAudioDriver(m_audioDriver);
const size_t numInputDrivers = m_numInputDrivers;
for (size_t i = 0; i < numInputDrivers; i++)
m_inputDrivers[i]->ProcessInput();
}
void GpAppEnvironment::StaticSuspendHookFunc(void *context, PortabilityLayer::HostSuspendCallID callID, const PortabilityLayer::HostSuspendCallArgument *args, PortabilityLayer::HostSuspendCallArgument *returnValue)

View File

@@ -14,6 +14,7 @@ namespace PortabilityLayer
struct IGpDisplayDriver;
struct IGpAudioDriver;
struct IGpInputDriver;
struct IGpFiber;
class GpAppEnvironment
@@ -29,6 +30,7 @@ public:
void SetDisplayDriver(IGpDisplayDriver *displayDriver);
void SetAudioDriver(IGpAudioDriver *audioDriver);
void SetInputDrivers(IGpInputDriver *const* inputDrivers, size_t numDrivers);
void SetFontHandler(PortabilityLayer::HostFontHandler *fontHandler);
void SetVOSEventQueue(GpVOSEventQueue *eventQueue);
@@ -54,12 +56,14 @@ private:
ApplicationState m_applicationState;
IGpDisplayDriver *m_displayDriver;
IGpAudioDriver *m_audioDriver;
IGpInputDriver *const* m_inputDrivers;
PortabilityLayer::HostFontHandler *m_fontHandler;
GpVOSEventQueue *m_vosEventQueue;
IGpFiber *m_applicationFiber;
IGpFiber *m_vosFiber;
uint32_t m_delaySuspendTicks;
size_t m_numInputDrivers;
PortabilityLayer::HostSuspendCallID m_suspendCallID;
const PortabilityLayer::HostSuspendCallArgument *m_suspendArgs;

View File

@@ -153,6 +153,7 @@
<ClCompile Include="GpFontHandlerFactory.cpp" />
<ClCompile Include="GpFontHandler_FreeType2.cpp" />
<ClCompile Include="GpGlobalConfig.cpp" />
<ClCompile Include="GpInputDriverFactory.cpp" />
<ClCompile Include="GpMain.cpp" />
<ClCompile Include="GpMain_Win32.cpp" />
<ClCompile Include="GpMemoryBuffer.cpp" />
@@ -166,20 +167,18 @@
<ClCompile Include="GpVOSEventQueue.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\GpCommon\EGpInputDriverType.h" />
<ClInclude Include="..\GpCommon\EGpStandardCursor.h" />
<ClInclude Include="..\GpCommon\GpInputDriverProperties.h" />
<ClInclude Include="..\GpCommon\IGpColorCursor.h" />
<ClInclude Include="..\GpCommon\IGpAudioChannelCallbacks.h" />
<ClInclude Include="..\GpCommon\GpColorCursor_Win32.h" />
<ClInclude Include="..\GpCommon\IGpDisplayDriverSurface.h" />
<ClInclude Include="EGpAudioDriverType.h" />
<ClInclude Include="EGpDisplayDriverType.h" />
<ClInclude Include="GpAppEnvironment.h" />
<ClInclude Include="GpAudioDriverFactory.h" />
<ClInclude Include="GpAudioDriverProperties.h" />
<ClInclude Include="GpComPtr.h" />
<ClInclude Include="GpCoreDefs.h" />
<ClInclude Include="GpDisplayDriverFactory.h" />
<ClInclude Include="GpDisplayDriverProperties.h" />
<ClInclude Include="GpFiber.h" />
<ClInclude Include="GpFiber_Win32.h" />
<ClInclude Include="GpFileStream_Win32.h" />
@@ -187,6 +186,7 @@
<ClInclude Include="GpFontHandler_FreeType2.h" />
<ClInclude Include="GpFontHandlerFactory.h" />
<ClInclude Include="GpGlobalConfig.h" />
<ClInclude Include="GpInputDriverFactory.h" />
<ClInclude Include="GpMain.h" />
<ClInclude Include="GpMemoryBuffer.h" />
<ClInclude Include="GpMutex_Win32.h" />
@@ -217,6 +217,9 @@
<ProjectReference Include="..\GpDisplayDriver_D3D11\GpDisplayDriver_D3D11.vcxproj">
<Project>{ffc961ac-55b4-4a38-a83e-06ae98f59acc}</Project>
</ProjectReference>
<ProjectReference Include="..\GpInputDriver_XInput\GpInputDriver_XInput.vcxproj">
<Project>{17b96f07-ef92-47cd-95a5-8e6ee38ab564}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="GpD3D.rc" />

View File

@@ -78,6 +78,9 @@
<ClCompile Include="GpColorCursor_Win32.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GpInputDriverFactory.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="GpWindows.h">
@@ -92,12 +95,6 @@
<ClInclude Include="GpMain.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="EGpDisplayDriverType.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpDisplayDriverProperties.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpGlobalConfig.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -140,12 +137,6 @@
<ClInclude Include="GpAudioDriverFactory.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="EGpAudioDriverType.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpAudioDriverProperties.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpPLGlueAudioDriver.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -191,6 +182,15 @@
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="GpInputDriverFactory.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\GpCommon\EGpInputDriverType.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\GpCommon\GpInputDriverProperties.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="GpD3D.rc">

View File

@@ -7,8 +7,8 @@ IGpDisplayDriver *GpDisplayDriverFactory::CreateDisplayDriver(const GpDisplayDri
{
assert(properties.m_type < EGpDisplayDriverType_Count);
if (ms_Registry[properties.m_type])
return ms_Registry[properties.m_type](properties);
if (ms_registry[properties.m_type])
return ms_registry[properties.m_type](properties);
else
return nullptr;
}
@@ -17,7 +17,7 @@ void GpDisplayDriverFactory::RegisterDisplayDriverFactory(EGpDisplayDriverType t
{
assert(type < EGpDisplayDriverType_Count);
ms_Registry[type] = func;
ms_registry[type] = func;
}
GpDisplayDriverFactory::FactoryFunc_t GpDisplayDriverFactory::ms_Registry[EGpDisplayDriverType_Count];
GpDisplayDriverFactory::FactoryFunc_t GpDisplayDriverFactory::ms_registry[EGpDisplayDriverType_Count];

View File

@@ -14,5 +14,5 @@ public:
static void RegisterDisplayDriverFactory(EGpDisplayDriverType type, FactoryFunc_t func);
private:
static FactoryFunc_t ms_Registry[EGpDisplayDriverType_Count];
static FactoryFunc_t ms_registry[EGpDisplayDriverType_Count];
};

View File

@@ -1,10 +1,16 @@
#pragma once
#include "EGpDisplayDriverType.h"
#include "EGpAudioDriverType.h"
#include "EGpInputDriverType.h"
struct GpGlobalConfig
{
EGpDisplayDriverType m_displayDriverType;
EGpAudioDriverType m_audioDriverType;
const EGpInputDriverType *m_inputDriverTypes;
size_t m_numInputDrivers;
void *m_osGlobals;
};

View File

@@ -0,0 +1,23 @@
#include "GpInputDriverFactory.h"
#include "GpInputDriverProperties.h"
#include <assert.h>
IGpInputDriver *GpInputDriverFactory::CreateInputDriver(const GpInputDriverProperties &properties)
{
assert(properties.m_type < EGpInputDriverType_Count);
if (ms_registry[properties.m_type])
return ms_registry[properties.m_type](properties);
else
return nullptr;
}
void GpInputDriverFactory::RegisterInputDriverFactory(EGpInputDriverType type, FactoryFunc_t func)
{
assert(type < EGpInputDriverType_Count);
ms_registry[type] = func;
}
GpInputDriverFactory::FactoryFunc_t GpInputDriverFactory::ms_registry[EGpInputDriverType_Count];

View File

@@ -0,0 +1,18 @@
#pragma once
#include "EGpInputDriverType.h"
struct IGpInputDriver;
struct GpInputDriverProperties;
class GpInputDriverFactory
{
public:
typedef IGpInputDriver *(*FactoryFunc_t)(const GpInputDriverProperties &properties);
static IGpInputDriver *CreateInputDriver(const GpInputDriverProperties &properties);
static void RegisterInputDriverFactory(EGpInputDriverType type, FactoryFunc_t func);
private:
static FactoryFunc_t ms_registry[EGpInputDriverType_Count];
};

View File

@@ -4,12 +4,16 @@
#include "GpFontHandlerFactory.h"
#include "GpDisplayDriverFactory.h"
#include "GpDisplayDriverProperties.h"
#include "GpInputDriverFactory.h"
#include "GpInputDriverProperties.h"
#include "GpGlobalConfig.h"
#include "GpAppEnvironment.h"
#include "IGpAudioDriver.h"
#include "IGpDisplayDriver.h"
#include "IGpInputDriver.h"
#include <string.h>
#include <stdlib.h>
namespace
{
@@ -32,8 +36,6 @@ int GpMain::Run()
GpDisplayDriverProperties ddProps;
memset(&ddProps, 0, sizeof(ddProps));
ddProps.m_type = EGpDisplayDriverType_D3D11;
ddProps.m_frameTimeLockNumerator = 1;
ddProps.m_frameTimeLockDenominator = 60;
@@ -58,10 +60,28 @@ int GpMain::Run()
// The sample rate used in all of Glider PRO's sound is 0x56ee8ba3
// This appears to be the "standard" Mac sample rate, probably rounded from 244800/11.
adProps.m_type = EGpAudioDriverType_XAudio2;
adProps.m_type = g_gpGlobalConfig.m_audioDriverType;
adProps.m_sampleRate = (244800 * 2 + 11) / (11 * 2);
adProps.m_debug = true;
IGpInputDriver **inputDrivers = static_cast<IGpInputDriver**>(malloc(sizeof(IGpInputDriver*) * g_gpGlobalConfig.m_numInputDrivers));
size_t numCreatedInputDrivers = 0;
if (inputDrivers)
{
for (size_t i = 0; i < g_gpGlobalConfig.m_numInputDrivers; i++)
{
GpInputDriverProperties inputProps;
memset(&inputProps, 0, sizeof(inputProps));
inputProps.m_type = g_gpGlobalConfig.m_inputDriverTypes[i];
inputProps.m_eventQueue = eventQueue;
if (IGpInputDriver *driver = GpInputDriverFactory::CreateInputDriver(inputProps))
inputDrivers[numCreatedInputDrivers++] = driver;
}
}
IGpDisplayDriver *displayDriver = GpDisplayDriverFactory::CreateDisplayDriver(ddProps);
IGpAudioDriver *audioDriver = GpAudioDriverFactory::CreateAudioDriver(adProps);
PortabilityLayer::HostFontHandler *fontHandler = GpFontHandlerFactory::Create();
@@ -70,11 +90,23 @@ int GpMain::Run()
appEnvironment->SetDisplayDriver(displayDriver);
appEnvironment->SetAudioDriver(audioDriver);
appEnvironment->SetInputDrivers(inputDrivers, numCreatedInputDrivers);
appEnvironment->SetFontHandler(fontHandler);
appEnvironment->SetVOSEventQueue(eventQueue);
// Start the display loop
displayDriver->Run();
// Clean up
if (inputDrivers)
{
for (size_t i = 0; i < numCreatedInputDrivers; i++)
inputDrivers[i]->Shutdown();
free(inputDrivers);
}
// GP TODO: Cleanup
return 0;
}

View File

@@ -5,6 +5,7 @@
#include "GpGlobalConfig.h"
#include "GpFiber_Win32.h"
#include "GpFileSystem_Win32.h"
#include "GpInputDriverFactory.h"
#include "GpAppInterface.h"
#include "GpSystemServices_Win32.h"
#include "GpVOSEvent.h"
@@ -21,6 +22,7 @@ GpWindowsGlobals g_gpWindowsGlobals;
extern "C" __declspec(dllimport) IGpAudioDriver *GpDriver_CreateAudioDriver_XAudio2(const GpAudioDriverProperties &properties);
extern "C" __declspec(dllimport) IGpDisplayDriver *GpDriver_CreateDisplayDriver_D3D11(const GpDisplayDriverProperties &properties);
extern "C" __declspec(dllimport) IGpInputDriver *GpDriver_CreateInputDriver_XInput(const GpInputDriverProperties &properties);
static void PostMouseEvent(IGpVOSEventQueue *eventQueue, GpMouseEventType_t eventType, GpMouseButton_t button, int32_t x, int32_t y)
{
@@ -372,10 +374,21 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
g_gpWindowsGlobals.m_translateWindowsMessageFunc = TranslateWindowsMessage;
g_gpGlobalConfig.m_displayDriverType = EGpDisplayDriverType_D3D11;
g_gpGlobalConfig.m_audioDriverType = EGpAudioDriverType_XAudio2;
EGpInputDriverType inputDrivers[] =
{
EGpInputDriverType_XInput
};
g_gpGlobalConfig.m_inputDriverTypes = inputDrivers;
g_gpGlobalConfig.m_numInputDrivers = sizeof(inputDrivers) / sizeof(inputDrivers[0]);
g_gpGlobalConfig.m_osGlobals = &g_gpWindowsGlobals;
GpDisplayDriverFactory::RegisterDisplayDriverFactory(EGpDisplayDriverType_D3D11, GpDriver_CreateDisplayDriver_D3D11);
GpAudioDriverFactory::RegisterAudioDriverFactory(EGpAudioDriverType_XAudio2, GpDriver_CreateAudioDriver_XAudio2);
GpInputDriverFactory::RegisterInputDriverFactory(EGpInputDriverType_XInput, GpDriver_CreateInputDriver_XInput);
return GpMain::Run();
}

View File

@@ -0,0 +1,183 @@
#include "GpInputDriverXInput.h"
#include "GpVOSEvent.h"
#include "GpWindows.h"
#include "IGpVOSEventQueue.h"
#include <stdlib.h>
#include <new>
#pragma comment(lib, "xinput.lib")
void GpInputDriverXInput::ProcessInput()
{
for (DWORD i = 0; i < XUSER_MAX_COUNT; i++)
{
XINPUT_STATE newState;
memset(&newState, 0, sizeof(newState));
DWORD result = XInputGetState(i, &newState);
if (result == ERROR_SUCCESS)
{
bool isNewState = false;
unsigned int playerNumber = 0;
if (m_xUserToPlayerNumber[i] < 0)
{
// Newly-connected player
for (int i = 0; i < XUSER_MAX_COUNT; i++)
{
if (!m_playerNumberIsConnected[i])
{
playerNumber = i;
break;
}
}
m_xUserToPlayerNumber[i] = playerNumber;
m_playerNumberIsConnected[playerNumber] = true;
isNewState = true;
}
else
{
playerNumber = m_xUserToPlayerNumber[i];
isNewState = (newState.dwPacketNumber != m_controllerStates[i].dwPacketNumber);
}
if (isNewState)
{
this->ProcessControllerStateChange(playerNumber, m_controllerStates[i], newState);
m_controllerStates[i] = newState;
}
}
else
{
if (m_xUserToPlayerNumber[i] >= 0)
{
// Was connected last frame, process as a blank state and then free the player slot
memset(&newState, 0, sizeof(newState));
const unsigned int playerNumber = m_xUserToPlayerNumber[i];
this->ProcessControllerStateChange(playerNumber, m_controllerStates[i], newState);
m_controllerStates[i] = newState;
m_playerNumberIsConnected[playerNumber] = false;
m_xUserToPlayerNumber[i] = -1;
}
}
}
}
void GpInputDriverXInput::Shutdown()
{
this->~GpInputDriverXInput();
free(this);
}
GpInputDriverXInput *GpInputDriverXInput::Create(const GpInputDriverProperties &props)
{
void *storage = malloc(sizeof(GpInputDriverXInput));
if (!storage)
return nullptr;
return new (storage) GpInputDriverXInput(props);
}
GpInputDriverXInput::GpInputDriverXInput(const GpInputDriverProperties &props)
: m_properties(props)
{
for (int i = 0; i < XUSER_MAX_COUNT; i++)
m_xUserToPlayerNumber[i] = -1;
memset(m_controllerStates, 0, sizeof(m_controllerStates));
memset(m_playerNumberIsConnected, 0, sizeof(m_playerNumberIsConnected));
}
GpInputDriverXInput::~GpInputDriverXInput()
{
}
void GpInputDriverXInput::ProcessControllerStateChange(unsigned int playerNumber, const XINPUT_STATE &prevState, const XINPUT_STATE &newState)
{
const XINPUT_GAMEPAD &prevGamepad = prevState.Gamepad;
const XINPUT_GAMEPAD &newGamepad = newState.Gamepad;
DWORD prevButtons = prevGamepad.wButtons;
DWORD newButtons = newGamepad.wButtons;
ProcessButtonStateChange(prevButtons, newButtons, XINPUT_GAMEPAD_START, playerNumber, GpGamepadButtons::kMisc1);
ProcessButtonStateChange(prevButtons, newButtons, XINPUT_GAMEPAD_BACK, playerNumber, GpGamepadButtons::kMisc2);
ProcessButtonStateChange(prevButtons, newButtons, XINPUT_GAMEPAD_DPAD_UP, playerNumber, GpGamepadButtons::kDPadUp);
ProcessButtonStateChange(prevButtons, newButtons, XINPUT_GAMEPAD_DPAD_DOWN, playerNumber, GpGamepadButtons::kDPadDown);
ProcessButtonStateChange(prevButtons, newButtons, XINPUT_GAMEPAD_DPAD_LEFT, playerNumber, GpGamepadButtons::kDPadLeft);
ProcessButtonStateChange(prevButtons, newButtons, XINPUT_GAMEPAD_DPAD_RIGHT, playerNumber, GpGamepadButtons::kDPadRight);
ProcessButtonStateChange(prevButtons, newButtons, XINPUT_GAMEPAD_LEFT_THUMB, playerNumber, GpGamepadButtons::kLeftStick);
ProcessButtonStateChange(prevButtons, newButtons, XINPUT_GAMEPAD_RIGHT_THUMB, playerNumber, GpGamepadButtons::kRightStick);
ProcessButtonStateChange(prevButtons, newButtons, XINPUT_GAMEPAD_LEFT_SHOULDER, playerNumber, GpGamepadButtons::kLeftBumper);
ProcessButtonStateChange(prevButtons, newButtons, XINPUT_GAMEPAD_RIGHT_SHOULDER, playerNumber, GpGamepadButtons::kRightBumper);
ProcessButtonStateChange(prevButtons, newButtons, XINPUT_GAMEPAD_Y, playerNumber, GpGamepadButtons::kFaceUp);
ProcessButtonStateChange(prevButtons, newButtons, XINPUT_GAMEPAD_A, playerNumber, GpGamepadButtons::kFaceDown);
ProcessButtonStateChange(prevButtons, newButtons, XINPUT_GAMEPAD_X, playerNumber, GpGamepadButtons::kFaceLeft);
ProcessButtonStateChange(prevButtons, newButtons, XINPUT_GAMEPAD_B, playerNumber, GpGamepadButtons::kFaceRight);
ProcessAxisStateChange(ConvertTriggerValue(prevState.Gamepad.bLeftTrigger), ConvertTriggerValue(newState.Gamepad.bLeftTrigger), playerNumber, GpGamepadAxes::kLeftTrigger);
ProcessAxisStateChange(ConvertTriggerValue(prevState.Gamepad.bRightTrigger), ConvertTriggerValue(newState.Gamepad.bRightTrigger), playerNumber, GpGamepadAxes::kRightTrigger);
ProcessAxisStateChange(prevState.Gamepad.sThumbLX, newState.Gamepad.sThumbLX, playerNumber, GpGamepadAxes::kLeftStickX);
ProcessAxisStateChange(prevState.Gamepad.sThumbLY, newState.Gamepad.sThumbLY, playerNumber, GpGamepadAxes::kLeftStickY);
ProcessAxisStateChange(prevState.Gamepad.sThumbRX, newState.Gamepad.sThumbRX, playerNumber, GpGamepadAxes::kRightStickX);
ProcessAxisStateChange(prevState.Gamepad.sThumbRY, newState.Gamepad.sThumbRY, playerNumber, GpGamepadAxes::kRightStickY);
}
void GpInputDriverXInput::ProcessButtonStateChange(DWORD prevState, DWORD newState, DWORD deltaBit, unsigned int playerNum, GpGamepadButton_t gamepadButton)
{
DWORD deltaState = prevState ^ newState;
if ((deltaState & deltaBit) == 0)
return;
const GpKeyboardInputEventType_t eventType = ((prevState & deltaBit) == 0) ? GpKeyboardInputEventTypes::kDown : GpKeyboardInputEventTypes::kUp;
if (GpVOSEvent *evt = m_properties.m_eventQueue->QueueEvent())
{
evt->m_eventType = GpVOSEventTypes::kKeyboardInput;
evt->m_event.m_keyboardInputEvent.m_eventType = eventType;
evt->m_event.m_keyboardInputEvent.m_keyIDSubset = GpKeyIDSubsets::kGamepadButton;
evt->m_event.m_keyboardInputEvent.m_key.m_gamepadKey.m_button = gamepadButton;
evt->m_event.m_keyboardInputEvent.m_key.m_gamepadKey.m_player = playerNum;
}
}
int16_t GpInputDriverXInput::ConvertTriggerValue(uint8_t v)
{
return static_cast<int16_t>((v * 257) >> 1);
}
void GpInputDriverXInput::ProcessAxisStateChange(int16_t prevState, int16_t newState, unsigned int playerNum, GpGamepadAxis_t gamepadAxis)
{
if (prevState != newState)
{
if (prevState == -32768)
prevState = -32767;
if (newState == -32768)
newState = -32767;
if (GpVOSEvent *evt = m_properties.m_eventQueue->QueueEvent())
{
evt->m_eventType = GpVOSEventTypes::kGamepadInput;
evt->m_event.m_gamepadInputEvent.m_eventType = GpGamepadInputEventTypes::kAnalogAxisChanged;
evt->m_event.m_gamepadInputEvent.m_event.m_analogAxisEvent.m_axis = gamepadAxis;
evt->m_event.m_gamepadInputEvent.m_event.m_analogAxisEvent.m_state = newState;
evt->m_event.m_gamepadInputEvent.m_event.m_analogAxisEvent.m_player = playerNum;
}
}
}
extern "C" __declspec(dllexport) IGpInputDriver *GpDriver_CreateInputDriver_XInput(const GpInputDriverProperties &properties)
{
return GpInputDriverXInput::Create(properties);
}

View File

@@ -0,0 +1,32 @@
#pragma once
#include "IGpInputDriver.h"
#include "GpInputDriverProperties.h"
#include "GpVOSEvent.h"
#include "GpWindows.h"
#include <Xinput.h>
class GpInputDriverXInput final : public IGpInputDriver
{
public:
void ProcessInput() override;
void Shutdown() override;
static GpInputDriverXInput *Create(const GpInputDriverProperties &props);
private:
GpInputDriverXInput(const GpInputDriverProperties &props);
~GpInputDriverXInput();
void ProcessControllerStateChange(unsigned int playerNumber, const XINPUT_STATE &prevState, const XINPUT_STATE &newState);
void ProcessButtonStateChange(DWORD prevState, DWORD newState, DWORD deltaBit, unsigned int playerNum, GpGamepadButton_t gamepadButton);
void ProcessAxisStateChange(int16_t prevState, int16_t newState, unsigned int playerNum, GpGamepadAxis_t gamepadAxis);
static int16_t ConvertTriggerValue(uint8_t v);
GpInputDriverProperties m_properties;
int m_xUserToPlayerNumber[XUSER_MAX_COUNT];
bool m_playerNumberIsConnected[XUSER_MAX_COUNT];
XINPUT_STATE m_controllerStates[XUSER_MAX_COUNT];
};

View File

@@ -0,0 +1,130 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{17B96F07-EF92-47CD-95A5-8E6EE38AB564}</ProjectGuid>
<RootNamespace>GpInputDriverXInput</RootNamespace>
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\GpCommon.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\GpCommon.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\GpCommon.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\GpCommon.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="GpInputDriverXInput.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="GpInputDriverXInput.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="GpInputDriverXInput.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="GpInputDriverXInput.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@@ -13,13 +13,18 @@ namespace PortabilityLayer
InputManagerImpl();
void GetKeys(KeyMap &keyMap) const override;
void ApplyEvent(const GpKeyboardInputEvent &vosEvent) override;
void ApplyKeyboardEvent(const GpKeyboardInputEvent &vosEvent) override;
void ApplyGamepadEvent(const GpGamepadInputEvent &vosEvent) override;
int16_t GetGamepadAxis(unsigned int playerNum, GpGamepadAxis_t gamepadAxis) override;
static InputManagerImpl *GetInstance();
private:
void ApplyEventAsKey(const GpKeyboardInputEvent &vosEvent, bool bit);
void ApplyAnalogAxisEvent(const GpGamepadAnalogAxisEvent &axisEvent);
KeyMap m_keyMap;
int16_t m_axisStates[PL_INPUT_MAX_PLAYERS][GpGamepadAxes::kCount];
static InputManagerImpl ms_instance;
};
@@ -29,7 +34,7 @@ namespace PortabilityLayer
keyMap = m_keyMap;
}
void InputManagerImpl::ApplyEvent(const GpKeyboardInputEvent &vosEvent)
void InputManagerImpl::ApplyKeyboardEvent(const GpKeyboardInputEvent &vosEvent)
{
if (vosEvent.m_eventType == GpKeyboardInputEventTypes::kDown)
ApplyEventAsKey(vosEvent, true);
@@ -37,6 +42,19 @@ namespace PortabilityLayer
ApplyEventAsKey(vosEvent, false);
}
void InputManagerImpl::ApplyGamepadEvent(const GpGamepadInputEvent &vosEvent)
{
if (vosEvent.m_eventType == GpGamepadInputEventTypes::kAnalogAxisChanged)
ApplyAnalogAxisEvent(vosEvent.m_event.m_analogAxisEvent);
}
int16_t InputManagerImpl::GetGamepadAxis(unsigned int playerNum, GpGamepadAxis_t gamepadAxis)
{
assert(playerNum < PL_INPUT_MAX_PLAYERS);
return m_axisStates[playerNum][gamepadAxis];
}
void InputManagerImpl::ApplyEventAsKey(const GpKeyboardInputEvent &vosEvent, bool bit)
{
switch (vosEvent.m_keyIDSubset)
@@ -70,12 +88,22 @@ namespace PortabilityLayer
case GpKeyIDSubsets::kFKey:
m_keyMap.m_fKey.Set(vosEvent.m_key.m_fKey - 1, bit);
break;
case GpKeyIDSubsets::kGamepadButton:
if (vosEvent.m_key.m_gamepadKey.m_player < PL_INPUT_MAX_PLAYERS)
m_keyMap.m_gamepadButtons[vosEvent.m_key.m_gamepadKey.m_player].Set(vosEvent.m_key.m_gamepadKey.m_button, bit);
break;
default:
assert(false);
break;
}
}
void InputManagerImpl::ApplyAnalogAxisEvent(const GpGamepadAnalogAxisEvent &axisEvent)
{
if (axisEvent.m_player < PL_INPUT_MAX_PLAYERS)
m_axisStates[axisEvent.m_player][axisEvent.m_axis] = axisEvent.m_state;
}
InputManagerImpl *InputManagerImpl::GetInstance()
{
return &ms_instance;
@@ -83,6 +111,7 @@ namespace PortabilityLayer
InputManagerImpl::InputManagerImpl()
{
memset(m_axisStates, 0, sizeof(m_axisStates));
}
InputManagerImpl InputManagerImpl::ms_instance;

View File

@@ -1,6 +1,9 @@
#pragma once
#include "GpVOSEvent.h"
struct GpKeyboardInputEvent;
struct GpGamepadInputEvent;
struct KeyMap;
namespace PortabilityLayer
@@ -9,7 +12,9 @@ namespace PortabilityLayer
{
public:
virtual void GetKeys(KeyMap &keys16) const = 0;
virtual void ApplyEvent(const GpKeyboardInputEvent &vosEvent) = 0;
virtual void ApplyKeyboardEvent(const GpKeyboardInputEvent &vosEvent) = 0;
virtual void ApplyGamepadEvent(const GpGamepadInputEvent &vosEvent) = 0;
virtual int16_t GetGamepadAxis(unsigned int playerNum, GpGamepadAxis_t gamepadAxis) = 0;
static InputManager *GetInstance();
};

View File

@@ -98,12 +98,24 @@ static void TranslateMouseInputEvent(const GpMouseInputEvent &vosEvent, Portabil
}
}
static void TranslateKeyboardInputEvent(const GpKeyboardInputEvent &vosEvent, PortabilityLayer::EventQueue *queue)
static void TranslateGamepadInputEvent(const GpGamepadInputEvent &vosEvent, PortabilityLayer::EventQueue *queue)
{
PortabilityLayer::InputManager *inputManager = PortabilityLayer::InputManager::GetInstance();
inputManager->ApplyGamepadEvent(vosEvent);
PL_DEAD(queue);
}
static void TranslateKeyboardInputEvent(const GpKeyboardInputEvent &vosEvent, PortabilityLayer::EventQueue *queue)
{
PL_STATIC_ASSERT((1 << PL_INPUT_PLAYER_INDEX_BITS) >= PL_INPUT_MAX_PLAYERS);
PL_STATIC_ASSERT((1 << PL_INPUT_TYPE_CODE_BITS) >= KeyEventType_Count);
PortabilityLayer::InputManager *inputManager = PortabilityLayer::InputManager::GetInstance();
if (vosEvent.m_eventType == GpKeyboardInputEventTypes::kUp || vosEvent.m_eventType == GpKeyboardInputEventTypes::kDown)
inputManager->ApplyEvent(vosEvent);
inputManager->ApplyKeyboardEvent(vosEvent);
intptr_t msg = 0;
@@ -134,6 +146,9 @@ static void TranslateKeyboardInputEvent(const GpKeyboardInputEvent &vosEvent, Po
}
}
break;
case GpKeyIDSubsets::kGamepadButton:
msg = PL_KEY_GAMEPAD_BUTTON_ENCODE(vosEvent.m_key.m_gamepadKey.m_button, vosEvent.m_key.m_gamepadKey.m_player);
break;
default:
PL_NotYetImplemented();
}
@@ -171,6 +186,9 @@ static void TranslateVOSEvent(const GpVOSEvent *vosEvent, PortabilityLayer::Even
case GpVOSEventTypes::kKeyboardInput:
TranslateKeyboardInputEvent(vosEvent->m_event.m_keyboardInputEvent, queue);
break;
case GpVOSEventTypes::kGamepadInput:
TranslateGamepadInputEvent(vosEvent->m_event.m_gamepadInputEvent, queue);
break;
}
}
@@ -521,6 +539,15 @@ bool BitTst(const KeyMap &keyMap, int encodedKey)
return keyMap.m_fKey.Get(evtValue - 1);
case KeyEventType_EitherSpecial:
return BitTestEitherSpecial(keyMap, evtValue);
case KeyEventType_GamepadButton:
{
unsigned int playerNum = evtValue & ((1 << PL_INPUT_PLAYER_INDEX_BITS) - 1);
assert(playerNum < PL_INPUT_MAX_PLAYERS);
unsigned int button = evtValue >> PL_INPUT_PLAYER_INDEX_BITS;
return keyMap.m_gamepadButtons[playerNum].Get(button);
}
break;
default:
assert(false);
return false;

View File

@@ -11,8 +11,10 @@ enum KeyEventType
KeyEventType_NumPadNumber,
KeyEventType_NumPadSpecial,
KeyEventType_FKey,
KeyEventType_EitherSpecial,
KeyEventType_GamepadButton,
KeyEventType_Count,
};
namespace KeyEventEitherSpecialCategories
@@ -25,18 +27,25 @@ namespace KeyEventEitherSpecialCategories
};
}
#define PL_KEY_SPECIAL(k) ((KeyEventType_Special) | (GpKeySpecials::k) << 3)
#define PL_KEY_SPECIAL_ENCODE(k) ((KeyEventType_Special) | (k) << 3)
#define PL_KEY_ASCII(k) ((KeyEventType_ASCII) | (k) << 3)
#define PL_KEY_MACROMAN(k) ((KeyEventType_MacRoman) | (k) << 3)
#define PL_KEY_NUMPAD_NUMBER(k) ((KeyEventType_NumPadNumber) | (k) << 3)
#define PL_KEY_NUMPAD_SPECIAL(k) ((KeyEventType_NumPadSpecial) | (GpKeySpecials::k) << 3)
#define PL_KEY_NUMPAD_SPECIAL_ENCODE(k) ((KeyEventType_NumPadSpecial) | (k) << 3)
#define PL_KEY_FKEY(k) ((KeyEventType_FKey) | (k) << 3)
#define PL_KEY_EITHER_SPECIAL(k) ((KeyEventType_EitherSpecial) | (KeyEventEitherSpecialCategories::k) << 3)
#define PL_INPUT_MAX_PLAYERS 2
#define PL_INPUT_PLAYER_INDEX_BITS 1
#define PL_KEY_GET_EVENT_TYPE(k) (static_cast<KeyEventType>(k & 7))
#define PL_KEY_GET_VALUE(k) ((k) >> 3)
#define PL_INPUT_TYPE_CODE_BITS 3
#define PL_KEY_SPECIAL(k) ((KeyEventType_Special) | ((GpKeySpecials::k) << PL_INPUT_TYPE_CODE_BITS))
#define PL_KEY_SPECIAL_ENCODE(k) ((KeyEventType_Special) | ((k) << PL_INPUT_TYPE_CODE_BITS))
#define PL_KEY_ASCII(k) ((KeyEventType_ASCII) | ((k) << PL_INPUT_TYPE_CODE_BITS))
#define PL_KEY_MACROMAN(k) ((KeyEventType_MacRoman) | ((k) << PL_INPUT_TYPE_CODE_BITS))
#define PL_KEY_NUMPAD_NUMBER(k) ((KeyEventType_NumPadNumber) | ((k) << PL_INPUT_TYPE_CODE_BITS))
#define PL_KEY_NUMPAD_SPECIAL(k) ((KeyEventType_NumPadSpecial) | ((GpKeySpecials::k) << PL_INPUT_TYPE_CODE_BITS))
#define PL_KEY_NUMPAD_SPECIAL_ENCODE(k) ((KeyEventType_NumPadSpecial) | ((k) << PL_INPUT_TYPE_CODE_BITS))
#define PL_KEY_FKEY(k) ((KeyEventType_FKey) | ((k) << PL_INPUT_TYPE_CODE_BITS))
#define PL_KEY_EITHER_SPECIAL(k) ((KeyEventType_EitherSpecial) | ((KeyEventEitherSpecialCategories::k) << PL_INPUT_TYPE_CODE_BITS))
#define PL_KEY_GAMEPAD_BUTTON(k, pl) ((KeyEventType_GamepadButton) | (pl << PL_INPUT_TYPE_CODE_BITS) | ((GpGamepadButtons::k) << (PL_INPUT_TYPE_CODE_BITS + PL_INPUT_PLAYER_INDEX_BITS)))
#define PL_KEY_GAMEPAD_BUTTON_ENCODE(k, pl) ((KeyEventType_GamepadButton) | (pl << PL_INPUT_TYPE_CODE_BITS) | ((k) << (PL_INPUT_TYPE_CODE_BITS + PL_INPUT_PLAYER_INDEX_BITS)))
#define PL_KEY_GET_EVENT_TYPE(k) (static_cast<KeyEventType>(k & ((1 << PL_INPUT_TYPE_CODE_BITS) - 1)))
#define PL_KEY_GET_VALUE(k) ((k) >> PL_INPUT_TYPE_CODE_BITS)
struct KeyMap
{
@@ -46,4 +55,5 @@ struct KeyMap
GpBitfield<10> m_numPadNumber;
GpBitfield<GpNumPadSpecials::kCount> m_numPadSpecial;
GpBitfield<GpFKeyMaximumInclusive> m_fKey;
GpBitfield<GpGamepadButtons::kCount> m_gamepadButtons[PL_INPUT_MAX_PLAYERS];
};