Skip to content

Commit 3ea97b8

Browse files
UI: Add analog speed limit mapping.
Only shows up as a setting if mapped, to avoid cluttering settings.
1 parent 626be05 commit 3ea97b8

14 files changed

+113
-5
lines changed

Core/Config.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -862,6 +862,8 @@ static ConfigSetting graphicsSettings[] = {
862862
ReportedConfigSetting("AutoFrameSkip", &g_Config.bAutoFrameSkip, false, true, true),
863863
ConfigSetting("FrameRate", &g_Config.iFpsLimit1, 0, true, true),
864864
ConfigSetting("FrameRate2", &g_Config.iFpsLimit2, -1, true, true),
865+
ConfigSetting("AnalogFrameRate", &g_Config.iAnalogFpsLimit, 240, true, true),
866+
ConfigSetting("AnalogFrameRateMode", &g_Config.iAnalogFpsMode, 0, true, true),
865867
ConfigSetting("UnthrottlingMode", &g_Config.iFastForwardMode, &DefaultFastForwardMode, &FastForwardModeToString, &FastForwardModeFromString, true, true),
866868
#if defined(USING_WIN_UI)
867869
ConfigSetting("RestartRequired", &g_Config.bRestartRequired, false, false),

Core/Config.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,8 @@ struct Config {
209209
bool bTexHardwareScaling;
210210
int iFpsLimit1;
211211
int iFpsLimit2;
212+
int iAnalogFpsLimit;
213+
int iAnalogFpsMode; // 0 = auto, 1 = single direction, 2 = mapped to opposite
212214
int iMaxRecent;
213215
int iCurrentStateSlot;
214216
int iRewindFlipFrequency;

Core/ConfigValues.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,3 +130,9 @@ enum class BackgroundAnimation {
130130
WAVE = 3,
131131
MOVING_BACKGROUND = 4,
132132
};
133+
134+
enum class AnalogFpsMode {
135+
AUTO = 0,
136+
MAPPED_DIRECTION = 1,
137+
MAPPED_TO_OPPOSITE = 2,
138+
};

Core/ControlMapper.cpp

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
#include "Core/KeyMap.h"
88
#include "Core/ControlMapper.h"
99
#include "Core/Config.h"
10+
#include "Core/CoreParameter.h"
11+
#include "Core/System.h"
1012

1113
static float MapAxisValue(float v) {
1214
const float deadzone = g_Config.fAnalogDeadzone;
@@ -334,12 +336,21 @@ void ControlMapper::processAxis(const AxisInput &axis, int direction) {
334336
case VIRTKEY_AXIS_RIGHT_Y_MAX:
335337
SetPSPAxis('Y', value, CTRL_STICK_RIGHT);
336338
break;
339+
340+
case VIRTKEY_SPEED_ANALOG:
341+
ProcessAnalogSpeed(axis, false);
342+
break;
337343
}
338344
}
339345

340346
std::vector<int> resultsOpposite;
341347
KeyMap::AxisToPspButton(axis.deviceId, axis.axisId, -direction, &resultsOpposite);
342348

349+
for (int result : resultsOpposite) {
350+
if (result == VIRTKEY_SPEED_ANALOG)
351+
ProcessAnalogSpeed(axis, true);
352+
}
353+
343354
int axisState = 0;
344355
float threshold = axis.deviceId == DEVICE_ID_MOUSE ? AXIS_BIND_THRESHOLD_MOUSE : AXIS_BIND_THRESHOLD;
345356
if (direction == 1 && axis.value >= threshold) {
@@ -375,3 +386,55 @@ void ControlMapper::processAxis(const AxisInput &axis, int direction) {
375386
}
376387
}
377388
}
389+
390+
void ControlMapper::ProcessAnalogSpeed(const AxisInput &axis, bool opposite) {
391+
FPSLimit &limitMode = PSP_CoreParameter().fpsLimit;
392+
// If we're using an alternate speed already, let that win.
393+
if (limitMode != FPSLimit::NORMAL && limitMode != FPSLimit::ANALOG)
394+
return;
395+
// Don't even try if the limit is invalid.
396+
if (g_Config.iAnalogFpsLimit <= 0)
397+
return;
398+
399+
AnalogFpsMode mode = (AnalogFpsMode)g_Config.iAnalogFpsMode;
400+
float value = axis.value;
401+
if (mode == AnalogFpsMode::AUTO) {
402+
// TODO: Consider the pad name for better auto? KeyMap::PadName(axis.deviceId);
403+
switch (axis.axisId) {
404+
case JOYSTICK_AXIS_X:
405+
case JOYSTICK_AXIS_Y:
406+
case JOYSTICK_AXIS_Z:
407+
case JOYSTICK_AXIS_RX:
408+
case JOYSTICK_AXIS_RY:
409+
case JOYSTICK_AXIS_RZ:
410+
// These, at least on directinput, can be used for triggers that go from mapped to opposite.
411+
mode = AnalogFpsMode::MAPPED_TO_OPPOSITE;
412+
break;
413+
414+
default:
415+
// Other axises probably don't go from negative to positive.
416+
mode = AnalogFpsMode::MAPPED_DIRECTION;
417+
break;
418+
}
419+
}
420+
421+
// Okay, now let's map it as appropriate.
422+
if (mode == AnalogFpsMode::MAPPED_DIRECTION) {
423+
value = fabsf(value);
424+
if (opposite)
425+
return;
426+
} else if (mode == AnalogFpsMode::MAPPED_TO_OPPOSITE) {
427+
value = fabsf(value);
428+
if (opposite)
429+
value = -value;
430+
value = 0.5f - value * 0.5f;
431+
}
432+
433+
// If target is above 60, value is how much to speed up over 60. Otherwise, it's how much slower.
434+
// So normalize the target.
435+
int target = g_Config.iAnalogFpsLimit - 60;
436+
PSP_CoreParameter().analogFpsLimit = 60 + (int)(target * value);
437+
438+
// If we've reset back to normal, turn it off.
439+
limitMode = PSP_CoreParameter().analogFpsLimit == 60 ? FPSLimit::NORMAL : FPSLimit::ANALOG;
440+
}

Core/ControlMapper.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ class ControlMapper {
3333
void setVKeyAnalog(char axis, int stick, int virtualKeyMin, int virtualKeyMax, bool setZero = true);
3434

3535
void SetPSPAxis(char axis, float value, int stick);
36+
void ProcessAnalogSpeed(const AxisInput &axis, bool opposite);
3637

3738
void onVKeyDown(int vkey);
3839
void onVKeyUp(int vkey);

Core/CoreParameter.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ enum class FPSLimit {
3333
NORMAL = 0,
3434
CUSTOM1 = 1,
3535
CUSTOM2 = 2,
36+
ANALOG = 3,
3637
};
3738

3839
class FileLoader;
@@ -76,6 +77,7 @@ struct CoreParameter {
7677
// Can be modified at runtime.
7778
bool fastForward = false;
7879
FPSLimit fpsLimit = FPSLimit::NORMAL;
80+
int analogFpsLimit = 0;
7981

8082
bool updateRecent = true;
8183

Core/HLE/sceDisplay.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,8 @@ static int FrameTimingLimit() {
354354
return g_Config.iFpsLimit1;
355355
if (PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM2)
356356
return g_Config.iFpsLimit2;
357+
if (PSP_CoreParameter().fpsLimit == FPSLimit::ANALOG)
358+
return PSP_CoreParameter().analogFpsLimit;
357359
if (PSP_CoreParameter().fastForward)
358360
return 0;
359361
return 60;

Core/KeyMap.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,7 @@ const KeyMap_IntStrPair psp_button_names[] = {
368368
{VIRTKEY_SPEED_TOGGLE, "SpeedToggle"},
369369
{VIRTKEY_SPEED_CUSTOM1, "Alt speed 1"},
370370
{VIRTKEY_SPEED_CUSTOM2, "Alt speed 2"},
371+
{VIRTKEY_SPEED_ANALOG, "Analog speed"},
371372
{VIRTKEY_PAUSE, "Pause"},
372373
#ifndef MOBILE_DEVICE
373374
{VIRTKEY_FRAME_ADVANCE, "Frame Advance"},
@@ -542,8 +543,10 @@ bool AxisFromPspButton(int btn, int *deviceId, int *axisId, int *direction) {
542543
for (auto iter = g_controllerMap.begin(); iter != g_controllerMap.end(); ++iter) {
543544
for (auto iter2 = iter->second.begin(); iter2 != iter->second.end(); ++iter2) {
544545
if (iter->first == btn && iter2->keyCode >= AXIS_BIND_NKCODE_START) {
545-
*deviceId = iter2->deviceId;
546-
*axisId = TranslateKeyCodeToAxis(iter2->keyCode, *direction);
546+
if (deviceId)
547+
*deviceId = iter2->deviceId;
548+
if (axisId)
549+
*axisId = TranslateKeyCodeToAxis(iter2->keyCode, *direction);
547550
return true;
548551
}
549552
}
@@ -797,6 +800,13 @@ const std::set<std::string> &GetSeenPads() {
797800
return g_seenPads;
798801
}
799802

803+
std::string PadName(int deviceId) {
804+
auto it = g_padNames.find(deviceId);
805+
if (it != g_padNames.end())
806+
return it->second;
807+
return "";
808+
}
809+
800810
// Swap direction buttons and left analog axis
801811
void SwapAxis() {
802812
g_swapped_keys = !g_swapped_keys;

Core/KeyMap.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ enum {
6767
VIRTKEY_SCREEN_ROTATION_VERTICAL180 = 0x40000021,
6868
VIRTKEY_SCREEN_ROTATION_HORIZONTAL = 0x40000022,
6969
VIRTKEY_SCREEN_ROTATION_HORIZONTAL180 = 0x40000023,
70+
VIRTKEY_SPEED_ANALOG = 0x40000024,
7071
VIRTKEY_LAST,
7172
VIRTKEY_COUNT = VIRTKEY_LAST - VIRTKEY_FIRST
7273
};
@@ -163,6 +164,7 @@ namespace KeyMap {
163164
bool HasBuiltinController(const std::string &name);
164165

165166
const std::set<std::string> &GetSeenPads();
167+
std::string PadName(int deviceId);
166168
void AutoConfForPad(const std::string &name);
167169

168170
bool IsKeyMapped(int device, int key);

GPU/GPUCommon.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -505,7 +505,14 @@ void GPUCommon::UpdateVsyncInterval(bool force) {
505505
desiredVSyncInterval = 0;
506506
}
507507
if (PSP_CoreParameter().fpsLimit != FPSLimit::NORMAL) {
508-
int limit = PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM1 ? g_Config.iFpsLimit1 : g_Config.iFpsLimit2;
508+
int limit;
509+
if (PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM1)
510+
limit = g_Config.iFpsLimit1;
511+
else if (PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM2)
512+
limit = g_Config.iFpsLimit2;
513+
else
514+
limit = PSP_CoreParameter().analogFpsLimit;
515+
509516
// For an alternative speed that is a clean factor of 60, the user probably still wants vsync.
510517
if (limit == 0 || (limit >= 0 && limit != 15 && limit != 30 && limit != 60)) {
511518
desiredVSyncInterval = 0;

0 commit comments

Comments
 (0)