From becbca47d48496d2f6569fd0a685a498c18f0f91 Mon Sep 17 00:00:00 2001 From: Tim Allen Date: Fri, 19 Apr 2019 18:02:31 +1000 Subject: [PATCH] Update to bsnes v107r3 beta release. byuu says: Changes: HD mode 7 supersampling support, HD mode 7 mosaic disable option, various HD mode 7 bugfixes, default waveOut audio latency to 128 instead of 512, removed 512x240 hires mode 7 mode. There's also a small experiment, making this release a beta release as well: for a large speedup, when in EXTBG mode, I'm bypassing rendering BG1 for a performance boost. EXTBG is only used as a priority layer, and is overwritten by BG2 except in one extremely pathological case. --- bsnes/emulator/emulator.hpp | 4 +- bsnes/sfc/coprocessor/dsp1/dsp1emu.cpp | 3 +- bsnes/sfc/interface/configuration.cpp | 3 +- bsnes/sfc/interface/configuration.hpp | 3 +- bsnes/sfc/ppu-fast/line.cpp | 10 +-- bsnes/sfc/ppu-fast/mode7.cpp | 10 ++- bsnes/sfc/ppu-fast/mode7hd.cpp | 104 ++++++++++++++--------- bsnes/sfc/ppu-fast/mode7hires.cpp | 63 -------------- bsnes/sfc/ppu-fast/ppu.cpp | 9 +- bsnes/sfc/ppu-fast/ppu.hpp | 7 +- bsnes/sfc/ppu-fast/serialization.cpp | 1 + bsnes/target-bsnes/program/hacks.cpp | 4 +- bsnes/target-bsnes/settings/drivers.cpp | 4 +- bsnes/target-bsnes/settings/emulator.cpp | 18 ++-- bsnes/target-bsnes/settings/settings.cpp | 3 +- bsnes/target-bsnes/settings/settings.hpp | 6 +- 16 files changed, 113 insertions(+), 139 deletions(-) delete mode 100644 bsnes/sfc/ppu-fast/mode7hires.cpp diff --git a/bsnes/emulator/emulator.hpp b/bsnes/emulator/emulator.hpp index 271809ad..0f63807c 100644 --- a/bsnes/emulator/emulator.hpp +++ b/bsnes/emulator/emulator.hpp @@ -31,13 +31,13 @@ using namespace nall; namespace Emulator { static const string Name = "bsnes"; - static const string Version = "107.2"; + static const string Version = "107.3"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "https://byuu.org/"; //incremented only when serialization format changes - static const string SerializerVersion = "107"; + static const string SerializerVersion = "107.3"; namespace Constants { namespace Colorburst { diff --git a/bsnes/sfc/coprocessor/dsp1/dsp1emu.cpp b/bsnes/sfc/coprocessor/dsp1/dsp1emu.cpp index d933b11c..c0ed19d4 100644 --- a/bsnes/sfc/coprocessor/dsp1/dsp1emu.cpp +++ b/bsnes/sfc/coprocessor/dsp1/dsp1emu.cpp @@ -1490,6 +1490,7 @@ const int16 Dsp1::SinTable[256] = { // As a curiosity, in the positions 0x21c-0x31c it's contained a // 257-points arccos table that, apparently, have been not used anywhere // (maybe for the MaxAZS_Exp table?). +// byuu note: the error at DataRom[0x3c] has been corrected from 0x0001 to 0x0010 const uint16 Dsp1::DataRom[1024] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, @@ -1498,7 +1499,7 @@ const int16 Dsp1::SinTable[256] = { 0x0000, 0x0000, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x7fff, 0x4000, 0x2000, 0x1000, 0x0800, 0x0400, 0x0200, - 0x0100, 0x0080, 0x0040, 0x0020, 0x0001, 0x0008, 0x0004, 0x0002, + 0x0100, 0x0080, 0x0040, 0x0020, 0x0010, 0x0008, 0x0004, 0x0002, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, diff --git a/bsnes/sfc/interface/configuration.cpp b/bsnes/sfc/interface/configuration.cpp index ec29a30b..6968b1ab 100644 --- a/bsnes/sfc/interface/configuration.cpp +++ b/bsnes/sfc/interface/configuration.cpp @@ -18,9 +18,10 @@ auto Configuration::process(Markup::Node document, bool load) -> void { bind(boolean, "Hacks/PPU/Fast", hacks.ppu.fast); bind(boolean, "Hacks/PPU/NoSpriteLimit", hacks.ppu.noSpriteLimit); - bind(boolean, "Hacks/PPU/Mode7/Hires", hacks.ppu.mode7.hires); bind(natural, "Hacks/PPU/Mode7/Scale", hacks.ppu.mode7.scale); bind(boolean, "Hacks/PPU/Mode7/Perspective", hacks.ppu.mode7.perspective); + bind(boolean, "Hacks/PPU/Mode7/Supersample", hacks.ppu.mode7.supersample); + bind(boolean, "Hacks/PPU/Mode7/Mosaic", hacks.ppu.mode7.mosaic); bind(boolean, "Hacks/DSP/Fast", hacks.dsp.fast); bind(boolean, "Hacks/DSP/Cubic", hacks.dsp.cubic); bind(boolean, "Hacks/Coprocessors/HLE", hacks.coprocessors.hle); diff --git a/bsnes/sfc/interface/configuration.hpp b/bsnes/sfc/interface/configuration.hpp index 06160cec..89c06143 100644 --- a/bsnes/sfc/interface/configuration.hpp +++ b/bsnes/sfc/interface/configuration.hpp @@ -29,9 +29,10 @@ struct Configuration { bool fast = true; bool noSpriteLimit = false; struct Mode7 { - bool hires = false; uint scale = 1; bool perspective = true; + bool supersample = false; + bool mosaic = true; } mode7; } ppu; struct DSP { diff --git a/bsnes/sfc/ppu-fast/line.cpp b/bsnes/sfc/ppu-fast/line.cpp index e879a47b..ec417f4b 100644 --- a/bsnes/sfc/ppu-fast/line.cpp +++ b/bsnes/sfc/ppu-fast/line.cpp @@ -14,6 +14,7 @@ auto PPUfast::Line::flush() -> void { auto PPUfast::Line::render() -> void { auto hd = ppufast.hd(); + auto ss = ppufast.ss(); auto scale = ppufast.hdScale(); auto output = ppufast.output + (!hd ? (y * 1024 + (ppufast.interlace() && ppufast.field() ? 512 : 0)) @@ -29,11 +30,10 @@ auto PPUfast::Line::render() -> void { } bool hires = io.pseudoHires || io.bgMode == 5 || io.bgMode == 6; - bool hiresMode7 = io.bgMode == 7 && configuration.hacks.ppu.mode7.hires; auto aboveColor = cgram[0]; auto belowColor = hires ? cgram[0] : io.col.fixedColor; - uint xa = hd && ppufast.interlace() && ppufast.field() ? 256 * scale * scale / 2 : 0; - uint xb = !hd ? 256 << hiresMode7 : ppufast.interlace() && !ppufast.field() ? 256 * scale * scale / 2 : 256 * scale * scale; + uint xa = (hd || ss) && ppufast.interlace() && ppufast.field() ? 256 * scale * scale / 2 : 0; + uint xb = !(hd || ss) ? 256 : ppufast.interlace() && !ppufast.field() ? 256 * scale * scale / 2 : 256 * scale * scale; for(uint x = xa; x < xb; x++) { above[x] = {Source::COL, 0, aboveColor}; below[x] = {Source::COL, 0, belowColor}; @@ -50,10 +50,6 @@ auto PPUfast::Line::render() -> void { auto luma = io.displayBrightness << 15; if(hd) for(uint x : range(256 * scale * scale)) { *output++ = luma | pixel(x / scale & 255, above[x], below[x]); - } else if(hiresMode7) for(uint x : range(512)) { - auto Above = above[x >> 1].source >= Source::OBJ1 ? above[x >> 1] : above[x >> 1 | (x & 1 ? 256 : 0)]; - auto Below = below[x >> 1].source >= Source::OBJ1 ? below[x >> 1] : below[x >> 1 | (x & 1 ? 256 : 0)]; - *output++ = luma | pixel(x >> 1, Above, Below); } else if(width == 256) for(uint x : range(256)) { *output++ = luma | pixel(x, above[x], below[x]); } else if(!hires) for(uint x : range(256)) { diff --git a/bsnes/sfc/ppu-fast/mode7.cpp b/bsnes/sfc/ppu-fast/mode7.cpp index da0c3853..dd4540e0 100644 --- a/bsnes/sfc/ppu-fast/mode7.cpp +++ b/bsnes/sfc/ppu-fast/mode7.cpp @@ -1,6 +1,12 @@ auto PPUfast::Line::renderMode7(PPUfast::IO::Background& self, uint source) -> void { - if(ppufast.hdScale() > 1) return renderMode7HD(self, source); - if(configuration.hacks.ppu.mode7.hires) return renderMode7Hires(self, source); + //EXTBG is only really used by games to give the mode 7 layer two priority levels + //especially with HD mode 7, it's just wasteful to render BG1 just to be overwritten by BG2 + if(io.extbg && source == Source::BG1) return; + + //HD mode 7 support + if(!ppufast.hdMosaic() || !self.mosaicEnable || !io.mosaicSize) { + if(ppufast.hdScale() > 1) return renderMode7HD(self, source); + } int Y = this->y - (self.mosaicEnable ? this->y % (1 + io.mosaicSize) : 0); int y = !io.mode7.vflip ? Y : 255 - Y; diff --git a/bsnes/sfc/ppu-fast/mode7hd.cpp b/bsnes/sfc/ppu-fast/mode7hd.cpp index 5ad17693..8a5fb65f 100644 --- a/bsnes/sfc/ppu-fast/mode7hd.cpp +++ b/bsnes/sfc/ppu-fast/mode7hd.cpp @@ -21,9 +21,6 @@ auto PPUfast::Line::renderMode7HD(PPUfast::IO::Background& self, uint source) -> } #undef isLineMode7 - int Y = y - (self.mosaicEnable ? y % (1 + io.mosaicSize) : 0); - float yt = !io.mode7.vflip ? Y : 255 - Y; - Line line_a = ppufast.lines[y_a]; float a_a = (int16)line_a.io.mode7.a; float b_a = (int16)line_a.io.mode7.b; @@ -41,6 +38,11 @@ auto PPUfast::Line::renderMode7HD(PPUfast::IO::Background& self, uint source) -> int hoffset = (int13)io.mode7.hoffset; int voffset = (int13)io.mode7.voffset; + if(io.mode7.vflip) { + y_a = 255 - y_a; + y_b = 255 - y_b; + } + array windowAbove; array windowBelow; renderWindow(self.window, self.window.aboveEnable, windowAbove); @@ -48,74 +50,92 @@ auto PPUfast::Line::renderMode7HD(PPUfast::IO::Background& self, uint source) -> int pixelYp = INT_MIN; for(int ys : range(scale)) { - float y = yt + ys * 1.0 / scale - 0.5; - float a = 1.0 / lerp(y_a, 1.0 / a_a, y_b, 1.0 / a_b, y); - float b = 1.0 / lerp(y_a, 1.0 / b_a, y_b, 1.0 / b_b, y); - float c = 1.0 / lerp(y_a, 1.0 / c_a, y_b, 1.0 / c_b, y); - float d = 1.0 / lerp(y_a, 1.0 / d_a, y_b, 1.0 / d_b, y); + float yf = y + ys * 1.0 / scale - 0.5; + if(io.mode7.vflip) yf = 255 - yf; + + float a = 1.0 / lerp(y_a, 1.0 / a_a, y_b, 1.0 / a_b, yf); + float b = 1.0 / lerp(y_a, 1.0 / b_a, y_b, 1.0 / b_b, yf); + float c = 1.0 / lerp(y_a, 1.0 / c_a, y_b, 1.0 / c_b, yf); + float d = 1.0 / lerp(y_a, 1.0 / d_a, y_b, 1.0 / d_b, yf); int ht = (hoffset - hcenter) % 1024; - float vty = ((voffset - vcenter) % 1024) + y; + float vty = ((voffset - vcenter) % 1024) + yf; float originX = (a * ht) + (b * vty) + (hcenter << 8); float originY = (c * ht) + (d * vty) + (vcenter << 8); - uint tile, palette, priority; - //some games enable mosaic with a mosaic size of 0 (1x1) - bool mosaicEnable = self.mosaicEnable && io.mosaicSize; - uint mosaicCounter = 1; - uint mosaicPalette = 0; - uint mosaicPriority = 0; - uint mosaicColor = 0; - Pixel mosaicPixel; - int pixelXp = INT_MIN; - for(int X : range(256)) { - float xt = !io.mode7.hflip ? X : 255 - X; - bool doAbove = self.aboveEnable && !windowAbove[X]; - bool doBelow = self.belowEnable && !windowBelow[X]; + for(int x : range(256)) { + bool doAbove = self.aboveEnable && !windowAbove[x]; + bool doBelow = self.belowEnable && !windowBelow[x]; for(int xs : range(scale)) { - float x = xt + xs * 1.0 / scale - 0.5; - int pixelX = (originX + a * x) / 256; - int pixelY = (originY + c * x) / 256; + float xf = x + xs * 1.0 / scale - 0.5; + if(io.mode7.hflip) xf = 255 - xf; + + int pixelX = (originX + a * xf) / 256; + int pixelY = (originY + c * xf) / 256; above++; below++; //only compute color again when coordinates have changed if(pixelX != pixelXp || pixelY != pixelYp) { - pixelXp = pixelX; - pixelYp = pixelY; - - tile = io.mode7.repeat == 3 && ((pixelX | pixelY) & ~1023) ? 0 : ppufast.vram[(pixelY >> 3 & 127) * 128 + (pixelX >> 3 & 127)].byte(0); - palette = io.mode7.repeat == 2 && ((pixelX | pixelY) & ~1023) ? 0 : ppufast.vram[(((pixelY & 7) << 3) + (pixelX & 7)) + (tile << 6)].byte(1); + uint tile = io.mode7.repeat == 3 && ((pixelX | pixelY) & ~1023) ? 0 : ppufast.vram[(pixelY >> 3 & 127) * 128 + (pixelX >> 3 & 127)].byte(0); + uint palette = io.mode7.repeat == 2 && ((pixelX | pixelY) & ~1023) ? 0 : ppufast.vram[(((pixelY & 7) << 3) + (pixelX & 7)) + (tile << 6)].byte(1); + uint priority; if(!extbg) { priority = self.priority[0]; } else { priority = self.priority[palette >> 7]; palette &= 0x7f; } - } + if(!palette) continue; - if(!mosaicEnable || --mosaicCounter == 0) { - mosaicCounter = (1 + io.mosaicSize) * scale; - mosaicPalette = palette; - mosaicPriority = priority; + uint color; if(io.col.directColor && !extbg) { - mosaicColor = directColor(0, palette); + color = directColor(0, palette); } else { - mosaicColor = cgram[palette]; + color = cgram[palette]; } - pixel = {source, mosaicPriority, mosaicColor}; - } - if(!mosaicPalette) continue; - if(doAbove && (!extbg || mosaicPriority > above->priority)) *above = pixel; - if(doBelow && (!extbg || mosaicPriority > below->priority)) *below = pixel; + pixel = {source, priority, color}; + pixelXp = pixelX; + pixelYp = pixelY; + } + + if(doAbove && (!extbg || pixel.priority > above->priority)) *above = pixel; + if(doBelow && (!extbg || pixel.priority > below->priority)) *below = pixel; } } } + + if(ppufast.ss()) { + uint divisor = scale * scale; + for(uint p : range(256)) { + uint ab = 0, bb = 0; + uint ag = 0, bg = 0; + uint ar = 0, br = 0; + for(uint y : range(scale)) { + auto above = &this->above[p * scale]; + auto below = &this->below[p * scale]; + for(uint x : range(scale)) { + uint a = above[x].color; + uint b = below[x].color; + ab += a >> 0 & 31; + ag += a >> 5 & 31; + ar += a >> 10 & 31; + bb += b >> 0 & 31; + bg += b >> 5 & 31; + br += b >> 10 & 31; + } + } + uint aboveColor = ab / divisor << 0 | ag / divisor << 5 | ar / divisor << 10; + uint belowColor = bb / divisor << 0 | bg / divisor << 5 | br / divisor << 10; + this->above[p] = {source, this->above[p * scale].priority, aboveColor}; + this->below[p] = {source, this->below[p * scale].priority, belowColor}; + } + } } //interpolation and extrapolation diff --git a/bsnes/sfc/ppu-fast/mode7hires.cpp b/bsnes/sfc/ppu-fast/mode7hires.cpp deleted file mode 100644 index d91c1d88..00000000 --- a/bsnes/sfc/ppu-fast/mode7hires.cpp +++ /dev/null @@ -1,63 +0,0 @@ -auto PPUfast::Line::renderMode7Hires(PPUfast::IO::Background& self, uint source) -> void { - int Y = this->y - (self.mosaicEnable ? this->y % (1 + io.mosaicSize) : 0); - int y = !io.mode7.vflip ? Y : 255 - Y; - - int a = (int16)io.mode7.a; - int b = (int16)io.mode7.b; - int c = (int16)io.mode7.c; - int d = (int16)io.mode7.d; - int hcenter = (int13)io.mode7.x; - int vcenter = (int13)io.mode7.y; - int hoffset = (int13)io.mode7.hoffset; - int voffset = (int13)io.mode7.voffset; - - uint mosaicCounter = 1; - uint mosaicPalette = 0; - uint mosaicPriority = 0; - uint mosaicColor = 0; - - auto clip = [](int n) -> int { return n & 0x2000 ? (n | ~1023) : (n & 1023); }; - int originX = (a * clip(hoffset - hcenter) & ~63) + (b * clip(voffset - vcenter) & ~63) + (b * y & ~63) + (hcenter << 8); - int originY = (c * clip(hoffset - hcenter) & ~63) + (d * clip(voffset - vcenter) & ~63) + (d * y & ~63) + (vcenter << 8); - - array windowAbove; - array windowBelow; - renderWindow(self.window, self.window.aboveEnable, windowAbove); - renderWindow(self.window, self.window.belowEnable, windowBelow); - - for(int X : range(512)) { - int x = !io.mode7.hflip ? X : 511 - X; - int pixelX = 2 * originX + a * x >> 9; - int pixelY = 2 * originY + c * x >> 9; - int tileX = pixelX >> 3 & 127; - int tileY = pixelY >> 3 & 127; - bool outOfBounds = (pixelX | pixelY) & ~1023; - uint15 tileAddress = tileY * 128 + tileX; - uint15 paletteAddress = ((pixelY & 7) << 3) + (pixelX & 7); - uint8 tile = io.mode7.repeat == 3 && outOfBounds ? 0 : ppufast.vram[tileAddress].byte(0); - uint8 palette = io.mode7.repeat == 2 && outOfBounds ? 0 : ppufast.vram[paletteAddress + (tile << 6)].byte(1); - - uint priority; - if(source == Source::BG1) { - priority = self.priority[0]; - } else if(source == Source::BG2) { - priority = self.priority[palette >> 7]; - palette &= 0x7f; - } - - if(!self.mosaicEnable || !io.mosaicSize || --mosaicCounter == 0) { - mosaicCounter = (1 + io.mosaicSize) << 1; - mosaicPalette = palette; - mosaicPriority = priority; - if(io.col.directColor && source == Source::BG1) { - mosaicColor = directColor(0, palette); - } else { - mosaicColor = cgram[palette]; - } - } - if(!mosaicPalette) continue; - - if(self.aboveEnable && !windowAbove[X >> 1]) plotAbove(X >> 1 | (X & 1 ? 256 : 0), source, mosaicPriority, mosaicColor); - if(self.belowEnable && !windowBelow[X >> 1]) plotBelow(X >> 1 | (X & 1 ? 256 : 0), source, mosaicPriority, mosaicColor); - } -} diff --git a/bsnes/sfc/ppu-fast/ppu.cpp b/bsnes/sfc/ppu-fast/ppu.cpp index d45ba9a8..9b22f747 100644 --- a/bsnes/sfc/ppu-fast/ppu.cpp +++ b/bsnes/sfc/ppu-fast/ppu.cpp @@ -9,7 +9,6 @@ PPUfast ppufast; #include "line.cpp" #include "background.cpp" #include "mode7.cpp" -#include "mode7hires.cpp" #include "mode7hd.cpp" #include "object.cpp" #include "window.cpp" @@ -20,8 +19,11 @@ auto PPUfast::overscan() const -> bool { return ppubase.display.overscan; } auto PPUfast::vdisp() const -> uint { return ppubase.display.vdisp; } auto PPUfast::hires() const -> bool { return latch.hires; } auto PPUfast::hd() const -> bool { return latch.hd; } +auto PPUfast::ss() const -> bool { return latch.ss; } auto PPUfast::hdScale() const -> uint { return configuration.hacks.ppu.mode7.scale; } auto PPUfast::hdPerspective() const -> bool { return configuration.hacks.ppu.mode7.perspective; } +auto PPUfast::hdSupersample() const -> bool { return configuration.hacks.ppu.mode7.supersample; } +auto PPUfast::hdMosaic() const -> bool { return configuration.hacks.ppu.mode7.mosaic; } PPUfast::PPUfast() { output = new uint32[2304 * 2304] + 72 * 2304; //overscan offset @@ -78,14 +80,15 @@ auto PPUfast::scanline() -> void { ppubase.display.overscan = io.overscan; latch.hires = false; latch.hd = false; + latch.ss = false; io.obj.timeOver = false; io.obj.rangeOver = false; } if(vcounter() > 0 && vcounter() < vdisp()) { latch.hires |= io.pseudoHires || io.bgMode == 5 || io.bgMode == 6; - latch.hires |= io.bgMode == 7 && configuration.hacks.ppu.mode7.hires; - latch.hd |= io.bgMode == 7 && hdScale() > 1; + latch.hd |= io.bgMode == 7 && hdScale() > 1 && hdSupersample() == 0; + latch.ss |= io.bgMode == 7 && hdScale() > 1 && hdSupersample() == 1; } if(vcounter() == vdisp() && !io.displayDisable) { diff --git a/bsnes/sfc/ppu-fast/ppu.hpp b/bsnes/sfc/ppu-fast/ppu.hpp index de057931..255795f0 100644 --- a/bsnes/sfc/ppu-fast/ppu.hpp +++ b/bsnes/sfc/ppu-fast/ppu.hpp @@ -11,8 +11,11 @@ struct PPUfast : Thread, PPUcounter { alwaysinline auto vdisp() const -> uint; alwaysinline auto hires() const -> bool; alwaysinline auto hd() const -> bool; + alwaysinline auto ss() const -> bool; alwaysinline auto hdScale() const -> uint; alwaysinline auto hdPerspective() const -> bool; + alwaysinline auto hdSupersample() const -> bool; + alwaysinline auto hdMosaic() const -> bool; //ppu.cpp PPUfast(); @@ -42,6 +45,7 @@ public: uint1 overscan; uint1 hires; uint1 hd; + uint1 ss; uint16 vram; uint8 oam; @@ -281,9 +285,6 @@ public: //mode7.cpp auto renderMode7(PPUfast::IO::Background&, uint source) -> void; - //mode7hires.cpp - auto renderMode7Hires(PPUfast::IO::Background&, uint source) -> void; - //mode7hd.cpp auto renderMode7HD(PPUfast::IO::Background&, uint source) -> void; alwaysinline auto lerp(float pa, float va, float pb, float vb, float pr) -> float; diff --git a/bsnes/sfc/ppu-fast/serialization.cpp b/bsnes/sfc/ppu-fast/serialization.cpp index 6c4d92ae..e578dda8 100644 --- a/bsnes/sfc/ppu-fast/serialization.cpp +++ b/bsnes/sfc/ppu-fast/serialization.cpp @@ -18,6 +18,7 @@ auto PPUfast::Latch::serialize(serializer& s) -> void { s.integer(overscan); s.integer(hires); s.integer(hd); + s.integer(ss); s.integer(vram); s.integer(oam); s.integer(cgram); diff --git a/bsnes/target-bsnes/program/hacks.cpp b/bsnes/target-bsnes/program/hacks.cpp index 6a54bf32..3e12b249 100644 --- a/bsnes/target-bsnes/program/hacks.cpp +++ b/bsnes/target-bsnes/program/hacks.cpp @@ -1,7 +1,6 @@ auto Program::hackCompatibility() -> void { bool fastPPU = emulatorSettings.fastPPU.checked(); bool fastPPUNoSpriteLimit = emulatorSettings.noSpriteLimit.checked(); - bool fastPPUHiresMode7 = emulatorSettings.hiresMode7.checked(); bool fastDSP = emulatorSettings.fastDSP.checked(); bool coprocessorsDelayedSync = emulatorSettings.coprocessorsDelayedSyncOption.checked(); @@ -12,9 +11,10 @@ auto Program::hackCompatibility() -> void { emulator->configure("Hacks/PPU/Fast", fastPPU); emulator->configure("Hacks/PPU/NoSpriteLimit", fastPPUNoSpriteLimit); - emulator->configure("Hacks/PPU/Mode7/Hires", fastPPUHiresMode7); emulator->configure("Hacks/PPU/Mode7/Scale", settings.emulator.hack.ppu.mode7.scale); emulator->configure("Hacks/PPU/Mode7/Perspective", settings.emulator.hack.ppu.mode7.perspective); + emulator->configure("Hacks/PPU/Mode7/Supersample", settings.emulator.hack.ppu.mode7.supersample); + emulator->configure("Hacks/PPU/Mode7/Mosaic", settings.emulator.hack.ppu.mode7.mosaic); emulator->configure("Hacks/DSP/Fast", fastDSP); emulator->configure("Hacks/DSP/Cubic", settings.emulator.hack.dsp.cubic); emulator->configure("Hacks/Coprocessors/DelayedSync", coprocessorsDelayedSync); diff --git a/bsnes/target-bsnes/settings/drivers.cpp b/bsnes/target-bsnes/settings/drivers.cpp index ca739d2b..a717f941 100644 --- a/bsnes/target-bsnes/settings/drivers.cpp +++ b/bsnes/target-bsnes/settings/drivers.cpp @@ -13,7 +13,7 @@ auto DriverSettings::create() -> void { videoDriverUpdate.setText("Change").onActivate([&] { videoDriverChange(); }); videoFormatLabel.setText("Format:"); videoFormatOption.onChange([&] { videoFormatChange(); }); - videoExclusiveToggle.setText("Exclusive").setToolTip( + videoExclusiveToggle.setText("Exclusive fullscreen mode").setToolTip( "(Direct3D driver only)\n\n" "Acquires exclusive access to the display in fullscreen mode.\n" "Eliminates compositing issues such as video stuttering." @@ -57,7 +57,7 @@ auto DriverSettings::create() -> void { audioFrequencyOption.onChange([&] { audioFrequencyChange(); }); audioLatencyLabel.setText("Latency:"); audioLatencyOption.onChange([&] { audioLatencyChange(); }); - audioExclusiveToggle.setText("Exclusive").setToolTip( + audioExclusiveToggle.setText("Exclusive mode").setToolTip( "(ASIO, WASAPI drivers only)\n\n" "Acquires exclusive control of the sound card device.\n" "This can significantly reduce audio latency.\n" diff --git a/bsnes/target-bsnes/settings/emulator.cpp b/bsnes/target-bsnes/settings/emulator.cpp index 8db1ee45..40f89a43 100644 --- a/bsnes/target-bsnes/settings/emulator.cpp +++ b/bsnes/target-bsnes/settings/emulator.cpp @@ -42,19 +42,13 @@ auto EmulatorSettings::create() -> void { settings.emulator.hack.ppu.fast = fastPPU.checked(); if(!fastPPU.checked()) { noSpriteLimit.setEnabled(false).setChecked(false).doToggle(); - hiresMode7.setEnabled(false).setChecked(false).doToggle(); } else { noSpriteLimit.setEnabled(true); - hiresMode7.setEnabled(true); } }).doToggle(); noSpriteLimit.setText("No sprite limit").setChecked(settings.emulator.hack.ppu.noSpriteLimit).onToggle([&] { settings.emulator.hack.ppu.noSpriteLimit = noSpriteLimit.checked(); }); - hiresMode7.setText("Hires mode 7").setChecked(settings.emulator.hack.ppu.mode7.hires).setVisible(false).onToggle([&] { - settings.emulator.hack.ppu.mode7.hires = hiresMode7.checked(); - emulator->configure("Hacks/PPU/Mode7/Hires", settings.emulator.hack.ppu.mode7.hires); - }); mode7Label.setText("HD Mode 7 (fast PPU only)").setFont(Font().setBold()); mode7ScaleLabel.setText("Scale:"); mode7Scale.append(ComboButtonItem().setText( "240p").setProperty("multiplier", 1)); @@ -77,6 +71,14 @@ auto EmulatorSettings::create() -> void { settings.emulator.hack.ppu.mode7.perspective = mode7Perspective.checked(); emulator->configure("Hacks/PPU/Mode7/Perspective", settings.emulator.hack.ppu.mode7.perspective); }); + mode7Supersample.setText("Supersample").setChecked(settings.emulator.hack.ppu.mode7.supersample).onToggle([&] { + settings.emulator.hack.ppu.mode7.supersample = mode7Supersample.checked(); + emulator->configure("Hacks/PPU/Mode7/Supersample", settings.emulator.hack.ppu.mode7.supersample); + }); + mode7Mosaic.setText("HD->SD Mosaic").setChecked(settings.emulator.hack.ppu.mode7.mosaic).onToggle([&] { + settings.emulator.hack.ppu.mode7.mosaic = mode7Mosaic.checked(); + emulator->configure("Hacks/PPU/Mode7/Mosaic", settings.emulator.hack.ppu.mode7.mosaic); + }); dspLabel.setText("DSP (audio)").setFont(Font().setBold()); fastDSP.setText("Fast mode").setChecked(settings.emulator.hack.dsp.fast).onToggle([&] { settings.emulator.hack.dsp.fast = fastDSP.checked(); @@ -105,8 +107,10 @@ auto EmulatorSettings::create() -> void { auto EmulatorSettings::updateConfiguration() -> void { emulator->configure("Hacks/PPU/Fast", fastPPU.checked()); emulator->configure("Hacks/PPU/NoSpriteLimit", noSpriteLimit.checked()); - emulator->configure("Hacks/PPU/Mode7/Hires", hiresMode7.checked()); emulator->configure("Hacks/PPU/Mode7/Scale", mode7Scale.selected().property("multiplier").natural()); + emulator->configure("Hacks/PPU/Mode7/Perspective", mode7Perspective.checked()); + emulator->configure("Hacks/PPU/Mode7/Supersample", mode7Supersample.checked()); + emulator->configure("Hacks/PPU/Mode7/Mosaic", mode7Mosaic.checked()); emulator->configure("Hacks/DSP/Fast", fastDSP.checked()); emulator->configure("Hacks/DSP/Cubic", cubicInterpolation.checked()); emulator->configure("Hacks/Coprocessor/DelayedSync", coprocessorsDelayedSyncOption.checked()); diff --git a/bsnes/target-bsnes/settings/settings.cpp b/bsnes/target-bsnes/settings/settings.cpp index 86583817..c3c247f2 100644 --- a/bsnes/target-bsnes/settings/settings.cpp +++ b/bsnes/target-bsnes/settings/settings.cpp @@ -97,9 +97,10 @@ auto Settings::process(bool load) -> void { bind(boolean, "Emulator/AutoLoadStateOnLoad", emulator.autoLoadStateOnLoad); bind(boolean, "Emulator/Hack/PPU/Fast", emulator.hack.ppu.fast); bind(boolean, "Emulator/Hack/PPU/NoSpriteLimit", emulator.hack.ppu.noSpriteLimit); - bind(boolean, "Emulator/Hack/PPU/Mode7/Hires", emulator.hack.ppu.mode7.hires); bind(natural, "Emulator/Hack/PPU/Mode7/Scale", emulator.hack.ppu.mode7.scale); bind(boolean, "Emulator/Hack/PPU/Mode7/Perspective", emulator.hack.ppu.mode7.perspective); + bind(boolean, "Emulator/Hack/PPU/Mode7/Supersample", emulator.hack.ppu.mode7.supersample); + bind(boolean, "Emulator/Hack/PPU/Mode7/Mosaic", emulator.hack.ppu.mode7.mosaic); bind(boolean, "Emulator/Hack/DSP/Fast", emulator.hack.dsp.fast); bind(boolean, "Emulator/Hack/DSP/Cubic", emulator.hack.dsp.cubic); bind(boolean, "Emulator/Hack/Coprocessors/DelayedSync", emulator.hack.coprocessors.delayedSync); diff --git a/bsnes/target-bsnes/settings/settings.hpp b/bsnes/target-bsnes/settings/settings.hpp index 4dd043d5..02f2947f 100644 --- a/bsnes/target-bsnes/settings/settings.hpp +++ b/bsnes/target-bsnes/settings/settings.hpp @@ -79,9 +79,10 @@ struct Settings : Markup::Node { bool fast = true; bool noSpriteLimit = false; struct Mode7 { - bool hires = false; uint scale = 1; bool perspective = true; + bool supersample = false; + bool mosaic = true; } mode7; } ppu; struct DSP { @@ -265,12 +266,13 @@ public: HorizontalLayout ppuLayout{&layout, Size{~0, 0}}; CheckLabel fastPPU{&ppuLayout, Size{0, 0}}; CheckLabel noSpriteLimit{&ppuLayout, Size{0, 0}}; - CheckLabel hiresMode7{&ppuLayout, Size{0, 0}}; Label mode7Label{&layout, Size{~0, 0}, 2}; HorizontalLayout mode7Layout{&layout, Size{~0, 0}}; Label mode7ScaleLabel{&mode7Layout, Size{0, 0}}; ComboButton mode7Scale{&mode7Layout, Size{0, 0}}; CheckLabel mode7Perspective{&mode7Layout, Size{0, 0}}; + CheckLabel mode7Supersample{&mode7Layout, Size{0, 0}}; + CheckLabel mode7Mosaic{&mode7Layout, Size{0, 0}}; Label dspLabel{&layout, Size{~0, 0}, 2}; HorizontalLayout dspLayout{&layout, Size{~0, 0}}; CheckLabel fastDSP{&dspLayout, Size{0, 0}};