space-invade.rs-hack/emulator/src/memory.rs

90 lines
2.5 KiB
Rust

use std::fs::File;
use std::io::Read;
use crate::state::State;
use crate::opcodes::Opcode;
use std::sync::{Mutex, RwLock};
use lazy_static::lazy_static;
use crate::emulator_state::SharedState;
const MEMORY_SIZE: usize = 0x10000;
pub const SCREEN_WIDTH: usize = 0x20; // 0x20 bytes (256 pixels)
pub const SCREEN_HEIGHT: usize = 0xe0;
pub const GRAPHIC_MEMORY_SIZE: usize = SCREEN_WIDTH * SCREEN_HEIGHT;
pub trait GraphicRenderer: Send {
fn draw(&mut self, x: u8, y: u8, value: u8);
fn color(&self, x: u8, y: u8) -> u8;
fn display(&self);
}
static _STATIC_MEMORY: [u8; MEMORY_SIZE] = [0; MEMORY_SIZE];
lazy_static! {
pub(crate) static ref STATIC_MEMORY: RwLock<[u8; MEMORY_SIZE]> = RwLock::new(_STATIC_MEMORY);
}
pub struct Memory {
pub verbose: bool,
}
impl Memory {
pub fn new() -> Self {
Memory {
verbose: false,
}
}
pub(crate) fn set_verbose(&mut self, v: bool) {
self.verbose = v;
}
pub fn read_file(&mut self, file_name: &str, start: usize) {
let mut file = File::open(file_name).expect("Couldn't open file");
let mut buffer = Vec::new();
file.read_to_end(&mut buffer).expect("Couldn't read file");
let mut state = State::default();
state.pc = start;
let mut i: usize = 0;
for byte in buffer {
self.write(i + state.pc, byte);
i += 1;
}
}
pub(crate) fn write(&mut self, address: usize, value: u8) {
STATIC_MEMORY.write().unwrap()[address] = value;
if self.verbose {
println!(" mem[{:04x}={:02X}]", address, value );
}
}
pub(crate) fn read(&self, i: usize) -> u8 {
STATIC_MEMORY.read().unwrap()[i]
}
pub(crate) fn read_word(&self, b0: u8, b1: u8) -> u8 {
STATIC_MEMORY.read().unwrap()[Memory::to_word(b0, b1)]
}
pub(crate) fn write_word(&mut self, b0: u8, b1: u8, value: u8) {
let address = Memory::to_word(b0, b1);
STATIC_MEMORY.write().unwrap()[address] = value;
}
pub(crate) fn disassemble(&self, opcode: &Opcode, pc: usize) -> (String, usize) {
let formatted_opcode = match opcode.size {
1 => opcode.display1(),
2 => opcode.display2(self.read(pc + 1)),
_ => opcode.display3(self.read(pc + 1), self.read(pc + 2)),
};
let result = format!("{:04x}: {}", pc, formatted_opcode);
(result, opcode.size)
}
pub(crate) fn to_word(b1: u8, b2: u8) -> usize {
return ((b2 as u16) << 8 | b1 as u16) as usize;
}
}