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}