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:
stephena 2012-05-10 15:36:20 +00:00
parent 3a63ef57c3
commit e171eddfd2
9 changed files with 107 additions and 58 deletions

View File

@ -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()

View File

@ -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

View File

@ -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 )
{ {

View File

@ -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

View File

@ -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 )

View File

@ -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");

View File

@ -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);
} }

View File

@ -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);

View File

@ -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'
}; };
}; };