17 using std::shared_ptr;
31 #ifdef SDL_JOYSTICK_DISABLED
32 (void)eventDistributor;
33 (void)stateChangeDistributor;
36 for (
auto i :
xrange(SDL_NumJoysticks())) {
37 if (SDL_Joystick* joystick = SDL_JoystickOpen(i)) {
46 std::make_unique<JoyMega>(
48 stateChangeDistributor,
61 unsigned press_,
unsigned release_)
63 , joyNum(joyNum_), press(press_), release(release_)
65 assert((press != 0) || (release != 0));
66 assert((press & release) == 0);
69 [[nodiscard]]
unsigned getPress()
const {
return press; }
70 [[nodiscard]]
unsigned getRelease()
const {
return release; }
72 template<
typename Archive>
void serialize(Archive& ar,
unsigned )
74 ar.template serializeBase<StateChange>(*
this);
75 ar.serialize(
"joyNum", joyNum,
81 unsigned press, release;
85 #ifndef SDL_JOYSTICK_DISABLED
92 SDL_Joystick* joystick_)
93 : eventDistributor(eventDistributor_)
94 , stateChangeDistributor(stateChangeDistributor_)
96 , joyNum(SDL_JoystickInstanceID(joystick_))
98 , desc(string(SDL_JoystickName(joystick_)))
99 , lastTime(EmuTime::zero())
101 const_cast<string&
>(name)[7] =
char(
'1' + joyNum);
109 SDL_JoystickClose(joystick);
126 status = calcInitialState();
130 cycleMask = (status & 0x800) ? 7 : 1;
133 void JoyMega::plugHelper2()
154 case 0:
case 2:
case 4:
156 return (status & 0x00f) | ((status & 0x060) >> 1);
159 return (status & 0x013) | ((status & 0x080) >> 2);
162 return (status & 0x010) | ((status & 0x080) >> 2);
165 return ((status & 0x400) >> 10) |
166 ((status & 0xA00) >> 8) |
167 ((status & 0x100) >> 6) |
168 ((status & 0x060) >> 1);
171 return (status & 0x010) | ((status & 0x080) >> 2) | 0x0f;
181 if (((value >> 2) & 1) != (cycle & 1)) {
182 cycle = (cycle + 1) & cycleMask;
184 assert(((value >> 2) & 1) == (cycle & 1));
187 void JoyMega::checkTime(EmuTime::param time)
195 static unsigned encodeButton(
unsigned button,
byte cycleMask)
197 unsigned n = (cycleMask == 7) ? 7 : 3;
198 return 1 << (4 + (button & n));
201 unsigned JoyMega::calcInitialState()
203 unsigned result = 0xfff;
204 int xAxis = SDL_JoystickGetAxis(joystick, 0);
211 int yAxis = SDL_JoystickGetAxis(joystick, 1);
220 result &= ~encodeButton(button, 7);
227 void JoyMega::signalMSXEvent(
const shared_ptr<const Event>& event, EmuTime::param time)
229 const auto* joyEvent =
dynamic_cast<const JoystickEvent*
>(
event.get());
230 if (!joyEvent)
return;
234 if (joyEvent->getJoystick() != joyNum)
return;
236 switch (event->getType()) {
238 const auto& mev = checked_cast<const JoystickAxisMotionEvent&>(*event);
239 int value = mev.getValue();
240 switch (mev.getAxis() & 1) {
272 const auto& butEv = checked_cast<const JoystickButtonEvent&>(*event);
273 createEvent(time, encodeButton(butEv.getButton(), cycleMask), 0);
277 const auto& butEv = checked_cast<const JoystickButtonEvent&>(*event);
278 createEvent(time, 0, encodeButton(butEv.getButton(), cycleMask));
286 void JoyMega::createEvent(EmuTime::param time,
unsigned press,
unsigned release)
288 unsigned newStatus = (status & ~press) | release;
289 createEvent(time, newStatus);
292 void JoyMega::createEvent(EmuTime::param time,
unsigned newStatus)
294 unsigned diff = status ^ newStatus;
300 unsigned press = status & diff;
301 unsigned release = newStatus & diff;
302 stateChangeDistributor.
distributeNew(std::make_shared<JoyMegaState>(
303 time, joyNum, press, release));
307 void JoyMega::signalStateChange(
const shared_ptr<StateChange>& event)
309 const auto* js =
dynamic_cast<const JoyMegaState*
>(
event.get());
317 if (js->getJoystick() != joyNum)
return;
319 status = (status & ~js->getPress()) | js->getRelease();
322 void JoyMega::stopReplay(EmuTime::param time)
324 createEvent(time, calcInitialState());
327 template<
typename Archive>
330 ar.serialize(
"lastTime", lastTime,
333 "cycleMask", cycleMask);
343 #endif // SDL_JOYSTICK_DISABLED