Fix warnings and formating

This commit is contained in:
Steins7 2024-03-10 15:07:09 +01:00
parent 27585d6440
commit 3c05bfdcaa
9 changed files with 159 additions and 231 deletions

View File

@ -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"),
}
}
}

View File

@ -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),

View File

@ -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(())
}

View File

@ -9,7 +9,7 @@ pub use nrom::Nrom128;
///A Mapper is a special `Peripheral` that can also be read by the `Ppu`. The exact memory layout
///is defined by the implementation
pub trait Mapper: Peripheral {
///read the specified 16 bits address using the ppu bus
fn ppu_read_addr(&self, addr: u16) -> u8;
}

View File

@ -20,32 +20,32 @@ impl Peripheral for Nrom128 {
match addr {
0x6000..=0x7FFF => self.prg_ram.read_addr(addr - 0x6000),
0x8000..=0xFFFF => self.prg_rom.read_addr((addr - 0x8000) % 0x4000),
0x8000..=0xFFFF => self.prg_rom.read_addr((addr - 0x8000) % 0x4000),
//mirrored every 16KiB
_ => panic!("{}: Invalid address", addr),
}
}
fn write_addr(&mut self, addr: u16, data: u8) {
match addr {
0x6000..=0x7FFF => self.prg_ram.write_addr(addr - 0x6000, data),
_ => (), //writes are ignored for rom or invald addresses
}
}
}
}
impl Mapper for Nrom128 {
fn ppu_read_addr(&self, addr: u16) -> u8 {
match addr {
0x0000..=0x1FFF => self.chr_rom.read_addr(addr),
0x2000..=0x3EFF => {
match self.vertical {
false => match (addr - 0x2000) % 0x0FFF {
0x0000..=0x07FF => self.v_ram.read_addr(addr % 0x0400),
0x0800..=0x0FFF => self.v_ram.read_addr((addr % 0x0400) + 0x0800),
0x0800..=0x0FFF => self.v_ram.read_addr((addr % 0x0400) + 0x0800),
_ => panic!("Unexpected behaviour"),
},
true => self.v_ram.read_addr(addr % 0x0800),
@ -58,7 +58,7 @@ impl Mapper for Nrom128 {
impl Nrom128 {
pub fn new(vertical: bool) -> Self {
Self {
prg_rom: Ram::<0x4000>::new(),
prg_ram: Ram::<0x2000>::new(),

View File

@ -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!();
}
}

View File

@ -8,7 +8,7 @@ pub struct Ram<const SIZE: usize> {
}
impl<const SIZE: usize> fmt::Debug for Ram<SIZE> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for i in 0x100..=0x1FF {
if i%0x10 == 0 {
@ -16,7 +16,7 @@ impl<const SIZE: usize> fmt::Debug for Ram<SIZE> {
}
f.write_fmt(format_args!(" {:0>2X}", self.buffer[i]))?
}
Ok(())
}
}
@ -35,7 +35,7 @@ impl<const SIZE: usize> Peripheral for Ram<SIZE> {
impl<const SIZE: usize> Ram<SIZE> {
pub fn new() -> Self {
Ram {
buffer: [0u8; SIZE],
}

View File

@ -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;
@ -42,7 +40,7 @@ impl std::ops::Add for Pixel {
}
impl std::ops::AddAssign for Pixel {
fn add_assign(&mut self, other: Self) {
let alpha = other.a as f32 / 255.0;
@ -76,7 +74,7 @@ pub struct PixelBuffer {
}
impl PixelBuffer {
pub fn new(w: usize, h: usize) -> Self {
PixelBuffer {
buffer: vec![Pixel::rgba(255u8, 255u8, 255u8, 255); h * w],
@ -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),
)
}
});
}
}
});
}
}

View File

@ -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(