From 3f4374747416b8158875b8777900a67fb8e13fe4 Mon Sep 17 00:00:00 2001 From: Tim Allen Date: Sun, 5 Sep 2010 23:22:26 +1000 Subject: [PATCH] Update to v068r13 release. byuu says: Bug-fix night for the new PPUs. Accuracy: Fixed BG palette clamping, which fixes Taz-Mania. Added blocking for CGRAM writes during active display, to match the compatibility core. It really should override to the last fetched palette color, I'll probably try that out soon enough. Performance: Mosaic should match the other renderers. Unfortunately, as suspected, it murders speed. 290->275fps. It's now only 11fps faster, hardly worth it at all. But the old rendering code is really awful, so maybe it's for the best it gets refreshed. It's really tough to understand why this is such a performance hit, it's just a decrement+compare check four times per pixel. But yeah, it hits it really, really hard. Fixed a missing check in Mode4 offset-per-tile, fixes vertical alignment of a test image in the SNES Test Program. --- bsnes/Makefile | 2 +- .../alt/ppu-new/background/background.cpp | 95 ++++++++++--------- .../alt/ppu-new/background/background.hpp | 5 +- bsnes/snes/alt/ppu-new/mmio/mmio.cpp | 4 - bsnes/snes/alt/ppu-new/ppu.cpp | 2 +- bsnes/snes/ppu/background/background.hpp | 4 +- bsnes/snes/ppu/mmio/mmio.cpp | 6 ++ bsnes/snes/ppu/sprite/sprite.hpp | 2 +- bsnes/snes/snes.hpp | 2 +- 9 files changed, 66 insertions(+), 56 deletions(-) diff --git a/bsnes/Makefile b/bsnes/Makefile index da0794e7..760ea410 100755 --- a/bsnes/Makefile +++ b/bsnes/Makefile @@ -1,6 +1,6 @@ include nall/Makefile snes := snes -profile := accuracy +profile := performance ui := qt # compiler diff --git a/bsnes/snes/alt/ppu-new/background/background.cpp b/bsnes/snes/alt/ppu-new/background/background.cpp index 1d48954c..4795920d 100755 --- a/bsnes/snes/alt/ppu-new/background/background.cpp +++ b/bsnes/snes/alt/ppu-new/background/background.cpp @@ -3,18 +3,18 @@ #include "mode7.cpp" unsigned PPU::Background::get_tile(unsigned hoffset, unsigned voffset) { - unsigned tile_x = hoffset >> tile_width; - unsigned tile_y = voffset >> tile_height; + unsigned tile_x = (hoffset & mask_x) >> tile_width; + unsigned tile_y = (voffset & mask_y) >> tile_height; unsigned tile_pos = ((tile_y & 0x1f) << 5) + (tile_x & 0x1f); if(tile_y & 0x20) tile_pos += scy; if(tile_x & 0x20) tile_pos += scx; - const unsigned tiledata_addr = regs.screen_addr + (tile_pos << 1); + const uint16 tiledata_addr = regs.screen_addr + (tile_pos << 1); return (memory::vram[tiledata_addr + 0] << 0) + (memory::vram[tiledata_addr + 1] << 8); } -void PPU::Background::offset_per_tile(unsigned x, unsigned &hoffset, unsigned &voffset) { +void PPU::Background::offset_per_tile(unsigned x, unsigned y, unsigned &hoffset, unsigned &voffset) { unsigned opt_x = (x + (hscroll & 7)), hval, vval; if(opt_x >= 8) { hval = self.bg3.get_tile((opt_x - 8) + (self.bg3.regs.hoffset & ~7), self.bg3.regs.voffset + 0); @@ -23,9 +23,11 @@ void PPU::Background::offset_per_tile(unsigned x, unsigned &hoffset, unsigned &v if(self.regs.bgmode == 4) { if(hval & opt_valid_bit) { - hoffset = opt_x + (hval & ~7); - } else { - voffset = y + hval; + if(!(hval & 0x8000)) { + hoffset = opt_x + (hval & ~7); + } else { + voffset = y + hval; + } } } else { if(hval & opt_valid_bit) { @@ -39,7 +41,15 @@ void PPU::Background::offset_per_tile(unsigned x, unsigned &hoffset, unsigned &v } void PPU::Background::scanline() { - y = mosaic_table[regs.mosaic][self.vcounter()] + (regs.mosaic > 0); + if(self.vcounter() == 1) { + mosaic_vcounter = regs.mosaic + 1; + y = 1; + } else if(--mosaic_vcounter == 0) { + mosaic_vcounter = regs.mosaic + 1; + y += regs.mosaic + 1; + } + if(self.regs.display_disable) return; + hires = (self.regs.bgmode == 5 || self.regs.bgmode == 6); width = !hires ? 256 : 512; @@ -66,6 +76,11 @@ void PPU::Background::render() { if(regs.sub_enable) window.render(1); if(regs.mode == Mode::Mode7) return render_mode7(); + unsigned mosaic_hcounter = 1; + unsigned mosaic_palette = 0; + unsigned mosaic_priority = 0; + unsigned mosaic_color = 0; + const unsigned bgpal_index = (self.regs.bgmode == 0 ? id << 5 : 0); const unsigned pal_size = 2 << regs.mode; const unsigned tile_mask = 0x0fff >> regs.mode; @@ -74,6 +89,7 @@ void PPU::Background::render() { hscroll = regs.hoffset; vscroll = regs.voffset; + unsigned y = Background::y; if(hires) { hscroll <<= 1; if(self.regs.interlace) y = (y << 1) + self.field(); @@ -91,7 +107,7 @@ void PPU::Background::render() { while(x < width) { hoffset = x + hscroll; voffset = y + vscroll; - if(is_opt_mode) offset_per_tile(x, hoffset, voffset); + if(is_opt_mode) offset_per_tile(x, y, hoffset, voffset); hoffset &= mask_x; voffset &= mask_y; @@ -100,53 +116,44 @@ void PPU::Background::render() { mirror_x = tile_num & 0x4000; tile_pri = tile_num & 0x2000 ? regs.priority1 : regs.priority0; pal_num = (tile_num >> 10) & 7; - pal_index = bgpal_index + (pal_num << pal_size); + pal_index = (bgpal_index + (pal_num << pal_size)) & 0xff; - if(tile_width == 4) { - if((bool)(hoffset & 8) != mirror_x) tile_num++; - } - - if(tile_height == 4) { - if((bool)(voffset & 8) != mirror_y) tile_num += 16; - } - - tile_num &= 0x03ff; - tile_num += tiledata_index; - tile_num &= tile_mask; + if(tile_width == 4 && (bool)(hoffset & 8) != mirror_x) tile_num += 1; + if(tile_height == 4 && (bool)(voffset & 8) != mirror_y) tile_num += 16; + tile_num = ((tile_num & 0x03ff) + tiledata_index) & tile_mask; if(mirror_y) voffset ^= 7; - signed step = mirror_x ? -1 : +1; - unsigned plot_x = x + (mirror_x ? 7 : 0); + unsigned mirror_xmask = !mirror_x ? 0 : 7; uint8 *tiledata = self.cache.tile(regs.mode, tile_num); tiledata += ((voffset & 7) * 8); - for(unsigned n = 0; n < 8; n++) { - unsigned col = tiledata[n & regs.mosaic_mask]; - if(col && !(plot_x & width)) { - unsigned color; + for(unsigned n = 0; n < 8; n++, x++) { + if(x & width) continue; + if(--mosaic_hcounter == 0) { + mosaic_hcounter = regs.mosaic + 1; + mosaic_palette = tiledata[n ^ mirror_xmask]; + mosaic_priority = tile_pri; if(is_direct_color_mode) { - color = self.screen.get_direct_color(pal_num, col); + mosaic_color = self.screen.get_direct_color(pal_num, mosaic_palette); } else { - color = self.screen.get_palette(pal_index + col); - } - - if(hires == false) { - if(regs.main_enable && !window.main[plot_x]) self.screen.output.plot_main(plot_x, color, tile_pri, id); - if(regs.sub_enable && !window.sub[plot_x]) self.screen.output.plot_sub(plot_x, color, tile_pri, id); - } else { - signed half_x = plot_x >> 1; - if(plot_x & 1) { - if(regs.main_enable && !window.main[half_x]) self.screen.output.plot_main(half_x, color, tile_pri, id); - } else { - if(regs.sub_enable && !window.sub[half_x]) self.screen.output.plot_sub(half_x, color, tile_pri, id); - } + mosaic_color = self.screen.get_palette(pal_index + mosaic_palette); } } - plot_x += step; - } + if(mosaic_palette == 0) continue; - x += 8; + if(hires == false) { + if(regs.main_enable && !window.main[x]) self.screen.output.plot_main(x, mosaic_color, mosaic_priority, id); + if(regs.sub_enable && !window.sub[x]) self.screen.output.plot_sub(x, mosaic_color, mosaic_priority, id); + } else { + signed half_x = x >> 1; + if(x & 1) { + if(regs.main_enable && !window.main[half_x]) self.screen.output.plot_main(half_x, mosaic_color, mosaic_priority, id); + } else { + if(regs.sub_enable && !window.sub[half_x]) self.screen.output.plot_sub(half_x, mosaic_color, mosaic_priority, id); + } + } + } } } diff --git a/bsnes/snes/alt/ppu-new/background/background.hpp b/bsnes/snes/alt/ppu-new/background/background.hpp index 3289e1dc..f4923f71 100755 --- a/bsnes/snes/alt/ppu-new/background/background.hpp +++ b/bsnes/snes/alt/ppu-new/background/background.hpp @@ -11,7 +11,6 @@ class Background { bool tile_size; unsigned mosaic; - unsigned mosaic_mask; unsigned screen_addr; unsigned screen_size; @@ -45,10 +44,12 @@ class Background { unsigned hscroll; unsigned vscroll; + unsigned mosaic_vcounter; + LayerWindow window; alwaysinline unsigned get_tile(unsigned hoffset, unsigned voffset); - void offset_per_tile(unsigned x, unsigned &hoffset, unsigned &voffset); + void offset_per_tile(unsigned x, unsigned y, unsigned &hoffset, unsigned &voffset); void scanline(); void render(); void render_mode7(); diff --git a/bsnes/snes/alt/ppu-new/mmio/mmio.cpp b/bsnes/snes/alt/ppu-new/mmio/mmio.cpp index 9a1de202..092f8bdf 100755 --- a/bsnes/snes/alt/ppu-new/mmio/mmio.cpp +++ b/bsnes/snes/alt/ppu-new/mmio/mmio.cpp @@ -341,10 +341,6 @@ void PPU::mmio_write(unsigned addr, uint8 data) { bg3.regs.mosaic = (data & 0x04 ? mosaic_size : 0); bg2.regs.mosaic = (data & 0x02 ? mosaic_size : 0); bg1.regs.mosaic = (data & 0x01 ? mosaic_size : 0); - bg4.regs.mosaic_mask = ~(bg4.regs.mosaic >> 1); - bg3.regs.mosaic_mask = ~(bg3.regs.mosaic >> 1); - bg2.regs.mosaic_mask = ~(bg2.regs.mosaic >> 1); - bg1.regs.mosaic_mask = ~(bg1.regs.mosaic >> 1); return; } diff --git a/bsnes/snes/alt/ppu-new/ppu.cpp b/bsnes/snes/alt/ppu-new/ppu.cpp index 9372f4a3..bdf6d6d2 100755 --- a/bsnes/snes/alt/ppu-new/ppu.cpp +++ b/bsnes/snes/alt/ppu-new/ppu.cpp @@ -56,11 +56,11 @@ void PPU::add_clocks(unsigned clocks) { } void PPU::render_scanline() { - if(regs.display_disable) return screen.render_black(); bg1.scanline(); bg2.scanline(); bg3.scanline(); bg4.scanline(); + if(regs.display_disable) return screen.render_black(); screen.scanline(); bg1.render(); bg2.render(); diff --git a/bsnes/snes/ppu/background/background.hpp b/bsnes/snes/ppu/background/background.hpp index faa24f59..fc315068 100755 --- a/bsnes/snes/ppu/background/background.hpp +++ b/bsnes/snes/ppu/background/background.hpp @@ -27,8 +27,8 @@ class Background { struct Output { struct Pixel { unsigned priority; //0 = none (transparent) - unsigned palette; - unsigned tile; + uint8 palette; + uint16 tile; } main, sub; } output; diff --git a/bsnes/snes/ppu/mmio/mmio.cpp b/bsnes/snes/ppu/mmio/mmio.cpp index 9490eb85..74b4569e 100755 --- a/bsnes/snes/ppu/mmio/mmio.cpp +++ b/bsnes/snes/ppu/mmio/mmio.cpp @@ -45,10 +45,16 @@ void PPU::oam_write(unsigned addr, uint8 data) { } uint8 PPU::cgram_read(unsigned addr) { + if(!regs.display_disable && vcounter() < (!regs.overscan ? 225 : 240)) { + if(hcounter() >= 128 && hcounter() < 1096) addr = 0x0000; + } return memory::cgram[addr]; } void PPU::cgram_write(unsigned addr, uint8 data) { + if(!regs.display_disable && vcounter() < (!regs.overscan ? 225 : 240)) { + if(hcounter() >= 128 && hcounter() < 1096) addr = 0x0000; + } memory::cgram[addr] = data; } diff --git a/bsnes/snes/ppu/sprite/sprite.hpp b/bsnes/snes/ppu/sprite/sprite.hpp index 8383d2c9..dad5924d 100755 --- a/bsnes/snes/ppu/sprite/sprite.hpp +++ b/bsnes/snes/ppu/sprite/sprite.hpp @@ -55,7 +55,7 @@ class Sprite { struct Output { struct Pixel { unsigned priority; //0 = none (transparent) - unsigned palette; + uint8 palette; } main, sub; } output; diff --git a/bsnes/snes/snes.hpp b/bsnes/snes/snes.hpp index b6d0427e..b87209e4 100755 --- a/bsnes/snes/snes.hpp +++ b/bsnes/snes/snes.hpp @@ -1,7 +1,7 @@ namespace SNES { namespace Info { static const char Name[] = "bsnes"; - static const char Version[] = "068.12"; + static const char Version[] = "068.13"; static const unsigned SerializerVersion = 13; } }