diff --git a/Changes.txt b/Changes.txt
index f0c1b4acc..557157f25 100644
--- a/Changes.txt
+++ b/Changes.txt
@@ -14,26 +14,39 @@
6.1.2 to 6.2: (??? ??, 2020)
- * Added that paddle centering and sensitivity can be adjusted (TODO: Doc)
-
- * Added that Driving controller sensitivity can be adjusted (TODO: Doc)
-
* Added high scores: Score addresses, game variation etc. can be defined for
a game. This allows the user to save high scores for these games. For each
game and variation, the top 10 scores can be saved. (TODO: Doc)
+ * Added interactive palette to Video & Audio settings.
+
* Added 'Custom' palette, generated from user controlled phase shifts.
+ * Added that adjustable audio & video settings are displayed as gauge bars
+
+ * Added four global hotkeys which allow selecting and changing numerous
+ audio & video settings without having to remember the dedicated hotkeys
+
* Added 'Turbo' mode, runs the game as fast as the computer allows.
+ * Added that paddle centering (per ROM) and sensitivity can be adjusted
+
+ * Added that mouse sensitivity for Driving controller can be adjusted
+
* Added selectable dialog fonts
* Added separate positioning of launcher, emulator and debugger
* Added option which lets default ROM path follow launcher navigation
+ * Added debugger 'saveaccess' function, which saves memory access counts to
+ a CSV file.
+
* Added displaying last write address in the debugger.
+ * Added debugger pseudo-register '_scanend', which gives the number of
+ scanlines at the end of the last frame.
+
* Added detection of color and audio data in DiStella.
* Restored 'cfg' directory for Distella config files.
@@ -42,9 +55,6 @@
* Removed unused CV+ and DASH bank switching types.
- * Added debugger pseudo-register '_scanend', which gives the number of
- scanlines at the end of the last frame.
-
-Have fun!
diff --git a/docs/debugger.html b/docs/debugger.html
index 91e71bd47..423a20aa1 100644
--- a/docs/debugger.html
+++ b/docs/debugger.html
@@ -978,6 +978,7 @@ clearsavestateifs - Clear all savestate points
runtopc - Run until PC is set to value xx
s - Set Stack Pointer to value xx
save - Save breaks, watches, traps and functions to file xx
+ saveaccess - Save access counters to CSV file
saveconfig - Save Distella config file (with default name)
savedis - Save Distella disassembly (with default name)
saverom - Save (possibly patched) ROM (with default name)
diff --git a/docs/graphics/eventmapping.png b/docs/graphics/eventmapping.png
index 86deacd4a..f9b089b6d 100644
Binary files a/docs/graphics/eventmapping.png and b/docs/graphics/eventmapping.png differ
diff --git a/docs/graphics/eventmapping_devsports.png b/docs/graphics/eventmapping_devsports.png
index d66197a72..ab187595e 100644
Binary files a/docs/graphics/eventmapping_devsports.png and b/docs/graphics/eventmapping_devsports.png differ
diff --git a/docs/graphics/eventmapping_mouse.png b/docs/graphics/eventmapping_mouse.png
new file mode 100644
index 000000000..daac75b09
Binary files /dev/null and b/docs/graphics/eventmapping_mouse.png differ
diff --git a/docs/graphics/eventmapping_remap.png b/docs/graphics/eventmapping_remap.png
index a2e3ce949..34df62937 100644
Binary files a/docs/graphics/eventmapping_remap.png and b/docs/graphics/eventmapping_remap.png differ
diff --git a/docs/graphics/options.png b/docs/graphics/options.png
index db86da3fb..9f8a95430 100644
Binary files a/docs/graphics/options.png and b/docs/graphics/options.png differ
diff --git a/docs/graphics/options_audio.png b/docs/graphics/options_audio.png
index e77d69a5e..f37f07c6f 100644
Binary files a/docs/graphics/options_audio.png and b/docs/graphics/options_audio.png differ
diff --git a/docs/graphics/options_developer_timemachine.png b/docs/graphics/options_developer_timemachine.png
index ddb58f28e..498f83c0f 100644
Binary files a/docs/graphics/options_developer_timemachine.png and b/docs/graphics/options_developer_timemachine.png differ
diff --git a/docs/graphics/options_emulation.png b/docs/graphics/options_emulation.png
new file mode 100644
index 000000000..99a1dfa4d
Binary files /dev/null and b/docs/graphics/options_emulation.png differ
diff --git a/docs/graphics/options_gameinfo_controller.png b/docs/graphics/options_gameinfo_controller.png
index 9b9413ab2..04cc025db 100644
Binary files a/docs/graphics/options_gameinfo_controller.png and b/docs/graphics/options_gameinfo_controller.png differ
diff --git a/docs/graphics/options_misc.png b/docs/graphics/options_misc.png
index b1930b45d..1faa756b5 100644
Binary files a/docs/graphics/options_misc.png and b/docs/graphics/options_misc.png differ
diff --git a/docs/graphics/options_video.png b/docs/graphics/options_video.png
index be67fe065..deb857ca4 100644
Binary files a/docs/graphics/options_video.png and b/docs/graphics/options_video.png differ
diff --git a/docs/graphics/options_video_palettes.png b/docs/graphics/options_video_palettes.png
new file mode 100644
index 000000000..dae0cf7ee
Binary files /dev/null and b/docs/graphics/options_video_palettes.png differ
diff --git a/docs/graphics/options_video_tv.png b/docs/graphics/options_video_tv.png
index e76d32ba6..5ce3c3f2a 100644
Binary files a/docs/graphics/options_video_tv.png and b/docs/graphics/options_video_tv.png differ
diff --git a/docs/index.html b/docs/index.html
index 851aea9dc..3bf9ee26a 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -19,7 +19,7 @@
These keys allow selecting and changing audio & video settings without having to remember the
+ dedicated keys.
+
Controller.MouseAxis: |
Indicates how the mouse should emulate virtual controllers.
diff --git a/src/common/JoyMap.hxx b/src/common/JoyMap.hxx
index 6448de1ff..e3cc7ff7a 100644
--- a/src/common/JoyMap.hxx
+++ b/src/common/JoyMap.hxx
@@ -19,6 +19,7 @@
#define CONTROLLERMAP_HXX
#include
+
#include "Event.hxx"
#include "EventHandlerConstants.hxx"
diff --git a/src/common/KeyMap.hxx b/src/common/KeyMap.hxx
index 94d3b4242..0b7eff2fe 100644
--- a/src/common/KeyMap.hxx
+++ b/src/common/KeyMap.hxx
@@ -21,6 +21,7 @@
#include
#include "Event.hxx"
#include "EventHandlerConstants.hxx"
+#include "StellaKeys.hxx"
/**
This class handles keyboard mappings in Stella.
diff --git a/src/common/PKeyboardHandler.cxx b/src/common/PKeyboardHandler.cxx
index f32600345..cf4a31831 100644
--- a/src/common/PKeyboardHandler.cxx
+++ b/src/common/PKeyboardHandler.cxx
@@ -17,13 +17,7 @@
#include "OSystem.hxx"
#include "Console.hxx"
-#include "Settings.hxx"
#include "EventHandler.hxx"
-#include "Sound.hxx"
-#include "StateManager.hxx"
-#include "StellaKeys.hxx"
-#include "TIASurface.hxx"
-#include "PNGLibrary.hxx"
#include "PKeyboardHandler.hxx"
#ifdef DEBUGGER_SUPPORT
@@ -466,8 +460,8 @@ PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultCommo
{Event::VidmodeIncrease, KBDK_EQUALS, MOD3},
{Event::VCenterDecrease, KBDK_PAGEUP, MOD3},
{Event::VCenterIncrease, KBDK_PAGEDOWN, MOD3},
- {Event::ScanlineAdjustDecrease, KBDK_PAGEDOWN, KBDM_SHIFT | MOD3},
- {Event::ScanlineAdjustIncrease, KBDK_PAGEUP, KBDM_SHIFT | MOD3},
+ {Event::VSizeAdjustDecrease, KBDK_PAGEDOWN, KBDM_SHIFT | MOD3},
+ {Event::VSizeAdjustIncrease, KBDK_PAGEUP, KBDM_SHIFT | MOD3},
{Event::VolumeDecrease, KBDK_LEFTBRACKET, MOD3},
{Event::VolumeIncrease, KBDK_RIGHTBRACKET, MOD3},
{Event::SoundToggle, KBDK_RIGHTBRACKET, KBDM_CTRL},
@@ -475,30 +469,47 @@ PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultCommo
{Event::ToggleFullScreen, KBDK_RETURN, MOD3},
{Event::OverscanDecrease, KBDK_PAGEDOWN, KBDM_SHIFT},
{Event::OverscanIncrease, KBDK_PAGEUP, KBDM_SHIFT},
- {Event::VidmodeStd, KBDK_1, MOD3},
- {Event::VidmodeRGB, KBDK_2, MOD3},
- {Event::VidmodeSVideo, KBDK_3, MOD3},
- {Event::VidModeComposite, KBDK_4, MOD3},
- {Event::VidModeBad, KBDK_5, MOD3},
- {Event::VidModeCustom, KBDK_6, MOD3},
- {Event::PreviousAttribute, KBDK_7, KBDM_SHIFT | MOD3},
- {Event::NextAttribute, KBDK_7, MOD3},
- {Event::DecreaseAttribute, KBDK_8, KBDM_SHIFT | MOD3},
- {Event::IncreaseAttribute, KBDK_8, MOD3},
- {Event::PhosphorDecrease, KBDK_9, KBDM_SHIFT | MOD3},
- {Event::PhosphorIncrease, KBDK_9, MOD3},
+ //{Event::VidmodeStd, KBDK_1, MOD3},
+ //{Event::VidmodeRGB, KBDK_2, MOD3},
+ //{Event::VidmodeSVideo, KBDK_3, MOD3},
+ //{Event::VidModeComposite, KBDK_4, MOD3},
+ //{Event::VidModeBad, KBDK_5, MOD3},
+ //{Event::VidModeCustom, KBDK_6, MOD3},
+ {Event::PreviousVideoMode, KBDK_1, KBDM_SHIFT | MOD3},
+ {Event::NextVideoMode, KBDK_1, MOD3},
+ {Event::PreviousAttribute, KBDK_2, KBDM_SHIFT | MOD3},
+ {Event::NextAttribute, KBDK_2, MOD3},
+ {Event::DecreaseAttribute, KBDK_3, KBDM_SHIFT | MOD3},
+ {Event::IncreaseAttribute, KBDK_3, MOD3},
+ {Event::PhosphorDecrease, KBDK_4, KBDM_SHIFT | MOD3},
+ {Event::PhosphorIncrease, KBDK_4, MOD3},
{Event::TogglePhosphor, KBDK_P, MOD3},
- {Event::ScanlinesDecrease, KBDK_0, KBDM_SHIFT | MOD3},
- {Event::ScanlinesIncrease, KBDK_0, MOD3},
+ {Event::ScanlinesDecrease, KBDK_5, KBDM_SHIFT | MOD3},
+ {Event::ScanlinesIncrease, KBDK_5, MOD3},
+ {Event::PreviousPaletteAttribute, KBDK_9, KBDM_SHIFT | MOD3},
+ {Event::NextPaletteAttribute, KBDK_9, MOD3},
+ {Event::PaletteAttributeDecrease, KBDK_0, KBDM_SHIFT | MOD3},
+ {Event::PaletteAttributeIncrease, KBDK_0, MOD3},
{Event::ToggleColorLoss, KBDK_L, KBDM_CTRL},
- {Event::TogglePalette, KBDK_P, KBDM_CTRL},
- {Event::ColorShiftDecrease, KBDK_9, KBDM_SHIFT | KBDM_CTRL},
- {Event::ColorShiftIncrease, KBDK_9, KBDM_CTRL},
+ {Event::PaletteDecrease, KBDK_P, KBDM_SHIFT | KBDM_CTRL},
+ {Event::PaletteIncrease, KBDK_P, KBDM_CTRL},
+
+#ifndef BSPF_MACOS
+ {Event::PreviousSetting, KBDK_END},
+ {Event::NextSetting, KBDK_HOME},
+#else
+ {Event::PreviousSetting, KBDK_HOME},
+ {Event::NextSetting, KBDK_END},
+#endif
+ {Event::SettingDecrease, KBDK_PAGEDOWN},
+ {Event::SettingIncrease, KBDK_PAGEUP},
+
{Event::ToggleInter, KBDK_I, KBDM_CTRL},
{Event::ToggleTurbo, KBDK_T, KBDM_CTRL},
{Event::ToggleJitter, KBDK_J, MOD3},
{Event::ToggleFrameStats, KBDK_L, MOD3},
{Event::ToggleTimeMachine, KBDK_T, MOD3},
+
#ifdef PNG_SUPPORT
{Event::ToggleContSnapshots, KBDK_S, MOD3},
{Event::ToggleContSnapshotsFrame, KBDK_S, KBDM_SHIFT | MOD3},
diff --git a/src/common/PaletteHandler.cxx b/src/common/PaletteHandler.cxx
new file mode 100644
index 000000000..d2a2a7768
--- /dev/null
+++ b/src/common/PaletteHandler.cxx
@@ -0,0 +1,725 @@
+//============================================================================
+//
+// SSSS tt lll lll
+// SS SS tt ll ll
+// SS tttttt eeee ll ll aaaa
+// SSSS tt ee ee ll ll aa
+// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
+// SS SS tt ee ll ll aa aa
+// SSSS ttt eeeee llll llll aaaaa
+//
+// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony
+// and the Stella Team
+//
+// See the file "License.txt" for information on usage and redistribution of
+// this file, and for a DISCLAIMER OF ALL WARRANTIES.
+//============================================================================
+
+#include
+
+#include "Console.hxx"
+#include "FrameBuffer.hxx"
+
+#include "PaletteHandler.hxx"
+
+PaletteHandler::PaletteHandler(OSystem& system)
+ : myOSystem(system)
+{
+ // Load user-defined palette for this ROM
+ loadUserPalette();
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+PaletteHandler::PaletteType PaletteHandler::toPaletteType(const string& name) const
+{
+ if(name == SETTING_Z26)
+ return PaletteType::Z26;
+
+ if(name == SETTING_USER && myUserPaletteDefined)
+ return PaletteType::User;
+
+ if(name == SETTING_CUSTOM)
+ return PaletteType::Custom;
+
+ return PaletteType::Standard;
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+string PaletteHandler::toPaletteName(PaletteType type) const
+{
+ const string SETTING_NAMES[int(PaletteType::NumTypes)] = {
+ SETTING_STANDARD, SETTING_Z26, SETTING_USER, SETTING_CUSTOM
+ };
+
+ return SETTING_NAMES[type];
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void PaletteHandler::cyclePalette(int direction)
+{
+ const string MESSAGES[PaletteType::NumTypes] = {
+ "Standard Stella", "Z26", "User-defined", "Custom"
+ };
+ int type = toPaletteType(myOSystem.settings().getString("palette"));
+
+ do {
+ type = BSPF::clampw(type + direction, int(PaletteType::MinType), int(PaletteType::MaxType));
+ } while(type == PaletteType::User && !myUserPaletteDefined);
+
+ const string palette = toPaletteName(PaletteType(type));
+ const string message = MESSAGES[type] + " palette";
+
+ myOSystem.frameBuffer().showMessage(message);
+
+ setPalette(palette);
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void PaletteHandler::showAdjustableMessage()
+{
+ const bool isPhaseShift = myAdjustables[myCurrentAdjustable].value == nullptr;
+ ostringstream msg, buf;
+
+ msg << "Palette " << myAdjustables[myCurrentAdjustable].name;
+ if(isPhaseShift)
+ {
+ const ConsoleTiming timing = myOSystem.console().timing();
+ const bool isNTSC = timing == ConsoleTiming::ntsc;
+ const float value = myOSystem.console().timing() == ConsoleTiming::pal ? myPhasePAL : myPhaseNTSC;
+ buf << std::fixed << std::setprecision(1) << value << DEGREE;
+ myOSystem.frameBuffer().showMessage("Palette phase shift", buf.str(), value,
+ (isNTSC ? DEF_NTSC_SHIFT : DEF_PAL_SHIFT) - MAX_SHIFT,
+ (isNTSC ? DEF_NTSC_SHIFT : DEF_PAL_SHIFT) + MAX_SHIFT);
+ }
+ else
+ {
+ const int value = scaleTo100(*myAdjustables[myCurrentAdjustable].value);
+ buf << value << "%";
+ myOSystem.frameBuffer().showMessage(
+ msg.str(), buf.str(), value);
+ }
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void PaletteHandler::cycleAdjustable(int direction)
+{
+ const bool isCustomPalette = SETTING_CUSTOM == myOSystem.settings().getString("palette");
+ bool isPhaseShift;
+
+ do {
+ myCurrentAdjustable = BSPF::clampw(int(myCurrentAdjustable + direction), 0, NUM_ADJUSTABLES - 1);
+ isPhaseShift = myAdjustables[myCurrentAdjustable].value == nullptr;
+ // skip phase shift when 'Custom' palette is not selected
+ if(!direction && isPhaseShift && !isCustomPalette)
+ myCurrentAdjustable++;
+ } while(isPhaseShift && !isCustomPalette);
+
+ showAdjustableMessage();
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void PaletteHandler::changeAdjustable(int adjustable, int direction)
+{
+ const bool isCustomPalette = SETTING_CUSTOM == myOSystem.settings().getString("palette");
+ const bool isPhaseShift = myAdjustables[adjustable].value == nullptr;
+
+ myCurrentAdjustable = adjustable;
+ if(isPhaseShift && !isCustomPalette)
+ myCurrentAdjustable++;
+
+ changeCurrentAdjustable(direction);
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void PaletteHandler::changeCurrentAdjustable(int direction)
+{
+ if(myAdjustables[myCurrentAdjustable].value == nullptr)
+ changeColorPhaseShift(direction);
+ else
+ {
+ int newVal = scaleTo100(*myAdjustables[myCurrentAdjustable].value);
+
+ newVal = BSPF::clamp(newVal + direction * 2, 0, 100);
+
+ *myAdjustables[myCurrentAdjustable].value = scaleFrom100(newVal);
+
+ showAdjustableMessage();
+ setPalette();
+ }
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void PaletteHandler::changeColorPhaseShift(int direction)
+{
+ const ConsoleTiming timing = myOSystem.console().timing();
+
+ // SECAM is not supported
+ if(timing != ConsoleTiming::secam)
+ {
+ const bool isNTSC = timing == ConsoleTiming::ntsc;
+ const float shift = isNTSC ? DEF_NTSC_SHIFT : DEF_PAL_SHIFT;
+ float newPhase = isNTSC ? myPhaseNTSC : myPhasePAL;
+
+ newPhase = BSPF::clamp(newPhase + direction * 0.3F, shift - MAX_SHIFT, shift + MAX_SHIFT);
+
+ if(isNTSC)
+ myPhaseNTSC = newPhase;
+ else
+ myPhasePAL = newPhase;
+
+ generateCustomPalette(timing);
+ setPalette(SETTING_CUSTOM);
+
+ showAdjustableMessage();
+ }
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void PaletteHandler::loadConfig(const Settings& settings)
+{
+ // Load adjustables
+ myPhaseNTSC = BSPF::clamp(settings.getFloat("pal.phase_ntsc"),
+ DEF_NTSC_SHIFT - MAX_SHIFT, DEF_NTSC_SHIFT + MAX_SHIFT);
+ myPhasePAL = BSPF::clamp(settings.getFloat("pal.phase_pal"),
+ DEF_PAL_SHIFT - MAX_SHIFT, DEF_PAL_SHIFT + MAX_SHIFT);
+
+ myHue = BSPF::clamp(settings.getFloat("pal.hue"), -1.0F, 1.0F);
+ mySaturation = BSPF::clamp(settings.getFloat("pal.saturation"), -1.0F, 1.0F);
+ myContrast = BSPF::clamp(settings.getFloat("pal.contrast"), -1.0F, 1.0F);
+ myBrightness = BSPF::clamp(settings.getFloat("pal.brightness"), -1.0F, 1.0F);
+ myGamma = BSPF::clamp(settings.getFloat("pal.gamma"), -1.0F, 1.0F);
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void PaletteHandler::saveConfig(Settings& settings) const
+{
+ // Save adjustables
+ settings.setValue("pal.phase_ntsc", myPhaseNTSC);
+ settings.setValue("pal.phase_pal", myPhasePAL);
+
+ settings.setValue("pal.hue", myHue);
+ settings.setValue("pal.saturation", mySaturation);
+ settings.setValue("pal.contrast", myContrast);
+ settings.setValue("pal.brightness", myBrightness);
+ settings.setValue("pal.gamma", myGamma);
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void PaletteHandler::setAdjustables(const Adjustable& adjustable)
+{
+ myPhaseNTSC = adjustable.phaseNtsc / 10.F;
+ myPhasePAL = adjustable.phasePal / 10.F;
+
+ myHue = scaleFrom100(adjustable.hue);
+ mySaturation = scaleFrom100(adjustable.saturation);
+ myContrast = scaleFrom100(adjustable.contrast);
+ myBrightness = scaleFrom100(adjustable.brightness);
+ myGamma = scaleFrom100(adjustable.gamma);
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void PaletteHandler::getAdjustables(Adjustable& adjustable) const
+{
+ adjustable.phaseNtsc = myPhaseNTSC * 10.F;
+ adjustable.phasePal = myPhasePAL * 10.F;
+
+ adjustable.hue = scaleTo100(myHue);
+ adjustable.saturation = scaleTo100(mySaturation);
+ adjustable.contrast = scaleTo100(myContrast);
+ adjustable.brightness = scaleTo100(myBrightness);
+ adjustable.gamma = scaleTo100(myGamma);
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void PaletteHandler::setPalette(const string& name)
+{
+ myOSystem.settings().setValue("palette", name);
+
+ setPalette();
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void PaletteHandler::setPalette()
+{
+ if(myOSystem.hasConsole())
+ {
+ const string& name = myOSystem.settings().getString("palette");
+
+ // Look at all the palettes, since we don't know which one is
+ // currently active
+ static constexpr BSPF::array2D palettes = {{
+ { &ourNTSCPalette, &ourPALPalette, &ourSECAMPalette },
+ { &ourNTSCPaletteZ26, &ourPALPaletteZ26, &ourSECAMPaletteZ26 },
+ { &ourUserNTSCPalette, &ourUserPALPalette, &ourUserSECAMPalette },
+ { &ourCustomNTSCPalette, &ourCustomPALPalette, &ourSECAMPalette }
+ }};
+ // See which format we should be using
+ const ConsoleTiming timing = myOSystem.console().timing();
+ const PaletteType paletteType = toPaletteType(name);
+ // Now consider the current display format
+ const PaletteArray* palette = palettes[paletteType][int(timing)];
+
+ if(paletteType == PaletteType::Custom)
+ generateCustomPalette(timing);
+
+ myOSystem.frameBuffer().setTIAPalette(adjustedPalette(*palette));
+ }
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+PaletteArray PaletteHandler::adjustedPalette(const PaletteArray& palette)
+{
+ PaletteArray destPalette;
+ // Constants for saturation and gray scale calculation
+ constexpr float PR = .2989F;
+ constexpr float PG = .5870F;
+ constexpr float PB = .1140F;
+ // Generate adjust table
+ constexpr int ADJUST_SIZE = 256;
+ constexpr int RGB_UNIT = 1 << 8;
+ constexpr float RGB_OFFSET = 0.5F;
+ const float hue = myHue;
+ const float brightness = myBrightness * (0.5F * RGB_UNIT) + RGB_OFFSET;
+ const float contrast = myContrast * (0.5F * RGB_UNIT) + RGB_UNIT;
+ const float saturation = mySaturation + 1;
+ const float gamma = 1.1333F - myGamma * 0.5F;
+ /* match common PC's 2.2 gamma to TV's 2.65 gamma */
+ constexpr float toFloat = 1.F / (ADJUST_SIZE - 1);
+ std::array adjust;
+
+ for(int i = 0; i < ADJUST_SIZE; i++)
+ adjust[i] = powf(i * toFloat, gamma) * contrast + brightness;
+
+ // Transform original palette into destination palette
+ for(size_t i = 0; i < destPalette.size(); i += 2)
+ {
+ const uInt32 pixel = palette[i];
+ int r = (pixel >> 16) & 0xff;
+ int g = (pixel >> 8) & 0xff;
+ int b = (pixel >> 0) & 0xff;
+
+ // adjust hue (different for NTSC and PAL?) and saturation
+ adjustHueSaturation(r, g, b, hue, saturation);
+
+ // adjust contrast, brightness, gamma
+ r = adjust[r];
+ g = adjust[g];
+ b = adjust[b];
+
+ r = BSPF::clamp(r, 0, 255);
+ g = BSPF::clamp(g, 0, 255);
+ b = BSPF::clamp(b, 0, 255);
+
+ destPalette[i] = (r << 16) + (g << 8) + b;
+
+ // Fill the odd numbered palette entries with gray values (calculated
+ // using the standard RGB -> grayscale conversion formula)
+ // Used for PAL color-loss data and 'greying out' the frame in the debugger.
+ const uInt8 lum = static_cast((r * PR) + (g * PG) + (b * PB));
+
+ destPalette[i + 1] = (lum << 16) + (lum << 8) + lum;
+ }
+ return destPalette;
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void PaletteHandler::loadUserPalette()
+{
+ if (!myOSystem.checkUserPalette(true))
+ return;
+
+ const string& palette = myOSystem.paletteFile();
+ ifstream in(palette, std::ios::binary);
+
+ // Now that we have valid data, create the user-defined palettes
+ std::array pixbuf; // Temporary buffer for one 24-bit pixel
+
+ for(int i = 0; i < 128; i++) // NTSC palette
+ {
+ in.read(reinterpret_cast(pixbuf.data()), 3);
+ const uInt32 pixel = (int(pixbuf[0]) << 16) + (int(pixbuf[1]) << 8) + int(pixbuf[2]);
+ ourUserNTSCPalette[(i<<1)] = pixel;
+ }
+ for(int i = 0; i < 128; i++) // PAL palette
+ {
+ in.read(reinterpret_cast(pixbuf.data()), 3);
+ const uInt32 pixel = (int(pixbuf[0]) << 16) + (int(pixbuf[1]) << 8) + int(pixbuf[2]);
+ ourUserPALPalette[(i<<1)] = pixel;
+ }
+
+ std::array secam; // All 8 24-bit pixels, plus 8 colorloss pixels
+ for(int i = 0; i < 8; i++) // SECAM palette
+ {
+ in.read(reinterpret_cast(pixbuf.data()), 3);
+ const uInt32 pixel = (int(pixbuf[0]) << 16) + (int(pixbuf[1]) << 8) + int(pixbuf[2]);
+ secam[(i<<1)] = pixel;
+ secam[(i<<1)+1] = 0;
+ }
+ uInt32* ptr = ourUserSECAMPalette.data();
+ for(int i = 0; i < 16; ++i)
+ {
+ const uInt32* s = secam.data();
+ for(int j = 0; j < 16; ++j)
+ *ptr++ = *s++;
+ }
+
+ myUserPaletteDefined = true;
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void PaletteHandler::generateCustomPalette(ConsoleTiming timing)
+{
+ constexpr int NUM_CHROMA = 16;
+ constexpr int NUM_LUMA = 8;
+ constexpr float SATURATION = 0.25F; // default saturation
+
+ float color[NUM_CHROMA][2] = {{0.0F}};
+
+ if(timing == ConsoleTiming::ntsc)
+ {
+ // YIQ is YUV shifted by 33°
+ constexpr float offset = 33 * BSPF::PI_f / 180;
+ const float shift = myPhaseNTSC * BSPF::PI_f / 180;
+
+ // color 0 is grayscale
+ for(int chroma = 1; chroma < NUM_CHROMA; chroma++)
+ {
+ color[chroma][0] = SATURATION * sinf(offset + shift * (chroma - 1));
+ color[chroma][1] = SATURATION * sinf(offset + shift * (chroma - 1 - BSPF::PI_f));
+ }
+
+ for(int chroma = 0; chroma < NUM_CHROMA; chroma++)
+ {
+ const float I = color[chroma][0];
+ const float Q = color[chroma][1];
+
+ for(int luma = 0; luma < NUM_LUMA; luma++)
+ {
+ const float Y = 0.05F + luma / 8.24F; // 0.05..~0.90
+
+ float R = Y + 0.956F * I + 0.621F * Q;
+ float G = Y - 0.272F * I - 0.647F * Q;
+ float B = Y - 1.106F * I + 1.703F * Q;
+
+ if(R < 0) R = 0;
+ if(G < 0) G = 0;
+ if(B < 0) B = 0;
+
+ R = powf(R, 0.9F);
+ G = powf(G, 0.9F);
+ B = powf(B, 0.9F);
+
+ int r = BSPF::clamp(R * 255.F, 0.F, 255.F);
+ int g = BSPF::clamp(G * 255.F, 0.F, 255.F);
+ int b = BSPF::clamp(B * 255.F, 0.F, 255.F);
+
+ ourCustomNTSCPalette[(chroma * NUM_LUMA + luma) << 1] = (r << 16) + (g << 8) + b;
+ }
+ }
+ }
+ else if(timing == ConsoleTiming::pal)
+ {
+ constexpr float offset = BSPF::PI_f;
+ const float shift = myPhasePAL * BSPF::PI_f / 180;
+ constexpr float fixedShift = 22.5F * BSPF::PI_f / 180;
+
+ // colors 0, 1, 14 and 15 are grayscale
+ for(int chroma = 2; chroma < NUM_CHROMA - 2; chroma++)
+ {
+ int idx = NUM_CHROMA - 1 - chroma;
+ color[idx][0] = SATURATION * sinf(offset - fixedShift * chroma);
+ if ((idx & 1) == 0)
+ color[idx][1] = SATURATION * sinf(offset - shift * (chroma - 3.5F) / 2.F);
+ else
+ color[idx][1] = SATURATION * -sinf(offset - shift * chroma / 2.F);
+ }
+
+ for(int chroma = 0; chroma < NUM_CHROMA; chroma++)
+ {
+ const float U = color[chroma][0];
+ const float V = color[chroma][1];
+
+ for(int luma = 0; luma < NUM_LUMA; luma++)
+ {
+ const float Y = 0.05F + luma / 8.24F; // 0.05..~0.90
+
+ // Most sources
+ float R = Y + 1.403F * V;
+ float G = Y - 0.344F * U - 0.714F * V;
+ float B = Y + 1.770F * U;
+ // German Wikipedia, huh???
+ //float B = Y + 1 / 0.493 * U;
+ //float R = Y + 1 / 0.877 * V;
+ //float G = 1.704 * Y - 0.590 * R - 0.194 * B;
+
+ if(R < 0) R = 0.0;
+ if(G < 0) G = 0.0;
+ if(B < 0) B = 0.0;
+
+ R = powf(R, 1.2F);
+ G = powf(G, 1.2F);
+ B = powf(B, 1.2F);
+
+ int r = BSPF::clamp(R * 255.F, 0.F, 255.F);
+ int g = BSPF::clamp(G * 255.F, 0.F, 255.F);
+ int b = BSPF::clamp(B * 255.F, 0.F, 255.F);
+
+ ourCustomPALPalette[(chroma * NUM_LUMA + luma) << 1] = (r << 16) + (g << 8) + b;
+ }
+ }
+ }
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void PaletteHandler::adjustHueSaturation(int& R, int& G, int& B, float H, float S)
+{
+ // Adapted from http://beesbuzz.biz/code/16-hsv-color-transforms
+ // (C) J. “Fluffy” Shagam
+ // License: CC BY-SA 4.0
+ const float su = S * cosf(-H * BSPF::PI_f);
+ const float sw = S * sinf(-H * BSPF::PI_f);
+ const float r = (.299F + .701F * su + .168F * sw) * R
+ + (.587F - .587F * su + .330F * sw) * G
+ + (.114F - .114F * su - .497F * sw) * B;
+ const float g = (.299F - .299F * su - .328F * sw) * R
+ + (.587F + .413F * su + .035F * sw) * G
+ + (.114F - .114F * su + .292F * sw) * B;
+ const float b = (.299F - .300F * su + 1.25F * sw) * R
+ + (.587F - .588F * su - 1.05F * sw) * G
+ + (.114F + .886F * su - .203F * sw) * B;
+
+ R = BSPF::clamp(r, 0.F, 255.F);
+ G = BSPF::clamp(g, 0.F, 255.F);
+ B = BSPF::clamp(b, 0.F, 255.F);
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+const PaletteArray PaletteHandler::ourNTSCPalette = {
+ 0x000000, 0, 0x4a4a4a, 0, 0x6f6f6f, 0, 0x8e8e8e, 0,
+ 0xaaaaaa, 0, 0xc0c0c0, 0, 0xd6d6d6, 0, 0xececec, 0,
+ 0x484800, 0, 0x69690f, 0, 0x86861d, 0, 0xa2a22a, 0,
+ 0xbbbb35, 0, 0xd2d240, 0, 0xe8e84a, 0, 0xfcfc54, 0,
+ 0x7c2c00, 0, 0x904811, 0, 0xa26221, 0, 0xb47a30, 0,
+ 0xc3903d, 0, 0xd2a44a, 0, 0xdfb755, 0, 0xecc860, 0,
+ 0x901c00, 0, 0xa33915, 0, 0xb55328, 0, 0xc66c3a, 0,
+ 0xd5824a, 0, 0xe39759, 0, 0xf0aa67, 0, 0xfcbc74, 0,
+ 0x940000, 0, 0xa71a1a, 0, 0xb83232, 0, 0xc84848, 0,
+ 0xd65c5c, 0, 0xe46f6f, 0, 0xf08080, 0, 0xfc9090, 0,
+ 0x840064, 0, 0x97197a, 0, 0xa8308f, 0, 0xb846a2, 0,
+ 0xc659b3, 0, 0xd46cc3, 0, 0xe07cd2, 0, 0xec8ce0, 0,
+ 0x500084, 0, 0x68199a, 0, 0x7d30ad, 0, 0x9246c0, 0,
+ 0xa459d0, 0, 0xb56ce0, 0, 0xc57cee, 0, 0xd48cfc, 0,
+ 0x140090, 0, 0x331aa3, 0, 0x4e32b5, 0, 0x6848c6, 0,
+ 0x7f5cd5, 0, 0x956fe3, 0, 0xa980f0, 0, 0xbc90fc, 0,
+ 0x000094, 0, 0x181aa7, 0, 0x2d32b8, 0, 0x4248c8, 0,
+ 0x545cd6, 0, 0x656fe4, 0, 0x7580f0, 0, 0x8490fc, 0,
+ 0x001c88, 0, 0x183b9d, 0, 0x2d57b0, 0, 0x4272c2, 0,
+ 0x548ad2, 0, 0x65a0e1, 0, 0x75b5ef, 0, 0x84c8fc, 0,
+ 0x003064, 0, 0x185080, 0, 0x2d6d98, 0, 0x4288b0, 0,
+ 0x54a0c5, 0, 0x65b7d9, 0, 0x75cceb, 0, 0x84e0fc, 0,
+ 0x004030, 0, 0x18624e, 0, 0x2d8169, 0, 0x429e82, 0,
+ 0x54b899, 0, 0x65d1ae, 0, 0x75e7c2, 0, 0x84fcd4, 0,
+ 0x004400, 0, 0x1a661a, 0, 0x328432, 0, 0x48a048, 0,
+ 0x5cba5c, 0, 0x6fd26f, 0, 0x80e880, 0, 0x90fc90, 0,
+ 0x143c00, 0, 0x355f18, 0, 0x527e2d, 0, 0x6e9c42, 0,
+ 0x87b754, 0, 0x9ed065, 0, 0xb4e775, 0, 0xc8fc84, 0,
+ 0x303800, 0, 0x505916, 0, 0x6d762b, 0, 0x88923e, 0,
+ 0xa0ab4f, 0, 0xb7c25f, 0, 0xccd86e, 0, 0xe0ec7c, 0,
+ 0x482c00, 0, 0x694d14, 0, 0x866a26, 0, 0xa28638, 0,
+ 0xbb9f47, 0, 0xd2b656, 0, 0xe8cc63, 0, 0xfce070, 0
+};
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+const PaletteArray PaletteHandler::ourPALPalette = {
+ 0x000000, 0, 0x121212, 0, 0x242424, 0, 0x484848, 0, // 180 0
+ 0x6c6c6c, 0, 0x909090, 0, 0xb4b4b4, 0, 0xd8d8d8, 0, // was 0x111111..0xcccccc
+ 0x000000, 0, 0x121212, 0, 0x242424, 0, 0x484848, 0, // 198 1
+ 0x6c6c6c, 0, 0x909090, 0, 0xb4b4b4, 0, 0xd8d8d8, 0,
+ 0x1d0f00, 0, 0x3f2700, 0, 0x614900, 0, 0x836b01, 0, // 1b0 2
+ 0xa58d23, 0, 0xc7af45, 0, 0xe9d167, 0, 0xffe789, 0, // was ..0xfff389
+ 0x002400, 0, 0x004600, 0, 0x216800, 0, 0x438a07, 0, // 1c8 3
+ 0x65ac29, 0, 0x87ce4b, 0, 0xa9f06d, 0, 0xcbff8f, 0,
+ 0x340000, 0, 0x561400, 0, 0x783602, 0, 0x9a5824, 0, // 1e0 4
+ 0xbc7a46, 0, 0xde9c68, 0, 0xffbe8a, 0, 0xffd0ad, 0, // was ..0xffe0ac
+ 0x002700, 0, 0x004900, 0, 0x0c6b0c, 0, 0x2e8d2e, 0, // 1f8 5
+ 0x50af50, 0, 0x72d172, 0, 0x94f394, 0, 0xb6ffb6, 0,
+ 0x3d0008, 0, 0x610511, 0, 0x832733, 0, 0xa54955, 0, // 210 6
+ 0xc76b77, 0, 0xe98d99, 0, 0xffafbb, 0, 0xffd1d7, 0, // was 0x3f0000..0xffd1dd
+ 0x001e12, 0, 0x004228, 0, 0x046540, 0, 0x268762, 0, // 228 7
+ 0x48a984, 0, 0x6acba6, 0, 0x8cedc8, 0, 0xafffe0, 0, // was 0x002100, 0x00431e..0xaeffff
+ 0x300025, 0, 0x5f0047, 0, 0x811e69, 0, 0xa3408b, 0, // 240 8
+ 0xc562ad, 0, 0xe784cf, 0, 0xffa8ea, 0, 0xffc9f2, 0, // was ..0xffa6f1, 0xffc8ff
+ 0x001431, 0, 0x003653, 0, 0x0a5875, 0, 0x2c7a97, 0, // 258 9
+ 0x4e9cb9, 0, 0x70bedb, 0, 0x92e0fd, 0, 0xb4ffff, 0,
+ 0x2c0052, 0, 0x4e0074, 0, 0x701d96, 0, 0x923fb8, 0, // 270 a
+ 0xb461da, 0, 0xd683fc, 0, 0xe2a5ff, 0, 0xeec9ff, 0, // was ..0xf8a5ff, 0xffc7ff
+ 0x001759, 0, 0x00247c, 0, 0x1d469e, 0, 0x3f68c0, 0, // 288 b
+ 0x618ae2, 0, 0x83acff, 0, 0xa5ceff, 0, 0xc7f0ff, 0,
+ 0x12006d, 0, 0x34038f, 0, 0x5625b1, 0, 0x7847d3, 0, // 2a0 c
+ 0x9a69f5, 0, 0xb48cff, 0, 0xc9adff, 0, 0xe1d1ff, 0, // was ..0xbc8bff, 0xdeadff, 0xffcfff,
+ 0x000070, 0, 0x161292, 0, 0x3834b4, 0, 0x5a56d6, 0, // 2b8 d
+ 0x7c78f8, 0, 0x9e9aff, 0, 0xc0bcff, 0, 0xe2deff, 0,
+ 0x000000, 0, 0x121212, 0, 0x242424, 0, 0x484848, 0, // 2d0 e
+ 0x6c6c6c, 0, 0x909090, 0, 0xb4b4b4, 0, 0xd8d8d8, 0,
+ 0x000000, 0, 0x121212, 0, 0x242424, 0, 0x484848, 0, // 2e8 f
+ 0x6c6c6c, 0, 0x909090, 0, 0xb4b4b4, 0, 0xd8d8d8, 0,
+};
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+const PaletteArray PaletteHandler::ourSECAMPalette = {
+ 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
+ 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
+ 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
+ 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
+ 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
+ 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
+ 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
+ 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
+ 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
+ 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
+ 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
+ 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
+ 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
+ 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
+ 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
+ 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
+ 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
+ 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
+ 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
+ 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
+ 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
+ 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
+ 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
+ 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
+ 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
+ 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
+ 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
+ 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
+ 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
+ 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
+ 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
+ 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0
+};
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+const PaletteArray PaletteHandler::ourNTSCPaletteZ26 = {
+ 0x000000, 0, 0x505050, 0, 0x646464, 0, 0x787878, 0,
+ 0x8c8c8c, 0, 0xa0a0a0, 0, 0xb4b4b4, 0, 0xc8c8c8, 0,
+ 0x445400, 0, 0x586800, 0, 0x6c7c00, 0, 0x809000, 0,
+ 0x94a414, 0, 0xa8b828, 0, 0xbccc3c, 0, 0xd0e050, 0,
+ 0x673900, 0, 0x7b4d00, 0, 0x8f6100, 0, 0xa37513, 0,
+ 0xb78927, 0, 0xcb9d3b, 0, 0xdfb14f, 0, 0xf3c563, 0,
+ 0x7b2504, 0, 0x8f3918, 0, 0xa34d2c, 0, 0xb76140, 0,
+ 0xcb7554, 0, 0xdf8968, 0, 0xf39d7c, 0, 0xffb190, 0,
+ 0x7d122c, 0, 0x912640, 0, 0xa53a54, 0, 0xb94e68, 0,
+ 0xcd627c, 0, 0xe17690, 0, 0xf58aa4, 0, 0xff9eb8, 0,
+ 0x730871, 0, 0x871c85, 0, 0x9b3099, 0, 0xaf44ad, 0,
+ 0xc358c1, 0, 0xd76cd5, 0, 0xeb80e9, 0, 0xff94fd, 0,
+ 0x5d0b92, 0, 0x711fa6, 0, 0x8533ba, 0, 0x9947ce, 0,
+ 0xad5be2, 0, 0xc16ff6, 0, 0xd583ff, 0, 0xe997ff, 0,
+ 0x401599, 0, 0x5429ad, 0, 0x683dc1, 0, 0x7c51d5, 0,
+ 0x9065e9, 0, 0xa479fd, 0, 0xb88dff, 0, 0xcca1ff, 0,
+ 0x252593, 0, 0x3939a7, 0, 0x4d4dbb, 0, 0x6161cf, 0,
+ 0x7575e3, 0, 0x8989f7, 0, 0x9d9dff, 0, 0xb1b1ff, 0,
+ 0x0f3480, 0, 0x234894, 0, 0x375ca8, 0, 0x4b70bc, 0,
+ 0x5f84d0, 0, 0x7398e4, 0, 0x87acf8, 0, 0x9bc0ff, 0,
+ 0x04425a, 0, 0x18566e, 0, 0x2c6a82, 0, 0x407e96, 0,
+ 0x5492aa, 0, 0x68a6be, 0, 0x7cbad2, 0, 0x90cee6, 0,
+ 0x044f30, 0, 0x186344, 0, 0x2c7758, 0, 0x408b6c, 0,
+ 0x549f80, 0, 0x68b394, 0, 0x7cc7a8, 0, 0x90dbbc, 0,
+ 0x0f550a, 0, 0x23691e, 0, 0x377d32, 0, 0x4b9146, 0,
+ 0x5fa55a, 0, 0x73b96e, 0, 0x87cd82, 0, 0x9be196, 0,
+ 0x1f5100, 0, 0x336505, 0, 0x477919, 0, 0x5b8d2d, 0,
+ 0x6fa141, 0, 0x83b555, 0, 0x97c969, 0, 0xabdd7d, 0,
+ 0x344600, 0, 0x485a00, 0, 0x5c6e14, 0, 0x708228, 0,
+ 0x84963c, 0, 0x98aa50, 0, 0xacbe64, 0, 0xc0d278, 0,
+ 0x463e00, 0, 0x5a5205, 0, 0x6e6619, 0, 0x827a2d, 0,
+ 0x968e41, 0, 0xaaa255, 0, 0xbeb669, 0, 0xd2ca7d, 0
+};
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+const PaletteArray PaletteHandler::ourPALPaletteZ26 = {
+ 0x000000, 0, 0x4c4c4c, 0, 0x606060, 0, 0x747474, 0,
+ 0x888888, 0, 0x9c9c9c, 0, 0xb0b0b0, 0, 0xc4c4c4, 0,
+ 0x000000, 0, 0x4c4c4c, 0, 0x606060, 0, 0x747474, 0,
+ 0x888888, 0, 0x9c9c9c, 0, 0xb0b0b0, 0, 0xc4c4c4, 0,
+ 0x533a00, 0, 0x674e00, 0, 0x7b6203, 0, 0x8f7617, 0,
+ 0xa38a2b, 0, 0xb79e3f, 0, 0xcbb253, 0, 0xdfc667, 0,
+ 0x1b5800, 0, 0x2f6c00, 0, 0x438001, 0, 0x579415, 0,
+ 0x6ba829, 0, 0x7fbc3d, 0, 0x93d051, 0, 0xa7e465, 0,
+ 0x6a2900, 0, 0x7e3d12, 0, 0x925126, 0, 0xa6653a, 0,
+ 0xba794e, 0, 0xce8d62, 0, 0xe2a176, 0, 0xf6b58a, 0,
+ 0x075b00, 0, 0x1b6f11, 0, 0x2f8325, 0, 0x439739, 0,
+ 0x57ab4d, 0, 0x6bbf61, 0, 0x7fd375, 0, 0x93e789, 0,
+ 0x741b2f, 0, 0x882f43, 0, 0x9c4357, 0, 0xb0576b, 0,
+ 0xc46b7f, 0, 0xd87f93, 0, 0xec93a7, 0, 0xffa7bb, 0,
+ 0x00572e, 0, 0x106b42, 0, 0x247f56, 0, 0x38936a, 0,
+ 0x4ca77e, 0, 0x60bb92, 0, 0x74cfa6, 0, 0x88e3ba, 0,
+ 0x6d165f, 0, 0x812a73, 0, 0x953e87, 0, 0xa9529b, 0,
+ 0xbd66af, 0, 0xd17ac3, 0, 0xe58ed7, 0, 0xf9a2eb, 0,
+ 0x014c5e, 0, 0x156072, 0, 0x297486, 0, 0x3d889a, 0,
+ 0x519cae, 0, 0x65b0c2, 0, 0x79c4d6, 0, 0x8dd8ea, 0,
+ 0x5f1588, 0, 0x73299c, 0, 0x873db0, 0, 0x9b51c4, 0,
+ 0xaf65d8, 0, 0xc379ec, 0, 0xd78dff, 0, 0xeba1ff, 0,
+ 0x123b87, 0, 0x264f9b, 0, 0x3a63af, 0, 0x4e77c3, 0,
+ 0x628bd7, 0, 0x769feb, 0, 0x8ab3ff, 0, 0x9ec7ff, 0,
+ 0x451e9d, 0, 0x5932b1, 0, 0x6d46c5, 0, 0x815ad9, 0,
+ 0x956eed, 0, 0xa982ff, 0, 0xbd96ff, 0, 0xd1aaff, 0,
+ 0x2a2b9e, 0, 0x3e3fb2, 0, 0x5253c6, 0, 0x6667da, 0,
+ 0x7a7bee, 0, 0x8e8fff, 0, 0xa2a3ff, 0, 0xb6b7ff, 0,
+ 0x000000, 0, 0x4c4c4c, 0, 0x606060, 0, 0x747474, 0,
+ 0x888888, 0, 0x9c9c9c, 0, 0xb0b0b0, 0, 0xc4c4c4, 0,
+ 0x000000, 0, 0x4c4c4c, 0, 0x606060, 0, 0x747474, 0,
+ 0x888888, 0, 0x9c9c9c, 0, 0xb0b0b0, 0, 0xc4c4c4, 0
+};
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+const PaletteArray PaletteHandler::ourSECAMPaletteZ26 = {
+ 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
+ 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
+ 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
+ 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
+ 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
+ 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
+ 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
+ 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
+ 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
+ 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
+ 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
+ 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
+ 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
+ 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
+ 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
+ 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
+ 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
+ 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
+ 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
+ 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
+ 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
+ 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
+ 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
+ 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
+ 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
+ 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
+ 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
+ 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
+ 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
+ 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
+ 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
+ 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0
+};
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+PaletteArray PaletteHandler::ourUserNTSCPalette = { 0 }; // filled from external file
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+PaletteArray PaletteHandler::ourUserPALPalette = { 0 }; // filled from external file
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+PaletteArray PaletteHandler::ourUserSECAMPalette = { 0 }; // filled from external file
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+PaletteArray PaletteHandler::ourCustomNTSCPalette = { 0 }; // filled by function
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+PaletteArray PaletteHandler::ourCustomPALPalette = { 0 }; // filled by function
diff --git a/src/common/PaletteHandler.hxx b/src/common/PaletteHandler.hxx
new file mode 100644
index 000000000..bd102d9f0
--- /dev/null
+++ b/src/common/PaletteHandler.hxx
@@ -0,0 +1,261 @@
+//============================================================================
+//
+// SSSS tt lll lll
+// SS SS tt ll ll
+// SS tttttt eeee ll ll aaaa
+// SSSS tt ee ee ll ll aa
+// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
+// SS SS tt ee ll ll aa aa
+// SSSS ttt eeeee llll llll aaaaa
+//
+// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony
+// and the Stella Team
+//
+// See the file "License.txt" for information on usage and redistribution of
+// this file, and for a DISCLAIMER OF ALL WARRANTIES.
+//============================================================================
+
+#ifndef PALETTE_HANDLER_HXX
+#define PALETTE_HANDLER_HXX
+
+#include "bspf.hxx"
+#include "OSystem.hxx"
+#include "ConsoleTiming.hxx"
+#include "EventHandlerConstants.hxx"
+
+class PaletteHandler
+{
+ public:
+ // Setting names of palette types
+ static constexpr const char* SETTING_STANDARD = "standard";
+ static constexpr const char* SETTING_Z26 = "z26";
+ static constexpr const char* SETTING_USER = "user";
+ static constexpr const char* SETTING_CUSTOM = "custom";
+
+ // Phase shift default and limits
+ static constexpr float DEF_NTSC_SHIFT = 26.2F;
+ static constexpr float DEF_PAL_SHIFT = 31.3F; // ~= 360 / 11.5
+ static constexpr float MAX_SHIFT = 4.5F;
+
+ enum Adjustables {
+ PHASE_SHIFT,
+ HUE,
+ SATURATION,
+ CONTRAST,
+ BRIGHTNESS,
+ GAMMA
+ };
+
+ // Externally used adjustment parameters
+ struct Adjustable {
+ float phaseNtsc{0.F}, phasePal{0.F};
+ uInt32 hue{0}, saturation{0}, contrast{0}, brightness{0}, gamma{0};
+ };
+
+ public:
+ PaletteHandler(OSystem& system);
+ virtual ~PaletteHandler() = default;
+
+ /**
+ Cycle through available palettes.
+
+ @param direction +1 indicates increase, -1 indicates decrease.
+ */
+ void cyclePalette(int direction = +1);
+
+ /*
+ Cycle through each palette adjustable.
+
+ @param direction +1 indicates increase, -1 indicates decrease.
+ */
+ void cycleAdjustable(int direction = +1);
+
+ /*
+ Increase or decrease given palette adjustable.
+
+ @param adjustable The adjustable to change
+ @param direction +1 indicates increase, -1 indicates decrease.
+ */
+ void changeAdjustable(int adjustable, int direction);
+
+ /*
+ Increase or decrease current palette adjustable.
+
+ @param direction +1 indicates increase, -1 indicates decrease.
+ */
+ void changeCurrentAdjustable(int direction = +1);
+
+ // Load adjustables from settings
+ void loadConfig(const Settings& settings);
+
+ // Save adjustables to settings
+ void saveConfig(Settings& settings) const;
+
+ // Set adjustables
+ void setAdjustables(const Adjustable& adjustable);
+
+ // Retrieve current adjustables
+ void getAdjustables(Adjustable& adjustable) const;
+
+ /**
+ Sets the palette according to the given palette name.
+
+ @param name The palette to switch to
+ */
+ void setPalette(const string& name);
+
+ /**
+ Sets the palette from current settings.
+ */
+ void setPalette();
+
+ private:
+ static constexpr char DEGREE = 0x1c;
+
+ enum PaletteType {
+ Standard,
+ Z26,
+ User,
+ Custom,
+ NumTypes,
+ MinType = Standard,
+ MaxType = Custom
+ };
+
+ /**
+ Convert adjustables from/to 100% scale
+ */
+ constexpr float scaleFrom100(float x) const { return (x / 50.F) - 1.F; }
+ constexpr uInt32 scaleTo100(float x) const { return uInt32(50 * (x + 1.F)); }
+
+ /**
+ Convert palette settings name to enumeration.
+
+ @param name The given palette's settings name
+
+ @return The palette type
+ */
+ PaletteType toPaletteType(const string& name) const;
+
+ /**
+ Convert enumeration to palette settings name.
+
+ @param type The given palette type
+
+ @return The palette's settings name
+ */
+ string toPaletteName(PaletteType type) const;
+
+ /**
+ Display current adjustable with gauge bar message
+ */
+ void showAdjustableMessage();
+
+ /**
+ Change the "phase shift" variable.
+ Note that there are two of these (NTSC and PAL). The currently
+ active mode will determine which one is used.
+
+ @param direction +1 indicates increase, -1 indicates decrease.
+ */
+ void changeColorPhaseShift(int direction = +1);
+
+ /**
+ Generates a custom palette, based on user defined phase shifts.
+
+ @param timing Use NTSC or PAL phase shift and generate according palette
+ */
+ void generateCustomPalette(ConsoleTiming timing);
+
+ /**
+ Create new palette by applying palette adjustments on given palette.
+
+ @param source The palette which should be adjusted
+
+ @return An adjusted palette
+ */
+ PaletteArray adjustedPalette(const PaletteArray& source);
+
+ /**
+ Adjust hue and saturation for given RGB values.
+
+ @param R The red value to adjust
+ @param G The green value to adjust
+ @param B The blue value to adjust
+ @param H The hue adjustment value
+ @param S The saturation
+ */
+ void adjustHueSaturation(int& R, int& G, int& B, float H, float S);
+
+ /**
+ Loads a user-defined palette file (from OSystem::paletteFile), filling the
+ appropriate user-defined palette arrays.
+ */
+ void loadUserPalette();
+
+ private:
+ static constexpr int NUM_ADJUSTABLES = 6;
+
+ OSystem& myOSystem;
+
+ // The currently selected adjustable
+ uInt32 myCurrentAdjustable{0};
+
+ struct AdjustableTag {
+ const char* const name{nullptr};
+ float* value{nullptr};
+ };
+ const std::array myAdjustables =
+ { {
+ { "phase shift", nullptr },
+ { "hue", &myHue },
+ { "saturation", &mySaturation },
+ { "contrast", &myContrast },
+ { "brightness", &myBrightness },
+ { "gamma", &myGamma },
+ } };
+
+ // NTSC and PAL color phase shifts
+ float myPhaseNTSC{DEF_NTSC_SHIFT};
+ float myPhasePAL{DEF_PAL_SHIFT};
+ // range -1.0 to +1.0 (as in AtariNTSC)
+ // Basic parameters
+ float myHue{0.0F}; // -1 = -180 degrees +1 = +180 degrees
+ float mySaturation{0.0F}; // -1 = grayscale (0.0) +1 = oversaturated colors (2.0)
+ float myContrast{0.0F}; // -1 = dark (0.5) +1 = light (1.5)
+ float myBrightness{0.0F}; // -1 = dark (0.5) +1 = light (1.5)
+ // Advanced parameters
+ float myGamma{0.0F}; // -1 = dark (1.5) +1 = light (0.5)
+
+ // Indicates whether an external palette was found and
+ // successfully loaded
+ bool myUserPaletteDefined{false};
+
+ // Table of RGB values for NTSC, PAL and SECAM
+ static const PaletteArray ourNTSCPalette;
+ static const PaletteArray ourPALPalette;
+ static const PaletteArray ourSECAMPalette;
+
+ // Table of RGB values for NTSC, PAL and SECAM - Z26 version
+ static const PaletteArray ourNTSCPaletteZ26;
+ static const PaletteArray ourPALPaletteZ26;
+ static const PaletteArray ourSECAMPaletteZ26;
+
+ // Table of RGB values for NTSC, PAL and SECAM - user-defined
+ static PaletteArray ourUserNTSCPalette;
+ static PaletteArray ourUserPALPalette;
+ static PaletteArray ourUserSECAMPalette;
+
+ // Table of RGB values for NTSC, PAL - custom-defined and generated
+ static PaletteArray ourCustomNTSCPalette;
+ static PaletteArray ourCustomPALPalette;
+
+ private:
+ PaletteHandler() = delete;
+ PaletteHandler(const PaletteHandler&) = delete;
+ PaletteHandler(PaletteHandler&&) = delete;
+ PaletteHandler& operator=(const PaletteHandler&) = delete;
+ PaletteHandler& operator=(const PaletteHandler&&) = delete;
+};
+
+#endif // PALETTE_HANDLER_HXX
diff --git a/src/common/RewindManager.cxx b/src/common/RewindManager.cxx
index d16bbd6c3..6bafbeeaa 100644
--- a/src/common/RewindManager.cxx
+++ b/src/common/RewindManager.cxx
@@ -18,6 +18,7 @@
#include
#include "OSystem.hxx"
+#include "Console.hxx"
#include "Serializer.hxx"
#include "StateManager.hxx"
#include "TIA.hxx"
diff --git a/src/common/SoundNull.hxx b/src/common/SoundNull.hxx
index 87ba7736a..8974e9834 100644
--- a/src/common/SoundNull.hxx
+++ b/src/common/SoundNull.hxx
@@ -18,12 +18,13 @@
#ifndef SOUND_NULL_HXX
#define SOUND_NULL_HXX
+class OSystem;
+class AudioQueue;
+class EmulationTiming;
+
#include "bspf.hxx"
#include "Logger.hxx"
#include "Sound.hxx"
-#include "OSystem.hxx"
-#include "AudioQueue.hxx"
-#include "EmulationTiming.hxx"
/**
This class implements a Null sound object, where-by sound generation
@@ -96,10 +97,9 @@ class SoundNull : public Sound
/**
Adjusts the volume of the sound device based on the given direction.
- @param direction Increase or decrease the current volume by a predefined
- amount based on the direction (1 = increase, -1 =decrease)
+ @param direction +1 indicates increase, -1 indicates decrease.
*/
- void adjustVolume(Int8 direction) override { }
+ void adjustVolume(int direction = 1) override { }
/**
This method is called to provide information about the sound device.
diff --git a/src/common/SoundSDL2.cxx b/src/common/SoundSDL2.cxx
index 671e5f83c..928ebbc44 100644
--- a/src/common/SoundSDL2.cxx
+++ b/src/common/SoundSDL2.cxx
@@ -186,16 +186,31 @@ bool SoundSDL2::mute(bool state)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool SoundSDL2::toggleMute()
{
- bool enabled = myAudioSettings.enabled();
+ bool enabled = !myAudioSettings.enabled();
- setEnabled(!enabled);
+ setEnabled(enabled);
myOSystem.console().initializeAudio();
string message = "Sound ";
- message += !enabled ? "unmuted" : "muted";
+ message += enabled ? "unmuted" : "muted";
myOSystem.frameBuffer().showMessage(message);
+ //ostringstream strval;
+ //uInt32 volume;
+ //// Now show an onscreen message
+ //if(enabled)
+ //{
+ // volume = myVolume;
+ // strval << volume << "%";
+ //}
+ //else
+ //{
+ // volume = 0;
+ // strval << "Muted";
+ //}
+ //myOSystem.frameBuffer().showMessage("Volume", strval.str(), volume);
+
return enabled;
}
@@ -214,20 +229,12 @@ void SoundSDL2::setVolume(uInt32 percent)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void SoundSDL2::adjustVolume(Int8 direction)
+void SoundSDL2::adjustVolume(int direction)
{
ostringstream strval;
- string message;
-
Int32 percent = myVolume;
- if(direction == -1)
- percent -= 2;
- else if(direction == 1)
- percent += 2;
-
- if((percent < 0) || (percent > 100))
- return;
+ percent = BSPF::clamp(percent + direction * 2, 0, 100);
setVolume(percent);
@@ -241,11 +248,11 @@ void SoundSDL2::adjustVolume(Int8 direction)
}
// Now show an onscreen message
- strval << percent;
- message = "Volume set to ";
- message += strval.str();
-
- myOSystem.frameBuffer().showMessage(message);
+ if(percent)
+ strval << percent << "%";
+ else
+ strval << "Off";
+ myOSystem.frameBuffer().showMessage("Volume", strval.str(), percent);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/src/common/SoundSDL2.hxx b/src/common/SoundSDL2.hxx
index 85fb86031..398f1fa92 100644
--- a/src/common/SoundSDL2.hxx
+++ b/src/common/SoundSDL2.hxx
@@ -24,12 +24,12 @@ class OSystem;
class AudioQueue;
class EmulationTiming;
class AudioSettings;
+class Resampler;
#include "SDL_lib.hxx"
#include "bspf.hxx"
#include "Sound.hxx"
-#include "audio/Resampler.hxx"
/**
This class implements the sound API for SDL.
@@ -98,10 +98,9 @@ class SoundSDL2 : public Sound
/**
Adjusts the volume of the sound device based on the given direction.
- @param direction Increase or decrease the current volume by a predefined
- amount based on the direction (1 = increase, -1 = decrease)
- */
- void adjustVolume(Int8 direction) override;
+ @param direction +1 indicates increase, -1 indicates decrease.
+ */
+ void adjustVolume(int direction = 1) override;
/**
This method is called to provide information about the sound device.
diff --git a/src/common/StateManager.cxx b/src/common/StateManager.cxx
index 667665054..a4add0889 100644
--- a/src/common/StateManager.cxx
+++ b/src/common/StateManager.cxx
@@ -299,15 +299,14 @@ void StateManager::saveState(int slot)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void StateManager::changeState(int direction)
{
- myCurrentSlot += direction;
- if (myCurrentSlot < 0)
- myCurrentSlot = 9;
- else
- myCurrentSlot %= 10;
+ myCurrentSlot = BSPF::clampw(myCurrentSlot + direction, 0, 9);
// Print appropriate message
ostringstream buf;
- buf << "Changed to slot " << myCurrentSlot;
+ if(direction)
+ buf << "Changed to state slot " << myCurrentSlot;
+ else
+ buf << "State slot " << myCurrentSlot;
myOSystem.frameBuffer().showMessage(buf.str());
}
diff --git a/src/common/StateManager.hxx b/src/common/StateManager.hxx
index 09de785fb..3da98499c 100644
--- a/src/common/StateManager.hxx
+++ b/src/common/StateManager.hxx
@@ -115,8 +115,10 @@ class StateManager
/**
Switches to the next higher or lower state slot (circular queue style).
+
+ @param direction +1 indicates increase, -1 indicates decrease.
*/
- void changeState(int direction);
+ void changeState(int direction = +1);
/**
Toggles auto slot mode.
diff --git a/src/common/bspf.hxx b/src/common/bspf.hxx
index 1484b21ed..f21a99a4c 100644
--- a/src/common/bspf.hxx
+++ b/src/common/bspf.hxx
@@ -43,6 +43,7 @@ using uInt64 = uint64_t;
#include
#include
#include
+#include
#include
#include
#include
@@ -86,6 +87,8 @@ using StringList = std::vector;
using ByteBuffer = std::unique_ptr; // NOLINT
using DWordBuffer = std::unique_ptr; // NOLINT
+using AdjustFunction = std::function;
+
// We use KB a lot; let's make a literal for it
constexpr uInt32 operator "" _KB(unsigned long long size)
{
@@ -133,6 +136,10 @@ namespace BSPF
{
if(val < lower || val > upper) val = setVal;
}
+ template inline T clampw(T val, T lower, T upper)
+ {
+ return (val < lower) ? upper : (val > upper) ? lower : val;
+ }
// Convert string to given case
inline const string& toUpperCase(string& s)
diff --git a/src/common/module.mk b/src/common/module.mk
index f7a228189..1aae6cd0a 100644
--- a/src/common/module.mk
+++ b/src/common/module.mk
@@ -11,6 +11,7 @@ MODULE_OBJS := \
src/common/Logger.o \
src/common/main.o \
src/common/MouseControl.o \
+ src/common/PaletteHandler.o \
src/common/PhosphorHandler.o \
src/common/PhysicalJoystick.o \
src/common/PJoystickHandler.o \
diff --git a/src/common/sdl_blitter/BilinearBlitter.cxx b/src/common/sdl_blitter/BilinearBlitter.cxx
index bae05207c..295d8e8e2 100644
--- a/src/common/sdl_blitter/BilinearBlitter.cxx
+++ b/src/common/sdl_blitter/BilinearBlitter.cxx
@@ -15,9 +15,9 @@
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
-#include "BilinearBlitter.hxx"
-
+#include "FrameBufferSDL2.hxx"
#include "ThreadDebugging.hxx"
+#include "BilinearBlitter.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
BilinearBlitter::BilinearBlitter(FrameBufferSDL2& fb, bool interpolate)
diff --git a/src/common/sdl_blitter/BilinearBlitter.hxx b/src/common/sdl_blitter/BilinearBlitter.hxx
index e18cba6bf..84c550ad1 100644
--- a/src/common/sdl_blitter/BilinearBlitter.hxx
+++ b/src/common/sdl_blitter/BilinearBlitter.hxx
@@ -18,8 +18,9 @@
#ifndef BILINEAR_BLITTER_HXX
#define BILINEAR_BLITTER_HXX
+class FrameBufferSDL2;
+
#include "Blitter.hxx"
-#include "FrameBufferSDL2.hxx"
#include "SDL_lib.hxx"
class BilinearBlitter : public Blitter {
diff --git a/src/common/sdl_blitter/QisBlitter.cxx b/src/common/sdl_blitter/QisBlitter.cxx
index 95d958565..c68c4bff9 100644
--- a/src/common/sdl_blitter/QisBlitter.cxx
+++ b/src/common/sdl_blitter/QisBlitter.cxx
@@ -15,9 +15,9 @@
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
-#include "QisBlitter.hxx"
-
+#include "FrameBufferSDL2.hxx"
#include "ThreadDebugging.hxx"
+#include "QisBlitter.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
QisBlitter::QisBlitter(FrameBufferSDL2& fb)
diff --git a/src/common/sdl_blitter/QisBlitter.hxx b/src/common/sdl_blitter/QisBlitter.hxx
index 77ab2b51d..14ee84fcc 100644
--- a/src/common/sdl_blitter/QisBlitter.hxx
+++ b/src/common/sdl_blitter/QisBlitter.hxx
@@ -18,8 +18,9 @@
#ifndef QIS_BLITTER_HXX
#define QIS_BLITTER_HXX
+class FrameBufferSDL2;
+
#include "Blitter.hxx"
-#include "FrameBufferSDL2.hxx"
#include "SDL_lib.hxx"
class QisBlitter : public Blitter {
diff --git a/src/common/tv_filters/AtariNTSC.cxx b/src/common/tv_filters/AtariNTSC.cxx
index a0b9ef169..ad57a12f8 100644
--- a/src/common/tv_filters/AtariNTSC.cxx
+++ b/src/common/tv_filters/AtariNTSC.cxx
@@ -57,9 +57,15 @@ void AtariNTSC::generateKernels()
const uInt8* ptr = myRGBPalette.data();
for(size_t entry = 0; entry < myRGBPalette.size() / 3; ++entry)
{
+ #ifdef BLARGG_PALETTE
float r = myImpl.to_float[*ptr++],
g = myImpl.to_float[*ptr++],
b = myImpl.to_float[*ptr++];
+ #else
+ float r = (*ptr++) / 255.F * rgb_unit + rgb_offset,
+ g = (*ptr++) / 255.F * rgb_unit + rgb_offset,
+ b = (*ptr++) / 255.F * rgb_unit + rgb_offset;
+ #endif
float y, i, q; RGB_TO_YIQ( r, g, b, y, i, q );
// Generate kernel
@@ -319,8 +325,10 @@ void AtariNTSC::renderWithPhosphorThread(const uInt8* atari_in, const uInt32 in_
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void AtariNTSC::init(init_t& impl, const Setup& setup)
{
+#ifdef BLARGG_PALETTE
impl.brightness = setup.brightness * (0.5F * rgb_unit) + rgb_offset;
impl.contrast = setup.contrast * (0.5F * rgb_unit) + rgb_unit;
+#endif
impl.artifacts = setup.artifacts;
if ( impl.artifacts > 0 )
@@ -334,6 +342,7 @@ void AtariNTSC::init(init_t& impl, const Setup& setup)
initFilters(impl, setup);
+#ifdef BLARGG_PALETTE
/* generate gamma table */
if (true) /* was (gamma_size > 1) */
{
@@ -341,19 +350,22 @@ void AtariNTSC::init(init_t& impl, const Setup& setup)
float const gamma = 1.1333F - setup.gamma * 0.5F;
/* match common PC's 2.2 gamma to TV's 2.65 gamma */
int i;
- for ( i = 0; i < gamma_size; i++ )
- impl.to_float [i] =
- powf( i * to_float, gamma ) * impl.contrast + impl.brightness;
+ for(i = 0; i < gamma_size; i++)
+ impl.to_float[i] =
+ powf(i * to_float, gamma) * impl.contrast + impl.brightness;
}
+#endif
/* setup decoder matricies */
{
+ #ifdef BLARGG_PALETTE
float hue = setup.hue * BSPF::PI_f + BSPF::PI_f / 180 * ext_decoder_hue;
float sat = setup.saturation + 1;
hue += BSPF::PI_f / 180 * (std_decoder_hue - ext_decoder_hue);
- float s = sinf( hue ) * sat;
- float c = cosf( hue ) * sat;
+ float s = sinf(hue)*sat;
+ float c = cosf(hue)*sat;
+ #endif
float* out = impl.to_rgb.data();
int n;
@@ -366,8 +378,13 @@ void AtariNTSC::init(init_t& impl, const Setup& setup)
{
float i = *in++;
float q = *in++;
+ #ifdef BLARGG_PALETTE
*out++ = i * c - q * s;
*out++ = i * s + q * c;
+ #else
+ *out++ = i ;
+ *out++ = q;
+ #endif
}
while ( --n2 );
#if 0 // burst_count is always 0
@@ -544,16 +561,32 @@ void AtariNTSC::genKernel(init_t& impl, float y, float i, float q, uInt32* out)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const AtariNTSC::Setup AtariNTSC::TV_Composite = {
+#ifdef BLARGG_PALETTE
0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.15F, 0.0F, 0.0F, 0.0F
+#else
+ 0.0F, 0.15F, 0.0F, 0.0F, 0.0F
+#endif
};
const AtariNTSC::Setup AtariNTSC::TV_SVideo = {
+#ifdef BLARGG_PALETTE
0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.45F, -1.0F, -1.0F, 0.0F
+#else
+ 0.0F, 0.45F, -1.0F, -1.0F, 0.0F
+#endif
};
const AtariNTSC::Setup AtariNTSC::TV_RGB = {
+#ifdef BLARGG_PALETTE
0.0F, 0.0F, 0.0F, 0.0F, 0.2F, 0.0F, 0.70F, -1.0F, -1.0F, -1.0F
+#else
+ 0.2F, 0.70F, -1.0F, -1.0F, -1.0F
+#endif
};
const AtariNTSC::Setup AtariNTSC::TV_Bad = {
+#ifdef BLARGG_PALETTE
0.1F, -0.3F, 0.3F, 0.25F, 0.2F, 0.0F, 0.1F, 0.5F, 0.5F, 0.5F
+#else
+ 0.2F, 0.1F, 0.5F, 0.5F, 0.5F
+#endif
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/src/common/tv_filters/AtariNTSC.hxx b/src/common/tv_filters/AtariNTSC.hxx
index 4ae7b666f..eb75bce3d 100644
--- a/src/common/tv_filters/AtariNTSC.hxx
+++ b/src/common/tv_filters/AtariNTSC.hxx
@@ -46,6 +46,8 @@
#include "FrameBufferConstants.hxx"
#include "bspf.hxx"
+//#define BLARGG_PALETTE // also modify contrast, brightness, saturation, gamma and hue when defined
+
class AtariNTSC
{
public:
@@ -57,14 +59,18 @@ class AtariNTSC
struct Setup
{
// Basic parameters
+ #ifdef BLARGG_PALETTE
float hue{0.F}; // -1 = -180 degrees +1 = +180 degrees
float saturation{0.F}; // -1 = grayscale (0.0) +1 = oversaturated colors (2.0)
float contrast{0.F}; // -1 = dark (0.5) +1 = light (1.5)
float brightness{0.F}; // -1 = dark (0.5) +1 = light (1.5)
+ #endif
float sharpness{0.F}; // edge contrast enhancement/blurring
// Advanced parameters
+ #ifdef BLARGG_PALETTE
float gamma{0.F}; // -1 = dark (1.5) +1 = light (0.5)
+ #endif
float resolution{0.F}; // image resolution
float artifacts{0.F}; // artifacts caused by color changes
float fringing{0.F}; // color artifacts caused by brightness changes
@@ -127,7 +133,9 @@ class AtariNTSC
burst_size = entry_size / burst_count,
kernel_half = 16,
kernel_size = kernel_half * 2 + 1,
+ #ifdef BLARGG_PALETTE
gamma_size = 256,
+ #endif
rgb_builder = ((1 << 21) | (1 << 11) | (1 << 1)),
rgb_kernel_size = burst_size / alignment_count,
@@ -162,16 +170,20 @@ class AtariNTSC
struct init_t
{
std::array to_rgb{0.F};
+ #ifdef BLARGG_PALETTE
std::array to_float{0.F};
float contrast{0.F};
float brightness{0.F};
+ #endif
float artifacts{0.F};
float fringing{0.F};
std::array kernel{0.F};
init_t() {
to_rgb.fill(0.0);
+ #ifdef BLARGG_PALETTE
to_float.fill(0.0);
+ #endif
kernel.fill(0.0);
}
};
diff --git a/src/common/tv_filters/NTSCFilter.cxx b/src/common/tv_filters/NTSCFilter.cxx
index 6ec1afc8c..9764f1ac3 100644
--- a/src/common/tv_filters/NTSCFilter.cxx
+++ b/src/common/tv_filters/NTSCFilter.cxx
@@ -62,9 +62,9 @@ string NTSCFilter::getPreset() const
{
switch(myPreset)
{
- case Preset::COMPOSITE: return "COMPOSITE";
- case Preset::SVIDEO: return "S-VIDEO";
case Preset::RGB: return "RGB";
+ case Preset::SVIDEO: return "S-VIDEO";
+ case Preset::COMPOSITE: return "COMPOSITE";
case Preset::BAD: return "BAD ADJUST";
case Preset::CUSTOM: return "CUSTOM";
default: return "Disabled";
@@ -72,81 +72,81 @@ string NTSCFilter::getPreset() const
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-string NTSCFilter::setNextAdjustable()
+void NTSCFilter::selectAdjustable(int direction,
+ string& text, string& valueText, Int32& value)
{
- if(myPreset != Preset::CUSTOM)
- return "'Custom' TV mode not selected";
+ if(direction == +1)
+ {
+ #ifdef BLARGG_PALETTE
+ myCurrentAdjustable = (myCurrentAdjustable + 1) % 10;
+ #else
+ myCurrentAdjustable = (myCurrentAdjustable + 1) % 5;
+ #endif
+ }
+ else if(direction == -1)
+ {
+ #ifdef BLARGG_PALETTE
+ if(myCurrentAdjustable == 0) myCurrentAdjustable = 9;
+ #else
+ if(myCurrentAdjustable == 0) myCurrentAdjustable = 4;
+ #endif
+ else --myCurrentAdjustable;
+ }
- myCurrentAdjustable = (myCurrentAdjustable + 1) % 10;
- ostringstream buf;
- buf << "Custom adjustable '" << ourCustomAdjustables[myCurrentAdjustable].type
- << "' selected";
+ ostringstream msg, val;
- return buf.str();
+ value = scaleTo100(*ourCustomAdjustables[myCurrentAdjustable].value);
+ msg << "Custom " << ourCustomAdjustables[myCurrentAdjustable].type;
+ val << value << "%";
+
+ text = msg.str();
+ valueText = val.str();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-string NTSCFilter::setPreviousAdjustable()
+void NTSCFilter::changeAdjustable(int adjustable, int direction,
+ string& text, string& valueText, Int32& newValue)
{
- 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();
+ myCurrentAdjustable = adjustable;
+ changeCurrentAdjustable(direction, text, valueText, newValue);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-string NTSCFilter::increaseAdjustable()
+void NTSCFilter::changeCurrentAdjustable(int direction,
+ string& text, string& valueText, Int32& newValue)
{
- if(myPreset != Preset::CUSTOM)
- return "'Custom' TV mode not selected";
+ //if(myPreset != Preset::CUSTOM)
+ // return "'Custom' TV mode not selected";
- uInt32 newval = scaleTo100(*ourCustomAdjustables[myCurrentAdjustable].value);
- newval += 2; if(newval > 100) newval = 100;
- *ourCustomAdjustables[myCurrentAdjustable].value = scaleFrom100(newval);
+ newValue = scaleTo100(*ourCustomAdjustables[myCurrentAdjustable].value);
+ newValue = BSPF::clamp(newValue + direction * 2, 0, 100);
- ostringstream buf;
- buf << "Custom '" << ourCustomAdjustables[myCurrentAdjustable].type
- << "' set to " << newval;
+ *ourCustomAdjustables[myCurrentAdjustable].value = scaleFrom100(newValue);
setPreset(myPreset);
- return buf.str();
-}
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-string NTSCFilter::decreaseAdjustable()
-{
- if(myPreset != Preset::CUSTOM)
- return "'Custom' TV mode not selected";
+ ostringstream msg, val;
- uInt32 newval = scaleTo100(*ourCustomAdjustables[myCurrentAdjustable].value);
- if(newval < 2) newval = 0;
- else newval -= 2;
- *ourCustomAdjustables[myCurrentAdjustable].value = scaleFrom100(newval);
+ msg << "Custom " << ourCustomAdjustables[myCurrentAdjustable].type;
+ val << newValue << "%";
- ostringstream buf;
- buf << "Custom '" << ourCustomAdjustables[myCurrentAdjustable].type
- << "' set to " << newval;
-
- setPreset(myPreset);
- return buf.str();
+ text = msg.str();
+ valueText = val.str();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void NTSCFilter::loadConfig(const Settings& settings)
{
+
// Load adjustables for custom mode
+#ifdef BLARGG_PALETTE
myCustomSetup.hue = BSPF::clamp(settings.getFloat("tv.hue"), -1.0F, 1.0F);
myCustomSetup.saturation = BSPF::clamp(settings.getFloat("tv.saturation"), -1.0F, 1.0F);
myCustomSetup.contrast = BSPF::clamp(settings.getFloat("tv.contrast"), -1.0F, 1.0F);
myCustomSetup.brightness = BSPF::clamp(settings.getFloat("tv.brightness"), -1.0F, 1.0F);
- myCustomSetup.sharpness = BSPF::clamp(settings.getFloat("tv.sharpness"), -1.0F, 1.0F);
myCustomSetup.gamma = BSPF::clamp(settings.getFloat("tv.gamma"), -1.0F, 1.0F);
+#endif
+ myCustomSetup.sharpness = BSPF::clamp(settings.getFloat("tv.sharpness"), -1.0F, 1.0F);
myCustomSetup.resolution = BSPF::clamp(settings.getFloat("tv.resolution"), -1.0F, 1.0F);
myCustomSetup.artifacts = BSPF::clamp(settings.getFloat("tv.artifacts"), -1.0F, 1.0F);
myCustomSetup.fringing = BSPF::clamp(settings.getFloat("tv.fringing"), -1.0F, 1.0F);
@@ -157,12 +157,14 @@ void NTSCFilter::loadConfig(const Settings& settings)
void NTSCFilter::saveConfig(Settings& settings) const
{
// Save adjustables for custom mode
+#ifdef BLARGG_PALETTE
settings.setValue("tv.hue", myCustomSetup.hue);
settings.setValue("tv.saturation", myCustomSetup.saturation);
settings.setValue("tv.contrast", myCustomSetup.contrast);
settings.setValue("tv.brightness", myCustomSetup.brightness);
- settings.setValue("tv.sharpness", myCustomSetup.sharpness);
settings.setValue("tv.gamma", myCustomSetup.gamma);
+#endif
+ settings.setValue("tv.sharpness", myCustomSetup.sharpness);
settings.setValue("tv.resolution", myCustomSetup.resolution);
settings.setValue("tv.artifacts", myCustomSetup.artifacts);
settings.setValue("tv.fringing", myCustomSetup.fringing);
@@ -174,12 +176,12 @@ void NTSCFilter::getAdjustables(Adjustable& adjustable, Preset preset) const
{
switch(preset)
{
- case Preset::COMPOSITE:
- convertToAdjustable(adjustable, AtariNTSC::TV_Composite); break;
- case Preset::SVIDEO:
- convertToAdjustable(adjustable, AtariNTSC::TV_SVideo); break;
case Preset::RGB:
convertToAdjustable(adjustable, AtariNTSC::TV_RGB); break;
+ case Preset::SVIDEO:
+ convertToAdjustable(adjustable, AtariNTSC::TV_SVideo); break;
+ case Preset::COMPOSITE:
+ convertToAdjustable(adjustable, AtariNTSC::TV_Composite); break;
case Preset::BAD:
convertToAdjustable(adjustable, AtariNTSC::TV_Bad); break;
case Preset::CUSTOM:
@@ -192,12 +194,14 @@ void NTSCFilter::getAdjustables(Adjustable& adjustable, Preset preset) const
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void NTSCFilter::setCustomAdjustables(Adjustable& adjustable)
{
- myCustomSetup.hue = scaleFrom100(adjustable.hue);
- myCustomSetup.saturation = scaleFrom100(adjustable.saturation);
- myCustomSetup.contrast = scaleFrom100(adjustable.contrast);
- myCustomSetup.brightness = scaleFrom100(adjustable.brightness);
+#ifdef BLARGG_PALETTE
+ //myCustomSetup.hue = scaleFrom100(adjustable.hue);
+ //myCustomSetup.saturation = scaleFrom100(adjustable.saturation);
+ //myCustomSetup.contrast = scaleFrom100(adjustable.contrast);
+ //myCustomSetup.brightness = scaleFrom100(adjustable.brightness);
+ //myCustomSetup.gamma = scaleFrom100(adjustable.gamma);
+#endif
myCustomSetup.sharpness = scaleFrom100(adjustable.sharpness);
- myCustomSetup.gamma = scaleFrom100(adjustable.gamma);
myCustomSetup.resolution = scaleFrom100(adjustable.resolution);
myCustomSetup.artifacts = scaleFrom100(adjustable.artifacts);
myCustomSetup.fringing = scaleFrom100(adjustable.fringing);
@@ -208,12 +212,14 @@ void NTSCFilter::setCustomAdjustables(Adjustable& adjustable)
void NTSCFilter::convertToAdjustable(Adjustable& adjustable,
const AtariNTSC::Setup& setup) const
{
- adjustable.hue = scaleTo100(setup.hue);
- adjustable.saturation = scaleTo100(setup.saturation);
- adjustable.contrast = scaleTo100(setup.contrast);
- adjustable.brightness = scaleTo100(setup.brightness);
+#ifdef BLARGG_PALETTE
+ //adjustable.hue = scaleTo100(setup.hue);
+ //adjustable.saturation = scaleTo100(setup.saturation);
+ //adjustable.contrast = scaleTo100(setup.contrast);
+ //adjustable.brightness = scaleTo100(setup.brightness);
+ //adjustable.gamma = scaleTo100(setup.gamma);
+#endif
adjustable.sharpness = scaleTo100(setup.sharpness);
- adjustable.gamma = scaleTo100(setup.gamma);
adjustable.resolution = scaleTo100(setup.resolution);
adjustable.artifacts = scaleTo100(setup.artifacts);
adjustable.fringing = scaleTo100(setup.fringing);
@@ -224,12 +230,16 @@ void NTSCFilter::convertToAdjustable(Adjustable& adjustable,
AtariNTSC::Setup NTSCFilter::myCustomSetup = AtariNTSC::TV_Composite;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+#ifdef BLARGG_PALETTE
const std::array NTSCFilter::ourCustomAdjustables = { {
{ "contrast", &myCustomSetup.contrast },
{ "brightness", &myCustomSetup.brightness },
{ "hue", &myCustomSetup.hue },
{ "saturation", &myCustomSetup.saturation },
{ "gamma", &myCustomSetup.gamma },
+#else
+const std::array NTSCFilter::ourCustomAdjustables = { {
+#endif
{ "sharpness", &myCustomSetup.sharpness },
{ "resolution", &myCustomSetup.resolution },
{ "artifacts", &myCustomSetup.artifacts },
diff --git a/src/common/tv_filters/NTSCFilter.hxx b/src/common/tv_filters/NTSCFilter.hxx
index b4a5e0e3d..b4b3aa713 100644
--- a/src/common/tv_filters/NTSCFilter.hxx
+++ b/src/common/tv_filters/NTSCFilter.hxx
@@ -47,12 +47,24 @@ class NTSCFilter
BAD,
CUSTOM
};
+ enum class Adjustables {
+ SHARPNESS,
+ RESOLUTION,
+ ARTIFACTS,
+ FRINGING,
+ BLEEDING,
+ NUM_ADJUSTABLES
+ };
/* Normally used in conjunction with custom mode, contains all
aspects currently adjustable in NTSC TV emulation. */
struct Adjustable {
+ #ifdef BLARGG_PALETTE
uInt32 hue, saturation, contrast, brightness, gamma,
sharpness, resolution, artifacts, fringing, bleed;
+ #else
+ uInt32 sharpness, resolution, artifacts, fringing, bleed;
+ #endif
};
public:
@@ -86,10 +98,12 @@ class NTSCFilter
// 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();
+ void selectAdjustable(int direction,
+ string& text, string& valueText, Int32& value);
+ void changeAdjustable(int adjustable, int direction,
+ string& text, string& valueText, Int32& newValue);
+ void changeCurrentAdjustable(int direction,
+ string& text, string& valueText, Int32& newValue);
// Load and save NTSC-related settings
void loadConfig(const Settings& settings);
@@ -139,7 +153,11 @@ class NTSCFilter
float* value{nullptr};
};
uInt32 myCurrentAdjustable{0};
+ #ifdef BLARGG_PALETTE
static const std::array ourCustomAdjustables;
+ #else
+ static const std::array ourCustomAdjustables;
+ #endif
private:
// Following constructors and assignment operators not supported
diff --git a/src/debugger/Debugger.cxx b/src/debugger/Debugger.cxx
index b46570a6a..cdb039491 100644
--- a/src/debugger/Debugger.cxx
+++ b/src/debugger/Debugger.cxx
@@ -293,9 +293,10 @@ void Debugger::loadAllStates()
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-int Debugger::step()
+int Debugger::step(bool save)
{
- saveOldState();
+ if(save)
+ saveOldState();
uInt64 startCycle = mySystem.cycles();
@@ -303,7 +304,8 @@ int Debugger::step()
myOSystem.console().tia().updateScanlineByStep().flushLineCache();
lockSystem();
- addState("step");
+ if(save)
+ addState("step");
return int(mySystem.cycles() - startCycle);
}
diff --git a/src/debugger/Debugger.hxx b/src/debugger/Debugger.hxx
index d063f2e90..6083d556a 100644
--- a/src/debugger/Debugger.hxx
+++ b/src/debugger/Debugger.hxx
@@ -306,7 +306,7 @@ class Debugger : public DialogContainer
*/
void setQuitState();
- int step();
+ int step(bool save = true);
int trace();
void nextScanline(int lines);
void nextFrame(int frames);
diff --git a/src/debugger/DebuggerParser.cxx b/src/debugger/DebuggerParser.cxx
index da3b0bc5f..49692ef8a 100644
--- a/src/debugger/DebuggerParser.cxx
+++ b/src/debugger/DebuggerParser.cxx
@@ -30,6 +30,7 @@
#include "M6502.hxx"
#include "Expression.hxx"
#include "FSNode.hxx"
+#include "OSystem.hxx"
#include "Settings.hxx"
#include "PromptWidget.hxx"
#include "RomWidget.hxx"
@@ -1743,7 +1744,7 @@ void DebuggerParser::executeRunTo()
bool done = false;
do {
- debugger.step();
+ debugger.step(false);
// Update romlist to point to current PC
int pcline = cartdbg.addressToLine(debugger.cpuDebug().pc());
@@ -1777,22 +1778,32 @@ void DebuggerParser::executeRunToPc()
uInt32 count = 0;
bool done = false;
+ constexpr uInt32 max_iterations = 1000000;
+ // Create a progress dialog box to show the progress searching through the
+ // disassembly, since this may be a time-consuming operation
+ ostringstream buf;
+ buf << "RunTo PC searching through " << max_iterations << " instructions";
+ ProgressDialog progress(debugger.baseDialog(), debugger.lfont(), buf.str());
+ progress.setRange(0, max_iterations, 5);
+
do {
- debugger.step();
+ debugger.step(false);
// Update romlist to point to current PC
int pcline = cartdbg.addressToLine(debugger.cpuDebug().pc());
done = (pcline >= 0) && (list[pcline].address == args[0]);
- } while(!done && ++count < list.size());
+ progress.setProgress(count);
+ } while(!done && ++count < max_iterations/*list.size()*/);
+ progress.close();
if(done)
commandResult
- << "set PC to " << Base::HEX4 << args[0] << " in "
- << dec << count << " disassembled instructions";
+ << "Set PC to $" << Base::HEX4 << args[0] << " in "
+ << dec << count << " instructions";
else
commandResult
- << "PC " << Base::HEX4 << args[0] << " not reached or found in "
- << dec << count << " disassembled instructions";
+ << "PC $" << Base::HEX4 << args[0] << " not reached or found in "
+ << dec << count << " instructions";
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -1930,9 +1941,23 @@ void DebuggerParser::executeStepwhile()
}
Expression* expr = YaccParser::getResult();
int ncycles = 0;
+ uInt32 count = 0;
+ constexpr uInt32 max_iterations = 1000000;
+
+ // Create a progress dialog box to show the progress searching through the
+ // disassembly, since this may be a time-consuming operation
+ ostringstream buf;
+ buf << "stepwhile running through " << max_iterations << " disassembled instructions";
+ ProgressDialog progress(debugger.baseDialog(), debugger.lfont(), buf.str());
+ progress.setRange(0, max_iterations, 5);
+
do {
- ncycles += debugger.step();
- } while (expr->evaluate());
+ ncycles += debugger.step(false);
+
+ progress.setProgress(count);
+ } while (expr->evaluate() && ++count < max_iterations);
+
+ progress.close();
commandResult << "executed " << ncycles << " cycles";
}
diff --git a/src/debugger/DiStella.cxx b/src/debugger/DiStella.cxx
index 8aff0b568..c77d1eabf 100644
--- a/src/debugger/DiStella.cxx
+++ b/src/debugger/DiStella.cxx
@@ -1179,7 +1179,7 @@ void DiStella::outputColors()
color = SECAM_COLOR[(byte >> 1) & 0x7];
myDisasmBuf << "$" << Base::HEX1 << (byte >> 4) << "|" << color;
}
- myDisasmBuf << std::setw(16 - color.length()) << std::setfill(' ');
+ myDisasmBuf << std::setw(int(16 - color.length())) << std::setfill(' ');
// output address
myDisasmBuf << "; $" << Base::HEX4 << myPC + myOffset << " "
diff --git a/src/debugger/gui/CartARWidget.cxx b/src/debugger/gui/CartARWidget.cxx
index 6037849f6..ec4c4037a 100644
--- a/src/debugger/gui/CartARWidget.cxx
+++ b/src/debugger/gui/CartARWidget.cxx
@@ -16,6 +16,9 @@
//============================================================================
#include "CartAR.hxx"
+#include "OSystem.hxx"
+#include "Debugger.hxx"
+#include "CartDebug.hxx"
#include "PopUpWidget.hxx"
#include "CartARWidget.hxx"
diff --git a/src/debugger/gui/CartCMWidget.cxx b/src/debugger/gui/CartCMWidget.cxx
index 8fa72f0bb..e4d11ba55 100644
--- a/src/debugger/gui/CartCMWidget.cxx
+++ b/src/debugger/gui/CartCMWidget.cxx
@@ -16,6 +16,7 @@
//============================================================================
#include "CartCM.hxx"
+#include "OSystem.hxx"
#include "Debugger.hxx"
#include "CartDebug.hxx"
#include "RiotDebug.hxx"
diff --git a/src/debugger/gui/CartCTYWidget.cxx b/src/debugger/gui/CartCTYWidget.cxx
index 76230fa21..659fb9bea 100644
--- a/src/debugger/gui/CartCTYWidget.cxx
+++ b/src/debugger/gui/CartCTYWidget.cxx
@@ -15,6 +15,7 @@
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
+#include "OSystem.hxx"
#include "Debugger.hxx"
#include "CartDebug.hxx"
#include "CartCTY.hxx"
diff --git a/src/debugger/gui/CartDebugWidget.hxx b/src/debugger/gui/CartDebugWidget.hxx
index 7bdcbf472..27c3befa5 100644
--- a/src/debugger/gui/CartDebugWidget.hxx
+++ b/src/debugger/gui/CartDebugWidget.hxx
@@ -19,7 +19,6 @@
#define CART_DEBUG_WIDGET_HXX
class GuiObject;
-class ButtonWidget;
class StringListWidget;
namespace GUI {
@@ -29,8 +28,6 @@ namespace GUI {
#include "Base.hxx" // not needed here, but all child classes need it
#include "Command.hxx"
#include "Widget.hxx"
-#include "Debugger.hxx"
-#include "CartDebug.hxx"
class CartDebugWidget : public Widget, public CommandSender
{
diff --git a/src/debugger/gui/CartE0Widget.cxx b/src/debugger/gui/CartE0Widget.cxx
index 12205c463..08ccc802a 100644
--- a/src/debugger/gui/CartE0Widget.cxx
+++ b/src/debugger/gui/CartE0Widget.cxx
@@ -49,7 +49,7 @@ string CartridgeE0Widget::romDescription()
info << "Segment #" << seg << " accessible @ $"
<< Common::Base::HEX4 << (ADDR_BASE | segmentOffset)
- << " - $" << (ADDR_BASE | segmentOffset + /*myCart.myBankSize - 1*/ 0x3FF) << ",\n";
+ << " - $" << (ADDR_BASE | (segmentOffset + /*myCart.myBankSize - 1*/ 0x3FF)) << ",\n";
if (seg < 3)
info << " Hotspots " << hotspotStr(0, seg, true) << " - " << hotspotStr(7, seg, true) << "\n";
else
diff --git a/src/debugger/gui/CartEnhancedWidget.cxx b/src/debugger/gui/CartEnhancedWidget.cxx
index f864a21c0..0bf38f529 100644
--- a/src/debugger/gui/CartEnhancedWidget.cxx
+++ b/src/debugger/gui/CartEnhancedWidget.cxx
@@ -15,8 +15,10 @@
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
-
#include "PopUpWidget.hxx"
+#include "OSystem.hxx"
+#include "Debugger.hxx"
+#include "CartDebug.hxx"
#include "CartEnhanced.hxx"
#include "CartEnhancedWidget.hxx"
diff --git a/src/debugger/gui/CartEnhancedWidget.hxx b/src/debugger/gui/CartEnhancedWidget.hxx
index 968a4bbf0..a367e8def 100644
--- a/src/debugger/gui/CartEnhancedWidget.hxx
+++ b/src/debugger/gui/CartEnhancedWidget.hxx
@@ -25,6 +25,7 @@ namespace GUI {
class Font;
}
+#include "Variant.hxx"
#include "CartDebugWidget.hxx"
class CartridgeEnhancedWidget : public CartDebugWidget
diff --git a/src/debugger/gui/ControllerWidget.hxx b/src/debugger/gui/ControllerWidget.hxx
index e552be284..d14c1ba69 100644
--- a/src/debugger/gui/ControllerWidget.hxx
+++ b/src/debugger/gui/ControllerWidget.hxx
@@ -23,6 +23,7 @@ class ButtonWidget;
#include "Font.hxx"
#include "Widget.hxx"
+#include "OSystem.hxx"
#include "Console.hxx"
#include "Command.hxx"
#include "ControlLowLevel.hxx"
diff --git a/src/debugger/gui/DataGridWidget.cxx b/src/debugger/gui/DataGridWidget.cxx
index 6b663609c..719eebef2 100644
--- a/src/debugger/gui/DataGridWidget.cxx
+++ b/src/debugger/gui/DataGridWidget.cxx
@@ -18,6 +18,7 @@
#include "Widget.hxx"
#include "Dialog.hxx"
#include "Font.hxx"
+#include "OSystem.hxx"
#include "Debugger.hxx"
#include "FrameBuffer.hxx"
#include "FBSurface.hxx"
diff --git a/src/debugger/gui/DebuggerDialog.cxx b/src/debugger/gui/DebuggerDialog.cxx
index 5d8404d06..6674311f6 100644
--- a/src/debugger/gui/DebuggerDialog.cxx
+++ b/src/debugger/gui/DebuggerDialog.cxx
@@ -47,6 +47,8 @@
#include "OptionsDialog.hxx"
#include "StateManager.hxx"
#include "FrameManager.hxx"
+#include "OSystem.hxx"
+#include "Console.hxx"
#include "DebuggerDialog.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -68,6 +70,11 @@ DebuggerDialog::DebuggerDialog(OSystem& osystem, DialogContainer& parent,
Menu::AppMode::debugger);
}
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+DebuggerDialog::~DebuggerDialog()
+{
+}
+
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DebuggerDialog::loadConfig()
{
diff --git a/src/debugger/gui/DebuggerDialog.hxx b/src/debugger/gui/DebuggerDialog.hxx
index b66ae37a6..f38e8b2dc 100644
--- a/src/debugger/gui/DebuggerDialog.hxx
+++ b/src/debugger/gui/DebuggerDialog.hxx
@@ -33,14 +33,16 @@ class TiaOutputWidget;
class TiaZoomWidget;
class CartDebugWidget;
class CartRamWidget;
+class OptionsDialog;
+namespace GUI {
+ class MessageBox;
+}
namespace Common {
struct Rect;
}
#include "Dialog.hxx"
-#include "MessageBox.hxx"
-#include "OptionsDialog.hxx"
class DebuggerDialog : public Dialog
{
@@ -55,7 +57,7 @@ class DebuggerDialog : public Dialog
DebuggerDialog(OSystem& osystem, DialogContainer& parent,
int x, int y, int w, int h);
- virtual ~DebuggerDialog() = default;
+ virtual ~DebuggerDialog();
const GUI::Font& lfont() const { return *myLFont; }
const GUI::Font& nfont() const { return *myNFont; }
diff --git a/src/debugger/gui/PromptWidget.cxx b/src/debugger/gui/PromptWidget.cxx
index b803adc17..eb27f5258 100644
--- a/src/debugger/gui/PromptWidget.cxx
+++ b/src/debugger/gui/PromptWidget.cxx
@@ -20,6 +20,7 @@
#include "Font.hxx"
#include "StellaKeys.hxx"
#include "Version.hxx"
+#include "OSystem.hxx"
#include "Debugger.hxx"
#include "DebuggerDialog.hxx"
#include "DebuggerParser.hxx"
diff --git a/src/debugger/gui/RiotRamWidget.cxx b/src/debugger/gui/RiotRamWidget.cxx
index 2666182ec..5f3d5c0ab 100644
--- a/src/debugger/gui/RiotRamWidget.cxx
+++ b/src/debugger/gui/RiotRamWidget.cxx
@@ -15,6 +15,7 @@
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
+#include "OSystem.hxx"
#include "Debugger.hxx"
#include "CartDebug.hxx"
diff --git a/src/debugger/gui/RomListWidget.cxx b/src/debugger/gui/RomListWidget.cxx
index 64ca2df9d..6e450e334 100644
--- a/src/debugger/gui/RomListWidget.cxx
+++ b/src/debugger/gui/RomListWidget.cxx
@@ -16,6 +16,7 @@
//============================================================================
#include "bspf.hxx"
+#include "OSystem.hxx"
#include "Debugger.hxx"
#include "DiStella.hxx"
#include "Widget.hxx"
diff --git a/src/debugger/gui/RomWidget.cxx b/src/debugger/gui/RomWidget.cxx
index 3279ca5d9..010ae5f0b 100644
--- a/src/debugger/gui/RomWidget.cxx
+++ b/src/debugger/gui/RomWidget.cxx
@@ -15,6 +15,7 @@
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
+#include "OSystem.hxx"
#include "Settings.hxx"
#include "Debugger.hxx"
#include "CartDebug.hxx"
@@ -199,7 +200,8 @@ void RomWidget::runtoPC(int disasm_line)
{
ostringstream command;
command << "runtopc #" << list[disasm_line].address;
- instance().debugger().run(command.str());
+ string msg = instance().debugger().run(command.str());
+ instance().frameBuffer().showMessage(msg);
}
}
diff --git a/src/emucore/AtariVox.cxx b/src/emucore/AtariVox.cxx
index 3314ac08c..700789352 100644
--- a/src/emucore/AtariVox.cxx
+++ b/src/emucore/AtariVox.cxx
@@ -36,6 +36,11 @@ AtariVox::AtariVox(Jack jack, const Event& event, const System& system,
setPin(DigitalPin::Four, true);
}
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+AtariVox::~AtariVox()
+{
+}
+
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool AtariVox::read(DigitalPin pin)
{
diff --git a/src/emucore/AtariVox.hxx b/src/emucore/AtariVox.hxx
index b21ec38b0..e0c2e72c7 100644
--- a/src/emucore/AtariVox.hxx
+++ b/src/emucore/AtariVox.hxx
@@ -19,10 +19,10 @@
#define ATARIVOX_HXX
class OSystem;
+class SerialPort;
#include "Control.hxx"
#include "SaveKey.hxx"
-#include "SerialPort.hxx"
/**
Richard Hutchinson's AtariVox "controller": A speech synthesizer and
@@ -49,7 +49,7 @@ class AtariVox : public SaveKey
AtariVox(Jack jack, const Event& event, const System& system,
const string& portname, const string& eepromfile,
const onMessageCallback& callback);
- virtual ~AtariVox() = default;
+ virtual ~AtariVox();
public:
using Controller::read;
diff --git a/src/emucore/Cart.hxx b/src/emucore/Cart.hxx
index 6fbf1a68d..b04a95f10 100644
--- a/src/emucore/Cart.hxx
+++ b/src/emucore/Cart.hxx
@@ -23,15 +23,18 @@ class Properties;
class CartDebugWidget;
class CartRamWidget;
class GuiObject;
+class Settings;
+
+#include
#include "bspf.hxx"
#include "Device.hxx"
-#include "Settings.hxx"
#ifdef DEBUGGER_SUPPORT
- #include "Font.hxx"
+ namespace GUI {
+ class Font;
+ }
#endif
-
/**
A cartridge is a device which contains the machine code for a
game and handles any bankswitching performed by the cartridge.
diff --git a/src/emucore/Cart3EPlus.hxx b/src/emucore/Cart3EPlus.hxx
index c2ce64cd8..fe6a0a263 100644
--- a/src/emucore/Cart3EPlus.hxx
+++ b/src/emucore/Cart3EPlus.hxx
@@ -24,7 +24,6 @@ class System;
#include "Cart3E.hxx"
#ifdef DEBUGGER_SUPPORT
-class Cartridge3EPlusWidget;
#include "Cart3EPlusWidget.hxx"
#endif
diff --git a/src/emucore/Cart3EX.hxx b/src/emucore/Cart3EX.hxx
index 7df53593e..c949a0c9c 100644
--- a/src/emucore/Cart3EX.hxx
+++ b/src/emucore/Cart3EX.hxx
@@ -19,7 +19,9 @@
#define CARTRIDGE3EX_HXX
class System;
+class Settings;
+#include "bspf.hxx"
#include "Cart3E.hxx"
/**
@@ -30,39 +32,38 @@ class System;
class Cartridge3EX : public Cartridge3E
{
+ public:
+ /**
+ Create a new cartridge using the specified image and size
-public:
- /**
- Create a new cartridge using the specified image and size
+ @param image Pointer to the ROM image
+ @param size The size of the ROM image
+ @param md5 The md5sum of the ROM image
+ @param settings A reference to the various settings (read-only)
+ */
+ Cartridge3EX(const ByteBuffer& image, size_t size, const string& md5,
+ const Settings& settings);
+ virtual ~Cartridge3EX() = default;
- @param image Pointer to the ROM image
- @param size The size of the ROM image
- @param md5 The md5sum of the ROM image
- @param settings A reference to the various settings (read-only)
- */
- Cartridge3EX(const ByteBuffer& image, size_t size, const string& md5,
- const Settings& settings);
- virtual ~Cartridge3EX() = default;
+ public:
+ /**
+ Get a descriptor for the device name (used in error checking).
-public:
- /**
- Get a descriptor for the device name (used in error checking).
+ @return The name of the object
+ */
+ string name() const override { return "Cartridge3EX"; }
- @return The name of the object
- */
- string name() const override { return "Cartridge3EX"; }
+ private:
+ // RAM size
+ static constexpr size_t RAM_SIZE = RAM_BANKS << (BANK_SHIFT - 1); // = 256K = 0x40000;
-private:
- // RAM size
- static constexpr size_t RAM_SIZE = RAM_BANKS << (BANK_SHIFT - 1); // = 256K = 0x40000;
-
-private:
- // Following constructors and assignment operators not supported
- Cartridge3EX() = delete;
- Cartridge3EX(const Cartridge3EX&) = delete;
- Cartridge3EX(Cartridge3EX&&) = delete;
- Cartridge3EX& operator=(const Cartridge3EX&) = delete;
- Cartridge3EX& operator=(Cartridge3EX&&) = delete;
+ private:
+ // Following constructors and assignment operators not supported
+ Cartridge3EX() = delete;
+ Cartridge3EX(const Cartridge3EX&) = delete;
+ Cartridge3EX(Cartridge3EX&&) = delete;
+ Cartridge3EX& operator=(const Cartridge3EX&) = delete;
+ Cartridge3EX& operator=(Cartridge3EX&&) = delete;
};
#endif
diff --git a/src/emucore/CartAR.cxx b/src/emucore/CartAR.cxx
index 2d8b204b6..a0eea7486 100644
--- a/src/emucore/CartAR.cxx
+++ b/src/emucore/CartAR.cxx
@@ -17,6 +17,7 @@
#include "M6502.hxx"
#include "System.hxx"
+#include "Settings.hxx"
#include "CartAR.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/src/emucore/CartDPC.cxx b/src/emucore/CartDPC.cxx
index 481e385be..bc8962b1b 100644
--- a/src/emucore/CartDPC.cxx
+++ b/src/emucore/CartDPC.cxx
@@ -15,6 +15,7 @@
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
+#include "Settings.hxx"
#include "System.hxx"
#include "AudioSettings.hxx"
#include "CartDPC.hxx"
diff --git a/src/emucore/CartDetector.cxx b/src/emucore/CartDetector.cxx
index 6c68bf6e4..976d56579 100644
--- a/src/emucore/CartDetector.cxx
+++ b/src/emucore/CartDetector.cxx
@@ -62,6 +62,7 @@
#include "MD5.hxx"
#include "Props.hxx"
#include "Logger.hxx"
+#include "OSystem.hxx"
#include "CartDetector.hxx"
diff --git a/src/emucore/CartDetector.hxx b/src/emucore/CartDetector.hxx
index 706731b0f..9ff193c87 100644
--- a/src/emucore/CartDetector.hxx
+++ b/src/emucore/CartDetector.hxx
@@ -20,10 +20,10 @@
class Cartridge;
class Properties;
+class Settings;
#include "Bankswitch.hxx"
#include "bspf.hxx"
-#include "Settings.hxx"
/**
Auto-detect cart type based on various attributes (file size, signatures,
diff --git a/src/emucore/CartEnhanced.cxx b/src/emucore/CartEnhanced.cxx
index f5c38c9a3..27fa425b5 100644
--- a/src/emucore/CartEnhanced.cxx
+++ b/src/emucore/CartEnhanced.cxx
@@ -35,12 +35,15 @@ CartridgeEnhanced::CartridgeEnhanced(const ByteBuffer& image, size_t size,
void CartridgeEnhanced::install(System& system)
{
// limit banked RAM size to the size of one RAM bank
- uInt32 ramSize = myRamBankCount > 0 ? 1 << (myBankShift - 1) : uInt32(myRamSize);
+ const uInt32 ramSize = myRamBankCount > 0 ? 1 << (myBankShift - 1) : uInt32(myRamSize);
// calculate bank switching and RAM sizes and masks
myBankSize = 1 << myBankShift; // e.g. = 2 ^ 12 = 4K = 0x1000
myBankMask = myBankSize - 1; // e.g. = 0x0FFF
- myBankSegs = 1 << (MAX_BANK_SHIFT - myBankShift); // e.g. = 1
+ // Either the bankswitching supports multiple segments
+ // or the ROM is < 4K (-> 1 segment)
+ myBankSegs = std::min(1 << (MAX_BANK_SHIFT - myBankShift),
+ int(mySize) / myBankSize); // e.g. = 1
myRomOffset = myRamBankCount > 0 ? 0 : uInt32(myRamSize) * 2;
myRamMask = ramSize - 1; // e.g. = 0xFFFF (doesn't matter for RAM size 0)
myWriteOffset = myRamWpHigh ? ramSize : 0; // e.g. = 0x0000
@@ -52,7 +55,8 @@ void CartridgeEnhanced::install(System& system)
myCurrentSegOffset = make_unique(myBankSegs);
// Allocate array for the RAM area
- myRAM = make_unique(myRamSize);
+ if(myRamSize > 0)
+ myRAM = make_unique(myRamSize);
mySystem = &system;
@@ -67,7 +71,7 @@ void CartridgeEnhanced::install(System& system)
access.type = System::PageAccessType::WRITE;
for(uInt16 addr = ROM_OFFSET + myWriteOffset; addr < ROM_OFFSET + myWriteOffset + myRamSize; addr += System::PAGE_SIZE)
{
- uInt16 offset = addr & myRamMask;
+ const uInt16 offset = addr & myRamMask;
access.directPokeBase = &myRAM[offset];
access.romAccessBase = &myRomAccessBase[myWriteOffset + offset];
@@ -81,7 +85,7 @@ void CartridgeEnhanced::install(System& system)
access.directPokeBase = nullptr;
for(uInt16 addr = ROM_OFFSET + myReadOffset; addr < ROM_OFFSET + myReadOffset + myRamSize; addr += System::PAGE_SIZE)
{
- uInt16 offset = addr & myRamMask;
+ const uInt16 offset = addr & myRamMask;
access.directPeekBase = &myRAM[offset];
access.romAccessBase = &myRomAccessBase[myReadOffset + offset];
@@ -101,7 +105,8 @@ void CartridgeEnhanced::install(System& system)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeEnhanced::reset()
{
- initializeRAM(myRAM.get(), myRamSize);
+ if(myRamSize > 0)
+ initializeRAM(myRAM.get(), myRamSize);
initializeStartBank(getStartBank());
@@ -112,7 +117,7 @@ void CartridgeEnhanced::reset()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 CartridgeEnhanced::peek(uInt16 address)
{
- uInt16 peekAddress = address;
+ const uInt16 peekAddress = address;
// hotspots in TIA range are reacting to pokes only
if (hotspot() >= 0x80)
@@ -152,7 +157,7 @@ bool CartridgeEnhanced::poke(uInt16 address, uInt8 value)
if(myRamSize > 0)
{
// Code should never get here (System::PageAccess::directPoke() handles this)
- uInt16 pokeAddress = address;
+ const uInt16 pokeAddress = address;
if(isRamBank(address))
{
@@ -188,20 +193,20 @@ bool CartridgeEnhanced::bank(uInt16 bank, uInt16 segment)
{
if(bankLocked()) return false;
- uInt16 segmentOffset = segment << myBankShift;
+ const uInt16 segmentOffset = segment << myBankShift;
if(myRamBankCount == 0 || bank < romBankCount())
{
// Setup ROM bank
- uInt16 romBank = bank % romBankCount();
+ const uInt16 romBank = bank % romBankCount();
// Remember what bank is in this segment
- uInt32 bankOffset = myCurrentSegOffset[segment] = romBank << myBankShift;
- uInt16 hotspot = this->hotspot();
+ const uInt32 bankOffset = myCurrentSegOffset[segment] = romBank << myBankShift;
+ const uInt16 hotspot = this->hotspot();
uInt16 hotSpotAddr;
// Skip extra RAM; if existing it is only mapped into first segment
- uInt16 fromAddr = (ROM_OFFSET + segmentOffset + (segment == 0 ? myRomOffset : 0)) & ~System::PAGE_MASK;
+ const uInt16 fromAddr = (ROM_OFFSET + segmentOffset + (segment == 0 ? myRomOffset : 0)) & ~System::PAGE_MASK;
// for ROMs < 4_KB, the whole address space will be mapped.
- uInt16 toAddr = (ROM_OFFSET + segmentOffset + (mySize < 4_KB ? 4_KB : myBankSize)) & ~System::PAGE_MASK;
+ const uInt16 toAddr = (ROM_OFFSET + segmentOffset + (mySize < 4_KB ? 4_KB : myBankSize)) & ~System::PAGE_MASK;
if(hotspot & 0x1000)
hotSpotAddr = (hotspot & ~System::PAGE_MASK);
@@ -212,7 +217,7 @@ bool CartridgeEnhanced::bank(uInt16 bank, uInt16 segment)
// Setup the page access methods for the current bank
for(uInt16 addr = fromAddr; addr < toAddr; addr += System::PAGE_SIZE)
{
- uInt32 offset = bankOffset + (addr & myBankMask);
+ const uInt32 offset = bankOffset + (addr & myBankMask);
if(myDirectPeek && addr != hotSpotAddr)
access.directPeekBase = &myImage[offset];
@@ -227,9 +232,9 @@ bool CartridgeEnhanced::bank(uInt16 bank, uInt16 segment)
else
{
// Setup RAM bank
- uInt16 ramBank = (bank - romBankCount()) % myRamBankCount;
+ const uInt16 ramBank = (bank - romBankCount()) % myRamBankCount;
// The RAM banks follow the ROM banks and are half the size of a ROM bank
- uInt32 bankOffset = uInt32(mySize) + (ramBank << (myBankShift - 1));
+ const uInt32 bankOffset = uInt32(mySize) + (ramBank << (myBankShift - 1));
// Remember what bank is in this segment
myCurrentSegOffset[segment] = uInt32(mySize) + (ramBank << myBankShift);
@@ -241,7 +246,7 @@ bool CartridgeEnhanced::bank(uInt16 bank, uInt16 segment)
for(uInt16 addr = fromAddr; addr < toAddr; addr += System::PAGE_SIZE)
{
- uInt32 offset = bankOffset + (addr & myRamMask);
+ const uInt32 offset = bankOffset + (addr & myRamMask);
access.directPokeBase = &myRAM[offset - mySize];
access.romAccessBase = &myRomAccessBase[offset];
@@ -258,7 +263,7 @@ bool CartridgeEnhanced::bank(uInt16 bank, uInt16 segment)
for(uInt16 addr = fromAddr; addr < toAddr; addr += System::PAGE_SIZE)
{
- uInt32 offset = bankOffset + (addr & myRamMask);
+ const uInt32 offset = bankOffset + (addr & myRamMask);
access.directPeekBase = &myRAM[offset - mySize];
access.romAccessBase = &myRomAccessBase[offset];
diff --git a/src/emucore/CompuMate.cxx b/src/emucore/CompuMate.cxx
index b39e46ab4..a3a0367cc 100644
--- a/src/emucore/CompuMate.cxx
+++ b/src/emucore/CompuMate.cxx
@@ -15,6 +15,9 @@
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
+#include "Console.hxx"
+#include "Event.hxx"
+#include "System.hxx"
#include "CompuMate.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/src/emucore/CompuMate.hxx b/src/emucore/CompuMate.hxx
index ff0e0f781..8b8d772e8 100644
--- a/src/emucore/CompuMate.hxx
+++ b/src/emucore/CompuMate.hxx
@@ -18,11 +18,12 @@
#ifndef COMPUMATE_HXX
#define COMPUMATE_HXX
+class Console;
+class Event;
+class System;
+
#include "bspf.hxx"
-#include "CartCM.hxx"
#include "Control.hxx"
-#include "Event.hxx"
-#include "Console.hxx"
/**
Handler for SpectraVideo CompuMate bankswitched games.
diff --git a/src/emucore/Console.cxx b/src/emucore/Console.cxx
index 29fe2bfac..1e796a0bd 100644
--- a/src/emucore/Console.cxx
+++ b/src/emucore/Console.cxx
@@ -24,6 +24,7 @@
#include "Cart.hxx"
#include "Control.hxx"
#include "Cart.hxx"
+#include "CartCM.hxx"
#include "Driving.hxx"
#include "Event.hxx"
#include "EventHandler.hxx"
@@ -81,13 +82,6 @@ Console::Console(OSystem& osystem, unique_ptr& cart,
myCart(std::move(cart)),
myAudioSettings(audioSettings)
{
- // Load user-defined palette for this ROM
- loadUserPalette();
-
- // Generate custom palette
- generateCustomPalette(0);
- generateCustomPalette(1);
-
// Create subsystems for the console
my6502 = make_unique(myOSystem.settings());
myRiot = make_unique(*this, myOSystem.settings());
@@ -355,23 +349,20 @@ bool Console::load(Serializer& in)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void Console::toggleFormat(int direction)
+void Console::selectFormat(int direction)
{
string saveformat, message;
- uInt32 format = myCurrentFormat;
+ Int32 format = myCurrentFormat;
- if(direction == 1)
- format = (myCurrentFormat + 1) % 7;
- else if(direction == -1)
- format = myCurrentFormat > 0 ? (myCurrentFormat - 1) : 6;
+ format = BSPF::clampw(format + direction, 0, 6);
- setFormat(format);
+ setFormat(format, true);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void Console::setFormat(uInt32 format)
+void Console::setFormat(uInt32 format, bool force)
{
- if(myCurrentFormat == format)
+ if(!force && myCurrentFormat == format)
return;
string saveformat, message;
@@ -382,7 +373,7 @@ void Console::setFormat(uInt32 format)
{
case 0: // auto-detect
{
- if (myFormatAutodetected) return;
+ if (!force && myFormatAutodetected) return;
myDisplayFormat = formatFromFilename();
if (myDisplayFormat == "AUTO")
@@ -441,7 +432,6 @@ void Console::setFormat(uInt32 format)
myConsoleInfo.DisplayFormat = myDisplayFormat + autodetected;
- setPalette(myOSystem.settings().getString("palette"));
setTIAProperties();
initializeVideo(); // takes care of refreshing the screen
initializeAudio(); // ensure that audio synthesis is set up to match emulation speed
@@ -478,107 +468,20 @@ void Console::enableColorLoss(bool state)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-int Console::getPaletteNum(const string& name) const
-{
- if(name == "z26")
- return PaletteType::Z26;
-
- if(name == "user" && myUserPaletteDefined)
- return PaletteType::User;
-
- if(name == "custom")
- return PaletteType::Custom;
-
- return PaletteType::Standard;
-}
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void Console::togglePalette()
-{
- string palette, message;
- palette = myOSystem.settings().getString("palette");
-
- if(palette == "standard") // switch to z26
- {
- palette = "z26";
- message = "Z26 palette";
- }
- else if(palette == "z26") // switch to user or standard
- {
- // If we have a user-defined palette, it will come next in
- // the sequence; otherwise loop back to the standard one
- if(myUserPaletteDefined)
- {
- palette = "user";
- message = "User-defined palette";
- }
- else
- {
- palette = "custom";
- message = "Custom palette";
- }
- }
- else if(palette == "user") // switch to custom
- {
- palette = "custom";
- message = "Custom palette";
- }
- else // switch to standard mode if we get this far
- {
- palette = "standard";
- message = "Standard Stella palette";
- }
-
- myOSystem.settings().setValue("palette", palette);
- myOSystem.frameBuffer().showMessage(message);
-
- setPalette(palette);
-}
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void Console::setPalette(const string& type)
-{
- // Look at all the palettes, since we don't know which one is
- // currently active
- static constexpr BSPF::array2D palettes = {{
- { &ourNTSCPalette, &ourPALPalette, &ourSECAMPalette },
- { &ourNTSCPaletteZ26, &ourPALPaletteZ26, &ourSECAMPaletteZ26 },
- { &ourUserNTSCPalette, &ourUserPALPalette, &ourUserSECAMPalette },
- { &ourCustomNTSCPalette, &ourCustomPALPalette, &ourSECAMPalette }
- }};
-
- // See which format we should be using
- int paletteNum = getPaletteNum(type);
-
- if(paletteNum == PaletteType::Custom)
- {
-
- }
-
- // Now consider the current display format
- const PaletteArray* palette =
- (myDisplayFormat.compare(0, 3, "PAL") == 0) ? palettes[paletteNum][1] :
- (myDisplayFormat.compare(0, 5, "SECAM") == 0) ? palettes[paletteNum][2] :
- palettes[paletteNum][0];
-
- myOSystem.frameBuffer().setTIAPalette(*palette);
-
- if(myTIA->usingFixedColors())
- myTIA->enableFixedColors(true);
-}
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void Console::toggleInter()
+void Console::toggleInter(bool toggle)
{
bool enabled = myOSystem.settings().getBool("tia.inter");
- myOSystem.settings().setValue("tia.inter", !enabled);
+ if(toggle)
+ enabled = !enabled;
+
+ myOSystem.settings().setValue("tia.inter", enabled);
// ... and apply potential setting changes to the TIA surface
myOSystem.frameBuffer().tiaSurface().updateSurfaceSettings();
ostringstream ss;
- ss << "Interpolation " << (!enabled ? "enabled" : "disabled");
+ ss << "Interpolation " << (enabled ? "enabled" : "disabled");
myOSystem.frameBuffer().showMessage(ss.str());
}
@@ -622,36 +525,20 @@ void Console::changePhosphor(int direction)
{
int blend = BSPF::stringToInt(myProperties.get(PropType::Display_PPBlend));
- if(direction == +1) // increase blend
- {
- if(blend >= 100)
- {
- myOSystem.frameBuffer().showMessage("Phosphor blend at maximum");
- myOSystem.frameBuffer().tiaSurface().enablePhosphor(true, 100);
- return;
- }
- else
- blend = std::min(blend+2, 100);
- }
- else if(direction == -1) // decrease blend
- {
- if(blend <= 2)
- {
- myOSystem.frameBuffer().showMessage("Phosphor blend at minimum");
- myOSystem.frameBuffer().tiaSurface().enablePhosphor(true, 0);
- return;
- }
- else
- blend = std::max(blend-2, 0);
- }
- else
- return;
+ blend = BSPF::clamp(blend + direction * 2, 0, 100);
+ myOSystem.frameBuffer().tiaSurface().enablePhosphor(true, blend);
ostringstream val;
val << blend;
myProperties.set(PropType::Display_PPBlend, val.str());
- myOSystem.frameBuffer().showMessage("Phosphor blend " + val.str());
- myOSystem.frameBuffer().tiaSurface().enablePhosphor(true, blend);
+ if(blend)
+ val << "%";
+ else
+ {
+ val.str("");
+ val << "Off";
+ }
+ myOSystem.frameBuffer().showMessage("Phosphor blend", val.str(), blend);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -677,12 +564,7 @@ FBInitStatus Console::initializeVideo(bool full)
myOSystem.frameBuffer().showFrameStats(
myOSystem.settings().getBool(devSettings ? "dev.stats" : "plr.stats"));
- generateCustomPalette(0);
- generateCustomPalette(1);
- generateColorLossPalette();
}
- setPalette(myOSystem.settings().getString("palette"));
-
return fbstatus;
}
@@ -737,41 +619,17 @@ void Console::changeVerticalCenter(int direction)
{
Int32 vcenter = myTIA->vcenter();
- if(direction == +1) // increase vcenter
- {
- if(vcenter >= myTIA->maxVcenter())
- {
- myOSystem.frameBuffer().showMessage("V-Center at maximum");
- return;
- }
- ++vcenter;
- }
- else if(direction == -1) // decrease vcenter
- {
- if (vcenter <= myTIA->minVcenter())
- {
- myOSystem.frameBuffer().showMessage("V-Center at minimum");
- return;
- }
- --vcenter;
- }
- else
- return;
+ vcenter = BSPF::clamp(vcenter + direction, myTIA->minVcenter(), myTIA->maxVcenter());
- ostringstream ss;
+ ostringstream ss, val;
ss << vcenter;
myProperties.set(PropType::Display_VCenter, ss.str());
if (vcenter != myTIA->vcenter()) myTIA->setVcenter(vcenter);
- ss.str("");
- ss << "V-Center ";
- if (!vcenter)
- ss << "default";
- else
- ss << (vcenter > 0 ? "+" : "") << vcenter << "px";
-
- myOSystem.frameBuffer().showMessage(ss.str());
+ val << (vcenter ? vcenter > 0 ? "+" : "" : " ") << vcenter << "px";
+ myOSystem.frameBuffer().showMessage("V-Center", val.str(), vcenter,
+ myTIA->minVcenter(), myTIA->maxVcenter());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -784,30 +642,11 @@ void Console::updateVcenter(Int32 vcenter)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void Console::changeScanlineAdjust(int direction)
+void Console::changeVSizeAdjust(int direction)
{
Int32 newAdjustVSize = myTIA->adjustVSize();
- if (direction != -1 && direction != +1) return;
-
- if(direction == +1) // increase scanline adjustment
- {
- if (newAdjustVSize >= 5)
- {
- myOSystem.frameBuffer().showMessage("V-Size at maximum");
- return;
- }
- newAdjustVSize++;
- }
- else if(direction == -1) // decrease scanline adjustment
- {
- if (newAdjustVSize <= -5)
- {
- myOSystem.frameBuffer().showMessage("V-Size at minimum");
- return;
- }
- newAdjustVSize--;
- }
+ newAdjustVSize = BSPF::clamp(newAdjustVSize + direction, -5, 5);
if (newAdjustVSize != myTIA->adjustVSize()) {
myTIA->setAdjustVSize(newAdjustVSize);
@@ -815,55 +654,10 @@ void Console::changeScanlineAdjust(int direction)
initializeVideo();
}
- ostringstream ss;
+ ostringstream val;
- ss << "V-Size ";
- if (!newAdjustVSize)
- ss << "default";
- else
- ss << (newAdjustVSize > 0 ? "+" : "") << newAdjustVSize << "%";
-
- myOSystem.frameBuffer().showMessage(ss.str());
-}
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void Console::changeColorPhaseShift(int direction)
-{
- const char DEGREE = 0x1c;
- const float NTSC_SHIFT = 26.2F;
- const float PAL_SHIFT = 31.3F; // 360 / 11.5
- const bool isNTSC = myDisplayFormat == "NTSC" || myDisplayFormat == "NTSC50";
- const bool isPAL = myDisplayFormat == "PAL" || myDisplayFormat == "PAL60";
-
- // SECAM is not supported
- if(isNTSC || isPAL)
- {
- const string key = isNTSC ? "phase_ntsc" : "phase_pal";
- const float shift = isNTSC ? NTSC_SHIFT : PAL_SHIFT;
- float phase = myOSystem.settings().getFloat(key);
-
- if(direction == +1) // increase color phase shift
- {
- phase += 0.3F;
- phase = std::min(phase, shift + 4.5F);
- }
- else if(direction == -1) // decrease color phase shift
- {
- phase -= 0.3F;
- phase = std::max(phase, shift - 4.5F);
- }
- myOSystem.settings().setValue(key, phase);
- generateCustomPalette(isNTSC ? 0 : 1);
-
- myOSystem.settings().setValue("palette", "custom");
- setPalette("custom");
-
- ostringstream ss;
- ss << "Color phase shift at "
- << std::fixed << std::setprecision(1) << phase << DEGREE;
-
- myOSystem.frameBuffer().showMessage(ss.str());
- }
+ val << (newAdjustVSize ? newAdjustVSize > 0 ? "+" : "" : " ") << newAdjustVSize << "%";
+ myOSystem.frameBuffer().showMessage("V-Size", val.str(), newAdjustVSize, -5, 5);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -1073,200 +867,6 @@ unique_ptr Console::getControllerPort(const Controller::Type type,
return controller;
}
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void Console::loadUserPalette()
-{
- if (!myOSystem.checkUserPalette(true))
- return;
-
- const string& palette = myOSystem.paletteFile();
- ifstream in(palette, std::ios::binary);
-
- // Now that we have valid data, create the user-defined palettes
- std::array pixbuf; // Temporary buffer for one 24-bit pixel
-
- for(int i = 0; i < 128; i++) // NTSC palette
- {
- in.read(reinterpret_cast(pixbuf.data()), 3);
- uInt32 pixel = (int(pixbuf[0]) << 16) + (int(pixbuf[1]) << 8) + int(pixbuf[2]);
- ourUserNTSCPalette[(i<<1)] = pixel;
- }
- for(int i = 0; i < 128; i++) // PAL palette
- {
- in.read(reinterpret_cast(pixbuf.data()), 3);
- uInt32 pixel = (int(pixbuf[0]) << 16) + (int(pixbuf[1]) << 8) + int(pixbuf[2]);
- ourUserPALPalette[(i<<1)] = pixel;
- }
-
- std::array secam; // All 8 24-bit pixels, plus 8 colorloss pixels
- for(int i = 0; i < 8; i++) // SECAM palette
- {
- in.read(reinterpret_cast(pixbuf.data()), 3);
- uInt32 pixel = (int(pixbuf[0]) << 16) + (int(pixbuf[1]) << 8) + int(pixbuf[2]);
- secam[(i<<1)] = pixel;
- secam[(i<<1)+1] = 0;
- }
- uInt32* ptr = ourUserSECAMPalette.data();
- for(int i = 0; i < 16; ++i)
- {
- const uInt32* s = secam.data();
- for(int j = 0; j < 16; ++j)
- *ptr++ = *s++;
- }
-
- myUserPaletteDefined = true;
-}
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void Console::generateCustomPalette(int type)
-{
- const int NUM_CHROMA = 16;
- const int NUM_LUMA = 8;
- const double SATURATION = 0.25;
-
- double color[NUM_CHROMA][2] = {{0.0}};
-
- if(type == 0)
- {
- // YIQ is YUV shifted by 33°
- const double offset = 33 * (2 * M_PI / 360);
- const double shift = myOSystem.settings().getFloat("phase_ntsc") * (2 * M_PI / 360);
-
- // color 0 is grayscale
- for(int chroma = 1; chroma < NUM_CHROMA; chroma++)
- {
- color[chroma][0] = SATURATION * sin(offset + shift * (chroma - 1));
- color[chroma][1] = SATURATION * sin(offset + shift * (chroma - 1 - M_PI));
- }
-
- for(int chroma = 0; chroma < NUM_CHROMA; chroma++)
- {
- const double I = color[chroma][0];
- const double Q = color[chroma][1];
-
- for(int luma = 0; luma < NUM_LUMA; luma++)
- {
- const double Y = 0.05 + luma / 8.24; // 0.05..~0.90
-
- double R = Y + 0.956 * I + 0.621 * Q;
- double G = Y - 0.272 * I - 0.647 * Q;
- double B = Y - 1.106 * I + 1.703 * Q;
-
- if(R < 0) R = 0;
- if(G < 0) G = 0;
- if(B < 0) B = 0;
-
- R = pow(R, 0.9);
- G = pow(G, 0.9);
- B = pow(B, 0.9);
-
- if(R > 1) R = 1;
- if(G > 1) G = 1;
- if(B > 1) B = 1;
-
- int r = R * 255.F;
- int g = G * 255.F;
- int b = B * 255.F;
-
- ourCustomNTSCPalette[(chroma * NUM_LUMA + luma) << 1] = (r << 16) + (g << 8) + b;
- }
- }
- }
- else
- {
- const double offset = 180 * (2 * M_PI / 360);
- const double shift = myOSystem.settings().getFloat("phase_pal") * (2 * M_PI / 360);
- const double fixedShift = 22.5 * (2 * M_PI / 360);
-
- // colors 0, 1, 14 and 15 are grayscale
- for(int chroma = 2; chroma < NUM_CHROMA - 2; chroma++)
- {
- int idx = NUM_CHROMA - 1 - chroma;
- color[idx][0] = SATURATION * sin(offset - fixedShift * chroma);
- if ((idx & 1) == 0)
- color[idx][1] = SATURATION * sin(offset - shift * (chroma - 3.5) / 2.F);
- else
- color[idx][1] = SATURATION * -sin(offset - shift * chroma / 2.F);
- }
-
- for(int chroma = 0; chroma < NUM_CHROMA; chroma++)
- {
- const double U = color[chroma][0];
- const double V = color[chroma][1];
-
- for(int luma = 0; luma < NUM_LUMA; luma++)
- {
- const double Y = 0.05 + luma / 8.24; // 0.05..~0.90
-
- // Most sources
- double R = Y + 1.403 * V;
- double G = Y - 0.344 * U - 0.714 * V;
- double B = Y + 1.770 * U;
-
- // German Wikipedia, huh???
- //double B = Y + 1 / 0.493 * U;
- //double R = Y + 1 / 0.877 * V;
- //double G = 1.704 * Y - 0.590 * R - 0.194 * B;
-
- if(R < 0) R = 0.0;
- if(G < 0) G = 0.0;
- if(B < 0) B = 0.0;
-
- R = pow(R, 1.2);
- G = pow(G, 1.2);
- B = pow(B, 1.2);
-
- if(R > 1) R = 1;
- if(G > 1) G = 1;
- if(B > 1) B = 1;
-
- int r = R * 255.F;
- int g = G * 255.F;
- int b = B * 255.F;
-
- ourCustomPALPalette[(chroma * NUM_LUMA + luma) << 1] = (r << 16) + (g << 8) + b;
- }
- }
- }
-}
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void Console::generateColorLossPalette()
-{
- // Look at all the palettes, since we don't know which one is
- // currently active
- std::array palette = {
- ourNTSCPalette.data(), ourPALPalette.data(), ourSECAMPalette.data(),
- ourNTSCPaletteZ26.data(), ourPALPaletteZ26.data(), ourSECAMPaletteZ26.data(),
- nullptr, nullptr, nullptr,
- ourCustomNTSCPalette.data(), ourCustomPALPalette.data(), ourSECAMPalette.data(),
- };
- if(myUserPaletteDefined)
- {
- palette[6] = ourUserNTSCPalette.data();
- palette[7] = ourUserPALPalette.data();
- palette[8] = ourUserSECAMPalette.data();
- }
-
- for(int i = 0; i < 3 * PaletteType::NumTypes; ++i)
- {
- if(palette[i] == nullptr)
- continue;
-
- // Fill the odd numbered palette entries with gray values (calculated
- // using the standard RGB -> grayscale conversion formula)
- for(int j = 0; j < 128; ++j)
- {
- const uInt32 pixel = palette[i][(j<<1)];
- const uInt8 r = (pixel >> 16) & 0xff;
- const uInt8 g = (pixel >> 8) & 0xff;
- const uInt8 b = (pixel >> 0) & 0xff;
- const uInt8 sum = static_cast((r * 0.2989) + (g * 0.5870) + (b * 0.1140));
- palette[i][(j<<1)+1] = (sum << 16) + (sum << 8) + sum;
- }
- }
-}
-
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
float Console::getFramerate() const
{
@@ -1338,234 +938,3 @@ void Console::stateChanged(EventHandlerState state)
{
// only the CompuMate used to care about state changes
}
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-PaletteArray Console::ourNTSCPalette = {
- 0x000000, 0, 0x4a4a4a, 0, 0x6f6f6f, 0, 0x8e8e8e, 0,
- 0xaaaaaa, 0, 0xc0c0c0, 0, 0xd6d6d6, 0, 0xececec, 0,
- 0x484800, 0, 0x69690f, 0, 0x86861d, 0, 0xa2a22a, 0,
- 0xbbbb35, 0, 0xd2d240, 0, 0xe8e84a, 0, 0xfcfc54, 0,
- 0x7c2c00, 0, 0x904811, 0, 0xa26221, 0, 0xb47a30, 0,
- 0xc3903d, 0, 0xd2a44a, 0, 0xdfb755, 0, 0xecc860, 0,
- 0x901c00, 0, 0xa33915, 0, 0xb55328, 0, 0xc66c3a, 0,
- 0xd5824a, 0, 0xe39759, 0, 0xf0aa67, 0, 0xfcbc74, 0,
- 0x940000, 0, 0xa71a1a, 0, 0xb83232, 0, 0xc84848, 0,
- 0xd65c5c, 0, 0xe46f6f, 0, 0xf08080, 0, 0xfc9090, 0,
- 0x840064, 0, 0x97197a, 0, 0xa8308f, 0, 0xb846a2, 0,
- 0xc659b3, 0, 0xd46cc3, 0, 0xe07cd2, 0, 0xec8ce0, 0,
- 0x500084, 0, 0x68199a, 0, 0x7d30ad, 0, 0x9246c0, 0,
- 0xa459d0, 0, 0xb56ce0, 0, 0xc57cee, 0, 0xd48cfc, 0,
- 0x140090, 0, 0x331aa3, 0, 0x4e32b5, 0, 0x6848c6, 0,
- 0x7f5cd5, 0, 0x956fe3, 0, 0xa980f0, 0, 0xbc90fc, 0,
- 0x000094, 0, 0x181aa7, 0, 0x2d32b8, 0, 0x4248c8, 0,
- 0x545cd6, 0, 0x656fe4, 0, 0x7580f0, 0, 0x8490fc, 0,
- 0x001c88, 0, 0x183b9d, 0, 0x2d57b0, 0, 0x4272c2, 0,
- 0x548ad2, 0, 0x65a0e1, 0, 0x75b5ef, 0, 0x84c8fc, 0,
- 0x003064, 0, 0x185080, 0, 0x2d6d98, 0, 0x4288b0, 0,
- 0x54a0c5, 0, 0x65b7d9, 0, 0x75cceb, 0, 0x84e0fc, 0,
- 0x004030, 0, 0x18624e, 0, 0x2d8169, 0, 0x429e82, 0,
- 0x54b899, 0, 0x65d1ae, 0, 0x75e7c2, 0, 0x84fcd4, 0,
- 0x004400, 0, 0x1a661a, 0, 0x328432, 0, 0x48a048, 0,
- 0x5cba5c, 0, 0x6fd26f, 0, 0x80e880, 0, 0x90fc90, 0,
- 0x143c00, 0, 0x355f18, 0, 0x527e2d, 0, 0x6e9c42, 0,
- 0x87b754, 0, 0x9ed065, 0, 0xb4e775, 0, 0xc8fc84, 0,
- 0x303800, 0, 0x505916, 0, 0x6d762b, 0, 0x88923e, 0,
- 0xa0ab4f, 0, 0xb7c25f, 0, 0xccd86e, 0, 0xe0ec7c, 0,
- 0x482c00, 0, 0x694d14, 0, 0x866a26, 0, 0xa28638, 0,
- 0xbb9f47, 0, 0xd2b656, 0, 0xe8cc63, 0, 0xfce070, 0
-};
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-PaletteArray Console::ourPALPalette = {
- 0x000000, 0, 0x121212, 0, 0x242424, 0, 0x484848, 0, // 180 0
- 0x6c6c6c, 0, 0x909090, 0, 0xb4b4b4, 0, 0xd8d8d8, 0, // was 0x111111..0xcccccc
- 0x000000, 0, 0x121212, 0, 0x242424, 0, 0x484848, 0, // 198 1
- 0x6c6c6c, 0, 0x909090, 0, 0xb4b4b4, 0, 0xd8d8d8, 0,
- 0x1d0f00, 0, 0x3f2700, 0, 0x614900, 0, 0x836b01, 0, // 1b0 2
- 0xa58d23, 0, 0xc7af45, 0, 0xe9d167, 0, 0xffe789, 0, // was ..0xfff389
- 0x002400, 0, 0x004600, 0, 0x216800, 0, 0x438a07, 0, // 1c8 3
- 0x65ac29, 0, 0x87ce4b, 0, 0xa9f06d, 0, 0xcbff8f, 0,
- 0x340000, 0, 0x561400, 0, 0x783602, 0, 0x9a5824, 0, // 1e0 4
- 0xbc7a46, 0, 0xde9c68, 0, 0xffbe8a, 0, 0xffd0ad, 0, // was ..0xffe0ac
- 0x002700, 0, 0x004900, 0, 0x0c6b0c, 0, 0x2e8d2e, 0, // 1f8 5
- 0x50af50, 0, 0x72d172, 0, 0x94f394, 0, 0xb6ffb6, 0,
- 0x3d0008, 0, 0x610511, 0, 0x832733, 0, 0xa54955, 0, // 210 6
- 0xc76b77, 0, 0xe98d99, 0, 0xffafbb, 0, 0xffd1d7, 0, // was 0x3f0000..0xffd1dd
- 0x001e12, 0, 0x004228, 0, 0x046540, 0, 0x268762, 0, // 228 7
- 0x48a984, 0, 0x6acba6, 0, 0x8cedc8, 0, 0xafffe0, 0, // was 0x002100, 0x00431e..0xaeffff
- 0x300025, 0, 0x5f0047, 0, 0x811e69, 0, 0xa3408b, 0, // 240 8
- 0xc562ad, 0, 0xe784cf, 0, 0xffa8ea, 0, 0xffc9f2, 0, // was ..0xffa6f1, 0xffc8ff
- 0x001431, 0, 0x003653, 0, 0x0a5875, 0, 0x2c7a97, 0, // 258 9
- 0x4e9cb9, 0, 0x70bedb, 0, 0x92e0fd, 0, 0xb4ffff, 0,
- 0x2c0052, 0, 0x4e0074, 0, 0x701d96, 0, 0x923fb8, 0, // 270 a
- 0xb461da, 0, 0xd683fc, 0, 0xe2a5ff, 0, 0xeec9ff, 0, // was ..0xf8a5ff, 0xffc7ff
- 0x001759, 0, 0x00247c, 0, 0x1d469e, 0, 0x3f68c0, 0, // 288 b
- 0x618ae2, 0, 0x83acff, 0, 0xa5ceff, 0, 0xc7f0ff, 0,
- 0x12006d, 0, 0x34038f, 0, 0x5625b1, 0, 0x7847d3, 0, // 2a0 c
- 0x9a69f5, 0, 0xb48cff, 0, 0xc9adff, 0, 0xe1d1ff, 0, // was ..0xbc8bff, 0xdeadff, 0xffcfff,
- 0x000070, 0, 0x161292, 0, 0x3834b4, 0, 0x5a56d6, 0, // 2b8 d
- 0x7c78f8, 0, 0x9e9aff, 0, 0xc0bcff, 0, 0xe2deff, 0,
- 0x000000, 0, 0x121212, 0, 0x242424, 0, 0x484848, 0, // 2d0 e
- 0x6c6c6c, 0, 0x909090, 0, 0xb4b4b4, 0, 0xd8d8d8, 0,
- 0x000000, 0, 0x121212, 0, 0x242424, 0, 0x484848, 0, // 2e8 f
- 0x6c6c6c, 0, 0x909090, 0, 0xb4b4b4, 0, 0xd8d8d8, 0,
-};
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-PaletteArray Console::ourSECAMPalette = {
- 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
- 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
- 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
- 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
- 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
- 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
- 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
- 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
- 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
- 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
- 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
- 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
- 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
- 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
- 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
- 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
- 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
- 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
- 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
- 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
- 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
- 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
- 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
- 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
- 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
- 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
- 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
- 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
- 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
- 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
- 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff50ff, 0,
- 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0
-};
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-PaletteArray Console::ourNTSCPaletteZ26 = {
- 0x000000, 0, 0x505050, 0, 0x646464, 0, 0x787878, 0,
- 0x8c8c8c, 0, 0xa0a0a0, 0, 0xb4b4b4, 0, 0xc8c8c8, 0,
- 0x445400, 0, 0x586800, 0, 0x6c7c00, 0, 0x809000, 0,
- 0x94a414, 0, 0xa8b828, 0, 0xbccc3c, 0, 0xd0e050, 0,
- 0x673900, 0, 0x7b4d00, 0, 0x8f6100, 0, 0xa37513, 0,
- 0xb78927, 0, 0xcb9d3b, 0, 0xdfb14f, 0, 0xf3c563, 0,
- 0x7b2504, 0, 0x8f3918, 0, 0xa34d2c, 0, 0xb76140, 0,
- 0xcb7554, 0, 0xdf8968, 0, 0xf39d7c, 0, 0xffb190, 0,
- 0x7d122c, 0, 0x912640, 0, 0xa53a54, 0, 0xb94e68, 0,
- 0xcd627c, 0, 0xe17690, 0, 0xf58aa4, 0, 0xff9eb8, 0,
- 0x730871, 0, 0x871c85, 0, 0x9b3099, 0, 0xaf44ad, 0,
- 0xc358c1, 0, 0xd76cd5, 0, 0xeb80e9, 0, 0xff94fd, 0,
- 0x5d0b92, 0, 0x711fa6, 0, 0x8533ba, 0, 0x9947ce, 0,
- 0xad5be2, 0, 0xc16ff6, 0, 0xd583ff, 0, 0xe997ff, 0,
- 0x401599, 0, 0x5429ad, 0, 0x683dc1, 0, 0x7c51d5, 0,
- 0x9065e9, 0, 0xa479fd, 0, 0xb88dff, 0, 0xcca1ff, 0,
- 0x252593, 0, 0x3939a7, 0, 0x4d4dbb, 0, 0x6161cf, 0,
- 0x7575e3, 0, 0x8989f7, 0, 0x9d9dff, 0, 0xb1b1ff, 0,
- 0x0f3480, 0, 0x234894, 0, 0x375ca8, 0, 0x4b70bc, 0,
- 0x5f84d0, 0, 0x7398e4, 0, 0x87acf8, 0, 0x9bc0ff, 0,
- 0x04425a, 0, 0x18566e, 0, 0x2c6a82, 0, 0x407e96, 0,
- 0x5492aa, 0, 0x68a6be, 0, 0x7cbad2, 0, 0x90cee6, 0,
- 0x044f30, 0, 0x186344, 0, 0x2c7758, 0, 0x408b6c, 0,
- 0x549f80, 0, 0x68b394, 0, 0x7cc7a8, 0, 0x90dbbc, 0,
- 0x0f550a, 0, 0x23691e, 0, 0x377d32, 0, 0x4b9146, 0,
- 0x5fa55a, 0, 0x73b96e, 0, 0x87cd82, 0, 0x9be196, 0,
- 0x1f5100, 0, 0x336505, 0, 0x477919, 0, 0x5b8d2d, 0,
- 0x6fa141, 0, 0x83b555, 0, 0x97c969, 0, 0xabdd7d, 0,
- 0x344600, 0, 0x485a00, 0, 0x5c6e14, 0, 0x708228, 0,
- 0x84963c, 0, 0x98aa50, 0, 0xacbe64, 0, 0xc0d278, 0,
- 0x463e00, 0, 0x5a5205, 0, 0x6e6619, 0, 0x827a2d, 0,
- 0x968e41, 0, 0xaaa255, 0, 0xbeb669, 0, 0xd2ca7d, 0
-};
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-PaletteArray Console::ourPALPaletteZ26 = {
- 0x000000, 0, 0x4c4c4c, 0, 0x606060, 0, 0x747474, 0,
- 0x888888, 0, 0x9c9c9c, 0, 0xb0b0b0, 0, 0xc4c4c4, 0,
- 0x000000, 0, 0x4c4c4c, 0, 0x606060, 0, 0x747474, 0,
- 0x888888, 0, 0x9c9c9c, 0, 0xb0b0b0, 0, 0xc4c4c4, 0,
- 0x533a00, 0, 0x674e00, 0, 0x7b6203, 0, 0x8f7617, 0,
- 0xa38a2b, 0, 0xb79e3f, 0, 0xcbb253, 0, 0xdfc667, 0,
- 0x1b5800, 0, 0x2f6c00, 0, 0x438001, 0, 0x579415, 0,
- 0x6ba829, 0, 0x7fbc3d, 0, 0x93d051, 0, 0xa7e465, 0,
- 0x6a2900, 0, 0x7e3d12, 0, 0x925126, 0, 0xa6653a, 0,
- 0xba794e, 0, 0xce8d62, 0, 0xe2a176, 0, 0xf6b58a, 0,
- 0x075b00, 0, 0x1b6f11, 0, 0x2f8325, 0, 0x439739, 0,
- 0x57ab4d, 0, 0x6bbf61, 0, 0x7fd375, 0, 0x93e789, 0,
- 0x741b2f, 0, 0x882f43, 0, 0x9c4357, 0, 0xb0576b, 0,
- 0xc46b7f, 0, 0xd87f93, 0, 0xec93a7, 0, 0xffa7bb, 0,
- 0x00572e, 0, 0x106b42, 0, 0x247f56, 0, 0x38936a, 0,
- 0x4ca77e, 0, 0x60bb92, 0, 0x74cfa6, 0, 0x88e3ba, 0,
- 0x6d165f, 0, 0x812a73, 0, 0x953e87, 0, 0xa9529b, 0,
- 0xbd66af, 0, 0xd17ac3, 0, 0xe58ed7, 0, 0xf9a2eb, 0,
- 0x014c5e, 0, 0x156072, 0, 0x297486, 0, 0x3d889a, 0,
- 0x519cae, 0, 0x65b0c2, 0, 0x79c4d6, 0, 0x8dd8ea, 0,
- 0x5f1588, 0, 0x73299c, 0, 0x873db0, 0, 0x9b51c4, 0,
- 0xaf65d8, 0, 0xc379ec, 0, 0xd78dff, 0, 0xeba1ff, 0,
- 0x123b87, 0, 0x264f9b, 0, 0x3a63af, 0, 0x4e77c3, 0,
- 0x628bd7, 0, 0x769feb, 0, 0x8ab3ff, 0, 0x9ec7ff, 0,
- 0x451e9d, 0, 0x5932b1, 0, 0x6d46c5, 0, 0x815ad9, 0,
- 0x956eed, 0, 0xa982ff, 0, 0xbd96ff, 0, 0xd1aaff, 0,
- 0x2a2b9e, 0, 0x3e3fb2, 0, 0x5253c6, 0, 0x6667da, 0,
- 0x7a7bee, 0, 0x8e8fff, 0, 0xa2a3ff, 0, 0xb6b7ff, 0,
- 0x000000, 0, 0x4c4c4c, 0, 0x606060, 0, 0x747474, 0,
- 0x888888, 0, 0x9c9c9c, 0, 0xb0b0b0, 0, 0xc4c4c4, 0,
- 0x000000, 0, 0x4c4c4c, 0, 0x606060, 0, 0x747474, 0,
- 0x888888, 0, 0x9c9c9c, 0, 0xb0b0b0, 0, 0xc4c4c4, 0
-};
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-PaletteArray Console::ourSECAMPaletteZ26 = {
- 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
- 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
- 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
- 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
- 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
- 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
- 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
- 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
- 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
- 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
- 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
- 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
- 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
- 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
- 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
- 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
- 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
- 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
- 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
- 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
- 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
- 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
- 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
- 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
- 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
- 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
- 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
- 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
- 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
- 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0,
- 0x000000, 0, 0x2121ff, 0, 0xf03c79, 0, 0xff3cff, 0,
- 0x7fff00, 0, 0x7fffff, 0, 0xffff3f, 0, 0xffffff, 0
-};
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-PaletteArray Console::ourUserNTSCPalette = { 0 }; // filled from external file
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-PaletteArray Console::ourUserPALPalette = { 0 }; // filled from external file
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-PaletteArray Console::ourUserSECAMPalette = { 0 }; // filled from external file
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-PaletteArray Console::ourCustomNTSCPalette = { 0 }; // filled by function
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-PaletteArray Console::ourCustomPALPalette = { 0 }; // filled by function
diff --git a/src/emucore/Console.hxx b/src/emucore/Console.hxx
index 9ff4b002c..d13588b07 100644
--- a/src/emucore/Console.hxx
+++ b/src/emucore/Console.hxx
@@ -39,7 +39,6 @@ class AudioSettings;
#include "FrameBufferConstants.hxx"
#include "Serializable.hxx"
#include "EventHandlerConstants.hxx"
-#include "NTSCFilter.hxx"
#include "EmulationTiming.hxx"
#include "ConsoleTiming.hxx"
#include "frame-manager/AbstractFrameManager.hxx"
@@ -190,41 +189,24 @@ class Console : public Serializable, public ConsoleIO
/**
Toggle between NTSC/PAL/SECAM (and variants) display format.
- @param direction +1 indicates increase, -1 indicates decrease.
+ @param direction +1 indicates increase, -1 indicates decrease.
*/
- void toggleFormat(int direction = 1);
+ void selectFormat(int direction = +1);
/**
Set NTSC/PAL/SECAM (and variants) display format.
*/
- void setFormat(uInt32 format);
+ void setFormat(uInt32 format, bool force = false);
/**
Get NTSC/PAL/SECAM (and variants) display format name
*/
string getFormatString() const { return myDisplayFormat; }
- /**
- Toggle between the available palettes.
- */
- void togglePalette();
-
- /**
- Generates a custom palette, based on user defined phase shifts.
- */
- void generateCustomPalette(int type);
-
- /**
- Sets the palette according to the given palette name.
-
- @param palette The palette to switch to.
- */
- void setPalette(const string& palette);
-
/**
Toggle interpolation on/off
*/
- void toggleInter();
+ void toggleInter(bool toggle = true);
/**
Toggle turbo mode on/off
@@ -240,9 +222,9 @@ class Console : public Serializable, public ConsoleIO
/**
Change the "Display.PPBlend" variable.
- @param direction +1 indicates increase, -1 indicates decrease.
+ @param direction +1 indicates increase, -1 indicates decrease.
*/
- void changePhosphor(int direction);
+ void changePhosphor(int direction = +1);
/**
Toggles the PAL color-loss effect.
@@ -275,28 +257,18 @@ class Console : public Serializable, public ConsoleIO
/**
Change the "Display.VCenter" variable.
- @param direction +1 indicates increase, -1 indicates decrease.
+ @param direction +1 indicates increase, -1 indicates decrease.
*/
- void changeVerticalCenter(int direction);
+ void changeVerticalCenter(int direction = +1);
/**
Change the "TIA scanline adjust" variable.
Note that there are currently two of these (NTSC and PAL). The currently
active mode will determine which one is used.
- @param direction +1 indicates increase, -1 indicates decrease.
+ @param direction +1 indicates increase, -1 indicates decrease.
*/
- void changeScanlineAdjust(int direction);
-
- /**
- Change the "phase shift" variable.
- Note that there are two of these (NTSC and PAL). The currently
- active mode will determine which one is used.
-
- @param direction +1 indicates increase, -1 indicates decrease.
-
- */
- void changeColorPhaseShift(int direction);
+ void changeVSizeAdjust(int direction = +1);
/**
Returns the current framerate.
@@ -379,35 +351,10 @@ class Console : public Serializable, public ConsoleIO
unique_ptr getControllerPort(const Controller::Type type,
const Controller::Jack port, const string& romMd5);
- /**
- Loads a user-defined palette file (from OSystem::paletteFile), filling the
- appropriate user-defined palette arrays.
- */
- void loadUserPalette();
-
- /**
- Loads all defined palettes with PAL color-loss data, even those that
- normally can't have it enabled (NTSC), since it's also used for
- 'greying out' the frame in the debugger.
- */
- void generateColorLossPalette();
-
- int getPaletteNum(const string& name) const;
-
-
void toggleTIABit(TIABit bit, const string& bitname, bool show = true) const;
void toggleTIACollision(TIABit bit, const string& bitname, bool show = true) const;
private:
-
- enum PaletteType {
- Standard,
- Z26,
- User,
- Custom,
- NumTypes
- };
-
// Reference to the osystem object
OSystem& myOSystem;
@@ -457,10 +404,6 @@ class Console : public Serializable, public ConsoleIO
// Is the TV format autodetected?
bool myFormatAutodetected{false};
- // Indicates whether an external palette was found and
- // successfully loaded
- bool myUserPaletteDefined{false};
-
// Contains detailed info about this console
ConsoleInfo myConsoleInfo;
@@ -474,25 +417,6 @@ class Console : public Serializable, public ConsoleIO
// The audio settings
AudioSettings& myAudioSettings;
- // Table of RGB values for NTSC, PAL and SECAM
- static PaletteArray ourNTSCPalette;
- static PaletteArray ourPALPalette;
- static PaletteArray ourSECAMPalette;
-
- // Table of RGB values for NTSC, PAL and SECAM - Z26 version
- static PaletteArray ourNTSCPaletteZ26;
- static PaletteArray ourPALPaletteZ26;
- static PaletteArray ourSECAMPaletteZ26;
-
- // Table of RGB values for NTSC, PAL and SECAM - user-defined
- static PaletteArray ourUserNTSCPalette;
- static PaletteArray ourUserPALPalette;
- static PaletteArray ourUserSECAMPalette;
-
- // Table of RGB values for NTSC, PAL - custom-defined
- static PaletteArray ourCustomNTSCPalette;
- static PaletteArray ourCustomPALPalette;
-
private:
// Following constructors and assignment operators not supported
Console() = delete;
diff --git a/src/emucore/ConsoleIO.hxx b/src/emucore/ConsoleIO.hxx
index d8ae106a6..2fde50ed8 100644
--- a/src/emucore/ConsoleIO.hxx
+++ b/src/emucore/ConsoleIO.hxx
@@ -15,12 +15,12 @@
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
-#include "Control.hxx"
-#include "Switches.hxx"
-
#ifndef CONSOLE_IO_HXX
#define CONSOLE_IO_HXX
+class Controller;
+class Switches;
+
class ConsoleIO
{
public:
diff --git a/src/emucore/ConsoleTiming.hxx b/src/emucore/ConsoleTiming.hxx
index 1f75db469..fd43caa98 100644
--- a/src/emucore/ConsoleTiming.hxx
+++ b/src/emucore/ConsoleTiming.hxx
@@ -25,7 +25,8 @@ enum class ConsoleTiming
{
ntsc, // console with CPU running at 1.193182 MHz, NTSC colours
pal, // console with CPU running at 1.182298 MHz, PAL colours
- secam // console with CPU running at 1.187500 MHz, SECAM colours
+ secam, // console with CPU running at 1.187500 MHz, SECAM colours
+ numTimings
};
#endif // CONSOLE_TIMING_HXX
diff --git a/src/emucore/Control.hxx b/src/emucore/Control.hxx
index 3647d1bc0..a670f39f6 100644
--- a/src/emucore/Control.hxx
+++ b/src/emucore/Control.hxx
@@ -25,8 +25,8 @@ class System;
#include
-#include "Serializable.hxx"
#include "bspf.hxx"
+#include "Serializable.hxx"
/**
A controller is a device that plugs into either the left or right
diff --git a/src/emucore/ControllerDetector.hxx b/src/emucore/ControllerDetector.hxx
index 737ea36f2..d37076eb1 100644
--- a/src/emucore/ControllerDetector.hxx
+++ b/src/emucore/ControllerDetector.hxx
@@ -18,6 +18,8 @@
#ifndef CONTROLLER_DETECTOR_HXX
#define CONTROLLER_DETECTOR_HXX
+class Settings;
+
#include "Control.hxx"
/**
diff --git a/src/emucore/Device.hxx b/src/emucore/Device.hxx
index 7c175852b..fb2423a35 100644
--- a/src/emucore/Device.hxx
+++ b/src/emucore/Device.hxx
@@ -20,9 +20,9 @@
class System;
-#include "Console.hxx"
-#include "Serializable.hxx"
#include "bspf.hxx"
+#include "ConsoleTiming.hxx"
+#include "Serializable.hxx"
/**
Abstract base class for devices which can be attached to a 6502
diff --git a/src/emucore/Event.hxx b/src/emucore/Event.hxx
index 915461e97..fa8a4d04d 100644
--- a/src/emucore/Event.hxx
+++ b/src/emucore/Event.hxx
@@ -22,7 +22,6 @@
#include
#include "bspf.hxx"
-#include "StellaKeys.hxx"
/**
@author Stephen Anthony, Christian Speckner, Thomas Jentzsch
@@ -92,6 +91,7 @@ class Event
TogglePauseMode, StartPauseMode,
OptionsMenuMode, CmdMenuMode, DebuggerMode, ExitMode,
TakeSnapshot, ToggleContSnapshots, ToggleContSnapshotsFrame,
+ ToggleTurbo,
NextState, PreviousState, LoadState, SaveState,
SaveAllStates, LoadAllStates,
@@ -100,12 +100,15 @@ class Event
Unwind1Menu, Unwind10Menu, UnwindAllMenu,
RewindPause, UnwindPause,
- FormatDecrease, FormatIncrease, TogglePalette, ToggleColorLoss,
+ FormatDecrease, FormatIncrease, PaletteDecrease, PaletteIncrease, ToggleColorLoss,
+ PreviousPaletteAttribute, NextPaletteAttribute,
+ PaletteAttributeDecrease, PaletteAttributeIncrease,
ToggleFullScreen, VidmodeDecrease, VidmodeIncrease,
- VCenterDecrease, VCenterIncrease, ScanlineAdjustDecrease, ScanlineAdjustIncrease,
+ VCenterDecrease, VCenterIncrease, VSizeAdjustDecrease, VSizeAdjustIncrease,
OverscanDecrease, OverscanIncrease,
VidmodeStd, VidmodeRGB, VidmodeSVideo, VidModeComposite, VidModeBad, VidModeCustom,
+ PreviousVideoMode, NextVideoMode,
PreviousAttribute, NextAttribute, DecreaseAttribute, IncreaseAttribute,
ScanlinesDecrease, ScanlinesIncrease,
PhosphorDecrease, PhosphorIncrease, TogglePhosphor, ToggleInter, ToggleJitter,
@@ -118,10 +121,8 @@ class Event
ToggleCollisions, ToggleBits, ToggleFixedColors,
ToggleFrameStats, ToggleSAPortOrder, ExitGame,
-
// add new events from here to avoid that user remapped events get overwritten
- ToggleTurbo,
- ColorShiftDecrease, ColorShiftIncrease,
+ SettingDecrease, SettingIncrease, PreviousSetting, NextSetting,
LastType
};
@@ -136,7 +137,7 @@ class Event
};
// Event list version, update only if the id of existing(!) event types changed
- static constexpr Int32 VERSION = 3;
+ static constexpr Int32 VERSION = 4;
using EventSet = std::set;
diff --git a/src/emucore/EventHandler.cxx b/src/emucore/EventHandler.cxx
index c9fa85835..fa87be91d 100644
--- a/src/emucore/EventHandler.cxx
+++ b/src/emucore/EventHandler.cxx
@@ -22,6 +22,7 @@
#include "Base.hxx"
#include "Console.hxx"
+#include "PaletteHandler.hxx"
#include "FrameBuffer.hxx"
#include "FSNode.hxx"
#include "OSystem.hxx"
@@ -62,6 +63,8 @@
#include "ScrollBarWidget.hxx"
#endif
+using namespace std::placeholders;
+
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EventHandler::EventHandler(OSystem& osystem)
: myOSystem(osystem)
@@ -339,15 +342,149 @@ void EventHandler::handleSystemEvent(SystemEvent e, int, int)
}
}
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+AdjustFunction EventHandler::cycleAdjustSetting(int direction)
+{
+ const bool isFullScreen = myOSystem.frameBuffer().fullScreen();
+ const bool isCustomPalette =
+ myOSystem.settings().getString("palette") == PaletteHandler::SETTING_CUSTOM;
+ const bool isCustomFilter =
+ myOSystem.settings().getInt("tv.filter") == int(NTSCFilter::Preset::CUSTOM);
+
+ do
+ {
+ myAdjustSetting =
+ AdjustSetting(BSPF::clampw(int(myAdjustSetting) + direction, 0, int(AdjustSetting::MAX_ADJ)));
+ // skip currently non-relevant adjustments
+ } while((myAdjustSetting == AdjustSetting::OVERSCAN && !isFullScreen)
+ || (myAdjustSetting == AdjustSetting::PALETTE_PHASE && !isCustomPalette)
+ || (myAdjustSetting >= AdjustSetting::NTSC_SHARPNESS
+ && myAdjustSetting <= AdjustSetting::NTSC_BLEEDING
+ && !isCustomFilter));
+
+ return getAdjustSetting(myAdjustSetting);
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+AdjustFunction EventHandler::getAdjustSetting(AdjustSetting setting)
+{
+ // Notes:
+ // - All methods MUST show a message
+ // - This array MUST have the same order as AdjustSetting
+ const AdjustFunction ADJUST_FUNCTIONS[int(AdjustSetting::NUM_ADJ)] =
+ {
+ std::bind(&Sound::adjustVolume, &myOSystem.sound(), _1),
+ std::bind(&FrameBuffer::selectVidMode, &myOSystem.frameBuffer(), _1),
+ std::bind(&FrameBuffer::toggleFullscreen, &myOSystem.frameBuffer(), _1),
+ std::bind(&FrameBuffer::changeOverscan, &myOSystem.frameBuffer(), _1),
+ std::bind(&Console::selectFormat, &myOSystem.console(), _1),
+ std::bind(&Console::changeVerticalCenter, &myOSystem.console(), _1),
+ std::bind(&Console::changeVSizeAdjust, &myOSystem.console(), _1),
+ // Palette adjustables
+ std::bind(&PaletteHandler::cyclePalette, &myOSystem.frameBuffer().tiaSurface().paletteHandler(), _1),
+ std::bind(&PaletteHandler::changeAdjustable, &myOSystem.frameBuffer().tiaSurface().paletteHandler(),
+ PaletteHandler::PHASE_SHIFT, _1),
+ std::bind(&PaletteHandler::changeAdjustable, &myOSystem.frameBuffer().tiaSurface().paletteHandler(),
+ PaletteHandler::HUE, _1),
+ std::bind(&PaletteHandler::changeAdjustable, &myOSystem.frameBuffer().tiaSurface().paletteHandler(),
+ PaletteHandler::SATURATION, _1),
+ std::bind(&PaletteHandler::changeAdjustable, &myOSystem.frameBuffer().tiaSurface().paletteHandler(),
+ PaletteHandler::CONTRAST, _1),
+ std::bind(&PaletteHandler::changeAdjustable, &myOSystem.frameBuffer().tiaSurface().paletteHandler(),
+ PaletteHandler::BRIGHTNESS, _1),
+ std::bind(&PaletteHandler::changeAdjustable, &myOSystem.frameBuffer().tiaSurface().paletteHandler(),
+ PaletteHandler::GAMMA, _1),
+ // NTSC filter adjustables
+ std::bind(&TIASurface::changeNTSC, &myOSystem.frameBuffer().tiaSurface(), _1),
+ std::bind(&TIASurface::changeNTSCAdjustable, &myOSystem.frameBuffer().tiaSurface(),
+ int(NTSCFilter::Adjustables::SHARPNESS), _1),
+ std::bind(&TIASurface::changeNTSCAdjustable, &myOSystem.frameBuffer().tiaSurface(),
+ int(NTSCFilter::Adjustables::RESOLUTION), _1),
+ std::bind(&TIASurface::changeNTSCAdjustable, &myOSystem.frameBuffer().tiaSurface(),
+ int(NTSCFilter::Adjustables::ARTIFACTS), _1),
+ std::bind(&TIASurface::changeNTSCAdjustable, &myOSystem.frameBuffer().tiaSurface(),
+ int(NTSCFilter::Adjustables::FRINGING), _1),
+ std::bind(&TIASurface::changeNTSCAdjustable, &myOSystem.frameBuffer().tiaSurface(),
+ int(NTSCFilter::Adjustables::BLEEDING), _1),
+ std::bind(&Console::changePhosphor, &myOSystem.console(), _1),
+ std::bind(&TIASurface::setScanlineIntensity, &myOSystem.frameBuffer().tiaSurface(), _1),
+ std::bind(&Console::toggleInter, &myOSystem.console(), _1),
+ // Following functions are not used when cycling settings but for "direct only" hotkeys
+ std::bind(&StateManager::changeState, &myOSystem.state(), _1),
+ std::bind(&PaletteHandler::changeCurrentAdjustable, &myOSystem.frameBuffer().tiaSurface().paletteHandler(), _1),
+ std::bind(&TIASurface::changeCurrentNTSCAdjustable, &myOSystem.frameBuffer().tiaSurface(), _1),
+ };
+
+ return ADJUST_FUNCTIONS[int(setting)];
+}
+
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated)
{
// Take care of special events that aren't part of the emulation core
// or need to be preprocessed before passing them on
- bool pressed = (value != 0);
+ const bool pressed = (value != 0);
+
+ // The global settings keys change settings or values as long as the setting
+ // message from the previous settings event is still displayed.
+ // Therefore, do not change global settings/values or direct values if
+ // a) the setting message is no longer shown
+ // b) other keys have been pressed
+ if(!myOSystem.frameBuffer().messageShown())
+ {
+ myAdjustActive = false;
+ myAdjustDirect = AdjustSetting::NONE;
+ }
+ const bool adjustActive = myAdjustActive;
+ const AdjustSetting adjustDirect = myAdjustDirect;
+ if(pressed)
+ {
+ myAdjustActive = false;
+ myAdjustDirect = AdjustSetting::NONE;
+ }
switch(event)
{
+ ////////////////////////////////////////////////////////////////////////
+ // Allow adjusting several (mostly repeated) settings using the same four hotkeys
+ case Event::PreviousSetting:
+ case Event::NextSetting:
+ if(pressed && !repeated)
+ {
+ const int direction = event == Event::PreviousSetting ? -1 : +1;
+
+ // Get (and display) the previous|next adjustment function,
+ // but do not change its value
+ cycleAdjustSetting(adjustActive ? direction : 0)(0);
+ // Fallback message when no message is displayed by method
+ //if(!myOSystem.frameBuffer().messageShown())
+ // myOSystem.frameBuffer().showMessage("Message " + std::to_string(int(myAdjustSetting)));
+ myAdjustActive = true;
+ }
+ break;
+
+ case Event::SettingDecrease:
+ case Event::SettingIncrease:
+ if(pressed)
+ {
+ const int direction = event == Event::SettingDecrease ? -1 : +1;
+
+ // if a "direct only" hotkey was pressed last, use this one
+ if(adjustDirect != AdjustSetting::NONE)
+ {
+ myAdjustDirect = adjustDirect;
+ getAdjustSetting(myAdjustDirect)(direction);
+ }
+ else
+ {
+ // Get (and display) the current adjustment function,
+ // but only change its value if the function was already active before
+ getAdjustSetting(myAdjustSetting)(adjustActive ? direction : 0);
+ myAdjustActive = true;
+ }
+ }
+ return;
+
////////////////////////////////////////////////////////////////////////
// If enabled, make sure 'impossible' joystick directions aren't allowed
case Event::JoystickZeroUp:
@@ -392,67 +529,169 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated)
////////////////////////////////////////////////////////////////////////
case Event::Fry:
- if (!repeated) myFryingFlag = pressed;
+ if(!repeated) myFryingFlag = pressed;
return;
case Event::ReloadConsole:
- if (pressed && !repeated) myOSystem.reloadConsole();
+ if(pressed && !repeated) myOSystem.reloadConsole();
return;
case Event::VolumeDecrease:
- if(pressed) myOSystem.sound().adjustVolume(-1);
+ if(pressed)
+ {
+ myOSystem.sound().adjustVolume(-1);
+ myAdjustSetting = AdjustSetting::VOLUME;
+ myAdjustActive = true;
+ }
return;
case Event::VolumeIncrease:
- if(pressed) myOSystem.sound().adjustVolume(+1);
+ if(pressed)
+ {
+ myOSystem.sound().adjustVolume(+1);
+ myAdjustSetting = AdjustSetting::VOLUME;
+ myAdjustActive = true;
+ }
return;
case Event::SoundToggle:
- if(pressed && !repeated) myOSystem.sound().toggleMute();
+ if(pressed && !repeated)
+ {
+ myOSystem.sound().toggleMute();
+ myAdjustSetting = AdjustSetting::VOLUME;
+ myAdjustActive = true;
+ }
return;
case Event::VidmodeDecrease:
- if(pressed) myOSystem.frameBuffer().changeVidMode(-1);
+ if(pressed)
+ {
+ myOSystem.frameBuffer().selectVidMode(-1);
+ myAdjustSetting = AdjustSetting::ZOOM;
+ myAdjustActive = true;
+ }
return;
case Event::VidmodeIncrease:
- if(pressed) myOSystem.frameBuffer().changeVidMode(+1);
+ if(pressed)
+ {
+ myOSystem.frameBuffer().selectVidMode(+1);
+ myAdjustSetting = AdjustSetting::ZOOM;
+ myAdjustActive = true;
+ }
return;
case Event::VCenterDecrease:
- if (pressed) myOSystem.console().changeVerticalCenter(-1);
+ if(pressed)
+ {
+ myOSystem.console().changeVerticalCenter(-1);
+ myAdjustSetting = AdjustSetting::VCENTER;
+ myAdjustActive = true;
+ }
return;
case Event::VCenterIncrease:
- if (pressed) myOSystem.console().changeVerticalCenter(+1);
+ if(pressed)
+ {
+ myOSystem.console().changeVerticalCenter(+1);
+ myAdjustSetting = AdjustSetting::VCENTER;
+ myAdjustActive = true;
+ }
return;
- case Event::ScanlineAdjustDecrease:
- if (pressed) myOSystem.console().changeScanlineAdjust(-1);
+ case Event::VSizeAdjustDecrease:
+ if(pressed)
+ {
+ myOSystem.console().changeVSizeAdjust(-1);
+ myAdjustSetting = AdjustSetting::VSIZE;
+ myAdjustActive = true;
+ }
return;
- case Event::ScanlineAdjustIncrease:
- if (pressed) myOSystem.console().changeScanlineAdjust(+1);
+ case Event::VSizeAdjustIncrease:
+ if(pressed)
+ {
+ myOSystem.console().changeVSizeAdjust(+1);
+ myAdjustSetting = AdjustSetting::VSIZE;
+ myAdjustActive = true;
+ }
return;
- case Event::ColorShiftDecrease:
- if (pressed) myOSystem.console().changeColorPhaseShift(-1);
+ case Event::PreviousPaletteAttribute:
+ if(pressed)
+ {
+ myOSystem.frameBuffer().tiaSurface().paletteHandler().cycleAdjustable(-1);
+ myAdjustDirect = AdjustSetting::PALETTE_CHANGE_ATTRIBUTE;
+ }
return;
- case Event::ColorShiftIncrease:
- if (pressed) myOSystem.console().changeColorPhaseShift(+1);
+ case Event::NextPaletteAttribute:
+ if(pressed)
+ {
+ myOSystem.frameBuffer().tiaSurface().paletteHandler().cycleAdjustable(+1);
+ myAdjustDirect = AdjustSetting::PALETTE_CHANGE_ATTRIBUTE;
+ }
+ return;
+
+ case Event::PaletteAttributeDecrease:
+ if(pressed)
+ {
+ myOSystem.frameBuffer().tiaSurface().paletteHandler().changeCurrentAdjustable(-1);
+ myAdjustDirect = AdjustSetting::PALETTE_CHANGE_ATTRIBUTE;
+ }
+ return;
+
+ case Event::PaletteAttributeIncrease:
+ if(pressed)
+ {
+ myOSystem.frameBuffer().tiaSurface().paletteHandler().changeCurrentAdjustable(+1);
+ myAdjustDirect = AdjustSetting::PALETTE_CHANGE_ATTRIBUTE;
+ }
return;
case Event::ToggleFullScreen:
- if (pressed && !repeated) myOSystem.frameBuffer().toggleFullscreen();
+ if(pressed && !repeated)
+ {
+ myOSystem.frameBuffer().toggleFullscreen();
+ myAdjustSetting = AdjustSetting::FULLSCREEN;
+ myAdjustActive = true;
+ }
return;
case Event::OverscanDecrease:
- if (pressed) myOSystem.frameBuffer().changeOverscan(-1);
+ if(pressed)
+ {
+ myOSystem.frameBuffer().changeOverscan(-1);
+ myAdjustSetting = AdjustSetting::OVERSCAN;
+ myAdjustActive = true;
+ }
return;
case Event::OverscanIncrease:
- if (pressed) myOSystem.frameBuffer().changeOverscan(1);
+ if(pressed)
+ {
+ myOSystem.frameBuffer().changeOverscan(+1);
+ myAdjustSetting = AdjustSetting::OVERSCAN;
+ myAdjustActive = true;
+ }
+ return;
+
+ case Event::PreviousVideoMode:
+ if(pressed && !repeated)
+ {
+ myOSystem.frameBuffer().tiaSurface().changeNTSC(-1);
+ myAdjustSetting = AdjustSetting::NTSC_PRESET;
+ myAdjustActive = true;
+ }
+ return;
+
+ case Event::NextVideoMode:
+ if(pressed && !repeated)
+ {
+ myOSystem.frameBuffer().tiaSurface().changeNTSC(+1);
+ myAdjustSetting = AdjustSetting::NTSC_PRESET;
+ myAdjustActive = true;
+ }
return;
case Event::VidmodeStd:
@@ -479,72 +718,113 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated)
if (pressed && !repeated) myOSystem.frameBuffer().tiaSurface().setNTSC(NTSCFilter::Preset::CUSTOM);
return;
- case Event::ScanlinesDecrease:
- if (pressed) myOSystem.frameBuffer().tiaSurface().setScanlineIntensity(-2);
- return;
-
- case Event::ScanlinesIncrease:
- if (pressed) myOSystem.frameBuffer().tiaSurface().setScanlineIntensity(+2);
- return;
-
case Event::PreviousAttribute:
- if (pressed)
+ if(pressed)
{
- myOSystem.frameBuffer().tiaSurface().setNTSC(NTSCFilter::Preset::CUSTOM);
- myOSystem.frameBuffer().showMessage(
- myOSystem.frameBuffer().tiaSurface().ntsc().setPreviousAdjustable());
+ myOSystem.frameBuffer().tiaSurface().setNTSCAdjustable(-1);
+ myAdjustDirect = AdjustSetting::NTSC_CHANGE_ATTRIBUTE;
}
return;
case Event::NextAttribute:
- if (pressed)
+ if(pressed)
{
- myOSystem.frameBuffer().tiaSurface().setNTSC(NTSCFilter::Preset::CUSTOM);
- myOSystem.frameBuffer().showMessage(
- myOSystem.frameBuffer().tiaSurface().ntsc().setNextAdjustable());
+ myOSystem.frameBuffer().tiaSurface().setNTSCAdjustable(+1);
+ myAdjustDirect = AdjustSetting::NTSC_CHANGE_ATTRIBUTE;
}
return;
case Event::DecreaseAttribute:
- if (pressed)
+ if(pressed)
{
- myOSystem.frameBuffer().tiaSurface().setNTSC(NTSCFilter::Preset::CUSTOM);
- myOSystem.frameBuffer().showMessage(
- myOSystem.frameBuffer().tiaSurface().ntsc().decreaseAdjustable());
+ myOSystem.frameBuffer().tiaSurface().changeCurrentNTSCAdjustable(-1);
+ myAdjustDirect = AdjustSetting::NTSC_CHANGE_ATTRIBUTE;
}
return;
case Event::IncreaseAttribute:
- if (pressed)
+ if(pressed)
{
- myOSystem.frameBuffer().tiaSurface().setNTSC(NTSCFilter::Preset::CUSTOM);
- myOSystem.frameBuffer().showMessage(
- myOSystem.frameBuffer().tiaSurface().ntsc().increaseAdjustable());
+ myOSystem.frameBuffer().tiaSurface().changeCurrentNTSCAdjustable(+1);
+ myAdjustDirect = AdjustSetting::NTSC_CHANGE_ATTRIBUTE;
+ }
+ return;
+
+ case Event::ScanlinesDecrease:
+ if(pressed)
+ {
+ myOSystem.frameBuffer().tiaSurface().setScanlineIntensity(-1);
+ myAdjustSetting = AdjustSetting::SCANLINES;
+ myAdjustActive = true;
+
+ }
+ return;
+
+ case Event::ScanlinesIncrease:
+ if(pressed)
+ {
+ myOSystem.frameBuffer().tiaSurface().setScanlineIntensity(+1);
+ myAdjustSetting = AdjustSetting::SCANLINES;
+ myAdjustActive = true;
}
return;
case Event::PhosphorDecrease:
- if (pressed) myOSystem.console().changePhosphor(-1);
+ if(pressed)
+ {
+ myOSystem.console().changePhosphor(-1);
+ myAdjustSetting = AdjustSetting::PHOSPHOR;
+ myAdjustActive = true;
+ }
return;
case Event::PhosphorIncrease:
- if (pressed) myOSystem.console().changePhosphor(1);
+ if(pressed)
+ {
+ myOSystem.console().changePhosphor(+1);
+ myAdjustSetting = AdjustSetting::PHOSPHOR;
+ myAdjustActive = true;
+ }
return;
case Event::TogglePhosphor:
- if (pressed && !repeated) myOSystem.console().togglePhosphor();
+ if(pressed && !repeated)
+ {
+ myOSystem.console().togglePhosphor();
+ myAdjustSetting = AdjustSetting::PHOSPHOR;
+ myAdjustActive = true;
+ }
return;
case Event::ToggleColorLoss:
if (pressed && !repeated) myOSystem.console().toggleColorLoss();
return;
- case Event::TogglePalette:
- if (pressed && !repeated) myOSystem.console().togglePalette();
+ case Event::PaletteDecrease:
+ if(pressed && !repeated)
+ {
+ myOSystem.frameBuffer().tiaSurface().paletteHandler().cyclePalette(-1);
+ myAdjustSetting = AdjustSetting::PALETTE;
+ myAdjustActive = true;
+ }
+ return;
+
+ case Event::PaletteIncrease:
+ if(pressed && !repeated)
+ {
+ myOSystem.frameBuffer().tiaSurface().paletteHandler().cyclePalette(+1);
+ myAdjustSetting = AdjustSetting::PALETTE;
+ myAdjustActive = true;
+ }
return;
case Event::ToggleInter:
- if (pressed && !repeated) myOSystem.console().toggleInter();
+ if(pressed && !repeated)
+ {
+ myOSystem.console().toggleInter();
+ myAdjustSetting = AdjustSetting::INTERPOLATION;
+ myAdjustActive = true;
+ }
return;
case Event::ToggleTurbo:
@@ -582,23 +862,26 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated)
return;
case Event::FormatDecrease:
- if (pressed) myOSystem.console().toggleFormat(-1);
+ if(pressed && !repeated)
+ {
+ myOSystem.console().selectFormat(-1);
+ myAdjustSetting = AdjustSetting::TVFORMAT;
+ myAdjustActive = true;
+ }
return;
case Event::FormatIncrease:
- if (pressed) myOSystem.console().toggleFormat(1);
+ if(pressed && !repeated)
+ {
+ myOSystem.console().selectFormat(+1);
+ myAdjustSetting = AdjustSetting::TVFORMAT;
+ myAdjustActive = true;
+ }
return;
case Event::ToggleGrabMouse:
if (pressed && !repeated && !myOSystem.frameBuffer().fullScreen())
- {
- bool oldState = myOSystem.frameBuffer().grabMouseEnabled();
myOSystem.frameBuffer().toggleGrabMouse();
- bool newState = myOSystem.frameBuffer().grabMouseEnabled();
- myOSystem.frameBuffer().showMessage(oldState != newState ? myOSystem.frameBuffer().grabMouseEnabled()
- ? "Grab mouse enabled" : "Grab mouse disabled"
- : "Grab mouse not allowed while cursor shown");
- }
return;
case Event::ToggleP0Collision:
@@ -662,7 +945,11 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated)
return;
case Event::SaveState:
- if(pressed && !repeated) myOSystem.state().saveState();
+ if(pressed && !repeated)
+ {
+ myOSystem.state().saveState();
+ myAdjustDirect = AdjustSetting::STATE;
+ }
return;
case Event::SaveAllStates:
@@ -670,12 +957,20 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated)
myOSystem.frameBuffer().showMessage(myOSystem.state().rewindManager().saveAllStates());
return;
- case Event::NextState:
- if(pressed) myOSystem.state().changeState(1);
+ case Event::PreviousState:
+ if(pressed)
+ {
+ myOSystem.state().changeState(-1);
+ myAdjustDirect = AdjustSetting::STATE;
+ }
return;
- case Event::PreviousState:
- if (pressed) myOSystem.state().changeState(-1);
+ case Event::NextState:
+ if(pressed)
+ {
+ myOSystem.state().changeState(+1);
+ myAdjustDirect = AdjustSetting::STATE;
+ }
return;
case Event::ToggleAutoSlot:
@@ -683,7 +978,11 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated)
return;
case Event::LoadState:
- if(pressed && !repeated) myOSystem.state().loadState();
+ if(pressed && !repeated)
+ {
+ myOSystem.state().loadState();
+ myAdjustDirect = AdjustSetting::STATE;
+ }
return;
case Event::LoadAllStates:
@@ -759,7 +1058,7 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated)
if (myOSystem.settings().getBool("confirmexit"))
{
StringList msg;
- string saveOnExit = myOSystem.settings().getString("saveonexit");
+ const string saveOnExit = myOSystem.settings().getString("saveonexit");
bool activeTM = myOSystem.settings().getBool(
myOSystem.settings().getBool("dev.settings") ? "dev.timemachine" : "plr.timemachine");
@@ -1084,12 +1383,12 @@ void EventHandler::setActionMappings(EventMode mode)
// Fill the EmulActionList with the current key and joystick mappings
for(auto& item: ourEmulActionList)
{
- Event::Type event = item.event;
+ const Event::Type event = item.event;
item.key = "None";
string key = myPKeyHandler->getMappingDesc(event, mode);
#ifdef JOYSTICK_SUPPORT
- string joydesc = myPJoyHandler->getMappingDesc(event, mode);
+ const string joydesc = myPJoyHandler->getMappingDesc(event, mode);
if(joydesc != "")
{
if(key != "")
@@ -1106,12 +1405,12 @@ void EventHandler::setActionMappings(EventMode mode)
// Fill the MenuActionList with the current key and joystick mappings
for(auto& item: ourMenuActionList)
{
- Event::Type event = item.event;
+ const Event::Type event = item.event;
item.key = "None";
string key = myPKeyHandler->getMappingDesc(event, mode);
#ifdef JOYSTICK_SUPPORT
- string joydesc = myPJoyHandler->getMappingDesc(event, mode);
+ const string joydesc = myPJoyHandler->getMappingDesc(event, mode);
if(joydesc != "")
{
if(key != "")
@@ -1137,7 +1436,7 @@ void EventHandler::setComboMap()
string list = myOSystem.settings().getString("combomap");
replace(list.begin(), list.end(), ':', ' ');
istringstream buf(list);
- Int32 version = myOSystem.settings().getInt("event_ver");
+ const Int32 version = myOSystem.settings().getInt("event_ver");
// Erase the 'combo' array
auto ERASE_ALL = [&]() {
@@ -1199,7 +1498,7 @@ void EventHandler::removePhysicalJoystickFromDatabase(const string& name)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool EventHandler::addKeyMapping(Event::Type event, EventMode mode, StellaKey key, StellaMod mod)
{
- bool mapped = myPKeyHandler->addMapping(event, mode, key, mod);
+ const bool mapped = myPKeyHandler->addMapping(event, mode, key, mod);
if(mapped)
setActionMappings(mode);
@@ -1212,7 +1511,7 @@ bool EventHandler::addJoyMapping(Event::Type event, EventMode mode,
bool updateMenus)
{
#ifdef JOYSTICK_SUPPORT
- bool mapped = myPJoyHandler->addJoyMapping(event, mode, stick, button, axis, adir);
+ const bool mapped = myPJoyHandler->addJoyMapping(event, mode, stick, button, axis, adir);
if (mapped && updateMenus)
setActionMappings(mode);
@@ -1410,7 +1709,7 @@ VariantList EventHandler::getComboList(EventMode /**/) const
VarList::push_back(l, "None", "-1");
for(uInt32 i = 0; i < ourEmulActionList.size(); ++i)
{
- Event::Type event = EventHandler::ourEmulActionList[i].event;
+ const Event::Type event = EventHandler::ourEmulActionList[i].event;
// exclude combos events
if(!(event >= Event::Combo1 && event <= Event::Combo16))
{
@@ -1432,7 +1731,7 @@ StringList EventHandler::getComboListForEvent(Event::Type event) const
int combo = event - Event::Combo1;
for(uInt32 i = 0; i < EVENTS_PER_COMBO; ++i)
{
- Event::Type e = myComboTable[combo][i];
+ const Event::Type e = myComboTable[combo][i];
for(uInt32 j = 0; j < ourEmulActionList.size(); ++j)
{
if(EventHandler::ourEmulActionList[j].event == e)
@@ -1456,7 +1755,7 @@ void EventHandler::setComboListForEvent(Event::Type event, const StringList& eve
if(event >= Event::Combo1 && event <= Event::Combo16)
{
assert(events.size() == 8);
- int combo = event - Event::Combo1;
+ const int combo = event - Event::Combo1;
for(uInt32 i = 0; i < 8; ++i)
{
uInt32 idx = BSPF::stringToInt(events[i]);
@@ -1543,7 +1842,7 @@ int EventHandler::getActionListIndex(int idx, Event::Group group) const
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Event::Type EventHandler::eventAtIndex(int idx, Event::Group group) const
{
- int index = getActionListIndex(idx, group);
+ const int index = getActionListIndex(idx, group);
if(group == Event::Group::Menu)
{
@@ -1564,7 +1863,7 @@ Event::Type EventHandler::eventAtIndex(int idx, Event::Group group) const
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string EventHandler::actionAtIndex(int idx, Event::Group group) const
{
- int index = getActionListIndex(idx, group);
+ const int index = getActionListIndex(idx, group);
if(group == Event::Group::Menu)
{
@@ -1585,7 +1884,7 @@ string EventHandler::actionAtIndex(int idx, Event::Group group) const
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string EventHandler::keyAtIndex(int idx, Event::Group group) const
{
- int index = getActionListIndex(idx, group);
+ const int index = getActionListIndex(idx, group);
if(group == Event::Group::Menu)
{
@@ -1796,8 +2095,8 @@ void EventHandler::setState(EventHandlerState state)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::exitEmulation(bool checkLauncher)
{
- string saveOnExit = myOSystem.settings().getString("saveonexit");
- bool activeTM = myOSystem.settings().getBool(
+ const string saveOnExit = myOSystem.settings().getString("saveonexit");
+ const bool activeTM = myOSystem.settings().getBool(
myOSystem.settings().getBool("dev.settings") ? "dev.timemachine" : "plr.timemachine");
@@ -1923,32 +2222,45 @@ EventHandler::EmulActionList EventHandler::ourEmulActionList = { {
{ Event::OverscanIncrease, "Increase overscan in fullscreen mode", "" },
{ Event::VidmodeDecrease, "Previous zoom level", "" },
{ Event::VidmodeIncrease, "Next zoom level", "" },
- { Event::ScanlineAdjustDecrease, "Decrease vertical display size", "" },
- { Event::ScanlineAdjustIncrease, "Increase vertical display size", "" },
+ { Event::VSizeAdjustDecrease, "Decrease vertical display size", "" },
+ { Event::VSizeAdjustIncrease, "Increase vertical display size", "" },
{ Event::VCenterDecrease, "Move display up", "" },
{ Event::VCenterIncrease, "Move display down", "" },
{ Event::FormatDecrease, "Decrease display format", "" },
{ Event::FormatIncrease, "Increase display format", "" },
- { Event::TogglePalette, "Switch palette (Std./Z26/User/Cust.)", "" },
- { Event::ColorShiftDecrease, "Decrease custom palette phase shift", "" },
- { Event::ColorShiftIncrease, "Increase custom palette phase shift", "" },
+ // Palette settings
+ { Event::PaletteDecrease, "Switch to previous palette", "" },
+ { Event::PaletteIncrease, "Switch to next palette", "" },
+ { Event::PreviousPaletteAttribute,"Select previous palette attribute", "" },
+ { Event::NextPaletteAttribute, "Select next palette attribute", "" },
+ { Event::PaletteAttributeDecrease,"Decrease selected palette attribute", "" },
+ { Event::PaletteAttributeIncrease,"Increase selected palette attribute", "" },
{ Event::ToggleInter, "Toggle display interpolation", "" },
- // TV effects:
+ // Blargg TV effects:
{ Event::VidmodeStd, "Disable TV effects", "" },
{ Event::VidmodeRGB, "Select 'RGB' preset", "" },
{ Event::VidmodeSVideo, "Select 'S-Video' preset", "" },
{ Event::VidModeComposite, "Select 'Composite' preset", "" },
{ Event::VidModeBad, "Select 'Badly adjusted' preset", "" },
{ Event::VidModeCustom, "Select 'Custom' preset", "" },
+ { Event::PreviousVideoMode, "Select previous TV effect mode preset", "" },
+ { Event::NextVideoMode, "Select next TV effect mode preset", "" },
{ Event::PreviousAttribute, "Select previous 'Custom' attribute", "" },
{ Event::NextAttribute, "Select next 'Custom' attribute", "" },
{ Event::DecreaseAttribute, "Decrease selected 'Custom' attribute", "" },
{ Event::IncreaseAttribute, "Increase selected 'Custom' attribute", "" },
+ // Other TV effects
{ Event::TogglePhosphor, "Toggle 'phosphor' effect", "" },
{ Event::PhosphorDecrease, "Decrease 'phosphor' blend", "" },
{ Event::PhosphorIncrease, "Increase 'phosphor' blend", "" },
{ Event::ScanlinesDecrease, "Decrease scanlines", "" },
{ Event::ScanlinesIncrease, "Increase scanlines", "" },
+
+ { Event::PreviousSetting, "Select previous setting", "" },
+ { Event::NextSetting, "Select next setting", "" },
+ { Event::SettingDecrease, "Decrease current setting", "" },
+ { Event::SettingIncrease, "Increase current setting", "" },
+
// Developer keys:
{ Event::ToggleFrameStats, "Toggle frame stats", "" },
{ Event::ToggleP0Bit, "Toggle TIA Player0 object", "" },
@@ -2050,16 +2362,21 @@ const Event::EventSet EventHandler::AudioVideoEvents = {
Event::VolumeDecrease, Event::VolumeIncrease, Event::SoundToggle,
Event::VidmodeDecrease, Event::VidmodeIncrease,
Event::ToggleFullScreen,
- Event::VidmodeStd, Event::VidmodeRGB, Event::VidmodeSVideo, Event::VidModeComposite, Event::VidModeBad, Event::VidModeCustom,
- Event::PreviousAttribute, Event::NextAttribute, Event::DecreaseAttribute, Event::IncreaseAttribute,
- Event::ScanlinesDecrease, Event::ScanlinesIncrease,
- Event::PhosphorDecrease, Event::PhosphorIncrease, Event::TogglePhosphor,
+ Event::OverscanDecrease, Event::OverscanIncrease,
Event::FormatDecrease, Event::FormatIncrease,
Event::VCenterDecrease, Event::VCenterIncrease,
- Event::ScanlineAdjustDecrease, Event::ScanlineAdjustIncrease,
- Event::OverscanDecrease, Event::OverscanIncrease,
- Event::TogglePalette, Event::ColorShiftDecrease, Event::ColorShiftIncrease,
- Event::ToggleInter
+ Event::VSizeAdjustDecrease, Event::VSizeAdjustIncrease,
+ Event::PaletteDecrease, Event::PaletteIncrease,
+ Event::PreviousPaletteAttribute, Event::NextPaletteAttribute,
+ Event::PaletteAttributeDecrease, Event::PaletteAttributeIncrease,
+ Event::VidmodeStd, Event::VidmodeRGB, Event::VidmodeSVideo, Event::VidModeComposite, Event::VidModeBad, Event::VidModeCustom,
+ Event::PreviousVideoMode, Event::NextVideoMode,
+ Event::PreviousAttribute, Event::NextAttribute, Event::DecreaseAttribute, Event::IncreaseAttribute,
+ Event::PhosphorDecrease, Event::PhosphorIncrease, Event::TogglePhosphor,
+ Event::ScanlinesDecrease, Event::ScanlinesIncrease,
+ Event::ToggleInter,
+ Event::PreviousSetting, Event::NextSetting,
+ Event::SettingDecrease, Event::SettingIncrease,
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/src/emucore/EventHandler.hxx b/src/emucore/EventHandler.hxx
index 8fe4c7821..0ab40c7cd 100644
--- a/src/emucore/EventHandler.hxx
+++ b/src/emucore/EventHandler.hxx
@@ -25,6 +25,7 @@ class OSystem;
class MouseControl;
class DialogContainer;
class PhysicalJoystick;
+class Variant;
namespace GUI {
class Font;
@@ -36,7 +37,6 @@ namespace GUI {
#include "StellaKeys.hxx"
#include "PKeyboardHandler.hxx"
#include "PJoystickHandler.hxx"
-#include "Variant.hxx"
#include "bspf.hxx"
/**
@@ -391,6 +391,43 @@ class EventHandler
*/
void removePhysicalJoystick(int index);
+ private:
+ enum class AdjustSetting
+ {
+ NONE = -1,
+ VOLUME,
+ ZOOM,
+ FULLSCREEN,
+ OVERSCAN,
+ TVFORMAT,
+ VCENTER,
+ VSIZE,
+ // Palette adjustables
+ PALETTE,
+ PALETTE_PHASE,
+ PALETTE_HUE,
+ PALETTE_SATURATION,
+ PALETTE_CONTRAST,
+ PALETTE_BRIGHTNESS,
+ PALETTE_GAMMA,
+ // NTSC filter adjustables
+ NTSC_PRESET,
+ NTSC_SHARPNESS,
+ NTSC_RESOLUTION,
+ NTSC_ARTIFACTS,
+ NTSC_FRINGING,
+ NTSC_BLEEDING,
+ PHOSPHOR,
+ SCANLINES,
+ INTERPOLATION,
+ MAX_ADJ = INTERPOLATION,
+ // Only used via direct hotkeys
+ STATE,
+ PALETTE_CHANGE_ATTRIBUTE,
+ NTSC_CHANGE_ATTRIBUTE,
+ NUM_ADJ
+ };
+
private:
// Define event groups
static const Event::EventSet MiscEvents;
@@ -417,6 +454,11 @@ class EventHandler
int getEmulActionListIndex(int idx, const Event::EventSet& events) const;
int getActionListIndex(int idx, Event::Group group) const;
+ // The following two methods are used for adjusting several settings using global hotkeys
+ // They return the function used to adjust the currenly selected setting
+ AdjustFunction cycleAdjustSetting(int direction);
+ AdjustFunction getAdjustSetting(AdjustSetting setting);
+
private:
// Structure used for action menu items
struct ActionList {
@@ -425,6 +467,13 @@ class EventHandler
string key;
};
+ // ID of the currently selected global setting
+ AdjustSetting myAdjustSetting{AdjustSetting::VOLUME};
+ // If true, the setting is visible and its value can be changed
+ bool myAdjustActive{false};
+ // ID of the currently selected direct hotkey setting (0 if none)
+ AdjustSetting myAdjustDirect{AdjustSetting::NONE};
+
// Global Event object
Event myEvent;
@@ -468,7 +517,7 @@ class EventHandler
#else
PNG_SIZE = 0,
#endif
- EMUL_ACTIONLIST_SIZE = 149 + PNG_SIZE + COMBO_SIZE,
+ EMUL_ACTIONLIST_SIZE = 156 + PNG_SIZE + COMBO_SIZE,
MENU_ACTIONLIST_SIZE = 18
;
diff --git a/src/emucore/FrameBuffer.cxx b/src/emucore/FrameBuffer.cxx
index 250a895cf..4599a3860 100644
--- a/src/emucore/FrameBuffer.cxx
+++ b/src/emucore/FrameBuffer.cxx
@@ -171,10 +171,9 @@ void FrameBuffer::setupFonts()
// However, we have to make sure all Dialogs are sized using the fontsize.
int zoom_h = (fd.height * 4 * 2) / GUI::stellaMediumDesc.height;
int zoom_w = (fd.maxwidth * 4 * 2) / GUI::stellaMediumDesc.maxwidth;
- myTIAMinZoom = std::max(zoom_w, zoom_h) / 4.F; // round to 25% steps
+ myTIAMinZoom = std::max(std::max(zoom_w, zoom_h) / 4.F, 2.F); // round to 25% steps, >= 200%
}
-
// The font used by the ROM launcher
const string& lf = myOSystem.settings().getString("launcherfont");
@@ -310,7 +309,12 @@ FBInitStatus FrameBuffer::createDisplay(const string& title, BufferType type,
}
if(!myMsg.surface)
- myMsg.surface = allocateSurface(FBMinimum::Width, font().getFontHeight() * 1.5);
+ {
+ const int fontWidth = font().getMaxCharWidth(),
+ HBORDER = fontWidth * 1.25 / 2.0;
+ myMsg.surface = allocateSurface(fontWidth * MESSAGE_WIDTH + HBORDER * 2,
+ font().getFontHeight() * 1.5);
+ }
#endif
// Print initial usage message, but only print it later if the status has changed
@@ -501,19 +505,72 @@ void FrameBuffer::showMessage(const string& message, MessagePosition position,
const int VBORDER = fontHeight / 4;
const int HBORDER = fontWidth * 1.25 / 2.0;
- // Precompute the message coordinates
- myMsg.text = message;
- myMsg.counter = uInt32(myOSystem.frameRate()) << 1; // Show message for 2 seconds
- if(myMsg.counter == 0) myMsg.counter = 60;
- myMsg.color = kBtnTextColor;
+ myMsg.counter = uInt32(myOSystem.frameRate()) * 2; // Show message for 2 seconds
+ if(myMsg.counter == 0)
+ myMsg.counter = 120;
- myMsg.w = font().getStringWidth(myMsg.text) + HBORDER * 2;
- myMsg.h = fontHeight + VBORDER * 2;
+ // Precompute the message coordinates
+ myMsg.text = message;
+ myMsg.color = kBtnTextColor;
+ myMsg.showGauge = false;
+ myMsg.w = font().getStringWidth(myMsg.text) + HBORDER * 2;
+ myMsg.h = fontHeight + VBORDER * 2;
+ myMsg.position = position;
+ myMsg.enabled = true;
myMsg.surface->setSrcSize(myMsg.w, myMsg.h);
myMsg.surface->setDstSize(myMsg.w * hidpiScaleFactor(), myMsg.h * hidpiScaleFactor());
- myMsg.position = position;
- myMsg.enabled = true;
+#endif
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void FrameBuffer::showMessage(const string& message, const string& valueText,
+ float value, float minValue, float maxValue)
+{
+#ifdef GUI_SUPPORT
+ // Only show messages if they've been enabled
+ if(myMsg.surface == nullptr || !myOSystem.settings().getBool("uimessages"))
+ return;
+
+ const int fontWidth = font().getMaxCharWidth(),
+ fontHeight = font().getFontHeight();
+ const int VBORDER = fontHeight / 4;
+ const int HBORDER = fontWidth * 1.25 / 2.0;
+
+ myMsg.counter = uInt32(myOSystem.frameRate()) * 2; // Show message for 2 seconds
+ if(myMsg.counter == 0)
+ myMsg.counter = 120;
+
+ // Precompute the message coordinates
+ myMsg.text = message;
+ myMsg.color = kBtnTextColor;
+ myMsg.showGauge = true;
+ if(maxValue - minValue != 0)
+ myMsg.value = (value - minValue) / (maxValue - minValue) * 100.F;
+ else
+ myMsg.value = 100.F;
+ myMsg.valueText = valueText;
+ myMsg.w = std::min(fontWidth * MESSAGE_WIDTH,
+ font().getStringWidth(myMsg.text)
+ + fontWidth * (GAUGEBAR_WIDTH + 2)
+ + font().getStringWidth(myMsg.valueText))
+ + HBORDER * 2;
+ myMsg.h = fontHeight + VBORDER * 2;
+ myMsg.position = MessagePosition::BottomCenter;
+ myMsg.enabled = true;
+
+ myMsg.surface->setSrcSize(myMsg.w, myMsg.h);
+ myMsg.surface->setDstSize(myMsg.w * hidpiScaleFactor(), myMsg.h * hidpiScaleFactor());
+#endif
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+bool FrameBuffer::messageShown()
+{
+#ifdef GUI_SUPPORT
+ return myMsg.enabled;
+#else
+ return false;
#endif
}
@@ -632,6 +689,7 @@ inline bool FrameBuffer::drawMessage()
fontHeight = font().getFontHeight();
const int VBORDER = fontHeight / 4;
const int HBORDER = fontWidth * 1.25 / 2.0;
+ constexpr int BORDER = 1;
switch(myMsg.position)
{
@@ -682,10 +740,44 @@ inline bool FrameBuffer::drawMessage()
}
myMsg.surface->setDstPos(myMsg.x + myImageRect.x(), myMsg.y + myImageRect.y());
- myMsg.surface->fillRect(1, 1, myMsg.w - 2, myMsg.h - 2, kBtnColor);
- myMsg.surface->frameRect(0, 0, myMsg.w, myMsg.h, kColor);
+ myMsg.surface->fillRect(0, 0, myMsg.w, myMsg.h, kColor);
+ myMsg.surface->fillRect(BORDER, BORDER, myMsg.w - BORDER * 2, myMsg.h - BORDER * 2, kBtnColor);
myMsg.surface->drawString(font(), myMsg.text, HBORDER, VBORDER,
myMsg.w, myMsg.color);
+
+ if(myMsg.showGauge)
+ {
+ constexpr int NUM_TICKMARKS = 4;
+ // limit gauge bar width if texts are too long
+ const int swidth = std::min(fontWidth * GAUGEBAR_WIDTH,
+ fontWidth * (MESSAGE_WIDTH - 2)
+ - font().getStringWidth(myMsg.text)
+ - font().getStringWidth(myMsg.valueText));
+ const int bwidth = swidth * myMsg.value / 100.F;
+ const int bheight = fontHeight >> 1;
+ const int x = HBORDER + font().getStringWidth(myMsg.text) + fontWidth;
+ // align bar with bottom of text
+ const int y = VBORDER + font().desc().ascent - bheight;
+
+ // draw gauge bar
+ myMsg.surface->fillRect(x - BORDER, y, swidth + BORDER * 2, bheight, kSliderBGColor);
+ myMsg.surface->fillRect(x, y + BORDER, bwidth, bheight - BORDER * 2, kSliderColor);
+ // draw tickmark in the middle of the bar
+ for(int i = 1; i < NUM_TICKMARKS; ++i)
+ {
+ ColorId color;
+ int xt = x + swidth * i / NUM_TICKMARKS;
+ if(bwidth < xt - x)
+ color = kCheckColor; // kSliderColor;
+ else
+ color = kSliderBGColor;
+ myMsg.surface->vLine(xt, y + bheight / 2, y + bheight - 1, color);
+ }
+ // draw value text
+ myMsg.surface->drawString(font(), myMsg.valueText,
+ x + swidth + fontWidth, VBORDER,
+ myMsg.w, myMsg.color);
+ }
myMsg.surface->render();
myMsg.counter--;
#endif
@@ -895,9 +987,13 @@ void FrameBuffer::setFullscreen(bool enable)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void FrameBuffer::toggleFullscreen()
+void FrameBuffer::toggleFullscreen(bool toggle)
{
- setFullscreen(!fullScreen());
+ const bool isFullscreen = toggle ? !fullScreen() : fullScreen();
+
+ setFullscreen(isFullscreen);
+
+ showMessage(string("Fullscreen ") + (isFullscreen ? "enabled" : "disabled"));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -915,14 +1011,18 @@ void FrameBuffer::changeOverscan(int direction)
// issue a complete framebuffer re-initialization
myOSystem.createFrameBuffer();
}
- ostringstream msg;
- msg << "Overscan at " << overscan << "%";
- showMessage(msg.str());
+
+ ostringstream val;
+ if(overscan)
+ val << (overscan > 0 ? "+" : "" ) << overscan << "%";
+ else
+ val << "Off";
+ myOSystem.frameBuffer().showMessage("Overscan", val.str(), overscan, 0, 10);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-bool FrameBuffer::changeVidMode(int direction)
+void FrameBuffer::selectVidMode(int direction)
{
EventHandlerState state = myOSystem.eventHandler().state();
bool tiaMode = (state != EventHandlerState::DEBUGGER &&
@@ -930,14 +1030,14 @@ bool FrameBuffer::changeVidMode(int direction)
// Only applicable when in TIA/emulation mode
if(!tiaMode)
- return false;
+ return;
if(direction == +1)
myCurrentModeList->next();
else if(direction == -1)
myCurrentModeList->previous();
- else
- return false;
+
+ saveCurrentWindowPosition();
// Changing the video mode can take some time, during which the last
// sound played may get 'stuck'
@@ -955,7 +1055,10 @@ bool FrameBuffer::changeVidMode(int direction)
myTIASurface->initialize(myOSystem.console(), mode);
resetSurfaces();
- showMessage(mode.description);
+ if(fullScreen())
+ showMessage(mode.description);
+ else
+ showMessage("Zoom", mode.description, mode.zoom, supportedTIAMinZoom(), myTIAMaxZoom);
myOSystem.sound().mute(oldMuteState);
if(fullScreen())
@@ -964,11 +1067,9 @@ bool FrameBuffer::changeVidMode(int direction)
else
myOSystem.settings().setValue("tia.zoom", mode.zoom);
- return true;
+ return;
}
myOSystem.sound().mute(oldMuteState);
-
- return false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -1023,9 +1124,14 @@ void FrameBuffer::enableGrabMouse(bool enable)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::toggleGrabMouse()
{
+ const bool oldState = myGrabMouse;
+
myGrabMouse = !myGrabMouse;
setCursorState();
myOSystem.settings().setValue("grabmouse", myGrabMouse);
+ myOSystem.frameBuffer().showMessage(oldState != myGrabMouse ? myGrabMouse
+ ? "Grab mouse enabled" : "Grab mouse disabled"
+ : "Grab mouse not allowed while cursor shown");
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -1076,7 +1182,7 @@ void FrameBuffer::setAvailableVidModes(uInt32 baseWidth, uInt32 baseHeight)
for(float zoom = minZoom; zoom <= myTIAMaxZoom; zoom += ZOOM_STEPS)
{
ostringstream desc;
- desc << "Zoom " << zoom << "x";
+ desc << (zoom * 100) << "%";
VideoMode mode(baseWidth*zoom, baseHeight*zoom, baseWidth*zoom, baseHeight*zoom,
VideoMode::Stretch::Fill, 1.0, desc.str(), zoom);
@@ -1096,12 +1202,12 @@ void FrameBuffer::setAvailableVidModes(uInt32 baseWidth, uInt32 baseHeight)
VideoMode mode1(baseWidth * myTIAMaxZoom, baseHeight * myTIAMaxZoom,
myFullscreenDisplays[i].w, myFullscreenDisplays[i].h,
VideoMode::Stretch::Preserve, overscan,
- "Preserve aspect, no stretch", myTIAMaxZoom, i);
+ "Fullscreen: Preserve aspect, no stretch", myTIAMaxZoom, i);
myFullscreenModeLists[i].add(mode1);
VideoMode mode2(baseWidth * myTIAMaxZoom, baseHeight * myTIAMaxZoom,
myFullscreenDisplays[i].w, myFullscreenDisplays[i].h,
VideoMode::Stretch::Fill, overscan,
- "Ignore aspect, full stretch", myTIAMaxZoom, i);
+ "Fullscreen: Ignore aspect, full stretch", myTIAMaxZoom, i);
myFullscreenModeLists[i].add(mode2);
}
}
diff --git a/src/emucore/FrameBuffer.hxx b/src/emucore/FrameBuffer.hxx
index a73b01ffb..3912f38cd 100644
--- a/src/emucore/FrameBuffer.hxx
+++ b/src/emucore/FrameBuffer.hxx
@@ -147,6 +147,19 @@ class FrameBuffer
void showMessage(const string& message,
MessagePosition position = MessagePosition::BottomCenter,
bool force = false);
+ /**
+ Shows a message with a gauge bar onscreen.
+
+ @param message The message to be shown
+ @param valueText The value of the gauge bar as text
+ @param value The gauge bar percentage
+ @param minValue The minimal value of the gauge bar
+ @param maxValue The maximal value of the gauge bar
+ */
+ void showMessage(const string& message, const string& valueText,
+ float value, float minValue = 0.F, float maxValue = 100.F);
+
+ bool messageShown();
/**
Toggles showing or hiding framerate statistics.
@@ -247,14 +260,14 @@ class FrameBuffer
/**
Toggles between fullscreen and window mode.
*/
- void toggleFullscreen();
+ void toggleFullscreen(bool toggle = true);
/**
Changes the fullscreen overscan.
- direction = -1 means less overscan
- direction = +1 means more overscan
+
+ @param direction +1 indicates increase, -1 indicates decrease.
*/
- void changeOverscan(int direction);
+ void changeOverscan(int direction = +1);
/**
This method is called when the user wants to switch to the next
@@ -264,9 +277,9 @@ class FrameBuffer
direction = -1 means go to the next lower video mode
direction = +1 means go to the next higher video mode
- @param direction Described above
+ @param direction +1 indicates increase, -1 indicates decrease.
*/
- bool changeVidMode(int direction);
+ void selectVidMode(int direction = +1);
/**
Sets the state of the cursor (hidden or grabbed) based on the
@@ -502,6 +515,11 @@ class FrameBuffer
OSystem& myOSystem;
private:
+ // Maximum message width [chars]
+ static constexpr int MESSAGE_WIDTH = 56;
+ // Maximum gauge bar width [chars]
+ static constexpr int GAUGEBAR_WIDTH = 30;
+
/**
Draw pending messages.
@@ -648,6 +666,9 @@ class FrameBuffer
ColorId color{kNone};
shared_ptr surface;
bool enabled{false};
+ bool showGauge{false};
+ float value{0.0F};
+ string valueText;
};
Message myMsg;
Message myStatsMsg;
diff --git a/src/emucore/Joystick.hxx b/src/emucore/Joystick.hxx
index 7acd631bc..505294456 100644
--- a/src/emucore/Joystick.hxx
+++ b/src/emucore/Joystick.hxx
@@ -19,8 +19,8 @@
#define JOYSTICK_HXX
#include "bspf.hxx"
-#include "Control.hxx"
#include "Event.hxx"
+#include "Control.hxx"
/**
The standard Atari 2600 joystick controller.
diff --git a/src/emucore/Keyboard.hxx b/src/emucore/Keyboard.hxx
index a241cbc37..9ec176d71 100644
--- a/src/emucore/Keyboard.hxx
+++ b/src/emucore/Keyboard.hxx
@@ -19,8 +19,8 @@
#define KEYBOARD_HXX
#include "bspf.hxx"
-#include "Control.hxx"
#include "Event.hxx"
+#include "Control.hxx"
/**
The standard Atari 2600 keyboard controller
diff --git a/src/emucore/Lightgun.hxx b/src/emucore/Lightgun.hxx
index 7bec4f4e2..facdffe1e 100644
--- a/src/emucore/Lightgun.hxx
+++ b/src/emucore/Lightgun.hxx
@@ -18,6 +18,11 @@
#ifndef LIGHTGUN_HXX
#define LIGHTGUN_HXX
+class FrameBuffer;
+
+#include "bspf.hxx"
+#include "Control.hxx"
+
/**
This class handles the lightgun controller
diff --git a/src/emucore/OSystem.cxx b/src/emucore/OSystem.cxx
index ccf6838cb..9c84b4165 100644
--- a/src/emucore/OSystem.cxx
+++ b/src/emucore/OSystem.cxx
@@ -49,6 +49,7 @@
#include "CartDetector.hxx"
#include "FrameBuffer.hxx"
#include "TIASurface.hxx"
+#include "PaletteHandler.hxx"
#include "TIAConstants.hxx"
#include "Settings.hxx"
#include "PropsSet.hxx"
@@ -243,6 +244,8 @@ void OSystem::saveConfig()
Logger::debug("Saving TV effects options ...");
myFrameBuffer->tiaSurface().ntsc().saveConfig(settings());
+ Logger::debug("Saving palette settings...");
+ myFrameBuffer->tiaSurface().paletteHandler().saveConfig(settings());
}
Logger::debug("Saving config options ...");
@@ -645,35 +648,8 @@ ByteBuffer OSystem::openROM(const FilesystemNode& rom, string& md5, size_t& size
if(md5 == "")
md5 = MD5::hash(image, size);
- // Handle ROM properties, do some error checking
- // Only add to the database when necessary
- bool toInsert = false;
-
- // First, does this ROM have a per-ROM properties entry?
- // If so, load it into the database
- FilesystemNode propsNode(rom.getPathWithExt(".pro"));
- if(propsNode.exists() && propsNode.isFile())
- {
- Logger::info("Loading per-ROM properties: " + propsNode.getShortPath());
- myPropSet->load(propsNode.getPath(), false);
- }
-
- // Next, make sure we have a valid md5 and name
- Properties props;
- if(!myPropSet->getMD5(md5, props))
- {
- props.set(PropType::Cart_MD5, md5);
- toInsert = true;
- }
- if(toInsert || props.get(PropType::Cart_Name) == EmptyString)
- {
- props.set(PropType::Cart_Name, rom.getNameWithExt(""));
- toInsert = true;
- }
-
- // Finally, insert properties if any info was missing
- if(toInsert)
- myPropSet->insert(props, false);
+ // Make sure to load a per-ROM properties entry, if one exists
+ myPropSet->loadPerROM(rom, md5);
return image;
}
diff --git a/src/emucore/OSystem.hxx b/src/emucore/OSystem.hxx
index b23cbdb83..2bc5368c6 100644
--- a/src/emucore/OSystem.hxx
+++ b/src/emucore/OSystem.hxx
@@ -41,7 +41,7 @@ class AudioSettings;
class Menu;
class MessageMenu;
class TimeMachine;
- class VideoDialog;
+ class VideoAudioDialog;
#endif
#ifdef PNG_SUPPORT
class PNGLibrary;
diff --git a/src/emucore/PointingDevice.cxx b/src/emucore/PointingDevice.cxx
index 1a2c781b4..4d91d010c 100644
--- a/src/emucore/PointingDevice.cxx
+++ b/src/emucore/PointingDevice.cxx
@@ -15,6 +15,8 @@
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
+#include
+
#include "Control.hxx"
#include "Event.hxx"
#include "System.hxx"
diff --git a/src/emucore/PointingDevice.hxx b/src/emucore/PointingDevice.hxx
index 4f0a007b5..11b9fcd2d 100644
--- a/src/emucore/PointingDevice.hxx
+++ b/src/emucore/PointingDevice.hxx
@@ -18,7 +18,6 @@
#ifndef POINTING_DEVICE_HXX
#define POINTING_DEVICE_HXX
-class Controller;
class Event;
#include "Control.hxx"
diff --git a/src/emucore/ProfilingRunner.cxx b/src/emucore/ProfilingRunner.cxx
index f561dc7a1..e7d81b997 100644
--- a/src/emucore/ProfilingRunner.cxx
+++ b/src/emucore/ProfilingRunner.cxx
@@ -54,7 +54,6 @@ namespace {
}
}
-
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ProfilingRunner::ProfilingRunner(int argc, char* argv[])
: profilingRuns(std::max(argc - 2, 0))
diff --git a/src/emucore/ProfilingRunner.hxx b/src/emucore/ProfilingRunner.hxx
index 1194cfdda..a3523b98f 100644
--- a/src/emucore/ProfilingRunner.hxx
+++ b/src/emucore/ProfilingRunner.hxx
@@ -18,10 +18,9 @@
#ifndef PROFILING_RUNNER
#define PROFILING_RUNNER
-class Control;
-class Switches;
-
#include "bspf.hxx"
+#include "Control.hxx"
+#include "Switches.hxx"
#include "Settings.hxx"
#include "ConsoleIO.hxx"
#include "Props.hxx"
@@ -41,13 +40,13 @@ class ProfilingRunner {
};
struct IO: public ConsoleIO {
- Controller& leftController() const override { return *myLeftControl; }
- Controller& rightController() const override { return *myRightControl; }
- Switches& switches() const override { return *mySwitches; }
+ Controller& leftController() const override { return *myLeftControl; }
+ Controller& rightController() const override { return *myRightControl; }
+ Switches& switches() const override { return *mySwitches; }
- unique_ptr myLeftControl;
- unique_ptr myRightControl;
- unique_ptr mySwitches;
+ unique_ptr myLeftControl;
+ unique_ptr myRightControl;
+ unique_ptr mySwitches;
};
private:
diff --git a/src/emucore/PropsSet.cxx b/src/emucore/PropsSet.cxx
index a13a9c759..a74a999e7 100644
--- a/src/emucore/PropsSet.cxx
+++ b/src/emucore/PropsSet.cxx
@@ -156,6 +156,37 @@ void PropertiesSet::insert(const Properties& properties, bool save)
}
}
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void PropertiesSet::loadPerROM(const FilesystemNode& rom, const string& md5)
+{
+ // Handle ROM properties, do some error checking
+ // Only add to the database when necessary
+ bool toInsert = false;
+
+ // First, does this ROM have a per-ROM properties entry?
+ // If so, load it into the database
+ FilesystemNode propsNode(rom.getPathWithExt(".pro"));
+ if(propsNode.exists() && propsNode.isFile())
+ load(propsNode.getPath(), false);
+
+ // Next, make sure we have a valid md5 and name
+ Properties props;
+ if(!getMD5(md5, props))
+ {
+ props.set(PropType::Cart_MD5, md5);
+ toInsert = true;
+ }
+ if(toInsert || props.get(PropType::Cart_Name) == EmptyString)
+ {
+ props.set(PropType::Cart_Name, rom.getNameWithExt(""));
+ toInsert = true;
+ }
+
+ // Finally, insert properties if any info was missing
+ if(toInsert)
+ insert(props, false);
+}
+
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PropertiesSet::print() const
{
diff --git a/src/emucore/PropsSet.hxx b/src/emucore/PropsSet.hxx
index 71924749a..f5a763ef8 100644
--- a/src/emucore/PropsSet.hxx
+++ b/src/emucore/PropsSet.hxx
@@ -42,7 +42,7 @@ class PropertiesSet
/**
Trivial constructor.
*/
- PropertiesSet() = default;
+ PropertiesSet() = default;
/**
Load properties from the specified file, and create an internal
@@ -90,6 +90,21 @@ class PropertiesSet
*/
void insert(const Properties& properties, bool save = true);
+ /**
+ Load properties for a specific ROM from a per-ROM properties file,
+ if it exists. In any event, also do some error checking, like making
+ sure that the properties have a valid name, etc.
+
+ NOTE: This method is meant to be called only when starting Stella
+ and loading a ROM for the first time. Currently, that means
+ only from the ROM launcher or when actually opening the ROM.
+ *** FOR ALL OTHER CASES, USE getMD5() ***
+
+ @param rom The node representing the rom file
+ @param md5 The md5 of the property to get
+ */
+ void loadPerROM(const FilesystemNode& rom, const string& md5);
+
/**
Prints the contents of the PropertiesSet as a flat file.
*/
diff --git a/src/emucore/Settings.cxx b/src/emucore/Settings.cxx
index c1c64dd20..f5e120408 100644
--- a/src/emucore/Settings.cxx
+++ b/src/emucore/Settings.cxx
@@ -21,6 +21,7 @@
#include "Version.hxx"
#include "Logger.hxx"
#include "AudioSettings.hxx"
+#include "PaletteHandler.hxx"
#include "Paddles.hxx"
#ifdef DEBUGGER_SUPPORT
@@ -45,31 +46,30 @@ Settings::Settings()
setPermanent("center", "true");
setPermanent("windowedpos", Common::Point(50, 50));
setPermanent("display", 0);
- setPermanent("palette", "standard");
- setPermanent("phase_ntsc", "26.2");
- setPermanent("phase_pal", "31.3");
setPermanent("uimessages", "true");
-
// TIA specific options
- setPermanent("tia.zoom", "3");
setPermanent("tia.inter", "false");
- setPermanent("tia.vsizeadjust", 0);
+ setPermanent("tia.zoom", "3");
setPermanent("fullscreen", "false");
setPermanent("tia.fs_stretch", "false");
setPermanent("tia.fs_overscan", "0");
+ setPermanent("tia.vsizeadjust", 0);
setPermanent("tia.dbgcolors", "roygpb");
-
+ // Palette options
+ setPermanent("palette", PaletteHandler::SETTING_STANDARD);
+ setPermanent("pal.phase_ntsc", "26.2");
+ setPermanent("pal.phase_pal", "31.3");
+ setPermanent("pal.contrast", "0.0");
+ setPermanent("pal.brightness", "0.0");
+ setPermanent("pal.hue", "0.0");
+ setPermanent("pal.saturation", "0.0");
+ setPermanent("pal.gamma", "0.0");
// TV filtering options
setPermanent("tv.filter", "0");
setPermanent("tv.phosphor", "byrom");
setPermanent("tv.phosblend", "50");
setPermanent("tv.scanlines", "25");
// TV options when using 'custom' mode
- setPermanent("tv.contrast", "0.0");
- setPermanent("tv.brightness", "0.0");
- setPermanent("tv.hue", "0.0");
- setPermanent("tv.saturation", "0.0");
- setPermanent("tv.gamma", "0.0");
setPermanent("tv.sharpness", "0.0");
setPermanent("tv.resolution", "0.0");
setPermanent("tv.artifacts", "0.0");
@@ -358,8 +358,11 @@ void Settings::validate()
else if(i > 10) setValue("ssinterval", "10");
s = getString("palette");
- if(s != "standard" && s != "z26" && s != "user" && s != "custom")
- setValue("palette", "standard");
+ if(s != PaletteHandler::SETTING_STANDARD
+ && s != PaletteHandler::SETTING_Z26
+ && s != PaletteHandler::SETTING_USER
+ && s != PaletteHandler::SETTING_CUSTOM)
+ setValue("palette", PaletteHandler::SETTING_STANDARD);
s = getString("launcherfont");
if(s != "small" && s != "low_medium" && s != "medium" && s != "large"
@@ -407,8 +410,13 @@ void Settings::usage() const
<< " -palette \n"
- << " -phase_ntsc Phase shift for NTSC custom color palette\n"
- << " -phase_pal Phase shift for PAL custom color palette\n"
+ << " -pal.phase_ntsc Phase shift for NTSC 'custom' palette\n"
+ << " -pal.phase_pal Phase shift for PAL 'custom' palette\n"
+ << " -pal.hue <-1.0 - 1.0> Adjust hue for current palette\n"
+ << " -pal.saturation <-1.0 - 1.0> Adjust saturation of current palette\n"
+ << " -pal.contrast <-1.0 - 1.0> Adjust contrast of current palette\n"
+ << " -pal.brightness <-1.0 - 1.0> Adjust brightness of current palette\n"
+ << " -pal.gamma <-1.0 - 1.0> Adjust gamma of current palette\n"
<< " -speed Run emulation at the given speed\n"
<< " -turbo <1|0> Enable 'Turbo' mode for maximum emulation speed\n"
<< " -uimessages <1|0> Show onscreen UI messages for different events\n"
@@ -443,11 +451,6 @@ void Settings::usage() const
<< " -tv.phosblend <0-100> Set default blend level in phosphor mode\n"
<< " -tv.scanlines <0-100> Set scanline intensity to percentage\n"
<< " (0 disables completely)\n"
- << " -tv.contrast <-1.0 - 1.0> Set TV effects custom contrast\n"
- << " -tv.brightness <-1.0 - 1.0> Set TV effects custom brightness\n"
- << " -tv.hue <-1.0 - 1.0> Set TV effects custom hue\n"
- << " -tv.saturation <-1.0 - 1.0> Set TV effects custom saturation\n"
- << " -tv.gamma <-1.0 - 1.0> Set TV effects custom gamma\n"
<< " -tv.sharpness <-1.0 - 1.0> Set TV effects custom sharpness\n"
<< " -tv.resolution <-1.0 - 1.0> Set TV effects custom resolution\n"
<< " -tv.artifacts <-1.0 - 1.0> Set TV effects custom artifacts\n"
diff --git a/src/emucore/Sound.hxx b/src/emucore/Sound.hxx
index f74705489..4e1fda0d5 100644
--- a/src/emucore/Sound.hxx
+++ b/src/emucore/Sound.hxx
@@ -88,10 +88,9 @@ class Sound
/**
Adjusts the volume of the sound device based on the given direction.
- @param direction Increase or decrease the current volume by a predefined
- amount based on the direction (1 = increase, -1 =decrease)
+ @param direction +1 indicates increase, -1 indicates decrease.
*/
- virtual void adjustVolume(Int8 direction) = 0;
+ virtual void adjustVolume(int direction = 1) = 0;
/**
This method is called to provide information about the sound device.
diff --git a/src/emucore/Switches.hxx b/src/emucore/Switches.hxx
index fb7ae4539..16c4dba74 100644
--- a/src/emucore/Switches.hxx
+++ b/src/emucore/Switches.hxx
@@ -22,8 +22,8 @@ class Event;
class Properties;
class Settings;
-#include "Serializable.hxx"
#include "bspf.hxx"
+#include "Serializable.hxx"
/**
This class represents the console switches of the game console.
diff --git a/src/emucore/System.hxx b/src/emucore/System.hxx
index 1c36acf53..dab87b28a 100644
--- a/src/emucore/System.hxx
+++ b/src/emucore/System.hxx
@@ -18,11 +18,10 @@
#ifndef SYSTEM_HXX
#define SYSTEM_HXX
-class Device;
class M6502;
class M6532;
class TIA;
-class NullDevice;
+class Cartridge;
#include "bspf.hxx"
#include "Device.hxx"
diff --git a/src/emucore/TIASurface.cxx b/src/emucore/TIASurface.cxx
index a13a9fd83..afaad7855 100644
--- a/src/emucore/TIASurface.cxx
+++ b/src/emucore/TIASurface.cxx
@@ -23,6 +23,7 @@
#include "Console.hxx"
#include "TIA.hxx"
#include "PNGLibrary.hxx"
+#include "PaletteHandler.hxx"
#include "TIASurface.hxx"
namespace {
@@ -76,6 +77,14 @@ TIASurface::TIASurface(OSystem& system)
// Enable/disable threading in the NTSC TV effects renderer
myNTSCFilter.enableThreading(myOSystem.settings().getBool("threads"));
+
+ myPaletteHandler = make_unique(myOSystem);
+ myPaletteHandler->loadConfig(myOSystem.settings());
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+TIASurface::~TIASurface()
+{
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -89,6 +98,8 @@ void TIASurface::initialize(const Console& console,
mySLineSurface->setDstPos(mode.image.x(), mode.image.y());
mySLineSurface->setDstSize(mode.image.w(), mode.image.h());
+ myPaletteHandler->setPalette();
+
// Phosphor mode can be enabled either globally or per-ROM
int p_blend = 0;
bool enable = false;
@@ -189,37 +200,87 @@ void TIASurface::setNTSC(NTSCFilter::Preset preset, bool show)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void TIASurface::setScanlineIntensity(int amount)
+void TIASurface::changeNTSC(int direction)
{
- ostringstream buf;
- uInt32 intensity = enableScanlines(amount);
+ constexpr NTSCFilter::Preset PRESETS[] = {
+ NTSCFilter::Preset::OFF, NTSCFilter::Preset::RGB, NTSCFilter::Preset::SVIDEO,
+ NTSCFilter::Preset::COMPOSITE, NTSCFilter::Preset::BAD, NTSCFilter::Preset::CUSTOM
+ };
+ int preset = myOSystem.settings().getInt("tv.filter");
- if(intensity == 0)
- buf << "Scanlines disabled";
- else
+ if(direction == +1)
{
- buf << "Scanline intensity at ";
- if(intensity < 100)
- buf << intensity << "%";
+ if(preset == int(NTSCFilter::Preset::CUSTOM))
+ preset = int(NTSCFilter::Preset::OFF);
else
- buf << "maximum";
+ preset++;
}
- myOSystem.settings().setValue("tv.scanlines", intensity);
-
- enableNTSC(ntscEnabled());
-
- myFB.showMessage(buf.str());
+ else if (direction == -1)
+ {
+ if(preset == int(NTSCFilter::Preset::OFF))
+ preset = int(NTSCFilter::Preset::CUSTOM);
+ else
+ preset--;
+ }
+ setNTSC(PRESETS[preset], true);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-uInt32 TIASurface::enableScanlines(int relative, int absolute)
+void TIASurface::setNTSCAdjustable(int direction)
+{
+ string text, valueText;
+ Int32 value;
+
+ setNTSC(NTSCFilter::Preset::CUSTOM);
+ ntsc().selectAdjustable(direction, text, valueText, value);
+ myOSystem.frameBuffer().showMessage(text, valueText, value);
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void TIASurface::changeNTSCAdjustable(int adjustable, int direction)
+{
+ string text, valueText;
+ Int32 newValue;
+
+ setNTSC(NTSCFilter::Preset::CUSTOM);
+ ntsc().changeAdjustable(adjustable, direction, text, valueText, newValue);
+ myOSystem.frameBuffer().showMessage(text, valueText, newValue);
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void TIASurface::changeCurrentNTSCAdjustable(int direction)
+{
+ string text, valueText;
+ Int32 newValue;
+
+ setNTSC(NTSCFilter::Preset::CUSTOM);
+ ntsc().changeCurrentAdjustable(direction, text, valueText, newValue);
+ myOSystem.frameBuffer().showMessage(text, valueText, newValue);
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void TIASurface::setScanlineIntensity(int direction)
+{
+ ostringstream buf;
+ uInt32 intensity = enableScanlines(direction * 2);
+
+ myOSystem.settings().setValue("tv.scanlines", intensity);
+ enableNTSC(ntscEnabled());
+
+ if(intensity)
+ buf << intensity << "%";
+ else
+ buf << "Off";
+ myFB.showMessage("Scanline intensity", buf.str(), intensity);
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+uInt32 TIASurface::enableScanlines(int change)
{
FBSurface::Attributes& attr = mySLineSurface->attributes();
- if(relative == 0) attr.blendalpha = absolute;
- else attr.blendalpha += relative;
- attr.blendalpha = std::max(0, Int32(attr.blendalpha));
- attr.blendalpha = std::min(100U, attr.blendalpha);
+ attr.blendalpha += change;
+ attr.blendalpha = BSPF::clamp(Int32(attr.blendalpha), 0, 100);
mySLineSurface->applyAttributes();
return attr.blendalpha;
diff --git a/src/emucore/TIASurface.hxx b/src/emucore/TIASurface.hxx
index c87ddc881..826ff75d9 100644
--- a/src/emucore/TIASurface.hxx
+++ b/src/emucore/TIASurface.hxx
@@ -22,6 +22,7 @@ class TIA;
class Console;
class OSystem;
class FBSurface;
+class PaletteHandler;
#include
@@ -48,6 +49,7 @@ class TIASurface
Creates a new TIASurface object
*/
explicit TIASurface(OSystem& system);
+ virtual ~TIASurface();
/**
Set the TIA object, which is needed for actually rendering the TIA image.
@@ -88,19 +90,53 @@ class TIASurface
void setNTSC(NTSCFilter::Preset preset, bool show = true);
/**
- Increase/decrease current scanline intensity by given relative amount.
+ Switch to next/previous NTSC filtering effect.
+
+ @param direction +1 indicates increase, -1 indicates decrease.
*/
- void setScanlineIntensity(int relative);
+ void changeNTSC(int direction = +1);
+
+ /**
+ Switch to next/previous NTSC filtering adjustable.
+
+ @param direction +1 indicates increase, -1 indicates decrease.
+ */
+ void setNTSCAdjustable(int direction = +1);
+
+ /**
+ Increase/decrease given NTSC filtering adjustable.
+
+ @param adjustable The adjustable to change
+ @param direction +1 indicates increase, -1 indicates decrease.
+ */
+ void changeNTSCAdjustable(int adjustable, int direction);
+
+ /**
+ Increase/decrease current NTSC filtering adjustable.
+
+ @param direction +1 indicates increase, -1 indicates decrease.
+ */
+ void changeCurrentNTSCAdjustable(int direction = +1);
+
+ /**
+ Retrieve palette handler.
+ */
+ PaletteHandler& paletteHandler() const { return *myPaletteHandler; }
+
+ /**
+ Increase/decrease current scanline intensity by given relative amount.
+
+ @param direction +1 indicates increase, -1 indicates decrease.
+ */
+ void setScanlineIntensity(int direction = +1);
/**
Change scanline intensity and interpolation.
- @param relative If non-zero, change current intensity by
- 'relative' amount, otherwise set to 'absolute'
+ @param change change current intensity by 'change'
@return New current intensity
*/
- uInt32 enableScanlines(int relative, int absolute = 50);
- void enableScanlineInterpolation(bool enable);
+ uInt32 enableScanlines(int change);
/**
Enable/disable/query phosphor effect.
@@ -183,6 +219,9 @@ class TIASurface
// Flag for saving a snapshot
bool mySaveSnapFlag{false};
+ // The palette handler
+ unique_ptrmyPaletteHandler;
+
private:
// Following constructors and assignment operators not supported
TIASurface() = delete;
diff --git a/src/emucore/Thumbulator.cxx b/src/emucore/Thumbulator.cxx
index c5bd3e637..2984159cd 100644
--- a/src/emucore/Thumbulator.cxx
+++ b/src/emucore/Thumbulator.cxx
@@ -108,6 +108,7 @@ void Thumbulator::setConsoleTiming(ConsoleTiming timing)
case ConsoleTiming::ntsc: timing_factor = NTSC; break;
case ConsoleTiming::secam: timing_factor = SECAM; break;
case ConsoleTiming::pal: timing_factor = PAL; break;
+ default: break; // satisfy compiler
}
}
diff --git a/src/emucore/tia/Audio.hxx b/src/emucore/tia/Audio.hxx
index 92e854a0d..5ab53ecae 100644
--- a/src/emucore/tia/Audio.hxx
+++ b/src/emucore/tia/Audio.hxx
@@ -18,12 +18,12 @@
#ifndef TIA_AUDIO_HXX
#define TIA_AUDIO_HXX
+class AudioQueue;
+
#include "bspf.hxx"
#include "AudioChannel.hxx"
#include "Serializable.hxx"
-class AudioQueue;
-
class Audio : public Serializable
{
public:
diff --git a/src/emucore/tia/Background.hxx b/src/emucore/tia/Background.hxx
index 3004c7978..ea84aed96 100644
--- a/src/emucore/tia/Background.hxx
+++ b/src/emucore/tia/Background.hxx
@@ -18,11 +18,11 @@
#ifndef TIA_BACKGROUND
#define TIA_BACKGROUND
+class TIA;
+
#include "Serializable.hxx"
#include "bspf.hxx"
-class TIA;
-
class Background : public Serializable
{
public:
diff --git a/src/emucore/tia/Ball.hxx b/src/emucore/tia/Ball.hxx
index 5b9b3a604..0a40250e2 100644
--- a/src/emucore/tia/Ball.hxx
+++ b/src/emucore/tia/Ball.hxx
@@ -18,11 +18,11 @@
#ifndef TIA_BALL
#define TIA_BALL
-#include "Serializable.hxx"
+class TIA;
+
#include "bspf.hxx"
#include "TIAConstants.hxx"
-
-class TIA;
+#include "Serializable.hxx"
class Ball : public Serializable
{
diff --git a/src/emucore/tia/DelayQueueIterator.hxx b/src/emucore/tia/DelayQueueIterator.hxx
index 31e5251e8..3b615e3d4 100644
--- a/src/emucore/tia/DelayQueueIterator.hxx
+++ b/src/emucore/tia/DelayQueueIterator.hxx
@@ -19,8 +19,6 @@
#define TIA_DELAY_QUEUE_ITERATOR
#include "bspf.hxx"
-#include "DelayQueue.hxx"
-#include "DelayQueueMember.hxx"
class DelayQueueIterator
{
diff --git a/src/emucore/tia/DelayQueueIteratorImpl.hxx b/src/emucore/tia/DelayQueueIteratorImpl.hxx
index b556cb279..9f9e4d4c7 100644
--- a/src/emucore/tia/DelayQueueIteratorImpl.hxx
+++ b/src/emucore/tia/DelayQueueIteratorImpl.hxx
@@ -20,7 +20,6 @@
#include "bspf.hxx"
#include "DelayQueue.hxx"
-#include "DelayQueueMember.hxx"
#include "DelayQueueIterator.hxx"
template
diff --git a/src/emucore/tia/DelayQueueMember.hxx b/src/emucore/tia/DelayQueueMember.hxx
index f87c9b459..653167b6f 100644
--- a/src/emucore/tia/DelayQueueMember.hxx
+++ b/src/emucore/tia/DelayQueueMember.hxx
@@ -18,8 +18,8 @@
#ifndef TIA_DELAY_QUEUE_MEMBER
#define TIA_DELAY_QUEUE_MEMBER
-#include "Serializable.hxx"
#include "bspf.hxx"
+#include "Serializable.hxx"
template
class DelayQueueMember : public Serializable {
diff --git a/src/emucore/tia/Missile.hxx b/src/emucore/tia/Missile.hxx
index dda9b493c..cd5cce582 100644
--- a/src/emucore/tia/Missile.hxx
+++ b/src/emucore/tia/Missile.hxx
@@ -18,13 +18,13 @@
#ifndef TIA_MISSILE
#define TIA_MISSILE
+class TIA;
+class Player;
+
#include "Serializable.hxx"
#include "bspf.hxx"
-#include "Player.hxx"
#include "TIAConstants.hxx"
-class TIA;
-
class Missile : public Serializable
{
public:
diff --git a/src/emucore/tia/PaddleReader.hxx b/src/emucore/tia/PaddleReader.hxx
index abbc013c6..8071617c6 100644
--- a/src/emucore/tia/PaddleReader.hxx
+++ b/src/emucore/tia/PaddleReader.hxx
@@ -20,7 +20,7 @@
#include "bspf.hxx"
#include "Serializable.hxx"
-#include "Console.hxx"
+#include "ConsoleTiming.hxx"
class PaddleReader : public Serializable
{
diff --git a/src/emucore/tia/Player.hxx b/src/emucore/tia/Player.hxx
index 454bfcd9f..60dfbe3c5 100644
--- a/src/emucore/tia/Player.hxx
+++ b/src/emucore/tia/Player.hxx
@@ -18,12 +18,12 @@
#ifndef TIA_PLAYER
#define TIA_PLAYER
+class TIA;
+
#include "bspf.hxx"
#include "Serializable.hxx"
#include "TIAConstants.hxx"
-class TIA;
-
class Player : public Serializable
{
public:
diff --git a/src/emucore/tia/Playfield.hxx b/src/emucore/tia/Playfield.hxx
index fe811d53a..4a1376991 100644
--- a/src/emucore/tia/Playfield.hxx
+++ b/src/emucore/tia/Playfield.hxx
@@ -18,11 +18,11 @@
#ifndef TIA_PLAYFIELD
#define TIA_PLAYFIELD
-#include "Serializable.hxx"
+class TIA;
+
#include "bspf.hxx"
#include "TIAConstants.hxx"
-
-class TIA;
+#include "Serializable.hxx"
class Playfield : public Serializable
{
diff --git a/src/emucore/tia/frame-manager/FrameLayoutDetector.hxx b/src/emucore/tia/frame-manager/FrameLayoutDetector.hxx
index fa7e50308..443b9c20c 100644
--- a/src/emucore/tia/frame-manager/FrameLayoutDetector.hxx
+++ b/src/emucore/tia/frame-manager/FrameLayoutDetector.hxx
@@ -18,8 +18,8 @@
#ifndef TIA_FRAME_LAYOUT_DETECTOR
#define TIA_FRAME_LAYOUT_DETECTOR
-#include "AbstractFrameManager.hxx"
#include "FrameLayout.hxx"
+#include "AbstractFrameManager.hxx"
/**
* This frame manager performs frame layout autodetection. It counts the scanlines
diff --git a/src/gui/AudioDialog.cxx b/src/gui/AudioDialog.cxx
deleted file mode 100644
index 1f97c2f8b..000000000
--- a/src/gui/AudioDialog.cxx
+++ /dev/null
@@ -1,353 +0,0 @@
-//============================================================================
-//
-// SSSS tt lll lll
-// SS SS tt ll ll
-// SS tttttt eeee ll ll aaaa
-// SSSS tt ee ee ll ll aa
-// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
-// SS SS tt ee ll ll aa aa
-// SSSS ttt eeeee llll llll aaaaa
-//
-// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony
-// and the Stella Team
-//
-// See the file "License.txt" for information on usage and redistribution of
-// this file, and for a DISCLAIMER OF ALL WARRANTIES.
-//============================================================================
-
-#include
-
-#include "bspf.hxx"
-
-#include "Console.hxx"
-#include "Cart.hxx"
-#include "CartDPC.hxx"
-#include "Control.hxx"
-#include "Dialog.hxx"
-#include "Font.hxx"
-#include "Menu.hxx"
-#include "OSystem.hxx"
-#include "PopUpWidget.hxx"
-#include "Settings.hxx"
-#include "Sound.hxx"
-#include "Widget.hxx"
-#include "AudioSettings.hxx"
-
-#include "AudioDialog.hxx"
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-AudioDialog::AudioDialog(OSystem& osystem, DialogContainer& parent,
- const GUI::Font& font)
- : Dialog(osystem, parent, font, "Audio settings")
-{
- const int lineHeight = font.getLineHeight(),
- fontHeight = font.getFontHeight(),
- fontWidth = font.getMaxCharWidth();
- const int VBORDER = fontHeight / 2;
- const int HBORDER = fontWidth * 1.25;
- const int INDENT = fontWidth * 2;
- const int VGAP = fontHeight / 4;
-
- int xpos, ypos;
- int lwidth = font.getStringWidth("Volume "),
- pwidth;
-
- WidgetArray wid;
- VariantList items;
-
- // Set real dimensions
- _w = 48 * fontWidth + HBORDER * 2;
- _h = 12 * (lineHeight + VGAP) + VBORDER + _th;
-
- xpos = HBORDER; ypos = VBORDER + _th;
-
- // Enable sound
- mySoundEnableCheckbox = new CheckboxWidget(this, font, xpos, ypos,
- "Enable sound", kSoundEnableChanged);
- wid.push_back(mySoundEnableCheckbox);
- ypos += lineHeight + VGAP;
- xpos += CheckboxWidget::prefixSize(font);
-
- // Volume
- myVolumeSlider = new SliderWidget(this, font, xpos, ypos,
- "Volume", lwidth, 0, 4 * fontWidth, "%");
- myVolumeSlider->setMinValue(1); myVolumeSlider->setMaxValue(100);
- myVolumeSlider->setTickmarkIntervals(4);
- wid.push_back(myVolumeSlider);
- ypos += lineHeight + VGAP;
-
- // Mode
- items.clear();
- VarList::push_back(items, "Low quality, medium lag", static_cast(AudioSettings::Preset::lowQualityMediumLag));
- VarList::push_back(items, "High quality, medium lag", static_cast(AudioSettings::Preset::highQualityMediumLag));
- VarList::push_back(items, "High quality, low lag", static_cast(AudioSettings::Preset::highQualityLowLag));
- VarList::push_back(items, "Ultra quality, minimal lag", static_cast(AudioSettings::Preset::ultraQualityMinimalLag));
- VarList::push_back(items, "Custom", static_cast(AudioSettings::Preset::custom));
- myModePopup = new PopUpWidget(this, font, xpos, ypos,
- font.getStringWidth("Ultry quality, minimal lag"), lineHeight,
- items, "Mode", lwidth, kModeChanged);
- wid.push_back(myModePopup);
- ypos += lineHeight + VGAP;
- xpos += INDENT;
-
- // Fragment size
- pwidth = font.getStringWidth("512 samples") + 7;
- lwidth = font.getStringWidth("Resampling quality ");
- items.clear();
- VarList::push_back(items, "128 samples", 128);
- VarList::push_back(items, "256 samples", 256);
- VarList::push_back(items, "512 samples", 512);
- VarList::push_back(items, "1k samples", 1024);
- VarList::push_back(items, "2k samples", 2048);
- VarList::push_back(items, "4K samples", 4096);
- myFragsizePopup = new PopUpWidget(this, font, xpos, ypos,
- pwidth, lineHeight,
- items, "Fragment size", lwidth);
- wid.push_back(myFragsizePopup);
- ypos += lineHeight + VGAP;
-
- // Output frequency
- items.clear();
- VarList::push_back(items, "44100 Hz", 44100);
- VarList::push_back(items, "48000 Hz", 48000);
- VarList::push_back(items, "96000 Hz", 96000);
- myFreqPopup = new PopUpWidget(this, font, xpos, ypos,
- pwidth, lineHeight,
- items, "Sample rate", lwidth);
- wid.push_back(myFreqPopup);
- ypos += lineHeight + VGAP;
-
- // Resampling quality
- items.clear();
- VarList::push_back(items, "Low", static_cast(AudioSettings::ResamplingQuality::nearestNeightbour));
- VarList::push_back(items, "High", static_cast(AudioSettings::ResamplingQuality::lanczos_2));
- VarList::push_back(items, "Ultra", static_cast(AudioSettings::ResamplingQuality::lanczos_3));
- myResamplingPopup = new PopUpWidget(this, font, xpos, ypos,
- pwidth, lineHeight,
- items, "Resampling quality ", lwidth);
- wid.push_back(myResamplingPopup);
- ypos += lineHeight + VGAP;
-
- // Param 1
- int swidth = pwidth+23;
- myHeadroomSlider = new SliderWidget(this, font, xpos, ypos, swidth, lineHeight,
- "Headroom ", 0, kHeadroomChanged, 10 * fontWidth);
- myHeadroomSlider->setMinValue(0); myHeadroomSlider->setMaxValue(AudioSettings::MAX_HEADROOM);
- myHeadroomSlider->setTickmarkIntervals(5);
- wid.push_back(myHeadroomSlider);
- ypos += lineHeight + VGAP;
-
- // Param 2
- myBufferSizeSlider = new SliderWidget(this, font, xpos, ypos, swidth, lineHeight,
- "Buffer size ", 0, kBufferSizeChanged, 10 * fontWidth);
- myBufferSizeSlider->setMinValue(0); myBufferSizeSlider->setMaxValue(AudioSettings::MAX_BUFFER_SIZE);
- myBufferSizeSlider->setTickmarkIntervals(5);
- wid.push_back(myBufferSizeSlider);
- ypos += lineHeight + VGAP;
-
- // Stereo sound
- xpos -= INDENT;
- myStereoSoundCheckbox = new CheckboxWidget(this, font, xpos, ypos,
- "Stereo for all ROMs");
- wid.push_back(myStereoSoundCheckbox);
- ypos += lineHeight + VGAP;
-
- myDpcPitch = new SliderWidget(this, font, xpos, ypos, swidth - 16, lineHeight,
- "Pitfall II music pitch ", 0, 0, 5 * fontWidth);
- myDpcPitch->setMinValue(10000); myDpcPitch->setMaxValue(30000);
- myDpcPitch->setStepValue(100);
- myDpcPitch->setTickmarkIntervals(2);
- wid.push_back(myDpcPitch);
-
- // Add Defaults, OK and Cancel buttons
- addDefaultsOKCancelBGroup(wid, font);
-
- addToFocusList(wid);
-}
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void AudioDialog::loadConfig()
-{
- AudioSettings& audioSettings = instance().audioSettings();
-
- // Enable sound
- mySoundEnableCheckbox->setState(audioSettings.enabled());
-
- // Volume
- myVolumeSlider->setValue(audioSettings.volume());
-
- // Stereo
- myStereoSoundCheckbox->setState(audioSettings.stereo());
-
- // DPC Pitch
- myDpcPitch->setValue(audioSettings.dpcPitch());
-
- // Preset / mode
- myModePopup->setSelected(static_cast(audioSettings.preset()));
-
- updateSettingsWithPreset(instance().audioSettings());
-
- updateEnabledState();
-}
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void AudioDialog::updateSettingsWithPreset(AudioSettings& audioSettings)
-{
- // Fragsize
- myFragsizePopup->setSelected(audioSettings.fragmentSize());
-
- // Output frequency
- myFreqPopup->setSelected(audioSettings.sampleRate());
-
- // Headroom
- myHeadroomSlider->setValue(audioSettings.headroom());
-
- // Buffer size
- myBufferSizeSlider->setValue(audioSettings.bufferSize());
-
- // Resampling quality
- myResamplingPopup->setSelected(static_cast(audioSettings.resamplingQuality()));
-}
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void AudioDialog::saveConfig()
-{
- AudioSettings& audioSettings = instance().audioSettings();
-
- // Enabled
- audioSettings.setEnabled(mySoundEnableCheckbox->getState());
- instance().sound().setEnabled(mySoundEnableCheckbox->getState());
-
- // Volume
- audioSettings.setVolume(myVolumeSlider->getValue());
- instance().sound().setVolume(myVolumeSlider->getValue());
-
- // Stereo
- audioSettings.setStereo(myStereoSoundCheckbox->getState());
-
- // DPC Pitch
- audioSettings.setDpcPitch(myDpcPitch->getValue());
- // update if current cart is Pitfall II
- if (instance().hasConsole() && instance().console().cartridge().name() == "CartridgeDPC")
- {
- CartridgeDPC& cart = static_cast(instance().console().cartridge());
- cart.setDpcPitch(myDpcPitch->getValue());
- }
-
- AudioSettings::Preset preset = static_cast(myModePopup->getSelectedTag().toInt());
- audioSettings.setPreset(preset);
-
- if (preset == AudioSettings::Preset::custom) {
- // Fragsize
- audioSettings.setFragmentSize(myFragsizePopup->getSelectedTag().toInt());
- audioSettings.setSampleRate(myFreqPopup->getSelectedTag().toInt());
- audioSettings.setHeadroom(myHeadroomSlider->getValue());
- audioSettings.setBufferSize(myBufferSizeSlider->getValue());
- audioSettings.setResamplingQuality(static_cast(myResamplingPopup->getSelectedTag().toInt()));
- }
-
- // Only force a re-initialization when necessary, since it can
- // be a time-consuming operation
- if(instance().hasConsole())
- instance().console().initializeAudio();
-}
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void AudioDialog::setDefaults()
-{
- mySoundEnableCheckbox->setState(AudioSettings::DEFAULT_ENABLED);
- myVolumeSlider->setValue(AudioSettings::DEFAULT_VOLUME);
- myStereoSoundCheckbox->setState(AudioSettings::DEFAULT_STEREO);
- myDpcPitch->setValue(AudioSettings::DEFAULT_DPC_PITCH);
- myModePopup->setSelected(static_cast(AudioSettings::DEFAULT_PRESET));
-
- if (AudioSettings::DEFAULT_PRESET == AudioSettings::Preset::custom) {
- myResamplingPopup->setSelected(static_cast(AudioSettings::DEFAULT_RESAMPLING_QUALITY));
- myFragsizePopup->setSelected(AudioSettings::DEFAULT_FRAGMENT_SIZE);
- myFreqPopup->setSelected(AudioSettings::DEFAULT_SAMPLE_RATE);
- myHeadroomSlider->setValue(AudioSettings::DEFAULT_HEADROOM);
- myBufferSizeSlider->setValue(AudioSettings::DEFAULT_BUFFER_SIZE);
- }
- else updatePreset();
-
- updateEnabledState();
-}
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void AudioDialog::updateEnabledState()
-{
- bool active = mySoundEnableCheckbox->getState();
- AudioSettings::Preset preset = static_cast(myModePopup->getSelectedTag().toInt());
- bool userMode = preset == AudioSettings::Preset::custom;
-
- myVolumeSlider->setEnabled(active);
- myStereoSoundCheckbox->setEnabled(active);
- myModePopup->setEnabled(active);
- // enable only for Pitfall II cart
- myDpcPitch->setEnabled(active && instance().hasConsole() && instance().console().cartridge().name() == "CartridgeDPC");
-
- myFragsizePopup->setEnabled(active && userMode);
- myFreqPopup->setEnabled(active && userMode);
- myResamplingPopup->setEnabled(active && userMode);
- myHeadroomSlider->setEnabled(active && userMode);
- myBufferSizeSlider->setEnabled(active && userMode);
-}
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void AudioDialog::updatePreset()
-{
- AudioSettings::Preset preset = static_cast(myModePopup->getSelectedTag().toInt());
-
- // Make a copy that does not affect the actual settings...
- AudioSettings audioSettings = instance().audioSettings();
- audioSettings.setPersistent(false);
- // ... and set the requested preset
- audioSettings.setPreset(preset);
-
- updateSettingsWithPreset(audioSettings);
-}
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void AudioDialog::handleCommand(CommandSender* sender, int cmd,
- int data, int id)
-{
- switch(cmd)
- {
- case GuiObject::kOKCmd:
- saveConfig();
- close();
- break;
-
- case GuiObject::kDefaultsCmd:
- setDefaults();
- break;
-
- case kSoundEnableChanged:
- updateEnabledState();
- break;
-
- case kModeChanged:
- updatePreset();
- updateEnabledState();
- break;
-
- case kHeadroomChanged:
- {
- std::ostringstream ss;
- ss << std::fixed << std::setprecision(1) << (0.5 * myHeadroomSlider->getValue()) << " frames";
- myHeadroomSlider->setValueLabel(ss.str());
- break;
- }
- case kBufferSizeChanged:
- {
- std::ostringstream ss;
- ss << std::fixed << std::setprecision(1) << (0.5 * myBufferSizeSlider->getValue()) << " frames";
- myBufferSizeSlider->setValueLabel(ss.str());
- break;
- }
-
- default:
- Dialog::handleCommand(sender, cmd, data, 0);
- break;
- }
-}
diff --git a/src/gui/AudioDialog.hxx b/src/gui/AudioDialog.hxx
deleted file mode 100644
index b7aa35c65..000000000
--- a/src/gui/AudioDialog.hxx
+++ /dev/null
@@ -1,77 +0,0 @@
-//============================================================================
-//
-// SSSS tt lll lll
-// SS SS tt ll ll
-// SS tttttt eeee ll ll aaaa
-// SSSS tt ee ee ll ll aa
-// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
-// SS SS tt ee ll ll aa aa
-// SSSS ttt eeeee llll llll aaaaa
-//
-// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony
-// and the Stella Team
-//
-// See the file "License.txt" for information on usage and redistribution of
-// this file, and for a DISCLAIMER OF ALL WARRANTIES.
-//============================================================================
-
-#ifndef AUDIO_DIALOG_HXX
-#define AUDIO_DIALOG_HXX
-
-class CommandSender;
-class Dialog;
-class DialogContainer;
-class PopUpWidget;
-class SliderWidget;
-class StaticTextWidget;
-class CheckboxWidget;
-class OSystem;
-class AudioSettings;
-
-#include "bspf.hxx"
-
-class AudioDialog : public Dialog
-{
- public:
- AudioDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font);
- virtual ~AudioDialog() = default;
-
- private:
- void loadConfig() override;
- void saveConfig() override;
- void setDefaults() override;
-
- void updatePreset();
- void updateEnabledState();
- void updateSettingsWithPreset(AudioSettings&);
- void handleCommand(CommandSender* sender, int cmd, int data, int id) override;
-
- private:
- enum {
- kSoundEnableChanged = 'ADse',
- kModeChanged = 'ADmc',
- kHeadroomChanged = 'ADhc',
- kBufferSizeChanged = 'ADbc'
- };
-
- CheckboxWidget* mySoundEnableCheckbox{nullptr};
- SliderWidget* myVolumeSlider{nullptr};
- CheckboxWidget* myStereoSoundCheckbox{nullptr};
- PopUpWidget* myModePopup{nullptr};
- PopUpWidget* myFragsizePopup{nullptr};
- PopUpWidget* myFreqPopup{nullptr};
- PopUpWidget* myResamplingPopup{nullptr};
- SliderWidget* myHeadroomSlider{nullptr};
- SliderWidget* myBufferSizeSlider{nullptr};
- SliderWidget* myDpcPitch{nullptr};
-
- private:
- // Following constructors and assignment operators not supported
- AudioDialog() = delete;
- AudioDialog(const AudioDialog&) = delete;
- AudioDialog(AudioDialog&&) = delete;
- AudioDialog& operator=(const AudioDialog&) = delete;
- AudioDialog& operator=(AudioDialog&&) = delete;
-};
-
-#endif
diff --git a/src/gui/ColorWidget.cxx b/src/gui/ColorWidget.cxx
index 6aa58a049..27f4bc3cf 100644
--- a/src/gui/ColorWidget.cxx
+++ b/src/gui/ColorWidget.cxx
@@ -25,9 +25,10 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ColorWidget::ColorWidget(GuiObject* boss, const GUI::Font& font,
- int x, int y, int w, int h, int cmd)
+ int x, int y, int w, int h, int cmd, bool framed)
: Widget(boss, font, x, y, w, h),
CommandSender(boss),
+ _framed(framed),
_cmd(cmd)
{
_flags = Widget::FLAG_ENABLED | Widget::FLAG_CLEARBG | Widget::FLAG_RETAIN_FOCUS;
@@ -46,11 +47,18 @@ void ColorWidget::drawWidget(bool hilite)
FBSurface& s = dialog().surface();
bool onTop = _boss->dialog().isOnTop();
+ if(_framed)
+ {
// Draw a thin frame around us.
- s.frameRect(_x, _y, _w, _h + 1, kColor);
+ s.frameRect(_x, _y, _w, _h + 1, kColor);
- // Show the currently selected color
- s.fillRect(_x+1, _y+1, _w-2, _h-1, onTop ? isEnabled() ? _color : kWidColor : kBGColorLo);
+ // Show the currently selected color
+ s.fillRect(_x + 1, _y + 1, _w - 2, _h - 1, onTop ? isEnabled() ? _color : kWidColor : kBGColorLo);
+ }
+ else
+ {
+ s.fillRect(_x, _y, _w, _h, onTop ? isEnabled() ? _color : kWidColor : kBGColorLo);
+ }
// Cross out the grid?
if(_crossGrid)
diff --git a/src/gui/ColorWidget.hxx b/src/gui/ColorWidget.hxx
index 7691ff6ad..9169c2153 100644
--- a/src/gui/ColorWidget.hxx
+++ b/src/gui/ColorWidget.hxx
@@ -36,7 +36,7 @@ class ColorWidget : public Widget, public CommandSender
public:
ColorWidget(GuiObject* boss, const GUI::Font& font,
- int x, int y, int w, int h, int cmd = 0);
+ int x, int y, int w, int h, int cmd = 0, bool framed = true);
virtual ~ColorWidget() = default;
void setColor(ColorId color);
@@ -49,6 +49,7 @@ class ColorWidget : public Widget, public CommandSender
protected:
ColorId _color{kNone};
+ bool _framed{true};
int _cmd{0};
bool _crossGrid{false};
diff --git a/src/gui/CommandDialog.cxx b/src/gui/CommandDialog.cxx
index 5c734a52e..e4c5f610a 100644
--- a/src/gui/CommandDialog.cxx
+++ b/src/gui/CommandDialog.cxx
@@ -16,6 +16,7 @@
//============================================================================
#include "Console.hxx"
+#include "PaletteHandler.hxx"
#include "TIA.hxx"
#include "Switches.hxx"
#include "Dialog.hxx"
@@ -198,12 +199,12 @@ void CommandDialog::handleCommand(CommandSender* sender, int cmd,
// Column 3
case kFormatCmd:
- instance().console().toggleFormat();
+ instance().console().selectFormat();
updateTVFormat();
break;
case kPaletteCmd:
- instance().console().togglePalette();
+ instance().frameBuffer().tiaSurface().paletteHandler().cyclePalette();
updatePalette();
break;
@@ -269,11 +270,11 @@ void CommandDialog::updatePalette()
string palette, label;
palette = instance().settings().getString("palette");
- if(BSPF::equalsIgnoreCase(palette, "standard"))
+ if(BSPF::equalsIgnoreCase(palette, PaletteHandler::SETTING_STANDARD))
label = "Stella Palette";
- else if(BSPF::equalsIgnoreCase(palette, "z26"))
+ else if(BSPF::equalsIgnoreCase(palette, PaletteHandler::SETTING_Z26))
label = "Z26 Palette";
- else if(BSPF::equalsIgnoreCase(palette, "user"))
+ else if(BSPF::equalsIgnoreCase(palette, PaletteHandler::SETTING_USER))
label = "User Palette";
else
label = "Custom Palette";
diff --git a/src/gui/CommandMenu.cxx b/src/gui/CommandMenu.cxx
index 68e9a0fef..1a6708f71 100644
--- a/src/gui/CommandMenu.cxx
+++ b/src/gui/CommandMenu.cxx
@@ -16,6 +16,8 @@
//============================================================================
#include "Dialog.hxx"
+#include "OSystem.hxx"
+#include "Settings.hxx"
#include "CommandDialog.hxx"
#include "MinUICommandDialog.hxx"
#include "CommandMenu.hxx"
diff --git a/src/gui/DeveloperDialog.cxx b/src/gui/DeveloperDialog.cxx
index 5badbc513..288fb6a40 100644
--- a/src/gui/DeveloperDialog.cxx
+++ b/src/gui/DeveloperDialog.cxx
@@ -499,31 +499,6 @@ void DeveloperDialog::addTimeMachineTab(const GUI::Font& font)
lineHeight, items, "Horizon ~ ", 0, kHorizonChanged);
wid.push_back(myStateHorizonWidget);
- xpos = HBORDER + INDENT;
- ypos += lineHeight + VGAP * 2;
- new StaticTextWidget(myTab, font, HBORDER, ypos + 1,
- "When entering/exiting emulation:");
- ypos += lineHeight + VGAP;
- mySaveOnExitGroup = new RadioButtonGroup();
- r = new RadioButtonWidget(myTab, font, xpos, ypos + 1,
- "Do nothing", mySaveOnExitGroup);
- wid.push_back(r);
- ypos += lineHeight + VGAP;
- r = new RadioButtonWidget(myTab, font, xpos, ypos + 1,
- "Save current state in current slot", mySaveOnExitGroup);
- wid.push_back(r);
- ypos += lineHeight + VGAP;
- r = new RadioButtonWidget(myTab, font, xpos, ypos + 1,
- "Load/save all Time Machine states", mySaveOnExitGroup);
- wid.push_back(r);
- ypos += lineHeight + VGAP;
- xpos = HBORDER;
-
-
- myAutoSlotWidget = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Automatically change save state slots");
- wid.push_back(myAutoSlotWidget);
- ypos += lineHeight + VGAP;
-
// Add message concerning usage
const GUI::Font& infofont = instance().frameBuffer().infoFont();
ypos = myTab->getHeight() - fontHeight - infofont.getFontHeight() - VGAP - VBORDER;
@@ -678,8 +653,6 @@ void DeveloperDialog::loadSettings(SettingsSet set)
myUncompressed[set] = instance().settings().getInt(prefix + "tm.uncompressed");
myStateInterval[set] = instance().settings().getString(prefix + "tm.interval");
myStateHorizon[set] = instance().settings().getString(prefix + "tm.horizon");
-
-
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -871,12 +844,6 @@ void DeveloperDialog::loadConfig()
// Debug colours
handleDebugColours(instance().settings().getString("tia.dbgcolors"));
- // Save on exit
- string saveOnExit = instance().settings().getString("saveonexit");
- mySaveOnExitGroup->setSelected(saveOnExit == "all" ? 2 : saveOnExit == "current" ? 1 : 0);
- // Automatically change save state slots
- myAutoSlotWidget->setState(instance().settings().getBool("autoslot"));
-
#ifdef DEBUGGER_SUPPORT
uInt32 w, h;
@@ -953,13 +920,6 @@ void DeveloperDialog::saveConfig()
instance().state().setRewindMode(myTimeMachineWidget->getState() ?
StateManager::Mode::TimeMachine : StateManager::Mode::Off);
- // Save on exit
- int saveOnExit = mySaveOnExitGroup->getSelected();
- instance().settings().setValue("saveonexit",
- saveOnExit == 0 ? "none" : saveOnExit == 1 ? "current" : "all");
- // Automatically change save state slots
- instance().settings().setValue("autoslot", myAutoSlotWidget->getState());
-
#ifdef DEBUGGER_SUPPORT
// Debugger font style
instance().settings().setValue("dbg.fontstyle",
@@ -1050,8 +1010,6 @@ void DeveloperDialog::setDefaults()
myStateHorizon[set] = devSettings ? "30s" : "10m";
setWidgetStates(set);
- mySaveOnExitGroup->setSelected(0);
- myAutoSlotWidget->setState(false);
break;
case 4: // Debugger options
diff --git a/src/gui/DeveloperDialog.hxx b/src/gui/DeveloperDialog.hxx
index ddee5468d..8bd84ab91 100644
--- a/src/gui/DeveloperDialog.hxx
+++ b/src/gui/DeveloperDialog.hxx
@@ -135,8 +135,6 @@ class DeveloperDialog : public Dialog
SliderWidget* myUncompressedWidget{nullptr};
PopUpWidget* myStateIntervalWidget{nullptr};
PopUpWidget* myStateHorizonWidget{nullptr};
- RadioButtonGroup* mySaveOnExitGroup{nullptr};
- CheckboxWidget* myAutoSlotWidget{nullptr};
#ifdef DEBUGGER_SUPPORT
// Debugger UI widgets
diff --git a/src/gui/DialogContainer.cxx b/src/gui/DialogContainer.cxx
index b60faf6d4..950d71c06 100644
--- a/src/gui/DialogContainer.cxx
+++ b/src/gui/DialogContainer.cxx
@@ -384,4 +384,3 @@ void DialogContainer::reset()
uInt64 DialogContainer::_DOUBLE_CLICK_DELAY = 500;
uInt64 DialogContainer::_REPEAT_INITIAL_DELAY = 400;
uInt64 DialogContainer::_REPEAT_SUSTAIN_DELAY = 50;
-
diff --git a/src/gui/EditTextWidget.hxx b/src/gui/EditTextWidget.hxx
index f752ae385..c7a346804 100644
--- a/src/gui/EditTextWidget.hxx
+++ b/src/gui/EditTextWidget.hxx
@@ -21,7 +21,6 @@
#include "Rect.hxx"
#include "EditableWidget.hxx"
-
/* EditTextWidget */
class EditTextWidget : public EditableWidget
{
diff --git a/src/gui/EmulationDialog.cxx b/src/gui/EmulationDialog.cxx
new file mode 100644
index 000000000..e9bb3804a
--- /dev/null
+++ b/src/gui/EmulationDialog.cxx
@@ -0,0 +1,284 @@
+//============================================================================
+//
+// SSSS tt lll lll
+// SS SS tt ll ll
+// SS tttttt eeee ll ll aaaa
+// SSSS tt ee ee ll ll aa
+// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
+// SS SS tt ee ll ll aa aa
+// SSSS ttt eeeee llll llll aaaaa
+//
+// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony
+// and the Stella Team
+//
+// See the file "License.txt" for information on usage and redistribution of
+// this file, and for a DISCLAIMER OF ALL WARRANTIES.
+//============================================================================
+
+#include "OSystem.hxx"
+#include "Console.hxx"
+#include "FrameBuffer.hxx"
+#include "RadioButtonWidget.hxx"
+#include "TIASurface.hxx"
+
+#include "EmulationDialog.hxx"
+
+namespace {
+ // Emulation speed is a positive float that multiplies the framerate. However, the UI controls
+ // adjust speed in terms of a speedup factor (1/10, 1/9 .. 1/2, 1, 2, 3, .., 10). The following
+ // mapping and formatting functions implement this conversion. The speedup factor is represented
+ // by an integer value between -900 and 900 (0 means no speedup).
+
+ constexpr int MAX_SPEED = 900;
+ constexpr int MIN_SPEED = -900;
+ constexpr int SPEED_STEP = 10;
+
+ int mapSpeed(float speed)
+ {
+ speed = std::abs(speed);
+
+ return BSPF::clamp(
+ static_cast(round(100 * (speed >= 1 ? speed - 1 : -1 / speed + 1))),
+ MIN_SPEED, MAX_SPEED
+ );
+ }
+
+ float unmapSpeed(int speed)
+ {
+ float f_speed = static_cast(speed) / 100;
+
+ return speed < 0 ? -1 / (f_speed - 1) : 1 + f_speed;
+ }
+
+ string formatSpeed(int speed) {
+ stringstream ss;
+
+ ss
+ << std::setw(3) << std::fixed << std::setprecision(0)
+ << (unmapSpeed(speed) * 100);
+
+ return ss.str();
+ }
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+EmulationDialog::EmulationDialog(OSystem& osystem, DialogContainer& parent,
+ const GUI::Font& font, int max_w, int max_h)
+ : Dialog(osystem, parent, font, "Emulation settings")
+{
+ const int lineHeight = font.getLineHeight(),
+ fontHeight = font.getFontHeight(),
+ fontWidth = font.getMaxCharWidth(),
+ buttonHeight = font.getLineHeight() * 1.25;
+ const int VBORDER = fontHeight / 2;
+ const int HBORDER = fontWidth * 1.25;
+ const int INDENT = fontWidth * 2;
+ const int VGAP = fontHeight / 4;
+
+ int xpos, ypos;
+ int lwidth = font.getStringWidth("Emulation speed ");
+ WidgetArray wid;
+ VariantList items;
+ const int swidth = fontWidth * 10;
+
+ // Set real dimensions
+ _w = 37 * fontWidth + HBORDER * 2 + CheckboxWidget::prefixSize(_font);
+ _h = 12 * (lineHeight + VGAP) + VGAP * 7 + VBORDER * 3 + _th + buttonHeight;
+
+ xpos = HBORDER; ypos = VBORDER + _th;
+
+ // Speed
+ mySpeed =
+ new SliderWidget(this, _font, xpos, ypos-1, swidth, lineHeight,
+ "Emulation speed ", lwidth, kSpeedupChanged, fontWidth * 5, "%");
+ mySpeed->setMinValue(MIN_SPEED); mySpeed->setMaxValue(MAX_SPEED);
+ mySpeed->setStepValue(SPEED_STEP);
+ mySpeed->setTickmarkIntervals(2);
+ wid.push_back(mySpeed);
+ ypos += lineHeight + VGAP;
+
+ // Use sync to vblank
+ myUseVSync = new CheckboxWidget(this, _font, xpos, ypos + 1, "VSync");
+ wid.push_back(myUseVSync);
+ ypos += lineHeight + VGAP;
+
+
+ myTurbo = new CheckboxWidget(this, _font, xpos, ypos + 1, "Turbo mode");
+ wid.push_back(myTurbo);
+ ypos += lineHeight + VGAP * 3;
+
+ // Use multi-threading
+ myUseThreads = new CheckboxWidget(this, _font, xpos, ypos + 1, "Multi-threading");
+ wid.push_back(myUseThreads);
+ ypos += lineHeight + VGAP;
+
+ // Skip progress load bars for SuperCharger ROMs
+ // Doesn't really belong here, but I couldn't find a better place for it
+ myFastSCBios = new CheckboxWidget(this, _font, xpos, ypos + 1, "Fast SuperCharger load");
+ wid.push_back(myFastSCBios);
+ ypos += lineHeight + VGAP;
+
+ // Show UI messages onscreen
+ myUIMessages = new CheckboxWidget(this, _font, xpos, ypos + 1, "Show UI messages");
+ wid.push_back(myUIMessages);
+ ypos += lineHeight + VGAP;
+
+ // Confirm dialog when exiting emulation
+ xpos = HBORDER; ypos += VGAP * 3;
+ myConfirmExitWidget = new CheckboxWidget(this, _font, xpos, ypos, "Confirm exiting emulation");
+ wid.push_back(myConfirmExitWidget);
+
+ xpos = HBORDER + INDENT;
+ ypos += lineHeight + VGAP * 3;
+ new StaticTextWidget(this, font, HBORDER, ypos + 1,
+ "When entering/exiting emulation:");
+ ypos += lineHeight + VGAP;
+ mySaveOnExitGroup = new RadioButtonGroup();
+ RadioButtonWidget* r;
+ r = new RadioButtonWidget(this, font, xpos, ypos + 1,
+ "Do nothing", mySaveOnExitGroup);
+ wid.push_back(r);
+ ypos += lineHeight + VGAP;
+ r = new RadioButtonWidget(this, font, xpos, ypos + 1,
+ "Save current state in current slot", mySaveOnExitGroup);
+ wid.push_back(r);
+ ypos += lineHeight + VGAP;
+ r = new RadioButtonWidget(this, font, xpos, ypos + 1,
+ "Load/save all Time Machine states", mySaveOnExitGroup);
+ wid.push_back(r);
+ ypos += lineHeight + VGAP;
+ xpos = HBORDER;
+
+
+ myAutoSlotWidget = new CheckboxWidget(this, font, xpos, ypos + 1, "Automatically change save state slots");
+ wid.push_back(myAutoSlotWidget);
+ ypos += lineHeight + VGAP;
+
+ // Add Defaults, OK and Cancel buttons
+ addDefaultsOKCancelBGroup(wid, font);
+
+ addToFocusList(wid);
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void EmulationDialog::loadConfig()
+{
+ Settings& settings = instance().settings();
+
+ // Emulation speed
+ int speed = mapSpeed(settings.getFloat("speed"));
+ mySpeed->setValue(speed);
+ mySpeed->setValueLabel(formatSpeed(speed));
+
+ // Use sync to vertical blank
+ myUseVSync->setState(settings.getBool("vsync"));
+
+ // Enable 'Turbo' mode
+ myTurbo->setState(settings.getBool("turbo"));
+
+ // Show UI messages
+ myUIMessages->setState(settings.getBool("uimessages"));
+
+ // Fast loading of Supercharger BIOS
+ myFastSCBios->setState(settings.getBool("fastscbios"));
+
+ // Multi-threaded rendering
+ myUseThreads->setState(settings.getBool("threads"));
+
+ // Confirm dialog when exiting emulation
+ myConfirmExitWidget->setState(settings.getBool("confirmexit"));
+
+ // Save on exit
+ string saveOnExit = settings.getString("saveonexit");
+ mySaveOnExitGroup->setSelected(saveOnExit == "all" ? 2 : saveOnExit == "current" ? 1 : 0);
+ // Automatically change save state slots
+ myAutoSlotWidget->setState(settings.getBool("autoslot"));
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void EmulationDialog::saveConfig()
+{
+ Settings& settings = instance().settings();
+
+ // Speed
+ const int speedup = mySpeed->getValue();
+ settings.setValue("speed", unmapSpeed(speedup));
+ if(instance().hasConsole())
+ instance().console().initializeAudio();
+
+ // Use sync to vertical blank
+ settings.setValue("vsync", myUseVSync->getState());
+
+ // Enable 'Turbo' mode
+ settings.setValue("turbo", myTurbo->getState());
+
+ // Show UI messages
+ settings.setValue("uimessages", myUIMessages->getState());
+
+ // Fast loading of Supercharger BIOS
+ settings.setValue("fastscbios", myFastSCBios->getState());
+
+ // Multi-threaded rendering
+ settings.setValue("threads", myUseThreads->getState());
+
+ // Confirm dialog when exiting emulation
+ settings.setValue("confirmexit", myConfirmExitWidget->getState());
+
+ // Save on exit
+ int saveOnExit = mySaveOnExitGroup->getSelected();
+ settings.setValue("saveonexit",
+ saveOnExit == 0 ? "none" : saveOnExit == 1 ? "current" : "all");
+ // Automatically change save state slots
+ settings.setValue("autoslot", myAutoSlotWidget->getState());
+
+ if(instance().hasConsole())
+ {
+ // update speed
+ instance().console().initializeAudio();
+ // update VSync
+ instance().console().initializeVideo();
+
+ instance().frameBuffer().tiaSurface().ntsc().enableThreading(myUseThreads->getState());
+ }
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void EmulationDialog::setDefaults()
+{
+ // speed
+ mySpeed->setValue(0);
+ myUseVSync->setState(true);
+ // misc
+ myUIMessages->setState(true);
+ myFastSCBios->setState(true);
+ myUseThreads->setState(false);
+ myConfirmExitWidget->setState(false);
+
+ mySaveOnExitGroup->setSelected(0);
+ myAutoSlotWidget->setState(false);
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void EmulationDialog::handleCommand(CommandSender* sender, int cmd,
+ int data, int id)
+{
+ switch(cmd)
+ {
+ case GuiObject::kOKCmd:
+ saveConfig();
+ close();
+ break;
+
+ case GuiObject::kDefaultsCmd:
+ setDefaults();
+ break;
+
+ case kSpeedupChanged:
+ mySpeed->setValueLabel(formatSpeed(mySpeed->getValue()));
+ break;
+
+ default:
+ Dialog::handleCommand(sender, cmd, data, 0);
+ break;
+ }
+}
diff --git a/src/gui/EmulationDialog.hxx b/src/gui/EmulationDialog.hxx
new file mode 100644
index 000000000..f1470d7bb
--- /dev/null
+++ b/src/gui/EmulationDialog.hxx
@@ -0,0 +1,63 @@
+//============================================================================
+//
+// SSSS tt lll lll
+// SS SS tt ll ll
+// SS tttttt eeee ll ll aaaa
+// SSSS tt ee ee ll ll aa
+// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
+// SS SS tt ee ll ll aa aa
+// SSSS ttt eeeee llll llll aaaaa
+//
+// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony
+// and the Stella Team
+//
+// See the file "License.txt" for information on usage and redistribution of
+// this file, and for a DISCLAIMER OF ALL WARRANTIES.
+//============================================================================
+
+#ifndef EMULATION_DIALOG_HXX
+#define EMULATION_DIALOG_HXX
+
+class RadioButtonGroup;
+
+#include "Dialog.hxx"
+
+class EmulationDialog : public Dialog
+{
+public:
+ EmulationDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font,
+ int max_w, int max_h);
+ virtual ~EmulationDialog() = default;
+
+private:
+ void loadConfig() override;
+ void saveConfig() override;
+ void setDefaults() override;
+
+ void handleCommand(CommandSender* sender, int cmd, int data, int id) override;
+
+private:
+ SliderWidget* mySpeed{nullptr};
+ CheckboxWidget* myUseVSync{nullptr};
+ CheckboxWidget* myTurbo{nullptr};
+ CheckboxWidget* myUIMessages{nullptr};
+ CheckboxWidget* myFastSCBios{nullptr};
+ CheckboxWidget* myUseThreads{nullptr};
+ CheckboxWidget* myConfirmExitWidget{nullptr};
+ RadioButtonGroup* mySaveOnExitGroup{nullptr};
+ CheckboxWidget* myAutoSlotWidget{nullptr};
+
+ enum {
+ kSpeedupChanged = 'EDSp',
+ };
+
+private:
+ // Following constructors and assignment operators not supported
+ EmulationDialog() = delete;
+ EmulationDialog(const EmulationDialog&) = delete;
+ EmulationDialog(EmulationDialog&&) = delete;
+ EmulationDialog& operator=(const EmulationDialog&) = delete;
+ EmulationDialog& operator=(EmulationDialog&&) = delete;
+};
+
+#endif
diff --git a/src/gui/GuiObject.hxx b/src/gui/GuiObject.hxx
index 3f473867b..fc8f77285 100644
--- a/src/gui/GuiObject.hxx
+++ b/src/gui/GuiObject.hxx
@@ -27,7 +27,6 @@ class Widget;
class OSystem;
#include "Command.hxx"
-#include "OSystem.hxx"
#include "Vec.hxx"
using WidgetArray = vector;
diff --git a/src/gui/HelpDialog.cxx b/src/gui/HelpDialog.cxx
index 5c9a6b1d3..77c01f174 100644
--- a/src/gui/HelpDialog.cxx
+++ b/src/gui/HelpDialog.cxx
@@ -121,7 +121,7 @@ void HelpDialog::updateStrings(uInt8 page, uInt8 lines, string& title)
case 2:
title = "Special commands";
ADD_EVENT(Event::FormatIncrease, "Switch between NTSC/PAL/SECAM");
- ADD_EVENT(Event::TogglePalette, "Switch palette");
+ ADD_EVENT(Event::PaletteIncrease, "Switch to next palette");
ADD_EVENT(Event::TogglePhosphor, "Toggle 'phosphor' effect");
ADD_LINE();
ADD_EVENT(Event::ToggleGrabMouse, "Grab mouse (keep in window)");
diff --git a/src/gui/InputDialog.cxx b/src/gui/InputDialog.cxx
index 03cedb644..3cced561b 100644
--- a/src/gui/InputDialog.cxx
+++ b/src/gui/InputDialog.cxx
@@ -53,7 +53,7 @@ InputDialog::InputDialog(OSystem& osystem, DialogContainer& parent,
int xpos, ypos, tabID;
// Set real dimensions
- setSize(50 * fontWidth + HBORDER * 2,
+ setSize(48 * fontWidth + PopUpWidget::dropDownWidth(_font) + HBORDER * 2,
_th + VGAP * 3 + lineHeight + 13 * (lineHeight + VGAP) + VGAP * 8 + buttonHeight + VBORDER * 3,
max_w, max_h);
@@ -127,10 +127,9 @@ void InputDialog::addDevicePortTab()
"Joystick deadzone size", lwidth, kDeadzoneChanged, 5 * fontWidth);
myDeadzone->setMinValue(0); myDeadzone->setMaxValue(29);
myDeadzone->setTickmarkIntervals(4);
- xpos = HBORDER + myDeadzone->getWidth() + 5;
wid.push_back(myDeadzone);
- xpos = HBORDER; ypos += lineHeight + VGAP * 2;
+ xpos = HBORDER; ypos += lineHeight + VGAP * 4;
new StaticTextWidget(myTab, _font, xpos, ypos+1, "Analog paddle:");
xpos += fontWidth * 2;
@@ -165,7 +164,7 @@ void InputDialog::addDevicePortTab()
wid.push_back(myDejitterDiff);
// Add paddle speed (digital emulation)
- ypos += lineHeight + VGAP * 3;
+ ypos += lineHeight + VGAP * 4;
myDPaddleSpeed = new SliderWidget(myTab, _font, HBORDER, ypos - 1, 13 * fontWidth, lineHeight,
"Digital paddle sensitivity",
lwidth, kDPSpeedChanged, 4 * fontWidth, "%");
@@ -173,26 +172,8 @@ void InputDialog::addDevicePortTab()
myDPaddleSpeed->setTickmarkIntervals(4);
wid.push_back(myDPaddleSpeed);
- // Add trackball speed
- ypos += lineHeight + VGAP;
- myTrackBallSpeed = new SliderWidget(myTab, _font, HBORDER, ypos - 1, 13 * fontWidth, lineHeight,
- "Trackball sensitivity",
- lwidth, kTBSpeedChanged, 4 * fontWidth, "%");
- myTrackBallSpeed->setMinValue(1); myTrackBallSpeed->setMaxValue(20);
- myTrackBallSpeed->setTickmarkIntervals(4);
- wid.push_back(myTrackBallSpeed);
-
- // Add driving controller speed
- ypos += lineHeight + VGAP;
- myDrivingSpeed = new SliderWidget(myTab, _font, HBORDER, ypos - 1, 13 * fontWidth, lineHeight,
- "Driving contr. sensitivity",
- lwidth, kDCSpeedChanged, 4 * fontWidth, "%");
- myDrivingSpeed->setMinValue(1); myDrivingSpeed->setMaxValue(20);
- myDrivingSpeed->setTickmarkIntervals(4);
- wid.push_back(myDrivingSpeed);
-
// Add 'allow all 4 directions' for joystick
- ypos += lineHeight + VGAP * 3;
+ ypos += lineHeight + VGAP * 4;
myAllowAll4 = new CheckboxWidget(myTab, _font, HBORDER, ypos,
"Allow all 4 directions on joystick");
wid.push_back(myAllowAll4);
@@ -231,7 +212,7 @@ void InputDialog::addDevicePortTab()
wid.push_back(myEraseEEPROMButton);
// Add AtariVox serial port
- ypos += lineHeight + VGAP * 2;
+ ypos += lineHeight + VGAP * 3;
lwidth = _font.getStringWidth("AVox serial port ");
fwidth = _w - HBORDER * 2 - 2 - lwidth;
new StaticTextWidget(myTab, _font, HBORDER, ypos + 2, "AVox serial port ");
@@ -252,7 +233,8 @@ void InputDialog::addMouseTab()
const int VGAP = fontHeight / 4;
const int VBORDER = fontHeight / 2;
const int HBORDER = fontWidth * 1.25;
- int ypos, lwidth, pwidth, tabID;
+ const int INDENT = fontWidth * 2;
+ int xpos = HBORDER, ypos, lwidth, pwidth, tabID;
WidgetArray wid;
VariantList items;
@@ -267,21 +249,43 @@ void InputDialog::addMouseTab()
VarList::push_back(items, "Always", "always");
VarList::push_back(items, "Analog devices", "analog");
VarList::push_back(items, "Never", "never");
- myMouseControl = new PopUpWidget(myTab, _font, HBORDER, ypos, pwidth, lineHeight, items,
+ myMouseControl = new PopUpWidget(myTab, _font, xpos, ypos, pwidth, lineHeight, items,
"Use mouse as a controller ", lwidth, kMouseCtrlChanged);
wid.push_back(myMouseControl);
- // Add paddle speed (mouse emulation)
ypos += lineHeight + VGAP;
- myMPaddleSpeed = new SliderWidget(myTab, _font, HBORDER, ypos - 1, 13 * fontWidth, lineHeight,
- "Mouse paddle sensitivity ",
+ myMouseSensitivity = new StaticTextWidget(myTab, _font, xpos, ypos + 1, "Sensitivity:");
+
+ // Add paddle speed (mouse emulation)
+ xpos += INDENT; ypos += lineHeight + VGAP;
+ lwidth -= INDENT;
+ myMPaddleSpeed = new SliderWidget(myTab, _font, xpos, ypos - 1, 13 * fontWidth, lineHeight,
+ "Paddle",
lwidth, kMPSpeedChanged, 4 * fontWidth, "%");
myMPaddleSpeed->setMinValue(1); myMPaddleSpeed->setMaxValue(20);
myMPaddleSpeed->setTickmarkIntervals(4);
wid.push_back(myMPaddleSpeed);
+ // Add trackball speed
+ ypos += lineHeight + VGAP;
+ myTrackBallSpeed = new SliderWidget(myTab, _font, xpos, ypos - 1, 13 * fontWidth, lineHeight,
+ "Trackball",
+ lwidth, kTBSpeedChanged, 4 * fontWidth, "%");
+ myTrackBallSpeed->setMinValue(1); myTrackBallSpeed->setMaxValue(20);
+ myTrackBallSpeed->setTickmarkIntervals(4);
+ wid.push_back(myTrackBallSpeed);
+
+ // Add driving controller speed
+ ypos += lineHeight + VGAP;
+ myDrivingSpeed = new SliderWidget(myTab, _font, xpos, ypos - 1, 13 * fontWidth, lineHeight,
+ "Driving controller",
+ lwidth, kDCSpeedChanged, 4 * fontWidth, "%");
+ myDrivingSpeed->setMinValue(1); myDrivingSpeed->setMaxValue(20);
+ myDrivingSpeed->setTickmarkIntervals(4);
+ wid.push_back(myDrivingSpeed);
// Mouse cursor state
+ lwidth += INDENT;
ypos += lineHeight + VGAP * 4;
items.clear();
VarList::push_back(items, "-UI, -Emulation", "0");
@@ -473,9 +477,6 @@ void InputDialog::setDefaults()
myDejitterBase->setValue(0);
myDejitterDiff->setValue(0);
#endif
- myDrivingSpeed->setValue(10);
- myTrackBallSpeed->setValue(10);
-
// AtariVox serial port
myAVoxPort->setText("");
@@ -491,15 +492,17 @@ void InputDialog::setDefaults()
// Use mouse as a controller
myMouseControl->setSelected("analog");
+ // Paddle speed (mouse)
+ myMPaddleSpeed->setValue(10);
+ myTrackBallSpeed->setValue(10);
+ myDrivingSpeed->setValue(10);
+
// Mouse cursor state
myCursorState->setSelected("2");
// Grab mouse
myGrabMouse->setState(true);
- // Paddle speed (mouse)
- myMPaddleSpeed->setValue(10);
-
handleMouseControlState();
handleCursorState();
break;
@@ -691,6 +694,7 @@ void InputDialog::handleCommand(CommandSender* sender, int cmd,
case kMouseCtrlChanged:
handleMouseControlState();
+ handleCursorState();
break;
case kCursorStateChanged:
@@ -725,14 +729,19 @@ void InputDialog::updateDejitterReaction()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void InputDialog::handleMouseControlState()
{
- myMPaddleSpeed->setEnabled(myMouseControl->getSelected() != 2);
+ bool enable = myMouseControl->getSelected() != 2;
+
+ myMouseSensitivity->setEnabled(enable);
+ myMPaddleSpeed->setEnabled(enable);
+ myTrackBallSpeed->setEnabled(enable);
+ myDrivingSpeed->setEnabled(enable);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void InputDialog::handleCursorState()
{
int state = myCursorState->getSelected();
- bool enableGrab = state != 1 && state != 3;
+ bool enableGrab = state != 1 && state != 3 && myMouseControl->getSelected() != 2;
myGrabMouse->setEnabled(enableGrab);
}
diff --git a/src/gui/InputDialog.hxx b/src/gui/InputDialog.hxx
index 54fde4a91..48e1629a3 100644
--- a/src/gui/InputDialog.hxx
+++ b/src/gui/InputDialog.hxx
@@ -62,7 +62,6 @@ class InputDialog : public Dialog
void addDevicePortTab();
void addMouseTab();
-
void handleMouseControlState();
void handleCursorState();
void updateDejitterAveraging();
@@ -91,9 +90,7 @@ class InputDialog : public Dialog
EventMappingWidget* myEmulEventMapper{nullptr};
EventMappingWidget* myMenuEventMapper{nullptr};
- CheckboxWidget* mySAPort{nullptr};
- PopUpWidget* myMouseControl{nullptr};
- PopUpWidget* myCursorState{nullptr};
+ CheckboxWidget* mySAPort{nullptr};
EditTextWidget* myAVoxPort{nullptr};
@@ -102,16 +99,20 @@ class InputDialog : public Dialog
SliderWidget* myDejitterBase{nullptr};
SliderWidget* myDejitterDiff{nullptr};
SliderWidget* myDPaddleSpeed{nullptr};
- SliderWidget* myMPaddleSpeed{nullptr};
- SliderWidget* myTrackBallSpeed{nullptr};
- SliderWidget* myDrivingSpeed{nullptr};
CheckboxWidget* myAllowAll4{nullptr};
- CheckboxWidget* myGrabMouse{nullptr};
CheckboxWidget* myModCombo{nullptr};
ButtonWidget* myJoyDlgButton{nullptr};
ButtonWidget* myEraseEEPROMButton{nullptr};
+ PopUpWidget* myMouseControl{nullptr};
+ StaticTextWidget* myMouseSensitivity{nullptr};
+ SliderWidget* myMPaddleSpeed{nullptr};
+ SliderWidget* myTrackBallSpeed{nullptr};
+ SliderWidget* myDrivingSpeed{nullptr};
+ PopUpWidget* myCursorState{nullptr};
+ CheckboxWidget* myGrabMouse{nullptr};
+
// Show the list of joysticks that the eventhandler knows about
unique_ptr myJoyDialog;
diff --git a/src/gui/LauncherDialog.hxx b/src/gui/LauncherDialog.hxx
index bfa0cecba..faeea2598 100644
--- a/src/gui/LauncherDialog.hxx
+++ b/src/gui/LauncherDialog.hxx
@@ -32,6 +32,9 @@ class EditTextWidget;
class FileListWidget;
class RomInfoWidget;
class StaticTextWidget;
+namespace Common {
+ struct Size;
+}
namespace GUI {
class MessageBox;
}
@@ -41,7 +44,6 @@ namespace GUI {
#include "bspf.hxx"
#include "Dialog.hxx"
#include "FSNode.hxx"
-#include "Stack.hxx"
class LauncherDialog : public Dialog
{
diff --git a/src/gui/Menu.cxx b/src/gui/Menu.cxx
index c2976857f..547f8e2ac 100644
--- a/src/gui/Menu.cxx
+++ b/src/gui/Menu.cxx
@@ -19,6 +19,7 @@
#include "FrameBufferConstants.hxx"
#include "OptionsDialog.hxx"
#include "StellaSettingsDialog.hxx"
+#include "OSystem.hxx"
#include "FrameBuffer.hxx"
#include "bspf.hxx"
#include "Menu.hxx"
diff --git a/src/gui/MessageDialog.cxx b/src/gui/MessageDialog.cxx
index d00acc5a5..ca52c99e6 100644
--- a/src/gui/MessageDialog.cxx
+++ b/src/gui/MessageDialog.cxx
@@ -15,6 +15,7 @@
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
+#include "OSystem.hxx"
#include "Console.hxx"
#include "EventHandler.hxx"
#include "Font.hxx"
diff --git a/src/gui/MessageMenu.cxx b/src/gui/MessageMenu.cxx
index f7c7f0faa..19b700ae7 100644
--- a/src/gui/MessageMenu.cxx
+++ b/src/gui/MessageMenu.cxx
@@ -16,6 +16,7 @@
//============================================================================
#include "Dialog.hxx"
+#include "OSystem.hxx"
#include "FrameBuffer.hxx"
#include "MessageDialog.hxx"
#include "MessageMenu.hxx"
diff --git a/src/gui/MinUICommandDialog.cxx b/src/gui/MinUICommandDialog.cxx
index b93b95890..080316005 100644
--- a/src/gui/MinUICommandDialog.cxx
+++ b/src/gui/MinUICommandDialog.cxx
@@ -217,7 +217,7 @@ void MinUICommandDialog::handleCommand(CommandSender* sender, int cmd,
// Column 3
case kFormatCmd:
- instance().console().toggleFormat();
+ instance().console().selectFormat();
updateTVFormat();
break;
diff --git a/src/gui/OptionsDialog.cxx b/src/gui/OptionsDialog.cxx
index 84ea9f605..865103822 100644
--- a/src/gui/OptionsDialog.cxx
+++ b/src/gui/OptionsDialog.cxx
@@ -23,8 +23,8 @@
#include "Widget.hxx"
#include "Font.hxx"
#include "Control.hxx"
-#include "VideoDialog.hxx"
-#include "AudioDialog.hxx"
+#include "EmulationDialog.hxx"
+#include "VideoAudioDialog.hxx"
#include "InputDialog.hxx"
#include "UIDialog.hxx"
#include "SnapshotDialog.hxx"
@@ -89,13 +89,10 @@ OptionsDialog::OptionsDialog(OSystem& osystem, DialogContainer& parent,
return bw;
};
- b = ADD_OD_BUTTON("Video" + ELLIPSIS, kVidCmd);
+ b = ADD_OD_BUTTON("Video & Audio" + ELLIPSIS, kVidCmd);
wid.push_back(b);
- b = ADD_OD_BUTTON("Audio" + ELLIPSIS, kAudCmd);
-#ifndef SOUND_SUPPORT
- b->clearFlags(Widget::FLAG_ENABLED);
-#endif
+ b = ADD_OD_BUTTON("Emulation" + ELLIPSIS, kEmuCmd);
wid.push_back(b);
b = ADD_OD_BUTTON("Input" + ELLIPSIS, kInptCmd);
@@ -143,8 +140,8 @@ OptionsDialog::OptionsDialog(OSystem& osystem, DialogContainer& parent,
addCancelWidget(b);
// Now create all the dialogs attached to each menu button
- myVideoDialog = make_unique(osystem, parent, _font, max_w, max_h);
- myAudioDialog = make_unique(osystem, parent, _font);
+ myVideoDialog = make_unique(osystem, parent, _font, max_w, max_h);
+ myEmulationDialog= make_unique(osystem, parent, _font, max_w, max_h);
myInputDialog = make_unique(osystem, parent, _font, max_w, max_h);
myUIDialog = make_unique(osystem, parent, _font, boss, max_w, max_h);
mySnapshotDialog = make_unique(osystem, parent, _font, max_w, max_h);
@@ -212,6 +209,10 @@ void OptionsDialog::handleCommand(CommandSender* sender, int cmd,
instance().eventHandler().leaveMenuMode();
break;
+ case kEmuCmd:
+ myEmulationDialog->open();
+ break;
+
case kVidCmd:
{
// This dialog is resizable under certain conditions, so we need
@@ -220,17 +221,12 @@ void OptionsDialog::handleCommand(CommandSender* sender, int cmd,
if(myVideoDialog == nullptr || myVideoDialog->shouldResize(w, h))
{
- myVideoDialog = make_unique(instance(), parent(),
+ myVideoDialog = make_unique(instance(), parent(),
instance().frameBuffer().font(), w, h);
}
myVideoDialog->open();
break;
}
-
- case kAudCmd:
- myAudioDialog->open();
- break;
-
case kInptCmd:
{
// This dialog is resizable under certain conditions, so we need
diff --git a/src/gui/OptionsDialog.hxx b/src/gui/OptionsDialog.hxx
index 3b5598693..001fad73b 100644
--- a/src/gui/OptionsDialog.hxx
+++ b/src/gui/OptionsDialog.hxx
@@ -22,8 +22,8 @@ class CommandSender;
class DialogContainer;
class GuiObject;
class OSystem;
-class VideoDialog;
-class AudioDialog;
+class EmulationDialog;
+class VideoAudioDialog;
class InputDialog;
class UIDialog;
class SnapshotDialog;
@@ -52,8 +52,8 @@ class OptionsDialog : public Dialog
void handleCommand(CommandSender* sender, int cmd, int data, int id) override;
private:
- unique_ptr myVideoDialog;
- unique_ptr myAudioDialog;
+ unique_ptr myVideoDialog;
+ unique_ptr myEmulationDialog;
unique_ptr myInputDialog;
unique_ptr myUIDialog;
unique_ptr mySnapshotDialog;
@@ -78,7 +78,7 @@ class OptionsDialog : public Dialog
enum {
kBasSetCmd = 'BAST',
kVidCmd = 'VIDO',
- kAudCmd = 'AUDO',
+ kEmuCmd = 'EMUO',
kInptCmd = 'INPT',
kUsrIfaceCmd = 'URIF',
kSnapCmd = 'SNAP',
diff --git a/src/gui/RomAuditDialog.cxx b/src/gui/RomAuditDialog.cxx
index 890da7e95..58b9acaba 100644
--- a/src/gui/RomAuditDialog.cxx
+++ b/src/gui/RomAuditDialog.cxx
@@ -25,6 +25,7 @@
#include "FSNode.hxx"
#include "Font.hxx"
#include "MessageBox.hxx"
+#include "OSystem.hxx"
#include "FrameBuffer.hxx"
#include "MD5.hxx"
#include "Props.hxx"
diff --git a/src/gui/RomInfoWidget.cxx b/src/gui/RomInfoWidget.cxx
index 8b1852528..3cfa43185 100644
--- a/src/gui/RomInfoWidget.cxx
+++ b/src/gui/RomInfoWidget.cxx
@@ -48,6 +48,11 @@ RomInfoWidget::RomInfoWidget(GuiObject* boss, const GUI::Font& font,
void RomInfoWidget::setProperties(const FilesystemNode& node, const string& md5)
{
myHaveProperties = true;
+
+ // Make sure to load a per-ROM properties entry, if one exists
+ instance().propSet().loadPerROM(node, md5);
+
+ // And now get the properties for this ROM
instance().propSet().getMD5(md5, myProperties);
// Decide whether the information should be shown immediately
diff --git a/src/gui/SnapshotDialog.cxx b/src/gui/SnapshotDialog.cxx
index 2c0534ffa..870a82b54 100644
--- a/src/gui/SnapshotDialog.cxx
+++ b/src/gui/SnapshotDialog.cxx
@@ -21,6 +21,7 @@
#include "FSNode.hxx"
#include "Font.hxx"
#include "LauncherDialog.hxx"
+#include "OSystem.hxx"
#include "Settings.hxx"
#include "SnapshotDialog.hxx"
diff --git a/src/gui/StellaSettingsDialog.cxx b/src/gui/StellaSettingsDialog.cxx
index fbd93dc7d..b5c1e5106 100644
--- a/src/gui/StellaSettingsDialog.cxx
+++ b/src/gui/StellaSettingsDialog.cxx
@@ -15,6 +15,7 @@
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
+#include "OSystem.hxx"
#include "Console.hxx"
#include "EventHandler.hxx"
#include "Launcher.hxx"
@@ -88,6 +89,11 @@ StellaSettingsDialog::StellaSettingsDialog(OSystem& osystem, DialogContainer& pa
addToFocusList(wid);
}
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+StellaSettingsDialog::~StellaSettingsDialog()
+{
+}
+
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void StellaSettingsDialog::addUIOptions(WidgetArray& wid, int& xpos, int& ypos)
{
diff --git a/src/gui/StellaSettingsDialog.hxx b/src/gui/StellaSettingsDialog.hxx
index 791db381c..6f7cfe8a8 100644
--- a/src/gui/StellaSettingsDialog.hxx
+++ b/src/gui/StellaSettingsDialog.hxx
@@ -23,7 +23,6 @@ class PopUpWidget;
#include "Props.hxx"
#include "Menu.hxx"
#include "Dialog.hxx"
-#include "MessageBox.hxx"
#if defined(RETRON77)
#include "R77HelpDialog.hxx"
@@ -33,6 +32,7 @@ class PopUpWidget;
namespace GUI {
class Font;
+ class MessageBox;
}
class StellaSettingsDialog : public Dialog
@@ -40,7 +40,7 @@ class StellaSettingsDialog : public Dialog
public:
StellaSettingsDialog(OSystem& osystem, DialogContainer& parent,
int max_w, int max_h, Menu::AppMode mode);
- virtual ~StellaSettingsDialog() = default;
+ virtual ~StellaSettingsDialog();
private:
void loadConfig() override;
diff --git a/src/gui/UIDialog.cxx b/src/gui/UIDialog.cxx
index 099886b9b..eafc2e00b 100644
--- a/src/gui/UIDialog.cxx
+++ b/src/gui/UIDialog.cxx
@@ -105,12 +105,13 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent,
wid.push_back(myDialogFontPopup);
// Enable HiDPI mode
- myHidpiWidget = new CheckboxWidget(myTab, font, myDialogFontPopup->getRight() + fontWidth * 5,
+ xpos = myDialogFontPopup->getRight() + fontWidth * 5;
+ myHidpiWidget = new CheckboxWidget(myTab, font, xpos,
ypos + 1, "HiDPI mode (*)");
wid.push_back(myHidpiWidget);
- ypos += lineHeight + VGAP;
// Dialog position
+ xpos = HBORDER; ypos += lineHeight + VGAP;
items.clear();
VarList::push_back(items, "Centered", 0);
VarList::push_back(items, "Left top", 1);
@@ -120,14 +121,14 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent,
myPositionPopup = new PopUpWidget(myTab, font, xpos, ypos, pwidth, lineHeight,
items, "Dialogs position", lwidth);
wid.push_back(myPositionPopup);
- ypos += lineHeight + VGAP * 2;
- // Confirm dialog when exiting emulation
- myConfirmExitWidget = new CheckboxWidget(myTab, font, xpos, ypos, "Confirm exiting emulation");
- wid.push_back(myConfirmExitWidget);
- ypos += lineHeight + VGAP * 3;
+ // Center window (in windowed mode)
+ xpos = myHidpiWidget->getLeft();
+ myCenter = new CheckboxWidget(myTab, _font, xpos, ypos + 1, "Center windows");
+ wid.push_back(myCenter);
// Delay between quick-selecting characters in ListWidget
+ xpos = HBORDER; ypos += lineHeight + VGAP * 4;
int swidth = myPalettePopup->getWidth() - lwidth;
myListDelaySlider = new SliderWidget(myTab, font, xpos, ypos, swidth, lineHeight,
"List input delay ", 0, kListDelay,
@@ -303,6 +304,10 @@ UIDialog::UIDialog(OSystem& osystem, DialogContainer& parent,
wid.clear();
addDefaultsOKCancelBGroup(wid, font);
addBGroupToFocusList(wid);
+
+#ifndef WINDOWED_SUPPORT
+ myCenter->clearFlags(Widget::FLAG_ENABLED);
+#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -353,6 +358,10 @@ void UIDialog::loadConfig()
const string& pal = settings.getString("uipalette");
myPalettePopup->setSelected(pal, "standard");
+ // Dialog font
+ const string& dialogFont = settings.getString("dialogfont");
+ myDialogFontPopup->setSelected(dialogFont, "medium");
+
// Enable HiDPI mode
if (!instance().frameBuffer().hidpiAllowed())
{
@@ -364,16 +373,12 @@ void UIDialog::loadConfig()
myHidpiWidget->setState(settings.getBool("hidpi"));
}
- // Confirm dialog when exiting emulation
- myConfirmExitWidget->setState(settings.getBool("confirmexit"));
-
- // Dialog font
- const string& dialogFont = settings.getString("dialogfont");
- myDialogFontPopup->setSelected(dialogFont, "medium");
-
// Dialog position
myPositionPopup->setSelected(settings.getString("dialogpos"), "0");
+ // Center window
+ myCenter->setState(settings.getBool("center"));
+
// Listwidget quick delay
int delay = settings.getInt("listdelay");
myListDelaySlider->setValue(delay);
@@ -436,18 +441,18 @@ void UIDialog::saveConfig()
myPalettePopup->getSelectedTag().toString());
instance().frameBuffer().setUIPalette();
- // Enable HiDPI mode
- settings.setValue("hidpi", myHidpiWidget->getState());
-
// Dialog font
settings.setValue("dialogfont",
myDialogFontPopup->getSelectedTag().toString());
+ // Enable HiDPI mode
+ settings.setValue("hidpi", myHidpiWidget->getState());
+
// Dialog position
settings.setValue("dialogpos", myPositionPopup->getSelectedTag().toString());
- // Confirm dialog when exiting emulation
- settings.setValue("confirmexit", myConfirmExitWidget->getState());
+ // Center window
+ settings.setValue("center", myCenter->getState());
// Listwidget quick delay
settings.setValue("listdelay", myListDelaySlider->getValue());
@@ -481,10 +486,10 @@ void UIDialog::setDefaults()
{
case 0: // Misc. options
myPalettePopup->setSelected("standard");
- myHidpiWidget->setState(false);
myDialogFontPopup->setSelected("medium", "");
+ myHidpiWidget->setState(false);
myPositionPopup->setSelected("0");
- myConfirmExitWidget->setState(false);
+ myCenter->setState(false);
myListDelaySlider->setValue(300);
myWheelLinesSlider->setValue(4);
myDoubleClickSlider->setValue(500);
diff --git a/src/gui/UIDialog.hxx b/src/gui/UIDialog.hxx
index 83851e971..6ed1c655f 100644
--- a/src/gui/UIDialog.hxx
+++ b/src/gui/UIDialog.hxx
@@ -66,10 +66,10 @@ class UIDialog : public Dialog, public CommandSender
// Misc options
PopUpWidget* myPalettePopup{nullptr};
- CheckboxWidget* myHidpiWidget{nullptr};
PopUpWidget* myDialogFontPopup{nullptr};
+ CheckboxWidget* myHidpiWidget{nullptr};
PopUpWidget* myPositionPopup{nullptr};
- CheckboxWidget* myConfirmExitWidget{nullptr};
+ CheckboxWidget* myCenter{nullptr};
SliderWidget* myListDelaySlider{nullptr};
SliderWidget* myWheelLinesSlider{nullptr};
SliderWidget* myControllerRateSlider{nullptr};
diff --git a/src/gui/VideoAudioDialog.cxx b/src/gui/VideoAudioDialog.cxx
new file mode 100644
index 000000000..48fdcc8de
--- /dev/null
+++ b/src/gui/VideoAudioDialog.cxx
@@ -0,0 +1,1084 @@
+//============================================================================
+//
+// SSSS tt lll lll
+// SS SS tt ll ll
+// SS tttttt eeee ll ll aaaa
+// SSSS tt ee ee ll ll aa
+// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
+// SS SS tt ee ll ll aa aa
+// SSSS ttt eeeee llll llll aaaaa
+//
+// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony
+// and the Stella Team
+//
+// See the file "License.txt" for information on usage and redistribution of
+// this file, and for a DISCLAIMER OF ALL WARRANTIES.
+//============================================================================
+
+#include
+
+#include "bspf.hxx"
+#include "Base.hxx"
+#include "Control.hxx"
+#include "Cart.hxx"
+#include "CartDPC.hxx"
+#include "Dialog.hxx"
+#include "Menu.hxx"
+#include "OSystem.hxx"
+#include "EditTextWidget.hxx"
+#include "PopUpWidget.hxx"
+#include "ColorWidget.hxx"
+#include "Console.hxx"
+#include "PaletteHandler.hxx"
+#include "TIA.hxx"
+#include "Settings.hxx"
+#include "Sound.hxx"
+#include "AudioSettings.hxx"
+#include "Widget.hxx"
+#include "Font.hxx"
+#include "TabWidget.hxx"
+#include "NTSCFilter.hxx"
+#include "TIASurface.hxx"
+
+#include "VideoAudioDialog.hxx"
+
+#define CREATE_CUSTOM_SLIDERS(obj, desc, cmd) \
+ myTV ## obj = \
+ new SliderWidget(myTab, _font, xpos, ypos-1, swidth, lineHeight, \
+ desc, lwidth, cmd, fontWidth*4, "%"); \
+ myTV ## obj->setMinValue(0); myTV ## obj->setMaxValue(100); \
+ myTV ## obj->setStepValue(2); \
+ myTV ## obj->setTickmarkIntervals(2); \
+ wid.push_back(myTV ## obj); \
+ ypos += lineHeight + VGAP;
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+VideoAudioDialog::VideoAudioDialog(OSystem& osystem, DialogContainer& parent,
+ const GUI::Font& font, int max_w, int max_h)
+ : Dialog(osystem, parent, font, "Video & Audio settings")
+{
+ const int lineHeight = _font.getLineHeight(),
+ fontHeight = _font.getFontHeight(),
+ fontWidth = _font.getMaxCharWidth(),
+ buttonHeight = _font.getLineHeight() * 1.25;
+ const int VGAP = fontHeight / 4;
+ const int VBORDER = fontHeight / 2;
+ const int HBORDER = fontWidth * 1.25;
+ int xpos, ypos;
+
+ // Set real dimensions
+ setSize(44 * fontWidth + HBORDER * 2 + PopUpWidget::dropDownWidth(font) * 2,
+ _th + VGAP * 6 + lineHeight + 10 * (lineHeight + VGAP) + buttonHeight + VBORDER * 3,
+ max_w, max_h);
+
+ // The tab widget
+ xpos = 2; ypos = VGAP;
+ myTab = new TabWidget(this, font, xpos, ypos + _th,
+ _w - 2*xpos,
+ _h - _th - VGAP - buttonHeight - VBORDER * 2);
+ addTabWidget(myTab);
+
+ addDisplayTab();
+ addPaletteTab();
+ addTVEffectsTab();
+ addAudioTab();
+
+ //const int req_w = std::max(myFastSCBios->getRight(), myCloneBad->getRight()) + HBORDER + 1;
+ //const int req_h = _th + VGAP * 3
+ // + std::max(myUseVSync->getBottom(), myTVScanIntense->getBottom())
+ // + buttonHeight + VBORDER * 2;
+ //// Set real dimensions
+ //setSize(req_w, req_h, max_w, max_h);
+
+
+ // Add Defaults, OK and Cancel buttons
+ WidgetArray wid;
+ addDefaultsOKCancelBGroup(wid, _font);
+ addBGroupToFocusList(wid);
+
+ // Activate the first tab
+ myTab->setActiveTab(0);
+
+ // Disable certain functions when we know they aren't present
+#ifndef WINDOWED_SUPPORT
+ myFullscreen->clearFlags(Widget::FLAG_ENABLED);
+ myUseStretch->clearFlags(Widget::FLAG_ENABLED);
+ myTVOverscan->clearFlags(Widget::FLAG_ENABLED);
+#endif
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void VideoAudioDialog::addDisplayTab()
+{
+ const int lineHeight = _font.getLineHeight(),
+ fontHeight = _font.getFontHeight(),
+ fontWidth = _font.getMaxCharWidth();
+ const int VGAP = fontHeight / 4;
+ const int VBORDER = fontHeight / 2;
+ const int HBORDER = fontWidth * 1.25;
+ const int INDENT = CheckboxWidget::prefixSize(_font);
+ const int lwidth = _font.getStringWidth("V-Size adjust "),
+ pwidth = _font.getStringWidth("OpenGLES2");
+ int xpos = HBORDER,
+ ypos = VBORDER;
+ WidgetArray wid;
+ VariantList items;
+ const int tabID = myTab->addTab(" Display ", TabWidget::AUTO_WIDTH);
+
+ // Video renderer
+ myRenderer = new PopUpWidget(myTab, _font, xpos, ypos, pwidth, lineHeight,
+ instance().frameBuffer().supportedRenderers(),
+ "Renderer ", lwidth);
+ wid.push_back(myRenderer);
+ const int swidth = myRenderer->getWidth() - lwidth;
+ ypos += lineHeight + VGAP;
+
+ // TIA interpolation
+ myTIAInterpolate = new CheckboxWidget(myTab, _font, xpos, ypos + 1, "Interpolation ");
+ wid.push_back(myTIAInterpolate); ypos += lineHeight + VGAP * 4;
+
+ // TIA zoom levels (will be dynamically filled later)
+ myTIAZoom = new SliderWidget(myTab, _font, xpos, ypos - 1, swidth, lineHeight,
+ "Zoom ", lwidth, 0, fontWidth * 4, "%");
+ myTIAZoom->setMinValue(200); myTIAZoom->setStepValue(FrameBuffer::ZOOM_STEPS * 100);
+ wid.push_back(myTIAZoom);
+ ypos += lineHeight + VGAP;
+
+ // Fullscreen
+ myFullscreen = new CheckboxWidget(myTab, _font, xpos, ypos + 1, "Fullscreen", kFullScreenChanged);
+ wid.push_back(myFullscreen);
+ ypos += lineHeight + VGAP;
+
+ /*pwidth = font.getStringWidth("0: 3840x2860@120Hz");
+ myFullScreenMode = new PopUpWidget(myTab, font, xpos + INDENT + 2, ypos, pwidth, lineHeight,
+ instance().frameBuffer().supportedScreenModes(), "Mode ");
+ wid.push_back(myFullScreenMode);
+ ypos += lineHeight + VGAP;*/
+
+ // FS stretch
+ myUseStretch = new CheckboxWidget(myTab, _font, xpos + INDENT, ypos + 1, "Stretch");
+ wid.push_back(myUseStretch);
+ ypos += lineHeight + VGAP;
+
+ // FS overscan
+ myTVOverscan = new SliderWidget(myTab, _font, xpos + INDENT, ypos - 1, swidth, lineHeight,
+ "Overscan", lwidth - INDENT, kOverscanChanged, fontWidth * 3, "%");
+ myTVOverscan->setMinValue(0); myTVOverscan->setMaxValue(10);
+ myTVOverscan->setTickmarkIntervals(2);
+ wid.push_back(myTVOverscan);
+ ypos += lineHeight + VGAP;
+
+ // Vertical size
+ myVSizeAdjust =
+ new SliderWidget(myTab, _font, xpos, ypos-1, swidth, lineHeight,
+ "V-Size adjust", lwidth, kVSizeChanged, fontWidth * 7, "%", 0, true);
+ myVSizeAdjust->setMinValue(-5); myVSizeAdjust->setMaxValue(5);
+ myVSizeAdjust->setTickmarkIntervals(2);
+ wid.push_back(myVSizeAdjust);
+
+ // Add items for tab 0
+ addToFocusList(wid, myTab, tabID);
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void VideoAudioDialog::addPaletteTab()
+{
+ const int lineHeight = _font.getLineHeight(),
+ fontHeight = _font.getFontHeight(),
+ fontWidth = _font.getMaxCharWidth();
+ const int VBORDER = fontHeight / 2;
+ const int HBORDER = fontWidth * 1.25;
+ const int INDENT = fontWidth * 2;
+ const int VGAP = fontHeight / 4;
+ const int lwidth = _font.getStringWidth(" NTSC phase ");
+ const int pwidth = _font.getStringWidth("Standard");
+ int xpos = HBORDER,
+ ypos = VBORDER;
+ WidgetArray wid;
+ VariantList items;
+ const int tabID = myTab->addTab(" Palettes ", TabWidget::AUTO_WIDTH);
+
+ // TIA Palette
+ items.clear();
+ VarList::push_back(items, "Standard", PaletteHandler::SETTING_STANDARD);
+ VarList::push_back(items, "z26", PaletteHandler::SETTING_Z26);
+ if (instance().checkUserPalette())
+ VarList::push_back(items, "User", PaletteHandler::SETTING_USER);
+ VarList::push_back(items, "Custom", PaletteHandler::SETTING_CUSTOM);
+ myTIAPalette = new PopUpWidget(myTab, _font, xpos, ypos, pwidth,
+ lineHeight, items, "Palette ", lwidth, kPaletteChanged);
+ wid.push_back(myTIAPalette);
+ ypos += lineHeight + VGAP;
+
+ const int swidth = myTIAPalette->getWidth() - lwidth;
+ const int plWidth = _font.getStringWidth("NTSC phase ");
+ const int pswidth = swidth - INDENT + lwidth - plWidth;
+
+ myPhaseShiftNtsc =
+ new SliderWidget(myTab, _font, xpos + INDENT, ypos-1, pswidth, lineHeight,
+ "NTSC phase", plWidth, kNtscShiftChanged, fontWidth * 5);
+ myPhaseShiftNtsc->setMinValue((PaletteHandler::DEF_NTSC_SHIFT - PaletteHandler::MAX_SHIFT) * 10);
+ myPhaseShiftNtsc->setMaxValue((PaletteHandler::DEF_NTSC_SHIFT + PaletteHandler::MAX_SHIFT) * 10);
+ myPhaseShiftNtsc->setTickmarkIntervals(4);
+ wid.push_back(myPhaseShiftNtsc);
+ ypos += lineHeight + VGAP;
+
+ myPhaseShiftPal =
+ new SliderWidget(myTab, _font, xpos + INDENT, ypos-1, pswidth, lineHeight,
+ "PAL phase", plWidth, kPalShiftChanged, fontWidth * 5);
+ myPhaseShiftPal->setMinValue((PaletteHandler::DEF_PAL_SHIFT - PaletteHandler::MAX_SHIFT) * 10);
+ myPhaseShiftPal->setMaxValue((PaletteHandler::DEF_PAL_SHIFT + PaletteHandler::MAX_SHIFT) * 10);
+ myPhaseShiftPal->setTickmarkIntervals(4);
+ wid.push_back(myPhaseShiftPal);
+ ypos += lineHeight + VGAP;
+
+ CREATE_CUSTOM_SLIDERS(Hue, "Hue ", kPaletteUpdated)
+ CREATE_CUSTOM_SLIDERS(Satur, "Saturation ", kPaletteUpdated)
+ CREATE_CUSTOM_SLIDERS(Contrast, "Contrast ", kPaletteUpdated)
+ CREATE_CUSTOM_SLIDERS(Bright, "Brightness ", kPaletteUpdated)
+ CREATE_CUSTOM_SLIDERS(Gamma, "Gamma ", kPaletteUpdated)
+
+ // The resulting palette
+ xpos = myPhaseShiftNtsc->getRight() + fontWidth * 2;
+ addPalette(xpos, VBORDER, _w - 2 * 2 - HBORDER - xpos,
+ myTVGamma->getBottom() - myTIAPalette->getTop());
+
+ // Add items for tab 2
+ addToFocusList(wid, myTab, tabID);
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void VideoAudioDialog::addTVEffectsTab()
+{
+ const int lineHeight = _font.getLineHeight(),
+ fontHeight = _font.getFontHeight(),
+ fontWidth = _font.getMaxCharWidth(),
+ buttonHeight = _font.getLineHeight() * 1.25;
+ const int VBORDER = fontHeight / 2;
+ const int HBORDER = fontWidth * 1.25;
+ const int INDENT = CheckboxWidget::prefixSize(_font);// fontWidth * 2;
+ const int VGAP = fontHeight / 4;
+ int xpos = HBORDER,
+ ypos = VBORDER;
+ const int lwidth = _font.getStringWidth("Saturation ");
+ const int pwidth = _font.getStringWidth("Bad adjust ");
+ WidgetArray wid;
+ VariantList items;
+ const int tabID = myTab->addTab(" TV Effects ", TabWidget::AUTO_WIDTH);
+
+ items.clear();
+ VarList::push_back(items, "Disabled", static_cast(NTSCFilter::Preset::OFF));
+ VarList::push_back(items, "RGB", static_cast(NTSCFilter::Preset::RGB));
+ VarList::push_back(items, "S-Video", static_cast(NTSCFilter::Preset::SVIDEO));
+ VarList::push_back(items, "Composite", static_cast(NTSCFilter::Preset::COMPOSITE));
+ VarList::push_back(items, "Bad adjust", static_cast(NTSCFilter::Preset::BAD));
+ VarList::push_back(items, "Custom", static_cast(NTSCFilter::Preset::CUSTOM));
+ myTVMode = new PopUpWidget(myTab, _font, xpos, ypos, pwidth, lineHeight,
+ items, "TV mode ", 0, kTVModeChanged);
+ wid.push_back(myTVMode);
+ ypos += lineHeight + VGAP;
+
+ // Custom adjustables (using macro voodoo)
+ const int swidth = myTVMode->getWidth() - INDENT - lwidth;
+ xpos += INDENT;
+
+ CREATE_CUSTOM_SLIDERS(Sharp, "Sharpness ", 0)
+ CREATE_CUSTOM_SLIDERS(Res, "Resolution ", 0)
+ CREATE_CUSTOM_SLIDERS(Artifacts, "Artifacts ", 0)
+ CREATE_CUSTOM_SLIDERS(Fringe, "Fringing ", 0)
+ CREATE_CUSTOM_SLIDERS(Bleed, "Bleeding ", 0)
+
+ ypos += VGAP * 3;
+
+ xpos = HBORDER;
+
+ // TV Phosphor effect
+ myTVPhosphor = new CheckboxWidget(myTab, _font, xpos, ypos + 1, "Phosphor for all ROMs", kPhosphorChanged);
+ wid.push_back(myTVPhosphor);
+ ypos += lineHeight + VGAP / 2;
+
+ // TV Phosphor blend level
+ xpos += INDENT;
+ CREATE_CUSTOM_SLIDERS(PhosLevel, "Blend", kPhosBlendChanged)
+ ypos += VGAP;
+
+ // Scanline intensity and interpolation
+ xpos -= INDENT;
+ myTVScanLabel = new StaticTextWidget(myTab, _font, xpos, ypos, "Scanlines:");
+ ypos += lineHeight + VGAP / 2;
+
+ xpos += INDENT;
+ CREATE_CUSTOM_SLIDERS(ScanIntense, "Intensity", kScanlinesChanged)
+
+ // Create buttons in 2nd column
+ int cloneWidth = _font.getStringWidth("Clone Bad Adjust") + fontWidth * 2.5;
+ xpos = _w - HBORDER - 2 * 2 - cloneWidth;
+ ypos = VBORDER - VGAP / 2;
+
+ // Adjustable presets
+#define CREATE_CLONE_BUTTON(obj, desc) \
+ myClone ## obj = \
+ new ButtonWidget(myTab, _font, xpos, ypos, cloneWidth, buttonHeight,\
+ desc, kClone ## obj ##Cmd); \
+ wid.push_back(myClone ## obj); \
+ ypos += buttonHeight + VGAP;
+
+ ypos += VGAP;
+ CREATE_CLONE_BUTTON(RGB, "Clone RGB")
+ CREATE_CLONE_BUTTON(Svideo, "Clone S-Video")
+ CREATE_CLONE_BUTTON(Composite, "Clone Composite")
+ CREATE_CLONE_BUTTON(Bad, "Clone Bad adjust")
+ CREATE_CLONE_BUTTON(Custom, "Revert")
+
+ // Add items for tab 3
+ addToFocusList(wid, myTab, tabID);
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void VideoAudioDialog::addAudioTab()
+{
+ const int lineHeight = _font.getLineHeight(),
+ fontHeight = _font.getFontHeight(),
+ fontWidth = _font.getMaxCharWidth();
+ const int VBORDER = fontHeight / 2;
+ const int HBORDER = fontWidth * 1.25;
+ const int INDENT = CheckboxWidget::prefixSize(_font);
+ const int VGAP = fontHeight / 4;
+
+ int xpos, ypos;
+ int lwidth = _font.getStringWidth("Volume "),
+ pwidth;
+ WidgetArray wid;
+ VariantList items;
+ const int tabID = myTab->addTab(" Audio ", TabWidget::AUTO_WIDTH);
+
+ xpos = HBORDER; ypos = VBORDER;
+
+ // Enable sound
+ mySoundEnableCheckbox = new CheckboxWidget(myTab, _font, xpos, ypos,
+ "Enable sound", kSoundEnableChanged);
+ wid.push_back(mySoundEnableCheckbox);
+ ypos += lineHeight + VGAP;
+ xpos += CheckboxWidget::prefixSize(_font);
+
+ // Volume
+ myVolumeSlider = new SliderWidget(myTab, _font, xpos, ypos,
+ "Volume", lwidth, 0, 4 * fontWidth, "%");
+ myVolumeSlider->setMinValue(1); myVolumeSlider->setMaxValue(100);
+ myVolumeSlider->setTickmarkIntervals(4);
+ wid.push_back(myVolumeSlider);
+ ypos += lineHeight + VGAP;
+
+ // Mode
+ items.clear();
+ VarList::push_back(items, "Low quality, medium lag", static_cast(AudioSettings::Preset::lowQualityMediumLag));
+ VarList::push_back(items, "High quality, medium lag", static_cast(AudioSettings::Preset::highQualityMediumLag));
+ VarList::push_back(items, "High quality, low lag", static_cast(AudioSettings::Preset::highQualityLowLag));
+ VarList::push_back(items, "Ultra quality, minimal lag", static_cast(AudioSettings::Preset::ultraQualityMinimalLag));
+ VarList::push_back(items, "Custom", static_cast(AudioSettings::Preset::custom));
+ myModePopup = new PopUpWidget(myTab, _font, xpos, ypos,
+ _font.getStringWidth("Ultry quality, minimal lag"), lineHeight,
+ items, "Mode", lwidth, kModeChanged);
+ wid.push_back(myModePopup);
+ ypos += lineHeight + VGAP;
+ xpos += INDENT;
+
+ // Fragment size
+ lwidth = _font.getStringWidth("Resampling quality ");
+ pwidth = myModePopup->getRight() - xpos - lwidth - PopUpWidget::dropDownWidth(_font);
+ items.clear();
+ VarList::push_back(items, "128 samples", 128);
+ VarList::push_back(items, "256 samples", 256);
+ VarList::push_back(items, "512 samples", 512);
+ VarList::push_back(items, "1k samples", 1024);
+ VarList::push_back(items, "2k samples", 2048);
+ VarList::push_back(items, "4K samples", 4096);
+ myFragsizePopup = new PopUpWidget(myTab, _font, xpos, ypos,
+ pwidth, lineHeight,
+ items, "Fragment size", lwidth);
+ wid.push_back(myFragsizePopup);
+ ypos += lineHeight + VGAP;
+
+ // Output frequency
+ items.clear();
+ VarList::push_back(items, "44100 Hz", 44100);
+ VarList::push_back(items, "48000 Hz", 48000);
+ VarList::push_back(items, "96000 Hz", 96000);
+ myFreqPopup = new PopUpWidget(myTab, _font, xpos, ypos,
+ pwidth, lineHeight,
+ items, "Sample rate", lwidth);
+ wid.push_back(myFreqPopup);
+ ypos += lineHeight + VGAP;
+
+ // Resampling quality
+ items.clear();
+ VarList::push_back(items, "Low", static_cast(AudioSettings::ResamplingQuality::nearestNeightbour));
+ VarList::push_back(items, "High", static_cast(AudioSettings::ResamplingQuality::lanczos_2));
+ VarList::push_back(items, "Ultra", static_cast(AudioSettings::ResamplingQuality::lanczos_3));
+ myResamplingPopup = new PopUpWidget(myTab, _font, xpos, ypos,
+ pwidth, lineHeight,
+ items, "Resampling quality ", lwidth);
+ wid.push_back(myResamplingPopup);
+ ypos += lineHeight + VGAP;
+
+ // Param 1
+ int swidth = pwidth + PopUpWidget::dropDownWidth(_font);
+ myHeadroomSlider = new SliderWidget(myTab, _font, xpos, ypos, swidth, lineHeight,
+ "Headroom ", 0, kHeadroomChanged, 10 * fontWidth);
+ myHeadroomSlider->setMinValue(0); myHeadroomSlider->setMaxValue(AudioSettings::MAX_HEADROOM);
+ myHeadroomSlider->setTickmarkIntervals(5);
+ wid.push_back(myHeadroomSlider);
+ ypos += lineHeight + VGAP;
+
+ // Param 2
+ myBufferSizeSlider = new SliderWidget(myTab, _font, xpos, ypos, swidth, lineHeight,
+ "Buffer size ", 0, kBufferSizeChanged, 10 * fontWidth);
+ myBufferSizeSlider->setMinValue(0); myBufferSizeSlider->setMaxValue(AudioSettings::MAX_BUFFER_SIZE);
+ myBufferSizeSlider->setTickmarkIntervals(5);
+ wid.push_back(myBufferSizeSlider);
+ ypos += lineHeight + VGAP;
+
+ // Stereo sound
+ xpos -= INDENT;
+ myStereoSoundCheckbox = new CheckboxWidget(myTab, _font, xpos, ypos,
+ "Stereo for all ROMs");
+ wid.push_back(myStereoSoundCheckbox);
+ ypos += lineHeight + VGAP;
+
+ swidth += INDENT - fontWidth * 4;
+ myDpcPitch = new SliderWidget(myTab, _font, xpos, ypos, swidth, lineHeight,
+ "Pitfall II music pitch ", 0, 0, 5 * fontWidth);
+ myDpcPitch->setMinValue(10000); myDpcPitch->setMaxValue(30000);
+ myDpcPitch->setStepValue(100);
+ myDpcPitch->setTickmarkIntervals(2);
+ wid.push_back(myDpcPitch);
+
+ // Add items for tab 4
+ addToFocusList(wid, myTab, tabID);
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void VideoAudioDialog::loadConfig()
+{
+ // Display tab
+ // Renderer settings
+ myRenderer->setSelected(instance().settings().getString("video"), "default");
+
+ // TIA interpolation
+ myTIAInterpolate->setState(instance().settings().getBool("tia.inter"));
+
+ // TIA zoom levels
+ // These are dynamically loaded, since they depend on the size of
+ // the desktop and which renderer we're using
+ float minZoom = instance().frameBuffer().supportedTIAMinZoom(); // or 2 if we allow lower values
+ float maxZoom = instance().frameBuffer().supportedTIAMaxZoom();
+
+ myTIAZoom->setMinValue(minZoom * 100);
+ myTIAZoom->setMaxValue(maxZoom * 100);
+ myTIAZoom->setTickmarkIntervals((maxZoom - minZoom) * 2); // every ~50%
+ myTIAZoom->setValue(instance().settings().getFloat("tia.zoom") * 100);
+
+ // Fullscreen
+ myFullscreen->setState(instance().settings().getBool("fullscreen"));
+ /*string mode = instance().settings().getString("fullscreenmode");
+ myFullScreenMode->setSelected(mode);*/
+ // Fullscreen stretch setting
+ myUseStretch->setState(instance().settings().getBool("tia.fs_stretch"));
+ // Fullscreen overscan setting
+ myTVOverscan->setValue(instance().settings().getInt("tia.fs_overscan"));
+ handleFullScreenChange();
+
+ // Aspect ratio setting (NTSC and PAL)
+ myVSizeAdjust->setValue(instance().settings().getInt("tia.vsizeadjust"));
+
+ /////////////////////////////////////////////////////////////////////////////
+ // Palettes tab
+ // TIA Palette
+ myPalette = instance().settings().getString("palette");
+ myTIAPalette->setSelected(myPalette, PaletteHandler::SETTING_STANDARD);
+
+ // Palette adjustables
+ instance().frameBuffer().tiaSurface().paletteHandler().getAdjustables(myPaletteAdj);
+ myPhaseShiftNtsc->setValue(myPaletteAdj.phaseNtsc);
+ myPhaseShiftPal->setValue(myPaletteAdj.phasePal);
+ myTVHue->setValue(myPaletteAdj.hue);
+ myTVBright->setValue(myPaletteAdj.brightness);
+ myTVContrast->setValue(myPaletteAdj.contrast);
+ myTVSatur->setValue(myPaletteAdj.saturation);
+ myTVGamma->setValue(myPaletteAdj.gamma);
+ handlePaletteChange();
+ colorPalette();
+
+ /////////////////////////////////////////////////////////////////////////////
+ // TV Effects tab
+ // TV Mode
+ myTVMode->setSelected(
+ instance().settings().getString("tv.filter"), "0");
+ int preset = instance().settings().getInt("tv.filter");
+ handleTVModeChange(NTSCFilter::Preset(preset));
+
+ // TV Custom adjustables
+ loadTVAdjustables(NTSCFilter::Preset::CUSTOM);
+
+ // TV phosphor mode
+ myTVPhosphor->setState(instance().settings().getString("tv.phosphor") == "always");
+
+ // TV phosphor blend
+ myTVPhosLevel->setValue(instance().settings().getInt("tv.phosblend"));
+ handlePhosphorChange();
+
+ // TV scanline intensity and interpolation
+ myTVScanIntense->setValue(instance().settings().getInt("tv.scanlines"));
+
+ /////////////////////////////////////////////////////////////////////////////
+ // Audio tab
+ AudioSettings& audioSettings = instance().audioSettings();
+
+ // Enable sound
+#ifdef SOUND_SUPPORT
+ mySoundEnableCheckbox->setState(audioSettings.enabled());
+#else
+ mySoundEnableCheckbox->setState(false);
+#endif
+
+ // Volume
+ myVolumeSlider->setValue(audioSettings.volume());
+
+ // Stereo
+ myStereoSoundCheckbox->setState(audioSettings.stereo());
+
+ // DPC Pitch
+ myDpcPitch->setValue(audioSettings.dpcPitch());
+
+ // Preset / mode
+ myModePopup->setSelected(static_cast(audioSettings.preset()));
+
+ updateSettingsWithPreset(instance().audioSettings());
+
+ updateEnabledState();
+
+ myTab->loadConfig();
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void VideoAudioDialog::updateSettingsWithPreset(AudioSettings& audioSettings)
+{
+ // Fragsize
+ myFragsizePopup->setSelected(audioSettings.fragmentSize());
+
+ // Output frequency
+ myFreqPopup->setSelected(audioSettings.sampleRate());
+
+ // Headroom
+ myHeadroomSlider->setValue(audioSettings.headroom());
+
+ // Buffer size
+ myBufferSizeSlider->setValue(audioSettings.bufferSize());
+
+ // Resampling quality
+ myResamplingPopup->setSelected(static_cast(audioSettings.resamplingQuality()));
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void VideoAudioDialog::saveConfig()
+{
+ /////////////////////////////////////////////////////////////////////////////
+ // Display tab
+ // Renderer setting
+ instance().settings().setValue("video",
+ myRenderer->getSelectedTag().toString());
+
+ // TIA interpolation
+ instance().settings().setValue("tia.inter", myTIAInterpolate->getState());
+
+ // Fullscreen
+ instance().settings().setValue("fullscreen", myFullscreen->getState());
+ // Fullscreen stretch setting
+ instance().settings().setValue("tia.fs_stretch", myUseStretch->getState());
+ // Fullscreen overscan
+ instance().settings().setValue("tia.fs_overscan", myTVOverscan->getValueLabel());
+
+ // TIA zoom levels
+ instance().settings().setValue("tia.zoom", myTIAZoom->getValue() / 100.0);
+
+ // Aspect ratio setting (NTSC and PAL)
+ const int oldAdjust = instance().settings().getInt("tia.vsizeadjust");
+ const int newAdjust = myVSizeAdjust->getValue();
+ const bool vsizeChanged = oldAdjust != newAdjust;
+
+ instance().settings().setValue("tia.vsizeadjust", newAdjust);
+
+
+ // Note: Palette values are saved directly when changed!
+
+
+ /////////////////////////////////////////////////////////////////////////////
+ // TV Effects tab
+ // TV Mode
+ instance().settings().setValue("tv.filter",
+ myTVMode->getSelectedTag().toString());
+ // TV Custom adjustables
+ NTSCFilter::Adjustable ntscAdj;
+ ntscAdj.sharpness = myTVSharp->getValue();
+ ntscAdj.resolution = myTVRes->getValue();
+ ntscAdj.artifacts = myTVArtifacts->getValue();
+ ntscAdj.fringing = myTVFringe->getValue();
+ ntscAdj.bleed = myTVBleed->getValue();
+ instance().frameBuffer().tiaSurface().ntsc().setCustomAdjustables(ntscAdj);
+
+ // TV phosphor mode
+ instance().settings().setValue("tv.phosphor",
+ myTVPhosphor->getState() ? "always" : "byrom");
+ // TV phosphor blend
+ instance().settings().setValue("tv.phosblend", myTVPhosLevel->getValueLabel() == "Off"
+ ? "0" : myTVPhosLevel->getValueLabel());
+
+ // TV scanline intensity
+ instance().settings().setValue("tv.scanlines", myTVScanIntense->getValueLabel());
+
+ if(instance().hasConsole())
+ {
+ instance().console().setTIAProperties();
+
+ if(vsizeChanged)
+ {
+ instance().console().tia().clearFrameBuffer();
+ instance().console().initializeVideo();
+ }
+ }
+
+ // Finally, issue a complete framebuffer re-initialization...
+ instance().createFrameBuffer();
+
+ // ... and apply potential setting changes to the TIA surface
+ instance().frameBuffer().tiaSurface().updateSurfaceSettings();
+
+ /////////////////////////////////////////////////////////////////////////////
+ // Audio tab
+ AudioSettings& audioSettings = instance().audioSettings();
+
+ // Enabled
+ audioSettings.setEnabled(mySoundEnableCheckbox->getState());
+ instance().sound().setEnabled(mySoundEnableCheckbox->getState());
+
+ // Volume
+ audioSettings.setVolume(myVolumeSlider->getValue());
+ instance().sound().setVolume(myVolumeSlider->getValue());
+
+ // Stereo
+ audioSettings.setStereo(myStereoSoundCheckbox->getState());
+
+ // DPC Pitch
+ audioSettings.setDpcPitch(myDpcPitch->getValue());
+ // update if current cart is Pitfall II
+ if (instance().hasConsole() && instance().console().cartridge().name() == "CartridgeDPC")
+ {
+ CartridgeDPC& cart = static_cast(instance().console().cartridge());
+ cart.setDpcPitch(myDpcPitch->getValue());
+ }
+
+ AudioSettings::Preset preset = static_cast(myModePopup->getSelectedTag().toInt());
+ audioSettings.setPreset(preset);
+
+ if (preset == AudioSettings::Preset::custom) {
+ // Fragsize
+ audioSettings.setFragmentSize(myFragsizePopup->getSelectedTag().toInt());
+ audioSettings.setSampleRate(myFreqPopup->getSelectedTag().toInt());
+ audioSettings.setHeadroom(myHeadroomSlider->getValue());
+ audioSettings.setBufferSize(myBufferSizeSlider->getValue());
+ audioSettings.setResamplingQuality(static_cast(myResamplingPopup->getSelectedTag().toInt()));
+ }
+
+ // Only force a re-initialization when necessary, since it can
+ // be a time-consuming operation
+ if(instance().hasConsole())
+ instance().console().initializeAudio();
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void VideoAudioDialog::setDefaults()
+{
+ switch(myTab->getActiveTab())
+ {
+ case 0: // General
+ {
+ myRenderer->setSelectedIndex(0);
+ myTIAInterpolate->setState(false);
+ // screen size
+ myFullscreen->setState(false);
+ //myFullScreenMode->setSelectedIndex(0);
+ myUseStretch->setState(false);
+ myTVOverscan->setValue(0);
+ myTIAZoom->setValue(300);
+ myVSizeAdjust->setValue(0);
+
+ handleFullScreenChange();
+ break;
+ }
+
+ case 1: // Palettes
+ myTIAPalette->setSelected(PaletteHandler::SETTING_STANDARD);
+ myPhaseShiftNtsc->setValue(PaletteHandler::DEF_NTSC_SHIFT * 10);
+ myPhaseShiftPal->setValue(PaletteHandler::DEF_PAL_SHIFT * 10);
+ myTVHue->setValue(50);
+ myTVSatur->setValue(50);
+ myTVContrast->setValue(50);
+ myTVBright->setValue(50);
+ myTVGamma->setValue(50);
+ handlePaletteChange();
+ break;
+
+ case 2: // TV effects
+ {
+ myTVMode->setSelected("0", "0");
+
+ // TV phosphor mode
+ myTVPhosphor->setState(false);
+
+ // TV phosphor blend
+ myTVPhosLevel->setValue(50);
+
+ // TV scanline intensity and interpolation
+ myTVScanIntense->setValue(25);
+
+ // Make sure that mutually-exclusive items are not enabled at the same time
+ handleTVModeChange(NTSCFilter::Preset::OFF);
+ handlePhosphorChange();
+ loadTVAdjustables(NTSCFilter::Preset::CUSTOM);
+ break;
+ }
+ case 3: // Audio
+ mySoundEnableCheckbox->setState(AudioSettings::DEFAULT_ENABLED);
+ myVolumeSlider->setValue(AudioSettings::DEFAULT_VOLUME);
+ myStereoSoundCheckbox->setState(AudioSettings::DEFAULT_STEREO);
+ myDpcPitch->setValue(AudioSettings::DEFAULT_DPC_PITCH);
+ myModePopup->setSelected(static_cast(AudioSettings::DEFAULT_PRESET));
+
+ if (AudioSettings::DEFAULT_PRESET == AudioSettings::Preset::custom) {
+ myResamplingPopup->setSelected(static_cast(AudioSettings::DEFAULT_RESAMPLING_QUALITY));
+ myFragsizePopup->setSelected(AudioSettings::DEFAULT_FRAGMENT_SIZE);
+ myFreqPopup->setSelected(AudioSettings::DEFAULT_SAMPLE_RATE);
+ myHeadroomSlider->setValue(AudioSettings::DEFAULT_HEADROOM);
+ myBufferSizeSlider->setValue(AudioSettings::DEFAULT_BUFFER_SIZE);
+ }
+ else updatePreset();
+
+ updateEnabledState();
+ break;
+ }
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void VideoAudioDialog::handleTVModeChange(NTSCFilter::Preset preset)
+{
+ bool enable = preset == NTSCFilter::Preset::CUSTOM;
+
+ myTVSharp->setEnabled(enable);
+ myTVRes->setEnabled(enable);
+ myTVArtifacts->setEnabled(enable);
+ myTVFringe->setEnabled(enable);
+ myTVBleed->setEnabled(enable);
+ myCloneComposite->setEnabled(enable);
+ myCloneSvideo->setEnabled(enable);
+ myCloneRGB->setEnabled(enable);
+ myCloneBad->setEnabled(enable);
+ myCloneCustom->setEnabled(enable);
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void VideoAudioDialog::loadTVAdjustables(NTSCFilter::Preset preset)
+{
+ NTSCFilter::Adjustable adj;
+ instance().frameBuffer().tiaSurface().ntsc().getAdjustables(
+ adj, NTSCFilter::Preset(preset));
+ myTVSharp->setValue(adj.sharpness);
+ myTVRes->setValue(adj.resolution);
+ myTVArtifacts->setValue(adj.artifacts);
+ myTVFringe->setValue(adj.fringing);
+ myTVBleed->setValue(adj.bleed);
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void VideoAudioDialog::handlePaletteChange()
+{
+ bool enable = myTIAPalette->getSelectedTag().toString() == "custom";
+
+ myPhaseShiftNtsc->setEnabled(enable);
+ myPhaseShiftPal->setEnabled(enable);
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void VideoAudioDialog::handlePaletteUpdate()
+{
+ // TIA Palette
+ instance().settings().setValue("palette",
+ myTIAPalette->getSelectedTag().toString());
+ // Palette adjustables
+ PaletteHandler::Adjustable paletteAdj;
+ paletteAdj.phaseNtsc = myPhaseShiftNtsc->getValue();
+ paletteAdj.phasePal = myPhaseShiftPal->getValue();
+ paletteAdj.hue = myTVHue->getValue();
+ paletteAdj.saturation = myTVSatur->getValue();
+ paletteAdj.contrast = myTVContrast->getValue();
+ paletteAdj.brightness = myTVBright->getValue();
+ paletteAdj.gamma = myTVGamma->getValue();
+ instance().frameBuffer().tiaSurface().paletteHandler().setAdjustables(paletteAdj);
+
+ if(instance().hasConsole())
+ instance().frameBuffer().tiaSurface().paletteHandler().setPalette();
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void VideoAudioDialog::handleFullScreenChange()
+{
+ bool enable = myFullscreen->getState();
+ myUseStretch->setEnabled(enable);
+ myTVOverscan->setEnabled(enable);
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void VideoAudioDialog::handleOverscanChange()
+{
+ if (myTVOverscan->getValue() == 0)
+ {
+ myTVOverscan->setValueLabel("Off");
+ myTVOverscan->setValueUnit("");
+ }
+ else
+ myTVOverscan->setValueUnit("%");
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void VideoAudioDialog::handlePhosphorChange()
+{
+ myTVPhosLevel->setEnabled(myTVPhosphor->getState());
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void VideoAudioDialog::handleCommand(CommandSender* sender, int cmd,
+ int data, int id)
+{
+ switch (cmd)
+ {
+ case GuiObject::kOKCmd:
+ saveConfig();
+ close();
+ break;
+
+ case GuiObject::kCloseCmd:
+ // restore palette settings
+ instance().frameBuffer().tiaSurface().paletteHandler().setAdjustables(myPaletteAdj);
+ instance().frameBuffer().tiaSurface().paletteHandler().setPalette(myPalette);
+ Dialog::handleCommand(sender, cmd, data, 0);
+ break;
+
+ case GuiObject::kDefaultsCmd:
+ setDefaults();
+ break;
+
+ case kPaletteChanged:
+ handlePaletteChange();
+ handlePaletteUpdate();
+ break;
+
+ case kPaletteUpdated:
+ handlePaletteUpdate();
+ break;
+
+ case kNtscShiftChanged:
+ {
+ std::ostringstream ss;
+
+ ss << std::setw(4) << std::fixed << std::setprecision(1)
+ << (0.1 * abs(myPhaseShiftNtsc->getValue())) << DEGREE;
+ myPhaseShiftNtsc->setValueLabel(ss.str());
+ handlePaletteUpdate();
+ break;
+ }
+ case kPalShiftChanged:
+ {
+ std::ostringstream ss;
+
+ ss << std::setw(4) << std::fixed << std::setprecision(1)
+ << (0.1 * abs(myPhaseShiftPal->getValue())) << DEGREE;
+ myPhaseShiftPal->setValueLabel(ss.str());
+ handlePaletteUpdate();
+ break;
+ }
+ case kVSizeChanged:
+ {
+ int adjust = myVSizeAdjust->getValue();
+
+ if (!adjust)
+ {
+ myVSizeAdjust->setValueLabel("Default");
+ myVSizeAdjust->setValueUnit("");
+ }
+ else
+ myVSizeAdjust->setValueUnit("%");
+ break;
+ }
+ case kFullScreenChanged:
+ handleFullScreenChange();
+ break;
+
+ case kOverscanChanged:
+ handleOverscanChange();
+ break;
+
+ case kTVModeChanged:
+ handleTVModeChange(NTSCFilter::Preset(myTVMode->getSelectedTag().toInt()));
+ break;
+
+ case kCloneCompositeCmd: loadTVAdjustables(NTSCFilter::Preset::COMPOSITE);
+ break;
+ case kCloneSvideoCmd: loadTVAdjustables(NTSCFilter::Preset::SVIDEO);
+ break;
+ case kCloneRGBCmd: loadTVAdjustables(NTSCFilter::Preset::RGB);
+ break;
+ case kCloneBadCmd: loadTVAdjustables(NTSCFilter::Preset::BAD);
+ break;
+ case kCloneCustomCmd: loadTVAdjustables(NTSCFilter::Preset::CUSTOM);
+ break;
+
+ case kScanlinesChanged:
+ if (myTVScanIntense->getValue() == 0)
+ {
+ myTVScanIntense->setValueLabel("Off");
+ myTVScanIntense->setValueUnit("");
+ }
+ else
+ myTVScanIntense->setValueUnit("%");
+ break;
+
+ case kPhosphorChanged:
+ handlePhosphorChange();
+ break;
+
+ case kPhosBlendChanged:
+ if (myTVPhosLevel->getValue() == 0)
+ {
+ myTVPhosLevel->setValueLabel("Off");
+ myTVPhosLevel->setValueUnit("");
+ }
+ else
+ myTVPhosLevel->setValueUnit("%");
+ break;
+
+ case kSoundEnableChanged:
+ updateEnabledState();
+ break;
+
+ case kModeChanged:
+ updatePreset();
+ updateEnabledState();
+ break;
+
+ case kHeadroomChanged:
+ {
+ std::ostringstream ss;
+ ss << std::fixed << std::setprecision(1) << (0.5 * myHeadroomSlider->getValue()) << " frames";
+ myHeadroomSlider->setValueLabel(ss.str());
+ break;
+ }
+ case kBufferSizeChanged:
+ {
+ std::ostringstream ss;
+ ss << std::fixed << std::setprecision(1) << (0.5 * myBufferSizeSlider->getValue()) << " frames";
+ myBufferSizeSlider->setValueLabel(ss.str());
+ break;
+ }
+
+ default:
+ Dialog::handleCommand(sender, cmd, data, 0);
+ break;
+ }
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void VideoAudioDialog::addPalette(int x, int y, int w, int h)
+{
+ if(instance().hasConsole())
+ {
+ constexpr int NUM_LUMA = 8;
+ constexpr int NUM_CHROMA = 16;
+ const GUI::Font& ifont = instance().frameBuffer().infoFont();
+ const int lwidth = ifont.getMaxCharWidth() * 1.5;
+ const float COLW = float(w - lwidth) / NUM_LUMA;
+ const float COLH = float(h) / NUM_CHROMA;
+ const int yofs = (COLH - ifont.getFontHeight() + 1) / 2;
+
+ for(int idx = 0; idx < NUM_CHROMA; ++idx)
+ {
+ myColorLbl[idx] = new StaticTextWidget(myTab, ifont, x, y + yofs + idx * COLH, " ");
+ for(int lum = 0; lum < NUM_LUMA; ++lum)
+ {
+ myColor[idx][lum] = new ColorWidget(myTab, _font, x + lwidth + lum * COLW, y + idx * COLH,
+ COLW + 1, COLH + 1, 0, false);
+ }
+ }
+ }
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void VideoAudioDialog::colorPalette()
+{
+ if(instance().hasConsole())
+ {
+ constexpr int NUM_LUMA = 8;
+ constexpr int NUM_CHROMA = 16;
+ const int order[2][NUM_CHROMA] =
+ {
+ {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
+ {0, 1, 2, 4, 6, 8, 10, 12, 13, 11, 9, 7, 5, 3, 14, 15}
+ };
+ const int type = instance().console().timing() == ConsoleTiming::pal ? 1 : 0;
+
+ for(int idx = 0; idx < NUM_CHROMA; ++idx)
+ {
+ ostringstream ss;
+ const int color = order[type][idx];
+
+ ss << Common::Base::HEX1 << std::uppercase << color;
+ myColorLbl[idx]->setLabel(ss.str());
+ for(int lum = 0; lum < NUM_LUMA; ++lum)
+ {
+ myColor[idx][lum]->setColor(color * NUM_CHROMA + lum * 2); // skip grayscale colors
+ }
+ }
+ }
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void VideoAudioDialog::updateEnabledState()
+{
+ bool active = mySoundEnableCheckbox->getState();
+ AudioSettings::Preset preset = static_cast(myModePopup->getSelectedTag().toInt());
+ bool userMode = preset == AudioSettings::Preset::custom;
+
+ myVolumeSlider->setEnabled(active);
+ myStereoSoundCheckbox->setEnabled(active);
+ myModePopup->setEnabled(active);
+ // enable only for Pitfall II cart
+ myDpcPitch->setEnabled(active && instance().hasConsole() && instance().console().cartridge().name() == "CartridgeDPC");
+
+ myFragsizePopup->setEnabled(active && userMode);
+ myFreqPopup->setEnabled(active && userMode);
+ myResamplingPopup->setEnabled(active && userMode);
+ myHeadroomSlider->setEnabled(active && userMode);
+ myBufferSizeSlider->setEnabled(active && userMode);
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void VideoAudioDialog::updatePreset()
+{
+ AudioSettings::Preset preset = static_cast(myModePopup->getSelectedTag().toInt());
+
+ // Make a copy that does not affect the actual settings...
+ AudioSettings audioSettings = instance().audioSettings();
+ audioSettings.setPersistent(false);
+ // ... and set the requested preset
+ audioSettings.setPreset(preset);
+
+ updateSettingsWithPreset(audioSettings);
+}
diff --git a/src/gui/VideoDialog.hxx b/src/gui/VideoAudioDialog.hxx
similarity index 66%
rename from src/gui/VideoDialog.hxx
rename to src/gui/VideoAudioDialog.hxx
index 429290082..f46740ae6 100644
--- a/src/gui/VideoDialog.hxx
+++ b/src/gui/VideoAudioDialog.hxx
@@ -15,77 +15,75 @@
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
-#ifndef VIDEO_DIALOG_HXX
-#define VIDEO_DIALOG_HXX
+#ifndef VIDEOAUDIO_DIALOG_HXX
+#define VIDEOAUDIO_DIALOG_HXX
class CommandSender;
class CheckboxWidget;
+class ColorWidget;
class DialogContainer;
class PopUpWidget;
+class RadioButtonGroup;
class SliderWidget;
class StaticTextWidget;
class TabWidget;
class OSystem;
#include "Dialog.hxx"
+#include "PaletteHandler.hxx"
#include "NTSCFilter.hxx"
#include "bspf.hxx"
-class VideoDialog : public Dialog
+class VideoAudioDialog : public Dialog
{
public:
- VideoDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font,
+ VideoAudioDialog(OSystem& osystem, DialogContainer& parent, const GUI::Font& font,
int max_w, int max_h);
- virtual ~VideoDialog() = default;
+ virtual ~VideoAudioDialog() = default;
private:
void loadConfig() override;
void saveConfig() override;
void setDefaults() override;
+ void addDisplayTab();
+ void addPaletteTab();
+ void addTVEffectsTab();
+ void addAudioTab();
void handleTVModeChange(NTSCFilter::Preset);
void loadTVAdjustables(NTSCFilter::Preset preset);
void handlePaletteChange();
+ void handlePaletteUpdate();
void handleFullScreenChange();
void handleOverscanChange();
void handlePhosphorChange();
void handleCommand(CommandSender* sender, int cmd, int data, int id) override;
+ void addPalette(int x, int y, int h, int w);
+ void colorPalette();
+ void updatePreset();
+ void updateEnabledState();
+ void updateSettingsWithPreset(AudioSettings&);
private:
TabWidget* myTab;
// General options
PopUpWidget* myRenderer{nullptr};
- SliderWidget* myTIAZoom{nullptr};
- PopUpWidget* myTIAPalette{nullptr};
- SliderWidget* myPhaseShiftNtsc{nullptr};
- SliderWidget* myPhaseShiftPal{nullptr};
CheckboxWidget* myTIAInterpolate{nullptr};
- SliderWidget* myVSizeAdjust{nullptr};
- SliderWidget* mySpeed{nullptr};
-
CheckboxWidget* myFullscreen{nullptr};
//PopUpWidget* myFullScreenMode;
CheckboxWidget* myUseStretch{nullptr};
SliderWidget* myTVOverscan{nullptr};
- CheckboxWidget* myUseVSync{nullptr};
- CheckboxWidget* myUIMessages{nullptr};
- CheckboxWidget* myCenter{nullptr};
- CheckboxWidget* myFastSCBios{nullptr};
- CheckboxWidget* myUseThreads{nullptr};
+ SliderWidget* myTIAZoom{nullptr};
+ SliderWidget* myVSizeAdjust{nullptr};
// TV effects adjustables (custom mode)
PopUpWidget* myTVMode{nullptr};
SliderWidget* myTVSharp{nullptr};
- SliderWidget* myTVHue{nullptr};
SliderWidget* myTVRes{nullptr};
SliderWidget* myTVArtifacts{nullptr};
SliderWidget* myTVFringe{nullptr};
SliderWidget* myTVBleed{nullptr};
- SliderWidget* myTVBright{nullptr};
- SliderWidget* myTVContrast{nullptr};
- SliderWidget* myTVSatur{nullptr};
- SliderWidget* myTVGamma{nullptr};
// TV phosphor effect
CheckboxWidget* myTVPhosphor{nullptr};
@@ -102,15 +100,44 @@ class VideoDialog : public Dialog
ButtonWidget* myCloneBad{nullptr};
ButtonWidget* myCloneCustom{nullptr};
+ // Palettes
+ PopUpWidget* myTIAPalette{nullptr};
+ SliderWidget* myPhaseShiftNtsc{nullptr};
+ SliderWidget* myPhaseShiftPal{nullptr};
+ SliderWidget* myTVHue{nullptr};
+ SliderWidget* myTVSatur{nullptr};
+ SliderWidget* myTVBright{nullptr};
+ SliderWidget* myTVContrast{nullptr};
+ SliderWidget* myTVGamma{nullptr};
+ std::array myColorLbl{nullptr};
+ ColorWidget* myColor[16][8]{{nullptr}};
+
+ // Audio
+ CheckboxWidget* mySoundEnableCheckbox{nullptr};
+ SliderWidget* myVolumeSlider{nullptr};
+ CheckboxWidget* myStereoSoundCheckbox{nullptr};
+ PopUpWidget* myModePopup{nullptr};
+ PopUpWidget* myFragsizePopup{nullptr};
+ PopUpWidget* myFreqPopup{nullptr};
+ PopUpWidget* myResamplingPopup{nullptr};
+ SliderWidget* myHeadroomSlider{nullptr};
+ SliderWidget* myBufferSizeSlider{nullptr};
+ SliderWidget* myDpcPitch{nullptr};
+
+ string myPalette;
+ PaletteHandler::Adjustable myPaletteAdj;
+
enum {
- kPaletteChanged = 'VDpl',
- kNtscShiftChanged = 'VDns',
- kPalShiftChanged = 'VDps',
- kSpeedupChanged = 'VDSp',
+ kZoomChanged = 'VDZo',
kVSizeChanged = 'VDVs',
kFullScreenChanged = 'VDFs',
kOverscanChanged = 'VDOv',
+ kPaletteChanged = 'VDpl',
+ kNtscShiftChanged = 'VDns',
+ kPalShiftChanged = 'VDps',
+ kPaletteUpdated = 'VDpu',
+
kTVModeChanged = 'VDtv',
kCloneCompositeCmd = 'CLcp',
kCloneSvideoCmd = 'CLsv',
@@ -119,16 +146,21 @@ class VideoDialog : public Dialog
kCloneCustomCmd = 'CLcu',
kPhosphorChanged = 'VDph',
kPhosBlendChanged = 'VDbl',
- kScanlinesChanged = 'VDsc'
+ kScanlinesChanged = 'VDsc',
+
+ kSoundEnableChanged = 'ADse',
+ kModeChanged = 'ADmc',
+ kHeadroomChanged = 'ADhc',
+ kBufferSizeChanged = 'ADbc'
};
private:
// Following constructors and assignment operators not supported
- VideoDialog() = delete;
- VideoDialog(const VideoDialog&) = delete;
- VideoDialog(VideoDialog&&) = delete;
- VideoDialog& operator=(const VideoDialog&) = delete;
- VideoDialog& operator=(VideoDialog&&) = delete;
+ VideoAudioDialog() = delete;
+ VideoAudioDialog(const VideoAudioDialog&) = delete;
+ VideoAudioDialog(VideoAudioDialog&&) = delete;
+ VideoAudioDialog& operator=(const VideoAudioDialog&) = delete;
+ VideoAudioDialog& operator=(VideoAudioDialog&&) = delete;
};
#endif
diff --git a/src/gui/VideoDialog.cxx b/src/gui/VideoDialog.cxx
deleted file mode 100644
index 30b7a6ccc..000000000
--- a/src/gui/VideoDialog.cxx
+++ /dev/null
@@ -1,772 +0,0 @@
-//============================================================================
-//
-// SSSS tt lll lll
-// SS SS tt ll ll
-// SS tttttt eeee ll ll aaaa
-// SSSS tt ee ee ll ll aa
-// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
-// SS SS tt ee ll ll aa aa
-// SSSS ttt eeeee llll llll aaaaa
-//
-// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony
-// and the Stella Team
-//
-// See the file "License.txt" for information on usage and redistribution of
-// this file, and for a DISCLAIMER OF ALL WARRANTIES.
-//============================================================================
-
-#include
-
-#include "bspf.hxx"
-#include "Control.hxx"
-#include "Dialog.hxx"
-#include "Menu.hxx"
-#include "OSystem.hxx"
-#include "EditTextWidget.hxx"
-#include "PopUpWidget.hxx"
-#include "Console.hxx"
-#include "TIA.hxx"
-#include "Settings.hxx"
-#include "Widget.hxx"
-#include "Font.hxx"
-#include "TabWidget.hxx"
-#include "NTSCFilter.hxx"
-#include "TIASurface.hxx"
-
-#include "VideoDialog.hxx"
-
-namespace {
- // Emulation speed is a positive float that multiplies the framerate. However, the UI controls
- // adjust speed in terms of a speedup factor (1/10, 1/9 .. 1/2, 1, 2, 3, .., 10). The following
- // mapping and formatting functions implement this conversion. The speedup factor is represented
- // by an integer value between -900 and 900 (0 means no speedup).
-
- constexpr int MAX_SPEED = 900;
- constexpr int MIN_SPEED = -900;
- constexpr int SPEED_STEP = 10;
-
- int mapSpeed(float speed)
- {
- speed = std::abs(speed);
-
- return BSPF::clamp(
- static_cast(round(100 * (speed >= 1 ? speed - 1 : -1 / speed + 1))),
- MIN_SPEED, MAX_SPEED
- );
- }
-
- float unmapSpeed(int speed)
- {
- float f_speed = static_cast(speed) / 100;
-
- return speed < 0 ? -1 / (f_speed - 1) : 1 + f_speed;
- }
-
- string formatSpeed(int speed) {
- stringstream ss;
-
- ss
- << std::setw(3) << std::fixed << std::setprecision(0)
- << (unmapSpeed(speed) * 100);
-
- return ss.str();
- }
-}
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-VideoDialog::VideoDialog(OSystem& osystem, DialogContainer& parent,
- const GUI::Font& font, int max_w, int max_h)
- : Dialog(osystem, parent, font, "Video settings")
-{
- const int lineHeight = font.getLineHeight(),
- fontHeight = font.getFontHeight(),
- fontWidth = font.getMaxCharWidth(),
- buttonHeight = font.getLineHeight() * 1.25;
- const int VGAP = fontHeight / 4;
- const int VBORDER = fontHeight / 2;
- const int HBORDER = fontWidth * 1.25;
- const int INDENT = fontWidth * 2;
-
- int xpos, ypos, tabID;
- int lwidth = font.getStringWidth("V-Size adjust "),
- pwidth = font.getStringWidth("XXXXxXXXX");
-
- WidgetArray wid;
- VariantList items;
-
- // Set real dimensions
- setSize(57 * fontWidth + HBORDER * 2 + PopUpWidget::dropDownWidth(font) * 2,
- _th + VGAP * 3 + lineHeight + 11 * (lineHeight + VGAP) + buttonHeight + VBORDER * 3,
- max_w, max_h);
-
- // The tab widget
- xpos = 2; ypos = VGAP;
- myTab = new TabWidget(this, font, xpos, ypos + _th,
- _w - 2*xpos,
- _h - _th - VGAP - buttonHeight - VBORDER * 2);
- addTabWidget(myTab);
-
- xpos = HBORDER; ypos = VBORDER;
- //////////////////////////////////////////////////////////
- // 1) General options
- tabID = myTab->addTab(" General ");
-
- // Video renderer
- myRenderer = new PopUpWidget(myTab, font, xpos, ypos, pwidth, lineHeight,
- instance().frameBuffer().supportedRenderers(),
- "Renderer ", lwidth);
- wid.push_back(myRenderer);
- ypos += lineHeight + VGAP;
-
- // TIA Palette
- items.clear();
- VarList::push_back(items, "Standard", "standard");
- VarList::push_back(items, "z26", "z26");
- if (instance().checkUserPalette())
- VarList::push_back(items, "User", "user");
- VarList::push_back(items, "Custom", "custom");
- myTIAPalette = new PopUpWidget(myTab, font, xpos, ypos, pwidth,
- lineHeight, items, "Palette ", lwidth, kPaletteChanged);
- wid.push_back(myTIAPalette);
- ypos += lineHeight + VGAP;
-
- int swidth = myTIAPalette->getWidth() - lwidth;
- int plWidth = font.getStringWidth("NTSC phase ");
- int pswidth = swidth - INDENT + lwidth - plWidth;
-
- myPhaseShiftNtsc =
- new SliderWidget(myTab, font, xpos + INDENT, ypos-1, pswidth, lineHeight,
- "NTSC phase", plWidth, kNtscShiftChanged, fontWidth * 5);
- myPhaseShiftNtsc->setMinValue(262 - 45); myPhaseShiftNtsc->setMaxValue(262 + 45);
- myPhaseShiftNtsc->setTickmarkIntervals(4);
- wid.push_back(myPhaseShiftNtsc);
- ypos += lineHeight + VGAP;
-
- myPhaseShiftPal =
- new SliderWidget(myTab, font, xpos + INDENT, ypos-1, pswidth, lineHeight,
- "PAL phase", plWidth, kPalShiftChanged, fontWidth * 5);
- myPhaseShiftPal->setMinValue(313 - 45); myPhaseShiftPal->setMaxValue(313 + 45);
- myPhaseShiftPal->setTickmarkIntervals(4);
- wid.push_back(myPhaseShiftPal);
- ypos += lineHeight + VGAP * 4;
-
- // TIA interpolation
- myTIAInterpolate = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Interpolation ");
- wid.push_back(myTIAInterpolate); ypos += lineHeight + VGAP;
-
-
- // TIA zoom levels (will be dynamically filled later)
- myTIAZoom = new SliderWidget(myTab, font, xpos, ypos - 1, swidth, lineHeight,
- "Zoom ", lwidth, 0, fontWidth * 4, "%");
- myTIAZoom->setMinValue(200); myTIAZoom->setStepValue(FrameBuffer::ZOOM_STEPS * 100);
- wid.push_back(myTIAZoom);
- ypos += lineHeight + VGAP;
-
- // Aspect ratio (NTSC mode)
- myVSizeAdjust =
- new SliderWidget(myTab, font, xpos, ypos-1, swidth, lineHeight,
- "V-Size adjust", lwidth, kVSizeChanged, fontWidth * 7, "%", 0, true);
- myVSizeAdjust->setMinValue(-5); myVSizeAdjust->setMaxValue(5);
- myVSizeAdjust->setTickmarkIntervals(2);
- wid.push_back(myVSizeAdjust);
- ypos += lineHeight + VGAP;
-
- // Speed
- mySpeed =
- new SliderWidget(myTab, font, xpos, ypos-1, swidth, lineHeight,
- "Emul. speed ", lwidth, kSpeedupChanged, fontWidth * 5, "%");
- mySpeed->setMinValue(MIN_SPEED); mySpeed->setMaxValue(MAX_SPEED);
- mySpeed->setStepValue(SPEED_STEP);
- mySpeed->setTickmarkIntervals(2);
- wid.push_back(mySpeed);
- ypos += lineHeight + VGAP;
-
- // Use sync to vblank
- myUseVSync = new CheckboxWidget(myTab, font, xpos, ypos + 1, "VSync");
- wid.push_back(myUseVSync);
-
- // Move over to the next column
- xpos = myVSizeAdjust->getRight() + fontWidth * 3;
- ypos = VBORDER;
-
- // Fullscreen
- myFullscreen = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Fullscreen", kFullScreenChanged);
- wid.push_back(myFullscreen);
- ypos += lineHeight + VGAP;
-
- /*pwidth = font.getStringWidth("0: 3840x2860@120Hz");
- myFullScreenMode = new PopUpWidget(myTab, font, xpos + INDENT + 2, ypos, pwidth, lineHeight,
- instance().frameBuffer().supportedScreenModes(), "Mode ");
- wid.push_back(myFullScreenMode);
- ypos += lineHeight + VGAP;*/
-
- // FS stretch
- myUseStretch = new CheckboxWidget(myTab, font, xpos + INDENT, ypos + 1, "Stretch");
- wid.push_back(myUseStretch);
- ypos += lineHeight + VGAP;
-
- // FS overscan
- myTVOverscan = new SliderWidget(myTab, font, xpos + INDENT, ypos - 1, swidth, lineHeight,
- "Overscan", font.getStringWidth("Overscan "), kOverscanChanged, fontWidth * 3, "%");
- myTVOverscan->setMinValue(0); myTVOverscan->setMaxValue(10);
- myTVOverscan->setTickmarkIntervals(2);
- wid.push_back(myTVOverscan);
- ypos += (lineHeight + VGAP) * 2;
-
- // Skip progress load bars for SuperCharger ROMs
- // Doesn't really belong here, but I couldn't find a better place for it
- myFastSCBios = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Fast SuperCharger load");
- wid.push_back(myFastSCBios);
- ypos += lineHeight + VGAP;
-
- // Show UI messages onscreen
- myUIMessages = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Show UI messages");
- wid.push_back(myUIMessages);
- ypos += lineHeight + VGAP;
-
- // Center window (in windowed mode)
- myCenter = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Center window");
- wid.push_back(myCenter);
- ypos += (lineHeight + VGAP) * 2;
-
- // Use multi-threading
- myUseThreads = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Multi-threading");
- wid.push_back(myUseThreads);
-
- // Add items for tab 0
- addToFocusList(wid, myTab, tabID);
-
- //////////////////////////////////////////////////////////
- // 2) TV effects options
- wid.clear();
- tabID = myTab->addTab(" TV Effects ");
- xpos = HBORDER;
- ypos = VBORDER;
- swidth = fontWidth * 8 - fontWidth / 2;
-
- // TV Mode
- items.clear();
- VarList::push_back(items, "Disabled", static_cast(NTSCFilter::Preset::OFF));
- VarList::push_back(items, "RGB", static_cast(NTSCFilter::Preset::RGB));
- VarList::push_back(items, "S-Video", static_cast(NTSCFilter::Preset::SVIDEO));
- VarList::push_back(items, "Composite", static_cast(NTSCFilter::Preset::COMPOSITE));
- VarList::push_back(items, "Bad adjust", static_cast(NTSCFilter::Preset::BAD));
- VarList::push_back(items, "Custom", static_cast(NTSCFilter::Preset::CUSTOM));
- lwidth = font.getStringWidth("TV Mode ");
- pwidth = font.getStringWidth("Bad adjust");
- myTVMode =
- new PopUpWidget(myTab, font, xpos, ypos, pwidth, lineHeight,
- items, "TV mode ", lwidth, kTVModeChanged);
- wid.push_back(myTVMode);
- ypos += lineHeight + VGAP;
-
- // Custom adjustables (using macro voodoo)
- xpos += INDENT - 2; ypos += 0;
- lwidth = font.getStringWidth("Saturation ");
-
-#define CREATE_CUSTOM_SLIDERS(obj, desc, cmd) \
- myTV ## obj = \
- new SliderWidget(myTab, font, xpos, ypos-1, swidth, lineHeight, \
- desc, lwidth, cmd, fontWidth*4, "%"); \
- myTV ## obj->setMinValue(0); myTV ## obj->setMaxValue(100); \
- myTV ## obj->setTickmarkIntervals(2); \
- wid.push_back(myTV ## obj); \
- ypos += lineHeight + VGAP;
-
- CREATE_CUSTOM_SLIDERS(Contrast, "Contrast ", 0)
- CREATE_CUSTOM_SLIDERS(Bright, "Brightness ", 0)
- CREATE_CUSTOM_SLIDERS(Hue, "Hue ", 0)
- CREATE_CUSTOM_SLIDERS(Satur, "Saturation ", 0)
- CREATE_CUSTOM_SLIDERS(Gamma, "Gamma ", 0)
- CREATE_CUSTOM_SLIDERS(Sharp, "Sharpness ", 0)
- CREATE_CUSTOM_SLIDERS(Res, "Resolution ", 0)
- CREATE_CUSTOM_SLIDERS(Artifacts, "Artifacts ", 0)
- CREATE_CUSTOM_SLIDERS(Fringe, "Fringing ", 0)
- CREATE_CUSTOM_SLIDERS(Bleed, "Bleeding ", 0)
-
- xpos += myTVContrast->getWidth() + fontWidth * 6;
- ypos = VBORDER;
-
- lwidth = font.getStringWidth("Intensity ");
-
- // TV Phosphor effect
- myTVPhosphor = new CheckboxWidget(myTab, font, xpos, ypos + 1, "Phosphor for all ROMs", kPhosphorChanged);
- wid.push_back(myTVPhosphor);
- ypos += lineHeight + VGAP / 2;
-
- // TV Phosphor blend level
- xpos += INDENT;
- swidth = font.getMaxCharWidth() * 10;
- CREATE_CUSTOM_SLIDERS(PhosLevel, "Blend ", kPhosBlendChanged)
- ypos += VGAP * 2;
-
- // Scanline intensity and interpolation
- xpos -= INDENT;
- myTVScanLabel = new StaticTextWidget(myTab, font, xpos, ypos, "Scanlines:");
- ypos += lineHeight + VGAP / 2;
-
- xpos += INDENT;
- CREATE_CUSTOM_SLIDERS(ScanIntense, "Intensity ", kScanlinesChanged)
- ypos += VGAP * 3;
-
- // Adjustable presets
- xpos -= INDENT;
- int cloneWidth = font.getStringWidth("Clone Bad Adjust") + 20;
-#define CREATE_CLONE_BUTTON(obj, desc) \
- myClone ## obj = \
- new ButtonWidget(myTab, font, xpos, ypos, cloneWidth, buttonHeight,\
- desc, kClone ## obj ##Cmd); \
- wid.push_back(myClone ## obj); \
- ypos += buttonHeight + VGAP;
-
- ypos += VGAP;
- CREATE_CLONE_BUTTON(RGB, "Clone RGB")
- CREATE_CLONE_BUTTON(Svideo, "Clone S-Video")
- CREATE_CLONE_BUTTON(Composite, "Clone Composite")
- CREATE_CLONE_BUTTON(Bad, "Clone Bad adjust")
- CREATE_CLONE_BUTTON(Custom, "Revert")
-
- // Add items for tab 2
- addToFocusList(wid, myTab, tabID);
-
- // Activate the first tab
- myTab->setActiveTab(0);
-
- // Add Defaults, OK and Cancel buttons
- wid.clear();
- addDefaultsOKCancelBGroup(wid, font);
- addBGroupToFocusList(wid);
-
- // Disable certain functions when we know they aren't present
-#ifndef WINDOWED_SUPPORT
- myFullscreen->clearFlags(Widget::FLAG_ENABLED);
- myCenter->clearFlags(Widget::FLAG_ENABLED);
-#endif
-}
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void VideoDialog::loadConfig()
-{
- // Renderer settings
- myRenderer->setSelected(instance().settings().getString("video"), "default");
-
- // TIA zoom levels
- // These are dynamically loaded, since they depend on the size of
- // the desktop and which renderer we're using
- float minZoom = instance().frameBuffer().supportedTIAMinZoom(); // or 2 if we allow lower values
- float maxZoom = instance().frameBuffer().supportedTIAMaxZoom();
-
- myTIAZoom->setMinValue(minZoom * 100);
- myTIAZoom->setMaxValue(maxZoom * 100);
- myTIAZoom->setTickmarkIntervals((maxZoom - minZoom) * 2); // every ~50%
- myTIAZoom->setValue(instance().settings().getFloat("tia.zoom") * 100);
-
- // TIA Palette
- myTIAPalette->setSelected(
- instance().settings().getString("palette"), "standard");
-
- // Custom Palette
- myPhaseShiftNtsc->setValue(instance().settings().getFloat("phase_ntsc") * 10);
- myPhaseShiftPal->setValue(instance().settings().getFloat("phase_pal") * 10);
- handlePaletteChange();
-
- // TIA interpolation
- myTIAInterpolate->setState(instance().settings().getBool("tia.inter"));
-
- // Aspect ratio setting (NTSC and PAL)
- myVSizeAdjust->setValue(instance().settings().getInt("tia.vsizeadjust"));
-
- // Emulation speed
- int speed = mapSpeed(instance().settings().getFloat("speed"));
- mySpeed->setValue(speed);
- mySpeed->setValueLabel(formatSpeed(speed));
-
- // Fullscreen
- myFullscreen->setState(instance().settings().getBool("fullscreen"));
- /*string mode = instance().settings().getString("fullscreenmode");
- myFullScreenMode->setSelected(mode);*/
- // Fullscreen stretch setting
- myUseStretch->setState(instance().settings().getBool("tia.fs_stretch"));
- // Fullscreen overscan setting
- myTVOverscan->setValue(instance().settings().getInt("tia.fs_overscan"));
- handleFullScreenChange();
-
- // Use sync to vertical blank
- myUseVSync->setState(instance().settings().getBool("vsync"));
-
- // Show UI messages
- myUIMessages->setState(instance().settings().getBool("uimessages"));
-
- // Center window
- myCenter->setState(instance().settings().getBool("center"));
-
- // Fast loading of Supercharger BIOS
- myFastSCBios->setState(instance().settings().getBool("fastscbios"));
-
- // Multi-threaded rendering
- myUseThreads->setState(instance().settings().getBool("threads"));
-
- // TV Mode
- myTVMode->setSelected(
- instance().settings().getString("tv.filter"), "0");
- int preset = instance().settings().getInt("tv.filter");
- handleTVModeChange(NTSCFilter::Preset(preset));
-
- // TV Custom adjustables
- loadTVAdjustables(NTSCFilter::Preset::CUSTOM);
-
- // TV phosphor mode
- myTVPhosphor->setState(instance().settings().getString("tv.phosphor") == "always");
-
- // TV phosphor blend
- myTVPhosLevel->setValue(instance().settings().getInt("tv.phosblend"));
- handlePhosphorChange();
-
- // TV scanline intensity and interpolation
- myTVScanIntense->setValue(instance().settings().getInt("tv.scanlines"));
-
- myTab->loadConfig();
-}
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void VideoDialog::saveConfig()
-{
- // Renderer setting
- instance().settings().setValue("video",
- myRenderer->getSelectedTag().toString());
-
- // TIA zoom levels
- instance().settings().setValue("tia.zoom", myTIAZoom->getValue() / 100.0);
-
- // TIA Palette
- instance().settings().setValue("palette",
- myTIAPalette->getSelectedTag().toString());
-
- // Custom Palette
- instance().settings().setValue("phase_ntsc", myPhaseShiftNtsc->getValue() / 10.0);
- instance().settings().setValue("phase_pal", myPhaseShiftPal->getValue() / 10.0);
-
- // TIA interpolation
- instance().settings().setValue("tia.inter", myTIAInterpolate->getState());
-
- // Aspect ratio setting (NTSC and PAL)
- int oldAdjust = instance().settings().getInt("tia.vsizeadjust");
- int newAdjust = myVSizeAdjust->getValue();
- bool vsizeChanged = oldAdjust != newAdjust;
-
- instance().settings().setValue("tia.vsizeadjust", newAdjust);
-
- // Speed
- int speedup = mySpeed->getValue();
- instance().settings().setValue("speed", unmapSpeed(speedup));
- if (instance().hasConsole()) instance().console().initializeAudio();
-
- // Fullscreen
- instance().settings().setValue("fullscreen", myFullscreen->getState());
- // Fullscreen stretch setting
- instance().settings().setValue("tia.fs_stretch", myUseStretch->getState());
- // Fullscreen overscan
- instance().settings().setValue("tia.fs_overscan", myTVOverscan->getValueLabel());
-
- // Use sync to vertical blank
- instance().settings().setValue("vsync", myUseVSync->getState());
-
- // Show UI messages
- instance().settings().setValue("uimessages", myUIMessages->getState());
-
- // Center window
- instance().settings().setValue("center", myCenter->getState());
-
- // Fast loading of Supercharger BIOS
- instance().settings().setValue("fastscbios", myFastSCBios->getState());
-
- // Multi-threaded rendering
- instance().settings().setValue("threads", myUseThreads->getState());
- if (instance().hasConsole())
- instance().frameBuffer().tiaSurface().ntsc().enableThreading(myUseThreads->getState());
-
- // TV Mode
- instance().settings().setValue("tv.filter",
- myTVMode->getSelectedTag().toString());
-
- // TV Custom adjustables
- NTSCFilter::Adjustable adj;
- adj.hue = myTVHue->getValue();
- adj.saturation = myTVSatur->getValue();
- adj.contrast = myTVContrast->getValue();
- adj.brightness = myTVBright->getValue();
- adj.sharpness = myTVSharp->getValue();
- adj.gamma = myTVGamma->getValue();
- adj.resolution = myTVRes->getValue();
- adj.artifacts = myTVArtifacts->getValue();
- adj.fringing = myTVFringe->getValue();
- adj.bleed = myTVBleed->getValue();
- instance().frameBuffer().tiaSurface().ntsc().setCustomAdjustables(adj);
-
- // TV phosphor mode
- instance().settings().setValue("tv.phosphor",
- myTVPhosphor->getState() ? "always" : "byrom");
- // TV phosphor blend
- instance().settings().setValue("tv.phosblend", myTVPhosLevel->getValueLabel() == "Off"
- ? "0" : myTVPhosLevel->getValueLabel());
-
- // TV scanline intensity
- instance().settings().setValue("tv.scanlines", myTVScanIntense->getValueLabel());
-
- if(instance().hasConsole())
- {
- instance().console().setTIAProperties();
-
- if(instance().settings().getString("palette") == "custom")
- {
- instance().console().generateCustomPalette(0);
- instance().console().generateCustomPalette(1);
- }
-
- if(vsizeChanged)
- {
- instance().console().tia().clearFrameBuffer();
- instance().console().initializeVideo();
- }
- }
-
- // Finally, issue a complete framebuffer re-initialization...
- instance().createFrameBuffer();
-
- // ... and apply potential setting changes to the TIA surface
- instance().frameBuffer().tiaSurface().updateSurfaceSettings();
-}
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void VideoDialog::setDefaults()
-{
- switch(myTab->getActiveTab())
- {
- case 0: // General
- {
- myRenderer->setSelectedIndex(0);
- myTIAZoom->setValue(300);
- myTIAPalette->setSelected("standard", "");
- myPhaseShiftNtsc->setValue(262);
- myPhaseShiftPal->setValue(313);
- myTIAInterpolate->setState(false);
- myVSizeAdjust->setValue(0);
- mySpeed->setValue(0);
-
- myFullscreen->setState(false);
- //myFullScreenMode->setSelectedIndex(0);
- myUseStretch->setState(false);
- myUseVSync->setState(true);
- myUIMessages->setState(true);
- myCenter->setState(false);
- myFastSCBios->setState(true);
- myUseThreads->setState(false);
-
- handlePaletteChange();
- break;
- }
-
- case 1: // TV effects
- {
- myTVMode->setSelected("0", "0");
-
- // TV phosphor mode
- myTVPhosphor->setState(false);
-
- // TV phosphor blend
- myTVPhosLevel->setValue(50);
-
- // TV scanline intensity and interpolation
- myTVScanIntense->setValue(25);
-
- // Make sure that mutually-exclusive items are not enabled at the same time
- handleTVModeChange(NTSCFilter::Preset::OFF);
- handlePhosphorChange();
- loadTVAdjustables(NTSCFilter::Preset::CUSTOM);
- break;
- }
- }
-}
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void VideoDialog::handleTVModeChange(NTSCFilter::Preset preset)
-{
- bool enable = preset == NTSCFilter::Preset::CUSTOM;
-
- myTVSharp->setEnabled(enable);
- myTVHue->setEnabled(enable);
- myTVRes->setEnabled(enable);
- myTVArtifacts->setEnabled(enable);
- myTVFringe->setEnabled(enable);
- myTVBleed->setEnabled(enable);
- myTVBright->setEnabled(enable);
- myTVContrast->setEnabled(enable);
- myTVSatur->setEnabled(enable);
- myTVGamma->setEnabled(enable);
- myCloneComposite->setEnabled(enable);
- myCloneSvideo->setEnabled(enable);
- myCloneRGB->setEnabled(enable);
- myCloneBad->setEnabled(enable);
- myCloneCustom->setEnabled(enable);
-}
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void VideoDialog::loadTVAdjustables(NTSCFilter::Preset preset)
-{
- NTSCFilter::Adjustable adj;
- instance().frameBuffer().tiaSurface().ntsc().getAdjustables(
- adj, NTSCFilter::Preset(preset));
- myTVSharp->setValue(adj.sharpness);
- myTVHue->setValue(adj.hue);
- myTVRes->setValue(adj.resolution);
- myTVArtifacts->setValue(adj.artifacts);
- myTVFringe->setValue(adj.fringing);
- myTVBleed->setValue(adj.bleed);
- myTVBright->setValue(adj.brightness);
- myTVContrast->setValue(adj.contrast);
- myTVSatur->setValue(adj.saturation);
- myTVGamma->setValue(adj.gamma);
-}
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void VideoDialog::handlePaletteChange()
-{
- bool enable = myTIAPalette->getSelectedTag().toString() == "custom";
-
- myPhaseShiftNtsc->setEnabled(enable);
- myPhaseShiftPal->setEnabled(enable);
-}
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void VideoDialog::handleFullScreenChange()
-{
- bool enable = myFullscreen->getState();
- myUseStretch->setEnabled(enable);
- myTVOverscan->setEnabled(enable);
-}
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void VideoDialog::handleOverscanChange()
-{
- if (myTVOverscan->getValue() == 0)
- {
- myTVOverscan->setValueLabel("Off");
- myTVOverscan->setValueUnit("");
- }
- else
- myTVOverscan->setValueUnit("%");
-}
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void VideoDialog::handlePhosphorChange()
-{
- myTVPhosLevel->setEnabled(myTVPhosphor->getState());
-}
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void VideoDialog::handleCommand(CommandSender* sender, int cmd,
- int data, int id)
-{
- switch (cmd)
- {
- case GuiObject::kOKCmd:
- saveConfig();
- close();
- break;
-
- case GuiObject::kDefaultsCmd:
- setDefaults();
- break;
-
- case kPaletteChanged:
- handlePaletteChange();
- break;
-
- case kNtscShiftChanged:
- {
- std::ostringstream ss;
-
- ss << std::setw(4) << std::fixed << std::setprecision(1)
- << (0.1 * abs(myPhaseShiftNtsc->getValue())) << DEGREE;
- myPhaseShiftNtsc->setValueLabel(ss.str());
- break;
- }
- case kPalShiftChanged:
- {
- std::ostringstream ss;
-
- ss << std::setw(4) << std::fixed << std::setprecision(1)
- << (0.1 * abs(myPhaseShiftPal->getValue())) << DEGREE;
- myPhaseShiftPal->setValueLabel(ss.str());
- break;
- }
- case kVSizeChanged:
- {
- int adjust = myVSizeAdjust->getValue();
-
- if (!adjust)
- {
- myVSizeAdjust->setValueLabel("Default");
- myVSizeAdjust->setValueUnit("");
- }
- else
- myVSizeAdjust->setValueUnit("%");
- break;
- }
-
- case kSpeedupChanged:
- mySpeed->setValueLabel(formatSpeed(mySpeed->getValue()));
- break;
-
- case kFullScreenChanged:
- handleFullScreenChange();
- break;
-
- case kOverscanChanged:
- handleOverscanChange();
- break;
-
- case kTVModeChanged:
- handleTVModeChange(NTSCFilter::Preset(myTVMode->getSelectedTag().toInt()));
- break;
-
- case kCloneCompositeCmd: loadTVAdjustables(NTSCFilter::Preset::COMPOSITE);
- break;
- case kCloneSvideoCmd: loadTVAdjustables(NTSCFilter::Preset::SVIDEO);
- break;
- case kCloneRGBCmd: loadTVAdjustables(NTSCFilter::Preset::RGB);
- break;
- case kCloneBadCmd: loadTVAdjustables(NTSCFilter::Preset::BAD);
- break;
- case kCloneCustomCmd: loadTVAdjustables(NTSCFilter::Preset::CUSTOM);
- break;
-
- case kScanlinesChanged:
- if (myTVScanIntense->getValue() == 0)
- {
- myTVScanIntense->setValueLabel("Off");
- myTVScanIntense->setValueUnit("");
- }
- else
- myTVScanIntense->setValueUnit("%");
- break;
-
- case kPhosphorChanged:
- handlePhosphorChange();
- break;
-
- case kPhosBlendChanged:
- if (myTVPhosLevel->getValue() == 0)
- {
- myTVPhosLevel->setValueLabel("Off");
- myTVPhosLevel->setValueUnit("");
- }
- else
- myTVPhosLevel->setValueUnit("%");
- break;
-
- default:
- Dialog::handleCommand(sender, cmd, data, 0);
- break;
- }
-}
diff --git a/src/gui/Widget.hxx b/src/gui/Widget.hxx
index eb31f7cd4..b20b8b159 100644
--- a/src/gui/Widget.hxx
+++ b/src/gui/Widget.hxx
@@ -23,14 +23,13 @@
class Dialog;
-namespace GUI {
- class Font;
-}
-
#include
#include "bspf.hxx"
#include "Event.hxx"
+#include "EventHandlerConstants.hxx"
+#include "FrameBufferConstants.hxx"
+#include "StellaKeys.hxx"
#include "GuiObject.hxx"
#include "Font.hxx"
diff --git a/src/gui/module.mk b/src/gui/module.mk
index f550e167d..1447b8195 100644
--- a/src/gui/module.mk
+++ b/src/gui/module.mk
@@ -2,7 +2,6 @@ MODULE := src/gui
MODULE_OBJS := \
src/gui/AboutDialog.o \
- src/gui/AudioDialog.o \
src/gui/BrowserDialog.o \
src/gui/CheckListWidget.o \
src/gui/ColorWidget.o \
@@ -15,6 +14,7 @@ MODULE_OBJS := \
src/gui/Dialog.o \
src/gui/EditableWidget.o \
src/gui/EditTextWidget.o \
+ src/gui/EmulationDialog.o \
src/gui/EventMappingWidget.o \
src/gui/FileListWidget.o \
src/gui/Font.o \
@@ -49,7 +49,7 @@ MODULE_OBJS := \
src/gui/TimeMachineDialog.o \
src/gui/TimeMachine.o \
src/gui/UIDialog.o \
- src/gui/VideoDialog.o \
+ src/gui/VideoAudioDialog.o \
src/gui/Widget.o
MODULE_DIRS += \
diff --git a/src/libpng/pngconf.h b/src/libpng/pngconf.h
index 927a769db..b5f468ae5 100644
--- a/src/libpng/pngconf.h
+++ b/src/libpng/pngconf.h
@@ -230,7 +230,7 @@
* the type.
*/
# ifndef PNG_EXPORT_TYPE
-# define PNG_EXPORT_TYPE(type) type PNG_IMPEXP
+# define PNG_EXPORT_TYPE(name) name PNG_IMPEXP
# endif
# define PNG_DLL_EXPORT __export
# else /* newer compiler */
@@ -450,7 +450,7 @@
# define PNG_FP_EXPORT(ordinal, type, name, args)\
PNG_EXPORT(ordinal, type, name, args);
# else /* No floating point APIs */
-# define PNG_FP_EXPORT(ordinal, type, name, args)
+# define PNG_FP_EXPORT(ordinal, name, name, args)
# endif
#endif
#ifndef PNG_FIXED_EXPORT /* A fixed point API. */
@@ -458,7 +458,7 @@
# define PNG_FIXED_EXPORT(ordinal, type, name, args)\
PNG_EXPORT(ordinal, type, name, args);
# else /* No fixed point APIs */
-# define PNG_FIXED_EXPORT(ordinal, type, name, args)
+# define PNG_FIXED_EXPORT(ordinal, name, name, args)
# endif
#endif
diff --git a/src/libretro/Makefile.common b/src/libretro/Makefile.common
index 1893fa57b..5fafdd855 100644
--- a/src/libretro/Makefile.common
+++ b/src/libretro/Makefile.common
@@ -23,6 +23,7 @@ SOURCES_CXX := \
$(CORE_DIR)/common/KeyMap.cxx \
$(CORE_DIR)/common/Logger.cxx \
$(CORE_DIR)/common/MouseControl.cxx \
+ $(CORE_DIR)/common/PaletteHandler.cxx \
$(CORE_DIR)/common/PhosphorHandler.cxx \
$(CORE_DIR)/common/PhysicalJoystick.cxx \
$(CORE_DIR)/common/PJoystickHandler.cxx \
diff --git a/src/libretro/SoundLIBRETRO.hxx b/src/libretro/SoundLIBRETRO.hxx
index 9709e4b3d..f99c8f341 100644
--- a/src/libretro/SoundLIBRETRO.hxx
+++ b/src/libretro/SoundLIBRETRO.hxx
@@ -27,7 +27,6 @@ class AudioSettings;
#include "bspf.hxx"
#include "Sound.hxx"
-#include "AudioQueue.hxx"
/**
This class implements the sound API for LIBRTRO.
@@ -96,10 +95,9 @@ class SoundLIBRETRO : public Sound
/**
Adjusts the volume of the sound device based on the given direction.
- @param direction Increase or decrease the current volume by a predefined
- amount based on the direction (1 = increase, -1 = decrease)
+ @param direction +1 indicates increase, -1 indicates decrease.
*/
- void adjustVolume(Int8 direction) override { }
+ void adjustVolume(int direction = +1) override { }
/**
This method is called to provide information about the sound device.
diff --git a/src/libretro/StellaLIBRETRO.cxx b/src/libretro/StellaLIBRETRO.cxx
index e3cb5073a..d670c45a9 100644
--- a/src/libretro/StellaLIBRETRO.cxx
+++ b/src/libretro/StellaLIBRETRO.cxx
@@ -21,6 +21,7 @@
#include "FrameBufferLIBRETRO.hxx"
#include "AtariNTSC.hxx"
+#include "PaletteHandler.hxx"
#include "AudioSettings.hxx"
#include "Serializer.hxx"
#include "StateManager.hxx"
@@ -28,7 +29,6 @@
#include "TIA.hxx"
#include "TIASurface.hxx"
-
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
StellaLIBRETRO::StellaLIBRETRO()
{
@@ -40,7 +40,7 @@ StellaLIBRETRO::StellaLIBRETRO()
video_aspect_ntsc = 0;
video_aspect_pal = 0;
- video_palette = "standard";
+ video_palette = PaletteHandler::SETTING_STANDARD;
video_filter = NTSCFilter::Preset::OFF;
video_ready = false;
@@ -374,19 +374,12 @@ void StellaLIBRETRO::setVideoFilter(NTSCFilter::Preset mode)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-void StellaLIBRETRO::setVideoPalette(uInt32 mode)
+void StellaLIBRETRO::setVideoPalette(const string& mode)
{
- switch (mode)
- {
- case 0: video_palette = "standard"; break;
- case 1: video_palette = "z26"; break;
- case 2: video_palette = "user"; break;
- }
-
if (system_ready)
{
myOSystem->settings().setValue("palette", video_palette);
- myOSystem->console().setPalette(video_palette);
+ myOSystem->frameBuffer().tiaSurface().paletteHandler().setPalette(video_palette);
}
}
diff --git a/src/libretro/StellaLIBRETRO.hxx b/src/libretro/StellaLIBRETRO.hxx
index f48a13708..3078e8eb1 100644
--- a/src/libretro/StellaLIBRETRO.hxx
+++ b/src/libretro/StellaLIBRETRO.hxx
@@ -104,7 +104,7 @@ class StellaLIBRETRO
void setVideoAspectPAL(uInt32 value) { video_aspect_pal = value; };
void setVideoFilter(NTSCFilter::Preset mode);
- void setVideoPalette(uInt32 mode);
+ void setVideoPalette(const string& mode);
void setVideoPhosphor(uInt32 mode, uInt32 blend);
void setAudioStereo(int mode);
diff --git a/src/libretro/libretro.cxx b/src/libretro/libretro.cxx
index 6babbf07f..8caae3765 100644
--- a/src/libretro/libretro.cxx
+++ b/src/libretro/libretro.cxx
@@ -15,6 +15,7 @@
#include "StellaLIBRETRO.hxx"
#include "Event.hxx"
#include "NTSCFilter.hxx"
+#include "PaletteHandler.hxx"
#include "Version.hxx"
@@ -30,11 +31,12 @@ static retro_audio_sample_batch_t audio_batch_cb;
// libretro UI settings
static int setting_ntsc, setting_pal;
-static int setting_stereo, setting_palette;
+static int setting_stereo;
static int setting_phosphor, setting_console, setting_phosphor_blend;
static int stella_paddle_joypad_sensitivity;
static int setting_crop_hoverscan, crop_left;
static NTSCFilter::Preset setting_filter;
+static const char* setting_palette;
static bool system_reset;
@@ -275,17 +277,11 @@ static void update_variables(bool init = false)
RETRO_GET("stella_palette")
{
- int value = 0;
-
- if(!strcmp(var.value, "standard")) value = 0;
- else if(!strcmp(var.value, "z26")) value = 1;
- else if(!strcmp(var.value, "user")) value = 2;
-
- if(setting_palette != value)
+ if(setting_palette != var.value)
{
- stella.setVideoPalette(value);
+ stella.setVideoPalette(var.value);
- setting_palette = value;
+ setting_palette = var.value;
}
}
@@ -494,7 +490,7 @@ void retro_set_environment(retro_environment_t cb)
static struct retro_variable variables[] = {
// Adding more variables and rearranging them is safe.
{ "stella_console", "Console display; auto|ntsc|pal|secam|ntsc50|pal60|secam60" },
- { "stella_palette", "Palette colors; standard|z26|user" },
+ { "stella_palette", "Palette colors; standard|z26|user|custom" },
{ "stella_filter", "TV effects; disabled|composite|s-video|rgb|badly adjusted" },
{ "stella_ntsc_aspect", "NTSC aspect %; par|100|101|102|103|104|105|106|107|108|109|110|111|112|113|114|115|116|117|118|119|120|121|122|123|124|125|50|75|76|77|78|79|80|81|82|83|84|85|86|87|88|89|90|91|92|93|94|95|96|97|98|99" },
{ "stella_pal_aspect", "PAL aspect %; par|100|101|102|103|104|105|106|107|108|109|110|111|112|113|114|115|116|117|118|119|120|121|122|123|124|125|50|75|76|77|78|79|80|81|82|83|84|85|86|87|88|89|90|91|92|93|94|95|96|97|98|99" },
diff --git a/src/macos/stella.xcodeproj/project.pbxproj b/src/macos/stella.xcodeproj/project.pbxproj
index 33eccde69..d59aac510 100644
--- a/src/macos/stella.xcodeproj/project.pbxproj
+++ b/src/macos/stella.xcodeproj/project.pbxproj
@@ -44,7 +44,6 @@
2D9173FA09BA90380026E9FF /* FrameBuffer.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2D733D71062895B2006265D9 /* FrameBuffer.hxx */; };
2D9173FB09BA90380026E9FF /* Settings.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2D733D77062895F1006265D9 /* Settings.hxx */; };
2D91740009BA90380026E9FF /* AboutDialog.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2DDBEAA4084578BF00812C11 /* AboutDialog.hxx */; };
- 2D91740109BA90380026E9FF /* AudioDialog.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2DDBEAA7084578BF00812C11 /* AudioDialog.hxx */; };
2D91740209BA90380026E9FF /* BrowserDialog.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2DDBEAA9084578BF00812C11 /* BrowserDialog.hxx */; };
2D91740309BA90380026E9FF /* Command.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2DDBEAAA084578BF00812C11 /* Command.hxx */; };
2D91740409BA90380026E9FF /* Dialog.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2DDBEAAC084578BF00812C11 /* Dialog.hxx */; };
@@ -61,7 +60,6 @@
2D91741209BA90380026E9FF /* ProgressDialog.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2DDBEAC9084578BF00812C11 /* ProgressDialog.hxx */; };
2D91741309BA90380026E9FF /* ScrollBarWidget.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2DDBEACB084578BF00812C11 /* ScrollBarWidget.hxx */; };
2D91741609BA90380026E9FF /* TabWidget.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2DDBEAD1084578BF00812C11 /* TabWidget.hxx */; };
- 2D91741709BA90380026E9FF /* VideoDialog.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2DDBEAD3084578BF00812C11 /* VideoDialog.hxx */; };
2D91741809BA90380026E9FF /* Widget.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2DDBEAD5084578BF00812C11 /* Widget.hxx */; };
2D91741909BA90380026E9FF /* CartUA.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2DDBEB7108457B7D00812C11 /* CartUA.hxx */; };
2D91741A09BA90380026E9FF /* FSNode.hxx in Headers */ = {isa = PBXBuildFile; fileRef = 2DDBEB7308457B7D00812C11 /* FSNode.hxx */; };
@@ -142,7 +140,6 @@
2D9174A309BA90380026E9FF /* Settings.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2D944848062904E800DD9879 /* Settings.cxx */; };
2D9174A809BA90380026E9FF /* FSNodePOSIX.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEA0C0845708800812C11 /* FSNodePOSIX.cxx */; };
2D9174AA09BA90380026E9FF /* AboutDialog.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEAA3084578BF00812C11 /* AboutDialog.cxx */; };
- 2D9174AB09BA90380026E9FF /* AudioDialog.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEAA6084578BF00812C11 /* AudioDialog.cxx */; };
2D9174AC09BA90380026E9FF /* BrowserDialog.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEAA8084578BF00812C11 /* BrowserDialog.cxx */; };
2D9174AD09BA90380026E9FF /* Dialog.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEAAB084578BF00812C11 /* Dialog.cxx */; };
2D9174AE09BA90380026E9FF /* DialogContainer.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEAAD084578BF00812C11 /* DialogContainer.cxx */; };
@@ -157,7 +154,6 @@
2D9174B909BA90380026E9FF /* ProgressDialog.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEAC8084578BF00812C11 /* ProgressDialog.cxx */; };
2D9174BA09BA90380026E9FF /* ScrollBarWidget.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEACA084578BF00812C11 /* ScrollBarWidget.cxx */; };
2D9174BB09BA90380026E9FF /* TabWidget.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEAD0084578BF00812C11 /* TabWidget.cxx */; };
- 2D9174BC09BA90380026E9FF /* VideoDialog.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEAD2084578BF00812C11 /* VideoDialog.cxx */; };
2D9174BD09BA90380026E9FF /* Widget.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEAD4084578BF00812C11 /* Widget.cxx */; };
2D9174BE09BA90380026E9FF /* CartUA.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEB7008457B7D00812C11 /* CartUA.cxx */; };
2D9174BF09BA90380026E9FF /* FSNode.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 2DDBEB7208457B7D00812C11 /* FSNode.cxx */; };
@@ -233,8 +229,6 @@
DC2410E32274BDA8007A4CBF /* MinUICommandDialog.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC2410E12274BDA7007A4CBF /* MinUICommandDialog.hxx */; };
DC2410E42274BDA8007A4CBF /* MinUICommandDialog.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC2410E22274BDA8007A4CBF /* MinUICommandDialog.cxx */; };
DC2874071F8F2278004BF21A /* TrapArray.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC2874061F8F2278004BF21A /* TrapArray.hxx */; };
- DC2AADAE194F389C0026C7A4 /* CartDASH.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC2AADAA194F389C0026C7A4 /* CartDASH.cxx */; };
- DC2AADAF194F389C0026C7A4 /* CartDASH.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC2AADAB194F389C0026C7A4 /* CartDASH.hxx */; };
DC2AADB0194F389C0026C7A4 /* TIASurface.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC2AADAC194F389C0026C7A4 /* TIASurface.cxx */; };
DC2AADB1194F389C0026C7A4 /* TIASurface.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC2AADAD194F389C0026C7A4 /* TIASurface.hxx */; };
DC2AADB4194F390F0026C7A4 /* CartRamWidget.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC2AADB2194F390F0026C7A4 /* CartRamWidget.cxx */; };
@@ -250,6 +244,18 @@
DC368F5918A2FB710084199C /* SoundSDL2.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC368F5318A2FB710084199C /* SoundSDL2.hxx */; };
DC36D2C814CAFAB0007DC821 /* CartFA2.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC36D2C614CAFAB0007DC821 /* CartFA2.cxx */; };
DC36D2C914CAFAB0007DC821 /* CartFA2.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC36D2C714CAFAB0007DC821 /* CartFA2.hxx */; };
+ DC3C9BC52469C8F700CF2D47 /* PaletteHandler.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC3C9BC32469C8F700CF2D47 /* PaletteHandler.cxx */; };
+ DC3C9BC62469C8F700CF2D47 /* PaletteHandler.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC3C9BC42469C8F700CF2D47 /* PaletteHandler.hxx */; };
+ DC3C9BCB2469C93D00CF2D47 /* VideoAudioDialog.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC3C9BC72469C93D00CF2D47 /* VideoAudioDialog.cxx */; };
+ DC3C9BCC2469C93D00CF2D47 /* EmulationDialog.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC3C9BC82469C93D00CF2D47 /* EmulationDialog.cxx */; };
+ DC3C9BCD2469C93D00CF2D47 /* VideoAudioDialog.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC3C9BC92469C93D00CF2D47 /* VideoAudioDialog.hxx */; };
+ DC3C9BCE2469C93D00CF2D47 /* EmulationDialog.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC3C9BCA2469C93D00CF2D47 /* EmulationDialog.hxx */; };
+ DC3C9BD32469C9A200CF2D47 /* CartEnhanced.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC3C9BCF2469C9A200CF2D47 /* CartEnhanced.cxx */; };
+ DC3C9BD42469C9A200CF2D47 /* Cart3EX.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC3C9BD02469C9A200CF2D47 /* Cart3EX.hxx */; };
+ DC3C9BD52469C9A200CF2D47 /* CartEnhanced.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC3C9BD12469C9A200CF2D47 /* CartEnhanced.hxx */; };
+ DC3C9BD62469C9A200CF2D47 /* Cart3EX.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC3C9BD22469C9A200CF2D47 /* Cart3EX.cxx */; };
+ DC3C9BD92469C9C700CF2D47 /* CartEnhancedWidget.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC3C9BD72469C9C700CF2D47 /* CartEnhancedWidget.cxx */; };
+ DC3C9BDA2469C9C700CF2D47 /* CartEnhancedWidget.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC3C9BD82469C9C700CF2D47 /* CartEnhancedWidget.hxx */; };
DC3DAFAC1F2E233B00A64410 /* PointingDevice.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC3DAFAB1F2E233B00A64410 /* PointingDevice.hxx */; };
DC3EE8561E2C0E6D00905161 /* adler32.c in Sources */ = {isa = PBXBuildFile; fileRef = DC3EE83C1E2C0E6D00905161 /* adler32.c */; settings = {COMPILER_FLAGS = "-w"; }; };
DC3EE8571E2C0E6D00905161 /* compress.c in Sources */ = {isa = PBXBuildFile; fileRef = DC3EE83D1E2C0E6D00905161 /* compress.c */; settings = {COMPILER_FLAGS = "-w"; }; };
@@ -393,8 +399,6 @@
DC73BD891915E5E3003FAFAD /* FBSurface.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC73BD871915E5E3003FAFAD /* FBSurface.cxx */; };
DC73BD8A1915E5E3003FAFAD /* FBSurface.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC73BD881915E5E3003FAFAD /* FBSurface.hxx */; };
DC74D6A2138D4D7E00F05C5C /* StringParser.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC74D6A0138D4D7E00F05C5C /* StringParser.hxx */; };
- DC74E5C6198AF12700F37E36 /* CartDASHWidget.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC74E5C4198AF12700F37E36 /* CartDASHWidget.cxx */; };
- DC74E5C7198AF12700F37E36 /* CartDASHWidget.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC74E5C5198AF12700F37E36 /* CartDASHWidget.hxx */; };
DC79F81217A88D9E00288B91 /* Base.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DC79F81017A88D9E00288B91 /* Base.cxx */; };
DC79F81317A88D9E00288B91 /* Base.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC79F81117A88D9E00288B91 /* Base.hxx */; };
DC7A24D5173B1CF600B20FE9 /* Variant.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DC7A24D4173B1CF600B20FE9 /* Variant.hxx */; };
@@ -494,10 +498,6 @@
DCAAE5F11715887B0080BB82 /* CartFAWidget.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DCAAE5D01715887B0080BB82 /* CartFAWidget.hxx */; };
DCAAE5F21715887B0080BB82 /* CartUAWidget.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DCAAE5D11715887B0080BB82 /* CartUAWidget.cxx */; };
DCAAE5F31715887B0080BB82 /* CartUAWidget.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DCAAE5D21715887B0080BB82 /* CartUAWidget.hxx */; };
- DCACBAD01C54296300703A9B /* CartCVPlusWidget.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DCACBACE1C54296300703A9B /* CartCVPlusWidget.cxx */; };
- DCACBAD11C54296300703A9B /* CartCVPlusWidget.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DCACBACF1C54296300703A9B /* CartCVPlusWidget.hxx */; };
- DCACBAD41C54298300703A9B /* CartCVPlus.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DCACBAD21C54298300703A9B /* CartCVPlus.cxx */; };
- DCACBAD51C54298300703A9B /* CartCVPlus.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DCACBAD31C54298300703A9B /* CartCVPlus.hxx */; };
DCAD60A81152F8BD00BC4184 /* CartDPCPlus.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DCAD60A61152F8BD00BC4184 /* CartDPCPlus.cxx */; };
DCAD60A91152F8BD00BC4184 /* CartDPCPlus.hxx in Headers */ = {isa = PBXBuildFile; fileRef = DCAD60A71152F8BD00BC4184 /* CartDPCPlus.hxx */; };
DCB20EC71A0C506C0048F595 /* main.cxx in Sources */ = {isa = PBXBuildFile; fileRef = DCB20EC61A0C506C0048F595 /* main.cxx */; };
@@ -828,8 +828,6 @@
2DDBEA0C0845708800812C11 /* FSNodePOSIX.cxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = FSNodePOSIX.cxx; sourceTree = ""; };
2DDBEAA3084578BF00812C11 /* AboutDialog.cxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AboutDialog.cxx; sourceTree = ""; };
2DDBEAA4084578BF00812C11 /* AboutDialog.hxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = AboutDialog.hxx; sourceTree = ""; };
- 2DDBEAA6084578BF00812C11 /* AudioDialog.cxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AudioDialog.cxx; sourceTree = ""; };
- 2DDBEAA7084578BF00812C11 /* AudioDialog.hxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = AudioDialog.hxx; sourceTree = ""; };
2DDBEAA8084578BF00812C11 /* BrowserDialog.cxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = BrowserDialog.cxx; sourceTree = ""; };
2DDBEAA9084578BF00812C11 /* BrowserDialog.hxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = BrowserDialog.hxx; sourceTree = ""; };
2DDBEAAA084578BF00812C11 /* Command.hxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = Command.hxx; sourceTree = ""; };
@@ -860,8 +858,6 @@
2DDBEACB084578BF00812C11 /* ScrollBarWidget.hxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = ScrollBarWidget.hxx; sourceTree = ""; };
2DDBEAD0084578BF00812C11 /* TabWidget.cxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = TabWidget.cxx; sourceTree = ""; };
2DDBEAD1084578BF00812C11 /* TabWidget.hxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = TabWidget.hxx; sourceTree = ""; };
- 2DDBEAD2084578BF00812C11 /* VideoDialog.cxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = VideoDialog.cxx; sourceTree = ""; };
- 2DDBEAD3084578BF00812C11 /* VideoDialog.hxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = VideoDialog.hxx; sourceTree = ""; };
2DDBEAD4084578BF00812C11 /* Widget.cxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Widget.cxx; sourceTree = ""; };
2DDBEAD5084578BF00812C11 /* Widget.hxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.h; path = Widget.hxx; sourceTree = ""; };
2DDBEB7008457B7D00812C11 /* CartUA.cxx */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CartUA.cxx; sourceTree = ""; };
@@ -972,8 +968,6 @@
DC2410E12274BDA7007A4CBF /* MinUICommandDialog.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = MinUICommandDialog.hxx; sourceTree = ""; };
DC2410E22274BDA8007A4CBF /* MinUICommandDialog.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MinUICommandDialog.cxx; sourceTree = ""; };
DC2874061F8F2278004BF21A /* TrapArray.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = TrapArray.hxx; sourceTree = ""; };
- DC2AADAA194F389C0026C7A4 /* CartDASH.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartDASH.cxx; sourceTree = ""; };
- DC2AADAB194F389C0026C7A4 /* CartDASH.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartDASH.hxx; sourceTree = ""; };
DC2AADAC194F389C0026C7A4 /* TIASurface.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TIASurface.cxx; sourceTree = ""; };
DC2AADAD194F389C0026C7A4 /* TIASurface.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = TIASurface.hxx; sourceTree = ""; };
DC2AADB2194F390F0026C7A4 /* CartRamWidget.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartRamWidget.cxx; sourceTree = ""; };
@@ -989,6 +983,18 @@
DC368F5318A2FB710084199C /* SoundSDL2.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SoundSDL2.hxx; sourceTree = ""; };
DC36D2C614CAFAB0007DC821 /* CartFA2.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartFA2.cxx; sourceTree = ""; };
DC36D2C714CAFAB0007DC821 /* CartFA2.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartFA2.hxx; sourceTree = ""; };
+ DC3C9BC32469C8F700CF2D47 /* PaletteHandler.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PaletteHandler.cxx; sourceTree = ""; };
+ DC3C9BC42469C8F700CF2D47 /* PaletteHandler.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = PaletteHandler.hxx; sourceTree = ""; };
+ DC3C9BC72469C93D00CF2D47 /* VideoAudioDialog.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VideoAudioDialog.cxx; sourceTree = ""; };
+ DC3C9BC82469C93D00CF2D47 /* EmulationDialog.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EmulationDialog.cxx; sourceTree = ""; };
+ DC3C9BC92469C93D00CF2D47 /* VideoAudioDialog.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = VideoAudioDialog.hxx; sourceTree = ""; };
+ DC3C9BCA2469C93D00CF2D47 /* EmulationDialog.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = EmulationDialog.hxx; sourceTree = ""; };
+ DC3C9BCF2469C9A200CF2D47 /* CartEnhanced.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartEnhanced.cxx; sourceTree = ""; };
+ DC3C9BD02469C9A200CF2D47 /* Cart3EX.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Cart3EX.hxx; sourceTree = ""; };
+ DC3C9BD12469C9A200CF2D47 /* CartEnhanced.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartEnhanced.hxx; sourceTree = ""; };
+ DC3C9BD22469C9A200CF2D47 /* Cart3EX.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Cart3EX.cxx; sourceTree = ""; };
+ DC3C9BD72469C9C700CF2D47 /* CartEnhancedWidget.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartEnhancedWidget.cxx; sourceTree = ""; };
+ DC3C9BD82469C9C700CF2D47 /* CartEnhancedWidget.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartEnhancedWidget.hxx; sourceTree = ""; };
DC3DAFAB1F2E233B00A64410 /* PointingDevice.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = PointingDevice.hxx; sourceTree = ""; };
DC3EE83C1E2C0E6D00905161 /* adler32.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = adler32.c; sourceTree = ""; };
DC3EE83D1E2C0E6D00905161 /* compress.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = compress.c; sourceTree = ""; };
@@ -1132,8 +1138,6 @@
DC73BD871915E5E3003FAFAD /* FBSurface.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FBSurface.cxx; sourceTree = ""; };
DC73BD881915E5E3003FAFAD /* FBSurface.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = FBSurface.hxx; sourceTree = ""; };
DC74D6A0138D4D7E00F05C5C /* StringParser.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = StringParser.hxx; sourceTree = ""; };
- DC74E5C4198AF12700F37E36 /* CartDASHWidget.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartDASHWidget.cxx; sourceTree = ""; };
- DC74E5C5198AF12700F37E36 /* CartDASHWidget.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartDASHWidget.hxx; sourceTree = ""; };
DC79F81017A88D9E00288B91 /* Base.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Base.cxx; sourceTree = ""; };
DC79F81117A88D9E00288B91 /* Base.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Base.hxx; sourceTree = ""; };
DC7A24D4173B1CF600B20FE9 /* Variant.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Variant.hxx; sourceTree = ""; };
@@ -1234,10 +1238,6 @@
DCAAE5D01715887B0080BB82 /* CartFAWidget.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartFAWidget.hxx; sourceTree = ""; };
DCAAE5D11715887B0080BB82 /* CartUAWidget.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartUAWidget.cxx; sourceTree = ""; };
DCAAE5D21715887B0080BB82 /* CartUAWidget.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartUAWidget.hxx; sourceTree = ""; };
- DCACBACE1C54296300703A9B /* CartCVPlusWidget.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartCVPlusWidget.cxx; sourceTree = ""; };
- DCACBACF1C54296300703A9B /* CartCVPlusWidget.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartCVPlusWidget.hxx; sourceTree = ""; };
- DCACBAD21C54298300703A9B /* CartCVPlus.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartCVPlus.cxx; sourceTree = ""; };
- DCACBAD31C54298300703A9B /* CartCVPlus.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartCVPlus.hxx; sourceTree = ""; };
DCAD60A61152F8BD00BC4184 /* CartDPCPlus.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CartDPCPlus.cxx; sourceTree = ""; };
DCAD60A71152F8BD00BC4184 /* CartDPCPlus.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CartDPCPlus.hxx; sourceTree = ""; };
DCB20EC61A0C506C0048F595 /* main.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cxx; sourceTree = ""; };
@@ -1589,12 +1589,8 @@
DC676A2C1729A0B000E4E73D /* CartCMWidget.hxx */,
DC676A2D1729A0B000E4E73D /* CartCTYWidget.cxx */,
DC676A2E1729A0B000E4E73D /* CartCTYWidget.hxx */,
- DCACBACE1C54296300703A9B /* CartCVPlusWidget.cxx */,
- DCACBACF1C54296300703A9B /* CartCVPlusWidget.hxx */,
DCAAE5BA1715887B0080BB82 /* CartCVWidget.cxx */,
DCAAE5BB1715887B0080BB82 /* CartCVWidget.hxx */,
- DC74E5C4198AF12700F37E36 /* CartDASHWidget.cxx */,
- DC74E5C5198AF12700F37E36 /* CartDASHWidget.hxx */,
DC5ACB5D1FBFCEB800A213FD /* CartDebugWidget.cxx */,
DCAAE5BC1715887B0080BB82 /* CartDebugWidget.hxx */,
DCAACB0A188D636F00A4D282 /* CartDFSCWidget.cxx */,
@@ -1615,6 +1611,8 @@
DCAAE5BE1715887B0080BB82 /* CartEFSCWidget.hxx */,
DCAAE5BF1715887B0080BB82 /* CartEFWidget.cxx */,
DCAAE5C01715887B0080BB82 /* CartEFWidget.hxx */,
+ DC3C9BD72469C9C700CF2D47 /* CartEnhancedWidget.cxx */,
+ DC3C9BD82469C9C700CF2D47 /* CartEnhancedWidget.hxx */,
DCAAE5C11715887B0080BB82 /* CartF0Widget.cxx */,
DCAAE5C21715887B0080BB82 /* CartF0Widget.hxx */,
DCAAE5C31715887B0080BB82 /* CartF4SCWidget.cxx */,
@@ -1744,6 +1742,8 @@
DCB87E571A104C1E00BF2A3B /* MediaFactory.hxx */,
DC56FCDC14CCCC4900A31CC3 /* MouseControl.cxx */,
DC56FCDD14CCCC4900A31CC3 /* MouseControl.hxx */,
+ DC3C9BC32469C8F700CF2D47 /* PaletteHandler.cxx */,
+ DC3C9BC42469C8F700CF2D47 /* PaletteHandler.hxx */,
DCA233AE23B583FE0032ABF3 /* PhosphorHandler.cxx */,
DCA233AF23B583FE0032ABF3 /* PhosphorHandler.hxx */,
DC6DC91A205DB879004A5FC3 /* PhysicalJoystick.cxx */,
@@ -1824,6 +1824,8 @@
2D9555DA0880E78000466554 /* Cart3E.hxx */,
DCBDDE9C1D6A5F2F009DF1E9 /* Cart3EPlus.cxx */,
DCBDDE9D1D6A5F2F009DF1E9 /* Cart3EPlus.hxx */,
+ DC3C9BD22469C9A200CF2D47 /* Cart3EX.cxx */,
+ DC3C9BD02469C9A200CF2D47 /* Cart3EX.hxx */,
2DE2DF160627AE07006BEC99 /* Cart3F.cxx */,
2DE2DF170627AE07006BEC99 /* Cart3F.hxx */,
DCD56D360B247D920092F9F8 /* Cart4A50.cxx */,
@@ -1850,10 +1852,6 @@
DC6727091556F4860023653B /* CartCTY.hxx */,
2DE2DF1C0627AE07006BEC99 /* CartCV.cxx */,
2DE2DF1D0627AE07006BEC99 /* CartCV.hxx */,
- DCACBAD21C54298300703A9B /* CartCVPlus.cxx */,
- DCACBAD31C54298300703A9B /* CartCVPlus.hxx */,
- DC2AADAA194F389C0026C7A4 /* CartDASH.cxx */,
- DC2AADAB194F389C0026C7A4 /* CartDASH.hxx */,
DCB2ECAC1F0AECA3009738A6 /* CartDetector.cxx */,
DCB2ECAD1F0AECA3009738A6 /* CartDetector.hxx */,
DCAACAF2188D631500A4D282 /* CartDF.cxx */,
@@ -1874,6 +1872,8 @@
DCF467BF0F939A1400B25D7A /* CartEF.hxx */,
DCF467C00F939A1400B25D7A /* CartEFSC.cxx */,
DCF467C10F939A1400B25D7A /* CartEFSC.hxx */,
+ DC3C9BCF2469C9A200CF2D47 /* CartEnhanced.cxx */,
+ DC3C9BD12469C9A200CF2D47 /* CartEnhanced.hxx */,
DCF7B0D910A762FC007A2870 /* CartF0.cxx */,
DCF7B0DA10A762FC007A2870 /* CartF0.hxx */,
2DE2DF240627AE07006BEC99 /* CartF4.cxx */,
@@ -2003,8 +2003,6 @@
children = (
2DDBEAA3084578BF00812C11 /* AboutDialog.cxx */,
2DDBEAA4084578BF00812C11 /* AboutDialog.hxx */,
- 2DDBEAA6084578BF00812C11 /* AudioDialog.cxx */,
- 2DDBEAA7084578BF00812C11 /* AudioDialog.hxx */,
2DDBEAA8084578BF00812C11 /* BrowserDialog.cxx */,
2DDBEAA9084578BF00812C11 /* BrowserDialog.hxx */,
2DEF21F808BC033500B246B4 /* CheckListWidget.cxx */,
@@ -2034,6 +2032,8 @@
2D403BA1086116D1001E31A1 /* EditableWidget.hxx */,
2D403BA4086116D1001E31A1 /* EditTextWidget.cxx */,
2D403BA5086116D1001E31A1 /* EditTextWidget.hxx */,
+ DC3C9BC82469C93D00CF2D47 /* EmulationDialog.cxx */,
+ DC3C9BCA2469C93D00CF2D47 /* EmulationDialog.hxx */,
2D05FF5E096E269100A518FE /* EventMappingWidget.cxx */,
2D05FF5F096E269100A518FE /* EventMappingWidget.hxx */,
DC7A24DD173B1DBC00B20FE9 /* FileListWidget.cxx */,
@@ -2107,8 +2107,8 @@
DCA82C701FEB4E780059340F /* TimeMachineDialog.hxx */,
DC8078E60B4BD697005E9305 /* UIDialog.cxx */,
DC8078E70B4BD697005E9305 /* UIDialog.hxx */,
- 2DDBEAD2084578BF00812C11 /* VideoDialog.cxx */,
- 2DDBEAD3084578BF00812C11 /* VideoDialog.hxx */,
+ DC3C9BC72469C93D00CF2D47 /* VideoAudioDialog.cxx */,
+ DC3C9BC92469C93D00CF2D47 /* VideoAudioDialog.hxx */,
2DDBEAD4084578BF00812C11 /* Widget.cxx */,
2DDBEAD5084578BF00812C11 /* Widget.hxx */,
);
@@ -2391,10 +2391,9 @@
DC5AAC2D1FCB24DF00C420A6 /* RadioButtonWidget.hxx in Headers */,
2D9173E309BA90380026E9FF /* Driving.hxx in Headers */,
2D9173E409BA90380026E9FF /* Event.hxx in Headers */,
+ DC3C9BCD2469C93D00CF2D47 /* VideoAudioDialog.hxx in Headers */,
2D9173E509BA90380026E9FF /* Joystick.hxx in Headers */,
2D9173E609BA90380026E9FF /* Keyboard.hxx in Headers */,
- DCACBAD51C54298300703A9B /* CartCVPlus.hxx in Headers */,
- DCACBAD11C54296300703A9B /* CartCVPlusWidget.hxx in Headers */,
DC1B2EC81E50036100F62837 /* TrakBall.hxx in Headers */,
2D9173E709BA90380026E9FF /* M6532.hxx in Headers */,
E0893AF3211B9842008B170D /* HighPass.hxx in Headers */,
@@ -2417,7 +2416,7 @@
DCF3A6EE1DFC75E3008A8AF3 /* DelayQueueMember.hxx in Headers */,
DC96162F1F817830008A2206 /* AtariMouseWidget.hxx in Headers */,
DCF4907A1A0ECE5B00A67AA9 /* Vec.hxx in Headers */,
- 2D91740109BA90380026E9FF /* AudioDialog.hxx in Headers */,
+ DC3C9BCE2469C93D00CF2D47 /* EmulationDialog.hxx in Headers */,
DC71EA9E1FDA06D2008827CB /* CartE78K.hxx in Headers */,
2D91740209BA90380026E9FF /* BrowserDialog.hxx in Headers */,
2D91740309BA90380026E9FF /* Command.hxx in Headers */,
@@ -2446,7 +2445,6 @@
2D91741309BA90380026E9FF /* ScrollBarWidget.hxx in Headers */,
2D91741609BA90380026E9FF /* TabWidget.hxx in Headers */,
DCB2ECB01F0AECA3009738A6 /* CartDetector.hxx in Headers */,
- 2D91741709BA90380026E9FF /* VideoDialog.hxx in Headers */,
2D91741809BA90380026E9FF /* Widget.hxx in Headers */,
2D91741909BA90380026E9FF /* CartUA.hxx in Headers */,
DCE8B1871E7E03B300189864 /* FrameLayout.hxx in Headers */,
@@ -2476,6 +2474,7 @@
DC3EE86C1E2C0E6D00905161 /* zconf.h in Headers */,
2D91743609BA90380026E9FF /* DebuggerSystem.hxx in Headers */,
2D91743A09BA90380026E9FF /* Expression.hxx in Headers */,
+ DC3C9BDA2469C9C700CF2D47 /* CartEnhancedWidget.hxx in Headers */,
2D91744F09BA90380026E9FF /* InputTextDialog.hxx in Headers */,
DC1B2EC61E50036100F62837 /* AtariMouse.hxx in Headers */,
DC9616331F817830008A2206 /* PointingDeviceWidget.hxx in Headers */,
@@ -2502,7 +2501,7 @@
DCA078351F8C1B04008EFEE5 /* SDL_lib.hxx in Headers */,
DCDA03B11A2009BB00711920 /* CartWD.hxx in Headers */,
2D91745909BA90380026E9FF /* PromptWidget.hxx in Headers */,
- DC2AADAF194F389C0026C7A4 /* CartDASH.hxx in Headers */,
+ DC3C9BC62469C8F700CF2D47 /* PaletteHandler.hxx in Headers */,
2D91745A09BA90380026E9FF /* RamWidget.hxx in Headers */,
2D91745B09BA90380026E9FF /* RomListWidget.hxx in Headers */,
2D91745C09BA90380026E9FF /* RomWidget.hxx in Headers */,
@@ -2513,6 +2512,7 @@
2D91746109BA90380026E9FF /* TogglePixelWidget.hxx in Headers */,
2D91746209BA90380026E9FF /* ToggleWidget.hxx in Headers */,
2D91746409BA90380026E9FF /* TiaZoomWidget.hxx in Headers */,
+ DC3C9BD52469C9A200CF2D47 /* CartEnhanced.hxx in Headers */,
DC1BC6672066B4390076F74A /* PKeyboardHandler.hxx in Headers */,
2D91746609BA90380026E9FF /* AudioWidget.hxx in Headers */,
DC70065E241EC97900A459AB /* Stella14x28tFont.hxx in Headers */,
@@ -2593,7 +2593,6 @@
DCD6FC7111C281ED005DA767 /* png.h in Headers */,
DCD6FC7211C281ED005DA767 /* pngconf.h in Headers */,
DCF3A6F41DFC75E3008A8AF3 /* LatchedInput.hxx in Headers */,
- DC74E5C7198AF12700F37E36 /* CartDASHWidget.hxx in Headers */,
DCD6FC7711C281ED005DA767 /* pngpriv.h in Headers */,
CFE3F60C1E84A9A200A8204E /* CartBUSWidget.hxx in Headers */,
DCD6FC9411C28C6F005DA767 /* PNGLibrary.hxx in Headers */,
@@ -2637,6 +2636,7 @@
DCE395EF16CB0B5F008DB1E5 /* FSNodeFactory.hxx in Headers */,
DCE395F116CB0B5F008DB1E5 /* FSNodeZIP.hxx in Headers */,
DCE395F316CB0B5F008DB1E5 /* ZipHandler.hxx in Headers */,
+ DC3C9BD42469C9A200CF2D47 /* Cart3EX.hxx in Headers */,
DCAAE5D41715887B0080BB82 /* Cart2KWidget.hxx in Headers */,
DCF7F129223D796000701A47 /* ProfilingRunner.hxx in Headers */,
DCAAE5D61715887B0080BB82 /* Cart3FWidget.hxx in Headers */,
@@ -2816,7 +2816,9 @@
E0A755792244294600101889 /* CartCDFInfoWidget.cxx in Sources */,
E0406FB81F81A85400A82AE0 /* FrameManager.cxx in Sources */,
2D91747409BA90380026E9FF /* SDLMain.m in Sources */,
+ DC3C9BC52469C8F700CF2D47 /* PaletteHandler.cxx in Sources */,
2D91747509BA90380026E9FF /* Booster.cxx in Sources */,
+ DC3C9BD62469C9A200CF2D47 /* Cart3EX.cxx in Sources */,
DC3EE8671E2C0E6D00905161 /* inftrees.c in Sources */,
2D91747609BA90380026E9FF /* Cart.cxx in Sources */,
2D91747709BA90380026E9FF /* Cart2K.cxx in Sources */,
@@ -2844,6 +2846,7 @@
DCF3A6FA1DFC75E3008A8AF3 /* Player.cxx in Sources */,
2D91748609BA90380026E9FF /* CartFE.cxx in Sources */,
2D91748909BA90380026E9FF /* Console.cxx in Sources */,
+ DC3C9BD32469C9A200CF2D47 /* CartEnhanced.cxx in Sources */,
DC6DC91E205DB879004A5FC3 /* PhysicalJoystick.cxx in Sources */,
E08FCD5323A037EB0051F59B /* QisBlitter.cxx in Sources */,
DCCE0355225104BF008C246F /* StellaSettingsDialog.cxx in Sources */,
@@ -2867,7 +2870,6 @@
2D9174A309BA90380026E9FF /* Settings.cxx in Sources */,
2D9174A809BA90380026E9FF /* FSNodePOSIX.cxx in Sources */,
2D9174AA09BA90380026E9FF /* AboutDialog.cxx in Sources */,
- 2D9174AB09BA90380026E9FF /* AudioDialog.cxx in Sources */,
2D9174AC09BA90380026E9FF /* BrowserDialog.cxx in Sources */,
2D9174AD09BA90380026E9FF /* Dialog.cxx in Sources */,
2D9174AE09BA90380026E9FF /* DialogContainer.cxx in Sources */,
@@ -2877,6 +2879,7 @@
2D9174B309BA90380026E9FF /* LauncherDialog.cxx in Sources */,
2D9174B509BA90380026E9FF /* ListWidget.cxx in Sources */,
2D9174B609BA90380026E9FF /* Menu.cxx in Sources */,
+ DC3C9BD92469C9C700CF2D47 /* CartEnhancedWidget.cxx in Sources */,
CFE3F60D1E84A9A200A8204E /* CartCDFWidget.cxx in Sources */,
2D9174B709BA90380026E9FF /* OptionsDialog.cxx in Sources */,
2D9174B809BA90380026E9FF /* PopUpWidget.cxx in Sources */,
@@ -2886,7 +2889,6 @@
2D9174B909BA90380026E9FF /* ProgressDialog.cxx in Sources */,
2D9174BA09BA90380026E9FF /* ScrollBarWidget.cxx in Sources */,
2D9174BB09BA90380026E9FF /* TabWidget.cxx in Sources */,
- 2D9174BC09BA90380026E9FF /* VideoDialog.cxx in Sources */,
DC6A18FC19B3E67A00DEB242 /* CartMDM.cxx in Sources */,
2D9174BD09BA90380026E9FF /* Widget.cxx in Sources */,
2D9174BE09BA90380026E9FF /* CartUA.cxx in Sources */,
@@ -2914,7 +2916,6 @@
2D9174F109BA90380026E9FF /* InputTextDialog.cxx in Sources */,
DC6DC920205DB879004A5FC3 /* PJoystickHandler.cxx in Sources */,
DC2410E42274BDA8007A4CBF /* MinUICommandDialog.cxx in Sources */,
- DC74E5C6198AF12700F37E36 /* CartDASHWidget.cxx in Sources */,
2D9174F209BA90380026E9FF /* CheckListWidget.cxx in Sources */,
2D9174F309BA90380026E9FF /* StringListWidget.cxx in Sources */,
2D9174F409BA90380026E9FF /* CommandDialog.cxx in Sources */,
@@ -2931,7 +2932,6 @@
DC5963132139FA14002736F2 /* Bankswitch.cxx in Sources */,
DCDFF08120B781B0001227C0 /* DispatchResult.cxx in Sources */,
2D9174FC09BA90380026E9FF /* RamWidget.cxx in Sources */,
- DC2AADAE194F389C0026C7A4 /* CartDASH.cxx in Sources */,
DC21E5C121CA903E007D0E1A /* SerialPortMACOS.cxx in Sources */,
E007231F210FBF5E002CF343 /* FpsMeter.cxx in Sources */,
2D9174FD09BA90380026E9FF /* RomListWidget.cxx in Sources */,
@@ -2960,7 +2960,6 @@
DC47455A09C34BFA00EDDA3A /* CheatManager.cxx in Sources */,
DC47455C09C34BFA00EDDA3A /* CheetahCheat.cxx in Sources */,
DC62E6471960E87B007AEF05 /* AtariVoxWidget.cxx in Sources */,
- DCACBAD41C54298300703A9B /* CartCVPlus.cxx in Sources */,
DC47455E09C34BFA00EDDA3A /* RamCheat.cxx in Sources */,
E0FABEEC20E9948200EB8E28 /* AudioSettings.cxx in Sources */,
DCD56D380B247D920092F9F8 /* Cart4A50.cxx in Sources */,
@@ -3003,6 +3002,7 @@
DC6B2BA411037FF200F199A7 /* CartDebug.cxx in Sources */,
DCB20EC71A0C506C0048F595 /* main.cxx in Sources */,
DC6B2BA611037FF200F199A7 /* DiStella.cxx in Sources */,
+ DC3C9BCB2469C93D00CF2D47 /* VideoAudioDialog.cxx in Sources */,
CFE3F6151E84A9CE00A8204E /* CartCDF.cxx in Sources */,
E08D2F3E23089B9B000BD709 /* JoyMap.cxx in Sources */,
DCA82C711FEB4E780059340F /* TimeMachine.cxx in Sources */,
@@ -3103,6 +3103,7 @@
DC676A531729A0B000E4E73D /* CartFA2Widget.cxx in Sources */,
DC676A551729A0B000E4E73D /* CartFEWidget.cxx in Sources */,
DC676A591729A0B000E4E73D /* CartSBWidget.cxx in Sources */,
+ DC3C9BCC2469C93D00CF2D47 /* EmulationDialog.cxx in Sources */,
DC676A5B1729A0B000E4E73D /* CartX07Widget.cxx in Sources */,
DC7A24DF173B1DBC00B20FE9 /* FileListWidget.cxx in Sources */,
DC13B53F176FF2F500B8B4BB /* RomListSettings.cxx in Sources */,
@@ -3116,7 +3117,6 @@
DCAACAFC188D631500A4D282 /* CartDF.cxx in Sources */,
DCAACAFE188D631500A4D282 /* CartDFSC.cxx in Sources */,
DCAACB0E188D636F00A4D282 /* Cart4KSCWidget.cxx in Sources */,
- DCACBAD01C54296300703A9B /* CartCVPlusWidget.cxx in Sources */,
DCAACB10188D636F00A4D282 /* CartBFSCWidget.cxx in Sources */,
DCAACB12188D636F00A4D282 /* CartBFWidget.cxx in Sources */,
DCAACB14188D636F00A4D282 /* CartDFSCWidget.cxx in Sources */,
diff --git a/src/windows/Stella.vcxproj b/src/windows/Stella.vcxproj
index 1095f2c09..6fef5d589 100644
--- a/src/windows/Stella.vcxproj
+++ b/src/windows/Stella.vcxproj
@@ -503,6 +503,7 @@
+
@@ -757,6 +758,7 @@
+
@@ -906,7 +908,6 @@
true
-
@@ -938,7 +939,7 @@
-
+
CompileAsC
@@ -1503,6 +1504,7 @@
+
@@ -1789,6 +1791,7 @@
+
@@ -1965,7 +1968,6 @@
-
@@ -2001,7 +2003,7 @@
-
+
diff --git a/src/windows/Stella.vcxproj.filters b/src/windows/Stella.vcxproj.filters
index fb763da4c..0e4f58929 100644
--- a/src/windows/Stella.vcxproj.filters
+++ b/src/windows/Stella.vcxproj.filters
@@ -342,9 +342,6 @@
Source Files\gui
-
- Source Files\gui
-
Source Files\gui
@@ -438,9 +435,6 @@
Source Files\gui
-
- Source Files\gui
-
Source Files\gui
@@ -1002,6 +996,15 @@
Source Files\emucore
+
+ Source Files
+
+
+ Source Files\gui
+
+
+ Source Files\gui
+
@@ -1313,9 +1316,6 @@
Header Files\gui
-
- Header Files\gui
-
Header Files\gui
@@ -1421,9 +1421,6 @@
Header Files\gui
-
- Header Files\gui
-
Header Files\gui
@@ -2057,6 +2054,15 @@
Header Files\emucore
+
+ Header Files
+
+
+ Header Files\gui
+
+
+ Header Files\gui
+
|