home *** CD-ROM | disk | FTP | other *** search
/ Game Audio Programming / GameAudioProgramming.iso / Extras / Sensaura / SDK1.0 / data1.cab / Example_Files / DS3DDemo / Source / directx.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-13  |  21.5 KB  |  515 lines

  1. /*
  2.     Company:            Sensaura
  3.     Copyright:          (C) 1998
  4.  
  5.     File Name:            directx.cpp
  6.     File Description:    Source file for implementation of DirectX error handling functions
  7.     Author:                Adam Philp
  8.     File Version:        1.02.000
  9.     Last Update:        19-APR-200
  10.  
  11.     Target Compiler:    Microsoft Visual C++ Version 5.0
  12. */
  13.  
  14. ///////////////////////    Included files ////////////////////////////////////////////////////////////
  15.  
  16. //#define __PCH    "stdafx.h"                // Precompiled header for MFC applications
  17. #define __PCH    <windows.h>                // Precompiled header for non-MFC applications
  18.  
  19. #include __PCH
  20.  
  21. #include <mmsystem.h>
  22. #include <d3drm.h>                        // Include all DirectX header files
  23. #include <ddraw.h>                        
  24. #include <dsound.h>
  25. #include <dinput.h>
  26.  
  27. #include "directx.h"                    // Function and macro declarations
  28.  
  29. #ifndef _MFC_VER                        // Use MFC TRACE macro if available
  30. #include "debug.h"                        // Use our own error handlers otherwise
  31. #endif
  32.  
  33.  
  34. /////////////////////// Global variables //////////////////////////////////////////////////////////
  35.  
  36. HRESULT g_hrDD = DD_OK;                    // DirectX error codes
  37. HRESULT g_hrD3DRM = D3DRM_OK;
  38. HRESULT g_hrD3D = D3D_OK;
  39. HRESULT g_hrDS = DS_OK;
  40. HRESULT g_hrDI = DI_OK;
  41.  
  42. /////////////////////// Local functions ///////////////////////////////////////////////////////////
  43.  
  44. /*
  45.     Function:            DirectXErrorToString
  46.     Description:        Translates a DirectX HRESULT value into a meaningful string which can be
  47.                         used for Message boxes, debugging etc.
  48.     Parameters:            hrError - the HRESULT value to translate
  49.     Return value:        Pointer to the translated string
  50. */
  51.  
  52. const char* DirectXErrorToString(HRESULT hrError)
  53. {
  54.     switch(hrError) 
  55.     {   
  56.     case DD_OK:                            // Also includes D3D_OK, D3DRM_OK, DS_OK, DI_OK, D3D_OK
  57.         return "No error.\0";
  58.  
  59.     case DDERR_ALREADYINITIALIZED:        // DirectDraw error codes
  60.         return "This object is already initialized.\0";
  61.     case DDERR_BLTFASTCANTCLIP:
  62.         return "Return if a clipper object is attached to the source surface passed into a BltFast call.\0";
  63.     case DDERR_CANNOTATTACHSURFACE:
  64.         return "This surface can not be attached to the requested surface.\0";
  65.     case DDERR_CANNOTDETACHSURFACE:
  66.         return "This surface can not be detached from the requested surface.\0";
  67.     case DDERR_CANTCREATEDC:
  68.         return "Windows can not create any more DCs.\0";
  69.     case DDERR_CANTDUPLICATE:
  70.         return "Can't duplicate primary & 3D surfaces, or surfaces that are implicitly created.\0";
  71.     case DDERR_CLIPPERISUSINGHWND:
  72.         return "An attempt was made to set a cliplist for a clipper object that is already monitoring an hwnd.\0";
  73.     case DDERR_COLORKEYNOTSET:
  74.         return "No src color key specified for this operation.\0";
  75.     case DDERR_CURRENTLYNOTAVAIL:
  76.         return "Support is currently not available.\0";
  77.     case DDERR_DIRECTDRAWALREADYCREATED:
  78.         return "A DirectDraw object representing this driver has already been created for this process.\0";
  79.     case DDERR_EXCEPTION:
  80.         return "An exception was encountered while performing the requested operation.\0";
  81.     case DDERR_EXCLUSIVEMODEALREADYSET:
  82.         return "An attempt was made to set the cooperative level when it was already set to exclusive.\0";
  83.     case DDERR_GENERIC:
  84.         return "Generic failure.\0";
  85.     case DDERR_HEIGHTALIGN:
  86.         return "Height of rectangle provided is not a multiple of reqd alignment.\0";
  87.     case DDERR_HWNDALREADYSET:
  88.         return "The CooperativeLevel HWND has already been set. It can not be reset while the process has surfaces or palettes created.\0";
  89.     case DDERR_HWNDSUBCLASSED:
  90.         return "HWND used by DirectDraw CooperativeLevel has been subclassed, this prevents DirectDraw from restoring state.\0";
  91.     case DDERR_IMPLICITLYCREATED:
  92.         return "This surface can not be restored because it is an implicitly created surface.\0";
  93.     case DDERR_INCOMPATIBLEPRIMARY:
  94.         return "Unable to match primary surface creation request with existing primary surface.\0";
  95.     case DDERR_INVALIDCAPS:
  96.         return "One or more of the caps bits passed to the callback are incorrect.\0";
  97.     case DDERR_INVALIDCLIPLIST:
  98.         return "DirectDraw does not support the provided cliplist.\0";
  99.     case DDERR_INVALIDDIRECTDRAWGUID:
  100.         return "The GUID passed to DirectDrawCreate is not a valid DirectDraw driver identifier.\0";
  101.     case DDERR_INVALIDMODE:
  102.         return "DirectDraw does not support the requested mode.\0";
  103.     case DDERR_INVALIDOBJECT:
  104.         return "DirectDraw received a pointer that was an invalid DIRECTDRAW object.\0";
  105.     case DDERR_INVALIDPARAMS:
  106.         return "One or more of the parameters passed to the function are incorrect.\0";
  107.     case DDERR_INVALIDPIXELFORMAT:
  108.         return "The pixel format was invalid as specified.\0";
  109.     case DDERR_INVALIDPOSITION:
  110.         return "Returned when the position of the overlay on the destination is no longer legal for that destination.\0";
  111.     case DDERR_INVALIDRECT:
  112.         return "Rectangle provided was invalid.\0";
  113.     case DDERR_LOCKEDSURFACES:
  114.         return "Operation could not be carried out because one or more surfaces are locked.\0";
  115.     case DDERR_NO3D:
  116.         return "There is no 3D present.\0";
  117.     case DDERR_NOALPHAHW:
  118.         return "Operation could not be carried out because there is no alpha accleration hardware present or available.\0";
  119.     case DDERR_NOBLTHW:
  120.         return "No blitter hardware present.\0";
  121.     case DDERR_NOCLIPLIST:
  122.         return "No cliplist available.\0";
  123.     case DDERR_NOCLIPPERATTACHED:
  124.         return "No clipper object attached to surface object.\0";
  125.     case DDERR_NOCOLORCONVHW:
  126.         return "Operation could not be carried out because there is no color conversion hardware present or available.\0";
  127.     case DDERR_NOCOLORKEY:
  128.         return "Surface doesn't currently have a color key\0";
  129.     case DDERR_NOCOLORKEYHW:
  130.         return "Operation could not be carried out because there is no hardware support of the destination color key.\0";
  131.     case DDERR_NOCOOPERATIVELEVELSET:
  132.         return "Create function called without DirectDraw object method SetCooperativeLevel being called.\0";
  133.     case DDERR_NODC:
  134.         return "No DC was ever created for this surface.\0";
  135.     case DDERR_NODDROPSHW:
  136.         return "No DirectDraw ROP hardware.\0";
  137.     case DDERR_NODIRECTDRAWHW:
  138.         return "A hardware-only DirectDraw object creation was attempted but the driver did not support any hardware.\0";
  139.     case DDERR_NOEMULATION:
  140.         return "Software emulation not available.\0";
  141.     case DDERR_NOEXCLUSIVEMODE:
  142.         return "Operation requires the application to have exclusive mode but the application does not have exclusive mode.\0";
  143.     case DDERR_NOFLIPHW:
  144.         return "Flipping visible surfaces is not supported.\0";
  145.     case DDERR_NOGDI:
  146.         return "There is no GDI present.\0";
  147.     case DDERR_NOHWND:
  148.         return "Clipper notification requires an HWND or no HWND has previously been set as the CooperativeLevel HWND.\0";
  149.     case DDERR_NOMIRRORHW:
  150.         return "Operation could not be carried out because there is no hardware present or available.\0";
  151.     case DDERR_NOOVERLAYDEST:
  152.         return "Returned when GetOverlayPosition is called on an overlay that UpdateOverlay has never been called on to establish a destination.\0";
  153.     case DDERR_NOOVERLAYHW:
  154.         return "Operation could not be carried out because there is no overlay hardware present or available.\0";
  155.     case DDERR_NOPALETTEATTACHED:
  156.         return "No palette object attached to this surface.\0";
  157.     case DDERR_NOPALETTEHW:
  158.         return "No hardware support for 16 or 256 color palettes.\0";
  159.     case DDERR_NORASTEROPHW:
  160.         return "Operation could not be carried out because there is no appropriate raster op hardware present or available.\0";
  161.     case DDERR_NOROTATIONHW:
  162.         return "Operation could not be carried out because there is no rotation hardware present or available.\0";
  163.     case DDERR_NOSTRETCHHW:
  164.         return "Operation could not be carried out because there is no hardware support for stretching.\0";
  165.     case DDERR_NOT4BITCOLOR:
  166.         return "DirectDrawSurface is not in 4 bit color palette and the requested operation requires 4 bit color palette.\0";
  167.     case DDERR_NOT4BITCOLORINDEX:
  168.         return "DirectDrawSurface is not in 4 bit color index palette and the requested operation requires 4 bit color index palette.\0";
  169.     case DDERR_NOT8BITCOLOR:
  170.         return "DirectDrawSurface is not in 8 bit color mode and the requested operation requires 8 bit color.\0";
  171.     case DDERR_NOTAOVERLAYSURFACE:
  172.         return "Returned when an overlay member is called for a non-overlay surface.\0";
  173.     case DDERR_NOTEXTUREHW:
  174.         return "Operation could not be carried out because there is no texture mapping hardware present or available.\0";
  175.     case DDERR_NOTFLIPPABLE:
  176.         return "An attempt has been made to flip a surface that is not flippable.\0";
  177.     case DDERR_NOTFOUND:
  178.         return "Requested item was not found.\0";
  179.     case DDERR_NOTLOCKED:
  180.         return "Surface was not locked.  An attempt to unlock a surface that was not locked at all, or by this process, has been attempted.\0";
  181.     case DDERR_NOTPALETTIZED:
  182.         return "The surface being used is not a palette-based surface.\0";
  183.     case DDERR_NOVSYNCHW:
  184.         return "Operation could not be carried out because there is no hardware support for vertical blank synchronized operations.\0";
  185.     case DDERR_NOZBUFFERHW:
  186.         return "Operation could not be carried out because there is no hardware support for zbuffer blitting.\0";
  187.     case DDERR_NOZOVERLAYHW:
  188.         return "Overlay surfaces could not be z layered based on their BltOrder because the hardware does not support z layering of overlays.\0";
  189.     case DDERR_OUTOFCAPS:
  190.         return "The hardware needed for the requested operation has already been allocated.\0";
  191.     case DDERR_OUTOFMEMORY:
  192.         return "DirectX does not have enough memory to perform the operation.\0";
  193.     case DDERR_OUTOFVIDEOMEMORY:
  194.         return "DirectDraw does not have enough memory to perform the operation.\0";
  195.     case DDERR_OVERLAYCANTCLIP:
  196.         return "The hardware does not support clipped overlays.\0";
  197.     case DDERR_OVERLAYCOLORKEYONLYONEACTIVE:
  198.         return "Can only have ony color key active at one time for overlays.\0";
  199.     case DDERR_OVERLAYNOTVISIBLE:
  200.         return "Returned when GetOverlayPosition is called on a hidden overlay.\0";
  201.     case DDERR_PALETTEBUSY:
  202.         return "Access to this palette is being refused because the palette is already locked by another thread.\0";
  203.     case DDERR_PRIMARYSURFACEALREADYEXISTS:
  204.         return "This process already has created a primary surface.\0";
  205.     case DDERR_REGIONTOOSMALL:
  206.         return "Region passed to Clipper::GetClipList is too small.\0";
  207.     case DDERR_SURFACEALREADYATTACHED:
  208.         return "This surface is already attached to the surface it is being attached to.\0";
  209.     case DDERR_SURFACEALREADYDEPENDENT:
  210.         return "This surface is already a dependency of the surface it is being made a dependency of.\0";
  211.     case DDERR_SURFACEBUSY:
  212.         return "Access to this surface is being refused because the surface is already locked by another thread.\0";
  213.     case DDERR_SURFACEISOBSCURED:
  214.         return "Access to surface refused because the surface is obscured.\0";
  215.     case DDERR_SURFACELOST:
  216.         return "Access to this surface is being refused because the surface memory is gone. The DirectDrawSurface object representing this surface should have Restore called on it.\0";
  217.     case DDERR_SURFACENOTATTACHED:
  218.         return "The requested surface is not attached.\0";
  219.     case DDERR_TOOBIGHEIGHT:
  220.         return "Height requested by DirectDraw is too large.\0";
  221.     case DDERR_TOOBIGSIZE:
  222.         return "Size requested by DirectDraw is too large, but the individual height and width are OK.\0";
  223.     case DDERR_TOOBIGWIDTH:
  224.         return "Width requested by DirectDraw is too large.\0";
  225.     case DDERR_UNSUPPORTED:
  226.         return "Action not supported.\0";
  227.     case DDERR_UNSUPPORTEDFORMAT:
  228.         return "FOURCC format requested is unsupported by DirectDraw.\0";
  229.     case DDERR_UNSUPPORTEDMASK:
  230.         return "Bitmask in the pixel format requested is unsupported by DirectDraw.\0";
  231.     case DDERR_VERTICALBLANKINPROGRESS:
  232.         return "Vertical blank is in progress.\0";
  233.     case DDERR_WASSTILLDRAWING:
  234.         return "Informs DirectDraw that the previous Blt which is transfering information to or from this Surface is incomplete.\0";
  235.     case DDERR_WRONGMODE:
  236.         return "This surface can not be restored because it was created in a different mode.\0";
  237.     case DDERR_XALIGN:
  238.         return "Rectangle provided was not horizontally aligned on required boundary.\0";
  239.      
  240.     case D3DERR_BADMAJORVERSION:        // Direct3D error codes
  241.         return "D3DERR_BADMAJORVERSION\0";
  242.     case D3DERR_BADMINORVERSION:
  243.         return "D3DERR_BADMINORVERSION\0";
  244.     case D3DERR_EXECUTE_LOCKED:
  245.         return "D3DERR_EXECUTE_LOCKED\0";
  246.     case D3DERR_EXECUTE_NOT_LOCKED:
  247.         return "D3DERR_EXECUTE_NOT_LOCKED\0";
  248.     case D3DERR_EXECUTE_CREATE_FAILED:
  249.         return "D3DERR_EXECUTE_CREATE_FAILED\0";
  250.     case D3DERR_EXECUTE_DESTROY_FAILED:
  251.         return "D3DERR_EXECUTE_DESTROY_FAILED\0";
  252.     case D3DERR_EXECUTE_LOCK_FAILED:
  253.         return "D3DERR_EXECUTE_LOCK_FAILED\0";
  254.     case D3DERR_EXECUTE_UNLOCK_FAILED:
  255.         return "D3DERR_EXECUTE_UNLOCK_FAILED\0";
  256.     case D3DERR_EXECUTE_FAILED:
  257.         return "D3DERR_EXECUTE_FAILED\0";
  258.     case D3DERR_EXECUTE_CLIPPED_FAILED:
  259.         return "D3DERR_EXECUTE_CLIPPED_FAILED\0";
  260.     case D3DERR_TEXTURE_NO_SUPPORT:
  261.         return "D3DERR_TEXTURE_NO_SUPPORT\0";
  262.     case D3DERR_TEXTURE_NOT_LOCKED:
  263.         return "D3DERR_TEXTURE_NOT_LOCKED\0";
  264.     case D3DERR_TEXTURE_LOCKED:
  265.         return "D3DERR_TEXTURELOCKED\0";
  266.     case D3DERR_TEXTURE_CREATE_FAILED:
  267.         return "D3DERR_TEXTURE_CREATE_FAILED\0";
  268.     case D3DERR_TEXTURE_DESTROY_FAILED:
  269.         return "D3DERR_TEXTURE_DESTROY_FAILED\0";
  270.     case D3DERR_TEXTURE_LOCK_FAILED:
  271.         return "D3DERR_TEXTURE_LOCK_FAILED\0";
  272.     case D3DERR_TEXTURE_UNLOCK_FAILED:
  273.         return "D3DERR_TEXTURE_UNLOCK_FAILED\0";
  274.     case D3DERR_TEXTURE_LOAD_FAILED:
  275.         return "D3DERR_TEXTURE_LOAD_FAILED\0";
  276.     case D3DERR_MATRIX_CREATE_FAILED:
  277.         return "D3DERR_MATRIX_CREATE_FAILED\0";
  278.     case D3DERR_MATRIX_DESTROY_FAILED:
  279.         return "D3DERR_MATRIX_DESTROY_FAILED\0";
  280.     case D3DERR_MATRIX_SETDATA_FAILED:
  281.         return "D3DERR_MATRIX_SETDATA_FAILED\0";
  282.     case D3DERR_SETVIEWPORTDATA_FAILED:
  283.         return "D3DERR_SETVIEWPORTDATA_FAILED\0";
  284.     case D3DERR_MATERIAL_CREATE_FAILED:
  285.         return "D3DERR_MATERIAL_CREATE_FAILED\0";
  286.     case D3DERR_MATERIAL_DESTROY_FAILED:
  287.         return "D3DERR_MATERIAL_DESTROY_FAILED\0";
  288.     case D3DERR_MATERIAL_SETDATA_FAILED:
  289.         return "D3DERR_MATERIAL_SETDATA_FAILED\0";
  290.     case D3DERR_LIGHT_SET_FAILED:
  291.         return "D3DERR_LIGHT_SET_FAILED\0";
  292.  
  293.     case D3DRMERR_BADOBJECT:            // Direct3D retained mode errors
  294.         return "D3DRMERR_BADOBJECT\0";
  295.     case D3DRMERR_BADTYPE:
  296.         return "D3DRMERR_BADTYPE\0";
  297.     case D3DRMERR_BADALLOC:
  298.         return "D3DRMERR_BADALLOC\0";
  299.     case D3DRMERR_FACEUSED:
  300.         return "D3DRMERR_FACEUSED\0";
  301.     case D3DRMERR_NOTFOUND:
  302.         return "D3DRMERR_NOTFOUND\0";
  303.     case D3DRMERR_NOTDONEYET:
  304.         return "D3DRMERR_NOTDONEYET\0";
  305.     case D3DRMERR_FILENOTFOUND:
  306.         return "The file was not found.\0";
  307.     case D3DRMERR_BADFILE:
  308.         return "D3DRMERR_BADFILE\0";
  309.     case D3DRMERR_BADDEVICE:
  310.         return "D3DRMERR_BADDEVICE\0";
  311.     case D3DRMERR_BADVALUE:
  312.         return "D3DRMERR_BADVALUE\0";
  313.     case D3DRMERR_BADMAJORVERSION:
  314.         return "D3DRMERR_BADMAJORVERSION\0";
  315.     case D3DRMERR_BADMINORVERSION:
  316.         return "D3DRMERR_BADMINORVERSION\0";
  317.     case D3DRMERR_UNABLETOEXECUTE:
  318.         return "D3DRMERR_UNABLETOEXECUTE\0";
  319.     
  320.     case DSERR_ALLOCATED:                // DirectSound errors
  321.         return "DSERR_ALLOCATED\0";
  322.     case DSERR_ALREADYINITIALIZED: 
  323.         return "DSERR_ALREADYINITIALIZED\0";
  324.     case DSERR_BADFORMAT: 
  325.         return "DSERR_BADFORMAT\0";
  326.     case DSERR_BUFFERLOST: 
  327.         return "DSERR_BUFFERLOST\0";
  328.     case DSERR_CONTROLUNAVAIL: 
  329.         return "DSERR_CONTROLUNAVAIL\0";
  330.     case DSERR_INVALIDCALL: 
  331.         return "DSERR_INVALIDCALL\0";
  332.     case DSERR_NOAGGREGATION: 
  333.         return "DSERR_NOAGGREGATION\0";
  334.     case DSERR_NODRIVER:
  335.         return "DSERR_NODRIVER\0";
  336.     case DSERR_NOINTERFACE: 
  337.         return "DSERR_NOINTERFACE\0";
  338.     case DSERR_OTHERAPPHASPRIO: 
  339.         return "DSERR_OTHERAPPHASPRIO\0";
  340.     case DSERR_PRIOLEVELNEEDED: 
  341.         return "DSERR_PRIOLEVELNEEDED\0";
  342.     case DSERR_UNINITIALIZED: 
  343.         return "DSERR_UNINITIALIZED\0";
  344.  
  345.     default:
  346.         return NULL;
  347.     }
  348. }
  349.  
  350. /////////////////////// Global functions //////////////////////////////////////////////////////////
  351.  
  352. /*
  353.     Function:            DirectXErrorMessageBox
  354.     Description:        Display a message box describing a DirectX error code
  355.     Parameters:            hrError - the HRESULT value to translate
  356. */
  357.  
  358. void DirectXErrorMessageBox(HRESULT hrError)
  359. {
  360.     char        str[255];
  361.     const char* strError;
  362.     const char* strMessage;
  363.                                         // Convert DirectX error code into a meaningful string
  364.     strError = DirectXErrorToString(hrError);
  365.     if(strError)                        // Did we recognize this error code?
  366.         strMessage = strError;            // Yes, so display the string
  367.     else 
  368.     {                                    // No, so display the error code
  369.         wsprintf(str, "Unrecognized error code: %08X", hrError);
  370.         strMessage = str;
  371.     }
  372. #ifdef _MFC_VER
  373.     TRACE("DirectX Error: %s\n", strMessage);
  374. #else
  375.     TRACE(0, "DirectX Error: %s\n", strMessage);
  376. #endif
  377.     MessageBox(NULL, strMessage, "DirectX Error", MB_ICONEXCLAMATION|MB_OK);
  378. }
  379.  
  380. /*
  381.     Function:            DirectXOK
  382.     Description:        Check whether any DirectX errors have occurred
  383.     Return value:        true if no DirectX errors have occurred, false otherwise
  384. */
  385.  
  386. bool DirectXOK()
  387.     return (g_hrDD || g_hrD3DRM || g_hrDS || g_hrDI) ? false : true; 
  388. }
  389.  
  390. /*
  391.     Function:            RandomD3DVALUE
  392.     Description:        Returns a random D3DVALUE within the specified range
  393.     Parameters:            min - the minimum allowed value of the returned D3DVALUE
  394.                         max - the maximum allowed value of the returned D3DVALUE
  395.     Return value:        A random D3DVALUE in the specified range
  396. */
  397.  
  398. D3DVALUE RandomD3DVALUE(double min, double max)
  399. {
  400.     double range;
  401.     double value;
  402.  
  403.     range = max-min;
  404.     value = range*(double)rand()/(double)RAND_MAX;
  405.     return(D3DVALUE)(value+min);
  406. }
  407.  
  408. /*
  409.     Function:            CreateDSBufferFromResource
  410.     Description:        Create a DirectSound buffer with the specified properties from the 
  411.                         specified resource
  412.     Parameters:            pDS - pointer to DirectSound
  413.                         dwFlags - the capabilities of the DirectSound
  414.                         pRes - resource ID string
  415.     Return value:        A pointer to the newly created buffer if successful, NULL otherwise
  416. */
  417.  
  418. LPDIRECTSOUNDBUFFER CreateDSBufferFromResource(LPDIRECTSOUND pDS, DWORD dwFlags, LPCTSTR pcszRes)
  419. {
  420.     LPDIRECTSOUNDBUFFER pBuffer = NULL;
  421.                                         // First, lock the WAVE resource in memory
  422.     HMODULE hModule = GetModuleHandle(NULL);
  423.     if(hModule == NULL)
  424.         return NULL;
  425.  
  426.     HRSRC hResInfo = FindResource(hModule, pcszRes, "WAVE");
  427.     if(hResInfo == NULL)
  428.         return NULL;
  429.  
  430.     HGLOBAL hResData = LoadResource(hModule, hResInfo);
  431.     if(hResData == NULL)
  432.         return NULL;
  433.  
  434.     LPVOID pRes = LockResource(hResData);
  435.     if(pRes == NULL)
  436.         return NULL;
  437.  
  438.      DSBUFFERDESC dsbd;                    // Next, extract the audio data from the resource and
  439.                                         // set up the DirectSound buffer description
  440.     dsbd.dwSize = sizeof(DSBUFFERDESC);    
  441.     dsbd.dwFlags = dwFlags;
  442.     dsbd.dwBufferBytes = 0;
  443.     dsbd.dwReserved = 0;
  444.     dsbd.lpwfxFormat = 0;                
  445.  
  446.     LPBYTE pData = NULL;
  447.  
  448.      bool bDataReady = false;
  449.     LPDWORD    pdw = (LPDWORD)pRes;
  450.     DWORD dwRiff = *pdw++;
  451.     DWORD dwLength = *pdw++;
  452.     DWORD dwType = *pdw++;
  453.  
  454.     if(dwRiff != mmioFOURCC('R', 'I', 'F', 'F'))
  455.         return NULL;      // not even RIFF
  456.     if(dwType != mmioFOURCC('W', 'A', 'V', 'E'))
  457.         return NULL;      // not a WAV
  458.  
  459.     LPDWORD pdwEnd = (LPDWORD)((LPBYTE)pdw+dwLength-4);
  460.     while(pdw < pdwEnd) 
  461.     {
  462.         dwType = *pdw++;
  463.         dwLength = *pdw++;
  464.  
  465.         switch(dwType)
  466.         {
  467.         case mmioFOURCC('f', 'm', 't', ' '):
  468.             if(!dsbd.lpwfxFormat) 
  469.             {
  470.                 if(dwLength < sizeof (WAVEFORMAT))
  471.                     return false;      // not a WAV
  472.                 dsbd.lpwfxFormat = (LPWAVEFORMATEX)pdw;
  473.                 if((pData) && (dsbd.dwBufferBytes))
  474.                     bDataReady = true;
  475.             }
  476.             break;
  477.  
  478.         case mmioFOURCC('d', 'a', 't', 'a'):
  479.             if(!pData || !dsbd.dwBufferBytes) 
  480.             {
  481.                 pData = (LPBYTE)pdw;
  482.                 dsbd.dwBufferBytes = dwLength;
  483.                 if(dsbd.lpwfxFormat)
  484.                     bDataReady = true;
  485.             }
  486.             break;
  487.  
  488.         default:
  489.             /* unknown chunk */
  490.             break;
  491.         }
  492.         pdw = (LPDWORD)((LPBYTE)pdw+((dwLength+1)&~1));
  493.     }
  494.                                         // Then create the buffer
  495.     TRY_DS(pDS->CreateSoundBuffer(&dsbd, &pBuffer, NULL))
  496.     if(pBuffer == NULL)
  497.         return NULL;
  498.                                         // Finally, fill the buffer with the audio data
  499.     LPVOID pMem1, pMem2;
  500.     DWORD dwSize1, dwSize2;
  501.  
  502.     TRY_DS(pBuffer->Lock(0, dsbd.dwBufferBytes, &pMem1, &dwSize1, &pMem2, &dwSize2, 0))
  503.     CopyMemory(pMem1, pData, dwSize1);
  504.     if(dwSize2)
  505.         CopyMemory(pMem2, LPVOID(pData+dwSize1), dwSize2);
  506.     TRY_DS(pBuffer->Unlock(pMem1, dwSize1, pMem2, dwSize2))
  507.  
  508.     return pBuffer;
  509.  
  510. DS_ERROR:
  511.     RELEASE(pBuffer)
  512.     return NULL;
  513. }
  514.