From 54b862599c63324dac2678ffc1fe85d5b2e01d82 Mon Sep 17 00:00:00 2001 From: Mr-Wiseguy Date: Sat, 4 May 2024 13:08:14 -0400 Subject: [PATCH] Implemented UI for controlling autosaving, fixed general config defaults not being applied correctly --- assets/config_menu/general.rml | 43 ++++++++++++++++++++++++++++++---- include/recomp_config.h | 14 +++++++++++ patches/autosaving.c | 5 +--- patches/misc_funcs.h | 1 + patches/syms.ld | 1 + src/game/config.cpp | 22 +++++++++++------ src/game/recomp_api.cpp | 5 ++++ src/ui/ui_config.cpp | 24 +++++++++++++++---- src/ui/ui_renderer.cpp | 6 ++--- 9 files changed, 98 insertions(+), 23 deletions(-) diff --git a/assets/config_menu/general.rml b/assets/config_menu/general.rml index f194478..4ca6931 100644 --- a/assets/config_menu/general.rml +++ b/assets/config_menu/general.rml @@ -93,7 +93,7 @@ - +
@@ -105,7 +105,7 @@ data-checked="background_input_mode" value="On" id="bg_input_enabled" - style="nav-up: #mouse_sensitivity_input" + style="nav-up: #mouse_sensitivity_input; nav-down: #autosave_enabled" /> @@ -117,11 +117,41 @@ data-checked="background_input_mode" value="Off" id="bg_input_disabled" - style="nav-up: #mouse_sensitivity_input" + style="nav-up: #mouse_sensitivity_input; nav-down: #autosave_disabled" />
+ + +
+ +
+ + + + + +
+
@@ -138,7 +168,7 @@ Note: To recalibrate controller gyro, set the controller down on a still, flat surface for 5 seconds.

- Controls the sensitivity of mouse aiming. Setting this to zero will disable mouse aiming. + Controls the sensitivity of mouse aiming when using items in first person. Setting this to zero will disable mouse aiming.

Note: This option does not allow mouse buttons to activate items. Mouse aiming is is intended to be used with inputs that are mapped to mouse movement, such as gyro on Steam Deck. @@ -148,6 +178,11 @@
This setting does not affect keyboard input.

+

+ Enables or disables the autosave feature. +
+ If any owl save exists when an autosave is made, the owl save will get replaced. +

