First pass at allowing a max range for paddle emulation when using

the mouse or digital input.  This will fix those ROMs that don't
use much of the range on a real paddle, and as such have a huge
deadzone in emulation.

For now, only the Paddle class is modified.  Still TODO is add the
ability to change this from the UI (per-ROM, obviously).


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@3247 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2015-12-30 23:57:54 +00:00
parent a263eb0c6b
commit a0536fb450
5 changed files with 90 additions and 79 deletions

View File

@ -12,6 +12,24 @@
Release History
===========================================================================
4.6.7 to 4.7: (January xx, 2016)
* Added ability to specify the maximum range of movement for paddles when
using a mouse or digital device to emulate the paddle. This is needed,
since on a real console most paddle games use very little of the
paddle range, and could result in moving the mouse onscreen with
nothing appearing to happen (when in effect it was as if you turned
a real paddle all the way to the end of the range). This eliminates
issues in (for example) Kaboom, where there was a huge 'deadzone'
when moving to the left.
* Added more C++11 updates all over the codebase, and ran Stella
through Coverity for the first time. I'm proud to say that Stella
now has a 0.00 defect rate!
-Have fun!
4.6.6 to 4.6.7: (October 28, 2015)
* Fixed bug when using real paddles plugged into a Stelladaptor
@ -19,8 +37,6 @@
* Fixed small logic error in 'MDM' bankswitching scheme.
-Have fun!
4.6.5 to 4.6.6: (October 11, 2015)

View File

