From e2f3898ef8b64bbcc042f382456dbbdc0e45ab41 Mon Sep 17 00:00:00 2001 From: LT-Schmiddy Date: Fri, 30 May 2025 22:30:38 -0400 Subject: [PATCH] mouse input mod API implemented --- include/recomp_input.h | 4 ++++ patches/play_patches.c | 30 +++++++++++++++++++++++++++++- patches/play_patches.h | 5 +++++ patches/syms.ld | 4 ++++ src/game/input.cpp | 23 ++++++++++++++++++++--- src/game/recomp_api.cpp | 18 ++++++++++++++++++ 6 files changed, 80 insertions(+), 4 deletions(-) diff --git a/include/recomp_input.h b/include/recomp_input.h index 8599628..064a6b0 100644 --- a/include/recomp_input.h +++ b/include/recomp_input.h @@ -76,6 +76,10 @@ namespace recomp { bool get_input_digital(const std::span fields); void get_gyro_deltas(float* x, float* y); void get_mouse_deltas(float* x, float* y); + int32_t get_mouse_wheel_pos(); + uint32_t get_mouse_buttons(); + uint32_t get_mouse_button_mask(); + void set_mouse_button_mask(uint32_t mask); void get_right_analog(float* x, float* y); enum class InputDevice { diff --git a/patches/play_patches.c b/patches/play_patches.c index 57767a9..f112abe 100644 --- a/patches/play_patches.c +++ b/patches/play_patches.c @@ -38,8 +38,11 @@ void controls_play_update(PlayState* play) { Player* player = GET_PLAYER(play); Camera* camera = GET_ACTIVE_CAM(play); + // Looks like this function doesn't like to be called more than once per frame. + // We'll cache the results here for other stuff to use. recomp_get_mouse_deltas(&mouse_input_handler.delta_x, &mouse_input_handler.delta_y); - //mouse_input_handler.crouch_shielding = player->stateFlags1 == PLAYER_STATE1_400000; + recomp_printf("Mouse Wheel Pos: %i\n", recomp_get_mouse_wheel_pos()); + // Best way I could come up with to reallow mouse movement when lockon shielding. mouse_input_handler.crouch_shielding = ((player->stateFlags1 == PLAYER_STATE1_400000) && !(camera->mode == CAM_MODE_TARGET || camera->mode == CAM_MODE_FOLLOWTARGET)); if (mouse_input_handler.crouch_shielding) { @@ -53,6 +56,31 @@ void controls_play_update(PlayState* play) { mouse_input_handler.shield_pos_y = 0.0f; } } + // @recomp mouse deltas export +RECOMP_EXPORT void zelda64_get_mouse_deltas(float* x, float* y) { + *x = mouse_input_handler.delta_x; + *y = mouse_input_handler.delta_y; +} + +RECOMP_EXPORT unsigned int zelda64_get_mouse_wheel_pos() { + return recomp_get_mouse_buttons(); +} + +// @recomp mouse deltas export +RECOMP_EXPORT unsigned int zelda64_get_mouse_buttons() { + return recomp_get_mouse_buttons(); +} + +RECOMP_EXPORT unsigned int zelda64_get_mouse_button_mask() { + return recomp_get_mouse_button_mask(); +} + +RECOMP_EXPORT void zelda64_set_mouse_button_mask(unsigned int mask) { + recomp_set_mouse_button_mask(mask); +} +// The zelda64 prefix is temporary. I can't have the names conflict with the recomp API, +// but those are the most fitting. A better solution is desired. + // @recomp Patched to add hooks for various added functionality. RECOMP_PATCH void Play_Main(GameState* thisx) { diff --git a/patches/play_patches.h b/patches/play_patches.h index a72c922..a144bcb 100644 --- a/patches/play_patches.h +++ b/patches/play_patches.h @@ -2,6 +2,7 @@ #define __PLAY_PATCHES_H__ #include "patches.h" +#include "patch_helpers.h" #define MOUSE_SHIELD_CLAMP_X 7200.0f #define MOUSE_SHIELD_CLAMP_Y 10800.0f @@ -27,4 +28,8 @@ void analog_cam_post_play_update(PlayState* play); void matrix_play_update(PlayState* play); void autosave_post_play_update(PlayState* play); +DECLARE_FUNC(unsigned int, recomp_get_mouse_buttons, ); +DECLARE_FUNC(unsigned int, recomp_get_mouse_button_mask, ); +DECLARE_FUNC(void, recomp_set_mouse_button_mask, unsigned int); +DECLARE_FUNC(unsigned int, recomp_get_mouse_wheel_pos, ); #endif diff --git a/patches/syms.ld b/patches/syms.ld index 2efa2c9..d070411 100644 --- a/patches/syms.ld +++ b/patches/syms.ld @@ -53,3 +53,7 @@ recomp_create_actor_data = 0x8F0000C8; recomp_destroy_actor_data = 0x8F0000CC; recomp_get_actor_data = 0x8F0000D0; recomp_get_actor_spawn_index = 0x8F0000D4; +recomp_get_mouse_buttons = 0x8F0000D8; +recomp_get_mouse_button_mask = 0x8F0000DC; +recomp_set_mouse_button_mask = 0x8F0000E0; +recomp_get_mouse_wheel_pos = 0x8F0000E4; \ No newline at end of file diff --git a/src/game/input.cpp b/src/game/input.cpp index 54aeaff..6a25f71 100644 --- a/src/game/input.cpp +++ b/src/game/input.cpp @@ -28,7 +28,8 @@ static struct { const Uint8* keys = nullptr; SDL_Keymod keymod = SDL_Keymod::KMOD_NONE; int numkeys = 0; - unsigned int mouse_button_state; + std::atomic mouse_button_state; + std::atomic mouse_button_mask = ~0; std::atomic_int32_t mouse_wheel_pos = 0; std::mutex cur_controllers_mutex; std::vector cur_controllers{}; @@ -488,7 +489,7 @@ const recomp::DefaultN64Mappings recomp::default_n64_controller_mappings = { }; void recomp::poll_inputs() { - InputState.mouse_button_state = SDL_GetMouseState(NULL, NULL); + InputState.mouse_button_state.store(SDL_GetMouseState(NULL, NULL)); InputState.keys = SDL_GetKeyboardState(&InputState.numkeys); InputState.keymod = SDL_GetModState(); @@ -678,7 +679,7 @@ bool recomp::get_input_digital(const recomp::InputField& field) { return controller_axis_state(field.input_id, true) >= axis_threshold; case InputType::Mouse: //std::cout << "Mouse State: " << InputState.mouse_button_state << "\n"; - return InputState.mouse_button_state & (1 << field.input_id); + return (InputState.mouse_button_state.load() & InputState.mouse_button_mask.load()) & (1 << field.input_id); // TODO mouse support return false; case InputType::None: @@ -708,6 +709,22 @@ void recomp::get_mouse_deltas(float* x, float* y) { *y = cur_mouse_delta[1] * sensitivity; } +int32_t recomp::get_mouse_wheel_pos() { + return InputState.mouse_wheel_pos.load(); +} + +uint32_t recomp::get_mouse_buttons() { + return InputState.mouse_button_state.load(); +} + +uint32_t recomp::get_mouse_button_mask() { + return InputState.mouse_button_mask.load(); +} + +void recomp::set_mouse_button_mask(unsigned int mask) { + return InputState.mouse_button_mask.store(mask); +} + void recomp::apply_joystick_deadzone(float x_in, float y_in, float* x_out, float* y_out) { float joystick_deadzone = (float)recomp::get_joystick_deadzone() / 100.0f; diff --git a/src/game/recomp_api.cpp b/src/game/recomp_api.cpp index 9ad08be..5d9170e 100644 --- a/src/game/recomp_api.cpp +++ b/src/game/recomp_api.cpp @@ -45,6 +45,24 @@ extern "C" void recomp_get_mouse_deltas(uint8_t* rdram, recomp_context* ctx) { recomp::get_mouse_deltas(x_out, y_out); } +extern "C" void recomp_get_mouse_wheel_pos(uint8_t* rdram, recomp_context* ctx) { + _return(ctx, recomp::get_mouse_wheel_pos()); +} + +extern "C" void recomp_get_mouse_buttons(uint8_t* rdram, recomp_context* ctx) { + _return(ctx, recomp::get_mouse_buttons()); +} + +extern "C" void recomp_get_mouse_button_mask(uint8_t* rdram, recomp_context* ctx) { + _return(ctx, recomp::get_mouse_button_mask()); +} + +extern "C" void recomp_set_mouse_button_mask(uint8_t* rdram, recomp_context* ctx) { + unsigned int out = _arg<0, unsigned int>(rdram, ctx); + recomp::set_mouse_button_mask(out); +} + + extern "C" void recomp_powf(uint8_t* rdram, recomp_context* ctx) { float a = _arg<0, float>(rdram, ctx); float b = ctx->f14.fl; //_arg<1, float>(rdram, ctx);