// DirectXHelpers.cpp: implementation of the CDirectXHelpers class.
//
//////////////////////////////////////////////////////////////////////

#include "DirectXHelpers.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

HRESULT MyDirectSoundCreate(LPGUID pGuid,LPDIRECTSOUND *ppDirectSound, LPUNKNOWN pUnknown)
{
    HMODULE hDSound;
    HRESULT hrReturn = DDERR_GENERIC;
    HRESULT (__stdcall *pFunc)(LPGUID ,LPDIRECTSOUND *, LPUNKNOWN );

    hDSound = LoadLibrary(TEXT("dsound.dll"));
    if (hDSound != NULL)
    {
#ifdef _WIN32_WCE
        pFunc = (HRESULT (__stdcall *)(LPGUID ,LPDIRECTSOUND *, LPUNKNOWN ))GetProcAddress(hDSound,L"DirectSoundCreate");
#else
        pFunc = (HRESULT (__stdcall *)(LPGUID ,LPDIRECTSOUND *, LPUNKNOWN ))GetProcAddress(hDSound,"DirectSoundCreate");
#endif
        if (pFunc)
        {
            hrReturn = pFunc(pGuid,ppDirectSound,pUnknown);
        }
    }

    return hrReturn;
}

HRESULT MyDirectDrawCreate(LPGUID pGuid,LPDIRECTDRAW *ppDirectDraw, LPUNKNOWN pUnknown)
{
    HMODULE hDDraw;
    HRESULT hrReturn = DDERR_GENERIC;
    HRESULT (__stdcall *pFunc)(LPGUID ,LPDIRECTDRAW *, LPUNKNOWN );

    hDDraw = LoadLibrary(TEXT("ddraw.dll"));
    if (hDDraw != NULL)
    {
#ifdef _WIN32_WCE
        pFunc = (HRESULT (__stdcall *)(LPGUID ,LPDIRECTDRAW *, LPUNKNOWN )) GetProcAddress(hDDraw,L"DirectDrawCreate");
#else
        pFunc = (HRESULT (__stdcall *)(LPGUID ,LPDIRECTDRAW *, LPUNKNOWN )) GetProcAddress(hDDraw,"DirectDrawCreate");
#endif
        if (pFunc)
        {
            hrReturn = pFunc(pGuid,ppDirectDraw,pUnknown);
        }
    }

    return hrReturn;
}

HRESULT MyDirectInputCreate(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUT *ppDI, LPUNKNOWN punkOuter)
{
    HMODULE hDInput;
    HRESULT hrReturn = DDERR_GENERIC;
    HRESULT (__stdcall *pFunc)(HINSTANCE , DWORD, LPDIRECTINPUT *, LPUNKNOWN );

    hDInput = LoadLibrary(TEXT("dinput.dll"));
    if (hDInput != NULL)
    {
#ifdef _WIN32_WCE
        pFunc = (HRESULT (__stdcall *)(HINSTANCE , DWORD, LPDIRECTINPUT *, LPUNKNOWN )) GetProcAddress(hDInput,L"DirectInputCreateW");
#else
        pFunc = (HRESULT (__stdcall *)(HINSTANCE , DWORD, LPDIRECTINPUT *, LPUNKNOWN )) GetProcAddress(hDInput,"DirectInputCreateW");
#endif
        if (pFunc)
        {
            hrReturn = pFunc(hinst,dwVersion,ppDI,punkOuter);
        }
    }

    return hrReturn;
}



typedef struct _RIFFHEADER
{
    char id[4];
    DWORD len;
} RIFFHEADER;



