mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2024-11-30 01:25:49 +00:00
e8782b98fa
- Added ability to configure axis min, centre and max values in INI file. This allows some types of steering wheel pedals that use an inverted value range to work properly with the emulator. - Modified CINIFile to read and write signed numbers (needed for above change). - Added check at configuration start for "bad" input sources such as axes that are wrongly calibrated or buttons that are always triggering a value. Otherwise they cause the configuration loop to wait indefinitely for the axis or button to be released. - Removed superfluous check for XInput devices when XInput is not enabled in CDirectInputSystem. - Improved force beedback code in CDirectInputSystem and also added the extra feedback effects needed so far for drive board emulation.
165 lines
4.5 KiB
C++
165 lines
4.5 KiB
C++
#include "Supermodel.h"
|
|
|
|
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)
|
|
{
|
|
ResetToDefaultMapping();
|
|
}
|
|
|
|
CInput::~CInput()
|
|
{
|
|
// Release source, if any
|
|
if (m_source != NULL)
|
|
m_source->Release();
|
|
}
|
|
|
|
void CInput::CreateSource()
|
|
{
|
|
// If already have a source, then release it now
|
|
if (m_source != NULL)
|
|
m_source->Release();
|
|
|
|
// 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;
|
|
else
|
|
{
|
|
// Otherwise, ask system to parse mapping into appropriate input source
|
|
m_source = m_system->ParseSource(m_mapping, !!(flags & INPUT_FLAGS_AXIS));
|
|
|
|
// Check that mapping was parsed okay and if so acquire it
|
|
if (m_source != NULL)
|
|
m_source->Acquire();
|
|
else
|
|
{
|
|
// Otherwise, fall back to default mapping
|
|
if (stricmp(m_mapping, m_defaultMapping) != 0)
|
|
{
|
|
ErrorLog("Unable to map input %s to [%s] - switching to default [%s].\n", id, m_mapping, m_defaultMapping);
|
|
|
|
ResetToDefaultMapping();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CInput::Initialize(CInputSystem *system)
|
|
{
|
|
m_system = system;
|
|
|
|
CreateSource();
|
|
}
|
|
|
|
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";
|
|
case GAME_INPUT_FIGHTING: return "Fighting Game Buttons";
|
|
case GAME_INPUT_SOCCER: return "Virtua Striker Buttons";
|
|
case GAME_INPUT_VEHICLE: return "Racing Game Steering Controls";
|
|
case GAME_INPUT_SHIFT4: return "Racing Game Gear Shift";
|
|
case GAME_INPUT_VR: return "Racing Game VR View Buttons";
|
|
case GAME_INPUT_RALLY: return "Sega Rally Buttons";
|
|
case GAME_INPUT_TWIN_JOYSTICKS: return "Virtua On Controls";
|
|
case GAME_INPUT_ANALOG_JOYSTICK: return "Analog Joystick";
|
|
case GAME_INPUT_GUN1: // Fall through to below
|
|
case GAME_INPUT_GUN2: return "Lightguns";
|
|
default: return "Misc";
|
|
}
|
|
}
|
|
|
|
const char *CInput::GetMapping()
|
|
{
|
|
return m_mapping;
|
|
}
|
|
|
|
void CInput::ClearMapping()
|
|
{
|
|
SetMapping("NONE");
|
|
}
|
|
|
|
void CInput::SetMapping(const char *mapping)
|
|
{
|
|
strncpy(m_mapping, mapping, MAX_MAPPING_LENGTH);
|
|
m_mapping[MAX_MAPPING_LENGTH] = '\0';
|
|
CreateSource();
|
|
}
|
|
|
|
void CInput::AppendMapping(const char *mapping)
|
|
{
|
|
// If mapping is empty or NONE, then simply set mapping
|
|
if (m_mapping[0] == '\0' || stricmp(m_mapping, "NONE") == 0)
|
|
SetMapping(mapping);
|
|
else
|
|
{
|
|
// Otherwise, append to mapping string and recreate source from new mapping string
|
|
int size = MAX_MAPPING_LENGTH - strlen(m_mapping);
|
|
strncat(m_mapping, ",", size--);
|
|
strncat(m_mapping, mapping, size);
|
|
CreateSource();
|
|
}
|
|
}
|
|
|
|
void CInput::ResetToDefaultMapping()
|
|
{
|
|
SetMapping(m_defaultMapping);
|
|
}
|
|
|
|
void CInput::ReadFromINIFile(CINIFile *ini, const char *section)
|
|
{
|
|
// See if input is configurable
|
|
if (IsConfigurable())
|
|
{
|
|
// If so, check INI file for mapping string
|
|
string key("Input");
|
|
key.append(id);
|
|
string mapping;
|
|
if (ini->Get(section, key, mapping) == OKAY)
|
|
{
|
|
// If found, then set mapping string
|
|
SetMapping(mapping.c_str());
|
|
return;
|
|
}
|
|
}
|
|
|
|
// If input has not been configured, then force recreation of source anyway since input system settings may have changed
|
|
CreateSource();
|
|
}
|
|
|
|
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];
|
|
if (!m_system->ReadMapping(mapping, MAX_MAPPING_LENGTH, !!(flags & INPUT_FLAGS_AXIS), READ_ALL, escapeMapping))
|
|
return false;
|
|
if (append)
|
|
AppendMapping(mapping);
|
|
else
|
|
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);
|
|
} |