openMSX
KeyJoystick.cc
Go to the documentation of this file.
1 #include "KeyJoystick.hh"
2 #include "MSXEventDistributor.hh"
4 #include "InputEvents.hh"
5 #include "StateChange.hh"
6 #include "checked_cast.hh"
7 #include "serialize.hh"
8 #include "serialize_meta.hh"
9 
10 using std::string;
11 using std::shared_ptr;
12 
13 namespace openmsx {
14 
15 class KeyJoyState final : public StateChange
16 {
17 public:
18  KeyJoyState() = default; // for serialize
19  KeyJoyState(EmuTime::param time_, string name_,
20  byte press_, byte release_)
21  : StateChange(time_)
22  , name(std::move(name_)), press(press_), release(release_) {}
23  const string& getName() const { return name; }
24  byte getPress() const { return press; }
25  byte getRelease() const { return release; }
26  template<typename Archive> void serialize(Archive& ar, unsigned /*version*/)
27  {
28  ar.template serializeBase<StateChange>(*this);
29  ar.serialize("name", name,
30  "press", press,
31  "release", release);
32  }
33 
34 private:
35  string name;
36  byte press, release;
37 };
38 REGISTER_POLYMORPHIC_CLASS(StateChange, KeyJoyState, "KeyJoyState");
39 
41  MSXEventDistributor& eventDistributor_,
42  StateChangeDistributor& stateChangeDistributor_,
43  std::string name_)
44  : eventDistributor(eventDistributor_)
45  , stateChangeDistributor(stateChangeDistributor_)
46  , name(std::move(name_))
47  , up (commandController, name + ".up",
48  "key for direction up", Keys::K_UP)
49  , down (commandController, name + ".down",
50  "key for direction down", Keys::K_DOWN)
51  , left (commandController, name + ".left",
52  "key for direction left", Keys::K_LEFT)
53  , right(commandController, name + ".right",
54  "key for direction right", Keys::K_RIGHT)
55  , trigA(commandController, name + ".triga",
56  "key for trigger A", Keys::K_SPACE)
57  , trigB(commandController, name + ".trigb",
58  "key for trigger B", Keys::K_M)
59 {
60  status = JOY_UP | JOY_DOWN | JOY_LEFT | JOY_RIGHT |
62 }
63 
65 {
66  if (isPluggedIn()) {
67  KeyJoystick::unplugHelper(EmuTime::dummy());
68  }
69 }
70 
71 
72 // Pluggable
73 const string& KeyJoystick::getName() const
74 {
75  return name;
76 }
77 
78 std::string_view KeyJoystick::getDescription() const
79 {
80  return "Key-Joystick, use your keyboard to emulate an MSX joystick. "
81  "See manual for information on how to configure this.";
82 }
83 
84 void KeyJoystick::plugHelper(Connector& /*connector*/, EmuTime::param /*time*/)
85 {
86  eventDistributor.registerEventListener(*this);
87  stateChangeDistributor.registerListener(*this);
88 }
89 
90 void KeyJoystick::unplugHelper(EmuTime::param /*time*/)
91 {
92  stateChangeDistributor.unregisterListener(*this);
93  eventDistributor.unregisterEventListener(*this);
94 }
95 
96 
97 // KeyJoystickDevice
98 byte KeyJoystick::read(EmuTime::param /*time*/)
99 {
100  return pin8 ? 0x3F : status;
101 }
102 
103 void KeyJoystick::write(byte value, EmuTime::param /*time*/)
104 {
105  pin8 = (value & 0x04) != 0;
106 }
107 
108 
109 // MSXEventListener
110 void KeyJoystick::signalMSXEvent(const shared_ptr<const Event>& event,
111  EmuTime::param time)
112 {
113  byte press = 0;
114  byte release = 0;
115  switch (event->getType()) {
117  case OPENMSX_KEY_UP_EVENT: {
118  auto& keyEvent = checked_cast<const KeyEvent&>(*event);
119  auto key = static_cast<Keys::KeyCode>(
120  int(keyEvent.getKeyCode()) & int(Keys::K_MASK));
121  if (event->getType() == OPENMSX_KEY_DOWN_EVENT) {
122  if (key == up .getKey()) press = JOY_UP;
123  else if (key == down .getKey()) press = JOY_DOWN;
124  else if (key == left .getKey()) press = JOY_LEFT;
125  else if (key == right.getKey()) press = JOY_RIGHT;
126  else if (key == trigA.getKey()) press = JOY_BUTTONA;
127  else if (key == trigB.getKey()) press = JOY_BUTTONB;
128  } else {
129  if (key == up .getKey()) release = JOY_UP;
130  else if (key == down .getKey()) release = JOY_DOWN;
131  else if (key == left .getKey()) release = JOY_LEFT;
132  else if (key == right.getKey()) release = JOY_RIGHT;
133  else if (key == trigA.getKey()) release = JOY_BUTTONA;
134  else if (key == trigB.getKey()) release = JOY_BUTTONB;
135  }
136  break;
137  }
138  default:
139  // ignore
140  break;
141  }
142 
143  if (((status & ~press) | release) != status) {
144  stateChangeDistributor.distributeNew(std::make_shared<KeyJoyState>(
145  time, name, press, release));
146  }
147 }
148 
149 // StateChangeListener
150 void KeyJoystick::signalStateChange(const shared_ptr<StateChange>& event)
151 {
152  auto kjs = dynamic_cast<const KeyJoyState*>(event.get());
153  if (!kjs) return;
154  if (kjs->getName() != name) return;
155 
156  status = (status & ~kjs->getPress()) | kjs->getRelease();
157 }
158 
159 void KeyJoystick::stopReplay(EmuTime::param time)
160 {
161  // TODO read actual host key state
162  byte newStatus = JOY_UP | JOY_DOWN | JOY_LEFT | JOY_RIGHT |
164  if (newStatus != status) {
165  byte release = newStatus & ~status;
166  stateChangeDistributor.distributeNew(std::make_shared<KeyJoyState>(
167  time, name, 0, release));
168  }
169 }
170 
171 
172 // version 1: Initial version, the variable status was not serialized.
173 // version 2: Also serialize the above variable, this is required for
174 // record/replay, see comment in Keyboard.cc for more details.
175 template<typename Archive>
176 void KeyJoystick::serialize(Archive& ar, unsigned version)
177 {
178  if (ar.versionAtLeast(version, 2)) {
179  ar.serialize("status", status);
180  }
181  if (ar.isLoader() && isPluggedIn()) {
182  plugHelper(*getConnector(), EmuTime::dummy());
183  }
184  // no need to serialize 'pin8'
185 }
188 
189 } // namespace openmsx
openmsx::KeyJoyState::KeyJoyState
KeyJoyState()=default
openmsx::KeyJoyState::getPress
byte getPress() const
Definition: KeyJoystick.cc:24
openmsx::CommandController
Definition: CommandController.hh:17
serialize.hh
MSXEventDistributor.hh
openmsx::MSXEventDistributor
Definition: MSXEventDistributor.hh:13
openmsx::KeyJoyState
Definition: KeyJoystick.cc:15
openmsx::StateChange
Base class for all external MSX state changing events.
Definition: StateChange.hh:13
openmsx::StateChangeDistributor::registerListener
void registerListener(StateChangeListener &listener)
(Un)registers the given object to receive state change events.
Definition: StateChangeDistributor.cc:19
serialize_meta.hh
openmsx::StateChangeDistributor::distributeNew
void distributeNew(const EventPtr &event)
Deliver the event to all registered listeners MSX input devices should call the distributeNew() versi...
Definition: StateChangeDistributor.cc:43
openmsx::KeyJoyState::KeyJoyState
KeyJoyState(EmuTime::param time_, string name_, byte press_, byte release_)
Definition: KeyJoystick.cc:19
openmsx::KeyJoystick::KeyJoystick
KeyJoystick(CommandController &commandController, MSXEventDistributor &eventDistributor, StateChangeDistributor &stateChangeDistributor, std::string name)
Definition: KeyJoystick.cc:40
openmsx::StateChangeDistributor
Definition: StateChangeDistributor.hh:14
openmsx::JoystickDevice::JOY_DOWN
static constexpr int JOY_DOWN
Definition: JoystickDevice.hh:40
openmsx::Keys::K_RIGHT
@ K_RIGHT
Definition: Keys.hh:126
openmsx::KeyJoyState::getRelease
byte getRelease() const
Definition: KeyJoystick.cc:25
openmsx::OPENMSX_KEY_DOWN_EVENT
@ OPENMSX_KEY_DOWN_EVENT
Definition: Event.hh:13
openmsx::Pluggable
Definition: Pluggable.hh:11
StateChangeDistributor.hh
openmsx::Pluggable::getConnector
Connector * getConnector() const
Get the connector this Pluggable is plugged into.
Definition: Pluggable.hh:43
openmsx::Keys::K_SPACE
@ K_SPACE
Definition: Keys.hh:37
openmsx::JoystickDevice::JOY_LEFT
static constexpr int JOY_LEFT
Definition: JoystickDevice.hh:41
openmsx::KeyCodeSetting::getKey
Keys::KeyCode getKey() const noexcept
Definition: KeyCodeSetting.cc:26
openmsx::Keys::K_DOWN
@ K_DOWN
Definition: Keys.hh:125
openmsx::KeyJoystick
Definition: KeyJoystick.hh:16
openmsx::KeyJoyState::getName
const string & getName() const
Definition: KeyJoystick.cc:23
InputEvents.hh
INSTANTIATE_SERIALIZE_METHODS
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
Definition: serialize.hh:981
openmsx::KeyJoystick::serialize
void serialize(Archive &ar, unsigned version)
Definition: KeyJoystick.cc:176
StateChange.hh
openmsx::KeyJoyState::serialize
void serialize(Archive &ar, unsigned)
Definition: KeyJoystick.cc:26
checked_cast.hh
openmsx::Keys::K_M
@ K_M
Definition: Keys.hh:88
openmsx::MSXEventDistributor::unregisterEventListener
void unregisterEventListener(MSXEventListener &listener)
Unregisters a previously registered event listener.
Definition: MSXEventDistributor.cc:24
openmsx::Keys::K_UP
@ K_UP
Definition: Keys.hh:124
openmsx::Keys::K_LEFT
@ K_LEFT
Definition: Keys.hh:127
openmsx::StateChangeDistributor::unregisterListener
void unregisterListener(StateChangeListener &listener)
Definition: StateChangeDistributor.cc:25
openmsx::JoystickDevice::JOY_BUTTONB
static constexpr int JOY_BUTTONB
Definition: JoystickDevice.hh:44
openmsx::JoystickDevice::JOY_BUTTONA
static constexpr int JOY_BUTTONA
Definition: JoystickDevice.hh:43
openmsx::REGISTER_POLYMORPHIC_CLASS
REGISTER_POLYMORPHIC_CLASS(DiskContainer, NowindRomDisk, "NowindRomDisk")
openmsx::Keys::KeyCode
KeyCode
Constants that identify keys and key modifiers.
Definition: Keys.hh:26
openmsx::OPENMSX_KEY_UP_EVENT
@ OPENMSX_KEY_UP_EVENT
Definition: Event.hh:12
openmsx::Pluggable::isPluggedIn
bool isPluggedIn() const
Returns true if this pluggable is currently plugged into a connector.
Definition: Pluggable.hh:49
KeyJoystick.hh
openmsx
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
openmsx::Keys::K_MASK
@ K_MASK
Definition: Keys.hh:27
openmsx::REGISTER_POLYMORPHIC_INITIALIZER
REGISTER_POLYMORPHIC_INITIALIZER(Pluggable, CassettePlayer, "CassettePlayer")
openmsx::JoystickDevice::JOY_UP
static constexpr int JOY_UP
Definition: JoystickDevice.hh:39
openmsx::KeyJoystick::~KeyJoystick
~KeyJoystick() override
Definition: KeyJoystick.cc:64
openmsx::MSXEventDistributor::registerEventListener
void registerEventListener(MSXEventListener &listener)
Registers a given object to receive certain events.
Definition: MSXEventDistributor.cc:18
openmsx::Connector
Connector
Definition: Connector.cc:83
openmsx::JoystickDevice::JOY_RIGHT
static constexpr int JOY_RIGHT
Definition: JoystickDevice.hh:42