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", audio_time_base_sig: "55 8B EC 83 EC 08 A1 ?? ?? ?? ?? 85 C0", 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}