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.

3905 lines
125 KiB

  1. /****************************************************************************
  2. MODULE: MIDI_OBJ.CPP
  3. Tab stops 5 9
  4. Copyright 1995, 1996, Microsoft Corporation, All Rights Reserved.
  5. PURPOSE: Methods for SWFF MIDI device object
  6. FUNCTIONS: Classes methods
  7. Author(s): Name:
  8. ---------- ----------------
  9. MEA Manolito E. Adan
  10. Revision History:
  11. -----------------
  12. Version Date Author Comments
  13. ------- ------ ----- -----------------------------------------
  14. 0.1 10-Sep-96 MEA original
  15. 1.1 20-May-97 MEA Added Mutex and Thread safe code
  16. 17-Jun-97 MEA Fixed bug Midi Handle lost if 1st process
  17. terminated.
  18. 16-Mar-99 waltw Add dwDeviceID param: CJoltMidi::Initialize
  19. and pass down food chain
  20. 16-Mar-99 waltw GetRing0DriverName in InitDigitalOverDrive
  21. now passes down joystick ID
  22. 20-Mar-99 waltw Added dwDeviceID param to DetectMidiDevice
  23. 20-Mar-99 waltw Comment out invalid call to CloseHandle in dtor
  24. ****************************************************************************/
  25. #include <assert.h>
  26. #include <windows.h>
  27. #include <stdlib.h>
  28. #include <stdio.h>
  29. #include <string.h>
  30. #include <mmsystem.h>
  31. #include "SW_Error.hpp"
  32. #include "midi_obj.hpp"
  33. #include "vxdioctl.hpp"
  34. #include "joyregst.hpp"
  35. #include "FFDevice.h"
  36. #include "CritSec.h"
  37. #define NT50 1
  38. #include "DTrans.h"
  39. DataTransmitter* g_pDataTransmitter = NULL;
  40. /****************************************************************************
  41. Declaration of externs
  42. ****************************************************************************/
  43. extern void CALLBACK midiOutputHandler(HMIDIOUT, UINT, DWORD, DWORD, DWORD);
  44. extern TCHAR szDeviceName[MAX_SIZE_SNAME];
  45. extern CJoltMidi *g_pJoltMidi;
  46. /****************************************************************************
  47. Declaration of variables
  48. ****************************************************************************/
  49. /****************************************************************************
  50. Macros etc
  51. ****************************************************************************/
  52. #ifdef _DEBUG
  53. extern char g_cMsg[160];
  54. void DebugOut(LPCTSTR szDebug)
  55. {
  56. g_CriticalSection.Enter();
  57. OutputDebugString(szDebug);
  58. g_CriticalSection.Leave();
  59. #ifdef _LOG_DEBUG
  60. #pragma message("Compiling with Debug Log to sw_effct.txt")
  61. FILE *pf = fopen("sw_effct.txt", "a");
  62. if (pf != NULL)
  63. {
  64. fputs(szDebug, pf);
  65. fclose(pf);
  66. }
  67. #endif // _LOG_DEBUG
  68. }
  69. #else !_DEBUG
  70. #define DebugOut(x)
  71. #endif // _DEBUG
  72. // ****************************************************************************
  73. // *** --- Member functions for base CJoltMidi
  74. //
  75. // ****************************************************************************
  76. //
  77. // ----------------------------------------------------------------------------
  78. // Function: CJoltMidi::CJoltMidi
  79. // Purpose: Constructor(s)/Destructor for CJoltMidi Object
  80. // Parameters:
  81. // Returns:
  82. // Algorithm:
  83. // ----------------------------------------------------------------------------
  84. CJoltMidi::CJoltMidi(void)
  85. {
  86. //
  87. // --- THIS IS A CRITICAL SECTION
  88. //
  89. CriticalLock cl;
  90. static char cWaterMark[MAX_SIZE_SNAME] = {"SWFF_SHAREDMEMORY MEA"};
  91. BOOL bAlreadyMapped = FALSE;
  92. #ifdef _DEBUG
  93. DebugOut("sw_effct(DX):CJoltMidi::CJoltMidi\n");
  94. #endif
  95. memset(this, 0, sizeof(CJoltMidi));
  96. m_hVxD = INVALID_HANDLE_VALUE;
  97. // Create an in-memory memory-mapped file
  98. m_hSharedMemoryFile = CreateFileMapping((HANDLE) 0xFFFFFFFF,
  99. NULL, PAGE_READWRITE, 0, SIZE_SHARED_MEMORY,
  100. __TEXT(SWFF_SHAREDMEM_FILE));
  101. if (m_hSharedMemoryFile == NULL)
  102. {
  103. #ifdef _DEBUG
  104. DebugOut("sw_effct(DX):ERROR! Failed to create Memory mapped file\n");
  105. #endif
  106. }
  107. else
  108. {
  109. if (GetLastError() == ERROR_ALREADY_EXISTS)
  110. {
  111. bAlreadyMapped = TRUE;
  112. }
  113. // File mapping created successfully.
  114. // Map a view of the file into the address space.
  115. m_pSharedMemory = (PSHARED_MEMORY) MapViewOfFile(m_hSharedMemoryFile,
  116. FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
  117. if ((BYTE *) m_pSharedMemory == NULL)
  118. {
  119. #ifdef _DEBUG
  120. DebugOut("sw_effct(DX):ERROR! Failed to Map view of shared memory\n");
  121. #endif
  122. }
  123. // ***** Shared Memory Access *****
  124. LockSharedMemory();
  125. if (!bAlreadyMapped)
  126. {
  127. // Set watermark and initialize, Bump Ref Count
  128. memcpy(&m_pSharedMemory->m_cWaterMark[0], &cWaterMark[0], MAX_SIZE_SNAME);
  129. m_pSharedMemory->m_RefCnt = 0;
  130. }
  131. m_pSharedMemory->m_RefCnt++;
  132. }
  133. #ifdef _DEBUG
  134. wsprintf(g_cMsg, "sw_effct(DX): Shared Memory:%lx, m_RefCnt:%d\n",m_pSharedMemory,
  135. m_pSharedMemory->m_RefCnt);
  136. DebugOut(g_cMsg);
  137. #endif
  138. UnlockSharedMemory();
  139. // ***** End of Shared Memory Access *****
  140. // --- END OF CRITICAL SECTION
  141. //
  142. }
  143. // --- Destructor
  144. CJoltMidi::~CJoltMidi()
  145. {
  146. //
  147. // --- THIS IS A CRITICAL SECTION
  148. //
  149. CriticalLock cl;
  150. BOOL bKillObject = FALSE;
  151. #ifdef _DEBUG
  152. DebugOut("sw_effct(DX):CJoltMidi::~CJoltMidi()\n");
  153. #endif
  154. // Normal CJoltMidi Destructor
  155. // Free all buffers and other data
  156. if (m_lpCallbackInstanceData) FreeCallbackInstanceData();
  157. // Free the MIDI Effect objects (except RTC Spring)
  158. DeleteDownloadedEffects();
  159. // Free the Primary SYS_EX locked memory
  160. if (m_hPrimaryBuffer)
  161. {
  162. GlobalUnlock(m_hPrimaryBuffer);
  163. GlobalFree(m_hPrimaryBuffer);
  164. }
  165. // ***** Shared Memory Access *****
  166. LockSharedMemory();
  167. // Decrement Ref Count and clean up if equal to zero.
  168. m_pSharedMemory->m_RefCnt--;
  169. #ifdef _DEBUG
  170. wsprintf(g_cMsg,"CJoltMidi::~CJoltMidi. RefCnt = %d\n",m_pSharedMemory->m_RefCnt);
  171. DebugOut(g_cMsg);
  172. #endif
  173. if (0 == m_pSharedMemory->m_RefCnt)
  174. {
  175. bKillObject = TRUE;
  176. // Tri-state Midi lines
  177. CMD_SetDeviceState(SWDEV_KILL_MIDI);
  178. if (m_pSharedMemory->m_hMidiOut) {
  179. if (COMM_WINMM == m_COMMInterface) {
  180. DebugOut("CJoltMidi::~CJoltMidi. Resetting and closing Midi handles\n");
  181. // Reset, close and release Midi Handles
  182. midiOutReset(HMIDIOUT(m_pSharedMemory->m_hMidiOut));
  183. midiOutClose(HMIDIOUT(m_pSharedMemory->m_hMidiOut));
  184. }
  185. // This is bogus - midiOutClose has already closed this handle
  186. // if (g_pDataTransmitter == NULL) { // DataTransmitter closes its own handle
  187. // CloseHandle(m_pSharedMemory->m_hMidiOut);
  188. // }
  189. m_pSharedMemory->m_hMidiOut = NULL;
  190. }
  191. // Kill Data Transmitter
  192. if (g_pDataTransmitter != NULL) {
  193. delete g_pDataTransmitter;
  194. g_pDataTransmitter = NULL;
  195. }
  196. // Release Mutex handles
  197. // if (m_hSWFFDataMutex) CloseHandle(m_hSWFFDataMutex); -- Unlock will take care of this
  198. // Kill RTC Spring object
  199. if (m_pJoltEffectList[SYSTEM_RTCSPRING_ID])
  200. {
  201. delete m_pJoltEffectList[SYSTEM_RTCSPRING_ID];
  202. m_pJoltEffectList[SYSTEM_RTCSPRING_ID] = NULL;
  203. }
  204. // Release the Midi Output Event handles
  205. if (m_hMidiOutputEvent)
  206. {
  207. CloseHandle (m_hMidiOutputEvent);
  208. m_hMidiOutputEvent = NULL;
  209. }
  210. }
  211. UnlockSharedMemory();
  212. // ***** End of Shared Memory Access *****
  213. // Release Memory Mapped file handles
  214. if (m_hSharedMemoryFile)
  215. {
  216. BOOL bRet = UnmapViewOfFile((LPCVOID) m_pSharedMemory);
  217. bRet = CloseHandle(m_hSharedMemoryFile);
  218. }
  219. // Close VxD handles
  220. if (g_pDriverCommunicator != NULL)
  221. {
  222. delete g_pDriverCommunicator;
  223. g_pDriverCommunicator = NULL;
  224. }
  225. memset(this, 0, sizeof(CJoltMidi));
  226. m_hVxD = INVALID_HANDLE_VALUE;
  227. // --- END OF CRITICAL SECTION
  228. //
  229. if (bKillObject)
  230. {
  231. // Delete the critical section object
  232. // DeleteCriticalSection(&g_SWFFCriticalSection);
  233. }
  234. }
  235. // ----------------------------------------------------------------------------
  236. // Function: CJoltMidi::Initialize
  237. // Purpose: Initializer
  238. // Parameters:
  239. // Returns:
  240. // Algorithm:
  241. // ----------------------------------------------------------------------------
  242. HRESULT CJoltMidi::Initialize(DWORD dwDeviceID)
  243. {
  244. //
  245. // --- THIS IS A CRITICAL SECTION
  246. //
  247. CriticalLock cl;
  248. HRESULT hRet = SUCCESS;
  249. // initialize the MIDI output information block
  250. m_MidiOutInfo.uDeviceType = MIDI_OUT;
  251. m_MidiOutInfo.hMidiOut = NULL;
  252. m_MidiOutInfo.fAlwaysKeepOpen = TRUE;
  253. m_MidiOutInfo.uDeviceStatus = MIDI_DEVICE_IDLE;
  254. m_MidiOutInfo.MidiHdr.dwBytesRecorded = 0;
  255. m_MidiOutInfo.MidiHdr.dwUser = 0;
  256. m_MidiOutInfo.MidiHdr.dwOffset = 0;
  257. m_MidiOutInfo.MidiHdr.dwFlags = 0;
  258. // Allocate and lock global memory for SysEx messages
  259. m_hPrimaryBuffer = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, MAX_SYS_EX_BUFFER_SIZE);
  260. assert(m_hPrimaryBuffer);
  261. if(NULL == m_hPrimaryBuffer)
  262. {
  263. return (SFERR_DRIVER_ERROR);
  264. }
  265. m_pPrimaryBuffer = (LPBYTE) GlobalLock(m_hPrimaryBuffer);
  266. assert(m_pPrimaryBuffer);
  267. if(NULL == m_pPrimaryBuffer)
  268. {
  269. GlobalFree(m_hPrimaryBuffer);
  270. return (SFERR_DRIVER_ERROR);
  271. }
  272. // Initialize the IOCTL interface to VjoyD mini-driver
  273. hRet = InitDigitalOverDrive(dwDeviceID);
  274. if (SUCCESS != hRet)
  275. {
  276. DebugOut("Warning! Could not Initialize Digital OverDrive\n");
  277. return (hRet);
  278. }
  279. else
  280. DebugOut("InitDigitalOverDrive - Success\n");
  281. // Create a Callback Event
  282. HANDLE hEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, SWFF_MIDIEVENT);
  283. if (NULL == hEvent)
  284. {
  285. // Create an Event for notification when Midi Output has completed
  286. m_hMidiOutputEvent = CreateEvent(NULL, // No security
  287. TRUE, // Manual reset
  288. FALSE, // Initial event is non-signaled
  289. SWFF_MIDIEVENT ); // Named
  290. assert(m_hMidiOutputEvent);
  291. }
  292. else
  293. m_hMidiOutputEvent = hEvent;
  294. // We are only called after g_pJoltMidi is created
  295. assert(g_pJoltMidi);
  296. PDELAY_PARAMS pDelayParams = g_pJoltMidi->DelayParamsPtrOf();
  297. GetDelayParams(dwDeviceID, pDelayParams);
  298. // Reset HW first
  299. g_pDriverCommunicator->ResetDevice();
  300. Sleep(DelayParamsPtrOf()->dwHWResetDelay);
  301. // Set MIDI channel to default then Detect a Midi Device
  302. SetMidiChannel(DEFAULT_MIDI_CHANNEL);
  303. if (!DetectMidiDevice(dwDeviceID, // joystick ID
  304. &m_MidiOutInfo.uDeviceID, // Midi Device ID
  305. &m_COMMInterface, // COMM_WINMM||COMM_BACKDOOR
  306. // ||COMM_SERIAL
  307. &m_COMMPort)) // Port address
  308. {
  309. DebugOut("SW_EFFCT: Warning! No Midi Device detected\n");
  310. return (SFERR_DRIVER_ERROR);
  311. }
  312. else
  313. {
  314. #ifdef _DEBUG
  315. wsprintf(g_cMsg,"DetectMidiDevice returned: DeviceID=%d, COMMInterface=%x, COMMPort=%x\n",
  316. m_MidiOutInfo.uDeviceID, m_COMMInterface, m_COMMPort);
  317. DebugOut(g_cMsg);
  318. #endif
  319. }
  320. // Allocate the Instance data buffer
  321. m_lpCallbackInstanceData = AllocCallbackInstanceData();
  322. assert(m_lpCallbackInstanceData);
  323. // Initialize Midi channel, then open the Input and Output channels
  324. m_MidiChannel = DEFAULT_MIDI_CHANNEL;
  325. // Send Initialization packet(s) to Jolt
  326. hRet = CMD_Init();
  327. if (SUCCESS != hRet)
  328. {
  329. DebugOut("Warning! Could not Initialize Jolt\n");
  330. return (hRet);
  331. }
  332. else
  333. DebugOut("JOLT CMD_Init - Success\n");
  334. // At this point, we have a valid MIDI path...
  335. // Continue by setting up the ROM Effects default table entries
  336. // ID , OutputRate, Gain, Duration
  337. static ROM_FX_PARAM RomFxTable [] = {{ RE_ROMID1 , 100, 100, 12289 }, // Random Noise
  338. { RE_ROMID2 , 100, 100, 2625 }, // AircraftCarrierTakeOff
  339. { RE_ROMID3 , 100, 50, 166 }, // BasketballDribble
  340. { RE_ROMID4 , 100, 14, 10000 }, // CarEngineIdling
  341. { RE_ROMID5 , 100, 30, 1000 }, // Chainsaw
  342. { RE_ROMID6 , 100, 100, 1000 }, // ChainsawingThings
  343. { RE_ROMID7 , 100, 40, 10000 }, // DieselEngineIdling
  344. { RE_ROMID8 , 100, 100, 348 }, // Jump
  345. { RE_ROMID9 , 100, 100, 250 }, // Land
  346. { RE_ROMID10, 200, 100, 1000 }, // MachineGun
  347. { RE_ROMID11, 100, 100, 83 }, // Punched
  348. { RE_ROMID12, 100, 100, 1000 }, // RocketLauncher
  349. { RE_ROMID13, 100, 98, 500 }, // SecretDoor
  350. { RE_ROMID14, 100, 66, 25 }, // SwitchClick
  351. { RE_ROMID15, 100, 75, 500 }, // WindGust
  352. { RE_ROMID16, 100, 100, 2500 }, // WindShear
  353. { RE_ROMID17, 100, 100, 50 }, // Pistol
  354. { RE_ROMID18, 100, 100, 295 }, // Shotgun
  355. { RE_ROMID19, 500, 95, 1000 }, // Laser1
  356. { RE_ROMID20, 500, 96, 1000 }, // Laser2
  357. { RE_ROMID21, 500, 100, 1000 }, // Laser3
  358. { RE_ROMID22, 500, 100, 1000 }, // Laser4
  359. { RE_ROMID23, 500, 100, 1000 }, // Laser5
  360. { RE_ROMID24, 500, 70, 1000 }, // Laser6
  361. { RE_ROMID25, 100, 100, 25 }, // OutOfAmmo
  362. { RE_ROMID26, 100, 71, 1000 }, // LigntningGun
  363. { RE_ROMID27, 100, 100, 250 }, // Missile
  364. { RE_ROMID28, 100, 100, 1000 }, // GatlingGun
  365. { RE_ROMID29, 500, 97, 250 }, // ShortPlasma
  366. { RE_ROMID30, 500, 100, 500 }, // PlasmaCannon1
  367. { RE_ROMID31, 500, 99, 625 }, // PlasmaCannon2
  368. { RE_ROMID32, 100, 100, 440 }}; // Cannon
  369. // { RE_ROMID33, 100, 68, 1000 }, // FlameThrower
  370. // { RE_ROMID34, 100, 100, 75 }, // BoltActionRifle
  371. // { RE_ROMID35, 500, 100, 300 }, // Crossbow
  372. // { RE_ROMID36, 100, 100, 1000 }, // Sine
  373. // { RE_ROMID37, 100, 100, 1000 }}; // Cosine
  374. m_pRomFxTable = &RomFxTable[0];
  375. // ***** Shared Memory Access *****
  376. LockSharedMemory();
  377. LONG lRefCnt = m_pSharedMemory->m_RefCnt;
  378. UnlockSharedMemory();
  379. // ***** End of Shared Memory Access *****
  380. // Initialize the RTC_Spring object
  381. SYSTEM_PARAMS SystemParams;
  382. GetSystemParams(dwDeviceID, &SystemParams);
  383. RTCSPRING_PARAM RTCSpring = { sizeof(RTCSPRING_PARAM),
  384. DEFAULT_RTC_KX,
  385. DEFAULT_RTC_KY,
  386. DEFAULT_RTC_X0,
  387. DEFAULT_RTC_Y0,
  388. DEFAULT_RTC_XSAT,
  389. DEFAULT_RTC_YSAT,
  390. DEFAULT_RTC_XDBAND,
  391. DEFAULT_RTC_YDBAND };
  392. CMidiRTCSpring * pMidiRTCSpring = new CMidiRTCSpring(&RTCSpring);
  393. SetEffectByID(SYSTEM_RTCSPRING_ID, pMidiRTCSpring);
  394. DNHANDLE DnHandle;
  395. CMD_Download_RTCSpring(&(SystemParams.RTCSpringParam),&DnHandle);
  396. // initialize the joystick params
  397. JOYSTICK_PARAMS JoystickParams;
  398. GetJoystickParams(dwDeviceID, &JoystickParams);
  399. UpdateJoystickParams(&JoystickParams);
  400. // initialize the firmware params fudge factors (for the first time)
  401. // in the case of the FFD interface, this will be the only time they
  402. // are initialized, which may cause a problem because joystick is assumed
  403. // to be ID1
  404. PFIRMWARE_PARAMS pFirmwareParams = g_pJoltMidi->FirmwareParamsPtrOf();
  405. GetFirmwareParams(dwDeviceID, pFirmwareParams);
  406. // --- END OF CRITICAL SECTION
  407. //
  408. return (SUCCESS);
  409. }
  410. // *** ---------------------------------------------------------------------***
  411. // Function: CJoltMidi::LockSharedMemory
  412. // Purpose: Creates a Mutex for Shared Memory access
  413. // Parameters: none
  414. //
  415. //
  416. // Returns: TRUE if Mutex available else FALSE
  417. // Algorithm:
  418. //
  419. // Comments:
  420. //
  421. //
  422. // *** ---------------------------------------------------------------------***
  423. BOOL CJoltMidi::LockSharedMemory(void)
  424. {
  425. DWORD dwRet;
  426. { // --- THIS IS A CRITICAL SECTION
  427. CriticalLock cl;
  428. // Create the SWFF mutex
  429. HANDLE hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, SWFF_SHAREDMEM_MUTEX);
  430. if (NULL == hMutex) {
  431. // Doesn't exist yet, so create it
  432. hMutex = CreateMutex(NULL, TRUE, SWFF_SHAREDMEM_MUTEX);
  433. if (NULL == hMutex)
  434. {
  435. #ifdef _DEBUG
  436. DebugOut("Error! Could not create SWFFDataMutex\n");
  437. #endif
  438. m_hSWFFDataMutex = NULL;
  439. return (FALSE);
  440. }
  441. }
  442. // SUCCESS
  443. m_hSWFFDataMutex = hMutex;
  444. dwRet = WaitForSingleObject(m_hSWFFDataMutex, MUTEX_TIMEOUT);
  445. } // --- END OF CRITICAL SECTION
  446. if (WAIT_OBJECT_0 == dwRet)
  447. return (TRUE);
  448. else
  449. {
  450. #ifdef _DEBUG
  451. g_CriticalSection.Enter();
  452. wsprintf(g_cMsg,"CJoltMidi::LockSharedMemory() error return: %lx\n", dwRet);
  453. DebugOut(g_cMsg);
  454. g_CriticalSection.Leave();
  455. #endif
  456. return (FALSE);
  457. }
  458. }
  459. // *** ---------------------------------------------------------------------***
  460. // Function: CJoltMidi::UnlockSharedMemory
  461. // Purpose: Releases Mutex for Shared Memory access
  462. // Parameters: none
  463. //
  464. //
  465. // Returns: none
  466. // Algorithm:
  467. //
  468. // Comments:
  469. //
  470. //
  471. // *** ---------------------------------------------------------------------***
  472. void CJoltMidi::UnlockSharedMemory(void)
  473. {
  474. //
  475. // --- THIS IS A CRITICAL SECTION
  476. //
  477. g_CriticalSection.Enter();
  478. if (NULL != m_hSWFFDataMutex)
  479. {
  480. ReleaseMutex(m_hSWFFDataMutex);
  481. CloseHandle(m_hSWFFDataMutex);
  482. m_hSWFFDataMutex=NULL;
  483. }
  484. // --- END OF CRITICAL SECTION
  485. //
  486. g_CriticalSection.Leave();
  487. }
  488. // ----------------------------------------------------------------------------
  489. // Function: CJoltMidi::NewEffectID
  490. // Purpose: Generates a new Effect ID
  491. // Parameters: PDNHANDLE pDnloadID - Pointer to a new Effect ID
  492. //
  493. // Returns: TRUE if successful, else FALSE
  494. // Algorithm:
  495. // ----------------------------------------------------------------------------
  496. BOOL CJoltMidi::NewEffectID(PDNHANDLE pDnloadID)
  497. {
  498. //
  499. // --- THIS IS A CRITICAL SECTION
  500. //
  501. g_CriticalSection.Enter();
  502. BOOL bRet = FALSE;
  503. int nID_Index = 2; // ID0 = RTC Spring, ID1 = Friction cancellation
  504. for (int i=nID_Index; i<MAX_EFFECT_IDS; i++)
  505. {
  506. if (NULL == m_pJoltEffectList[i])
  507. {
  508. *pDnloadID = (DNHANDLE) i;
  509. #ifdef _DEBUG
  510. wsprintf(g_cMsg,"New Effect ID=%d\n",i);
  511. DebugOut(g_cMsg);
  512. #endif
  513. bRet = TRUE;
  514. break;
  515. }
  516. }
  517. // --- END OF CRITICAL SECTION
  518. //
  519. g_CriticalSection.Leave();
  520. return (bRet);
  521. }
  522. // ----------------------------------------------------------------------------
  523. // Function: CJoltMidi::DeleteDownloadedEffects
  524. // Purpose: Deletes all downloaded Effects
  525. // Parameters: none
  526. //
  527. // Returns:
  528. // Algorithm:
  529. // Note: Does not delete System Effect IDs like RTC_SPRING and FRICTION CANCEL
  530. //
  531. // ----------------------------------------------------------------------------
  532. void CJoltMidi::DeleteDownloadedEffects(void)
  533. {
  534. //
  535. // --- THIS IS A CRITICAL SECTION
  536. //
  537. g_CriticalSection.Enter();
  538. #ifdef _DEBUG
  539. DebugOut("CJoltMidi::DeleteDownloadedEffects()\n");
  540. #endif
  541. // Free the MIDI Effect objects
  542. for (int i=(SYSTEM_RTCSPRING_ID+1); i<MAX_EFFECT_IDS; i++)
  543. {
  544. if (m_pJoltEffectList[i])
  545. {
  546. delete m_pJoltEffectList[i];
  547. m_pJoltEffectList[i]= NULL;
  548. }
  549. }
  550. // --- END OF CRITICAL SECTION
  551. //
  552. g_CriticalSection.Leave();
  553. }
  554. // ----------------------------------------------------------------------------
  555. // Function: CJoltMidi::RestoreDownloadedEffects
  556. // Purpose: Restores all Downloaded Effects
  557. // Parameters: none
  558. //
  559. // Returns:
  560. // Algorithm:
  561. // ----------------------------------------------------------------------------
  562. void CJoltMidi::RestoreDownloadedEffects(void)
  563. {
  564. //
  565. // --- THIS IS A CRITICAL SECTION
  566. //
  567. CriticalLock cl;
  568. HRESULT hRet;
  569. DNHANDLE DummyID;
  570. #ifdef _DEBUG
  571. DebugOut("CJoltMidi::RestoreDownloadedEffects()\n");
  572. #endif
  573. // Walk the list and restore the MIDI Effect objects
  574. for (int i=0; i<MAX_EFFECT_IDS; i++)
  575. {
  576. if (m_pJoltEffectList[i])
  577. {
  578. #ifdef _DEBUG
  579. wsprintf(g_cMsg,"Restoring Effect ID:%d\n", i);
  580. DebugOut(g_cMsg);
  581. #endif
  582. // Generate Sys_Ex packet then prepare for output
  583. (m_pJoltEffectList[i])->GenerateSysExPacket();
  584. int nSizeBuf = (m_pJoltEffectList[i])->MidiBufferSizeOf();
  585. int nRetries = MAX_RETRY_COUNT;
  586. while (nRetries > 0)
  587. {
  588. hRet = (m_pJoltEffectList[i])->SendPacket(&DummyID, nSizeBuf);
  589. if (SUCCESS == hRet) break;
  590. BumpRetryCounter();
  591. nRetries--;
  592. }
  593. assert(SUCCESS == hRet);
  594. }
  595. }
  596. // --- END OF CRITICAL SECTION
  597. //
  598. }
  599. // ----------------------------------------------------------------------------
  600. // Function: CJoltMidi::OpenOutput
  601. // Purpose: Opens Midi Output
  602. // Parameters: int nDeviceID - MIDI device ID 0-based.
  603. //
  604. // Returns: success or Error code
  605. // Algorithm:
  606. // ----------------------------------------------------------------------------
  607. HRESULT CJoltMidi::OpenOutput(int nDeviceID)
  608. {
  609. //
  610. // --- THIS IS A CRITICAL SECTION
  611. //
  612. CriticalLock cl;
  613. // ***** Shared Memory Access *****
  614. LockSharedMemory();
  615. // Return if already opened by another task
  616. if (m_pSharedMemory->m_hMidiOut)
  617. {
  618. m_MidiOutInfo = m_pSharedMemory->m_MidiOutInfo;
  619. UnlockSharedMemory();
  620. // ***** End of Shared Memory Access *****
  621. return (SUCCESS);
  622. }
  623. MMRESULT wRtn;
  624. // Get MIDI input device caps
  625. assert(nDeviceID <= (int) midiOutGetNumDevs());
  626. wRtn = midiOutGetDevCaps(nDeviceID, (LPMIDIOUTCAPS) &m_MidiOutCaps,
  627. sizeof(MIDIOUTCAPS));
  628. if(MMSYSERR_NOERROR != wRtn)
  629. {
  630. #ifdef _DEBUG
  631. midiOutGetErrorText(wRtn, (LPSTR)g_cMsg, sizeof(g_cMsg));
  632. DebugOut(g_cMsg);
  633. DebugOut(":midiOutGetDevCaps\n");
  634. #endif
  635. return (SFERR_DRIVER_ERROR);
  636. }
  637. // Now open, with Callback handler
  638. HANDLE hMidiOut = NULL;
  639. wRtn = midiOutOpen((LPHMIDIOUT)&hMidiOut,
  640. nDeviceID,
  641. // (DWORD) m_hMidiOutputEvent,
  642. (DWORD) NULL,
  643. (DWORD) this, // the CJoltMidi object
  644. CALLBACK_EVENT);
  645. if(MMSYSERR_NOERROR != wRtn)
  646. {
  647. #ifdef _DEBUG
  648. midiOutGetErrorText(wRtn, (LPSTR)g_cMsg, sizeof(g_cMsg));
  649. DebugOut(g_cMsg);
  650. wsprintf(g_cMsg, "midiOutOpen(%u)\n", nDeviceID);
  651. DebugOut(g_cMsg);
  652. #endif
  653. return (SFERR_DRIVER_ERROR);
  654. }
  655. m_MidiOutInfo.hMidiOut = HMIDIOUT(hMidiOut);
  656. m_MidiOutDeviceID = nDeviceID;
  657. m_MidiOutOpened = TRUE;
  658. m_pSharedMemory->m_MidiOutInfo = m_MidiOutInfo;
  659. // Copy Midi Output handle to SharedMemory
  660. m_pSharedMemory->m_hMidiOut = hMidiOut;
  661. UnlockSharedMemory();
  662. // ***** End of Shared Memory Access *****
  663. // --- END OF CRITICAL SECTION
  664. //
  665. return (SUCCESS);
  666. }
  667. // ----------------------------------------------------------------------------
  668. // Function: CJoltMidi::AllocCallbackInstanceData
  669. // Purpose: Allocates a CALLBACKINSTANCEDATA structure. This structure is
  670. // used to pass information to the low-level callback function,
  671. // each time it receives a message. Because this structure is
  672. // accessed by the low-level callback function, it must be
  673. // allocated using GlobalAlloc() with the GMEM_SHARE and
  674. // GMEM_MOVEABLE flags and page-locked with GlobalPageLock().
  675. //
  676. // Parameters: none
  677. //
  678. // Returns: A pointer to the allocated CALLBACKINSTANCE data structure.
  679. // else NULL if Fail
  680. // Algorithm:
  681. // ----------------------------------------------------------------------------
  682. LPCALLBACKINSTANCEDATA CJoltMidi::AllocCallbackInstanceData(void)
  683. {
  684. HANDLE hMem;
  685. LPCALLBACKINSTANCEDATA lpBuf;
  686. // Allocate and lock global memory.
  687. hMem = GlobalAlloc(GMEM_SHARE | GMEM_MOVEABLE,
  688. (DWORD)sizeof(CALLBACKINSTANCEDATA));
  689. if(hMem == NULL) return NULL;
  690. lpBuf = (LPCALLBACKINSTANCEDATA)GlobalLock(hMem);
  691. if(lpBuf == NULL)
  692. {
  693. GlobalFree(hMem);
  694. return NULL;
  695. }
  696. // Save the handle.
  697. lpBuf->hSelf = hMem;
  698. return lpBuf;
  699. }
  700. // ----------------------------------------------------------------------------
  701. // Function: CJoltMidi::FreeCallbackInstanceData
  702. // Purpose: Frees the memory for the CALLBACKINSTANCEDATA structure
  703. // Parameters: none
  704. //
  705. // Returns: none
  706. // Algorithm:
  707. // ----------------------------------------------------------------------------
  708. void CJoltMidi::FreeCallbackInstanceData(void)
  709. {
  710. LPCALLBACKINSTANCEDATA lpBuf = m_lpCallbackInstanceData;
  711. HANDLE hMem;
  712. // Save the handle until we're through here.
  713. hMem = lpBuf->hSelf;
  714. // Free the structure.
  715. GlobalUnlock(hMem);
  716. GlobalFree(hMem);
  717. }
  718. // ----------------------------------------------------------------------------
  719. // Function: CJoltMidi::GetAckNackData
  720. // Purpose: Waits for a Response ACK
  721. //
  722. // Parameters: int nTImeWait - Time to wait in 1 ms increment, 0=no wait
  723. // PACKNACK pAckNack - Pointer to ACKNACK structure
  724. //
  725. // Returns: SUCCESS else error code SFERR_DRIVER_ERROR
  726. //
  727. // Algorithm:
  728. //
  729. // Note: For Short messages the MidiOutProc callback receives no MM_MOM_DONE
  730. // indicating completed transmission. Only Long (SysEx) messages do.
  731. // Uses:
  732. //typedef struct _ACKNACK {
  733. // DWORD cBytes;
  734. // DWORD dwAckNack; //ACK, NACK
  735. // DWORD dwErrorCode;
  736. // DWORD dwEffectStatus; //DEV_STS_EFFECT_RUNNING||DEV_STS_EFFECT_STOPPED
  737. //} ACKNACK, *PACKNACK;
  738. //
  739. // ----------------------------------------------------------------------------
  740. HRESULT CJoltMidi::GetAckNackData(
  741. IN int nTimeWait,
  742. IN OUT PACKNACK pAckNack,
  743. IN USHORT regindex)
  744. {
  745. //
  746. // --- THIS IS A CRITICAL SECTION
  747. //
  748. CriticalLock cl;
  749. assert(pAckNack);
  750. // Use IOCTL from VxD to get AckNack data
  751. // Wait for Event to be set
  752. if (nTimeWait && m_hMidiOutputEvent)
  753. {
  754. DWORD dwRet = WaitForSingleObject(m_hMidiOutputEvent, nTimeWait);
  755. // :
  756. #ifdef _DEBUG
  757. wsprintf(g_cMsg,"WaitForSingleObject %lx returned %lx, nTimeWait=%ld\n", m_hMidiOutputEvent, dwRet, nTimeWait);
  758. DebugOut(g_cMsg);
  759. #endif
  760. BOOL bRet = ResetEvent(m_hMidiOutputEvent);
  761. }
  762. HRESULT hRet = g_pDriverCommunicator->GetAckNack(*pAckNack, regindex);
  763. // --- END OF CRITICAL SECTION
  764. //
  765. return (hRet);
  766. }
  767. // ----------------------------------------------------------------------------
  768. // Function: CJoltMidi::GetEffectStatus
  769. // Purpose: Checks status of Effect
  770. //
  771. // Parameters: int DnloadID - Effect ID
  772. // PBYTE pStatusCode - Ptr to a byte for status code
  773. //
  774. // Returns: SUCCESS else error code SFERR_DRIVER_ERROR
  775. //
  776. // Algorithm:
  777. //
  778. // Note: For Short messages the MidiOutProc callback receives no MM_MOM_DONE
  779. // indicating completed transmission. Only Long (SysEx) messages do.
  780. // Uses:
  781. //typedef struct _ACKNACK {
  782. // DWORD cBytes;
  783. // DWORD dwAckNack; //ACK, NACK
  784. // DWORD dwErrorCode;
  785. // DWORD dwEffectStatus; //DEV_STS_EFFECT_RUNNING||DEV_STS_EFFECT_STOPPED
  786. //} ACKNACK, *PACKNACK;
  787. //
  788. // ----------------------------------------------------------------------------
  789. HRESULT CJoltMidi::GetEffectStatus(
  790. IN DWORD DnloadID ,
  791. IN OUT PBYTE pStatusCode)
  792. {
  793. //
  794. // --- THIS IS A CRITICAL SECTION
  795. //
  796. g_CriticalSection.Enter();
  797. assert(pStatusCode);
  798. HRESULT hRet = CMD_GetEffectStatus((DNHANDLE) DnloadID, pStatusCode);
  799. // --- END OF CRITICAL SECTION
  800. //
  801. g_CriticalSection.Leave();
  802. return (hRet);
  803. }
  804. // ----------------------------------------------------------------------------
  805. // Function: CJoltMidi::InitDigitalOverDrive
  806. // Purpose: Initialize the VxD interface
  807. //
  808. // Parameters: none
  809. //
  810. // Returns: SUCCESS or Error code
  811. //
  812. // Algorithm:
  813. // ----------------------------------------------------------------------------
  814. HRESULT CJoltMidi::InitDigitalOverDrive(DWORD dwDeviceID)
  815. {
  816. if (g_pDriverCommunicator != NULL)
  817. { // Attempt to reinit
  818. ASSUME_NOT_REACHED();
  819. return S_OK;
  820. }
  821. //
  822. // --- THIS IS A CRITICAL SECTION
  823. //
  824. HRESULT hRet = SUCCESS;
  825. DWORD driverMajor = 0xFFFFFFFF;
  826. DWORD driverMinor = 0xFFFFFFFF;
  827. g_CriticalSection.Enter();
  828. // This fork works on NT5 only (VxD stuff removed)
  829. assert(g_ForceFeedbackDevice.IsOSNT5() == TRUE);
  830. {
  831. g_pDriverCommunicator = new HIDFeatureCommunicator;
  832. if (g_pDriverCommunicator == NULL)
  833. {
  834. g_CriticalSection.Leave();
  835. return DIERR_OUTOFMEMORY;
  836. }
  837. if (((HIDFeatureCommunicator*)g_pDriverCommunicator)->Initialize(dwDeviceID) == FALSE)
  838. { // Could not load the driver
  839. hRet = SFERR_DRIVER_ERROR;
  840. }
  841. }
  842. if (FAILED(hRet))
  843. {
  844. return hRet;
  845. }
  846. // Loaded driver, get the version
  847. g_pDriverCommunicator->GetDriverVersion(driverMajor, driverMinor);
  848. // --- END OF CRITICAL SECTION
  849. //
  850. g_CriticalSection.Leave();
  851. g_ForceFeedbackDevice.SetDriverVersion(driverMajor, driverMinor);
  852. return (hRet);
  853. }
  854. // ----------------------------------------------------------------------------
  855. // Function: CJoltMidi::GetJoltStatus
  856. // Purpose: Returns JOLT Device Status using SWForce SWDEVICESTATE struct
  857. //
  858. // Parameters: LPDEVICESTATE pDeviceState
  859. //
  860. // Returns: none
  861. //
  862. // Algorithm: copies SWDEVICESTATUS to caller
  863. // Internal Representation:
  864. //typedef struct _SWDEVICESTATE {
  865. // ULONG m_Bytes; // size of this structure
  866. // ULONG m_ForceState; // DS_FORCE_ON || DS_FORCE_OFF || DS_SHUTDOWN
  867. // ULONG m_EffectState; // DS_STOP_ALL || DS_CONTINUE || DS_PAUSE
  868. // ULONG m_HOTS; // Hands On Throttle and Stick Status
  869. // 0 = Hands Off, 1 = Hands On
  870. // ULONG m_BandWidth; // Percentage of CPU available 1 to 100%
  871. // Lower number indicates CPU is in trouble!
  872. // ULONG m_ACBrickFault; // 0 = AC Brick OK, 1 = AC Brick Fault
  873. // ULONG m_ResetDetect; // 1 = HW Reset Detected
  874. // ULONG m_ShutdownDetect; // 1 = Shutdown detected
  875. // ULONG m_CommMode; // TRUE=SERIAL, FALSE=MIDI
  876. //} SWDEVICESTATE, *PSWDEVICESTATE;
  877. //
  878. // ----------------------------------------------------------------------------
  879. HRESULT CJoltMidi::GetJoltStatus(PSWDEVICESTATE pDeviceState)
  880. {
  881. //
  882. // --- THIS IS A CRITICAL SECTION
  883. //
  884. g_CriticalSection.Enter();
  885. // Use Digital Overdrive to get the status packet
  886. JOYCHANNELSTATUS statusPacket = { sizeof JOYCHANNELSTATUS };
  887. HRESULT hRet = g_pDriverCommunicator->GetStatus(statusPacket);
  888. if (hRet == SUCCESS) {
  889. // Store/update Jolt's status in main object
  890. SetJoltStatus(&statusPacket);
  891. memcpy(pDeviceState, &m_DeviceState, sizeof(SWDEVICESTATE));
  892. }
  893. //
  894. // --- END OF CRITICAL SECTION
  895. //
  896. g_CriticalSection.Leave();
  897. return (hRet);
  898. }
  899. // ----------------------------------------------------------------------------
  900. // Function: CJoltMidi::GetJoltStatus
  901. // Purpose: Returns JOLT Device Status
  902. //
  903. // Parameters: LPDEVICESTATE pDeviceState using DXFF DEVICESTATE
  904. //
  905. // Returns: none
  906. //
  907. // Algorithm: copies SWDEVICESTATUS to caller converted to DEVICESTATE
  908. // Internal Representation:
  909. //typedef struct _SWDEVICESTATE {
  910. // ULONG m_Bytes; // size of this structure
  911. // ULONG m_ForceState; // DS_FORCE_ON || DS_FORCE_OFF || DS_SHUTDOWN
  912. // ULONG m_EffectState; // DS_STOP_ALL || DS_CONTINUE || DS_PAUSE
  913. // ULONG m_HOTS; // Hands On Throttle and Stick Status
  914. // 0 = Hands Off, 1 = Hands On
  915. // ULONG m_BandWidth; // Percentage of CPU available 1 to 100%
  916. // Lower number indicates CPU is in trouble!
  917. // ULONG m_ACBrickFault; // 0 = AC Brick OK, 1 = AC Brick Fault
  918. // ULONG m_ResetDetect; // 1 = HW Reset Detected
  919. // ULONG m_ShutdownDetect; // 1 = Shutdown detected
  920. // ULONG m_CommMode; // 0 = Midi, 1-4 = Serial
  921. //} SWDEVICESTATE, *PSWDEVICESTATE;
  922. //
  923. // DirectInputEffect Representation
  924. //typedef struct DEVICESTATE {
  925. // DWORD dwSize;
  926. // DWORD dwState;
  927. // DWORD dwSwitches;
  928. // DWORD dwLoading;
  929. //} DEVICESTATE, *LPDEVICESTATE;
  930. //
  931. //where:
  932. //// dwState values:
  933. //DS_FORCE_SHUTDOWN 0x00000001
  934. //DS_FORCE_ON 0x00000002
  935. //DS_FORCE_OFF 0x00000003
  936. //DS_CONTINUE 0x00000004
  937. //DS_PAUSE 0x00000005
  938. //DS_STOP_ALL 0x00000006
  939. //
  940. // dwSwitches values:
  941. //DSW_ACTUATORSON 0x00000001
  942. //DSW_ACTUATORSOFF 0x00000002
  943. //DSW_POWERON 0x00000004
  944. //DSW_POWEROFF 0x00000008
  945. //DSW_SAFETYSWITCHON 0x00000010
  946. //DSW_SAFETYSWITCHOFF 0x00000020
  947. //DSW_USERFFSWITCHON 0x00000040
  948. //DSW_USERFFSWTTCHOFF 0x00000080
  949. //
  950. // Note: Apparently, DSW_ACTUATORSON and DSW_ACTUATORSOFF is a mirrored state
  951. // from DS_FORCE_ON and DS_FORCE_OFF as set from SetForceFeedbackState
  952. //
  953. // ----------------------------------------------------------------------------
  954. HRESULT CJoltMidi::GetJoltStatus(LPDIDEVICESTATE pDeviceState)
  955. {
  956. //
  957. // --- THIS IS A CRITICAL SECTION
  958. //
  959. CriticalLock cl;
  960. // Use Digital Overdrive to get the status packet
  961. JOYCHANNELSTATUS StatusPacket = {sizeof(JOYCHANNELSTATUS)};
  962. HRESULT hRet = g_pDriverCommunicator->GetStatus(StatusPacket);
  963. if (hRet != SUCCESS) {
  964. return (hRet);
  965. }
  966. // Store/update Jolts status
  967. SetJoltStatus(&StatusPacket);
  968. #ifdef _DEBUG
  969. wsprintf(g_cMsg,"%s: DXFF:dwDeviceStatus=%.8lx\n",&szDeviceName, StatusPacket.dwDeviceStatus);
  970. DebugOut(g_cMsg);
  971. #endif
  972. pDeviceState->dwState = 0;
  973. // Note: Apparently, DSW_ACTUATORSON and DSW_ACTUATORSOFF is a mirrored state
  974. // from DS_FORCE_ON and DS_FORCE_OFF as set from SetForceFeedbackState
  975. // So, also Map the redundant info that DI needs if necessary
  976. switch(m_DeviceState.m_ForceState)
  977. {
  978. case SWDEV_SHUTDOWN:
  979. pDeviceState->dwState = DIGFFS_ACTUATORSON;
  980. break;
  981. case SWDEV_FORCE_ON:
  982. pDeviceState->dwState = DIGFFS_ACTUATORSON;
  983. break;
  984. case SWDEV_FORCE_OFF:
  985. pDeviceState->dwState = DIGFFS_ACTUATORSOFF;
  986. break;
  987. default:
  988. break;
  989. }
  990. // see if the stick is empty
  991. // remember that ID's start at 2
  992. BOOL bEmpty = TRUE;
  993. for (int i=2; i<MAX_EFFECT_IDS; i++)
  994. {
  995. if (m_pJoltEffectList[i] != NULL)
  996. bEmpty = FALSE;
  997. }
  998. if(bEmpty)
  999. pDeviceState->dwState |= DIGFFS_EMPTY;
  1000. switch(m_DeviceState.m_EffectState)
  1001. {
  1002. case SWDEV_PAUSE:
  1003. pDeviceState->dwState |= DIGFFS_PAUSED;
  1004. break;
  1005. case SWDEV_CONTINUE:
  1006. break;
  1007. case SWDEV_STOP_ALL:
  1008. pDeviceState->dwState |= DIGFFS_STOPPED;
  1009. break;
  1010. default:
  1011. break;
  1012. }
  1013. if(m_DeviceState.m_HOTS)
  1014. pDeviceState->dwState |= DIGFFS_SAFETYSWITCHON;
  1015. else
  1016. pDeviceState->dwState |= DIGFFS_SAFETYSWITCHOFF;
  1017. if (m_DeviceState.m_ACBrickFault)
  1018. pDeviceState->dwState |= DIGFFS_POWEROFF;
  1019. else
  1020. pDeviceState->dwState |= DIGFFS_POWERON;
  1021. pDeviceState->dwLoad = 0; //m_DeviceState.m_BandWidth * SCALE_GAIN;
  1022. // --- END OF CRITICAL SECTION
  1023. //
  1024. return SUCCESS;
  1025. }
  1026. // ----------------------------------------------------------------------------
  1027. // Function: CJoltMidi::SetJoltStatus
  1028. // Purpose: Sets JOLT Device Status
  1029. //
  1030. // Parameters: PJOYCHANNELSTATUS pJoyChannelStatus
  1031. //
  1032. // Returns: none
  1033. //
  1034. // Algorithm: Sets SWDEVICESTATE from caller
  1035. //typedef struct _SWDEVICESTATE {
  1036. // ULONG m_Bytes; // size of this structure
  1037. // ULONG m_ForceState; // DS_FORCE_ON || DS_FORCE_OFF || DS_FORCE_SHUTDOWN
  1038. // ULONG m_EffectState; // DS_STOP_ALL || DS_CONTINUE || DS_PAUSE
  1039. // ULONG m_HOTS; // Hands On Throttle and Stick Status
  1040. // 0(FALSE) = Hands Off, 1 (TRUE) = Hands On
  1041. // ULONG m_BandWidth; // Percentage of CPU available 1 to 100%
  1042. // Lower number indicates CPU is in trouble!
  1043. // ULONG m_ACBrickFault; // 0(FALSE) = AC Brick OK, 1(TRUE) = AC Fault
  1044. // ULONG m_ResetDetect; // 1(TRUE) = HW Reset Detected
  1045. // ULONG m_ShutdownDetect; // 1(TRUE) = Shutdown detected
  1046. // ULONG m_CommMode; // 0(FALSE) = Midi, 1(TRUE) = Serial
  1047. //} SWDEVICESTATE, *PSWDEVICESTATE;
  1048. // ----------------------------------------------------------------------------
  1049. void CJoltMidi::SetJoltStatus(JOYCHANNELSTATUS* pJoyChannelStatus)
  1050. {
  1051. //
  1052. // --- THIS IS A CRITICAL SECTION
  1053. //
  1054. CriticalLock cl;
  1055. if (pJoyChannelStatus->dwDeviceStatus & HOTS_MASK)
  1056. m_DeviceState.m_HOTS = TRUE;
  1057. else
  1058. m_DeviceState.m_HOTS = FALSE;
  1059. if (pJoyChannelStatus->dwDeviceStatus & BANDWIDTH_MASK)
  1060. m_DeviceState.m_BandWidth = MINIMUM_BANDWIDTH;
  1061. else
  1062. m_DeviceState.m_BandWidth = MAXIMUM_BANDWIDTH;
  1063. if (pJoyChannelStatus->dwDeviceStatus & AC_FAULT_MASK)
  1064. m_DeviceState.m_ACBrickFault = TRUE;
  1065. else
  1066. m_DeviceState.m_ACBrickFault = FALSE;
  1067. if (pJoyChannelStatus->dwDeviceStatus & COMM_MODE_MASK)
  1068. m_DeviceState.m_CommMode = TRUE; // Serial RS232
  1069. else
  1070. m_DeviceState.m_CommMode = FALSE; // Midi port
  1071. if (pJoyChannelStatus->dwDeviceStatus & RESET_MASK)
  1072. m_DeviceState.m_ResetDetect = TRUE; // Power ON Reset entered
  1073. else
  1074. m_DeviceState.m_ResetDetect = FALSE;
  1075. //REVIEW: If we detected a Reset, shouldn't we go through re-init of object?
  1076. if (pJoyChannelStatus->dwDeviceStatus & SHUTDOWN_MASK)
  1077. m_DeviceState.m_ShutdownDetect = TRUE; // Soft Reset received
  1078. else
  1079. m_DeviceState.m_ShutdownDetect = FALSE;
  1080. // --- END OF CRITICAL SECTION
  1081. //
  1082. }
  1083. // ----------------------------------------------------------------------------
  1084. // Function: CJoltMidi::UpdateDeviceMode
  1085. // Purpose: Sets JOLT Device Mode
  1086. //
  1087. // Parameters: ULONG ulMode
  1088. //
  1089. // Returns: none
  1090. //
  1091. // Algorithm:
  1092. // This is the SideWinder State structure
  1093. //typedef struct _SWDEVICESTATE {
  1094. // ULONG m_Bytes; // size of this structure
  1095. // ULONG m_ForceState; // DS_FORCE_ON || DS_FORCE_OFF || DS_SHUTDOWN
  1096. // ULONG m_EffectState; // DS_STOP_ALL || DS_CONTINUE || DS_PAUSE
  1097. // ULONG m_HOTS; // Hands On Throttle and Stick Status
  1098. // // 0 = Hands Off, 1 = Hands On
  1099. // ULONG m_BandWidth; // Percentage of CPU available 1 to 100%
  1100. // // Lower number indicates CPU is in trouble!
  1101. // ULONG m_ACBrickFault; // 0 = AC Brick OK, 1 = AC Brick Fault
  1102. // ULONG m_ResetDetect; // 1 = HW Reset Detected
  1103. // ULONG m_ShutdownDetect; // 1 = Shutdown detected
  1104. // ULONG m_CommMode; // 0 = Midi, 1-4 = Serial
  1105. //} SWDEVICESTATE, *PSWDEVICESTATE;
  1106. //
  1107. // ----------------------------------------------------------------------------
  1108. void CJoltMidi::UpdateDeviceMode(ULONG ulMode)
  1109. {
  1110. //
  1111. // --- THIS IS A CRITICAL SECTION
  1112. //
  1113. CriticalLock cl;
  1114. switch (ulMode)
  1115. {
  1116. case SWDEV_FORCE_ON: // REVIEW
  1117. case SWDEV_FORCE_OFF:
  1118. m_DeviceState.m_ForceState = ulMode;
  1119. break;
  1120. case SWDEV_SHUTDOWN:
  1121. m_DeviceState.m_ForceState = ulMode;
  1122. m_DeviceState.m_EffectState = 0;
  1123. break;
  1124. case SWDEV_STOP_ALL:
  1125. case SWDEV_CONTINUE:
  1126. case SWDEV_PAUSE:
  1127. m_DeviceState.m_EffectState = ulMode;
  1128. break;
  1129. default:
  1130. break;
  1131. }
  1132. // --- END OF CRITICAL SECTION
  1133. //
  1134. }
  1135. // ----------------------------------------------------------------------------
  1136. // Function: CJoltMidi::GetJoltID
  1137. // Purpose: Returns JOLT ProductID
  1138. //
  1139. // Parameters: LOCAL_PRODUCT_ID pProductID - Pointer to a LOCAL_PRODUCT_ID structure
  1140. //
  1141. // Returns: none
  1142. //
  1143. // Algorithm:
  1144. //
  1145. // ----------------------------------------------------------------------------
  1146. HRESULT CJoltMidi::GetJoltID(LOCAL_PRODUCT_ID* pProductID)
  1147. {
  1148. HRESULT hRet;
  1149. assert(pProductID->cBytes = sizeof LOCAL_PRODUCT_ID);
  1150. if (pProductID->cBytes != sizeof LOCAL_PRODUCT_ID) return (SFERR_INVALID_STRUCT_SIZE);
  1151. //
  1152. // --- THIS IS A CRITICAL SECTION
  1153. //
  1154. g_CriticalSection.Enter();
  1155. for (int i=0;i<MAX_RETRY_COUNT;i++)
  1156. {
  1157. if (SUCCESS == (hRet = g_pDriverCommunicator->GetID(*pProductID))) break;
  1158. }
  1159. if (SUCCESS == hRet)
  1160. {
  1161. memcpy(&m_ProductID, pProductID, sizeof LOCAL_PRODUCT_ID);
  1162. }
  1163. else
  1164. DebugOut("GetJoltID: Warning! GetIDPacket - Fail\n");
  1165. // --- END OF CRITICAL SECTION
  1166. //
  1167. g_CriticalSection.Leave();
  1168. return (hRet);
  1169. }
  1170. // ----------------------------------------------------------------------------
  1171. // Function: CJoltMidi::LogError
  1172. // Purpose: Logs Error codes
  1173. //
  1174. // Parameters: HRESULT SystemError - System Error code
  1175. // HRESULT DriverError - Driver Error code
  1176. //
  1177. // Returns: SWFORCE Error code
  1178. //
  1179. // Algorithm:
  1180. // ----------------------------------------------------------------------------
  1181. typedef struct _DRIVERERROR {
  1182. ULONG ulDriverCode;
  1183. LONG lSystemCode;
  1184. } DRIVERERROR, *PDRIVERERROR;
  1185. HRESULT CJoltMidi::LogError(
  1186. IN HRESULT SystemError,
  1187. IN HRESULT DriverError)
  1188. {
  1189. // REVIEW: map MM error codes to our SWForce codes
  1190. DRIVERERROR DriverErrorCodes[] = {
  1191. {DEV_ERR_INVALID_ID , SWDEV_ERR_INVALID_ID},
  1192. {DEV_ERR_INVALID_PARAM , SWDEV_ERR_INVALID_PARAM},
  1193. {DEV_ERR_CHECKSUM , SWDEV_ERR_CHECKSUM},
  1194. {DEV_ERR_TYPE_FULL , SWDEV_ERR_TYPE_FULL},
  1195. {DEV_ERR_UNKNOWN_CMD , SWDEV_ERR_UNKNOWN_CMD},
  1196. {DEV_ERR_PLAYLIST_FULL , SWDEV_ERR_PLAYLIST_FULL},
  1197. {DEV_ERR_PROCESS_LIST_FULL , SWDEV_ERR_PROCESSLIST_FULL} };
  1198. int nDriverErrorCodes = sizeof(DriverErrorCodes)/(sizeof(DRIVERERROR));
  1199. for (int i=0; i<nDriverErrorCodes; i++)
  1200. {
  1201. if (DriverError == (LONG) DriverErrorCodes[i].ulDriverCode)
  1202. {
  1203. SystemError = DriverErrorCodes[i].lSystemCode;
  1204. break;
  1205. }
  1206. }
  1207. // Store in Jolt object
  1208. m_Error.HCode = SystemError;
  1209. m_Error.ulDriverCode = DriverError;
  1210. #ifdef _DEBUG
  1211. wsprintf(g_cMsg,"LogError: SystemError=%.8lx, DriverError=%.8lx\n",
  1212. SystemError, DriverError);
  1213. DebugOut(g_cMsg);
  1214. #endif
  1215. return SystemError;
  1216. }
  1217. //
  1218. // ----------------------------------------------------------------------------
  1219. // Function: SetupROM_Fx
  1220. // Purpose: Sets up parameters for ROM Effects
  1221. // Parameters: PEFFECT pEffect
  1222. //
  1223. //
  1224. // Returns: pEffect is updated with new ROM parameters
  1225. // OutputRate
  1226. // Gain
  1227. // Duration
  1228. //
  1229. // Algorithm:
  1230. // ----------------------------------------------------------------------------
  1231. HRESULT CJoltMidi::SetupROM_Fx(
  1232. IN OUT PEFFECT pEffect)
  1233. {
  1234. assert(pEffect);
  1235. if (NULL == pEffect) return (SFERR_INVALID_PARAM);
  1236. ULONG ulSubType = pEffect->m_SubType;
  1237. BOOL bFound = FALSE;
  1238. for (int i=0; i< MAX_ROM_EFFECTS; i++)
  1239. {
  1240. if (ulSubType == m_pRomFxTable[i].m_ROM_Id)
  1241. {
  1242. bFound = TRUE;
  1243. break;
  1244. }
  1245. }
  1246. if (!bFound) return (SFERR_INVALID_OBJECT);
  1247. // Found, so fill in the default parameters, use Default if Gain=1, Duration=-1, OutputRate=-1
  1248. BOOL bDefaultDuration = (ULONG)-1 == pEffect->m_Duration;
  1249. if (1 == pEffect->m_Gain) pEffect->m_Gain = m_pRomFxTable[i].m_Gain;
  1250. if (bDefaultDuration) pEffect->m_Duration = m_pRomFxTable[i].m_Duration;
  1251. if ((ULONG)-1 == pEffect->m_ForceOutputRate)
  1252. {
  1253. pEffect->m_ForceOutputRate = m_pRomFxTable[i].m_ForceOutputRate;
  1254. }
  1255. else if(bDefaultDuration && pEffect->m_ForceOutputRate != 0)
  1256. {
  1257. // scale the duration to correspond to the output rate
  1258. pEffect->m_Duration = pEffect->m_Duration*m_pRomFxTable[i].m_ForceOutputRate/pEffect->m_ForceOutputRate;
  1259. }
  1260. return (SUCCESS);
  1261. }
  1262. // *** ---------------------------------------------------------------------***
  1263. // Function: DetectMidiDevice
  1264. // Purpose: Determines Midi Output Device ID
  1265. // Parameters:
  1266. // DWORD dwDeviceID - joystick ID
  1267. // UINT *pDeviceOutID - Ptr to Midi Out Device ID
  1268. // ULONG pCOMMInterface - Ptr to COMMInterface value
  1269. // ULONG pCOMMPort - Ptr to COMMPort value (Registry)
  1270. // Returns: BOOL TRUE if successful match and IDs are filled in
  1271. // else FALSE
  1272. //
  1273. // *** ---------------------------------------------------------------------***
  1274. BOOL CJoltMidi::DetectMidiDevice(
  1275. IN DWORD dwDeviceID,
  1276. IN OUT UINT *pDeviceOutID,
  1277. OUT ULONG *pCOMMInterface,
  1278. OUT ULONG *pCOMMPort)
  1279. {
  1280. //
  1281. // --- THIS IS A CRITICAL SECTION
  1282. //
  1283. CriticalLock cl;
  1284. HRESULT hRet;
  1285. BOOL bMidiOutFound = FALSE;
  1286. int nMidiOutDevices;
  1287. // Valid Serial and MIDI ports table
  1288. ULONG MIDI_Ports[] = {0x300, 0x310, 0x320, 0x330, 0x340, 0x350, 0x360, 0x370,
  1289. 0x380, 0x390, 0x3a0, 0x3b0, 0x3c0, 0x3d0, 0x3e0, 0x3f0};
  1290. ULONG Serial_Ports[] = { 1, 2, 3, 4 }; // Entry0 is default
  1291. int nMIDI_Ports = sizeof(MIDI_Ports)/sizeof(ULONG);
  1292. int nSerial_Ports = sizeof(Serial_Ports)/sizeof(ULONG);
  1293. // Set defaults
  1294. *pCOMMInterface = COMM_WINMM;
  1295. *pCOMMPort = NULL;
  1296. *pDeviceOutID = 0;
  1297. SWDEVICESTATE SWDeviceState = {sizeof(SWDEVICESTATE)};
  1298. // Turn on tristated Jolt MIDI lines by call GetIDPacket()
  1299. LOCAL_PRODUCT_ID ProductID = {sizeof LOCAL_PRODUCT_ID };
  1300. Sleep(DelayParamsPtrOf()->dwDigitalOverdrivePrechargeCmdDelay);
  1301. if (SUCCESS != GetJoltID(&ProductID))
  1302. {
  1303. DebugOut("DetectMidiDevice: Warning! GetIDPacket - Fail\n");
  1304. return (FALSE);
  1305. }
  1306. #ifdef _DEBUG
  1307. wsprintf(g_cMsg,"%s: ProductID=%.8lx, FWVersion=%d.%.2ld\n",
  1308. &szDeviceName,
  1309. m_ProductID.dwProductID,
  1310. m_ProductID.dwFWMajVersion,
  1311. m_ProductID.dwFWMinVersion);
  1312. DebugOut(g_cMsg);
  1313. #endif
  1314. // Set the device firmware version from GetID
  1315. g_ForceFeedbackDevice.SetFirmwareVersion(dwDeviceID, m_ProductID.dwFWMajVersion, m_ProductID.dwFWMinVersion);
  1316. // Get Device status prior to starting detection
  1317. BOOL statusPacketFailed = (GetJoltStatus(&SWDeviceState) != SUCCESS);
  1318. if (statusPacketFailed)
  1319. {
  1320. DebugOut("DetectMidiDevice: Warning! StatusPacket - Fail\n");
  1321. }
  1322. if (statusPacketFailed == FALSE) {
  1323. #ifdef _DEBUG
  1324. wsprintf(g_cMsg, "RESETDetect=%.8lx, SHUTDOWNDetect=%.8lx, COMMMode=%.8lx\n",
  1325. SWDeviceState.m_ResetDetect,
  1326. SWDeviceState.m_ShutdownDetect,
  1327. SWDeviceState.m_CommMode);
  1328. DebugOut(g_cMsg);
  1329. #endif
  1330. // Make sure HW Reset Detect bit is cleared after GetID
  1331. if (SWDeviceState.m_ResetDetect) {
  1332. DebugOut("DetectMidiDevice: Error! Jolt ResetDetect bit not cleared after GetID\n");
  1333. return (FALSE);
  1334. }
  1335. }
  1336. // See if Serial Dongle connected, otherwise must be MIDI device
  1337. DebugOut("sw_effct:Trying Auto HW Detection: MIDI Serial Port Device...\n");
  1338. // Get Registry values, If high bit of COMMInterface is set, then force override
  1339. // otherwise, do automatic scanning as follows:
  1340. // 1. Backdoor mode
  1341. // 2. WinMM mode
  1342. //
  1343. // joyGetForceFeedbackCOMMInterface's 1st param changed to joystick ID
  1344. if (SUCCESS != joyGetForceFeedbackCOMMInterface(dwDeviceID, pCOMMInterface, pCOMMPort)) {
  1345. DebugOut("DetectMidiDevice: Registry key(s) missing! Bailing Out...\n");
  1346. return (FALSE);
  1347. }
  1348. #ifdef _DEBUG
  1349. wsprintf(g_cMsg, "DetectMidiDevice: Registry.COMMInterface=%lx, Registry.COMMPort=%lx\n",
  1350. *pCOMMInterface, *pCOMMPort);
  1351. DebugOut(g_cMsg);
  1352. #endif
  1353. ULONG regInterface = *pCOMMInterface;
  1354. // Was a serial dongle detected, or did we fail to get status
  1355. if (SWDeviceState.m_CommMode || statusPacketFailed) { // Use serial (regardless what registry says!)
  1356. DebugOut("DetectMidiDevice: Serial Port interface detected.\n");
  1357. // Set to backdoor serial method by default
  1358. *pCOMMInterface = COMM_SERIAL_BACKDOOR;
  1359. m_COMMInterface = COMM_SERIAL_BACKDOOR;
  1360. // Use front-door (serial file method) only, if NT5
  1361. // since there is no backdoor on NT5 registry is irrelevent
  1362. if (g_ForceFeedbackDevice.IsOSNT5()) {
  1363. *pCOMMInterface = COMM_SERIAL_FILE;
  1364. m_COMMInterface = COMM_SERIAL_FILE;
  1365. } else if ((g_ForceFeedbackDevice.GetFirmwareVersionMajor() == 1) && (g_ForceFeedbackDevice.GetFirmwareVersionMinor() != 16)) {
  1366. // Firmware is not 1.16 (which can't use the frontdoor serial with quick ack/nack)
  1367. if (!(regInterface & MASK_SERIAL_BACKDOOR)) { // Is back door forced by registry
  1368. *pCOMMInterface = COMM_SERIAL_FILE; // Use Serial File method
  1369. m_COMMInterface = COMM_SERIAL_FILE;
  1370. }
  1371. }
  1372. // See if already detected and ready to use
  1373. // ***** Shared Memory Access *****
  1374. LockSharedMemory();
  1375. HANDLE hMidiOut = m_pSharedMemory->m_hMidiOut;
  1376. UnlockSharedMemory();
  1377. // ***** End of Shared Memory Access *****
  1378. // Return if already opened by another task
  1379. if (NULL != hMidiOut) {
  1380. bMidiOutFound = TRUE;
  1381. } else { // Use the serial transmitter to find the proper port (even if backdoor selected)
  1382. if (g_pDataTransmitter != NULL) {
  1383. delete g_pDataTransmitter;
  1384. g_pDataTransmitter = NULL;
  1385. }
  1386. g_pDataTransmitter = new SerialDataTransmitter();
  1387. if (g_pDataTransmitter->Initialize()) {
  1388. LockSharedMemory();
  1389. m_pSharedMemory->m_hMidiOut = g_pDataTransmitter->GetCOMMHandleHack();
  1390. UnlockSharedMemory();
  1391. bMidiOutFound = TRUE;
  1392. }
  1393. // If Serial Backdoor let the driver know which port, kill DataTransmitter (without closing port)
  1394. if (m_COMMInterface == COMM_SERIAL_BACKDOOR) {
  1395. hRet = g_pDriverCommunicator->SetBackdoorPort(g_pDataTransmitter->GetSerialPortHack());
  1396. if (hRet != SUCCESS) { // Low level driver fails, use normal serial routines not backdoor
  1397. DebugOut("\nDetectMidiDevice: Warning! Could not set serial I/O port, cannot use backdoor serial\n");
  1398. *pCOMMInterface = COMM_SERIAL_FILE;
  1399. m_COMMInterface = COMM_SERIAL_FILE;
  1400. } else {
  1401. g_pDataTransmitter->StopAutoClose();
  1402. delete g_pDataTransmitter;
  1403. g_pDataTransmitter = NULL;
  1404. }
  1405. }
  1406. }
  1407. if (bMidiOutFound)
  1408. {
  1409. regInterface = (regInterface & (MASK_OVERRIDE_MIDI_PATH | MASK_SERIAL_BACKDOOR)) | m_COMMInterface;
  1410. // joySetForceFeedbackCOMMInterface's 1st param changed to joystick ID
  1411. joySetForceFeedbackCOMMInterface(dwDeviceID, regInterface, *pCOMMPort);
  1412. }
  1413. if ((statusPacketFailed == FALSE) || bMidiOutFound)
  1414. {
  1415. return (bMidiOutFound);
  1416. }
  1417. } // End of Serial Port Auto HW selection
  1418. // No Serial HW dongle detected, check if any Midi device for WinMM and Backdoor
  1419. DebugOut("sw_effct:Scanning MIDI Output Devices\n");
  1420. nMidiOutDevices = midiOutGetNumDevs();
  1421. if (0 == nMidiOutDevices) {
  1422. DebugOut("DetectMidiDevice: No MIDI devices present\n");
  1423. return (FALSE);
  1424. }
  1425. #if 0
  1426. // Try the midi pin solution
  1427. g_pDataTransmitter = new PinTransmitter();
  1428. if (g_pDataTransmitter->Initialize()) {
  1429. // Use backdoor flag for now
  1430. m_COMMInterface = COMM_MIDI_BACKDOOR;
  1431. *pCOMMInterface = COMM_MIDI_BACKDOOR;
  1432. return TRUE;
  1433. }
  1434. // Pin failed delete transmitter continue looking
  1435. delete g_pDataTransmitter;
  1436. g_pDataTransmitter = NULL;
  1437. #endif
  1438. ULONG ulPort = *pCOMMPort;
  1439. if ( !(*pCOMMInterface & MASK_OVERRIDE_MIDI_PATH) ) { // Use Automatic detection
  1440. DebugOut("DetectMidiDevice: Auto Detection. Trying Backdoor\n");
  1441. // Back Door
  1442. bMidiOutFound = FindJoltBackdoor(pDeviceOutID, pCOMMInterface, pCOMMPort);
  1443. if (!bMidiOutFound) { // Try Front Door
  1444. DebugOut("DetectMidiDevice: trying WINMM...\n");
  1445. bMidiOutFound = FindJoltWinMM(pDeviceOutID, pCOMMInterface, pCOMMPort);
  1446. }
  1447. if (bMidiOutFound) {
  1448. regInterface = (regInterface & (MASK_OVERRIDE_MIDI_PATH | MASK_SERIAL_BACKDOOR)) | m_COMMInterface;
  1449. joySetForceFeedbackCOMMInterface(*pDeviceOutID, regInterface, *pCOMMPort);
  1450. }
  1451. return (bMidiOutFound);
  1452. }
  1453. // Over-ride since high bit is set
  1454. *pCOMMInterface &= ~(MASK_OVERRIDE_MIDI_PATH | MASK_SERIAL_BACKDOOR); // Mask out high bit (and second bit)
  1455. switch (*pCOMMInterface)
  1456. {
  1457. case COMM_WINMM:
  1458. bMidiOutFound = FindJoltWinMM(pDeviceOutID, pCOMMInterface, pCOMMPort);
  1459. if (!bMidiOutFound) {
  1460. DebugOut("DetectMidiDevice: Error! Invalid Over-ride parameter values!\n");
  1461. }
  1462. return (bMidiOutFound);
  1463. case COMM_MIDI_BACKDOOR:
  1464. int i;
  1465. for (i=0;i<nMIDI_Ports;i++)
  1466. {
  1467. if (ulPort == MIDI_Ports[i])
  1468. {
  1469. bMidiOutFound = TRUE;
  1470. break;
  1471. }
  1472. }
  1473. break;
  1474. case COMM_SERIAL_BACKDOOR: // mlc - This should never work if no dongle detected
  1475. for (i=0;i<nSerial_Ports;i++)
  1476. {
  1477. if (ulPort == Serial_Ports[i])
  1478. {
  1479. bMidiOutFound = TRUE;
  1480. break;
  1481. }
  1482. }
  1483. break;
  1484. default:
  1485. bMidiOutFound = FALSE;
  1486. break;
  1487. }
  1488. if (!bMidiOutFound)
  1489. {
  1490. DebugOut("DetectMidiDevice: Error! Invalid Over-ride parameter values\n");
  1491. return (bMidiOutFound);
  1492. }
  1493. // We have the forced Port #, Let's see if Jolt is out there
  1494. #ifdef _DEBUG
  1495. wsprintf(g_cMsg,"DetectMidiDevice: (Over-ride) MIDI%.8lx Query - ", ulPort);
  1496. DebugOut(g_cMsg);
  1497. #endif
  1498. bMidiOutFound = FALSE;
  1499. hRet = g_pDriverCommunicator->SetBackdoorPort(ulPort);
  1500. if (SUCCESS != hRet)
  1501. {
  1502. DebugOut("\nDetectMidiDevice: Warning! Could not Set Midi/Serial I/O Port\n");
  1503. }
  1504. else
  1505. {
  1506. if (QueryForJolt())
  1507. {
  1508. DebugOut(" Success!\n");
  1509. bMidiOutFound = TRUE;
  1510. }
  1511. else
  1512. DebugOut(" No Answer\n");
  1513. }
  1514. // --- END OF CRITICAL SECTION
  1515. //
  1516. return (bMidiOutFound);
  1517. }
  1518. // *** ---------------------------------------------------------------------***
  1519. // Function: FindJoltWinMM
  1520. // Purpose: Searches for Jolt using WinMM
  1521. // Parameters: none
  1522. // UINT *pDeviceOutID - Ptr to Midi Out Device ID
  1523. // ULONG pCOMMInterface - Ptr to COMMInterface value
  1524. // ULONG pCOMMPort - Ptr to COMMPort value (Registry)
  1525. // Returns: BOOL TRUE if successful match and IDs are filled in
  1526. //
  1527. // Comments: SHUTDOWN is destructive!!!
  1528. //
  1529. // *** ---------------------------------------------------------------------***
  1530. BOOL CJoltMidi::FindJoltWinMM(
  1531. IN OUT UINT *pDeviceOutID,
  1532. OUT ULONG *pCOMMInterface,
  1533. OUT ULONG *pCOMMPort)
  1534. {
  1535. HRESULT hRet;
  1536. WORD wTechnology; // looking for MOD_MIDIPORT
  1537. WORD wChannelMask; // ==0xFFFF if all 16 channels
  1538. BOOL bMidiOutFound = FALSE;
  1539. // Device Capabilities
  1540. MIDIOUTCAPS midiOutCaps;
  1541. int nMidiOutDevices = midiOutGetNumDevs();
  1542. if (0 == nMidiOutDevices) return (FALSE);
  1543. m_COMMInterface = COMM_WINMM;
  1544. for (int nIndex=0;nIndex<(nMidiOutDevices);nIndex++)
  1545. {
  1546. MMRESULT ret = midiOutGetDevCaps(nIndex, &midiOutCaps, sizeof(midiOutCaps));
  1547. if (ret != MMSYSERR_NOERROR) break;
  1548. wTechnology = midiOutCaps.wTechnology;
  1549. wChannelMask= midiOutCaps.wChannelMask;
  1550. #ifdef _DEBUG
  1551. g_CriticalSection.Enter();
  1552. wsprintf(g_cMsg,"FindJoltWinMM: Technology=%x," \
  1553. "ChannelMask=%x, Mid=%d, Pid=%d\r\n", midiOutCaps.szPname,
  1554. wTechnology, wChannelMask, midiOutCaps.wMid,
  1555. midiOutCaps.wPid);
  1556. DebugOut(g_cMsg);
  1557. g_CriticalSection.Leave();
  1558. #endif
  1559. // Check if this is a MOD_MIDIPORT device
  1560. //REVIEW: Need to check for multiple MOD_MIDIPORT devices
  1561. if (wTechnology == MOD_MIDIPORT)
  1562. {
  1563. *pDeviceOutID = (UINT) nIndex;
  1564. #ifdef _DEBUG
  1565. DebugOut("DetectMidiDevice: Opening WinMM Midi Output\n");
  1566. #endif
  1567. hRet = OpenOutput(m_MidiOutInfo.uDeviceID);
  1568. if (SUCCESS != hRet)
  1569. {
  1570. DebugOut("DetectMidiDevice: Error! Could not Open WinMM Midi Output\n");
  1571. return (FALSE);
  1572. }
  1573. else
  1574. {
  1575. DebugOut("Open Midi Output - Success.\nQuery for Jolt Device - ");
  1576. if (QueryForJolt())
  1577. {
  1578. DebugOut(" Success!\n");
  1579. bMidiOutFound = TRUE;
  1580. }
  1581. else
  1582. {
  1583. DebugOut(" No Answer\n");
  1584. bMidiOutFound = FALSE;
  1585. break;
  1586. }
  1587. return (bMidiOutFound);
  1588. }
  1589. } // end of MOD_MIDIPORT
  1590. }
  1591. return (bMidiOutFound);
  1592. }
  1593. // *** ---------------------------------------------------------------------***
  1594. // Function: FindJoltBackdoor
  1595. // Purpose: Searches for Jolt using BackDoor
  1596. // Parameters: none
  1597. // UINT *pDeviceOutID - Ptr to Midi Out Device ID
  1598. // ULONG pCOMMInterface - Ptr to COMMInterface value
  1599. // ULONG pCOMMPort - Ptr to COMMPort value (Registry)
  1600. // Returns: BOOL TRUE if successful match and IDs are filled in
  1601. //
  1602. // Comments: SHUTDOWN is destructive!!!
  1603. //
  1604. // *** ---------------------------------------------------------------------***
  1605. BOOL CJoltMidi::FindJoltBackdoor(
  1606. IN OUT UINT *pDeviceOutID,
  1607. OUT ULONG *pCOMMInterface,
  1608. OUT ULONG *pCOMMPort)
  1609. {
  1610. int nMidiOutDevices = midiOutGetNumDevs();
  1611. if (0 == nMidiOutDevices) return (FALSE);
  1612. HRESULT hRet;
  1613. // Valid Serial and MIDI ports table
  1614. ULONG MIDI_Ports[] = {0x300, 0x310, 0x320, 0x330, 0x340, 0x350, 0x360, 0x370,
  1615. 0x380, 0x390, 0x3a0, 0x3b0, 0x3c0, 0x3d0, 0x3e0, 0x3f0};
  1616. int nMIDI_Ports = sizeof(MIDI_Ports)/sizeof(ULONG);
  1617. BOOL bMidiOutFound = FALSE;
  1618. m_COMMInterface = COMM_MIDI_BACKDOOR;
  1619. *pCOMMInterface = COMM_MIDI_BACKDOOR;
  1620. *pCOMMPort = 0;
  1621. for (int i=0;i<nMIDI_Ports;i++)
  1622. {
  1623. #ifdef _DEBUG
  1624. wsprintf(g_cMsg,"FindJoltBackdoor: Midi Port:%lx - ", MIDI_Ports[i]);
  1625. DebugOut(g_cMsg);
  1626. #endif
  1627. // We have the Port #, Let's see if Jolt is out there
  1628. hRet = g_pDriverCommunicator->SetBackdoorPort(MIDI_Ports[i]);
  1629. if (SUCCESS == hRet)
  1630. {
  1631. if (QueryForJolt())
  1632. {
  1633. DebugOut(" Success!\n");
  1634. bMidiOutFound = TRUE;
  1635. *pCOMMPort = MIDI_Ports[i];
  1636. break;
  1637. }
  1638. else
  1639. DebugOut(" No Answer\n");
  1640. }
  1641. }
  1642. return (bMidiOutFound);
  1643. }
  1644. // *** ---------------------------------------------------------------------***
  1645. // Function: QueryForJolt
  1646. // Purpose: Sends Shutdown and Queries for Shutdown status bit
  1647. // Parameters: none
  1648. // Returns: BOOL TRUE if Jolt found, else FALSE
  1649. //
  1650. // Comments: SHUTDOWN is destructive!!!
  1651. //
  1652. // *** ---------------------------------------------------------------------***
  1653. BOOL CJoltMidi::QueryForJolt(void)
  1654. {
  1655. HRESULT hRet;
  1656. // Send Shutdown command then detect if Shutdown Detect bit is set
  1657. SWDEVICESTATE SWDeviceState = {sizeof(SWDEVICESTATE)};
  1658. for (int i=0;i<MAX_RETRY_COUNT;i++)
  1659. {
  1660. // Send a ShutDown, then check for response
  1661. MidiSendShortMsg((SYSTEM_CMD|DEFAULT_MIDI_CHANNEL), SWDEV_SHUTDOWN, 0);
  1662. Sleep(DelayParamsPtrOf()->dwShutdownDelay); // 10 ms
  1663. if (SUCCESS == (hRet=GetJoltStatus(&SWDeviceState))) break;
  1664. }
  1665. Sleep(DelayParamsPtrOf()->dwDigitalOverdrivePrechargeCmdDelay);
  1666. // Clear the Previous state and turn on tri-state buffers
  1667. LOCAL_PRODUCT_ID ProductID = {sizeof LOCAL_PRODUCT_ID };
  1668. hRet = GetJoltID(&ProductID);
  1669. if (SUCCESS != hRet)
  1670. {
  1671. #ifdef _DEBUG
  1672. DebugOut("QueryForJolt: Driver Error. Get Jolt Status/ID\n");
  1673. #endif
  1674. return (FALSE);
  1675. }
  1676. if (SWDeviceState.m_ShutdownDetect)
  1677. return (TRUE);
  1678. else
  1679. return (FALSE);
  1680. }
  1681. // *** ---------------------------------------------------------------------***
  1682. // Function: MidiSendShortMsg
  1683. // Purpose: Send status, channel and data.
  1684. // Parameters:
  1685. // BYTE cStatus - MIDI status byte for this message
  1686. // BYTE cData1 - MIDI data byte for this message
  1687. // BYTE cData2 - 2nd MIDI data byte for this message (may be 0)
  1688. // Returns: HRESULT
  1689. //
  1690. // *** ---------------------------------------------------------------------***
  1691. HRESULT CJoltMidi::MidiSendShortMsg(
  1692. IN BYTE cStatus,
  1693. IN BYTE cData1,
  1694. IN BYTE cData2)
  1695. {
  1696. //
  1697. // --- THIS IS A CRITICAL SECTION
  1698. //
  1699. CriticalLock cl;
  1700. DWORD dwMsg;
  1701. HRESULT hRet = SUCCESS;
  1702. // For diagnostics, record the attempts at this message
  1703. BumpShortMsgCounter();
  1704. if ((m_COMMInterface == COMM_WINMM) && (NULL == m_MidiOutInfo.hMidiOut))
  1705. {
  1706. DebugOut("SW_EFFECT: No Midi Out Devs opened\r\n ");
  1707. ASSUME_NOT_REACHED();
  1708. return (SFERR_DRIVER_ERROR);
  1709. }
  1710. // pack the message and send it
  1711. dwMsg = MAKEMIDISHORTMSG(cStatus, m_MidiChannel, cData1, cData2);
  1712. if (COMM_WINMM == m_COMMInterface)
  1713. {
  1714. // Clear the Event Callback
  1715. BOOL bRet = ResetEvent(m_hMidiOutputEvent);
  1716. // send the message only if valid Handle
  1717. if (SUCCESS == ValidateMidiHandle())
  1718. {
  1719. hRet = midiOutShortMsg(m_MidiOutInfo.hMidiOut, dwMsg);
  1720. }
  1721. else
  1722. {
  1723. return (SFERR_DRIVER_ERROR);
  1724. }
  1725. if (SUCCESS != hRet) hRet = SFERR_DRIVER_ERROR;
  1726. }
  1727. else
  1728. {
  1729. hRet = g_pDriverCommunicator->SendBackdoorShortMidi(dwMsg);
  1730. }
  1731. // --- END OF CRITICAL SECTION
  1732. //
  1733. return (hRet);
  1734. }
  1735. // *** ---------------------------------------------------------------------***
  1736. // Function: MidiSendLongMsg
  1737. // Purpose: Send system exclusive message or series of short messages.
  1738. // Parameters:
  1739. // none - assumes m_pMidiOutInfo structure is valid
  1740. //
  1741. // Returns:
  1742. //
  1743. //
  1744. // *** ---------------------------------------------------------------------***
  1745. HRESULT CJoltMidi::MidiSendLongMsg(void)
  1746. {
  1747. //
  1748. // --- THIS IS A CRITICAL SECTION
  1749. //
  1750. CriticalLock cl;
  1751. if (NULL == g_pJoltMidi) return (SFERR_DRIVER_ERROR);
  1752. HRESULT hRet = SUCCESS;
  1753. // For diagnostics, record the attempts at this message
  1754. BumpLongMsgCounter();
  1755. if (m_MidiOutInfo.uDeviceType != MIDI_OUT)
  1756. {
  1757. #ifdef _DEBUG
  1758. MessageBox(NULL, "Must use a MIDI output device",
  1759. "MidiSendLongMsg", MB_ICONSTOP);
  1760. #endif
  1761. return (SFERR_DRIVER_ERROR);
  1762. }
  1763. if (COMM_WINMM == m_COMMInterface)
  1764. {
  1765. // Clear the Event Callback
  1766. BOOL bRet = ResetEvent(m_hMidiOutputEvent);
  1767. // send the long message only if valid Handle
  1768. if (SUCCESS == ValidateMidiHandle())
  1769. hRet = midiOutLongMsg(m_MidiOutInfo.hMidiOut,
  1770. &(m_MidiOutInfo.MidiHdr), sizeof(MIDIHDR));
  1771. else
  1772. {
  1773. return (SFERR_DRIVER_ERROR);
  1774. }
  1775. if (SUCCESS == hRet)
  1776. m_MidiOutInfo.uDeviceStatus = MIDI_DEVICE_BUSY;
  1777. else
  1778. {
  1779. if (m_MidiOutInfo.MidiHdr.dwFlags != MHDR_DONE)
  1780. {
  1781. // abort the current message
  1782. hRet = midiOutReset(m_MidiOutInfo.hMidiOut);
  1783. // set the device status because buffer(s) have been marked as
  1784. // done and returned to the application
  1785. if (SUCCESS == hRet)
  1786. m_MidiOutInfo.uDeviceStatus = MIDI_DEVICE_ABANDONED;
  1787. }
  1788. else
  1789. // tried to abort but the operation was already complete
  1790. m_MidiOutInfo.uDeviceStatus = MIDI_DEVICE_IDLE;
  1791. }
  1792. if (SUCCESS != hRet) hRet = (SFERR_DRIVER_ERROR);
  1793. }
  1794. else
  1795. {
  1796. hRet = g_pDriverCommunicator->SendBackdoorLongMidi(PBYTE(m_MidiOutInfo.MidiHdr.lpData));
  1797. }
  1798. Sleep(g_pJoltMidi->DelayParamsPtrOf()->dwLongMsgDelay);
  1799. // --- END OF CRITICAL SECTION
  1800. //
  1801. return (hRet);
  1802. }
  1803. // *** ---------------------------------------------------------------------***
  1804. // Function: ValidateMidiHandle
  1805. // Purpose: Validates Midi handle and reopens if necessary
  1806. // Parameters:
  1807. // none - assumes m_pMidiOutInfo structure is valid
  1808. //
  1809. // Returns:
  1810. //
  1811. //
  1812. // *** ---------------------------------------------------------------------***
  1813. HRESULT CJoltMidi::ValidateMidiHandle(void)
  1814. {
  1815. HRESULT hRet = SUCCESS;
  1816. UINT dwID;
  1817. if (MMSYSERR_INVALHANDLE == midiOutGetID(m_MidiOutInfo.hMidiOut, &dwID))
  1818. {
  1819. #ifdef _DEBUG
  1820. DebugOut("CJoltMidi::MidiValidateHandle - Midi Handle invalid. Re-opening...\n");
  1821. #endif
  1822. // Clear old global handle and Re-open Midi channel
  1823. // ***** Shared Memory Access *****
  1824. LockSharedMemory();
  1825. m_pSharedMemory->m_hMidiOut = NULL;
  1826. UnlockSharedMemory();
  1827. // ***** End of Shared Memory Access *****
  1828. hRet = OpenOutput(m_MidiOutInfo.uDeviceID);
  1829. }
  1830. return (hRet);
  1831. }
  1832. // *** ---------------------------------------------------------------------***
  1833. // Function: MidiAssignBuffer
  1834. // Purpose: Assign lpData and dwBufferLength members and prepare the
  1835. // MIDIHDR. Also add the buffer if it is an input buffer.
  1836. // If the third parameter is false, unprepare and reinitialize
  1837. // the header.
  1838. // Parameters:
  1839. // LPSTR lpData - address of buffer, NULL if cleaning up
  1840. // DWORD dwBufferLength - buffer size in bytes
  1841. // BOOL fAssign - TRUE = Assign, FALSE = cleanup
  1842. //
  1843. // Returns: SUCCESS or SFERR_DRIVER_ERROR
  1844. //
  1845. // Note: assumes m_pMidiOutInfo structure is valid
  1846. //
  1847. // *** ---------------------------------------------------------------------***
  1848. HRESULT CJoltMidi::MidiAssignBuffer(
  1849. LPSTR lpData, // address of buffer, NULL if cleaning up
  1850. DWORD dwBufferLength, // size of buffer in bytes, 0L if cleaning up
  1851. BOOL fAssign) // TRUE = assign, FALSE = cleanup
  1852. {
  1853. //
  1854. // --- THIS IS A CRITICAL SECTION
  1855. //
  1856. CriticalLock cl;
  1857. #ifdef _DEBUG
  1858. DebugOut("MidiAssignBuffer:\n");
  1859. #endif
  1860. HRESULT hRet = SUCCESS;
  1861. if (m_MidiOutInfo.uDeviceType == MIDI_OUT)
  1862. {
  1863. if ((COMM_WINMM == m_COMMInterface) && !m_MidiOutInfo.hMidiOut)
  1864. {
  1865. if (!fAssign && m_MidiOutInfo.uDeviceStatus == MIDI_DEVICE_ABANDONED)
  1866. {
  1867. // clear the device status
  1868. m_MidiOutInfo.uDeviceStatus = MIDI_DEVICE_IDLE;
  1869. // don't return an error for this case because if the user aborts
  1870. // the transmission of a long message before it completes the
  1871. // buffers will be marked as done and returned to the application,
  1872. // just as when recording successfully completes. So it is ok
  1873. // for this function to be called (with fAssign = FALSE) when
  1874. // hMidiIn = 0, as long as uDeviceStatus = MIDI_DEVICE_ABANDONED.
  1875. return (SUCCESS);
  1876. }
  1877. else
  1878. {
  1879. // all other cases are an application error
  1880. #ifdef _DEBUG
  1881. MessageBox(NULL, "Must open MIDI output device first",
  1882. "MidiAssignBuffer", MB_ICONSTOP);
  1883. #endif
  1884. // because this failed call might result in an input or output
  1885. // device being reset (if the application is written to do so),
  1886. // an MM_MOM_DONE or MM_MIM_LONGDATA message could be sent to
  1887. // the application. This might result in an additional call to
  1888. // this routine, so set the device status to prevent another
  1889. // error message
  1890. m_MidiOutInfo.uDeviceStatus = MIDI_DEVICE_ABANDONED;
  1891. return (SFERR_DRIVER_ERROR);
  1892. }
  1893. }
  1894. }
  1895. else
  1896. {
  1897. #ifdef _DEBUG
  1898. DebugOut("\r\nMidiAssignBuffer: uDeviceType bad");
  1899. #endif
  1900. return (SFERR_INVALID_PARAM);
  1901. }
  1902. if (fAssign)
  1903. {
  1904. // check for the buffer's address and size
  1905. if (!lpData || !dwBufferLength)
  1906. {
  1907. #ifdef _DEBUG
  1908. MessageBox(NULL, "Must specify a buffer and size",
  1909. "MidiAssignBuffer", MB_ICONSTOP);
  1910. #endif
  1911. return (SFERR_INVALID_PARAM);
  1912. }
  1913. // assign buffer to the MIDIHDR
  1914. m_MidiOutInfo.MidiHdr.lpData = lpData;
  1915. m_MidiOutInfo.MidiHdr.dwBufferLength = dwBufferLength;
  1916. m_MidiOutInfo.MidiHdr.dwBytesRecorded = dwBufferLength;
  1917. if (COMM_WINMM == m_COMMInterface)
  1918. {
  1919. // prepare the MIDIHDR
  1920. m_MidiOutInfo.MidiHdr.dwFlags = 0;
  1921. hRet = midiOutPrepareHeader(m_MidiOutInfo.hMidiOut,
  1922. &(m_MidiOutInfo.MidiHdr), sizeof(MIDIHDR));
  1923. }
  1924. }
  1925. else
  1926. { // unprepare the MIDIHDR
  1927. if (COMM_WINMM == m_COMMInterface)
  1928. {
  1929. if ((m_MidiOutInfo.MidiHdr.dwFlags & MHDR_DONE) != MHDR_DONE)
  1930. {
  1931. //hRet = midiOutReset(m_MidiOutInfo.hMidiOut);
  1932. }
  1933. if (SUCCESS == hRet)
  1934. {
  1935. hRet = midiOutUnprepareHeader(m_MidiOutInfo.hMidiOut,
  1936. &(m_MidiOutInfo.MidiHdr), sizeof(MIDIHDR));
  1937. }
  1938. }
  1939. else
  1940. hRet = SUCCESS;
  1941. if (SUCCESS == hRet)
  1942. {
  1943. // reinitialize MIDIHDR to guard against casual re-use
  1944. m_MidiOutInfo.MidiHdr.lpData = NULL;
  1945. m_MidiOutInfo.MidiHdr.dwBufferLength = 0;
  1946. m_MidiOutInfo.MidiHdr.dwBytesRecorded = 0;
  1947. // clear the device status
  1948. m_MidiOutInfo.uDeviceStatus = MIDI_DEVICE_IDLE;
  1949. }
  1950. }
  1951. if (SUCCESS != hRet) hRet = SFERR_DRIVER_ERROR;
  1952. #ifdef _DEBUG
  1953. wsprintf(g_cMsg, "Returning from MidiAssignBuffer: %lx\n", hRet);
  1954. #endif
  1955. // --- END OF CRITICAL SECTION
  1956. //
  1957. return (hRet);
  1958. }
  1959. // ****************************************************************************
  1960. // *** --- Helper functions for CJoltMidi
  1961. //
  1962. // ****************************************************************************
  1963. //
  1964. #define REGSTR_VAL_FIRMWARE_PARAMS "FirmwareParams"
  1965. void GetFirmwareParams(UINT nJoystickID, PFIRMWARE_PARAMS pFirmwareParams)
  1966. {
  1967. BOOL bFail = FALSE;
  1968. // try to open the registry key
  1969. HKEY hKey;
  1970. DWORD dwcb = sizeof(FIRMWARE_PARAMS);
  1971. LONG lr;
  1972. hKey = joyOpenOEMForceFeedbackKey(nJoystickID);
  1973. if(!hKey)
  1974. bFail = TRUE;
  1975. if (!bFail)
  1976. {
  1977. // Get Firmware Parameters
  1978. lr = RegQueryValueEx( hKey,
  1979. REGSTR_VAL_FIRMWARE_PARAMS,
  1980. NULL, NULL,
  1981. (PBYTE)pFirmwareParams,
  1982. &dwcb);
  1983. RegCloseKey(hKey);
  1984. if (lr != ERROR_SUCCESS)
  1985. bFail = TRUE;
  1986. }
  1987. if(bFail)
  1988. {
  1989. // if reading from the registry fails, just use the defaults
  1990. pFirmwareParams->dwScaleKx = DEF_SCALE_KX;
  1991. pFirmwareParams->dwScaleKy = DEF_SCALE_KY;
  1992. pFirmwareParams->dwScaleBx = DEF_SCALE_BX;
  1993. pFirmwareParams->dwScaleBy = DEF_SCALE_BY;
  1994. pFirmwareParams->dwScaleMx = DEF_SCALE_MX;
  1995. pFirmwareParams->dwScaleMy = DEF_SCALE_MY;
  1996. pFirmwareParams->dwScaleFx = DEF_SCALE_FX;
  1997. pFirmwareParams->dwScaleFy = DEF_SCALE_FY;
  1998. pFirmwareParams->dwScaleW = DEF_SCALE_W;
  1999. }
  2000. }
  2001. #define REGSTR_VAL_SYSTEM_PARAMS "SystemParams"
  2002. void GetSystemParams(UINT nJoystickID, PSYSTEM_PARAMS pSystemParams)
  2003. {
  2004. BOOL bFail = FALSE;
  2005. // try to open the registry key
  2006. HKEY hKey;
  2007. DWORD dwcb = sizeof(SYSTEM_PARAMS);
  2008. LONG lr;
  2009. hKey = joyOpenOEMForceFeedbackKey(nJoystickID);
  2010. if(!hKey)
  2011. bFail = TRUE;
  2012. if (!bFail)
  2013. {
  2014. // Get Firmware Parameters
  2015. lr = RegQueryValueEx( hKey,
  2016. REGSTR_VAL_SYSTEM_PARAMS,
  2017. NULL, NULL,
  2018. (PBYTE)pSystemParams,
  2019. &dwcb);
  2020. // scale them
  2021. pSystemParams->RTCSpringParam.m_XKConstant /= SCALE_CONSTANTS;
  2022. pSystemParams->RTCSpringParam.m_YKConstant /= SCALE_CONSTANTS;
  2023. pSystemParams->RTCSpringParam.m_XAxisCenter /= SCALE_POSITION;
  2024. pSystemParams->RTCSpringParam.m_YAxisCenter = -pSystemParams->RTCSpringParam.m_YAxisCenter/SCALE_POSITION;
  2025. pSystemParams->RTCSpringParam.m_XSaturation /= SCALE_POSITION;
  2026. pSystemParams->RTCSpringParam.m_YSaturation /= SCALE_POSITION;
  2027. pSystemParams->RTCSpringParam.m_XDeadBand /= SCALE_POSITION;
  2028. pSystemParams->RTCSpringParam.m_YDeadBand /= SCALE_POSITION;
  2029. RegCloseKey(hKey);
  2030. if (lr != ERROR_SUCCESS)
  2031. bFail = TRUE;
  2032. }
  2033. if(bFail)
  2034. {
  2035. // if reading from the registry fails, just use the defaults
  2036. pSystemParams->RTCSpringParam.m_Bytes = sizeof(RTCSPRING_PARAM);
  2037. pSystemParams->RTCSpringParam.m_XKConstant = DEFAULT_RTC_KX;
  2038. pSystemParams->RTCSpringParam.m_YKConstant = DEFAULT_RTC_KY;
  2039. pSystemParams->RTCSpringParam.m_XAxisCenter = DEFAULT_RTC_X0;
  2040. pSystemParams->RTCSpringParam.m_YAxisCenter = DEFAULT_RTC_Y0;
  2041. pSystemParams->RTCSpringParam.m_XSaturation = DEFAULT_RTC_XSAT;
  2042. pSystemParams->RTCSpringParam.m_YSaturation = DEFAULT_RTC_YSAT;
  2043. pSystemParams->RTCSpringParam.m_XDeadBand = DEFAULT_RTC_XDBAND;
  2044. pSystemParams->RTCSpringParam.m_YDeadBand = DEFAULT_RTC_YDBAND;
  2045. }
  2046. }
  2047. #define REGSTR_VAL_DELAY_PARAMS "TimingParams"
  2048. void GetDelayParams(UINT nJoystickID, PDELAY_PARAMS pDelayParams)
  2049. {
  2050. BOOL bFail = FALSE;
  2051. // try to open the registry key
  2052. HKEY hKey;
  2053. DWORD dwcb = sizeof(DELAY_PARAMS);
  2054. LONG lr;
  2055. hKey = joyOpenOEMForceFeedbackKey(nJoystickID);
  2056. if(!hKey)
  2057. bFail = TRUE;
  2058. if (!bFail)
  2059. {
  2060. // Get Firmware Parameters
  2061. lr = RegQueryValueEx( hKey,
  2062. REGSTR_VAL_DELAY_PARAMS,
  2063. NULL, NULL,
  2064. (PBYTE)pDelayParams,
  2065. &dwcb);
  2066. RegCloseKey(hKey);
  2067. if (lr != ERROR_SUCCESS)
  2068. bFail = TRUE;
  2069. }
  2070. if(bFail)
  2071. {
  2072. // if reading from the registry fails, just use the defaults
  2073. pDelayParams->dwBytes = sizeof(DELAY_PARAMS);
  2074. pDelayParams->dwDigitalOverdrivePrechargeCmdDelay = DEFAULT_DIGITAL_OVERDRIVE_PRECHARGE_CMD_DELAY;
  2075. pDelayParams->dwShutdownDelay = DEFAULT_SHUTDOWN_DELAY;
  2076. pDelayParams->dwHWResetDelay = DEFAULT_HWRESET_DELAY;
  2077. pDelayParams->dwPostSetDeviceStateDelay = DEFAULT_POST_SET_DEVICE_STATE_DELAY;
  2078. pDelayParams->dwGetEffectStatusDelay = DEFAULT_GET_EFFECT_STATUS_DELAY;
  2079. pDelayParams->dwGetDataPacketDelay = DEFAULT_GET_DATA_PACKET_DELAY;
  2080. pDelayParams->dwGetStatusPacketDelay = DEFAULT_GET_STATUS_PACKET_DELAY;
  2081. pDelayParams->dwGetIDPacketDelay = DEFAULT_GET_ID_PACKET_DELAY;
  2082. pDelayParams->dwGetStatusGateDataDelay = DEFAULT_GET_STATUS_GATE_DATA_DELAY;
  2083. pDelayParams->dwSetIndexDelay = DEFAULT_SET_INDEX_DELAY;
  2084. pDelayParams->dwModifyParamDelay = DEFAULT_MODIFY_PARAM_DELAY;
  2085. pDelayParams->dwForceOutDelay = DEFAULT_FORCE_OUT_DELAY;
  2086. pDelayParams->dwShortMsgDelay = DEFAULT_SHORT_MSG_DELAY;
  2087. pDelayParams->dwLongMsgDelay = DEFAULT_LONG_MSG_DELAY;
  2088. pDelayParams->dwDestroyEffectDelay = DEFAULT_DESTROY_EFFECT_DELAY;
  2089. pDelayParams->dwForceOutMod = DEFAULT_FORCE_OUT_MOD;
  2090. // write the defaults to the registry
  2091. hKey = joyOpenOEMForceFeedbackKey(nJoystickID);
  2092. if(hKey)
  2093. {
  2094. // Modify Registry Values
  2095. RegSetValueEx ( hKey, REGSTR_VAL_DELAY_PARAMS, 0, REG_BINARY, (const unsigned char *)pDelayParams, sizeof(DELAY_PARAMS) );
  2096. // Close Key
  2097. RegCloseKey(hKey);
  2098. }
  2099. }
  2100. if(pDelayParams->dwForceOutMod == 0)
  2101. pDelayParams->dwForceOutMod = 1;
  2102. }
  2103. #define REGSTR_VAL_JOYSTICK_PARAMS "JoystickParams"
  2104. void GetJoystickParams(UINT nJoystickID, PJOYSTICK_PARAMS pJoystickParams)
  2105. {
  2106. BOOL bFail = FALSE;
  2107. // try to open the registry key
  2108. HKEY hKey;
  2109. DWORD dwcb = sizeof(JOYSTICK_PARAMS);
  2110. LONG lr;
  2111. hKey = joyOpenOEMForceFeedbackKey(nJoystickID);
  2112. if(!hKey)
  2113. bFail = TRUE;
  2114. if (!bFail)
  2115. {
  2116. // Get Firmware Parameters
  2117. lr = RegQueryValueEx( hKey,
  2118. REGSTR_VAL_JOYSTICK_PARAMS,
  2119. NULL, NULL,
  2120. (PBYTE)pJoystickParams,
  2121. &dwcb);
  2122. RegCloseKey(hKey);
  2123. if (lr != ERROR_SUCCESS)
  2124. bFail = TRUE;
  2125. }
  2126. if(bFail)
  2127. {
  2128. // if reading from the registry fails, just use the defaults
  2129. pJoystickParams->dwXYConst = DEF_XY_CONST;
  2130. pJoystickParams->dwRotConst = DEF_ROT_CONST;
  2131. pJoystickParams->dwSldrConst = DEF_SLDR_CONST;
  2132. pJoystickParams->dwAJPos = DEF_AJ_POS;
  2133. pJoystickParams->dwAJRot = DEF_AJ_ROT;
  2134. pJoystickParams->dwAJSldr = DEF_AJ_SLDR;
  2135. pJoystickParams->dwSprScl = DEF_SPR_SCL;
  2136. pJoystickParams->dwBmpScl = DEF_BMP_SCL;
  2137. pJoystickParams->dwDmpScl = DEF_DMP_SCL;
  2138. pJoystickParams->dwInertScl = DEF_INERT_SCL;
  2139. pJoystickParams->dwVelOffScl = DEF_VEL_OFFSET_SCL;
  2140. pJoystickParams->dwAccOffScl = DEF_ACC_OFFSET_SCL;
  2141. pJoystickParams->dwYMotBoost = DEF_Y_MOT_BOOST;
  2142. pJoystickParams->dwXMotSat = DEF_X_MOT_SATURATION;
  2143. pJoystickParams->dwReserved = 0;
  2144. pJoystickParams->dwMasterGain = 0;
  2145. }
  2146. }
  2147. void UpdateJoystickParams(PJOYSTICK_PARAMS pJoystickParams)
  2148. {
  2149. // modify the Joystick Params by modifying the SYSTEM_EFFECT_ID
  2150. // note that some parameters must be divided by 2 before being sent
  2151. // Jolt will multiply by 2 to restore to original
  2152. CMD_ModifyParamByIndex(INDEX0, SYSTEM_EFFECT_ID, ((WORD)(pJoystickParams->dwXYConst))/2);
  2153. CMD_ModifyParamByIndex(INDEX1, SYSTEM_EFFECT_ID, ((WORD)(pJoystickParams->dwRotConst))/2);
  2154. CMD_ModifyParamByIndex(INDEX2, SYSTEM_EFFECT_ID, (WORD)(pJoystickParams->dwSldrConst));
  2155. CMD_ModifyParamByIndex(INDEX3, SYSTEM_EFFECT_ID, (WORD)(pJoystickParams->dwAJPos));
  2156. CMD_ModifyParamByIndex(INDEX4, SYSTEM_EFFECT_ID, (WORD)(pJoystickParams->dwAJRot));
  2157. CMD_ModifyParamByIndex(INDEX5, SYSTEM_EFFECT_ID, (WORD)(pJoystickParams->dwAJSldr));
  2158. CMD_ModifyParamByIndex(INDEX6, SYSTEM_EFFECT_ID, (WORD)(pJoystickParams->dwSprScl));
  2159. CMD_ModifyParamByIndex(INDEX7, SYSTEM_EFFECT_ID, (WORD)(pJoystickParams->dwBmpScl));
  2160. CMD_ModifyParamByIndex(INDEX8, SYSTEM_EFFECT_ID, (WORD)(pJoystickParams->dwDmpScl));
  2161. CMD_ModifyParamByIndex(INDEX9, SYSTEM_EFFECT_ID, (WORD)(pJoystickParams->dwInertScl));
  2162. CMD_ModifyParamByIndex(INDEX10, SYSTEM_EFFECT_ID, (WORD)(pJoystickParams->dwVelOffScl));
  2163. CMD_ModifyParamByIndex(INDEX11, SYSTEM_EFFECT_ID, (WORD)(pJoystickParams->dwAccOffScl));
  2164. CMD_ModifyParamByIndex(INDEX12, SYSTEM_EFFECT_ID, ((WORD)(pJoystickParams->dwYMotBoost))/2);
  2165. CMD_ModifyParamByIndex(INDEX13, SYSTEM_EFFECT_ID, (WORD)(pJoystickParams->dwXMotSat));
  2166. }
  2167. // ****************************************************************************
  2168. // *** --- Member functions for base class CMidiEffect
  2169. //
  2170. // ****************************************************************************
  2171. //
  2172. // ----------------------------------------------------------------------------
  2173. // Function: CMidiEffect::CMidiEffect
  2174. // Purpose: Constructor(s)/Destructor for CMidiEffect Object
  2175. // Parameters:
  2176. // Returns:
  2177. // Algorithm:
  2178. // ----------------------------------------------------------------------------
  2179. CMidiEffect::CMidiEffect(IN ULONG ulButtonPlayMask)
  2180. {
  2181. m_bSysExCmd = SYS_EX_CMD; // SysEx Fx command
  2182. m_bEscManufID = 0; // Escape to long Manufac. ID, s/b 0
  2183. m_bManufIDL = (MS_MANUFACTURER_ID & 0x7f); // Low byte
  2184. m_bManufIDH = ((MS_MANUFACTURER_ID >> 8) & 0x7f); // High byte
  2185. m_bProdID = JOLT_PRODUCT_ID; // Product ID
  2186. m_bAxisMask = X_AXIS|Y_AXIS;
  2187. m_bEffectID = NEW_EFFECT_ID; // Default to indicate create NEW
  2188. Effect.bDurationL = 1; // in 2ms increments
  2189. Effect.bDurationH = 0; // in 2ms increments
  2190. Effect.bAngleL = 0; // 0 to 359 degrees
  2191. Effect.bAngleH = 0;
  2192. Effect.bGain = (BYTE) 100; // 1 to 100 %
  2193. Effect.bButtonPlayL = (BYTE) ulButtonPlayMask & 0x7f;
  2194. Effect.bButtonPlayH = (BYTE) ((ulButtonPlayMask >> 7) & 0x03);// Button 1- 9
  2195. Effect.bForceOutRateL= DEFAULT_JOLT_FORCE_RATE; // 1 to 500 Hz
  2196. Effect.bForceOutRateH=0;
  2197. Effect.bPercentL = (BYTE) ((DEFAULT_PERCENT) & 0x7f);
  2198. Effect.bPercentH = (BYTE) ((DEFAULT_PERCENT >> 7 ) & 0x7f);
  2199. m_LoopCount = 1; // Default
  2200. SetPlayMode(PLAY_STORE); // Default
  2201. }
  2202. // ----------------------------------------------------------------------------
  2203. // Function: CMidiEffect::CMidiEffect
  2204. // Purpose: Constructor(s)/Destructor for CMidiEffect Object
  2205. // Parameters:
  2206. // Returns:
  2207. // Algorithm:
  2208. // ----------------------------------------------------------------------------
  2209. CMidiEffect::CMidiEffect(
  2210. IN PEFFECT pEffect,
  2211. IN PENVELOPE pEnvelope)
  2212. {
  2213. m_bSysExCmd = SYS_EX_CMD; // SysEx Fx command
  2214. m_bEscManufID = 0; // Escape to long Manufac. ID, s/b 0
  2215. m_bManufIDL = (MS_MANUFACTURER_ID & 0x7f); // Low byte
  2216. m_bManufIDH = ((MS_MANUFACTURER_ID >> 8) & 0x7f); // High byte
  2217. m_bProdID = JOLT_PRODUCT_ID; // Product ID
  2218. m_bAxisMask = X_AXIS|Y_AXIS;
  2219. m_OpCode = DNLOAD_DATA | X_AXIS|Y_AXIS; // Subcommand opcode:DNLOAD_DATA
  2220. m_bEffectID = NEW_EFFECT_ID; // Default to indicate create NEW
  2221. SetDuration(pEffect->m_Duration);
  2222. Effect.bDurationL = (BYTE) (m_Duration & 0x7f); // in 2ms increments
  2223. Effect.bDurationH = (BYTE) ((m_Duration >> 7 ) & 0x7f); // in 2ms increments
  2224. Effect.bAngleL = (BYTE) (pEffect->m_DirectionAngle2D & 0x7f); // 0 to 359 degrees
  2225. Effect.bAngleH = (BYTE) ((pEffect->m_DirectionAngle2D >> 7 ) & 0x7f);
  2226. Effect.bGain = (BYTE) (pEffect->m_Gain & 0x7f); // 1 to 100 %
  2227. Effect.bButtonPlayL = (BYTE) (pEffect->m_ButtonPlayMask & 0x7f);
  2228. Effect.bButtonPlayH = (BYTE) ((pEffect->m_ButtonPlayMask >> 7) & 0x03);// Button 1- 9
  2229. Effect.bForceOutRateL=(BYTE) (pEffect->m_ForceOutputRate & 0x7f); // 1 to 500 Hz
  2230. Effect.bForceOutRateH=(BYTE) ((pEffect->m_ForceOutputRate >> 7 ) & 0x03);
  2231. Effect.bPercentL = (BYTE) ((DEFAULT_PERCENT) & 0x7f);
  2232. Effect.bPercentH = (BYTE) ((DEFAULT_PERCENT >> 7 ) & 0x7f);
  2233. m_LoopCount = 1; // Default
  2234. SetPlayMode(PLAY_STORE); // Default
  2235. // Set Envelope members
  2236. if (pEnvelope)
  2237. {
  2238. m_Envelope.m_Type = pEnvelope->m_Type;
  2239. m_Envelope.m_Attack = pEnvelope->m_Attack;
  2240. m_Envelope.m_Sustain = pEnvelope->m_Sustain;
  2241. m_Envelope.m_Decay = pEnvelope->m_Decay;
  2242. m_Envelope.m_StartAmp = (ULONG) (pEnvelope->m_StartAmp);
  2243. m_Envelope.m_SustainAmp = (ULONG) (pEnvelope->m_SustainAmp);
  2244. m_Envelope.m_EndAmp = (ULONG) (pEnvelope->m_EndAmp);
  2245. }
  2246. // save the original effect params
  2247. m_OriginalEffectParam = *pEffect;
  2248. }
  2249. // --- Destructor
  2250. CMidiEffect::~CMidiEffect()
  2251. {
  2252. memset(this, 0, sizeof(CMidiEffect));
  2253. }
  2254. // ----------------------------------------------------------------------------
  2255. // Function: CMidiEffect::SetDuration
  2256. // Purpose: Sets the Duration member
  2257. // Parameters: ULONG ulArg - the duration
  2258. // Returns:
  2259. // Algorithm:
  2260. // ----------------------------------------------------------------------------
  2261. void CMidiEffect::SetDuration(ULONG ulArg)
  2262. {
  2263. if (ulArg != 0)
  2264. {
  2265. ulArg = (ULONG) ( (float) ulArg/TICKRATE);
  2266. if (ulArg <= 0) ulArg = 1;
  2267. }
  2268. m_Duration = ulArg;
  2269. }
  2270. // ----------------------------------------------------------------------------
  2271. // Function: CMidiEffect::SetTotalDuration
  2272. // Purpose: Modifies the Effect.bDurationL/H parameter for Loop Counts
  2273. // Parameters: none
  2274. //
  2275. // Returns: Effect.bDurationL/H is filled with total duration
  2276. // Algorithm:
  2277. // Notes: Percentage is 1 to 10000
  2278. // Total Duration = ((Percentage of waveform)/10000) * Duration * Loop Count
  2279. // Example: Loop count of 1, the Percentage of waveform =10000,
  2280. // Total Duration = (10000/10000) * 1 * Duration
  2281. //
  2282. // ----------------------------------------------------------------------------
  2283. void CMidiEffect::SetTotalDuration(void)
  2284. {
  2285. ULONG ulPercent = Effect.bPercentL + ((USHORT)Effect.bPercentH << 7);
  2286. ULONG ulTotalDuration = (ULONG) (((float) ulPercent/10000.0)
  2287. * (float) m_LoopCount
  2288. * (float) m_Duration );
  2289. Effect.bDurationL = (BYTE) ulTotalDuration & 0x7f;
  2290. Effect.bDurationH = (BYTE) (ulTotalDuration >> 7) & 0x7f;
  2291. }
  2292. // ----------------------------------------------------------------------------
  2293. // Function: CMidiEffect::ComputeEnvelope
  2294. // Purpose: Computes the Envelope for the Effect, Loopcount in consideration
  2295. // Parameters: none
  2296. // Returns: none
  2297. // Algorithm:
  2298. //For our standard PERCENTAGE Envelope, set the following as default:
  2299. //m_Type = PERCENTAGE
  2300. //
  2301. // Baseline is (m_MaxAmp + m_MinAmp)/2
  2302. // m_StartAmp = 0
  2303. // m_SustainAmp = Effect.m_MaxAmp - baseline
  2304. // m_EndAmp = m_StartAmp;
  2305. // where: baseline = (Effect.m_MaxAmp + Effect.m_MinAmp)/2;
  2306. // ----------------------------------------------------------------------------
  2307. void CMidiEffect::ComputeEnvelope(void)
  2308. {
  2309. ULONG ulTimeToSustain;
  2310. ULONG ulTimeToDecay;
  2311. //REVIEW: TIME vs PERCENTAGE option
  2312. if (PERCENTAGE == m_Envelope.m_Type)
  2313. {
  2314. ULONG ulPercent = Effect.bPercentL + ((USHORT)Effect.bPercentH << 7);
  2315. ULONG ulTotalDuration = (ULONG) (((float) ulPercent/10000.0)
  2316. * (float) m_LoopCount
  2317. * (float) m_Duration );
  2318. ulTimeToSustain = (ULONG) ((m_Envelope.m_Attack * ulTotalDuration) /100.);
  2319. ulTimeToDecay = (ULONG) ((m_Envelope.m_Attack + m_Envelope.m_Sustain)
  2320. * ulTotalDuration /100.);
  2321. }
  2322. else // TIME option envelope
  2323. {
  2324. ulTimeToSustain = (ULONG) (m_Envelope.m_Attack);
  2325. ulTimeToDecay = (ULONG) (m_Envelope.m_Attack + m_Envelope.m_Sustain);
  2326. ulTimeToSustain = (ULONG) ( (float) ulTimeToSustain/TICKRATE);
  2327. ulTimeToDecay = (ULONG) ( (float) ulTimeToDecay/TICKRATE);
  2328. }
  2329. Envelope.bAttackLevel = (BYTE) (m_Envelope.m_StartAmp & 0x7f);
  2330. Envelope.bSustainLevel = (BYTE) (m_Envelope.m_SustainAmp & 0x7f);
  2331. Envelope.bDecayLevel = (BYTE) (m_Envelope.m_EndAmp & 0x7f);
  2332. Envelope.bSustainL = (BYTE) (ulTimeToSustain & 0x7f);
  2333. Envelope.bSustainH = (BYTE) ((ulTimeToSustain >> 7) & 0x7f);
  2334. Envelope.bDecayL = (BYTE) (ulTimeToDecay & 0x7f);
  2335. Envelope.bDecayH = (BYTE) ((ulTimeToDecay >> 7) & 0x7f);
  2336. }
  2337. // ----------------------------------------------------------------------------
  2338. // Function: CMidiEffect::SubTypeOf
  2339. // Purpose: Returns the SubType for the Effect
  2340. // Parameters: none
  2341. // Returns: ULONG - DirectEffect style SubType
  2342. // Algorithm:
  2343. // ----------------------------------------------------------------------------
  2344. ULONG CMidiEffect::SubTypeOf(void)
  2345. {
  2346. static EFFECT_TYPE EffectTypes[] = {
  2347. {BE_SPRING , ET_BE_SPRING},
  2348. {BE_SPRING_2D , ET_BE_SPRING},
  2349. {BE_DAMPER , ET_BE_DAMPER},
  2350. {BE_DAMPER_2D , ET_BE_DAMPER},
  2351. {BE_INERTIA , ET_BE_INERTIA},
  2352. {BE_INERTIA_2D , ET_BE_INERTIA},
  2353. {BE_FRICTION , ET_BE_FRICTION},
  2354. {BE_FRICTION_2D , ET_BE_FRICTION},
  2355. {BE_WALL , ET_BE_WALL},
  2356. {BE_DELAY , ET_BE_DELAY},
  2357. {SE_CONSTANT_FORCE , ET_SE_CONSTANT_FORCE},
  2358. {SE_SINE , ET_SE_SINE},
  2359. {SE_COSINE , ET_SE_COSINE},
  2360. {SE_SQUARELOW , ET_SE_SQUARELOW},
  2361. {SE_SQUAREHIGH , ET_SE_SQUAREHIGH},
  2362. {SE_RAMPUP , ET_SE_RAMPUP},
  2363. {SE_RAMPDOWN , ET_SE_RAMPDOWN},
  2364. {SE_TRIANGLEUP , ET_SE_TRIANGLEUP},
  2365. {SE_TRIANGLEDOWN , ET_SE_TRIANGLEDOWN},
  2366. {SE_SAWTOOTHUP , ET_SE_SAWTOOTHUP},
  2367. {SE_SAWTOOTHDOWN , ET_SE_SAWTOOTHDOWN},
  2368. {PL_CONCATENATE , ET_PL_CONCATENATE},
  2369. {PL_SUPERIMPOSE , ET_PL_SUPERIMPOSE},
  2370. {RE_ROMID1 , ET_RE_ROMID1 },
  2371. {RE_ROMID2 , ET_RE_ROMID2 },
  2372. {RE_ROMID3 , ET_RE_ROMID3 },
  2373. {RE_ROMID4 , ET_RE_ROMID4 },
  2374. {RE_ROMID5 , ET_RE_ROMID5 },
  2375. {RE_ROMID6 , ET_RE_ROMID6 },
  2376. {RE_ROMID7 , ET_RE_ROMID7 },
  2377. {RE_ROMID8 , ET_RE_ROMID8 },
  2378. {RE_ROMID9 , ET_RE_ROMID9 },
  2379. {RE_ROMID10 , ET_RE_ROMID10 },
  2380. {RE_ROMID11 , ET_RE_ROMID11 },
  2381. {RE_ROMID12 , ET_RE_ROMID12 },
  2382. {RE_ROMID13 , ET_RE_ROMID13 },
  2383. {RE_ROMID14 , ET_RE_ROMID14 },
  2384. {RE_ROMID15 , ET_RE_ROMID15 },
  2385. {RE_ROMID16 , ET_RE_ROMID16 },
  2386. {RE_ROMID17 , ET_RE_ROMID17 },
  2387. {RE_ROMID18 , ET_RE_ROMID18 },
  2388. {RE_ROMID19 , ET_RE_ROMID19 },
  2389. {RE_ROMID20 , ET_RE_ROMID20 },
  2390. {RE_ROMID21 , ET_RE_ROMID21 },
  2391. {RE_ROMID22 , ET_RE_ROMID22 },
  2392. {RE_ROMID23 , ET_RE_ROMID23 },
  2393. {RE_ROMID24 , ET_RE_ROMID24 },
  2394. {RE_ROMID25 , ET_RE_ROMID25 },
  2395. {RE_ROMID26 , ET_RE_ROMID26 },
  2396. {RE_ROMID27 , ET_RE_ROMID27 },
  2397. {RE_ROMID28 , ET_RE_ROMID28 },
  2398. {RE_ROMID29 , ET_RE_ROMID29 },
  2399. {RE_ROMID30 , ET_RE_ROMID30 },
  2400. {RE_ROMID31 , ET_RE_ROMID31 },
  2401. {RE_ROMID32 , ET_RE_ROMID32 }};
  2402. int nNumEffectTypes = sizeof(EffectTypes)/(sizeof(EFFECT_TYPE));
  2403. for (int i=0; i<nNumEffectTypes; i++)
  2404. {
  2405. if (m_SubType == EffectTypes[i].bDeviceSubType)
  2406. return EffectTypes[i].ulHostSubType;
  2407. }
  2408. return (NULL);
  2409. }
  2410. // ----------------------------------------------------------------------------
  2411. // Function: CMidiEffect::SubTypeOf
  2412. // Purpose: Sets the SubType for the Effect
  2413. // Parameters: ULONG - DirectEffect style SubType
  2414. // Returns: none
  2415. // Algorithm:
  2416. // ----------------------------------------------------------------------------
  2417. void CMidiEffect::SetSubType(ULONG ulSubType)
  2418. {
  2419. static EFFECT_TYPE EffectTypes[] = {
  2420. {BE_SPRING , ET_BE_SPRING},
  2421. {BE_SPRING_2D , ET_BE_SPRING},
  2422. {BE_DAMPER , ET_BE_DAMPER},
  2423. {BE_DAMPER_2D , ET_BE_DAMPER},
  2424. {BE_INERTIA , ET_BE_INERTIA},
  2425. {BE_INERTIA_2D , ET_BE_INERTIA},
  2426. {BE_FRICTION , ET_BE_FRICTION},
  2427. {BE_FRICTION_2D , ET_BE_FRICTION},
  2428. {BE_WALL , ET_BE_WALL},
  2429. {BE_DELAY , ET_BE_DELAY},
  2430. {SE_CONSTANT_FORCE , ET_SE_CONSTANT_FORCE},
  2431. {SE_SINE , ET_SE_SINE},
  2432. {SE_COSINE , ET_SE_COSINE},
  2433. {SE_SQUARELOW , ET_SE_SQUARELOW},
  2434. {SE_SQUAREHIGH , ET_SE_SQUAREHIGH},
  2435. {SE_RAMPUP , ET_SE_RAMPUP},
  2436. {SE_RAMPDOWN , ET_SE_RAMPDOWN},
  2437. {SE_TRIANGLEUP , ET_SE_TRIANGLEUP},
  2438. {SE_TRIANGLEDOWN , ET_SE_TRIANGLEDOWN},
  2439. {SE_SAWTOOTHUP , ET_SE_SAWTOOTHUP},
  2440. {SE_SAWTOOTHDOWN , ET_SE_SAWTOOTHDOWN},
  2441. {PL_CONCATENATE , ET_PL_CONCATENATE},
  2442. {PL_SUPERIMPOSE , ET_PL_SUPERIMPOSE},
  2443. {RE_ROMID1 , ET_RE_ROMID1 },
  2444. {RE_ROMID2 , ET_RE_ROMID2 },
  2445. {RE_ROMID3 , ET_RE_ROMID3 },
  2446. {RE_ROMID4 , ET_RE_ROMID4 },
  2447. {RE_ROMID5 , ET_RE_ROMID5 },
  2448. {RE_ROMID6 , ET_RE_ROMID6 },
  2449. {RE_ROMID7 , ET_RE_ROMID7 },
  2450. {RE_ROMID8 , ET_RE_ROMID8 },
  2451. {RE_ROMID9 , ET_RE_ROMID9 },
  2452. {RE_ROMID10 , ET_RE_ROMID10 },
  2453. {RE_ROMID11 , ET_RE_ROMID11 },
  2454. {RE_ROMID12 , ET_RE_ROMID12 },
  2455. {RE_ROMID13 , ET_RE_ROMID13 },
  2456. {RE_ROMID14 , ET_RE_ROMID14 },
  2457. {RE_ROMID15 , ET_RE_ROMID15 },
  2458. {RE_ROMID16 , ET_RE_ROMID16 },
  2459. {RE_ROMID17 , ET_RE_ROMID17 },
  2460. {RE_ROMID18 , ET_RE_ROMID18 },
  2461. {RE_ROMID19 , ET_RE_ROMID19 },
  2462. {RE_ROMID20 , ET_RE_ROMID20 },
  2463. {RE_ROMID21 , ET_RE_ROMID21 },
  2464. {RE_ROMID22 , ET_RE_ROMID22 },
  2465. {RE_ROMID23 , ET_RE_ROMID23 },
  2466. {RE_ROMID24 , ET_RE_ROMID24 },
  2467. {RE_ROMID25 , ET_RE_ROMID25 },
  2468. {RE_ROMID26 , ET_RE_ROMID26 },
  2469. {RE_ROMID27 , ET_RE_ROMID27 },
  2470. {RE_ROMID28 , ET_RE_ROMID28 },
  2471. {RE_ROMID29 , ET_RE_ROMID29 },
  2472. {RE_ROMID30 , ET_RE_ROMID30 },
  2473. {RE_ROMID31 , ET_RE_ROMID31 },
  2474. {RE_ROMID32 , ET_RE_ROMID32 }};
  2475. int nNumEffectTypes = sizeof(EffectTypes)/(sizeof(EFFECT_TYPE));
  2476. for (int i=0; i<nNumEffectTypes; i++)
  2477. {
  2478. if (ulSubType == EffectTypes[i].ulHostSubType)
  2479. {
  2480. m_SubType = EffectTypes[i].bDeviceSubType;
  2481. return;
  2482. }
  2483. }
  2484. m_SubType = NULL;
  2485. }
  2486. // ----------------------------------------------------------------------------
  2487. // Function: CMidiEffect::ComputeChecksum
  2488. // Purpose: Computes current checksum in the m_pBuffer
  2489. // Parameters: none
  2490. // Returns: Midi packet block is checksummed
  2491. // Algorithm:
  2492. // ----------------------------------------------------------------------------
  2493. BYTE CMidiEffect::ComputeChecksum(PBYTE pBuffer, int nBufferSize)
  2494. {
  2495. assert(pBuffer);
  2496. int nStart = sizeof(SYS_EX_HDR);
  2497. PBYTE pBytePacket = pBuffer;
  2498. pBytePacket += nStart;
  2499. BYTE nSum = 0;
  2500. // Checksum only the bytes in the "Body" and s/b 7 bit checksum.
  2501. for (int i=nStart;i < (nBufferSize-2);i++)
  2502. {
  2503. nSum += *pBytePacket;
  2504. pBytePacket++;
  2505. }
  2506. return ((-nSum) & 0x7f);
  2507. }
  2508. // ----------------------------------------------------------------------------
  2509. // Function: CMidiEffect::SendPacket
  2510. // Purpose: Sends the SYS_EX Packet
  2511. // Parameters: PDNHANDLE pDnloadID - Pointer to DnloadID
  2512. // int nPacketSize - Size of SysEx packet
  2513. //
  2514. // Returns: *pDnloadID is filled.
  2515. // else Error code
  2516. // Algorithm:
  2517. // ----------------------------------------------------------------------------
  2518. HRESULT CMidiEffect::SendPacket(PDNHANDLE pDnloadID, int nPacketSize)
  2519. {
  2520. //
  2521. // --- THIS IS A CRITICAL SECTION
  2522. //
  2523. CriticalLock cl;
  2524. HRESULT hRet = SUCCESS;
  2525. if (NULL == g_pJoltMidi) return (SFERR_DRIVER_ERROR);
  2526. // Prepare the buffer for SysEx output
  2527. hRet = g_pJoltMidi->MidiAssignBuffer((LPSTR) m_pBuffer,
  2528. (DWORD) nPacketSize, TRUE);
  2529. assert(SUCCESS == hRet);
  2530. if (SUCCESS != hRet)
  2531. {
  2532. return (hRet);
  2533. }
  2534. ACKNACK AckNack = {sizeof(ACKNACK)};
  2535. for(int i=0; i<MAX_RETRY_COUNT; i++)
  2536. {
  2537. g_pJoltMidi->BumpLongMsgCounter();
  2538. // Send the message and Wait for the ACK + Download ID
  2539. hRet = g_pJoltMidi->MidiSendLongMsg();
  2540. assert(SUCCESS == hRet);
  2541. if (SUCCESS != hRet)
  2542. {
  2543. #ifdef _DEBUG
  2544. OutputDebugString("SendPacket Error: MidiSendLongMsg()\n");
  2545. #endif
  2546. // Release the Midi buffers and Return
  2547. g_pJoltMidi->MidiAssignBuffer((LPSTR) m_pBuffer, 0, FALSE);
  2548. return (hRet);
  2549. }
  2550. // Wait for ACK. Note: WinMM has callback Event notification
  2551. // while Backdoor and serial does not.
  2552. if (COMM_WINMM == g_pJoltMidi->COMMInterfaceOf())
  2553. {
  2554. hRet = g_pJoltMidi->GetAckNackData(10, &AckNack, REGBITS_DOWNLOADEFFECT);
  2555. }
  2556. else // Serial or Backdoor
  2557. {
  2558. if ((COMM_SERIAL_FILE == g_pJoltMidi->COMMInterfaceOf()) || (COMM_SERIAL_BACKDOOR == g_pJoltMidi->COMMInterfaceOf()))
  2559. {
  2560. hRet = g_pJoltMidi->GetAckNackData(LONG_MSG_TIMEOUT, &AckNack, REGBITS_DOWNLOADEFFECT);
  2561. }
  2562. else // Backdoor, hopefully to keep Jeff(Mr. Performance '97) happy
  2563. {
  2564. hRet = g_pJoltMidi->GetAckNackData(SHORT_MSG_TIMEOUT, &AckNack, REGBITS_DOWNLOADEFFECT);
  2565. }
  2566. }
  2567. // :
  2568. #ifdef _DEBUG
  2569. if (SUCCESS!=hRet)
  2570. OutputDebugString("Error getting ACKNACK data\n");
  2571. if (ACK != AckNack.dwAckNack)
  2572. g_pJoltMidi->LogError(SFERR_DEVICE_NACK, AckNack.dwErrorCode);
  2573. #endif
  2574. // NOTE: Special check for Device-Full because in certain circumstances
  2575. // (e.g. create multiple ROM effects after STOP_ALL command), retries of
  2576. // creation will succeed even though device is full
  2577. if (ACK == AckNack.dwAckNack || (NACK == AckNack.dwAckNack && AckNack.dwErrorCode == DEV_ERR_TYPE_FULL))
  2578. break;
  2579. // ******
  2580. }
  2581. // Release the Midi buffers
  2582. g_pJoltMidi->MidiAssignBuffer((LPSTR) m_pBuffer, 0, FALSE);
  2583. if (SUCCEEDED(hRet) && (ACK == AckNack.dwAckNack))
  2584. {
  2585. // Store in Device ID List Array
  2586. // First we need to generate a new Effect ID if necessary
  2587. if (NEW_EFFECT_ID == m_bEffectID)
  2588. {
  2589. DNHANDLE DnloadID;
  2590. if (g_pJoltMidi->NewEffectID(&DnloadID)) // Successful ID created
  2591. {
  2592. m_bEffectID = (BYTE) DnloadID;
  2593. *pDnloadID = DnloadID;
  2594. g_pJoltMidi->SetEffectByID((BYTE) *pDnloadID, this);
  2595. }
  2596. }
  2597. }
  2598. else // Failure of some sort
  2599. {
  2600. if(NACK == AckNack.dwAckNack)
  2601. {
  2602. g_pJoltMidi->BumpNACKCounter();
  2603. switch (AckNack.dwErrorCode)
  2604. {
  2605. case DEV_ERR_TYPE_FULL:
  2606. case DEV_ERR_PROCESS_LIST_FULL:
  2607. case DEV_ERR_PLAYLIST_FULL:
  2608. hRet = g_pJoltMidi->LogError(SFERR_FFDEVICE_MEMORY,
  2609. AckNack.dwErrorCode);
  2610. break;
  2611. default:
  2612. case DEV_ERR_INVALID_PARAM:
  2613. case DEV_ERR_CHECKSUM:
  2614. case DEV_ERR_UNKNOWN_CMD:
  2615. case DEV_ERR_INVALID_ID:
  2616. hRet = g_pJoltMidi->LogError(SFERR_DEVICE_NACK,
  2617. AckNack.dwErrorCode);
  2618. break;
  2619. }
  2620. }
  2621. }
  2622. // --- END OF CRITICAL SECTION
  2623. //
  2624. return (hRet);
  2625. }
  2626. // ----------------------------------------------------------------------------
  2627. // Function: CMidiEffect::DestroyEffect
  2628. // Purpose: Sends the SYS_EX Packet
  2629. // Parameters: PDNHANDLE pDnloadID - Pointer to DnloadID
  2630. // int nPacketSize - Size of SysEx packet
  2631. //
  2632. // Returns: *pDnloadID is filled.
  2633. // else Error code
  2634. // Algorithm:
  2635. // ----------------------------------------------------------------------------
  2636. HRESULT CMidiEffect::DestroyEffect()
  2637. {
  2638. HRESULT hRet;
  2639. if (NULL == g_pJoltMidi) return (SFERR_DRIVER_ERROR);
  2640. hRet = g_pJoltMidi->MidiSendShortMsg(EFFECT_CMD,DESTROY_EFFECT,EffectIDOf());
  2641. if(!FAILED(hRet))
  2642. g_pJoltMidi->SetEffectByID(EffectIDOf(), NULL);
  2643. Sleep(g_pJoltMidi->DelayParamsPtrOf()->dwDestroyEffectDelay);
  2644. return hRet;
  2645. }
  2646. // ****************************************************************************
  2647. // *** --- Member functions for derived class CMidiBehavioral
  2648. //
  2649. // ****************************************************************************
  2650. //
  2651. // ----------------------------------------------------------------------------
  2652. // Function: CMidiBehavioral::CMidiBehavioral
  2653. // Purpose: Constructor(s)/Destructor for CMidiBehavioral Object
  2654. // Parameters:
  2655. // Returns:
  2656. // Algorithm:
  2657. // ----------------------------------------------------------------------------
  2658. CMidiBehavioral::CMidiBehavioral(PEFFECT pEffect, PENVELOPE pEnvelope,
  2659. PBE_XXX pBE_XXX):CMidiEffect(pEffect, NULL)
  2660. {
  2661. SetSubType(pEffect->m_SubType);
  2662. SetXConstant(pBE_XXX->m_XConstant);
  2663. SetYConstant(pBE_XXX->m_YConstant);
  2664. SetParam3(pBE_XXX->m_Param3);
  2665. SetParam4(pBE_XXX->m_Param4);
  2666. m_MidiBufferSize = sizeof(BEHAVIORAL_SYS_EX);
  2667. }
  2668. // --- Destructor
  2669. CMidiBehavioral::~CMidiBehavioral()
  2670. {
  2671. memset(this, 0, sizeof(CMidiBehavioral));
  2672. }
  2673. // ----------------------------------------------------------------------------
  2674. // Function: CMidiBehavioral::SetEffect
  2675. // Purpose: Sets the common MIDI_EFFECT parameters
  2676. // Parameters: PEFFECT pEffect
  2677. // Returns: none
  2678. // Algorithm:
  2679. // ----------------------------------------------------------------------------
  2680. void CMidiBehavioral::SetEffectParams(PEFFECT pEffect, PBE_XXX pBE_XXX)
  2681. {
  2682. // Set the MIDI_EFFECT parameters
  2683. SetDuration(pEffect->m_Duration);
  2684. SetButtonPlaymask(pEffect->m_ButtonPlayMask);
  2685. SetAxisMask(X_AXIS|Y_AXIS);
  2686. SetDirectionAngle(pEffect->m_DirectionAngle2D);
  2687. SetGain((BYTE) (pEffect->m_Gain));
  2688. SetForceOutRate(pEffect->m_ForceOutputRate);
  2689. Effect.bPercentL = (BYTE) (DEFAULT_PERCENT & 0x7f);
  2690. Effect.bPercentH = (BYTE) ((DEFAULT_PERCENT >> 7) & 0x7f);
  2691. // set the type specific parameters for BE_XXX
  2692. SetXConstant(pBE_XXX->m_XConstant);
  2693. SetYConstant(pBE_XXX->m_YConstant);
  2694. SetParam3(pBE_XXX->m_Param3);
  2695. SetParam4(pBE_XXX->m_Param4);
  2696. }
  2697. // ----------------------------------------------------------------------------
  2698. // Function: CMidiBehavioral::GenerateSysExPacket
  2699. // Purpose: Builds the SysEx packet into the pBuf
  2700. // Parameters: none
  2701. // Returns: PBYTE - pointer to a buffer filled with SysEx Packet
  2702. // Algorithm:
  2703. // ----------------------------------------------------------------------------
  2704. PBYTE CMidiBehavioral::GenerateSysExPacket(void)
  2705. {
  2706. if (NULL == g_pJoltMidi) return ((PBYTE) NULL);
  2707. PBYTE pSysExBuffer = g_pJoltMidi->PrimaryBufferPtrOf();
  2708. assert(pSysExBuffer);
  2709. // Copy SysEx Header + m_OpCode + m_SubType
  2710. memcpy(pSysExBuffer, &m_bSysExCmd, sizeof(SYS_EX_HDR)+2 );
  2711. PBEHAVIORAL_SYS_EX pBuf = (PBEHAVIORAL_SYS_EX) pSysExBuffer;
  2712. SetTotalDuration(); // Compute total with Loop count parameter
  2713. pBuf->bDurationL = (BYTE) (Effect.bDurationL & 0x7f);
  2714. pBuf->bDurationH = (BYTE) (Effect.bDurationH & 0x7f);
  2715. pBuf->bButtonPlayL = (BYTE) (Effect.bButtonPlayL & 0x7f);
  2716. pBuf->bButtonPlayH = (BYTE) (Effect.bButtonPlayH & 0x7f);
  2717. // Behavioral params
  2718. LONG XConstant = (LONG) (XConstantOf() * MAX_SCALE);
  2719. LONG YConstant = (LONG) (YConstantOf() * MAX_SCALE);
  2720. pBuf->bXConstantL = (BYTE) XConstant & 0x7f;
  2721. pBuf->bXConstantH = (BYTE) (XConstant >> 7 ) & 0x01;
  2722. pBuf->bYConstantL = (BYTE) YConstant & 0x7f;
  2723. pBuf->bYConstantH = (BYTE) (YConstant >> 7 ) & 0x01;
  2724. LONG Param3 = (LONG) (Param3Of() * MAX_SCALE);
  2725. LONG Param4 = (LONG) (Param4Of() * MAX_SCALE);
  2726. pBuf->bParam3L = (BYTE) Param3 & 0x7f;
  2727. pBuf->bParam3H = (BYTE) (Param3 >> 7 ) & 0x01;
  2728. pBuf->bParam4L = (BYTE) Param4 & 0x7f;
  2729. pBuf->bParam4H = (BYTE) (Param4 >> 7 ) & 0x01;
  2730. pBuf->bEffectID = m_bEffectID;
  2731. pBuf->bChecksum = ComputeChecksum((PBYTE) pSysExBuffer,
  2732. sizeof(BEHAVIORAL_SYS_EX));
  2733. pBuf->bEOX = MIDI_EOX;
  2734. return ((PBYTE) pSysExBuffer);
  2735. }
  2736. // ****************************************************************************
  2737. // *** --- Member functions for derived class CMidiFriction
  2738. //
  2739. // ****************************************************************************
  2740. //
  2741. // ----------------------------------------------------------------------------
  2742. // Function: CMidiFriction::CMidiFriction
  2743. // Purpose: Constructor(s)/Destructor for CMidiFriction Object
  2744. // Parameters:
  2745. // Returns:
  2746. // Algorithm:
  2747. // ----------------------------------------------------------------------------
  2748. CMidiFriction::CMidiFriction(PEFFECT pEffect, PENVELOPE pEnvelope,
  2749. PBE_XXX pBE_XXX):CMidiBehavioral(pEffect, NULL, pBE_XXX)
  2750. {
  2751. m_MidiBufferSize = sizeof(FRICTION_SYS_EX);
  2752. }
  2753. // --- Destructor
  2754. CMidiFriction::~CMidiFriction()
  2755. {
  2756. memset(this, 0, sizeof(CMidiFriction));
  2757. }
  2758. // ----------------------------------------------------------------------------
  2759. // Function: CMidiFriction::GenerateSysExPacket
  2760. // Purpose: Builds the SysEx packet into the pBuf
  2761. // Parameters: none
  2762. // Returns: PBYTE - pointer to a buffer filled with SysEx Packet
  2763. // Algorithm:
  2764. // ----------------------------------------------------------------------------
  2765. PBYTE CMidiFriction::GenerateSysExPacket(void)
  2766. {
  2767. if (NULL == g_pJoltMidi) return ((PBYTE) NULL);
  2768. PBYTE pSysExBuffer = g_pJoltMidi->PrimaryBufferPtrOf();
  2769. assert(pSysExBuffer);
  2770. // Copy SysEx Header + m_OpCode + m_SubType
  2771. memcpy(pSysExBuffer, &m_bSysExCmd, sizeof(SYS_EX_HDR)+2 );
  2772. PFRICTION_SYS_EX pBuf = (PFRICTION_SYS_EX) pSysExBuffer;
  2773. SetTotalDuration(); // Compute total with Loop count parameter
  2774. pBuf->bDurationL = (BYTE) (Effect.bDurationL & 0x7f);
  2775. pBuf->bDurationH = (BYTE) (Effect.bDurationH & 0x7f);
  2776. pBuf->bButtonPlayL = (BYTE) (Effect.bButtonPlayL & 0x7f);
  2777. pBuf->bButtonPlayH = (BYTE) (Effect.bButtonPlayH & 0x7f);
  2778. // BE_FRICTION params
  2779. LONG XConstant = (LONG) (XConstantOf() * MAX_SCALE);
  2780. LONG YConstant = (LONG) (YConstantOf() * MAX_SCALE);
  2781. pBuf->bXFConstantL = (BYTE) XConstant & 0x7f;
  2782. pBuf->bXFConstantH = (BYTE) (XConstant >> 7 ) & 0x01;
  2783. pBuf->bYFConstantL = (BYTE) YConstant & 0x7f;
  2784. pBuf->bYFConstantH = (BYTE) (YConstant >> 7 ) & 0x01;
  2785. pBuf->bEffectID = m_bEffectID;
  2786. pBuf->bChecksum = ComputeChecksum((PBYTE) pSysExBuffer,
  2787. sizeof(FRICTION_SYS_EX));
  2788. pBuf->bEOX = MIDI_EOX;
  2789. return ((PBYTE) pSysExBuffer);
  2790. }
  2791. // ****************************************************************************
  2792. // *** --- Member functions for derived class CMidiWall
  2793. //
  2794. // ****************************************************************************
  2795. //
  2796. // ----------------------------------------------------------------------------
  2797. // Function: CMidiWall::CMidiWall
  2798. // Purpose: Constructor(s)/Destructor for CMidiWall Object
  2799. // Parameters:
  2800. // Returns:
  2801. // Algorithm:
  2802. // ----------------------------------------------------------------------------
  2803. CMidiWall::CMidiWall(PEFFECT pEffect, PENVELOPE pEnvelope,
  2804. PBE_XXX pBE_XXX):CMidiBehavioral(pEffect, NULL, pBE_XXX)
  2805. {
  2806. m_MidiBufferSize = sizeof(WALL_SYS_EX);
  2807. }
  2808. // --- Destructor
  2809. CMidiWall::~CMidiWall()
  2810. {
  2811. memset(this, 0, sizeof(CMidiWall));
  2812. }
  2813. // ----------------------------------------------------------------------------
  2814. // Function: CMidiWall::GenerateSysExPacket
  2815. // Purpose: Builds the SysEx packet into the pBuf
  2816. // Parameters: none
  2817. // Returns: PBYTE - pointer to a buffer filled with SysEx Packet
  2818. // Algorithm:
  2819. // ----------------------------------------------------------------------------
  2820. PBYTE CMidiWall::GenerateSysExPacket(void)
  2821. {
  2822. if (NULL == g_pJoltMidi) return ((PBYTE) NULL);
  2823. PBYTE pSysExBuffer = g_pJoltMidi->PrimaryBufferPtrOf();
  2824. assert(pSysExBuffer);
  2825. // Copy SysEx Header + m_OpCode + m_SubType
  2826. memcpy(pSysExBuffer, &m_bSysExCmd, sizeof(SYS_EX_HDR)+2 );
  2827. PWALL_SYS_EX pBuf = (PWALL_SYS_EX) pSysExBuffer;
  2828. SetTotalDuration(); // Compute total with Loop count parameter
  2829. pBuf->bDurationL = (BYTE) (Effect.bDurationL & 0x7f);
  2830. pBuf->bDurationH = (BYTE) (Effect.bDurationH & 0x7f);
  2831. pBuf->bButtonPlayL = (BYTE) (Effect.bButtonPlayL & 0x7f);
  2832. pBuf->bButtonPlayH = (BYTE) (Effect.bButtonPlayH & 0x7f);
  2833. // BE_WALL params
  2834. LONG WallType = (LONG) (XConstantOf());
  2835. LONG WallConstant = (LONG) (YConstantOf() * MAX_SCALE);
  2836. LONG WallAngle = (LONG) Param3Of();
  2837. LONG WallDistance = (LONG) (Param4Of() * MAX_SCALE);
  2838. pBuf->bWallType = (BYTE) (WallType & 0x01);
  2839. pBuf->bWallConstantL = (BYTE) (WallConstant & 0x7f);
  2840. pBuf->bWallConstantH = (BYTE) ((WallConstant >> 7 ) & 0x01); //+/-100
  2841. pBuf->bWallAngleL = (BYTE) (WallAngle & 0x7f); // 0 to 359
  2842. pBuf->bWallAngleH = (BYTE) ((WallAngle >> 7 ) & 0x03);
  2843. pBuf->bWallDistance = (BYTE) (WallDistance & 0x7f);
  2844. pBuf->bEffectID = m_bEffectID;
  2845. pBuf->bChecksum = ComputeChecksum((PBYTE) pSysExBuffer,
  2846. sizeof(WALL_SYS_EX));
  2847. pBuf->bEOX = MIDI_EOX;
  2848. return ((PBYTE) pSysExBuffer);
  2849. }
  2850. // ****************************************************************************
  2851. // *** --- Member functions for derived class CMidiRTCSpring
  2852. //
  2853. // ****************************************************************************
  2854. //
  2855. // ----------------------------------------------------------------------------
  2856. // Function: CMidiRTCSpring::CMidiRTCSpring
  2857. // Purpose: Constructor(s)/Destructor for CMidiRTCSpring Object
  2858. // Parameters:
  2859. // Returns:
  2860. // Algorithm:
  2861. // ----------------------------------------------------------------------------
  2862. CMidiRTCSpring::CMidiRTCSpring(PRTCSPRING_PARAM pRTCSpring):CMidiEffect(NULL)
  2863. {
  2864. memcpy(&m_RTCSPRINGParam, pRTCSpring, sizeof(RTCSPRING_PARAM));
  2865. }
  2866. // --- Destructor
  2867. CMidiRTCSpring::~CMidiRTCSpring()
  2868. {
  2869. memset(this, 0, sizeof(CMidiRTCSpring));
  2870. }
  2871. // ----------------------------------------------------------------------------
  2872. // Function: CMidiRTCSpring::SetEffectParams
  2873. // Purpose: Sets parameters
  2874. // Parameters:
  2875. // Returns:
  2876. // Algorithm:
  2877. // ----------------------------------------------------------------------------
  2878. void CMidiRTCSpring::SetEffectParams(PRTCSPRING_PARAM pRTCSpring)
  2879. {
  2880. memcpy(&m_RTCSPRINGParam, pRTCSpring, sizeof(RTCSPRING_PARAM));
  2881. }
  2882. // ----------------------------------------------------------------------------
  2883. // Function: CMidiRTCSpring::GenerateSysExPacket
  2884. // Purpose: virtual
  2885. // Parameters: none
  2886. // Returns:
  2887. // Algorithm:
  2888. // ----------------------------------------------------------------------------
  2889. PBYTE CMidiRTCSpring::GenerateSysExPacket(void)
  2890. {
  2891. return (NULL);
  2892. }
  2893. // ****************************************************************************
  2894. // *** --- Member functions for derived class CMidiDelay
  2895. //
  2896. // ****************************************************************************
  2897. //
  2898. // ----------------------------------------------------------------------------
  2899. // Function: CMidiDelay::CMidiDelay
  2900. // Purpose: Constructor(s)/Destructor for CMidiDelay Object
  2901. // Parameters:
  2902. // Returns:
  2903. // Algorithm:
  2904. // ----------------------------------------------------------------------------
  2905. CMidiDelay::CMidiDelay(PEFFECT pEffect) : CMidiEffect(pEffect, NULL)
  2906. {
  2907. m_SubType = ET_BE_DELAY; // BE Effect Type: BE_DELAY
  2908. m_OpCode = DNLOAD_DATA | X_AXIS|Y_AXIS | PLAY_SUPERIMPOSE;
  2909. m_MidiBufferSize = sizeof(NOP_SYS_EX);
  2910. }
  2911. // --- Destructor
  2912. CMidiDelay::~CMidiDelay()
  2913. {
  2914. memset(this, 0, sizeof(CMidiDelay));
  2915. }
  2916. // ----------------------------------------------------------------------------
  2917. // Function: CMidiDelay::GenerateSysExPacket
  2918. // Purpose: Builds the SysEx packet into the pBuf
  2919. // Parameters: none
  2920. // Returns: PBYTE - pointer to a buffer filled with SysEx Packet
  2921. // Algorithm:
  2922. // ----------------------------------------------------------------------------
  2923. PBYTE CMidiDelay::GenerateSysExPacket(void)
  2924. {
  2925. if (NULL == g_pJoltMidi) return ((PBYTE) NULL);
  2926. PBYTE pSysExBuffer = g_pJoltMidi->PrimaryBufferPtrOf();
  2927. assert(pSysExBuffer);
  2928. // Copy SysEx Header + m_OpCode + m_SubType
  2929. memcpy(pSysExBuffer, &m_bSysExCmd, sizeof(SYS_EX_HDR)+2 );
  2930. PNOP_SYS_EX pBuf = (PNOP_SYS_EX) pSysExBuffer;
  2931. pBuf->bEffectID = m_bEffectID;
  2932. SetTotalDuration(); // Compute total with Loop count parameter
  2933. pBuf->bDurationL = (BYTE) (Effect.bDurationL & 0x7f);
  2934. pBuf->bDurationH = (BYTE) (Effect.bDurationH & 0x7f);
  2935. pBuf->bChecksum = ComputeChecksum((PBYTE) pSysExBuffer,
  2936. sizeof(NOP_SYS_EX));
  2937. pBuf->bEOX = MIDI_EOX;
  2938. return ((PBYTE) pSysExBuffer);
  2939. }
  2940. // ****************************************************************************
  2941. // *** --- Member functions for derived class CMidiSynthesized
  2942. //
  2943. // ****************************************************************************
  2944. //
  2945. // ----------------------------------------------------------------------------
  2946. // Function: CMidiSynthesized::CMidiSynthesized
  2947. // Purpose: Constructor(s)/Destructor for CMidiSynthesized Object
  2948. // Parameters:
  2949. // Returns:
  2950. // Algorithm:
  2951. // ----------------------------------------------------------------------------
  2952. CMidiSynthesized::CMidiSynthesized(PEFFECT pEffect, PENVELOPE pEnvelope,
  2953. PSE_PARAM pParam ) : CMidiEffect(pEffect, pEnvelope)
  2954. {
  2955. SetSubType(pEffect->m_SubType); // SE Effect Type
  2956. // Effect.bForceOutRateL= (BYTE) pParam->m_SampleRate & 0x7f; // 1 to 500 Hz
  2957. // Effect.bForceOutRateH= (BYTE) ((pParam->m_SampleRate >> 7) & 0x3);
  2958. Effect.bPercentL = (BYTE) (DEFAULT_PERCENT & 0x7f);
  2959. Effect.bPercentH = (BYTE) ((DEFAULT_PERCENT >> 7) & 0x7f);
  2960. m_Freq = pParam->m_Freq; // Frequency
  2961. m_MaxAmp = pParam->m_MaxAmp; // Maximum Amplitude
  2962. // Special case a SE_CONSTANT_FORCE
  2963. if (SE_CONSTANT_FORCE == pEffect->m_SubType)
  2964. m_MinAmp = 0;
  2965. else
  2966. m_MinAmp = pParam->m_MinAmp; // Minimum Amplitude
  2967. m_MidiBufferSize = sizeof(SE_WAVEFORM_SYS_EX);
  2968. }
  2969. // --- Destructor
  2970. CMidiSynthesized::~CMidiSynthesized()
  2971. {
  2972. memset(this, 0, sizeof(CMidiSynthesized));
  2973. }
  2974. // ----------------------------------------------------------------------------
  2975. // Function: CMidiSynthesized::SetEffect
  2976. // Purpose: Sets the common MIDI_EFFECT parameters
  2977. // Parameters: PEFFECT pEffect
  2978. // Returns: none
  2979. // Algorithm:
  2980. // ----------------------------------------------------------------------------
  2981. void CMidiSynthesized::SetEffectParams(PEFFECT pEffect, PSE_PARAM pParam,
  2982. ULONG ulAction)
  2983. {
  2984. // Set the MIDI_EFFECT parameters
  2985. SetDuration(pEffect->m_Duration);
  2986. SetButtonPlaymask(pEffect->m_ButtonPlayMask);
  2987. SetAxisMask(X_AXIS|Y_AXIS);
  2988. SetDirectionAngle(pEffect->m_DirectionAngle2D);
  2989. SetGain((BYTE) (pEffect->m_Gain));
  2990. SetForceOutRate(pEffect->m_ForceOutputRate);
  2991. //Set the loop count from HIWORD of ulAction
  2992. m_LoopCount = (ulAction >> 16) & 0xffff;
  2993. if (0 == m_LoopCount) m_LoopCount++;
  2994. Effect.bPercentL = (BYTE) (DEFAULT_PERCENT & 0x7f);
  2995. Effect.bPercentH = (BYTE) ((DEFAULT_PERCENT >> 7) & 0x7f);
  2996. // set the type specific parameters for SE_xxx
  2997. m_Freq = pParam->m_Freq;
  2998. m_MaxAmp = pParam->m_MaxAmp;
  2999. m_MinAmp = pParam->m_MinAmp;
  3000. }
  3001. // ----------------------------------------------------------------------------
  3002. // Function: CMidiSynthesized::GenerateSysExPacket
  3003. // Purpose: Builds the SysEx packet into the pBuf
  3004. // Parameters: none
  3005. // Returns: PBYTE - pointer to a buffer filled with SysEx Packet
  3006. // Algorithm:
  3007. // ----------------------------------------------------------------------------
  3008. PBYTE CMidiSynthesized::GenerateSysExPacket(void)
  3009. {
  3010. if (NULL == g_pJoltMidi) return ((PBYTE) NULL);
  3011. PBYTE pSysExBuffer = g_pJoltMidi->PrimaryBufferPtrOf();
  3012. assert(pSysExBuffer);
  3013. // Compute total with Loop count parameter, Note: Envelope parameters are
  3014. // adjusted according to the Loop Count parameter, if affected.
  3015. SetTotalDuration();
  3016. ComputeEnvelope();
  3017. // Copy SysEx Header + m_OpCode + m_SubType + m_bEffectID + MIDI_EFFECT
  3018. // + MIDI_ENVELOPE
  3019. memcpy(pSysExBuffer,&m_bSysExCmd, (sizeof(SYS_EX_HDR)+3+sizeof(MIDI_EFFECT)+
  3020. sizeof(MIDI_ENVELOPE)) );
  3021. PSE_WAVEFORM_SYS_EX pBuf = (PSE_WAVEFORM_SYS_EX) pSysExBuffer;
  3022. // Scale the gain, and Envelope amplitudes
  3023. pBuf->Effect.bGain = (BYTE) (pBuf->Effect.bGain * MAX_SCALE) & 0x7f;
  3024. pBuf->Envelope.bAttackLevel = (BYTE) (pBuf->Envelope.bAttackLevel * MAX_SCALE) & 0x7f;
  3025. pBuf->Envelope.bSustainLevel = (BYTE) (pBuf->Envelope.bSustainLevel * MAX_SCALE) & 0x7f;
  3026. pBuf->Envelope.bDecayLevel = (BYTE) (pBuf->Envelope.bDecayLevel * MAX_SCALE) & 0x7f;
  3027. // Copy the SE specific parameters
  3028. LONG MaxAmp = (LONG) (m_MaxAmp * MAX_SCALE);
  3029. LONG MinAmp = (LONG) (m_MinAmp * MAX_SCALE);
  3030. pBuf->bFreqL = (BYTE) (m_Freq & 0x7f);
  3031. pBuf->bFreqH = (BYTE) ((m_Freq >> 7 ) & 0x03); // 1 to 500
  3032. pBuf->bMaxAmpL = (BYTE) (MaxAmp & 0x7f);
  3033. pBuf->bMaxAmpH = (BYTE) ((MaxAmp >> 7 ) &0x01); // +127 to -128
  3034. pBuf->bMinAmpL = (BYTE) (MinAmp & 0x7f);
  3035. pBuf->bMinAmpH = (BYTE) ((MinAmp >> 7 ) & 0x01);
  3036. pBuf->bChecksum = ComputeChecksum((PBYTE) pSysExBuffer,
  3037. sizeof(SE_WAVEFORM_SYS_EX));
  3038. pBuf->bEOX = MIDI_EOX;
  3039. return ((PBYTE) pSysExBuffer);
  3040. }
  3041. // ****************************************************************************
  3042. // *** --- Member functions for derived class CUD_Waveform
  3043. //
  3044. // ****************************************************************************
  3045. //
  3046. // ----------------------------------------------------------------------------
  3047. // Function: CUD_Waveform::CUD_Waveform
  3048. // Purpose: Constructor(s)/Destructor for CUD_Waveform Object
  3049. // Parameters:
  3050. // Returns:
  3051. // Algorithm:
  3052. // ----------------------------------------------------------------------------
  3053. CMidiUD_Waveform::CMidiUD_Waveform(PEFFECT pEffect, ULONG ulNumVectors, PLONG pArray) : CMidiEffect(pEffect, NULL),
  3054. m_pRawData(NULL)
  3055. {
  3056. m_OpCode = DNLOAD_DATA | X_AXIS|Y_AXIS;// Sub-command opcode: DNLOAD_DATA
  3057. m_SubType = ET_UD_WAVEFORM; // Effect Type: UD_WAVEFORM
  3058. assert(pArray);
  3059. // Create the buffer to hold the waveform data, compress it,
  3060. // then copy to this object
  3061. // The buffer size is initially set to the number of uncompressed vectors
  3062. // x 2 bytes, for worse-case Absolute data
  3063. // Once the buffer is compressed, the actual size is determined
  3064. // Also, create a temp copy so that the original unscaled data is not
  3065. // affected.
  3066. // Set a fixed maximum size
  3067. DWORD nSize = MAX_MIDI_WAVEFORM_DATA_SIZE + 2;
  3068. m_pArrayData = new BYTE[nSize];
  3069. // m_pRawData = new BYTE [nSize*2];
  3070. assert(m_pArrayData);
  3071. ULONG NewForceRate;
  3072. m_MidiBufferSize = SetTypeParams(ulNumVectors, pArray, &NewForceRate);
  3073. // Copy structures to object
  3074. memcpy(&m_Effect.m_Bytes, pEffect, sizeof(EFFECT));
  3075. SetForceOutRate(NewForceRate);
  3076. m_Effect.m_Gain = m_Effect.m_Gain & 0x7f;
  3077. m_Effect.m_Duration = (ULONG) ((float) (m_Effect.m_Duration / TICKRATE));
  3078. m_Duration = m_Effect.m_Duration;
  3079. }
  3080. // --- Destructor
  3081. CMidiUD_Waveform::~CMidiUD_Waveform()
  3082. {
  3083. if (m_pArrayData) delete [] m_pArrayData;
  3084. memset(this, 0, sizeof(CMidiUD_Waveform));
  3085. }
  3086. // ----------------------------------------------------------------------------
  3087. // Function: CMidiUD_Waveform::SetEffectParams
  3088. // Purpose: Sets the Effect specific parameters
  3089. // Parameters: PEFFECT pEffect
  3090. // Returns:
  3091. // Algorithm:
  3092. // ----------------------------------------------------------------------------
  3093. void CMidiUD_Waveform::SetEffectParams(PEFFECT pEffect)
  3094. {
  3095. // Set the MIDI_EFFECT parameters
  3096. SetButtonPlaymask(pEffect->m_ButtonPlayMask);
  3097. SetAxisMask(X_AXIS|Y_AXIS);
  3098. SetDirectionAngle(pEffect->m_DirectionAngle2D);
  3099. SetGain((BYTE) (pEffect->m_Gain));
  3100. SetForceOutRate(pEffect->m_ForceOutputRate);
  3101. }
  3102. // ----------------------------------------------------------------------------
  3103. // Function: CMidiUD_Waveform::SetTypeParams
  3104. // Purpose: Sets the type specific parameters
  3105. // Parameters: int nSize - size of the array
  3106. // PLONG pArray - Pointer to an ARRAY of force values
  3107. //
  3108. // Returns: MidiBuffer size for the packet
  3109. // Algorithm:
  3110. // ----------------------------------------------------------------------------
  3111. int CMidiUD_Waveform::SetTypeParams(int nSize, PLONG pArray, ULONG *pNewRate)
  3112. {
  3113. // Compress the buffer data then copy to this object
  3114. // The buffer size is initially set to the number of uncompressed vectors
  3115. // x 2 bytes, for worse-case Absolute data
  3116. // Once the buffer is compressed, the actual size is determined
  3117. // Also, create a temp copy so that the original unscaled data is not
  3118. // affected.
  3119. m_NumberOfVectors = 0;
  3120. m_pRawData = new BYTE [nSize*2];
  3121. if (m_pRawData != NULL)
  3122. {
  3123. // Convert to -128 to +127
  3124. for (int i=0; i<nSize; i++)
  3125. {
  3126. m_pRawData[i] = (BYTE) ((LONG) (pArray[i] * MAX_SCALE));
  3127. }
  3128. m_NumberOfVectors = CompressWaveform(&m_pRawData[0], m_pArrayData, nSize, pNewRate);
  3129. assert(m_NumberOfVectors <= (MAX_MIDI_WAVEFORM_DATA_SIZE));
  3130. delete [] m_pRawData;
  3131. m_pRawData = 0;
  3132. }
  3133. if (0 == m_NumberOfVectors) // No room!
  3134. return (0);
  3135. m_MidiBufferSize = (m_NumberOfVectors + sizeof(UD_WAVEFORM_SYS_EX) + 2);
  3136. return (m_MidiBufferSize);
  3137. }
  3138. // ----------------------------------------------------------------------------
  3139. // Function: CMidiUD_Waveform::CompressWaveform
  3140. // Purpose: Builds the SysEx packet into the pBuf
  3141. // Parameters: PBYTE pSrcArray - Source Array pointer
  3142. // PBYTE pDestArray - Dest. Array Pointer
  3143. // int nSize - Size in Bytes of the Source Array
  3144. //
  3145. // Returns: int - Size of the compressed Array (in bytes)
  3146. // Algorithm:
  3147. // To "compress" we need to fit the entire waveform into 98 points (there is a
  3148. // FW bug that limits us to 100 points only, and we need at least two samples
  3149. // for the starting Absolute mode point.
  3150. // 1. Determine how many points over 98.
  3151. // nSrcSize: Total sample size
  3152. // nMaxSamples: Maximum samples to squeeze into = 98
  3153. // nOver: nSrcSize - nMaxSamples
  3154. // nSkipSample: # of points to keep before skipping one
  3155. // = nSrcSize/nOver
  3156. // while ( Sample is less than nSrcSize, bump index)
  3157. // {
  3158. // if ( (index % nSkipSample) == 0) // no remainder
  3159. // {
  3160. // index++ // bump to skip the next sample
  3161. // }
  3162. // Compress the data
  3163. // }
  3164. //
  3165. // ----------------------------------------------------------------------------
  3166. int CMidiUD_Waveform::CompressWaveform(
  3167. IN PBYTE pSrcArray,
  3168. IN OUT PBYTE pDestArray,
  3169. IN int nSrcSize,
  3170. OUT ULONG *pNewForceRate)
  3171. {
  3172. assert(pSrcArray && pDestArray);
  3173. LONG nDifference;
  3174. // 8 bits (-128 to +127) Starting Absolute Data Value
  3175. pDestArray[0] = pSrcArray[0] & 0x3f;
  3176. pDestArray[1] = (pSrcArray[0] >> 6) & 0x03;
  3177. // int nMaxSamples = MAX_MIDI_WAVEFORM_DATA_SIZE;
  3178. int nSkipSample, nSrcIndex, nDestIndex;
  3179. int nAbsolute = 0;
  3180. int nRelative = 0;
  3181. //
  3182. // Start with Finest Resolution, then reduce until # of Samples <= nMaxSamples
  3183. //
  3184. nSkipSample = nSrcSize;
  3185. while (TRUE)
  3186. {
  3187. nSrcIndex = 0; // 1st sample already accounted for
  3188. nDestIndex = 2;
  3189. #ifdef _DEBUG
  3190. g_CriticalSection.Enter();
  3191. wsprintf(g_cMsg,"nSkipSample=%d\n",nSkipSample);
  3192. DebugOut(g_cMsg);
  3193. g_CriticalSection.Leave();
  3194. #endif
  3195. while (nSrcIndex < nSrcSize)
  3196. {
  3197. nSrcIndex++;
  3198. if (0 == (nSrcIndex % nSkipSample))
  3199. {
  3200. nSrcIndex++; // Skip next one
  3201. nDifference = ((char) pSrcArray[nSrcIndex]) - ((char) pSrcArray[nSrcIndex-2]);
  3202. }
  3203. else
  3204. nDifference = ((char) pSrcArray[nSrcIndex]) - ((char) pSrcArray[nSrcIndex-1]);
  3205. // make sure we do not write outside of array bounds
  3206. if(nDestIndex > MAX_MIDI_WAVEFORM_DATA_SIZE) break;
  3207. if (abs(nDifference) < DIFFERENCE_THRESHOLD)
  3208. {
  3209. pDestArray[nDestIndex] = (BYTE)((nDifference & 0x3f) | DIFFERENCE_BIT);
  3210. nDestIndex++;
  3211. nRelative++;
  3212. }
  3213. else // Switch to Absolute Data (8 bits)
  3214. {
  3215. pDestArray[nDestIndex] = pSrcArray[nSrcIndex] & 0x3f;
  3216. pDestArray[nDestIndex+1] = (pSrcArray[nSrcIndex] >> 6) & 0x3;
  3217. nDestIndex = nDestIndex+2;
  3218. nAbsolute++;
  3219. }
  3220. }
  3221. if (nDestIndex <= MAX_MIDI_WAVEFORM_DATA_SIZE) break;
  3222. // Reduce the resolution
  3223. if (nSkipSample < 8)
  3224. nSkipSample--;
  3225. else
  3226. nSkipSample = nSkipSample/2;
  3227. if (1 == nSkipSample) return (0); // Sorry charlie, no room!
  3228. nAbsolute = 0;
  3229. nRelative = 0;
  3230. }
  3231. // Done
  3232. ULONG ulOriginalForceRate = ForceOutRateOf();
  3233. // *pNewForceRate = (ulOriginalForceRate - (ULONG) (ulOriginalForceRate * ((float) nSkipSample / (float) nSrcSize)))/nSkipSample;
  3234. *pNewForceRate = (ULONG) ((1.0f - (1.0f/nSkipSample)) * ulOriginalForceRate);
  3235. #ifdef _DEBUG
  3236. g_CriticalSection.Enter();
  3237. wsprintf(g_cMsg, "CompressWaveform: nSrcSize=%d, nSkipSample=%d, NewForceRate=%d\n",
  3238. nSrcSize, nSkipSample, *pNewForceRate);
  3239. DebugOut(g_cMsg);
  3240. wsprintf(g_cMsg,"\nTotal Absolute Data:%d, Relative Data:%d", nAbsolute, nRelative);
  3241. DebugOut(g_cMsg);
  3242. g_CriticalSection.Leave();
  3243. #endif
  3244. #ifdef _SHOWCOMPRESS
  3245. #pragma message("Compiling with SHOWCOMPRESS")
  3246. g_CriticalSection.Enter();
  3247. DebugOut("CMidiUD_Waveform::CompressWaveform(..) \npSrcArray Dump (Decimal)\n");
  3248. for (int i=0; i<nSrcSize; i++)
  3249. {
  3250. wsprintf(g_cMsg," %0.4ld",((char) pSrcArray[i]));
  3251. DebugOut(g_cMsg);
  3252. }
  3253. DebugOut("\npDestArray Dump (HEX)\n");
  3254. for (i=0; i<nDestIndex; i++)
  3255. {
  3256. wsprintf(g_cMsg," %0.4x",pDestArray[i]);
  3257. DebugOut(g_cMsg);
  3258. }
  3259. g_CriticalSection.Leave();
  3260. #endif
  3261. return (nDestIndex);
  3262. }
  3263. // ----------------------------------------------------------------------------
  3264. // Function: CMidiUD_Waveform::GenerateSysExPacket
  3265. // Purpose: Builds the SysEx packet into the pBuf
  3266. // Parameters: none
  3267. // Returns: PBYTE - pointer to a buffer filled with SysEx Packet
  3268. // Algorithm:
  3269. // ----------------------------------------------------------------------------
  3270. PBYTE CMidiUD_Waveform::GenerateSysExPacket(void)
  3271. {
  3272. if (NULL == g_pJoltMidi) return ((PBYTE) NULL);
  3273. PBYTE pSysExBuffer = g_pJoltMidi->PrimaryBufferPtrOf();
  3274. assert(pSysExBuffer);
  3275. // Copy SysEx Header + m_OpCode + m_SubType
  3276. memcpy(pSysExBuffer, &m_bSysExCmd, sizeof(SYS_EX_HDR)+2 );
  3277. PUD_WAVEFORM_SYS_EX pBuf = (PUD_WAVEFORM_SYS_EX) pSysExBuffer;
  3278. SetTotalDuration(); // Compute total with Loop count parameter
  3279. pBuf->Effect.bDurationL = (BYTE) (m_Duration & 0x7f);
  3280. pBuf->Effect.bDurationH = (BYTE) (m_Duration >> 7) & 0x7f;
  3281. pBuf->Effect.bAngleL = Effect.bAngleL & 0x7f;
  3282. pBuf->Effect.bAngleH = Effect.bAngleH & 0x7f;
  3283. pBuf->Effect.bGain = (BYTE) (Effect.bGain * MAX_SCALE) & 0x7f;
  3284. pBuf->Effect.bButtonPlayL = Effect.bButtonPlayL & 0x7f;
  3285. pBuf->Effect.bButtonPlayH = Effect.bButtonPlayH & 0x7f;
  3286. pBuf->Effect.bForceOutRateL = Effect.bForceOutRateL & 0x7f;
  3287. pBuf->Effect.bForceOutRateH = Effect.bForceOutRateH & 0x7f;
  3288. pBuf->Effect.bPercentL = Effect.bPercentL & 0x7f;
  3289. pBuf->Effect.bPercentH = Effect.bPercentH & 0x7f;
  3290. // Fill in the Array Data
  3291. PBYTE pArray = ((PBYTE) pBuf) + UD_WAVEFORM_START_OFFSET;
  3292. memcpy(pArray, m_pArrayData, m_NumberOfVectors); // Already scaled!
  3293. pBuf->bEffectID = m_bEffectID;
  3294. int nArraySize = (m_NumberOfVectors + sizeof(UD_WAVEFORM_SYS_EX));
  3295. pSysExBuffer[nArraySize] = 0;
  3296. pSysExBuffer[nArraySize+1] = 0;
  3297. pSysExBuffer[nArraySize] = ComputeChecksum((PBYTE) pSysExBuffer, (nArraySize+2));
  3298. pSysExBuffer[nArraySize+1]= MIDI_EOX;
  3299. return ((PBYTE) pSysExBuffer);
  3300. }
  3301. // ****************************************************************************
  3302. // *** --- Member functions for derived class CMidiProcessList
  3303. //
  3304. // ****************************************************************************
  3305. //
  3306. // ----------------------------------------------------------------------------
  3307. // Function: CMidiProcessList::CMidiProcessList
  3308. // Purpose: Constructor(s)/Destructor for CMidiProcessList Object
  3309. // Parameters:
  3310. // Returns:
  3311. // Algorithm:
  3312. // ----------------------------------------------------------------------------
  3313. CMidiProcessList::CMidiProcessList(ULONG ulButtonPlayMask, PPLIST pParam)
  3314. : CMidiEffect(ulButtonPlayMask)
  3315. {
  3316. m_OpCode = PROCESS_DATA | X_AXIS|Y_AXIS; // Subcommand opcode:PROCESS_DATA
  3317. m_NumEffects = pParam->ulNumEffects;
  3318. if (m_NumEffects > MAX_PLIST_EFFECT_SIZE) m_NumEffects = MAX_PLIST_EFFECT_SIZE;
  3319. assert(m_NumEffects > 0 && m_NumEffects <= MAX_PLIST_EFFECT_SIZE);
  3320. m_ProcessMode = pParam->ulProcessMode;
  3321. m_pEffectArray = new BYTE [m_NumEffects];
  3322. if (m_pEffectArray != NULL)
  3323. {
  3324. for (int i=0; i< (int) m_NumEffects; i++)
  3325. {
  3326. m_pEffectArray[i] = (BYTE) (pParam->pEffectArray)[i];
  3327. }
  3328. }
  3329. m_MidiBufferSize = sizeof(SYS_EX_HDR)+5+m_NumEffects + 2;
  3330. }
  3331. // --- Destructor
  3332. CMidiProcessList::~CMidiProcessList()
  3333. {
  3334. if (m_pEffectArray) delete [] m_pEffectArray;
  3335. memset(this, 0, sizeof(CMidiProcessList));
  3336. }
  3337. // ----------------------------------------------------------------------------
  3338. // Function: CMidiProcessList::SetParams
  3339. // Purpose: Sets the type specific parameters
  3340. // Parameters: PPLIST pParam
  3341. // Returns:
  3342. // Algorithm:
  3343. // ----------------------------------------------------------------------------
  3344. void CMidiProcessList::SetParams(ULONG ulButtonPlayMask, PPLIST pParam)
  3345. {
  3346. m_NumEffects = pParam->ulNumEffects;
  3347. if (m_NumEffects > MAX_PLIST_EFFECT_SIZE) m_NumEffects = MAX_PLIST_EFFECT_SIZE;
  3348. assert(m_NumEffects > 0 && m_NumEffects <= MAX_PLIST_EFFECT_SIZE);
  3349. Effect.bButtonPlayL = (BYTE) ulButtonPlayMask & 0x7f;
  3350. Effect.bButtonPlayH = (BYTE) ((ulButtonPlayMask >> 7) & 0x03);
  3351. m_ProcessMode = pParam->ulProcessMode;
  3352. if (m_pEffectArray != NULL)
  3353. {
  3354. for (int i=0; i< (int) m_NumEffects; i++)
  3355. {
  3356. m_pEffectArray[i] = (BYTE) (pParam->pEffectArray)[i];
  3357. }
  3358. }
  3359. }
  3360. // ----------------------------------------------------------------------------
  3361. // Function: CMidiProcessList::GenerateSysExPacket
  3362. // Purpose: Builds the SysEx packet into the pBuf
  3363. // Parameters: none
  3364. // Returns: PBYTE - pointer to a buffer filled with SysEx Packet
  3365. // Algorithm:
  3366. // ----------------------------------------------------------------------------
  3367. PBYTE CMidiProcessList::GenerateSysExPacket(void)
  3368. {
  3369. if (NULL == g_pJoltMidi) return ((PBYTE) NULL);
  3370. PBYTE pSysExBuffer = g_pJoltMidi->PrimaryBufferPtrOf();
  3371. assert(pSysExBuffer);
  3372. // Copy SysEx Header + m_OpCode + m_SubType + m_bEffectID + m_bButtonPlayL
  3373. // + m_bButtonPlayH
  3374. memcpy(pSysExBuffer,&m_bSysExCmd, (sizeof(SYS_EX_HDR) + 5 ));
  3375. PPROCESS_LIST_SYS_EX pBuf = (PPROCESS_LIST_SYS_EX) pSysExBuffer;
  3376. if (PL_SUPERIMPOSE == m_ProcessMode)
  3377. pBuf->bSubType = PLIST_SUPERIMPOSE;
  3378. else
  3379. pBuf->bSubType = PLIST_CONCATENATE;
  3380. pBuf->bButtonPlayL = (BYTE) (Effect.bButtonPlayL & 0x7f);
  3381. pBuf->bButtonPlayH = (BYTE) (Effect.bButtonPlayH & 0x7f);
  3382. // Copy the PLIST specific parameters
  3383. memcpy(&pBuf->bEffectArrayID, m_pEffectArray, m_NumEffects);
  3384. PBYTE pChecksum = (PBYTE) ( &pBuf->bEffectArrayID + m_NumEffects );
  3385. pChecksum[0] = ComputeChecksum((PBYTE) pSysExBuffer,
  3386. sizeof(SYS_EX_HDR)+5+m_NumEffects+2);
  3387. pChecksum[1] = MIDI_EOX;
  3388. return ((PBYTE) pSysExBuffer);
  3389. }
  3390. // ****************************************************************************
  3391. // *** --- Member functions for derived class CMidiVFXProcessList
  3392. //
  3393. // ****************************************************************************
  3394. //
  3395. // ----------------------------------------------------------------------------
  3396. // Function: CMidiVFXProcessList::CMidiVFXProcessList
  3397. // Purpose: Constructor(s)/Destructor for CMidiVFXProcessList Object
  3398. // Parameters:
  3399. // Returns:
  3400. // Algorithm:
  3401. // ----------------------------------------------------------------------------
  3402. CMidiVFXProcessList::CMidiVFXProcessList(ULONG ulButtonPlayMask, PPLIST pParam)
  3403. : CMidiProcessList(ulButtonPlayMask, pParam)
  3404. {
  3405. }
  3406. // ----------------------------------------------------------------------------
  3407. // Function: CMidiVFXEffect::DestroyEffect
  3408. // Purpose: Sends the Short Message for itself and children
  3409. // Parameters:
  3410. // Returns: Error code
  3411. // Algorithm:
  3412. // ----------------------------------------------------------------------------
  3413. HRESULT CMidiVFXProcessList::DestroyEffect()
  3414. {
  3415. HRESULT hRet;
  3416. if (NULL == g_pJoltMidi) return (SFERR_DRIVER_ERROR);
  3417. // destroy the children
  3418. for (int i=0; i< (int) m_NumEffects; i++)
  3419. {
  3420. // get the CMidiEffect object corresponding to child ID
  3421. CMidiEffect* pMidiEffect = g_pJoltMidi->GetEffectByID(m_pEffectArray[i]);
  3422. assert(NULL != pMidiEffect);
  3423. if (NULL == pMidiEffect) return (SFERR_INVALID_OBJECT);
  3424. // destroy the effect
  3425. hRet = pMidiEffect->DestroyEffect();
  3426. // remove it from the map
  3427. if(!FAILED(hRet))
  3428. g_pJoltMidi->SetEffectByID(EffectIDOf(), NULL);
  3429. // delete the object
  3430. delete pMidiEffect;
  3431. }
  3432. // destroy itself
  3433. hRet = CMidiEffect::DestroyEffect();
  3434. // remove it from the map
  3435. if(!FAILED(hRet))
  3436. g_pJoltMidi->SetEffectByID(EffectIDOf(), NULL);
  3437. return hRet;
  3438. }
  3439. // ****************************************************************************
  3440. // *** --- Member functions for derived class CMidiAssign
  3441. //
  3442. // ****************************************************************************
  3443. //
  3444. // ----------------------------------------------------------------------------
  3445. // Function: CMidiAssign::CMidiAssign
  3446. // Purpose: Constructor(s)/Destructor for CMidiAssign Object
  3447. // Parameters:
  3448. // Returns:
  3449. // Algorithm:
  3450. // ----------------------------------------------------------------------------
  3451. CMidiAssign::CMidiAssign(void) : CMidiEffect(NULL)
  3452. {
  3453. //
  3454. // --- THIS IS A CRITICAL SECTION
  3455. //
  3456. CriticalLock cl;
  3457. m_OpCode = MIDI_ASSIGN; // Sub-command opcode
  3458. m_SubType = 0; // not used
  3459. m_Channel = DEFAULT_MIDI_CHANNEL; // Midi channel
  3460. m_MidiBufferSize = sizeof(MIDI_ASSIGN_SYS_EX);
  3461. // --- END OF CRITICAL SECTION
  3462. //
  3463. }
  3464. // --- Destructor
  3465. CMidiAssign::~CMidiAssign()
  3466. {
  3467. memset(this, 0, sizeof(CMidiAssign));
  3468. }
  3469. // ----------------------------------------------------------------------------
  3470. // Function: CMidiAssign::GenerateSysExPacket
  3471. // Purpose: Builds the SysEx packet into the pBuf
  3472. // Parameters: none
  3473. // Returns: PBYTE - pointer to a buffer filled with SysEx Packet
  3474. // Algorithm:
  3475. // ----------------------------------------------------------------------------
  3476. PBYTE CMidiAssign::GenerateSysExPacket(void)
  3477. {
  3478. if (NULL == g_pJoltMidi) return ((PBYTE) NULL);
  3479. PBYTE pSysExBuffer = g_pJoltMidi->PrimaryBufferPtrOf();
  3480. assert(pSysExBuffer);
  3481. // Copy SysEx Header + m_OpCode + m_SubType
  3482. memcpy(pSysExBuffer, &m_bSysExCmd, sizeof(SYS_EX_HDR)+2 );
  3483. PMIDI_ASSIGN_SYS_EX pBuf = (PMIDI_ASSIGN_SYS_EX) pSysExBuffer;
  3484. pBuf->bChannel = (BYTE) (m_Channel & 0x0f);
  3485. pBuf->bChecksum = ComputeChecksum((PBYTE) pSysExBuffer,
  3486. sizeof(MIDI_ASSIGN_SYS_EX));
  3487. pBuf->bEOX = MIDI_EOX;
  3488. return ((PBYTE) pSysExBuffer);
  3489. }