Merge upstream main (v0.2.31) into openxr-work

Brings in 25 upstream commits: Dolphin-compatible input expressions and
GCPadNew.ini import, NAND setting.txt console identity, empty-MKW-save
handling, rumble toggle, LLVM 22, and CI caching.

The only conflict was runtime/CMakeLists.txt, where both sides appended
test targets after mkw_platform_paths_tests. Both blocks are kept: the VR
first-person test alongside upstream's NAND save/settings, SC serial, and
input expression tests.

runtime_config.h and settings_overlay.cpp auto-merged; the VR settings
menu, recenter hotkey, and stereo/first-person init calls are intact
alongside upstream's InputBindings wiring.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
iChris4andClaude Opus 5 committed 2026-09-08 22:32:59 +02:00
commit a138670b37
46 files changed
+2866 -364

No files matched your search

+34 -1
View File
@@ -11,6 +11,7 @@
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <optional>
#include <sstream>
#include <string>
@@ -108,6 +109,8 @@ struct RuntimeUserConfig {
// comma-separated SDL-style physical button names ("south", or
// "dpad_up,left_shoulder") as values; pressing either bound button counts.
std::array<std::optional<std::string>, 12> controllerButtons;
std::optional<bool> rumbleEnabled;
std::map<std::string, std::string> controllerExpressions;
};
namespace RuntimeConfigFile {
@@ -507,6 +510,17 @@ inline RuntimeUserConfig ParseConfigDocument(const toml::value& document) {
FindConfigValue<std::string>(document, "controller", buttonKeys[index]);
}
config.rumbleEnabled = FindConfigValue<bool>(document, "controller", "rumble");
if (const auto* section = document.contains("controller") ? &document.at("controller") : nullptr;
section != nullptr && section->is_table()) {
for (const auto& [key, value] : section->as_table()) {
if (key.rfind("expr_", 0) == 0 && value.is_string()) {
config.controllerExpressions[key] = value.as_string();
}
}
}
config.widescreen = FindConfigValue<bool>(document, "video", "widescreen");
config.windowPosX = FindConfigInt(document, "video", "window_x");
config.windowPosY = FindConfigInt(document, "video", "window_y");
@@ -927,6 +941,25 @@ inline bool SetControllerButton(size_t index, std::string value) {
return WriteSetting("controller", kControllerButtonKeys[index], FormatString(value));
}
inline std::string ControllerExpression(const std::string& key) {
const auto it = Get().controllerExpressions.find(key);
return it == Get().controllerExpressions.end() ? std::string() : it->second;
}
inline bool SetControllerExpression(const std::string& key, const std::string& value) {
Mutable().controllerExpressions[key] = value;
return WriteSetting("controller", key, FormatString(value));
}
inline bool RumbleEnabled(bool fallback = true) {
return Get().rumbleEnabled.value_or(fallback);
}
inline bool SetRumbleEnabled(bool value) {
Mutable().rumbleEnabled = value;
return WriteSetting("controller", "rumble", value ? "true" : "false");
}
inline bool SetAudioVolume(float value) {
value = std::clamp(value, 0.0f, 1.0f);
Mutable().audioVolume = value;
@@ -1054,7 +1087,7 @@ inline bool SetWiiRemotesEnabled(bool value) {
}
// Whether to keep rescanning Bluetooth while no Wii controller is connected.
inline bool WiiContinuousScanEnabled(bool fallback = true) {
inline bool WiiContinuousScanEnabled(bool fallback = false) {
return Get().wiiContinuousScan.value_or(fallback);
}