diff --git a/Changes.txt b/Changes.txt index a3f595894..38b0e0106 100644 --- a/Changes.txt +++ b/Changes.txt @@ -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 diff --git a/docs/index.html b/docs/index.html index 059a2defe..4303154a7 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1865,6 +1865,23 @@ (vs. an integral stretch which won't necessarily completely fill the screen). + +
-tia.debugcolors <ROYGBP>
+ 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. + + + + +
-tv.phosphor <0 - 100>
+ 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. + + +
-tv.jitter <1|0>
Enable TV jitter/roll effect, when there are too many or too few scanlines diff --git a/src/emucore/EventHandler.cxx b/src/emucore/EventHandler.cxx index a83bcb49f..dcf8624f3 100644 --- a/src/emucore/EventHandler.cxx +++ b/src/emucore/EventHandler.cxx @@ -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")); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/emucore/Props.cxx b/src/emucore/Props.cxx index 59b24b3e3..a9bba8039 100644 --- a/src/emucore/Props.cxx +++ b/src/emucore/Props.cxx @@ -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,14 +265,7 @@ 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]; - } + myProperties[i] = ourDefaultProperties[i]; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -310,7 +307,7 @@ void Properties::printHeader() } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const char* const Properties::ourDefaultProperties[LastPropType] = { +string Properties::ourDefaultProperties[LastPropType] = { "", // Cartridge.MD5 "", // Cartridge.Manufacturer "", // Cartridge.ModelNo diff --git a/src/emucore/Props.hxx b/src/emucore/Props.hxx index 272005a8b..a1b1ab108 100644 --- a/src/emucore/Props.hxx +++ b/src/emucore/Props.hxx @@ -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]; diff --git a/src/emucore/Settings.cxx b/src/emucore/Settings.cxx index 84908a796..2a8d1e5bd 100644 --- a/src/emucore/Settings.cxx +++ b/src/emucore/Settings.cxx @@ -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"); @@ -368,17 +372,19 @@ void Settings::usage() const << " -volume Set the volume (0 - 100)\n" << endl #endif - << " -tia.zoom Use the specified zoom level (windowed mode) for TIA image\n" - << " -tia.inter <1|0> Enable interpolated (smooth) scaling for TIA image\n" - << " -tia.aspectn Scale TIA width by the given percentage in NTSC mode\n" - << " -tia.aspectp Scale TIA width by the given percentage in PAL mode\n" - << " -tia.fsfill <1|0> Stretch TIA image to fill fullscreen mode\n" + << " -tia.zoom Use the specified zoom level (windowed mode) for TIA image\n" + << " -tia.inter <1|0> Enable interpolated (smooth) scaling for TIA image\n" + << " -tia.aspectn Scale TIA width by the given percentage in NTSC mode\n" + << " -tia.aspectp 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 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 Set TV effects custom contrast to value 1.0 - 1.0\n" << " -tv.brightness Set TV effects custom brightness to value 1.0 - 1.0\n" << " -tv.hue Set TV effects custom hue to value 1.0 - 1.0\n" diff --git a/src/gui/GameInfoDialog.cxx b/src/gui/GameInfoDialog.cxx index 30717911d..57f9beaf8 100644 --- a/src/gui/GameInfoDialog.cxx +++ b/src/gui/GameInfoDialog.cxx @@ -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,7 +613,10 @@ void GameInfoDialog::handleCommand(CommandSender* sender, int cmd, break; case kPPBlendChanged: - myPPBlendLabel->setValue(myPPBlend->getValue()); + if(myPPBlend->getValue() == 0) + myPPBlendLabel->setLabel("Auto"); + else + myPPBlendLabel->setValue(myPPBlend->getValue()); break; case kMRangeChanged: diff --git a/src/gui/VideoDialog.cxx b/src/gui/VideoDialog.cxx index 58ee2215f..e3c6808df 100644 --- a/src/gui/VideoDialog.cxx +++ b/src/gui/VideoDialog.cxx @@ -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); diff --git a/src/gui/VideoDialog.hxx b/src/gui/VideoDialog.hxx index af3b128fe..28a168051 100644 --- a/src/gui/VideoDialog.hxx +++ b/src/gui/VideoDialog.hxx @@ -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',