Moar reworks

This commit is contained in:
PeronTheDuck 2020-01-28 03:21:14 -03:00
parent a9f1a63900
commit 4fd4d326c1
5 changed files with 127 additions and 38 deletions

View File

@ -1,6 +1,7 @@
use std::convert::{From, Into};
struct Address(usize);
#[derive(Copy, Clone, PartialEq, PartialOrd, Debug)]
pub struct Address(pub usize);
impl From<usize> for Address {
fn from(v: usize) -> Self {
if v > 0xFFFF {
@ -9,11 +10,69 @@ impl From<usize> for Address {
Self(v)
}
}
impl From<i32> for Address {
fn from(v: i32) -> Self {
if v < 0 || v > 0xFFFF {
panic!("Can't use {}i32 as address", v);
}
Address((v & 0xFFFF) as usize)
}
}
impl From<u16> for Address {
fn from(v: u16) -> Self {
Self(v as usize)
}
}
impl From<u8> for Address {
fn from(v: u8) -> Self {
Address((v as usize) & 0xFF)
}
}
impl Into<usize> for Address {
fn into(self) -> usize {
*self & 0xFFFF
}
}
impl Into<u16> for Address {
fn into(self) -> u16 {
(*self & 0xFFFF) as u16
}
}
impl std::ops::Deref for Address {
type Target = usize;
fn deref(&self) -> &usize {
&self.0
}
}
impl std::ops::DerefMut for Address {
fn deref_mut(&mut self) -> &mut usize {
&mut self.0
}
}
impl std::ops::Add for Address {
type Output = Self;
fn add(self, rhs: Self) -> Self {
let result = *self + *rhs;
if result > 0xFFFF {
panic!(
"Resulting op between Address and 0x{:04X} is bigger than 0xFFFF",
*rhs
);
}
Address(result)
}
}
impl Address {
pub fn same_page_add<I: Into<usize>>(self, rhs: I) -> Self {
let rhs = rhs.into() & 0x00FF;
let hi = *self & 0xFF00;
let lo = (*self + rhs) & 0xFF;
Address(hi | lo)
}
pub fn next(&self) -> Self {
Address(self.0 + 1)
}
}
pub fn get_size(addr_mode: AddressingMode) -> usize {
OP_SIZES[addr_mode as usize]

View File

@ -1,3 +1,33 @@
use super::addressing_modes::Address;
/* #region Ram */
pub struct Ram(pub [u8; 0x10000]);
impl Ram {
pub fn load(&mut self, code: [u8; 0x10000]) {
self.0 = code;
}
}
impl std::ops::Index<Address> for Ram {
type Output = u8;
fn index(&self, idx: Address) -> &u8 {
let idx: usize = idx.into();
&self.0[idx]
}
}
impl std::ops::IndexMut<Address> for Ram {
fn index_mut(&mut self, idx: Address) -> &mut u8 {
let idx: usize = idx.into();
&mut self.0[idx]
}
}
impl std::ops::Deref for Ram {
type Target = [u8; 0x10000];
fn deref(&self) -> &[u8; 0x10000] {
&self.0
}
}
/* #endregion */
#[repr(u8)]
#[derive(PartialEq, Copy, Clone, Debug)]
pub enum Flags {
@ -15,7 +45,7 @@ pub struct Registers {
pub A: u8,
pub X: u8,
pub Y: u8,
pub PC: u16,
pub PC: Address,
pub flags: u8,
}
impl Registers {
@ -52,7 +82,7 @@ impl std::default::Default for Registers {
A: 0x00,
X: 0x00,
Y: 0x00,
PC: 0x0000,
PC: 0x0000usize.into(),
flags: 0b_0010_0000,
}
}
@ -62,7 +92,7 @@ impl std::fmt::Debug for Registers {
write!(
f,
"Registers: \n PC: {:04X}\n A: {:02X} X: {:02X} Y: {:02X}\nNV-BDIZC\n{:08b}",
self.PC, self.A, self.X, self.Y, self.flags
*self.PC, self.A, self.X, self.Y, self.flags
)
}
}

View File

@ -5,6 +5,6 @@ mod addressing_modes;
use addressing_modes::AddressingMode;
mod opcodes;
use opcodes::OpcodeType;
mod registers;
mod components;
mod system;
pub use system::System;

View File

@ -1,24 +1,24 @@
use super::addressing_modes::{get_size, Address, AddressingMode};
use super::components::{Flags, Ram, Registers};
use super::error;
use super::opcodes;
use super::registers::{Flags, Registers};
use super::OpcodeType;
use super::{addressing_modes::get_size, AddressingMode};
fn invalid_mode<T>(mode_used: AddressingMode) -> T {
panic!("The addressign mode used ({:?}) is either not valid for this opcode, or expects an argument which was not provided",mode_used)
}
static RESET_VEC_ADDR: usize = 0xFFFC;
static RESET_VEC_ADDR: Address = Address(0xFFFC);
macro_rules! fetch {
($self:ident PC+$off:expr) => {
$self.ram[$self.registers.PC as usize + $off]
$self.ram[$self.registers.PC + Address($off)]
};
($self:ident $addr:expr) => {
$self.ram[$addr as usize]
$self.ram[$addr]
};
($self:ident D $addr:expr) => {
($self.ram[$addr as usize + 1] as u16) << 8 | $self.ram[$addr as usize] as u16
($self.ram[$addr.next()] as u16) << 8 | $self.ram[$addr] as u16
};
}
macro_rules! operation {
@ -35,22 +35,22 @@ macro_rules! operation {
pub struct System {
pub cycles: usize,
pub ram: [u8; 0x10000],
pub ram: Ram,
pub registers: Registers,
}
impl System {
pub fn new() -> Self {
Self {
cycles: 0,
ram: [0x00; 0x10000],
ram: Ram([0x00; 0x10000]),
registers: Registers::default(),
}
}
pub fn init(&mut self) -> Result<(), error::CpuError> {
let lo: u16 = self.ram[RESET_VEC_ADDR] as u16;
let hi: u16 = self.ram[RESET_VEC_ADDR + 1] as u16;
let hi: u16 = self.ram[RESET_VEC_ADDR.same_page_add(1usize)] as u16;
let addr = hi << 8 | lo;
self.registers.PC = addr;
self.registers.PC = addr.into();
Ok(())
}
pub fn step(&mut self) -> Result<(), error::CpuError> {
@ -61,8 +61,8 @@ impl System {
/* if self.registers.test(Flags::Break) {
return Err(error::EmulatorError::Break);
} */
println!("Step on {:04X}", self.registers.PC);
let code = self.ram[self.registers.PC as usize];
println!("Step on {:04X}", *self.registers.PC);
let code = self.ram[self.registers.PC];
let code = match opcodes::from_code(code) {
None => return Err(error::CpuError::UnknownOp(code)),
Some(v) => v,
@ -78,28 +78,28 @@ impl System {
}
AddressingMode::ABS => {
// Next 2 bytes are an address from where to fetch the real argument
let addr = self.registers.PC as usize + 1;
let addr = self.registers.PC.next();
Some(fetch!(self D addr) as u16)
}
AddressingMode::ZPG => {
// Next byte is an address from the range 0x0000-0x00FF
let addr = self.registers.PC as usize + 1;
let addr = self.registers.PC.same_page_add(1u16);
Some(fetch!(self addr) as u16)
}
AddressingMode::INDX => {
// Take the next byte and add it to X,
// then use the result as an address and fetch 2 bytes
let arg = fetch!(self PC+1); // Opcode arg
let addr: u8 = operation!(self X+arg); // Zero-page addr
let addr_lo = self.ram[addr as usize] as usize;
let addr_hi = self.ram[addr.wrapping_add(1) as usize] as usize;
let addr: Address = operation!(self X+arg).into(); // Zero-page addr
let addr_lo = self.ram[addr] as usize;
let addr_hi = self.ram[addr.next()] as usize;
let res_addr = addr_hi << 8 | addr_lo;
Some(res_addr as u16)
}
AddressingMode::REL => {
// Add PC with the next byte
let arg = fetch!(self PC+1) as u8 as i8 as isize;
let pc = self.registers.PC as usize as isize;
let pc = (*self.registers.PC) as isize;
let new_pc = (arg + pc) & 0xFFFF;
Some(new_pc as u16)
}
@ -120,21 +120,21 @@ impl System {
AddressingMode::IMM => self.registers.set_a(operation!(unwrap arg code) as u8),
AddressingMode::ABS => self
.registers
.set_a(fetch!(self operation!(unwrap arg code))),
.set_a(fetch!(self operation!(unwrap arg code).into())),
AddressingMode::ZPG => self
.registers
.set_a(fetch!(self operation!(unwrap arg code))),
.set_a(fetch!(self operation!(unwrap arg code).into())),
_ => panic!("Invalid addressing mode for {:?}", code.name),
},
OpcodeType::STA => match code.addr_mode {
AddressingMode::ABS => {
self.ram[operation!(unwrap arg code) as usize] = self.registers.A
self.ram[operation!(unwrap arg code).into()] = self.registers.A
}
AddressingMode::ZPG => {
self.ram[operation!(unwrap arg code) as usize] = self.registers.A
self.ram[operation!(unwrap arg code).into()] = self.registers.A
}
AddressingMode::INDX => {
self.ram[operation!(unwrap arg code) as usize] = self.registers.A
self.ram[operation!(unwrap arg code).into()] = self.registers.A
}
_ => panic!("Invalid addressing mode for {:?}", code.name),
},
@ -143,18 +143,18 @@ impl System {
_ => panic!("Invalid addressing mode for {:?}", code.name),
},
OpcodeType::JMP => match code.addr_mode {
AddressingMode::ABS => self.registers.PC = operation!(unwrap arg code) as u16,
AddressingMode::ABS => self.registers.PC = operation!(unwrap arg code).into(),
_ => panic!("Invalid addressing mode for {:?}", code.name),
},
OpcodeType::BEQ if code.addr_mode == AddressingMode::REL => {
if self.registers.test(Flags::Zero) {
self.registers.PC = operation!(unwrap arg code);
self.registers.PC = operation!(unwrap arg code).into();
branch_taken = true;
}
}
OpcodeType::BNE if code.addr_mode == AddressingMode::REL => {
if !self.registers.test(Flags::Zero) {
self.registers.PC = operation!(unwrap arg code);
self.registers.PC = operation!(unwrap arg code).into();
branch_taken = true;
}
}
@ -169,14 +169,14 @@ impl System {
if branch_taken || code.name == OpcodeType::JMP {
println!("Don't increment PC");
} else {
self.registers.PC += get_size(code.addr_mode) as u16;
self.registers.PC = self.registers.PC + get_size(code.addr_mode).into();
}
self.cycles += 1;
Ok(())
}
pub fn restart(&mut self) {
self.cycles = 0;
self.ram = [0x00; 0x10000];
self.ram.load([0x00; 0x10000]);
self.registers = Registers::default();
}
}

View File

@ -71,18 +71,18 @@ impl ThreadedEmulator {
match cmd {
Cmd::Step => {
system.step()?;
let page_02 = Vec::from(&system.ram[0x200..0x300]);
let page_02 = Vec::from(&(*system.ram)[0x200..0x300]);
tdata.send(page_02);
}
Cmd::Reset => {
system.restart();
system.ram = *TEST_CODE;
system.ram.load(*TEST_CODE);
}
Cmd::Run => loop {
if let Err(e) = rcmd.recv_timeout(std::time::Duration::from_millis(1)) {
if e == std::sync::mpsc::RecvTimeoutError::Timeout {
system.step()?;
let page_02 = Vec::from(&system.ram[0x200..0x300]);
let page_02 = Vec::from(&(*system.ram)[0x200..0x300]);
tdata.send(page_02);
} else {
panic!("Controller mpsc disconnected: {}", e)
@ -94,14 +94,14 @@ impl ThreadedEmulator {
Cmd::Get(what) => match what {
GetType::Flags => {}
GetType::Range(start, end) => {
let data = &system.ram[start..end];
let data = &(*system.ram)[start..end];
tdata
.send(Vec::from(data))
.expect("Couldn't send requested value");
}
GetType::Value(addr) => {
tdata
.send(vec![system.ram[addr]])
.send(vec![(*system.ram)[addr]])
.expect("Couldn't send requested value");
}
},