Commit 1ca46090 authored by Tim Allen's avatar Tim Allen

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
parent 82c58527
Pipeline #8629441 failed with stage
in 10 minutes and 18 seconds
......@@ -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;
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);
}
pitch = 1024 * 4;
return data = buffer;
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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment