stella/src/common/PKeyboardHandler.cxx

888 lines
36 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-2020 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
#include "OSystem.hxx"
#include "Console.hxx"
#include "EventHandler.hxx"
#include "PKeyboardHandler.hxx"
#ifdef DEBUGGER_SUPPORT
#include "Debugger.hxx"
#endif
#ifdef GUI_SUPPORT
#include "DialogContainer.hxx"
#endif
#if defined(BSPF_MACOS) || defined(MACOS_KEYS)
static constexpr int MOD3 = KBDM_GUI;
static constexpr int CMD = KBDM_GUI;
static constexpr int OPTION = KBDM_ALT;
#else
static constexpr int MOD3 = KBDM_ALT;
#endif
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PhysicalKeyboardHandler::PhysicalKeyboardHandler(OSystem& system, EventHandler& handler)
: myOSystem(system),
myHandler(handler)
{
Int32 version = myOSystem.settings().getInt("event_ver");
bool updateDefaults = false;
// Compare if event list version has changed so that key maps became invalid
if (version == Event::VERSION)
{
string list = myOSystem.settings().getString("keymap_emu");
myKeyMap.loadMapping(list, EventMode::kCommonMode);
list = myOSystem.settings().getString("keymap_joy");
myKeyMap.loadMapping(list, EventMode::kJoystickMode);
list = myOSystem.settings().getString("keymap_pad");
myKeyMap.loadMapping(list, EventMode::kPaddlesMode);
list = myOSystem.settings().getString("keymap_key");
myKeyMap.loadMapping(list, EventMode::kKeypadMode);
list = myOSystem.settings().getString("keymap_ui");
myKeyMap.loadMapping(list, EventMode::kMenuMode);
updateDefaults = true;
}
myKeyMap.enableMod() = myOSystem.settings().getBool("modcombo");
setDefaultMapping(Event::NoType, EventMode::kEmulationMode, updateDefaults);
setDefaultMapping(Event::NoType, EventMode::kMenuMode, updateDefaults);
setDefaultMapping(Event::NoType, EventMode::kEditMode, updateDefaults);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool PhysicalKeyboardHandler::isMappingUsed(EventMode mode, const EventMapping& map) const
{
// Menu events can only interfere with
// - other menu events
if(mode == EventMode::kMenuMode)
return myKeyMap.check(EventMode::kMenuMode, map.key, map.mod);
// Controller events can interfere with
// - other events of the same controller
// - and common emulation events
if(mode != EventMode::kCommonMode)
return myKeyMap.check(mode, map.key, map.mod)
|| myKeyMap.check(EventMode::kCommonMode, map.key, map.mod);
// Common emulation events can interfere with
// - other common emulation events
// - and all controller events
return myKeyMap.check(EventMode::kCommonMode, map.key, map.mod)
|| myKeyMap.check(EventMode::kJoystickMode, map.key, map.mod)
|| myKeyMap.check(EventMode::kPaddlesMode, map.key, map.mod)
|| myKeyMap.check(EventMode::kKeypadMode, map.key, map.mod)
|| myKeyMap.check(EventMode::kCompuMateMode, map.key, map.mod);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Depending on parameters, this method does the following:
// 1. update all events with default (event == Event::NoType, updateDefault == true)
// 2. reset all events to default (event == Event::NoType, updateDefault == false)
// 3. reset one event to default (event != Event::NoType)
void PhysicalKeyboardHandler::setDefaultKey(EventMapping map, Event::Type event,
EventMode mode, bool updateDefaults)
{
// If event is 'NoType', erase and reset all mappings
// Otherwise, only reset the given event
bool eraseAll = !updateDefaults && (event == Event::NoType);
// Swap Y and Z for QWERTZ keyboards
if(mode == EventMode::kEditMode && myHandler.isQwertz())
{
if(map.key == KBDK_Z)
map.key = KBDK_Y;
else if(map.key == KBDK_Y)
map.key = KBDK_Z;
}
if (updateDefaults)
{
// if there is no existing mapping for the event and
// the default mapping for the event is unused, set default key for event
if (myKeyMap.getEventMapping(map.event, mode).size() == 0 &&
!isMappingUsed(mode, map))
{
addMapping(map.event, mode, map.key, StellaMod(map.mod));
}
}
else if (eraseAll || map.event == event)
{
//myKeyMap.eraseEvent(map.event, mode);
addMapping(map.event, mode, map.key, StellaMod(map.mod));
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Depending on parameters, this method does the following:
// 1. update all events with default (event == Event::NoType, updateDefault == true)
// 2. reset all events to default (event == Event::NoType, updateDefault == false)
// 3. reset one event to default (event != Event::NoType)
void PhysicalKeyboardHandler::setDefaultMapping(Event::Type event, EventMode mode,
bool updateDefaults)
{
if (!updateDefaults)
{
myKeyMap.eraseEvent(event, mode);
myKeyMap.eraseEvent(event, getEventMode(event, mode));
}
switch(mode)
{
case EventMode::kEmulationMode:
for (const auto& item: DefaultCommonMapping)
setDefaultKey(item, event, EventMode::kCommonMode, updateDefaults);
// put all controller events into their own mode's mappings
for (const auto& item: DefaultJoystickMapping)
setDefaultKey(item, event, EventMode::kJoystickMode, updateDefaults);
for (const auto& item: DefaultPaddleMapping)
setDefaultKey(item, event, EventMode::kPaddlesMode, updateDefaults);
for (const auto& item: DefaultKeypadMapping)
setDefaultKey(item, event, EventMode::kKeypadMode, updateDefaults);
for (const auto& item : CompuMateMapping)
setDefaultKey(item, event, EventMode::kCompuMateMode, updateDefaults);
break;
case EventMode::kMenuMode:
for (const auto& item: DefaultMenuMapping)
setDefaultKey(item, event, EventMode::kMenuMode, updateDefaults);
break;
case EventMode::kEditMode:
// Edit mode events are always set because they are not saved
for(const auto& item : FixedEditMapping)
setDefaultKey(item, event, EventMode::kEditMode);
break;
default:
break;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PhysicalKeyboardHandler::defineControllerMappings(const Controller::Type type, Controller::Jack port)
{
// determine controller events to use
switch(type)
{
case Controller::Type::Keyboard:
case Controller::Type::KidVid:
if(port == Controller::Jack::Left)
myLeftMode = EventMode::kKeypadMode;
else
myRightMode = EventMode::kKeypadMode;
break;
case Controller::Type::Paddles:
case Controller::Type::PaddlesIAxDr:
case Controller::Type::PaddlesIAxis:
if(port == Controller::Jack::Left)
myLeftMode = EventMode::kPaddlesMode;
else
myRightMode = EventMode::kPaddlesMode;
break;
case Controller::Type::CompuMate:
myLeftMode = myRightMode = EventMode::kCompuMateMode;
break;
default:
// let's use joystick then
if(port == Controller::Jack::Left)
myLeftMode = EventMode::kJoystickMode;
else
myRightMode = EventMode::kJoystickMode;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PhysicalKeyboardHandler::enableEmulationMappings()
{
// start from scratch and enable common mappings
myKeyMap.eraseMode(EventMode::kEmulationMode);
enableCommonMappings();
// enable right mode first, so that in case of mapping clashes the left controller has preference
switch (myRightMode)
{
case EventMode::kPaddlesMode:
enableMappings(RightPaddlesEvents, EventMode::kPaddlesMode);
break;
case EventMode::kKeypadMode:
enableMappings(RightKeypadEvents, EventMode::kKeypadMode);
break;
case EventMode::kCompuMateMode:
// see below
break;
default:
enableMappings(RightJoystickEvents, EventMode::kJoystickMode);
break;
}
switch (myLeftMode)
{
case EventMode::kPaddlesMode:
enableMappings(LeftPaddlesEvents, EventMode::kPaddlesMode);
break;
case EventMode::kKeypadMode:
enableMappings(LeftKeypadEvents, EventMode::kKeypadMode);
break;
case EventMode::kCompuMateMode:
for (const auto& item : CompuMateMapping)
enableMapping(item.event, EventMode::kCompuMateMode);
break;
default:
enableMappings(LeftJoystickEvents, EventMode::kJoystickMode);
break;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PhysicalKeyboardHandler::enableCommonMappings()
{
for (int i = Event::NoType + 1; i < Event::LastType; i++)
{
Event::Type event = static_cast<Event::Type>(i);
if (isCommonEvent(event))
enableMapping(event, EventMode::kCommonMode);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PhysicalKeyboardHandler::enableMappings(const Event::EventSet& events, EventMode mode)
{
for (const auto& event : events)
enableMapping(event, mode);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PhysicalKeyboardHandler::enableMapping(const Event::Type event, EventMode mode)
{
// copy from controller mode into emulation mode
KeyMap::MappingArray mappings = myKeyMap.getEventMapping(event, mode);
for (const auto& mapping : mappings)
myKeyMap.add(event, EventMode::kEmulationMode, mapping.key, mapping.mod);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EventMode PhysicalKeyboardHandler::getEventMode(const Event::Type event, const EventMode mode) const
{
if (mode == EventMode::kEmulationMode)
{
if (isJoystickEvent(event))
return EventMode::kJoystickMode;
if (isPaddleEvent(event))
return EventMode::kPaddlesMode;
if (isKeypadEvent(event))
return EventMode::kKeypadMode;
if (isCommonEvent(event))
return EventMode::kCommonMode;
}
return mode;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool PhysicalKeyboardHandler::isJoystickEvent(const Event::Type event) const
{
return LeftJoystickEvents.find(event) != LeftJoystickEvents.end()
|| RightJoystickEvents.find(event) != RightJoystickEvents.end();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool PhysicalKeyboardHandler::isPaddleEvent(const Event::Type event) const
{
return LeftPaddlesEvents.find(event) != LeftPaddlesEvents.end()
|| RightPaddlesEvents.find(event) != RightPaddlesEvents.end();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool PhysicalKeyboardHandler::isKeypadEvent(const Event::Type event) const
{
return LeftKeypadEvents.find(event) != LeftKeypadEvents.end()
|| RightKeypadEvents.find(event) != RightKeypadEvents.end();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool PhysicalKeyboardHandler::isCommonEvent(const Event::Type event) const
{
return !(isJoystickEvent(event) || isPaddleEvent(event) || isKeypadEvent(event));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PhysicalKeyboardHandler::eraseMapping(Event::Type event, EventMode mode)
{
myKeyMap.eraseEvent(event, mode);
myKeyMap.eraseEvent(event, getEventMode(event, mode));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PhysicalKeyboardHandler::saveMapping()
{
myOSystem.settings().setValue("event_ver", Event::VERSION);
myOSystem.settings().setValue("keymap_emu", myKeyMap.saveMapping(EventMode::kCommonMode));
myOSystem.settings().setValue("keymap_joy", myKeyMap.saveMapping(EventMode::kJoystickMode));
myOSystem.settings().setValue("keymap_pad", myKeyMap.saveMapping(EventMode::kPaddlesMode));
myOSystem.settings().setValue("keymap_key", myKeyMap.saveMapping(EventMode::kKeypadMode));
myOSystem.settings().setValue("keymap_ui", myKeyMap.saveMapping(EventMode::kMenuMode));
enableEmulationMappings();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool PhysicalKeyboardHandler::addMapping(Event::Type event, EventMode mode,
StellaKey key, StellaMod mod)
{
// These events cannot be remapped to keys
if(Event::isAnalog(event))
return false;
else
{
EventMode evMode = getEventMode(event, mode);
// avoid double mapping in common and controller modes
if (evMode == EventMode::kCommonMode)
{
// erase identical mappings for all controller modes
myKeyMap.erase(EventMode::kJoystickMode, key, mod);
myKeyMap.erase(EventMode::kPaddlesMode, key, mod);
myKeyMap.erase(EventMode::kKeypadMode, key, mod);
myKeyMap.erase(EventMode::kCompuMateMode, key, mod);
}
else if(evMode != EventMode::kMenuMode && evMode != EventMode::kEditMode)
{
// erase identical mapping for kCommonMode
myKeyMap.erase(EventMode::kCommonMode, key, mod);
}
myKeyMap.add(event, evMode, key, mod);
if (evMode == myLeftMode || evMode == myRightMode)
myKeyMap.add(event, mode, key, mod);
}
return true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PhysicalKeyboardHandler::handleEvent(StellaKey key, StellaMod mod, bool pressed, bool repeated)
{
#ifdef BSPF_UNIX
// Swallow KBDK_TAB under certain conditions
// See commments on 'myAltKeyCounter' for more information
if(myAltKeyCounter > 1 && key == KBDK_TAB)
{
myAltKeyCounter = 0;
return;
}
if (key == KBDK_TAB && pressed && StellaModTest::isAlt(mod))
{
// Swallow Alt-Tab, but remember that it happened
myAltKeyCounter = 1;
return;
}
#endif
EventHandlerState estate = myHandler.state();
// special handling for CompuMate in emulation modes
if ((estate == EventHandlerState::EMULATION || estate == EventHandlerState::PAUSE) &&
myOSystem.console().leftController().type() == Controller::Type::CompuMate)
{
Event::Type event = myKeyMap.get(EventMode::kCompuMateMode, key, mod);
// (potential) CompuMate events are handled directly.
if (myKeyMap.get(EventMode::kEmulationMode, key, mod) != Event::ExitMode &&
!StellaModTest::isAlt(mod) && event != Event::NoType)
{
myHandler.handleEvent(event, pressed, repeated);
return;
}
}
// Arrange the logic to take advantage of short-circuit evaluation
// Handle keys which switch eventhandler state
if (!pressed && myHandler.changeStateByEvent(myKeyMap.get(EventMode::kEmulationMode, key, mod)))
return;
// Otherwise, let the event handler deal with it
switch(estate)
{
case EventHandlerState::EMULATION:
case EventHandlerState::PAUSE:
case EventHandlerState::PLAYBACK:
myHandler.handleEvent(myKeyMap.get(EventMode::kEmulationMode, key, mod), pressed, repeated);
break;
default:
#ifdef GUI_SUPPORT
if (myHandler.hasOverlay())
myHandler.overlay().handleKeyEvent(key, mod, pressed, repeated);
#endif
myHandler.handleEvent(myKeyMap.get(EventMode::kMenuMode, key, mod), pressed, repeated);
break;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultCommonMapping = {
{Event::ConsoleSelect, KBDK_F1},
{Event::ConsoleReset, KBDK_F2},
{Event::ConsoleColor, KBDK_F3},
{Event::Console7800Pause, KBDK_F3, MOD3},
{Event::ConsoleLeftDiffA, KBDK_F5},
{Event::ConsoleRightDiffA, KBDK_F7},
{Event::SaveState, KBDK_F9},
{Event::SaveAllStates, KBDK_F9, MOD3},
{Event::PreviousState, KBDK_F10, KBDM_SHIFT},
{Event::NextState, KBDK_F10},
{Event::ToggleAutoSlot, KBDK_F10, MOD3},
{Event::LoadState, KBDK_F11},
{Event::LoadAllStates, KBDK_F11, MOD3},
{Event::TakeSnapshot, KBDK_F12},
#ifdef BSPF_MACOS
{Event::TogglePauseMode, KBDK_P, KBDM_SHIFT | MOD3},
#else
{Event::TogglePauseMode, KBDK_PAUSE},
#endif
{Event::OptionsMenuMode, KBDK_TAB},
{Event::CmdMenuMode, KBDK_BACKSLASH},
{Event::TimeMachineMode, KBDK_T, KBDM_SHIFT},
{Event::DebuggerMode, KBDK_GRAVE},
{Event::ExitMode, KBDK_ESCAPE},
#ifdef BSPF_MACOS
{Event::Quit, KBDK_Q, MOD3},
#else
{Event::Quit, KBDK_Q, KBDM_CTRL},
#endif
{Event::ReloadConsole, KBDK_R, KBDM_CTRL},
{Event::PreviousMultiCartRom, KBDK_R, KBDM_SHIFT | KBDM_CTRL},
{Event::VidmodeDecrease, KBDK_MINUS, MOD3},
{Event::VidmodeIncrease, KBDK_EQUALS, MOD3},
{Event::VCenterDecrease, KBDK_PAGEUP, MOD3},
{Event::VCenterIncrease, KBDK_PAGEDOWN, MOD3},
{Event::VSizeAdjustDecrease, KBDK_PAGEDOWN, KBDM_SHIFT | MOD3},
{Event::VSizeAdjustIncrease, KBDK_PAGEUP, KBDM_SHIFT | MOD3},
{Event::ToggleCorrectAspectRatio, KBDK_C, KBDM_CTRL},
{Event::VolumeDecrease, KBDK_LEFTBRACKET, MOD3},
{Event::VolumeIncrease, KBDK_RIGHTBRACKET, MOD3},
{Event::SoundToggle, KBDK_RIGHTBRACKET, KBDM_CTRL},
{Event::ToggleFullScreen, KBDK_RETURN, MOD3},
{Event::ToggleAdaptRefresh, KBDK_R, MOD3},
{Event::OverscanDecrease, KBDK_PAGEDOWN, KBDM_SHIFT},
{Event::OverscanIncrease, KBDK_PAGEUP, KBDM_SHIFT},
//{Event::VidmodeStd, KBDK_1, MOD3},
//{Event::VidmodeRGB, KBDK_2, MOD3},
//{Event::VidmodeSVideo, KBDK_3, MOD3},
//{Event::VidModeComposite, KBDK_4, MOD3},
//{Event::VidModeBad, KBDK_5, MOD3},
//{Event::VidModeCustom, KBDK_6, MOD3},
{Event::PreviousVideoMode, KBDK_1, KBDM_SHIFT | MOD3},
{Event::NextVideoMode, KBDK_1, MOD3},
{Event::PreviousAttribute, KBDK_2, KBDM_SHIFT | MOD3},
{Event::NextAttribute, KBDK_2, MOD3},
{Event::DecreaseAttribute, KBDK_3, KBDM_SHIFT | MOD3},
{Event::IncreaseAttribute, KBDK_3, MOD3},
{Event::PhosphorDecrease, KBDK_4, KBDM_SHIFT | MOD3},
{Event::PhosphorIncrease, KBDK_4, MOD3},
{Event::TogglePhosphor, KBDK_P, MOD3},
{Event::ScanlinesDecrease, KBDK_5, KBDM_SHIFT | MOD3},
{Event::ScanlinesIncrease, KBDK_5, MOD3},
{Event::PreviousPaletteAttribute, KBDK_9, KBDM_SHIFT | MOD3},
{Event::NextPaletteAttribute, KBDK_9, MOD3},
{Event::PaletteAttributeDecrease, KBDK_0, KBDM_SHIFT | MOD3},
{Event::PaletteAttributeIncrease, KBDK_0, MOD3},
{Event::ToggleColorLoss, KBDK_L, KBDM_CTRL},
{Event::PaletteDecrease, KBDK_P, KBDM_SHIFT | KBDM_CTRL},
{Event::PaletteIncrease, KBDK_P, KBDM_CTRL},
#ifndef BSPF_MACOS
{Event::PreviousSetting, KBDK_END},
{Event::NextSetting, KBDK_HOME},
{Event::PreviousSettingGroup, KBDK_END, KBDM_CTRL},
{Event::NextSettingGroup, KBDK_HOME, KBDM_CTRL},
#else
// HOME & END keys are swapped on Mac keyboards
{Event::PreviousSetting, KBDK_HOME},
{Event::NextSetting, KBDK_END},
{Event::PreviousSettingGroup, KBDK_HOME, KBDM_CTRL},
{Event::NextSettingGroup, KBDK_END, KBDM_CTRL},
#endif
{Event::PreviousSetting, KBDK_KP_1},
{Event::NextSetting, KBDK_KP_7},
{Event::PreviousSettingGroup, KBDK_KP_1, KBDM_CTRL},
{Event::NextSettingGroup, KBDK_KP_7, KBDM_CTRL},
{Event::SettingDecrease, KBDK_PAGEDOWN},
{Event::SettingDecrease, KBDK_KP_3, KBDM_CTRL},
{Event::SettingIncrease, KBDK_PAGEUP},
{Event::SettingIncrease, KBDK_KP_9, KBDM_CTRL},
{Event::ToggleInter, KBDK_I, KBDM_CTRL},
{Event::DecreaseSpeed, KBDK_S, KBDM_SHIFT | KBDM_CTRL},
{Event::IncreaseSpeed, KBDK_S, KBDM_CTRL },
{Event::ToggleTurbo, KBDK_T, KBDM_CTRL},
{Event::ToggleJitter, KBDK_J, MOD3},
{Event::ToggleFrameStats, KBDK_L, MOD3},
{Event::ToggleTimeMachine, KBDK_T, MOD3},
#ifdef PNG_SUPPORT
{Event::ToggleContSnapshots, KBDK_S, MOD3 | KBDM_CTRL},
{Event::ToggleContSnapshotsFrame, KBDK_S, KBDM_SHIFT | MOD3 | KBDM_CTRL},
#endif
{Event::DecreaseAutoFire, KBDK_A, KBDM_SHIFT | KBDM_CTRL},
{Event::IncreaseAutoFire, KBDK_A, KBDM_CTRL },
{Event::HandleMouseControl, KBDK_0, KBDM_CTRL},
{Event::ToggleGrabMouse, KBDK_G, KBDM_CTRL},
{Event::ToggleSAPortOrder, KBDK_1, KBDM_CTRL},
{Event::FormatDecrease, KBDK_F, KBDM_SHIFT | KBDM_CTRL},
{Event::FormatIncrease, KBDK_F, KBDM_CTRL},
{Event::ToggleP0Collision, KBDK_Z, KBDM_SHIFT | MOD3},
{Event::ToggleP0Bit, KBDK_Z, MOD3},
{Event::ToggleP1Collision, KBDK_X, KBDM_SHIFT | MOD3},
{Event::ToggleP1Bit, KBDK_X, MOD3},
{Event::ToggleM0Collision, KBDK_C, KBDM_SHIFT | MOD3},
{Event::ToggleM0Bit, KBDK_C, MOD3},
{Event::ToggleM1Collision, KBDK_V, KBDM_SHIFT | MOD3},
{Event::ToggleM1Bit, KBDK_V, MOD3},
{Event::ToggleBLCollision, KBDK_B, KBDM_SHIFT | MOD3},
{Event::ToggleBLBit, KBDK_B, MOD3},
{Event::TogglePFCollision, KBDK_N, KBDM_SHIFT | MOD3},
{Event::TogglePFBit, KBDK_N, MOD3},
{Event::ToggleCollisions, KBDK_COMMA, KBDM_SHIFT | MOD3},
{Event::ToggleBits, KBDK_COMMA, MOD3},
{Event::ToggleFixedColors, KBDK_PERIOD, MOD3},
{Event::RewindPause, KBDK_LEFT, KBDM_SHIFT},
{Event::Rewind1Menu, KBDK_LEFT, MOD3},
{Event::Rewind10Menu, KBDK_LEFT, KBDM_SHIFT | MOD3},
{Event::RewindAllMenu, KBDK_DOWN, MOD3},
{Event::UnwindPause, KBDK_LEFT, KBDM_SHIFT},
{Event::Unwind1Menu, KBDK_RIGHT, MOD3},
{Event::Unwind10Menu, KBDK_RIGHT, KBDM_SHIFT | MOD3},
{Event::UnwindAllMenu, KBDK_UP, MOD3},
{Event::TogglePlayBackMode, KBDK_SPACE, KBDM_SHIFT},
#if defined(RETRON77)
{Event::ConsoleColorToggle, KBDK_F4}, // back ("COLOR","B/W")
{Event::ConsoleLeftDiffToggle, KBDK_F6}, // front ("SKILL P1")
{Event::ConsoleRightDiffToggle, KBDK_F8}, // front ("SKILL P2")
{Event::CmdMenuMode, KBDK_F13}, // back ("4:3","16:9")
{Event::ExitMode, KBDK_BACKSPACE}, // back ("FRY")
#else // defining duplicate keys must be avoided!
{Event::ConsoleBlackWhite, KBDK_F4},
{Event::ConsoleLeftDiffB, KBDK_F6},
{Event::ConsoleRightDiffB, KBDK_F8},
{Event::Fry, KBDK_BACKSPACE},
#endif
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultMenuMapping = {
{Event::UIUp, KBDK_UP},
{Event::UIDown, KBDK_DOWN},
{Event::UILeft, KBDK_LEFT},
{Event::UIRight, KBDK_RIGHT},
{Event::UISelect, KBDK_RETURN},
{Event::UISelect, KBDK_SPACE},
{Event::UIHome, KBDK_HOME},
{Event::UIEnd, KBDK_END},
{Event::UIPgUp, KBDK_PAGEUP},
{Event::UIPgDown, KBDK_PAGEDOWN},
// same with keypad
{Event::UIUp, KBDK_KP_8},
{Event::UIDown, KBDK_KP_2},
{Event::UILeft, KBDK_KP_4},
{Event::UIRight, KBDK_KP_6},
{Event::UISelect, KBDK_KP_ENTER},
{Event::UIHome, KBDK_KP_7},
{Event::UIEnd, KBDK_KP_1},
{Event::UIPgUp, KBDK_KP_9},
{Event::UIPgDown, KBDK_KP_3},
{Event::UICancel, KBDK_ESCAPE},
{Event::UINavPrev, KBDK_TAB, KBDM_SHIFT},
{Event::UINavNext, KBDK_TAB},
{Event::UITabPrev, KBDK_TAB, KBDM_SHIFT | KBDM_CTRL},
{Event::UITabNext, KBDK_TAB, KBDM_CTRL},
{Event::ToggleFullScreen, KBDK_RETURN, MOD3},
#ifdef BSPF_MACOS
{Event::Quit, KBDK_Q, MOD3},
#else
{Event::Quit, KBDK_Q, KBDM_CTRL},
#endif
#if defined(RETRON77)
{Event::UIUp, KBDK_F9}, // front ("SAVE")
{Event::UIDown, KBDK_F2}, // front ("RESET")
{Event::UINavPrev, KBDK_F11}, // front ("LOAD")
{Event::UINavNext, KBDK_F1}, // front ("MODE")
{Event::UISelect, KBDK_F6}, // front ("SKILL P1")
{Event::UICancel, KBDK_F8}, // front ("SKILL P2")
//{Event::NoType, KBDK_F4}, // back ("COLOR","B/W")
{Event::UITabPrev, KBDK_F13}, // back ("4:3","16:9")
{Event::UITabNext, KBDK_BACKSPACE}, // back (FRY)
#else // defining duplicate keys must be avoided!
{Event::UIPrevDir, KBDK_BACKSPACE},
#endif
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::FixedEditMapping = {
// TOOD: check MacOS mappings
{Event::MoveLeftChar, KBDK_LEFT},
{Event::MoveRightChar, KBDK_RIGHT},
{Event::SelectLeftChar, KBDK_LEFT, KBDM_SHIFT},
{Event::SelectRightChar, KBDK_RIGHT, KBDM_SHIFT},
#if defined(BSPF_MACOS) || defined(MACOS_KEYS)
{Event::MoveLeftWord, KBDK_LEFT, OPTION},
{Event::MoveRightWord, KBDK_RIGHT, OPTION},
{Event::MoveHome, KBDK_HOME},
{Event::MoveHome, KBDK_A, KBDM_CTRL},
{Event::MoveHome, KBDK_LEFT, CMD},
{Event::MoveEnd, KBDK_END},
{Event::MoveEnd, KBDK_E, KBDM_CTRL},
{Event::MoveEnd, KBDK_RIGHT, CMD},
{Event::SelectLeftWord, KBDK_LEFT, KBDM_SHIFT | OPTION},
{Event::SelectRightWord, KBDK_RIGHT, KBDM_SHIFT | OPTION},
{Event::SelectHome, KBDK_HOME, KBDM_SHIFT},
{Event::SelectHome, KBDK_LEFT, KBDM_SHIFT | CMD},
{Event::SelectHome, KBDK_A, KBDM_CTRL | KBDM_SHIFT},
{Event::SelectEnd, KBDK_E, KBDM_SHIFT | KBDM_CTRL},
{Event::SelectEnd, KBDK_RIGHT, KBDM_SHIFT | CMD},
{Event::SelectEnd, KBDK_END, KBDM_SHIFT},
{Event::SelectAll, KBDK_A, CMD},
{Event::Delete, KBDK_DELETE},
{Event::DeleteChar, KBDK_D, KBDM_CTRL},
{Event::DeleteWord, KBDK_W, KBDM_CTRL},
{Event::DeleteWord, KBDK_BACKSPACE, KBDM_CTRL},
{Event::DeleteHome, KBDK_U, KBDM_CTRL},
{Event::DeleteHome, KBDK_BACKSPACE, CMD},
{Event::DeleteEnd, KBDK_K, KBDM_CTRL},
{Event::Backspace, KBDK_BACKSPACE},
{Event::Undo, KBDK_Z, CMD},
{Event::Redo, KBDK_Y, CMD},
{Event::Redo, KBDK_Z, KBDM_SHIFT | CMD},
{Event::Cut, KBDK_X, CMD},
{Event::Copy, KBDK_C, CMD},
{Event::Paste, KBDK_V, CMD},
#else
{Event::MoveLeftWord, KBDK_LEFT, KBDM_CTRL},
{Event::MoveRightWord, KBDK_RIGHT, KBDM_CTRL},
{Event::MoveHome, KBDK_HOME},
{Event::MoveEnd, KBDK_END},
{Event::SelectLeftWord, KBDK_LEFT, KBDM_SHIFT | KBDM_CTRL},
{Event::SelectRightWord, KBDK_RIGHT, KBDM_SHIFT | KBDM_CTRL},
{Event::SelectHome, KBDK_HOME, KBDM_SHIFT},
{Event::SelectEnd, KBDK_END, KBDM_SHIFT},
{Event::SelectAll, KBDK_A, KBDM_CTRL},
{Event::Delete, KBDK_DELETE},
{Event::Delete, KBDK_KP_PERIOD},
{Event::DeleteChar, KBDK_D, KBDM_CTRL},
{Event::DeleteWord, KBDK_W, KBDM_CTRL},
{Event::DeleteHome, KBDK_U, KBDM_CTRL},
{Event::DeleteEnd, KBDK_K, KBDM_CTRL},
{Event::Backspace, KBDK_BACKSPACE},
{Event::Undo, KBDK_Z, KBDM_CTRL},
{Event::Redo, KBDK_Y, KBDM_CTRL},
{Event::Redo, KBDK_Z, KBDM_SHIFT | KBDM_CTRL},
{Event::Cut, KBDK_X, KBDM_CTRL},
{Event::Cut, KBDK_DELETE, KBDM_SHIFT},
{Event::Cut, KBDK_KP_PERIOD, KBDM_SHIFT},
{Event::Copy, KBDK_C, KBDM_CTRL},
{Event::Copy, KBDK_INSERT, KBDM_CTRL},
{Event::Paste, KBDK_V, KBDM_CTRL},
{Event::Paste, KBDK_INSERT, KBDM_SHIFT},
#endif
{Event::EndEdit, KBDK_RETURN},
{Event::EndEdit, KBDK_KP_ENTER},
{Event::AbortEdit, KBDK_ESCAPE},
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultJoystickMapping = {
{Event::JoystickZeroUp, KBDK_UP},
{Event::JoystickZeroDown, KBDK_DOWN},
{Event::JoystickZeroLeft, KBDK_LEFT},
{Event::JoystickZeroRight, KBDK_RIGHT},
{Event::JoystickZeroUp, KBDK_KP_8},
{Event::JoystickZeroDown, KBDK_KP_2},
{Event::JoystickZeroLeft, KBDK_KP_4},
{Event::JoystickZeroRight, KBDK_KP_6},
{Event::JoystickZeroFire, KBDK_SPACE},
{Event::JoystickZeroFire, KBDK_LCTRL},
{Event::JoystickZeroFire, KBDK_KP_5},
{Event::JoystickZeroFire5, KBDK_4},
{Event::JoystickZeroFire5, KBDK_RSHIFT},
{Event::JoystickZeroFire5, KBDK_KP_9},
{Event::JoystickZeroFire9, KBDK_5},
{Event::JoystickZeroFire9, KBDK_RCTRL},
{Event::JoystickZeroFire9, KBDK_KP_3},
{Event::JoystickOneUp, KBDK_Y},
{Event::JoystickOneDown, KBDK_H},
{Event::JoystickOneLeft, KBDK_G},
{Event::JoystickOneRight, KBDK_J},
{Event::JoystickOneFire, KBDK_F},
{Event::JoystickOneFire5, KBDK_6},
{Event::JoystickOneFire9, KBDK_7},
{Event::JoystickTwoUp, KBDK_UP, KBDM_SHIFT},
{Event::JoystickTwoDown, KBDK_DOWN, KBDM_SHIFT},
{Event::JoystickTwoLeft, KBDK_LEFT, KBDM_SHIFT},
{Event::JoystickTwoRight, KBDK_RIGHT, KBDM_SHIFT},
{Event::JoystickTwoUp, KBDK_KP_8, KBDM_SHIFT},
{Event::JoystickTwoDown, KBDK_KP_2, KBDM_SHIFT},
{Event::JoystickTwoLeft, KBDK_KP_4, KBDM_SHIFT},
{Event::JoystickTwoRight, KBDK_KP_6, KBDM_SHIFT},
{Event::JoystickTwoFire, KBDK_SPACE, KBDM_SHIFT},
{Event::JoystickThreeUp, KBDK_Y, KBDM_SHIFT},
{Event::JoystickThreeDown, KBDK_H, KBDM_SHIFT},
{Event::JoystickThreeLeft, KBDK_G, KBDM_SHIFT},
{Event::JoystickThreeRight, KBDK_J, KBDM_SHIFT},
{Event::JoystickThreeFire, KBDK_F, KBDM_SHIFT},
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultPaddleMapping = {
{Event::PaddleZeroDecrease, KBDK_RIGHT},
{Event::PaddleZeroIncrease, KBDK_LEFT},
{Event::PaddleZeroFire, KBDK_SPACE},
{Event::PaddleZeroFire, KBDK_LCTRL},
{Event::PaddleZeroFire, KBDK_KP_5},
{Event::PaddleOneDecrease, KBDK_DOWN},
{Event::PaddleOneIncrease, KBDK_UP},
{Event::PaddleOneFire, KBDK_4},
{Event::PaddleOneFire, KBDK_RCTRL},
{Event::PaddleTwoDecrease, KBDK_J},
{Event::PaddleTwoIncrease, KBDK_G},
{Event::PaddleTwoFire, KBDK_F},
{Event::PaddleThreeDecrease, KBDK_H},
{Event::PaddleThreeIncrease, KBDK_Y},
{Event::PaddleThreeFire, KBDK_6},
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultKeypadMapping = {
{Event::KeyboardZero1, KBDK_1},
{Event::KeyboardZero2, KBDK_2},
{Event::KeyboardZero3, KBDK_3},
{Event::KeyboardZero4, KBDK_Q},
{Event::KeyboardZero5, KBDK_W},
{Event::KeyboardZero6, KBDK_E},
{Event::KeyboardZero7, KBDK_A},
{Event::KeyboardZero8, KBDK_S},
{Event::KeyboardZero9, KBDK_D},
{Event::KeyboardZeroStar, KBDK_Z},
{Event::KeyboardZero0, KBDK_X},
{Event::KeyboardZeroPound, KBDK_C},
{Event::KeyboardOne1, KBDK_8},
{Event::KeyboardOne2, KBDK_9},
{Event::KeyboardOne3, KBDK_0},
{Event::KeyboardOne4, KBDK_I},
{Event::KeyboardOne5, KBDK_O},
{Event::KeyboardOne6, KBDK_P},
{Event::KeyboardOne7, KBDK_K},
{Event::KeyboardOne8, KBDK_L},
{Event::KeyboardOne9, KBDK_SEMICOLON},
{Event::KeyboardOneStar, KBDK_COMMA},
{Event::KeyboardOne0, KBDK_PERIOD},
{Event::KeyboardOnePound, KBDK_SLASH},
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::CompuMateMapping = {
{Event::CompuMateShift, KBDK_LSHIFT},
{Event::CompuMateShift, KBDK_RSHIFT},
{Event::CompuMateFunc, KBDK_LCTRL},
{Event::CompuMateFunc, KBDK_RCTRL},
{Event::CompuMate0, KBDK_0},
{Event::CompuMate1, KBDK_1},
{Event::CompuMate2, KBDK_2},
{Event::CompuMate3, KBDK_3},
{Event::CompuMate4, KBDK_4},
{Event::CompuMate5, KBDK_5},
{Event::CompuMate6, KBDK_6},
{Event::CompuMate7, KBDK_7},
{Event::CompuMate8, KBDK_8},
{Event::CompuMate9, KBDK_9},
{Event::CompuMateA, KBDK_A},
{Event::CompuMateB, KBDK_B},
{Event::CompuMateC, KBDK_C},
{Event::CompuMateD, KBDK_D},
{Event::CompuMateE, KBDK_E},
{Event::CompuMateF, KBDK_F},
{Event::CompuMateG, KBDK_G},
{Event::CompuMateH, KBDK_H},
{Event::CompuMateI, KBDK_I},
{Event::CompuMateJ, KBDK_J},
{Event::CompuMateK, KBDK_K},
{Event::CompuMateL, KBDK_L},
{Event::CompuMateM, KBDK_M},
{Event::CompuMateN, KBDK_N},
{Event::CompuMateO, KBDK_O},
{Event::CompuMateP, KBDK_P},
{Event::CompuMateQ, KBDK_Q},
{Event::CompuMateR, KBDK_R},
{Event::CompuMateS, KBDK_S},
{Event::CompuMateT, KBDK_T},
{Event::CompuMateU, KBDK_U},
{Event::CompuMateV, KBDK_V},
{Event::CompuMateW, KBDK_W},
{Event::CompuMateX, KBDK_X},
{Event::CompuMateY, KBDK_Y},
{Event::CompuMateZ, KBDK_Z},
{Event::CompuMateComma, KBDK_COMMA},
{Event::CompuMatePeriod, KBDK_PERIOD},
{Event::CompuMateEnter, KBDK_RETURN},
{Event::CompuMateEnter, KBDK_KP_ENTER},
{Event::CompuMateSpace, KBDK_SPACE},
// extra emulated keys
{Event::CompuMateQuestion, KBDK_SLASH, KBDM_SHIFT},
{Event::CompuMateLeftBracket, KBDK_LEFTBRACKET},
{Event::CompuMateRightBracket, KBDK_RIGHTBRACKET},
{Event::CompuMateMinus, KBDK_MINUS},
{Event::CompuMateQuote, KBDK_APOSTROPHE, KBDM_SHIFT},
{Event::CompuMateBackspace, KBDK_BACKSPACE, KBDM_SHIFT},
{Event::CompuMateEquals, KBDK_EQUALS},
{Event::CompuMatePlus, KBDK_EQUALS, KBDM_SHIFT},
{Event::CompuMateSlash, KBDK_SLASH}
};