Update to v083r09 release.

byuu says:

Added frequency, latency, resampler selection to the audio settings
panel (I really only wanted it there for resampler selection ... having
three options matches the driver selection style though, so whatever.)
The linear/hermite sampler will double the framerate when running Game
Boy games, and sounds the same. Same framerate and sound quality on
SNES. But it will cause buzzing in many NES titles.
Also re-added the composition { never, fullscreen, always } modes.
I think that option is clutter, but it's just impossible to get good
audio+video on Windows 7 without it ...
Lastly, HQ2x was ported over, but not very well. I just convert source
pixels from RGB888 to RGB555, and output pixels in the opposite
direction.
Need someone good to port the diff() and blend functions over to RGB888
in a way that's not terribly slow.
This commit is contained in:
Tim Allen 2011-10-31 20:55:48 +11:00
parent 483f9f8f20
commit bf78e66027
26 changed files with 293 additions and 177 deletions

View File

@ -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

View File

@ -36,6 +36,13 @@ namespace nall {
buffersize = newsize;
}
template<typename... Args>
bool append(const T& data, Args&&... args) {
bool result = append(data);
append(std::forward<Args>(args)...);
return result;
}
bool append(const T data) {
for(unsigned index = 0; index < buffersize; index++) {
if(pool[index] == &data) return false;

View File

@ -2,6 +2,7 @@
#include <snes/snes.hpp>
#include <gameboy/gameboy.hpp>
#include <nall/compositor.hpp>
#include <nall/config.hpp>
#include <nall/directory.hpp>
#include <nall/dsp.hpp>
@ -32,6 +33,7 @@ struct Application {
bool quit;
bool pause;
bool autopause;
bool compositionEnable;
string basepath;
string userpath;

View File

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

View File

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

View File

@ -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);
}
//

View File

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

View File

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

View File

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

View File

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

View File

@ -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() {

View File

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

View File

@ -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" });

View File

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

View File

@ -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, "%" });

View File

@ -18,6 +18,9 @@ struct VideoSettings : SettingsLayout {
Label fullScreenMode;
HorizontalLayout fullScreenLayout;
RadioBox fullScreen[3];
Label compositorLabel;
HorizontalLayout compositorLayout;
RadioBox compositor[3];
void synchronize();
VideoSettings();

View File

@ -109,6 +109,11 @@ void Utility::toggleFullScreen() {
}
resizeMainWindow();
if(application->compositionEnable) {
if(config->video.compositionMode == 1) {
compositor::enable(mainWindow->fullScreen() == false);
}
}
}
void Utility::bindVideoFilter() {

View File

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

View File

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

View File

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

View File

@ -1,30 +0,0 @@
#include <nall/platform.hpp>
#include <nall/stdint.hpp>
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;
}
}
}

View File

@ -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;
}
}
}

View File

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

View File

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

View File

@ -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++;

View File

@ -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;
}
}
}