libscemu/emu/maps/
mem64.rs1use md5;
6use std::fs::File;
7use std::io::prelude::*;
8use std::io::BufReader;
9use std::io::Read;
10use std::io::SeekFrom;
11use std::io::Write;
12
13#[derive(Clone)]
14pub struct Mem64 {
15 mem_name: String,
16 base_addr: u64,
17 bottom_addr: u64,
18 pub mem: Vec<u8>,
19}
20
21impl Mem64 {
22 pub fn new() -> Mem64 {
23 Mem64 {
24 mem_name: "".to_string(),
25 base_addr: 0,
26 bottom_addr: 0,
27 mem: Vec::new(),
28 }
29 }
30
31 pub fn get_name(&self) -> String {
32 return self.mem_name.clone();
33 }
34
35 pub fn set_name(&mut self, name: &str) {
36 self.mem_name = name.to_string();
37 }
38
39 pub fn get_mem(&self) -> Vec<u8> {
40 return self.mem.clone();
41 }
42
43 pub fn alloc(&mut self, amount: usize) {
44 self.mem = vec![0; amount];
45 }
46
47 pub fn extend(&mut self, amount: usize) {
48 for i in 0..amount {
49 self.mem.push(0);
50 }
51 self.bottom_addr += amount as u64;
52 }
53
54 pub fn size(&self) -> usize {
55 self.mem.len()
56 }
57
58 pub fn get_base(&self) -> u64 {
59 self.base_addr
60 }
61
62 pub fn get_bottom(&self) -> u64 {
63 self.bottom_addr
64 }
65
66 pub fn memcpy(&mut self, ptr: &[u8], sz: usize) {
67 if self.mem.len() < sz {
68 panic!("memcpy: {} < {}", self.mem.len(), sz);
69 }
70 for i in 0..sz {
71 self.mem[i] = ptr[i];
72 }
73 }
74
75 pub fn inside(&self, addr: u64) -> bool {
76 if addr >= self.base_addr && addr < self.bottom_addr {
77 return true;
78 }
79 false
80 }
81
82 pub fn set_base(&mut self, base_addr: u64) {
83 self.base_addr = base_addr;
84 self.bottom_addr = base_addr;
85 }
86
87 pub fn update_base(&mut self, base_addr: u64) {
88 self.base_addr = base_addr;
89 }
90
91 pub fn set_bottom(&mut self, bottom_addr: u64) {
92 self.bottom_addr = bottom_addr;
93 let size = self.bottom_addr - self.base_addr;
94 self.alloc(size as usize);
95 }
96
97 pub fn update_bottom(&mut self, bottom_addr: u64) {
98 self.bottom_addr = bottom_addr;
99 }
100
101 pub fn set_size(&mut self, size: u64) {
102 self.bottom_addr = self.base_addr + size;
103 self.alloc(size as usize);
104 }
105
106 pub fn read_from(&self, addr: u64) -> &[u8] {
107 let idx = (addr - self.base_addr) as usize;
108 let max_sz = (self.bottom_addr - self.base_addr) as usize;
109 return self.mem.get(idx..max_sz).unwrap();
115 }
116
117 pub fn read_bytes(&self, addr: u64, sz: usize) -> &[u8] {
118 let idx = (addr - self.base_addr) as usize;
119 let sz2 = idx as usize + sz;
120 if sz2 > self.mem.len() {
121 return &[0; 0];
122 }
123 return self.mem.get(idx..sz2).unwrap();
124 }
125
126 pub fn read_byte(&self, addr: u64) -> u8 {
127 assert!(self.inside(addr));
128
129 let idx = (addr - self.base_addr) as usize;
130 if idx < self.mem.len() {
131 self.mem[idx]
132 } else {
133 panic!("reading at 0x{:x}", addr);
134 }
135 }
136
137 pub fn read_word(&self, addr: u64) -> u16 {
138 let idx = (addr - self.base_addr) as usize;
139 (self.mem[idx] as u16) + ((self.mem[idx + 1] as u16) << 8)
140 }
141
142 pub fn read_dword(&self, addr: u64) -> u32 {
143 let idx = (addr - self.base_addr) as usize;
144 (self.mem[idx] as u32)
145 + ((self.mem[idx + 1] as u32) << 8)
146 + ((self.mem[idx + 2] as u32) << 16)
147 + ((self.mem[idx + 3] as u32) << 24)
148 }
149
150 pub fn read_qword(&self, addr: u64) -> u64 {
151 let idx = (addr - self.base_addr) as usize;
152 let mut r: u64 = 0;
153
154 for i in 0..8 {
155 r |= (self.mem[idx + i] as u64) << (8 * i);
156 }
157
158 r
159 }
160
161 pub fn write_byte(&mut self, addr: u64, value: u8) {
162 let idx = (addr - self.base_addr) as usize;
163 self.mem[idx] = value;
164 }
165
166 pub fn write_bytes(&mut self, addr: u64, bs: &[u8]) {
167 let idx = (addr - self.base_addr) as usize;
168 for i in 0..bs.len() {
169 self.mem[idx + i] = bs[i];
170 }
171 }
172
173 pub fn write_word(&mut self, addr: u64, value: u16) {
174 let idx = (addr - self.base_addr) as usize;
175 self.mem[idx] = (value & 0x00ff) as u8;
176 self.mem[idx + 1] = ((value & 0xff00) >> 8) as u8;
177 }
178
179 pub fn write_dword(&mut self, addr: u64, value: u32) {
180 let idx = (addr - self.base_addr) as usize;
181 assert!(idx < self.mem.len());
182 self.mem[idx] = (value & 0x000000ff) as u8;
183 self.mem[idx + 1] = ((value & 0x0000ff00) >> 8) as u8;
184 self.mem[idx + 2] = ((value & 0x00ff0000) >> 16) as u8;
185 self.mem[idx + 3] = ((value & 0xff000000) >> 24) as u8;
186 }
187
188 pub fn write_qword(&mut self, addr: u64, value: u64) {
189 let idx = (addr - self.base_addr) as usize;
190 for i in 0..8 {
191 self.mem[idx + i] = ((value >> (i * 8)) & 0xff) as u8;
192 }
193 }
194
195 pub fn write_string(&mut self, addr: u64, s: &str) {
196 let mut v = s.as_bytes().to_vec();
197 v.push(0);
198 self.write_bytes(addr, &v);
199 }
200
201 pub fn write_wide_string(&mut self, addr: u64, s: &str) {
202 let mut wv: Vec<u8> = Vec::new();
203 let v = s.as_bytes().to_vec();
204 for b in v {
205 wv.push(b);
206 wv.push(0);
207 }
208 wv.push(0);
209 wv.push(0);
210 self.write_bytes(addr, &wv);
211 }
212
213 pub fn print_bytes(&self) {
214 log::info!("---mem---");
215 for b in self.mem.iter() {
216 print!("{}", b);
217 }
218 log::info!("---");
219 }
220
221 pub fn print_dwords(&self) {
222 self.print_dwords_from_to(self.get_base(), self.get_bottom());
223 }
224
225 pub fn print_dwords_from_to(&self, from: u64, to: u64) {
226 log::info!("---mem---");
227 for addr in (from..to).step_by(4) {
228 log::info!("0x{:x}", self.read_dword(addr))
229 }
230
231 log::info!("---");
232 }
233
234 pub fn md5(&self) -> md5::Digest {
235 md5::compute(&self.mem)
236 }
237
238 pub fn load_at(&mut self, base_addr: u64) {
239 self.set_base(base_addr);
240 let mut name: String = String::from(&self.mem_name);
241 name.push_str(".bin");
242 self.load(name.as_str());
243 }
244
245 pub fn load_chunk(&mut self, filename: &str, off: u64, sz: usize) -> bool {
246 let mut f = match File::open(&filename) {
248 Ok(f) => f,
249 Err(_) => {
250 return false;
251 }
252 };
253 f.seek(SeekFrom::Start(off));
254 let mut reader = BufReader::new(&f);
255 self.mem.clear();
256 for i in 0..sz {
257 self.mem.push(0);
258 }
259 reader
260 .read_exact(&mut self.mem)
261 .expect("cannot load chunk of file");
262 f.sync_all(); true
264 }
265
266 pub fn load(&mut self, filename: &str) -> bool {
267 let f = match File::open(&filename) {
269 Ok(f) => f,
270 Err(_) => {
271 return false;
272 }
273 };
274 let len = f.metadata().unwrap().len();
275 self.bottom_addr = self.base_addr + len;
276 let mut reader = BufReader::new(&f);
277 reader
278 .read_to_end(&mut self.mem)
279 .expect("cannot load map file");
280 f.sync_all(); true
282 }
283
284 pub fn save(&self, addr: u64, size: usize, filename: String) {
285 let idx = (addr - self.base_addr) as usize;
286 let sz2 = idx as usize + size;
287 if sz2 > self.mem.len() {
288 log::info!("size too big, map size is {} sz2:{}", self.mem.len(), sz2);
289 return;
290 }
291
292 let mut f = match File::create(filename) {
293 Ok(f) => f,
294 Err(e) => {
295 log::info!("cannot create the file {}", e);
296 return;
297 }
298 };
299
300 let blob = self.mem.get(idx..sz2).unwrap();
301
302 match f.write_all(blob) {
303 Ok(_) => log::info!("saved."),
304 Err(_) => log::info!("couldn't save the file"),
305 }
306
307 f.sync_all().unwrap();
308 }
309}