- Added joystick config loading and saving support; moved generic joystick

interfaces to m_joy.h.
- Added Raw Input PS2 adapter support.


SVN r1713 (trunk)
This commit is contained in:
Randy Heit 2009-07-11 01:40:01 +00:00
parent ae2c4a6dbc
commit 417779440d
15 changed files with 1733 additions and 156 deletions

View file

@ -1,4 +1,11 @@
July 6, 2009 (Changes by Graf Zahl)
July 10, 2009
- Added joystick config loading and saving support; moved generic joystick
interfaces to m_joy.h.
July 9, 2009
- Added Raw Input PS2 adapter support.
July 6, 2009 (Changes by Graf Zahl)
- Added Gez's A_WeaponReady enhancement submission.
July 5, 2009 (Changes by Graf Zahl)

View file

@ -412,6 +412,7 @@ if( WIN32 )
win32/i_keyboard.cpp
win32/i_mouse.cpp
win32/i_dijoy.cpp
win32/i_rawps2.cpp
win32/i_xinput.cpp
win32/i_main.cpp
win32/i_movie.cpp
@ -527,6 +528,7 @@ add_executable( zdoom WIN32
m_argv.cpp
m_bbox.cpp
m_cheat.cpp
m_joy.cpp
m_menu.cpp
m_misc.cpp
m_options.cpp

View file

@ -217,18 +217,6 @@ enum ESkillLevels
#define NUM_KEYS 0x1C4
enum EJoyAxis
{
JOYAXIS_None = -1,
JOYAXIS_Yaw,
JOYAXIS_Pitch,
JOYAXIS_Forward,
JOYAXIS_Side,
JOYAXIS_Up,
// JOYAXIS_Roll, // Ha ha. No roll for you.
NUM_JOYAXIS,
};
// [RH] dmflags bits (based on Q2's)
enum
{

View file

@ -75,6 +75,7 @@
#include "d_net.h"
#include "d_event.h"
#include "p_acs.h"
#include "m_joy.h"
#include <zlib.h>

144
src/m_joy.cpp Normal file
View file

@ -0,0 +1,144 @@
// HEADER FILES ------------------------------------------------------------
#include "m_joy.h"
#include "gameconfigfile.h"
// MACROS ------------------------------------------------------------------
// TYPES -------------------------------------------------------------------
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
// CODE --------------------------------------------------------------------
//==========================================================================
//
// M_SetJoystickConfigSection
//
// Sets up the config for reading or writing this controller's axis config.
//
//==========================================================================
static bool M_SetJoystickConfigSection(IJoystickConfig *joy, bool create)
{
FString id = "Joy:";
id += joy->GetIdentifier();
return GameConfig->SetSection(id, create);
}
//==========================================================================
//
// M_LoadJoystickConfig
//
//==========================================================================
bool M_LoadJoystickConfig(IJoystickConfig *joy)
{
char key[32];
const char *value;
int axislen;
int numaxes;
joy->SetDefaultConfig();
if (!M_SetJoystickConfigSection(joy, false))
{
return false;
}
value = GameConfig->GetValueForKey("Sensitivity");
if (value != NULL)
{
joy->SetSensitivity((float)atof(value));
}
numaxes = joy->GetNumAxes();
for (int i = 0; i < numaxes; ++i)
{
axislen = mysnprintf(key, countof(key), "Axis%u", i);
mysnprintf(key + axislen, countof(key) - axislen, "deadzone");
value = GameConfig->GetValueForKey(key);
if (value != NULL)
{
joy->SetAxisDeadZone(i, (float)atof(value));
}
mysnprintf(key + axislen, countof(key) - axislen, "scale");
value = GameConfig->GetValueForKey(key);
if (value != NULL)
{
joy->SetAxisScale(i, (float)atof(value));
}
mysnprintf(key + axislen, countof(key) - axislen, "map");
value = GameConfig->GetValueForKey(key);
if (value != NULL)
{
EJoyAxis gameaxis = (EJoyAxis)atoi(value);
if (gameaxis < JOYAXIS_None || gameaxis >= NUM_JOYAXIS)
{
gameaxis = JOYAXIS_None;
}
joy->SetAxisMap(i, gameaxis);
}
}
return true;
}
//==========================================================================
//
// M_SaveJoystickConfig
//
// Only saves settings that are not at their defaults.
//
//==========================================================================
void M_SaveJoystickConfig(IJoystickConfig *joy)
{
char key[32], value[32];
int axislen, numaxes;
if (M_SetJoystickConfigSection(joy, true))
{
GameConfig->ClearCurrentSection();
if (!joy->IsSensitivityDefault())
{
mysnprintf(value, countof(value), "%g", joy->GetSensitivity());
GameConfig->SetValueForKey("Sensitivity", value);
}
numaxes = joy->GetNumAxes();
for (int i = 0; i < numaxes; ++i)
{
axislen = mysnprintf(key, countof(key), "Axis%u", i);
if (!joy->IsAxisDeadZoneDefault(i))
{
mysnprintf(key + axislen, countof(key) - axislen, "deadzone");
mysnprintf(value, countof(value), "%g", joy->GetAxisDeadZone(i));
GameConfig->SetValueForKey(key, value);
}
if (!joy->IsAxisScaleDefault(i))
{
mysnprintf(key + axislen, countof(key) - axislen, "scale");
mysnprintf(value, countof(value), "%g", joy->GetAxisScale(i));
GameConfig->SetValueForKey(key, value);
}
if (!joy->IsAxisMapDefault(i))
{
mysnprintf(key + axislen, countof(key) - axislen, "map");
mysnprintf(value, countof(value), "%d", joy->GetAxisMap(i));
GameConfig->SetValueForKey(key, value);
}
}
// If the joystick is entirely at its defaults, delete this section
// so that we don't write out a lone section header.
if (GameConfig->SectionIsEmpty())
{
GameConfig->DeleteCurrentSection();
}
}
}

53
src/m_joy.h Normal file
View file

@ -0,0 +1,53 @@
#ifndef M_JOY_H
#define M_JOY_H
#include "doomtype.h"
#include "tarray.h"
enum EJoyAxis
{
JOYAXIS_None = -1,
JOYAXIS_Yaw,
JOYAXIS_Pitch,
JOYAXIS_Forward,
JOYAXIS_Side,
JOYAXIS_Up,
// JOYAXIS_Roll, // Ha ha. No roll for you.
NUM_JOYAXIS,
};
// Generic configuration interface for a controller.
struct NOVTABLE IJoystickConfig
{
virtual FString GetName() = 0;
virtual float GetSensitivity() = 0;
virtual void SetSensitivity(float scale) = 0;
virtual int GetNumAxes() = 0;
virtual float GetAxisDeadZone(int axis) = 0;
virtual EJoyAxis GetAxisMap(int axis) = 0;
virtual const char *GetAxisName(int axis) = 0;
virtual float GetAxisScale(int axis) = 0;
virtual void SetAxisDeadZone(int axis, float zone) = 0;
virtual void SetAxisMap(int axis, EJoyAxis gameaxis) = 0;
virtual void SetAxisScale(int axis, float scale) = 0;
// Used by the saver to not save properties that are at their defaults.
virtual bool IsSensitivityDefault() = 0;
virtual bool IsAxisDeadZoneDefault(int axis) = 0;
virtual bool IsAxisMapDefault(int axis) = 0;
virtual bool IsAxisScaleDefault(int axis) = 0;
virtual void SetDefaultConfig() = 0;
virtual FString GetIdentifier() = 0;
};
bool M_LoadJoystickConfig(IJoystickConfig *joy);
void M_SaveJoystickConfig(IJoystickConfig *joy);
// These ought to be provided by a system-specific i_input.cpp.
void I_GetAxes(float axes[NUM_JOYAXIS]);
void I_GetJoysticks(TArray<IJoystickConfig *> &sticks);
#endif

View file

@ -53,6 +53,7 @@
#include "i_music.h"
#include "i_input.h"
#include "m_joy.h"
#include "v_video.h"
#include "v_text.h"

View file

@ -17,6 +17,7 @@
#include "dikeys.h"
#include "templates.h"
#include "s_sound.h"
#include "m_joy.h"
static void I_CheckGUICapture ();
static void I_CheckNativeMouse ();
@ -461,6 +462,11 @@ void I_StartFrame ()
}
}
void I_GetJoysticks(TArray<IJoystickConfig *> &sticks)
{
sticks.Clear();
}
void I_GetAxes(float axes[NUM_JOYAXIS])
{
for (int i = 0; i < NUM_JOYAXIS; ++i)

View file

@ -4,7 +4,5 @@
void I_PutInClipboard (const char *str);
FString I_GetFromClipboard (bool use_primary_selection);
void I_GetAxes(float axes[NUM_JOYAXIS]);
#endif

View file

@ -131,10 +131,6 @@ public:
bool GetDevice();
void ProcessInput();
void AddAxes(float axes[NUM_JOYAXIS]);
void SaveConfig();
bool LoadConfig();
FString GetIdentifier();
void SetDefaultConfig();
// IJoystickConfig interface
FString GetName();
@ -151,6 +147,14 @@ public:
void SetAxisMap(int axis, EJoyAxis gameaxis);
void SetAxisScale(int axis, float scale);
bool IsSensitivityDefault();
bool IsAxisDeadZoneDefault(int axis);
bool IsAxisMapDefault(int axis);
bool IsAxisScaleDefault(int axis);
void SetDefaultConfig();
FString GetIdentifier();
protected:
struct AxisInfo
{
@ -160,9 +164,9 @@ protected:
DWORD Ofs;
LONG Min, Max;
float Value;
float DeadZone;
float Multiplier;
EJoyAxis GameAxis;
float DeadZone, DefaultDeadZone;
float Multiplier, DefaultMultiplier;
EJoyAxis GameAxis, DefaultGameAxis;
BYTE ButtonValue;
};
struct ButtonInfo
@ -220,7 +224,6 @@ protected:
static BOOL CALLBACK EnumCallback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef);
static int STACK_ARGS NameSort(const void *a, const void *b);
static int STACK_ARGS GUIDSort(const void *a, const void *b);
static bool IsXInputDevice(const GUID *guid);
};
@ -282,7 +285,12 @@ FDInputJoystick::FDInputJoystick(const GUID *instance, FString &name)
FDInputJoystick::~FDInputJoystick()
{
SAFE_RELEASE(Device);
if (Device != NULL)
{
M_SaveJoystickConfig(this);
Device->Release();
Device = NULL;
}
if (DataFormat.rgodf != NULL)
{
delete[] DataFormat.rgodf;
@ -323,7 +331,7 @@ bool FDInputJoystick::GetDevice()
return false;
}
Device->Acquire();
LoadConfig();
M_LoadJoystickConfig(this);
Warmup = 4;
return true;
}
@ -680,107 +688,6 @@ FString FDInputJoystick::GetIdentifier()
return id;
}
//===========================================================================
//
// FDInputJoystick :: SetConfigSection
//
// Sets up the config for reading or writing this controller's axis config.
//
//===========================================================================
bool FDInputJoystick::SetConfigSection(bool create)
{
FString id = GetIdentifier();
id += ".Axes";
return GameConfig->SetSection(id, create);
DIDEVICEINSTANCE inst = { sizeof(DIDEVICEINSTANCE), };
}
//===========================================================================
//
// FDInputJoystick :: LoadConfig
//
//===========================================================================
bool FDInputJoystick::LoadConfig()
{
char key[32];
const char *value;
int axislen;
SetDefaultConfig();
if (!SetConfigSection(false))
{
return false;
}
value = GameConfig->GetValueForKey("Multiplier");
if (value != NULL)
{
Multiplier = (float)atof(value);
}
for (unsigned i = 0; i < Axes.Size(); ++i)
{
axislen = mysnprintf(key, countof(key), "Axis%u", i);
mysnprintf(key + axislen, countof(key) - axislen, "deadzone");
value = GameConfig->GetValueForKey(key);
if (value != NULL)
{
Axes[i].DeadZone = (float)atof(value);
}
mysnprintf(key + axislen, countof(key) - axislen, "multiplier");
value = GameConfig->GetValueForKey(key);
if (value != NULL)
{
Axes[i].Multiplier = (float)atof(value);
}
mysnprintf(key + axislen, countof(key) - axislen, "gameaxis");
value = GameConfig->GetValueForKey(key);
if (value != NULL)
{
Axes[i].GameAxis = (EJoyAxis)atoi(value);
if (Axes[i].GameAxis < JOYAXIS_None || Axes[i].GameAxis >= NUM_JOYAXIS)
{
Axes[i].GameAxis = JOYAXIS_None;
}
}
}
return true;
}
//===========================================================================
//
// FDInputJoystick :: SaveConfig
//
//===========================================================================
void FDInputJoystick::SaveConfig()
{
char key[32], value[32];
int axislen;
if (SetConfigSection(true))
{
GameConfig->ClearCurrentSection();
mysnprintf(value, countof(value), "%g", Multiplier);
GameConfig->SetValueForKey("Multiplier", value);
for (unsigned i = 0; i < Axes.Size(); ++i)
{
axislen = mysnprintf(key, countof(key), "Axis%u", i);
mysnprintf(key + axislen, countof(key) - axislen, "deadzone");
mysnprintf(value, countof(value), "%g", Axes[i].DeadZone);
GameConfig->SetValueForKey(key, value);
mysnprintf(key + axislen, countof(key) - axislen, "multiplier");
mysnprintf(value, countof(value), "%g", Axes[i].Multiplier);
GameConfig->SetValueForKey(key, value);
mysnprintf(key + axislen, countof(key) - axislen, "gameaxis");
mysnprintf(value, countof(value), "%d", Axes[i].GameAxis);
GameConfig->SetValueForKey(key, value);
}
}
}
//===========================================================================
//
// FDInputJoystick :: SetDefaultConfig
@ -791,8 +698,10 @@ void FDInputJoystick::SaveConfig()
void FDInputJoystick::SetDefaultConfig()
{
unsigned i;
Multiplier = 1;
for (unsigned i = 0; i < Axes.Size(); ++i)
for (i = 0; i < Axes.Size(); ++i)
{
Axes[i].DeadZone = DEFAULT_DEADZONE;
Axes[i].Multiplier = 1;
@ -828,6 +737,14 @@ void FDInputJoystick::SetDefaultConfig()
}
// If there is only one axis, then we make no assumptions about how
// the user might want to use it.
// Preserve defaults for config saving.
for (i = 0; i < Axes.Size(); ++i)
{
Axes[i].DefaultDeadZone = Axes[i].DeadZone;
Axes[i].DefaultMultiplier = Axes[i].Multiplier;
Axes[i].DefaultGameAxis = Axes[i].GameAxis;
}
}
//===========================================================================
@ -863,6 +780,17 @@ void FDInputJoystick::SetSensitivity(float scale)
Multiplier = scale;
}
//===========================================================================
//
// FDInputJoystick :: IsSensitivityDefault
//
//===========================================================================
bool FDInputJoystick::IsSensitivityDefault()
{
return Multiplier == 1;
}
//===========================================================================
//
// FDInputJoystick :: GetNumAxes
@ -976,6 +904,51 @@ void FDInputJoystick::SetAxisScale(int axis, float scale)
}
}
//===========================================================================
//
// FDInputJoystick :: IsAxisDeadZoneDefault
//
//===========================================================================
bool FDInputJoystick::IsAxisDeadZoneDefault(int axis)
{
if (unsigned(axis) < Axes.Size())
{
return Axes[axis].DeadZone == Axes[axis].DefaultDeadZone;
}
return true;
}
//===========================================================================
//
// FDInputJoystick :: IsAxisScaleDefault
//
//===========================================================================
bool FDInputJoystick::IsAxisScaleDefault(int axis)
{
if (unsigned(axis) < Axes.Size())
{
return Axes[axis].Multiplier == Axes[axis].DefaultMultiplier;
}
return true;
}
//===========================================================================
//
// FDInputJoystick :: IsAxisMapDefault
//
//===========================================================================
bool FDInputJoystick::IsAxisMapDefault(int axis)
{
if (unsigned(axis) < Axes.Size())
{
return Axes[axis].GameAxis == Axes[axis].DefaultGameAxis;
}
return true;
}
//===========================================================================
//
// FDInputJoystickManager - Constructor
@ -1109,8 +1082,10 @@ bool FDInputJoystickManager::WndProcHook(HWND hWnd, UINT message, WPARAM wParam,
BOOL CALLBACK FDInputJoystickManager::EnumCallback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef)
{
// Do not add PS2 adapters if Raw PS2 Input was initialized.
// Do not add XInput devices if XInput was initialized.
if (JoyDevices[INPUT_XInput] == NULL || !IsXInputDevice(&lpddi->guidProduct))
if ((JoyDevices[INPUT_RawPS2] == NULL || !I_IsPS2Adapter(lpddi->guidProduct.Data1)) &&
(JoyDevices[INPUT_XInput] == NULL || !IsXInputDevice(&lpddi->guidProduct)))
{
TArray<Enumerator> *all = (TArray<Enumerator> *)pvRef;
Enumerator thisone;
@ -1415,3 +1390,22 @@ void Joy_GenerateButtonEvents(int oldbuttons, int newbuttons, int numbuttons, in
}
}
}
void Joy_GenerateButtonEvents(int oldbuttons, int newbuttons, int numbuttons, const int *keys)
{
int changed = oldbuttons ^ newbuttons;
if (changed != 0)
{
event_t ev = { 0 };
int mask = 1;
for (int j = 0; j < numbuttons; mask <<= 1, ++j)
{
if (changed & mask)
{
ev.data1 = keys[j];
ev.type = (newbuttons & mask) ? EV_KeyDown : EV_KeyUp;
D_PostEvent(&ev);
}
}
}
}

