beta 10.4
171
.github/workflows/CI.yml
vendored
|
@ -1,12 +1,12 @@
|
|||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
Windows:
|
||||
runs-on: windows-latest
|
||||
env:
|
||||
POWERSHELL_TELEMETRY_OPTOUT: 1
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
|
@ -15,16 +15,38 @@ jobs:
|
|||
run: mingw32-make -j $env:NUMBER_OF_PROCESSORS -C bsnes
|
||||
- name: Prepare artifacts
|
||||
run: |
|
||||
mkdir bsnes/out/pack
|
||||
unzip packraw.zip -d bsnes/out/pack
|
||||
cp README.md bsnes/out/pack
|
||||
cp bsnes/out/bsnes.exe bsnes/out/pack
|
||||
mv bsnes/out/pack/bsnes.exe bsnes/out/pack/bsnes_hd.exe
|
||||
cp -R pack bsnes\out\
|
||||
cp README.md bsnes\out\pack\readme.md
|
||||
cp bsnes\out\bsnes.exe bsnes\out\pack\bsnes_hd.exe
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v1.0.0
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: bsnes_hd_build-${{ runner.os }}
|
||||
name: bsnes_hd_beta_X_windows
|
||||
path: bsnes\out\pack
|
||||
if-no-files-found: error
|
||||
|
||||
Windows-libretro:
|
||||
runs-on: windows-latest
|
||||
env:
|
||||
POWERSHELL_TELEMETRY_OPTOUT: 1
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Build
|
||||
run: mingw32-make -j $env:NUMBER_OF_PROCESSORS -C bsnes target=libretro
|
||||
- name: Prepare artifacts
|
||||
run: |
|
||||
mkdir bsnes/out/pack
|
||||
cp README.md bsnes/out/pack
|
||||
cp LICENSE bsnes/out/pack
|
||||
cp -R bsnes/out/*bsnes* bsnes/out/pack
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: bsnes_hd_beta_X_windows_libretro
|
||||
path: bsnes\out\pack
|
||||
if-no-files-found: error
|
||||
|
||||
Linux:
|
||||
runs-on: ubuntu-latest
|
||||
|
@ -35,51 +57,37 @@ jobs:
|
|||
- name: Setup
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get -y install build-essential libgtk2.0-dev libpulse-dev mesa-common-dev libgtksourceview2.0-dev libcairo2-dev libsdl2-dev libxv-dev libao-dev libopenal-dev libudev-dev zip
|
||||
sudo apt-get -y install build-essential libgtk2.0-dev libpulse-dev mesa-common-dev libgtksourceview2.0-dev libcairo2-dev libsdl2-dev libxv-dev libao-dev libopenal-dev libudev-dev
|
||||
- name: Build
|
||||
run: make -j $(nproc) -C bsnes
|
||||
- name: Prepare artifacts
|
||||
run: |
|
||||
mkdir bsnes/out/pack
|
||||
unzip packraw.zip -d bsnes/out/pack
|
||||
cp README.md bsnes/out/pack
|
||||
cp -R bsnes/out/*bsnes* bsnes/out/pack
|
||||
mv bsnes/out/pack/bsnes bsnes/out/pack/bsnes_hd
|
||||
cp -R pack bsnes/out/
|
||||
cp README.md bsnes/out/pack/readme.md
|
||||
cp bsnes/out/bsnes bsnes/out/pack/bsnes_hd
|
||||
chmod +x bsnes/out/pack/bsnes_hd
|
||||
mkdir bsnes/out/tar
|
||||
cd bsnes/out/pack
|
||||
tar -jcvpf ../tar/bsnes_hd_beta_X_linux.tar.bz2 *
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v1.0.0
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: bsnes_hd_build-${{ runner.os }}
|
||||
path: bsnes/out/pack
|
||||
name: UNPACK-LINUX
|
||||
path: bsnes/out/tar
|
||||
if-no-files-found: error
|
||||
|
||||
macOS:
|
||||
runs-on: macos
|
||||
Linux-libretro:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Build
|
||||
run: make -j $(sysctl -n hw.ncpu) -C bsnes
|
||||
- name: Prepare artifacts
|
||||
- name: Setup
|
||||
run: |
|
||||
mkdir bsnes/out/pack
|
||||
unzip packraw.zip -d bsnes/out/pack
|
||||
cp README.md bsnes/out/pack
|
||||
cp -R bsnes/out/*bsnes* bsnes/out/pack
|
||||
mv bsnes/out/pack/bsnes.app bsnes/out/pack/bsnes_hd.app
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v1.0.0
|
||||
with:
|
||||
name: bsnes_hd_build-${{ runner.os }}
|
||||
path: bsnes/out/pack
|
||||
|
||||
macOS-libretro:
|
||||
runs-on: macos
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
sudo apt-get update
|
||||
sudo apt-get -y install build-essential libgtk2.0-dev libpulse-dev mesa-common-dev libgtksourceview2.0-dev libcairo2-dev libsdl2-dev libxv-dev libao-dev libopenal-dev libudev-dev
|
||||
- name: Build
|
||||
run: make -j $(sysctl -n hw.ncpu) -C bsnes target=libretro
|
||||
run: make -j $(nproc) -C bsnes target=libretro
|
||||
- name: Prepare artifacts
|
||||
run: |
|
||||
mkdir bsnes/out/pack
|
||||
|
@ -87,7 +95,82 @@ jobs:
|
|||
cp LICENSE bsnes/out/pack
|
||||
cp -R bsnes/out/*bsnes* bsnes/out/pack
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v1.0.0
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: bsnes_hd_libretro_build-${{ runner.os }}
|
||||
name: bsnes_hd_beta_X_linux_libretro
|
||||
path: bsnes/out/pack
|
||||
if-no-files-found: error
|
||||
|
||||
macOS:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Build
|
||||
run: |
|
||||
export MACOSX_DEPLOYMENT_TARGET=10.14
|
||||
make -j $(sysctl -n hw.ncpu) -C bsnes
|
||||
- name: Prepare artifacts
|
||||
run: |
|
||||
mkdir bsnes/out/pack
|
||||
cp LICENSE bsnes/out/pack
|
||||
cp README.md bsnes/out/pack
|
||||
cp -R bsnes/out/*bsnes* bsnes/out/pack
|
||||
mv bsnes/out/pack/bsnes.app bsnes/out/pack/bsnes_hd.app
|
||||
chmod +x bsnes/out/pack/bsnes_hd.app/Contents/MacOS/bsnes
|
||||
mkdir bsnes/out/tar
|
||||
cd bsnes/out/pack
|
||||
tar -jcvpf ../tar/bsnes_hd_beta_X_mac.tar.bz2 *
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: UNPACK-MAC
|
||||
path: bsnes/out/tar
|
||||
if-no-files-found: error
|
||||
|
||||
macOS-libretro:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Build
|
||||
run: |
|
||||
export MACOSX_DEPLOYMENT_TARGET=10.14
|
||||
make -j $(sysctl -n hw.ncpu) -C bsnes target=libretro
|
||||
- name: Prepare artifacts
|
||||
run: |
|
||||
mkdir bsnes/out/pack
|
||||
cp README.md bsnes/out/pack
|
||||
cp LICENSE bsnes/out/pack
|
||||
cp -R bsnes/out/*bsnes* bsnes/out/pack
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: bsnes_hd_beta_X_mac_libretro
|
||||
path: bsnes/out/pack
|
||||
if-no-files-found: error
|
||||
|
||||
Android-libretro:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: nttld/setup-ndk@v1
|
||||
with:
|
||||
ndk-version: r22
|
||||
- name: Build
|
||||
run: |
|
||||
cd bsnes/target-libretro/jni
|
||||
ndk-build
|
||||
cd ../../..
|
||||
cp README.md bsnes/target-libretro/libs
|
||||
cp LICENSE bsnes/target-libretro/libs
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: bsnes_hd_beta_X_android_libretro
|
||||
path: bsnes/target-libretro/libs
|
||||
if-no-files-found: error
|
||||
|
|
40
README.md
|
@ -1,10 +1,9 @@
|
|||
# bsnes-hd *beta 10.3*
|
||||
# bsnes-hd *beta 10.4*
|
||||
|
||||
- [downloads](https://github.com/DerKoun/bsnes-hd/releases) for the latest betas
|
||||
- [downloads](https://github.com/DerKoun/bsnes-hd/releases) for the latest betas (there are only beta) / also on the libretro auto-updater
|
||||
- [GitHub project](https://github.com/DerKoun/bsnes-hd) for source code, issues, feature requests, ...
|
||||
- [Reddit](https://www.reddit.com/r/emulation/search/?q=bsnes-hd&restrict_sr=1&sort=new) for announcements and discussions on *r/emulation*
|
||||
- [Discord](https://discord.gg/7ahAzCV) if you prefer chatting (Thanks to everyone who set it up and keeps it running)
|
||||
- [Forum](https://www.retrowide.com/forums) for widescreen discussions, both ROM-hacking and technical
|
||||
|
||||
1. [What is it?](#what-is-it)
|
||||
2. [Help wanted](#help-wanted)
|
||||
|
@ -54,10 +53,9 @@ Feel free to suggest features. Please remember that this fork focuses on HD and
|
|||
|
||||
It would be helpful to know how the framerates of different scale levels is on various devices, especially handhelds and consoles, Android and others.
|
||||
|
||||
### OpenGL/Vulkan
|
||||
|
||||
### Vulkan/OpenGL
|
||||
|
||||
If someone could set me up a very basic libretro core, that can just display 3 textures, than can have their image data and 3D position changed each frame, I could try out some experiments to improve both performance and quality for most games.
|
||||
If anyone with OpenGL/Vulkan programming and/or shader knowledge would assit me, we could work on a fork that improves both quality and performance using the GPU. This is a long-term goal that I won't start on without help.
|
||||
|
||||
### Logo
|
||||
|
||||
|
@ -202,18 +200,34 @@ The file must contain alternating letters and numbers, each pair overriding a se
|
|||
| widescreen mode | w | 0:off 1:on(always) 2:on(mode7) |
|
||||
| widescreen sprites | s | 0:safe 1:unsafe(widescreen) 2:clip |
|
||||
| widescreen aspect ratio | W | 0-200:widescreen-extension 201+:AR(*see below*) |
|
||||
| widescreen background 1/2/3/4 | b/B/c/C | 0:off 1:on 2:auto(horizontal and vertical) |
|
||||
| widescreen background 1/2/3/4 | b/B/c/C | 0+:WS 10+:crop 20:disab 1000+:line(*see below*) |
|
||||
| widescreen marker | m | 0:off 1+:line 11+:darken (*see below*) |
|
||||
| mode 7 perspective correction | P | 0:off 1-3:auto 4-6+:on (*see below*) |
|
||||
| pixel aspect ratio correction | p | 0:off 1:on |
|
||||
| overscan | o | 0:off(216 lines(5th HD)) 1:on(224 lines) |
|
||||
| ignore window | i | 0:none 1:outside 2:outside&always 3:all |
|
||||
| ignore window fallback x-coordinate | I | 0-255:x-coordinate |
|
||||
| overclock CPU | O | 100+:percentage(100 is normal) |
|
||||
|
||||
#### Widescreen values
|
||||
#### Widescreen Aspect Ratio values
|
||||
|
||||
Values of 200 and less specify the widescreen extension on each side in pixel columns. It is recommended to use values dividable by as large a power of 2 as possible, at least by 4.
|
||||
|
||||
Values larger than 200 specify the aspect ratio as (horizontal*100+vertical), e.g. 16:10, 16:9, 2:1 and 21:9 as 1610, 1609, 201 and 2109, respectively. From this AR the widescreen extension is computed in the same way as for ARs specified in the settings dialog, except that arbitrary ARs can be specified here.
|
||||
|
||||
#### Widescreen Background
|
||||
|
||||
0:off, 1:on, 2:auto(horizanotal+vertical), 2:auto(horizanotal), 10:crop, 11:crop(auto), 20:disable.
|
||||
To enable widescreen for the background only above or below a certain line the value must be the line number plus 1000 or 2000 respectively.
|
||||
|
||||
#### Widescreen Marker
|
||||
|
||||
Values from 1-10 and 11-20 enable lines and darkening respectively. The values in the respective ranges vary the opacity.
|
||||
|
||||
#### Perspective Correction
|
||||
|
||||
1-3 and 4-6 trigger auto an on respectively. In both cases the 3 settings are in the order: wide, medium, narrow.
|
||||
|
||||
#### Sample
|
||||
|
||||
To force enable widescreen, including for sprites and setting a widescreen extension of 64 the file can simply be:
|
||||
|
@ -226,9 +240,11 @@ w : 1
|
|||
s : 1
|
||||
W : 64
|
||||
```
|
||||
Only the last letter before a number is taken into account, basically allowing comments:
|
||||
The percent character ("%") disabled and enables interpretation, allowing comments:
|
||||
```
|
||||
widescreen always on: w: 1
|
||||
widescreen sprites on: s: 1
|
||||
widescreen extension : W:64
|
||||
% HyperZone %
|
||||
B : 2100 % bg 2 includes dashboard (non-ws) and far away bg (ws):
|
||||
enable widescreen for line 100 and below %
|
||||
s : 1 % unlimited sprites (not perfect, but worth trying) %
|
||||
m : 0 % no ws markers %
|
||||
```
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
target ?= bsnes
|
||||
binary ?= application
|
||||
target := bsnes
|
||||
binary := application
|
||||
build := performance
|
||||
openmp := true
|
||||
local := false
|
||||
|
|
|
@ -31,7 +31,7 @@ using namespace nall;
|
|||
|
||||
namespace Emulator {
|
||||
static const string Name = "bsnes-hd beta";
|
||||
static const string Version = "10.3";//bsnes/target-bsnes/presentation/presentation.cpp:create:about:setVersion
|
||||
static const string Version = "10.4";//bsnes/target-bsnes/presentation/presentation.cpp:create:about:setVersion
|
||||
static const string Author = "DerKoun(byuu)";
|
||||
static const string License = "GPLv3";
|
||||
static const string Website = "https://github.com/DerKoun/bsnes-hd";
|
||||
|
|
|
@ -1,23 +1,23 @@
|
|||
namespace HdToolkit {
|
||||
static constexpr auto determineWsExt(int ws, bool overscan, bool aspectCorrection) -> int {
|
||||
if (ws < 200) {
|
||||
return ws;
|
||||
double val = ws;
|
||||
if (ws > 200) {
|
||||
int w = ws / 100;
|
||||
int h = ws % 100;
|
||||
val = overscan ? 224.0 : 216.0;
|
||||
val *= w;
|
||||
val /= h;
|
||||
if (aspectCorrection) {
|
||||
val *= 7;
|
||||
val /= 8;
|
||||
}
|
||||
if (val <= 256) {
|
||||
return 0;
|
||||
}
|
||||
val -= 256;
|
||||
val /= 2;
|
||||
}
|
||||
int w = ws / 100;
|
||||
int h = ws % 100;
|
||||
double val = overscan ? 224.0 : 216.0;
|
||||
val *= w;
|
||||
val /= h;
|
||||
if (aspectCorrection) {
|
||||
val *= 7;
|
||||
val /= 8;
|
||||
}
|
||||
if (val <= 256) {
|
||||
return 0;
|
||||
}
|
||||
val -= 256;
|
||||
val /= 2;
|
||||
val /= 4;
|
||||
val /= 8;
|
||||
if (overscan || aspectCorrection) {
|
||||
val += 0.5;
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ namespace HdToolkit {
|
|||
if (ws <= 0) {
|
||||
return 0;
|
||||
}
|
||||
ws *= 4;
|
||||
ws *= 8;
|
||||
return ws;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@ 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(boolean, "Hacks/PPU/Mode7/Strwin", hacks.ppu.mode7.strwin);
|
||||
bind(natural, "Hacks/PPU/Mode7/BgGrad", hacks.ppu.mode7.bgGrad);
|
||||
bind(natural, "Hacks/PPU/Mode7/WindRad", hacks.ppu.mode7.windRad);
|
||||
bind(natural, "Hacks/PPU/Mode7/WsMode", hacks.ppu.mode7.wsMode);
|
||||
|
|
|
@ -57,6 +57,7 @@ struct Configuration {
|
|||
uint wsobj = 0;
|
||||
uint igwin = 1;
|
||||
uint igwinx = 128;
|
||||
bool strwin = false;
|
||||
uint bgGrad = 4;
|
||||
uint windRad = 0;
|
||||
uint wsMode = 1;
|
||||
|
|
|
@ -21,15 +21,20 @@ auto PPU::Line::renderBackground(PPU::IO::Background& self, uint8 source) -> voi
|
|||
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))))) {
|
||||
} else if(wsConf == 0
|
||||
|| (wsConf >= 2 && wsConf <= 11 && (((wsConf % 2) != 0) == (y < (((int)(wsConf / 2)) * 40))))
|
||||
|| (wsConf >= 1000 && wsConf < 3000 && ((wsConf < 2000) != (y < ((int)(wsConf % 1000)))))
|
||||
) {
|
||||
ws = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool windowAbove[256];
|
||||
bool windowBelow[256];
|
||||
renderWindow(self.window, self.window.aboveEnable, windowAbove);
|
||||
renderWindow(self.window, self.window.belowEnable, windowBelow);
|
||||
bool windowAbove[1024];
|
||||
bool windowBelow[1024];
|
||||
renderWindow(self.window, self.window.aboveEnable, windowAbove,
|
||||
ppufast.widescreen(), ppufast.strwin());
|
||||
renderWindow(self.window, self.window.belowEnable, windowBelow,
|
||||
ppufast.widescreen(), ppufast.strwin());
|
||||
|
||||
bool hires = io.bgMode == 5 || io.bgMode == 6;
|
||||
bool offsetPerTileMode = io.bgMode == 2 || io.bgMode == 4 || io.bgMode == 6;
|
||||
|
|
|
@ -110,9 +110,18 @@ auto PPU::Line::avgBgC(uint dist, uint offset) const -> uint32 {
|
|||
auto luma = ppu.lightTable[io.displayBrightness];
|
||||
uint32 t = luma[io.col.fixedColor];
|
||||
if(dist < 1) return t;
|
||||
uint32 a = (t >> 16) & 255;
|
||||
uint32 b = (t >> 8) & 255;
|
||||
uint32 c = (t >> 0) & 255;
|
||||
int32 aBase = (t >> 16) & 255;
|
||||
int32 bBase = (t >> 8) & 255;
|
||||
int32 cBase = (t >> 0) & 255;
|
||||
uint32 a = aBase;
|
||||
uint32 b = bBase;
|
||||
uint32 c = cBase;
|
||||
int32 aU = 0;
|
||||
int32 bU = 0;
|
||||
int32 cU = 0;
|
||||
int32 aD = 0;
|
||||
int32 bD = 0;
|
||||
int32 cD = 0;
|
||||
int scale = ppufast.hd() ? ppufast.hdScale() : 1;
|
||||
int hdY = y * scale + offset;
|
||||
int count = 1;
|
||||
|
@ -137,13 +146,18 @@ auto PPU::Line::avgBgC(uint dist, uint offset) const -> uint32 {
|
|||
io.bg3.tileMode != dL.io.bg3.tileMode || io.bg3.tileMode != uL.io.bg3.tileMode ||
|
||||
io.bg4.tileMode != dL.io.bg4.tileMode || io.bg4.tileMode != uL.io.bg4.tileMode) break;
|
||||
t = luma[uL.io.col.fixedColor];
|
||||
a += (t >> 16) & 255;
|
||||
b += (t >> 8) & 255;
|
||||
c += (t >> 0) & 255;
|
||||
aU = (t >> 16) & 255;
|
||||
bU = (t >> 8) & 255;
|
||||
cU = (t >> 0) & 255;
|
||||
t = luma[dL.io.col.fixedColor];
|
||||
a += (t >> 16) & 255;
|
||||
b += (t >> 8) & 255;
|
||||
c += (t >> 0) & 255;
|
||||
aD = (t >> 16) & 255;
|
||||
bD = (t >> 8) & 255;
|
||||
cD = (t >> 0) & 255;
|
||||
if (((abs(aU - aBase) + abs(bU - bBase) + abs(cU - cBase)) > 76) ||
|
||||
((abs(aD - aBase) + abs(bD - bBase) + abs(cD - cBase)) > 76)) break;
|
||||
a += aU + aD;
|
||||
b += bU + bD;
|
||||
c += cU + cD;
|
||||
count += 2;
|
||||
}
|
||||
a /= count;
|
||||
|
@ -219,10 +233,10 @@ auto PPU::Line::render(bool fieldID) -> void {
|
|||
y = this->y;
|
||||
uint windRad = ppufast.windRad();
|
||||
for (int offset = 0; offset < scale; offset++) {
|
||||
uint oneLeft = io.window.oneLeft;
|
||||
uint oneRight = io.window.oneRight;
|
||||
uint twoLeft = io.window.twoLeft;
|
||||
uint twoRight = io.window.twoRight;
|
||||
int oneLeft = io.window.oneLeft;
|
||||
int oneRight = io.window.oneRight;
|
||||
int twoLeft = io.window.twoLeft;
|
||||
int twoRight = io.window.twoRight;
|
||||
|
||||
int hdY = y * scale + offset;
|
||||
int count = 1;
|
||||
|
@ -279,15 +293,56 @@ auto PPU::Line::render(bool fieldID) -> void {
|
|||
|
||||
count += 2;
|
||||
}
|
||||
oneLeft = oneLeft * scale / count;
|
||||
oneRight = oneRight * scale / count + scale - 1;
|
||||
twoLeft = twoLeft * scale / count;
|
||||
twoRight = twoRight * scale / count + scale - 1;
|
||||
if (ppu.strwin()) {
|
||||
oneLeft *= 2;
|
||||
oneRight *= 2;
|
||||
twoLeft *= 2;
|
||||
twoRight *= 2;
|
||||
}
|
||||
int ws = ppu.widescreen() * scale;
|
||||
oneLeft = oneLeft * scale / count + ws;
|
||||
oneRight = oneRight * scale / count + ws + scale - 1;
|
||||
twoLeft = twoLeft * scale / count + ws;
|
||||
twoRight = twoRight * scale / count + ws + scale - 1;
|
||||
|
||||
if (ppu.strwin()) {
|
||||
oneLeft -= 128 * scale;
|
||||
oneRight -= 128 * scale;
|
||||
twoLeft -= 128 * scale;
|
||||
twoRight -= 128 * scale;
|
||||
} else {
|
||||
int lw = 0 - scale * 10;
|
||||
int l = ws + scale;
|
||||
int r = ws + 255 * scale;
|
||||
int rw = ws + 255 * scale + ws + scale * 10;
|
||||
if (oneLeft < l) {
|
||||
oneLeft = lw;
|
||||
} else if (oneLeft >= r) {
|
||||
oneLeft = rw;
|
||||
}
|
||||
if (oneRight < l) {
|
||||
oneRight = lw;
|
||||
} else if (oneRight >= r) {
|
||||
oneRight = rw;
|
||||
}
|
||||
if (twoLeft < l) {
|
||||
twoLeft = lw;
|
||||
} else if (twoLeft >= r) {
|
||||
twoLeft = rw;
|
||||
}
|
||||
if (twoRight < l) {
|
||||
twoRight = lw;
|
||||
} else if (twoRight >= r) {
|
||||
twoRight = rw;
|
||||
}
|
||||
}
|
||||
|
||||
renderWindow(io.col.window, io.col.window.aboveMask, windowAbove,
|
||||
oneLeft, oneRight, twoLeft, twoRight, scale, 256*scale*offset);
|
||||
oneLeft, oneRight, twoLeft, twoRight, scale,
|
||||
(256 + 2 * ppu.widescreen())*scale*offset, ppu.widescreen());
|
||||
renderWindow(io.col.window, io.col.window.belowMask, windowBelow,
|
||||
oneLeft, oneRight, twoLeft, twoRight, scale, 256*scale*offset);
|
||||
oneLeft, oneRight, twoLeft, twoRight, scale,
|
||||
(256 + 2 * ppu.widescreen())*scale*offset, ppu.widescreen());
|
||||
}
|
||||
|
||||
uint wsm = (ppu.widescreen() == 0 || ppu.wsOverride()) ? 0 : ppu.wsMarker();
|
||||
|
@ -295,40 +350,25 @@ auto PPU::Line::render(bool fieldID) -> void {
|
|||
|
||||
uint curr = 0, prev = 0;
|
||||
if(hd) {
|
||||
int x = 0;
|
||||
int xWindow = 0;
|
||||
for(uint ySub : range(scale)) {
|
||||
for(uint i : range(ppufast.widescreen() * scale)) {
|
||||
*output++ = pixel(xWindow, above[x], below[x], wsm, wsma, bgFixedColors[ySub]);
|
||||
x++;
|
||||
for(uint x : range((256 + 2 * ppufast.widescreen() ) * scale)) {
|
||||
*output++ = pixel(x, above[x], below[x], ppu.widescreen(), wsm, wsma, bgFixedColors[ySub]);
|
||||
}
|
||||
for(uint i : range(256 * scale)) {
|
||||
*output++ = pixel(xWindow, above[x], below[x], wsm, wsma, bgFixedColors[ySub]);
|
||||
x++;
|
||||
xWindow++;
|
||||
}
|
||||
xWindow--;
|
||||
for(uint i : range(ppufast.widescreen() * scale)) {
|
||||
*output++ = pixel(xWindow, above[x], below[x], wsm, wsma, bgFixedColors[ySub]);
|
||||
x++;
|
||||
}
|
||||
xWindow++;
|
||||
}
|
||||
|
||||
} else if(width == 256) for(uint x : range(256)) {
|
||||
*output++ = pixel(x, above[x], below[x], wsm, wsma, bgFixedColors[0]);
|
||||
*output++ = pixel(x, above[x], below[x], 0, 0, 0, bgFixedColors[0]);
|
||||
} else if(!hires) for(uint x : range(256)) {
|
||||
auto color = pixel(x, above[x], below[x], wsm, wsma, bgFixedColors[0]);
|
||||
auto color = pixel(x, above[x], below[x], 0, 0, 0, bgFixedColors[0]);
|
||||
*output++ = color;
|
||||
*output++ = color;
|
||||
} else if(!configuration.video.blurEmulation) for(uint x : range(256)) {
|
||||
*output++ = pixel(x, below[x], above[x], wsm, wsma, bgFixedColors[0]);
|
||||
*output++ = pixel(x, above[x], below[x], wsm, wsma, bgFixedColors[0]);
|
||||
*output++ = pixel(x, below[x], above[x], 0, 0, 0, bgFixedColors[0]);
|
||||
*output++ = pixel(x, above[x], below[x], 0, 0, 0, bgFixedColors[0]);
|
||||
} else for(uint x : range(256)) {
|
||||
curr = pixel(x, below[x], above[x], wsm, wsm, bgFixedColors[0]);
|
||||
curr = pixel(x, below[x], above[x], 0, 0, 0, bgFixedColors[0]);
|
||||
*output++ = (prev + curr - ((prev ^ curr) & 0x00010101)) >> 1;
|
||||
prev = curr;
|
||||
curr = pixel(x, above[x], below[x], wsm, wsma, bgFixedColors[0]);
|
||||
curr = pixel(x, above[x], below[x], 0, 0, 0, bgFixedColors[0]);
|
||||
*output++ = (prev + curr - ((prev ^ curr) & 0x00010101)) >> 1;
|
||||
prev = curr;
|
||||
}
|
||||
|
@ -338,7 +378,8 @@ auto PPU::Line::render(bool fieldID) -> void {
|
|||
|
||||
}
|
||||
|
||||
auto PPU::Line::pixel(uint x, Pixel above, Pixel below, uint wsm, uint wsma, uint32 bgFixedColor) const -> uint32 {
|
||||
auto PPU::Line::pixel(uint x, Pixel above, Pixel below, uint ws, uint wsm,
|
||||
uint wsma, uint32 bgFixedColor) const -> uint32 {
|
||||
uint32 r = 0;
|
||||
if(!windowAbove[ppufast.winXadHd(x, false)]) above.color = 0x0000;
|
||||
if(!windowBelow[ppufast.winXadHd(x, true)]) r = above.color;
|
||||
|
@ -346,9 +387,8 @@ auto PPU::Line::pixel(uint x, Pixel above, Pixel below, uint wsm, uint wsma, uin
|
|||
else if(!io.col.blendMode) r = blend(above.color, bgFixedColor, io.col.halve && windowAbove[x]);
|
||||
else r = blend(above.color, below.color, io.col.halve && windowAbove[x] && below.source != Source::COL);
|
||||
if(wsm > 0) {
|
||||
x = (x / ppufast.hdScale()) % 256;
|
||||
if(wsm == 1 && (x == 1 || x == 254)
|
||||
|| wsm == 2 && (x == 0 || x == 255)) {
|
||||
x /= ppufast.hdScale();
|
||||
if(x == ws - 1 || x == ws + 256 || wsm == 2 && (x <= ws - 1 || x >= ws + 256)) {
|
||||
int b = wsm == 2 ? 0 : ((y / 4) % 2 == 0) ? 0 : 255;
|
||||
r = ((((((r >> 16) & 255) * wsma) + b) / (wsma + 1)) << 16)
|
||||
+ ((((((r >> 8) & 255) * wsma) + b) / (wsma + 1)) << 8)
|
||||
|
|
|
@ -27,10 +27,12 @@ auto PPU::Line::renderMode7(PPU::IO::Background& self, uint8 source) -> void {
|
|||
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);
|
||||
|
||||
bool windowAbove[256];
|
||||
bool windowBelow[256];
|
||||
renderWindow(self.window, self.window.aboveEnable, windowAbove);
|
||||
renderWindow(self.window, self.window.belowEnable, windowBelow);
|
||||
bool windowAbove[1024];
|
||||
bool windowBelow[1024];
|
||||
renderWindow(self.window, self.window.aboveEnable, windowAbove,
|
||||
ppufast.widescreen(), ppufast.strwin());
|
||||
renderWindow(self.window, self.window.belowEnable, windowBelow,
|
||||
ppufast.widescreen(), ppufast.strwin());
|
||||
|
||||
auto luma = ppu.lightTable[io.displayBrightness];
|
||||
for(int X : range(256)) {
|
||||
|
|
|
@ -7,7 +7,7 @@ auto PPU::Line::cacheMode7HD() -> void {
|
|||
))
|
||||
bool state = false;
|
||||
uint y;
|
||||
//find the moe 7 groups
|
||||
//find the mode 7 groups
|
||||
for(y = 0; y < Line::count; y++) {
|
||||
if(state != isLineMode7(ppu.lines[Line::start + y])) {
|
||||
state = !state;
|
||||
|
@ -156,10 +156,12 @@ auto PPU::Line::renderMode7HD(PPU::IO::Background& self, uint8 source) -> void {
|
|||
y_b = 255 - y_b;
|
||||
}
|
||||
|
||||
bool windowAbove[256];
|
||||
bool windowBelow[256];
|
||||
renderWindow(self.window, self.window.aboveEnable, windowAbove);
|
||||
renderWindow(self.window, self.window.belowEnable, windowBelow);
|
||||
bool windowAbove[1024];
|
||||
bool windowBelow[1024];
|
||||
renderWindow(self.window, self.window.aboveEnable, windowAbove,
|
||||
ppufast.widescreen(), ppufast.strwin());
|
||||
renderWindow(self.window, self.window.belowEnable, windowBelow,
|
||||
ppufast.widescreen(), ppufast.strwin());
|
||||
|
||||
auto luma = ppu.lightTable[io.displayBrightness];
|
||||
int pixelYp = INT_MIN;
|
||||
|
|
|
@ -4,10 +4,12 @@ auto PPU::Line::renderObject(PPU::IO::Object& self) -> void {
|
|||
|
||||
uint wsobj = ppufast.wsOverride() ? 3 : ppufast.wsobj();
|
||||
|
||||
bool windowAbove[256];
|
||||
bool windowBelow[256];
|
||||
renderWindow(self.window, self.window.aboveEnable, windowAbove);
|
||||
renderWindow(self.window, self.window.belowEnable, windowBelow);
|
||||
bool windowAbove[1024];
|
||||
bool windowBelow[1024];
|
||||
renderWindow(self.window, self.window.aboveEnable, windowAbove,
|
||||
ppufast.widescreen(), ppufast.strwin());
|
||||
renderWindow(self.window, self.window.belowEnable, windowBelow,
|
||||
ppufast.widescreen(), ppufast.strwin());
|
||||
|
||||
uint itemCount = 0;
|
||||
uint tileCount = 0;
|
||||
|
@ -137,13 +139,13 @@ auto PPU::Line::renderObject(PPU::IO::Object& self) -> void {
|
|||
|
||||
if(ppufast.hires() && ppufast.hd()) {
|
||||
// Match non-hires backgrounds in hires mode (see background)
|
||||
if(self.aboveEnable && !windowAbove[ppufast.winXad(x, false)]) plotHD(above, xc, source, priority[x], mctc, true, false);
|
||||
if(self.aboveEnable && !windowAbove[ppufast.winXad(x, false)]) plotHD(above, xc, source, priority[x], mctc, true, true);
|
||||
if(self.aboveEnable && !windowAbove[ppufast.winXad(x, false)]) plotHD(below, xc, source, priority[x], mctc, true, false);
|
||||
if(self.aboveEnable && !windowAbove[ppufast.winXad(x, false)]) plotHD(below, xc, source, priority[x], mctc, true, true);
|
||||
if(self.aboveEnable && !windowAbove[ppufast.winXad(xc, false)]) plotHD(above, xc, source, priority[x], mctc, true, false);
|
||||
if(self.aboveEnable && !windowAbove[ppufast.winXad(xc, false)]) plotHD(above, xc, source, priority[x], mctc, true, true);
|
||||
if(self.aboveEnable && !windowAbove[ppufast.winXad(xc, false)]) plotHD(below, xc, source, priority[x], mctc, true, false);
|
||||
if(self.aboveEnable && !windowAbove[ppufast.winXad(xc, false)]) plotHD(below, xc, source, priority[x], mctc, true, true);
|
||||
} else {
|
||||
if(self.aboveEnable && !windowAbove[ppufast.winXad(x, false)]) plotAbove(xc, source, priority[x], mctc);
|
||||
if(self.belowEnable && !windowBelow[ppufast.winXad(x, true)]) plotBelow(xc, source, priority[x], mctc);
|
||||
if(self.aboveEnable && !windowAbove[ppufast.winXad(xc, false)]) plotAbove(xc, source, priority[x], mctc);
|
||||
if(self.belowEnable && !windowBelow[ppufast.winXad(xc, true)]) plotBelow(xc, source, priority[x], mctc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,15 +38,16 @@ auto PPU::wsbg(uint bg) const -> uint {
|
|||
return 0; }
|
||||
auto PPU::wsobj() const -> uint { return configuration.hacks.ppu.mode7.wsobj; }
|
||||
auto PPU::winXad(uint x, bool bel) const -> uint {
|
||||
return (configuration.hacks.ppu.mode7.igwin != 0 && (configuration.hacks.ppu.mode7.igwin >= 3
|
||||
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) + widescreen(); }
|
||||
auto PPU::winXadHd(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 * PPU::hdScale() : x; }
|
||||
auto PPU::strwin() const -> bool { return configuration.hacks.ppu.mode7.strwin; }
|
||||
auto PPU::bgGrad() const -> uint { return !hd() ? 0 : configuration.hacks.ppu.mode7.bgGrad; }
|
||||
auto PPU::windRad() const -> uint { return !hd() ? 0 : configuration.hacks.ppu.mode7.windRad; }
|
||||
auto PPU::wsOverrideCandidate() const -> bool { return configuration.hacks.ppu.mode7.wsMode == 1; }
|
||||
|
|
|
@ -24,6 +24,7 @@ struct PPU : PPUcounter {
|
|||
alwaysinline auto wsobj() const -> uint;
|
||||
alwaysinline auto winXad(uint x, bool bel) const -> uint;
|
||||
alwaysinline auto winXadHd(uint x, bool bel) const -> uint;
|
||||
alwaysinline auto strwin() const -> bool;
|
||||
alwaysinline auto bgGrad() const -> uint;
|
||||
alwaysinline auto windRad() const -> uint;
|
||||
alwaysinline auto wsOverrideCandidate() const -> bool;
|
||||
|
@ -309,7 +310,8 @@ public:
|
|||
auto cache() -> void;
|
||||
auto render(bool field) -> void;
|
||||
|
||||
alwaysinline auto pixel(uint x, Pixel above, Pixel below, uint wsm, uint wsma, uint32 bgFixedColor) const -> uint32;
|
||||
alwaysinline auto pixel(uint x, Pixel above, Pixel below, uint ws, uint wsm,
|
||||
uint wsma, uint32 bgFixedColor) const -> uint32;
|
||||
alwaysinline auto blend(uint x, uint y, bool halve) const -> uint32;
|
||||
alwaysinline auto directColor(uint paletteIndex, uint paletteColor) const -> uint32;
|
||||
alwaysinline auto plotAbove(int x, uint8 source, uint8 priority, uint32 color) -> void;
|
||||
|
@ -330,23 +332,15 @@ public:
|
|||
auto renderMode7HD(PPU::IO::Background&, uint8 source) -> void;
|
||||
alwaysinline auto lerp(float pa, float va, float pb, float vb, float pr) -> float;
|
||||
|
||||
//mode7hd-avx2.cpp
|
||||
auto renderMode7HD_AVX2(
|
||||
PPU::IO::Background&, uint8 source,
|
||||
Pixel* above, Pixel* below,
|
||||
bool* windowAbove, bool* windowBelow,
|
||||
float originX, float a,
|
||||
float originY, float c
|
||||
) -> void;
|
||||
|
||||
//object.cpp
|
||||
auto renderObject(PPU::IO::Object&) -> void;
|
||||
|
||||
//window.cpp
|
||||
alwaysinline auto renderWindow(PPU::IO::WindowLayer&, bool enable, bool output[256]) -> void;
|
||||
alwaysinline auto renderWindow(PPU::IO::WindowLayer&, bool enable,
|
||||
bool output[1024], uint ws, bool stretch) -> void;
|
||||
alwaysinline auto renderWindow(PPU::IO::WindowColor&, uint mask, bool *output,
|
||||
uint oneLeft, uint oneRight, uint twoLeft, uint twoRight,
|
||||
uint scale, uint offset) -> void;
|
||||
int oneLeft, int oneRight, int twoLeft, int twoRight,
|
||||
uint scale, uint offset, uint ws) -> void;
|
||||
|
||||
//unserialized:
|
||||
uint y; //constant
|
||||
|
@ -361,8 +355,8 @@ public:
|
|||
Pixel *above = new Pixel[61440];
|
||||
Pixel *below = new Pixel[61440];
|
||||
|
||||
bool *windowAbove = new bool[25600] ;
|
||||
bool *windowBelow = new bool[25600] ;
|
||||
bool *windowAbove = new bool[61440] ;
|
||||
bool *windowBelow = new bool[61440] ;
|
||||
|
||||
//flush()
|
||||
static uint start;
|
||||
|
|
|
@ -1,28 +1,74 @@
|
|||
auto PPU::Line::renderWindow(PPU::IO::WindowLayer& self, bool enable, bool output[256]) -> void {
|
||||
auto PPU::Line::renderWindow(PPU::IO::WindowLayer& self, bool enable,
|
||||
bool output[1024], uint ws, bool stretch) -> void {
|
||||
uint width = 256 + 2 * ws;
|
||||
if(!enable || (!self.oneEnable && !self.twoEnable)) {
|
||||
memory::fill<bool>(output, 256, 0);
|
||||
memory::fill<bool>(output, width, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
int oneLeft = io.window.oneLeft;
|
||||
int oneRight = io.window.oneRight;
|
||||
if (stretch) {
|
||||
oneLeft = (oneLeft << 1) - 128 + ws;
|
||||
oneRight = (oneRight << 1) - 128 + ws;
|
||||
} else {
|
||||
if (oneLeft == 0) {
|
||||
oneLeft = -1;
|
||||
} else if (oneLeft == 255) {
|
||||
oneLeft = width;
|
||||
} else {
|
||||
oneLeft += ws;
|
||||
}
|
||||
if (oneRight == 0) {
|
||||
oneRight = -1;
|
||||
} else if (oneRight == 255) {
|
||||
oneRight = width;
|
||||
} else {
|
||||
oneRight += ws;
|
||||
}
|
||||
}
|
||||
|
||||
if(self.oneEnable && !self.twoEnable) {
|
||||
bool set = 1 ^ self.oneInvert, clear = !set;
|
||||
for(uint x : range(256)) {
|
||||
output[x] = x >= io.window.oneLeft && x <= io.window.oneRight ? set : clear;
|
||||
for(int x : range(width)) {
|
||||
output[x] = x >= oneLeft && x <= oneRight ? set : clear;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int twoLeft = io.window.twoLeft;
|
||||
int twoRight = io.window.twoRight;
|
||||
if (stretch) {
|
||||
twoLeft = (twoLeft << 1) - 128 + ws;
|
||||
twoRight = (twoRight << 1) - 128 + ws;
|
||||
} else { // extend edges
|
||||
if (twoLeft == 0) {
|
||||
twoLeft = -1;
|
||||
} else if (twoLeft == 255) {
|
||||
twoLeft = width;
|
||||
} else {
|
||||
twoLeft += ws;
|
||||
}
|
||||
if (twoRight == 0) {
|
||||
twoRight = -1;
|
||||
} else if (twoRight == 255) {
|
||||
twoRight = width;
|
||||
} else {
|
||||
twoRight += ws;
|
||||
}
|
||||
}
|
||||
|
||||
if(self.twoEnable && !self.oneEnable) {
|
||||
bool set = 1 ^ self.twoInvert, clear = !set;
|
||||
for(uint x : range(256)) {
|
||||
output[x] = x >= io.window.twoLeft && x <= io.window.twoRight ? set : clear;
|
||||
for(int x : range(width)) {
|
||||
output[x] = x >= twoLeft && x <= twoRight ? set : clear;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for(uint x : range(256)) {
|
||||
bool oneMask = (x >= io.window.oneLeft && x <= io.window.oneRight) ^ self.oneInvert;
|
||||
bool twoMask = (x >= io.window.twoLeft && x <= io.window.twoRight) ^ self.twoInvert;
|
||||
for(int x : range(width)) {
|
||||
bool oneMask = (x >= oneLeft && x <= oneRight) ^ self.oneInvert;
|
||||
bool twoMask = (x >= twoLeft && x <= twoRight) ^ self.twoInvert;
|
||||
switch(self.mask) {
|
||||
case 0: output[x] = (oneMask | twoMask) == 1; break;
|
||||
case 1: output[x] = (oneMask & twoMask) == 1; break;
|
||||
|
@ -33,24 +79,25 @@ auto PPU::Line::renderWindow(PPU::IO::WindowLayer& self, bool enable, bool outpu
|
|||
}
|
||||
|
||||
auto PPU::Line::renderWindow(PPU::IO::WindowColor& self, uint mask, bool *output,
|
||||
uint oneLeft, uint oneRight, uint twoLeft, uint twoRight,
|
||||
uint scale, uint offset) -> void {
|
||||
int oneLeft, int oneRight, int twoLeft, int twoRight,
|
||||
uint scale, uint offset, uint ws) -> void {
|
||||
uint width = 256 + 2 * ws;
|
||||
bool set, clear;
|
||||
switch(mask) {
|
||||
case 0: memory::fill<bool>(output, 256 * scale * scale, 1); return; //always
|
||||
case 0: memory::fill<bool>(output, width * scale * scale, 1); return; //always
|
||||
case 1: set = 1, clear = 0; break; //inside
|
||||
case 2: set = 0, clear = 1; break; //outside
|
||||
case 3: memory::fill<bool>(output, 256 * scale * scale, 0); return; //never
|
||||
case 3: memory::fill<bool>(output, width * scale * scale, 0); return; //never
|
||||
}
|
||||
|
||||
if(!self.oneEnable && !self.twoEnable) {
|
||||
memory::fill<bool>(output, 256 * scale * scale, clear);
|
||||
memory::fill<bool>(output, width * scale * scale, clear);
|
||||
return;
|
||||
}
|
||||
|
||||
if(self.oneEnable && !self.twoEnable) {
|
||||
if(self.oneInvert) set ^= 1, clear ^= 1;
|
||||
for(uint x : range(256 * scale)) {
|
||||
for(int x : range(width * scale)) {
|
||||
output[x+offset] = x >= oneLeft && x <= oneRight ? set : clear;
|
||||
}
|
||||
return;
|
||||
|
@ -58,13 +105,13 @@ auto PPU::Line::renderWindow(PPU::IO::WindowColor& self, uint mask, bool *output
|
|||
|
||||
if(self.twoEnable && !self.oneEnable) {
|
||||
if(self.twoInvert) set ^= 1, clear ^= 1;
|
||||
for(uint x : range(256 * scale)) {
|
||||
for(int x : range(width * scale)) {
|
||||
output[x+offset] = x >= twoLeft && x <= twoRight ? set : clear;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for(uint x : range(256 * scale)) {
|
||||
for(int x : range(width * scale)) {
|
||||
bool oneMask = (x >= oneLeft && x <= oneRight) ^ self.oneInvert;
|
||||
bool twoMask = (x >= twoLeft && x <= twoRight) ^ self.twoInvert;
|
||||
switch(self.mask) {
|
||||
|
|
|
@ -165,7 +165,6 @@ auto Program::loadSuperFamicom(string location) -> bool {
|
|||
}
|
||||
|
||||
// load and apply simple settings override file (if found)
|
||||
vector<uint8_t> rso;
|
||||
if(location.endsWith("/")) {
|
||||
rso = file::read({location, "gamesettings.bso"});
|
||||
} else if(location.iendsWith(".zip")) {
|
||||
|
@ -182,71 +181,7 @@ auto Program::loadSuperFamicom(string location) -> bool {
|
|||
} else {
|
||||
rso = file::read(path("gamesettings", location, ".bso"));
|
||||
}
|
||||
if(rso) {
|
||||
int i = 0;
|
||||
int v = 0;
|
||||
int c = -1;
|
||||
int n = 0;
|
||||
while (i < rso.size()) {
|
||||
v = rso[i];
|
||||
if ((v >= 'a' && v <= 'z') || (v >= 'A' && v <= 'Z')) {
|
||||
c = v;
|
||||
} else if (c > -1 && v >= '0' && v <= '9') {
|
||||
n = (n * 10) + (v - '0');
|
||||
if (i+1 == rso.size() || rso[i+1] < '0' || rso[i+1] > '9') {
|
||||
switch (c) {
|
||||
case 'p': //pixelAspectCorrect 0:off 1:on
|
||||
settings.video.aspectCorrection = n == 1;
|
||||
emulator->configure("Video/AspectCorrection", settings.video.aspectCorrection);
|
||||
break;
|
||||
case 'o': //overscan 0:216 1:224 (2:240 3:240f)
|
||||
settings.video.overscan = n == 1;
|
||||
emulator->configure("Video/Overscan", settings.video.overscan);
|
||||
break;
|
||||
case 'w': //widescreenMode 0:none 1:on 2:mode7
|
||||
settings.emulator.hack.ppu.mode7.wsMode = n == 1 ? 2 : (n == 2 ? 1 : 0);
|
||||
emulator->configure("Hacks/PPU/Mode7/WsMode", settings.emulator.hack.ppu.mode7.wsMode);
|
||||
break;
|
||||
case 'W': //WSaspectRatio int [<=200:wsExt, >200:ar]
|
||||
settings.emulator.hack.ppu.mode7.widescreen = n;
|
||||
emulator->configure("Hacks/PPU/Mode7/Widescreen", settings.emulator.hack.ppu.mode7.widescreen);
|
||||
break;
|
||||
case 's': //WSsprites 0:safe 1:unsafe 2:clip
|
||||
settings.emulator.hack.ppu.mode7.wsobj = n == 1 ? 1 : (n == 2 ? 3 : 0);
|
||||
emulator->configure("Hacks/PPU/Mode7/Wsobj", settings.emulator.hack.ppu.mode7.wsobj);
|
||||
break;
|
||||
case 'i': //igwin 0:none 1:outside 2:outside&always 3:all
|
||||
settings.emulator.hack.ppu.mode7.igwin = n > 3 ? 0 : n;
|
||||
emulator->configure("Hacks/PPU/Mode7/Igwin", settings.emulator.hack.ppu.mode7.igwin);
|
||||
break;
|
||||
case 'I': //igwinx int
|
||||
settings.emulator.hack.ppu.mode7.igwinx = n > 255 ? 128 : n;
|
||||
emulator->configure("Hacks/PPU/Mode7/Igwinx", settings.emulator.hack.ppu.mode7.igwinx);
|
||||
break;
|
||||
case 'b': //bg1WS 0:off 1:on 2:auto(h+v)
|
||||
settings.emulator.hack.ppu.mode7.wsbg1 = n == 1 ? 1 : (n == 2 ? 16 : 0);
|
||||
emulator->configure("Hacks/PPU/Mode7/Wsbg1", settings.emulator.hack.ppu.mode7.wsbg1);
|
||||
break;
|
||||
case 'B': //bg2WS 0:off 1:on 2:auto(h+v)
|
||||
settings.emulator.hack.ppu.mode7.wsbg2 = n == 1 ? 1 : (n == 2 ? 16 : 0);
|
||||
emulator->configure("Hacks/PPU/Mode7/Wsbg2", settings.emulator.hack.ppu.mode7.wsbg2);
|
||||
break;
|
||||
case 'c': //bg3WS 0:off 1:on 2:auto(h+v)
|
||||
settings.emulator.hack.ppu.mode7.wsbg3 = n == 1 ? 1 : (n == 2 ? 16 : 0);
|
||||
emulator->configure("Hacks/PPU/Mode7/Wsbg3", settings.emulator.hack.ppu.mode7.wsbg3);
|
||||
break;
|
||||
case 'C': //bg4WS 0:off 1:on 2:auto(h+v)
|
||||
settings.emulator.hack.ppu.mode7.wsbg4 = n == 1 ? 1 : (n == 2 ? 16 : 0);
|
||||
emulator->configure("Hacks/PPU/Mode7/Wsbg4", settings.emulator.hack.ppu.mode7.wsbg4);
|
||||
break;
|
||||
}
|
||||
c = -1;
|
||||
n = 0;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -71,9 +71,139 @@ auto Program::hackCompatibility() -> void {
|
|||
emulator->configure("Hacks/PPU/Fast", fastPPU);
|
||||
emulator->configure("Hacks/PPU/NoSpriteLimit", fastPPUNoSpriteLimit);
|
||||
emulator->configure("Hacks/PPU/RenderCycle", renderCycle);
|
||||
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/Widescreen", settings.emulator.hack.ppu.mode7.widescreen);
|
||||
emulator->configure("Hacks/PPU/Mode7/Wsbg1", settings.emulator.hack.ppu.mode7.wsbg1);
|
||||
emulator->configure("Hacks/PPU/Mode7/Wsbg2", settings.emulator.hack.ppu.mode7.wsbg2);
|
||||
emulator->configure("Hacks/PPU/Mode7/Wsbg3", settings.emulator.hack.ppu.mode7.wsbg3);
|
||||
emulator->configure("Hacks/PPU/Mode7/Wsbg4", settings.emulator.hack.ppu.mode7.wsbg4);
|
||||
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/Strwin", false);
|
||||
emulator->configure("Hacks/PPU/Mode7/BgGrad", settings.emulator.hack.ppu.mode7.bgGrad);
|
||||
emulator->configure("Hacks/PPU/Mode7/WindRad", settings.emulator.hack.ppu.mode7.windRad);
|
||||
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/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);
|
||||
emulator->configure("Hacks/DSP/Cubic", settings.emulator.hack.dsp.cubic);
|
||||
emulator->configure("Hacks/Coprocessor/DelayedSync", coprocessorDelayedSync);
|
||||
|
||||
if(rso) {
|
||||
int i = 0;
|
||||
int v = 0;
|
||||
int c = -1;
|
||||
int n = 0;
|
||||
bool e = true;
|
||||
while (i < rso.size()) {
|
||||
v = rso[i++];
|
||||
if (v == '%') {
|
||||
e = !e;
|
||||
}
|
||||
if (!e) {
|
||||
continue;
|
||||
}
|
||||
if ((v >= 'a' && v <= 'z') || (v >= 'A' && v <= 'Z')) {
|
||||
c = v;
|
||||
} else if (c > -1 && v >= '0' && v <= '9') {
|
||||
n = (n * 10) + (v - '0');
|
||||
if (i == rso.size() || rso[i] < '0' || rso[i] > '9') {
|
||||
switch (c) {
|
||||
case 'p': //pixelAspectCorrect 0:off 1:on
|
||||
emulator->configure("Video/AspectCorrection", n == 1);
|
||||
break;
|
||||
case 'o': //overscan 0:216 1:224 (2:240 3:240f)
|
||||
emulator->configure("Video/Overscan", n == 1);
|
||||
break;
|
||||
case 'w': //widescreenMode 0:none 1:on 2:mode7
|
||||
emulator->configure("Hacks/PPU/Mode7/WsMode", n == 1 ? 2 : (n == 2 ? 1 : 0));
|
||||
break;
|
||||
case 'W': //WSaspectRatio int [<=200:wsExt, >200:ar]
|
||||
emulator->configure("Hacks/PPU/Mode7/Widescreen", n);
|
||||
break;
|
||||
case 's': //WSsprites 0:safe 1:unsafe 2:clip
|
||||
emulator->configure("Hacks/PPU/Mode7/Wsobj", n == 1 ? 1 : (n == 2 ? 3 : 0));
|
||||
break;
|
||||
case 'i': //igwin 0:none 1:outside 2:outside&always 3:all
|
||||
emulator->configure("Hacks/PPU/Mode7/Igwin", n > 3 ? 0 : n);
|
||||
break;
|
||||
case 'I': //igwinx int
|
||||
emulator->configure("Hacks/PPU/Mode7/Igwinx", n > 255 ? 128 : n);
|
||||
break;
|
||||
case 'b': //bg1WS 0:off 1:on 2:auto(h+v)
|
||||
emulator->configure("Hacks/PPU/Mode7/Wsbg1",
|
||||
n >= 1000 ? n : //above/below line (processed later)
|
||||
(n == 1 ? 1 : //on
|
||||
(n == 2 ? 16 : //auto H+V
|
||||
(n == 3 ? 15 : //auto H
|
||||
(n == 10 ? 12 : //crop
|
||||
(n == 11 ? 13 : //crop auto
|
||||
(n == 20 ? 14 : //disable
|
||||
0)))))) //off
|
||||
);
|
||||
break;
|
||||
case 'B': //bg2WS 0:off 1:on 2:auto(h+v)
|
||||
emulator->configure("Hacks/PPU/Mode7/Wsbg2",
|
||||
n >= 1000 ? n : //above/below line (processed later)
|
||||
(n == 1 ? 1 : //on
|
||||
(n == 2 ? 16 : //auto H+V
|
||||
(n == 3 ? 15 : //auto H
|
||||
(n == 10 ? 12 : //crop
|
||||
(n == 11 ? 13 : //crop auto
|
||||
(n == 20 ? 14 : //disable
|
||||
0)))))) //off
|
||||
);
|
||||
break;
|
||||
case 'c': //bg3WS 0:off 1:on 2:auto(h+v)
|
||||
emulator->configure("Hacks/PPU/Mode7/Wsbg3",
|
||||
n >= 1000 ? n : //above/below line (processed later)
|
||||
(n == 1 ? 1 : //on
|
||||
(n == 2 ? 16 : //auto H+V
|
||||
(n == 3 ? 15 : //auto H
|
||||
(n == 10 ? 12 : //crop
|
||||
(n == 11 ? 13 : //crop auto
|
||||
(n == 20 ? 14 : //disable
|
||||
0)))))) //off
|
||||
);
|
||||
break;
|
||||
case 'C': //bg4WS 0:off 1:on 2:auto(h+v)
|
||||
emulator->configure("Hacks/PPU/Mode7/Wsbg4",
|
||||
n >= 1000 ? n : //above/below line (processed later)
|
||||
(n == 1 ? 1 : //on
|
||||
(n == 2 ? 16 : //auto H+V
|
||||
(n == 3 ? 15 : //auto H
|
||||
(n == 10 ? 12 : //crop
|
||||
(n == 11 ? 13 : //crop auto
|
||||
(n == 20 ? 14 : //disable
|
||||
0)))))) //off
|
||||
);
|
||||
break;
|
||||
case 'm': //wsMarker 0:off 1-10:lines 11-20:darken, wsMarkerAlpha 1-10/11-20:opaque-transparent
|
||||
emulator->configure("Hacks/PPU/Mode7/WsMarker", n < 1 || n > 20 ? 0 : (n - 1) / 10 + 1);
|
||||
emulator->configure("Hacks/PPU/Mode7/WsMarkerAlpha", (n - 1) % 10 + 1);
|
||||
break;
|
||||
case 'P': //Perspective 0:off 1-3:auto 4-6+:on (wide, medium, narrow)
|
||||
emulator->configure("Hacks/PPU/Mode7/Perspective", n < 1 || n > 6 ? 0 : n );
|
||||
break;
|
||||
case 'O': //Overlock CPU percentage
|
||||
emulator->configure("Hacks/CPU/Overclock", n );
|
||||
break;
|
||||
case 'S': //Stretch Window [EXPERIMENTAL!! DO NOT USE!!]
|
||||
emulator->configure("Hacks/PPU/Mode7/Strwin", n == 2 );
|
||||
break;
|
||||
}
|
||||
c = -1;
|
||||
n = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
auto Program::hackPatchMemory(vector<uint8_t>& data) -> void {
|
||||
|
|
|
@ -27,6 +27,8 @@ struct Program : Lock, Emulator::Platform {
|
|||
auto unload() -> void;
|
||||
auto verified() const -> bool;
|
||||
|
||||
vector<uint8_t> rso;
|
||||
|
||||
//game-pak.cpp
|
||||
auto openPakSuperFamicom(string name, vfs::file::mode mode) -> shared_pointer<vfs::file>;
|
||||
auto openPakGameBoy(string name, vfs::file::mode mode) -> shared_pointer<vfs::file>;
|
||||
|
|
|
@ -41,8 +41,10 @@ static vector<string> cheatList;
|
|||
#define RETRO_DEVICE_LIGHTGUN_JUSTIFIERS RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_LIGHTGUN, 2)
|
||||
|
||||
#define RETRO_GAME_TYPE_SGB 0x101 | 0x1000
|
||||
#define RETRO_GAME_TYPE_BSX 0x110 | 0x1000
|
||||
#define RETRO_MEMORY_SGB_SRAM ((1 << 8) | RETRO_MEMORY_SAVE_RAM)
|
||||
#define RETRO_MEMORY_GB_SRAM ((2 << 8) | RETRO_MEMORY_SAVE_RAM)
|
||||
#define RETRO_MEMORY_BSX_SRAM ((3 << 8) | RETRO_MEMORY_SAVE_RAM)
|
||||
|
||||
static bool flush_variables() // returns whether video dimensions have changed (overscan, aspectcorrection scale or widescreen AR)
|
||||
{
|
||||
|
@ -499,7 +501,7 @@ static bool flush_variables() // returns whether video dimensions have changed (
|
|||
int v = variable.value[0] - '0';
|
||||
if (v >= 0 && v <= 8) val = v;
|
||||
}
|
||||
emulator->configure("Hacks/PPU/Mode7/'WindRad", val);
|
||||
emulator->configure("Hacks/PPU/Mode7/WindRad", val);
|
||||
}
|
||||
|
||||
bool aspectcorrection = program->aspectcorrection;
|
||||
|
@ -598,14 +600,24 @@ static void set_environment_info(retro_environment_t cb)
|
|||
static const struct retro_subsystem_memory_info gb_memory[] = {
|
||||
{ "srm", RETRO_MEMORY_GB_SRAM },
|
||||
};
|
||||
|
||||
static const struct retro_subsystem_memory_info bsx_memory[] = {
|
||||
{ "srm", RETRO_MEMORY_BSX_SRAM },
|
||||
};
|
||||
|
||||
static const struct retro_subsystem_rom_info sgb_roms[] = {
|
||||
{ "Game Boy ROM", "gb|gbc", true, false, true, gb_memory, 1 },
|
||||
{ "Super Game Boy ROM", "smc|sfc|swc|fig|bs", true, false, true, sgb_memory, 1 },
|
||||
{ "Super Game Boy ROM", "smc|sfc|swc|fig", true, false, true, sgb_memory, 1 },
|
||||
};
|
||||
|
||||
static const struct retro_subsystem_rom_info bsx_roms[] = {
|
||||
{ "BS-X ROM", "bs", true, false, true, bsx_memory, 1 },
|
||||
{ "BS-X BIOS ROM", "smc|sfc|swc|fig", true, false, true, bsx_memory, 1 },
|
||||
};
|
||||
|
||||
static const struct retro_subsystem_info subsystems[] = {
|
||||
{ "Super Game Boy", "sgb", sgb_roms, 2, RETRO_GAME_TYPE_SGB },
|
||||
{ "BS-X Satellaview", "bsx", bsx_roms, 2, RETRO_GAME_TYPE_BSX },
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -808,7 +820,7 @@ RETRO_API void retro_get_system_info(retro_system_info *info)
|
|||
info->library_name = Emulator::Name;
|
||||
info->library_version = Emulator::Version;
|
||||
info->need_fullpath = true;
|
||||
info->valid_extensions = "smc|sfc";
|
||||
info->valid_extensions = "smc|sfc|gb|gbc|bs";
|
||||
info->block_extract = false;
|
||||
}
|
||||
|
||||
|
@ -933,17 +945,54 @@ RETRO_API bool retro_load_game(const retro_game_info *game)
|
|||
|
||||
flush_variables();
|
||||
|
||||
if (string(game->path).endsWith(".gb") || string(game->path).endsWith(".gbc"))
|
||||
if (string(game->path).endsWith(".gb"))
|
||||
{
|
||||
const char *system_dir;
|
||||
environ_cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &system_dir);
|
||||
string sgb_full_path = string(system_dir, "/", sgb_bios).transform("\\", "/");
|
||||
if (!file::exists(sgb_full_path)) {
|
||||
string sgb_full_path = string(game->path).transform("\\", "/");
|
||||
string sgb_full_path2 = string(sgb_full_path).replace(".gb", ".sfc");
|
||||
if (!file::exists(sgb_full_path2)) {
|
||||
string sgb_full_path = string(system_dir, "/", sgb_bios).transform("\\", "/");
|
||||
program->superFamicom.location = sgb_full_path;
|
||||
}
|
||||
else {
|
||||
program->superFamicom.location = sgb_full_path2;
|
||||
}
|
||||
program->gameBoy.location = string(game->path);
|
||||
if (!file::exists(program->superFamicom.location)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (string(game->path).endsWith(".gbc"))
|
||||
{
|
||||
const char *system_dir;
|
||||
environ_cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &system_dir);
|
||||
string sgb_full_path = string(game->path).transform("\\", "/");
|
||||
string sgb_full_path2 = string(sgb_full_path).replace(".gbc", ".sfc");
|
||||
if (!file::exists(sgb_full_path2)) {
|
||||
string sgb_full_path = string(system_dir, "/", sgb_bios).transform("\\", "/");
|
||||
program->superFamicom.location = sgb_full_path;
|
||||
}
|
||||
else {
|
||||
program->superFamicom.location = sgb_full_path2;
|
||||
}
|
||||
program->gameBoy.location = string(game->path);
|
||||
if (!file::exists(program->superFamicom.location)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
program->superFamicom.location = sgb_full_path;
|
||||
program->gameBoy.location = string(game->path);
|
||||
}
|
||||
else if (string(game->path).endsWith(".bs"))
|
||||
{
|
||||
const char *system_dir;
|
||||
environ_cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &system_dir);
|
||||
string bs_full_path = string(system_dir, "/", "BS-X.bin").transform("\\", "/");
|
||||
if (!file::exists(bs_full_path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
program->superFamicom.location = bs_full_path;
|
||||
program->bsMemory.location = string(game->path);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -979,6 +1028,14 @@ RETRO_API bool retro_load_game_special(unsigned game_type,
|
|||
program->superFamicom.location = info[1].path;
|
||||
}
|
||||
break;
|
||||
case RETRO_GAME_TYPE_BSX:
|
||||
{
|
||||
libretro_print(RETRO_LOG_INFO, "BS-X ROM: %s\n", info[0].path);
|
||||
libretro_print(RETRO_LOG_INFO, "BS-X BIOS ROM: %s\n", info[1].path);
|
||||
program->bsMemory.location = info[0].path;
|
||||
program->superFamicom.location = info[1].path;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ using namespace nall;
|
|||
#include <heuristics/heuristics.cpp>
|
||||
#include <heuristics/super-famicom.cpp>
|
||||
#include <heuristics/game-boy.cpp>
|
||||
#include <heuristics/bs-memory.cpp>
|
||||
|
||||
#include "resources.hpp"
|
||||
|
||||
|
@ -36,11 +37,13 @@ struct Program : Emulator::Platform
|
|||
auto loadFile(string location) -> vector<uint8_t>;
|
||||
auto loadSuperFamicom(string location) -> bool;
|
||||
auto loadGameBoy(string location) -> bool;
|
||||
auto loadBSMemory(string location) -> bool;
|
||||
|
||||
auto save() -> void;
|
||||
|
||||
auto openRomSuperFamicom(string name, vfs::file::mode mode) -> shared_pointer<vfs::file>;
|
||||
auto openRomGameBoy(string name, vfs::file::mode mode) -> shared_pointer<vfs::file>;
|
||||
auto openRomBSMemory(string name, vfs::file::mode mode) -> shared_pointer<vfs::file>;
|
||||
|
||||
auto hackPatchMemory(vector<uint8_t>& data) -> void;
|
||||
|
||||
|
@ -76,6 +79,10 @@ public:
|
|||
struct GameBoy : Game {
|
||||
vector<uint8_t> program;
|
||||
} gameBoy;
|
||||
|
||||
struct BSMemory : Game {
|
||||
vector<uint8_t> program;
|
||||
} bsMemory;
|
||||
};
|
||||
|
||||
static Program *program = nullptr;
|
||||
|
@ -136,6 +143,21 @@ auto Program::open(uint id, string name, vfs::file::mode mode, bool required) ->
|
|||
result = openRomGameBoy(name, mode);
|
||||
}
|
||||
}
|
||||
else if (id == 3) { //BS Memory
|
||||
if (name == "manifest.bml" && mode == vfs::file::mode::read) {
|
||||
result = vfs::memory::file::open(bsMemory.manifest.data<uint8_t>(), bsMemory.manifest.size());
|
||||
}
|
||||
else if (name == "program.rom" && mode == vfs::file::mode::read) {
|
||||
result = vfs::memory::file::open(bsMemory.program.data(), bsMemory.program.size());
|
||||
}
|
||||
else if(name == "program.flash") {
|
||||
//writes are not flushed to disk in bsnes
|
||||
result = vfs::memory::file::open(bsMemory.program.data(), bsMemory.program.size());
|
||||
}
|
||||
else {
|
||||
result = openRomBSMemory(name, mode);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -221,6 +243,11 @@ auto Program::load(uint id, string name, string type, vector<string> options) ->
|
|||
return { id, NULL };
|
||||
}
|
||||
}
|
||||
else if (id == 3) {
|
||||
if (loadBSMemory(bsMemory.location)) {
|
||||
return { id, NULL };
|
||||
}
|
||||
}
|
||||
return { id, options(0) };
|
||||
}
|
||||
|
||||
|
@ -421,6 +448,21 @@ auto Program::openRomGameBoy(string name, vfs::file::mode mode) -> shared_pointe
|
|||
return {};
|
||||
}
|
||||
|
||||
auto Program::openRomBSMemory(string name, vfs::file::mode mode) -> shared_pointer<vfs::file> {
|
||||
if (name == "program.rom" && mode == vfs::file::mode::read)
|
||||
{
|
||||
return vfs::memory::file::open(bsMemory.program.data(), bsMemory.program.size());
|
||||
}
|
||||
|
||||
if (name == "program.flash")
|
||||
{
|
||||
//writes are not flushed to disk
|
||||
return vfs::memory::file::open(bsMemory.program.data(), bsMemory.program.size());
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
auto Program::loadFile(string location) -> vector<uint8_t>
|
||||
{
|
||||
if(Location::suffix(location).downcase() == ".zip") {
|
||||
|
@ -510,6 +552,23 @@ auto Program::loadGameBoy(string location) -> bool {
|
|||
return true;
|
||||
}
|
||||
|
||||
auto Program::loadBSMemory(string location) -> bool {
|
||||
vector<uint8_t> rom;
|
||||
rom = loadFile(location);
|
||||
|
||||
if (rom.size() < 0x8000) return false;
|
||||
|
||||
auto heuristics = Heuristics::BSMemory(rom, location);
|
||||
auto sha256 = Hash::SHA256(rom).digest();
|
||||
|
||||
bsMemory.manifest = heuristics.manifest();
|
||||
bsMemory.document = BML::unserialize(bsMemory.manifest);
|
||||
bsMemory.location = location;
|
||||
|
||||
bsMemory.program = rom;
|
||||
return true;
|
||||
}
|
||||
|
||||
auto Program::hackPatchMemory(vector<uint8_t>& data) -> void
|
||||
{
|
||||
auto title = superFamicom.title;
|
||||
|
|
|
@ -124,7 +124,7 @@ ifeq ($(platform),windows)
|
|||
options += -mthreads -lpthread -lws2_32 -lole32
|
||||
options += $(if $(findstring g++,$(compiler)),-static -static-libgcc -static-libstdc++)
|
||||
options += $(if $(findstring true,$(console)),-mconsole,-mwindows)
|
||||
windres ?= windres
|
||||
windres := windres
|
||||
endif
|
||||
|
||||
# macos settings
|
||||
|
|
44
pack/Database/BS Memory.bml
Normal file
|
@ -0,0 +1,44 @@
|
|||
database
|
||||
revision: 2020-01-01
|
||||
|
||||
//BS Memory (JPN)
|
||||
|
||||
database
|
||||
revision: 2018-04-14
|
||||
|
||||
game
|
||||
sha256: 80c34b50817d58820bc8c88d2d9fa462550b4a76372e19c6467cbfbc8cf5d9ef
|
||||
label: 鮫亀 キャラカセット
|
||||
name: Same Game - Chara Cassette
|
||||
region: BSMC-ZS5J-JPN
|
||||
revision: BSMC-ZS5J-0
|
||||
board: BSMC-CR-01
|
||||
memory
|
||||
type: ROM
|
||||
size: 0x80000
|
||||
content: Program
|
||||
|
||||
game
|
||||
sha256: 859c7f7b4771d920a5bdb11f1d247ab6b43fb026594d1062f6f72d32cd340a0a
|
||||
label: 鮫亀 キャラデータ集
|
||||
name: Same Game - Chara Data Shuu
|
||||
region: BSMC-YS5J-JPN
|
||||
revision: BSMC-YS5J-0
|
||||
board: BSMC-CR-01
|
||||
memory
|
||||
type: ROM
|
||||
size: 0x80000
|
||||
content: Program
|
||||
|
||||
game
|
||||
sha256: c92a15fdd9b0133f9ea69105d0230a3acd1cdeef98567462eca86ea02a959e4e
|
||||
label: SDガンダム ジーネクスト ユニット&マップコレクション
|
||||
name: SD Gundam G Next - Unit & Map Collection
|
||||
region: BSMC-ZX3J-JPN
|
||||
revision: BSMC-ZX3J-0
|
||||
board: BSMC-BR-01
|
||||
memory
|
||||
type: ROM
|
||||
size: 0x80000
|
||||
content: Program
|
||||
|
87497
pack/Database/Cheat Codes.bml
Normal file
213
pack/Database/Sufami Turbo.bml
Normal file
|
@ -0,0 +1,213 @@
|
|||
database
|
||||
revision: 2020-01-01
|
||||
|
||||
//Sufami Turbo (JPN)
|
||||
|
||||
database
|
||||
revision: 2018-04-14
|
||||
|
||||
game
|
||||
sha256: f73bda08743565e0bd101632ebbac2d363d703a3ab39d23f49d95217cab29269
|
||||
label: 美少女戦士セーラームーン セーラースターズ ふわふわパニック2
|
||||
name: Bishoujo Senshi Sailor Moon Sailor Stars - Fuwafuwa Panic 2
|
||||
region: SFT-0112-JPN
|
||||
revision: SAILOR MOON
|
||||
board: PT-911
|
||||
memory
|
||||
type: ROM
|
||||
size: 0x100000
|
||||
content: Program
|
||||
note: Unlinkable
|
||||
|
||||
game
|
||||
sha256: afb3f2a83b5bfcb1b8829b6995f108cc4d64ca322d1ba4a50b83af6e1f2e89bd
|
||||
label: クレヨンしんちゃん 長ぐつドボン!!
|
||||
name: Crayon Shin-chan - Nagagutsu Dobon!!
|
||||
region: SFT-0113-JPN
|
||||
revision: SHINCYAN
|
||||
board: PT-911
|
||||
memory
|
||||
type: ROM
|
||||
size: 0x80000
|
||||
content: Program
|
||||
note: Unlinkable
|
||||
|
||||
game
|
||||
sha256: d93b3a570e7cf343f680ab0768a50b77e3577f9c555007e2de3decd6bc4765c8
|
||||
label: ゲゲゲの鬼太郎 妖怪ドンジャラ
|
||||
name: Gegege no Kitarou - Youkai Donjara
|
||||
region: SFT-0106-JPN
|
||||
revision: KITARO DONJYAR
|
||||
board: PT-911
|
||||
memory
|
||||
type: ROM
|
||||
size: 0x80000
|
||||
content: Program
|
||||
note: Unlinkable
|
||||
|
||||
game
|
||||
sha256: 89aecd4e23d8219c8de3e71bb75db3dfe667d51c1eba4ea7239d2f772743d0cc
|
||||
label: 激走戦隊カーレンジャ 全開!レーサー戦士
|
||||
name: Gekisou Sentai Carranger - Zenkai! Racer Senshi
|
||||
region: SFT-0109-JPN
|
||||
revision: CAR RANGER
|
||||
board: PT-911
|
||||
memory
|
||||
type: ROM
|
||||
size: 0x80000
|
||||
content: Program
|
||||
note: Unlinkable
|
||||
|
||||
game
|
||||
sha256: 602b20b788640f5743487108a10f3f77bca5ce2d24208b25b1ca498a96eb0d69
|
||||
label: ぽいぽい忍者ワールド
|
||||
name: Poi Poi Ninja World
|
||||
region: SFT-0103-JPN
|
||||
revision: POI POI NINJYA
|
||||
board: PT-911
|
||||
memory
|
||||
type: ROM
|
||||
size: 0x80000
|
||||
content: Program
|
||||
memory
|
||||
type: RAM
|
||||
size: 0x800
|
||||
content: Save
|
||||
note: Linkable: SFT-0103-JPN
|
||||
|
||||
game
|
||||
sha256: 2a9d7c9a61318861028a73ca03e32a48cff162d76cba36fbaab8690b212efe9b
|
||||
label: SDガンダムジェネレーション アクシズ戦記
|
||||
name: SD Gundam Generation - Axis Senki
|
||||
region: SFT-0107-JPN
|
||||
revision: GUNDAM C
|
||||
board: PT-912
|
||||
memory
|
||||
type: ROM
|
||||
size: 0x80000
|
||||
content: Program
|
||||
memory
|
||||
type: RAM
|
||||
size: 0x2000
|
||||
content: Save
|
||||
note: Linkable: SFT-0104-JPN, SFT-0105-JPN, SFT-0107-JPN, SFT-0108-JPN, SFT-0110-JPN, SFT-0111-JPN
|
||||
|
||||
game
|
||||
sha256: 60ac017c18f534e8cf24ca7f38e22ce92db95ea6c30b2d59d76f13c4f1c8a6e4
|
||||
label: SDガンダムジェネレーション バビロニア建国戦記
|
||||
name: SD Gundam Generation - Babylonia Kenkoku Senki
|
||||
region: SFT-0108-JPN
|
||||
revision: GUNDAM D
|
||||
board: PT-912
|
||||
memory
|
||||
type: ROM
|
||||
size: 0x80000
|
||||
content: Program
|
||||
memory
|
||||
type: RAM
|
||||
size: 0x2000
|
||||
content: Save
|
||||
note: Linkable: SFT-0104-JPN, SFT-0105-JPN, SFT-0107-JPN, SFT-0108-JPN, SFT-0110-JPN, SFT-0111-JPN
|
||||
|
||||
game
|
||||
sha256: e639b5d5d722432b6809ccc6801dc584e1a3016379f34b335ed2dfa73b1ebf69
|
||||
label: SDガンダムジェネレーション コロニー格闘記
|
||||
name: SD Gundam Generation - Colony Kakutouki
|
||||
region: SFT-0111-JPN
|
||||
revision: GUNDAM F
|
||||
board: PT-912
|
||||
memory
|
||||
type: ROM
|
||||
size: 0x80000
|
||||
content: Program
|
||||
memory
|
||||
type: RAM
|
||||
size: 0x2000
|
||||
content: Save
|
||||
note: Linkable: SFT-0104-JPN, SFT-0105-JPN, SFT-0107-JPN, SFT-0108-JPN, SFT-0110-JPN, SFT-0111-JPN
|
||||
|
||||
game
|
||||
sha256: 8547a08ed11fe408eac282a90ac46654bd2e5f49bda3aec8e5edf166a0a4b9af
|
||||
label: SDガンダムジェネレーション グリプス戦記
|
||||
name: SD Gundam Generation - Gryps Senki
|
||||
region: SFT-0105-JPN
|
||||
revision: GUNDAM B
|
||||
board: PT-912
|
||||
memory
|
||||
type: ROM
|
||||
size: 0x80000
|
||||
content: Program
|
||||
memory
|
||||
type: RAM
|
||||
size: 0x2000
|
||||
content: Save
|
||||
note: Linkable: SFT-0104-JPN, SFT-0105-JPN, SFT-0107-JPN, SFT-0108-JPN, SFT-0110-JPN, SFT-0111-JPN
|
||||
|
||||
game
|
||||
sha256: 3e82215bed08274874b30d461fc4a965c6bca932229da5d46d56e36f484d65eb
|
||||
label: SDガンダムジェネレーション 一年戦争記
|
||||
name: SD Gundam Generation - Ichinen Sensouki
|
||||
region: SFT-0104-JPN
|
||||
revision: GUNDAM A
|
||||
board: PT-912
|
||||
memory
|
||||
type: ROM
|
||||
size: 0x80000
|
||||
content: Program
|
||||
memory
|
||||
type: RAM
|
||||
size: 0x2000
|
||||
content: Save
|
||||
note: Linkable: SFT-0104-JPN, SFT-0105-JPN, SFT-0107-JPN, SFT-0108-JPN, SFT-0110-JPN, SFT-0111-JPN
|
||||
|
||||
game
|
||||
sha256: 5951a58a91d8e397d0a237ccc2b1248e17c7312cb9cc11cbc350200a97b4e021
|
||||
label: SDガンダムジェネレーション ザンスカール戦記
|
||||
name: SD Gundam Generation - Zanscare Senki
|
||||
region: SFT-0110-JPN
|
||||
revision: GUNDAM E
|
||||
board: PT-912
|
||||
memory
|
||||
type: ROM
|
||||
size: 0x80000
|
||||
content: Program
|
||||
memory
|
||||
type: RAM
|
||||
size: 0x2000
|
||||
content: Save
|
||||
note: Linkable: SFT-0104-JPN, SFT-0105-JPN, SFT-0107-JPN, SFT-0108-JPN, SFT-0110-JPN, SFT-0111-JPN
|
||||
|
||||
game
|
||||
sha256: 2fec5f2bc7dee010af10569a3d2bc18715a79a126940800c3eade5abbd625e3f
|
||||
label: SDウルトラバトル セブン伝説
|
||||
name: SD Ultra Battle - Seven Densetsu
|
||||
region: SFT-0102-JPN
|
||||
revision: ULTRA SEVEN 1
|
||||
board: PT-911
|
||||
memory
|
||||
type: ROM
|
||||
size: 0x80000
|
||||
content: Program
|
||||
memory
|
||||
type: RAM
|
||||
size: 0x800
|
||||
content: Save
|
||||
note: Linkable: SFT-0101-JPN, SFT-0102-JPN
|
||||
|
||||
game
|
||||
sha256: 2bb55214fb668ca603d7b944b14f105dfb10b987a8902d420fe4ae1cb69c1d4a
|
||||
label: SDウルトラバトル ウルトラマン伝説
|
||||
name: SD Ultra Battle - Ultraman Densetsu
|
||||
region: SFT-0101-JPN
|
||||
revision: ULTRA MAN 1
|
||||
board: PT-911
|
||||
memory
|
||||
type: ROM
|
||||
size: 0x80000
|
||||
content: Program
|
||||
memory
|
||||
type: RAM
|
||||
size: 0x800
|
||||
content: Save
|
||||
note: Linkable: SFT-0101-JPN, SFT-0102-JPN
|
||||
|
16069
pack/Database/Super Famicom.bml
Normal file
0
pack/Firmware/place_firmware_roms_here
Normal file
674
pack/GPLv3.txt
Normal file
|
@ -0,0 +1,674 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
93
pack/Shaders/AANN.shader/AANN.fs
Normal file
|
@ -0,0 +1,93 @@
|
|||
#version 150
|
||||
|
||||
// AntiAliased Nearest Neighbor
|
||||
// by jimbo1qaz and wareya
|
||||
// Licensed MIT
|
||||
|
||||
precision highp float;
|
||||
|
||||
uniform sampler2D source[];
|
||||
uniform vec4 sourceSize[];
|
||||
uniform vec4 targetSize[];
|
||||
|
||||
in Vertex {
|
||||
vec2 texCoord;
|
||||
};
|
||||
|
||||
out vec4 fragColor;
|
||||
|
||||
#define NOT(fl) (1-fl)
|
||||
#define YES(fl) fl
|
||||
|
||||
vec4 vpow(vec4 n, float e)
|
||||
{
|
||||
return vec4(pow(n.x, e), pow(n.y, e), pow(n.z, e), pow(n.w, e));
|
||||
}
|
||||
|
||||
vec4 getLQV(vec3 mine) {
|
||||
return vec4
|
||||
( mine.r
|
||||
, mine.g
|
||||
, mine.b
|
||||
, mine.r*0.2989 + mine.g*0.5870 + mine.b*0.1140);
|
||||
}
|
||||
vec3 fromLQV(vec4 mine) {
|
||||
float f = mine.w/(mine.r*0.2989 + mine.g*0.5870 + mine.b*0.1140);
|
||||
return vec3(mine.rgb)*f;
|
||||
}
|
||||
|
||||
vec3 percent(float ssize, float tsize, float coord) {
|
||||
float minfull = (coord*tsize - 0.5) /tsize*ssize;
|
||||
float maxfull = (coord*tsize + 0.5) /tsize*ssize;
|
||||
|
||||
float realfull = floor(maxfull);
|
||||
|
||||
if (minfull > realfull) {
|
||||
return vec3(1, (realfull+0.5)/ssize, (realfull+0.5)/ssize);
|
||||
}
|
||||
|
||||
return vec3(
|
||||
(maxfull - realfull) / (maxfull - minfull),
|
||||
(realfull-0.5) / ssize,
|
||||
(realfull+0.5) / ssize
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
void main() {
|
||||
float cheapsrgb = 2.1;
|
||||
float gamma = 3.0;
|
||||
vec3 xstuff = percent(sourceSize[0].x, targetSize[0].x, texCoord.x);
|
||||
vec3 ystuff = percent(sourceSize[0].y, targetSize[0].y, texCoord.y);
|
||||
|
||||
float xkeep = xstuff[0];
|
||||
float ykeep = ystuff[0];
|
||||
|
||||
// get points to interpolate across, in linear rgb
|
||||
vec4 a = getLQV(vpow(texture(source[0],vec2(xstuff[1],ystuff[1])), cheapsrgb).rgb);
|
||||
vec4 b = getLQV(vpow(texture(source[0],vec2(xstuff[2],ystuff[1])), cheapsrgb).rgb);
|
||||
vec4 c = getLQV(vpow(texture(source[0],vec2(xstuff[1],ystuff[2])), cheapsrgb).rgb);
|
||||
vec4 d = getLQV(vpow(texture(source[0],vec2(xstuff[2],ystuff[2])), cheapsrgb).rgb);
|
||||
|
||||
// use perceptual gamma for luminance component
|
||||
a.w = pow(a.w, 1/gamma);
|
||||
b.w = pow(b.w, 1/gamma);
|
||||
c.w = pow(c.w, 1/gamma);
|
||||
d.w = pow(d.w, 1/gamma);
|
||||
|
||||
// interpolate
|
||||
vec4 gammaLQVresult =
|
||||
NOT(xkeep)*NOT(ykeep)*a +
|
||||
YES(xkeep)*NOT(ykeep)*b +
|
||||
NOT(xkeep)*YES(ykeep)*c +
|
||||
YES(xkeep)*YES(ykeep)*d;
|
||||
|
||||
// change luminance gamma back to linear
|
||||
vec4 LQVresult = gammaLQVresult;
|
||||
LQVresult.w = pow(gammaLQVresult.w, gamma);
|
||||
|
||||
// convert back to srgb; lqv -> lrgb -> srgb
|
||||
vec4 c1 = vpow(vec4(fromLQV(LQVresult), 1), 1/cheapsrgb);
|
||||
|
||||
fragColor = c1;
|
||||
}
|
8
pack/Shaders/AANN.shader/manifest.bml
Normal file
|
@ -0,0 +1,8 @@
|
|||
input
|
||||
filter: nearest
|
||||
|
||||
program
|
||||
fragment: AANN.fs
|
||||
|
||||
output
|
||||
filter: nearest
|
297
pack/Shaders/CRT-Geom.shader/crt-geom.fs
Normal file
|
@ -0,0 +1,297 @@
|
|||
#version 150
|
||||
|
||||
/*
|
||||
CRT-interlaced
|
||||
|
||||
Copyright (C) 2010-2012 cgwg, Themaister and DOLLS
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 2 of the License, or (at your option)
|
||||
any later version.
|
||||
|
||||
(cgwg gave their consent to have the original version of this shader
|
||||
distributed under the GPL in this message:
|
||||
|
||||
http://board.byuu.org/viewtopic.php?p=26075#p26075
|
||||
|
||||
"Feel free to distribute my shaders under the GPL. After all, the
|
||||
barrel distortion code was taken from the Curvature shader, which is
|
||||
under the GPL."
|
||||
)
|
||||
This shader variant is pre-configured with screen curvature
|
||||
*/
|
||||
|
||||
//#define INTERLACED
|
||||
|
||||
uniform sampler2D source[];
|
||||
uniform vec4 sourceSize[];
|
||||
uniform vec4 targetSize;
|
||||
uniform int phase;
|
||||
|
||||
in Vertex {
|
||||
vec2 texCoord;
|
||||
};
|
||||
|
||||
out vec4 fragColor;
|
||||
|
||||
// Comment the next line to disable interpolation in linear gamma (and gain speed).
|
||||
#define LINEAR_PROCESSING
|
||||
|
||||
// Enable screen curvature.
|
||||
#define CURVATURE
|
||||
|
||||
// Enable 3x oversampling of the beam profile
|
||||
#define OVERSAMPLE
|
||||
|
||||
// Use the older, purely gaussian beam profile
|
||||
//#define USEGAUSSIAN
|
||||
|
||||
// vertex params //
|
||||
|
||||
// gamma of simulated CRT
|
||||
#define CRTgamma 2.4
|
||||
// gamma of display monitor (typically 2.2 is correct)
|
||||
#define monitorgamma 2.2
|
||||
// overscan (e.g. 1.02 for 2% overscan)
|
||||
#define overscan vec2(1.0 , 1.0)//(0.93 , 0.915)
|
||||
// aspect ratio
|
||||
#define aspect vec2(1.0, 0.75)
|
||||
// lengths are measured in units of (approximately) the width of the monitor
|
||||
// simulated distance from viewer to monitor
|
||||
#define d 2.0
|
||||
// radius of curvature
|
||||
#define R 2.0
|
||||
// tilt angle in radians
|
||||
// (behavior might be a bit wrong if both components are nonzero)
|
||||
#define angle vec2(0.0,-0.0)
|
||||
// size of curved corners
|
||||
#define cornersize 0.02
|
||||
// border smoothness parameter
|
||||
// decrease if borders are too aliased
|
||||
#define cornersmooth 80.0
|
||||
|
||||
#define sinangle sin(angle)
|
||||
#define cosangle cos(angle)
|
||||
#define stretch maxscale()
|
||||
#define ilfac vec2(1.0, floor(sourceSize[0].y / 200.0))
|
||||
#define one (ilfac / sourceSize[0].xy)
|
||||
#define mod_factor (texCoord.x * targetSize.x)
|
||||
|
||||
// END of vertex params //
|
||||
|
||||
// Macros.
|
||||
#define FIX(c) max(abs(c), 1e-5);
|
||||
#define PI 3.141592653589
|
||||
|
||||
#ifdef LINEAR_PROCESSING
|
||||
# define TEX2D(c) pow(texture(source[0], (c)), vec4(CRTgamma))
|
||||
#else
|
||||
# define TEX2D(c) texture(source[0], (c))
|
||||
#endif
|
||||
|
||||
#define FIX(c) max(abs(c), 1e-5);
|
||||
|
||||
float intersect(vec2 xy)
|
||||
{
|
||||
float A = dot(xy,xy)+d*d;
|
||||
float B = 2.0*(R*(dot(xy,sinangle)-d*cosangle.x*cosangle.y)-d*d);
|
||||
float C = d*d + 2.0*R*d*cosangle.x*cosangle.y;
|
||||
return (-B-sqrt(B*B-4.0*A*C))/(2.0*A);
|
||||
}
|
||||
|
||||
vec2 bkwtrans(vec2 xy)
|
||||
{
|
||||
float c = intersect(xy);
|
||||
vec2 point = vec2(c)*xy;
|
||||
point -= vec2(-R)*sinangle;
|
||||
point /= vec2(R);
|
||||
vec2 tang = sinangle/cosangle;
|
||||
vec2 poc = point/cosangle;
|
||||
float A = dot(tang,tang)+1.0;
|
||||
float B = -2.0*dot(poc,tang);
|
||||
float C = dot(poc,poc)-1.0;
|
||||
float a = (-B+sqrt(B*B-4.0*A*C))/(2.0*A);
|
||||
vec2 uv = (point-a*sinangle)/cosangle;
|
||||
float r = R*acos(a);
|
||||
return uv*r/sin(r/R);
|
||||
}
|
||||
|
||||
vec2 fwtrans(vec2 uv)
|
||||
{
|
||||
float r = FIX(sqrt(dot(uv,uv)));
|
||||
uv *= sin(r/R)/r;
|
||||
float x = 1.0-cos(r/R);
|
||||
float D = d/R + x*cosangle.x*cosangle.y+dot(uv,sinangle);
|
||||
return d*(uv*cosangle-x*sinangle)/D;
|
||||
}
|
||||
|
||||
vec3 maxscale()
|
||||
{
|
||||
vec2 c = bkwtrans(-R * sinangle / (1.0 + R/d*cosangle.x*cosangle.y));
|
||||
vec2 a = vec2(0.5,0.5)*aspect;
|
||||
vec2 lo = vec2(fwtrans(vec2(-a.x,c.y)).x,
|
||||
fwtrans(vec2(c.x,-a.y)).y)/aspect;
|
||||
vec2 hi = vec2(fwtrans(vec2(+a.x,c.y)).x,
|
||||
fwtrans(vec2(c.x,+a.y)).y)/aspect;
|
||||
return vec3((hi+lo)*aspect*0.5,max(hi.x-lo.x,hi.y-lo.y));
|
||||
}
|
||||
|
||||
vec2 transform(vec2 coord)
|
||||
{
|
||||
coord = (coord-vec2(0.5))*aspect*stretch.z+stretch.xy;
|
||||
return (bkwtrans(coord)/overscan/aspect+vec2(0.5));
|
||||
}
|
||||
|
||||
float corner(vec2 coord)
|
||||
{
|
||||
coord = (coord - vec2(0.5)) * overscan + vec2(0.5);
|
||||
coord = min(coord, vec2(1.0)-coord) * aspect;
|
||||
vec2 cdist = vec2(cornersize);
|
||||
coord = (cdist - min(coord,cdist));
|
||||
float dist = sqrt(dot(coord,coord));
|
||||
return clamp((cdist.x-dist)*cornersmooth,0.0, 1.0);
|
||||
}
|
||||
|
||||
// Calculate the influence of a scanline on the current pixel.
|
||||
//
|
||||
// 'distance' is the distance in texture coordinates from the current
|
||||
// pixel to the scanline in question.
|
||||
// 'color' is the colour of the scanline at the horizontal location of
|
||||
// the current pixel.
|
||||
vec4 scanlineWeights(float distance, vec4 color)
|
||||
{
|
||||
// "wid" controls the width of the scanline beam, for each RGB channel
|
||||
// The "weights" lines basically specify the formula that gives
|
||||
// you the profile of the beam, i.e. the intensity as
|
||||
// a function of distance from the vertical center of the
|
||||
// scanline. In this case, it is gaussian if width=2, and
|
||||
// becomes nongaussian for larger widths. Ideally this should
|
||||
// be normalized so that the integral across the beam is
|
||||
// independent of its width. That is, for a narrower beam
|
||||
// "weights" should have a higher peak at the center of the
|
||||
// scanline than for a wider beam.
|
||||
#ifdef USEGAUSSIAN
|
||||
vec4 wid = 0.3 + 0.1 * pow(color, vec4(3.0));
|
||||
vec4 weights = vec4(distance / wid);
|
||||
return 0.4 * exp(-weights * weights) / wid;
|
||||
#else
|
||||
vec4 wid = 2.0 + 2.0 * pow(color, vec4(4.0));
|
||||
vec4 weights = vec4(distance / 0.3);
|
||||
return 1.4 * exp(-pow(weights * inversesqrt(0.5 * wid), wid)) / (0.6 + 0.2 * wid);
|
||||
#endif
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
|
||||
// Here's a helpful diagram to keep in mind while trying to
|
||||
// understand the code:
|
||||
//
|
||||
// | | | | |
|
||||
// -------------------------------
|
||||
// | | | | |
|
||||
// | 01 | 11 | 21 | 31 | <-- current scanline
|
||||
// | | @ | | |
|
||||
// -------------------------------
|
||||
// | | | | |
|
||||
// | 02 | 12 | 22 | 32 | <-- next scanline
|
||||
// | | | | |
|
||||
// -------------------------------
|
||||
// | | | | |
|
||||
//
|
||||
// Each character-cell represents a pixel on the output
|
||||
// surface, "@" represents the current pixel (always somewhere
|
||||
// in the bottom half of the current scan-line, or the top-half
|
||||
// of the next scanline). The grid of lines represents the
|
||||
// edges of the texels of the underlying texture.
|
||||
|
||||
// Texture coordinates of the texel containing the active pixel.
|
||||
#ifdef CURVATURE
|
||||
vec2 xy = transform(texCoord);
|
||||
#else
|
||||
vec2 xy = texCoord;
|
||||
#endif
|
||||
float cval = corner(xy);
|
||||
|
||||
// Of all the pixels that are mapped onto the texel we are
|
||||
// currently rendering, which pixel are we currently rendering?
|
||||
#ifdef INTERLACED
|
||||
vec2 ilvec = vec2(0.0,ilfac.y > 1.5 ? mod(float(phase),2.0) : 0.0);
|
||||
#else
|
||||
vec2 ilvec = vec2(0.0,ilfac.y);
|
||||
#endif
|
||||
vec2 ratio_scale = (xy * sourceSize[0].xy - vec2(0.5) + ilvec)/ilfac;
|
||||
#ifdef OVERSAMPLE
|
||||
float filter_ = sourceSize[0].y / targetSize.y;
|
||||
#endif
|
||||
vec2 uv_ratio = fract(ratio_scale);
|
||||
|
||||
// Snap to the center of the underlying texel.
|
||||
xy = (floor(ratio_scale)*ilfac + vec2(0.5) - ilvec) / sourceSize[0].xy;
|
||||
|
||||
// Calculate Lanczos scaling coefficients describing the effect
|
||||
// of various neighbour texels in a scanline on the current
|
||||
// pixel.
|
||||
vec4 coeffs = PI * vec4(1.0 + uv_ratio.x, uv_ratio.x, 1.0 - uv_ratio.x, 2.0 - uv_ratio.x);
|
||||
|
||||
// Prevent division by zero.
|
||||
coeffs = FIX(coeffs);
|
||||
|
||||
// Lanczos2 kernel.
|
||||
coeffs = 2.0 * sin(coeffs) * sin(coeffs / 2.0) / (coeffs * coeffs);
|
||||
|
||||
// Normalize.
|
||||
coeffs /= dot(coeffs, vec4(1.0));
|
||||
|
||||
// Calculate the effective colour of the current and next
|
||||
// scanlines at the horizontal location of the current pixel,
|
||||
// using the Lanczos coefficients above.
|
||||
vec4 col = clamp(mat4(
|
||||
TEX2D(xy + vec2(-one.x, 0.0)),
|
||||
TEX2D(xy),
|
||||
TEX2D(xy + vec2(one.x, 0.0)),
|
||||
TEX2D(xy + vec2(2.0 * one.x, 0.0))) * coeffs,
|
||||
0.0, 1.0);
|
||||
vec4 col2 = clamp(mat4(
|
||||
TEX2D(xy + vec2(-one.x, one.y)),
|
||||
TEX2D(xy + vec2(0.0, one.y)),
|
||||
TEX2D(xy + one),
|
||||
TEX2D(xy + vec2(2.0 * one.x, one.y))) * coeffs,
|
||||
0.0, 1.0);
|
||||
|
||||
#ifndef LINEAR_PROCESSING
|
||||
col = pow(col , vec4(CRTgamma));
|
||||
col2 = pow(col2, vec4(CRTgamma));
|
||||
#endif
|
||||
|
||||
// Calculate the influence of the current and next scanlines on
|
||||
// the current pixel.
|
||||
vec4 weights = scanlineWeights(uv_ratio.y, col);
|
||||
vec4 weights2 = scanlineWeights(1.0 - uv_ratio.y, col2);
|
||||
#ifdef OVERSAMPLE
|
||||
uv_ratio.y =uv_ratio.y+1.0/3.0*filter_;
|
||||
weights = (weights+scanlineWeights(uv_ratio.y, col))/3.0;
|
||||
weights2=(weights2+scanlineWeights(abs(1.0-uv_ratio.y), col2))/3.0;
|
||||
uv_ratio.y =uv_ratio.y-2.0/3.0*filter_;
|
||||
weights=weights+scanlineWeights(abs(uv_ratio.y), col)/3.0;
|
||||
weights2=weights2+scanlineWeights(abs(1.0-uv_ratio.y), col2)/3.0;
|
||||
#endif
|
||||
vec3 mul_res = (col * weights + col2 * weights2).rgb * vec3(cval);
|
||||
|
||||
// dot-mask emulation:
|
||||
// Output pixels are alternately tinted green and magenta.
|
||||
vec3 dotMaskWeights = mix(
|
||||
vec3(1.0, 0.7, 1.0),
|
||||
vec3(0.7, 1.0, 0.7),
|
||||
floor(mod(mod_factor, 2.0))
|
||||
);
|
||||
|
||||
mul_res *= dotMaskWeights;
|
||||
|
||||
// Convert the image gamma for display on our output device.
|
||||
mul_res = pow(mul_res, vec3(1.0 / monitorgamma));
|
||||
|
||||
// Color the texel.
|
||||
fragColor = vec4(mul_res, 1.0);
|
||||
}
|
121
pack/Shaders/CRT-Geom.shader/crt-geom.vs
Normal file
|
@ -0,0 +1,121 @@
|
|||
#version 150
|
||||
|
||||
in vec4 position;
|
||||
in vec2 texCoord;
|
||||
in vec4 sourceSize[];
|
||||
in vec4 targetSize;
|
||||
|
||||
out Vertex {
|
||||
vec2 texCoord;
|
||||
} vertexOut;
|
||||
|
||||
float CRTgamma;
|
||||
float monitorgamma;
|
||||
vec2 overscan;
|
||||
vec2 aspect;
|
||||
float d;
|
||||
float R;
|
||||
float cornersize;
|
||||
float cornersmooth;
|
||||
|
||||
vec3 stretch;
|
||||
vec2 sinangle;
|
||||
vec2 cosangle;
|
||||
|
||||
vec2 one;
|
||||
float mod_factor;
|
||||
vec2 ilfac;
|
||||
|
||||
#define FIX(c) max(abs(c), 1e-5);
|
||||
|
||||
float intersect(vec2 xy)
|
||||
{
|
||||
float A = dot(xy,xy)+d*d;
|
||||
float B = 2.0*(R*(dot(xy,sinangle)-d*cosangle.x*cosangle.y)-d*d);
|
||||
float C = d*d + 2.0*R*d*cosangle.x*cosangle.y;
|
||||
return (-B-sqrt(B*B-4.0*A*C))/(2.0*A);
|
||||
}
|
||||
|
||||
vec2 bkwtrans(vec2 xy)
|
||||
{
|
||||
float c = intersect(xy);
|
||||
vec2 point = vec2(c)*xy;
|
||||
point -= vec2(-R)*sinangle;
|
||||
point /= vec2(R);
|
||||
vec2 tang = sinangle/cosangle;
|
||||
vec2 poc = point/cosangle;
|
||||
float A = dot(tang,tang)+1.0;
|
||||
float B = -2.0*dot(poc,tang);
|
||||
float C = dot(poc,poc)-1.0;
|
||||
float a = (-B+sqrt(B*B-4.0*A*C))/(2.0*A);
|
||||
vec2 uv = (point-a*sinangle)/cosangle;
|
||||
float r = R*acos(a);
|
||||
return uv*r/sin(r/R);
|
||||
}
|
||||
|
||||
vec2 fwtrans(vec2 uv)
|
||||
{
|
||||
float r = FIX(sqrt(dot(uv,uv)));
|
||||
uv *= sin(r/R)/r;
|
||||
float x = 1.0-cos(r/R);
|
||||
float D = d/R + x*cosangle.x*cosangle.y+dot(uv,sinangle);
|
||||
return d*(uv*cosangle-x*sinangle)/D;
|
||||
}
|
||||
|
||||
vec3 maxscale()
|
||||
{
|
||||
vec2 c = bkwtrans(-R * sinangle / (1.0 + R/d*cosangle.x*cosangle.y));
|
||||
vec2 a = vec2(0.5,0.5)*aspect;
|
||||
vec2 lo = vec2(fwtrans(vec2(-a.x,c.y)).x,
|
||||
fwtrans(vec2(c.x,-a.y)).y)/aspect;
|
||||
vec2 hi = vec2(fwtrans(vec2(+a.x,c.y)).x,
|
||||
fwtrans(vec2(c.x,+a.y)).y)/aspect;
|
||||
return vec3((hi+lo)*aspect*0.5,max(hi.x-lo.x,hi.y-lo.y));
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
|
||||
// START of parameters
|
||||
|
||||
// gamma of simulated CRT
|
||||
CRTgamma = 2.4;
|
||||
// gamma of display monitor (typically 2.2 is correct)
|
||||
monitorgamma = 2.2;
|
||||
// overscan (e.g. 1.02 for 2% overscan)
|
||||
overscan = vec2(0.99,0.99);
|
||||
// aspect ratio
|
||||
aspect = vec2(1.0, 0.75);
|
||||
// lengths are measured in units of (approximately) the width of the monitor
|
||||
// simulated distance from viewer to monitor
|
||||
d = 2.0;
|
||||
// radius of curvature
|
||||
R = 2.0;
|
||||
// tilt angle in radians
|
||||
// (behavior might be a bit wrong if both components are nonzero)
|
||||
const vec2 angle = vec2(0.0,-0.0);
|
||||
// size of curved corners
|
||||
cornersize = 0.03;
|
||||
// border smoothness parameter
|
||||
// decrease if borders are too aliased
|
||||
cornersmooth = 80.0;
|
||||
|
||||
// END of parameters
|
||||
|
||||
vertexOut.texCoord = texCoord.xy;
|
||||
gl_Position = position;
|
||||
|
||||
// Precalculate a bunch of useful values we'll need in the fragment
|
||||
// shader.
|
||||
sinangle = sin(angle);
|
||||
cosangle = cos(angle);
|
||||
stretch = maxscale();
|
||||
|
||||
ilfac = vec2(1.0,floor(sourceSize[0].y/200.0));
|
||||
|
||||
// The size of one texel, in texture-coordinates.
|
||||
one = ilfac / sourceSize[0].xy;
|
||||
|
||||
// Resulting X pixel-coordinate of the pixel we're drawing.
|
||||
mod_factor = texCoord.x * targetSize.x;
|
||||
}
|
21
pack/Shaders/CRT-Geom.shader/curvature.fs
Normal file
|
@ -0,0 +1,21 @@
|
|||
#version 150
|
||||
#define distortion 0.08
|
||||
|
||||
uniform sampler2D source[];
|
||||
uniform vec4 sourceSize[];
|
||||
|
||||
in Vertex {
|
||||
vec2 texCoord;
|
||||
};
|
||||
|
||||
out vec4 fragColor;
|
||||
|
||||
vec2 radialDistortion(vec2 coord) {
|
||||
vec2 cc = coord - vec2(0.5);
|
||||
float dist = dot(cc, cc) * distortion;
|
||||
return coord + cc * (1.0 - dist) * dist;
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
fragColor = texture(source[0], radialDistortion(texCoord));
|
||||
}
|
5
pack/Shaders/CRT-Geom.shader/manifest.bml
Normal file
|
@ -0,0 +1,5 @@
|
|||
program
|
||||
vertex: crt-geom.vs
|
||||
fragment: crt-geom.fs
|
||||
modulo: 2
|
||||
|
32
pack/Shaders/CRT-Glow.shader/blur_horiz.fs
Normal file
|
@ -0,0 +1,32 @@
|
|||
#version 150
|
||||
|
||||
uniform sampler2D source[];
|
||||
uniform vec4 sourceSize[];
|
||||
|
||||
in Vertex {
|
||||
vec2 vTexCoord;
|
||||
};
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
// Higher value, more centered glow.
|
||||
// Lower values might need more taps.
|
||||
#define GLOW_FALLOFF 0.35
|
||||
#define TAPS 4
|
||||
|
||||
#define kernel(x) exp(-GLOW_FALLOFF * (x) * (x))
|
||||
|
||||
void main() {
|
||||
vec3 col = vec3(0.0);
|
||||
float dx = 4.0 * sourceSize[0].z; // Mipmapped
|
||||
|
||||
float k_total = 0.0;
|
||||
for (int i = -TAPS; i <= TAPS; i++)
|
||||
{
|
||||
float k = kernel(i);
|
||||
k_total += k;
|
||||
col += k * texture(source[0], vTexCoord + vec2(float(i) * dx, 0.0)).rgb;
|
||||
}
|
||||
|
||||
FragColor = vec4(col / k_total, 1.0);
|
||||
}
|
16
pack/Shaders/CRT-Glow.shader/blur_horiz.vs
Normal file
|
@ -0,0 +1,16 @@
|
|||
#version 150
|
||||
|
||||
in vec4 position;
|
||||
in vec2 texCoord;
|
||||
|
||||
out Vertex {
|
||||
vec2 vTexCoord;
|
||||
};
|
||||
|
||||
uniform vec4 targetSize;
|
||||
uniform vec4 sourceSize[];
|
||||
|
||||
void main() {
|
||||
gl_Position = position;
|
||||
vTexCoord = texCoord;
|
||||
}
|
32
pack/Shaders/CRT-Glow.shader/blur_vert.fs
Normal file
|
@ -0,0 +1,32 @@
|
|||
#version 150
|
||||
|
||||
uniform sampler2D source[];
|
||||
uniform vec4 sourceSize[];
|
||||
|
||||
in Vertex {
|
||||
vec2 vTexCoord;
|
||||
};
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
// Higher value, more centered glow.
|
||||
// Lower values might need more taps.
|
||||
#define GLOW_FALLOFF 0.35
|
||||
#define TAPS 4
|
||||
|
||||
#define kernel(x) exp(-GLOW_FALLOFF * (x) * (x))
|
||||
|
||||
void main() {
|
||||
vec3 col = vec3(0.0);
|
||||
float dy = sourceSize[0].w;
|
||||
|
||||
float k_total = 0.0;
|
||||
for (int i = -TAPS; i <= TAPS; i++)
|
||||
{
|
||||
float k = kernel(i);
|
||||
k_total += k;
|
||||
col += k * texture(source[0], vTexCoord + vec2(0.0, float(i) * dy)).rgb;
|
||||
}
|
||||
|
||||
FragColor = vec4(col / k_total, 1.0);
|
||||
}
|
13
pack/Shaders/CRT-Glow.shader/blur_vert.vs
Normal file
|
@ -0,0 +1,13 @@
|
|||
#version 150
|
||||
|
||||
in vec4 position;
|
||||
in vec2 texCoord;
|
||||
|
||||
out Vertex {
|
||||
vec2 vTexCoord;
|
||||
};
|
||||
|
||||
void main() {
|
||||
gl_Position = position;
|
||||
vTexCoord = texCoord;
|
||||
}
|
33
pack/Shaders/CRT-Glow.shader/gauss_horiz.fs
Normal file
|
@ -0,0 +1,33 @@
|
|||
#version 150
|
||||
|
||||
#define INV_SQRT_2_PI 0.38 // Doesn't have to be accurate.
|
||||
|
||||
#define HORIZ_GAUSS_WIDTH 0.5
|
||||
|
||||
uniform sampler2D source[];
|
||||
uniform vec4 sourceSize[];
|
||||
|
||||
in Vertex {
|
||||
vec2 vTexCoord;
|
||||
float data_pix_no;
|
||||
float data_one;
|
||||
};
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
void main() {
|
||||
float texel = floor(data_pix_no);
|
||||
float phase = data_pix_no - texel;
|
||||
float base_phase = phase - 0.5;
|
||||
vec2 tex = vec2((texel + 0.5) * sourceSize[0].z, vTexCoord.y);
|
||||
|
||||
vec3 col = vec3(0.0);
|
||||
for (int i = -2; i <= 2; i++)
|
||||
{
|
||||
float phase = base_phase - float(i);
|
||||
float g = INV_SQRT_2_PI * exp(-0.5 * phase * phase / (HORIZ_GAUSS_WIDTH * HORIZ_GAUSS_WIDTH)) / HORIZ_GAUSS_WIDTH;
|
||||
col += texture(source[0], tex + vec2(float(i) * data_one, 0.0)).rgb * g;
|
||||
}
|
||||
|
||||
FragColor = vec4(col, 1.0);
|
||||
}
|
20
pack/Shaders/CRT-Glow.shader/gauss_horiz.vs
Normal file
|
@ -0,0 +1,20 @@
|
|||
#version 150
|
||||
|
||||
in vec4 position;
|
||||
in vec2 texCoord;
|
||||
|
||||
out Vertex {
|
||||
vec2 vTexCoord;
|
||||
float data_pix_no;
|
||||
float data_one;
|
||||
};
|
||||
|
||||
uniform vec4 sourceSize[];
|
||||
|
||||
void main() {
|
||||
gl_Position = position;
|
||||
vTexCoord = texCoord;
|
||||
|
||||
data_pix_no = vTexCoord.x * sourceSize[0].x;
|
||||
data_one = sourceSize[0].z;
|
||||
}
|
49
pack/Shaders/CRT-Glow.shader/gauss_vert.fs
Normal file
|
@ -0,0 +1,49 @@
|
|||
#version 150
|
||||
|
||||
#define BOOST 1.0
|
||||
#define CRT_GEOM_BEAM 1
|
||||
|
||||
uniform sampler2D source[];
|
||||
uniform vec4 sourceSize[];
|
||||
|
||||
in Vertex {
|
||||
vec2 vTexCoord;
|
||||
vec2 data_pix_no;
|
||||
float data_one;
|
||||
};
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
vec3 beam(vec3 color, float dist)
|
||||
{
|
||||
#if CRT_GEOM_BEAM
|
||||
vec3 wid = 2.0 + 2.0 * pow(color, vec3(4.0));
|
||||
vec3 weights = vec3(abs(dist) * 3.333333333);
|
||||
|
||||
return 2.0 * color * exp(-pow(weights * inversesqrt(0.5 * wid), wid)) / (0.6 + 0.2 * wid);
|
||||
#else
|
||||
float reciprocal_width = 4.0;
|
||||
vec3 x = dist * reciprocal_width;
|
||||
|
||||
return 2.0 * color * exp(-0.5 * x * x) * reciprocal_width;
|
||||
#endif
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 texel = floor(data_pix_no);
|
||||
float phase = data_pix_no.y - texel.y;
|
||||
vec2 tex = vec2(texel + 0.5) * sourceSize[0].zw;
|
||||
|
||||
vec3 top = texture(source[0], tex + vec2(0.0, 0 * data_one)).rgb;
|
||||
vec3 bottom = texture(source[0], tex + vec2(0.0, 1 * data_one)).rgb;
|
||||
|
||||
float dist0 = phase;
|
||||
float dist1 = 1.0 - phase;
|
||||
|
||||
vec3 scanline = vec3(0.0);
|
||||
|
||||
scanline += beam(top, dist0);
|
||||
scanline += beam(bottom, dist1);
|
||||
|
||||
FragColor = vec4(BOOST * scanline * 0.869565217391304, 1.0);
|
||||
}
|
20
pack/Shaders/CRT-Glow.shader/gauss_vert.vs
Normal file
|
@ -0,0 +1,20 @@
|
|||
#version 150
|
||||
|
||||
in vec4 position;
|
||||
in vec2 texCoord;
|
||||
|
||||
out Vertex {
|
||||
vec2 vTexCoord;
|
||||
vec2 data_pix_no;
|
||||
float data_one;
|
||||
};
|
||||
|
||||
uniform vec4 sourceSize[];
|
||||
|
||||
void main() {
|
||||
gl_Position = position;
|
||||
vTexCoord = texCoord;
|
||||
|
||||
data_pix_no = vTexCoord.xy * sourceSize[0].xy - vec2(0.0, 0.5);
|
||||
data_one = sourceSize[0].w;
|
||||
}
|
13
pack/Shaders/CRT-Glow.shader/lanczos_horiz.fs
Normal file
|
@ -0,0 +1,13 @@
|
|||
#version 150
|
||||
|
||||
uniform sampler2D source[];
|
||||
|
||||
in Vertex {
|
||||
vec2 vTexCoord;
|
||||
};
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
void main() {
|
||||
FragColor = texture(source[0], vTexCoord);
|
||||
}
|
15
pack/Shaders/CRT-Glow.shader/lanczos_horiz.vs
Normal file
|
@ -0,0 +1,15 @@
|
|||
#version 150
|
||||
|
||||
in vec4 position;
|
||||
in vec2 texCoord;
|
||||
|
||||
out Vertex {
|
||||
vec2 vTexCoord;
|
||||
};
|
||||
|
||||
uniform vec4 sourceSize[];
|
||||
|
||||
void main() {
|
||||
gl_Position = position;
|
||||
vTexCoord = texCoord;
|
||||
}
|
15
pack/Shaders/CRT-Glow.shader/linearize.fs
Normal file
|
@ -0,0 +1,15 @@
|
|||
#version 150
|
||||
|
||||
#define INPUT_GAMMA 2.2
|
||||
|
||||
uniform sampler2D source[];
|
||||
|
||||
in Vertex {
|
||||
vec2 vTexCoord;
|
||||
};
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
void main() {
|
||||
FragColor = pow(texture(source[0], vTexCoord), vec4(INPUT_GAMMA));
|
||||
}
|
15
pack/Shaders/CRT-Glow.shader/linearize.vs
Normal file
|
@ -0,0 +1,15 @@
|
|||
#version 150
|
||||
|
||||
in vec4 position;
|
||||
in vec2 texCoord;
|
||||
|
||||
out Vertex {
|
||||
vec2 vTexCoord;
|
||||
};
|
||||
|
||||
uniform vec4 sourceSize[];
|
||||
|
||||
void main() {
|
||||
gl_Position = position;
|
||||
vTexCoord = texCoord;
|
||||
}
|
54
pack/Shaders/CRT-Glow.shader/manifest.bml
Normal file
|
@ -0,0 +1,54 @@
|
|||
input
|
||||
filter: nearest
|
||||
|
||||
program
|
||||
format: srgb8
|
||||
filter: nearest
|
||||
vertex: linearize.vs
|
||||
fragment: linearize.fs
|
||||
|
||||
program
|
||||
format: srgb8
|
||||
filter: nearest
|
||||
height: 25%
|
||||
width: 100%
|
||||
vertex: gauss_horiz.vs
|
||||
fragment: gauss_horiz.fs
|
||||
|
||||
program
|
||||
format: srgb8
|
||||
filter: nearest
|
||||
vertex: gauss_vert.vs
|
||||
fragment: gauss_vert.fs
|
||||
|
||||
program
|
||||
format: srgb8
|
||||
filter: nearest
|
||||
height: 100%
|
||||
width: 100%
|
||||
vertex: threshold.vs
|
||||
fragment: threshold.fs
|
||||
|
||||
program
|
||||
format: srgb8
|
||||
filter: linear
|
||||
height: 25%
|
||||
width: 25%
|
||||
vertex: blur_horiz.vs
|
||||
fragment: blur_horiz.fs
|
||||
|
||||
program
|
||||
format: srgb8
|
||||
filter: linear
|
||||
height: 100%
|
||||
width: 100%
|
||||
vertex: blur_vert.vs
|
||||
fragment: blur_vert.fs
|
||||
|
||||
program
|
||||
filter: linear
|
||||
vertex: resolve.vs
|
||||
fragment: resolve.fs
|
||||
|
||||
output
|
||||
filter: linear
|
28
pack/Shaders/CRT-Glow.shader/resolve.fs
Normal file
|
@ -0,0 +1,28 @@
|
|||
#version 150
|
||||
|
||||
#define BLOOM_STRENGTH 0.25
|
||||
#define OUTPUT_GAMMA 2.2
|
||||
|
||||
uniform sampler2D source[];
|
||||
|
||||
in Vertex {
|
||||
vec2 vTexCoord;
|
||||
};
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
// For debugging
|
||||
#define BLOOM_ONLY 0
|
||||
|
||||
#define CRT_PASS source[3]
|
||||
|
||||
void main() {
|
||||
#if BLOOM_ONLY
|
||||
vec3 source = BLOOM_STRENGTH * texture(source[0], vTexCoord).rgb;
|
||||
#else
|
||||
vec3 source_ = 1.15 * texture(CRT_PASS, vTexCoord).rgb;
|
||||
vec3 bloom = texture(source[0], vTexCoord).rgb;
|
||||
source_ += BLOOM_STRENGTH * bloom;
|
||||
#endif
|
||||
FragColor = vec4(pow(clamp(source_, 0.0, 1.0), vec3(1.0 / OUTPUT_GAMMA)), 1.0);
|
||||
}
|
13
pack/Shaders/CRT-Glow.shader/resolve.vs
Normal file
|
@ -0,0 +1,13 @@
|
|||
#version 150
|
||||
|
||||
in vec4 position;
|
||||
in vec2 texCoord;
|
||||
|
||||
out Vertex {
|
||||
vec2 vTexCoord;
|
||||
};
|
||||
|
||||
void main() {
|
||||
gl_Position = position;
|
||||
vTexCoord = texCoord;
|
||||
}
|
19
pack/Shaders/CRT-Glow.shader/threshold.fs
Normal file
|
@ -0,0 +1,19 @@
|
|||
#version 150
|
||||
|
||||
#define GLOW_WHITEPOINT 1.0
|
||||
#define GLOW_ROLLOFF 3.0
|
||||
|
||||
uniform sampler2D source[];
|
||||
|
||||
in Vertex {
|
||||
vec2 vTexCoord;
|
||||
};
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
void main() {
|
||||
vec3 color = 1.15 * texture(source[0], vTexCoord).rgb;
|
||||
vec3 factor = clamp(color / GLOW_WHITEPOINT, 0.0, 1.0);
|
||||
|
||||
FragColor = vec4(pow(factor, vec3(GLOW_ROLLOFF)), 1.0);
|
||||
}
|
13
pack/Shaders/CRT-Glow.shader/threshold.vs
Normal file
|
@ -0,0 +1,13 @@
|
|||
#version 150
|
||||
|
||||
in vec4 position;
|
||||
in vec2 texCoord;
|
||||
|
||||
out Vertex {
|
||||
vec2 vTexCoord;
|
||||
};
|
||||
|
||||
void main() {
|
||||
gl_Position = position;
|
||||
vTexCoord = texCoord;
|
||||
}
|
306
pack/Shaders/CRT-Lottes.shader/bloompass.fs
Normal file
|
@ -0,0 +1,306 @@
|
|||
#version 150
|
||||
|
||||
// PUBLIC DOMAIN CRT STYLED SCAN-LINE SHADER
|
||||
//
|
||||
// by Timothy Lottes
|
||||
//
|
||||
// This is more along the style of a really good CGA arcade monitor.
|
||||
// With RGB inputs instead of NTSC.
|
||||
// The shadow mask example has the mask rotated 90 degrees for less chromatic aberration.
|
||||
//
|
||||
// Left it unoptimized to show the theory behind the algorithm.
|
||||
//
|
||||
// It is an example what I personally would want as a display option for pixel art games.
|
||||
// Please take and use, change, or whatever.
|
||||
|
||||
#define hardScan -8.0
|
||||
#define hardPix -3.0
|
||||
#define warpX 0.031
|
||||
#define warpY 0.041
|
||||
#define maskDark 0.5
|
||||
#define maskLight 1.5
|
||||
#define scaleInLinearGamma 1.0
|
||||
#define shadowMask 3.0
|
||||
#define brightBoost 1.0
|
||||
#define hardBloomPix -1.5
|
||||
#define hardBloomScan -2.0
|
||||
#define bloomAmount 0.4
|
||||
#define shape 2.0
|
||||
|
||||
uniform sampler2D source[];
|
||||
uniform vec4 sourceSize[];
|
||||
|
||||
in Vertex {
|
||||
vec2 vTexCoord;
|
||||
};
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
//Uncomment to reduce instructions with simpler linearization
|
||||
//(fixes HD3000 Sandy Bridge IGP)
|
||||
//#define SIMPLE_LINEAR_GAMMA
|
||||
#define DO_BLOOM 1
|
||||
|
||||
// ------------- //
|
||||
|
||||
// sRGB to Linear.
|
||||
// Assuming using sRGB typed textures this should not be needed.
|
||||
#ifdef SIMPLE_LINEAR_GAMMA
|
||||
float ToLinear1(float c)
|
||||
{
|
||||
return c;
|
||||
}
|
||||
vec3 ToLinear(vec3 c)
|
||||
{
|
||||
return c;
|
||||
}
|
||||
vec3 ToSrgb(vec3 c)
|
||||
{
|
||||
return pow(c, vec3(1.0 / 2.2));
|
||||
}
|
||||
#else
|
||||
float ToLinear1(float c)
|
||||
{
|
||||
if (scaleInLinearGamma == 0)
|
||||
return c;
|
||||
|
||||
return(c<=0.04045) ? c/12.92 : pow((c + 0.055)/1.055, 2.4);
|
||||
}
|
||||
|
||||
vec3 ToLinear(vec3 c)
|
||||
{
|
||||
if (scaleInLinearGamma==0)
|
||||
return c;
|
||||
|
||||
return vec3(ToLinear1(c.r), ToLinear1(c.g), ToLinear1(c.b));
|
||||
}
|
||||
|
||||
// Linear to sRGB.
|
||||
// Assuming using sRGB typed textures this should not be needed.
|
||||
float ToSrgb1(float c)
|
||||
{
|
||||
if (scaleInLinearGamma == 0)
|
||||
return c;
|
||||
|
||||
return(c<0.0031308 ? c*12.92 : 1.055*pow(c, 0.41666) - 0.055);
|
||||
}
|
||||
|
||||
vec3 ToSrgb(vec3 c)
|
||||
{
|
||||
if (scaleInLinearGamma == 0)
|
||||
return c;
|
||||
|
||||
return vec3(ToSrgb1(c.r), ToSrgb1(c.g), ToSrgb1(c.b));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// Nearest emulated sample given floating point position and texel offset.
|
||||
// Also zero's off screen.
|
||||
vec3 Fetch(vec2 pos,vec2 off){
|
||||
pos=(floor(pos*sourceSize[0].xy+off)+vec2(0.5,0.5))/sourceSize[0].xy;
|
||||
#ifdef SIMPLE_LINEAR_GAMMA
|
||||
return ToLinear(brightBoost * pow(texture(source[0],pos.xy).rgb, vec3(2.2)));
|
||||
#else
|
||||
return ToLinear(brightBoost * texture(source[0],pos.xy).rgb);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Distance in emulated pixels to nearest texel.
|
||||
vec2 Dist(vec2 pos)
|
||||
{
|
||||
pos = pos*sourceSize[0].xy;
|
||||
|
||||
return -((pos - floor(pos)) - vec2(0.5));
|
||||
}
|
||||
|
||||
// 1D Gaussian.
|
||||
float Gaus(float pos, float scale)
|
||||
{
|
||||
return exp2(scale*pow(abs(pos), shape));
|
||||
}
|
||||
|
||||
// 3-tap Gaussian filter along horz line.
|
||||
vec3 Horz3(vec2 pos, float off)
|
||||
{
|
||||
vec3 b = Fetch(pos, vec2(-1.0, off));
|
||||
vec3 c = Fetch(pos, vec2( 0.0, off));
|
||||
vec3 d = Fetch(pos, vec2( 1.0, off));
|
||||
float dst = Dist(pos).x;
|
||||
|
||||
// Convert distance to weight.
|
||||
float scale = hardPix;
|
||||
float wb = Gaus(dst-1.0,scale);
|
||||
float wc = Gaus(dst+0.0,scale);
|
||||
float wd = Gaus(dst+1.0,scale);
|
||||
|
||||
// Return filtered sample.
|
||||
return (b*wb+c*wc+d*wd)/(wb+wc+wd);
|
||||
}
|
||||
|
||||
// 5-tap Gaussian filter along horz line.
|
||||
vec3 Horz5(vec2 pos,float off){
|
||||
vec3 a = Fetch(pos,vec2(-2.0, off));
|
||||
vec3 b = Fetch(pos,vec2(-1.0, off));
|
||||
vec3 c = Fetch(pos,vec2( 0.0, off));
|
||||
vec3 d = Fetch(pos,vec2( 1.0, off));
|
||||
vec3 e = Fetch(pos,vec2( 2.0, off));
|
||||
|
||||
float dst = Dist(pos).x;
|
||||
// Convert distance to weight.
|
||||
float scale = hardPix;
|
||||
float wa = Gaus(dst - 2.0, scale);
|
||||
float wb = Gaus(dst - 1.0, scale);
|
||||
float wc = Gaus(dst + 0.0, scale);
|
||||
float wd = Gaus(dst + 1.0, scale);
|
||||
float we = Gaus(dst + 2.0, scale);
|
||||
|
||||
// Return filtered sample.
|
||||
return (a*wa+b*wb+c*wc+d*wd+e*we)/(wa+wb+wc+wd+we);
|
||||
}
|
||||
|
||||
// 7-tap Gaussian filter along horz line.
|
||||
vec3 Horz7(vec2 pos,float off)
|
||||
{
|
||||
vec3 a = Fetch(pos, vec2(-3.0, off));
|
||||
vec3 b = Fetch(pos, vec2(-2.0, off));
|
||||
vec3 c = Fetch(pos, vec2(-1.0, off));
|
||||
vec3 d = Fetch(pos, vec2( 0.0, off));
|
||||
vec3 e = Fetch(pos, vec2( 1.0, off));
|
||||
vec3 f = Fetch(pos, vec2( 2.0, off));
|
||||
vec3 g = Fetch(pos, vec2( 3.0, off));
|
||||
|
||||
float dst = Dist(pos).x;
|
||||
// Convert distance to weight.
|
||||
float scale = hardBloomPix;
|
||||
float wa = Gaus(dst - 3.0, scale);
|
||||
float wb = Gaus(dst - 2.0, scale);
|
||||
float wc = Gaus(dst - 1.0, scale);
|
||||
float wd = Gaus(dst + 0.0, scale);
|
||||
float we = Gaus(dst + 1.0, scale);
|
||||
float wf = Gaus(dst + 2.0, scale);
|
||||
float wg = Gaus(dst + 3.0, scale);
|
||||
|
||||
// Return filtered sample.
|
||||
return (a*wa+b*wb+c*wc+d*wd+e*we+f*wf+g*wg)/(wa+wb+wc+wd+we+wf+wg);
|
||||
}
|
||||
|
||||
// Return scanline weight.
|
||||
float Scan(vec2 pos, float off)
|
||||
{
|
||||
float dst = Dist(pos).y;
|
||||
|
||||
return Gaus(dst + off, hardScan);
|
||||
}
|
||||
|
||||
// Return scanline weight for bloom.
|
||||
float BloomScan(vec2 pos, float off)
|
||||
{
|
||||
float dst = Dist(pos).y;
|
||||
|
||||
return Gaus(dst + off, hardBloomScan);
|
||||
}
|
||||
|
||||
// Allow nearest three lines to effect pixel.
|
||||
vec3 Tri(vec2 pos)
|
||||
{
|
||||
vec3 a = Horz3(pos,-1.0);
|
||||
vec3 b = Horz5(pos, 0.0);
|
||||
vec3 c = Horz3(pos, 1.0);
|
||||
|
||||
float wa = Scan(pos,-1.0);
|
||||
float wb = Scan(pos, 0.0);
|
||||
float wc = Scan(pos, 1.0);
|
||||
|
||||
return a*wa + b*wb + c*wc;
|
||||
}
|
||||
|
||||
// Small bloom.
|
||||
vec3 Bloom(vec2 pos)
|
||||
{
|
||||
vec3 a = Horz5(pos,-2.0);
|
||||
vec3 b = Horz7(pos,-1.0);
|
||||
vec3 c = Horz7(pos, 0.0);
|
||||
vec3 d = Horz7(pos, 1.0);
|
||||
vec3 e = Horz5(pos, 2.0);
|
||||
|
||||
float wa = BloomScan(pos,-2.0);
|
||||
float wb = BloomScan(pos,-1.0);
|
||||
float wc = BloomScan(pos, 0.0);
|
||||
float wd = BloomScan(pos, 1.0);
|
||||
float we = BloomScan(pos, 2.0);
|
||||
|
||||
return a*wa+b*wb+c*wc+d*wd+e*we;
|
||||
}
|
||||
|
||||
// Distortion of scanlines, and end of screen alpha.
|
||||
vec2 Warp(vec2 pos)
|
||||
{
|
||||
pos = pos*2.0-1.0;
|
||||
pos *= vec2(1.0 + (pos.y*pos.y)*warpX, 1.0 + (pos.x*pos.x)*warpY);
|
||||
|
||||
return pos*0.5 + 0.5;
|
||||
}
|
||||
|
||||
// Shadow mask.
|
||||
vec3 Mask(vec2 pos)
|
||||
{
|
||||
vec3 mask = vec3(maskDark, maskDark, maskDark);
|
||||
|
||||
// Very compressed TV style shadow mask.
|
||||
if (shadowMask == 1.0)
|
||||
{
|
||||
float line = maskLight;
|
||||
float odd = 0.0;
|
||||
|
||||
if (fract(pos.x*0.166666666) < 0.5) odd = 1.0;
|
||||
if (fract((pos.y + odd) * 0.5) < 0.5) line = maskDark;
|
||||
|
||||
pos.x = fract(pos.x*0.333333333);
|
||||
|
||||
if (pos.x < 0.333) mask.r = maskLight;
|
||||
else if (pos.x < 0.666) mask.g = maskLight;
|
||||
else mask.b = maskLight;
|
||||
mask*=line;
|
||||
}
|
||||
|
||||
// Aperture-grille.
|
||||
else if (shadowMask == 2.0)
|
||||
{
|
||||
pos.x = fract(pos.x*0.333333333);
|
||||
|
||||
if (pos.x < 0.333) mask.r = maskLight;
|
||||
else if (pos.x < 0.666) mask.g = maskLight;
|
||||
else mask.b = maskLight;
|
||||
}
|
||||
|
||||
// Stretched VGA style shadow mask (same as prior shaders).
|
||||
else if (shadowMask == 3.0)
|
||||
{
|
||||
pos.x += pos.y*3.0;
|
||||
pos.x = fract(pos.x*0.166666666);
|
||||
|
||||
if (pos.x < 0.333) mask.r = maskLight;
|
||||
else if (pos.x < 0.666) mask.g = maskLight;
|
||||
else mask.b = maskLight;
|
||||
}
|
||||
|
||||
// VGA style shadow mask.
|
||||
else if (shadowMask == 4.0)
|
||||
{
|
||||
pos.xy = floor(pos.xy*vec2(1.0, 0.5));
|
||||
pos.x += pos.y*3.0;
|
||||
pos.x = fract(pos.x*0.166666666);
|
||||
|
||||
if (pos.x < 0.333) mask.r = maskLight;
|
||||
else if (pos.x < 0.666) mask.g = maskLight;
|
||||
else mask.b = maskLight;
|
||||
}
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
void main() {
|
||||
FragColor = vec4(Bloom(vTexCoord)*bloomAmount, 1.0);
|
||||
}
|
15
pack/Shaders/CRT-Lottes.shader/bloompass.vs
Normal file
|
@ -0,0 +1,15 @@
|
|||
#version 150
|
||||
|
||||
in vec4 position;
|
||||
in vec2 texCoord;
|
||||
|
||||
out Vertex {
|
||||
vec2 vTexCoord;
|
||||
};
|
||||
|
||||
uniform vec4 sourceSize[];
|
||||
|
||||
void main() {
|
||||
gl_Position = position;
|
||||
vTexCoord = texCoord;
|
||||
}
|
18
pack/Shaders/CRT-Lottes.shader/manifest.bml
Normal file
|
@ -0,0 +1,18 @@
|
|||
input
|
||||
filter: nearest
|
||||
|
||||
program
|
||||
filter: nearest
|
||||
format: srgb8
|
||||
height: 100%
|
||||
width: 100%
|
||||
vertex: bloompass.vs
|
||||
fragment: bloompass.fs
|
||||
|
||||
program
|
||||
filter: nearest
|
||||
vertex: scanpass.vs
|
||||
fragment: scanpass.fs
|
||||
|
||||
output
|
||||
filter: linear
|
317
pack/Shaders/CRT-Lottes.shader/scanpass.fs
Normal file
|
@ -0,0 +1,317 @@
|
|||
#version 150
|
||||
|
||||
// PUBLIC DOMAIN CRT STYLED SCAN-LINE SHADER
|
||||
//
|
||||
// by Timothy Lottes
|
||||
//
|
||||
// This is more along the style of a really good CGA arcade monitor.
|
||||
// With RGB inputs instead of NTSC.
|
||||
// The shadow mask example has the mask rotated 90 degrees for less chromatic aberration.
|
||||
//
|
||||
// Left it unoptimized to show the theory behind the algorithm.
|
||||
//
|
||||
// It is an example what I personally would want as a display option for pixel art games.
|
||||
// Please take and use, change, or whatever.
|
||||
|
||||
#define hardScan -8.0
|
||||
#define hardPix -3.0
|
||||
#define warpX 0.031
|
||||
#define warpY 0.041
|
||||
#define maskDark 0.5
|
||||
#define maskLight 1.5
|
||||
#define scaleInLinearGamma 1.0
|
||||
#define shadowMask 3.0
|
||||
#define brightBoost 1.0
|
||||
#define hardBloomPix -1.5
|
||||
#define hardBloomScan -2.0
|
||||
#define bloomAmount 0.4
|
||||
#define shape 2.0
|
||||
|
||||
uniform sampler2D source[];
|
||||
uniform vec4 sourceSize[];
|
||||
uniform vec4 outputSize;
|
||||
|
||||
in Vertex {
|
||||
vec2 vTexCoord;
|
||||
};
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
//Uncomment to reduce instructions with simpler linearization
|
||||
//(fixes HD3000 Sandy Bridge IGP)
|
||||
//#define SIMPLE_LINEAR_GAMMA
|
||||
#define DO_BLOOM 1
|
||||
|
||||
// ------------- //
|
||||
|
||||
// sRGB to Linear.
|
||||
// Assuming using sRGB typed textures this should not be needed.
|
||||
#ifdef SIMPLE_LINEAR_GAMMA
|
||||
float ToLinear1(float c)
|
||||
{
|
||||
return c;
|
||||
}
|
||||
vec3 ToLinear(vec3 c)
|
||||
{
|
||||
return c;
|
||||
}
|
||||
vec3 ToSrgb(vec3 c)
|
||||
{
|
||||
return pow(c, vec3(1.0 / 2.2));
|
||||
}
|
||||
#else
|
||||
float ToLinear1(float c)
|
||||
{
|
||||
if (scaleInLinearGamma == 0)
|
||||
return c;
|
||||
|
||||
return(c<=0.04045) ? c/12.92 : pow((c + 0.055)/1.055, 2.4);
|
||||
}
|
||||
|
||||
vec3 ToLinear(vec3 c)
|
||||
{
|
||||
if (scaleInLinearGamma==0)
|
||||
return c;
|
||||
|
||||
return vec3(ToLinear1(c.r), ToLinear1(c.g), ToLinear1(c.b));
|
||||
}
|
||||
|
||||
// Linear to sRGB.
|
||||
// Assuming using sRGB typed textures this should not be needed.
|
||||
float ToSrgb1(float c)
|
||||
{
|
||||
if (scaleInLinearGamma == 0)
|
||||
return c;
|
||||
|
||||
return(c<0.0031308 ? c*12.92 : 1.055*pow(c, 0.41666) - 0.055);
|
||||
}
|
||||
|
||||
vec3 ToSrgb(vec3 c)
|
||||
{
|
||||
if (scaleInLinearGamma == 0)
|
||||
return c;
|
||||
|
||||
return vec3(ToSrgb1(c.r), ToSrgb1(c.g), ToSrgb1(c.b));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// Nearest emulated sample given floating point position and texel offset.
|
||||
// Also zero's off screen.
|
||||
vec3 Fetch(vec2 pos,vec2 off){
|
||||
pos=(floor(pos*sourceSize[0].xy+off)+vec2(0.5,0.5))/sourceSize[0].xy;
|
||||
#ifdef SIMPLE_LINEAR_GAMMA
|
||||
return ToLinear(brightBoost * pow(texture(source[1],pos.xy).rgb, vec3(2.2)));
|
||||
#else
|
||||
return ToLinear(brightBoost * texture(source[1],pos.xy).rgb);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Distance in emulated pixels to nearest texel.
|
||||
vec2 Dist(vec2 pos)
|
||||
{
|
||||
pos = pos*sourceSize[0].xy;
|
||||
|
||||
return -((pos - floor(pos)) - vec2(0.5));
|
||||
}
|
||||
|
||||
// 1D Gaussian.
|
||||
float Gaus(float pos, float scale)
|
||||
{
|
||||
return exp2(scale*pow(abs(pos), shape));
|
||||
}
|
||||
|
||||
// 3-tap Gaussian filter along horz line.
|
||||
vec3 Horz3(vec2 pos, float off)
|
||||
{
|
||||
vec3 b = Fetch(pos, vec2(-1.0, off));
|
||||
vec3 c = Fetch(pos, vec2( 0.0, off));
|
||||
vec3 d = Fetch(pos, vec2( 1.0, off));
|
||||
float dst = Dist(pos).x;
|
||||
|
||||
// Convert distance to weight.
|
||||
float scale = hardPix;
|
||||
float wb = Gaus(dst-1.0,scale);
|
||||
float wc = Gaus(dst+0.0,scale);
|
||||
float wd = Gaus(dst+1.0,scale);
|
||||
|
||||
// Return filtered sample.
|
||||
return (b*wb+c*wc+d*wd)/(wb+wc+wd);
|
||||
}
|
||||
|
||||
// 5-tap Gaussian filter along horz line.
|
||||
vec3 Horz5(vec2 pos,float off){
|
||||
vec3 a = Fetch(pos,vec2(-2.0, off));
|
||||
vec3 b = Fetch(pos,vec2(-1.0, off));
|
||||
vec3 c = Fetch(pos,vec2( 0.0, off));
|
||||
vec3 d = Fetch(pos,vec2( 1.0, off));
|
||||
vec3 e = Fetch(pos,vec2( 2.0, off));
|
||||
|
||||
float dst = Dist(pos).x;
|
||||
// Convert distance to weight.
|
||||
float scale = hardPix;
|
||||
float wa = Gaus(dst - 2.0, scale);
|
||||
float wb = Gaus(dst - 1.0, scale);
|
||||
float wc = Gaus(dst + 0.0, scale);
|
||||
float wd = Gaus(dst + 1.0, scale);
|
||||
float we = Gaus(dst + 2.0, scale);
|
||||
|
||||
// Return filtered sample.
|
||||
return (a*wa+b*wb+c*wc+d*wd+e*we)/(wa+wb+wc+wd+we);
|
||||
}
|
||||
|
||||
// 7-tap Gaussian filter along horz line.
|
||||
vec3 Horz7(vec2 pos,float off)
|
||||
{
|
||||
vec3 a = Fetch(pos, vec2(-3.0, off));
|
||||
vec3 b = Fetch(pos, vec2(-2.0, off));
|
||||
vec3 c = Fetch(pos, vec2(-1.0, off));
|
||||
vec3 d = Fetch(pos, vec2( 0.0, off));
|
||||
vec3 e = Fetch(pos, vec2( 1.0, off));
|
||||
vec3 f = Fetch(pos, vec2( 2.0, off));
|
||||
vec3 g = Fetch(pos, vec2( 3.0, off));
|
||||
|
||||
float dst = Dist(pos).x;
|
||||
// Convert distance to weight.
|
||||
float scale = hardBloomPix;
|
||||
float wa = Gaus(dst - 3.0, scale);
|
||||
float wb = Gaus(dst - 2.0, scale);
|
||||
float wc = Gaus(dst - 1.0, scale);
|
||||
float wd = Gaus(dst + 0.0, scale);
|
||||
float we = Gaus(dst + 1.0, scale);
|
||||
float wf = Gaus(dst + 2.0, scale);
|
||||
float wg = Gaus(dst + 3.0, scale);
|
||||
|
||||
// Return filtered sample.
|
||||
return (a*wa+b*wb+c*wc+d*wd+e*we+f*wf+g*wg)/(wa+wb+wc+wd+we+wf+wg);
|
||||
}
|
||||
|
||||
// Return scanline weight.
|
||||
float Scan(vec2 pos, float off)
|
||||
{
|
||||
float dst = Dist(pos).y;
|
||||
|
||||
return Gaus(dst + off, hardScan);
|
||||
}
|
||||
|
||||
// Return scanline weight for bloom.
|
||||
float BloomScan(vec2 pos, float off)
|
||||
{
|
||||
float dst = Dist(pos).y;
|
||||
|
||||
return Gaus(dst + off, hardBloomScan);
|
||||
}
|
||||
|
||||
// Allow nearest three lines to effect pixel.
|
||||
vec3 Tri(vec2 pos)
|
||||
{
|
||||
vec3 a = Horz3(pos,-1.0);
|
||||
vec3 b = Horz5(pos, 0.0);
|
||||
vec3 c = Horz3(pos, 1.0);
|
||||
|
||||
float wa = Scan(pos,-1.0);
|
||||
float wb = Scan(pos, 0.0);
|
||||
float wc = Scan(pos, 1.0);
|
||||
|
||||
return a*wa + b*wb + c*wc;
|
||||
}
|
||||
|
||||
// Small bloom.
|
||||
vec3 Bloom(vec2 pos)
|
||||
{
|
||||
vec3 a = Horz5(pos,-2.0);
|
||||
vec3 b = Horz7(pos,-1.0);
|
||||
vec3 c = Horz7(pos, 0.0);
|
||||
vec3 d = Horz7(pos, 1.0);
|
||||
vec3 e = Horz5(pos, 2.0);
|
||||
|
||||
float wa = BloomScan(pos,-2.0);
|
||||
float wb = BloomScan(pos,-1.0);
|
||||
float wc = BloomScan(pos, 0.0);
|
||||
float wd = BloomScan(pos, 1.0);
|
||||
float we = BloomScan(pos, 2.0);
|
||||
|
||||
return a*wa+b*wb+c*wc+d*wd+e*we;
|
||||
}
|
||||
|
||||
// Distortion of scanlines, and end of screen alpha.
|
||||
vec2 Warp(vec2 pos)
|
||||
{
|
||||
pos = pos*2.0-1.0;
|
||||
pos *= vec2(1.0 + (pos.y*pos.y)*warpX, 1.0 + (pos.x*pos.x)*warpY);
|
||||
|
||||
return pos*0.5 + 0.5;
|
||||
}
|
||||
|
||||
// Shadow mask.
|
||||
vec3 Mask(vec2 pos)
|
||||
{
|
||||
vec3 mask = vec3(maskDark, maskDark, maskDark);
|
||||
|
||||
// Very compressed TV style shadow mask.
|
||||
if (shadowMask == 1.0)
|
||||
{
|
||||
float line = maskLight;
|
||||
float odd = 0.0;
|
||||
|
||||
if (fract(pos.x*0.166666666) < 0.5) odd = 1.0;
|
||||
if (fract((pos.y + odd) * 0.5) < 0.5) line = maskDark;
|
||||
|
||||
pos.x = fract(pos.x*0.333333333);
|
||||
|
||||
if (pos.x < 0.333) mask.r = maskLight;
|
||||
else if (pos.x < 0.666) mask.g = maskLight;
|
||||
else mask.b = maskLight;
|
||||
mask*=line;
|
||||
}
|
||||
|
||||
// Aperture-grille.
|
||||
else if (shadowMask == 2.0)
|
||||
{
|
||||
pos.x = fract(pos.x*0.333333333);
|
||||
|
||||
if (pos.x < 0.333) mask.r = maskLight;
|
||||
else if (pos.x < 0.666) mask.g = maskLight;
|
||||
else mask.b = maskLight;
|
||||
}
|
||||
|
||||
// Stretched VGA style shadow mask (same as prior shaders).
|
||||
else if (shadowMask == 3.0)
|
||||
{
|
||||
pos.x += pos.y*3.0;
|
||||
pos.x = fract(pos.x*0.166666666);
|
||||
|
||||
if (pos.x < 0.333) mask.r = maskLight;
|
||||
else if (pos.x < 0.666) mask.g = maskLight;
|
||||
else mask.b = maskLight;
|
||||
}
|
||||
|
||||
// VGA style shadow mask.
|
||||
else if (shadowMask == 4.0)
|
||||
{
|
||||
pos.xy = floor(pos.xy*vec2(1.0, 0.5));
|
||||
pos.x += pos.y*3.0;
|
||||
pos.x = fract(pos.x*0.166666666);
|
||||
|
||||
if (pos.x < 0.333) mask.r = maskLight;
|
||||
else if (pos.x < 0.666) mask.g = maskLight;
|
||||
else mask.b = maskLight;
|
||||
}
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 pos = Warp(vTexCoord);
|
||||
vec3 outColor = Tri(pos).rgb;
|
||||
|
||||
if (shadowMask > 0.0)
|
||||
outColor.rgb *= Mask(vTexCoord.xy * outputSize.xy * 1.000001);
|
||||
#ifdef DO_BLOOM
|
||||
//Add Bloom
|
||||
outColor.rgb += mix( vec3(0.0), texture(source[0], pos).rgb, bloomAmount);
|
||||
#endif
|
||||
|
||||
FragColor = vec4(ToSrgb(outColor.rgb), 1.0);
|
||||
}
|
15
pack/Shaders/CRT-Lottes.shader/scanpass.vs
Normal file
|
@ -0,0 +1,15 @@
|
|||
#version 150
|
||||
|
||||
in vec4 position;
|
||||
in vec2 texCoord;
|
||||
|
||||
out Vertex {
|
||||
vec2 vTexCoord;
|
||||
};
|
||||
|
||||
uniform vec4 sourceSize[];
|
||||
|
||||
void main() {
|
||||
gl_Position = position;
|
||||
vTexCoord = texCoord;
|
||||
}
|
13973
pack/Shaders/CRT-Royale.shader/bloom-approx.fs
Normal file
5859
pack/Shaders/CRT-Royale.shader/bloom-approx.vs
Normal file
7240
pack/Shaders/CRT-Royale.shader/bloom-horizontal-reconstitute.fs
Normal file
6570
pack/Shaders/CRT-Royale.shader/bloom-horizontal-reconstitute.vs
Normal file
4824
pack/Shaders/CRT-Royale.shader/bloom-vertical.fs
Normal file
3792
pack/Shaders/CRT-Royale.shader/bloom-vertical.vs
Normal file
2016
pack/Shaders/CRT-Royale.shader/blur9fast-horizontal.fs
Normal file
2025
pack/Shaders/CRT-Royale.shader/blur9fast-horizontal.vs
Normal file
2016
pack/Shaders/CRT-Royale.shader/blur9fast-vertical.fs
Normal file
2025
pack/Shaders/CRT-Royale.shader/blur9fast-vertical.vs
Normal file
14481
pack/Shaders/CRT-Royale.shader/brightpass.fs
Normal file
6551
pack/Shaders/CRT-Royale.shader/brightpass.vs
Normal file
5279
pack/Shaders/CRT-Royale.shader/geometry-aa-last-pass.fs
Normal file
5263
pack/Shaders/CRT-Royale.shader/geometry-aa-last-pass.vs
Normal file
214
pack/Shaders/CRT-Royale.shader/manifest.bml
Normal file
|
@ -0,0 +1,214 @@
|
|||
input
|
||||
filter: nearest
|
||||
|
||||
// IMPORTANT:
|
||||
// Shader passes need to know details about the image in the mask_texture LUT
|
||||
// files, so set the following constants in user-preset-constants.h accordingly:
|
||||
// 1.) mask_triads_per_tile = (number of horizontal triads in mask texture LUT's)
|
||||
// 2.) mask_texture_small_size = (texture size of mask*texture_small LUT's)
|
||||
// 3.) mask_texture_large_size = (texture size of mask*texture_large LUT's)
|
||||
// 4.) mask_grille_avg_color = (avg. brightness of mask_grille_texture* LUT's, in [0, 1])
|
||||
// 5.) mask_slot_avg_color = (avg. brightness of mask_slot_texture* LUT's, in [0, 1])
|
||||
// 6.) mask_shadow_avg_color = (avg. brightness of mask_shadow_texture* LUT's, in [0, 1])
|
||||
// Shader passes also need to know certain scales set in this preset, but their
|
||||
// compilation model doesn't currently allow the preset file to tell them. Make
|
||||
// sure to set the following constants in user-preset-constants.h accordingly too:
|
||||
// 1.) bloom_approx_scale_x = scale_x2
|
||||
// 2.) mask_resize_viewport_scale = vec2(scale_x6, scale_y5)
|
||||
// Finally, shader passes need to know the value of geom_max_aspect_ratio used to
|
||||
// calculate scale_y5 (among other values):
|
||||
// 1.) geom_max_aspect_ratio = (geom_max_aspect_ratio used to calculate scale_y5)
|
||||
|
||||
// Pass0: Linearize the input based on CRT gamma and bob interlaced fields.
|
||||
// (Bobbing ensures we can immediately blur without getting artifacts.)
|
||||
program
|
||||
filter: nearest
|
||||
vertex: first-pass-linearize-crt-gamma-bob-fields.vs
|
||||
fragment: first-pass-linearize-crt-gamma-bob-fields.fs
|
||||
format: rgba16f
|
||||
height: 100%
|
||||
width: 100%
|
||||
|
||||
// Pass1: Resample interlaced (and misconverged) scanlines vertically.
|
||||
// Separating vertical/horizontal scanline sampling is faster: It lets us
|
||||
// consider more scanlines while calculating weights for fewer pixels, and
|
||||
// it reduces our samples from vertical*horizontal to vertical+horizontal.
|
||||
// This has to come right after ORIG_LINEARIZED, because there's no
|
||||
// "original_source" scale_type we can use later.
|
||||
program
|
||||
filter: linear
|
||||
vertex: scanlines-vertical-interlacing.vs
|
||||
fragment: scanlines-vertical-interlacing.fs
|
||||
height: 400%
|
||||
width: 100%
|
||||
format: rgba16f
|
||||
|
||||
// Pass2: Do a small resize blur of ORIG_LINEARIZED at an absolute size, and
|
||||
// account for convergence offsets. We want to blur a predictable portion of the
|
||||
// screen to match the phosphor bloom, and absolute scale works best for
|
||||
// reliable results with a fixed-size bloom. Picking a scale is tricky:
|
||||
// a.) 400x300 is a good compromise for the "fake-bloom" version: It's low enough
|
||||
// to blur high-res/interlaced sources but high enough that resampling
|
||||
// doesn't smear low-res sources too much.
|
||||
// b.) 320x240 works well for the "real bloom" version: It's 1-1.5% faster, and
|
||||
// the only noticeable visual difference is a larger halation spread (which
|
||||
// may be a good thing for people who like to crank it up).
|
||||
// Note the 4:3 aspect ratio assumes the input has cropped geom_overscan (so it's
|
||||
// *intended* for an ~4:3 aspect ratio).
|
||||
program
|
||||
filter: linear
|
||||
vertex: bloom-approx.vs
|
||||
fragment: bloom-approx.fs
|
||||
format: rgba16f
|
||||
width: 320 px
|
||||
height: 240 px
|
||||
|
||||
// Pass3: Vertically blur the input for halation and refractive diffusion.
|
||||
// Base this on BLOOM_APPROX: This blur should be small and fast, and blurring
|
||||
// a constant portion of the screen is probably physically correct if the
|
||||
// viewport resolution is proportional to the simulated CRT size.
|
||||
program
|
||||
filter: linear
|
||||
vertex: blur9fast-vertical.vs
|
||||
fragment: blur9fast-vertical.fs
|
||||
format: rgba16f
|
||||
height: 100%
|
||||
width: 100%
|
||||
|
||||
// Pass4: Horizontally blur the input for halation and refractive diffusion.
|
||||
// Note: Using a one-pass 9x9 blur is about 1% slower.
|
||||
program
|
||||
filter: linear
|
||||
vertex: blur9fast-horizontal.vs
|
||||
fragment: blur9fast-horizontal.fs
|
||||
format: rgba16f
|
||||
height: 100%
|
||||
width: 100%
|
||||
|
||||
// Pass5: Lanczos-resize the phosphor mask vertically. Set the absolute
|
||||
// scale_x5 == mask_texture_small_size.x (see IMPORTANT above). Larger scales
|
||||
// will blur, and smaller scales could get nasty. The vertical size must be
|
||||
// based on the viewport size and calculated carefully to avoid artifacts later.
|
||||
// First calculate the minimum number of mask tiles we need to draw.
|
||||
// Since curvature is computed after the scanline masking pass:
|
||||
// num_resized_mask_tiles = 2.0;
|
||||
// If curvature were computed in the scanline masking pass (it's not):
|
||||
// max_mask_texel_border = ~3.0 * (1/3.0 + 4.0*sqrt(2.0) + 0.5 + 1.0);
|
||||
// max_mask_tile_border = max_mask_texel_border/
|
||||
// (min_resized_phosphor_triad_size * mask_triads_per_tile);
|
||||
// num_resized_mask_tiles = max(2.0, 1.0 + max_mask_tile_border * 2.0);
|
||||
// At typical values (triad_size >= 2.0, mask_triads_per_tile == 8):
|
||||
// num_resized_mask_tiles = ~3.8
|
||||
// Triad sizes are given in horizontal terms, so we need geom_max_aspect_ratio
|
||||
// to relate them to vertical resolution. The widest we expect is:
|
||||
// geom_max_aspect_ratio = 4.0/3.0 // Note: Shader passes need to know this!
|
||||
// The fewer triads we tile across the screen, the larger each triad will be as a
|
||||
// fraction of the viewport size, and the larger scale_y5 must be to draw a full
|
||||
// num_resized_mask_tiles. Therefore, we must decide the smallest number of
|
||||
// triads we'll guarantee can be displayed on screen. We'll set this according
|
||||
// to 3-pixel triads at 768p resolution (the lowest anyone's likely to use):
|
||||
// min_allowed_viewport_triads = 768.0*geom_max_aspect_ratio / 3.0 = 341.333333
|
||||
// Now calculate the viewport scale that ensures we can draw resized_mask_tiles:
|
||||
// min_scale_x = resized_mask_tiles * mask_triads_per_tile /
|
||||
// min_allowed_viewport_triads
|
||||
// scale_y5 = geom_max_aspect_ratio * min_scale_x
|
||||
// # Some code might depend on equal scales:
|
||||
// scale_x6 = scale_y5
|
||||
// Given our default geom_max_aspect_ratio and min_allowed_viewport_triads:
|
||||
// scale_y5 = 4.0/3.0 * 2.0/(341.33333 / 8.0) = 0.0625
|
||||
// IMPORTANT: The scales MUST be calculated in this way. If you wish to change
|
||||
// geom_max_aspect_ratio, update that constant in user-preset-constants.h!
|
||||
program
|
||||
filter: linear
|
||||
format: rgba16f
|
||||
width: 64 px
|
||||
height: 6.25%
|
||||
vertex: mask-resize-vertical.vs
|
||||
fragment: mask-resize-vertical.fs
|
||||
pixmap: textures/TileableLinearApertureGrille15Wide8And5d5SpacingResizeTo64.png
|
||||
filter: linear
|
||||
wrap: repeat
|
||||
pixmap: textures/TileableLinearApertureGrille15Wide8And5d5Spacing.png
|
||||
filter: linear
|
||||
wrap: repeat
|
||||
pixmap: textures/TileableLinearSlotMaskTall15Wide9And4d5Horizontal9d14VerticalSpacingResizeTo64.png
|
||||
filter: linear
|
||||
wrap: repeat
|
||||
pixmap: textures/TileableLinearSlotMaskTall15Wide9And4d5Horizontal9d14VerticalSpacing.png
|
||||
filter: linear
|
||||
wrap: repeat
|
||||
pixmap: textures/TileableLinearShadowMaskEDPResizeTo64.png
|
||||
filter: linear
|
||||
wrap: repeat
|
||||
pixmap: textures/TileableLinearShadowMaskEDP.png
|
||||
filter: linear
|
||||
wrap: repeat
|
||||
|
||||
// Pass6: Lanczos-resize the phosphor mask horizontally. scale_x6 = scale_y5.
|
||||
// TODO: Check again if the shaders actually require equal scales.
|
||||
program
|
||||
filter: nearest
|
||||
vertex: mask-resize-horizontal.vs
|
||||
fragment: mask-resize-horizontal.fs
|
||||
format: rgba16f
|
||||
|
||||
// Pass7: Resample (misconverged) scanlines horizontally, apply halation, and
|
||||
// apply the phosphor mask.
|
||||
program
|
||||
filter: linear
|
||||
format: rgba16f
|
||||
height: 100%
|
||||
width: 100%
|
||||
vertex: scanlines-horizontal-apply-mask.vs
|
||||
fragment: scanlines-horizontal-apply-mask.fs
|
||||
pixmap: textures/TileableLinearApertureGrille15Wide8And5d5SpacingResizeTo64.png
|
||||
filter: linear
|
||||
wrap: repeat
|
||||
pixmap: textures/TileableLinearApertureGrille15Wide8And5d5Spacing.png
|
||||
filter: linear
|
||||
wrap: repeat
|
||||
pixmap: textures/TileableLinearSlotMaskTall15Wide9And4d5Horizontal9d14VerticalSpacingResizeTo64.png
|
||||
filter: linear
|
||||
wrap: repeat
|
||||
pixmap: textures/TileableLinearSlotMaskTall15Wide9And4d5Horizontal9d14VerticalSpacing.png
|
||||
filter: linear
|
||||
wrap: repeat
|
||||
pixmap: textures/TileableLinearShadowMaskEDPResizeTo64.png
|
||||
filter: linear
|
||||
wrap: repeat
|
||||
pixmap: textures/TileableLinearShadowMaskEDP.png
|
||||
filter: linear
|
||||
wrap: repeat
|
||||
|
||||
// Pass 8: Compute a brightpass. This will require reading the final mask.
|
||||
program
|
||||
filter: linear
|
||||
format: rgba16f
|
||||
vertex: brightpass.vs
|
||||
fragment: brightpass.fs
|
||||
|
||||
// Pass 9: Blur the brightpass vertically
|
||||
program
|
||||
filter: linear
|
||||
format: rgba16f
|
||||
vertex: bloom-vertical.vs
|
||||
fragment: bloom-vertical.fs
|
||||
|
||||
// Pass 10: Blur the brightpass horizontally and combine it with the dimpass:
|
||||
program
|
||||
filter: linear
|
||||
format: rgba16f
|
||||
height: 100%
|
||||
width: 100%
|
||||
vertex: bloom-horizontal-reconstitute.vs
|
||||
fragment: bloom-horizontal-reconstitute.fs
|
||||
|
||||
// Pass 11: Compute curvature/AA:
|
||||
program
|
||||
filter: linear
|
||||
format: rgba16f
|
||||
vertex: geometry-aa-last-pass.vs
|
||||
fragment: geometry-aa-last-pass.fs
|
||||
|
||||
output
|
||||
filter: nearest
|
3208
pack/Shaders/CRT-Royale.shader/mask-resize-horizontal.fs
Normal file
3236
pack/Shaders/CRT-Royale.shader/mask-resize-horizontal.vs
Normal file
3248
pack/Shaders/CRT-Royale.shader/mask-resize-vertical.fs
Normal file
3212
pack/Shaders/CRT-Royale.shader/mask-resize-vertical.vs
Normal file
10845
pack/Shaders/CRT-Royale.shader/scanlines-horizontal-apply-mask.fs
Normal file
6047
pack/Shaders/CRT-Royale.shader/scanlines-horizontal-apply-mask.vs
Normal file
5963
pack/Shaders/CRT-Royale.shader/scanlines-vertical-interlacing.fs
Normal file
5830
pack/Shaders/CRT-Royale.shader/scanlines-vertical-interlacing.vs
Normal file
After Width: | Height: | Size: 194 KiB |
After Width: | Height: | Size: 4.1 KiB |
After Width: | Height: | Size: 214 KiB |
After Width: | Height: | Size: 202 KiB |
After Width: | Height: | Size: 5.2 KiB |
After Width: | Height: | Size: 5.9 KiB |
After Width: | Height: | Size: 200 KiB |
After Width: | Height: | Size: 6.8 KiB |
52
pack/Shaders/GTU.shader/GTU-pass1.fs
Normal file
|
@ -0,0 +1,52 @@
|
|||
#version 150
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// GTU version 0.40
|
||||
// Author: aliaspider - aliaspider@gmail.com
|
||||
// License: GPLv3
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// SETTINGS
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
//#define CROP_OVERSCAN
|
||||
#define TV_COLOR_LEVELS
|
||||
//#define COMPOSITE_CONNECTION
|
||||
//#define NO_SCANLINES
|
||||
#define TV_HORIZONTAL_RESOLUTION 400.0
|
||||
#define TV_VERTICAL_RESOLUTION 300.0
|
||||
#define SIGNAL_RESOLUTION 280.0
|
||||
#define SIGNAL_RESOLUTION_I 83.0
|
||||
#define SIGNAL_RESOLUTION_Q 25.0
|
||||
#define TV_DISPLAY_GAMMA 2.4
|
||||
#define OUTPUT_DISPLAY_GAMMA 2.2
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
//
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#define RGB_to_YIQ mat3x3( 0.299 , 0.595716 , 0.211456 , 0.587 , -0.274453 , -0.522591 , 0.114 , -0.321263 , 0.311135 )
|
||||
#define YIQ_to_RGB mat3x3( 1.0 , 1.0 , 1.0 , 0.9563 , -0.2721 , -1.1070 , 0.6210 , -0.6474 , 1.7046 )
|
||||
#define LEVELS(C) clamp((C -16/ 255.0)*255.0/(235.0-16.0),0.0,1.0)
|
||||
|
||||
uniform sampler2D source[];
|
||||
uniform vec4 sourceSize[];
|
||||
|
||||
in Vertex {
|
||||
vec2 texCoord;
|
||||
};
|
||||
out vec4 fragColor;
|
||||
|
||||
|
||||
void main() {
|
||||
vec3 c=texture2D(source[0], texCoord.xy).xyz;
|
||||
#ifdef TV_COLOR_LEVELS
|
||||
c=LEVELS(c);
|
||||
#endif
|
||||
#ifdef COMPOSITE_CONNECTION
|
||||
c=RGB_to_YIQ*c;
|
||||
#endif
|
||||
fragColor = vec4(c, 1.0);
|
||||
}
|
77
pack/Shaders/GTU.shader/GTU-pass2.fs
Normal file
|
@ -0,0 +1,77 @@
|
|||
#version 150
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// GTU version 0.40
|
||||
// Author: aliaspider - aliaspider@gmail.com
|
||||
// License: GPLv3
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// SETTINGS
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
//#define CROP_OVERSCAN
|
||||
#define TV_COLOR_LEVELS
|
||||
//#define COMPOSITE_CONNECTION
|
||||
//#define NO_SCANLINES
|
||||
#define TV_HORIZONTAL_RESOLUTION 400.0
|
||||
#define TV_VERTICAL_RESOLUTION 300.0
|
||||
#define SIGNAL_RESOLUTION 280.0
|
||||
#define SIGNAL_RESOLUTION_I 83.0
|
||||
#define SIGNAL_RESOLUTION_Q 25.0
|
||||
#define TV_DISPLAY_GAMMA 2.4
|
||||
#define OUTPUT_DISPLAY_GAMMA 2.2
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
//
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#define YIQ_to_RGB mat3x3( 1.0 , 1.0 , 1.0 , 0.9563 , -0.2721 , -1.1070 , 0.6210 , -0.6474 , 1.7046 )
|
||||
|
||||
|
||||
|
||||
|
||||
#define pi 3.14159265358
|
||||
#define a(x) abs(x)
|
||||
#define d(x,b) (pi*b*min(a(x)+0.5,1.0/b))
|
||||
#define e(x,b) (pi*b*min(max(a(x)-0.5,-1.0/b),1.0/b))
|
||||
#define STU(x,b) ((d(x,b)+sin(d(x,b))-e(x,b)-sin(e(x,b)))/(2.0*pi))
|
||||
#define X(i) (offset-(i))
|
||||
|
||||
#define GETC (texture(source[0], vec2(texCoord.x - X*sourceSize[0].z,texCoord.y)).xyz)
|
||||
|
||||
#ifdef COMPOSITE_CONNECTION
|
||||
#define VAL vec3((c.x*STU(X,(SIGNAL_RESOLUTION*sourceSize[0].z))),(c.y*STU(X,(SIGNAL_RESOLUTION_I*sourceSize[0].z))),(c.z*STU(X,(SIGNAL_RESOLUTION_Q*sourceSize[0].z))))
|
||||
#else
|
||||
#define VAL (c*STU(X,(SIGNAL_RESOLUTION*sourceSize[0].z)))
|
||||
#endif //COMPOSITE_CONNECTION
|
||||
|
||||
#define PROCESS(i) X=X(i);c=GETC;tempColor+=VAL;
|
||||
|
||||
uniform sampler2D source[];
|
||||
uniform vec4 sourceSize[];
|
||||
|
||||
in Vertex {
|
||||
vec2 texCoord;
|
||||
};
|
||||
out vec4 fragColor;
|
||||
|
||||
|
||||
void main() {
|
||||
|
||||
float offset = fract((texCoord.x * sourceSize[0].x) - 0.5);
|
||||
vec3 tempColor = vec3(0.0);
|
||||
float X;
|
||||
vec3 c;
|
||||
PROCESS(-6)PROCESS(-5)PROCESS(-4)PROCESS(-3)PROCESS(-2)PROCESS(-1)PROCESS( 0)
|
||||
PROCESS( 7)PROCESS( 6)PROCESS( 5)PROCESS( 4)PROCESS( 3)PROCESS( 2)PROCESS( 1)
|
||||
|
||||
|
||||
#ifdef COMPOSITE_CONNECTION
|
||||
tempColor=clamp(YIQ_to_RGB*tempColor,0.0,1.0);
|
||||
#endif
|
||||
tempColor=clamp(pow(tempColor,vec3(TV_DISPLAY_GAMMA)),0.0,1.0);
|
||||
fragColor = vec4(tempColor,1.0);
|
||||
}
|
46
pack/Shaders/GTU.shader/GTU-pass2.vs
Normal file
|
@ -0,0 +1,46 @@
|
|||
#version 150
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// GTU version 0.40
|
||||
// Author: aliaspider - aliaspider@gmail.com
|
||||
// License: GPLv3
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// SETTINGS
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
//#define CROP_OVERSCAN
|
||||
#define TV_COLOR_LEVELS
|
||||
//#define COMPOSITE_CONNECTION
|
||||
//#define NO_SCANLINES
|
||||
#define TV_HORIZONTAL_RESOLUTION 400.0
|
||||
#define TV_VERTICAL_RESOLUTION 300.0
|
||||
#define SIGNAL_RESOLUTION 280.0
|
||||
#define SIGNAL_RESOLUTION_I 83.0
|
||||
#define SIGNAL_RESOLUTION_Q 25.0
|
||||
#define TV_DISPLAY_GAMMA 2.4
|
||||
#define OUTPUT_DISPLAY_GAMMA 2.2
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
//
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
in vec4 position;
|
||||
in vec2 texCoord;
|
||||
|
||||
out Vertex{
|
||||
vec2 texCoord;
|
||||
}vertexOut;
|
||||
|
||||
void main(void){
|
||||
|
||||
#ifdef CROP_OVERSCAN
|
||||
gl_Position=position;
|
||||
gl_Position.x/=(224.0/240.0);
|
||||
#else
|
||||
gl_Position=position;
|
||||
#endif
|
||||
|
||||
vertexOut.texCoord=texCoord;
|
||||
}
|
63
pack/Shaders/GTU.shader/GTU-pass3.fs
Normal file
|
@ -0,0 +1,63 @@
|
|||
#version 150
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// GTU version 0.40
|
||||
// Author: aliaspider - aliaspider@gmail.com
|
||||
// License: GPLv3
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// SETTINGS
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
//#define CROP_OVERSCAN
|
||||
#define TV_COLOR_LEVELS
|
||||
//#define COMPOSITE_CONNECTION
|
||||
//#define NO_SCANLINES
|
||||
#define TV_HORIZONTAL_RESOLUTION 400.0
|
||||
#define TV_VERTICAL_RESOLUTION 300.0
|
||||
#define SIGNAL_RESOLUTION 280.0
|
||||
#define SIGNAL_RESOLUTION_I 83.0
|
||||
#define SIGNAL_RESOLUTION_Q 25.0
|
||||
#define TV_DISPLAY_GAMMA 2.4
|
||||
#define OUTPUT_DISPLAY_GAMMA 2.2
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
//
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#define pi 3.14159265358
|
||||
#define a(x) abs(x)
|
||||
#define d(x,b) (pi*b*min(a(x)+0.5,1.0/b))
|
||||
#define e(x,b) (pi*b*min(max(a(x)-0.5,-1.0/b),1.0/b))
|
||||
#define STU(x,b) ((d(x,b)+sin(d(x,b))-e(x,b)-sin(e(x,b)))/(2.0*pi))
|
||||
#define X(i) (offset-(i))
|
||||
|
||||
#define GETC (texture(source[0], vec2(texCoord.x - X*sourceSize[0].z,texCoord.y)).xyz)
|
||||
#define VAL (c*STU(X,(TV_HORIZONTAL_RESOLUTION*sourceSize[0].z)))
|
||||
|
||||
#define PROCESS(i) X=X(i);c=GETC;tempColor+=VAL;
|
||||
|
||||
uniform sampler2D source[];
|
||||
uniform vec4 sourceSize[];
|
||||
|
||||
in Vertex {
|
||||
vec2 texCoord;
|
||||
};
|
||||
out vec4 fragColor;
|
||||
|
||||
|
||||
void main() {
|
||||
|
||||
float offset = fract((texCoord.x * sourceSize[0].x) - 0.5);
|
||||
vec3 tempColor = vec3(0.0);
|
||||
float X;
|
||||
vec3 c;
|
||||
PROCESS(-6)PROCESS(-5)PROCESS(-4)PROCESS(-3)PROCESS(-2)PROCESS(-1)PROCESS( 0)
|
||||
PROCESS( 7)PROCESS( 6)PROCESS( 5)PROCESS( 4)PROCESS( 3)PROCESS( 2)PROCESS( 1)
|
||||
|
||||
// tempColor=pow(tempColor,vec3(1.0/2.2));
|
||||
fragColor = vec4(tempColor,1.0);
|
||||
}
|
78
pack/Shaders/GTU.shader/GTU-pass4.fs
Normal file
|
@ -0,0 +1,78 @@
|
|||
#version 150
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// GTU version 0.40
|
||||
// Author: aliaspider - aliaspider@gmail.com
|
||||
// License: GPLv3
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// SETTINGS
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
//#define CROP_OVERSCAN
|
||||
#define TV_COLOR_LEVELS
|
||||
//#define COMPOSITE_CONNECTION
|
||||
//#define NO_SCANLINES
|
||||
#define TV_HORIZONTAL_RESOLUTION 400.0
|
||||
#define TV_VERTICAL_RESOLUTION 300.0
|
||||
#define SIGNAL_RESOLUTION 280.0
|
||||
#define SIGNAL_RESOLUTION_I 83.0
|
||||
#define SIGNAL_RESOLUTION_Q 25.0
|
||||
#define TV_DISPLAY_GAMMA 2.4
|
||||
#define OUTPUT_DISPLAY_GAMMA 2.2
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
//
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#define SCANLINE_WIDTH (1.5*sourceSize[0].y/TV_VERTICAL_RESOLUTION)
|
||||
|
||||
uniform sampler2D source[];
|
||||
uniform sampler2D texture[];
|
||||
uniform vec4 sourceSize[];
|
||||
|
||||
in Vertex {
|
||||
vec2 texCoord;
|
||||
};
|
||||
out vec4 fragColor;
|
||||
|
||||
|
||||
#define GAMMAOUT(c0) (pow(c0, vec3(1.0/OUTPUTG2)))
|
||||
#define pi 3.14159265358
|
||||
#define GAUSS(x,w) ((sqrt(2.0) / (w)) * (exp((-2.0 * pi * (x) * (x)) / ((w) * (w)))))
|
||||
#define Y(j) (offset.y-(j))
|
||||
#define a(x) abs(x)
|
||||
#define d(x,b) (pi*b*min(a(x)+0.5,1.0/b))
|
||||
#define e(x,b) (pi*b*min(max(a(x)-0.5,-1.0/b),1.0/b))
|
||||
#define STU(x,b) ((d(x,b)+sin(d(x,b))-e(x,b)-sin(e(x,b)))/(2.0*pi))
|
||||
|
||||
#define SOURCE(j) vec2(texCoord.x,texCoord.y - Y(j)*sourceSize[0].w)
|
||||
#define C(j) (texture2D(source[0], SOURCE(j)).xyz)
|
||||
|
||||
#ifdef NO_SCANLINES
|
||||
#define VAL(j) (C(j)*STU(Y(j),(TV_VERTICAL_RESOLUTION*sourceSize[0].w)))
|
||||
#else
|
||||
#define VAL(j) (C(j)*GAUSS(Y(j),SCANLINE_WIDTH))
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
void main() {
|
||||
|
||||
vec2 offset = fract((texCoord.xy * sourceSize[0].xy) - 0.5);
|
||||
vec3 tempColor = vec3(0.0);
|
||||
|
||||
tempColor+=VAL(-3.0);
|
||||
tempColor+=VAL(-2.0);
|
||||
tempColor+=VAL(-1.0);
|
||||
tempColor+=VAL(0.0);
|
||||
tempColor+=VAL(1.0);
|
||||
tempColor+=VAL(2.0);
|
||||
tempColor+=VAL(3.0);
|
||||
tempColor+=VAL(4.0);
|
||||
|
||||
fragColor = vec4(pow(tempColor,vec3(1.0/OUTPUT_DISPLAY_GAMMA)), 1.0);
|
||||
}
|
46
pack/Shaders/GTU.shader/GTU-pass4.vs
Normal file
|
@ -0,0 +1,46 @@
|
|||
#version 150
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// GTU version 0.40
|
||||
// Author: aliaspider - aliaspider@gmail.com
|
||||
// License: GPLv3
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// SETTINGS
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
//#define CROP_OVERSCAN
|
||||
#define TV_COLOR_LEVELS
|
||||
//#define COMPOSITE_CONNECTION
|
||||
//#define NO_SCANLINES
|
||||
#define TV_HORIZONTAL_RESOLUTION 400.0
|
||||
#define TV_VERTICAL_RESOLUTION 300.0
|
||||
#define SIGNAL_RESOLUTION 280.0
|
||||
#define SIGNAL_RESOLUTION_I 83.0
|
||||
#define SIGNAL_RESOLUTION_Q 25.0
|
||||
#define TV_DISPLAY_GAMMA 2.4
|
||||
#define OUTPUT_DISPLAY_GAMMA 2.2
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
//
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
in vec4 position;
|
||||
in vec2 texCoord;
|
||||
|
||||
out Vertex{
|
||||
vec2 texCoord;
|
||||
}vertexOut;
|
||||
|
||||
void main(void){
|
||||
|
||||
#ifdef CROP_OVERSCAN
|
||||
gl_Position=position;
|
||||
gl_Position.y/=(224.0/240.0);
|
||||
#else
|
||||
gl_Position=position;
|
||||
#endif
|
||||
|
||||
vertexOut.texCoord=texCoord;
|
||||
}
|
28
pack/Shaders/GTU.shader/manifest.bml
Normal file
|
@ -0,0 +1,28 @@
|
|||
program
|
||||
width: 100%
|
||||
height: 100%
|
||||
format: rgba32f
|
||||
filter: nearest
|
||||
wrap: edge
|
||||
fragment: GTU-pass1.fs
|
||||
program
|
||||
height: 100%
|
||||
format: rgba32f
|
||||
filter: nearest
|
||||
wrap: edge
|
||||
vertex: GTU-pass2.vs
|
||||
fragment: GTU-pass2.fs
|
||||
program
|
||||
height: 100%
|
||||
format: rgba32f
|
||||
filter: nearest
|
||||
wrap: edge
|
||||
fragment: GTU-pass3.fs
|
||||
program
|
||||
format: rgba8
|
||||
filter: nearest
|
||||
wrap: edge
|
||||
vertex: GTU-pass4.vs
|
||||
fragment: GTU-pass4.fs
|
||||
output
|
||||
filter: nearest
|
88
pack/Shaders/LCD-cgwg.shader/lcd-grid.fs
Normal file
|
@ -0,0 +1,88 @@
|
|||
#version 150
|
||||
|
||||
#in red
|
||||
#in green
|
||||
#in blue
|
||||
#in gain
|
||||
#in gamma
|
||||
#in blacklevel
|
||||
#in ambient
|
||||
#in BGR
|
||||
|
||||
#define outgamma 2.2
|
||||
|
||||
uniform sampler2D source[];
|
||||
uniform vec4 sourceSize[];
|
||||
uniform vec4 targetSize;
|
||||
|
||||
in Vertex {
|
||||
vec2 texCoord;
|
||||
};
|
||||
|
||||
out vec4 fragColor;
|
||||
|
||||
#define fetch_offset(coord,offset) (pow(vec3(gain) * texelFetchOffset(source[0], (coord), 0, (offset)).rgb + vec3(blacklevel), vec3(gamma)) + vec3(ambient))
|
||||
|
||||
// integral of (1 - x^2 - x^4 + x^6)^2
|
||||
const float coeffs_x[] = float[](1.0, -2.0/3.0, -1.0/5.0, 4.0/7.0, -1.0/9.0, -2.0/11.0, 1.0/13.0);
|
||||
// integral of (1 - 2x^4 + x^6)^2
|
||||
const float coeffs_y[] = float[](1.0, 0.0, -4.0/5.0, 2.0/7.0, 4.0/9.0, -4.0/11.0, 1.0/13.0);
|
||||
float intsmear_func(float z, float coeffs[7])
|
||||
{
|
||||
float z2 = z*z;
|
||||
float zn = z;
|
||||
float ret = 0.0;
|
||||
for (int i = 0; i < 7; i++) {
|
||||
ret += zn*coeffs[i];
|
||||
zn *= z2;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
float intsmear(float x, float dx, float d, float coeffs[7])
|
||||
{
|
||||
float zl = clamp((x-dx*0.5)/d,-1.0,1.0);
|
||||
float zh = clamp((x+dx*0.5)/d,-1.0,1.0);
|
||||
return d * ( intsmear_func(zh,coeffs) - intsmear_func(zl,coeffs) )/dx;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 texelSize = 1.0 / sourceSize[0].xy;
|
||||
vec2 range = sourceSize[0].xy / (targetSize.xy * sourceSize[0].xy);
|
||||
|
||||
vec3 cred = pow(red, vec3(outgamma));
|
||||
vec3 cgreen = pow(green, vec3(outgamma));
|
||||
vec3 cblue = pow(blue, vec3(outgamma));
|
||||
|
||||
ivec2 tli = ivec2(floor(texCoord/texelSize-vec2(0.4999)));
|
||||
|
||||
vec3 lcol, rcol;
|
||||
float subpix = (texCoord.x/texelSize.x - 0.4999 - float(tli.x))*3.0;
|
||||
float rsubpix = range.x/texelSize.x * 3.0;
|
||||
lcol = vec3(intsmear(subpix+1.0,rsubpix, 1.5, coeffs_x),
|
||||
intsmear(subpix ,rsubpix, 1.5, coeffs_x),
|
||||
intsmear(subpix-1.0,rsubpix, 1.5, coeffs_x));
|
||||
rcol = vec3(intsmear(subpix-2.0,rsubpix, 1.5, coeffs_x),
|
||||
intsmear(subpix-3.0,rsubpix, 1.5, coeffs_x),
|
||||
intsmear(subpix-4.0,rsubpix, 1.5, coeffs_x));
|
||||
#ifdef BGR
|
||||
lcol.rgb = lcol.bgr;
|
||||
rcol.rgb = rcol.bgr;
|
||||
#endif
|
||||
float tcol, bcol;
|
||||
subpix = texCoord.y/texelSize.y - 0.4999 - float(tli.y);
|
||||
rsubpix = range.y/texelSize.y;
|
||||
tcol = intsmear(subpix ,rsubpix, 0.63, coeffs_y);
|
||||
bcol = intsmear(subpix-1.0,rsubpix, 0.63, coeffs_y);
|
||||
|
||||
vec3 topLeftColor = fetch_offset(tli, ivec2(0,0)) * lcol * vec3(tcol);
|
||||
vec3 bottomRightColor = fetch_offset(tli, ivec2(1,1)) * rcol * vec3(bcol);
|
||||
vec3 bottomLeftColor = fetch_offset(tli, ivec2(0,1)) * lcol * vec3(bcol);
|
||||
vec3 topRightColor = fetch_offset(tli, ivec2(1,0)) * rcol * vec3(tcol);
|
||||
|
||||
vec3 averageColor = topLeftColor + bottomRightColor + bottomLeftColor + topRightColor;
|
||||
|
||||
averageColor = mat3x3(cred, cgreen, cblue) * averageColor;
|
||||
|
||||
fragColor = vec4(pow(averageColor,vec3(1.0/outgamma)),0.0);
|
||||
}
|
23
pack/Shaders/LCD-cgwg.shader/manifest.bml
Normal file
|
@ -0,0 +1,23 @@
|
|||
settings
|
||||
persistence: 0.5
|
||||
red: vec3(1,0,0)
|
||||
green: vec3(0,1,0)
|
||||
blue: vec3(0,0,1)
|
||||
gain: 1.0
|
||||
gamma: 3.0
|
||||
blacklevel: 0.05
|
||||
ambient: 0.0
|
||||
BGR
|
||||
|
||||
input
|
||||
history: 8
|
||||
filter: nearest
|
||||
|
||||
program
|
||||
fragment: motion-blur.fs
|
||||
filter: nearest
|
||||
width: 100%
|
||||
height: 100%
|
||||
|
||||
program
|
||||
fragment: lcd-grid.fs
|
23
pack/Shaders/LCD-cgwg.shader/motion-blur.fs
Normal file
|
@ -0,0 +1,23 @@
|
|||
#version 150
|
||||
|
||||
uniform sampler2D source[];
|
||||
uniform sampler2D history[];
|
||||
|
||||
in Vertex {
|
||||
vec2 texCoord;
|
||||
};
|
||||
|
||||
out vec4 fragColor;
|
||||
|
||||
void main() {
|
||||
vec4 color = pow(texture(history[7], texCoord).rgba, vec4(2.2));
|
||||
color = (color + pow(texture(history[6], texCoord).rgba, vec4(2.2))) / 2.0;
|
||||
color = (color + pow(texture(history[5], texCoord).rgba, vec4(2.2))) / 2.0;
|
||||
color = (color + pow(texture(history[4], texCoord).rgba, vec4(2.2))) / 2.0;
|
||||
color = (color + pow(texture(history[3], texCoord).rgba, vec4(2.2))) / 2.0;
|
||||
color = (color + pow(texture(history[2], texCoord).rgba, vec4(2.2))) / 2.0;
|
||||
color = (color + pow(texture(history[1], texCoord).rgba, vec4(2.2))) / 2.0;
|
||||
color = (color + pow(texture(history[0], texCoord).rgba, vec4(2.2))) / 2.0;
|
||||
color = (color + pow(texture(source[0], texCoord).rgba, vec4(2.2))) / 2.0;
|
||||
fragColor = pow(color, vec4(1.0 / 2.2));
|
||||
}
|
24
pack/Shaders/MDAPT-Dedithering.shader/manifest.bml
Normal file
|
@ -0,0 +1,24 @@
|
|||
program
|
||||
width: 100%
|
||||
height: 100%
|
||||
filter: nearest
|
||||
fragment: mdapt-pass1.fs
|
||||
wrap: edge
|
||||
program
|
||||
width: 100%
|
||||
height: 100%
|
||||
filter: nearest
|
||||
fragment: mdapt-pass2.fs
|
||||
wrap: edge
|
||||
program
|
||||
width: 100%
|
||||
height: 100%
|
||||
filter: nearest
|
||||
fragment: mdapt-pass3.fs
|
||||
wrap: edge
|
||||
program
|
||||
width: 100%
|
||||
height: 100%
|
||||
filter: nearest
|
||||
fragment: mdapt-pass4.fs
|
||||
wrap: edge
|
200
pack/Shaders/MDAPT-Dedithering.shader/mdapt-pass1.fs
Normal file
|
@ -0,0 +1,200 @@
|
|||
// This is a port of the original CG shader to the quark format
|
||||
// the original shader can be found here :
|
||||
// https://github.com/libretro/common-shaders/tree/master/dithering/mdapt-4p
|
||||
|
||||
/*
|
||||
Merge Dithering and Pseudo Transparency Shader v1.5 - Pass 1
|
||||
by Sp00kyFox, 2013
|
||||
|
||||
Finds specific patterns and tags their central pixel.
|
||||
|
||||
*/
|
||||
#version 150
|
||||
//#define HORI
|
||||
//#define VERT
|
||||
#define dtt vec3(65536,255,1)
|
||||
#define eq_threshold 5.0
|
||||
|
||||
|
||||
uniform sampler2D source[];
|
||||
uniform vec4 sourceSize[];
|
||||
uniform vec4 targetSize;
|
||||
in Vertex{
|
||||
vec2 texCoord;
|
||||
};
|
||||
|
||||
out vec4 fragColor;
|
||||
|
||||
float reduce(vec3 color)
|
||||
{
|
||||
return dot(color, dtt);
|
||||
}
|
||||
|
||||
float df(float A, float B)
|
||||
{
|
||||
return abs(A-B);
|
||||
}
|
||||
|
||||
bool eq(float A, float B)
|
||||
{
|
||||
return (A == B);
|
||||
}
|
||||
|
||||
float remapTo01(float v, float low, float high)
|
||||
{
|
||||
return clamp((v - low)/(high-low),0.0,1.0);
|
||||
}
|
||||
|
||||
|
||||
void main(void) {
|
||||
vec2 pos = texCoord*sourceSize[0].xy; // pos = pixel position
|
||||
vec2 dir = sign(pos); // dir = pixel direction
|
||||
|
||||
vec2 g1 = dir*vec2(sourceSize[0].z,0.0);
|
||||
vec2 g2 = dir*vec2(0.0,sourceSize[0].w);;
|
||||
|
||||
/*
|
||||
U3
|
||||
UUL U2 UUR
|
||||
ULL UL U1 UR URR
|
||||
L3 L2 L1 C R1 R2 R3
|
||||
DLL DL D1 DR DRR
|
||||
DDL D2 DDR
|
||||
D3
|
||||
*/
|
||||
|
||||
vec3 c = texture(source[0], texCoord).xyz;
|
||||
vec3 l1 = texture(source[0], texCoord - g1).xyz;
|
||||
vec3 l2 = texture(source[0], texCoord - 2*g1).xyz;
|
||||
vec3 r1 = texture(source[0], texCoord + g1).xyz;
|
||||
vec3 r2 = texture(source[0], texCoord + 2*g1).xyz;
|
||||
vec3 u1 = texture(source[0], texCoord - g2).xyz;
|
||||
vec3 u2 = texture(source[0], texCoord - 2*g2).xyz;
|
||||
vec3 d1 = texture(source[0], texCoord + g2).xyz;
|
||||
vec3 d2 = texture(source[0], texCoord + 2*g2).xyz;
|
||||
vec3 ul = texture(source[0], texCoord - g1 - g2).xyz;
|
||||
vec3 ur = texture(source[0], texCoord + g1 - g2).xyz;
|
||||
vec3 dl = texture(source[0], texCoord - g1 + g2).xyz;
|
||||
vec3 dr = texture(source[0], texCoord + g1 + g2).xyz;
|
||||
|
||||
vec3 ull = texture(source[0], texCoord - 2*g1 - g2).xyz;
|
||||
vec3 uul = texture(source[0], texCoord - g1 - 2*g2).xyz;
|
||||
vec3 uur = texture(source[0], texCoord + g1 - 2*g2).xyz;
|
||||
vec3 urr = texture(source[0], texCoord + 2*g1 - g2).xyz;
|
||||
vec3 drr = texture(source[0], texCoord + 2*g1 + g2).xyz;
|
||||
vec3 ddr = texture(source[0], texCoord + g1 + 2*g2).xyz;
|
||||
vec3 ddl = texture(source[0], texCoord - g1 + 2*g2).xyz;
|
||||
vec3 dll = texture(source[0], texCoord - 2*g1 + g2).xyz;
|
||||
|
||||
vec3 l3 = texture(source[0], texCoord - 3*g1).xyz;
|
||||
vec3 r3 = texture(source[0], texCoord + 3*g1).xyz;
|
||||
vec3 u3 = texture(source[0], texCoord - 3*g2).xyz;
|
||||
vec3 d3 = texture(source[0], texCoord + 3*g2).xyz;
|
||||
|
||||
float C = reduce( c );
|
||||
|
||||
float L1 = reduce( l1 ); float U1 = reduce( u1 );
|
||||
float L2 = reduce( l2 ); float U2 = reduce( u2 );
|
||||
float R1 = reduce( r1 ); float D1 = reduce( d1 );
|
||||
float R2 = reduce( r2 ); float D2 = reduce( d2 );
|
||||
|
||||
float UL = reduce( ul ); float L3 = reduce( l3 );
|
||||
float UR = reduce( ur ); float R3 = reduce( r3 );
|
||||
float DL = reduce( dl ); float U3 = reduce( u3 );
|
||||
float DR = reduce( dr ); float D3 = reduce( d3 );
|
||||
|
||||
float ULL = reduce( ull ); float DRR = reduce( drr );
|
||||
float UUL = reduce( uul ); float DDR = reduce( ddr );
|
||||
float UUR = reduce( uur ); float DDL = reduce( ddl );
|
||||
float URR = reduce( urr ); float DLL = reduce( dll );
|
||||
|
||||
/*
|
||||
tag values:
|
||||
0 nothing
|
||||
|
||||
checkerboard pattern
|
||||
9 DL
|
||||
8 DR
|
||||
7 UR
|
||||
6 UL
|
||||
5 full
|
||||
|
||||
horizontal two-line checkerboard
|
||||
4 bottom line
|
||||
3 upper line
|
||||
|
||||
vertical two-line checkerboard
|
||||
2 left line
|
||||
1 right line
|
||||
|
||||
one line dither
|
||||
-1 horizontal
|
||||
-2 vertical
|
||||
*/
|
||||
|
||||
float type=0;
|
||||
|
||||
// checkerboard pattern
|
||||
if(!eq(C,D1) && !eq(C,U1) && !eq(C,L1) && !eq(C,R1))
|
||||
{
|
||||
if(eq(C,UL))
|
||||
{
|
||||
if(eq(C,UR))
|
||||
{
|
||||
if(eq(C,DR))
|
||||
{
|
||||
if(eq(C,DL))
|
||||
type = 5;
|
||||
else if(!eq(D1,L1) || eq(D1,DL))
|
||||
type = 9;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(eq(C,DL) && (!eq(D1,R1) || eq(D1,DR)))
|
||||
type = 8;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(eq(C,DR) && eq(C,DL) && (!eq(U1,R1) || eq(U1,UR)))
|
||||
type = 7;
|
||||
}
|
||||
}
|
||||
else if(eq(C,UR) && eq(C,DR) && eq(C,DL) && (!eq(U1,L1) || eq(U1,UL)))
|
||||
type = 6;
|
||||
}
|
||||
// horizontal two-line checkerboard
|
||||
else if(eq(C,L2) && eq(C,R2) && eq(C,UL) && eq(C,UR) && !eq(C,L1) && !eq(C,R1) && !eq(C,ULL) && !eq(C,U1) && !eq(C,URR))
|
||||
{
|
||||
type = 4;
|
||||
}
|
||||
else if(eq(C,L2) && eq(C,R2) && eq(C,DL) && eq(C,DR) && !eq(C,L1) && !eq(C,R1) && !eq(C,DLL) && !eq(C,D1) && !eq(C,DRR))
|
||||
{
|
||||
type = 3;
|
||||
}
|
||||
// vertical two-line checkerboard
|
||||
else if(eq(C,U2) && eq(C,D2) && eq(C,UR) && eq(C,DR) && !eq(C,U1) && !eq(C,D1) && !eq(C,R1) && !eq(C,UUR) && !eq(C,DDR))
|
||||
{
|
||||
type = 2;
|
||||
}
|
||||
else if(eq(C,U2) && eq(C,D2) && eq(C,UL) && eq(C,DL) && !eq(C,U1) && !eq(C,D1) && !eq(C,L1) && !eq(C,UUL) && !eq(C,DDL))
|
||||
{
|
||||
type = 1;
|
||||
}
|
||||
#ifdef HORI
|
||||
// horizontal one line dither
|
||||
else if(eq(C,L2) && eq(C,R2) && eq(L1,R1) && !eq(C,L1) && !eq(C,L3) && !eq(C,R3))
|
||||
type = -1;
|
||||
#endif
|
||||
#ifdef VERT
|
||||
// vertical one line dither
|
||||
else if(eq(C,U2) && eq(C,D2) && eq(U1,D1) && !eq(C,U1) && !eq(C,U3) && !eq(C,D3))
|
||||
type = -2;
|
||||
#endif
|
||||
|
||||
fragColor=vec4(c, remapTo01(type+2, 0, 15));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|