Replace unmaintained cpptoml with toml++

This commit is contained in:
James Benton 2022-01-23 15:42:05 +00:00
parent 1b94896a21
commit f0276954be
16 changed files with 429 additions and 447 deletions

6
.gitmodules vendored
View file

@ -31,9 +31,6 @@
[submodule "libraries/catch"] [submodule "libraries/catch"]
path = libraries/catch path = libraries/catch
url = https://github.com/philsquared/Catch.git url = https://github.com/philsquared/Catch.git
[submodule "libraries/cpptoml"]
path = libraries/cpptoml
url = https://github.com/decaf-emu/cpptoml.git
[submodule "libraries/cpp-peglib"] [submodule "libraries/cpp-peglib"]
path = libraries/cpp-peglib path = libraries/cpp-peglib
url = https://github.com/yhirose/cpp-peglib.git url = https://github.com/yhirose/cpp-peglib.git
@ -46,3 +43,6 @@
[submodule "libraries/qtads"] [submodule "libraries/qtads"]
path = libraries/qtads path = libraries/qtads
url = https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System.git url = https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System.git
[submodule "libraries/tomlplusplus"]
path = libraries/tomlplusplus
url = https://github.com/marzer/tomlplusplus.git

View file

@ -31,12 +31,6 @@ add_library(cnl INTERFACE IMPORTED GLOBAL)
set_target_properties(cnl PROPERTIES set_target_properties(cnl PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/cnl/include") INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/cnl/include")
# cpptoml
add_library(cpptoml INTERFACE IMPORTED GLOBAL)
set_target_properties(cpptoml PROPERTIES
INTERFACE_COMPILE_DEFINITIONS "CPPTOML_USE_MAP"
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/cpptoml/include")
# excmd # excmd
add_library(excmd INTERFACE IMPORTED GLOBAL) add_library(excmd INTERFACE IMPORTED GLOBAL)
set_target_properties(excmd PROPERTIES set_target_properties(excmd PROPERTIES
@ -94,6 +88,11 @@ set(SPDLOG_FMT_EXTERNAL ON CACHE BOOL "Use external fmt library instead of bundl
add_subdirectory(spdlog) add_subdirectory(spdlog)
set_target_properties(spdlog PROPERTIES FOLDER libraries) set_target_properties(spdlog PROPERTIES FOLDER libraries)
# tomlplusplus
add_library(tomlplusplus INTERFACE IMPORTED GLOBAL)
set_target_properties(tomlplusplus PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/tomlplusplus/include")
# Qt Advanced Docking System # Qt Advanced Docking System
if(DECAF_QT) if(DECAF_QT)
set(BUILD_STATIC TRUE CACHE BOOL "ADS: Build the static library") set(BUILD_STATIC TRUE CACHE BOOL "ADS: Build the static library")

@ -1 +0,0 @@
Subproject commit 5a6d92731aa8c2d1b2eb2741b1ea982967f77029

@ -0,0 +1 @@
Subproject commit 8e669aa6990e0ed219c169d491472d749f54c393

View file

@ -11,22 +11,17 @@ int timeout_ms = 0;
} // namespace system } // namespace system
bool bool
loadFrontendToml(std::shared_ptr<cpptoml::table> config) loadFrontendToml(const toml::table &config)
{ {
system::timeout_ms = config->get_qualified_as<int>("system.timeout_ms").value_or(system::timeout_ms); readValue(config, "system.timeout_ms", system::timeout_ms);
return true; return true;
} }
bool bool
saveFrontendToml(std::shared_ptr<cpptoml::table> config) saveFrontendToml(toml::table &config)
{ {
auto system = config->get_table("system"); auto system = config.insert("system", toml::table()).first->second.as_table();
if (!system) {
system = cpptoml::make_table();
}
system->insert("timeout_ms", system::timeout_ms); system->insert("timeout_ms", system::timeout_ms);
config->insert("system", system);
return true; return true;
} }

View file

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <libconfig/config_toml.h> #include <libconfig/config_toml.h>
#include <string> #include <string>
#include <toml++/toml.h>
namespace config namespace config
{ {
@ -13,9 +14,9 @@ extern int timeout_ms;
} // namespace system } // namespace system
bool bool
loadFrontendToml(std::shared_ptr<cpptoml::table> config); loadFrontendToml(const toml::table &config);
bool bool
saveFrontendToml(std::shared_ptr<cpptoml::table> config); saveFrontendToml(toml::table &config);
} // namespace config } // namespace config

View file

@ -11,6 +11,7 @@
#include <libdecaf/decaf.h> #include <libdecaf/decaf.h>
#include <libdecaf/decaf_log.h> #include <libdecaf/decaf_log.h>
#include <spdlog/sinks/stdout_sinks.h> #include <spdlog/sinks/stdout_sinks.h>
#include <toml++/toml.h>
std::shared_ptr<spdlog::logger> std::shared_ptr<spdlog::logger>
gCliLog; gCliLog;
@ -115,22 +116,22 @@ start(excmd::parser &parser,
// If config file does not exist, create a default one. // If config file does not exist, create a default one.
if (!platform::fileExists(configPath)) { if (!platform::fileExists(configPath)) {
auto toml = cpptoml::make_table(); auto toml = toml::table();
config::saveToTOML(toml, cpuSettings); config::saveToTOML(toml, cpuSettings);
config::saveToTOML(toml, gpuSettings); config::saveToTOML(toml, gpuSettings);
config::saveToTOML(toml, decafSettings); config::saveToTOML(toml, decafSettings);
config::saveFrontendToml(toml); config::saveFrontendToml(toml);
std::ofstream out { configPath }; std::ofstream out { configPath };
out << (*toml); out << toml;
} }
try { try {
auto toml = cpptoml::parse_file(configPath); auto toml = toml::parse_file(configPath);
config::loadFromTOML(toml, cpuSettings); config::loadFromTOML(toml, cpuSettings);
config::loadFromTOML(toml, gpuSettings); config::loadFromTOML(toml, gpuSettings);
config::loadFromTOML(toml, decafSettings); config::loadFromTOML(toml, decafSettings);
config::loadFrontendToml(toml); config::loadFrontendToml(toml);
} catch (cpptoml::parse_exception ex) { } catch (const toml::parse_error &ex) {
configError = ex.what(); configError = ex.what();
} }

View file

@ -7,7 +7,6 @@
#include <array> #include <array>
#include <libdecaf/decaf_input.h> #include <libdecaf/decaf_input.h>
#include <mutex> #include <mutex>
#include <cpptoml.h>
class QKeyEvent; class QKeyEvent;
class SettingsStorage; class SettingsStorage;

View file

@ -3,20 +3,21 @@
#include <libconfig/config_toml.h> #include <libconfig/config_toml.h>
#include <optional> #include <optional>
#include <toml++/toml.h>
static bool loadFromTOML(std::shared_ptr<cpptoml::table> config, static bool loadFromTOML(const toml::table &config,
InputConfiguration &inputConfiguration); InputConfiguration &inputConfiguration);
static bool saveToTOML(std::shared_ptr<cpptoml::table> config, static bool saveToTOML(toml::table &config,
const InputConfiguration &inputConfiguration); const InputConfiguration &inputConfiguration);
static bool loadFromTOML(std::shared_ptr<cpptoml::table> config, static bool loadFromTOML(const toml::table &config,
SoundSettings &soundSettings); SoundSettings &soundSettings);
static bool saveToTOML(std::shared_ptr<cpptoml::table> config, static bool saveToTOML(toml::table &config,
const SoundSettings &soundSettings); const SoundSettings &soundSettings);
static bool loadFromTOML(std::shared_ptr<cpptoml::table> config, static bool loadFromTOML(const toml::table &config,
UiSettings &uiSettings); UiSettings &uiSettings);
static bool saveToTOML(std::shared_ptr<cpptoml::table> config, static bool saveToTOML(toml::table &config,
const UiSettings &uiSettings); const UiSettings &uiSettings);
bool bool
@ -24,7 +25,7 @@ loadSettings(const std::string &path,
Settings &settings) Settings &settings)
{ {
try { try {
auto toml = cpptoml::parse_file(path); toml::table toml = toml::parse_file(path);
config::loadFromTOML(toml, settings.cpu); config::loadFromTOML(toml, settings.cpu);
config::loadFromTOML(toml, settings.decaf); config::loadFromTOML(toml, settings.decaf);
config::loadFromTOML(toml, settings.gpu); config::loadFromTOML(toml, settings.gpu);
@ -32,7 +33,7 @@ loadSettings(const std::string &path,
loadFromTOML(toml, settings.sound); loadFromTOML(toml, settings.sound);
loadFromTOML(toml, settings.ui); loadFromTOML(toml, settings.ui);
return true; return true;
} catch (cpptoml::parse_exception ex) { } catch (const toml::parse_error &) {
return false; return false;
} }
} }
@ -41,12 +42,11 @@ bool
saveSettings(const std::string &path, saveSettings(const std::string &path,
const Settings &settings) const Settings &settings)
{ {
auto toml = std::shared_ptr<cpptoml::table> { }; toml::table toml;
try { try {
// Read current file and modify that // Read current file and modify that
toml = cpptoml::parse_file(path); toml = toml::parse_file(path);
} catch (cpptoml::parse_exception ex) { } catch (const toml::parse_error &) {
toml = cpptoml::make_table();
} }
// Update it // Update it
@ -63,7 +63,7 @@ saveSettings(const std::string &path,
return false; return false;
} }
out << (*toml); out << toml;
return true; return true;
} }
@ -129,105 +129,111 @@ getConfigButtonName(ButtonType type)
} }
bool bool
loadFromTOML(std::shared_ptr<cpptoml::table> config, loadFromTOML(const toml::table &config,
InputConfiguration &inputConfiguration) InputConfiguration &inputConfiguration)
{ {
auto controllers = config->get_table_array_qualified("input.controller"); auto controllers = config.at_path("input.controller").as_array();
if (!controllers) {
return true;
}
if (controllers) { for (const auto &controllerConfig : *controllers) {
for (const auto &controllerConfig : *controllers) { auto controllerConfigTable = controllerConfig.as_table();
auto controllerType = controllerConfig->get_as<std::string>("type").value_or(""); if (!controllerConfigTable) {
auto &controller = inputConfiguration.controllers.emplace_back(); continue;
}
auto &controller = inputConfiguration.controllers.emplace_back();
if (controllerType == "gamepad") { auto controllerType = controllerConfigTable->get_as<std::string>("type");
controller.type = ControllerType::Gamepad; if (!controllerType) {
} else if (controllerType == "wiimote") { continue;
controller.type = ControllerType::WiiMote; } else if (**controllerType == "gamepad") {
} else if (controllerType == "pro") { controller.type = ControllerType::Gamepad;
controller.type = ControllerType::ProController; } else if (**controllerType == "wiimote") {
} else if (controllerType == "classic") { controller.type = ControllerType::WiiMote;
controller.type = ControllerType::ClassicController; } else if (**controllerType == "pro") {
} else { controller.type = ControllerType::ProController;
continue; } else if (**controllerType == "classic") {
} controller.type = ControllerType::ClassicController;
} else {
continue;
}
auto readInputConfig = [](std::shared_ptr<cpptoml::table> controllerConfig, InputConfiguration::Controller &controller, ButtonType buttonType) auto readInputConfig =
[](const toml::table &controllerConfig,
InputConfiguration::Controller &controller,
ButtonType buttonType)
{ {
auto &input = controller.inputs[static_cast<size_t>(buttonType)]; auto &input = controller.inputs[static_cast<size_t>(buttonType)];
auto buttonConfig = controllerConfig->get_table(getConfigButtonName(buttonType)); auto buttonConfig = controllerConfig.get_as<toml::table>(getConfigButtonName(buttonType));
if (buttonConfig) { if (buttonConfig) {
if (auto guid = buttonConfig->get_as<std::string>("sdl_joystick_guid"); guid) { if (auto guid = buttonConfig->get_as<std::string>("sdl_joystick_guid"); guid) {
input.joystickGuid = SDL_JoystickGetGUIDFromString(guid->c_str()); input.joystickGuid = SDL_JoystickGetGUIDFromString(guid->get().c_str());
} }
if (auto id = buttonConfig->get_as<int>("sdl_joystick_duplicate_id"); id) { if (auto id = buttonConfig->get_as<int64_t>("sdl_joystick_duplicate_id"); id) {
input.joystickDuplicateId = *id; input.joystickDuplicateId = id->get();
} }
if (auto key = buttonConfig->get_as<int>("key"); key) { if (auto key = buttonConfig->get_as<int64_t>("key"); key) {
input.source = InputConfiguration::Input::KeyboardKey; input.source = InputConfiguration::Input::KeyboardKey;
input.id = *key; input.id = key->get();
} }
if (auto button = buttonConfig->get_as<int>("button"); button) { if (auto button = buttonConfig->get_as<int64_t>("button"); button) {
input.source = InputConfiguration::Input::JoystickButton; input.source = InputConfiguration::Input::JoystickButton;
input.id = *button; input.id = button->get();
} }
if (auto axis = buttonConfig->get_as<int>("axis"); axis) { if (auto axis = buttonConfig->get_as<int64_t>("axis"); axis) {
input.source = InputConfiguration::Input::JoystickAxis; input.source = InputConfiguration::Input::JoystickAxis;
input.id = *axis; input.id = axis->get();
} }
if (auto hat = buttonConfig->get_as<int>("hat"); hat) { if (auto hat = buttonConfig->get_as<int64_t>("hat"); hat) {
input.source = InputConfiguration::Input::JoystickHat; input.source = InputConfiguration::Input::JoystickHat;
input.id = *hat; input.id = hat->get();
input.hatValue = 0; input.hatValue = 0;
} }
if (auto hatValue = buttonConfig->get_as<int>("hat_value"); hatValue) { if (auto hatValue = buttonConfig->get_as<int64_t>("hat_value"); hatValue) {
input.hatValue = *hatValue; input.hatValue = hatValue->get();
} }
if (auto invert = buttonConfig->get_as<bool>("invert"); invert) { if (auto invert = buttonConfig->get_as<bool>("invert"); invert) {
input.invert = *invert; input.invert = invert->get();
} }
} }
}; };
for (auto i = 0u; i < static_cast<size_t>(ButtonType::MaxButtonType); ++i) { for (auto i = 0u; i < static_cast<size_t>(ButtonType::MaxButtonType); ++i) {
readInputConfig(controllerConfig, controller, static_cast<ButtonType>(i)); readInputConfig(*controllerConfigTable, controller, static_cast<ButtonType>(i));
}
} }
} }
return true; return true;
} }
bool bool
saveToTOML(std::shared_ptr<cpptoml::table> config, saveToTOML(toml::table &config,
const InputConfiguration &inputConfiguration) const InputConfiguration &inputConfiguration)
{ {
auto input = config->get_table("input"); auto input = config.insert("input", toml::table()).first->second.as_table();
if (!input) {
input = cpptoml::make_table();
}
auto controllers = cpptoml::make_table_array(); auto controllers = toml::array();
if (input->get_table_array("controller")) { if (input->contains("controller")) {
input->erase("controller"); input->erase("controller");
} }
for (auto &controller : inputConfiguration.controllers) { for (auto &controller : inputConfiguration.controllers) {
auto controllerConfig = cpptoml::make_table(); auto controllerConfig = toml::table();
if (controller.type == ControllerType::Gamepad) { if (controller.type == ControllerType::Gamepad) {
controllerConfig->insert("type", "gamepad"); controllerConfig.insert("type", "gamepad");
} else if (controller.type == ControllerType::WiiMote) { } else if (controller.type == ControllerType::WiiMote) {
controllerConfig->insert("type", "wiimote"); controllerConfig.insert("type", "wiimote");
} else if (controller.type == ControllerType::ProController) { } else if (controller.type == ControllerType::ProController) {
controllerConfig->insert("type", "pro"); controllerConfig.insert("type", "pro");
} else if (controller.type == ControllerType::ClassicController) { } else if (controller.type == ControllerType::ClassicController) {
controllerConfig->insert("type", "classic"); controllerConfig.insert("type", "classic");
} else { } else {
continue; continue;
} }
@ -235,68 +241,57 @@ saveToTOML(std::shared_ptr<cpptoml::table> config,
for (auto i = 0u; i < static_cast<size_t>(ButtonType::MaxButtonType); ++i) { for (auto i = 0u; i < static_cast<size_t>(ButtonType::MaxButtonType); ++i) {
auto buttonType = static_cast<ButtonType>(i); auto buttonType = static_cast<ButtonType>(i);
auto &input = controller.inputs[i]; auto &input = controller.inputs[i];
auto inputConfig = cpptoml::make_table(); auto inputConfig = toml::table();
if (input.source == InputConfiguration::Input::Unassigned) { if (input.source == InputConfiguration::Input::Unassigned) {
continue; continue;
} else if (input.source == InputConfiguration::Input::KeyboardKey) { } else if (input.source == InputConfiguration::Input::KeyboardKey) {
inputConfig->insert("key", input.id); inputConfig.insert("key", input.id);
} else if (input.source == InputConfiguration::Input::JoystickAxis) { } else if (input.source == InputConfiguration::Input::JoystickAxis) {
char guidBuffer[33]; char guidBuffer[33];
SDL_JoystickGetGUIDString(input.joystickGuid, guidBuffer, 33); SDL_JoystickGetGUIDString(input.joystickGuid, guidBuffer, 33);
inputConfig->insert("sdl_joystick_guid", guidBuffer); inputConfig.insert("sdl_joystick_guid", guidBuffer);
inputConfig->insert("sdl_joystick_duplicate_id", input.joystickDuplicateId); inputConfig.insert("sdl_joystick_duplicate_id", input.joystickDuplicateId);
inputConfig->insert("axis", input.id); inputConfig.insert("axis", input.id);
inputConfig->insert("invert", input.invert); inputConfig.insert("invert", input.invert);
} else if (input.source == InputConfiguration::Input::JoystickButton) { } else if (input.source == InputConfiguration::Input::JoystickButton) {
char guidBuffer[33]; char guidBuffer[33];
SDL_JoystickGetGUIDString(input.joystickGuid, guidBuffer, 33); SDL_JoystickGetGUIDString(input.joystickGuid, guidBuffer, 33);
inputConfig->insert("sdl_joystick_guid", guidBuffer); inputConfig.insert("sdl_joystick_guid", guidBuffer);
inputConfig->insert("sdl_joystick_duplicate_id", input.joystickDuplicateId); inputConfig.insert("sdl_joystick_duplicate_id", input.joystickDuplicateId);
inputConfig->insert("button", input.id); inputConfig.insert("button", input.id);
} else if (input.source == InputConfiguration::Input::JoystickHat) { } else if (input.source == InputConfiguration::Input::JoystickHat) {
char guidBuffer[33]; char guidBuffer[33];
SDL_JoystickGetGUIDString(input.joystickGuid, guidBuffer, 33); SDL_JoystickGetGUIDString(input.joystickGuid, guidBuffer, 33);
inputConfig->insert("sdl_joystick_guid", guidBuffer); inputConfig.insert("sdl_joystick_guid", guidBuffer);
inputConfig->insert("sdl_joystick_duplicate_id", input.joystickDuplicateId); inputConfig.insert("sdl_joystick_duplicate_id", input.joystickDuplicateId);
inputConfig->insert("hat", input.id); inputConfig.insert("hat", input.id);
inputConfig->insert("hat_value", input.hatValue); inputConfig.insert("hat_value", input.hatValue);
} }
controllerConfig->insert(getConfigButtonName(buttonType), inputConfig); controllerConfig.insert(getConfigButtonName(buttonType), inputConfig);
} }
controllers->push_back(controllerConfig); controllers.push_back(std::move(controllerConfig));
} }
input->insert("controller", controllers); input->insert("controller", std::move(controllers));
config->insert("input", input);
return true; return true;
} }
bool bool
loadFromTOML(std::shared_ptr<cpptoml::table> config, loadFromTOML(const toml::table &config,
SoundSettings &soundSettings) SoundSettings &soundSettings)
{ {
if (auto sound = config->get_table("sound")) { config::readValue(config, "sound.playback_enabled", soundSettings.playbackEnabled);
if (auto playbackEnabled = sound->get_as<bool>("playback_enabled"); playbackEnabled) {
soundSettings.playbackEnabled = *playbackEnabled;
}
}
return true; return true;
} }
bool bool
saveToTOML(std::shared_ptr<cpptoml::table> config, saveToTOML(toml::table &config,
const SoundSettings &soundSettings) const SoundSettings &soundSettings)
{ {
auto sound = config->get_table("sound"); auto sound = config.insert("sound", toml::table()).first->second.as_table();
if (!sound) {
sound = cpptoml::make_table();
}
sound->insert("playback_enabled", soundSettings.playbackEnabled); sound->insert("playback_enabled", soundSettings.playbackEnabled);
config->insert("sound", sound);
return true; return true;
} }
@ -326,33 +321,27 @@ translateTitleListMode(const std::string &text)
} }
bool bool
loadFromTOML(std::shared_ptr<cpptoml::table> config, loadFromTOML(const toml::table &config,
UiSettings &uiSettings) UiSettings &uiSettings)
{ {
if (auto ui = config->get_table("ui")) { std::string titleListModeText;
if (auto text = ui->get_as<std::string>("title_list_mode"); text) { config::readValue(config, "ui.title_list_mode", titleListModeText);
if (auto mode = translateTitleListMode(*text); mode) { if (auto mode = translateTitleListMode(titleListModeText); mode) {
uiSettings.titleListMode = *mode; uiSettings.titleListMode = *mode;
}
}
} }
return true; return true;
} }
bool bool
saveToTOML(std::shared_ptr<cpptoml::table> config, saveToTOML(toml::table &config,
const UiSettings &uiSettings) const UiSettings &uiSettings)
{ {
auto ui = config->get_table("ui"); auto ui = config.insert("ui", toml::table()).first->second.as_table();
if (!ui) {
ui = cpptoml::make_table();
}
if (auto text = translateTitleListMode(uiSettings.titleListMode); text) { if (auto text = translateTitleListMode(uiSettings.titleListMode); text) {
ui->insert("title_list_mode", text); ui->insert("title_list_mode", text);
} }
config->insert("ui", ui);
return true; return true;
} }

View file

@ -78,14 +78,18 @@ setupDefaultInputDevices()
device.button_minus = SDL_SCANCODE_2; device.button_minus = SDL_SCANCODE_2;
device.button_home = SDL_SCANCODE_3; device.button_home = SDL_SCANCODE_3;
device.button_sync = SDL_SCANCODE_4; device.button_sync = SDL_SCANCODE_4;
device.keyboard.left_stick_up = SDL_SCANCODE_KP_8;
device.keyboard.left_stick_down = SDL_SCANCODE_KP_2; input::InputDeviceKeyboard keyboard;
device.keyboard.left_stick_left = SDL_SCANCODE_KP_4; keyboard.left_stick_up = SDL_SCANCODE_KP_8;
device.keyboard.left_stick_right = SDL_SCANCODE_KP_6; keyboard.left_stick_down = SDL_SCANCODE_KP_2;
device.keyboard.right_stick_up = -1; keyboard.left_stick_left = SDL_SCANCODE_KP_4;
device.keyboard.right_stick_down = -1; keyboard.left_stick_right = SDL_SCANCODE_KP_6;
device.keyboard.right_stick_left = -1; keyboard.right_stick_up = -1;
device.keyboard.right_stick_right = -1; keyboard.right_stick_down = -1;
keyboard.right_stick_left = -1;
keyboard.right_stick_right = -1;
device.typeExtra = keyboard;
input::devices.push_back(device); input::devices.push_back(device);
} }
@ -113,195 +117,191 @@ setupDefaultInputDevices()
device.button_minus = -2; device.button_minus = -2;
device.button_home = -2; device.button_home = -2;
device.button_sync = -2; device.button_sync = -2;
device.joystick.left_stick_x = -2;
device.joystick.left_stick_x_invert = false; input::InputDeviceJoystick joystick;
device.joystick.left_stick_y = -2; joystick.left_stick_x = -2;
device.joystick.left_stick_y_invert = false; joystick.left_stick_x_invert = false;
device.joystick.right_stick_x = -2; joystick.left_stick_y = -2;
device.joystick.right_stick_x_invert = false; joystick.left_stick_y_invert = false;
device.joystick.right_stick_y = -2; joystick.right_stick_x = -2;
device.joystick.right_stick_y_invert = false; joystick.right_stick_x_invert = false;
joystick.right_stick_y = -2;
joystick.right_stick_y_invert = false;
device.typeExtra = joystick;
input::devices.push_back(device); input::devices.push_back(device);
} }
} }
bool bool
loadFrontendToml(std::shared_ptr<cpptoml::table> config) loadFrontendToml(const toml::table &config)
{ {
// input // input
auto devices = config->get_table_array_qualified("input.devices"); auto devices = config.at_path("input.devices").as_array();
input::devices.clear(); input::devices.clear();
if (devices) { if (devices) {
for (const auto &cfgDevice : *devices) { for (auto itr = devices->begin(); itr != devices->end(); ++itr) {
auto cfgDevice = itr->as_table();
config::input::InputDevice device; config::input::InputDevice device;
auto type = cfgDevice->get_as<std::string>("type").value_or("");
if (type == "keyboard") { auto type = cfgDevice->get_as<std::string>("type");
if (!type) {
continue;
} else if (type->get() == "keyboard") {
device.type = config::input::ControllerType::Keyboard; device.type = config::input::ControllerType::Keyboard;
} else if (type == "joystick") { } else if (type->get() == "joystick") {
device.type = config::input::ControllerType::Joystick; device.type = config::input::ControllerType::Joystick;
} else { } else {
continue; continue;
} }
device.id = cfgDevice->get_as<std::string>("id").value_or(""); readValue(*cfgDevice, "id", device.id);
device.device_name = cfgDevice->get_as<std::string>("device_name").value_or(""); readValue(*cfgDevice, "device_name", device.device_name);
device.button_up = cfgDevice->get_as<int>("button_up").value_or(-1); readValue(*cfgDevice, "button_up", device.button_up);
device.button_down = cfgDevice->get_as<int>("button_down").value_or(-1); readValue(*cfgDevice, "button_down", device.button_down);
device.button_left = cfgDevice->get_as<int>("button_left").value_or(-1); readValue(*cfgDevice, "button_left", device.button_left);
device.button_right = cfgDevice->get_as<int>("button_right").value_or(-1); readValue(*cfgDevice, "button_right", device.button_right);
device.button_a = cfgDevice->get_as<int>("button_a").value_or(-1); readValue(*cfgDevice, "button_a", device.button_a);
device.button_b = cfgDevice->get_as<int>("button_b").value_or(-1); readValue(*cfgDevice, "button_b", device.button_b);
device.button_x = cfgDevice->get_as<int>("button_x").value_or(-1); readValue(*cfgDevice, "button_x", device.button_x);
device.button_y = cfgDevice->get_as<int>("button_y").value_or(-1); readValue(*cfgDevice, "button_y", device.button_y);
device.button_trigger_r = cfgDevice->get_as<int>("button_trigger_r").value_or(-1); readValue(*cfgDevice, "button_trigger_r", device.button_trigger_r);
device.button_trigger_l = cfgDevice->get_as<int>("button_trigger_l").value_or(-1); readValue(*cfgDevice, "button_trigger_l", device.button_trigger_l);
device.button_trigger_zr = cfgDevice->get_as<int>("button_trigger_zr").value_or(-1); readValue(*cfgDevice, "button_trigger_zr", device.button_trigger_zr);
device.button_trigger_zl = cfgDevice->get_as<int>("button_trigger_zl").value_or(-1); readValue(*cfgDevice, "button_trigger_zl", device.button_trigger_zl);
device.button_stick_l = cfgDevice->get_as<int>("button_stick_l").value_or(-1); readValue(*cfgDevice, "button_stick_l", device.button_stick_l);
device.button_stick_r = cfgDevice->get_as<int>("button_stick_r").value_or(-1); readValue(*cfgDevice, "button_stick_r", device.button_stick_r);
device.button_plus = cfgDevice->get_as<int>("button_plus").value_or(-1); readValue(*cfgDevice, "button_plus", device.button_plus);
device.button_minus = cfgDevice->get_as<int>("button_minus").value_or(-1); readValue(*cfgDevice, "button_minus", device.button_minus);
device.button_home = cfgDevice->get_as<int>("button_home").value_or(-1); readValue(*cfgDevice, "button_home", device.button_home);
device.button_sync = cfgDevice->get_as<int>("button_sync").value_or(-1); readValue(*cfgDevice, "button_sync", device.button_sync);
if (device.type == config::input::ControllerType::Keyboard) { if (device.type == config::input::ControllerType::Keyboard) {
device.keyboard.left_stick_up = cfgDevice->get_as<int>("left_stick_up").value_or(-1); auto keyboard = config::input::InputDeviceKeyboard {};
device.keyboard.left_stick_down = cfgDevice->get_as<int>("left_stick_down").value_or(-1); readValue(*cfgDevice, "left_stick_up", keyboard.left_stick_up);
device.keyboard.left_stick_left = cfgDevice->get_as<int>("left_stick_left").value_or(-1); readValue(*cfgDevice, "left_stick_down", keyboard.left_stick_down);
device.keyboard.left_stick_right = cfgDevice->get_as<int>("left_stick_right").value_or(-1); readValue(*cfgDevice, "left_stick_left", keyboard.left_stick_left);
device.keyboard.right_stick_up = cfgDevice->get_as<int>("right_stick_up").value_or(-1); readValue(*cfgDevice, "left_stick_right", keyboard.left_stick_right);
device.keyboard.right_stick_down = cfgDevice->get_as<int>("right_stick_down").value_or(-1);
device.keyboard.right_stick_left = cfgDevice->get_as<int>("right_stick_left").value_or(-1); readValue(*cfgDevice, "right_stick_up", keyboard.right_stick_up);
device.keyboard.right_stick_right = cfgDevice->get_as<int>("right_stick_right").value_or(-1); readValue(*cfgDevice, "right_stick_down", keyboard.right_stick_down);
readValue(*cfgDevice, "right_stick_left", keyboard.right_stick_left);
readValue(*cfgDevice, "right_stick_right", keyboard.right_stick_right);
device.typeExtra = keyboard;
} else if (device.type == config::input::ControllerType::Joystick) { } else if (device.type == config::input::ControllerType::Joystick) {
device.joystick.left_stick_x = cfgDevice->get_as<int>("left_stick_x").value_or(-1); auto joystick = config::input::InputDeviceJoystick {};
device.joystick.left_stick_x_invert = cfgDevice->get_as<bool>("left_stick_x_invert").value_or(false); readValue(*cfgDevice, "left_stick_x", joystick.left_stick_x);
device.joystick.left_stick_y = cfgDevice->get_as<int>("left_stick_y").value_or(-1); readValue(*cfgDevice, "left_stick_x_invert", joystick.left_stick_x_invert);
device.joystick.left_stick_y_invert = cfgDevice->get_as<bool>("left_stick_y_invert").value_or(false); readValue(*cfgDevice, "left_stick_y", joystick.left_stick_y);
device.joystick.right_stick_x = cfgDevice->get_as<int>("right_stick_x").value_or(-1); readValue(*cfgDevice, "left_stick_y_invert", joystick.left_stick_y_invert);
device.joystick.right_stick_x_invert = cfgDevice->get_as<bool>("right_stick_x_invert").value_or(false);
device.joystick.right_stick_y = cfgDevice->get_as<int>("right_stick_y").value_or(-1); readValue(*cfgDevice, "right_stick_x", joystick.right_stick_x);
device.joystick.right_stick_y_invert = cfgDevice->get_as<bool>("right_stick_y_invert").value_or(false); readValue(*cfgDevice, "right_stick_x_invert", joystick.right_stick_x_invert);
readValue(*cfgDevice, "right_stick_y", joystick.right_stick_y);
readValue(*cfgDevice, "right_stick_y_invert", joystick.right_stick_y_invert);
device.typeExtra = joystick;
} }
config::input::devices.push_back(device); config::input::devices.push_back(device);
} }
} }
config::input::vpad0 = config->get_qualified_as<std::string>("input.vpad0").value_or(config::input::vpad0); readValue(config, "input.vpad0", config::input::vpad0);
setupDefaultInputDevices(); setupDefaultInputDevices();
// sound // sound
config::sound::frame_length = config->get_qualified_as<unsigned int>("sound.frame_length").value_or(config::sound::frame_length); readValue(config, "sound.frame_length", config::sound::frame_length);
// test // test
config::test::timeout_ms = config->get_qualified_as<int>("test.timeout_ms").value_or(config::test::timeout_ms); readValue(config, "test.timeout_ms", config::test::timeout_ms);
config::test::timeout_frames = config->get_qualified_as<int>("test.timeout_frames").value_or(config::test::timeout_frames); readValue(config, "test.timeout_frames", config::test::timeout_frames);
config::test::dump_drc_frames = config->get_qualified_as<bool>("test.dump_drc_frames").value_or(config::test::dump_drc_frames); readValue(config, "test.dump_drc_frames", config::test::dump_drc_frames);
config::test::dump_tv_frames = config->get_qualified_as<bool>("test.dump_tv_frames").value_or(config::test::dump_tv_frames); readValue(config, "test.dump_tv_frames", config::test::dump_tv_frames);
config::test::dump_frames_dir = config->get_qualified_as<std::string>("test.dump_frames_dir").value_or(config::test::dump_frames_dir); readValue(config, "test.dump_frames_dir", config::test::dump_frames_dir);
return true; return true;
} }
bool bool
saveFrontendToml(std::shared_ptr<cpptoml::table> config) saveFrontendToml(toml::table &config)
{ {
setupDefaultInputDevices(); setupDefaultInputDevices();
// input // input
auto input = config->get_table("input"); auto input = config.insert("input", toml::table()).first->second.as_table();
if (!input) {
input = cpptoml::make_table();
}
input->insert("vpad0", config::input::vpad0); input->insert("vpad0", config::input::vpad0);
auto devices = config->get_table_array("devices"); auto devices = config.insert("devices", toml::array()).first->second.as_array();
if (!devices) {
devices = cpptoml::make_table_array();
}
for (const auto &device : config::input::devices) { for (const auto &device : config::input::devices) {
auto cfgDevice = cpptoml::make_table(); auto cfgDevice = toml::table();
if (device.type == config::input::ControllerType::Joystick) { if (device.type == config::input::ControllerType::Joystick) {
cfgDevice->insert("type", "joystick"); cfgDevice.insert("type", "joystick");
} else if (device.type == config::input::ControllerType::Keyboard) { } else if (device.type == config::input::ControllerType::Keyboard) {
cfgDevice->insert("type", "keyboard"); cfgDevice.insert("type", "keyboard");
} else { } else {
cfgDevice->insert("type", "unknown"); cfgDevice.insert("type", "unknown");
} }
cfgDevice->insert("id", device.id); cfgDevice.insert("id", device.id);
cfgDevice->insert("device_name", device.device_name); cfgDevice.insert("device_name", device.device_name);
cfgDevice->insert("button_up", device.button_up); cfgDevice.insert("button_up", device.button_up);
cfgDevice->insert("button_down", device.button_down); cfgDevice.insert("button_down", device.button_down);
cfgDevice->insert("button_left", device.button_left); cfgDevice.insert("button_left", device.button_left);
cfgDevice->insert("button_right", device.button_right); cfgDevice.insert("button_right", device.button_right);
cfgDevice->insert("button_a", device.button_a); cfgDevice.insert("button_a", device.button_a);
cfgDevice->insert("button_b", device.button_b); cfgDevice.insert("button_b", device.button_b);
cfgDevice->insert("button_x", device.button_x); cfgDevice.insert("button_x", device.button_x);
cfgDevice->insert("button_y", device.button_y); cfgDevice.insert("button_y", device.button_y);
cfgDevice->insert("button_trigger_r", device.button_trigger_r); cfgDevice.insert("button_trigger_r", device.button_trigger_r);
cfgDevice->insert("button_trigger_l", device.button_trigger_l); cfgDevice.insert("button_trigger_l", device.button_trigger_l);
cfgDevice->insert("button_trigger_zr", device.button_trigger_zr); cfgDevice.insert("button_trigger_zr", device.button_trigger_zr);
cfgDevice->insert("button_trigger_zl", device.button_trigger_zl); cfgDevice.insert("button_trigger_zl", device.button_trigger_zl);
cfgDevice->insert("button_stick_l", device.button_stick_l); cfgDevice.insert("button_stick_l", device.button_stick_l);
cfgDevice->insert("button_stick_r", device.button_stick_r); cfgDevice.insert("button_stick_r", device.button_stick_r);
cfgDevice->insert("button_plus", device.button_plus); cfgDevice.insert("button_plus", device.button_plus);
cfgDevice->insert("button_minus", device.button_minus); cfgDevice.insert("button_minus", device.button_minus);
cfgDevice->insert("button_home", device.button_home); cfgDevice.insert("button_home", device.button_home);
cfgDevice->insert("button_sync", device.button_sync); cfgDevice.insert("button_sync", device.button_sync);
if (device.type == config::input::ControllerType::Keyboard) { if (device.type == config::input::ControllerType::Keyboard) {
cfgDevice->insert("left_stick_up", device.keyboard.left_stick_up); const auto &keyboard =
cfgDevice->insert("left_stick_down", device.keyboard.left_stick_down); std::get<config::input::InputDeviceKeyboard>(device.typeExtra);
cfgDevice->insert("left_stick_left", device.keyboard.left_stick_left); cfgDevice.insert("left_stick_up", keyboard.left_stick_up);
cfgDevice->insert("left_stick_right", device.keyboard.left_stick_right); cfgDevice.insert("left_stick_down", keyboard.left_stick_down);
cfgDevice->insert("right_stick_up", device.keyboard.right_stick_up); cfgDevice.insert("left_stick_left", keyboard.left_stick_left);
cfgDevice->insert("right_stick_down", device.keyboard.right_stick_down); cfgDevice.insert("left_stick_right", keyboard.left_stick_right);
cfgDevice->insert("right_stick_left", device.keyboard.right_stick_left); cfgDevice.insert("right_stick_up", keyboard.right_stick_up);
cfgDevice->insert("right_stick_right", device.keyboard.right_stick_right); cfgDevice.insert("right_stick_down", keyboard.right_stick_down);
cfgDevice.insert("right_stick_left", keyboard.right_stick_left);
cfgDevice.insert("right_stick_right", keyboard.right_stick_right);
} else if (device.type == config::input::ControllerType::Joystick) { } else if (device.type == config::input::ControllerType::Joystick) {
cfgDevice->insert("left_stick_x", device.joystick.left_stick_x); const auto &joystick =
cfgDevice->insert("left_stick_x_invert", device.joystick.left_stick_x_invert); std::get<config::input::InputDeviceJoystick>(device.typeExtra);
cfgDevice->insert("left_stick_y", device.joystick.left_stick_y); cfgDevice.insert("left_stick_x", joystick.left_stick_x);
cfgDevice->insert("left_stick_y_invert", device.joystick.left_stick_y_invert); cfgDevice.insert("left_stick_x_invert", joystick.left_stick_x_invert);
cfgDevice->insert("right_stick_x", device.joystick.right_stick_x); cfgDevice.insert("left_stick_y", joystick.left_stick_y);
cfgDevice->insert("right_stick_x_invert", device.joystick.right_stick_x_invert); cfgDevice.insert("left_stick_y_invert", joystick.left_stick_y_invert);
cfgDevice->insert("right_stick_y", device.joystick.right_stick_y); cfgDevice.insert("right_stick_x", joystick.right_stick_x);
cfgDevice->insert("right_stick_y_invert", device.joystick.right_stick_y_invert); cfgDevice.insert("right_stick_x_invert", joystick.right_stick_x_invert);
cfgDevice.insert("right_stick_y", joystick.right_stick_y);
cfgDevice.insert("right_stick_y_invert", joystick.right_stick_y_invert);
} }
devices->push_back(cfgDevice); devices->push_back(cfgDevice);
} }
input->insert("devices", devices);
config->insert("input", input);
// sound // sound
auto sound = config->get_table("sound"); auto sound = config.insert("sound", toml::table()).first->second.as_table();
if (!sound) {
sound = cpptoml::make_table();
}
sound->insert("frame_length", config::sound::frame_length); sound->insert("frame_length", config::sound::frame_length);
config->insert("sound", sound);
// test // test
auto test = config->get_table("test"); auto test = config.insert("test", toml::table()).first->second.as_table();
if (!test) {
test = cpptoml::make_table();
}
test->insert("timeout_ms", config::test::timeout_ms); test->insert("timeout_ms", config::test::timeout_ms);
test->insert("timeout_frames", config::test::timeout_frames); test->insert("timeout_frames", config::test::timeout_frames);
test->insert("dump_drc_frames", config::test::dump_drc_frames); test->insert("dump_drc_frames", config::test::dump_drc_frames);
test->insert("dump_tv_frames", config::test::dump_tv_frames); test->insert("dump_tv_frames", config::test::dump_tv_frames);
test->insert("dump_frames_dir", config::test::dump_frames_dir); test->insert("dump_frames_dir", config::test::dump_frames_dir);
config->insert("test", test);
return true; return true;
} }

