1
/* Mednafen - Multi-system Emulator
3
* This program is free software; you can redistribute it and/or modify
4
* it under the terms of the GNU General Public License as published by
5
* the Free Software Foundation; either version 2 of the License, or
6
* (at your option) any later version.
8
* This program is distributed in the hope that it will be useful,
9
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
* GNU General Public License for more details.
13
* You should have received a copy of the GNU General Public License
14
* along with this program; if not, write to the Free Software
15
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
The joystick driver configuration priority system should be considered as last-resort protection for multiple-API platforms(such as DirectInput + XInput on Windows), in the
19
event that all reasonable attempts at preventing the same physical device from being opened via multiple APIs fail. (The configuration priority system generally should
20
work ok as long as the user isn't extremely unlucky, doesn't try to configure too quickly(or too slowly ;)), and the controller is well-behaved; but it is still
21
inherently race-conditiony).
26
#include "../math_ops.h"
31
#include "Joystick_SDL.h"
34
#ifdef HAVE_LINUX_JOYSTICK
35
#include "Joystick_Linux.h"
39
#include "Joystick_DX5.h"
40
#include "Joystick_XInput.h"
44
#include "Joystick_DOS_Standard.h"
45
//#include "Joystick_DOS_SideWinder.h"
48
Joystick::Joystick() : num_axes(0), num_rel_axes(0), num_buttons(0), id(0)
58
void Joystick::CalcOldStyleID(unsigned arg_num_axes, unsigned arg_num_balls, unsigned arg_num_hats, unsigned arg_num_buttons)
65
//printf("%u %u %u %u\n", arg_num_axes, arg_num_balls, arg_num_hats, arg_num_buttons);
67
tohash[0] = arg_num_axes;
68
tohash[1] = arg_num_balls;
69
tohash[2] = arg_num_hats;
70
tohash[3] = arg_num_buttons;
73
hashie.update((uint8 *)tohash, sizeof(tohash));
74
hashie.finish(digest);
76
for(int x = 0; x < 16; x++)
78
ret ^= (uint64)digest[x] << ((x & 7) * 8);
84
void Joystick::SetRumble(uint8 weak_intensity, uint8 strong_intensity)
90
bool Joystick::IsAxisButton(unsigned axis)
95
unsigned Joystick::HatToAxisCompat(unsigned hat)
100
unsigned Joystick::HatToButtonCompat(unsigned hat)
105
JoystickDriver::JoystickDriver()
110
JoystickDriver::~JoystickDriver()
115
unsigned JoystickDriver::NumJoysticks()
120
Joystick *JoystickDriver::GetJoystick(unsigned index)
125
void JoystickDriver::UpdateJoysticks(void)
130
JoystickManager::JoystickManager()
132
JoystickDriver *main_driver = NULL;
133
JoystickDriver *hicp_driver = NULL;
135
MDFNI_printf(_("Initializing joysticks...\n"));
140
#ifdef HAVE_LINUX_JOYSTICK
141
main_driver = JoystickDriver_Linux_New();
144
hicp_driver = JoystickDriver_XInput_New();
145
main_driver = JoystickDriver_DX5_New(hicp_driver != NULL && hicp_driver->NumJoysticks() > 0);
147
#elif defined(HAVE_SDL)
148
main_driver = JoystickDriver_SDL_New();
151
if(hicp_driver != NULL)
153
JoystickDrivers.push_back(hicp_driver);
156
if(main_driver != NULL)
158
JoystickDrivers.push_back(main_driver);
161
for(unsigned jd = 0; jd < JoystickDrivers.size(); jd++)
163
for(unsigned i = 0; i < JoystickDrivers[jd]->NumJoysticks(); i++)
165
JoystickManager_Cache ce;
167
ce.joystick = JoystickDrivers[jd]->GetJoystick(i);
168
ce.UniqueID = ce.joystick->ID();
169
ce.config_prio = (JoystickDrivers[jd] == hicp_driver) ? 1 : 0;
172
for(unsigned nji = 0; nji < JoystickCache.size(); nji++)
174
if(JoystickCache[nji].UniqueID == ce.UniqueID)
181
MDFN_printf(_("Joystick %u - %s - Unique ID: %016llx\n"), (unsigned)JoystickCache.size(), ce.joystick->Name(), (unsigned long long)ce.UniqueID);
183
ce.axis_config_type.resize(ce.joystick->NumAxes());
184
ce.prev_state_valid = false;
185
ce.prev_axis_state.resize(ce.joystick->NumAxes());
186
ce.axis_hysterical_ax_murderer.resize(ce.joystick->NumAxes());
187
ce.prev_button_state.resize(ce.joystick->NumButtons());
188
ce.rel_axis_accum_state.resize(ce.joystick->NumRelAxes());
190
JoystickCache.push_back(ce);
195
catch(std::exception &e)
197
MDFND_PrintError(e.what());
198
if(main_driver != NULL)
203
if(hicp_driver != NULL)
212
void JoystickManager::SetAnalogThreshold(double thresh)
214
AnalogThreshold = thresh * 32767;
217
JoystickManager::~JoystickManager()
219
for(unsigned i = 0; i < JoystickDrivers.size(); i++)
220
delete JoystickDrivers[i];
223
unsigned JoystickManager::DetectAnalogButtonsForChangeCheck(void)
227
for(unsigned i = 0; i < JoystickCache.size(); i++)
229
for(unsigned axis = 0; axis < JoystickCache[i].joystick->NumAxes(); axis++)
231
JoystickCache[i].axis_config_type[axis] = JoystickManager_Cache::AXIS_CONFIG_TYPE_GENERIC;
233
if(JoystickCache[i].joystick->IsAxisButton(axis))
237
int pos = JoystickCache[i].joystick->GetAxis(axis);
239
if(abs(pos) >= 31000)
242
JoystickCache[i].axis_config_type[axis] = JoystickManager_Cache::AXIS_CONFIG_TYPE_ANABUTTON_POSPRESS;
244
JoystickCache[i].axis_config_type[axis] = JoystickManager_Cache::AXIS_CONFIG_TYPE_ANABUTTON_NEGPRESS;
246
printf("SPOON -- joystick=%u, axis=%u, type=%u\n", i, axis, JoystickCache[i].axis_config_type[axis]);
255
void JoystickManager::Reset_BC_ChangeCheck(void)
257
for(unsigned i = 0; i < JoystickCache.size(); i++)
258
JoystickCache[i].prev_state_valid = false;
260
BCPending.ButtType = BUTTC_NONE;
265
bool JoystickManager::Do_BC_ChangeCheck(ButtConfig *bc) //, bool hint_analog)
267
if(BCPending.ButtType != BUTTC_NONE)
269
if((BCPending_Time + 150) <= MDFND_GetTime() && BCPending_CCCC >= 5) //(int32)(MDFND_GetTime() - BCPending_Time) >= 150)
272
BCPending.ButtType = BUTTC_NONE;
278
int SaveAT = AnalogThreshold; // Begin Kludge
279
AnalogThreshold = ((JoystickCache[BCPending.DeviceNum].config_prio > 0) ? 25000 : 26000);
280
if(!TestButton(BCPending))
282
BCPending.ButtType = BUTTC_NONE;
288
AnalogThreshold = SaveAT; // End Kludge.
291
for(unsigned i = 0; i < JoystickCache.size(); i++)
293
JoystickManager_Cache *const jsc = &JoystickCache[i];
294
Joystick *const js = jsc->joystick;
295
const int ana_low_thresh = ((jsc->config_prio > 0) ? 6000 : 5000);
296
const int ana_high_thresh = ((jsc->config_prio > 0) ? 25000 : 26000);
298
// Search buttons first, then axes?
299
for(unsigned button = 0; button < js->NumButtons(); button++)
301
bool button_state = js->GetButton(button);
303
if(jsc->prev_state_valid && (button_state != jsc->prev_button_state[button]) && button_state)
307
bctmp.ButtType = BUTTC_JOYSTICK;
309
bctmp.ButtonNum = button;
310
bctmp.DeviceID = jsc->UniqueID;
312
if(jsc->config_prio >= 0 && (jsc->config_prio > BCPending_Prio || 0)) // TODO: add axis/button priority logic(replace || 0) for gamepads that send axis and button events for analog button presses.
315
BCPending_Prio = jsc->config_prio;
316
BCPending_Time = MDFND_GetTime();
320
jsc->prev_button_state[button] = button_state;
323
for(unsigned axis = 0; axis < js->NumAxes(); axis++)
325
int16 axis_state = js->GetAxis(axis);
327
if(jsc->axis_config_type[axis] == JoystickManager_Cache::AXIS_CONFIG_TYPE_ANABUTTON_POSPRESS)
329
if(axis_state < -32767)
332
axis_state = (axis_state + 32767) >> 1;
333
//printf("%u: %u\n", axis, axis_state);
335
else if(jsc->axis_config_type[axis] == JoystickManager_Cache::AXIS_CONFIG_TYPE_ANABUTTON_NEGPRESS)
337
if(axis_state < -32767)
340
axis_state = -axis_state;
342
axis_state = (axis_state + 32767) >> 1;
343
//printf("%u: %u\n", axis, axis_state);
346
if(jsc->prev_state_valid)
348
if(jsc->axis_hysterical_ax_murderer[axis] && abs(axis_state) >= ana_high_thresh)
352
bctmp.ButtType = BUTTC_JOYSTICK;
355
if(jsc->axis_config_type[axis] == JoystickManager_Cache::AXIS_CONFIG_TYPE_ANABUTTON_POSPRESS)
356
bctmp.ButtonNum = (1 << 16) | axis;
357
else if(jsc->axis_config_type[axis] == JoystickManager_Cache::AXIS_CONFIG_TYPE_ANABUTTON_NEGPRESS)
358
bctmp.ButtonNum = (1 << 16) | (1 << 17) | axis;
360
bctmp.ButtonNum = 0x8000 | axis | ((axis_state < 0) ? 0x4000 : 0);
362
bctmp.DeviceID = jsc->UniqueID;
364
if(jsc->config_prio >= 0 && (jsc->config_prio > BCPending_Prio || 0)) // TODO: add axis/button priority logic(replace || 0) for gamepads that send axis and button events for analog button presses.
367
BCPending_Prio = jsc->config_prio;
368
BCPending_Time = MDFND_GetTime();
372
else if(!jsc->axis_hysterical_ax_murderer[axis] && abs(axis_state) < ana_low_thresh)
374
jsc->axis_hysterical_ax_murderer[axis] = 1;
379
if(abs(axis_state) >= ana_low_thresh)
380
jsc->axis_hysterical_ax_murderer[axis] = 0;
382
jsc->axis_hysterical_ax_murderer[axis] = 1;
385
jsc->prev_axis_state[axis] = axis_state;
389
jsc->prev_state_valid = true;
395
void JoystickManager::SetRumble(const std::vector<ButtConfig> &bc, uint8 weak_intensity, uint8 strong_intensity)
397
for(unsigned i = 0; i < bc.size(); i++)
399
if(bc[i].ButtType != BUTTC_JOYSTICK)
402
if(bc[i].DeviceNum >= JoystickCache.size())
405
Joystick *joy = JoystickCache[bc[i].DeviceNum].joystick;
406
joy->SetRumble(weak_intensity, strong_intensity);
410
void JoystickManager::TestRumble(void)
413
//uint32 cur_time = MDFND_GetTime();
417
for(unsigned i = 0; i < JoystickCache.size(); i++)
419
Joystick *joy = JoystickCache[i].joystick;
420
joy->SetRumble(weak, strong);
424
void JoystickManager::UpdateJoysticks(void)
427
for(unsigned i = 0; i < JoystickDrivers.size(); i++)
429
JoystickDrivers[i]->UpdateJoysticks();
433
bool JoystickManager::TestButton(const ButtConfig &bc)
435
if(bc.DeviceNum >= JoystickCache.size())
438
//printf("%u\n", AnalogThreshold);
440
Joystick *joy = JoystickCache[bc.DeviceNum].joystick;
442
if(bc.ButtonNum & (0x8000 | 0x2000)) /* Axis "button" (| 0x2000 for backwards-compat hat translation)*/
444
bool neg_req = (bool)(bc.ButtonNum & 0x4000);
445
unsigned axis = bc.ButtonNum & 0x3FFF;
448
if(bc.ButtonNum & 0x2000)
450
axis = joy->HatToAxisCompat((bc.ButtonNum >> 8) & 0x1F);
451
if(axis == ~0U) // Not-implemented case. See if implemented for buttons.
453
unsigned button = joy->HatToButtonCompat((bc.ButtonNum >> 8) & 0x1F);
457
button += uilog2(bc.ButtonNum & 0xF);
459
if(button >= joy->NumButtons())
462
return joy->GetButton(button);
467
if(bc.ButtonNum & 0x05)
470
neg_req = bc.ButtonNum & 0x09;
473
if(axis >= joy->NumAxes())
476
pos = joy->GetAxis(axis);
478
if(neg_req && (pos <= -AnalogThreshold))
480
else if(!neg_req && (pos >= AnalogThreshold))
483
else if(bc.ButtonNum & (1 << 16)) // Analog button axis.
485
unsigned axis = bc.ButtonNum & 0x3FFF;
488
if(axis >= joy->NumAxes())
491
pos = joy->GetAxis(axis);
495
if(bc.ButtonNum & (1 << 17))
501
if(pos >= AnalogThreshold)
506
unsigned button = bc.ButtonNum;
508
if(button >= joy->NumButtons())
511
return joy->GetButton(button);
517
int JoystickManager::TestAnalogButton(const ButtConfig &bc)
519
if(bc.DeviceNum >= JoystickCache.size())
522
Joystick *joy = JoystickCache[bc.DeviceNum].joystick;
524
if(bc.ButtonNum & 0x8000) /* Axis "button" */
526
unsigned axis = bc.ButtonNum & 0x3FFF;
529
if(axis >= joy->NumAxes())
531
pos = joy->GetAxis(axis);
533
if((bc.ButtonNum & 0x4000) && pos < 0)
534
return(std::min<int>(-pos, 32767));
535
else if (!(bc.ButtonNum & 0x4000) && pos > 0)
538
else if(bc.ButtonNum & (1 << 16)) // Analog button axis.
540
unsigned axis = bc.ButtonNum & 0x3FFF;
543
if(axis >= joy->NumAxes())
546
pos = joy->GetAxis(axis);
550
if(bc.ButtonNum & (1 << 17))
560
return(TestButton(bc) ? 32767 : 0);
566
unsigned JoystickManager::GetIndexByUniqueID(uint64 unique_id)
568
for(unsigned i = 0; i < JoystickCache.size(); i++)
570
if(JoystickCache[i].UniqueID == unique_id)
572
//printf("%16llx %u\n", unique_id, i);
580
unsigned JoystickManager::GetUniqueIDByIndex(unsigned index)
582
return JoystickCache[index].UniqueID;