From 9719af9578f854bd7ed54db6335eb9639f36e8b7 Mon Sep 17 00:00:00 2001 From: SuddyN Date: Sun, 10 May 2026 17:30:08 -0400 Subject: [PATCH 1/5] less delay initial commit --- Cargo.toml | 7 +--- src/chara_select/player_port.rs | 71 +++++++++++++++++++++++++-------- src/controls.rs | 1 - src/lib.rs | 3 -- src/vsync.rs | 50 ----------------------- symbaker.toml | 6 --- 6 files changed, 57 insertions(+), 81 deletions(-) delete mode 100644 src/vsync.rs delete mode 100644 symbaker.toml diff --git a/Cargo.toml b/Cargo.toml index f79445337c..7d82011a66 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,15 +8,11 @@ version = "0.0.0-dev" authors = ["HDR Development Team"] edition = "2021" -[workspace.metadata.symbaker] -prefix = "hdr" - [workspace.dependencies] skyline = { git = "https://github.com/ultimate-research/skyline-rs" } skyline_smash = { git = "https://github.com/ultimate-research/skyline-smash", features = ["weak_l2cvalue"] } skyline-web = { git = "https://github.com/skyline-rs/skyline-web" } smashline = { git = "https://github.com/HDR-Development/smashline" } -# ssbusync = { git = "https://github.com/BlankMauser/ssbu-sync.git", tag = "1.0.3", default-features = false } proc-hitbox = { git = "https://github.com/HDR-Development/compile-time-smash-script" } proc-hitbox-macro = { git = "https://github.com/HDR-Development/compile-time-smash-script" } @@ -233,15 +229,16 @@ runtime-motion-patcher.git = "https://github.com/WuBoytH/runtime-motion-patcher" skyline.workspace = true skyline_smash.workspace = true smashline.workspace = true -# ssbusync = { git = "https://github.com/BlankMauser/ssbu-sync.git", tag = "1.0.3", default-features = false, features = ["disabler-symbol"] } skyline-web = { workspace = true, optional = true } utils.workspace = true hash40 = "1.2.0" smash-arc = { version = "0.6.0", features = ["rust-zstd", "smash-runtime"] } smash2 = { git = "https://github.com/WuBoytH/smash-rs", package = "smash"} rlua-lua53-sys = { git = "https://github.com/HDR-Development/rlua", branch = "smash" } +ultelier = { git = "https://github.com/BlankMauser/smash-ultelier.git", default-features = false, features = ["sync-guest"] } [patch.crates-io] +skyline = { git = "https://github.com/ultimate-research/skyline-rs" } nnsdk = { git = "https://github.com/ultimate-research/nnsdk-rs" } libc = { git="https://github.com/rust-lang/libc", rev = "0.2.166"} diff --git a/src/chara_select/player_port.rs b/src/chara_select/player_port.rs index 79be9485f8..fd14e7957a 100644 --- a/src/chara_select/player_port.rs +++ b/src/chara_select/player_port.rs @@ -1,7 +1,7 @@ use super::*; use ninput::*; use parking_lot::RwLock; -// use crate::vsync::SsbuSync; +use ultelier::sync_guest::{self as sync, BufferMode}; static ID_LIST: &[u32] = &[0, 1, 2, 3, 4, 5, 6, 7, 0x20]; @@ -13,7 +13,9 @@ struct PortData { enable_swap: bool, root_card: u64, active_controllers: Vec, - swap_target: Option + swap_target: Option, + sync_guest_missing: bool, + last_buffer_mode: Option, } impl Default for PortData { fn default() -> Self { @@ -21,7 +23,9 @@ impl Default for PortData { enable_swap: false, root_card: 0x0, active_controllers: Vec::new(), - swap_target: None + swap_target: None, + sync_guest_missing: false, + last_buffer_mode: None, } } } @@ -188,6 +192,47 @@ unsafe fn count_active_players(instance: CharaSelect) -> i32 { active_players } +fn update_css_buffer_mode(data: &mut PortData, player_count: i32) { + if data.sync_guest_missing { + return; + } + + let desired_mode = if player_count <= 2 { + BufferMode::Double + } else { + BufferMode::Triple + }; + + let current_mode = match sync::env_flags() { + Some(flags) => { + if flags.contains(sync::EnvironmentFlags::TRIPLE_ENABLED) { + BufferMode::Triple + } else { + BufferMode::Double + } + } + None => { + data.sync_guest_missing = true; + return; + } + }; + + if current_mode == desired_mode { + data.last_buffer_mode = Some(desired_mode); + return; + } + + match sync::set_buffer_mode(desired_mode) { + Some(true) => { + data.last_buffer_mode = Some(desired_mode); + } + Some(false) => {} + None => { + data.sync_guest_missing = true; + } + } +} + static mut IS_UNPRESSED : bool = false; // this function loops while the css is active, allowing for runtime operations #[skyline::hook(offset = 0x1a2b570)] @@ -220,19 +265,9 @@ unsafe fn css_main_loop(arg: *const CharaSelect) { data.enable_swap = true; data.root_card = instance.first_player as u64; } - - // TODO: implement buffer swap for >2 players - // if SsbuSync::ALLOW_BUFFER_SWAP() { - // let player_count = count_active_players(instance); - // crate::set_doubles_delay(player_count); - // ssbusync::Check_Buffer_Swap(); - // } - - // TODO: is this really the best way to check for online gamemodes? - // let is_online = (instance.max_players_allowed != 8 || instance.local_wireless != 0); - // if SsbuSync::SyncEnv::online_only() { - // SsbuSync::online::ToggleOnlineFix(is_online); - // } + + let player_count = count_active_players(instance); + update_css_buffer_mode(&mut data, player_count); if !data.enable_swap || instance.ready_state != 0 { return original!()(arg); @@ -430,6 +465,10 @@ unsafe fn controller_something_off(wireless_state: u32, player: *const PlayerInf unsafe fn controller_token_off(css_instance: *const CharaSelect, player: *const PlayerInfo); pub fn install() { + //*Install only menu hooks to run without custom overclocker. + //sync::runtime::install_menu_hooks(); + + sync::runtime::install_auto_profile_switcher(); skyline::install_hooks!( css_main_loop, init_css_player diff --git a/src/controls.rs b/src/controls.rs index 6116bce913..871e7c7816 100644 --- a/src/controls.rs +++ b/src/controls.rs @@ -1,7 +1,6 @@ use skyline::hooks::InlineCtx; use std::sync::atomic::Ordering; use utils::consts::{melee_mode, smash_mode}; -// use ssbusync::*; mod css; mod submenu; diff --git a/src/lib.rs b/src/lib.rs index ea39e8fedb..b452518dbe 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -39,8 +39,6 @@ mod online; #[cfg(feature = "main_nro")] mod matchup; -pub mod vsync; - use skyline::libc::c_char; use std::os::raw::c_void; #[cfg(feature = "main_nro")] @@ -421,7 +419,6 @@ fn save_report_stub(uid: *mut u8) { } pub fn main() { #[cfg(feature = "main_nro")] { - // vsync::setup_ssbu_sync(); quick_validate_install(); skyline::install_hooks!(change_version_string_hook); chara_select::install(); diff --git a/src/vsync.rs b/src/vsync.rs deleted file mode 100644 index 1cd18140b1..0000000000 --- a/src/vsync.rs +++ /dev/null @@ -1,50 +0,0 @@ -// pub use ssbusync as SsbuSync; -// use SsbuSync::*; - -// pub fn setup_ssbu_sync() { -// println!("[HDR] installing custom ssbusync path via Main \n"); -// let mut sync_config = SsbuSyncConfig::default(); -// sync_config.disable_vsync = true; -// sync_config.disable_pacer = false; -// sync_config.slow_pacer_bias = false; -// sync_config.enable_triple_buffer = false; -// sync_config.allow_buffer_swap = false; -// sync_config.smooth_ffa = false; -// sync_config.online_only = false; - -// // create a profile with ssbusync config -// // but we don't actually use the options that are stored in that profile if they are changed by the user -// SsbuSync::Get_Init_SsbuSync_Profile("HDR", &sync_config, 1.0); -// ssbusync::Install_SSBU_Sync(sync_config); - -// // if ssbusync::render::buffer_swap::subscribe_buffer_mode_change(on_buffer_switch) { -// // println!("[HDR] Subscribed to buffer switch \n"); -// // } else { -// // println!("[HDR] Failed to subscribe to buffer switch \n"); -// // } -// } - -// Work-around for setting input delay during doubles/FFAs -// pub fn set_doubles_delay(playercount: i32) -> bool { -// if (playercount > 2) { -// ssbusync::Enable_Triple_Buffer(); -// return true; -// } else { -// ssbusync::Enable_Double_Buffer(); -// return false; -// } -// } - -// fn on_buffer_switch(mode: ssbusync::render::buffer_swap::BufferMode) { -// println!("Buffer Successfully Switched: {:?} \n", mode) -// } - -// if ssbusync::SyncEnv::ALLOW_BUFFER_SWAP() { -// let player_count = count_active_players(instance); -// crate::set_doubles_delay(player_count); -// ssbusync::Check_Buffer_Swap(); -// } - -// if ssbusync::SyncEnv::online_only() { -// EmuNetplay::check_online_fix_emu(); -// } \ No newline at end of file diff --git a/symbaker.toml b/symbaker.toml deleted file mode 100644 index a57fe14190..0000000000 --- a/symbaker.toml +++ /dev/null @@ -1,6 +0,0 @@ -prefix = "hdr" -sep = "__" -priority = ["attr", "env_prefix", "config", "top_package", "workspace", "package", "crate"] - -[overrides] -# ssbusync = "hdr" From 2bf6b94d6bb942ca838eb515cebc4bffd2428157 Mon Sep 17 00:00:00 2001 From: SuddyN Date: Sun, 10 May 2026 20:27:02 -0400 Subject: [PATCH 2/5] move delay switch to match load --- src/chara_select/match_load.rs | 101 ++++++++++++++++++++++++++++++++ src/chara_select/mod.rs | 2 + src/chara_select/player_port.rs | 57 +----------------- utils/src/one_player.rs | 27 --------- 4 files changed, 105 insertions(+), 82 deletions(-) create mode 100644 src/chara_select/match_load.rs diff --git a/src/chara_select/match_load.rs b/src/chara_select/match_load.rs new file mode 100644 index 0000000000..eeb6c6ab5f --- /dev/null +++ b/src/chara_select/match_load.rs @@ -0,0 +1,101 @@ +use skyline::hooks::InlineCtx; +use smash2::app::FighterManager; +use smash::lib::lua_const::*; +use ultelier::sync_guest::{self as sync, BufferMode}; +static mut SYNC_GUEST_MISSING: bool = false; +static mut LAST_BUFFER_MODE: Option = None; + +unsafe fn update_ssbusync_buffer_mode() { + if SYNC_GUEST_MISSING { + return; + } + + let match_mode = utils::util::get_match_mode().0; + let player_count = if let Some(fighter_manager) = FighterManager::instance() { + fighter_manager.entry_count() + } else { + 0 + }; + + // only use double buffer mode for online modes with 2 or fewer players + // prioritize stability for offline matches + let online_modes = [ + 45, // online arena smash + 58 // local wireless smash + ]; + let desired_mode = if online_modes.contains(&match_mode) && player_count <= 2 { + BufferMode::Double + } else { + BufferMode::Triple + }; + + let current_mode = match sync::env_flags() { + Some(flags) => { + if flags.contains(sync::EnvironmentFlags::TRIPLE_ENABLED) { + BufferMode::Triple + } else { + BufferMode::Double + } + } + None => { + SYNC_GUEST_MISSING = true; + println!("SSBU Sync Guest is not running, skipping buffer mode update."); + return; + } + }; + + if current_mode == desired_mode { + LAST_BUFFER_MODE = Some(desired_mode); + println!("Buffer mode is already {:?}, no update needed.", desired_mode); + return; + } + println!("Updating buffer mode to {:?} from {:?} for match mode {} with {} active players", desired_mode, current_mode, match_mode, player_count); + + match sync::set_buffer_mode(desired_mode) { + Some(true) => { + LAST_BUFFER_MODE = Some(desired_mode); + } + Some(false) => {} + None => { + SYNC_GUEST_MISSING = true; + } + } +} + +#[skyline::hook(offset = 0x1b7b814, inline)] +unsafe fn match_load(ctx: &mut InlineCtx) { + update_ssbusync_buffer_mode(); + + if !utils::one_player::one_player_entry() { + return; + } + + let result_ptr = ctx.registers[22].x() as *const u64; + let pane = *result_ptr.add(1); + if pane == 0 { + return; + } + + let internal = *(pane as *const u64); + if internal == 0 { + return; + } + + let parent = *((internal as *const u8).add(0x18) as *const u64); + if parent == 0 { + return; + } + + // hide timer + *(parent as *mut u8).add(0x58) &= 0xFE; +} + +pub fn install() { + //*Install only menu hooks to run without custom overclocker. + //sync::runtime::install_menu_hooks(); + sync::runtime::install_auto_profile_switcher(); + + skyline::install_hooks!( + match_load, + ); +} diff --git a/src/chara_select/mod.rs b/src/chara_select/mod.rs index d8fb34dde4..88a43ffc69 100644 --- a/src/chara_select/mod.rs +++ b/src/chara_select/mod.rs @@ -16,6 +16,7 @@ use crate::NEW_CSS_SFX; mod layout; mod random; mod player_port; +mod match_load; pub const KEY_MASK: u64 = 0xFFFFFF_0000000000; @@ -268,6 +269,7 @@ pub fn install() { layout::install(); random::install(); player_port::install(); + match_load::install(); // These patches are required to "undo" a stacked CSS diff --git a/src/chara_select/player_port.rs b/src/chara_select/player_port.rs index fd14e7957a..bba71c6ee5 100644 --- a/src/chara_select/player_port.rs +++ b/src/chara_select/player_port.rs @@ -1,7 +1,6 @@ use super::*; use ninput::*; use parking_lot::RwLock; -use ultelier::sync_guest::{self as sync, BufferMode}; static ID_LIST: &[u32] = &[0, 1, 2, 3, 4, 5, 6, 7, 0x20]; @@ -13,9 +12,7 @@ struct PortData { enable_swap: bool, root_card: u64, active_controllers: Vec, - swap_target: Option, - sync_guest_missing: bool, - last_buffer_mode: Option, + swap_target: Option } impl Default for PortData { fn default() -> Self { @@ -23,9 +20,7 @@ impl Default for PortData { enable_swap: false, root_card: 0x0, active_controllers: Vec::new(), - swap_target: None, - sync_guest_missing: false, - last_buffer_mode: None, + swap_target: None } } } @@ -192,47 +187,6 @@ unsafe fn count_active_players(instance: CharaSelect) -> i32 { active_players } -fn update_css_buffer_mode(data: &mut PortData, player_count: i32) { - if data.sync_guest_missing { - return; - } - - let desired_mode = if player_count <= 2 { - BufferMode::Double - } else { - BufferMode::Triple - }; - - let current_mode = match sync::env_flags() { - Some(flags) => { - if flags.contains(sync::EnvironmentFlags::TRIPLE_ENABLED) { - BufferMode::Triple - } else { - BufferMode::Double - } - } - None => { - data.sync_guest_missing = true; - return; - } - }; - - if current_mode == desired_mode { - data.last_buffer_mode = Some(desired_mode); - return; - } - - match sync::set_buffer_mode(desired_mode) { - Some(true) => { - data.last_buffer_mode = Some(desired_mode); - } - Some(false) => {} - None => { - data.sync_guest_missing = true; - } - } -} - static mut IS_UNPRESSED : bool = false; // this function loops while the css is active, allowing for runtime operations #[skyline::hook(offset = 0x1a2b570)] @@ -266,9 +220,6 @@ unsafe fn css_main_loop(arg: *const CharaSelect) { data.root_card = instance.first_player as u64; } - let player_count = count_active_players(instance); - update_css_buffer_mode(&mut data, player_count); - if !data.enable_swap || instance.ready_state != 0 { return original!()(arg); } @@ -465,10 +416,6 @@ unsafe fn controller_something_off(wireless_state: u32, player: *const PlayerInf unsafe fn controller_token_off(css_instance: *const CharaSelect, player: *const PlayerInfo); pub fn install() { - //*Install only menu hooks to run without custom overclocker. - //sync::runtime::install_menu_hooks(); - - sync::runtime::install_auto_profile_switcher(); skyline::install_hooks!( css_main_loop, init_css_player diff --git a/utils/src/one_player.rs b/utils/src/one_player.rs index bd2c9f2de4..2b7dbe92b8 100644 --- a/utils/src/one_player.rs +++ b/utils/src/one_player.rs @@ -7,32 +7,6 @@ use utils_dyn::util::MATCH_EXITING; pub static IS_RULE_TIME: AtomicBool = AtomicBool::new(false); -#[skyline::hook(offset = 0x1b7b814, inline)] -unsafe fn match_load(ctx: &mut InlineCtx) { - if !one_player_entry() { - return; - } - - let result_ptr = ctx.registers[22].x() as *const u64; - let pane = *result_ptr.add(1); - if pane == 0 { - return; - } - - let internal = *(pane as *const u64); - if internal == 0 { - return; - } - - let parent = *((internal as *const u8).add(0x18) as *const u64); - if parent == 0 { - return; - } - - // hide timer - *(parent as *mut u8).add(0x58) &= 0xFE; -} - // Set the match timer to 99 minutes every frame in 1P mode so it never expires. #[skyline::hook(offset = 0x15812b8, inline)] unsafe fn once_per_frame(ctx: &mut InlineCtx) { @@ -93,7 +67,6 @@ pub fn install() { game_over_declare, prevent_match_end_transition, once_per_frame, - match_load, ); // Allow 0 CPUs in Training Mode menu From 27b0f855bbbaa46bb5c728799dd45a5c93f0cc07 Mon Sep 17 00:00:00 2001 From: SuddyN Date: Mon, 11 May 2026 21:59:26 -0400 Subject: [PATCH 3/5] un-pin libc --- Cargo.toml | 1 - ssbu-sync | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) create mode 160000 ssbu-sync diff --git a/Cargo.toml b/Cargo.toml index 7d82011a66..73deb4ae4a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -240,7 +240,6 @@ ultelier = { git = "https://github.com/BlankMauser/smash-ultelier.git", default- [patch.crates-io] skyline = { git = "https://github.com/ultimate-research/skyline-rs" } nnsdk = { git = "https://github.com/ultimate-research/nnsdk-rs" } -libc = { git="https://github.com/rust-lang/libc", rev = "0.2.166"} [features] default = [ diff --git a/ssbu-sync b/ssbu-sync new file mode 160000 index 0000000000..5e7407e69d --- /dev/null +++ b/ssbu-sync @@ -0,0 +1 @@ +Subproject commit 5e7407e69de8cca1376c3846aadf2b606745f529 From bcfec4eb7a0f18d2fa5f10011d2632d3d32f74b5 Mon Sep 17 00:00:00 2001 From: SuddyN Date: Mon, 11 May 2026 22:29:06 -0400 Subject: [PATCH 4/5] remove ssbusync default installs --- src/chara_select/match_load.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/chara_select/match_load.rs b/src/chara_select/match_load.rs index eeb6c6ab5f..97be979c28 100644 --- a/src/chara_select/match_load.rs +++ b/src/chara_select/match_load.rs @@ -91,10 +91,6 @@ unsafe fn match_load(ctx: &mut InlineCtx) { } pub fn install() { - //*Install only menu hooks to run without custom overclocker. - //sync::runtime::install_menu_hooks(); - sync::runtime::install_auto_profile_switcher(); - skyline::install_hooks!( match_load, ); From 57564c4bb26d8fbe280bc515ba36dce7884f9614 Mon Sep 17 00:00:00 2001 From: SuddyN Date: Mon, 11 May 2026 23:00:15 -0400 Subject: [PATCH 5/5] Delete ssbu-sync --- ssbu-sync | 1 - 1 file changed, 1 deletion(-) delete mode 160000 ssbu-sync diff --git a/ssbu-sync b/ssbu-sync deleted file mode 160000 index 5e7407e69d..0000000000 --- a/ssbu-sync +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 5e7407e69de8cca1376c3846aadf2b606745f529