mirror of https://github.com/stella-emu/stella.git
OK, now it's time to start adding adjustable knobs for the TV effects.
git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@2466 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
parent
3a63ef57c3
commit
e171eddfd2
|
@ -30,8 +30,6 @@
|
||||||
#define FILTER_NTSC_FRINGING_MAX 1.0
|
#define FILTER_NTSC_FRINGING_MAX 1.0
|
||||||
#define FILTER_NTSC_BLEED_MIN -1.0
|
#define FILTER_NTSC_BLEED_MIN -1.0
|
||||||
#define FILTER_NTSC_BLEED_MAX 1.0
|
#define FILTER_NTSC_BLEED_MAX 1.0
|
||||||
#define FILTER_NTSC_BURST_PHASE_MIN -1.0
|
|
||||||
#define FILTER_NTSC_BURST_PHASE_MAX 1.0
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
NTSCFilter::NTSCFilter()
|
NTSCFilter::NTSCFilter()
|
||||||
|
|
|
@ -54,9 +54,8 @@ class NTSCFilter
|
||||||
/* Normally used in conjunction with custom mode, contains all
|
/* Normally used in conjunction with custom mode, contains all
|
||||||
aspects currently adjustable in NTSC TV emulation. */
|
aspects currently adjustable in NTSC TV emulation. */
|
||||||
struct Adjustable {
|
struct Adjustable {
|
||||||
double hue, saturation, contrast, brightness, gamma,
|
uInt32 hue, saturation, contrast, brightness, gamma,
|
||||||
sharpness, resolution, artifacts, fringing, bleed,
|
sharpness, resolution, artifacts, fringing, bleed;
|
||||||
burst_phase;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -73,8 +72,7 @@ class NTSCFilter
|
||||||
// have changed)
|
// have changed)
|
||||||
void updateFilter()
|
void updateFilter()
|
||||||
{
|
{
|
||||||
mySetup.palette = myTIAPalette;
|
atari_ntsc_init(&myFilter, &mySetup, myTIAPalette);
|
||||||
atari_ntsc_init(&myFilter, &mySetup);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load and save NTSC-related settings
|
// Load and save NTSC-related settings
|
||||||
|
|
|
@ -31,11 +31,10 @@
|
||||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
atari_ntsc_setup_t const atari_ntsc_composite = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.15, 0.0, 0.0, 0.0, 0, 0, 0, 0 };
|
atari_ntsc_setup_t const atari_ntsc_composite = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.15, 0.0, 0.0, 0.0, 0 };
|
||||||
atari_ntsc_setup_t const atari_ntsc_svideo = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.45, -1.0, -1.0, 0.0, 0, 0, 0, 0 };
|
atari_ntsc_setup_t const atari_ntsc_svideo = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.45, -1.0, -1.0, 0.0, 0 };
|
||||||
atari_ntsc_setup_t const atari_ntsc_rgb = { 0.0, 0.0, 0.0, 0.0, 0.2, 0.0, 0.70, -1.0, -1.0, -1.0, 0, 0, 0, 0 };
|
atari_ntsc_setup_t const atari_ntsc_rgb = { 0.0, 0.0, 0.0, 0.0, 0.2, 0.0, 0.70, -1.0, -1.0, -1.0, 0 };
|
||||||
atari_ntsc_setup_t const atari_ntsc_bad = { 0.1, -0.3, 0.3, 0.25, 0.2, 0.0, 0.1, 0.5, 0.5, 0.5, 0, 0, 0, 0 };
|
atari_ntsc_setup_t const atari_ntsc_bad = { 0.1, -0.3, 0.3, 0.25, 0.2, 0.0, 0.1, 0.5, 0.5, 0.5, 0 };
|
||||||
atari_ntsc_setup_t const atari_ntsc_horrible = { -0.1, -0.5, 0.6, 0.43, 0.4, 0.0, 0.05, 0.7, -0.8, -0.7, 0, 0, 0, 0 };
|
|
||||||
|
|
||||||
#define alignment_count 2
|
#define alignment_count 2
|
||||||
#define burst_count 1
|
#define burst_count 1
|
||||||
|
@ -48,7 +47,6 @@ atari_ntsc_setup_t const atari_ntsc_horrible = { -0.1, -0.5, 0.6, 0.43, 0.4, 0.
|
||||||
#define std_decoder_hue 0
|
#define std_decoder_hue 0
|
||||||
|
|
||||||
#define gamma_size 256
|
#define gamma_size 256
|
||||||
#define default_palette_contrast 1.0f
|
|
||||||
|
|
||||||
#include "atari_ntsc_impl.h"
|
#include "atari_ntsc_impl.h"
|
||||||
|
|
||||||
|
@ -70,9 +68,9 @@ static void correct_errors( atari_ntsc_rgb_t color, atari_ntsc_rgb_t* out )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void atari_ntsc_init( atari_ntsc_t* ntsc, atari_ntsc_setup_t const* setup )
|
void atari_ntsc_init( atari_ntsc_t* ntsc, atari_ntsc_setup_t const* setup,
|
||||||
|
atari_ntsc_in_t const* palette )
|
||||||
{
|
{
|
||||||
atari_ntsc_in_t* palette;
|
|
||||||
int entry;
|
int entry;
|
||||||
init_t impl;
|
init_t impl;
|
||||||
if ( !setup )
|
if ( !setup )
|
||||||
|
@ -80,11 +78,6 @@ void atari_ntsc_init( atari_ntsc_t* ntsc, atari_ntsc_setup_t const* setup )
|
||||||
init( &impl, setup );
|
init( &impl, setup );
|
||||||
|
|
||||||
// Palette stores R/G/B data for 'atari_ntsc_palette_size' entries
|
// Palette stores R/G/B data for 'atari_ntsc_palette_size' entries
|
||||||
palette = (atari_ntsc_in_t*) setup->palette;
|
|
||||||
|
|
||||||
// Burst-phase (TODO - how is this actually used?)
|
|
||||||
// float start_angle = - ((213.0f) * M_PI / 180.0f) - setup->burst_phase * M_PI;
|
|
||||||
|
|
||||||
for ( entry = 0; entry < atari_ntsc_palette_size; entry++ )
|
for ( entry = 0; entry < atari_ntsc_palette_size; entry++ )
|
||||||
{
|
{
|
||||||
float r = impl.to_float [*palette++];
|
float r = impl.to_float [*palette++];
|
||||||
|
@ -95,7 +88,7 @@ void atari_ntsc_init( atari_ntsc_t* ntsc, atari_ntsc_setup_t const* setup )
|
||||||
|
|
||||||
// Generate kernel
|
// Generate kernel
|
||||||
int ir, ig, ib = YIQ_TO_RGB( y, i, q, impl.to_rgb, int, ir, ig );
|
int ir, ig, ib = YIQ_TO_RGB( y, i, q, impl.to_rgb, int, ir, ig );
|
||||||
atari_ntsc_rgb_t rgb = PACK_RGB( ir, ig, ib ); //(ib < 0x3E0 ? ib: 0x3E0)
|
atari_ntsc_rgb_t rgb = PACK_RGB( ir, ig, ib );
|
||||||
|
|
||||||
if ( ntsc )
|
if ( ntsc )
|
||||||
{
|
{
|
||||||
|
|
|
@ -48,29 +48,21 @@ typedef struct atari_ntsc_setup_t
|
||||||
double fringing; /* color artifacts caused by brightness changes */
|
double fringing; /* color artifacts caused by brightness changes */
|
||||||
double bleed; /* color bleed (color resolution reduction) */
|
double bleed; /* color bleed (color resolution reduction) */
|
||||||
float const* decoder_matrix; /* optional RGB decoder matrix, 6 elements */
|
float const* decoder_matrix; /* optional RGB decoder matrix, 6 elements */
|
||||||
|
|
||||||
/* You can replace the standard TI color generation with an RGB palette. */
|
|
||||||
unsigned char const* palette;/* optional RGB palette in, 3 bytes per color */
|
|
||||||
unsigned char* palette_out; /* optional RGB palette out, 3 bytes per color */
|
|
||||||
|
|
||||||
/* Atari change: additional setup fields */
|
|
||||||
double burst_phase; /* Phase at which colorburst signal is turned on;
|
|
||||||
this defines colors of artifacts.
|
|
||||||
In radians; -1.0 = -180 degrees, 1.0 = +180 degrees */
|
|
||||||
} atari_ntsc_setup_t;
|
} atari_ntsc_setup_t;
|
||||||
|
|
||||||
/* Video format presets */
|
/* Video format presets */
|
||||||
extern atari_ntsc_setup_t const atari_ntsc_composite; /* color bleeding + artifacts */
|
extern atari_ntsc_setup_t const atari_ntsc_composite; /* color bleeding + artifacts */
|
||||||
extern atari_ntsc_setup_t const atari_ntsc_svideo; /* color bleeding only */
|
extern atari_ntsc_setup_t const atari_ntsc_svideo; /* color bleeding only */
|
||||||
extern atari_ntsc_setup_t const atari_ntsc_rgb; /* crisp image */
|
extern atari_ntsc_setup_t const atari_ntsc_rgb; /* crisp image */
|
||||||
extern atari_ntsc_setup_t const atari_ntsc_bad;
|
extern atari_ntsc_setup_t const atari_ntsc_bad; /* badly adjusted TV */
|
||||||
|
|
||||||
enum { atari_ntsc_palette_size = 128 };
|
enum { atari_ntsc_palette_size = 128 };
|
||||||
|
|
||||||
/* Initializes and adjusts parameters. Can be called multiple times on the same
|
/* Initializes and adjusts parameters. Can be called multiple times on the same
|
||||||
atari_ntsc_t object. Can pass NULL for either parameter. */
|
atari_ntsc_t object. Can pass NULL for either parameter. */
|
||||||
typedef struct atari_ntsc_t atari_ntsc_t;
|
typedef struct atari_ntsc_t atari_ntsc_t;
|
||||||
void atari_ntsc_init( atari_ntsc_t* ntsc, atari_ntsc_setup_t const* setup );
|
void atari_ntsc_init( atari_ntsc_t* ntsc, atari_ntsc_setup_t const* setup,
|
||||||
|
atari_ntsc_in_t const* palette );
|
||||||
|
|
||||||
/* Filters one or more rows of pixels. Input pixels are 8-bit Atari palette colors.
|
/* Filters one or more rows of pixels. Input pixels are 8-bit Atari palette colors.
|
||||||
In_row_width is the number of pixels to get to the next input row. Out_pitch
|
In_row_width is the number of pixels to get to the next input row. Out_pitch
|
||||||
|
|
|
@ -220,10 +220,6 @@ static void init( init_t* impl, atari_ntsc_setup_t const* setup )
|
||||||
{
|
{
|
||||||
impl->brightness = (float) setup->brightness * (0.5f * rgb_unit) + rgb_offset;
|
impl->brightness = (float) setup->brightness * (0.5f * rgb_unit) + rgb_offset;
|
||||||
impl->contrast = (float) setup->contrast * (0.5f * rgb_unit) + rgb_unit;
|
impl->contrast = (float) setup->contrast * (0.5f * rgb_unit) + rgb_unit;
|
||||||
#ifdef default_palette_contrast
|
|
||||||
if ( !setup->palette )
|
|
||||||
impl->contrast *= default_palette_contrast;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
impl->artifacts = (float) setup->artifacts;
|
impl->artifacts = (float) setup->artifacts;
|
||||||
if ( impl->artifacts > 0 )
|
if ( impl->artifacts > 0 )
|
||||||
|
@ -251,20 +247,7 @@ static void init( init_t* impl, atari_ntsc_setup_t const* setup )
|
||||||
|
|
||||||
/* setup decoder matricies */
|
/* setup decoder matricies */
|
||||||
{
|
{
|
||||||
#if 0 // FIXME - research this
|
|
||||||
/* Atari change:
|
|
||||||
NTSC colorburst angle in YIQ colorspace. Colorburst is at
|
|
||||||
180 degrees in YUV - that is, a gold color. In YIQ, gold is at
|
|
||||||
different angle. However, YIQ is actually YUV turned
|
|
||||||
33 degrees. So by looking at screenshots at Wikipedia we can
|
|
||||||
conclude that the colorburst angle is 180+33 in YIQ.
|
|
||||||
(See http://en.wikipedia.org/wiki/YUV and
|
|
||||||
http://en.wikipedia.org/wiki/YIQ) */
|
|
||||||
static float const colorburst_angle = (213.0f) * PI / 180.0f;
|
|
||||||
float hue = (float) setup->hue * PI + PI / 180 * ext_decoder_hue - PI * setup->burst_phase - colorburst_angle;
|
|
||||||
#else
|
|
||||||
float hue = (float) setup->hue * PI + PI / 180 * ext_decoder_hue;
|
float hue = (float) setup->hue * PI + PI / 180 * ext_decoder_hue;
|
||||||
#endif
|
|
||||||
float sat = (float) setup->saturation + 1;
|
float sat = (float) setup->saturation + 1;
|
||||||
float const* decoder = setup->decoder_matrix;
|
float const* decoder = setup->decoder_matrix;
|
||||||
if ( !decoder )
|
if ( !decoder )
|
||||||
|
|
|
@ -40,7 +40,6 @@ Settings::Settings(OSystem* osystem)
|
||||||
setInternal("video", "soft");
|
setInternal("video", "soft");
|
||||||
|
|
||||||
// OpenGL specific options
|
// OpenGL specific options
|
||||||
setInternal("gl_inter", "false");
|
|
||||||
setInternal("gl_aspectn", "90");
|
setInternal("gl_aspectn", "90");
|
||||||
setInternal("gl_aspectp", "100");
|
setInternal("gl_aspectp", "100");
|
||||||
setInternal("gl_fsscale", "false");
|
setInternal("gl_fsscale", "false");
|
||||||
|
@ -61,8 +60,19 @@ Settings::Settings(OSystem* osystem)
|
||||||
|
|
||||||
// TV filtering options
|
// TV filtering options
|
||||||
setInternal("tv_filter", "0");
|
setInternal("tv_filter", "0");
|
||||||
setInternal("tv_scanlines", "50");
|
setInternal("tv_inter", "false");
|
||||||
|
setInternal("tv_scanlines", "40");
|
||||||
setInternal("tv_scaninter", "true");
|
setInternal("tv_scaninter", "true");
|
||||||
|
// TV options when using 'custom' mode
|
||||||
|
setInternal("tv_sharpness", "0.0");
|
||||||
|
setInternal("tv_resolution", "0.0");
|
||||||
|
setInternal("tv_artifacts", "0.0");
|
||||||
|
setInternal("tv_fringing", "0.0");
|
||||||
|
setInternal("tv_bleed", "0.0");
|
||||||
|
setInternal("tv_brightness", "0.0");
|
||||||
|
setInternal("tv_contrast", "0.0");
|
||||||
|
setInternal("tv_saturation", "0.0");
|
||||||
|
setInternal("tv_gamma", "0.0");
|
||||||
|
|
||||||
// Sound options
|
// Sound options
|
||||||
setInternal("sound", "true");
|
setInternal("sound", "true");
|
||||||
|
|
|
@ -169,7 +169,7 @@ class Settings
|
||||||
static string trim(string& str)
|
static string trim(string& str)
|
||||||
{
|
{
|
||||||
string::size_type first = str.find_first_not_of(' ');
|
string::size_type first = str.find_first_not_of(' ');
|
||||||
return (first == string::npos) ? string() :
|
return (first == string::npos) ? EmptyString :
|
||||||
str.substr(first, str.find_last_not_of(' ')-first+1);
|
str.substr(first, str.find_last_not_of(' ')-first+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#include "Widget.hxx"
|
#include "Widget.hxx"
|
||||||
#include "TabWidget.hxx"
|
#include "TabWidget.hxx"
|
||||||
#include "FrameBufferGL.hxx"
|
#include "FrameBufferGL.hxx"
|
||||||
|
#include "NTSCFilter.hxx"
|
||||||
|
|
||||||
#include "VideoDialog.hxx"
|
#include "VideoDialog.hxx"
|
||||||
|
|
||||||
|
@ -237,17 +238,61 @@ VideoDialog::VideoDialog(OSystem* osystem, DialogContainer* parent,
|
||||||
// Add items for tab 0
|
// Add items for tab 0
|
||||||
addToFocusList(wid, tabID);
|
addToFocusList(wid, tabID);
|
||||||
|
|
||||||
#if 0
|
|
||||||
//////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////
|
||||||
// 2) TV effects options
|
// 2) TV effects options
|
||||||
wid.clear();
|
wid.clear();
|
||||||
tabID = myTab->addTab(" TV Effects ");
|
tabID = myTab->addTab(" TV Effects ");
|
||||||
xpos = ypos = 8;
|
xpos = ypos = 5;
|
||||||
// TODO ...
|
|
||||||
|
// TV Mode
|
||||||
|
items.clear();
|
||||||
|
items.push_back("Disabled", BSPF_toString(NTSCFilter::PRESET_OFF));
|
||||||
|
items.push_back("Composite", BSPF_toString(NTSCFilter::PRESET_COMPOSITE));
|
||||||
|
items.push_back("S-Video", BSPF_toString(NTSCFilter::PRESET_SVIDEO));
|
||||||
|
items.push_back("RGB", BSPF_toString(NTSCFilter::PRESET_RGB));
|
||||||
|
items.push_back("Badly adjusted", BSPF_toString(NTSCFilter::PRESET_BAD));
|
||||||
|
items.push_back("Custom", BSPF_toString(NTSCFilter::PRESET_CUSTOM));
|
||||||
|
lwidth = font.getStringWidth("TV Mode: ");
|
||||||
|
pwidth = font.getStringWidth("Badly adjusted"),
|
||||||
|
myTVMode =
|
||||||
|
new PopUpWidget(myTab, font, xpos, ypos, pwidth, lineHeight,
|
||||||
|
items, "TV Mode: ", lwidth, kTVModeChanged);
|
||||||
|
wid.push_back(myTVMode);
|
||||||
|
ypos += lineHeight + 4;
|
||||||
|
|
||||||
|
// Custom adjustables (using macro voodoo)
|
||||||
|
xpos += 8; ypos += 4;
|
||||||
|
pwidth = lwidth;
|
||||||
|
lwidth = font.getStringWidth("Saturation: ");
|
||||||
|
|
||||||
|
#define CREATE_CUSTOM_SLIDERS(obj, desc) \
|
||||||
|
myTV ## obj = \
|
||||||
|
new SliderWidget(myTab, font, xpos, ypos, pwidth, lineHeight, \
|
||||||
|
desc, lwidth, kTV ## obj ##Changed); \
|
||||||
|
myTV ## obj->setMinValue(0); myTV ## obj->setMaxValue(100); \
|
||||||
|
wid.push_back(myTV ## obj); \
|
||||||
|
myTV ## obj ## Label = \
|
||||||
|
new StaticTextWidget(myTab, font, xpos+myTV ## obj->getWidth()+4, \
|
||||||
|
ypos+1, fontWidth*3, fontHeight, "", kTextAlignLeft);\
|
||||||
|
myTV ## obj->setFlags(WIDGET_CLEARBG); \
|
||||||
|
ypos += lineHeight + 4
|
||||||
|
|
||||||
|
CREATE_CUSTOM_SLIDERS(Sharp, "Sharpness: ");
|
||||||
|
CREATE_CUSTOM_SLIDERS(Res, "Resolution: ");
|
||||||
|
CREATE_CUSTOM_SLIDERS(Artifacts, "Artifacts: ");
|
||||||
|
CREATE_CUSTOM_SLIDERS(Fringe, "Fringing: ");
|
||||||
|
CREATE_CUSTOM_SLIDERS(Blend, "Blending: ");
|
||||||
|
CREATE_CUSTOM_SLIDERS(Bright, "Brightness: ");
|
||||||
|
CREATE_CUSTOM_SLIDERS(Contrast, "Contrast: ");
|
||||||
|
CREATE_CUSTOM_SLIDERS(Satur, "Saturation: ");
|
||||||
|
CREATE_CUSTOM_SLIDERS(Gamma, "Gamma: ");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Add items for tab 2
|
// Add items for tab 2
|
||||||
addToFocusList(wid, tabID);
|
addToFocusList(wid, tabID);
|
||||||
#endif
|
|
||||||
|
|
||||||
// Activate the first tab
|
// Activate the first tab
|
||||||
myTab->setActiveTab(0);
|
myTab->setActiveTab(0);
|
||||||
|
|
|
@ -78,13 +78,43 @@ class VideoDialog : public Dialog
|
||||||
CheckboxWidget* myFastSCBiosCheckbox;
|
CheckboxWidget* myFastSCBiosCheckbox;
|
||||||
|
|
||||||
// TV effects options
|
// TV effects options
|
||||||
// TODO ...
|
PopUpWidget* myTVMode;
|
||||||
|
SliderWidget* myTVSharp;
|
||||||
|
StaticTextWidget* myTVSharpLabel;
|
||||||
|
SliderWidget* myTVRes;
|
||||||
|
StaticTextWidget* myTVResLabel;
|
||||||
|
SliderWidget* myTVArtifacts;
|
||||||
|
StaticTextWidget* myTVArtifactsLabel;
|
||||||
|
SliderWidget* myTVFringe;
|
||||||
|
StaticTextWidget* myTVFringeLabel;
|
||||||
|
SliderWidget* myTVBlend;
|
||||||
|
StaticTextWidget* myTVBlendLabel;
|
||||||
|
SliderWidget* myTVBright;
|
||||||
|
StaticTextWidget* myTVBrightLabel;
|
||||||
|
SliderWidget* myTVContrast;
|
||||||
|
StaticTextWidget* myTVContrastLabel;
|
||||||
|
SliderWidget* myTVSatur;
|
||||||
|
StaticTextWidget* myTVSaturLabel;
|
||||||
|
SliderWidget* myTVGamma;
|
||||||
|
StaticTextWidget* myTVGammaLabel;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
kNAspectRatioChanged = 'VDan',
|
kNAspectRatioChanged = 'VDan',
|
||||||
kPAspectRatioChanged = 'VDap',
|
kPAspectRatioChanged = 'VDap',
|
||||||
kFrameRateChanged = 'VDfr',
|
kFrameRateChanged = 'VDfr',
|
||||||
kFullScrChanged = 'VDfs'
|
kFullScrChanged = 'VDfs',
|
||||||
|
|
||||||
|
kTVModeChanged = 'VDtv',
|
||||||
|
kTVSharpChanged = 'TVsh',
|
||||||
|
kTVResChanged = 'TVrs',
|
||||||
|
kTVArtifactsChanged = 'TVar',
|
||||||
|
kTVFringeChanged = 'TVfr',
|
||||||
|
kTVBlendChanged = 'TVbl',
|
||||||
|
kTVBrightChanged = 'TVbr',
|
||||||
|
kTVContrastChanged = 'TVct',
|
||||||
|
kTVSaturChanged = 'TVsa',
|
||||||
|
kTVGammaChanged = 'TVga',
|
||||||
|
kTVScanChanged = 'TVsc'
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue