From dfdeb66b10c1c1af8243c475bca69839e2bdd6e8 Mon Sep 17 00:00:00 2001 From: Determinant Date: Tue, 14 Nov 2017 12:30:05 -0500 Subject: ... --- src/main.rs | 14 +++++++-- src/mos6502.rs | 97 +++++++++++++++++++++++++++++++++++----------------------- src/ppu.rs | 30 ++++++++++++------ 3 files changed, 90 insertions(+), 51 deletions(-) diff --git a/src/main.rs b/src/main.rs index 54885ca..cef6d4c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -186,6 +186,7 @@ fn main() { mem.init(&mut cpu, &mut ppu); let mut cnt = 0; let mut cnt2 = 0; + let mut flag = false; loop { if win.poll() {break} cpu.step(); @@ -196,9 +197,16 @@ fn main() { if ppu.tick() { println!("triggering nmi"); cpu.trigger_nmi(); - println!("{} cpu {} ppu per frame", cnt, cnt2); - cnt2 = 0; - cnt = 0; + } + if ppu.get_flag_vblank() { + if !flag { + println!("{} cpu {} ppu per frame", cnt, cnt2); + cnt2 = 0; + cnt = 0; + flag = true; + } + } else { + flag = false; } } cpu.cycle -= 1; diff --git a/src/mos6502.rs b/src/mos6502.rs index a267236..45c4166 100644 --- a/src/mos6502.rs +++ b/src/mos6502.rs @@ -42,7 +42,6 @@ macro_rules! make_addrtable { rel, iny, nil, iny, zpx, zpx, zpx, zpx, nil, aby, nil, aby, abx, abx, abx, abx, ];); } - const INST_LENGTH: [u8; 0x100] = [ 1, 2, 0, 0, 2, 2, 2, 0, 1, 2, 1, 0, 3, 3, 3, 0, 2, 2, 0, 0, 2, 2, 2, 0, 1, 3, 1, 0, 3, 3, 3, 0, @@ -81,6 +80,26 @@ const INST_CYCLE: [u8; 0x100] = [ 2, 5, 2, 8, 4, 4, 6, 6, 2, 4, 2, 7, 4, 4, 7, 7, ]; +const INST_EXTRA_CYCLE: [u8; 0x100] = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, +]; + + const NMI_VECTOR: u16 = 0xfffa; const RESET_VECTOR: u16 = 0xfffc; const IRQ_VECTOR: u16 = 0xfffe; @@ -417,8 +436,8 @@ mod ops { ($f: ident, $e: ident) => (fn $f(cpu: &mut CPU) { match cpu.$e() { 0 => { + cpu.cycle += 1 + ((cpu.pc >> 8) != (cpu.ea >> 8)) as u32; cpu.pc = cpu.ea; - cpu.cycle += 1; }, _ => () }}); @@ -429,8 +448,8 @@ mod ops { match cpu.$e() { 0 => (), _ => { + cpu.cycle += 1 + ((cpu.pc >> 8) != (cpu.ea >> 8)) as u32; cpu.pc = cpu.ea; - cpu.cycle += 1; } }}); } @@ -579,75 +598,74 @@ mod ops { mod addr { use mos6502::{CPU}; - make_addrtable!(ADDR_MODES, fn (&mut CPU)); + make_addrtable!(ADDR_MODES, fn (&mut CPU) -> u8); - fn acc(cpu: &mut CPU) { - cpu.acc = true; + fn acc(cpu: &mut CPU) -> u8 { + cpu.acc = true; 0 } - fn imm(cpu: &mut CPU) { - cpu.ea = cpu.opr; + fn imm(cpu: &mut CPU) -> u8 { + cpu.ea = cpu.opr; 0 } - fn zpg(cpu: &mut CPU) { - cpu.ea = cpu.mem.read(cpu.opr) as u16; + fn zpg(cpu: &mut CPU) -> u8 { + cpu.ea = cpu.mem.read(cpu.opr) as u16; 0 } - fn zpx(cpu: &mut CPU) { + fn zpx(cpu: &mut CPU) -> u8 { cpu.ea = (cpu.mem.read(cpu.opr) - .wrapping_add(cpu.x)) as u16; + .wrapping_add(cpu.x)) as u16; 0 } - fn zpy(cpu: &mut CPU) { + fn zpy(cpu: &mut CPU) -> u8 { cpu.ea = (cpu.mem.read(cpu.opr) - .wrapping_add(cpu.y)) as u16; + .wrapping_add(cpu.y)) as u16; 0 } - fn rel(cpu: &mut CPU) { + fn rel(cpu: &mut CPU) -> u8 { let base = cpu.pc; let offset = cpu.mem.read(cpu.opr) as i8 as i16; - let sum = ((base & 0xff) as i16 + offset) as u16; - cpu.ea = (base & 0xff00).wrapping_add(sum); - cpu.cycle += (sum >> 8) as u32; + cpu.ea = base.wrapping_add(offset as u16); + 0 } - fn abs(cpu: &mut CPU) { - cpu.ea = read16!(cpu.mem, cpu.opr); + fn abs(cpu: &mut CPU) -> u8 { + cpu.ea = read16!(cpu.mem, cpu.opr); 0 } - fn abx(cpu: &mut CPU) { + fn abx(cpu: &mut CPU) -> u8 { let base = read16!(cpu.mem, cpu.opr); let sum = (base & 0xff) + (cpu.x as u16); cpu.ea = (base & 0xff00).wrapping_add(sum); - cpu.cycle += (sum >> 8) as u32; /* boundary cross if carry */ + (sum >> 8) as u8 /* boundary cross if carry */ } - fn aby(cpu: &mut CPU) { + fn aby(cpu: &mut CPU) -> u8 { let base = read16!(cpu.mem, cpu.opr); let sum = (base & 0xff) + (cpu.y as u16); cpu.ea = (base & 0xff00).wrapping_add(sum); - cpu.cycle += (sum >> 8) as u32; /* boundary cross if carry */ + (sum >> 8) as u8 /* boundary cross if carry */ } - fn ind(cpu: &mut CPU) { + fn ind(cpu: &mut CPU) -> u8 { let addr = read16!(cpu.mem, cpu.opr); - cpu.ea = read16!(cpu.mem, addr); + cpu.ea = read16!(cpu.mem, addr); 0 } - fn xin(cpu: &mut CPU) { + fn xin(cpu: &mut CPU) -> u8 { cpu.ea = read16!(cpu.mem, cpu.mem.read(cpu.opr) - .wrapping_add(cpu.x) as u16) as u16; + .wrapping_add(cpu.x) as u16) as u16; 0 } - fn iny(cpu: &mut CPU) { + fn iny(cpu: &mut CPU) -> u8 { let base = read16!(cpu.mem, cpu.mem.read(cpu.opr) as u16); let sum = (base & 0xff) + (cpu.y as u16); cpu.ea = (base & 0xff00).wrapping_add(sum); - cpu.cycle += (sum >> 8) as u32; /* boundary cross if carry */ + (sum >> 8) as u8 /* boundary cross if carry */ } - fn nil(_cpu: &mut CPU) {} + fn nil(_cpu: &mut CPU) -> u8 {0} } enum IntType { @@ -717,12 +735,15 @@ impl<'a> CPU<'a> { make_int!(irq, IRQ_VECTOR); pub fn step(&mut self) { - match self.int { - Some(IntType::NMI) => self.nmi(), - Some(IntType::IRQ) => self.irq(), - _ => () + if self.int.is_some() { + match self.int { + Some(IntType::NMI) => self.nmi(), + Some(IntType::IRQ) => self.irq(), + _ => () + } + self.int = None; + return; } - self.int = None; let pc = self.pc; let opcode = self.mem.read(pc) as usize; let len = INST_LENGTH[opcode]; @@ -738,10 +759,10 @@ impl<'a> CPU<'a> { self.pc = pc.wrapping_add(INST_LENGTH[opcode] as u16); /* get effective address based on addressing mode */ self.acc = false; - addr::ADDR_MODES[opcode](self); + let e = addr::ADDR_MODES[opcode](self) * INST_EXTRA_CYCLE[opcode]; /* execute the inst */ ops::OPS[opcode](self); - self.cycle += INST_CYCLE[opcode] as u32; + self.cycle += (INST_CYCLE[opcode] + e) as u32; } pub fn get_pc(&self) -> u16 { self.pc } diff --git a/src/ppu.rs b/src/ppu.rs index 4b64b5d..4114f5d 100644 --- a/src/ppu.rs +++ b/src/ppu.rs @@ -50,6 +50,7 @@ pub struct PPU<'a> { sp_zero_insight: bool, rendering: bool, buffered_read: u8, + early_read: bool, /* IO */ mem: &'a VMem, scr: &'a Screen, @@ -71,6 +72,9 @@ impl<'a> PPU<'a> { let res = (self.ppustatus & !0x1fu8) | (self.reg & 0x1f); self.ppustatus &= !PPU::FLAG_VBLANK; self.w = false; + if self.scanline == 241 && self.cycle == 0 { + self.early_read = true; + } res } @@ -103,7 +107,7 @@ impl<'a> PPU<'a> { false => { self.t = (self.t & 0x7fe0) | (data >> 3); self.x = (data & 0x07) as u8; - assert!(self.x == 0); + //assert!(self.x == 0); self.w = true; }, true => { @@ -178,6 +182,7 @@ impl<'a> PPU<'a> { #[inline(always)] fn get_show_leftmost_sp(&self) -> bool { (self.ppumask >> 2) & 1 == 1} #[inline(always)] fn get_show_bg(&self) -> bool { (self.ppumask >> 3) & 1 == 1} #[inline(always)] fn get_show_sp(&self) -> bool { (self.ppumask >> 4) & 1 == 1} + #[inline(always)] pub fn get_flag_vblank(&self) -> bool { (self.ppustatus >> 7) & 1 == 1 } const FLAG_OVERFLOW: u8 = 1 << 5; const FLAG_SPRITE_ZERO: u8 = 1 << 6; const FLAG_VBLANK: u8 = 1 << 7; @@ -225,10 +230,10 @@ impl<'a> PPU<'a> { // self.bg_palette[0] >> 8 == 0 && // self.bg_palette[1] >> 8 == 0)) { // println!("at cycle {} {}", self.scanline, self.cycle) } - assert!(self.bg_bitmap[0] >> 8 == 0 && - self.bg_bitmap[1] >> 8 == 0 && - self.bg_palette[0] >> 8 == 0 && - self.bg_palette[1] >> 8 == 0); + //assert!(self.bg_bitmap[0] >> 8 == 0 && + // self.bg_bitmap[1] >> 8 == 0 && + // self.bg_palette[0] >> 8 == 0 && + // self.bg_palette[1] >> 8 == 0); self.bg_bitmap[0] |= (PPU::reverse_byte(self.bg_bit_low) as u16) << 8; self.bg_bitmap[1] |= (PPU::reverse_byte(self.bg_bit_high) as u16) << 8; self.bg_palette[0] |= (self.bg_attr & 1) as u16 * 0xff00; @@ -389,7 +394,8 @@ impl<'a> PPU<'a> { #[inline(always)] fn get_bg_pidx(&self) -> u8 { if self.get_show_bg() { - ((self.bg_bitmap[1] & 1) << 1) as u8 | (self.bg_bitmap[0] & 1) as u8 + (((self.bg_bitmap[1] >> self.x) & 1) << 1) as u8 | + ((self.bg_bitmap[0] >> self.x) & 1) as u8 } else { 0 } } @@ -439,8 +445,8 @@ impl<'a> PPU<'a> { sp_pidx as u16) } else { self.mem.read(0x3f00 | - (((self.bg_palette[1] & 1) << 3) | - ((self.bg_palette[0] & 1) << 2)) as u16 | + ((((self.bg_palette[1] >> self.x) & 1) << 3) | + (((self.bg_palette[0] >> self.x) & 1) << 2)) as u16 | bg_pidx as u16) }); } @@ -474,6 +480,7 @@ impl<'a> PPU<'a> { sp_zero_insight: false, rendering: false, buffered_read, + early_read: false, mem, scr } } @@ -545,9 +552,12 @@ impl<'a> PPU<'a> { } } else if self.scanline == 241 && cycle == 1 { self.scr.render(); - self.ppustatus |= PPU::FLAG_VBLANK; + if !self.early_read { + self.ppustatus |= PPU::FLAG_VBLANK; + } self.cycle += 1; - return self.get_flag_nmi(); /* trigger cpu's NMI */ + self.early_read = false; + return !self.early_read && self.get_flag_nmi(); /* trigger cpu's NMI */ } self.cycle += 1; if self.cycle > 340 { -- cgit v1.2.3-70-g09d2