Huge improvements to paddle and mouse handling:

- mouse can now emulate joystick, booster-grip and driving controllers
 - digital and mouse sensitivity for paddles can now be tweaked
   separately, and have a greater range
 - the mouse now correctly honours its controller setting, and only
   controls a device on one one port (not both at the same time)

Added support for 2600-daptor device.  Credit for creator of device
is forthcoming.  This device is basically an updated Stelladaptor,
with improved handling for paddle data.

Grabmouse functionality is no longer user-definable; the mouse is
always grabbed while playing a game, and released otherwise.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@2228 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2011-05-06 14:29:39 +00:00
parent 329f553f09
commit 264145a939
28 changed files with 725 additions and 519 deletions

View File

@ -12,11 +12,23 @@
Release History
===========================================================================
3.3 to 3.4: (xx. xx, 2011)
3.3 to 3.4: (May. xx, 2011)
* The mouse can now be used in joystick games (ie, moving the mouse
emulates joystick directions, and pressing a mouse button emulates
the joystick fire button).
* Many improvements to input handling, particularly with the mouse and
paddles:
- The mouse can now be used to emulate a joystick, booster-grip or
driving controller.
- The mouse now controls only one device at a time (1 of 4 paddles,
1 of 2 joysticks, etc), instead of devices from both virtual ports.
- The sensitivity for digital and mouse input (for paddles) can now
be set separately with the 'dsense' and 'msense' commandline
arguments, and from within the Input Settings UI.
* Added support for the 2600-daptor device, which is similar to a
Stelladaptor but improves handling of paddles. Thanks go to XXX
for a complimentary test sample of this device.
* Added preliminary support for emulating ARM code to the DPC+
bankswitching scheme (thanks to Batari).
@ -28,6 +40,9 @@
directory in the ROM launcher, and reloads the directory after
the audit is complete.
* Removed the 'grabmouse' functionality; the mouse is now always
grabbed while playing a game, and released otherwise.
* Updated built-in version of the PNG library to the latest version.
-Have fun!

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 8.4 KiB

View File

@ -1689,11 +1689,6 @@
<td>Centers game window (if possible).</td>
</tr>
<tr>
<td><pre>-grabmouse &lt;1|0&gt;</pre></td>
<td>Keeps the mouse in the game window.</td>
</tr>
<tr>
<td><pre>-palette &lt;standard|z26|user&gt;</pre></td>
<td>Set the palette to either normal Stella, the one used in the z26
@ -1800,8 +1795,18 @@
</tr>
<tr>
<td><pre>-pspeed &lt;number&gt;</pre></td>
<td>Speed for digital emulation of paddles (1-15).</td>
<td><pre>-dsense &lt;number&gt;</pre></td>
<td>Sensitivity for emulation of paddles when using a digital device
(ie, joystick digital axis or button, keyboard key, etc).
Valid range of values is from 1 to 10, with larger numbers causing
faster movement.</td>
</tr>
<tr>
<td><pre>-msense &lt;number&gt;</pre></td>
<td>Sensitivity for emulation of paddles when using a mouse.
Valid range of values is from 1 to 10, with larger numbers causing
faster movement.</td>
</tr>
<tr>
@ -2172,7 +2177,6 @@
<tr><td>PAL color-loss</td><td>use PAL color-loss effect</td><td>-colorloss</td></tr>
<tr><td>GL FS Stretch</td><td>stretch fullscreen OpenGL in emulation mode</td><td>-gl_fsmax</td></tr>
<tr><td>GL VSync</td><td>enable OpenGL vertical synchronization</td><td>-gl_vsync</td></tr>
<tr><td>Grab mouse</td><td>keep mouse in SDL window</td><td>-grabmouse</td></tr>
<tr><td>Show UI messages</td><td>overlay UI messages onscreen</td><td>-uimessages</td></tr>
<tr><td>Center window</td><td>attempt to center application window</td><td>-center</td></tr>
<tr><td>Fast SC/AR BIOS</td><td>Skip progress loading bars for SuperCharger ROMs</td><td>-fastscbios</td></tr>
@ -2367,8 +2371,9 @@
<tr><th>Item</th><th>Brief description</th><th>For more information,<br>see <a href="#CommandLine">CommandLine</a></th></tr>
<tr><td>Stelladaptor X is</td><td>Specifies which virtual port each Stelladaptor uses (See <b>Advanced Configuration - <a href="#Adaptor">Stelladaptor Support</a></b>)</td><td>-sa1 &amp; -sa2</td></tr>
<tr><td>AVox serial port</td><td>Described in further detail in <b>Advanced Configuration - <a href="#AtariVox">AtariVox/SaveKey Support</a></b> </td><td>-avoxport</td></tr>
<tr><td>Joy deadzone</td><td>Deadzone area for axes on joysticks/gamepads</td><td>-joydeadzone</td></tr>
<tr><td>Paddle speed</td><td>Speed used when emulating a paddle using a digital device</td><td>-pspeed</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>Sensitvity 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>Allow all 4 ...</td><td>Allow all 4 joystick directions to be pressed simultaneously</td><td>-joyallow4</td></tr>
<tr><td>Use mouse as ...</td><td>Use the mouse for various controllers (paddles, driving, etc)</td><td>-usemouse</td></tr>
</table>

View File

@ -22,7 +22,7 @@
#include <cstdlib>
#define STELLA_VERSION "3.3.05"
#define STELLA_VERSION "3.4_svn1"
#define STELLA_BUILD atoi("$Rev$" + 6)
#endif

View File

@ -82,7 +82,7 @@ void BoosterGrip::update()
if(xaxis < 16384+4096)
myDigitalPinState[Three] = false;
}
if(xaxis < -16384)
else if(xaxis < -16384)
myDigitalPinState[Three] = false;
if(yaxis > 16384-4096)
{
@ -91,6 +91,39 @@ void BoosterGrip::update()
if(yaxis < 16384+4096)
myDigitalPinState[One] = false;
}
if(yaxis < -16384)
else if(yaxis < -16384)
myDigitalPinState[One] = false;
// Mouse motion and button events
// Since there are 4 possible controller numbers, we use 0 & 2
// for the left jack, and 1 & 3 for the right jack
if((myJack == Left && !(ourControlNum & 0x1)) ||
(myJack == Right && ourControlNum & 0x1))
{
// The following code was taken from z26
#define MJ_Threshold 2
int mousex = myEvent.get(Event::MouseAxisXValue),
mousey = myEvent.get(Event::MouseAxisYValue);
if(mousex || mousey)
{
if((!(abs(mousey) > abs(mousex) << 1)) && (abs(mousex) >= MJ_Threshold))
{
if(mousex < 0)
myDigitalPinState[Three] = false;
else if (mousex > 0)
myDigitalPinState[Four] = false;
}
if((!(abs(mousex) > abs(mousey) << 1)) && (abs(mousey) >= MJ_Threshold))
{
if(mousey < 0)
myDigitalPinState[One] = false;
else if(mousey > 0)
myDigitalPinState[Two] = false;
}
}
// Get mouse button state
if(myEvent.get(Event::MouseButtonValue))
myDigitalPinState[Six] = false;
}
}

View File

