From d8f9a2e5c8386cdc8faebfbbf5cb88975c0ff45e Mon Sep 17 00:00:00 2001 From: Mr-Wiseguy Date: Sun, 26 May 2024 03:37:29 -0400 Subject: [PATCH] Split camera inversion into two settings, hooked up aiming camera inversion --- assets/config_menu/general.rml | 69 +++++++++++++++++++++++++++++++--- include/recomp_input.h | 3 ++ patches/camera_patches.c | 11 +++--- patches/input.c | 33 ++++++++++++++-- patches/input.h | 1 + patches/syms.ld | 1 + src/game/config.cpp | 2 + src/game/recomp_api.cpp | 10 +++++ src/ui/ui_config.cpp | 13 +++++++ 9 files changed, 129 insertions(+), 14 deletions(-) diff --git a/assets/config_menu/general.rml b/assets/config_menu/general.rml index 42b7182..d2ab0a8 100644 --- a/assets/config_menu/general.rml +++ b/assets/config_menu/general.rml @@ -174,7 +174,7 @@
- +
@@ -250,11 +250,65 @@ data-checked="analog_cam_mode" value="Off" id="analog_cam_disabled" - style="nav-up: #camera_inversion_x" + style="nav-up: #camera_inversion_x; nav-down: analog_camera_inversion_x" />
+ + +
+ +
+ + + + + + + + + + + +
+
@@ -294,10 +348,15 @@ If autosaving is disabled, existing autosaves will be deleted when loaded.

- Camera inversion description. + Inverts the camera controls for first-person aiming. Invert Y is the default and matches the original game.

- Analog cam description. + Enables an analog "free" camera similar to later entries in the series, which will be mapped to the right analog stick on your controller. +
+ When you move the right stick, the camera will enter "free" mode and stop centering behind Link. Press the Target button at any time to go back into "normal" camera. The camera will also return to "normal" mode after a cutscene plays or when you move between areas. +

+

+ Inverts the camera controls for the analog camera if it's enabled. None is the default.

