mirror of https://github.com/stella-emu/stella.git
505 lines
14 KiB
C++
505 lines
14 KiB
C++
//============================================================================
|
|
//
|
|
// 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-2010 by Bradford W. Mott 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.
|
|
//
|
|
// $Id$
|
|
//============================================================================
|
|
|
|
#ifndef EVENTHANDLER_HXX
|
|
#define EVENTHANDLER_HXX
|
|
|
|
#include <SDL.h>
|
|
|
|
class Console;
|
|
class OSystem;
|
|
class DialogContainer;
|
|
class EventMappingWidget;
|
|
|
|
#include "Array.hxx"
|
|
#include "Event.hxx"
|
|
#include "Control.hxx"
|
|
#include "StringList.hxx"
|
|
#include "bspf.hxx"
|
|
|
|
|
|
enum MouseButton {
|
|
EVENT_LBUTTONDOWN,
|
|
EVENT_LBUTTONUP,
|
|
EVENT_RBUTTONDOWN,
|
|
EVENT_RBUTTONUP,
|
|
EVENT_WHEELDOWN,
|
|
EVENT_WHEELUP
|
|
};
|
|
|
|
enum EventMode {
|
|
kEmulationMode = 0, // make sure these are set correctly,
|
|
kMenuMode = 1, // since they'll be used as array indices
|
|
kNumModes = 2
|
|
};
|
|
|
|
/**
|
|
This class takes care of event remapping and dispatching for the
|
|
Stella core, as well as keeping track of the current 'mode'.
|
|
|
|
The frontend will send translated events here, and the handler will
|
|
check to see what the current 'mode' is.
|
|
|
|
If in emulation mode, events received from the frontend are remapped and
|
|
sent to the emulation core. If in menu mode, the events are sent
|
|
unchanged to the menu class, where (among other things) changing key
|
|
mapping can take place.
|
|
|
|
@author Stephen Anthony
|
|
@version $Id$
|
|
*/
|
|
class EventHandler
|
|
{
|
|
public:
|
|
/**
|
|
Create a new event handler object
|
|
*/
|
|
EventHandler(OSystem* osystem);
|
|
|
|
/**
|
|
Destructor
|
|
*/
|
|
virtual ~EventHandler();
|
|
|
|
// Enumeration representing the different states of operation
|
|
enum State {
|
|
S_NONE,
|
|
S_EMULATE,
|
|
S_PAUSE,
|
|
S_LAUNCHER,
|
|
S_MENU,
|
|
S_CMDMENU,
|
|
S_DEBUGGER
|
|
};
|
|
|
|
/**
|
|
Returns the event object associated with this handler class.
|
|
|
|
@return The event object
|
|
*/
|
|
Event* event() { return myEvent; }
|
|
|
|
/**
|
|
Initialize state of this eventhandler.
|
|
*/
|
|
void initialize();
|
|
|
|
/**
|
|
Set up any joysticks on the system. This must be called *after* the
|
|
framebuffer has been created, since SDL requires the video to be
|
|
intialized before joysticks can be probed.
|
|
*/
|
|
void setupJoysticks();
|
|
|
|
/**
|
|
Maps the given stelladaptors to specified ports on a real 2600
|
|
|
|
@param sa1 Port for the first Stelladaptor to emulate (left or right)
|
|
@param sa2 Port for the second Stelladaptor to emulate (left or right)
|
|
*/
|
|
void mapStelladaptors(const string& sa1, const string& sa2);
|
|
|
|
/**
|
|
Collects and dispatches any pending events. This method should be
|
|
called regularly (at X times per second, where X is the game framerate).
|
|
|
|
@param time The current time in microseconds.
|
|
*/
|
|
void poll(uInt64 time);
|
|
|
|
/**
|
|
Set the default action for a joystick button to the given event
|
|
|
|
@param event The event we are assigning
|
|
@param mode The mode where this event is active
|
|
@param stick The joystick number
|
|
@param button The joystick button
|
|
*/
|
|
void setDefaultJoyMapping(Event::Type event, EventMode mode,
|
|
int stick, int button);
|
|
|
|
/**
|
|
Set the default for a joystick axis to the given event
|
|
|
|
@param event The event we are assigning
|
|
@param mode The mode where this event is active
|
|
@param stick The joystick number
|
|
@param axis The joystick axis
|
|
@param value The value on the given axis
|
|
*/
|
|
void setDefaultJoyAxisMapping(Event::Type event, EventMode mode,
|
|
int stick, int axis, int value);
|
|
|
|
/**
|
|
Set the default for a joystick hat to the given event
|
|
|
|
@param event The event we are assigning
|
|
@param mode The mode where this event is active
|
|
@param stick The joystick number
|
|
@param axis The joystick axis
|
|
@param value The value on the given axis
|
|
*/
|
|
void setDefaultJoyHatMapping(Event::Type event, EventMode mode,
|
|
int stick, int hat, int value);
|
|
|
|
/**
|
|
Returns the current state of the EventHandler
|
|
|
|
@return The State type
|
|
*/
|
|
inline State state() { return myState; }
|
|
|
|
/**
|
|
Resets the state machine of the EventHandler to the defaults
|
|
|
|
@param state The current state to set
|
|
*/
|
|
void reset(State state);
|
|
|
|
/**
|
|
This method indicates that the system should terminate.
|
|
*/
|
|
void quit() { handleEvent(Event::Quit, 1); }
|
|
|
|
/**
|
|
Sets the mouse to act as paddle 'num'
|
|
|
|
@param num The paddle which the mouse should emulate
|
|
@param showmessage Print a message to the framebuffer
|
|
*/
|
|
void setPaddleMode(int num, bool showmessage = false);
|
|
|
|
inline bool kbdAlt(int mod)
|
|
{
|
|
#ifndef MAC_OSX
|
|
return (mod & KMOD_ALT);
|
|
#else
|
|
return (mod & KMOD_META);
|
|
#endif
|
|
}
|
|
|
|
inline bool kbdControl(int mod)
|
|
{
|
|
return (mod & KMOD_CTRL) > 0;
|
|
}
|
|
|
|
inline bool kbdShift(int mod)
|
|
{
|
|
return (mod & KMOD_SHIFT);
|
|
}
|
|
|
|
void enterMenuMode(State state);
|
|
void leaveMenuMode();
|
|
bool enterDebugMode();
|
|
void leaveDebugMode();
|
|
void takeSnapshot();
|
|
|
|
/**
|
|
Send an event directly to the event handler.
|
|
These events cannot be remapped.
|
|
|
|
@param type The event
|
|
@param value The value for the event
|
|
*/
|
|
void handleEvent(Event::Type type, Int32 value);
|
|
|
|
inline bool frying() { return myFryingFlag; }
|
|
|
|
inline SDL_Joystick* getJoystick(int i) { return ourJoysticks[i].stick; }
|
|
|
|
StringList getActionList(EventMode mode);
|
|
|
|
inline Event::Type eventForKey(int key, EventMode mode)
|
|
{ return myKeyTable[key][mode]; }
|
|
inline Event::Type eventForJoyButton(int stick, int button, EventMode mode)
|
|
{ return myJoyTable[stick][button][mode]; }
|
|
inline Event::Type eventForJoyAxis(int stick, int axis, int value, EventMode mode)
|
|
{ return myJoyAxisTable[stick][axis][(value > 0)][mode]; }
|
|
inline Event::Type eventForJoyHat(int stick, int hat, int value, EventMode mode)
|
|
{ return myJoyHatTable[stick][hat][value][mode]; }
|
|
|
|
Event::Type eventAtIndex(int idx, EventMode mode);
|
|
string actionAtIndex(int idx, EventMode mode);
|
|
string keyAtIndex(int idx, EventMode mode);
|
|
|
|
/**
|
|
Bind a key to an event/action and regenerate the mapping array(s)
|
|
|
|
@param event The event we are remapping
|
|
@param mode The mode where this event is active
|
|
@param key The key to bind to this event
|
|
*/
|
|
bool addKeyMapping(Event::Type event, EventMode mode, int key);
|
|
|
|
/**
|
|
Bind a joystick button to an event/action and regenerate the
|
|
mapping array(s)
|
|
|
|
@param event The event we are remapping
|
|
@param mode The mode where this event is active
|
|
@param stick The joystick number
|
|
@param button The joystick button
|
|
*/
|
|
bool addJoyMapping(Event::Type event, EventMode mode, int stick, int button);
|
|
|
|
/**
|
|
Bind a joystick axis direction to an event/action and regenerate
|
|
the mapping array(s)
|
|
|
|
@param event The event we are remapping
|
|
@param mode The mode where this event is active
|
|
@param stick The joystick number
|
|
@param axis The joystick axis
|
|
@param value The value on the given axis
|
|
*/
|
|
bool addJoyAxisMapping(Event::Type event, EventMode mode,
|
|
int stick, int axis, int value);
|
|
|
|
/**
|
|
Bind a joystick hat direction to an event/action and regenerate
|
|
the mapping array(s)
|
|
|
|
@param event The event we are remapping
|
|
@param mode The mode where this event is active
|
|
@param stick The joystick number
|
|
@param axis The joystick hat
|
|
@param value The value on the given hat
|
|
*/
|
|
bool addJoyHatMapping(Event::Type event, EventMode mode,
|
|
int stick, int hat, int value);
|
|
|
|
/**
|
|
Erase the specified mapping
|
|
|
|
@event The event for which we erase all mappings
|
|
@param mode The mode where this event is active
|
|
*/
|
|
void eraseMapping(Event::Type event, EventMode mode);
|
|
|
|
/**
|
|
Resets the event mappings to default values
|
|
|
|
@param mode The mode for which the defaults are set
|
|
*/
|
|
void setDefaultMapping(EventMode mode);
|
|
|
|
/**
|
|
Joystick emulates 'impossible' directions (ie, left & right
|
|
at the same time)
|
|
|
|
@param allow Whether or not to allow impossible directions
|
|
*/
|
|
void allowAllDirections(bool allow) { myAllowAllDirectionsFlag = allow; }
|
|
|
|
private:
|
|
/**
|
|
Send a mouse motion event to the handler.
|
|
|
|
@param event The mouse motion event generated by SDL
|
|
*/
|
|
void handleMouseMotionEvent(SDL_Event& event);
|
|
|
|
/**
|
|
Send a mouse button event to the handler.
|
|
|
|
@param event The mouse button event generated by SDL
|
|
*/
|
|
void handleMouseButtonEvent(SDL_Event& event, int state);
|
|
|
|
/**
|
|
Send a joystick button event to the handler
|
|
|
|
@param stick The joystick number
|
|
@param button The joystick button
|
|
@param state The state of the button (pressed or released)
|
|
*/
|
|
void handleJoyEvent(int stick, int button, int state);
|
|
|
|
/**
|
|
Send a joystick axis event to the handler
|
|
|
|
@param stick The joystick number
|
|
@param axis The joystick axis
|
|
@param value The value on the given axis
|
|
*/
|
|
void handleJoyAxisEvent(int stick, int axis, int value);
|
|
|
|
/**
|
|
Send a joystick hat event to the handler
|
|
|
|
@param stick The joystick number
|
|
@param axis The joystick hat
|
|
@param value The value on the given hat
|
|
*/
|
|
void handleJoyHatEvent(int stick, int hat, int value);
|
|
|
|
/**
|
|
Detects and changes the eventhandler state
|
|
|
|
@param type The event
|
|
@return True if the state changed, else false
|
|
*/
|
|
inline bool eventStateChange(Event::Type type);
|
|
|
|
/**
|
|
The following methods take care of assigning action mappings.
|
|
*/
|
|
void setActionMappings(EventMode mode);
|
|
void setSDLMappings();
|
|
void setKeymap();
|
|
void setJoymap();
|
|
void setJoyAxisMap();
|
|
void setJoyHatMap();
|
|
void setDefaultKeymap(EventMode mode);
|
|
void setDefaultJoymap(EventMode mode);
|
|
void setDefaultJoyAxisMap(EventMode mode);
|
|
void setDefaultJoyHatMap(EventMode mode);
|
|
void saveKeyMapping();
|
|
void saveJoyMapping();
|
|
void saveJoyAxisMapping();
|
|
void saveJoyHatMapping();
|
|
|
|
/**
|
|
Tests if a mapping list is valid, both by length and by event count.
|
|
|
|
@param list The string containing the mappings, separated by ':'
|
|
@param map The result of parsing the string for int mappings
|
|
@param length The number of items that should be in the list
|
|
|
|
@return True if valid list, else false
|
|
*/
|
|
bool isValidList(string& list, IntArray& map, uInt32 length);
|
|
|
|
/**
|
|
Tests if a given event should use continuous/analog values.
|
|
|
|
@param event The event to test for analog processing
|
|
@return True if analog, else false
|
|
*/
|
|
inline bool eventIsAnalog(Event::Type event);
|
|
|
|
void setEventState(State state);
|
|
|
|
private:
|
|
enum {
|
|
kEmulActionListSize = 75,
|
|
kMenuActionListSize = 14
|
|
};
|
|
|
|
// Structure used for action menu items
|
|
struct ActionList {
|
|
Event::Type event;
|
|
const char* action;
|
|
char* key;
|
|
};
|
|
|
|
// Joystick related items
|
|
enum {
|
|
kNumJoysticks = 8,
|
|
kNumJoyButtons = 24,
|
|
kNumJoyAxis = 16,
|
|
kNumJoyHats = 16
|
|
};
|
|
enum JoyType {
|
|
JT_NONE,
|
|
JT_REGULAR,
|
|
JT_STELLADAPTOR_LEFT,
|
|
JT_STELLADAPTOR_RIGHT
|
|
};
|
|
struct Stella_Joystick {
|
|
SDL_Joystick* stick;
|
|
JoyType type;
|
|
string name;
|
|
};
|
|
enum JoyHat {
|
|
kJHatUp,
|
|
kJHatDown,
|
|
kJHatLeft,
|
|
kJHatRight,
|
|
kJHatCentered
|
|
};
|
|
struct JoyMouse { // Used for joystick to mouse emulation
|
|
bool active;
|
|
int x, y, x_amt, y_amt, amt, val, old_val;
|
|
};
|
|
|
|
// Global OSystem object
|
|
OSystem* myOSystem;
|
|
|
|
// Global Event object
|
|
Event* myEvent;
|
|
|
|
// Indicates current overlay object
|
|
DialogContainer* myOverlay;
|
|
|
|
// Array of key events, indexed by SDLKey
|
|
Event::Type myKeyTable[SDLK_LAST][kNumModes];
|
|
|
|
// Array of joystick button events
|
|
Event::Type myJoyTable[kNumJoysticks][kNumJoyButtons][kNumModes];
|
|
|
|
// Array of joystick axis events
|
|
Event::Type myJoyAxisTable[kNumJoysticks][kNumJoyAxis][2][kNumModes];
|
|
|
|
// Array of joystick hat events (we don't record diagonals)
|
|
Event::Type myJoyHatTable[kNumJoysticks][kNumJoyHats][4][kNumModes];
|
|
|
|
// Array of messages for each Event
|
|
string ourMessageTable[Event::LastType];
|
|
|
|
// Array of strings which correspond to the given SDL key
|
|
string ourSDLMapping[SDLK_LAST];
|
|
|
|
// Array of joysticks available to Stella
|
|
Stella_Joystick ourJoysticks[kNumJoysticks];
|
|
|
|
// 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;
|
|
|
|
// Indicates whether the joystick emulates 'impossible' directions
|
|
bool myAllowAllDirectionsFlag;
|
|
|
|
// Indicates whether or not we're in frying mode
|
|
bool myFryingFlag;
|
|
|
|
// Indicates whether the key-combos tied to the Control key are
|
|
// being used or not (since Ctrl by default is the fire button,
|
|
// pressing it with a movement key could inadvertantly activate
|
|
// a Ctrl combo when it isn't wanted)
|
|
bool myUseCtrlKeyFlag;
|
|
|
|
// Indicates which paddle the mouse currently emulates
|
|
Int8 myPaddleMode;
|
|
|
|
// Holds static strings for the remap menu (emulation and menu events)
|
|
static ActionList ourEmulActionList[kEmulActionListSize];
|
|
static ActionList ourMenuActionList[kMenuActionListSize];
|
|
|
|
// Static lookup tables for Stelladaptor axis/button support
|
|
static const Event::Type SA_Axis[2][2];
|
|
static const Event::Type SA_Button[2][2];
|
|
};
|
|
|
|
#endif
|