mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-10-05 10:21:42 +02:00
byuu says: Ported phoenix/Windows and phoenix/GTK+ over to the new system. There are some problems that need to be addressed: - Windows ComboBox height setting needs widget creation height to properly scale itself (make Widget::setGeometry virtual and override ComboBox::setGeometry) - Windows Canvas is completely broken - GTK+ Canvas is slow as shit compared to Qt Canvas, probably nothing I can do about it, have to do a very costly conversion because GTK+ is stupid and uses BGR like Nintendo - GTK+ listboxes are fucking insanely complicated to set up. Currently I just split the second-half of creation to the setHeaderText call, but when you don't call that, things explode - I'm probably going to have to completely destroy and recreate listboxes when changing the header text / column count - Qt resize code is still impossible to get right, it's not letting me size a window > 2/3rds of the screen size (it's in their docs) - I swear, Qt is the most painful API in the world to move/size windows with - now that Window is separate, it really needs geometry() and frameGeometry() as the two are quite different - I need a way to toggle window resizability for fixed layouts, Qt is once again going to be a nightmare as it lacks a way to do this other than fixed layouts - GTK+ currently explodes on bsnes, millions of console messages, wonderful - plenty more I'm forgetting One bit of really cool/good news though: I made Fixed/Horizontal/Vertical layouts external to phoenix itself. The code is included for all targets so that it's always there and compiled into one object, but the great news is that you can easily write your own layout widgets and they'll work on all toolkits instantly. That resize issue with bsnes was so simple it's annoying: my FixedLayout container was repositioning on geometry updates. Made it only do it once at creation like it should. bsnes now has a fancy resize, grow the window and get black borders, shrink it and the video shrinks with it. I plan to make it fancier with constraint settings (center, scale, stretch). Basically I want to turn the fullscreen setting into a general setting that also applies to windowed scaling. I will probably turn the video scale X sizes into regular items instead of radio boxes, so you can easily reset to a fixed size whenever you want. Update bsnes to remember width,height geometry as well and it should be quite nice.
140 lines
3.9 KiB
C++
Executable File
140 lines
3.9 KiB
C++
Executable File
Palette palette;
|
|
Filter filter;
|
|
Interface interface;
|
|
|
|
const uint8_t Palette::gammaRamp[32] = {
|
|
0x00, 0x01, 0x03, 0x06, 0x0a, 0x0f, 0x15, 0x1c,
|
|
0x24, 0x2d, 0x37, 0x42, 0x4e, 0x5b, 0x69, 0x78,
|
|
0x88, 0x90, 0x98, 0xa0, 0xa8, 0xb0, 0xb8, 0xc0,
|
|
0xc8, 0xd0, 0xd8, 0xe0, 0xe8, 0xf0, 0xf8, 0xff,
|
|
};
|
|
|
|
uint8_t Palette::contrastAdjust(uint8_t input) {
|
|
signed contrast = config.video.contrast - 100;
|
|
signed result = input - contrast + (2 * contrast * input + 127) / 255;
|
|
return max(0, min(255, result));
|
|
}
|
|
|
|
uint8_t Palette::brightnessAdjust(uint8_t input) {
|
|
signed brightness = config.video.brightness - 100;
|
|
signed result = input + brightness;
|
|
return max(0, min(255, result));
|
|
}
|
|
|
|
uint8_t Palette::gammaAdjust(uint8_t input) {
|
|
signed result = (signed)(pow(((double)input / 255.0), (double)config.video.gamma / 100.0) * 255.0 + 0.5);
|
|
return max(0, min(255, result));
|
|
}
|
|
|
|
void Palette::update() {
|
|
for(unsigned i = 0; i < 32768; i++) {
|
|
unsigned r = (i >> 10) & 31;
|
|
unsigned g = (i >> 5) & 31;
|
|
unsigned b = (i >> 0) & 31;
|
|
|
|
r = (r << 3) | (r >> 2);
|
|
g = (g << 3) | (g >> 2);
|
|
b = (b << 3) | (b >> 2);
|
|
|
|
if(config.video.useGammaRamp) {
|
|
r = gammaRamp[r >> 3];
|
|
g = gammaRamp[g >> 3];
|
|
b = gammaRamp[b >> 3];
|
|
}
|
|
|
|
if(config.video.contrast != 100) {
|
|
r = contrastAdjust(r);
|
|
g = contrastAdjust(g);
|
|
b = contrastAdjust(b);
|
|
}
|
|
|
|
if(config.video.brightness != 100) {
|
|
r = brightnessAdjust(r);
|
|
g = brightnessAdjust(g);
|
|
b = brightnessAdjust(b);
|
|
}
|
|
|
|
if(config.video.gamma != 100) {
|
|
r = gammaAdjust(r);
|
|
g = gammaAdjust(g);
|
|
b = gammaAdjust(b);
|
|
}
|
|
|
|
color[i] = (r << 16) | (g << 8) | (b << 0);
|
|
}
|
|
}
|
|
|
|
void Filter::size(unsigned &width, unsigned &height) {
|
|
if(opened() && dl_size) return dl_size(width, height);
|
|
}
|
|
|
|
void Filter::render(uint32_t *output, unsigned outpitch, const uint16_t *input, unsigned pitch, unsigned width, unsigned height) {
|
|
if(opened() && dl_render) return dl_render(palette.color, output, outpitch, input, pitch, width, height);
|
|
|
|
for(unsigned y = 0; y < height; y++) {
|
|
uint32_t *outputLine = output + y * (outpitch >> 2);
|
|
const uint16_t *inputLine = input + y * (pitch >> 1);
|
|
for(unsigned x = 0; x < width; x++) *outputLine++ = palette.color[*inputLine++];
|
|
}
|
|
}
|
|
|
|
void Interface::video_refresh(const uint16_t *data, unsigned width, unsigned height) {
|
|
bool interlace = (height >= 240);
|
|
bool overscan = (height == 239 || height == 478);
|
|
unsigned inpitch = interlace ? 1024 : 2048;
|
|
|
|
uint32_t *buffer;
|
|
unsigned outpitch;
|
|
|
|
if(config.video.region == 0 && (height == 239 || height == 478)) {
|
|
//NTSC overscan compensation (center image, remove 15 lines)
|
|
data += 7 * 1024;
|
|
if(height == 239) height = 224;
|
|
if(height == 478) height = 448;
|
|
}
|
|
|
|
if(config.video.region == 1 && (height == 224 || height == 448)) {
|
|
//PAL underscan compensation (center image, add 15 lines)
|
|
data -= 7 * 1024;
|
|
if(height == 224) height = 239;
|
|
if(height == 448) height = 478;
|
|
}
|
|
|
|
unsigned outwidth = width, outheight = height;
|
|
filter.size(outwidth, outheight);
|
|
|
|
if(video.lock(buffer, outpitch, outwidth, outheight)) {
|
|
filter.render(buffer, outpitch, data, inpitch, width, height);
|
|
video.unlock();
|
|
video.refresh();
|
|
}
|
|
|
|
static unsigned frameCounter = 0;
|
|
static time_t previous, current;
|
|
frameCounter++;
|
|
|
|
time(¤t);
|
|
if(current != previous) {
|
|
utility.setStatus({ "FPS: ", frameCounter });
|
|
frameCounter = 0;
|
|
previous = current;
|
|
}
|
|
}
|
|
|
|
void Interface::audio_sample(uint16_t left, uint16_t right) {
|
|
if(config.audio.mute) left = right = 0;
|
|
audio.sample(left, right);
|
|
}
|
|
|
|
void Interface::input_poll() {
|
|
}
|
|
|
|
int16_t Interface::input_poll(bool port, SNES::Input::Device device, unsigned index, unsigned id) {
|
|
if(config.settings.focusPolicy == 1 && mainWindow.focused() == false) return 0;
|
|
return inputMapper.poll(port, device, index, id);
|
|
}
|
|
|
|
void Interface::message(const string &text) {
|
|
MessageWindow::information(mainWindow, text);
|
|
}
|