View file

@ -336,9 +336,12 @@ LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
int code = GET_RAWINPUT_CODE_WPARAM(wParam);
if (Keyboard == NULL || !Keyboard->ProcessRawInput((RAWINPUT *)buffer, code))
{
if (Mouse != NULL)
if (Mouse == NULL || !Mouse->ProcessRawInput((RAWINPUT *)buffer, code))
{
Mouse->ProcessRawInput((RAWINPUT *)buffer, code);
if (JoyDevices[INPUT_RawPS2] != NULL)
{
JoyDevices[INPUT_RawPS2]->ProcessRawInput((RAWINPUT *)buffer, code);
}
}
}
}
@ -625,6 +628,9 @@ bool I_InitInput (void *hwnd)
Printf ("I_StartupXInput\n");
I_StartupXInput();
Printf ("I_StartupRawPS2\n");
I_StartupRawPS2();
Printf ("I_StartupDirectInputJoystick\n");
I_StartupDirectInputJoystick();

View file

@ -44,26 +44,9 @@ FString I_GetFromClipboard (bool windows_has_no_selection_clipboard);
void I_GetEvent();
struct NOVTABLE IJoystickConfig
{
virtual FString GetName() = 0;
virtual float GetSensitivity() = 0;
virtual void SetSensitivity(float scale) = 0;
virtual int GetNumAxes() = 0;
virtual float GetAxisDeadZone(int axis) = 0;
virtual EJoyAxis GetAxisMap(int axis) = 0;
virtual const char *GetAxisName(int axis) = 0;
virtual float GetAxisScale(int axis) = 0;
virtual void SetAxisDeadZone(int axis, float zone) = 0;
virtual void SetAxisMap(int axis, EJoyAxis gameaxis) = 0;
virtual void SetAxisScale(int axis, float scale) = 0;
};
void I_GetAxes(float axes[NUM_JOYAXIS]);
void I_GetJoysticks(TArray<IJoystickConfig *> &sticks);
#ifdef USE_WINDOWS_DWORD
#include "m_joy.h"
// Don't make these definitions available to the main body of the source code.
struct tagRAWINPUT;
@ -138,7 +121,7 @@ enum
{
INPUT_DIJoy,
INPUT_XInput,
INPUT_PS2EMS,
INPUT_RawPS2,
NUM_JOYDEVICES
};
@ -149,8 +132,11 @@ void I_CheckNativeMouse(bool prefer_native);
void I_StartupKeyboard();
void I_StartupXInput();
void I_StartupDirectInputJoystick();
void I_StartupRawPS2();
bool I_IsPS2Adapter(DWORD vidpid);
void Joy_GenerateButtonEvents(int oldbuttons, int newbuttons, int numbuttons, int base);
void Joy_GenerateButtonEvents(int oldbuttons, int newbuttons, int numbuttons, const int *keys);
double Joy_RemoveDeadZone(double axisval, double deadzone, BYTE *buttons);
// USB HID usage page numbers

