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