mirror of https://github.com/stella-emu/stella.git
Refactor pointing devices, include Thomas' patch for movement inconsistencies.
This commit is contained in:
parent
aebe8fabc6
commit
218da3576c
|
@ -1,122 +0,0 @@
|
|||
//============================================================================
|
||||
//
|
||||
// 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 "Event.hxx"
|
||||
#include "System.hxx"
|
||||
#include "TIA.hxx"
|
||||
#include "AmigaMouse.hxx"
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
AmigaMouse::AmigaMouse(Jack jack, const Event& event, const System& system)
|
||||
: Controller(jack, event, system, Controller::AmigaMouse),
|
||||
myHCounter(0),
|
||||
myVCounter(0),
|
||||
myMouseEnabled(false)
|
||||
{
|
||||
// This 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
|
||||
|
||||
myTrakBallCountH = myTrakBallCountV = 0;
|
||||
myTrakBallLinesH = myTrakBallLinesV = 1;
|
||||
|
||||
myTrakBallLeft = myTrakBallDown = myScanCountV = myScanCountH =
|
||||
myCountV = myCountH = 0;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt8 AmigaMouse::read()
|
||||
{
|
||||
int scanline = mySystem.tia().scanlines();
|
||||
|
||||
if(myScanCountV > scanline) myScanCountV = 0;
|
||||
if(myScanCountH > scanline) myScanCountH = 0;
|
||||
while((myScanCountV + myTrakBallLinesV) < scanline)
|
||||
{
|
||||
if(myTrakBallCountV)
|
||||
{
|
||||
if(myTrakBallDown) myCountV--;
|
||||
else myCountV++;
|
||||
myTrakBallCountV--;
|
||||
}
|
||||
myScanCountV += myTrakBallLinesV;
|
||||
}
|
||||
|
||||
while((myScanCountH + myTrakBallLinesH) < scanline)
|
||||
{
|
||||
if(myTrakBallCountH)
|
||||
{
|
||||
if(myTrakBallLeft) myCountH--;
|
||||
else myCountH++;
|
||||
myTrakBallCountH--;
|
||||
}
|
||||
myScanCountH += myTrakBallLinesH;
|
||||
}
|
||||
|
||||
myCountV &= 0x03;
|
||||
myCountH &= 0x03;
|
||||
|
||||
static constexpr uInt32 ourTableH[4] = { 0x00, 0x10, 0x50, 0x40 };
|
||||
static constexpr uInt32 ourTableV[4] = { 0x00, 0x80, 0xa0, 0x20 };
|
||||
uInt8 IOPortA = ourTableV[myCountV] | ourTableH[myCountH];
|
||||
|
||||
myDigitalPinState[One] = IOPortA & 0x10;
|
||||
myDigitalPinState[Two] = IOPortA & 0x20;
|
||||
myDigitalPinState[Three] = IOPortA & 0x40;
|
||||
myDigitalPinState[Four] = IOPortA & 0x80;
|
||||
|
||||
return (IOPortA >> 4);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void AmigaMouse::update()
|
||||
{
|
||||
if(!myMouseEnabled)
|
||||
return;
|
||||
|
||||
// Get the current mouse position
|
||||
myHCounter = myEvent.get(Event::MouseAxisXValue);
|
||||
myVCounter = myEvent.get(Event::MouseAxisYValue);
|
||||
|
||||
if(myVCounter < 0) myTrakBallLeft = 1;
|
||||
else myTrakBallLeft = 0;
|
||||
if(myHCounter < 0) myTrakBallDown = 0;
|
||||
else myTrakBallDown = 1;
|
||||
myTrakBallCountH = abs(myVCounter >> 1);
|
||||
myTrakBallCountV = abs(myHCounter >> 1);
|
||||
myTrakBallLinesH = mySystem.tia().height() / (myTrakBallCountH + 1);
|
||||
if(myTrakBallLinesH == 0) myTrakBallLinesH = 1;
|
||||
myTrakBallLinesV = mySystem.tia().height() / (myTrakBallCountV + 1);
|
||||
if(myTrakBallLinesV == 0) myTrakBallLinesV = 1;
|
||||
|
||||
// Get mouse button state
|
||||
myDigitalPinState[Six] = (myEvent.get(Event::MouseButtonLeftValue) == 0) &&
|
||||
(myEvent.get(Event::MouseButtonRightValue) == 0);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool AmigaMouse::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;
|
||||
}
|
|
@ -18,93 +18,28 @@
|
|||
#ifndef AMIGAMOUSE_HXX
|
||||
#define AMIGAMOUSE_HXX
|
||||
|
||||
#include "bspf.hxx"
|
||||
#include "Control.hxx"
|
||||
#include "Event.hxx"
|
||||
#include "PointingDevice.hxx"
|
||||
|
||||
/**
|
||||
Trakball-like controller emulating the original Amiga mouse.
|
||||
This code was heavily borrowed from z26.
|
||||
namespace {
|
||||
|
||||
@author Stephen Anthony & z26 team
|
||||
*/
|
||||
class AmigaMouse : public Controller
|
||||
{
|
||||
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);
|
||||
virtual ~AmigaMouse() = default;
|
||||
public:
|
||||
static uInt8 ioPortA(uInt8 countH, uInt8 countV, uInt8 left, uInt8 down) {
|
||||
static constexpr uInt32 ourTableH[4] = { 0x00, 0x10, 0x50, 0x40 };
|
||||
static constexpr uInt32 ourTableV[4] = { 0x00, 0x80, 0xa0, 0x20 };
|
||||
|
||||
public:
|
||||
using Controller::read;
|
||||
return ourTableV[countV] | ourTableH[countH];
|
||||
}
|
||||
|
||||
/**
|
||||
Read the entire state of all digital pins for this controller.
|
||||
Note that this method must use the lower 4 bits, and zero the upper bits.
|
||||
public:
|
||||
static constexpr Controller::Type controllerType = Controller::AmigaMouse;
|
||||
|
||||
@return The state of all digital pins
|
||||
*/
|
||||
uInt8 read() override;
|
||||
static constexpr uInt8 counterDivide = 2;
|
||||
};
|
||||
|
||||
/**
|
||||
Update the entire digital and analog pin state according to the
|
||||
events currently set.
|
||||
*/
|
||||
void update() override;
|
||||
}
|
||||
|
||||
/**
|
||||
Determines how this controller will treat values received from the
|
||||
X/Y axis and left/right buttons of the mouse. Since not all controllers
|
||||
use the mouse the same way (or at all), it's up to the specific class to
|
||||
decide how to use this data.
|
||||
typedef PointingDevice<AmigaMouseHelper> AmigaMouse;
|
||||
|
||||
In the current implementation, the left button is tied to the X axis,
|
||||
and the right one tied to the Y axis.
|
||||
|
||||
@param xtype The controller to use for x-axis data
|
||||
@param xid The controller ID to use for x-axis data (-1 for no id)
|
||||
@param ytype The controller to use for y-axis data
|
||||
@param yid The controller ID to use for y-axis data (-1 for no id)
|
||||
|
||||
@return Whether the controller supports using the mouse
|
||||
*/
|
||||
bool setMouseControl(Controller::Type xtype, int xid,
|
||||
Controller::Type ytype, int yid) override;
|
||||
|
||||
private:
|
||||
// Counter to iterate through the gray codes
|
||||
int myHCounter, myVCounter;
|
||||
|
||||
// How many new horizontal and vertical values this frame
|
||||
int myTrakBallCountH, myTrakBallCountV;
|
||||
|
||||
// How many lines to wait before sending new horz and vert val
|
||||
int myTrakBallLinesH, myTrakBallLinesV;
|
||||
|
||||
// Was TrakBall moved left or moved right instead
|
||||
int myTrakBallLeft;
|
||||
|
||||
// Was TrakBall moved down or moved up instead
|
||||
int myTrakBallDown;
|
||||
|
||||
int myScanCountH, myScanCountV, myCountH, myCountV;
|
||||
|
||||
// Whether to use the mouse to emulate this controller
|
||||
int myMouseEnabled;
|
||||
|
||||
private:
|
||||
// Following constructors and assignment operators not supported
|
||||
AmigaMouse() = delete;
|
||||
AmigaMouse(const AmigaMouse&) = delete;
|
||||
AmigaMouse(AmigaMouse&&) = delete;
|
||||
AmigaMouse& operator=(const AmigaMouse&) = delete;
|
||||
AmigaMouse& operator=(AmigaMouse&&) = delete;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif // AMIGAMOUSE_HXX
|
||||
|
|
|
@ -1,122 +0,0 @@
|
|||
//============================================================================
|
||||
//
|
||||
// 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 "Event.hxx"
|
||||
#include "System.hxx"
|
||||
#include "TIA.hxx"
|
||||
#include "AtariMouse.hxx"
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
AtariMouse::AtariMouse(Jack jack, const Event& event, const System& system)
|
||||
: Controller(jack, event, system, Controller::AtariMouse),
|
||||
myHCounter(0),
|
||||
myVCounter(0),
|
||||
myMouseEnabled(false)
|
||||
{
|
||||
// This 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
|
||||
|
||||
myTrakBallCountH = myTrakBallCountV = 0;
|
||||
myTrakBallLinesH = myTrakBallLinesV = 1;
|
||||
|
||||
myTrakBallLeft = myTrakBallDown = myScanCountV = myScanCountH =
|
||||
myCountV = myCountH = 0;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt8 AtariMouse::read()
|
||||
{
|
||||
int scanline = mySystem.tia().scanlines();
|
||||
|
||||
if(myScanCountV > scanline) myScanCountV = 0;
|
||||
if(myScanCountH > scanline) myScanCountH = 0;
|
||||
while((myScanCountV + myTrakBallLinesV) < scanline)
|
||||
{
|
||||
if(myTrakBallCountV)
|
||||
{
|
||||
if(myTrakBallDown) myCountV--;
|
||||
else myCountV++;
|
||||
myTrakBallCountV--;
|
||||
}
|
||||
myScanCountV += myTrakBallLinesV;
|
||||
}
|
||||
|
||||
while((myScanCountH + myTrakBallLinesH) < scanline)
|
||||
{
|
||||
if(myTrakBallCountH)
|
||||
{
|
||||
if(myTrakBallLeft) myCountH--;
|
||||
else myCountH++;
|
||||
myTrakBallCountH--;
|
||||
}
|
||||
myScanCountH += myTrakBallLinesH;
|
||||
}
|
||||
|
||||
myCountV &= 0x03;
|
||||
myCountH &= 0x03;
|
||||
|
||||
static constexpr uInt32 ourTableH[4] = { 0x00, 0x80, 0xc0, 0x40 };
|
||||
static constexpr uInt32 ourTableV[4] = { 0x00, 0x10, 0x30, 0x20 };
|
||||
uInt8 IOPortA = ourTableV[myCountV] | ourTableH[myCountH];
|
||||
|
||||
myDigitalPinState[One] = IOPortA & 0x10;
|
||||
myDigitalPinState[Two] = IOPortA & 0x20;
|
||||
myDigitalPinState[Three] = IOPortA & 0x40;
|
||||
myDigitalPinState[Four] = IOPortA & 0x80;
|
||||
|
||||
return (IOPortA >> 4);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void AtariMouse::update()
|
||||
{
|
||||
if(!myMouseEnabled)
|
||||
return;
|
||||
|
||||
// Get the current mouse position
|
||||
myHCounter = myEvent.get(Event::MouseAxisXValue);
|
||||
myVCounter = myEvent.get(Event::MouseAxisYValue);
|
||||
|
||||
if(myVCounter < 0) myTrakBallLeft = 1;
|
||||
else myTrakBallLeft = 0;
|
||||
if(myHCounter < 0) myTrakBallDown = 0;
|
||||
else myTrakBallDown = 1;
|
||||
myTrakBallCountH = abs(myVCounter >> 1);
|
||||
myTrakBallCountV = abs(myHCounter >> 1);
|
||||
myTrakBallLinesH = mySystem.tia().height() / (myTrakBallCountH + 1);
|
||||
if(myTrakBallLinesH == 0) myTrakBallLinesH = 1;
|
||||
myTrakBallLinesV = mySystem.tia().height() / (myTrakBallCountV + 1);
|
||||
if(myTrakBallLinesV == 0) myTrakBallLinesV = 1;
|
||||
|
||||
// Get mouse button state
|
||||
myDigitalPinState[Six] = (myEvent.get(Event::MouseButtonLeftValue) == 0) &&
|
||||
(myEvent.get(Event::MouseButtonRightValue) == 0);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool AtariMouse::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;
|
||||
}
|
|
@ -18,93 +18,28 @@
|
|||
#ifndef ATARIMOUSE_HXX
|
||||
#define ATARIMOUSE_HXX
|
||||
|
||||
#include "bspf.hxx"
|
||||
#include "Control.hxx"
|
||||
#include "Event.hxx"
|
||||
#include "PointingDevice.hxx"
|
||||
|
||||
/**
|
||||
Trakball-like controller emulating the Atari ST mouse.
|
||||
This code was heavily borrowed from z26.
|
||||
namespace {
|
||||
|
||||
@author Stephen Anthony & z26 team
|
||||
*/
|
||||
class AtariMouse : public Controller
|
||||
{
|
||||
public:
|
||||
/**
|
||||
Create a new AtariMouse 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);
|
||||
virtual ~AtariMouse() = default;
|
||||
public:
|
||||
static uInt8 ioPortA(uInt8 countH, uInt8 countV, uInt8 left, uInt8 down) {
|
||||
static constexpr uInt32 ourTableH[4] = { 0x00, 0x80, 0xc0, 0x40 };
|
||||
static constexpr uInt32 ourTableV[4] = { 0x00, 0x10, 0x30, 0x20 };
|
||||
|
||||
public:
|
||||
using Controller::read;
|
||||
return ourTableV[countV] | ourTableH[countH];
|
||||
}
|
||||
|
||||
/**
|
||||
Read the entire state of all digital pins for this controller.
|
||||
Note that this method must use the lower 4 bits, and zero the upper bits.
|
||||
public:
|
||||
static constexpr Controller::Type controllerType = Controller::AtariMouse;
|
||||
|
||||
@return The state of all digital pins
|
||||
*/
|
||||
uInt8 read() override;
|
||||
static constexpr uInt8 counterDivide = 2;
|
||||
};
|
||||
|
||||
/**
|
||||
Update the entire digital and analog pin state according to the
|
||||
events currently set.
|
||||
*/
|
||||
void update() override;
|
||||
}
|
||||
|
||||
/**
|
||||
Determines how this controller will treat values received from the
|
||||
X/Y axis and left/right buttons of the mouse. Since not all controllers
|
||||
use the mouse the same way (or at all), it's up to the specific class to
|
||||
decide how to use this data.
|
||||
typedef PointingDevice<AtariMouseHelper> AtariMouse;
|
||||
|
||||
In the current implementation, the left button is tied to the X axis,
|
||||
and the right one tied to the Y axis.
|
||||
|
||||
@param xtype The controller to use for x-axis data
|
||||
@param xid The controller ID to use for x-axis data (-1 for no id)
|
||||
@param ytype The controller to use for y-axis data
|
||||
@param yid The controller ID to use for y-axis data (-1 for no id)
|
||||
|
||||
@return Whether the controller supports using the mouse
|
||||
*/
|
||||
bool setMouseControl(Controller::Type xtype, int xid,
|
||||
Controller::Type ytype, int yid) override;
|
||||
|
||||
private:
|
||||
// Counter to iterate through the gray codes
|
||||
int myHCounter, myVCounter;
|
||||
|
||||
// How many new horizontal and vertical values this frame
|
||||
int myTrakBallCountH, myTrakBallCountV;
|
||||
|
||||
// How many lines to wait before sending new horz and vert val
|
||||
int myTrakBallLinesH, myTrakBallLinesV;
|
||||
|
||||
// Was TrakBall moved left or moved right instead
|
||||
int myTrakBallLeft;
|
||||
|
||||
// Was TrakBall moved down or moved up instead
|
||||
int myTrakBallDown;
|
||||
|
||||
int myScanCountH, myScanCountV, myCountH, myCountV;
|
||||
|
||||
// Whether to use the mouse to emulate this controller
|
||||
int myMouseEnabled;
|
||||
|
||||
private:
|
||||
// Following constructors and assignment operators not supported
|
||||
AtariMouse() = delete;
|
||||
AtariMouse(const AtariMouse&) = delete;
|
||||
AtariMouse(AtariMouse&&) = delete;
|
||||
AtariMouse& operator=(const AtariMouse&) = delete;
|
||||
AtariMouse& operator=(AtariMouse&&) = delete;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif // ATARIMOUSE_HXX
|
||||
|
|
|
@ -0,0 +1,220 @@
|
|||
//============================================================================
|
||||
//
|
||||
// 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.
|
||||
//============================================================================
|
||||
|
||||
#ifndef POINTING_DEVICE_HXX
|
||||
#define POINTING_DEVICE_HXX
|
||||
|
||||
#include "bspf.hxx"
|
||||
#include "Control.hxx"
|
||||
#include "Event.hxx"
|
||||
|
||||
/**
|
||||
Common controller class for pointing devices (Atari Mouse, Amiga Mouse, TrakBall)
|
||||
This code was heavily borrowed from z26.
|
||||
|
||||
@author Stephen Anthony & z26 team
|
||||
*/
|
||||
template<class T> class PointingDevice : public Controller
|
||||
{
|
||||
public:
|
||||
PointingDevice(Jack jack, const Event& event, const System& system);
|
||||
virtual ~PointingDevice() = default;
|
||||
|
||||
public:
|
||||
using Controller::read;
|
||||
|
||||
/**
|
||||
Read the entire state of all digital pins for this controller.
|
||||
Note that this method must use the lower 4 bits, and zero the upper bits.
|
||||
|
||||
@return The state of all digital pins
|
||||
*/
|
||||
uInt8 read() override;
|
||||
|
||||
/**
|
||||
Update the entire digital and analog pin state according to the
|
||||
events currently set.
|
||||
*/
|
||||
void update() override;
|
||||
|
||||
/**
|
||||
Determines how this controller will treat values received from the
|
||||
X/Y axis and left/right buttons of the mouse. Since not all controllers
|
||||
use the mouse the same way (or at all), it's up to the specific class to
|
||||
decide how to use this data.
|
||||
|
||||
In the current implementation, the left button is tied to the X axis,
|
||||
and the right one tied to the Y axis.
|
||||
|
||||
@param xtype The controller to use for x-axis data
|
||||
@param xid The controller ID to use for x-axis data (-1 for no id)
|
||||
@param ytype The controller to use for y-axis data
|
||||
@param yid The controller ID to use for y-axis data (-1 for no id)
|
||||
|
||||
@return Whether the controller supports using the mouse
|
||||
*/
|
||||
bool setMouseControl(Controller::Type xtype, int xid,
|
||||
Controller::Type ytype, int yid) override;
|
||||
|
||||
private:
|
||||
// Counter to iterate through the gray codes
|
||||
int myHCounter, myVCounter;
|
||||
int myHCounterRemainder, myVCounterRemainder;
|
||||
|
||||
// How many new horizontal and vertical values this frame
|
||||
int myTrakBallCountH, myTrakBallCountV;
|
||||
|
||||
// How many lines to wait before sending new horz and vert val
|
||||
int myTrakBallLinesH, myTrakBallLinesV;
|
||||
|
||||
// Was TrakBall moved left or moved right instead
|
||||
uInt8 myTrakBallLeft;
|
||||
|
||||
// Was TrakBall moved down or moved up instead
|
||||
uInt8 myTrakBallDown;
|
||||
|
||||
uInt8 myCountH, myCountV;
|
||||
int myScanCountH, myScanCountV;
|
||||
|
||||
// Whether to use the mouse to emulate this controller
|
||||
bool myMouseEnabled;
|
||||
|
||||
private:
|
||||
// Following constructors and assignment operators not supported
|
||||
PointingDevice() = delete;
|
||||
PointingDevice(const PointingDevice<T>&) = delete;
|
||||
PointingDevice(PointingDevice<T>&&) = delete;
|
||||
PointingDevice& operator=(const PointingDevice<T>&) = delete;
|
||||
PointingDevice& operator=(PointingDevice<T>&&) = delete;
|
||||
};
|
||||
|
||||
// ############################################################################
|
||||
// Implementation
|
||||
// ############################################################################
|
||||
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
template<class T>
|
||||
PointingDevice<T>::PointingDevice(Jack jack, const Event& event, const System& system)
|
||||
: Controller(jack, event, system, T::controllerType),
|
||||
myHCounter(0),
|
||||
myVCounter(0),
|
||||
myHCounterRemainder(0),
|
||||
myVCounterRemainder(0),
|
||||
myMouseEnabled(false)
|
||||
{
|
||||
// This 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
|
||||
|
||||
myTrakBallCountH = myTrakBallCountV = 0;
|
||||
myTrakBallLinesH = myTrakBallLinesV = 1;
|
||||
|
||||
myTrakBallLeft = myTrakBallDown = myScanCountV = myScanCountH =
|
||||
myCountV = myCountH = 0;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
template<class T>
|
||||
uInt8 PointingDevice<T>::read()
|
||||
{
|
||||
int scanline = mySystem.tia().scanlines();
|
||||
|
||||
if(myScanCountV > scanline) myScanCountV = 0;
|
||||
if(myScanCountH > scanline) myScanCountH = 0;
|
||||
while((myScanCountV + myTrakBallLinesV) < scanline)
|
||||
{
|
||||
if(myTrakBallCountV)
|
||||
{
|
||||
if(myTrakBallDown) myCountV--;
|
||||
else myCountV++;
|
||||
myTrakBallCountV--;
|
||||
}
|
||||
myScanCountV += myTrakBallLinesV;
|
||||
}
|
||||
|
||||
while((myScanCountH + myTrakBallLinesH) < scanline)
|
||||
{
|
||||
if(myTrakBallCountH)
|
||||
{
|
||||
if(myTrakBallLeft) myCountH--;
|
||||
else myCountH++;
|
||||
myTrakBallCountH--;
|
||||
}
|
||||
myScanCountH += myTrakBallLinesH;
|
||||
}
|
||||
|
||||
myCountV &= 0x03;
|
||||
myCountH &= 0x03;
|
||||
|
||||
uInt8 ioPortA = T::ioPortA(myCountH, myCountV, myTrakBallLeft, myTrakBallDown);
|
||||
|
||||
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;
|
||||
|
||||
// Get the current mouse position
|
||||
myHCounter = myEvent.get(Event::MouseAxisXValue) + myHCounterRemainder;
|
||||
myVCounter = myEvent.get(Event::MouseAxisYValue) + myVCounterRemainder;
|
||||
|
||||
if(myVCounter < 0) myTrakBallLeft = 1;
|
||||
else myTrakBallLeft = 0;
|
||||
if(myHCounter < 0) myTrakBallDown = 0;
|
||||
else myTrakBallDown = 1;
|
||||
|
||||
myHCounterRemainder = myHCounter % T::counterDivide;
|
||||
myVCounterRemainder = myVCounter % T::counterDivide;
|
||||
|
||||
myTrakBallCountH = abs(myVCounter / T::counterDivide);
|
||||
myTrakBallCountV = abs(myHCounter / T::counterDivide);
|
||||
|
||||
myTrakBallLinesH = mySystem.tia().height() / (myTrakBallCountH + 1);
|
||||
if(myTrakBallLinesH == 0) myTrakBallLinesH = 1;
|
||||
myTrakBallLinesV = mySystem.tia().height() / (myTrakBallCountV + 1);
|
||||
if(myTrakBallLinesV == 0) myTrakBallLinesV = 1;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
#endif // POINTING_DEVICE_HXX
|
|
@ -1,125 +0,0 @@
|
|||
//============================================================================
|
||||
//
|
||||
// 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 <cstdlib>
|
||||
|
||||
#include "Event.hxx"
|
||||
#include "System.hxx"
|
||||
#include "TIA.hxx"
|
||||
#include "TrakBall.hxx"
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
TrakBall::TrakBall(Jack jack, const Event& event, const System& system)
|
||||
: Controller(jack, event, system, Controller::TrakBall),
|
||||
myHCounter(0),
|
||||
myVCounter(0),
|
||||
myMouseEnabled(false)
|
||||
{
|
||||
// This 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
|
||||
|
||||
myTrakBallCountH = myTrakBallCountV = 0;
|
||||
myTrakBallLinesH = myTrakBallLinesV = 1;
|
||||
|
||||
myTrakBallLeft = myTrakBallDown = myScanCountV = myScanCountH =
|
||||
myCountV = myCountH = 0;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt8 TrakBall::read()
|
||||
{
|
||||
int scanline = mySystem.tia().scanlines();
|
||||
|
||||
if(myScanCountV > scanline) myScanCountV = 0;
|
||||
if(myScanCountH > scanline) myScanCountH = 0;
|
||||
while((myScanCountV + myTrakBallLinesV) < scanline)
|
||||
{
|
||||
if(myTrakBallCountV)
|
||||
{
|
||||
if(myTrakBallDown) myCountV--;
|
||||
else myCountV++;
|
||||
myTrakBallCountV--;
|
||||
}
|
||||
myScanCountV += myTrakBallLinesV;
|
||||
}
|
||||
|
||||
while((myScanCountH + myTrakBallLinesH) < scanline)
|
||||
{
|
||||
if(myTrakBallCountH)
|
||||
{
|
||||
if(myTrakBallLeft) myCountH--;
|
||||
else myCountH++;
|
||||
myTrakBallCountH--;
|
||||
}
|
||||
myScanCountH += myTrakBallLinesH;
|
||||
}
|
||||
|
||||
myCountV &= 0x03;
|
||||
myCountH &= 0x03;
|
||||
|
||||
static constexpr uInt32 ourTableH[2][2] = {{ 0x40, 0x00 }, { 0xc0, 0x80 }};
|
||||
static constexpr uInt32 ourTableV[2][2] = {{ 0x00, 0x10 }, { 0x20, 0x30 }};
|
||||
uInt8 IOPortA = ourTableV[myCountV & 0x01][myTrakBallDown] |
|
||||
ourTableH[myCountH & 0x01][myTrakBallLeft];
|
||||
|
||||
myDigitalPinState[One] = IOPortA & 0x10;
|
||||
myDigitalPinState[Two] = IOPortA & 0x20;
|
||||
myDigitalPinState[Three] = IOPortA & 0x40;
|
||||
myDigitalPinState[Four] = IOPortA & 0x80;
|
||||
|
||||
return (IOPortA >> 4);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void TrakBall::update()
|
||||
{
|
||||
if(!myMouseEnabled)
|
||||
return;
|
||||
|
||||
// Get the current mouse position
|
||||
myHCounter = myEvent.get(Event::MouseAxisXValue);
|
||||
myVCounter = myEvent.get(Event::MouseAxisYValue);
|
||||
|
||||
if(myVCounter < 0) myTrakBallLeft = 1;
|
||||
else myTrakBallLeft = 0;
|
||||
if(myHCounter < 0) myTrakBallDown = 0;
|
||||
else myTrakBallDown = 1;
|
||||
myTrakBallCountH = abs(myVCounter >> 2); // Extra div by 2, since trakball has
|
||||
myTrakBallCountV = abs(myHCounter >> 2); // half spatial resolution as ST/Amiga mouse
|
||||
myTrakBallLinesH = mySystem.tia().height() / (myTrakBallCountH + 1);
|
||||
if(myTrakBallLinesH == 0) myTrakBallLinesH = 1;
|
||||
myTrakBallLinesV = mySystem.tia().height() / (myTrakBallCountV + 1);
|
||||
if(myTrakBallLinesV == 0) myTrakBallLinesV = 1;
|
||||
|
||||
// Get mouse button state
|
||||
myDigitalPinState[Six] = (myEvent.get(Event::MouseButtonLeftValue) == 0) &&
|
||||
(myEvent.get(Event::MouseButtonRightValue) == 0);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool TrakBall::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;
|
||||
}
|
|
@ -18,93 +18,29 @@
|
|||
#ifndef TRAKBALL_HXX
|
||||
#define TRAKBALL_HXX
|
||||
|
||||
#include "bspf.hxx"
|
||||
#include "Control.hxx"
|
||||
#include "Event.hxx"
|
||||
#include "PointingDevice.hxx"
|
||||
|
||||
/**
|
||||
Emulates the standard trakball controller, sometimes known as the 'CX22'
|
||||
controller. This code was heavily borrowed from z26.
|
||||
namespace {
|
||||
|
||||
@author Stephen Anthony & z26 team
|
||||
*/
|
||||
class TrakBall : public Controller
|
||||
{
|
||||
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);
|
||||
virtual ~TrakBall() = default;
|
||||
public:
|
||||
static uInt8 ioPortA(uInt8 countH, uInt8 countV, uInt8 left, uInt8 down) {
|
||||
static constexpr uInt32 ourTableH[2][2] = {{ 0x40, 0x00 }, { 0xc0, 0x80 }};
|
||||
static constexpr uInt32 ourTableV[2][2] = {{ 0x00, 0x10 }, { 0x20, 0x30 }};
|
||||
|
||||
public:
|
||||
using Controller::read;
|
||||
return ourTableV[countV & 0x01][down] |
|
||||
ourTableH[countH & 0x01][left];
|
||||
}
|
||||
|
||||
/**
|
||||
Read the entire state of all digital pins for this controller.
|
||||
Note that this method must use the lower 4 bits, and zero the upper bits.
|
||||
public:
|
||||
static constexpr Controller::Type controllerType = Controller::TrakBall;
|
||||
|
||||
@return The state of all digital pins
|
||||
*/
|
||||
uInt8 read() override;
|
||||
static constexpr uInt8 counterDivide = 4;
|
||||
};
|
||||
|
||||
/**
|
||||
Update the entire digital and analog pin state according to the
|
||||
events currently set.
|
||||
*/
|
||||
void update() override;
|
||||
}
|
||||
|
||||
/**
|
||||
Determines how this controller will treat values received from the
|
||||
X/Y axis and left/right buttons of the mouse. Since not all controllers
|
||||
use the mouse the same way (or at all), it's up to the specific class to
|
||||
decide how to use this data.
|
||||
typedef PointingDevice<TrakBallHelper> TrakBall;
|
||||
|
||||
In the current implementation, the left button is tied to the X axis,
|
||||
and the right one tied to the Y axis.
|
||||
|
||||
@param xtype The controller to use for x-axis data
|
||||
@param xid The controller ID to use for x-axis data (-1 for no id)
|
||||
@param ytype The controller to use for y-axis data
|
||||
@param yid The controller ID to use for y-axis data (-1 for no id)
|
||||
|
||||
@return Whether the controller supports using the mouse
|
||||
*/
|
||||
bool setMouseControl(Controller::Type xtype, int xid,
|
||||
Controller::Type ytype, int yid) override;
|
||||
|
||||
private:
|
||||
// Counter to iterate through the gray codes
|
||||
int myHCounter, myVCounter;
|
||||
|
||||
// How many new horizontal and vertical values this frame
|
||||
int myTrakBallCountH, myTrakBallCountV;
|
||||
|
||||
// How many lines to wait before sending new horz and vert val
|
||||
int myTrakBallLinesH, myTrakBallLinesV;
|
||||
|
||||
// Was TrakBall moved left or moved right instead
|
||||
int myTrakBallLeft;
|
||||
|
||||
// Was TrakBall moved down or moved up instead
|
||||
int myTrakBallDown;
|
||||
|
||||
int myScanCountH, myScanCountV, myCountH, myCountV;
|
||||
|
||||
// Whether to use the mouse to emulate this controller
|
||||
int myMouseEnabled;
|
||||
|
||||
private:
|
||||
// Following constructors and assignment operators not supported
|
||||
TrakBall() = delete;
|
||||
TrakBall(const TrakBall&) = delete;
|
||||
TrakBall(TrakBall&&) = delete;
|
||||
TrakBall& operator=(const TrakBall&) = delete;
|
||||
TrakBall& operator=(TrakBall&&) = delete;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif // TRAKBALL_HXX
|
||||
|
|
|
@ -77,9 +77,6 @@ MODULE_OBJS := \
|
|||
src/emucore/System.o \
|
||||
src/emucore/TIASnd.o \
|
||||
src/emucore/TIASurface.o \
|
||||
src/emucore/AmigaMouse.o \
|
||||
src/emucore/AtariMouse.o \
|
||||
src/emucore/TrakBall.o \
|
||||
src/emucore/Thumbulator.o
|
||||
|
||||
MODULE_DIRS += \
|
||||
|
|
Loading…
Reference in New Issue