Commit 3a54adec authored by Christian Speckner's avatar Christian Speckner
Browse files

Merge remote-tracking branch 'origin/master' into feature/fix-surfaces

parents 9f74a780 fb73d90c
Pipeline #11387 passed with stages
in 2 minutes and 3 seconds
......@@ -2730,6 +2730,10 @@
indicating serious errors override this setting, and are always
shown.</td>
</tr>
<tr>
<td><pre>-pausedim &lt;1|0&gt;</pre></td>
<td>Enable or disable emulation dimming in pause mode.</td>
</tr>
<tr>
<td><pre>-audio.enabled &lt;1|0&gt;</pre></td>
......
......@@ -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
}
......
......@@ -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;
// 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;
}
}
// First paddle is 0, second is 1
myP0AxisValue = Event::PaddleZeroAnalog;
myP1AxisValue = Event::PaddleOneAnalog;
myP0FireEvent = Event::PaddleZeroFire;
myP1FireEvent = Event::PaddleOneFire;
// 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;
// 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;
// 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;
}
}
// First paddle is 2, second is 3
myP0AxisValue = Event::PaddleTwoAnalog;
myP1AxisValue = Event::PaddleThreeAnalog;
myP0FireEvent = Event::PaddleTwoFire;
myP1FireEvent = Event::PaddleThreeFire;
// These can be affected by changes in axis orientation
myP0DecEvent = Event::PaddleTwoDecrease;
myP0IncEvent = Event::PaddleTwoIncrease;
myP1DecEvent = Event::PaddleThreeDecrease;
myP1IncEvent = Event::PaddleThreeIncrease;
}
// 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<double, MAX_DEJITTER - MIN_DEJITTER + 1> bFac = {
// higher values mean more dejitter strength
......@@ -221,24 +189,28 @@ void Paddles::update()
static constexpr std::array<double, MAX_DEJITTER - MIN_DEJITTER + 1> 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];
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
......
......@@ -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;
......
......@@ -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 <number> 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"
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment