1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
|
Description: Use SDL2 to play force feedback effects
Author: Sven Eckelmann <sven@narfation.org>
---
diff --git a/src/plugin.c b/src/plugin.c
index 26b1814fd9ce666d5dda1f550f438210e642f603..9e553b1463040b1359e95667e6de2957e8e0abf1 100644
--- a/src/plugin.c
+++ b/src/plugin.c
@@ -111,7 +111,7 @@ static int romopen = 0; // is a rom opened
static unsigned char myKeyState[SDL_NUM_SCANCODES];
-#ifdef __linux__
+#if __linux__ && !SDL_VERSION_ATLEAST(2,0,0)
static struct ff_effect ffeffect[4];
static struct ff_effect ffstrong[4];
static struct ff_effect ffweak[4];
@@ -402,7 +402,15 @@ EXPORT void CALL ControllerCommand(int Control, unsigned char *Command)
unsigned int dwAddress = (Command[3] << 8) + (Command[4] & 0xE0);
if (dwAddress == PAK_IO_RUMBLE && *Data)
DebugMessage(M64MSG_VERBOSE, "Triggering rumble pack.");
-#ifdef __linux__
+#if SDL_VERSION_ATLEAST(2,0,0)
+ if(dwAddress == PAK_IO_RUMBLE && controller[Control].event_joystick) {
+ if (*Data) {
+ SDL_HapticRumblePlay(controller[Control].event_joystick, 1, SDL_HAPTIC_INFINITY);
+ } else {
+ SDL_HapticRumbleStop(controller[Control].event_joystick);
+ }
+ }
+#elif __linux__
struct input_event play;
if( dwAddress == PAK_IO_RUMBLE && controller[Control].event_joystick != 0)
{
@@ -617,7 +625,30 @@ EXPORT void CALL GetKeys( int Control, BUTTONS *Keys )
*Keys = controller[Control].buttons;
/* handle mempack / rumblepak switching (only if rumble is active on joystick) */
-#ifdef __linux__
+#if SDL_VERSION_ATLEAST(2,0,0)
+ if (controller[Control].event_joystick) {
+ static unsigned int SwitchPackTime[4] = {0, 0, 0, 0}, SwitchPackType[4] = {0, 0, 0, 0};
+ if (controller[Control].buttons.Value & button_bits[14]) {
+ SwitchPackTime[Control] = SDL_GetTicks(); // time at which the 'switch pack' command was given
+ SwitchPackType[Control] = PLUGIN_MEMPAK; // type of new pack to insert
+ controller[Control].control->Plugin = PLUGIN_NONE;// remove old pack
+ SDL_HapticRumblePlay(controller[Control].event_joystick, 0.5, 500);
+ }
+ if (controller[Control].buttons.Value & button_bits[15]) {
+ SwitchPackTime[Control] = SDL_GetTicks(); // time at which the 'switch pack' command was given
+ SwitchPackType[Control] = PLUGIN_RAW; // type of new pack to insert
+ controller[Control].control->Plugin = PLUGIN_NONE;// remove old pack
+ SDL_HapticRumblePlay(controller[Control].event_joystick, 1, 500);
+ }
+ // handle inserting new pack if the time has arrived
+ if (SwitchPackTime[Control] != 0 && (SDL_GetTicks() - SwitchPackTime[Control]) >= 1000)
+ {
+ SDL_HapticRumbleStop(controller[Control].event_joystick);
+ controller[Control].control->Plugin = SwitchPackType[Control];
+ SwitchPackTime[Control] = 0;
+ }
+ }
+#elif __linux__
if (controller[Control].event_joystick != 0)
{
struct input_event play;
@@ -657,9 +688,66 @@ EXPORT void CALL GetKeys( int Control, BUTTONS *Keys )
controller[Control].buttons.Value = 0;
}
+static void InitiateJoysticks(int cntrl)
+{
+ // init SDL joystick subsystem
+ if (!SDL_WasInit(SDL_INIT_JOYSTICK))
+ if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1) {
+ DebugMessage(M64MSG_ERROR, "Couldn't init SDL joystick subsystem: %s", SDL_GetError() );
+ return;
+ }
+
+ if (controller[cntrl].device >= 0) {
+ controller[cntrl].joystick = SDL_JoystickOpen(controller[cntrl].device);
+ if (!controller[cntrl].joystick)
+ DebugMessage(M64MSG_WARNING, "Couldn't open joystick for controller #%d: %s", cntrl + 1, SDL_GetError());
+ } else {
+ controller[cntrl].joystick = NULL;
+ }
+}
+
+static void DeinitJoystick(int cntrl)
+{
+#if SDL_VERSION_ATLEAST(2,0,0)
+ if (controller[cntrl].joystick) {
+ SDL_JoystickClose(controller[cntrl].joystick);
+ controller[cntrl].joystick = NULL;
+ }
+#endif
+}
+
static void InitiateRumble(int cntrl)
{
-#ifdef __linux__
+#if SDL_VERSION_ATLEAST(2,0,0)
+ if (!SDL_WasInit(SDL_INIT_HAPTIC)) {
+ if (SDL_InitSubSystem(SDL_INIT_HAPTIC) == -1) {
+ DebugMessage(M64MSG_ERROR, "Couldn't init SDL haptic subsystem: %s", SDL_GetError() );
+ return;
+ }
+ }
+
+ controller[cntrl].event_joystick = SDL_HapticOpenFromJoystick(controller[cntrl].joystick);
+ if (!controller[cntrl].event_joystick) {
+ DebugMessage(M64MSG_WARNING, "Couldn't open rumble support for joystick #%i", cntrl + 1);
+ return;
+ }
+
+ if (SDL_HapticRumbleSupported(controller[cntrl].event_joystick) == SDL_FALSE) {
+ SDL_HapticClose(controller[cntrl].event_joystick);
+ controller[cntrl].event_joystick = NULL;
+ DebugMessage(M64MSG_WARNING, "Joystick #%i doesn't support rumble effect", cntrl + 1);
+ return;
+ }
+
+ if (SDL_HapticRumbleInit(controller[cntrl].event_joystick) != 0) {
+ SDL_HapticClose(controller[cntrl].event_joystick);
+ controller[cntrl].event_joystick = NULL;
+ DebugMessage(M64MSG_WARNING, "Rumble initialization failed for Joystick #%i", cntrl + 1);
+ return;
+ }
+
+ DebugMessage(M64MSG_INFO, "Rumble activated on N64 joystick #%i", cntrl + 1);
+#elif __linux__
DIR* dp;
struct dirent* ep;
unsigned long features[4];
@@ -763,6 +851,16 @@ static void InitiateRumble(int cntrl)
#endif /* __linux__ */
}
+static void DeinitRumble(int cntrl)
+{
+#if SDL_VERSION_ATLEAST(2,0,0)
+ if (controller[cntrl].event_joystick) {
+ SDL_HapticClose(controller[cntrl].event_joystick);
+ controller[cntrl].event_joystick = NULL;
+ }
+#endif
+}
+
/******************************************************************
Function: InitiateControllers
Purpose: This function initialises how each of the controllers
@@ -793,10 +891,13 @@ EXPORT void CALL InitiateControllers(CONTROL_INFO ControlInfo)
for( i = 0; i < 4; i++ )
{
// test for rumble support for this joystick
+ InitiateJoysticks(i);
InitiateRumble(i);
// if rumble not supported, switch to mempack
if (controller[i].control->Plugin == PLUGIN_RAW && controller[i].event_joystick == 0)
controller[i].control->Plugin = PLUGIN_MEMPAK;
+ DeinitRumble(i);
+ DeinitJoystick(i);
}
DebugMessage(M64MSG_INFO, "%s version %i.%i.%i initialized.", PLUGIN_NAME, VERSION_PRINTF_SPLIT(PLUGIN_VERSION));
@@ -833,12 +934,10 @@ EXPORT void CALL RomClosed(void)
int i;
// close joysticks
- for( i = 0; i < 4; i++ )
- if( controller[i].joystick )
- {
- SDL_JoystickClose( controller[i].joystick );
- controller[i].joystick = NULL;
- }
+ for( i = 0; i < 4; i++ ) {
+ DeinitRumble(i);
+ DeinitJoystick(i);
+ }
// quit SDL joystick subsystem
SDL_QuitSubSystem( SDL_INIT_JOYSTICK );
@@ -874,15 +973,10 @@ EXPORT int CALL RomOpen(void)
}
// open joysticks
- for( i = 0; i < 4; i++ )
- if( controller[i].device >= 0 )
- {
- controller[i].joystick = SDL_JoystickOpen( controller[i].device );
- if( controller[i].joystick == NULL )
- DebugMessage(M64MSG_WARNING, "Couldn't open joystick for controller #%d: %s", i + 1, SDL_GetError() );
- }
- else
- controller[i].joystick = NULL;
+ for (i = 0; i < 4; i++) {
+ InitiateJoysticks(i);
+ InitiateRumble(i);
+ }
// grab mouse
if (controller[0].mouse || controller[1].mouse || controller[2].mouse || controller[3].mouse)
diff --git a/src/plugin.h b/src/plugin.h
index f5e7bfd32916d650447efd39076eaf0038bea6eb..c55e96bee51f7e5df429f53724d4baa688a624b4 100644
--- a/src/plugin.h
+++ b/src/plugin.h
@@ -135,7 +135,11 @@ typedef struct
int device; // joystick device; -1 = keyboard; -2 = none
int mouse; // mouse enabled: 0 = no; 1 = yes
SDL_Joystick *joystick; // SDL joystick device
+#if SDL_VERSION_ATLEAST(2,0,0)
+ SDL_Haptic *event_joystick; // the sdl device for force feeback
+#else
int event_joystick; // the /dev/input/eventX device for force feeback
+#endif
int axis_deadzone[2]; // minimum absolute value before analog movement is recognized
int axis_peak[2]; // highest analog value returned by SDL, used for scaling
float mouse_sens[2]; // mouse sensitivity
|