DWORD GetWaveData(WCHAR *wszFileName, WAVEFORMATEX *pWaveFormat,
                  BYTE **pbtChannel1, DWORD *pdwChannel1Length,
                  BYTE **pbtChannel2, DWORD *pdwChannel2Length)
{
    RIFFHEADER FileHeader;
    RIFFHEADER RiffHeader;
//    WAVEFORMATEX WaveFormatEx;
    HANDLE hFile;
    DWORD dwRetVal = 1;
    DWORD dwBytesRead;
    CHAR szTemp[200];
    BOOL bDone;

    hFile = CreateFile(wszFileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
    if (hFile != INVALID_HANDLE_VALUE)
    {
        ReadFile(hFile,&FileHeader,sizeof(RIFFHEADER),&dwBytesRead,NULL);
        ReadFile(hFile,szTemp,4,&dwBytesRead,NULL);
        szTemp[4] = 0;
        if (strcmp(szTemp,"WAVE") != 0)
        {
            CloseHandle(hFile);
            return dwRetVal;
        }

        bDone = FALSE;
        //search for the wave header info
        while (!bDone)
        {
            ReadFile(hFile,&RiffHeader,sizeof(RIFFHEADER),&dwBytesRead,NULL);
            if (!dwBytesRead)
                break;

            if (memcmp(RiffHeader.id,"fmt ",4) == 0)
            {
                switch (RiffHeader.len)
                {
                case 16:
                    ReadFile(hFile,pWaveFormat,sizeof(PCMWAVEFORMAT),&dwBytesRead,NULL);
                    pWaveFormat->cbSize = 0;
                    break;
                case 12:
                    ReadFile(hFile,pWaveFormat,sizeof(WAVEFORMAT),&dwBytesRead,NULL);
                    pWaveFormat->cbSize = 0;
                    pWaveFormat->wBitsPerSample = 0;
                    break;
                case 20:
                    ReadFile(hFile,pWaveFormat,sizeof(WAVEFORMATEX),&dwBytesRead,NULL);
                    break;
                }
            } 
            else if (memcmp(RiffHeader.id,"data",4) == 0)
            {
                bDone = TRUE;
            }
        }

        if (bDone)
        {
            //time to read in data
            if (pWaveFormat->nChannels == 1)
            {
                *pdwChannel1Length = RiffHeader.len;
                *pbtChannel1 = (BYTE *)malloc(sizeof(BYTE)*RiffHeader.len);
                //sound data is mono
                *pdwChannel2Length = 0;
                ReadFile(hFile,*pbtChannel1,RiffHeader.len,&dwBytesRead,NULL);
                dwRetVal = 0;
            }
            else if (pWaveFormat->nChannels == 2)
            {
                //sound data is stereo, we need to parse out each channel
                *pdwChannel1Length = RiffHeader.len/2;
                *pbtChannel1 = (BYTE *)malloc(sizeof(BYTE)*RiffHeader.len);
                *pdwChannel2Length = RiffHeader.len/2;
                *pbtChannel2 = (BYTE *)malloc(sizeof(BYTE)*RiffHeader.len);
            }
        }
        CloseHandle(hFile);
    }
    else
    {
        dwBytesRead = GetLastError();
    }

    return dwRetVal;
}

DWORD OpenWaveFile(WCHAR *wszFileName)
{
    

    return 0;
}


//guid defines from some library
#define MYDEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
        const GUID name \
                = { l, w1, w2, { b1, b2,  b3,  b4,  b5,  b6,  b7,  b8 } }

/****************************************************************************
 *
 *      Class IDs
 *
 ****************************************************************************/

MYDEFINE_GUID(CLSID_DirectInput,      0x25E609E0,0xB259,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
MYDEFINE_GUID(CLSID_DirectInputDevice,0x25E609E1,0xB259,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
MYDEFINE_GUID(CLSID_DirectSound, 0x47d4d946, 0x62e8, 0x11cf, 0x93, 0xbc, 0x44, 0x45, 0x53, 0x54, 0x0, 0x0);
MYDEFINE_GUID(CLSID_DirectDraw,			0xD7B70EE0,0x4340,0x11CF,0xB0,0x63,0x00,0x20,0xAF,0xC2,0xCD,0x35 );

/****************************************************************************
 *
 *      Interfaces
 *
 ****************************************************************************/

MYDEFINE_GUID(IID_IDirectDraw,			0x6C14DB80,0xA733,0x11CE,0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60 );
MYDEFINE_GUID(IID_IDirectDraw2,                  0xB3A6F3E0,0x2B43,0x11CF,0xA2,0xDE,0x00,0xAA,0x00,0xB9,0x33,0x56 );
MYDEFINE_GUID(IID_IDirectSound, 0x279AFA83, 0x4981, 0x11CE, 0xA5, 0x21, 0x00, 0x20, 0xAF, 0x0B, 0xE5, 0x60);


MYDEFINE_GUID(IID_IDirectInputA,     0x89521360,0xAA8A,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
MYDEFINE_GUID(IID_IDirectInputW,     0x89521361,0xAA8A,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
MYDEFINE_GUID(IID_IDirectInput2A,    0x5944E662,0xAA8A,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
MYDEFINE_GUID(IID_IDirectInput2W,    0x5944E663,0xAA8A,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);

MYDEFINE_GUID(IID_IDirectInputDeviceA, 0x5944E680,0xC92E,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
MYDEFINE_GUID(IID_IDirectInputDeviceW, 0x5944E681,0xC92E,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
MYDEFINE_GUID(IID_IDirectInputDevice2A,0x5944E682,0xC92E,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
MYDEFINE_GUID(IID_IDirectInputDevice2W,0x5944E683,0xC92E,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);

MYDEFINE_GUID(IID_IDirectInputEffect,  0xE7E1F7C0,0x88D2,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35);

/****************************************************************************
 *
 *      Predefined object types
 *
 ****************************************************************************/

MYDEFINE_GUID(GUID_XAxis,   0xA36D02E0,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
MYDEFINE_GUID(GUID_YAxis,   0xA36D02E1,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
MYDEFINE_GUID(GUID_ZAxis,   0xA36D02E2,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
MYDEFINE_GUID(GUID_RxAxis,  0xA36D02F4,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
MYDEFINE_GUID(GUID_RyAxis,  0xA36D02F5,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
MYDEFINE_GUID(GUID_RzAxis,  0xA36D02E3,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
MYDEFINE_GUID(GUID_Slider,  0xA36D02E4,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);

MYDEFINE_GUID(GUID_Button,  0xA36D02F0,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
MYDEFINE_GUID(GUID_Key,     0x55728220,0xD33C,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);

MYDEFINE_GUID(GUID_POV,     0xA36D02F2,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);

MYDEFINE_GUID(GUID_Unknown, 0xA36D02F3,0xC9F3,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);

/****************************************************************************
 *
 *      Predefined product GUIDs
 *
 ****************************************************************************/

MYDEFINE_GUID(GUID_SysMouse,   0x6F1D2B60,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
MYDEFINE_GUID(GUID_SysKeyboard,0x6F1D2B61,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
MYDEFINE_GUID(GUID_Joystick   ,0x6F1D2B70,0xD5A0,0x11CF,0xBF,0xC7,0x44,0x45,0x53,0x54,0x00,0x00);
/****************************************************************************
 *
 *      Predefined force feedback effects
 *
 ****************************************************************************/

MYDEFINE_GUID(GUID_ConstantForce,0x13541C20,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35);
MYDEFINE_GUID(GUID_RampForce,    0x13541C21,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35);
MYDEFINE_GUID(GUID_Square,       0x13541C22,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35);
MYDEFINE_GUID(GUID_Sine,         0x13541C23,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35);
MYDEFINE_GUID(GUID_Triangle,     0x13541C24,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35);
MYDEFINE_GUID(GUID_SawtoothUp,   0x13541C25,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35);
MYDEFINE_GUID(GUID_SawtoothDown, 0x13541C26,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35);
MYDEFINE_GUID(GUID_Spring,       0x13541C27,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35);
MYDEFINE_GUID(GUID_Damper,       0x13541C28,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35);
MYDEFINE_GUID(GUID_Inertia,      0x13541C29,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35);
MYDEFINE_GUID(GUID_Friction,     0x13541C2A,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35);
MYDEFINE_GUID(GUID_CustomForce,  0x13541C2B,0x8E33,0x11D0,0x9A,0xD0,0x00,0xA0,0xC9,0xA0,0x6E,0x35);


 