2024-02-18 22:03:10 +05:30
|
|
|
use std::cell::RefCell;
|
2024-02-17 09:54:41 +05:30
|
|
|
use std::ops::Index;
|
2024-02-16 23:13:59 +05:30
|
|
|
use crate::emu::mmu::Memory;
|
2024-02-17 09:54:41 +05:30
|
|
|
use crate::misc::emulator_error::DeviceType::RAM;
|
|
|
|
use crate::misc::emulator_error::EmulatorError;
|
|
|
|
use crate::misc::result::EmulatorResult;
|
2024-02-16 23:13:59 +05:30
|
|
|
|
2024-02-18 09:44:49 +05:30
|
|
|
const MAPPED_MEMORY_NOT_REQUIRED: u8 = 8;
|
|
|
|
const MEM_LENGTH: usize = (2 << 24) - (MAPPED_MEMORY_NOT_REQUIRED as usize);
|
2024-02-16 23:13:59 +05:30
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
pub struct RamMemory {
|
2024-02-18 22:03:10 +05:30
|
|
|
data: RefCell<Box<[u8; MEM_LENGTH]>>,
|
2024-02-16 23:13:59 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
impl RamMemory {
|
2024-02-17 09:54:41 +05:30
|
|
|
pub fn try_new() -> EmulatorResult<RamMemory> {
|
|
|
|
let alloc_result = vec![0; MEM_LENGTH].into_boxed_slice();
|
|
|
|
let data = alloc_result.try_into().map_err(|err|{
|
2024-02-17 11:22:26 +05:30
|
|
|
EmulatorError::AllocationFailure(RAM, "Allocation failed")
|
2024-02-17 09:54:41 +05:30
|
|
|
})?;
|
2024-02-18 22:03:10 +05:30
|
|
|
let data_refcell = RefCell::new(data);
|
2024-02-17 09:54:41 +05:30
|
|
|
Ok(RamMemory {
|
2024-02-18 22:03:10 +05:30
|
|
|
data: data_refcell
|
2024-02-17 09:54:41 +05:30
|
|
|
})
|
2024-02-16 23:13:59 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-17 09:54:41 +05:30
|
|
|
|
2024-02-16 23:13:59 +05:30
|
|
|
impl Memory for RamMemory {
|
2024-02-17 09:54:41 +05:30
|
|
|
fn try_get_byte(&self, address: u32) -> EmulatorResult<u8> {
|
2024-02-16 23:13:59 +05:30
|
|
|
log::trace!("Fetch RAM memory at address {}",address);
|
2024-02-18 22:03:10 +05:30
|
|
|
let mut data = self.data.borrow_mut();
|
|
|
|
let x = *data.get(address as usize).ok_or(EmulatorError::UnreachableMemory(RAM, address))?;
|
2024-02-17 09:54:41 +05:30
|
|
|
Ok(x)
|
2024-02-16 23:13:59 +05:30
|
|
|
}
|
|
|
|
|
2024-02-18 22:03:10 +05:30
|
|
|
fn try_set_byte(&self, address: u32, value: u8) -> EmulatorResult<()> {
|
2024-02-17 09:54:41 +05:30
|
|
|
if address>= MEM_LENGTH as u32 {
|
2024-02-17 11:22:26 +05:30
|
|
|
return Err(EmulatorError::UnreachableMemory(RAM, address))
|
2024-02-17 09:54:41 +05:30
|
|
|
}
|
2024-02-18 22:03:10 +05:30
|
|
|
let mut data = self.data.borrow_mut();
|
|
|
|
data[address as usize] = value;
|
2024-02-17 09:54:41 +05:30
|
|
|
Ok(())
|
2024-02-16 23:13:59 +05:30
|
|
|
}
|
2024-02-17 12:26:27 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests{
|
2024-02-18 09:44:49 +05:30
|
|
|
use crate::emu::ram::RamMemory;
|
2024-02-17 12:26:27 +05:30
|
|
|
use crate::emu::mmu::Memory;
|
|
|
|
const EXAMPLE_ADDRESS:u32=0x24;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
pub fn get_mem(){
|
|
|
|
let ram_result = RamMemory::try_new();
|
|
|
|
assert!(ram_result.is_ok())
|
|
|
|
}
|
|
|
|
#[test]
|
|
|
|
pub fn get_set_memory(){
|
|
|
|
const EXAMPLE_DATA:u8 = 0xa5;
|
|
|
|
let mut ram = RamMemory::try_new().unwrap();
|
|
|
|
let byte_before = ram.try_get_byte(EXAMPLE_ADDRESS).unwrap();
|
|
|
|
ram.try_set_byte(EXAMPLE_ADDRESS, EXAMPLE_DATA).unwrap();
|
|
|
|
let byte_after = ram.try_get_byte(EXAMPLE_ADDRESS).unwrap();
|
|
|
|
assert_eq!(0,byte_before);
|
|
|
|
assert_eq!(EXAMPLE_DATA,byte_after);
|
|
|
|
}
|
2024-02-16 23:13:59 +05:30
|
|
|
}
|