diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/mos6502.rs | 81 | ||||
-rw-r--r-- | src/ppu.rs | 78 |
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); @@ -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 { |