Updated PointingDevice (trakball and friends)

- changed from templates back to inheritance (sorry DirtyHairy :))
 - added 'tsense' commandline argument and associated UI
 - updated docs and screenshots for new functionality
This commit is contained in:
Stephen Anthony 2017-08-02 16:07:02 -02:30
parent ace146fe52
commit d22ed691b5
17 changed files with 311 additions and 200 deletions

View File

@ -16,6 +16,8 @@
* Improved emulation of Trakball controller, eliminating bias in left/ * Improved emulation of Trakball controller, eliminating bias in left/
right directions. Thanks to Thomas Jentzsch for the idea and code. right directions. Thanks to Thomas Jentzsch for the idea and code.
Related to this, added 'tsense' commandline argument and associated
UI item, to allow changing sensitivity of mouse trackball emulation.
* Fixed an annoying bug in Linux, where Alt-Tab'ing out of a window and * Fixed an annoying bug in Linux, where Alt-Tab'ing out of a window and
then back again would pass a 'Tab' key event to the app, which in then back again would pass a 'Tab' key event to the app, which in

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.0 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

After

Width:  |  Height:  |  Size: 7.8 KiB

View File

@ -2703,6 +2703,7 @@
<tr><td>Joy deadzone size</td><td>Deadzone area for axes on joysticks/gamepads</td><td>-joydeadzone</td></tr> <tr><td>Joy deadzone size</td><td>Deadzone area for axes on joysticks/gamepads</td><td>-joydeadzone</td></tr>
<tr><td>Digital paddle sensitivity</td><td>Sensitivity used when emulating a paddle using a digital device</td><td>-dsense</td></tr> <tr><td>Digital paddle sensitivity</td><td>Sensitivity used when emulating a paddle using a digital device</td><td>-dsense</td></tr>
<tr><td>Mouse paddle sensitivity</td><td>Sensitivity used when emulating a paddle using a mouse</td><td>-msense</td></tr> <tr><td>Mouse paddle sensitivity</td><td>Sensitivity used when emulating a paddle using a mouse</td><td>-msense</td></tr>
<tr><td>Trackball sensitivity</td><td>Sensitivity used when emulating a trackball device using a mouse</td><td>-tsense</td></tr>
<tr><td>Allow all 4 ...</td><td>Allow all 4 joystick directions to be pressed simultaneously</td><td>-joyallow4</td></tr> <tr><td>Allow all 4 ...</td><td>Allow all 4 joystick directions to be pressed simultaneously</td><td>-joyallow4</td></tr>
<tr><td>Grab mouse ...</td><td>Keep mouse in window in emulation mode</td><td>-grabmouse</td></tr> <tr><td>Grab mouse ...</td><td>Keep mouse in window in emulation mode</td><td>-grabmouse</td></tr>
<tr><td>Use Control key combos</td><td>Enable using Control key in keyboard actions</td><td>-ctrlcombo</td></tr> <tr><td>Use Control key combos</td><td>Enable using Control key in keyboard actions</td><td>-ctrlcombo</td></tr>

View File

@ -20,24 +20,31 @@
#include "PointingDevice.hxx" #include "PointingDevice.hxx"
namespace { class AmigaMouse : public PointingDevice
{
public:
/**
Create a new Amiga Mouse controller plugged into the specified jack
class AmigaMouseHelper { @param jack The jack the controller is plugged into
@param event The event object to use for events
@param system The system using this controller
*/
AmigaMouse(Jack jack, const Event& event, const System& system)
: PointingDevice(jack, event, system, Controller::AmigaMouse,
trackballSensitivity) { }
virtual ~AmigaMouse() = default;
public: protected:
static uInt8 ioPortA(uInt8 countH, uInt8 countV, uInt8 left, uInt8 down) { uInt8 ioPortA(uInt8 countH, uInt8 countV, uInt8, uInt8) override
static constexpr uInt32 ourTableH[4] = { 0x00, 0x10, 0x50, 0x40 }; {
static constexpr uInt32 ourTableV[4] = { 0x00, 0x80, 0xa0, 0x20 }; static constexpr uInt32 ourTableH[4] = { 0x00, 0x80, 0xa0, 0x20 };
static constexpr uInt32 ourTableV[4] = { 0x00, 0x10, 0x50, 0x40 };
return ourTableV[countV] | ourTableH[countH]; return ourTableH[countH] | ourTableV[countV];
} }
public: static constexpr float trackballSensitivity = 0.8;
static constexpr Controller::Type controllerType = Controller::AmigaMouse; };
static constexpr double trackballSensitivity = 0.8; // TODO: make configurable
};
}
using AmigaMouse = PointingDevice<AmigaMouseHelper>;
#endif // AMIGAMOUSE_HXX #endif // AMIGAMOUSE_HXX

