diff --git a/plugins/onepad/CMakeLists.txt b/plugins/onepad/CMakeLists.txt index 68ffb82df2..b0c93908c7 100644 --- a/plugins/onepad/CMakeLists.txt +++ b/plugins/onepad/CMakeLists.txt @@ -13,18 +13,20 @@ set(onepadFinalFlags "") # onepad sources set(onepadSources controller.cpp - joystick.cpp + GamePad.cpp + SDL/joystick.cpp keyboard.cpp - KeyStatus.cpp + KeyStatus.cpp onepad.cpp) # onepad headers set(onepadHeaders bitwise.h controller.h - joystick.h + GamePad.h + SDL/joystick.h keyboard.h - KeyStatus.h + KeyStatus.h onepad.h) # onepad Linux sources @@ -49,10 +51,12 @@ if (SDL2_API) set(onepadFinalLibs ${SDL2_LIBRARIES} ) + add_definitions(-DSDL_BUILD) else() set(onepadFinalLibs ${SDL_LIBRARY} ) + add_definitions(-DSDL_BUILD) endif() set(onepadFinalLibs diff --git a/plugins/onepad/GamePad.cpp b/plugins/onepad/GamePad.cpp new file mode 100644 index 0000000000..a20c4cf5cb --- /dev/null +++ b/plugins/onepad/GamePad.cpp @@ -0,0 +1,42 @@ +#include "GamePad.h" +#ifdef SDL_BUILD +#include "SDL/joystick.h" +#endif + +vector s_vgamePad; +bool GamePadIdWithinBounds(int GamePadId) +{ + return ((GamePadId >= 0) && (GamePadId < (int)s_vgamePad.size())); +} + +/** + * Following static methods are just forwarders to their backend + * This is where link between agnostic and specific code is done + **/ + +/** + * Find every interesting devices and create right structure for them(depend on backend) + **/ +void GamePad::EnumerateGamePads(vector& vgamePad) +{ +#ifdef SDL_BUILD + JoystickInfo::EnumerateJoysticks(vgamePad); +#endif +} +void GamePad::UpdateReleaseState() +{ +#ifdef SDL_BUILD + JoystickInfo::UpdateReleaseState(); +#endif +} +/** + * Update state of every attached devices + **/ +void GamePad::UpdateGamePadState() +{ +#ifdef SDL_BUILD + SDL_JoystickUpdate(); // No need to make yet another function call for that +#endif +} + + diff --git a/plugins/onepad/GamePad.h b/plugins/onepad/GamePad.h new file mode 100644 index 0000000000..10e2dd9766 --- /dev/null +++ b/plugins/onepad/GamePad.h @@ -0,0 +1,139 @@ +#pragma once + +#include "onepad.h" +#include "controller.h" +#ifdef SDL_BUILD +#include +#define HAT_UP SDL_HAT_UP +#define HAT_DOWN SDL_HAT_DOWN +#define HAT_RIGHT SDL_HAT_RIGHT +#define HAT_LEFT SDL_HAT_LEFT +#endif + +class GamePad +{ + public: + GamePad() : devname(""), _id(-1), numbuttons(0), numaxes(0), numhats(0), + deadzone(1500), pad(-1) { + vbuttonstate.clear(); + vaxisstate.clear(); + vhatstate.clear(); + } + + virtual ~GamePad() + { + return; + } + + GamePad(const GamePad&); // copy constructor + GamePad& operator=(const GamePad&); // assignment + + /** + * Find every interesting devices and create right structure for them(depend on backend) + **/ + static void EnumerateGamePads(vector& vgamePad); + static void UpdateReleaseState(); + /** + * Update state of every attached devices + **/ + static void UpdateGamePadState(); + + /** + * Causes devices to rumble + * Rumble will differ according to type which is either 0(small motor) or 1(big motor) + **/ + virtual void Rumble(int type,int pad){return;} + + virtual bool Init(int id){return false;} // opens a handle and gets information + + /** + * Used for GUI checkbox to give feedback to the user + **/ + virtual void TestForce(){return;} + + virtual bool PollButtons(u32 &pkey){return false;} + virtual bool PollAxes(u32 &pkey){return false;} + virtual bool PollHats(u32 &pkey){return false;} + + virtual int GetHat(int key_to_axis) + { + return 0; + } + + virtual int GetButton(int key_to_button) + { + return 0; + } + + virtual const string& GetName() + { + return devname; + } + + virtual int GetNumButtons() + { + return numbuttons; + } + + virtual int GetNumAxes() + { + return numaxes; + } + + virtual int GetNumHats() + { + return numhats; + } + + virtual int GetDeadzone() + { + return deadzone; + } + + virtual void SaveState(){return;} + + virtual int GetButtonState(int i) + { + return vbuttonstate[i]; + } + + virtual int GetAxisState(int i) + { + return vaxisstate[i]; + } + + virtual int GetHatState(int i) + { + //PAD_LOG("Getting POV State of %d.\n", i); + return vhatstate[i]; + } + + virtual void SetButtonState(int i, int state) + { + vbuttonstate[i] = state; + } + + virtual void SetAxisState(int i, int value) + { + vaxisstate[i] = value; + } + + virtual void SetHatState(int i, int value) + { + //PAD_LOG("We should set %d to %d.\n", i, value); + vhatstate[i] = value; + } + + virtual int GetAxisFromKey(int pad, int index){return 0;} +// These fields need to be inherited by child classes + protected: + string devname; // pretty device name + int _id; + int numbuttons, numaxes, numhats; + int deadzone; + int pad; + vector vbuttonstate, vaxisstate, vhatstate; +}; + +extern vector s_vgamePad; +extern bool GamePadIdWithinBounds(int joyid); diff --git a/plugins/onepad/KeyStatus.cpp b/plugins/onepad/KeyStatus.cpp index 98d438a084..11c2f410d1 100644 --- a/plugins/onepad/KeyStatus.cpp +++ b/plugins/onepad/KeyStatus.cpp @@ -69,7 +69,7 @@ void KeyStatus::press(u32 pad, u32 index, s32 value) // Normal mode : expect value 0 -> 80 -> FF // Reverse mode: expect value FF -> 7F -> 0 u8 force = (value / 256); - if (analog_is_reversed(index)) analog_set(pad, index, 0x7F - force); + if (analog_is_reversed(pad,index)) analog_set(pad, index, 0x7F - force); else analog_set(pad, index, 0x80 + force); } } @@ -117,25 +117,25 @@ void KeyStatus::analog_set(u32 pad, u32 index, u8 value) } } -bool KeyStatus::analog_is_reversed(u32 index) +bool KeyStatus::analog_is_reversed(u32 pad, u32 index) { switch (index) { case PAD_L_RIGHT: case PAD_L_LEFT: - return ((conf->options & PADOPTION_REVERSELX) != 0); + return (conf->pad_options[pad].reverse_lx); case PAD_R_LEFT: case PAD_R_RIGHT: - return ((conf->options & PADOPTION_REVERSERX) != 0); + return (conf->pad_options[pad].reverse_rx); case PAD_L_UP: case PAD_L_DOWN: - return ((conf->options & PADOPTION_REVERSELY) != 0); + return (conf->pad_options[pad].reverse_ly); case PAD_R_DOWN: case PAD_R_UP: - return ((conf->options & PADOPTION_REVERSERY) != 0); + return (conf->pad_options[pad].reverse_ry); default: return false; } diff --git a/plugins/onepad/KeyStatus.h b/plugins/onepad/KeyStatus.h index 847f64bc19..98b912f928 100644 --- a/plugins/onepad/KeyStatus.h +++ b/plugins/onepad/KeyStatus.h @@ -49,7 +49,7 @@ class KeyStatus PADAnalog m_internal_analog_joy[2]; void analog_set(u32 pad, u32 index, u8 value); - bool analog_is_reversed(u32 index); + bool analog_is_reversed(u32 pad, u32 index); u8 analog_merge(u8 kbd, u8 joy); public: diff --git a/plugins/onepad/Linux/dialog.cpp b/plugins/onepad/Linux/dialog.cpp index e81caf3244..2a3e3f10d3 100644 --- a/plugins/onepad/Linux/dialog.cpp +++ b/plugins/onepad/Linux/dialog.cpp @@ -19,7 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ -#include "joystick.h" +#include "GamePad.h" #include "keyboard.h" #include "onepad.h" #include @@ -243,14 +243,14 @@ keys_tree *key_tree_manager; void populate_new_joysticks(GtkComboBoxText *box) { char str[255]; - JoystickInfo::EnumerateJoysticks(s_vjoysticks); + GamePad::EnumerateGamePads(s_vgamePad); gtk_combo_box_text_append_text(box, "Keyboard/mouse only"); - vector::iterator it = s_vjoysticks.begin(); + vector::iterator it = s_vgamePad.begin(); // Get everything in the vector vjoysticks. - while (it != s_vjoysticks.end()) + while (it != s_vgamePad.end()) { sprintf(str, "Keyboard/mouse and %s - but: %d, axes: %d, hats: %d", (*it)->GetName().c_str(), (*it)->GetNumButtons(), (*it)->GetNumAxes(), (*it)->GetNumHats()); @@ -262,7 +262,7 @@ void populate_new_joysticks(GtkComboBoxText *box) void set_current_joy() { u32 joyid = conf->get_joyid(current_pad); - if (JoystickIdWithinBounds(joyid)) + if (GamePadIdWithinBounds(joyid)) // 0 is special case for no gamepad. So you must increase of 1. gtk_combo_box_set_active(GTK_COMBO_BOX(joy_choose_cbox), joyid+1); else @@ -294,7 +294,7 @@ typedef struct mask = mask_value; gtk_fixed_put(GTK_FIXED(area), widget, x, y); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), mask & conf->options); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), mask & conf->packed_options); g_signal_connect(widget, "toggled", G_CALLBACK(on_toggle_option), this); } } dialog_checkbox; @@ -305,10 +305,10 @@ void config_key(int pad, int key) u32 key_pressed = 0; // I don't have any guarantee that not-yet-pressed state is egual to released state - JoystickInfo::UpdateReleaseState(); + GamePad::UpdateReleaseState(); while (!captured) { - vector::iterator itjoy; + vector::iterator itjoy; if (PollX11KeyboardMouseEvent(key_pressed)) { @@ -321,10 +321,10 @@ void config_key(int pad, int key) break; } - SDL_JoystickUpdate(); + GamePad::UpdateGamePadState(); - itjoy = s_vjoysticks.begin(); - while ((itjoy != s_vjoysticks.end()) && (!captured)) + itjoy = s_vgamePad.begin(); + while ((itjoy != s_vgamePad.end()) && (!captured)) { if ((*itjoy)->PollButtons(key_pressed)) { set_key(pad, key, key_pressed); @@ -393,9 +393,13 @@ void on_toggle_option(GtkToggleButton *togglebutton, gpointer user_data) dialog_checkbox *checkbox = (dialog_checkbox*)user_data; if (gtk_toggle_button_get_active(togglebutton)) - conf->options |= checkbox->mask; + { + conf->packed_options |= checkbox->mask; + if(checkbox->mask == PADOPTION_FORCEFEEDBACK && (conf->get_joyid(current_pad)< s_vgamePad.size())) + s_vgamePad[conf->get_joyid(current_pad)]->TestForce(); + } else - conf->options &= ~checkbox->mask; + conf->packed_options &= ~checkbox->mask; } void joy_changed(GtkComboBoxText *box, gpointer user_data) @@ -427,23 +431,6 @@ void pad_changed(GtkNotebook *notebook, void *notebook_page, int page, void *dat set_current_joy(); } -//void on_forcefeedback_toggled(GtkToggleButton *togglebutton, gpointer user_data) -//{ -// int mask = PADOPTION_REVERSELX << (16 * s_selectedpad); -// -// if (gtk_toggle_button_get_active(togglebutton)) -// { -// conf->options |= mask; -// -// u32 joyid = conf->get_joyid(current_pad); -// if (JoystickIdWithinBounds(joyid)) s_vjoysticks[joyid]->TestForce(); -// } -// else -// { -// conf->options &= ~mask; -// } -//} - struct button_positions { const char* label; diff --git a/plugins/onepad/Linux/ini.cpp b/plugins/onepad/Linux/ini.cpp index 0a0933edd9..c494b80c08 100644 --- a/plugins/onepad/Linux/ini.cpp +++ b/plugins/onepad/Linux/ini.cpp @@ -22,7 +22,7 @@ #include #include -#include "joystick.h" +#include "GamePad.h" #include "keyboard.h" #include "onepad.h" #include "linux.h" @@ -73,19 +73,19 @@ string KeyName(int pad, int key, int keysym) int axis = key_to_axis(pad, key); switch(key_to_hat_dir(pad, key)) { - case SDL_HAT_UP: + case HAT_UP: sprintf(&tmp[0], "JPOVU-%d", axis); break; - case SDL_HAT_RIGHT: + case HAT_RIGHT: sprintf(&tmp[0], "JPOVR-%d", axis); break; - case SDL_HAT_DOWN: + case HAT_DOWN: sprintf(&tmp[0], "JPOVD-%d", axis); break; - case SDL_HAT_LEFT: + case HAT_LEFT: sprintf(&tmp[0], "JPOVL-%d", axis); break; } @@ -129,10 +129,10 @@ void SaveConfig() } fprintf(f, "log = %d\n", conf->log); - fprintf(f, "options = %d\n", conf->options); - fprintf(f, "mouse_sensibility = %d\n", conf->sensibility); + fprintf(f, "options = %d\n", conf->packed_options); + fprintf(f, "mouse_sensibility = %d\n", conf->get_sensibility()); fprintf(f, "joy_pad_map = %d\n", conf->joyid_map); - fprintf(f, "ff_intensity = %d\n", conf->ff_intensity); + fprintf(f, "ff_intensity = %d\n", conf->get_ff_intensity()); for (int pad = 0; pad < 2; pad++) { @@ -174,13 +174,13 @@ void LoadConfig() if (fscanf(f, "log = %d\n", &value) == 0) goto error; conf->log = value; if (fscanf(f, "options = %d\n", &value) == 0) goto error; - conf->options = value; + conf->packed_options = value; if (fscanf(f, "mouse_sensibility = %d\n", &value) == 0) goto error; - conf->sensibility = value; + conf->set_sensibility(value); if (fscanf(f, "joy_pad_map = %d\n", &value) == 0) goto error; conf->joyid_map = value; if (fscanf(f, "ff_intensity = %d\n", &value) == 0) goto error; - conf->ff_intensity = value; + conf->set_ff_intensity(value); for (int pad = 0; pad < 2; pad++) { diff --git a/plugins/onepad/Linux/linux.cpp b/plugins/onepad/Linux/linux.cpp index 10e00b020b..086cc5cd95 100644 --- a/plugins/onepad/Linux/linux.cpp +++ b/plugins/onepad/Linux/linux.cpp @@ -19,7 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ -#include "joystick.h" +#include "GamePad.h" #include "onepad.h" #include "keyboard.h" @@ -74,34 +74,34 @@ void _PADclose() { SetAutoRepeat(true); - vector::iterator it = s_vjoysticks.begin(); + vector::iterator it = s_vgamePad.begin(); // Delete everything in the vector vjoysticks. - while (it != s_vjoysticks.end()) + while (it != s_vgamePad.end()) { delete *it; it ++; } - s_vjoysticks.clear(); + s_vgamePad.clear(); } void PollForJoystickInput(int cpad) { int joyid = conf->get_joyid(cpad); - if (!JoystickIdWithinBounds(joyid)) return; + if (!GamePadIdWithinBounds(joyid)) return; - SDL_JoystickUpdate(); + GamePad::UpdateGamePadState(); for (int i = 0; i < MAX_KEYS; i++) { - JoystickInfo* pjoy = s_vjoysticks[joyid]; + GamePad* gamePad = s_vgamePad[joyid]; switch (type_of_joykey(cpad, i)) { case PAD_JOYBUTTONS: { - int value = SDL_JoystickGetButton((pjoy)->GetJoy(), key_to_button(cpad, i)); + int value = gamePad->GetButton(key_to_button(cpad, i)); if (value) key_status->press(cpad, i); else @@ -111,7 +111,7 @@ void PollForJoystickInput(int cpad) } case PAD_HAT: { - int value = SDL_JoystickGetHat((pjoy)->GetJoy(), key_to_axis(cpad, i)); + int value = gamePad->GetHat(key_to_axis(cpad, i)); // key_to_hat_dir and SDL_JoystickGetHat are a 4 bits bitmap, one for each directions. Only 1 bit can be high for // key_to_hat_dir. SDL_JoystickGetHat handles diagonal too (2 bits) so you must check the intersection @@ -125,12 +125,12 @@ void PollForJoystickInput(int cpad) } case PAD_AXIS: { - int value = pjoy->GetAxisFromKey(cpad, i); + int value = gamePad->GetAxisFromKey(cpad, i); bool sign = key_to_axis_sign(cpad, i); bool full_axis = key_to_axis_type(cpad, i); if (IsAnalogKey(i)) { - if (abs(value) > pjoy->GetDeadzone()) + if (abs(value) > gamePad->GetDeadzone()) key_status->press(cpad, i, value); else key_status->release(cpad, i); @@ -138,15 +138,15 @@ void PollForJoystickInput(int cpad) } else { if (full_axis) { value += 0x8000; - if (value > pjoy->GetDeadzone()) + if (value > gamePad->GetDeadzone()) key_status->press(cpad, i, min(value/256 , 0xFF)); else key_status->release(cpad, i); } else { - if (sign && (-value > pjoy->GetDeadzone())) + if (sign && (-value > gamePad->GetDeadzone())) key_status->press(cpad, i, min(-value /128, 0xFF)); - else if (!sign && (value > pjoy->GetDeadzone())) + else if (!sign && (value > gamePad->GetDeadzone())) key_status->press(cpad, i, min(value /128, 0xFF)); else key_status->release(cpad, i); diff --git a/plugins/onepad/joystick.cpp b/plugins/onepad/SDL/joystick.cpp similarity index 64% rename from plugins/onepad/joystick.cpp rename to plugins/onepad/SDL/joystick.cpp index 94884fdcbf..7d2acfdb6f 100644 --- a/plugins/onepad/joystick.cpp +++ b/plugins/onepad/SDL/joystick.cpp @@ -25,30 +25,24 @@ // Joystick definitions // ////////////////////////// -vector s_vjoysticks; static u32 s_bSDLInit = false; void JoystickInfo::UpdateReleaseState() { - vector::iterator itjoy = s_vjoysticks.begin(); + vector::iterator itjoy = s_vgamePad.begin(); SDL_JoystickUpdate(); // Save everything in the vector s_vjoysticks. - while (itjoy != s_vjoysticks.end()) + while (itjoy != s_vgamePad.end()) { (*itjoy)->SaveState(); itjoy++; } } -bool JoystickIdWithinBounds(int joyid) -{ - return ((joyid >= 0) && (joyid < (int)s_vjoysticks.size())); -} - // opens handles to all possible joysticks -void JoystickInfo::EnumerateJoysticks(vector& vjoysticks) +void JoystickInfo::EnumerateJoysticks(vector& vjoysticks) { if (!s_bSDLInit) @@ -56,10 +50,7 @@ void JoystickInfo::EnumerateJoysticks(vector& vjoysticks) #if SDL_MAJOR_VERSION >= 2 // Tell SDL to catch event even if the windows isn't focussed SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1"); - // SDL in 3rdparty wrap X11 call. In order to get x11 symbols loaded - // video must be loaded too. - // Example of X11 symbol are XAutoRepeatOn/XAutoRepeatOff - if (SDL_Init(SDL_INIT_JOYSTICK|SDL_INIT_VIDEO|SDL_INIT_HAPTIC|SDL_INIT_GAMECONTROLLER|SDL_INIT_EVENTS) < 0) return; + if (SDL_Init(SDL_INIT_JOYSTICK|SDL_INIT_HAPTIC|SDL_INIT_EVENTS) < 0) return; #else if (SDL_Init(SDL_INIT_JOYSTICK) < 0) return; #endif @@ -67,7 +58,7 @@ void JoystickInfo::EnumerateJoysticks(vector& vjoysticks) s_bSDLInit = true; } - vector::iterator it = vjoysticks.begin(); + vector::iterator it = vjoysticks.begin(); // Delete everything in the vector vjoysticks. while (it != vjoysticks.end()) @@ -85,84 +76,68 @@ void JoystickInfo::EnumerateJoysticks(vector& vjoysticks) } } -void JoystickInfo::InitHapticEffect() +void JoystickInfo::GenerateDefaultEffect() { + for(int i=0;iget_ff_intensity()); // Effect at maximum instensity + effect.periodic.offset = 0; + effect.periodic.phase = 18000; + effect.periodic.length = 125; // 125ms feels quite near to original + effect.periodic.delay = 0; + effect.periodic.attack_length = 0; + effects[i] = effect; + } +} + +void JoystickInfo::Rumble(int type, int pad) +{ + if (type > 1) return; + if ( !(conf->pad_options[pad].forcefeedback) ) return; + #if SDL_MAJOR_VERSION >= 2 if (haptic == NULL) return; -#if 0 - additional field of the effect - /* Trigger */ - Uint16 button; /**< Button that triggers the effect. */ - Uint16 interval; /**< How soon it can be triggered again after button. */ - - // periodic parameter - Sint16 offset; /**< Mean value of the wave. */ - Uint16 phase; /**< Horizontal shift given by hundredth of a cycle. */ -#endif - - /*******************************************************************/ - /* Effect big & small */ - /*******************************************************************/ - for (int new_effect = 0; new_effect < 2 ; new_effect++) { - - // Direction of the effect SDL_HapticDirection - haptic_effect_data[new_effect].periodic.direction.type = SDL_HAPTIC_POLAR; // Polar coordinates - haptic_effect_data[new_effect].periodic.direction.dir[0] = 18000; // Force comes from south - - // periodic parameter - haptic_effect_data[new_effect].periodic.period = 20; // 20 ms - haptic_effect_data[new_effect].periodic.magnitude = 2000; // 2000/32767 strength - - // Replay - haptic_effect_data[new_effect].periodic.length = 60; // 60 ms long - haptic_effect_data[new_effect].periodic.delay = 0; // start 0 second after the upload - - // enveloppe - haptic_effect_data[new_effect].periodic.attack_length = 5;// Takes 5 ms to get max strength - haptic_effect_data[new_effect].periodic.attack_level = 0; // start at 0 - haptic_effect_data[new_effect].periodic.fade_length = 5; // Takes 5 ms to fade away - haptic_effect_data[new_effect].periodic.fade_level = 0; // finish at 0 + if(first) + {// If done multiple times, device memory will be filled + first = 0; + GenerateDefaultEffect(); + /** Sine and triangle are quite probably the best, don't change that lightly and if you do + * keep effects ordered by type + **/ + /** Effect for small motor **/ + /** Sine seems to be the only effect making little motor from DS3/4 react + * Intensity has pretty much no effect either(which is coherent with what is explain in hid_sony driver + **/ + effects[0].type = SDL_HAPTIC_SINE; + effects_id[0] = SDL_HapticNewEffect(haptic, &effects[0]); + if(effects_id[0] < 0) + { + fprintf(stderr,"ERROR: Effect is not uploaded! %s, id is %d\n",SDL_GetError(),effects_id[0]); + } + + /** Effect for big motor **/ + effects[1].type = SDL_HAPTIC_TRIANGLE; + effects_id[1] = SDL_HapticNewEffect(haptic, &effects[1]); + if(effects_id[1] < 0) + { + fprintf(stderr,"ERROR: Effect is not uploaded! %s, id is %d\n",SDL_GetError(),effects_id[1]); + } } - /*******************************************************************/ - /* Effect small */ - /*******************************************************************/ - haptic_effect_data[0].type = SDL_HAPTIC_LEFTRIGHT; - - /*******************************************************************/ - /* Effect big */ - /*******************************************************************/ - haptic_effect_data[1].type = SDL_HAPTIC_TRIANGLE; - - /*******************************************************************/ - /* Upload effect to the device */ - /*******************************************************************/ - for (int i = 0 ; i < 2 ; i++) - haptic_effect_id[i] = SDL_HapticNewEffect(haptic, &haptic_effect_data[i]); -#endif -} - -void JoystickInfo::DoHapticEffect(int type, int pad, int force) -{ - if (type > 1) return; - if ( !(conf->options & (PADOPTION_FORCEFEEDBACK << 16 * pad)) ) return; - -#if SDL_MAJOR_VERSION >= 2 - int joyid = conf->get_joyid(pad); - if (!JoystickIdWithinBounds(joyid)) return; - JoystickInfo* pjoy = s_vjoysticks[joyid]; - - if (pjoy->haptic == NULL) return; - if (pjoy->haptic_effect_id[type] < 0) return; - - // FIXME: might need to multiply force - pjoy->haptic_effect_data[type].periodic.magnitude = force * conf->ff_intensity ; // force/32767 strength - // Upload the new effect - SDL_HapticUpdateEffect(pjoy->haptic, pjoy->haptic_effect_id[type], &pjoy->haptic_effect_data[type]); - - // run the effect once - SDL_HapticRunEffect( pjoy->haptic, pjoy->haptic_effect_id[type], 1 ); + int id; + id = effects_id[type]; + if(SDL_HapticRunEffect(haptic, id, 1) != 0) + { + fprintf(stderr,"ERROR: Effect is not working! %s, id is %d\n",SDL_GetError(),id); + } #endif } @@ -179,7 +154,9 @@ void JoystickInfo::Destroy() #endif #if SDL_MAJOR_VERSION >= 2 +#if SDL_MINOR_VERSION >= 4 // Version before 2.0.4 are bugged, JoystickClose crashes randomly if (joy) SDL_JoystickClose(joy); +#endif #else if (SDL_JoystickOpened(_id)) SDL_JoystickClose(joy); #endif @@ -230,8 +207,7 @@ bool JoystickInfo::Init(int id) PAD_LOG("Haptic devices not supported!\n"); } else { haptic = SDL_HapticOpenFromJoystick(joy); - // upload some default effect - InitHapticEffect(); + first = true; } } #endif @@ -251,7 +227,14 @@ void JoystickInfo::SaveState() } void JoystickInfo::TestForce() -{ +{ // This code just use standard rumble to check that SDL handles the pad correctly! --3kinox + if(haptic == NULL) return; // Otherwise, core dump! + SDL_HapticRumbleInit( haptic ); + // Make the haptic pad rumble 60% strength for half a second, shoudld be enough for user to see if it works or not + if( SDL_HapticRumblePlay( haptic, 0.60, 400 ) != 0) + { + fprintf(stderr,"ERROR: Rumble is not working! %s\n",SDL_GetError()); + } } bool JoystickInfo::PollButtons(u32 &pkey) @@ -289,7 +272,7 @@ bool JoystickInfo::PollAxes(u32 &pkey) if (found_hack != string::npos) { // The analog mode of the hat button is quite erratic. Values can be in half- axis // or full axis... So better keep them as button for the moment -- gregory - if (i >= 8 && i <= 11 && (conf->options & PADOPTION_SIXAXIS_USB)) + if (i >= 8 && i <= 11 && (conf->pad_options[pad].sixaxis_usb)) continue; // Disable accelerometer if ((i >= 4 && i <= 6)) @@ -360,6 +343,16 @@ bool JoystickInfo::PollHats(u32 &pkey) return false; } +int JoystickInfo::GetHat(int key_to_axis) +{ + return SDL_JoystickGetHat(GetJoy(),key_to_axis); +} + +int JoystickInfo::GetButton(int key_to_button) +{ + return SDL_JoystickGetButton(GetJoy(),key_to_button); +} + int JoystickInfo::GetAxisFromKey(int pad, int index) { return SDL_JoystickGetAxis(GetJoy(), key_to_axis(pad, index)); diff --git a/plugins/onepad/joystick.h b/plugins/onepad/SDL/joystick.h similarity index 82% rename from plugins/onepad/joystick.h rename to plugins/onepad/SDL/joystick.h index a7da84b6c1..6ec6187d07 100644 --- a/plugins/onepad/joystick.h +++ b/plugins/onepad/SDL/joystick.h @@ -19,31 +19,29 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ -#ifndef __JOYSTICK_H__ -#define __JOYSTICK_H__ +#pragma once #include #if SDL_MAJOR_VERSION >= 2 #include #endif - +#include "GamePad.h" #include "onepad.h" #include "controller.h" - +#define NB_EFFECT 2 // Don't use more than two, ps2 only has one for big motor and one for small(like most systems) // holds all joystick info -class JoystickInfo +class JoystickInfo : GamePad { public: JoystickInfo() : devname(""), _id(-1), numbuttons(0), numaxes(0), numhats(0), deadzone(1500), pad(-1), joy(NULL) { - vbuttonstate.clear(); - vaxisstate.clear(); - vhatstate.clear(); + vbuttonstate.clear(); + vaxisstate.clear(); + vhatstate.clear(); #if SDL_MAJOR_VERSION >= 2 - haptic = NULL; - for (int i = 0 ; i < 2 ; i++) - haptic_effect_id[i] = -1; + haptic = NULL; + first = true; #endif } @@ -57,10 +55,9 @@ class JoystickInfo void Destroy(); // opens handles to all possible joysticks - static void EnumerateJoysticks(vector& vjoysticks); + static void EnumerateJoysticks(vector& vjoysticks); - void InitHapticEffect(); - static void DoHapticEffect(int type, int pad, int force); + void Rumble(int type,int pad); bool Init(int id); // opens a handle and gets information @@ -70,6 +67,10 @@ class JoystickInfo bool PollAxes(u32 &pkey); bool PollHats(u32 &pkey); + int GetHat(int key_to_axis); + + int GetButton(int key_to_button); + const string& GetName() { return devname; @@ -134,16 +135,16 @@ class JoystickInfo vhatstate[i] = value; } - SDL_Joystick* GetJoy() - { - return joy; - } - int GetAxisFromKey(int pad, int index); static void UpdateReleaseState(); private: + SDL_Joystick* GetJoy() + { + return joy; + } + void GenerateDefaultEffect(); string devname; // pretty device name int _id; int numbuttons, numaxes, numhats; @@ -155,13 +156,8 @@ class JoystickInfo SDL_Joystick* joy; #if SDL_MAJOR_VERSION >= 2 SDL_Haptic* haptic; - SDL_HapticEffect haptic_effect_data[2]; - int haptic_effect_id[2]; + bool first; + SDL_HapticEffect effects[NB_EFFECT]; + int effects_id[NB_EFFECT]; #endif }; - - -extern int s_selectedpad; -extern vector s_vjoysticks; -extern bool JoystickIdWithinBounds(int joyid); -#endif diff --git a/plugins/onepad/controller.h b/plugins/onepad/controller.h index 1f640dfe1e..8d8f7a920b 100644 --- a/plugins/onepad/controller.h +++ b/plugins/onepad/controller.h @@ -19,9 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ -#ifndef __CONTROLLER_H__ -#define __CONTROLLER_H__ - +#pragma once +#include // for memset #ifdef __linux__ #define MAX_KEYS 24 #else @@ -55,23 +54,37 @@ extern int hat_to_key(int dir, int axis_id); extern int PadEnum[2][2]; -struct PADconf +class PADconf { + u32 ff_intensity; + u32 sensibility; public: + union { + struct { + u32 forcefeedback :1; + u32 reverse_lx :1; + u32 reverse_ly :1; + u32 reverse_rx :1; + u32 reverse_ry :1; + u32 mouse_l :1; + u32 mouse_r :1; + u32 sixaxis_usb :1; + u32 _free : 8; // The 8 remaining bits are unused, do what you wish with them ;) + } pad_options[2]; // One for each pads + u32 packed_options; // Only first 8 bits of each 16 bits series are really used, rest is padding + }; + u32 keys[2][MAX_KEYS]; u32 log; - u32 options; // upper 16 bits are for pad2 - u32 sensibility; u32 joyid_map; - u32 ff_intensity; map keysym_map[2]; PADconf() { init(); } void init() { memset(&keys, 0, sizeof(keys)); - log = options = joyid_map = 0; - ff_intensity = 100; + log = packed_options = joyid_map = 0; + ff_intensity = 0x7FFF; // set it at max value by default sensibility = 500; for (int pad = 0; pad < 2 ; pad++) keysym_map[pad].clear(); @@ -87,6 +100,43 @@ struct PADconf int shift = 8 * pad; return ((joyid_map >> shift) & 0xFF); } + + /** + * Return (a copy of) private memner ff_instensity + **/ + u32 get_ff_intensity() + { + return ff_intensity; + } + + /** + * Set intensity while checking that the new value is within + * valid range, more than 0x7FFF will cause pad not to rumble(and less than 0 is obviously bad) + **/ + void set_ff_intensity(u32 new_intensity) + { + if(new_intensity < 0x7FFF && new_intensity >= 0) + { + ff_intensity = new_intensity; + } + } + + /** + * Set sensibility value, sensibility is not yet implemented(and will probably be after evdev) + * However, there will be an upper range too, less than 0 is an obvious wrong + * Anyway, we are doing object oriented code, members are definitely not supposed to be public + **/ + void set_sensibility(u32 new_sensibility) + { + if(sensibility > 0) + { + sensibility = new_sensibility; + } + } + + u32 get_sensibility() + { + return sensibility; + } }; extern PADconf *conf; -#endif diff --git a/plugins/onepad/keyboard.cpp b/plugins/onepad/keyboard.cpp index 2426bbd9f1..f5df504103 100644 --- a/plugins/onepad/keyboard.cpp +++ b/plugins/onepad/keyboard.cpp @@ -142,11 +142,11 @@ void AnalyzeKeyEvent(int pad, keyEvent &evt) // 1/ small move == no move. Cons : can not do small movement // 2/ use a watchdog timer thread // 3/ ??? idea welcome ;) - if (conf->options & ((PADOPTION_MOUSE_L|PADOPTION_MOUSE_R) << 16 * pad )) { + if (conf->pad_options[pad].mouse_l|conf->pad_options[pad].mouse_r) { unsigned int pad_x; unsigned int pad_y; // Note when both PADOPTION_MOUSE_R and PADOPTION_MOUSE_L are set, take only the right one - if (conf->options & (PADOPTION_MOUSE_R << 16 * pad)) { + if (conf->pad_options[pad].mouse_r) { pad_x = PAD_R_RIGHT; pad_y = PAD_R_UP; } else { @@ -156,7 +156,7 @@ void AnalyzeKeyEvent(int pad, keyEvent &evt) unsigned x = evt.key & 0xFFFF; unsigned int value = (s_previous_mouse_x > x) ? s_previous_mouse_x - x : x - s_previous_mouse_x; - value *= conf->sensibility; + value *= conf->get_sensibility(); if (x == 0) key_status->press(pad, pad_x, -MAX_ANALOG_VALUE); @@ -172,7 +172,7 @@ void AnalyzeKeyEvent(int pad, keyEvent &evt) unsigned y = evt.key >> 16; value = (s_previous_mouse_y > y) ? s_previous_mouse_y - y : y - s_previous_mouse_y; - value *= conf->sensibility; + value *= conf->get_sensibility(); if (y == 0) key_status->press(pad, pad_y, -MAX_ANALOG_VALUE); diff --git a/plugins/onepad/onepad.cpp b/plugins/onepad/onepad.cpp index 6d036876ef..91d796ff39 100644 --- a/plugins/onepad/onepad.cpp +++ b/plugins/onepad/onepad.cpp @@ -263,7 +263,7 @@ EXPORT_C_(s32) PADopen(void *pDsp) mutex_WasInit = true; #ifdef __linux__ - JoystickInfo::EnumerateJoysticks(s_vjoysticks); + GamePad::EnumerateGamePads(s_vgamePad); #endif return _PADopen(pDsp); } @@ -300,7 +300,6 @@ EXPORT_C_(u32) PADquery() void PADsetMode(int pad, int mode) { padMode[pad] = mode; - // FIXME FEEDBACK padVib0[pad] = 0; padVib1[pad] = 0; padVibF[pad][0] = 0; @@ -413,7 +412,6 @@ u8 _PADpoll(u8 value) buf = stdpar[curPad]; - // FIXME FEEDBACK. Set effect here /* Small Motor */ vib_small = padVibF[curPad][0] ? 2000 : 0; // if ((padVibF[curPad][2] != vib_small) && (padVibC[curPad] >= 0)) @@ -421,7 +419,8 @@ u8 _PADpoll(u8 value) { padVibF[curPad][2] = vib_small; // SetDeviceForceS (padVibC[curPad], vib_small); - JoystickInfo::DoHapticEffect(0, curPad, vib_small); + GamePad* gamePad = s_vgamePad[conf->get_joyid(curPad)]; + gamePad->Rumble(0,curPad); } /* Big Motor */ @@ -431,7 +430,8 @@ u8 _PADpoll(u8 value) { padVibF[curPad][3] = vib_big; // SetDeviceForceB (padVibC[curPad], vib_big); - JoystickInfo::DoHapticEffect(1, curPad, vib_big); + GamePad* gamePad = s_vgamePad[conf->get_joyid(curPad)]; + gamePad->Rumble(1,curPad); } return padID[curPad]; @@ -491,7 +491,7 @@ u8 _PADpoll(u8 value) switch (curCmd) { case CMD_READ_DATA_AND_VIBRATE: - // FIXME FEEDBACK + if (curByte == padVib0[curPad]) padVibF[curPad][0] = value; if (curByte == padVib1[curPad]) @@ -557,7 +557,7 @@ u8 _PADpoll(u8 value) break; case CMD_VIBRATION_TOGGLE: - // FIXME FEEDBACK + if (curByte >= 2) { if (curByte == padVib0[curPad]) @@ -567,16 +567,10 @@ u8 _PADpoll(u8 value) if (value == 0x00) { padVib0[curPad] = curByte; - // FIXME: code from SSSXPAD I'm not sure we need this part - // if ((padID[curPad] & 0x0f) < (curByte - 1) / 2) - // padID[curPad] = (padID[curPad] & 0xf0) + (curByte - 1) / 2; } else if (value == 0x01) { padVib1[curPad] = curByte; - // FIXME: code from SSSXPAD I'm not sure we need this part - // if ((padID[curPad] & 0x0f) < (curByte - 1) / 2) - // padID[curPad] = (padID[curPad] & 0xf0) + (curByte - 1) / 2; } } break; diff --git a/plugins/onepad/onepad.h b/plugins/onepad/onepad.h index f97796e70a..0e76352f2c 100644 --- a/plugins/onepad/onepad.h +++ b/plugins/onepad/onepad.h @@ -48,7 +48,7 @@ using namespace std; #include "PS2Edefs.h" #ifdef __linux__ -#include "joystick.h" +#include "GamePad.h" #endif #include "bitwise.h" #include "controller.h"