aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDeterminant <[email protected]>2017-11-13 23:29:01 -0500
committerDeterminant <[email protected]>2017-11-13 23:29:01 -0500
commita77a04381c9f7f1db123668ee892ee94a0a7c2dc (patch)
tree492a264980925738be155bae5470253f77f4d145 /src
parent71cbf2b7aeeafb2d7b7c6cfcc1e7938b36f79fb1 (diff)
...
Diffstat (limited to 'src')
-rw-r--r--src/mos6502.rs81
-rw-r--r--src/ppu.rs78
2 files changed, 60 insertions, 99 deletions
diff --git a/src/mos6502.rs b/src/mos6502.rs
index e960d32..a267236 100644
--- a/src/mos6502.rs
+++ b/src/mos6502.rs
@@ -227,10 +227,7 @@ mod ops {
fn adc(cpu: &mut CPU) {
let opr1 = cpu.a as u16;
- let opr2 = match cpu.addr_mode {
- AddrMode::Immediate => cpu.imm_val,
- _ => cpu.mem.read(cpu.ea)
- } as u16;
+ let opr2 = cpu.mem.read(cpu.ea) as u16;
let res = opr1 + opr2 + (cpu.get_carry() as u16);
let mut status = cpu.status & !(CARRY_FLAG | ZERO_FLAG | OVER_FLAG | NEG_FLAG);
cpu.a = res as u8;
@@ -245,10 +242,7 @@ mod ops {
fn sbc(cpu: &mut CPU) {
let opr1 = cpu.a as u16;
- let opr2 = match cpu.addr_mode {
- AddrMode::Immediate => cpu.imm_val,
- _ => cpu.mem.read(cpu.ea)
- } as u16;
+ let opr2 = cpu.mem.read(cpu.ea) as u16;
let res = opr1 + (0xff - opr2) + (cpu.get_carry() as u16);
let mut status = cpu.status & !(CARRY_FLAG | ZERO_FLAG | OVER_FLAG | NEG_FLAG);
cpu.a = res as u8;
@@ -263,10 +257,7 @@ mod ops {
macro_rules! make_cmp {
($f: ident, $r: ident) => (fn $f(cpu: &mut CPU) {
let opr1 = cpu.$r as u16;
- let opr2 = match cpu.addr_mode {
- AddrMode::Immediate => cpu.imm_val,
- _ => cpu.mem.read(cpu.ea)
- } as u16;
+ let opr2 = cpu.mem.read(cpu.ea) as u16;
let res = opr1.wrapping_sub(opr2);
let mut status = cpu.status & !(CARRY_FLAG | ZERO_FLAG | NEG_FLAG);
status |= (res < 0x100) as u8; /* if opr1 >= opr2 */
@@ -314,10 +305,7 @@ mod ops {
macro_rules! make_logic {
($f: ident, $op: tt) => (
fn $f(cpu: &mut CPU) {
- let res = cpu.a $op match cpu.addr_mode {
- AddrMode::Immediate => cpu.imm_val,
- _ => cpu.mem.read(cpu.ea)
- };
+ let res = cpu.a $op cpu.mem.read(cpu.ea);
let mut status = cpu.status & !(ZERO_FLAG | NEG_FLAG);
cpu.a = res as u8;
check_zero!(status, res);
@@ -340,13 +328,13 @@ mod ops {
/* shifts */
fn asl(cpu: &mut CPU) {
- let res = match cpu.addr_mode {
- AddrMode::Accumulator => {
+ let res = match cpu.acc {
+ true => {
let t = (cpu.a as u16) << 1;
cpu.a = t as u8;
t
},
- _ => {
+ false => {
let t = (cpu.mem.read(cpu.ea) as u16) << 1;
cpu.mem.write(cpu.ea, t as u8);
t
@@ -360,15 +348,15 @@ mod ops {
fn lsr(cpu: &mut CPU) {
let mut status = cpu.status & !(CARRY_FLAG | ZERO_FLAG | NEG_FLAG);
- let res = match cpu.addr_mode {
- AddrMode::Accumulator => {
+ let res = match cpu.acc {
+ true => {
let old = cpu.a;
let t = old >> 1;
cpu.a = t as u8;
status |= (old & 1) as u8; /* carry flag */
t
},
- _ => {
+ false => {
let old = cpu.mem.read(cpu.ea);
let t = old >> 1;
cpu.mem.write(cpu.ea, t as u8);
@@ -382,15 +370,15 @@ mod ops {
fn rol(cpu: &mut CPU) {
let mut status = cpu.status & !(CARRY_FLAG | ZERO_FLAG | NEG_FLAG);
- let res = match cpu.addr_mode {
- AddrMode::Accumulator => {
+ let res = match cpu.acc {
+ true => {
let old = cpu.a;
let t = old.rotate_left(1);
cpu.a = t as u8;
status |= old >> 7 as u8; /* carry flag */
t
},
- _ => {
+ false => {
let old = cpu.mem.read(cpu.ea);
let t = old.rotate_left(1);
cpu.mem.write(cpu.ea, t as u8);
@@ -404,15 +392,15 @@ mod ops {
fn ror(cpu: &mut CPU) {
let mut status = cpu.status & !(CARRY_FLAG | ZERO_FLAG | NEG_FLAG);
- let res = match cpu.addr_mode {
- AddrMode::Accumulator => {
+ let res = match cpu.acc {
+ true => {
let old = cpu.a;
let t = old.rotate_right(1);
cpu.a = t as u8;
status |= old & 1 as u8; /* carry flag */
t
},
- _ => {
+ false => {
let old = cpu.mem.read(cpu.ea);
let t = old.rotate_right(1);
cpu.mem.write(cpu.ea, t as u8);
@@ -512,10 +500,7 @@ mod ops {
macro_rules! make_ld {
($f: ident, $r: ident) => (fn $f(cpu: &mut CPU) {
let mut status = cpu.status & !(ZERO_FLAG | NEG_FLAG);
- let res = match cpu.addr_mode {
- AddrMode::Immediate => cpu.imm_val,
- _ => cpu.mem.read(cpu.ea)
- };
+ let res = cpu.mem.read(cpu.ea);
cpu.$r = res;
check_zero!(status, res);
check_neg!(status, res);
@@ -593,37 +578,32 @@ mod ops {
}
mod addr {
- use mos6502::{CPU, AddrMode};
+ use mos6502::{CPU};
make_addrtable!(ADDR_MODES, fn (&mut CPU));
fn acc(cpu: &mut CPU) {
- cpu.addr_mode = AddrMode::Accumulator;
+ cpu.acc = true;
}
fn imm(cpu: &mut CPU) {
- cpu.addr_mode = AddrMode::Immediate;
- cpu.imm_val = cpu.mem.read(cpu.opr);
+ cpu.ea = cpu.opr;
}
fn zpg(cpu: &mut CPU) {
- cpu.addr_mode = AddrMode::EffAddr;
cpu.ea = cpu.mem.read(cpu.opr) as u16;
}
fn zpx(cpu: &mut CPU) {
- cpu.addr_mode = AddrMode::EffAddr;
cpu.ea = (cpu.mem.read(cpu.opr)
.wrapping_add(cpu.x)) as u16;
}
fn zpy(cpu: &mut CPU) {
- cpu.addr_mode = AddrMode::EffAddr;
cpu.ea = (cpu.mem.read(cpu.opr)
.wrapping_add(cpu.y)) as u16;
}
fn rel(cpu: &mut CPU) {
- cpu.addr_mode = AddrMode::EffAddr;
let base = cpu.pc;
let offset = cpu.mem.read(cpu.opr) as i8 as i16;
let sum = ((base & 0xff) as i16 + offset) as u16;
@@ -632,12 +612,10 @@ mod addr {
}
fn abs(cpu: &mut CPU) {
- cpu.addr_mode = AddrMode::EffAddr;
cpu.ea = read16!(cpu.mem, cpu.opr);
}
fn abx(cpu: &mut CPU) {
- cpu.addr_mode = AddrMode::EffAddr;
let base = read16!(cpu.mem, cpu.opr);
let sum = (base & 0xff) + (cpu.x as u16);
cpu.ea = (base & 0xff00).wrapping_add(sum);
@@ -645,7 +623,6 @@ mod addr {
}
fn aby(cpu: &mut CPU) {
- cpu.addr_mode = AddrMode::EffAddr;
let base = read16!(cpu.mem, cpu.opr);
let sum = (base & 0xff) + (cpu.y as u16);
cpu.ea = (base & 0xff00).wrapping_add(sum);
@@ -653,20 +630,17 @@ mod addr {
}
fn ind(cpu: &mut CPU) {
- cpu.addr_mode = AddrMode::EffAddr;
let addr = read16!(cpu.mem, cpu.opr);
cpu.ea = read16!(cpu.mem, addr);
}
fn xin(cpu: &mut CPU) {
- cpu.addr_mode = AddrMode::EffAddr;
cpu.ea = read16!(cpu.mem,
cpu.mem.read(cpu.opr)
.wrapping_add(cpu.x) as u16) as u16;
}
fn iny(cpu: &mut CPU) {
- cpu.addr_mode = AddrMode::EffAddr;
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);
@@ -676,12 +650,6 @@ mod addr {
fn nil(_cpu: &mut CPU) {}
}
-enum AddrMode {
- Immediate,
- Accumulator,
- EffAddr
-}
-
enum IntType {
NMI,
IRQ
@@ -696,7 +664,7 @@ pub struct CPU<'a> {
pc: u16,
sp: u8,
/* internal state */
- addr_mode: AddrMode,
+ acc: bool,
opr: u16,
ea: u16, /* effective address */
imm_val: u8,
@@ -741,7 +709,7 @@ impl<'a> CPU<'a> {
pc, sp, status, cycle,
opr: 0, ea: 0, imm_val: 0,
int: None,
- addr_mode: AddrMode::EffAddr,
+ acc: false,
mem}
}
@@ -762,13 +730,14 @@ impl<'a> CPU<'a> {
for i in 0..len as u16 {
code[i as usize] = self.mem.read(pc + i);
}
- //println!("0x{:04x} {} a:{} x:{} y:{}",
- // pc, disasm::parse(opcode as u8, &code[1..]), self.a, self.x, self.y);
+ println!("0x{:04x} {} a:{} x:{} y:{}",
+ pc, disasm::parse(opcode as u8, &code[1..]), self.a, self.x, self.y);
/* update opr pointing to operands of current inst */
self.opr = pc.wrapping_add(1);
/* update program counter pointing to next inst */
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);
/* execute the inst */
ops::OPS[opcode](self);
diff --git a/src/ppu.rs b/src/ppu.rs
index baaff19..4b64b5d 100644
--- a/src/ppu.rs
+++ b/src/ppu.rs
@@ -57,11 +57,13 @@ pub struct PPU<'a> {
impl<'a> PPU<'a> {
pub fn write_ctl(&mut self, data: u8) {
+ self.reg = data;
self.ppuctl = data;
self.t = (self.t & 0x73ff) | ((data as u16 & 3) << 10);
}
pub fn write_mask(&mut self, data: u8) {
+ self.reg = data;
self.ppumask = data;
}
@@ -73,10 +75,12 @@ impl<'a> PPU<'a> {
}
pub fn write_oamaddr(&mut self, data: u8) {
+ self.reg = data;
self.oamaddr = data;
}
pub fn write_oamdata(&mut self, data: u8) {
+ self.reg = data;
if self.rendering { return }
unsafe {
let oam_raw = transmute::<&mut[Sprite; 64], &mut[u8; 256]>(&mut self.oam);
@@ -93,6 +97,7 @@ impl<'a> PPU<'a> {
}
pub fn write_scroll(&mut self, data: u8) {
+ self.reg = data;
let data = data as u16;
match self.w {
false => {
@@ -109,6 +114,7 @@ impl<'a> PPU<'a> {
}
pub fn write_addr(&mut self, data: u8) {
+ self.reg = data;
let data = data as u16;
match self.w {
false => {
@@ -141,6 +147,7 @@ impl<'a> PPU<'a> {
}
pub fn write_data(&mut self, data: u8) {
+ self.reg = data;
self.mem.write(self.v, data);
self.v = self.v.wrapping_add(match self.get_vram_inc() {
0 => 1,
@@ -149,6 +156,7 @@ impl<'a> PPU<'a> {
}
pub fn write_oamdma(&mut self, data: u8, cpu: &mut CPU) {
+ self.reg = data;
let mut addr = (data as u16) << 8;
unsafe {
let oam_raw = transmute::<&mut[Sprite; 64], &mut[u8; 256]>(&mut self.oam);
@@ -217,10 +225,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;
@@ -244,13 +252,13 @@ impl<'a> PPU<'a> {
}
#[inline(always)]
- fn shift_bgtile(&mut self, d: u8) {
+ fn shift_bgtile(&mut self) {
let t1 = &mut self.bg_bitmap;
let t2 = &mut self.bg_palette;
- t1[0] = t1[0].wrapping_shr(d as u32);
- t1[1] = t1[1].wrapping_shr(d as u32);
- t2[0] = t2[0].wrapping_shr(d as u32);
- t2[1] = t2[1].wrapping_shr(d as u32);
+ t1[0] = t1[0].wrapping_shr(1);
+ t1[1] = t1[1].wrapping_shr(1);
+ t2[0] = t2[0].wrapping_shr(1);
+ t2[1] = t2[1].wrapping_shr(1);
}
#[inline(always)]
@@ -292,10 +300,12 @@ impl<'a> PPU<'a> {
#[inline(always)]
fn clear_sprite(&mut self) {
+ if self.scanline == 261 { return }
self.oam2 = [0x100; 8];
}
fn eval_sprite(&mut self) {
+ if self.scanline == 261 { return }
/* we use scanline here because s.y is the (actual y) - 1 */
let mut nidx = 0;
let mut n = 0;
@@ -341,6 +351,7 @@ impl<'a> PPU<'a> {
}
fn fetch_sprite(&mut self) {
+ if self.scanline == 261 { return }
/* we use scanline here because s.y is the (actual y) - 1 */
self.sp_idx = [0x100; 8];
for (i, v) in self.oam2.iter().enumerate() {
@@ -483,9 +494,9 @@ impl<'a> PPU<'a> {
self.cycle = cycle + 1;
return false;
}
- let visible = self.scanline < 240;
+ let visible_line = self.scanline < 240;
let pre_render = self.scanline == 261;
- self.rendering = pre_render || visible;
+ self.rendering = pre_render || visible_line;
if pre_render && cycle == 1 {
/* clear vblank, sprite zero hit & overflow */
self.ppustatus &= !(PPU::FLAG_VBLANK |
@@ -495,14 +506,16 @@ impl<'a> PPU<'a> {
if pre_render && 279 < cycle && cycle < 305 {
self.reset_y();
} else {
- let shifting = 0 < cycle && cycle < 257; /* 1..256 */
- let fetch = shifting || (320 < cycle && cycle < 337);
- if fetch { /* 1..256 and 321..336 */
+ let visible_cycle = 0 < cycle && cycle < 257; /* 1..256 */
+ let fetch_cycle = visible_cycle || (320 < cycle && cycle < 337);
+ if visible_line && visible_cycle {
+ self.render_pixel();
+ self.shift_sprites();
+ }
+ if fetch_cycle { /* 1..256 and 321..336 */
match cycle & 0x7 {
1 => {
- if shifting && cycle > 1 {
- self.load_bgtile();
- }
+ self.load_bgtile();
self.fetch_nametable_byte();
},
3 => self.fetch_attrtable_byte(),
@@ -511,26 +524,15 @@ impl<'a> PPU<'a> {
0 => self.wrapping_inc_cx(),
_ => ()
}
- if visible {
- match cycle {
- 1 => self.clear_sprite(), /* clear secondary OAM */
- 65 => self.eval_sprite(), /* sprite evaluation */
- _ => ()
- }
- }
match cycle {
- 256 => {
- self.wrapping_inc_y()
- },
- 329 => self.load_bgtile(),
+ 1 => self.clear_sprite(), /* clear secondary OAM */
+ 65 => self.eval_sprite(), /* sprite evaluation */
+ 256 => self.wrapping_inc_y(),
_ => ()
}
+ self.shift_bgtile();
} else if cycle > 336 { /* 337..340 */
if cycle & 1 == 1 {
- if cycle == 337 {
- self.shift_bgtile(8);
- self.load_bgtile();
- }
self.fetch_nametable_byte();
}
} else if cycle == 257 {
@@ -538,17 +540,7 @@ impl<'a> PPU<'a> {
* from the secondary OAM which is not subject to any change during this
* scanline */
self.reset_cx();
- if visible {
- self.fetch_sprite();
- }
- }
-
- if shifting {
- if visible {
- self.render_pixel();
- }
- self.shift_bgtile(1);
- self.shift_sprites();
+ self.fetch_sprite();
}
}
} else if self.scanline == 241 && cycle == 1 {