From 39b1acb177ebc46a1837dec47549530d001601bd Mon Sep 17 00:00:00 2001 From: Tim Allen Date: Sat, 28 Aug 2010 19:47:06 +1000 Subject: [PATCH] Update to v068r02 release. byuu says: This adds mosaic improvements to the S-PPU dot renderer. Specifically, it eliminates the mosaic_table entirely, and performs mosaic adjustment per pixel instead. It also moves from a mosaic countdown for mosaic Y to a mosaic counter (incrementing). In the process, I realized Sim Earth's map was broken, so I fixed that. In doing so, I also fixed my old Mode7 demo that was always off-by-one, causing different results on real hardware versus emulation. But then I broke both Final Fantasy 5 and Air Strike Patrol effects that use Mode7 but no mosaic. I'm not really sure what's going on, but I think I am close. This is the first time I can reproduce the Mode7 test ROM results without screwing with M7Y which was obviously wrong. I think that somehow a mosaic >= 1 is glitching the Ycounter for the BG layers to tick one extra time. There's a workaround that's not very nice to get everything going right now. It could very well be that the workaround is hardware accurate, but I can't help but feel there's a more eloquent way of doing this. --- bsnes/Makefile | 2 +- bsnes/snes/ppu/background/background.cpp | 44 ++++++++++++++---------- bsnes/snes/ppu/background/background.hpp | 10 +++--- bsnes/snes/ppu/background/mode7.cpp | 22 ++++-------- bsnes/snes/ppu/ppu.cpp | 9 ++++- bsnes/snes/ppu/serialization.cpp | 5 +-- bsnes/snes/snes.hpp | 6 ++-- 7 files changed, 52 insertions(+), 46 deletions(-) diff --git a/bsnes/Makefile b/bsnes/Makefile index 2dedd988..394e75db 100755 --- a/bsnes/Makefile +++ b/bsnes/Makefile @@ -1,6 +1,6 @@ include nall/Makefile snes := snes -profile := compatibility +profile := accuracy ui := qt # compiler diff --git a/bsnes/snes/ppu/background/background.cpp b/bsnes/snes/ppu/background/background.cpp index 7010068d..ec44c906 100755 --- a/bsnes/snes/ppu/background/background.cpp +++ b/bsnes/snes/ppu/background/background.cpp @@ -2,20 +2,26 @@ #include "mode7.cpp" +void PPU::Background::frame() { +} + void PPU::Background::scanline() { if(self.vcounter() == 1) { - t.mosaic_y = 1; - t.mosaic_countdown = 0; - } else { - if(!regs.mosaic || !t.mosaic_countdown) t.mosaic_y = self.vcounter(); - if(!t.mosaic_countdown) t.mosaic_countdown = regs.mosaic + 1; - t.mosaic_countdown--; + t.mosaic_y = regs.mosaic ? 1 : 0; //TODO: this is most likely incorrect + t.mosaic_vcounter = 0; } - t.x = 0; + if(t.mosaic_vcounter++ == regs.mosaic) { + t.mosaic_vcounter = 0; + t.mosaic_y += regs.mosaic + 1; + } + + t.mosaic_x = 0; + t.mosaic_hcounter = 0; } void PPU::Background::run() { + if(self.vcounter() == 0) return; bool hires = (self.regs.bgmode == 5 || self.regs.bgmode == 6); if((self.hcounter() & 2) == 0) { @@ -28,9 +34,13 @@ void PPU::Background::run() { if(regs.mode == Mode::Inactive) return; if(regs.main_enabled == false && regs.sub_enabled == false) return; - unsigned x = t.x++; + unsigned x = t.mosaic_x; unsigned y = t.mosaic_y; - if(regs.mode == Mode::Mode7) return run_mode7(x, y); + if(t.mosaic_hcounter++ == regs.mosaic) { + t.mosaic_hcounter = 0; + t.mosaic_x += regs.mosaic + 1; + } + if(regs.mode == Mode::Mode7) return run_mode7(); unsigned color_depth = (regs.mode == Mode::BPP2 ? 0 : regs.mode == Mode::BPP4 ? 1 : 2); unsigned palette_offset = (self.regs.bgmode == 0 ? (id << 5) : 0); @@ -56,7 +66,7 @@ void PPU::Background::run() { if(self.regs.interlace) y = (y << 1) + self.field(); } - unsigned hoffset = hscroll + mosaic_table[regs.mosaic][x]; + unsigned hoffset = hscroll + x; unsigned voffset = vscroll + y; if(self.regs.bgmode == 2 || self.regs.bgmode == 4 || self.regs.bgmode == 6) { @@ -215,9 +225,11 @@ unsigned PPU::Background::get_color(unsigned x, unsigned y, uint16 offset) { } void PPU::Background::reset() { - t.x = 0; + t.mosaic_x = 0; t.mosaic_y = 0; - t.mosaic_countdown = 0; + t.mosaic_hcounter = 0; + t.mosaic_vcounter = 0; + regs.tiledata_addr = 0; regs.screen_addr = 0; regs.screen_size = 0; @@ -230,6 +242,7 @@ void PPU::Background::reset() { regs.sub_enabled = 0; regs.hoffset = 0; regs.voffset = 0; + output.main.palette = 0; output.main.priority = 0; output.sub.palette = 0; @@ -237,13 +250,6 @@ void PPU::Background::reset() { } PPU::Background::Background(PPU &self, unsigned id) : self(self), id(id) { - for(unsigned m = 0; m < 16; m++) { - for(unsigned x = 0; x < 4096; x++) { - mosaic_table[m][x] = (x / (m + 1)) * (m + 1); - } - } } -uint16 PPU::Background::mosaic_table[16][4096]; - #endif diff --git a/bsnes/snes/ppu/background/background.hpp b/bsnes/snes/ppu/background/background.hpp index 0849022e..8e2ad81b 100755 --- a/bsnes/snes/ppu/background/background.hpp +++ b/bsnes/snes/ppu/background/background.hpp @@ -9,9 +9,10 @@ public: struct TileSize { enum { Size8x8, Size16x16 }; }; struct { - unsigned x; + unsigned mosaic_x; unsigned mosaic_y; - unsigned mosaic_countdown; + unsigned mosaic_hcounter; + unsigned mosaic_vcounter; } t; struct { @@ -40,6 +41,7 @@ public: } main, sub; } output; + void frame(); void scanline(); void run(); unsigned get_tile(unsigned x, unsigned y); @@ -50,9 +52,7 @@ public: Background(PPU &self, unsigned id); private: - static uint16 mosaic_table[16][4096]; - //mode7.cpp signed clip(signed n); - void run_mode7(unsigned x, unsigned y); + void run_mode7(); }; diff --git a/bsnes/snes/ppu/background/mode7.cpp b/bsnes/snes/ppu/background/mode7.cpp index c370fd67..cb8dcac6 100755 --- a/bsnes/snes/ppu/background/mode7.cpp +++ b/bsnes/snes/ppu/background/mode7.cpp @@ -5,7 +5,7 @@ signed PPU::Background::clip(signed n) { return n & 0x2000 ? (n | ~1023) : (n & 1023); } -void PPU::Background::run_mode7(unsigned x, unsigned y) { +void PPU::Background::run_mode7() { signed a = sclip<16>(self.regs.m7a); signed b = sclip<16>(self.regs.m7b); signed c = sclip<16>(self.regs.m7c); @@ -16,24 +16,16 @@ void PPU::Background::run_mode7(unsigned x, unsigned y) { signed hoffset = sclip<13>(self.regs.mode7_hoffset); signed voffset = sclip<13>(self.regs.mode7_voffset); + unsigned x = t.mosaic_x; + unsigned y = self.bg1.t.mosaic_y; //BG2 vertical mosaic uses BG1 mosaic size if(self.regs.mode7_hflip) x = 255 - x; if(self.regs.mode7_vflip) y = 255 - y; - unsigned mosaic_x; - unsigned mosaic_y; - if(id == ID::BG1) { - mosaic_x = mosaic_table[self.bg1.regs.mosaic][x]; - mosaic_y = mosaic_table[self.bg1.regs.mosaic][y]; - } else if(id == ID::BG2) { - mosaic_x = mosaic_table[self.bg2.regs.mosaic][x]; - mosaic_y = mosaic_table[self.bg1.regs.mosaic][y]; //BG2 vertical mosaic uses BG1 mosaic size - } + signed psx = ((a * clip(hoffset - cx)) & ~63) + ((b * clip(voffset - cy)) & ~63) + ((b * y) & ~63) + (cx << 8); + signed psy = ((c * clip(hoffset - cx)) & ~63) + ((d * clip(voffset - cy)) & ~63) + ((d * y) & ~63) + (cy << 8); - signed psx = ((a * clip(hoffset - cx)) & ~63) + ((b * clip(voffset - cy)) & ~63) + ((b * mosaic_y) & ~63) + (cx << 8); - signed psy = ((c * clip(hoffset - cx)) & ~63) + ((d * clip(voffset - cy)) & ~63) + ((d * mosaic_y) & ~63) + (cy << 8); - - signed px = psx + (a * mosaic_x); - signed py = psy + (c * mosaic_x); + signed px = psx + (a * x); + signed py = psy + (c * x); //mask pseudo-FP bits px >>= 8; diff --git a/bsnes/snes/ppu/ppu.cpp b/bsnes/snes/ppu/ppu.cpp index d633b40f..437c654d 100755 --- a/bsnes/snes/ppu/ppu.cpp +++ b/bsnes/snes/ppu/ppu.cpp @@ -106,7 +106,14 @@ void PPU::reset() { } void PPU::scanline() { - if(vcounter() == 0) frame(); + if(vcounter() == 0) { + frame(); + bg1.frame(); + bg2.frame(); + bg3.frame(); + bg4.frame(); + } + bg1.scanline(); bg2.scanline(); bg3.scanline(); diff --git a/bsnes/snes/ppu/serialization.cpp b/bsnes/snes/ppu/serialization.cpp index 06f95ad6..b4b341bf 100755 --- a/bsnes/snes/ppu/serialization.cpp +++ b/bsnes/snes/ppu/serialization.cpp @@ -89,9 +89,10 @@ void PPU::serialize(serializer &s) { void PPU::Background::serialize(serializer &s) { s.integer(id); - s.integer(t.x); + s.integer(t.mosaic_x); s.integer(t.mosaic_y); - s.integer(t.mosaic_countdown); + s.integer(t.mosaic_hcounter); + s.integer(t.mosaic_vcounter); s.integer(regs.tiledata_addr); s.integer(regs.screen_addr); diff --git a/bsnes/snes/snes.hpp b/bsnes/snes/snes.hpp index 8f0d53f7..bd9c2b85 100755 --- a/bsnes/snes/snes.hpp +++ b/bsnes/snes/snes.hpp @@ -1,12 +1,12 @@ namespace SNES { namespace Info { static const char Name[] = "bsnes"; - static const char Version[] = "068.01"; - static const unsigned SerializerVersion = 12; + static const char Version[] = "068.02"; + static const unsigned SerializerVersion = 13; } } -#define DEBUGGER +//#define DEBUGGER #define CHEAT_SYSTEM #include