scanmem alternative with concurrent memory scanning
at master 3.5 kB view raw
1use rand::Rng; 2use std::{ 3 io::{self, Read, Write}, 4 sync::mpsc, 5 thread, 6 time::Duration, 7}; 8 9// This is a practice program to test if the main programs behaviour works fine 10// This program has been validated and confirmed to work as expected with scanmem 11 12// Structure to hold the "real" game state 13struct GameState { 14 // Internal values that control the actual game state 15 values: Vec<i32>, 16} 17 18// Structure to manage what's displayed on screen 19struct GameDisplay { 20 // Pointers to copies of values shown to the player 21 display_values: Vec<Box<i32>>, 22} 23 24impl GameState { 25 fn new(count: usize, rng: &mut impl Rng) -> Self { 26 let mut values = Vec::with_capacity(count); 27 for _ in 0..count { 28 values.push(rng.gen_range(1..10)); 29 } 30 Self { values } 31 } 32 33 fn get_value(&self, index: usize) -> i32 { 34 self.values[index] 35 } 36 37 fn set_value(&mut self, index: usize, value: i32) { 38 self.values[index] = value; 39 } 40} 41 42impl GameDisplay { 43 fn new(count: usize) -> Self { 44 let mut display_values = Vec::with_capacity(count); 45 for _ in 0..count { 46 display_values.push(Box::new(0)); 47 } 48 Self { display_values } 49 } 50 51 fn update_from_state(&mut self, state: &GameState) { 52 for (i, val) in state.values.iter().enumerate() { 53 *self.display_values[i] = *val; 54 } 55 } 56 57 fn get_display_ptr(&self, index: usize) -> *const i32 { 58 &*self.display_values[index] as *const i32 59 } 60 61 fn get_displayed_value(&self, index: usize) -> i32 { 62 *self.display_values[index] 63 } 64} 65 66fn main() { 67 let mut rng = rand::thread_rng(); 68 69 const LEN: usize = 10; 70 71 let mut game_state = GameState::new(LEN, &mut rng); 72 let mut game_display = GameDisplay::new(LEN); 73 74 game_display.update_from_state(&game_state); 75 76 let (tx, rx) = mpsc::channel(); 77 78 thread::spawn(move || { 79 let mut buffer = [0; 1]; 80 loop { 81 if let Ok(_) = io::stdin().read_exact(&mut buffer) { 82 let _ = tx.send(()); 83 } 84 } 85 }); 86 87 let mut refresh_counter = 0; 88 89 loop { 90 print!("\x1B[2J\x1B[1;1H"); 91 92 refresh_counter += 1; 93 if refresh_counter >= 3 { 94 refresh_counter = 0; 95 game_display.update_from_state(&game_state); 96 println!("(Display refreshed from game state)"); 97 } 98 99 println!( 100 "Memory Scanner Target (Realistic Game Structure) - Press ENTER for new values, Ctrl+C to quit" 101 ); 102 println!("Displayed values (what you see on screen):"); 103 104 for i in 0..LEN { 105 let display_value = game_display.get_displayed_value(i); 106 let display_ptr = game_display.get_display_ptr(i); 107 println!( 108 "Value {}: {} (displayed at {:p})", 109 i, display_value, display_ptr 110 ); 111 } 112 113 println!("\nInternal game state (would be hidden in a real game):"); 114 for i in 0..LEN { 115 println!("Value {}: {}", i, game_state.get_value(i)); 116 } 117 118 println!("\nPress ENTER to change all values..."); 119 io::stdout().flush().unwrap(); 120 121 if rx.recv_timeout(Duration::from_secs(1)).is_ok() { 122 for i in 0..LEN { 123 game_state.set_value(i, rng.gen_range(1..10)); 124 } 125 game_display.update_from_state(&game_state); 126 refresh_counter = 0; 127 } 128 } 129}