rosu_memory_lib/reader/beatmap/stable/
memory.rs1use crate::common::GameMode;
2use crate::generate_offset_getter;
3use crate::reader::beatmap::common::{
4 BeatmapInfo, BeatmapLocation, BeatmapMetadata, BeatmapStats, BeatmapStatus,
5 BeatmapTechnicalInfo,
6};
7use crate::reader::beatmap::stable::{beatmap_addr, offset::BEATMAP_OFFSET};
8use crate::reader::helpers::{read_f32, read_i32, read_string, read_u32};
9use crate::reader::structs::State;
10use crate::Error;
11use rosu_mem::process::{Process, ProcessTraits};
12
13generate_offset_getter! {
14 id: i32 = read_i32(BEATMAP_OFFSET.technical.id, beatmap_addr);
15 set_id: i32 = read_i32(BEATMAP_OFFSET.technical.set_id, beatmap_addr);
16 tags: String = read_string(BEATMAP_OFFSET.metadata.tags, beatmap_addr);
17 length: i32 = read_i32(BEATMAP_OFFSET.stats.total_length, beatmap_addr);
18 drain_time: i32 = read_i32(BEATMAP_OFFSET.stats.drain_time, beatmap_addr);
19 author: String = read_string(BEATMAP_OFFSET.metadata.author, beatmap_addr);
20 creator: String = read_string(BEATMAP_OFFSET.metadata.creator, beatmap_addr);
21 md5: String = read_string(BEATMAP_OFFSET.technical.md5, beatmap_addr);
22 title_romanized: String = read_string(BEATMAP_OFFSET.metadata.title_romanized, beatmap_addr);
23 title: String = read_string(BEATMAP_OFFSET.metadata.title_original, beatmap_addr);
24 difficulty: String = read_string(BEATMAP_OFFSET.metadata.difficulty, beatmap_addr);
25 od: f32 = read_f32(BEATMAP_OFFSET.stats.od, beatmap_addr);
26 ar: f32 = read_f32(BEATMAP_OFFSET.stats.ar, beatmap_addr);
27 cs: f32 = read_f32(BEATMAP_OFFSET.stats.cs, beatmap_addr);
28 hp: f32 = read_f32(BEATMAP_OFFSET.stats.hp, beatmap_addr);
29 object_count: u32 = read_u32(BEATMAP_OFFSET.stats.object_count, beatmap_addr);
30 slider_count: i32 = read_i32(BEATMAP_OFFSET.stats.slider_count, beatmap_addr);
31 folder: String = read_string(BEATMAP_OFFSET.location.folder, beatmap_addr);
32 filename: String = read_string(BEATMAP_OFFSET.location.filename, beatmap_addr);
33 audio: String = read_string(BEATMAP_OFFSET.location.audio, beatmap_addr);
34 cover: String = read_string(BEATMAP_OFFSET.location.cover, beatmap_addr);
35 mode: GameMode = read_i32(BEATMAP_OFFSET.technical.mode, beatmap_addr);
36 status: BeatmapStatus = read_i32(BEATMAP_OFFSET.technical.ranked_status, beatmap_addr);
37}
38
39pub fn stats(p: &Process, state: &mut State) -> Result<BeatmapStats, Error> {
40 let beatmap_addr = beatmap_addr(p, state)?;
41 let mut buffer = [0u8; size_of::<f32>() * 4];
42 p.read(beatmap_addr + 0x2c, size_of::<f32>() * 4, &mut buffer)?;
43
44 Ok(BeatmapStats {
45 ar: f32::from_le_bytes(buffer[0..4].try_into().unwrap()),
46 cs: f32::from_le_bytes(buffer[4..8].try_into().unwrap()),
47 hp: f32::from_le_bytes(buffer[8..12].try_into().unwrap()),
48 od: f32::from_le_bytes(buffer[12..].try_into().unwrap()),
49 length: p.read_i32(beatmap_addr + BEATMAP_OFFSET.stats.total_length)?,
50 star_rating: crate::reader::beatmap::stable::file::star_rating(p, state)?,
51 object_count: p.read_i32(beatmap_addr + BEATMAP_OFFSET.stats.object_count)?,
52 slider_count: p.read_i32(beatmap_addr + BEATMAP_OFFSET.stats.slider_count)?,
53 })
54}
55
56pub fn info(p: &Process, state: &mut State) -> Result<BeatmapInfo, Error> {
57 let beatmap_addr = beatmap_addr(p, state)?;
58
59 let mut buffer = [0u8; size_of::<f32>() * 4];
60 p.read(beatmap_addr + 0x2c, size_of::<f32>() * 4, &mut buffer)?;
61
62 let stats = BeatmapStats {
63 ar: f32::from_le_bytes(buffer[0..4].try_into().unwrap()),
64 cs: f32::from_le_bytes(buffer[4..8].try_into().unwrap()),
65 hp: f32::from_le_bytes(buffer[8..12].try_into().unwrap()),
66 od: f32::from_le_bytes(buffer[12..].try_into().unwrap()),
67 length: p.read_i32(beatmap_addr + BEATMAP_OFFSET.stats.total_length)?,
68 star_rating: crate::reader::beatmap::stable::file::star_rating(p, state)?,
69 object_count: p.read_i32(beatmap_addr + BEATMAP_OFFSET.stats.object_count)?,
70 slider_count: p.read_i32(beatmap_addr + BEATMAP_OFFSET.stats.slider_count)?,
71 };
72 Ok(BeatmapInfo {
73 technical: BeatmapTechnicalInfo {
74 md5: p.read_string(beatmap_addr + BEATMAP_OFFSET.technical.md5)?,
75 id: p.read_i32(beatmap_addr + BEATMAP_OFFSET.technical.id)?,
76 set_id: p.read_i32(beatmap_addr + BEATMAP_OFFSET.technical.set_id)?,
77 mode: GameMode::Osu,
78 ranked_status: BeatmapStatus::from(
79 p.read_i32(beatmap_addr + BEATMAP_OFFSET.technical.ranked_status)?,
80 ),
81 },
82 metadata: BeatmapMetadata {
83 author: p.read_string(beatmap_addr + BEATMAP_OFFSET.metadata.author)?,
84 creator: p.read_string(beatmap_addr + BEATMAP_OFFSET.metadata.creator)?,
85 title_romanized: p
86 .read_string(beatmap_addr + BEATMAP_OFFSET.metadata.title_romanized)?,
87 title_original: p.read_string(beatmap_addr + BEATMAP_OFFSET.metadata.title_original)?,
88 difficulty: p.read_string(beatmap_addr + BEATMAP_OFFSET.metadata.difficulty)?,
89 tags: p.read_string(beatmap_addr + BEATMAP_OFFSET.metadata.tags)?,
90 },
91 stats,
92 location: BeatmapLocation {
93 folder: p.read_string(beatmap_addr + BEATMAP_OFFSET.location.folder)?,
94 filename: p.read_string(beatmap_addr + BEATMAP_OFFSET.location.filename)?,
95 audio: p.read_string(beatmap_addr + BEATMAP_OFFSET.location.audio)?,
96 cover: p.read_string(beatmap_addr + BEATMAP_OFFSET.location.cover)?,
97 },
98 })
99}