Files
dolphin/Source/Core/Core/ConfigLoaders/BaseConfigLoader.cpp
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

237 lines
7.5 KiB
C++
Raw Normal View History

2016-01-27 18:08:58 -06:00
// Copyright 2016 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
2016-01-27 18:08:58 -06:00
2017-06-08 00:53:59 -04:00
#include "Core/ConfigLoaders/BaseConfigLoader.h"
2019-06-30 12:44:38 +02:00
#include <algorithm>
2016-01-27 18:08:58 -06:00
#include <cstring>
#include <functional>
2016-01-27 18:08:58 -06:00
#include <list>
#include <map>
2017-06-06 23:36:16 -04:00
#include <memory>
2016-01-27 18:08:58 -06:00
#include <string>
2017-08-01 22:37:42 +08:00
#include <type_traits>
#include <variant>
2016-01-27 18:08:58 -06:00
#include "Common/CommonTypes.h"
#include "Common/Config/Config.h"
#include "Common/FileUtil.h"
#include "Common/IniFile.h"
#include "Common/Logging/Log.h"
#include "Core/Config/MainSettings.h"
2017-08-01 22:37:42 +08:00
#include "Core/Config/SYSCONFSettings.h"
#include "Core/ConfigLoaders/IsSettingSaveable.h"
#include "Core/ConfigManager.h"
2017-08-01 22:37:42 +08:00
#include "Core/Core.h"
#include "Core/IOS/IOS.h"
2017-08-01 22:37:42 +08:00
#include "Core/IOS/USB/Bluetooth/BTBase.h"
2018-03-11 11:43:54 +01:00
#include "Core/SysConf.h"
2016-01-27 18:08:58 -06:00
namespace ConfigLoaders
{
void SaveToSYSCONF(Config::LayerType layer, std::function<bool(const Config::Location&)> predicate)
2017-08-01 22:37:42 +08:00
{
if (Core::IsRunning())
return;
IOS::HLE::Kernel ios;
SysConf sysconf{ios.GetFS()};
2017-08-01 22:37:42 +08:00
for (const Config::SYSCONFSetting& setting : Config::SYSCONF_SETTINGS)
{
std::visit(
[&](auto* info) {
if (predicate && !predicate(info->GetLocation()))
return;
2020-09-20 19:11:20 +02:00
const std::string key = info->GetLocation().section + "." + info->GetLocation().key;
2017-08-01 22:37:42 +08:00
if (setting.type == SysConf::Entry::Type::Long)
2019-06-30 12:44:38 +02:00
{
2020-09-20 19:11:20 +02:00
sysconf.SetData<u32>(key, setting.type, Config::Get(layer, *info));
2019-06-30 12:44:38 +02:00
}
2017-08-01 22:37:42 +08:00
else if (setting.type == SysConf::Entry::Type::Byte)
2019-06-30 12:44:38 +02:00
{
2020-09-20 19:11:20 +02:00
sysconf.SetData<u8>(key, setting.type, static_cast<u8>(Config::Get(layer, *info)));
2019-06-30 12:44:38 +02:00
}
else if (setting.type == SysConf::Entry::Type::BigArray)
{
// Somewhat hacky support for IPL.SADR. The setting only stores the
// first 4 bytes even thought the SYSCONF entry is much bigger.
SysConf::Entry* entry = sysconf.GetOrAddEntry(key, setting.type);
if (entry->bytes.size() < 0x1007 + 1)
entry->bytes.resize(0x1007 + 1);
2020-09-20 19:11:20 +02:00
*reinterpret_cast<u32*>(entry->bytes.data()) = Config::Get(layer, *info);
2019-06-30 12:44:38 +02:00
}
2017-08-01 22:37:42 +08:00
},
setting.config_info);
}
sysconf.SetData<u32>("IPL.CB", SysConf::Entry::Type::Long, 0);
2017-08-01 22:37:42 +08:00
// Disable WiiConnect24's standby mode. If it is enabled, it prevents us from receiving
// shutdown commands in the State Transition Manager (STM).
// TODO: remove this if and once Dolphin supports WC24 standby mode.
SysConf::Entry* idle_entry = sysconf.GetOrAddEntry("IPL.IDL", SysConf::Entry::Type::SmallArray);
if (idle_entry->bytes.empty())
idle_entry->bytes = std::vector<u8>(2);
else
idle_entry->bytes[0] = 0;
2020-11-18 06:01:15 -05:00
NOTICE_LOG_FMT(CORE, "Disabling WC24 'standby' (shutdown to idle) to avoid hanging on shutdown");
2017-08-01 22:37:42 +08:00
IOS::HLE::RestoreBTInfoSection(&sysconf);
sysconf.Save();
}
2016-01-27 18:08:58 -06:00
const std::map<Config::System, int> system_to_ini = {
{Config::System::Main, F_DOLPHINCONFIG_IDX},
{Config::System::GCPad, F_GCPADCONFIG_IDX},
{Config::System::WiiPad, F_WIIPADCONFIG_IDX},
{Config::System::GCKeyboard, F_GCKEYBOARDCONFIG_IDX},
{Config::System::GFX, F_GFXCONFIG_IDX},
{Config::System::Logger, F_LOGGERCONFIG_IDX},
{Config::System::Debugger, F_DEBUGGERCONFIG_IDX},
{Config::System::DualShockUDPClient, F_DUALSHOCKUDPCLIENTCONFIG_IDX},
2020-07-22 19:19:35 -05:00
{Config::System::FreeLook, F_FREELOOKCONFIG_IDX},
2021-06-09 20:16:41 +02:00
// Config::System::Session should not be added to this list
2016-01-27 18:08:58 -06:00
};
// INI layer configuration loader
2017-08-01 22:37:42 +08:00
class BaseConfigLayerLoader final : public Config::ConfigLayerLoader
2016-01-27 18:08:58 -06:00
{
public:
2017-08-01 22:37:42 +08:00
BaseConfigLayerLoader() : ConfigLayerLoader(Config::LayerType::Base) {}
2017-10-29 19:11:15 +00:00
void Load(Config::Layer* layer) override
2016-01-27 18:08:58 -06:00
{
// List of settings that under no circumstances should be loaded from the global config INI.
static const auto s_setting_disallowed = {
&Config::MAIN_MEMORY_CARD_SIZE.GetLocation(),
};
2017-10-29 19:11:15 +00:00
LoadFromSYSCONF(layer);
2016-01-27 18:08:58 -06:00
for (const auto& system : system_to_ini)
{
IniFile ini;
ini.Load(File::GetUserPath(system.second));
const std::list<IniFile::Section>& system_sections = ini.GetSections();
for (const auto& section : system_sections)
{
const std::string section_name = section.GetName();
const IniFile::Section::SectionMap& section_map = section.GetValues();
for (const auto& value : section_map)
2017-10-29 19:11:15 +00:00
{
const Config::Location location{system.first, section_name, value.first};
const bool load_disallowed =
std::any_of(begin(s_setting_disallowed), end(s_setting_disallowed),
[&location](const Config::Location* l) { return *l == location; });
if (load_disallowed)
continue;
2017-10-29 19:11:15 +00:00
layer->Set(location, value.second);
}
2016-01-27 18:08:58 -06:00
}
}
}
2017-10-29 19:11:15 +00:00
void Save(Config::Layer* layer) override
2016-01-27 18:08:58 -06:00
{
2017-10-29 19:11:15 +00:00
SaveToSYSCONF(layer->GetLayer());
2017-08-01 22:37:42 +08:00
2017-10-29 19:11:15 +00:00
std::map<Config::System, IniFile> inis;
for (const auto& system : system_to_ini)
{
inis[system.first].Load(File::GetUserPath(system.second));
}
for (const auto& config : layer->GetLayerMap())
{
const Config::Location& location = config.first;
2017-10-29 19:11:15 +00:00
const std::optional<std::string>& value = config.second;
// Done by SaveToSYSCONF
if (location.system == Config::System::SYSCONF)
continue;
2021-06-09 20:16:41 +02:00
if (location.system == Config::System::Session)
continue;
2017-10-29 19:11:15 +00:00
auto ini = inis.find(location.system);
if (ini == inis.end())
2016-01-27 18:08:58 -06:00
{
2020-11-18 06:01:15 -05:00
ERROR_LOG_FMT(COMMON, "Config can't map system '{}' to an INI file!",
Config::GetSystemName(location.system));
2016-01-27 18:08:58 -06:00
continue;
}
2017-10-29 19:11:15 +00:00
if (!IsSettingSaveable(location))
continue;
2016-01-27 18:08:58 -06:00
2017-10-29 19:11:15 +00:00
if (value)
2016-01-27 18:08:58 -06:00
{
2017-10-29 19:11:15 +00:00
IniFile::Section* ini_section = ini->second.GetOrCreateSection(location.section);
ini_section->Set(location.key, *value);
2016-01-27 18:08:58 -06:00
}
2017-10-29 19:11:15 +00:00
else
{
ini->second.DeleteKey(location.section, location.key);
}
}
2016-01-27 18:08:58 -06:00
2017-10-29 19:11:15 +00:00
for (const auto& system : system_to_ini)
{
inis[system.first].Save(File::GetUserPath(system.second));
2016-01-27 18:08:58 -06:00
}
}
2017-08-01 22:37:42 +08:00
private:
void LoadFromSYSCONF(Config::Layer* layer)
{
if (Core::IsRunning())
return;
IOS::HLE::Kernel ios;
SysConf sysconf{ios.GetFS()};
2017-08-01 22:37:42 +08:00
for (const Config::SYSCONFSetting& setting : Config::SYSCONF_SETTINGS)
{
std::visit(
2020-09-20 19:11:20 +02:00
[&](auto* info) {
const Config::Location location = info->GetLocation();
2020-09-20 13:58:17 +02:00
const std::string key = location.section + "." + location.key;
2017-08-01 22:37:42 +08:00
if (setting.type == SysConf::Entry::Type::Long)
2019-06-30 12:44:38 +02:00
{
2020-09-20 19:11:20 +02:00
layer->Set(location, sysconf.GetData<u32>(key, info->GetDefaultValue()));
2019-06-30 12:44:38 +02:00
}
2017-08-01 22:37:42 +08:00
else if (setting.type == SysConf::Entry::Type::Byte)
2019-06-30 12:44:38 +02:00
{
2020-09-20 19:11:20 +02:00
layer->Set(location, sysconf.GetData<u8>(key, info->GetDefaultValue()));
2019-06-30 12:44:38 +02:00
}
else if (setting.type == SysConf::Entry::Type::BigArray)
{
// Somewhat hacky support for IPL.SADR. The setting only stores the
// first 4 bytes even thought the SYSCONF entry is much bigger.
2020-09-20 19:11:20 +02:00
u32 value = info->GetDefaultValue();
2019-06-30 12:44:38 +02:00
SysConf::Entry* entry = sysconf.GetEntry(key);
if (entry)
{
std::memcpy(&value, entry->bytes.data(),
std::min(entry->bytes.size(), sizeof(u32)));
}
2020-09-20 13:58:17 +02:00
layer->Set(location, value);
2019-06-30 12:44:38 +02:00
}
2017-08-01 22:37:42 +08:00
},
setting.config_info);
}
}
2016-01-27 18:08:58 -06:00
};
// Loader generation
std::unique_ptr<Config::ConfigLayerLoader> GenerateBaseConfigLoader()
{
2017-08-01 22:37:42 +08:00
return std::make_unique<BaseConfigLayerLoader>();
2016-01-27 18:08:58 -06:00
}
} // namespace ConfigLoaders