diff --git a/docs/index.html b/docs/index.html
index cc57d0546..b11f7b770 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -2730,6 +2730,10 @@
indicating serious errors override this setting, and are always
shown.
+
+ -pausedim <1|0> |
+ Enable or disable emulation dimming in pause mode. |
+
-audio.enabled <1|0> |
diff --git a/src/emucore/FrameBuffer.cxx b/src/emucore/FrameBuffer.cxx
index 6eb8ec6fd..f74f084b9 100644
--- a/src/emucore/FrameBuffer.cxx
+++ b/src/emucore/FrameBuffer.cxx
@@ -339,14 +339,16 @@ void FrameBuffer::update(UpdateMode mode)
case EventHandlerState::PAUSE:
{
// Show a pause message immediately and then every 7 seconds
+ bool shade = myOSystem.settings().getBool("pausedim");
+
if(myPausedCount-- <= 0)
{
myPausedCount = uInt32(7 * myOSystem.frameRate());
showTextMessage("Paused", MessagePosition::MiddleCenter);
- myTIASurface->render(true);
+ myTIASurface->render(shade);
}
if(rerender)
- myTIASurface->render(true);
+ myTIASurface->render(shade);
break; // EventHandlerState::PAUSE
}
diff --git a/src/emucore/Paddles.cxx b/src/emucore/Paddles.cxx
index 737eb048b..e5e9146ac 100644
--- a/src/emucore/Paddles.cxx
+++ b/src/emucore/Paddles.cxx
@@ -47,113 +47,50 @@ Paddles::Paddles(Jack jack, const Event& event, const System& system,
// Consider whether this is the left or right port
if(myJack == Jack::Left)
{
- if(!swappaddle) // First paddle is 0, second is 1
- {
- // These aren't affected by changes in axis orientation
- myP0AxisValue = Event::PaddleZeroAnalog;
- myP1AxisValue = Event::PaddleOneAnalog;
- myP0FireEvent = Event::PaddleZeroFire;
- myP1FireEvent = Event::PaddleOneFire;
+ // First paddle is 0, second is 1
+ myP0AxisValue = Event::PaddleZeroAnalog;
+ myP1AxisValue = Event::PaddleOneAnalog;
+ myP0FireEvent = Event::PaddleZeroFire;
+ myP1FireEvent = Event::PaddleOneFire;
- // Direction of movement is swapped
- // That is, moving in a certain direction on an axis can
- // result in either increasing or decreasing paddle movement
- if(!swapdir)
- {
- myP0DecEvent = Event::PaddleZeroDecrease;
- myP0IncEvent = Event::PaddleZeroIncrease;
- myP1DecEvent = Event::PaddleOneDecrease;
- myP1IncEvent = Event::PaddleOneIncrease;
- }
- else
- {
- myP0DecEvent = Event::PaddleZeroIncrease;
- myP0IncEvent = Event::PaddleZeroDecrease;
- myP1DecEvent = Event::PaddleOneIncrease;
- myP1IncEvent = Event::PaddleOneDecrease;
- }
- }
- else // First paddle is 1, second is 0
- {
- // These aren't affected by changes in axis orientation
- myP0AxisValue = Event::PaddleOneAnalog;
- myP1AxisValue = Event::PaddleZeroAnalog;
- myP0FireEvent = Event::PaddleOneFire;
- myP1FireEvent = Event::PaddleZeroFire;
-
- // Direction of movement is swapped
- // That is, moving in a certain direction on an axis can
- // result in either increasing or decreasing paddle movement
- if(!swapdir)
- {
- myP0DecEvent = Event::PaddleOneDecrease;
- myP0IncEvent = Event::PaddleOneIncrease;
- myP1DecEvent = Event::PaddleZeroDecrease;
- myP1IncEvent = Event::PaddleZeroIncrease;
- }
- else
- {
- myP0DecEvent = Event::PaddleOneIncrease;
- myP0IncEvent = Event::PaddleOneDecrease;
- myP1DecEvent = Event::PaddleZeroIncrease;
- myP1IncEvent = Event::PaddleZeroDecrease;
- }
- }
+ // These can be affected by changes in axis orientation
+ myP0DecEvent = Event::PaddleZeroDecrease;
+ myP0IncEvent = Event::PaddleZeroIncrease;
+ myP1DecEvent = Event::PaddleOneDecrease;
+ myP1IncEvent = Event::PaddleOneIncrease;
}
else // Jack is right port
{
- if(!swappaddle) // First paddle is 2, second is 3
- {
- // These aren't affected by changes in axis orientation
- myP0AxisValue = Event::PaddleTwoAnalog;
- myP1AxisValue = Event::PaddleThreeAnalog;
- myP0FireEvent = Event::PaddleTwoFire;
- myP1FireEvent = Event::PaddleThreeFire;
+ // First paddle is 2, second is 3
+ myP0AxisValue = Event::PaddleTwoAnalog;
+ myP1AxisValue = Event::PaddleThreeAnalog;
+ myP0FireEvent = Event::PaddleTwoFire;
+ myP1FireEvent = Event::PaddleThreeFire;
- // Direction of movement is swapped
- // That is, moving in a certain direction on an axis can
- // result in either increasing or decreasing paddle movement
- if(!swapdir)
- {
- myP0DecEvent = Event::PaddleTwoDecrease;
- myP0IncEvent = Event::PaddleTwoIncrease;
- myP1DecEvent = Event::PaddleThreeDecrease;
- myP1IncEvent = Event::PaddleThreeIncrease;
- }
- else
- {
- myP0DecEvent = Event::PaddleTwoIncrease;
- myP0IncEvent = Event::PaddleTwoDecrease;
- myP1DecEvent = Event::PaddleThreeIncrease;
- myP1IncEvent = Event::PaddleThreeDecrease;
- }
- }
- else // First paddle is 3, second is 2
- {
- // These aren't affected by changes in axis orientation
- myP0AxisValue = Event::PaddleThreeAnalog;
- myP1AxisValue = Event::PaddleTwoAnalog;
- myP0FireEvent = Event::PaddleThreeFire;
- myP1FireEvent = Event::PaddleTwoFire;
+ // These can be affected by changes in axis orientation
+ myP0DecEvent = Event::PaddleTwoDecrease;
+ myP0IncEvent = Event::PaddleTwoIncrease;
+ myP1DecEvent = Event::PaddleThreeDecrease;
+ myP1IncEvent = Event::PaddleThreeIncrease;
+ }
- // Direction of movement is swapped
- // That is, moving in a certain direction on an axis can
- // result in either increasing or decreasing paddle movement
- if(!swapdir)
- {
- myP0DecEvent = Event::PaddleThreeDecrease;
- myP0IncEvent = Event::PaddleThreeIncrease;
- myP1DecEvent = Event::PaddleTwoDecrease;
- myP1IncEvent = Event::PaddleTwoIncrease;
- }
- else
- {
- myP0DecEvent = Event::PaddleThreeIncrease;
- myP0IncEvent = Event::PaddleThreeDecrease;
- myP1DecEvent = Event::PaddleTwoIncrease;
- myP1IncEvent = Event::PaddleTwoDecrease;
- }
- }
+ // Some games swap the paddles
+ if(swappaddle)
+ {
+ // First paddle is 1|3, second is 0|2
+ swapEvents(myP0AxisValue, myP1AxisValue);
+ swapEvents(myP0FireEvent, myP1FireEvent);
+ swapEvents(myP0DecEvent, myP1DecEvent);
+ swapEvents(myP0IncEvent, myP1IncEvent);
+ }
+
+ // Direction of movement can be swapped
+ // That is, moving in a certain direction on an axis can
+ // result in either increasing or decreasing paddle movement
+ if(swapdir)
+ {
+ swapEvents(myP0DecEvent, myP0IncEvent);
+ swapEvents(myP1DecEvent, myP1IncEvent);
}
// The following are independent of whether or not the port
@@ -179,6 +116,16 @@ Paddles::Paddles(Jack jack, const Event& event, const System& system,
setPin(DigitalPin::Six, true);
}
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void Paddles::swapEvents(Event::Type& event1, Event::Type& event2)
+{
+ Event::Type swappedEvent;
+
+ swappedEvent = event1;
+ event1 = event2;
+ event2 = swappedEvent;
+}
+
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Paddles::update()
{
@@ -200,6 +147,31 @@ void Paddles::update()
// And to top it all off, we don't want one devices input to conflict
// with the others ...
+ if(!updateAnalogAxes())
+ {
+ updateMouse(firePressedP0, firePressedP1);
+ updateDigitalAxes();
+
+ // Only change state if the charge has actually changed
+ if(myCharge[1] != myLastCharge[1])
+ {
+ setPin(AnalogPin::Five, Int32(MAX_RESISTANCE * (myCharge[1] / double(TRIGMAX))));
+ myLastCharge[1] = myCharge[1];
+ }
+ if(myCharge[0] != myLastCharge[0])
+ {
+ setPin(AnalogPin::Nine, Int32(MAX_RESISTANCE * (myCharge[0] / double(TRIGMAX))));
+ myLastCharge[0] = myCharge[0];
+ }
+ }
+
+ setPin(DigitalPin::Four, !getAutoFireState(firePressedP0));
+ setPin(DigitalPin::Three, !getAutoFireStateP1(firePressedP1));
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+bool Paddles::updateAnalogAxes()
+{
// Analog axis events from Stelladaptor-like devices
// These devices generate data in the range -32768 to 32767,
// so we have to scale appropriately
@@ -207,10 +179,6 @@ void Paddles::update()
// we only process the first one we see (when it differs from
// previous values by a pre-defined amount)
// Otherwise, it would always override input from digital and mouse
- bool sa_changed = false;
- int sa_xaxis = myEvent.get(myP0AxisValue);
- int sa_yaxis = myEvent.get(myP1AxisValue);
- int new_val;
static constexpr std::array bFac = {
// higher values mean more dejitter strength
@@ -221,24 +189,28 @@ void Paddles::update()
static constexpr std::array dFac = {
// lower values mean more dejitter strength
1, // off
- 1.0 / 181, 1.0 / 256, 1.0 / 362, 1.0 / 512, 1.0 / 724,
+ 1.0 / 181, 1.0 / 256, 1.0 / 362, 1.0 / 512, 1.0 / 724,
1.0 / 1024, 1.0 / 1448, 1.0 / 2048, 1.0 / 2896, 1.0 / 4096
};
const double baseFactor = bFac[DEJITTER_BASE];
const double diffFactor = dFac[DEJITTER_DIFF];
+ int sa_xaxis = myEvent.get(myP0AxisValue);
+ int sa_yaxis = myEvent.get(myP1AxisValue);
+ bool sa_changed = false;
+
if(abs(myLastAxisX - sa_xaxis) > 10)
{
// dejitter, suppress small changes only
double dejitter = std::pow(baseFactor, abs(sa_xaxis - myLastAxisX) * diffFactor);
- new_val = sa_xaxis * (1 - dejitter) + myLastAxisX * dejitter;
+ int new_val = sa_xaxis * (1 - dejitter) + myLastAxisX * dejitter;
// only use new dejittered value for larger differences
if(abs(new_val - sa_xaxis) > 10)
sa_xaxis = new_val;
setPin(AnalogPin::Nine, Int32(MAX_RESISTANCE *
- (BSPF::clamp(32768 - Int32(Int32(sa_xaxis) * SENSITIVITY + XCENTER), 0, 65536) / 65536.0)));
+ (BSPF::clamp(32768 - Int32(Int32(sa_xaxis) * SENSITIVITY + XCENTER), 0, 65536) / 65536.0)));
sa_changed = true;
}
@@ -246,29 +218,33 @@ void Paddles::update()
{
// dejitter, suppress small changes only
double dejitter = std::pow(baseFactor, abs(sa_yaxis - myLastAxisY) * diffFactor);
- new_val = sa_yaxis * (1 - dejitter) + myLastAxisY * dejitter;
+ int new_val = sa_yaxis * (1 - dejitter) + myLastAxisY * dejitter;
// only use new dejittered value for larger differences
- if (abs(new_val - sa_yaxis) > 10)
+ if(abs(new_val - sa_yaxis) > 10)
sa_yaxis = new_val;
setPin(AnalogPin::Five, Int32(MAX_RESISTANCE *
- (BSPF::clamp(32768 - Int32(Int32(sa_yaxis) * SENSITIVITY + YCENTER), 0, 65536) / 65536.0)));
+ (BSPF::clamp(32768 - Int32(Int32(sa_yaxis) * SENSITIVITY + YCENTER), 0, 65536) / 65536.0)));
sa_changed = true;
}
myLastAxisX = sa_xaxis;
myLastAxisY = sa_yaxis;
- if(sa_changed)
- return;
+ return sa_changed;
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void Paddles::updateMouse(bool& firePressedP0, bool& firePressedP1)
+{
// Mouse motion events give relative movement
// That is, they're only relevant if they're non-zero
if(myMPaddleID > -1)
{
// We're in auto mode, where a single axis is used for one paddle only
myCharge[myMPaddleID] = BSPF::clamp(myCharge[myMPaddleID] -
- (myEvent.get(myAxisMouseMotion) * MOUSE_SENSITIVITY),
- TRIGMIN, TRIGRANGE);
+ (myEvent.get(myAxisMouseMotion) * MOUSE_SENSITIVITY),
+ TRIGMIN, TRIGRANGE);
if(myMPaddleID == 0)
firePressedP0 = firePressedP0
|| myEvent.get(Event::MouseButtonLeftValue)
@@ -285,9 +261,8 @@ void Paddles::update()
if(myMPaddleIDX > -1)
{
myCharge[myMPaddleIDX] = BSPF::clamp(myCharge[myMPaddleIDX] -
- (myEvent.get(Event::MouseAxisXMove) * MOUSE_SENSITIVITY),
- TRIGMIN, TRIGRANGE);
-
+ (myEvent.get(Event::MouseAxisXMove) * MOUSE_SENSITIVITY),
+ TRIGMIN, TRIGRANGE);
if(myMPaddleIDX == 0)
firePressedP0 = firePressedP0
|| myEvent.get(Event::MouseButtonLeftValue);
@@ -298,9 +273,8 @@ void Paddles::update()
if(myMPaddleIDY > -1)
{
myCharge[myMPaddleIDY] = BSPF::clamp(myCharge[myMPaddleIDY] -
- (myEvent.get(Event::MouseAxisYMove) * MOUSE_SENSITIVITY),
- TRIGMIN, TRIGRANGE);
-
+ (myEvent.get(Event::MouseAxisYMove) * MOUSE_SENSITIVITY),
+ TRIGMIN, TRIGRANGE);
if(myMPaddleIDY == 0)
firePressedP0 = firePressedP0
|| myEvent.get(Event::MouseButtonRightValue);
@@ -309,9 +283,11 @@ void Paddles::update()
|| myEvent.get(Event::MouseButtonRightValue);
}
}
- setPin(DigitalPin::Four, !getAutoFireState(firePressedP0));
- setPin(DigitalPin::Three, !getAutoFireStateP1(firePressedP1));
+}
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void Paddles::updateDigitalAxes()
+{
// Finally, consider digital input, where movement happens
// until a digital event is released
if(myKeyRepeat0)
@@ -354,15 +330,6 @@ void Paddles::update()
if((myCharge[myAxisDigitalOne] + myPaddleRepeat1) < TRIGRANGE)
myCharge[myAxisDigitalOne] += myPaddleRepeat1;
}
-
- // Only change state if the charge has actually changed
- if(myCharge[1] != myLastCharge[1])
- setPin(AnalogPin::Five, Int32(MAX_RESISTANCE * (myCharge[1] / double(TRIGMAX))));
- if(myCharge[0] != myLastCharge[0])
- setPin(AnalogPin::Nine, Int32(MAX_RESISTANCE * (myCharge[0] / double(TRIGMAX))));
-
- myLastCharge[1] = myCharge[1];
- myLastCharge[0] = myCharge[0];
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/src/emucore/Paddles.hxx b/src/emucore/Paddles.hxx
index 0ba4cd8c8..ea77de6ad 100644
--- a/src/emucore/Paddles.hxx
+++ b/src/emucore/Paddles.hxx
@@ -197,6 +197,26 @@ class Paddles : public Controller
static int DEJITTER_BASE, DEJITTER_DIFF;
static int MOUSE_SENSITIVITY;
+ /**
+ Swap two events.
+ */
+ void swapEvents(Event::Type& event1, Event::Type& event2);
+
+ /**
+ Update the axes pin state according to the events currently set.
+ */
+ bool updateAnalogAxes();
+
+ /**
+ Update the entire state according to mouse events currently set.
+ */
+ void updateMouse(bool& firePressedP0, bool& firePressedP1);
+
+ /**
+ Update the axes pin state according to the keyboard events currently set.
+ */
+ void updateDigitalAxes();
+
private:
// Following constructors and assignment operators not supported
Paddles() = delete;
diff --git a/src/emucore/Settings.cxx b/src/emucore/Settings.cxx
index 215588c31..bbd1b24b3 100644
--- a/src/emucore/Settings.cxx
+++ b/src/emucore/Settings.cxx
@@ -47,6 +47,7 @@ Settings::Settings()
setPermanent("windowedpos", Common::Point(50, 50));
setPermanent("display", 0);
setPermanent("uimessages", "true");
+ setPermanent("pausedim", "true");
// TIA specific options
setPermanent("tia.inter", "false");
setPermanent("tia.zoom", "3");
@@ -446,6 +447,7 @@ void Settings::usage() const
<< " -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"
+ << " -pausedim <1|0> Enable emulation dimming in pause mode\n"
<< endl
#ifdef SOUND_SUPPORT
<< " -audio.enabled <1|0> Enable audio\n"