Libretro: Make NTSC filters output in 240p (faster & works better with shaders)

This commit is contained in:
Sour 2018-01-11 22:31:07 -05:00
parent 0b7b98f726
commit 4fc1cb107b
8 changed files with 115 additions and 82 deletions

View file

@ -40,7 +40,15 @@ BisqwitNtscFilter::BisqwitNtscFilter(int resDivider)
} }
uint32_t* outputBuffer = (uint32_t*)GetOutputBuffer(); uint32_t* outputBuffer = (uint32_t*)GetOutputBuffer();
DecodeFrame(120, 239 - GetOverscan().Bottom, _ppuOutputBuffer, outputBuffer + GetOverscan().GetScreenWidth() * 64 / _resDivider / _resDivider * (120 - GetOverscan().Top), (_isOddFrame ? 8 : 0) + 327360);
//Adjust outputbuffer to start at the middle of the picture
if(_keepVerticalRes) {
outputBuffer += GetOverscan().GetScreenWidth() * 8 / _resDivider * (120 - GetOverscan().Top);
} else {
outputBuffer += GetOverscan().GetScreenWidth() * 64 / _resDivider / _resDivider * (120 - GetOverscan().Top);
}
DecodeFrame(120, 239 - GetOverscan().Bottom, _ppuOutputBuffer, outputBuffer, (_isOddFrame ? 8 : 0) + 327360);
_workDone = true; _workDone = true;
} }
@ -68,7 +76,11 @@ void BisqwitNtscFilter::ApplyFilter(uint16_t *ppuOutputBuffer)
FrameInfo BisqwitNtscFilter::GetFrameInfo() FrameInfo BisqwitNtscFilter::GetFrameInfo()
{ {
OverscanDimensions overscan = GetOverscan(); OverscanDimensions overscan = GetOverscan();
return{ overscan.GetScreenWidth()*8/_resDivider, overscan.GetScreenHeight()*8/_resDivider, PPU::ScreenWidth, PPU::ScreenHeight, 4 }; if(_keepVerticalRes) {
return { overscan.GetScreenWidth() * 8 / _resDivider, overscan.GetScreenHeight(), PPU::ScreenWidth, PPU::ScreenHeight, 4 };
} else {
return { overscan.GetScreenWidth() * 8 / _resDivider, overscan.GetScreenHeight() * 8 / _resDivider, PPU::ScreenWidth, PPU::ScreenHeight, 4 };
}
} }
void BisqwitNtscFilter::OnBeforeApplyFilter() void BisqwitNtscFilter::OnBeforeApplyFilter()
@ -76,6 +88,8 @@ void BisqwitNtscFilter::OnBeforeApplyFilter()
PictureSettings pictureSettings = EmulationSettings::GetPictureSettings(); PictureSettings pictureSettings = EmulationSettings::GetPictureSettings();
NtscFilterSettings ntscSettings = EmulationSettings::GetNtscFilterSettings(); NtscFilterSettings ntscSettings = EmulationSettings::GetNtscFilterSettings();
_keepVerticalRes = ntscSettings.KeepVerticalResolution;
const double pi = std::atan(1.0) * 4; const double pi = std::atan(1.0) * 4;
int contrast = (int)((pictureSettings.Contrast + 1.0) * (pictureSettings.Contrast + 1.0) * 167941); int contrast = (int)((pictureSettings.Contrast + 1.0) * (pictureSettings.Contrast + 1.0) * 167941);
int saturation = (int)((pictureSettings.Saturation + 1.0) * (pictureSettings.Saturation + 1.0) * 144044); int saturation = (int)((pictureSettings.Saturation + 1.0) * (pictureSettings.Saturation + 1.0) * 144044);
@ -183,7 +197,10 @@ void BisqwitNtscFilter::DecodeFrame(int startRow, int endRow, uint16_t *ppuOutpu
int pixelsPerCycle = 8 / _resDivider; int pixelsPerCycle = 8 / _resDivider;
int phase = startPhase; int phase = startPhase;
int8_t rowSignal[256 * _signalsPerPixel]; int8_t rowSignal[256 * _signalsPerPixel];
uint32_t rowPixelGap = GetOverscan().GetScreenWidth() * pixelsPerCycle * pixelsPerCycle; uint32_t rowPixelGap = GetOverscan().GetScreenWidth() * pixelsPerCycle;
if(!_keepVerticalRes) {
rowPixelGap *= pixelsPerCycle;
}
uint32_t* orgBuffer = outputBuffer; uint32_t* orgBuffer = outputBuffer;
@ -199,18 +216,20 @@ void BisqwitNtscFilter::DecodeFrame(int startRow, int endRow, uint16_t *ppuOutpu
outputBuffer += rowPixelGap; outputBuffer += rowPixelGap;
} }
//Generate the missing vertical lines if(!_keepVerticalRes) {
outputBuffer = orgBuffer; //Generate the missing vertical lines
int lastRow = 239 - GetOverscan().Bottom; outputBuffer = orgBuffer;
bool verticalBlend = EmulationSettings::GetNtscFilterSettings().VerticalBlend; int lastRow = 239 - GetOverscan().Bottom;
for(int y = startRow; y <= endRow; y++) { bool verticalBlend = EmulationSettings::GetNtscFilterSettings().VerticalBlend;
uint64_t* currentLine = (uint64_t*)outputBuffer; for(int y = startRow; y <= endRow; y++) {
uint64_t* nextLine = y == lastRow ? currentLine : (uint64_t*)(outputBuffer + rowPixelGap); uint64_t* currentLine = (uint64_t*)outputBuffer;
uint64_t* buffer = (uint64_t*)(outputBuffer + rowPixelGap / 2); uint64_t* nextLine = y == lastRow ? currentLine : (uint64_t*)(outputBuffer + rowPixelGap);
uint64_t* buffer = (uint64_t*)(outputBuffer + rowPixelGap / 2);
RecursiveBlend(4 / _resDivider, buffer, currentLine, nextLine, pixelsPerCycle, verticalBlend); RecursiveBlend(4 / _resDivider, buffer, currentLine, nextLine, pixelsPerCycle, verticalBlend);
outputBuffer += rowPixelGap; outputBuffer += rowPixelGap;
}
} }
} }

