diff --git a/bsnes/nall/intrinsics.hpp b/bsnes/nall/intrinsics.hpp index 45d25eb2..413ef593 100755 --- a/bsnes/nall/intrinsics.hpp +++ b/bsnes/nall/intrinsics.hpp @@ -20,6 +20,7 @@ struct Intrinsics { #define COMPILER_VISUALC Intrinsics::Compiler Intrinsics::compiler() { return Intrinsics::Compiler::VisualC; } #else + #warning "unable to detect compiler" #define COMPILER_UNKNOWN Intrinsics::Compiler Intrinsics::compiler() { return Intrinsics::Compiler::Unknown; } #endif @@ -37,8 +38,9 @@ struct Intrinsics { #define PLATFORM_WIN Intrinsics::Platform Intrinsics::platform() { return Intrinsics::Platform::Windows; } #else + #warning "unable to detect platform" #define PLATFORM_UNKNOWN - + Intrinsics::Platform Intrinsics::platform() { return Intrinsics::Platform::Unknown; } #endif /* Endian detection */ @@ -52,9 +54,10 @@ struct Intrinsics { #define ARCH_MSB Intrinsics::Endian Intrinsics::endian() { return Intrinsics::Endian::MSB; } #else + #warning "unable to detect endian" #define ENDIAN_UNKNOWN #define ARCH_UNKNOWN - Intrinsics::Endian Intrinsics::endia() { return Intrinsics::Endian::Unknown; } + Intrinsics::Endian Intrinsics::endian() { return Intrinsics::Endian::Unknown; } #endif #endif diff --git a/bsnes/nall/reference_array.hpp b/bsnes/nall/reference_array.hpp index b01ae8c0..bf96802d 100755 --- a/bsnes/nall/reference_array.hpp +++ b/bsnes/nall/reference_array.hpp @@ -36,6 +36,13 @@ namespace nall { buffersize = newsize; } + template + bool append(const T& data, Args&&... args) { + bool result = append(data); + append(std::forward(args)...); + return result; + } + bool append(const T data) { for(unsigned index = 0; index < buffersize; index++) { if(pool[index] == &data) return false; diff --git a/bsnes/ui/base.hpp b/bsnes/ui/base.hpp index 52c066d7..bc22c6c6 100755 --- a/bsnes/ui/base.hpp +++ b/bsnes/ui/base.hpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -32,6 +33,7 @@ struct Application { bool quit; bool pause; bool autopause; + bool compositionEnable; string basepath; string userpath; diff --git a/bsnes/ui/config/config.cpp b/bsnes/ui/config/config.cpp index 546531e3..d8f46b62 100755 --- a/bsnes/ui/config/config.cpp +++ b/bsnes/ui/config/config.cpp @@ -19,12 +19,14 @@ Config::Config() { attach(video.fullScreenMode = 0, "Video::FullScreenMode"); attach(video.startFullScreen = false, "Video::StartFullScreen"); + attach(video.compositionMode = 0, "Video::CompositionMode"); attach(audio.driver = "", "Audio::Driver"); attach(audio.synchronize = true, "Audio::Synchronize"); attach(audio.mute = false, "Audio::Mute"); attach(audio.volume = 100, "Audio::Volume"); attach(audio.latency = 60, "Audio::Latency"); + attach(audio.resampler = "sinc", "Audio::Resampler"); attach(audio.frequency = 48000, "Audio::Frequency::Native"); attach(audio.frequencyNES = 1789772, "Audio::Frequency::NES"); diff --git a/bsnes/ui/config/config.hpp b/bsnes/ui/config/config.hpp index a5fdaf1a..a20041bd 100755 --- a/bsnes/ui/config/config.hpp +++ b/bsnes/ui/config/config.hpp @@ -15,6 +15,7 @@ struct Config : public configuration { unsigned gamma; unsigned fullScreenMode; + unsigned compositionMode; bool startFullScreen; } video; @@ -25,6 +26,7 @@ struct Config : public configuration { bool mute; unsigned volume; unsigned latency; + string resampler; unsigned frequency; unsigned frequencyNES; diff --git a/bsnes/ui/input/gameboy.cpp b/bsnes/ui/input/gameboy.cpp index 5b5f7357..c8b9bbe2 100755 --- a/bsnes/ui/input/gameboy.cpp +++ b/bsnes/ui/input/gameboy.cpp @@ -35,9 +35,7 @@ GameBoyController::GameBoyController() { select.mapping = "KB0::Apostrophe"; start.mapping = "KB0::Return"; - append(up); append(down); append(left); append(right); - append(b); append(a); append(select); append(start); - append(bTurbo); append(aTurbo); + append(up, down, left, right, b, a, select, start, bTurbo, aTurbo); } // diff --git a/bsnes/ui/input/nes.cpp b/bsnes/ui/input/nes.cpp index 95f5bbf0..60703a0e 100755 --- a/bsnes/ui/input/nes.cpp +++ b/bsnes/ui/input/nes.cpp @@ -35,9 +35,7 @@ NesGamepad::NesGamepad() { select.mapping = "KB0::Apostrophe"; start.mapping = "KB0::Return"; - append(up); append(down); append(left); append(right); - append(b); append(a); append(select); append(start); - append(bTurbo); append(aTurbo); + append(up, down, left, right, b,a, select, start, bTurbo, aTurbo); } // @@ -58,6 +56,5 @@ NesPort2Input::NesPort2Input() { NesInput::NesInput() { name = "NES"; - append(port1); - append(port2); + append(port1, port1); } diff --git a/bsnes/ui/input/snes.cpp b/bsnes/ui/input/snes.cpp index e2e7ad5d..e08c5606 100755 --- a/bsnes/ui/input/snes.cpp +++ b/bsnes/ui/input/snes.cpp @@ -8,8 +8,8 @@ int16_t SnesGamepad::poll(unsigned n) { case SNES::Input::JoypadID::A: return a.poll() | aTurbo.poll(); case SNES::Input::JoypadID::Y: return y.poll() | yTurbo.poll(); case SNES::Input::JoypadID::X: return x.poll() | xTurbo.poll(); - case SNES::Input::JoypadID::L: return l.poll(); - case SNES::Input::JoypadID::R: return r.poll(); + case SNES::Input::JoypadID::L: return l.poll() | lTurbo.poll(); + case SNES::Input::JoypadID::R: return r.poll() | rTurbo.poll(); case SNES::Input::JoypadID::Select: return select.poll(); case SNES::Input::JoypadID::Start: return start.poll(); } @@ -23,6 +23,7 @@ SnesGamepad::SnesGamepad(const string &name, bool defaultBindings) { b.name = "B", a.name = "A", y.name = "Y", x.name = "X"; l.name = "L", r.name = "R", select.name = "Select", start.name = "Start"; bTurbo.name = "Turbo B", aTurbo.name = "Turbo A", yTurbo.name = "Turbo Y", xTurbo.name = "Turbo X"; + lTurbo.name = "Turbo L", rTurbo.name = "Turbo R"; if(defaultBindings) { up.mapping = "KB0::Up"; @@ -39,10 +40,8 @@ SnesGamepad::SnesGamepad(const string &name, bool defaultBindings) { start.mapping = "KB0::Return"; } - append(up); append(down); append(left); append(right); - append(b); append(a); append(y); append(x); - append(l); append(r); append(select); append(start); - append(bTurbo); append(aTurbo); append(yTurbo); append(xTurbo); + append(up, down, left, right, b, a, y, x, l, r, select, start); + append(bTurbo, aTurbo, yTurbo, xTurbo, lTurbo, rTurbo); } // @@ -70,8 +69,7 @@ SnesMouse::SnesMouse(const string &name, bool defaultBindings) { right.mapping = "MS0::Button2"; } - append(xaxis); append(yaxis); - append(left); append(right); + append(xaxis, yaxis, left, right); } // @@ -103,8 +101,7 @@ SnesSuperScope::SnesSuperScope(const string &name, bool defaultBindings) { pause.mapping = "KB0::P"; } - append(xaxis); append(yaxis); - append(trigger); append(cursor); append(turbo); append(pause); + append(xaxis, yaxis, trigger, cursor, turbo, pause); } // @@ -132,8 +129,7 @@ SnesJustifier::SnesJustifier(const string &name, bool defaultBindings) { start.mapping = "MS0::Button2"; } - append(xaxis), append(yaxis); - append(trigger), append(start); + append(xaxis, yaxis, trigger, start); } // @@ -184,6 +180,5 @@ justifier2("Justifier - Port 2", false) SnesInput::SnesInput() { name = "SNES"; - append(port1); - append(port2); + append(port1, port2); } diff --git a/bsnes/ui/input/snes.hpp b/bsnes/ui/input/snes.hpp index 65925589..a9e343a2 100755 --- a/bsnes/ui/input/snes.hpp +++ b/bsnes/ui/input/snes.hpp @@ -3,6 +3,7 @@ struct SnesGamepad : TertiaryInput { DigitalInput b, a, y, x; DigitalInput l, r, select, start; TurboInput bTurbo, aTurbo, yTurbo, xTurbo; + TurboInput lTurbo, rTurbo; int16_t poll(unsigned n); SnesGamepad(const string &name, bool defaultBindings); diff --git a/bsnes/ui/interface/interface.cpp b/bsnes/ui/interface/interface.cpp index 26b4d134..3c714e97 100755 --- a/bsnes/ui/interface/interface.cpp +++ b/bsnes/ui/interface/interface.cpp @@ -44,7 +44,15 @@ void Interface::setController(unsigned port, unsigned device) { } void Interface::updateDSP() { + audio.set(Audio::Frequency, config->audio.frequency); + audio.set(Audio::Latency, config->audio.latency); + + if(config->audio.resampler == "linear" ) dspaudio.setResampler(DSP::ResampleEngine::Linear); + if(config->audio.resampler == "hermite") dspaudio.setResampler(DSP::ResampleEngine::Hermite); + if(config->audio.resampler == "sinc" ) dspaudio.setResampler(DSP::ResampleEngine::Sinc); + dspaudio.setResamplerFrequency(config->audio.frequency); dspaudio.setVolume(config->audio.mute == false ? (double)config->audio.volume / 100.0 : 0.0); + switch(mode()) { case Mode::NES: return dspaudio.setFrequency(config->audio.frequencyNES); case Mode::SNES: return dspaudio.setFrequency(config->audio.frequencySNES); diff --git a/bsnes/ui/main.cpp b/bsnes/ui/main.cpp index 5966950d..9a7a5c18 100755 --- a/bsnes/ui/main.cpp +++ b/bsnes/ui/main.cpp @@ -27,7 +27,7 @@ void Application::run() { } Application::Application(int argc, char **argv) { - title = "bsnes v083.08"; + title = "bsnes v083.09"; application = this; quit = false; @@ -56,6 +56,9 @@ Application::Application(int argc, char **argv) { boldFont = { fontFamily, "8, Bold" }; titleFont = { fontFamily, "16, Bold" }; + compositionEnable = compositor::enabled(); + if(config->video.compositionMode == 2) compositor::enable(false); + windowManager = new WindowManager; mainWindow = new MainWindow; fileBrowser = new FileBrowser; @@ -104,6 +107,7 @@ Application::Application(int argc, char **argv) { interface->unloadCartridge(); windowManager->saveGeometry(); + if(compositionEnable) compositor::enable(true); } Application::~Application() { diff --git a/bsnes/ui/settings/advanced.cpp b/bsnes/ui/settings/advanced.cpp index 83d8ae05..f5b8e237 100755 --- a/bsnes/ui/settings/advanced.cpp +++ b/bsnes/ui/settings/advanced.cpp @@ -16,7 +16,7 @@ AdvancedSettings::AdvancedSettings() { RadioBox::group(focusPolicy[0], focusPolicy[1], focusPolicy[2]); focusPolicy[config->input.focusPolicy].setChecked(); aboutLabel.setFont(application->boldFont); - aboutLabel.setText("bsnes author: byuu license: GPLv3 website: http://byuu.org/"); + aboutLabel.setText("bsnes author: byuu license: GPLv3 website: byuu.org"); lstring list; diff --git a/bsnes/ui/settings/audio.cpp b/bsnes/ui/settings/audio.cpp index f934c5ea..e9b3baa1 100755 --- a/bsnes/ui/settings/audio.cpp +++ b/bsnes/ui/settings/audio.cpp @@ -23,6 +23,33 @@ void AudioSlider::setPosition(unsigned position) { AudioSettings::AudioSettings() { title.setFont(application->titleFont); title.setText("Audio Settings"); + + outputLabel.setFont(application->boldFont); + outputLabel.setText("Output settings:"); + + frequencyLabel.setText("Frequency:"); + frequencySelection.append("32000hz"); + frequencySelection.append("44100hz"); + frequencySelection.append("48000hz"); + frequencySelection.append("96000hz"); + + latencyLabel.setText("Latency:"); + latencySelection.append( "40ms"); + latencySelection.append( "60ms"); + latencySelection.append( "80ms"); + latencySelection.append("100ms"); + latencySelection.append("120ms"); + + resamplerLabel.setText("Resampler:"); + resamplerSelection.append("Linear"); + resamplerSelection.append("Hermite"); + resamplerSelection.append("Sinc"); + + volume.name.setText("Volume:"); + volume.slider.setLength(201); + volume.base = 100; + volume.step = 1; + frequencyAdjustmentLabel.setFont(application->boldFont); frequencyAdjustmentLabel.setText("Frequency: (lower to reduce audio crackling; raise to reduce video tearing)"); @@ -41,39 +68,79 @@ AudioSettings::AudioSettings() { gameBoy.base = 4194304; gameBoy.step = 131; - outputAdjustmentLabel.setFont(application->boldFont); - outputAdjustmentLabel.setText("Output:"); - - volume.name.setText("Volume:"); - volume.slider.setLength(201); - volume.base = 100; - volume.step = 1; - append(title, ~0, 0, 5); + append(outputLabel, ~0, 0); + append(outputLayout, ~0, 0, 5); + outputLayout.append(frequencyLabel, 0, 0, 5); + outputLayout.append(frequencySelection, ~0, 0, 5); + outputLayout.append(latencyLabel, 0, 0, 5); + outputLayout.append(latencySelection, ~0, 0, 5); + outputLayout.append(resamplerLabel, 0, 0, 5); + outputLayout.append(resamplerSelection, ~0, 0); + append(volume, ~0, 0, 5); append(frequencyAdjustmentLabel, ~0, 0); append(nes, ~0, 0); append(snes, ~0, 0); - append(gameBoy, ~0, 0, 5); - append(outputAdjustmentLabel, ~0, 0); - append(volume, ~0, 0); + append(gameBoy, ~0, 0); + + frequencySelection.setSelection( + config->audio.frequency == 32000 ? 0 : + config->audio.frequency == 44100 ? 1 : + config->audio.frequency == 48000 ? 2 : + config->audio.frequency == 96000 ? 3 : 0 + ); + + latencySelection.setSelection( + config->audio.latency == 40 ? 0 : + config->audio.latency == 60 ? 1 : + config->audio.latency == 80 ? 2 : + config->audio.latency == 100 ? 3 : + config->audio.latency == 120 ? 4 : 0 + ); + + resamplerSelection.setSelection( + config->audio.resampler == "linear" ? 0 : + config->audio.resampler == "hermite" ? 1 : + config->audio.resampler == "sinc" ? 2 : 0 + ); + + volume.setPosition(config->audio.volume); nes.setPosition(config->audio.frequencyNES); snes.setPosition(config->audio.frequencySNES); gameBoy.setPosition(config->audio.frequencyGameBoy); - volume.setPosition(config->audio.volume); - nes.slider.onChange = snes.slider.onChange = gameBoy.slider.onChange = - volume.slider.onChange = + frequencySelection.onChange = latencySelection.onChange = resamplerSelection.onChange = + volume.slider.onChange = nes.slider.onChange = snes.slider.onChange = gameBoy.slider.onChange = { &AudioSettings::synchronize, this }; synchronize(); } void AudioSettings::synchronize() { + config->audio.frequency = + frequencySelection.selection() == 0 ? 32000 : + frequencySelection.selection() == 1 ? 44100 : + frequencySelection.selection() == 2 ? 48000 : + frequencySelection.selection() == 3 ? 96000 : 48000; + + config->audio.latency = + latencySelection.selection() == 0 ? 40 : + latencySelection.selection() == 1 ? 60 : + latencySelection.selection() == 2 ? 80 : + latencySelection.selection() == 3 ? 100 : + latencySelection.selection() == 4 ? 120 : 60; + + config->audio.resampler = + resamplerSelection.selection() == 0 ? "linear" : + resamplerSelection.selection() == 1 ? "hermite" : + resamplerSelection.selection() == 2 ? "sinc" : "sinc"; + + config->audio.volume = volume.position(); + config->audio.frequencyNES = nes.position(); config->audio.frequencySNES = snes.position(); config->audio.frequencyGameBoy = gameBoy.position(); - config->audio.volume = volume.position(); nes.value.setText({ nes.position(), "hz" }); snes.value.setText({ snes.position(), "hz" }); diff --git a/bsnes/ui/settings/audio.hpp b/bsnes/ui/settings/audio.hpp index 78abc331..a647d122 100755 --- a/bsnes/ui/settings/audio.hpp +++ b/bsnes/ui/settings/audio.hpp @@ -13,12 +13,19 @@ struct AudioSlider : HorizontalLayout { struct AudioSettings : SettingsLayout { Label title; + Label outputLabel; + HorizontalLayout outputLayout; + Label frequencyLabel; + ComboBox frequencySelection; + Label latencyLabel; + ComboBox latencySelection; + Label resamplerLabel; + ComboBox resamplerSelection; + AudioSlider volume; Label frequencyAdjustmentLabel; AudioSlider nes; AudioSlider snes; AudioSlider gameBoy; - Label outputAdjustmentLabel; - AudioSlider volume; void synchronize(); AudioSettings(); diff --git a/bsnes/ui/settings/video.cpp b/bsnes/ui/settings/video.cpp index cb0a651b..47fd2ed0 100755 --- a/bsnes/ui/settings/video.cpp +++ b/bsnes/ui/settings/video.cpp @@ -29,6 +29,12 @@ VideoSettings::VideoSettings() { fullScreen[1].setText("Scale"); fullScreen[2].setText("Stretch"); RadioBox::group(fullScreen[0], fullScreen[1], fullScreen[2]); + compositorLabel.setText("Disable window compositor:"); + compositorLabel.setFont(application->boldFont); + compositor[0].setText("Never"); + compositor[1].setText("Fullscreen"); + compositor[2].setText("Always"); + RadioBox::group(compositor[0], compositor[1], compositor[2]); append(title, ~0, 0, 5); append(colorAdjustment, ~0, 0); @@ -39,10 +45,15 @@ VideoSettings::VideoSettings() { append(overscanHorizontal, ~0, 0); append(overscanVertical, ~0, 0, 5); append(fullScreenMode, ~0, 0); - append(fullScreenLayout, ~0, 0); + append(fullScreenLayout, ~0, 0, 5); fullScreenLayout.append(fullScreen[0], ~0, 0, 5); fullScreenLayout.append(fullScreen[1], ~0, 0, 5); fullScreenLayout.append(fullScreen[2], ~0, 0); + append(compositorLabel, ~0, 0); + append(compositorLayout, ~0, 0); + compositorLayout.append(compositor[0], ~0, 0, 5); + compositorLayout.append(compositor[1], ~0, 0, 5); + compositorLayout.append(compositor[2], ~0, 0); brightness.slider.setPosition(config->video.brightness); contrast.slider.setPosition(config->video.contrast); @@ -50,13 +61,32 @@ VideoSettings::VideoSettings() { overscanHorizontal.slider.setPosition(config->video.maskOverscanHorizontal); overscanVertical.slider.setPosition(config->video.maskOverscanVertical); fullScreen[config->video.fullScreenMode].setChecked(); + compositor[config->video.compositionMode].setChecked(); synchronize(); brightness.slider.onChange = contrast.slider.onChange = gamma.slider.onChange = overscanHorizontal.slider.onChange = overscanVertical.slider.onChange = - fullScreen[0].onTick = fullScreen[1].onTick = fullScreen[2].onTick = { &VideoSettings::synchronize, this }; + + fullScreen[0].onTick = [&] { config->video.fullScreenMode = 0; }; + fullScreen[1].onTick = [&] { config->video.fullScreenMode = 1; }; + fullScreen[2].onTick = [&] { config->video.fullScreenMode = 2; }; + + compositor[0].onTick = [&] { + config->video.compositionMode = 0; + compositor::enable(application->compositionEnable); + }; + + compositor[1].onTick = [&] { + config->video.compositionMode = 1; + compositor::enable(application->compositionEnable && mainWindow->fullScreen() == false); + }; + + compositor[2].onTick = [&] { + config->video.compositionMode = 2; + compositor::enable(false); + }; } void VideoSettings::synchronize() { @@ -65,9 +95,9 @@ void VideoSettings::synchronize() { config->video.gamma = gamma.slider.position(); config->video.maskOverscanHorizontal = overscanHorizontal.slider.position(); config->video.maskOverscanVertical = overscanVertical.slider.position(); - if(fullScreen[0].checked()) config->video.fullScreenMode = 0; - if(fullScreen[1].checked()) config->video.fullScreenMode = 1; - if(fullScreen[2].checked()) config->video.fullScreenMode = 2; + if(fullScreen[0].checked()) { config->video.fullScreenMode = 0; } + if(fullScreen[1].checked()) { config->video.fullScreenMode = 1; } + if(fullScreen[2].checked()) { config->video.fullScreenMode = 2; } brightness.value.setText({ config->video.brightness, "%" }); contrast.value.setText({ config->video.contrast, "%" }); diff --git a/bsnes/ui/settings/video.hpp b/bsnes/ui/settings/video.hpp index 111df450..ce5866d1 100755 --- a/bsnes/ui/settings/video.hpp +++ b/bsnes/ui/settings/video.hpp @@ -18,6 +18,9 @@ struct VideoSettings : SettingsLayout { Label fullScreenMode; HorizontalLayout fullScreenLayout; RadioBox fullScreen[3]; + Label compositorLabel; + HorizontalLayout compositorLayout; + RadioBox compositor[3]; void synchronize(); VideoSettings(); diff --git a/bsnes/ui/utility/utility.cpp b/bsnes/ui/utility/utility.cpp index 9f5c3b38..cfcd5f31 100755 --- a/bsnes/ui/utility/utility.cpp +++ b/bsnes/ui/utility/utility.cpp @@ -109,6 +109,11 @@ void Utility::toggleFullScreen() { } resizeMainWindow(); + if(application->compositionEnable) { + if(config->video.compositionMode == 1) { + compositor::enable(mainWindow->fullScreen() == false); + } + } } void Utility::bindVideoFilter() { diff --git a/snesfilter/HQ2x/HQ2x.cpp b/snesfilter/HQ2x/HQ2x.cpp index 89aa1e70..46f88c15 100755 --- a/snesfilter/HQ2x/HQ2x.cpp +++ b/snesfilter/HQ2x/HQ2x.cpp @@ -4,7 +4,7 @@ using namespace nall; extern "C" { void filter_size(unsigned&, unsigned&); - void filter_render(uint16_t*, unsigned, const uint16_t*, unsigned, unsigned, unsigned); + void filter_render(uint32_t*, unsigned, const uint32_t*, unsigned, unsigned, unsigned); }; enum { @@ -34,6 +34,15 @@ const uint8_t hqTable[256] = { 4, 4, 6, 2, 4, 4, 6, 2, 5, 3, 1, 12, 5, 3, 1, 14, }; +static uint16_t rgb555(uint32_t C) { + return ((C >> 9) & 0x7c00) + ((C >> 6) & 0x03e0) + ((C >> 3) & 0x001f); +} + +static uint32_t rgb888(uint16_t C) { + return ((C & 0x7c00) << 9) + ((C & 0x03e0) << 6) + ((C & 0x001f) << 3) + + ((C & 0x7000) << 4) + ((C & 0x0380) << 1) + ((C & 0x001c) >> 2); +} + static void initialize() { static bool initialized = false; if(initialized == true) return; @@ -42,16 +51,12 @@ static void initialize() { yuvTable = new uint32_t[32768]; for(unsigned i = 0; i < 32768; i++) { - uint8_t R = (i >> 0) & 31; - uint8_t G = (i >> 5) & 31; - uint8_t B = (i >> 10) & 31; + uint32_t C = rgb888(i); - //bgr555->bgr888 - double r = (R << 3) | (R >> 2); - double g = (G << 3) | (G >> 2); - double b = (B << 3) | (B >> 2); + double r = (uint8_t)(C >> 16); + double g = (uint8_t)(C >> 8); + double b = (uint8_t)(C >> 0); - //bgr888->yuv double y = (r + g + b) * (0.25f * (63.5f / 48.0f)); double u = ((r - b) * 0.25f + 128.0f) * (7.5f / 7.0f); double v = ((g * 2.0f - r - b) * 0.125f + 128.0f) * (7.5f / 6.0f); @@ -147,18 +152,18 @@ dllexport void filter_size(unsigned &width, unsigned &height) { } dllexport void filter_render( - uint16_t *output, unsigned outputPitch, - const uint16_t *input, unsigned inputPitch, + uint32_t *output, unsigned outputPitch, + const uint32_t *input, unsigned inputPitch, unsigned width, unsigned height ) { initialize(); - outputPitch >>= 1, inputPitch >>= 1; + outputPitch >>= 2, inputPitch >>= 2; #pragma omp parallel for for(unsigned y = 0; y < height; y++) { - const uint16_t *in = input + y * inputPitch; - uint16_t *out0 = output + y * outputPitch * 2; - uint16_t *out1 = output + y * outputPitch * 2 + outputPitch; + const uint32_t *in = input + y * inputPitch; + uint32_t *out0 = output + y * outputPitch * 2; + uint32_t *out1 = output + y * outputPitch * 2 + outputPitch; int prevline = (y == 0 ? 0 : inputPitch); int nextline = (y == height - 1 ? 0 : inputPitch); @@ -168,15 +173,15 @@ dllexport void filter_render( *out1++ = 0; *out1++ = 0; for(unsigned x = 1; x < width - 1; x++) { - uint16_t A = *(in - prevline - 1); - uint16_t B = *(in - prevline + 0); - uint16_t C = *(in - prevline + 1); - uint16_t D = *(in - 1); - uint16_t E = *(in + 0); - uint16_t F = *(in + 1); - uint16_t G = *(in + nextline - 1); - uint16_t H = *(in + nextline + 0); - uint16_t I = *(in + nextline + 1); + uint16_t A = rgb555(*(in - prevline - 1)); + uint16_t B = rgb555(*(in - prevline + 0)); + uint16_t C = rgb555(*(in - prevline + 1)); + uint16_t D = rgb555(*(in - 1)); + uint16_t E = rgb555(*(in + 0)); + uint16_t F = rgb555(*(in + 1)); + uint16_t G = rgb555(*(in + nextline - 1)); + uint16_t H = rgb555(*(in + nextline + 0)); + uint16_t I = rgb555(*(in + nextline + 1)); uint32_t e = yuvTable[E] + diff_offset; uint8_t pattern; @@ -189,10 +194,10 @@ dllexport void filter_render( pattern |= diff(e, H) << 6; pattern |= diff(e, I) << 7; - *(out0 + 0) = blend(hqTable[pattern], E, A, B, D, F, H); pattern = rotate[pattern]; - *(out0 + 1) = blend(hqTable[pattern], E, C, F, B, H, D); pattern = rotate[pattern]; - *(out1 + 1) = blend(hqTable[pattern], E, I, H, F, D, B); pattern = rotate[pattern]; - *(out1 + 0) = blend(hqTable[pattern], E, G, D, H, B, F); + *(out0 + 0) = rgb888(blend(hqTable[pattern], E, A, B, D, F, H)); pattern = rotate[pattern]; + *(out0 + 1) = rgb888(blend(hqTable[pattern], E, C, F, B, H, D)); pattern = rotate[pattern]; + *(out1 + 1) = rgb888(blend(hqTable[pattern], E, I, H, F, D, B)); pattern = rotate[pattern]; + *(out1 + 0) = rgb888(blend(hqTable[pattern], E, G, D, H, B, F)); in++; out0 += 2; diff --git a/snesfilter/LQ2x/LQ2x.cpp b/snesfilter/LQ2x/LQ2x.cpp index 9da5f593..f5696266 100755 --- a/snesfilter/LQ2x/LQ2x.cpp +++ b/snesfilter/LQ2x/LQ2x.cpp @@ -4,7 +4,7 @@ using namespace nall; extern "C" { void filter_size(unsigned&, unsigned&); - void filter_render(uint16_t*, unsigned, const uint16_t*, unsigned, unsigned, unsigned); + void filter_render(uint32_t*, unsigned, const uint32_t*, unsigned, unsigned, unsigned); }; dllexport void filter_size(unsigned &width, unsigned &height) { @@ -13,33 +13,33 @@ dllexport void filter_size(unsigned &width, unsigned &height) { } dllexport void filter_render( - uint16_t *output, unsigned outputPitch, - const uint16_t *input, unsigned inputPitch, + uint32_t *output, unsigned outputPitch, + const uint32_t *input, unsigned inputPitch, unsigned width, unsigned height ) { - outputPitch >>= 1, inputPitch >>= 1; + outputPitch >>= 2, inputPitch >>= 2; #pragma omp parallel for for(unsigned y = 0; y < height; y++) { - const uint16_t *in = input + y * inputPitch; - uint16_t *out0 = output + y * outputPitch * 2; - uint16_t *out1 = output + y * outputPitch * 2 + outputPitch; + const uint32_t *in = input + y * inputPitch; + uint32_t *out0 = output + y * outputPitch * 2; + uint32_t *out1 = output + y * outputPitch * 2 + outputPitch; int prevline = (y == 0 ? 0 : inputPitch); int nextline = (y == height - 1 ? 0 : inputPitch); for(unsigned x = 0; x < width; x++) { - uint16_t A = *(input - prevline); - uint16_t B = (x > 0) ? *(input - 1) : *input; - uint16_t C = *input; - uint16_t D = (x < width - 1) ? *(input + 1) : *input; - uint16_t E = *(input++ + nextline); + uint32_t A = *(in - prevline); + uint32_t B = (x > 0) ? *(in - 1) : *in; + uint32_t C = *in; + uint32_t D = (x < width - 1) ? *(in + 1) : *in; + uint32_t E = *(in++ + nextline); if(A != E && B != D) { - *out0++ = (A == B ? C + A - ((C ^ A) & 0x0421) >> 1 : C); - *out0++ = (A == D ? C + A - ((C ^ A) & 0x0421) >> 1 : C); - *out1++ = (E == B ? C + E - ((C ^ E) & 0x0421) >> 1 : C); - *out1++ = (E == D ? C + E - ((C ^ E) & 0x0421) >> 1 : C); + *out0++ = (A == B ? C + A - ((C ^ A) & 0x010101) >> 1 : C); + *out0++ = (A == D ? C + A - ((C ^ A) & 0x010101) >> 1 : C); + *out1++ = (E == B ? C + E - ((C ^ E) & 0x010101) >> 1 : C); + *out1++ = (E == D ? C + E - ((C ^ E) & 0x010101) >> 1 : C); } else { *out0++ = C; *out0++ = C; diff --git a/snesfilter/Makefile b/snesfilter/Makefile index 6b632820..1a29918a 100755 --- a/snesfilter/Makefile +++ b/snesfilter/Makefile @@ -16,7 +16,6 @@ objects += out/Scanline-Light.filter objects += out/Scale2x.filter objects += out/LQ2x.filter objects += out/HQ2x.filter -objects += out/Overscan.filter objects += out/Phosphor3x.filter compile = $(cpp) $(link) $(flags) -o $@ -shared $< @@ -31,7 +30,6 @@ out/Scanline-Light.filter: Scanline/Scanline-Light.cpp Scanline/* out/Scale2x.filter: Scale2x/Scale2x.cpp Scale2x/* out/LQ2x.filter: LQ2x/LQ2x.cpp LQ2x/* out/HQ2x.filter: HQ2x/HQ2x.cpp HQ2x/* -out/Overscan.filter: Overscan/Overscan.cpp Overscan/* out/Phosphor3x.filter: Phosphor3x/Phosphor3x.cpp Phosphor3x/* build: $(objects) diff --git a/snesfilter/Overscan/Overscan.cpp b/snesfilter/Overscan/Overscan.cpp deleted file mode 100755 index 05500964..00000000 --- a/snesfilter/Overscan/Overscan.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include -#include -using namespace nall; - -extern "C" { - void filter_size(unsigned&, unsigned&); - void filter_render(uint16_t*, unsigned, const uint16_t*, unsigned, unsigned, unsigned); -}; - -dllexport void filter_size(unsigned &width, unsigned &height) { -} - -dllexport void filter_render( - uint16_t *output, unsigned outputPitch, - const uint16_t *input, unsigned inputPitch, - unsigned width, unsigned height -) { - outputPitch >>= 1, inputPitch >>= 1; - - #pragma omp parallel for - for(unsigned y = 0; y < height; y++) { - const uint16_t *in = input + y * inputPitch; - uint16_t *out = output + y * outputPitch; - for(unsigned x = 0; x < width; x++) { - uint16_t pixel = *in++; - if(x < 8 || x >= width - 8 || y < 8 || y >= height - 8) pixel = 0; - *out++ = pixel; - } - } -} diff --git a/snesfilter/Phosphor3x/Phosphor3x.cpp b/snesfilter/Phosphor3x/Phosphor3x.cpp index 4ed1e313..817fc9be 100755 --- a/snesfilter/Phosphor3x/Phosphor3x.cpp +++ b/snesfilter/Phosphor3x/Phosphor3x.cpp @@ -4,7 +4,7 @@ using namespace nall; extern "C" { void filter_size(unsigned&, unsigned&); - void filter_render(uint16_t*, unsigned, const uint16_t*, unsigned, unsigned, unsigned); + void filter_render(uint32_t*, unsigned, const uint32_t*, unsigned, unsigned, unsigned); }; dllexport void filter_size(unsigned &width, unsigned &height) { @@ -13,33 +13,45 @@ dllexport void filter_size(unsigned &width, unsigned &height) { } dllexport void filter_render( - uint16_t *output, unsigned outputPitch, - const uint16_t *input, unsigned inputPitch, + uint32_t *output, unsigned outputPitch, + const uint32_t *input, unsigned inputPitch, unsigned width, unsigned height ) { - outputPitch >>= 1, inputPitch >>= 1; + outputPitch >>= 2, inputPitch >>= 2; #pragma omp parallel for for(unsigned y = 0; y < height; y++) { - const uint16_t *in = input + y * inputPitch; - uint16_t *out0 = output + y * outputPitch * 3; - uint16_t *out1 = output + y * outputPitch * 3 + outputPitch; - uint16_t *out2 = output + y * outputPitch * 3 + outputPitch + outputPitch; + const uint32_t *in = input + y * inputPitch; + uint32_t *out0 = output + y * outputPitch * 3; + uint32_t *out1 = output + y * outputPitch * 3 + outputPitch; + uint32_t *out2 = output + y * outputPitch * 3 + outputPitch + outputPitch; for(unsigned x = 0; x < width; x++) { - uint16_t full = *in++, half = (full >> 1) & 0x3def; + uint32_t A = (x == 0 ? 0 : *(in - 1)); + uint32_t B = *in; + uint32_t C = (x == width - 1 ? 0 : *(in + 1)); - *out0++ = (full & 0x7c00); - *out1++ = (full & 0x7c00); - *out2++ = (half & 0x7c00); + uint8_t Ar = A >> 16, Ag = A >> 8, Ab = A >> 0; + uint8_t Br = B >> 16, Bg = B >> 8, Bb = B >> 0; + uint8_t Cr = C >> 16, Cg = C >> 8, Cb = C >> 0; - *out0++ = (full & 0x03e0); - *out1++ = (full & 0x03e0); - *out2++ = (half & 0x03e0); + A = ((Br >> 0) << 16) + ((Bg >> 1) << 8) + ((Ab >> 1) << 0); + B = ((Br >> 1) << 16) + ((Bg >> 0) << 8) + ((Bb >> 1) << 0); + C = ((Cr >> 1) << 16) + ((Bg >> 1) << 8) + ((Bb >> 0) << 0); - *out0++ = (full & 0x001f); - *out1++ = (full & 0x001f); - *out2++ = (half & 0x001f); + in++; + + *out0++ = A; + *out1++ = A; + *out2++ = (A & 0xf8f8f8) >> 1; + + *out0++ = B; + *out1++ = B; + *out2++ = (B & 0xf8f8f8) >> 1; + + *out0++ = C; + *out1++ = C; + *out2++ = (C & 0xf8f8f8) >> 1; } } } diff --git a/snesfilter/Pixellate2x/Pixellate2x.cpp b/snesfilter/Pixellate2x/Pixellate2x.cpp index c15a3b67..0376d191 100755 --- a/snesfilter/Pixellate2x/Pixellate2x.cpp +++ b/snesfilter/Pixellate2x/Pixellate2x.cpp @@ -4,7 +4,7 @@ using namespace nall; extern "C" { void filter_size(unsigned&, unsigned&); - void filter_render(uint16_t*, unsigned, const uint16_t*, unsigned, unsigned, unsigned); + void filter_render(uint32_t*, unsigned, const uint32_t*, unsigned, unsigned, unsigned); }; dllexport void filter_size(unsigned &width, unsigned &height) { @@ -13,20 +13,20 @@ dllexport void filter_size(unsigned &width, unsigned &height) { } dllexport void filter_render( - uint16_t *output, unsigned outputPitch, - const uint16_t *input, unsigned inputPitch, + uint32_t *output, unsigned outputPitch, + const uint32_t *input, unsigned inputPitch, unsigned width, unsigned height ) { - outputPitch >>= 1, inputPitch >>= 1; + outputPitch >>= 2, inputPitch >>= 2; #pragma omp parallel for for(unsigned y = 0; y < height; y++) { - const uint16_t *in = input + y * inputPitch; - uint16_t *out0 = output + y * outputPitch * 2; - uint16_t *out1 = output + y * outputPitch * 2 + outputPitch; + const uint32_t *in = input + y * inputPitch; + uint32_t *out0 = output + y * outputPitch * 2; + uint32_t *out1 = output + y * outputPitch * 2 + outputPitch; for(unsigned x = 0; x < width; x++) { - uint16_t pixel = *in++; + uint32_t pixel = *in++; *out0++ = pixel; *out0++ = pixel; *out1++ = pixel; diff --git a/snesfilter/Scale2x/Scale2x.cpp b/snesfilter/Scale2x/Scale2x.cpp index a98f08d4..6e5025dc 100755 --- a/snesfilter/Scale2x/Scale2x.cpp +++ b/snesfilter/Scale2x/Scale2x.cpp @@ -4,7 +4,7 @@ using namespace nall; extern "C" { void filter_size(unsigned&, unsigned&); - void filter_render(uint16_t*, unsigned, const uint16_t*, unsigned, unsigned, unsigned); + void filter_render(uint32_t*, unsigned, const uint32_t*, unsigned, unsigned, unsigned); }; dllexport void filter_size(unsigned &width, unsigned &height) { @@ -13,27 +13,27 @@ dllexport void filter_size(unsigned &width, unsigned &height) { } dllexport void filter_render( - uint16_t *output, unsigned outputPitch, - const uint16_t *input, unsigned inputPitch, + uint32_t *output, unsigned outputPitch, + const uint32_t *input, unsigned inputPitch, unsigned width, unsigned height ) { - outputPitch >>= 1, inputPitch >>= 1; + outputPitch >>= 2, inputPitch >>= 2; #pragma omp parallel for for(unsigned y = 0; y < height; y++) { - const uint16_t *in = input + y * inputPitch; - uint16_t *out0 = output + y * outputPitch * 2; - uint16_t *out1 = output + y * outputPitch * 2 + outputPitch; + const uint32_t *in = input + y * inputPitch; + uint32_t *out0 = output + y * outputPitch * 2; + uint32_t *out1 = output + y * outputPitch * 2 + outputPitch; int prevline = (y == 0 ? 0 : inputPitch); int nextline = (y == height - 1 ? 0 : inputPitch); for(unsigned x = 0; x < width; x++) { - uint16_t A = *(input - prevline); - uint16_t B = (x > 0) ? *(input - 1) : *input; - uint16_t C = *input; - uint16_t D = (x < width - 1) ? *(input + 1) : *input; - uint16_t E = *(input++ + nextline); + uint32_t A = *(in - prevline); + uint32_t B = (x > 0) ? *(in - 1) : *in; + uint32_t C = *in; + uint32_t D = (x < width - 1) ? *(in + 1) : *in; + uint32_t E = *(in++ + nextline); if(A != E && B != D) { *out0++ = (A == B ? A : C); diff --git a/snesfilter/Scanline/Scanline-Dark.cpp b/snesfilter/Scanline/Scanline-Dark.cpp index 68c1f72c..8ff69e40 100755 --- a/snesfilter/Scanline/Scanline-Dark.cpp +++ b/snesfilter/Scanline/Scanline-Dark.cpp @@ -4,7 +4,7 @@ using namespace nall; extern "C" { void filter_size(unsigned&, unsigned&); - void filter_render(uint16_t*, unsigned, const uint16_t*, unsigned, unsigned, unsigned); + void filter_render(uint32_t*, unsigned, const uint32_t*, unsigned, unsigned, unsigned); }; dllexport void filter_size(unsigned &width, unsigned &height) { @@ -12,17 +12,17 @@ dllexport void filter_size(unsigned &width, unsigned &height) { } dllexport void filter_render( - uint16_t *output, unsigned outputPitch, - const uint16_t *input, unsigned inputPitch, + uint32_t *output, unsigned outputPitch, + const uint32_t *input, unsigned inputPitch, unsigned width, unsigned height ) { - outputPitch >>= 1, inputPitch >>= 1; + outputPitch >>= 2, inputPitch >>= 2; #pragma omp parallel for for(unsigned y = 0; y < height; y++) { - const uint16_t *in = input + y * inputPitch; - uint16_t *out0 = output + y * outputPitch * 2; - uint16_t *out1 = output + y * outputPitch * 2 + outputPitch; + const uint32_t *in = input + y * inputPitch; + uint32_t *out0 = output + y * outputPitch * 2; + uint32_t *out1 = output + y * outputPitch * 2 + outputPitch; for(unsigned x = 0; x < width; x++) { *out0++ = *in++; diff --git a/snesfilter/Scanline/Scanline-Light.cpp b/snesfilter/Scanline/Scanline-Light.cpp index 6662a9c7..f38b8ef9 100755 --- a/snesfilter/Scanline/Scanline-Light.cpp +++ b/snesfilter/Scanline/Scanline-Light.cpp @@ -4,7 +4,7 @@ using namespace nall; extern "C" { void filter_size(unsigned&, unsigned&); - void filter_render(uint16_t*, unsigned, const uint16_t*, unsigned, unsigned, unsigned); + void filter_render(uint32_t*, unsigned, const uint32_t*, unsigned, unsigned, unsigned); }; dllexport void filter_size(unsigned &width, unsigned &height) { @@ -12,21 +12,21 @@ dllexport void filter_size(unsigned &width, unsigned &height) { } dllexport void filter_render( - uint16_t *output, unsigned outputPitch, - const uint16_t *input, unsigned inputPitch, + uint32_t *output, unsigned outputPitch, + const uint32_t *input, unsigned inputPitch, unsigned width, unsigned height ) { - outputPitch >>= 1, inputPitch >>= 1; + outputPitch >>= 2, inputPitch >>= 2; #pragma omp parallel for for(unsigned y = 0; y < height; y++) { - const uint16_t *in = input + y * inputPitch; - uint16_t *out0 = output + y * outputPitch * 2; - uint16_t *out1 = output + y * outputPitch * 2 + outputPitch; + const uint32_t *in = input + y * inputPitch; + uint32_t *out0 = output + y * outputPitch * 2; + uint32_t *out1 = output + y * outputPitch * 2 + outputPitch; for(unsigned x = 0; x < width; x++) { *out0++ = *in; - *out1++ = (*in++ & 0x7bde) >> 1; + *out1++ = (*in++ & 0xf8f8f8) >> 1; } } }