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.

2404 lines
80 KiB

  1. /****************************************************************************
  2. MODULE: MIDI_OBJ.CPP
  3. Tab stops 5 9
  4. Copyright 1995, 1996, 1999, 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. 21-Mar-99 waltw Removed unreferenced UpdateJoystickParams,
  19. GetJoystickParams
  20. 21-Mar-99 waltw Add dwDeviceID param: CJoltMidi::Initialize
  21. and pass down food chain
  22. 21-Mar-99 waltw Added dwDeviceID param to DetectMidiDevice,
  23. InitDigitalOverDrive,
  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 "DPack.h"
  37. #include "CritSec.h"
  38. #include "DTrans.h"
  39. /****************************************************************************
  40. Declaration of externs
  41. ****************************************************************************/
  42. extern void CALLBACK midiOutputHandler(HMIDIOUT, UINT, DWORD, DWORD, DWORD);
  43. extern TCHAR szDeviceName[MAX_SIZE_SNAME];
  44. extern CJoltMidi *g_pJoltMidi;
  45. /****************************************************************************
  46. Declaration of variables
  47. ****************************************************************************/
  48. /****************************************************************************
  49. Macros etc
  50. ****************************************************************************/
  51. #ifdef _DEBUG
  52. extern char g_cMsg[160];
  53. void DebugOut(LPCTSTR szDebug)
  54. {
  55. g_CriticalSection.Enter();
  56. _RPT0(_CRT_WARN, szDebug);
  57. g_CriticalSection.Leave();
  58. #ifdef _LOG_DEBUG
  59. #pragma message("Compiling with Debug Log to SW_WHEEL.txt")
  60. FILE *pf = fopen("SW_WHEEL.txt", "a");
  61. if (pf != NULL)
  62. {
  63. fputs(szDebug, pf);
  64. fclose(pf);
  65. }
  66. #endif // _LOG_DEBUG
  67. }
  68. #else !_DEBUG
  69. #define DebugOut(x)
  70. #endif // _DEBUG
  71. // ****************************************************************************
  72. // *** --- Member functions for base CJoltMidi
  73. //
  74. // ****************************************************************************
  75. //
  76. // ----------------------------------------------------------------------------
  77. // Function: CJoltMidi::CJoltMidi
  78. // Purpose: Constructor(s)/Destructor for CJoltMidi Object
  79. // Parameters:
  80. // Returns:
  81. // Algorithm:
  82. // ----------------------------------------------------------------------------
  83. CJoltMidi::CJoltMidi(void)
  84. {
  85. CriticalLock cl;
  86. static char cWaterMark[MAX_SIZE_SNAME] = {"SWFF_SHAREDMEMORY MEA"};
  87. BOOL bAlreadyMapped = FALSE;
  88. #ifdef _DEBUG
  89. DebugOut("SWFF_PRO(DX):CJoltMidi::CJoltMidi\n");
  90. #endif
  91. memset(this, 0, sizeof(CJoltMidi));
  92. m_hVxD = INVALID_HANDLE_VALUE;
  93. // Create an in-memory memory-mapped file
  94. m_hSharedMemoryFile = CreateFileMapping((HANDLE) 0xFFFFFFFF,
  95. NULL, PAGE_READWRITE, 0, SIZE_SHARED_MEMORY,
  96. __TEXT(SWFF_SHAREDMEM_FILE));
  97. if (m_hSharedMemoryFile == NULL)
  98. {
  99. #ifdef _DEBUG
  100. DebugOut("SW_WHEEL(DX):ERROR! Failed to create Memory mapped file\n");
  101. #endif
  102. }
  103. else
  104. {
  105. if (GetLastError() == ERROR_ALREADY_EXISTS)
  106. {
  107. bAlreadyMapped = TRUE;
  108. }
  109. // File mapping created successfully.
  110. // Map a view of the file into the address space.
  111. m_pSharedMemory = (PSHARED_MEMORY) MapViewOfFile(m_hSharedMemoryFile,
  112. FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
  113. if ((BYTE *) m_pSharedMemory == NULL)
  114. {
  115. #ifdef _DEBUG
  116. DebugOut("SW_WHEEL(DX):ERROR! Failed to Map view of shared memory\n");
  117. #endif
  118. }
  119. // ***** Shared Memory Access *****
  120. LockSharedMemory();
  121. if (!bAlreadyMapped)
  122. {
  123. // Set watermark and initialize, Bump Ref Count
  124. memcpy(&m_pSharedMemory->m_cWaterMark[0], &cWaterMark[0], MAX_SIZE_SNAME);
  125. m_pSharedMemory->m_RefCnt = 0;
  126. }
  127. m_pSharedMemory->m_RefCnt++;
  128. }
  129. #ifdef _DEBUG
  130. wsprintf(g_cMsg, "SW_WHEEL(DX): Shared Memory:%lx, m_RefCnt:%d\n",m_pSharedMemory,
  131. m_pSharedMemory->m_RefCnt);
  132. DebugOut(g_cMsg);
  133. #endif
  134. UnlockSharedMemory();
  135. // ***** End of Shared Memory Access *****
  136. }
  137. // --- Destructor
  138. CJoltMidi::~CJoltMidi()
  139. {
  140. CriticalLock cl;
  141. DebugOut("SW_WHEEL(DX):CJoltMidi::~CJoltMidi()\n");
  142. // Normal CJoltMidi Destructor
  143. // Free the Primary SYS_EX locked memory
  144. if (m_hPrimaryBuffer) {
  145. GlobalUnlock(m_hPrimaryBuffer);
  146. GlobalFree(m_hPrimaryBuffer);
  147. }
  148. // ***** Shared Memory Access *****
  149. LockSharedMemory();
  150. // Decrement Ref Count and clean up if equal to zero.
  151. m_pSharedMemory->m_RefCnt--;
  152. #ifdef _DEBUG
  153. wsprintf(g_cMsg,"CJoltMidi::~CJoltMidi. RefCnt = %d\n",m_pSharedMemory->m_RefCnt);
  154. DebugOut(g_cMsg);
  155. #endif
  156. if (0 == m_pSharedMemory->m_RefCnt)
  157. {
  158. if ((g_pDataTransmitter != NULL) && (g_pDataPackager != NULL)) {
  159. // Tri-state Midi lines
  160. if (g_pDataPackager->SendForceFeedbackCommand(SWDEV_KILL_MIDI) == SUCCESS) {
  161. ACKNACK ackNack;
  162. g_pDataTransmitter->Transmit(ackNack); // Send it off
  163. }
  164. }
  165. }
  166. // Kill Data Packager
  167. delete g_pDataPackager;
  168. g_pDataPackager = NULL;
  169. // Kill Data Transmitter
  170. delete g_pDataTransmitter;
  171. g_pDataTransmitter = NULL;
  172. // This gets closed in UnlockSharedMemory call below. 22-Mar-99 waltw
  173. // if (m_hSWFFDataMutex) CloseHandle(m_hSWFFDataMutex);
  174. // Release the Midi Output Event handles
  175. if (m_hMidiOutputEvent) {
  176. CloseHandle (m_hMidiOutputEvent);
  177. m_hMidiOutputEvent = NULL;
  178. }
  179. // ***** End of Shared Memory Access *****
  180. // Release Memory Mapped file handles
  181. if (m_hSharedMemoryFile != NULL) {
  182. UnmapViewOfFile((LPCVOID) m_pSharedMemory);
  183. CloseHandle(m_hSharedMemoryFile);
  184. }
  185. // Release Mutex handle after releasing Mem Mapped file
  186. UnlockSharedMemory();
  187. // Close VxD handles
  188. if (g_pDriverCommunicator != NULL)
  189. {
  190. delete g_pDriverCommunicator;
  191. g_pDriverCommunicator = NULL;
  192. }
  193. memset(this, 0, sizeof(CJoltMidi));
  194. m_hVxD = INVALID_HANDLE_VALUE;
  195. }
  196. // ----------------------------------------------------------------------------
  197. // Function: CJoltMidi::Initialize
  198. // Purpose: Initializer
  199. // Parameters:
  200. // Returns:
  201. // Algorithm:
  202. // ----------------------------------------------------------------------------
  203. HRESULT CJoltMidi::Initialize(DWORD dwDeviceID)
  204. {
  205. CriticalLock cl;
  206. HRESULT hRet = SUCCESS;
  207. // initialize the MIDI output information block
  208. m_MidiOutInfo.uDeviceType = MIDI_OUT;
  209. m_MidiOutInfo.hMidiOut = NULL;
  210. m_MidiOutInfo.fAlwaysKeepOpen = TRUE;
  211. m_MidiOutInfo.uDeviceStatus = MIDI_DEVICE_IDLE;
  212. m_MidiOutInfo.MidiHdr.dwBytesRecorded = 0;
  213. m_MidiOutInfo.MidiHdr.dwUser = 0;
  214. m_MidiOutInfo.MidiHdr.dwOffset = 0;
  215. m_MidiOutInfo.MidiHdr.dwFlags = 0;
  216. // Allocate and lock global memory for SysEx messages
  217. m_hPrimaryBuffer = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, MAX_SYS_EX_BUFFER_SIZE);
  218. assert(m_hPrimaryBuffer);
  219. if (m_hPrimaryBuffer == NULL)
  220. {
  221. return E_OUTOFMEMORY;
  222. }
  223. m_pPrimaryBuffer = (LPBYTE) GlobalLock(m_hPrimaryBuffer);
  224. assert(m_pPrimaryBuffer);
  225. if(NULL == m_pPrimaryBuffer)
  226. {
  227. GlobalFree(m_hPrimaryBuffer);
  228. return (SFERR_DRIVER_ERROR);
  229. }
  230. // Initialize the IOCTL interface to VjoyD mini-driver
  231. hRet = InitDigitalOverDrive(dwDeviceID);
  232. if (SUCCESS != hRet)
  233. {
  234. DebugOut("Warning! Could not Initialize Digital OverDrive\n");
  235. return (hRet);
  236. }
  237. else
  238. DebugOut("InitDigitalOverDrive - Success\n");
  239. // Create a Callback Event
  240. HANDLE hEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, SWFF_MIDIEVENT);
  241. if (NULL == hEvent)
  242. {
  243. // Create an Event for notification when Midi Output has completed
  244. m_hMidiOutputEvent = CreateEvent(NULL, // No security
  245. TRUE, // Manual reset
  246. FALSE, // Initial event is non-signaled
  247. SWFF_MIDIEVENT ); // Named
  248. assert(m_hMidiOutputEvent);
  249. }
  250. else
  251. m_hMidiOutputEvent = hEvent;
  252. // This function is only called after g_pJoltMidi created
  253. assert(g_pJoltMidi);
  254. PDELAY_PARAMS pDelayParams = g_pJoltMidi->DelayParamsPtrOf();
  255. GetDelayParams(dwDeviceID, pDelayParams);
  256. // Reset HW first
  257. g_pDriverCommunicator->ResetDevice();
  258. Sleep(DelayParamsPtrOf()->dwHWResetDelay);
  259. // Set MIDI channel to default then Detect a Midi Device
  260. if (!DetectMidiDevice(dwDeviceID, &m_COMMPort)) { // Port address
  261. DebugOut("Warning! No Midi Device detected\n");
  262. return (SFERR_DRIVER_ERROR);
  263. } else {
  264. #ifdef _DEBUG
  265. wsprintf(g_cMsg,"DetectMidiDevice returned: DeviceID=%d, COMMInterface=%x, COMMPort=%x\n",
  266. m_MidiOutInfo.uDeviceID, m_COMMInterface, m_COMMPort);
  267. DebugOut(g_cMsg);
  268. #endif
  269. }
  270. if ((g_pDataPackager == NULL) || (g_pDataTransmitter == NULL)) {
  271. ASSUME_NOT_REACHED();
  272. return SFERR_DRIVER_ERROR;
  273. }
  274. // Set the status byte properly
  275. ULONG portByte = 0;
  276. g_pDriverCommunicator->GetPortByte(portByte); // don't care about success, always fails on old driver
  277. if (portByte & STATUS_GATE_200) {
  278. g_pDataTransmitter->SetNextNack(1);
  279. } else {
  280. g_pDataTransmitter->SetNextNack(0);
  281. }
  282. // Send Initialization packet(s) to Jolt
  283. hRet = g_pDataPackager->SetMidiChannel(DEFAULT_MIDI_CHANNEL);
  284. if (hRet == SUCCESS) {
  285. ACKNACK ackNack;
  286. hRet = g_pDataTransmitter->Transmit(ackNack);
  287. }
  288. if (hRet != SUCCESS) {
  289. DebugOut("Warning! Could not Initialize Jolt\n");
  290. return (hRet);
  291. } else {
  292. DebugOut("JOLT SetMidiChannel - Success\n");
  293. }
  294. // At this point, we have a valid MIDI path...
  295. // Continue by setting up the ROM Effects default table entries
  296. // ID , OutputRate, Gain, Duration
  297. static ROM_FX_PARAM RomFxTable [] = {{ RE_ROMID1 , 100, 100, 12289 }, // Random Noise
  298. { RE_ROMID2 , 100, 100, 2625 }, // AircraftCarrierTakeOff
  299. { RE_ROMID3 , 100, 50, 166 }, // BasketballDribble
  300. { RE_ROMID4 , 100, 14, 10000 }, // CarEngineIdling
  301. { RE_ROMID5 , 100, 30, 1000 }, // Chainsaw
  302. { RE_ROMID6 , 100, 100, 1000 }, // ChainsawingThings
  303. { RE_ROMID7 , 100, 40, 10000 }, // DieselEngineIdling
  304. { RE_ROMID8 , 100, 100, 348 }, // Jump
  305. { RE_ROMID9 , 100, 100, 250 }, // Land
  306. { RE_ROMID10, 200, 100, 1000 }, // MachineGun
  307. { RE_ROMID11, 100, 100, 83 }, // Punched
  308. { RE_ROMID12, 100, 100, 1000 }, // RocketLauncher
  309. { RE_ROMID13, 100, 98, 500 }, // SecretDoor
  310. { RE_ROMID14, 100, 66, 25 }, // SwitchClick
  311. { RE_ROMID15, 100, 75, 500 }, // WindGust
  312. { RE_ROMID16, 100, 100, 2500 }, // WindShear
  313. { RE_ROMID17, 100, 100, 50 }, // Pistol
  314. { RE_ROMID18, 100, 100, 295 }, // Shotgun
  315. { RE_ROMID19, 500, 95, 1000 }, // Laser1
  316. { RE_ROMID20, 500, 96, 1000 }, // Laser2
  317. { RE_ROMID21, 500, 100, 1000 }, // Laser3
  318. { RE_ROMID22, 500, 100, 1000 }, // Laser4
  319. { RE_ROMID23, 500, 100, 1000 }, // Laser5
  320. { RE_ROMID24, 500, 70, 1000 }, // Laser6
  321. { RE_ROMID25, 100, 100, 25 }, // OutOfAmmo
  322. { RE_ROMID26, 100, 71, 1000 }, // LigntningGun
  323. { RE_ROMID27, 100, 100, 250 }, // Missile
  324. { RE_ROMID28, 100, 100, 1000 }, // GatlingGun
  325. { RE_ROMID29, 500, 97, 250 }, // ShortPlasma
  326. { RE_ROMID30, 500, 100, 500 }, // PlasmaCannon1
  327. { RE_ROMID31, 500, 99, 625 }, // PlasmaCannon2
  328. { RE_ROMID32, 100, 100, 440 }}; // Cannon
  329. // { RE_ROMID33, 100, 68, 1000 }, // FlameThrower
  330. // { RE_ROMID34, 100, 100, 75 }, // BoltActionRifle
  331. // { RE_ROMID35, 500, 100, 300 }, // Crossbow
  332. // { RE_ROMID36, 100, 100, 1000 }, // Sine
  333. // { RE_ROMID37, 100, 100, 1000 }}; // Cosine
  334. m_pRomFxTable = &RomFxTable[0];
  335. // ***** Shared Memory Access *****
  336. LockSharedMemory();
  337. LONG lRefCnt = m_pSharedMemory->m_RefCnt;
  338. UnlockSharedMemory();
  339. // ***** End of Shared Memory Access *****
  340. // Initialize the RTC_Spring object
  341. g_ForceFeedbackDevice.InitRTCSpring(dwDeviceID);
  342. // initialize the joystick params
  343. g_ForceFeedbackDevice.InitJoystickParams(dwDeviceID);
  344. // initialize the firmware params fudge factors (for the first time)
  345. // in the case of the FFD interface, this will be the only time they
  346. // are initialized, which may cause a problem because joystick is assumed
  347. // to be ID1
  348. PFIRMWARE_PARAMS pFirmwareParams = g_pJoltMidi->FirmwareParamsPtrOf();
  349. GetFirmwareParams(dwDeviceID, pFirmwareParams);
  350. return (SUCCESS);
  351. }
  352. // *** ---------------------------------------------------------------------***
  353. // Function: CJoltMidi::LockSharedMemory
  354. // Purpose: Creates a Mutex for Shared Memory access
  355. // Parameters: none
  356. //
  357. //
  358. // Returns: TRUE if Mutex available else FALSE
  359. // Algorithm:
  360. //
  361. // Comments:
  362. //
  363. //
  364. // *** ---------------------------------------------------------------------***
  365. BOOL CJoltMidi::LockSharedMemory(void)
  366. {
  367. DWORD dwRet;
  368. {
  369. CriticalLock cl;
  370. // Create the SWFF mutex
  371. HANDLE hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, SWFF_SHAREDMEM_MUTEX);
  372. if (NULL == hMutex)
  373. {
  374. // Doesn't exist yet, so create it
  375. hMutex = CreateMutex(NULL, TRUE, SWFF_SHAREDMEM_MUTEX);
  376. if (NULL == hMutex)
  377. {
  378. #ifdef _DEBUG
  379. DebugOut("Error! Could not create SWFFDataMutex\n");
  380. #endif
  381. m_hSWFFDataMutex = NULL;
  382. return (FALSE);
  383. }
  384. }
  385. // SUCCESS
  386. m_hSWFFDataMutex = hMutex;
  387. dwRet = WaitForSingleObject(m_hSWFFDataMutex, MUTEX_TIMEOUT);
  388. } // End of Critical Section
  389. if (WAIT_OBJECT_0 == dwRet)
  390. return (TRUE);
  391. else
  392. {
  393. #ifdef _DEBUG
  394. g_CriticalSection.Enter();
  395. wsprintf(g_cMsg,"CJoltMidi::LockSharedMemory() error return: %lx\n", dwRet);
  396. DebugOut(g_cMsg);
  397. g_CriticalSection.Leave();
  398. #endif
  399. return (FALSE);
  400. }
  401. }
  402. // *** ---------------------------------------------------------------------***
  403. // Function: CJoltMidi::UnlockSharedMemory
  404. // Purpose: Releases Mutex for Shared Memory access
  405. // Parameters: none
  406. //
  407. //
  408. // Returns: none
  409. // Algorithm:
  410. //
  411. // Comments:
  412. //
  413. //
  414. // *** ---------------------------------------------------------------------***
  415. void CJoltMidi::UnlockSharedMemory(void)
  416. {
  417. //
  418. // --- THIS IS A CRITICAL SECTION
  419. //
  420. g_CriticalSection.Enter();
  421. if (NULL != m_hSWFFDataMutex)
  422. {
  423. ReleaseMutex(m_hSWFFDataMutex);
  424. CloseHandle(m_hSWFFDataMutex);
  425. m_hSWFFDataMutex=NULL;
  426. }
  427. // --- END OF CRITICAL SECTION
  428. //
  429. g_CriticalSection.Leave();
  430. }
  431. // ----------------------------------------------------------------------------
  432. // Function: CJoltMidi::GetAckNackData
  433. // Purpose: Waits for a Response ACK
  434. //
  435. // Parameters: int nTImeWait - Time to wait in 1 ms increment, 0=no wait
  436. // PACKNACK pAckNack - Pointer to ACKNACK structure
  437. //
  438. // Returns: SUCCESS else error code SFERR_DRIVER_ERROR
  439. //
  440. // Algorithm:
  441. //
  442. // Note: For Short messages the MidiOutProc callback receives no MM_MOM_DONE
  443. // indicating completed transmission. Only Long (SysEx) messages do.
  444. // Uses:
  445. //typedef struct _ACKNACK {
  446. // DWORD cBytes;
  447. // DWORD dwAckNack; //ACK, NACK
  448. // DWORD dwErrorCode;
  449. // DWORD dwEffectStatus; //DEV_STS_EFFECT_RUNNING||DEV_STS_EFFECT_STOPPED
  450. //} ACKNACK, *PACKNACK;
  451. //
  452. // ----------------------------------------------------------------------------
  453. HRESULT CJoltMidi::GetAckNackData(
  454. IN int nTimeWait,
  455. IN OUT PACKNACK pAckNack,
  456. IN USHORT usRegIndex)
  457. {
  458. CriticalLock cl;
  459. assert(pAckNack);
  460. // Use IOCTL from VxD to get AckNack data
  461. // Wait for Event to be set
  462. if (nTimeWait && m_hMidiOutputEvent)
  463. {
  464. DWORD dwRet = WaitForSingleObject(m_hMidiOutputEvent, nTimeWait);
  465. // :
  466. #ifdef _DEBUG
  467. wsprintf(g_cMsg,"WaitForSingleObject %lx returned %lx, nTimeWait=%ld\n", m_hMidiOutputEvent, dwRet, nTimeWait);
  468. DebugOut(g_cMsg);
  469. #endif
  470. BOOL bRet = ResetEvent(m_hMidiOutputEvent);
  471. }
  472. HRESULT hRet = g_pDriverCommunicator->GetAckNack(*pAckNack, usRegIndex);
  473. return (hRet);
  474. }
  475. // ----------------------------------------------------------------------------
  476. // Function: CJoltMidi::InitDigitalOverDrive
  477. // Purpose: Initialize the VxD interface
  478. //
  479. // Parameters: none
  480. //
  481. // Returns: SUCCESS or Error code
  482. //
  483. // Algorithm:
  484. // ----------------------------------------------------------------------------
  485. HRESULT CJoltMidi::InitDigitalOverDrive(DWORD dwDeviceID)
  486. {
  487. if (g_pDriverCommunicator != NULL)
  488. { // Attempt to reinit
  489. ASSUME_NOT_REACHED();
  490. return S_OK;
  491. }
  492. //
  493. // --- THIS IS A CRITICAL SECTION
  494. //
  495. HRESULT hRet = SUCCESS;
  496. DWORD driverMajor = 0xFFFFFFFF;
  497. DWORD driverMinor = 0xFFFFFFFF;
  498. CriticalLock cl;
  499. // This fork works on NT5 only (VxD stuff removed)
  500. assert(g_ForceFeedbackDevice.IsOSNT5() == TRUE);
  501. {
  502. g_pDriverCommunicator = new HIDFeatureCommunicator;
  503. if (g_pDriverCommunicator == NULL)
  504. {
  505. return DIERR_OUTOFMEMORY;
  506. }
  507. if (((HIDFeatureCommunicator*)g_pDriverCommunicator)->Initialize(dwDeviceID) == FALSE)
  508. { // Could not load the driver
  509. hRet = SFERR_DRIVER_ERROR;
  510. }
  511. }
  512. if (FAILED(hRet))
  513. {
  514. return hRet;
  515. }
  516. // Loaded driver, get the version
  517. g_pDriverCommunicator->GetDriverVersion(driverMajor, driverMinor);
  518. g_ForceFeedbackDevice.SetDriverVersion(driverMajor, driverMinor);
  519. return (hRet);
  520. }
  521. // ----------------------------------------------------------------------------
  522. // Function: CJoltMidi::UpdateDeviceMode
  523. // Purpose: Sets JOLT Device Mode
  524. //
  525. // Parameters: ULONG ulMode
  526. //
  527. // Returns: none
  528. //
  529. // Algorithm:
  530. // This is the SideWinder State structure
  531. //typedef struct _SWDEVICESTATE {
  532. // ULONG m_Bytes; // size of this structure
  533. // ULONG m_ForceState; // DS_FORCE_ON || DS_FORCE_OFF || DS_SHUTDOWN
  534. // ULONG m_EffectState; // DS_STOP_ALL || DS_CONTINUE || DS_PAUSE
  535. // ULONG m_HOTS; // Hands On Throttle and Stick Status
  536. // // 0 = Hands Off, 1 = Hands On
  537. // ULONG m_BandWidth; // Percentage of CPU available 1 to 100%
  538. // // Lower number indicates CPU is in trouble!
  539. // ULONG m_ACBrickFault; // 0 = AC Brick OK, 1 = AC Brick Fault
  540. // ULONG m_ResetDetect; // 1 = HW Reset Detected
  541. // ULONG m_ShutdownDetect; // 1 = Shutdown detected
  542. // ULONG m_CommMode; // 0 = Midi, 1-4 = Serial
  543. //} SWDEVICESTATE, *PSWDEVICESTATE;
  544. //
  545. // ----------------------------------------------------------------------------
  546. void CJoltMidi::UpdateDeviceMode(ULONG ulMode)
  547. {
  548. //
  549. // --- THIS IS A CRITICAL SECTION
  550. //
  551. g_CriticalSection.Enter();
  552. switch (ulMode)
  553. {
  554. case SWDEV_FORCE_ON: // REVIEW
  555. case SWDEV_FORCE_OFF:
  556. m_DeviceState.m_ForceState = ulMode;
  557. break;
  558. case SWDEV_SHUTDOWN:
  559. m_DeviceState.m_ForceState = ulMode;
  560. m_DeviceState.m_EffectState = 0;
  561. break;
  562. case SWDEV_STOP_ALL:
  563. case SWDEV_CONTINUE:
  564. case SWDEV_PAUSE:
  565. m_DeviceState.m_EffectState = ulMode;
  566. break;
  567. default:
  568. break;
  569. }
  570. // --- END OF CRITICAL SECTION
  571. //
  572. g_CriticalSection.Leave();
  573. }
  574. // ----------------------------------------------------------------------------
  575. // Function: CJoltMidi::GetJoltID
  576. // Purpose: Returns JOLT ProductID
  577. //
  578. // Parameters: LOCAL_PRODUCT_ID* pProductID - Pointer to a PRODUCT_ID structure
  579. //
  580. // Returns: none
  581. //
  582. // Algorithm:
  583. //
  584. // ----------------------------------------------------------------------------
  585. HRESULT CJoltMidi::GetJoltID(LOCAL_PRODUCT_ID* pProductID)
  586. {
  587. HRESULT hRet;
  588. assert(pProductID->cBytes = sizeof(LOCAL_PRODUCT_ID));
  589. if (pProductID->cBytes != sizeof(LOCAL_PRODUCT_ID)) return (SFERR_INVALID_STRUCT_SIZE);
  590. //
  591. // --- THIS IS A CRITICAL SECTION
  592. //
  593. g_CriticalSection.Enter();
  594. for (int i=0;i<MAX_RETRY_COUNT;i++)
  595. {
  596. if (SUCCESS == (hRet = g_pDriverCommunicator->GetID(*pProductID))) break;
  597. }
  598. if (SUCCESS == hRet)
  599. {
  600. memcpy(&m_ProductID, pProductID, sizeof(LOCAL_PRODUCT_ID));
  601. }
  602. else
  603. DebugOut("GetJoltID: Warning! GetIDPacket - Fail\n");
  604. // --- END OF CRITICAL SECTION
  605. //
  606. g_CriticalSection.Leave();
  607. return (hRet);
  608. }
  609. // ----------------------------------------------------------------------------
  610. // Function: CJoltMidi::LogError
  611. // Purpose: Logs Error codes
  612. //
  613. // Parameters: HRESULT SystemError - System Error code
  614. // HRESULT DriverError - Driver Error code
  615. //
  616. // Returns: SWFORCE Error code
  617. //
  618. // Algorithm:
  619. // ----------------------------------------------------------------------------
  620. typedef struct _DRIVERERROR {
  621. ULONG ulDriverCode;
  622. LONG lSystemCode;
  623. } DRIVERERROR, *PDRIVERERROR;
  624. HRESULT CJoltMidi::LogError(
  625. IN HRESULT SystemError,
  626. IN HRESULT DriverError)
  627. {
  628. // REVIEW: map MM error codes to our SWForce codes
  629. DRIVERERROR DriverErrorCodes[] = {
  630. {DEV_ERR_INVALID_ID , SWDEV_ERR_INVALID_ID},
  631. {DEV_ERR_INVALID_PARAM , SWDEV_ERR_INVALID_PARAM},
  632. {DEV_ERR_CHECKSUM , SWDEV_ERR_CHECKSUM},
  633. {DEV_ERR_TYPE_FULL , SWDEV_ERR_TYPE_FULL},
  634. {DEV_ERR_UNKNOWN_CMD , SWDEV_ERR_UNKNOWN_CMD},
  635. {DEV_ERR_PLAYLIST_FULL , SWDEV_ERR_PLAYLIST_FULL},
  636. {DEV_ERR_PROCESS_LIST_FULL , SWDEV_ERR_PROCESSLIST_FULL} };
  637. int nDriverErrorCodes = sizeof(DriverErrorCodes)/(sizeof(DRIVERERROR));
  638. for (int i=0; i<nDriverErrorCodes; i++)
  639. {
  640. if (DriverError == (LONG) DriverErrorCodes[i].ulDriverCode)
  641. {
  642. SystemError = DriverErrorCodes[i].lSystemCode;
  643. break;
  644. }
  645. }
  646. // Store in Jolt object
  647. m_Error.HCode = SystemError;
  648. m_Error.ulDriverCode = DriverError;
  649. #ifdef _DEBUG
  650. wsprintf(g_cMsg,"LogError: SystemError=%.8lx, DriverError=%.8lx\n",
  651. SystemError, DriverError);
  652. DebugOut(g_cMsg);
  653. #endif
  654. return SystemError;
  655. }
  656. //
  657. // ----------------------------------------------------------------------------
  658. // Function: SetupROM_Fx
  659. // Purpose: Sets up parameters for ROM Effects
  660. // Parameters: PEFFECT pEffect
  661. //
  662. //
  663. // Returns: pEffect is updated with new ROM parameters
  664. // OutputRate
  665. // Gain
  666. // Duration
  667. //
  668. // Algorithm:
  669. // ----------------------------------------------------------------------------
  670. HRESULT CJoltMidi::SetupROM_Fx(
  671. IN OUT PEFFECT pEffect)
  672. {
  673. assert(pEffect);
  674. if (NULL == pEffect) return (SFERR_INVALID_PARAM);
  675. ULONG ulSubType = pEffect->m_SubType;
  676. BOOL bFound = FALSE;
  677. for (int i=0; i< MAX_ROM_EFFECTS; i++)
  678. {
  679. if (ulSubType == m_pRomFxTable[i].m_ROM_Id)
  680. {
  681. bFound = TRUE;
  682. break;
  683. }
  684. }
  685. if (!bFound) return (SFERR_INVALID_OBJECT);
  686. // Found, so fill in the default parameters, use Default if Gain=1, Duration=-1, OutputRate=-1
  687. BOOL bDefaultDuration = (ULONG)-1 == pEffect->m_Duration;
  688. if (1 == pEffect->m_Gain) pEffect->m_Gain = m_pRomFxTable[i].m_Gain;
  689. if (bDefaultDuration) pEffect->m_Duration = m_pRomFxTable[i].m_Duration;
  690. if ((ULONG)-1 == pEffect->m_ForceOutputRate)
  691. {
  692. pEffect->m_ForceOutputRate = m_pRomFxTable[i].m_ForceOutputRate;
  693. }
  694. else if(bDefaultDuration && pEffect->m_ForceOutputRate != 0)
  695. {
  696. // scale the duration to correspond to the output rate
  697. pEffect->m_Duration = pEffect->m_Duration*m_pRomFxTable[i].m_ForceOutputRate/pEffect->m_ForceOutputRate;
  698. }
  699. return (SUCCESS);
  700. }
  701. // *** ---------------------------------------------------------------------***
  702. // Function: DetectMidiDevice
  703. // Purpose: Determines Midi Output Device ID
  704. // Parameters:
  705. // ULONG pCOMMInterface - Ptr to COMMInterface value
  706. // ULONG pCOMMPort - Ptr to COMMPort value (Registry)
  707. // Returns: BOOL TRUE if successful match and IDs are filled in
  708. // else FALSE
  709. //
  710. // *** ---------------------------------------------------------------------***
  711. BOOL CJoltMidi::DetectMidiDevice(
  712. IN DWORD dwDeviceID,
  713. OUT ULONG *pCOMMPort)
  714. {
  715. CriticalLock cl;
  716. // Set defaults
  717. *pCOMMPort = NULL;
  718. // Turn on tristated Jolt MIDI lines by call GetIDPacket()
  719. LOCAL_PRODUCT_ID ProductID = {sizeof(LOCAL_PRODUCT_ID)};
  720. Sleep(DelayParamsPtrOf()->dwDigitalOverdrivePrechargeCmdDelay);
  721. if (SUCCESS != GetJoltID(&ProductID))
  722. {
  723. DebugOut("DetectMidiDevice: Warning! GetIDPacket - Fail\n");
  724. return (FALSE);
  725. }
  726. #ifdef _DEBUG
  727. wsprintf(g_cMsg,"%s: ProductID=%.8lx, FWVersion=%d.%.2ld\n",
  728. &szDeviceName,
  729. m_ProductID.dwProductID,
  730. m_ProductID.dwFWMajVersion,
  731. m_ProductID.dwFWMinVersion);
  732. DebugOut(g_cMsg);
  733. #endif
  734. // Set the device firmware version from GetID
  735. g_ForceFeedbackDevice.SetFirmwareVersion(dwDeviceID, m_ProductID.dwFWMajVersion, m_ProductID.dwFWMinVersion);
  736. // Get Device status prior to starting detection
  737. BOOL statusPacketFailed = (g_ForceFeedbackDevice.QueryStatus() != SUCCESS);
  738. /* if (statusPacketFailed == FALSE) { --- GetID does not clear soft reset bit
  739. if (g_ForceFeedbackDevice.IsHardwareReset()) { // Make sure HW Reset Detect bit is cleared after GetID
  740. DebugOut("DetectMidiDevice: Error! Jolt ResetDetect bit not cleared after GetID\n");
  741. return (FALSE);
  742. }
  743. }
  744. */
  745. // See if Serial Dongle connected, otherwise must be MIDI device
  746. DebugOut("SW_WHEEL:Trying Auto HW Detection: MIDI Serial Port Device...\n");
  747. // Get Registry values, If high bit of COMMInterface is set, then force override (should add)
  748. DWORD commInterface;
  749. if (SUCCESS != joyGetForceFeedbackCOMMInterface(dwDeviceID, &commInterface, pCOMMPort)) {
  750. DebugOut("DetectMidiDevice: Registry key(s) missing! Bailing Out...\n");
  751. return (FALSE);
  752. }
  753. #ifdef _DEBUG
  754. wsprintf(g_cMsg, "DetectMidiDevice: Registry.COMMInterface=%lx, Registry.COMMPort=%lx\n",
  755. commInterface, *pCOMMPort);
  756. DebugOut(g_cMsg);
  757. #endif
  758. ULONG regInterface = commInterface;
  759. // Delete any data transmitter (unless this is called multiple times - shouldn't happen)
  760. if (g_pDataTransmitter != NULL) {
  761. DebugOut("Unexpected multiple DetectMidiDevice() calls\r\n");
  762. delete g_pDataTransmitter;
  763. g_pDataTransmitter = NULL;
  764. }
  765. // Was a serial dongle detected, or did we fail to get status
  766. if (g_ForceFeedbackDevice.IsSerial() || statusPacketFailed) { // Use serial (regardless what registry says!)
  767. DebugOut("DetectMidiDevice: Serial Port interface detected. Or Status Packet failed\n");
  768. // Set to backdoor serial method by default
  769. m_COMMInterface = COMM_SERIAL_BACKDOOR;
  770. // Should we try backdoor first (old firmware, or reg says so)
  771. if ((g_ForceFeedbackDevice.GetFirmwareVersionMajor() == 1) && (g_ForceFeedbackDevice.GetFirmwareVersionMinor() == 16)
  772. || (regInterface & MASK_SERIAL_BACKDOOR)) {
  773. g_pDataTransmitter = new SerialBackdoorDataTransmitter;
  774. if (!g_pDataTransmitter->Initialize(dwDeviceID)) {
  775. delete g_pDataTransmitter;
  776. g_pDataTransmitter = NULL;
  777. }
  778. }
  779. // Backdoor not warrented or didn't work - front door
  780. if (g_pDataTransmitter == NULL) {
  781. g_pDataTransmitter = new SerialDataTransmitter();
  782. m_COMMInterface = COMM_SERIAL_FILE;
  783. if (!g_pDataTransmitter->Initialize(dwDeviceID)) { // Failed Front Door! (yech)
  784. delete g_pDataTransmitter;
  785. g_pDataTransmitter = NULL;
  786. }
  787. }
  788. if ((statusPacketFailed == FALSE) || (g_pDataTransmitter != NULL)) {
  789. return (g_pDataTransmitter != NULL);
  790. }
  791. } // End of Serial Port Auto HW selection
  792. // No Serial HW dongle detected, try midi-backdoor and WinMM
  793. DebugOut("Trying Midi (Serial No Go or No Dongle)\n");
  794. ULONG ulPort = *pCOMMPort; // Set in the registry (assumed valid if override is set
  795. if ( !(regInterface & MASK_OVERRIDE_MIDI_PATH) ) { // Use Automatic detection
  796. DebugOut("DetectMidiDevice: Auto Detection. Trying Backdoor\n");
  797. // Back Door
  798. g_pDataTransmitter = new MidiBackdoorDataTransmitter();
  799. if (!g_pDataTransmitter->Initialize(dwDeviceID)) {
  800. delete g_pDataTransmitter;
  801. g_pDataTransmitter = NULL;
  802. }
  803. if (g_pDataTransmitter == NULL) { // Try Front Door
  804. DebugOut("DetectMidiDevice: trying WINMM...\n");
  805. g_pDataTransmitter = new WinMMDataTransmitter();
  806. if (!g_pDataTransmitter->Initialize(dwDeviceID)) {
  807. delete g_pDataTransmitter;
  808. g_pDataTransmitter = NULL;
  809. }
  810. }
  811. return (g_pDataTransmitter != NULL);
  812. }
  813. // Over-ride since high bit is set
  814. commInterface &= ~(MASK_OVERRIDE_MIDI_PATH | MASK_SERIAL_BACKDOOR); // Mask out high bit (and second bit)
  815. switch (commInterface) {
  816. case COMM_WINMM: {
  817. g_pDataTransmitter = new WinMMDataTransmitter();
  818. if (!g_pDataTransmitter->Initialize(dwDeviceID)) {
  819. delete g_pDataTransmitter;
  820. g_pDataTransmitter = NULL;
  821. }
  822. break;
  823. }
  824. case COMM_MIDI_BACKDOOR: {
  825. // Back Door
  826. g_pDataTransmitter = new MidiBackdoorDataTransmitter();
  827. if (!((MidiBackdoorDataTransmitter*)g_pDataTransmitter)->InitializeSpecific(dwDeviceID, HANDLE(ulPort))) {
  828. delete g_pDataTransmitter;
  829. g_pDataTransmitter = NULL;
  830. }
  831. break;
  832. }
  833. case COMM_SERIAL_BACKDOOR: { // mlc - This will never work if no dongle detected
  834. DebugOut("Cannot force Serial Backdoor if no serial dongle is connected\r\n");
  835. break;
  836. }
  837. }
  838. if (g_pDataTransmitter == NULL) {
  839. DebugOut("DetectMidiDevice: Error! Invalid Over-ride parameter values\n");
  840. }
  841. return (g_pDataTransmitter != NULL);
  842. }
  843. // *** ---------------------------------------------------------------------***
  844. // Function: QueryForJolt
  845. // Purpose: Sends Shutdown and Queries for Shutdown status bit
  846. // Parameters: none
  847. // Returns: BOOL TRUE if Jolt found, else FALSE
  848. //
  849. // Comments: SHUTDOWN is destructive!!!
  850. //
  851. // *** ---------------------------------------------------------------------***
  852. BOOL CJoltMidi::QueryForJolt(void)
  853. {
  854. HRESULT hRet;
  855. // Sanity check
  856. if (g_pDataPackager == NULL) {
  857. ASSUME_NOT_REACHED();
  858. return FALSE;
  859. }
  860. if (g_pDataTransmitter == NULL) {
  861. ASSUME_NOT_REACHED();
  862. return FALSE;
  863. }
  864. // Send Shutdown command then detect if Shutdown was detected
  865. for (int i=0;i<MAX_RETRY_COUNT;i++)
  866. {
  867. // Send a ShutDown, then check for response
  868. if (g_pDataPackager->SendForceFeedbackCommand(DISFFC_RESET) != SUCCESS) {
  869. ASSUME_NOT_REACHED(); // Could not package?
  870. return FALSE;
  871. }
  872. // Get rid of unneeded delay here
  873. DataPacket* packet = g_pDataPackager->GetPacket(0);
  874. if (packet != NULL) {
  875. packet->m_AckNackDelay = 0;
  876. }
  877. ACKNACK ackNack;
  878. if (g_pDataTransmitter->Transmit(ackNack) != SUCCESS) { // Send it off
  879. ASSUME_NOT_REACHED(); // Inable to transmit?
  880. return FALSE;
  881. }
  882. Sleep(DelayParamsPtrOf()->dwShutdownDelay); // 10 ms
  883. hRet = g_ForceFeedbackDevice.QueryStatus();
  884. if (hRet == SUCCESS) {
  885. break;
  886. }
  887. }
  888. Sleep(DelayParamsPtrOf()->dwDigitalOverdrivePrechargeCmdDelay);
  889. // Clear the Previous state and turn on tri-state buffers
  890. LOCAL_PRODUCT_ID ProductID = {sizeof(LOCAL_PRODUCT_ID)};
  891. hRet = GetJoltID(&ProductID);
  892. if (hRet != SUCCESS) {
  893. DebugOut("QueryForJolt: Driver Error. Get Jolt Status/ID\n");
  894. return (FALSE);
  895. }
  896. return g_ForceFeedbackDevice.IsHostReset();
  897. }
  898. // *** ---------------------------------------------------------------------***
  899. // Function: MidiSendShortMsg
  900. // Purpose: Send status, channel and data.
  901. // Parameters:
  902. // BYTE cStatus - MIDI status byte for this message
  903. // BYTE cData1 - MIDI data byte for this message
  904. // BYTE cData2 - 2nd MIDI data byte for this message (may be 0)
  905. // Returns: HRESULT
  906. //
  907. // *** ---------------------------------------------------------------------***
  908. HRESULT CJoltMidi::MidiSendShortMsg(
  909. IN BYTE cStatus,
  910. IN BYTE cData1,
  911. IN BYTE cData2)
  912. {
  913. ASSUME_NOT_REACHED();
  914. return SUCCESS;
  915. /*
  916. g_CriticalSection.Enter();
  917. // For diagnostics, record the attempts at this message
  918. BumpShortMsgCounter();
  919. HRESULT retVal = SFERR_DRIVER_ERROR;
  920. if (g_pDataTransmitter != NULL) {
  921. BYTE data[3];
  922. data[0] = cStatus;
  923. data[1] = cData1;
  924. data[2] = cData2;
  925. int numBytes = 3;
  926. DWORD cmd = cStatus & 0xF0;
  927. if ((cmd == 0xC0 ) || (cmd == 0xD0)) {
  928. numBytes = 2;
  929. }
  930. if (g_pDataTransmitter->Send(data, numBytes)) {
  931. retVal = SUCCESS;
  932. }
  933. }
  934. g_CriticalSection.Leave();
  935. return retVal;
  936. */
  937. }
  938. // *** ---------------------------------------------------------------------***
  939. // Function: MidiSendLongMsg
  940. // Purpose: Send system exclusive message or series of short messages.
  941. // Parameters:
  942. // none - assumes m_pMidiOutInfo structure is valid
  943. //
  944. // Returns:
  945. //
  946. //
  947. // *** ---------------------------------------------------------------------***
  948. HRESULT CJoltMidi::MidiSendLongMsg(void)
  949. {
  950. ASSUME_NOT_REACHED();
  951. return SUCCESS;
  952. /*
  953. g_CriticalSection.Enter();
  954. // For diagnostics, record the attempts at this message
  955. BumpLongMsgCounter();
  956. HRESULT retVal = SFERR_DRIVER_ERROR;
  957. if (g_pDataTransmitter != NULL) {
  958. if (g_pDataTransmitter->Send((PBYTE)m_MidiOutInfo.MidiHdr.lpData, m_MidiOutInfo.MidiHdr.dwBufferLength)) {
  959. retVal = SUCCESS;
  960. }
  961. }
  962. ::Sleep(g_pJoltMidi->DelayParamsPtrOf()->dwLongMsgDelay);
  963. g_CriticalSection.Leave();
  964. return retVal;
  965. */
  966. }
  967. // ****************************************************************************
  968. // *** --- Helper functions for CJoltMidi
  969. //
  970. // ****************************************************************************
  971. //
  972. #define REGSTR_VAL_FIRMWARE_PARAMS "FirmwareParams"
  973. void GetFirmwareParams(UINT nJoystickID, PFIRMWARE_PARAMS pFirmwareParams)
  974. {
  975. BOOL bFail = FALSE;
  976. // try to open the registry key
  977. HKEY hKey;
  978. DWORD dwcb = sizeof(FIRMWARE_PARAMS);
  979. LONG lr;
  980. hKey = joyOpenOEMForceFeedbackKey(nJoystickID);
  981. if(!hKey)
  982. bFail = TRUE;
  983. if (!bFail)
  984. {
  985. // Get Firmware Parameters
  986. lr = RegQueryValueEx( hKey,
  987. REGSTR_VAL_FIRMWARE_PARAMS,
  988. NULL, NULL,
  989. (PBYTE)pFirmwareParams,
  990. &dwcb);
  991. RegCloseKey(hKey);
  992. if (lr != ERROR_SUCCESS)
  993. bFail = TRUE;
  994. }
  995. if(bFail)
  996. {
  997. // if reading from the registry fails, just use the defaults
  998. pFirmwareParams->dwScaleKx = DEF_SCALE_KX;
  999. pFirmwareParams->dwScaleKy = DEF_SCALE_KY;
  1000. pFirmwareParams->dwScaleBx = DEF_SCALE_BX;
  1001. pFirmwareParams->dwScaleBy = DEF_SCALE_BY;
  1002. pFirmwareParams->dwScaleMx = DEF_SCALE_MX;
  1003. pFirmwareParams->dwScaleMy = DEF_SCALE_MY;
  1004. pFirmwareParams->dwScaleFx = DEF_SCALE_FX;
  1005. pFirmwareParams->dwScaleFy = DEF_SCALE_FY;
  1006. pFirmwareParams->dwScaleW = DEF_SCALE_W;
  1007. }
  1008. }
  1009. #define REGSTR_VAL_SYSTEM_PARAMS "SystemParams"
  1010. void GetSystemParams(UINT nJoystickID, PSYSTEM_PARAMS pSystemParams)
  1011. {
  1012. BOOL bFail = FALSE;
  1013. // try to open the registry key
  1014. HKEY hKey;
  1015. DWORD dwcb = sizeof(SYSTEM_PARAMS);
  1016. LONG lr;
  1017. hKey = joyOpenOEMForceFeedbackKey(nJoystickID);
  1018. if(!hKey)
  1019. bFail = TRUE;
  1020. if (!bFail)
  1021. {
  1022. // Get Firmware Parameters
  1023. lr = RegQueryValueEx( hKey,
  1024. REGSTR_VAL_SYSTEM_PARAMS,
  1025. NULL, NULL,
  1026. (PBYTE)pSystemParams,
  1027. &dwcb);
  1028. // scale them
  1029. pSystemParams->RTCSpringParam.m_XKConstant /= SCALE_CONSTANTS;
  1030. pSystemParams->RTCSpringParam.m_YKConstant /= SCALE_CONSTANTS;
  1031. pSystemParams->RTCSpringParam.m_XAxisCenter /= SCALE_POSITION;
  1032. pSystemParams->RTCSpringParam.m_YAxisCenter = -pSystemParams->RTCSpringParam.m_YAxisCenter/SCALE_POSITION;
  1033. pSystemParams->RTCSpringParam.m_XSaturation /= SCALE_POSITION;
  1034. pSystemParams->RTCSpringParam.m_YSaturation /= SCALE_POSITION;
  1035. pSystemParams->RTCSpringParam.m_XDeadBand /= SCALE_POSITION;
  1036. pSystemParams->RTCSpringParam.m_YDeadBand /= SCALE_POSITION;
  1037. RegCloseKey(hKey);
  1038. if (lr != ERROR_SUCCESS)
  1039. bFail = TRUE;
  1040. }
  1041. if(bFail)
  1042. {
  1043. // if reading from the registry fails, just use the defaults
  1044. pSystemParams->RTCSpringParam.m_Bytes = sizeof(RTCSPRING_PARAM);
  1045. pSystemParams->RTCSpringParam.m_XKConstant = DEFAULT_RTC_KX;
  1046. pSystemParams->RTCSpringParam.m_YKConstant = DEFAULT_RTC_KY;
  1047. pSystemParams->RTCSpringParam.m_XAxisCenter = DEFAULT_RTC_X0;
  1048. pSystemParams->RTCSpringParam.m_YAxisCenter = DEFAULT_RTC_Y0;
  1049. pSystemParams->RTCSpringParam.m_XSaturation = DEFAULT_RTC_XSAT;
  1050. pSystemParams->RTCSpringParam.m_YSaturation = DEFAULT_RTC_YSAT;
  1051. pSystemParams->RTCSpringParam.m_XDeadBand = DEFAULT_RTC_XDBAND;
  1052. pSystemParams->RTCSpringParam.m_YDeadBand = DEFAULT_RTC_YDBAND;
  1053. }
  1054. }
  1055. #define REGSTR_VAL_DELAY_PARAMS "TimingParams"
  1056. void GetDelayParams(UINT nJoystickID, PDELAY_PARAMS pDelayParams)
  1057. {
  1058. BOOL bFail = FALSE;
  1059. // try to open the registry key
  1060. HKEY hKey;
  1061. DWORD dwcb = sizeof(DELAY_PARAMS);
  1062. LONG lr;
  1063. hKey = joyOpenOEMForceFeedbackKey(nJoystickID);
  1064. if(!hKey)
  1065. bFail = TRUE;
  1066. if (!bFail)
  1067. {
  1068. // Get Firmware Parameters
  1069. lr = RegQueryValueEx( hKey,
  1070. REGSTR_VAL_DELAY_PARAMS,
  1071. NULL, NULL,
  1072. (PBYTE)pDelayParams,
  1073. &dwcb);
  1074. RegCloseKey(hKey);
  1075. if (lr != ERROR_SUCCESS)
  1076. bFail = TRUE;
  1077. }
  1078. if(bFail)
  1079. {
  1080. // if reading from the registry fails, just use the defaults
  1081. pDelayParams->dwBytes = sizeof(DELAY_PARAMS);
  1082. pDelayParams->dwDigitalOverdrivePrechargeCmdDelay = DEFAULT_DIGITAL_OVERDRIVE_PRECHARGE_CMD_DELAY;
  1083. pDelayParams->dwShutdownDelay = DEFAULT_SHUTDOWN_DELAY;
  1084. pDelayParams->dwHWResetDelay = DEFAULT_HWRESET_DELAY;
  1085. pDelayParams->dwPostSetDeviceStateDelay = DEFAULT_POST_SET_DEVICE_STATE_DELAY;
  1086. pDelayParams->dwGetEffectStatusDelay = DEFAULT_GET_EFFECT_STATUS_DELAY;
  1087. pDelayParams->dwGetDataPacketDelay = DEFAULT_GET_DATA_PACKET_DELAY;
  1088. pDelayParams->dwGetStatusPacketDelay = DEFAULT_GET_STATUS_PACKET_DELAY;
  1089. pDelayParams->dwGetIDPacketDelay = DEFAULT_GET_ID_PACKET_DELAY;
  1090. pDelayParams->dwGetStatusGateDataDelay = DEFAULT_GET_STATUS_GATE_DATA_DELAY;
  1091. pDelayParams->dwSetIndexDelay = DEFAULT_SET_INDEX_DELAY;
  1092. pDelayParams->dwModifyParamDelay = DEFAULT_MODIFY_PARAM_DELAY;
  1093. pDelayParams->dwForceOutDelay = DEFAULT_FORCE_OUT_DELAY;
  1094. pDelayParams->dwShortMsgDelay = DEFAULT_SHORT_MSG_DELAY;
  1095. pDelayParams->dwLongMsgDelay = DEFAULT_LONG_MSG_DELAY;
  1096. pDelayParams->dwDestroyEffectDelay = DEFAULT_DESTROY_EFFECT_DELAY;
  1097. pDelayParams->dwForceOutMod = DEFAULT_FORCE_OUT_MOD;
  1098. // write the defaults to the registry
  1099. hKey = joyOpenOEMForceFeedbackKey(nJoystickID);
  1100. if(hKey)
  1101. {
  1102. // Modify Registry Values
  1103. RegSetValueEx ( hKey, REGSTR_VAL_DELAY_PARAMS, 0, REG_BINARY, (const unsigned char *)pDelayParams, sizeof(DELAY_PARAMS) );
  1104. // Close Key
  1105. RegCloseKey(hKey);
  1106. }
  1107. }
  1108. if(pDelayParams->dwForceOutMod == 0)
  1109. pDelayParams->dwForceOutMod = 1;
  1110. }
  1111. //#define REGSTR_VAL_JOYSTICK_PARAMS "JoystickParams"
  1112. // ****************************************************************************
  1113. // *** --- Member functions for base class CMidiEffect
  1114. //
  1115. // ****************************************************************************
  1116. //
  1117. // ----------------------------------------------------------------------------
  1118. // Function: CMidiEffect::CMidiEffect
  1119. // Purpose: Constructor(s)/Destructor for CMidiEffect Object
  1120. // Parameters:
  1121. // Returns:
  1122. // Algorithm:
  1123. // ----------------------------------------------------------------------------
  1124. CMidiEffect::CMidiEffect(IN ULONG ulButtonPlayMask)
  1125. {
  1126. m_bSysExCmd = SYS_EX_CMD; // SysEx Fx command
  1127. m_bEscManufID = 0; // Escape to long Manufac. ID, s/b 0
  1128. m_bManufIDL = (MS_MANUFACTURER_ID & 0x7f); // Low byte
  1129. m_bManufIDH = ((MS_MANUFACTURER_ID >> 8) & 0x7f); // High byte
  1130. m_bProdID = JOLT_PRODUCT_ID; // Product ID
  1131. m_bAxisMask = X_AXIS|Y_AXIS;
  1132. m_bEffectID = NEW_EFFECT_ID; // Default to indicate create NEW
  1133. Effect.bDurationL = 1; // in 2ms increments
  1134. Effect.bDurationH = 0; // in 2ms increments
  1135. Effect.bAngleL = 0; // 0 to 359 degrees
  1136. Effect.bAngleH = 0;
  1137. Effect.bGain = (BYTE) 100; // 1 to 100 %
  1138. Effect.bButtonPlayL = (BYTE) ulButtonPlayMask & 0x7f;
  1139. Effect.bButtonPlayH = (BYTE) ((ulButtonPlayMask >> 7) & 0x03);// Button 1- 9
  1140. Effect.bForceOutRateL= DEFAULT_JOLT_FORCE_RATE; // 1 to 500 Hz
  1141. Effect.bForceOutRateH=0;
  1142. Effect.bPercentL = (BYTE) ((DEFAULT_PERCENT) & 0x7f);
  1143. Effect.bPercentH = (BYTE) ((DEFAULT_PERCENT >> 7 ) & 0x7f);
  1144. m_LoopCount = 1; // Default
  1145. SetPlayMode(PLAY_STORE); // Default
  1146. }
  1147. // ----------------------------------------------------------------------------
  1148. // Function: CMidiEffect::CMidiEffect
  1149. // Purpose: Constructor(s)/Destructor for CMidiEffect Object
  1150. // Parameters:
  1151. // Returns:
  1152. // Algorithm:
  1153. // ----------------------------------------------------------------------------
  1154. CMidiEffect::CMidiEffect(
  1155. IN PEFFECT pEffect,
  1156. IN PENVELOPE pEnvelope)
  1157. {
  1158. m_bSysExCmd = SYS_EX_CMD; // SysEx Fx command
  1159. m_bEscManufID = 0; // Escape to long Manufac. ID, s/b 0
  1160. m_bManufIDL = (MS_MANUFACTURER_ID & 0x7f); // Low byte
  1161. m_bManufIDH = ((MS_MANUFACTURER_ID >> 8) & 0x7f); // High byte
  1162. m_bProdID = JOLT_PRODUCT_ID; // Product ID
  1163. m_bAxisMask = X_AXIS|Y_AXIS;
  1164. m_OpCode = DNLOAD_DATA | X_AXIS|Y_AXIS; // Subcommand opcode:DNLOAD_DATA
  1165. m_bEffectID = NEW_EFFECT_ID; // Default to indicate create NEW
  1166. SetDuration(pEffect->m_Duration);
  1167. Effect.bDurationL = (BYTE) (m_Duration & 0x7f); // in 2ms increments
  1168. Effect.bDurationH = (BYTE) ((m_Duration >> 7 ) & 0x7f); // in 2ms increments
  1169. Effect.bAngleL = (BYTE) (pEffect->m_DirectionAngle2D & 0x7f); // 0 to 359 degrees
  1170. Effect.bAngleH = (BYTE) ((pEffect->m_DirectionAngle2D >> 7 ) & 0x7f);
  1171. Effect.bGain = (BYTE) (pEffect->m_Gain & 0x7f); // 1 to 100 %
  1172. Effect.bButtonPlayL = (BYTE) (pEffect->m_ButtonPlayMask & 0x7f);
  1173. Effect.bButtonPlayH = (BYTE) ((pEffect->m_ButtonPlayMask >> 7) & 0x03);// Button 1- 9
  1174. Effect.bForceOutRateL=(BYTE) (pEffect->m_ForceOutputRate & 0x7f); // 1 to 500 Hz
  1175. Effect.bForceOutRateH=(BYTE) ((pEffect->m_ForceOutputRate >> 7 ) & 0x03);
  1176. Effect.bPercentL = (BYTE) ((DEFAULT_PERCENT) & 0x7f);
  1177. Effect.bPercentH = (BYTE) ((DEFAULT_PERCENT >> 7 ) & 0x7f);
  1178. m_LoopCount = 1; // Default
  1179. SetPlayMode(PLAY_STORE); // Default
  1180. // Set Envelope members
  1181. if (pEnvelope)
  1182. {
  1183. m_Envelope.m_Type = pEnvelope->m_Type;
  1184. m_Envelope.m_Attack = pEnvelope->m_Attack;
  1185. m_Envelope.m_Sustain = pEnvelope->m_Sustain;
  1186. m_Envelope.m_Decay = pEnvelope->m_Decay;
  1187. m_Envelope.m_StartAmp = (ULONG) (pEnvelope->m_StartAmp);
  1188. m_Envelope.m_SustainAmp = (ULONG) (pEnvelope->m_SustainAmp);
  1189. m_Envelope.m_EndAmp = (ULONG) (pEnvelope->m_EndAmp);
  1190. }
  1191. // save the original effect params
  1192. m_OriginalEffectParam = *pEffect;
  1193. }
  1194. // --- Destructor
  1195. CMidiEffect::~CMidiEffect()
  1196. {
  1197. memset(this, 0, sizeof(CMidiEffect));
  1198. }
  1199. // ----------------------------------------------------------------------------
  1200. // Function: CMidiEffect::SetDuration
  1201. // Purpose: Sets the Duration member
  1202. // Parameters: ULONG ulArg - the duration
  1203. // Returns:
  1204. // Algorithm:
  1205. // ----------------------------------------------------------------------------
  1206. void CMidiEffect::SetDuration(ULONG ulArg)
  1207. {
  1208. if (ulArg != 0)
  1209. {
  1210. ulArg = (ULONG) ( (float) ulArg/TICKRATE);
  1211. if (ulArg <= 0) ulArg = 1;
  1212. }
  1213. m_Duration = ulArg;
  1214. }
  1215. // ----------------------------------------------------------------------------
  1216. // Function: CMidiEffect::SetTotalDuration
  1217. // Purpose: Modifies the Effect.bDurationL/H parameter for Loop Counts
  1218. // Parameters: none
  1219. //
  1220. // Returns: Effect.bDurationL/H is filled with total duration
  1221. // Algorithm:
  1222. // Notes: Percentage is 1 to 10000
  1223. // Total Duration = ((Percentage of waveform)/10000) * Duration * Loop Count
  1224. // Example: Loop count of 1, the Percentage of waveform =10000,
  1225. // Total Duration = (10000/10000) * 1 * Duration
  1226. //
  1227. // ----------------------------------------------------------------------------
  1228. void CMidiEffect::SetTotalDuration(void)
  1229. {
  1230. ULONG ulPercent = Effect.bPercentL + ((USHORT)Effect.bPercentH << 7);
  1231. ULONG ulTotalDuration = (ULONG) (((float) ulPercent/10000.0)
  1232. * (float) m_LoopCount
  1233. * (float) m_Duration );
  1234. Effect.bDurationL = (BYTE) ulTotalDuration & 0x7f;
  1235. Effect.bDurationH = (BYTE) (ulTotalDuration >> 7) & 0x7f;
  1236. }
  1237. // ----------------------------------------------------------------------------
  1238. // Function: CMidiEffect::ComputeEnvelope
  1239. // Purpose: Computes the Envelope for the Effect, Loopcount in consideration
  1240. // Parameters: none
  1241. // Returns: none
  1242. // Algorithm:
  1243. //For our standard PERCENTAGE Envelope, set the following as default:
  1244. //m_Type = PERCENTAGE
  1245. //
  1246. // Baseline is (m_MaxAmp + m_MinAmp)/2
  1247. // m_StartAmp = 0
  1248. // m_SustainAmp = Effect.m_MaxAmp - baseline
  1249. // m_EndAmp = m_StartAmp;
  1250. // where: baseline = (Effect.m_MaxAmp + Effect.m_MinAmp)/2;
  1251. // ----------------------------------------------------------------------------
  1252. void CMidiEffect::ComputeEnvelope(void)
  1253. {
  1254. ULONG ulTimeToSustain;
  1255. ULONG ulTimeToDecay;
  1256. //REVIEW: TIME vs PERCENTAGE option
  1257. if (PERCENTAGE == m_Envelope.m_Type)
  1258. {
  1259. ULONG ulPercent = Effect.bPercentL + ((USHORT)Effect.bPercentH << 7);
  1260. ULONG ulTotalDuration = (ULONG) (((float) ulPercent/10000.0)
  1261. * (float) m_LoopCount
  1262. * (float) m_Duration );
  1263. ulTimeToSustain = (ULONG) ((m_Envelope.m_Attack * ulTotalDuration) /100.);
  1264. ulTimeToDecay = (ULONG) ((m_Envelope.m_Attack + m_Envelope.m_Sustain)
  1265. * ulTotalDuration /100.);
  1266. }
  1267. else // TIME option envelope
  1268. {
  1269. ulTimeToSustain = (ULONG) (m_Envelope.m_Attack);
  1270. ulTimeToDecay = (ULONG) (m_Envelope.m_Attack + m_Envelope.m_Sustain);
  1271. ulTimeToSustain = (ULONG) ( (float) ulTimeToSustain/TICKRATE);
  1272. ulTimeToDecay = (ULONG) ( (float) ulTimeToDecay/TICKRATE);
  1273. }
  1274. Envelope.bAttackLevel = (BYTE) (m_Envelope.m_StartAmp & 0x7f);
  1275. Envelope.bSustainLevel = (BYTE) (m_Envelope.m_SustainAmp & 0x7f);
  1276. Envelope.bDecayLevel = (BYTE) (m_Envelope.m_EndAmp & 0x7f);
  1277. Envelope.bSustainL = (BYTE) (ulTimeToSustain & 0x7f);
  1278. Envelope.bSustainH = (BYTE) ((ulTimeToSustain >> 7) & 0x7f);
  1279. Envelope.bDecayL = (BYTE) (ulTimeToDecay & 0x7f);
  1280. Envelope.bDecayH = (BYTE) ((ulTimeToDecay >> 7) & 0x7f);
  1281. }
  1282. // ----------------------------------------------------------------------------
  1283. // Function: CMidiEffect::SubTypeOf
  1284. // Purpose: Returns the SubType for the Effect
  1285. // Parameters: none
  1286. // Returns: ULONG - DirectEffect style SubType
  1287. // Algorithm:
  1288. // ----------------------------------------------------------------------------
  1289. ULONG CMidiEffect::SubTypeOf(void)
  1290. {
  1291. static EFFECT_TYPE EffectTypes[] = {
  1292. {BE_SPRING , ET_BE_SPRING},
  1293. {BE_SPRING_2D , ET_BE_SPRING},
  1294. {BE_DAMPER , ET_BE_DAMPER},
  1295. {BE_DAMPER_2D , ET_BE_DAMPER},
  1296. {BE_INERTIA , ET_BE_INERTIA},
  1297. {BE_INERTIA_2D , ET_BE_INERTIA},
  1298. {BE_FRICTION , ET_BE_FRICTION},
  1299. {BE_FRICTION_2D , ET_BE_FRICTION},
  1300. {BE_WALL , ET_BE_WALL},
  1301. {BE_DELAY , ET_BE_DELAY},
  1302. {SE_CONSTANT_FORCE , ET_SE_CONSTANT_FORCE},
  1303. {SE_SINE , ET_SE_SINE},
  1304. {SE_COSINE , ET_SE_COSINE},
  1305. {SE_SQUARELOW , ET_SE_SQUARELOW},
  1306. {SE_SQUAREHIGH , ET_SE_SQUAREHIGH},
  1307. {SE_RAMPUP , ET_SE_RAMPUP},
  1308. {SE_RAMPDOWN , ET_SE_RAMPDOWN},
  1309. {SE_TRIANGLEUP , ET_SE_TRIANGLEUP},
  1310. {SE_TRIANGLEDOWN , ET_SE_TRIANGLEDOWN},
  1311. {SE_SAWTOOTHUP , ET_SE_SAWTOOTHUP},
  1312. {SE_SAWTOOTHDOWN , ET_SE_SAWTOOTHDOWN},
  1313. {PL_CONCATENATE , ET_PL_CONCATENATE},
  1314. {PL_SUPERIMPOSE , ET_PL_SUPERIMPOSE},
  1315. {RE_ROMID1 , ET_RE_ROMID1 },
  1316. {RE_ROMID2 , ET_RE_ROMID2 },
  1317. {RE_ROMID3 , ET_RE_ROMID3 },
  1318. {RE_ROMID4 , ET_RE_ROMID4 },
  1319. {RE_ROMID5 , ET_RE_ROMID5 },
  1320. {RE_ROMID6 , ET_RE_ROMID6 },
  1321. {RE_ROMID7 , ET_RE_ROMID7 },
  1322. {RE_ROMID8 , ET_RE_ROMID8 },
  1323. {RE_ROMID9 , ET_RE_ROMID9 },
  1324. {RE_ROMID10 , ET_RE_ROMID10 },
  1325. {RE_ROMID11 , ET_RE_ROMID11 },
  1326. {RE_ROMID12 , ET_RE_ROMID12 },
  1327. {RE_ROMID13 , ET_RE_ROMID13 },
  1328. {RE_ROMID14 , ET_RE_ROMID14 },
  1329. {RE_ROMID15 , ET_RE_ROMID15 },
  1330. {RE_ROMID16 , ET_RE_ROMID16 },
  1331. {RE_ROMID17 , ET_RE_ROMID17 },
  1332. {RE_ROMID18 , ET_RE_ROMID18 },
  1333. {RE_ROMID19 , ET_RE_ROMID19 },
  1334. {RE_ROMID20 , ET_RE_ROMID20 },
  1335. {RE_ROMID21 , ET_RE_ROMID21 },
  1336. {RE_ROMID22 , ET_RE_ROMID22 },
  1337. {RE_ROMID23 , ET_RE_ROMID23 },
  1338. {RE_ROMID24 , ET_RE_ROMID24 },
  1339. {RE_ROMID25 , ET_RE_ROMID25 },
  1340. {RE_ROMID26 , ET_RE_ROMID26 },
  1341. {RE_ROMID27 , ET_RE_ROMID27 },
  1342. {RE_ROMID28 , ET_RE_ROMID28 },
  1343. {RE_ROMID29 , ET_RE_ROMID29 },
  1344. {RE_ROMID30 , ET_RE_ROMID30 },
  1345. {RE_ROMID31 , ET_RE_ROMID31 },
  1346. {RE_ROMID32 , ET_RE_ROMID32 }};
  1347. int nNumEffectTypes = sizeof(EffectTypes)/(sizeof(EFFECT_TYPE));
  1348. for (int i=0; i<nNumEffectTypes; i++)
  1349. {
  1350. if (m_SubType == EffectTypes[i].bDeviceSubType)
  1351. return EffectTypes[i].ulHostSubType;
  1352. }
  1353. return (NULL);
  1354. }
  1355. // ----------------------------------------------------------------------------
  1356. // Function: CMidiEffect::SubTypeOf
  1357. // Purpose: Sets the SubType for the Effect
  1358. // Parameters: ULONG - DirectEffect style SubType
  1359. // Returns: none
  1360. // Algorithm:
  1361. // ----------------------------------------------------------------------------
  1362. void CMidiEffect::SetSubType(ULONG ulSubType)
  1363. {
  1364. static EFFECT_TYPE EffectTypes[] = {
  1365. {BE_SPRING , ET_BE_SPRING},
  1366. {BE_SPRING_2D , ET_BE_SPRING},
  1367. {BE_DAMPER , ET_BE_DAMPER},
  1368. {BE_DAMPER_2D , ET_BE_DAMPER},
  1369. {BE_INERTIA , ET_BE_INERTIA},
  1370. {BE_INERTIA_2D , ET_BE_INERTIA},
  1371. {BE_FRICTION , ET_BE_FRICTION},
  1372. {BE_FRICTION_2D , ET_BE_FRICTION},
  1373. {BE_WALL , ET_BE_WALL},
  1374. {BE_DELAY , ET_BE_DELAY},
  1375. {SE_CONSTANT_FORCE , ET_SE_CONSTANT_FORCE},
  1376. {SE_SINE , ET_SE_SINE},
  1377. {SE_COSINE , ET_SE_COSINE},
  1378. {SE_SQUARELOW , ET_SE_SQUARELOW},
  1379. {SE_SQUAREHIGH , ET_SE_SQUAREHIGH},
  1380. {SE_RAMPUP , ET_SE_RAMPUP},
  1381. {SE_RAMPDOWN , ET_SE_RAMPDOWN},
  1382. {SE_TRIANGLEUP , ET_SE_TRIANGLEUP},
  1383. {SE_TRIANGLEDOWN , ET_SE_TRIANGLEDOWN},
  1384. {SE_SAWTOOTHUP , ET_SE_SAWTOOTHUP},
  1385. {SE_SAWTOOTHDOWN , ET_SE_SAWTOOTHDOWN},
  1386. {PL_CONCATENATE , ET_PL_CONCATENATE},
  1387. {PL_SUPERIMPOSE , ET_PL_SUPERIMPOSE},
  1388. {RE_ROMID1 , ET_RE_ROMID1 },
  1389. {RE_ROMID2 , ET_RE_ROMID2 },
  1390. {RE_ROMID3 , ET_RE_ROMID3 },
  1391. {RE_ROMID4 , ET_RE_ROMID4 },
  1392. {RE_ROMID5 , ET_RE_ROMID5 },
  1393. {RE_ROMID6 , ET_RE_ROMID6 },
  1394. {RE_ROMID7 , ET_RE_ROMID7 },
  1395. {RE_ROMID8 , ET_RE_ROMID8 },
  1396. {RE_ROMID9 , ET_RE_ROMID9 },
  1397. {RE_ROMID10 , ET_RE_ROMID10 },
  1398. {RE_ROMID11 , ET_RE_ROMID11 },
  1399. {RE_ROMID12 , ET_RE_ROMID12 },
  1400. {RE_ROMID13 , ET_RE_ROMID13 },
  1401. {RE_ROMID14 , ET_RE_ROMID14 },
  1402. {RE_ROMID15 , ET_RE_ROMID15 },
  1403. {RE_ROMID16 , ET_RE_ROMID16 },
  1404. {RE_ROMID17 , ET_RE_ROMID17 },
  1405. {RE_ROMID18 , ET_RE_ROMID18 },
  1406. {RE_ROMID19 , ET_RE_ROMID19 },
  1407. {RE_ROMID20 , ET_RE_ROMID20 },
  1408. {RE_ROMID21 , ET_RE_ROMID21 },
  1409. {RE_ROMID22 , ET_RE_ROMID22 },
  1410. {RE_ROMID23 , ET_RE_ROMID23 },
  1411. {RE_ROMID24 , ET_RE_ROMID24 },
  1412. {RE_ROMID25 , ET_RE_ROMID25 },
  1413. {RE_ROMID26 , ET_RE_ROMID26 },
  1414. {RE_ROMID27 , ET_RE_ROMID27 },
  1415. {RE_ROMID28 , ET_RE_ROMID28 },
  1416. {RE_ROMID29 , ET_RE_ROMID29 },
  1417. {RE_ROMID30 , ET_RE_ROMID30 },
  1418. {RE_ROMID31 , ET_RE_ROMID31 },
  1419. {RE_ROMID32 , ET_RE_ROMID32 }};
  1420. int nNumEffectTypes = sizeof(EffectTypes)/(sizeof(EFFECT_TYPE));
  1421. for (int i=0; i<nNumEffectTypes; i++)
  1422. {
  1423. if (ulSubType == EffectTypes[i].ulHostSubType)
  1424. {
  1425. m_SubType = EffectTypes[i].bDeviceSubType;
  1426. return;
  1427. }
  1428. }
  1429. m_SubType = NULL;
  1430. }
  1431. // ----------------------------------------------------------------------------
  1432. // Function: CMidiEffect::ComputeChecksum
  1433. // Purpose: Computes current checksum in the m_pBuffer
  1434. // Parameters: none
  1435. // Returns: Midi packet block is checksummed
  1436. // Algorithm:
  1437. // ----------------------------------------------------------------------------
  1438. BYTE CMidiEffect::ComputeChecksum(PBYTE pBuffer, int nBufferSize)
  1439. {
  1440. assert(pBuffer);
  1441. int nStart = sizeof(SYS_EX_HDR);
  1442. PBYTE pBytePacket = pBuffer;
  1443. pBytePacket += nStart;
  1444. BYTE nSum = 0;
  1445. // Checksum only the bytes in the "Body" and s/b 7 bit checksum.
  1446. for (int i=nStart;i < (nBufferSize-2);i++)
  1447. {
  1448. nSum += *pBytePacket;
  1449. pBytePacket++;
  1450. }
  1451. return ((-nSum) & 0x7f);
  1452. }
  1453. // ----------------------------------------------------------------------------
  1454. // Function: CMidiEffect::SendPacket
  1455. // Purpose: Sends the SYS_EX Packet
  1456. // Parameters: PDNHANDLE pDnloadID - Pointer to DnloadID
  1457. // int nPacketSize - Size of SysEx packet
  1458. //
  1459. // Returns: *pDnloadID is filled.
  1460. // else Error code
  1461. // Algorithm:
  1462. // ----------------------------------------------------------------------------
  1463. HRESULT CMidiEffect::SendPacket(PDNHANDLE pDnloadID, int nPacketSize)
  1464. {
  1465. ASSUME_NOT_REACHED();
  1466. return SUCCESS;
  1467. }
  1468. // ----------------------------------------------------------------------------
  1469. // Function: CMidiEffect::DestroyEffect
  1470. // Purpose: Sends the SYS_EX Packet
  1471. // Parameters: PDNHANDLE pDnloadID - Pointer to DnloadID
  1472. // int nPacketSize - Size of SysEx packet
  1473. //
  1474. // Returns: *pDnloadID is filled.
  1475. // else Error code
  1476. // Algorithm:
  1477. // ----------------------------------------------------------------------------
  1478. HRESULT CMidiEffect::DestroyEffect()
  1479. {
  1480. ASSUME_NOT_REACHED();
  1481. return SUCCESS;
  1482. }
  1483. // ****************************************************************************
  1484. // *** --- Member functions for derived class CMidiBehavioral
  1485. //
  1486. // ****************************************************************************
  1487. //
  1488. // ----------------------------------------------------------------------------
  1489. // Function: CMidiBehavioral::CMidiBehavioral
  1490. // Purpose: Constructor(s)/Destructor for CMidiBehavioral Object
  1491. // Parameters:
  1492. // Returns:
  1493. // Algorithm:
  1494. // ----------------------------------------------------------------------------
  1495. CMidiBehavioral::CMidiBehavioral(PEFFECT pEffect, PENVELOPE pEnvelope,
  1496. PBE_XXX pBE_XXX):CMidiEffect(pEffect, NULL)
  1497. {
  1498. SetSubType(pEffect->m_SubType);
  1499. SetXConstant(pBE_XXX->m_XConstant);
  1500. SetYConstant(pBE_XXX->m_YConstant);
  1501. SetParam3(pBE_XXX->m_Param3);
  1502. SetParam4(pBE_XXX->m_Param4);
  1503. m_MidiBufferSize = sizeof(BEHAVIORAL_SYS_EX);
  1504. }
  1505. // --- Destructor
  1506. CMidiBehavioral::~CMidiBehavioral()
  1507. {
  1508. memset(this, 0, sizeof(CMidiBehavioral));
  1509. }
  1510. // ----------------------------------------------------------------------------
  1511. // Function: CMidiBehavioral::SetEffect
  1512. // Purpose: Sets the common MIDI_EFFECT parameters
  1513. // Parameters: PEFFECT pEffect
  1514. // Returns: none
  1515. // Algorithm:
  1516. // ----------------------------------------------------------------------------
  1517. void CMidiBehavioral::SetEffectParams(PEFFECT pEffect, PBE_XXX pBE_XXX)
  1518. {
  1519. // Set the MIDI_EFFECT parameters
  1520. SetDuration(pEffect->m_Duration);
  1521. SetButtonPlaymask(pEffect->m_ButtonPlayMask);
  1522. SetAxisMask(X_AXIS|Y_AXIS);
  1523. SetDirectionAngle(pEffect->m_DirectionAngle2D);
  1524. SetGain((BYTE) (pEffect->m_Gain));
  1525. SetForceOutRate(pEffect->m_ForceOutputRate);
  1526. Effect.bPercentL = (BYTE) (DEFAULT_PERCENT & 0x7f);
  1527. Effect.bPercentH = (BYTE) ((DEFAULT_PERCENT >> 7) & 0x7f);
  1528. // set the type specific parameters for BE_XXX
  1529. SetXConstant(pBE_XXX->m_XConstant);
  1530. SetYConstant(pBE_XXX->m_YConstant);
  1531. SetParam3(pBE_XXX->m_Param3);
  1532. SetParam4(pBE_XXX->m_Param4);
  1533. }
  1534. // ----------------------------------------------------------------------------
  1535. // Function: CMidiBehavioral::GenerateSysExPacket
  1536. // Purpose: Builds the SysEx packet into the pBuf
  1537. // Parameters: none
  1538. // Returns: PBYTE - pointer to a buffer filled with SysEx Packet
  1539. // Algorithm:
  1540. // ----------------------------------------------------------------------------
  1541. PBYTE CMidiBehavioral::GenerateSysExPacket(void)
  1542. {
  1543. if(NULL == g_pJoltMidi) return ((PBYTE) NULL);
  1544. PBYTE pSysExBuffer = g_pJoltMidi->PrimaryBufferPtrOf();
  1545. assert(pSysExBuffer);
  1546. // Copy SysEx Header + m_OpCode + m_SubType
  1547. memcpy(pSysExBuffer, &m_bSysExCmd, sizeof(SYS_EX_HDR)+2 );
  1548. PBEHAVIORAL_SYS_EX pBuf = (PBEHAVIORAL_SYS_EX) pSysExBuffer;
  1549. SetTotalDuration(); // Compute total with Loop count parameter
  1550. pBuf->bDurationL = (BYTE) (Effect.bDurationL & 0x7f);
  1551. pBuf->bDurationH = (BYTE) (Effect.bDurationH & 0x7f);
  1552. pBuf->bButtonPlayL = (BYTE) (Effect.bButtonPlayL & 0x7f);
  1553. pBuf->bButtonPlayH = (BYTE) (Effect.bButtonPlayH & 0x7f);
  1554. // Behavioral params
  1555. LONG XConstant = (LONG) (XConstantOf() * MAX_SCALE);
  1556. LONG YConstant = (LONG) (YConstantOf() * MAX_SCALE);
  1557. pBuf->bXConstantL = (BYTE) XConstant & 0x7f;
  1558. pBuf->bXConstantH = (BYTE) (XConstant >> 7 ) & 0x01;
  1559. pBuf->bYConstantL = (BYTE) YConstant & 0x7f;
  1560. pBuf->bYConstantH = (BYTE) (YConstant >> 7 ) & 0x01;
  1561. LONG Param3 = (LONG) (Param3Of() * MAX_SCALE);
  1562. LONG Param4 = (LONG) (Param4Of() * MAX_SCALE);
  1563. pBuf->bParam3L = (BYTE) Param3 & 0x7f;
  1564. pBuf->bParam3H = (BYTE) (Param3 >> 7 ) & 0x01;
  1565. pBuf->bParam4L = (BYTE) Param4 & 0x7f;
  1566. pBuf->bParam4H = (BYTE) (Param4 >> 7 ) & 0x01;
  1567. pBuf->bEffectID = m_bEffectID;
  1568. pBuf->bChecksum = ComputeChecksum((PBYTE) pSysExBuffer,
  1569. sizeof(BEHAVIORAL_SYS_EX));
  1570. pBuf->bEOX = MIDI_EOX;
  1571. return ((PBYTE) pSysExBuffer);
  1572. }
  1573. // ****************************************************************************
  1574. // *** --- Member functions for derived class CMidiFriction
  1575. //
  1576. // ****************************************************************************
  1577. //
  1578. // ----------------------------------------------------------------------------
  1579. // Function: CMidiFriction::CMidiFriction
  1580. // Purpose: Constructor(s)/Destructor for CMidiFriction Object
  1581. // Parameters:
  1582. // Returns:
  1583. // Algorithm:
  1584. // ----------------------------------------------------------------------------
  1585. CMidiFriction::CMidiFriction(PEFFECT pEffect, PENVELOPE pEnvelope,
  1586. PBE_XXX pBE_XXX):CMidiBehavioral(pEffect, NULL, pBE_XXX)
  1587. {
  1588. m_MidiBufferSize = sizeof(FRICTION_SYS_EX);
  1589. }
  1590. // --- Destructor
  1591. CMidiFriction::~CMidiFriction()
  1592. {
  1593. memset(this, 0, sizeof(CMidiFriction));
  1594. }
  1595. // ----------------------------------------------------------------------------
  1596. // Function: CMidiFriction::GenerateSysExPacket
  1597. // Purpose: Builds the SysEx packet into the pBuf
  1598. // Parameters: none
  1599. // Returns: PBYTE - pointer to a buffer filled with SysEx Packet
  1600. // Algorithm:
  1601. // ----------------------------------------------------------------------------
  1602. PBYTE CMidiFriction::GenerateSysExPacket(void)
  1603. {
  1604. if(NULL == g_pJoltMidi) return ((PBYTE) NULL);
  1605. PBYTE pSysExBuffer = g_pJoltMidi->PrimaryBufferPtrOf();
  1606. assert(pSysExBuffer);
  1607. // Copy SysEx Header + m_OpCode + m_SubType
  1608. memcpy(pSysExBuffer, &m_bSysExCmd, sizeof(SYS_EX_HDR)+2 );
  1609. PFRICTION_SYS_EX pBuf = (PFRICTION_SYS_EX) pSysExBuffer;
  1610. SetTotalDuration(); // Compute total with Loop count parameter
  1611. pBuf->bDurationL = (BYTE) (Effect.bDurationL & 0x7f);
  1612. pBuf->bDurationH = (BYTE) (Effect.bDurationH & 0x7f);
  1613. pBuf->bButtonPlayL = (BYTE) (Effect.bButtonPlayL & 0x7f);
  1614. pBuf->bButtonPlayH = (BYTE) (Effect.bButtonPlayH & 0x7f);
  1615. // BE_FRICTION params
  1616. LONG XConstant = (LONG) (XConstantOf() * MAX_SCALE);
  1617. LONG YConstant = (LONG) (YConstantOf() * MAX_SCALE);
  1618. pBuf->bXFConstantL = (BYTE) XConstant & 0x7f;
  1619. pBuf->bXFConstantH = (BYTE) (XConstant >> 7 ) & 0x01;
  1620. pBuf->bYFConstantL = (BYTE) YConstant & 0x7f;
  1621. pBuf->bYFConstantH = (BYTE) (YConstant >> 7 ) & 0x01;
  1622. pBuf->bEffectID = m_bEffectID;
  1623. pBuf->bChecksum = ComputeChecksum((PBYTE) pSysExBuffer,
  1624. sizeof(FRICTION_SYS_EX));
  1625. pBuf->bEOX = MIDI_EOX;
  1626. return ((PBYTE) pSysExBuffer);
  1627. }
  1628. // ****************************************************************************
  1629. // *** --- Member functions for derived class CMidiWall
  1630. //
  1631. // ****************************************************************************
  1632. //
  1633. // ----------------------------------------------------------------------------
  1634. // Function: CMidiWall::CMidiWall
  1635. // Purpose: Constructor(s)/Destructor for CMidiWall Object
  1636. // Parameters:
  1637. // Returns:
  1638. // Algorithm:
  1639. // ----------------------------------------------------------------------------
  1640. CMidiWall::CMidiWall(PEFFECT pEffect, PENVELOPE pEnvelope,
  1641. PBE_XXX pBE_XXX):CMidiBehavioral(pEffect, NULL, pBE_XXX)
  1642. {
  1643. m_MidiBufferSize = sizeof(WALL_SYS_EX);
  1644. }
  1645. // --- Destructor
  1646. CMidiWall::~CMidiWall()
  1647. {
  1648. memset(this, 0, sizeof(CMidiWall));
  1649. }
  1650. // ----------------------------------------------------------------------------
  1651. // Function: CMidiWall::GenerateSysExPacket
  1652. // Purpose: Builds the SysEx packet into the pBuf
  1653. // Parameters: none
  1654. // Returns: PBYTE - pointer to a buffer filled with SysEx Packet
  1655. // Algorithm:
  1656. // ----------------------------------------------------------------------------
  1657. PBYTE CMidiWall::GenerateSysExPacket(void)
  1658. {
  1659. if(NULL == g_pJoltMidi) return ((PBYTE) NULL);
  1660. PBYTE pSysExBuffer = g_pJoltMidi->PrimaryBufferPtrOf();
  1661. assert(pSysExBuffer);
  1662. // Copy SysEx Header + m_OpCode + m_SubType
  1663. memcpy(pSysExBuffer, &m_bSysExCmd, sizeof(SYS_EX_HDR)+2 );
  1664. PWALL_SYS_EX pBuf = (PWALL_SYS_EX) pSysExBuffer;
  1665. SetTotalDuration(); // Compute total with Loop count parameter
  1666. pBuf->bDurationL = (BYTE) (Effect.bDurationL & 0x7f);
  1667. pBuf->bDurationH = (BYTE) (Effect.bDurationH & 0x7f);
  1668. pBuf->bButtonPlayL = (BYTE) (Effect.bButtonPlayL & 0x7f);
  1669. pBuf->bButtonPlayH = (BYTE) (Effect.bButtonPlayH & 0x7f);
  1670. // BE_WALL params
  1671. LONG WallType = (LONG) (XConstantOf());
  1672. LONG WallConstant = (LONG) (YConstantOf() * MAX_SCALE);
  1673. LONG WallAngle = (LONG) Param3Of();
  1674. LONG WallDistance = (LONG) (Param4Of() * MAX_SCALE);
  1675. pBuf->bWallType = (BYTE) (WallType & 0x01);
  1676. pBuf->bWallConstantL = (BYTE) (WallConstant & 0x7f);
  1677. pBuf->bWallConstantH = (BYTE) ((WallConstant >> 7 ) & 0x01); //+/-100
  1678. pBuf->bWallAngleL = (BYTE) (WallAngle & 0x7f); // 0 to 359
  1679. pBuf->bWallAngleH = (BYTE) ((WallAngle >> 7 ) & 0x03);
  1680. pBuf->bWallDistance = (BYTE) (WallDistance & 0x7f);
  1681. pBuf->bEffectID = m_bEffectID;
  1682. pBuf->bChecksum = ComputeChecksum((PBYTE) pSysExBuffer,
  1683. sizeof(WALL_SYS_EX));
  1684. pBuf->bEOX = MIDI_EOX;
  1685. return ((PBYTE) pSysExBuffer);
  1686. }
  1687. // ****************************************************************************
  1688. // *** --- Member functions for derived class CMidiRTCSpring
  1689. //
  1690. // ****************************************************************************
  1691. //
  1692. // ----------------------------------------------------------------------------
  1693. // Function: CMidiRTCSpring::CMidiRTCSpring
  1694. // Purpose: Constructor(s)/Destructor for CMidiRTCSpring Object
  1695. // Parameters:
  1696. // Returns:
  1697. // Algorithm:
  1698. // ----------------------------------------------------------------------------
  1699. CMidiRTCSpring::CMidiRTCSpring(PRTCSPRING_PARAM pRTCSpring):CMidiEffect(NULL)
  1700. {
  1701. memcpy(&m_RTCSPRINGParam, pRTCSpring, sizeof(RTCSPRING_PARAM));
  1702. }
  1703. // --- Destructor
  1704. CMidiRTCSpring::~CMidiRTCSpring()
  1705. {
  1706. memset(this, 0, sizeof(CMidiRTCSpring));
  1707. }
  1708. // ----------------------------------------------------------------------------
  1709. // Function: CMidiRTCSpring::SetEffectParams
  1710. // Purpose: Sets parameters
  1711. // Parameters:
  1712. // Returns:
  1713. // Algorithm:
  1714. // ----------------------------------------------------------------------------
  1715. void CMidiRTCSpring::SetEffectParams(PRTCSPRING_PARAM pRTCSpring)
  1716. {
  1717. memcpy(&m_RTCSPRINGParam, pRTCSpring, sizeof(RTCSPRING_PARAM));
  1718. }
  1719. // ----------------------------------------------------------------------------
  1720. // Function: CMidiRTCSpring::GenerateSysExPacket
  1721. // Purpose: virtual
  1722. // Parameters: none
  1723. // Returns:
  1724. // Algorithm:
  1725. // ----------------------------------------------------------------------------
  1726. PBYTE CMidiRTCSpring::GenerateSysExPacket(void)
  1727. {
  1728. return (NULL);
  1729. }
  1730. // ****************************************************************************
  1731. // *** --- Member functions for derived class CMidiDelay
  1732. //
  1733. // ****************************************************************************
  1734. //
  1735. // ----------------------------------------------------------------------------
  1736. // Function: CMidiDelay::CMidiDelay
  1737. // Purpose: Constructor(s)/Destructor for CMidiDelay Object
  1738. // Parameters:
  1739. // Returns:
  1740. // Algorithm:
  1741. // ----------------------------------------------------------------------------
  1742. CMidiDelay::CMidiDelay(PEFFECT pEffect) : CMidiEffect(pEffect, NULL)
  1743. {
  1744. m_SubType = ET_BE_DELAY; // BE Effect Type: BE_DELAY
  1745. m_OpCode = DNLOAD_DATA | X_AXIS|Y_AXIS | PLAY_SUPERIMPOSE;
  1746. m_MidiBufferSize = sizeof(NOP_SYS_EX);
  1747. }
  1748. // --- Destructor
  1749. CMidiDelay::~CMidiDelay()
  1750. {
  1751. memset(this, 0, sizeof(CMidiDelay));
  1752. }
  1753. // ----------------------------------------------------------------------------
  1754. // Function: CMidiDelay::GenerateSysExPacket
  1755. // Purpose: Builds the SysEx packet into the pBuf
  1756. // Parameters: none
  1757. // Returns: PBYTE - pointer to a buffer filled with SysEx Packet
  1758. // Algorithm:
  1759. // ----------------------------------------------------------------------------
  1760. PBYTE CMidiDelay::GenerateSysExPacket(void)
  1761. {
  1762. if(NULL == g_pJoltMidi) return ((PBYTE) NULL);
  1763. PBYTE pSysExBuffer = g_pJoltMidi->PrimaryBufferPtrOf();
  1764. assert(pSysExBuffer);
  1765. // Copy SysEx Header + m_OpCode + m_SubType
  1766. memcpy(pSysExBuffer, &m_bSysExCmd, sizeof(SYS_EX_HDR)+2 );
  1767. PNOP_SYS_EX pBuf = (PNOP_SYS_EX) pSysExBuffer;
  1768. pBuf->bEffectID = m_bEffectID;
  1769. SetTotalDuration(); // Compute total with Loop count parameter
  1770. pBuf->bDurationL = (BYTE) (Effect.bDurationL & 0x7f);
  1771. pBuf->bDurationH = (BYTE) (Effect.bDurationH & 0x7f);
  1772. pBuf->bChecksum = ComputeChecksum((PBYTE) pSysExBuffer,
  1773. sizeof(NOP_SYS_EX));
  1774. pBuf->bEOX = MIDI_EOX;
  1775. return ((PBYTE) pSysExBuffer);
  1776. }
  1777. // ****************************************************************************
  1778. // *** --- Member functions for derived class CMidiSynthesized
  1779. //
  1780. // ****************************************************************************
  1781. //
  1782. // ----------------------------------------------------------------------------
  1783. // Function: CMidiSynthesized::CMidiSynthesized
  1784. // Purpose: Constructor(s)/Destructor for CMidiSynthesized Object
  1785. // Parameters:
  1786. // Returns:
  1787. // Algorithm:
  1788. // ----------------------------------------------------------------------------
  1789. CMidiSynthesized::CMidiSynthesized(PEFFECT pEffect, PENVELOPE pEnvelope,
  1790. PSE_PARAM pParam ) : CMidiEffect(pEffect, pEnvelope)
  1791. {
  1792. SetSubType(pEffect->m_SubType); // SE Effect Type
  1793. // Effect.bForceOutRateL= (BYTE) pParam->m_SampleRate & 0x7f; // 1 to 500 Hz
  1794. // Effect.bForceOutRateH= (BYTE) ((pParam->m_SampleRate >> 7) & 0x3);
  1795. Effect.bPercentL = (BYTE) (DEFAULT_PERCENT & 0x7f);
  1796. Effect.bPercentH = (BYTE) ((DEFAULT_PERCENT >> 7) & 0x7f);
  1797. m_Freq = pParam->m_Freq; // Frequency
  1798. m_MaxAmp = pParam->m_MaxAmp; // Maximum Amplitude
  1799. // Special case a SE_CONSTANT_FORCE
  1800. if (SE_CONSTANT_FORCE == pEffect->m_SubType)
  1801. m_MinAmp = 0;
  1802. else
  1803. m_MinAmp = pParam->m_MinAmp; // Minimum Amplitude
  1804. m_MidiBufferSize = sizeof(SE_WAVEFORM_SYS_EX);
  1805. }
  1806. // --- Destructor
  1807. CMidiSynthesized::~CMidiSynthesized()
  1808. {
  1809. memset(this, 0, sizeof(CMidiSynthesized));
  1810. }
  1811. // ----------------------------------------------------------------------------
  1812. // Function: CMidiSynthesized::SetEffect
  1813. // Purpose: Sets the common MIDI_EFFECT parameters
  1814. // Parameters: PEFFECT pEffect
  1815. // Returns: none
  1816. // Algorithm:
  1817. // ----------------------------------------------------------------------------
  1818. void CMidiSynthesized::SetEffectParams(PEFFECT pEffect, PSE_PARAM pParam,
  1819. ULONG ulAction)
  1820. {
  1821. // Set the MIDI_EFFECT parameters
  1822. SetDuration(pEffect->m_Duration);
  1823. SetButtonPlaymask(pEffect->m_ButtonPlayMask);
  1824. SetAxisMask(X_AXIS|Y_AXIS);
  1825. SetDirectionAngle(pEffect->m_DirectionAngle2D);
  1826. SetGain((BYTE) (pEffect->m_Gain));
  1827. SetForceOutRate(pEffect->m_ForceOutputRate);
  1828. //Set the loop count from HIWORD of ulAction
  1829. m_LoopCount = (ulAction >> 16) & 0xffff;
  1830. if (0 == m_LoopCount) m_LoopCount++;
  1831. Effect.bPercentL = (BYTE) (DEFAULT_PERCENT & 0x7f);
  1832. Effect.bPercentH = (BYTE) ((DEFAULT_PERCENT >> 7) & 0x7f);
  1833. // set the type specific parameters for SE_xxx
  1834. m_Freq = pParam->m_Freq;
  1835. m_MaxAmp = pParam->m_MaxAmp;
  1836. m_MinAmp = pParam->m_MinAmp;
  1837. }
  1838. // ----------------------------------------------------------------------------
  1839. // Function: CMidiSynthesized::GenerateSysExPacket
  1840. // Purpose: Builds the SysEx packet into the pBuf
  1841. // Parameters: none
  1842. // Returns: PBYTE - pointer to a buffer filled with SysEx Packet
  1843. // Algorithm:
  1844. // ----------------------------------------------------------------------------
  1845. PBYTE CMidiSynthesized::GenerateSysExPacket(void)
  1846. {
  1847. if(NULL == g_pJoltMidi) return ((PBYTE) NULL);
  1848. PBYTE pSysExBuffer = g_pJoltMidi->PrimaryBufferPtrOf();
  1849. assert(pSysExBuffer);
  1850. // Compute total with Loop count parameter, Note: Envelope parameters are
  1851. // adjusted according to the Loop Count parameter, if affected.
  1852. SetTotalDuration();
  1853. ComputeEnvelope();
  1854. // Copy SysEx Header + m_OpCode + m_SubType + m_bEffectID + MIDI_EFFECT
  1855. // + MIDI_ENVELOPE
  1856. memcpy(pSysExBuffer,&m_bSysExCmd, (sizeof(SYS_EX_HDR)+3+sizeof(MIDI_EFFECT)+
  1857. sizeof(MIDI_ENVELOPE)) );
  1858. PSE_WAVEFORM_SYS_EX pBuf = (PSE_WAVEFORM_SYS_EX) pSysExBuffer;
  1859. // Scale the gain, and Envelope amplitudes
  1860. pBuf->Effect.bGain = (BYTE) (pBuf->Effect.bGain * MAX_SCALE) & 0x7f;
  1861. pBuf->Envelope.bAttackLevel = (BYTE) (pBuf->Envelope.bAttackLevel * MAX_SCALE) & 0x7f;
  1862. pBuf->Envelope.bSustainLevel = (BYTE) (pBuf->Envelope.bSustainLevel * MAX_SCALE) & 0x7f;
  1863. pBuf->Envelope.bDecayLevel = (BYTE) (pBuf->Envelope.bDecayLevel * MAX_SCALE) & 0x7f;
  1864. // Copy the SE specific parameters
  1865. LONG MaxAmp = (LONG) (m_MaxAmp * MAX_SCALE);
  1866. LONG MinAmp = (LONG) (m_MinAmp * MAX_SCALE);
  1867. pBuf->bFreqL = (BYTE) (m_Freq & 0x7f);
  1868. pBuf->bFreqH = (BYTE) ((m_Freq >> 7 ) & 0x03); // 1 to 500
  1869. pBuf->bMaxAmpL = (BYTE) (MaxAmp & 0x7f);
  1870. pBuf->bMaxAmpH = (BYTE) ((MaxAmp >> 7 ) &0x01); // +127 to -128
  1871. pBuf->bMinAmpL = (BYTE) (MinAmp & 0x7f);
  1872. pBuf->bMinAmpH = (BYTE) ((MinAmp >> 7 ) & 0x01);
  1873. pBuf->bChecksum = ComputeChecksum((PBYTE) pSysExBuffer,
  1874. sizeof(SE_WAVEFORM_SYS_EX));
  1875. pBuf->bEOX = MIDI_EOX;
  1876. return ((PBYTE) pSysExBuffer);
  1877. }
  1878. // ****************************************************************************
  1879. // *** --- Member functions for derived class CUD_Waveform
  1880. //
  1881. // ****************************************************************************
  1882. //
  1883. // ----------------------------------------------------------------------------
  1884. // Function: CUD_Waveform::CUD_Waveform
  1885. // Purpose: Constructor(s)/Destructor for CUD_Waveform Object
  1886. // Parameters:
  1887. // Returns:
  1888. // Algorithm:
  1889. // ----------------------------------------------------------------------------
  1890. CMidiUD_Waveform::CMidiUD_Waveform(PEFFECT pEffect, ULONG ulNumVectors, PLONG pArray) : CMidiEffect(pEffect, NULL),
  1891. m_pRawData(NULL)
  1892. {
  1893. m_OpCode = DNLOAD_DATA | X_AXIS|Y_AXIS;// Sub-command opcode: DNLOAD_DATA
  1894. m_SubType = ET_UD_WAVEFORM; // Effect Type: UD_WAVEFORM
  1895. assert(pArray);
  1896. // Create the buffer to hold the waveform data, compress it,
  1897. // then copy to this object
  1898. // The buffer size is initially set to the number of uncompressed vectors
  1899. // x 2 bytes, for worse-case Absolute data
  1900. // Once the buffer is compressed, the actual size is determined
  1901. // Also, create a temp copy so that the original unscaled data is not
  1902. // affected.
  1903. // Set a fixed maximum size
  1904. DWORD nSize = MAX_MIDI_WAVEFORM_DATA_SIZE + 2;
  1905. m_pArrayData = new BYTE[nSize];
  1906. // m_pRawData = new BYTE [nSize*2];
  1907. assert(m_pArrayData);
  1908. ULONG NewForceRate;
  1909. m_MidiBufferSize = SetTypeParams(ulNumVectors, pArray, &NewForceRate);
  1910. // Copy structures to object
  1911. memcpy(&m_Effect.m_Bytes, pEffect, sizeof(EFFECT));
  1912. SetForceOutRate(NewForceRate);
  1913. m_Effect.m_Gain = m_Effect.m_Gain & 0x7f;
  1914. m_Effect.m_Duration = (ULONG) ((float) (m_Effect.m_Duration / TICKRATE));
  1915. m_Duration = m_Effect.m_Duration;
  1916. }
  1917. // --- Destructor
  1918. CMidiUD_Waveform::~CMidiUD_Waveform()
  1919. {
  1920. if (m_pArrayData) delete [] m_pArrayData;
  1921. memset(this, 0, sizeof(CMidiUD_Waveform));
  1922. }
  1923. // ----------------------------------------------------------------------------
  1924. // Function: CMidiUD_Waveform::SetEffectParams
  1925. // Purpose: Sets the Effect specific parameters
  1926. // Parameters: PEFFECT pEffect
  1927. // Returns:
  1928. // Algorithm:
  1929. // ----------------------------------------------------------------------------
  1930. void CMidiUD_Waveform::SetEffectParams(PEFFECT pEffect)
  1931. {
  1932. // Set the MIDI_EFFECT parameters
  1933. SetButtonPlaymask(pEffect->m_ButtonPlayMask);
  1934. SetAxisMask(X_AXIS|Y_AXIS);
  1935. SetDirectionAngle(pEffect->m_DirectionAngle2D);
  1936. SetGain((BYTE) (pEffect->m_Gain));
  1937. SetForceOutRate(pEffect->m_ForceOutputRate);
  1938. }
  1939. // ----------------------------------------------------------------------------
  1940. // Function: CMidiUD_Waveform::SetTypeParams
  1941. // Purpose: Sets the type specific parameters
  1942. // Parameters: int nSize - size of the array
  1943. // PLONG pArray - Pointer to an ARRAY of force values
  1944. //
  1945. // Returns: MidiBuffer size for the packet
  1946. // Algorithm:
  1947. // ----------------------------------------------------------------------------
  1948. int CMidiUD_Waveform::SetTypeParams(int nSize, PLONG pArray, ULONG *pNewRate)
  1949. {
  1950. // Compress the buffer data then copy to this object
  1951. // The buffer size is initially set to the number of uncompressed vectors
  1952. // x 2 bytes, for worse-case Absolute data
  1953. // Once the buffer is compressed, the actual size is determined
  1954. // Also, create a temp copy so that the original unscaled data is not
  1955. // affected.
  1956. m_pRawData = new BYTE [nSize*2];
  1957. if (m_pRawData == NULL)
  1958. {
  1959. return 0;
  1960. }
  1961. // Convert to -128 to +127
  1962. for (int i=0; i<nSize; i++)
  1963. {
  1964. m_pRawData[i] = (BYTE) ((LONG) (pArray[i] * MAX_SCALE));
  1965. }
  1966. m_NumberOfVectors = CompressWaveform(&m_pRawData[0], m_pArrayData, nSize, pNewRate);
  1967. assert(m_NumberOfVectors <= (MAX_MIDI_WAVEFORM_DATA_SIZE));
  1968. if (m_pRawData)
  1969. {
  1970. delete [] m_pRawData;
  1971. m_pRawData = 0;
  1972. }
  1973. if (0 == m_NumberOfVectors) // No room!
  1974. return (0);
  1975. m_MidiBufferSize = (m_NumberOfVectors + sizeof(UD_WAVEFORM_SYS_EX) + 2);
  1976. return (m_MidiBufferSize);
  1977. }
  1978. // ----------------------------------------------------------------------------
  1979. // Function: CMidiUD_Waveform::CompressWaveform
  1980. // Purpose: Builds the SysEx packet into the pBuf
  1981. // Parameters: PBYTE pSrcArray - Source Array pointer
  1982. // PBYTE pDestArray - Dest. Array Pointer
  1983. // int nSize - Size in Bytes of the Source Array
  1984. //
  1985. // Returns: int - Size of the compressed Array (in bytes)
  1986. // Algorithm:
  1987. // To "compress" we need to fit the entire waveform into 98 points (there is a
  1988. // FW bug that limits us to 100 points only, and we need at least two samples
  1989. // for the starting Absolute mode point.
  1990. // 1. Determine how many points over 98.
  1991. // nSrcSize: Total sample size
  1992. // nMaxSamples: Maximum samples to squeeze into = 98
  1993. // nOver: nSrcSize - nMaxSamples
  1994. // nSkipSample: # of points to keep before skipping one
  1995. // = nSrcSize/nOver
  1996. // while ( Sample is less than nSrcSize, bump index)
  1997. // {
  1998. // if ( (index % nSkipSample) == 0) // no remainder
  1999. // {
  2000. // index++ // bump to skip the next sample
  2001. // }
  2002. // Compress the data
  2003. // }
  2004. //
  2005. // ----------------------------------------------------------------------------
  2006. int CMidiUD_Waveform::CompressWaveform(
  2007. IN PBYTE pSrcArray,
  2008. IN OUT PBYTE pDestArray,
  2009. IN int nSrcSize,
  2010. OUT ULONG *pNewForceRate)
  2011. {
  2012. assert(pSrcArray && pDestArray);
  2013. LONG nDifference;
  2014. // 8 bits (-128 to +127) Starting Absolute Data Value
  2015. pDestArray[0] = pSrcArray[0] & 0x3f;
  2016. pDestArray[1] = (pSrcArray[0] >> 6) & 0x03;
  2017. // int nMaxSamples = MAX_MIDI_WAVEFORM_DATA_SIZE;
  2018. int nSkipSample, nSrcIndex, nDestIndex;
  2019. int nAbsolute = 0;
  2020. int nRelative = 0;
  2021. //
  2022. // Start with Finest Resolution, then reduce until # of Samples <= nMaxSamples
  2023. //
  2024. nSkipSample = nSrcSize;
  2025. while (TRUE)
  2026. {
  2027. nSrcIndex = 0; // 1st sample already accounted for
  2028. nDestIndex = 2;
  2029. #ifdef _DEBUG
  2030. g_CriticalSection.Enter();
  2031. wsprintf(g_cMsg,"nSkipSample=%d\n",nSkipSample);
  2032. DebugOut(g_cMsg);
  2033. g_CriticalSection.Leave();
  2034. #endif
  2035. while (nSrcIndex < nSrcSize)
  2036. {
  2037. nSrcIndex++;
  2038. if (0 == (nSrcIndex % nSkipSample))
  2039. {
  2040. nSrcIndex++; // Skip next one
  2041. nDifference = ((char) pSrcArray[nSrcIndex]) - ((char) pSrcArray[nSrcIndex-2]);
  2042. }
  2043. else
  2044. nDifference = ((char) pSrcArray[nSrcIndex]) - ((char) pSrcArray[nSrcIndex-1]);
  2045. // make sure we do not write outside of array bounds
  2046. if(nDestIndex > MAX_MIDI_WAVEFORM_DATA_SIZE) break;
  2047. if (abs(nDifference) < DIFFERENCE_THRESHOLD)
  2048. {
  2049. pDestArray[nDestIndex] = (BYTE)((nDifference & 0x3f) | DIFFERENCE_BIT);
  2050. nDestIndex++;
  2051. nRelative++;
  2052. }
  2053. else // Switch to Absolute Data (8 bits)
  2054. {
  2055. pDestArray[nDestIndex] = pSrcArray[nSrcIndex] & 0x3f;
  2056. pDestArray[nDestIndex+1] = (pSrcArray[nSrcIndex] >> 6) & 0x3;
  2057. nDestIndex = nDestIndex+2;
  2058. nAbsolute++;
  2059. }
  2060. }
  2061. if (nDestIndex <= MAX_MIDI_WAVEFORM_DATA_SIZE) break;
  2062. // Reduce the resolution
  2063. if (nSkipSample < 8)
  2064. nSkipSample--;
  2065. else
  2066. nSkipSample = nSkipSample/2;
  2067. if (1 == nSkipSample) return (0); // Sorry charlie, no room!
  2068. nAbsolute = 0;
  2069. nRelative = 0;
  2070. }
  2071. // Done
  2072. ULONG ulOriginalForceRate = ForceOutRateOf();
  2073. // *pNewForceRate = (ulOriginalForceRate - (ULONG) (ulOriginalForceRate * ((float) nSkipSample / (float) nSrcSize)))/nSkipSample;
  2074. *pNewForceRate = (ULONG) ((1.0f - (1.0f/nSkipSample)) * ulOriginalForceRate);
  2075. #ifdef _DEBUG
  2076. g_CriticalSection.Enter();
  2077. wsprintf(g_cMsg, "CompressWaveform: nSrcSize=%d, nSkipSample=%d, NewForceRate=%d\n",
  2078. nSrcSize, nSkipSample, *pNewForceRate);
  2079. DebugOut(g_cMsg);
  2080. wsprintf(g_cMsg,"\nTotal Absolute Data:%d, Relative Data:%d", nAbsolute, nRelative);
  2081. DebugOut(g_cMsg);
  2082. g_CriticalSection.Leave();
  2083. #endif
  2084. #ifdef _SHOWCOMPRESS
  2085. #pragma message("Compiling with SHOWCOMPRESS")
  2086. g_CriticalSection.Enter();
  2087. DebugOut("CMidiUD_Waveform::CompressWaveform(..) \npSrcArray Dump (Decimal)\n");
  2088. for (int i=0; i<nSrcSize; i++)
  2089. {
  2090. wsprintf(g_cMsg," %0.4ld",((char) pSrcArray[i]));
  2091. DebugOut(g_cMsg);
  2092. }
  2093. DebugOut("\npDestArray Dump (HEX)\n");
  2094. for (i=0; i<nDestIndex; i++)
  2095. {
  2096. wsprintf(g_cMsg," %0.4x",pDestArray[i]);
  2097. DebugOut(g_cMsg);
  2098. }
  2099. g_CriticalSection.Leave();
  2100. #endif
  2101. return (nDestIndex);
  2102. }
  2103. // ----------------------------------------------------------------------------
  2104. // Function: CMidiUD_Waveform::GenerateSysExPacket
  2105. // Purpose: Builds the SysEx packet into the pBuf
  2106. // Parameters: none
  2107. // Returns: PBYTE - pointer to a buffer filled with SysEx Packet
  2108. // Algorithm:
  2109. // ----------------------------------------------------------------------------
  2110. PBYTE CMidiUD_Waveform::GenerateSysExPacket(void)
  2111. {
  2112. if(NULL == g_pJoltMidi) return ((PBYTE) NULL);
  2113. PBYTE pSysExBuffer = g_pJoltMidi->PrimaryBufferPtrOf();
  2114. assert(pSysExBuffer);
  2115. // Copy SysEx Header + m_OpCode + m_SubType
  2116. memcpy(pSysExBuffer, &m_bSysExCmd, sizeof(SYS_EX_HDR)+2 );
  2117. PUD_WAVEFORM_SYS_EX pBuf = (PUD_WAVEFORM_SYS_EX) pSysExBuffer;
  2118. SetTotalDuration(); // Compute total with Loop count parameter
  2119. pBuf->Effect.bDurationL = (BYTE) (m_Duration & 0x7f);
  2120. pBuf->Effect.bDurationH = (BYTE) (m_Duration >> 7) & 0x7f;
  2121. pBuf->Effect.bAngleL = Effect.bAngleL & 0x7f;
  2122. pBuf->Effect.bAngleH = Effect.bAngleH & 0x7f;
  2123. pBuf->Effect.bGain = (BYTE) (Effect.bGain * MAX_SCALE) & 0x7f;
  2124. pBuf->Effect.bButtonPlayL = Effect.bButtonPlayL & 0x7f;
  2125. pBuf->Effect.bButtonPlayH = Effect.bButtonPlayH & 0x7f;
  2126. pBuf->Effect.bForceOutRateL = Effect.bForceOutRateL & 0x7f;
  2127. pBuf->Effect.bForceOutRateH = Effect.bForceOutRateH & 0x7f;
  2128. pBuf->Effect.bPercentL = Effect.bPercentL & 0x7f;
  2129. pBuf->Effect.bPercentH = Effect.bPercentH & 0x7f;
  2130. // Fill in the Array Data
  2131. PBYTE pArray = ((PBYTE) pBuf) + UD_WAVEFORM_START_OFFSET;
  2132. memcpy(pArray, m_pArrayData, m_NumberOfVectors); // Already scaled!
  2133. pBuf->bEffectID = m_bEffectID;
  2134. int nArraySize = (m_NumberOfVectors + sizeof(UD_WAVEFORM_SYS_EX));
  2135. pSysExBuffer[nArraySize] = 0;
  2136. pSysExBuffer[nArraySize+1] = 0;
  2137. pSysExBuffer[nArraySize] = ComputeChecksum((PBYTE) pSysExBuffer, (nArraySize+2));
  2138. pSysExBuffer[nArraySize+1]= MIDI_EOX;
  2139. return ((PBYTE) pSysExBuffer);
  2140. }