@ -619,7 +619,8 @@ void Console::setControllers(const string& rommd5)
// Also check if we should swap the paddles plugged into a jack
bool swapPaddles = myProperties.get(Controller_SwapPaddles) == "YES";
Paddles::setMouseIsPaddle(-1); // Reset to defaults
// Set default controller for mouse
Controller::setMouseIsController(0);
// Construct left controller
if(left == "BOOSTERGRIP")
@ -636,7 +637,10 @@ void Console::setControllers(const string& rommd5)
}
else if(left == "PADDLES")
{
myControllers[leftPort] = new Paddles(Controller::Left, *myEvent, *mySystem, swapPaddles);
Controller::setMouseIsController(swapPaddles ? 1 : 0);
myControllers[leftPort] =
new Paddles(Controller::Left, *myEvent, *mySystem,
swapPaddles, false, false);
}
else if(left == "TRACKBALL22")
{
@ -677,7 +681,11 @@ void Console::setControllers(const string& rommd5)
}
else if(right == "PADDLES")
{
myControllers[rightPort] = new Paddles(Controller::Right, *myEvent, *mySystem, swapPaddles);
if(left != "PADDLES")
Controller::setMouseIsController(swapPaddles ? 3 : 2);
myControllers[rightPort] =
new Paddles(Controller::Right, *myEvent, *mySystem,
swapPaddles, false, false);
}
else if(right == "TRACKBALL22")
{

View File

@ -182,12 +182,23 @@ string Controller::about() const
return name() + " in " + (myJack == Left ? "left port" : "right port");
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Controller::setMouseIsController(int number)
{
ourControlNum = number;
if(ourControlNum < 0) ourControlNum = 0;
else if (ourControlNum > 3) ourControlNum = 3;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const Int32 Controller::maximumResistance = 0x7FFFFFFF;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const Int32 Controller::minimumResistance = 0x00000000;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Int32 Controller::ourControlNum = 0;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Controller::Controller(const Controller& c)
: myJack(c.myJack),

View File

@ -192,6 +192,17 @@ class Controller : public Serializable
*/
bool load(Serializer& in);
/**
Sets the mouse to emulate controller number 'X'. Note that this
can accept values 0 to 3, since there can be up to four possible
controllers (when using paddles). In all other cases when only
two controllers are present, it's up to the specific class to
decide how to use this data.
@param number The controller number (0, 1, 2, 3)
*/
static void setMouseIsController(int number);
public:
/// Constant which represents maximum resistance for analog pins
static const Int32 maximumResistance;
@ -221,6 +232,9 @@ class Controller : public Serializable
/// The analog value on each analog pin
Int32 myAnalogPinValue[2];
/// The controller number
static Int32 ourControlNum;
protected:
// Copy constructor isn't supported by controllers so make it private
Controller(const Controller&);

View File

@ -65,10 +65,22 @@ void Driving::update()
// Digital events (from keyboard or joystick hats & buttons)
myDigitalPinState[Six] = (myEvent.get(myFireEvent) == 0);
int d_axis = myEvent.get(myXAxisValue);
if(myEvent.get(myCCWEvent) != 0 || d_axis < -16384) myCounter--;
else if(myEvent.get(myCWEvent) != 0 || d_axis > 16384) myCounter++;
int xaxis = myEvent.get(myXAxisValue);
if(myEvent.get(myCCWEvent) != 0 || xaxis < -16384) myCounter--;
else if(myEvent.get(myCWEvent) != 0 || xaxis > 16384) myCounter++;
// Mouse motion and button events
// Since there are 4 possible controller numbers, we use 0 & 2
// for the left jack, and 1 & 3 for the right jack
if((myJack == Left && !(ourControlNum & 0x1)) ||
(myJack == Right && ourControlNum & 0x1))
{
int m_axis = myEvent.get(Event::MouseAxisXValue);
if(m_axis < -2) myCounter--;
else if(m_axis > 2) myCounter++;
if(myEvent.get(Event::MouseButtonValue))
myDigitalPinState[Six] = false;
}
// Only consider the lower-most bits (corresponding to pins 1 & 2)
myCounter &= 0x0f;

View File

@ -68,7 +68,8 @@ class Driving : public Controller
// Pre-compute the events we care about based on given port
// This will eliminate test for left or right port in update()
Event::Type myCWEvent, myCCWEvent, myFireEvent, myXAxisValue, myYAxisValue;
Event::Type myCWEvent, myCCWEvent, myFireEvent,
myXAxisValue, myYAxisValue, myAxisMouseMotion;
};
#endif

View File

@ -40,8 +40,8 @@ class Event
{
NoType,
ConsoleOn, ConsoleOff, ConsoleColor, ConsoleBlackWhite,
ConsoleLeftDifficultyA, ConsoleLeftDifficultyB,
ConsoleRightDifficultyA, ConsoleRightDifficultyB,
ConsoleLeftDiffA, ConsoleLeftDiffB,
ConsoleRightDiffA, ConsoleRightDiffB,
ConsoleSelect, ConsoleReset,
JoystickZeroUp, JoystickZeroDown, JoystickZeroLeft, JoystickZeroRight,

View File

@ -64,7 +64,6 @@ EventHandler::EventHandler(OSystem* osystem)
myEvent(NULL),
myOverlay(NULL),
myState(S_NONE),
myGrabMouseFlag(false),
myAllowAllDirectionsFlag(false),
myFryingFlag(false)
{
@ -115,10 +114,10 @@ EventHandler::EventHandler(OSystem* osystem)
// Set unchanging messages
ourMessageTable[Event::ConsoleColor] = "Color Mode";
ourMessageTable[Event::ConsoleBlackWhite] = "BW Mode";
ourMessageTable[Event::ConsoleLeftDifficultyA] = "Left Difficulty A";
ourMessageTable[Event::ConsoleLeftDifficultyB] = "Left Difficulty B";
ourMessageTable[Event::ConsoleRightDifficultyA] = "Right Difficulty A";
ourMessageTable[Event::ConsoleRightDifficultyB] = "Right Difficulty B";
ourMessageTable[Event::ConsoleLeftDiffA] = "Left Difficulty A";
ourMessageTable[Event::ConsoleLeftDiffB] = "Left Difficulty B";
ourMessageTable[Event::ConsoleRightDiffA] = "Right Difficulty A";
ourMessageTable[Event::ConsoleRightDiffB] = "Right Difficulty B";
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -160,12 +159,12 @@ void EventHandler::initialize()
setActionMappings(kEmulationMode);
setActionMappings(kMenuMode);
myGrabMouseFlag = myOSystem->settings().getBool("grabmouse");
myUseCtrlKeyFlag = myOSystem->settings().getBool("ctrlcombo");
Joystick::setDeadZone(myOSystem->settings().getInt("joydeadzone"));
Paddles::setDigitalSpeed(myOSystem->settings().getInt("pspeed"));
setPaddleMode(myOSystem->settings().getBool("usemouse") ? 0 : -1, false);
Paddles::setDigitalSensitivity(myOSystem->settings().getInt("dsense"));
Paddles::setMouseSensitivity(myOSystem->settings().getInt("msense"));
setMouseControllerMode(myOSystem->settings().getBool("usemouse") ? 0 : -1, false);
// Set quick select delay when typing characters in listwidgets
ListWidget::setQuickSelectDelay(myOSystem->settings().getInt("listdelay"));
@ -230,7 +229,20 @@ void EventHandler::setupJoysticks()
// Figure out what type of joystick this is
ostringstream buf;
if(name.find("Stelladaptor", 0) != string::npos)
if(name.find("2600-daptor", 0) != string::npos)
{
saCount++;
if(saCount > 2) // Ignore more than 2 Stelladaptors
continue;
else if(saCount == 1) // Type will be set by mapStelladaptors()
ourJoysticks[i].name = "2600-daptor 1";
else if(saCount == 2)
ourJoysticks[i].name = "2600-daptor 2";
buf << " " << i << ": " << ourJoysticks[i].name << endl;
myOSystem->logMessage(buf.str(), 1);
}
else if(name.find("Stelladaptor", 0) != string::npos)
{
saCount++;
if(saCount > 2) // Ignore more than 2 Stelladaptors
@ -300,6 +312,32 @@ void EventHandler::mapStelladaptors(const string& sa1, const string& sa2)
myOSystem->logMessage(" Stelladaptor 2 emulates right joystick port\n", 1);
}
}
else if(ourJoysticks[i].name == "2600-daptor 1")
{
if(sa1 == "left")
{
ourJoysticks[i].type = JT_2600DAPTOR_LEFT;
myOSystem->logMessage(" 2600-daptor 1 emulates left joystick port\n", 1);
}
else if(sa1 == "right")
{
ourJoysticks[i].type = JT_2600DAPTOR_RIGHT;
myOSystem->logMessage(" 2600-daptor 1 emulates right joystick port\n", 1);
}
}
else if(ourJoysticks[i].name == "2600-daptor 2")
{
if(sa2 == "left")
{
ourJoysticks[i].type = JT_2600DAPTOR_LEFT;
myOSystem->logMessage(" 2600-daptor 2 emulates left joystick port\n", 1);
}
else if(sa2 == "right")
{
ourJoysticks[i].type = JT_2600DAPTOR_RIGHT;
myOSystem->logMessage(" 2600-daptor 2 emulates right joystick port\n", 1);
}
}
}
myOSystem->logMessage("\n", 1);
@ -508,16 +546,6 @@ void EventHandler::poll(uInt64 time)
{
handleEvent(Event::Quit, 1);
}
else if(key == SDLK_g)
{
// don't change grabmouse in fullscreen mode
if(!myOSystem->frameBuffer().fullScreen())
{
myGrabMouseFlag = !myGrabMouseFlag;
myOSystem->settings().setBool("grabmouse", myGrabMouseFlag);
myOSystem->frameBuffer().grabMouse(myGrabMouseFlag);
}
}
// These only work when in emulation mode
else if(myState == S_EMULATE)
{
@ -530,20 +558,20 @@ void EventHandler::poll(uInt64 time)
handleMacOSXKeypress(int(key));
break;
#endif
case SDLK_0: // Ctrl-0 sets the mouse to paddle 0
setPaddleMode(0, true);
case SDLK_0: // Ctrl-0 sets the mouse to controller 0
setMouseControllerMode(0, true);
break;
case SDLK_1: // Ctrl-1 sets the mouse to paddle 1
setPaddleMode(1, true);
case SDLK_1: // Ctrl-1 sets the mouse to controller 1
setMouseControllerMode(1, true);
break;
case SDLK_2: // Ctrl-2 sets the mouse to paddle 2
setPaddleMode(2, true);
case SDLK_2: // Ctrl-2 sets the mouse to controller 2
setMouseControllerMode(2, true);
break;
case SDLK_3: // Ctrl-3 sets the mouse to paddle 3
setPaddleMode(3, true);
case SDLK_3: // Ctrl-3 sets the mouse to controller 3
setMouseControllerMode(3, true);
break;
case SDLK_f: // Ctrl-f toggles NTSC/PAL mode
@ -730,16 +758,22 @@ void EventHandler::poll(uInt64 time)
}
break; // Regular button
// These events don't have to pass through handleEvent, since
// they can never be remapped
case JT_STELLADAPTOR_LEFT:
case JT_STELLADAPTOR_RIGHT:
// The 'type-2' here refers to the fact that 'JT_STELLADAPTOR_LEFT'
// and 'JT_STELLADAPTOR_RIGHT' are at index 2 and 3 in the JoyType
// enum; subtracting two gives us Controller 0 and 1
// These events don't have to pass through handleEvent, since
// they can never be remapped
if(button < 2) myEvent->set(SA_Button[type-2][button], state);
break; // Stelladaptor button
case JT_2600DAPTOR_LEFT:
case JT_2600DAPTOR_RIGHT:
// The 'type-4' here refers to the fact that 'JT_2600DAPTOR_LEFT'
// and 'JT_2600DAPTOR_RIGHT' are at index 4 and 5 in the JoyType
// enum; subtracting four gives us Controller 0 and 1
if(button < 2) myEvent->set(SA_Button[type-4][button], state);
break; // 2600DAPTOR button
}
break; // SDL_JOYBUTTONUP, SDL_JOYBUTTONDOWN
}
@ -820,19 +854,27 @@ void EventHandler::poll(uInt64 time)
}
break; // Regular joystick axis
// Since the various controller classes deal with Stelladaptor
// devices differently, we send the raw X and Y axis data directly,
// and let the controller handle it
// These events don't have to pass through handleEvent, since
// they can never be remapped
case JT_STELLADAPTOR_LEFT:
case JT_STELLADAPTOR_RIGHT:
// Since the various controller classes deal with the
// Stelladaptor differently, we send the raw X and Y axis
// data directly, and let the controller handle it
// The 'type-2' here refers to the fact that 'JT_STELLADAPTOR_LEFT'
// and 'JT_STELLADAPTOR_RIGHT' are at index 2 and 3 in the JoyType
// enum; subtracting two gives us Controller 0 and 1
// These events don't have to pass through handleEvent, since
// they can never be remapped
if(axis < 2) myEvent->set(SA_Axis[type-2][axis], value);
if(axis < 2)
myEvent->set(SA_Axis[type-2][axis], value);
break; // Stelladaptor axis
case JT_2600DAPTOR_LEFT:
case JT_2600DAPTOR_RIGHT:
// The 'type-4' here refers to the fact that 'JT_2600DAPTOR_LEFT'
// and 'JT_2600DAPTOR_RIGHT' are at index 4 and 5 in the JoyType
// enum; subtracting four gives us Controller 0 and 1
if(axis < 2)
myEvent->set(SA_Axis[type-4][axis], value);
break; // 26000daptor axis
}
break; // SDL_JOYAXISMOTION
}
@ -1621,10 +1663,10 @@ void EventHandler::setDefaultKeymap(Event::Type event, EventMode mode)
SET_DEFAULT_KEY(SDLK_F2, mode, Event::ConsoleReset, event);
SET_DEFAULT_KEY(SDLK_F3, mode, Event::ConsoleColor, event);
SET_DEFAULT_KEY(SDLK_F4, mode, Event::ConsoleBlackWhite, event);
SET_DEFAULT_KEY(SDLK_F5, mode, Event::ConsoleLeftDifficultyA, event);
SET_DEFAULT_KEY(SDLK_F6, mode, Event::ConsoleLeftDifficultyB, event);
SET_DEFAULT_KEY(SDLK_F7, mode, Event::ConsoleRightDifficultyA, event);
SET_DEFAULT_KEY(SDLK_F8, mode, Event::ConsoleRightDifficultyB, event);
SET_DEFAULT_KEY(SDLK_F5, mode, Event::ConsoleLeftDiffA, event);
SET_DEFAULT_KEY(SDLK_F6, mode, Event::ConsoleLeftDiffB, event);
SET_DEFAULT_KEY(SDLK_F7, mode, Event::ConsoleRightDiffA, event);
SET_DEFAULT_KEY(SDLK_F8, mode, Event::ConsoleRightDiffB, event);
SET_DEFAULT_KEY(SDLK_F9, mode, Event::SaveState, event);
SET_DEFAULT_KEY(SDLK_F10, mode, Event::ChangeState, event);
SET_DEFAULT_KEY(SDLK_F11, mode, Event::LoadState, event);
@ -2052,16 +2094,16 @@ void EventHandler::takeSnapshot(uInt32 number)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::setPaddleMode(int num, bool showmessage)
void EventHandler::setMouseControllerMode(int num, bool showmessage)
{
if(num >= 0 && num <= 3)
{
myMouseEnabled = true;
Paddles::setMouseIsPaddle(num);
Controller::setMouseIsController(num);
if(showmessage)
{
ostringstream buf;
buf << "Mouse is paddle " << num;
buf << "Mouse is controller " << num;
myOSystem->frameBuffer().showMessage(buf.str());
}
}
@ -2081,9 +2123,6 @@ void EventHandler::enterMenuMode(State state)
{
setEventState(state);
myOverlay->reStack();
myOSystem->frameBuffer().setCursorState();
myOSystem->sound().mute(true);
}
@ -2091,9 +2130,6 @@ void EventHandler::enterMenuMode(State state)
void EventHandler::leaveMenuMode()
{
setEventState(S_EMULATE);
myOSystem->frameBuffer().setCursorState();
myOSystem->sound().mute(false);
}
@ -2122,7 +2158,6 @@ bool EventHandler::enterDebugMode()
return false;
}
myOverlay->reStack();
myOSystem->frameBuffer().setCursorState();
myOSystem->sound().mute(true);
#else
myOSystem->frameBuffer().showMessage("Debugger support not included",
@ -2145,7 +2180,6 @@ void EventHandler::leaveDebugMode()
setEventState(S_EMULATE);
myOSystem->createFrameBuffer();
myOSystem->frameBuffer().setCursorState();
myOSystem->sound().mute(false);
#endif
}
@ -2192,7 +2226,10 @@ void EventHandler::setEventState(State state)
// Inform various subsystems about the new state
myOSystem->stateChanged(myState);
if(&myOSystem->frameBuffer())
{
myOSystem->frameBuffer().stateChanged(myState);
myOSystem->frameBuffer().setCursorState();
}
// Always clear any pending events when changing states
myEvent->clear();
@ -2440,10 +2477,10 @@ EventHandler::ActionList EventHandler::ourEmulActionList[kEmulActionListSize] =
{ Event::ConsoleReset, "Reset", 0, true },
{ Event::ConsoleColor, "Color TV", 0, true },
{ Event::ConsoleBlackWhite, "Black & White TV", 0, true },
{ Event::ConsoleLeftDifficultyA, "P0 Difficulty A", 0, true },
{ Event::ConsoleLeftDifficultyB, "P0 Difficulty B", 0, true },
{ Event::ConsoleRightDifficultyA, "P1 Difficulty A", 0, true },
{ Event::ConsoleRightDifficultyB, "P1 Difficulty B", 0, true },
{ Event::ConsoleLeftDiffA, "P0 Difficulty A", 0, true },
{ Event::ConsoleLeftDiffB, "P0 Difficulty B", 0, true },
{ Event::ConsoleRightDiffA, "P1 Difficulty A", 0, true },
{ Event::ConsoleRightDiffB, "P1 Difficulty B", 0, true },
{ Event::SaveState, "Save State", 0, false },
{ Event::ChangeState, "Change State", 0, false },
{ Event::LoadState, "Load State", 0, false },

