aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDeterminant <ted.sybil@gmail.com>2017-11-14 12:30:05 -0500
committerDeterminant <ted.sybil@gmail.com>2017-11-14 12:30:05 -0500
commitdfdeb66b10c1c1af8243c475bca69839e2bdd6e8 (patch)
tree668dff28721609227b7c47805604129ffd376f96
parenta77a04381c9f7f1db123668ee892ee94a0a7c2dc (diff)
...
-rw-r--r--src/main.rs14
-rw-r--r--src/mos6502.rs97
-rw-r--r--src/ppu.rs30
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 {