View file

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <libconfig/config_toml.h> #include <libconfig/config_toml.h>
#include <string> #include <string>
#include <variant>
#include <vector> #include <vector>
namespace config namespace config
@ -16,62 +17,67 @@ enum ControllerType
Joystick, Joystick,
}; };
/*
* For keyboard input, each entry is an SDL_SCANCODE_ *constant; for
* joystick input, each entry is the button number, or -2 to let SDL
* choose an appropriate button. In both cases, -1 means nothing is
* assigned.
*/
struct InputDeviceKeyboard
{
int left_stick_up = -1;
int left_stick_down = -1;
int left_stick_left = -1;
int left_stick_right = -1;
int right_stick_up = -1;
int right_stick_down = -1;
int right_stick_left = -1;
int right_stick_right = -1;
};
struct InputDeviceJoystick
{
int left_stick_x = -1;
bool left_stick_x_invert = false;
int left_stick_y = -1;
bool left_stick_y_invert = false;
int right_stick_x = -1;
bool right_stick_x_invert = false;
int right_stick_y = -1;
bool right_stick_y_invert = false;
};
struct InputDevice struct InputDevice
{ {
ControllerType type; ControllerType type;
std::string id; std::string id;
std::string device_name; std::string device_name;
// For keyboard input, each entry is an SDL_SCANCODE_* constant; for int button_up = -1;
// joystick input, each entry is the button number, or -2 to let SDL int button_down = -1;
// choose an appropriate button. In both cases, -1 means nothing is int button_left = -1;
// assigned. int button_right = -1;
int button_a = -1;
int button_b = -1;
int button_x = -1;
int button_y = -1;
int button_trigger_r = -1;
int button_trigger_l = -1;
int button_trigger_zr = -1;
int button_trigger_zl = -1;
int button_stick_l = -1;
int button_stick_r = -1;
int button_plus = -1;
int button_minus = -1;
int button_home = -1;
int button_sync = -1;
int button_up; std::variant<InputDeviceKeyboard, InputDeviceJoystick> typeExtra;
int button_down;
int button_left;
int button_right;
int button_a;
int button_b;
int button_x;
int button_y;
int button_trigger_r;
int button_trigger_l;
int button_trigger_zr;
int button_trigger_zl;
int button_stick_l;
int button_stick_r;
int button_plus;
int button_minus;
int button_home;
int button_sync;
union
{
struct
{
int left_stick_up;
int left_stick_down;
int left_stick_left;
int left_stick_right;
int right_stick_up;
int right_stick_down;
int right_stick_left;
int right_stick_right;
} keyboard;
struct
{
int left_stick_x;
bool left_stick_x_invert;
int left_stick_y;
bool left_stick_y_invert;
int right_stick_x;
bool right_stick_x_invert;
int right_stick_y;
bool right_stick_y_invert;
} joystick;
};
}; };
extern std::vector<InputDevice> devices; extern std::vector<InputDevice> devices;
@ -112,9 +118,9 @@ void
setupDefaultInputDevices(); setupDefaultInputDevices();
bool bool
loadFrontendToml(std::shared_ptr<cpptoml::table> config); loadFrontendToml(const toml::table &config);
bool bool
saveFrontendToml(std::shared_ptr<cpptoml::table> config); saveFrontendToml(toml::table &config);
} // namespace config } // namespace config

