Joysticks are now detected dynamically, meaning that they can be added/removed

while the emulator is running.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@3002 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2014-10-13 22:37:15 +00:00
parent 5959f69405
commit c21220ce2c
12 changed files with 757 additions and 623 deletions

View File

@ -14,6 +14,11 @@
4.1.1 to 4.2: (xxx xx, 2014) 4.1.1 to 4.2: (xxx xx, 2014)
* Controllers are now detected dynamically by Stella. This means that
you can plug/unplug joysticks/paddles/etc while Stella is running,
and they will be added and removed automatically. Also fixed is
a bug whereby sometimes custom joystick mappings weren't being saved.
* Fixed 'MDM' scheme to trigger bankswitching on writes to hotspots * Fixed 'MDM' scheme to trigger bankswitching on writes to hotspots
(previously it only triggered on reads). Also, the scheme has been (previously it only triggered on reads). Also, the scheme has been
modified as originally designed by E. Blink; hotspots are now in the modified as originally designed by E. Blink; hotspots are now in the

View File

@ -10,7 +10,7 @@
<br><br> <br><br>
<center><h2><b>A multi-platform Atari 2600 VCS emulator</b></h2></center> <center><h2><b>A multi-platform Atari 2600 VCS emulator</b></h2></center>
<center><h4><b>Release 4.1.1</b></h4></center> <center><h4><b>Release 4.2</b></h4></center>
<br><br> <br><br>
<center><h2><b>User's Guide</b></h2></center> <center><h2><b>User's Guide</b></h2></center>
@ -54,7 +54,7 @@
<br><br><br> <br><br><br>
<center><b>February 1999 - September 2014</b></center> <center><b>February 1999 - October 2014</b></center>
<center><b>The Stella Team</b></center> <center><b>The Stella Team</b></center>
<center><b><a href="http://stella.sourceforge.net">Stella Homepage</a></b></center> <center><b><a href="http://stella.sourceforge.net">Stella Homepage</a></b></center>
@ -2767,10 +2767,9 @@
<a href="http://2600-daptor.com">2600-adaptor</a> devices.</p> <a href="http://2600-daptor.com">2600-adaptor</a> devices.</p>
<p>Stella can use up to <b>two</b> adaptors; any extra ones are ignored. <p>Stella can use up to <b>two</b> adaptors; any extra ones are ignored.
Stelladaptor devices will be automatically detected and configured. Stelladaptor Stelladaptor devices will be automatically detected and configured. The
devices must be plugged in before starting the application; actual controllers actual controllers can be plugged/unplugged while the emulator is running,
can be plugged/unplugged while the emulator is running, although you will need although you will need to restart the game currently being emulated.</p>
to restart the game currently being emulated.</p>
<p>The detection and configuration is as follows: <p>The detection and configuration is as follows:

View File

