mirror of
https://github.com/SourMesen/Mesen-S.git
synced 2024-06-23 14:52:12 -04:00
91 lines
3.5 KiB
C++
91 lines
3.5 KiB
C++
#include "stdafx.h"
|
|
#include "NtscFilter.h"
|
|
#include "EmuSettings.h"
|
|
#include "SettingTypes.h"
|
|
#include "Console.h"
|
|
|
|
NtscFilter::NtscFilter(shared_ptr<Console> console) : BaseVideoFilter(console)
|
|
{
|
|
memset(&_ntscData, 0, sizeof(_ntscData));
|
|
_ntscSetup = { };
|
|
snes_ntsc_init(&_ntscData, &_ntscSetup);
|
|
_ntscBuffer = new uint32_t[SNES_NTSC_OUT_WIDTH(256) * 480];
|
|
}
|
|
|
|
FrameInfo NtscFilter::GetFrameInfo()
|
|
{
|
|
OverscanDimensions overscan = GetOverscan();
|
|
int widthDivider = _baseFrameInfo.Width == 512 ? 2 : 1;
|
|
int heightMultiplier = _baseFrameInfo.Width == 512 ? 1 : 2;
|
|
|
|
FrameInfo frameInfo;
|
|
frameInfo.Width = SNES_NTSC_OUT_WIDTH(_baseFrameInfo.Width / widthDivider) - overscan.Left*2 - overscan.Right*2;
|
|
frameInfo.Height = _baseFrameInfo.Height * heightMultiplier - overscan.Top*2 - overscan.Bottom*2;
|
|
return frameInfo;
|
|
}
|
|
|
|
void NtscFilter::OnBeforeApplyFilter()
|
|
{
|
|
VideoConfig cfg = _console->GetSettings()->GetVideoConfig();
|
|
|
|
if(_ntscSetup.hue != cfg.Hue / 100.0 || _ntscSetup.saturation != cfg.Saturation / 100.0 || _ntscSetup.brightness != cfg.Brightness / 100.0 || _ntscSetup.contrast != cfg.Contrast / 100.0 ||
|
|
_ntscSetup.artifacts != cfg.NtscArtifacts || _ntscSetup.bleed != cfg.NtscBleed || _ntscSetup.fringing != cfg.NtscFringing || _ntscSetup.gamma != cfg.NtscGamma ||
|
|
(_ntscSetup.merge_fields == 1) != cfg.NtscMergeFields || _ntscSetup.resolution != cfg.NtscResolution || _ntscSetup.sharpness != cfg.NtscSharpness) {
|
|
_ntscSetup.hue = cfg.Hue;
|
|
_ntscSetup.saturation = cfg.Saturation;
|
|
_ntscSetup.brightness = cfg.Brightness;
|
|
_ntscSetup.contrast = cfg.Contrast;
|
|
|
|
_ntscSetup.artifacts = cfg.NtscArtifacts;
|
|
_ntscSetup.bleed = cfg.NtscBleed;
|
|
_ntscSetup.fringing = cfg.NtscFringing;
|
|
_ntscSetup.gamma = cfg.NtscGamma;
|
|
_ntscSetup.merge_fields = (int)cfg.NtscMergeFields;
|
|
_ntscSetup.resolution = cfg.NtscResolution;
|
|
_ntscSetup.sharpness = cfg.NtscSharpness;
|
|
snes_ntsc_init(&_ntscData, &_ntscSetup);
|
|
}
|
|
}
|
|
|
|
void NtscFilter::ApplyFilter(uint16_t *ppuOutputBuffer)
|
|
{
|
|
FrameInfo frameInfo = GetFrameInfo();
|
|
OverscanDimensions overscan = GetOverscan();
|
|
|
|
bool useHighResOutput = _baseFrameInfo.Width == 512;
|
|
uint32_t baseWidth = SNES_NTSC_OUT_WIDTH(256);
|
|
uint32_t xOffset = overscan.Left * 2;
|
|
uint32_t yOffset = overscan.Top * 2 * baseWidth;
|
|
|
|
if(useHighResOutput) {
|
|
snes_ntsc_blit_hires(&_ntscData, ppuOutputBuffer, 512, IsOddFrame() ? 0 : 1, 512, _baseFrameInfo.Height, _ntscBuffer, SNES_NTSC_OUT_WIDTH(256) * 4);
|
|
} else {
|
|
snes_ntsc_blit(&_ntscData, ppuOutputBuffer, 256, IsOddFrame() ? 0 : 1, 256, _baseFrameInfo.Height, _ntscBuffer, SNES_NTSC_OUT_WIDTH(256) * 8);
|
|
}
|
|
VideoConfig cfg = _console->GetSettings()->GetVideoConfig();
|
|
|
|
if(cfg.ScanlineIntensity == 0) {
|
|
for(uint32_t i = 0; i < frameInfo.Height; i+=2) {
|
|
memcpy(GetOutputBuffer()+i*frameInfo.Width, _ntscBuffer + yOffset + xOffset + i*baseWidth, frameInfo.Width * sizeof(uint32_t));
|
|
memcpy(GetOutputBuffer()+(i+1)*frameInfo.Width, _ntscBuffer + yOffset + xOffset + i*baseWidth, frameInfo.Width * sizeof(uint32_t));
|
|
}
|
|
} else {
|
|
uint8_t intensity = (uint8_t)((1.0 - cfg.ScanlineIntensity) * 255);
|
|
for(uint32_t i = 0; i < frameInfo.Height; i++) {
|
|
if(i & 0x01) {
|
|
uint32_t *in = _ntscBuffer + yOffset + xOffset + (i - 1) * baseWidth;
|
|
uint32_t *out = GetOutputBuffer() + i * frameInfo.Width;
|
|
for(uint32_t j = 0; j < frameInfo.Width; j++) {
|
|
out[j] = ApplyScanlineEffect(in[j], intensity);
|
|
}
|
|
} else {
|
|
memcpy(GetOutputBuffer()+i*frameInfo.Width, _ntscBuffer + yOffset + xOffset + i*baseWidth, frameInfo.Width * sizeof(uint32_t));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
NtscFilter::~NtscFilter()
|
|
{
|
|
delete[] _ntscBuffer;
|
|
} |