mirror of https://github.com/bsnes-emu/bsnes.git
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.
This commit is contained in:
parent
920d139302
commit
39b1acb177
|
@ -1,6 +1,6 @@
|
|||
include nall/Makefile
|
||||
snes := snes
|
||||
profile := compatibility
|
||||
profile := accuracy
|
||||
ui := qt
|
||||
|
||||
# compiler
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 <libco/libco.h>
|
||||
|
|
Loading…
Reference in New Issue