mirror of https://github.com/bsnes-emu/bsnes.git
Update to v091 release.
byuu says: A few issues crept up in the last release, this should take care of them. First, it seems that the 32-bit runtime on 64-bit versions of Windows have 64-bit time functions; whereas true 32-bit Windows does not. This was causing a DLL error when attempting to load bsnes v090. Second, when there were more than 2,000 files in the same folder on Windows, it was lagging the file browser. With OV2's help, I've fixed that and it'll now load the list instantly. Lastly, I've included the missing video shaders this time.
This commit is contained in:
parent
47dffcae85
commit
7f404e6edb
File diff suppressed because it is too large
Load Diff
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
namespace Emulator {
|
namespace Emulator {
|
||||||
static const char Name[] = "bsnes";
|
static const char Name[] = "bsnes";
|
||||||
static const char Version[] = "090";
|
static const char Version[] = "091";
|
||||||
static const char Author[] = "byuu";
|
static const char Author[] = "byuu";
|
||||||
static const char License[] = "GPLv3";
|
static const char License[] = "GPLv3";
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,14 @@ struct image {
|
||||||
uint64_t mask;
|
uint64_t mask;
|
||||||
unsigned depth;
|
unsigned depth;
|
||||||
unsigned shift;
|
unsigned shift;
|
||||||
|
|
||||||
|
inline bool operator==(const Channel &source) {
|
||||||
|
return mask == source.mask && depth == source.depth && shift == source.shift;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator!=(const Channel &source) {
|
||||||
|
return !operator==(source);
|
||||||
|
}
|
||||||
} alpha, red, green, blue;
|
} alpha, red, green, blue;
|
||||||
|
|
||||||
typedef double (*interpolation)(double, double, double, double, double);
|
typedef double (*interpolation)(double, double, double, double, double);
|
||||||
|
@ -31,6 +39,9 @@ struct image {
|
||||||
static inline unsigned bitShift(uint64_t color);
|
static inline unsigned bitShift(uint64_t color);
|
||||||
static inline uint64_t normalize(uint64_t color, unsigned sourceDepth, unsigned targetDepth);
|
static inline uint64_t normalize(uint64_t color, unsigned sourceDepth, unsigned targetDepth);
|
||||||
|
|
||||||
|
inline bool operator==(const image &source);
|
||||||
|
inline bool operator!=(const image &source);
|
||||||
|
|
||||||
inline image& operator=(const image &source);
|
inline image& operator=(const image &source);
|
||||||
inline image& operator=(image &&source);
|
inline image& operator=(image &&source);
|
||||||
inline image(const image &source);
|
inline image(const image &source);
|
||||||
|
@ -89,6 +100,26 @@ uint64_t image::normalize(uint64_t color, unsigned sourceDepth, unsigned targetD
|
||||||
|
|
||||||
//public
|
//public
|
||||||
|
|
||||||
|
bool image::operator==(const image &source) {
|
||||||
|
if(width != source.width) return false;
|
||||||
|
if(height != source.height) return false;
|
||||||
|
if(pitch != source.pitch) return false;
|
||||||
|
|
||||||
|
if(endian != source.endian) return false;
|
||||||
|
if(stride != source.stride) return false;
|
||||||
|
|
||||||
|
if(alpha != source.alpha) return false;
|
||||||
|
if(red != source.red) return false;
|
||||||
|
if(green != source.green) return false;
|
||||||
|
if(blue != source.blue) return false;
|
||||||
|
|
||||||
|
return memcmp(data, source.data, width * height * stride) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool image::operator!=(const image &source) {
|
||||||
|
return !operator==(source);
|
||||||
|
}
|
||||||
|
|
||||||
image& image::operator=(const image &source) {
|
image& image::operator=(const image &source) {
|
||||||
free();
|
free();
|
||||||
|
|
||||||
|
@ -110,6 +141,8 @@ image& image::operator=(const image &source) {
|
||||||
}
|
}
|
||||||
|
|
||||||
image& image::operator=(image &&source) {
|
image& image::operator=(image &&source) {
|
||||||
|
free();
|
||||||
|
|
||||||
width = source.width;
|
width = source.width;
|
||||||
height = source.height;
|
height = source.height;
|
||||||
pitch = source.pitch;
|
pitch = source.pitch;
|
||||||
|
|
|
@ -8,13 +8,23 @@
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <nds/nds.hpp>
|
#include <nds/nds.hpp>
|
||||||
|
|
||||||
struct timeval {
|
#if defined(__amd64__) || defined(_M_AMD64)
|
||||||
int64_t tv_sec, tv_usec;
|
struct timeval {
|
||||||
};
|
int64_t tv_sec, tv_usec;
|
||||||
#define timegm(tm) _mkgmtime64(tm)
|
};
|
||||||
#define gmtime(tv) _gmtime64(tv)
|
#define timegm(tm) _mkgmtime64(tm)
|
||||||
|
#define gmtime(tv) _gmtime64(tv)
|
||||||
|
#else
|
||||||
|
//Windows 32-bit run-time doesn't have 64-bit time functions
|
||||||
|
struct timeval {
|
||||||
|
time_t tv_sec, tv_usec;
|
||||||
|
};
|
||||||
|
#define timegm(tm) mktime(tm)
|
||||||
|
#define gmtime(tv) localtime(tv)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define gettimeofday(tv,tz) gettimeofday64(tv,tz)
|
#define gettimeofday(tv,tz) gettimeofday64(tv,tz)
|
||||||
|
|
||||||
int gettimeofday64(struct timeval *tv, struct timezone *tz) {
|
int gettimeofday64(struct timeval *tv, struct timezone *tz) {
|
||||||
FILETIME ft;
|
FILETIME ft;
|
||||||
GetSystemTimeAsFileTime(&ft); // UTC in 100ns units
|
GetSystemTimeAsFileTime(&ft); // UTC in 100ns units
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
** Meta object code from reading C++ file 'platform.moc.hpp'
|
** Meta object code from reading C++ file 'platform.moc.hpp'
|
||||||
**
|
**
|
||||||
** Created: Sun Jul 22 02:20:29 2012
|
** Created: Thu Aug 9 18:10:14 2012
|
||||||
** by: The Qt Meta Object Compiler version 62 (Qt 4.6.3)
|
** by: The Qt Meta Object Compiler version 62 (Qt 4.6.3)
|
||||||
**
|
**
|
||||||
** WARNING! All changes made in this file will be lost!
|
** WARNING! All changes made in this file will be lost!
|
||||||
|
|
|
@ -69,6 +69,8 @@ struct pTimer : public pObject {
|
||||||
struct pWindow : public pObject {
|
struct pWindow : public pObject {
|
||||||
Window &window;
|
Window &window;
|
||||||
|
|
||||||
|
static Window& none();
|
||||||
|
|
||||||
void append(Layout &layout);
|
void append(Layout &layout);
|
||||||
void append(Menu &menu);
|
void append(Menu &menu);
|
||||||
void append(Widget &widget);
|
void append(Widget &widget);
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
Window& pWindow::none() {
|
||||||
|
static Window *window = nullptr;
|
||||||
|
if(window == nullptr) window = new Window;
|
||||||
|
return *window;
|
||||||
|
}
|
||||||
|
|
||||||
void pWindow::append(Layout &layout) {
|
void pWindow::append(Layout &layout) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,16 +56,26 @@ string pDialogWindow::fileSave(Window &parent, const string &path, const lstring
|
||||||
return FileDialog(true, parent, path, filter);
|
return FileDialog(true, parent, path, filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int CALLBACK BrowseCallbackProc(HWND hwnd, UINT msg, LPARAM lparam, LPARAM lpdata) {
|
||||||
|
if(msg == BFFM_INITIALIZED) {
|
||||||
|
if(lpdata) SendMessage(hwnd, BFFM_SETSELECTION, TRUE, lpdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
string pDialogWindow::folderSelect(Window &parent, const string &path) {
|
string pDialogWindow::folderSelect(Window &parent, const string &path) {
|
||||||
wchar_t wfilename[PATH_MAX + 1] = L"";
|
wchar_t wfilename[PATH_MAX + 1] = L"";
|
||||||
|
utf16_t wpath(string{path}.transform("/", "\\"));
|
||||||
|
|
||||||
BROWSEINFO bi;
|
BROWSEINFO bi;
|
||||||
bi.hwndOwner = &parent != &Window::none() ? parent.p.hwnd : 0;
|
bi.hwndOwner = &parent != &Window::none() ? parent.p.hwnd : 0;
|
||||||
bi.pidlRoot = NULL;
|
bi.pidlRoot = NULL;
|
||||||
bi.pszDisplayName = wfilename;
|
bi.pszDisplayName = wfilename;
|
||||||
bi.lpszTitle = L"";
|
bi.lpszTitle = L"";
|
||||||
bi.ulFlags = BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS;
|
bi.ulFlags = BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS;
|
||||||
bi.lpfn = NULL;
|
bi.lpfn = BrowseCallbackProc;
|
||||||
bi.lParam = 0;
|
bi.lParam = (LPARAM)(wchar_t*)wpath;
|
||||||
bi.iImage = 0;
|
bi.iImage = 0;
|
||||||
bool result = false;
|
bool result = false;
|
||||||
LPITEMIDLIST pidl = SHBrowseForFolder(&bi);
|
LPITEMIDLIST pidl = SHBrowseForFolder(&bi);
|
||||||
|
|
|
@ -373,6 +373,8 @@ struct pLineEdit : public pWidget {
|
||||||
struct pListView : public pWidget {
|
struct pListView : public pWidget {
|
||||||
ListView &listView;
|
ListView &listView;
|
||||||
HIMAGELIST imageList;
|
HIMAGELIST imageList;
|
||||||
|
vector<vector<unsigned>> imageMap;
|
||||||
|
vector<image> images;
|
||||||
bool lostFocus;
|
bool lostFocus;
|
||||||
|
|
||||||
void append(const lstring &text);
|
void append(const lstring &text);
|
||||||
|
@ -396,7 +398,7 @@ struct pListView : public pWidget {
|
||||||
void destructor();
|
void destructor();
|
||||||
void orphan();
|
void orphan();
|
||||||
void setGeometry(const Geometry &geometry);
|
void setGeometry(const Geometry &geometry);
|
||||||
void setImageList();
|
void buildImageList();
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pProgressBar : public pWidget {
|
struct pProgressBar : public pWidget {
|
||||||
|
|
|
@ -6,6 +6,34 @@ unsigned ListView_GetColumnCount(HWND hwnd) {
|
||||||
return --count;
|
return --count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ListView_SetImage(HWND hwnd, HIMAGELIST imageList, unsigned row, unsigned column, unsigned imageID) {
|
||||||
|
//if this is the first image assigned, set image list now
|
||||||
|
//do not set sooner, or image blocks will appear in a list with no images
|
||||||
|
if(ListView_GetImageList(hwnd, LVSIL_SMALL) != imageList) {
|
||||||
|
ListView_SetImageList(hwnd, imageList, LVSIL_SMALL);
|
||||||
|
}
|
||||||
|
|
||||||
|
LVITEM item;
|
||||||
|
item.mask = LVIF_IMAGE;
|
||||||
|
item.iItem = row;
|
||||||
|
item.iSubItem = column;
|
||||||
|
item.iImage = imageID;
|
||||||
|
ListView_SetItem(hwnd, &item);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageList_Append(HIMAGELIST imageList, const nall::image &source) {
|
||||||
|
auto image = source;
|
||||||
|
if(image.empty()) {
|
||||||
|
image.allocate(15, 15);
|
||||||
|
image.clear(GetSysColor(COLOR_WINDOW));
|
||||||
|
}
|
||||||
|
image.transform(0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0);
|
||||||
|
image.scale(15, 15, Interpolation::Linear);
|
||||||
|
HBITMAP bitmap = CreateBitmap(image);
|
||||||
|
ImageList_Add(imageList, bitmap, NULL);
|
||||||
|
DeleteObject(bitmap);
|
||||||
|
}
|
||||||
|
|
||||||
void pListView::append(const lstring &list) {
|
void pListView::append(const lstring &list) {
|
||||||
wchar_t empty[] = L"";
|
wchar_t empty[] = L"";
|
||||||
unsigned row = ListView_GetItemCount(hwnd);
|
unsigned row = ListView_GetItemCount(hwnd);
|
||||||
|
@ -43,11 +71,11 @@ void pListView::modify(unsigned row, const lstring &list) {
|
||||||
|
|
||||||
void pListView::remove(unsigned row) {
|
void pListView::remove(unsigned row) {
|
||||||
ListView_DeleteItem(hwnd, row);
|
ListView_DeleteItem(hwnd, row);
|
||||||
setImageList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void pListView::reset() {
|
void pListView::reset() {
|
||||||
ListView_DeleteAllItems(hwnd);
|
ListView_DeleteAllItems(hwnd);
|
||||||
|
buildImageList(); //free previously allocated images
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pListView::selected() {
|
bool pListView::selected() {
|
||||||
|
@ -103,7 +131,19 @@ void pListView::setHeaderVisible(bool visible) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void pListView::setImage(unsigned row, unsigned column, const image &image) {
|
void pListView::setImage(unsigned row, unsigned column, const image &image) {
|
||||||
setImageList();
|
//assign existing image
|
||||||
|
for(unsigned n = 0; n < images.size(); n++) {
|
||||||
|
if(images[n] == image) {
|
||||||
|
imageMap(row)(column) = n;
|
||||||
|
return ListView_SetImage(hwnd, imageList, row, column, n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//append and assign new image
|
||||||
|
imageMap(row)(column) = images.size();
|
||||||
|
images.append(image);
|
||||||
|
ImageList_Append(imageList, image);
|
||||||
|
ListView_SetImage(hwnd, imageList, row, column, imageMap(row)(column));
|
||||||
}
|
}
|
||||||
|
|
||||||
void pListView::setSelected(bool selected) {
|
void pListView::setSelected(bool selected) {
|
||||||
|
@ -138,7 +178,7 @@ void pListView::constructor() {
|
||||||
setCheckable(listView.state.checkable);
|
setCheckable(listView.state.checkable);
|
||||||
for(auto &text : listView.state.text) append(text);
|
for(auto &text : listView.state.text) append(text);
|
||||||
for(unsigned n = 0; n < listView.state.checked.size(); n++) setChecked(n, listView.state.checked[n]);
|
for(unsigned n = 0; n < listView.state.checked.size(); n++) setChecked(n, listView.state.checked[n]);
|
||||||
setImageList();
|
buildImageList();
|
||||||
if(listView.state.selected) setSelection(listView.state.selection);
|
if(listView.state.selected) setSelection(listView.state.selection);
|
||||||
autoSizeColumns();
|
autoSizeColumns();
|
||||||
synchronize();
|
synchronize();
|
||||||
|
@ -158,53 +198,46 @@ void pListView::setGeometry(const Geometry &geometry) {
|
||||||
autoSizeColumns();
|
autoSizeColumns();
|
||||||
}
|
}
|
||||||
|
|
||||||
void pListView::setImageList() {
|
void pListView::buildImageList() {
|
||||||
auto &list = listView.state.image;
|
auto &list = listView.state.image;
|
||||||
|
unsigned columns = listView.state.text.size();
|
||||||
|
unsigned rows = max(1u, listView.state.headerText.size());
|
||||||
|
|
||||||
if(imageList) {
|
ListView_SetImageList(hwnd, NULL, LVSIL_SMALL);
|
||||||
ImageList_Destroy(imageList);
|
if(imageList) ImageList_Destroy(imageList);
|
||||||
imageList = nullptr;
|
imageList = ImageList_Create(15, 15, ILC_COLOR32, 1, 0);
|
||||||
}
|
|
||||||
|
|
||||||
bool found = false;
|
imageMap.reset();
|
||||||
for(auto &row : listView.state.image) {
|
images.reset();
|
||||||
for(auto &column : row) {
|
images.append(nall::image()); //empty icon for cells without an image assigned (I_IMAGENONE does not work)
|
||||||
if(column.empty() == false) {
|
|
||||||
found = true;
|
//create a vector of unique images from all images used (many cells may use the same image)
|
||||||
break;
|
for(unsigned y = 0; y < list.size(); y++) {
|
||||||
|
for(unsigned x = 0; x < list[y].size(); x++) {
|
||||||
|
bool found = false;
|
||||||
|
for(unsigned z = 0; z < images.size(); z++) {
|
||||||
|
if(list[y][x] == images[z]) {
|
||||||
|
found = true;
|
||||||
|
imageMap(y)(x) = z;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(found == false) {
|
||||||
|
imageMap(y)(x) = images.size();
|
||||||
|
images.append(list[y][x]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(found == false) return;
|
|
||||||
|
|
||||||
imageList = ImageList_Create(15, 15, ILC_COLOR32, 1, 0);
|
//build image list
|
||||||
nall::image image;
|
for(auto &imageItem : images) ImageList_Append(imageList, imageItem);
|
||||||
image.allocate(15, 15);
|
if(images.size() <= 1) return;
|
||||||
image.clear(GetSysColor(COLOR_WINDOW));
|
|
||||||
ImageList_Add(imageList, CreateBitmap(image), NULL);
|
|
||||||
|
|
||||||
for(unsigned row = 0; row < list.size(); row++) {
|
//set images for all cells
|
||||||
for(unsigned column = 0; column < list(row).size(); column++) {
|
for(unsigned y = 0; y < columns; y++) {
|
||||||
nall::image image = list(row)(column);
|
for(unsigned x = 0; x < rows; x++) {
|
||||||
if(image.empty()) continue;
|
ListView_SetImage(hwnd, imageList, y, x, imageMap(y)(x));
|
||||||
image.transform(0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0);
|
|
||||||
image.scale(15, 15, Interpolation::Linear);
|
|
||||||
ImageList_Add(imageList, CreateBitmap(image), NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ListView_SetImageList(hwnd, imageList, LVSIL_SMALL);
|
|
||||||
|
|
||||||
unsigned ID = 1;
|
|
||||||
for(unsigned row = 0; row < list.size(); row++) {
|
|
||||||
for(unsigned column = 0; column < list(row).size(); column++) {
|
|
||||||
if(list(row)(column).empty()) continue; //I_IMAGENONE does not work properly
|
|
||||||
LVITEM item;
|
|
||||||
item.mask = LVIF_IMAGE;
|
|
||||||
item.iItem = row;
|
|
||||||
item.iSubItem = column;
|
|
||||||
item.iImage = ID++;
|
|
||||||
ListView_SetItem(hwnd, &item);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
shader language=GLSL
|
||||||
|
vertex~
|
||||||
|
void main(void) {
|
||||||
|
gl_Position = ftransform();
|
||||||
|
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||||
|
}
|
||||||
|
|
||||||
|
fragment~ filter=linear
|
||||||
|
uniform sampler2D rubyTexture;
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
vec4 rgb = texture2D(rubyTexture, gl_TexCoord[0].xy);
|
||||||
|
vec4 intens = smoothstep(0.2,0.8,rgb) + normalize(vec4(rgb.xyz, 1.0));
|
||||||
|
|
||||||
|
if(fract(gl_FragCoord.y * 0.5) > 0.5) intens = rgb * 0.8;
|
||||||
|
gl_FragColor = intens;
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
shader language=GLSL
|
||||||
|
vertex~
|
||||||
|
uniform vec2 rubyTextureSize;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
float x = 0.5 * (1.0 / rubyTextureSize.x);
|
||||||
|
float y = 0.5 * (1.0 / rubyTextureSize.y);
|
||||||
|
vec2 dg1 = vec2( x, y);
|
||||||
|
vec2 dg2 = vec2(-x, y);
|
||||||
|
vec2 dx = vec2(x, 0.0);
|
||||||
|
vec2 dy = vec2(0.0, y);
|
||||||
|
|
||||||
|
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
|
||||||
|
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||||
|
gl_TexCoord[1].xy = gl_TexCoord[0].xy - dg1;
|
||||||
|
gl_TexCoord[1].zw = gl_TexCoord[0].xy - dy;
|
||||||
|
gl_TexCoord[2].xy = gl_TexCoord[0].xy - dg2;
|
||||||
|
gl_TexCoord[2].zw = gl_TexCoord[0].xy + dx;
|
||||||
|
gl_TexCoord[3].xy = gl_TexCoord[0].xy + dg1;
|
||||||
|
gl_TexCoord[3].zw = gl_TexCoord[0].xy + dy;
|
||||||
|
gl_TexCoord[4].xy = gl_TexCoord[0].xy + dg2;
|
||||||
|
gl_TexCoord[4].zw = gl_TexCoord[0].xy - dx;
|
||||||
|
}
|
||||||
|
|
||||||
|
fragment~ filter=linear
|
||||||
|
vec4 compress(vec4 in_color, float threshold, float ratio)
|
||||||
|
{
|
||||||
|
vec4 diff = in_color - vec4(threshold);
|
||||||
|
diff = clamp(diff, 0.0, 100.0);
|
||||||
|
return in_color - (diff * (1.0 - 1.0/ratio));
|
||||||
|
}
|
||||||
|
|
||||||
|
uniform sampler2D rubyTexture;
|
||||||
|
uniform vec2 rubyTextureSize;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec3 c00 = texture2D(rubyTexture, gl_TexCoord[1].xy).xyz;
|
||||||
|
vec3 c01 = texture2D(rubyTexture, gl_TexCoord[4].zw).xyz;
|
||||||
|
vec3 c02 = texture2D(rubyTexture, gl_TexCoord[4].xy).xyz;
|
||||||
|
vec3 c10 = texture2D(rubyTexture, gl_TexCoord[1].zw).xyz;
|
||||||
|
vec3 c11 = texture2D(rubyTexture, gl_TexCoord[0].xy).xyz;
|
||||||
|
vec3 c12 = texture2D(rubyTexture, gl_TexCoord[3].zw).xyz;
|
||||||
|
vec3 c20 = texture2D(rubyTexture, gl_TexCoord[2].xy).xyz;
|
||||||
|
vec3 c21 = texture2D(rubyTexture, gl_TexCoord[2].zw).xyz;
|
||||||
|
vec3 c22 = texture2D(rubyTexture, gl_TexCoord[3].xy).xyz;
|
||||||
|
|
||||||
|
vec2 tex = gl_TexCoord[0].xy;
|
||||||
|
vec2 texsize = rubyTextureSize;
|
||||||
|
|
||||||
|
vec3 first = mix(c00, c20, fract(tex.x * texsize.x + 0.5));
|
||||||
|
vec3 second = mix(c02, c22, fract(tex.x * texsize.x + 0.5));
|
||||||
|
|
||||||
|
vec3 mid_horiz = mix(c01, c21, fract(tex.x * texsize.x + 0.5));
|
||||||
|
vec3 mid_vert = mix(c10, c12, fract(tex.y * texsize.y + 0.5));
|
||||||
|
|
||||||
|
vec3 res = mix(first, second, fract(tex.y * texsize.y + 0.5));
|
||||||
|
vec4 final = vec4(0.26 * (res + mid_horiz + mid_vert) + 3.5 * abs(res - mix(mid_horiz, mid_vert, 0.5)), 1.0);
|
||||||
|
gl_FragColor = compress(final, 0.8, 5.0);
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<shader language="GLSL">
|
||||||
|
<fragment filter="linear"><![CDATA[
|
||||||
|
uniform sampler2D rubyTexture;
|
||||||
|
uniform vec2 rubyInputSize;
|
||||||
|
uniform vec2 rubyTextureSize;
|
||||||
|
|
||||||
|
#define distortion 0.2
|
||||||
|
|
||||||
|
vec2 barrelDistortion(vec2 coord) {
|
||||||
|
vec2 cc = coord - 0.5;
|
||||||
|
float dist = dot(cc, cc);
|
||||||
|
return coord + cc * (dist + distortion * dist * dist) * distortion;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
vec2 coord = barrelDistortion (gl_TexCoord[0] * rubyTextureSize / rubyInputSize) * rubyInputSize / rubyTextureSize;
|
||||||
|
|
||||||
|
gl_FragColor = texture2D(rubyTexture, coord);
|
||||||
|
}
|
||||||
|
]]></fragment>
|
||||||
|
</shader>
|
|
@ -0,0 +1,73 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<shader language="GLSL">
|
||||||
|
<vertex><![CDATA[
|
||||||
|
uniform vec2 rubyTextureSize;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
float x = 0.5 * (1.0 / rubyTextureSize.x);
|
||||||
|
float y = 0.5 * (1.0 / rubyTextureSize.y);
|
||||||
|
vec2 dg1 = vec2( x, y);
|
||||||
|
vec2 dg2 = vec2(-x, y);
|
||||||
|
vec2 dx = vec2(x, 0.0);
|
||||||
|
vec2 dy = vec2(0.0, y);
|
||||||
|
|
||||||
|
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
|
||||||
|
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||||
|
gl_TexCoord[1].xy = gl_TexCoord[0].xy - dg1;
|
||||||
|
gl_TexCoord[1].zw = gl_TexCoord[0].xy - dy;
|
||||||
|
gl_TexCoord[2].xy = gl_TexCoord[0].xy - dg2;
|
||||||
|
gl_TexCoord[2].zw = gl_TexCoord[0].xy + dx;
|
||||||
|
gl_TexCoord[3].xy = gl_TexCoord[0].xy + dg1;
|
||||||
|
gl_TexCoord[3].zw = gl_TexCoord[0].xy + dy;
|
||||||
|
gl_TexCoord[4].xy = gl_TexCoord[0].xy + dg2;
|
||||||
|
gl_TexCoord[4].zw = gl_TexCoord[0].xy - dx;
|
||||||
|
}
|
||||||
|
]]></vertex>
|
||||||
|
|
||||||
|
<fragment filter="nearest"><![CDATA[
|
||||||
|
uniform sampler2D rubyTexture;
|
||||||
|
|
||||||
|
const float mx = 0.325; // start smoothing wt.
|
||||||
|
const float k = -0.250; // wt. decrease factor
|
||||||
|
const float max_w = 0.25; // max filter weigth
|
||||||
|
const float min_w =-0.05; // min filter weigth
|
||||||
|
const float lum_add = 0.25; // effects smoothing
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec3 c00 = texture2D(rubyTexture, gl_TexCoord[1].xy).xyz;
|
||||||
|
vec3 c10 = texture2D(rubyTexture, gl_TexCoord[1].zw).xyz;
|
||||||
|
vec3 c20 = texture2D(rubyTexture, gl_TexCoord[2].xy).xyz;
|
||||||
|
vec3 c01 = texture2D(rubyTexture, gl_TexCoord[4].zw).xyz;
|
||||||
|
vec3 c11 = texture2D(rubyTexture, gl_TexCoord[0].xy).xyz;
|
||||||
|
vec3 c21 = texture2D(rubyTexture, gl_TexCoord[2].zw).xyz;
|
||||||
|
vec3 c02 = texture2D(rubyTexture, gl_TexCoord[4].xy).xyz;
|
||||||
|
vec3 c12 = texture2D(rubyTexture, gl_TexCoord[3].zw).xyz;
|
||||||
|
vec3 c22 = texture2D(rubyTexture, gl_TexCoord[3].xy).xyz;
|
||||||
|
vec3 dt = vec3(1.0, 1.0, 1.0);
|
||||||
|
|
||||||
|
float md1 = dot(abs(c00 - c22), dt);
|
||||||
|
float md2 = dot(abs(c02 - c20), dt);
|
||||||
|
|
||||||
|
float w1 = dot(abs(c22 - c11), dt) * md2;
|
||||||
|
float w2 = dot(abs(c02 - c11), dt) * md1;
|
||||||
|
float w3 = dot(abs(c00 - c11), dt) * md2;
|
||||||
|
float w4 = dot(abs(c20 - c11), dt) * md1;
|
||||||
|
|
||||||
|
float t1 = w1 + w3;
|
||||||
|
float t2 = w2 + w4;
|
||||||
|
float ww = max(t1, t2) + 0.0001;
|
||||||
|
|
||||||
|
c11 = (w1 * c00 + w2 * c20 + w3 * c22 + w4 * c02 + ww * c11) / (t1 + t2 + ww);
|
||||||
|
|
||||||
|
float lc1 = k / (0.12 * dot(c10 + c12 + c11, dt) + lum_add);
|
||||||
|
float lc2 = k / (0.12 * dot(c01 + c21 + c11, dt) + lum_add);
|
||||||
|
|
||||||
|
w1 = clamp(lc1 * dot(abs(c11 - c10), dt) + mx, min_w, max_w);
|
||||||
|
w2 = clamp(lc2 * dot(abs(c11 - c21), dt) + mx, min_w, max_w);
|
||||||
|
w3 = clamp(lc1 * dot(abs(c11 - c12), dt) + mx, min_w, max_w);
|
||||||
|
w4 = clamp(lc2 * dot(abs(c11 - c01), dt) + mx, min_w, max_w);
|
||||||
|
|
||||||
|
gl_FragColor.xyz = w1 * c10 + w2 * c21 + w3 * c12 + w4 * c01 + (1.0 - w1 - w2 - w3 - w4) * c11;
|
||||||
|
}
|
||||||
|
]]></fragment>
|
||||||
|
</shader>
|
|
@ -0,0 +1,4 @@
|
||||||
|
install:
|
||||||
|
mkdir -p ~/.config/bsnes/shaders
|
||||||
|
chmod 777 ~/.config/bsnes/shaders
|
||||||
|
cp *.shader ~/.config/bsnes/shaders
|
|
@ -0,0 +1,44 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<shader language="GLSL">
|
||||||
|
<vertex><![CDATA[
|
||||||
|
void main() {
|
||||||
|
gl_Position = ftransform();
|
||||||
|
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||||
|
}
|
||||||
|
]]></vertex>
|
||||||
|
|
||||||
|
<fragment filter="nearest"><![CDATA[
|
||||||
|
uniform sampler2D rubyTexture;
|
||||||
|
uniform vec2 rubyTextureSize;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec2 texelSize = 1.0 / rubyTextureSize;
|
||||||
|
|
||||||
|
vec2 range;
|
||||||
|
range.x = dFdx(gl_TexCoord[0].x) / 2.0 * 0.99;
|
||||||
|
range.y = dFdy(gl_TexCoord[0].y) / 2.0 * 0.99;
|
||||||
|
|
||||||
|
float left = gl_TexCoord[0].x - range.x;
|
||||||
|
float top = gl_TexCoord[0].y + range.y;
|
||||||
|
float right = gl_TexCoord[0].x + range.x;
|
||||||
|
float bottom = gl_TexCoord[0].y - range.y;
|
||||||
|
|
||||||
|
vec4 topLeftColor = texture2D(rubyTexture, (floor(vec2(left, top) / texelSize) + 0.5) * texelSize);
|
||||||
|
vec4 bottomRightColor = texture2D(rubyTexture, (floor(vec2(right, bottom) / texelSize) + 0.5) * texelSize);
|
||||||
|
vec4 bottomLeftColor = texture2D(rubyTexture, (floor(vec2(left, bottom) / texelSize) + 0.5) * texelSize);
|
||||||
|
vec4 topRightColor = texture2D(rubyTexture, (floor(vec2(right, top) / texelSize) + 0.5) * texelSize);
|
||||||
|
|
||||||
|
vec2 border = clamp(round(gl_TexCoord[0] / texelSize) * texelSize, vec2(left, bottom), vec2(right, top));
|
||||||
|
|
||||||
|
float totalArea = 4.0 * range.x * range.y;
|
||||||
|
|
||||||
|
vec4 averageColor;
|
||||||
|
averageColor = ((border.x - left) * (top - border.y) / totalArea) * topLeftColor;
|
||||||
|
averageColor += ((right - border.x) * (border.y - bottom) / totalArea) * bottomRightColor;
|
||||||
|
averageColor += ((border.x - left) * (border.y - bottom) / totalArea) * bottomLeftColor;
|
||||||
|
averageColor += ((right - border.x) * (top - border.y) / totalArea) * topRightColor;
|
||||||
|
|
||||||
|
gl_FragColor = averageColor;
|
||||||
|
}
|
||||||
|
]]></fragment>
|
||||||
|
</shader>
|
|
@ -0,0 +1,55 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<shader language="GLSL">
|
||||||
|
<vertex><![CDATA[
|
||||||
|
uniform vec2 rubyTextureSize;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec4 offsetx;
|
||||||
|
vec4 offsety;
|
||||||
|
|
||||||
|
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
|
||||||
|
|
||||||
|
offsetx.x = 1.0 / rubyTextureSize.x;
|
||||||
|
offsetx.y = 0.0;
|
||||||
|
offsetx.w = 0.0;
|
||||||
|
offsetx.z = 0.0;
|
||||||
|
offsety.y = 1.0 / rubyTextureSize.y;
|
||||||
|
offsety.x = 0.0;
|
||||||
|
offsety.w = 0.0;
|
||||||
|
offsety.z = 0.0;
|
||||||
|
|
||||||
|
gl_TexCoord[0] = gl_MultiTexCoord0; //center
|
||||||
|
gl_TexCoord[1] = gl_TexCoord[0] - offsetx; //left
|
||||||
|
gl_TexCoord[2] = gl_TexCoord[0] + offsetx; //right
|
||||||
|
gl_TexCoord[3] = gl_TexCoord[0] - offsety; //top
|
||||||
|
gl_TexCoord[4] = gl_TexCoord[0] + offsety; //bottom
|
||||||
|
}
|
||||||
|
]]></vertex>
|
||||||
|
|
||||||
|
<fragment filter="nearest"><![CDATA[
|
||||||
|
uniform sampler2D rubyTexture;
|
||||||
|
uniform vec2 rubyTextureSize;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec4 colD, colF, colB, colH, col, tmp;
|
||||||
|
vec2 sel;
|
||||||
|
|
||||||
|
col = texture2DProj(rubyTexture, gl_TexCoord[0]); //central (can be E0-E3)
|
||||||
|
colD = texture2DProj(rubyTexture, gl_TexCoord[1]); //D (left)
|
||||||
|
colF = texture2DProj(rubyTexture, gl_TexCoord[2]); //F (right)
|
||||||
|
colB = texture2DProj(rubyTexture, gl_TexCoord[3]); //B (top)
|
||||||
|
colH = texture2DProj(rubyTexture, gl_TexCoord[4]); //H (bottom)
|
||||||
|
|
||||||
|
sel = fract(gl_TexCoord[0].xy * rubyTextureSize.xy); //where are we (E0-E3)? E0 is default
|
||||||
|
|
||||||
|
if(sel.y >= 0.5) { tmp = colB; colB = colH; colH = tmp; } //E1 (or E3): swap B and H
|
||||||
|
if(sel.x >= 0.5) { tmp = colF; colF = colD; colD = tmp; } //E2 (or E3): swap D and F
|
||||||
|
|
||||||
|
if(colB == colD && colB != colF && colD != colH) { //do the Scale2x rule
|
||||||
|
col = colD;
|
||||||
|
}
|
||||||
|
|
||||||
|
gl_FragColor = col;
|
||||||
|
}
|
||||||
|
]]></fragment>
|
||||||
|
</shader>
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<shader language="HLSL">
|
||||||
|
<source><![CDATA[
|
||||||
|
texture rubyTexture;
|
||||||
|
|
||||||
|
float4 vec;
|
||||||
|
|
||||||
|
sampler s0 = sampler_state { texture = <rubyTexture>; };
|
||||||
|
float3 LightColor = { 1.0, 0.7, 0.5 };
|
||||||
|
float3 DarkColor = { 0.2, 0.05, 0.0 };
|
||||||
|
|
||||||
|
float4 DiffColorPass(in float2 Tex : TEXCOORD0) : COLOR0
|
||||||
|
{
|
||||||
|
vec.x = 0.5;
|
||||||
|
vec.y = 1.0;
|
||||||
|
float3 scnColor = LightColor * tex2D(s0, Tex).xyz;
|
||||||
|
float3 grayXfer = float3(0.3, 0.59, 0.11);
|
||||||
|
float gray = dot(grayXfer, scnColor);
|
||||||
|
float3 muted = lerp(scnColor, gray.xxx, vec.x);
|
||||||
|
float3 sepia = lerp(DarkColor, LightColor, gray);
|
||||||
|
float3 result = lerp(muted, sepia, vec.y);
|
||||||
|
return float4(result, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Technique T0
|
||||||
|
{
|
||||||
|
pass p0 { PixelShader = compile ps_2_0 DiffColorPass(); }
|
||||||
|
}
|
||||||
|
]]></source>
|
||||||
|
</shader>
|
Loading…
Reference in New Issue