The default phosphor blend level can now be set globally (fixes #144).

Added new 'tv.phosphor' commandline argument to accomplish the above,
and associated UI item in Video Settings.

Updated docs for 'tv.phosphor' and 'tia.debugcolors'.  More work is
needed on this, since I need to add screenshots for this new functionality.
This commit is contained in:
Stephen Anthony 2017-07-09 22:36:50 -02:30
parent aa5be284cb
commit d613173cd7
9 changed files with 129 additions and 48 deletions

View File

@ -24,11 +24,13 @@
choice of 'red', 'orange', 'yellow', 'green', 'blue' and 'purple'.
This is accessible through the new 'tia.dbgcolors' commandline
argument.
- ...
- The defaul
* Implemented new phosphor emulation mode, which is much closer to real
TV output. Special thanks to Thomas Jentzsch for the idea and
implementation.
TV output. Related to this, added ability to change the default
phosphor blend level in the UI and through the new 'tv.phosphor'
commandline argument. Special thanks to Thomas Jentzsch for the idea
and implementation.
* Much improved RIOT timer emulation never before seen in any emulator.
Special thanks to DirtyHairy for the implementation, and alex_79 for

View File

@ -1865,6 +1865,23 @@
(vs. an integral stretch which won't necessarily completely fill the screen).</td>
</tr>
<tr>
<td><pre>-tia.debugcolors &lt;ROYGBP&gt;</pre></td>
<td>Assigns the colours (R)ed, (O)range, (Y)ellow, (G)reen, (B)lue and (P)urple
to each graphical register P0/M0/P1/M1/PF/BL, respectively. Currently,
these change be changed around to apply different colours to the
respective register.
</td>
</tr>
<tr>
<td><pre>-tv.phosphor &lt;0 - 100&gt;</pre></td>
<td>Enable default phosphor blending level; 0 implies no mixing, and 100
is full mixing (not recommended). Note that this doesn't actually
enable phosphor mode; that is done for each ROM in the ROM properties.
</td>
</tr>
<tr>
<td><pre>-tv.jitter &lt;1|0&gt;</pre></td>
<td>Enable TV jitter/roll effect, when there are too many or too few scanlines

View File

@ -103,6 +103,10 @@ void EventHandler::initialize()
// Integer to string conversions (for HEX) use upper or lower-case
Common::Base::setHexUppercase(myOSystem.settings().getBool("dbg.uhex"));
// Default phosphor blend
Properties::setDefault(Display_PPBlend,
myOSystem.settings().getString("tv.phosphor"));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -63,13 +63,11 @@ void Properties::set(PropertyType key, const string& value)
break;
}
case Display_PPBlend: // FIXME - handle global default
case Display_PPBlend:
{
int blend = atoi(myProperties[key].c_str());
if(blend < 1 || blend > 100) blend = 50;
ostringstream buf;
buf << blend;
myProperties[key] = buf.str();
if(blend < 1 || blend > 100)
myProperties[key] = ourDefaultProperties[key];
break;
}
@ -222,6 +220,12 @@ Properties& Properties::operator=(const Properties& properties)
return *this;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Properties::setDefault(PropertyType key, const string& value)
{
ourDefaultProperties[key] = value;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Properties::copy(const Properties& properties)
{
@ -261,15 +265,8 @@ void Properties::print() const
void Properties::setDefaults()
{
for(int i = 0; i < LastPropType; ++i)
{
if(i == Display_PPBlend) // special case, handle global default
{
myProperties[i] = "50"; // FIXME - for now, just use 50
}
else
myProperties[i] = ourDefaultProperties[i];
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PropertyType Properties::getPropertyType(const string& name)
@ -310,7 +307,7 @@ void Properties::printHeader()
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const char* const Properties::ourDefaultProperties[LastPropType] = {
string Properties::ourDefaultProperties[LastPropType] = {
"", // Cartridge.MD5
"", // Cartridge.Manufacturer
"", // Cartridge.ModelNo

View File

@ -136,6 +136,14 @@ class Properties
*/
Properties& operator = (const Properties& properties);
/**
Set the default value associated with key to the given value.
@param key The key of the property to set
@param value The value to assign to the property
*/
static void setDefault(PropertyType key, const string& value);
private:
/**
Helper function to perform a deep copy of the specified
@ -183,7 +191,7 @@ class Properties
string myProperties[LastPropType];
// List of default properties to use when none have been provided
static const char* const ourDefaultProperties[LastPropType];
static string ourDefaultProperties[LastPropType];
// The text strings associated with each property type
static const char* const ourPropertyNames[LastPropType];

View File

@ -55,10 +55,11 @@ Settings::Settings(OSystem& osystem)
// TV filtering options
setInternal("tv.filter", "0");
setInternal("tv.scanlines", "25");
setInternal("tv.scaninter", "true");
setInternal("tv.phosphor", "50");
setInternal("tv.jitter", "false");
setInternal("tv.jitter_recovery", "10");
setInternal("tv.scanlines", "25");
setInternal("tv.scaninter", "true");
// TV options when using 'custom' mode
setInternal("tv.contrast", "0.0");
setInternal("tv.brightness", "0.0");
@ -278,6 +279,9 @@ void Settings::validate()
sort(s.begin(), s.end());
if(s != "bgopry") setInternal("tia.dbgcolors", "roygpb");
i = getInt("tv.phosphor");
if(i < 0 || i > 100) setInternal("tv.phosphor", "50");
i = getInt("tv.filter");
if(i < 0 || i > 5) setInternal("tv.filter", "0");
@ -373,12 +377,14 @@ void Settings::usage() const
<< " -tia.aspectn <number> Scale TIA width by the given percentage in NTSC mode\n"
<< " -tia.aspectp <number> Scale TIA width by the given percentage in PAL mode\n"
<< " -tia.fsfill <1|0> Stretch TIA image to fill fullscreen mode\n"
<< " -tia.dbgcolors <string> Debug colors to use for each object (see manual for description)\n"
<< endl
<< " -tv.filter <0-5> Set TV effects off (0) or to specified mode (1-5)\n"
<< " -tv.scanlines <0-100> Set scanline intensity to percentage (0 disables completely)\n"
<< " -tv.scaninter <1|0> Enable interpolated (smooth) scanlines\n"
<< " -tv.phosphor <0-100> Set default blend level in phosphor mode\n"
<< " -tv.jitter <1|0> Enable TV jitter effect\n"
<< " -tv.jitter_recovery <1-20> Set recovery time for TV jitter effect\n"
<< " -tv.scanlines <0-100> Set scanline intensity to percentage (0 disables completely)\n"
<< " -tv.scaninter <1|0> Enable interpolated (smooth) scanlines\n"
<< " -tv.contrast <value> Set TV effects custom contrast to value 1.0 - 1.0\n"
<< " -tv.brightness <value> Set TV effects custom brightness to value 1.0 - 1.0\n"
<< " -tv.hue <value> Set TV effects custom hue to value 1.0 - 1.0\n"

View File

@ -361,7 +361,7 @@ GameInfoDialog::GameInfoDialog(
myPPBlendLabel = new StaticTextWidget(myTab, font,
xpos + lwidth + myPhosphor->getWidth() + 10 +
myPPBlend->getWidth() + 4, ypos+1,
3*fontWidth, fontHeight, "", kTextAlignLeft);
5*fontWidth, fontHeight, "", kTextAlignLeft);
myPPBlendLabel->setFlags(WIDGET_CLEARBG);
// Add items for tab 3
@ -490,7 +490,7 @@ void GameInfoDialog::loadView()
const string& blend = myGameProperties.get(Display_PPBlend);
myPPBlend->setValue(atoi(blend.c_str()));
myPPBlendLabel->setLabel(blend);
myPPBlendLabel->setLabel(blend == "0" ? "Auto" : blend);
myTab->loadConfig();
}
@ -539,7 +539,8 @@ void GameInfoDialog::saveConfig()
myGameProperties.set(Display_Height, myHeightLabel->getLabel() == "Auto" ? "0" :
myHeightLabel->getLabel());
myGameProperties.set(Display_Phosphor, myPhosphor->getSelectedTag().toString());
myGameProperties.set(Display_PPBlend, myPPBlendLabel->getLabel());
myGameProperties.set(Display_PPBlend, myPPBlendLabel->getLabel() == "Auto" ? "0" :
myPPBlendLabel->getLabel());
// Determine whether to add or remove an entry from the properties set
if(myDefaultsSelected)
@ -612,6 +613,9 @@ void GameInfoDialog::handleCommand(CommandSender* sender, int cmd,
break;
case kPPBlendChanged:
if(myPPBlend->getValue() == 0)
myPPBlendLabel->setLabel("Auto");
else
myPPBlendLabel->setValue(myPPBlend->getValue());
break;

View File

@ -52,7 +52,7 @@ VideoDialog::VideoDialog(OSystem& osystem, DialogContainer& parent,
// Set real dimensions
_w = std::min(52 * fontWidth + 10, max_w);
_h = std::min(14 * (lineHeight + 4) + 10, max_h);
_h = std::min(16 * (lineHeight + 4) + 10, max_h);
// The tab widget
xpos = ypos = 5;
@ -244,18 +244,33 @@ VideoDialog::VideoDialog(OSystem& osystem, DialogContainer& parent,
xpos += myTVContrast->getWidth() + myTVContrastLabel->getWidth() + 20;
ypos = 8;
// TV jitter effect
myTVJitter = new CheckboxWidget(myTab, font, xpos, ypos,
"Jitter/Roll effect", kTVJitterChanged);
wid.push_back(myTVJitter);
ypos += lineHeight;
lwidth = font.getStringWidth("Intensity ");
pwidth = font.getMaxCharWidth() * 6;
// TV Phosphor effect
myTVPhosLabel = new StaticTextWidget(myTab, font, xpos, ypos,
font.getStringWidth("Phosphor Effect"), fontHeight,
"Phosphor Effect", kTextAlignLeft);
ypos += lineHeight;
// TV Phosphor default level
xpos += 20;
CREATE_CUSTOM_SLIDERS(PhosLevel, "Default ");
ypos += 4;
// TV jitter effect
xpos -= 20;
myTVJitter = new CheckboxWidget(myTab, font, xpos, ypos,
"Jitter/Roll Effect", kTVJitterChanged);
wid.push_back(myTVJitter);
xpos += 20;
ypos += lineHeight;
CREATE_CUSTOM_SLIDERS(JitterRec, "Recovery ");
myTVJitterRec->setMinValue(1); myTVJitterRec->setMaxValue(20);
ypos += 4;
// Scanline intensity and interpolation
xpos -= 20;
myTVScanLabel =
new StaticTextWidget(myTab, font, xpos, ypos, font.getStringWidth("Scanline settings"),
fontHeight, "Scanline settings", kTextAlignLeft);
@ -289,6 +304,13 @@ VideoDialog::VideoDialog(OSystem& osystem, DialogContainer& parent,
// Add items for tab 2
addToFocusList(wid, myTab, tabID);
//////////////////////////////////////////////////////////
// 3) TIA debug colours
wid.clear();
tabID = myTab->addTab(" Debug Colors ");
xpos = ypos = 8;
// Activate the first tab
myTab->setActiveTab(0);
@ -376,6 +398,10 @@ void VideoDialog::loadConfig()
// TV Custom adjustables
loadTVAdjustables(NTSCFilter::PRESET_CUSTOM);
// TV phosphor blend
myTVPhosLevel->setValue(instance().settings().getInt("tv.phosphor"));
myTVPhosLevelLabel->setLabel(instance().settings().getString("tv.phosphor"));
// TV jitter
myTVJitterRec->setValue(instance().settings().getInt("tv.jitter_recovery"));
myTVJitterRecLabel->setLabel(instance().settings().getString("tv.jitter_recovery"));
@ -467,6 +493,10 @@ void VideoDialog::saveConfig()
adj.bleed = myTVBleed->getValue();
instance().frameBuffer().tiaSurface().ntsc().setCustomAdjustables(adj);
// TV phosphor blend
instance().settings().setValue("tv.phosphor", myTVPhosLevelLabel->getLabel());
Properties::setDefault(Display_PPBlend, myTVPhosLevelLabel->getLabel());
// TV jitter
instance().settings().setValue("tv.jitter", myTVJitter->getState());
instance().settings().setValue("tv.jitter_recovery", myTVJitterRecLabel->getLabel());
@ -517,6 +547,15 @@ void VideoDialog::setDefaults()
{
myTVMode->setSelected("0", "0");
// TV phosphor blend
myTVPhosLevel->setValue(50);
myTVPhosLevelLabel->setLabel("50");
// TV jitter
myTVJitterRec->setValue(10);
myTVJitterRecLabel->setLabel("10");
handleTVJitterChange(false);
// TV scanline intensity and interpolation
myTVScanIntense->setValue(25);
myTVScanIntenseLabel->setLabel("25");
@ -525,11 +564,6 @@ void VideoDialog::setDefaults()
// Make sure that mutually-exclusive items are not enabled at the same time
handleTVModeChange(NTSCFilter::PRESET_OFF);
loadTVAdjustables(NTSCFilter::PRESET_CUSTOM);
// TV jitter
myTVJitterRec->setValue(10);
myTVJitterRecLabel->setLabel("10");
handleTVJitterChange(false);
break;
}
}
@ -666,12 +700,14 @@ void VideoDialog::handleCommand(CommandSender* sender, int cmd,
break;
case kTVGammaChanged: myTVGammaLabel->setValue(myTVGamma->getValue());
break;
case kTVScanIntenseChanged: myTVScanIntenseLabel->setValue(myTVScanIntense->getValue());
case kTVPhosLevelChanged: myTVPhosLevelLabel->setValue(myTVPhosLevel->getValue());
break;
case kTVJitterChanged: handleTVJitterChange(myTVJitter->getState());
break;
case kTVJitterRecChanged: myTVJitterRecLabel->setValue(myTVJitterRec->getValue());
break;
case kTVScanIntenseChanged: myTVScanIntenseLabel->setValue(myTVScanIntense->getValue());
break;
case kCloneCompositeCmd: loadTVAdjustables(NTSCFilter::PRESET_COMPOSITE);
break;
case kCloneSvideoCmd: loadTVAdjustables(NTSCFilter::PRESET_SVIDEO);

View File

@ -95,6 +95,16 @@ class VideoDialog : public Dialog
SliderWidget* myTVGamma;
StaticTextWidget* myTVGammaLabel;
// TV jitter effects
CheckboxWidget* myTVJitter;
SliderWidget* myTVJitterRec;
StaticTextWidget* myTVJitterRecLabel;
// TV phosphor effect
StaticTextWidget* myTVPhosLabel;
SliderWidget* myTVPhosLevel;
StaticTextWidget* myTVPhosLevelLabel;
// TV scanline intensity and interpolation
StaticTextWidget* myTVScanLabel;
SliderWidget* myTVScanIntense;
@ -108,11 +118,6 @@ class VideoDialog : public Dialog
ButtonWidget* myCloneBad;
ButtonWidget* myCloneCustom;
// TV jitter effects
CheckboxWidget* myTVJitter;
SliderWidget* myTVJitterRec;
StaticTextWidget* myTVJitterRecLabel;
enum {
kNAspectRatioChanged = 'VDan',
kPAspectRatioChanged = 'VDap',
@ -134,6 +139,8 @@ class VideoDialog : public Dialog
kTVJitterChanged = 'TVjt',
kTVJitterRecChanged = 'TVjr',
kTVPhosLevelChanged = 'TVpl',
kCloneCompositeCmd = 'CLcp',
kCloneSvideoCmd = 'CLsv',
kCloneRGBCmd = 'CLrb',