View file

@ -18,6 +18,8 @@ private:
atomic<bool> _stopThread; atomic<bool> _stopThread;
atomic<bool> _workDone; atomic<bool> _workDone;
bool _keepVerticalRes = false;
int _resDivider = 1; int _resDivider = 1;
bool _isOddFrame = false; bool _isOddFrame = false;
uint16_t *_ppuOutputBuffer = nullptr; uint16_t *_ppuOutputBuffer = nullptr;

View file

@ -204,6 +204,7 @@ struct NtscFilterSettings
double Bleed = 0; double Bleed = 0;
bool MergeFields = false; bool MergeFields = false;
bool VerticalBlend = false; bool VerticalBlend = false;
bool KeepVerticalResolution = false;
double YFilterLength = 0; double YFilterLength = 0;
double IFilterLength = 0; double IFilterLength = 0;
@ -1131,7 +1132,7 @@ public:
return _pictureSettings; return _pictureSettings;
} }
static void SetNtscFilterSettings(double artifacts, double bleed, double fringing, double gamma, double resolution, double sharpness, bool mergeFields, double yFilterLength, double iFilterLength, double qFilterLength, bool verticalBlend) static void SetNtscFilterSettings(double artifacts, double bleed, double fringing, double gamma, double resolution, double sharpness, bool mergeFields, double yFilterLength, double iFilterLength, double qFilterLength, bool verticalBlend, bool keepVerticalResolution)
{ {
_ntscFilterSettings.Artifacts = artifacts; _ntscFilterSettings.Artifacts = artifacts;
_ntscFilterSettings.Bleed = bleed; _ntscFilterSettings.Bleed = bleed;
@ -1147,6 +1148,7 @@ public:
_ntscFilterSettings.QFilterLength = qFilterLength; _ntscFilterSettings.QFilterLength = qFilterLength;
_ntscFilterSettings.VerticalBlend = verticalBlend; _ntscFilterSettings.VerticalBlend = verticalBlend;
_ntscFilterSettings.KeepVerticalResolution = keepVerticalResolution;
} }
static NtscFilterSettings GetNtscFilterSettings() static NtscFilterSettings GetNtscFilterSettings()

View file

@ -8,6 +8,7 @@ NtscFilter::NtscFilter()
memset(_basePalette, 0, 64 * 3); memset(_basePalette, 0, 64 * 3);
_ntscData = new nes_ntsc_t(); _ntscData = new nes_ntsc_t();
_ntscSetup = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; _ntscSetup = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
_ntscBuffer = new uint32_t[NES_NTSC_OUT_WIDTH(256) * 240];
} }
FrameInfo NtscFilter::GetFrameInfo() FrameInfo NtscFilter::GetFrameInfo()
@ -15,7 +16,12 @@ FrameInfo NtscFilter::GetFrameInfo()
OverscanDimensions overscan = GetOverscan(); OverscanDimensions overscan = GetOverscan();
int overscanLeft = overscan.Left > 0 ? NES_NTSC_OUT_WIDTH(overscan.Left) : 0; int overscanLeft = overscan.Left > 0 ? NES_NTSC_OUT_WIDTH(overscan.Left) : 0;
int overscanRight = overscan.Right > 0 ? NES_NTSC_OUT_WIDTH(overscan.Right) : 0; int overscanRight = overscan.Right > 0 ? NES_NTSC_OUT_WIDTH(overscan.Right) : 0;
return { NES_NTSC_OUT_WIDTH(PPU::ScreenWidth) - overscanLeft - overscanRight, (PPU::ScreenHeight - overscan.Top - overscan.Bottom) * 2, NES_NTSC_OUT_WIDTH(PPU::ScreenWidth), PPU::ScreenHeight * 2, 4 };
if(_keepVerticalRes) {
return { NES_NTSC_OUT_WIDTH(PPU::ScreenWidth) - overscanLeft - overscanRight, (PPU::ScreenHeight - overscan.Top - overscan.Bottom), NES_NTSC_OUT_WIDTH(PPU::ScreenWidth), PPU::ScreenHeight, 4 };
} else {
return { NES_NTSC_OUT_WIDTH(PPU::ScreenWidth) - overscanLeft - overscanRight, (PPU::ScreenHeight - overscan.Top - overscan.Bottom) * 2, NES_NTSC_OUT_WIDTH(PPU::ScreenWidth), PPU::ScreenHeight * 2, 4 };
}
} }
void NtscFilter::OnBeforeApplyFilter() void NtscFilter::OnBeforeApplyFilter()
@ -38,6 +44,9 @@ void NtscFilter::OnBeforeApplyFilter()
PictureSettings pictureSettings = EmulationSettings::GetPictureSettings(); PictureSettings pictureSettings = EmulationSettings::GetPictureSettings();
NtscFilterSettings ntscSettings = EmulationSettings::GetNtscFilterSettings(); NtscFilterSettings ntscSettings = EmulationSettings::GetNtscFilterSettings();
_keepVerticalRes = ntscSettings.KeepVerticalResolution;
if(paletteChanged || _ntscSetup.hue != pictureSettings.Hue || _ntscSetup.saturation != pictureSettings.Saturation || _ntscSetup.brightness != pictureSettings.Brightness || _ntscSetup.contrast != pictureSettings.Contrast || if(paletteChanged || _ntscSetup.hue != pictureSettings.Hue || _ntscSetup.saturation != pictureSettings.Saturation || _ntscSetup.brightness != pictureSettings.Brightness || _ntscSetup.contrast != pictureSettings.Contrast ||
_ntscSetup.artifacts != ntscSettings.Artifacts || _ntscSetup.bleed != ntscSettings.Bleed || _ntscSetup.fringing != ntscSettings.Fringing || _ntscSetup.gamma != ntscSettings.Gamma || _ntscSetup.artifacts != ntscSettings.Artifacts || _ntscSetup.bleed != ntscSettings.Bleed || _ntscSetup.fringing != ntscSettings.Fringing || _ntscSetup.gamma != ntscSettings.Gamma ||
(_ntscSetup.merge_fields == 1) != ntscSettings.MergeFields || _ntscSetup.resolution != ntscSettings.Resolution || _ntscSetup.sharpness != ntscSettings.Sharpness) { (_ntscSetup.merge_fields == 1) != ntscSettings.MergeFields || _ntscSetup.resolution != ntscSettings.Resolution || _ntscSetup.sharpness != ntscSettings.Sharpness) {
@ -67,13 +76,11 @@ void NtscFilter::ApplyFilter(uint16_t *ppuOutputBuffer)
static bool oddFrame = false; static bool oddFrame = false;
oddFrame = !oddFrame; oddFrame = !oddFrame;
uint32_t* ntscBuffer = new uint32_t[NES_NTSC_OUT_WIDTH(256) * 240]; nes_ntsc_blit(_ntscData, ppuOutputBuffer, PPU::ScreenWidth, oddFrame ? 0 : 1, PPU::ScreenWidth, 240, _ntscBuffer, NES_NTSC_OUT_WIDTH(PPU::ScreenWidth)*4);
nes_ntsc_blit(_ntscData, ppuOutputBuffer, PPU::ScreenWidth, oddFrame ? 0 : 1, PPU::ScreenWidth, 240, ntscBuffer, NES_NTSC_OUT_WIDTH(PPU::ScreenWidth)*4); GenerateArgbFrame(_ntscBuffer);
DoubleOutputHeight(ntscBuffer);
delete[] ntscBuffer;
} }
void NtscFilter::DoubleOutputHeight(uint32_t *ntscBuffer) void NtscFilter::GenerateArgbFrame(uint32_t *ntscBuffer)
{ {
uint32_t* outputBuffer = (uint32_t*)GetOutputBuffer(); uint32_t* outputBuffer = (uint32_t*)GetOutputBuffer();
OverscanDimensions overscan = GetOverscan(); OverscanDimensions overscan = GetOverscan();
@ -82,43 +89,51 @@ void NtscFilter::DoubleOutputHeight(uint32_t *ntscBuffer)
int rowWidth = NES_NTSC_OUT_WIDTH(PPU::ScreenWidth); int rowWidth = NES_NTSC_OUT_WIDTH(PPU::ScreenWidth);
int rowWidthOverscan = rowWidth - overscanLeft - overscanRight; int rowWidthOverscan = rowWidth - overscanLeft - overscanRight;
double scanlineIntensity = 1.0 - EmulationSettings::GetPictureSettings().ScanlineIntensity; if(_keepVerticalRes) {
bool verticalBlend = EmulationSettings::GetNtscFilterSettings().VerticalBlend; for(uint32_t y = overscan.Top; y < PPU::ScreenHeight - overscan.Bottom; y++) {
memcpy(outputBuffer, ntscBuffer, rowWidthOverscan * sizeof(uint32_t));
outputBuffer += rowWidthOverscan;
ntscBuffer += rowWidth;
}
} else {
double scanlineIntensity = 1.0 - EmulationSettings::GetPictureSettings().ScanlineIntensity;
bool verticalBlend = EmulationSettings::GetNtscFilterSettings().VerticalBlend;
for(int y = PPU::ScreenHeight - 1 - overscan.Bottom; y >= (int)overscan.Top; y--) { for(int y = PPU::ScreenHeight - 1 - overscan.Bottom; y >= (int)overscan.Top; y--) {
uint32_t const* in = ntscBuffer + y * rowWidth; uint32_t const* in = ntscBuffer + y * rowWidth;
uint32_t* out = outputBuffer + (y - overscan.Top) * 2 * rowWidthOverscan; uint32_t* out = outputBuffer + (y - overscan.Top) * 2 * rowWidthOverscan;
if(verticalBlend || scanlineIntensity < 1.0) { if(verticalBlend || scanlineIntensity < 1.0) {
for(int x = 0; x < rowWidthOverscan; x++) { for(int x = 0; x < rowWidthOverscan; x++) {
uint32_t prev = in[overscanLeft]; uint32_t prev = in[overscanLeft];
uint32_t next = y < 239 ? in[overscanLeft + rowWidth] : 0; uint32_t next = y < 239 ? in[overscanLeft + rowWidth] : 0;
*out = 0xFF000000 | prev; *out = 0xFF000000 | prev;
/* mix 24-bit rgb without losing low bits */ /* mix 24-bit rgb without losing low bits */
uint32_t mixed; uint32_t mixed;
if(verticalBlend) { if(verticalBlend) {
mixed = (prev + next + ((prev ^ next) & 0x030303)) >> 1; mixed = (prev + next + ((prev ^ next) & 0x030303)) >> 1;
} else { } else {
mixed = prev; mixed = prev;
}
if(scanlineIntensity < 1.0) {
uint8_t r = (mixed >> 16) & 0xFF, g = (mixed >> 8) & 0xFF, b = mixed & 0xFF;
r = (uint8_t)(r * scanlineIntensity);
g = (uint8_t)(g * scanlineIntensity);
b = (uint8_t)(b * scanlineIntensity);
*(out + rowWidthOverscan) = 0xFF000000 | (r << 16) | (g << 8) | b;
} else {
*(out + rowWidthOverscan) = 0xFF000000 | mixed;
}
in++;
out++;
} }
} else {
if(scanlineIntensity < 1.0) { memcpy(out, in + overscanLeft, rowWidthOverscan * sizeof(uint32_t));
uint8_t r = (mixed >> 16) & 0xFF, g = (mixed >> 8) & 0xFF, b = mixed & 0xFF; memcpy(out + rowWidthOverscan, in + overscanLeft, rowWidthOverscan * sizeof(uint32_t));
r = (uint8_t)(r * scanlineIntensity);
g = (uint8_t)(g * scanlineIntensity);
b = (uint8_t)(b * scanlineIntensity);
*(out + rowWidthOverscan) = 0xFF000000 | (r << 16) | (g << 8) | b;
} else {
*(out + rowWidthOverscan) = 0xFF000000 | mixed;
}
in++;
out++;
} }
} else {
memcpy(out, in+overscanLeft, rowWidthOverscan * sizeof(uint32_t));
memcpy(out + rowWidthOverscan, in + overscanLeft, rowWidthOverscan * sizeof(uint32_t));
} }
} }
} }
@ -126,4 +141,5 @@ void NtscFilter::DoubleOutputHeight(uint32_t *ntscBuffer)
NtscFilter::~NtscFilter() NtscFilter::~NtscFilter()
{ {
delete _ntscData; delete _ntscData;
delete[] _ntscBuffer;
} }