View File

@ -185,12 +185,12 @@ class EventHandler
void quit() { handleEvent(Event::Quit, 1); }
/**
Sets the mouse to act as paddle 'num'
Sets the mouse to act as controller 'num'
@param num The paddle which the mouse should emulate
@param num The controller which the mouse should emulate
@param showmessage Print a message to the framebuffer
*/
void setPaddleMode(int num, bool showmessage = false);
void setMouseControllerMode(int num, bool showmessage = false);
/**
Set the number of seconds between taking a snapshot in
@ -407,10 +407,12 @@ class EventHandler
kNumJoyHats = 16
};
enum JoyType {
JT_NONE,
JT_REGULAR,
JT_STELLADAPTOR_LEFT,
JT_STELLADAPTOR_RIGHT
JT_NONE = 0,
JT_REGULAR = 1,
JT_STELLADAPTOR_LEFT = 2,
JT_STELLADAPTOR_RIGHT = 3,
JT_2600DAPTOR_LEFT = 4,
JT_2600DAPTOR_RIGHT = 5
};
struct Stella_Joystick {
SDL_Joystick* stick;
@ -460,9 +462,6 @@ class EventHandler
// Indicates the current state of the system (ie, which mode is current)
State myState;
// Indicates whether the mouse cursor is grabbed
bool myGrabMouseFlag;
// Indicates whether the mouse is enabled for game controller actions
bool myMouseEnabled;

View File

@ -743,21 +743,12 @@ cerr << "New mode:" << endl
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::setCursorState()
{
if(fullScreen())
grabMouse(true);
else
grabMouse(myOSystem->settings().getBool("grabmouse"));
switch(myOSystem->eventHandler().state())
{
case EventHandler::S_EMULATE:
case EventHandler::S_PAUSE:
showCursor(false);
break;
default:
showCursor(true);
break;
}
// Always grab mouse in fullscreen or during emulation,
// and don't show the cursor during emulation
bool emulation =
myOSystem->eventHandler().state() == EventHandler::S_EMULATE;
grabMouse(fullScreen() || emulation);
showCursor(!emulation);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -240,11 +240,6 @@ class FrameBuffer
*/
virtual void showCursor(bool show);
/**
Grabs or ungrabs the mouse based on the given boolean value.
*/
void grabMouse(bool grab);
/**
Answers if the display is currently in fullscreen mode.
*/
@ -470,6 +465,11 @@ class FrameBuffer
uInt32 myZoomLevel;
private:
/**
Grabs or ungrabs the mouse based on the given boolean value.
*/
void grabMouse(bool grab);
/**
Set the icon for the main SDL window.
*/

