Libretro: Make NTSC filters output in 240p (faster & works better with shaders)
This commit is contained in:
parent
0b7b98f726
commit
4fc1cb107b
8 changed files with 115 additions and 82 deletions
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
|
@ -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();
|
||||||
|
|
|
@ -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); }
|
||||||
|
|
|
@ -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 = {};
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue