#include #include "librecomp/recomp.h" #include "librecomp/overlays.hpp" #include "librecomp/config_store.hpp" #include "zelda_config.h" #include "recomp_input.h" #include "recomp_ui.h" #include "zelda_render.h" #include "zelda_sound.h" #include "librecomp/helpers.hpp" #include "../patches/input.h" #include "../patches/graphics.h" #include "../patches/sound.h" #include "ultramodern/ultramodern.hpp" #include "ultramodern/config.hpp" extern "C" void recomp_update_inputs(uint8_t* rdram, recomp_context* ctx) { recomp::poll_inputs(); } extern "C" void recomp_puts(uint8_t* rdram, recomp_context* ctx) { PTR(char) cur_str = _arg<0, PTR(char)>(rdram, ctx); u32 length = _arg<1, u32>(rdram, ctx); for (u32 i = 0; i < length; i++) { fputc(MEM_B(i, (gpr)cur_str), stdout); } } extern "C" void recomp_exit(uint8_t* rdram, recomp_context* ctx) { ultramodern::quit(); } extern "C" void recomp_get_gyro_deltas(uint8_t* rdram, recomp_context* ctx) { float* x_out = _arg<0, float*>(rdram, ctx); float* y_out = _arg<1, float*>(rdram, ctx); recomp::get_gyro_deltas(x_out, y_out); } extern "C" void recomp_get_mouse_deltas(uint8_t* rdram, recomp_context* ctx) { float* x_out = _arg<0, float*>(rdram, ctx); float* y_out = _arg<1, float*>(rdram, ctx); recomp::get_mouse_deltas(x_out, y_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); _return(ctx, std::pow(a, b)); } extern "C" void recomp_get_target_framerate(uint8_t* rdram, recomp_context* ctx) { int frame_divisor = _arg<0, u32>(rdram, ctx); _return(ctx, ultramodern::get_target_framerate(60 / frame_divisor)); } extern "C" void recomp_get_aspect_ratio(uint8_t* rdram, recomp_context* ctx) { ultramodern::renderer::GraphicsConfig graphics_config = ultramodern::renderer::get_graphics_config(); float original = _arg<0, float>(rdram, ctx); int width, height; recompui::get_window_size(width, height); switch (graphics_config.ar_option) { case ultramodern::renderer::AspectRatio::Original: default: _return(ctx, original); return; case ultramodern::renderer::AspectRatio::Expand: _return(ctx, std::max(static_cast(width) / height, original)); return; } } extern "C" void recomp_get_targeting_mode(uint8_t* rdram, recomp_context* ctx) { _return(ctx, static_cast(zelda64::get_targeting_mode())); } extern "C" void recomp_get_bgm_volume(uint8_t* rdram, recomp_context* ctx) { _return(ctx, zelda64::get_bgm_volume() / 100.0f); } extern "C" void recomp_get_low_health_beeps_enabled(uint8_t* rdram, recomp_context* ctx) { _return(ctx, static_cast(zelda64::get_low_health_beeps_enabled())); } 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(zelda64::get_autosave_mode() == zelda64::AutosaveMode::On)); } extern "C" void recomp_load_overlays(uint8_t * rdram, recomp_context * ctx) { u32 rom = _arg<0, u32>(rdram, ctx); PTR(void) ram = _arg<1, PTR(void)>(rdram, ctx); u32 size = _arg<2, u32>(rdram, ctx); load_overlays(rom, ram, size); } extern "C" void recomp_high_precision_fb_enabled(uint8_t * rdram, recomp_context * ctx) { _return(ctx, static_cast(zelda64::renderer::RT64HighPrecisionFBEnabled())); } extern "C" void recomp_get_resolution_scale(uint8_t* rdram, recomp_context* ctx) { _return(ctx, ultramodern::get_resolution_scale()); } extern "C" void recomp_get_inverted_axes(uint8_t* rdram, recomp_context* ctx) { s32* x_out = _arg<0, s32*>(rdram, ctx); s32* y_out = _arg<1, s32*>(rdram, ctx); zelda64::CameraInvertMode mode = zelda64::get_camera_invert_mode(); *x_out = (mode == zelda64::CameraInvertMode::InvertX || mode == zelda64::CameraInvertMode::InvertBoth); *y_out = (mode == zelda64::CameraInvertMode::InvertY || mode == zelda64::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); zelda64::CameraInvertMode mode = zelda64::get_analog_camera_invert_mode(); *x_out = (mode == zelda64::CameraInvertMode::InvertX || mode == zelda64::CameraInvertMode::InvertBoth); *y_out = (mode == zelda64::CameraInvertMode::InvertY || mode == zelda64::CameraInvertMode::InvertBoth); } extern "C" void recomp_analog_cam_enabled(uint8_t* rdram, recomp_context* ctx) { _return(ctx, zelda64::get_analog_cam_mode() == zelda64::AnalogCamMode::On); } extern "C" void recomp_get_camera_inputs(uint8_t* rdram, recomp_context* ctx) { float* x_out = _arg<0, float*>(rdram, ctx); float* y_out = _arg<1, float*>(rdram, ctx); // TODO expose this in the menu constexpr float radial_deadzone = 0.05f; float x, y; recomp::get_right_analog(&x, &y); float magnitude = sqrtf(x * x + y * y); if (magnitude < radial_deadzone) { *x_out = 0.0f; *y_out = 0.0f; } else { float x_normalized = x / magnitude; float y_normalized = y / magnitude; *x_out = x_normalized * ((magnitude - radial_deadzone) / (1 - radial_deadzone)); *y_out = y_normalized * ((magnitude - radial_deadzone) / (1 - radial_deadzone)); } } extern "C" void recomp_set_right_analog_suppressed(uint8_t* rdram, recomp_context* ctx) { s32 suppressed = _arg<0, s32>(rdram, ctx); recomp::set_right_analog_suppressed(suppressed); } extern "C" void recomp_get_config_store_int(uint8_t* rdram, recomp_context* ctx) { thread_local std::vector key_buffer{}; key_buffer.clear(); char c; PTR(char) cur_char = _arg<0, PTR(char)>(rdram, ctx); size_t i = 0; while ((c = MEM_B(cur_char, i)) != '\0') { key_buffer.push_back(c); i++; } _return(ctx, recomp::get_config_store_value( std::string_view{key_buffer.data(), key_buffer.size()} )); }