mirror of https://github.com/bsnes-emu/bsnes.git
Update to v102r18 release.
byuu says: This WIP fixes all the critical pending issues I had open. I'm sure there's many more that simply didn't make their way into said list. So by all means, please report important issues you're aware of so they can get fixed. Changelog: - ruby: add variable texture support to GDI video driver [bug reported by Cydrak] - ruby: minor cleanups to XShm video driver - ruby: fix handling of up+down, left+right hat cases for XInput driver [bug reported by Cydrak] - nall: fixed vector class so that compilation with GCC 7.1 should succeed [SuperMikeMan] - sfc: initialize most DSP registers to random values to fix Magical Drop [Jonas Quinn] - sfc: lower PPU brightness when luma=0 from 50% scale to 25% scale; helps scenes like Final Fantasy III's intro
This commit is contained in:
parent
82c58527c3
commit
1ca4609079
|
@ -12,7 +12,7 @@ using namespace nall;
|
|||
|
||||
namespace Emulator {
|
||||
static const string Name = "higan";
|
||||
static const string Version = "102.17";
|
||||
static const string Version = "102.18";
|
||||
static const string Author = "byuu";
|
||||
static const string License = "GPLv3";
|
||||
static const string Website = "http://byuu.org/";
|
||||
|
|
|
@ -246,6 +246,15 @@ auto DSP::power() -> void {
|
|||
voice[n].vidx = n * 0x10;
|
||||
}
|
||||
|
||||
for(auto r : range(0x80)) {
|
||||
REG(r) = random(0x00);
|
||||
}
|
||||
|
||||
for(auto v : range(8)) {
|
||||
REG(v * 0x10 + ENVX) = 0;
|
||||
REG(v * 0x10 + OUTX) = 0;
|
||||
}
|
||||
|
||||
REG(FLG) = 0xe0;
|
||||
}
|
||||
|
||||
|
|
|
@ -139,7 +139,9 @@ auto Interface::videoColor(uint32 color) -> uint64 {
|
|||
uint b = color.bits(10,14);
|
||||
uint l = color.bits(15,18);
|
||||
|
||||
double L = (1.0 + l) / 16.0 * (l ? 1.0 : 0.5);
|
||||
//luma=0 is not 100% black; but it's much darker than normal linear scaling
|
||||
//exact effect seems to be analog; requires > 24-bit color depth to represent accurately
|
||||
double L = (1.0 + l) / 16.0 * (l ? 1.0 : 0.25);
|
||||
uint64 R = L * image::normalize(r, 5, 16);
|
||||
uint64 G = L * image::normalize(g, 5, 16);
|
||||
uint64 B = L * image::normalize(b, 5, 16);
|
||||
|
|
|
@ -81,11 +81,11 @@ struct vector {
|
|||
auto take(uint offset) -> T;
|
||||
|
||||
//iterator.hpp
|
||||
auto begin() { return vector_iterator<T>{*this, 0}; }
|
||||
auto end() { return vector_iterator<T>{*this, size()}; }
|
||||
auto begin() -> vector_iterator<T> { return vector_iterator<T>{*this, 0}; }
|
||||
auto end() -> vector_iterator<T> { return vector_iterator<T>{*this, size()}; }
|
||||
|
||||
auto begin() const { return vector_iterator_const<T>{*this, 0}; }
|
||||
auto end() const { return vector_iterator_const<T>{*this, size()}; }
|
||||
auto begin() const -> vector_iterator_const<T> { return vector_iterator_const<T>{*this, 0}; }
|
||||
auto end() const -> vector_iterator_const<T> { return vector_iterator_const<T>{*this, size()}; }
|
||||
|
||||
//utility.hpp
|
||||
auto sort(const function<bool (const T& lhs, const T& rhs)>& comparator = [](auto& lhs, auto& rhs) { return lhs < rhs; }) -> void;
|
||||
|
|
|
@ -55,10 +55,10 @@ struct InputJoypadXInput {
|
|||
|
||||
int16_t hatX = 0;
|
||||
int16_t hatY = 0;
|
||||
if(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP ) hatY = -32768;
|
||||
if(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN ) hatY = +32767;
|
||||
if(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT ) hatX = -32768;
|
||||
if(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) hatX = +32767;
|
||||
if(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP ) hatY -= 32767;
|
||||
if(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN ) hatY += 32767;
|
||||
if(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT ) hatX -= 32767;
|
||||
if(state.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) hatX += 32767;
|
||||
|
||||
assign(jp.hid, HID::Joypad::GroupID::Hat, 0, hatX);
|
||||
assign(jp.hid, HID::Joypad::GroupID::Hat, 1, hatY);
|
||||
|
|
|
@ -3,16 +3,18 @@
|
|||
struct VideoGDI : Video {
|
||||
~VideoGDI() { term(); }
|
||||
|
||||
uint32_t* buffer = nullptr;
|
||||
HBITMAP bitmap = nullptr;
|
||||
HDC bitmapdc = nullptr;
|
||||
BITMAPINFO bmi;
|
||||
struct Device {
|
||||
HBITMAP bitmap = nullptr;
|
||||
HDC dc = nullptr;
|
||||
BITMAPINFO info = {};
|
||||
} device;
|
||||
|
||||
struct {
|
||||
struct Settings {
|
||||
HWND handle = nullptr;
|
||||
|
||||
unsigned width = 0;
|
||||
unsigned height = 0;
|
||||
uint32_t* buffer = nullptr;
|
||||
uint width = 0;
|
||||
uint height = 0;
|
||||
} settings;
|
||||
|
||||
auto cap(const string& name) -> bool {
|
||||
|
@ -34,12 +36,38 @@ struct VideoGDI : Video {
|
|||
return false;
|
||||
}
|
||||
|
||||
auto lock(uint32_t*& data, unsigned& pitch, unsigned width, unsigned height) -> bool {
|
||||
settings.width = width;
|
||||
settings.height = height;
|
||||
auto lock(uint32_t*& data, uint& pitch, uint width, uint height) -> bool {
|
||||
if(!settings.buffer || settings.width != width || settings.height != height) {
|
||||
if(settings.buffer) {
|
||||
delete] settings.buffer;
|
||||
DeleteObject(device.bitmap);
|
||||
DeleteObject(device.dc);
|
||||
}
|
||||
settings.buffer = new uint32_t[width * height]();
|
||||
settings.width = width;
|
||||
settings.height = height;
|
||||
|
||||
pitch = 1024 * 4;
|
||||
return data = buffer;
|
||||
HDC hdc = GetDC(settings.handle);
|
||||
device.dc = CreateCompatibleDC(hdc);
|
||||
assert(device.dc);
|
||||
device.bitmap = CreateCompatibleBitmap(hdc, width, height);
|
||||
assert(device.bitmap);
|
||||
SelectObject(device.dc, device.bitmap);
|
||||
ReleaseDC(settings.handle, hdc);
|
||||
|
||||
memory::fill(&device.info, sizeof(BITMAPINFO));
|
||||
device.info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
device.info.bmiHeader.biWidth = width;
|
||||
device.info.bmiHeader.biHeight = -height;
|
||||
device.info.bmiHeader.biPlanes = 1;
|
||||
device.info.bmiHeader.biBitCount = 32;
|
||||
device.info.bmiHeader.biCompression = BI_RGB;
|
||||
device.info.bmiHeader.biSizeImage = width * height * sizeof(uint32_t);
|
||||
}
|
||||
|
||||
data = settings.buffer;
|
||||
pitch = settings.width * sizeof(uint32_t);
|
||||
return true;
|
||||
}
|
||||
|
||||
auto unlock() -> void {}
|
||||
|
@ -50,40 +78,26 @@ struct VideoGDI : Video {
|
|||
RECT rc;
|
||||
GetClientRect(settings.handle, &rc);
|
||||
|
||||
SetDIBits(bitmapdc, bitmap, 0, settings.height, (void*)buffer, &bmi, DIB_RGB_COLORS);
|
||||
SetDIBits(device.dc, device.bitmap, 0, settings.height, (void*)settings.buffer, &device.info, DIB_RGB_COLORS);
|
||||
HDC hdc = GetDC(settings.handle);
|
||||
StretchBlt(hdc, rc.left, rc.top, rc.right, rc.bottom, bitmapdc, 0, 1024 - settings.height, settings.width, settings.height, SRCCOPY);
|
||||
StretchBlt(hdc, rc.left, rc.top, rc.right, rc.bottom, device.dc, 0, -settings.height, settings.width, settings.height, SRCCOPY);
|
||||
ReleaseDC(settings.handle, hdc);
|
||||
}
|
||||
|
||||
auto init() -> bool {
|
||||
buffer = (uint32_t*)memory::allocate(1024 * 1024 * sizeof(uint32_t));
|
||||
|
||||
HDC hdc = GetDC(settings.handle);
|
||||
bitmapdc = CreateCompatibleDC(hdc);
|
||||
assert(bitmapdc);
|
||||
bitmap = CreateCompatibleBitmap(hdc, 1024, 1024);
|
||||
assert(bitmap);
|
||||
SelectObject(bitmapdc, bitmap);
|
||||
ReleaseDC(settings.handle, hdc);
|
||||
|
||||
memset(&bmi, 0, sizeof(BITMAPINFO));
|
||||
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
bmi.bmiHeader.biWidth = 1024;
|
||||
bmi.bmiHeader.biHeight = -1024;
|
||||
bmi.bmiHeader.biPlanes = 1;
|
||||
bmi.bmiHeader.biBitCount = 32; //biBitCount of 15 is invalid, biBitCount of 16 is really RGB555
|
||||
bmi.bmiHeader.biCompression = BI_RGB;
|
||||
bmi.bmiHeader.biSizeImage = 1024 * 1024 * sizeof(uint32_t);
|
||||
|
||||
settings.width = 256;
|
||||
settings.height = 256;
|
||||
settings.width = 0;
|
||||
settings.height = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
auto term() -> void {
|
||||
DeleteObject(bitmap);
|
||||
DeleteDC(bitmapdc);
|
||||
if(buffer) { memory::free(buffer); buffer = nullptr; }
|
||||
if(settings.buffer) {
|
||||
delete[] settings.buffer;
|
||||
DeleteObject(device.bitmap);
|
||||
DeleteDC(device.dc);
|
||||
settings.buffer = nullptr;
|
||||
device.bitmap = nullptr;
|
||||
device.dc = nullptr;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -13,25 +13,25 @@ struct VideoXShm : Video {
|
|||
|
||||
struct Device {
|
||||
Display* display = nullptr;
|
||||
signed screen = 0;
|
||||
signed depth = 0;
|
||||
int screen = 0;
|
||||
int depth = 0;
|
||||
Visual* visual = nullptr;
|
||||
Window window = 0;
|
||||
|
||||
XShmSegmentInfo shmInfo;
|
||||
XImage* image = nullptr;
|
||||
uint32_t* buffer = nullptr;
|
||||
unsigned width = 0;
|
||||
unsigned height = 0;
|
||||
uint width = 0;
|
||||
uint height = 0;
|
||||
} device;
|
||||
|
||||
struct Settings {
|
||||
uintptr_t handle = 0;
|
||||
unsigned filter = Video::FilterLinear;
|
||||
uint filter = Video::FilterLinear;
|
||||
|
||||
uint32_t* buffer = nullptr;
|
||||
unsigned width = 0;
|
||||
unsigned height = 0;
|
||||
uint width = 0;
|
||||
uint height = 0;
|
||||
} settings;
|
||||
|
||||
auto cap(const string& name) -> bool {
|
||||
|
@ -51,15 +51,15 @@ struct VideoXShm : Video {
|
|||
settings.handle = value.get<uintptr_t>();
|
||||
return true;
|
||||
}
|
||||
if(name == Video::Filter && value.is<unsigned>()) {
|
||||
settings.filter = value.get<unsigned>();
|
||||
if(name == Video::Filter && value.is<uint>()) {
|
||||
settings.filter = value.get<uint>();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
auto lock(uint32_t*& data, unsigned& pitch, unsigned width, unsigned height) -> bool {
|
||||
if(settings.buffer == nullptr || settings.width != width || settings.height != height) {
|
||||
auto lock(uint32_t*& data, uint& pitch, uint width, uint height) -> bool {
|
||||
if(!settings.buffer || settings.width != width || settings.height != height) {
|
||||
if(settings.buffer) delete[] settings.buffer;
|
||||
settings.width = width, settings.height = height;
|
||||
settings.buffer = new uint32_t[width * height + 16]; //+16 is padding for linear interpolation
|
||||
|
@ -74,36 +74,36 @@ struct VideoXShm : Video {
|
|||
}
|
||||
|
||||
auto clear() -> void {
|
||||
if(settings.buffer == nullptr) return;
|
||||
if(!settings.buffer) return;
|
||||
uint32_t* dp = settings.buffer;
|
||||
unsigned length = settings.width * settings.height;
|
||||
uint length = settings.width * settings.height;
|
||||
while(length--) *dp++ = 255u << 24;
|
||||
refresh();
|
||||
}
|
||||
|
||||
auto refresh() -> void {
|
||||
if(settings.buffer == nullptr) return;
|
||||
if(!settings.buffer) return;
|
||||
size();
|
||||
|
||||
float xratio = (float)settings.width / (float)device.width;
|
||||
float yratio = (float)settings.height / (float)device.height;
|
||||
|
||||
#pragma omp parallel for
|
||||
for(unsigned y = 0; y < device.height; y++) {
|
||||
for(uint y = 0; y < device.height; y++) {
|
||||
float ystep = y * yratio;
|
||||
float xstep = 0;
|
||||
|
||||
uint32_t* sp = settings.buffer + (unsigned)ystep * settings.width;
|
||||
uint32_t* sp = settings.buffer + (uint)ystep * settings.width;
|
||||
uint32_t* dp = device.buffer + y * device.width;
|
||||
|
||||
if(settings.filter == Video::FilterNearest) {
|
||||
for(unsigned x = 0; x < device.width; x++) {
|
||||
*dp++ = 255u << 24 | sp[(unsigned)xstep];
|
||||
for(uint x = 0; x < device.width; x++) {
|
||||
*dp++ = 255u << 24 | sp[(uint)xstep];
|
||||
xstep += xratio;
|
||||
}
|
||||
} else { //settings.filter == Video::FilterLinear
|
||||
for(unsigned x = 0; x < device.width; x++) {
|
||||
*dp++ = 255u << 24 | interpolate(xstep - (unsigned)xstep, sp[(unsigned)xstep], sp[(unsigned)xstep + 1]);
|
||||
for(uint x = 0; x < device.width; x++) {
|
||||
*dp++ = 255u << 24 | interpolate(xstep - (uint)xstep, sp[(uint)xstep], sp[(uint)xstep + 1]);
|
||||
xstep += xratio;
|
||||
}
|
||||
}
|
||||
|
@ -149,7 +149,7 @@ struct VideoXShm : Video {
|
|||
XNextEvent(device.display, &event);
|
||||
}
|
||||
|
||||
if(size() == false) return false;
|
||||
if(!size()) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -186,7 +186,7 @@ private:
|
|||
}
|
||||
|
||||
auto free() -> void {
|
||||
if(device.buffer == nullptr) return;
|
||||
if(!device.buffer) return;
|
||||
device.buffer = nullptr;
|
||||
XShmDetach(device.display, &device.shmInfo);
|
||||
XDestroyImage(device.image);
|
||||
|
|
Loading…
Reference in New Issue