Figure 5   Create Direct Input Object


 ///////// this is in your function:
 // Declare pointers to direct input objects/interfaces/effects
 LPDIRECTINPUT pDI = NULL;                     // Direct input object
 LPDIRECTINPUTDEVICE2 pDIDevice = NULL;        // Ptr to DIInputDevice2 interface
 #define FFBE_JOYSTICK_INIT_FAILED    1        // error
 #define RELEASE(ptr) ( (ptr)->Release(); }    // handy macro - recurring theme
 // Open the joystick using SWFF wrapper function: HWND is in m_hWnd in 
 // this application
     HRESULT hresult;
     // create the DirectInput object and put it in pDI
     hresult = DirectInputCreate(GetModuleHandle(NULL), 
                                 DIRECTINPUT_VERSION, 
                                 &pDI, NULL);
     if(FAILED(hresult))
         return FFBE_JOYSTICK_INIT_FAILED;
     
     // enumerate the first attached forcefeedback joystick
     DIDEVICEINSTANCE deviceInstance;
     deviceInstance.dwDevType = 0;
     hresult = pDI->EnumDevices(DIDEVTYPE_JOYSTICK, 
         EnumCallback, 
         &deviceInstance, 
         DIEDFL_FORCEFEEDBACK);
     if(FAILED(hresult) || deviceInstance.dwDevType == 0)
     {
         RELEASE(pDI);
         return FFBE_JOYSTICK_INIT_FAILED;
     }
 
     // create DirectInput Device object. This does not have FFB methods.
     LPDIRECTINPUTDEVICE pDIDeviceObject = NULL;
     hresult = pDI->CreateDevice(deviceInstance.guidInstance, 
         &pDIDeviceObject, NULL);
     if(FAILED(hresult))
     {
         RELEASE(pDI);
         return FFBE_JOYSTICK_INIT_FAILED;
     }
 
     // get a pointer to its DirectInputDevice2 interface with FFB methods
     hresult = pDIDeviceObject->QueryInterface(IID_IDirectInputDevice2, 
         (void**) (&pDIDevice) );
     if(FAILED(hresult))
     {
         RELEASE(pDIDeviceObject);
         RELEASE(pDI);
         return FFBE_JOYSTICK_INIT_FAILED;
     }
 
     // we now have a pointer to the right COM interface. we can get
     // rid of the device object now.
     RELEASE(pDIDeviceObject);
 
     // set the data format to the pre-defined DirectInput joystick format
     hresult = pDIDevice->SetDataFormat(&c_dfDIJoystick);
     if(FAILED(hresult))
     {
         RELEASE(pDIDevice);
         RELEASE(pDI);
         return FFBE_JOYSTICK_INIT_FAILED;
     }
 
     // set the cooperative level
     hresult = pDIDevice->SetCooperativeLevel(m_hWnd, 
         DISCL_EXCLUSIVE | DISCL_FOREGROUND);
     if(FAILED(hresult))
     {
         RELEASE(pDIDevice);
         RELEASE(pDI);
         return FFBE_JOYSTICK_INIT_FAILED;
     }
 
     // turn auto-center off using set property function
     // This should be done or else the spring will confound the
     // sensation of other force effects.
     DIPROPDWORD autoCenter;
     autoCenter.diph.dwSize = sizeof(autoCenter);
     autoCenter.diph.dwHeaderSize = sizeof(DIPROPHEADER);
     autoCenter.diph.dwObj = 0;
     autoCenter.diph.dwHow = DIPH_DEVICE;
     autoCenter.dwData = 0;
 
     hresult = pDIDevice->SetProperty(DIPROP_AUTOCENTER, 
         &autoCenter.diph);
     if(FAILED(hresult))
     {
         RELEASE(pDIDevice);
         RELEASE(pDI);
         return FFBE_JOYSTICK_INIT_FAILED;
     }
 
     // acquire the joystick
     hresult = pDIDevice->Acquire();
     if(FAILED(hresult))
     {
         RELEASE(pDIDevice);
         RELEASE(pDI);
         return FFBE_JOYSTICK_INIT_FAILED;
     }
 
     // Finally done. Phew.
     SWFFInitialized = TRUE;
     return FFBE_NO_ERROR;

