mirror of https://github.com/stella-emu/stella.git
Further improvements to trakball handling by Thomas Jentzsch.
This commit is contained in:
parent
6e4503f762
commit
87282e6707
|
@ -23,12 +23,11 @@
|
||||||
#include "Event.hxx"
|
#include "Event.hxx"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Common controller class for pointing devices (Atari Mouse, Amiga Mouse, TrakBall)
|
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 & z26 team
|
@author Stephen Anthony, Thomas Jentzsch & z26 team
|
||||||
Template-ification by Christian Speckner, based on ideas by
|
Template-ification by Christian Speckner
|
||||||
Thomas Jentzsch
|
|
||||||
*/
|
*/
|
||||||
template<class T>
|
template<class T>
|
||||||
class PointingDevice : public Controller
|
class PointingDevice : public Controller
|
||||||
|
@ -74,21 +73,31 @@ class PointingDevice : public Controller
|
||||||
Controller::Type ytype, int yid) override;
|
Controller::Type ytype, int yid) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float myHCounterRemainder, myVCounterRemainder;
|
void updateDirection(const int& counter, double& counterRemainder,
|
||||||
|
bool& trackBallDir, int& trackBallLines,
|
||||||
|
int& scanCount, int& firstScanOffset);
|
||||||
|
|
||||||
|
private:
|
||||||
|
double 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 myTrakBallLinesH, myTrakBallLinesV;
|
int myTrackBallLinesH, myTrackBallLinesV;
|
||||||
|
|
||||||
// Was TrakBall moved left or moved right instead
|
// Was TrackBall moved left or moved right instead
|
||||||
uInt8 myTrakBallLeft;
|
bool myTrackBallLeft;
|
||||||
|
|
||||||
// Was TrakBall moved down or moved up instead
|
// Was TrackBall moved down or moved up instead
|
||||||
uInt8 myTrakBallDown;
|
bool myTrackBallDown;
|
||||||
|
|
||||||
// Counter to iterate through the gray codes
|
// Counter to iterate through the gray codes
|
||||||
uInt8 myCountH, myCountV;
|
uInt8 myCountH, myCountV;
|
||||||
|
|
||||||
|
// Next scanline for change
|
||||||
int myScanCountH, myScanCountV;
|
int myScanCountH, myScanCountV;
|
||||||
|
|
||||||
|
// Offset factor for first scanline, 0..(1 << 12 - 1)
|
||||||
|
int myFirstScanOffsetH, myFirstScanOffsetV;
|
||||||
|
|
||||||
// Whether to use the mouse to emulate this controller
|
// Whether to use the mouse to emulate this controller
|
||||||
bool myMouseEnabled;
|
bool myMouseEnabled;
|
||||||
|
|
||||||
|
@ -110,12 +119,12 @@ class PointingDevice : public Controller
|
||||||
template<class T>
|
template<class T>
|
||||||
PointingDevice<T>::PointingDevice(Jack jack, const Event& event, const System& system)
|
PointingDevice<T>::PointingDevice(Jack jack, const Event& event, const System& system)
|
||||||
: Controller(jack, event, system, T::controllerType),
|
: Controller(jack, event, system, T::controllerType),
|
||||||
myHCounterRemainder(0.0),
|
myHCounterRemainder(0.0), myVCounterRemainder(0.0),
|
||||||
myVCounterRemainder(0.0),
|
myTrackBallLinesH(1), myTrackBallLinesV(1),
|
||||||
myTrakBallLinesH(1), myTrakBallLinesV(1),
|
myTrackBallLeft(false), myTrackBallDown(false),
|
||||||
myTrakBallLeft(0), myTrakBallDown(0),
|
|
||||||
myCountH(0), myCountV(0),
|
myCountH(0), myCountV(0),
|
||||||
myScanCountH(0), myScanCountV(0),
|
myScanCountH(0), myScanCountV(0),
|
||||||
|
myFirstScanOffsetH(0), myFirstScanOffsetV(0),
|
||||||
myMouseEnabled(false)
|
myMouseEnabled(false)
|
||||||
{
|
{
|
||||||
// The code in ::read() is set up to always return IOPortA values in
|
// The code in ::read() is set up to always return IOPortA values in
|
||||||
|
@ -132,27 +141,27 @@ uInt8 PointingDevice<T>::read()
|
||||||
// Loop over all missed changes
|
// Loop over all missed changes
|
||||||
while(myScanCountH < scanline)
|
while(myScanCountH < scanline)
|
||||||
{
|
{
|
||||||
if(myTrakBallLeft) myCountH--;
|
if(myTrackBallLeft) myCountH--;
|
||||||
else myCountH++;
|
else myCountH++;
|
||||||
|
|
||||||
// Define scanline of next change
|
// Define scanline of next change
|
||||||
myScanCountH += myTrakBallLinesH;
|
myScanCountH += myTrackBallLinesH;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loop over all missed changes
|
// Loop over all missed changes
|
||||||
while(myScanCountV < scanline)
|
while(myScanCountV < scanline)
|
||||||
{
|
{
|
||||||
if(myTrakBallDown) myCountV--;
|
if(myTrackBallDown) myCountV--;
|
||||||
else myCountV++;
|
else myCountV++;
|
||||||
|
|
||||||
// Define scanline of next change
|
// Define scanline of next change
|
||||||
myScanCountV += myTrakBallLinesV;
|
myScanCountV += myTrackBallLinesV;
|
||||||
}
|
}
|
||||||
|
|
||||||
myCountH &= 0x03;
|
myCountH &= 0x03;
|
||||||
myCountV &= 0x03;
|
myCountV &= 0x03;
|
||||||
|
|
||||||
uInt8 ioPortA = T::ioPortA(myCountV, myCountH, myTrakBallDown, myTrakBallLeft);
|
uInt8 ioPortA = T::ioPortA(myCountV, myCountH, myTrackBallDown, myTrackBallLeft);
|
||||||
|
|
||||||
myDigitalPinState[One] = ioPortA & 0x10;
|
myDigitalPinState[One] = ioPortA & 0x10;
|
||||||
myDigitalPinState[Two] = ioPortA & 0x20;
|
myDigitalPinState[Two] = ioPortA & 0x20;
|
||||||
|
@ -169,61 +178,16 @@ void PointingDevice<T>::update()
|
||||||
if(!myMouseEnabled)
|
if(!myMouseEnabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Get the current mouse position
|
// Update horizontal direction
|
||||||
int hCounter = myEvent.get(Event::MouseAxisXValue);
|
updateDirection( myEvent.get(Event::MouseAxisXValue), myHCounterRemainder,
|
||||||
int vCounter = myEvent.get(Event::MouseAxisYValue);
|
myTrackBallLeft, myTrackBallLinesH, myScanCountH, myFirstScanOffsetH);
|
||||||
|
|
||||||
// Apply sensitivity and calculate remainders
|
// Update vertical direction
|
||||||
float fTrakBallCountH = hCounter * T::trackballSensitivity + myHCounterRemainder;
|
updateDirection(-myEvent.get(Event::MouseAxisYValue), myVCounterRemainder,
|
||||||
int trakBallCountH = std::lround(fTrakBallCountH);
|
myTrackBallDown, myTrackBallLinesV, myScanCountV, myFirstScanOffsetV);
|
||||||
myHCounterRemainder = fTrakBallCountH - trakBallCountH;
|
|
||||||
|
|
||||||
float fTrakBallCountV = vCounter * T::trackballSensitivity + myVCounterRemainder;
|
|
||||||
int trakBallCountV = std::lround(fTrakBallCountV);
|
|
||||||
myVCounterRemainder = fTrakBallCountV - trakBallCountV;
|
|
||||||
|
|
||||||
if(trakBallCountH)
|
|
||||||
{
|
|
||||||
myTrakBallLeft = (trakBallCountH < 0) ? 0 : 1;
|
|
||||||
trakBallCountH = abs(trakBallCountH);
|
|
||||||
|
|
||||||
// Calculate lines to wait between sending new horz values
|
|
||||||
myTrakBallLinesH = mySystem.tia().scanlinesLastFrame() / trakBallCountH;
|
|
||||||
|
|
||||||
// Set lower limit in case of (unrealistic) ultra fast mouse movements
|
|
||||||
if (myTrakBallLinesH == 0) myTrakBallLinesH = 1;
|
|
||||||
|
|
||||||
// Define random scanline of first change
|
|
||||||
myScanCountH = rand() % myTrakBallLinesH;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Prevent any change
|
|
||||||
myScanCountH = INT_MAX;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(trakBallCountV)
|
|
||||||
{
|
|
||||||
myTrakBallDown = (trakBallCountV < 0) ? 1 : 0;
|
|
||||||
trakBallCountV = abs(trakBallCountV);
|
|
||||||
|
|
||||||
// Calculate lines to wait between sending new vert values
|
|
||||||
myTrakBallLinesV = mySystem.tia().scanlinesLastFrame() / trakBallCountV;
|
|
||||||
|
|
||||||
// Set lower limit in case of (unrealistic) ultra fast mouse movements
|
|
||||||
if (myTrakBallLinesV == 0) myTrakBallLinesV = 1;
|
|
||||||
|
|
||||||
// Define random scanline of first change
|
|
||||||
myScanCountV = rand() % myTrakBallLinesV;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Prevent any change
|
|
||||||
myScanCountV = INT_MAX;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get mouse button state
|
// Get mouse button state
|
||||||
myDigitalPinState[Six] = (myEvent.get(Event::MouseButtonLeftValue) == 0) &&
|
myDigitalPinState[Six] = (myEvent.get(Event::MouseButtonLeftValue) == 0) &&
|
||||||
(myEvent.get(Event::MouseButtonRightValue) == 0);
|
(myEvent.get(Event::MouseButtonRightValue) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,4 +205,39 @@ bool PointingDevice<T>::setMouseControl(
|
||||||
return true;
|
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
|
||||||
|
|
Loading…
Reference in New Issue