aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDeterminant <ted.sybil@gmail.com>2017-11-14 20:38:45 -0500
committerDeterminant <ted.sybil@gmail.com>2017-11-14 20:38:45 -0500
commit4857ed73e80619d6046af223a61242e99e81235a (patch)
tree87f410ef10b3560c71e1443c971ae604fb87899c
parentc3050f4863f5999dbb338b9ba296834527699f8c (diff)
ppu optimization
-rw-r--r--src/main.rs51
-rw-r--r--src/mapper.rs71
-rw-r--r--src/memory.rs64
-rw-r--r--src/ppu.rs107
4 files changed, 143 insertions, 150 deletions
diff --git a/src/main.rs b/src/main.rs
index eb327ac..19364c7 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -19,11 +19,11 @@ use sdl2::rect::Rect;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
-struct Window {
+struct DummyWindow {
buff: RefCell<[[u8; 256]; 240]>
}
-impl ppu::Screen for Window {
+impl ppu::Screen for DummyWindow {
fn put(&self, x: u8, y: u8, color: u8) {
self.buff.borrow_mut()[y as usize][x as usize] = color;
}
@@ -75,20 +75,20 @@ impl SDLWindow {
}
}
-const PIXEL_SIZE: u32 = 4;
-const COLORS: [u32; 64] = [
- 0x666666, 0x002A88, 0x1412A7, 0x3B00A4, 0x5C007E, 0x6E0040, 0x6C0600, 0x561D00,
- 0x333500, 0x0B4800, 0x005200, 0x004F08, 0x00404D, 0x000000, 0x000000, 0x000000,
- 0xADADAD, 0x155FD9, 0x4240FF, 0x7527FE, 0xA01ACC, 0xB71E7B, 0xB53120, 0x994E00,
- 0x6B6D00, 0x388700, 0x0C9300, 0x008F32, 0x007C8D, 0x000000, 0x000000, 0x000000,
- 0xFFFEFF, 0x64B0FF, 0x9290FF, 0xC676FF, 0xF36AFF, 0xFE6ECC, 0xFE8170, 0xEA9E22,
- 0xBCBE00, 0x88D800, 0x5CE430, 0x45E082, 0x48CDDE, 0x4F4F4F, 0x000000, 0x000000,
- 0xFFFEFF, 0xC0DFFF, 0xD3D2FF, 0xE8C8FF, 0xFBC2FF, 0xFEC4EA, 0xFECCC5, 0xF7D8A5,
- 0xE4E594, 0xCFEF96, 0xBDF4AB, 0xB3F3CC, 0xB5EBF2, 0xB8B8B8, 0x000000, 0x000000,
+const PIXEL_SIZE: u32 = 2;
+const RGB_COLORS: [u32; 64] = [
+ 0x666666, 0x002a88, 0x1412a7, 0x3b00a4, 0x5c007e, 0x6e0040, 0x6c0600, 0x561d00,
+ 0x333500, 0x0b4800, 0x005200, 0x004f08, 0x00404d, 0x000000, 0x000000, 0x000000,
+ 0xadadad, 0x155fd9, 0x4240ff, 0x7527fe, 0xa01acc, 0xb71e7b, 0xb53120, 0x994e00,
+ 0x6b6d00, 0x388700, 0x0c9300, 0x008f32, 0x007c8d, 0x000000, 0x000000, 0x000000,
+ 0xfffeff, 0x64b0ff, 0x9290ff, 0xc676ff, 0xf36aff, 0xfe6ecc, 0xfe8170, 0xea9e22,
+ 0xbcbe00, 0x88d800, 0x5ce430, 0x45e082, 0x48cdde, 0x4f4f4f, 0x000000, 0x000000,
+ 0xfffeff, 0xc0dfff, 0xd3d2ff, 0xe8c8ff, 0xfbc2ff, 0xfec4ea, 0xfeccc5, 0xf7d8a5,
+ 0xe4e594, 0xcfef96, 0xbdf4ab, 0xb3f3cc, 0xb5ebf2, 0xb8b8b8, 0x000000, 0x000000,
];
fn get_rgb(color: u8) -> Color {
- let c = COLORS[color as usize];
+ let c = RGB_COLORS[color as usize];
Color::RGB((c >> 16) as u8, ((c >> 8) & 0xff) as u8, (c & 0xff) as u8)
}
@@ -162,19 +162,23 @@ fn main() {
}
let sram = vec![0; 0x4000];
println!("read prg {}", file.read(&mut prg_rom[..]).unwrap());
+ /*
for (i, v) in prg_rom.iter().enumerate() {
print!("{:02x} ", v);
if i & 15 == 15 {
println!(" {:04x}", i);
}
}
+ */
println!("read chr {}", file.read(&mut chr_rom[..]).unwrap());
+ /*
for (i, v) in chr_rom.iter().enumerate() {
print!("{:02x} ", v);
if i & 15 == 15 {
println!("");
}
}
+ */
let cart = cartridge::Cartridge::new(chr_rom, prg_rom, sram, mirror);
//let win = Window {buff: RefCell::new([[0; 256]; 240])};
let win = SDLWindow::new();
@@ -185,33 +189,22 @@ fn main() {
let mut cpu = mos6502::CPU::new(&mem);
mem.init(&mut cpu, &mut ppu);
let mut cnt = 0;
- let mut cnt2 = 0;
- let mut flag = false;
loop {
- if win.poll() {break}
+ if cnt == 1000 {
+ if win.poll() {break}
+ cnt = 0;
+ }
cpu.step();
//println!("cpu at 0x{:04x}", cpu.get_pc());
while cpu.cycle > 0 {
for _ in 0..3 {
- cnt2 += 1;
if ppu.tick() {
println!("triggering nmi");
cpu.trigger_nmi();
}
- if ppu.get_flag_vblank() {
- if !flag {
- println!("{} cpu {} ppu per frame", cnt, cnt2);
- cnt2 = 0;
- cnt = 0;
- flag = true;
- //pmem.dump();
- }
- } else {
- flag = false;
- }
}
cpu.cycle -= 1;
- cnt += 1;
}
+ cnt += 1;
}
}
diff --git a/src/mapper.rs b/src/mapper.rs
index c54acb4..210b59f 100644
--- a/src/mapper.rs
+++ b/src/mapper.rs
@@ -1,61 +1,64 @@
#![allow(dead_code)]
use memory::VMem;
use cartridge::{Cartridge, BankType};
-use core::cell::RefCell;
+use core::cell::UnsafeCell;
pub struct Mapper2<'a> {
cart: &'a Cartridge,
- prg_bank1: RefCell<&'a [u8]>,
- prg_bank2: RefCell<&'a [u8]>,
- chr_bank: RefCell<&'a mut [u8]>,
- sram: RefCell<&'a mut [u8]>,
+ prg_bank1: UnsafeCell<&'a [u8]>,
+ prg_bank2: UnsafeCell<&'a [u8]>,
+ chr_bank: UnsafeCell<&'a mut [u8]>,
+ sram: UnsafeCell<&'a mut [u8]>,
prg_nbank: usize
}
impl<'a> VMem for Mapper2<'a> {
fn read(&self, addr: u16) -> u8 {
let addr = addr as usize;
- if addr < 0x2000 { /* 0x2000 size bank */
- self.chr_bank.borrow()[addr]
- } else if addr >= 0xc000 { /* 0x4000 size bank */
- self.prg_bank2.borrow()[addr - 0xc000]
- } else if addr >= 0x8000 { /* 0x4000 size bank */
- self.prg_bank1.borrow()[addr - 0x8000]
- } else if addr >= 0x6000 {
- self.sram.borrow()[addr - 0x6000]
- } else {
- panic!("unmapped address: 0x{:04x}", addr)
+ unsafe {
+ if addr < 0x2000 { /* 0x2000 size bank */
+ (*self.chr_bank.get())[addr]
+ } else if addr >= 0xc000 { /* 0x4000 size bank */
+ (*self.prg_bank2.get())[addr - 0xc000]
+ } else if addr >= 0x8000 { /* 0x4000 size bank */
+ (*self.prg_bank1.get())[addr - 0x8000]
+ } else if addr >= 0x6000 {
+ (*self.sram.get())[addr - 0x6000]
+ } else {
+ panic!("unmapped address: 0x{:04x}", addr)
+ }
}
}
fn write(&self, addr: u16, data: u8) {
let addr = addr as usize;
- if addr < 0x2000 {
- self.chr_bank.borrow_mut()[addr] = data;
- } else if addr >= 0x8000 {
- (*self.prg_bank1.borrow_mut()) = unsafe {
- &*self.cart.get_bank(((data as usize) % self.prg_nbank) << 14,
- 0x4000,
- BankType::PrgRom)};
- } else if addr >= 0x6000 {
- self.sram.borrow_mut()[addr - 0x6000] = data;
- } else {
- panic!("invalid write to address: 0x{:04x}", addr);
+ unsafe {
+ if addr < 0x2000 {
+ (*self.chr_bank.get())[addr] = data;
+ } else if addr >= 0x8000 {
+ (*self.prg_bank1.get()) =
+ &*self.cart.get_bank(((data as usize) % self.prg_nbank) << 14,
+ 0x4000,
+ BankType::PrgRom);
+ } else if addr >= 0x6000 {
+ (*self.sram.get())[addr - 0x6000] = data;
+ } else {
+ panic!("invalid write to address: 0x{:04x}", addr);
+ }
}
}
}
impl<'a> Mapper2<'a> {
- pub fn new(cart: *const Cartridge) -> Self {
+ pub fn new(cart: &'a Cartridge) -> Self {
unsafe {
- let cart = &*cart;
let nbank = cart.get_size(BankType::PrgRom) >> 14;
- Mapper2{cart: &cart,
- prg_bank1: RefCell::new(&*cart.get_bank(0, 0x4000, BankType::PrgRom)),
- prg_bank2: RefCell::new(&*cart.get_bank((nbank - 1) << 14, 0x4000, BankType::PrgRom)),
- chr_bank: RefCell::new(&mut *cart.get_bank(0, 0x2000, BankType::ChrRom)),
- sram: RefCell::new(&mut *cart.get_bank(0, 0x2000, BankType::Sram)),
- prg_nbank: nbank}
+ Mapper2{cart,
+ prg_bank1: UnsafeCell::new(&*cart.get_bank(0, 0x4000, BankType::PrgRom)),
+ prg_bank2: UnsafeCell::new(&*cart.get_bank((nbank - 1) << 14, 0x4000, BankType::PrgRom)),
+ chr_bank: UnsafeCell::new(&mut *cart.get_bank(0, 0x2000, BankType::ChrRom)),
+ sram: UnsafeCell::new(&mut *cart.get_bank(0, 0x2000, BankType::Sram)),
+ prg_nbank: nbank}
}
}
}
diff --git a/src/memory.rs b/src/memory.rs
index a3e9d70..7d14b61 100644
--- a/src/memory.rs
+++ b/src/memory.rs
@@ -2,7 +2,7 @@
use ppu::PPU;
use mos6502::CPU;
use cartridge::{MirrorType, Cartridge};
-use core::cell::{RefCell, Cell};
+use core::cell::{UnsafeCell, Cell};
use core::ptr::null_mut;
pub trait VMem {
@@ -11,7 +11,7 @@ pub trait VMem {
}
pub struct CPUMemory<'a> {
- sram: RefCell<[u8; 2048]>,
+ sram: UnsafeCell<[u8; 2048]>,
ppu: Cell<*mut PPU<'a>>,
cpu: Cell<*mut CPU<'a>>,
mapper: &'a VMem
@@ -19,7 +19,7 @@ pub struct CPUMemory<'a> {
impl<'a> CPUMemory<'a> {
pub fn new(mapper: &'a VMem) -> Self {
- CPUMemory{sram: RefCell::new([0; 2048]),
+ CPUMemory{sram: UnsafeCell::new([0; 2048]),
cpu: Cell::new(null_mut()),
ppu: Cell::new(null_mut()),
mapper}
@@ -37,7 +37,7 @@ impl<'a> VMem for CPUMemory<'a> {
fn read(&self, addr: u16) -> u8 {
match addr {
_ => if addr < 0x2000 {
- self.sram.borrow()[(addr & 0x07ff) as usize]
+ unsafe{(*self.sram.get())[(addr & 0x07ff) as usize]}
} else if addr < 0x4000 {
let ppu = unsafe {&mut *self.ppu.get()};
match addr & 0x7 {
@@ -47,7 +47,6 @@ impl<'a> VMem for CPUMemory<'a> {
_ => 0
}
} else if addr < 0x6000 {
- println!("feeding dummy data for 0x{:04x}", addr);
0
} else {
self.mapper.read(addr)
@@ -58,7 +57,7 @@ impl<'a> VMem for CPUMemory<'a> {
let ppu = unsafe {&mut *self.ppu.get()};
let cpu = unsafe {&mut *self.cpu.get()};
if addr < 0x2000 {
- self.sram.borrow_mut()[(addr & 0x07ff) as usize] = data;
+ unsafe{(*self.sram.get())[(addr & 0x07ff) as usize] = data;}
} else if addr < 0x4000 {
match addr & 0x7 {
0x0 => ppu.write_ctl(data),
@@ -83,9 +82,8 @@ impl<'a> VMem for CPUMemory<'a> {
}
pub struct PPUMemory<'a> {
- pattern_table: RefCell<[u8; 0x2000]>,
- nametable: RefCell<[u8; 0x800]>,
- palette: RefCell<[u8; 0x20]>,
+ nametable: UnsafeCell<[u8; 0x800]>,
+ palette: UnsafeCell<[u8; 0x20]>,
cart: &'a Cartridge,
mapper: &'a VMem,
}
@@ -94,21 +92,22 @@ impl<'a> PPUMemory<'a> {
pub fn new(mapper: &'a VMem,
cart: &'a Cartridge) -> Self {
PPUMemory{
- pattern_table: RefCell::new([0; 0x2000]),
- nametable: RefCell::new([0; 0x800]),
- palette: RefCell::new([0; 0x20]),
+ nametable: UnsafeCell::new([0; 0x800]),
+ palette: UnsafeCell::new([0; 0x20]),
cart,
mapper}
}
pub fn dump(&self) {
- for (i, v) in self.palette.borrow().iter().enumerate() {
- print!("{:02x} ", *v);
- if (i & 0x7) == 0x7 {println!("@{:02x}", i)}
- }
- for (i, v) in self.nametable.borrow().iter().enumerate() {
- print!("{:02x} ", *v);
- if (i & 0x1f) == 0x1f {println!("@{:02x}", i)}
+ unsafe {
+ for (i, v) in (*self.palette.get()).iter().enumerate() {
+ print!("{:02x} ", *v);
+ if (i & 0x7) == 0x7 {println!("@{:02x}", i)}
+ }
+ for (i, v) in (*self.nametable.get()).iter().enumerate() {
+ print!("{:02x} ", *v);
+ if (i & 0x1f) == 0x1f {println!("@{:02x}", i)}
+ }
}
}
}
@@ -121,6 +120,7 @@ const MIRROR_IDX: [[u8; 4]; 5] = [
[0, 1, 2, 3],
];
+#[inline(always)]
fn get_mirror_addr(kind: MirrorType, mut addr: u16) -> u16 {
addr = (addr - 0x2000) & 0x0fff;
let table = addr >> 10;
@@ -128,7 +128,8 @@ fn get_mirror_addr(kind: MirrorType, mut addr: u16) -> u16 {
0x2000 + ((MIRROR_IDX[kind as usize][table as usize] as u16) << 10) + offset
}
-fn mirror_palette(addr: u16) -> u16 {
+#[inline(always)]
+fn get_mirror_palette(addr: u16) -> u16 {
if addr >= 0x10 && addr & 3 == 0 {
addr - 0x10
} else { addr }
@@ -141,11 +142,15 @@ impl<'a> VMem for PPUMemory<'a> {
self.mapper.read(addr)
} else if addr < 0x3f00 {
let kind = self.cart.mirror_type;
- self.nametable.borrow()
+ unsafe {
+ (*self.nametable.get())
[(get_mirror_addr(kind, addr) & 0x07ff) as usize]
+ }
} else if addr < 0x4000 {
- self.palette.borrow()
- [mirror_palette(addr & 0x1f) as usize]
+ unsafe {
+ (*self.palette.get())
+ [get_mirror_palette(addr & 0x1f) as usize]
+ }
} else {
panic!("invalid ppu read access at 0x{:04x}", addr)
}
@@ -153,16 +158,19 @@ impl<'a> VMem for PPUMemory<'a> {
fn write(&self, mut addr: u16, data: u8) {
addr &= 0x3fff;
- println!("writing 0x{:02x} to 0x{:04x}", data, addr);
if addr < 0x2000 {
self.mapper.write(addr, data)
} else if addr < 0x3f00 {
let kind = self.cart.mirror_type;
- self.nametable.borrow_mut()
- [(get_mirror_addr(kind, addr) & 0x07ff) as usize] = data
+ unsafe {
+ (*self.nametable.get())
+ [(get_mirror_addr(kind, addr) & 0x07ff) as usize] = data;
+ }
} else if addr < 0x4000 {
- self.palette.borrow_mut()
- [mirror_palette(addr & 0x1f) as usize] = data
+ unsafe {
+ (*self.palette.get())
+ [get_mirror_palette(addr & 0x1f) as usize] = data;
+ }
} else {
panic!("invalid ppu write access at 0x{:04x}", addr)
}
diff --git a/src/ppu.rs b/src/ppu.rs
index 7f8a39d..8daf009 100644
--- a/src/ppu.rs
+++ b/src/ppu.rs
@@ -34,8 +34,7 @@ pub struct PPU<'a> {
cycle: u16, /* cycle in the current scanline */
/* rendering regs & latches */
/* background registers */
- bg_bitmap: [u16; 2],
- bg_palette: [u16; 2],
+ bg_pixel: u64,
/* background latches */
bg_nt: u8,
bg_attr: u8,
@@ -44,7 +43,7 @@ pub struct PPU<'a> {
/* sprites */
oam: [Sprite; 64],
oam2: [usize; 8],
- sp_bitmap: [[u8; 2]; 8],
+ sp_pixel: [u32; 8],
sp_idx: [usize; 8],
sp_cnt: [u8; 8],
rendering: bool,
@@ -56,17 +55,20 @@ pub struct PPU<'a> {
}
impl<'a> PPU<'a> {
+ #[inline]
pub fn write_ctl(&mut self, data: u8) {
self.reg = data;
self.ppuctl = data;
self.t = (self.t & 0x73ff) | ((data as u16 & 3) << 10);
}
+ #[inline]
pub fn write_mask(&mut self, data: u8) {
self.reg = data;
self.ppumask = data;
}
+ #[inline]
pub fn read_status(&mut self) -> u8 {
let res = (self.ppustatus & !0x1fu8) | (self.reg & 0x1f);
self.ppustatus &= !PPU::FLAG_VBLANK;
@@ -77,11 +79,13 @@ impl<'a> PPU<'a> {
res
}
+ #[inline]
pub fn write_oamaddr(&mut self, data: u8) {
self.reg = data;
self.oamaddr = data;
}
+ #[inline]
pub fn write_oamdata(&mut self, data: u8) {
self.reg = data;
if self.rendering { return }
@@ -92,6 +96,7 @@ impl<'a> PPU<'a> {
}
}
+ #[inline]
pub fn read_oamdata(&self) -> u8 {
unsafe {
let oam_raw = transmute::<&[Sprite; 64], &[u8; 256]>(&self.oam);
@@ -99,6 +104,7 @@ impl<'a> PPU<'a> {
}
}
+ #[inline]
pub fn write_scroll(&mut self, data: u8) {
self.reg = data;
let data = data as u16;
@@ -116,6 +122,7 @@ impl<'a> PPU<'a> {
}
}
+ #[inline]
pub fn write_addr(&mut self, data: u8) {
self.reg = data;
let data = data as u16;
@@ -132,6 +139,7 @@ impl<'a> PPU<'a> {
}
}
+ #[inline]
pub fn read_data(&mut self) -> u8 {
let data = self.mem.read(self.v);
let res = if self.v & 0x3fff < 0x3f00 {
@@ -149,6 +157,7 @@ impl<'a> PPU<'a> {
res
}
+ #[inline]
pub fn write_data(&mut self, data: u8) {
self.reg = data;
self.mem.write(self.v, data);
@@ -158,6 +167,7 @@ impl<'a> PPU<'a> {
});
}
+ #[inline]
pub fn write_oamdma(&mut self, data: u8, cpu: &mut CPU) {
self.reg = data;
let mut addr = (data as u16) << 8;
@@ -182,6 +192,7 @@ impl<'a> PPU<'a> {
#[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;
@@ -224,19 +235,16 @@ impl<'a> PPU<'a> {
fn load_bgtile(&mut self) {
/* load the tile bitmap to high 8 bits of bitmap,
* assume the high 8 bits are zeros */
- //if (!(self.bg_bitmap[0] >> 8 == 0 &&
- // self.bg_bitmap[1] >> 8 == 0 &&
- // 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);
- 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;
- self.bg_palette[1] |= ((self.bg_attr >> 1) & 1) as u16 * 0xff00;
+ assert!(self.bg_pixel >> 32 == 0);
+ let mut t: u64 = 0;
+ let mut bl = self.bg_bit_low;
+ let mut bh = self.bg_bit_high;
+ for _ in 0..8 {
+ t = (t << 4) | ((self.bg_attr << 2) | (bl & 1) | ((bh & 1) << 1)) as u64;
+ bl >>= 1;
+ bh >>= 1;
+ }
+ self.bg_pixel |= t << 32;
}
#[inline(always)]
@@ -245,11 +253,7 @@ impl<'a> PPU<'a> {
if self.sp_idx[i] > 0xff { break }
let c0 = *c;
match c0 {
- 0 => {
- let t = &mut self.sp_bitmap[i];
- t[0] = t[0].wrapping_shr(1);
- t[1] = t[1].wrapping_shr(1);
- },
+ 0 => self.sp_pixel[i] >>= 4,
_ => *c = c0 - 1
}
}
@@ -257,12 +261,7 @@ impl<'a> PPU<'a> {
#[inline(always)]
fn shift_bgtile(&mut self) {
- let t1 = &mut self.bg_bitmap;
- let t2 = &mut self.bg_palette;
- 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);
+ self.bg_pixel >>= 4;
}
#[inline(always)]
@@ -381,44 +380,39 @@ impl<'a> PPU<'a> {
self.sp_cnt[i] = s.x;
let mut low = self.mem.read(ptable | ((tidx as u16) << 4) | 0x0 | y as u16);
let mut high = self.mem.read(ptable | ((tidx as u16) << 4) | 0x8 | y as u16);
- if (s.attr & 0x40) != 0x40 {
+ if (s.attr & 0x40) == 0x40 {
low = PPU::reverse_byte(low);
high = PPU::reverse_byte(high);
}
- self.sp_bitmap[i][0] = low;
- self.sp_bitmap[i][1] = high;
+ let attr = s.attr & 3;
+ let mut t = 0u32;
+ for _ in 0..8 {
+ t = (t << 4) | ((attr << 2) | ((high & 1) << 1) | (low & 1)) as u32;
+ high >>= 1;
+ low >>= 1;
+ }
+ self.sp_pixel[i] = t;
}
}
- #[inline(always)]
- fn get_bg_pidx(&self) -> u8 {
- if self.get_show_bg() {
- (((self.bg_bitmap[1] >> self.x) & 1) << 1) as u8 |
- ((self.bg_bitmap[0] >> self.x) & 1) as u8
- } else { 0 }
- }
-
- #[inline(always)]
- fn get_sp_pidx(&self, i: usize) -> u8 {
- if self.get_show_sp() {
- ((self.sp_bitmap[i][1] & 1) << 1) | (self.sp_bitmap[i][0] & 1)
- } else { 0 }
- }
-
fn render_pixel(&mut self) {
let x = self.cycle - 1;
+ let bg = ((self.bg_pixel >> (self.x << 2)) & 0xf) as u16;
let bg_pidx =
- if x >= 8 || self.get_show_leftmost_bg() {self.get_bg_pidx()}
- else {0};
+ if x >= 8 || self.get_show_leftmost_bg() {
+ if self.get_show_bg() {bg & 3} else {0}
+ } else {0};
let mut sp_pidx = 0x0;
- let mut sp_id = 0;
let mut pri = 0x1;
+ let mut sp = 0;
+ let show_sp = self.get_show_sp();
if x >= 8 || self.get_show_leftmost_sp() {
for i in 0..8 {
if self.sp_idx[i] > 0xff { break }
- let s = &self.oam[self.sp_idx[i]];
if self.sp_cnt[i] != 0 { continue; } /* not active */
- match self.get_sp_pidx(i) {
+ let s = &self.oam[self.sp_idx[i]];
+ sp = if show_sp {(self.sp_pixel[i] & 0xf) as u16} else { 0 };
+ match sp & 3 {
0x0 => (),
pidx => {
if bg_pidx != 0 && self.sp_idx[i] == 0 &&
@@ -426,7 +420,6 @@ impl<'a> PPU<'a> {
self.ppustatus |= PPU::FLAG_SPRITE_ZERO; /* set sprite zero hit */
}
sp_pidx = pidx;
- sp_id = i;
pri = (s.attr >> 5) & 1;
break;
}
@@ -438,14 +431,11 @@ impl<'a> PPU<'a> {
self.scr.put((self.cycle - 1) as u8,
self.scanline as u8,
self.mem.read(if (pri == 0 || bg_pidx == 0) && sp_pidx != 0 {
- 0x3f10 | ((self.oam[self.sp_idx[sp_id]].attr & 3) << 2) as u16 |
- sp_pidx as u16
+ 0x3f10 | sp
} else {
0x3f00 | match bg_pidx {
0 => 0,
- _ => ((((self.bg_palette[1] >> self.x) & 1) << 3) |
- (((self.bg_palette[0] >> self.x) & 1) << 2)) as u16 |
- bg_pidx as u16
+ _ => bg
}
}));
}
@@ -467,14 +457,13 @@ impl<'a> PPU<'a> {
oamaddr,
reg: 0,
x: 0, v: 0, t: 0, w, cycle,
- bg_bitmap: [0; 2],
- bg_palette: [0; 2],
+ bg_pixel: 0,
bg_nt: 0, bg_attr: 0,
bg_bit_low: 0, bg_bit_high: 0,
oam: [Sprite{y: 0, tile: 0, attr: 0, x: 0}; 64],
oam2: [0x100; 8],
sp_idx: [0x100; 8],
- sp_bitmap: [[0; 2]; 8],
+ sp_pixel: [0; 8],
sp_cnt: [0; 8],
rendering: false,
buffered_read,