mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2025-02-16 17:35:39 +00:00
Changes to input system:
- Joystick axis saturation values can now range from 1-200 rather than just 1-100. This lets the user make axis less sensitive, if required. - Added joystick axes calibration menus to -config-inputs. - Moved DirectInput & XInput feedback settings out of CDirectInputSystem and into COSDConfig (so that they can be configured per-game). - DirectInput mode now only grabs background access to keyboard, mice and joystick when configuring inputs, otherwise it only grabs foreground access. Other changes: - Main.cpp now ensures all Model3 threads are paused before shutting down.
This commit is contained in:
parent
f0697dbc84
commit
b9430cd988
|
@ -169,6 +169,12 @@ void CInput::WriteToINIFile(CINIFile *ini, const char *section)
|
|||
ini->Set(section, key, m_mapping);
|
||||
}
|
||||
|
||||
void CInput::InputSystemChanged()
|
||||
{
|
||||
// If input system or its settings have changed, then force recreation of source
|
||||
CreateSource();
|
||||
}
|
||||
|
||||
bool CInput::Configure(bool append, const char *escapeMapping)
|
||||
{
|
||||
char mapping[MAX_MAPPING_LENGTH];
|
||||
|
|
|
@ -161,6 +161,8 @@ public:
|
|||
*/
|
||||
virtual void WriteToINIFile(CINIFile *ini, const char *section);
|
||||
|
||||
void InputSystemChanged();
|
||||
|
||||
/*
|
||||
* Returns true if the input is a UI input.
|
||||
*/
|
||||
|
|
|
@ -24,9 +24,17 @@
|
|||
*
|
||||
* Implementation of CInputSystem, the base input system class.
|
||||
*/
|
||||
|
||||
|
||||
// TODO
|
||||
// - switch to using more C++ strings
|
||||
// - simplify handling of configuration settings because it is a mess
|
||||
// - think more about where config, calibrate and debug methods should go - OSD classes, CInputs or here?
|
||||
// - open up API to allow direct access to keyboard, mouse and joystick values
|
||||
// - add GetKey method that is easier to use than reading keyboard with ReadMapping
|
||||
|
||||
#include "Supermodel.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
@ -377,6 +385,11 @@ JoyPartsStruct CInputSystem::s_joyParts[] =
|
|||
|
||||
const char *CInputSystem::s_axisNames[] = { "X", "Y", "Z", "RX", "RY", "RZ" };
|
||||
|
||||
const char *CInputSystem::GetDefaultAxisName(int axisNum)
|
||||
{
|
||||
return (axisNum >= 0 && axisNum < 6 ? s_axisNames[axisNum] : "");
|
||||
}
|
||||
|
||||
CInputSystem::CInputSystem(const char *systemName) :
|
||||
name(systemName), m_dispX(0), m_dispY(0), m_dispW(0), m_dispH(0), m_grabMouse(false)
|
||||
{
|
||||
|
@ -1523,6 +1536,8 @@ bool CInputSystem::Initialize()
|
|||
|
||||
// Create cache to hold input sources
|
||||
CreateSourceCache();
|
||||
|
||||
GrabMouse();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1663,20 +1678,22 @@ bool CInputSystem::ReadMapping(char *buffer, unsigned bufSize, bool fullAxisOnly
|
|||
{
|
||||
// Map given escape mapping to an input source
|
||||
CInputSource *escape = ParseSource(escapeMapping);
|
||||
escape->Acquire();
|
||||
if (escape)
|
||||
escape->Acquire();
|
||||
|
||||
string badMapping;
|
||||
string mapping;
|
||||
vector<CInputSource*> badSources;
|
||||
vector<CInputSource*> sources;
|
||||
bool mseCentered = false;
|
||||
|
||||
bool cancelled = false;
|
||||
|
||||
// See which sources activated to begin with and from here on ignore these (this stops badly calibrated axes that are constantly "active"
|
||||
// from preventing the user from exiting read loop)
|
||||
if (!Poll())
|
||||
{
|
||||
escape->Release();
|
||||
return false;
|
||||
cancelled = true;
|
||||
goto Finish;
|
||||
}
|
||||
|
||||
CheckAllSources(readFlags, fullAxisOnly, mseCentered, badSources, badMapping, sources);
|
||||
|
@ -1687,25 +1704,25 @@ bool CInputSystem::ReadMapping(char *buffer, unsigned bufSize, bool fullAxisOnly
|
|||
// Poll inputs
|
||||
if (!Poll())
|
||||
{
|
||||
escape->Release();
|
||||
return false;
|
||||
cancelled = true;
|
||||
goto Finish;
|
||||
}
|
||||
|
||||
// Check if escape source was triggered
|
||||
if (escape != NULL && escape->IsActive())
|
||||
if (escape && escape->IsActive())
|
||||
{
|
||||
// If so, wait until source no longer active and then exit
|
||||
while (escape->IsActive())
|
||||
{
|
||||
if (!Poll())
|
||||
{
|
||||
escape->Release();
|
||||
return false;
|
||||
cancelled = true;
|
||||
goto Finish;
|
||||
}
|
||||
Wait(1000/60);
|
||||
}
|
||||
escape->Release();
|
||||
return false;
|
||||
cancelled = true;
|
||||
goto Finish;
|
||||
}
|
||||
|
||||
// Check all active sources
|
||||
|
@ -1745,8 +1762,10 @@ bool CInputSystem::ReadMapping(char *buffer, unsigned bufSize, bool fullAxisOnly
|
|||
strncpy(buffer, mapping.c_str(), bufSize - 1);
|
||||
buffer[bufSize - 1] = '\0';
|
||||
|
||||
escape->Release();
|
||||
return true;
|
||||
Finish:
|
||||
if (escape)
|
||||
escape->Release();
|
||||
return !cancelled;
|
||||
}
|
||||
|
||||
void CInputSystem::GrabMouse()
|
||||
|
@ -1770,6 +1789,233 @@ bool CInputSystem::SendForceFeedbackCmd(int joyNum, int axisNum, ForceFeedbackCm
|
|||
return ProcessForceFeedbackCmd(joyNum, axisNum, ffCmd);
|
||||
}
|
||||
|
||||
bool CInputSystem::CalibrateJoystickAxis(unsigned joyNum, unsigned axisNum, const char *escapeMapping, const char *confirmMapping)
|
||||
{
|
||||
const JoyDetails *joyDetails = GetJoyDetails(joyNum);
|
||||
if (joyDetails == NULL || axisNum >= NUM_JOY_AXES || !joyDetails->hasAxis[axisNum])
|
||||
{
|
||||
printf("No such axis or joystick");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Map given escape mapping to input source
|
||||
CInputSource *escape = ParseSource(escapeMapping);
|
||||
CInputSource *output = ParseSource("KEY_SHIFT");
|
||||
if (escape)
|
||||
escape->Acquire();
|
||||
if (output)
|
||||
output->Acquire();
|
||||
|
||||
Repeat:
|
||||
printf("Calibrating %s of joystick '%s'.\n\n", joyDetails->axisName[axisNum], joyDetails->name);
|
||||
|
||||
int posVal;
|
||||
int negVal;
|
||||
int offVal;
|
||||
unsigned posRange;
|
||||
unsigned negRange;
|
||||
unsigned posOffRange;
|
||||
unsigned negOffRange;
|
||||
char mapping[50];
|
||||
bool cancelled = false;
|
||||
for (unsigned step = 0; step < 3; step++)
|
||||
{
|
||||
switch (step)
|
||||
{
|
||||
case 0:
|
||||
puts("Step 1:");
|
||||
puts(" Move axis now to its furthest positive/'on' position and hold, ie:");
|
||||
if (axisNum == AXIS_X || axisNum == AXIS_RX || axisNum == AXIS_Z || axisNum == AXIS_RZ)
|
||||
puts(" - for a joystick X-Axis, push it all the way to the right.");
|
||||
if (axisNum == AXIS_Y || axisNum == AXIS_RY || axisNum == AXIS_Z || axisNum == AXIS_RZ)
|
||||
puts(" - for a joystick Y-Axis, push it all the way downwards.");
|
||||
puts(" - for a steering wheel, turn it all the way to the right.");
|
||||
puts(" - for a pedal, press it all the way to the floor.");
|
||||
break;
|
||||
case 1:
|
||||
puts("Step 2:");
|
||||
puts(" Move axis the other way to its furthest negative position and hold, ie:");
|
||||
if (axisNum == AXIS_X || axisNum == AXIS_RX || axisNum == AXIS_Z || axisNum == AXIS_RZ)
|
||||
puts(" - for a joystick X-Axis, push it all the way to the left.");
|
||||
if (axisNum == AXIS_Y || axisNum == AXIS_RY || axisNum == AXIS_Z || axisNum == AXIS_RZ)
|
||||
puts(" - for a joystick Y-Axis, push it all the way updwards.");
|
||||
puts(" - for a steering wheel, turn it all the way to the left.");
|
||||
puts(" - for a pedal, let go of the pedal completely. If there is another pedal");
|
||||
puts(" that shares the same axis then press that one all the way to the floor.");
|
||||
break;
|
||||
case 2:
|
||||
puts("Step 3:");
|
||||
puts(" Return axis to its center/'off' position and hold, ie:");
|
||||
puts(" - for a joystick axis, let it return to the middle.");
|
||||
puts(" - for a steering weel, turn it back to its central position.");
|
||||
puts(" - for a pedal, let go of all pedals completely.");
|
||||
break;
|
||||
}
|
||||
printf("\nPress Return when ready (or press Esc to cancel): ");
|
||||
|
||||
// Loop until user confirms or aborts
|
||||
for (;;)
|
||||
{
|
||||
if (!ReadMapping(mapping, 50, false, READ_KEYBOARD|READ_MERGE, escapeMapping))
|
||||
{
|
||||
cancelled = true;
|
||||
goto Finish;
|
||||
}
|
||||
if (stricmp(mapping, confirmMapping) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
printf("Calibrating... ");
|
||||
|
||||
// Loop until at least three seconds have elapsed or user aborts
|
||||
int joyVal = GetJoyAxisValue(joyNum, axisNum);
|
||||
int minVal = joyVal;
|
||||
int maxVal = joyVal;
|
||||
bool firstOut = true;
|
||||
for (unsigned frames = 0; frames < 3 * 60; frames++)
|
||||
{
|
||||
if (!Poll())
|
||||
{
|
||||
cancelled = true;
|
||||
goto Finish;
|
||||
}
|
||||
|
||||
// Check if escape source was triggered
|
||||
if (escape && escape->IsActive())
|
||||
{
|
||||
// If so, wait until source no longer active and then exit
|
||||
while (escape->IsActive())
|
||||
{
|
||||
if (!Poll())
|
||||
{
|
||||
cancelled = true;
|
||||
goto Finish;
|
||||
}
|
||||
Wait(1000/60);
|
||||
}
|
||||
cancelled = true;
|
||||
goto Finish;
|
||||
}
|
||||
|
||||
joyVal = GetJoyAxisValue(joyNum, axisNum);
|
||||
minVal = min<int>(minVal, joyVal);
|
||||
maxVal = max<int>(maxVal, joyVal);
|
||||
|
||||
// Check if output source is triggered, and if so output value for debugging
|
||||
if (output != NULL && output->IsActive())
|
||||
{
|
||||
if (firstOut)
|
||||
puts("");
|
||||
printf(" [value: %d, min: %d, %max: %d]\n", joyVal, minVal, maxVal);
|
||||
firstOut = false;
|
||||
}
|
||||
|
||||
// Don't poll continuously
|
||||
Wait(1000/60);
|
||||
}
|
||||
|
||||
printf("Done\n\n");
|
||||
|
||||
switch (step)
|
||||
{
|
||||
case 0: posVal = (abs(maxVal) >= abs(minVal) ? maxVal : minVal); break;
|
||||
case 1: negVal = (abs(minVal) >= abs(maxVal) ? minVal : maxVal); break;
|
||||
case 2:
|
||||
if (minVal <= 0 && maxVal >= 0)
|
||||
offVal = 0;
|
||||
else if (minVal == DEFAULT_JOY_AXISMINVAL)
|
||||
offVal = DEFAULT_JOY_AXISMINVAL;
|
||||
else if (maxVal == DEFAULT_JOY_AXISMAXVAL)
|
||||
offVal = DEFAULT_JOY_AXISMAXVAL;
|
||||
else
|
||||
offVal = (minVal + maxVal) / 2;
|
||||
posRange = abs(posVal - offVal);
|
||||
negRange = abs(negVal - offVal);
|
||||
posOffRange = (unsigned)(posVal > offVal ? maxVal - offVal : offVal - minVal);
|
||||
negOffRange = (unsigned)(posVal > offVal ? offVal - minVal : maxVal - offVal);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned totalRange = posRange + negRange;
|
||||
|
||||
unsigned posDeadZone = (unsigned)ceil(100.0 * (double)posOffRange / (double)posRange);
|
||||
unsigned negDeadZone = (unsigned)ceil(100.0 * (double)negOffRange / (double)negRange);
|
||||
unsigned deadZone = max<unsigned>(1, max<unsigned>(negDeadZone, posDeadZone));
|
||||
|
||||
bool okay;
|
||||
if (posVal > negVal)
|
||||
okay = negVal <= offVal && offVal <= posVal && totalRange > 3000 && deadZone < 90;
|
||||
else
|
||||
okay = posVal <= offVal && offVal <= negVal && totalRange > 3000 && deadZone < 90;
|
||||
if (okay)
|
||||
{
|
||||
JoySettings *commonSettings = GetJoySettings(ANY_JOYSTICK, true);
|
||||
JoySettings *joySettings = GetJoySettings(joyNum, false);
|
||||
if (joySettings == NULL)
|
||||
{
|
||||
joySettings = new JoySettings(*commonSettings);
|
||||
m_joySettings.push_back(joySettings);
|
||||
joySettings->joyNum = joyNum;
|
||||
}
|
||||
|
||||
printf("Calibrated Axis Settings:\n\n");
|
||||
printf(" Min Value = %d\n", negVal);
|
||||
printf(" Center/Off Value = %d\n", offVal);
|
||||
printf(" Max Value = %d\n", posVal);
|
||||
printf(" Dead Zone = %d %%\n", deadZone);
|
||||
printf("\nAccept these settings: y/n? ");
|
||||
|
||||
// Loop until user confirms or declines
|
||||
while (ReadMapping(mapping, 50, false, READ_KEYBOARD|READ_MERGE, escapeMapping))
|
||||
{
|
||||
if (stricmp(mapping, "KEY_N") == 0)
|
||||
break;
|
||||
else if (stricmp(mapping, "KEY_Y") == 0)
|
||||
{
|
||||
joySettings->axisMinVals[axisNum] = negVal;
|
||||
joySettings->axisMaxVals[axisNum] = posVal;
|
||||
joySettings->axisOffVals[axisNum] = offVal;
|
||||
joySettings->deadZones[axisNum] = deadZone;
|
||||
|
||||
ClearSourceCache();
|
||||
|
||||
puts("Accepted");
|
||||
goto Finish;
|
||||
}
|
||||
}
|
||||
cancelled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
puts("There was a problem calibrating the axis. This may be because the steps");
|
||||
puts("were not followed correctly or the joystick is sending invalid data.");
|
||||
printf("\nTry calibrating again: y/n? ");
|
||||
|
||||
// Loop until user confirms or declines
|
||||
while (ReadMapping(mapping, 50, false, READ_KEYBOARD|READ_MERGE, escapeMapping))
|
||||
{
|
||||
if (stricmp(mapping, "KEY_N") == 0)
|
||||
break;
|
||||
else if (stricmp(mapping, "KEY_Y") == 0)
|
||||
{
|
||||
puts("[Cancelled]");
|
||||
goto Repeat;
|
||||
}
|
||||
}
|
||||
cancelled = true;
|
||||
}
|
||||
|
||||
Finish:
|
||||
if (cancelled)
|
||||
puts("[Cancelled]");
|
||||
if (escape)
|
||||
escape->Release();
|
||||
if (output)
|
||||
output->Release();
|
||||
return !cancelled;
|
||||
}
|
||||
|
||||
void CInputSystem::PrintDevices()
|
||||
{
|
||||
puts("Keyboards:");
|
||||
|
@ -1974,9 +2220,9 @@ CInputSystem::CJoyAxisInputSource::CJoyAxisInputSource(CInputSystem *system, int
|
|||
{
|
||||
m_axisInverted = m_axisMaxVal < m_axisMinVal;
|
||||
// Calculate pos/neg deadzone and saturation points (joystick raw values range from axisMinVal to axisMasVal (centered/off at axisOffVal),
|
||||
// deadzone given as percentage 0-99 and saturation given as percentage 1-100)
|
||||
// deadzone given as percentage 0-99 and saturation given as percentage 1 - 200)
|
||||
double dDeadZone = (double)Clamp((int)deadZone, 0, 99) / 100.0;
|
||||
double dSaturation = (double)Clamp((int)saturation, (int)deadZone + 1, 100) / 100.0;
|
||||
double dSaturation = (double)Clamp((int)saturation, (int)deadZone + 1, 200) / 100.0;
|
||||
m_posDZone = m_axisOffVal + (int)(dDeadZone * (m_axisMaxVal - m_axisOffVal));
|
||||
m_negDZone = m_axisOffVal + (int)(dDeadZone * (m_axisMinVal - m_axisOffVal));
|
||||
m_posSat = m_axisOffVal + (int)(dSaturation * (m_axisMaxVal - m_axisOffVal));
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
#ifndef INCLUDED_INPUTSYSTEM_H
|
||||
#define INCLUDED_INPUTSYSTEM_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
using namespace std;
|
||||
|
@ -264,7 +264,7 @@ struct JoySettings
|
|||
int axisOffVals[NUM_JOY_AXES]; // Axis center/off value (default 0)
|
||||
int axisMaxVals[NUM_JOY_AXES]; // Axis max raw value (default 32767)
|
||||
unsigned deadZones[NUM_JOY_AXES]; // Axis dead zone as a percentage 0-99 of axis positive/negative ranges
|
||||
unsigned saturations[NUM_JOY_AXES]; // Axis saturation as a percentage 1-100 of axis positive/negative ranges
|
||||
unsigned saturations[NUM_JOY_AXES]; // Axis saturation as a percentage 1-200 of axis positive/negative ranges
|
||||
|
||||
/*
|
||||
* Creates a JoySettings with default settings
|
||||
|
@ -296,13 +296,14 @@ struct MouseDetails
|
|||
|
||||
struct JoyDetails
|
||||
{
|
||||
char name[MAX_NAME_LENGTH + 1]; // 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
|
||||
char name[MAX_NAME_LENGTH + 1]; // 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
|
||||
char axisName[NUM_JOY_AXES][MAX_NAME_LENGTH + 1]; // Axis names (if available)
|
||||
bool axisHasFF[NUM_JOY_AXES]; // Flags to indicate which axes are force feedback enabled
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -722,6 +723,7 @@ public:
|
|||
static unsigned totalSrcsAcquired;
|
||||
static unsigned totalSrcsReleased;
|
||||
#endif
|
||||
static const char *GetDefaultAxisName(int axisNum);
|
||||
|
||||
// Name of this input system
|
||||
const char *name;
|
||||
|
@ -841,6 +843,8 @@ public:
|
|||
|
||||
virtual bool SendForceFeedbackCmd(int joyNum, int axisNum, ForceFeedbackCmd ffCmd);
|
||||
|
||||
bool CalibrateJoystickAxis(unsigned joyNum, unsigned axisNum, const char *escapeMapping = "KEY_ESCAPE", const char *confirmMapping = "KEY_RETURN");
|
||||
|
||||
void PrintDevices();
|
||||
|
||||
//
|
||||
|
|
|
@ -265,6 +265,7 @@ 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(" b Calibrate joystick axes,");
|
||||
puts(" i Display information about input system and attached devices,");
|
||||
puts(" h Display this help again,");
|
||||
puts(" q Finish and save all changes,");
|
||||
|
@ -374,6 +375,8 @@ bool CInputs::ConfigureInputs(const GameInfo *game)
|
|||
|
||||
const char *groupLabel = NULL;
|
||||
|
||||
bool cancelled = false;
|
||||
|
||||
// Loop through all the inputs to be configured
|
||||
index = 0;
|
||||
while (index < toConfigure.size())
|
||||
|
@ -392,9 +395,9 @@ bool CInputs::ConfigureInputs(const GameInfo *game)
|
|||
Redisplay:
|
||||
// Print the input label, current input mapping and available options
|
||||
if (index > 0)
|
||||
printf(" %s [%s]: Ret/c/s/a/r/Up/Down/h/q/Esc? ", input->label, input->GetMapping());
|
||||
printf(" %s [%s]: Ret/c/s/a/r/Up/Down/b/h/q/Esc? ", input->label, input->GetMapping());
|
||||
else
|
||||
printf(" %s [%s]: Ret/c/s/a/r/Down/h/q/Esc? ", input->label, input->GetMapping());
|
||||
printf(" %s [%s]: Ret/c/s/a/r/Down/h/b/q/Esc? ", input->label, input->GetMapping());
|
||||
fflush(stdout); // required on terminals that use buffering
|
||||
|
||||
// Loop until user has selected a valid option
|
||||
|
@ -412,27 +415,26 @@ Redisplay:
|
|||
(*it)->SetMapping(oldMappings[index].c_str());
|
||||
index++;
|
||||
}
|
||||
puts("");
|
||||
|
||||
m_system->GrabMouse();
|
||||
return false;
|
||||
cancelled = true;
|
||||
goto Finish;
|
||||
}
|
||||
|
||||
if (stricmp(mapping, "KEY_RETURN") == 0 || stricmp(mapping, "KEY_S") == 0)
|
||||
{
|
||||
// Set the input mapping
|
||||
printf("Setting...");
|
||||
printf("Setting... ");
|
||||
fflush(stdout); // required on terminals that use buffering
|
||||
if (input->Configure(false, uiExit->GetMapping()))
|
||||
{
|
||||
printf(" %s\n", input->GetMapping());
|
||||
puts(input->GetMapping());
|
||||
if (stricmp(mapping, "KEY_RETURN") == 0)
|
||||
index++;
|
||||
done = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf(" [Cancelled]\n");
|
||||
puts("[Cancelled]");
|
||||
goto Redisplay;
|
||||
}
|
||||
}
|
||||
|
@ -442,23 +444,23 @@ Redisplay:
|
|||
printf("Appending...");
|
||||
fflush(stdout); // required on terminals that use buffering
|
||||
if (input->Configure(true, uiExit->GetMapping()))
|
||||
printf(" %s\n", input->GetMapping());
|
||||
puts(input->GetMapping());
|
||||
else
|
||||
printf(" [Cancelled]\n");
|
||||
puts("[Cancelled]");
|
||||
goto Redisplay;
|
||||
}
|
||||
else if (stricmp(mapping, "KEY_C") == 0)
|
||||
{
|
||||
// Clear the input mapping(s)
|
||||
input->SetMapping("NONE");
|
||||
printf("Cleared\n");
|
||||
puts("Cleared");
|
||||
goto Redisplay;
|
||||
}
|
||||
else if (stricmp(mapping, "KEY_R") == 0)
|
||||
{
|
||||
// Reset the input mapping(s) to the default
|
||||
input->ResetToDefaultMapping();
|
||||
printf("Reset\n");
|
||||
puts("Reset");
|
||||
goto Redisplay;
|
||||
}
|
||||
else if (stricmp(mapping, "KEY_DOWN") == 0)
|
||||
|
@ -485,6 +487,14 @@ Redisplay:
|
|||
index = 0;
|
||||
done = true;
|
||||
}
|
||||
else if (stricmp(mapping, "KEY_B") == 0)
|
||||
{
|
||||
// Calibrate joysticks
|
||||
printf("\n\n");
|
||||
CalibrateJoysticks();
|
||||
puts("");
|
||||
goto Redisplay;
|
||||
}
|
||||
else if (stricmp(mapping, "KEY_I") == 0)
|
||||
{
|
||||
// Print info about input system
|
||||
|
@ -500,21 +510,15 @@ Redisplay:
|
|||
goto Redisplay;
|
||||
}
|
||||
else if (stricmp(mapping, "KEY_Q") == 0)
|
||||
{
|
||||
// Finish configuration
|
||||
puts("");
|
||||
|
||||
m_system->GrabMouse();
|
||||
return true;
|
||||
}
|
||||
goto Finish;
|
||||
}
|
||||
}
|
||||
|
||||
// All inputs set, finish configuration
|
||||
puts("");
|
||||
Finish:
|
||||
printf("\n\n");
|
||||
|
||||
m_system->GrabMouse();
|
||||
return true;
|
||||
return !cancelled;
|
||||
}
|
||||
|
||||
bool CInputs::ConfigureInputs(const GameInfo *game, unsigned dispX, unsigned dispY, unsigned dispW, unsigned dispH)
|
||||
|
@ -525,6 +529,85 @@ bool CInputs::ConfigureInputs(const GameInfo *game, unsigned dispX, unsigned dis
|
|||
return ConfigureInputs(game);
|
||||
}
|
||||
|
||||
void CInputs::CalibrateJoysticks()
|
||||
{
|
||||
unsigned numJoys = m_system->GetNumJoysticks();
|
||||
if (numJoys == 0 || numJoys == ANY_JOYSTICK)
|
||||
puts("No joysticks attached to calibrate!");
|
||||
else
|
||||
{
|
||||
puts("Choose joystick to calibrate (or press Esc to cancel):");
|
||||
if (numJoys > 10)
|
||||
numJoys = 10;
|
||||
for (int joyNum = 0; joyNum < numJoys; joyNum++)
|
||||
{
|
||||
const JoyDetails *joyDetails = m_system->GetJoyDetails(joyNum);
|
||||
unsigned dispNum = (joyNum == 9 ? 0 : joyNum + 1);
|
||||
printf(" %u: %s\n", dispNum, joyDetails->name);
|
||||
}
|
||||
|
||||
char mapping[50];
|
||||
while (m_system->ReadMapping(mapping, 50, false, READ_KEYBOARD|READ_MERGE, uiExit->GetMapping()))
|
||||
{
|
||||
if (strlen(mapping) != 5 || strncmp(mapping, "KEY_", 4) != 0)
|
||||
continue;
|
||||
char c = mapping[4];
|
||||
if (!isdigit(c))
|
||||
continue;
|
||||
unsigned joyNum = c - '0';
|
||||
joyNum = (joyNum == 0 ? 9 : joyNum - 1);
|
||||
if (joyNum >= numJoys)
|
||||
continue;
|
||||
puts("");
|
||||
CalibrateJoystick(joyNum);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CInputs::CalibrateJoystick(int joyNum)
|
||||
{
|
||||
const JoyDetails *joyDetails = m_system->GetJoyDetails(joyNum);
|
||||
if (joyDetails == NULL || joyDetails->numAxes == 0)
|
||||
{
|
||||
printf("No axes available to calibrate on joystick!");
|
||||
return;
|
||||
}
|
||||
|
||||
printf("Calibrating joystick '%s'.\n\n", joyDetails->name);
|
||||
|
||||
puts("Choose axis to calibrate (or press Esc to cancel):");
|
||||
vector<unsigned> axisNumList;
|
||||
for (unsigned axisNum = 0; axisNum < NUM_JOY_AXES; axisNum++)
|
||||
{
|
||||
if (!joyDetails->hasAxis[axisNum])
|
||||
continue;
|
||||
axisNumList.push_back(axisNum);
|
||||
printf(" %u: %s\n", axisNumList.size(), joyDetails->axisName[axisNum]);
|
||||
}
|
||||
|
||||
char mapping[50];
|
||||
while (m_system->ReadMapping(mapping, 50, false, READ_KEYBOARD|READ_MERGE, uiExit->GetMapping()))
|
||||
{
|
||||
if (strlen(mapping) != 5 || strncmp(mapping, "KEY_", 4) != 0)
|
||||
continue;
|
||||
char c = mapping[4];
|
||||
if (!isdigit(c))
|
||||
continue;
|
||||
unsigned optNum = c - '0';
|
||||
if (optNum == 0 || optNum > axisNumList.size())
|
||||
continue;
|
||||
unsigned axisNum = axisNumList[optNum - 1];
|
||||
puts("");
|
||||
if (m_system->CalibrateJoystickAxis(joyNum, axisNum))
|
||||
{
|
||||
for (vector<CInput*>::iterator it = m_inputs.begin(); it != m_inputs.end(); it++)
|
||||
(*it)->InputSystemChanged();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void CInputs::PrintInputs(const GameInfo *game)
|
||||
{
|
||||
// Print header
|
||||
|
|
|
@ -246,6 +246,10 @@ public:
|
|||
*/
|
||||
bool ConfigureInputs(const GameInfo *game, unsigned dispX, unsigned dispY, unsigned dispW, unsigned dispH);
|
||||
|
||||
void CalibrateJoysticks();
|
||||
|
||||
void CalibrateJoystick(int joyNum);
|
||||
|
||||
/*
|
||||
* Prints to stdout the current input mapping assignments for the given game, or all inputs if game is NULL.
|
||||
*/
|
||||
|
|
|
@ -409,6 +409,20 @@ static void ApplySettings(CINIFile *INI, const char *section)
|
|||
g_Config.showFPS = x ? true : false;
|
||||
if (OKAY == INI->Get(section, "FlipStereo", x))
|
||||
g_Config.flipStereo = x ? true : false;
|
||||
|
||||
#ifdef SUPERMODEL_WIN32
|
||||
// DirectInput ForceFeedback
|
||||
INI->Get(section, "DirectInputEffectsGain", g_Config.dInputEffectsGain);
|
||||
INI->Get(section, "DirectInputConstForceMax", g_Config.dInputConstForceMax);
|
||||
INI->Get(section, "DirectInputSelfCenterMax", g_Config.dInputSelfCenterMax);
|
||||
INI->Get(section, "DirectInputFrictionMax", g_Config.dInputFrictionMax);
|
||||
INI->Get(section, "DirectInputVibrateMax", g_Config.dInputVibrateMax);
|
||||
|
||||
// XInput ForceFeedback
|
||||
INI->Get(section, "XInputConstForceThreshold", g_Config.xInputConstForceThreshold);
|
||||
INI->Get(section, "XInputConstForceMax", g_Config.xInputConstForceMax);
|
||||
INI->Get(section, "XInputVibrateMax", g_Config.xInputVibrateMax);
|
||||
#endif // SUPERMODEL_WIN32
|
||||
}
|
||||
|
||||
// Read settings (from a specific section) from the config file
|
||||
|
@ -429,36 +443,50 @@ static void LogConfig(void)
|
|||
InfoLog("Program settings:");
|
||||
|
||||
// COSDConfig
|
||||
InfoLog("\tXResolution = %d", g_Config.xRes);
|
||||
InfoLog("\tYResolution = %d", g_Config.yRes);
|
||||
InfoLog("\tFullScreen = %d", g_Config.fullScreen);
|
||||
InfoLog("\tThrottle = %d", g_Config.throttle);
|
||||
InfoLog("\tShowFrameRate = %d", g_Config.showFPS);
|
||||
InfoLog("\tXResolution = %d", g_Config.xRes);
|
||||
InfoLog("\tYResolution = %d", g_Config.yRes);
|
||||
InfoLog("\tFullScreen = %d", g_Config.fullScreen);
|
||||
InfoLog("\tThrottle = %d", g_Config.throttle);
|
||||
InfoLog("\tShowFrameRate = %d", g_Config.showFPS);
|
||||
#ifdef SUPERMODEL_DEBUGGER
|
||||
InfoLog("\tDisableDebugger = %d", g_Config.disableDebugger);
|
||||
InfoLog("\tDisableDebugger = %d", g_Config.disableDebugger);
|
||||
#endif
|
||||
InfoLog("\tInputSystem = %s", g_Config.GetInputSystem());
|
||||
InfoLog("\tFlipStereo = %d", g_Config.flipStereo);
|
||||
InfoLog("\tInputSystem = %s", g_Config.GetInputSystem());
|
||||
InfoLog("\tFlipStereo = %d", g_Config.flipStereo);
|
||||
|
||||
#ifdef SUPERMODEL_WIN32
|
||||
// DirectInput ForceFeedback
|
||||
InfoLog("\tDirectInputEffectsGain = %u", g_Config.dInputEffectsGain);
|
||||
InfoLog("\tDirectInputConstForceMax = %u", g_Config.dInputConstForceMax);
|
||||
InfoLog("\tDirectInputSelfCenterMax = %u", g_Config.dInputSelfCenterMax);
|
||||
InfoLog("\tDirectInputFrictionMax = %u", g_Config.dInputFrictionMax);
|
||||
InfoLog("\tDirectInputVibrateMax = %u", g_Config.dInputVibrateMax);
|
||||
|
||||
// XInput ForceFeedback
|
||||
InfoLog("\tXInputConstForceThreshold = %u", g_Config.xInputConstForceThreshold);
|
||||
InfoLog("\tXInputConstForceMax = %u", g_Config.xInputConstForceMax);
|
||||
InfoLog("\tXInputVibrateMax = %u", g_Config.xInputVibrateMax);
|
||||
#endif // SUPERMODEL_WIN32
|
||||
|
||||
// CModel3Config
|
||||
InfoLog("\tMultiThreaded = %d", g_Config.multiThreaded);
|
||||
InfoLog("\tPowerPCFrequency = %d", g_Config.GetPowerPCFrequency());
|
||||
InfoLog("\tMultiThreaded = %d", g_Config.multiThreaded);
|
||||
InfoLog("\tPowerPCFrequency = %d", g_Config.GetPowerPCFrequency());
|
||||
|
||||
// CSoundBoardConfig
|
||||
InfoLog("\tEmulateSound = %d", g_Config.emulateSound);
|
||||
InfoLog("\tEmulateSound = %d", g_Config.emulateSound);
|
||||
|
||||
// CDSBConfig
|
||||
InfoLog("\tEmulateDSB = %d", g_Config.emulateDSB);
|
||||
InfoLog("\tSoundVolume = %d", g_Config.GetSoundVolume());
|
||||
InfoLog("\tMusicVolume = %d", g_Config.GetMusicVolume());
|
||||
InfoLog("\tEmulateDSB = %d", g_Config.emulateDSB);
|
||||
InfoLog("\tSoundVolume = %d", g_Config.GetSoundVolume());
|
||||
InfoLog("\tMusicVolume = %d", g_Config.GetMusicVolume());
|
||||
|
||||
// CDriveBoardConfig
|
||||
InfoLog("\tForceFeedback = %d", g_Config.forceFeedback);
|
||||
InfoLog("\tForceFeedback = %d", g_Config.forceFeedback);
|
||||
|
||||
// CRender3DConfig
|
||||
InfoLog("\tVertexShader = %s", g_Config.vertexShaderFile.c_str());
|
||||
InfoLog("\tFragmentShader = %s", g_Config.fragmentShaderFile.c_str());
|
||||
|
||||
InfoLog("\tVertexShader = %s", g_Config.vertexShaderFile.c_str());
|
||||
InfoLog("\tFragmentShader = %s", g_Config.fragmentShaderFile.c_str());
|
||||
|
||||
InfoLog("");
|
||||
}
|
||||
|
||||
|
@ -1030,6 +1058,9 @@ int Supermodel(const char *zipFile, CInputs *Inputs, CINIFile *CmdLine)
|
|||
}
|
||||
}
|
||||
|
||||
// Make sure all threads are paused before shutting down
|
||||
Model3->PauseThreads();
|
||||
|
||||
#ifdef SUPERMODEL_DEBUGGER
|
||||
// If debugger was supplied, detach it from system and restore old logger
|
||||
if (Debugger != NULL)
|
||||
|
@ -1461,11 +1492,11 @@ int main(int argc, char **argv)
|
|||
InputSystem = new CSDLInputSystem();
|
||||
#ifdef SUPERMODEL_WIN32
|
||||
else if (stricmp(g_Config.GetInputSystem(), "dinput") == 0)
|
||||
InputSystem = new CDirectInputSystem(false, false, true);
|
||||
InputSystem = new CDirectInputSystem(false, false);
|
||||
else if (stricmp(g_Config.GetInputSystem(), "xinput") == 0)
|
||||
InputSystem = new CDirectInputSystem(false, true, true);
|
||||
InputSystem = new CDirectInputSystem(false, true);
|
||||
else if (stricmp(g_Config.GetInputSystem(), "rawinput") == 0)
|
||||
InputSystem = new CDirectInputSystem(true, false, true);
|
||||
InputSystem = new CDirectInputSystem(true, false);
|
||||
#endif // SUPERMODEL_WIN32
|
||||
else
|
||||
{
|
||||
|
|
|
@ -52,7 +52,18 @@ public:
|
|||
#ifdef SUPERMODEL_DEBUGGER
|
||||
bool disableDebugger; // disables the debugger (not stored in the config. file)
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef SUPERMODEL_WIN32
|
||||
unsigned dInputEffectsGain;
|
||||
unsigned dInputConstForceMax;
|
||||
unsigned dInputSelfCenterMax;
|
||||
unsigned dInputFrictionMax;
|
||||
unsigned dInputVibrateMax;
|
||||
unsigned xInputConstForceThreshold;
|
||||
unsigned xInputConstForceMax;
|
||||
unsigned xInputVibrateMax;
|
||||
#endif
|
||||
|
||||
// Input system
|
||||
inline void SetInputSystem(const char *inpSysName)
|
||||
{
|
||||
|
@ -104,6 +115,14 @@ public:
|
|||
#endif
|
||||
#ifdef SUPERMODEL_WIN32
|
||||
inputSystem = "dinput";
|
||||
dInputEffectsGain = 100;
|
||||
dInputConstForceMax = 100;
|
||||
dInputSelfCenterMax = 100;
|
||||
dInputFrictionMax = 100;
|
||||
dInputVibrateMax = 100;
|
||||
xInputConstForceThreshold = 30;
|
||||
xInputConstForceMax = 100;
|
||||
xInputVibrateMax = 100;
|
||||
#else
|
||||
inputSystem = "sdl";
|
||||
#endif
|
||||
|
|
|
@ -215,6 +215,9 @@ void CSDLInputSystem::OpenJoysticks()
|
|||
{
|
||||
joyDetails.hasAxis[axisNum] = joyDetails.numAxes > axisNum;
|
||||
joyDetails.axisHasFF[axisNum] = false; // SDL 1.2 does not support force feedback
|
||||
char *axisName = joyDetails.axisName[axisNum];
|
||||
strcpy(axisName, CInputSystem::GetDefaultAxisName(axisNum)); // SDL 1.2 does not support axis names
|
||||
strcat(axisName, "-Axis");
|
||||
}
|
||||
joyDetails.numPOVs = SDL_JoystickNumHats(joystick);
|
||||
joyDetails.numButtons = SDL_JoystickNumButtons(joystick);
|
||||
|
|
|
@ -319,6 +319,14 @@ BOOL CALLBACK DI8EnumAxesCallback(LPCDIDEVICEOBJECTINSTANCE instance, LPVOID con
|
|||
JoyDetails *joyDetails = (JoyDetails*)context;
|
||||
joyDetails->hasAxis[axisNum] = true;
|
||||
joyDetails->axisHasFF[axisNum] = !!(instance->dwFlags & DIDOI_FFACTUATOR);
|
||||
|
||||
// Get axis name from DirectInput
|
||||
char *axisName = joyDetails->axisName[axisNum];
|
||||
strcpy(axisName, CInputSystem::GetDefaultAxisName(axisNum));
|
||||
strcat(axisName, "-Axis (");
|
||||
strncat(axisName, instance->tszName, MAX_NAME_LENGTH - strlen(axisName) - 1);
|
||||
strcat(axisName, ")");
|
||||
|
||||
return DIENUM_CONTINUE;
|
||||
}
|
||||
|
||||
|
@ -331,7 +339,7 @@ BOOL CALLBACK DI8EnumEffectsCallback(LPCDIEFFECTINFO effectInfo, LPVOID context)
|
|||
return DIENUM_CONTINUE;
|
||||
}
|
||||
|
||||
const char *CDirectInputSystem::ConstructName(bool useRawInput, bool useXInput, bool enableFFeedback)
|
||||
const char *CDirectInputSystem::ConstructName(bool useRawInput, bool useXInput)
|
||||
{
|
||||
if (useRawInput)
|
||||
return (useXInput ? "RawInput/XInput" : "RawInput/DirectInput");
|
||||
|
@ -339,14 +347,12 @@ const char *CDirectInputSystem::ConstructName(bool useRawInput, bool useXInput,
|
|||
return (useXInput ? "Xinput" : "DirectInput");
|
||||
}
|
||||
|
||||
CDirectInputSystem::CDirectInputSystem(bool useRawInput, bool useXInput, bool enableFFeedback) :
|
||||
CInputSystem(ConstructName(useRawInput, useXInput, enableFFeedback)),
|
||||
m_useRawInput(useRawInput), m_useXInput(useXInput), m_enableFFeedback(enableFFeedback),
|
||||
CDirectInputSystem::CDirectInputSystem(bool useRawInput, bool useXInput) :
|
||||
CInputSystem(ConstructName(useRawInput, useXInput)),
|
||||
m_useRawInput(useRawInput), m_useXInput(useXInput), m_enableFFeedback(true),
|
||||
m_initializedCOM(false), m_activated(false), m_hwnd(NULL), m_screenW(0), m_screenH(0),
|
||||
m_getRIDevListPtr(NULL), m_getRIDevInfoPtr(NULL), m_regRIDevsPtr(NULL), m_getRIDataPtr(NULL),
|
||||
m_xiGetCapabilitiesPtr(NULL), m_xiGetStatePtr(NULL), m_xiSetStatePtr(NULL), m_di8(NULL), m_di8Keyboard(NULL), m_di8Mouse(NULL),
|
||||
m_diEffectsGain(100), m_diConstForceMax(100), m_diSelfCenterMax(100), m_diFrictionMax(100), m_diVibrateMax(100),
|
||||
m_xiConstForceThreshold(65), m_xiConstForceMax(100), m_xiVibrateMax(100)
|
||||
m_xiGetCapabilitiesPtr(NULL), m_xiGetStatePtr(NULL), m_xiSetStatePtr(NULL), m_di8(NULL), m_di8Keyboard(NULL), m_di8Mouse(NULL)
|
||||
{
|
||||
// Reset initial states
|
||||
memset(&m_combRawMseState, 0, sizeof(RawMseState));
|
||||
|
@ -675,9 +681,17 @@ void CDirectInputSystem::ActivateKeyboardsAndMice()
|
|||
|
||||
// Set DirectInput cooperative level of keyboard and mouse
|
||||
if (m_di8Keyboard != NULL)
|
||||
m_di8Keyboard->SetCooperativeLevel(m_hwnd, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND);
|
||||
{
|
||||
m_di8Keyboard->Unacquire();
|
||||
m_di8Keyboard->SetCooperativeLevel(m_hwnd, (m_grabMouse ? DISCL_FOREGROUND : DISCL_BACKGROUND) | DISCL_NONEXCLUSIVE);
|
||||
m_di8Keyboard->Acquire();
|
||||
}
|
||||
if (m_di8Mouse != NULL)
|
||||
m_di8Mouse->SetCooperativeLevel(m_hwnd, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND);
|
||||
{
|
||||
m_di8Mouse->Unacquire();
|
||||
m_di8Mouse->SetCooperativeLevel(m_hwnd, (m_grabMouse ? DISCL_FOREGROUND : DISCL_BACKGROUND) | DISCL_NONEXCLUSIVE);
|
||||
m_di8Mouse->Acquire();
|
||||
}
|
||||
}
|
||||
|
||||
void CDirectInputSystem::PollKeyboardsAndMice()
|
||||
|
@ -1178,10 +1192,12 @@ void CDirectInputSystem::ActivateJoysticks()
|
|||
if (!it->isXInput)
|
||||
{
|
||||
LPDIRECTINPUTDEVICE8 joystick = m_di8Joysticks[it->dInputNum];
|
||||
if (m_joyDetails[joyNum].hasFFeedback)
|
||||
joystick->Unacquire();
|
||||
if (m_grabMouse)
|
||||
joystick->SetCooperativeLevel(m_hwnd, DISCL_EXCLUSIVE | DISCL_FOREGROUND);
|
||||
else
|
||||
joystick->SetCooperativeLevel(m_hwnd, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND);
|
||||
joystick->Acquire();
|
||||
}
|
||||
joyNum++;
|
||||
}
|
||||
|
@ -1330,7 +1346,7 @@ HRESULT CDirectInputSystem::CreateJoystickEffect(LPDIRECTINPUTDEVICE8 joystick,
|
|||
eff.dwFlags = DIEFF_CARTESIAN | DIEFF_OBJECTOFFSETS;
|
||||
eff.dwTriggerButton = DIEB_NOTRIGGER;
|
||||
eff.dwTriggerRepeatInterval = 0;
|
||||
eff.dwGain = min<LONG>(m_diEffectsGain * DI_EFFECTS_SCALE, DI_EFFECTS_MAX);
|
||||
eff.dwGain = min<LONG>(g_Config.dInputEffectsGain * DI_EFFECTS_SCALE, DI_EFFECTS_MAX);
|
||||
eff.cAxes = 1;
|
||||
eff.rgdwAxes = &dwAxis;
|
||||
eff.rglDirection = &lDirection;
|
||||
|
@ -1651,12 +1667,12 @@ bool CDirectInputSystem::ProcessForceFeedbackCmd(int joyNum, int axisNum, ForceF
|
|||
|
||||
case FFConstantForce:
|
||||
// Check if constant force effect is disabled
|
||||
if (m_xiConstForceMax == 0)
|
||||
if (g_Config.xInputConstForceMax == 0)
|
||||
return false;
|
||||
// Constant force effect is mapped to either left or right vibration motor depending on its direction
|
||||
negForce = ffCmd.force < 0.0f;
|
||||
absForce = (negForce ? -ffCmd.force : ffCmd.force);
|
||||
threshold = (float)m_xiConstForceThreshold / 100.0f;
|
||||
threshold = (float)g_Config.xInputConstForceThreshold / 100.0f;
|
||||
// Check if constant force effect is being stopped or is below threshold
|
||||
if (absForce == 0.0f || absForce < threshold)
|
||||
{
|
||||
|
@ -1667,14 +1683,14 @@ bool CDirectInputSystem::ProcessForceFeedbackCmd(int joyNum, int axisNum, ForceF
|
|||
else if (negForce)
|
||||
{
|
||||
// If force is negative (to left), set left motor vibrating
|
||||
pInfo->xiConstForceLeft = (WORD)(absForce * (float)(m_xiConstForceMax * XI_VIBRATE_SCALE));
|
||||
pInfo->xiConstForceLeft = (WORD)(absForce * (float)(g_Config.xInputConstForceMax * XI_VIBRATE_SCALE));
|
||||
pInfo->xiConstForceRight = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If force positive (to right), set right motor vibrating
|
||||
pInfo->xiConstForceLeft = 0;
|
||||
pInfo->xiConstForceRight = (WORD)(absForce * (float)(m_xiConstForceMax * XI_VIBRATE_SCALE));
|
||||
pInfo->xiConstForceRight = (WORD)(absForce * (float)(g_Config.xInputConstForceMax * XI_VIBRATE_SCALE));
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1685,7 +1701,7 @@ bool CDirectInputSystem::ProcessForceFeedbackCmd(int joyNum, int axisNum, ForceF
|
|||
|
||||
case FFVibrate:
|
||||
// Check if vibration effect is disabled
|
||||
if (m_xiVibrateMax == 0)
|
||||
if (g_Config.xInputVibrateMax == 0)
|
||||
return false;
|
||||
// Check if vibration effect is being stopped
|
||||
if (ffCmd.force == 0.0f)
|
||||
|
@ -1696,7 +1712,7 @@ bool CDirectInputSystem::ProcessForceFeedbackCmd(int joyNum, int axisNum, ForceF
|
|||
else
|
||||
{
|
||||
// Otherwise, set both motors vibrating
|
||||
pInfo->xiVibrateBoth = (WORD)(ffCmd.force * (float)(m_xiVibrateMax * XI_VIBRATE_SCALE));
|
||||
pInfo->xiVibrateBoth = (WORD)(ffCmd.force * (float)(g_Config.xInputVibrateMax * XI_VIBRATE_SCALE));
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1748,9 +1764,9 @@ bool CDirectInputSystem::ProcessForceFeedbackCmd(int joyNum, int axisNum, ForceF
|
|||
{
|
||||
case FFConstantForce:
|
||||
//printf("FFConstantForce %0.2f\n", 100.0f * ffCmd.force);
|
||||
if (m_diConstForceMax == 0)
|
||||
if (g_Config.dInputConstForceMax == 0)
|
||||
return false;
|
||||
dicf.lMagnitude = min<LONG>(-ffCmd.force * (float)(m_diConstForceMax * DI_EFFECTS_SCALE), DI_EFFECTS_MAX); // Invert sign for DirectInput effect
|
||||
dicf.lMagnitude = min<LONG>(-ffCmd.force * (float)(g_Config.dInputConstForceMax * DI_EFFECTS_SCALE), DI_EFFECTS_MAX); // Invert sign for DirectInput effect
|
||||
|
||||
eff.cbTypeSpecificParams = sizeof(DICONSTANTFORCE);
|
||||
eff.lpvTypeSpecificParams = &dicf;
|
||||
|
@ -1758,11 +1774,11 @@ bool CDirectInputSystem::ProcessForceFeedbackCmd(int joyNum, int axisNum, ForceF
|
|||
|
||||
case FFSelfCenter:
|
||||
//printf("FFSelfCenter %0.2f\n", 100.0f * ffCmd.force);
|
||||
if (m_diSelfCenterMax == 0)
|
||||
if (g_Config.dInputSelfCenterMax == 0)
|
||||
return false;
|
||||
dic.lOffset = 0;
|
||||
dic.lPositiveCoefficient = min<LONG>(ffCmd.force * (float)(m_diSelfCenterMax * DI_EFFECTS_SCALE), DI_EFFECTS_MAX);
|
||||
dic.lNegativeCoefficient = min<LONG>(ffCmd.force * (float)(m_diSelfCenterMax * DI_EFFECTS_SCALE), DI_EFFECTS_MAX);
|
||||
dic.lPositiveCoefficient = min<LONG>(ffCmd.force * (float)(g_Config.dInputSelfCenterMax * DI_EFFECTS_SCALE), DI_EFFECTS_MAX);
|
||||
dic.lNegativeCoefficient = min<LONG>(ffCmd.force * (float)(g_Config.dInputSelfCenterMax * DI_EFFECTS_SCALE), DI_EFFECTS_MAX);
|
||||
dic.dwPositiveSaturation = DI_FFNOMINALMAX;
|
||||
dic.dwNegativeSaturation = DI_FFNOMINALMAX;
|
||||
dic.lDeadBand = (LONG)(0.05 * DI_FFNOMINALMAX);
|
||||
|
@ -1773,11 +1789,11 @@ bool CDirectInputSystem::ProcessForceFeedbackCmd(int joyNum, int axisNum, ForceF
|
|||
|
||||
case FFFriction:
|
||||
//printf("FFFriction %0.2f\n", 100.0f * ffCmd.force);
|
||||
if (m_diFrictionMax == 0)
|
||||
if (g_Config.dInputFrictionMax == 0)
|
||||
return false;
|
||||
dic.lOffset = 0;
|
||||
dic.lPositiveCoefficient = min<LONG>(ffCmd.force * (float)(m_diFrictionMax * DI_EFFECTS_SCALE), DI_EFFECTS_MAX);
|
||||
dic.lNegativeCoefficient = min<LONG>(ffCmd.force * (float)(m_diFrictionMax * DI_EFFECTS_SCALE), DI_EFFECTS_MAX);
|
||||
dic.lPositiveCoefficient = min<LONG>(ffCmd.force * (float)(g_Config.dInputFrictionMax * DI_EFFECTS_SCALE), DI_EFFECTS_MAX);
|
||||
dic.lNegativeCoefficient = min<LONG>(ffCmd.force * (float)(g_Config.dInputFrictionMax * DI_EFFECTS_SCALE), DI_EFFECTS_MAX);
|
||||
dic.dwPositiveSaturation = DI_FFNOMINALMAX;
|
||||
dic.dwNegativeSaturation = DI_FFNOMINALMAX;
|
||||
dic.lDeadBand = 0;
|
||||
|
@ -1788,9 +1804,9 @@ bool CDirectInputSystem::ProcessForceFeedbackCmd(int joyNum, int axisNum, ForceF
|
|||
|
||||
case FFVibrate:
|
||||
//printf("FFVibrate %0.2f\n", 100.0f * ffCmd.force);
|
||||
if (m_diVibrateMax == 0)
|
||||
if (g_Config.dInputVibrateMax == 0)
|
||||
return false;
|
||||
dip.dwMagnitude = min<DWORD>(ffCmd.force * (float)(m_diVibrateMax * DI_EFFECTS_SCALE), DI_EFFECTS_MAX);
|
||||
dip.dwMagnitude = min<DWORD>(ffCmd.force * (float)(g_Config.dInputVibrateMax * DI_EFFECTS_SCALE), DI_EFFECTS_MAX);
|
||||
dip.lOffset = 0;
|
||||
dip.dwPhase = 0;
|
||||
dip.dwPeriod = (DWORD)(0.05 * DI_SECONDS); // 1/20th second
|
||||
|
@ -1878,47 +1894,6 @@ const JoyDetails *CDirectInputSystem::GetJoyDetails(int joyNum)
|
|||
return &m_joyDetails[joyNum];
|
||||
}
|
||||
|
||||
void CDirectInputSystem::ReadFromINIFile(CINIFile *ini, const char *section)
|
||||
{
|
||||
CInputSystem::ReadFromINIFile(ini, section);
|
||||
|
||||
ini->Get(section, "DirectInputEffectsGain", m_diEffectsGain);
|
||||
ini->Get(section, "DirectInputConstForceMax", m_diConstForceMax);
|
||||
ini->Get(section, "DirectInputSelfCenterMax", m_diSelfCenterMax);
|
||||
ini->Get(section, "DirectInputFrictionMax", m_diFrictionMax);
|
||||
ini->Get(section, "DirectInputVibrateMax", m_diVibrateMax);
|
||||
ini->Get(section, "XInputConstForceThreshold", m_xiConstForceThreshold);
|
||||
ini->Get(section, "XInputConstForceMax", m_xiConstForceMax);
|
||||
ini->Get(section, "XInputVibrateMax", m_xiVibrateMax);
|
||||
}
|
||||
|
||||
void CDirectInputSystem::WriteToINIFile(CINIFile *ini, const char *section)
|
||||
{
|
||||
CInputSystem::WriteToINIFile(ini, section);
|
||||
|
||||
// Only write out those settings which have changed from default
|
||||
/*
|
||||
if (m_diEffectsGain != 100) ini->Set(section, "DirectInputEffectsGain", m_diEffectsGain);
|
||||
if (m_diConstForceMax != 100) ini->Set(section, "DirectInputConstForceMax", m_diConstForceMax);
|
||||
if (m_diSelfCenterMax != 100) ini->Set(section, "DirectInputSelfCenterMax", m_diSelfCenterMax);
|
||||
if (m_diFrictionMax != 100) ini->Set(section, "DirectInputFrictionMax", m_diFrictionMax);
|
||||
if (m_diVibrateMax != 100) ini->Set(section, "DirectInputVibrateMax", m_diVibrateMax);
|
||||
if (m_xiConstForceThreshold != 65) ini->Set(section, "XInputConstForceThreshold", m_xiConstForceThreshold);
|
||||
if (m_xiConstForceMax != 100) ini->Set(section, "XInputConstForceMax", m_xiConstForceMax);
|
||||
if (m_xiVibrateMax != 100) ini->Set(section, "XInputVibrateMax", m_xiVibrateMax);
|
||||
*/
|
||||
|
||||
// Always write out
|
||||
ini->Set(section, "DirectInputEffectsGain", m_diEffectsGain);
|
||||
ini->Set(section, "DirectInputConstForceMax", m_diConstForceMax);
|
||||
ini->Set(section, "DirectInputSelfCenterMax", m_diSelfCenterMax);
|
||||
ini->Set(section, "DirectInputFrictionMax", m_diFrictionMax);
|
||||
ini->Set(section, "DirectInputVibrateMax", m_diVibrateMax);
|
||||
ini->Set(section, "XInputConstForceThreshold", m_xiConstForceThreshold);
|
||||
ini->Set(section, "XInputConstForceMax", m_xiConstForceMax);
|
||||
ini->Set(section, "XInputVibrateMax", m_xiVibrateMax);
|
||||
}
|
||||
|
||||
bool CDirectInputSystem::Poll()
|
||||
{
|
||||
// See if keyboard, mice and joysticks have been activated yet
|
||||
|
@ -1997,18 +1972,25 @@ void CDirectInputSystem::GrabMouse()
|
|||
{
|
||||
CInputSystem::GrabMouse();
|
||||
|
||||
SetMouseVisibility(false);
|
||||
if (m_useRawInput)
|
||||
SetMouseVisibility(false);
|
||||
|
||||
// When grabbing mouse, make sure devices get re-activated
|
||||
ActivateKeyboardsAndMice();
|
||||
ActivateJoysticks();
|
||||
if (m_activated)
|
||||
{
|
||||
ActivateKeyboardsAndMice();
|
||||
ActivateJoysticks();
|
||||
}
|
||||
}
|
||||
|
||||
void CDirectInputSystem::UngrabMouse()
|
||||
{
|
||||
CInputSystem::UngrabMouse();
|
||||
|
||||
// When ungrabbing mouse place, make sure devices get re-activated
|
||||
ActivateKeyboardsAndMice();
|
||||
ActivateJoysticks();
|
||||
// When ungrabbing mouse, make sure devices get re-activated
|
||||
if (m_activated)
|
||||
{
|
||||
ActivateKeyboardsAndMice();
|
||||
ActivateJoysticks();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -126,7 +126,7 @@ 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);
|
||||
static const char *ConstructName(bool useRawInput, bool useXInput);
|
||||
|
||||
bool m_useRawInput;
|
||||
bool m_useXInput;
|
||||
|
@ -176,18 +176,6 @@ private:
|
|||
vector<DIJoyInfo> m_diJoyInfos;
|
||||
vector<DIJOYSTATE2> m_diJoyStates;
|
||||
|
||||
// DirectInput force feedback parameters (100% = max)
|
||||
unsigned m_diEffectsGain;
|
||||
unsigned m_diConstForceMax;
|
||||
unsigned m_diSelfCenterMax;
|
||||
unsigned m_diFrictionMax;
|
||||
unsigned m_diVibrateMax;
|
||||
|
||||
// XInput force feedback parameters (100% = max)
|
||||
unsigned m_xiConstForceThreshold;
|
||||
unsigned m_xiConstForceMax;
|
||||
unsigned m_xiVibrateMax;
|
||||
|
||||
bool GetRegString(HKEY regKey, const char *regPath, string &str);
|
||||
|
||||
bool GetRegDeviceName(const char *rawDevName, char *name);
|
||||
|
@ -259,7 +247,7 @@ public:
|
|||
* 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, bool useXInput, bool enableFFeedback);
|
||||
CDirectInputSystem(bool useRawInput, bool useXInput);
|
||||
|
||||
~CDirectInputSystem();
|
||||
|
||||
|
@ -275,10 +263,6 @@ public:
|
|||
|
||||
const JoyDetails *GetJoyDetails(int joyNum);
|
||||
|
||||
void ReadFromINIFile(CINIFile *ini, const char *section);
|
||||
|
||||
void WriteToINIFile(CINIFile *ini, const char *section);
|
||||
|
||||
bool Poll();
|
||||
|
||||
void GrabMouse();
|
||||
|
|
Loading…
Reference in a new issue