Figure 6   Create SquareWaveEffect


 // Pointer to effect
 LPDIRECTINPUTEFFECT pSquareWaveEffect;
 #define FFBE_SQUARE_WAVE_FAILED 5
 
 // Set up the Directinput periodic struct with the right effect parameters 
 DIPERIODIC periodicEffectStruct;
 periodicEffectStruct.dwMagnitude = 50000;    // 50%
 periodicEffectStruct.lOffset = 0;            // no offset
 periodicEffectStruct.dwPhase = 0;            // no phase shift
 periodicEffectStruct.dwPeriod = DI_SECONDS/10;  //.1s=10Hz
 
 // For demonstration purposes - if it's an empty envelope, you can pass 
 // in lpEnvelope = NULL instead.
 
 DIENVELOPE squareWaveEnvelopeStruct;
 squareWaveEnvelopeStruct.dwSize = sizeof(DIENVELOPE);
 squareWaveEnvelopeStruct.dwAttackTime = 500000; // 0.5 sec ramp-up
 squareWaveEnvelopeStruct.dwAttackLevel = 0;
 squareWaveEnvelopeStruct.dwFadeTime = 0;
 squareWaveEnvelopeStruct.dwFadeLevel = 0;
 
 DWORD axes[2] = {DIJOFS_X,DIJOFS_Y};
 LONG direction[2] = {0,0};            // start out vertical: up and down
 
 DIEFFECT squareWaveEffectStruct;
 squareWaveEffectStruct.dwSize          = sizeof(DIEFFECT);
 squareWaveEffectStruct.dwFlags         = DIEFF_OBJECTOFFSETS | DIEFF_POLAR;
 squareWaveEffectStruct.dwDuration      = INFINITE;       // do this forever
 squareWaveEffectStruct.dwSamplePeriod  = 10000;          // 100Hz sample period
 squareWaveEffectStruct.dwGain          = 10000;          // 100% gain
 squareWaveEffectStruct.dwTriggerButton = DIEB_NOTRIGGER; // not tied to buttons
 squareWaveEffectStruct.dwTriggerRepeatInterval= 0;
 squareWaveEffectStruct.cAxes           = 2;
 squareWaveEffectStruct.rgdwAxes        = axes;
 squareWaveEffectStruct.rglDirection    = direction;
 squareWaveEffectStruct.lpEnvelope      = &squareWaveEnvelopeStruct;
 squareWaveEffectStruct.cbTypeSpecificParams  = sizeof(periodicEffectStruct);
 squareWaveEffectStruct.lpvTypeSpecificParams = &periodicEffectStruct;
 
 // Create and download
 hresult = pDIDevice->CreateEffect(GUID_Square, 
           &squareWaveEffectStruct, 
           &pEffects[FFB_TEST_SQUARE_WAVE, NULL);
 if (FAILED(hresult))  
     return FFBE_SQUARE_WAVE_FAILED;
 
 // Start the effect
 if ( (pSquareWaveEffect)->Start(1, 0))
        return FFBE_SQUARE_WAVE_FAILED;

Figure 7   Modify SquareWaveEffect


 // Retrieve current parameters: first set up the structures
 // to contain the data back, then retrieve it with GetParameters()
 #define FFBE_MODIFY_SQUARE_WAVE_FAILED    13
 DIEFFECT squareWaveEffectStruct = {sizeof(DIEFFECT)};
 DIPERIODIC periodicEffectStruct = {sizeof(DIPERIODIC)};
 squareWaveEffectStruct.cbTypeSpecificParams = 
        sizeof(periodicEffectStruct);
 squareWaveEffectStruct.lpvTypeSpecificParams = &periodicEffectStruct;
 if ( (pEffects[FFB_TEST_SQUARE_WAVE])->GetParameters(&squareWaveEffectStruct, 
        DIEP_TYPESPECIFICPARAMS))
        return FFBE_MODIFY_SQUARE_WAVE_FAILED;
 
 // Modify a few parameters.
 // The standard square wave we were playing with had 50% strength
 // in the up-down direction; it was at 10Hz. we will now change
 // it to 100% strength, at 5Hz. It will be quite noticeable.
 periodicEffectStruct.dwMagnitude = 100000;    // was 50% now 100%
 periodicEffectStruct.dwPeriod = 200000;        // was 10Hz now .2s=5Hz
 
 // Modify the effect: immediately visible.
 if ( (pEffects[FFB_TEST_SQUARE_WAVE])->SetParameters(&squareWaveEffectStruct, 
        DIEP_TYPESPECIFICPARAMS))
        return FFBE_MODIFY_SQUARE_WAVE_FAILED;

Figure 8   ForceFeedbackDlg.cpp


 // ForceFeedbackDlg.cpp : implementation file
 //
 
 #include "stdafx.h"
 #include "ForceFeedback.h"
 #include "ForceFeedbackDlg.h"
 
 
 #ifdef _DEBUG
 #define new DEBUG_NEW
 #undef THIS_FILE
 static char THIS_FILE[] = __FILE__;
 #endif
 
 /////////////////////////////////////////////////////////////////////////////
 // CAboutDlg dialog used for App About
 
 class CAboutDlg : public CDialog
 {
 public:
     CAboutDlg();
 
 // Dialog Data
     //{{AFX_DATA(CAboutDlg)
     enum { IDD = IDD_ABOUTBOX };
     //}}AFX_DATA
 
     // ClassWizard generated virtual function overrides
     //{{AFX_VIRTUAL(CAboutDlg)
     protected:
     virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
     //}}AFX_VIRTUAL
 
 // Implementation
 protected:
     //{{AFX_MSG(CAboutDlg)
     //}}AFX_MSG
     DECLARE_MESSAGE_MAP()
 };
 
 CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
 {
     //{{AFX_DATA_INIT(CAboutDlg)
     //}}AFX_DATA_INIT
 }
 
 void CAboutDlg::DoDataExchange(CDataExchange* pDX)
 {
     CDialog::DoDataExchange(pDX);
     //{{AFX_DATA_MAP(CAboutDlg)
     //}}AFX_DATA_MAP
 }
 
 BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
     //{{AFX_MSG_MAP(CAboutDlg)
         // No message handlers
     //}}AFX_MSG_MAP
 END_MESSAGE_MAP()
 
 /////////////////////////////////////////////////////////////////////////////
 // CForceFeedbackDlg dialog
 
 CForceFeedbackDlg::CForceFeedbackDlg(CWnd* pParent /*=NULL*/)
     : CDialog(CForceFeedbackDlg::IDD, pParent)
 {
     //{{AFX_DATA_INIT(CForceFeedbackDlg)
     m_status_CString = _T("No error");
     //}}AFX_DATA_INIT
     // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
     m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
 }
 
 void CForceFeedbackDlg::DoDataExchange(CDataExchange* pDX)
 {
     CDialog::DoDataExchange(pDX);
     //{{AFX_DATA_MAP(CForceFeedbackDlg)
     DDX_Control(pDX, IDC_DX_ACTUATORS_ON, m_actuators_on);
     DDX_Control(pDX, IDC_DX_ACTUATORS_OFF, m_actuators_off);
     //}}AFX_DATA_MAP
 }
 
 BEGIN_MESSAGE_MAP(CForceFeedbackDlg, CDialog)
     //{{AFX_MSG_MAP(CForceFeedbackDlg)
     ON_WM_SYSCOMMAND()
     ON_WM_DESTROY()
     ON_WM_PAINT()
     ON_WM_QUERYDRAGICON()
 
     // SWFF demo calls
     ON_BN_CLICKED(IDC_INIT_SWFFSTICK, InitSwffstick)
     ON_BN_CLICKED(IDC_SHUTDOWN_SWFFSTICK, ShutdownSwffstick)
     ON_BN_CLICKED(IDC_TEST_SPRING, TestSpring)
     ON_BN_CLICKED(IDC_TEST_DAMPER, TestDamper)
     ON_BN_CLICKED(IDC_TEST_SQUARE_WAVE, TestSquareWave)
     ON_BN_CLICKED(IDC_TEST_SAW_TOOTH, TestSawTooth)
     ON_BN_CLICKED(IDC_TEST_RAMP, TestRamp)
     ON_BN_CLICKED(IDC_TEST_CONSTANT_FORCE, TestConstantForce)
     ON_BN_CLICKED(IDC_TEST_ROM, TestRom)
     ON_BN_CLICKED(IDC_TEST_RAW_FORCE, TestRawForce)
     ON_BN_CLICKED(IDC_TEST_VFX, TestVfx)
     ON_BN_CLICKED(IDC_TEST_WALL, TestWall)
 
     // Direct X demo calls
     ON_BN_CLICKED(IDC_DX_INIT, DxInit)
     ON_BN_CLICKED(IDC_DX_SHUTDOWN, DxShutdown)
     ON_BN_CLICKED(IDC_DX_SPRING, DxSpring)
     ON_BN_CLICKED(IDC_DX_SQUARE, DxSquare)
     ON_BN_CLICKED(IDC_DX_MODIFY_SQUARE_WAVE, DxModifySquare)
     ON_BN_CLICKED(IDC_DX_ACTUATORS_ON, DxActuatorsOn)
     ON_BN_CLICKED(IDC_DX_ACTUATORS_OFF, DxActuatorsOff)
     //}}AFX_MSG_MAP
 END_MESSAGE_MAP()
 
 /////////////////////////////////////////////////////////////////////////////
 // CForceFeedbackDlg message handlers
 
 BOOL CForceFeedbackDlg::OnInitDialog()
 {
     CDialog::OnInitDialog();
 
     // Add "About..." menu item to system menu.
 
     // IDM_ABOUTBOX must be in the system command range.
     ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
     ASSERT(IDM_ABOUTBOX < 0xF000);
 
     CMenu* pSysMenu = GetSystemMenu(FALSE);
     if (pSysMenu != NULL)
     {
         CString strAboutMenu;
         strAboutMenu.LoadString(IDS_ABOUTBOX);
         if (!strAboutMenu.IsEmpty())
         {
             pSysMenu->AppendMenu(MF_SEPARATOR);
             pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
         }
     }
 
     // Set the icon for this dialog.  The framework does this automatically
     //  when the application's main window is not a dialog
     SetIcon(m_hIcon, TRUE);            // Set big icon
     SetIcon(m_hIcon, FALSE);          // Set small icon
     
     // TODO: Add extra initialization here
     
     return TRUE;  // return TRUE  unless you set the focus to a control
 }
 
 void CForceFeedbackDlg::OnSysCommand(UINT nID, LPARAM lParam)
 {
     if ((nID & 0xFFF0) == IDM_ABOUTBOX)
     {
         CAboutDlg dlgAbout;
         dlgAbout.DoModal();
     }
     else
     {
         CDialog::OnSysCommand(nID, lParam);
     }
 }
 
 void CForceFeedbackDlg::OnDestroy()
 {
     ShutdownSwffstick();    // make sure joystick is off when exiting
     WinHelp(0L, HELP_QUIT);
     CDialog::OnDestroy();
 }
 
 // If you add a minimize button to your dialog, you will need the code below
 //  to draw the icon.  For MFC applications using the document/view model,
 //  this is automatically done for you by the framework.
 
 void CForceFeedbackDlg::OnPaint() 
 {
     if (IsIconic())
     {
         CPaintDC dc(this); // device context for painting
 
         SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
 
         // Center icon in client rectangle
         int cxIcon = GetSystemMetrics(SM_CXICON);
         int cyIcon = GetSystemMetrics(SM_CYICON);
         CRect rect;
         GetClientRect(&rect);
         int x = (rect.Width() - cxIcon + 1) / 2;
         int y = (rect.Height() - cyIcon + 1) / 2;
 
         // Draw the icon
         dc.DrawIcon(x, y, m_hIcon);
     }
     else
     {
         CDialog::OnPaint();
     }
 }
 
 // The system calls this to obtain the cursor to display while the user drags
 // the minimized window.
 HCURSOR CForceFeedbackDlg::OnQueryDragIcon()
 {
     return (HCURSOR) m_hIcon;
 }
 
 /////////////////////////////////////////////////////////
 /////////////////////////////////////////////////////////
 /////////////////////////////////////////////////////////
 /////////////////////////////////////////////////////////
 // Force feedback demonstration code start here!!
 /////////////////////////////////////////////////////////
 /////////////////////////////////////////////////////////
 /////////////////////////////////////////////////////////
 /////////////////////////////////////////////////////////
 
 // Include files
 #include "sw_force.h"
 #include "ForceFeedbackDemo.h"
 #define INITGUIDS       // Make GUID available
 #include "SW_guid.hpp"
 #include "dinput.h"
 #undef INITGUIDS
 
 // File static variables
 
 // Flag to indicate whether the joystick has
 // been already acquired
 static SWFFInitialized = FALSE;
 
 // Pointer to DirectInputDevice Object
 static LPDIRECTINPUT pDI = NULL;
 
 // Pointer to DI Input Device 2 interface
 static LPDIRECTINPUTDEVICE2 pDIDevice = NULL;
 
 // Array of pointers to test effects: 10 in total
 static LPDIRECTINPUTEFFECT pEffects[FFB_N_TESTS];
 
 // Error reporting
 static HRESULT hresult;
 
 /////////////////////////////////////////////////////////
 /////////////////////////////////////////////////////////
 // USING SIDEWINDER WRAPPER LIBRARY CALLS
 /////////////////////////////////////////////////////////
 /////////////////////////////////////////////////////////
 
 /////////////////////////////////////////////////////////
 // InitSwffstick(): initializes FF stick and remembers 
 // whether or not it was initialized already
 /////////////////////////////////////////////////////////
 
 FFB_ERROR CForceFeedbackDlg::InitSwffstick() 
 {
     int i;
 
     // Make sure we only try to open the joystick when 
     // it has not been previously initialized
     if (SWFFInitialized)
         return FFBE_NO_ERROR;
 
     // Open the joystick using SWFF wrapper function
     hresult = SWFF_OpenDefaultFFJoystick(m_hWnd,&pDI,&pDIDevice);
     if (FAILED(hresult))
         return FFBE_JOYSTICK_INIT_FAILED;
 
     // Set up the effect pointer array
     for (i = 0; i < FFB_N_TESTS; i++)
         pEffects[i] = NULL;
     
     // Set flag
     SWFFInitialized = TRUE;
 
     // play with buttons!
 
     return FFBE_NO_ERROR;
 }
 
 /////////////////////////////////////////////////////////
 // ShutdownSwffstick(): initializes FF stick and remembers 
 // whether or not it was initialized already
 /////////////////////////////////////////////////////////
 FFB_ERROR CForceFeedbackDlg::ShutdownSwffstick() 
 {
     int i;
 
     // Make sure the joystick was open to begin with before
     // attempting to close it
     if (!SWFFInitialized) 
         return FFBE_NO_ERROR;
 
     // Shut off everything
     hresult = SWFF_DestroyAllEffects(pDIDevice);
     if (FAILED(hresult))
         return FFBE_JOYSTICK_SHUTDOWN_FAILED;
 
     // unacquire joystick and release DI and DI Device
     pDIDevice->Unacquire();
     RELEASE(pDIDevice);
     RELEASE(pDI);
 
     // Clean up 
     for (i = 0; i < FFB_N_TESTS; i++)
         pEffects[i] = NULL;
     pDIDevice = NULL;
     pDI = NULL;
     SWFFInitialized = FALSE;
     
     return FFBE_NO_ERROR;
 }
 
 /////////////////////////////////////////////////////////
 // TestSpring(): Turns on a spring effect using the 
 //                    canned SWFF_CreateSpringEffect()
 //                    provided by swff_lib.cpp
 /////////////////////////////////////////////////////////
 FFB_ERROR CForceFeedbackDlg::TestSpring() 
 {
     FFB_ERROR error = FFBE_NO_ERROR;
 
     // Make sure the joystick was open to begin with before
     // attempting to create start an effect
     if (!SWFFInitialized) {
         error = InitSwffstick();
         if (error) return error;
     }
 
     // Only create a new effect if it was not created already
     if (pEffects[FFB_TEST_SPRING] == NULL) 
     {
 
         // Create the effect and download to stick
         hresult = SWFF_CreateSpringEffect(    pDIDevice,
             &(pEffects[FFB_TEST_SPRING]),
             INFINITE,        // duration in uS
             5000,            // Kx: 50.00%
             0,               // X offset
             5000,            // Ky: 50.00%
             0,                // Y Offset
             -1);              // button: don't tie this to anything
         if (FAILED(hresult))
             return FFBE_SPRING_FAILED;
 
         // Now start it
         hresult = (pEffects[FFB_TEST_SPRING])->Start(1, 0);
         if (FAILED(hresult))
             return FFBE_SPRING_FAILED;
     
     }
 
     // All's well that ends well
     return FFBE_NO_ERROR;
 }
 
 /////////////////////////////////////////////////////////
 // TestDamper(): Turns on a damper effect using the more
 //                    generic SWFF_CreateConditionEffect().
 /////////////////////////////////////////////////////////
 FFB_ERROR CForceFeedbackDlg::TestDamper() 
 {
     FFB_ERROR error = FFBE_NO_ERROR;
 
     // Make sure the joystick was open to begin with before
     // attempting to start an effect
     if (!SWFFInitialized) {
         error = InitSwffstick();
         if (error) return error;
     }
 
     // Only create a new effect if it was not created already
     if (pEffects[FFB_TEST_DAMPER] == NULL) 
     {
         // Create the effect and download to stick
         hresult = SWFF_CreateConditionEffect(pDIDevice,
             &(pEffects[FFB_TEST_DAMPER]),
             DAMPER,                // Damper type effect
             INFINITE,              // duration in uS
             5000,                  // Bx: 50.00%
             0,                     // X offset
             5000,                  // By: 50.00%
             0,                     // Y Offset
             -1);                   // button: don't tie to anything
         if (FAILED(hresult))
             return FFBE_DAMPER_FAILED;
 
         // Now start it
         hresult = (pEffects[FFB_TEST_DAMPER])->Start(1, 0);
         if (FAILED(hresult))
             return FFBE_DAMPER_FAILED;
     }
     
     return FFBE_NO_ERROR;
 
 }
 
 /////////////////////////////////////////////////////////
 // TestSquareWave(): Turns on a square wave effect using 
 // SWFF_CreateEffect().
 /////////////////////////////////////////////////////////
 FFB_ERROR CForceFeedbackDlg::TestSquareWave() 
 {
     FFB_ERROR error = FFBE_NO_ERROR;
 
     // Make sure the joystick was open to begin with before
     // attempting to start an effect
     if (!SWFFInitialized) {
         error = InitSwffstick();
         if (error) return error;
     }
 
     // Only create a new effect if it was not created already
     if (pEffects[FFB_TEST_SQUARE_WAVE] == NULL) 
     {
         // Create an effect in memory
         hresult = SWFF_CreatePeriodicEffect(pDIDevice,
             &(pEffects[FFB_TEST_SQUARE_WAVE]),
             SQUARE_HIGH,    // square waveform
             INFINITE,       // duration in us
             100000,         // period in us(.1s=10Hz)
             0,              // orientation(degrees)
             5000,           // magnitude: 50.00%
             0,              // offset
             0,0,0,0,        // envelope
             -1);            // button: don't tie to anything
         if (FAILED(hresult))
             return FFBE_SQUARE_WAVE_FAILED;
 
         // Start the effect
         hresult = (pEffects[FFB_TEST_SQUARE_WAVE])->Start(1, 0);
         if (FAILED(hresult))
             return FFBE_SQUARE_WAVE_FAILED;
     }
 
     return FFBE_NO_ERROR;
 }
 
 /////////////////////////////////////////////////////////
 // TestSawtooth(): Turns on a ramp effect using the more
 //                 generic SWFF_CreatePeriodicEffect().
 //                 In this effect I have tied the execution
 //                 of the sawtooth to the trigger button.
 //                 The sawtooth will fire as long as
 //                 the trigger button is depressed.
 /////////////////////////////////////////////////////////
 FFB_ERROR CForceFeedbackDlg::TestSawTooth() 
 {
     FFB_ERROR error = FFBE_NO_ERROR;
 
     // Make sure the joystick was open to begin with before
     // attempting to start an effect
     if (!SWFFInitialized) {
         error = InitSwffstick();
         if (error) return error;
     }
 
     // Only create a new effect if it was not created already
     if (pEffects[FFB_TEST_SAWTOOTH] == NULL) 
     {
         // Create an effect in memory
         hresult = SWFF_CreatePeriodicEffect(pDIDevice,
             &(pEffects[FFB_TEST_SAWTOOTH]),
             SAWTOOTH_UP,     // square waveform
             INFINITE,        // duration
             100000,          // period in us(.1s=10Hz)
             0,               // orientation(degrees)
             5000,            // magnitude: 50.00%
             0,               // offset
             0,0,0,0,         // envelope
             BUTTON_TRIGGER); // Turn on sawtooth when trigger depressed!
         if (FAILED(hresult))
             return FFBE_SAWTOOTH_FAILED;
 
         // Since this effect is tied to a button and is on only
         // when the button is depressed, there is no need to start it!
     }
     return FFBE_NO_ERROR;
 }
 
 /////////////////////////////////////////////////////////
 // TestRamp(): Turns on a ramp effect 
 /////////////////////////////////////////////////////////
 FFB_ERROR CForceFeedbackDlg::TestRamp() 
 {
     FFB_ERROR error = FFBE_NO_ERROR;
 
     // Make sure the joystick was open to begin with before
     // attempting to start an effect
     if (!SWFFInitialized) {
         error = InitSwffstick();
         if (error) return error;
     }
 
     // Only create a new effect if it was not created already
     if (pEffects[FFB_TEST_RAMP] == NULL) 
     { 
         // Create an effect in memory
         hresult = SWFF_CreateRampEffect(pDIDevice,
             &(pEffects[FFB_TEST_RAMP]),
             INFINITE,  // duration
             4500,      // orientation(1/100th degrees)
             -10000,    // start magnitude (1/100th%)
             10000,     // end magnitude(1/100th%)
             0,0,0,0,   // envelope
             -1);       // button tied to nothing
         if (FAILED(hresult))
             return FFBE_RAMP_FAILED;
 
         // Start the effect
         hresult = (pEffects[FFB_TEST_RAMP])->Start(1, 0);
         if (FAILED(hresult))
             return FFBE_RAMP_FAILED;
     }
 
     return FFBE_NO_ERROR;
     
 }
 
 /////////////////////////////////////////////////////////
 // TestConstantForce(): Turns on a constant force
 /////////////////////////////////////////////////////////
 FFB_ERROR CForceFeedbackDlg::TestConstantForce() 
 {
     FFB_ERROR error = FFBE_NO_ERROR;
 
     // Make sure the joystick was open to begin with before
     // attempting to start an effect
     if (!SWFFInitialized) {
         error = InitSwffstick();
         if (error) return error;
     }
 
     // Only create a new effect if it was not created already
     if (pEffects[FFB_TEST_CONSTANT_FORCE] == NULL)
     {
         // Create an effect in memory
         hresult = SWFF_CreateConstantForceEffect(pDIDevice,
             &(pEffects[FFB_TEST_CONSTANT_FORCE]),
             5000000,          // duration: make this 5 seconds
             0,                // orientation(1/100th degrees)
             10000,            // magnitude (1/100th%)
             5000,0,5000,0,    // .5s to rise and .5s to fade
             -1);              // button
         if (FAILED(hresult))
             return FFBE_CONSTANT_FORCE_FAILED;
 
         // Start the effect
         hresult = (pEffects[FFB_TEST_CONSTANT_FORCE])->Start(1, 0);
         if (FAILED(hresult))
             return FFBE_CONSTANT_FORCE_FAILED;
     }
 
     return FFBE_NO_ERROR;
     
 }
 
 /////////////////////////////////////////////////////////
 // TestRom(): SWFF SPECIFIC: Turns on a Sidewinder Canned Effect.
 //            There are 32 such canned effects in the
 //            Sidewinder stick.
 /////////////////////////////////////////////////////////
 
 FFB_ERROR CForceFeedbackDlg::TestRom() 
 {
     FFB_ERROR error = FFBE_NO_ERROR;
 
     // Make sure the joystick was open to begin with before
     // attempting to start an effect
     if (!SWFFInitialized) {
         error = InitSwffstick();
         if (error) return error;
     }
 
     // Only create a new effect if it was not created already
     if (pEffects[FFB_TEST_ROM_EFFECT] == NULL) 
     {
         // Create an effect in memory
         hresult = SWFF_CreateROMEffect(pDIDevice,
             &(pEffects[FFB_TEST_ROM_EFFECT]),
             GUID_ChainsawInAction,    // square waveform
             DEFAULT_ROM_EFFECT_DURATION,
             DEFAULT_ROM_EFFECT_GAIN,
             0,                        // orientation(degrees)
             -1);                      // button
         if (FAILED(hresult))
             return FFBE_ROM_FAILED;
 
         // Start the effect
         hresult = (pEffects[FFB_TEST_ROM_EFFECT])->Start(1, 0);
         if (FAILED(hresult))
             return FFBE_ROM_FAILED;
     }
 
     return FFBE_NO_ERROR;
     
 }
 
 /////////////////////////////////////////////////////////
 // TestRawForce(): SWFF SPECIFIC: Turns on a raw force. This feels exactly
 //                 like the constant force effect minus 
 //                 the rise time and fade time and also it doesn't
 //                 die until you explicitly kill it off.
 /////////////////////////////////////////////////////////
 FFB_ERROR CForceFeedbackDlg::TestRawForce() 
 {
     FFB_ERROR error = FFBE_NO_ERROR;
 
     // Make sure the joystick was open to begin with before
     // attempting to start an effect
     if (!SWFFInitialized) {
         error = InitSwffstick();
         if (error) return error;
     }
 
     // Only create a new effect if it was not created already
     if (pEffects[FFB_TEST_RAW_FORCE] == NULL) 
     {
         // Create an effect in memory
         hresult = SWFF_CreateRawForceEffect(pDIDevice, 
             &(pEffects[FFB_TEST_RAW_FORCE]),0, 0);
         if (FAILED(hresult))
             return FFBE_RAW_FORCE_FAILED;
 
         // Now put the force out
         hresult = SWFF_PutRawForce(pEffects[FFB_TEST_RAW_FORCE],
             10000,             // 100.00% magnitude
             27000);            // orientation(degrees)
         if (FAILED(hresult))
             return FFBE_RAW_FORCE_FAILED;
     }
 
     return FFBE_NO_ERROR;
 }
 
 /////////////////////////////////////////////////////////
 // TestRawForce(): SWFF SPECIFIC: Turns on a wall
 /////////////////////////////////////////////////////////
 FFB_ERROR CForceFeedbackDlg::TestWall() 
 {
     FFB_ERROR error = FFBE_NO_ERROR;
 
     // Make sure the joystick was open to begin with before
     // attempting to start an effect
     if (!SWFFInitialized) {
         error = InitSwffstick();
         if (error) return error;
     }
 
     // Only create a new effect if it was not created already
     if (pEffects[FFB_TEST_WALL] == NULL)
     {
         // Create an effect in memory
         hresult = SWFF_CreateWallEffect(pDIDevice,
                     &(pEffects[FFB_TEST_WALL]),
                     INFINITE,    // uS
                     0,           // degrees from North
                     1000,        // distance from center
                     FALSE,       // tap right to touch wall
                     10000,       // Wall Constant
                     -1);         // button play mask
 
         if (FAILED(hresult))
                 return FFBE_WALL_FAILED;
 
         // Start the effect
         hresult = (pEffects[FFB_TEST_WALL])->Start(1, 0);
         if (FAILED(hresult))
             return FFBE_WALL_FAILED;
     }
 
     return FFBE_NO_ERROR;
     
 }
 
 /////////////////////////////////////////////////////////
 // TestVfx(): SWFF SPECIFIC: Tests downloading a force effect from file.
 /////////////////////////////////////////////////////////
 FFB_ERROR CForceFeedbackDlg::TestVfx() 
 {
     FFB_ERROR error = FFBE_NO_ERROR;
     const TCHAR filename[] = {"Chainsaw.FRC"};
 
     // Make sure the joystick was open to begin with before
     // attempting to start an effect
     if (!SWFFInitialized) {
         error = InitSwffstick();
         if (error) return error;
     }
 
     // Only create a new effect if it was not created already
     if (pEffects[FFB_TEST_DOWNLOAD_FROM_FILE] == NULL) {
 
         // Create an effect in memory
         hresult = SWFF_CreateVFXEffectFromFile(pDIDevice, 
             &(pEffects[FFB_TEST_DOWNLOAD_FROM_FILE]),
             filename);  // file containing effect
         if (FAILED(hresult))
             return FFBE_DOWNLOAD_FROM_FILE_FAILED;
 
         // Start the effect
         hresult = (pEffects[FFB_TEST_DOWNLOAD_FROM_FILE])->Start(1, 0);
         if (FAILED(hresult))
             return FFBE_DOWNLOAD_FROM_FILE_FAILED;
     }
     return FFBE_NO_ERROR;
 }
 
 /////////////////////////////////////////////////////////
 /////////////////////////////////////////////////////////
 // USING DIRECTX CALLS
 /////////////////////////////////////////////////////////
 /////////////////////////////////////////////////////////
 
 /////////////////////////////////////////////////////////
 // DxInit():
 // Initializes force feedback joystick.
 // Steps:
 // 1. Create Direct Input Object
 // 2. Enumerate the joystick
 // 3. Create DirectInputDevice object; this interface
 //    does not have the force feedback stuff in it
 // 4. Get a pointer to the DirectInputDevice2 interface;
 //    This interface does have the FFB stuff in it
 // 5. Now that we have the right pointer to the right
 //    interface we can get rid of the DirectInputDevice 
 //    object. All subsequent work is done using the 
 //    pointer to the DIDevice2 interface.
 /////////////////////////////////////////////////////////
 
 // This is a local call - the callback function you have to
 // supply when you try to enumerate the force feedback joystick.
 // Basically you tell EnumDevices to stop when it has found a 
 // force feedback joystick. 
 static BOOL CALLBACK EnumCallback(LPCDIDEVICEINSTANCE lpddi, 
                                     LPVOID lpvContext)
 {
     LPDIDEVICEINSTANCE pInstance = (LPDIDEVICEINSTANCE)lpvContext;
     if(pInstance == NULL)
         return DIENUM_STOP;
 
     if(GET_DIDEVICE_TYPE(lpddi->dwDevType) == DIDEVTYPE_JOYSTICK)
     {
         memcpy((void*)pInstance, (void*)lpddi, sizeof(*pInstance));
         return DIENUM_STOP;
     }
     return DIENUM_CONTINUE;
 }
 
 /////////////////////////////////////////////////////////
 // DxInit():
 // This function does EXACTLY the same thing as
 // the function InitSwffstick() which uses the wrapper
 // function Swff_OpenDefaultJoystick(). This function,
 // however, exclusively performs this using DirectX calls.
 /////////////////////////////////////////////////////////
 FFB_ERROR CForceFeedbackDlg::DxInit() 
 {
     // Safety check: this must update the same flag as well
     if (SWFFInitialized)
         return FFBE_NO_ERROR;
 
     // create the DirectInput object and put it in static
     // pointer pDI
     hresult = DirectInputCreate(GetModuleHandle(NULL), 
         DIRECTINPUT_VERSION, 
         &pDI, NULL);
     if(FAILED(hresult)) 
         return FFBE_JOYSTICK_INIT_FAILED;
     
     // enumerate the first attached forcefeedback joystick
     DIDEVICEINSTANCE deviceInstance;
     deviceInstance.dwDevType = 0;
     hresult = pDI->EnumDevices(DIDEVTYPE_JOYSTICK, 
         EnumCallback, 
         &deviceInstance, 
         DIEDFL_FORCEFEEDBACK);
     if (FAILED(hresult) || deviceInstance.dwDevType == 0)
     {
         RELEASE(pDI);
         return FFBE_JOYSTICK_INIT_FAILED;
     }
 
     // create DirectInput Device object. This does not have FFB methods.
     LPDIRECTINPUTDEVICE pDIDeviceObject = NULL;
     hresult = pDI->CreateDevice(deviceInstance.guidInstance, 
         &pDIDeviceObject, NULL);
     if (FAILED(hresult))
     {
         RELEASE(pDI);
         return FFBE_JOYSTICK_INIT_FAILED;
     }
 
     // get a pointer to its DirectInputDevice2 interface with FFB methods
     hresult = pDIDeviceObject->QueryInterface(IID_IDirectInputDevice2, 
         (void**) (&pDIDevice) );
     if(FAILED(hresult))
     {
         RELEASE(pDIDeviceObject);
         RELEASE(pDI);
         return FFBE_JOYSTICK_INIT_FAILED;
     }
 
     // we now have a pointer to the right COM interface. we can get
     // rid of the device object now. 
     RELEASE(pDIDeviceObject);
 
     // set the data format to the pre-defined DirectInput joystick format
     hresult = pDIDevice->SetDataFormat(&c_dfDIJoystick);
     if(FAILED(hresult))
     {
         RELEASE(pDIDevice);
         RELEASE(pDI);
         return FFBE_JOYSTICK_INIT_FAILED;
     }
 
     // set the cooperative level
     hresult = pDIDevice->SetCooperativeLevel(m_hWnd, 
         DISCL_EXCLUSIVE | DISCL_FOREGROUND);
     if(FAILED(hresult))    {
         RELEASE(pDIDevice);
         RELEASE(pDI);
         return FFBE_JOYSTICK_INIT_FAILED;
     }
 
     // turn auto-center off using set property function
     // This should be done or else the spring will confound the
     // sensation of other force effects.
     DIPROPDWORD autoCenter;
     autoCenter.diph.dwSize = sizeof(autoCenter);
     autoCenter.diph.dwHeaderSize = sizeof(DIPROPHEADER);
     autoCenter.diph.dwObj = 0;
     autoCenter.diph.dwHow = DIPH_DEVICE;
     autoCenter.dwData = 0;
 
     hresult = pDIDevice->SetProperty(DIPROP_AUTOCENTER, 
                                      &autoCenter.diph);
 //  hresult = pDIDevice->SetProperty(DIPROP_AUTOCENTER, 
 //                                   &autoCenterPropertyHeader);
     if(FAILED(hresult))
     {
         RELEASE(pDIDevice);
         RELEASE(pDI);
         return FFBE_JOYSTICK_INIT_FAILED;
     }
 
     // acquire the joystick: 
     // Generally this shouldn't be part of init, but in this
     // particular app the init is not really done before the app
     // launches but is done on demand, AFTER the app is running,
     // and ONLY when the the app is the active window, since
     // that's the only time when the user has access to the button 
     // that does the init then the acquisition.
     hresult = pDIDevice->Acquire();
     if (FAILED(hresult))
     {
         RELEASE(pDIDevice);
         RELEASE(pDI);
         return FFBE_JOYSTICK_INIT_FAILED;
     }
 
     // Finally done. Phew.
     SWFFInitialized = TRUE;
     return FFBE_NO_ERROR;    
 }
 
 // Another callback function:
 // Kill off all existing effects in the joystick
 static BOOL CALLBACK DestroyAllCreatedEffects(LPDIRECTINPUTEFFECT pEffect, 
                                               LPVOID lpvRef)
 {
     RELEASE(pEffect);
     return DIENUM_CONTINUE;
 }
 
 /////////////////////////////////////////////////////////
 // DxShutDown
 // This function does EXACTLY the same thing as
 // the function ShutdownSwffsick() which uses the wrapper
 // function Swff_DestroyAllEffects(). This function,
 // however, exclusively performs this using DirectX calls.
 /////////////////////////////////////////////////////////
 FFB_ERROR CForceFeedbackDlg::DxShutdown() 
 {
     int i;
 
     // only do this if the stick was initialized
     if (!SWFFInitialized)
         return FFBE_NO_ERROR;
 
     // Find and destroy all downloaded effects in the stick
     // Now we could decide to use our own book-keeping scheme
     // in the pEffects[] and release the existing effects in
     // our locally maintained and serviced list of effects,
     // but the following code shows what SWFF_DestroyAllEffects()
     // really does - it weeds out and eliminates all created effects.
     // It is more thorough than doing our own bookkeeping but
     // it does have the disadvantage that it would destroy someone else's
     // created effects should the app be sharing the stick with some
     // other app.
     hresult = pDIDevice->EnumCreatedEffectObjects(DestroyAllCreatedEffects, 
         NULL, 0);
     if (FAILED(hresult))
         return FFBE_JOYSTICK_SHUTDOWN_FAILED;
 
     // unacquire joystick and release DI and DI Device
     pDIDevice->Unacquire();
     RELEASE(pDIDevice);
     RELEASE(pDI);
 
     // Clean up 
     for (i = 0; i < FFB_N_TESTS; i++)
         pEffects[i] = NULL;
     pDIDevice = NULL;
     pDI = NULL;
     SWFFInitialized = FALSE;
 
     return FFBE_NO_ERROR;
 }
 
 /////////////////////////////////////////////////////////
 // DxSpring
 // This function does EXACTLY the same thing as
 // the function TestSpring() which uses the wrapper
 // function Swff_CreateSpringEffect(). This function,
 // however, exclusively performs this using DirectX calls.
 /////////////////////////////////////////////////////////
 FFB_ERROR CForceFeedbackDlg::DxSpring() 
 {
     FFB_ERROR error = FFBE_NO_ERROR;
 
     // Make sure the joystick was open to begin with before
     // attempting to start an effect
     if (!SWFFInitialized) {
         error = InitSwffstick();
         if (error) return error;
     }
 
     // If spring was already created don't go any further either
     if (pEffects[FFB_TEST_SPRING] == NULL) 
     {
 
         // Set up the Direct input condition struct to contain
         // the right effect parameters. This goes for all condition
         // effects: spring damper inertia etc.
         DICONDITION conditionEffectParams[2];
         conditionEffectParams[0].lOffset              = 0;     // centered spring
         conditionEffectParams[0].lPositiveCoefficient = 
         conditionEffectParams[0].lNegativeCoefficient = 50000; // Kx: 50.00%
         conditionEffectParams[0].dwPositiveSaturation = 
         conditionEffectParams[0].dwNegativeSaturation = 10000; // go all the way to 100%
         conditionEffectParams[0].lDeadBand            = 0;    
         conditionEffectParams[1].lOffset              = 0;
         conditionEffectParams[1].lPositiveCoefficient = 
         conditionEffectParams[1].lNegativeCoefficient = 50000; // Ky: 50.00%
         conditionEffectParams[1].dwPositiveSaturation = 
         conditionEffectParams[1].dwNegativeSaturation = 10000;
         conditionEffectParams[1].lDeadBand            = 0;
 
         // This is going to be a 2-dof spring, 2 axes.
         DWORD axes[2] = {DIJOFS_X,DIJOFS_Y};
         LONG direction[2] = {0,0};
 
         // OK, we are ready to set up the effect structure now.
         DIEFFECT springEffectStruct;
         springEffectStruct.dwSize          = sizeof(DIEFFECT);
         springEffectStruct.dwFlags         = DIEFF_OBJECTOFFSETS | DIEFF_CARTESIAN;
         springEffectStruct.dwDuration      = INFINITE;        // forever
         springEffectStruct.dwSamplePeriod  = 10000;           // 0.01s=100Hz
         springEffectStruct.dwGain          = 10000;           // 100.00%
         springEffectStruct.dwTriggerButton = DIEB_NOTRIGGER;  // don't use button
         springEffectStruct.dwTriggerRepeatInterval = 0;        
         springEffectStruct.cAxes                 = 2;          // 2 axes
         springEffectStruct.rgdwAxes              = axes;      // X and Y axes
         springEffectStruct.rglDirection          = direction; 
            // direction is meaningless for this effect
         springEffectStruct.lpEnvelope            = NULL;      // no envelope
         springEffectStruct.cbTypeSpecificParams  = sizeof(DICONDITION[2]);
         springEffectStruct.lpvTypeSpecificParams = conditionEffectParams;
 
         // Download the effect now
         hresult = pDIDevice->CreateEffect(GUID_Spring, 
             &springEffectStruct, 
             &pEffects[FFB_TEST_SPRING], NULL);
         if (FAILED(hresult))
             return FFBE_SPRING_FAILED;
 
         // Start the effect
         hresult = pEffects[FFB_TEST_SPRING]->Start(1,0);
         if (FAILED(hresult))
             return FFBE_SPRING_FAILED;
 
     }
     return FFBE_NO_ERROR;
     
 }
 
 /////////////////////////////////////////////////////////
 // DxSquare()
 // This does exactly the same thing as TestSquare()
 // but uses only DirectX calls
 /////////////////////////////////////////////////////////
 
 FFB_ERROR CForceFeedbackDlg::DxSquare() 
 {
     FFB_ERROR error = FFBE_NO_ERROR;
 
     // Make sure the joystick was open to begin with before
     // attempting to start an effect
     if (!SWFFInitialized) {
         error = InitSwffstick();
         if (error) return error;
     }
 
     // If square wave already created don't go any further 
     if (pEffects[FFB_TEST_SQUARE_WAVE] == NULL) 
     {
         // Set up the Direct input periodic struct to contain the 
         // right effect parameters.There are definitions for max magnitude 
         // and period in seconds and such but I am showing the values in 
         // their full numerical splendor so that it is easy to make the connection
         // and create a 20% magnitude by putting in 2000.
         DIPERIODIC periodicEffectStruct;
         periodicEffectStruct.dwMagnitude = 5000;    // 50%
         periodicEffectStruct.lOffset = 0;            // no offset
         periodicEffectStruct.dwPhase = 0;            // no phase shift
         periodicEffectStruct.dwPeriod = 100000;    //100000 microseconds =.1s=10Hz
                                                 
 
         DIENVELOPE squareWaveEnvelopeStruct;
         squareWaveEnvelopeStruct.dwSize = sizeof(DIENVELOPE);
         squareWaveEnvelopeStruct.dwAttackTime = 500000; // take 0.5s to ramp the 
                                                        // square wave
                                                         // to its maximum magnitude
         squareWaveEnvelopeStruct.dwAttackLevel = 0;
         squareWaveEnvelopeStruct.dwFadeTime = 0;
         squareWaveEnvelopeStruct.dwFadeLevel = 0;
 
         DWORD axes[2] = {DIJOFS_X,DIJOFS_Y};
         LONG direction[2] = {0,0};            // start out vertical: up and down
 
         DIEFFECT squareWaveEffectStruct;
         squareWaveEffectStruct.dwSize          = sizeof(DIEFFECT);
         squareWaveEffectStruct.dwFlags         = DIEFF_OBJECTOFFSETS | DIEFF_POLAR;
         squareWaveEffectStruct.dwDuration      = INFINITE;  // do this forever
         squareWaveEffectStruct.dwSamplePeriod  = 10000;     // 100Hz sample period
         squareWaveEffectStruct.dwGain          = 10000;     // 100% gain
         squareWaveEffectStruct.dwTriggerButton = DIEB_NOTRIGGER; // not tied to buttons
         squareWaveEffectStruct.dwTriggerRepeatInterval = 0;
         squareWaveEffectStruct.cAxes                 = 2;
         squareWaveEffectStruct.rgdwAxes              = axes;
         squareWaveEffectStruct.rglDirection          = direction;
         squareWaveEffectStruct.lpEnvelope            = &squareWaveEnvelopeStruct;
         squareWaveEffectStruct.cbTypeSpecificParams  = sizeof(periodicEffectStruct);
         squareWaveEffectStruct.lpvTypeSpecificParams = &periodicEffectStruct;
 
         // Create and download
         hresult = pDIDevice->CreateEffect(GUID_Square, 
             &squareWaveEffectStruct, 
             &pEffects[FFB_TEST_SQUARE_WAVE], NULL);
         if (FAILED(hresult))
             return FFBE_SQUARE_WAVE_FAILED;
                 
         // Start the effect
         hresult = (pEffects[FFB_TEST_SQUARE_WAVE])->Start(1, 0);
         if (FAILED(hresult))
             return FFBE_SQUARE_WAVE_FAILED;
     }
             
     return FFBE_NO_ERROR;
     
 }
 
 /////////////////////////////////////////////////////////
 // DxModifySquare()
 // We started with a 10Hz, 50% square wave. we will now
 // change it to 5Hz, 100% square wave.
 /////////////////////////////////////////////////////////
 
 FFB_ERROR CForceFeedbackDlg::DxModifySquare() 
 {
     FFB_ERROR error = FFBE_NO_ERROR;
 
     // Make sure the joystick was open to begin with before
     // attempting to start an effect
     if (!SWFFInitialized) {
         error = InitSwffstick();
         if (error) return error;
     }
 
     // If square wave wasn't already created don't go any further.
     // You cannot modify an effect that does not exist.
     if (pEffects[FFB_TEST_SQUARE_WAVE] == NULL)
         return FFBE_MODIFY_SQUARE_WAVE_FAILED;
     else
     {
 
         // Retrieve current parameters: first set up the structures
         // to contain the data back, then retrieve it with GetParameters()
         DIEFFECT squareWaveEffectStruct = {sizeof(DIEFFECT)};
         DIPERIODIC periodicEffectStruct = {sizeof(DIPERIODIC)};
         squareWaveEffectStruct.cbTypeSpecificParams = 
             sizeof(periodicEffectStruct);
         squareWaveEffectStruct.lpvTypeSpecificParams = &periodicEffectStruct;
         hresult = (pEffects[FFB_TEST_SQUARE_WAVE])->GetParameters(
            &squareWaveEffectStruct, 
             DIEP_TYPESPECIFICPARAMS);
         if (FAILED(hresult))
             return FFBE_MODIFY_SQUARE_WAVE_FAILED;
 
         // Modify a few parameters.
         // The standard square wave we were playing with had 50% strength
         // in the up-down direction; it was at 10Hz. we will now change
         // it to 100% strength, at 5Hz. It will be quite noticeable.
         periodicEffectStruct.dwMagnitude = 100000;    // was 50% now 100%
         periodicEffectStruct.dwPeriod = 200000;       // was 10Hz now.2s=5Hz
 
         // Modify the effect: immediately visible.
         hresult = (pEffects[FFB_TEST_SQUARE_WAVE])->SetParameters(
            &squareWaveEffectStruct, 
             DIEP_TYPESPECIFICPARAMS);
         if (FAILED(hresult))
             return FFBE_MODIFY_SQUARE_WAVE_FAILED;
     }
     return FFBE_NO_ERROR;
 
 }
 
 /////////////////////////////////////////////////////////
 // DxActuatorsOn()
 // This enables actuators to be turned on without 
 // messing with any new or existing effects
 /////////////////////////////////////////////////////////
 
 FFB_ERROR CForceFeedbackDlg::DxActuatorsOn() 
 {
     FFB_ERROR error = FFBE_NO_ERROR;
 
     // Make sure the joystick was open to begin with before
     // attempting to start an effect
     if (!SWFFInitialized) {
         error = InitSwffstick();
         if (error) return error;
     }
     
     // Turn on the actuators
     hresult = pDIDevice->SendForceFeedbackCommand(DISFFC_SETACTUATORSON);
     if (FAILED(hresult))
         return FFBE_ACTUATORS_ON_FAILED;
 
     return FFBE_NO_ERROR;
     
 }
 
 /////////////////////////////////////////////////////////
 // DxActuatorsOff()
 // This enables actuators to be turned off without 
 // messing with any new or existing effects
 /////////////////////////////////////////////////////////
 
 FFB_ERROR CForceFeedbackDlg::DxActuatorsOff() 
 {
     FFB_ERROR error = FFBE_NO_ERROR;
 
     // Make sure the joystick was open to begin with before
     // attempting to start an effect
     if (!SWFFInitialized) {
         error = InitSwffstick();
         if (error) return error;
     }
     
     // Turn on the actuators
     hresult = pDIDevice->SendForceFeedbackCommand(DISFFC_SETACTUATORSOFF);
     if (FAILED(hresult))
         return FFBE_ACTUATORS_OFF_FAILED;
 
     return FFBE_NO_ERROR;
     
 }