Package: mupen64plus-input-sdl / 2.0-4

sdl2_forcefeedback.patch Patch series | download
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