diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 9c73f6473..0be317ff0 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -55,7 +55,7 @@ add_library(core
target_include_directories(core PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/..")
target_include_directories(core PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/..")
-target_link_libraries(core PRIVATE Threads::Threads YBaseLib common imgui glad stb)
+target_link_libraries(core PRIVATE Threads::Threads YBaseLib common imgui glad simpleini stb)
if(WIN32)
target_sources(core PRIVATE
diff --git a/src/core/core.vcxproj b/src/core/core.vcxproj
index 21bc7b334..d00e2d2fb 100644
--- a/src/core/core.vcxproj
+++ b/src/core/core.vcxproj
@@ -249,7 +249,7 @@
ENABLE_VOODOO=1;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
true
ProgramDatabase
- $(SolutionDir)dep\msvc\include;$(SolutionDir)dep\YBaseLib\Include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\imgui\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)
+ $(SolutionDir)dep\msvc\include;$(SolutionDir)dep\YBaseLib\Include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\imgui\include;$(SolutionDir)dep\simpleini\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)
true
false
stdcpp17
@@ -271,7 +271,7 @@
ENABLE_VOODOO=1;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
true
ProgramDatabase
- $(SolutionDir)dep\msvc\include;$(SolutionDir)dep\YBaseLib\Include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\imgui\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)
+ $(SolutionDir)dep\msvc\include;$(SolutionDir)dep\YBaseLib\Include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\imgui\include;$(SolutionDir)dep\simpleini\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)
true
false
stdcpp17
@@ -293,7 +293,7 @@
ENABLE_VOODOO=1;_ITERATOR_DEBUG_LEVEL=1;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUGFAST;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
true
ProgramDatabase
- $(SolutionDir)dep\msvc\include;$(SolutionDir)dep\YBaseLib\Include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\imgui\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)
+ $(SolutionDir)dep\msvc\include;$(SolutionDir)dep\YBaseLib\Include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\imgui\include;$(SolutionDir)dep\simpleini\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)
Default
true
false
@@ -318,7 +318,7 @@
ENABLE_VOODOO=1;_ITERATOR_DEBUG_LEVEL=1;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUGFAST;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
true
ProgramDatabase
- $(SolutionDir)dep\msvc\include;$(SolutionDir)dep\YBaseLib\Include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\imgui\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)
+ $(SolutionDir)dep\msvc\include;$(SolutionDir)dep\YBaseLib\Include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\imgui\include;$(SolutionDir)dep\simpleini\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)
Default
true
false
@@ -342,7 +342,7 @@
MaxSpeed
true
ENABLE_VOODOO=1;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
- $(SolutionDir)dep\msvc\include;$(SolutionDir)dep\YBaseLib\Include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\imgui\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)
+ $(SolutionDir)dep\msvc\include;$(SolutionDir)dep\YBaseLib\Include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\imgui\include;$(SolutionDir)dep\simpleini\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)
true
false
stdcpp17
@@ -365,7 +365,7 @@
MaxSpeed
true
ENABLE_VOODOO=1;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
- $(SolutionDir)dep\msvc\include;$(SolutionDir)dep\YBaseLib\Include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\imgui\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)
+ $(SolutionDir)dep\msvc\include;$(SolutionDir)dep\YBaseLib\Include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\imgui\include;$(SolutionDir)dep\simpleini\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)
true
true
stdcpp17
@@ -389,7 +389,7 @@
MaxSpeed
true
ENABLE_VOODOO=1;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
- $(SolutionDir)dep\msvc\include;$(SolutionDir)dep\YBaseLib\Include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\imgui\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)
+ $(SolutionDir)dep\msvc\include;$(SolutionDir)dep\YBaseLib\Include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\imgui\include;$(SolutionDir)dep\simpleini\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)
true
false
stdcpp17
@@ -412,7 +412,7 @@
MaxSpeed
true
ENABLE_VOODOO=1;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
- $(SolutionDir)dep\msvc\include;$(SolutionDir)dep\YBaseLib\Include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\imgui\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)
+ $(SolutionDir)dep\msvc\include;$(SolutionDir)dep\YBaseLib\Include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\imgui\include;$(SolutionDir)dep\simpleini\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)
true
true
stdcpp17
diff --git a/src/core/host_interface.cpp b/src/core/host_interface.cpp
index c94dc0df8..a7f518a2b 100644
--- a/src/core/host_interface.cpp
+++ b/src/core/host_interface.cpp
@@ -7,8 +7,7 @@ Log_SetChannel(HostInterface);
HostInterface::HostInterface()
{
- m_settings.gpu_renderer = Settings::GPURenderer::HardwareOpenGL;
- m_settings.memory_card_a_filename = "memory_card_a.mcd";
+ m_settings.Load("settings.ini");
}
HostInterface::~HostInterface() = default;
diff --git a/src/core/settings.cpp b/src/core/settings.cpp
index 96aa9b689..fa18e9632 100644
--- a/src/core/settings.cpp
+++ b/src/core/settings.cpp
@@ -1,3 +1,103 @@
#include "settings.h"
+#include "SimpleIni.h"
+#include "YBaseLib/Log.h"
+#include
+#include
+Log_SetChannel(Settings);
-Settings::Settings() = default;
\ No newline at end of file
+#ifdef _MSC_VER
+#define strcasecmp stricmp
+#endif
+
+Settings::Settings() = default;
+
+void Settings::SetDefaults()
+{
+ gpu_renderer = GPURenderer::HardwareOpenGL;
+ gpu_resolution_scale = 1;
+ gpu_vsync = true;
+ gpu_true_color = true;
+
+ display_linear_filtering = true;
+
+ bios_path = "scph1001.bin";
+
+ memory_card_a_filename = "memory_card_a.mcd";
+ memory_card_b_filename.clear();
+}
+
+void Settings::Load(const char* filename)
+{
+ CSimpleIniA ini(true);
+ SI_Error err = ini.LoadFile(filename);
+ if (err != SI_OK)
+ {
+ Log_WarningPrintf("Settings could not be loaded from '%s', defaults will be used.", filename);
+ SetDefaults();
+ return;
+ }
+
+ gpu_renderer = ParseRendererName(ini.GetValue("GPU", "Renderer", "OpenGL")).value_or(GPURenderer::HardwareOpenGL);
+ gpu_resolution_scale = static_cast(ini.GetLongValue("GPU", "ResolutionScale", 1));
+ gpu_vsync = static_cast(ini.GetBoolValue("GPU", "VSync", true));
+ gpu_true_color = ini.GetBoolValue("GPU", "TrueColor", false);
+
+ display_linear_filtering = ini.GetBoolValue("Display", "LinearFiltering", true);
+
+ bios_path = ini.GetValue("BIOS", "Path", "scph1001.bin");
+
+ memory_card_a_filename = ini.GetValue("MemoryCard", "CardAPath", "memory_card_a.mcd");
+ memory_card_b_filename = ini.GetValue("MemoryCard", "CardBPath", "");
+}
+
+bool Settings::Save(const char* filename) const
+{
+ // Load the file first to preserve the comments.
+ CSimpleIniA ini;
+ SI_Error err = ini.LoadFile(filename);
+ if (err != SI_OK)
+ ini.Reset();
+
+ ini.SetValue("GPU", "Renderer", GetRendererName(gpu_renderer));
+ ini.SetLongValue("GPU", "ResolutionScale", static_cast(gpu_resolution_scale));
+ ini.SetBoolValue("GPU", "VSync", gpu_vsync);
+ ini.SetBoolValue("GPU", "TrueColor", gpu_true_color);
+
+ ini.SetBoolValue("Display", "LinearFiltering", display_linear_filtering);
+
+ ini.SetValue("BIOS", "Path", bios_path.c_str());
+
+ if (!memory_card_a_filename.empty())
+ ini.SetValue("MemoryCard", "CardAPath", memory_card_a_filename.c_str());
+ else
+ ini.DeleteValue("MemoryCard", "CardAPath", nullptr);
+
+ if (!memory_card_b_filename.empty())
+ ini.SetValue("MemoryCard", "CardBPath", memory_card_b_filename.c_str());
+ else
+ ini.DeleteValue("MemoryCard", "CardBPath", nullptr);
+
+ err = ini.SaveFile(filename, false);
+ return (err == SI_OK);
+}
+
+static std::array s_gpu_renderer_names = {{"D3D11", "OpenGL", "Software"}};
+
+std::optional Settings::ParseRendererName(const char* str)
+{
+ int index = 0;
+ for (const char* name : s_gpu_renderer_names)
+ {
+ if (strcasecmp(name, str) == 0)
+ return static_cast(index);
+
+ index++;
+ }
+
+ return std::nullopt;
+}
+
+const char* Settings::GetRendererName(GPURenderer renderer)
+{
+ return s_gpu_renderer_names[static_cast(renderer)];
+}
diff --git a/src/core/settings.h b/src/core/settings.h
index fbee45171..6f070f75d 100644
--- a/src/core/settings.h
+++ b/src/core/settings.h
@@ -1,5 +1,6 @@
#pragma once
#include "types.h"
+#include
struct Settings
{
@@ -36,6 +37,14 @@ struct Settings
// TODO: Controllers, memory cards, etc.
+ std::string bios_path;
std::string memory_card_a_filename;
std::string memory_card_b_filename;
+
+ void SetDefaults();
+ void Load(const char* filename);
+ bool Save(const char* filename) const;
+
+ static std::optional ParseRendererName(const char* str);
+ static const char* GetRendererName(GPURenderer renderer);
};
diff --git a/src/duckstation/sdl_host_interface.cpp b/src/duckstation/sdl_host_interface.cpp
index 0cb53d2bf..e5fec5ec0 100644
--- a/src/duckstation/sdl_host_interface.cpp
+++ b/src/duckstation/sdl_host_interface.cpp
@@ -843,6 +843,7 @@ void SDLHostInterface::DrawAboutWindow()
ImGui::Text("Uses Dear ImGui (https://github.com/ocornut/imgui)");
ImGui::Text("Uses libcue (https://github.com/lipnitsk/libcue)");
ImGui::Text("Uses stb_image_write (https://github.com/nothings/stb)");
+ ImGui::Text("Uses simpleini (https://github.com/brofield/simpleini)");
ImGui::NewLine();
ImGui::Text("Duck icon by icons8 (https://icons8.com/icon/74847/platforms.undefined.short-title)");