From 1ca4609079bf8a8ec21171238da344048daf0de1 Mon Sep 17 00:00:00 2001 From: Tim Allen Date: Tue, 30 May 2017 17:48:41 +1000 Subject: [PATCH] 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 --- higan/emulator/emulator.hpp | 2 +- higan/sfc/dsp/dsp.cpp | 9 ++++ higan/sfc/interface/interface.cpp | 4 +- nall/vector.hpp | 8 +-- ruby/input/joypad/xinput.cpp | 8 +-- ruby/video/gdi.cpp | 90 ++++++++++++++++++------------- ruby/video/xshm.cpp | 44 +++++++-------- 7 files changed, 95 insertions(+), 70 deletions(-) diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index c6b85b07..4f5a921b 100644 --- a/higan/emulator/emulator.hpp +++ b/higan/emulator/emulator.hpp @@ -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/"; diff --git a/higan/sfc/dsp/dsp.cpp b/higan/sfc/dsp/dsp.cpp index 8357d039..379aac17 100644 --- a/higan/sfc/dsp/dsp.cpp +++ b/higan/sfc/dsp/dsp.cpp @@ -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; } diff --git a/higan/sfc/interface/interface.cpp b/higan/sfc/interface/interface.cpp index 5e2c3825..83042276 100644 --- a/higan/sfc/interface/interface.cpp +++ b/higan/sfc/interface/interface.cpp @@ -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); diff --git a/nall/vector.hpp b/nall/vector.hpp index 6a99019c..3cd63a13 100644 --- a/nall/vector.hpp +++ b/nall/vector.hpp @@ -81,11 +81,11 @@ struct vector { auto take(uint offset) -> T; //iterator.hpp - auto begin() { return vector_iterator{*this, 0}; } - auto end() { return vector_iterator{*this, size()}; } + auto begin() -> vector_iterator { return vector_iterator{*this, 0}; } + auto end() -> vector_iterator { return vector_iterator{*this, size()}; } - auto begin() const { return vector_iterator_const{*this, 0}; } - auto end() const { return vector_iterator_const{*this, size()}; } + auto begin() const -> vector_iterator_const { return vector_iterator_const{*this, 0}; } + auto end() const -> vector_iterator_const { return vector_iterator_const{*this, size()}; } //utility.hpp auto sort(const function& comparator = [](auto& lhs, auto& rhs) { return lhs < rhs; }) -> void; diff --git a/ruby/input/joypad/xinput.cpp b/ruby/input/joypad/xinput.cpp index a5b9bf82..0999c74a 100644 --- a/ruby/input/joypad/xinput.cpp +++ b/ruby/input/joypad/xinput.cpp @@ -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); diff --git a/ruby/video/gdi.cpp b/ruby/video/gdi.cpp index f3afb8d8..dfee776c 100644 --- a/ruby/video/gdi.cpp +++ b/ruby/video/gdi.cpp @@ -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; + } } }; diff --git a/ruby/video/xshm.cpp b/ruby/video/xshm.cpp index 7631a71f..9f8f8b6c 100644 --- a/ruby/video/xshm.cpp +++ b/ruby/video/xshm.cpp @@ -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(); return true; } - if(name == Video::Filter && value.is()) { - settings.filter = value.get(); + if(name == Video::Filter && value.is()) { + settings.filter = value.get(); 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);