summaryrefslogtreecommitdiff
path: root/Source/Core/VideoCommon/GraphicsModSystem/Config/GraphicsTarget.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Core/VideoCommon/GraphicsModSystem/Config/GraphicsTarget.cpp')
-rw-r--r--Source/Core/VideoCommon/GraphicsModSystem/Config/GraphicsTarget.cpp254
1 files changed, 254 insertions, 0 deletions
diff --git a/Source/Core/VideoCommon/GraphicsModSystem/Config/GraphicsTarget.cpp b/Source/Core/VideoCommon/GraphicsModSystem/Config/GraphicsTarget.cpp
new file mode 100644
index 0000000000..f55f184520
--- /dev/null
+++ b/Source/Core/VideoCommon/GraphicsModSystem/Config/GraphicsTarget.cpp
@@ -0,0 +1,254 @@
+// Copyright 2022 Dolphin Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "VideoCommon/GraphicsModSystem/Config/GraphicsTarget.h"
+
+#include "Common/Logging/Log.h"
+#include "Common/StringUtil.h"
+#include "VideoCommon/TextureCacheBase.h"
+
+namespace
+{
+template <typename T, std::enable_if_t<std::is_base_of_v<FBTarget, T>, int> = 0>
+std::optional<T> DeserializeFBTargetFromConfig(const picojson::object& obj, std::string_view prefix)
+{
+ T fb;
+ const auto texture_filename_iter = obj.find("texture_filename");
+ if (texture_filename_iter == obj.end())
+ {
+ ERROR_LOG_FMT(VIDEO,
+ "Failed to load mod configuration file, option 'texture_filename' not found");
+ return std::nullopt;
+ }
+ if (!texture_filename_iter->second.is<std::string>())
+ {
+ ERROR_LOG_FMT(
+ VIDEO,
+ "Failed to load mod configuration file, option 'texture_filename' is not a string type");
+ return std::nullopt;
+ }
+ const auto texture_filename = texture_filename_iter->second.get<std::string>();
+ const auto texture_filename_without_prefix = texture_filename.substr(prefix.size() + 1);
+ const auto split_str_values = SplitString(texture_filename_without_prefix, '_');
+ if (split_str_values.size() == 1)
+ {
+ ERROR_LOG_FMT(
+ VIDEO, "Failed to load mod configuration file, value in 'texture_filename' is not valid");
+ return std::nullopt;
+ }
+ const auto split_width_height_values = SplitString(texture_filename_without_prefix, 'x');
+ if (split_width_height_values.size() != 2)
+ {
+ ERROR_LOG_FMT(VIDEO, "Failed to load mod configuration file, value in 'texture_filename' is "
+ "not valid, width and height separator found more matches than expected");
+ return std::nullopt;
+ }
+
+ const std::size_t width_underscore_pos = split_width_height_values[0].find_last_of('_');
+ std::string width_str;
+ if (width_underscore_pos == std::string::npos)
+ {
+ width_str = split_width_height_values[0];
+ }
+ else
+ {
+ width_str = split_width_height_values[0].substr(width_underscore_pos + 1);
+ }
+ if (!TryParse(width_str, &fb.m_width))
+ {
+ ERROR_LOG_FMT(VIDEO, "Failed to load mod configuration file, value in 'texture_filename' is "
+ "not valid, width not a number");
+ return std::nullopt;
+ }
+
+ const std::size_t height_underscore_pos = split_width_height_values[1].find_first_of('_');
+ if (height_underscore_pos == std::string::npos ||
+ height_underscore_pos == split_width_height_values[1].size() - 1)
+ {
+ ERROR_LOG_FMT(VIDEO, "Failed to load mod configuration file, value in 'texture_filename' is "
+ "not valid, underscore after height is missing or incomplete");
+ return std::nullopt;
+ }
+ const std::string height_str = split_width_height_values[1].substr(0, height_underscore_pos);
+ if (!TryParse(height_str, &fb.m_height))
+ {
+ ERROR_LOG_FMT(VIDEO, "Failed to load mod configuration file, value in 'texture_filename' is "
+ "not valid, height not a number");
+ return std::nullopt;
+ }
+
+ const std::size_t format_underscore_pos =
+ split_width_height_values[1].find_first_of('_', height_underscore_pos + 1);
+
+ std::string format_str;
+ if (format_underscore_pos == std::string::npos)
+ {
+ format_str = split_width_height_values[1].substr(height_underscore_pos + 1);
+ }
+ else
+ {
+ format_str = split_width_height_values[1].substr(
+ height_underscore_pos + 1, (format_underscore_pos - height_underscore_pos) - 1);
+ }
+ u32 format;
+ if (!TryParse(format_str, &format))
+ {
+ ERROR_LOG_FMT(VIDEO, "Failed to load mod configuration file, value in 'texture_filename' is "
+ "not valid, texture format is not a number");
+ return std::nullopt;
+ }
+ if (!IsValidTextureFormat(static_cast<TextureFormat>(format)))
+ {
+ ERROR_LOG_FMT(VIDEO, "Failed to load mod configuration file, value in 'texture_filename' is "
+ "not valid, texture format is not valid");
+ return std::nullopt;
+ }
+ fb.m_texture_format = static_cast<TextureFormat>(format);
+
+ return fb;
+}
+std::optional<std::string> ExtractTextureFilenameForConfig(const picojson::object& obj)
+{
+ const auto texture_filename_iter = obj.find("texture_filename");
+ if (texture_filename_iter == obj.end())
+ {
+ ERROR_LOG_FMT(VIDEO,
+ "Failed to load mod configuration file, option 'texture_filename' not found");
+ return std::nullopt;
+ }
+ if (!texture_filename_iter->second.is<std::string>())
+ {
+ ERROR_LOG_FMT(
+ VIDEO,
+ "Failed to load mod configuration file, option 'texture_filename' is not a string type");
+ return std::nullopt;
+ }
+ std::string texture_info = texture_filename_iter->second.get<std::string>();
+ if (texture_info.find(EFB_DUMP_PREFIX) != std::string::npos)
+ {
+ const auto letter_c_pos = texture_info.find_first_of('n');
+ if (letter_c_pos == std::string::npos)
+ {
+ ERROR_LOG_FMT(VIDEO, "Failed to load mod configuration file, value in 'texture_filename' "
+ "is an efb without a count");
+ return std::nullopt;
+ }
+ texture_info =
+ texture_info.substr(letter_c_pos - 1, texture_info.find_first_of("_", letter_c_pos));
+ }
+ else if (texture_info.find(XFB_DUMP_PREFIX) != std::string::npos)
+ {
+ const auto letter_c_pos = texture_info.find_first_of('n');
+ if (letter_c_pos == std::string::npos)
+ {
+ ERROR_LOG_FMT(VIDEO, "Failed to load mod configuration file, value in 'texture_filename' "
+ "is an xfb without a count");
+ return std::nullopt;
+ }
+ texture_info =
+ texture_info.substr(letter_c_pos - 1, texture_info.find_first_of("_", letter_c_pos));
+ }
+ return texture_info;
+}
+} // namespace
+
+std::optional<GraphicsTargetConfig> DeserializeTargetFromConfig(const picojson::object& obj)
+{
+ const auto type_iter = obj.find("type");
+ if (type_iter == obj.end())
+ {
+ ERROR_LOG_FMT(VIDEO, "Failed to load mod configuration file, option 'type' not found");
+ return std::nullopt;
+ }
+ if (!type_iter->second.is<std::string>())
+ {
+ ERROR_LOG_FMT(VIDEO,
+ "Failed to load mod configuration file, option 'type' is not a string type");
+ return std::nullopt;
+ }
+ const std::string& type = type_iter->second.get<std::string>();
+ if (type == "draw_started")
+ {
+ std::optional<std::string> texture_info = ExtractTextureFilenameForConfig(obj);
+ if (!texture_info.has_value())
+ return std::nullopt;
+
+ DrawStartedTextureTarget target;
+ target.m_texture_info_string = texture_info.value();
+ return target;
+ }
+ else if (type == "load_texture")
+ {
+ std::optional<std::string> texture_info = ExtractTextureFilenameForConfig(obj);
+ if (!texture_info.has_value())
+ return std::nullopt;
+
+ LoadTextureTarget target;
+ target.m_texture_info_string = texture_info.value();
+ return target;
+ }
+ else if (type == "efb")
+ {
+ return DeserializeFBTargetFromConfig<EFBTarget>(obj, EFB_DUMP_PREFIX);
+ }
+ else if (type == "xfb")
+ {
+ return DeserializeFBTargetFromConfig<XFBTarget>(obj, EFB_DUMP_PREFIX);
+ }
+ else if (type == "projection")
+ {
+ ProjectionTarget target;
+ const auto texture_iter = obj.find("texture_filename");
+ if (texture_iter != obj.end())
+ {
+ std::optional<std::string> texture_info = ExtractTextureFilenameForConfig(obj);
+ if (!texture_info.has_value())
+ return std::nullopt;
+ target.m_texture_info_string = texture_info;
+ }
+ const auto value_iter = obj.find("value");
+ if (value_iter == obj.end())
+ {
+ ERROR_LOG_FMT(VIDEO, "Failed to load mod configuration file, option 'value' not found");
+ return std::nullopt;
+ }
+ if (!value_iter->second.is<std::string>())
+ {
+ ERROR_LOG_FMT(VIDEO,
+ "Failed to load mod configuration file, option 'value' is not a string type");
+ return std::nullopt;
+ }
+ const auto& value_str = value_iter->second.get<std::string>();
+ if (value_str == "2d")
+ {
+ target.m_projection_type = ProjectionType::Orthographic;
+ }
+ else if (value_str == "3d")
+ {
+ target.m_projection_type = ProjectionType::Perspective;
+ }
+ else
+ {
+ ERROR_LOG_FMT(VIDEO, "Failed to load mod configuration file, option 'value' is not a valid "
+ "value, valid values are: 2d, 3d");
+ return std::nullopt;
+ }
+ return target;
+ }
+ else
+ {
+ ERROR_LOG_FMT(VIDEO,
+ "Failed to load mod configuration file, option 'type' is not a valid value");
+ }
+ return std::nullopt;
+}
+
+void SerializeTargetToProfile(picojson::object*, const GraphicsTargetConfig&)
+{
+ // Added for consistency, no functionality as of now
+}
+
+void DeserializeTargetFromProfile(const picojson::object&, GraphicsTargetConfig*)
+{
+ // Added for consistency, no functionality as of now
+}