@ -17,8 +17,6 @@
// $Id$
//============================================================================
#include <cassert>
#include "Event.hxx"
#include "Paddles.hxx"
@ -198,8 +196,8 @@ Paddles::Paddles(Jack jack, const Event& event, const System& system,
// The following are independent of whether or not the port
// is left or right
_MOUSE_SENSITIVITY = swapdir ? -abs(_MOUSE_SENSITIVITY) :
abs(_MOUSE_SENSITIVITY);
MOUSE_SENSITIVITY = swapdir ? -abs(MOUSE_SENSITIVITY) :
abs(MOUSE_SENSITIVITY);
if(!swapaxis)
{
myAxisMouseMotion = Event::MouseAxisXValue;
@ -224,10 +222,6 @@ Paddles::Paddles(Jack jack, const Event& event, const System& system,
myCharge[0] = myCharge[1] = TRIGRANGE / 2;
myLastCharge[0] = myLastCharge[1] = 0;
// Paranoid mode: defaults for the global variables should be set
// before the first instance of this class is instantiated
assert(_DIGITAL_SENSITIVITY != -1 && _MOUSE_SENSITIVITY != -1);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -282,12 +276,9 @@ void Paddles::update()
if(myMPaddleID > -1)
{
// We're in auto mode, where a single axis is used for one paddle only
myCharge[myMPaddleID] -=
((myEvent.get(myAxisMouseMotion) >> 1) * _MOUSE_SENSITIVITY);
if(myCharge[myMPaddleID] < TRIGMIN)
myCharge[myMPaddleID] = TRIGMIN;
if(myCharge[myMPaddleID] > TRIGMAX)
myCharge[myMPaddleID] = TRIGMAX;
myCharge[myMPaddleID] = BSPF_clamp(myCharge[myMPaddleID] -
(myEvent.get(myAxisMouseMotion) * MOUSE_SENSITIVITY),
TRIGMIN, TRIGRANGE);
if(myEvent.get(Event::MouseButtonLeftValue) ||
myEvent.get(Event::MouseButtonRightValue))
myDigitalPinState[ourButtonPin[myMPaddleID]] = false;
@ -298,23 +289,17 @@ void Paddles::update()
// mapped to a separate paddle
if(myMPaddleIDX > -1)
{
myCharge[myMPaddleIDX] -=
((myEvent.get(Event::MouseAxisXValue) >> 1) * _MOUSE_SENSITIVITY);
if(myCharge[myMPaddleIDX] < TRIGMIN)
myCharge[myMPaddleIDX] = TRIGMIN;
if(myCharge[myMPaddleIDX] > TRIGMAX)
myCharge[myMPaddleIDX] = TRIGMAX;
myCharge[myMPaddleIDX] = BSPF_clamp(myCharge[myMPaddleIDX] -
(myEvent.get(Event::MouseAxisXValue) * MOUSE_SENSITIVITY),
TRIGMIN, TRIGRANGE);
if(myEvent.get(Event::MouseButtonLeftValue))
myDigitalPinState[ourButtonPin[myMPaddleIDX]] = false;
}
if(myMPaddleIDY > -1)
{
myCharge[myMPaddleIDY] -=
((myEvent.get(Event::MouseAxisYValue) >> 1) * _MOUSE_SENSITIVITY);
if(myCharge[myMPaddleIDY] < TRIGMIN)
myCharge[myMPaddleIDY] = TRIGMIN;
if(myCharge[myMPaddleIDY] > TRIGMAX)
myCharge[myMPaddleIDY] = TRIGMAX;
myCharge[myMPaddleIDY] = BSPF_clamp(myCharge[myMPaddleIDY] -
(myEvent.get(Event::MouseAxisYValue) * MOUSE_SENSITIVITY),
TRIGMIN, TRIGRANGE);
if(myEvent.get(Event::MouseButtonRightValue))
myDigitalPinState[ourButtonPin[myMPaddleIDY]] = false;
}
@ -325,14 +310,14 @@ void Paddles::update()
if(myKeyRepeat0)
{
myPaddleRepeat0++;
if(myPaddleRepeat0 > _DIGITAL_SENSITIVITY)
myPaddleRepeat0 = _DIGITAL_DISTANCE;
if(myPaddleRepeat0 > DIGITAL_SENSITIVITY)
myPaddleRepeat0 = DIGITAL_DISTANCE;
}
if(myKeyRepeat1)
{
myPaddleRepeat1++;
if(myPaddleRepeat1 > _DIGITAL_SENSITIVITY)
myPaddleRepeat1 = _DIGITAL_DISTANCE;
if(myPaddleRepeat1 > DIGITAL_SENSITIVITY)
myPaddleRepeat1 = DIGITAL_DISTANCE;
}
myKeyRepeat0 = false;
@ -347,7 +332,7 @@ void Paddles::update()
if(myEvent.get(myP0IncEvent1) || myEvent.get(myP0IncEvent2))
{
myKeyRepeat0 = true;
if((myCharge[myAxisDigitalZero] + myPaddleRepeat0) < TRIGMAX)
if((myCharge[myAxisDigitalZero] + myPaddleRepeat0) < TRIGRANGE)
myCharge[myAxisDigitalZero] += myPaddleRepeat0;
}
if(myEvent.get(myP1DecEvent1) || myEvent.get(myP1DecEvent2))
@ -359,17 +344,17 @@ void Paddles::update()
if(myEvent.get(myP1IncEvent1) || myEvent.get(myP1IncEvent2))
{
myKeyRepeat1 = true;
if((myCharge[myAxisDigitalOne] + myPaddleRepeat1) < TRIGMAX)
if((myCharge[myAxisDigitalOne] + myPaddleRepeat1) < TRIGRANGE)
myCharge[myAxisDigitalOne] += myPaddleRepeat1;
}
// Only change state if the charge has actually changed
if(myCharge[1] != myLastCharge[1])
myAnalogPinValue[Five] =
Int32(1400000 * (myCharge[1] / float(TRIGRANGE)));
Int32(1400000 * (myCharge[1] / float(TRIGMAX)));
if(myCharge[0] != myLastCharge[0])
myAnalogPinValue[Nine] =
Int32(1400000 * (myCharge[0] / float(TRIGRANGE)));
Int32(1400000 * (myCharge[0] / float(TRIGMAX)));
myLastCharge[1] = myCharge[1];
myLastCharge[0] = myCharge[0];
@ -412,26 +397,28 @@ bool Paddles::setMouseControl(
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Paddles::setDigitalSensitivity(int sensitivity)
{
if(sensitivity < 1) sensitivity = 1;
else if(sensitivity > 10) sensitivity = 10;
_DIGITAL_SENSITIVITY = sensitivity;
_DIGITAL_DISTANCE = 20 + (sensitivity << 3);
DIGITAL_SENSITIVITY = BSPF_clamp(sensitivity, 1, MAX_DIGITAL_SENSE);
DIGITAL_DISTANCE = 20 + (DIGITAL_SENSITIVITY << 3);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Paddles::setMouseSensitivity(int sensitivity)
{
if(sensitivity < 1) sensitivity = 1;
else if(sensitivity > 15) sensitivity = 15;
_MOUSE_SENSITIVITY = sensitivity;
MOUSE_SENSITIVITY = BSPF_clamp(sensitivity, 1, MAX_MOUSE_SENSE);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int Paddles::_DIGITAL_SENSITIVITY = -1;
int Paddles::_DIGITAL_DISTANCE = -1;
int Paddles::_MOUSE_SENSITIVITY = -1;
void Paddles::setPaddleRange(int range)
{
range = BSPF_clamp(range, 1, 100);
TRIGRANGE = TRIGMAX * (range / 100.0);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int Paddles::TRIGRANGE = Paddles::TRIGMAX;
int Paddles::DIGITAL_SENSITIVITY = -1;
int Paddles::DIGITAL_DISTANCE = -1;
int Paddles::MOUSE_SENSITIVITY = -1;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const Controller::DigitalPin Paddles::ourButtonPin[2] = { Four, Three };

View File

@ -77,8 +77,8 @@ class Paddles : public Controller
@return Whether the controller supports using the mouse
*/
bool setMouseControl(
Controller::Type xtype, int xid, Controller::Type ytype, int yid) override;
bool setMouseControl(Controller::Type xtype, int xid,
Controller::Type ytype, int yid) override;
/**
Sets the sensitivity for digital emulation of paddle movement.
@ -86,8 +86,8 @@ class Paddles : public Controller
or digital joystick axis events); Stelladaptors or the mouse are
not modified.
@param sensitivity Value from 1 to 10, with larger values
causing more movement
@param sensitivity Value from 1 to MAX_DIGITAL_SENSE, with larger
values causing more movement
*/
static void setDigitalSensitivity(int sensitivity);
@ -95,20 +95,23 @@ class Paddles : public Controller
Sets the sensitivity for analog emulation of paddle movement
using a mouse.
@param sensitivity Value from 1 to 10, with larger values
causing more movement
@param sensitivity Value from 1 to MAX_MOUSE_SENSE, with larger
values causing more movement
*/
static void setMouseSensitivity(int sensitivity);
private:
// Range of values over which digital and mouse movement is scaled
// to paddle resistance
enum {
TRIGRANGE = 4096,
TRIGMAX = 3856,
TRIGMIN = 1
};
/**
Sets the maximum upper range for digital/mouse emulation of paddle
movement (ie, a value of 50 means to only use 50% of the possible
range of movement). Note that this specfically does not apply to
Stelladaptor-like devices, which uses an absolute value range.
@param sensitivity Value from 1 to 100, representing the percentage
of the range to use
*/
static void setPaddleRange(int range);
private:
// Pre-compute the events we care about based on given port
// This will eliminate test for left or right port in update()
Event::Type myP0AxisValue, myP1AxisValue,
@ -127,8 +130,16 @@ class Paddles : public Controller
int myLastAxisX, myLastAxisY;
int myAxisDigitalZero, myAxisDigitalOne;
static int _DIGITAL_SENSITIVITY, _DIGITAL_DISTANCE;
static int _MOUSE_SENSITIVITY;
// Range of values over which digital and mouse movement is scaled
// to paddle resistance
static const int TRIGMIN = 1;
static const int TRIGMAX = 4096;
static int TRIGRANGE; // This one is variable for the upper range
static const int MAX_DIGITAL_SENSE = 20;
static const int MAX_MOUSE_SENSE = 20;
static int DIGITAL_SENSITIVITY, DIGITAL_DISTANCE;
static int MOUSE_SENSITIVITY;
// Lookup table for associating paddle buttons with controller pins
// Yes, this is hideously complex

View File

@ -86,8 +86,8 @@ Settings::Settings(OSystem& osystem)
setInternal("usemouse", "analog");
setInternal("grabmouse", "true");
setInternal("cursor", "2");
setInternal("dsense", "5");
setInternal("msense", "7");
setInternal("dsense", "10");
setInternal("msense", "10");
setInternal("saport", "lr");
setInternal("ctrlcombo", "true");
@ -289,20 +289,17 @@ void Settings::validate()
if(i < 0) setInternal("joydeadzone", "0");
else if(i > 29) setInternal("joydeadzone", "29");
if(i < 1) setInternal("dsense", "1");
else if(i > 10) setInternal("dsense", "10");
i = getInt("cursor");
if(i < 0 || i > 3)
setInternal("cursor", "2");
i = getInt("dsense");
if(i < 1) setInternal("dsense", "1");
else if(i > 10) setInternal("dsense", "10");
else if(i > 20) setInternal("dsense", "10");
i = getInt("msense");
if(i < 1) setInternal("msense", "1");
else if(i > 15) setInternal("msense", "15");
else if(i > 20) setInternal("msense", "15");
i = getInt("ssinterval");
if(i < 1) setInternal("ssinterval", "2");
@ -394,8 +391,8 @@ void Settings::usage() const
<< " never> Use mouse as a controller as specified by ROM properties in given mode(see manual)\n"
<< " -grabmouse <1|0> Locks the mouse cursor in the TIA window\n"
<< " -cursor <0,1,2,3> Set cursor state in UI/emulation modes\n"
<< " -dsense <number> Sensitivity of digital emulated paddle movement (1-10)\n"
<< " -msense <number> Sensitivity of mouse emulated paddle movement (1-15)\n"
<< " -dsense <number> Sensitivity of digital emulated paddle movement (1-20)\n"
<< " -msense <number> Sensitivity of mouse emulated paddle movement (1-20)\n"
<< " -saport <lr|rl> How to assign virtual ports to multiple Stelladaptor/2600-daptors\n"
<< " -ctrlcombo <1|0> Use key combos involving the Control key (Control-Q for quit may be disabled!)\n"
<< " -autoslot <1|0> Automatically switch to next save slot when state saving\n"

View File

@ -168,7 +168,7 @@ void InputDialog::addDevicePortTab(const GUI::Font& font)
myDPaddleSpeed = new SliderWidget(myTab, font, xpos, ypos, pwidth, lineHeight,
"Digital paddle sensitivity: ",
lwidth, kDPSpeedChanged);
myDPaddleSpeed->setMinValue(1); myDPaddleSpeed->setMaxValue(10);
myDPaddleSpeed->setMinValue(1); myDPaddleSpeed->setMaxValue(20);
xpos += myDPaddleSpeed->getWidth() + 5;
myDPaddleLabel = new StaticTextWidget(myTab, font, xpos, ypos+1, 24, lineHeight,
"", kTextAlignLeft);
@ -180,7 +180,7 @@ void InputDialog::addDevicePortTab(const GUI::Font& font)
myMPaddleSpeed = new SliderWidget(myTab, font, xpos, ypos, pwidth, lineHeight,
"Mouse paddle sensitivity: ",
lwidth, kMPSpeedChanged);
myMPaddleSpeed->setMinValue(1); myMPaddleSpeed->setMaxValue(15);
myMPaddleSpeed->setMinValue(1); myMPaddleSpeed->setMaxValue(20);
xpos += myMPaddleSpeed->getWidth() + 5;
myMPaddleLabel = new StaticTextWidget(myTab, font, xpos, ypos+1, 24, lineHeight,
"", kTextAlignLeft);
@ -328,10 +328,10 @@ void InputDialog::setDefaults()
myDeadzoneLabel->setValue(3200);
// Paddle speed (digital and mouse)
myDPaddleSpeed->setValue(5);
myDPaddleLabel->setLabel("5");
myMPaddleSpeed->setValue(6);
myMPaddleLabel->setLabel("6");
myDPaddleSpeed->setValue(10);
myDPaddleLabel->setLabel("10");
myMPaddleSpeed->setValue(10);
myMPaddleLabel->setLabel("10");
// AtariVox serial port
myAVoxPort->setText("");