66 lines
2.4 KiB
Rust
66 lines
2.4 KiB
Rust
use std::convert::TryFrom;
|
|
use ferretro::retro::ffi::{MemoryMap};
|
|
|
|
pub struct LibRetroMemoryMap {
|
|
regions: Vec<LibRetroMemoryRegion>,
|
|
}
|
|
|
|
impl LibRetroMemoryMap {
|
|
pub fn get_slice_from_region(&self, offset: usize, length: usize, bank_switch: usize) -> Option<&'static mut [u8]> {
|
|
match self.find_bank(offset, length, bank_switch) {
|
|
Some(ptr) => Some(unsafe { std::slice::from_raw_parts_mut(ptr as *mut u8, length) }),
|
|
None => None
|
|
}
|
|
}
|
|
|
|
fn find_bank(&self, offset: usize, length: usize, bank_switch: usize) -> Option<*const std::ffi::c_void> {
|
|
if self.regions.len() == 0 {
|
|
return None;
|
|
}
|
|
|
|
for item in self.regions.iter() {
|
|
if (item.start <= offset) && (offset < item.end) {
|
|
if offset + length > item.end {
|
|
println!("({:x}, {:x}) overruns ({:x}, {:x}) memory bank.", offset, length, item.start, item.end);
|
|
return None;
|
|
}
|
|
|
|
let bank_size = item.end - item.start;
|
|
let relative_offset = isize::try_from(offset - item.start + (bank_size * bank_switch)).unwrap();
|
|
return unsafe { Some(item.pointer.offset(relative_offset)) }
|
|
}
|
|
}
|
|
println!("({:x}, {:x}) address range not found in any memory map region.", offset, length);
|
|
None
|
|
}
|
|
|
|
pub fn create(memory_map: &MemoryMap) -> Self {
|
|
let mut regions: Vec<LibRetroMemoryRegion> = Vec::new();
|
|
let num_descriptors = isize::try_from(memory_map.num_descriptors).unwrap();
|
|
for i in 0..num_descriptors {
|
|
let region = unsafe { &*memory_map.descriptors.offset(i) };
|
|
let mut length = region.len;
|
|
|
|
if region.select > 0 { // FIXME: hack for oversized SRAM eating addr space
|
|
length = (!region.select + 1) & 0xffffffff;
|
|
println!("truncating memory region {:x} from size {:x} to {:x} banks of size {:x}", region.start, region.len, region.len/length, length)
|
|
}
|
|
|
|
regions.push(LibRetroMemoryRegion {
|
|
start: region.start,
|
|
end: region.start + length,
|
|
pointer: region.ptr,
|
|
})
|
|
}
|
|
|
|
LibRetroMemoryMap {
|
|
regions: regions
|
|
}
|
|
}
|
|
}
|
|
|
|
struct LibRetroMemoryRegion {
|
|
start: usize,
|
|
end: usize,
|
|
pointer: *const std::ffi::c_void,
|
|
} |