This commit is contained in:
DerKoun 2019-06-25 21:39:24 +02:00
parent 853368687e
commit 2a322e57b6
15 changed files with 405 additions and 178 deletions

101
README.md
View file

@ -1,99 +1,144 @@
# bsnes-hd
- [github project](https://github.com/DerKoun/bsnes-hd)
- [downloads](https://github.com/DerKoun/bsnes-hd/releases) for the latest betas
- [posts](https://www.reddit.com/r/emulation/search/?q=hd%20mode%207&restrict_sr=1&sort=new) and discussions for every beta on Reddit *r/emulation*
- [bsneshd-dev](https://discord.gg/3bVaNcK) at *Emulator Nexus* Discord (not just for developers, feel free to post suggestions, issues, game specific settings, recommended games, broken games, videos, screenshots, ...)
## What is it?
bsnes-hd (formally "*HD Mode 7 mod, for bsnes*") is a fork of bsnes (currently 107r3) that adds HD video features, such as:
bsnes-hd (called "*HD Mode 7 mod, for bsnes*" in early betas) is a fork of bsnes (great SNES emulator by *byuu*, currently based on version 107r3) that adds HD video features, such as:
### HD Mode 7
Rendering the rotated, scaled or pseudo perspective backgrounds at higher resolutions. This does not involve new custom imagery or upscaling algorithms. It is a higher resolution version of the process the SNES uses.
- [image comparison](http://www.framecompare.com/image-compare/screenshotcomparison/EB9MNNNU) (framecompare)
- [video comparison](https://www.youtube.com/watch?v=6VrzJ6Y1kjQ) by *reznoire* (youtube)
### Widescreen
Mostly for Mode 7 scenes, but also works for some other scenes/games here and there. Some setting tweaking required...
Extending the scenes to the left and right, without distorting them. Works for most Mode 7 scenes, but also for some other scenes/games, after some setting tweaking.
- **Demo video**: *Chrono Trigger* ending credits: [Beyond Time](https://www.youtube.com/watch?v=YE1gp6BWilg) by *retroprez* (youtube)
- **Demo video**: *Chrono Trigger* ending credits: [Float Away](https://www.youtube.com/watch?v=Ss49vVbULOQ) by *retroprez* (youtube)
### more to come
For example higher color depth and interpolation for the colors blending that help the sense of depth.
### plus some none-HD related features
### plus some non-HD related features
like the ability to disable background layers, sprites and window effects for screenshots for wallpapers or soft crop to zoom in, leaving maps or static art off the sides of the screen.
## Help Wanted
### Converting C++ Rendering Code to Shaders for Optimization
Currently all the HD rendering is running on the CPU cores. This will have to be moved to the GPU to achieve usable performance. I'd really appreciate any help with that, even if it's just to get started. Please open an issue if you want to contribute, or contact me on Reddit.
## Settings
all in Settings / Emulator
### Scale
The resolution Mode 7 is rendered at. Higher setting drastically increase CPU usage. "*disable*" uses the classic Mode 7 code, disabling some of the following features.
The resolution Mode 7 is rendered at. Higher setting drastically increase CPU usage. "*disable*" uses the classic Mode 7 code, disabling some of the following features. (defaults to 2x, to show the effect with the smallest possible CPU impact)
### Perspective correction
Whether and how pseudo 3D perspective are optimized, avoiding limitations of SNES integer math.
- **off**: disable correction
- **on**: enable correction
- **auto**(default): enable correction, but try to detect when it breaks the image and automatically disable it
- **auto**(default): enable correction, but try to detect when it breaks the image and automatically disable it.
- **wide**(default)/**medium**/**narrow**: the distance between the lines used for the interpolation (and also for the detection, if enabled). Use "*wide*" unless it causes issues. Only currently known game that requires this is "*Tales of Phantasia*", requiring "*narrow*".
### Mosaic
How to handle Mosaic effects on Mode 7 backgrounds.
- **non-HD**: use 'classic' Mode 7 with Mosaic applied. Looks as intended, but disables HD and widescreen.
- **1x scale**(default): instead of the set *Scale* use "*1x*". Provides a good compromise between the other two options.
- **ignore**: ignore the Mosaic effect completely.
### Supersampling
Allows basing every resulting pixel on the average of multiple pixels. At 1x scale it allows using the higher precision at the original resolution, e.g. for use with CRT-shaders. At higher resolutions it is basically expensive anti-aliasing. Keep in mind that to estimate the performance impact you have to multiply(!) this value with the "*scale*" value.
### Keep Mosaics non-HD
When unchecked mosaic effects are ignored on Mode 7 backgrounds. When checked the affected lines fall back to classic Mode 7.
Allows basing every resulting pixel on the average of multiple pixels. At 1x scale it allows using the higher precision at the original resolution, e.g. for use with CRT-shaders. At higher resolutions it is basically expensive anti-aliasing. (defaults to "*none*") *Keep in mind that to estimate the performance impact you have to multiply(!) this value with the "*scale*" value.*
### Widescreen
Enables experimental widescreen (works best for Mode 7 scenes, rest is hit and miss) and sets its AR. The actual AR are slightly wider than the selection, use some "*soft crop*" "*left*" and "*right*" for the ideal fullscreen experience. "*HDcrop*" at 5x scale results in a width of 1920, which (combined with "*soft crop*" "*top*" and "*bottom*" at 10, output/center and shader/none) results in perfect 1080p fullscreen.
Enables experimental widescreen functionality
- **none**: do not enable widescreen
- **Mode 7**(default): enable widescreen for Mode 7 scenes (works for most games)
- **all**: enable widescreen for all scenes (non-Mode 7 scenes only work acceptable in some games, but many have mostly artifacts)
### Aspect ratio
Specifies the widescreen aspect ratio. The actual AR are slightly wider than the selection, use some "*soft crop*" "*left*" and "*right*" for the ideal fullscreen experience. "*HD*" at 5x scale results in a width of 1920, which (combined with "*soft crop*" "*top*" and "*bottom*" at 10, output/center and shader/none) results in perfect 1080p fullscreen. (defaults to 16:9)
### WS bg
Sets how the backgrounds of the widescreen areas are filled
- **color**: always fill the widescreen areas with the scanline background colors.
- **auto**(default): fill the widescreen areas with the scanline background colors, except when the "*Widescreen:Mode 7*" setting disables widescreen for the scene, then use black.
- **black**: the widescreen areas always have a black background, ignoring the background color, even when the scene is widescreen. (do not use unless a a game specifically requires it, none known for now)
### WS marker
Allows highlighting the edges of the widescreen areas in some ways.
- **none**(default): no highlighting
- **lines**: shows a dashed lined at the edges of each widescreen area
- **darken**: darkens the widescreen areas
### WSM alpha
Specifies how translucent the widescreen markers are. (defaults to 1/1)
### BG1/BG2/BG2/BG4
Settings for the background layers:
Settings for the background layers.
- **off**: no widescreen (e.g. for HUDs)
- **on**: widescreen enabled
- **< xy**/**> xy**: widescreen enabled above/below a certain scanline (for backgrounds that contain HUDs and backgrounds).
- **autoHor**: Disables widescreen for this background when it is as wide as the screen and has a horizontal position of 0.
- **autoHor&Ver**(default): Disables widescreen for this background when it is as wide as the screen and has a horizontal and vertical position of 0.
- **crop**: do not draw the left- and right-most 8 pixels (next to the widescreen areas) of the background (for backgrounds blanking some edge pixels, leaving black lines in widescreen, e.g. "*Top Gear 2*").
- **cAuto**: same as "*crop*", except for 2 differences. Only black pixel are not rendered. And lines of black pixel starting in the left crop area are removed entirely, e.g. for "*Super Mario Kart*".
- **dis.**: Disable the background entirely, e.g. to remove HUDs for screenshots for wallpapers.
- **cropAuto**: same as "*crop*", except for 2 differences. Only black pixel are not rendered. And lines of black pixel starting in the left crop area are removed entirely, e.g. for "*Super Mario Kart*".
- **disable**: Disable the background entirely, e.g. to remove HUDs for screenshots for wallpapers.
### Sprites
- **normal**: Sprites are rendered if they are at least partially in the classic content area. So they can only partially reach into the widescreen areas.
Settings for sprites/objects.
- **clip**: Sprites are clipped at the edges of the widescreen areas.
- **safe**(default): Sprites are rendered if they are at least partially in the classic content area. So they can only partially reach into the widescreen areas.
- **unsafe**: Sprites are rendered, even if they are entirely in a widescreen area. Works fine for a view games, like "*Super Mario World*", causes artifacts in many.
- **disab.**: Disable sprites entirely, e.g. to remove characters or HUD elements for screenshots for wallpapers.
- **disable**: Disable sprites entirely, e.g. to remove characters or HUD elements for screenshots for wallpapers.
### Ignore window
- **none**: Apply window effects normally. Widescreen pixels are treated like the nearest non-widescreen pixel.
- **outside**: "*outside*" window effects are ignored, i.e. all pixels are treated like they are at the "*fallback x-coordinate*" for this purpose. This allows Mode 7 widescreen in "*Final Fantasy III*"
- **outside&alw**: Same as outside, but also for "*always*" window effects.
- **all**: Same as outside, but for all window effects. Can for example be used to remove the shadow and meter from "*F-Zero*" for screenshots for wallpapers (requires a "*fallback x-coordinate*" other than 128).
- **outside**(default): "*outside*" window effects are ignored, i.e. all pixels are treated like they are at the "*fallback x-coordinate*" for this purpose. This allows Mode 7 widescreen in "*Final Fantasy III*"
- **outside&always**: Same as outside, but also for "*always*" window effects.
- **all**: Same as outside, but for all window effects. Can for example be used to remove the shadow and meter from "*F-Zero*" for screenshots for wallpapers (requires changing "*fallback x-coordinate*" from 128 to something like 40).
### Fallback x-coordinate
The x-coordinate used as fallback for "*ignore window*"
The x-coordinate used as fallback for "*ignore window*". (defaults to 128 (the center))
### Soft crop
Allows widths at the four edges of the image to be declared uninteresting. So when sizing and placing the image, especially in fullscreen, they can overflow the screen, allowing the significant parts of the image to be larger. So to focus on the top part of "*Super Mario Kart*" set "*bottom*" to 130 and "*top*" to 0. Further tweaking based on your monitor AR and liking may be required.
- **none**: disable soft crop
- **center**: enable soft crop for output/center
- **center**(default): enable soft crop for output/center
- **scale**: enable soft crop for output/center and output/scale
### Top/Bottom/Left/Right
### SC Top/Bottom/Left/Right
The soft crop widths for all four edges.
The soft crop widths for all four edges. (defaults to 10, 10, 20, 20)
## Help Wanted
### Converting C++ Rendering Code to Shaders for Optimization
Currently all the HD rendering is running on the CPU cores. This will have to be moved to the GPU to achieve usable performance. I'd really appreciate any help with that, even if it's just to get started. Please open an issue if you want to contribute, or contact me on Reddit.
## More documentation to come...

View file

@ -28,13 +28,17 @@ auto Configuration::process(Markup::Node document, bool load) -> void {
bind(natural, "Hacks/PPU/Mode7/Wsobj", hacks.ppu.mode7.wsobj);
bind(natural, "Hacks/PPU/Mode7/Igwin", hacks.ppu.mode7.igwin);
bind(natural, "Hacks/PPU/Mode7/Igwinx", hacks.ppu.mode7.igwinx);
bind(natural, "Hacks/PPU/Mode7/WsMode", hacks.ppu.mode7.wsMode);
bind(natural, "Hacks/PPU/Mode7/WsBgCol", hacks.ppu.mode7.wsBgCol);
bind(natural, "Hacks/PPU/Mode7/UnintrMode", hacks.ppu.mode7.unintrMode);
bind(natural, "Hacks/PPU/Mode7/UnintrTop", hacks.ppu.mode7.unintrTop);
bind(natural, "Hacks/PPU/Mode7/UnintrBottom", hacks.ppu.mode7.unintrBottom);
bind(natural, "Hacks/PPU/Mode7/UnintrLeft", hacks.ppu.mode7.unintrLeft);
bind(natural, "Hacks/PPU/Mode7/UnintrRight", hacks.ppu.mode7.unintrRight);
bind(natural, "Hacks/PPU/Mode7/WsMarker", hacks.ppu.mode7.wsMarker);
bind(natural, "Hacks/PPU/Mode7/WsMarkerAlpha", hacks.ppu.mode7.wsMarkerAlpha);
bind(natural, "Hacks/PPU/Mode7/Supersample", hacks.ppu.mode7.supersample);
bind(boolean, "Hacks/PPU/Mode7/Mosaic", hacks.ppu.mode7.mosaic);
bind(natural, "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);

View file

@ -32,20 +32,24 @@ struct Configuration {
uint scale = 2;
uint perspective = 1;
uint widescreen = 72;
uint wsbg1 = 1;
uint wsbg2 = 1;
uint wsbg3 = 1;
uint wsbg4 = 1;
uint wsbg1 = 16;
uint wsbg2 = 16;
uint wsbg3 = 16;
uint wsbg4 = 16;
uint wsobj = 0;
uint igwin = 0;
uint igwin = 1;
uint igwinx = 128;
uint wsMode = 1;
uint wsBgCol = 1;
uint unintrMode = 1;
uint unintrTop = 10;
uint unintrBottom = 10;
uint unintrLeft = 20;
uint unintrRight = 20;
uint wsMarker = 0;
uint wsMarkerAlpha = 1;
uint supersample = 1;
bool mosaic = false;
uint mosaic = 1;
} mode7;
} ppu;
struct DSP {

View file

@ -10,15 +10,21 @@ auto PPUfast::Line::renderBackground(PPUfast::IO::Background& self, uint source)
bool autoCrop = false;
int ws = (int)ppufast.widescreen();
if(ws > 0) {
if(wsConf == 12) {
if(ppufast.wsOverride()) {
ws = 0;
} else if(wsConf == 12) {
ws = -8;
} else if(wsConf == 13) {
ws = 0;
autoCrop = true;
} else if(wsConf == 15) {
if (self.tileSize == 0 && self.hoffset == 0) ws = 0;
} else if(wsConf == 16) {
if (self.tileSize == 0 && self.hoffset == 0 && self.voffset == 0) ws = 0;
} else if(wsConf == 0 || (wsConf != 1 && (((wsConf % 2) != 0) == (y < (((int)(wsConf / 2)) * 40))))) {
ws = 0;
}
}
}
array<bool[256]> windowAbove;
array<bool[256]> windowBelow;

View file

@ -2,11 +2,11 @@ uint PPUfast::Line::start = 0;
uint PPUfast::Line::count = 0;
auto PPUfast::Line::flush() -> void {
ppufast.ind = 0;
uint perspCorMode = ppufast.hdPerspective();
if(perspCorMode > 0) {
#define isLineMode7(l) (l.io.bg1.tileMode == TileMode::Mode7 \
&& !l.io.displayDisable && (l.io.bg1.aboveEnable || l.io.bg1.belowEnable))
ppufast.ind = 0;
bool state = false;
uint y;
int offsPart = 8;
@ -104,6 +104,20 @@ auto PPUfast::Line::flush() -> void {
}
}
}
} else if(ppufast.wsOverrideCandidate()) {
#define isLineMode7(l) (l.io.bg1.tileMode == TileMode::Mode7 \
&& !l.io.displayDisable && (l.io.bg1.aboveEnable || l.io.bg1.belowEnable))
for(uint y = 0; y < Line::count; y++) {
if(isLineMode7(ppufast.lines[Line::start + y])) {
ppufast.ind = 1;
ppufast.starts[0] = -1;
ppufast.ends[0] = -1;
ppufast.startsp[0] = -1;
ppufast.endsp[0] = -1;
break;
}
}
#undef isLineMode7
}
if(Line::count) {
@ -138,9 +152,22 @@ auto PPUfast::Line::render() -> void {
auto belowColor = hires ? cgram[0] : io.col.fixedColor;
uint xa = (hd || ss) && ppufast.interlace() && ppufast.field() ? 256 * scale * scale / 2 : 0;
uint xb = !(hd || ss) ? 256 : ppufast.interlace() && !ppufast.field() ? (256+2*ppufast.widescreen()) * scale * scale / 2 : (256+2*ppufast.widescreen()) * scale * scale;
for(uint x = xa; x < xb; x++) {
above[x] = {Source::COL, 0, aboveColor};
below[x] = {Source::COL, 0, belowColor};
if (hd && ppufast.wsBgCol()) {
for(uint x = xa; x < xb; x++) {
int cx = (x % ((256+2*ppufast.widescreen()) * scale)) - (ppufast.widescreen() * scale);
if (cx >= 0 && cx <= (256 * scale)) {
above[x] = {Source::COL, 0, aboveColor};
below[x] = {Source::COL, 0, belowColor};
} else {
above[x] = {Source::COL, 0, 0};
below[x] = {Source::COL, 0, 0};
}
}
} else {
for(uint x = xa; x < xb; x++) {
above[x] = {Source::COL, 0, aboveColor};
below[x] = {Source::COL, 0, belowColor};
}
}
renderBackground(io.bg1, Source::BG1);
@ -152,27 +179,41 @@ auto PPUfast::Line::render() -> void {
renderWindow(io.col.window, io.col.window.aboveMask, windowAbove);
renderWindow(io.col.window, io.col.window.belowMask, windowBelow);
uint wsm = (ppufast.widescreen() == 0 || ppufast.wsOverride()) ? 0 : ppufast.wsMarker();
uint wsma = ppufast.wsMarkerAlpha();
auto luma = io.displayBrightness << 15;
if(hd) for(uint x : range((256+2*ppufast.widescreen()) * scale * scale)) {
*output++ = luma | pixel((x / scale % (256+2*ppufast.widescreen()) - ppufast.widescreen()), above[x], below[x]);
*output++ = luma | pixel((x / scale % (256+2*ppufast.widescreen()) - ppufast.widescreen()), above[x], below[x], wsm, wsma);
} else if(width == 256) for(uint x : range(256)) {
*output++ = luma | pixel(x, above[x], below[x]);
*output++ = luma | pixel(x, above[x], below[x], wsm, wsma);
} else if(!hires) for(uint x : range(256)) {
auto color = luma | pixel(x, above[x], below[x]);
auto color = luma | pixel(x, above[x], below[x], wsm, wsma);
*output++ = color;
*output++ = color;
} else for(uint x : range(256)) {
*output++ = luma | pixel(x, below[x], above[x]);
*output++ = luma | pixel(x, above[x], below[x]);
*output++ = luma | pixel(x, below[x], above[x], wsm, wsma);
*output++ = luma | pixel(x, above[x], below[x], wsm, wsma);
}
}
auto PPUfast::Line::pixel(uint x, Pixel above, Pixel below) const -> uint15 {
auto PPUfast::Line::pixel(uint x, Pixel above, Pixel below, uint wsm, uint wsma) const -> uint15 {
uint15 r = 0;
if(!windowAbove[ppufast.winXad(x, false)]) above.color = 0x0000;
if(!windowBelow[ppufast.winXad(x, true)]) return above.color;
if(!io.col.enable[above.source]) return above.color;
if(!io.col.blendMode) return blend(above.color, io.col.fixedColor, io.col.halve && windowAbove[ppufast.winXad(x, false)]);
return blend(above.color, below.color, io.col.halve && windowAbove[ppufast.winXad(x, false)] && below.source != Source::COL);
else if(!windowBelow[ppufast.winXad(x, true)]) r = above.color;
else if(!io.col.enable[above.source]) r = above.color;
else if(!io.col.blendMode) r = blend(above.color, io.col.fixedColor, io.col.halve && windowAbove[ppufast.winXad(x, false)]);
else r = blend(above.color, below.color, io.col.halve && windowAbove[ppufast.winXad(x, false)] && below.source != Source::COL);
if(wsm > 0) {
if(wsm == 1 && (x == 0 || x == 255)
|| wsm == 2 && (!(x >= 0 && x <= 255))) {
int b = wsm == 2 ? 0 : ((y / 4) % 2 == 0) ? 0 : 31;
r = ((((((r >> 10) & 31) * wsma) + b) / (wsma + 1)) << 10)
+ ((((((r >> 5) & 31) * wsma) + b) / (wsma + 1)) << 5)
+ ((((((r >> 0) & 31) * wsma) + b) / (wsma + 1)) << 0);
}
}
return r;
}
auto PPUfast::Line::blend(uint x, uint y, bool halve) const -> uint15 {

View file

@ -4,8 +4,9 @@ auto PPUfast::Line::renderMode7(PPUfast::IO::Background& self, uint source) -> v
if(io.extbg && source == Source::BG1) return;
//HD mode 7 support
if(!ppufast.hdMosaic() || !self.mosaicEnable || !io.mosaicSize) {
if(ppufast.hdScale() > 0) return renderMode7HD(self, source);
if(ppufast.hdScale() > 0 && (ppufast.hdMosaic() != 0
|| !self.mosaicEnable || !io.mosaicSize)) {
return renderMode7HD(self, source);
}
int Y = this->y - (self.mosaicEnable ? this->y % (1 + io.mosaicSize) : 0);

View file

@ -1,7 +1,8 @@
auto PPUfast::Line::renderMode7HD(PPUfast::IO::Background& self, uint source) -> void {
const bool extbg = source == Source::BG2;
const uint sampScale = ppufast.hdSupersample();
const uint scale = ppufast.hdScale() * sampScale;
bool mosSing = self.mosaicEnable && io.mosaicSize && ppufast.hdMosaic() == 1;
const uint sampScale = mosSing ? 1 : ppufast.hdSupersample();
const uint scale = mosSing ? 1 : ppufast.hdScale() * sampScale;
int sampSize = sampScale < 2 ? 0 : (256+2*ppufast.widescreen()) * 4 * scale/sampScale;
uint *sampTmp = new uint[sampSize];
@ -118,6 +119,10 @@ auto PPUfast::Line::renderMode7HD(PPUfast::IO::Background& self, uint source) ->
}
}
if(mosSing) {
if(self.aboveEnable && !windowAbove[ppufast.winXad(x, false)]) plotAbove(x, pixel.source, pixel.priority, pixel.color);
if(self.belowEnable && !windowBelow[ppufast.winXad(x, true)]) plotBelow(x, pixel.source, pixel.priority, pixel.color);
} else
if(sampScale == 1) {
if(!skip && doAbove && (!extbg || pixel.priority > above->priority)) *above = pixel;
if(!skip && doBelow && (!extbg || pixel.priority > below->priority)) *below = pixel;

View file

@ -2,6 +2,8 @@ auto PPUfast::Line::renderObject(PPUfast::IO::Object& self) -> void {
if(!self.aboveEnable && !self.belowEnable) return;
if(ppufast.wsobj() == 2) return;
uint wsobj = ppufast.wsOverride() ? 3 : ppufast.wsobj();
array<bool[256]> windowAbove;
array<bool[256]> windowBelow;
renderWindow(self.window, self.window.aboveEnable, windowAbove);
@ -29,8 +31,7 @@ auto PPUfast::Line::renderObject(PPUfast::IO::Object& self) -> void {
item.height = heights[self.baseSize];
}
if(ppufast.wsobj() == 0
&& object.x > 256 && object.x + item.width - 1 < 512) continue;
if((wsobj == 0 || wsobj == 3) && object.x > 256 && object.x + item.width - 1 < 512) continue;
uint height = item.height >> self.interlace;
if((y >= object.y && y < object.y + height)
|| (object.y + height >= 256 && y < (object.y + height & 255))
@ -124,7 +125,7 @@ auto PPUfast::Line::renderObject(PPUfast::IO::Object& self) -> void {
uint source = palette[x] < 192 ? Source::OBJ1 : Source::OBJ2;
int xc = x;//
if(xc > 384) xc -= 512; // 256+256/2
if(xc < wsl || xc >= wsr) continue;
if(xc < wsl || xc >= wsr || (wsobj == 3 && (xc < 0 || xc >= 256))) continue;
if(self.aboveEnable && !windowAbove[ppufast.winXad(x, false)]) plotAbove(xc, source, priority[x], cgram[palette[x]]);
if(self.belowEnable && !windowBelow[ppufast.winXad(x, true)]) plotBelow(xc, source, priority[x], cgram[palette[x]]);
}

View file

@ -23,22 +23,26 @@ auto PPUfast::ss() const -> bool { return latch.ss; }
auto PPUfast::hdScale() const -> uint { return configuration.hacks.ppu.mode7.scale; }
auto PPUfast::hdPerspective() const -> uint { return configuration.hacks.ppu.mode7.perspective; }
auto PPUfast::hdSupersample() const -> uint { return configuration.hacks.ppu.mode7.supersample; }
auto PPUfast::hdMosaic() const -> bool { return configuration.hacks.ppu.mode7.mosaic; }
auto PPUfast::widescreen() const -> uint { return configuration.hacks.ppu.mode7.widescreen; } // 64 / 0 #widescreenextension
auto PPUfast::hdMosaic() const -> uint { return configuration.hacks.ppu.mode7.mosaic; }
auto PPUfast::widescreen() const -> uint { return configuration.hacks.ppu.mode7.wsMode == 0 ? 0 : configuration.hacks.ppu.mode7.widescreen; }
auto PPUfast::wsbg(uint bg) const -> uint {
if (bg == Source::BG1) return configuration.hacks.ppu.mode7.wsbg1;
if (bg == Source::BG2) return configuration.hacks.ppu.mode7.wsbg2;
if (bg == Source::BG3) return configuration.hacks.ppu.mode7.wsbg3;
if (bg == Source::BG4) return configuration.hacks.ppu.mode7.wsbg4;
return 0;
}
return 0; }
auto PPUfast::wsobj() const -> uint { return configuration.hacks.ppu.mode7.wsobj; }
auto PPUfast::winXad(uint x, bool bel) const -> uint {
return (configuration.hacks.ppu.mode7.igwin != 0 && (configuration.hacks.ppu.mode7.igwin >= 3
|| configuration.hacks.ppu.mode7.igwin >= 2 && ((bel ? io.col.window.belowMask : io.col.window.aboveMask) == 0)
|| configuration.hacks.ppu.mode7.igwin >= 1 && ((bel ? io.col.window.belowMask : io.col.window.aboveMask) == 2)))
? configuration.hacks.ppu.mode7.igwinx : (x < 0 ? 0 : (x > 255 ? 255 : x));
}
? configuration.hacks.ppu.mode7.igwinx : (x < 0 ? 0 : (x > 255 ? 255 : x)); }
auto PPUfast::wsOverrideCandidate() const -> bool { return configuration.hacks.ppu.mode7.wsMode == 1; }
auto PPUfast::wsOverride() const -> bool { return ind < 1 && wsOverrideCandidate(); }
auto PPUfast::wsBgCol() const -> bool { return configuration.hacks.ppu.mode7.wsBgCol == 2
|| configuration.hacks.ppu.mode7.wsBgCol == 1 && wsOverride(); }
auto PPUfast::wsMarker() const -> uint { return configuration.hacks.ppu.mode7.wsMarker; }
auto PPUfast::wsMarkerAlpha() const -> uint { return configuration.hacks.ppu.mode7.wsMarkerAlpha; }
PPUfast::PPUfast() {
output = new uint32[2304 * 2304] + 72 * 2304; //overscan offset

View file

@ -15,11 +15,16 @@ struct PPUfast : Thread, PPUcounter {
alwaysinline auto hdScale() const -> uint;
alwaysinline auto hdPerspective() const -> uint;
alwaysinline auto hdSupersample() const -> uint;
alwaysinline auto hdMosaic() const -> bool;
alwaysinline auto hdMosaic() const -> uint;
alwaysinline auto widescreen() const -> uint;
alwaysinline auto wsbg(uint bg) const -> uint;
alwaysinline auto wsobj() const -> uint;
alwaysinline auto winXad(uint x, bool bel) const -> uint;
alwaysinline auto wsOverrideCandidate() const -> bool;
alwaysinline auto wsOverride() const -> bool;
alwaysinline auto wsBgCol() const -> bool;
alwaysinline auto wsMarker() const -> uint;
alwaysinline auto wsMarkerAlpha() const -> uint;
//ppu.cpp
PPUfast();
@ -275,8 +280,8 @@ public:
//line.cpp
static auto flush() -> void;
auto render() -> void;
auto pixel(uint x, Pixel above, Pixel below) const -> uint15;
auto blend(uint x, uint y, bool halve) const -> uint15;
alwaysinline auto pixel(uint x, Pixel above, Pixel below, uint wsm, uint wsma) const -> uint15;
alwaysinline auto blend(uint x, uint y, bool halve) const -> uint15;
alwaysinline auto directColor(uint paletteIndex, uint paletteColor) const -> uint15;
alwaysinline auto plotAbove(int x, uint source, uint priority, uint color) -> void;
alwaysinline auto plotBelow(int x, uint source, uint priority, uint color) -> void;
@ -284,7 +289,7 @@ public:
//background.cpp
auto renderBackground(PPUfast::IO::Background&, uint source) -> void;
auto getTile(PPUfast::IO::Background&, uint hoffset, uint voffset) -> uint;
alwaysinline auto getTile(PPUfast::IO::Background&, uint hoffset, uint voffset) -> uint;
//mode7.cpp
auto renderMode7(PPUfast::IO::Background&, uint source) -> void;
@ -297,8 +302,8 @@ public:
auto renderObject(PPUfast::IO::Object&) -> void;
//window.cpp
auto renderWindow(PPUfast::IO::WindowLayer&, bool, array<bool[256]>&) -> void;
auto renderWindow(PPUfast::IO::WindowColor&, uint, array<bool[256]>&) -> void;
alwaysinline auto renderWindow(PPUfast::IO::WindowLayer&, bool, array<bool[256]>&) -> void;
alwaysinline auto renderWindow(PPUfast::IO::WindowColor&, uint, array<bool[256]>&) -> void;
//[unserialized]
uint9 y; //constant

View file

@ -253,7 +253,9 @@ auto Presentation::resizeViewport() -> void {
uint layoutWidth = viewportLayout.geometry().width();
uint layoutHeight = viewportLayout.geometry().height();
uint widescreen = settings.emulator.hack.ppu.mode7.scale > 0 ? settings.emulator.hack.ppu.mode7.widescreen : 0;
uint widescreen = (settings.emulator.hack.ppu.mode7.scale > 0
&& settings.emulator.hack.ppu.mode7.wsMode > 0)
? settings.emulator.hack.ppu.mode7.widescreen : 0;
uint unintrMode = settings.emulator.hack.ppu.mode7.unintrMode;
uint unintrTop = settings.emulator.hack.ppu.mode7.unintrTop;
uint unintrBottom = settings.emulator.hack.ppu.mode7.unintrBottom;
@ -312,7 +314,7 @@ auto Presentation::resizeWindow() -> void {
if(fullScreen()) return;
if(maximized()) setMaximized(false);
int widescreen = settings.emulator.hack.ppu.mode7.scale > 0 ? settings.emulator.hack.ppu.mode7.widescreen : 0; // 64 / 0 #widescreenextension
int widescreen = settings.emulator.hack.ppu.mode7.wsMode > 0 ? settings.emulator.hack.ppu.mode7.widescreen : 0; // 64 / 0 #widescreenextension
uint width = (256+2*widescreen) * (settings.video.aspectCorrection && !widescreen ? 8.0 / 7.0 : 1.0);
uint height = (settings.video.overscan ? 240.0 : 224.0);
uint multiplier = max(1, settings.video.multiplier);

View file

@ -21,11 +21,15 @@ auto Program::hackCompatibility() -> void {
emulator->configure("Hacks/PPU/Mode7/Wsobj", settings.emulator.hack.ppu.mode7.wsobj);
emulator->configure("Hacks/PPU/Mode7/Igwin", settings.emulator.hack.ppu.mode7.igwin);
emulator->configure("Hacks/PPU/Mode7/Igwinx", settings.emulator.hack.ppu.mode7.igwinx);
emulator->configure("Hacks/PPU/Mode7/WsMode", settings.emulator.hack.ppu.mode7.wsMode);
emulator->configure("Hacks/PPU/Mode7/WsBgCol", settings.emulator.hack.ppu.mode7.wsBgCol);
emulator->configure("Hacks/PPU/Mode7/UnintrMode", settings.emulator.hack.ppu.mode7.unintrMode);
emulator->configure("Hacks/PPU/Mode7/UnintrTop", settings.emulator.hack.ppu.mode7.unintrTop);
emulator->configure("Hacks/PPU/Mode7/UnintrBottom", settings.emulator.hack.ppu.mode7.unintrBottom);
emulator->configure("Hacks/PPU/Mode7/UnintrLeft", settings.emulator.hack.ppu.mode7.unintrLeft);
emulator->configure("Hacks/PPU/Mode7/UnintrRight", settings.emulator.hack.ppu.mode7.unintrRight);
emulator->configure("Hacks/PPU/Mode7/WsMarker", settings.emulator.hack.ppu.mode7.wsMarker);
emulator->configure("Hacks/PPU/Mode7/WsMarkerAlpha", settings.emulator.hack.ppu.mode7.wsMarkerAlpha);
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);

View file

@ -36,15 +36,6 @@ auto EmulatorSettings::create() -> void {
autoLoadStateOnLoad.setText("Auto-resume on load").setChecked(settings.emulator.autoLoadStateOnLoad).onToggle([&] {
settings.emulator.autoLoadStateOnLoad = autoLoadStateOnLoad.checked();
});
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();
emulator->configure("Hacks/DSP/Fast", settings.emulator.hack.dsp.fast);
});
cubicInterpolation.setText("Cubic interpolation").setChecked(settings.emulator.hack.dsp.cubic).onToggle([&] {
settings.emulator.hack.dsp.cubic = cubicInterpolation.checked();
emulator->configure("Hacks/DSP/Cubic", settings.emulator.hack.dsp.cubic);
});
coprocessorLabel.setText("Coprocessors").setFont(Font().setBold());
coprocessorsDelayedSyncOption.setText("Fast mode").setChecked(settings.emulator.hack.coprocessors.delayedSync).onToggle([&] {
settings.emulator.hack.coprocessors.delayedSync = coprocessorsDelayedSyncOption.checked();
@ -58,8 +49,8 @@ auto EmulatorSettings::create() -> void {
settings.emulator.hack.fastSuperFX = superFXClock.position() * 10 + 100;
superFXValue.setText({settings.emulator.hack.fastSuperFX, "%"});
}).doChange();
ppuLabel.setText("PPU (video)").setFont(Font().setBold());
fastPPU.setText("Fast mode [required for HD Mode 7 / bsnes-hd]").setChecked(settings.emulator.hack.ppu.fast).onToggle([&] {
ppuDspLabel.setText("PPU (video) / DSP (audio)").setFont(Font().setBold());
fastPPU.setText("Fast PPU mode [required for HD Mode 7 / bsnes-hd]").setChecked(settings.emulator.hack.ppu.fast).onToggle([&] {
settings.emulator.hack.ppu.fast = fastPPU.checked();
if(!fastPPU.checked()) {
noSpriteLimit.setEnabled(false).setChecked(false).doToggle();
@ -70,6 +61,14 @@ auto EmulatorSettings::create() -> void {
noSpriteLimit.setText("No sprite limit").setChecked(settings.emulator.hack.ppu.noSpriteLimit).onToggle([&] {
settings.emulator.hack.ppu.noSpriteLimit = noSpriteLimit.checked();
});
fastDSP.setText("Fast DSP mode").setChecked(settings.emulator.hack.dsp.fast).onToggle([&] {
settings.emulator.hack.dsp.fast = fastDSP.checked();
emulator->configure("Hacks/DSP/Fast", settings.emulator.hack.dsp.fast);
});
cubicInterpolation.setText("Cubic interpolation").setChecked(settings.emulator.hack.dsp.cubic).onToggle([&] {
settings.emulator.hack.dsp.cubic = cubicInterpolation.checked();
emulator->configure("Hacks/DSP/Cubic", settings.emulator.hack.dsp.cubic);
});
mode7Label.setText("HD Mode 7 / bsnes-hd").setFont(Font().setBold());
mode7ScaleLabel.setText("Scale:");
mode7Scale.append(ComboButtonItem().setText("disable").setProperty("multiplier", 0));
@ -123,20 +122,28 @@ auto EmulatorSettings::create() -> void {
settings.emulator.hack.ppu.mode7.supersample = mode7Supersample.selected().property("sss").natural();
emulator->configure("Hacks/PPU/Mode7/Supersample", settings.emulator.hack.ppu.mode7.supersample);
});
mode7Mosaic.setText("Keep Mosaics non-HD").setChecked(settings.emulator.hack.ppu.mode7.mosaic).onToggle([&] {
settings.emulator.hack.ppu.mode7.mosaic = mode7Mosaic.checked();
mode7MosaicLabel.setText("Mosaic:");
mode7Mosaic.append(ComboButtonItem().setText("non-HD").setProperty("mode", 0));
mode7Mosaic.append(ComboButtonItem().setText("1x scale").setProperty("mode", 1));
mode7Mosaic.append(ComboButtonItem().setText("ignore").setProperty("mode", 2));
for(uint n = 0; n <= 2; n++) {
if(mode7Mosaic.item(n).property("mode").natural() == settings.emulator.hack.ppu.mode7.mosaic)
mode7Mosaic.item(n).setSelected();
}
mode7Mosaic.onChange([&] {
settings.emulator.hack.ppu.mode7.mosaic = mode7Mosaic.selected().property("mode").natural();
emulator->configure("Hacks/PPU/Mode7/Mosaic", settings.emulator.hack.ppu.mode7.mosaic);
});
mode7WidescreenLabel.setText("Widescreen:");
mode7Widescreen.append(ComboButtonItem().setText(" none ").setProperty("adval", 0));
mode7Widescreen.append(ComboButtonItem().setText(" 4 : 3").setProperty("adval", 24));
mode7Widescreen.append(ComboButtonItem().setText("16 :10").setProperty("adval", 56));
mode7Widescreen.append(ComboButtonItem().setText("HDcrop").setProperty("adval", 64));
mode7Widescreen.append(ComboButtonItem().setText("16 : 9").setProperty("adval", 72));
mode7Widescreen.append(ComboButtonItem().setText("21 :10").setProperty("adval", 104));
mode7Widescreen.append(ComboButtonItem().setText("21 : 9").setProperty("adval", 136));
mode7Widescreen.append(ComboButtonItem().setText(" 8 : 3").setProperty("adval", 168));
for(uint n = 0; n < 8; n++) {
mode7WidescreenLabel.setText("Aspect ratio:");
mode7Widescreen.append(ComboButtonItem().setText("4:3").setProperty("adval", 24));
mode7Widescreen.append(ComboButtonItem().setText("16:10").setProperty("adval", 56));
mode7Widescreen.append(ComboButtonItem().setText("HD").setProperty("adval", 64));
mode7Widescreen.append(ComboButtonItem().setText("16:9").setProperty("adval", 72));
mode7Widescreen.append(ComboButtonItem().setText("21:10").setProperty("adval", 104));
mode7Widescreen.append(ComboButtonItem().setText("21:9").setProperty("adval", 136));
mode7Widescreen.append(ComboButtonItem().setText("8:3").setProperty("adval", 168));
for(uint n = 0; n < 7; n++) {
if(mode7Widescreen.item(n).property("adval").natural() == settings.emulator.hack.ppu.mode7.widescreen)
mode7Widescreen.item(n).setSelected();
}
@ -146,8 +153,8 @@ auto EmulatorSettings::create() -> void {
presentation.resizeViewport();
});
wsBG1Label.setText("BG1:");
wsBG1.append(ComboButtonItem().setText(" off").setProperty("wsbgmode", 0));
wsBG1.append(ComboButtonItem().setText(" on ").setProperty("wsbgmode", 1));
wsBG1.append(ComboButtonItem().setText("off").setProperty("wsbgmode", 0));
wsBG1.append(ComboButtonItem().setText("on").setProperty("wsbgmode", 1));
wsBG1.append(ComboButtonItem().setText("< 40").setProperty("wsbgmode", 2));
wsBG1.append(ComboButtonItem().setText("> 40").setProperty("wsbgmode", 3));
wsBG1.append(ComboButtonItem().setText("< 80").setProperty("wsbgmode", 4));
@ -158,10 +165,12 @@ auto EmulatorSettings::create() -> void {
wsBG1.append(ComboButtonItem().setText(">160").setProperty("wsbgmode", 9));
wsBG1.append(ComboButtonItem().setText("<200").setProperty("wsbgmode", 10));
wsBG1.append(ComboButtonItem().setText(">200").setProperty("wsbgmode", 11));
wsBG1.append(ComboButtonItem().setText("autoHor").setProperty("wsbgmode", 15));
wsBG1.append(ComboButtonItem().setText("autoHor&Ver").setProperty("wsbgmode", 16));
wsBG1.append(ComboButtonItem().setText("crop").setProperty("wsbgmode", 12));
wsBG1.append(ComboButtonItem().setText("cAut").setProperty("wsbgmode", 13));
wsBG1.append(ComboButtonItem().setText("dis.").setProperty("wsbgmode", 14));
for(uint n = 0; n <= 14; n++) {
wsBG1.append(ComboButtonItem().setText("cropAuto").setProperty("wsbgmode", 13));
wsBG1.append(ComboButtonItem().setText("disable").setProperty("wsbgmode", 14));
for(uint n = 0; n <= 16; n++) {
if(wsBG1.item(n).property("wsbgmode").natural() == settings.emulator.hack.ppu.mode7.wsbg1)
wsBG1.item(n).setSelected();
}
@ -170,8 +179,8 @@ auto EmulatorSettings::create() -> void {
emulator->configure("Hacks/PPU/Mode7/Wsbg1", settings.emulator.hack.ppu.mode7.wsbg1);
});
wsBG2Label.setText("BG2:");
wsBG2.append(ComboButtonItem().setText(" off").setProperty("wsbgmode", 0));
wsBG2.append(ComboButtonItem().setText(" on ").setProperty("wsbgmode", 1));
wsBG2.append(ComboButtonItem().setText("off").setProperty("wsbgmode", 0));
wsBG2.append(ComboButtonItem().setText("on").setProperty("wsbgmode", 1));
wsBG2.append(ComboButtonItem().setText("< 40").setProperty("wsbgmode", 2));
wsBG2.append(ComboButtonItem().setText("> 40").setProperty("wsbgmode", 3));
wsBG2.append(ComboButtonItem().setText("< 80").setProperty("wsbgmode", 4));
@ -182,10 +191,12 @@ auto EmulatorSettings::create() -> void {
wsBG2.append(ComboButtonItem().setText(">160").setProperty("wsbgmode", 9));
wsBG2.append(ComboButtonItem().setText("<200").setProperty("wsbgmode", 10));
wsBG2.append(ComboButtonItem().setText(">200").setProperty("wsbgmode", 11));
wsBG2.append(ComboButtonItem().setText("autoHor").setProperty("wsbgmode", 15));
wsBG2.append(ComboButtonItem().setText("autoHor&Ver").setProperty("wsbgmode", 16));
wsBG2.append(ComboButtonItem().setText("crop").setProperty("wsbgmode", 12));
wsBG2.append(ComboButtonItem().setText("cAut").setProperty("wsbgmode", 13));
wsBG2.append(ComboButtonItem().setText("dis.").setProperty("wsbgmode", 14));
for(uint n = 0; n <= 14; n++) {
wsBG2.append(ComboButtonItem().setText("cropAuto").setProperty("wsbgmode", 13));
wsBG2.append(ComboButtonItem().setText("disable").setProperty("wsbgmode", 14));
for(uint n = 0; n <= 16; n++) {
if(wsBG2.item(n).property("wsbgmode").natural() == settings.emulator.hack.ppu.mode7.wsbg2)
wsBG2.item(n).setSelected();
}
@ -194,8 +205,8 @@ auto EmulatorSettings::create() -> void {
emulator->configure("Hacks/PPU/Mode7/Wsbg2", settings.emulator.hack.ppu.mode7.wsbg2);
});
wsBG3Label.setText("BG3:");
wsBG3.append(ComboButtonItem().setText(" off").setProperty("wsbgmode", 0));
wsBG3.append(ComboButtonItem().setText(" on ").setProperty("wsbgmode", 1));
wsBG3.append(ComboButtonItem().setText("off").setProperty("wsbgmode", 0));
wsBG3.append(ComboButtonItem().setText("on").setProperty("wsbgmode", 1));
wsBG3.append(ComboButtonItem().setText("< 40").setProperty("wsbgmode", 2));
wsBG3.append(ComboButtonItem().setText("> 40").setProperty("wsbgmode", 3));
wsBG3.append(ComboButtonItem().setText("< 80").setProperty("wsbgmode", 4));
@ -206,10 +217,12 @@ auto EmulatorSettings::create() -> void {
wsBG3.append(ComboButtonItem().setText(">160").setProperty("wsbgmode", 9));
wsBG3.append(ComboButtonItem().setText("<200").setProperty("wsbgmode", 10));
wsBG3.append(ComboButtonItem().setText(">200").setProperty("wsbgmode", 11));
wsBG3.append(ComboButtonItem().setText("autoHor").setProperty("wsbgmode", 15));
wsBG3.append(ComboButtonItem().setText("autoHor&Ver").setProperty("wsbgmode", 16));
wsBG3.append(ComboButtonItem().setText("crop").setProperty("wsbgmode", 12));
wsBG3.append(ComboButtonItem().setText("cAut").setProperty("wsbgmode", 13));
wsBG3.append(ComboButtonItem().setText("dis.").setProperty("wsbgmode", 14));
for(uint n = 0; n <= 14; n++) {
wsBG3.append(ComboButtonItem().setText("cropAuto").setProperty("wsbgmode", 13));
wsBG3.append(ComboButtonItem().setText("disable").setProperty("wsbgmode", 14));
for(uint n = 0; n <= 16; n++) {
if(wsBG3.item(n).property("wsbgmode").natural() == settings.emulator.hack.ppu.mode7.wsbg3)
wsBG3.item(n).setSelected();
}
@ -218,8 +231,8 @@ auto EmulatorSettings::create() -> void {
emulator->configure("Hacks/PPU/Mode7/Wsbg3", settings.emulator.hack.ppu.mode7.wsbg3);
});
wsBG4Label.setText("BG4:");
wsBG4.append(ComboButtonItem().setText(" off").setProperty("wsbgmode", 0));
wsBG4.append(ComboButtonItem().setText(" on ").setProperty("wsbgmode", 1));
wsBG4.append(ComboButtonItem().setText("off").setProperty("wsbgmode", 0));
wsBG4.append(ComboButtonItem().setText("on").setProperty("wsbgmode", 1));
wsBG4.append(ComboButtonItem().setText("< 40").setProperty("wsbgmode", 2));
wsBG4.append(ComboButtonItem().setText("> 40").setProperty("wsbgmode", 3));
wsBG4.append(ComboButtonItem().setText("< 80").setProperty("wsbgmode", 4));
@ -230,10 +243,12 @@ auto EmulatorSettings::create() -> void {
wsBG4.append(ComboButtonItem().setText(">160").setProperty("wsbgmode", 9));
wsBG4.append(ComboButtonItem().setText("<200").setProperty("wsbgmode", 10));
wsBG4.append(ComboButtonItem().setText(">200").setProperty("wsbgmode", 11));
wsBG4.append(ComboButtonItem().setText("autoHor").setProperty("wsbgmode", 15));
wsBG4.append(ComboButtonItem().setText("autoHor&Ver").setProperty("wsbgmode", 16));
wsBG4.append(ComboButtonItem().setText("crop").setProperty("wsbgmode", 12));
wsBG4.append(ComboButtonItem().setText("cAut").setProperty("wsbgmode", 13));
wsBG4.append(ComboButtonItem().setText("dis.").setProperty("wsbgmode", 14));
for(uint n = 0; n <= 14; n++) {
wsBG4.append(ComboButtonItem().setText("cropAuto").setProperty("wsbgmode", 13));
wsBG4.append(ComboButtonItem().setText("disable").setProperty("wsbgmode", 14));
for(uint n = 0; n <= 16; n++) {
if(wsBG4.item(n).property("wsbgmode").natural() == settings.emulator.hack.ppu.mode7.wsbg4)
wsBG4.item(n).setSelected();
}
@ -242,11 +257,12 @@ auto EmulatorSettings::create() -> void {
emulator->configure("Hacks/PPU/Mode7/Wsbg4", settings.emulator.hack.ppu.mode7.wsbg4);
});
wsObjLabel.setText("Sprites:");
wsObj.append(ComboButtonItem().setText("normal").setProperty("mode", 0));
wsObj.append(ComboButtonItem().setText("clip").setProperty("mode", 3));
wsObj.append(ComboButtonItem().setText("safe").setProperty("mode", 0));
wsObj.append(ComboButtonItem().setText("unsafe").setProperty("mode", 1));
wsObj.append(ComboButtonItem().setText("disab.").setProperty("mode", 2));
for(uint n = 0; n < 3; n++) {
if(wsObj.item(n).property("mode").natural() == settings.emulator.hack.ppu.mode7.igwin)
wsObj.append(ComboButtonItem().setText("disable").setProperty("mode", 2));
for(uint n = 0; n <= 3; n++) {
if(wsObj.item(n).property("mode").natural() == settings.emulator.hack.ppu.mode7.wsobj)
wsObj.item(n).setSelected();
}
wsObj.onChange([&] {
@ -256,7 +272,7 @@ auto EmulatorSettings::create() -> void {
igwinLabel.setText("Ignore window:");
igwin.append(ComboButtonItem().setText("none").setProperty("mode", 0));
igwin.append(ComboButtonItem().setText("outside").setProperty("mode", 1));
igwin.append(ComboButtonItem().setText("outs&alw").setProperty("mode", 2));
igwin.append(ComboButtonItem().setText("outside&always").setProperty("mode", 2));
igwin.append(ComboButtonItem().setText("all").setProperty("mode", 3));
for(uint n = 0; n < 4; n++) {
if(igwin.item(n).property("mode").natural() == settings.emulator.hack.ppu.mode7.igwin)
@ -266,7 +282,7 @@ auto EmulatorSettings::create() -> void {
settings.emulator.hack.ppu.mode7.igwin = igwin.selected().property("mode").natural();
emulator->configure("Hacks/PPU/Mode7/Igwin", settings.emulator.hack.ppu.mode7.igwin);
});
igwinxLabel.setText("Fallback x-coordinate:");
igwinxLabel.setText("IW fallback x-coordinate:");
igwinx.append(ComboButtonItem().setText(" 40").setProperty("col", 40));
igwinx.append(ComboButtonItem().setText(" 88").setProperty("col", 88));
igwinx.append(ComboButtonItem().setText("128").setProperty("col", 128));
@ -280,6 +296,34 @@ auto EmulatorSettings::create() -> void {
settings.emulator.hack.ppu.mode7.igwinx = igwinx.selected().property("col").natural();
emulator->configure("Hacks/PPU/Mode7/Igwinx", settings.emulator.hack.ppu.mode7.igwinx);
});
wsBgColLabel.setText("WS bg:");
wsBgCol.append(ComboButtonItem().setText("color").setProperty("mode", 0));
wsBgCol.append(ComboButtonItem().setText("auto").setProperty("mode", 1));
wsBgCol.append(ComboButtonItem().setText("black").setProperty("mode", 2));
for(uint n = 0; n <= 2; n++) {
if(wsBgCol.item(n).property("mode").natural() == settings.emulator.hack.ppu.mode7.wsBgCol)
wsBgCol.item(n).setSelected();
}
wsBgCol.onChange([&] {
settings.emulator.hack.ppu.mode7.wsBgCol = wsBgCol.selected().property("mode").natural();
emulator->configure("Hacks/PPU/Mode7/WsBgCol", settings.emulator.hack.ppu.mode7.wsBgCol);
});
wsModeLabel.setText("Widescreen:");
wsMode.append(ComboButtonItem().setText("none").setProperty("mode", 0));
wsMode.append(ComboButtonItem().setText("Mode 7").setProperty("mode", 1));
wsMode.append(ComboButtonItem().setText("all").setProperty("mode", 2));
for(uint n = 0; n < 3; n++) {
if(wsMode.item(n).property("mode").natural() == settings.emulator.hack.ppu.mode7.wsMode)
wsMode.item(n).setSelected();
}
wsMode.onChange([&] {
settings.emulator.hack.ppu.mode7.wsMode = wsMode.selected().property("mode").natural();
emulator->configure("Hacks/PPU/Mode7/WsMode", settings.emulator.hack.ppu.mode7.wsMode);
presentation.resizeViewport();
});
unintrModeLabel.setText("Soft crop:");
unintrMode.append(ComboButtonItem().setText(" none ").setProperty("mode", 0));
unintrMode.append(ComboButtonItem().setText("center").setProperty("mode", 1));
@ -291,9 +335,10 @@ auto EmulatorSettings::create() -> void {
unintrMode.onChange([&] {
settings.emulator.hack.ppu.mode7.unintrMode = unintrMode.selected().property("mode").natural();
emulator->configure("Hacks/PPU/Mode7/UnintrMode", settings.emulator.hack.ppu.mode7.unintrMode);
presentation.resizeViewport();
});
unintrTopLabel.setText("Top:");
unintrTopLabel.setText("SC top:");
unintrTop.append(ComboButtonItem().setText(" 0").setProperty("marg", 0));
unintrTop.append(ComboButtonItem().setText(" 10").setProperty("marg", 10));
unintrTop.append(ComboButtonItem().setText(" 20").setProperty("marg", 20));
@ -317,9 +362,10 @@ auto EmulatorSettings::create() -> void {
unintrTop.onChange([&] {
settings.emulator.hack.ppu.mode7.unintrTop = unintrTop.selected().property("marg").natural();
emulator->configure("Hacks/PPU/Mode7/UnintrTop", settings.emulator.hack.ppu.mode7.unintrTop);
presentation.resizeViewport();
});
unintrBottomLabel.setText("Bottom:");
unintrBottomLabel.setText("SC bottom:");
unintrBottom.append(ComboButtonItem().setText(" 0").setProperty("marg", 0));
unintrBottom.append(ComboButtonItem().setText(" 10").setProperty("marg", 10));
unintrBottom.append(ComboButtonItem().setText(" 20").setProperty("marg", 20));
@ -343,9 +389,10 @@ auto EmulatorSettings::create() -> void {
unintrBottom.onChange([&] {
settings.emulator.hack.ppu.mode7.unintrBottom = unintrBottom.selected().property("marg").natural();
emulator->configure("Hacks/PPU/Mode7/UnintrBottom", settings.emulator.hack.ppu.mode7.unintrBottom);
presentation.resizeViewport();
});
unintrLeftLabel.setText("Left:");
unintrLeftLabel.setText("SC left:");
unintrLeft.append(ComboButtonItem().setText(" 0").setProperty("marg", 0));
unintrLeft.append(ComboButtonItem().setText(" 10").setProperty("marg", 10));
unintrLeft.append(ComboButtonItem().setText(" 20").setProperty("marg", 20));
@ -369,9 +416,10 @@ auto EmulatorSettings::create() -> void {
unintrLeft.onChange([&] {
settings.emulator.hack.ppu.mode7.unintrLeft = unintrLeft.selected().property("marg").natural();
emulator->configure("Hacks/PPU/Mode7/UnintrLeft", settings.emulator.hack.ppu.mode7.unintrLeft);
presentation.resizeViewport();
});
unintrRightLabel.setText("Right:");
unintrRightLabel.setText("SC right:");
unintrRight.append(ComboButtonItem().setText(" 0").setProperty("marg", 0));
unintrRight.append(ComboButtonItem().setText(" 10").setProperty("marg", 10));
unintrRight.append(ComboButtonItem().setText(" 20").setProperty("marg", 20));
@ -395,8 +443,45 @@ auto EmulatorSettings::create() -> void {
unintrRight.onChange([&] {
settings.emulator.hack.ppu.mode7.unintrRight = unintrRight.selected().property("marg").natural();
emulator->configure("Hacks/PPU/Mode7/UnintrRight", settings.emulator.hack.ppu.mode7.unintrRight);
presentation.resizeViewport();
});
wsMarkerLabel.setText("WS marker:");
wsMarker.append(ComboButtonItem().setText("none").setProperty("mode", 0));
wsMarker.append(ComboButtonItem().setText("lines").setProperty("mode", 1));
wsMarker.append(ComboButtonItem().setText("darken").setProperty("mode", 2));
for(uint n = 0; n <= 2; n++) {
if(wsMarker.item(n).property("mode").natural() == settings.emulator.hack.ppu.mode7.wsMarker)
wsMarker.item(n).setSelected();
}
wsMarker.onChange([&] {
settings.emulator.hack.ppu.mode7.wsMarker = wsMarker.selected().property("mode").natural();
emulator->configure("Hacks/PPU/Mode7/WsMarker", settings.emulator.hack.ppu.mode7.wsMarker);
});
wsMarkerAlphaLabel.setText("WSM alpha:");
wsMarkerAlpha.append(ComboButtonItem().setText("1/1" ).setProperty("alpha", 1));
wsMarkerAlpha.append(ComboButtonItem().setText("1/2" ).setProperty("alpha", 2));
wsMarkerAlpha.append(ComboButtonItem().setText("1/3" ).setProperty("alpha", 3));
wsMarkerAlpha.append(ComboButtonItem().setText("1/4" ).setProperty("alpha", 4));
wsMarkerAlpha.append(ComboButtonItem().setText("1/5" ).setProperty("alpha", 5));
wsMarkerAlpha.append(ComboButtonItem().setText("1/6" ).setProperty("alpha", 6));
wsMarkerAlpha.append(ComboButtonItem().setText("1/7" ).setProperty("alpha", 7));
wsMarkerAlpha.append(ComboButtonItem().setText("1/8" ).setProperty("alpha", 8));
wsMarkerAlpha.append(ComboButtonItem().setText("1/9" ).setProperty("alpha", 9));
wsMarkerAlpha.append(ComboButtonItem().setText("1/10").setProperty("alpha", 10));
for(uint n = 0; n < 10; n++) {
if(wsMarkerAlpha.item(n).property("alpha").natural() == settings.emulator.hack.ppu.mode7.wsMarkerAlpha)
wsMarkerAlpha.item(n).setSelected();
}
wsMarkerAlpha.onChange([&] {
settings.emulator.hack.ppu.mode7.wsMarkerAlpha = wsMarkerAlpha.selected().property("alpha").natural();
emulator->configure("Hacks/PPU/Mode7/WsMarkerAlpha", settings.emulator.hack.ppu.mode7.wsMarkerAlpha);
});
}
auto EmulatorSettings::updateConfiguration() -> void {
@ -412,13 +497,17 @@ auto EmulatorSettings::updateConfiguration() -> void {
emulator->configure("Hacks/PPU/Mode7/Wsobj", wsObj.property("mode").natural());
emulator->configure("Hacks/PPU/Mode7/Igwin", igwin.property("mode").natural());
emulator->configure("Hacks/PPU/Mode7/Igwinx", igwin.property("col").natural());
emulator->configure("Hacks/PPU/Mode7/WsMode", wsMode.property("mode").natural());
emulator->configure("Hacks/PPU/Mode7/WsBgCol", wsBgCol.property("mode").natural());
emulator->configure("Hacks/PPU/Mode7/UnintrMode", igwin.property("mode").natural());
emulator->configure("Hacks/PPU/Mode7/UnintrTop", igwin.property("marg").natural());
emulator->configure("Hacks/PPU/Mode7/UnintrBottom", igwin.property("marg").natural());
emulator->configure("Hacks/PPU/Mode7/UnintrLeft", igwin.property("marg").natural());
emulator->configure("Hacks/PPU/Mode7/WsMarker", wsMarker.property("mode").natural());
emulator->configure("Hacks/PPU/Mode7/WsMarkerAlpha", wsMarkerAlpha.property("alpha").natural());
emulator->configure("Hacks/PPU/Mode7/UnintrRight", igwin.property("marg").natural());
emulator->configure("Hacks/PPU/Mode7/Supersample", mode7Supersample.property("sss").natural());
emulator->configure("Hacks/PPU/Mode7/Mosaic", mode7Mosaic.checked());
emulator->configure("Hacks/PPU/Mode7/Mosaic", mode7Mosaic.property("mode").natural());
emulator->configure("Hacks/DSP/Fast", fastDSP.checked());
emulator->configure("Hacks/DSP/Cubic", cubicInterpolation.checked());
emulator->configure("Hacks/Coprocessor/DelayedSync", coprocessorsDelayedSyncOption.checked());

View file

@ -108,13 +108,17 @@ auto Settings::process(bool load) -> void {
bind(natural, "Emulator/Hack/PPU/Mode7/Wsobj", emulator.hack.ppu.mode7.wsobj);
bind(natural, "Emulator/Hack/PPU/Mode7/Igwin", emulator.hack.ppu.mode7.igwin);
bind(natural, "Emulator/Hack/PPU/Mode7/Igwinx", emulator.hack.ppu.mode7.igwinx);
bind(natural, "Emulator/Hack/PPU/Mode7/WsMode", emulator.hack.ppu.mode7.wsMode);
bind(natural, "Emulator/Hack/PPU/Mode7/WsBgCol", emulator.hack.ppu.mode7.wsBgCol);
bind(natural, "Emulator/Hack/PPU/Mode7/UnintrMode", emulator.hack.ppu.mode7.unintrMode);
bind(natural, "Emulator/Hack/PPU/Mode7/UnintrTop", emulator.hack.ppu.mode7.unintrTop);
bind(natural, "Emulator/Hack/PPU/Mode7/UnintrBottom", emulator.hack.ppu.mode7.unintrBottom);
bind(natural, "Emulator/Hack/PPU/Mode7/UnintrLeft", emulator.hack.ppu.mode7.unintrLeft);
bind(natural, "Emulator/Hack/PPU/Mode7/UnintrRight", emulator.hack.ppu.mode7.unintrRight);
bind(natural, "Emulator/Hack/PPU/Mode7/WsMarker", emulator.hack.ppu.mode7.wsMarker);
bind(natural, "Emulator/Hack/PPU/Mode7/WsMarkerAlpha", emulator.hack.ppu.mode7.wsMarkerAlpha);
bind(natural, "Emulator/Hack/PPU/Mode7/Supersample", emulator.hack.ppu.mode7.supersample);
bind(boolean, "Emulator/Hack/PPU/Mode7/Mosaic", emulator.hack.ppu.mode7.mosaic);
bind(natural, "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);

View file

@ -82,20 +82,24 @@ struct Settings : Markup::Node {
uint scale = 2;
uint perspective = 1;
uint supersample = 1;
bool mosaic = false;
uint mosaic = 1;
uint widescreen = 72;
uint wsbg1 = 1;
uint wsbg2 = 1;
uint wsbg3 = 1;
uint wsbg4 = 1;
uint wsbg1 = 16;
uint wsbg2 = 16;
uint wsbg3 = 16;
uint wsbg4 = 16;
uint wsobj = 0;
uint igwin = 0;
uint igwin = 1;
uint igwinx = 128;
uint wsMode = 1;
uint wsBgCol = 1;
uint unintrMode = 1;
uint unintrTop = 10;
uint unintrBottom = 10;
uint unintrLeft = 20;
uint unintrRight = 20;
uint wsMarker = 0;
uint wsMarkerAlpha = 1;
} mode7;
} ppu;
struct DSP {
@ -275,10 +279,6 @@ public:
CheckLabel autoSaveMemory{&autoStateLayout, Size{~0, 0}};
CheckLabel autoSaveStateOnUnload{&autoStateLayout, Size{0, 0}};
CheckLabel autoLoadStateOnLoad{&autoStateLayout, Size{0, 0}};
Label dspLabel{&layout, Size{~0, 0}, 2};
HorizontalLayout dspLayout{&layout, Size{~0, 0}};
CheckLabel fastDSP{&dspLayout, Size{0, 0}};
CheckLabel cubicInterpolation{&dspLayout, Size{0, 0}};
Label coprocessorLabel{&layout, Size{~0, 0}, 2};
HorizontalLayout coprocessorsLayout{&layout, Size{~0, 0}};
Label superFXLabel{&coprocessorsLayout, Size{0, 0}};
@ -286,48 +286,60 @@ public:
HorizontalSlider superFXClock{&coprocessorsLayout, Size{~0, 0}};
CheckLabel coprocessorsDelayedSyncOption{&coprocessorsLayout, Size{0, 0}};
CheckLabel coprocessorsHLEOption{&coprocessorsLayout, Size{0, 0}};
Label ppuLabel{&layout, Size{~0, 0}, 2};
HorizontalLayout ppuLayout{&layout, Size{~0, 0}};
CheckLabel fastPPU{&ppuLayout, Size{0, 0}};
CheckLabel noSpriteLimit{&ppuLayout, Size{0, 0}};
Label ppuDspLabel{&layout, Size{~0, 0}, 2};
HorizontalLayout ppuDspLayout{&layout, Size{~0, 0}};
CheckLabel fastPPU{&ppuDspLayout, Size{0, 0}};
CheckLabel noSpriteLimit{&ppuDspLayout, Size{0, 0}};
CheckLabel fastDSP{&ppuDspLayout, Size{0, 0}};
CheckLabel cubicInterpolation{&ppuDspLayout, 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}};
Label mode7PerspectiveLabel{&mode7Layout, Size{0, 0}};
ComboButton mode7Perspective{&mode7Layout, Size{0, 0}};
Label mode7SupersampleLabel{&mode7Layout, Size{0, 0}};
ComboButton mode7Supersample{&mode7Layout, Size{0, 0}};
CheckLabel mode7Mosaic{&mode7Layout, Size{0, 0}};
HorizontalLayout widescreenLayout{&layout, Size{~0, 0}};
Label mode7WidescreenLabel{&widescreenLayout, Size{0, 0}};
ComboButton mode7Widescreen{&widescreenLayout, Size{0, 0}};
Label wsBG1Label{&widescreenLayout, Size{0, 0}};
ComboButton wsBG1{&widescreenLayout, Size{0, 0}};
Label wsBG2Label{&widescreenLayout, Size{0, 0}};
ComboButton wsBG2{&widescreenLayout, Size{0, 0}};
Label wsBG3Label{&widescreenLayout, Size{0, 0}};
ComboButton wsBG3{&widescreenLayout, Size{0, 0}};
Label wsBG4Label{&widescreenLayout, Size{0, 0}};
ComboButton wsBG4{&widescreenLayout, Size{0, 0}};
Label wsObjLabel{&widescreenLayout, Size{0, 0}};
ComboButton wsObj{&widescreenLayout, Size{0, 0}};
HorizontalLayout viewModLayout{&layout, Size{~0, 0}};
Label igwinLabel{&viewModLayout, Size{0, 0}};
ComboButton igwin{&viewModLayout, Size{0, 0}};
Label igwinxLabel{&viewModLayout, Size{0, 0}};
ComboButton igwinx{&viewModLayout, Size{0, 0}};
HorizontalLayout unintrLayout{&layout, Size{~0, 0}};
Label unintrModeLabel{&unintrLayout, Size{0, 0}};
ComboButton unintrMode{&unintrLayout, Size{0, 0}};
Label unintrTopLabel{&unintrLayout, Size{0, 0}};
ComboButton unintrTop{&unintrLayout, Size{0, 0}};
Label unintrBottomLabel{&unintrLayout, Size{0, 0}};
ComboButton unintrBottom{&unintrLayout, Size{0, 0}};
Label unintrLeftLabel{&unintrLayout, Size{0, 0}};
ComboButton unintrLeft{&unintrLayout, Size{0, 0}};
Label unintrRightLabel{&unintrLayout, Size{0, 0}};
ComboButton unintrRight{&unintrLayout, Size{0, 0}};
HorizontalLayout hdALayout{&layout, Size{~0, 0}};
Label mode7ScaleLabel{&hdALayout, Size{0, 0}};
ComboButton mode7Scale{&hdALayout, Size{0, 0}};
Label mode7PerspectiveLabel{&hdALayout, Size{0, 0}};
ComboButton mode7Perspective{&hdALayout, Size{0, 0}};
Label mode7MosaicLabel{&hdALayout, Size{0, 0}};
ComboButton mode7Mosaic{&hdALayout, Size{0, 0}};
Label mode7SupersampleLabel{&hdALayout, Size{0, 0}};
ComboButton mode7Supersample{&hdALayout, Size{0, 0}};
HorizontalLayout hdBLayout{&layout, Size{~0, 0}};
Label wsModeLabel{&hdBLayout, Size{0, 0}};
ComboButton wsMode{&hdBLayout, Size{0, 0}};
Label mode7WidescreenLabel{&hdBLayout, Size{0, 0}};
ComboButton mode7Widescreen{&hdBLayout, Size{0, 0}};
Label wsBgColLabel{&hdBLayout, Size{0, 0}};
ComboButton wsBgCol{&hdBLayout, Size{0, 0}};
Label wsMarkerLabel{&hdBLayout, Size{0, 0}};
ComboButton wsMarker{&hdBLayout, Size{0, 0}};
Label wsMarkerAlphaLabel{&hdBLayout, Size{0, 0}};
ComboButton wsMarkerAlpha{&hdBLayout, Size{0, 0}};
HorizontalLayout hdCLayout{&layout, Size{~0, 0}};
Label wsBG1Label{&hdCLayout, Size{0, 0}};
ComboButton wsBG1{&hdCLayout, Size{0, 0}};
Label wsBG2Label{&hdCLayout, Size{0, 0}};
ComboButton wsBG2{&hdCLayout, Size{0, 0}};
Label wsBG3Label{&hdCLayout, Size{0, 0}};
ComboButton wsBG3{&hdCLayout, Size{0, 0}};
Label wsBG4Label{&hdCLayout, Size{0, 0}};
ComboButton wsBG4{&hdCLayout, Size{0, 0}};
Label wsObjLabel{&hdCLayout, Size{0, 0}};
ComboButton wsObj{&hdCLayout, Size{0, 0}};
HorizontalLayout hdDLayout{&layout, Size{~0, 0}};
Label igwinLabel{&hdDLayout, Size{0, 0}};
ComboButton igwin{&hdDLayout, Size{0, 0}};
Label igwinxLabel{&hdDLayout, Size{0, 0}};
ComboButton igwinx{&hdDLayout, Size{0, 0}};
HorizontalLayout hdELayout{&layout, Size{~0, 0}};
Label unintrModeLabel{&hdELayout, Size{0, 0}};
ComboButton unintrMode{&hdELayout, Size{0, 0}};
Label unintrTopLabel{&hdELayout, Size{0, 0}};
ComboButton unintrTop{&hdELayout, Size{0, 0}};
Label unintrBottomLabel{&hdELayout, Size{0, 0}};
ComboButton unintrBottom{&hdELayout, Size{0, 0}};
Label unintrLeftLabel{&hdELayout, Size{0, 0}};
ComboButton unintrLeft{&hdELayout, Size{0, 0}};
Label unintrRightLabel{&hdELayout, Size{0, 0}};
ComboButton unintrRight{&hdELayout, Size{0, 0}};
};
struct DriverSettings : TabFrameItem {