Initial commit
This commit is contained in:
163
src/mem.rs
Normal file
163
src/mem.rs
Normal file
@@ -0,0 +1,163 @@
|
||||
use crate::hex_view::Memory;
|
||||
|
||||
pub enum Value<'a, R> {
|
||||
Value(u8),
|
||||
Register { reg: &'a R, offset: u16 },
|
||||
}
|
||||
|
||||
impl<R> Value<'_, R> {
|
||||
pub fn reg_map(self, f: impl FnOnce(&R, u16) -> u8) -> u8 {
|
||||
match self {
|
||||
Value::Value(v) => v,
|
||||
Value::Register { reg, offset } => f(reg, offset),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Data<R> {
|
||||
RAM(Vec<u8>),
|
||||
ROM(Vec<u8>),
|
||||
Mirror(usize),
|
||||
Reg(R),
|
||||
// Disabled(),
|
||||
}
|
||||
|
||||
pub struct Segment<R> {
|
||||
name: &'static str,
|
||||
position: u16,
|
||||
size: u16,
|
||||
mem: Data<R>,
|
||||
}
|
||||
|
||||
impl<R> Segment<R> {
|
||||
pub fn ram(name: &'static str, position: u16, size: u16) -> Self {
|
||||
Self {
|
||||
name,
|
||||
position,
|
||||
size,
|
||||
mem: Data::RAM(vec![0u8; size as usize]),
|
||||
}
|
||||
}
|
||||
pub fn rom(name: &'static str, position: u16, raw: &[u8]) -> Self {
|
||||
Self {
|
||||
name,
|
||||
position,
|
||||
size: raw.len() as u16,
|
||||
mem: Data::ROM(Vec::from(raw)),
|
||||
}
|
||||
}
|
||||
pub fn reg(name: &'static str, position: u16, size: u16, reg: R) -> Self {
|
||||
Self {
|
||||
name,
|
||||
position,
|
||||
size,
|
||||
mem: Data::Reg(reg),
|
||||
}
|
||||
}
|
||||
pub fn mirror(name: &'static str, position: u16, size: u16, of: usize) -> Self {
|
||||
Self {
|
||||
name,
|
||||
position,
|
||||
size,
|
||||
mem: Data::Mirror(of),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MemoryMap<R> {
|
||||
edit_ver: usize,
|
||||
segments: Vec<Segment<R>>,
|
||||
}
|
||||
|
||||
impl<R> MemoryMap<R> {
|
||||
pub fn new(segments: Vec<Segment<R>>) -> Self {
|
||||
Self { edit_ver: 0, segments }
|
||||
}
|
||||
pub fn read(&self, addr: u16) -> Value<'_, R> {
|
||||
// self.edit_ver += 1;
|
||||
for segment in &self.segments {
|
||||
if segment.position <= addr && addr - segment.position < segment.size {
|
||||
return match &segment.mem {
|
||||
Data::RAM(items) => Value::Value(items[(addr - segment.position) as usize]),
|
||||
Data::ROM(items) => Value::Value(items[(addr - segment.position) as usize]),
|
||||
Data::Reg(reg) => Value::Register {
|
||||
reg,
|
||||
offset: addr - segment.position,
|
||||
},
|
||||
Data::Mirror(index) => {
|
||||
let offset = addr - segment.position;
|
||||
let s = &self.segments[*index];
|
||||
self.read(s.position + offset % s.size)
|
||||
}
|
||||
// Data::Disabled() => todo!(),
|
||||
};
|
||||
}
|
||||
}
|
||||
todo!("Open bus")
|
||||
}
|
||||
|
||||
pub fn write(&mut self, addr: u16, val: u8, reg_fn: impl FnOnce(&R, u16, u8)) {
|
||||
self.edit_ver += 1;
|
||||
for segment in &mut self.segments {
|
||||
if segment.position <= addr && addr - segment.position < segment.size {
|
||||
return match &mut segment.mem {
|
||||
Data::RAM(items) => {
|
||||
items[(addr - segment.position) as usize] = val;
|
||||
}
|
||||
Data::ROM(_items) => (),
|
||||
Data::Reg(reg) => reg_fn(reg, addr - segment.position, val),
|
||||
Data::Mirror(index) => {
|
||||
let offset = addr - segment.position;
|
||||
let index = *index;
|
||||
let s = &self.segments[index];
|
||||
self.write(s.position + offset % s.size, val, reg_fn)
|
||||
}
|
||||
// Data::Disabled() => todo!(),
|
||||
};
|
||||
}
|
||||
}
|
||||
todo!("Open bus")
|
||||
}
|
||||
|
||||
pub fn clear(&mut self) {
|
||||
for s in &mut self.segments {
|
||||
match &mut s.mem {
|
||||
Data::RAM(items) => items.fill(0),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn rom(&self, idx: usize) -> Option<&[u8]> {
|
||||
if let Some(Segment { mem: Data::ROM(val), .. }) = self.segments.get(idx) {
|
||||
Some(val)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<R> Memory for MemoryMap<R> {
|
||||
fn peek(&self, addr: u16) -> Option<u8> {
|
||||
for segment in &self.segments {
|
||||
if segment.position <= addr && addr - segment.position < segment.size {
|
||||
return match &segment.mem {
|
||||
Data::RAM(items) => Some(items[(addr - segment.position) as usize]),
|
||||
Data::ROM(items) => Some(items[(addr - segment.position) as usize]),
|
||||
Data::Reg(_) => None,
|
||||
Data::Mirror(index) => {
|
||||
let offset = addr - segment.position;
|
||||
let s = &self.segments[*index];
|
||||
self.peek(s.position + offset % s.size)
|
||||
}
|
||||
// Data::Disabled() => todo!(),
|
||||
};
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn edit_ver(&self) -> usize {
|
||||
self.edit_ver
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user