View File

@ -20,24 +20,31 @@
#include "PointingDevice.hxx" #include "PointingDevice.hxx"
namespace { class AtariMouse : public PointingDevice
{
public:
/**
Create a new Atari Mouse controller plugged into the specified jack
class AtariMouseHelper { @param jack The jack the controller is plugged into
@param event The event object to use for events
@param system The system using this controller
*/
AtariMouse(Jack jack, const Event& event, const System& system)
: PointingDevice(jack, event, system, Controller::AtariMouse,
trackballSensitivity) { }
virtual ~AtariMouse() = default;
public: protected:
static uInt8 ioPortA(uInt8 countH, uInt8 countV, uInt8 left, uInt8 down) { uInt8 ioPortA(uInt8 countH, uInt8 countV, uInt8, uInt8) override
static constexpr uInt32 ourTableH[4] = { 0x00, 0x80, 0xc0, 0x40 }; {
static constexpr uInt32 ourTableV[4] = { 0x00, 0x10, 0x30, 0x20 }; static constexpr uInt32 ourTableH[4] = { 0x00, 0x10, 0x30, 0x20 };
static constexpr uInt32 ourTableV[4] = { 0x00, 0x80, 0xc0, 0x40 };
return ourTableV[countV] | ourTableH[countH]; return ourTableH[countH] | ourTableV[countV];
} }
public: static constexpr float trackballSensitivity = 0.8;
static constexpr Controller::Type controllerType = Controller::AtariMouse; };
static constexpr double trackballSensitivity = 0.8; // TODO: make configurable
};
}
using AtariMouse = PointingDevice<AtariMouseHelper>;
#endif // ATARIMOUSE_HXX #endif // ATARIMOUSE_HXX

View File

@ -32,6 +32,7 @@
#include "OSystem.hxx" #include "OSystem.hxx"
#include "Joystick.hxx" #include "Joystick.hxx"
#include "Paddles.hxx" #include "Paddles.hxx"
#include "PointingDevice.hxx"
#include "PropsSet.hxx" #include "PropsSet.hxx"
#include "ListWidget.hxx" #include "ListWidget.hxx"
#include "ScrollBarWidget.hxx" #include "ScrollBarWidget.hxx"
@ -95,6 +96,7 @@ void EventHandler::initialize()
Joystick::setDeadZone(myOSystem.settings().getInt("joydeadzone")); Joystick::setDeadZone(myOSystem.settings().getInt("joydeadzone"));
Paddles::setDigitalSensitivity(myOSystem.settings().getInt("dsense")); Paddles::setDigitalSensitivity(myOSystem.settings().getInt("dsense"));
Paddles::setMouseSensitivity(myOSystem.settings().getInt("msense")); Paddles::setMouseSensitivity(myOSystem.settings().getInt("msense"));
PointingDevice::setSensitivity(myOSystem.settings().getInt("tsense"));
// Set quick select delay when typing characters in listwidgets // Set quick select delay when typing characters in listwidgets
ListWidget::setQuickSelectDelay(myOSystem.settings().getInt("listdelay")); ListWidget::setQuickSelectDelay(myOSystem.settings().getInt("listdelay"));

View File

@ -127,12 +127,12 @@ class Paddles : public Controller
// Range of values over which digital and mouse movement is scaled // Range of values over which digital and mouse movement is scaled
// to paddle resistance // to paddle resistance
static const int TRIGMIN = 1; static constexpr int TRIGMIN = 1;
static const int TRIGMAX = 4096; static constexpr int TRIGMAX = 4096;
static int TRIGRANGE; // This one is variable for the upper range static int TRIGRANGE; // This one is variable for the upper range
static const int MAX_DIGITAL_SENSE = 20; static constexpr int MAX_DIGITAL_SENSE = 20;
static const int MAX_MOUSE_SENSE = 20; static constexpr int MAX_MOUSE_SENSE = 20;
static int DIGITAL_SENSITIVITY, DIGITAL_DISTANCE; static int DIGITAL_SENSITIVITY, DIGITAL_DISTANCE;
static int MOUSE_SENSITIVITY; static int MOUSE_SENSITIVITY;

