]> icculus.org git repositories - taylor/freespace2.git/blob - src/io/swff_lib.cpp
Initial revision
[taylor/freespace2.git] / src / io / swff_lib.cpp
1 /****************************************************************************
2
3 Module name:    SWFF_LIB.cpp
4
5         (C) Copyright Microsoft Corp. 1993.  All rights reserved.
6
7         You have a royalty-free right to use, modify, reproduce and 
8         distribute the Library Files (and/or any modified version) in 
9         any way you find useful, provided that you agree that 
10         Microsoft has no warranty obligations or liability for any 
11         Sample Application Files which are modified. 
12
13
14 Purpose:        This module provides routines to simplify creating Effects
15                         using the DirectInput Force Feedback subsystem.
16                                         
17 Algorithm:      
18
19 Version Date            Author  Comments
20 ------- ---------       ------  --------
21  1.1    01-Apr-97       MEA/DJS
22                 15-Apr-97       MEA             Moved prototype SWFF_SetDuration to sw_force.h
23                 16-Apr-97       DMS             Added SWFF_CreateEffectFromVFXEx
24                 14-May-97       DMS             Added SWFF_PutRawAxisForce 
25                                                           and SWFF_CreateRawAxisForceEffect
26                 22-May-97       DMS             Added SWFF_CreateEffectFromVFX2
27                                                           and SWFF_CreateEffectFromVFX2Ex
28                                                           and SWFF_CreateEffectFromVFXBuffer
29
30
31 ****************************************************************************/
32
33 #include <windows.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include "mmsystem.h"
37 #include "sw_force.h"           // SideWinder Force Feedback Header File
38
39 #define INITGUIDS       // Make GUID available
40 #include "sw_guid.hpp"
41 #include "vdinput.h"
42 #undef INITGUIDS
43
44
45 BOOL CALLBACK DIEnumAndDestroyCreatedEffectsProc(LPDIRECTINPUTEFFECT pDIEffect, LPVOID lpvRef);
46 BOOL CALLBACK DIEnumDevicesProc(LPCDIDEVICEINSTANCE lpddi, LPVOID lpvContext);
47
48
49 // ----------------------------------------------------------------------------
50 //
51 // ***** FUNCTIONS ************************************************************
52 //
53 // ----------------------------------------------------------------------------
54
55 // ----------------------------------------------------------------------------
56 // Function:    SWFF_OpenDefaultFFJoystick
57 // Parameters:  HWND hWnd                                                 - Client Window Handle 
58 //                              LPDIRECTINPUT* ppDI                               - Pointer to DIRECTINPUT
59 //                              LPDIRECTINPUTDEVICE2* ppDIDevice) - Pointer to IDIRECTINPUTDEVICE2
60 //
61 // Returns:
62 // Algorithm:
63 // Comments:
64 // ----------------------------------------------------------------------------
65 HRESULT SWFF_OpenDefaultFFJoystick(
66         IN HWND hWnd,
67         LPDIRECTINPUT* ppDI, 
68         LPDIRECTINPUTDEVICE2* ppDIDevice)
69 {
70         HRESULT hResult;
71         if(hWnd == NULL || ppDI == NULL || ppDIDevice == NULL)
72         {
73                 return SFERR_INVALID_PARAM;
74         }
75
76         // create the DirectInput object
77         hResult = DirectInputCreate(GetModuleHandle(NULL), DIRECTINPUT_VERSION, ppDI, NULL);
78         if(FAILED(hResult))
79                 return hResult;
80         
81         // enumerate the first attached joystick
82         // instance goes in pDIDeviceInstance
83         DIDEVICEINSTANCE DIDeviceInstance;
84         DIDeviceInstance.dwDevType = 0;
85         hResult = (*ppDI)->EnumDevices(DIDEVTYPE_JOYSTICK, DIEnumDevicesProc, &DIDeviceInstance, DIEDFL_FORCEFEEDBACK);
86         if(FAILED(hResult))
87         {
88                 (*ppDI)->Release();
89                 *ppDI = NULL;
90                 return hResult;
91         }
92         if(DIDeviceInstance.dwDevType == 0)
93         {
94                 (*ppDI)->Release();
95                 *ppDI = NULL;
96                 return DIERR_DEVICENOTREG;
97         }
98
99         // create the DirectInput Device object
100         LPDIRECTINPUTDEVICE pDIDevice = NULL;
101         hResult = (*ppDI)->CreateDevice(DIDeviceInstance.guidInstance, &pDIDevice, NULL);
102         if(FAILED(hResult))
103         {
104                 (*ppDI)->Release();
105                 *ppDI = NULL;
106                 return hResult;
107         }
108
109         // get a pointer to its DirectInputDevice2 interface
110         hResult = pDIDevice->QueryInterface(IID_IDirectInputDevice2, (void**)ppDIDevice);
111         if(FAILED(hResult))
112         {
113                 pDIDevice->Release();
114                 pDIDevice = NULL;
115                 (*ppDI)->Release();
116                 *ppDI = NULL;
117                 return hResult;
118         }
119         pDIDevice->Release();
120         pDIDevice = NULL;
121
122         // set the data format to the pre-defined DirectInput joystick format
123         hResult = (*ppDIDevice)->SetDataFormat(&c_dfDIJoystick);
124         if(FAILED(hResult))
125         {
126                 (*ppDIDevice)->Release();
127                 *ppDIDevice = NULL;
128                 (*ppDI)->Release();
129                 *ppDI = NULL;
130                 return hResult;
131         }
132
133         // set the cooperative level
134         hResult = (*ppDIDevice)->SetCooperativeLevel(hWnd, DISCL_EXCLUSIVE | DISCL_FOREGROUND);
135         if(FAILED(hResult))
136         {
137                 (*ppDIDevice)->Release();
138                 *ppDIDevice = NULL;
139                 (*ppDI)->Release();
140                 *ppDI = NULL;
141                 return hResult;
142         }
143
144         // turn auto-center off
145 /*      DIPROPDWORD DIPropAutoCenter;
146         DIPropAutoCenter.diph.dwSize = sizeof(DIPropAutoCenter);
147         DIPropAutoCenter.diph.dwHeaderSize = sizeof(DIPROPHEADER);
148         DIPropAutoCenter.diph.dwObj = 0;
149         DIPropAutoCenter.diph.dwHow = DIPH_DEVICE;
150         DIPropAutoCenter.dwData = 0;
151
152         hResult = (*ppDIDevice)->SetProperty(DIPROP_AUTOCENTER, &DIPropAutoCenter.diph);
153         if(FAILED(hResult))
154         {
155                 (*ppDIDevice)->Release();
156                 *ppDIDevice = NULL;
157                 (*ppDI)->Release();
158                 *ppDI = NULL;
159                 return hResult;
160         }
161 */
162         // acquire the joystick
163         hResult = (*ppDIDevice)->Acquire();
164         if(FAILED(hResult))
165         {
166                 (*ppDIDevice)->Release();
167                 *ppDIDevice = NULL;
168                 (*ppDI)->Release();
169                 *ppDI = NULL;
170                 return hResult;
171         }
172         return SUCCESS;
173
174
175
176 // ----------------------------------------------------------------------------
177 // Function:    SWFF_OpenDefaultFFJoystickEx
178 // Parameters:  HWND hWnd                                                 - Client Window Handle 
179 //                              LPDIRECTINPUT* ppDI                               - Pointer to IDIRECTINPUT
180 //                              HINSTANCE hInstance                               - object instance handle
181 //                              LPDIRECTINPUTDEVICE2* ppDIDevice) - Pointer to IDIRECTINPUTDEVICE2
182 //                              DWORD dwFlags                                     - DISCL_EXCLUSIVE | DISCL_FOREGROUND
183 //
184 // Returns:
185 // Algorithm:
186 // Comments:
187 // ----------------------------------------------------------------------------
188 HRESULT SWFF_OpenDefaultFFJoystickEx(
189         IN HWND hWnd,
190         IN HINSTANCE hInstance,
191         OUT LPDIRECTINPUT* ppDI, 
192         OUT LPDIRECTINPUTDEVICE2* ppDIDevice,
193         IN DWORD dwFlags)
194 {
195         HRESULT hResult;
196         if(hWnd == NULL || hInstance == NULL || ppDI == NULL || ppDIDevice == NULL)
197         {
198                 return SFERR_INVALID_PARAM;
199         }
200
201         // create the DirectInput object
202         hResult = DirectInputCreate(hInstance, DIRECTINPUT_VERSION, ppDI, NULL);
203         if(FAILED(hResult))
204                 return hResult;
205         
206         // enumerate the first attached joystick
207         // instance goes in pDIDeviceInstance
208         DIDEVICEINSTANCE DIDeviceInstance;
209         DIDeviceInstance.dwDevType = 0;
210         hResult = (*ppDI)->EnumDevices(DIDEVTYPE_JOYSTICK, DIEnumDevicesProc, &DIDeviceInstance, DIEDFL_FORCEFEEDBACK);
211         if(FAILED(hResult))
212         {
213                 (*ppDI)->Release();
214                 *ppDI = NULL;
215                 return hResult;
216         }
217         if(DIDeviceInstance.dwDevType == 0)
218         {
219                 (*ppDI)->Release();
220                 *ppDI = NULL;
221                 return DIERR_DEVICENOTREG;
222         }
223
224         // create the DirectInput Device object
225         LPDIRECTINPUTDEVICE pDIDevice = NULL;
226         hResult = (*ppDI)->CreateDevice(DIDeviceInstance.guidInstance, &pDIDevice, NULL);
227         if(FAILED(hResult))
228         {
229                 (*ppDI)->Release();
230                 *ppDI = NULL;
231                 return hResult;
232         }
233
234         // get a pointer to its DirectInputDevice2 interface
235         hResult = pDIDevice->QueryInterface(IID_IDirectInputDevice2, (void**)ppDIDevice);
236         if(FAILED(hResult))
237         {
238                 pDIDevice->Release();
239                 pDIDevice = NULL;
240                 (*ppDI)->Release();
241                 *ppDI = NULL;
242                 return hResult;
243         }
244         pDIDevice->Release();
245         pDIDevice = NULL;
246
247         // set the data format to the pre-defined DirectInput joystick format
248         hResult = (*ppDIDevice)->SetDataFormat(&c_dfDIJoystick);
249         if(FAILED(hResult))
250         {
251                 (*ppDIDevice)->Release();
252                 *ppDIDevice = NULL;
253                 (*ppDI)->Release();
254                 *ppDI = NULL;
255                 return hResult;
256         }
257
258         // set the cooperative level
259         hResult = (*ppDIDevice)->SetCooperativeLevel(hWnd, dwFlags);
260         if(FAILED(hResult))
261         {
262                 (*ppDIDevice)->Release();
263                 *ppDIDevice = NULL;
264                 (*ppDI)->Release();
265                 *ppDI = NULL;
266                 return hResult;
267         }
268
269         // turn auto-center off
270         DIPROPDWORD DIPropAutoCenter;
271         DIPropAutoCenter.diph.dwSize = sizeof(DIPropAutoCenter);
272         DIPropAutoCenter.diph.dwHeaderSize = sizeof(DIPROPHEADER);
273         DIPropAutoCenter.diph.dwObj = 0;
274         DIPropAutoCenter.diph.dwHow = DIPH_DEVICE;
275         DIPropAutoCenter.dwData = 0;
276
277         hResult = (*ppDIDevice)->SetProperty(DIPROP_AUTOCENTER, &DIPropAutoCenter.diph);
278         if(FAILED(hResult))
279         {
280                 (*ppDIDevice)->Release();
281                 *ppDIDevice = NULL;
282                 (*ppDI)->Release();
283                 *ppDI = NULL;
284                 return hResult;
285         }
286
287         // acquire the joystick
288         hResult = (*ppDIDevice)->Acquire();
289         if(FAILED(hResult))
290         {
291                 (*ppDIDevice)->Release();
292                 *ppDIDevice = NULL;
293                 (*ppDI)->Release();
294                 *ppDI = NULL;
295                 return hResult;
296         }
297         return SUCCESS;
298
299
300
301 BOOL CALLBACK DIEnumDevicesProc(LPCDIDEVICEINSTANCE lpddi, LPVOID lpvContext)
302 {
303         LPDIDEVICEINSTANCE pDIDeviceInstance = (LPDIDEVICEINSTANCE)lpvContext;
304         if(pDIDeviceInstance == NULL)
305         {
306                 return DIENUM_STOP;
307         }
308
309         if(GET_DIDEVICE_TYPE(lpddi->dwDevType) == DIDEVTYPE_JOYSTICK)
310         {
311                 memcpy((LPVOID)pDIDeviceInstance, (LPVOID)lpddi, sizeof(*pDIDeviceInstance));
312
313                 return DIENUM_STOP;
314         }
315
316         return DIENUM_CONTINUE;
317 }
318
319 // ----------------------------------------------------------------------------
320 // Function:    SWFF_DestroyEffect
321 // Purpose:             Destroys one effect or all effects
322 // Parameters:  LPDIRECTINPUTDEVICE2 pDIDevice  - IDIRECTINPUTDEVICE2 interface
323 //                              LPDIRECTINPUTEFFECT pDIEffect   - Effect to destroy
324 //                                                                                              - NULL destroys all effects
325 // Returns:
326 // Algorithm:   
327 // Comments:
328 // 
329 // ----------------------------------------------------------------------------
330 HRESULT SWFF_DestroyEffect(
331         IN LPDIRECTINPUTDEVICE2 pDIDevice,
332         IN LPDIRECTINPUTEFFECT pDIEffect)
333 {
334         HRESULT hResult = SUCCESS;
335         if(pDIEffect != NULL)
336         {
337                 pDIEffect->Release();
338         }
339         else
340                 hResult = SWFF_DestroyAllEffects(pDIDevice);
341
342         return hResult;
343 }
344
345 // ----------------------------------------------------------------------------
346 // Function:    SWFF_DestroyAllEffects
347 // Purpose:             Destroys all created effects
348 // Parameters:  LPDIRECTINPUTDEVICE2 pDIDevice  - IDIRECTINPUTDEVICE2 interface
349 // Returns:
350 // Algorithm:   
351 // Comments:
352 // 
353 // ----------------------------------------------------------------------------
354 HRESULT SWFF_DestroyAllEffects(
355         IN LPDIRECTINPUTDEVICE2 pDIDevice)
356 {
357         HRESULT hResult;
358
359         if(pDIDevice == NULL)
360                 return SFERR_INVALID_PARAM;
361
362         hResult = pDIDevice->EnumCreatedEffectObjects(DIEnumAndDestroyCreatedEffectsProc, NULL, 0);
363
364         return hResult;
365 }
366
367 BOOL CALLBACK DIEnumAndDestroyCreatedEffectsProc(LPDIRECTINPUTEFFECT pDIEffect, LPVOID lpvRef)
368 {
369         pDIEffect->Release();
370
371         return DIENUM_CONTINUE;
372 }
373
374 // ----------------------------------------------------------------------------
375 // Function:    SWFF_SetGain
376 // Purpose:             Sets Gain for the Effect
377 // Parameters:  LPDIRECTINPUTEFFECT     pDIEffect       - Pointer to effect to set the gain for
378 //                              DWORD dwGain                                    - Gain in 1 to 10000
379 // Returns:
380 // Algorithm:   
381 // Comments:
382 // 
383 // ----------------------------------------------------------------------------
384 HRESULT SWFF_SetGain(
385         IN LPDIRECTINPUTEFFECT pDIEffect,
386         IN DWORD dwGain)
387 {
388         if(pDIEffect == NULL)
389                 return SFERR_INVALID_PARAM;
390
391         DIEFFECT thisEffect = { sizeof(DIEFFECT) };
392         thisEffect.dwGain = dwGain;
393         return pDIEffect->SetParameters(&thisEffect, DIEP_GAIN);
394 }
395
396
397 // ----------------------------------------------------------------------------
398 // Function:    SWFF_SetDirection
399 // Purpose:             Sets 2D Angle Direction for the Effect
400 // Parameters:  LPDIRECTINPUTEFFECT pDIEffect   - Pointer to effect to set the direction for
401 //                              DWORD dwAngle                                   - Direction in 0 to 35999
402 // Returns:
403 // Algorithm:   
404 // Comments:
405 // 
406 // ----------------------------------------------------------------------------
407 HRESULT SWFF_SetDirection(
408         IN LPDIRECTINPUTEFFECT pDIEffect,
409         IN DWORD dwAngle)
410 {
411         if(pDIEffect == NULL)
412                 return SFERR_INVALID_PARAM;
413
414         // set up a DIEFFECT structure so we can change direction
415         LONG rglDirection[2];
416         DIEFFECT thisEffect = {sizeof(DIEFFECT)};
417         thisEffect.dwFlags = DIEFF_OBJECTOFFSETS | DIEFF_POLAR;
418         thisEffect.cAxes = 2;
419         thisEffect.rgdwAxes = NULL;
420         thisEffect.rglDirection = rglDirection;
421         thisEffect.rglDirection[0] = dwAngle;
422         return pDIEffect->SetParameters(&thisEffect, DIEP_DIRECTION);
423 }
424
425 HRESULT SWFF_SetDirectionGain(
426         IN LPDIRECTINPUTEFFECT pDIEffect,
427         IN DWORD dwAngle,
428         IN DWORD dwGain)
429 {
430         if(pDIEffect == NULL)
431                 return SFERR_INVALID_PARAM;
432
433         // set up a DIEFFECT structure so we can change direction
434         LONG rglDirection[2];
435         DIEFFECT thisEffect = {sizeof(DIEFFECT)};
436
437         thisEffect.dwFlags = DIEFF_OBJECTOFFSETS | DIEFF_POLAR;
438         thisEffect.cAxes = 2;
439         thisEffect.rgdwAxes = NULL;
440         thisEffect.rglDirection = rglDirection;
441         thisEffect.rglDirection[0] = dwAngle;
442         thisEffect.dwGain = dwGain;
443         return pDIEffect->SetParameters(&thisEffect, DIEP_DIRECTION | DIEP_GAIN);
444 }
445
446 // ----------------------------------------------------------------------------
447 // Function:    SWFF_SetDuration
448 // Purpose:             Sets Duration for the Effect
449 // Parameters:  LPDIRECTINPUTEFFECT pDIEffect   - Pointer to effect to set the duration for
450 //                              DWORD dwDuration                                - In uSecs, INFINITE is FOREVER
451 // Returns:
452 // Algorithm:   
453 // Comments:
454 // 
455 // ----------------------------------------------------------------------------
456 HRESULT SWFF_SetDuration(
457         IN LPDIRECTINPUTEFFECT pDIEffect,
458         IN DWORD dwDuration)
459 {
460         if(pDIEffect == NULL)
461                 return SFERR_INVALID_PARAM;
462
463         DIEFFECT thisEffect = { sizeof(DIEFFECT) };
464         thisEffect.dwDuration = dwDuration;
465         return pDIEffect->SetParameters(&thisEffect, DIEP_DURATION);
466 }
467
468
469 // ----------------------------------------------------------------------------
470 // Function:    SWFF_PutRawForce
471 // Purpose:             Sends Force Value,Direction to ff Device
472 // Parameters:  LPDIRECTINPUTEFFECT pDIEffect   - Pointer to a two axis raw force object
473 //                              LONG lMagnitude                                 - -10000 to +10000 force value
474 //                              DWORD dwDirection                               - 0 to 35999
475 // Returns:
476 // Algorithm:   
477 // Comments:    To use this, you need to create the effect using
478 //                              SWFF_CreateRawForceEffect() first
479 // 
480 // ----------------------------------------------------------------------------
481 HRESULT SWFF_PutRawForce(
482         IN LPDIRECTINPUTEFFECT pDIEffect,
483         IN LONG lMagnitude,
484         IN DWORD dwDirection)
485 {
486         if(pDIEffect == NULL)
487                 return SFERR_INVALID_PARAM;
488
489         DICONSTANTFORCE DIConstantForceStruct;
490         DIConstantForceStruct.lMagnitude = lMagnitude;
491
492         DWORD rgdwAxes[2];
493         rgdwAxes[0] = DIJOFS_X;
494         rgdwAxes[1] = DIJOFS_Y;
495
496         LONG rglDirection[2];
497         rglDirection[0] = dwDirection;
498         rglDirection[1] = 0;
499
500         DIEFFECT thisEffect = { sizeof(DIEFFECT) };
501         thisEffect.dwFlags = DIEFF_OBJECTOFFSETS | DIEFF_POLAR;
502         thisEffect.cAxes                   = 2;
503         thisEffect.rgdwAxes                = rgdwAxes;
504         thisEffect.rglDirection    = rglDirection;
505
506         thisEffect.cbTypeSpecificParams = sizeof(DICONSTANTFORCE);
507         thisEffect.lpvTypeSpecificParams        = &DIConstantForceStruct;
508         return pDIEffect->SetParameters(&thisEffect, DIEP_DIRECTION|DIEP_TYPESPECIFICPARAMS);
509 }
510
511 // ----------------------------------------------------------------------------
512 // Function:    SWFF_PutRawAxisForce
513 // Purpose:             Sends Force Value,Direction to ff Device
514 // Parameters:  LPDIRECTINPUTEFFECT pDIEffect   - Pointer to a one axis raw force object
515 //                              LONG lMagnitude                                 - -10000 to +10000 force value
516 // Returns:
517 // Algorithm:   
518 // Comments:    To use this, you need to create the effect using
519 //                              SWFF_CreateRawAxisForceEffect() first
520 // 
521 // ----------------------------------------------------------------------------
522 HRESULT SWFF_PutRawAxisForce(
523         IN LPDIRECTINPUTEFFECT pDIEffect,
524         IN LONG lMagnitude)
525 {
526         if(pDIEffect == NULL)
527                 return SFERR_INVALID_PARAM;
528
529         DICONSTANTFORCE DIConstantForceStruct;
530         DIConstantForceStruct.lMagnitude = lMagnitude;
531
532         DIEFFECT thisEffect = { sizeof(DIEFFECT) };
533
534         thisEffect.cbTypeSpecificParams = sizeof(DICONSTANTFORCE);
535         thisEffect.lpvTypeSpecificParams        = &DIConstantForceStruct;
536         return pDIEffect->SetParameters(&thisEffect, DIEP_TYPESPECIFICPARAMS);
537 }
538
539 // ----------------------------------------------------------------------------
540 // Function:    SWFF_CreateRawForceEffect
541 // Parameters:  LPDIRECTINPUTDEVICE2 pDIDevice  - IDIRECTINPUTDEVICE2 interface
542 //                              LPDIRECTINPUTEFFECT* ppDIEffect - Receives pointer to created effect
543 //                              LONG lMagnitude                                 - -10000 to 10000
544 //                              DWORD dwDirection                               - 0 to 35999
545 //
546 //                              
547 // Returns:             
548 // Algorithm:
549 // Comments:    Create this Effect once, then use SetParameter(...) to play the
550 //                              force value
551 //
552 // ----------------------------------------------------------------------------
553 #if 0
554 HRESULT SWFF_CreateRawForceEffect(
555         IN LPDIRECTINPUTDEVICE2 pDIDevice, 
556         IN OUT LPDIRECTINPUTEFFECT * ppDIEffect,
557         IN LONG lMagnitude,
558         IN DWORD dwDirection)
559 {
560         if(pDIDevice == NULL || ppDIEffect == NULL)
561                 return SFERR_INVALID_PARAM;
562         // Always clear return IPtr
563         *ppDIEffect = NULL;
564
565         LPDIRECTINPUTEFFECT  pRawForce;
566
567         DICONSTANTFORCE DIConstantForceStruct;
568         DIConstantForceStruct.lMagnitude = lMagnitude;
569
570         DWORD rgdwAxes[2];
571         rgdwAxes[0] = DIJOFS_X;
572         rgdwAxes[1] = DIJOFS_Y;
573
574         LONG rglDirection[2];
575         rglDirection[0] = dwDirection;
576         rglDirection[1] = 0;
577
578         DIEFFECT DIEffect;
579         DIEffect.dwSize                                 = sizeof(DIEFFECT);
580         DIEffect.dwFlags                                = DIEFF_OBJECTOFFSETS | DIEFF_POLAR;
581         DIEffect.dwDuration                             = INFINITE;
582         DIEffect.dwSamplePeriod                 = HZ_TO_uS(100);
583         DIEffect.dwGain                                 = 10000;
584         DIEffect.dwTriggerButton                = DIEB_NOTRIGGER;
585         DIEffect.dwTriggerRepeatInterval= 0;
586         DIEffect.cAxes                                  = 2;
587         DIEffect.rgdwAxes                               = rgdwAxes;
588         DIEffect.rglDirection                   = rglDirection;
589         DIEffect.lpEnvelope                             = NULL;
590         DIEffect.cbTypeSpecificParams   = sizeof(DICONSTANTFORCE);
591         DIEffect.lpvTypeSpecificParams  = &DIConstantForceStruct;
592
593         HRESULT hRet;
594         hRet = pDIDevice->CreateEffect(GUID_RawForce, &DIEffect, &pRawForce, NULL);
595         if(FAILED(hRet)) return hRet;
596
597         *ppDIEffect = pRawForce;
598         return SUCCESS;
599 }
600 #endif
601
602 // ----------------------------------------------------------------------------
603 // Function:    SWFF_CreateRawAxisForceEffect
604 // Parameters:  LPDIRECTINPUTDEVICE2 pDIDevice          - IDIRECTINPUTDEVICE2 interface
605 //                              LPDIRECTINPUTEFFECT* ppDIEffect         - Receives pointer to created effect
606 //                              LONG lMagnitude                                         - -10000 to 10000
607 //                              DWORD dwAxis                                            - Either X_AXIS or Y_AXIS
608 //
609 //                              
610 // Returns:             
611 // Algorithm:
612 // Comments:    Create this Effect once, then use SetParameter(...) to play the
613 //                              force value
614 //
615 // ----------------------------------------------------------------------------
616 #if 0
617 HRESULT SWFF_CreateRawAxisForceEffect(
618         IN LPDIRECTINPUTDEVICE2 pDIDevice, 
619         IN OUT LPDIRECTINPUTEFFECT * ppDIEffect,
620         IN LONG lMagnitude,
621         IN DWORD dwAxis)
622 {
623         if(pDIDevice == NULL || ppDIEffect == NULL)
624                 return SFERR_INVALID_PARAM;
625
626         if(!(dwAxis == X_AXIS || dwAxis == Y_AXIS))
627                 return SFERR_INVALID_PARAM;
628
629         // Always clear return IPtr
630         *ppDIEffect = NULL;
631
632         LPDIRECTINPUTEFFECT  pRawForce;
633
634         DICONSTANTFORCE DIConstantForceStruct;
635         DIConstantForceStruct.lMagnitude = lMagnitude;
636
637         DWORD rgdwAxes[1];
638         if(dwAxis == X_AXIS)
639                 rgdwAxes[0] = DIJOFS_X;
640         else
641                 rgdwAxes[0] = DIJOFS_Y;
642
643         LONG rglDirection[1];
644         rglDirection[0] = 0;
645
646         DIEFFECT DIEffect;
647         DIEffect.dwSize                                 = sizeof(DIEFFECT);
648         DIEffect.dwFlags                                = DIEFF_OBJECTOFFSETS | DIEFF_CARTESIAN;
649         DIEffect.dwDuration                             = INFINITE;
650         DIEffect.dwSamplePeriod                 = HZ_TO_uS(100);
651         DIEffect.dwGain                                 = 10000;
652         DIEffect.dwTriggerButton                = DIEB_NOTRIGGER;
653         DIEffect.dwTriggerRepeatInterval= 0;
654         DIEffect.cAxes                                  = 1;
655         DIEffect.rgdwAxes                               = rgdwAxes;
656         DIEffect.rglDirection                   = rglDirection;
657         DIEffect.lpEnvelope                             = NULL;
658         DIEffect.cbTypeSpecificParams   = sizeof(DICONSTANTFORCE);
659         DIEffect.lpvTypeSpecificParams  = &DIConstantForceStruct;
660
661         HRESULT hRet;
662         hRet = pDIDevice->CreateEffect(GUID_RawForce, &DIEffect, &pRawForce, NULL);
663         if(FAILED(hRet)) return hRet;
664
665         *ppDIEffect = pRawForce;
666         return SUCCESS;
667 }
668 #endif
669
670 // ----------------------------------------------------------------------------
671 // Function:    SWFF_CreateROMEffect
672 // Parameters:  LPDIRECTINPUTDEVICE2 pDIDevice  - IDIRECTINPUTDEVICE2 interface
673 //                              LPDIRECTINPUTEFFECT* ppDIEffect - Receives pointer to created effect
674 //                              REFGUID refGUID                                 - GUID for ROM Effect
675 //                              DWORD dwDuration                                - uS
676 //                              DWORD dwGain                                    - 1 to 10000
677 //                              DWORD dwDirection                               - 0 to 35999
678 //                              LONG lButton                                    - Index of playback button, -1 for none
679 //
680 // Returns:             
681 // Algorithm:
682 // Comments:    Assumes valid GUID for the ROM Effect
683 // Note:                If unmodified ROM Effect, user has to pass
684 //                                 DEFAULT_ROM_EFFECT_DURATION,  DEFAULT_ROM_EFFECT_GAIN
685 // ----------------------------------------------------------------------------
686 HRESULT SWFF_CreateROMEffect(
687         IN LPDIRECTINPUTDEVICE2 pDIDevice, 
688         IN OUT LPDIRECTINPUTEFFECT * ppDIEffect,
689         IN REFGUID refGUID,
690         IN DWORD dwDuration,            
691         IN DWORD dwGain,
692         IN DWORD dwDirection,           
693         IN LONG lButton)                        
694 {
695         if(pDIDevice == NULL || ppDIEffect == NULL)
696                 return SFERR_INVALID_PARAM;
697         // Always clear return IPtr
698         *ppDIEffect = NULL;
699
700         LPDIRECTINPUTEFFECT  pROMEffect = NULL;
701
702         // Default NO Envelope
703         DIENVELOPE DIEnvelopeStruct;                            
704         DIEnvelopeStruct.dwSize = sizeof(DIENVELOPE);
705         DIEnvelopeStruct.dwAttackTime = 0;
706         DIEnvelopeStruct.dwAttackLevel = 10000;
707         DIEnvelopeStruct.dwFadeTime = 0;
708         DIEnvelopeStruct.dwFadeLevel = 10000;
709
710         // 2DOF
711         DWORD rgdwAxes[2];
712         rgdwAxes[0] = DIJOFS_X;
713         rgdwAxes[1] = DIJOFS_Y;
714
715         LONG rglDirection[2];
716         rglDirection[0] = dwDirection;
717         rglDirection[1] = 0;
718
719         DIEFFECT DIEffect;
720         DIEffect.dwSize                                 = sizeof(DIEFFECT);
721         DIEffect.dwFlags                                = DIEFF_OBJECTOFFSETS | DIEFF_POLAR;
722         // Set Duration and Gain to use Default ROM Effect params unless overridden
723         DIEffect.dwDuration                             = dwDuration;   // can be DEFAULT_ROM_EFFECT_DURATION
724         DIEffect.dwSamplePeriod                 = DEFAULT_ROM_EFFECT_OUTPUTRATE;
725         DIEffect.dwGain                                 = dwGain;               // can be DEFAULT_ROM_EFFECT_GAIN;      
726         //
727         DIEffect.dwTriggerButton                = lButton == -1 ? DIEB_NOTRIGGER : FIELD_OFFSET(DIJOYSTATE, rgbButtons) + lButton;
728         DIEffect.dwTriggerRepeatInterval= 0;
729         DIEffect.cAxes                                  = 2;
730         DIEffect.rgdwAxes                               = rgdwAxes;
731         DIEffect.rglDirection                   = rglDirection;
732         DIEffect.lpEnvelope                             = &DIEnvelopeStruct;
733         DIEffect.cbTypeSpecificParams   = 0;
734         DIEffect.lpvTypeSpecificParams  = NULL;
735
736         HRESULT hRet = pDIDevice->CreateEffect(refGUID, &DIEffect, &pROMEffect, NULL);
737         if(FAILED(hRet)) return hRet;
738
739         *ppDIEffect = pROMEffect;
740         return SUCCESS;
741 }
742
743 // ----------------------------------------------------------------------------
744 // Function:    SWFF_WriteRegString
745 // Parameters:  LPCTSTR         pszKey          -       The key under HKCR to place the value
746 //                              LPCTSTR         pszValue        -       The string value for pszKey
747 //                              
748 // Returns:             TRUE if the registry entry was successfully made
749 // Algorithm:
750 // Comments:    Helper function for SWFF_RegisterVFXObject to write registry entries
751 // Note:
752 // ----------------------------------------------------------------------------
753 BOOL SWFF_WriteRegString(
754         IN LPCTSTR pszKey,
755         IN LPCTSTR pszValue)
756 {
757         HKEY hKey;
758         LONG lRet;
759         int nLen;
760
761         if(pszKey == NULL || pszValue == NULL)
762                 return FALSE;
763
764         // create it
765         hKey = HKEY_CLASSES_ROOT;
766         lRet = RegCreateKey(hKey, pszKey, &hKey);
767         if(lRet != ERROR_SUCCESS)
768                 return FALSE;
769
770         // save the value into the key
771         nLen = strlen(pszValue);
772         lRet = RegSetValueEx(hKey, NULL, 0, REG_SZ, (PBYTE)pszValue, nLen + 1);
773         if(lRet != ERROR_SUCCESS)
774         {
775                 RegCloseKey(hKey);
776                 return FALSE;
777         }
778
779         // close the key
780         RegCloseKey(hKey);
781         if(lRet != ERROR_SUCCESS)
782                 return FALSE;
783
784         // if we have reached this point, then it was a success
785         return TRUE;
786 }
787
788 // ----------------------------------------------------------------------------
789 // Function:    SWFF_RegisterVFXObject
790 // Parameters:  LPCTSTR         - Pointer to the fully-qualified path name of VFX.DLL
791 //                              
792 // Returns:             TRUE if the object was successfully registered
793 // Algorithm:
794 // Comments:    Example of code to register the VFX com object.  
795 //                              You supply lpszVFXPath depending on where you install VFX.DLL
796 // Note:
797 // ----------------------------------------------------------------------------
798 #define GUID_VFX_Object "{04ace0a7-1fa8-11d0-aa22-00a0c911f471}"
799 BOOL SWFF_RegisterVFXObject(IN LPCTSTR pszVFXPath)
800 {
801         if(pszVFXPath == NULL)
802                 return FALSE;
803
804         return  SWFF_WriteRegString("\\VFX1.0", "VFX Object")
805                 &&      SWFF_WriteRegString("\\VFX1.0\\CLSID", GUID_VFX_Object)
806                 &&      SWFF_WriteRegString("\\VFX", "VFX Object")
807                 &&      SWFF_WriteRegString("\\VFX\\CurVer", "VFX1.0")
808                 &&      SWFF_WriteRegString("\\VFX\\CLSID", GUID_VFX_Object)
809                 &&      SWFF_WriteRegString("\\CLSID\\"GUID_VFX_Object, "VFX Object")
810                 &&      SWFF_WriteRegString("\\CLSID\\"GUID_VFX_Object"\\VersionIndependentProgID", "VFX")
811                 &&      SWFF_WriteRegString("\\CLSID\\"GUID_VFX_Object"\\InprocServer32", pszVFXPath)
812                 &&      SWFF_WriteRegString("\\CLSID\\"GUID_VFX_Object"\\NotInsertable", "");
813 }
814
815 // ----------------------------------------------------------------------------
816 // Function:    SWFF_CreateVFXEffectFromFile
817 // Parameters:  LPDIRECTINPUTDEVICE2 pDIDevice  - IDIRECTINPUTDEVICE2 interface
818 //                              LPDIRECTINPUTEFFECT* ppDIEffect - Receives pointer to created effect
819 //                              TCHAR *pszFileName                              - Pointer to VFX File name
820 //                              
821 // Returns:             
822 // Algorithm:
823 // Comments:
824 // Note:
825 // ----------------------------------------------------------------------------
826 #if 0
827 HRESULT SWFF_CreateVFXEffectFromFile(
828         IN LPDIRECTINPUTDEVICE2 pDIDevice, 
829         IN OUT LPDIRECTINPUTEFFECT* ppDIEffect,
830         IN const TCHAR *pszFileName)
831 {
832         if(pDIDevice == NULL || ppDIEffect == NULL || pszFileName == NULL)
833                 return SFERR_INVALID_PARAM;
834
835         // Always clear return IPtr
836         *ppDIEffect = NULL;
837
838         LPDIRECTINPUTEFFECT  pVFXEffect;
839
840         VFX_PARAM VFXParam;
841         VFXParam.m_Bytes = sizeof(VFX_PARAM);
842         VFXParam.m_PointerType = VFX_FILENAME;
843         VFXParam.m_BufferSize = 0;
844         VFXParam.m_pFileNameOrBuffer = (PVOID) pszFileName;
845
846         DWORD rgdwAxes[2];
847         rgdwAxes[0] = DIJOFS_X;
848         rgdwAxes[1] = DIJOFS_Y;
849
850         LONG rglDirection[2];
851         rglDirection[0] = DEFAULT_VFX_EFFECT_DIRECTION;
852         rglDirection[1] = 0;
853
854         DIEFFECT DIEffectStruct;
855         DIEffectStruct.dwSize                                   = sizeof(DIEFFECT);
856         DIEffectStruct.dwFlags                                  = DIEFF_OBJECTOFFSETS | DIEFF_POLAR;
857         DIEffectStruct.dwDuration                               = DEFAULT_VFX_EFFECT_DURATION;
858         DIEffectStruct.dwSamplePeriod                   = HZ_TO_uS(100);
859         DIEffectStruct.dwGain                                   = DEFAULT_VFX_EFFECT_GAIN;
860         DIEffectStruct.dwTriggerButton                  = DIEB_NOTRIGGER;
861         DIEffectStruct.dwTriggerRepeatInterval  = 0;
862         DIEffectStruct.cAxes                                    = 2;
863         DIEffectStruct.rgdwAxes                                 = rgdwAxes;
864         DIEffectStruct.rglDirection                             = rglDirection;
865         DIEffectStruct.lpEnvelope                               = NULL;
866         DIEffectStruct.cbTypeSpecificParams             = sizeof(VFX_PARAM);
867         DIEffectStruct.lpvTypeSpecificParams    = &VFXParam;
868
869         HRESULT hResult;
870         hResult = pDIDevice->CreateEffect(GUID_VFXEffect, &DIEffectStruct, &pVFXEffect, NULL);
871         if(FAILED(hResult)) return hResult;
872
873         *ppDIEffect = pVFXEffect;
874         return hResult;
875
876 #endif
877
878 // ----------------------------------------------------------------------------
879 // Function:    SWFF_CreateVFXEffectFromFileEx
880 // Parameters:  LPDIRECTINPUTDEVICE2 pDIDevice  - IDIRECTINPUTDEVICE2 interface
881 //                              LPDIRECTINPUTEFFECT* ppDIEffect - Receives pointer to created effect
882 //                              TCHAR *pszFileName                              - Pointer to VFX File
883 //                              DWORD dwDuration                                - INFINITE or default
884 //                              DWORD dwGain                                    - 1 to 10000
885 //                              DWORD dwDirection                               - 0 to 35999
886 //                              
887 // Returns:             
888 // Algorithm:
889 // Comments:
890 // Note:
891 // ----------------------------------------------------------------------------
892 #if 0
893 HRESULT SWFF_CreateVFXEffectFromFileEx(
894         IN LPDIRECTINPUTDEVICE2 pDIDevice, 
895         IN OUT LPDIRECTINPUTEFFECT* ppDIEffect,
896         IN const TCHAR *pszFileName,
897         IN DWORD dwDuration,
898         IN DWORD dwGain,
899         IN DWORD dwDirection)
900 {
901         if(pDIDevice == NULL || ppDIEffect == NULL || pszFileName == NULL)
902                 return SFERR_INVALID_PARAM;
903         // Always clear return IPtr
904         *ppDIEffect = NULL;
905
906         LPDIRECTINPUTEFFECT  pVFXEffect;
907
908         VFX_PARAM VFXParam;
909         VFXParam.m_Bytes = sizeof(VFX_PARAM);
910         VFXParam.m_PointerType = VFX_FILENAME;
911         VFXParam.m_BufferSize = 0;
912         VFXParam.m_pFileNameOrBuffer = (PVOID) pszFileName;
913
914         DWORD rgdwAxes[2];
915         rgdwAxes[0] = DIJOFS_X;
916         rgdwAxes[1] = DIJOFS_Y;
917
918         LONG rglDirection[2];
919         rglDirection[0] = dwDirection;
920         rglDirection[1] = 0;
921
922         DIEFFECT DIEffectStruct;
923         DIEffectStruct.dwSize                                   = sizeof(DIEFFECT);
924         DIEffectStruct.dwFlags                                  = DIEFF_OBJECTOFFSETS | DIEFF_POLAR;
925         DIEffectStruct.dwDuration                               = dwDuration;
926         DIEffectStruct.dwSamplePeriod                   = HZ_TO_uS(100);
927         DIEffectStruct.dwGain                                   = dwGain;
928         DIEffectStruct.dwTriggerButton                  = DIEB_NOTRIGGER;
929         DIEffectStruct.dwTriggerRepeatInterval  = 0;
930         DIEffectStruct.cAxes                                    = 2;
931         DIEffectStruct.rgdwAxes                                 = rgdwAxes;
932         DIEffectStruct.rglDirection                             = rglDirection;
933         DIEffectStruct.lpEnvelope                               = NULL;
934         DIEffectStruct.cbTypeSpecificParams             = sizeof(VFX_PARAM);
935         DIEffectStruct.lpvTypeSpecificParams    = &VFXParam;
936
937         HRESULT hResult;
938         hResult = pDIDevice->CreateEffect(GUID_VFXEffect, &DIEffectStruct, &pVFXEffect, NULL);
939         if(FAILED(hResult)) return hResult;
940
941         *ppDIEffect = pVFXEffect;
942         return hResult;
943
944 #endif
945
946 // ----------------------------------------------------------------------------
947 // Function:    SWFF_CreateVFXEffectFromBuffer
948 // Parameters:  LPDIRECTINPUTDEVICE2 pDIDevice  - IDIRECTINPUTDEVICE2 interface
949 //                              LPDIRECTINPUTEFFECT* ppDIEffect - Receives pointer to created effect
950 //                              LPVOID pBuffer                                  - Pointer to VFX Buffer
951 //                              DWORD dwBufferSize                              - Buffer size in bytes
952 //                              
953 // Returns:             
954 // Algorithm:
955 // Comments:
956 // Note:
957 //              If you are compiling the FRC files as resources in your executable
958 //              by putting #include "script.vfx" in your .rc file, you would use
959 //              code similar to the following to create the effect (no error checking).
960 //      
961 //                      HRSRC hResInfo = FindResource(NULL, "IDF_FOO", "FORCE");
962 //                      DWORD dwBytes = SizeofResource(NULL, hResInfo);
963 //                      HGLOBAL hRsrc = LoadResource(NULL, hResInfo);
964 //                      PVOID pBuffer = LockResource(hRsrc);
965 //                      SWFF_CreateEffectFromVFXBuffer(pDIDevice, pBuffer, dwBytes, &pDIEffect);
966 //
967 // ----------------------------------------------------------------------------
968 #if 0
969 HRESULT SWFF_CreateVFXEffectFromBuffer(
970         IN LPDIRECTINPUTDEVICE2 pDIDevice, 
971         IN OUT LPDIRECTINPUTEFFECT* ppDIEffect,
972         IN const LPVOID pBuffer,
973         IN DWORD dwBufferSize)
974 {
975         if(pDIDevice == NULL || ppDIEffect == NULL || pBuffer == NULL)
976                 return SFERR_INVALID_PARAM;
977         
978         // Always clear return IPtr
979         *ppDIEffect = NULL;
980
981         LPDIRECTINPUTEFFECT  pVFXEffect;
982
983         VFX_PARAM VFXParam;
984         VFXParam.m_Bytes = sizeof(VFX_PARAM);
985         VFXParam.m_PointerType = VFX_BUFFER;
986         VFXParam.m_BufferSize = dwBufferSize;
987         VFXParam.m_pFileNameOrBuffer = pBuffer;
988
989         DWORD rgdwAxes[2];
990         rgdwAxes[0] = DIJOFS_X;
991         rgdwAxes[1] = DIJOFS_Y;
992
993         LONG rglDirection[2];
994         rglDirection[0] = DEFAULT_VFX_EFFECT_DIRECTION;
995         rglDirection[1] = 0;
996
997         DIEFFECT DIEffectStruct;
998         DIEffectStruct.dwSize                                   = sizeof(DIEFFECT);
999         DIEffectStruct.dwFlags                                  = DIEFF_OBJECTOFFSETS | DIEFF_POLAR;
1000         DIEffectStruct.dwDuration                               = DEFAULT_VFX_EFFECT_DURATION;
1001         DIEffectStruct.dwSamplePeriod                   = HZ_TO_uS(100);
1002         DIEffectStruct.dwGain                                   = DEFAULT_VFX_EFFECT_GAIN;
1003         DIEffectStruct.dwTriggerButton                  = DIEB_NOTRIGGER;
1004         DIEffectStruct.dwTriggerRepeatInterval  = 0;
1005         DIEffectStruct.cAxes                                    = 2;
1006         DIEffectStruct.rgdwAxes                                 = rgdwAxes;
1007         DIEffectStruct.rglDirection                             = rglDirection;
1008         DIEffectStruct.lpEnvelope                               = NULL;
1009         DIEffectStruct.cbTypeSpecificParams             = sizeof(VFX_PARAM);
1010         DIEffectStruct.lpvTypeSpecificParams    = &VFXParam;
1011
1012         HRESULT hResult;
1013         hResult = pDIDevice->CreateEffect(GUID_VFXEffect, &DIEffectStruct, &pVFXEffect, NULL);
1014         if(FAILED(hResult)) return hResult;
1015
1016         *ppDIEffect = pVFXEffect;
1017         return hResult;
1018
1019 #endif
1020
1021 // ----------------------------------------------------------------------------
1022 // Function:    SWFF_CreateVFXEffectFromBufferEx
1023 // Parameters:  LPDIRECTINPUTDEVICE2 pDIDevice  - IDIRECTINPUTDEVICE2 interface
1024 //                              LPDIRECTINPUTEFFECT* ppDIEffect - Receives pointer to created effect
1025 //                              LPVOID pBuffer                                  - Pointer to VFX Buffer
1026 //                              DWORD dwBufferSize                              - Buffer size in bytes
1027 //                              DWORD dwDuration                                - INFINITE or default
1028 //                              DWORD dwGain                                    - 1 to 10000
1029 //                              DWORD dwDirection                               - 0 to 35999
1030 //                              
1031 // Returns:             
1032 // Algorithm:
1033 // Comments:
1034 // Note:
1035 //              See note for SWFF_CreateVFXEffectFromBuffer(...)
1036 // ----------------------------------------------------------------------------
1037 #if 0
1038 HRESULT SWFF_CreateVFXEffectFromBufferEx(
1039         IN LPDIRECTINPUTDEVICE2 pDIDevice, 
1040         IN OUT LPDIRECTINPUTEFFECT* ppDIEffect,
1041         IN const LPVOID pBuffer,
1042         IN DWORD dwBufferSize,
1043         IN DWORD dwDuration,
1044         IN DWORD dwGain,
1045         IN DWORD dwDirection)
1046 {
1047         if(pDIDevice == NULL || ppDIEffect == NULL || pBuffer == NULL)
1048                 return SFERR_INVALID_PARAM;
1049         // Always clear return IPtr
1050         *ppDIEffect = NULL;
1051
1052         LPDIRECTINPUTEFFECT  pVFXEffect;
1053
1054         VFX_PARAM VFXParam;
1055         VFXParam.m_Bytes = sizeof(VFX_PARAM);
1056         VFXParam.m_PointerType = VFX_BUFFER;
1057         VFXParam.m_BufferSize = dwBufferSize;
1058         VFXParam.m_pFileNameOrBuffer = pBuffer;
1059
1060         DWORD rgdwAxes[2];
1061         rgdwAxes[0] = DIJOFS_X;
1062         rgdwAxes[1] = DIJOFS_Y;
1063
1064         LONG rglDirection[2];
1065         rglDirection[0] = dwDirection;
1066         rglDirection[1] = 0;
1067
1068         DIEFFECT DIEffectStruct;
1069         DIEffectStruct.dwSize                                   = sizeof(DIEFFECT);
1070         DIEffectStruct.dwFlags                                  = DIEFF_OBJECTOFFSETS | DIEFF_POLAR;
1071         DIEffectStruct.dwDuration                               = dwDuration;
1072         DIEffectStruct.dwSamplePeriod                   = HZ_TO_uS(100);
1073         DIEffectStruct.dwGain                                   = dwGain;
1074         DIEffectStruct.dwTriggerButton                  = DIEB_NOTRIGGER;
1075         DIEffectStruct.dwTriggerRepeatInterval  = 0;
1076         DIEffectStruct.cAxes                                    = 2;
1077         DIEffectStruct.rgdwAxes                                 = rgdwAxes;
1078         DIEffectStruct.rglDirection                             = rglDirection;
1079         DIEffectStruct.lpEnvelope                               = NULL;
1080         DIEffectStruct.cbTypeSpecificParams             = sizeof(VFX_PARAM);
1081         DIEffectStruct.lpvTypeSpecificParams    = &VFXParam;
1082
1083         HRESULT hResult;
1084         hResult = pDIDevice->CreateEffect(GUID_VFXEffect, &DIEffectStruct, &pVFXEffect, NULL);
1085         if(FAILED(hResult)) return hResult;
1086
1087         *ppDIEffect = pVFXEffect;
1088         return hResult;
1089
1090 #endif
1091
1092 // ----------------------------------------------------------------------------
1093 // Function:    SWFF_CreateDIEffectFromFile
1094 // Parameters:  LPDIRECTINPUTDEVICE2 pDIDevice  - IDIRECTINPUTDEVICE2 interface
1095 //                              LPDIRECTINPUTEFFECT* ppDIEffect - Receives pointer to created effect
1096 //                              TCHAR *pszFileName                              - Pointer to VFX File name
1097 //                              
1098 // Returns:             
1099 // Algorithm:
1100 // Comments:
1101 // Note:                If the file contains multiple effects or a custom effect this
1102 //                              function will fail. Use SWFF_CreateDIEffectFromFileEx.
1103 // ----------------------------------------------------------------------------
1104 #if 0
1105 HRESULT SWFF_CreateDIEffectFromFile(
1106         IN LPDIRECTINPUTDEVICE2 pDIDevice, 
1107         IN OUT LPDIRECTINPUTEFFECT* ppDIEffect,
1108         IN const TCHAR *pszFileName)
1109 {
1110         HRESULT hResult;
1111         PVFX pIVFX;
1112
1113         if(pDIDevice == NULL || pszFileName == NULL || ppDIEffect == NULL)
1114                 return SFERR_INVALID_PARAM;
1115
1116         *ppDIEffect = NULL;
1117
1118         hResult = CoInitialize(NULL);
1119         if(FAILED(hResult))
1120                 return hResult;
1121
1122         hResult = CoCreateInstance(CLSID_VFX, 
1123                                 NULL, 
1124                                 CLSCTX_INPROC_SERVER,
1125                                 IID_IVFX,
1126                                 (void**)&pIVFX);
1127         if(pIVFX == NULL)
1128         {
1129                 CoUninitialize();
1130                 return SFERR_SYSTEM_INIT;
1131         }
1132         
1133         if(FAILED(hResult))
1134         {
1135                 CoUninitialize();
1136                 return hResult;
1137         }
1138
1139         // Create the Effect from a *.frc file
1140         DWORD dwInFlags = VFXCE_CREATE_SINGLE;
1141         hResult = pIVFX->CreateEffectFromFile(pDIDevice, ppDIEffect,
1142                                 0, pszFileName, NULL, NULL, dwInFlags, NULL);
1143
1144         // clean up
1145         pIVFX->Release();
1146         CoUninitialize();
1147
1148         if(FAILED(hResult)) return hResult;
1149
1150         return hResult;
1151 }
1152 #endif
1153
1154 // ----------------------------------------------------------------------------
1155 // Function:    SWFF_CreateDIEffectFromFileEx
1156 // Parameters:  LPDIRECTINPUTDEVICE2 pDIDevice  - IDIRECTINPUTDEVICE2 interface
1157 //                              LPDIRECTINPUTEFFECT** pppDIEffect       - Pointer to an array of 
1158 //                                                                                                              LPDIRECTINPUTEFFECT's.
1159 //                                                                                                              This array is allocated
1160 //                                                                                                              by the function.  Caller is
1161 //                                                                                                              responsible for deleting.
1162 //                              PDWORD pdwEffectCount                   - Gets the number of effects in array
1163 //                              TCHAR *pszFileName                              - Pointer to VFX File name
1164 //                              PPVOID ppUDBuffer                               - Gets an array containing custom force 
1165 //                                                                                                      samples.  This array is allocated by
1166 //                                                                                                      the function.  Caller is 
1167 //                                                                                                      responsible for deleting.
1168 //                              PDWORD pdwOutFlags                              - Receives 0 if the file contains
1169 //                                                                                                      a single effect.  Otherwise
1170 //                                                                                                      it receives VFXCE_CONCATENATE
1171 //                                                                                                      or VFXCE_SUPERIMPOSE.
1172 //                              
1173 // Returns:             
1174 // Algorithm:
1175 // Comments:
1176 // Note:        call delete [] pppDIEffect and delete [] ppUDBuffer after
1177 //                      releasing the effects
1178 // ----------------------------------------------------------------------------
1179 #if 0
1180 HRESULT SWFF_CreateDIEffectFromFileEx(
1181         IN LPDIRECTINPUTDEVICE2 pDIDevice, 
1182         IN OUT LPDIRECTINPUTEFFECT** pppDIEffect,
1183         IN OUT PDWORD pdwEffectCount,
1184         IN const TCHAR *pszFileName,
1185         IN OUT void** ppUDBuffer,
1186         IN OUT PDWORD pdwOutFlags)
1187 {
1188         // parameter check
1189         if(pDIDevice == NULL || pszFileName == NULL || pppDIEffect == NULL || 
1190                 pdwEffectCount == NULL || ppUDBuffer == NULL || pdwOutFlags == NULL)
1191         {
1192                 return SFERR_INVALID_PARAM;
1193         }
1194
1195         // zero out the return values
1196         *pppDIEffect = NULL;
1197         *pdwEffectCount = 0;
1198         *ppUDBuffer = NULL;
1199         *pdwOutFlags = 0;
1200
1201         HRESULT hResult;
1202         PVFX pIVFX;
1203
1204         hResult = CoInitialize(NULL);
1205         if(FAILED(hResult))
1206                 return hResult;
1207
1208         hResult = CoCreateInstance(CLSID_VFX, 
1209                                 NULL, 
1210                                 CLSCTX_INPROC_SERVER,
1211                                 IID_IVFX,
1212                                 (void**)&pIVFX);
1213         if(pIVFX == NULL)
1214         {
1215                 CoUninitialize();
1216                 return SFERR_SYSTEM_INIT;
1217         }
1218         
1219         if(FAILED(hResult))
1220         {
1221                 CoUninitialize();
1222                 return hResult;
1223         }
1224
1225         // see how big a DIEffect array we have to allocate, and see how much memory, if any, 
1226         // we need to allocate for UD sample caching
1227         DWORD dwInFlags = VFXCE_CALC_BUFFER_SIZE | VFXCE_CALC_EFFECT_COUNT;
1228         DWORD dwEffectCount;
1229         DWORD dwBufferSize;
1230         hResult = pIVFX->CreateEffectFromFile(NULL, NULL,
1231                                 &dwEffectCount, pszFileName, NULL, &dwBufferSize, dwInFlags, NULL);
1232         if(FAILED(hResult))
1233         {
1234                 pIVFX->Release();
1235                 CoUninitialize();
1236                 return hResult;
1237         }
1238
1239         // allocate memory for the effects
1240         LPDIRECTINPUTEFFECT* ppDIEffect = new LPDIRECTINPUTEFFECT[dwEffectCount];
1241         if(ppDIEffect == NULL)
1242         {
1243                 pIVFX->Release();
1244                 CoUninitialize();
1245                 return DIERR_OUTOFMEMORY;
1246         }
1247
1248         // allocate memory for the custom force samples
1249         PVOID pUDBuffer = NULL;
1250         if(dwBufferSize > 0)
1251         {
1252                 pUDBuffer = new BYTE[dwBufferSize];
1253                 if(pUDBuffer == NULL)
1254                 {
1255                         delete [] ppDIEffect;
1256                         ppDIEffect = NULL;
1257                         pIVFX->Release();
1258                         CoUninitialize();
1259                         return DIERR_OUTOFMEMORY;
1260                 }
1261         }
1262
1263         // Create the Effect from a *.frc file
1264         DWORD dwOutFlags;
1265         dwInFlags = VFXCE_CREATE_MULTIPLE;
1266         hResult = pIVFX->CreateEffectFromFile(pDIDevice, ppDIEffect,
1267                                 &dwEffectCount, pszFileName, pUDBuffer, &dwBufferSize, dwInFlags, &dwOutFlags);
1268
1269         if(FAILED(hResult))
1270         {
1271                 delete [] ppDIEffect;
1272                 ppDIEffect = NULL;
1273                 delete [] pUDBuffer;
1274                 pUDBuffer = NULL;
1275                 pIVFX->Release();
1276                 CoUninitialize();
1277                 return hResult;
1278         }
1279
1280         // clean up
1281         pIVFX->Release();
1282         CoUninitialize();
1283
1284         if(FAILED(hResult)) return hResult;
1285
1286         // assign the results
1287         *pppDIEffect = ppDIEffect;
1288         *pdwEffectCount = dwEffectCount;
1289         *ppUDBuffer = pUDBuffer;
1290         *pdwOutFlags = dwOutFlags;
1291
1292         return hResult;
1293 }
1294 #endif
1295
1296 // ----------------------------------------------------------------------------
1297 // Function:    SWFF_CreateDIEffectFromBuffer
1298 // Parameters:  LPDIRECTINPUTDEVICE2 pDIDevice  - IDIRECTINPUTDEVICE2 interface
1299 //                              LPDIRECTINPUTEFFECT* ppDIEffect - Receives pointer to created effect
1300 //                              LPVOID pBuffer                                  - Pointer to VFX Buffer
1301 //                              DWORD dwBufferSize                              - Buffer size in bytes
1302 //                              
1303 // Returns:             
1304 // Algorithm:
1305 // Comments:
1306 // Note:                If the file contains multiple effects or a custom effect this
1307 //                              function will fail. Use SWFF_CreateDIEffectFromBufferEx.
1308 // ----------------------------------------------------------------------------
1309 #if 0
1310 HRESULT SWFF_CreateDIEffectFromBuffer(
1311         IN LPDIRECTINPUTDEVICE2 pDIDevice, 
1312         IN OUT LPDIRECTINPUTEFFECT* ppDIEffect,
1313         IN const LPVOID pBuffer,
1314         IN DWORD dwBufferSize)
1315 {
1316         HRESULT hResult;
1317         PVFX pIVFX;
1318
1319         if(pDIDevice == NULL || pBuffer == NULL || ppDIEffect == NULL)
1320                 return SFERR_INVALID_PARAM;
1321
1322         *ppDIEffect = NULL;
1323
1324         hResult = CoInitialize(NULL);
1325         if(FAILED(hResult))
1326                 return hResult;
1327
1328         hResult = CoCreateInstance(CLSID_VFX, 
1329                                 NULL, 
1330                                 CLSCTX_INPROC_SERVER,
1331                                 IID_IVFX,
1332                                 (void**)&pIVFX);
1333         if(pIVFX == NULL)
1334         {
1335                 CoUninitialize();
1336                 return SFERR_SYSTEM_INIT;
1337         }
1338         
1339         if(FAILED(hResult))
1340         {
1341                 CoUninitialize();
1342                 return hResult;
1343         }
1344
1345         // Create the Effect from a *.frc file
1346         DWORD dwInFlags = VFXCE_CREATE_SINGLE;
1347         hResult = pIVFX->CreateEffectFromBuffer(pDIDevice, ppDIEffect,
1348                                 0, pBuffer, dwBufferSize, NULL, NULL, dwInFlags, NULL);
1349
1350         // clean up
1351         pIVFX->Release();
1352         CoUninitialize();
1353
1354         if(FAILED(hResult)) return hResult;
1355
1356         return hResult;
1357 }
1358 #endif
1359
1360 // ----------------------------------------------------------------------------
1361 // Function:    SWFF_CreateDIEffectFromBufferEx
1362 // Parameters:  LPDIRECTINPUTDEVICE2 pDIDevice  - Pointer to DirectInputDevice
1363 //                              LPDIRECTINPUTEFFECT** pppDIEffect       - Pointer to an array of 
1364 //                                                                                                              LPDIRECTINPUTEFFECT's.
1365 //                                                                                                              This array is allocated
1366 //                                                                                                              by the function.  Caller is
1367 //                                                                                                              responsible for deleting.
1368 //                              PDWORD pdwEffectCount                   - Gets the number of effects in array
1369 //                              LPVOID pBuffer                                  - Pointer to VFX Buffer
1370 //                              DWORD dwBufferSize                              - Buffer size in bytes
1371 //                              PPVOID ppUDBuffer                               - Gets an array containing custom force 
1372 //                                                                                                      samples.  This array is allocated by
1373 //                                                                                                      the function.  Caller is 
1374 //                                                                                                      responsible for deleting.
1375 //                              PDWORD pdwOutFlags                              - Receives 0 if the file contains
1376 //                                                                                                      a single effect.  Otherwise
1377 //                                                                                                      it receives VFXCE_CONCATENATE
1378 //                                                                                                      or VFXCE_SUPERIMPOSE.
1379 //                              
1380 // Returns:             
1381 // Algorithm:
1382 // Comments:
1383 // Note:        call delete [] pppDIEffect and delete [] ppUDBuffer after
1384 //                      releasing the effects
1385 // ----------------------------------------------------------------------------
1386 #if 0
1387 HRESULT SWFF_CreateDIEffectFromBufferEx(
1388         IN LPDIRECTINPUTDEVICE2 pDIDevice, 
1389         IN OUT LPDIRECTINPUTEFFECT** pppDIEffect,
1390         IN OUT PDWORD pdwEffectCount,
1391         IN const LPVOID pBuffer,
1392         IN DWORD dwBufferSize,
1393         IN OUT void** ppUDBuffer,
1394         IN OUT PDWORD pdwOutFlags)
1395 {
1396         // parameter check
1397         if(pDIDevice == NULL || pBuffer == NULL || pppDIEffect == NULL|| 
1398                 pdwEffectCount == NULL || ppUDBuffer == NULL || pdwOutFlags == NULL)
1399         {
1400                 return SFERR_INVALID_PARAM;
1401         }
1402
1403         // zero out the return values
1404         *pppDIEffect = NULL;
1405         *pdwEffectCount = 0;
1406         *ppUDBuffer = NULL;
1407         *pdwOutFlags = 0;
1408
1409         HRESULT hResult;
1410         PVFX pIVFX;
1411
1412
1413
1414         hResult = CoInitialize(NULL);
1415         if(FAILED(hResult))
1416                 return hResult;
1417
1418         hResult = CoCreateInstance(CLSID_VFX, 
1419                                 NULL, 
1420                                 CLSCTX_INPROC_SERVER,
1421                                 IID_IVFX,
1422                                 (void**)&pIVFX);
1423         if(pIVFX == NULL)
1424         {
1425                 CoUninitialize();
1426                 return SFERR_SYSTEM_INIT;
1427         }
1428         
1429         if(FAILED(hResult))
1430         {
1431                 CoUninitialize();
1432                 return hResult;
1433         }
1434
1435         // see how big a DIEffect array we have to allocate, and see how much memory, if any, 
1436         // we need to allocate for UD sample caching
1437         DWORD dwInFlags = VFXCE_CALC_BUFFER_SIZE | VFXCE_CALC_EFFECT_COUNT;
1438         DWORD dwEffectCount;
1439         DWORD dwUDBufferSize;
1440         hResult = pIVFX->CreateEffectFromBuffer(NULL, NULL,
1441                                 &dwEffectCount, pBuffer, dwBufferSize, NULL, &dwUDBufferSize, dwInFlags, NULL);
1442         if(FAILED(hResult))
1443         {
1444                 pIVFX->Release();
1445                 CoUninitialize();
1446                 return  hResult;
1447         }
1448
1449         // allocate memory for the effects
1450         LPDIRECTINPUTEFFECT* ppDIEffect = new LPDIRECTINPUTEFFECT[dwEffectCount];
1451         if(ppDIEffect == NULL)
1452         {
1453                 pIVFX->Release();
1454                 CoUninitialize();
1455                 return DIERR_OUTOFMEMORY;
1456         }
1457
1458         // allocate memory for the custom force samples
1459         PVOID pUDBuffer = NULL;
1460         if(dwUDBufferSize > 0)
1461         {
1462                 pUDBuffer = new BYTE[dwUDBufferSize];
1463                 if(pUDBuffer == NULL)
1464                 {
1465                         delete [] ppDIEffect;
1466                         ppDIEffect = NULL;
1467                         pIVFX->Release();
1468                         CoUninitialize();
1469                         return DIERR_OUTOFMEMORY;
1470                 }
1471         }
1472
1473         // Create the Effect from a *.frc file
1474         DWORD dwOutFlags;
1475         dwInFlags = VFXCE_CREATE_MULTIPLE;
1476         hResult = pIVFX->CreateEffectFromBuffer(pDIDevice, ppDIEffect,
1477                                 &dwEffectCount, pBuffer, dwBufferSize, pUDBuffer, &dwUDBufferSize, dwInFlags, &dwOutFlags);
1478
1479         if(FAILED(hResult))
1480         {
1481                 delete [] ppDIEffect;
1482                 ppDIEffect = NULL;
1483                 delete [] pUDBuffer;
1484                 pUDBuffer = NULL;
1485                 pIVFX->Release();
1486                 CoUninitialize();
1487                 return hResult;
1488         }
1489
1490         // clean up
1491         pIVFX->Release();
1492         CoUninitialize();
1493
1494         if(FAILED(hResult)) return hResult;
1495
1496         // assign the results
1497         *pppDIEffect = ppDIEffect;
1498         *pdwEffectCount = dwEffectCount;
1499         *ppUDBuffer = pUDBuffer;
1500         *pdwOutFlags = dwOutFlags;
1501
1502         return hResult;
1503 }
1504 #endif
1505
1506 // ----------------------------------------------------------------------------
1507 // Function:    SWFF_CreatePeriodicEffect
1508 // Purpose:             Creates a Periodic type Effect with specified params
1509 // Parameters:  LPDIRECTINPUTDEVICE2 pDIDevice  - IDIRECTINPUTDEVICE2 interface
1510 //                              LPDIRECTINPUTEFFECT* ppDIEffect - Receives pointer to created effect
1511 //                              DWORD dwType                    - Type of PERIODIC Effect (SINE | COSINE | ...)
1512 //                              DWORD dwDuration                - uS
1513 //                              DWORD dwPeriod                  - uS
1514 //                              DWORD dwDirection               - 0 to 35999
1515 //                              DWORD dwMagnitude               - 0 to 10000
1516 //                              LONG lOffset                    - Offset in -10000 to 10000
1517 //                              DWORD dwAttackTime              - Envelope Attack Time in uS
1518 //                              DWORD dwAttackLevel             - Envelope Attack Level in 0 to 10000
1519 //                              DWORD dwFadeTime                - Envelope Fade time in uS
1520 //                              DWORD dwFadeLevel               - Envelope Fade Level
1521 //                              LONG lButton                    - Index of playback button, -1 for none
1522 //
1523 // Returns:
1524 // Algorithm:   
1525 // Comments:
1526 // 
1527 // ----------------------------------------------------------------------------
1528 HRESULT SWFF_CreatePeriodicEffect(      IN LPDIRECTINPUTDEVICE2 pDIDevice,
1529                                                                 IN OUT LPDIRECTINPUTEFFECT* ppDIEffect,
1530                                                                 IN DWORD dwType,
1531                                                                 IN DWORD dwDuration,            
1532                                                                 IN DWORD dwPeriod,                      
1533                                                                 IN DWORD dwDirection,           
1534                                                                 IN DWORD dwMagnitude,           
1535                                                                 IN LONG lOffset,                        
1536                                                                 IN DWORD dwAttackTime,          
1537                                                                 IN DWORD dwAttackLevel,         
1538                                                                 IN DWORD dwFadeTime,            
1539                                                                 IN DWORD dwFadeLevel,           
1540                                                                 IN LONG lButton)                        
1541 {
1542         if(pDIDevice == NULL || ppDIEffect == NULL)
1543                 return SFERR_INVALID_PARAM;
1544         // Always clear return IPtr
1545         *ppDIEffect = NULL;
1546
1547         // type-specific stuff
1548         DWORD dwPhase = 0;
1549         GUID guid;
1550         switch(dwType)
1551         {
1552                 case SINE:
1553                         guid = GUID_Sine;
1554                         break;
1555                 case COSINE:
1556                         guid = GUID_Sine;
1557                         dwPhase = 9000;
1558                         break;
1559                 case SQUARE_HIGH:
1560                         guid = GUID_Square;
1561                         break;
1562                 case SQUARE_LOW:
1563                         guid = GUID_Square;
1564                         dwPhase = 18000;
1565                         break;
1566                 case TRIANGLE_UP:
1567                         guid = GUID_Triangle;
1568                         break;
1569                 case TRIANGLE_DOWN:
1570                         guid = GUID_Triangle;
1571                         dwPhase = 18000;
1572                         break;
1573                 case SAWTOOTH_UP:
1574                         guid = GUID_SawtoothUp;
1575                         break;
1576                 case SAWTOOTH_DOWN:
1577                         guid = GUID_SawtoothDown;
1578                         break;
1579                 default:
1580                         // illegal
1581                         break;
1582         }
1583
1584         DIPERIODIC DIPeriodicStruct;
1585         DIPeriodicStruct.dwMagnitude = dwMagnitude;
1586         DIPeriodicStruct.lOffset = lOffset;
1587         DIPeriodicStruct.dwPhase = dwPhase;
1588         DIPeriodicStruct.dwPeriod = dwPeriod;
1589
1590         DIENVELOPE DIEnvelopeStruct;
1591         DIEnvelopeStruct.dwSize = sizeof(DIENVELOPE);
1592         DIEnvelopeStruct.dwAttackTime = dwAttackTime;
1593         DIEnvelopeStruct.dwAttackLevel = dwAttackLevel;
1594         DIEnvelopeStruct.dwFadeTime = dwFadeTime;
1595         DIEnvelopeStruct.dwFadeLevel = dwFadeLevel;
1596
1597         DWORD rgdwAxes[2];
1598         rgdwAxes[0] = DIJOFS_X;
1599         rgdwAxes[1] = DIJOFS_Y;
1600
1601         LONG rglDirection[2];
1602         rglDirection[0] = dwDirection;
1603         rglDirection[1] = 0;
1604
1605         DIEFFECT DIEffectStruct;
1606         DIEffectStruct.dwSize                                   = sizeof(DIEFFECT);
1607         DIEffectStruct.dwFlags                                  = DIEFF_OBJECTOFFSETS | DIEFF_POLAR;
1608         DIEffectStruct.dwDuration                               = dwDuration;
1609         DIEffectStruct.dwSamplePeriod                   = HZ_TO_uS(100);
1610         DIEffectStruct.dwGain                                   = 10000;
1611         DIEffectStruct.dwTriggerButton                  = lButton == -1 ? DIEB_NOTRIGGER : FIELD_OFFSET(DIJOYSTATE, rgbButtons) + lButton;
1612         DIEffectStruct.dwTriggerRepeatInterval  = 0;
1613         DIEffectStruct.cAxes                                    = 2;
1614         DIEffectStruct.rgdwAxes                                 = rgdwAxes;
1615         DIEffectStruct.rglDirection                             = rglDirection;
1616         DIEffectStruct.lpEnvelope                               = &DIEnvelopeStruct;
1617         DIEffectStruct.cbTypeSpecificParams             = sizeof(DIPeriodicStruct);
1618         DIEffectStruct.lpvTypeSpecificParams    = &DIPeriodicStruct;
1619
1620         HRESULT hResult;
1621         hResult = pDIDevice->CreateEffect(guid, &DIEffectStruct, ppDIEffect, NULL);
1622
1623         return hResult;
1624 }
1625
1626 // ----------------------------------------------------------------------------
1627 // Function:    SWFF_CreateSpringEffect
1628 // Purpose:             Creates a Spring type Effect with specified params
1629 // Parameters:  LPDIRECTINPUTDEVICE2 pDIDevice  - IDIRECTINPUTDEVICE2 interface
1630 //                              LPDIRECTINPUTEFFECT* ppDIEffect - Receives pointer to created effect
1631 //                              DWORD dwDuration                                - Duration in uS
1632 //                              LONG lKx                                                - X-Axis K Coefficient in -10000 to 10000
1633 //                              LONG lCenterx                                   - X-Axis Center in -10000 to 10000
1634 //                              LONG lKy                                                - Y-Axis K Coefficient in -10000 to 10000
1635 //                              LONG lCentery                                   - Y-Axis Center in -10000 to 10000
1636 //                              LONG lButton                                    - Index of playback button, -1 for none
1637 //
1638 // Returns:
1639 // Algorithm:   
1640 // Comments:
1641 //                      To create a 1D spring, set the lKx or lKy parameter to 0
1642 //                      To create a 2D spring, set both lKx and lKy parameter to non-zero
1643 //                              or set both lFx and lFy to zero
1644 //  
1645 // ----------------------------------------------------------------------------
1646 HRESULT SWFF_CreateSpringEffect(        IN LPDIRECTINPUTDEVICE2 pDIDevice,
1647                                                         IN OUT LPDIRECTINPUTEFFECT* ppDIEffect,
1648                                                         IN DWORD dwDuration,
1649                                                         IN LONG lKx,
1650                                                         IN LONG lCenterx,
1651                                                         IN LONG lKy,
1652                                                         IN LONG lCentery,
1653                                                         IN LONG lButton)
1654 {
1655         if(pDIDevice == NULL || ppDIEffect == NULL)
1656                 return SFERR_INVALID_PARAM;
1657         
1658         // Always clear return IPtr
1659         *ppDIEffect = NULL;
1660
1661         HRESULT hResult = SWFF_CreateConditionEffect(pDIDevice,
1662                                                                                         ppDIEffect,
1663                                                                                         SPRING,
1664                                                                                         dwDuration,
1665                                                                                         lKx, lCenterx,
1666                                                                                         lKy, lCentery,
1667                                                                                         lButton);
1668
1669         return hResult;
1670 }
1671
1672 // ----------------------------------------------------------------------------
1673 // Function:    SWFF_CreateDamperEffect
1674 // Purpose:             Creates a Damper type Effect with specified params
1675 // Parameters:  LPDIRECTINPUTDEVICE2 pDIDevice  - IDIRECTINPUTDEVICE2 interface
1676 //                              LPDIRECTINPUTEFFECT* ppDIEffect - Receives pointer to created effect
1677 //                              DWORD dwDuration                                - Duration in uS
1678 //                              LONG lBx                                                - X-Axis B Coefficient +/-10000
1679 //                              LONG lV0x                                               - X-Axis Initial Velocity +/-10000
1680 //                              LONG lBy                                                - Y-Axis B Coefficient +/-10000
1681 //                              LONG lV0y                                               - Y-Axis Initial Velocity +/-10000
1682 //                              LONG lButton                                    - Index of playback button, -1 for none
1683 // Returns:
1684 // Algorithm:   
1685 // Comments:
1686 //                      To create a 1D Damper, set the lBx or lBy parameter to 0
1687 //                      To create a 2D Damper, set both lBx and lBy parameter to non-zero
1688 //                              or set both lFx and lFy to zero
1689 // 
1690 // ----------------------------------------------------------------------------
1691 HRESULT SWFF_CreateDamperEffect(
1692         IN LPDIRECTINPUTDEVICE2 pDIDevice,
1693         IN OUT LPDIRECTINPUTEFFECT* ppDIEffect,
1694         IN DWORD dwDuration,
1695         IN LONG lBx,
1696         IN LONG lV0x,
1697         IN LONG lBy,
1698         IN LONG lV0y,
1699         IN LONG lButton)
1700 {
1701         if(pDIDevice == NULL || ppDIEffect == NULL)
1702                 return SFERR_INVALID_PARAM;
1703         
1704         // Always clear return IPtr
1705         *ppDIEffect = NULL;
1706
1707         HRESULT hResult = SWFF_CreateConditionEffect(pDIDevice,
1708                                                                                         ppDIEffect,
1709                                                                                         DAMPER,
1710                                                                                         dwDuration,
1711                                                                                         lBx, lV0x,
1712                                                                                         lBy, lV0y,
1713                                                                                         lButton);
1714
1715         return hResult;
1716 }
1717
1718
1719 // ----------------------------------------------------------------------------
1720 // Function:    SWFF_CreateInertiaEffect
1721 // Purpose:             Creates an Inertia type Effect with specified params
1722 // Parameters:  LPDIRECTINPUTDEVICE2 pDIDevice  - IDIRECTINPUTDEVICE2 interface
1723 //                              LPDIRECTINPUTEFFECT* ppDIEffect - Receives pointer to created effect
1724 //                              DWORD dwDuration                                - Duration in uS
1725 //                              LONG lMx                                                - X-Axis M Coefficient +/-10000
1726 //                              LONG lA0x                                               - X-Axis Initial Acceleration +/-10000
1727 //                              LONG lMy                                                - Y-Axis N Coefficient +/-10000
1728 //                              LONG lA0y                                               - Y-Axis Initial Acceleration +/-10000
1729 //                              LONG lButton                                    - Index of playback button, -1 for none
1730 // Returns:
1731 // Algorithm:   
1732 // Comments:
1733 //                      To create a 1D Inertia, set the lMx or lMy parameter to 0
1734 //                      To create a 2D Inertia, set both lMx and lMy parameter to non-zero
1735 //                              or set both lFx and lFy to zero
1736 // 
1737 // ----------------------------------------------------------------------------
1738 HRESULT SWFF_CreateInertiaEffect(
1739         IN LPDIRECTINPUTDEVICE2 pDIDevice,
1740         IN OUT LPDIRECTINPUTEFFECT* ppDIEffect,
1741         IN DWORD dwDuration,
1742         IN LONG lMx,
1743         IN LONG lA0x,
1744         IN LONG lMy,
1745         IN LONG lA0y,
1746         IN LONG lButton)
1747 {
1748         if(pDIDevice == NULL || ppDIEffect == NULL)
1749                 return SFERR_INVALID_PARAM;
1750         
1751         // Always clear return IPtr
1752         *ppDIEffect = NULL;
1753
1754         HRESULT hResult = SWFF_CreateConditionEffect(pDIDevice,
1755                                                                                         ppDIEffect,
1756                                                                                         INERTIA,
1757                                                                                         dwDuration,
1758                                                                                         lMx, lA0x,
1759                                                                                         lMy, lA0y,
1760                                                                                         lButton);
1761
1762         return hResult;
1763 }
1764
1765 // ----------------------------------------------------------------------------
1766 // Function:    SWFF_CreateFrictionEffect
1767 // Purpose:             Creates a Friction type Effect with specified params
1768 // Parameters:  LPDIRECTINPUTDEVICE2 pDIDevice  - IDIRECTINPUTDEVICE2 interface
1769 //                              LPDIRECTINPUTEFFECT* ppDIEffect - Receives pointer to created effect
1770 //                              DWORD dwDuration                                - Duration in uS
1771 //                              LONG lFx                                                - X-Axis F Coefficient +/-10000
1772 //                              LONG lFy                                                - Y-Axis F Coefficient +/-10000
1773 //                              LONG lButton                                    - Index of playback button, -1 for none
1774 // Returns:
1775 // Algorithm:   
1776 // Comments:
1777 //                      To create a 1D Friction, set the lFx or lFy parameter to 0
1778 //                      To create a 2D Friction, set both lFx and lFy parameter to non-zero
1779 //                              or set both lFx and lFy to zero
1780 // 
1781 // ----------------------------------------------------------------------------
1782 HRESULT SWFF_CreateFrictionEffect(
1783         IN LPDIRECTINPUTDEVICE2 pDIDevice,
1784         IN OUT LPDIRECTINPUTEFFECT* ppDIEffect,
1785         IN DWORD dwDuration,
1786         IN LONG lFx,
1787         IN LONG lFy,
1788         IN LONG lButton)
1789 {
1790         if(pDIDevice == NULL || ppDIEffect == NULL)
1791                 return SFERR_INVALID_PARAM;
1792         
1793         // Always clear return IPtr
1794         *ppDIEffect = NULL;
1795
1796         HRESULT hResult = SWFF_CreateConditionEffect(pDIDevice,
1797                                                                                         ppDIEffect,
1798                                                                                         FRICTION,
1799                                                                                         dwDuration,
1800                                                                                         lFx, 0,
1801                                                                                         lFy, 0,
1802                                                                                         lButton);
1803
1804         return hResult;
1805 }
1806
1807 HRESULT SWFF_CreateConditionEffectStruct(
1808         di_condition_effect_struct *ptr,
1809         IN LPDIRECTINPUTDEVICE2 pDIDevice,
1810         IN OUT LPDIRECTINPUTEFFECT* ppDIEffect,
1811         IN DWORD dwType,
1812         IN DWORD dwDuration,
1813         IN LONG lXCoefficient,
1814         IN LONG lXOffset,
1815         IN LONG lYCoefficient,
1816         IN LONG lYOffset,
1817         IN LONG lButton)
1818 {
1819         if(pDIDevice == NULL || ppDIEffect == NULL)
1820                 return SFERR_INVALID_PARAM;
1821
1822         // Always clear return IPtr
1823         *ppDIEffect = NULL;
1824
1825         GUID guid;
1826         switch(dwType)
1827         {
1828                 case SPRING:
1829                         guid = GUID_Spring;
1830                         break;
1831                 case INERTIA:
1832                         guid = GUID_Inertia;
1833                         break;
1834                 case DAMPER:
1835                         guid = GUID_Damper;
1836                         break;
1837                 case FRICTION:
1838                         guid = GUID_Friction;
1839                         break;
1840                 default:
1841                         break;
1842         }
1843
1844         ptr->DIConditionStruct[0].lOffset                               = lXOffset;
1845         ptr->DIConditionStruct[0].lPositiveCoefficient  = lXCoefficient;
1846         ptr->DIConditionStruct[0].lNegativeCoefficient  = lXCoefficient;
1847         ptr->DIConditionStruct[0].dwPositiveSaturation  = 10000;
1848         ptr->DIConditionStruct[0].dwNegativeSaturation  = 10000;
1849         ptr->DIConditionStruct[0].lDeadBand                             = 0;
1850         ptr->DIConditionStruct[1].lOffset                               = lYOffset;
1851         ptr->DIConditionStruct[1].lPositiveCoefficient  = lYCoefficient;
1852         ptr->DIConditionStruct[1].lNegativeCoefficient  = lYCoefficient;
1853         ptr->DIConditionStruct[1].dwPositiveSaturation  = 10000;
1854         ptr->DIConditionStruct[1].dwNegativeSaturation  = 10000;
1855         ptr->DIConditionStruct[1].lDeadBand                             = 0;
1856
1857         DWORD rgdwAxes[2];
1858         int nAxisCount = 0;
1859         if(lXCoefficient != 0)
1860         {
1861                 rgdwAxes[nAxisCount] = DIJOFS_X;
1862                 nAxisCount++;
1863         }
1864
1865         if(lYCoefficient != 0)
1866         {
1867                 rgdwAxes[nAxisCount] = DIJOFS_Y;
1868                 nAxisCount++;
1869         }
1870
1871         if(lXCoefficient == 0 && lYCoefficient == 0)
1872         {
1873                 nAxisCount = 2;
1874                 rgdwAxes[0] = DIJOFS_X;
1875                 rgdwAxes[1] = DIJOFS_Y;
1876         }
1877
1878         DWORD cbTypeSpecificParams;
1879         PVOID pvTypeSpecificParams;
1880
1881         if (nAxisCount == 1) {
1882                 cbTypeSpecificParams = sizeof(DICONDITION[1]);
1883                 if (lXCoefficient)
1884                         pvTypeSpecificParams = &ptr->DIConditionStruct[0];
1885                 else
1886                         pvTypeSpecificParams = &ptr->DIConditionStruct[1];
1887
1888         } else {
1889                 cbTypeSpecificParams = sizeof(DICONDITION[2]);
1890                 pvTypeSpecificParams = &ptr->DIConditionStruct[0];
1891         }
1892
1893         ptr->rglDirection[0] = 0;
1894         ptr->rglDirection[1] = 0;
1895
1896         ptr->DIEffectStruct.dwSize                                      = sizeof(DIEFFECT);
1897         ptr->DIEffectStruct.dwFlags                                     = DIEFF_OBJECTOFFSETS | DIEFF_CARTESIAN;
1898         ptr->DIEffectStruct.dwDuration                          = dwDuration;
1899         ptr->DIEffectStruct.dwSamplePeriod                      = HZ_TO_uS(100);
1900         ptr->DIEffectStruct.dwGain                                      = 10000;
1901         ptr->DIEffectStruct.dwTriggerButton                     = lButton == -1 ? DIEB_NOTRIGGER : FIELD_OFFSET(DIJOYSTATE, rgbButtons) + lButton;
1902         ptr->DIEffectStruct.dwTriggerRepeatInterval     = 0;
1903         ptr->DIEffectStruct.cAxes                                       = nAxisCount;
1904         ptr->DIEffectStruct.rgdwAxes                                    = rgdwAxes;
1905         ptr->DIEffectStruct.rglDirection                                = ptr->rglDirection;
1906         ptr->DIEffectStruct.lpEnvelope                          = NULL;
1907         ptr->DIEffectStruct.cbTypeSpecificParams                = cbTypeSpecificParams;
1908         ptr->DIEffectStruct.lpvTypeSpecificParams       = pvTypeSpecificParams;
1909
1910         HRESULT hResult;
1911         hResult = pDIDevice->CreateEffect(guid, &ptr->DIEffectStruct, ppDIEffect, NULL);
1912
1913         return hResult;
1914 }
1915
1916 // ----------------------------------------------------------------------------
1917 // Function:    SWFF_CreateConditionEffect
1918 // Purpose:             Creates a Condition type Effect with specified params
1919 // Parameters:  LPDIRECTINPUTDEVICE2 pDIDevice  - IDIRECTINPUTDEVICE2 interface
1920 //                              LPDIRECTINPUTEFFECT* ppDIEffect - Receives pointer to created effect
1921 //                              DWORD dwType                                    - SPRING | INERTIA | DAMPER | FRICTION
1922 //                              DWORD dwDuration                                - Duration in uS
1923 //                              LONG lXCoefficient                              - Coefficient in -10000 to 10000
1924 //                              LONG lXOffset                                   - Offset in -10000 to 10000
1925 //                              LONG lYCoefficient                              - Coefficient in -10000 to 10000
1926 //                              LONG lYOffset                                   - Offset in -10000 to 10000
1927 //                              LONG lButton                                    - Index of playback button, -1 for none
1928 // Returns:
1929 // Algorithm:   
1930 // Comments:
1931 //                      To create a 1D Friction, set the lFx or lFy parameter to 0
1932 //                      To create a 2D Friction, set both lFx and lFy parameter to non-zero
1933 //                              or set both lFx and lFy to zero
1934 // 
1935 // ----------------------------------------------------------------------------
1936 HRESULT SWFF_CreateConditionEffect(     
1937         IN LPDIRECTINPUTDEVICE2 pDIDevice,
1938         IN OUT LPDIRECTINPUTEFFECT* ppDIEffect,
1939         IN DWORD dwType,
1940         IN DWORD dwDuration,
1941         IN LONG lXCoefficient,
1942         IN LONG lXOffset,
1943         IN LONG lYCoefficient,
1944         IN LONG lYOffset,
1945         IN LONG lButton)
1946 {
1947         if(pDIDevice == NULL || ppDIEffect == NULL)
1948                 return SFERR_INVALID_PARAM;
1949
1950         // Always clear return IPtr
1951         *ppDIEffect = NULL;
1952
1953         GUID guid;
1954         switch(dwType)
1955         {
1956                 case SPRING:
1957                         guid = GUID_Spring;
1958                         break;
1959                 case INERTIA:
1960                         guid = GUID_Inertia;
1961                         break;
1962                 case DAMPER:
1963                         guid = GUID_Damper;
1964                         break;
1965                 case FRICTION:
1966                         guid = GUID_Friction;
1967                         break;
1968                 default:
1969                         break;
1970         }
1971
1972         DICONDITION DIConditionStruct[2];
1973         DIConditionStruct[0].lOffset                            = lXOffset;
1974         DIConditionStruct[0].lPositiveCoefficient       = lXCoefficient;
1975         DIConditionStruct[0].lNegativeCoefficient       = lXCoefficient;
1976         DIConditionStruct[0].dwPositiveSaturation       = 10000;
1977         DIConditionStruct[0].dwNegativeSaturation       = 10000;
1978         DIConditionStruct[0].lDeadBand                          = 0;
1979         DIConditionStruct[1].lOffset                            = lYOffset;
1980         DIConditionStruct[1].lPositiveCoefficient       = lYCoefficient;
1981         DIConditionStruct[1].lNegativeCoefficient       = lYCoefficient;
1982         DIConditionStruct[1].dwPositiveSaturation       = 10000;
1983         DIConditionStruct[1].dwNegativeSaturation       = 10000;
1984         DIConditionStruct[1].lDeadBand                          = 0;
1985
1986         DWORD rgdwAxes[2];
1987         int nAxisCount = 0;
1988         if(lXCoefficient != 0)
1989         {
1990                 rgdwAxes[nAxisCount] = DIJOFS_X;
1991                 nAxisCount++;
1992         }
1993         if(lYCoefficient != 0)
1994         {
1995                 rgdwAxes[nAxisCount] = DIJOFS_Y;
1996                 nAxisCount++;
1997         }
1998         if(lXCoefficient == 0 && lYCoefficient == 0)
1999         {
2000                 nAxisCount = 2;
2001                 rgdwAxes[0] = DIJOFS_X;
2002                 rgdwAxes[1] = DIJOFS_Y;
2003         }
2004
2005         DWORD cbTypeSpecificParams;
2006         PVOID pvTypeSpecificParams;
2007         if(nAxisCount == 1)
2008         {
2009                 cbTypeSpecificParams = sizeof(DICONDITION[1]);
2010                 if(lXCoefficient != 0)
2011                         pvTypeSpecificParams = &DIConditionStruct[0];
2012                 else
2013                         pvTypeSpecificParams = &DIConditionStruct[1];
2014         }
2015         else
2016         {
2017                 cbTypeSpecificParams = sizeof(DICONDITION[2]);
2018                 pvTypeSpecificParams = &DIConditionStruct[0];
2019         }
2020
2021         LONG rglDirection[2];
2022         rglDirection[0] = 0;
2023         rglDirection[1] = 0;
2024
2025         DIEFFECT DIEffectStruct;
2026         DIEffectStruct.dwSize                                   = sizeof(DIEFFECT);
2027         DIEffectStruct.dwFlags                                  = DIEFF_OBJECTOFFSETS | DIEFF_CARTESIAN;
2028         DIEffectStruct.dwDuration                               = dwDuration;
2029         DIEffectStruct.dwSamplePeriod                   = HZ_TO_uS(100);
2030         DIEffectStruct.dwGain                                   = 10000;
2031         DIEffectStruct.dwTriggerButton                  = lButton == -1 ? DIEB_NOTRIGGER : FIELD_OFFSET(DIJOYSTATE, rgbButtons) + lButton;
2032         DIEffectStruct.dwTriggerRepeatInterval  = 0;
2033         DIEffectStruct.cAxes                                    = nAxisCount;
2034         DIEffectStruct.rgdwAxes                                 = rgdwAxes;
2035         DIEffectStruct.rglDirection                             = rglDirection;
2036         DIEffectStruct.lpEnvelope                               = NULL;
2037         DIEffectStruct.cbTypeSpecificParams             = cbTypeSpecificParams;
2038         DIEffectStruct.lpvTypeSpecificParams    = pvTypeSpecificParams;
2039
2040         HRESULT hResult;
2041         hResult = pDIDevice->CreateEffect(guid, &DIEffectStruct, ppDIEffect, NULL);
2042
2043         return hResult;
2044 }
2045
2046 // ----------------------------------------------------------------------------
2047 // Function:    SWFF_CreateRampEffect
2048 // Purpose:             Creates a Ramp type Effect with specified params
2049 // Parameters:  LPDIRECTINPUTDEVICE2 pDIDevice  - IDIRECTINPUTDEVICE2 interface
2050 //                              LPDIRECTINPUTEFFECT* ppDIEffect - Receives pointer to created effect
2051 //                              DWORD dwDuration                - uS
2052 //                              DWORD dwDirection               - 0 to 35999
2053 //                              LONG lStart                             - -10000 to 10000
2054 //                              LONG lEnd                               - -10000 to 10000
2055 //                              DWORD dwAttackTime              - Envelope Attack Time in uS
2056 //                              DWORD dwAttackLevel             - Envelope Attack Level in 0 to 10000
2057 //                              DWORD dwFadeTime                - Envelope Fade time in uS
2058 //                              DWORD dwFadeLevel               - Envelope Fade Level
2059 //                              LONG lButton                    - Index of playback button, -1 for none
2060 // Returns:
2061 // Algorithm:   
2062 // Comments:
2063 // 
2064 // ----------------------------------------------------------------------------
2065 HRESULT SWFF_CreateRampEffect(  
2066         IN LPDIRECTINPUTDEVICE2 pDIDevice,
2067         IN OUT LPDIRECTINPUTEFFECT* ppDIEffect,
2068         IN DWORD dwDuration,
2069         IN DWORD dwDirection,
2070         IN LONG lStart,
2071         IN LONG lEnd,
2072         IN DWORD dwAttackTime,
2073         IN DWORD dwAttackLevel,
2074         IN DWORD dwFadeTime,
2075         IN DWORD dwFadeLevel,
2076         IN LONG lButton)
2077 {
2078         if(pDIDevice == NULL || ppDIEffect == NULL)
2079                 return SFERR_INVALID_PARAM;
2080         
2081         // Always clear return IPtr
2082         *ppDIEffect = NULL;
2083
2084         DIRAMPFORCE DIRampStruct;
2085         DIRampStruct.lStart = lStart;
2086         DIRampStruct.lEnd = lEnd;
2087
2088         DIENVELOPE DIEnvelopeStruct;
2089         DIEnvelopeStruct.dwSize = sizeof(DIENVELOPE);
2090         DIEnvelopeStruct.dwAttackTime = dwAttackTime;
2091         DIEnvelopeStruct.dwAttackLevel = dwAttackLevel;
2092         DIEnvelopeStruct.dwFadeTime = dwFadeTime;
2093         DIEnvelopeStruct.dwFadeLevel = dwFadeLevel;
2094
2095         DWORD rgdwAxes[2];
2096         rgdwAxes[0] = DIJOFS_X;
2097         rgdwAxes[1] = DIJOFS_Y;
2098
2099         LONG rglDirection[2];
2100         rglDirection[0] = dwDirection;
2101         rglDirection[1] = 0;
2102
2103         DIEFFECT DIEffectStruct;
2104         DIEffectStruct.dwSize                                   = sizeof(DIEFFECT);
2105         DIEffectStruct.dwFlags                                  = DIEFF_OBJECTOFFSETS | DIEFF_POLAR;
2106         DIEffectStruct.dwDuration                               = dwDuration;
2107         DIEffectStruct.dwSamplePeriod                   = HZ_TO_uS(100);
2108         DIEffectStruct.dwGain                                   = 10000;
2109         DIEffectStruct.dwTriggerButton                  = lButton == -1 ? DIEB_NOTRIGGER : FIELD_OFFSET(DIJOYSTATE, rgbButtons) + lButton;
2110         DIEffectStruct.dwTriggerRepeatInterval  = 0;
2111         DIEffectStruct.cAxes                                    = 2;
2112         DIEffectStruct.rgdwAxes                                 = rgdwAxes;
2113         DIEffectStruct.rglDirection                             = rglDirection;
2114         DIEffectStruct.lpEnvelope                               = &DIEnvelopeStruct;
2115         DIEffectStruct.cbTypeSpecificParams             = sizeof(DIRampStruct);
2116         DIEffectStruct.lpvTypeSpecificParams    = &DIRampStruct;
2117
2118         HRESULT hResult;
2119         hResult = pDIDevice->CreateEffect(GUID_RampForce, &DIEffectStruct, ppDIEffect, NULL);
2120
2121         return hResult;
2122 }
2123
2124 // ----------------------------------------------------------------------------
2125 // Function:    SWFF_CreateConstantForceEffect
2126 // Purpose:             Creates a ConstantForce type Effect with specified params
2127 // Parameters:  LPDIRECTINPUTDEVICE2 pDIDevice  - IDIRECTINPUTDEVICE2 interface
2128 //                              LPDIRECTINPUTEFFECT* ppDIEffect - Receives pointer to created effect
2129 //                              DWORD dwDuration                - in uS
2130 //                              DWORD dwDirection               - in 0 to 35999
2131 //                              LONG lMagnitude                 - in -10000 to 10000
2132 //                              DWORD dwAttackTime              - Envelope Attack Time in uS
2133 //                              DWORD dwAttackLevel             - Envelope Attack Level in 0 to 10000
2134 //                              DWORD dwFadeTime                - Envelope Fade time in uS
2135 //                              DWORD dwFadeLevel               - Envelope Fade Level
2136 //                              LONG lButton                    - Index of playback button, -1 for none
2137 // Returns:
2138 // Algorithm:   
2139 // Comments:
2140 // 
2141 // ----------------------------------------------------------------------------
2142 HRESULT SWFF_CreateConstantForceEffect( 
2143         IN LPDIRECTINPUTDEVICE2 pDIDevice,
2144         IN OUT LPDIRECTINPUTEFFECT* ppDIEffect,
2145         IN DWORD dwDuration,
2146         IN DWORD dwDirection,
2147         IN LONG lMagnitude,
2148         IN DWORD dwAttackTime,
2149         IN DWORD dwAttackLevel,
2150         IN DWORD dwFadeTime,
2151         IN DWORD dwFadeLevel,
2152         IN LONG lButton)
2153 {
2154         if(pDIDevice == NULL || ppDIEffect == NULL)
2155                 return SFERR_INVALID_PARAM;
2156         
2157         // Always clear return IPtr
2158         *ppDIEffect = NULL;
2159
2160         DICONSTANTFORCE DIConstantForceStruct;
2161         DIConstantForceStruct.lMagnitude = lMagnitude;
2162
2163         DIENVELOPE DIEnvelopeStruct;
2164         DIEnvelopeStruct.dwSize = sizeof(DIENVELOPE);
2165         DIEnvelopeStruct.dwAttackTime = dwAttackTime;
2166         DIEnvelopeStruct.dwAttackLevel = dwAttackLevel;
2167         DIEnvelopeStruct.dwFadeTime = dwFadeTime;
2168         DIEnvelopeStruct.dwFadeLevel = dwFadeLevel;
2169
2170         DWORD rgdwAxes[2];
2171         rgdwAxes[0] = DIJOFS_X;
2172         rgdwAxes[1] = DIJOFS_Y;
2173
2174         LONG rglDirection[2];
2175         rglDirection[0] = dwDirection;
2176         rglDirection[1] = 0;
2177
2178         DIEFFECT DIEffectStruct;
2179         DIEffectStruct.dwSize                                   = sizeof(DIEFFECT);
2180         DIEffectStruct.dwFlags                                  = DIEFF_OBJECTOFFSETS | DIEFF_POLAR;
2181         DIEffectStruct.dwDuration                               = dwDuration;
2182         DIEffectStruct.dwSamplePeriod                   = HZ_TO_uS(100);
2183         DIEffectStruct.dwGain                                   = 10000;
2184         DIEffectStruct.dwTriggerButton                  = lButton == -1 ? DIEB_NOTRIGGER : FIELD_OFFSET(DIJOYSTATE, rgbButtons) + lButton;
2185         DIEffectStruct.dwTriggerRepeatInterval  = 0;
2186         DIEffectStruct.cAxes                                    = 2;
2187         DIEffectStruct.rgdwAxes                                 = rgdwAxes;
2188         DIEffectStruct.rglDirection                             = rglDirection;
2189         DIEffectStruct.lpEnvelope                               = &DIEnvelopeStruct;
2190         DIEffectStruct.cbTypeSpecificParams             = sizeof(DICONSTANTFORCE);
2191         DIEffectStruct.lpvTypeSpecificParams    = &DIConstantForceStruct;
2192
2193         HRESULT hResult;
2194         hResult = pDIDevice->CreateEffect(GUID_ConstantForce, &DIEffectStruct, ppDIEffect, NULL);
2195
2196         return hResult;
2197 }
2198
2199
2200 // ----------------------------------------------------------------------------
2201 // Function:    SWFF_CreateWallEffect
2202 // Purpose:             Creates a Wall Effect
2203 // Parameters:  LPDIRECTINPUTDEVICE2 pDIDevice  - IDIRECTINPUTDEVICE2 interface
2204 //                              LPDIRECTINPUTEFFECT* ppDIEffect - Receives pointer to created effect
2205 //                              DWORD dwDuration                - in uS
2206 //                              DWORD dwDirection               - 0 | 9000 | 18000 | 27000
2207 //                              DWORD dwDistance                - Distance from centerin 0 to 10000
2208 //                              BOOL bInner                             - T/F = Inner/Outer
2209 //                              LONG lCoefficient               - Wall Constant in 0 to 10000
2210 //                              LONG lButton                    - Index of playback button, -1 for none
2211 // Returns:
2212 // Algorithm:   
2213 // Comments:
2214 // 
2215 // ----------------------------------------------------------------------------
2216 #if 0
2217 HRESULT SWFF_CreateWallEffect(  
2218         IN LPDIRECTINPUTDEVICE2 pDIDevice,
2219         IN OUT LPDIRECTINPUTEFFECT* ppDIEffect,
2220         IN DWORD dwDuration,
2221         IN DWORD dwDirection,
2222         IN DWORD dwDistance,
2223         IN BOOL bInner,
2224         IN LONG lWallCoefficient,
2225         IN LONG lButton)
2226 {
2227         if(pDIDevice == NULL || ppDIEffect == NULL)
2228                 return SFERR_INVALID_PARAM;
2229
2230         // Always clear return IPtr
2231         *ppDIEffect = NULL;
2232
2233         BE_WALL_PARAM WallStruct;
2234         WallStruct.m_Bytes = sizeof(WallStruct);
2235         WallStruct.m_WallType = bInner ? WALL_INNER : WALL_OUTER;
2236         WallStruct.m_WallConstant = lWallCoefficient;
2237         WallStruct.m_WallAngle = dwDirection;
2238         WallStruct.m_WallDistance = dwDistance;
2239
2240
2241         DWORD rgdwAxes[2];
2242         rgdwAxes[0] = DIJOFS_X;
2243         rgdwAxes[1] = DIJOFS_Y;
2244
2245         LONG rglDirection[2];
2246         rglDirection[0] = 0;
2247         rglDirection[1] = 0;
2248
2249         DIEFFECT DIEffectStruct;
2250         DIEffectStruct.dwSize                                   = sizeof(DIEFFECT);
2251         DIEffectStruct.dwFlags                                  = DIEFF_OBJECTOFFSETS | DIEFF_POLAR;
2252         DIEffectStruct.dwDuration                               = dwDuration;
2253         DIEffectStruct.dwSamplePeriod                   = HZ_TO_uS(100);
2254         DIEffectStruct.dwGain                                   = 10000;
2255         DIEffectStruct.dwTriggerButton                  = lButton == -1 ? DIEB_NOTRIGGER : FIELD_OFFSET(DIJOYSTATE, rgbButtons) + lButton;
2256         DIEffectStruct.dwTriggerRepeatInterval  = 0;
2257         DIEffectStruct.cAxes                                    = 2;
2258         DIEffectStruct.rgdwAxes                                 = rgdwAxes;
2259         DIEffectStruct.rglDirection                             = rglDirection;
2260         DIEffectStruct.lpEnvelope                               = NULL;
2261         DIEffectStruct.cbTypeSpecificParams             = sizeof(WallStruct);
2262         DIEffectStruct.lpvTypeSpecificParams    = &WallStruct;
2263
2264         HRESULT hResult;
2265         hResult = pDIDevice->CreateEffect(GUID_Wall, &DIEffectStruct, ppDIEffect, NULL);
2266
2267         return hResult;
2268 }
2269 #endif
2270
2271
2272 // ----------------------------------------------------------------------------
2273 // FUNCTION:    SWFF_GetJoyData
2274 // PURPOSE:     Retrieves Joystick data
2275 // PARAMETERS:  int nJoyID              - JOYSTICKID1-16
2276 //                              JOYINFOEX *pjix - PTR to a JOYYINFOEX structure
2277 //                              char *pszErr    - Ptr to Error code string
2278 // RETURNS:             JOYINFOEX filled in
2279 //
2280 //                              The axis and buttons info:
2281 //                              All axis are in the range 0 to 65535.
2282 //                                      jix.dwXpos - X position.
2283 //                                      jix.dwYpos - Y position.
2284 //                                      jix.dwZpos - Throttle slider control
2285 //                                      jix.dwRpos - Z Rotation position.
2286 //
2287 //                              To see if button 1 is pressed: 
2288 //                                 (jix.dwButtons & JOY_BUTTON1) ? PRESSED : NOT_PRESSED;
2289 //                              likewise for the other buttons JOY_BUTTON2, JOY_BUTTON3 \85 
2290 //                              JOY_BUTTON8
2291 //
2292 //                              Hat Switch (POV) is in jix.dwPOV
2293 //                                 The range is 0 to 35900 and the value is -1 if the 
2294 //                              Hat Switch is not pressed.
2295 //
2296 //                              TRUE if successful, else FALSE
2297 // COMMENTS:    
2298 // ----------------------------------------------------------------------------
2299 BOOL SWFF_GetJoyData(int nJoyID, JOYINFOEX * pjix, char *pszErr)
2300 {
2301         if(pjix == NULL || pszErr == NULL)
2302                 return FALSE;
2303
2304         memset(pjix, 0x00, sizeof(JOYINFOEX));  // for good measure
2305         pjix->dwSize = sizeof(JOYINFOEX);
2306
2307 // NOTE:  With SideWinder Digital OverDrive, it takes no more time to return all 
2308 // information from the joystick than it does to just get 
2309 // the button states or axis.
2310 //
2311         pjix->dwFlags = JOY_RETURNALL;
2312
2313
2314 // joyGetPoxEx will fill in the joyinfoex struct with all the
2315 // joystick information 
2316 //
2317  
2318         switch(joyGetPosEx(nJoyID, pjix))
2319         {
2320                 case JOYERR_NOERROR: // no problem
2321                         strcpy(pszErr,"SUCCESS");
2322                         break;
2323                  
2324                 case MMSYSERR_NODRIVER:
2325                         strcpy(pszErr,"The joystick driver is not present.");
2326                         return FALSE;
2327                  
2328                 case MMSYSERR_INVALPARAM:
2329                         strcpy(pszErr,"An invalid parameter was passed.");
2330                         return FALSE;
2331                  
2332                 case MMSYSERR_BADDEVICEID:        
2333                         strcpy(pszErr,"The specified joystick identifier is invalid.");
2334                         return FALSE;
2335                  
2336                 case JOYERR_UNPLUGGED:        
2337                         strcpy(pszErr,"Your joystick is unplugged.");
2338                         return FALSE;
2339                  
2340                 default:
2341                         strcpy(pszErr,"Unknown joystick error.");
2342                         return FALSE;
2343          
2344          }   // end of switch
2345         return TRUE; 
2346  } // GetJoyData()
2347
2348
2349 // ----------------------------------------------------------------------------
2350 // FUNCTION:    SWFF_GetJoyData2
2351 // PURPOSE:     Retrieves Joystick data using DInput calls  
2352 // PARAMETERS:  LPDIRECTINPUTDEVICE2 pDIDevice  - Pointer to DirectInputDevice
2353 //                      LPDIJOYSTATE pjs                                - PTR to a DIJOYSTATE structure
2354 // RETURNS:             DIJOYSTATE filled in
2355 //
2356 //                              The axis info:
2357 //                                      all axes have range from 0 to 65535
2358 //                                      pjs->lX - X position
2359 //                                      pjs->lY - Y position
2360 //                                      pjs->lZ - Throttle position
2361 //
2362 //                              To see if button 0 is pressed: 
2363 //                                 (pjs->rgbButtons[0] & 0x80) ? PRESSED : NOT_PRESSED;
2364 //                                      likewise for the other buttons pjs->rgbButtons[1],
2365 //                                      pjs->rgbButtons[2]
2366 //
2367 //                              Hat Switch (POV) is in pjs->rgdwPov[0]
2368 //                                 The range is 0 to 35999 and the value is -1 if the 
2369 //                                      Hat Switch is not pressed.
2370 //
2371 // COMMENTS:    
2372 // ----------------------------------------------------------------------------
2373 /*HRESULT SWFF_GetJoyData2(
2374         IN LPDIRECTINPUTDEVICE2 pDIDevice,
2375         IN OUT LPDIJOYSTATE pjs)
2376 {
2377         HRESULT hResult;
2378
2379         if(pDIDevice == NULL || pjs == NULL)
2380                 return SFERR_INVALID_PARAM;
2381
2382         memset(pjs, 0x00, sizeof(DIJOYSTATE));  // for good measure
2383
2384         // NOTE:  With SideWinder Digital OverDrive, it takes no more time to return all 
2385         // information from the joystick than it does to just get 
2386         // the button states or axis.
2387         //
2388         
2389         // must poll before using GetDeviceState(...)
2390         hResult = pDIDevice->Poll();
2391         if(FAILED(hResult))
2392                 return hResult;
2393
2394         // retrieve the values cached during Poll()
2395         hResult = pDIDevice->GetDeviceState(sizeof(DIJOYSTATE), pjs);
2396
2397         return hResult;
2398  } // GetJoyData2()
2399 */
2400
2401 // ----------------------------------------------------------------------------
2402 // Function:    SWFF_ErrorCodeToString
2403 // Parameters:  HRESULT hResult         - Error Code
2404 //                              TCHAR * pszString       - Ptr to string to fill with code
2405 // Returns:
2406 // Algorithm:
2407 // Comments:
2408 // 
2409 // ----------------------------------------------------------------------------
2410 void SWFF_ErrorCodeToString(HRESULT hResult, TCHAR * pszCodeString)
2411 {               
2412         if(pszCodeString == NULL)
2413                 return;
2414
2415 //XSTR:OFF
2416
2417         switch(hResult)
2418         {
2419                 case S_FALSE: strcpy(pszCodeString, "S_FALSE"); break;
2420                 case DI_POLLEDDEVICE: strcpy(pszCodeString, "DI_POLLEDDEVICE"); break;
2421 //              case DI_DOWNLOADSKIPPED: strcpy(pszCodeString, "DI_DOWNLOADSKIPPED"); break;
2422 //              case DI_EFFECTRESTARTED: strcpy(pszCodeString, "DI_EFFECTRESTARTED"); break;
2423                 case DIERR_OLDDIRECTINPUTVERSION: strcpy(pszCodeString, "DIERR_OLDDIRECTINPUTVERSION" ); break;
2424                 case DIERR_BETADIRECTINPUTVERSION: strcpy(pszCodeString, "DIERR_BETADIRECTINPUTVERSION" ); break;
2425                 case DIERR_BADDRIVERVER: strcpy(pszCodeString, "DIERR_BADDRIVERVER" ); break;
2426                 case DIERR_DEVICENOTREG: strcpy(pszCodeString, "DIERR_DEVICENOTREG" ); break;
2427                 case DIERR_NOTFOUND: strcpy(pszCodeString, "DIERR_NOTFOUND" ); break;
2428                 case DIERR_INVALIDPARAM: strcpy(pszCodeString, "DIERR_INVALIDPARAM" ); break;
2429                 case DIERR_NOINTERFACE: strcpy(pszCodeString, "DIERR_NOINTERFACE" ); break;
2430                 case DIERR_GENERIC: strcpy(pszCodeString, "DIERR_GENERIC" ); break;
2431                 case DIERR_OUTOFMEMORY: strcpy(pszCodeString, "DIERR_OUTOFMEMORY" ); break;
2432                 case DIERR_UNSUPPORTED: strcpy(pszCodeString, "DIERR_UNSUPPORTED" ); break;
2433                 case DIERR_NOTINITIALIZED: strcpy(pszCodeString, "DIERR_NOTINITIALIZED" ); break;
2434                 case DIERR_ALREADYINITIALIZED: strcpy(pszCodeString, "DIERR_ALREADYINITIALIZED" ); break;
2435                 case DIERR_NOAGGREGATION: strcpy(pszCodeString, "DIERR_NOAGGREGATION" ); break;
2436                 case DIERR_INPUTLOST: strcpy(pszCodeString, "DIERR_INPUTLOST" ); break;
2437                 case DIERR_ACQUIRED: strcpy(pszCodeString, "DIERR_ACQUIRED" ); break;
2438                 case DIERR_NOTACQUIRED: strcpy(pszCodeString, "DIERR_NOTACQUIRED" ); break;
2439                 case E_ACCESSDENIED: strcpy(pszCodeString, "E_ACCESSDENIED: DIERR_OTHERAPPHASPRIO, DIERR_READONLY, DIERR_HANDLEEXISTS"); break;
2440                 case E_PENDING: strcpy(pszCodeString, "E_PENDING" ); break;
2441                 case DIERR_INSUFFICIENTPRIVS: strcpy(pszCodeString, "DIERR_INSUFFICIENTPRIVS" ); break;
2442                 case DIERR_DEVICEFULL: strcpy(pszCodeString, "DIERR_DEVICEFULL" ); break;
2443                 case DIERR_MOREDATA: strcpy(pszCodeString, "DIERR_MOREDATA" ); break;
2444                 case DIERR_NOTDOWNLOADED: strcpy(pszCodeString, "DIERR_NOTDOWNLOADED" ); break;
2445                 case DIERR_HASEFFECTS: strcpy(pszCodeString, "DIERR_HASEFFECTS" ); break;
2446                 case DIERR_NOTEXCLUSIVEACQUIRED: strcpy(pszCodeString, "DIERR_NOTEXCLUSIVEACQUIRED"); break;
2447                 case DIERR_INCOMPLETEEFFECT: strcpy(pszCodeString, "DIERR_INCOMPLETEEFFECT" ); break;
2448                 case DIERR_NOTBUFFERED: strcpy(pszCodeString, "DIERR_NOTBUFFERED" ); break;
2449                 case DIERR_EFFECTPLAYING: strcpy(pszCodeString, "DIERR_EFFECTPLAYING"); break;
2450                 case SFERR_INVALID_OBJECT: strcpy(pszCodeString, "SFERR_INVALID_OBJECT" ); break;
2451                 case SFERR_END_OF_LIST: strcpy(pszCodeString, "SFERR_END_OF_LIST" ); break;
2452                 case SFERR_DEVICE_NACK: strcpy(pszCodeString, "SFERR_DEVICE_NACK" ); break;
2453                 case SFERR_RAW_OUT_DATAEVENT_CREATION: strcpy(pszCodeString, "SFERR_RAW_OUT_DATAEVENT_CREATION" ); break;
2454                 case SFERR_RAW_OUT_THREAD_CREATION: strcpy(pszCodeString, "SFERR_RAW_OUT_THREAD_CREATION" ); break;
2455                 case SFERR_SYSTEM_INIT: strcpy(pszCodeString, "SFERR_SYSTEM_INIT" ); break;
2456                 case SFERR_DRIVER_ERROR: strcpy(pszCodeString, "SFERR_DRIVER_ERROR" ); break;
2457                 case SFERR_NON_FF_DEVICE: strcpy(pszCodeString, "SFERR_NON_FF_DEVICE" ); break;
2458                 case SFERR_INVALID_HAL_OBJECT: strcpy(pszCodeString, "SFERR_INVALID_HAL_OBJECT" ); break;
2459                 case VFX_ERR_FILE_NOT_FOUND: strcpy(pszCodeString, "VFX_ERR_FILE_NOT_FOUND" ); break;
2460                 case VFX_ERR_FILE_CANNOT_OPEN: strcpy(pszCodeString, "VFX_ERR_FILE_CANNOT_OPEN" ); break;
2461                 case VFX_ERR_FILE_CANNOT_CLOSE: strcpy(pszCodeString, "VFX_ERR_FILE_CANNOT_CLOSE" ); break;
2462                 case VFX_ERR_FILE_CANNOT_READ: strcpy(pszCodeString, "VFX_ERR_FILE_CANNOT_READ" ); break;
2463                 case VFX_ERR_FILE_CANNOT_WRITE: strcpy(pszCodeString, "VFX_ERR_FILE_CANNOT_WRITE" ); break;
2464                 case VFX_ERR_FILE_CANNOT_SEEK: strcpy(pszCodeString, "VFX_ERR_FILE_CANNOT_SEEK" ); break;
2465                 case VFX_ERR_FILE_UNKNOWN_ERROR: strcpy(pszCodeString, "VFX_ERR_FILE_UNKNOWN_ERROR" ); break;
2466                 case VFX_ERR_FILE_BAD_FORMAT: strcpy(pszCodeString, "VFX_ERR_FILE_BAD_FORMAT" ); break;
2467                 case VFX_ERR_FILE_ACCESS_DENIED: strcpy(pszCodeString, "VFX_ERR_FILE_ACCESS_DENIED" ); break;
2468                 case VFX_ERR_FILE_SHARING_VIOLATION: strcpy(pszCodeString, "VFX_ERR_FILE_SHARING_VIOLATION" ); break;
2469                 case VFX_ERR_FILE_NETWORK_ERROR: strcpy(pszCodeString, "VFX_ERR_FILE_NETWORK_ERROR" ); break;
2470                 case VFX_ERR_FILE_TOO_MANY_OPEN_FILES: strcpy(pszCodeString, "VFX_ERR_FILE_TOO_MANY_OPEN_FILES" ); break;
2471                 case VFX_ERR_FILE_INVALID: strcpy(pszCodeString, "VFX_ERR_FILE_INVALID" ); break;
2472                 case VFX_ERR_FILE_END_OF_FILE: strcpy(pszCodeString, "VFX_ERR_FILE_END_OF_FILE" ); break;
2473                 case SWDEV_ERR_INVALID_ID : strcpy(pszCodeString, "SWDEV_ERR_INVALID_ID" ); break;
2474                 case SWDEV_ERR_INVALID_PARAM : strcpy(pszCodeString, "SWDEV_ERR_INVALID_PARAM" ); break;
2475                 case SWDEV_ERR_CHECKSUM : strcpy(pszCodeString, "SWDEV_ERR_CHECKSUM" ); break;
2476                 case SWDEV_ERR_TYPE_FULL : strcpy(pszCodeString, "SWDEV_ERR_TYPE_FULL" ); break;
2477                 case SWDEV_ERR_UNKNOWN_CMD : strcpy(pszCodeString, "SWDEV_ERR_UNKNOWN_CMD" ); break;
2478                 case SWDEV_ERR_PLAYLIST_FULL : strcpy(pszCodeString, "SWDEV_ERR_PLAYLIST_FULL" ); break;
2479                 case SWDEV_ERR_PROCESSLIST_FULL : strcpy(pszCodeString, "SWDEV_ERR_PROCESSLIST_FULL" ); break;
2480                 default: sprintf(pszCodeString, "%x", hResult); break;
2481         }
2482
2483 //XSTR:ON
2484
2485