diff --git a/.github/workflows/check-flake.yml b/.github/workflows/check-flake.yml new file mode 100644 index 0000000..2393d87 --- /dev/null +++ b/.github/workflows/check-flake.yml @@ -0,0 +1,21 @@ +name: Code quality + +on: pull_request + +concurrency: + group: "${{ github.head_ref }}" + cancel-in-progress: true + +jobs: + check: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - uses: DeterminateSystems/nix-installer-action@main + - uses: DeterminateSystems/magic-nix-cache-action@main + + - name: Check + run: | + nix flake check --print-build-logs -j auto diff --git a/Cargo.lock b/Cargo.lock index c9ff1be..2a72ffa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -21,7 +21,7 @@ dependencies = [ [[package]] name = "latency-slider-de" -version = "0.3.2" +version = "0.4.0" dependencies = [ "ninput", "once_cell", diff --git a/Cargo.toml b/Cargo.toml index f639a72..6ba7a62 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "latency-slider-de" -version = "0.3.2" +version = "0.4.0" authors = [] edition = "2021" @@ -14,7 +14,11 @@ crate-type = ["cdylib"] ninput = { git = "https://github.com/blu-dev/ninput", version = "0.1.0" } skyline_smash = { git = "https://github.com/jugeeya/skyline-smash.git", branch = "patch-2" } skyline = { git = "https://github.com/ultimate-research/skyline-rs.git" } -once_cell = { version = "1.20.2" } +once_cell = { version = "1.20.2", default-features = true } + +[features] +default = ["css_ui"] +css_ui = [] [profile.dev] panic = "abort" diff --git a/README.md b/README.md index e5d2af4..d56a601 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,15 @@ You will need a moddable switch with atmosphere already installed on it. If you Congratulations, Smash Ultimate online is now actually playable! +### What is `liblatency_slider_de_classic.nro`? + +The "classic" version of the plugin is closer to the original latency slider in functionality: + +- You can only see and adjust your desired latency in arenas, D-pad inputs on any CSS are ignored. +- The latency you select in arenas carries over to all gamemodes, including quickplay / elite. + +The reason you'd pick classic over mainline is mod compatibility. Because it's much more barebones, it has a higher chance of being compatible with big, complex mods like the CSK collection. If you don't have any issues with mod compatibility however, there is no reason to use "classic" over the regular version. + ## Building The project can be reproducibly built using only the Nix package manager. @@ -88,7 +97,13 @@ NO. These essentially do the same thing but differently, running multiple of the #### Is this mod compatible with the VSync mod? -The VSync mod, aka "1 frame less delay", aka `less-delay` is compatible with this mod. I maintain a repo for that one as well, over here: https://github.com/xNaxdy/less-delay +The VSync mod, aka "1 frame less delay", aka `less-delay` is compatible with this mod. I maintain a repo for that one as well, over here: https://github.com/Naxdy/less-delay + +#### Is this mod compatible with the Ultimate Training Modpack? + +Yesn't. Both Latency Slider DE and the Ultimate Training Modpack attempt to hook the game's `draw` function, by trying to find its signature. The thing is, once one of the mods hooks that function, its signature changes, so whichever mod is loaded _second_ will fail to find that function. Therefore, if Latency Slider DE detects that you have Ultimate Training Modpack installed, it will display a warning message letting you know that it will run with reduced functionality in order to avoid crashing the game, making it so that it will not be able to display the input latency on the character select screen in Elite Smash. + +It will, however, remain fully functional otherwise (including applying your selected latency in all online modes), and you will still be able to select your desired latency in arenas, as well as adjust it "blindly" on any CSS. #### Is this mod compatible with [insert other mod here]? @@ -96,6 +111,8 @@ Don't know, don't care. SSBU modding is kind of like chemistry, except you don't I _highly_ suggest using a mod manager of some sort to enable / disable mods as you need, to avoid potential complications. +There's also the `liblatency_slider_classic.nro` version of the plugin, which is a more barebones build, closer in functionality of the original latency slider (with the exception that it too works in all online modes). Because it is more barebones, there's a higher chance that it may work together with mods that present issues with the mainline latency slider. + Unfortunately I can't really invest any time into ensuring that latency-slider-de is compatible with each and every mod out there. However, if you submit a PR that improves compatibility with other mods, I will happily accept it! #### Are you fine with people using this mod to cheat in online tournaments, or on qp? @@ -108,6 +125,14 @@ Additionally, even without latency slider, there are mods (software and hardware The bottom line here is that online tournaments have never been - and will never be - "fair", and if there's a will to cheat, there's a way (even without this mod). Unless you can ensure a 100% stable connection, equal and consistent input delay for both parties, and proctor all players to ensure they aren't using any special hardware to improve their play, this entire discussion is pointless to me. +#### Did you steal the source code of this plugin? + +No. This project's source code has been licensed under the AGPL by the original authors, which is a license that grants everyone the right to view, modify, and redistribute the project's source code, so long as the original license is preserved. See [this project's license](./LICENSE), as well as [the license for HDR](https://github.com/HDR-Development/HewDraw-Remix/blob/pre-release/LICENSE) - the project this functionality was originally developed for. + +I would also like to stress at this point that the AGPL regards "network interaction" as "distribution", meaning that if you download the source code for this plugin, modify it locally, and then use it to play online with others, you _have_ to publish your modifications to the source code, otherwise you are in violation of the license. According to section 13 of the [license](./LICENSE): + +> Notwithstanding any other provision of this License, if you modify the Program, your modified version must prominently offer all users interacting with it remotely through a computer network (if your version supports such interaction) an opportunity to receive the Corresponding Source of your version by providing access to the Corresponding Source from a network server at no charge, through some standard or customary means of facilitating copying of software. This Corresponding Source shall include the Corresponding Source for any work covered by version 3 of the GNU General Public License that is incorporated pursuant to the following paragraph. + ## Final Note This fork is published under the original project's AGPL license. Though I pinky promise to never take this repo offline or privatize the source code in any way, I encourage you to fork it and re-share it as much as your heart desires. diff --git a/flake.lock b/flake.lock index d9cb4ce..e99d1de 100644 --- a/flake.lock +++ b/flake.lock @@ -118,11 +118,11 @@ ] }, "locked": { - "lastModified": 1728550495, - "narHash": "sha256-oXuJVYVaFmXBS0k3fZJWdOSpGpFiUjhKzh8G8kejvoU=", + "lastModified": 1729419431, + "narHash": "sha256-Gt2hv1Gqly/IMBmaay43yxE3+BgHmNKUtd15NXJhp90=", "owner": "Naxdy", "repo": "nix-skyline-rs", - "rev": "19f12da0648c066cd894c44860ba5f6de17b628b", + "rev": "3affcb6a21193fdc75e323e78e408f8d5ec66338", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index d44ee2f..9c4af63 100644 --- a/flake.nix +++ b/flake.nix @@ -12,8 +12,14 @@ { self , flake-utils , nix-skyline-rs - , ... - }: (flake-utils.lib.eachDefaultSystem (system: { + , nixpkgs + }: (flake-utils.lib.eachDefaultSystem (system: + let + pkgs = import nixpkgs { + inherit system; + }; + in + { packages = { default = self.packages.${system}.latency-slider-de; @@ -21,11 +27,42 @@ let cargoTOML = builtins.fromTOML (builtins.readFile ./Cargo.toml); in - nix-skyline-rs.lib.${system}.mkNroPackage { - pname = cargoTOML.package.name; - version = cargoTOML.package.version; - src = self; - }; + pkgs.callPackage + ({ mode ? "build", copyLibs ? true, cargoBuildOptions ? old: old, overrideMain ? old: old }: + nix-skyline-rs.lib.${system}.mkNroPackage { + pname = cargoTOML.package.name; + version = cargoTOML.package.version; + src = self; + + inherit cargoBuildOptions overrideMain mode copyLibs; + }) + { }; + + latency-slider-de-classic = pkgs.callPackage + ({ mode ? "build", copyLibs ? true }: self.packages.${system}.latency-slider-de.override { + inherit mode copyLibs; + + cargoBuildOptions = old: old ++ [ + "--no-default-features" + ]; + + overrideMain = old: { + postInstall = (if (old ? postInstall) && (old.postInstall != false) then old.postInstall else "") + (pkgs.lib.optionalString (mode == "build") '' + mv $out/lib/liblatency_slider_de.nro $out/lib/liblatency_slider_de_classic.nro + ''); + }; + }) + { }; + }; + + checks = { + clippy = self.packages.${system}.latency-slider-de.override { + mode = "clippy"; + }; + + clippy-classic = self.packages.${system}.latency-slider-de-classic.override { + mode = "clippy"; + }; }; devShells.default = nix-skyline-rs.devShells.${system}.default; diff --git a/src/css_ui.rs b/src/css_ui.rs new file mode 100644 index 0000000..697c449 --- /dev/null +++ b/src/css_ui.rs @@ -0,0 +1,149 @@ +use std::path::Path; + +use skyline::{ + hooks::InlineCtx, + nn::ui2d::{Layout, Pane}, +}; +use smash::ui2d::SmashPane; + +use crate::{ + ensure_hooks, handle_user_input, + offsets::css_ui::{ + LOC_DISPLAY_CSS, LOC_DRAW, LOC_INGAME_SCENE, LOC_MAIN_MENU_SCENE, + LOC_MELEE_NORMAL_SEQUENCE_SCENE, LOC_ONLINE_MELEE_ANY_SCENE, LOC_UPDATE_CSS, + }, + set_text_string, CURRENT_INPUT_BUFFER, MOST_RECENT_AUTO, STEALTH_MODE, +}; + +static mut ORIG_VIP_TEXT: String = String::new(); +pub static mut IS_CSS: bool = false; + +const TRAINING_MODPACK_LOCATION: &str = + "sd:/atmosphere/contents/01006A800016E000/romfs/skyline/plugins/libtraining_modpack.nro"; + +const DONTANNOYME_LOCATION: &str = "sd:/dontannoyme.txt"; + +unsafe fn draw_ui(root_pane: &Pane) { + let vip_pane_00 = root_pane.find_pane_by_name_recursive("txt_vip_title_00"); + let vip_pane_01 = root_pane.find_pane_by_name_recursive("txt_vip_title_01"); + + if ORIG_VIP_TEXT.is_empty() { + match (vip_pane_00, vip_pane_01) { + (Some(x), _) | (_, Some(x)) => { + ORIG_VIP_TEXT = dbg!(String::from_utf16(std::slice::from_raw_parts( + x.as_textbox().text_buf as *mut u16, + x.as_textbox().text_buf_len as usize, + )) + .unwrap()); + } + _ => (), + } + } else if let (Some(x), Some(y)) = (vip_pane_00, vip_pane_01) { + let s = if !STEALTH_MODE { + if CURRENT_INPUT_BUFFER != -1 { + format!("Input Latency: {}\0", CURRENT_INPUT_BUFFER) + } else if MOST_RECENT_AUTO == -1 { + "Input Latency: Auto\0".to_string() + } else { + format!("Input Latency: Auto ({})\0", MOST_RECENT_AUTO) + } + } else { + ORIG_VIP_TEXT.clone() + }; + + [x, y] + .into_iter() + .for_each(|e| set_text_string(e as *mut Pane as u64, s.as_str().as_ptr())); + } +} + +#[skyline::hook(offset = LOC_DISPLAY_CSS.get_offset_in_memory().unwrap(), inline)] +unsafe fn display_css_hook(_: &InlineCtx) { + use crate::STEALTH_MODE; + + if !STEALTH_MODE { + IS_CSS = true; + } +} + +#[skyline::hook(offset = LOC_MELEE_NORMAL_SEQUENCE_SCENE.get_offset_in_memory().unwrap(), inline)] +unsafe fn melee_normal_sequence_scene_hook(_: &InlineCtx) { + IS_CSS = false; +} + +#[skyline::hook(offset = LOC_MAIN_MENU_SCENE.get_offset_in_memory().unwrap(), inline)] +unsafe fn main_menu_scene_hook(_: &InlineCtx) { + IS_CSS = false; +} + +#[skyline::hook(offset = LOC_ONLINE_MELEE_ANY_SCENE.get_offset_in_memory().unwrap(), inline)] +unsafe fn online_melee_any_scene_hook(_: &InlineCtx) { + IS_CSS = false; +} + +#[skyline::hook(offset = LOC_INGAME_SCENE.get_offset_in_memory().unwrap(), inline)] +unsafe fn ingame_scene_hook(_: &InlineCtx) { + IS_CSS = false; +} + +#[skyline::hook(offset = LOC_DRAW.get_offset_in_memory().unwrap())] +unsafe fn handle_draw_hook(layout: *mut Layout, draw_info: u64, cmd_buffer: u64) { + if IS_CSS { + let root_pane = &mut *(*layout).root_pane; + + draw_ui(root_pane); + } + + call_original!(layout, draw_info, cmd_buffer); +} + +#[skyline::hook(offset = LOC_UPDATE_CSS.get_offset_in_memory().unwrap())] +unsafe fn update_css_hook(arg: u64) { + handle_user_input(true); + + call_original!(arg) +} + +pub fn hook_css_funcs() { + if ensure_hooks!( + LOC_UPDATE_CSS, + LOC_DISPLAY_CSS, + LOC_INGAME_SCENE, + LOC_ONLINE_MELEE_ANY_SCENE, + LOC_MAIN_MENU_SCENE, + LOC_MELEE_NORMAL_SEQUENCE_SCENE + ) { + skyline::install_hooks!( + update_css_hook, + display_css_hook, + melee_normal_sequence_scene_hook, + main_menu_scene_hook, + online_melee_any_scene_hook, + ingame_scene_hook + ); + } + + // only hook draw if training mode modpack doesn't exist + if Path::new(TRAINING_MODPACK_LOCATION).exists() { + if !Path::new(DONTANNOYME_LOCATION).exists() { + skyline::error::show_error( + 69420, + "Latency Slider DE will run with reduced features. View details for more info.\0", + format!("{}\n\n{}\n\n{}\n\n{}\n\n{}\n\n{}\0", + "Latency Slider DE has detected the presence of the Ultimate Training Modpack in your plugins folder.", + "Due to conflicting functionality, Latency Slider DE will NOT be able to display your desired latency on the quickplay / Elite Smash screen.", + "The mod will remain fully functional otherwise, and you will still be able to see your desired latency in arenas, which will carry over to all online modes (including quickplay / Elite).", + "You can also still \"blindly\" adjust your desired latency on any character select screen, even if the latency is not displayed.", + "If you wish to see your latency on the quickplay / Elite Smash screen again, you will have to (temporarily) remove / disable the Ultimate Training Modpack.", + "If you don't want to see this message ever again, create an empty file named \"dontannoyme.txt\" and place it in the root (the topmost) folder of your SD card." + ).as_str() + ); + } else { + println!( + "[latency-slider-de] NOT enabling draw hook; user doesn't wish to be informed." + ) + } + } else if ensure_hooks!(LOC_DRAW) { + skyline::install_hooks!(handle_draw_hook); + } +} diff --git a/src/lib.rs b/src/lib.rs index da33e6c..22e8aa2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,23 +1,15 @@ #![feature(restricted_std)] -use std::path::Path; +#[cfg(feature = "css_ui")] +use css_ui::IS_CSS; -use offsets::{ - LOC_DISPLAY_CSS, LOC_DRAW, LOC_INGAME_SCENE, LOC_MAIN_MENU_SCENE, - LOC_MELEE_NORMAL_SEQUENCE_SCENE, LOC_ONLINE_MELEE_ANY_SCENE, LOC_SET_ONLINE_LATENCY, - LOC_SET_ROOM_ID, LOC_UPDATE_CSS, LOC_UPDATE_ROOM, -}; +use offsets::{LOC_SET_ONLINE_LATENCY, LOC_SET_ROOM_ID, LOC_UPDATE_ROOM}; use skyline::hooks::InlineCtx; -use skyline::nn::ui2d::{Layout, Pane}; -use smash::ui2d::SmashPane; +#[cfg(feature = "css_ui")] +mod css_ui; mod offsets; -const TRAINING_MODPACK_LOCATION: &str = - "sd:/atmosphere/contents/01006A800016E000/romfs/skyline/plugins/libtraining_modpack.nro"; - -const DONTANNOYME_LOCATION: &str = "sd:/dontannoyme.txt"; - #[skyline::from_offset(0x37a1f10)] unsafe fn set_text_string(pane: u64, string: *const u8); @@ -26,8 +18,6 @@ static mut CURRENT_ARENA_ID: String = String::new(); static mut CURRENT_INPUT_BUFFER: isize = 4; static mut MOST_RECENT_AUTO: isize = -1; static mut STEALTH_MODE: bool = false; -static mut ORIG_VIP_TEXT: String = String::new(); -static mut IS_CSS: bool = false; const MAX_INPUT_BUFFER: isize = 25; const MIN_INPUT_BUFFER: isize = -1; @@ -46,7 +36,7 @@ static mut DPAD: DpadInputState = DpadInputState { down_released: true, }; -unsafe fn handle_user_input(on_css: bool) { +unsafe fn handle_user_input(#[cfg(feature = "css_ui")] on_css: bool) { if ninput::any::is_press(ninput::Buttons::RIGHT) && DPAD.right_released { CURRENT_INPUT_BUFFER += 1; DPAD.right_released = false; @@ -62,9 +52,12 @@ unsafe fn handle_user_input(on_css: bool) { STEALTH_MODE = false; DPAD.down_released = false; - // kinda hacky for elite smash text - if on_css { - IS_CSS = true; + #[cfg(feature = "css_ui")] + { + // kinda hacky for elite smash text + if on_css { + IS_CSS = true; + } } } @@ -87,10 +80,17 @@ unsafe fn handle_user_input(on_css: bool) { #[skyline::hook(offset = LOC_UPDATE_ROOM.get_offset_in_memory().unwrap(), inline)] unsafe fn non_hdr_update_room_hook(_: &skyline::hooks::InlineCtx) { + #[cfg(feature = "css_ui")] handle_user_input(false); - if IS_CSS { - IS_CSS = false; + #[cfg(not(feature = "css_ui"))] + handle_user_input(); + + #[cfg(feature = "css_ui")] + { + if IS_CSS { + IS_CSS = false; + } } if STEALTH_MODE { @@ -126,25 +126,6 @@ unsafe fn non_hdr_update_room_hook(_: &skyline::hooks::InlineCtx) { } } -#[skyline::hook(offset = LOC_DRAW.get_offset_in_memory().unwrap())] -unsafe fn handle_draw_hook(layout: *mut Layout, draw_info: u64, cmd_buffer: u64) { - if IS_CSS { - let root_pane = &mut *(*layout).root_pane; - - // TODO: Reevaluate functionality after update to 19.0.0 - draw_ui(root_pane); - } - - call_original!(layout, draw_info, cmd_buffer); -} - -#[skyline::hook(offset = LOC_UPDATE_CSS.get_offset_in_memory().unwrap())] -unsafe fn update_css_hook(arg: u64) { - handle_user_input(true); - - call_original!(arg) -} - #[skyline::hook(offset = LOC_SET_ROOM_ID.get_offset_in_memory().unwrap(), inline)] unsafe fn non_hdr_set_room_id(ctx: &skyline::hooks::InlineCtx) { let panel = *((*((*ctx.registers[0].x.as_ref() + 8) as *const u64) + 0x10) as *const u64); @@ -166,116 +147,22 @@ unsafe fn non_hdr_set_online_latency(ctx: &InlineCtx) { } } -#[skyline::hook(offset = LOC_DISPLAY_CSS.get_offset_in_memory().unwrap(), inline)] -unsafe fn display_css_hook(_: &InlineCtx) { - if !STEALTH_MODE { - IS_CSS = true; - } -} - -#[skyline::hook(offset = LOC_MELEE_NORMAL_SEQUENCE_SCENE.get_offset_in_memory().unwrap(), inline)] -unsafe fn melee_normal_sequence_scene_hook(_: &InlineCtx) { - IS_CSS = false; -} - -#[skyline::hook(offset = LOC_MAIN_MENU_SCENE.get_offset_in_memory().unwrap(), inline)] -unsafe fn main_menu_scene_hook(_: &InlineCtx) { - IS_CSS = false; -} - -#[skyline::hook(offset = LOC_ONLINE_MELEE_ANY_SCENE.get_offset_in_memory().unwrap(), inline)] -unsafe fn online_melee_any_scene_hook(_: &InlineCtx) { - IS_CSS = false; -} - -#[skyline::hook(offset = LOC_INGAME_SCENE.get_offset_in_memory().unwrap(), inline)] -unsafe fn ingame_scene_hook(_: &InlineCtx) { - IS_CSS = false; -} - -unsafe fn draw_ui(root_pane: &Pane) { - let vip_pane_00 = root_pane.find_pane_by_name_recursive("txt_vip_title_00"); - let vip_pane_01 = root_pane.find_pane_by_name_recursive("txt_vip_title_01"); - - if ORIG_VIP_TEXT.is_empty() { - match (vip_pane_00, vip_pane_01) { - (Some(x), _) | (_, Some(x)) => { - ORIG_VIP_TEXT = dbg!(String::from_utf16(std::slice::from_raw_parts( - x.as_textbox().text_buf as *mut u16, - x.as_textbox().text_buf_len as usize, - )) - .unwrap()); - } - _ => (), - } - } else if let (Some(x), Some(y)) = (vip_pane_00, vip_pane_01) { - let s = if !STEALTH_MODE { - if CURRENT_INPUT_BUFFER != -1 { - format!("Input Latency: {}\0", CURRENT_INPUT_BUFFER) - } else if MOST_RECENT_AUTO == -1 { - "Input Latency: Auto\0".to_string() - } else { - format!("Input Latency: Auto ({})\0", MOST_RECENT_AUTO) - } - } else { - ORIG_VIP_TEXT.clone() - }; - - [x, y] - .into_iter() - .for_each(|e| set_text_string(e as *mut Pane as u64, s.as_str().as_ptr())); - } -} - #[skyline::main(name = "latency-slider-de")] pub fn main() { // make sure that all hooks are findable // and don't crash the game if they're not - if ensure_hooks!( - LOC_UPDATE_ROOM, - LOC_UPDATE_CSS, - LOC_SET_ROOM_ID, - LOC_DISPLAY_CSS, - LOC_SET_ONLINE_LATENCY, - LOC_INGAME_SCENE, - LOC_ONLINE_MELEE_ANY_SCENE, - LOC_MAIN_MENU_SCENE, - LOC_MELEE_NORMAL_SEQUENCE_SCENE - ) { + if ensure_hooks!(LOC_UPDATE_ROOM, LOC_SET_ROOM_ID, LOC_SET_ONLINE_LATENCY) { skyline::install_hooks!( non_hdr_set_room_id, non_hdr_update_room_hook, non_hdr_set_online_latency, - update_css_hook, - display_css_hook, - melee_normal_sequence_scene_hook, - main_menu_scene_hook, - online_melee_any_scene_hook, - ingame_scene_hook ); } - // only hook draw if training mode modpack doesn't exist - if Path::new(TRAINING_MODPACK_LOCATION).exists() { - if !Path::new(DONTANNOYME_LOCATION).exists() { - skyline::error::show_error( - 69420, - "Latency Slider DE will run with reduced features.\0", - format!("{}\n\n{}\n\n{}\n\n{}\n\n{}\n\n{}\0", - "Latency Slider DE has detected the presence of the Ultimate Training Modpack in your plugins folder.", - "Due to conflicting functionality, Latency Slider DE will NOT be able to display your desired latency on the quickplay / Elite Smash screen.", - "The mod will remain fully functional otherwise, and you will still be able to see your desired latency in arenas, which will carry over to all online modes (including quickplay / Elite).", - "You can also still \"blindly\" adjust your desired latency on any character select screen, even if the latency is not displayed.", - "If you wish to see your latency on the quickplay / Elite Smash screen again, you will have to (temporarily) remove / disable the Ultimate Training Modpack.", - "If you don't want to see this message ever again, create an empty file named \"dontannoyme.txt\" and place it in the root (the topmost) folder of your SD card." - ).as_str() - ); - } else { - println!( - "[latency-slider-de] NOT enabling draw hook; user doesn't wish to be informed." - ) - } - } else if ensure_hooks!(LOC_DRAW) { - skyline::install_hooks!(handle_draw_hook); + #[cfg(feature = "css_ui")] + { + use css_ui::hook_css_funcs; + + hook_css_funcs(); } } diff --git a/src/offsets.rs b/src/offsets.rs index 1450e54..78e581e 100644 --- a/src/offsets.rs +++ b/src/offsets.rs @@ -82,17 +82,6 @@ impl SSBUMemoryLocation<'_> { } } -pub static LOC_DRAW: SSBUMemoryLocation = SSBUMemoryLocation { - signature: &[ - 0x08, 0x0c, 0x40, 0xf9, 0xc8, 0x03, 0x00, 0xb4, 0xff, 0x83, 0x01, 0xd1, 0xf5, 0x1b, 0x00, - 0xf9, 0xf4, 0x4f, 0x04, 0xa9, 0xfd, 0x7b, 0x05, 0xa9, 0xfd, 0x43, 0x01, 0x91, 0xf4, 0x03, - 0x00, 0xaa, - ], - start_offset: 0, - location_name: "draw", - cached_offset: OnceCell::new(), -}; - pub static LOC_SET_ONLINE_LATENCY: SSBUMemoryLocation = SSBUMemoryLocation { signature: &[ 0xfd, 0x7b, 0x42, 0xa9, 0xf4, 0x4f, 0x41, 0xa9, 0xe8, 0x07, 0x43, 0xfc, 0xc0, 0x03, 0x5f, @@ -103,68 +92,6 @@ pub static LOC_SET_ONLINE_LATENCY: SSBUMemoryLocation = SSBUMemoryLocation { cached_offset: OnceCell::new(), }; -pub static LOC_INGAME_SCENE: SSBUMemoryLocation = SSBUMemoryLocation { - signature: &[ - 0xff, 0x83, 0x01, 0xd1, 0xfa, 0x67, 0x01, 0xa9, 0xf8, 0x5f, 0x02, 0xa9, 0xf6, 0x57, 0x03, - 0xa9, 0xf4, 0x4f, 0x04, 0xa9, 0xfd, 0x7b, 0x05, 0xa9, 0xfd, 0x43, 0x01, 0x91, 0xf5, 0x03, - 0x01, 0xaa, 0xf3, 0x03, 0x00, 0xaa, 0x16, 0x40, 0x01, 0x91, 0x01, 0x37, 0x80, 0x52, 0xe0, - 0x03, 0x1c, 0x32, - ], - start_offset: 48, - location_name: "ingame_scene", - cached_offset: OnceCell::new(), -}; - -pub static LOC_ONLINE_MELEE_ANY_SCENE: SSBUMemoryLocation = SSBUMemoryLocation { - signature: &[ - 0xe8, 0x69, 0x01, 0xb0, 0x08, 0x01, 0x00, 0x91, 0x1f, 0x40, 0x00, 0x39, 0x08, 0x7c, 0x00, - 0xa9, 0x1f, 0x40, 0x01, 0x39, 0x1f, 0x54, 0x00, 0xb9, 0x1f, 0x2c, 0x00, 0xf9, 0xfd, 0x7b, - 0x41, 0xa9, 0xff, 0x83, 0x00, 0x91, 0xc0, 0x03, 0x5f, 0xd6, - ], - start_offset: 12, - location_name: "online_melee_any_scene", - cached_offset: OnceCell::new(), -}; - -pub static LOC_MAIN_MENU_SCENE: SSBUMemoryLocation = SSBUMemoryLocation { - signature: &[ - 0x48, 0x6a, 0x01, 0xb0, 0x08, 0xe1, 0x18, 0x91, 0x7f, 0x42, 0x00, 0x39, 0x68, 0x7e, 0x00, - 0xa9, 0xa8, 0x7e, 0x01, 0xb0, 0x7f, 0x42, 0x01, 0x39, 0xe1, 0x03, 0x00, 0x32, 0x7f, 0x56, - 0x00, 0xb9, 0x7f, 0x2e, 0x00, 0xf9, 0x00, 0xf9, 0x43, 0xf9, 0xc7, 0x43, 0x3e, 0x94, 0xe0, - 0x03, 0x13, 0xaa, 0xfd, 0x7b, 0x42, 0xa9, 0xf3, 0x0b, 0x40, 0xf9, 0xff, 0xc3, 0x00, 0x91, - 0xc0, 0x03, 0x5f, 0xd6, - ], - start_offset: 12, - location_name: "main_menu_scene", - cached_offset: OnceCell::new(), -}; - -pub static LOC_MELEE_NORMAL_SEQUENCE_SCENE: SSBUMemoryLocation = SSBUMemoryLocation { - signature: &[ - 0xc8, 0x6e, 0x01, 0xf0, 0x08, 0xc1, 0x0b, 0x91, 0x60, 0x42, 0x01, 0x91, 0x7f, 0x42, 0x00, - 0x39, 0x68, 0x7e, 0x00, 0xa9, 0x64, 0x1f, 0x51, 0x94, 0x28, 0x6e, 0x01, 0xd0, 0x08, 0xc1, - 0x01, 0x91, 0xe9, 0x6e, 0x01, 0x90, 0x29, 0xe1, 0x29, 0x91, 0x7f, 0xc2, 0x01, 0x79, 0x7f, - 0xe6, 0x00, 0xb9, 0x68, 0x2a, 0x00, 0xf9, 0x69, 0x02, 0x00, 0xf9, 0xe0, 0x03, 0x13, 0xaa, - 0x7f, 0x76, 0x00, 0xf9, 0xfd, 0x7b, 0x42, 0xa9, 0xf3, 0x0b, 0x40, 0xf9, 0xff, 0xc3, 0x00, - 0x91, 0xc0, 0x03, 0x5f, 0xd6, - ], - start_offset: 20, - location_name: "melee_normal_sequence_scene", - cached_offset: OnceCell::new(), -}; - -pub static LOC_DISPLAY_CSS: SSBUMemoryLocation = SSBUMemoryLocation { - signature: &[ - 0xa0, 0x83, 0x53, 0xf8, 0x34, 0x00, 0x00, 0x94, 0xff, 0x03, 0x0e, 0x91, 0xe9, 0x23, 0x43, - 0x6d, 0xeb, 0x2b, 0x42, 0x6d, 0xed, 0x33, 0x41, 0x6d, 0xfd, 0x7b, 0x49, 0xa9, 0xf4, 0x4f, - 0x48, 0xa9, 0xf6, 0x57, 0x47, 0xa9, 0xf8, 0x5f, 0x46, 0xa9, 0xfa, 0x67, 0x45, 0xa9, 0xfc, - 0x6f, 0x44, 0xa9, 0xef, 0x3b, 0xca, 0x6c, 0xc0, 0x03, 0x5f, 0xd6, - ], - start_offset: 4, - location_name: "display_css", - cached_offset: OnceCell::new(), -}; - pub static LOC_SET_ROOM_ID: SSBUMemoryLocation = SSBUMemoryLocation { signature: &[ 0x81, 0x54, 0x01, 0x90, 0x21, 0x2c, 0x3a, 0x91, 0xe8, 0xc3, 0x00, 0x91, 0xe0, 0x03, 0x14, @@ -178,20 +105,6 @@ pub static LOC_SET_ROOM_ID: SSBUMemoryLocation = SSBUMemoryLocation { cached_offset: OnceCell::new(), }; -pub static LOC_UPDATE_CSS: SSBUMemoryLocation = SSBUMemoryLocation { - signature: &[ - 0xea, 0x0f, 0x18, 0xfc, 0xe9, 0x23, 0x01, 0x6d, 0xfc, 0x6f, 0x02, 0xa9, 0xfa, 0x67, 0x03, - 0xa9, 0xf8, 0x5f, 0x04, 0xa9, 0xf6, 0x57, 0x05, 0xa9, 0xf4, 0x4f, 0x06, 0xa9, 0xfd, 0x7b, - 0x07, 0xa9, 0xfd, 0xc3, 0x01, 0x91, 0xff, 0x83, 0x0b, 0xd1, 0x08, 0x3c, 0x41, 0xb9, 0xf3, - 0x03, 0x00, 0xaa, 0x08, 0x01, 0x00, 0x35, 0x68, 0xce, 0x40, 0xf9, 0x08, 0x01, 0x40, 0xf9, - 0x00, 0x01, 0x40, 0xf9, 0xe1, 0x03, 0x00, 0x32, 0xef, 0x89, 0x75, 0x94, 0x60, 0xfa, 0x46, - 0xf9, 0x1d, 0xf2, 0x62, 0x94, - ], - start_offset: 0, - location_name: "update_css", - cached_offset: OnceCell::new(), -}; - pub static LOC_UPDATE_ROOM: SSBUMemoryLocation = SSBUMemoryLocation { signature: &[ 0xff, 0x03, 0x01, 0xd1, 0xf6, 0x57, 0x01, 0xa9, 0xf4, 0x4f, 0x02, 0xa9, 0xfd, 0x7b, 0x03, @@ -206,6 +119,100 @@ pub static LOC_UPDATE_ROOM: SSBUMemoryLocation = SSBUMemoryLocation { cached_offset: OnceCell::new(), }; +#[cfg(feature = "css_ui")] +pub mod css_ui { + use once_cell::sync::OnceCell; + + use super::SSBUMemoryLocation; + + pub static LOC_DRAW: SSBUMemoryLocation = SSBUMemoryLocation { + signature: &[ + 0x08, 0x0c, 0x40, 0xf9, 0xc8, 0x03, 0x00, 0xb4, 0xff, 0x83, 0x01, 0xd1, 0xf5, 0x1b, + 0x00, 0xf9, 0xf4, 0x4f, 0x04, 0xa9, 0xfd, 0x7b, 0x05, 0xa9, 0xfd, 0x43, 0x01, 0x91, + 0xf4, 0x03, 0x00, 0xaa, + ], + start_offset: 0, + location_name: "draw", + cached_offset: OnceCell::new(), + }; + + pub static LOC_INGAME_SCENE: SSBUMemoryLocation = SSBUMemoryLocation { + signature: &[ + 0xff, 0x83, 0x01, 0xd1, 0xfa, 0x67, 0x01, 0xa9, 0xf8, 0x5f, 0x02, 0xa9, 0xf6, 0x57, + 0x03, 0xa9, 0xf4, 0x4f, 0x04, 0xa9, 0xfd, 0x7b, 0x05, 0xa9, 0xfd, 0x43, 0x01, 0x91, + 0xf5, 0x03, 0x01, 0xaa, 0xf3, 0x03, 0x00, 0xaa, 0x16, 0x40, 0x01, 0x91, 0x01, 0x37, + 0x80, 0x52, 0xe0, 0x03, 0x1c, 0x32, + ], + start_offset: 48, + location_name: "ingame_scene", + cached_offset: OnceCell::new(), + }; + + pub static LOC_ONLINE_MELEE_ANY_SCENE: SSBUMemoryLocation = SSBUMemoryLocation { + signature: &[ + 0xe8, 0x69, 0x01, 0xb0, 0x08, 0x01, 0x00, 0x91, 0x1f, 0x40, 0x00, 0x39, 0x08, 0x7c, + 0x00, 0xa9, 0x1f, 0x40, 0x01, 0x39, 0x1f, 0x54, 0x00, 0xb9, 0x1f, 0x2c, 0x00, 0xf9, + 0xfd, 0x7b, 0x41, 0xa9, 0xff, 0x83, 0x00, 0x91, 0xc0, 0x03, 0x5f, 0xd6, + ], + start_offset: 12, + location_name: "online_melee_any_scene", + cached_offset: OnceCell::new(), + }; + + pub static LOC_MAIN_MENU_SCENE: SSBUMemoryLocation = SSBUMemoryLocation { + signature: &[ + 0x48, 0x6a, 0x01, 0xb0, 0x08, 0xe1, 0x18, 0x91, 0x7f, 0x42, 0x00, 0x39, 0x68, 0x7e, + 0x00, 0xa9, 0xa8, 0x7e, 0x01, 0xb0, 0x7f, 0x42, 0x01, 0x39, 0xe1, 0x03, 0x00, 0x32, + 0x7f, 0x56, 0x00, 0xb9, 0x7f, 0x2e, 0x00, 0xf9, 0x00, 0xf9, 0x43, 0xf9, 0xc7, 0x43, + 0x3e, 0x94, 0xe0, 0x03, 0x13, 0xaa, 0xfd, 0x7b, 0x42, 0xa9, 0xf3, 0x0b, 0x40, 0xf9, + 0xff, 0xc3, 0x00, 0x91, 0xc0, 0x03, 0x5f, 0xd6, + ], + start_offset: 12, + location_name: "main_menu_scene", + cached_offset: OnceCell::new(), + }; + + pub static LOC_MELEE_NORMAL_SEQUENCE_SCENE: SSBUMemoryLocation = SSBUMemoryLocation { + signature: &[ + 0xc8, 0x6e, 0x01, 0xf0, 0x08, 0xc1, 0x0b, 0x91, 0x60, 0x42, 0x01, 0x91, 0x7f, 0x42, + 0x00, 0x39, 0x68, 0x7e, 0x00, 0xa9, 0x64, 0x1f, 0x51, 0x94, 0x28, 0x6e, 0x01, 0xd0, + 0x08, 0xc1, 0x01, 0x91, 0xe9, 0x6e, 0x01, 0x90, 0x29, 0xe1, 0x29, 0x91, 0x7f, 0xc2, + 0x01, 0x79, 0x7f, 0xe6, 0x00, 0xb9, 0x68, 0x2a, 0x00, 0xf9, 0x69, 0x02, 0x00, 0xf9, + 0xe0, 0x03, 0x13, 0xaa, 0x7f, 0x76, 0x00, 0xf9, 0xfd, 0x7b, 0x42, 0xa9, 0xf3, 0x0b, + 0x40, 0xf9, 0xff, 0xc3, 0x00, 0x91, 0xc0, 0x03, 0x5f, 0xd6, + ], + start_offset: 20, + location_name: "melee_normal_sequence_scene", + cached_offset: OnceCell::new(), + }; + + pub static LOC_DISPLAY_CSS: SSBUMemoryLocation = SSBUMemoryLocation { + signature: &[ + 0xa0, 0x83, 0x53, 0xf8, 0x34, 0x00, 0x00, 0x94, 0xff, 0x03, 0x0e, 0x91, 0xe9, 0x23, + 0x43, 0x6d, 0xeb, 0x2b, 0x42, 0x6d, 0xed, 0x33, 0x41, 0x6d, 0xfd, 0x7b, 0x49, 0xa9, + 0xf4, 0x4f, 0x48, 0xa9, 0xf6, 0x57, 0x47, 0xa9, 0xf8, 0x5f, 0x46, 0xa9, 0xfa, 0x67, + 0x45, 0xa9, 0xfc, 0x6f, 0x44, 0xa9, 0xef, 0x3b, 0xca, 0x6c, 0xc0, 0x03, 0x5f, 0xd6, + ], + start_offset: 4, + location_name: "display_css", + cached_offset: OnceCell::new(), + }; + + pub static LOC_UPDATE_CSS: SSBUMemoryLocation = SSBUMemoryLocation { + signature: &[ + 0xea, 0x0f, 0x18, 0xfc, 0xe9, 0x23, 0x01, 0x6d, 0xfc, 0x6f, 0x02, 0xa9, 0xfa, 0x67, + 0x03, 0xa9, 0xf8, 0x5f, 0x04, 0xa9, 0xf6, 0x57, 0x05, 0xa9, 0xf4, 0x4f, 0x06, 0xa9, + 0xfd, 0x7b, 0x07, 0xa9, 0xfd, 0xc3, 0x01, 0x91, 0xff, 0x83, 0x0b, 0xd1, 0x08, 0x3c, + 0x41, 0xb9, 0xf3, 0x03, 0x00, 0xaa, 0x08, 0x01, 0x00, 0x35, 0x68, 0xce, 0x40, 0xf9, + 0x08, 0x01, 0x40, 0xf9, 0x00, 0x01, 0x40, 0xf9, 0xe1, 0x03, 0x00, 0x32, 0xef, 0x89, + 0x75, 0x94, 0x60, 0xfa, 0x46, 0xf9, 0x1d, 0xf2, 0x62, 0x94, + ], + start_offset: 0, + location_name: "update_css", + cached_offset: OnceCell::new(), + }; +} + // TODO: not findable atm, probably need to change search algo. // this and `find_pane_by_name_recursive` are currently the only hardcoded offsets // pub static LOC_SET_TEXT_STRING: SSBUMemoryLocation = SSBUMemoryLocation {