Update to spice2x-23-06-08

This commit is contained in:
[ ]
2023-09-20 02:09:17 +09:00
parent 8957d9d446
commit d03cca1fe2
98 changed files with 21957 additions and 4977 deletions
+1
View File
@@ -13,5 +13,6 @@ IDR_CHANGELOG RCDATA "../changelog.txt"
IDR_LICENSES RCDATA "../licenses.txt"
IDR_PATCHES RCDATA "../build/patches.json"
IDR_README RCDATA "../readme.txt"
IDR_DSEGFONT RCDATA "../external/dseg/DSEG14Classic-Italic.ttf"
#endif
+5 -1
View File
@@ -29,7 +29,7 @@ cfg::ConfiguratorWindow::ConfiguratorWindow() {
// determine window title
if (cfg::CONFIGURATOR_TYPE == cfg::ConfigType::Config) {
WINDOW_TITLE = "SpiceTools Config (" + to_string(VERSION_STRING_CFG) + ")";
WINDOW_TITLE = "spice2x config - a fork of SpiceTools (" + to_string(VERSION_STRING_CFG) + ")";
WINDOW_SIZE_X = 800;
WINDOW_SIZE_Y = 600;
} else if (cfg::CONFIGURATOR_TYPE == cfg::ConfigType::KFControl) {
@@ -49,6 +49,10 @@ cfg::ConfiguratorWindow::ConfiguratorWindow() {
NULL,
GetModuleHandle(NULL),
(LPVOID) this);
if (this->hWnd) {
overlay::USE_WM_CHAR_FOR_IMGUI_CHAR_INPUT = true;
}
}
cfg::ConfiguratorWindow::~ConfiguratorWindow() {
+1 -1
View File
@@ -6,7 +6,7 @@
name="spicecfg.exe"
type="win32"
/>
<description>SpiceTools Config</description>
<description>spice2x config</description>
<dependency>
<dependentAssembly>
<assemblyIdentity
+18 -3
View File
@@ -68,17 +68,32 @@ std::vector<std::string> Option::values_text() const {
return values;
}
int Option::value_int() const {
uint32_t Option::value_uint32() const {
if (this->definition.type != OptionType::Integer && this->definition.type != OptionType::Enum) {
log_fatal("option", "value_int() called on {}/{}", this->definition.title, this->definition.type);
log_fatal("option", "invalid call: value_uint32() called on {}/{}", this->definition.title, this->definition.type);
return 0;
}
char *p;
auto res = strtol(this->value.c_str(), &p, 10);
if (*p) {
log_fatal("option", "tried to convert {} to integer ({})", this->value, this->definition.title);
log_fatal("option", "failed to convert {} to unsigned integer (option: {})", this->value, this->definition.title);
return 0;
} else {
return res;
}
}
uint64_t Option::value_hex64() const {
if (this->definition.type != OptionType::Hex) {
log_fatal("option", "invalid call: value_hex() called on {}/{}", this->definition.title, this->definition.type);
return 0;
}
uint64_t affinity = 0;
try {
affinity = std::stoull(this->value.c_str(), nullptr, 16);
} catch (const std::exception &ex) {
log_fatal("option", "failed to parse {} as hexadecimal (option: {})", this->value, this->definition.title);
}
return affinity;
}
+3 -1
View File
@@ -9,6 +9,7 @@ enum class OptionType {
Text,
Integer,
Enum,
Hex,
};
struct OptionDefinition {
@@ -54,5 +55,6 @@ public:
const std::string &value_text() const;
std::vector<std::string> values() const;
std::vector<std::string> values_text() const;
int value_int() const;
uint32_t value_uint32() const;
uint64_t value_hex64() const;
};
+1
View File
@@ -4,3 +4,4 @@
#define IDR_LICENSES 131
#define IDR_PATCHES 132
#define IDR_README 133
#define IDR_DSEGFONT 134
+167 -76
View File
@@ -1,11 +1,12 @@
#include "screen_resize.h"
#include "external/rapidjson/document.h"
#include "external/rapidjson/writer.h"
#include "external/rapidjson/pointer.h"
#include "external/rapidjson/prettywriter.h"
#include "misc/eamuse.h"
#include "util/utils.h"
#include "util/fileutils.h"
using namespace rapidjson;
#include "hooks/graphics/graphics.h"
namespace cfg {
@@ -26,90 +27,180 @@ namespace cfg {
log_info("ScreenResize", "loading config");
std::string config = fileutils::text_read(this->config_path);
if (!config.empty()) {
if (config.empty()) {
return;
}
// parse document
Document doc;
doc.Parse(config.c_str());
// parse document
rapidjson::Document doc;
doc.Parse(config.c_str());
// check parse error
auto error = doc.GetParseError();
if (error) {
log_warning("ScreenResize", "config parse error: {}", error);
}
// check parse error
auto error = doc.GetParseError();
if (error) {
log_warning("ScreenResize", "config parse error: {}", error);
return;
}
// verify root is a dict
if (doc.IsObject()) {
bool valid = true;
auto offset_x = doc.FindMember("offset_x");
if (offset_x == doc.MemberEnd() || !offset_x->value.IsInt()) {
log_warning("ScreenResize", "offset_x not found");
valid = false;
}
auto offset_y = doc.FindMember("offset_y");
if (offset_y == doc.MemberEnd() || !offset_y->value.IsInt()) {
log_warning("ScreenResize", "offset_y not found");
valid = false;
}
auto scale_x = doc.FindMember("scale_x");
if (scale_x == doc.MemberEnd() || !scale_x->value.IsDouble()) {
log_warning("ScreenResize", "scale_x not found");
valid = false;
}
auto scale_y = doc.FindMember("scale_y");
if (scale_y == doc.MemberEnd() || !scale_y->value.IsDouble()) {
log_warning("ScreenResize", "scale_y not found");
valid = false;
}
auto enable_screen_resize = doc.FindMember("enable_screen_resize");
if (enable_screen_resize == doc.MemberEnd() || !enable_screen_resize->value.IsBool()) {
log_warning("ScreenResize", "enable_screen_resize not found");
valid = false;
}
auto enable_linear_filter = doc.FindMember("enable_linear_filter");
if (enable_linear_filter == doc.MemberEnd() || !enable_linear_filter->value.IsBool()) {
log_warning("ScreenResize", "enable_linear_filter not found");
valid = false;
}
auto keep_aspect_ratio = doc.FindMember("keep_aspect_ratio");
if (keep_aspect_ratio == doc.MemberEnd() || !keep_aspect_ratio->value.IsBool()) {
log_warning("ScreenResize", "keep_aspect_ratio not found");
valid = false;
}
if (valid) {
this->offset_x = offset_x->value.GetInt();
this->offset_y = offset_y->value.GetInt();
this->scale_x = (float)scale_x->value.GetDouble();
this->scale_y = (float)scale_y->value.GetDouble();
this->enable_screen_resize = enable_screen_resize->value.GetBool();
this->enable_linear_filter = enable_linear_filter->value.GetBool();
this->keep_aspect_ratio = keep_aspect_ratio->value.GetBool();
}
} else {
log_warning("ScreenResize", "config not found");
// verify root is a dict
if (!doc.IsObject()) {
log_warning("ScreenResize", "config not found");
return;
}
bool use_game_setting = false;
std::string root("/");
// try to find game-specific setting, if one exists
{
const auto game = rapidjson::Pointer("/sp2x_games/" + eamuse_get_game()).Get(doc);
if (game && game->IsObject()) {
use_game_setting = true;
root = "/sp2x_games/" + eamuse_get_game() + "/";
}
}
log_misc(
"ScreenResize",
"Loading fullscreen image settings. Game = {}, is_global = {}, JSON path: {}",
eamuse_get_game(),
use_game_setting,
root);
load_int_value(doc, root + "offset_x", this->offset_x);
load_int_value(doc, root + "offset_y", this->offset_y);
load_float_value(doc, root + "scale_x", this->scale_x);
load_float_value(doc, root + "scale_y", this->scale_y);
load_bool_value(doc, root + "enable_screen_resize", this->enable_screen_resize);
load_bool_value(doc, root + "enable_linear_filter", this->enable_linear_filter);
load_bool_value(doc, root + "keep_aspect_ratio", this->keep_aspect_ratio);
load_bool_value(doc, root + "centered", this->centered);
// windowed settings are always under game settings
root = "/sp2x_games/" + eamuse_get_game() + "/";
log_misc(
"ScreenResize",
"Loading window settings. Game = {}, JSON path: {}",
eamuse_get_game(),
root);
load_bool_value(doc, root + "w_always_on_top", this->window_always_on_top);
load_bool_value(doc, root + "w_enable_resize", this->enable_window_resize);
load_bool_value(doc, root + "w_keep_aspect_ratio", this->client_keep_aspect_ratio);
load_int_value(doc, root + "w_border_type", this->window_decoration);
load_uint32_value(doc, root + "w_width", this->client_width);
load_uint32_value(doc, root + "w_height", this->client_height);
load_int_value(doc, root + "w_offset_x", this->window_offset_x);
load_int_value(doc, root + "w_offset_y", this->window_offset_y);
}
bool ScreenResize::load_bool_value(rapidjson::Document& doc, std::string path, bool& value) {
const auto v = rapidjson::Pointer(path).Get(doc);
if (!v) {
log_warning("ScreenResize", "{} not found", path);
return false;
}
if (!v->IsBool()) {
log_warning("ScreenResize", "{} is invalid type", path);
return false;
}
value = v->GetBool();
return true;
}
bool ScreenResize::load_int_value(rapidjson::Document& doc, std::string path, int& value) {
const auto v = rapidjson::Pointer(path).Get(doc);
if (!v) {
log_warning("ScreenResize", "{} not found", path);
return false;
}
if (!v->IsInt()) {
log_warning("ScreenResize", "{} is invalid type", path);
return false;
}
value = v->GetInt();
return true;
}
bool ScreenResize::load_uint32_value(rapidjson::Document& doc, std::string path, uint32_t& value) {
const auto v = rapidjson::Pointer(path).Get(doc);
if (!v) {
log_warning("ScreenResize", "{} not found", path);
return false;
}
if (!v->IsUint()) {
log_warning("ScreenResize", "{} is invalid type", path);
return false;
}
value = v->GetUint();
return true;
}
bool ScreenResize::load_float_value(rapidjson::Document& doc, std::string path, float& value) {
const auto v = rapidjson::Pointer(path).Get(doc);
if (!v) {
log_warning("ScreenResize", "{} not found", path);
return false;
}
if (v->IsInt()) {
value = v->GetInt();
return true;
}
if (v->IsDouble()) {
value = v->GetDouble();
return true;
}
if (v->IsFloat()) {
value = v->GetFloat();
return true;
}
return false;
}
void ScreenResize::config_save() {
log_info("ScreenResize", "saving config");
// create document
Document doc;
doc.SetObject();
auto &alloc = doc.GetAllocator();
doc.AddMember("offset_x", this->offset_x, alloc);
doc.AddMember("offset_y", this->offset_y, alloc);
doc.AddMember("scale_x", this->scale_x, alloc);
doc.AddMember("scale_y", this->scale_y, alloc);
doc.AddMember("enable_screen_resize", this->enable_screen_resize, alloc);
doc.AddMember("enable_linear_filter", this->enable_linear_filter, alloc);
doc.AddMember("keep_aspect_ratio", this->keep_aspect_ratio, alloc);
rapidjson::Document doc;
std::string config = fileutils::text_read(this->config_path);
if (!config.empty()) {
doc.Parse(config.c_str());
log_misc("ScreenResize", "existing config file found");
}
if (!doc.IsObject()) {
log_misc("ScreenResize", "clearing out config file");
doc.SetObject();
}
// always save under per-game settings
std::string root("/sp2x_games/" + eamuse_get_game() + "/");
log_misc(
"ScreenResize",
"Game = {}, JSON path = {}",
eamuse_get_game(),
root);
// full screen image settings
rapidjson::Pointer(root + "offset_x").Set(doc, this->offset_x);
rapidjson::Pointer(root + "offset_y").Set(doc, this->offset_y);
rapidjson::Pointer(root + "scale_x").Set(doc, this->scale_x);
rapidjson::Pointer(root + "scale_y").Set(doc, this->scale_y);
rapidjson::Pointer(root + "enable_screen_resize").Set(doc, this->enable_screen_resize);
rapidjson::Pointer(root + "enable_linear_filter").Set(doc, this->enable_linear_filter);
rapidjson::Pointer(root + "keep_aspect_ratio").Set(doc, this->keep_aspect_ratio);
rapidjson::Pointer(root + "centered").Set(doc, this->centered);
// windowed mode settings
rapidjson::Pointer(root + "w_always_on_top").Set(doc, this->window_always_on_top);
rapidjson::Pointer(root + "w_enable_resize").Set(doc, this->enable_window_resize);
rapidjson::Pointer(root + "w_keep_aspect_ratio").Set(doc, this->client_keep_aspect_ratio);
rapidjson::Pointer(root + "w_border_type").Set(doc, this->window_decoration);
rapidjson::Pointer(root + "w_width").Set(doc, this->client_width);
rapidjson::Pointer(root + "w_height").Set(doc, this->client_height);
rapidjson::Pointer(root + "w_offset_x").Set(doc, this->window_offset_x);
rapidjson::Pointer(root + "w_offset_y").Set(doc, this->window_offset_y);
// build JSON
StringBuffer buffer;
Writer<StringBuffer> writer(buffer);
rapidjson::StringBuffer buffer;
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buffer);
doc.Accept(writer);
// save to file
+38 -3
View File
@@ -2,26 +2,61 @@
#include <memory>
#include <string>
#include "external/rapidjson/document.h"
namespace cfg {
enum WindowDecorationMode {
Default = 0,
Borderless = 1,
ResizableFrame = 2
};
class ScreenResize {
private:
std::string config_path;
// bool config_dirty = false;
bool load_bool_value(rapidjson::Document& doc, std::string path, bool& value);
bool load_int_value(rapidjson::Document& doc, std::string path, int& value);
bool load_uint32_value(rapidjson::Document& doc, std::string path, uint32_t& value);
bool load_float_value(rapidjson::Document& doc, std::string path, float& value);
public:
ScreenResize();
~ScreenResize();
// full screen (directx) image settings
int offset_x = 0;
int offset_y = 0;
float scale_x = 1.0;
float scale_y = 1.0;
bool enable_screen_resize = false;
bool enable_linear_filter = false;
bool keep_aspect_ratio = false;
bool enable_linear_filter = true;
bool keep_aspect_ratio = true;
bool centered = true;
// windowed mode sizing
// Windows terminology:
// window = rectangle including the frame
// client = just the content area without frames.
bool window_always_on_top = false;
bool client_keep_aspect_ratio = true;
bool enable_window_resize = false;
int window_decoration = 0; // enum type WindowDecorationMode
uint32_t client_width = 0;
uint32_t client_height = 0;
int32_t window_offset_x = 0;
int32_t window_offset_y = 0;
// these are not saved by config, but used by window management
uint32_t init_client_width = 0;
uint32_t init_client_height = 0;
float init_client_aspect_ratio = 1.f;
uint32_t init_window_style = 0;
uint32_t window_deco_width = 0;
uint32_t window_deco_height = 0;
void config_load();
void config_save();
};