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);