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