New implementation for reading/showing vram
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
sync::{Arc, Mutex, MutexGuard},
|
||||
};
|
||||
|
||||
use bytemuck::BoxBytes;
|
||||
|
||||
use crate::emulator::{EmulatorClient, EmulatorCommand, SimId};
|
||||
|
||||
pub struct MemoryMonitor {
|
||||
client: EmulatorClient,
|
||||
regions: HashMap<MemoryRegion, Arc<Mutex<BoxBytes>>>,
|
||||
}
|
||||
|
||||
impl MemoryMonitor {
|
||||
pub fn new(client: EmulatorClient) -> Self {
|
||||
Self {
|
||||
client,
|
||||
regions: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn view(&mut self, sim: SimId, start: u32, length: usize) -> MemoryView {
|
||||
let region = MemoryRegion { sim, start, length };
|
||||
let memory = self.regions.entry(region).or_insert_with(|| {
|
||||
let mut buf = aligned_memory(start, length);
|
||||
let (tx, rx) = oneshot::channel();
|
||||
self.client
|
||||
.send_command(EmulatorCommand::ReadMemory(sim, start, length, vec![], tx));
|
||||
let bytes = pollster::block_on(rx).unwrap();
|
||||
buf.copy_from_slice(&bytes);
|
||||
#[expect(clippy::arc_with_non_send_sync)] // TODO: remove after bytemuck upgrade
|
||||
Arc::new(Mutex::new(buf))
|
||||
});
|
||||
MemoryView {
|
||||
memory: memory.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn aligned_memory(start: u32, length: usize) -> BoxBytes {
|
||||
if start % 4 == 0 && length % 4 == 0 {
|
||||
let memory = vec![0u32; length / 4].into_boxed_slice();
|
||||
return bytemuck::box_bytes_of(memory);
|
||||
}
|
||||
if start % 2 == 0 && length % 2 == 0 {
|
||||
let memory = vec![0u16; length / 2].into_boxed_slice();
|
||||
return bytemuck::box_bytes_of(memory);
|
||||
}
|
||||
let memory = vec![0u8; length].into_boxed_slice();
|
||||
bytemuck::box_bytes_of(memory)
|
||||
}
|
||||
|
||||
pub struct MemoryView {
|
||||
memory: Arc<Mutex<BoxBytes>>,
|
||||
}
|
||||
// SAFETY: BoxBytes is supposed to be Send+Sync, will be in a new version
|
||||
unsafe impl Send for MemoryView {}
|
||||
|
||||
impl MemoryView {
|
||||
pub fn borrow(&self) -> MemoryRef<'_> {
|
||||
MemoryRef {
|
||||
inner: self.memory.lock().unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MemoryRef<'a> {
|
||||
inner: MutexGuard<'a, BoxBytes>,
|
||||
}
|
||||
|
||||
impl MemoryRef<'_> {
|
||||
pub fn read(&self, index: usize) -> u8 {
|
||||
self.inner[index]
|
||||
}
|
||||
pub fn range<T: bytemuck::AnyBitPattern>(&self, start: usize, count: usize) -> &[T] {
|
||||
let from = start * size_of::<T>();
|
||||
let to = from + (count * size_of::<T>());
|
||||
bytemuck::cast_slice(&self.inner[from..to])
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
||||
struct MemoryRegion {
|
||||
sim: SimId,
|
||||
start: u32,
|
||||
length: usize,
|
||||
}
|
||||
Reference in New Issue
Block a user