Custom TV 'adjustables' can now be changed dynamically as follows:

- Alt-9 / Shift-Alt-9 selects (increases/decreases) between
    the various adjustables
  - Alt-0 / Shift-Alt-0 increases/decreases the actual values for
    the previously selected adjustable

Cleaned up the API a little, moving some stuff from Console to
FrameBuffer class.  I think we're due for a pretty major
reorganization of parts of the codebase very soon.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@2473 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2012-05-14 15:06:06 +00:00
parent 732ccaca76
commit e7b38e9963
9 changed files with 238 additions and 120 deletions

View File

@ -397,7 +397,7 @@ void FrameBufferGL::enableNTSC(bool enable)
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 FrameBufferGL::changeScanlines(int relative, int absolute) uInt32 FrameBufferGL::enableScanlines(int relative, int absolute)
{ {
int intensity = myTiaSurface->myScanlineIntensityI; int intensity = myTiaSurface->myScanlineIntensityI;
if(myTiaSurface) if(myTiaSurface)

View File

@ -93,20 +93,6 @@ class FrameBufferGL : public FrameBuffer
void enableNTSC(bool enable); void enableNTSC(bool enable);
bool ntscEnabled() const { return myFilterType == kBlarggNTSC; } bool ntscEnabled() const { return myFilterType == kBlarggNTSC; }
/**
Change scanline intensity and interpolation.
relative = -1 means decrease current intensity by 'directin
direction = 0 means to reload the current video mode
direction = +1 means go to the next higher video mode
@param relative If non-zero, change current intensity by
'relative' amount, otherwise set to 'absolute'
@return New current intensity
*/
uInt32 changeScanlines(int relative, int absolute = 50);
void enableScanlineInterpolation(bool enable);
/** /**
Set up the TIA/emulation palette for a screen of any depth > 8. Set up the TIA/emulation palette for a screen of any depth > 8.
@ -205,6 +191,16 @@ class FrameBufferGL : public FrameBuffer
*/ */
void postFrameUpdate(); void postFrameUpdate();
/**
Change scanline intensity and interpolation.
@param relative If non-zero, change current intensity by
'relative' amount, otherwise set to 'absolute'
@return New current intensity
*/
uInt32 enableScanlines(int relative, int absolute = 50);
void enableScanlineInterpolation(bool enable);
private: private:
enum GLFunctionality { enum GLFunctionality {
kGL_BASIC, kGL_VBO kGL_BASIC, kGL_VBO

View File

@ -19,11 +19,14 @@
#include "NTSCFilter.hxx" #include "NTSCFilter.hxx"
#define SCALE_FROM_100(x) ((x/50.0)-1.0)
#define SCALE_TO_100(x) (uInt32)(50*(x+1.0))
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NTSCFilter::NTSCFilter() NTSCFilter::NTSCFilter()
: mySetup(atari_ntsc_composite), : mySetup(atari_ntsc_composite),
myCustomSetup(atari_ntsc_composite), myPreset(PRESET_OFF),
myPreset(PRESET_OFF) myCurrentAdjustable(0)
{ {
} }
@ -81,6 +84,72 @@ string NTSCFilter::setPreset(Preset preset)
return msg; return msg;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string NTSCFilter::setNextAdjustable()
{
if(myPreset != PRESET_CUSTOM)
return "'Custom' TV mode not selected";
myCurrentAdjustable = (myCurrentAdjustable + 1) % 10;
ostringstream buf;
buf << "Custom adjustable '" << ourCustomAdjustables[myCurrentAdjustable].type
<< "' selected";
return buf.str();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string NTSCFilter::setPreviousAdjustable()
{
if(myPreset != PRESET_CUSTOM)
return "'Custom' TV mode not selected";
if(myCurrentAdjustable == 0) myCurrentAdjustable = 9;
else myCurrentAdjustable--;
ostringstream buf;
buf << "Custom adjustable '" << ourCustomAdjustables[myCurrentAdjustable].type
<< "' selected";
return buf.str();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string NTSCFilter::increaseAdjustable()
{
if(myPreset != PRESET_CUSTOM)
return "'Custom' TV mode not selected";
uInt32 newval = SCALE_TO_100(*ourCustomAdjustables[myCurrentAdjustable].value);
newval += 2; if(newval > 100) newval = 100;
*ourCustomAdjustables[myCurrentAdjustable].value = SCALE_FROM_100(newval);
ostringstream buf;
buf << "Custom '" << ourCustomAdjustables[myCurrentAdjustable].type
<< "' set to " << newval;
setPreset(myPreset);
return buf.str();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string NTSCFilter::decreaseAdjustable()
{
if(myPreset != PRESET_CUSTOM)
return "'Custom' TV mode not selected";
uInt32 newval = SCALE_TO_100(*ourCustomAdjustables[myCurrentAdjustable].value);
if(newval < 2) newval = 0;
else newval -= 2;
*ourCustomAdjustables[myCurrentAdjustable].value = SCALE_FROM_100(newval);
ostringstream buf;
buf << "Custom '" << ourCustomAdjustables[myCurrentAdjustable].type
<< "' set to " << newval;
setPreset(myPreset);
return buf.str();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void NTSCFilter::loadConfig(const Settings& settings) void NTSCFilter::loadConfig(const Settings& settings)
{ {
@ -136,7 +205,6 @@ void NTSCFilter::getAdjustables(Adjustable& adjustable, Preset preset)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void NTSCFilter::setCustomAdjustables(Adjustable& adjustable) void NTSCFilter::setCustomAdjustables(Adjustable& adjustable)
{ {
#define SCALE_FROM_100(x) ((x/50.0)-1.0)
myCustomSetup.hue = SCALE_FROM_100(adjustable.hue); myCustomSetup.hue = SCALE_FROM_100(adjustable.hue);
myCustomSetup.saturation = SCALE_FROM_100(adjustable.saturation); myCustomSetup.saturation = SCALE_FROM_100(adjustable.saturation);
myCustomSetup.contrast = SCALE_FROM_100(adjustable.contrast); myCustomSetup.contrast = SCALE_FROM_100(adjustable.contrast);
@ -153,7 +221,6 @@ void NTSCFilter::setCustomAdjustables(Adjustable& adjustable)
void NTSCFilter::convertToAdjustable(Adjustable& adjustable, void NTSCFilter::convertToAdjustable(Adjustable& adjustable,
const atari_ntsc_setup_t& setup) const const atari_ntsc_setup_t& setup) const
{ {
#define SCALE_TO_100(x) (uInt32)(50*(x+1.0))
adjustable.hue = SCALE_TO_100(setup.hue); adjustable.hue = SCALE_TO_100(setup.hue);
adjustable.saturation = SCALE_TO_100(setup.saturation); adjustable.saturation = SCALE_TO_100(setup.saturation);
adjustable.contrast = SCALE_TO_100(setup.contrast); adjustable.contrast = SCALE_TO_100(setup.contrast);
@ -165,3 +232,20 @@ void NTSCFilter::convertToAdjustable(Adjustable& adjustable,
adjustable.fringing = SCALE_TO_100(setup.fringing); adjustable.fringing = SCALE_TO_100(setup.fringing);
adjustable.bleed = SCALE_TO_100(setup.bleed); adjustable.bleed = SCALE_TO_100(setup.bleed);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
atari_ntsc_setup_t NTSCFilter::myCustomSetup = atari_ntsc_composite;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const NTSCFilter::AdjustableTag NTSCFilter::ourCustomAdjustables[10] = {
{ "contrast", &myCustomSetup.contrast },
{ "brightness", &myCustomSetup.brightness },
{ "hue", &myCustomSetup.hue },
{ "saturation", &myCustomSetup.saturation },
{ "gamma", &myCustomSetup.gamma },
{ "sharpness", &myCustomSetup.sharpness },
{ "resolution", &myCustomSetup.resolution },
{ "artifacts", &myCustomSetup.artifacts },
{ "fringing", &myCustomSetup.fringing },
{ "bleeding", &myCustomSetup.bleed }
};

View File

@ -85,6 +85,17 @@ class NTSCFilter
// they're actually stored internally // they're actually stored internally
void setCustomAdjustables(Adjustable& adjustable); void setCustomAdjustables(Adjustable& adjustable);
// The following methods cycle through each custom adjustable
// They are used in conjunction with the increase/decrease
// methods, which change the currently selected adjustable
// Changes are made this way since otherwise 20 key-combinations
// would be needed to dynamically change each setting, and now
// only 4 combinations are necessary
string setNextAdjustable();
string setPreviousAdjustable();
string increaseAdjustable();
string decreaseAdjustable();
// Load and save NTSC-related settings // Load and save NTSC-related settings
void loadConfig(const Settings& settings); void loadConfig(const Settings& settings);
void saveConfig(Settings& settings) const; void saveConfig(Settings& settings) const;
@ -123,13 +134,20 @@ class NTSCFilter
// This setup is used only in custom mode (after it is modified, // This setup is used only in custom mode (after it is modified,
// it is copied to mySetup) // it is copied to mySetup)
atari_ntsc_setup_t myCustomSetup; static atari_ntsc_setup_t myCustomSetup;
// Current preset in use // Current preset in use
Preset myPreset; Preset myPreset;
// 128 colours by 3 components per colour // 128 colours by 3 components per colour
uInt8 myTIAPalette[128 * 3]; uInt8 myTIAPalette[128 * 3];
struct AdjustableTag {
const char* type;
double* value;
};
uInt32 myCurrentAdjustable;
static const AdjustableTag ourCustomAdjustables[10];
}; };
#endif #endif

View File

@ -443,75 +443,6 @@ void Console::togglePhosphor()
myOSystem->frameBuffer().enablePhosphor(enable, blend); myOSystem->frameBuffer().enablePhosphor(enable, blend);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Console::toggleNTSC(NTSCFilter::Preset preset, bool show)
{
ostringstream buf;
if(myOSystem->frameBuffer().type() == kDoubleBuffer)
{
if(preset == NTSCFilter::PRESET_OFF)
{
myOSystem->frameBuffer().enableNTSC(false);
buf << "TV filtering disabled";
}
else
{
myOSystem->frameBuffer().enableNTSC(true);
const string& mode = myOSystem->frameBuffer().ntsc().setPreset(preset);
buf << "TV filtering (" << mode << " mode)";
}
myOSystem->settings().setInt("tv_filter", (int)preset);
if(show) myOSystem->frameBuffer().showMessage(buf.str());
}
else
buf << "TV filtering not available in software mode";
if(show) myOSystem->frameBuffer().showMessage(buf.str());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Console::changeScanlines(int amount, bool show)
{
ostringstream buf;
if(myOSystem->frameBuffer().type() == kDoubleBuffer)
{
if(myOSystem->frameBuffer().ntscEnabled())
{
uInt32 intensity = myOSystem->frameBuffer().changeScanlines(amount);
buf << "Scanline intensity at " << intensity << "%";
myOSystem->settings().setInt("tv_scanlines", intensity);
}
else
buf << "Scanlines only available in TV filtering mode";
}
else
buf << "Scanlines not available in software mode";
if(show) myOSystem->frameBuffer().showMessage(buf.str());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Console::toggleScanlineInterpolation()
{
ostringstream buf;
if(myOSystem->frameBuffer().type() == kDoubleBuffer)
{
if(myOSystem->frameBuffer().ntscEnabled())
{
bool enable = !myOSystem->settings().getBool("tv_scaninter");
myOSystem->frameBuffer().enableScanlineInterpolation(enable);
buf << "Scanline interpolation " << (enable ? "enabled" : "disabled");
myOSystem->settings().setBool("tv_scaninter", enable);
}
else
buf << "Scanlines only available in TV filtering mode";
}
else
buf << "Scanlines not available in software mode";
myOSystem->frameBuffer().showMessage(buf.str());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Console::setProperties(const Properties& props) void Console::setProperties(const Properties& props)
{ {
@ -539,7 +470,8 @@ FBInitStatus Console::initializeVideo(bool full)
bool enable = myProperties.get(Display_Phosphor) == "YES"; bool enable = myProperties.get(Display_Phosphor) == "YES";
int blend = atoi(myProperties.get(Display_PPBlend).c_str()); int blend = atoi(myProperties.get(Display_PPBlend).c_str());
myOSystem->frameBuffer().enablePhosphor(enable, blend); myOSystem->frameBuffer().enablePhosphor(enable, blend);
toggleNTSC((NTSCFilter::Preset)myOSystem->settings().getInt("tv_filter")); myOSystem->frameBuffer().setNTSC(
(NTSCFilter::Preset)myOSystem->settings().getInt("tv_filter"), false);
setPalette(myOSystem->settings().getString("palette")); setPalette(myOSystem->settings().getString("palette"));
// Set the correct framerate based on the format of the ROM // Set the correct framerate based on the format of the ROM

View File

@ -202,21 +202,6 @@ class Console : public Serializable
*/ */
void togglePhosphor(); void togglePhosphor();
/**
Toggles NTSC filtering effects to use the given preset.
*/
void toggleNTSC(NTSCFilter::Preset preset, bool show = false);
/**
Increase/decrease current scanline intensity by given amount.
*/
void changeScanlines(int amount, bool show = false);
/**
Toggles interpolation/smoothing of scanlines in TV modes.
*/
void toggleScanlineInterpolation();
/** /**
Toggles the PAL color-loss effect. Toggles the PAL color-loss effect.
*/ */

View File

@ -379,38 +379,62 @@ void EventHandler::poll(uInt64 time)
break; break;
case KBDK_1: // Alt-1 turns off NTSC filtering case KBDK_1: // Alt-1 turns off NTSC filtering
myOSystem->console().toggleNTSC(NTSCFilter::PRESET_OFF, true); myOSystem->frameBuffer().setNTSC(NTSCFilter::PRESET_OFF);
break; break;
case KBDK_2: // Alt-2 turns on 'composite' NTSC filtering case KBDK_2: // Alt-2 turns on 'composite' NTSC filtering
myOSystem->console().toggleNTSC(NTSCFilter::PRESET_COMPOSITE, true); myOSystem->frameBuffer().setNTSC(NTSCFilter::PRESET_COMPOSITE);
break; break;
case KBDK_3: // Alt-3 turns on 'svideo' NTSC filtering case KBDK_3: // Alt-3 turns on 'svideo' NTSC filtering
myOSystem->console().toggleNTSC(NTSCFilter::PRESET_SVIDEO, true); myOSystem->frameBuffer().setNTSC(NTSCFilter::PRESET_SVIDEO);
break; break;
case KBDK_4: // Alt-4 turns on 'rgb' NTSC filtering case KBDK_4: // Alt-4 turns on 'rgb' NTSC filtering
myOSystem->console().toggleNTSC(NTSCFilter::PRESET_RGB, true); myOSystem->frameBuffer().setNTSC(NTSCFilter::PRESET_RGB);
break; break;
case KBDK_5: // Alt-5 turns on 'bad' NTSC filtering case KBDK_5: // Alt-5 turns on 'bad' NTSC filtering
myOSystem->console().toggleNTSC(NTSCFilter::PRESET_BAD, true); myOSystem->frameBuffer().setNTSC(NTSCFilter::PRESET_BAD);
break; break;
case KBDK_6: // Alt-6 turns on 'custom' NTSC filtering case KBDK_6: // Alt-6 turns on 'custom' NTSC filtering
myOSystem->console().toggleNTSC(NTSCFilter::PRESET_CUSTOM, true); myOSystem->frameBuffer().setNTSC(NTSCFilter::PRESET_CUSTOM);
break; break;
case KBDK_7: // Alt-7 changes scanline intensity for NTSC filtering case KBDK_7: // Alt-7 changes scanline intensity for NTSC filtering
if(mod & KMOD_SHIFT) if(mod & KMOD_SHIFT)
myOSystem->console().changeScanlines(-5, true); myOSystem->frameBuffer().setScanlineIntensity(-5);
else else
myOSystem->console().changeScanlines(+5, true); myOSystem->frameBuffer().setScanlineIntensity(+5);
break; break;
case KBDK_8: // Alt-8 turns toggles scanline interpolation case KBDK_8: // Alt-8 turns toggles scanline interpolation
myOSystem->console().toggleScanlineInterpolation(); myOSystem->frameBuffer().toggleScanlineInterpolation();
break;
case KBDK_9: // Alt-9 selects various custom adjustables for NTSC filtering
if(myOSystem->frameBuffer().ntscEnabled())
{
if(mod & KMOD_SHIFT)
myOSystem->frameBuffer().showMessage(
myOSystem->frameBuffer().ntsc().setPreviousAdjustable());
else
myOSystem->frameBuffer().showMessage(
myOSystem->frameBuffer().ntsc().setNextAdjustable());
}
break;
case KBDK_0: // Alt-0 changes custom adjustables for NTSC filtering
if(myOSystem->frameBuffer().ntscEnabled())
{
if(mod & KMOD_SHIFT)
myOSystem->frameBuffer().showMessage(
myOSystem->frameBuffer().ntsc().decreaseAdjustable());
else
myOSystem->frameBuffer().showMessage(
myOSystem->frameBuffer().ntsc().increaseAdjustable());
}
break; break;
case KBDK_z: case KBDK_z:
@ -471,7 +495,7 @@ void EventHandler::poll(uInt64 time)
break; break;
case KBDK_p: // Alt-p toggles phosphor effect case KBDK_p: // Alt-p toggles phosphor effect
// Currently, phosphor mode cannot be enabled with NTSC filtering // FIXME - Currently, phosphor mode cannot be enabled with NTSC filtering
if(!myOSystem->frameBuffer().ntscEnabled()) if(!myOSystem->frameBuffer().ntscEnabled())
myOSystem->console().togglePhosphor(); myOSystem->console().togglePhosphor();
break; break;

View File

@ -517,6 +517,74 @@ void FrameBuffer::refresh()
} }
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::setNTSC(NTSCFilter::Preset preset, bool show)
{
ostringstream buf;
if(type() == kDoubleBuffer)
{
if(preset == NTSCFilter::PRESET_OFF)
{
enableNTSC(false);
buf << "TV filtering disabled";
}
else
{
enableNTSC(true);
const string& mode = myNTSCFilter.setPreset(preset);
buf << "TV filtering (" << mode << " mode)";
}
myOSystem->settings().setInt("tv_filter", (int)preset);
}
else
buf << "TV filtering not available in software mode";
if(show) showMessage(buf.str());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::setScanlineIntensity(int amount)
{
ostringstream buf;
if(type() == kDoubleBuffer)
{
if(ntscEnabled())
{
uInt32 intensity = enableScanlines(amount);
buf << "Scanline intensity at " << intensity << "%";
myOSystem->settings().setInt("tv_scanlines", intensity);
}
else
buf << "Scanlines only available in TV filtering mode";
}
else
buf << "Scanlines not available in software mode";
showMessage(buf.str());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::toggleScanlineInterpolation()
{
ostringstream buf;
if(type() == kDoubleBuffer)
{
if(ntscEnabled())
{
bool enable = !myOSystem->settings().getBool("tv_scaninter");
enableScanlineInterpolation(enable);
buf << "Scanline interpolation " << (enable ? "enabled" : "disabled");
myOSystem->settings().setBool("tv_scaninter", enable);
}
else
buf << "Scanlines only available in TV filtering mode";
}
else
buf << "Scanlines not available in software mode";
showMessage(buf.str());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int FrameBuffer::allocateSurface(int w, int h, bool useBase) int FrameBuffer::allocateSurface(int w, int h, bool useBase)
{ {

View File

@ -290,6 +290,20 @@ class FrameBuffer
*/ */
NTSCFilter& ntsc() { return myNTSCFilter; } NTSCFilter& ntsc() { return myNTSCFilter; }
/**
Use NTSC filtering effects specified by the given preset.
*/
void setNTSC(NTSCFilter::Preset preset, bool show = true);
/**
Increase/decrease current scanline intensity by given relative amount.
*/
void setScanlineIntensity(int relative);
/**
Toggles interpolation/smoothing of scanlines in TV modes.
*/
void toggleScanlineInterpolation();
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// The following methods are system-specific and *may* be implemented // The following methods are system-specific and *may* be implemented
@ -302,18 +316,15 @@ class FrameBuffer
virtual void enableNTSC(bool enable) { } virtual void enableNTSC(bool enable) { }
virtual bool ntscEnabled() const { return false; } virtual bool ntscEnabled() const { return false; }
private:
/** /**
Change scanline intensity and interpolation. Change scanline intensity and interpolation.
relative = -1 means decrease current intensity by 'directin
direction = 0 means to reload the current video mode
direction = +1 means go to the next higher video mode
@param relative If non-zero, change current intensity by @param relative If non-zero, change current intensity by
'relative' amount, otherwise set to 'absolute' 'relative' amount, otherwise set to 'absolute'
@return New current intensity @return New current intensity
*/ */
virtual uInt32 changeScanlines(int relative, int absolute = 50) { return absolute; } virtual uInt32 enableScanlines(int relative, int absolute = 50) { return absolute; }
virtual void enableScanlineInterpolation(bool enable) { } virtual void enableScanlineInterpolation(bool enable) { }
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////