This commit is contained in:
LT_SCHMIDDY 2026-05-18 19:50:36 +02:00 committed by GitHub
commit c35fa4de8d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 174 additions and 17 deletions

View file

@ -31,8 +31,7 @@
"cmakeCommandArgs": "",
"buildCommandArgs": "",
"ctestCommandArgs": "",
"inheritEnvironments": [ "clang_cl_x64" ],
"variables": []
"inheritEnvironments": [ "clang_cl_x64" ]
}
]
}

BIN
CONTRIB-Zelda64Recomp.zip Normal file

Binary file not shown.

View file

@ -0,0 +1,3 @@
./N64Recomp us.rev1.toml
./RSPRecomp aspMain.us.rev1.toml
./RSPRecomp njpgdspMain.us.rev1.toml

View file

@ -76,6 +76,10 @@ namespace recomp {
bool get_input_digital(const std::span<const recomp::InputField> 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 {

View file

@ -28,6 +28,8 @@ float analog_camera_y_sensitivity = 500.0f;
static const float analog_cam_threshold = 0.1f;
float mouse_camera_sensitivity = 0.1f;
RECOMP_EXPORT void recomp_set_camera_fixes(bool new_val) {
camera_fixes = new_val;
}
@ -66,8 +68,12 @@ void update_analog_cam(Camera* c) {
}
// Enable analog cam if the right stick is held.
float input_x, input_y;
recomp_get_camera_inputs(&input_x, &input_y);
float analog_x, analog_y;
recomp_get_camera_inputs(&analog_x, &analog_y);
float input_x = analog_x + (mouse_input_handler.crouch_shielding ? 0.0f : mouse_input_handler.delta_x * MOUSE_CAMERA_SCALE_X);
float input_y = analog_y + (mouse_input_handler.crouch_shielding ? 0.0f : mouse_input_handler.delta_y * MOUSE_CAMERA_SCALE_Y);
if (fabsf(input_x) >= analog_cam_threshold || fabsf(input_y) >= analog_cam_threshold) {
analog_cam_active = true;

View file

@ -1,4 +1,5 @@
#include "patches.h"
#include "play_patches.h"
#include "input.h"
#include "z64snap.h"
// Decomp rename, TODO update decomp and remove this
@ -6,6 +7,8 @@
#include "z64voice.h"
#include "audiothread_cmd.h"
MouseInputHandler mouse_input_handler;
RECOMP_DECLARE_EVENT(recomp_before_first_person_aiming_update_event(PlayState* play, Player* this, bool in_free_look, RecompAimingOverideMode* recomp_aiming_override_mode));
RECOMP_DECLARE_EVENT(recomp_after_first_person_aiming_update_event(PlayState* play, Player* this, bool in_free_look));
RECOMP_DECLARE_EVENT(recomp_set_extra_item_slot_statuses(PlayState* play, s32 enabled));
@ -102,12 +105,9 @@ RECOMP_PATCH s32 func_80847190(PlayState* play, Player* this, s32 arg2) {
filtered_gyro_x = filtered_gyro_x * gyro_filter_factor + total_gyro_x * (1.0f - gyro_filter_factor);
filtered_gyro_y = filtered_gyro_y * gyro_filter_factor + total_gyro_y * (1.0f - gyro_filter_factor);
float delta_mouse_x, delta_mouse_y;
recomp_get_mouse_deltas(&delta_mouse_x, &delta_mouse_y);
total_mouse_x += delta_mouse_x;
total_mouse_y += delta_mouse_y;
total_mouse_x += mouse_input_handler.delta_x;
total_mouse_y += mouse_input_handler.delta_y;
// The gyro X-axis (tilt) corresponds to the camera X-axis (tilt).
// The gyro Y-axis (left/right rotation) corresponds to the camera Y-axis (left/right rotation).
@ -1473,10 +1473,13 @@ RECOMP_PATCH void Player_Action_18(Player* this, PlayState* play) {
func_8082F164(this, BTN_R | BTN_B);
}
}
if (this->av2.actionVar2 != 0) {
f32 yStick = sPlayerControlInput->rel.stick_y * 180;
f32 xStick = sPlayerControlInput->rel.stick_x * -120;
f32 yStick = sPlayerControlInput->rel.stick_y * 180 + mouse_input_handler.shield_pos_y;
f32 xStick = sPlayerControlInput->rel.stick_x * -120 + mouse_input_handler.shield_pos_x;
// Needed so analog input and mouse input don't double up.
xStick = CLAMP(xStick, -MOUSE_SHIELD_CLAMP_X, MOUSE_SHIELD_CLAMP_X);
yStick = CLAMP(yStick, -MOUSE_SHIELD_CLAMP_Y, MOUSE_SHIELD_CLAMP_Y);
s16 temp_a0 = this->actor.shape.rot.y - Camera_GetInputDirYaw(GET_ACTIVE_CAM(play));
s16 var_a1;
s16 temp_ft5;
@ -1493,7 +1496,6 @@ RECOMP_PATCH void Player_Action_18(Player* this, PlayState* play) {
if (inverted_x) {
xStick = -xStick;
}
var_a1 = (yStick * Math_CosS(temp_a0)) + (Math_SinS(temp_a0) * xStick);
temp_ft5 = (xStick * Math_CosS(temp_a0)) - (Math_SinS(temp_a0) * yStick);

View file

@ -34,7 +34,53 @@ RECOMP_DECLARE_EVENT(recomp_after_play_update(PlayState* play));
void controls_play_update(PlayState* play) {
gSaveContext.options.zTargetSetting = recomp_get_targeting_mode();
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);
// 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) {
mouse_input_handler.shield_pos_x -= mouse_input_handler.delta_x * 10.0f;
mouse_input_handler.shield_pos_y -= mouse_input_handler.delta_y * 10.0f;
mouse_input_handler.shield_pos_x = CLAMP(mouse_input_handler.shield_pos_x, -MOUSE_SHIELD_CLAMP_X, MOUSE_SHIELD_CLAMP_X);
mouse_input_handler.shield_pos_y = CLAMP(mouse_input_handler.shield_pos_y, -MOUSE_SHIELD_CLAMP_Y, MOUSE_SHIELD_CLAMP_Y);
}
else {
mouse_input_handler.shield_pos_x = 0.0f;
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) {
@ -174,6 +220,11 @@ RECOMP_PATCH void Play_Init(GameState* thisx) {
// @recomp_event recomp_on_play_init(PlayState* this): A new PlayState is being initialized.
recomp_on_play_init(this);
mouse_input_handler.crouch_shielding = false;
mouse_input_handler.delta_x = 0.0f;
mouse_input_handler.delta_y = 0.0f;
mouse_input_handler.shield_pos_x = 0.0f;
mouse_input_handler.shield_pos_y = 0.0f;
if ((gSaveContext.respawnFlag == -4) || (gSaveContext.respawnFlag == -0x63)) {
if (CHECK_EVENTINF(EVENTINF_TRIGGER_DAYTELOP)) {

View file

@ -2,6 +2,23 @@
#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
#define MOUSE_CAMERA_SCALE_X 0.04f
#define MOUSE_CAMERA_SCALE_Y 0.08f // For some reason, the vertical sensitivity seemed less than the horizontal. This compensates.
typedef struct {
float delta_x;
float delta_y;
bool crouch_shielding;
float shield_pos_x;
float shield_pos_y;
} MouseInputHandler;
extern MouseInputHandler mouse_input_handler;
void debug_play_update(PlayState* play);
void camera_pre_play_update(PlayState* play);
@ -11,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

View file

@ -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;

View file

@ -14,7 +14,7 @@
#elif defined(__linux__)
#include <unistd.h>
#include <pwd.h>
#elif defined(__APPLE__)
#elif defined(__APPLE__)
#include "apple/rt64_apple.h"
#endif

View file

@ -1,5 +1,6 @@
#include <atomic>
#include <mutex>
#include <iostream>
#include "ultramodern/ultramodern.hpp"
#include "recomp.h"
@ -27,6 +28,8 @@ static struct {
const Uint8* keys = nullptr;
SDL_Keymod keymod = SDL_Keymod::KMOD_NONE;
int numkeys = 0;
std::atomic<unsigned int> mouse_button_state;
std::atomic<unsigned int> mouse_button_mask = ~0;
std::atomic_int32_t mouse_wheel_pos = 0;
std::mutex cur_controllers_mutex;
std::vector<SDL_GameController*> cur_controllers{};
@ -130,6 +133,25 @@ bool sdl_event_filter(void* userdata, SDL_Event* event) {
}
}
break;
case SDL_EventType::SDL_MOUSEBUTTONDOWN:
{
SDL_MouseButtonEvent* mouseevent = &event->button;
// Skip repeated events when not in the menu
if (!recompui::is_context_capturing_input()) {
break;
}
if (scanning_device != recomp::InputDevice::COUNT) {
if (scanning_device == recomp::InputDevice::Keyboard) {
set_scanned_input({ (uint32_t)InputType::Mouse, mouseevent->button - 1}); // subtract 1 because of the bit-shifting used to process SDL_GetMouseState
}
}
else {
queue_if_enabled(event);
}
}
break;
case SDL_EventType::SDL_CONTROLLERDEVICEADDED:
{
SDL_ControllerDeviceEvent* controller_event = &event->cdevice;
@ -334,7 +356,7 @@ const recomp::DefaultN64Mappings recomp::default_n64_keyboard_mappings = {
{.input_type = (uint32_t)InputType::Keyboard, .input_id = SDL_SCANCODE_SPACE}
},
.b = {
{.input_type = (uint32_t)InputType::Keyboard, .input_id = SDL_SCANCODE_LSHIFT}
{.input_type = (uint32_t)InputType::Mouse, .input_id = 0}
},
.l = {
{.input_type = (uint32_t)InputType::Keyboard, .input_id = SDL_SCANCODE_E}
@ -467,6 +489,8 @@ const recomp::DefaultN64Mappings recomp::default_n64_controller_mappings = {
};
void recomp::poll_inputs() {
InputState.mouse_button_state.store(SDL_GetMouseState(NULL, NULL));
InputState.keys = SDL_GetKeyboardState(&InputState.numkeys);
InputState.keymod = SDL_GetModState();
@ -654,8 +678,11 @@ bool recomp::get_input_digital(const recomp::InputField& field) {
// TODO adjustable threshold
return controller_axis_state(field.input_id, true) >= axis_threshold;
case InputType::Mouse:
// TODO mouse support
return false;
if (recomp::game_input_disabled()) {
return false;
}
return (InputState.mouse_button_state.load() & InputState.mouse_button_mask.load()) & (1 << field.input_id);
case InputType::None:
return false;
}
@ -683,6 +710,28 @@ void recomp::get_mouse_deltas(float* x, float* y) {
*y = cur_mouse_delta[1] * sensitivity;
}
int32_t recomp::get_mouse_wheel_pos() {
if (recomp::game_input_disabled()) {
return 0;
}
return InputState.mouse_wheel_pos.load();
}
uint32_t recomp::get_mouse_buttons() {
if (recomp::game_input_disabled()) {
return 0;
}
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;

View file

@ -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);