libscemu/emu/maps/
mem64.rs

1/*
2    Little endian 64 bits and inferior bits memory.
3*/
4
5use 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        /*
110        let mut sz = idx + 5;
111        if sz > max_sz {
112            sz = max_sz;
113        }*/
114        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        // log::info!("loading chunk: {} {} {}", filename, off, sz);
247        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(); // thanks Alberto Segura
263        true
264    }
265
266    pub fn load(&mut self, filename: &str) -> bool {
267        // log::info!("loading map: {}", filename);
268        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(); // thanks Alberto Segura
281        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}