rosu_memory_lib/reader/
structs.rs

1#![allow(unused_imports)]
2#[cfg(feature = "parallel-read")]
3use rayon::prelude::*;
4
5use crate::Error;
6use rosu_mem::{
7    process::{Process, ProcessTraits},
8    signature::Signature,
9};
10use std::collections::HashMap;
11use std::str::FromStr;
12use std::time::Instant;
13
14#[derive(Default, Clone)]
15pub struct StaticAddresses {
16    pub base: i32,
17    pub status: i32,
18    pub menu_mods: i32,
19    pub rulesets: i32,
20    pub playtime: i32,
21    pub skin: i32,
22    pub chat_checker: i32,
23    pub audio_time_base: i32,
24    pub ig_time_base: i32,
25    pub settings: i32,
26    pub user_profile: i32,
27}
28
29#[derive(Debug, Default, Clone)]
30pub struct Hit {
31    pub _geki: i16,
32    pub _300: i16,
33    pub _katu: i16,
34    pub _100: i16,
35    pub _50: i16,
36    pub _miss: i16,
37}
38
39#[derive(Debug, Clone)]
40pub(crate) struct SignatureBase {
41    base_sig: &'static str,
42    status_sig: &'static str,
43    menu_mods_sig: &'static str,
44    rulesets_sig: &'static str,
45    playtime_sig: &'static str,
46    skin_sig: &'static str,
47    chat_checker_sig: &'static str,
48    audio_time_base_sig: &'static str,
49    ig_time_base_sig: &'static str,
50    settings_sig: &'static str,
51    user_profile_sig: &'static str,
52}
53
54pub(crate) const SIGNATURES: SignatureBase = SignatureBase {
55    base_sig: "F8 01 74 04 83 65",
56    status_sig: "48 83 F8 04 73 1E",
57    menu_mods_sig: "C8 FF ?? ?? ?? ?? ?? 81 0D ?? ?? ?? ?? 00 08 00 00",
58    rulesets_sig: "7D 15 A1 ?? ?? ?? ?? 85 C0",
59    playtime_sig: "5E 5F 5D C3 A1 ?? ?? ?? ?? 89 ?? 04",
60    skin_sig: "75 21 8B 1D",
61    chat_checker_sig: "0A D7 23 3C 00 00 ?? 01",
62    audio_time_base_sig: "DB 5C 24 34 8B 44 24 34",
63    ig_time_base_sig: "EB 0A A1 ?? ?? ?? ?? A3",
64    settings_sig: "83 E0 20 85 C0 7E 2F",
65    user_profile_sig: "FF 15 ?? ?? ?? ?? A1 ?? ?? ?? ?? 8B 48 54 33 D2",
66};
67
68impl StaticAddresses {
69    pub fn new(p: &Process) -> Result<Self, Error> {
70        let start = Instant::now();
71        println!("Reading signatures...");
72
73        #[cfg(feature = "parallel-read")]
74        {
75            println!("Using parallel signature reading with rayon...");
76            Self::new_parallel(p, start)
77        }
78
79        #[cfg(not(feature = "parallel-read"))]
80        {
81            println!("Using sequential signature reading...");
82            Self::new_sequential(p, start)
83        }
84    }
85
86    #[cfg(feature = "parallel-read")]
87    fn new_parallel(p: &Process, start: Instant) -> Result<Self, Error> {
88        use rayon::prelude::*;
89
90        let signatures = [
91            ("base", SIGNATURES.base_sig),
92            ("status", SIGNATURES.status_sig),
93            ("menu_mods", SIGNATURES.menu_mods_sig),
94            ("rulesets", SIGNATURES.rulesets_sig),
95            ("playtime", SIGNATURES.playtime_sig),
96            ("skin", SIGNATURES.skin_sig),
97            ("chat_checker", SIGNATURES.chat_checker_sig),
98            ("audio_time_base", SIGNATURES.audio_time_base_sig),
99            ("ig_time_base", SIGNATURES.ig_time_base_sig),
100            ("settings", SIGNATURES.settings_sig),
101            ("user_profile", SIGNATURES.user_profile_sig),
102        ];
103
104        let results: HashMap<&str, i32> = signatures
105            .par_iter()
106            .map(|(name, sig)| {
107                let signature = Signature::from_str(sig)?;
108                let addr = p.read_signature(&signature)?;
109                Ok::<_, Error>((*name, addr))
110            })
111            .collect::<Result<_, Error>>()?;
112
113        println!("Time taken: {:?}", start.elapsed());
114
115        Ok(Self {
116            base: results["base"],
117            status: results["status"],
118            menu_mods: results["menu_mods"],
119            rulesets: results["rulesets"],
120            playtime: results["playtime"],
121            skin: results["skin"],
122            chat_checker: results["chat_checker"],
123            audio_time_base: results["audio_time_base"],
124            ig_time_base: results["ig_time_base"],
125            settings: results["settings"],
126            user_profile: results["user_profile"],
127        })
128    }
129
130    #[cfg(not(feature = "parallel-read"))]
131    fn new_sequential(p: &Process, start: Instant) -> Result<Self, Error> {
132        let signatures = [
133            ("base", SIGNATURES.base_sig),
134            ("status", SIGNATURES.status_sig),
135            ("menu_mods", SIGNATURES.menu_mods_sig),
136            ("rulesets", SIGNATURES.rulesets_sig),
137            ("playtime", SIGNATURES.playtime_sig),
138            ("skin", SIGNATURES.skin_sig),
139            ("chat_checker", SIGNATURES.chat_checker_sig),
140            ("audio_time_base", SIGNATURES.audio_time_base_sig),
141            ("ig_time_base", SIGNATURES.ig_time_base_sig),
142            ("settings", SIGNATURES.settings_sig),
143            ("user_profile", SIGNATURES.user_profile_sig),
144        ];
145
146        let mut results = HashMap::new();
147        for (name, sig) in signatures.iter() {
148            let signature = Signature::from_str(sig)?;
149            let addr = p.read_signature(&signature)?;
150            results.insert(*name, addr);
151        }
152
153        println!("Time taken: {:?}", start.elapsed());
154
155        Ok(Self {
156            base: results["base"],
157            status: results["status"],
158            menu_mods: results["menu_mods"],
159            rulesets: results["rulesets"],
160            playtime: results["playtime"],
161            skin: results["skin"],
162            chat_checker: results["chat_checker"],
163            audio_time_base: results["audio_time_base"],
164            ig_time_base: results["ig_time_base"],
165            settings: results["settings"],
166            user_profile: results["user_profile"],
167        })
168    }
169}
170
171#[derive(Default, Clone)]
172pub struct State {
173    pub addresses: StaticAddresses,
174}