UI: Added video options (scale, filters, aspect ratio)
This commit is contained in:
parent
337416f3a5
commit
60af2e2f64
45 changed files with 2597 additions and 913 deletions
|
@ -76,6 +76,15 @@ uint32_t* BaseVideoFilter::GetOutputBuffer()
|
|||
return _outputBuffer;
|
||||
}
|
||||
|
||||
uint32_t BaseVideoFilter::ApplyScanlineEffect(uint32_t argb, uint8_t scanlineIntensity)
|
||||
{
|
||||
uint8_t r = ((argb & 0xFF0000) >> 16) * scanlineIntensity / 255;
|
||||
uint8_t g = ((argb & 0xFF00) >> 8) * scanlineIntensity / 255;
|
||||
uint8_t b = (argb & 0xFF) * scanlineIntensity / 255;
|
||||
|
||||
return 0xFF000000 | (r << 16) | (g << 8) | b;
|
||||
}
|
||||
|
||||
void BaseVideoFilter::TakeScreenshot(VideoFilterType filterType, string filename, std::stringstream *stream)
|
||||
{
|
||||
uint32_t* pngBuffer;
|
||||
|
|
|
@ -23,6 +23,7 @@ protected:
|
|||
virtual void ApplyFilter(uint16_t *ppuOutputBuffer) = 0;
|
||||
virtual void OnBeforeApplyFilter();
|
||||
bool IsOddFrame();
|
||||
uint32_t ApplyScanlineEffect(uint32_t argb, uint8_t scanlineIntensity);
|
||||
|
||||
public:
|
||||
BaseVideoFilter(shared_ptr<Console> console);
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "MessageManager.h"
|
||||
#include "KeyManager.h"
|
||||
#include "EventType.h"
|
||||
#include "EmuSettings.h"
|
||||
#include "../Utilities/Timer.h"
|
||||
#include "../Utilities/VirtualFile.h"
|
||||
#include "../Utilities/PlatformUtilities.h"
|
||||
|
@ -31,6 +32,7 @@ Console::~Console()
|
|||
|
||||
void Console::Initialize()
|
||||
{
|
||||
_settings.reset(new EmuSettings());
|
||||
_notificationManager.reset(new NotificationManager());
|
||||
_videoDecoder.reset(new VideoDecoder(shared_from_this()));
|
||||
_videoRenderer.reset(new VideoRenderer(shared_from_this()));
|
||||
|
@ -176,6 +178,11 @@ shared_ptr<NotificationManager> Console::GetNotificationManager()
|
|||
return _notificationManager;
|
||||
}
|
||||
|
||||
shared_ptr<EmuSettings> Console::GetSettings()
|
||||
{
|
||||
return _settings;
|
||||
}
|
||||
|
||||
shared_ptr<DebugHud> Console::GetDebugHud()
|
||||
{
|
||||
return _debugHud;
|
||||
|
|
|
@ -17,6 +17,7 @@ class SoundMixer;
|
|||
class VideoRenderer;
|
||||
class VideoDecoder;
|
||||
class NotificationManager;
|
||||
class EmuSettings;
|
||||
enum class MemoryOperationType;
|
||||
enum class SnesMemoryType;
|
||||
enum class EventType;
|
||||
|
@ -40,6 +41,7 @@ private:
|
|||
shared_ptr<VideoRenderer> _videoRenderer;
|
||||
shared_ptr<VideoDecoder> _videoDecoder;
|
||||
shared_ptr<DebugHud> _debugHud;
|
||||
shared_ptr<EmuSettings> _settings;
|
||||
|
||||
thread::id _emulationThreadId;
|
||||
|
||||
|
@ -62,6 +64,7 @@ public:
|
|||
shared_ptr<VideoRenderer> GetVideoRenderer();
|
||||
shared_ptr<VideoDecoder> GetVideoDecoder();
|
||||
shared_ptr<NotificationManager> GetNotificationManager();
|
||||
shared_ptr<EmuSettings> GetSettings();
|
||||
|
||||
shared_ptr<DebugHud> GetDebugHud();
|
||||
|
||||
|
|
|
@ -61,9 +61,11 @@
|
|||
<ClInclude Include="Cpu.h" />
|
||||
<ClInclude Include="DebugBreakHelper.h" />
|
||||
<ClInclude Include="DummyCpu.h" />
|
||||
<ClInclude Include="EmuSettings.h" />
|
||||
<ClInclude Include="EventManager.h" />
|
||||
<ClInclude Include="EventType.h" />
|
||||
<ClInclude Include="ExpressionEvaluator.h" />
|
||||
<ClInclude Include="NtscFilter.h" />
|
||||
<ClInclude Include="PpuTools.h" />
|
||||
<ClInclude Include="RegisterHandlerB.h" />
|
||||
<ClInclude Include="CpuTypes.h" />
|
||||
|
@ -101,6 +103,7 @@
|
|||
<ClInclude Include="RamHandler.h" />
|
||||
<ClInclude Include="RegisterHandlerA.h" />
|
||||
<ClInclude Include="RomHandler.h" />
|
||||
<ClInclude Include="ScaleFilter.h" />
|
||||
<ClInclude Include="SettingTypes.h" />
|
||||
<ClInclude Include="SnesController.h" />
|
||||
<ClInclude Include="SNES_SPC.h" />
|
||||
|
@ -133,6 +136,7 @@
|
|||
<ClCompile Include="Disassembler.cpp" />
|
||||
<ClCompile Include="DisassemblyInfo.cpp" />
|
||||
<ClCompile Include="DmaController.cpp" />
|
||||
<ClCompile Include="EmuSettings.cpp" />
|
||||
<ClCompile Include="EventManager.cpp" />
|
||||
<ClCompile Include="ExpressionEvaluator.cpp" />
|
||||
<ClCompile Include="InternalRegisters.cpp" />
|
||||
|
@ -141,8 +145,10 @@
|
|||
<ClCompile Include="MemoryManager.cpp" />
|
||||
<ClCompile Include="MessageManager.cpp" />
|
||||
<ClCompile Include="NotificationManager.cpp" />
|
||||
<ClCompile Include="NtscFilter.cpp" />
|
||||
<ClCompile Include="Ppu.cpp" />
|
||||
<ClCompile Include="PpuTools.cpp" />
|
||||
<ClCompile Include="ScaleFilter.cpp" />
|
||||
<ClCompile Include="SNES_SPC.cpp" />
|
||||
<ClCompile Include="SNES_SPC_misc.cpp" />
|
||||
<ClCompile Include="SNES_SPC_state.cpp" />
|
||||
|
|
|
@ -209,6 +209,15 @@
|
|||
<ClInclude Include="DebugBreakHelper.h">
|
||||
<Filter>Debugger</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="EmuSettings.h">
|
||||
<Filter>Misc</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ScaleFilter.h">
|
||||
<Filter>Video</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="NtscFilter.h">
|
||||
<Filter>Video</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="stdafx.cpp" />
|
||||
|
@ -326,6 +335,15 @@
|
|||
<ClCompile Include="PpuTools.cpp">
|
||||
<Filter>Debugger</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="EmuSettings.cpp">
|
||||
<Filter>Misc</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ScaleFilter.cpp">
|
||||
<Filter>Video</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="NtscFilter.cpp">
|
||||
<Filter>Video</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="SNES">
|
||||
|
|
|
@ -5,17 +5,16 @@
|
|||
#include <algorithm>
|
||||
#include "DebugHud.h"
|
||||
#include "Console.h"
|
||||
#include "EmuSettings.h"
|
||||
#include "SettingTypes.h"
|
||||
|
||||
DefaultVideoFilter::DefaultVideoFilter(shared_ptr<Console> console) : BaseVideoFilter(console)
|
||||
{
|
||||
InitConversionMatrix(_pictureSettings.Hue, _pictureSettings.Saturation);
|
||||
InitLookupTable();
|
||||
}
|
||||
|
||||
void DefaultVideoFilter::InitConversionMatrix(double hueShift, double saturationShift)
|
||||
{
|
||||
_pictureSettings.Hue = hueShift;
|
||||
_pictureSettings.Saturation = saturationShift;
|
||||
|
||||
double hue = hueShift * M_PI;
|
||||
double sat = saturationShift + 1;
|
||||
|
||||
|
@ -34,60 +33,40 @@ void DefaultVideoFilter::InitConversionMatrix(double hueShift, double saturation
|
|||
}
|
||||
}
|
||||
|
||||
void DefaultVideoFilter::OnBeforeApplyFilter()
|
||||
void DefaultVideoFilter::InitLookupTable()
|
||||
{
|
||||
/*PictureSettings currentSettings = _console->GetSettings()->GetPictureSettings();
|
||||
if(_pictureSettings.Hue != currentSettings.Hue || _pictureSettings.Saturation != currentSettings.Saturation) {
|
||||
InitConversionMatrix(currentSettings.Hue, currentSettings.Saturation);
|
||||
VideoConfig config = _console->GetSettings()->GetVideoConfig();
|
||||
|
||||
InitConversionMatrix(config.Hue, config.Saturation);
|
||||
|
||||
double y, i, q;
|
||||
for(int rgb555 = 0; rgb555 < 0x8000; rgb555++) {
|
||||
double redChannel = To8Bit(rgb555 & 0x1F) / 255.0;
|
||||
double greenChannel = To8Bit((rgb555 >> 5) & 0x1F) / 255.0;
|
||||
double blueChannel = To8Bit(rgb555 >> 10) / 255.0;
|
||||
|
||||
//Apply brightness, contrast, hue & saturation
|
||||
RgbToYiq(redChannel, greenChannel, blueChannel, y, i, q);
|
||||
y *= config.Contrast * 0.5f + 1;
|
||||
y += config.Brightness * 0.5f;
|
||||
YiqToRgb(y, i, q, redChannel, greenChannel, blueChannel);
|
||||
|
||||
int r = std::min(255, (int)(redChannel * 255));
|
||||
int g = std::min(255, (int)(greenChannel * 255));
|
||||
int b = std::min(255, (int)(blueChannel * 255));
|
||||
|
||||
_calculatedPalette[rgb555] = 0xFF000000 | (r << 16) | (g << 8) | b;
|
||||
}
|
||||
_pictureSettings = currentSettings;
|
||||
_needToProcess = _pictureSettings.Hue != 0 || _pictureSettings.Saturation != 0 || _pictureSettings.Brightness || _pictureSettings.Contrast;
|
||||
|
||||
if(_needToProcess) {
|
||||
double y, i, q;
|
||||
uint32_t* originalPalette = _console->GetSettings()->GetRgbPalette();
|
||||
|
||||
for(int pal = 0; pal < 512; pal++) {
|
||||
uint32_t pixelOutput = originalPalette[pal];
|
||||
double redChannel = ((pixelOutput & 0xFF0000) >> 16) / 255.0;
|
||||
double greenChannel = ((pixelOutput & 0xFF00) >> 8) / 255.0;
|
||||
double blueChannel = (pixelOutput & 0xFF) / 255.0;
|
||||
|
||||
//Apply brightness, contrast, hue & saturation
|
||||
RgbToYiq(redChannel, greenChannel, blueChannel, y, i, q);
|
||||
y *= _pictureSettings.Contrast * 0.5f + 1;
|
||||
y += _pictureSettings.Brightness * 0.5f;
|
||||
YiqToRgb(y, i, q, redChannel, greenChannel, blueChannel);
|
||||
|
||||
int r = std::min(255, (int)(redChannel * 255));
|
||||
int g = std::min(255, (int)(greenChannel * 255));
|
||||
int b = std::min(255, (int)(blueChannel * 255));
|
||||
|
||||
_calculatedPalette[pal] = 0xFF000000 | (r << 16) | (g << 8) | b;
|
||||
}
|
||||
} else {
|
||||
memcpy(_calculatedPalette, _console->GetSettings()->GetRgbPalette(), sizeof(_calculatedPalette));
|
||||
}*/
|
||||
_videoConfig = config;
|
||||
}
|
||||
|
||||
void DefaultVideoFilter::DecodePpuBuffer(uint16_t *ppuOutputBuffer, uint32_t* outputBuffer, bool displayScanlines)
|
||||
void DefaultVideoFilter::OnBeforeApplyFilter()
|
||||
{
|
||||
/*uint32_t* out = outputBuffer;
|
||||
OverscanDimensions overscan = GetOverscan();
|
||||
uint8_t scanlineIntensity = (uint8_t)((1.0 - _console->GetSettings()->GetPictureSettings().ScanlineIntensity) * 255);
|
||||
for(uint32_t i = overscan.Top, iMax = 240 - overscan.Bottom; i < iMax; i++) {
|
||||
if(displayScanlines && (i + overscan.Top) % 2 == 0) {
|
||||
for(uint32_t j = overscan.Left, jMax = 256 - overscan.Right; j < jMax; j++) {
|
||||
*out = ApplyScanlineEffect(ppuOutputBuffer[i * 256 + j], scanlineIntensity);
|
||||
out++;
|
||||
}
|
||||
} else {
|
||||
for(uint32_t j = overscan.Left, jMax = 256 - overscan.Right; j < jMax; j++) {
|
||||
*out = _calculatedPalette[ppuOutputBuffer[i * 256 + j]];
|
||||
out++;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
VideoConfig config = _console->GetSettings()->GetVideoConfig();
|
||||
if(_videoConfig.Hue != config.Hue || _videoConfig.Saturation != config.Saturation || _videoConfig.Contrast != config.Contrast || _videoConfig.Brightness != config.Brightness) {
|
||||
InitLookupTable();
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t DefaultVideoFilter::To8Bit(uint8_t color)
|
||||
|
@ -107,10 +86,28 @@ uint32_t DefaultVideoFilter::ToArgb(uint16_t rgb555)
|
|||
void DefaultVideoFilter::ApplyFilter(uint16_t *ppuOutputBuffer)
|
||||
{
|
||||
uint32_t *out = GetOutputBuffer();
|
||||
uint32_t pixelCount = GetFrameInfo().Width * GetFrameInfo().Height;
|
||||
|
||||
for(uint32_t i = 0; i < pixelCount; i++) {
|
||||
out[i] = ToArgb(ppuOutputBuffer[i]);
|
||||
FrameInfo frameInfo = GetFrameInfo();
|
||||
|
||||
uint8_t scanlineIntensity = (uint8_t)((1.0 - _console->GetSettings()->GetVideoConfig().ScanlineIntensity) * 255);
|
||||
if(scanlineIntensity < 255) {
|
||||
for(uint32_t i = 0; i < frameInfo.Height; i++) {
|
||||
if(i & 0x01) {
|
||||
for(uint32_t j = 0; j < frameInfo.Width; j++) {
|
||||
*out = ApplyScanlineEffect(_calculatedPalette[ppuOutputBuffer[i * 512 + j]], scanlineIntensity);
|
||||
out++;
|
||||
}
|
||||
} else {
|
||||
for(uint32_t j = 0; j < frameInfo.Width; j++) {
|
||||
*out = _calculatedPalette[ppuOutputBuffer[i * 512 + j]];
|
||||
out++;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
uint32_t pixelCount = frameInfo.Width * frameInfo.Height;
|
||||
for(uint32_t i = 0; i < pixelCount; i++) {
|
||||
out[i] = _calculatedPalette[ppuOutputBuffer[i]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -126,15 +123,4 @@ void DefaultVideoFilter::YiqToRgb(double y, double i, double q, double &r, doubl
|
|||
r = std::max(0.0, std::min(1.0, (y + _yiqToRgbMatrix[0] * i + _yiqToRgbMatrix[1] * q)));
|
||||
g = std::max(0.0, std::min(1.0, (y + _yiqToRgbMatrix[2] * i + _yiqToRgbMatrix[3] * q)));
|
||||
b = std::max(0.0, std::min(1.0, (y + _yiqToRgbMatrix[4] * i + _yiqToRgbMatrix[5] * q)));
|
||||
}
|
||||
|
||||
uint32_t DefaultVideoFilter::ApplyScanlineEffect(uint16_t ppuPixel, uint8_t scanlineIntensity)
|
||||
{
|
||||
uint32_t pixelOutput = _calculatedPalette[ppuPixel];
|
||||
|
||||
uint8_t r = ((pixelOutput & 0xFF0000) >> 16) * scanlineIntensity / 255;
|
||||
uint8_t g = ((pixelOutput & 0xFF00) >> 8) * scanlineIntensity / 255;
|
||||
uint8_t b = (pixelOutput & 0xFF) * scanlineIntensity / 255;
|
||||
|
||||
return 0xFF000000 | (r << 16) | (g << 8) | b;
|
||||
}
|
|
@ -2,24 +2,24 @@
|
|||
|
||||
#include "stdafx.h"
|
||||
#include "BaseVideoFilter.h"
|
||||
#include "SettingTypes.h"
|
||||
|
||||
class DefaultVideoFilter : public BaseVideoFilter
|
||||
{
|
||||
private:
|
||||
uint32_t _calculatedPalette[0x8000];
|
||||
double _yiqToRgbMatrix[6];
|
||||
uint32_t _calculatedPalette[512];
|
||||
PictureSettings _pictureSettings;
|
||||
VideoConfig _videoConfig;
|
||||
bool _needToProcess = false;
|
||||
|
||||
void InitConversionMatrix(double hueShift, double saturationShift);
|
||||
void InitLookupTable();
|
||||
|
||||
void RgbToYiq(double r, double g, double b, double &y, double &i, double &q);
|
||||
void YiqToRgb(double y, double i, double q, double &r, double &g, double &b);
|
||||
__forceinline static uint8_t To8Bit(uint8_t color);
|
||||
|
||||
protected:
|
||||
void DecodePpuBuffer(uint16_t *ppuOutputBuffer, uint32_t* outputBuffer, bool displayScanlines);
|
||||
uint32_t ApplyScanlineEffect(uint16_t ppuPixel, uint8_t scanlineIntensity);
|
||||
void OnBeforeApplyFilter();
|
||||
|
||||
public:
|
||||
|
|
32
Core/EmuSettings.cpp
Normal file
32
Core/EmuSettings.cpp
Normal file
|
@ -0,0 +1,32 @@
|
|||
#include "stdafx.h"
|
||||
#include "EmuSettings.h"
|
||||
|
||||
void EmuSettings::SetVideoConfig(VideoConfig config)
|
||||
{
|
||||
_video = config;
|
||||
}
|
||||
|
||||
VideoConfig EmuSettings::GetVideoConfig()
|
||||
{
|
||||
return _video;
|
||||
}
|
||||
|
||||
double EmuSettings::GetAspectRatio()
|
||||
{
|
||||
switch(_video.AspectRatio) {
|
||||
case VideoAspectRatio::NoStretching: return 0.0;
|
||||
|
||||
case VideoAspectRatio::Auto:
|
||||
{
|
||||
bool isPal = false;
|
||||
return isPal ? (9440000.0 / 6384411.0) : (128.0 / 105.0);
|
||||
}
|
||||
|
||||
case VideoAspectRatio::NTSC: return 128.0 / 105.0;
|
||||
case VideoAspectRatio::PAL: return 9440000.0 / 6384411.0;
|
||||
case VideoAspectRatio::Standard: return 4.0 / 3.0;
|
||||
case VideoAspectRatio::Widescreen: return 16.0 / 9.0;
|
||||
case VideoAspectRatio::Custom: return _video.CustomAspectRatio;
|
||||
}
|
||||
return 0.0;
|
||||
}
|
14
Core/EmuSettings.h
Normal file
14
Core/EmuSettings.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
#pragma once
|
||||
#include "stdafx.h"
|
||||
#include "SettingTypes.h"
|
||||
|
||||
class EmuSettings
|
||||
{
|
||||
private:
|
||||
VideoConfig _video;
|
||||
|
||||
public:
|
||||
void SetVideoConfig(VideoConfig config);
|
||||
VideoConfig GetVideoConfig();
|
||||
double GetAspectRatio();
|
||||
};
|
72
Core/NtscFilter.cpp
Normal file
72
Core/NtscFilter.cpp
Normal file
|
@ -0,0 +1,72 @@
|
|||
#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()
|
||||
{
|
||||
FrameInfo frameInfo = BaseVideoFilter::GetFrameInfo();
|
||||
frameInfo.Width = SNES_NTSC_OUT_WIDTH(frameInfo.Width / 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();
|
||||
snes_ntsc_blit_hires(&_ntscData, ppuOutputBuffer, 512, IsOddFrame() ? 0 : 1, 512, frameInfo.Height, _ntscBuffer, SNES_NTSC_OUT_WIDTH(256)*4);
|
||||
VideoConfig cfg = _console->GetSettings()->GetVideoConfig();
|
||||
|
||||
if(cfg.ScanlineIntensity == 0) {
|
||||
memcpy(GetOutputBuffer(), _ntscBuffer, frameInfo.Width * frameInfo.Height * 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 + i * frameInfo.Width;
|
||||
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+i*frameInfo.Width, frameInfo.Width * sizeof(uint32_t));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NtscFilter::~NtscFilter()
|
||||
{
|
||||
delete[] _ntscBuffer;
|
||||
}
|
24
Core/NtscFilter.h
Normal file
24
Core/NtscFilter.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
#pragma once
|
||||
#include "stdafx.h"
|
||||
#include "BaseVideoFilter.h"
|
||||
#include "../Utilities/snes_ntsc.h"
|
||||
|
||||
class Console;
|
||||
|
||||
class NtscFilter : public BaseVideoFilter
|
||||
{
|
||||
private:
|
||||
snes_ntsc_setup_t _ntscSetup;
|
||||
snes_ntsc_t _ntscData;
|
||||
uint32_t* _ntscBuffer;
|
||||
|
||||
protected:
|
||||
void OnBeforeApplyFilter();
|
||||
|
||||
public:
|
||||
NtscFilter(shared_ptr<Console> console);
|
||||
virtual ~NtscFilter();
|
||||
|
||||
virtual void ApplyFilter(uint16_t *ppuOutputBuffer);
|
||||
virtual FrameInfo GetFrameInfo();
|
||||
};
|
141
Core/ScaleFilter.cpp
Normal file
141
Core/ScaleFilter.cpp
Normal file
|
@ -0,0 +1,141 @@
|
|||
#include "stdafx.h"
|
||||
#include "ScaleFilter.h"
|
||||
#include "../Utilities/xBRZ/xbrz.h"
|
||||
#include "../Utilities/HQX/hqx.h"
|
||||
#include "../Utilities/Scale2x/scalebit.h"
|
||||
#include "../Utilities/KreedSaiEagle/SaiEagle.h"
|
||||
|
||||
bool ScaleFilter::_hqxInitDone = false;
|
||||
|
||||
ScaleFilter::ScaleFilter(ScaleFilterType scaleFilterType, uint32_t scale)
|
||||
{
|
||||
_scaleFilterType = scaleFilterType;
|
||||
_filterScale = scale;
|
||||
|
||||
if(!_hqxInitDone && _scaleFilterType == ScaleFilterType::HQX) {
|
||||
hqxInit();
|
||||
_hqxInitDone = true;
|
||||
}
|
||||
}
|
||||
|
||||
ScaleFilter::~ScaleFilter()
|
||||
{
|
||||
if(_outputBuffer) {
|
||||
delete[] _outputBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t ScaleFilter::GetScale()
|
||||
{
|
||||
return _filterScale;
|
||||
}
|
||||
|
||||
void ScaleFilter::ApplyPrescaleFilter(uint32_t *inputArgbBuffer)
|
||||
{
|
||||
uint32_t* outputBuffer = _outputBuffer;
|
||||
|
||||
for(uint32_t y = 0; y < _height; y++) {
|
||||
for(uint32_t x = 0; x < _width; x++) {
|
||||
for(uint32_t i = 0; i < _filterScale; i++) {
|
||||
*(outputBuffer++) = *inputArgbBuffer;
|
||||
}
|
||||
inputArgbBuffer++;
|
||||
}
|
||||
for(uint32_t i = 1; i < _filterScale; i++) {
|
||||
memcpy(outputBuffer, outputBuffer - _width*_filterScale, _width*_filterScale *4);
|
||||
outputBuffer += _width*_filterScale;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ScaleFilter::UpdateOutputBuffer(uint32_t width, uint32_t height)
|
||||
{
|
||||
if(!_outputBuffer || width != _width || height != _height) {
|
||||
if(_outputBuffer) {
|
||||
delete[] _outputBuffer;
|
||||
}
|
||||
|
||||
_width = width;
|
||||
_height = height;
|
||||
_outputBuffer = new uint32_t[_width*_height*_filterScale*_filterScale];
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t* ScaleFilter::ApplyFilter(uint32_t *inputArgbBuffer, uint32_t width, uint32_t height, double scanlineIntensity)
|
||||
{
|
||||
UpdateOutputBuffer(width, height);
|
||||
|
||||
if(_scaleFilterType == ScaleFilterType::xBRZ) {
|
||||
xbrz::scale(_filterScale, inputArgbBuffer, _outputBuffer, width, height, xbrz::ColorFormat::ARGB);
|
||||
} else if(_scaleFilterType == ScaleFilterType::HQX) {
|
||||
hqx(_filterScale, inputArgbBuffer, _outputBuffer, width, height);
|
||||
} else if(_scaleFilterType == ScaleFilterType::Scale2x) {
|
||||
scale(_filterScale, _outputBuffer, width*sizeof(uint32_t)*_filterScale, inputArgbBuffer, width*sizeof(uint32_t), 4, width, height);
|
||||
} else if(_scaleFilterType == ScaleFilterType::_2xSai) {
|
||||
twoxsai_generic_xrgb8888(width, height, inputArgbBuffer, width, _outputBuffer, width * _filterScale);
|
||||
} else if(_scaleFilterType == ScaleFilterType::Super2xSai) {
|
||||
supertwoxsai_generic_xrgb8888(width, height, inputArgbBuffer, width, _outputBuffer, width * _filterScale);
|
||||
} else if(_scaleFilterType == ScaleFilterType::SuperEagle) {
|
||||
supereagle_generic_xrgb8888(width, height, inputArgbBuffer, width, _outputBuffer, width * _filterScale);
|
||||
} else if(_scaleFilterType == ScaleFilterType::Prescale) {
|
||||
ApplyPrescaleFilter(inputArgbBuffer);
|
||||
}
|
||||
|
||||
scanlineIntensity = 1.0 - scanlineIntensity;
|
||||
|
||||
if(scanlineIntensity < 1.0) {
|
||||
for(int y = 1, yMax = height * _filterScale; y < yMax; y += 2) {
|
||||
for(int x = 0, xMax = width * _filterScale; x < xMax; x++) {
|
||||
uint32_t &color = _outputBuffer[y*xMax + x];
|
||||
uint8_t r = (color >> 16) & 0xFF, g = (color >> 8) & 0xFF, b = color & 0xFF;
|
||||
r = (uint8_t)(r * scanlineIntensity);
|
||||
g = (uint8_t)(g * scanlineIntensity);
|
||||
b = (uint8_t)(b * scanlineIntensity);
|
||||
color = 0xFF000000 | (r << 16) | (g << 8) | b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _outputBuffer;
|
||||
}
|
||||
|
||||
shared_ptr<ScaleFilter> ScaleFilter::GetScaleFilter(VideoFilterType filter)
|
||||
{
|
||||
shared_ptr<ScaleFilter> scaleFilter;
|
||||
switch(filter) {
|
||||
case VideoFilterType::NTSC:
|
||||
case VideoFilterType::None:
|
||||
break;
|
||||
|
||||
case VideoFilterType::xBRZ2x: scaleFilter.reset(new ScaleFilter(ScaleFilterType::xBRZ, 2)); break;
|
||||
case VideoFilterType::xBRZ3x: scaleFilter.reset(new ScaleFilter(ScaleFilterType::xBRZ, 3)); break;
|
||||
case VideoFilterType::xBRZ4x: scaleFilter.reset(new ScaleFilter(ScaleFilterType::xBRZ, 4)); break;
|
||||
case VideoFilterType::xBRZ5x: scaleFilter.reset(new ScaleFilter(ScaleFilterType::xBRZ, 5)); break;
|
||||
case VideoFilterType::xBRZ6x: scaleFilter.reset(new ScaleFilter(ScaleFilterType::xBRZ, 6)); break;
|
||||
case VideoFilterType::HQ2x: scaleFilter.reset(new ScaleFilter(ScaleFilterType::HQX, 2)); break;
|
||||
case VideoFilterType::HQ3x: scaleFilter.reset(new ScaleFilter(ScaleFilterType::HQX, 3)); break;
|
||||
case VideoFilterType::HQ4x: scaleFilter.reset(new ScaleFilter(ScaleFilterType::HQX, 4)); break;
|
||||
case VideoFilterType::Scale2x: scaleFilter.reset(new ScaleFilter(ScaleFilterType::Scale2x, 2)); break;
|
||||
case VideoFilterType::Scale3x: scaleFilter.reset(new ScaleFilter(ScaleFilterType::Scale2x, 3)); break;
|
||||
case VideoFilterType::Scale4x: scaleFilter.reset(new ScaleFilter(ScaleFilterType::Scale2x, 4)); break;
|
||||
case VideoFilterType::_2xSai: scaleFilter.reset(new ScaleFilter(ScaleFilterType::_2xSai, 2)); break;
|
||||
case VideoFilterType::Super2xSai: scaleFilter.reset(new ScaleFilter(ScaleFilterType::Super2xSai, 2)); break;
|
||||
case VideoFilterType::SuperEagle: scaleFilter.reset(new ScaleFilter(ScaleFilterType::SuperEagle, 2)); break;
|
||||
|
||||
case VideoFilterType::Prescale2x: scaleFilter.reset(new ScaleFilter(ScaleFilterType::Prescale, 2)); break;
|
||||
case VideoFilterType::Prescale3x: scaleFilter.reset(new ScaleFilter(ScaleFilterType::Prescale, 3)); break;
|
||||
case VideoFilterType::Prescale4x: scaleFilter.reset(new ScaleFilter(ScaleFilterType::Prescale, 4)); break;
|
||||
case VideoFilterType::Prescale6x: scaleFilter.reset(new ScaleFilter(ScaleFilterType::Prescale, 6)); break;
|
||||
case VideoFilterType::Prescale8x: scaleFilter.reset(new ScaleFilter(ScaleFilterType::Prescale, 8)); break;
|
||||
case VideoFilterType::Prescale10x: scaleFilter.reset(new ScaleFilter(ScaleFilterType::Prescale, 10)); break;
|
||||
}
|
||||
return scaleFilter;
|
||||
}
|
||||
|
||||
FrameInfo ScaleFilter::GetFrameInfo(FrameInfo baseFrameInfo)
|
||||
{
|
||||
FrameInfo info = baseFrameInfo;
|
||||
info.Height *= this->GetScale();
|
||||
info.Width *= this->GetScale();
|
||||
return info;
|
||||
}
|
28
Core/ScaleFilter.h
Normal file
28
Core/ScaleFilter.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
#pragma once
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "DefaultVideoFilter.h"
|
||||
|
||||
class ScaleFilter
|
||||
{
|
||||
private:
|
||||
static bool _hqxInitDone;
|
||||
uint32_t _filterScale;
|
||||
ScaleFilterType _scaleFilterType;
|
||||
uint32_t *_outputBuffer = nullptr;
|
||||
uint32_t _width = 0;
|
||||
uint32_t _height = 0;
|
||||
|
||||
void ApplyPrescaleFilter(uint32_t *inputArgbBuffer);
|
||||
void UpdateOutputBuffer(uint32_t width, uint32_t height);
|
||||
|
||||
public:
|
||||
ScaleFilter(ScaleFilterType scaleFilterType, uint32_t scale);
|
||||
~ScaleFilter();
|
||||
|
||||
uint32_t GetScale();
|
||||
uint32_t* ApplyFilter(uint32_t *inputArgbBuffer, uint32_t width, uint32_t height, double scanlineIntensity);
|
||||
FrameInfo GetFrameInfo(FrameInfo baseFrameInfo);
|
||||
|
||||
static shared_ptr<ScaleFilter> GetScaleFilter(VideoFilterType filter);
|
||||
};
|
|
@ -15,32 +15,27 @@ enum class ScaleFilterType
|
|||
enum class VideoFilterType
|
||||
{
|
||||
None = 0,
|
||||
NTSC = 1,
|
||||
BisqwitNtscQuarterRes = 2,
|
||||
BisqwitNtscHalfRes = 3,
|
||||
BisqwitNtsc = 4,
|
||||
xBRZ2x = 5,
|
||||
xBRZ3x = 6,
|
||||
xBRZ4x = 7,
|
||||
xBRZ5x = 8,
|
||||
xBRZ6x = 9,
|
||||
HQ2x = 10,
|
||||
HQ3x = 11,
|
||||
HQ4x = 12,
|
||||
Scale2x = 13,
|
||||
Scale3x = 14,
|
||||
Scale4x = 15,
|
||||
_2xSai = 16,
|
||||
Super2xSai = 17,
|
||||
SuperEagle = 18,
|
||||
Prescale2x = 19,
|
||||
Prescale3x = 20,
|
||||
Prescale4x = 21,
|
||||
Prescale6x = 22,
|
||||
Prescale8x = 23,
|
||||
Prescale10x = 24,
|
||||
Raw = 25,
|
||||
HdPack = 999
|
||||
NTSC,
|
||||
xBRZ2x,
|
||||
xBRZ3x,
|
||||
xBRZ4x,
|
||||
xBRZ5x,
|
||||
xBRZ6x,
|
||||
HQ2x,
|
||||
HQ3x,
|
||||
HQ4x,
|
||||
Scale2x,
|
||||
Scale3x,
|
||||
Scale4x,
|
||||
_2xSai,
|
||||
Super2xSai,
|
||||
SuperEagle,
|
||||
Prescale2x,
|
||||
Prescale3x,
|
||||
Prescale4x,
|
||||
Prescale6x,
|
||||
Prescale8x,
|
||||
Prescale10x
|
||||
};
|
||||
|
||||
enum class VideoResizeFilter
|
||||
|
@ -60,6 +55,35 @@ enum class VideoAspectRatio
|
|||
Custom = 6
|
||||
};
|
||||
|
||||
struct VideoConfig
|
||||
{
|
||||
double VideoScale = 2;
|
||||
double CustomAspectRatio = 1.0;
|
||||
VideoFilterType VideoFilter = VideoFilterType::NTSC;
|
||||
VideoAspectRatio AspectRatio = VideoAspectRatio::NoStretching;
|
||||
bool UseBilinearInterpolation = false;
|
||||
bool VerticalSync = false;
|
||||
bool IntegerFpsMode = false;
|
||||
|
||||
double Brightness = 0;
|
||||
double Contrast = 0;
|
||||
double Hue = 0;
|
||||
double Saturation = 0;
|
||||
double ScanlineIntensity = 0;
|
||||
|
||||
double NtscArtifacts = 0;
|
||||
double NtscBleed = 0;
|
||||
double NtscFringing = 0;
|
||||
double NtscGamma = 0;
|
||||
double NtscResolution = 0;
|
||||
double NtscSharpness = 0;
|
||||
bool NtscMergeFields = false;
|
||||
|
||||
bool FullscreenForceIntegerScale = false;
|
||||
bool UseExclusiveFullscreen = false;
|
||||
int32_t ExclusiveFullscreenRefreshRate = 60;
|
||||
};
|
||||
|
||||
struct OverscanDimensions
|
||||
{
|
||||
uint32_t Left = 0;
|
||||
|
@ -68,32 +92,6 @@ struct OverscanDimensions
|
|||
uint32_t Bottom = 0;
|
||||
};
|
||||
|
||||
struct PictureSettings
|
||||
{
|
||||
double Brightness = 0;
|
||||
double Contrast = 0;
|
||||
double Saturation = 0;
|
||||
double Hue = 0;
|
||||
double ScanlineIntensity = 0;
|
||||
};
|
||||
|
||||
struct NtscFilterSettings
|
||||
{
|
||||
double Sharpness = 0;
|
||||
double Gamma = 0;
|
||||
double Resolution = 0;
|
||||
double Artifacts = 0;
|
||||
double Fringing = 0;
|
||||
double Bleed = 0;
|
||||
bool MergeFields = false;
|
||||
bool VerticalBlend = false;
|
||||
bool KeepVerticalResolution = false;
|
||||
|
||||
double YFilterLength = 0;
|
||||
double IFilterLength = 0;
|
||||
double QFilterLength = 0;
|
||||
};
|
||||
|
||||
struct FrameInfo
|
||||
{
|
||||
uint32_t Width;
|
||||
|
|
|
@ -3,7 +3,12 @@
|
|||
#include "VideoDecoder.h"
|
||||
#include "VideoRenderer.h"
|
||||
#include "DefaultVideoFilter.h"
|
||||
#include "NotificationManager.h"
|
||||
#include "Console.h"
|
||||
#include "EmuSettings.h"
|
||||
#include "SettingTypes.h"
|
||||
#include "NtscFilter.h"
|
||||
#include "ScaleFilter.h"
|
||||
#include "Ppu.h"
|
||||
#include "DebugHud.h"
|
||||
|
||||
|
@ -25,64 +30,40 @@ FrameInfo VideoDecoder::GetFrameInfo()
|
|||
return _lastFrameInfo;
|
||||
}
|
||||
|
||||
void VideoDecoder::GetScreenSize(ScreenSize &size, bool ignoreScale)
|
||||
ScreenSize VideoDecoder::GetScreenSize(bool ignoreScale)
|
||||
{
|
||||
ScreenSize size = {};
|
||||
if(_videoFilter) {
|
||||
/*OverscanDimensions overscan = ignoreScale ? _videoFilter->GetOverscan() : _console->GetSettings()->GetOverscanDimensions();
|
||||
FrameInfo frameInfo{ overscan.GetScreenWidth(), overscan.GetScreenHeight(), PPU::ScreenWidth, PPU::ScreenHeight, 4 };
|
||||
double aspectRatio = _console->GetSettings()->GetAspectRatio(_console);
|
||||
double scale = (ignoreScale ? 1 : _console->GetSettings()->GetVideoScale());
|
||||
size.Width = (int32_t)(frameInfo.Width * scale);
|
||||
size.Height = (int32_t)(frameInfo.Height * scale);
|
||||
VideoConfig config = _console->GetSettings()->GetVideoConfig();
|
||||
double aspectRatio = _console->GetSettings()->GetAspectRatio();
|
||||
double scale = (ignoreScale ? 1 : config.VideoScale);
|
||||
size.Width = (int32_t)(_baseFrameInfo.Width * scale / 2);
|
||||
size.Height = (int32_t)(_baseFrameInfo.Height * scale / 2);
|
||||
size.Scale = scale;
|
||||
if(aspectRatio != 0.0) {
|
||||
size.Width = (uint32_t)(frameInfo.OriginalHeight * scale * aspectRatio * ((double)frameInfo.Width / frameInfo.OriginalWidth));
|
||||
size.Width = (uint32_t)(_baseFrameInfo.Height * scale * aspectRatio / 2);
|
||||
}
|
||||
|
||||
if(_console->GetSettings()->GetScreenRotation() % 180) {
|
||||
/*if(_console->GetSettings()->GetScreenRotation() % 180) {
|
||||
std::swap(size.Width, size.Height);
|
||||
}
|
||||
|
||||
size.Scale = scale;*/
|
||||
|
||||
size.Scale = 2;
|
||||
if(ignoreScale) {
|
||||
size.Width = _baseFrameInfo.Width;
|
||||
size.Height = _baseFrameInfo.Height;
|
||||
} else {
|
||||
if(_baseFrameInfo.Width == 256) {
|
||||
size.Width = (int32_t)(_baseFrameInfo.Width * size.Scale);
|
||||
size.Height = (int32_t)(_baseFrameInfo.Height * size.Scale);
|
||||
} else {
|
||||
size.Width = (int32_t)_baseFrameInfo.Width;
|
||||
size.Height = (int32_t)_baseFrameInfo.Height;
|
||||
if(_baseFrameInfo.Height <= 240) {
|
||||
size.Height *= 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
void VideoDecoder::UpdateVideoFilter()
|
||||
{
|
||||
VideoFilterType newFilter = VideoFilterType::None;
|
||||
VideoFilterType newFilter = _console->GetSettings()->GetVideoConfig().VideoFilter;
|
||||
|
||||
if(_videoFilterType != newFilter || _videoFilter == nullptr) {
|
||||
_videoFilterType = newFilter;
|
||||
_videoFilter.reset(new DefaultVideoFilter(_console));
|
||||
//_scaleFilter.reset();
|
||||
_scaleFilter.reset();
|
||||
|
||||
switch(_videoFilterType) {
|
||||
case VideoFilterType::None: break;
|
||||
|
||||
//TODO
|
||||
/*
|
||||
case VideoFilterType::NTSC: _videoFilter.reset(new NtscFilter(_console)); break;
|
||||
case VideoFilterType::BisqwitNtsc: _videoFilter.reset(new BisqwitNtscFilter(_console, 1)); break;
|
||||
case VideoFilterType::BisqwitNtscHalfRes: _videoFilter.reset(new BisqwitNtscFilter(_console, 2)); break;
|
||||
case VideoFilterType::BisqwitNtscQuarterRes: _videoFilter.reset(new BisqwitNtscFilter(_console, 4)); break;
|
||||
case VideoFilterType::Raw: _videoFilter.reset(new RawVideoFilter(_console)); break;
|
||||
default: _scaleFilter = ScaleFilter::GetScaleFilter(_videoFilterType); break;*/
|
||||
default: _scaleFilter = ScaleFilter::GetScaleFilter(_videoFilterType); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -112,23 +93,24 @@ void VideoDecoder::DecodeFrame(bool synchronous)
|
|||
if(_rotateFilter) {
|
||||
outputBuffer = _rotateFilter->ApplyFilter(outputBuffer, frameInfo.Width, frameInfo.Height);
|
||||
frameInfo = _rotateFilter->GetFrameInfo(frameInfo);
|
||||
}
|
||||
}*/
|
||||
|
||||
if(_scaleFilter) {
|
||||
outputBuffer = _scaleFilter->ApplyFilter(outputBuffer, frameInfo.Width, frameInfo.Height, _console->GetSettings()->GetPictureSettings().ScanlineIntensity);
|
||||
outputBuffer = _scaleFilter->ApplyFilter(outputBuffer, frameInfo.Width, frameInfo.Height, _console->GetSettings()->GetVideoConfig().ScanlineIntensity);
|
||||
frameInfo = _scaleFilter->GetFrameInfo(frameInfo);
|
||||
}
|
||||
|
||||
/*
|
||||
if(_hud) {
|
||||
_hud->DrawHud(_console, outputBuffer, frameInfo, _videoFilter->GetOverscan());
|
||||
}*/
|
||||
|
||||
ScreenSize screenSize;
|
||||
GetScreenSize(screenSize, true);
|
||||
/*if(_previousScale != _console->GetSettings()->GetVideoScale() || screenSize.Height != _previousScreenSize.Height || screenSize.Width != _previousScreenSize.Width) {
|
||||
ScreenSize screenSize = GetScreenSize(true);
|
||||
VideoConfig config = _console->GetSettings()->GetVideoConfig();
|
||||
if(_previousScale != config.VideoScale || screenSize.Height != _previousScreenSize.Height || screenSize.Width != _previousScreenSize.Width) {
|
||||
_console->GetNotificationManager()->SendNotification(ConsoleNotificationType::ResolutionChanged);
|
||||
}*/
|
||||
_previousScale = 1; // _console->GetSettings()->GetVideoScale();
|
||||
}
|
||||
_previousScale = config.VideoScale;
|
||||
_previousScreenSize = screenSize;
|
||||
_lastFrameInfo = frameInfo;
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include "SettingTypes.h"
|
||||
|
||||
class BaseVideoFilter;
|
||||
//class ScaleFilter;
|
||||
class ScaleFilter;
|
||||
//class RotateFilter;
|
||||
class IRenderingDevice;
|
||||
//class VideoHud;
|
||||
|
@ -35,7 +35,7 @@ private:
|
|||
|
||||
VideoFilterType _videoFilterType = VideoFilterType::None;
|
||||
unique_ptr<BaseVideoFilter> _videoFilter;
|
||||
//shared_ptr<ScaleFilter> _scaleFilter;
|
||||
shared_ptr<ScaleFilter> _scaleFilter;
|
||||
//shared_ptr<RotateFilter> _rotateFilter;
|
||||
|
||||
void UpdateVideoFilter();
|
||||
|
@ -53,7 +53,7 @@ public:
|
|||
uint32_t GetFrameCount();
|
||||
|
||||
FrameInfo GetFrameInfo();
|
||||
void GetScreenSize(ScreenSize &size, bool ignoreScale);
|
||||
ScreenSize GetScreenSize(bool ignoreScale);
|
||||
|
||||
void UpdateFrameSync(uint16_t *ppuOutputBuffer, uint16_t width, uint16_t height, uint32_t frameNumber);
|
||||
void UpdateFrame(uint16_t *ppuOutputBuffer, uint16_t width, uint16_t height, uint32_t frameNumber);
|
||||
|
|
13
InteropDLL/ConfigApiWrapper.cpp
Normal file
13
InteropDLL/ConfigApiWrapper.cpp
Normal file
|
@ -0,0 +1,13 @@
|
|||
#include "stdafx.h"
|
||||
#include "../Core/Console.h"
|
||||
#include "../Core/EmuSettings.h"
|
||||
#include "../Core/SettingTypes.h"
|
||||
|
||||
extern shared_ptr<Console> _console;
|
||||
|
||||
extern "C" {
|
||||
DllExport void __stdcall SetVideoConfig(VideoConfig config)
|
||||
{
|
||||
_console->GetSettings()->SetVideoConfig(config);
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
#include "stdafx.h"
|
||||
#include "../Core/Console.h"
|
||||
#include "../Core/VideoDecoder.h"
|
||||
#include "../Core/MessageManager.h"
|
||||
#include "../Core/INotificationListener.h"
|
||||
#include "../Core/KeyManager.h"
|
||||
|
@ -28,182 +29,185 @@ string _logString;
|
|||
shared_ptr<Console> _console;
|
||||
InteropNotificationListeners _listeners;
|
||||
|
||||
namespace InteropEmu {
|
||||
extern "C" {
|
||||
DllExport bool __stdcall TestDll()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
extern "C" {
|
||||
DllExport bool __stdcall TestDll()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
DllExport uint32_t __stdcall GetMesenVersion() { return 0x00000100; }
|
||||
DllExport uint32_t __stdcall GetMesenVersion() { return 0x00000100; }
|
||||
|
||||
DllExport void __stdcall InitDll()
|
||||
{
|
||||
_console.reset(new Console());
|
||||
_console->Initialize();
|
||||
}
|
||||
DllExport void __stdcall InitDll()
|
||||
{
|
||||
_console.reset(new Console());
|
||||
_console->Initialize();
|
||||
}
|
||||
|
||||
DllExport void __stdcall InitializeEmu(const char* homeFolder, void *windowHandle, void *viewerHandle, bool noAudio, bool noVideo, bool noInput)
|
||||
{
|
||||
FolderUtilities::SetHomeFolder(homeFolder);
|
||||
//_shortcutKeyHandler.reset(new ShortcutKeyHandler(_console));
|
||||
DllExport void __stdcall InitializeEmu(const char* homeFolder, void *windowHandle, void *viewerHandle, bool noAudio, bool noVideo, bool noInput)
|
||||
{
|
||||
FolderUtilities::SetHomeFolder(homeFolder);
|
||||
//_shortcutKeyHandler.reset(new ShortcutKeyHandler(_console));
|
||||
|
||||
if(windowHandle != nullptr && viewerHandle != nullptr) {
|
||||
_windowHandle = windowHandle;
|
||||
_viewerHandle = viewerHandle;
|
||||
if(windowHandle != nullptr && viewerHandle != nullptr) {
|
||||
_windowHandle = windowHandle;
|
||||
_viewerHandle = viewerHandle;
|
||||
|
||||
if(!noVideo) {
|
||||
#ifdef _WIN32
|
||||
_renderer.reset(new Renderer(_console, (HWND)_viewerHandle, true));
|
||||
#else
|
||||
_renderer.reset(new SdlRenderer(_console, _viewerHandle, true));
|
||||
#endif
|
||||
}
|
||||
|
||||
if(!noAudio) {
|
||||
#ifdef _WIN32
|
||||
_soundManager.reset(new SoundManager(_console, (HWND)_windowHandle));
|
||||
#else
|
||||
_soundManager.reset(new SdlSoundManager(_console));
|
||||
#endif
|
||||
}
|
||||
|
||||
if(!noInput) {
|
||||
#ifdef _WIN32
|
||||
_keyManager.reset(new WindowsKeyManager(_console, (HWND)_windowHandle));
|
||||
#else
|
||||
_keyManager.reset(new LinuxKeyManager(_console));
|
||||
#endif
|
||||
|
||||
KeyManager::RegisterKeyManager(_keyManager.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DllExport void __stdcall SetFullscreenMode(bool fullscreen, void *windowHandle, uint32_t monitorWidth, uint32_t monitorHeight)
|
||||
{
|
||||
if(_renderer) {
|
||||
_renderer->SetFullscreenMode(fullscreen, windowHandle, monitorWidth, monitorHeight);
|
||||
}
|
||||
}
|
||||
|
||||
DllExport void __stdcall LoadRom(char* filename, char* patchFile) { _console->LoadRom((VirtualFile)filename, (VirtualFile)patchFile); }
|
||||
//DllExport void __stdcall AddKnownGameFolder(char* folder) { FolderUtilities::AddKnownGameFolder(folder); }
|
||||
//DllExport void __stdcall SetFolderOverrides(char* saveFolder, char* saveStateFolder, char* screenshotFolder) { FolderUtilities::SetFolderOverrides(saveFolder, saveStateFolder, screenshotFolder); }
|
||||
|
||||
DllExport const char* __stdcall GetArchiveRomList(char* filename) {
|
||||
std::ostringstream out;
|
||||
shared_ptr<ArchiveReader> reader = ArchiveReader::GetReader(filename);
|
||||
if(reader) {
|
||||
for(string romName : reader->GetFileList({ ".sfc" })) {
|
||||
out << romName << "[!|!]";
|
||||
}
|
||||
}
|
||||
_returnString = out.str();
|
||||
return _returnString.c_str();
|
||||
}
|
||||
|
||||
DllExport void __stdcall SetMousePosition(double x, double y) { KeyManager::SetMousePosition(x, y); }
|
||||
DllExport void __stdcall SetMouseMovement(int16_t x, int16_t y) { KeyManager::SetMouseMovement(x, y); }
|
||||
|
||||
DllExport void __stdcall UpdateInputDevices() { if(_keyManager) { _keyManager->UpdateDevices(); } }
|
||||
DllExport void __stdcall GetPressedKeys(uint32_t *keyBuffer) {
|
||||
vector<uint32_t> pressedKeys = KeyManager::GetPressedKeys();
|
||||
for(size_t i = 0; i < pressedKeys.size() && i < 3; i++) {
|
||||
keyBuffer[i] = pressedKeys[i];
|
||||
}
|
||||
}
|
||||
DllExport void __stdcall DisableAllKeys(bool disabled) {
|
||||
if(_keyManager) {
|
||||
_keyManager->SetDisabled(disabled);
|
||||
}
|
||||
}
|
||||
DllExport void __stdcall SetKeyState(int32_t scanCode, bool state) {
|
||||
if(_keyManager) {
|
||||
_keyManager->SetKeyState(scanCode, state);
|
||||
//_shortcutKeyHandler->ProcessKeys();
|
||||
if(!noVideo) {
|
||||
#ifdef _WIN32
|
||||
_renderer.reset(new Renderer(_console, (HWND)_viewerHandle, true));
|
||||
#else
|
||||
_renderer.reset(new SdlRenderer(_console, _viewerHandle, true));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
DllExport void __stdcall ResetKeyState() { if(_keyManager) { _keyManager->ResetKeyState(); } }
|
||||
DllExport const char* __stdcall GetKeyName(uint32_t keyCode)
|
||||
{
|
||||
_returnString = KeyManager::GetKeyName(keyCode);
|
||||
return _returnString.c_str();
|
||||
}
|
||||
DllExport uint32_t __stdcall GetKeyCode(char* keyName) {
|
||||
if(keyName) {
|
||||
return KeyManager::GetKeyCode(keyName);
|
||||
} else {
|
||||
return 0;
|
||||
|
||||
if(!noAudio) {
|
||||
#ifdef _WIN32
|
||||
_soundManager.reset(new SoundManager(_console, (HWND)_windowHandle));
|
||||
#else
|
||||
_soundManager.reset(new SdlSoundManager(_console));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
DllExport void __stdcall Run()
|
||||
{
|
||||
if(_console) {
|
||||
_console->Run();
|
||||
}
|
||||
}
|
||||
|
||||
DllExport void __stdcall Stop()
|
||||
{
|
||||
if(_console) {
|
||||
_console->Stop();
|
||||
}
|
||||
}
|
||||
|
||||
DllExport void __stdcall Release()
|
||||
{
|
||||
_console->Stop();
|
||||
|
||||
_renderer.reset();
|
||||
_soundManager.reset();
|
||||
_keyManager.reset();
|
||||
|
||||
_console->Release();
|
||||
_console.reset();
|
||||
|
||||
//_shortcutKeyHandler.reset();
|
||||
}
|
||||
|
||||
DllExport INotificationListener* __stdcall RegisterNotificationCallback(NotificationListenerCallback callback)
|
||||
{
|
||||
return _listeners.RegisterNotificationCallback(callback, _console);
|
||||
}
|
||||
|
||||
DllExport void __stdcall UnregisterNotificationCallback(INotificationListener *listener)
|
||||
{
|
||||
_listeners.UnregisterNotificationCallback(listener);
|
||||
}
|
||||
|
||||
DllExport void __stdcall DisplayMessage(char* title, char* message, char* param1) { MessageManager::DisplayMessage(title, message, param1 ? param1 : ""); }
|
||||
DllExport const char* __stdcall GetLog()
|
||||
{
|
||||
_logString = MessageManager::GetLog();
|
||||
return _logString.c_str();
|
||||
}
|
||||
|
||||
DllExport void __stdcall WriteLogEntry(char* message) { MessageManager::Log(message); }
|
||||
|
||||
DllExport void __stdcall PgoRunTest(vector<string> testRoms, bool enableDebugger)
|
||||
{
|
||||
FolderUtilities::SetHomeFolder("../PGOMesenHome");
|
||||
|
||||
for(size_t i = 0; i < testRoms.size(); i++) {
|
||||
std::cout << "Running: " << testRoms[i] << std::endl;
|
||||
|
||||
_console.reset(new Console());
|
||||
_console->Initialize();
|
||||
_console->LoadRom((VirtualFile)testRoms[i], VirtualFile());
|
||||
|
||||
thread testThread([=] {
|
||||
_console->Run();
|
||||
});
|
||||
std::this_thread::sleep_for(std::chrono::duration<int, std::milli>(5000));
|
||||
_console->Stop();
|
||||
testThread.join();
|
||||
_console->Release();
|
||||
if(!noInput) {
|
||||
#ifdef _WIN32
|
||||
_keyManager.reset(new WindowsKeyManager(_console, (HWND)_windowHandle));
|
||||
#else
|
||||
_keyManager.reset(new LinuxKeyManager(_console));
|
||||
#endif
|
||||
|
||||
KeyManager::RegisterKeyManager(_keyManager.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DllExport void __stdcall SetFullscreenMode(bool fullscreen, void *windowHandle, uint32_t monitorWidth, uint32_t monitorHeight)
|
||||
{
|
||||
if(_renderer) {
|
||||
_renderer->SetFullscreenMode(fullscreen, windowHandle, monitorWidth, monitorHeight);
|
||||
}
|
||||
}
|
||||
|
||||
DllExport void __stdcall LoadRom(char* filename, char* patchFile) { _console->LoadRom((VirtualFile)filename, (VirtualFile)patchFile); }
|
||||
//DllExport void __stdcall AddKnownGameFolder(char* folder) { FolderUtilities::AddKnownGameFolder(folder); }
|
||||
//DllExport void __stdcall SetFolderOverrides(char* saveFolder, char* saveStateFolder, char* screenshotFolder) { FolderUtilities::SetFolderOverrides(saveFolder, saveStateFolder, screenshotFolder); }
|
||||
|
||||
DllExport const char* __stdcall GetArchiveRomList(char* filename) {
|
||||
std::ostringstream out;
|
||||
shared_ptr<ArchiveReader> reader = ArchiveReader::GetReader(filename);
|
||||
if(reader) {
|
||||
for(string romName : reader->GetFileList({ ".sfc" })) {
|
||||
out << romName << "[!|!]";
|
||||
}
|
||||
}
|
||||
_returnString = out.str();
|
||||
return _returnString.c_str();
|
||||
}
|
||||
|
||||
DllExport void __stdcall SetMousePosition(double x, double y) { KeyManager::SetMousePosition(x, y); }
|
||||
DllExport void __stdcall SetMouseMovement(int16_t x, int16_t y) { KeyManager::SetMouseMovement(x, y); }
|
||||
|
||||
DllExport void __stdcall UpdateInputDevices() { if(_keyManager) { _keyManager->UpdateDevices(); } }
|
||||
DllExport void __stdcall GetPressedKeys(uint32_t *keyBuffer) {
|
||||
vector<uint32_t> pressedKeys = KeyManager::GetPressedKeys();
|
||||
for(size_t i = 0; i < pressedKeys.size() && i < 3; i++) {
|
||||
keyBuffer[i] = pressedKeys[i];
|
||||
}
|
||||
}
|
||||
DllExport void __stdcall DisableAllKeys(bool disabled) {
|
||||
if(_keyManager) {
|
||||
_keyManager->SetDisabled(disabled);
|
||||
}
|
||||
}
|
||||
DllExport void __stdcall SetKeyState(int32_t scanCode, bool state) {
|
||||
if(_keyManager) {
|
||||
_keyManager->SetKeyState(scanCode, state);
|
||||
//_shortcutKeyHandler->ProcessKeys();
|
||||
}
|
||||
}
|
||||
DllExport void __stdcall ResetKeyState() { if(_keyManager) { _keyManager->ResetKeyState(); } }
|
||||
DllExport const char* __stdcall GetKeyName(uint32_t keyCode)
|
||||
{
|
||||
_returnString = KeyManager::GetKeyName(keyCode);
|
||||
return _returnString.c_str();
|
||||
}
|
||||
DllExport uint32_t __stdcall GetKeyCode(char* keyName) {
|
||||
if(keyName) {
|
||||
return KeyManager::GetKeyCode(keyName);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
DllExport void __stdcall Run()
|
||||
{
|
||||
if(_console) {
|
||||
_console->Run();
|
||||
}
|
||||
}
|
||||
|
||||
DllExport void __stdcall Stop()
|
||||
{
|
||||
if(_console) {
|
||||
_console->Stop();
|
||||
}
|
||||
}
|
||||
|
||||
DllExport void __stdcall Release()
|
||||
{
|
||||
_console->Stop();
|
||||
|
||||
_renderer.reset();
|
||||
_soundManager.reset();
|
||||
_keyManager.reset();
|
||||
|
||||
_console->Release();
|
||||
_console.reset();
|
||||
|
||||
//_shortcutKeyHandler.reset();
|
||||
}
|
||||
|
||||
DllExport INotificationListener* __stdcall RegisterNotificationCallback(NotificationListenerCallback callback)
|
||||
{
|
||||
return _listeners.RegisterNotificationCallback(callback, _console);
|
||||
}
|
||||
|
||||
DllExport void __stdcall UnregisterNotificationCallback(INotificationListener *listener)
|
||||
{
|
||||
_listeners.UnregisterNotificationCallback(listener);
|
||||
}
|
||||
|
||||
DllExport void __stdcall DisplayMessage(char* title, char* message, char* param1) { MessageManager::DisplayMessage(title, message, param1 ? param1 : ""); }
|
||||
DllExport const char* __stdcall GetLog()
|
||||
{
|
||||
_logString = MessageManager::GetLog();
|
||||
return _logString.c_str();
|
||||
}
|
||||
|
||||
DllExport ScreenSize __stdcall GetScreenSize(bool ignoreScale)
|
||||
{
|
||||
return _console->GetVideoDecoder()->GetScreenSize(ignoreScale);
|
||||
}
|
||||
|
||||
DllExport void __stdcall WriteLogEntry(char* message) { MessageManager::Log(message); }
|
||||
|
||||
DllExport void __stdcall PgoRunTest(vector<string> testRoms, bool enableDebugger)
|
||||
{
|
||||
FolderUtilities::SetHomeFolder("../PGOMesenHome");
|
||||
|
||||
for(size_t i = 0; i < testRoms.size(); i++) {
|
||||
std::cout << "Running: " << testRoms[i] << std::endl;
|
||||
|
||||
_console.reset(new Console());
|
||||
_console->Initialize();
|
||||
_console->LoadRom((VirtualFile)testRoms[i], VirtualFile());
|
||||
|
||||
thread testThread([=] {
|
||||
_console->Run();
|
||||
});
|
||||
std::this_thread::sleep_for(std::chrono::duration<int, std::milli>(5000));
|
||||
_console->Stop();
|
||||
testThread.join();
|
||||
_console->Release();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -453,6 +453,7 @@
|
|||
<ClInclude Include="stdafx.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="ConfigApiWrapper.cpp" />
|
||||
<ClCompile Include="EmuApiWrapper.cpp" />
|
||||
<ClCompile Include="DebugApiWrapper.cpp" />
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
|
|
|
@ -31,5 +31,8 @@
|
|||
<ClCompile Include="EmuApiWrapper.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ConfigApiWrapper.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
18
UI/Config/BaseConfig.cs
Normal file
18
UI/Config/BaseConfig.cs
Normal file
|
@ -0,0 +1,18 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Mesen.GUI.Config
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class BaseConfig<T>
|
||||
{
|
||||
public T Clone()
|
||||
{
|
||||
return (T)this.MemberwiseClone();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,6 +17,7 @@ namespace Mesen.GUI.Config
|
|||
|
||||
public string Version = "0.1.0";
|
||||
public List<RecentItem> RecentFiles;
|
||||
public VideoConfig Video;
|
||||
public DebugInfo Debug;
|
||||
public Point? WindowLocation;
|
||||
public Size? WindowSize;
|
||||
|
@ -25,6 +26,7 @@ namespace Mesen.GUI.Config
|
|||
{
|
||||
RecentFiles = new List<RecentItem>();
|
||||
Debug = new DebugInfo();
|
||||
Video = new VideoConfig();
|
||||
}
|
||||
|
||||
~Configuration()
|
||||
|
@ -50,6 +52,7 @@ namespace Mesen.GUI.Config
|
|||
|
||||
public void ApplyConfig()
|
||||
{
|
||||
Video.ApplyConfig();
|
||||
}
|
||||
|
||||
public void InitializeDefaults()
|
||||
|
|
82
UI/Config/VideoConfig.cs
Normal file
82
UI/Config/VideoConfig.cs
Normal file
|
@ -0,0 +1,82 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Mesen.GUI.Config
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public class VideoConfig : BaseConfig<VideoConfig>
|
||||
{
|
||||
[MinMax(0.1, 10.0)] public double VideoScale = 2;
|
||||
[MinMax(0.1, 5.0)] public double CustomAspectRatio = 1.0;
|
||||
public VideoFilterType VideoFilter = VideoFilterType.None;
|
||||
public VideoAspectRatio AspectRatio = VideoAspectRatio.NoStretching;
|
||||
|
||||
[MarshalAs(UnmanagedType.I1)] public bool UseBilinearInterpolation = false;
|
||||
[MarshalAs(UnmanagedType.I1)] public bool VerticalSync = false;
|
||||
[MarshalAs(UnmanagedType.I1)] public bool IntegerFpsMode = false;
|
||||
|
||||
[MinMax(-1, 1.0)] public double Brightness = 0;
|
||||
[MinMax(-1, 1.0)] public double Contrast = 0;
|
||||
[MinMax(-1, 1.0)] public double Hue = 0;
|
||||
[MinMax(-1, 1.0)] public double Saturation = 0;
|
||||
[MinMax(0, 1.0)] public double ScanlineIntensity = 0;
|
||||
|
||||
[MinMax(-1, 1.0)] public double NtscArtifacts = 0;
|
||||
[MinMax(-1, 1.0)] public double NtscBleed = 0;
|
||||
[MinMax(-1, 1.0)] public double NtscFringing = 0;
|
||||
[MinMax(-1, 1.0)] public double NtscGamma = 0;
|
||||
[MinMax(-1, 1.0)] public double NtscResolution = 0;
|
||||
[MinMax(-1, 1.0)] public double NtscSharpness = 0;
|
||||
[MarshalAs(UnmanagedType.I1)] public bool NtscMergeFields = false;
|
||||
|
||||
[MarshalAs(UnmanagedType.I1)] public bool FullscreenForceIntegerScale = false;
|
||||
[MarshalAs(UnmanagedType.I1)] public bool UseExclusiveFullscreen = false;
|
||||
public Int32 ExclusiveFullscreenRefreshRate = 60;
|
||||
|
||||
public void ApplyConfig()
|
||||
{
|
||||
ConfigApi.SetVideoConfig(this);
|
||||
}
|
||||
}
|
||||
|
||||
public enum VideoFilterType
|
||||
{
|
||||
None = 0,
|
||||
NTSC,
|
||||
xBRZ2x,
|
||||
xBRZ3x,
|
||||
xBRZ4x,
|
||||
xBRZ5x,
|
||||
xBRZ6x,
|
||||
HQ2x,
|
||||
HQ3x,
|
||||
HQ4x,
|
||||
Scale2x,
|
||||
Scale3x,
|
||||
Scale4x,
|
||||
_2xSai,
|
||||
Super2xSai,
|
||||
SuperEagle,
|
||||
Prescale2x,
|
||||
Prescale3x,
|
||||
Prescale4x,
|
||||
Prescale6x,
|
||||
Prescale8x,
|
||||
Prescale10x
|
||||
}
|
||||
|
||||
public enum VideoAspectRatio
|
||||
{
|
||||
NoStretching = 0,
|
||||
Auto = 1,
|
||||
NTSC = 2,
|
||||
PAL = 3,
|
||||
Standard = 4,
|
||||
Widescreen = 5,
|
||||
Custom = 6
|
||||
}
|
||||
}
|
|
@ -74,11 +74,7 @@ namespace Mesen.GUI.Forms
|
|||
if(this.DialogResult == System.Windows.Forms.DialogResult.OK) {
|
||||
UpdateObject();
|
||||
if(ApplyChangesOnOK) {
|
||||
ConfigManager.ApplyChanges();
|
||||
}
|
||||
} else {
|
||||
if(ApplyChangesOnOK) {
|
||||
ConfigManager.RejectChanges();
|
||||
OnApply();
|
||||
}
|
||||
}
|
||||
base.OnFormClosed(e);
|
||||
|
@ -89,6 +85,9 @@ namespace Mesen.GUI.Forms
|
|||
get { return true; }
|
||||
}
|
||||
|
||||
protected virtual void OnApply()
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual void UpdateConfig()
|
||||
{
|
||||
|
|
900
UI/Forms/Config/frmVideoConfig.Designer.cs
generated
Normal file
900
UI/Forms/Config/frmVideoConfig.Designer.cs
generated
Normal file
|
@ -0,0 +1,900 @@
|
|||
namespace Mesen.GUI.Forms.Config
|
||||
{
|
||||
partial class frmVideoConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if(disposing && (components != null)) {
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.components = new System.ComponentModel.Container();
|
||||
this.tabMain = new System.Windows.Forms.TabControl();
|
||||
this.tpgGeneral = new System.Windows.Forms.TabPage();
|
||||
this.tlpMain = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.chkUseExclusiveFullscreen = new System.Windows.Forms.CheckBox();
|
||||
this.lblVideoScale = new System.Windows.Forms.Label();
|
||||
this.chkVerticalSync = new System.Windows.Forms.CheckBox();
|
||||
this.lblDisplayRatio = new System.Windows.Forms.Label();
|
||||
this.nudScale = new Mesen.GUI.Controls.MesenNumericUpDown();
|
||||
this.flowLayoutPanel6 = new System.Windows.Forms.FlowLayoutPanel();
|
||||
this.cboAspectRatio = new System.Windows.Forms.ComboBox();
|
||||
this.lblCustomRatio = new System.Windows.Forms.Label();
|
||||
this.nudCustomRatio = new Mesen.GUI.Controls.MesenNumericUpDown();
|
||||
this.chkFullscreenForceIntegerScale = new System.Windows.Forms.CheckBox();
|
||||
this.chkShowFps = new System.Windows.Forms.CheckBox();
|
||||
this.chkIntegerFpsMode = new System.Windows.Forms.CheckBox();
|
||||
this.flpRefreshRate = new System.Windows.Forms.FlowLayoutPanel();
|
||||
this.lblRequestedRefreshRate = new System.Windows.Forms.Label();
|
||||
this.cboRefreshRate = new System.Windows.Forms.ComboBox();
|
||||
this.tpgPicture = new System.Windows.Forms.TabPage();
|
||||
this.tableLayoutPanel5 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.tableLayoutPanel7 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.btnSelectPreset = new System.Windows.Forms.Button();
|
||||
this.btnResetPictureSettings = new System.Windows.Forms.Button();
|
||||
this.grpNtscFilter = new System.Windows.Forms.GroupBox();
|
||||
this.tlpNtscFilter = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.chkMergeFields = new System.Windows.Forms.CheckBox();
|
||||
this.trkArtifacts = new Mesen.GUI.Controls.ctrlHorizontalTrackbar();
|
||||
this.trkBleed = new Mesen.GUI.Controls.ctrlHorizontalTrackbar();
|
||||
this.trkFringing = new Mesen.GUI.Controls.ctrlHorizontalTrackbar();
|
||||
this.trkGamma = new Mesen.GUI.Controls.ctrlHorizontalTrackbar();
|
||||
this.trkResolution = new Mesen.GUI.Controls.ctrlHorizontalTrackbar();
|
||||
this.trkSharpness = new Mesen.GUI.Controls.ctrlHorizontalTrackbar();
|
||||
this.grpCommon = new System.Windows.Forms.GroupBox();
|
||||
this.tableLayoutPanel4 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.chkBilinearInterpolation = new System.Windows.Forms.CheckBox();
|
||||
this.trkBrightness = new Mesen.GUI.Controls.ctrlHorizontalTrackbar();
|
||||
this.trkContrast = new Mesen.GUI.Controls.ctrlHorizontalTrackbar();
|
||||
this.trkHue = new Mesen.GUI.Controls.ctrlHorizontalTrackbar();
|
||||
this.trkSaturation = new Mesen.GUI.Controls.ctrlHorizontalTrackbar();
|
||||
this.grpScanlines = new System.Windows.Forms.GroupBox();
|
||||
this.trkScanlines = new Mesen.GUI.Controls.ctrlHorizontalTrackbar();
|
||||
this.tableLayoutPanel8 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.cboFilter = new System.Windows.Forms.ComboBox();
|
||||
this.lblVideoFilter = new System.Windows.Forms.Label();
|
||||
this.ctxPicturePresets = new System.Windows.Forms.ContextMenuStrip(this.components);
|
||||
this.mnuPresetComposite = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuPresetSVideo = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuPresetRgb = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuPresetMonochrome = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.tabMain.SuspendLayout();
|
||||
this.tpgGeneral.SuspendLayout();
|
||||
this.tlpMain.SuspendLayout();
|
||||
this.flowLayoutPanel6.SuspendLayout();
|
||||
this.flpRefreshRate.SuspendLayout();
|
||||
this.tpgPicture.SuspendLayout();
|
||||
this.tableLayoutPanel5.SuspendLayout();
|
||||
this.tableLayoutPanel7.SuspendLayout();
|
||||
this.grpNtscFilter.SuspendLayout();
|
||||
this.tlpNtscFilter.SuspendLayout();
|
||||
this.grpCommon.SuspendLayout();
|
||||
this.tableLayoutPanel4.SuspendLayout();
|
||||
this.grpScanlines.SuspendLayout();
|
||||
this.tableLayoutPanel8.SuspendLayout();
|
||||
this.ctxPicturePresets.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// baseConfigPanel
|
||||
//
|
||||
this.baseConfigPanel.Location = new System.Drawing.Point(0, 408);
|
||||
this.baseConfigPanel.Size = new System.Drawing.Size(574, 29);
|
||||
//
|
||||
// tabMain
|
||||
//
|
||||
this.tabMain.Controls.Add(this.tpgGeneral);
|
||||
this.tabMain.Controls.Add(this.tpgPicture);
|
||||
this.tabMain.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.tabMain.Location = new System.Drawing.Point(0, 0);
|
||||
this.tabMain.Name = "tabMain";
|
||||
this.tabMain.SelectedIndex = 0;
|
||||
this.tabMain.Size = new System.Drawing.Size(574, 408);
|
||||
this.tabMain.TabIndex = 2;
|
||||
//
|
||||
// tpgGeneral
|
||||
//
|
||||
this.tpgGeneral.Controls.Add(this.tlpMain);
|
||||
this.tpgGeneral.Location = new System.Drawing.Point(4, 22);
|
||||
this.tpgGeneral.Name = "tpgGeneral";
|
||||
this.tpgGeneral.Padding = new System.Windows.Forms.Padding(3);
|
||||
this.tpgGeneral.Size = new System.Drawing.Size(566, 382);
|
||||
this.tpgGeneral.TabIndex = 5;
|
||||
this.tpgGeneral.Text = "General";
|
||||
this.tpgGeneral.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// tlpMain
|
||||
//
|
||||
this.tlpMain.ColumnCount = 2;
|
||||
this.tlpMain.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tlpMain.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tlpMain.Controls.Add(this.chkUseExclusiveFullscreen, 0, 4);
|
||||
this.tlpMain.Controls.Add(this.lblVideoScale, 0, 0);
|
||||
this.tlpMain.Controls.Add(this.chkVerticalSync, 0, 3);
|
||||
this.tlpMain.Controls.Add(this.lblDisplayRatio, 0, 1);
|
||||
this.tlpMain.Controls.Add(this.nudScale, 1, 0);
|
||||
this.tlpMain.Controls.Add(this.flowLayoutPanel6, 1, 1);
|
||||
this.tlpMain.Controls.Add(this.chkFullscreenForceIntegerScale, 0, 6);
|
||||
this.tlpMain.Controls.Add(this.chkShowFps, 0, 7);
|
||||
this.tlpMain.Controls.Add(this.chkIntegerFpsMode, 0, 2);
|
||||
this.tlpMain.Controls.Add(this.flpRefreshRate, 0, 5);
|
||||
this.tlpMain.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.tlpMain.Location = new System.Drawing.Point(3, 3);
|
||||
this.tlpMain.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.tlpMain.Name = "tlpMain";
|
||||
this.tlpMain.RowCount = 9;
|
||||
this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tlpMain.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
|
||||
this.tlpMain.Size = new System.Drawing.Size(560, 376);
|
||||
this.tlpMain.TabIndex = 1;
|
||||
//
|
||||
// chkUseExclusiveFullscreen
|
||||
//
|
||||
this.chkUseExclusiveFullscreen.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.chkUseExclusiveFullscreen.AutoSize = true;
|
||||
this.tlpMain.SetColumnSpan(this.chkUseExclusiveFullscreen, 2);
|
||||
this.chkUseExclusiveFullscreen.Location = new System.Drawing.Point(3, 96);
|
||||
this.chkUseExclusiveFullscreen.Name = "chkUseExclusiveFullscreen";
|
||||
this.chkUseExclusiveFullscreen.Size = new System.Drawing.Size(169, 17);
|
||||
this.chkUseExclusiveFullscreen.TabIndex = 24;
|
||||
this.chkUseExclusiveFullscreen.Text = "Use exclusive fullscreen mode";
|
||||
this.chkUseExclusiveFullscreen.UseVisualStyleBackColor = true;
|
||||
this.chkUseExclusiveFullscreen.Visible = false;
|
||||
//
|
||||
// lblVideoScale
|
||||
//
|
||||
this.lblVideoScale.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.lblVideoScale.AutoSize = true;
|
||||
this.lblVideoScale.Location = new System.Drawing.Point(3, 4);
|
||||
this.lblVideoScale.Name = "lblVideoScale";
|
||||
this.lblVideoScale.Size = new System.Drawing.Size(37, 13);
|
||||
this.lblVideoScale.TabIndex = 11;
|
||||
this.lblVideoScale.Text = "Scale:";
|
||||
//
|
||||
// chkVerticalSync
|
||||
//
|
||||
this.chkVerticalSync.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.chkVerticalSync.AutoSize = true;
|
||||
this.tlpMain.SetColumnSpan(this.chkVerticalSync, 2);
|
||||
this.chkVerticalSync.Location = new System.Drawing.Point(3, 73);
|
||||
this.chkVerticalSync.Name = "chkVerticalSync";
|
||||
this.chkVerticalSync.Size = new System.Drawing.Size(121, 17);
|
||||
this.chkVerticalSync.TabIndex = 15;
|
||||
this.chkVerticalSync.Text = "Enable vertical sync";
|
||||
this.chkVerticalSync.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// lblDisplayRatio
|
||||
//
|
||||
this.lblDisplayRatio.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.lblDisplayRatio.AutoSize = true;
|
||||
this.lblDisplayRatio.Location = new System.Drawing.Point(3, 27);
|
||||
this.lblDisplayRatio.Name = "lblDisplayRatio";
|
||||
this.lblDisplayRatio.Size = new System.Drawing.Size(71, 13);
|
||||
this.lblDisplayRatio.TabIndex = 17;
|
||||
this.lblDisplayRatio.Text = "Aspect Ratio:";
|
||||
//
|
||||
// nudScale
|
||||
//
|
||||
this.nudScale.DecimalPlaces = 2;
|
||||
this.nudScale.Increment = new decimal(new int[] {
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.nudScale.Location = new System.Drawing.Point(77, 0);
|
||||
this.nudScale.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.nudScale.Maximum = new decimal(new int[] {
|
||||
10,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.nudScale.MaximumSize = new System.Drawing.Size(10000, 20);
|
||||
this.nudScale.Minimum = new decimal(new int[] {
|
||||
5,
|
||||
0,
|
||||
0,
|
||||
65536});
|
||||
this.nudScale.MinimumSize = new System.Drawing.Size(0, 21);
|
||||
this.nudScale.Name = "nudScale";
|
||||
this.nudScale.Size = new System.Drawing.Size(48, 21);
|
||||
this.nudScale.TabIndex = 21;
|
||||
this.nudScale.Value = new decimal(new int[] {
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
//
|
||||
// flowLayoutPanel6
|
||||
//
|
||||
this.flowLayoutPanel6.Controls.Add(this.cboAspectRatio);
|
||||
this.flowLayoutPanel6.Controls.Add(this.lblCustomRatio);
|
||||
this.flowLayoutPanel6.Controls.Add(this.nudCustomRatio);
|
||||
this.flowLayoutPanel6.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.flowLayoutPanel6.Location = new System.Drawing.Point(77, 21);
|
||||
this.flowLayoutPanel6.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.flowLayoutPanel6.Name = "flowLayoutPanel6";
|
||||
this.flowLayoutPanel6.Size = new System.Drawing.Size(483, 26);
|
||||
this.flowLayoutPanel6.TabIndex = 22;
|
||||
//
|
||||
// cboAspectRatio
|
||||
//
|
||||
this.cboAspectRatio.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
this.cboAspectRatio.FormattingEnabled = true;
|
||||
this.cboAspectRatio.Items.AddRange(new object[] {
|
||||
"Auto",
|
||||
"NTSC (8:7)",
|
||||
"PAL (18:13)",
|
||||
"Standard (4:3)",
|
||||
"Widescreen (16:9)"});
|
||||
this.cboAspectRatio.Location = new System.Drawing.Point(3, 3);
|
||||
this.cboAspectRatio.Name = "cboAspectRatio";
|
||||
this.cboAspectRatio.Size = new System.Drawing.Size(197, 21);
|
||||
this.cboAspectRatio.TabIndex = 16;
|
||||
//
|
||||
// lblCustomRatio
|
||||
//
|
||||
this.lblCustomRatio.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.lblCustomRatio.AutoSize = true;
|
||||
this.lblCustomRatio.Location = new System.Drawing.Point(206, 7);
|
||||
this.lblCustomRatio.Name = "lblCustomRatio";
|
||||
this.lblCustomRatio.Size = new System.Drawing.Size(76, 13);
|
||||
this.lblCustomRatio.TabIndex = 17;
|
||||
this.lblCustomRatio.Text = "Custom Ratio: ";
|
||||
this.lblCustomRatio.Visible = false;
|
||||
//
|
||||
// nudCustomRatio
|
||||
//
|
||||
this.nudCustomRatio.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.nudCustomRatio.DecimalPlaces = 3;
|
||||
this.nudCustomRatio.Increment = new decimal(new int[] {
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
65536});
|
||||
this.nudCustomRatio.Location = new System.Drawing.Point(285, 3);
|
||||
this.nudCustomRatio.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.nudCustomRatio.Maximum = new decimal(new int[] {
|
||||
5,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.nudCustomRatio.MaximumSize = new System.Drawing.Size(10000, 20);
|
||||
this.nudCustomRatio.Minimum = new decimal(new int[] {
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
65536});
|
||||
this.nudCustomRatio.MinimumSize = new System.Drawing.Size(0, 21);
|
||||
this.nudCustomRatio.Name = "nudCustomRatio";
|
||||
this.nudCustomRatio.Size = new System.Drawing.Size(48, 21);
|
||||
this.nudCustomRatio.TabIndex = 22;
|
||||
this.nudCustomRatio.Value = new decimal(new int[] {
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
65536});
|
||||
this.nudCustomRatio.Visible = false;
|
||||
//
|
||||
// chkFullscreenForceIntegerScale
|
||||
//
|
||||
this.chkFullscreenForceIntegerScale.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.chkFullscreenForceIntegerScale.AutoSize = true;
|
||||
this.tlpMain.SetColumnSpan(this.chkFullscreenForceIntegerScale, 2);
|
||||
this.chkFullscreenForceIntegerScale.Location = new System.Drawing.Point(3, 146);
|
||||
this.chkFullscreenForceIntegerScale.Name = "chkFullscreenForceIntegerScale";
|
||||
this.chkFullscreenForceIntegerScale.Size = new System.Drawing.Size(289, 17);
|
||||
this.chkFullscreenForceIntegerScale.TabIndex = 23;
|
||||
this.chkFullscreenForceIntegerScale.Text = "Use integer scale values when entering fullscreen mode";
|
||||
this.chkFullscreenForceIntegerScale.UseVisualStyleBackColor = true;
|
||||
this.chkFullscreenForceIntegerScale.Visible = false;
|
||||
//
|
||||
// chkShowFps
|
||||
//
|
||||
this.chkShowFps.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.chkShowFps.AutoSize = true;
|
||||
this.tlpMain.SetColumnSpan(this.chkShowFps, 2);
|
||||
this.chkShowFps.Location = new System.Drawing.Point(3, 169);
|
||||
this.chkShowFps.Name = "chkShowFps";
|
||||
this.chkShowFps.Size = new System.Drawing.Size(76, 17);
|
||||
this.chkShowFps.TabIndex = 9;
|
||||
this.chkShowFps.Text = "Show FPS";
|
||||
this.chkShowFps.UseVisualStyleBackColor = true;
|
||||
this.chkShowFps.Visible = false;
|
||||
//
|
||||
// chkIntegerFpsMode
|
||||
//
|
||||
this.chkIntegerFpsMode.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.chkIntegerFpsMode.AutoSize = true;
|
||||
this.tlpMain.SetColumnSpan(this.chkIntegerFpsMode, 2);
|
||||
this.chkIntegerFpsMode.Location = new System.Drawing.Point(3, 50);
|
||||
this.chkIntegerFpsMode.Name = "chkIntegerFpsMode";
|
||||
this.chkIntegerFpsMode.Size = new System.Drawing.Size(308, 17);
|
||||
this.chkIntegerFpsMode.TabIndex = 24;
|
||||
this.chkIntegerFpsMode.Text = "Enable integer FPS mode (e.g: run at 60 fps instead of 60.1)";
|
||||
this.chkIntegerFpsMode.UseVisualStyleBackColor = true;
|
||||
this.chkIntegerFpsMode.Visible = false;
|
||||
//
|
||||
// flpRefreshRate
|
||||
//
|
||||
this.tlpMain.SetColumnSpan(this.flpRefreshRate, 2);
|
||||
this.flpRefreshRate.Controls.Add(this.lblRequestedRefreshRate);
|
||||
this.flpRefreshRate.Controls.Add(this.cboRefreshRate);
|
||||
this.flpRefreshRate.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.flpRefreshRate.Location = new System.Drawing.Point(30, 116);
|
||||
this.flpRefreshRate.Margin = new System.Windows.Forms.Padding(30, 0, 0, 0);
|
||||
this.flpRefreshRate.Name = "flpRefreshRate";
|
||||
this.flpRefreshRate.Size = new System.Drawing.Size(530, 27);
|
||||
this.flpRefreshRate.TabIndex = 26;
|
||||
this.flpRefreshRate.Visible = false;
|
||||
//
|
||||
// lblRequestedRefreshRate
|
||||
//
|
||||
this.lblRequestedRefreshRate.Anchor = System.Windows.Forms.AnchorStyles.Right;
|
||||
this.lblRequestedRefreshRate.AutoSize = true;
|
||||
this.lblRequestedRefreshRate.Location = new System.Drawing.Point(3, 7);
|
||||
this.lblRequestedRefreshRate.Name = "lblRequestedRefreshRate";
|
||||
this.lblRequestedRefreshRate.Size = new System.Drawing.Size(128, 13);
|
||||
this.lblRequestedRefreshRate.TabIndex = 17;
|
||||
this.lblRequestedRefreshRate.Text = "Requested Refresh Rate:";
|
||||
//
|
||||
// cboRefreshRate
|
||||
//
|
||||
this.cboRefreshRate.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
this.cboRefreshRate.FormattingEnabled = true;
|
||||
this.cboRefreshRate.Items.AddRange(new object[] {
|
||||
"Auto",
|
||||
"NTSC (8:7)",
|
||||
"PAL (18:13)",
|
||||
"Standard (4:3)",
|
||||
"Widescreen (16:9)"});
|
||||
this.cboRefreshRate.Location = new System.Drawing.Point(137, 3);
|
||||
this.cboRefreshRate.Name = "cboRefreshRate";
|
||||
this.cboRefreshRate.Size = new System.Drawing.Size(68, 21);
|
||||
this.cboRefreshRate.TabIndex = 25;
|
||||
//
|
||||
// tpgPicture
|
||||
//
|
||||
this.tpgPicture.Controls.Add(this.tableLayoutPanel5);
|
||||
this.tpgPicture.Location = new System.Drawing.Point(4, 22);
|
||||
this.tpgPicture.Name = "tpgPicture";
|
||||
this.tpgPicture.Padding = new System.Windows.Forms.Padding(3);
|
||||
this.tpgPicture.Size = new System.Drawing.Size(566, 382);
|
||||
this.tpgPicture.TabIndex = 4;
|
||||
this.tpgPicture.Text = "Picture";
|
||||
this.tpgPicture.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// tableLayoutPanel5
|
||||
//
|
||||
this.tableLayoutPanel5.ColumnCount = 2;
|
||||
this.tableLayoutPanel5.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
|
||||
this.tableLayoutPanel5.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
|
||||
this.tableLayoutPanel5.Controls.Add(this.tableLayoutPanel7, 0, 3);
|
||||
this.tableLayoutPanel5.Controls.Add(this.grpNtscFilter, 1, 1);
|
||||
this.tableLayoutPanel5.Controls.Add(this.grpCommon, 0, 1);
|
||||
this.tableLayoutPanel5.Controls.Add(this.grpScanlines, 0, 2);
|
||||
this.tableLayoutPanel5.Controls.Add(this.tableLayoutPanel8, 0, 0);
|
||||
this.tableLayoutPanel5.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.tableLayoutPanel5.Location = new System.Drawing.Point(3, 3);
|
||||
this.tableLayoutPanel5.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.tableLayoutPanel5.Name = "tableLayoutPanel5";
|
||||
this.tableLayoutPanel5.RowCount = 4;
|
||||
this.tableLayoutPanel5.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel5.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel5.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel5.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tableLayoutPanel5.Size = new System.Drawing.Size(560, 376);
|
||||
this.tableLayoutPanel5.TabIndex = 5;
|
||||
//
|
||||
// tableLayoutPanel7
|
||||
//
|
||||
this.tableLayoutPanel7.ColumnCount = 2;
|
||||
this.tableLayoutPanel7.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 36.92308F));
|
||||
this.tableLayoutPanel7.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 63.07692F));
|
||||
this.tableLayoutPanel7.Controls.Add(this.btnSelectPreset, 1, 0);
|
||||
this.tableLayoutPanel7.Controls.Add(this.btnResetPictureSettings, 0, 0);
|
||||
this.tableLayoutPanel7.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.tableLayoutPanel7.Location = new System.Drawing.Point(0, 341);
|
||||
this.tableLayoutPanel7.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.tableLayoutPanel7.Name = "tableLayoutPanel7";
|
||||
this.tableLayoutPanel7.RowCount = 1;
|
||||
this.tableLayoutPanel7.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
|
||||
this.tableLayoutPanel7.Size = new System.Drawing.Size(280, 35);
|
||||
this.tableLayoutPanel7.TabIndex = 3;
|
||||
//
|
||||
// btnSelectPreset
|
||||
//
|
||||
this.btnSelectPreset.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.btnSelectPreset.AutoSize = true;
|
||||
this.btnSelectPreset.Image = global::Mesen.GUI.Properties.Resources.DownArrow;
|
||||
this.btnSelectPreset.ImageAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||
this.btnSelectPreset.Location = new System.Drawing.Point(178, 9);
|
||||
this.btnSelectPreset.Name = "btnSelectPreset";
|
||||
this.btnSelectPreset.Padding = new System.Windows.Forms.Padding(0, 0, 3, 0);
|
||||
this.btnSelectPreset.Size = new System.Drawing.Size(99, 23);
|
||||
this.btnSelectPreset.TabIndex = 3;
|
||||
this.btnSelectPreset.Text = "Select Preset...";
|
||||
this.btnSelectPreset.TextImageRelation = System.Windows.Forms.TextImageRelation.TextBeforeImage;
|
||||
this.btnSelectPreset.UseVisualStyleBackColor = true;
|
||||
this.btnSelectPreset.Click += new System.EventHandler(this.btnSelectPreset_Click);
|
||||
//
|
||||
// btnResetPictureSettings
|
||||
//
|
||||
this.btnResetPictureSettings.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.btnResetPictureSettings.AutoSize = true;
|
||||
this.btnResetPictureSettings.Location = new System.Drawing.Point(3, 9);
|
||||
this.btnResetPictureSettings.Name = "btnResetPictureSettings";
|
||||
this.btnResetPictureSettings.Size = new System.Drawing.Size(45, 23);
|
||||
this.btnResetPictureSettings.TabIndex = 3;
|
||||
this.btnResetPictureSettings.Text = "Reset";
|
||||
this.btnResetPictureSettings.UseVisualStyleBackColor = true;
|
||||
this.btnResetPictureSettings.Click += new System.EventHandler(this.btnResetPictureSettings_Click);
|
||||
//
|
||||
// grpNtscFilter
|
||||
//
|
||||
this.grpNtscFilter.Controls.Add(this.tlpNtscFilter);
|
||||
this.grpNtscFilter.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.grpNtscFilter.Location = new System.Drawing.Point(282, 27);
|
||||
this.grpNtscFilter.Margin = new System.Windows.Forms.Padding(2, 0, 0, 0);
|
||||
this.grpNtscFilter.Name = "grpNtscFilter";
|
||||
this.tableLayoutPanel5.SetRowSpan(this.grpNtscFilter, 3);
|
||||
this.grpNtscFilter.Size = new System.Drawing.Size(278, 349);
|
||||
this.grpNtscFilter.TabIndex = 4;
|
||||
this.grpNtscFilter.TabStop = false;
|
||||
this.grpNtscFilter.Text = "NTSC Filter";
|
||||
//
|
||||
// tlpNtscFilter
|
||||
//
|
||||
this.tlpNtscFilter.ColumnCount = 1;
|
||||
this.tlpNtscFilter.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tlpNtscFilter.Controls.Add(this.chkMergeFields, 0, 6);
|
||||
this.tlpNtscFilter.Controls.Add(this.trkArtifacts, 0, 0);
|
||||
this.tlpNtscFilter.Controls.Add(this.trkBleed, 0, 1);
|
||||
this.tlpNtscFilter.Controls.Add(this.trkFringing, 0, 2);
|
||||
this.tlpNtscFilter.Controls.Add(this.trkGamma, 0, 3);
|
||||
this.tlpNtscFilter.Controls.Add(this.trkResolution, 0, 4);
|
||||
this.tlpNtscFilter.Controls.Add(this.trkSharpness, 0, 5);
|
||||
this.tlpNtscFilter.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.tlpNtscFilter.Location = new System.Drawing.Point(3, 16);
|
||||
this.tlpNtscFilter.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.tlpNtscFilter.Name = "tlpNtscFilter";
|
||||
this.tlpNtscFilter.RowCount = 7;
|
||||
this.tlpNtscFilter.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tlpNtscFilter.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tlpNtscFilter.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tlpNtscFilter.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tlpNtscFilter.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tlpNtscFilter.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tlpNtscFilter.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tlpNtscFilter.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
|
||||
this.tlpNtscFilter.Size = new System.Drawing.Size(272, 330);
|
||||
this.tlpNtscFilter.TabIndex = 5;
|
||||
//
|
||||
// chkMergeFields
|
||||
//
|
||||
this.chkMergeFields.AutoSize = true;
|
||||
this.chkMergeFields.Location = new System.Drawing.Point(3, 303);
|
||||
this.chkMergeFields.Name = "chkMergeFields";
|
||||
this.chkMergeFields.Size = new System.Drawing.Size(86, 17);
|
||||
this.chkMergeFields.TabIndex = 30;
|
||||
this.chkMergeFields.Text = "Merge Fields";
|
||||
this.chkMergeFields.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// trkArtifacts
|
||||
//
|
||||
this.trkArtifacts.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.trkArtifacts.Location = new System.Drawing.Point(0, 0);
|
||||
this.trkArtifacts.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.trkArtifacts.Maximum = 100;
|
||||
this.trkArtifacts.MaximumSize = new System.Drawing.Size(0, 60);
|
||||
this.trkArtifacts.Minimum = -100;
|
||||
this.trkArtifacts.MinimumSize = new System.Drawing.Size(206, 50);
|
||||
this.trkArtifacts.Name = "trkArtifacts";
|
||||
this.trkArtifacts.Size = new System.Drawing.Size(272, 50);
|
||||
this.trkArtifacts.TabIndex = 24;
|
||||
this.trkArtifacts.Text = "Artifacts";
|
||||
this.trkArtifacts.Value = 0;
|
||||
//
|
||||
// trkBleed
|
||||
//
|
||||
this.trkBleed.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.trkBleed.Location = new System.Drawing.Point(0, 50);
|
||||
this.trkBleed.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.trkBleed.Maximum = 100;
|
||||
this.trkBleed.MaximumSize = new System.Drawing.Size(400, 55);
|
||||
this.trkBleed.Minimum = -100;
|
||||
this.trkBleed.MinimumSize = new System.Drawing.Size(206, 50);
|
||||
this.trkBleed.Name = "trkBleed";
|
||||
this.trkBleed.Size = new System.Drawing.Size(272, 50);
|
||||
this.trkBleed.TabIndex = 25;
|
||||
this.trkBleed.Text = "Bleed";
|
||||
this.trkBleed.Value = 0;
|
||||
//
|
||||
// trkFringing
|
||||
//
|
||||
this.trkFringing.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.trkFringing.Location = new System.Drawing.Point(0, 100);
|
||||
this.trkFringing.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.trkFringing.Maximum = 100;
|
||||
this.trkFringing.MaximumSize = new System.Drawing.Size(0, 41);
|
||||
this.trkFringing.Minimum = -100;
|
||||
this.trkFringing.MinimumSize = new System.Drawing.Size(206, 50);
|
||||
this.trkFringing.Name = "trkFringing";
|
||||
this.trkFringing.Size = new System.Drawing.Size(272, 50);
|
||||
this.trkFringing.TabIndex = 26;
|
||||
this.trkFringing.Text = "Fringing";
|
||||
this.trkFringing.Value = 0;
|
||||
//
|
||||
// trkGamma
|
||||
//
|
||||
this.trkGamma.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.trkGamma.Location = new System.Drawing.Point(0, 150);
|
||||
this.trkGamma.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.trkGamma.Maximum = 100;
|
||||
this.trkGamma.MaximumSize = new System.Drawing.Size(0, 41);
|
||||
this.trkGamma.Minimum = -100;
|
||||
this.trkGamma.MinimumSize = new System.Drawing.Size(206, 50);
|
||||
this.trkGamma.Name = "trkGamma";
|
||||
this.trkGamma.Size = new System.Drawing.Size(272, 50);
|
||||
this.trkGamma.TabIndex = 27;
|
||||
this.trkGamma.Text = "Gamma";
|
||||
this.trkGamma.Value = 0;
|
||||
//
|
||||
// trkResolution
|
||||
//
|
||||
this.trkResolution.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.trkResolution.Location = new System.Drawing.Point(0, 200);
|
||||
this.trkResolution.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.trkResolution.Maximum = 100;
|
||||
this.trkResolution.MaximumSize = new System.Drawing.Size(0, 41);
|
||||
this.trkResolution.Minimum = -100;
|
||||
this.trkResolution.MinimumSize = new System.Drawing.Size(206, 50);
|
||||
this.trkResolution.Name = "trkResolution";
|
||||
this.trkResolution.Size = new System.Drawing.Size(272, 50);
|
||||
this.trkResolution.TabIndex = 28;
|
||||
this.trkResolution.Text = "Resolution";
|
||||
this.trkResolution.Value = 0;
|
||||
//
|
||||
// trkSharpness
|
||||
//
|
||||
this.trkSharpness.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.trkSharpness.Location = new System.Drawing.Point(0, 250);
|
||||
this.trkSharpness.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.trkSharpness.Maximum = 100;
|
||||
this.trkSharpness.MaximumSize = new System.Drawing.Size(0, 41);
|
||||
this.trkSharpness.Minimum = -100;
|
||||
this.trkSharpness.MinimumSize = new System.Drawing.Size(206, 50);
|
||||
this.trkSharpness.Name = "trkSharpness";
|
||||
this.trkSharpness.Size = new System.Drawing.Size(272, 50);
|
||||
this.trkSharpness.TabIndex = 29;
|
||||
this.trkSharpness.Text = "Sharpness";
|
||||
this.trkSharpness.Value = 0;
|
||||
//
|
||||
// grpCommon
|
||||
//
|
||||
this.grpCommon.Controls.Add(this.tableLayoutPanel4);
|
||||
this.grpCommon.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.grpCommon.Location = new System.Drawing.Point(0, 27);
|
||||
this.grpCommon.Margin = new System.Windows.Forms.Padding(0, 0, 2, 0);
|
||||
this.grpCommon.Name = "grpCommon";
|
||||
this.grpCommon.Padding = new System.Windows.Forms.Padding(3, 2, 3, 2);
|
||||
this.grpCommon.Size = new System.Drawing.Size(278, 242);
|
||||
this.grpCommon.TabIndex = 3;
|
||||
this.grpCommon.TabStop = false;
|
||||
this.grpCommon.Text = "Common Settings";
|
||||
//
|
||||
// tableLayoutPanel4
|
||||
//
|
||||
this.tableLayoutPanel4.ColumnCount = 1;
|
||||
this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F));
|
||||
this.tableLayoutPanel4.Controls.Add(this.chkBilinearInterpolation, 0, 4);
|
||||
this.tableLayoutPanel4.Controls.Add(this.trkBrightness, 0, 0);
|
||||
this.tableLayoutPanel4.Controls.Add(this.trkContrast, 0, 1);
|
||||
this.tableLayoutPanel4.Controls.Add(this.trkHue, 0, 2);
|
||||
this.tableLayoutPanel4.Controls.Add(this.trkSaturation, 0, 3);
|
||||
this.tableLayoutPanel4.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.tableLayoutPanel4.Location = new System.Drawing.Point(3, 15);
|
||||
this.tableLayoutPanel4.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.tableLayoutPanel4.Name = "tableLayoutPanel4";
|
||||
this.tableLayoutPanel4.RowCount = 5;
|
||||
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle());
|
||||
this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tableLayoutPanel4.Size = new System.Drawing.Size(272, 225);
|
||||
this.tableLayoutPanel4.TabIndex = 4;
|
||||
//
|
||||
// chkBilinearInterpolation
|
||||
//
|
||||
this.chkBilinearInterpolation.AutoSize = true;
|
||||
this.tableLayoutPanel4.SetColumnSpan(this.chkBilinearInterpolation, 2);
|
||||
this.chkBilinearInterpolation.Location = new System.Drawing.Point(3, 203);
|
||||
this.chkBilinearInterpolation.Name = "chkBilinearInterpolation";
|
||||
this.chkBilinearInterpolation.Size = new System.Drawing.Size(206, 17);
|
||||
this.chkBilinearInterpolation.TabIndex = 28;
|
||||
this.chkBilinearInterpolation.Text = "Use bilinear interpolation when scaling";
|
||||
this.chkBilinearInterpolation.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// trkBrightness
|
||||
//
|
||||
this.trkBrightness.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.trkBrightness.Location = new System.Drawing.Point(0, 0);
|
||||
this.trkBrightness.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.trkBrightness.Maximum = 100;
|
||||
this.trkBrightness.MaximumSize = new System.Drawing.Size(0, 60);
|
||||
this.trkBrightness.Minimum = -100;
|
||||
this.trkBrightness.MinimumSize = new System.Drawing.Size(206, 50);
|
||||
this.trkBrightness.Name = "trkBrightness";
|
||||
this.trkBrightness.Size = new System.Drawing.Size(272, 50);
|
||||
this.trkBrightness.TabIndex = 24;
|
||||
this.trkBrightness.Text = "Brightness";
|
||||
this.trkBrightness.Value = 0;
|
||||
//
|
||||
// trkContrast
|
||||
//
|
||||
this.trkContrast.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.trkContrast.Location = new System.Drawing.Point(0, 50);
|
||||
this.trkContrast.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.trkContrast.Maximum = 100;
|
||||
this.trkContrast.MaximumSize = new System.Drawing.Size(400, 55);
|
||||
this.trkContrast.Minimum = -100;
|
||||
this.trkContrast.MinimumSize = new System.Drawing.Size(206, 50);
|
||||
this.trkContrast.Name = "trkContrast";
|
||||
this.trkContrast.Size = new System.Drawing.Size(272, 50);
|
||||
this.trkContrast.TabIndex = 25;
|
||||
this.trkContrast.Text = "Contrast";
|
||||
this.trkContrast.Value = 0;
|
||||
//
|
||||
// trkHue
|
||||
//
|
||||
this.trkHue.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.trkHue.Location = new System.Drawing.Point(0, 100);
|
||||
this.trkHue.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.trkHue.Maximum = 100;
|
||||
this.trkHue.MaximumSize = new System.Drawing.Size(0, 41);
|
||||
this.trkHue.Minimum = -100;
|
||||
this.trkHue.MinimumSize = new System.Drawing.Size(206, 50);
|
||||
this.trkHue.Name = "trkHue";
|
||||
this.trkHue.Size = new System.Drawing.Size(272, 50);
|
||||
this.trkHue.TabIndex = 26;
|
||||
this.trkHue.Text = "Hue";
|
||||
this.trkHue.Value = 0;
|
||||
//
|
||||
// trkSaturation
|
||||
//
|
||||
this.trkSaturation.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.trkSaturation.Location = new System.Drawing.Point(0, 150);
|
||||
this.trkSaturation.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.trkSaturation.Maximum = 100;
|
||||
this.trkSaturation.MaximumSize = new System.Drawing.Size(0, 41);
|
||||
this.trkSaturation.Minimum = -100;
|
||||
this.trkSaturation.MinimumSize = new System.Drawing.Size(206, 50);
|
||||
this.trkSaturation.Name = "trkSaturation";
|
||||
this.trkSaturation.Size = new System.Drawing.Size(272, 50);
|
||||
this.trkSaturation.TabIndex = 27;
|
||||
this.trkSaturation.Text = "Saturation";
|
||||
this.trkSaturation.Value = 0;
|
||||
//
|
||||
// grpScanlines
|
||||
//
|
||||
this.grpScanlines.Controls.Add(this.trkScanlines);
|
||||
this.grpScanlines.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.grpScanlines.Location = new System.Drawing.Point(0, 269);
|
||||
this.grpScanlines.Margin = new System.Windows.Forms.Padding(0, 0, 2, 0);
|
||||
this.grpScanlines.Name = "grpScanlines";
|
||||
this.grpScanlines.Size = new System.Drawing.Size(278, 72);
|
||||
this.grpScanlines.TabIndex = 5;
|
||||
this.grpScanlines.TabStop = false;
|
||||
this.grpScanlines.Text = "Scanlines";
|
||||
//
|
||||
// trkScanlines
|
||||
//
|
||||
this.trkScanlines.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.trkScanlines.Location = new System.Drawing.Point(3, 16);
|
||||
this.trkScanlines.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.trkScanlines.Maximum = 100;
|
||||
this.trkScanlines.MaximumSize = new System.Drawing.Size(0, 41);
|
||||
this.trkScanlines.Minimum = 0;
|
||||
this.trkScanlines.MinimumSize = new System.Drawing.Size(206, 50);
|
||||
this.trkScanlines.Name = "trkScanlines";
|
||||
this.trkScanlines.Size = new System.Drawing.Size(272, 50);
|
||||
this.trkScanlines.TabIndex = 28;
|
||||
this.trkScanlines.Text = "Scanlines";
|
||||
this.trkScanlines.Value = 0;
|
||||
//
|
||||
// tableLayoutPanel8
|
||||
//
|
||||
this.tableLayoutPanel8.ColumnCount = 2;
|
||||
this.tableLayoutPanel5.SetColumnSpan(this.tableLayoutPanel8, 2);
|
||||
this.tableLayoutPanel8.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
|
||||
this.tableLayoutPanel8.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tableLayoutPanel8.Controls.Add(this.cboFilter, 1, 0);
|
||||
this.tableLayoutPanel8.Controls.Add(this.lblVideoFilter, 0, 0);
|
||||
this.tableLayoutPanel8.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.tableLayoutPanel8.Location = new System.Drawing.Point(0, 0);
|
||||
this.tableLayoutPanel8.Margin = new System.Windows.Forms.Padding(0);
|
||||
this.tableLayoutPanel8.Name = "tableLayoutPanel8";
|
||||
this.tableLayoutPanel8.RowCount = 1;
|
||||
this.tableLayoutPanel8.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
|
||||
this.tableLayoutPanel8.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 27F));
|
||||
this.tableLayoutPanel8.Size = new System.Drawing.Size(560, 27);
|
||||
this.tableLayoutPanel8.TabIndex = 6;
|
||||
//
|
||||
// cboFilter
|
||||
//
|
||||
this.cboFilter.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.cboFilter.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
this.cboFilter.FormattingEnabled = true;
|
||||
this.cboFilter.Items.AddRange(new object[] {
|
||||
"None",
|
||||
"NTSC"});
|
||||
this.cboFilter.Location = new System.Drawing.Point(41, 3);
|
||||
this.cboFilter.Name = "cboFilter";
|
||||
this.cboFilter.Size = new System.Drawing.Size(516, 21);
|
||||
this.cboFilter.TabIndex = 15;
|
||||
//
|
||||
// lblVideoFilter
|
||||
//
|
||||
this.lblVideoFilter.Anchor = System.Windows.Forms.AnchorStyles.Left;
|
||||
this.lblVideoFilter.AutoSize = true;
|
||||
this.lblVideoFilter.Location = new System.Drawing.Point(3, 7);
|
||||
this.lblVideoFilter.Name = "lblVideoFilter";
|
||||
this.lblVideoFilter.Size = new System.Drawing.Size(32, 13);
|
||||
this.lblVideoFilter.TabIndex = 13;
|
||||
this.lblVideoFilter.Text = "Filter:";
|
||||
//
|
||||
// ctxPicturePresets
|
||||
//
|
||||
this.ctxPicturePresets.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.mnuPresetComposite,
|
||||
this.mnuPresetSVideo,
|
||||
this.mnuPresetRgb,
|
||||
this.mnuPresetMonochrome});
|
||||
this.ctxPicturePresets.Name = "contextPicturePresets";
|
||||
this.ctxPicturePresets.Size = new System.Drawing.Size(148, 92);
|
||||
//
|
||||
// mnuPresetComposite
|
||||
//
|
||||
this.mnuPresetComposite.Name = "mnuPresetComposite";
|
||||
this.mnuPresetComposite.Size = new System.Drawing.Size(147, 22);
|
||||
this.mnuPresetComposite.Text = "Composite";
|
||||
this.mnuPresetComposite.Click += new System.EventHandler(this.mnuPresetComposite_Click);
|
||||
//
|
||||
// mnuPresetSVideo
|
||||
//
|
||||
this.mnuPresetSVideo.Name = "mnuPresetSVideo";
|
||||
this.mnuPresetSVideo.Size = new System.Drawing.Size(147, 22);
|
||||
this.mnuPresetSVideo.Text = "S-Video";
|
||||
this.mnuPresetSVideo.Click += new System.EventHandler(this.mnuPresetSVideo_Click);
|
||||
//
|
||||
// mnuPresetRgb
|
||||
//
|
||||
this.mnuPresetRgb.Name = "mnuPresetRgb";
|
||||
this.mnuPresetRgb.Size = new System.Drawing.Size(147, 22);
|
||||
this.mnuPresetRgb.Text = "RGB";
|
||||
this.mnuPresetRgb.Click += new System.EventHandler(this.mnuPresetRgb_Click);
|
||||
//
|
||||
// mnuPresetMonochrome
|
||||
//
|
||||
this.mnuPresetMonochrome.Name = "mnuPresetMonochrome";
|
||||
this.mnuPresetMonochrome.Size = new System.Drawing.Size(147, 22);
|
||||
this.mnuPresetMonochrome.Text = "Monochrome";
|
||||
this.mnuPresetMonochrome.Click += new System.EventHandler(this.mnuPresetMonochrome_Click);
|
||||
//
|
||||
// frmVideoConfig
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(574, 437);
|
||||
this.Controls.Add(this.tabMain);
|
||||
this.Name = "frmVideoConfig";
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
||||
this.Text = "frmVideoConfig";
|
||||
this.Controls.SetChildIndex(this.baseConfigPanel, 0);
|
||||
this.Controls.SetChildIndex(this.tabMain, 0);
|
||||
this.tabMain.ResumeLayout(false);
|
||||
this.tpgGeneral.ResumeLayout(false);
|
||||
this.tlpMain.ResumeLayout(false);
|
||||
this.tlpMain.PerformLayout();
|
||||
this.flowLayoutPanel6.ResumeLayout(false);
|
||||
this.flowLayoutPanel6.PerformLayout();
|
||||
this.flpRefreshRate.ResumeLayout(false);
|
||||
this.flpRefreshRate.PerformLayout();
|
||||
this.tpgPicture.ResumeLayout(false);
|
||||
this.tableLayoutPanel5.ResumeLayout(false);
|
||||
this.tableLayoutPanel7.ResumeLayout(false);
|
||||
this.tableLayoutPanel7.PerformLayout();
|
||||
this.grpNtscFilter.ResumeLayout(false);
|
||||
this.tlpNtscFilter.ResumeLayout(false);
|
||||
this.tlpNtscFilter.PerformLayout();
|
||||
this.grpCommon.ResumeLayout(false);
|
||||
this.tableLayoutPanel4.ResumeLayout(false);
|
||||
this.tableLayoutPanel4.PerformLayout();
|
||||
this.grpScanlines.ResumeLayout(false);
|
||||
this.tableLayoutPanel8.ResumeLayout(false);
|
||||
this.tableLayoutPanel8.PerformLayout();
|
||||
this.ctxPicturePresets.ResumeLayout(false);
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.TabControl tabMain;
|
||||
private System.Windows.Forms.TabPage tpgGeneral;
|
||||
private System.Windows.Forms.TableLayoutPanel tlpMain;
|
||||
private System.Windows.Forms.CheckBox chkUseExclusiveFullscreen;
|
||||
private System.Windows.Forms.Label lblVideoScale;
|
||||
private System.Windows.Forms.CheckBox chkVerticalSync;
|
||||
private System.Windows.Forms.Label lblDisplayRatio;
|
||||
private Controls.MesenNumericUpDown nudScale;
|
||||
private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel6;
|
||||
private System.Windows.Forms.ComboBox cboAspectRatio;
|
||||
private System.Windows.Forms.Label lblCustomRatio;
|
||||
private Controls.MesenNumericUpDown nudCustomRatio;
|
||||
private System.Windows.Forms.CheckBox chkFullscreenForceIntegerScale;
|
||||
private System.Windows.Forms.CheckBox chkShowFps;
|
||||
private System.Windows.Forms.CheckBox chkIntegerFpsMode;
|
||||
private System.Windows.Forms.FlowLayoutPanel flpRefreshRate;
|
||||
private System.Windows.Forms.Label lblRequestedRefreshRate;
|
||||
private System.Windows.Forms.ComboBox cboRefreshRate;
|
||||
private System.Windows.Forms.TabPage tpgPicture;
|
||||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel5;
|
||||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel7;
|
||||
private System.Windows.Forms.Button btnSelectPreset;
|
||||
private System.Windows.Forms.Button btnResetPictureSettings;
|
||||
private System.Windows.Forms.GroupBox grpNtscFilter;
|
||||
private System.Windows.Forms.TableLayoutPanel tlpNtscFilter;
|
||||
private System.Windows.Forms.CheckBox chkMergeFields;
|
||||
private Controls.ctrlHorizontalTrackbar trkArtifacts;
|
||||
private Controls.ctrlHorizontalTrackbar trkBleed;
|
||||
private Controls.ctrlHorizontalTrackbar trkFringing;
|
||||
private Controls.ctrlHorizontalTrackbar trkGamma;
|
||||
private Controls.ctrlHorizontalTrackbar trkResolution;
|
||||
private Controls.ctrlHorizontalTrackbar trkSharpness;
|
||||
private System.Windows.Forms.GroupBox grpCommon;
|
||||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel4;
|
||||
private System.Windows.Forms.CheckBox chkBilinearInterpolation;
|
||||
private Controls.ctrlHorizontalTrackbar trkBrightness;
|
||||
private Controls.ctrlHorizontalTrackbar trkContrast;
|
||||
private Controls.ctrlHorizontalTrackbar trkHue;
|
||||
private Controls.ctrlHorizontalTrackbar trkSaturation;
|
||||
private System.Windows.Forms.GroupBox grpScanlines;
|
||||
private Controls.ctrlHorizontalTrackbar trkScanlines;
|
||||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel8;
|
||||
private System.Windows.Forms.ComboBox cboFilter;
|
||||
private System.Windows.Forms.Label lblVideoFilter;
|
||||
private System.Windows.Forms.ContextMenuStrip ctxPicturePresets;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuPresetComposite;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuPresetSVideo;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuPresetRgb;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuPresetMonochrome;
|
||||
}
|
||||
}
|
128
UI/Forms/Config/frmVideoConfig.cs
Normal file
128
UI/Forms/Config/frmVideoConfig.cs
Normal file
|
@ -0,0 +1,128 @@
|
|||
using Mesen.GUI.Config;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Mesen.GUI.Forms.Config
|
||||
{
|
||||
public partial class frmVideoConfig : BaseConfigForm
|
||||
{
|
||||
public frmVideoConfig()
|
||||
{
|
||||
InitializeComponent();
|
||||
if(DesignMode) {
|
||||
return;
|
||||
}
|
||||
|
||||
Entity = ConfigManager.Config.Video.Clone();
|
||||
|
||||
//AddBinding(nameof(VideoConfig.ShowFPS), chkShowFps);
|
||||
AddBinding(nameof(VideoConfig.UseBilinearInterpolation), chkBilinearInterpolation);
|
||||
AddBinding(nameof(VideoConfig.VerticalSync), chkVerticalSync);
|
||||
AddBinding(nameof(VideoConfig.IntegerFpsMode), chkIntegerFpsMode);
|
||||
AddBinding(nameof(VideoConfig.FullscreenForceIntegerScale), chkFullscreenForceIntegerScale);
|
||||
AddBinding(nameof(VideoConfig.UseExclusiveFullscreen), chkUseExclusiveFullscreen);
|
||||
AddBinding(nameof(VideoConfig.ExclusiveFullscreenRefreshRate), cboRefreshRate);
|
||||
|
||||
AddBinding(nameof(VideoConfig.VideoScale), nudScale);
|
||||
AddBinding(nameof(VideoConfig.AspectRatio), cboAspectRatio);
|
||||
AddBinding(nameof(VideoConfig.CustomAspectRatio), nudCustomRatio);
|
||||
AddBinding(nameof(VideoConfig.VideoFilter), cboFilter);
|
||||
|
||||
AddBinding(nameof(VideoConfig.Brightness), trkBrightness);
|
||||
AddBinding(nameof(VideoConfig.Contrast), trkContrast);
|
||||
AddBinding(nameof(VideoConfig.Hue), trkHue);
|
||||
AddBinding(nameof(VideoConfig.Saturation), trkSaturation);
|
||||
AddBinding(nameof(VideoConfig.ScanlineIntensity), trkScanlines);
|
||||
|
||||
AddBinding(nameof(VideoConfig.NtscArtifacts), trkArtifacts);
|
||||
AddBinding(nameof(VideoConfig.NtscBleed), trkBleed);
|
||||
AddBinding(nameof(VideoConfig.NtscFringing), trkFringing);
|
||||
AddBinding(nameof(VideoConfig.NtscGamma), trkGamma);
|
||||
AddBinding(nameof(VideoConfig.NtscResolution), trkResolution);
|
||||
AddBinding(nameof(VideoConfig.NtscSharpness), trkSharpness);
|
||||
AddBinding(nameof(VideoConfig.NtscMergeFields), chkMergeFields);
|
||||
}
|
||||
|
||||
protected override bool ValidateInput()
|
||||
{
|
||||
UpdateObject();
|
||||
UpdateCustomRatioVisibility();
|
||||
|
||||
VideoFilterType filter = ((VideoConfig)Entity).VideoFilter;
|
||||
grpNtscFilter.Visible = (filter == VideoFilterType.NTSC);
|
||||
|
||||
((VideoConfig)this.Entity).ApplyConfig();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void OnApply()
|
||||
{
|
||||
ConfigManager.Config.Video = (VideoConfig)this.Entity;
|
||||
ConfigManager.ApplyChanges();
|
||||
}
|
||||
|
||||
private void UpdateCustomRatioVisibility()
|
||||
{
|
||||
VideoAspectRatio ratio = cboAspectRatio.GetEnumValue<VideoAspectRatio>();
|
||||
lblCustomRatio.Visible = ratio == VideoAspectRatio.Custom;
|
||||
nudCustomRatio.Visible = ratio == VideoAspectRatio.Custom;
|
||||
}
|
||||
|
||||
private void btnResetPictureSettings_Click(object sender, EventArgs e)
|
||||
{
|
||||
SetNtscPreset(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false);
|
||||
cboFilter.SetEnumValue(VideoFilterType.None);
|
||||
}
|
||||
|
||||
private void btnSelectPreset_Click(object sender, EventArgs e)
|
||||
{
|
||||
ctxPicturePresets.Show(btnSelectPreset.PointToScreen(new Point(0, btnSelectPreset.Height - 1)));
|
||||
}
|
||||
|
||||
private void SetNtscPreset(int hue, int saturation, int contrast, int brightness, int sharpness, int gamma, int resolution, int artifacts, int fringing, int bleed, int scanlines, bool mergeFields)
|
||||
{
|
||||
cboFilter.SetEnumValue(VideoFilterType.NTSC);
|
||||
trkHue.Value = hue;
|
||||
trkSaturation.Value = saturation;
|
||||
trkContrast.Value = contrast;
|
||||
trkBrightness.Value = brightness;
|
||||
trkSharpness.Value = sharpness;
|
||||
trkGamma.Value = gamma;
|
||||
trkResolution.Value = resolution;
|
||||
trkArtifacts.Value = artifacts;
|
||||
trkFringing.Value = fringing;
|
||||
trkBleed.Value = bleed;
|
||||
chkMergeFields.Checked = mergeFields;
|
||||
|
||||
trkScanlines.Value = scanlines;
|
||||
}
|
||||
|
||||
private void mnuPresetComposite_Click(object sender, EventArgs e)
|
||||
{
|
||||
SetNtscPreset(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, false);
|
||||
}
|
||||
|
||||
private void mnuPresetSVideo_Click(object sender, EventArgs e)
|
||||
{
|
||||
SetNtscPreset(0, 0, 0, 0, 20, 0, 20, -100, -100, 0, 15, false);
|
||||
}
|
||||
|
||||
private void mnuPresetRgb_Click(object sender, EventArgs e)
|
||||
{
|
||||
SetNtscPreset(0, 0, 0, 0, 20, 0, 70, -100, -100, -100, 15, false);
|
||||
}
|
||||
|
||||
private void mnuPresetMonochrome_Click(object sender, EventArgs e)
|
||||
{
|
||||
SetNtscPreset(0, -100, 0, 0, 20, 0, 70, -20, -20, -10, 15, false);
|
||||
}
|
||||
}
|
||||
}
|
126
UI/Forms/Config/frmVideoConfig.resx
Normal file
126
UI/Forms/Config/frmVideoConfig.resx
Normal file
|
@ -0,0 +1,126 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<metadata name="toolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
<metadata name="ctxPicturePresets.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>107, 17</value>
|
||||
</metadata>
|
||||
</root>
|
|
@ -102,7 +102,11 @@ namespace Mesen.GUI.Forms
|
|||
((ctrlTrackbar)kvp.Value).Value = (int)(uint)value;
|
||||
}
|
||||
} else if(kvp.Value is ctrlHorizontalTrackbar) {
|
||||
((ctrlHorizontalTrackbar)kvp.Value).Value = (int)value;
|
||||
if(field.FieldType == typeof(double)) {
|
||||
((ctrlHorizontalTrackbar)kvp.Value).Value = (int)((double)value * 100);
|
||||
} else {
|
||||
((ctrlHorizontalTrackbar)kvp.Value).Value = (int)value;
|
||||
}
|
||||
} else if(kvp.Value is TrackBar) {
|
||||
if(field.FieldType == typeof(Int32)) {
|
||||
((TrackBar)kvp.Value).Value = (int)value;
|
||||
|
@ -236,7 +240,11 @@ namespace Mesen.GUI.Forms
|
|||
field.SetValue(Entity, (UInt32)((ctrlTrackbar)kvp.Value).Value);
|
||||
}
|
||||
} else if(kvp.Value is ctrlHorizontalTrackbar) {
|
||||
field.SetValue(Entity, (Int32)((ctrlHorizontalTrackbar)kvp.Value).Value);
|
||||
if(field.FieldType == typeof(double)) {
|
||||
field.SetValue(Entity, ((ctrlHorizontalTrackbar)kvp.Value).Value / 100.0);
|
||||
} else {
|
||||
field.SetValue(Entity, (Int32)((ctrlHorizontalTrackbar)kvp.Value).Value);
|
||||
}
|
||||
} else if(kvp.Value is TrackBar) {
|
||||
if(field.FieldType == typeof(Int32)) {
|
||||
field.SetValue(Entity, ((TrackBar)kvp.Value).Value);
|
||||
|
|
41
UI/Forms/frmMain.Designer.cs
generated
41
UI/Forms/frmMain.Designer.cs
generated
|
@ -31,6 +31,8 @@
|
|||
this.mnuMain = new Mesen.GUI.Controls.ctrlMesenMenuStrip();
|
||||
this.mnuFile = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuOpen = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.optionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuVideoConfig = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.debugToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuRun = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuStep = new System.Windows.Forms.ToolStripMenuItem();
|
||||
|
@ -41,12 +43,14 @@
|
|||
this.mnuTraceLogger = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuTilemapViewer = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.mnuEventViewer = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.pnlRenderer = new System.Windows.Forms.Panel();
|
||||
this.mnuMain.SuspendLayout();
|
||||
this.pnlRenderer.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// ctrlRenderer
|
||||
//
|
||||
this.ctrlRenderer.Location = new System.Drawing.Point(0, 27);
|
||||
this.ctrlRenderer.Location = new System.Drawing.Point(0, 0);
|
||||
this.ctrlRenderer.Name = "ctrlRenderer";
|
||||
this.ctrlRenderer.Size = new System.Drawing.Size(512, 448);
|
||||
this.ctrlRenderer.TabIndex = 0;
|
||||
|
@ -55,6 +59,7 @@
|
|||
//
|
||||
this.mnuMain.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.mnuFile,
|
||||
this.optionsToolStripMenuItem,
|
||||
this.debugToolStripMenuItem});
|
||||
this.mnuMain.Location = new System.Drawing.Point(0, 0);
|
||||
this.mnuMain.Name = "mnuMain";
|
||||
|
@ -79,6 +84,22 @@
|
|||
this.mnuOpen.Text = "Open";
|
||||
this.mnuOpen.Click += new System.EventHandler(this.mnuOpen_Click);
|
||||
//
|
||||
// optionsToolStripMenuItem
|
||||
//
|
||||
this.optionsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.mnuVideoConfig});
|
||||
this.optionsToolStripMenuItem.Name = "optionsToolStripMenuItem";
|
||||
this.optionsToolStripMenuItem.Size = new System.Drawing.Size(61, 20);
|
||||
this.optionsToolStripMenuItem.Text = "Options";
|
||||
//
|
||||
// mnuVideoConfig
|
||||
//
|
||||
this.mnuVideoConfig.Image = global::Mesen.GUI.Properties.Resources.VideoOptions;
|
||||
this.mnuVideoConfig.Name = "mnuVideoConfig";
|
||||
this.mnuVideoConfig.Size = new System.Drawing.Size(104, 22);
|
||||
this.mnuVideoConfig.Text = "Video";
|
||||
this.mnuVideoConfig.Click += new System.EventHandler(this.mnuVideoConfig_Click);
|
||||
//
|
||||
// debugToolStripMenuItem
|
||||
//
|
||||
this.debugToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
|
@ -164,19 +185,30 @@
|
|||
this.mnuEventViewer.Text = "Event Viewer";
|
||||
this.mnuEventViewer.Click += new System.EventHandler(this.mnuEventViewer_Click);
|
||||
//
|
||||
// pnlRenderer
|
||||
//
|
||||
this.pnlRenderer.BackColor = System.Drawing.Color.Black;
|
||||
this.pnlRenderer.Controls.Add(this.ctrlRenderer);
|
||||
this.pnlRenderer.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.pnlRenderer.Location = new System.Drawing.Point(0, 24);
|
||||
this.pnlRenderer.Name = "pnlRenderer";
|
||||
this.pnlRenderer.Size = new System.Drawing.Size(512, 448);
|
||||
this.pnlRenderer.TabIndex = 2;
|
||||
//
|
||||
// frmMain
|
||||
//
|
||||
this.AllowDrop = true;
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(512, 475);
|
||||
this.Controls.Add(this.ctrlRenderer);
|
||||
this.ClientSize = new System.Drawing.Size(512, 472);
|
||||
this.Controls.Add(this.pnlRenderer);
|
||||
this.Controls.Add(this.mnuMain);
|
||||
this.MainMenuStrip = this.mnuMain;
|
||||
this.Name = "frmMain";
|
||||
this.Text = "frmMain";
|
||||
this.mnuMain.ResumeLayout(false);
|
||||
this.mnuMain.PerformLayout();
|
||||
this.pnlRenderer.ResumeLayout(false);
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
|
@ -198,5 +230,8 @@
|
|||
private System.Windows.Forms.ToolStripMenuItem mnuMemoryTools;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuTilemapViewer;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuEventViewer;
|
||||
private System.Windows.Forms.ToolStripMenuItem optionsToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem mnuVideoConfig;
|
||||
private System.Windows.Forms.Panel pnlRenderer;
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
using Mesen.GUI.Config;
|
||||
using Mesen.GUI.Debugger;
|
||||
using Mesen.GUI.Forms.Config;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
|
@ -30,6 +31,8 @@ namespace Mesen.GUI.Forms
|
|||
EmuApi.InitDll();
|
||||
EmuApi.InitializeEmu(ConfigManager.HomeFolder, Handle, ctrlRenderer.Handle, false, false, false);
|
||||
|
||||
ConfigManager.Config.ApplyConfig();
|
||||
|
||||
_notifListener = new NotificationListener();
|
||||
_notifListener.OnNotification += OnNotificationReceived;
|
||||
|
||||
|
@ -45,6 +48,8 @@ namespace Mesen.GUI.Forms
|
|||
_notifListener = null;
|
||||
}
|
||||
|
||||
ConfigManager.ApplyChanges();
|
||||
|
||||
DebugApi.ResumeExecution();
|
||||
EmuApi.Stop();
|
||||
EmuApi.Release();
|
||||
|
@ -53,10 +58,40 @@ namespace Mesen.GUI.Forms
|
|||
private void OnNotificationReceived(NotificationEventArgs e)
|
||||
{
|
||||
switch(e.NotificationType) {
|
||||
case ConsoleNotificationType.CodeBreak:
|
||||
case ConsoleNotificationType.ResolutionChanged:
|
||||
ScreenSize size = EmuApi.GetScreenSize(false);
|
||||
this.BeginInvoke((Action)(() => {
|
||||
UpdateViewerSize(size);
|
||||
}));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateViewerSize(ScreenSize screenSize)
|
||||
{
|
||||
//this.Resize -= frmMain_Resize;
|
||||
|
||||
//if(forceUpdate || (!_customSize && this.WindowState != FormWindowState.Maximized)) {
|
||||
Size newSize = new Size(screenSize.Width, screenSize.Height);
|
||||
|
||||
//UpdateScaleMenu(size.Scale);
|
||||
this.ClientSize = new Size(newSize.Width, newSize.Height + pnlRenderer.Top);
|
||||
//}
|
||||
|
||||
ctrlRenderer.Size = new Size(screenSize.Width, screenSize.Height);
|
||||
ctrlRenderer.Top = (pnlRenderer.Height - ctrlRenderer.Height) / 2;
|
||||
ctrlRenderer.Left = (pnlRenderer.Width - ctrlRenderer.Width) / 2;
|
||||
|
||||
//this.Resize += frmMain_Resize;
|
||||
}
|
||||
|
||||
private void mnuVideoConfig_Click(object sender, EventArgs e)
|
||||
{
|
||||
using(frmVideoConfig frm = new frmVideoConfig()) {
|
||||
frm.ShowDialog(sender, this);
|
||||
}
|
||||
ConfigManager.Config.Video.ApplyConfig();
|
||||
}
|
||||
|
||||
private void mnuDebugger_Click(object sender, EventArgs e)
|
||||
{
|
||||
|
|
21
UI/Interop/ConfigApi.cs
Normal file
21
UI/Interop/ConfigApi.cs
Normal file
|
@ -0,0 +1,21 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using Mesen.GUI.Config;
|
||||
using Mesen.GUI.Forms;
|
||||
|
||||
namespace Mesen.GUI
|
||||
{
|
||||
public class ConfigApi
|
||||
{
|
||||
private const string DllPath = "MesenSCore.dll";
|
||||
|
||||
[DllImport(DllPath)] public static extern void SetVideoConfig(VideoConfig config);
|
||||
}
|
||||
}
|
|
@ -40,7 +40,16 @@ namespace Mesen.GUI
|
|||
|
||||
[DllImport(DllPath)] public static extern void SetDisplayLanguage(Language lang);
|
||||
|
||||
[DllImport(DllPath)] public static extern ScreenSize GetScreenSize([MarshalAs(UnmanagedType.I1)]bool ignoreScale);
|
||||
|
||||
[DllImport(DllPath, EntryPoint = "GetLog")] private static extern IntPtr GetLogWrapper();
|
||||
public static string GetLog() { return Utf8Marshaler.PtrToStringUtf8(EmuApi.GetLogWrapper()).Replace("\n", Environment.NewLine); }
|
||||
}
|
||||
|
||||
public struct ScreenSize
|
||||
{
|
||||
public Int32 Width;
|
||||
public Int32 Height;
|
||||
public double Scale;
|
||||
}
|
||||
}
|
||||
|
|
12
UI/UI.csproj
12
UI/UI.csproj
|
@ -209,9 +209,11 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="CommandLineHelper.cs" />
|
||||
<Compile Include="Config\BaseConfig.cs" />
|
||||
<Compile Include="Config\ConfigAttributes.cs" />
|
||||
<Compile Include="Config\Configuration.cs" />
|
||||
<Compile Include="Config\ConfigManager.cs" />
|
||||
<Compile Include="Config\VideoConfig.cs" />
|
||||
<Compile Include="Debugger\Breakpoints\Breakpoint.cs" />
|
||||
<Compile Include="Debugger\Breakpoints\BreakpointManager.cs" />
|
||||
<Compile Include="Debugger\Breakpoints\ctrlBreakpoints.cs">
|
||||
|
@ -462,6 +464,12 @@
|
|||
<Compile Include="Forms\BaseInputForm.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Forms\Config\frmVideoConfig.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Forms\Config\frmVideoConfig.Designer.cs">
|
||||
<DependentUpon>frmVideoConfig.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Forms\EntityBinder.cs" />
|
||||
<Compile Include="Forms\frmLogWindow.cs">
|
||||
<SubType>Form</SubType>
|
||||
|
@ -480,6 +488,7 @@
|
|||
<Compile Include="Forms\ResourceHelper.cs" />
|
||||
<Compile Include="Forms\ResourcePath.cs" />
|
||||
<Compile Include="Interop\DebugApi.cs" />
|
||||
<Compile Include="Interop\ConfigApi.cs" />
|
||||
<Compile Include="Interop\EmuApi.cs" />
|
||||
<Compile Include="Interop\NotificationListener.cs" />
|
||||
<Compile Include="Interop\Utf8Marshaler.cs" />
|
||||
|
@ -585,6 +594,9 @@
|
|||
<EmbeddedResource Include="Forms\BaseInputForm.resx">
|
||||
<DependentUpon>BaseInputForm.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Forms\Config\frmVideoConfig.resx">
|
||||
<DependentUpon>frmVideoConfig.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Forms\frmLogWindow.resx">
|
||||
<DependentUpon>frmLogWindow.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
|
|
|
@ -417,9 +417,6 @@
|
|||
<ClInclude Include="md5.h" />
|
||||
<ClInclude Include="miniz.h" />
|
||||
<ClInclude Include="AutoResetEvent.h" />
|
||||
<ClInclude Include="nes_ntsc.h" />
|
||||
<ClInclude Include="nes_ntsc_config.h" />
|
||||
<ClInclude Include="nes_ntsc_impl.h" />
|
||||
<ClInclude Include="BaseCodec.h" />
|
||||
<ClInclude Include="orfanidis_eq.h" />
|
||||
<ClInclude Include="PlatformUtilities.h" />
|
||||
|
@ -429,6 +426,9 @@
|
|||
<ClInclude Include="Scale2x\scale3x.h" />
|
||||
<ClInclude Include="Scale2x\scalebit.h" />
|
||||
<ClInclude Include="sha1.h" />
|
||||
<ClInclude Include="snes_ntsc.h" />
|
||||
<ClInclude Include="snes_ntsc_config.h" />
|
||||
<ClInclude Include="snes_ntsc_impl.h" />
|
||||
<ClInclude Include="stb_vorbis.h" />
|
||||
<ClInclude Include="StringUtilities.h" />
|
||||
<ClInclude Include="SZReader.h" />
|
||||
|
@ -543,7 +543,6 @@
|
|||
</ClCompile>
|
||||
<ClCompile Include="md5.cpp" />
|
||||
<ClCompile Include="miniz.cpp" />
|
||||
<ClCompile Include="nes_ntsc.cpp" />
|
||||
<ClCompile Include="PlatformUtilities.cpp" />
|
||||
<ClCompile Include="PNGHelper.cpp" />
|
||||
<ClCompile Include="AutoResetEvent.cpp" />
|
||||
|
@ -585,6 +584,7 @@
|
|||
</ClCompile>
|
||||
<ClCompile Include="sha1.cpp" />
|
||||
<ClCompile Include="SimpleLock.cpp" />
|
||||
<ClCompile Include="snes_ntsc.cpp" />
|
||||
<ClCompile Include="Socket.cpp" />
|
||||
<ClCompile Include="stb_vorbis.cpp" />
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
|
|
|
@ -80,15 +80,6 @@
|
|||
<ClInclude Include="blip_buf.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="nes_ntsc.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="nes_ntsc_config.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="nes_ntsc_impl.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="xBRZ\config.h">
|
||||
<Filter>xBRZ</Filter>
|
||||
</ClInclude>
|
||||
|
@ -170,6 +161,15 @@
|
|||
<ClInclude Include="FastString.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="snes_ntsc.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="snes_ntsc_config.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="snes_ntsc_impl.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
|
@ -217,9 +217,6 @@
|
|||
<ClCompile Include="blip_buf.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="nes_ntsc.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="xBRZ\xbrz.cpp">
|
||||
<Filter>xBRZ</Filter>
|
||||
</ClCompile>
|
||||
|
@ -292,5 +289,8 @@
|
|||
<ClCompile Include="VirtualFile.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="snes_ntsc.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -1,291 +0,0 @@
|
|||
#include "stdafx.h"
|
||||
|
||||
/* nes_ntsc 0.2.2. http://www.slack.net/~ant/ */
|
||||
|
||||
#include "nes_ntsc.h"
|
||||
|
||||
/* Copyright (C) 2006-2007 Shay Green. This module is free software; you
|
||||
can redistribute it and/or modify it under the terms of the GNU Lesser
|
||||
General Public License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version. This
|
||||
module is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
details. You should have received a copy of the GNU Lesser General Public
|
||||
License along with this module; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
nes_ntsc_setup_t const nes_ntsc_monochrome = { 0,-1, 0, 0,.2, 0,.2,-.2,-.2,-1, 1, 0, 0, 0, 0 };
|
||||
nes_ntsc_setup_t const nes_ntsc_composite = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 };
|
||||
nes_ntsc_setup_t const nes_ntsc_svideo = { 0, 0, 0, 0,.2, 0,.2, -1, -1, 0, 1, 0, 0, 0, 0 };
|
||||
nes_ntsc_setup_t const nes_ntsc_rgb = { 0, 0, 0, 0,.2, 0,.7, -1, -1,-1, 1, 0, 0, 0, 0 };
|
||||
|
||||
#define alignment_count 3
|
||||
#define burst_count 3
|
||||
#define rescale_in 8
|
||||
#define rescale_out 7
|
||||
|
||||
#define artifacts_mid 1.0f
|
||||
#define fringing_mid 1.0f
|
||||
#define std_decoder_hue -15
|
||||
|
||||
#define STD_HUE_CONDITION( setup ) !(setup->base_palette || setup->palette)
|
||||
|
||||
#include "nes_ntsc_impl.h"
|
||||
|
||||
/* 3 input pixels -> 8 composite samples */
|
||||
pixel_info_t const nes_ntsc_pixels [alignment_count] = {
|
||||
{ PIXEL_OFFSET( -4, -9 ), { 1, 1, .6667f, 0 } },
|
||||
{ PIXEL_OFFSET( -2, -7 ), { .3333f, 1, 1, .3333f } },
|
||||
{ PIXEL_OFFSET( 0, -5 ), { 0, .6667f, 1, 1 } },
|
||||
};
|
||||
|
||||
static void merge_kernel_fields( nes_ntsc_rgb_t* io )
|
||||
{
|
||||
int n;
|
||||
for ( n = burst_size; n; --n )
|
||||
{
|
||||
nes_ntsc_rgb_t p0 = io [burst_size * 0] + rgb_bias;
|
||||
nes_ntsc_rgb_t p1 = io [burst_size * 1] + rgb_bias;
|
||||
nes_ntsc_rgb_t p2 = io [burst_size * 2] + rgb_bias;
|
||||
/* merge colors without losing precision */
|
||||
io [burst_size * 0] =
|
||||
((p0 + p1 - ((p0 ^ p1) & nes_ntsc_rgb_builder)) >> 1) - rgb_bias;
|
||||
io [burst_size * 1] =
|
||||
((p1 + p2 - ((p1 ^ p2) & nes_ntsc_rgb_builder)) >> 1) - rgb_bias;
|
||||
io [burst_size * 2] =
|
||||
((p2 + p0 - ((p2 ^ p0) & nes_ntsc_rgb_builder)) >> 1) - rgb_bias;
|
||||
++io;
|
||||
}
|
||||
}
|
||||
|
||||
static void correct_errors( nes_ntsc_rgb_t color, nes_ntsc_rgb_t* out )
|
||||
{
|
||||
int n;
|
||||
for ( n = burst_count; n; --n )
|
||||
{
|
||||
unsigned i;
|
||||
for ( i = 0; i < rgb_kernel_size / 2; i++ )
|
||||
{
|
||||
nes_ntsc_rgb_t error = color -
|
||||
out [i ] - out [(i+12)%14+14] - out [(i+10)%14+28] -
|
||||
out [i + 7] - out [i + 5 +14] - out [i + 3 +28];
|
||||
DISTRIBUTE_ERROR( i+3+28, i+5+14, i+7 );
|
||||
}
|
||||
out += alignment_count * rgb_kernel_size;
|
||||
}
|
||||
}
|
||||
|
||||
void nes_ntsc_init( nes_ntsc_t* ntsc, nes_ntsc_setup_t const* setup )
|
||||
{
|
||||
int merge_fields;
|
||||
int entry;
|
||||
init_t impl;
|
||||
float gamma_factor;
|
||||
|
||||
if ( !setup )
|
||||
setup = &nes_ntsc_composite;
|
||||
init( &impl, setup );
|
||||
|
||||
/* setup fast gamma */
|
||||
{
|
||||
float gamma = (float) setup->gamma * -0.5f;
|
||||
if ( STD_HUE_CONDITION( setup ) )
|
||||
gamma += 0.1333f;
|
||||
|
||||
gamma_factor = (float) pow( (float) fabs( gamma ), 0.73f );
|
||||
if ( gamma < 0 )
|
||||
gamma_factor = -gamma_factor;
|
||||
}
|
||||
|
||||
merge_fields = setup->merge_fields;
|
||||
if ( setup->artifacts <= -1 && setup->fringing <= -1 )
|
||||
merge_fields = 1;
|
||||
|
||||
for ( entry = 0; entry < nes_ntsc_palette_size; entry++ )
|
||||
{
|
||||
/* Base 64-color generation */
|
||||
static float const lo_levels [4] = { -0.12f, 0.00f, 0.31f, 0.72f };
|
||||
static float const hi_levels [4] = { 0.40f, 0.68f, 1.00f, 1.00f };
|
||||
int level = entry >> 4 & 0x03;
|
||||
float lo = lo_levels [level];
|
||||
float hi = hi_levels [level];
|
||||
|
||||
int color = entry & 0x0F;
|
||||
if ( color == 0 )
|
||||
lo = hi;
|
||||
if ( color == 0x0D )
|
||||
hi = lo;
|
||||
if ( color > 0x0D )
|
||||
hi = lo = 0.0f;
|
||||
|
||||
{
|
||||
/* phases [i] = cos( i * PI / 6 ) */
|
||||
static float const phases [0x10 + 3] = {
|
||||
-1.0f, -0.866025f, -0.5f, 0.0f, 0.5f, 0.866025f,
|
||||
1.0f, 0.866025f, 0.5f, 0.0f, -0.5f, -0.866025f,
|
||||
-1.0f, -0.866025f, -0.5f, 0.0f, 0.5f, 0.866025f,
|
||||
1.0f
|
||||
};
|
||||
#define TO_ANGLE_SIN( color ) phases [color]
|
||||
#define TO_ANGLE_COS( color ) phases [(color) + 3]
|
||||
|
||||
/* Convert raw waveform to YIQ */
|
||||
float sat = (hi - lo) * 0.5f;
|
||||
float i = TO_ANGLE_SIN( color ) * sat;
|
||||
float q = TO_ANGLE_COS( color ) * sat;
|
||||
float y = (hi + lo) * 0.5f;
|
||||
|
||||
/* Optionally use base palette instead */
|
||||
if ( setup->base_palette )
|
||||
{
|
||||
unsigned char const* in = &setup->base_palette [(entry & 0x3F) * 3];
|
||||
static float const to_float = 1.0f / 0xFF;
|
||||
float r = to_float * in [0];
|
||||
float g = to_float * in [1];
|
||||
float b = to_float * in [2];
|
||||
q = RGB_TO_YIQ( r, g, b, y, i );
|
||||
}
|
||||
|
||||
/* Apply color emphasis */
|
||||
#ifdef NES_NTSC_EMPHASIS
|
||||
{
|
||||
int tint = entry >> 6 & 7;
|
||||
if ( tint && color <= 0x0D )
|
||||
{
|
||||
static float const atten_mul = 0.79399f;
|
||||
static float const atten_sub = 0.0782838f;
|
||||
|
||||
if ( tint == 7 )
|
||||
{
|
||||
y = y * (atten_mul * 1.13f) - (atten_sub * 1.13f);
|
||||
}
|
||||
else
|
||||
{
|
||||
static unsigned char const tints [8] = { 0, 6, 10, 8, 2, 4, 0, 0 };
|
||||
int const tint_color = tints [tint];
|
||||
float sat = hi * (0.5f - atten_mul * 0.5f) + atten_sub * 0.5f;
|
||||
y -= sat * 0.5f;
|
||||
if ( tint >= 3 && tint != 4 )
|
||||
{
|
||||
/* combined tint bits */
|
||||
sat *= 0.6f;
|
||||
y -= sat;
|
||||
}
|
||||
i += TO_ANGLE_SIN( tint_color ) * sat;
|
||||
q += TO_ANGLE_COS( tint_color ) * sat;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Optionally use palette instead */
|
||||
if ( setup->palette )
|
||||
{
|
||||
unsigned char const* in = &setup->palette [entry * 3];
|
||||
static float const to_float = 1.0f / 0xFF;
|
||||
float r = to_float * in [0];
|
||||
float g = to_float * in [1];
|
||||
float b = to_float * in [2];
|
||||
q = RGB_TO_YIQ( r, g, b, y, i );
|
||||
}
|
||||
|
||||
/* Apply brightness, contrast, and gamma */
|
||||
y *= (float) setup->contrast * 0.5f + 1;
|
||||
/* adjustment reduces error when using input palette */
|
||||
y += (float) setup->brightness * 0.5f - 0.5f / 256;
|
||||
|
||||
{
|
||||
float r, g, b = YIQ_TO_RGB( y, i, q, default_decoder, float, r, g );
|
||||
|
||||
/* fast approximation of n = pow( n, gamma ) */
|
||||
r = (r * gamma_factor - gamma_factor) * r + r;
|
||||
g = (g * gamma_factor - gamma_factor) * g + g;
|
||||
b = (b * gamma_factor - gamma_factor) * b + b;
|
||||
|
||||
q = RGB_TO_YIQ( r, g, b, y, i );
|
||||
}
|
||||
|
||||
i *= rgb_unit;
|
||||
q *= rgb_unit;
|
||||
y *= rgb_unit;
|
||||
y += rgb_offset;
|
||||
|
||||
/* Generate kernel */
|
||||
{
|
||||
int r, g, b = YIQ_TO_RGB( y, i, q, impl.to_rgb, int, r, g );
|
||||
/* blue tends to overflow, so clamp it */
|
||||
nes_ntsc_rgb_t rgb = PACK_RGB( r, g, (b < 0x3E0 ? b: 0x3E0) );
|
||||
|
||||
if ( setup->palette_out )
|
||||
RGB_PALETTE_OUT( rgb, &setup->palette_out [entry * 3] );
|
||||
|
||||
if ( ntsc )
|
||||
{
|
||||
nes_ntsc_rgb_t* kernel = ntsc->table [entry];
|
||||
gen_kernel( &impl, y, i, q, kernel );
|
||||
if ( merge_fields )
|
||||
merge_kernel_fields( kernel );
|
||||
correct_errors( rgb, kernel );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NES_NTSC_NO_BLITTERS
|
||||
|
||||
void nes_ntsc_blit( nes_ntsc_t const* ntsc, NES_NTSC_IN_T const* input, long in_row_width,
|
||||
int burst_phase, int in_width, int in_height, void* rgb_out, long out_pitch )
|
||||
{
|
||||
int chunk_count = (in_width - 1) / nes_ntsc_in_chunk;
|
||||
for ( ; in_height; --in_height )
|
||||
{
|
||||
NES_NTSC_IN_T const* line_in = input;
|
||||
NES_NTSC_BEGIN_ROW( ntsc, burst_phase,
|
||||
nes_ntsc_black, nes_ntsc_black, NES_NTSC_ADJ_IN( *line_in ) );
|
||||
nes_ntsc_out_t* restrict line_out = (nes_ntsc_out_t*) rgb_out;
|
||||
int n;
|
||||
++line_in;
|
||||
|
||||
for ( n = chunk_count; n; --n )
|
||||
{
|
||||
/* order of input and output pixels must not be altered */
|
||||
NES_NTSC_COLOR_IN( 0, NES_NTSC_ADJ_IN( line_in [0] ) );
|
||||
NES_NTSC_RGB_OUT( 0, line_out [0], NES_NTSC_OUT_DEPTH );
|
||||
NES_NTSC_RGB_OUT( 1, line_out [1], NES_NTSC_OUT_DEPTH );
|
||||
|
||||
NES_NTSC_COLOR_IN( 1, NES_NTSC_ADJ_IN( line_in [1] ) );
|
||||
NES_NTSC_RGB_OUT( 2, line_out [2], NES_NTSC_OUT_DEPTH );
|
||||
NES_NTSC_RGB_OUT( 3, line_out [3], NES_NTSC_OUT_DEPTH );
|
||||
|
||||
NES_NTSC_COLOR_IN( 2, NES_NTSC_ADJ_IN( line_in [2] ) );
|
||||
NES_NTSC_RGB_OUT( 4, line_out [4], NES_NTSC_OUT_DEPTH );
|
||||
NES_NTSC_RGB_OUT( 5, line_out [5], NES_NTSC_OUT_DEPTH );
|
||||
NES_NTSC_RGB_OUT( 6, line_out [6], NES_NTSC_OUT_DEPTH );
|
||||
|
||||
line_in += 3;
|
||||
line_out += 7;
|
||||
}
|
||||
|
||||
/* finish final pixels */
|
||||
NES_NTSC_COLOR_IN( 0, nes_ntsc_black );
|
||||
NES_NTSC_RGB_OUT( 0, line_out [0], NES_NTSC_OUT_DEPTH );
|
||||
NES_NTSC_RGB_OUT( 1, line_out [1], NES_NTSC_OUT_DEPTH );
|
||||
|
||||
NES_NTSC_COLOR_IN( 1, nes_ntsc_black );
|
||||
NES_NTSC_RGB_OUT( 2, line_out [2], NES_NTSC_OUT_DEPTH );
|
||||
NES_NTSC_RGB_OUT( 3, line_out [3], NES_NTSC_OUT_DEPTH );
|
||||
|
||||
NES_NTSC_COLOR_IN( 2, nes_ntsc_black );
|
||||
NES_NTSC_RGB_OUT( 4, line_out [4], NES_NTSC_OUT_DEPTH );
|
||||
NES_NTSC_RGB_OUT( 5, line_out [5], NES_NTSC_OUT_DEPTH );
|
||||
NES_NTSC_RGB_OUT( 6, line_out [6], NES_NTSC_OUT_DEPTH );
|
||||
|
||||
burst_phase = (burst_phase + 1) % nes_ntsc_burst_count;
|
||||
input += in_row_width;
|
||||
rgb_out = (char*) rgb_out + out_pitch;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,199 +0,0 @@
|
|||
#pragma once
|
||||
/* NES NTSC video filter */
|
||||
|
||||
/* nes_ntsc 0.2.2 */
|
||||
#ifndef NES_NTSC_H
|
||||
#define NES_NTSC_H
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define EXPORT
|
||||
#endif
|
||||
|
||||
#include "nes_ntsc_config.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Image parameters, ranging from -1.0 to 1.0. Actual internal values shown
|
||||
in parenthesis and should remain fairly stable in future versions. */
|
||||
typedef struct nes_ntsc_setup_t
|
||||
{
|
||||
/* Basic parameters */
|
||||
double hue; /* -1 = -180 degrees +1 = +180 degrees */
|
||||
double saturation; /* -1 = grayscale (0.0) +1 = oversaturated colors (2.0) */
|
||||
double contrast; /* -1 = dark (0.5) +1 = light (1.5) */
|
||||
double brightness; /* -1 = dark (0.5) +1 = light (1.5) */
|
||||
double sharpness; /* edge contrast enhancement/blurring */
|
||||
|
||||
/* Advanced parameters */
|
||||
double gamma; /* -1 = dark (1.5) +1 = light (0.5) */
|
||||
double resolution; /* image resolution */
|
||||
double artifacts; /* artifacts caused by color changes */
|
||||
double fringing; /* color artifacts caused by brightness changes */
|
||||
double bleed; /* color bleed (color resolution reduction) */
|
||||
int merge_fields; /* if 1, merges even and odd fields together to reduce flicker */
|
||||
float const* decoder_matrix; /* optional RGB decoder matrix, 6 elements */
|
||||
|
||||
unsigned char* palette_out; /* optional RGB palette out, 3 bytes per color */
|
||||
|
||||
/* You can replace the standard NES color generation with an RGB palette. The
|
||||
first replaces all color generation, while the second replaces only the core
|
||||
64-color generation and does standard color emphasis calculations on it. */
|
||||
unsigned char const* palette;/* optional 512-entry RGB palette in, 3 bytes per color */
|
||||
unsigned char const* base_palette;/* optional 64-entry RGB palette in, 3 bytes per color */
|
||||
} nes_ntsc_setup_t;
|
||||
|
||||
/* Video format presets */
|
||||
extern nes_ntsc_setup_t const nes_ntsc_composite; /* color bleeding + artifacts */
|
||||
extern nes_ntsc_setup_t const nes_ntsc_svideo; /* color bleeding only */
|
||||
extern nes_ntsc_setup_t const nes_ntsc_rgb; /* crisp image */
|
||||
extern nes_ntsc_setup_t const nes_ntsc_monochrome;/* desaturated + artifacts */
|
||||
|
||||
#ifdef NES_NTSC_EMPHASIS
|
||||
enum { nes_ntsc_palette_size = 64 * 8 };
|
||||
#else
|
||||
enum { nes_ntsc_palette_size = 64 };
|
||||
#endif
|
||||
|
||||
/* Initializes and adjusts parameters. Can be called multiple times on the same
|
||||
nes_ntsc_t object. Can pass NULL for either parameter. */
|
||||
typedef struct nes_ntsc_t nes_ntsc_t;
|
||||
EXPORT void nes_ntsc_init( nes_ntsc_t* ntsc, nes_ntsc_setup_t const* setup );
|
||||
|
||||
/* Filters one or more rows of pixels. Input pixels are 6/9-bit palette indicies.
|
||||
In_row_width is the number of pixels to get to the next input row. Out_pitch
|
||||
is the number of *bytes* to get to the next output row. Output pixel format
|
||||
is set by NES_NTSC_OUT_DEPTH (defaults to 16-bit RGB). */
|
||||
EXPORT void nes_ntsc_blit( nes_ntsc_t const* ntsc, NES_NTSC_IN_T const* nes_in,
|
||||
long in_row_width, int burst_phase, int in_width, int in_height,
|
||||
void* rgb_out, long out_pitch );
|
||||
|
||||
/* Number of output pixels written by blitter for given input width. Width might
|
||||
be rounded down slightly; use NES_NTSC_IN_WIDTH() on result to find rounded
|
||||
value. Guaranteed not to round 256 down at all. */
|
||||
#define NES_NTSC_OUT_WIDTH( in_width ) \
|
||||
((((in_width) - 1) / nes_ntsc_in_chunk + 1) * nes_ntsc_out_chunk)
|
||||
|
||||
/* Number of input pixels that will fit within given output width. Might be
|
||||
rounded down slightly; use NES_NTSC_OUT_WIDTH() on result to find rounded
|
||||
value. */
|
||||
#define NES_NTSC_IN_WIDTH( out_width ) \
|
||||
(((out_width) / nes_ntsc_out_chunk - 1) * nes_ntsc_in_chunk + 1)
|
||||
|
||||
|
||||
/* Interface for user-defined custom blitters */
|
||||
|
||||
enum { nes_ntsc_in_chunk = 3 }; /* number of input pixels read per chunk */
|
||||
enum { nes_ntsc_out_chunk = 7 }; /* number of output pixels generated per chunk */
|
||||
enum { nes_ntsc_black = 15 }; /* palette index for black */
|
||||
enum { nes_ntsc_burst_count = 3 }; /* burst phase cycles through 0, 1, and 2 */
|
||||
|
||||
/* Begins outputting row and starts three pixels. First pixel will be cut off a bit.
|
||||
Use nes_ntsc_black for unused pixels. Declares variables, so must be before first
|
||||
statement in a block (unless you're using C++). */
|
||||
#define NES_NTSC_BEGIN_ROW( ntsc, burst, pixel0, pixel1, pixel2 ) \
|
||||
char const* const ktable = \
|
||||
(char const*) (ntsc)->table [0] + burst * (nes_ntsc_burst_size * sizeof (nes_ntsc_rgb_t));\
|
||||
NES_NTSC_BEGIN_ROW_6_( pixel0, pixel1, pixel2, NES_NTSC_ENTRY_, ktable )
|
||||
|
||||
/* Begins input pixel */
|
||||
#define NES_NTSC_COLOR_IN( in_index, color_in ) \
|
||||
NES_NTSC_COLOR_IN_( in_index, color_in, NES_NTSC_ENTRY_, ktable )
|
||||
|
||||
/* Generates output pixel. Bits can be 24, 16, 15, 32 (treated as 24), or 0:
|
||||
24: RRRRRRRR GGGGGGGG BBBBBBBB (8-8-8 RGB)
|
||||
16: RRRRRGGG GGGBBBBB (5-6-5 RGB)
|
||||
15: RRRRRGG GGGBBBBB (5-5-5 RGB)
|
||||
0: xxxRRRRR RRRxxGGG GGGGGxxB BBBBBBBx (native internal format; x = junk bits) */
|
||||
#define NES_NTSC_RGB_OUT( index, rgb_out, bits ) \
|
||||
NES_NTSC_RGB_OUT_14_( index, rgb_out, bits, 0 )
|
||||
|
||||
|
||||
/* private */
|
||||
enum { nes_ntsc_entry_size = 128 };
|
||||
typedef unsigned long nes_ntsc_rgb_t;
|
||||
struct nes_ntsc_t {
|
||||
nes_ntsc_rgb_t table [nes_ntsc_palette_size] [nes_ntsc_entry_size];
|
||||
};
|
||||
enum { nes_ntsc_burst_size = nes_ntsc_entry_size / nes_ntsc_burst_count };
|
||||
|
||||
#define NES_NTSC_ENTRY_( ktable, n ) \
|
||||
(nes_ntsc_rgb_t const*) (ktable + (n) * (nes_ntsc_entry_size * sizeof (nes_ntsc_rgb_t)))
|
||||
|
||||
/* deprecated */
|
||||
#define NES_NTSC_RGB24_OUT( x, out ) NES_NTSC_RGB_OUT( x, out, 24 )
|
||||
#define NES_NTSC_RGB16_OUT( x, out ) NES_NTSC_RGB_OUT( x, out, 16 )
|
||||
#define NES_NTSC_RGB15_OUT( x, out ) NES_NTSC_RGB_OUT( x, out, 15 )
|
||||
#define NES_NTSC_RAW_OUT( x, out ) NES_NTSC_RGB_OUT( x, out, 0 )
|
||||
|
||||
enum { nes_ntsc_min_in_width = 256 };
|
||||
enum { nes_ntsc_min_out_width = NES_NTSC_OUT_WIDTH( nes_ntsc_min_in_width ) };
|
||||
|
||||
enum { nes_ntsc_640_in_width = 271 };
|
||||
enum { nes_ntsc_640_out_width = NES_NTSC_OUT_WIDTH( nes_ntsc_640_in_width ) };
|
||||
enum { nes_ntsc_640_overscan_left = 8 };
|
||||
enum { nes_ntsc_640_overscan_right = nes_ntsc_640_in_width - 256 - nes_ntsc_640_overscan_left };
|
||||
|
||||
enum { nes_ntsc_full_in_width = 283 };
|
||||
enum { nes_ntsc_full_out_width = NES_NTSC_OUT_WIDTH( nes_ntsc_full_in_width ) };
|
||||
enum { nes_ntsc_full_overscan_left = 16 };
|
||||
enum { nes_ntsc_full_overscan_right = nes_ntsc_full_in_width - 256 - nes_ntsc_full_overscan_left };
|
||||
|
||||
/* common 3->7 ntsc macros */
|
||||
#define NES_NTSC_BEGIN_ROW_6_( pixel0, pixel1, pixel2, ENTRY, table ) \
|
||||
unsigned const nes_ntsc_pixel0_ = (pixel0);\
|
||||
nes_ntsc_rgb_t const* kernel0 = ENTRY( table, nes_ntsc_pixel0_ );\
|
||||
unsigned const nes_ntsc_pixel1_ = (pixel1);\
|
||||
nes_ntsc_rgb_t const* kernel1 = ENTRY( table, nes_ntsc_pixel1_ );\
|
||||
unsigned const nes_ntsc_pixel2_ = (pixel2);\
|
||||
nes_ntsc_rgb_t const* kernel2 = ENTRY( table, nes_ntsc_pixel2_ );\
|
||||
nes_ntsc_rgb_t const* kernelx0;\
|
||||
nes_ntsc_rgb_t const* kernelx1 = kernel0;\
|
||||
nes_ntsc_rgb_t const* kernelx2 = kernel0
|
||||
|
||||
#define NES_NTSC_RGB_OUT_14_( x, rgb_out, bits, shift ) {\
|
||||
nes_ntsc_rgb_t raw_ =\
|
||||
kernel0 [x ] + kernel1 [(x+12)%7+14] + kernel2 [(x+10)%7+28] +\
|
||||
kernelx0 [(x+7)%14] + kernelx1 [(x+ 5)%7+21] + kernelx2 [(x+ 3)%7+35];\
|
||||
NES_NTSC_CLAMP_( raw_, shift );\
|
||||
NES_NTSC_RGB_OUT_( rgb_out, bits, shift );\
|
||||
}
|
||||
|
||||
/* common ntsc macros */
|
||||
#define nes_ntsc_rgb_builder ((1L << 21) | (1 << 11) | (1 << 1))
|
||||
#define nes_ntsc_clamp_mask (nes_ntsc_rgb_builder * 3 / 2)
|
||||
#define nes_ntsc_clamp_add (nes_ntsc_rgb_builder * 0x101)
|
||||
#define NES_NTSC_CLAMP_( io, shift ) {\
|
||||
nes_ntsc_rgb_t sub = (io) >> (9-(shift)) & nes_ntsc_clamp_mask;\
|
||||
nes_ntsc_rgb_t clamp = nes_ntsc_clamp_add - sub;\
|
||||
io |= clamp;\
|
||||
clamp -= sub;\
|
||||
io &= clamp;\
|
||||
}
|
||||
|
||||
#define NES_NTSC_COLOR_IN_( index, color, ENTRY, table ) {\
|
||||
unsigned color_;\
|
||||
kernelx##index = kernel##index;\
|
||||
kernel##index = (color_ = (color), ENTRY( table, color_ ));\
|
||||
}
|
||||
|
||||
/* x is always zero except in snes_ntsc library */
|
||||
#define NES_NTSC_RGB_OUT_( rgb_out, bits, x ) {\
|
||||
if ( bits == 16 )\
|
||||
rgb_out = (raw_>>(13-x)& 0xF800)|(raw_>>(8-x)&0x07E0)|(raw_>>(4-x)&0x001F);\
|
||||
if ( bits == 32 || bits == 24 )\
|
||||
rgb_out = (raw_>>(5-x)&0xFF0000)|(raw_>>(3-x)&0xFF00)|(raw_>>(1-x)&0xFF);\
|
||||
if ( bits == 15 )\
|
||||
rgb_out = (raw_>>(14-x)& 0x7C00)|(raw_>>(9-x)&0x03E0)|(raw_>>(4-x)&0x001F);\
|
||||
if ( bits == 0 )\
|
||||
rgb_out = raw_ << x;\
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,27 +0,0 @@
|
|||
/* Configure library by modifying this file */
|
||||
|
||||
#ifndef NES_NTSC_CONFIG_H
|
||||
#define NES_NTSC_CONFIG_H
|
||||
|
||||
/* Uncomment to enable emphasis support and use a 512 color palette instead
|
||||
of the base 64 color palette. */
|
||||
#define NES_NTSC_EMPHASIS 1
|
||||
|
||||
/* The following affect the built-in blitter only; a custom blitter can
|
||||
handle things however it wants. */
|
||||
|
||||
/* Bits per pixel of output. Can be 15, 16, 32, or 24 (same as 32). */
|
||||
#define NES_NTSC_OUT_DEPTH 32
|
||||
|
||||
/* Type of input pixel values. You'll probably use unsigned short
|
||||
if you enable emphasis above. */
|
||||
#define NES_NTSC_IN_T unsigned short
|
||||
|
||||
/* Each raw pixel input value is passed through this. You might want to mask
|
||||
the pixel index if you use the high bits as flags, etc. */
|
||||
#define NES_NTSC_ADJ_IN( in ) in
|
||||
|
||||
/* For each pixel, this is the basic operation:
|
||||
output_color = color_palette [NES_NTSC_ADJ_IN( NES_NTSC_IN_T )] */
|
||||
|
||||
#endif
|
252
Utilities/snes_ntsc.cpp
Normal file
252
Utilities/snes_ntsc.cpp
Normal file
|
@ -0,0 +1,252 @@
|
|||
#include "stdafx.h"
|
||||
/* snes_ntsc 0.2.2. http://www.slack.net/~ant/ */
|
||||
|
||||
#include "snes_ntsc.h"
|
||||
|
||||
/* Copyright (C) 2006-2007 Shay Green. This module is free software; you
|
||||
can redistribute it and/or modify it under the terms of the GNU Lesser
|
||||
General Public License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version. This
|
||||
module is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
details. You should have received a copy of the GNU Lesser General Public
|
||||
License along with this module; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
snes_ntsc_setup_t const snes_ntsc_monochrome = { 0,-1, 0, 0,.2, 0,.2,-.2,-.2,-1, 1, 0, 0 };
|
||||
snes_ntsc_setup_t const snes_ntsc_composite = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 };
|
||||
snes_ntsc_setup_t const snes_ntsc_svideo = { 0, 0, 0, 0,.2, 0,.2, -1, -1, 0, 1, 0, 0 };
|
||||
snes_ntsc_setup_t const snes_ntsc_rgb = { 0, 0, 0, 0,.2, 0,.7, -1, -1,-1, 1, 0, 0 };
|
||||
|
||||
#define alignment_count 3
|
||||
#define burst_count 3
|
||||
#define rescale_in 8
|
||||
#define rescale_out 7
|
||||
|
||||
#define artifacts_mid 1.0f
|
||||
#define fringing_mid 1.0f
|
||||
#define std_decoder_hue 0
|
||||
|
||||
#define rgb_bits 7 /* half normal range to allow for doubled hires pixels */
|
||||
#define gamma_size 32
|
||||
|
||||
#include "snes_ntsc_impl.h"
|
||||
|
||||
/* 3 input pixels -> 8 composite samples */
|
||||
pixel_info_t const snes_ntsc_pixels [alignment_count] = {
|
||||
{ PIXEL_OFFSET( -4, -9 ), { 1, 1, .6667f, 0 } },
|
||||
{ PIXEL_OFFSET( -2, -7 ), { .3333f, 1, 1, .3333f } },
|
||||
{ PIXEL_OFFSET( 0, -5 ), { 0, .6667f, 1, 1 } },
|
||||
};
|
||||
|
||||
static void merge_kernel_fields( snes_ntsc_rgb_t* io )
|
||||
{
|
||||
int n;
|
||||
for ( n = burst_size; n; --n )
|
||||
{
|
||||
snes_ntsc_rgb_t p0 = io [burst_size * 0] + rgb_bias;
|
||||
snes_ntsc_rgb_t p1 = io [burst_size * 1] + rgb_bias;
|
||||
snes_ntsc_rgb_t p2 = io [burst_size * 2] + rgb_bias;
|
||||
/* merge colors without losing precision */
|
||||
io [burst_size * 0] =
|
||||
((p0 + p1 - ((p0 ^ p1) & snes_ntsc_rgb_builder)) >> 1) - rgb_bias;
|
||||
io [burst_size * 1] =
|
||||
((p1 + p2 - ((p1 ^ p2) & snes_ntsc_rgb_builder)) >> 1) - rgb_bias;
|
||||
io [burst_size * 2] =
|
||||
((p2 + p0 - ((p2 ^ p0) & snes_ntsc_rgb_builder)) >> 1) - rgb_bias;
|
||||
++io;
|
||||
}
|
||||
}
|
||||
|
||||
static void correct_errors( snes_ntsc_rgb_t color, snes_ntsc_rgb_t* out )
|
||||
{
|
||||
int n;
|
||||
for ( n = burst_count; n; --n )
|
||||
{
|
||||
unsigned i;
|
||||
for ( i = 0; i < rgb_kernel_size / 2; i++ )
|
||||
{
|
||||
snes_ntsc_rgb_t error = color -
|
||||
out [i ] - out [(i+12)%14+14] - out [(i+10)%14+28] -
|
||||
out [i + 7] - out [i + 5 +14] - out [i + 3 +28];
|
||||
DISTRIBUTE_ERROR( i+3+28, i+5+14, i+7 );
|
||||
}
|
||||
out += alignment_count * rgb_kernel_size;
|
||||
}
|
||||
}
|
||||
|
||||
void snes_ntsc_init( snes_ntsc_t* ntsc, snes_ntsc_setup_t const* setup )
|
||||
{
|
||||
int merge_fields;
|
||||
int entry;
|
||||
init_t impl;
|
||||
if ( !setup )
|
||||
setup = &snes_ntsc_composite;
|
||||
init( &impl, setup );
|
||||
|
||||
merge_fields = setup->merge_fields;
|
||||
if ( setup->artifacts <= -1 && setup->fringing <= -1 )
|
||||
merge_fields = 1;
|
||||
|
||||
for ( entry = 0; entry < snes_ntsc_palette_size; entry++ )
|
||||
{
|
||||
/* Reduce number of significant bits of source color. Clearing the
|
||||
low bits of R and B were least notictable. Modifying green was too
|
||||
noticeable. */
|
||||
int ir = entry >> 8 & 0x1E;
|
||||
int ig = entry >> 4 & 0x1F;
|
||||
int ib = entry << 1 & 0x1E;
|
||||
|
||||
#if SNES_NTSC_BSNES_COLORTBL
|
||||
if ( setup->bsnes_colortbl )
|
||||
{
|
||||
int bgr15 = (ib << 10) | (ig << 5) | ir;
|
||||
unsigned long rgb16 = setup->bsnes_colortbl [bgr15];
|
||||
ir = rgb16 >> 11 & 0x1E;
|
||||
ig = rgb16 >> 6 & 0x1F;
|
||||
ib = rgb16 & 0x1E;
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
float rr = impl.to_float [ir];
|
||||
float gg = impl.to_float [ig];
|
||||
float bb = impl.to_float [ib];
|
||||
|
||||
float y, i, q = RGB_TO_YIQ( rr, gg, bb, y, i );
|
||||
|
||||
int r, g, b = YIQ_TO_RGB( y, i, q, impl.to_rgb, int, r, g );
|
||||
snes_ntsc_rgb_t rgb = PACK_RGB( r, g, b );
|
||||
|
||||
snes_ntsc_rgb_t* out = ntsc->table [entry];
|
||||
gen_kernel( &impl, y, i, q, out );
|
||||
if ( merge_fields )
|
||||
merge_kernel_fields( out );
|
||||
correct_errors( rgb, out );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef SNES_NTSC_NO_BLITTERS
|
||||
|
||||
void snes_ntsc_blit( snes_ntsc_t const* ntsc, SNES_NTSC_IN_T const* input, long in_row_width,
|
||||
int burst_phase, int in_width, int in_height, void* rgb_out, long out_pitch )
|
||||
{
|
||||
int chunk_count = (in_width - 1) / snes_ntsc_in_chunk;
|
||||
for ( ; in_height; --in_height )
|
||||
{
|
||||
SNES_NTSC_IN_T const* line_in = input;
|
||||
SNES_NTSC_BEGIN_ROW( ntsc, burst_phase,
|
||||
snes_ntsc_black, snes_ntsc_black, SNES_NTSC_ADJ_IN( *line_in ) );
|
||||
snes_ntsc_out_t* restrict line_out = (snes_ntsc_out_t*) rgb_out;
|
||||
int n;
|
||||
++line_in;
|
||||
|
||||
for ( n = chunk_count; n; --n )
|
||||
{
|
||||
/* order of input and output pixels must not be altered */
|
||||
SNES_NTSC_COLOR_IN( 0, SNES_NTSC_ADJ_IN( line_in [0] ) );
|
||||
SNES_NTSC_RGB_OUT( 0, line_out [0], SNES_NTSC_OUT_DEPTH );
|
||||
SNES_NTSC_RGB_OUT( 1, line_out [1], SNES_NTSC_OUT_DEPTH );
|
||||
|
||||
SNES_NTSC_COLOR_IN( 1, SNES_NTSC_ADJ_IN( line_in [1] ) );
|
||||
SNES_NTSC_RGB_OUT( 2, line_out [2], SNES_NTSC_OUT_DEPTH );
|
||||
SNES_NTSC_RGB_OUT( 3, line_out [3], SNES_NTSC_OUT_DEPTH );
|
||||
|
||||
SNES_NTSC_COLOR_IN( 2, SNES_NTSC_ADJ_IN( line_in [2] ) );
|
||||
SNES_NTSC_RGB_OUT( 4, line_out [4], SNES_NTSC_OUT_DEPTH );
|
||||
SNES_NTSC_RGB_OUT( 5, line_out [5], SNES_NTSC_OUT_DEPTH );
|
||||
SNES_NTSC_RGB_OUT( 6, line_out [6], SNES_NTSC_OUT_DEPTH );
|
||||
|
||||
line_in += 3;
|
||||
line_out += 7;
|
||||
}
|
||||
|
||||
/* finish final pixels */
|
||||
SNES_NTSC_COLOR_IN( 0, snes_ntsc_black );
|
||||
SNES_NTSC_RGB_OUT( 0, line_out [0], SNES_NTSC_OUT_DEPTH );
|
||||
SNES_NTSC_RGB_OUT( 1, line_out [1], SNES_NTSC_OUT_DEPTH );
|
||||
|
||||
SNES_NTSC_COLOR_IN( 1, snes_ntsc_black );
|
||||
SNES_NTSC_RGB_OUT( 2, line_out [2], SNES_NTSC_OUT_DEPTH );
|
||||
SNES_NTSC_RGB_OUT( 3, line_out [3], SNES_NTSC_OUT_DEPTH );
|
||||
|
||||
SNES_NTSC_COLOR_IN( 2, snes_ntsc_black );
|
||||
SNES_NTSC_RGB_OUT( 4, line_out [4], SNES_NTSC_OUT_DEPTH );
|
||||
SNES_NTSC_RGB_OUT( 5, line_out [5], SNES_NTSC_OUT_DEPTH );
|
||||
SNES_NTSC_RGB_OUT( 6, line_out [6], SNES_NTSC_OUT_DEPTH );
|
||||
|
||||
burst_phase = (burst_phase + 1) % snes_ntsc_burst_count;
|
||||
input += in_row_width;
|
||||
rgb_out = (char*) rgb_out + out_pitch;
|
||||
}
|
||||
}
|
||||
|
||||
void snes_ntsc_blit_hires( snes_ntsc_t const* ntsc, SNES_NTSC_IN_T const* input, long in_row_width,
|
||||
int burst_phase, int in_width, int in_height, void* rgb_out, long out_pitch )
|
||||
{
|
||||
int chunk_count = (in_width - 2) / (snes_ntsc_in_chunk * 2);
|
||||
for ( ; in_height; --in_height )
|
||||
{
|
||||
SNES_NTSC_IN_T const* line_in = input;
|
||||
SNES_NTSC_HIRES_ROW( ntsc, burst_phase,
|
||||
snes_ntsc_black, snes_ntsc_black, snes_ntsc_black,
|
||||
SNES_NTSC_ADJ_IN( line_in [0] ),
|
||||
SNES_NTSC_ADJ_IN( line_in [1] ) );
|
||||
snes_ntsc_out_t* restrict line_out = (snes_ntsc_out_t*) rgb_out;
|
||||
int n;
|
||||
line_in += 2;
|
||||
|
||||
for ( n = chunk_count; n; --n )
|
||||
{
|
||||
/* twice as many input pixels per chunk */
|
||||
SNES_NTSC_COLOR_IN( 0, SNES_NTSC_ADJ_IN( line_in [0] ) );
|
||||
SNES_NTSC_HIRES_OUT( 0, line_out [0], SNES_NTSC_OUT_DEPTH );
|
||||
|
||||
SNES_NTSC_COLOR_IN( 1, SNES_NTSC_ADJ_IN( line_in [1] ) );
|
||||
SNES_NTSC_HIRES_OUT( 1, line_out [1], SNES_NTSC_OUT_DEPTH );
|
||||
|
||||
SNES_NTSC_COLOR_IN( 2, SNES_NTSC_ADJ_IN( line_in [2] ) );
|
||||
SNES_NTSC_HIRES_OUT( 2, line_out [2], SNES_NTSC_OUT_DEPTH );
|
||||
|
||||
SNES_NTSC_COLOR_IN( 3, SNES_NTSC_ADJ_IN( line_in [3] ) );
|
||||
SNES_NTSC_HIRES_OUT( 3, line_out [3], SNES_NTSC_OUT_DEPTH );
|
||||
|
||||
SNES_NTSC_COLOR_IN( 4, SNES_NTSC_ADJ_IN( line_in [4] ) );
|
||||
SNES_NTSC_HIRES_OUT( 4, line_out [4], SNES_NTSC_OUT_DEPTH );
|
||||
|
||||
SNES_NTSC_COLOR_IN( 5, SNES_NTSC_ADJ_IN( line_in [5] ) );
|
||||
SNES_NTSC_HIRES_OUT( 5, line_out [5], SNES_NTSC_OUT_DEPTH );
|
||||
SNES_NTSC_HIRES_OUT( 6, line_out [6], SNES_NTSC_OUT_DEPTH );
|
||||
|
||||
line_in += 6;
|
||||
line_out += 7;
|
||||
}
|
||||
|
||||
SNES_NTSC_COLOR_IN( 0, snes_ntsc_black );
|
||||
SNES_NTSC_HIRES_OUT( 0, line_out [0], SNES_NTSC_OUT_DEPTH );
|
||||
|
||||
SNES_NTSC_COLOR_IN( 1, snes_ntsc_black );
|
||||
SNES_NTSC_HIRES_OUT( 1, line_out [1], SNES_NTSC_OUT_DEPTH );
|
||||
|
||||
SNES_NTSC_COLOR_IN( 2, snes_ntsc_black );
|
||||
SNES_NTSC_HIRES_OUT( 2, line_out [2], SNES_NTSC_OUT_DEPTH );
|
||||
|
||||
SNES_NTSC_COLOR_IN( 3, snes_ntsc_black );
|
||||
SNES_NTSC_HIRES_OUT( 3, line_out [3], SNES_NTSC_OUT_DEPTH );
|
||||
|
||||
SNES_NTSC_COLOR_IN( 4, snes_ntsc_black );
|
||||
SNES_NTSC_HIRES_OUT( 4, line_out [4], SNES_NTSC_OUT_DEPTH );
|
||||
|
||||
SNES_NTSC_COLOR_IN( 5, snes_ntsc_black );
|
||||
SNES_NTSC_HIRES_OUT( 5, line_out [5], SNES_NTSC_OUT_DEPTH );
|
||||
SNES_NTSC_HIRES_OUT( 6, line_out [6], SNES_NTSC_OUT_DEPTH );
|
||||
|
||||
burst_phase = (burst_phase + 1) % snes_ntsc_burst_count;
|
||||
input += in_row_width;
|
||||
rgb_out = (char*) rgb_out + out_pitch;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
206
Utilities/snes_ntsc.h
Normal file
206
Utilities/snes_ntsc.h
Normal file
|
@ -0,0 +1,206 @@
|
|||
/* SNES NTSC video filter */
|
||||
|
||||
/* snes_ntsc 0.2.2 */
|
||||
#ifndef SNES_NTSC_H
|
||||
#define SNES_NTSC_H
|
||||
|
||||
#include "snes_ntsc_config.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Image parameters, ranging from -1.0 to 1.0. Actual internal values shown
|
||||
in parenthesis and should remain fairly stable in future versions. */
|
||||
typedef struct snes_ntsc_setup_t
|
||||
{
|
||||
/* Basic parameters */
|
||||
double hue; /* -1 = -180 degrees +1 = +180 degrees */
|
||||
double saturation; /* -1 = grayscale (0.0) +1 = oversaturated colors (2.0) */
|
||||
double contrast; /* -1 = dark (0.5) +1 = light (1.5) */
|
||||
double brightness; /* -1 = dark (0.5) +1 = light (1.5) */
|
||||
double sharpness; /* edge contrast enhancement/blurring */
|
||||
|
||||
/* Advanced parameters */
|
||||
double gamma; /* -1 = dark (1.5) +1 = light (0.5) */
|
||||
double resolution; /* image resolution */
|
||||
double artifacts; /* artifacts caused by color changes */
|
||||
double fringing; /* color artifacts caused by brightness changes */
|
||||
double bleed; /* color bleed (color resolution reduction) */
|
||||
int merge_fields; /* if 1, merges even and odd fields together to reduce flicker */
|
||||
float const* decoder_matrix; /* optional RGB decoder matrix, 6 elements */
|
||||
|
||||
unsigned long const* bsnes_colortbl; /* undocumented; set to 0 */
|
||||
} snes_ntsc_setup_t;
|
||||
|
||||
/* Video format presets */
|
||||
extern snes_ntsc_setup_t const snes_ntsc_composite; /* color bleeding + artifacts */
|
||||
extern snes_ntsc_setup_t const snes_ntsc_svideo; /* color bleeding only */
|
||||
extern snes_ntsc_setup_t const snes_ntsc_rgb; /* crisp image */
|
||||
extern snes_ntsc_setup_t const snes_ntsc_monochrome;/* desaturated + artifacts */
|
||||
|
||||
/* Initializes and adjusts parameters. Can be called multiple times on the same
|
||||
snes_ntsc_t object. Can pass NULL for either parameter. */
|
||||
typedef struct snes_ntsc_t snes_ntsc_t;
|
||||
void snes_ntsc_init( snes_ntsc_t* ntsc, snes_ntsc_setup_t const* setup );
|
||||
|
||||
/* Filters one or more rows of pixels. Input pixel format is set by SNES_NTSC_IN_FORMAT
|
||||
and output RGB depth is set by SNES_NTSC_OUT_DEPTH. Both default to 16-bit RGB.
|
||||
In_row_width is the number of pixels to get to the next input row. Out_pitch
|
||||
is the number of *bytes* to get to the next output row. */
|
||||
void snes_ntsc_blit( snes_ntsc_t const* ntsc, SNES_NTSC_IN_T const* input,
|
||||
long in_row_width, int burst_phase, int in_width, int in_height,
|
||||
void* rgb_out, long out_pitch );
|
||||
|
||||
void snes_ntsc_blit_hires( snes_ntsc_t const* ntsc, SNES_NTSC_IN_T const* input,
|
||||
long in_row_width, int burst_phase, int in_width, int in_height,
|
||||
void* rgb_out, long out_pitch );
|
||||
|
||||
/* Number of output pixels written by low-res blitter for given input width. Width
|
||||
might be rounded down slightly; use SNES_NTSC_IN_WIDTH() on result to find rounded
|
||||
value. Guaranteed not to round 256 down at all. */
|
||||
#define SNES_NTSC_OUT_WIDTH( in_width ) \
|
||||
((((in_width) - 1) / snes_ntsc_in_chunk + 1) * snes_ntsc_out_chunk)
|
||||
|
||||
/* Number of low-res input pixels that will fit within given output width. Might be
|
||||
rounded down slightly; use SNES_NTSC_OUT_WIDTH() on result to find rounded
|
||||
value. */
|
||||
#define SNES_NTSC_IN_WIDTH( out_width ) \
|
||||
(((out_width) / snes_ntsc_out_chunk - 1) * snes_ntsc_in_chunk + 1)
|
||||
|
||||
|
||||
/* Interface for user-defined custom blitters */
|
||||
|
||||
enum { snes_ntsc_in_chunk = 3 }; /* number of input pixels read per chunk */
|
||||
enum { snes_ntsc_out_chunk = 7 }; /* number of output pixels generated per chunk */
|
||||
enum { snes_ntsc_black = 0 }; /* palette index for black */
|
||||
enum { snes_ntsc_burst_count = 3 }; /* burst phase cycles through 0, 1, and 2 */
|
||||
|
||||
/* Begins outputting row and starts three pixels. First pixel will be cut off a bit.
|
||||
Use snes_ntsc_black for unused pixels. Declares variables, so must be before first
|
||||
statement in a block (unless you're using C++). */
|
||||
#define SNES_NTSC_BEGIN_ROW( ntsc, burst, pixel0, pixel1, pixel2 ) \
|
||||
char const* ktable = \
|
||||
(char const*) (ntsc)->table + burst * (snes_ntsc_burst_size * sizeof (snes_ntsc_rgb_t));\
|
||||
SNES_NTSC_BEGIN_ROW_6_( pixel0, pixel1, pixel2, SNES_NTSC_IN_FORMAT, ktable )
|
||||
|
||||
/* Begins input pixel */
|
||||
#define SNES_NTSC_COLOR_IN( index, color ) \
|
||||
SNES_NTSC_COLOR_IN_( index, color, SNES_NTSC_IN_FORMAT, ktable )
|
||||
|
||||
/* Generates output pixel. Bits can be 24, 16, 15, 14, 32 (treated as 24), or 0:
|
||||
24: RRRRRRRR GGGGGGGG BBBBBBBB (8-8-8 RGB)
|
||||
16: RRRRRGGG GGGBBBBB (5-6-5 RGB)
|
||||
15: RRRRRGG GGGBBBBB (5-5-5 RGB)
|
||||
14: BBBBBGG GGGRRRRR (5-5-5 BGR, native SNES format)
|
||||
0: xxxRRRRR RRRxxGGG GGGGGxxB BBBBBBBx (native internal format; x = junk bits) */
|
||||
#define SNES_NTSC_RGB_OUT( index, rgb_out, bits ) \
|
||||
SNES_NTSC_RGB_OUT_14_( index, rgb_out, bits, 1 )
|
||||
|
||||
/* Hires equivalents */
|
||||
#define SNES_NTSC_HIRES_ROW( ntsc, burst, pixel1, pixel2, pixel3, pixel4, pixel5 ) \
|
||||
char const* ktable = \
|
||||
(char const*) (ntsc)->table + burst * (snes_ntsc_burst_size * sizeof (snes_ntsc_rgb_t));\
|
||||
unsigned const snes_ntsc_pixel1_ = (pixel1);\
|
||||
snes_ntsc_rgb_t const* kernel1 = SNES_NTSC_IN_FORMAT( ktable, snes_ntsc_pixel1_ );\
|
||||
unsigned const snes_ntsc_pixel2_ = (pixel2);\
|
||||
snes_ntsc_rgb_t const* kernel2 = SNES_NTSC_IN_FORMAT( ktable, snes_ntsc_pixel2_ );\
|
||||
unsigned const snes_ntsc_pixel3_ = (pixel3);\
|
||||
snes_ntsc_rgb_t const* kernel3 = SNES_NTSC_IN_FORMAT( ktable, snes_ntsc_pixel3_ );\
|
||||
unsigned const snes_ntsc_pixel4_ = (pixel4);\
|
||||
snes_ntsc_rgb_t const* kernel4 = SNES_NTSC_IN_FORMAT( ktable, snes_ntsc_pixel4_ );\
|
||||
unsigned const snes_ntsc_pixel5_ = (pixel5);\
|
||||
snes_ntsc_rgb_t const* kernel5 = SNES_NTSC_IN_FORMAT( ktable, snes_ntsc_pixel5_ );\
|
||||
snes_ntsc_rgb_t const* kernel0 = kernel1;\
|
||||
snes_ntsc_rgb_t const* kernelx0;\
|
||||
snes_ntsc_rgb_t const* kernelx1 = kernel1;\
|
||||
snes_ntsc_rgb_t const* kernelx2 = kernel1;\
|
||||
snes_ntsc_rgb_t const* kernelx3 = kernel1;\
|
||||
snes_ntsc_rgb_t const* kernelx4 = kernel1;\
|
||||
snes_ntsc_rgb_t const* kernelx5 = kernel1
|
||||
|
||||
#define SNES_NTSC_HIRES_OUT( x, rgb_out, bits ) {\
|
||||
snes_ntsc_rgb_t raw_ =\
|
||||
kernel0 [ x ] + kernel2 [(x+5)%7+14] + kernel4 [(x+3)%7+28] +\
|
||||
kernelx0 [(x+7)%7+7] + kernelx2 [(x+5)%7+21] + kernelx4 [(x+3)%7+35] +\
|
||||
kernel1 [(x+6)%7 ] + kernel3 [(x+4)%7+14] + kernel5 [(x+2)%7+28] +\
|
||||
kernelx1 [(x+6)%7+7] + kernelx3 [(x+4)%7+21] + kernelx5 [(x+2)%7+35];\
|
||||
SNES_NTSC_CLAMP_( raw_, 0 );\
|
||||
SNES_NTSC_RGB_OUT_( rgb_out, (bits), 0 );\
|
||||
}
|
||||
|
||||
|
||||
/* private */
|
||||
enum { snes_ntsc_entry_size = 128 };
|
||||
enum { snes_ntsc_palette_size = 0x2000 };
|
||||
typedef unsigned long snes_ntsc_rgb_t;
|
||||
struct snes_ntsc_t {
|
||||
snes_ntsc_rgb_t table [snes_ntsc_palette_size] [snes_ntsc_entry_size];
|
||||
};
|
||||
enum { snes_ntsc_burst_size = snes_ntsc_entry_size / snes_ntsc_burst_count };
|
||||
|
||||
#define SNES_NTSC_RGB16( ktable, n ) \
|
||||
(snes_ntsc_rgb_t const*) (ktable + ((n & 0x001E) | (n >> 1 & 0x03E0) | (n >> 2 & 0x3C00)) * \
|
||||
(snes_ntsc_entry_size / 2 * sizeof (snes_ntsc_rgb_t)))
|
||||
|
||||
#define SNES_NTSC_BGR15( ktable, n ) \
|
||||
(snes_ntsc_rgb_t const*) (ktable + ((n << 9 & 0x3C00) | (n & 0x03E0) | (n >> 10 & 0x001E)) * \
|
||||
(snes_ntsc_entry_size / 2 * sizeof (snes_ntsc_rgb_t)))
|
||||
|
||||
/* common 3->7 ntsc macros */
|
||||
#define SNES_NTSC_BEGIN_ROW_6_( pixel0, pixel1, pixel2, ENTRY, table ) \
|
||||
unsigned const snes_ntsc_pixel0_ = (pixel0);\
|
||||
snes_ntsc_rgb_t const* kernel0 = ENTRY( table, snes_ntsc_pixel0_ );\
|
||||
unsigned const snes_ntsc_pixel1_ = (pixel1);\
|
||||
snes_ntsc_rgb_t const* kernel1 = ENTRY( table, snes_ntsc_pixel1_ );\
|
||||
unsigned const snes_ntsc_pixel2_ = (pixel2);\
|
||||
snes_ntsc_rgb_t const* kernel2 = ENTRY( table, snes_ntsc_pixel2_ );\
|
||||
snes_ntsc_rgb_t const* kernelx0;\
|
||||
snes_ntsc_rgb_t const* kernelx1 = kernel0;\
|
||||
snes_ntsc_rgb_t const* kernelx2 = kernel0
|
||||
|
||||
#define SNES_NTSC_RGB_OUT_14_( x, rgb_out, bits, shift ) {\
|
||||
snes_ntsc_rgb_t raw_ =\
|
||||
kernel0 [x ] + kernel1 [(x+12)%7+14] + kernel2 [(x+10)%7+28] +\
|
||||
kernelx0 [(x+7)%14] + kernelx1 [(x+ 5)%7+21] + kernelx2 [(x+ 3)%7+35];\
|
||||
SNES_NTSC_CLAMP_( raw_, shift );\
|
||||
SNES_NTSC_RGB_OUT_( rgb_out, bits, shift );\
|
||||
}
|
||||
|
||||
/* common ntsc macros */
|
||||
#define snes_ntsc_rgb_builder ((1L << 21) | (1 << 11) | (1 << 1))
|
||||
#define snes_ntsc_clamp_mask (snes_ntsc_rgb_builder * 3 / 2)
|
||||
#define snes_ntsc_clamp_add (snes_ntsc_rgb_builder * 0x101)
|
||||
#define SNES_NTSC_CLAMP_( io, shift ) {\
|
||||
snes_ntsc_rgb_t sub = (io) >> (9-(shift)) & snes_ntsc_clamp_mask;\
|
||||
snes_ntsc_rgb_t clamp = snes_ntsc_clamp_add - sub;\
|
||||
io |= clamp;\
|
||||
clamp -= sub;\
|
||||
io &= clamp;\
|
||||
}
|
||||
|
||||
#define SNES_NTSC_COLOR_IN_( index, color, ENTRY, table ) {\
|
||||
unsigned color_;\
|
||||
kernelx##index = kernel##index;\
|
||||
kernel##index = (color_ = (color), ENTRY( table, color_ ));\
|
||||
}
|
||||
|
||||
/* x is always zero except in snes_ntsc library */
|
||||
#define SNES_NTSC_RGB_OUT_( rgb_out, bits, x ) {\
|
||||
if ( bits == 16 )\
|
||||
rgb_out = (raw_>>(13-x)& 0xF800)|(raw_>>(8-x)&0x07E0)|(raw_>>(4-x)&0x001F);\
|
||||
if ( bits == 24 || bits == 32 )\
|
||||
rgb_out = 0xFF000000|(raw_>>(5-x)&0xFF0000)|(raw_>>(3-x)&0xFF00)|(raw_>>(1-x)&0xFF);\
|
||||
if ( bits == 15 )\
|
||||
rgb_out = (raw_>>(14-x)& 0x7C00)|(raw_>>(9-x)&0x03E0)|(raw_>>(4-x)&0x001F);\
|
||||
if ( bits == 14 )\
|
||||
rgb_out = (raw_>>(24-x)& 0x001F)|(raw_>>(9-x)&0x03E0)|(raw_<<(6+x)&0x7C00);\
|
||||
if ( bits == 0 )\
|
||||
rgb_out = raw_ << x;\
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
26
Utilities/snes_ntsc_config.h
Normal file
26
Utilities/snes_ntsc_config.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
/* Configure library by modifying this file */
|
||||
|
||||
#ifndef SNES_NTSC_CONFIG_H
|
||||
#define SNES_NTSC_CONFIG_H
|
||||
|
||||
/* Format of source pixels */
|
||||
/* #define SNES_NTSC_IN_FORMAT SNES_NTSC_RGB16 */
|
||||
#define SNES_NTSC_IN_FORMAT SNES_NTSC_BGR15
|
||||
|
||||
/* The following affect the built-in blitter only; a custom blitter can
|
||||
handle things however it wants. */
|
||||
|
||||
/* Bits per pixel of output. Can be 15, 16, 32, or 24 (same as 32). */
|
||||
#define SNES_NTSC_OUT_DEPTH 32
|
||||
|
||||
/* Type of input pixel values */
|
||||
#define SNES_NTSC_IN_T unsigned short
|
||||
|
||||
/* Each raw pixel input value is passed through this. You might want to mask
|
||||
the pixel index if you use the high bits as flags, etc. */
|
||||
#define SNES_NTSC_ADJ_IN( in ) in
|
||||
|
||||
/* For each pixel, this is the basic operation:
|
||||
output_color = SNES_NTSC_ADJ_IN( SNES_NTSC_IN_T ) */
|
||||
|
||||
#endif
|
|
@ -1,4 +1,4 @@
|
|||
/* nes_ntsc 0.2.2. http://www.slack.net/~ant/ */
|
||||
/* snes_ntsc 0.2.2. http://www.slack.net/~ant/ */
|
||||
|
||||
/* Common implementation of NTSC filters */
|
||||
|
||||
|
@ -44,7 +44,7 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
|||
#define rgb_unit (1 << rgb_bits)
|
||||
#define rgb_offset (rgb_unit * 2 + 0.5f)
|
||||
|
||||
enum { burst_size = nes_ntsc_entry_size / burst_count };
|
||||
enum { burst_size = snes_ntsc_entry_size / burst_count };
|
||||
enum { kernel_half = 16 };
|
||||
enum { kernel_size = kernel_half * 2 + 1 };
|
||||
|
||||
|
@ -66,7 +66,7 @@ typedef struct init_t
|
|||
i = t;\
|
||||
}
|
||||
|
||||
static void init_filters( init_t* impl, nes_ntsc_setup_t const* setup )
|
||||
static void init_filters( init_t* impl, snes_ntsc_setup_t const* setup )
|
||||
{
|
||||
#if rescale_out > 1
|
||||
float kernels [kernel_size * 2];
|
||||
|
@ -195,7 +195,7 @@ static void init_filters( init_t* impl, nes_ntsc_setup_t const* setup )
|
|||
static float const default_decoder [6] =
|
||||
{ 0.956f, 0.621f, -0.272f, -0.647f, -1.105f, 1.702f };
|
||||
|
||||
static void init( init_t* impl, nes_ntsc_setup_t const* setup )
|
||||
static void init( init_t* impl, snes_ntsc_setup_t const* setup )
|
||||
{
|
||||
impl->brightness = (float) setup->brightness * (0.5f * rgb_unit) + rgb_offset;
|
||||
impl->contrast = (float) setup->contrast * (0.5f * rgb_unit) + rgb_unit;
|
||||
|
@ -285,7 +285,7 @@ static void init( init_t* impl, nes_ntsc_setup_t const* setup )
|
|||
#define PACK_RGB( r, g, b ) ((r) << 21 | (g) << 11 | (b) << 1)
|
||||
|
||||
enum { rgb_kernel_size = burst_size / alignment_count };
|
||||
enum { rgb_bias = rgb_unit * 2 * nes_ntsc_rgb_builder };
|
||||
enum { rgb_bias = rgb_unit * 2 * snes_ntsc_rgb_builder };
|
||||
|
||||
typedef struct pixel_info_t
|
||||
{
|
||||
|
@ -309,10 +309,10 @@ typedef struct pixel_info_t
|
|||
(1.0f - (((ntsc) + 100) & 2))
|
||||
#endif
|
||||
|
||||
extern pixel_info_t const nes_ntsc_pixels [alignment_count];
|
||||
extern pixel_info_t const snes_ntsc_pixels [alignment_count];
|
||||
|
||||
/* Generate pixel at all burst phases and column alignments */
|
||||
static void gen_kernel( init_t* impl, float y, float i, float q, nes_ntsc_rgb_t* out )
|
||||
static void gen_kernel( init_t* impl, float y, float i, float q, snes_ntsc_rgb_t* out )
|
||||
{
|
||||
/* generate for each scanline burst phase */
|
||||
float const* to_rgb = impl->to_rgb;
|
||||
|
@ -324,7 +324,7 @@ static void gen_kernel( init_t* impl, float y, float i, float q, nes_ntsc_rgb_t*
|
|||
Convolve these with kernels which: filter respective components, apply
|
||||
sharpening, and rescale horizontally. Convert resulting yiq to rgb and pack
|
||||
into integer. Based on algorithm by NewRisingSun. */
|
||||
pixel_info_t const* pixel = nes_ntsc_pixels;
|
||||
pixel_info_t const* pixel = snes_ntsc_pixels;
|
||||
int alignment_remain = alignment_count;
|
||||
do
|
||||
{
|
||||
|
@ -377,7 +377,7 @@ static void gen_kernel( init_t* impl, float y, float i, float q, nes_ntsc_rgb_t*
|
|||
while ( --burst_remain );
|
||||
}
|
||||
|
||||
static void correct_errors( nes_ntsc_rgb_t color, nes_ntsc_rgb_t* out );
|
||||
static void correct_errors( snes_ntsc_rgb_t color, snes_ntsc_rgb_t* out );
|
||||
|
||||
#if DISABLE_CORRECTION
|
||||
#define CORRECT_ERROR( a ) { out [i] += rgb_bias; }
|
||||
|
@ -385,8 +385,8 @@ static void correct_errors( nes_ntsc_rgb_t color, nes_ntsc_rgb_t* out );
|
|||
#else
|
||||
#define CORRECT_ERROR( a ) { out [a] += error; }
|
||||
#define DISTRIBUTE_ERROR( a, b, c ) {\
|
||||
nes_ntsc_rgb_t fourth = (error + 2 * nes_ntsc_rgb_builder) >> 2;\
|
||||
fourth &= (rgb_bias >> 1) - nes_ntsc_rgb_builder;\
|
||||
snes_ntsc_rgb_t fourth = (error + 2 * snes_ntsc_rgb_builder) >> 2;\
|
||||
fourth &= (rgb_bias >> 1) - snes_ntsc_rgb_builder;\
|
||||
fourth -= rgb_bias >> 2;\
|
||||
out [a] += fourth;\
|
||||
out [b] += fourth;\
|
||||
|
@ -398,8 +398,8 @@ static void correct_errors( nes_ntsc_rgb_t color, nes_ntsc_rgb_t* out );
|
|||
#define RGB_PALETTE_OUT( rgb, out_ )\
|
||||
{\
|
||||
unsigned char* out = (out_);\
|
||||
nes_ntsc_rgb_t clamped = (rgb);\
|
||||
NES_NTSC_CLAMP_( clamped, (8 - rgb_bits) );\
|
||||
snes_ntsc_rgb_t clamped = (rgb);\
|
||||
SNES_NTSC_CLAMP_( clamped, (8 - rgb_bits) );\
|
||||
out [0] = (unsigned char) (clamped >> 21);\
|
||||
out [1] = (unsigned char) (clamped >> 11);\
|
||||
out [2] = (unsigned char) (clamped >> 1);\
|
||||
|
@ -420,18 +420,18 @@ static void correct_errors( nes_ntsc_rgb_t color, nes_ntsc_rgb_t* out );
|
|||
|
||||
#include <limits.h>
|
||||
|
||||
#if NES_NTSC_OUT_DEPTH <= 16
|
||||
#if SNES_NTSC_OUT_DEPTH <= 16
|
||||
#if USHRT_MAX == 0xFFFF
|
||||
typedef unsigned short nes_ntsc_out_t;
|
||||
typedef unsigned short snes_ntsc_out_t;
|
||||
#else
|
||||
#error "Need 16-bit int type"
|
||||
#endif
|
||||
|
||||
#else
|
||||
#if UINT_MAX == 0xFFFFFFFF
|
||||
typedef unsigned int nes_ntsc_out_t;
|
||||
typedef unsigned int snes_ntsc_out_t;
|
||||
#elif ULONG_MAX == 0xFFFFFFFF
|
||||
typedef unsigned long nes_ntsc_out_t;
|
||||
typedef unsigned long snes_ntsc_out_t;
|
||||
#else
|
||||
#error "Need 32-bit int type"
|
||||
#endif
|
|
@ -8,6 +8,7 @@
|
|||
#include "../Core/Debugger.h"
|
||||
#include "../Core/MessageManager.h"
|
||||
#include "../Core/SettingTypes.h"
|
||||
#include "../Core/EmuSettings.h"
|
||||
#include "../Utilities/UTF8Util.h"
|
||||
|
||||
using namespace DirectX;
|
||||
|
@ -40,20 +41,18 @@ void Renderer::SetFullscreenMode(bool fullscreen, void* windowHandle, uint32_t m
|
|||
|
||||
void Renderer::SetScreenSize(uint32_t width, uint32_t height)
|
||||
{
|
||||
ScreenSize screenSize;
|
||||
_console->GetVideoDecoder()->GetScreenSize(screenSize, false);
|
||||
|
||||
//TODO _resizeFilter != _console->GetSettings()->GetVideoResizeFilter()
|
||||
if(_screenHeight != screenSize.Height || _screenWidth != screenSize.Width || _nesFrameHeight != height || _nesFrameWidth != width || _newFullscreen != _fullscreen) {
|
||||
ScreenSize screenSize = _console->GetVideoDecoder()->GetScreenSize(false);
|
||||
VideoConfig cfg = _console->GetSettings()->GetVideoConfig();
|
||||
if(_screenHeight != screenSize.Height || _screenWidth != screenSize.Width || _nesFrameHeight != height || _nesFrameWidth != width || _newFullscreen != _fullscreen || _useBilinearInterpolation != cfg.UseBilinearInterpolation) {
|
||||
auto frameLock = _frameLock.AcquireSafe();
|
||||
auto textureLock = _textureLock.AcquireSafe();
|
||||
_console->GetVideoDecoder()->GetScreenSize(screenSize, false);
|
||||
if(_screenHeight != screenSize.Height || _screenWidth != screenSize.Width || _nesFrameHeight != height || _nesFrameWidth != width || _newFullscreen != _fullscreen) {
|
||||
screenSize = _console->GetVideoDecoder()->GetScreenSize(false);
|
||||
if(_screenHeight != screenSize.Height || _screenWidth != screenSize.Width || _nesFrameHeight != height || _nesFrameWidth != width || _newFullscreen != _fullscreen || _useBilinearInterpolation != cfg.UseBilinearInterpolation) {
|
||||
_nesFrameHeight = height;
|
||||
_nesFrameWidth = width;
|
||||
_newFrameBufferSize = width*height;
|
||||
|
||||
bool needReset = _fullscreen != _newFullscreen;//TODO || _resizeFilter != _console->GetSettings()->GetVideoResizeFilter();
|
||||
bool needReset = _fullscreen != _newFullscreen || _useBilinearInterpolation != cfg.UseBilinearInterpolation;
|
||||
bool fullscreenResizeMode = _fullscreen && _newFullscreen;
|
||||
|
||||
if(_pSwapChain && _fullscreen && !_newFullscreen) {
|
||||
|
@ -278,7 +277,7 @@ HRESULT Renderer::InitDevice()
|
|||
sd.BufferDesc.Width = _realScreenWidth;
|
||||
sd.BufferDesc.Height = _realScreenHeight;
|
||||
sd.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
sd.BufferDesc.RefreshRate.Numerator = 60; //TODO _console->GetSettings()->GetExclusiveRefreshRate();
|
||||
sd.BufferDesc.RefreshRate.Numerator = _console->GetSettings()->GetVideoConfig().ExclusiveFullscreenRefreshRate;
|
||||
sd.BufferDesc.RefreshRate.Denominator = 1;
|
||||
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
sd.Flags = _fullscreen ? DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH : 0;
|
||||
|
@ -401,12 +400,12 @@ HRESULT Renderer::InitDevice()
|
|||
|
||||
HRESULT Renderer::CreateSamplerState()
|
||||
{
|
||||
_resizeFilter = VideoResizeFilter::NearestNeighbor; //TODO _console->GetSettings()->GetVideoResizeFilter();
|
||||
_useBilinearInterpolation = _console->GetSettings()->GetVideoConfig().UseBilinearInterpolation;
|
||||
|
||||
//Sample state
|
||||
D3D11_SAMPLER_DESC samplerDesc;
|
||||
ZeroMemory(&samplerDesc, sizeof(samplerDesc));
|
||||
samplerDesc.Filter = _resizeFilter == VideoResizeFilter::Bilinear ? D3D11_FILTER_MIN_MAG_MIP_LINEAR : D3D11_FILTER_MIN_MAG_MIP_POINT;
|
||||
samplerDesc.Filter = _useBilinearInterpolation ? D3D11_FILTER_MIN_MAG_MIP_LINEAR : D3D11_FILTER_MIN_MAG_MIP_POINT;
|
||||
samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
|
@ -637,7 +636,7 @@ void Renderer::Render()
|
|||
|
||||
// Present the information rendered to the back buffer to the front buffer (the screen)
|
||||
|
||||
bool waitVSync = false; //TODO _console->GetSettings()->CheckFlag(EmulationFlags::VerticalSync)
|
||||
bool waitVSync = _console->GetSettings()->GetVideoConfig().VerticalSync;
|
||||
HRESULT hr = _pSwapChain->Present(waitVSync ? 1 : 0, 0);
|
||||
if(FAILED(hr)) {
|
||||
MessageManager::Log("SwapChain::Present() failed - Error:" + std::to_string(hr));
|
||||
|
|
|
@ -42,7 +42,7 @@ private:
|
|||
SimpleLock _frameLock;
|
||||
SimpleLock _textureLock;
|
||||
|
||||
VideoResizeFilter _resizeFilter = VideoResizeFilter::NearestNeighbor;
|
||||
bool _useBilinearInterpolation = false;
|
||||
|
||||
unique_ptr<SpriteFont> _font;
|
||||
unique_ptr<SpriteFont> _largeFont;
|
||||
|
|
Loading…
Add table
Reference in a new issue