View File

@ -74,7 +74,7 @@ void Joystick::update()
if(xaxis < 16384+4096)
myDigitalPinState[Three] = false;
}
if(xaxis < -16384)
else if(xaxis < -16384)
myDigitalPinState[Three] = false;
if(yaxis > 16384-4096)
{
@ -83,12 +83,17 @@ void Joystick::update()
if(yaxis < 16384+4096)
myDigitalPinState[One] = false;
}
if(yaxis < -16384)
else if(yaxis < -16384)
myDigitalPinState[One] = false;
// Mouse motion and button events
// Since there are 4 possible controller numbers, we use 0 & 2
// for the left jack, and 1 & 3 for the right jack
if((myJack == Left && !(ourControlNum & 0x1)) ||
(myJack == Right && ourControlNum & 0x1))
{
// The following code was taken from z26
// Mouse events
#define MJ_Threshold 2
#define MJ_Threshold 2
int mousex = myEvent.get(Event::MouseAxisXValue),
mousey = myEvent.get(Event::MouseAxisYValue);
if(mousex || mousey)
@ -112,6 +117,7 @@ void Joystick::update()
// Get mouse button state
if(myEvent.get(Event::MouseButtonValue))
myDigitalPinState[Six] = false;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -17,103 +17,196 @@
// $Id$
//============================================================================
#define TRIGMAX 240
#define TRIGMIN 1
#include <cassert>
#include "Event.hxx"
#include "Paddles.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Paddles::Paddles(Jack jack, const Event& event, const System& system, bool swap)
Paddles::Paddles(Jack jack, const Event& event, const System& system,
bool swapport, bool swapaxis, bool swapdir)
: Controller(jack, event, system, Controller::Paddles)
{
// Swap the paddle events, from paddle 0 <=> 1 and paddle 2 <=> 3
// Also consider whether this is the left or right port
// The following logic reflects that mapping paddles to different
// devices can be extremely complex
// As well, while many paddle games have horizontal movement of
// objects (which maps nicely to horizontal movement of the joystick
// or mouse), others have vertical movement
// This vertical handling is taken care of by swapping the axes
// On the other hand, some games treat paddle resistance differently,
// (ie, increasing resistance can move an object right instead of left)
// This is taken care of by swapping the direction of movement
// Arrgh, did I mention that paddles are complex ...
// As much as possible, precompute which events we care about for
// a given port; this will speed up processing in update()
// Consider whether this is the left or right port
if(myJack == Left)
{
if(!swap)
if(!swapport) // First paddle is 0, second is 1
{
// These aren't affected by changes in axis orientation
myP0AxisValue = Event::SALeftAxis0Value;
myP1AxisValue = Event::SALeftAxis1Value;
myP0FireEvent1 = Event::PaddleZeroFire;
myP0FireEvent2 = Event::JoystickZeroFire1;
myP1FireEvent1 = Event::PaddleOneFire;
myP1FireEvent2 = Event::JoystickZeroFire3;
// 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)
{
myP0DecEvent1 = Event::PaddleZeroDecrease;
myP0DecEvent2 = Event::JoystickZeroRight;
myP0IncEvent1 = Event::PaddleZeroIncrease;
myP0IncEvent2 = Event::JoystickZeroLeft;
myP0FireEvent1 = Event::PaddleZeroFire;
myP0FireEvent2 = Event::JoystickZeroFire1;
myP1AxisValue = Event::SALeftAxis1Value;
myP1DecEvent1 = Event::PaddleOneDecrease;
myP1DecEvent2 = Event::JoystickZeroUp;
myP1DecEvent2 = Event::JoystickZeroDown;
myP1IncEvent1 = Event::PaddleOneIncrease;
myP1IncEvent2 = Event::JoystickZeroDown;
myP1FireEvent1 = Event::PaddleOneFire;
myP1FireEvent2 = Event::JoystickZeroFire3;
if(_MOUSEX_PADDLE < 0) _MOUSEX_PADDLE = 0;
myP1IncEvent2 = Event::JoystickZeroUp;
}
else
{
myP0DecEvent1 = Event::PaddleZeroIncrease;
myP0DecEvent2 = Event::JoystickZeroLeft;
myP0IncEvent1 = Event::PaddleZeroDecrease;
myP0IncEvent2 = Event::JoystickZeroRight;
myP1DecEvent1 = Event::PaddleOneIncrease;
myP1DecEvent2 = Event::JoystickZeroUp;
myP1IncEvent1 = Event::PaddleOneDecrease;
myP1IncEvent2 = Event::JoystickZeroDown;
}
}
else // First paddle is 1, second is 0
{
// These aren't affected by changes in axis orientation
myP0AxisValue = Event::SALeftAxis1Value;
myP0DecEvent1 = Event::PaddleOneDecrease;
myP0DecEvent2 = Event::JoystickZeroUp;
myP0IncEvent1 = Event::PaddleOneIncrease;
myP0IncEvent2 = Event::JoystickZeroDown;
myP1AxisValue = Event::SALeftAxis0Value;
myP0FireEvent1 = Event::PaddleOneFire;
myP0FireEvent2 = Event::JoystickZeroFire3;
myP1FireEvent1 = Event::PaddleZeroFire;
myP1FireEvent2 = Event::JoystickZeroFire1;
myP1AxisValue = Event::SALeftAxis0Value;
// 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)
{
myP0DecEvent1 = Event::PaddleOneDecrease;
myP0DecEvent2 = Event::JoystickZeroDown;
myP0IncEvent1 = Event::PaddleOneIncrease;
myP0IncEvent2 = Event::JoystickZeroUp;
myP1DecEvent1 = Event::PaddleZeroDecrease;
myP1DecEvent2 = Event::JoystickZeroRight;
myP1IncEvent1 = Event::PaddleZeroIncrease;
myP1IncEvent2 = Event::JoystickZeroLeft;
myP1FireEvent1 = Event::PaddleZeroFire;
myP1FireEvent2 = Event::JoystickZeroFire1;
if(_MOUSEX_PADDLE < 0) _MOUSEX_PADDLE = 1;
}
}
else
{
if(!swap)
myP0DecEvent1 = Event::PaddleOneIncrease;
myP0DecEvent2 = Event::JoystickZeroUp;
myP0IncEvent1 = Event::PaddleOneDecrease;
myP0IncEvent2 = Event::JoystickZeroDown;
myP1DecEvent1 = Event::PaddleZeroIncrease;
myP1DecEvent2 = Event::JoystickZeroLeft;
myP1IncEvent1 = Event::PaddleZeroDecrease;
myP1IncEvent2 = Event::JoystickZeroRight;
}
}
}
else // Jack is right port
{
if(!swapport) // First paddle is 2, second is 3
{
// These aren't affected by changes in axis orientation
myP0AxisValue = Event::SARightAxis0Value;
myP1AxisValue = Event::SARightAxis1Value;
myP0FireEvent1 = Event::PaddleTwoFire;
myP0FireEvent2 = Event::JoystickOneFire1;
myP1FireEvent1 = Event::PaddleThreeFire;
myP1FireEvent2 = Event::JoystickOneFire3;
// 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)
{
myP0DecEvent1 = Event::PaddleTwoDecrease;
myP0DecEvent2 = Event::JoystickOneRight;
myP0IncEvent1 = Event::PaddleTwoIncrease;
myP0IncEvent2 = Event::JoystickOneLeft;
myP0FireEvent1 = Event::PaddleTwoFire;
myP0FireEvent2 = Event::JoystickOneFire1;
myP1AxisValue = Event::SARightAxis1Value;
myP1DecEvent1 = Event::PaddleThreeDecrease;
myP1DecEvent2 = Event::JoystickOneUp;
myP1DecEvent2 = Event::JoystickOneDown;
myP1IncEvent1 = Event::PaddleThreeIncrease;
myP1IncEvent2 = Event::JoystickOneDown;
myP1FireEvent1 = Event::PaddleThreeFire;
myP1FireEvent2 = Event::JoystickOneFire3;
if(_MOUSEX_PADDLE < 0) _MOUSEX_PADDLE = 0;
myP1IncEvent2 = Event::JoystickOneUp;
}
else
{
myP0DecEvent1 = Event::PaddleTwoIncrease;
myP0DecEvent2 = Event::JoystickOneLeft;
myP0IncEvent1 = Event::PaddleTwoDecrease;
myP0IncEvent2 = Event::JoystickOneRight;
myP1DecEvent1 = Event::PaddleThreeIncrease;
myP1DecEvent2 = Event::JoystickOneUp;
myP1IncEvent1 = Event::PaddleThreeDecrease;
myP1IncEvent2 = Event::JoystickOneDown;
}
}
else // First paddle is 3, second is 2
{
// These aren't affected by changes in axis orientation
myP0AxisValue = Event::SARightAxis1Value;
myP0DecEvent1 = Event::PaddleThreeDecrease;
myP0DecEvent2 = Event::JoystickOneUp;
myP0IncEvent1 = Event::PaddleThreeIncrease;
myP0IncEvent2 = Event::JoystickOneDown;
myP1AxisValue = Event::SARightAxis0Value;
myP0FireEvent1 = Event::PaddleThreeFire;
myP0FireEvent2 = Event::JoystickOneFire3;
myP1FireEvent1 = Event::PaddleTwoFire;
myP1FireEvent2 = Event::JoystickOneFire1;
myP1AxisValue = Event::SARightAxis0Value;
// 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)
{
myP0DecEvent1 = Event::PaddleThreeDecrease;
myP0DecEvent2 = Event::JoystickOneDown;
myP0IncEvent1 = Event::PaddleThreeIncrease;
myP0IncEvent2 = Event::JoystickOneUp;
myP1DecEvent1 = Event::PaddleTwoDecrease;
myP1DecEvent2 = Event::JoystickOneRight;
myP1IncEvent1 = Event::PaddleTwoIncrease;
myP1IncEvent2 = Event::JoystickOneLeft;
myP1FireEvent1 = Event::PaddleTwoFire;
myP1FireEvent2 = Event::JoystickOneFire1;
if(_MOUSEX_PADDLE < 0) _MOUSEX_PADDLE = 1;
}
else
{
myP0DecEvent1 = Event::PaddleThreeIncrease;
myP0DecEvent2 = Event::JoystickOneUp;
myP0IncEvent1 = Event::PaddleThreeDecrease;
myP0IncEvent2 = Event::JoystickOneDown;
myP1DecEvent1 = Event::PaddleTwoIncrease;
myP1DecEvent2 = Event::JoystickOneLeft;
myP1IncEvent1 = Event::PaddleTwoDecrease;
myP1IncEvent2 = Event::JoystickOneRight;
}
}
}
// The following are independent of whether or not the port
// is left or right
_MOUSE_SENSITIVITY = swapdir ? -abs(_MOUSE_SENSITIVITY) :
abs(_MOUSE_SENSITIVITY);
if(!swapaxis)
{
myAxisMouseMotion = Event::MouseAxisXValue;
myAxisDigitalZero = 0;
myAxisDigitalOne = 1;
}
else
{
myAxisMouseMotion = Event::MouseAxisYValue;
myAxisDigitalZero = 1;
myAxisDigitalOne = 0;
}
// Digital pins 1, 2 and 6 are not connected
@ -122,11 +215,14 @@ Paddles::Paddles(Jack jack, const Event& event, const System& system, bool swap)
myDigitalPinState[Six] = true;
// Digital emulation of analog paddle movement
myKeyRepeat0 = myPaddleRepeat0 = myKeyRepeat1 = myPaddleRepeat1 = 0;
myKeyRepeat0 = myKeyRepeat1 = false;
myPaddleRepeat0 = myPaddleRepeat1 = myLastAxisX = myLastAxisY = 0;
myCharge[0] = myCharge[1] =
myLastCharge[0] = myLastCharge[1] = TRIGMAX/2; // half of maximum paddle charge
myLeftMotion[0] = myLeftMotion[1] = 0;
myCharge[0] = myCharge[1] = 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);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -145,179 +241,138 @@ void Paddles::update()
myDigitalPinState[Four] =
(myEvent.get(myP0FireEvent1) == 0 && myEvent.get(myP0FireEvent2) == 0);
// Paddle movement is a very difficult thing to accurately emulate,
// since it originally came from an analog device that had very
// peculiar behaviour
// Compounding the problem is the fact that we'd like to emulate
// movement with 'digital' data (like from a keyboard or a digital
// joystick axis), but also from a mouse (relative values)
// and Stelladaptor-like devices (absolute analog values clamped to
// a certain range)
// And to top it all off, we don't want one devices input to conflict
// with the others ...
// Analog axis events from Stelladaptor-like devices
// These devices generate data in the range -32768 to 32767,
// so we have to scale appropriately
// Since these events are generated and stored indefinitely,
// 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);
if(abs(myLastAxisX - sa_xaxis) > 10)
{
myAnalogPinValue[Nine] = (Int32)(1400000 *
(float)(32767 - (Int16)sa_xaxis) / 65536.0);
sa_changed = true;
}
if(abs(myLastAxisY - sa_yaxis) > 10)
{
myAnalogPinValue[Five] = (Int32)(1400000 *
(float)(32767 - (Int16)sa_yaxis) / 65536.0);
sa_changed = true;
}
myLastAxisX = sa_xaxis;
myLastAxisY = sa_yaxis;
if(sa_changed)
return;
// Mouse motion events give relative movement
// That is, they're only relevant if they're non-zero
if((myJack == Left && ourControlNum <= 1) ||
(myJack == Right && ourControlNum > 1))
{
int num = ourControlNum & 0x01;
myCharge[num] -=
((myEvent.get(myAxisMouseMotion) >> 1) * _MOUSE_SENSITIVITY);
if(myCharge[num] < TRIGMIN)
myCharge[num] = TRIGMIN;
if(myCharge[num] > TRIGMAX)
myCharge[num] = TRIGMAX;
if(myEvent.get(Event::MouseButtonValue))
myDigitalPinState[ourButtonPin[num]] = false;
}
// Finally, consider digital input, where movement happens
// until a digital event is released
if(myKeyRepeat0)
{
myPaddleRepeat0++;
if(myPaddleRepeat0 > _PADDLE_SPEED) myPaddleRepeat0 = 2;
if(myPaddleRepeat0 > _DIGITAL_SENSITIVITY)
myPaddleRepeat0 = _DIGITAL_DISTANCE;
}
if(myKeyRepeat1)
{
myPaddleRepeat1++;
if(myPaddleRepeat1 > _PADDLE_SPEED) myPaddleRepeat1 = 2;
if(myPaddleRepeat1 > _DIGITAL_SENSITIVITY)
myPaddleRepeat1 = _DIGITAL_DISTANCE;
}
myKeyRepeat0 = 0;
myKeyRepeat1 = 0;
myKeyRepeat0 = false;
myKeyRepeat1 = false;
if(myEvent.get(myP0DecEvent1) || myEvent.get(myP0DecEvent2))
{
myKeyRepeat0 = 1;
if(myCharge[0] > myPaddleRepeat0)
myCharge[0] -= myPaddleRepeat0;
myKeyRepeat0 = true;
if(myCharge[myAxisDigitalZero] > myPaddleRepeat0)
myCharge[myAxisDigitalZero] -= myPaddleRepeat0;
}
if(myEvent.get(myP0IncEvent1) || myEvent.get(myP0IncEvent2))
{
myKeyRepeat0 = 1;
if((myCharge[0] + myPaddleRepeat0) < TRIGMAX)
myCharge[0] += myPaddleRepeat0;
myKeyRepeat0 = true;
if((myCharge[myAxisDigitalZero] + myPaddleRepeat0) < TRIGMAX)
myCharge[myAxisDigitalZero] += myPaddleRepeat0;
}
if(myEvent.get(myP1DecEvent1) || myEvent.get(myP1DecEvent2))
{
myKeyRepeat1 = 1;
if(myCharge[1] > myPaddleRepeat1)
myCharge[1] -= myPaddleRepeat1;
myKeyRepeat1 = true;
if(myCharge[myAxisDigitalOne] > myPaddleRepeat1)
myCharge[myAxisDigitalOne] -= myPaddleRepeat1;
}
if(myEvent.get(myP1IncEvent1) || myEvent.get(myP1IncEvent2))
{
myKeyRepeat1 = 1;
if((myCharge[1] + myPaddleRepeat1) < TRIGMAX)
myCharge[1] += myPaddleRepeat1;
myKeyRepeat1 = true;
if((myCharge[myAxisDigitalOne] + myPaddleRepeat1) < TRIGMAX)
myCharge[myAxisDigitalOne] += myPaddleRepeat1;
}
// Mouse events
if(myJack == Left && (_MOUSEX_PADDLE == 0 || _MOUSEX_PADDLE == 1))
{
// TODO - add infrastructure to map mouse direction to increase or decrease charge
myCharge[_MOUSEX_PADDLE] -= myEvent.get(Event::MouseAxisXValue);
if(myCharge[_MOUSEX_PADDLE] < TRIGMIN) myCharge[_MOUSEX_PADDLE] = TRIGMIN;
if(myCharge[_MOUSEX_PADDLE] > TRIGMAX) myCharge[_MOUSEX_PADDLE] = TRIGMAX;
if(myEvent.get(Event::MouseButtonValue))
myDigitalPinState[ourButtonPin[_MOUSEX_PADDLE]] = false;
}
else if(myJack == Right && (_MOUSEX_PADDLE == 2 || _MOUSEX_PADDLE == 3))
{
// TODO - add infrastructure to map mouse direction to increase or decrease charge
myCharge[_MOUSEX_PADDLE-2] -= myEvent.get(Event::MouseAxisXValue);
if(myCharge[_MOUSEX_PADDLE-2] < TRIGMIN) myCharge[_MOUSEX_PADDLE-2] = TRIGMIN;
if(myCharge[_MOUSEX_PADDLE-2] > TRIGMAX) myCharge[_MOUSEX_PADDLE-2] = TRIGMAX;
if(myEvent.get(Event::MouseButtonValue))
myDigitalPinState[ourButtonPin[_MOUSEX_PADDLE-2]] = false;
}
// Only change state if the charge has actually changed
if(myCharge[1] != myLastCharge[1])
myAnalogPinValue[Five] =
(Int32)(1400000 * (myCharge[1] / float(TRIGRANGE)));
if(myCharge[0] != myLastCharge[0])
myAnalogPinValue[Nine] =
(Int32)(1400000 * (myCharge[0] / float(TRIGRANGE)));
// Axis events (possibly use analog values)
int xaxis = myEvent.get(myP0AxisValue);
int yaxis = myEvent.get(myP1AxisValue);
// Filter out jitter by not allowing rapid direction changes
int charge0 = ((32767 - xaxis) >> 8) & 0xff;
if(charge0 - myLastCharge[0] > 0) // we are moving left
{
if(!myLeftMotion[0]) // moving right before?
{
if(charge0 - myLastCharge[0] <= 4)
{
myCharge[0] = myLastCharge[0];
}
else
{
myCharge[0] = (charge0 + myLastCharge[0]) >> 1;
myLastCharge[0] = charge0;
myLeftMotion[0] = 1;
}
}
else
{
myCharge[0] = (charge0 + myLastCharge[0]) >> 1;
myLastCharge[0] = charge0;
}
}
// Filter out jitter by not allowing rapid direction changes
else if(charge0 - myLastCharge[0] < 0) // we are moving right
{
if(myLeftMotion[0]) // moving left before?
{
if(myLastCharge[0] - charge0 <= 4)
{
myCharge[0] = myLastCharge[0];
}
else
{
myCharge[0] = (charge0 + myLastCharge[0]) >> 1;
myLastCharge[0] = charge0;
myLeftMotion[0] = 0;
}
}
else
{
myCharge[0] = (charge0 + myLastCharge[0]) >> 1;
myLastCharge[0] = charge0;
}
}
// Filter out jitter by not allowing rapid direction changes
int charge1 = ((32767 - yaxis) >> 8) & 0xff;
if(charge1 - myLastCharge[1] > 0) // we are moving left
{
if(!myLeftMotion[1]) // moving right before?
{
if(charge1 - myLastCharge[1] <= 4)
{
myCharge[1] = myLastCharge[1];
}
else
{
myCharge[1] = (charge1 + myLastCharge[1]) >> 1;
myLastCharge[1] = charge1;
myLeftMotion[1] = 1;
}
}
else
{
myCharge[1] = (charge1 + myLastCharge[1]) >> 1;
myLastCharge[1] = charge1;
}
}
// Filter out jitter by not allowing rapid direction changes
else if(charge1 - myLastCharge[1] < 0) // we are moving right
{
if(myLeftMotion[1]) // moving left before?
{
if(myLastCharge[1] - charge1 <= 4)
{
myCharge[1] = myLastCharge[1];
}
else
{
myCharge[1] = (charge1 + myLastCharge[1]) >> 1;
myLastCharge[1] = charge1;
myLeftMotion[1] = 0;
}
}
else
{
myCharge[1] = (charge1 + myLastCharge[1]) >> 1;
myLastCharge[1] = charge1;
}
}
myAnalogPinValue[Five] = (Int32)(1400000 * (myCharge[1] / 255.0));
myAnalogPinValue[Nine] = (Int32)(1400000 * (myCharge[0] / 255.0));
myLastCharge[1] = myCharge[1];
myLastCharge[0] = myCharge[0];
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Paddles::setMouseIsPaddle(int number, int dir)
void Paddles::setDigitalSensitivity(int sensitivity)
{
// TODO - make mouse Y axis be actually used in the code above
if(dir == 0)
_MOUSEX_PADDLE = number;
else
_MOUSEY_PADDLE = number;
if(sensitivity < 1) sensitivity = 1;
else if(sensitivity > 10) sensitivity = 10;
_DIGITAL_SENSITIVITY = sensitivity;
_DIGITAL_DISTANCE = 20 + (sensitivity << 3);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int Paddles::_PADDLE_SPEED = 6;
int Paddles::_MOUSEX_PADDLE = -1;
int Paddles::_MOUSEY_PADDLE = -1;
void Paddles::setMouseSensitivity(int sensitivity)
{
if(sensitivity < 1) sensitivity = 1;
else if(sensitivity > 15) sensitivity = 15;
_MOUSE_SENSITIVITY = sensitivity;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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

@ -39,9 +39,15 @@ class Paddles : public Controller
@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
@param swap Whether to swap the paddles plugged into this jack
@param swapport Whether to swap the paddles plugged into this jack
@param swapaxis Whether to swap the axis on the paddle (x <-> y)
@param swapdir Whether to swap the direction for which an axis
causes movement (lesser axis values cause paddle
resistance to decrease instead of increase)
*/
Paddles(Jack jack, const Event& event, const System& system, bool swap);
Paddles(Jack jack, const Event& event, const System& system,
bool swapport, bool swapaxis, bool swapdir);
/**
Destructor
@ -56,39 +62,50 @@ class Paddles : public Controller
virtual void update();
/**
Sets the speed for digital emulation of paddle movement.
This is only used for *digital* events (ie, buttons or keys
generating paddle movement events); axis events from joysticks,
Stelladaptors or the mouse are not modified.
Sets the sensitivity for digital emulation of paddle movement.
This is only used for *digital* events (ie, buttons or keys,
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
*/
static void setDigitalSpeed(int speed) { _PADDLE_SPEED = speed; }
static void setDigitalSensitivity(int sensitivity);
/**
Sets the mouse to emulate the paddle 'number' in the X or Y
axis. X -> dir 0, Y -> dir 1
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
*/
static void setMouseIsPaddle(int number, int dir = 0);
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
};
// 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,
myP0DecEvent1, myP0DecEvent2, myP0IncEvent1, myP0IncEvent2,
myP1DecEvent1, myP1DecEvent2, myP1IncEvent1, myP1IncEvent2,
myP0FireEvent1, myP0FireEvent2, myP1FireEvent1, myP1FireEvent2;
myP0FireEvent1, myP0FireEvent2, myP1FireEvent1, myP1FireEvent2,
myAxisMouseMotion;
int myKeyRepeat0;
int myPaddleRepeat0;
int myKeyRepeat1;
int myPaddleRepeat1;
bool myKeyRepeat0, myKeyRepeat1;
int myPaddleRepeat0, myPaddleRepeat1;
int myCharge[2], myLastCharge[2];
int myLastAxisX, myLastAxisY;
int myAxisDigitalZero, myAxisDigitalOne;
int myCharge[2];
int myLastCharge[2];
int myLeftMotion[2];
static int _PADDLE_SPEED;
static int _MOUSEX_PADDLE;
static int _MOUSEY_PADDLE;
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

@ -54,7 +54,6 @@ Settings::Settings(OSystem* osystem)
setInternal("fullscreen", "0");
setInternal("fullres", "auto");
setInternal("center", "false");
setInternal("grabmouse", "false");
setInternal("palette", "standard");
setInternal("colorloss", "false");
setInternal("timing", "sleep");
@ -84,7 +83,8 @@ Settings::Settings(OSystem* osystem)
setInternal("joydeadzone", "13");
setInternal("joyallow4", "false");
setInternal("usemouse", "true");
setInternal("pspeed", "6");
setInternal("dsense", "5");
setInternal("msense", "7");
setInternal("sa1", "left");
setInternal("sa2", "right");
setInternal("ctrlcombo", "true");
@ -284,9 +284,13 @@ void Settings::validate()
if(i < 0) setInternal("joydeadzone", "0");
else if(i > 29) setInternal("joydeadzone", "29");
i = getInt("pspeed");
if(i < 1) setInternal("pspeed", "1");
else if(i > 15) setInternal("pspeed", "15");
i = getInt("dsense");
if(i < 1) setInternal("dsense", "1");
else if(i > 10) setInternal("dsense", "10");
i = getInt("msense");
if(i < 1) setInternal("msense", "1");
else if(i > 15) setInternal("msense", "15");
i = getInt("ssinterval");
if(i < 1) setInternal("ssinterval", "2");
@ -366,7 +370,6 @@ void Settings::usage()
<< " -fullscreen <1|0|-1> Use fullscreen mode (1 or 0), or disable switching to fullscreen entirely\n"
<< " -fullres <auto|WxH> The resolution to use in fullscreen mode\n"
<< " -center <1|0> Centers game window (if possible)\n"
<< " -grabmouse <1|0> Keeps the mouse in the game window\n"
<< " -palette <standard| Use the specified color palette\n"
<< " z26|\n"
<< " user>\n"
@ -389,7 +392,8 @@ void Settings::usage()
<< " -joydeadzone <number> Sets 'deadzone' area for analog joysticks (0-29)\n"
<< " -joyallow4 <1|0> Allow all 4 directions on a joystick to be pressed simultaneously\n"
<< " -usemouse <1|0> Use mouse for various controllers (paddle, driving, etc)\n"
<< " -pspeed <number> Speed of digital emulated paddle movement (1-15)\n"
<< " -dsense <number> Sensitivity of digital emulated paddle movement (1-10)\n"
<< " -msense <number> Sensitivity of mouse emulated paddle movement (1-15)\n"
<< " -sa1 <left|right> Stelladaptor 1 emulates specified joystick port\n"
<< " -sa2 <left|right> Stelladaptor 2 emulates specified joystick port\n"
<< " -ctrlcombo <1|0> Use key combos involving the Control key (Control-Q for quit may be disabled!)\n"

View File

@ -71,20 +71,20 @@ void Switches::update()
mySwitches &= ~0x08;
}
if(myEvent.get(Event::ConsoleRightDifficultyA) != 0)
if(myEvent.get(Event::ConsoleRightDiffA) != 0)
{
mySwitches |= 0x80;
}
else if(myEvent.get(Event::ConsoleRightDifficultyB) != 0)
else if(myEvent.get(Event::ConsoleRightDiffB) != 0)
{
mySwitches &= ~0x80;
}
if(myEvent.get(Event::ConsoleLeftDifficultyA) != 0)
if(myEvent.get(Event::ConsoleLeftDiffA) != 0)
{
mySwitches |= 0x40;
}
else if(myEvent.get(Event::ConsoleLeftDifficultyB) != 0)
else if(myEvent.get(Event::ConsoleLeftDiffB) != 0)
{
mySwitches &= ~0x40;
}