@ -31,29 +31,6 @@ EventHandlerSDL2::~EventHandlerSDL2()
{ {
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandlerSDL2::initializeJoysticks()
{
#ifdef JOYSTICK_SUPPORT
// Initialize the joystick subsystem
if(SDL_WasInit(SDL_INIT_JOYSTICK) != 0)
{
if(SDL_NumJoysticks() > 0)
{
int numSticks = SDL_NumJoysticks();
for(int i = 0; i < numSticks; ++i)
addJoystick(new JoystickSDL2(i), i);
myOSystem.logMessage("EventHandlerSDL2::initializeJoysticks() +sticks", 2);
}
else
myOSystem.logMessage("EventHandlerSDL2::initializeJoysticks() -sticks", 2);
}
else
myOSystem.logMessage("EventHandlerSDL2::initializeJoysticks() failed!", 2);
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandlerSDL2::enableTextEvents(bool enable) void EventHandlerSDL2::enableTextEvents(bool enable)
{ {
@ -157,6 +134,17 @@ void EventHandlerSDL2::pollEvent()
handleJoyHatEvent(myEvent.jhat.which, myEvent.jhat.hat, value); handleJoyHatEvent(myEvent.jhat.which, myEvent.jhat.hat, value);
break; // SDL_JOYHATMOTION break; // SDL_JOYHATMOTION
} }
case SDL_JOYDEVICEADDED:
{
addJoystick(new JoystickSDL2(myEvent.jdevice.which));
break; // SDL_JOYDEVICEADDED
}
case SDL_JOYDEVICEREMOVED:
{
removeJoystick(myEvent.jdevice.which);
break; // SDL_JOYDEVICEREMOVED
}
#endif #endif
case SDL_QUIT: case SDL_QUIT:
@ -216,23 +204,19 @@ void EventHandlerSDL2::pollEvent()
EventHandlerSDL2::JoystickSDL2::JoystickSDL2(int idx) EventHandlerSDL2::JoystickSDL2::JoystickSDL2(int idx)
: myStick(NULL) : myStick(NULL)
{ {
#ifdef JOYSTICK_SUPPORT
myStick = SDL_JoystickOpen(idx); myStick = SDL_JoystickOpen(idx);
if(myStick) if(myStick)
{ {
initialize(SDL_JoystickName(myStick), initialize(idx, SDL_JoystickName(myStick),
SDL_JoystickNumAxes(myStick), SDL_JoystickNumButtons(myStick), SDL_JoystickNumAxes(myStick), SDL_JoystickNumButtons(myStick),
SDL_JoystickNumHats(myStick), SDL_JoystickNumBalls(myStick)); SDL_JoystickNumHats(myStick), SDL_JoystickNumBalls(myStick));
} }
#endif
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EventHandlerSDL2::JoystickSDL2::~JoystickSDL2() EventHandlerSDL2::JoystickSDL2::~JoystickSDL2()
{ {
#ifdef JOYSTICK_SUPPORT
if(myStick) if(myStick)
SDL_JoystickClose(myStick); SDL_JoystickClose(myStick);
myStick = NULL; myStick = NULL;
#endif
} }

View File

@ -45,11 +45,6 @@ class EventHandlerSDL2 : public EventHandler
virtual ~EventHandlerSDL2(); virtual ~EventHandlerSDL2();
private: private:
/**
Set up any joysticks on the system.
*/
void initializeJoysticks();
/** /**
Enable/disable text events (distinct from single-key events). Enable/disable text events (distinct from single-key events).
*/ */

View File

@ -62,7 +62,8 @@ EventHandler::EventHandler(OSystem& osystem)
myState(S_NONE), myState(S_NONE),
myAllowAllDirectionsFlag(false), myAllowAllDirectionsFlag(false),
myFryingFlag(false), myFryingFlag(false),
mySkipMouseMotion(true) mySkipMouseMotion(true),
myJoyHandler(NULL)
{ {
// Erase the key mapping array // Erase the key mapping array
for(int i = 0; i < KBDK_LAST; ++i) for(int i = 0; i < KBDK_LAST; ++i)
@ -73,6 +74,9 @@ EventHandler::EventHandler(OSystem& osystem)
for(int i = 0; i < kComboSize; ++i) for(int i = 0; i < kComboSize; ++i)
for(int j = 0; j < kEventsPerCombo; ++j) for(int j = 0; j < kEventsPerCombo; ++j)
myComboTable[i][j] = Event::NoType; myComboTable[i][j] = Event::NoType;
// Create joystick handler (to handle all joystick functionality)
myJoyHandler = new JoystickHandler(osystem);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -86,9 +90,8 @@ EventHandler::~EventHandler()
if(ourMenuActionList[i].key) if(ourMenuActionList[i].key)
free(ourMenuActionList[i].key); free(ourMenuActionList[i].key);
delete myMouseControl; delete myMouseControl; myMouseControl = NULL;
for(uInt32 i = 0; i < myJoysticks.size(); ++i) delete myJoyHandler; myJoyHandler = NULL;
delete myJoysticks[i];
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -115,31 +118,6 @@ void EventHandler::initialize()
// Integer to string conversions (for HEX) use upper or lower-case // Integer to string conversions (for HEX) use upper or lower-case
Common::Base::setHexUppercase(myOSystem.settings().getBool("dbg.uhex")); Common::Base::setHexUppercase(myOSystem.settings().getBool("dbg.uhex"));
// Joystick stuff
#ifdef JOYSTICK_SUPPORT
initializeJoysticks();
// Map the stelladaptors we've found according to the specified ports
mapStelladaptors(myOSystem.settings().getString("saport"));
setJoymap();
setActionMappings(kEmulationMode);
setActionMappings(kMenuMode);
ostringstream buf;
buf << "Joystick devices found:" << endl;
if(myJoysticks.size() == 0)
buf << "No joysticks present." << endl;
else
{
for(uInt32 i = 0; i < myJoysticks.size(); ++i)
buf << " " << i << ": " << myJoysticks[i]->about() << endl;
}
myOSystem.logMessage(buf.str(), 1);
#else
myOSystem.logMessage("Joystick support disabled.", 1);
#endif
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -158,104 +136,20 @@ void EventHandler::reset(State state)
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::addJoystick(StellaJoystick* stick, int idx) void EventHandler::addJoystick(StellaJoystick* stick)
{ {
#ifdef JOYSTICK_SUPPORT #ifdef JOYSTICK_SUPPORT
myJoysticks.insert_at(idx, stick); int idx = myJoyHandler->add(stick);
if(idx < 0)
// Skip if we couldn't open it for any reason
if(stick->name == "None")
return; return;
// Figure out what type of joystick this is setActionMappings(kEmulationMode);
if(stick->name.find("2600-daptor", 0) != string::npos) setActionMappings(kMenuMode);
{
// 2600-daptorII devices have 3 axes and 12 buttons, and the value of the z-axis
// determines how those 12 buttons are used (not all buttons are used in all modes)
if(stick->numAxes == 3)
{
// TODO - stubbed out for now, until we find a way to reliably get info
// from the Z axis
stick->name = "2600-daptor II";
}
else
stick->name = "2600-daptor";
}
else if(stick->name.find("Stelladaptor", 0) != string::npos)
{
stick->name = "Stelladaptor";
}
else
{
// We need unique names for mappable devices
int count = 0;
for(uInt32 i = 0; i < myJoysticks.size(); ++i)
if(BSPF_startsWithIgnoreCase(myJoysticks[i]->name, stick->name))
++count;
if(count > 1) ostringstream buf;
{ buf << "Added joystick " << stick->ID << ":" << endl
ostringstream name; << " " << stick->about() << endl;
name << stick->name << " " << count; myOSystem.logMessage(buf.str(), 1);
stick->name = name.str();
}
stick->type = StellaJoystick::JT_REGULAR;
}
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::mapStelladaptors(const string& saport)
{
#ifdef JOYSTICK_SUPPORT
// saport will have two values:
// 'lr' means treat first valid adaptor as left port, second as right port
// 'rl' means treat first valid adaptor as right port, second as left port
// We know there will be only two such devices (at most), since the logic
// in setupJoysticks take care of that
int saCount = 0;
int saOrder[2];
if(BSPF_equalsIgnoreCase(saport, "lr"))
{
saOrder[0] = 1; saOrder[1] = 2;
}
else
{
saOrder[0] = 2; saOrder[1] = 1;
}
for(uInt32 i = 0; i < myJoysticks.size(); ++i)
{
if(BSPF_startsWithIgnoreCase(myJoysticks[i]->name, "Stelladaptor"))
{
if(saOrder[saCount] == 1)
{
myJoysticks[i]->name += " (emulates left joystick port)";
myJoysticks[i]->type = StellaJoystick::JT_STELLADAPTOR_LEFT;
}
else if(saOrder[saCount] == 2)
{
myJoysticks[i]->name += " (emulates right joystick port)";
myJoysticks[i]->type = StellaJoystick::JT_STELLADAPTOR_RIGHT;
}
saCount++;
}
else if(BSPF_startsWithIgnoreCase(myJoysticks[i]->name, "2600-daptor"))
{
if(saOrder[saCount] == 1)
{
myJoysticks[i]->name += " (emulates left joystick port)";
myJoysticks[i]->type = StellaJoystick::JT_2600DAPTOR_LEFT;
}
else if(saOrder[saCount] == 2)
{
myJoysticks[i]->name += " (emulates right joystick port)";
myJoysticks[i]->type = StellaJoystick::JT_2600DAPTOR_RIGHT;
}
saCount++;
}
}
myOSystem.settings().setValue("saport", saport);
// We're potentially swapping out an input device behind the back of // We're potentially swapping out an input device behind the back of
// the Event system, so we make sure all Stelladaptor-generated events // the Event system, so we make sure all Stelladaptor-generated events
@ -272,9 +166,26 @@ void EventHandler::mapStelladaptors(const string& saport)
#endif #endif
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::removeJoystick(int idx)
{
#ifdef JOYSTICK_SUPPORT
myJoyHandler->remove(idx);
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::mapStelladaptors(const string& saport)
{
#ifdef JOYSTICK_SUPPORT
myJoyHandler->mapStelladaptors(saport);
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::toggleSAPortOrder() void EventHandler::toggleSAPortOrder()
{ {
#ifdef JOYSTICK_SUPPORT
const string& saport = myOSystem.settings().getString("saport"); const string& saport = myOSystem.settings().getString("saport");
if(saport == "lr") if(saport == "lr")
{ {
@ -286,6 +197,7 @@ void EventHandler::toggleSAPortOrder()
mapStelladaptors("lr"); mapStelladaptors("lr");
myOSystem.frameBuffer().showMessage("Stelladaptor ports left/right"); myOSystem.frameBuffer().showMessage("Stelladaptor ports left/right");
} }
#endif
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -690,21 +602,20 @@ void EventHandler::handleMouseButtonEvent(MouseButton b, int x, int y)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::handleJoyEvent(int stick, int button, uInt8 state) void EventHandler::handleJoyEvent(int stick, int button, uInt8 state)
{ {
if(stick >= (int)myJoysticks.size()) const StellaJoystick* joy = myJoyHandler->joy(stick);
return; if(!joy) return;
// Stelladaptors handle buttons differently than regular joysticks // Stelladaptors handle buttons differently than regular joysticks
const StellaJoystick& joy = *myJoysticks[stick]; switch(joy->type)
switch(joy.type)
{ {
case StellaJoystick::JT_REGULAR: case StellaJoystick::JT_REGULAR:
// Handle buttons which switch eventhandler state // Handle buttons which switch eventhandler state
if(state && eventStateChange(joy.btnTable[button][kEmulationMode])) if(state && eventStateChange(joy->btnTable[button][kEmulationMode]))
return; return;
// Determine which mode we're in, then send the event to the appropriate place // Determine which mode we're in, then send the event to the appropriate place
if(myState == S_EMULATE) if(myState == S_EMULATE)
handleEvent(joy.btnTable[button][kEmulationMode], state); handleEvent(joy->btnTable[button][kEmulationMode], state);
else if(myOverlay != NULL) else if(myOverlay != NULL)
myOverlay->handleJoyEvent(stick, button, state); myOverlay->handleJoyEvent(stick, button, state);
break; // Regular button break; // Regular button
@ -716,7 +627,7 @@ void EventHandler::handleJoyEvent(int stick, int button, uInt8 state)
// The 'type-2' here refers to the fact that 'StellaJoystick::JT_STELLADAPTOR_LEFT' // The 'type-2' here refers to the fact that 'StellaJoystick::JT_STELLADAPTOR_LEFT'
// and 'StellaJoystick::JT_STELLADAPTOR_RIGHT' are at index 2 and 3 in the JoyType // and 'StellaJoystick::JT_STELLADAPTOR_RIGHT' are at index 2 and 3 in the JoyType
// enum; subtracting two gives us Controller 0 and 1 // enum; subtracting two gives us Controller 0 and 1
if(button < 2) myEvent.set(SA_Button[joy.type-2][button], state); if(button < 2) myEvent.set(SA_Button[joy->type-2][button], state);
break; // Stelladaptor button break; // Stelladaptor button
case StellaJoystick::JT_2600DAPTOR_LEFT: case StellaJoystick::JT_2600DAPTOR_LEFT:
case StellaJoystick::JT_2600DAPTOR_RIGHT: case StellaJoystick::JT_2600DAPTOR_RIGHT:
@ -728,18 +639,18 @@ void EventHandler::handleJoyEvent(int stick, int button, uInt8 state)
switch(myOSystem.console().controller(Controller::Left).type()) switch(myOSystem.console().controller(Controller::Left).type())
{ {
case Controller::Keyboard: case Controller::Keyboard:
if(button < 12) myEvent.set(SA_Key[joy.type-4][button], state); if(button < 12) myEvent.set(SA_Key[joy->type-4][button], state);
break; break;
default: default:
if(button < 4) myEvent.set(SA_Button[joy.type-4][button], state); if(button < 4) myEvent.set(SA_Button[joy->type-4][button], state);
} }
switch(myOSystem.console().controller(Controller::Right).type()) switch(myOSystem.console().controller(Controller::Right).type())
{ {
case Controller::Keyboard: case Controller::Keyboard:
if(button < 12) myEvent.set(SA_Key[joy.type-4][button], state); if(button < 12) myEvent.set(SA_Key[joy->type-4][button], state);
break; break;
default: default:
if(button < 4) myEvent.set(SA_Button[joy.type-4][button], state); if(button < 4) myEvent.set(SA_Button[joy->type-4][button], state);
} }
} }
break; // 2600DAPTOR button break; // 2600DAPTOR button
@ -751,19 +662,18 @@ void EventHandler::handleJoyEvent(int stick, int button, uInt8 state)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::handleJoyAxisEvent(int stick, int axis, int value) void EventHandler::handleJoyAxisEvent(int stick, int axis, int value)
{ {
if(stick >= (int)myJoysticks.size()) const StellaJoystick* joy = myJoyHandler->joy(stick);
return; if(!joy) return;
// Stelladaptors handle axis differently than regular joysticks // Stelladaptors handle axis differently than regular joysticks
const StellaJoystick& joy = *myJoysticks[stick]; switch(joy->type)
switch(joy.type)
{ {
case StellaJoystick::JT_REGULAR: case StellaJoystick::JT_REGULAR:
if(myState == S_EMULATE) if(myState == S_EMULATE)
{ {
// Every axis event has two associated values, negative and positive // Every axis event has two associated values, negative and positive
Event::Type eventAxisNeg = joy.axisTable[axis][0][kEmulationMode]; Event::Type eventAxisNeg = joy->axisTable[axis][0][kEmulationMode];
Event::Type eventAxisPos = joy.axisTable[axis][1][kEmulationMode]; Event::Type eventAxisPos = joy->axisTable[axis][1][kEmulationMode];
// Check for analog events, which are handled differently // Check for analog events, which are handled differently
// We'll pass them off as Stelladaptor events, and let the controllers // We'll pass them off as Stelladaptor events, and let the controllers
@ -796,7 +706,7 @@ void EventHandler::handleJoyAxisEvent(int stick, int axis, int value)
// Now filter out consecutive, similar values // Now filter out consecutive, similar values
// (only pass on the event if the state has changed) // (only pass on the event if the state has changed)
if(joy.axisLastValue[axis] != value) if(joy->axisLastValue[axis] != value)
{ {
// Turn off both events, since we don't know exactly which one // Turn off both events, since we don't know exactly which one
// was previously activated. // was previously activated.
@ -804,7 +714,7 @@ void EventHandler::handleJoyAxisEvent(int stick, int axis, int value)
handleEvent(eventAxisPos, 0); handleEvent(eventAxisPos, 0);
} }
} }
joy.axisLastValue[axis] = value; joy->axisLastValue[axis] = value;
break; break;
} }
} }
@ -822,10 +732,10 @@ void EventHandler::handleJoyAxisEvent(int stick, int axis, int value)
// Now filter out consecutive, similar values // Now filter out consecutive, similar values
// (only pass on the event if the state has changed) // (only pass on the event if the state has changed)
if(value != joy.axisLastValue[axis]) if(value != joy->axisLastValue[axis])
{ {
myOverlay->handleJoyAxisEvent(stick, axis, value); myOverlay->handleJoyAxisEvent(stick, axis, value);
joy.axisLastValue[axis] = value; joy->axisLastValue[axis] = value;
} }
} }
break; // Regular joystick axis break; // Regular joystick axis
@ -841,7 +751,7 @@ void EventHandler::handleJoyAxisEvent(int stick, int axis, int value)
// and 'StellaJoystick::JT_STELLADAPTOR_RIGHT' are at index 2 and 3 in the JoyType // and 'StellaJoystick::JT_STELLADAPTOR_RIGHT' are at index 2 and 3 in the JoyType
// enum; subtracting two gives us Controller 0 and 1 // enum; subtracting two gives us Controller 0 and 1
if(axis < 2) if(axis < 2)
myEvent.set(SA_Axis[joy.type-2][axis], value); myEvent.set(SA_Axis[joy->type-2][axis], value);
break; // Stelladaptor axis break; // Stelladaptor axis
case StellaJoystick::JT_2600DAPTOR_LEFT: case StellaJoystick::JT_2600DAPTOR_LEFT:
case StellaJoystick::JT_2600DAPTOR_RIGHT: case StellaJoystick::JT_2600DAPTOR_RIGHT:
@ -849,7 +759,7 @@ void EventHandler::handleJoyAxisEvent(int stick, int axis, int value)
// and 'StellaJoystick::JT_2600DAPTOR_RIGHT' are at index 4 and 5 in the JoyType // and 'StellaJoystick::JT_2600DAPTOR_RIGHT' are at index 4 and 5 in the JoyType
// enum; subtracting four gives us Controller 0 and 1 // enum; subtracting four gives us Controller 0 and 1
if(axis < 2) if(axis < 2)
myEvent.set(SA_Axis[joy.type-4][axis], value); myEvent.set(SA_Axis[joy->type-4][axis], value);
break; // 26000daptor axis break; // 26000daptor axis
default: default:
break; break;
@ -859,23 +769,21 @@ void EventHandler::handleJoyAxisEvent(int stick, int axis, int value)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::handleJoyHatEvent(int stick, int hat, int value) void EventHandler::handleJoyHatEvent(int stick, int hat, int value)
{ {
if(stick >= (int)myJoysticks.size()) const StellaJoystick* joy = myJoyHandler->joy(stick);
return; if(!joy) return;
const StellaJoystick& joy = *myJoysticks[stick];
// Preprocess all hat events, converting to Stella JoyHat type // Preprocess all hat events, converting to Stella JoyHat type
// Generate multiple equivalent hat events representing combined direction // Generate multiple equivalent hat events representing combined direction
// when we get a diagonal hat event // when we get a diagonal hat event
if(myState == S_EMULATE) if(myState == S_EMULATE)
{ {
handleEvent(joy.hatTable[hat][EVENT_HATUP][kEmulationMode], handleEvent(joy->hatTable[hat][EVENT_HATUP][kEmulationMode],
value & EVENT_HATUP_M); value & EVENT_HATUP_M);
handleEvent(joy.hatTable[hat][EVENT_HATRIGHT][kEmulationMode], handleEvent(joy->hatTable[hat][EVENT_HATRIGHT][kEmulationMode],
value & EVENT_HATRIGHT_M); value & EVENT_HATRIGHT_M);
handleEvent(joy.hatTable[hat][EVENT_HATDOWN][kEmulationMode], handleEvent(joy->hatTable[hat][EVENT_HATDOWN][kEmulationMode],
value & EVENT_HATDOWN_M); value & EVENT_HATDOWN_M);
handleEvent(joy.hatTable[hat][EVENT_HATLEFT][kEmulationMode], handleEvent(joy->hatTable[hat][EVENT_HATLEFT][kEmulationMode],
value & EVENT_HATLEFT_M); value & EVENT_HATLEFT_M);
} }
else if(myOverlay != NULL) else if(myOverlay != NULL)
@ -1164,14 +1072,15 @@ void EventHandler::setActionMappings(EventMode mode)
} }
#ifdef JOYSTICK_SUPPORT #ifdef JOYSTICK_SUPPORT
for(uInt32 stick = 0; stick < myJoysticks.size(); ++stick) for(uInt32 stick = 0; stick < myJoyHandler->numSticks(); ++stick)
{ {
const StellaJoystick& joy = *myJoysticks[stick]; const StellaJoystick* joy = myJoyHandler->joy(stick);
if(!joy) continue;
// Joystick button mapping/labeling // Joystick button mapping/labeling
for(int button = 0; button < joy.numButtons; ++button) for(int button = 0; button < joy->numButtons; ++button)
{ {
if(joy.btnTable[button][mode] == event) if(joy->btnTable[button][mode] == event)
{ {
buf.str(""); buf.str("");
buf << "J" << stick << "/B" << button; buf << "J" << stick << "/B" << button;
@ -1183,11 +1092,11 @@ void EventHandler::setActionMappings(EventMode mode)
} }
// Joystick axis mapping/labeling // Joystick axis mapping/labeling
for(int axis = 0; axis < joy.numAxes; ++axis) for(int axis = 0; axis < joy->numAxes; ++axis)
{ {
for(int dir = 0; dir < 2; ++dir) for(int dir = 0; dir < 2; ++dir)
{ {
if(joy.axisTable[axis][dir][mode] == event) if(joy->axisTable[axis][dir][mode] == event)
{ {
buf.str(""); buf.str("");
buf << "J" << stick << "/A" << axis; buf << "J" << stick << "/A" << axis;
@ -1210,11 +1119,11 @@ void EventHandler::setActionMappings(EventMode mode)
} }
// Joystick hat mapping/labeling // Joystick hat mapping/labeling
for(int hat = 0; hat < joy.numHats; ++hat) for(int hat = 0; hat < joy->numHats; ++hat)
{ {
for(int dir = 0; dir < 4; ++dir) for(int dir = 0; dir < 4; ++dir)
{ {
if(joy.hatTable[hat][dir][mode] == event) if(joy->hatTable[hat][dir][mode] == event)
{ {
buf.str(""); buf.str("");
buf << "J" << stick << "/H" << hat; buf << "J" << stick << "/H" << hat;
@ -1298,48 +1207,6 @@ void EventHandler::setKeymap()
} }
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::setJoymap()
{
#ifdef JOYSTICK_SUPPORT
setDefaultJoymap(Event::NoType, kEmulationMode);
setDefaultJoymap(Event::NoType, kMenuMode);
// Get all mappings from the settings
istringstream buf(myOSystem.settings().getString("joymap"));
string joymap;
// First check the event type, and disregard the entire mapping if it's invalid
getline(buf, joymap, '^');
if(atoi(joymap.c_str()) != Event::LastType)
return;
// Otherwise, put each joystick mapping entry into a hashmap
while(getline(buf, joymap, '^'))
{
istringstream namebuf(joymap);
string joyname;
getline(namebuf, joyname, '|');
if(joyname.length() != 0)
myJoystickMap.insert(make_pair(joyname, joymap));
}
// Next try to match the mappings to the specific joystick (by name)
// We do it this way since a joystick may be unplugged and replugged,
// but it's settings should stay the same
for(uInt32 i = 0; i < myJoysticks.size(); ++i)
{
StellaJoystick& joy = *myJoysticks[i];
if(joy.type == StellaJoystick::JT_REGULAR)
{
map<string,string>::const_iterator iter = myJoystickMap.find(joy.name);
if(iter != myJoystickMap.end())
joy.setMap(iter->second);
}
}
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::setComboMap() void EventHandler::setComboMap()
{ {
@ -1404,36 +1271,34 @@ bool EventHandler::addJoyAxisMapping(Event::Type event, EventMode mode,
bool updateMenus) bool updateMenus)
{ {
#ifdef JOYSTICK_SUPPORT #ifdef JOYSTICK_SUPPORT
if(stick >= 0 && stick < (int)myJoysticks.size()) const StellaJoystick* joy = myJoyHandler->joy(stick);
if(joy)
{ {
const StellaJoystick& joy = *myJoysticks[stick]; if(axis >= 0 && axis < joy->numAxes &&
if(axis >= 0 && axis < joy.numAxes &&
event >= 0 && event < Event::LastType) event >= 0 && event < Event::LastType)
{ {
// This confusing code is because each axis has two associated values, // This confusing code is because each axis has two associated values,
// but analog events only affect one of the axis. // but analog events only affect one of the axis.
if(eventIsAnalog(event)) if(eventIsAnalog(event))
joy.axisTable[axis][0][mode] = joy->axisTable[axis][0][mode] =
joy.axisTable[axis][1][mode] = event; joy->axisTable[axis][1][mode] = event;
else else
{ {
// Otherwise, turn off the analog event(s) for this axis // Otherwise, turn off the analog event(s) for this axis
if(eventIsAnalog(joy.axisTable[axis][0][mode])) if(eventIsAnalog(joy->axisTable[axis][0][mode]))
joy.axisTable[axis][0][mode] = Event::NoType; joy->axisTable[axis][0][mode] = Event::NoType;
if(eventIsAnalog(joy.axisTable[axis][1][mode])) if(eventIsAnalog(joy->axisTable[axis][1][mode]))
joy.axisTable[axis][1][mode] = Event::NoType; joy->axisTable[axis][1][mode] = Event::NoType;
joy.axisTable[axis][(value > 0)][mode] = event; joy->axisTable[axis][(value > 0)][mode] = event;
} }
if(updateMenus) if(updateMenus)
setActionMappings(mode); setActionMappings(mode);
return true; return true;
} }
} }
return false;
#else
return false;
#endif #endif
return false;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -1442,22 +1307,20 @@ bool EventHandler::addJoyButtonMapping(Event::Type event, EventMode mode,
bool updateMenus) bool updateMenus)
{ {
#ifdef JOYSTICK_SUPPORT #ifdef JOYSTICK_SUPPORT
if(stick >= 0 && stick < (int)myJoysticks.size() && !eventIsAnalog(event)) const StellaJoystick* joy = myJoyHandler->joy(stick);
if(joy)
{ {
const StellaJoystick& joy = *myJoysticks[stick]; if(button >= 0 && button < joy->numButtons &&
if(button >= 0 && button < joy.numButtons &&
event >= 0 && event < Event::LastType) event >= 0 && event < Event::LastType)
{ {
joy.btnTable[button][mode] = event; joy->btnTable[button][mode] = event;
if(updateMenus) if(updateMenus)
setActionMappings(mode); setActionMappings(mode);
return true; return true;
} }
} }
return false;
#else
return false;
#endif #endif
return false;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -1466,22 +1329,20 @@ bool EventHandler::addJoyHatMapping(Event::Type event, EventMode mode,
bool updateMenus) bool updateMenus)
{ {
#ifdef JOYSTICK_SUPPORT #ifdef JOYSTICK_SUPPORT
if(stick >= 0 && stick < (int)myJoysticks.size() && !eventIsAnalog(event)) const StellaJoystick* joy = myJoyHandler->joy(stick);
if(joy)
{ {
const StellaJoystick& joy = *myJoysticks[stick]; if(hat >= 0 && hat < joy->numHats &&
if(hat >= 0 && hat < joy.numHats &&
event >= 0 && event < Event::LastType && value != EVENT_HATCENTER) event >= 0 && event < Event::LastType && value != EVENT_HATCENTER)
{ {
joy.hatTable[hat][value][mode] = event; joy->hatTable[hat][value][mode] = event;
if(updateMenus) if(updateMenus)
setActionMappings(mode); setActionMappings(mode);
return true; return true;
} }
} }
return false;
#else
return false;
#endif #endif
return false;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -1494,8 +1355,7 @@ void EventHandler::eraseMapping(Event::Type event, EventMode mode)
#ifdef JOYSTICK_SUPPORT #ifdef JOYSTICK_SUPPORT
// Erase the joystick mapping arrays // Erase the joystick mapping arrays
for(uInt32 i = 0; i < myJoysticks.size(); ++i) myJoyHandler->eraseMapping(event, mode);
myJoysticks[i]->eraseMap(mode);
#endif #endif
setActionMappings(mode); setActionMappings(mode);
@ -1619,19 +1479,8 @@ void EventHandler::setDefaultKeymap(Event::Type event, EventMode mode)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::setDefaultJoymap(Event::Type event, EventMode mode) void EventHandler::setDefaultJoymap(Event::Type event, EventMode mode)
{ {
#ifdef JOYSTICK_SUPPORT myJoyHandler->setDefaultMapping(event, mode);
// If event is 'NoType', erase and reset all mappings
// Otherwise, only reset the given event
for(uInt32 i = 0; i < myJoysticks.size(); ++i)
{
if(event == Event::NoType)
myJoysticks[i]->eraseMap(mode); // erase *all* mappings
else
myJoysticks[i]->eraseEvent(event, mode); // only reset the specific event
}
myOSystem.setDefaultJoymap(event, mode);
setActionMappings(mode); setActionMappings(mode);
#endif
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -1651,37 +1500,7 @@ void EventHandler::saveKeyMapping()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::saveJoyMapping() void EventHandler::saveJoyMapping()
{ {
#ifdef JOYSTICK_SUPPORT myJoyHandler->saveMapping();
// Don't update the joymap at all if it hasn't been modified during the
// program run
if(myJoysticks.size() == 0)
return;
// Save the joystick mapping hash table, making sure to update it with
// any changes that have been made during the program run
for(uInt32 i = 0; i < myJoysticks.size(); ++i)
{
const StellaJoystick& joy = *myJoysticks[i];
if(joy.type == StellaJoystick::JT_REGULAR)
{
// Update hashmap, removing the joystick entry (if it exists)
// and adding the most recent mapping from the joystick itself
map<string,string>::iterator iter = myJoystickMap.find(joy.name);
if(iter != myJoystickMap.end())
myJoystickMap.erase(iter);
myJoystickMap.insert(make_pair(joy.name, joy.getMap()));
}
}
// Now save the contents of the hashmap
ostringstream joybuf;
joybuf << Event::LastType;
map<string,string>::const_iterator iter;
for(iter = myJoystickMap.begin(); iter != myJoystickMap.end(); ++iter)
joybuf << "^" << iter->second;
myOSystem.settings().setValue("joymap", joybuf.str());
#endif
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -2316,208 +2135,3 @@ const Event::Type EventHandler::SA_Key[2][12] = {
Event::KeyboardOne7, Event::KeyboardOne8, Event::KeyboardOne9, Event::KeyboardOne7, Event::KeyboardOne8, Event::KeyboardOne9,
Event::KeyboardOneStar, Event::KeyboardOne0, Event::KeyboardOnePound } Event::KeyboardOneStar, Event::KeyboardOne0, Event::KeyboardOnePound }
}; };
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EventHandler::StellaJoystick::StellaJoystick()
: type(JT_NONE),
name("None"),
numAxes(0),
numButtons(0),
numHats(0),
axisTable(NULL),
btnTable(NULL),
hatTable(NULL),
axisLastValue(NULL)
{
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EventHandler::StellaJoystick::~StellaJoystick()
{
delete[] axisTable; axisTable = NULL;
delete[] btnTable; btnTable = NULL;
delete[] hatTable; hatTable = NULL;
delete[] axisLastValue; axisLastValue = NULL;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::StellaJoystick::initialize(const string& desc,
int axes, int buttons, int hats, int /*balls*/)
{
name = desc;
// Dynamically create the various mapping arrays for this joystick,
// based on its specific attributes
numAxes = axes;
numButtons = buttons;
numHats = hats;
if(numAxes)
axisTable = new Event::Type[numAxes][2][kNumModes];
if(numButtons)
btnTable = new Event::Type[numButtons][kNumModes];
if(numHats)
hatTable = new Event::Type[numHats][4][kNumModes];
axisLastValue = new int[numAxes];
// Erase the joystick axis mapping array and last axis value
for(int a = 0; a < numAxes; ++a)
{
axisLastValue[a] = 0;
for(int m = 0; m < kNumModes; ++m)
axisTable[a][0][m] = axisTable[a][1][m] = Event::NoType;
}
// Erase the joystick button mapping array
for(int b = 0; b < numButtons; ++b)
for(int m = 0; m < kNumModes; ++m)
btnTable[b][m] = Event::NoType;
// Erase the joystick hat mapping array
for(int h = 0; h < numHats; ++h)
for(int m = 0; m < kNumModes; ++m)
hatTable[h][0][m] = hatTable[h][1][m] =
hatTable[h][2][m] = hatTable[h][3][m] = Event::NoType;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string EventHandler::StellaJoystick::getMap() const
{
// The mapping structure (for remappable devices) is defined as follows:
// NAME | AXIS # + values | BUTTON # + values | HAT # + values,
// where each subsection of values is separated by ':'
if(type == JT_REGULAR)
{
ostringstream joybuf;
joybuf << name << "|" << numAxes;
for(int m = 0; m < kNumModes; ++m)
for(int a = 0; a < numAxes; ++a)
for(int k = 0; k < 2; ++k)
joybuf << " " << axisTable[a][k][m];
joybuf << "|" << numButtons;
for(int m = 0; m < kNumModes; ++m)
for(int b = 0; b < numButtons; ++b)
joybuf << " " << btnTable[b][m];
joybuf << "|" << numHats;
for(int m = 0; m < kNumModes; ++m)
for(int h = 0; h < numHats; ++h)
for(int k = 0; k < 4; ++k)
joybuf << " " << hatTable[h][k][m];
return joybuf.str();
}
return EmptyString;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool EventHandler::StellaJoystick::setMap(const string& m)
{
istringstream buf(m);
StringList items;
string item;
while(getline(buf, item, '|'))
items.push_back(item);
// Error checking
if(items.size() != 4)
return false;
IntArray map;
// Parse axis/button/hat values
getValues(items[1], map);
if((int)map.size() == numAxes * 2 * kNumModes)
{
// Fill the axes table with events
IntArray::const_iterator event = map.begin();
for(int m = 0; m < kNumModes; ++m)
for(int a = 0; a < numAxes; ++a)
for(int k = 0; k < 2; ++k)
axisTable[a][k][m] = (Event::Type) *event++;
}
getValues(items[2], map);
if((int)map.size() == numButtons * kNumModes)
{
IntArray::const_iterator event = map.begin();
for(int m = 0; m < kNumModes; ++m)
for(int b = 0; b < numButtons; ++b)
btnTable[b][m] = (Event::Type) *event++;
}
getValues(items[3], map);
if((int)map.size() == numHats * 4 * kNumModes)
{
IntArray::const_iterator event = map.begin();
for(int m = 0; m < kNumModes; ++m)
for(int h = 0; h < numHats; ++h)
for(int k = 0; k < 4; ++k)
hatTable[h][k][m] = (Event::Type) *event++;
}
return true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::StellaJoystick::eraseMap(EventMode mode)
{
// Erase axis mappings
for(int a = 0; a < numAxes; ++a)
axisTable[a][0][mode] = axisTable[a][1][mode] = Event::NoType;
// Erase button mappings
for(int b = 0; b < numButtons; ++b)
btnTable[b][mode] = Event::NoType;
// Erase hat mappings
for(int h = 0; h < numHats; ++h)
hatTable[h][0][mode] = hatTable[h][1][mode] =
hatTable[h][2][mode] = hatTable[h][3][mode] = Event::NoType;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::StellaJoystick::eraseEvent(Event::Type event, EventMode mode)
{
// Erase axis mappings
for(int a = 0; a < numAxes; ++a)
{
if(axisTable[a][0][mode] == event) axisTable[a][0][mode] = Event::NoType;
if(axisTable[a][1][mode] == event) axisTable[a][1][mode] = Event::NoType;
}
// Erase button mappings
for(int b = 0; b < numButtons; ++b)
if(btnTable[b][mode] == event) btnTable[b][mode] = Event::NoType;
// Erase hat mappings
for(int h = 0; h < numHats; ++h)
{
if(hatTable[h][0][mode] == event) hatTable[h][0][mode] = Event::NoType;
if(hatTable[h][1][mode] == event) hatTable[h][1][mode] = Event::NoType;
if(hatTable[h][2][mode] == event) hatTable[h][2][mode] = Event::NoType;
if(hatTable[h][3][mode] == event) hatTable[h][3][mode] = Event::NoType;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::StellaJoystick::getValues(const string& list, IntArray& map)
{
map.clear();
istringstream buf(list);
int value;
buf >> value; // we don't need to know the # of items at this point
while(buf >> value)
map.push_back(value);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string EventHandler::StellaJoystick::about() const
{
ostringstream buf;
buf << name;
if(type == JT_REGULAR)
buf << " with:" << endl << " "
<< numAxes << " axes, "
<< numButtons << " buttons, "
<< numHats << " hats";
return buf.str();
}

View File

@ -219,12 +219,18 @@ class EventHandler
Event::Type eventForKey(StellaKey key, EventMode mode) const Event::Type eventForKey(StellaKey key, EventMode mode) const
{ return myKeyTable[key][mode]; } { return myKeyTable[key][mode]; }
Event::Type eventForJoyAxis(int stick, int axis, int value, EventMode mode) const Event::Type eventForJoyAxis(int stick, int axis, int value, EventMode mode) const {
{ return myJoysticks[stick]->axisTable[axis][(value > 0)][mode]; } const StellaJoystick* joy = myJoyHandler->joy(stick);
Event::Type eventForJoyButton(int stick, int button, EventMode mode) const return joy ? joy->axisTable[axis][(value > 0)][mode] : Event::NoType;
{ return myJoysticks[stick]->btnTable[button][mode]; } }
Event::Type eventForJoyHat(int stick, int hat, int value, EventMode mode) const Event::Type eventForJoyButton(int stick, int button, EventMode mode) const {
{ return myJoysticks[stick]->hatTable[hat][value][mode]; } const StellaJoystick* joy = myJoyHandler->joy(stick);
return joy ? joy->btnTable[button][mode] : Event::NoType;
}
Event::Type eventForJoyHat(int stick, int hat, int value, EventMode mode) const {
const StellaJoystick* joy = myJoyHandler->joy(stick);
return joy ? joy->hatTable[hat][value][mode] : Event::NoType;
}
Event::Type eventAtIndex(int idx, EventMode mode) const; Event::Type eventAtIndex(int idx, EventMode mode) const;
string actionAtIndex(int idx, EventMode mode) const; string actionAtIndex(int idx, EventMode mode) const;
@ -333,11 +339,6 @@ class EventHandler
void handleJoyAxisEvent(int stick, int axis, int value); void handleJoyAxisEvent(int stick, int axis, int value);
void handleJoyHatEvent(int stick, int hat, int value); void handleJoyHatEvent(int stick, int hat, int value);
/**
Set up any joysticks on the system.
*/
virtual void initializeJoysticks() = 0;
/** /**
Enable/disable text events (distinct from single-key events). Enable/disable text events (distinct from single-key events).
*/ */
@ -391,7 +392,8 @@ class EventHandler
string about() const; string about() const;
protected: protected:
void initialize(const string& desc, int axes, int buttons, int hats, int balls); void initialize(int index, const string& desc,
int axes, int buttons, int hats, int balls);
private: private:
enum JoyType { enum JoyType {
@ -404,6 +406,7 @@ class EventHandler
}; };
JoyType type; JoyType type;
int ID;
string name; string name;
int numAxes, numButtons, numHats; int numAxes, numButtons, numHats;
Event::Type (*axisTable)[2][kNumModes]; Event::Type (*axisTable)[2][kNumModes];
@ -413,12 +416,67 @@ class EventHandler
private: private:
void getValues(const string& list, IntArray& map); void getValues(const string& list, IntArray& map);
friend ostream& operator<<(ostream& os, const StellaJoystick& s) {
os << " ID: " << s.ID << ", name: " << s.name << ", numaxis: " << s.numAxes
<< ", numbtns: " << s.numButtons << ", numhats: " << s.numHats;
return os;
}
};
class JoystickHandler
{
public:
JoystickHandler(OSystem& system);
~JoystickHandler();
int add(StellaJoystick* stick);
int remove(int id);
uInt32 numSticks() const { return mySticks.size(); }
void mapStelladaptors(const string& saport);
void setDefaultMapping(Event::Type type, EventMode mode);
void eraseMapping(Event::Type event, EventMode mode);
void saveMapping();
const StellaJoystick* joy(int id) const {
return id < mySticks.size() ? mySticks[id] : NULL;
}
private:
OSystem& myOSystem;
struct StickInfo
{
StickInfo(const string& map = EmptyString, StellaJoystick* stick = NULL)
: mapping(map), joy(stick) {}
string mapping;
StellaJoystick* joy;
friend ostream& operator<<(ostream& os, const StickInfo& si) {
os << " joy: " << si.joy << endl << " map: " << si.mapping;
return os;
}
};
// Contains all joysticks that Stella knows about, indexed by name
map<string,StickInfo> myDatabase;
// Contains only joysticks that are currently available, indexed by id
Common::Array<StellaJoystick*> mySticks;
void setStickDefaultMapping(int stick, Event::Type type, EventMode mode);
void printDatabase();
}; };
/** /**
Add the given joystick to the list of sticks available to the handler. Add the given joystick to the list of sticks available to the handler.
*/ */
void addJoystick(StellaJoystick* stick, int idx); void addJoystick(StellaJoystick* stick);
/**
Remove joystick at the current index.
*/
void removeJoystick(int index);
private: private:
enum { enum {
@ -442,7 +500,6 @@ class EventHandler
void setActionMappings(EventMode mode); void setActionMappings(EventMode mode);
void setKeyNames(); void setKeyNames();
void setKeymap(); void setKeymap();
void setJoymap();
void setDefaultKeymap(Event::Type, EventMode mode); void setDefaultKeymap(Event::Type, EventMode mode);
void setDefaultJoymap(Event::Type, EventMode mode); void setDefaultJoymap(Event::Type, EventMode mode);
void saveKeyMapping(); void saveKeyMapping();
@ -519,8 +576,8 @@ class EventHandler
static const Event::Type SA_Button[2][4]; static const Event::Type SA_Button[2][4];
static const Event::Type SA_Key[2][12]; static const Event::Type SA_Key[2][12];
Common::Array<StellaJoystick*> myJoysticks; // Handler for all joystick addition/removal/mapping
map<string,string> myJoystickMap; JoystickHandler* myJoyHandler;
}; };
#endif #endif

View File

@ -0,0 +1,562 @@
//============================================================================
//
// 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-2014 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.
//
// $Id$
//============================================================================
#include <sstream>
#include <map>
#include "OSystem.hxx"
#include "Settings.hxx"
#include "bspf.hxx"
#include "EventHandler.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EventHandler::StellaJoystick::StellaJoystick()
: type(JT_NONE),
ID(-1),
name("None"),
numAxes(0),
numButtons(0),
numHats(0),
axisTable(NULL),
btnTable(NULL),
hatTable(NULL),
axisLastValue(NULL)
{
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EventHandler::StellaJoystick::~StellaJoystick()
{
delete[] axisTable; axisTable = NULL;
delete[] btnTable; btnTable = NULL;
delete[] hatTable; hatTable = NULL;
delete[] axisLastValue; axisLastValue = NULL;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::StellaJoystick::initialize(int index, const string& desc,
int axes, int buttons, int hats, int /*balls*/)
{
ID = index;
name = desc;
// Dynamically create the various mapping arrays for this joystick,
// based on its specific attributes
numAxes = axes;
numButtons = buttons;
numHats = hats;
if(numAxes)
axisTable = new Event::Type[numAxes][2][kNumModes];
if(numButtons)
btnTable = new Event::Type[numButtons][kNumModes];
if(numHats)
hatTable = new Event::Type[numHats][4][kNumModes];
axisLastValue = new int[numAxes];
// Erase the joystick axis mapping array and last axis value
for(int a = 0; a < numAxes; ++a)
{
axisLastValue[a] = 0;
for(int m = 0; m < kNumModes; ++m)
axisTable[a][0][m] = axisTable[a][1][m] = Event::NoType;
}
// Erase the joystick button mapping array
for(int b = 0; b < numButtons; ++b)
for(int m = 0; m < kNumModes; ++m)
btnTable[b][m] = Event::NoType;
// Erase the joystick hat mapping array
for(int h = 0; h < numHats; ++h)
for(int m = 0; m < kNumModes; ++m)
hatTable[h][0][m] = hatTable[h][1][m] =
hatTable[h][2][m] = hatTable[h][3][m] = Event::NoType;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string EventHandler::StellaJoystick::getMap() const
{
// The mapping structure (for remappable devices) is defined as follows:
// NAME | AXIS # + values | BUTTON # + values | HAT # + values,
// where each subsection of values is separated by ':'
if(type == JT_REGULAR)
{
ostringstream joybuf;
joybuf << name << "|" << numAxes;
for(int m = 0; m < kNumModes; ++m)
for(int a = 0; a < numAxes; ++a)
for(int k = 0; k < 2; ++k)
joybuf << " " << axisTable[a][k][m];
joybuf << "|" << numButtons;
for(int m = 0; m < kNumModes; ++m)
for(int b = 0; b < numButtons; ++b)
joybuf << " " << btnTable[b][m];
joybuf << "|" << numHats;
for(int m = 0; m < kNumModes; ++m)
for(int h = 0; h < numHats; ++h)
for(int k = 0; k < 4; ++k)
joybuf << " " << hatTable[h][k][m];
return joybuf.str();
}
return EmptyString;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool EventHandler::StellaJoystick::setMap(const string& m)
{
istringstream buf(m);
StringList items;
string item;
while(getline(buf, item, '|'))
items.push_back(item);
// Error checking
if(items.size() != 4)
return false;
IntArray map;
// Parse axis/button/hat values
getValues(items[1], map);
if((int)map.size() == numAxes * 2 * kNumModes)
{
// Fill the axes table with events
IntArray::const_iterator event = map.begin();
for(int m = 0; m < kNumModes; ++m)
for(int a = 0; a < numAxes; ++a)
for(int k = 0; k < 2; ++k)
axisTable[a][k][m] = (Event::Type) *event++;
}
getValues(items[2], map);
if((int)map.size() == numButtons * kNumModes)
{
IntArray::const_iterator event = map.begin();
for(int m = 0; m < kNumModes; ++m)
for(int b = 0; b < numButtons; ++b)
btnTable[b][m] = (Event::Type) *event++;
}
getValues(items[3], map);
if((int)map.size() == numHats * 4 * kNumModes)
{
IntArray::const_iterator event = map.begin();
for(int m = 0; m < kNumModes; ++m)
for(int h = 0; h < numHats; ++h)
for(int k = 0; k < 4; ++k)
hatTable[h][k][m] = (Event::Type) *event++;
}
return true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::StellaJoystick::eraseMap(EventMode mode)
{
// Erase axis mappings
for(int a = 0; a < numAxes; ++a)
axisTable[a][0][mode] = axisTable[a][1][mode] = Event::NoType;
// Erase button mappings
for(int b = 0; b < numButtons; ++b)
btnTable[b][mode] = Event::NoType;
// Erase hat mappings
for(int h = 0; h < numHats; ++h)
hatTable[h][0][mode] = hatTable[h][1][mode] =
hatTable[h][2][mode] = hatTable[h][3][mode] = Event::NoType;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::StellaJoystick::eraseEvent(Event::Type event, EventMode mode)
{
// Erase axis mappings
for(int a = 0; a < numAxes; ++a)
{
if(axisTable[a][0][mode] == event) axisTable[a][0][mode] = Event::NoType;
if(axisTable[a][1][mode] == event) axisTable[a][1][mode] = Event::NoType;
}
// Erase button mappings
for(int b = 0; b < numButtons; ++b)
if(btnTable[b][mode] == event) btnTable[b][mode] = Event::NoType;
// Erase hat mappings
for(int h = 0; h < numHats; ++h)
{
if(hatTable[h][0][mode] == event) hatTable[h][0][mode] = Event::NoType;
if(hatTable[h][1][mode] == event) hatTable[h][1][mode] = Event::NoType;
if(hatTable[h][2][mode] == event) hatTable[h][2][mode] = Event::NoType;
if(hatTable[h][3][mode] == event) hatTable[h][3][mode] = Event::NoType;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::StellaJoystick::getValues(const string& list, IntArray& map)
{
map.clear();
istringstream buf(list);
int value;
buf >> value; // we don't need to know the # of items at this point
while(buf >> value)
map.push_back(value);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string EventHandler::StellaJoystick::about() const
{
ostringstream buf;
buf << name;
if(type == JT_REGULAR)
buf << " with: " << numAxes << " axes, " << numButtons << " buttons, "
<< numHats << " hats";
return buf.str();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EventHandler::JoystickHandler::JoystickHandler(OSystem& system)
: myOSystem(system)
{
// Load previously saved joystick mapping (if any) from settings
istringstream buf(myOSystem.settings().getString("joymap"));
string joymap, joyname;
// First check the event type, and disregard the entire mapping if it's invalid
getline(buf, joymap, '^');
if(atoi(joymap.c_str()) == Event::LastType)
{
// Otherwise, put each joystick mapping entry into the database
while(getline(buf, joymap, '^'))
{
istringstream namebuf(joymap);
getline(namebuf, joyname, '|');
if(joyname.length() != 0)
{
StickInfo info(joymap);
myDatabase.insert(make_pair(joyname, info));
}
}
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EventHandler::JoystickHandler::~JoystickHandler()
{
map<string,StickInfo>::const_iterator it;
for(it = myDatabase.begin(); it != myDatabase.end(); ++it)
delete it->second.joy;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::JoystickHandler::printDatabase()
{
cerr << "---------------------------------------------------------" << endl
<< "joy database:" << endl;
map<string,StickInfo>::const_iterator it;
for(it = myDatabase.begin(); it != myDatabase.end(); ++it)
cerr << it->first << endl << it->second << endl << endl;
cerr << "---------------------------------------------------------" << endl
<< "joy active:" << endl;
for(uInt32 i = 0; i < mySticks.size(); ++i)
cerr << *mySticks[i] << endl;
cerr << endl;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int EventHandler::JoystickHandler::add(StellaJoystick* stick)
{
// Skip if we couldn't open it for any reason
if(stick->ID < 0)
return stick->ID;
// Figure out what type of joystick this is
bool specialAdaptor = false;
if(stick->name.find("2600-daptor", 0) != string::npos)
{
// 2600-daptorII devices have 3 axes and 12 buttons, and the value of the z-axis
// determines how those 12 buttons are used (not all buttons are used in all modes)
if(stick->numAxes == 3)
{
// TODO - stubbed out for now, until we find a way to reliably get info
// from the Z axis
stick->name = "2600-daptor II";
}
else
stick->name = "2600-daptor";
specialAdaptor = true;
}
else if(stick->name.find("Stelladaptor", 0) != string::npos)
{
stick->name = "Stelladaptor";
specialAdaptor = true;
}
else
{
// We need unique names for mappable devices
int count = 0;
map<string,StickInfo>::const_iterator c_it;
for(c_it = myDatabase.begin(); c_it != myDatabase.end(); ++c_it)
if(BSPF_startsWithIgnoreCase(c_it->first, stick->name))
++count;
if(count > 1)
{
ostringstream name;
name << stick->name << " " << count;
stick->name = name.str();
}
stick->type = StellaJoystick::JT_REGULAR;
}
mySticks.insert_at(stick->ID, stick);
// Map the stelladaptors we've found according to the specified ports
if(specialAdaptor)
mapStelladaptors(myOSystem.settings().getString("saport"));
// Add stick to database
map<string,StickInfo>::iterator it = myDatabase.find(stick->name);
if(it != myDatabase.end()) // already present
{
it->second.joy = stick;
stick->setMap(it->second.mapping);
}
else // adding for the first time
{
StickInfo info("", stick);
myDatabase.insert(make_pair(stick->name, info));
setStickDefaultMapping(stick->ID, Event::NoType, kEmulationMode);
setStickDefaultMapping(stick->ID, Event::NoType, kMenuMode);
}
return stick->ID;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int EventHandler::JoystickHandler::remove(int index)
{
// When a joystick is removed, we delete the actual joystick object but
// remember its mapping, since it will eventually be saved to settings
// Sticks that are removed must have initially been added
// So we use the 'active' joystick list to access them
if(index >= 0 && index < mySticks.size() && mySticks[index] != NULL)
{
StellaJoystick* stick = mySticks[index];
map<string,StickInfo>::iterator it = myDatabase.find(stick->name);
if(it != myDatabase.end() && it->second.joy == stick)
{
ostringstream buf;
buf << "Removed joystick " << mySticks[index]->ID << ":" << endl
<< " " << mySticks[index]->about() << endl;
myOSystem.logMessage(buf.str(), 1);
// Remove joystick, but remember mapping
it->second.mapping = stick->getMap();
delete it->second.joy; it->second.joy = NULL;
mySticks[index] = NULL;
return index;
}
}
return -1;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::JoystickHandler::mapStelladaptors(const string& saport)
{
// saport will have two values:
// 'lr' means treat first valid adaptor as left port, second as right port
// 'rl' means treat first valid adaptor as right port, second as left port
// We know there will be only two such devices (at most), since the logic
// in setupJoysticks take care of that
int saCount = 0;
int saOrder[2] = { 1, 2 };
if(BSPF_equalsIgnoreCase(saport, "rl"))
{
saOrder[0] = 2; saOrder[1] = 1;
}
for(uInt32 i = 0; i < mySticks.size(); ++i)
{
if(BSPF_startsWithIgnoreCase(mySticks[i]->name, "Stelladaptor"))
{
if(saOrder[saCount] == 1)
{
mySticks[i]->name += " (emulates left joystick port)";
mySticks[i]->type = StellaJoystick::JT_STELLADAPTOR_LEFT;
}
else if(saOrder[saCount] == 2)
{
mySticks[i]->name += " (emulates right joystick port)";
mySticks[i]->type = StellaJoystick::JT_STELLADAPTOR_RIGHT;
}
saCount++;
}
else if(BSPF_startsWithIgnoreCase(mySticks[i]->name, "2600-daptor"))
{
if(saOrder[saCount] == 1)
{
mySticks[i]->name += " (emulates left joystick port)";
mySticks[i]->type = StellaJoystick::JT_2600DAPTOR_LEFT;
}
else if(saOrder[saCount] == 2)
{
mySticks[i]->name += " (emulates right joystick port)";
mySticks[i]->type = StellaJoystick::JT_2600DAPTOR_RIGHT;
}
saCount++;
}
}
myOSystem.settings().setValue("saport", saport);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::JoystickHandler::setDefaultMapping(Event::Type event, EventMode mode)
{
eraseMapping(event, mode);
setStickDefaultMapping(0, event, mode);
setStickDefaultMapping(1, event, mode);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::JoystickHandler::setStickDefaultMapping(int stick,
Event::Type event, EventMode mode)
{
#define SET_DEFAULT_AXIS(sda_event, sda_mode, sda_stick, sda_axis, sda_val, sda_cmp_event) \
if(eraseAll || sda_cmp_event == sda_event) \
handler.addJoyAxisMapping(sda_event, sda_mode, sda_stick, sda_axis, sda_val, false);
#define SET_DEFAULT_BTN(sdb_event, sdb_mode, sdb_stick, sdb_button, sdb_cmp_event) \
if(eraseAll || sdb_cmp_event == sdb_event) \
handler.addJoyButtonMapping(sdb_event, sdb_mode, sdb_stick, sdb_button, false);
#define SET_DEFAULT_HAT(sdh_event, sdh_mode, sdh_stick, sdh_hat, sdh_dir, sdh_cmp_event) \
if(eraseAll || sdh_cmp_event == sdh_event) \
handler.addJoyHatMapping(sdh_event, sdh_mode, sdh_stick, sdh_hat, sdh_dir, false);
EventHandler& handler = myOSystem.eventHandler();
bool eraseAll = (event == Event::NoType);
switch(mode)
{
case kEmulationMode: // Default emulation events
if(stick == 0)
{
// Left joystick left/right directions (assume joystick zero)
SET_DEFAULT_AXIS(Event::JoystickZeroLeft, mode, 0, 0, 0, event);
SET_DEFAULT_AXIS(Event::JoystickZeroRight, mode, 0, 0, 1, event);
// Left joystick up/down directions (assume joystick zero)
SET_DEFAULT_AXIS(Event::JoystickZeroUp, mode, 0, 1, 0, event);
SET_DEFAULT_AXIS(Event::JoystickZeroDown, mode, 0, 1, 1, event);
// Left joystick (assume joystick zero, button zero)
SET_DEFAULT_BTN(Event::JoystickZeroFire, mode, 0, 0, event);
// Left joystick left/right directions (assume joystick zero and hat 0)
SET_DEFAULT_HAT(Event::JoystickZeroLeft, mode, 0, 0, EVENT_HATLEFT, event);
SET_DEFAULT_HAT(Event::JoystickZeroRight, mode, 0, 0, EVENT_HATRIGHT, event);
// Left joystick up/down directions (assume joystick zero and hat 0)
SET_DEFAULT_HAT(Event::JoystickZeroUp, mode, 0, 0, EVENT_HATUP, event);
SET_DEFAULT_HAT(Event::JoystickZeroDown, mode, 0, 0, EVENT_HATDOWN, event);
}
else if(stick == 1)
{
// Right joystick left/right directions (assume joystick one)
SET_DEFAULT_AXIS(Event::JoystickOneLeft, mode, 1, 0, 0, event);
SET_DEFAULT_AXIS(Event::JoystickOneRight, mode, 1, 0, 1, event);
// Right joystick left/right directions (assume joystick one)
SET_DEFAULT_AXIS(Event::JoystickOneUp, mode, 1, 1, 0, event);
SET_DEFAULT_AXIS(Event::JoystickOneDown, mode, 1, 1, 1, event);
// Right joystick (assume joystick one, button zero)
SET_DEFAULT_BTN(Event::JoystickOneFire, mode, 1, 0, event);
// Right joystick left/right directions (assume joystick one and hat 0)
SET_DEFAULT_HAT(Event::JoystickOneLeft, mode, 1, 0, EVENT_HATLEFT, event);
SET_DEFAULT_HAT(Event::JoystickOneRight, mode, 1, 0, EVENT_HATRIGHT, event);
// Right joystick up/down directions (assume joystick one and hat 0)
SET_DEFAULT_HAT(Event::JoystickOneUp, mode, 1, 0, EVENT_HATUP, event);
SET_DEFAULT_HAT(Event::JoystickOneDown, mode, 1, 0, EVENT_HATDOWN, event);
}
break;
case kMenuMode: // Default menu/UI events
if(stick == 0)
{
SET_DEFAULT_AXIS(Event::UILeft, mode, 0, 0, 0, event);
SET_DEFAULT_AXIS(Event::UIRight, mode, 0, 0, 1, event);
SET_DEFAULT_AXIS(Event::UIUp, mode, 0, 1, 0, event);
SET_DEFAULT_AXIS(Event::UIDown, mode, 0, 1, 1, event);
// Left joystick (assume joystick zero, button zero)
SET_DEFAULT_BTN(Event::UISelect, mode, 0, 0, event);
// Right joystick (assume joystick one, button zero)
SET_DEFAULT_BTN(Event::UISelect, mode, 1, 0, event);
SET_DEFAULT_HAT(Event::UILeft, mode, 0, 0, EVENT_HATLEFT, event);
SET_DEFAULT_HAT(Event::UIRight, mode, 0, 0, EVENT_HATRIGHT, event);
SET_DEFAULT_HAT(Event::UIUp, mode, 0, 0, EVENT_HATUP, event);
SET_DEFAULT_HAT(Event::UIDown, mode, 0, 0, EVENT_HATDOWN, event);
}
break;
default:
break;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::JoystickHandler::eraseMapping(Event::Type event, EventMode mode)
{
// If event is 'NoType', erase and reset all mappings
// Otherwise, only reset the given event
if(event == Event::NoType)
{
for(uInt32 i = 0; i < mySticks.size(); ++i)
mySticks[i]->eraseMap(mode); // erase all events
}
else
{
for(uInt32 i = 0; i < mySticks.size(); ++i)
mySticks[i]->eraseEvent(event, mode); // only reset the specific event
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandler::JoystickHandler::saveMapping()
{
// Save the joystick mapping hash table, making sure to update it with
// any changes that have been made during the program run
ostringstream joybuf;
joybuf << Event::LastType;
map<string,StickInfo>::const_iterator it;
for(it = myDatabase.begin(); it != myDatabase.end(); ++it)
{
const string& map = it->second.joy ?
it->second.joy->getMap() : it->second.mapping;
if(map != "")
joybuf << "^" << map;
}
myOSystem.settings().setValue("joymap", joybuf.str());
}

View File

@ -705,81 +705,6 @@ void OSystem::validatePath(string& path, const string& setting,
mySettings->setValue(setting, node.getShortPath()); mySettings->setValue(setting, node.getShortPath());
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void OSystem::setDefaultJoymap(Event::Type event, EventMode mode)
{
#define SET_DEFAULT_AXIS(sda_event, sda_mode, sda_stick, sda_axis, sda_val, sda_cmp_event) \
if(eraseAll || sda_cmp_event == sda_event) \
myEventHandler->addJoyAxisMapping(sda_event, sda_mode, sda_stick, sda_axis, sda_val, false);
#define SET_DEFAULT_BTN(sdb_event, sdb_mode, sdb_stick, sdb_button, sdb_cmp_event) \
if(eraseAll || sdb_cmp_event == sdb_event) \
myEventHandler->addJoyButtonMapping(sdb_event, sdb_mode, sdb_stick, sdb_button, false);
#define SET_DEFAULT_HAT(sdh_event, sdh_mode, sdh_stick, sdh_hat, sdh_dir, sdh_cmp_event) \
if(eraseAll || sdh_cmp_event == sdh_event) \
myEventHandler->addJoyHatMapping(sdh_event, sdh_mode, sdh_stick, sdh_hat, sdh_dir, false);
bool eraseAll = (event == Event::NoType);
switch(mode)
{
case kEmulationMode: // Default emulation events
// Left joystick left/right directions (assume joystick zero)
SET_DEFAULT_AXIS(Event::JoystickZeroLeft, mode, 0, 0, 0, event);
SET_DEFAULT_AXIS(Event::JoystickZeroRight, mode, 0, 0, 1, event);
// Left joystick up/down directions (assume joystick zero)
SET_DEFAULT_AXIS(Event::JoystickZeroUp, mode, 0, 1, 0, event);
SET_DEFAULT_AXIS(Event::JoystickZeroDown, mode, 0, 1, 1, event);
// Right joystick left/right directions (assume joystick one)
SET_DEFAULT_AXIS(Event::JoystickOneLeft, mode, 1, 0, 0, event);
SET_DEFAULT_AXIS(Event::JoystickOneRight, mode, 1, 0, 1, event);
// Right joystick left/right directions (assume joystick one)
SET_DEFAULT_AXIS(Event::JoystickOneUp, mode, 1, 1, 0, event);
SET_DEFAULT_AXIS(Event::JoystickOneDown, mode, 1, 1, 1, event);
// Left joystick (assume joystick zero, button zero)
SET_DEFAULT_BTN(Event::JoystickZeroFire, mode, 0, 0, event);
// Right joystick (assume joystick one, button zero)
SET_DEFAULT_BTN(Event::JoystickOneFire, mode, 1, 0, event);
// Left joystick left/right directions (assume joystick zero and hat 0)
SET_DEFAULT_HAT(Event::JoystickZeroLeft, mode, 0, 0, EVENT_HATLEFT, event);
SET_DEFAULT_HAT(Event::JoystickZeroRight, mode, 0, 0, EVENT_HATRIGHT, event);
// Left joystick up/down directions (assume joystick zero and hat 0)
SET_DEFAULT_HAT(Event::JoystickZeroUp, mode, 0, 0, EVENT_HATUP, event);
SET_DEFAULT_HAT(Event::JoystickZeroDown, mode, 0, 0, EVENT_HATDOWN, event);
// Right joystick left/right directions (assume joystick one and hat 0)
SET_DEFAULT_HAT(Event::JoystickOneLeft, mode, 1, 0, EVENT_HATLEFT, event);
SET_DEFAULT_HAT(Event::JoystickOneRight, mode, 1, 0, EVENT_HATRIGHT, event);
// Right joystick up/down directions (assume joystick one and hat 0)
SET_DEFAULT_HAT(Event::JoystickOneUp, mode, 1, 0, EVENT_HATUP, event);
SET_DEFAULT_HAT(Event::JoystickOneDown, mode, 1, 0, EVENT_HATDOWN, event);
break;
case kMenuMode: // Default menu/UI events
SET_DEFAULT_AXIS(Event::UILeft, mode, 0, 0, 0, event);
SET_DEFAULT_AXIS(Event::UIRight, mode, 0, 0, 1, event);
SET_DEFAULT_AXIS(Event::UIUp, mode, 0, 1, 0, event);
SET_DEFAULT_AXIS(Event::UIDown, mode, 0, 1, 1, event);
// Left joystick (assume joystick zero, button zero)
SET_DEFAULT_BTN(Event::UISelect, mode, 0, 0, event);
// Right joystick (assume joystick one, button zero)
SET_DEFAULT_BTN(Event::UISelect, mode, 1, 0, event);
SET_DEFAULT_HAT(Event::UILeft, mode, 0, 0, EVENT_HATLEFT, event);
SET_DEFAULT_HAT(Event::UIRight, mode, 0, 0, EVENT_HATRIGHT, event);
SET_DEFAULT_HAT(Event::UIUp, mode, 0, 0, EVENT_HATUP, event);
SET_DEFAULT_HAT(Event::UIDown, mode, 0, 0, EVENT_HATDOWN, event);
break;
default:
break;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt64 OSystem::getTicks() const uInt64 OSystem::getTicks() const
{ {

View File

@ -419,15 +419,6 @@ class OSystem
*/ */
virtual void mainLoop(); virtual void mainLoop();
/**
This method determines the default mapping of joystick actions to
Stella events for a specific system/platform.
@param event The event which to (re)set (Event::NoType resets all)
@param mode The mode for which the defaults are set
*/
virtual void setDefaultJoymap(Event::Type event, EventMode mode);
/** /**
Informs the OSystem of a change in EventHandler state. Informs the OSystem of a change in EventHandler state.
*/ */

View File

@ -46,6 +46,7 @@ MODULE_OBJS := \
src/emucore/Control.o \ src/emucore/Control.o \
src/emucore/Driving.o \ src/emucore/Driving.o \
src/emucore/EventHandler.o \ src/emucore/EventHandler.o \
src/emucore/EventJoyHandler.o \
src/emucore/FrameBuffer.o \ src/emucore/FrameBuffer.o \
src/emucore/FBSurface.o \ src/emucore/FBSurface.o \
src/emucore/FSNode.o \ src/emucore/FSNode.o \

View File

@ -48,8 +48,8 @@ LoggerDialog::LoggerDialog(OSystem* osystem, DialogContainer* parent,
// Set real dimensions // Set real dimensions
// This is one dialog that can take as much space as is available // This is one dialog that can take as much space as is available
_w = BSPF_min(max_w, 480); _w = max_w;
_h = BSPF_min(max_h, 380); _h = max_h;
// Test listing of the log output // Test listing of the log output
xpos = 10; ypos = 10; xpos = 10; ypos = 10;

View File

@ -29,7 +29,8 @@ class Properties;
Menu::Menu(OSystem* osystem) Menu::Menu(OSystem* osystem)
: DialogContainer(osystem) : DialogContainer(osystem)
{ {
myBaseDialog = new OptionsDialog(myOSystem, this, 0, 480, 380, false); myBaseDialog = new OptionsDialog(myOSystem, this, 0,
FrameBuffer::kFBMinW, FrameBuffer::kFBMinH, false);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -