Tested and fixed all instructions
! something might still be bugged since the test program is failing, although not in an obvious manner
This commit is contained in:
parent
051cfe6611
commit
1b9c73c432
5
.gitignore
vendored
5
.gitignore
vendored
@ -1,3 +1,6 @@
|
|||||||
/target
|
/target
|
||||||
.log
|
*.log
|
||||||
|
*.bin
|
||||||
|
*.bin.*
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
36
src/bus.rs
36
src/bus.rs
@ -112,3 +112,39 @@ impl Bus {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// special Bus only used for testing the emulator
|
||||||
|
pub struct FileBus {
|
||||||
|
mem: Ram<0x10000>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for FileBus {
|
||||||
|
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
f.debug_struct("Bus")
|
||||||
|
.field("mem", &self.mem)
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Memory for FileBus {
|
||||||
|
|
||||||
|
fn read_addr(&self, addr: u16) -> u8 {
|
||||||
|
self.mem.read_addr(addr) //RAM is mirrored 3 times
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_addr(&mut self, addr: u16, data: u8) {
|
||||||
|
self.mem.write_addr(addr % 0x0800, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FileBus {
|
||||||
|
|
||||||
|
pub fn new() -> Self {
|
||||||
|
FileBus {
|
||||||
|
mem: Ram::from_file("6502_functional_test.bin"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
107
src/cpu.rs
107
src/cpu.rs
@ -4,7 +4,7 @@ use log::{debug, error, info, trace, warn};
|
|||||||
use bitflags::bitflags;
|
use bitflags::bitflags;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
bus::Bus,
|
bus::FileBus,
|
||||||
memory::Memory,
|
memory::Memory,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -17,11 +17,11 @@ trait Input {
|
|||||||
}
|
}
|
||||||
|
|
||||||
trait RInput: Input {
|
trait RInput: Input {
|
||||||
fn read(&self, acc: &u8, bus: &Bus) -> u8;
|
fn read<M: Memory>(&self, acc: &u8, bus: &M) -> u8;
|
||||||
}
|
}
|
||||||
|
|
||||||
trait WInput: Input {
|
trait WInput: Input {
|
||||||
fn write(&mut self, acc: &mut u8, bus: &mut Bus, data: u8);
|
fn write<M: Memory>(&mut self, acc: &mut u8, bus: &mut M, data: u8);
|
||||||
}
|
}
|
||||||
|
|
||||||
trait RWInput: RInput + WInput {}
|
trait RWInput: RInput + WInput {}
|
||||||
@ -33,11 +33,11 @@ impl Input for Accumulator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl RInput for Accumulator {
|
impl RInput for Accumulator {
|
||||||
fn read(&self, acc: &u8, _bus: &Bus) -> u8 { *acc }
|
fn read<M: Memory>(&self, acc: &u8, _bus: &M) -> u8 { *acc }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WInput for Accumulator {
|
impl WInput for Accumulator {
|
||||||
fn write(&mut self, acc: &mut u8, _bus: &mut Bus, data: u8) { *acc = data }
|
fn write<M: Memory>(&mut self, acc: &mut u8, _bus: &mut M, data: u8) { *acc = data }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RWInput for Accumulator {}
|
impl RWInput for Accumulator {}
|
||||||
@ -51,7 +51,7 @@ impl Input for Data {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl RInput for Data {
|
impl RInput for Data {
|
||||||
fn read(&self, _acc: &u8, _bus: &Bus) -> u8 { self.data }
|
fn read<M: Memory>(&self, _acc: &u8, _bus: &M) -> u8 { self.data }
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MemoryVal {
|
struct MemoryVal {
|
||||||
@ -64,13 +64,13 @@ impl Input for MemoryVal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl RInput for MemoryVal {
|
impl RInput for MemoryVal {
|
||||||
fn read(&self, _acc: &u8, bus: &Bus) -> u8 {
|
fn read<M: Memory>(&self, _acc: &u8, bus: &M) -> u8 {
|
||||||
bus.read_addr(self.addr)
|
bus.read_addr(self.addr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WInput for MemoryVal {
|
impl WInput for MemoryVal {
|
||||||
fn write(&mut self, _acc: &mut u8, bus: &mut Bus, data: u8) {
|
fn write<M: Memory>(&mut self, _acc: &mut u8, bus: &mut M, data: u8) {
|
||||||
bus.write_addr(self.addr, data);
|
bus.write_addr(self.addr, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -93,13 +93,13 @@ impl Input for MemoryValExtra {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl RInput for MemoryValExtra {
|
impl RInput for MemoryValExtra {
|
||||||
fn read(&self, _acc: &u8, bus: &Bus) -> u8 {
|
fn read<M: Memory>(&self, _acc: &u8, bus: &M) -> u8 {
|
||||||
bus.read_addr(self.addr)
|
bus.read_addr(self.addr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WInput for MemoryValExtra {
|
impl WInput for MemoryValExtra {
|
||||||
fn write(&mut self, _acc: &mut u8, bus: &mut Bus, data: u8) {
|
fn write<M: Memory>(&mut self, _acc: &mut u8, bus: &mut M, data: u8) {
|
||||||
bus.write_addr(self.addr, data);
|
bus.write_addr(self.addr, data);
|
||||||
|
|
||||||
self.extra_cycle = true;
|
self.extra_cycle = true;
|
||||||
@ -145,7 +145,7 @@ pub struct Cpu {
|
|||||||
pc: u16,
|
pc: u16,
|
||||||
s: u8,
|
s: u8,
|
||||||
p: StatusReg,
|
p: StatusReg,
|
||||||
bus: Bus,
|
bus: FileBus,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for Cpu {
|
impl fmt::Debug for Cpu {
|
||||||
@ -167,14 +167,20 @@ impl fmt::Debug for Cpu {
|
|||||||
impl Cpu {
|
impl Cpu {
|
||||||
|
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
|
|
||||||
|
// read initial PC value from reset vector
|
||||||
|
let bus = FileBus::new();
|
||||||
|
let pc_lo = bus.read_addr(0xFFFC) as u16;
|
||||||
|
let pc_hi = bus.read_addr(0xFFFD) as u16;
|
||||||
|
|
||||||
Cpu {
|
Cpu {
|
||||||
a: 1,
|
a: 0,
|
||||||
x: 1, //TODO temporary
|
x: 0,
|
||||||
y: 2, //TODO temporary
|
y: 0,
|
||||||
pc: 0, //TODO to be verified
|
pc: (pc_lo | (pc_hi << 8)) + 3,
|
||||||
s: 0xFD,
|
s: 0xFD,
|
||||||
p: StatusReg::from_bits(0x35).unwrap(),
|
p: StatusReg::from_bits(0x34).unwrap(),
|
||||||
bus: Bus::new(),
|
bus,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,8 +190,15 @@ impl Cpu {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn execute(&mut self) {
|
fn execute(&mut self) {
|
||||||
|
|
||||||
let opcode = self.read_pc_addr();
|
let opcode = self.read_pc_addr();
|
||||||
|
// if self.pc-1 > 0x36D0 && self.pc-1 < 0x36D8 {
|
||||||
|
// println!("{:#?}", self);
|
||||||
|
// }
|
||||||
|
// if (self.pc-1) != 0x36D8 {
|
||||||
|
// println!("0x{:0>4X}: {:0>2X}", self.pc-1, opcode);
|
||||||
|
// }
|
||||||
|
|
||||||
let cycles = parse_opcode!(self, opcode,
|
let cycles = parse_opcode!(self, opcode,
|
||||||
0x69 => adc(mode_immediate),
|
0x69 => adc(mode_immediate),
|
||||||
0x65 => adc(mode_zero_page),
|
0x65 => adc(mode_zero_page),
|
||||||
@ -296,9 +309,9 @@ impl Cpu {
|
|||||||
|
|
||||||
0xA0 => ldy(mode_immediate),
|
0xA0 => ldy(mode_immediate),
|
||||||
0xA4 => ldy(mode_zero_page),
|
0xA4 => ldy(mode_zero_page),
|
||||||
0xB4 => ldy(mode_zero_page_y),
|
0xB4 => ldy(mode_zero_page_x),
|
||||||
0xAC => ldy(mode_absolute),
|
0xAC => ldy(mode_absolute),
|
||||||
0xBC => ldy(mode_absolute_y),
|
0xBC => ldy(mode_absolute_x),
|
||||||
|
|
||||||
0x4A => lsr(mode_accumulator),
|
0x4A => lsr(mode_accumulator),
|
||||||
0x46 => lsr(mode_zero_page),
|
0x46 => lsr(mode_zero_page),
|
||||||
@ -372,10 +385,7 @@ impl Cpu {
|
|||||||
0x8A => txa(mode_implicit),
|
0x8A => txa(mode_implicit),
|
||||||
0x9A => txs(mode_implicit),
|
0x9A => txs(mode_implicit),
|
||||||
0x98 => tya(mode_implicit),
|
0x98 => tya(mode_implicit),
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
info!("0x{:X}: {} cycles", opcode, cycles);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Implicit mode
|
/// Implicit mode
|
||||||
@ -411,7 +421,7 @@ impl Cpu {
|
|||||||
/// val = PEEK((arg + X) & 0xFF)
|
/// val = PEEK((arg + X) & 0xFF)
|
||||||
fn mode_zero_page_x(&mut self) -> MemoryVal {
|
fn mode_zero_page_x(&mut self) -> MemoryVal {
|
||||||
MemoryVal {
|
MemoryVal {
|
||||||
addr: (self.read_pc_addr() + self.x) as u16 & 0x00FF,
|
addr: (self.read_pc_addr().wrapping_add(self.x)) as u16 & 0x00FF,
|
||||||
cycles: 4,
|
cycles: 4,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -421,7 +431,7 @@ impl Cpu {
|
|||||||
/// val = PEEK((arg + Y) & 0xFF)
|
/// val = PEEK((arg + Y) & 0xFF)
|
||||||
fn mode_zero_page_y(&mut self) -> MemoryVal {
|
fn mode_zero_page_y(&mut self) -> MemoryVal {
|
||||||
MemoryVal {
|
MemoryVal {
|
||||||
addr: (self.read_pc_addr() + self.y) as u16 & 0x00FF,
|
addr: (self.read_pc_addr().wrapping_add(self.y)) as u16 & 0x00FF,
|
||||||
cycles: 4,
|
cycles: 4,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -558,8 +568,8 @@ impl Cpu {
|
|||||||
/// Increment PC, then read corresponding value in memory
|
/// Increment PC, then read corresponding value in memory
|
||||||
fn read_pc_addr(&mut self) -> u8 {
|
fn read_pc_addr(&mut self) -> u8 {
|
||||||
|
|
||||||
self.pc += 1;
|
|
||||||
let val = self.bus.read_addr(self.pc);
|
let val = self.bus.read_addr(self.pc);
|
||||||
|
self.pc += 1;
|
||||||
|
|
||||||
val
|
val
|
||||||
}
|
}
|
||||||
@ -692,11 +702,12 @@ impl Cpu {
|
|||||||
fn brk(&mut self, _: ()) -> u32 {
|
fn brk(&mut self, _: ()) -> u32 {
|
||||||
|
|
||||||
// store PC on stack
|
// store PC on stack
|
||||||
self.push_stack((self.pc >> 8) as u8);
|
let pc = self.pc.wrapping_add(1);
|
||||||
self.push_stack(self.pc as u8);
|
self.push_stack((pc >> 8) as u8);
|
||||||
|
self.push_stack(pc as u8);
|
||||||
|
|
||||||
// store status register
|
// store status register
|
||||||
self.p.set(StatusReg::B, true);
|
self.p.set(StatusReg::B | StatusReg::U, true);
|
||||||
self.push_stack(self.p.bits() as u8);
|
self.push_stack(self.p.bits() as u8);
|
||||||
|
|
||||||
// load interrupt vector
|
// load interrupt vector
|
||||||
@ -743,7 +754,7 @@ impl Cpu {
|
|||||||
|
|
||||||
self.p.set(StatusReg::C, reg >= val);
|
self.p.set(StatusReg::C, reg >= val);
|
||||||
self.p.set(StatusReg::Z, reg == val);
|
self.p.set(StatusReg::Z, reg == val);
|
||||||
self.p.set(StatusReg::N, ((reg - val) & (0x1 << 7)) != 0);
|
self.p.set(StatusReg::N, ((reg.wrapping_sub(val)) & (0x1 << 7)) != 0);
|
||||||
|
|
||||||
input.get_cycles()
|
input.get_cycles()
|
||||||
}
|
}
|
||||||
@ -798,8 +809,8 @@ impl Cpu {
|
|||||||
|
|
||||||
// compute
|
// compute
|
||||||
self.a = (!self.a & val) | (self.a & !val);
|
self.a = (!self.a & val) | (self.a & !val);
|
||||||
self.p.set(StatusReg::Z, self.y == 0);
|
self.p.set(StatusReg::Z, self.a == 0);
|
||||||
self.p.set(StatusReg::N, (self.y & (0x1 << 7)) != 0);
|
self.p.set(StatusReg::N, (self.a & (0x1 << 7)) != 0);
|
||||||
|
|
||||||
input.get_cycles()
|
input.get_cycles()
|
||||||
}
|
}
|
||||||
@ -809,8 +820,8 @@ impl Cpu {
|
|||||||
|
|
||||||
// compute
|
// compute
|
||||||
val = val.wrapping_add(1);
|
val = val.wrapping_add(1);
|
||||||
self.p.set(StatusReg::Z, self.y == 0);
|
self.p.set(StatusReg::Z, val == 0);
|
||||||
self.p.set(StatusReg::N, (self.y & (0x1 << 7)) != 0);
|
self.p.set(StatusReg::N, (val & (0x1 << 7)) != 0);
|
||||||
|
|
||||||
// store result
|
// store result
|
||||||
input.write(&mut self.a, &mut self.bus, val);
|
input.write(&mut self.a, &mut self.bus, val);
|
||||||
@ -821,8 +832,8 @@ impl Cpu {
|
|||||||
|
|
||||||
// compute
|
// compute
|
||||||
self.x = self.x.wrapping_add(1);
|
self.x = self.x.wrapping_add(1);
|
||||||
self.p.set(StatusReg::Z, self.y == 0);
|
self.p.set(StatusReg::Z, self.x == 0);
|
||||||
self.p.set(StatusReg::N, (self.y & (0x1 << 7)) != 0);
|
self.p.set(StatusReg::N, (self.x & (0x1 << 7)) != 0);
|
||||||
|
|
||||||
2
|
2
|
||||||
}
|
}
|
||||||
@ -845,8 +856,9 @@ impl Cpu {
|
|||||||
fn jsr(&mut self, input: MemoryVal) -> u32 {
|
fn jsr(&mut self, input: MemoryVal) -> u32 {
|
||||||
|
|
||||||
// store return point
|
// store return point
|
||||||
self.push_stack((self.pc >> 8) as u8);
|
let pc = self.pc.wrapping_sub(1);
|
||||||
self.push_stack(self.pc as u8);
|
self.push_stack((pc >> 8) as u8);
|
||||||
|
self.push_stack(pc as u8);
|
||||||
|
|
||||||
// load target address
|
// load target address
|
||||||
self.pc = input.addr;
|
self.pc = input.addr;
|
||||||
@ -924,12 +936,18 @@ impl Cpu {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn php(&mut self, _: ()) -> u32 {
|
fn php(&mut self, _: ()) -> u32 {
|
||||||
self.push_stack(self.p.bits() as u8);
|
let mut p = self.p;
|
||||||
|
p.set(StatusReg::B | StatusReg::U, true);
|
||||||
|
self.push_stack(p.bits() as u8);
|
||||||
3
|
3
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pla(&mut self, _: ()) -> u32 {
|
fn pla(&mut self, _: ()) -> u32 {
|
||||||
|
|
||||||
self.a = self.pop_stack();
|
self.a = self.pop_stack();
|
||||||
|
self.p.set(StatusReg::Z, self.a == 0);
|
||||||
|
self.p.set(StatusReg::N, (self.a & (0x1 << 7)) != 0);
|
||||||
|
|
||||||
4
|
4
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -952,6 +970,10 @@ impl Cpu {
|
|||||||
}
|
}
|
||||||
self.p.set(StatusReg::C, carry);
|
self.p.set(StatusReg::C, carry);
|
||||||
|
|
||||||
|
// update status bits
|
||||||
|
self.p.set(StatusReg::Z, val == 0);
|
||||||
|
self.p.set(StatusReg::N, (val & (0x1 << 7)) != 0);
|
||||||
|
|
||||||
// store value
|
// store value
|
||||||
input.write(&mut self.a, &mut self.bus, val);
|
input.write(&mut self.a, &mut self.bus, val);
|
||||||
input.get_cycles() + 2
|
input.get_cycles() + 2
|
||||||
@ -970,6 +992,10 @@ impl Cpu {
|
|||||||
}
|
}
|
||||||
self.p.set(StatusReg::C, carry);
|
self.p.set(StatusReg::C, carry);
|
||||||
|
|
||||||
|
// update status bits
|
||||||
|
self.p.set(StatusReg::Z, val == 0);
|
||||||
|
self.p.set(StatusReg::N, (val & (0x1 << 7)) != 0);
|
||||||
|
|
||||||
// store value
|
// store value
|
||||||
input.write(&mut self.a, &mut self.bus, val);
|
input.write(&mut self.a, &mut self.bus, val);
|
||||||
input.get_cycles() + 2
|
input.get_cycles() + 2
|
||||||
@ -979,7 +1005,7 @@ impl Cpu {
|
|||||||
|
|
||||||
// load status register (B is cleared and I overrided)
|
// load status register (B is cleared and I overrided)
|
||||||
self.p = StatusReg::from_bits_truncate(self.pop_stack());
|
self.p = StatusReg::from_bits_truncate(self.pop_stack());
|
||||||
self.p.set(StatusReg::B, false);
|
self.p.set(StatusReg::B | StatusReg::U, false);
|
||||||
|
|
||||||
// load pc
|
// load pc
|
||||||
let pc_lo = self.pop_stack() as u16;
|
let pc_lo = self.pop_stack() as u16;
|
||||||
@ -995,6 +1021,7 @@ impl Cpu {
|
|||||||
let pc_lo = self.pop_stack() as u16;
|
let pc_lo = self.pop_stack() as u16;
|
||||||
let pc_hi = self.pop_stack() as u16;
|
let pc_hi = self.pop_stack() as u16;
|
||||||
self.pc = pc_lo | (pc_hi << 8);
|
self.pc = pc_lo | (pc_hi << 8);
|
||||||
|
self.pc = self.pc.wrapping_add(1);
|
||||||
|
|
||||||
6
|
6
|
||||||
}
|
}
|
||||||
|
|||||||
42
src/main.rs
42
src/main.rs
@ -39,13 +39,15 @@ fn main() -> Result<(), &'static str> {
|
|||||||
|
|
||||||
let vec: Vec<[u8; 4]> = (&buffer).into();
|
let vec: Vec<[u8; 4]> = (&buffer).into();
|
||||||
fb.update_buffer(&vec);
|
fb.update_buffer(&vec);
|
||||||
|
let mut update = false;
|
||||||
|
let mut refresh = true;
|
||||||
|
let mut frame_counter = 0;
|
||||||
|
|
||||||
// event loop
|
// event loop
|
||||||
fb.glutin_handle_basic_input(&mut event_loop, |fb, input| {
|
fb.glutin_handle_basic_input(&mut event_loop, |fb, input| {
|
||||||
use winit::event::VirtualKeyCode;
|
use winit::event::VirtualKeyCode;
|
||||||
|
|
||||||
// wait for input before updating
|
// wait for input before updating
|
||||||
input.wait = true;
|
|
||||||
|
|
||||||
// close if escape is pressed
|
// close if escape is pressed
|
||||||
if input.key_pressed(VirtualKeyCode::Escape) {
|
if input.key_pressed(VirtualKeyCode::Escape) {
|
||||||
@ -55,16 +57,44 @@ fn main() -> Result<(), &'static str> {
|
|||||||
// execute next cpu instruction (step mode)
|
// execute next cpu instruction (step mode)
|
||||||
if input.key_pressed(VirtualKeyCode::S) {
|
if input.key_pressed(VirtualKeyCode::S) {
|
||||||
cpu.tick();
|
cpu.tick();
|
||||||
|
refresh = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if input.key_pressed(VirtualKeyCode::R) {
|
||||||
|
update = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if input.key_pressed(VirtualKeyCode::C) {
|
||||||
|
update = false;
|
||||||
|
refresh = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if update {
|
||||||
|
cpu.tick();
|
||||||
|
|
||||||
|
frame_counter += 1;
|
||||||
|
if frame_counter > 1000 {
|
||||||
|
frame_counter = 0;
|
||||||
|
refresh = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.wait = false;
|
||||||
|
} else {
|
||||||
|
input.wait = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if refresh {
|
||||||
|
refresh = false;
|
||||||
|
|
||||||
let mut debug_str = String::new();
|
let mut debug_str = String::new();
|
||||||
write!(debug_str, "{:#?}", cpu).unwrap();
|
write!(debug_str, "{:#?}", cpu).unwrap();
|
||||||
buffer.fill([20, 20], [760, 560], Pixel::rgba(255, 255, 255, 255));
|
buffer.fill([20, 20], [760, 560], Pixel::rgba(255, 255, 255, 255));
|
||||||
renderer.draw(&mut buffer, &debug_str, [20, 20], [760, 560]);
|
renderer.draw(&mut buffer, &debug_str, [20, 20], [760, 560]);
|
||||||
}
|
|
||||||
|
|
||||||
let vec: Vec<[u8; 4]> = (&buffer).into();
|
let vec: Vec<[u8; 4]> = (&buffer).into();
|
||||||
fb.update_buffer(&vec);
|
fb.update_buffer(&vec);
|
||||||
|
}
|
||||||
|
|
||||||
true
|
true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -16,18 +16,13 @@ pub struct Ram<const SIZE: usize> {
|
|||||||
impl<const SIZE: usize> fmt::Debug for Ram<SIZE> {
|
impl<const SIZE: usize> fmt::Debug for Ram<SIZE> {
|
||||||
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
self.buffer.iter().enumerate()
|
for i in 0x100..=0x1FF {
|
||||||
.try_for_each(|(i, elem)| {
|
if i%0x10 == 0 {
|
||||||
if i <= 0xFF {
|
f.write_fmt(format_args!("\n {:0>4X}", i))?;
|
||||||
if i%0x10 == 0 {
|
}
|
||||||
f.write_fmt(format_args!("\n {:0>4X}", i))?;
|
f.write_fmt(format_args!(" {:0>2X}", self.buffer[i]))?
|
||||||
}
|
}
|
||||||
f.write_fmt(format_args!(" {:0>2X}", elem))
|
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
})?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -51,4 +46,19 @@ impl<const SIZE: usize> Ram<SIZE> {
|
|||||||
buffer: [0u8; SIZE],
|
buffer: [0u8; SIZE],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_file(file: &str) -> Self {
|
||||||
|
use std::{
|
||||||
|
fs::File,
|
||||||
|
io::Read,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut f = File::open(file).unwrap();
|
||||||
|
let mut buffer = [0u8; SIZE];
|
||||||
|
f.read_exact(&mut buffer).unwrap();
|
||||||
|
|
||||||
|
Ram {
|
||||||
|
buffer,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user