Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1315 lines
37 KiB

  1. /****************************************************************************
  2. MODULE: FFD_SWFF.CPP
  3. Tab settings: 5 9
  4. Copyright 1995, 1996, 1999, Microsoft Corporation, All Rights Reserved.
  5. PURPOSE: FFD (SWForce HAL) API
  6. FUNCTIONS: Function prototypes for Force Feedback Joystick interface
  7. between the SWForce and the device
  8. FFD_PutRawForce
  9. FFD_DownloadEffect
  10. FFD_DestroyEffect
  11. FFD_GetEffectForceValue
  12. FFD_PutRawForce
  13. VFX functions:
  14. Download_VFX
  15. CreateEffectFromFile
  16. CreateEffectFromBuffer
  17. These functionality are not necessarily supported by all Force Feedback
  18. devices. For example, if a device does not support built-in synthesis
  19. capability, then the entry point DownloadEffect, will return an error
  20. code ERROR_NO_SUPPORT.
  21. COMMENTS:
  22. This module of functions are encapsulated in SWFF_PRO.dll the DirectInput
  23. DDI driver
  24. Author(s): Name:
  25. ---------- ----------------
  26. MEA Manolito E. Adan
  27. Revision History:
  28. -----------------
  29. Version Date Author Comments
  30. 1.0 21-Mar-97 MEA original from SWForce code
  31. 12-Mar-99 waltw Removed dead code (mostly FFD_xxx functions)
  32. These functions no longer exported in .def
  33. ****************************************************************************/
  34. #include <windows.h>
  35. #include <mmsystem.h>
  36. #include <assert.h>
  37. #include "midi.hpp"
  38. #include "hau_midi.hpp"
  39. #include "math.h"
  40. #include "FFD_SWFF.hpp"
  41. #include "midi_obj.hpp"
  42. #include "CritSec.h"
  43. // Force Output range values
  44. #define MAX_AMP 2047
  45. #define MIN_AMP -2048
  46. #define FORCE_RANGE ((MAX_AMP - MIN_AMP)/2)
  47. extern TCHAR szDeviceName[MAX_SIZE_SNAME];
  48. extern CJoltMidi *g_pJoltMidi;
  49. #ifdef _DEBUG
  50. extern char g_cMsg[160];
  51. #endif
  52. static HRESULT AngleToXY(
  53. IN LONG lDirectionAngle2D,
  54. IN LONG lValueData,
  55. IN ULONG ulAxisMask,
  56. IN OUT PLONG pX,
  57. IN OUT PLONG pY);
  58. // *** ---------------------------------------------------------------------***
  59. // Function: FFD_GetDiagCounters
  60. // Purpose: Returns the DIAG_COUNTER structure
  61. // Parameters:
  62. // PDIAG_COUNTER pDiagCounter - Ptr to DIAG_COUNTER struct.
  63. //
  64. // Returns: SUCCESS - always successful
  65. //
  66. // Algorithm:
  67. // Comments:
  68. // *** ---------------------------------------------------------------------***
  69. HRESULT WINAPI FFD_GetDiagCounters(PDIAG_COUNTER pDiagCounter)
  70. {
  71. #ifdef _DEBUG
  72. g_CriticalSection.Enter();
  73. wsprintf(g_cMsg, "FFD_GetDiagCounters: %s \r\n", &szDeviceName[0]);
  74. OutputDebugString(g_cMsg);
  75. g_CriticalSection.Leave();
  76. #endif
  77. if (NULL == g_pJoltMidi) return (SFERR_DRIVER_ERROR);
  78. pDiagCounter = g_pJoltMidi->DiagCounterPtrOf();
  79. return (SUCCESS);
  80. }
  81. // *** ---------------------------------------------------------------------***
  82. // Function: FFD_PutRawForce
  83. // Purpose: Send force object parameters to be played back by the FF device.
  84. // Parameters:
  85. // IN PFORCE pForce - A pointer to a FORCE data structure
  86. //
  87. // Returns: SUCCESS if successful, else
  88. // SFERR_NO_SUPPORT
  89. //
  90. // Algorithm:
  91. //
  92. // Comments:
  93. // Note: The Playback mode will be ONCE
  94. //
  95. //
  96. // *** ---------------------------------------------------------------------***
  97. HRESULT WINAPI FFD_PutRawForce(
  98. IN PFORCE pForce)
  99. {
  100. assert(pForce);
  101. HRESULT hRet;
  102. long lForceDataX, lForceDataY;
  103. long lForceData = (long) ( FORCE_RANGE * (float) (pForce->m_ForceValue/100.00));
  104. // If single Axis only, then use the force on that axis.
  105. // If X and Y-axis, then use 2D angle
  106. // if (AngleToXY(pForce->m_DirectionAngle2D+90, lForceData, pForce->m_AxisMask,
  107. // &lForceDataX, &lForceDataY) != SUCCESS) return SFERR_NO_SUPPORT;
  108. if (AngleToXY(pForce->m_DirectionAngle2D, lForceData, pForce->m_AxisMask,
  109. &lForceDataX, &lForceDataY) != SUCCESS) return SFERR_NO_SUPPORT;
  110. #ifdef _DEBUG
  111. g_CriticalSection.Enter();
  112. wsprintf(g_cMsg, "Enter: FFD_PutRawForce: %Force=%ld\n",szDeviceName, (LONG) lForceData);
  113. OutputDebugString(g_cMsg);
  114. g_CriticalSection.Leave();
  115. #endif
  116. switch (pForce->m_AxisMask)
  117. {
  118. case (X_AXIS|Y_AXIS): // use 2D
  119. hRet = CMD_Force_Out(lForceDataX, X_AXIS);
  120. if (FAILED(hRet)) break;
  121. hRet = CMD_Force_Out(lForceDataY, Y_AXIS);
  122. break;
  123. case X_AXIS:
  124. lForceDataX = lForceData;
  125. hRet = CMD_Force_Out(lForceDataX, X_AXIS);
  126. break;
  127. case Y_AXIS:
  128. lForceDataY = lForceData;
  129. hRet = CMD_Force_Out(lForceDataY, Y_AXIS);
  130. break;
  131. default:
  132. hRet = SFERR_NO_SUPPORT;
  133. break;
  134. }
  135. #ifdef _DEBUG
  136. g_CriticalSection.Enter();
  137. wsprintf(g_cMsg, "Exit: FFD_PutRawForce: %Force=%ld\n",szDeviceName, (LONG) lForceData);
  138. OutputDebugString(g_cMsg);
  139. g_CriticalSection.Leave();
  140. #endif
  141. return hRet;
  142. }
  143. // ----------------------------------------------------------------------------
  144. // Function: FFD_Download
  145. //
  146. // Purpose: Downloads the specified Effect object UD/BE/SE to the FF device.
  147. // Parameters:
  148. // IN OUT PDNHANDLE pDnloadD - Ptr to DNHANDLE to store EffectID
  149. // IN PEFFECT pEffect - Ptr Common attributes for Effects
  150. // IN PENVELOPE pEnvelope - Ptr to an ENVELOPE
  151. // IN PVOID pTypeParam - Ptr to a Type specific parameter
  152. // IN ULONG ulAction - Type of action desired
  153. //
  154. // Returns:
  155. // SUCCESS - if successful
  156. // SFERR_FFDEVICE_MEMORY - no more download RAM available
  157. // SFERR_INVALID_PARAM - Invalid parameters
  158. // SFERR_NO_SUPPORT - if function is unsupported.
  159. // Algorithm:
  160. //
  161. // Comments:
  162. //
  163. // ulAction: Type of action desired after downloading
  164. // PLAY_STORE - stores in Device only
  165. // || the following options:
  166. // PLAY_STORE - stores in Device only
  167. // || the following options:
  168. // PLAY_SOLO - stop other forces playing, make this the only one.
  169. // PLAY_SUPERIMPOSE- mix with currently playing device
  170. // PLAY_LOOP - Loops for Count times, where count value is in
  171. // HIWORD
  172. // PLAY_FOREVER - Play forever until told to stop: PLAY_LOOP with 0
  173. // value in HIWORD
  174. // ----------------------------------------------------------------------------
  175. HRESULT WINAPI FFD_DownloadEffect(
  176. IN OUT PDNHANDLE pDnloadID,
  177. IN PEFFECT pEffect,
  178. IN PENVELOPE pEnvelope,
  179. IN PVOID pTypeParam,
  180. IN ULONG ulAction)
  181. {
  182. #ifdef _DEBUG
  183. g_CriticalSection.Enter();
  184. wsprintf(g_cMsg, "Enter: FFD_DownloadEffect. DnloadID= %ld, Type=%ld, SubType=%ld\r\n",
  185. *pDnloadID,
  186. pEffect->m_Type, pEffect->m_SubType);
  187. OutputDebugString(g_cMsg);
  188. g_CriticalSection.Leave();
  189. #endif
  190. if (NULL == g_pJoltMidi) return (SFERR_DRIVER_ERROR);
  191. //REVIEW: Still need to do boundary Assertions, structure size check etc...
  192. assert(pDnloadID && pEffect);
  193. if (!pDnloadID || !pEffect) return (SFERR_INVALID_PARAM);
  194. // If the Effect type is not a BE_DELAY or EF_ROM_EFFECT,
  195. // make sure there is a pTypeParam
  196. if ((BE_DELAY != pEffect->m_SubType) && (EF_ROM_EFFECT != pEffect->m_Type))
  197. {
  198. assert(pTypeParam);
  199. if (NULL == pTypeParam) return (SFERR_INVALID_PARAM);
  200. }
  201. // Don't support PLAY_LOOP for this version
  202. if ((ulAction & PLAY_LOOP) || (ulAction & 0xffff0000))
  203. return (SFERR_NO_SUPPORT);
  204. // REVIEW: TO increase performance, we should do a parameter mod check
  205. // For now, we'll assume all parameters are changed, for dwFlags
  206. // otherwise, we should check for:
  207. //#define DIEP_ALLPARAMS 0x000000FF - All fields valid
  208. //#define DIEP_AXES 0x00000020 - cAxes and rgdwAxes
  209. //#define DIEP_DIRECTION 0x00000040 - cAxes and rglDirection
  210. //#define DIEP_DURATION 0x00000001 - dwDuration
  211. //#define DIEP_ENVELOPE 0x00000080 - lpEnvelope
  212. //#define DIEP_GAIN 0x00000004 - dwGain
  213. //#define DIEP_NODOWNLOAD 0x80000000 - suppress auto - download
  214. //#define DIEP_SAMPLEPERIOD 0x00000002 - dwSamplePeriod
  215. //#define DIEP_TRIGGERBUTTON 0x00000008 - dwTriggerButton
  216. //#define DIEP_TRIGGERREPEATINTERVAL 0x00000010 - dwTriggerRepeatInterval
  217. //#define DIEP_TYPESPECIFICPARAMS 0x00000100 - cbTypeSpecificParams
  218. // and lpTypeSpecificParams
  219. // Figure out the Common members
  220. BYTE bAxisMask = (BYTE) pEffect->m_AxisMask;
  221. ULONG ulDuration = pEffect->m_Duration;
  222. if (PLAY_FOREVER == (ulAction & PLAY_FOREVER)) ulDuration = 0;
  223. // map button 10 to button 9
  224. if(pEffect->m_ButtonPlayMask == 0x0200)
  225. pEffect->m_ButtonPlayMask = 0x0100;
  226. else if(pEffect->m_ButtonPlayMask == 0x0100)
  227. return SFERR_NO_SUPPORT;
  228. DWORD dwFlags = DIEP_ALLPARAMS;
  229. SE_PARAM seParam = { sizeof(SE_PARAM)};
  230. PBE_SPRING_PARAM pBE_xxx1D;
  231. PBE_SPRING_2D_PARAM pBE_xxx2D;
  232. BE_XXX BE_xxx;
  233. PBE_WALL_PARAM pBE_Wall;
  234. // Decode the type of Download to use
  235. HRESULT hRet = SFERR_INVALID_PARAM;
  236. ULONG ulSubType = pEffect->m_SubType;
  237. switch (pEffect->m_Type)
  238. {
  239. case EF_BEHAVIOR:
  240. switch (ulSubType)
  241. {
  242. case BE_SPRING: // 1D Spring
  243. case BE_DAMPER: // 1D Damper
  244. case BE_INERTIA: // 1D Inertia
  245. case BE_FRICTION: // 1D Friction
  246. pBE_xxx1D = (PBE_SPRING_PARAM) pTypeParam;
  247. if (X_AXIS == bAxisMask)
  248. {
  249. BE_xxx.m_XConstant = pBE_xxx1D->m_Kconstant;
  250. BE_xxx.m_YConstant = 0;
  251. if (ulSubType != BE_FRICTION)
  252. BE_xxx.m_Param3 = pBE_xxx1D->m_AxisCenter;
  253. BE_xxx.m_Param4= 0;
  254. }
  255. else
  256. {
  257. if (Y_AXIS != bAxisMask)
  258. break;
  259. else
  260. {
  261. BE_xxx.m_YConstant = pBE_xxx1D->m_Kconstant;
  262. BE_xxx.m_XConstant = 0;
  263. if (ulSubType != BE_FRICTION)
  264. BE_xxx.m_Param4 = pBE_xxx1D->m_AxisCenter;
  265. BE_xxx.m_Param3= 0;
  266. }
  267. }
  268. hRet = CMD_Download_BE_XXX(pEffect, NULL, &BE_xxx, (PDNHANDLE) pDnloadID, dwFlags);
  269. break;
  270. case BE_SPRING_2D: // 2D Spring
  271. case BE_DAMPER_2D: // 2D Damperfs
  272. case BE_INERTIA_2D: // 2D Inertia
  273. case BE_FRICTION_2D: // 2D Friction
  274. // Validate AxisMask is for 2D
  275. if ( (X_AXIS|Y_AXIS) != bAxisMask)
  276. break;
  277. pBE_xxx2D = (PBE_SPRING_2D_PARAM) pTypeParam;
  278. BE_xxx.m_XConstant = pBE_xxx2D->m_XKconstant;
  279. if (ulSubType != BE_FRICTION_2D)
  280. {
  281. BE_xxx.m_YConstant = pBE_xxx2D->m_YKconstant;
  282. BE_xxx.m_Param3 = pBE_xxx2D->m_XAxisCenter;
  283. BE_xxx.m_Param4 = pBE_xxx2D->m_YAxisCenter;
  284. }
  285. else
  286. {
  287. BE_xxx.m_YConstant = pBE_xxx2D->m_XAxisCenter;
  288. BE_xxx.m_Param3 = 0;
  289. BE_xxx.m_Param4 = 0;
  290. }
  291. hRet = CMD_Download_BE_XXX(pEffect, NULL, &BE_xxx, (PDNHANDLE) pDnloadID, dwFlags);
  292. break;
  293. case BE_WALL:
  294. pBE_Wall = (PBE_WALL_PARAM) pTypeParam;
  295. if ( (pBE_Wall->m_WallAngle == 0)
  296. || (pBE_Wall->m_WallAngle == 90)
  297. || (pBE_Wall->m_WallAngle == 180)
  298. || (pBE_Wall->m_WallAngle == 270) )
  299. {
  300. BE_xxx.m_XConstant = pBE_Wall->m_WallType;
  301. BE_xxx.m_YConstant = pBE_Wall->m_WallConstant;
  302. BE_xxx.m_Param3 = pBE_Wall->m_WallAngle;
  303. BE_xxx.m_Param4 = pBE_Wall->m_WallDistance;
  304. hRet = CMD_Download_BE_XXX(pEffect, NULL, &BE_xxx, (PDNHANDLE) pDnloadID, dwFlags);
  305. }
  306. else
  307. hRet = SFERR_NO_SUPPORT;
  308. break;
  309. case BE_DELAY:
  310. if (0 == ulDuration) return (SFERR_INVALID_PARAM);
  311. hRet = CMD_Download_NOP_DELAY(ulDuration, pEffect, (PDNHANDLE) pDnloadID);
  312. break;
  313. default:
  314. hRet = SFERR_NO_SUPPORT;
  315. break;
  316. }
  317. break;
  318. case EF_USER_DEFINED:
  319. hRet = CMD_Download_UD_Waveform(ulDuration, pEffect,
  320. ((PUD_PARAM)pTypeParam)->m_NumVectors,
  321. ((PUD_PARAM)pTypeParam)->m_pForceData,
  322. ulAction, pDnloadID, dwFlags);
  323. break;
  324. case EF_ROM_EFFECT:
  325. // Setup the default parameters for the Effect
  326. if (SUCCESS != g_pJoltMidi->SetupROM_Fx(pEffect))
  327. {
  328. hRet = SFERR_INVALID_OBJECT;
  329. break;
  330. }
  331. // Map the SE_PARAM
  332. // set the frequency
  333. seParam.m_Freq = 0; // unused by ROM Effect
  334. seParam.m_SampleRate = pEffect->m_ForceOutputRate;
  335. seParam.m_MinAmp = -100;
  336. seParam.m_MaxAmp = 100;
  337. hRet = CMD_Download_SYNTH(pEffect, pEnvelope,
  338. &seParam, ulAction, (USHORT *) pDnloadID, dwFlags);
  339. break;
  340. case EF_SYNTHESIZED:
  341. if (0 == ((PSE_PARAM)pTypeParam)->m_SampleRate)
  342. ((PSE_PARAM)pTypeParam)->m_SampleRate = DEFAULT_JOLT_FORCE_RATE;
  343. if (0 == pEffect->m_ForceOutputRate)
  344. pEffect->m_ForceOutputRate = DEFAULT_JOLT_FORCE_RATE;
  345. hRet = CMD_Download_SYNTH(pEffect, pEnvelope,
  346. (PSE_PARAM) pTypeParam, ulAction, pDnloadID, dwFlags);
  347. break;
  348. default:
  349. hRet = SFERR_INVALID_PARAM;
  350. }
  351. #ifdef _DEBUG
  352. g_CriticalSection.Enter();
  353. wsprintf(g_cMsg, "Exit: FFD_DownloadEffect. DnloadID = %lx, hRet=%lx\r\n",
  354. *pDnloadID, hRet);
  355. OutputDebugString(g_cMsg);
  356. g_CriticalSection.Leave();
  357. #endif
  358. return (hRet);
  359. }
  360. // *** ---------------------------------------------------------------------***
  361. // Function: FFD_DestroyEffect
  362. // Purpose: Destroys the Effect from download RAM storage area.
  363. // Parameters:
  364. // IN EFHANDLE EffectID // an Effect ID
  365. //
  366. // Returns: SUCCESS if successful command sent, else
  367. // SFERR_INVALID_ID
  368. // SFERR_NO_SUPPORT
  369. //
  370. // Algorithm:
  371. //
  372. // Comments:
  373. // The Device's Effect ID and memory is returned to free pool.
  374. //
  375. // *** ---------------------------------------------------------------------***
  376. HRESULT WINAPI FFD_DestroyEffect(
  377. IN DNHANDLE DnloadID)
  378. {
  379. #ifdef _DEBUG
  380. g_CriticalSection.Enter();
  381. wsprintf(g_cMsg, "Enter: FFD_DestroyEffect. DnloadID:%ld\r\n",
  382. DnloadID);
  383. OutputDebugString(g_cMsg);
  384. g_CriticalSection.Leave();
  385. #endif
  386. HRESULT hRet = CMD_DestroyEffect(DnloadID);
  387. #ifdef _DEBUG
  388. g_CriticalSection.Enter();
  389. wsprintf(g_cMsg, "Exit: FFD_DestroyEffect. DnloadID:%ld\r\n",
  390. DnloadID);
  391. OutputDebugString(g_cMsg);
  392. g_CriticalSection.Leave();
  393. #endif
  394. return (hRet);
  395. }
  396. // *** ---------------------------------------------------------------------***
  397. // Function: FFD_VFXProcessEffect
  398. // Purpose: Commands FF device to process downloaded Effects
  399. //
  400. // Parameters:
  401. // IN OUT PDNHANDLE pDnloadID // Storage for new Download ID
  402. // IN int nNumEffects // Number of Effect IDs in the array
  403. // IN ULONG ulProcessMode // Processing mode
  404. // IN PDNHANDLE pPListArray// Pointer to an array of Effect IDs
  405. //
  406. // Returns: SUCCESS - if successful, else
  407. // SFERR_INVALID_PARAM
  408. // SFERR_NO_SUPPORT
  409. //
  410. // Algorithm:
  411. //
  412. // Comments:
  413. // The following processing is available:
  414. // CONCATENATE: Enew = E1 followed by E2
  415. // SUPERIMPOSE: Enew = E1 (t1) + E2 (t1) + E1 (t2)
  416. // + E2 (t2) + . . . E1 (tn) + E2 (tn)
  417. //
  418. // ulProcessMode:
  419. // Processing mode:
  420. // CONCATENATE - CONCATENATE
  421. // SUPERIMPOSE - Mix or overlay
  422. //
  423. // pEFHandle:
  424. // The array of Effect IDs must be one more than the actual number
  425. // of Effect IDs to use. The first entry pEFHandle[0] will be
  426. // used to store the new Effect ID created for the CONCATENATE
  427. // and SUPERIMPOSE process choice.
  428. //
  429. // *** ---------------------------------------------------------------------***
  430. HRESULT WINAPI FFD_VFXProcessEffect(
  431. IN ULONG ulButtonPlayMask,
  432. IN OUT PDNHANDLE pDnloadID,
  433. IN int nNumEffects,
  434. IN ULONG ulProcessMode,
  435. IN PDNHANDLE pPListArray)
  436. {
  437. #ifdef _DEBUG
  438. g_CriticalSection.Enter();
  439. wsprintf(g_cMsg, "FFD_ProcessEffect, DnloadID=%ld\r\n",
  440. *pDnloadID);
  441. OutputDebugString(g_cMsg);
  442. g_CriticalSection.Leave();
  443. #endif
  444. assert(pDnloadID && pPListArray);
  445. if ((NULL == pDnloadID) || (NULL == pPListArray)) return (SFERR_INVALID_PARAM);
  446. assert(nNumEffects > 0 && nNumEffects <= MAX_PLIST_EFFECT_SIZE);
  447. if ((nNumEffects > MAX_PLIST_EFFECT_SIZE) || (nNumEffects <= 0))
  448. return (SFERR_INVALID_PARAM);
  449. // map button 10 to button 9
  450. if(ulButtonPlayMask == 0x0200)
  451. ulButtonPlayMask = 0x0100;
  452. else if(ulButtonPlayMask == 0x0100)
  453. return SFERR_NO_SUPPORT;
  454. HRESULT hRet;
  455. hRet = CMD_VFXProcessEffect(ulButtonPlayMask, pDnloadID,nNumEffects,
  456. ulProcessMode,pPListArray, PLAY_STORE);
  457. return (hRet);
  458. }
  459. // *** ---------------------------------------------------------------------***
  460. // Function: FFD_GetEffectForceValue
  461. // Purpose: Returns the force value at tick time for the Effect
  462. //
  463. // Parameters: DNHANDLE DnloadID - Effect ID
  464. // ULONG ulAxisMask - X_AXIS or Y_AXIS
  465. // ULONG ulIndex - Index into the Effect
  466. // PLONG pForceValue - Ptr to a LONG variable
  467. //
  468. // Returns: SUCCESS - if successful, else
  469. // SFERR_INVALID_PARAM
  470. // SFERR_NO_SUPPORT
  471. //
  472. // Algorithm:
  473. //
  474. // Comments:
  475. // *** ---------------------------------------------------------------------***
  476. HRESULT FFD_GetEffectForceValue(
  477. IN DNHANDLE DnloadID,
  478. IN ULONG ulAxisMask,
  479. IN ULONG ulIndex,
  480. IN OUT PLONG pForceValue)
  481. {
  482. #ifdef _DEBUG
  483. g_CriticalSection.Enter();
  484. wsprintf(g_cMsg, "FFD_GetEffectForceValue, DnloadID=%d\r\n", DnloadID);
  485. OutputDebugString(g_cMsg);
  486. g_CriticalSection.Leave();
  487. #endif
  488. return (SFERR_NO_SUPPORT);
  489. }
  490. // *** ---------------------------------------------------------------------***
  491. // Function: AngleToXY
  492. // Purpose: Computes XY from Angle
  493. // Parameters:
  494. // IN LONG lDirectionAngle2D - Angle in Degrees
  495. // IN LONG lForceValue - Resultant Force
  496. // IN ULONG ulAxisMask - Axis to Affect
  497. // IN OUT PLONG pX - X-Axis store
  498. // IN OUT PLONG pY - Y-Axis store
  499. // Returns: pX, pY with valid angle components
  500. //
  501. // *** ---------------------------------------------------------------------***
  502. HRESULT AngleToXY(
  503. IN LONG lDirectionAngle2D,
  504. IN LONG lValueData,
  505. IN ULONG ulAxisMask,
  506. IN OUT PLONG pX,
  507. IN OUT PLONG pY)
  508. {
  509. // If single Axis only, then use the force on that axis.
  510. // If X and Y-axis, then use 2D angle
  511. // If X, Y, and Z-axis, then use 3D angle
  512. // If axis is other than X,Y,Z then no support
  513. double Radian;
  514. switch (ulAxisMask)
  515. {
  516. case (X_AXIS|Y_AXIS): // use 2D
  517. Radian = xDegrees2Radians(lDirectionAngle2D % 360);
  518. #ifdef ORIENTATION_MODE1
  519. *pX = - (long) (lValueData * cos(Radian));
  520. *pY = (long) (lValueData * sin(Radian));
  521. #else
  522. *pX = - (long) (lValueData * sin(Radian));
  523. *pY = (long) (lValueData * cos(Radian));
  524. #endif
  525. break;
  526. case X_AXIS:
  527. *pX = lValueData;
  528. *pY = 0;
  529. break;
  530. case Y_AXIS:
  531. *pX = 0;
  532. *pY = lValueData;
  533. break;
  534. case (X_AXIS|Y_AXIS|Z_AXIS): // use 3D
  535. default:
  536. return (SFERR_NO_SUPPORT);
  537. break;
  538. }
  539. return SUCCESS;
  540. }
  541. //
  542. // --- VFX SUPPORT FUNCTIONS
  543. //
  544. // *** ---------------------------------------------------------------------***
  545. // Function: CreateEffectFromFile
  546. // Purpose: Creates an Effect from a RIFF file
  547. // Parameters: PSWFORCE pISWForce - Ptr to a SWForce
  548. // PPSWEFFECT ppISWEffect - Ptr to a SWEffect
  549. // TCHAR* pszFileName - Name of file to open
  550. // DWORD dwByteCount - Bytes in block
  551. // LPGUID lpGUID - Joystick GUID
  552. //
  553. //
  554. // Returns: SUCCESS - if successful, else
  555. // error code
  556. //
  557. // Algorithm:
  558. //
  559. // Comments:
  560. //
  561. // *** ---------------------------------------------------------------------***
  562. HRESULT CreateEffectFromFile(
  563. IN LPCTSTR pszFileName,
  564. IN ULONG ulAction,
  565. IN OUT PDNHANDLE pDnloadID,
  566. IN DWORD dwFlags)
  567. {
  568. #ifdef _DEBUG
  569. OutputDebugString("CImpIVFX::CreateEffectFromFile\n");
  570. #endif
  571. // parameter checking
  572. if ( !(pszFileName && pDnloadID) )
  573. return SFERR_INVALID_PARAM;
  574. HMMIO hmmio = NULL;
  575. DWORD dwFileSize;
  576. DWORD dwFilePos;
  577. BYTE* pBuffer = NULL;
  578. DWORD dwBytesRead;
  579. HRESULT hResult = SUCCESS;
  580. MMRESULT mmresult;
  581. // open a RIFF file using the buffer
  582. MMIOINFO mmioinfo;
  583. mmioinfo.dwFlags = 0;
  584. mmioinfo.fccIOProc = NULL;
  585. mmioinfo.pIOProc = NULL;
  586. mmioinfo.wErrorRet = 0;
  587. mmioinfo.htask = NULL;
  588. mmioinfo.cchBuffer = 0;
  589. mmioinfo.pchBuffer = NULL;
  590. mmioinfo.pchNext = 0;
  591. mmioinfo.pchEndRead = 0;
  592. mmioinfo.lBufOffset = 0;
  593. mmioinfo.adwInfo[0] = 0;
  594. mmioinfo.adwInfo[1] = 0;
  595. mmioinfo.adwInfo[3] = 0;
  596. mmioinfo.dwReserved1 = 0;
  597. mmioinfo.dwReserved2 = 0;
  598. mmioinfo.hmmio = NULL;
  599. // make a non-constant copy of the string
  600. TCHAR szFileNameCopy[256];
  601. strcpy(szFileNameCopy, pszFileName);
  602. // open the RIFF file for reading
  603. hmmio = mmioOpen(szFileNameCopy, &mmioinfo, MMIO_READ);
  604. if(hmmio == NULL)
  605. {
  606. hResult = MMIOErrorToSFERRor(mmioinfo.wErrorRet);
  607. goto cleanup;
  608. }
  609. // calculate the size of the file
  610. dwFileSize = mmioSeek(hmmio, 0, SEEK_END);
  611. if(dwFileSize == -1)
  612. {
  613. hResult = MMIOErrorToSFERRor(MMIOERR_CANNOTSEEK);
  614. goto cleanup;
  615. }
  616. dwFilePos = mmioSeek(hmmio, 0, SEEK_SET);
  617. if(dwFilePos == -1)
  618. {
  619. hResult = MMIOErrorToSFERRor(MMIOERR_CANNOTSEEK);
  620. goto cleanup;
  621. }
  622. // get a chunk of memory big enough to hold it
  623. pBuffer = new BYTE[dwFileSize];
  624. if(pBuffer == NULL)
  625. {
  626. hResult = VFX_ERR_FILE_OUT_OF_MEMORY;
  627. goto cleanup;
  628. }
  629. // read the file into the chunk of memory
  630. dwBytesRead = mmioRead(hmmio, (char*)pBuffer, dwFileSize);
  631. if(dwBytesRead != dwFileSize)
  632. {
  633. if(dwBytesRead == 0)
  634. hResult = VFX_ERR_FILE_END_OF_FILE;
  635. else
  636. hResult = MMIOErrorToSFERRor(MMIOERR_CANNOTREAD);
  637. goto cleanup;
  638. }
  639. // close the RIFF file
  640. mmresult = mmioClose(hmmio, 0);
  641. hmmio = NULL;
  642. if(mmresult != MMSYSERR_NOERROR)
  643. {
  644. hResult = MMIOErrorToSFERRor(mmresult);
  645. goto cleanup;
  646. }
  647. // call CreateEffectFromBuffer
  648. hResult = CreateEffectFromBuffer(pBuffer, dwFileSize, ulAction, pDnloadID, dwFlags);
  649. // clean up
  650. cleanup:
  651. // close the RIFF file
  652. if(hmmio != NULL)
  653. {
  654. mmresult = mmioClose(hmmio, 0);
  655. if(mmresult != MMSYSERR_NOERROR)
  656. {
  657. hResult = MMIOErrorToSFERRor(mmresult);
  658. }
  659. }
  660. // de-allocate any allocated memory
  661. if(pBuffer != NULL)
  662. delete [] pBuffer;
  663. // return the error code, which is SUCCESS, unless there was an error
  664. return hResult;
  665. }
  666. // *** ---------------------------------------------------------------------***
  667. // Function: CreateEffectFromBuffer
  668. // Purpose: Creates an Effect from a buffer
  669. // Parameters: PSWFORCE pISWForce - Ptr to a SWForce
  670. // PPSWEFFECT ppISWEffect - Ptr to a SWEffect
  671. // PVOID pBuffer - Ptr to a buffer block
  672. // DWORD dwByteCount - Bytes in block
  673. // LPGUID lpGUID - Joystick GUID
  674. //
  675. //
  676. // Returns: SUCCESS - if successful, else
  677. // error code
  678. //
  679. // Algorithm:
  680. //
  681. // Comments:
  682. //
  683. // *** ---------------------------------------------------------------------***
  684. HRESULT CreateEffectFromBuffer(
  685. IN PVOID pBuffer,
  686. IN DWORD dwByteCount,
  687. IN ULONG ulAction,
  688. IN OUT PDNHANDLE pDnloadID,
  689. IN DWORD dwFlags)
  690. {
  691. #ifdef _DEBUG
  692. OutputDebugString("CImpIVFX::CreateEffectFromBuffer\n");
  693. #endif
  694. // parameter checking
  695. if ( !(pBuffer && pDnloadID) )
  696. return SFERR_INVALID_PARAM;
  697. // variables used in this function
  698. #define ID_TABLE_SIZE 50
  699. MMRESULT mmresult;
  700. DWORD dwMaxID = 0; // maximum id of effects entered into the following table
  701. DNHANDLE rgdwDnloadIDTable[ID_TABLE_SIZE];
  702. DNHANDLE dwCurrentDnloadID = 0;
  703. int nNextID = 0;
  704. HRESULT hResult = SUCCESS;
  705. DWORD dwBytesRead;
  706. DWORD dwBytesToRead;
  707. BYTE* pParam = NULL;
  708. BOOL bDone = FALSE;
  709. BOOL bSubEffects = FALSE;
  710. DWORD dwID;
  711. DWORD c; // cleanup counter variable
  712. // debugging variables (to make sure we destroy all but one
  713. // created effect on success, and that we destory every
  714. // created effect on failure)...
  715. #ifdef _DEBUG
  716. int nEffectsCreated = 0;
  717. int nEffectsDestroyed = 0;
  718. BOOL bFunctionSuccessful = FALSE;
  719. #endif //_DEBUG
  720. // clear effect table (we check it during cleanup... anything
  721. // that isn't NULL gets destroyed.)
  722. memset(rgdwDnloadIDTable,NULL,sizeof(rgdwDnloadIDTable));
  723. // open a RIFF memory file using the buffer
  724. MMIOINFO mmioinfo;
  725. mmioinfo.dwFlags = 0;
  726. mmioinfo.fccIOProc = FOURCC_MEM;
  727. mmioinfo.pIOProc = NULL;
  728. mmioinfo.wErrorRet = 0;
  729. mmioinfo.htask = NULL;
  730. mmioinfo.cchBuffer = dwByteCount;
  731. mmioinfo.pchBuffer = (char*)pBuffer;
  732. mmioinfo.pchNext = 0;
  733. mmioinfo.pchEndRead = 0;
  734. mmioinfo.lBufOffset = 0;
  735. mmioinfo.adwInfo[0] = 0;
  736. mmioinfo.adwInfo[1] = 0;
  737. mmioinfo.adwInfo[2] = 0;
  738. mmioinfo.dwReserved1 = 0;
  739. mmioinfo.dwReserved2 = 0;
  740. mmioinfo.hmmio = NULL;
  741. HMMIO hmmio;
  742. hmmio = mmioOpen(NULL, &mmioinfo, MMIO_READWRITE);
  743. if(hmmio == NULL)
  744. {
  745. hResult = MMIOErrorToSFERRor(mmioinfo.wErrorRet);
  746. goto cleanup;
  747. }
  748. // descend into FORC RIFF
  749. MMCKINFO mmckinfoForceEffectRIFF;
  750. mmckinfoForceEffectRIFF.fccType = FCC_FORCE_EFFECT_RIFF;
  751. mmresult = mmioDescend(hmmio, &mmckinfoForceEffectRIFF, NULL, MMIO_FINDRIFF);
  752. if(mmresult != MMSYSERR_NOERROR)
  753. {
  754. hResult = MMIOErrorToSFERRor(mmresult);
  755. goto cleanup;
  756. }
  757. //! handle loading of GUID chunk when its implemented/testable
  758. // descend into trak list
  759. MMCKINFO mmckinfoTrackLIST;
  760. mmckinfoTrackLIST.fccType = FCC_TRACK_LIST;
  761. mmresult = mmioDescend(hmmio, &mmckinfoTrackLIST, &mmckinfoForceEffectRIFF,
  762. MMIO_FINDLIST);
  763. if(mmresult != MMSYSERR_NOERROR)
  764. {
  765. hResult = MMIOErrorToSFERRor(mmresult);
  766. goto cleanup;
  767. }
  768. // descend into the first efct list (there has to be at least one effect)
  769. MMCKINFO mmckinfoEffectLIST;
  770. mmckinfoEffectLIST.fccType = FCC_EFFECT_LIST;
  771. mmresult = mmioDescend(hmmio, &mmckinfoEffectLIST, &mmckinfoTrackLIST,
  772. MMIO_FINDLIST);
  773. if(mmresult != MMSYSERR_NOERROR)
  774. {
  775. hResult = MMIOErrorToSFERRor(mmresult);
  776. goto cleanup;
  777. }
  778. bDone = FALSE;
  779. do
  780. {
  781. // descend into id chunk
  782. MMCKINFO mmckinfoIDCHUNK;
  783. mmckinfoIDCHUNK.ckid = FCC_ID_CHUNK;
  784. mmresult = mmioDescend(hmmio, &mmckinfoIDCHUNK, &mmckinfoEffectLIST,
  785. MMIO_FINDCHUNK);
  786. if(mmresult != MMSYSERR_NOERROR)
  787. {
  788. hResult = MMIOErrorToSFERRor(mmresult);
  789. goto cleanup;
  790. }
  791. // read the id
  792. //DWORD dwID; moved to being function global so we can use it near the end
  793. dwBytesToRead = sizeof(DWORD);
  794. dwBytesRead = mmioRead(hmmio, (char*)&dwID, dwBytesToRead);
  795. if(dwBytesRead != dwBytesToRead)
  796. {
  797. if(dwBytesRead == 0)
  798. hResult = VFX_ERR_FILE_END_OF_FILE;
  799. else
  800. hResult = MMIOErrorToSFERRor(MMIOERR_CANNOTREAD);
  801. goto cleanup;
  802. }
  803. if(dwID >= ID_TABLE_SIZE)
  804. {
  805. hResult = VFX_ERR_FILE_BAD_FORMAT;
  806. goto cleanup;
  807. }
  808. // ascend from id chunk
  809. mmresult = mmioAscend(hmmio, &mmckinfoIDCHUNK, 0);
  810. if(mmresult != MMSYSERR_NOERROR)
  811. {
  812. hResult = MMIOErrorToSFERRor(mmresult);
  813. goto cleanup;
  814. }
  815. // descend into data chunk
  816. MMCKINFO mmckinfoDataCHUNK;
  817. mmckinfoDataCHUNK.ckid = FCC_DATA_CHUNK;
  818. mmresult = mmioDescend(hmmio, &mmckinfoDataCHUNK, &mmckinfoEffectLIST,
  819. MMIO_FINDCHUNK);
  820. if(mmresult != MMSYSERR_NOERROR)
  821. {
  822. hResult = MMIOErrorToSFERRor(mmresult);
  823. goto cleanup;
  824. }
  825. // read the effect structure
  826. EFFECT effect;
  827. dwBytesToRead = sizeof(EFFECT);
  828. dwBytesRead = mmioRead(hmmio, (char*)&effect, dwBytesToRead);
  829. if(dwBytesRead != dwBytesToRead)
  830. {
  831. if(dwBytesRead == 0)
  832. hResult = VFX_ERR_FILE_END_OF_FILE;
  833. else
  834. hResult = MMIOErrorToSFERRor(MMIOERR_CANNOTREAD);
  835. goto cleanup;
  836. }
  837. // get the envelope structure
  838. ENVELOPE envelope;
  839. dwBytesToRead = sizeof(ENVELOPE);
  840. dwBytesRead = mmioRead(hmmio, (char*)&envelope, dwBytesToRead);
  841. if(dwBytesRead != dwBytesToRead)
  842. {
  843. if(dwBytesRead == 0)
  844. hResult = VFX_ERR_FILE_END_OF_FILE;
  845. else
  846. hResult = MMIOErrorToSFERRor(MMIOERR_CANNOTREAD);
  847. goto cleanup;
  848. }
  849. // calculate the size of and allocate a param structure
  850. if(pParam != NULL)
  851. {
  852. delete [] pParam;
  853. pParam = NULL;
  854. }
  855. // find cur pos w/o changing it
  856. DWORD dwCurrentFilePos = mmioSeek(hmmio, 0, SEEK_CUR);
  857. if(dwCurrentFilePos == -1)
  858. {
  859. hResult = MMIOErrorToSFERRor(MMIOERR_CANNOTSEEK);
  860. goto cleanup;
  861. }
  862. DWORD dwEndOfChunk = mmckinfoDataCHUNK.dwDataOffset
  863. + mmckinfoDataCHUNK.cksize;
  864. dwBytesToRead = dwEndOfChunk - dwCurrentFilePos;
  865. pParam = new BYTE[dwBytesToRead];
  866. if(pParam == NULL)
  867. {
  868. hResult = VFX_ERR_FILE_OUT_OF_MEMORY;
  869. goto cleanup;
  870. }
  871. // get the param structure
  872. dwBytesRead = mmioRead(hmmio, (char*)pParam, dwBytesToRead);
  873. if(dwBytesRead != dwBytesToRead)
  874. {
  875. if(dwBytesRead == 0)
  876. hResult = VFX_ERR_FILE_END_OF_FILE;
  877. else
  878. hResult = MMIOErrorToSFERRor(MMIOERR_CANNOTREAD);
  879. goto cleanup;
  880. }
  881. // ascend the data chunk
  882. mmresult = mmioAscend(hmmio, &mmckinfoDataCHUNK, 0);
  883. if(mmresult != MMSYSERR_NOERROR)
  884. {
  885. hResult = MMIOErrorToSFERRor(mmresult);
  886. goto cleanup;
  887. }
  888. // ascend from the efct list
  889. mmresult = mmioAscend(hmmio, &mmckinfoEffectLIST, 0);
  890. if(mmresult != MMSYSERR_NOERROR)
  891. {
  892. hResult = MMIOErrorToSFERRor(mmresult);
  893. goto cleanup;
  894. }
  895. // reset subeffects flag
  896. bSubEffects = FALSE;
  897. // special fix-ups for user-defined
  898. if(effect.m_Type == EF_USER_DEFINED &&
  899. (effect.m_SubType == PL_CONCATENATE
  900. || effect.m_SubType == PL_SUPERIMPOSE
  901. || effect.m_SubType == UD_WAVEFORM))
  902. {
  903. if(effect.m_SubType == UD_WAVEFORM)
  904. {
  905. // fix the pointer to the force data in the UD_PARAM
  906. BYTE* pForceData = pParam + sizeof(UD_PARAM); // - sizeof(LONG*);
  907. UD_PARAM* pUDParam = (UD_PARAM*)pParam;
  908. pUDParam->m_pForceData = (LONG*)pForceData;
  909. // do a sanity check
  910. if(pUDParam->m_NumVectors > MAX_UD_PARAM_FORCE_DATA_COUNT)
  911. {
  912. hResult = VFX_ERR_FILE_BAD_FORMAT;
  913. goto cleanup;
  914. }
  915. }
  916. else if(effect.m_SubType == PL_CONCATENATE
  917. || effect.m_SubType == PL_SUPERIMPOSE)
  918. {
  919. // fix the pointer to the PSWEFFECT list in the PL_PARAM
  920. BYTE* pProcessList = pParam + sizeof(PL_PARAM);
  921. PL_PARAM* pPLParam = (PL_PARAM*)pParam;
  922. pPLParam->m_pProcessList = (PPSWEFFECT)pProcessList;
  923. // do a sanity check
  924. if(pPLParam->m_NumEffects > MAX_PL_PARAM_NUM_EFFECTS)
  925. {
  926. hResult = VFX_ERR_FILE_BAD_FORMAT;
  927. goto cleanup;
  928. }
  929. // make sure all entries in this process list are valid
  930. ULONG i;
  931. for (i = 0; i < pPLParam->m_NumEffects; i++)
  932. {
  933. UINT nThisID = (UINT)pPLParam->m_pProcessList[i];
  934. if(nThisID >= ID_TABLE_SIZE)
  935. {
  936. hResult = VFX_ERR_FILE_BAD_FORMAT;
  937. goto cleanup;
  938. }
  939. DNHANDLE dwThisDnloadID=rgdwDnloadIDTable[nThisID];
  940. if(dwThisDnloadID == 0)
  941. {
  942. hResult = VFX_ERR_FILE_BAD_FORMAT;
  943. goto cleanup;
  944. }
  945. }
  946. // use the ID table to insert the download ID's
  947. for(i=0; i<pPLParam->m_NumEffects; i++)
  948. {
  949. UINT nThisID = (UINT)pPLParam->m_pProcessList[i];
  950. DNHANDLE dwThisDnloadID=rgdwDnloadIDTable[nThisID];
  951. pPLParam->m_pProcessList[i] = (IDirectInputEffect*)dwThisDnloadID;
  952. // since this effect has been used in a process list,
  953. // and it will be destroyed after being used in CreateEffect,
  954. // null it's entry in the table so it doesn't get erroneously
  955. // redestroyed during cleanup of an error.
  956. rgdwDnloadIDTable[nThisID] = NULL;
  957. }
  958. // we have a process list with sub effects, so set the flag
  959. bSubEffects = TRUE;
  960. }
  961. else
  962. {
  963. // there are no other UD sub-types
  964. hResult = VFX_ERR_FILE_BAD_FORMAT;
  965. goto cleanup;
  966. }
  967. }
  968. // download the effect
  969. // create the effect
  970. //hResult = pISWForce->CreateEffect(&pISWEffect, &effect,
  971. // &envelope, pParam);
  972. if(effect.m_SubType != PL_CONCATENATE && effect.m_SubType != PL_SUPERIMPOSE)
  973. {
  974. EFFECT SmallEffect;
  975. SmallEffect.m_Bytes = sizeof(EFFECT);
  976. SmallEffect.m_Type = effect.m_Type;
  977. SmallEffect.m_SubType = effect.m_SubType;
  978. SmallEffect.m_AxisMask = effect.m_AxisMask;
  979. SmallEffect.m_DirectionAngle2D = effect.m_DirectionAngle2D;
  980. SmallEffect.m_DirectionAngle3D = effect.m_DirectionAngle3D;
  981. SmallEffect.m_Duration = effect.m_Duration;
  982. SmallEffect.m_ForceOutputRate = effect.m_ForceOutputRate;
  983. SmallEffect.m_Gain = effect.m_Gain;
  984. SmallEffect.m_ButtonPlayMask = effect.m_ButtonPlayMask;
  985. *pDnloadID = 0;
  986. hResult = FFD_DownloadEffect(pDnloadID, &SmallEffect, &envelope, pParam, ulAction);
  987. }
  988. else
  989. {
  990. ULONG ulButtonPlayMask = effect.m_ButtonPlayMask;
  991. int nNumEffects = ((PL_PARAM*)pParam)->m_NumEffects;
  992. ULONG ulProcessMode = effect.m_SubType;
  993. PDNHANDLE pPListArray = new DNHANDLE[ID_TABLE_SIZE];
  994. for(int i=0; i<nNumEffects; i++)
  995. pPListArray[i] = (DNHANDLE)(((PL_PARAM*)pParam)->m_pProcessList[i]);
  996. *pDnloadID = 0;
  997. hResult = FFD_VFXProcessEffect(ulButtonPlayMask, pDnloadID, nNumEffects,
  998. ulProcessMode,pPListArray);
  999. }
  1000. // moved check for success below...
  1001. #ifdef _DEBUG
  1002. if (!FAILED(hResult))
  1003. nEffectsCreated++;
  1004. #endif //_DEBUG
  1005. // if there were sub effects we need to destroy them, making
  1006. // their ref counts become 1, so the entire effect can be destroyed
  1007. // by destroying the root effect.
  1008. #if 0
  1009. if (bSubEffects)
  1010. {
  1011. PL_PARAM* pPLParam = (PL_PARAM*)pParam;
  1012. for (ULONG i = 0; i < pPLParam->m_NumEffects; i++)
  1013. {
  1014. ASSERT(pPLParam->m_pProcessList[i] != NULL);
  1015. pISWForce->DestroyEffect(pPLParam->m_pProcessList[i]);
  1016. #ifdef _DEBUG
  1017. nEffectsDestroyed++;
  1018. #endif //_DEBUG
  1019. }
  1020. }
  1021. #endif
  1022. // now check for success of CreateEffect, because regardless of
  1023. // whether or not it succeeded, we -must- have destroyed the subeffects
  1024. // before continuing, or cleanup will not work properly...
  1025. if (SUCCESS != hResult)
  1026. {
  1027. goto cleanup;
  1028. }
  1029. // put the id/DnloadID pair into the map
  1030. rgdwDnloadIDTable[dwID] = *pDnloadID; //pISWEffect;
  1031. // keep track of the highest ID in the effect table
  1032. if (dwID > dwMaxID)
  1033. dwMaxID = dwID;
  1034. // try to descend the next efct
  1035. mmresult = mmioDescend(hmmio, &mmckinfoEffectLIST, &mmckinfoTrackLIST,
  1036. MMIO_FINDLIST);
  1037. if(mmresult == MMIOERR_CHUNKNOTFOUND)
  1038. {
  1039. // we are at the end of the list
  1040. bDone = TRUE;
  1041. }
  1042. else if(mmresult != MMSYSERR_NOERROR)
  1043. {
  1044. hResult = MMIOErrorToSFERRor(mmresult);
  1045. goto cleanup;
  1046. }
  1047. }
  1048. while(!bDone);
  1049. // ascend from trak list
  1050. mmresult = mmioAscend(hmmio, &mmckinfoTrackLIST, 0);
  1051. if(mmresult != MMSYSERR_NOERROR)
  1052. {
  1053. hResult = MMIOErrorToSFERRor(mmresult);
  1054. goto cleanup;
  1055. }
  1056. // ascend from FORCE RIFF
  1057. mmresult = mmioAscend(hmmio, &mmckinfoForceEffectRIFF, 0);
  1058. if(mmresult != MMSYSERR_NOERROR)
  1059. {
  1060. hResult = MMIOErrorToSFERRor(mmresult);
  1061. goto cleanup;
  1062. }
  1063. // get the return value
  1064. //*pDnloadID = dwCurrentDnloadID;
  1065. // clear the final effect's entry in the table so we don't destroy it during cleanup
  1066. rgdwDnloadIDTable[dwID] = 0;
  1067. // at this point the entire table should be NULL... make sure of it
  1068. for (c = 0; c <= dwMaxID; c++)
  1069. ;
  1070. #ifdef _DEBUG
  1071. bFunctionSuccessful = TRUE;
  1072. #endif //_DEBUG
  1073. cleanup:
  1074. // destroy everything in the effect table that isn't NULL
  1075. for (c = 0; c <= dwMaxID; c++)
  1076. if (NULL != rgdwDnloadIDTable[c])
  1077. {
  1078. FFD_DestroyEffect(rgdwDnloadIDTable[c]);
  1079. rgdwDnloadIDTable[c] = 0;
  1080. #ifdef _DEBUG
  1081. nEffectsDestroyed++;
  1082. #endif //_DEBUG
  1083. }
  1084. #ifdef _DEBUG
  1085. // make sure we destroy all but one created effect on success,
  1086. // and that we destory -every- created effect on failure.
  1087. if (bFunctionSuccessful)
  1088. {
  1089. ;//ASSERT(nEffectsCreated - 1 == nEffectsDestroyed);
  1090. }
  1091. else
  1092. {
  1093. ;//ASSERT(nEffectsCreated == nEffectsDestroyed);
  1094. }
  1095. #endif //_DEBUG
  1096. // close the memory RIFF file
  1097. if(hmmio != NULL)
  1098. {
  1099. mmresult = mmioClose(hmmio, 0);
  1100. if(mmresult != MMSYSERR_NOERROR)
  1101. {
  1102. hResult = MMIOErrorToSFERRor(mmresult);
  1103. }
  1104. }
  1105. // de-allocate any allocated memory
  1106. if(pParam != NULL)
  1107. delete [] pParam;
  1108. // return the error code, which is SUCCESS, unless there was an error
  1109. return hResult;
  1110. }
  1111. HRESULT MMIOErrorToSFERRor(MMRESULT mmresult)
  1112. {
  1113. HRESULT hResult;
  1114. switch(mmresult)
  1115. {
  1116. case MMIOERR_FILENOTFOUND:
  1117. hResult = VFX_ERR_FILE_NOT_FOUND;
  1118. break;
  1119. case MMIOERR_OUTOFMEMORY:
  1120. hResult = VFX_ERR_FILE_OUT_OF_MEMORY;
  1121. break;
  1122. case MMIOERR_CANNOTOPEN:
  1123. hResult = VFX_ERR_FILE_CANNOT_OPEN;
  1124. break;
  1125. case MMIOERR_CANNOTCLOSE:
  1126. hResult = VFX_ERR_FILE_CANNOT_CLOSE;
  1127. break;
  1128. case MMIOERR_CANNOTREAD:
  1129. hResult = VFX_ERR_FILE_CANNOT_READ;
  1130. break;
  1131. case MMIOERR_CANNOTWRITE:
  1132. hResult = VFX_ERR_FILE_CANNOT_WRITE;
  1133. break;
  1134. case MMIOERR_CANNOTSEEK:
  1135. hResult = VFX_ERR_FILE_CANNOT_SEEK;
  1136. break;
  1137. case MMIOERR_CANNOTEXPAND:
  1138. hResult = VFX_ERR_FILE_UNKNOWN_ERROR;
  1139. break;
  1140. case MMIOERR_CHUNKNOTFOUND:
  1141. hResult = VFX_ERR_FILE_BAD_FORMAT;
  1142. break;
  1143. case MMIOERR_UNBUFFERED:
  1144. hResult = VFX_ERR_FILE_UNKNOWN_ERROR;
  1145. break;
  1146. case MMIOERR_PATHNOTFOUND:
  1147. hResult = VFX_ERR_FILE_NOT_FOUND;
  1148. break;
  1149. case MMIOERR_ACCESSDENIED:
  1150. hResult = VFX_ERR_FILE_ACCESS_DENIED;
  1151. break;
  1152. case MMIOERR_SHARINGVIOLATION:
  1153. hResult = VFX_ERR_FILE_SHARING_VIOLATION;
  1154. break;
  1155. case MMIOERR_NETWORKERROR:
  1156. hResult = VFX_ERR_FILE_NETWORK_ERROR;
  1157. break;
  1158. case MMIOERR_TOOMANYOPENFILES:
  1159. hResult = VFX_ERR_FILE_TOO_MANY_OPEN_FILES;
  1160. break;
  1161. case MMIOERR_INVALIDFILE:
  1162. hResult = VFX_ERR_FILE_INVALID;
  1163. break;
  1164. default:
  1165. hResult = VFX_ERR_FILE_UNKNOWN_ERROR;
  1166. break;
  1167. }
  1168. return hResult;
  1169. }