Fix warnings and formating
This commit is contained in:
parent
27585d6440
commit
3c05bfdcaa
221
src/bus.rs
221
src/bus.rs
@ -1,164 +1,165 @@
|
||||
use std::{
|
||||
fmt,
|
||||
rc::Rc,
|
||||
cell::RefCell,
|
||||
fmt,
|
||||
rc::Rc,
|
||||
cell::RefCell,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
utils::DisplayBuffer,
|
||||
peripherals::{Peripheral, Ram, Mapper, Ppu},
|
||||
utils::DisplayBuffer,
|
||||
peripherals::{Peripheral, Ram, Mapper, Ppu},
|
||||
};
|
||||
|
||||
pub struct Bus<M: Mapper> {
|
||||
ram: Ram<0x800>,
|
||||
ppu: Ppu<M>,
|
||||
apu: Ram<0x1F>,//TODO
|
||||
cartridge: Rc<RefCell<M>>,
|
||||
ram: Ram<0x800>,
|
||||
ppu: Ppu<M>,
|
||||
apu: Ram<0x1F>,//TODO
|
||||
cartridge: Rc<RefCell<M>>,
|
||||
}
|
||||
|
||||
impl<M: Mapper> fmt::Debug for Bus<M> {
|
||||
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("Bus")
|
||||
.field("ram", &self.ram)
|
||||
.finish_non_exhaustive()
|
||||
}
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("Bus")
|
||||
.field("ram", &self.ram)
|
||||
.finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: Mapper> Peripheral for Bus<M> {
|
||||
|
||||
fn read_addr(&self, addr: u16) -> u8 {
|
||||
fn read_addr(&self, addr: u16) -> u8 {
|
||||
|
||||
match addr {
|
||||
0x0000..=0x1FFF => self.ram.read_addr(addr % 0x0800), //RAM is mirrored 3 times
|
||||
0x2000..=0x3FFF => self.ppu.read_addr(addr % 0x8), //PPU is mirrored every 8 bytes
|
||||
0x4000..=0x401F => self.apu.read_addr(addr),
|
||||
0x4020..=0xFFFF => self.cartridge.borrow().read_addr(addr),
|
||||
}
|
||||
}
|
||||
match addr {
|
||||
0x0000..=0x1FFF => self.ram.read_addr(addr % 0x0800), //RAM is mirrored 3 times
|
||||
0x2000..=0x3FFF => self.ppu.read_addr(addr % 0x8), //PPU is mirrored every 8 bytes
|
||||
0x4000..=0x401F => self.apu.read_addr(addr),
|
||||
0x4020..=0xFFFF => self.cartridge.borrow().read_addr(addr),
|
||||
}
|
||||
}
|
||||
|
||||
fn write_addr(&mut self, addr: u16, data: u8) {
|
||||
fn write_addr(&mut self, addr: u16, data: u8) {
|
||||
|
||||
match addr {
|
||||
0x0000..=0x1FFF => self.ram.write_addr(addr % 0x0800, data),
|
||||
0x2000..=0x3FFF => self.ppu.write_addr(addr % 0x8, data),
|
||||
0x4000..=0x401F => self.apu.write_addr(addr, data),
|
||||
0x4020..=0xFFFF => self.cartridge.borrow_mut().write_addr(addr, data),
|
||||
};
|
||||
}
|
||||
match addr {
|
||||
0x0000..=0x1FFF => self.ram.write_addr(addr % 0x0800, data),
|
||||
0x2000..=0x3FFF => self.ppu.write_addr(addr % 0x8, data),
|
||||
0x4000..=0x401F => self.apu.write_addr(addr, data),
|
||||
0x4020..=0xFFFF => self.cartridge.borrow_mut().write_addr(addr, data),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: Mapper> Bus<M> {
|
||||
|
||||
pub fn new(mapper: Rc<RefCell<M>>,
|
||||
screen: Rc<RefCell<DisplayBuffer>>,
|
||||
pattern_table: Rc<RefCell<DisplayBuffer>>)
|
||||
-> Self {
|
||||
pub fn new(mapper: Rc<RefCell<M>>,
|
||||
screen: Rc<RefCell<DisplayBuffer>>,
|
||||
pattern_table: Rc<RefCell<DisplayBuffer>>)
|
||||
-> Self {
|
||||
|
||||
let mut ram = Ram::<0x800>::new();
|
||||
let mut ram = Ram::<0x800>::new();
|
||||
|
||||
//TODO temporary for instruction tests
|
||||
ram.buffer[0x01] = 0xE9; //sbc
|
||||
ram.buffer[0x02] = (-3 as i8) as u8;
|
||||
ram.buffer[0x03] = 0x09;
|
||||
ram.buffer[0x04] = 0x00;
|
||||
ram.buffer[0x05] = 0xA9; //lda
|
||||
ram.buffer[0x06] = 0x01;
|
||||
ram.buffer[0x07] = 0x4C; //jmp
|
||||
ram.buffer[0x08] = 0x00;
|
||||
ram.buffer[0x09] = 0x00;
|
||||
ram.buffer[0x0A] = 0x2A; //fn rol
|
||||
ram.buffer[0x0B] = 0x90; //bcc
|
||||
ram.buffer[0x0C] = (-3 as i8) as u8;
|
||||
ram.buffer[0x0D] = 0x60; //rts
|
||||
ram.buffer[0x0E] = 0xFD;
|
||||
ram.buffer[0x0F] = 0x01;
|
||||
ram.buffer[0x10] = 0x21;
|
||||
ram.buffer[0x11] = 0x9F;
|
||||
ram.buffer[0x12] = 0x31;
|
||||
ram.buffer[0x13] = 0xB0;
|
||||
//TODO temporary for instruction tests
|
||||
ram.buffer[0x01] = 0xE9; //sbc
|
||||
ram.buffer[0x02] = (-3 as i8) as u8;
|
||||
ram.buffer[0x03] = 0x09;
|
||||
ram.buffer[0x04] = 0x00;
|
||||
ram.buffer[0x05] = 0xA9; //lda
|
||||
ram.buffer[0x06] = 0x01;
|
||||
ram.buffer[0x07] = 0x4C; //jmp
|
||||
ram.buffer[0x08] = 0x00;
|
||||
ram.buffer[0x09] = 0x00;
|
||||
ram.buffer[0x0A] = 0x2A; //fn rol
|
||||
ram.buffer[0x0B] = 0x90; //bcc
|
||||
ram.buffer[0x0C] = (-3 as i8) as u8;
|
||||
ram.buffer[0x0D] = 0x60; //rts
|
||||
ram.buffer[0x0E] = 0xFD;
|
||||
ram.buffer[0x0F] = 0x01;
|
||||
ram.buffer[0x10] = 0x21;
|
||||
ram.buffer[0x11] = 0x9F;
|
||||
ram.buffer[0x12] = 0x31;
|
||||
ram.buffer[0x13] = 0xB0;
|
||||
|
||||
// boundary
|
||||
ram.buffer[0x14] = 0x3D;
|
||||
ram.buffer[0x15] = 0xFF;
|
||||
ram.buffer[0x16] = 0x02;
|
||||
ram.buffer[0x17] = 0x39;
|
||||
ram.buffer[0x18] = 0xFE;
|
||||
ram.buffer[0x19] = 0x02;
|
||||
ram.buffer[0x1A] = 0x31;
|
||||
ram.buffer[0x1B] = 0xB2;
|
||||
// boundary
|
||||
ram.buffer[0x14] = 0x3D;
|
||||
ram.buffer[0x15] = 0xFF;
|
||||
ram.buffer[0x16] = 0x02;
|
||||
ram.buffer[0x17] = 0x39;
|
||||
ram.buffer[0x18] = 0xFE;
|
||||
ram.buffer[0x19] = 0x02;
|
||||
ram.buffer[0x1A] = 0x31;
|
||||
ram.buffer[0x1B] = 0xB2;
|
||||
|
||||
|
||||
// ptr to val
|
||||
ram.buffer[0xA0] = 0xFF;
|
||||
ram.buffer[0xA1] = 0x01;
|
||||
// ptr to val
|
||||
ram.buffer[0xA0] = 0xFF;
|
||||
ram.buffer[0xA1] = 0x01;
|
||||
|
||||
// ptr to val as table
|
||||
ram.buffer[0xB0] = 0xFD;
|
||||
ram.buffer[0xB1] = 0x01;
|
||||
ram.buffer[0xB2] = 0xFE; //boundary
|
||||
ram.buffer[0xB3] = 0x02;
|
||||
// ptr to val as table
|
||||
ram.buffer[0xB0] = 0xFD;
|
||||
ram.buffer[0xB1] = 0x01;
|
||||
ram.buffer[0xB2] = 0xFE; //boundary
|
||||
ram.buffer[0xB3] = 0x02;
|
||||
|
||||
// zero page val
|
||||
ram.buffer[0xFF] = 0x01;
|
||||
// zero page val
|
||||
ram.buffer[0xFF] = 0x01;
|
||||
|
||||
// val
|
||||
ram.buffer[0x01FF] = 0x01;
|
||||
ram.buffer[0x02FF] = 0xFF; //boundary
|
||||
ram.buffer[0x0300] = 0x03;
|
||||
// val
|
||||
ram.buffer[0x01FF] = 0x01;
|
||||
ram.buffer[0x02FF] = 0xFF; //boundary
|
||||
ram.buffer[0x0300] = 0x03;
|
||||
|
||||
// ptr to test
|
||||
ram.buffer[0x030F] = 0xFF;
|
||||
ram.buffer[0x0310] = 0x03;
|
||||
// ptr to test
|
||||
ram.buffer[0x030F] = 0xFF;
|
||||
ram.buffer[0x0310] = 0x03;
|
||||
|
||||
// jmp test
|
||||
ram.buffer[0x0400] = 0xE6;
|
||||
// jmp test
|
||||
ram.buffer[0x0400] = 0xE6;
|
||||
|
||||
Bus {
|
||||
ram,
|
||||
ppu: Ppu::new(mapper.clone(), screen, pattern_table),
|
||||
apu: Ram::<0x1F>::new(),
|
||||
cartridge: mapper,
|
||||
}
|
||||
}
|
||||
Bus {
|
||||
ram,
|
||||
ppu: Ppu::new(mapper.clone(), screen, pattern_table),
|
||||
apu: Ram::<0x1F>::new(),
|
||||
cartridge: mapper,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tick(&mut self) {
|
||||
self.ppu.tick();
|
||||
}
|
||||
pub fn tick(&mut self) {
|
||||
self.ppu.tick();
|
||||
}
|
||||
}
|
||||
|
||||
/// special Bus only used for testing the emulator
|
||||
pub struct FileBus {
|
||||
mem: Ram<0x10000>,
|
||||
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()
|
||||
}
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("Bus")
|
||||
.field("mem", &self.mem)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Peripheral for FileBus {
|
||||
|
||||
fn read_addr(&self, addr: u16) -> u8 {
|
||||
self.mem.read_addr(addr) //RAM is mirrored 3 times
|
||||
}
|
||||
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)
|
||||
}
|
||||
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"),
|
||||
}
|
||||
}
|
||||
#[allow(dead_code)]
|
||||
pub fn new() -> Self {
|
||||
FileBus {
|
||||
mem: Ram::from_file("6502_functional_test.bin"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -208,7 +208,7 @@ impl<M: Mapper> Cpu<M> {
|
||||
// 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),
|
||||
0x65 => adc(mode_zero_page),
|
||||
0x75 => adc(mode_zero_page_x),
|
||||
|
||||
49
src/main.rs
49
src/main.rs
@ -18,8 +18,8 @@ use peripherals::mapper::Nrom128;
|
||||
mod utils;
|
||||
|
||||
use canvas::{
|
||||
Application,
|
||||
Canvas,
|
||||
Application,
|
||||
Canvas,
|
||||
sprite::{Sprite, TextureSprite, TextSprite, Center},
|
||||
utils::{Size, Color, Position},
|
||||
};
|
||||
@ -29,6 +29,7 @@ struct EmulatorState {
|
||||
pub screen: Rc<RefCell<DisplayBuffer>>,
|
||||
pub screen_sprite: TextureSprite,
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub pattern_table: Rc<RefCell<DisplayBuffer>>,
|
||||
pub pattern_sprite: TextureSprite,
|
||||
|
||||
@ -66,13 +67,13 @@ impl Application<EmulatorState> for NesEmulator {
|
||||
pattern_sprite.set_position(Position {x: 100, y: 50});
|
||||
let pattern_table = Rc::new(RefCell::new(DisplayBuffer::from_texture(pattern_texture)));
|
||||
|
||||
let mut fps_text = canvas.create_text_sprite("00", Size {w: 20, h: 20}, 20.0);
|
||||
let mut fps_text = canvas.create_text_sprite("00", Size {w: 30, h: 20}, 20.0);
|
||||
fps_text.set_center(Center::TopLeft);
|
||||
fps_text.set_position(Position {x:0, y:720});
|
||||
fps_text.set_position(Position {x:0, y:720});
|
||||
|
||||
let mut debug_text = canvas.create_text_sprite("00", Size {w: 300, h: 600}, 20.0);
|
||||
debug_text.set_center(Center::BotLeft);
|
||||
debug_text.set_position(Position {x:700, y:50});
|
||||
debug_text.set_position(Position {x:700, y:50});
|
||||
|
||||
let mapper = Rc::new(RefCell::new(Nrom128::new(false)));
|
||||
let cpu = Cpu::new(mapper, screen.clone(), pattern_table.clone());
|
||||
@ -124,9 +125,9 @@ impl Application<EmulatorState> for NesEmulator {
|
||||
|
||||
fn main() -> Result<(), &'static str> {
|
||||
|
||||
setup_logger()
|
||||
.map_err(|_| "Failed to setup logger")?;
|
||||
canvas::run_canvas("NES emulator", Size {w: 1280, h: 720}, NesEmulator {});
|
||||
setup_logger()
|
||||
.map_err(|_| "Failed to setup logger")?;
|
||||
canvas::run_canvas("NES emulator", Size {w: 1280, h: 720}, NesEmulator {});
|
||||
}
|
||||
|
||||
// use utils::{Pixel, PixelBuffer, FontRenderer, DisplayBuffer};
|
||||
@ -239,22 +240,22 @@ fn main() -> Result<(), &'static str> {
|
||||
|
||||
fn setup_logger() -> Result<(), fern::InitError> {
|
||||
|
||||
fern::Dispatch::new()
|
||||
.format(|out, message, record| {
|
||||
out.finish(format_args!(
|
||||
"{}[{}][{}] {}",
|
||||
chrono::Local::now().format("[%H:%M:%S]"),
|
||||
record.target(),
|
||||
//record.file(),
|
||||
record.level(),
|
||||
message
|
||||
))
|
||||
})
|
||||
.level(log::LevelFilter::Error)
|
||||
.chain(std::io::stdout())
|
||||
.chain(fern::log_file("output.log")?)
|
||||
.apply()?;
|
||||
fern::Dispatch::new()
|
||||
.format(|out, message, record| {
|
||||
out.finish(format_args!(
|
||||
"{}[{}][{}] {}",
|
||||
chrono::Local::now().format("[%H:%M:%S]"),
|
||||
record.target(),
|
||||
//record.file(),
|
||||
record.level(),
|
||||
message
|
||||
))
|
||||
})
|
||||
.level(log::LevelFilter::Error)
|
||||
.chain(std::io::stdout())
|
||||
.chain(fern::log_file("output.log")?)
|
||||
.apply()?;
|
||||
|
||||
Ok(())
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@ -48,6 +48,7 @@ bitflags! {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub struct Ppu<M: Mapper> {
|
||||
vbus: Rc<RefCell<M>>,
|
||||
ppu_ctrl: PpuCtrl,
|
||||
@ -76,7 +77,7 @@ impl<M: Mapper> Peripheral for Ppu<M> {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
fn write_addr(&mut self, addr: u16, data: u8) {
|
||||
fn write_addr(&mut self, _addr: u16, _data: u8) {
|
||||
unimplemented!();
|
||||
}
|
||||
}
|
||||
|
||||
75
src/utils.rs
75
src/utils.rs
@ -1,8 +1,6 @@
|
||||
#[allow(unused_imports)]
|
||||
use log::{debug, error, info, trace, warn};
|
||||
|
||||
use rusttype::{point, Font, Scale, VMetrics};
|
||||
|
||||
mod display_buffer;
|
||||
pub use display_buffer::DisplayBuffer;
|
||||
|
||||
@ -124,76 +122,3 @@ impl From<&PixelBuffer> for Vec<[u8; 4]> {
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/* FontRenderer struct */
|
||||
|
||||
pub struct FontRenderer {
|
||||
font: Font<'static>, scale: Scale, v_metrics: VMetrics, color: [u8; 3],
|
||||
}
|
||||
|
||||
impl FontRenderer {
|
||||
|
||||
pub fn new(size: f32, color: [u8; 3]) -> Self {
|
||||
|
||||
// Load the font
|
||||
let font = {
|
||||
let font_data = include_bytes!("../fonts/DejaVuSansMono.ttf");
|
||||
// This only succeeds if collection consists of one font
|
||||
Font::try_from_bytes(font_data as &[u8]).expect("Error constructing Font")
|
||||
};
|
||||
|
||||
let scale = Scale::uniform(size);
|
||||
let v_metrics = font.v_metrics(scale);
|
||||
|
||||
FontRenderer {
|
||||
font,
|
||||
scale,
|
||||
v_metrics,
|
||||
color,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw(&mut self, buffer: &mut PixelBuffer, text: &str, origin: [usize; 2],
|
||||
size: [usize; 2]) {
|
||||
|
||||
let line_offset = (self.v_metrics.line_gap + self.v_metrics.ascent
|
||||
- self.v_metrics.descent) as usize;
|
||||
|
||||
// split text along '\n'
|
||||
text.split('\n')
|
||||
.enumerate()
|
||||
.for_each(|(id, line)| {
|
||||
|
||||
// layout the glyphs in a line with 20 pixels padding
|
||||
let glyphs: Vec<_> = self.font
|
||||
.layout(line, self.scale, point(origin[0] as f32,
|
||||
origin[1] as f32 + self.v_metrics.ascent))
|
||||
.collect();
|
||||
|
||||
// Loop through the glyphs in the text, positing each one on a line
|
||||
for glyph in glyphs {
|
||||
if let Some(bounding_box) = glyph.pixel_bounding_box() {
|
||||
// Draw the glyph into the image per-pixel by using the draw closure
|
||||
glyph.draw(|x, y, v| {
|
||||
let x_pos = (x + bounding_box.min.x as u32) as usize;
|
||||
let y_pos = (y + bounding_box.min.y as u32) as usize + id * line_offset;
|
||||
|
||||
if x_pos < origin[0] + size[0] && y_pos < origin[1] + size[1] {
|
||||
buffer.put_pixel(
|
||||
x_pos,
|
||||
y_pos,
|
||||
// Turn the coverage into an alpha value
|
||||
Pixel::rgba(
|
||||
self.color[0],
|
||||
self.color[1],
|
||||
self.color[2],
|
||||
(v * 255.0) as u8),
|
||||
)
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -4,20 +4,20 @@ use canvas::texture::TextureHandle;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
pub struct DisplayBuffer {
|
||||
pub is_ready: bool,
|
||||
pub is_ready: bool,
|
||||
|
||||
texture: TextureHandle,
|
||||
texture: TextureHandle,
|
||||
}
|
||||
|
||||
impl DisplayBuffer {
|
||||
|
||||
pub fn from_texture(texture: TextureHandle) -> Self {
|
||||
pub fn from_texture(texture: TextureHandle) -> Self {
|
||||
|
||||
Self {
|
||||
texture,
|
||||
is_ready: false,
|
||||
}
|
||||
}
|
||||
Self {
|
||||
texture,
|
||||
is_ready: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_pixel(&mut self, x: usize, y: usize, pixel: Pixel) {
|
||||
self.texture.set_pixel(
|
||||
|
||||
Loading…
Reference in New Issue
Block a user