diff --git a/include/recomp_config.h b/include/recomp_config.h index 98abbc9..fa5e42d 100644 --- a/include/recomp_config.h +++ b/include/recomp_config.h @@ -20,6 +20,20 @@ namespace recomp { bool get_debug_mode_enabled(); void set_debug_mode_enabled(bool enabled); + + enum class AutosaveMode { + On, + Off, + OptionCount + }; + + NLOHMANN_JSON_SERIALIZE_ENUM(recomp::AutosaveMode, { + {recomp::AutosaveMode::On, "On"}, + {recomp::AutosaveMode::Off, "Off"} + }); + + AutosaveMode get_autosave_mode(); + void set_autosave_mode(AutosaveMode mode); }; #endif diff --git a/patches/autosaving.c b/patches/autosaving.c index 4e8f93b..4435704 100644 --- a/patches/autosaving.c +++ b/patches/autosaving.c @@ -3,6 +3,7 @@ #include "z64save.h" #include "overlays/gamestates/ovl_file_choose/z_file_select.h" #include "overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope.h" +#include "misc_funcs.h" #define SAVE_TYPE_AUTOSAVE 2 @@ -268,10 +269,6 @@ void show_autosave_icon() { autosave_icon_counter = AUTOSAVE_ICON_TOTAL_FRAMES; } -s32 recomp_autosave_enabled() { - return 1; -} - u32 recomp_autosave_interval() { return 2 * 60 * 1000; } diff --git a/patches/misc_funcs.h b/patches/misc_funcs.h index b474e15..4c0a0c8 100644 --- a/patches/misc_funcs.h +++ b/patches/misc_funcs.h @@ -9,5 +9,6 @@ DECLARE_FUNC(void, recomp_handle_quicksave_actions, OSMesgQueue* enter_mq, OSMes DECLARE_FUNC(void, recomp_handle_quicksave_actions_main, OSMesgQueue* enter_mq, OSMesgQueue* exit_mq); DECLARE_FUNC(u16, recomp_get_pending_warp); DECLARE_FUNC(u32, recomp_get_pending_set_time); +DECLARE_FUNC(s32, recomp_autosave_enabled); #endif diff --git a/patches/syms.ld b/patches/syms.ld index a047b55..587f9bd 100644 --- a/patches/syms.ld +++ b/patches/syms.ld @@ -49,3 +49,4 @@ osContGetQuery_recomp = 0x8F00007C; recomp_get_mouse_deltas = 0x8F000080; bcmp_recomp = 0x8F000084; osGetTime_recomp = 0x8F000088; +recomp_autosave_enabled = 0x8F00008C; diff --git a/src/game/config.cpp b/src/game/config.cpp index 59cb45d..7c37d2a 100644 --- a/src/game/config.cpp +++ b/src/game/config.cpp @@ -160,22 +160,28 @@ void save_general_config(const std::filesystem::path& path) { config_json["rumble_strength"] = recomp::get_rumble_strength(); config_json["gyro_sensitivity"] = recomp::get_gyro_sensitivity(); config_json["mouse_sensitivity"] = recomp::get_mouse_sensitivity(); + config_json["autosave_mode"] = recomp::get_autosave_mode(); config_json["debug_mode"] = recomp::get_debug_mode_enabled(); config_file << std::setw(4) << config_json; } +void set_general_settings_from_json(const nlohmann::json& config_json) { + recomp::set_targeting_mode(from_or_default(config_json, "targeting_mode", recomp::TargetingMode::Switch)); + recomp::set_background_input_mode(from_or_default(config_json, "background_input_mode", recomp::BackgroundInputMode::On)); + recomp::set_rumble_strength(from_or_default(config_json, "rumble_strength", 25)); + recomp::set_gyro_sensitivity(from_or_default(config_json, "gyro_sensitivity", 50)); + recomp::set_mouse_sensitivity(from_or_default(config_json, "mouse_sensitivity", is_steam_deck ? 50 : 0)); + recomp::set_autosave_mode(from_or_default(config_json, "autosave_mode", recomp::AutosaveMode::On)); + recomp::set_debug_mode_enabled(from_or_default(config_json, "debug_mode", false)); +} + void load_general_config(const std::filesystem::path& path) { std::ifstream config_file{path}; nlohmann::json config_json{}; config_file >> config_json; - - recomp::set_targeting_mode(from_or_default(config_json, "targeting_mode", recomp::TargetingMode::Switch)); - recomp::set_background_input_mode(from_or_default(config_json, "background_input_mode", recomp::BackgroundInputMode::On)); - recomp::set_rumble_strength(from_or_default(config_json, "rumble_strength", 25)); - recomp::set_gyro_sensitivity(from_or_default(config_json, "gyro_sensitivity", 50)); - recomp::set_mouse_sensitivity(from_or_default(config_json, "mouse_sensitivity", is_steam_deck ? 50 : 0)); - recomp::set_debug_mode_enabled(from_or_default(config_json, "debug_mode", false)); + + set_general_settings_from_json(config_json); } void assign_mapping(recomp::InputDevice device, recomp::GameInput input, const std::vector& value) { @@ -374,6 +380,8 @@ void recomp::load_config() { load_general_config(general_path); } else { + // Set the general settings from an empty json to use defaults. + set_general_settings_from_json({}); save_general_config(general_path); } diff --git a/src/game/recomp_api.cpp b/src/game/recomp_api.cpp index 8a82278..fa07464 100644 --- a/src/game/recomp_api.cpp +++ b/src/game/recomp_api.cpp @@ -1,6 +1,7 @@ #include #include "recomp.h" +#include "recomp_config.h" #include "recomp_input.h" #include "recomp_ui.h" #include "recomp_sound.h" @@ -88,3 +89,7 @@ extern "C" void recomp_get_low_health_beeps_enabled(uint8_t* rdram, recomp_conte extern "C" void recomp_time_us(uint8_t* rdram, recomp_context* ctx) { _return(ctx, static_cast(std::chrono::duration_cast(ultramodern::time_since_start()).count())); } + +extern "C" void recomp_autosave_enabled(uint8_t* rdram, recomp_context* ctx) { + _return(ctx, static_cast(recomp::get_autosave_mode() == recomp::AutosaveMode::On)); +} diff --git a/src/ui/ui_config.cpp b/src/ui/ui_config.cpp index 48203d2..1891fec 100644 --- a/src/ui/ui_config.cpp +++ b/src/ui/ui_config.cpp @@ -269,12 +269,14 @@ void recomp::open_quit_game_prompt() { ); } +// These defaults values don't matter, as the config file handling overrides them. struct ControlOptionsContext { - int rumble_strength = 50; // 0 to 100 - int gyro_sensitivity = 50; // 0 to 100 - int mouse_sensitivity = 50; // 0 to 100 - recomp::TargetingMode targeting_mode = recomp::TargetingMode::Switch; - recomp::BackgroundInputMode background_input_mode = recomp::BackgroundInputMode::On; + int rumble_strength; // 0 to 100 + int gyro_sensitivity; // 0 to 100 + int mouse_sensitivity; // 0 to 100 + recomp::TargetingMode targeting_mode; + recomp::BackgroundInputMode background_input_mode; + recomp::AutosaveMode autosave_mode; }; ControlOptionsContext control_options_context; @@ -340,6 +342,17 @@ void recomp::set_background_input_mode(recomp::BackgroundInputMode mode) { ); } +recomp::AutosaveMode recomp::get_autosave_mode() { + return control_options_context.autosave_mode; +} + +void recomp::set_autosave_mode(recomp::AutosaveMode mode) { + control_options_context.autosave_mode = mode; + if (general_model_handle) { + general_model_handle.DirtyVariable("autosave_mode"); + } +} + struct SoundOptionsContext { std::atomic bgm_volume; std::atomic low_health_beeps_enabled; // RmlUi doesn't seem to like "true"/"false" strings for setting variants so an int is used here instead. @@ -824,6 +837,7 @@ public: constructor.Bind("mouse_sensitivity", &control_options_context.mouse_sensitivity); bind_option(constructor, "targeting_mode", &control_options_context.targeting_mode); bind_option(constructor, "background_input_mode", &control_options_context.background_input_mode); + bind_option(constructor, "autosave_mode", &control_options_context.autosave_mode); general_model_handle = constructor.GetModelHandle(); } diff --git a/src/ui/ui_renderer.cpp b/src/ui/ui_renderer.cpp index 9908e08..79d2671 100644 --- a/src/ui/ui_renderer.cpp +++ b/src/ui/ui_renderer.cpp @@ -521,7 +521,7 @@ public: if (row_byte_padding == 0) { // Copy row-by-row if the image is flipped. if (flip_y) { - for (uint32_t row = 0; row < source_dimensions.y; row++) { + for (int row = 0; row < source_dimensions.y; row++) { memcpy(dst_data + row_byte_width * (source_dimensions.y - row - 1), source + row_byte_width * row, row_byte_width); } } @@ -536,7 +536,7 @@ public: uint32_t src_stride = flip_y ? -row_pitch : row_pitch; size_t offset = 0; - for (uint32_t row = 0; row < source_dimensions.y; row++) { //(offset + increment) <= image_size_bytes) { + for (int row = 0; row < source_dimensions.y; row++) { //(offset + increment) <= image_size_bytes) { memcpy(dst_data, src_data, row_pitch); src_data += src_stride; offset += row_pitch; @@ -581,7 +581,7 @@ public: mvp_ = projection_mtx_ * transform_; } - void start(RT64::RenderCommandList* list, uint32_t image_width, uint32_t image_height) { + void start(RT64::RenderCommandList* list, int image_width, int image_height) { list_ = list; if (multisampling_.sampleCount > 1) {