View file

@ -104,35 +104,36 @@ DecafSDL::sampleVpadController(int channel, vpad::Status &status)
status.rightStickX = 0.0f; status.rightStickX = 0.0f;
status.rightStickY = 0.0f; status.rightStickY = 0.0f;
if (getState(device->keyboard.left_stick_up)) { auto &deviceKeyboard = std::get<config::input::InputDeviceKeyboard>(device->typeExtra);
if (getState(deviceKeyboard.left_stick_up)) {
status.leftStickY += 1.0f; status.leftStickY += 1.0f;
} }
if (getState(device->keyboard.left_stick_down)) { if (getState(deviceKeyboard.left_stick_down)) {
status.leftStickY -= 1.0f; status.leftStickY -= 1.0f;
} }
if (getState(device->keyboard.left_stick_left)) { if (getState(deviceKeyboard.left_stick_left)) {
status.leftStickX -= 1.0f; status.leftStickX -= 1.0f;
} }
if (getState(device->keyboard.left_stick_right)) { if (getState(deviceKeyboard.left_stick_right)) {
status.leftStickX += 1.0f; status.leftStickX += 1.0f;
} }
if (getState(device->keyboard.right_stick_up)) { if (getState(deviceKeyboard.right_stick_up)) {
status.rightStickY += 1.0f; status.rightStickY += 1.0f;
} }
if (getState(device->keyboard.right_stick_down)) { if (getState(deviceKeyboard.right_stick_down)) {
status.rightStickY -= 1.0f; status.rightStickY -= 1.0f;
} }
if (getState(device->keyboard.right_stick_left)) { if (getState(deviceKeyboard.right_stick_left)) {
status.rightStickX -= 1.0f; status.rightStickX -= 1.0f;
} }
if (getState(device->keyboard.right_stick_right)) { if (getState(deviceKeyboard.right_stick_right)) {
status.rightStickX += 1.0f; status.rightStickX += 1.0f;
} }
@ -214,25 +215,26 @@ DecafSDL::sampleVpadController(int channel, vpad::Status &status)
status.buttons.b = getState(device->button_b, SDL_CONTROLLER_BUTTON_A); status.buttons.b = getState(device->button_b, SDL_CONTROLLER_BUTTON_A);
status.buttons.a = getState(device->button_a, SDL_CONTROLLER_BUTTON_B); status.buttons.a = getState(device->button_a, SDL_CONTROLLER_BUTTON_B);
status.leftStickX = getAxis(device->joystick.left_stick_x, SDL_CONTROLLER_AXIS_LEFTX); auto &deviceJoystick = std::get<config::input::InputDeviceJoystick>(device->typeExtra);
status.leftStickY = getAxis(device->joystick.left_stick_y, SDL_CONTROLLER_AXIS_LEFTY); status.leftStickX = getAxis(deviceJoystick.left_stick_x, SDL_CONTROLLER_AXIS_LEFTX);
status.leftStickY = getAxis(deviceJoystick.left_stick_y, SDL_CONTROLLER_AXIS_LEFTY);
if (device->joystick.left_stick_x_invert) { if (deviceJoystick.left_stick_x_invert) {
status.leftStickX = -status.leftStickX; status.leftStickX = -status.leftStickX;
} }
if (device->joystick.left_stick_y_invert) { if (deviceJoystick.left_stick_y_invert) {
status.leftStickY = -status.leftStickY; status.leftStickY = -status.leftStickY;
} }
status.rightStickX = getAxis(device->joystick.right_stick_x, SDL_CONTROLLER_AXIS_RIGHTX); status.rightStickX = getAxis(deviceJoystick.right_stick_x, SDL_CONTROLLER_AXIS_RIGHTX);
status.rightStickY = getAxis(device->joystick.right_stick_y, SDL_CONTROLLER_AXIS_RIGHTY); status.rightStickY = getAxis(deviceJoystick.right_stick_y, SDL_CONTROLLER_AXIS_RIGHTY);
if (device->joystick.right_stick_x_invert) { if (deviceJoystick.right_stick_x_invert) {
status.rightStickX = -status.rightStickX; status.rightStickX = -status.rightStickX;
} }
if (device->joystick.right_stick_y_invert) { if (deviceJoystick.right_stick_y_invert) {
status.rightStickY = -status.rightStickY; status.rightStickY = -status.rightStickY;
} }
} else { } else {

View file

@ -156,22 +156,22 @@ start(excmd::parser &parser,
// If config file does not exist, create a default one. // If config file does not exist, create a default one.
if (!platform::fileExists(configPath)) { if (!platform::fileExists(configPath)) {
auto toml = cpptoml::make_table(); auto toml = toml::table();
config::saveToTOML(toml, cpuSettings); config::saveToTOML(toml, cpuSettings);
config::saveToTOML(toml, gpuSettings); config::saveToTOML(toml, gpuSettings);
config::saveToTOML(toml, decafSettings); config::saveToTOML(toml, decafSettings);
config::saveFrontendToml(toml); config::saveFrontendToml(toml);
std::ofstream out { configPath }; std::ofstream out { configPath };
out << (*toml); out << toml;
} }
try { try {
auto toml = cpptoml::parse_file(configPath); auto toml = toml::parse_file(configPath);
config::loadFromTOML(toml, cpuSettings); config::loadFromTOML(toml, cpuSettings);
config::loadFromTOML(toml, gpuSettings); config::loadFromTOML(toml, gpuSettings);
config::loadFromTOML(toml, decafSettings); config::loadFromTOML(toml, decafSettings);
config::loadFrontendToml(toml); config::loadFrontendToml(toml);
} catch (cpptoml::parse_exception ex) { } catch (const toml::parse_error &ex) {
configError = ex.what(); configError = ex.what();
} }

View file

@ -14,5 +14,5 @@ target_link_libraries(libconfig
libcpu libcpu
libdecaf libdecaf
libgpu libgpu
cpptoml tomlplusplus
excmd) excmd)

View file

@ -1,53 +1,72 @@
#pragma once #pragma once
#include <common/type_traits.h> #include <common/type_traits.h>
#include <cpptoml.h>
#include <libcpu/cpu_config.h> #include <libcpu/cpu_config.h>
#include <libdecaf/decaf_config.h> #include <libdecaf/decaf_config.h>
#include <libgpu/gpu_config.h> #include <libgpu/gpu_config.h>
#include <string> #include <string>
#include <toml++/toml.h>
#include <memory> #include <memory>
#include <type_traits>
namespace config namespace config
{ {
template<typename Type>
inline void
readValue(const std::shared_ptr<cpptoml::table> &config, const char *name, Type &value)
{
value = static_cast<Type>(
config->get_qualified_as<typename safe_underlying_type<Type>::type>(name)
.value_or(static_cast<typename safe_underlying_type<Type>::type>(value)));
}
template<typename Type>
inline void
readArray(const std::shared_ptr<cpptoml::table> &config, const char *name, std::vector<Type> &value)
{
value = config->get_qualified_array_of<Type>(name).value_or(value);
}
bool bool
loadFromTOML(std::shared_ptr<cpptoml::table> config, loadFromTOML(const toml::table &config,
cpu::Settings &cpuSettings); cpu::Settings &cpuSettings);
bool bool
loadFromTOML(std::shared_ptr<cpptoml::table> config, loadFromTOML(const toml::table &config,
decaf::Settings &decafSettings); decaf::Settings &decafSettings);
bool bool
loadFromTOML(std::shared_ptr<cpptoml::table> config, loadFromTOML(const toml::table &config,
gpu::Settings &gpuSettings); gpu::Settings &gpuSettings);
bool bool
saveToTOML(std::shared_ptr<cpptoml::table> config, saveToTOML(toml::table &config,
const cpu::Settings &cpuSettings); const cpu::Settings &cpuSettings);
bool bool
saveToTOML(std::shared_ptr<cpptoml::table> config, saveToTOML(toml::table &config,
const decaf::Settings &decafSettings); const decaf::Settings &decafSettings);
bool bool
saveToTOML(std::shared_ptr<cpptoml::table> config, saveToTOML(toml::table &config,
const gpu::Settings &gpuSettings); const gpu::Settings &gpuSettings);
template<typename Type>
void
readValue(const toml::table &config,
const char *name,
Type &value)
{
auto node = config.at_path(name);
if constexpr (std::is_same_v<Type, bool>) {
if (auto ptr = node.as_boolean()) {
value = ptr->get();
}
} else if constexpr (std::is_integral_v<typename safe_underlying_type<Type>::type>) {
if (auto ptr = node.as_integer()) {
value = static_cast<Type>(ptr->get());
}
} else if constexpr (std::is_floating_point_v<typename safe_underlying_type<Type>::type>) {
if (auto ptr = node.as_floating_point()) {
value = static_cast<Type>(ptr->get());
}
} else if constexpr (std::is_same_v<Type, std::string>) {
if (auto ptr = node.as_string()) {
value = static_cast<Type>(ptr->get());
}
} else {
static_assert(
std::is_same_v<Type, bool> ||
std::is_integral_v<typename safe_underlying_type<Type>::type> ||
std::is_floating_point_v<typename safe_underlying_type<Type>::type> ||
std::is_same_v<Type, std::string>,
"Invalid type passed to readValue");
}
}
} // namespace config } // namespace config

View file

@ -6,6 +6,19 @@
namespace config namespace config
{ {
template<typename Type>
inline void
readArray(const toml::table &config, const char *name, std::vector<Type> &value)
{
auto ptr = config.at_path(name).as_array();
if (ptr) {
value.clear();
for (auto itr = ptr->begin(); itr != ptr->end(); ++itr) {
value.push_back(itr->template as<Type>()->get());
}
}
}
static const char * static const char *
translateDisplayBackend(gpu::DisplaySettings::Backend backend) translateDisplayBackend(gpu::DisplaySettings::Backend backend)
{ {
@ -87,7 +100,7 @@ translateViewMode(const std::string &text)
} }
bool bool
loadFromTOML(std::shared_ptr<cpptoml::table> config, loadFromTOML(const toml::table &config,
cpu::Settings &cpuSettings) cpu::Settings &cpuSettings)
{ {
readValue(config, "mem.writetrack", cpuSettings.memory.writeTrackEnabled); readValue(config, "mem.writetrack", cpuSettings.memory.writeTrackEnabled);
@ -103,7 +116,7 @@ loadFromTOML(std::shared_ptr<cpptoml::table> config,
} }
bool bool
loadFromTOML(std::shared_ptr<cpptoml::table> config, loadFromTOML(const toml::table &config,
decaf::Settings &decafSettings) decaf::Settings &decafSettings)
{ {
readValue(config, "debugger.enabled", decafSettings.debugger.enabled); readValue(config, "debugger.enabled", decafSettings.debugger.enabled);
@ -125,12 +138,12 @@ loadFromTOML(std::shared_ptr<cpptoml::table> config,
readValue(config, "log.to_file", decafSettings.log.to_file); readValue(config, "log.to_file", decafSettings.log.to_file);
readValue(config, "log.to_stdout", decafSettings.log.to_stdout); readValue(config, "log.to_stdout", decafSettings.log.to_stdout);
auto logLevels = config->get_table_qualified("log.levels"); auto logLevels = config.at_path("log.levels").as_table();
if (logLevels) { if (logLevels) {
decafSettings.log.levels.clear(); decafSettings.log.levels.clear();
for (auto item : *logLevels) { for (auto item : *logLevels) {
if (auto level = item.second->as<std::string>()) { if (auto level = item.second.as_string()) {
decafSettings.log.levels.emplace_back(item.first, level->get()); decafSettings.log.levels.emplace_back(item.first, **level);
} }
} }
} }
@ -153,47 +166,47 @@ loadFromTOML(std::shared_ptr<cpptoml::table> config,
} }
bool bool
loadFromTOML(std::shared_ptr<cpptoml::table> config, loadFromTOML(const toml::table &config,
gpu::Settings &gpuSettings) gpu::Settings &gpuSettings)
{ {
readValue(config, "gpu.debug", gpuSettings.debug.debug_enabled); readValue(config, "gpu.debug", gpuSettings.debug.debug_enabled);
readValue(config, "gpu.dump_shaders", gpuSettings.debug.dump_shaders); readValue(config, "gpu.dump_shaders", gpuSettings.debug.dump_shaders);
readValue(config, "gpu.dump_shader_binaries_only", gpuSettings.debug.dump_shader_binaries_only); readValue(config, "gpu.dump_shader_binaries_only", gpuSettings.debug.dump_shader_binaries_only);
auto display = config->get_table("display"); auto display = config.get_as<toml::table>("display");
if (display) { if (display) {
if (auto text = display->get_as<std::string>("backend"); text) { if (auto text = display->get_as<std::string>("backend"); text) {
if (auto backend = translateDisplayBackend(*text); backend) { if (auto backend = translateDisplayBackend(**text); backend) {
gpuSettings.display.backend = *backend; gpuSettings.display.backend = *backend;
} }
} }
if (auto text = display->get_as<std::string>("screen_mode"); text) { if (auto text = display->get_as<std::string>("screen_mode"); text) {
if (auto screenMode = translateScreenMode(*text); screenMode) { if (auto screenMode = translateScreenMode(**text); screenMode) {
gpuSettings.display.screenMode = *screenMode; gpuSettings.display.screenMode = *screenMode;
} }
} }
if (auto text = display->get_as<std::string>("view_mode"); text) { if (auto text = display->get_as<std::string>("view_mode"); text) {
if (auto viewMode = translateViewMode(*text); viewMode) { if (auto viewMode = translateViewMode(**text); viewMode) {
gpuSettings.display.viewMode = *viewMode; gpuSettings.display.viewMode = *viewMode;
} }
} }
if (auto maintainAspectRatio = display->get_as<bool>("maintain_aspect_ratio"); maintainAspectRatio) { if (auto maintainAspectRatio = display->get_as<bool>("maintain_aspect_ratio"); maintainAspectRatio) {
gpuSettings.display.maintainAspectRatio = *maintainAspectRatio; gpuSettings.display.maintainAspectRatio = **maintainAspectRatio;
} }
if (auto splitSeperation = display->get_as<double>("split_seperation"); splitSeperation) { if (auto splitSeperation = display->get_as<double>("split_seperation"); splitSeperation) {
gpuSettings.display.splitSeperation = *splitSeperation; gpuSettings.display.splitSeperation = **splitSeperation;
} }
if (auto backgroundColour = display->get_array_of<int64_t>("background_colour"); if (auto backgroundColour = display->get_as<toml::array>("background_colour");
backgroundColour && backgroundColour->size() >= 3) { backgroundColour && backgroundColour->size() >= 3) {
gpuSettings.display.backgroundColour = { gpuSettings.display.backgroundColour = {
static_cast<int>(backgroundColour->at(0)), static_cast<int>(**backgroundColour->at(0).as_integer()),
static_cast<int>(backgroundColour->at(1)), static_cast<int>(**backgroundColour->at(1).as_integer()),
static_cast<int>(backgroundColour->at(2)) static_cast<int>(**backgroundColour->at(2).as_integer())
}; };
} }
} }
@ -202,13 +215,12 @@ loadFromTOML(std::shared_ptr<cpptoml::table> config,
} }
bool bool
saveToTOML(std::shared_ptr<cpptoml::table> config, saveToTOML(toml::table &config,
const cpu::Settings &cpuSettings) const cpu::Settings &cpuSettings)
{ {
// jit auto jit = config.get_as<toml::table>("jit");
auto jit = config->get_table("jit");
if (!jit) { if (!jit) {
jit = cpptoml::make_table(); jit = config.insert("jit", toml::table()).first->second.as_table();
} }
jit->insert("enabled", cpuSettings.jit.enabled); jit->insert("enabled", cpuSettings.jit.enabled);
@ -218,49 +230,34 @@ saveToTOML(std::shared_ptr<cpptoml::table> config,
jit->insert("data_cache_size_mb", cpuSettings.jit.dataCacheSizeMB); jit->insert("data_cache_size_mb", cpuSettings.jit.dataCacheSizeMB);
jit->insert("rodata_read_only", cpuSettings.jit.rodataReadOnly); jit->insert("rodata_read_only", cpuSettings.jit.rodataReadOnly);
auto opt_flags = cpptoml::make_array(); auto opt_flags = toml::array();
for (auto &flag : cpuSettings.jit.optimisationFlags) { for (auto &flag : cpuSettings.jit.optimisationFlags) {
opt_flags->push_back(flag); opt_flags.push_back(flag);
} }
jit->insert("opt_flags", opt_flags); jit->insert("opt_flags", opt_flags);
config->insert("jit", jit);
return true; return true;
} }
bool bool
saveToTOML(std::shared_ptr<cpptoml::table> config, saveToTOML(toml::table &config,
const decaf::Settings &decafSettings) const decaf::Settings &decafSettings)
{ {
// debugger // debugger
auto debugger = config->get_table("debugger"); auto debugger = config.insert("debugger", toml::table()).first->second.as_table();
if (!debugger) {
debugger = cpptoml::make_table();
}
debugger->insert("enabled", decafSettings.debugger.enabled); debugger->insert("enabled", decafSettings.debugger.enabled);
debugger->insert("break_on_entry", decafSettings.debugger.break_on_entry); debugger->insert("break_on_entry", decafSettings.debugger.break_on_entry);
debugger->insert("break_on_exit", decafSettings.debugger.break_on_exit); debugger->insert("break_on_exit", decafSettings.debugger.break_on_exit);
debugger->insert("gdb_stub", decafSettings.debugger.gdb_stub); debugger->insert("gdb_stub", decafSettings.debugger.gdb_stub);
debugger->insert("gdb_stub_port", decafSettings.debugger.gdb_stub_port); debugger->insert("gdb_stub_port", decafSettings.debugger.gdb_stub_port);
config->insert("debugger", debugger);
// gx2 // gx2
auto gx2 = config->get_table("gx2"); auto gx2 = config.insert("gx2", toml::table()).first->second.as_table();
if (!gx2) {
gx2 = cpptoml::make_table();
}
gx2->insert("dump_textures", decafSettings.gx2.dump_textures); gx2->insert("dump_textures", decafSettings.gx2.dump_textures);
gx2->insert("dump_shaders", decafSettings.gx2.dump_shaders); gx2->insert("dump_shaders", decafSettings.gx2.dump_shaders);
config->insert("gx2", gx2);
// log // log
auto log = config->get_table("log"); auto log = config.insert("log", toml::table()).first->second.as_table();
if (!log) {
log = cpptoml::make_table();
}
log->insert("async", decafSettings.log.async); log->insert("async", decafSettings.log.async);
log->insert("branch_trace", decafSettings.log.branch_trace); log->insert("branch_trace", decafSettings.log.branch_trace);
log->insert("directory", decafSettings.log.directory); log->insert("directory", decafSettings.log.directory);
@ -270,35 +267,25 @@ saveToTOML(std::shared_ptr<cpptoml::table> config,
log->insert("to_file", decafSettings.log.to_file); log->insert("to_file", decafSettings.log.to_file);
log->insert("to_stdout", decafSettings.log.to_stdout); log->insert("to_stdout", decafSettings.log.to_stdout);
auto levels = cpptoml::make_table(); auto levels = toml::table();
for (auto item : decafSettings.log.levels) { for (auto item : decafSettings.log.levels) {
levels->insert(item.first, item.second); levels.insert(item.first, item.second);
} }
log->insert("levels", levels); log->insert("levels", std::move(levels));
auto hle_trace_filters = cpptoml::make_array(); auto hle_trace_filters = toml::array();
for (auto &filter : decafSettings.log.hle_trace_filters) { for (auto &filter : decafSettings.log.hle_trace_filters) {
hle_trace_filters->push_back(filter); hle_trace_filters.push_back(filter);
} }
log->insert("hle_trace_filters", hle_trace_filters); log->insert("hle_trace_filters", std::move(hle_trace_filters));
config->insert("log", log);
// sound // sound
auto sound = config->get_table("sound"); auto sound = config.insert("sound", toml::table()).first->second.as_table();
if (!sound) {
sound = cpptoml::make_table();
}
sound->insert("dump_sounds", decafSettings.sound.dump_sounds); sound->insert("dump_sounds", decafSettings.sound.dump_sounds);
config->insert("sound", sound);
// system // system
auto system = config->get_table("system"); auto system = config.insert("system", toml::table()).first->second.as_table();
if (!system) {
system = cpptoml::make_table();
}
system->insert("region", static_cast<int>(decafSettings.system.region)); system->insert("region", static_cast<int>(decafSettings.system.region));
system->insert("hfio_path", decafSettings.system.hfio_path); system->insert("hfio_path", decafSettings.system.hfio_path);
system->insert("mlc_path", decafSettings.system.mlc_path); system->insert("mlc_path", decafSettings.system.mlc_path);
@ -309,59 +296,43 @@ saveToTOML(std::shared_ptr<cpptoml::table> config,
system->insert("content_path", decafSettings.system.content_path); system->insert("content_path", decafSettings.system.content_path);
system->insert("time_scale", decafSettings.system.time_scale); system->insert("time_scale", decafSettings.system.time_scale);
auto lle_modules = cpptoml::make_array(); auto lle_modules = toml::array();
for (auto &name : decafSettings.system.lle_modules) { for (auto &name : decafSettings.system.lle_modules) {
lle_modules->push_back(name); lle_modules.push_back(name);
} }
system->insert("lle_modules", std::move(lle_modules));
system->insert("lle_modules", lle_modules); auto title_directories = toml::array();
auto title_directories = cpptoml::make_array();
for (auto &name : decafSettings.system.title_directories) { for (auto &name : decafSettings.system.title_directories) {
title_directories->push_back(name); title_directories.push_back(name);
} }
system->insert("title_directories", std::move(title_directories));
system->insert("title_directories", title_directories);
config->insert("system", system);
return true; return true;
} }
bool bool
saveToTOML(std::shared_ptr<cpptoml::table> config, saveToTOML(toml::table &config,
const gpu::Settings &gpuSettings) const gpu::Settings &gpuSettings)
{ {
// gpu // gpu
auto gpu = config->get_table("gpu"); auto gpu = config.insert("gpu", toml::table()).first->second.as_table();
if (!gpu) {
gpu = cpptoml::make_table();
}
gpu->insert("debug", gpuSettings.debug.debug_enabled); gpu->insert("debug", gpuSettings.debug.debug_enabled);
gpu->insert("dump_shaders", gpuSettings.debug.dump_shaders); gpu->insert("dump_shaders", gpuSettings.debug.dump_shaders);
gpu->insert("dump_shader_binaries_only", gpuSettings.debug.dump_shader_binaries_only); gpu->insert("dump_shader_binaries_only", gpuSettings.debug.dump_shader_binaries_only);
config->insert("gpu", gpu);
// display // display
auto display = config->get_table("display"); auto display = config.insert("display", toml::table()).first->second.as_table();
if (!display) {
display = cpptoml::make_table();
}
display->insert("backend", translateDisplayBackend(gpuSettings.display.backend)); display->insert("backend", translateDisplayBackend(gpuSettings.display.backend));
display->insert("screen_mode", translateScreenMode(gpuSettings.display.screenMode)); display->insert("screen_mode", translateScreenMode(gpuSettings.display.screenMode));
display->insert("view_mode", translateViewMode(gpuSettings.display.viewMode)); display->insert("view_mode", translateViewMode(gpuSettings.display.viewMode));
display->insert("maintain_aspect_ratio", gpuSettings.display.maintainAspectRatio); display->insert("maintain_aspect_ratio", gpuSettings.display.maintainAspectRatio);
display->insert("split_seperation", gpuSettings.display.splitSeperation); display->insert("split_seperation", gpuSettings.display.splitSeperation);
auto backgroundColour = cpptoml::make_array(); auto backgroundColour = toml::array();
backgroundColour->push_back(gpuSettings.display.backgroundColour[0]); backgroundColour.push_back(gpuSettings.display.backgroundColour[0]);
backgroundColour->push_back(gpuSettings.display.backgroundColour[1]); backgroundColour.push_back(gpuSettings.display.backgroundColour[1]);
backgroundColour->push_back(gpuSettings.display.backgroundColour[2]); backgroundColour.push_back(gpuSettings.display.backgroundColour[2]);
display->insert("background_colour", backgroundColour); display->insert("background_colour", std::move(backgroundColour));
config->insert("display", display);
return true; return true;
} }