View File

@ -126,22 +126,22 @@ void CommandDialog::handleCommand(CommandSender* sender, int cmd,
break;
case kLeftDiffACmd:
event = Event::ConsoleLeftDifficultyA;
event = Event::ConsoleLeftDiffA;
consoleCmd = true;
break;
case kLeftDiffBCmd:
event = Event::ConsoleLeftDifficultyB;
event = Event::ConsoleLeftDiffB;
consoleCmd = true;
break;
case kRightDiffACmd:
event = Event::ConsoleRightDifficultyA;
event = Event::ConsoleRightDiffA;
consoleCmd = true;
break;
case kRightDiffBCmd:
event = Event::ConsoleRightDifficultyB;
event = Event::ConsoleRightDiffB;
consoleCmd = true;
break;

View File

@ -140,13 +140,13 @@ void InputDialog::addDevicePortTab(const GUI::Font& font)
fwidth, fontHeight, "");
wid.push_back(myAVoxPort);
lwidth = font.getStringWidth("Digital paddle speed: ");
lwidth = font.getStringWidth("Digital paddle sensitivity: ");
pwidth = font.getMaxCharWidth() * 8;
// Add joystick deadzone setting
ypos += 2*lineHeight;
ypos += lineHeight + 5;
myDeadzone = new SliderWidget(myTab, font, xpos, ypos, pwidth, lineHeight,
"Joystick deadzone: ", lwidth, kDeadzoneChanged);
"Joystick deadzone size: ", lwidth, kDeadzoneChanged);
myDeadzone->setMinValue(0); myDeadzone->setMaxValue(29);
xpos += myDeadzone->getWidth() + 5;
myDeadzoneLabel = new StaticTextWidget(myTab, font, xpos, ypos+1, 5*fontWidth,
@ -154,17 +154,29 @@ void InputDialog::addDevicePortTab(const GUI::Font& font)
myDeadzoneLabel->setFlags(WIDGET_CLEARBG);
wid.push_back(myDeadzone);
// Add paddle speed
// Add paddle speed (digital emulation)
xpos = 5; ypos += lineHeight + 3;
myPaddleSpeed = new SliderWidget(myTab, font, xpos, ypos, pwidth, lineHeight,
"Digital paddle speed: ",
lwidth, kPSpeedChanged);
myPaddleSpeed->setMinValue(1); myPaddleSpeed->setMaxValue(15);
xpos += myPaddleSpeed->getWidth() + 5;
myPaddleLabel = new StaticTextWidget(myTab, font, xpos, ypos+1, 24, lineHeight,
myDPaddleSpeed = new SliderWidget(myTab, font, xpos, ypos, pwidth, lineHeight,
"Digital paddle sensitivity: ",
lwidth, kDPSpeedChanged);
myDPaddleSpeed->setMinValue(1); myDPaddleSpeed->setMaxValue(10);
xpos += myDPaddleSpeed->getWidth() + 5;
myDPaddleLabel = new StaticTextWidget(myTab, font, xpos, ypos+1, 24, lineHeight,
"", kTextAlignLeft);
myPaddleLabel->setFlags(WIDGET_CLEARBG);
wid.push_back(myPaddleSpeed);
myDPaddleLabel->setFlags(WIDGET_CLEARBG);
wid.push_back(myDPaddleSpeed);
// Add paddle speed (mouse emulation)
xpos = 5; ypos += lineHeight + 3;
myMPaddleSpeed = new SliderWidget(myTab, font, xpos, ypos, pwidth, lineHeight,
"Mouse paddle sensitivity: ",
lwidth, kMPSpeedChanged);
myMPaddleSpeed->setMinValue(1); myMPaddleSpeed->setMaxValue(15);
xpos += myMPaddleSpeed->getWidth() + 5;
myMPaddleLabel = new StaticTextWidget(myTab, font, xpos, ypos+1, 24, lineHeight,
"", kTextAlignLeft);
myMPaddleSpeed->setFlags(WIDGET_CLEARBG);
wid.push_back(myMPaddleSpeed);
// Add 'allow all 4 directions' for joystick
xpos = 10; ypos += 2*lineHeight;
@ -201,9 +213,11 @@ void InputDialog::loadConfig()
bool usemouse = instance().settings().getBool("usemouse");
myMouseEnabled->setState(usemouse);
// Paddle speed
myPaddleSpeed->setValue(instance().settings().getInt("pspeed"));
myPaddleLabel->setLabel(instance().settings().getString("pspeed"));
// Paddle speed (digital and mouse)
myDPaddleSpeed->setValue(instance().settings().getInt("dsense"));
myDPaddleLabel->setLabel(instance().settings().getString("dsense"));
myMPaddleSpeed->setValue(instance().settings().getInt("msense"));
myMPaddleLabel->setLabel(instance().settings().getString("msense"));
// AtariVox serial port
myAVoxPort->setEditString(instance().settings().getString("avoxport"));
@ -230,12 +244,15 @@ void InputDialog::saveConfig()
// Mouse/paddle enabled
bool usemouse = myMouseEnabled->getState();
instance().settings().setBool("usemouse", usemouse);
instance().eventHandler().setPaddleMode(usemouse ? 0 : -1);
instance().eventHandler().setMouseControllerMode(usemouse ? 0 : -1);
// Paddle speed
int speed = myPaddleSpeed->getValue();
instance().settings().setInt("pspeed", speed);
Paddles::setDigitalSpeed(speed);
// Paddle speed (digital and mouse)
int sensitivity = myDPaddleSpeed->getValue();
instance().settings().setInt("dsense", sensitivity);
Paddles::setDigitalSensitivity(sensitivity);
sensitivity = myMPaddleSpeed->getValue();
instance().settings().setInt("msense", sensitivity);
Paddles::setMouseSensitivity(sensitivity);
// AtariVox serial port
instance().settings().setString("avoxport", myAVoxPort->getEditString());
@ -272,9 +289,11 @@ void InputDialog::setDefaults()
// Mouse/paddle enabled
myMouseEnabled->setState(true);
// Paddle speed
myPaddleSpeed->setValue(6);
myPaddleLabel->setLabel("6");
// Paddle speed (digital and mouse)
myDPaddleSpeed->setValue(5);
myDPaddleLabel->setLabel("5");
myMPaddleSpeed->setValue(6);
myMPaddleLabel->setLabel("6");
// AtariVox serial port
myAVoxPort->setEditString("");
@ -373,8 +392,12 @@ void InputDialog::handleCommand(CommandSender* sender, int cmd,
myDeadzoneLabel->setValue(3200 + 1000*myDeadzone->getValue());
break;
case kPSpeedChanged:
myPaddleLabel->setValue(myPaddleSpeed->getValue());
case kDPSpeedChanged:
myDPaddleLabel->setValue(myDPaddleSpeed->getValue());
break;
case kMPSpeedChanged:
myMPaddleLabel->setValue(myMPaddleSpeed->getValue());
break;
default:

View File

@ -59,7 +59,8 @@ class InputDialog : public Dialog
kLeftChanged = 'LCch',
kRightChanged = 'RCch',
kDeadzoneChanged = 'DZch',
kPSpeedChanged = 'PSch'
kDPSpeedChanged = 'PDch',
kMPSpeedChanged = 'PMch'
};
TabWidget* myTab;
@ -74,8 +75,10 @@ class InputDialog : public Dialog
SliderWidget* myDeadzone;
StaticTextWidget* myDeadzoneLabel;
SliderWidget* myPaddleSpeed;
StaticTextWidget* myPaddleLabel;
SliderWidget* myDPaddleSpeed;
SliderWidget* myMPaddleSpeed;
StaticTextWidget* myDPaddleLabel;
StaticTextWidget* myMPaddleLabel;
CheckboxWidget* myAllowAll4;
CheckboxWidget* myMouseEnabled;
};

View File

@ -213,12 +213,6 @@ VideoDialog::VideoDialog(OSystem* osystem, DialogContainer* parent,
wid.push_back(myUseVSyncCheckbox);
ypos += lineHeight + 4;
// Grab mouse (in windowed mode)
myGrabmouseCheckbox = new CheckboxWidget(myTab, font, xpos, ypos,
"Grab mouse");
wid.push_back(myGrabmouseCheckbox);
ypos += lineHeight + 4;
// Show UI messages onscreen
myUIMessagesCheckbox = new CheckboxWidget(myTab, font, xpos, ypos,
"Show UI messages");
@ -344,7 +338,6 @@ VideoDialog::VideoDialog(OSystem* osystem, DialogContainer* parent,
#endif
#ifndef WINDOWED_SUPPORT
myFullscreenCheckbox->clearFlags(WIDGET_ENABLED);
myGrabmouseCheckbox->clearFlags(WIDGET_ENABLED);
myCenterCheckbox->clearFlags(WIDGET_ENABLED);
#endif
#if !(defined(BSPF_WIN32) || (defined(BSPF_UNIX) && defined(HAVE_X11)))
@ -425,9 +418,6 @@ void VideoDialog::loadConfig()
myUseVSyncCheckbox->setState(instance().settings().getBool("gl_vsync"));
myUseVSyncCheckbox->setEnabled(gl);
// Grab mouse
myGrabmouseCheckbox->setState(instance().settings().getBool("grabmouse"));
// Show UI messages
myUIMessagesCheckbox->setState(instance().settings().getBool("uimessages"));
@ -522,10 +512,6 @@ void VideoDialog::saveConfig()
// Use sync to vertical blank (GL mode only)
instance().settings().setBool("gl_vsync", myUseVSyncCheckbox->getState());
// Grab mouse
instance().settings().setBool("grabmouse", myGrabmouseCheckbox->getState());
instance().frameBuffer().setCursorState();
// Show UI messages
instance().settings().setBool("uimessages", myUIMessagesCheckbox->getState());
@ -572,7 +558,6 @@ void VideoDialog::setDefaults()
myColorLossCheckbox->setState(false);
myGLStretchCheckbox->setState(false);
myUseVSyncCheckbox->setState(true);
myGrabmouseCheckbox->setState(false);
myUIMessagesCheckbox->setState(true);
myCenterCheckbox->setState(false);
myFastSCBiosCheckbox->setState(false);

View File

@ -75,7 +75,6 @@ class VideoDialog : public Dialog
CheckboxWidget* myUseVSyncCheckbox;
CheckboxWidget* myUIMessagesCheckbox;
CheckboxWidget* myCenterCheckbox;
CheckboxWidget* myGrabmouseCheckbox;
CheckboxWidget* myFastSCBiosCheckbox;
// TV effects options

View File

@ -37,7 +37,6 @@
IBOutlet id mousePaddle1MenuItem;
IBOutlet id mousePaddle2MenuItem;
IBOutlet id mousePaddle3MenuItem;
IBOutlet id grabMouseMenuItem;
IBOutlet id increaseVolumeMenuItem;
IBOutlet id decreaseVolumeMenuItem;
}
@ -50,7 +49,6 @@
- (IBAction)fullScreen:(id)sender;
- (IBAction)openCart:(id)sender;
- (IBAction)restartGame:(id)sender;
- (IBAction)grabMouse:(id)sender;
- (IBAction)doPrefs:(id)sender;
- (IBAction)volumePlus:(id)sender;
- (IBAction)volumeMinus:(id)sender;

View File

@ -197,11 +197,6 @@ static Menus *sharedInstance = nil;
[self pushKeyEvent:SDLK_r:NO:NO:YES];
}
- (IBAction)grabMouse:(id)sender
{
[self pushKeyEvent:SDLK_g:NO:NO:YES];
}
- (IBAction)doPrefs:(id)sender
{
[self pushKeyEvent:SDLK_TAB:NO:NO:NO];
@ -229,7 +224,6 @@ static Menus *sharedInstance = nil;
[mousePaddle1MenuItem setTarget:self];
[mousePaddle2MenuItem setTarget:self];
[mousePaddle3MenuItem setTarget:self];
[grabMouseMenuItem setTarget:self];
[increaseVolumeMenuItem setTarget:self];
[decreaseVolumeMenuItem setTarget:self];
}
@ -246,7 +240,6 @@ static Menus *sharedInstance = nil;
[mousePaddle1MenuItem setTarget:nil];
[mousePaddle2MenuItem setTarget:nil];
[mousePaddle3MenuItem setTarget:nil];
[grabMouseMenuItem setTarget:nil];
[increaseVolumeMenuItem setTarget:nil];
[decreaseVolumeMenuItem setTarget:nil];
}
@ -263,7 +256,6 @@ static Menus *sharedInstance = nil;
[mousePaddle1MenuItem setTarget:nil];
[mousePaddle2MenuItem setTarget:nil];
[mousePaddle3MenuItem setTarget:nil];
[grabMouseMenuItem setTarget:nil];
[increaseVolumeMenuItem setTarget:nil];
[decreaseVolumeMenuItem setTarget:nil];
}
@ -280,7 +272,6 @@ static Menus *sharedInstance = nil;
[mousePaddle1MenuItem setTarget:nil];
[mousePaddle2MenuItem setTarget:nil];
[mousePaddle3MenuItem setTarget:nil];
[grabMouseMenuItem setTarget:nil];
[increaseVolumeMenuItem setTarget:nil];
[decreaseVolumeMenuItem setTarget:nil];
}
@ -297,7 +288,6 @@ static Menus *sharedInstance = nil;
[mousePaddle1MenuItem setTarget:nil];
[mousePaddle2MenuItem setTarget:nil];
[mousePaddle3MenuItem setTarget:nil];
[grabMouseMenuItem setTarget:nil];
[increaseVolumeMenuItem setTarget:nil];
[decreaseVolumeMenuItem setTarget:nil];
}