Update to v078r07 release.

byuu says:

Would appreciate testing on any games with mosaic, especially Mode7
mosaic.I have tested Super Turrican 2, Sim Earth, Contra III and SNES
Test Program.

This only applies to BG modes 0-6, and technically should not affect
Mode7 at all. I am not sure if Mode7 needs the same change made or not,
but given the way it fetches that could prove quite challenging. I also
simplified the background renderer a good bit. See eg the pixel copy
stuff in Background::run().

I've only fixed this in the accuracy renderer. I'm sorry, but the
compatibility renderer is a fucking mess. I haven't really touched it in
four or five years now.

Will probably just revert to the accuracy/SMP in the performance profile
for the next release since it's not being used otherwise. People can
toggle it on if they want to try it out.
This commit is contained in:
Tim Allen 2011-06-05 13:25:24 +10:00
parent bc0b86891a
commit d129b72ced
6 changed files with 76 additions and 91 deletions

View File

@ -1,7 +1,7 @@
include nall/Makefile include nall/Makefile
snes := snes snes := snes
gameboy := gameboy gameboy := gameboy
profile := compatibility profile := accuracy
ui := ui ui := ui
# debugger # debugger

View File

@ -9,26 +9,31 @@ void PPU::Background::scanline() {
bool hires = (self.regs.bgmode == 5 || self.regs.bgmode == 6); bool hires = (self.regs.bgmode == 5 || self.regs.bgmode == 6);
x = -7; x = -7;
y = self.vcounter(); y = self.vcounter();
tile_counter = (7 - (regs.hoffset & 7)) << hires;
for(unsigned n = 0; n < 8; n++) data[n] = 0;
if(self.vcounter() == 1) { if(y == 1) {
mosaic_vcounter = regs.mosaic + 1; mosaic.vcounter = regs.mosaic + 1;
mosaic_voffset = 1; mosaic.voffset = 1;
} else if(--mosaic_vcounter == 0) { mosaic.vscroll = regs.voffset;
mosaic_vcounter = regs.mosaic + 1; mosaic.hscroll = regs.hoffset;
mosaic_voffset += regs.mosaic + 1; } else if(--mosaic.vcounter == 0) {
mosaic.vcounter = regs.mosaic + 1;
mosaic.voffset += regs.mosaic + 1;
mosaic.vscroll = regs.voffset;
mosaic.hscroll = regs.hoffset;
} }
mosaic_hcounter = regs.mosaic + 1; tile_counter = (7 - (mosaic.hscroll & 7)) << hires;
mosaic_hoffset = 0; for(unsigned n = 0; n < 8; n++) data[n] = 0;
mosaic.hcounter = regs.mosaic + 1;
mosaic.hoffset = 0;
} }
void PPU::Background::get_tile() { void PPU::Background::get_tile() {
bool hires = (self.regs.bgmode == 5 || self.regs.bgmode == 6); bool hires = (self.regs.bgmode == 5 || self.regs.bgmode == 6);
unsigned color_depth = (regs.mode == Mode::BPP2 ? 0 : regs.mode == Mode::BPP4 ? 1 : 2); unsigned color_depth = (regs.mode == Mode::BPP2 ? 0 : regs.mode == Mode::BPP4 ? 1 : 2);
unsigned palette_offset = (self.regs.bgmode == 0 ? (id << 5) : 0); unsigned palette_offset = (self.regs.bgmode == 0 ? id << 5 : 0);
unsigned palette_size = 2 << color_depth; unsigned palette_size = 2 << color_depth;
unsigned tile_mask = 0x0fff >> color_depth; unsigned tile_mask = 0x0fff >> color_depth;
unsigned tiledata_index = regs.tiledata_addr >> (4 + color_depth); unsigned tiledata_index = regs.tiledata_addr >> (4 + color_depth);
@ -38,18 +43,18 @@ void PPU::Background::get_tile() {
unsigned width = 256 << hires; unsigned width = 256 << hires;
unsigned mask_x = (tile_height == 3 ? width : (width << 1)); unsigned hmask = (tile_height == 3 ? width : width << 1);
unsigned mask_y = mask_x; unsigned vmask = hmask;
if(regs.screen_size & 1) mask_x <<= 1; if(regs.screen_size & 1) hmask <<= 1;
if(regs.screen_size & 2) mask_y <<= 1; if(regs.screen_size & 2) vmask <<= 1;
mask_x--; hmask--;
mask_y--; vmask--;
unsigned px = x << hires; unsigned px = x << hires;
unsigned py = (regs.mosaic == 0 ? y : mosaic_voffset); unsigned py = (regs.mosaic == 0 ? y : mosaic.voffset);
unsigned hscroll = regs.hoffset; unsigned hscroll = mosaic.hscroll;
unsigned vscroll = regs.voffset; unsigned vscroll = mosaic.vscroll;
if(hires) { if(hires) {
hscroll <<= 1; hscroll <<= 1;
if(self.regs.interlace) py = (py << 1) + self.field(); if(self.regs.interlace) py = (py << 1) + self.field();
@ -81,8 +86,8 @@ void PPU::Background::get_tile() {
} }
} }
hoffset &= mask_x; hoffset &= hmask;
voffset &= mask_y; voffset &= vmask;
unsigned screen_x = (regs.screen_size & 1 ? 32 << 5 : 0); unsigned screen_x = (regs.screen_size & 1 ? 32 << 5 : 0);
unsigned screen_y = (regs.screen_size & 2 ? 32 << 5 : 0); unsigned screen_y = (regs.screen_size & 2 ? 32 << 5 : 0);
@ -143,9 +148,8 @@ void PPU::Background::run(bool screen) {
if(hires == false) return; if(hires == false) return;
} }
if(regs.mode == Mode::Inactive) return;
if(regs.main_enable == false && regs.sub_enable == false) return; if(regs.main_enable == false && regs.sub_enable == false) return;
if(regs.mode == Mode::Inactive) return;
if(regs.mode == Mode::Mode7) return run_mode7(); if(regs.mode == Mode::Mode7) return run_mode7();
if(tile_counter-- == 0) { if(tile_counter-- == 0) {
@ -154,41 +158,18 @@ void PPU::Background::run(bool screen) {
} }
uint8 palette = get_tile_color(); uint8 palette = get_tile_color();
if(x == 0) mosaic_hcounter = 1; if(x == 0) mosaic.hcounter = 1;
if(x >= 0 && --mosaic_hcounter == 0) { if(x >= 0 && --mosaic.hcounter == 0) {
mosaic_hcounter = regs.mosaic + 1; mosaic.hcounter = regs.mosaic + 1;
mosaic_priority = priority; mosaic.priority = priority;
mosaic_palette = palette ? palette_index + palette : 0; mosaic.palette = palette ? palette_index + palette : 0;
mosaic_tile = tile; mosaic.tile = tile;
} }
if(screen == Screen::Main) x++; if(screen == Screen::Main) x++;
if(mosaic_palette == 0) return; if(mosaic.palette == 0) return;
if(hires == false) { if(hires == false || screen == Screen::Main) if(regs.main_enable) output.main = mosaic;
if(regs.main_enable) { if(hires == false || screen == Screen::Sub ) if(regs.sub_enable ) output.sub = mosaic;
output.main.priority = mosaic_priority;
output.main.palette = mosaic_palette;
output.main.tile = mosaic_tile;
}
if(regs.sub_enable) {
output.sub.priority = mosaic_priority;
output.sub.palette = mosaic_palette;
output.sub.tile = mosaic_tile;
}
} else if(screen == Screen::Main) {
if(regs.main_enable) {
output.main.priority = mosaic_priority;
output.main.palette = mosaic_palette;
output.main.tile = mosaic_tile;
}
} else if(screen == Screen::Sub) {
if(regs.sub_enable) {
output.sub.priority = mosaic_priority;
output.sub.palette = mosaic_palette;
output.sub.tile = mosaic_tile;
}
}
} }
unsigned PPU::Background::get_tile_color() { unsigned PPU::Background::get_tile_color() {
@ -229,18 +210,20 @@ void PPU::Background::reset() {
output.sub.palette = 0; output.sub.palette = 0;
output.sub.priority = 0; output.sub.priority = 0;
mosaic.priority = 0;
mosaic.palette = 0;
mosaic.tile = 0;
mosaic.vcounter = 0;
mosaic.voffset = 0;
mosaic.vscroll = 0;
mosaic.hcounter = 0;
mosaic.hoffset = 0;
mosaic.hscroll = 0;
x = 0; x = 0;
y = 0; y = 0;
mosaic_vcounter = 0;
mosaic_voffset = 0;
mosaic_hcounter = 0;
mosaic_hoffset = 0;
mosaic_priority = 0;
mosaic_palette = 0;
mosaic_tile = 0;
tile_counter = 0; tile_counter = 0;
tile = 0; tile = 0;
priority = 0; priority = 0;
@ -254,15 +237,15 @@ unsigned PPU::Background::get_tile(unsigned x, unsigned y) {
unsigned tile_height = (regs.tile_size == TileSize::Size8x8 ? 3 : 4); unsigned tile_height = (regs.tile_size == TileSize::Size8x8 ? 3 : 4);
unsigned tile_width = (!hires ? tile_height : 4); unsigned tile_width = (!hires ? tile_height : 4);
unsigned width = (!hires ? 256 : 512); unsigned width = (!hires ? 256 : 512);
unsigned mask_x = (tile_height == 3 ? width : (width << 1)); unsigned mask_x = (tile_height == 3 ? width : width << 1);
unsigned mask_y = mask_x; unsigned mask_y = mask_x;
if(regs.screen_size & 1) mask_x <<= 1; if(regs.screen_size & 1) mask_x <<= 1;
if(regs.screen_size & 2) mask_y <<= 1; if(regs.screen_size & 2) mask_y <<= 1;
mask_x--; mask_x--;
mask_y--; mask_y--;
unsigned screen_x = (regs.screen_size & 1 ? (32 << 5) : 0); unsigned screen_x = (regs.screen_size & 1 ? 32 << 5 : 0);
unsigned screen_y = (regs.screen_size & 2 ? (32 << 5) : 0); unsigned screen_y = (regs.screen_size & 2 ? 32 << 5 : 0);
if(regs.screen_size == 3) screen_y <<= 1; if(regs.screen_size == 3) screen_y <<= 1;
x = (x & mask_x) >> tile_width; x = (x & mask_x) >> tile_width;

View File

@ -33,19 +33,19 @@ class Background {
} main, sub; } main, sub;
} output; } output;
struct Mosaic : Output::Pixel {
unsigned vcounter;
unsigned voffset;
unsigned vscroll;
unsigned hcounter;
unsigned hoffset;
unsigned hscroll;
} mosaic;
struct { struct {
signed x; signed x;
signed y; signed y;
unsigned mosaic_vcounter;
unsigned mosaic_voffset;
unsigned mosaic_hcounter;
unsigned mosaic_hoffset;
unsigned mosaic_priority;
uint8 mosaic_palette;
uint16 mosaic_tile;
unsigned tile_counter; unsigned tile_counter;
unsigned tile; unsigned tile;
unsigned priority; unsigned priority;

View File

@ -17,12 +17,12 @@ void PPU::Background::run_mode7() {
signed voffset = sclip<13>(self.regs.mode7_voffset); signed voffset = sclip<13>(self.regs.mode7_voffset);
if(Background::x++ & ~255) return; if(Background::x++ & ~255) return;
unsigned x = mosaic_hoffset; unsigned x = mosaic.hoffset;
unsigned y = self.bg1.mosaic_voffset; //BG2 vertical mosaic uses BG1 mosaic size unsigned y = self.bg1.mosaic.voffset; //BG2 vertical mosaic uses BG1 mosaic size
if(--mosaic_hcounter == 0) { if(--mosaic.hcounter == 0) {
mosaic_hcounter = regs.mosaic + 1; mosaic.hcounter = regs.mosaic + 1;
mosaic_hoffset += regs.mosaic + 1; mosaic.hoffset += regs.mosaic + 1;
} }
if(self.regs.mode7_hflip) x = 255 - x; if(self.regs.mode7_hflip) x = 255 - x;

View File

@ -120,14 +120,16 @@ void PPU::Background::serialize(serializer &s) {
s.integer(x); s.integer(x);
s.integer(y); s.integer(y);
s.integer(mosaic_vcounter); s.integer(mosaic.priority);
s.integer(mosaic_voffset); s.integer(mosaic.palette);
s.integer(mosaic_hcounter); s.integer(mosaic.tile);
s.integer(mosaic_hoffset);
s.integer(mosaic_priority); s.integer(mosaic.vcounter);
s.integer(mosaic_palette); s.integer(mosaic.voffset);
s.integer(mosaic_tile); s.integer(mosaic.vscroll);
s.integer(mosaic.hcounter);
s.integer(mosaic.hoffset);
s.integer(mosaic.hscroll);
s.integer(tile_counter); s.integer(tile_counter);
s.integer(tile); s.integer(tile);

View File

@ -1,7 +1,7 @@
namespace SNES { namespace SNES {
namespace Info { namespace Info {
static const char Name[] = "bsnes"; static const char Name[] = "bsnes";
static const char Version[] = "078.06"; static const char Version[] = "078.07";
static const unsigned SerializerVersion = 20; static const unsigned SerializerVersion = 20;
} }
} }