Changes relating to input system:

- Fixed bug with mapping of multiple assignments.
- Added new ! operator for input mappings, which lets the user specify that an input must not be active.
- Added option to print info about input system (such as settings and detected keyboards, mice and joysticks) during input configuration.
- Added new trigger input for lightgun games with a configurable option to automatically pull trigger when offscreen input is activated (this makes playing with the mouse easier as the gun can be reloaded with single mouse button, rather than having to press both
 buttons at the same time).
- Added -xinput command line option that switches to using XInput API rather than DirectInput for XBox 360 controllers (this allows the XBox 360 controller's two triggers to be read independently which works better for driving games when they are mapped to accele
rator and brake).
- Added initial version of force feedback implementation to DirectInputSystem (this still needs work).
This commit is contained in:
Nik Henson 2011-06-05 20:53:39 +00:00
parent c69067e0be
commit 5e247021be
21 changed files with 1814 additions and 644 deletions

View file

@ -2,13 +2,17 @@
CInput::CInput(const char *inputId, const char *inputLabel, unsigned inputFlags, unsigned inputGameFlags, const char *defaultMapping, UINT16 initValue) :
id(inputId), label(inputLabel), flags(inputFlags), gameFlags(inputGameFlags), m_defaultMapping(defaultMapping), value(initValue), prevValue(initValue),
m_system(NULL), m_source(NULL)
m_system(NULL), m_source(NULL)
{
ResetToDefaultMapping();
}
void CInput::CreateSource()
{
// If already have a source, then release it now
if (m_system != NULL && m_source != NULL)
m_system->ReleaseSource(m_source);
// If no system set yet or mapping is empty or NONE, then set source to NULL
if (m_system == NULL || m_mapping[0] == '\0' || stricmp(m_mapping, "NONE") == 0)
m_source = NULL;
@ -38,6 +42,7 @@ const char* CInput::GetInputGroup()
{
switch (gameFlags)
{
case GAME_INPUT_UI: return "User Interface Controls";
case GAME_INPUT_COMMON: return "Common Controls";
case GAME_INPUT_JOYSTICK1: // Fall through to below
case GAME_INPUT_JOYSTICK2: return "8-Way Joysticks";
@ -92,6 +97,26 @@ void CInput::ResetToDefaultMapping()
SetMapping(m_defaultMapping);
}
void CInput::ReadFromINIFile(CINIFile *ini, const char *section)
{
if (!IsConfigurable())
return;
string key("Input");
key.append(id);
string mapping;
if (ini->Get(section, key, mapping) == OKAY)
SetMapping(mapping.c_str());
}
void CInput::WriteToINIFile(CINIFile *ini, const char *section)
{
if (!IsConfigurable())
return;
string key("Input");
key.append(id);
ini->Set(section, key, m_mapping);
}
bool CInput::Configure(bool append, const char *escapeMapping)
{
char mapping[MAX_MAPPING_LENGTH];
@ -103,3 +128,15 @@ bool CInput::Configure(bool append, const char *escapeMapping)
SetMapping(mapping);
return true;
}
bool CInput::Changed()
{
return value != prevValue;
}
bool CInput::SendForceFeedbackCmd(ForceFeedbackCmd *ffCmd)
{
if (m_source == NULL)
return false;
return m_source->SendForceFeedbackCmd(ffCmd);
}

View file

@ -5,6 +5,10 @@
class CInputSource;
class CInputSystem;
class CINIFile;
// Special game input flag for UI controls
#define GAME_INPUT_UI 0
// Flags for inputs
#define INPUT_FLAGS_SWITCH 0x0001
@ -14,6 +18,18 @@ class CInputSystem;
#define MAX_MAPPING_LENGTH 255
enum EForceFeedback
{
FFStop,
FFConstantForce
};
struct ForceFeedbackCmd
{
EForceFeedback id;
int data;
};
/*
* Base class for any type of Model3 input control.
*/
@ -46,10 +62,10 @@ public:
const char *label;
// Input flags
unsigned flags;
const unsigned flags;
// Input game flags
unsigned gameFlags;
const unsigned gameFlags;
// Current input value
UINT16 value;
@ -84,7 +100,9 @@ public:
void ClearMapping();
/*
* Sets the current mapping(s) assigned to this input. Multiple mapping assignments are comma-separated, eg KEY_RIGHT,JOY1_XAXIS_POS
* Sets the current mapping(s) assigned to this input.
* Multiple mapping assignments are comma-separated, eg KEY_RIGHT,JOY1_XAXIS_POS.
* Simultaneous assignments are joined with a plus, eg KEY_ALT+KEY_P.
*/
void SetMapping(const char *mapping);
@ -98,6 +116,31 @@ public:
*/
void ResetToDefaultMapping();
/*
* Reads the input's mapping(s) from the given INI file, as well as any other settings.
*/
virtual void ReadFromINIFile(CINIFile *ini, const char *section);
/*
* Writes the current input mapping(s) to the given INI file, as well as any other settings.
*/
virtual void WriteToINIFile(CINIFile *ini, const char *section);
/*
* Returns true if the input is a UI input.
*/
bool IsUIInput();
/*
* Returns true if the input is configurable and can be set by the user.
*/
bool IsConfigurable();
/*
* Returns true if the input is a virtual input, ie one which generates its value based on other inputs and so has no mapping.
*/
bool IsVirtual();
/*
* Configures the current mapping(s) assigned to this input by asking the user for input.
* If append is true, then the user's selected mapping is appended. Otherwise, it overwrites the existing mapping(s).
@ -109,6 +152,36 @@ public:
* Polls (updates) this input, updating its value from the input source
*/
virtual void Poll() = 0;
/*
* Returns true if the value of this input changed during the last poll.
*/
bool Changed();
/*
* Sends a force feedback command to the input source of this input.
*/
bool SendForceFeedbackCmd(ForceFeedbackCmd *ffCmd);
};
//
// Inlined methods
//
inline bool CInput::IsUIInput()
{
return gameFlags == GAME_INPUT_UI;
}
inline bool CInput::IsConfigurable()
{
// All inputs except UI and virtual ones can be configured by the user
return (gameFlags != GAME_INPUT_UI) && !(flags & INPUT_FLAGS_VIRTUAL);
}
inline bool CInput::IsVirtual()
{
return !!(flags & INPUT_FLAGS_VIRTUAL);
}
#endif // INCLUDED_INPUT_H

View file

@ -81,4 +81,9 @@ bool CInputSource::IsActive()
{
bool boolVal;
return GetValueAsSwitch(boolVal);
}
bool CInputSource::SendForceFeedbackCmd(ForceFeedbackCmd *ffCmd)
{
return false;
}

View file

@ -5,7 +5,11 @@
using namespace std;
class CInputSystem;
struct ForceFeedbackCmd;
/*
* Enumeration to represent different types of sources.
*/
enum ESourceType
{
SourceInvalid = -1,
@ -24,6 +28,9 @@ protected:
CInputSource(ESourceType sourceType);
public:
/*
* The type of this source.
*/
const ESourceType type;
//
@ -46,11 +53,6 @@ public:
*/
static int Scale(int val, int fromMinVal, int fromOffVal, int fromMaxVal, int toMinVal, int toOffVal, int toMaxVal);
/*
* Returns true if this source represents a switch input (such as a button). Otherwise it is assumed to be an analog input (such as axis or pedal).
*/
ESourceType GetType();
/*
* Returns true if the source is active (taken from GetValueAsSwitch).
*/
@ -67,6 +69,11 @@ public:
* Returns true if the value was set.
*/
virtual bool GetValueAsAnalog(int &val, int minVal, int offVal, int maxVal) = 0;
/*
* Sends a force feedback command to the input source.
*/
virtual bool SendForceFeedbackCmd(ForceFeedbackCmd *ffCmd);
};
#endif // INCLUDED_INPUTSOURCE_H

View file

@ -343,17 +343,17 @@ JoyPartsStruct CInputSystem::s_joyParts[] =
{ NULL, JoyUnknown }
};
CMultiInputSource *CInputSystem::s_emptySource = new CMultiInputSource();
CInputSystem::CInputSystem(const char *systemName) : name(systemName), m_dispX(0), m_dispY(0), m_dispW(0), m_dispH(0), m_isConfiguring(false)
CInputSystem::CInputSystem(const char *systemName) :
name(systemName), m_dispX(0), m_dispY(0), m_dispW(0), m_dispH(0), m_grabMouse(false)
{
//
m_emptySource = new CMultiInputSource(this);
}
CInputSystem::~CInputSystem()
{
DeleteSourceCache();
ClearSettings();
delete m_emptySource;
}
void CInputSystem::CreateSourceCache()
@ -398,6 +398,74 @@ void CInputSystem::CreateSourceCache()
}
}
bool CInputSystem::IsInSourceCache(CInputSource *source)
{
// Check keyboard source cache
if (m_anyKeySources != NULL)
{
for (int keyIndex = 0; keyIndex < NUM_VALID_KEYS; keyIndex++)
{
if (source == m_anyKeySources[keyIndex])
return true;
}
if (m_numKbds != ANY_KEYBOARD)
{
for (int kbdNum = 0; kbdNum < m_numKbds; kbdNum++)
{
for (int keyIndex = 0; keyIndex < NUM_VALID_KEYS; keyIndex++)
{
if (source == m_keySources[kbdNum][keyIndex])
return true;
}
}
}
}
// Check mouse source cache
if (m_anyMseSources != NULL)
{
for (int mseIndex = 0; mseIndex < NUM_MOUSE_PARTS; mseIndex++)
{
if (source == m_anyMseSources[mseIndex])
return true;
}
if (m_numMice != ANY_MOUSE)
{
for (int mseNum = 0; mseNum < m_numMice; mseNum++)
{
for (int mseIndex = 0; mseIndex < NUM_MOUSE_PARTS; mseIndex++)
{
if (source == m_mseSources[mseNum][mseIndex])
return true;
}
}
}
}
// Check joystick source cache
if (m_anyJoySources != NULL)
{
for (int joyIndex = 0; joyIndex < NUM_JOY_PARTS; joyIndex++)
{
if (source == m_anyJoySources[joyIndex])
return true;
}
if (m_numJoys != ANY_JOYSTICK)
{
for (int joyNum = 0; joyNum < m_numJoys; joyNum++)
{
for (int joyIndex = 0; joyIndex < NUM_JOY_PARTS; joyIndex++)
{
if (source == m_joySources[joyNum][joyIndex])
return true;
}
}
}
}
return false;
}
void CInputSystem::DeleteSourceCache()
{
// Delete cache for keyboard sources
@ -463,7 +531,7 @@ void CInputSystem::DeleteSourceCache()
void CInputSystem::DeleteSource(CInputSource *source)
{
if (source != NULL && source != s_emptySource)
if (source != NULL && source != m_emptySource)
delete source;
}
@ -489,7 +557,7 @@ CInputSource *CInputSystem::GetKeySource(int kbdNum, int keyIndex)
return m_keySources[kbdNum][keyIndex];
}
else
return s_emptySource;
return m_emptySource;
}
CInputSource *CInputSystem::GetMouseSource(int mseNum, EMousePart msePart)
@ -515,7 +583,7 @@ CInputSource *CInputSystem::GetMouseSource(int mseNum, EMousePart msePart)
return m_mseSources[mseNum][mseIndex];
}
else
return s_emptySource;
return m_emptySource;
}
CInputSource *CInputSystem::GetJoySource(int joyNum, EJoyPart joyPart)
@ -541,7 +609,7 @@ CInputSource *CInputSystem::GetJoySource(int joyNum, EJoyPart joyPart)
return m_joySources[joyNum][joyIndex];
}
else
return s_emptySource;
return m_emptySource;
}
void CInputSystem::CheckKeySources(int kbdNum, bool fullAxisOnly, vector<CInputSource*> &sources, string &mapping)
@ -802,11 +870,27 @@ CInputSource* CInputSystem::ParseMultiSource(string str, bool fullAxisOnly, bool
while (start < size);
// If only parsed a single source, return that, otherwise return a CMultiInputSource combining all the sources
return (isMulti ? new CMultiInputSource(isOr, sources) : source);
return (isMulti ? new CMultiInputSource(this, isOr, sources) : source);
}
CInputSource *CInputSystem::ParseSingleSource(string str)
{
// First, check for ! at beginning of string, which means input source must not be activated
if (str[0] == '!')
{
// If found, skip any whitespace after that and get remaining string and parse it again
size_t i = 1;
while (i < str.size() && str[i] == ' ')
i++;
str.erase(0, i);
CInputSource *source = ParseSingleSource(str);
if (source != NULL && source != m_emptySource)
return new CNegInputSource(this, source);
else
return source;
}
// Try parsing a key mapping
int kbdNum;
int keyNameIndex = ParseDevMapping(str, "KEY", kbdNum);
@ -840,9 +924,9 @@ CInputSource *CInputSystem::ParseSingleSource(string str)
sources.push_back(rightSource);
}
if (sources.size() > 0)
return new CMultiInputSource(true, sources);
return new CMultiInputSource(this, true, sources);
}
return s_emptySource;
return m_emptySource;
}
}
@ -877,7 +961,7 @@ CInputSource *CInputSystem::ParseSingleSource(string str)
if (keyIndex >= 0)
return GetKeySource(ANY_KEYBOARD, keyIndex);
else
return s_emptySource;
return m_emptySource;
}
// If got here, it was not possible to parse mapping string so return NULL
@ -1079,7 +1163,7 @@ void CInputSystem::WriteJoySettings(CINIFile *ini, const char *section, JoySetti
KeySettings *CInputSystem::GetKeySettings(int kbdNum, bool useDefault)
{
KeySettings *common = NULL;
for (vector<KeySettings*>::iterator it = m_keySettings.begin(); it < m_keySettings.end(); it++)
for (vector<KeySettings*>::iterator it = m_keySettings.begin(); it != m_keySettings.end(); it++)
{
if ((*it)->kbdNum == kbdNum)
return *it;
@ -1094,7 +1178,7 @@ KeySettings *CInputSystem::GetKeySettings(int kbdNum, bool useDefault)
MouseSettings *CInputSystem::GetMouseSettings(int mseNum, bool useDefault)
{
MouseSettings *common = NULL;
for (vector<MouseSettings*>::iterator it = m_mseSettings.begin(); it < m_mseSettings.end(); it++)
for (vector<MouseSettings*>::iterator it = m_mseSettings.begin(); it != m_mseSettings.end(); it++)
{
if ((*it)->mseNum == mseNum)
return *it;
@ -1109,7 +1193,7 @@ MouseSettings *CInputSystem::GetMouseSettings(int mseNum, bool useDefault)
JoySettings *CInputSystem::GetJoySettings(int joyNum, bool useDefault)
{
JoySettings *common = NULL;
for (vector<JoySettings*>::iterator it = m_joySettings.begin(); it < m_joySettings.end(); it++)
for (vector<JoySettings*>::iterator it = m_joySettings.begin(); it != m_joySettings.end(); it++)
{
if ((*it)->joyNum == joyNum)
return *it;
@ -1241,7 +1325,7 @@ bool CInputSystem::ConfigMouseCentered()
// See if mouse in center of display
unsigned lx = m_dispX + m_dispW / 4;
unsigned ly = m_dispY + m_dispH / 4;
return mx >= lx && mx <= lx + m_dispW / 2 && my >= ly && my <= ly + m_dispH / 2;
return mx >= (int)lx && mx <= (int)(lx + m_dispW / 2) && my >= (int)ly && my <= (int)(ly + m_dispH / 2);
}
CInputSource *CInputSystem::CreateAnyKeySource(int keyIndex)
@ -1254,7 +1338,7 @@ CInputSource *CInputSystem::CreateAnyKeySource(int keyIndex)
if (keySrc != NULL)
keySrcs.push_back(keySrc);
}
return new CMultiInputSource(true, keySrcs);
return new CMultiInputSource(this, true, keySrcs);
}
CInputSource *CInputSystem::CreateAnyMouseSource(EMousePart msePart)
@ -1267,7 +1351,7 @@ CInputSource *CInputSystem::CreateAnyMouseSource(EMousePart msePart)
if (mseSrc != NULL)
mseSrcs.push_back(mseSrc);
}
return new CMultiInputSource(true, mseSrcs);
return new CMultiInputSource(this, true, mseSrcs);
}
CInputSource *CInputSystem::CreateAnyJoySource(EJoyPart joyPart)
@ -1280,7 +1364,7 @@ CInputSource *CInputSystem::CreateAnyJoySource(EJoyPart joyPart)
if (joySrc != NULL)
joySrcs.push_back(joySrc);
}
return new CMultiInputSource(true, joySrcs);
return new CMultiInputSource(this, true, joySrcs);
}
CInputSource *CInputSystem::CreateKeySource(int kbdNum, int keyIndex)
@ -1329,7 +1413,7 @@ CInputSource *CInputSystem::CreateMouseSource(int mseNum, EMousePart msePart)
CInputSource *CInputSystem::CreateJoySource(int joyNum, EJoyPart joyPart)
{
// Get joystick details and settings
JoyDetails *joyDetails = GetJoyDetails(joyNum);
const JoyDetails *joyDetails = GetJoyDetails(joyNum);
JoySettings *settings = GetJoySettings(joyNum, true);
// Create source according to given joystick part
@ -1339,29 +1423,29 @@ CInputSource *CInputSystem::CreateJoySource(int joyNum, EJoyPart joyPart)
int povDir;
if (GetAxisDetails(joyPart, axisNum, axisDir))
{
// Part is joystick axis so see whether joystick has this axis and get the deadzone and saturation settings for it
bool hasAxis;
// Part is joystick axis so get the deadzone and saturation settings for it
unsigned axisDZone;
unsigned axisSat;
switch (axisNum)
{
case AXIS_X: hasAxis = joyDetails->hasXAxis; axisDZone = settings->xDeadZone; axisSat = settings->xSaturation; break;
case AXIS_Y: hasAxis = joyDetails->hasYAxis; axisDZone = settings->yDeadZone; axisSat = settings->ySaturation; break;
case AXIS_Z: hasAxis = joyDetails->hasZAxis; axisDZone = settings->zDeadZone; axisSat = settings->zSaturation; break;
case AXIS_RX: hasAxis = joyDetails->hasRXAxis; axisDZone = settings->rxDeadZone; axisSat = settings->rxSaturation; break;
case AXIS_RY: hasAxis = joyDetails->hasRYAxis; axisDZone = settings->ryDeadZone; axisSat = settings->rySaturation; break;
case AXIS_RZ: hasAxis = joyDetails->hasRZAxis; axisDZone = settings->rzDeadZone; axisSat = settings->rzSaturation; break;
case AXIS_X: axisDZone = settings->xDeadZone; axisSat = settings->xSaturation; break;
case AXIS_Y: axisDZone = settings->yDeadZone; axisSat = settings->ySaturation; break;
case AXIS_Z: axisDZone = settings->zDeadZone; axisSat = settings->zSaturation; break;
case AXIS_RX: axisDZone = settings->rxDeadZone; axisSat = settings->rxSaturation; break;
case AXIS_RY: axisDZone = settings->ryDeadZone; axisSat = settings->rySaturation; break;
case AXIS_RZ: axisDZone = settings->rzDeadZone; axisSat = settings->rzSaturation; break;
default: return NULL; // Any other axis numbers are invalid
}
if (!hasAxis)
return s_emptySource; // If joystick doesn't have axis, then return empty source rather than NULL as not really an error
// See whether joystick has this axis
if (!joyDetails->hasAxis[axisNum])
return m_emptySource; // If joystick doesn't have axis, then return empty source rather than NULL as not really an error
return new CJoyAxisInputSource(this, joyNum, axisNum, axisDir, axisDZone, axisSat);
}
else if (GetPOVDetails(joyPart, povNum, povDir))
{
// Part is joystick POV hat controller so see whether joystick has this POV
if (povNum >= joyDetails->numPOVs)
return s_emptySource; // If joystick doesn't have POV, then return empty source rather than NULL as not really an error
return m_emptySource; // If joystick doesn't have POV, then return empty source rather than NULL as not really an error
return new CJoyPOVInputSource(this, joyNum, povNum, povDir);
}
else if (IsButton(joyPart))
@ -1371,7 +1455,7 @@ CInputSource *CInputSystem::CreateJoySource(int joyNum, EJoyPart joyPart)
if (butNum < 0)
return NULL; // Buttons out of range are invalid
if (butNum >= joyDetails->numButtons)
return s_emptySource; // If joystick doesn't have button, then return empty source rather than NULL as not really an error
return m_emptySource; // If joystick doesn't have button, then return empty source rather than NULL as not really an error
return new CJoyButInputSource(this, joyNum, butNum);
}
@ -1385,7 +1469,7 @@ bool CInputSystem::Initialize()
if (!InitializeSystem())
return false;
// Get number of keyboard, mice and joysticks
// Get number of keyboard, mice and joysticks (they are stored here as need to access the values in the destructor)
m_numKbds = GetNumKeyboards();
m_numMice = GetNumMice();
m_numJoys = GetNumJoysticks();
@ -1409,20 +1493,27 @@ CInputSource* CInputSystem::ParseSource(const char *mapping, bool fullAxisOnly)
return ParseMultiSource(mapping, fullAxisOnly, true);
}
void CInputSystem::ReleaseSource(CInputSource *source)
{
// If source is not being cached then delete it
if (!IsInSourceCache(source))
DeleteSource(source);
}
void CInputSystem::ClearSettings()
{
// Delete all key settings
for (vector<KeySettings*>::iterator it = m_keySettings.begin(); it < m_keySettings.end(); it++)
for (vector<KeySettings*>::iterator it = m_keySettings.begin(); it != m_keySettings.end(); it++)
delete *it;
m_keySettings.clear();
// Delete all mouse settings
for (vector<MouseSettings*>::iterator it = m_mseSettings.begin(); it < m_mseSettings.end(); it++)
for (vector<MouseSettings*>::iterator it = m_mseSettings.begin(); it != m_mseSettings.end(); it++)
delete *it;
m_mseSettings.clear();
// Delete all joystick settings
for (vector<JoySettings*>::iterator it = m_joySettings.begin(); it < m_joySettings.end(); it++)
for (vector<JoySettings*>::iterator it = m_joySettings.begin(); it != m_joySettings.end(); it++)
delete *it;
m_joySettings.clear();
}
@ -1437,6 +1528,10 @@ void CInputSystem::PrintSettings()
puts("");
PrintDevices();
puts("");
// Print all key settings for attached keyboards
KeySettings *keySettings = GetKeySettings(ANY_KEYBOARD, true);
PrintKeySettings(keySettings);
@ -1511,15 +1606,15 @@ void CInputSystem::ReadFromINIFile(CINIFile *ini, const char *section)
void CInputSystem::WriteToINIFile(CINIFile *ini, const char *section)
{
// Write all key settings
for (vector<KeySettings*>::iterator it = m_keySettings.begin(); it < m_keySettings.end(); it++)
for (vector<KeySettings*>::iterator it = m_keySettings.begin(); it != m_keySettings.end(); it++)
WriteKeySettings(ini, section, *it);
// Write all mouse settings
for (vector<MouseSettings*>::iterator it = m_mseSettings.begin(); it < m_mseSettings.end(); it++)
for (vector<MouseSettings*>::iterator it = m_mseSettings.begin(); it != m_mseSettings.end(); it++)
WriteMouseSettings(ini, section, *it);
// Write all joystick settings
for (vector<JoySettings*>::iterator it = m_joySettings.begin(); it < m_joySettings.end(); it++)
for (vector<JoySettings*>::iterator it = m_joySettings.begin(); it != m_joySettings.end(); it++)
WriteJoySettings(ini, section, *it);
}
@ -1533,7 +1628,7 @@ bool CInputSystem::ReadMapping(char *buffer, unsigned bufSize, bool fullAxisOnly
bool mseCentered = false;
// Loop until have received meaningful inputs
while (true)
for (;;)
{
// Poll inputs
if (!Poll())
@ -1600,7 +1695,7 @@ bool CInputSystem::ReadMapping(char *buffer, unsigned bufSize, bool fullAxisOnly
{
// Check each source is no longer active
bool active = false;
for (vector<CInputSource*>::iterator it = sources.begin(); it < sources.end(); it++)
for (vector<CInputSource*>::iterator it = sources.begin(); it != sources.end(); it++)
{
if ((*it)->IsActive())
{
@ -1631,19 +1726,19 @@ bool CInputSystem::ReadMapping(char *buffer, unsigned bufSize, bool fullAxisOnly
return true;
}
void CInputSystem::ConfigStart()
void CInputSystem::GrabMouse()
{
m_isConfiguring = true;
m_grabMouse = true;
}
void CInputSystem::UngrabMouse()
{
m_grabMouse = false;
// Make sure mouse is visible
SetMouseVisibility(true);
}
void CInputSystem::ConfigEnd()
{
m_isConfiguring = false;
}
/*
* CInputSystem::CKeyInputSource
*/
@ -1848,6 +1943,11 @@ bool CInputSystem::CJoyAxisInputSource::GetValueAsAnalog(int &val, int minVal, i
return true;
}
bool CInputSystem::CJoyAxisInputSource::SendForceFeedbackCmd(ForceFeedbackCmd *ffCmd)
{
return m_system->SendForceFeedbackCmd(m_joyNum, m_axisNum, ffCmd);
}
/*
* CInputSystem::CJoyPOVInputSource
*/

View file

@ -1,6 +1,7 @@
#ifndef INCLUDED_INPUTSYSTEM_H
#define INCLUDED_INPUTSYSTEM_H
#include <stdio.h>
#include <string>
#include <vector>
using namespace std;
@ -11,6 +12,8 @@ class CInput;
class CInputSource;
class CINIFile;
#define MAX_NAME_LENGTH 255
// Read flags for ReadMapping
#define READ_KEYBOARD 1
#define READ_MOUSE 2
@ -262,17 +265,26 @@ struct JoySettings
}
};
struct KeyDetails
{
char name[MAX_NAME_LENGTH]; // Keyboard name (if available)
};
struct MouseDetails
{
char name[MAX_NAME_LENGTH]; // Mouse name (if available)
bool isAbsolute; // True if uses absolute positions (ie lightgun)
};
struct JoyDetails
{
bool hasXAxis; // Flags to indicate which axes available on joystick
bool hasYAxis;
bool hasZAxis;
bool hasRXAxis;
bool hasRYAxis;
bool hasRZAxis;
int numAxes; // Total number of axes on joystick
int numPOVs; // Total number of POV hat controllers on joystick
int numButtons; // Total number of buttons on joystick
char name[MAX_NAME_LENGTH]; // Joystick name (if available)
int numAxes; // Total number of axes on joystick
int numPOVs; // Total number of POV hat controllers on joystick
int numButtons; // Total number of buttons on joystick
bool hasFFeedback; // True if joystick supports force feedback
bool hasAxis[NUM_JOY_AXES]; // Flags to indicate which axes available on joystick
bool axisHasFF[NUM_JOY_AXES]; // Flags to indicate which axes are force feedback enabled
};
/*
@ -291,9 +303,6 @@ private:
// Lookup table for translating joystick mapping strings to their respective joystick parts
static JoyPartsStruct s_joyParts[];
// Empty input source
static CMultiInputSource *s_emptySource;
// Number of keyboards, mice and joysticks
int m_numKbds;
int m_numMice;
@ -317,6 +326,9 @@ private:
vector<MouseSettings*> m_mseSettings;
vector<JoySettings*> m_joySettings;
// Empty input source
CMultiInputSource *m_emptySource;
//
// Helper methods
//
@ -326,28 +338,36 @@ private:
*/
void CreateSourceCache();
/*
* Returns true if the given source is in the source cache.
*/
bool IsInSourceCache(CInputSource *source);
/*
* Deletes cache for all sources.
*/
void DeleteSourceCache();
/*
* Deletes an input source
* Deletes an input source.
*/
void DeleteSource(CInputSource *source);
/*
* Returns a key source for the given keyboard number (or all keyboards if ANY_KEYBOARD supplied) and key index
* Returns a key source for the given keyboard number (or all keyboards if ANY_KEYBOARD supplied) and key index.
* Will check the source cache first and if not found will create the source with CreateAnyKeySource or CreateKeySource.
*/
CInputSource *GetKeySource(int kbdNum, int keyIndex);
/*
* Returns a mouse source for the given mouse number (or all mice if ANY_MOUSE supplied) and mouse index
* Returns a mouse source for the given mouse number (or all mice if ANY_MOUSE supplied) and mouse index.
* Will check the source cache first and if not found will create the source with CreateAnyMouseSource or CreateMouseSource.
*/
CInputSource *GetMouseSource(int mseNum, EMousePart msePart);
/*
* Returns a joystick source for the given joystick number (or all joysticks if ANY_JOYSTICK supplied) and joystick index
* Returns a joystick source for the given joystick number (or all joysticks if ANY_JOYSTICK supplied) and joystick index.
* Will check the source cache first and if not found will create the source with CreateAnyJoySource or CreateJoySource.
*/
CInputSource *GetJoySource(int joyNum, EJoyPart joyPart);
@ -474,32 +494,14 @@ protected:
unsigned m_dispW;
unsigned m_dispH;
// Flag to indicate if system currently being configured
bool m_isConfiguring;
// Flag to indicate if system has grabbed mouse
bool m_grabMouse;
/*
* Constructs an input system with the given name.
*/
CInputSystem(const char *systemName);
/*
* Returns the current key settings for given keyboard number, or common settings if ANY_KEYBOARD specified.
* If no settings are found and useDefault is false, NULL is returned. If useDefault is true then default settings are returned.
*/
KeySettings *GetKeySettings(int kbdNum, bool useDefault);
/*
* Returns the current mouse settings for given mouse number, or common settings if ANY_MOUSE specified.
* If no settings are found and useDefault is false, NULL is returned. If useDefault is true then default settings are returned.
*/
MouseSettings *GetMouseSettings(int mseNum, bool useDefault);
/*
* Returns the current joystick settings for given joystick number, or common settings if ANY_JOYSTICK specified.
* If no settings are found and useDefault is false, NULL is returned. If useDefault is true then default settings are returned.
*/
JoySettings *GetJoySettings(int joyNum, bool useDefault);
/*
* Returns true if the given EMousePart is an axis.
*/
@ -602,24 +604,6 @@ protected:
virtual bool InitializeSystem() = 0;
/*
* Returns the number of attached keyboards (or 0 if the system cannot handle keyboards at all or ANY_KEYBOARD if the system cannot
* handle multiple keyboards).
*/
virtual int GetNumKeyboards() = 0;
/*
* Returns the number of attached mice (or 0 if the system cannot handle mice at all or ANY_MOUSE if the system cannot handle
* multiple mice).
*/
virtual int GetNumMice() = 0;
/*
* Returns number of attached joysticks (or 0 if the system cannot handle joysticks at all or ANY_JOYSTICK if the system cannot
* handle multiple joysticks).
*/
virtual int GetNumJoysticks() = 0;
/*
* Returns the system-specific key index that represents the given key name.
*/
@ -630,11 +614,6 @@ protected:
*/
virtual const char *GetKeyName(int keyIndex) = 0;
/*
* Returns details about the joystick with the given number, or NULL if it does not exist.
*/
virtual JoyDetails *GetJoyDetails(int joyNum) = 0;
/*
* Returns true if for the given keyboard the key with the system-specific key index is currently pressed.
*/
@ -671,6 +650,11 @@ protected:
*/
virtual bool IsJoyButPressed(int joyNum, int butNum) = 0;
/*
* Processes the given force feedback command for the given joystick and axis number.
*/
virtual bool ProcessForceFeedbackCmd(int joyNum, int axisNum, ForceFeedbackCmd *ffCmd) = 0;
/*
* Waits for the given time in milliseconds
*/
@ -681,7 +665,7 @@ protected:
//
/*
* Returns true if the mouse is currently centered in the display.
* Returns true if the mouse is currently centered in the display during configuration.
*/
virtual bool ConfigMouseCentered();
@ -716,6 +700,7 @@ protected:
virtual CInputSource *CreateJoySource(int joyNum, EJoyPart joyPart);
public:
// Name of this input system
const char *name;
@ -731,12 +716,40 @@ public:
* Sets the current display geometry so that mouse movements can be scaled properly.
*/
void SetDisplayGeom(unsigned dispX, unsigned dispY, unsigned dispW, unsigned dispH);
/*
* Returns the number of attached keyboards (or 0 if the system cannot handle keyboards at all or ANY_KEYBOARD if the system cannot
* handle multiple keyboards).
*/
virtual int GetNumKeyboards() = 0;
/*
* Returns the input source for the given mapping, or NULL if mapping is not valid.
* Returns the number of attached mice (or 0 if the system cannot handle mice at all or ANY_MOUSE if the system cannot handle
* multiple mice).
*/
CInputSource* ParseSource(const char *mapping, bool fullAxisOnly = false);
virtual int GetNumMice() = 0;
/*
* Returns number of attached joysticks (or 0 if the system cannot handle joysticks at all or ANY_JOYSTICK if the system cannot
* handle multiple joysticks).
*/
virtual int GetNumJoysticks() = 0;
/*
* Returns details about the keyboard with the given number, or NULL if it does not exist.
*/
virtual const KeyDetails *GetKeyDetails(int kbdNum) = 0;
/*
* Returns details about the mouse with the given number, or NULL if it does not exist.
*/
virtual const MouseDetails *GetMouseDetails(int mseNum) = 0;
/*
* Returns details about the joystick with the given number, or NULL if it does not exist.
*/
virtual const JoyDetails *GetJoyDetails(int joyNum) = 0;
/*
* Clears all keyboard, mouse and joystick settings.
*/
@ -757,6 +770,34 @@ public:
*/
virtual void WriteToINIFile(CINIFile *ini, const char *section);
/*
* Returns the current key settings for given keyboard number, or common settings if ANY_KEYBOARD specified.
* If no settings are found and useDefault is false, NULL is returned. If useDefault is true then default settings are returned.
*/
KeySettings *GetKeySettings(int kbdNum, bool useDefault);
/*
* Returns the current mouse settings for given mouse number, or common settings if ANY_MOUSE specified.
* If no settings are found and useDefault is false, NULL is returned. If useDefault is true then default settings are returned.
*/
MouseSettings *GetMouseSettings(int mseNum, bool useDefault);
/*
* Returns the current joystick settings for given joystick number, or common settings if ANY_JOYSTICK specified.
* If no settings are found and useDefault is false, NULL is returned. If useDefault is true then default settings are returned.
*/
JoySettings *GetJoySettings(int joyNum, bool useDefault);
/*
* Returns the input source for the given mapping, or NULL if mapping is not valid.
*/
CInputSource* ParseSource(const char *mapping, bool fullAxisOnly = false);
/*
* Releases the given source when it is no longer in use.
*/
void ReleaseSource(CInputSource *source);
/*
* Waits for any input from the user and once received copies a mapping configuration representing the input (eg KEY_A or JOY1_AXIS_POS)
* into the given buffer.
@ -765,28 +806,78 @@ public:
* mapping, eg return MOUSE_XAXIS rather than MOUSE3_XAXIS.
* If fullAxisOnly is true, then only mappings representing a full axis are returned, eg JOY1_XAXIS is allowed but not JOY1_XAXIS_POS.
*/
bool ReadMapping(char *buffer, unsigned bufSize, bool fullAxisOnly, unsigned readFlags = READ_ALL, const char *escapeMapping = "KEY_ESCAPE");
bool ReadMapping(char *buffer, unsigned bufSize, bool fullAxisOnly = false, unsigned readFlags = READ_ALL, const char *escapeMapping = "KEY_ESCAPE");
/*
* Updates the current state of the input system (called by CInputs.Poll).
* Updates the current state of the input system (called by CInputs::Poll).
*/
virtual bool Poll() = 0;
/*
* Lets the input system know that inputs are being configured (called by CInputs.ConfigureInputs).
*/
virtual void ConfigStart();
virtual void GrabMouse();
/*
* Lets the input system know that inputs are no longer being configured (called by CInputs.ConfigureInputs).
*/
virtual void ConfigEnd();
virtual void UngrabMouse();
/*
* Sets the mouse visibility (some systems may choose to ignore this).
*/
virtual void SetMouseVisibility(bool visible) = 0;
virtual bool SendForceFeedbackCmd(int joyNum, int axisNum, ForceFeedbackCmd *ffCmd)
{
const JoyDetails *joyDetails = GetJoyDetails(joyNum);
if (!joyDetails->hasFFeedback || !joyDetails->axisHasFF[axisNum])
return false;
return ProcessForceFeedbackCmd(joyNum, axisNum, ffCmd);
}
void PrintDevices()
{
puts("Keyboards:");
if (m_numKbds == 0)
puts(" None");
else if (m_numKbds == ANY_KEYBOARD)
puts(" System Keyboard");
else
{
for (int kbdNum = 0; kbdNum < m_numKbds; kbdNum++)
{
const KeyDetails *keyDetails = GetKeyDetails(kbdNum);
printf(" %d: %s\n", kbdNum + 1, keyDetails->name);
}
}
puts("Mice:");
if (m_numMice == 0)
puts(" None");
else if (m_numMice == ANY_MOUSE)
puts(" System Mouse");
else
{
for (int mseNum = 0; mseNum < m_numMice; mseNum++)
{
const MouseDetails *mseDetails = GetMouseDetails(mseNum);
printf(" %d: %s\n", mseNum + 1, mseDetails->name);
}
}
puts("Joysticks:");
if (m_numJoys == 0)
puts(" None");
else if (m_numJoys == ANY_JOYSTICK)
puts(" System Joystick");
else
{
for (int joyNum = 0; joyNum < m_numJoys; joyNum++)
{
const JoyDetails *joyDetails = GetJoyDetails(joyNum);
if (joyDetails->hasFFeedback)
printf(" %d: %s [Force Feedback Available]\n", joyNum + 1, joyDetails->name);
else
printf(" %d: %s\n", joyNum + 1, joyDetails->name);
}
}
}
//
// Nested Classes
//
@ -821,7 +912,7 @@ public:
private:
CInputSystem *m_system; // Parent input system
int m_mseNum; // Mouse number
int m_axisNum; // Axis number (0 = XAxis, 1 = YAxis, 2 = ZAxis)
int m_axisNum; // Axis number (AXIS_X, AXIS_Y or AXIS_Z)
int m_axisDir; // Axis direction (AXIS_FULL, AXIS_INVERTED, AXIS_POSITIVE or AXIS_NEGATIVE)
int m_deadPixels; // Size in pixels of dead zone in centre of axis
@ -864,7 +955,7 @@ public:
private:
CInputSystem *m_system; // Parent input system
int m_joyNum; // Joystick number
int m_axisNum; // Axis number (0 = XAxis, 1 = YAxis, 2 = ZAxis, 3 = RXAxis, 4 = RYAxis, 5 = RZAxis)
int m_axisNum; // Axis number (AXIS_X, AXIS_Y, AXIS_Z, AXIS_RX, AXIS_RY or AXIS_RZ)
int m_axisDir; // Axis direction (AXIS_FULL, AXIS_INVERTED, AXIS_POSITIVE or AXIS_NEGATIVE)
int m_posDZone; // Dead zone for positive range
int m_negDZone; // Dead zone for negative range
@ -882,6 +973,8 @@ public:
bool GetValueAsSwitch(bool &val);
bool GetValueAsAnalog(int &val, int minVal, int offVal, int maxVal);
bool SendForceFeedbackCmd(ForceFeedbackCmd *fFeedback);
};
/*

View file

@ -146,3 +146,65 @@ void CGearShift4Input::Poll()
if (m_shiftUpInput->Pressed()) value = CInputSource::Clamp(value + 1, 0, 4);
else if (m_shiftDownInput->Pressed()) value = CInputSource::Clamp(value - 1, 0, 4);
}
CTriggerInput::CTriggerInput(const char *inputId, const char *inputLabel, unsigned inputGameFlags,
CSwitchInput *triggerInput, CSwitchInput *offscreenInput, UINT16 offVal, UINT16 onVal) :
CInput(inputId, inputLabel, INPUT_FLAGS_VIRTUAL, inputGameFlags),
m_triggerInput(triggerInput), m_offscreenInput(offscreenInput), m_autoTrigger(false), m_offscreenCount(0), m_offVal(offVal), m_onVal(onVal)
{
//
}
void CTriggerInput::ReadFromINIFile(CINIFile *ini, const char *section)
{
CInput::ReadFromINIFile(ini, section);
string key("Input");
key.append(id);
unsigned int autoTrigger;
if (ini->Get(section, key, autoTrigger) == OKAY)
m_autoTrigger = !!autoTrigger;
}
void CTriggerInput::WriteToINIFile(CINIFile *ini, const char *section)
{
CInput::WriteToINIFile(ini, section);
string key("Input");
key.append(id);
ini->Set(section, key, (unsigned)m_autoTrigger);
}
void CTriggerInput::Poll()
{
prevValue = value;
// See if auto-trigger on reload is enabled
if (m_autoTrigger)
{
// If so, when offscreen activated simulate triggered being pressed a short while afterwards
if (m_offscreenCount > 0)
{
value = m_offscreenCount < 5;
offscreenValue = m_onVal;
m_offscreenCount--;
}
else
{
value = m_triggerInput->value;
if (m_offscreenInput->Pressed())
{
offscreenValue = m_onVal;
m_offscreenCount = 10;
}
else
offscreenValue = m_offVal;
}
}
else
{
// Otherwise if disabled, just take raw values from inputs
value = m_triggerInput->value;
offscreenValue = m_offscreenInput->value;
}
}

View file

@ -132,4 +132,40 @@ public:
void Poll();
};
/*
* Represents a trigger input, with both a trigger value and an offscreen value. If required, it can simulate pointing offscreen and pulling
* the trigger (in that order, which lightgun games require to reload properly) when just the offscreen input is activated. This makes
* reloading the gun easier when playing with just the mouse for example.
*/
class CTriggerInput : public CInput
{
private:
// Real trigger and offscreen inputs
CSwitchInput *m_triggerInput;
CSwitchInput *m_offscreenInput;
// Offscreen on and off values
UINT16 m_offVal;
UINT16 m_onVal;
bool m_autoTrigger;
int m_offscreenCount;
public:
// Offscreen value
UINT16 offscreenValue;
CTriggerInput(const char *inputId, const char *inputLabel, unsigned inputGameFlags, CSwitchInput *triggerInput, CSwitchInput *offscreenInput,
UINT16 offVal = 0x00, UINT16 onVal = 0x01);
void ReadFromINIFile(CINIFile *ini, const char *section);
void WriteToINIFile(CINIFile *ini, const char *section);
/*
* Polls (updates) the input, updating its trigger value and offscreen value from the switch inputs
*/
void Poll();
};
#endif // INCLUDED_INPUTTYPES_H

View file

@ -6,21 +6,19 @@
#include <iostream>
using namespace std;
#define UI_INPUT 0
CInputs::CInputs(CInputSystem *system) : m_system(system)
{
// UI Controls
uiExit = AddSwitchInput("UIExit", "Exit UI", UI_INPUT, "KEY_ESCAPE");
uiReset = AddSwitchInput("UIReset", "Reset", UI_INPUT, "KEY_ALT+KEY_R");
uiPause = AddSwitchInput("UIPause", "Pause", UI_INPUT, "KEY_PAUSE");
uiSaveState = AddSwitchInput("UISaveState", "Save State", UI_INPUT, "KEY_F5");
uiChangeSlot = AddSwitchInput("UIChangeSlot", "Change Save Slot", UI_INPUT, "KEY_F6");
uiLoadState = AddSwitchInput("UILoadState", "Load State", UI_INPUT, "KEY_F7");
uiDumpInpState = AddSwitchInput("UIDumpInputState", "Dump Input State", UI_INPUT, "KEY_F8");
uiClearNVRAM = AddSwitchInput("UIClearNVRAM", "Clear NVRAM", UI_INPUT, "KEY_ALT+KEY_N");
uiToggleCursor = AddSwitchInput("UIToggleCursor", "Toggle Cursor", UI_INPUT, "KEY_ALT+KEY_I");
uiToggleFrLimit = AddSwitchInput("UIToggleFrameLimit", "Toggle Frame Limiting", UI_INPUT, "KEY_ALT+KEY_T");
uiExit = AddSwitchInput("UIExit", "Exit UI", GAME_INPUT_UI, "KEY_ESCAPE");
uiReset = AddSwitchInput("UIReset", "Reset", GAME_INPUT_UI, "KEY_ALT+KEY_R");
uiPause = AddSwitchInput("UIPause", "Pause", GAME_INPUT_UI, "KEY_ALT+KEY_P");
uiSaveState = AddSwitchInput("UISaveState", "Save State", GAME_INPUT_UI, "KEY_F5");
uiChangeSlot = AddSwitchInput("UIChangeSlot", "Change Save Slot", GAME_INPUT_UI, "KEY_F6");
uiLoadState = AddSwitchInput("UILoadState", "Load State", GAME_INPUT_UI, "KEY_F7");
uiDumpInpState = AddSwitchInput("UIDumpInputState", "Dump Input State", GAME_INPUT_UI, "KEY_F8");
uiClearNVRAM = AddSwitchInput("UIClearNVRAM", "Clear NVRAM", GAME_INPUT_UI, "KEY_ALT+KEY_N");
uiToggleCursor = AddSwitchInput("UIToggleCursor", "Toggle Cursor", GAME_INPUT_UI, "KEY_ALT+KEY_I");
uiToggleFrLimit = AddSwitchInput("UIToggleFrameLimit", "Toggle Frame Limiting", GAME_INPUT_UI, "KEY_ALT+KEY_T");
// Common Controls
start[0] = AddSwitchInput("Start1", "P1 Start", GAME_INPUT_COMMON, "KEY_1,JOY1_BUTTON9");
@ -61,8 +59,8 @@ CInputs::CInputs(CInputSystem *system) : m_system(system)
shoot[1] = AddSwitchInput("Shoot1", "P2 Shoot", GAME_INPUT_SOCCER, "JOY2_BUTTON3");
// Racing Game Steering Controls
CAnalogInput* steeringLeft = AddAnalogInput("SteeringLeft", "Steer Left", GAME_INPUT_VEHICLE, "KEY_LEFT");
CAnalogInput* steeringRight = AddAnalogInput("SteeringRight", "Steer Right", GAME_INPUT_VEHICLE, "KEY_RIGHT");
CAnalogInput *steeringLeft = AddAnalogInput("SteeringLeft", "Steer Left", GAME_INPUT_VEHICLE, "KEY_LEFT");
CAnalogInput *steeringRight = AddAnalogInput("SteeringRight", "Steer Right", GAME_INPUT_VEHICLE, "KEY_RIGHT");
steering = AddAxisInput ("Steering", "Full Steering", GAME_INPUT_VEHICLE, "JOY1_XAXIS", steeringLeft, steeringRight);
accelerator = AddAnalogInput("Accelerator", "Accelerator Pedal", GAME_INPUT_VEHICLE, "KEY_UP,JOY1_UP");
@ -89,19 +87,19 @@ CInputs::CInputs(CInputSystem *system) : m_system(system)
handBrake = AddSwitchInput("HandBrake", "Hand Brake", GAME_INPUT_RALLY, "KEY_S,JOY1_BUTTON2");
// Virtua On Controls
twinJoyTurnLeft = AddSwitchInput("TwinJoyTurnLeft", "Turn Left", GAME_INPUT_TWIN_JOYSTICKS, "KEY_Q,JOY1_RZAXIS_POS");
twinJoyTurnRight = AddSwitchInput("TwinJoyTurnRight", "Turn Right", GAME_INPUT_TWIN_JOYSTICKS, "KEY_W,JOY1_RZAXIS_NEG");
twinJoyForward = AddSwitchInput("TwinJoyForward", "Forward", GAME_INPUT_TWIN_JOYSTICKS, "KEY_UP,JOY1_UP");
twinJoyReverse = AddSwitchInput("TwinJoyReverse", "Reverse", GAME_INPUT_TWIN_JOYSTICKS, "KEY_DOWN,JOY1_DOWN");
twinJoyStrafeLeft = AddSwitchInput("TwinJoyStrafeLeft", "Strafe Left", GAME_INPUT_TWIN_JOYSTICKS, "KEY_LEFT,JOY1_LEFT");
twinJoyStrafeRight = AddSwitchInput("TwinJoyStrafeRight", "Strafe Right", GAME_INPUT_TWIN_JOYSTICKS, "KEY_RIGHT,JOY1_RIGHT");
twinJoyTurnLeft = AddSwitchInput("TwinJoyTurnLeft", "Turn Left", GAME_INPUT_TWIN_JOYSTICKS, "KEY_Q,JOY1_RXAXIS_NEG");
twinJoyTurnRight = AddSwitchInput("TwinJoyTurnRight", "Turn Right", GAME_INPUT_TWIN_JOYSTICKS, "KEY_W,JOY1_RXAXIS_POS");
twinJoyForward = AddSwitchInput("TwinJoyForward", "Forward", GAME_INPUT_TWIN_JOYSTICKS, "KEY_UP,JOY1_YAXIS_NEG");
twinJoyReverse = AddSwitchInput("TwinJoyReverse", "Reverse", GAME_INPUT_TWIN_JOYSTICKS, "KEY_DOWN,JOY1_YAXIS_POS");
twinJoyStrafeLeft = AddSwitchInput("TwinJoyStrafeLeft", "Strafe Left", GAME_INPUT_TWIN_JOYSTICKS, "KEY_LEFT,JOY1_XAXIS_NEG");
twinJoyStrafeRight = AddSwitchInput("TwinJoyStrafeRight", "Strafe Right", GAME_INPUT_TWIN_JOYSTICKS, "KEY_RIGHT,JOY1_XAXIS_POS");
twinJoyJump = AddSwitchInput("TwinJoyJump", "Jump", GAME_INPUT_TWIN_JOYSTICKS, "KEY_E,JOY1_BUTTON1");
twinJoyCrouch = AddSwitchInput("TwinJoyCrouch", "Crouch", GAME_INPUT_TWIN_JOYSTICKS, "KEY_R,JOY1_BUTTON2");
twinJoyLeftShot = AddSwitchInput("TwinJoyLeftShot", "Left Shot Trigger", GAME_INPUT_TWIN_JOYSTICKS, "KEY_A,JOY1_BUTTON5");
twinJoyRightShot = AddSwitchInput("TwinJoyRightShot", "Right Shot Trigger", GAME_INPUT_TWIN_JOYSTICKS, "KEY_S,JOY1_BUTTON6");
twinJoyLeftTurbo = AddSwitchInput("TwinJoyLeftTurbo", "Left Turbo", GAME_INPUT_TWIN_JOYSTICKS, "KEY_Z,JOY1_BUTTON7");
twinJoyRightTurbo = AddSwitchInput("TwinJoyRightTurbo", "Right Turbo", GAME_INPUT_TWIN_JOYSTICKS, "KEY_X,JOY1_BUTTON8");
// Analog Joystick
CAnalogInput *analogJoyLeft = AddAnalogInput("AnalogJoyLeft", "Analog Left", GAME_INPUT_ANALOG_JOYSTICK, "KEY_LEFT");
CAnalogInput *analogJoyRight = AddAnalogInput("AnalogJoyRight", "Analog Right", GAME_INPUT_ANALOG_JOYSTICK, "KEY_RIGHT");
@ -119,29 +117,36 @@ CInputs::CInputs(CInputSystem *system) : m_system(system)
CAnalogInput *gun1Up = AddAnalogInput("GunUp", "P1 Gun Up", GAME_INPUT_GUN1, "KEY_UP");
CAnalogInput *gun1Down = AddAnalogInput("GunDown", "P1 Gun Down", GAME_INPUT_GUN1, "KEY_DOWN");
gunX[0] = AddAxisInput ("GunX", "P1 Gun X-Axis", GAME_INPUT_GUN1, "JOY1_XAXIS,MOUSE_XAXIS", gun1Left, gun1Right, 150, 400, 651); // normalize to [150,651]
gunY[0] = AddAxisInput ("GunY", "P1 Gun Y-Axis", GAME_INPUT_GUN1, "JOY1_YAXIS,MOUSE_YAXIS", gun1Up, gun1Down, 80, 272, 465); // normalize to [80,465]
trigger[0] = AddSwitchInput("Trigger", "P1 Trigger", GAME_INPUT_GUN1, "KEY_A,JOY1_BUTTON1,MOUSE_LEFT_BUTTON");
offscreen[0] = AddSwitchInput("Offscreen", "P1 Point Off-screen", GAME_INPUT_GUN1, "KEY_S,JOY1_BUTTON2,MOUSE_RIGHT_BUTTON");
gunX[0] = AddAxisInput("GunX", "P1 Gun X-Axis", GAME_INPUT_GUN1, "MOUSE_XAXIS,JOY1_XAXIS", gun1Left, gun1Right, 150, 400, 651); // normalize to [150,651]
gunY[0] = AddAxisInput("GunY", "P1 Gun Y-Axis", GAME_INPUT_GUN1, "MOUSE_YAXIS,JOY1_YAXIS", gun1Up, gun1Down, 80, 272, 465); // normalize to [80,465]
CSwitchInput *gun1Trigger = AddSwitchInput("Trigger", "P1 Trigger", GAME_INPUT_GUN1, "KEY_A,JOY1_BUTTON1,MOUSE_LEFT_BUTTON");
CSwitchInput *gun1Offscreen = AddSwitchInput("Offscreen", "P1 Point Off-screen", GAME_INPUT_GUN1, "KEY_S,JOY1_BUTTON2,MOUSE_RIGHT_BUTTON");
trigger[0] = AddTriggerInput("AutoTrigger", "P1 Auto Trigger", GAME_INPUT_GUN1, gun1Trigger, gun1Offscreen);
CAnalogInput *gun2Left = AddAnalogInput("GunLeft2", "P2 Gun Left", GAME_INPUT_GUN2, "NONE");
CAnalogInput *gun2Right = AddAnalogInput("GunRight2", "P2 Gun Right", GAME_INPUT_GUN2, "NONE");
CAnalogInput *gun2Up = AddAnalogInput("GunUp2", "P2 Gun Up", GAME_INPUT_GUN2, "NONE");
CAnalogInput *gun2Down = AddAnalogInput("GunDown2", "P2 Gun Down", GAME_INPUT_GUN2, "NONE");
gunX[1] = AddAxisInput ("GunX2", "P2 Gun X-Axis", GAME_INPUT_GUN2, "JOY2_XAXIS", gun2Left, gun2Right, 150, 400, 651); // normalize to [150,651]
gunY[1] = AddAxisInput ("GunY2", "P2 Gun Y-Axis", GAME_INPUT_GUN2, "JOY2_YAXIS", gun2Up, gun2Down, 80, 272, 465); // normalize to [80,465]
trigger[1] = AddSwitchInput("Trigger2", "P2 Trigger", GAME_INPUT_GUN2, "JOY2_BUTTON1");
offscreen[1] = AddSwitchInput("Offscreen2", "P2 Point Off-screen", GAME_INPUT_GUN2, "JOY2_BUTTON2");
gunX[1] = AddAxisInput("GunX2", "P2 Gun X-Axis", GAME_INPUT_GUN2, "JOY2_XAXIS", gun2Left, gun2Right, 150, 400, 651); // normalize to [150,651]
gunY[1] = AddAxisInput("GunY2", "P2 Gun Y-Axis", GAME_INPUT_GUN2, "JOY2_YAXIS", gun2Up, gun2Down, 80, 272, 465); // normalize to [80,465]
CSwitchInput *gun2Trigger = AddSwitchInput("Trigger2", "P2 Trigger", GAME_INPUT_GUN2, "JOY2_BUTTON1");
CSwitchInput *gun2Offscreen = AddSwitchInput("Offscreen2", "P2 Point Off-screen", GAME_INPUT_GUN2, "JOY2_BUTTON2");
trigger[1] = AddTriggerInput("AutoTrigger2", "P2 Auto Trigger", GAME_INPUT_GUN2, gun2Trigger, gun2Offscreen);
}
CInputs::~CInputs()
{
for (vector<CInput*>::iterator it = m_inputs.begin(); it < m_inputs.end(); it++)
for (vector<CInput*>::iterator it = m_inputs.begin(); it != m_inputs.end(); it++)
delete *it;
m_inputs.clear();
}
CSwitchInput* CInputs::AddSwitchInput(const char *id, const char *label, unsigned gameFlags, const char *defaultMapping,
CSwitchInput *CInputs::AddSwitchInput(const char *id, const char *label, unsigned gameFlags, const char *defaultMapping,
UINT16 offVal, UINT16 onVal)
{
CSwitchInput *input = new CSwitchInput(id, label, gameFlags, defaultMapping, offVal, onVal);
@ -149,7 +154,7 @@ CSwitchInput* CInputs::AddSwitchInput(const char *id, const char *label, unsigne
return input;
}
CAnalogInput* CInputs::AddAnalogInput(const char *id, const char *label, unsigned gameFlags, const char *defaultMapping,
CAnalogInput *CInputs::AddAnalogInput(const char *id, const char *label, unsigned gameFlags, const char *defaultMapping,
UINT16 minVal, UINT16 maxVal)
{
CAnalogInput *input = new CAnalogInput(id, label, gameFlags, defaultMapping, minVal, maxVal);
@ -157,15 +162,15 @@ CAnalogInput* CInputs::AddAnalogInput(const char *id, const char *label, unsigne
return input;
}
CAxisInput* CInputs::AddAxisInput(const char *id, const char *label, unsigned gameFlags, const char *defaultMapping,
CAnalogInput* axisNeg, CAnalogInput* axisPos, UINT16 minVal, UINT16 offVal, UINT16 maxVal)
CAxisInput *CInputs::AddAxisInput(const char *id, const char *label, unsigned gameFlags, const char *defaultMapping,
CAnalogInput *axisNeg, CAnalogInput *axisPos, UINT16 minVal, UINT16 offVal, UINT16 maxVal)
{
CAxisInput *input = new CAxisInput(id, label, gameFlags, defaultMapping, axisNeg, axisPos, minVal, offVal, maxVal);
m_inputs.push_back(input);
return input;
}
CGearShift4Input* CInputs::AddGearShift4Input(const char *id, const char *label, unsigned gameFlags,
CGearShift4Input *CInputs::AddGearShift4Input(const char *id, const char *label, unsigned gameFlags,
CSwitchInput *shift1, CSwitchInput *shift2, CSwitchInput *shift3, CSwitchInput *shift4, CSwitchInput *shiftUp, CSwitchInput *shiftDown)
{
CGearShift4Input *input = new CGearShift4Input(id, label, gameFlags, shift1, shift2, shift3, shift4, shiftUp, shiftDown);
@ -173,6 +178,14 @@ CGearShift4Input* CInputs::AddGearShift4Input(const char *id, const char *label,
return input;
}
CTriggerInput *CInputs::AddTriggerInput(const char *id, const char *label, unsigned gameFlags,
CSwitchInput *trigger, CSwitchInput *offscreen, UINT16 offVal, UINT16 onVal)
{
CTriggerInput *input = new CTriggerInput(id, label, gameFlags, trigger, offscreen, offVal, onVal);
m_inputs.push_back(input);
return input;
}
void CInputs::PrintHeader(const char *fmt, ...)
{
char header[1024];
@ -199,20 +212,23 @@ void CInputs::PrintConfigureInputsHelp()
puts(" r Reset current input mapping to default and remain there,");
puts(" Down Move onto next control,");
puts(" Up Go back to previous control,");
puts(" i Display information about input system and attached devices,");
puts(" h Display this help again,");
puts(" q Finish and save all changes,");
puts(" Esc Finish without saving any changes.");
puts("");
puts("To assign inputs, simply press the appropriate key, mouse button or");
puts("joystick button or move the mouse along an axis or move a joystick's");
puts("axis or POV hat controller.");
puts("To assign input(s), simply press the appropriate key(s), mouse button(s)");
puts("or joystick button(s) or move the mouse along one or more axes or move a");
puts("joystick's axis or POV hat controller(s). The input(s) will be accepted");
puts("as soon as all pressed keys and buttons are released and all moved mouse");
puts("and joystick controllers are returned to their rest positions.");
puts("");
puts("NOTES:");
puts(" - in order to assign a key the configuration window must on top,");
puts(" - in order to assign a mouse button the mouse must be clicked");
puts(" - in order to assign keys the configuration window must on top,");
puts(" - in order to assign mouse buttons the mouse must be clicked");
puts(" within the window,");
puts(" - in order to assign a mouse axis, the cursor must be placed in");
puts(" the center of the window and moved in the corresponding");
puts(" - in order to assign mouse axes, the cursor must first be placed in");
puts(" the center of the window and then moved in the corresponding");
puts(" direction to the window's edge and then returned to the center.");
puts("");
}
@ -229,58 +245,26 @@ bool CInputs::Initialize()
return false;
// Initialize all the inputs
for (vector<CInput*>::iterator it = m_inputs.begin(); it < m_inputs.end(); it++)
for (vector<CInput*>::iterator it = m_inputs.begin(); it != m_inputs.end(); it++)
(*it)->Initialize(m_system);
return true;
}
bool CInputs::InputIsConfigurable(CInput *input)
{
// All inputs except UI and virtual ones can be configured by the user
return input->flags != UI_INPUT && !(input->flags & INPUT_FLAGS_VIRTUAL);
}
CInput* CInputs::LookupInputByID(const char* id)
{
for (vector<CInput*>::iterator it = m_inputs.begin(); it < m_inputs.end(); it++)
{
if (stricmp(id, (*it)->id) == 0)
return *it;
}
return NULL;
}
void CInputs::ReadFromINIFile(CINIFile *ini, const char *section)
{
for (vector<CInput*>::iterator it = m_inputs.begin(); it < m_inputs.end(); it++)
{
if (!InputIsConfigurable(*it))
continue;
string key("Input");
key.append((*it)->id);
string mapping;
if (ini->Get(section, key, mapping) == OKAY)
(*it)->SetMapping(mapping.c_str());
}
for (vector<CInput*>::iterator it = m_inputs.begin(); it != m_inputs.end(); it++)
(*it)->ReadFromINIFile(ini, section);
}
void CInputs::WriteToINIFile(CINIFile *ini, const char *section)
{
for (vector<CInput*>::iterator it = m_inputs.begin(); it < m_inputs.end(); it++)
{
if (!InputIsConfigurable(*it))
continue;
string key("Input");
key.append((*it)->id);
ini->Set(section, key, (*it)->GetMapping());
}
for (vector<CInput*>::iterator it = m_inputs.begin(); it != m_inputs.end(); it++)
(*it)->WriteToINIFile(ini, section);
}
bool CInputs::ConfigureInputs(const GameInfo *game, unsigned dispX, unsigned dispY, unsigned dispW, unsigned dispH)
{
m_system->ConfigStart();
m_system->UngrabMouse();
// Let the input system know the display geometry
m_system->SetDisplayGeom(dispX, dispY, dispW, dispH);
@ -302,16 +286,16 @@ bool CInputs::ConfigureInputs(const GameInfo *game, unsigned dispX, unsigned dis
// Get all inputs to be configured
vector<CInput*> toConfigure;
vector<CInput*>::iterator it;
for (it = m_inputs.begin(); it < m_inputs.end(); it++)
for (it = m_inputs.begin(); it != m_inputs.end(); it++)
{
if (InputIsConfigurable(*it) && ((*it)->gameFlags & gameFlags))
if ((*it)->IsConfigurable() && ((*it)->gameFlags & gameFlags))
toConfigure.push_back(*it);
}
// Remember current mappings for each input in case changes need to be undone later
vector<string> oldMappings(toConfigure.size());
size_t index = 0;
for (it = toConfigure.begin(); it < toConfigure.end(); it++)
for (it = toConfigure.begin(); it != toConfigure.end(); it++)
oldMappings[index++] = (*it)->GetMapping();
const char *groupLabel = NULL;
@ -321,7 +305,7 @@ bool CInputs::ConfigureInputs(const GameInfo *game, unsigned dispX, unsigned dis
while (index < toConfigure.size())
{
// Get the current input
CInput* input = toConfigure[index];
CInput *input = toConfigure[index];
// If have moved to a new input group, print the group heading
const char *itGroupLabel = input->GetInputGroup();
@ -349,14 +333,14 @@ Redisplay:
{
// If user pressed aborted input, then undo all changes and finish configuration
index = 0;
for (it = toConfigure.begin(); it < toConfigure.end(); it++)
for (it = toConfigure.begin(); it != toConfigure.end(); it++)
{
(*it)->SetMapping(oldMappings[index].c_str());
index++;
}
puts("");
m_system->ConfigEnd();
m_system->GrabMouse();
return false;
}
@ -427,10 +411,17 @@ Redisplay:
index = 0;
done = true;
}
else if (stricmp(mapping, "KEY_I") == 0)
{
// Print info about input system
printf("\n\n");
m_system->PrintSettings();
goto Redisplay;
}
else if (stricmp(mapping, "KEY_H") == 0)
{
// Print the help message again
puts("");
printf("\n\n");
PrintConfigureInputsHelp();
goto Redisplay;
}
@ -439,7 +430,7 @@ Redisplay:
// Finish configuration
puts("");
m_system->ConfigEnd();
m_system->GrabMouse();
return true;
}
}
@ -448,7 +439,7 @@ Redisplay:
// All inputs set, finish configuration
puts("");
m_system->ConfigEnd();
m_system->GrabMouse();
return true;
}
@ -468,10 +459,9 @@ void CInputs::PrintInputs(const GameInfo *game)
}
const char *groupLabel = NULL;
for (vector<CInput*>::iterator it = m_inputs.begin(); it < m_inputs.end(); it++)
for (vector<CInput*>::iterator it = m_inputs.begin(); it != m_inputs.end(); it++)
{
if (!InputIsConfigurable(*it) || !((*it)->gameFlags & gameFlags))
if (!(*it)->IsConfigurable() || !((*it)->gameFlags & gameFlags))
continue;
const char *itGroupLabel = (*it)->GetInputGroup();
@ -498,9 +488,9 @@ bool CInputs::Poll(const GameInfo *game, unsigned dispX, unsigned dispY, unsigne
// Poll all UI inputs and all the inputs used by the current game, or all inputs if game is NULL
int gameFlags = (game != NULL ? game->inputFlags : GAME_INPUT_ALL);
for (vector<CInput*>::iterator it = m_inputs.begin(); it < m_inputs.end(); it++)
for (vector<CInput*>::iterator it = m_inputs.begin(); it != m_inputs.end(); it++)
{
if ((*it)->gameFlags == UI_INPUT || (*it)->gameFlags & gameFlags)
if ((*it)->IsUIInput() || ((*it)->gameFlags & gameFlags))
(*it)->Poll();
}
return true;
@ -522,14 +512,14 @@ void CInputs::DumpState(const GameInfo *game)
}
// Loop through the inputs used by the current game, or all inputs if game is NULL, and dump their values to stdout
for (vector<CInput*>::iterator it = m_inputs.begin(); it < m_inputs.end(); it++)
for (vector<CInput*>::iterator it = m_inputs.begin(); it != m_inputs.end(); it++)
{
if (!((*it)->gameFlags & gameFlags))
if (!(*it)->IsUIInput() && !((*it)->gameFlags & gameFlags))
continue;
if (InputIsConfigurable(*it))
printf("%s [%s] = (%d)\n", (*it)->id, (*it)->GetMapping(), (*it)->value);
else
if ((*it)->IsVirtual())
printf("%s = (%d)\n", (*it)->id, (*it)->value);
else
printf("%s [%s] = (%d)\n", (*it)->id, (*it)->GetMapping(), (*it)->value);
}
}

View file

@ -12,6 +12,7 @@ class CAnalogInput;
class CAxisInput;
class CSwitchInput;
class CGearShift4Input;
class CTriggerInput;
class CINIFile;
struct GameInfo;
@ -30,113 +31,121 @@ private:
/*
* Adds a switch input (eg button) to this collection.
*/
CSwitchInput* AddSwitchInput(const char *id, const char *label, unsigned gameFlags, const char *defaultMapping,
CSwitchInput *AddSwitchInput(const char *id, const char *label, unsigned gameFlags, const char *defaultMapping,
UINT16 offVal = 0x00, UINT16 onVal = 0x01);
/*
* Adds an analog input (eg pedal) to this collection.
*/
CAnalogInput* AddAnalogInput(const char *id, const char *label, unsigned gameFlags, const char *defaultMapping,
CAnalogInput *AddAnalogInput(const char *id, const char *label, unsigned gameFlags, const char *defaultMapping,
UINT16 minVal = 0x00, UINT16 maxVal = 0xFF);
/*
* Adds an axis input (eg jostick axis, light gun axis or steering wheel) to this collection.
*/
CAxisInput* AddAxisInput(const char *id, const char *label, unsigned gameFlags, const char *defaultMapping,
CAnalogInput* axisNeg, CAnalogInput* axisPos, UINT16 minVal = 0x00, UINT16 offVal = 0x80, UINT16 maxVal = 0xFF);
CAxisInput *AddAxisInput(const char *id, const char *label, unsigned gameFlags, const char *defaultMapping,
CAnalogInput *axisNeg, CAnalogInput *axisPos, UINT16 minVal = 0x00, UINT16 offVal = 0x80, UINT16 maxVal = 0xFF);
/*
* Adds a 4-gear shifter input to this collection.
*/
CGearShift4Input* AddGearShift4Input(const char *id, const char *label, unsigned gameFlags,
CGearShift4Input *AddGearShift4Input(const char *id, const char *label, unsigned gameFlags,
CSwitchInput *shift1, CSwitchInput *shift2, CSwitchInput *shift3, CSwitchInput *shift4, CSwitchInput *shiftUp, CSwitchInput *shiftDown);
/*
* Adds a lightgun trigger input to this collection.
*/
CTriggerInput *AddTriggerInput(const char *id, const char *label, unsigned gameFlags,
CSwitchInput *trigger, CSwitchInput *offscreen, UINT16 offVal = 0x00, UINT16 onVal = 0x01);
void PrintHeader(const char *fmt, ...);
void PrintConfigureInputsHelp();
public:
// UI controls
CSwitchInput* uiExit;
CSwitchInput* uiReset;
CSwitchInput* uiPause;
CSwitchInput* uiSaveState;
CSwitchInput* uiChangeSlot;
CSwitchInput* uiLoadState;
CSwitchInput* uiDumpInpState;
CSwitchInput* uiClearNVRAM;
CSwitchInput* uiToggleCursor;
CSwitchInput* uiToggleFrLimit;
CSwitchInput *uiExit;
CSwitchInput *uiReset;
CSwitchInput *uiPause;
CSwitchInput *uiSaveState;
CSwitchInput *uiChangeSlot;
CSwitchInput *uiLoadState;
CSwitchInput *uiDumpInpState;
CSwitchInput *uiClearNVRAM;
CSwitchInput *uiToggleCursor;
CSwitchInput *uiToggleFrLimit;
// Common controls between all games
CSwitchInput* coin[2];
CSwitchInput* start[2];
CSwitchInput* test[2];
CSwitchInput* service[2];
CSwitchInput *coin[2];
CSwitchInput *start[2];
CSwitchInput *test[2];
CSwitchInput *service[2];
// Joysticks (players 1 and 2)
CSwitchInput* up[2];
CSwitchInput* down[2];
CSwitchInput* left[2];
CSwitchInput* right[2];
CSwitchInput *up[2];
CSwitchInput *down[2];
CSwitchInput *left[2];
CSwitchInput *right[2];
// Fighting game controls (players 1 and 2)
CSwitchInput* punch[2];
CSwitchInput* kick[2];
CSwitchInput* guard[2];
CSwitchInput* escape[2];
CSwitchInput *punch[2];
CSwitchInput *kick[2];
CSwitchInput *guard[2];
CSwitchInput *escape[2];
// Soccer game controls (players 1 and 2)
CSwitchInput* shortPass[2];
CSwitchInput* longPass[2];
CSwitchInput* shoot[2];
CSwitchInput *shortPass[2];
CSwitchInput *longPass[2];
CSwitchInput *shoot[2];
// Vehicle controls
CAxisInput* steering;
CAnalogInput* accelerator;
CAnalogInput* brake;
CAxisInput *steering;
CAnalogInput *accelerator;
CAnalogInput *brake;
// VR view buttons: VR1 Red, VR2 Blue, VR3 Yellow, VR4 Green
CSwitchInput* vr[4];
CSwitchInput *vr[4];
// 4-speed gear shift
CGearShift4Input* gearShift4;
CGearShift4Input *gearShift4;
// Rally controls
CSwitchInput* viewChange;
CSwitchInput* handBrake;
CSwitchInput *viewChange;
CSwitchInput *handBrake;
// Twin joysticks
CSwitchInput* twinJoyTurnLeft;
CSwitchInput* twinJoyTurnRight;
CSwitchInput* twinJoyStrafeLeft;
CSwitchInput* twinJoyStrafeRight;
CSwitchInput* twinJoyForward;
CSwitchInput* twinJoyReverse;
CSwitchInput* twinJoyJump;
CSwitchInput* twinJoyCrouch;
CSwitchInput* twinJoyLeftShot;
CSwitchInput* twinJoyRightShot;
CSwitchInput* twinJoyLeftTurbo;
CSwitchInput* twinJoyRightTurbo;
CSwitchInput *twinJoyTurnLeft;
CSwitchInput *twinJoyTurnRight;
CSwitchInput *twinJoyStrafeLeft;
CSwitchInput *twinJoyStrafeRight;
CSwitchInput *twinJoyForward;
CSwitchInput *twinJoyReverse;
CSwitchInput *twinJoyJump;
CSwitchInput *twinJoyCrouch;
CSwitchInput *twinJoyLeftShot;
CSwitchInput *twinJoyRightShot;
CSwitchInput *twinJoyLeftTurbo;
CSwitchInput *twinJoyRightTurbo;
// Analog joystick
CAxisInput* analogJoyX;
CAxisInput* analogJoyY;
CSwitchInput* analogJoyTrigger;
CSwitchInput* analogJoyEvent;
CAxisInput *analogJoyX;
CAxisInput *analogJoyY;
CSwitchInput *analogJoyTrigger;
CSwitchInput *analogJoyEvent;
// Gun controls (players 1 and 2)
CAxisInput* gunX[2];
CAxisInput* gunY[2];
CSwitchInput* trigger[2];
CSwitchInput* offscreen[2];
CAxisInput *gunX[2];
CAxisInput *gunY[2];
CTriggerInput *trigger[2];
/*
* Creates a set of inputs with the given input system.
*/
CInputs(CInputSystem *system);
/*
* CInputs destructor.
*/
~CInputs();
/*
@ -144,21 +153,31 @@ public:
*/
CInputSystem *GetInputSystem();
unsigned Count()
{
return (unsigned)m_inputs.size();
}
CInput *operator[](const unsigned index)
{
return m_inputs[index];
}
CInput *operator[](const char *idOrLabel)
{
for (vector<CInput*>::iterator it = m_inputs.begin(); it != m_inputs.end(); it++)
{
if (stricmp((*it)->id, idOrLabel) == 0 || stricmp((*it)->label, idOrLabel) == 0)
return *it;
}
return NULL;
}
/*
* Initializes the inputs. Must be called before any other methods are used.
*/
bool Initialize();
/*
* Looks up an input by its identifier.
*/
CInput* LookupInputByID(const char* id);
/*
* Returns true if the given input is configurable and can be set by the user.
*/
bool InputIsConfigurable(CInput *input);
/*
* Reads the input mapping assignments from the given INI file.
*/

View file

@ -12,7 +12,7 @@ ESourceType CMultiInputSource::GetCombinedType(vector<CInputSource*> &sources)
bool allSwitches = true;
bool hasFullAxis = false;
bool hasHalfAxis = false;
for (vector<CInputSource*>::iterator it = sources.begin(); it < sources.end(); it++)
for (vector<CInputSource*>::iterator it = sources.begin(); it != sources.end(); it++)
{
if ((*it)->type == SourceInvalid)
return SourceInvalid; // An invalid source makes the whole lot invalid
@ -39,10 +39,10 @@ ESourceType CMultiInputSource::GetCombinedType(vector<CInputSource*> &sources)
else return SourceEmpty;
}
CMultiInputSource::CMultiInputSource() : CInputSource(SourceEmpty), m_isOr(true), m_numSrcs(0), m_srcArray(NULL) { }
CMultiInputSource::CMultiInputSource(CInputSystem *system) : CInputSource(SourceEmpty), m_system(system), m_isOr(true), m_numSrcs(0), m_srcArray(NULL) { }
CMultiInputSource::CMultiInputSource(bool isOr, vector<CInputSource*> &sources) :
CInputSource(GetCombinedType(sources)), m_isOr(isOr), m_numSrcs(sources.size())
CMultiInputSource::CMultiInputSource(CInputSystem *system, bool isOr, vector<CInputSource*> &sources) :
CInputSource(GetCombinedType(sources)), m_system(system), m_isOr(isOr), m_numSrcs(sources.size())
{
m_srcArray = new CInputSource*[m_numSrcs];
copy(sources.begin(), sources.end(), m_srcArray);
@ -51,7 +51,11 @@ CMultiInputSource::CMultiInputSource(bool isOr, vector<CInputSource*> &sources)
CMultiInputSource::~CMultiInputSource()
{
if (m_srcArray != NULL)
{
for (int i = 0; i < m_numSrcs; i++)
m_system->ReleaseSource(m_srcArray[i]);
delete m_srcArray;
}
}
bool CMultiInputSource::GetValueAsSwitch(bool &val)
@ -68,20 +72,13 @@ bool CMultiInputSource::GetValueAsSwitch(bool &val)
}
else
{
// Check all switch inputs are active
// Check all inputs are active
for (int i = 0; i < m_numSrcs; i++)
{
if (m_srcArray[i]->type == SourceSwitch && !m_srcArray[i]->GetValueAsSwitch(val))
if (!m_srcArray[i]->GetValueAsSwitch(val))
return false;
}
// Then return value for first non-switch input that is active
for (int i = 0; i < m_numSrcs; i++)
{
if (m_srcArray[i]->type != SourceSwitch && m_srcArray[i]->GetValueAsSwitch(val))
return true;
}
// Otherwise, value is only valid if not empty and all inputs are switches
return m_numSrcs > 0 && type == SourceSwitch;
return m_numSrcs > 0;
}
}
@ -105,13 +102,52 @@ bool CMultiInputSource::GetValueAsAnalog(int &val, int minVal, int offVal, int m
if (m_srcArray[i]->type == SourceSwitch && !m_srcArray[i]->GetValueAsAnalog(val, minVal, offVal, maxVal))
return false;
}
// Then return value for first non-switch input that is active
// If so, then return value for first non-switch input that is active
for (int i = 0; i < m_numSrcs; i++)
{
if (m_srcArray[i]->type != SourceSwitch && m_srcArray[i]->GetValueAsAnalog(val, minVal, offVal, maxVal))
return true;
}
// Otherwise, value is only valid if not empty and all inputs are switches
// If non found, then value is only valid if not empty and all inputs are switches
return m_numSrcs > 0 && type == SourceSwitch;
}
}
bool CMultiInputSource::SendForceFeedbackCmd(ForceFeedbackCmd *ffCmd)
{
bool result = false;
for (int i = 0; i < m_numSrcs; i++)
result |= m_srcArray[i]->SendForceFeedbackCmd(ffCmd);
return result;
}
CNegInputSource::CNegInputSource(CInputSystem *system, CInputSource *source) : CInputSource(source->type), m_system(system), m_source(source) { }
CNegInputSource::~CNegInputSource()
{
m_system->ReleaseSource(m_source);
}
bool CNegInputSource::GetValueAsSwitch(bool &val)
{
bool oldVal = val;
if (m_source->GetValueAsSwitch(val))
{
val = oldVal;
return false;
}
val = true;
return true;
}
bool CNegInputSource::GetValueAsAnalog(int &val, int minVal, int offVal, int maxVal)
{
int oldVal = val;
if (m_source->GetValueAsAnalog(val, minVal, offVal, maxVal))
{
val = oldVal;
return false;
}
val = maxVal;
return true;
}

View file

@ -5,13 +5,18 @@
#include <vector>
using namespace std;
/*
* Represents a collection of input sources and combines their values into a single value.
* When multiple mappings are assigned to an input, this is the input source that is created.
* Can either represent a combination of multiple assignments that all map to the same input, eg KEY_ALT,JOY1_BUTTON1 or be
* used specify that controls must be activated together, eg KEY_ALT+KEY_P.
*/
class CMultiInputSource : public CInputSource
{
private:
// Input system that created this source
CInputSystem *m_system;
// Controls how the inputs sources are combined
bool m_isOr;
@ -31,7 +36,7 @@ public:
/*
* Constructs an 'empty' source (ie one which is always 'off').
*/
CMultiInputSource();
CMultiInputSource(CInputSystem *system);
/*
* Constructs a multiple input source from the given vector of sources.
@ -39,12 +44,38 @@ public:
* switch inputs must be active for this input to have a value (which will be the value of the first non-switch input in the list,
* or the first switch input if there are none).
*/
CMultiInputSource(bool isOr, vector<CInputSource*> &sources);
CMultiInputSource(CInputSystem *system, bool isOr, vector<CInputSource*> &sources);
~CMultiInputSource();
bool GetValueAsSwitch(bool &val);
bool GetValueAsAnalog(int &val, int minVal, int offVal, int maxVal);
bool SendForceFeedbackCmd(ForceFeedbackCmd *ffCmd);
};
/*
* Represents a negation of an input source - ie is active when the given source is inactive and vice-versa.
* Can be used to specify that a particular input must not be active when used in multiple assignments, eg !KEY_ALT+KEY_P. This helps
* to get rid of collisions that might otherwise occur.
*/
class CNegInputSource : public CInputSource
{
private:
// Input system that created this source
CInputSystem *m_system;
// Input source being negated
CInputSource *m_source;
public:
CNegInputSource(CInputSystem *system, CInputSource *source);
~CNegInputSource();
bool GetValueAsSwitch(bool &val);
bool GetValueAsAnalog(int &val, int minVal, int offVal, int maxVal);
};

View file

@ -471,7 +471,7 @@ void CModel3::WriteInputs(unsigned reg, UINT8 data)
serialFIFO2 = (Inputs->gunX[1]->value>>8)&3;
break;
case 8: // Off-screen indicator (bit 0 = player 1, bit 1 = player 2, set indicates off screen)
serialFIFO2 = (Inputs->offscreen[1]->value<<1)|Inputs->offscreen[0]->value;
serialFIFO2 = (Inputs->trigger[1]->offscreenValue<<1)|Inputs->trigger[0]->offscreenValue;
break;
default:
DebugLog("Unknown gun register: %X\n", gunReg);

View file

@ -28,8 +28,6 @@
#ifndef INCLUDED_MODEL3_H
#define INCLUDED_MODEL3_H
#include "Inputs/Inputs.h"
/*
* CModel3:
*

View file

@ -203,7 +203,9 @@ int SCSP68KRunCallback(int numCycles)
void CSoundBoard::WriteMIDIPort(UINT8 data)
{
#ifdef SUPERMODEL_SOUND
SCSP_MidiIn(data);
#endif
}
void CSoundBoard::RunFrame(void)
@ -252,6 +254,7 @@ void CSoundBoard::Reset(void)
BOOL CSoundBoard::Init(const UINT8 *soundROMPtr, const UINT8 *sampleROMPtr, CIRQ *ppcIRQObjectPtr, unsigned soundIRQBit)
{
#ifdef SUPERMODEL_SOUND
float memSizeMB = (float)MEMORY_POOL_SIZE/(float)0x100000;
// Attach IRQ controller
@ -273,7 +276,6 @@ BOOL CSoundBoard::Init(const UINT8 *soundROMPtr, const UINT8 *sampleROMPtr, CIRQ
ram2 = &memoryPool[OFFSET_RAM2];
// Initialize 68K core
#ifdef SUPERMODEL_SOUND
mapFetch[0].ptr = mapRead8[0].ptr = mapRead16[0].ptr = mapRead32[0].ptr =
mapWrite8[0].ptr = mapWrite16[0].ptr = mapWrite32[0].ptr = (UINT32)ram1 - mapFetch[0].base;;
@ -296,7 +298,6 @@ BOOL CSoundBoard::Init(const UINT8 *soundROMPtr, const UINT8 *sampleROMPtr, CIRQ
Turbo68KSetWriteByte(mapWrite8, NULL);
Turbo68KSetWriteWord(mapWrite16, NULL);
Turbo68KSetWriteLong(mapWrite32, NULL);
#endif
// Initialize SCSPs
SCSP_SetBuffers(leftBuffer, rightBuffer, 44100/60);
@ -306,7 +307,6 @@ BOOL CSoundBoard::Init(const UINT8 *soundROMPtr, const UINT8 *sampleROMPtr, CIRQ
SCSP_SetRAM(1, ram2);
// Binary logging
#ifdef SUPERMODEL_SOUND
soundFP = fopen("sound.bin","wb"); // delete existing file
fclose(soundFP);
soundFP = fopen("sound.bin","ab"); // append mode
@ -364,7 +364,6 @@ CSoundBoard::~CSoundBoard(void)
}
//#endif
#endif
SCSP_Deinit();
@ -375,5 +374,7 @@ CSoundBoard::~CSoundBoard(void)
}
ram1 = NULL;
ram2 = NULL;
#endif
DebugLog("Destroyed Sound Board\n");
}

View file

@ -1025,9 +1025,11 @@ int main(int argc, char **argv)
InputSystem = new CSDLInputSystem();
#ifdef SUPERMODEL_WIN32
else if (stricmp(inpSysName, "dinput") == 0)
InputSystem = new CDirectInputSystem(false);
InputSystem = new CDirectInputSystem(false, false, false);
else if (stricmp(inpSysName, "xinput") == 0)
InputSystem = new CDirectInputSystem(false, true, false);
else if (stricmp(inpSysName, "rawinput") == 0)
InputSystem = new CDirectInputSystem(true);
InputSystem = new CDirectInputSystem(true, false, false);
#endif
else
{

View file

@ -178,17 +178,20 @@ void CSDLInputSystem::OpenJoysticks()
continue;
}
// Gather joystick details (num POVs & buttons and which axes are available)
int numAxes = SDL_JoystickNumAxes(joystick);
JoyDetails *joyDetails = new JoyDetails();
joyDetails->hasXAxis = numAxes > 0;
joyDetails->hasYAxis = numAxes > 1;
joyDetails->hasZAxis = numAxes > 2;
joyDetails->hasRXAxis = numAxes > 3;
joyDetails->hasRYAxis = numAxes > 4;
joyDetails->hasRZAxis = numAxes > 5;
joyDetails->numPOVs = SDL_JoystickNumHats(joystick);
joyDetails->numButtons = SDL_JoystickNumButtons(joystick);
// Gather joystick details (name, num POVs & buttons and which axes are available)
JoyDetails joyDetails;
const char *pName = SDL_JoystickName(joyNum);
strncpy(joyDetails.name, pName, MAX_NAME_LENGTH - 1);
joyDetails.name[MAX_NAME_LENGTH - 1] = '\0';
joyDetails.numAxes = SDL_JoystickNumAxes(joystick);
for (int axisNum = 0; axisNum < NUM_JOY_AXES; axisNum++)
{
joyDetails.hasAxis[axisNum] = joyDetails.numAxes > axisNum;
joyDetails.axisHasFF[axisNum] = false; // SDL 1.2 does not support force feedback
}
joyDetails.numPOVs = SDL_JoystickNumHats(joystick);
joyDetails.numButtons = SDL_JoystickNumButtons(joystick);
joyDetails.hasFFeedback = false; // SDL 1.2 does not support force feedback
m_joysticks.push_back(joystick);
m_joyDetails.push_back(joyDetails);
@ -201,10 +204,7 @@ void CSDLInputSystem::CloseJoysticks()
for (size_t i = 0; i < m_joysticks.size(); i++)
{
SDL_Joystick *joystick = m_joysticks[i];
JoyDetails *joyDetails = m_joyDetails[i];
SDL_JoystickClose(joystick);
delete joyDetails;
}
m_joysticks.clear();
@ -227,24 +227,6 @@ bool CSDLInputSystem::InitializeSystem()
return true;
}
int CSDLInputSystem::GetNumKeyboards()
{
// Return ANY_KEYBOARD as SDL 1.2 cannot handle multiple keyboards
return ANY_KEYBOARD;
}
int CSDLInputSystem::GetNumMice()
{
// Return ANY_MOUSE as SDL 1.2 cannot handle multiple mice
return ANY_MOUSE;
}
int CSDLInputSystem::GetNumJoysticks()
{
// Return number of joysticks found
return m_joysticks.size();
}
int CSDLInputSystem::GetKeyIndex(const char *keyName)
{
for (int i = 0; i < NUM_SDL_KEYS; i++)
@ -262,11 +244,6 @@ const char *CSDLInputSystem::GetKeyName(int keyIndex)
return s_keyMap[keyIndex].keyName;
}
JoyDetails *CSDLInputSystem::GetJoyDetails(int joyNum)
{
return m_joyDetails[joyNum];
}
bool CSDLInputSystem::IsKeyPressed(int kbdNum, int keyIndex)
{
// Get SDL key for given index and check if currently pressed
@ -336,14 +313,50 @@ bool CSDLInputSystem::IsJoyButPressed(int joyNum, int butNum)
return !!SDL_JoystickGetButton(joystick, butNum);
}
bool CSDLInputSystem::ProcessForceFeedbackCmd(int joyNum, int axisNum, ForceFeedbackCmd *ffCmd)
{
// SDL 1.2 does not support force feedback
return false;
}
void CSDLInputSystem::Wait(int ms)
{
SDL_Delay(ms);
}
void CSDLInputSystem::SetMouseVisibility(bool visible)
int CSDLInputSystem::GetNumKeyboards()
{
SDL_ShowCursor(visible ? SDL_ENABLE : SDL_DISABLE);
// Return ANY_KEYBOARD as SDL 1.2 cannot handle multiple keyboards
return ANY_KEYBOARD;
}
int CSDLInputSystem::GetNumMice()
{
// Return ANY_MOUSE as SDL 1.2 cannot handle multiple mice
return ANY_MOUSE;
}
int CSDLInputSystem::GetNumJoysticks()
{
// Return number of joysticks found
return m_joysticks.size();
}
const KeyDetails *CSDLInputSystem::GetKeyDetails(int kbdNum)
{
// Return NULL as SDL 1.2 cannot handle multiple keyboards
return NULL;
}
const MouseDetails *CSDLInputSystem::GetMouseDetails(int mseNum)
{
// Return NULL as SDL 1.2 cannot handle multiple mice
return NULL;
}
const JoyDetails *CSDLInputSystem::GetJoyDetails(int joyNum)
{
return &m_joyDetails[joyNum];
}
bool CSDLInputSystem::Poll()
@ -383,4 +396,9 @@ bool CSDLInputSystem::Poll()
// Update joystick state (not required as called implicitly by SDL_PollEvent above)
//SDL_JoystickUpdate();
return true;
}
void CSDLInputSystem::SetMouseVisibility(bool visible)
{
SDL_ShowCursor(visible ? SDL_ENABLE : SDL_DISABLE);
}

View file

@ -34,7 +34,8 @@ private:
// Vector to keep track of attached joysticks
vector<SDL_Joystick*> m_joysticks;
vector<JoyDetails*> m_joyDetails;
// Vector of joystick details
vector<JoyDetails> m_joyDetails;
// Current key state obtained from SDL
Uint8 *m_keyState;
@ -62,18 +63,10 @@ protected:
*/
bool InitializeSystem();
int GetNumKeyboards();
int GetNumMice();
int GetNumJoysticks();
int GetKeyIndex(const char *keyName);
const char *GetKeyName(int keyIndex);
JoyDetails *GetJoyDetails(int joyNum);
bool IsKeyPressed(int kbdNum, int keyIndex);
int GetMouseAxisValue(int mseNum, int axisNum);
@ -88,9 +81,9 @@ protected:
bool IsJoyButPressed(int joyNum, int butNum);
void Wait(int ms);
bool ProcessForceFeedbackCmd(int joyNum, int axisNum, ForceFeedbackCmd *ffCmd);
void SetMouseVisibility(bool visible);
void Wait(int ms);
public:
/*
@ -100,7 +93,21 @@ public:
~CSDLInputSystem();
int GetNumKeyboards();
int GetNumMice();
int GetNumJoysticks();
const KeyDetails *GetKeyDetails(int kbdNum);
const MouseDetails *GetMouseDetails(int mseNum);
const JoyDetails *GetJoyDetails(int joyNum);
bool Poll();
void SetMouseVisibility(bool visible);
};
#endif // INCLUDED_SDLINPUTSYSTEM_H

File diff suppressed because it is too large Load diff

View file

@ -2,26 +2,20 @@
#define INCLUDED_DIRECTINPUTSYSTEM_H
#include "Types.h"
#include "Inputs/Input.h"
#include "Inputs/InputSource.h"
#include "Inputs/InputSystem.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <dinput.h>
#include <XInput.h>
#include <vector>
using namespace std;
#define NUM_DI_KEYS (sizeof(s_keyMap) / sizeof(DIKeyMapStruct))
#define MATCHES_USAGE(wUsage, wUsagePage, word) wUsage == LOWORD(word) && wUsagePage == HIWORD(word)
#define X_AXIS_USAGE 0x00010030
#define Y_AXIS_USAGE 0x00010031
#define Z_AXIS_USAGE 0x00010032
#define RX_AXIS_USAGE 0x00010033
#define RY_AXIS_USAGE 0x00010034
#define RZ_AXIS_USAGE 0x00010035
struct DIKeyMapStruct
{
const char *keyName;
@ -47,21 +41,36 @@ struct DIMseState
BYTE buttons[5];
};
struct DIJoyInfo
{
GUID guid;
bool isXInput;
int dInputNum;
int xInputNum;
};
// RawInput API
typedef /*WINUSERAPI*/ INT (WINAPI *GetRawInputDeviceListPtr)(OUT PRAWINPUTDEVICELIST pRawInputDeviceList, IN OUT PUINT puiNumDevices, IN UINT cbSize);
typedef /*WINUSERAPI*/ INT (WINAPI *GetRawInputDeviceInfoPtr)(IN HANDLE hDevice, IN UINT uiCommand, OUT LPVOID pData, IN OUT PUINT pcbSize);
typedef /*WINUSERAPI*/ BOOL (WINAPI *RegisterRawInputDevicesPtr)(IN PCRAWINPUTDEVICE pRawInputDevices, IN UINT uiNumDevices, IN UINT cbSize);
typedef /*WINUSERAPI*/ INT (WINAPI *GetRawInputDataPtr)(IN HRAWINPUT hRawInput, IN UINT uiCommand, OUT LPVOID pData, IN OUT PUINT pcbSize, IN UINT cbSizeHeader);
LRESULT WINAPI CallWndProc(int nCode, WPARAM wParam, LPARAM lParam);
// XInput API
typedef /*WINUSERAPI*/ DWORD (WINAPI *XInputGetCapabilitiesPtr)(IN DWORD dwUserIndex, IN DWORD dwFlags, OUT PXINPUT_CAPABILITIES pCapabilities);
typedef /*WINUSERAPI*/ DWORD (WINAPI *XInputGetStatePtr)(IN DWORD dwUserIndex, OUT PXINPUT_STATE pState);
typedef /*WINUSERAPI*/ DWORD (WINAPI *XInputSetStatePtr)(IN DWORD dwUserIndex, IN PXINPUT_VIBRATION pVibration);
LRESULT WINAPI GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam);
// DirectInput callbacks
static bool IsXInputDevice(const GUID &devProdGUID);
BOOL CALLBACK DI8EnumDevicesCallback(LPCDIDEVICEINSTANCE instance, LPVOID context);
static BOOL CALLBACK DI8EnumDevicesCallback(LPCDIDEVICEINSTANCE instance, LPVOID context);
BOOL CALLBACK DI8EnumAxesCallback(LPDIDEVICEOBJECTINSTANCE instance, LPVOID context);
static BOOL CALLBACK DI8EnumAxesCallback(LPDIDEVICEOBJECTINSTANCE instance, LPVOID context);
static BOOL CALLBACK DI8EnumEffectsCallback(LPCDIEFFECTINFO effectInfo, LPVOID context);
/*
* Input system that uses DirectInput and RawInput APIs.
* Input system that uses combination of DirectInput, XInput and RawInput APIs.
*/
class CDirectInputSystem : public CInputSystem
{
@ -69,33 +78,58 @@ private:
// Lookup table to map key names to DirectInput keycodes and Virtual keycodes
static DIKeyMapStruct s_keyMap[];
static const char *ConstructName(bool useRawInput, bool useXInput, bool enableFFeedback);
bool m_useRawInput;
bool m_useXInput;
bool m_enableFFeedback;
HWND m_hwnd;
DWORD m_screenW;
DWORD m_screenH;
bool m_activated;
// Function pointers for RawInput API
GetRawInputDeviceListPtr m_getRIDevListPtr;
GetRawInputDeviceInfoPtr m_getRIDevInfoPtr;
RegisterRawInputDevicesPtr m_regRIDevsPtr;
GetRawInputDataPtr m_getRIDataPtr;
// Keyboard, mouse and joystick details
vector<KeyDetails> m_keyDetails;
vector<MouseDetails> m_mseDetails;
vector<JoyDetails> m_joyDetails;
// RawInput keyboard and mice handles and states
vector<HANDLE> m_rawKeyboards;
vector<BOOL*> m_rawKeyStates;
vector<HANDLE> m_rawMice;
RawMseState m_combRawMseState;
vector<RawMseState*> m_rawMseStates;
vector<RawMseState> m_rawMseStates;
// Function pointers for XInput API
XInputGetCapabilitiesPtr m_xiGetCapabilitiesPtr;
XInputGetStatePtr m_xiGetStatePtr;
XInputSetStatePtr m_xiSetStatePtr;
// DirectInput pointers and details
LPDIRECTINPUT8 m_di8;
LPDIRECTINPUTDEVICE8 m_di8Keyboard;
LPDIRECTINPUTDEVICE8 m_di8Mouse;
vector<LPDIRECTINPUTDEVICE8> m_di8Joysticks;
vector<JoyDetails*> m_joyDetails;
// DirectInput keyboard and mouse states
BYTE m_diKeyState[256];
DIMseState m_diMseState;
vector<LPDIJOYSTATE2> m_diJoyStates;
// DirectInput joystick infos and states
vector<DIJoyInfo> m_diJoyInfos;
vector<DIJOYSTATE2> m_diJoyStates;
bool GetRegString(HKEY regKey, const char *regPath, string &str);
bool GetRegDeviceName(const char *rawDevName, char *name);
void OpenKeyboardsAndMice();
@ -117,24 +151,18 @@ private:
void CloseJoysticks();
HRESULT CreateJoystickEffect(LPDIRECTINPUTDEVICE8 di8Joystick, int axisNum, LPDIRECTINPUTEFFECT *di8Effect);
protected:
/*
* Initializes the DirectInput input system.
*/
bool InitializeSystem();
int GetNumKeyboards();
int GetNumMice();
int GetNumJoysticks();
int GetKeyIndex(const char *keyName);
const char *GetKeyName(int keyIndex);
JoyDetails *GetJoyDetails(int joyNum);
bool IsKeyPressed(int joyNum, int keyIndex);
int GetMouseAxisValue(int mseNum, int axisNum);
@ -148,6 +176,8 @@ protected:
bool IsJoyPOVInDir(int joyNum, int povNum, int povDir);
bool IsJoyButPressed(int joyNum, int butNum);
bool ProcessForceFeedbackCmd(int joyNum, int axisNum, ForceFeedbackCmd *ffCmd);
void Wait(int ms);
@ -157,20 +187,40 @@ protected:
public:
/*
* Constructs a DirectInput/RawInput input system.
* If useRawInput is true then RawInput is used for keyboard and mice movements (allowing multiple devices). If false
* then DirectInput is used instead (which doesn't allow multiple devices).
* In both cases, DirectInput is used for reading joysticks.
* Constructs a DirectInput/XInput/RawInput input system.
* If useRawInput is true then RawInput is used for keyboard and mice movements (allowing multiple devices, eg for dual lightguns in gun
* games such as Lost World). If false then DirectInput is used instead (which doesn't allow multiple devices). In both cases,
* DirectInput/XInput is used for reading joysticks.
* If useXInput is true then XInput is used for reading XBox 360 game controllers (and/or XInput compatible joysticks) and DirectInput is used
* for all other types of joystick. If false, then DirectInput is used for reading all joysticks (including XBox 360 ones).
* The advantage of using XInput for XBox 360 game controllers is that it allows the left and right triggers to be used simultaneously
* (ie to brake and accelerate at the same time in order to power slide the car in Daytona USA 2). Under DirectInput the triggers get mapped
* to the same shared axis and so cannot be distinguished when pressed together.
* If enableFFeedback is true then force feedback is enabled (for those joysticks which are force feedback capable).
*/
CDirectInputSystem(bool useRawInput);
CDirectInputSystem(bool useRawInput, bool useXInput, bool enableFFeedback);
~CDirectInputSystem();
int GetNumKeyboards();
int GetNumMice();
int GetNumJoysticks();
const KeyDetails *GetKeyDetails(int kbdNum);
const MouseDetails *GetMouseDetails(int mseNum);
const JoyDetails *GetJoyDetails(int joyNum);
bool Poll();
void SetMouseVisibility(bool visible);
void GrabMouse();
void ConfigEnd();
void UngrabMouse();
void SetMouseVisibility(bool visible);
};
#endif // INCLUDED_DIRECTINPUTSYSTEM_H

View file

@ -131,11 +131,17 @@ extern void InfoLog(const char *fmt, ...);
#include "Graphics/Render2D.h"
#include "Graphics/Render3D.h"
#include "Graphics/Shader.h"
#include "CPU/PowerPC/ppc.h"
#include "CPU/PowerPC/PPCDisasm.h"
#include "CPU/PowerPC/ppc.h"
#ifdef SUPERMODEL_SOUND
#include "CPU/68K/Turbo68K.h"
#endif
#endif // SUPERMODEL_SOUND
#include "Inputs/Input.h"
#include "Inputs/Inputs.h"
#include "Inputs/InputSource.h"
#include "Inputs/InputSystem.h"
#include "Inputs/InputTypes.h"
#include "Inputs/MultiInputSource.h"
#include "Model3/Bus.h"
#include "Model3/IRQ.h"
#include "Model3/PCI.h"
@ -148,12 +154,6 @@ extern void InfoLog(const char *fmt, ...);
#include "Sound/SCSP.h"
#include "Model3/SoundBoard.h"
#include "Model3/Model3.h"
#include "Inputs/Input.h"
#include "Inputs/Inputs.h"
#include "Inputs/InputSource.h"
#include "Inputs/InputSystem.h"
#include "Inputs/InputTypes.h"
#include "Inputs/MultiInputSource.h"
/******************************************************************************
Helpful Macros and Inlines