View file

@ -8,9 +8,11 @@ class NtscFilter : public BaseVideoFilter
private: private:
nes_ntsc_setup_t _ntscSetup; nes_ntsc_setup_t _ntscSetup;
nes_ntsc_t* _ntscData; nes_ntsc_t* _ntscData;
bool _keepVerticalRes = false;
uint8_t _basePalette[64 * 3]; uint8_t _basePalette[64 * 3];
uint32_t* _ntscBuffer;
void DoubleOutputHeight(uint32_t *outputBuffer); void GenerateArgbFrame(uint32_t *outputBuffer);
protected: protected:
void OnBeforeApplyFilter(); void OnBeforeApplyFilter();

View file

@ -464,7 +464,7 @@ namespace InteropEmu {
DllExport void __stdcall GetRgbPalette(uint32_t *paletteBuffer) { EmulationSettings::GetRgbPalette(paletteBuffer); } DllExport void __stdcall GetRgbPalette(uint32_t *paletteBuffer) { EmulationSettings::GetRgbPalette(paletteBuffer); }
DllExport void __stdcall SetRgbPalette(uint32_t *paletteBuffer) { EmulationSettings::SetRgbPalette(paletteBuffer); } DllExport void __stdcall SetRgbPalette(uint32_t *paletteBuffer) { EmulationSettings::SetRgbPalette(paletteBuffer); }
DllExport void __stdcall SetPictureSettings(double brightness, double contrast, double saturation, double hue, double scanlineIntensity) { EmulationSettings::SetPictureSettings(brightness, contrast, saturation, hue, scanlineIntensity); } DllExport void __stdcall SetPictureSettings(double brightness, double contrast, double saturation, double hue, double scanlineIntensity) { EmulationSettings::SetPictureSettings(brightness, contrast, saturation, hue, scanlineIntensity); }
DllExport void __stdcall SetNtscFilterSettings(double artifacts, double bleed, double fringing, double gamma, double resolution, double sharpness, bool mergeFields, double yFilterLength, double iFilterLength, double qFilterLength, bool verticalBlend) { EmulationSettings::SetNtscFilterSettings(artifacts, bleed, fringing, gamma, resolution, sharpness, mergeFields, yFilterLength, iFilterLength, qFilterLength, verticalBlend); } DllExport void __stdcall SetNtscFilterSettings(double artifacts, double bleed, double fringing, double gamma, double resolution, double sharpness, bool mergeFields, double yFilterLength, double iFilterLength, double qFilterLength, bool verticalBlend) { EmulationSettings::SetNtscFilterSettings(artifacts, bleed, fringing, gamma, resolution, sharpness, mergeFields, yFilterLength, iFilterLength, qFilterLength, verticalBlend, false); }
DllExport void __stdcall SetInputDisplaySettings(uint8_t visiblePorts, InputDisplayPosition displayPosition, bool displayHorizontally) { EmulationSettings::SetInputDisplaySettings(visiblePorts, displayPosition, displayHorizontally); } DllExport void __stdcall SetInputDisplaySettings(uint8_t visiblePorts, InputDisplayPosition displayPosition, bool displayHorizontally) { EmulationSettings::SetInputDisplaySettings(visiblePorts, displayPosition, displayHorizontally); }
DllExport void __stdcall SetAutoSaveOptions(uint32_t delayInMinutes, bool showMessage) { EmulationSettings::SetAutoSaveOptions(delayInMinutes, showMessage); } DllExport void __stdcall SetAutoSaveOptions(uint32_t delayInMinutes, bool showMessage) { EmulationSettings::SetAutoSaveOptions(delayInMinutes, showMessage); }

View file

@ -33,7 +33,7 @@ public:
if(!_skipMode && _sendFrame) { if(!_skipMode && _sendFrame) {
//Use Blargg's NTSC filter's max size as a minimum resolution, to prevent changing resolution too often //Use Blargg's NTSC filter's max size as a minimum resolution, to prevent changing resolution too often
int32_t newWidth = std::max<int32_t>(width, NES_NTSC_OUT_WIDTH(256)); int32_t newWidth = std::max<int32_t>(width, NES_NTSC_OUT_WIDTH(256));
int32_t newHeight = std::max<int32_t>(height, 480); int32_t newHeight = std::max<int32_t>(height, 240);
if(_previousWidth != newWidth || _previousHeight != newHeight) { if(_previousWidth != newWidth || _previousHeight != newHeight) {
//Resolution change is needed //Resolution change is needed
retro_system_av_info avInfo = {}; retro_system_av_info avInfo = {};

View file

@ -54,7 +54,6 @@ static std::unique_ptr<LibretroKeyManager> _keyManager;
static std::unique_ptr<LibretroMessageManager> _messageManager; static std::unique_ptr<LibretroMessageManager> _messageManager;
static const char* MesenNtscFilter = "mesen_ntsc_filter"; static const char* MesenNtscFilter = "mesen_ntsc_filter";
static const char* MesenNtscVerticalBlend = "mesen_ntsc_vertical_blend";
static const char* MesenPalette = "mesen_palette"; static const char* MesenPalette = "mesen_palette";
static const char* MesenNoSpriteLimit = "mesen_nospritelimit"; static const char* MesenNoSpriteLimit = "mesen_nospritelimit";
static const char* MesenOverclock = "mesen_overclock"; static const char* MesenOverclock = "mesen_overclock";
@ -139,7 +138,6 @@ extern "C" {
static const struct retro_variable vars[] = { static const struct retro_variable vars[] = {
{ MesenNtscFilter, "NTSC filter; Disabled|Composite (Blargg)|S-Video (Blargg)|RGB (Blargg)|Monochrome (Blargg)|Bisqwit 2x|Bisqwit 4x|Bisqwit 8x" }, { MesenNtscFilter, "NTSC filter; Disabled|Composite (Blargg)|S-Video (Blargg)|RGB (Blargg)|Monochrome (Blargg)|Bisqwit 2x|Bisqwit 4x|Bisqwit 8x" },
{ MesenNtscVerticalBlend, "NTSC filter: Vertical blending; disabled|enabled" },
{ MesenPalette, "Palette; Default|Composite Direct (by FirebrandX)|Nes Classic|Nestopia (RGB)|Original Hardware (by FirebrandX)|PVM Style (by FirebrandX)|Sony CXA2025AS|Unsaturated v6 (by FirebrandX)|YUV v3 (by FirebrandX)|Custom" }, { MesenPalette, "Palette; Default|Composite Direct (by FirebrandX)|Nes Classic|Nestopia (RGB)|Original Hardware (by FirebrandX)|PVM Style (by FirebrandX)|Sony CXA2025AS|Unsaturated v6 (by FirebrandX)|YUV v3 (by FirebrandX)|Custom" },
{ MesenOverclock, "Overclock; None|Low|Medium|High|Very High" }, { MesenOverclock, "Overclock; None|Low|Medium|High|Very High" },
{ MesenOverclockType, "Overclock Type; Before NMI (Recommended)|After NMI" }, { MesenOverclockType, "Overclock Type; Before NMI (Recommended)|After NMI" },
@ -320,14 +318,6 @@ extern "C" {
} }
} }
bool verticalBlend = false;
var.key = MesenNtscVerticalBlend;
if(retroEnv(RETRO_ENVIRONMENT_GET_VARIABLE, &var)) {
if(string(var.value) == "enabled") {
verticalBlend = true;
}
}
var.key = MesenNtscFilter; var.key = MesenNtscFilter;
if(retroEnv(RETRO_ENVIRONMENT_GET_VARIABLE, &var)) { if(retroEnv(RETRO_ENVIRONMENT_GET_VARIABLE, &var)) {
string value = string(var.value); string value = string(var.value);
@ -335,27 +325,27 @@ extern "C" {
EmulationSettings::SetVideoFilterType(VideoFilterType::None); EmulationSettings::SetVideoFilterType(VideoFilterType::None);
} else if(value == "Composite (Blargg)") { } else if(value == "Composite (Blargg)") {
EmulationSettings::SetVideoFilterType(VideoFilterType::NTSC); EmulationSettings::SetVideoFilterType(VideoFilterType::NTSC);
EmulationSettings::SetNtscFilterSettings(0, 0, 0, 0, 0, 0, false, 0, 0, 0, verticalBlend); EmulationSettings::SetNtscFilterSettings(0, 0, 0, 0, 0, 0, false, 0, 0, 0, false, true);
} else if(value == "S-Video (Blargg)") { } else if(value == "S-Video (Blargg)") {
EmulationSettings::SetVideoFilterType(VideoFilterType::NTSC); EmulationSettings::SetVideoFilterType(VideoFilterType::NTSC);
EmulationSettings::SetNtscFilterSettings(-1.0, 0, -1.0, 0, 0.2, 0.2, false, 0, 0, 0, verticalBlend); EmulationSettings::SetNtscFilterSettings(-1.0, 0, -1.0, 0, 0.2, 0.2, false, 0, 0, 0, false, true);
} else if(value == "RGB (Blargg)") { } else if(value == "RGB (Blargg)") {
EmulationSettings::SetVideoFilterType(VideoFilterType::NTSC); EmulationSettings::SetVideoFilterType(VideoFilterType::NTSC);
EmulationSettings::SetPictureSettings(0, 0, 0, 0, 0); EmulationSettings::SetPictureSettings(0, 0, 0, 0, 0);
EmulationSettings::SetNtscFilterSettings(-1.0, -1.0, -1.0, 0, 0.7, 0.2, false, 0, 0, 0, verticalBlend); EmulationSettings::SetNtscFilterSettings(-1.0, -1.0, -1.0, 0, 0.7, 0.2, false, 0, 0, 0, false, true);
} else if(value == "Monochrome (Blargg)") { } else if(value == "Monochrome (Blargg)") {
EmulationSettings::SetVideoFilterType(VideoFilterType::NTSC); EmulationSettings::SetVideoFilterType(VideoFilterType::NTSC);
EmulationSettings::SetPictureSettings(0, 0, -1.0, 0, 0); EmulationSettings::SetPictureSettings(0, 0, -1.0, 0, 0);
EmulationSettings::SetNtscFilterSettings(-0.2, -0.1, -0.2, 0, 0.7, 0.2, false, 0, 0, 0, verticalBlend); EmulationSettings::SetNtscFilterSettings(-0.2, -0.1, -0.2, 0, 0.7, 0.2, false, 0, 0, 0, false, true);
} else if(value == "Bisqwit 2x") { } else if(value == "Bisqwit 2x") {
EmulationSettings::SetVideoFilterType(VideoFilterType::BisqwitNtscQuarterRes); EmulationSettings::SetVideoFilterType(VideoFilterType::BisqwitNtscQuarterRes);
EmulationSettings::SetNtscFilterSettings(0, 0, 0, 0, 0, 0, false, 0, 0, 0, verticalBlend); EmulationSettings::SetNtscFilterSettings(0, 0, 0, 0, 0, 0, false, 0, 0, 0, false, true);
} else if(value == "Bisqwit 4x") { } else if(value == "Bisqwit 4x") {
EmulationSettings::SetVideoFilterType(VideoFilterType::BisqwitNtscHalfRes); EmulationSettings::SetVideoFilterType(VideoFilterType::BisqwitNtscHalfRes);
EmulationSettings::SetNtscFilterSettings(0, 0, 0, 0, 0, 0, false, 0, 0, 0, verticalBlend); EmulationSettings::SetNtscFilterSettings(0, 0, 0, 0, 0, 0, false, 0, 0, 0, false, true);
} else if(value == "Bisqwit 8x") { } else if(value == "Bisqwit 8x") {
EmulationSettings::SetVideoFilterType(VideoFilterType::BisqwitNtsc); EmulationSettings::SetVideoFilterType(VideoFilterType::BisqwitNtsc);
EmulationSettings::SetNtscFilterSettings(0, 0, 0, 0, 0, 0, false, 0, 0, 0, verticalBlend); EmulationSettings::SetNtscFilterSettings(0, 0, 0, 0, 0, 0, false, 0, 0, 0, false, true);
} }
} }
@ -974,24 +964,26 @@ extern "C" {
RETRO_API void retro_get_system_av_info(struct retro_system_av_info *info) RETRO_API void retro_get_system_av_info(struct retro_system_av_info *info)
{ {
uint32_t scale = 1; uint32_t hscale = 1;
uint32_t vscale = 1;
switch(EmulationSettings::GetVideoFilterType()) { switch(EmulationSettings::GetVideoFilterType()) {
case VideoFilterType::NTSC: scale = 2; break; case VideoFilterType::NTSC: hscale = 2; break;
case VideoFilterType::BisqwitNtscQuarterRes: scale = 2; break; case VideoFilterType::BisqwitNtscQuarterRes: hscale = 2; break;
case VideoFilterType::BisqwitNtscHalfRes: scale = 4; break; case VideoFilterType::BisqwitNtscHalfRes: hscale = 4; break;
case VideoFilterType::BisqwitNtsc: scale = 8; break; case VideoFilterType::BisqwitNtsc: hscale = 8; break;
default: scale = 1; break; default: hscale = 1; break;
} }
HdPackData* hdData = Console::GetHdData(); HdPackData* hdData = Console::GetHdData();
if(hdData != nullptr) { if(hdData != nullptr) {
scale = hdData->Scale; hscale = hdData->Scale;
vscale = hdData->Scale;
} }
if(scale <= 2) { if(hscale <= 2) {
_renderer->GetSystemAudioVideoInfo(*info, NES_NTSC_OUT_WIDTH(256), 240 * 2); _renderer->GetSystemAudioVideoInfo(*info, NES_NTSC_OUT_WIDTH(256), 240 * vscale);
} else { } else {
_renderer->GetSystemAudioVideoInfo(*info, 256 * scale, 240 * scale); _renderer->GetSystemAudioVideoInfo(*info, 256 * hscale, 240 * vscale);
} }
} }