View File

@ -0,0 +1,156 @@
//============================================================================
//
// 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-2017 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 "Control.hxx"
#include "Event.hxx"
#include "System.hxx"
#include "TIA.hxx"
#include "PointingDevice.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PointingDevice::PointingDevice(Jack jack, const Event& event,
const System& system, Controller::Type type,
float sensitivity)
: Controller(jack, event, system, type),
mySensitivity(sensitivity),
myHCounterRemainder(0.0), myVCounterRemainder(0.0),
myTrackBallLinesH(1), myTrackBallLinesV(1),
myTrackBallLeft(false), myTrackBallDown(false),
myCountH(0), myCountV(0),
myScanCountH(0), myScanCountV(0),
myFirstScanOffsetH(0), myFirstScanOffsetV(0),
myMouseEnabled(false)
{
// The code in ::read() is set up to always return IOPortA values in
// the lower 4 bits data value
// As such, the jack type (left or right) isn't necessary here
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 PointingDevice::read()
{
int scanline = mySystem.tia().scanlines();
// Loop over all missed changes
while(myScanCountH < scanline)
{
if(myTrackBallLeft) myCountH--;
else myCountH++;
// Define scanline of next change
myScanCountH += myTrackBallLinesH;
}
// Loop over all missed changes
while(myScanCountV < scanline)
{
if(myTrackBallDown) myCountV--;
else myCountV++;
// Define scanline of next change
myScanCountV += myTrackBallLinesV;
}
myCountH &= 0x03;
myCountV &= 0x03;
uInt8 portA = ioPortA(myCountH, myCountV, myTrackBallLeft, myTrackBallDown);
myDigitalPinState[One] = portA & 0x10;
myDigitalPinState[Two] = portA & 0x20;
myDigitalPinState[Three] = portA & 0x40;
myDigitalPinState[Four] = portA & 0x80;
return (portA >> 4);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PointingDevice::update()
{
if(!myMouseEnabled)
return;
// Update horizontal direction
updateDirection( myEvent.get(Event::MouseAxisXValue), myHCounterRemainder,
myTrackBallLeft, myTrackBallLinesH, myScanCountH, myFirstScanOffsetH);
// Update vertical direction
updateDirection(-myEvent.get(Event::MouseAxisYValue), myVCounterRemainder,
myTrackBallDown, myTrackBallLinesV, myScanCountV, myFirstScanOffsetV);
// Get mouse button state
myDigitalPinState[Six] = (myEvent.get(Event::MouseButtonLeftValue) == 0) &&
(myEvent.get(Event::MouseButtonRightValue) == 0);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool PointingDevice::setMouseControl(
Controller::Type xtype, int xid, Controller::Type ytype, int yid)
{
// Currently, the various trakball controllers take full control of the
// mouse, and use both mouse buttons for the single fire button
// As well, there's no separate setting for x and y axis, so any
// combination of Controller and id is valid
myMouseEnabled = (xtype == myType || ytype == myType) &&
(xid != -1 || yid != -1);
return true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PointingDevice::setSensitivity(int sensitivity)
{
BSPF::clamp(sensitivity, 1, 20, 10);
TB_SENSITIVITY = sensitivity / 10.0;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PointingDevice::updateDirection(const int& counter, float& counterRemainder,
bool& trackBallDir, int& trackBallLines, int& scanCount, int& firstScanOffset)
{
// Apply sensitivity and calculate remainder
float fTrackBallCount = counter * mySensitivity * TB_SENSITIVITY + counterRemainder;
int trackBallCount = std::lround(fTrackBallCount);
counterRemainder = fTrackBallCount - trackBallCount;
if(trackBallCount)
{
trackBallDir = (trackBallCount > 0);
trackBallCount = abs(trackBallCount);
// Calculate lines to wait between sending new horz/vert values
trackBallLines = mySystem.tia().scanlinesLastFrame() / trackBallCount;
// Set lower limit in case of (unrealistic) ultra fast mouse movements
if (trackBallLines == 0) trackBallLines = 1;
// Define scanline of first change
scanCount = (trackBallLines * firstScanOffset) >> 12;
}
else
{
// Prevent any change
scanCount = INT_MAX;
// Define offset factor for first change, move randomly forward by up to 1/8th
firstScanOffset = (((firstScanOffset << 3) + rand() %
(1 << 12)) >> 3) & ((1 << 12) - 1);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
float PointingDevice::TB_SENSITIVITY = 1.0;

View File

@ -18,22 +18,23 @@
#ifndef POINTING_DEVICE_HXX #ifndef POINTING_DEVICE_HXX
#define POINTING_DEVICE_HXX #define POINTING_DEVICE_HXX
class Controller;
class Event;
#include "bspf.hxx" #include "bspf.hxx"
#include "Control.hxx"
#include "Event.hxx"
/** /**
Common controller class for pointing devices (Atari Mouse, Amiga Mouse, Trak-Ball) Common controller class for pointing devices (Atari Mouse, Amiga Mouse, Trak-Ball)
This code was heavily borrowed from z26. This code was heavily borrowed from z26.
@author Stephen Anthony, Thomas Jentzsch & z26 team @author Stephen Anthony, Thomas Jentzsch & z26 team
Template-ification by Christian Speckner
*/ */
template<class T>
class PointingDevice : public Controller class PointingDevice : public Controller
{ {
public: public:
PointingDevice(Jack jack, const Event& event, const System& system); PointingDevice(Jack jack, const Event& event,
const System& system, Controller::Type type,
float sensitivity);
virtual ~PointingDevice() = default; virtual ~PointingDevice() = default;
public: public:
@ -72,13 +73,28 @@ class PointingDevice : public Controller
bool setMouseControl(Controller::Type xtype, int xid, bool setMouseControl(Controller::Type xtype, int xid,
Controller::Type ytype, int yid) override; Controller::Type ytype, int yid) override;
/**
Sets the sensitivity for analog emulation of trackball movement
using a mouse.
@param sensitivity Value from 1 to 20, with larger values causing
more movement (10 represents the baseline)
*/
static void setSensitivity(int sensitivity);
protected:
// Each derived class must implement this, to determine how its
// IOPortA values are calculated
virtual uInt8 ioPortA(uInt8 countH, uInt8 countV, uInt8 left, uInt8 down) = 0;
private: private:
void updateDirection(const int& counter, double& counterRemainder, void updateDirection(const int& counter, float& counterRemainder,
bool& trackBallDir, int& trackBallLines, bool& trackBallDir, int& trackBallLines,
int& scanCount, int& firstScanOffset); int& scanCount, int& firstScanOffset);
private: private:
double myHCounterRemainder, myVCounterRemainder; // Mouse input to sensitivity emulation
float mySensitivity, myHCounterRemainder, myVCounterRemainder;
// How many lines to wait between sending new horz and vert values // How many lines to wait between sending new horz and vert values
int myTrackBallLinesH, myTrackBallLinesV; int myTrackBallLinesH, myTrackBallLinesV;
@ -101,143 +117,17 @@ class PointingDevice : public Controller
// Whether to use the mouse to emulate this controller // Whether to use the mouse to emulate this controller
bool myMouseEnabled; bool myMouseEnabled;
private: // User-defined sensitivity; adjustable since end-users may have different
// mouse speeds
static float TB_SENSITIVITY;
private:
// Following constructors and assignment operators not supported // Following constructors and assignment operators not supported
PointingDevice() = delete; PointingDevice() = delete;
PointingDevice(const PointingDevice<T>&) = delete; PointingDevice(const PointingDevice&) = delete;
PointingDevice(PointingDevice<T>&&) = delete; PointingDevice(PointingDevice&&) = delete;
PointingDevice& operator=(const PointingDevice<T>&) = delete; PointingDevice& operator=(const PointingDevice&) = delete;
PointingDevice& operator=(PointingDevice<T>&&) = delete; PointingDevice& operator=(PointingDevice&&) = delete;
}; };
// ############################################################################
// Implementation
// ############################################################################
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
template<class T>
PointingDevice<T>::PointingDevice(Jack jack, const Event& event, const System& system)
: Controller(jack, event, system, T::controllerType),
myHCounterRemainder(0.0), myVCounterRemainder(0.0),
myTrackBallLinesH(1), myTrackBallLinesV(1),
myTrackBallLeft(false), myTrackBallDown(false),
myCountH(0), myCountV(0),
myScanCountH(0), myScanCountV(0),
myFirstScanOffsetH(0), myFirstScanOffsetV(0),
myMouseEnabled(false)
{
// The code in ::read() is set up to always return IOPortA values in
// the lower 4 bits data value
// As such, the jack type (left or right) isn't necessary here
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
template<class T>
uInt8 PointingDevice<T>::read()
{
int scanline = mySystem.tia().scanlines();
// Loop over all missed changes
while(myScanCountH < scanline)
{
if(myTrackBallLeft) myCountH--;
else myCountH++;
// Define scanline of next change
myScanCountH += myTrackBallLinesH;
}
// Loop over all missed changes
while(myScanCountV < scanline)
{
if(myTrackBallDown) myCountV--;
else myCountV++;
// Define scanline of next change
myScanCountV += myTrackBallLinesV;
}
myCountH &= 0x03;
myCountV &= 0x03;
uInt8 ioPortA = T::ioPortA(myCountV, myCountH, myTrackBallDown, myTrackBallLeft);
myDigitalPinState[One] = ioPortA & 0x10;
myDigitalPinState[Two] = ioPortA & 0x20;
myDigitalPinState[Three] = ioPortA & 0x40;
myDigitalPinState[Four] = ioPortA & 0x80;
return (ioPortA >> 4);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
template<class T>
void PointingDevice<T>::update()
{
if(!myMouseEnabled)
return;
// Update horizontal direction
updateDirection( myEvent.get(Event::MouseAxisXValue), myHCounterRemainder,
myTrackBallLeft, myTrackBallLinesH, myScanCountH, myFirstScanOffsetH);
// Update vertical direction
updateDirection(-myEvent.get(Event::MouseAxisYValue), myVCounterRemainder,
myTrackBallDown, myTrackBallLinesV, myScanCountV, myFirstScanOffsetV);
// Get mouse button state
myDigitalPinState[Six] = (myEvent.get(Event::MouseButtonLeftValue) == 0) &&
(myEvent.get(Event::MouseButtonRightValue) == 0);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
template<class T>
bool PointingDevice<T>::setMouseControl(
Controller::Type xtype, int xid, Controller::Type ytype, int yid)
{
// Currently, the various trakball controllers take full control of the
// mouse, and use both mouse buttons for the single fire button
// As well, there's no separate setting for x and y axis, so any
// combination of Controller and id is valid
myMouseEnabled = (xtype == myType || ytype == myType) &&
(xid != -1 || yid != -1);
return true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
template<class T>
void PointingDevice<T>::updateDirection(const int& counter, double& counterRemainder,
bool& trackBallDir, int& trackBallLines, int& scanCount, int& firstScanOffset)
{
// Apply sensitivity and calculate remainder
float fTrackBallCount = counter * T::trackballSensitivity + counterRemainder;
int trackBallCount = std::lround(fTrackBallCount);
counterRemainder = fTrackBallCount - trackBallCount;
if(trackBallCount)
{
trackBallDir = (trackBallCount > 0);
trackBallCount = abs(trackBallCount);
// Calculate lines to wait between sending new horz/vert values
trackBallLines = mySystem.tia().scanlinesLastFrame() / trackBallCount;
// Set lower limit in case of (unrealistic) ultra fast mouse movements
if (trackBallLines == 0) trackBallLines = 1;
// Define scanline of first change
scanCount = (trackBallLines * firstScanOffset) >> 12;
}
else
{
// Prevent any change
scanCount = INT_MAX;
// Define offset factor for first change, move randomly forward by up to 1/8th
firstScanOffset = (((firstScanOffset << 3) + rand() %
(1 << 12)) >> 3) & ((1 << 12) - 1);
}
}
#endif // POINTING_DEVICE_HXX #endif // POINTING_DEVICE_HXX

View File

@ -90,6 +90,7 @@ Settings::Settings(OSystem& osystem)
setInternal("cursor", "2"); setInternal("cursor", "2");
setInternal("dsense", "10"); setInternal("dsense", "10");
setInternal("msense", "10"); setInternal("msense", "10");
setInternal("tsense", "10");
setInternal("saport", "lr"); setInternal("saport", "lr");
setInternal("ctrlcombo", "true"); setInternal("ctrlcombo", "true");
@ -309,12 +310,16 @@ void Settings::validate()
setInternal("cursor", "2"); setInternal("cursor", "2");
i = getInt("dsense"); i = getInt("dsense");
if(i < 1) setInternal("dsense", "1"); if(i < 1 || i > 20)
else if(i > 20) setInternal("dsense", "10"); setInternal("dsense", "10");
i = getInt("msense"); i = getInt("msense");
if(i < 1) setInternal("msense", "1"); if(i < 1 || i > 20)
else if(i > 20) setInternal("msense", "15"); setInternal("msense", "10");
i = getInt("tsense");
if(i < 1 || i > 20)
setInternal("tsense", "10");
i = getInt("ssinterval"); i = getInt("ssinterval");
if(i < 1) setInternal("ssinterval", "2"); if(i < 1) setInternal("ssinterval", "2");
@ -413,6 +418,7 @@ void Settings::usage() const
<< " -cursor <0,1,2,3> Set cursor state in UI/emulation modes\n" << " -cursor <0,1,2,3> Set cursor state in UI/emulation modes\n"
<< " -dsense <number> Sensitivity of digital emulated paddle movement (1-20)\n" << " -dsense <number> Sensitivity of digital emulated paddle movement (1-20)\n"
<< " -msense <number> Sensitivity of mouse emulated paddle movement (1-20)\n" << " -msense <number> Sensitivity of mouse emulated paddle movement (1-20)\n"
<< " -tsense <number> Sensitivity of mouse emulated trackball movement (1-20)\n"
<< " -saport <lr|rl> How to assign virtual ports to multiple Stelladaptor/2600-daptors\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" << " -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" << " -autoslot <1|0> Automatically switch to next save slot when state saving\n"

View File

@ -20,24 +20,32 @@
#include "PointingDevice.hxx" #include "PointingDevice.hxx"
namespace { class TrakBall : public PointingDevice
{
public:
/**
Create a new trakball controller plugged into the specified jack
class TrakBallHelper { @param jack The jack the controller is plugged into
@param event The event object to use for events
@param system The system using this controller
*/
TrakBall(Jack jack, const Event& event, const System& system)
: PointingDevice(jack, event, system, Controller::TrakBall,
trackballSensitivity) { }
virtual ~TrakBall() = default;
public: protected:
static uInt8 ioPortA(uInt8 countH, uInt8 countV, uInt8 left, uInt8 down) { uInt8 ioPortA(uInt8 countH, uInt8 countV, uInt8 left, uInt8 down) override
static constexpr uInt32 ourTableH[2][2] = {{ 0x40, 0x00 }, { 0xc0, 0x80 }}; {
static constexpr uInt32 ourTableV[2][2] = {{ 0x00, 0x10 }, { 0x20, 0x30 }}; static constexpr uInt32 ourTableH[2][2] = {{ 0x00, 0x10 }, { 0x20, 0x30 }};
static constexpr uInt32 ourTableV[2][2] = {{ 0x40, 0x00 }, { 0xc0, 0x80 }};
return ourTableV[countV & 0x01][down] | ourTableH[countH & 0x01][left]; return ourTableH[countH & 0x01][left] | ourTableV[countV & 0x01][down];
} }
public: // 50% of Atari and Amiga mouse
static constexpr Controller::Type controllerType = Controller::TrakBall; static constexpr float trackballSensitivity = 0.4;
static constexpr double trackballSensitivity = 0.4; // 50% of Atari and Amiga mouse; TODO: make configurable };
};
}
using TrakBall = PointingDevice<TrakBallHelper>;
#endif // TRAKBALL_HXX #endif // TRAKBALL_HXX

View File

@ -67,6 +67,7 @@ MODULE_OBJS := \
src/emucore/MD5.o \ src/emucore/MD5.o \
src/emucore/OSystem.o \ src/emucore/OSystem.o \
src/emucore/Paddles.o \ src/emucore/Paddles.o \
src/emucore/PointingDevice.o \
src/emucore/Props.o \ src/emucore/Props.o \
src/emucore/PropsSet.o \ src/emucore/PropsSet.o \
src/emucore/SaveKey.o \ src/emucore/SaveKey.o \

View File

@ -20,6 +20,7 @@
#include "OSystem.hxx" #include "OSystem.hxx"
#include "Joystick.hxx" #include "Joystick.hxx"
#include "Paddles.hxx" #include "Paddles.hxx"
#include "PointingDevice.hxx"
#include "Settings.hxx" #include "Settings.hxx"
#include "EventMappingWidget.hxx" #include "EventMappingWidget.hxx"
#include "EditTextWidget.hxx" #include "EditTextWidget.hxx"
@ -45,7 +46,7 @@ InputDialog::InputDialog(OSystem& osystem, DialogContainer& parent,
// Set real dimensions // Set real dimensions
_w = std::min(50 * fontWidth + 10, max_w); _w = std::min(50 * fontWidth + 10, max_w);
_h = std::min(15 * (lineHeight + 4) + 14, max_h); _h = std::min(16 * (lineHeight + 4) + 14, max_h);
// The tab widget // The tab widget
xpos = 2; ypos = vBorder; xpos = 2; ypos = vBorder;
@ -164,8 +165,8 @@ void InputDialog::addDevicePortTab(const GUI::Font& font)
// Add paddle speed (digital emulation) // Add paddle speed (digital emulation)
xpos = 5; ypos += lineHeight + 4; xpos = 5; ypos += lineHeight + 4;
myDPaddleSpeed = new SliderWidget(myTab, font, xpos, ypos, pwidth, lineHeight, myDPaddleSpeed = new SliderWidget(myTab, font, xpos, ypos, pwidth, lineHeight,
"Digital paddle sensitivity ", "Digital paddle sensitivity ",
lwidth, kDPSpeedChanged); lwidth, kDPSpeedChanged);
myDPaddleSpeed->setMinValue(1); myDPaddleSpeed->setMaxValue(20); myDPaddleSpeed->setMinValue(1); myDPaddleSpeed->setMaxValue(20);
xpos += myDPaddleSpeed->getWidth() + 5; xpos += myDPaddleSpeed->getWidth() + 5;
myDPaddleLabel = new StaticTextWidget(myTab, font, xpos, ypos+1, 24, lineHeight, myDPaddleLabel = new StaticTextWidget(myTab, font, xpos, ypos+1, 24, lineHeight,
@ -176,8 +177,8 @@ void InputDialog::addDevicePortTab(const GUI::Font& font)
// Add paddle speed (mouse emulation) // Add paddle speed (mouse emulation)
xpos = 5; ypos += lineHeight + 4; xpos = 5; ypos += lineHeight + 4;
myMPaddleSpeed = new SliderWidget(myTab, font, xpos, ypos, pwidth, lineHeight, myMPaddleSpeed = new SliderWidget(myTab, font, xpos, ypos, pwidth, lineHeight,
"Mouse paddle sensitivity ", "Mouse paddle sensitivity ",
lwidth, kMPSpeedChanged); lwidth, kMPSpeedChanged);
myMPaddleSpeed->setMinValue(1); myMPaddleSpeed->setMaxValue(20); myMPaddleSpeed->setMinValue(1); myMPaddleSpeed->setMaxValue(20);
xpos += myMPaddleSpeed->getWidth() + 5; xpos += myMPaddleSpeed->getWidth() + 5;
myMPaddleLabel = new StaticTextWidget(myTab, font, xpos, ypos+1, 24, lineHeight, myMPaddleLabel = new StaticTextWidget(myTab, font, xpos, ypos+1, 24, lineHeight,
@ -185,6 +186,18 @@ void InputDialog::addDevicePortTab(const GUI::Font& font)
myMPaddleSpeed->setFlags(WIDGET_CLEARBG); myMPaddleSpeed->setFlags(WIDGET_CLEARBG);
wid.push_back(myMPaddleSpeed); wid.push_back(myMPaddleSpeed);
// Add trackball speed
xpos = 5; ypos += lineHeight + 4;
myTrackBallSpeed = new SliderWidget(myTab, font, xpos, ypos, pwidth, lineHeight,
"Trackball sensitivity ",
lwidth, kTBSpeedChanged);
myTrackBallSpeed->setMinValue(1); myTrackBallSpeed->setMaxValue(20);
xpos += myTrackBallSpeed->getWidth() + 5;
myTrackBallLabel = new StaticTextWidget(myTab, font, xpos, ypos+1, 24, lineHeight,
"", kTextAlignLeft);
myTrackBallSpeed->setFlags(WIDGET_CLEARBG);
wid.push_back(myTrackBallSpeed);
// Add 'allow all 4 directions' for joystick // Add 'allow all 4 directions' for joystick
xpos = 10; ypos += lineHeight + 12; xpos = 10; ypos += lineHeight + 12;
myAllowAll4 = new CheckboxWidget(myTab, font, xpos, ypos, myAllowAll4 = new CheckboxWidget(myTab, font, xpos, ypos,
@ -240,6 +253,10 @@ void InputDialog::loadConfig()
myMPaddleSpeed->setValue(instance().settings().getInt("msense")); myMPaddleSpeed->setValue(instance().settings().getInt("msense"));
myMPaddleLabel->setLabel(instance().settings().getString("msense")); myMPaddleLabel->setLabel(instance().settings().getString("msense"));
// Trackball speed
myTrackBallSpeed->setValue(instance().settings().getInt("tsense"));
myTrackBallLabel->setLabel(instance().settings().getString("tsense"));
// AtariVox serial port // AtariVox serial port
myAVoxPort->setText(instance().settings().getString("avoxport")); myAVoxPort->setText(instance().settings().getString("avoxport"));
@ -279,6 +296,11 @@ void InputDialog::saveConfig()
instance().settings().setValue("msense", sensitivity); instance().settings().setValue("msense", sensitivity);
Paddles::setMouseSensitivity(sensitivity); Paddles::setMouseSensitivity(sensitivity);
// Trackball speed
sensitivity = myTrackBallSpeed->getValue();
instance().settings().setValue("tsense", sensitivity);
PointingDevice::setSensitivity(sensitivity);
// AtariVox serial port // AtariVox serial port
instance().settings().setValue("avoxport", myAVoxPort->getText()); instance().settings().setValue("avoxport", myAVoxPort->getText());
@ -330,6 +352,8 @@ void InputDialog::setDefaults()
myDPaddleLabel->setLabel("10"); myDPaddleLabel->setLabel("10");
myMPaddleSpeed->setValue(10); myMPaddleSpeed->setValue(10);
myMPaddleLabel->setLabel("10"); myMPaddleLabel->setLabel("10");
myTrackBallSpeed->setValue(10);
myTrackBallLabel->setLabel("10");
// AtariVox serial port // AtariVox serial port
myAVoxPort->setText(""); myAVoxPort->setText("");
@ -433,6 +457,10 @@ void InputDialog::handleCommand(CommandSender* sender, int cmd,
myMPaddleLabel->setValue(myMPaddleSpeed->getValue()); myMPaddleLabel->setValue(myMPaddleSpeed->getValue());
break; break;
case kTBSpeedChanged:
myTrackBallLabel->setValue(myTrackBallSpeed->getValue());
break;
case kDBButtonPressed: case kDBButtonPressed:
if(!myJoyDialog) if(!myJoyDialog)
myJoyDialog = make_unique<JoystickDialog> myJoyDialog = make_unique<JoystickDialog>

View File

@ -57,6 +57,7 @@ class InputDialog : public Dialog
kDeadzoneChanged = 'DZch', kDeadzoneChanged = 'DZch',
kDPSpeedChanged = 'PDch', kDPSpeedChanged = 'PDch',
kMPSpeedChanged = 'PMch', kMPSpeedChanged = 'PMch',
kTBSpeedChanged = 'TBch',
kDBButtonPressed = 'DBbp' kDBButtonPressed = 'DBbp'
}; };
@ -75,8 +76,10 @@ class InputDialog : public Dialog
StaticTextWidget* myDeadzoneLabel; StaticTextWidget* myDeadzoneLabel;
SliderWidget* myDPaddleSpeed; SliderWidget* myDPaddleSpeed;
SliderWidget* myMPaddleSpeed; SliderWidget* myMPaddleSpeed;
SliderWidget* myTrackBallSpeed;
StaticTextWidget* myDPaddleLabel; StaticTextWidget* myDPaddleLabel;
StaticTextWidget* myMPaddleLabel; StaticTextWidget* myMPaddleLabel;
StaticTextWidget* myTrackBallLabel;
CheckboxWidget* myAllowAll4; CheckboxWidget* myAllowAll4;
CheckboxWidget* myGrabMouse; CheckboxWidget* myGrabMouse;
CheckboxWidget* myCtrlCombo; CheckboxWidget* myCtrlCombo;