diff --git a/include/recomp_input.h b/include/recomp_input.h index 4da126b..d2d718e 100644 --- a/include/recomp_input.h +++ b/include/recomp_input.h @@ -183,6 +183,9 @@ namespace recomp { CameraInvertMode get_camera_invert_mode(); void set_camera_invert_mode(CameraInvertMode mode); + CameraInvertMode get_analog_camera_invert_mode(); + void set_analog_camera_invert_mode(CameraInvertMode mode); + bool game_input_disabled(); bool all_input_disabled(); diff --git a/patches/camera_patches.c b/patches/camera_patches.c index f3e6086..db5b080 100644 --- a/patches/camera_patches.c +++ b/patches/camera_patches.c @@ -67,7 +67,7 @@ void update_analog_cam(Camera* c) { if (analog_cam_active) { s32 inverted_x, inverted_y; - recomp_get_inverted_axes(&inverted_x, &inverted_y); + recomp_get_analog_inverted_axes(&inverted_x, &inverted_y); if (inverted_x) { input_x = -input_x; @@ -78,7 +78,7 @@ void update_analog_cam(Camera* c) { } analog_camera_yaw_vel = -input_x * analog_camera_x_sensitivity; - analog_camera_pitch_vel = -input_y * analog_camera_y_sensitivity; + analog_camera_pitch_vel = input_y * analog_camera_y_sensitivity; analog_camera_pos.pitch += analog_camera_pitch_vel; analog_camera_pos.yaw += analog_camera_yaw_vel; @@ -87,10 +87,11 @@ void update_analog_cam(Camera* c) { analog_camera_pos.pitch = 0x36B0; } - // -76.9 degrees - if (analog_camera_pos.pitch < -0x36B0) { - analog_camera_pos.pitch = -0x36B0; + if (analog_camera_pos.pitch < -0x16D0) { + analog_camera_pos.pitch = -0x16D0; } + + recomp_printf("analog cam pitch: %05X\n", analog_camera_pos.pitch); } } diff --git a/patches/input.c b/patches/input.c index 4e7e1fe..61f8133 100644 --- a/patches/input.c +++ b/patches/input.c @@ -13,12 +13,25 @@ s32 func_8082EF20(Player* this); s32 func_80847190(PlayState* play, Player* this, s32 arg2) { s32 pad; s16 var_s0; + // @recomp Get the aiming camera inversion state. + s32 inverted_x, inverted_y; + recomp_get_inverted_axes(&inverted_x, &inverted_y); if (!func_800B7128(this) && !func_8082EF20(this) && !arg2) { + var_s0 = play->state.input[0].rel.stick_y * 0xF0; + + // @recomp Invert the Y axis accordingly (default is inverted, so negate if not inverted). + if (!inverted_y) { + var_s0 = -var_s0; + } Math_SmoothStepToS(&this->actor.focus.rot.x, var_s0, 0xE, 0xFA0, 0x1E); var_s0 = play->state.input[0].rel.stick_x * -0x10; + // @recomp Invert the X axis accordingly + if (inverted_x) { + var_s0 = -var_s0; + } var_s0 = CLAMP(var_s0, -0xBB8, 0xBB8); this->actor.focus.rot.y += var_s0; } @@ -62,8 +75,14 @@ s32 func_80847190(PlayState* play, Player* this, s32 arg2) { s16 temp3; - temp3 = ((play->state.input[0].rel.stick_y >= 0) ? 1 : -1) * - (s32)((1.0f - Math_CosS(play->state.input[0].rel.stick_y * 0xC8)) * 1500.0f); + // @recomp Invert the Y axis accordingly (default is inverted, so negate if not inverted). + s8 stick_y = play->state.input[0].rel.stick_y; + if (!inverted_y) { + stick_y = -stick_y; + } + + temp3 = ((stick_y >= 0) ? 1 : -1) * + (s32)((1.0f - Math_CosS(stick_y * 0xC8)) * 1500.0f); this->actor.focus.rot.x += temp3 + (s32)(target_aim_x - applied_aim_x); applied_aim_x = target_aim_x; @@ -75,8 +94,14 @@ s32 func_80847190(PlayState* play, Player* this, s32 arg2) { } var_s0 = this->actor.focus.rot.y - this->actor.shape.rot.y; - temp3 = ((play->state.input[0].rel.stick_x >= 0) ? 1 : -1) * - (s32)((1.0f - Math_CosS(play->state.input[0].rel.stick_x * 0xC8)) * -1500.0f); + + // @recomp Invert the X axis accordingly. + s8 stick_x = play->state.input[0].rel.stick_x; + if (inverted_x) { + stick_x = -stick_x; + } + temp3 = ((stick_x >= 0) ? 1 : -1) * + (s32)((1.0f - Math_CosS(stick_x * 0xC8)) * -1500.0f); var_s0 += temp3 + (s32)(target_aim_y - applied_aim_y); applied_aim_y = target_aim_y; diff --git a/patches/input.h b/patches/input.h index bd234f5..0f00e36 100644 --- a/patches/input.h +++ b/patches/input.h @@ -15,6 +15,7 @@ DECLARE_FUNC(void, recomp_get_mouse_deltas, float* x, float* y); DECLARE_FUNC(s32, recomp_get_targeting_mode); DECLARE_FUNC(void, recomp_get_inverted_axes, s32* x, s32* y); DECLARE_FUNC(s32, recomp_analog_cam_enabled); +DECLARE_FUNC(void, recomp_get_analog_inverted_axes, s32* x, s32* y); DECLARE_FUNC(void, recomp_get_camera_inputs, float* x, float* y); DECLARE_FUNC(void, recomp_set_right_analog_suppressed, s32 suppressed); diff --git a/patches/syms.ld b/patches/syms.ld index cc5a433..dced678 100644 --- a/patches/syms.ld +++ b/patches/syms.ld @@ -58,3 +58,4 @@ recomp_set_right_analog_suppressed = 0x8F0000A0; recomp_get_inverted_axes = 0x8F0000A4; recomp_high_precision_fb_enabled = 0x8F0000A8; recomp_get_resolution_scale = 0x8F0000AC; +recomp_get_analog_inverted_axes = 0x8F0000B0; diff --git a/src/game/config.cpp b/src/game/config.cpp index 2ecdb52..9e31488 100644 --- a/src/game/config.cpp +++ b/src/game/config.cpp @@ -167,6 +167,7 @@ void save_general_config(const std::filesystem::path& path) { config_json["autosave_mode"] = recomp::get_autosave_mode(); config_json["camera_invert_mode"] = recomp::get_camera_invert_mode(); config_json["analog_cam_mode"] = recomp::get_analog_cam_mode(); + config_json["analog_camera_invert_mode"] = recomp::get_analog_camera_invert_mode(); config_json["debug_mode"] = recomp::get_debug_mode_enabled(); config_file << std::setw(4) << config_json; } @@ -181,6 +182,7 @@ void set_general_settings_from_json(const nlohmann::json& config_json) { recomp::set_autosave_mode(from_or_default(config_json, "autosave_mode", recomp::AutosaveMode::On)); recomp::set_camera_invert_mode(from_or_default(config_json, "camera_invert_mode", recomp::CameraInvertMode::InvertY)); recomp::set_analog_cam_mode(from_or_default(config_json, "analog_cam_mode", recomp::AnalogCamMode::Off)); + recomp::set_analog_camera_invert_mode(from_or_default(config_json, "analog_camera_invert_mode", recomp::CameraInvertMode::InvertNone)); recomp::set_debug_mode_enabled(from_or_default(config_json, "debug_mode", false)); } diff --git a/src/game/recomp_api.cpp b/src/game/recomp_api.cpp index b71ae75..d993971 100644 --- a/src/game/recomp_api.cpp +++ b/src/game/recomp_api.cpp @@ -121,6 +121,16 @@ extern "C" void recomp_get_inverted_axes(uint8_t* rdram, recomp_context* ctx) { *y_out = (mode == recomp::CameraInvertMode::InvertY || mode == recomp::CameraInvertMode::InvertBoth); } +extern "C" void recomp_get_analog_inverted_axes(uint8_t* rdram, recomp_context* ctx) { + s32* x_out = _arg<0, s32*>(rdram, ctx); + s32* y_out = _arg<1, s32*>(rdram, ctx); + + recomp::CameraInvertMode mode = recomp::get_analog_camera_invert_mode(); + + *x_out = (mode == recomp::CameraInvertMode::InvertX || mode == recomp::CameraInvertMode::InvertBoth); + *y_out = (mode == recomp::CameraInvertMode::InvertY || mode == recomp::CameraInvertMode::InvertBoth); +} + extern "C" void recomp_analog_cam_enabled(uint8_t* rdram, recomp_context* ctx) { _return(ctx, recomp::get_analog_cam_mode() == recomp::AnalogCamMode::On); } diff --git a/src/ui/ui_config.cpp b/src/ui/ui_config.cpp index a6bf2f9..ec25ab2 100644 --- a/src/ui/ui_config.cpp +++ b/src/ui/ui_config.cpp @@ -280,6 +280,7 @@ struct ControlOptionsContext { recomp::AutosaveMode autosave_mode; recomp::CameraInvertMode camera_invert_mode; recomp::AnalogCamMode analog_cam_mode; + recomp::CameraInvertMode analog_camera_invert_mode; }; ControlOptionsContext control_options_context; @@ -389,6 +390,17 @@ void recomp::set_analog_cam_mode(recomp::AnalogCamMode mode) { } } +recomp::CameraInvertMode recomp::get_analog_camera_invert_mode() { + return control_options_context.analog_camera_invert_mode; +} + +void recomp::set_analog_camera_invert_mode(recomp::CameraInvertMode mode) { + control_options_context.analog_camera_invert_mode = mode; + if (general_model_handle) { + general_model_handle.DirtyVariable("analog_camera_invert_mode"); + } +} + struct SoundOptionsContext { std::atomic main_volume; // Option to control the volume of all sound std::atomic bgm_volume; @@ -890,6 +902,7 @@ public: bind_option(constructor, "autosave_mode", &control_options_context.autosave_mode); bind_option(constructor, "camera_invert_mode", &control_options_context.camera_invert_mode); bind_option(constructor, "analog_cam_mode", &control_options_context.analog_cam_mode); + bind_option(constructor, "analog_camera_invert_mode", &control_options_context.analog_camera_invert_mode); general_model_handle = constructor.GetModelHandle(); }