diff --git a/README.md b/README.md index 0ed91b7..71375e7 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Usage: ``` Make sure to compile with `--release` for 60 fps. -![Screenshot](https://i.imgur.com/1TMHZrs.png) +![Screenshot](https://i.imgur.com/4s4cDWHl.png) ### what works * CPU diff --git a/src/main.rs b/src/main.rs index f37c352..7d5bd77 100644 --- a/src/main.rs +++ b/src/main.rs @@ -110,7 +110,7 @@ fn main() -> Result<(), Error> { }).collect(); // Main loop - let mut run = true; + let mut run = false; while let Some(event) = events.next(&mut window) { if let Some(_) = event.render_args() { // Run enough clocks to render the next frame @@ -121,8 +121,8 @@ fn main() -> Result<(), Error> { let mut ppu = nes.ppu.borrow_mut(); let ppu_bus = nes.ppu_bus.borrow(); // main_texture.update(&mut texture_ctx, &ppu.canvas_main).unwrap(); - pattern_table_textures[0].update(&mut texture_ctx, &ppu.get_pattern_table(&*ppu_bus, 0, 1)).unwrap(); - pattern_table_textures[1].update(&mut texture_ctx, &ppu.get_pattern_table(&*ppu_bus, 1, 1)).unwrap(); + pattern_table_textures[0].update(&mut texture_ctx, &ppu.get_pattern_table(&*ppu_bus, 0, 0)).unwrap(); + pattern_table_textures[1].update(&mut texture_ctx, &ppu.get_pattern_table(&*ppu_bus, 1, 0)).unwrap(); palette_textures[0].update(&mut texture_ctx, &ppu.get_palette(&*ppu_bus, 0)).unwrap(); palette_textures[1].update(&mut texture_ctx, &ppu.get_palette(&*ppu_bus, 1)).unwrap(); palette_textures[2].update(&mut texture_ctx, &ppu.get_palette(&*ppu_bus, 2)).unwrap(); @@ -249,6 +249,13 @@ fn render_cpu(glyphs: &mut GlyphBrush, cpu: &CPU, offset: [f cpu.is_flag_set(Flags::CARRY) ], offset); + glyphs.queue(Section { + text: &format!("({:#04x})", cpu.regs.flags.bits()), + scale: *FT_SCALE, + screen_position: (offset[0]+200.0, offset[1]+FT_SIZE_PX) , + color: FT_COLOR_WHITE, + ..Section::default() + }); let cpu_register_texts = [ &format!("A: {0:#x} ({0})", cpu.regs.a), diff --git a/src/nes.rs b/src/nes.rs index 1096f82..8f88b87 100644 --- a/src/nes.rs +++ b/src/nes.rs @@ -74,7 +74,13 @@ impl NES { if self.clock_count % 3 == 0 { self.cpu.clock(&mut self.bus); } - self.ppu.borrow_mut().clock(&mut *self.ppu_bus.borrow_mut()); + let mut ppu = self.ppu.borrow_mut(); + ppu.clock(&mut *self.ppu_bus.borrow_mut()); + if ppu.nmi { + ppu.nmi = false; + self.cpu.nmi(&mut self.bus); + debug!("NMI triggered by PPU.") + } if self.clock_count % 100000 == 0 { info!("clock {}", self.clock_count); } diff --git a/src/nes/cpu.rs b/src/nes/cpu.rs index bfb3c25..b81e6f3 100644 --- a/src/nes/cpu.rs +++ b/src/nes/cpu.rs @@ -123,6 +123,41 @@ impl CPU { self.curr_op = 0x00; } + fn interrupt(&mut self, mem: &mut T, pc_addr: Addr) { + // push pc to stack + self.pushb_sp(mem, (self.regs.pc >> 8) as Byte); + self.pushb_sp(mem, self.regs.pc as Byte); + + // push status reg with set interrupt flags to stack + self.set_flag(Flags::BREAK, false); + self.set_flag(Flags::UNUSED, true); + self.set_flag(Flags::IRQ, true); + self.pushb_sp(mem, self.regs.flags.bits()); + + // read new pc + let lo = mem.readb(pc_addr); + let hi = mem.readb(pc_addr + 1); + self.regs.pc = ((hi as Addr) << 8) | lo as Addr; + } + + // Non maskable interrupt + pub fn nmi(&mut self, mem: &mut T) { + let new_pc_addr = 0xFFFA; + self.interrupt(mem, new_pc_addr); + self.cycles_ahead = 8; + } + + // Interrupt request: Same as nmi, but only takes place if interrupts are + // allowed + pub fn irq(&mut self, mem: &mut T) { + if self.is_flag_set(Flags::IRQ) { + let new_pc_addr = 0xFFFE; + self.interrupt(mem, new_pc_addr); + self.cycles_ahead = 7; + }; + } + + // True if the operation is not finished yet pub fn is_ahead(&self) -> bool { return self.cycles_ahead > 0; diff --git a/src/nes/ppu.rs b/src/nes/ppu.rs index ff4d6ba..27e64d3 100644 --- a/src/nes/ppu.rs +++ b/src/nes/ppu.rs @@ -98,10 +98,11 @@ pub struct PPU { pub regs: Registers, pub cycle: u16, pub scanline: u16, + pub frame_ready: bool, + pub nmi: bool, pub canvas_main: Sprite, pub pattern_tables: [Sprite; 2], pub palettes: [Sprite; 8], - pub frame_ready: bool, addr_latch_set: bool, data_buffer: Byte, } @@ -112,6 +113,8 @@ impl PPU { regs: Registers::new(), cycle: 0, scanline: 0, + frame_ready: false, + nmi: false, canvas_main: ImageBuffer::from_pixel(256, 240, PALETTE[&0x00]), pattern_tables: [ ImageBuffer::from_pixel(128, 128, PALETTE[&0x00]), @@ -127,7 +130,6 @@ impl PPU { ImageBuffer::from_pixel(4, 1, PALETTE[&0x00]), ImageBuffer::from_pixel(4, 1, PALETTE[&0x00]), ], - frame_ready: false, addr_latch_set: false, data_buffer: 0 } @@ -190,6 +192,9 @@ impl PPU { // set/clear vblank flag if self.scanline == 241 && self.cycle == 1 { self.set_status(Status::VERTICAL_BLANK, true); + if self.get_control(Control::ENABLE_NMI) { + self.nmi = true; + } } else if self.scanline == 261 && self.cycle == 1 { self.set_status(Status::VERTICAL_BLANK, false); @@ -221,7 +226,7 @@ impl PPU { // palette memory let data = self.data_buffer; self.data_buffer = mem.readb_ppu(addr); - + if addr > 0x3F00 { // everything above 0x3F00 is palette self.data_buffer } else {