1317
src/win32/i_rawps2.cpp Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,3 +1,5 @@
#ifndef NO_XINPUT
// HEADER FILES ------------------------------------------------------------
#define WIN32_LEAN_AND_MEAN
@ -26,8 +28,6 @@
// MACROS ------------------------------------------------------------------
#ifndef NO_XINPUT
// TYPES -------------------------------------------------------------------
typedef DWORD (WINAPI *XInputGetStateType)(DWORD index, XINPUT_STATE *state);
@ -43,8 +43,6 @@ public:
void ProcessInput();
void AddAxes(float axes[NUM_JOYAXIS]);
FString GetIdentifier();
void SetDefaultConfig();
bool IsConnected() { return Connected; }
// IJoystickConfig interface
@ -62,6 +60,14 @@ public:
void SetAxisMap(int axis, EJoyAxis gameaxis);
void SetAxisScale(int axis, float scale);
bool IsSensitivityDefault();
bool IsAxisDeadZoneDefault(int axis);
bool IsAxisMapDefault(int axis);
bool IsAxisScaleDefault(int axis);
void SetDefaultConfig();
FString GetIdentifier();
protected:
struct AxisInfo
{
@ -170,7 +176,7 @@ FXInputController::FXInputController(int index)
{
Index = index;
Connected = false;
SetDefaultConfig();
M_LoadJoystickConfig(this);
}
//==========================================================================
@ -181,6 +187,7 @@ FXInputController::FXInputController(int index)
FXInputController::~FXInputController()
{
M_SaveJoystickConfig(this);
}
//==========================================================================
@ -419,6 +426,17 @@ void FXInputController::SetSensitivity(float scale)
Multiplier = scale;
}
//==========================================================================
//
// FXInputController :: IsSensitivityDefault
//
//==========================================================================
bool FXInputController::IsSensitivityDefault()
{
return Multiplier == 1;
}
//==========================================================================
//
// FXInputController :: GetNumAxes
@ -532,6 +550,51 @@ void FXInputController::SetAxisScale(int axis, float scale)
}
}
//===========================================================================
//
// FXInputController :: IsAxisDeadZoneDefault
//
//===========================================================================
bool FXInputController::IsAxisDeadZoneDefault(int axis)
{
if (unsigned(axis) < NUM_AXES)
{
return Axes[axis].DeadZone == DefaultAxes[axis].DeadZone;
}
return true;
}
//===========================================================================
//
// FXInputController :: IsAxisScaleDefault
//
//===========================================================================
bool FXInputController::IsAxisScaleDefault(int axis)
{
if (unsigned(axis) < NUM_AXES)
{
return Axes[axis].Multiplier == DefaultAxes[axis].Multiplier;
}
return true;
}
//===========================================================================
//
// FXInputController :: IsAxisMapDefault
//
//===========================================================================
bool FXInputController::IsAxisMapDefault(int axis)
{
if (unsigned(axis) < NUM_AXES)
{
return Axes[axis].GameAxis == DefaultAxes[axis].GameAxis;
}
return true;
}
//==========================================================================
//
// FXInputManager - Constructor
@ -694,4 +757,3 @@ void I_StartupXInput()
}
#endif

View file

@ -684,6 +684,10 @@
RelativePath=".\src\m_cheat.cpp"
>
</File>
<File
RelativePath=".\src\m_joy.cpp"
>
</File>
<File
RelativePath=".\src\m_menu.cpp"
>
@ -1373,6 +1377,10 @@
RelativePath=".\src\m_fixed.h"
>
</File>
<File
RelativePath=".\src\m_joy.h"
>
</File>
<File
RelativePath=".\src\m_menu.h"
>
@ -1996,6 +2004,10 @@
RelativePath=".\src\win32\i_movie.cpp"
>
</File>
<File
RelativePath=".\src\win32\i_rawps2.cpp"
>
</File>
<File
RelativePath=".\src\win32\I_system.cpp"
>