Skip to content

Commit 8dbe935

Browse files
committed
Control profiles
1 parent 3f133be commit 8dbe935

File tree

10 files changed

+232
-22
lines changed

10 files changed

+232
-22
lines changed

Common/Data/Format/IniFile.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -703,6 +703,18 @@ bool IniFile::Get(const char* sectionName, const char* key, bool* value, bool de
703703
}
704704
}
705705

706+
bool IniFile::Get(const char* sectionName, const char* key, float* value, float defaultValue)
707+
{
708+
Section *section = GetSection(sectionName);
709+
if (!section) {
710+
*value = defaultValue;
711+
return false;
712+
} else {
713+
return section->Get(key, value, defaultValue);
714+
}
715+
}
716+
717+
706718

707719
// Unit test. TODO: Move to the real unit test framework.
708720
/*

Common/Data/Format/IniFile.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ class IniFile {
121121
bool Get(const char* sectionName, const char* key, uint32_t* value, uint32_t defaultValue = 0);
122122
bool Get(const char* sectionName, const char* key, uint64_t* value, uint64_t defaultValue = 0);
123123
bool Get(const char* sectionName, const char* key, bool* value, bool defaultValue = false);
124+
bool Get(const char* sectionName, const char* key, float* value, float defaultValue = 0.0f);
124125
bool Get(const char* sectionName, const char* key, std::vector<std::string>& values);
125126

126127
template<typename T> bool GetIfExists(const char* sectionName, const char* key, T value)

Core/Config.cpp

Lines changed: 100 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -562,21 +562,6 @@ static ConfigSetting generalSettings[] = {
562562
ConfigSetting("GridView1", &g_Config.bGridView1, true),
563563
ConfigSetting("GridView2", &g_Config.bGridView2, true),
564564
ConfigSetting("GridView3", &g_Config.bGridView3, false),
565-
ConfigSetting("RightAnalogUp", &g_Config.iRightAnalogUp, 0, true, true),
566-
ConfigSetting("RightAnalogDown", &g_Config.iRightAnalogDown, 0, true, true),
567-
ConfigSetting("RightAnalogLeft", &g_Config.iRightAnalogLeft, 0, true, true),
568-
ConfigSetting("RightAnalogRight", &g_Config.iRightAnalogRight, 0, true, true),
569-
ConfigSetting("RightAnalogPress", &g_Config.iRightAnalogPress, 0, true, true),
570-
ConfigSetting("RightAnalogCustom", &g_Config.bRightAnalogCustom, false, true, true),
571-
ConfigSetting("RightAnalogDisableDiagonal", &g_Config.bRightAnalogDisableDiagonal, false, true, true),
572-
ConfigSetting("SwipeUp", &g_Config.iSwipeUp, 0, true, true),
573-
ConfigSetting("SwipeDown", &g_Config.iSwipeDown, 0, true, true),
574-
ConfigSetting("SwipeLeft", &g_Config.iSwipeLeft, 0, true, true),
575-
ConfigSetting("SwipeRight", &g_Config.iSwipeRight, 0, true, true),
576-
ConfigSetting("SwipeSensitivity", &g_Config.fSwipeSensitivity, 1.0f, true, true),
577-
ConfigSetting("SwipeSmoothing", &g_Config.fSwipeSmoothing, 0.3f, true, true),
578-
ConfigSetting("DoubleTapGesture", &g_Config.iDoubleTapGesture, 0, true, true),
579-
ConfigSetting("GestureControlEnabled", &g_Config.bGestureControlEnabled, false, true, true),
580565

581566
// "default" means let emulator decide, "" means disable.
582567
ConfigSetting("ReportingHost", &g_Config.sReportHost, "default"),
@@ -616,6 +601,7 @@ static ConfigSetting generalSettings[] = {
616601
ConfigSetting("EnablePlugins", &g_Config.bLoadPlugins, true, true, true),
617602

618603
ReportedConfigSetting("IgnoreCompatSettings", &g_Config.sIgnoreCompatSettings, "", true, true),
604+
ConfigSetting("SettingsVersion", &g_Config.uSettingsVersion, 0u, true, true), // Per game for game configs
619605

620606
ConfigSetting(false),
621607
};
@@ -1089,6 +1075,23 @@ static ConfigSetting controlSettings[] = {
10891075
ConfigSetting("MouseSensitivity", &g_Config.fMouseSensitivity, 0.1f, true, true),
10901076
ConfigSetting("MouseSmoothing", &g_Config.fMouseSmoothing, 0.9f, true, true),
10911077

1078+
ConfigSetting("RightAnalogUp", &g_Config.iRightAnalogUp, 0, true, true),
1079+
ConfigSetting("RightAnalogDown", &g_Config.iRightAnalogDown, 0, true, true),
1080+
ConfigSetting("RightAnalogLeft", &g_Config.iRightAnalogLeft, 0, true, true),
1081+
ConfigSetting("RightAnalogRight", &g_Config.iRightAnalogRight, 0, true, true),
1082+
ConfigSetting("RightAnalogPress", &g_Config.iRightAnalogPress, 0, true, true),
1083+
ConfigSetting("RightAnalogCustom", &g_Config.bRightAnalogCustom, false, true, true),
1084+
ConfigSetting("RightAnalogDisableDiagonal", &g_Config.bRightAnalogDisableDiagonal, false, true, true),
1085+
1086+
ConfigSetting("SwipeUp", &g_Config.iSwipeUp, 0, true, true),
1087+
ConfigSetting("SwipeDown", &g_Config.iSwipeDown, 0, true, true),
1088+
ConfigSetting("SwipeLeft", &g_Config.iSwipeLeft, 0, true, true),
1089+
ConfigSetting("SwipeRight", &g_Config.iSwipeRight, 0, true, true),
1090+
ConfigSetting("SwipeSensitivity", &g_Config.fSwipeSensitivity, 1.0f, true, true),
1091+
ConfigSetting("SwipeSmoothing", &g_Config.fSwipeSmoothing, 0.3f, true, true),
1092+
ConfigSetting("DoubleTapGesture", &g_Config.iDoubleTapGesture, 0, true, true),
1093+
ConfigSetting("GestureControlEnabled", &g_Config.bGestureControlEnabled, false, true, true),
1094+
10921095
ConfigSetting("SystemControls", &g_Config.bSystemControls, true, true, false),
10931096

10941097
ConfigSetting(false),
@@ -1322,6 +1325,24 @@ void Config::UpdateIniLocation(const char *iniFileName, const char *controllerIn
13221325
controllerIniFilename_ = FindConfigFile(useControllerIniFilename ? controllerIniFilename : "controls.ini");
13231326
}
13241327

1328+
static void loadOldControlSettings(IniFile &iniFile) {
1329+
iniFile.GetIfExists("General", "RightAnalogUp", &g_Config.iRightAnalogUp);
1330+
iniFile.GetIfExists("General", "RightAnalogDown", &g_Config.iRightAnalogDown);
1331+
iniFile.GetIfExists("General", "RightAnalogLeft", &g_Config.iRightAnalogLeft);
1332+
iniFile.GetIfExists("General", "RightAnalogRight", &g_Config.iRightAnalogRight);
1333+
iniFile.GetIfExists("General", "RightAnalogPress", &g_Config.iRightAnalogPress);
1334+
iniFile.GetIfExists("General", "SwipeUp", &g_Config.iSwipeUp);
1335+
iniFile.GetIfExists("General", "SwipeDown", &g_Config.iSwipeDown);
1336+
iniFile.GetIfExists("General", "SwipeLeft", &g_Config.iSwipeLeft);
1337+
iniFile.GetIfExists("General", "SwipeRight", &g_Config.iSwipeRight);
1338+
iniFile.GetIfExists("General", "DoubleTapGesture", &g_Config.iDoubleTapGesture);
1339+
iniFile.GetIfExists("General", "SwipeSensitivity", &g_Config.fSwipeSensitivity);
1340+
iniFile.GetIfExists("General", "SwipeSmoothing", &g_Config.fSwipeSmoothing);
1341+
iniFile.GetIfExists("General", "RightAnalogCustom", &g_Config.bRightAnalogCustom);
1342+
iniFile.GetIfExists("General", "RightAnalogDisableDiagonal", &g_Config.bRightAnalogDisableDiagonal);
1343+
iniFile.GetIfExists("General", "GestureControlEnabled", &g_Config.bGestureControlEnabled);
1344+
}
1345+
13251346
void Config::Load(const char *iniFileName, const char *controllerIniFilename) {
13261347
if (!bUpdatedInstanceCounter) {
13271348
InitInstanceCounter();
@@ -1419,6 +1440,12 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename) {
14191440
ResetControlLayout();
14201441
}
14211442

1443+
if (g_Config.uSettingsVersion == 0) {
1444+
g_Config.uSettingsVersion = 1;
1445+
1446+
loadOldControlSettings(iniFile);
1447+
}
1448+
14221449
const char *gitVer = PPSSPP_GIT_VERSION;
14231450
Version installed(gitVer);
14241451
Version upgrade(upgradeVersion);
@@ -1488,6 +1515,58 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename) {
14881515
INFO_LOG(LOADER, "Config loaded: '%s'", iniFilename_.c_str());
14891516
}
14901517

1518+
bool Config::SaveControllerProfile(uint32_t id) {
1519+
IniFile iniFile;
1520+
if (!iniFile.Load(controllerIniFilename_)) {
1521+
ERROR_LOG(LOADER, "Error saving controller profile - can't read ini '%s'", controllerIniFilename_.c_str());
1522+
return false;
1523+
}
1524+
1525+
Section *section = iniFile.GetOrCreateSection(StringFromFormat("ControlProfile%uSettings", id).c_str());
1526+
for (auto setting = controlSettings; setting->HasMore(); ++setting) {
1527+
setting->Set(section);
1528+
}
1529+
1530+
KeyMap::SaveToIni(iniFile, StringFromFormat("ControlProfile%uMapping", id).c_str());
1531+
1532+
if (!iniFile.Save(controllerIniFilename_)) {
1533+
ERROR_LOG(LOADER, "Error saving controller profile - can't write ini '%s'", controllerIniFilename_.c_str());
1534+
return false;
1535+
}
1536+
1537+
return true;
1538+
}
1539+
1540+
bool Config::ControllerProfileExist(uint32_t id) {
1541+
IniFile iniFile;
1542+
if (!iniFile.Load(controllerIniFilename_)) {
1543+
ERROR_LOG(LOADER, "Error checking controller profile - can't read ini '%s'", controllerIniFilename_.c_str());
1544+
return false;
1545+
}
1546+
1547+
return iniFile.HasSection(StringFromFormat("ControlProfile%uSettings", id).c_str());
1548+
}
1549+
1550+
bool Config::LoadControllerProfile(uint32_t id) {
1551+
IniFile iniFile;
1552+
if (!iniFile.Load(controllerIniFilename_)) {
1553+
ERROR_LOG(LOADER, "Error loading controller profile - can't read ini '%s'", controllerIniFilename_.c_str());
1554+
return false;
1555+
}
1556+
1557+
if (!iniFile.HasSection(StringFromFormat("ControlProfile%uSettings", id).c_str()))
1558+
return false;
1559+
1560+
Section *section = iniFile.GetOrCreateSection(StringFromFormat("ControlProfile%uSettings", id).c_str());
1561+
for (auto setting = controlSettings; setting->HasMore(); ++setting) {
1562+
setting->Get(section);
1563+
}
1564+
1565+
KeyMap::LoadFromIni(iniFile, StringFromFormat("ControlProfile%uMapping", id).c_str());
1566+
1567+
return true;
1568+
}
1569+
14911570
bool Config::Save(const char *saveReason) {
14921571
if (!IsFirstInstance()) {
14931572
// TODO: Should we allow saving config if started from a different directory?
@@ -1895,6 +1974,12 @@ bool Config::loadGameConfig(const std::string &pGameId, const std::string &title
18951974
}
18961975
});
18971976

1977+
if (g_Config.uSettingsVersion == 0) {
1978+
g_Config.uSettingsVersion = 1;
1979+
1980+
loadOldControlSettings(iniFile);
1981+
}
1982+
18981983
KeyMap::LoadFromIni(iniFile);
18991984
return true;
19001985
}

Core/Config.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ struct Config {
9292
bool bEnableLogging;
9393
bool bDumpDecryptedEboot;
9494
bool bFullscreenOnDoubleclick;
95+
uint32_t uSettingsVersion;
9596

9697
// These four are Win UI only
9798
bool bPauseOnLostFocus;
@@ -519,6 +520,9 @@ struct Config {
519520

520521
void Load(const char *iniFileName = nullptr, const char *controllerIniFilename = nullptr);
521522
bool Save(const char *saveReason);
523+
bool SaveControllerProfile(uint32_t id);
524+
bool LoadControllerProfile(uint32_t id);
525+
bool ControllerProfileExist(uint32_t id);
522526
void Reload();
523527
void RestoreDefaults();
524528

Core/KeyMap.cpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,12 @@ const KeyMap_IntStrPair psp_button_names[] = {
424424
{CTRL_VOL_DOWN, "Vol -"},
425425
{CTRL_SCREEN, "Screen"},
426426
{CTRL_NOTE, "Note"},
427+
428+
{VIRTKEY_CONTROLLER_PROFILE_1, "Load control profile 1"},
429+
{VIRTKEY_CONTROLLER_PROFILE_2, "Load control profile 2"},
430+
{VIRTKEY_CONTROLLER_PROFILE_3, "Load control profile 3"},
431+
{VIRTKEY_CONTROLLER_PROFILE_4, "Load control profile 4"},
432+
{VIRTKEY_CONTROLLER_PROFILE_5, "Load control profile 5"},
427433
};
428434

429435
const int AXIS_BIND_NKCODE_START = 4000;
@@ -702,13 +708,13 @@ void RestoreDefault() {
702708
}
703709

704710
// TODO: Make the ini format nicer.
705-
void LoadFromIni(IniFile &file) {
711+
void LoadFromIni(IniFile &file, const char *section) {
706712
RestoreDefault();
707-
if (!file.HasSection("ControlMapping")) {
713+
if (!file.HasSection("ControlMapping")) { // Only on default section
708714
return;
709715
}
710716

711-
Section *controls = file.GetOrCreateSection("ControlMapping");
717+
Section *controls = file.GetOrCreateSection(section);
712718
for (size_t i = 0; i < ARRAY_SIZE(psp_button_names); i++) {
713719
std::string value;
714720
controls->Get(psp_button_names[i].name, &value, "");
@@ -735,8 +741,8 @@ void LoadFromIni(IniFile &file) {
735741
UpdateNativeMenuKeys();
736742
}
737743

738-
void SaveToIni(IniFile &file) {
739-
Section *controls = file.GetOrCreateSection("ControlMapping");
744+
void SaveToIni(IniFile &file, const char *section) {
745+
Section *controls = file.GetOrCreateSection(section);
740746

741747
for (size_t i = 0; i < ARRAY_SIZE(psp_button_names); i++) {
742748
std::vector<KeyDef> keys;

Core/KeyMap.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ enum {
7070
VIRTKEY_SPEED_ANALOG = 0x40000024,
7171
VIRTKEY_VR_CAMERA_ADJUST = 0x40000025,
7272
VIRTKEY_VR_CAMERA_RESET = 0x40000026,
73+
VIRTKEY_CONTROLLER_PROFILE_1 = 0x40000027,
74+
VIRTKEY_CONTROLLER_PROFILE_2 = 0x40000028,
75+
VIRTKEY_CONTROLLER_PROFILE_3 = 0x40000029,
76+
VIRTKEY_CONTROLLER_PROFILE_4 = 0x4000002A,
77+
VIRTKEY_CONTROLLER_PROFILE_5 = 0x4000002B,
7378
VIRTKEY_LAST,
7479
VIRTKEY_COUNT = VIRTKEY_LAST - VIRTKEY_FIRST
7580
};
@@ -146,8 +151,8 @@ namespace KeyMap {
146151
bool AxisFromPspButton(int btn, int *deviceId, int *axisId, int *direction);
147152
MappedAnalogAxes MappedAxesForDevice(int deviceId);
148153

149-
void LoadFromIni(IniFile &iniFile);
150-
void SaveToIni(IniFile &iniFile);
154+
void LoadFromIni(IniFile &iniFile, const char *section = "ControlMapping");
155+
void SaveToIni(IniFile &iniFile, const char *section = "ControlMapping");
151156

152157
void SetDefaultKeyMap(DefaultMaps dmap, bool replace);
153158

UI/EmuScreen.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,26 @@ void EmuScreen::onVKeyDown(int virtualKeyCode) {
735735
case VIRTKEY_SCREEN_ROTATION_HORIZONTAL180:
736736
g_Config.iInternalScreenRotation = ROTATION_LOCKED_HORIZONTAL180;
737737
break;
738+
case VIRTKEY_CONTROLLER_PROFILE_1:
739+
g_Config.LoadControllerProfile(1);
740+
RecreateViews();
741+
break;
742+
case VIRTKEY_CONTROLLER_PROFILE_2:
743+
g_Config.LoadControllerProfile(2);
744+
RecreateViews();
745+
break;
746+
case VIRTKEY_CONTROLLER_PROFILE_3:
747+
g_Config.LoadControllerProfile(3);
748+
RecreateViews();
749+
break;
750+
case VIRTKEY_CONTROLLER_PROFILE_4:
751+
g_Config.LoadControllerProfile(4);
752+
RecreateViews();
753+
break;
754+
case VIRTKEY_CONTROLLER_PROFILE_5:
755+
g_Config.LoadControllerProfile(5);
756+
RecreateViews();
757+
break;
738758
}
739759
}
740760

UI/GameSettingsScreen.cpp

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -726,6 +726,11 @@ void GameSettingsScreen::CreateViews() {
726726
controlsSettings->Add(new Choice(co->T("Control Mapping")))->OnClick.Handle(this, &GameSettingsScreen::OnControlMapping);
727727
controlsSettings->Add(new Choice(co->T("Calibrate Analog Stick")))->OnClick.Handle(this, &GameSettingsScreen::OnCalibrateAnalogs);
728728

729+
controlsSettings->Add(new Choice(co->T("Control Profiles")))->OnClick.Add([=](EventParams &e) {
730+
screenManager()->push(new ControllerProfileScreen());
731+
return UI::EVENT_DONE;
732+
});
733+
729734
#if defined(USING_WIN_UI)
730735
controlsSettings->Add(new CheckBox(&g_Config.bSystemControls, co->T("Enable standard shortcut keys")));
731736
controlsSettings->Add(new CheckBox(&g_Config.bGamepadOnlyFocused, co->T("Ignore gamepads when not focused")));
@@ -2279,3 +2284,56 @@ void GestureMappingScreen::CreateViews() {
22792284
vert->Add(new ItemHeader(co->T("Double tap")));
22802285
vert->Add(new PopupMultiChoice(&g_Config.iDoubleTapGesture, mc->T("Double tap button"), gestureButton, 0, ARRAY_SIZE(gestureButton), mc->GetName(), screenManager()))->SetEnabledPtr(&g_Config.bGestureControlEnabled);
22812286
}
2287+
2288+
void ControllerProfileScreen::CreateViews() {
2289+
using namespace UI;
2290+
2291+
auto co = GetI18NCategory("Controls");
2292+
2293+
root_ = new AnchorLayout(new LayoutParams(FILL_PARENT, FILL_PARENT));
2294+
AddStandardBack(root_);
2295+
TabHolder *tabHolder = new TabHolder(ORIENT_VERTICAL, 200, new AnchorLayoutParams(10, 0, 10, 0, false));
2296+
root_->Add(tabHolder);
2297+
ScrollView *rightPanel = new ScrollView(ORIENT_VERTICAL);
2298+
tabHolder->AddTab(co->T("Profiles"), rightPanel);
2299+
LinearLayout *vert = rightPanel->Add(new LinearLayout(ORIENT_VERTICAL, new LayoutParams(FILL_PARENT, FILL_PARENT)));
2300+
vert->SetSpacing(0);
2301+
2302+
float leftSide = 40.0f;
2303+
if (dp_yres <= dp_xres * 1.1f) {
2304+
leftSide += 200.0f;
2305+
}
2306+
settingInfo_ = new SettingInfoMessage(ALIGN_CENTER | FLAG_WRAP_TEXT, new AnchorLayoutParams(dp_xres - leftSide - 40.0f, WRAP_CONTENT, leftSide, dp_yres - 80.0f - 40.0f, NONE, NONE));
2307+
settingInfo_->SetBottomCutoff(dp_yres - 200.0f);
2308+
root_->Add(settingInfo_);
2309+
2310+
static constexpr int MAX_PROFILE = 5; // Should we have 5 with binding for fast selection and unlimited just to have them?
2311+
for (int i = 1; i <= MAX_PROFILE; ++i) {
2312+
vert->Add(new ItemHeader(ReplaceAll(co->T("Profile %1"), "%1", std::to_string(i))));
2313+
2314+
Choice *save = new Choice(co->T("Save current control settings"));
2315+
Choice *load = new Choice(co->T("Load control profile"));
2316+
2317+
load->OnClick.Add([=](EventParams &e) {
2318+
if (g_Config.LoadControllerProfile(i))
2319+
settingInfo_->Show(co->T("Control profile loaded"), e.v);
2320+
2321+
return UI::EVENT_CONTINUE;
2322+
});
2323+
2324+
save->OnClick.Add([=](EventParams &e) {
2325+
if (g_Config.SaveControllerProfile(i)) {
2326+
settingInfo_->Show(co->T("Control profile saved"), e.v);
2327+
load->SetEnabled(true);
2328+
}
2329+
2330+
return UI::EVENT_CONTINUE;
2331+
});
2332+
2333+
// Not a func to avoid Android slow IO problems
2334+
load->SetEnabled(g_Config.ControllerProfileExist(i));
2335+
vert->Add(save);
2336+
vert->Add(load);
2337+
}
2338+
}
2339+

UI/GameSettingsScreen.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,3 +254,12 @@ class GestureMappingScreen : public UIDialogScreenWithBackground {
254254

255255
const char *tag() const override { return "GestureMapping"; }
256256
};
257+
258+
class ControllerProfileScreen : public UIDialogScreenWithBackground {
259+
public:
260+
void CreateViews() override;
261+
262+
const char *tag() const override { return "ControllerProfile"; }
263+
private:
264+
SettingInfoMessage *settingInfo_;
265+
};

0 commit comments

Comments
 (0)