diff --git a/README.md b/README.md index 9272259..7f7303c 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,6 @@ Source: [Wikipedia](https://en.wikipedia.org/wiki/MOS_Technology_6502) ## How to use this library ```rust -use mos6502::address::Address; use mos6502::cpu; fn main() { @@ -52,9 +51,9 @@ fn main() { let mut cpu = cpu::CPU::new(); - cpu.memory.set_bytes(Address(0x00), &zero_page_data); - cpu.memory.set_bytes(Address(0x10), &program); - cpu.registers.program_counter = Address(0x10); + cpu.memory.set_bytes(0x00, &zero_page_data); + cpu.memory.set_bytes(0x10, &program); + cpu.registers.program_counter = 0x10; cpu.run(); diff --git a/examples/euclidean_algo.rs b/examples/euclidean_algo.rs index cf22eef..0177362 100644 --- a/examples/euclidean_algo.rs +++ b/examples/euclidean_algo.rs @@ -1,5 +1,5 @@ extern crate mos6502; -use mos6502::address::Address; + use mos6502::cpu; fn main() { @@ -35,9 +35,9 @@ fn main() { let mut cpu = cpu::CPU::new(); - cpu.memory.set_bytes(Address(0x00), &zero_page_data); - cpu.memory.set_bytes(Address(0x10), &program); - cpu.registers.program_counter = Address(0x10); + cpu.memory.set_bytes(0x00, &zero_page_data); + cpu.memory.set_bytes(0x10, &program); + cpu.registers.program_counter = 0x10; cpu.run(); diff --git a/examples/mos6502.rs b/examples/mos6502.rs index 04c163b..c71080c 100644 --- a/examples/mos6502.rs +++ b/examples/mos6502.rs @@ -30,9 +30,6 @@ extern crate mos6502; #[cfg(not(test))] use mos6502::cpu; -#[cfg(not(test))] -use mos6502::address::Address; - #[cfg(not(test))] fn main() { let mut cpu = cpu::CPU::new(); @@ -94,11 +91,11 @@ fn main() { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, // ADC IndirectIndexedY target ]; - cpu.memory.set_bytes(Address(0x0000), &zero_page_data); - cpu.memory.set_bytes(Address(0x4000), &program); - cpu.memory.set_bytes(Address(0x8000), &data); + cpu.memory.set_bytes(0x0000, &zero_page_data); + cpu.memory.set_bytes(0x4000, &program); + cpu.memory.set_bytes(0x8000, &data); - cpu.registers.program_counter = Address(0x4000); + cpu.registers.program_counter = 0x4000; cpu.run(); diff --git a/src/address.rs b/src/address.rs deleted file mode 100644 index 98a1c19..0000000 --- a/src/address.rs +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright (C) 2014 The 6502-rs Developers -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// 3. Neither the names of the copyright holders nor the names of any -// contributors may be used to endorse or promote products derived from this -// software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -// POSSIBILITY OF SUCH DAMAGE. - -use core::ops::Add; - -// The idea here is that it doesn't make sense to add two addresses, but it -// does make sense to add an address and an "address-difference". (If this -// is too annoying to work with we should let it go.) -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)] -pub struct AddressDiff(pub i32); - -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)] -pub struct Address(pub u16); - -impl Add for Address { - type Output = Address; - - fn add(self, AddressDiff(rhs): AddressDiff) -> Address { - let Address(lhs) = self; - - Address(((i32::from(lhs)) + rhs) as u16) - } -} - -impl Add for AddressDiff { - type Output = AddressDiff; - - fn add(self, AddressDiff(rhs): AddressDiff) -> AddressDiff { - let AddressDiff(lhs) = self; - AddressDiff(lhs + rhs) - } -} - -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] -pub struct CheckedAddressDiff(u16); - -impl Add for Address { - type Output = Address; - - fn add(self, CheckedAddressDiff(rhs): CheckedAddressDiff) -> Address { - let Address(lhs) = self; - - // We probably don't want to overflow when doing arithmetic in our own - // code. - debug_assert!(lhs.checked_add(rhs).is_some()); - - Address(lhs + rhs) - } -} - -impl Address { - pub fn to_u16(self) -> u16 { - self.0 - } - - pub fn to_usize(self) -> usize { - self.to_u16() as usize - } - - pub fn get_page_number(self) -> u8 { - (self.to_u16() & 0xff00 >> 8) as u8 - } - - pub fn get_offset(self) -> u8 { - (self.to_u16() & 0x00ff) as u8 - } -} diff --git a/src/cpu.rs b/src/cpu.rs index e78e698..4c8cf69 100644 --- a/src/cpu.rs +++ b/src/cpu.rs @@ -25,7 +25,6 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. -use crate::address::{Address, AddressDiff}; use crate::instruction::{self, DecodedInstr, Instruction, OpInput}; use crate::memory::Memory; use crate::registers::{Registers, StackPointer, Status, StatusArgs}; @@ -60,15 +59,16 @@ impl CPU { match instruction::OPCODES[x as usize] { Some((instr, am)) => { let extra_bytes = am.extra_bytes(); - let num_bytes = AddressDiff(1) + extra_bytes; + let num_bytes = extra_bytes + 1; - let data_start = self.registers.program_counter + AddressDiff(1); + let data_start = self.registers.program_counter.wrapping_add(1); let slice = self.memory.get_slice(data_start, extra_bytes); let am_out = am.process(self, slice); // Increment program counter - self.registers.program_counter = self.registers.program_counter + num_bytes; + self.registers.program_counter = + self.registers.program_counter.wrapping_add(num_bytes); Some((instr, am_out)) } @@ -110,17 +110,17 @@ impl CPU { } (Instruction::BCC, OpInput::UseRelative(rel)) => { - let addr = self.registers.program_counter + AddressDiff(i32::from(rel)); + let addr = self.registers.program_counter.wrapping_add(rel); self.branch_if_carry_clear(addr); } (Instruction::BCS, OpInput::UseRelative(rel)) => { - let addr = self.registers.program_counter + AddressDiff(i32::from(rel)); + let addr = self.registers.program_counter.wrapping_add(rel); self.branch_if_carry_set(addr); } (Instruction::BEQ, OpInput::UseRelative(rel)) => { - let addr = self.registers.program_counter + AddressDiff(i32::from(rel)); + let addr = self.registers.program_counter.wrapping_add(rel); self.branch_if_equal(addr); } @@ -150,23 +150,23 @@ impl CPU { } (Instruction::BMI, OpInput::UseRelative(rel)) => { - let addr = self.registers.program_counter + AddressDiff(i32::from(rel)); + let addr = self.registers.program_counter.wrapping_add(rel); debug!("branch if minus relative. address: {:?}", addr); self.branch_if_minus(addr); } (Instruction::BPL, OpInput::UseRelative(rel)) => { - let addr = self.registers.program_counter + AddressDiff(i32::from(rel)); + let addr = self.registers.program_counter.wrapping_add(rel); self.branch_if_positive(addr); } (Instruction::BVC, OpInput::UseRelative(rel)) => { - let addr = self.registers.program_counter + AddressDiff(i32::from(rel)); + let addr = self.registers.program_counter.wrapping_add(rel); self.branch_if_overflow_clear(addr); } (Instruction::BVS, OpInput::UseRelative(rel)) => { - let addr = self.registers.program_counter + AddressDiff(i32::from(rel)); + let addr = self.registers.program_counter.wrapping_add(rel); self.branch_if_overflow_set(addr); } @@ -648,7 +648,7 @@ impl CPU { self.load_accumulator(result); } - fn decrement_memory(&mut self, addr: Address) { + fn decrement_memory(&mut self, addr: u16) { let value_new = self.memory.get_byte(addr).wrapping_sub(1); self.memory.set_byte(addr, value_new); @@ -671,47 +671,47 @@ impl CPU { self.load_x_register(val - 1); } - fn jump(&mut self, addr: Address) { + fn jump(&mut self, addr: u16) { self.registers.program_counter = addr; } - fn branch_if_carry_clear(&mut self, addr: Address) { + fn branch_if_carry_clear(&mut self, addr: u16) { if !self.registers.status.contains(Status::PS_CARRY) { self.registers.program_counter = addr; } } - fn branch_if_carry_set(&mut self, addr: Address) { + fn branch_if_carry_set(&mut self, addr: u16) { if self.registers.status.contains(Status::PS_CARRY) { self.registers.program_counter = addr; } } - fn branch_if_equal(&mut self, addr: Address) { + fn branch_if_equal(&mut self, addr: u16) { if self.registers.status.contains(Status::PS_ZERO) { self.registers.program_counter = addr; } } - fn branch_if_minus(&mut self, addr: Address) { + fn branch_if_minus(&mut self, addr: u16) { if self.registers.status.contains(Status::PS_NEGATIVE) { self.registers.program_counter = addr; } } - fn branch_if_positive(&mut self, addr: Address) { + fn branch_if_positive(&mut self, addr: u16) { if !self.registers.status.contains(Status::PS_NEGATIVE) { self.registers.program_counter = addr; } } - fn branch_if_overflow_clear(&mut self, addr: Address) { + fn branch_if_overflow_clear(&mut self, addr: u16) { if !self.registers.status.contains(Status::PS_OVERFLOW) { self.registers.program_counter = addr; } } - fn branch_if_overflow_set(&mut self, addr: Address) { + fn branch_if_overflow_set(&mut self, addr: u16) { if self.registers.status.contains(Status::PS_OVERFLOW) { self.registers.program_counter = addr; } @@ -773,13 +773,13 @@ impl CPU { } fn push_on_stack(&mut self, val: u8) { - let addr = self.registers.stack_pointer.to_address(); + let addr = self.registers.stack_pointer.to_u16(); self.memory.set_byte(addr, val); self.registers.stack_pointer.decrement(); } fn pull_from_stack(&mut self) -> u8 { - let addr = self.registers.stack_pointer.to_address(); + let addr = self.registers.stack_pointer.to_u16(); let out = self.memory.get_byte(addr); self.registers.stack_pointer.increment(); out @@ -1022,7 +1022,7 @@ mod tests { #[test] fn decrement_memory_test() { let mut cpu = CPU::new(); - let addr = Address(0xA1B2); + let addr: u16 = 0xA1B2; cpu.memory.set_byte(addr, 5); @@ -1135,7 +1135,7 @@ mod tests { #[test] fn jump_test() { let mut cpu = CPU::new(); - let addr = Address(0xA1B1); + let addr: u16 = 0xA1B1; cpu.jump(addr); assert_eq!(cpu.registers.program_counter, addr); @@ -1146,12 +1146,12 @@ mod tests { let mut cpu = CPU::new(); cpu.execute_instruction((Instruction::SEC, OpInput::UseImplied)); - cpu.branch_if_carry_clear(Address(0xABCD)); - assert_eq!(cpu.registers.program_counter, Address(0)); + cpu.branch_if_carry_clear(0xABCD); + assert_eq!(cpu.registers.program_counter, (0)); cpu.execute_instruction((Instruction::CLC, OpInput::UseImplied)); - cpu.branch_if_carry_clear(Address(0xABCD)); - assert_eq!(cpu.registers.program_counter, Address(0xABCD)); + cpu.branch_if_carry_clear(0xABCD); + assert_eq!(cpu.registers.program_counter, (0xABCD)); } #[test] @@ -1159,24 +1159,24 @@ mod tests { let mut cpu = CPU::new(); cpu.execute_instruction((Instruction::CLC, OpInput::UseImplied)); - cpu.branch_if_carry_set(Address(0xABCD)); - assert_eq!(cpu.registers.program_counter, Address(0)); + cpu.branch_if_carry_set(0xABCD); + assert_eq!(cpu.registers.program_counter, (0)); cpu.execute_instruction((Instruction::SEC, OpInput::UseImplied)); - cpu.branch_if_carry_set(Address(0xABCD)); - assert_eq!(cpu.registers.program_counter, Address(0xABCD)); + cpu.branch_if_carry_set(0xABCD); + assert_eq!(cpu.registers.program_counter, (0xABCD)); } #[test] fn branch_if_equal_test() { let mut cpu = CPU::new(); - cpu.branch_if_equal(Address(0xABCD)); - assert_eq!(cpu.registers.program_counter, Address(0)); + cpu.branch_if_equal(0xABCD); + assert_eq!(cpu.registers.program_counter, (0)); cpu.registers.status.or(Status::PS_ZERO); - cpu.branch_if_equal(Address(0xABCD)); - assert_eq!(cpu.registers.program_counter, Address(0xABCD)); + cpu.branch_if_equal(0xABCD); + assert_eq!(cpu.registers.program_counter, (0xABCD)); } #[test] @@ -1185,9 +1185,9 @@ mod tests { let mut cpu = CPU::new(); let registers_before = cpu.registers; - cpu.branch_if_minus(Address(0xABCD)); + cpu.branch_if_minus(0xABCD); assert_eq!(cpu.registers, registers_before); - assert_eq!(cpu.registers.program_counter, Address(0)); + assert_eq!(cpu.registers.program_counter, (0)); } { @@ -1196,9 +1196,9 @@ mod tests { cpu.registers.status.or(Status::PS_NEGATIVE); let registers_before = cpu.registers; - cpu.branch_if_minus(Address(0xABCD)); + cpu.branch_if_minus(0xABCD); assert_eq!(cpu.registers.status, registers_before.status); - assert_eq!(cpu.registers.program_counter, Address(0xABCD)); + assert_eq!(cpu.registers.program_counter, (0xABCD)); } } @@ -1207,12 +1207,12 @@ mod tests { let mut cpu = CPU::new(); cpu.registers.status.insert(Status::PS_NEGATIVE); - cpu.branch_if_positive(Address(0xABCD)); - assert_eq!(cpu.registers.program_counter, Address(0)); + cpu.branch_if_positive(0xABCD); + assert_eq!(cpu.registers.program_counter, (0)); cpu.registers.status.remove(Status::PS_NEGATIVE); - cpu.branch_if_positive(Address(0xABCD)); - assert_eq!(cpu.registers.program_counter, Address(0xABCD)); + cpu.branch_if_positive(0xABCD); + assert_eq!(cpu.registers.program_counter, (0xABCD)); } #[test] @@ -1220,24 +1220,34 @@ mod tests { let mut cpu = CPU::new(); cpu.registers.status.insert(Status::PS_OVERFLOW); - cpu.branch_if_overflow_clear(Address(0xABCD)); - assert_eq!(cpu.registers.program_counter, Address(0)); + cpu.branch_if_overflow_clear(0xABCD); + assert_eq!(cpu.registers.program_counter, (0)); cpu.registers.status.remove(Status::PS_OVERFLOW); - cpu.branch_if_overflow_clear(Address(0xABCD)); - assert_eq!(cpu.registers.program_counter, Address(0xABCD)); + cpu.branch_if_overflow_clear(0xABCD); + assert_eq!(cpu.registers.program_counter, (0xABCD)); + } + + #[test] + fn branch_across_end_of_address_space() { + let mut cpu = CPU::new(); + cpu.registers.program_counter = 0xffff; + + cpu.registers.status.insert(Status::PS_OVERFLOW); + cpu.branch_if_overflow_set(0xABCD); + assert_eq!(cpu.registers.program_counter, (0xABCD)); } #[test] fn branch_if_overflow_set_test() { let mut cpu = CPU::new(); - cpu.branch_if_overflow_set(Address(0xABCD)); - assert_eq!(cpu.registers.program_counter, Address(0)); + cpu.branch_if_overflow_set(0xABCD); + assert_eq!(cpu.registers.program_counter, (0)); cpu.registers.status.insert(Status::PS_OVERFLOW); - cpu.branch_if_overflow_set(Address(0xABCD)); - assert_eq!(cpu.registers.program_counter, Address(0xABCD)); + cpu.branch_if_overflow_set(0xABCD); + assert_eq!(cpu.registers.program_counter, (0xABCD)); } #[cfg(test)] diff --git a/src/instruction.rs b/src/instruction.rs index 10c4b78..2b27985 100644 --- a/src/instruction.rs +++ b/src/instruction.rs @@ -25,8 +25,6 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. -use crate::address::Address; -use crate::address::AddressDiff; use crate::cpu::CPU; // Abbreviations @@ -113,8 +111,8 @@ pub enum Instruction { pub enum OpInput { UseImplied, UseImmediate(u8), - UseRelative(i8), - UseAddress(Address), + UseRelative(u16), + UseAddress(u16), } #[derive(Copy, Clone)] @@ -136,16 +134,19 @@ pub enum AddressingMode { // zero page address) plus Y register } -fn arr_to_addr(arr: &[u8]) -> Address { +fn xextend(x: u8) -> u16 { + u16::from(x) +} + +fn arr_to_addr(arr: &[u8]) -> u16 { debug_assert!(arr.len() == 2); - let x = u16::from(arr[0]) + (u16::from(arr[1]) << 8usize); - Address(x) + u16::from(arr[0]) + (u16::from(arr[1]) << 8usize) } impl AddressingMode { - pub fn extra_bytes(self) -> AddressDiff { - let x = match self { + pub fn extra_bytes(self) -> u16 { + match self { AddressingMode::Accumulator => 0, AddressingMode::Implied => 0, AddressingMode::Immediate => 1, @@ -159,15 +160,11 @@ impl AddressingMode { AddressingMode::Indirect => 2, AddressingMode::IndexedIndirectX => 1, AddressingMode::IndirectIndexedY => 1, - }; - AddressDiff(x) + } } pub fn process(self, cpu: &CPU, arr: &[u8]) -> OpInput { - debug_assert!({ - let AddressDiff(x) = self.extra_bytes(); - arr.len() == x as usize - }); + debug_assert!(arr.len() == self.extra_bytes() as usize); let x = cpu.registers.index_x as u8; let y = cpu.registers.index_y as u8; @@ -187,24 +184,29 @@ impl AddressingMode { // Use [u8, ..1] from instruction // Interpret as zero page address // (Output: an 8-bit zero-page address) - OpInput::UseAddress(Address(u16::from(arr[0]))) + OpInput::UseAddress(u16::from(arr[0])) } AddressingMode::ZeroPageX => { // Use [u8, ..1] from instruction // Add to X register (as u8 -- the final address is in 0-page) // (Output: an 8-bit zero-page address) - OpInput::UseAddress(Address(u16::from(arr[0] + x))) + OpInput::UseAddress(u16::from(arr[0].wrapping_add(x))) } AddressingMode::ZeroPageY => { // Use [u8, ..1] from instruction // Add to Y register (as u8 -- the final address is in 0-page) // (Output: an 8-bit zero-page address) - OpInput::UseAddress(Address(u16::from(arr[0] + y))) + OpInput::UseAddress(u16::from(arr[0].wrapping_add(y))) } AddressingMode::Relative => { // Use [u8, ..1] from instruction // (interpret as relative...) - OpInput::UseRelative(arr[0] as i8) + // (This is sign extended to a 16-but data type, but an unsigned one: u16. It's a + // little weird, but it's so we can add the PC and the offset easily) + let offset = arr[0]; + let sign_extend = if offset & 0x80 == 0x80 { 0xffu8 } else { 0x0 }; + let rel = u16::from_le_bytes([offset, sign_extend]); + OpInput::UseRelative(rel) } AddressingMode::Absolute => { // Use [u8, ..2] from instruction as address @@ -214,18 +216,18 @@ impl AddressingMode { AddressingMode::AbsoluteX => { // Use [u8, ..2] from instruction as address, add X // (Output: a 16-bit address) - OpInput::UseAddress(arr_to_addr(arr) + AddressDiff(i32::from(x))) + OpInput::UseAddress(arr_to_addr(arr).wrapping_add(xextend(x))) } AddressingMode::AbsoluteY => { // Use [u8, ..2] from instruction as address, add Y // (Output: a 16-bit address) - OpInput::UseAddress(arr_to_addr(arr) + AddressDiff(i32::from(y))) + OpInput::UseAddress(arr_to_addr(arr).wrapping_add(xextend(y))) } AddressingMode::Indirect => { // Use [u8, ..2] from instruction as an address. Interpret the // two bytes starting at that address as an address. // (Output: a 16-bit address) - let slice = memory.get_slice(arr_to_addr(arr), AddressDiff(2)); + let slice = memory.get_slice(arr_to_addr(arr), 2); OpInput::UseAddress(arr_to_addr(slice)) } AddressingMode::IndexedIndirectX => { @@ -233,8 +235,8 @@ impl AddressingMode { // Add to X register with 0-page wraparound, like ZeroPageX. // This is where the absolute (16-bit) target address is stored. // (Output: a 16-bit address) - let start = arr[0] + x; - let slice = memory.get_slice(Address(u16::from(start)), AddressDiff(2)); + let start = arr[0].wrapping_add(x); + let slice = memory.get_slice(u16::from(start), 2); OpInput::UseAddress(arr_to_addr(slice)) } AddressingMode::IndirectIndexedY => { @@ -243,8 +245,8 @@ impl AddressingMode { // Add Y register to this address to get the final address // (Output: a 16-bit address) let start = arr[0]; - let slice = memory.get_slice(Address(u16::from(start)), AddressDiff(2)); - OpInput::UseAddress(arr_to_addr(slice) + AddressDiff(i32::from(y))) + let slice = memory.get_slice(u16::from(start), 2); + OpInput::UseAddress(arr_to_addr(slice).wrapping_add(xextend(y))) } } } @@ -766,3 +768,26 @@ pub static OPCODES: [Option<(Instruction, AddressingMode)>; 256] = [ /*0xFF*/ None, ]; + +#[cfg(test)] +mod tests { + + #[test] + fn zeropage_wrap_around() { + use crate::instruction::AddressingMode; + use crate::instruction::OpInput; + use crate::instruction::CPU; + + let mut cpu = CPU::new(); + cpu.registers.index_x = 9; + + assert!(matches!( + AddressingMode::ZeroPageX.process(&cpu, &[10]), + OpInput::UseAddress(19) + )); + assert!(matches!( + AddressingMode::ZeroPageX.process(&cpu, &[250]), + OpInput::UseAddress(3) + )); + } +} diff --git a/src/lib.rs b/src/lib.rs index 9e12bbb..8065990 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -35,7 +35,6 @@ extern crate num; #[macro_use] extern crate bitflags; -pub mod address; pub mod cpu; pub mod instruction; pub mod memory; diff --git a/src/memory.rs b/src/memory.rs index 64a994e..9b7bc42 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -25,8 +25,6 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. -use crate::address::{Address, AddressDiff}; - // JAM: We can probably come up with a better way to represent address ranges. // Address range type? // @@ -39,12 +37,12 @@ use crate::address::{Address, AddressDiff}; const ADDR_LO_BARE: u16 = 0x0000; const ADDR_HI_BARE: u16 = 0xFFFF; -pub const MEMORY_ADDRESS_LO: Address = Address(ADDR_LO_BARE); -pub const MEMORY_ADDRESS_HI: Address = Address(ADDR_HI_BARE); -pub const STACK_ADDRESS_LO: Address = Address(0x0100); -pub const STACK_ADDRESS_HI: Address = Address(0x01FF); -pub const IRQ_INTERRUPT_VECTOR_LO: Address = Address(0xFFFE); -pub const IRQ_INTERRUPT_VECTOR_HI: Address = Address(0xFFFF); +pub const MEMORY_ADDRESS_LO: u16 = ADDR_LO_BARE; +pub const MEMORY_ADDRESS_HI: u16 = ADDR_HI_BARE; +pub const STACK_ADDRESS_LO: u16 = 0x0100; +pub const STACK_ADDRESS_HI: u16 = 0x01FF; +pub const IRQ_INTERRUPT_VECTOR_LO: u16 = 0xFFFE; +pub const IRQ_INTERRUPT_VECTOR_HI: u16 = 0xFFFF; const MEMORY_SIZE: usize = (ADDR_HI_BARE - ADDR_LO_BARE) as usize + 1usize; @@ -67,28 +65,31 @@ impl Memory { } } - pub fn get_byte(&self, address: Address) -> u8 { - self.bytes[address.to_usize()] + pub fn get_byte(&self, address: u16) -> u8 { + self.bytes[address as usize] } - pub fn get_byte_mut_ref(&mut self, address: Address) -> &mut u8 { - &mut self.bytes[address.to_usize()] + pub fn get_byte_mut_ref(&mut self, address: u16) -> &mut u8 { + &mut self.bytes[address as usize] } - pub fn get_slice(&self, start: Address, diff: AddressDiff) -> &[u8] { - &self.bytes[start.to_usize()..(start + diff).to_usize()] + pub fn get_slice(&self, start: u16, diff: u16) -> &[u8] { + let orig: usize = start.into(); + let end = orig + diff as usize; + + &self.bytes[orig..end] } // Sets the byte at the given address to the given value and returns the // previous value at the address. - pub fn set_byte(&mut self, address: Address, value: u8) -> u8 { + pub fn set_byte(&mut self, address: u16, value: u8) -> u8 { let old_value = self.get_byte(address); - self.bytes[address.to_usize()] = value; + self.bytes[address as usize] = value; old_value } - pub fn set_bytes(&mut self, start: Address, values: &[u8]) { - let start = start.to_usize(); + pub fn set_bytes(&mut self, start: u16, values: &[u8]) { + let start = start as usize; // This panics if the range is invalid let end = start + values.len(); @@ -96,8 +97,8 @@ impl Memory { self.bytes[start..end].copy_from_slice(values); } - pub fn is_stack_address(address: Address) -> bool { - (STACK_ADDRESS_LO..=STACK_ADDRESS_HI).contains(&address) + pub fn is_stack_address(address: u16) -> bool { + address > 0xff && address < 0x200 } } @@ -108,17 +109,14 @@ mod tests { #[test] fn test_memory_set_bytes() { let mut memory = Memory::new(); - memory.set_bytes(Address(0x0100), &[1, 2, 3, 4, 5]); - assert_eq!( - memory.get_slice(Address(0x00FF), AddressDiff(7)), - &[0, 1, 2, 3, 4, 5, 0] - ); + memory.set_bytes(0x0100, &[1, 2, 3, 4, 5]); + assert_eq!(memory.get_slice(0x00FF, 7), &[0, 1, 2, 3, 4, 5, 0]); } #[test] #[should_panic] fn test_memory_overflow_panic() { let mut memory = Memory::new(); - memory.set_bytes(Address(0xFFFE), &[1, 2, 3]); + memory.set_bytes(0xFFFE, &[1, 2, 3]); } } diff --git a/src/registers.rs b/src/registers.rs index c861d41..a179ab8 100644 --- a/src/registers.rs +++ b/src/registers.rs @@ -25,9 +25,6 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. -use crate::address::{Address, AddressDiff}; -use crate::memory::{STACK_ADDRESS_HI, STACK_ADDRESS_LO}; - // Useful for constructing Status instances #[derive(Copy, Clone)] pub struct StatusArgs { @@ -147,8 +144,9 @@ impl Status { pub struct StackPointer(pub u8); impl StackPointer { - pub fn to_address(self) -> Address { - STACK_ADDRESS_LO + AddressDiff(i32::from(self.0)) + pub fn to_u16(self) -> u16 { + let StackPointer(val) = self; + u16::from_le_bytes([val, 0x01]) } pub fn decrement(&mut self) { @@ -166,7 +164,7 @@ pub struct Registers { pub index_x: i8, pub index_y: i8, pub stack_pointer: StackPointer, - pub program_counter: Address, + pub program_counter: u16, pub status: Status, } @@ -183,8 +181,8 @@ impl Registers { accumulator: 0, index_x: 0, index_y: 0, - stack_pointer: StackPointer(STACK_ADDRESS_HI.get_offset()), - program_counter: Address(0), + stack_pointer: StackPointer(0), + program_counter: 0, status: Status::default(), } }