#define WIN32_LEAN_AND_MEAN #include #include #include #define DIRECTINPUT_VERSION 0x0800 #include #include #include #include #include #include #include // globals for mxJoystick extern LPDIRECTINPUTDEVICE8 p_joy; extern LPDIRECTINPUT8 pdi; inline void ErrorMsg(const char *str, ...) { char text[5000]; va_list list; va_start(list, str); vsprintf((char*)text,str,list); va_end(list); MessageBox(GetForegroundWindow(),text,"Error !",MB_OK | MB_ICONERROR ); } template inline void SafeFree(type t) { if(t) { t->Release(); t = 0; } } struct mxScreen { LPDIRECT3D9 pd3d; LPDIRECT3DDEVICE9 pd3d_dev; LPDIRECT3DSURFACE9 pback; mxScreen() { pd3d = 0; pd3d_dev = 0; pback = 0; } RECT scr_rc; ~mxScreen(); }; class mxText { mxScreen *mxscr; LPD3DXFONT pfont; D3DCOLOR color; public: void Init(mxScreen *mscr) { this->mxscr = mscr; if(FAILED(D3DXCreateFont( mxscr->pd3d_dev, -12, 0, FW_BOLD, 1, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Arial", &pfont ) ) ) { ErrorMsg("Error Couldnt create font"); } color = D3DCOLOR_XRGB(255,0,0); } void settextcolor(D3DCOLOR color) { this->color = color; } void setfont(HFONT hfont) { char fnt_name[255]; HDC dc = GetDC(GetForegroundWindow()); HFONT prev_font = (HFONT) SelectObject(dc,(HFONT)hfont); GetTextFace(dc,LF_FULLFACESIZE,fnt_name); TEXTMETRIC textmetric; GetTextMetrics (dc, &textmetric) ; if(pfont) { SafeFree(pfont); } if(FAILED(D3DXCreateFont( mxscr->pd3d_dev, textmetric.tmHeight, 0, FW_BOLD, 1, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, fnt_name, &pfont ) ) ) { ErrorMsg("Error Couldnt create font"); } SelectObject(dc,prev_font); } void printtextf(int x, int y, const char *str, ...) { mxscr->pd3d_dev->BeginScene(); RECT rc = {x,y,0,0}; char text[5000]; va_list list; va_start(list, str); vsprintf((char*)text,str,list); va_end(list); pfont->DrawText(NULL,text,-1,&rc,DT_NOCLIP,color); mxscr->pd3d_dev->EndScene(); } mxText() { pfont = 0; } ~mxText() { SafeFree(pfont); } }; class mxSprite { mxScreen *mxscr; D3DCOLOR color_key; public: LPDIRECT3DTEXTURE9 tex; LPD3DXSPRITE sprite; D3DSURFACE_DESC surface_desc; int w,h; void init(mxScreen *mxscr) { this->mxscr = mxscr; w = h = 0; } void setcolorkey(D3DCOLOR color_key) { this->color_key = color_key; } bool load(const char *source) { if(FAILED(D3DXCreateTextureFromFileEx(mxscr->pd3d_dev, source, D3DX_DEFAULT_NONPOW2, D3DX_DEFAULT_NONPOW2, D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, color_key, NULL, NULL, &tex))) { ErrorMsg("Error couldnt load texture!\n"); return false; } if(FAILED(D3DXCreateSprite(mxscr->pd3d_dev,&sprite))) { ErrorMsg("Error couldnt load sprite!\n"); return false; } tex->GetLevelDesc(0, &surface_desc); w = surface_desc.Width; h = surface_desc.Height; return true; } void display(float x, float y) { D3DXVECTOR3 pos; pos.x=x; pos.y=y; pos.z=0.0f; if(sprite) { sprite->Begin(D3DXSPRITE_ALPHABLEND); sprite->Draw(tex,NULL,NULL,&pos,0xFFFFFFFF); sprite->End(); } } void display_scale(float x, float y, float scale_x, float scale_y, float rotation) { D3DXVECTOR3 pos; pos.x=x; pos.y=y; pos.z=0.0f; if(sprite) { sprite->Begin(D3DXSPRITE_ALPHABLEND); D3DXVECTOR2 sprite_center =D3DXVECTOR2(0.0f,0.0f); D3DXVECTOR2 trans=D3DXVECTOR2(x,y); D3DXMATRIX mat; D3DXVECTOR2 scaling(scale_x,scale_y); D3DXMatrixTransformation2D(&mat,NULL,0.0,&scaling,&sprite_center,rotation,&trans); sprite->SetTransform(&mat); sprite->Draw(tex,NULL,NULL,&pos,0xFFFFFFFF); sprite->End(); } } void display_ex(float x, float y, int x1, int y1, int x2, int y2, float scale_x, float scale_y, float rotation) { D3DXVECTOR3 pos; pos.x=x; pos.y=y; pos.z=0.0f; RECT rc = { x1,y1,x2,y2 }; if(sprite) { sprite->Begin(D3DXSPRITE_ALPHABLEND); D3DXVECTOR2 sprite_center =D3DXVECTOR2(0.0f,0.0f); D3DXVECTOR2 trans=D3DXVECTOR2(x,y); D3DXMATRIX mat; D3DXVECTOR2 scaling(scale_x,scale_y); D3DXMatrixTransformation2D(&mat,0,0.0,&scaling,&sprite_center,rotation,&trans); sprite->SetTransform(&mat); sprite->Draw(tex,&rc,NULL,&pos,0xFFFFFFFF); sprite->End(); } } mxSprite() { tex = 0; sprite = 0; color_key = 0; } ~mxSprite() { SafeFree(tex); SafeFree(sprite); } }; class mxPaint { mxScreen *mxscr; public: D3DLOCKED_RECT rect; DWORD *data; void init(mxScreen *mxscr) { this->mxscr = mxscr; data = 0; } void __fastcall Lock(); void __fastcall UnLock(); void __fastcall fast_sp(int x, int y, int pitch, D3DCOLOR color); void __fastcall setpixel(int x, int y, D3DCOLOR color); DWORD __fastcall fast_gp(int x, int y); void __fastcall drawrect(int x, int y, int w , int h, D3DCOLOR color); // slow gdi functions void __fastcall drawroundrect(int x, int y, int w, int h,int ch, int cw, COLORREF color, COLORREF out_color); void __fastcall drawpie(int x, int y, int x2, int y2, int nx, int ny, int nx2, int ny2, COLORREF fill,COLORREF outline); void __fastcall drawchord(int x, int y, int x2, int y2, int nx, int ny, int nx2, int ny2,COLORREF fill,COLORREF outline); void __fastcall drawellipse(int x, int y, int x2, int y2,COLORREF fill,COLORREF outline); void __fastcall drawpolygon(CONST POINT* point,int n_points,COLORREF fill,COLORREF outline); void __fastcall drawanglearc(int x, int y, long radius, float startangle,float sweepangle,COLORREF fill,COLORREF outline); void __fastcall drawarc(int x1, int x2, int x3, int x4,int x5, int x6,int x7, int x8,COLORREF fill,COLORREF outline); void __fastcall drawlineto(int x, int y,COLORREF fill,COLORREF outline); void __fastcall drawpixel(int x, int y, COLORREF color); COLORREF __fastcall drawgetpixel(int x, int y); void __fastcall drawline(int start_x, int start_y, int stop_x, int stop_y,COLORREF color); }; class mxKeyboard { public: LPDIRECTINPUTDEVICE8 key_dev; char keys[256]; void Init(LPDIRECTINPUT8 pdi,HWND hwnd) { HRESULT rt = pdi->CreateDevice(GUID_SysKeyboard,&key_dev,NULL); if(FAILED(rt)) { ErrorMsg("Error couldnt create the keyboard device."); return; } if(FAILED(key_dev->SetDataFormat(&c_dfDIKeyboard))) { ErrorMsg("Couldnt set the data format!\n"); return; } if(FAILED(key_dev->SetCooperativeLevel(hwnd,DISCL_FOREGROUND | DISCL_NONEXCLUSIVE))) { ErrorMsg("Failed to set cooperative level!\n"); return; } } void Clear() { memset((void*)keys,0,sizeof(char)*256); } void Free() { if(key_dev) key_dev->Unacquire(); SafeFree(key_dev); } bool KeyCheck(int key) { if(keys[key] & 0x80) { return true; } return false; } void Update() { char new_state[256]; HRESULT rt = key_dev->Poll(); memset(new_state,0,sizeof(new_state)); rt = key_dev->GetDeviceState(sizeof(new_state),(void*)&new_state); if(FAILED(rt)) { rt = key_dev->Acquire(); if(FAILED(rt)) { OutputDebugString("Failed to aquire keyboard.\n"); return; } rt = key_dev->Poll(); rt = key_dev->GetDeviceState(sizeof(new_state),(void*)&new_state); if(FAILED(rt)) { OutputDebugString("Failed to get Device State.\n"); return; } } memcpy(keys,new_state,256); } }; extern bool joy_exisits; extern char joy_name[256]; class mxJoystick { public: DIJOYSTATE2 joy_st; void Init(HWND hwnd, LPDIRECTINPUT8 pdix) { pdi = pdix; pdi->EnumDevices( DI8DEVCLASS_GAMECTRL,Enum,NULL, DIEDFL_ATTACHEDONLY ); if(p_joy == 0) { OutputDebugString("Joystick Not Found!.\n"); return; } HRESULT rt = p_joy->SetDataFormat( &c_dfDIJoystick2 ); rt = p_joy->SetCooperativeLevel( hwnd, DISCL_EXCLUSIVE | DISCL_FOREGROUND ); if(FAILED(rt)) { OutputDebugString("Error setting of cooperative level for joystick failed!.\n"); return; } rt = p_joy->EnumObjects( EnumObjects,(VOID*)hwnd, DIDFT_ALL ); if(FAILED(rt)) { OutputDebugString("FAILED to enumObjects\n"); return; } } void Update() { if(p_joy == 0) return; HRESULT rt = p_joy->Poll(); if(FAILED(rt)) { p_joy->Acquire(); while( rt == DIERR_INPUTLOST ) rt = p_joy->Acquire(); return; } rt = p_joy->GetDeviceState( sizeof(DIJOYSTATE2), &joy_st ); if(FAILED(rt)) { return; } } void Free() { if(p_joy) { SafeFree(p_joy); } } static BOOL CALLBACK Enum(const DIDEVICEINSTANCE *joy_inst, VOID *context) { HRESULT hr = pdi->CreateDevice( joy_inst->guidInstance, &p_joy, NULL ); if(FAILED(hr)) { return DIENUM_CONTINUE; } else { strcpy(joy_name,joy_inst->tszProductName); joy_exisits = true; } return DIENUM_STOP; } static BOOL CALLBACK EnumObjects(const DIDEVICEOBJECTINSTANCE* dioi, VOID* context) { if( dioi->dwType & DIDFT_AXIS ) { DIPROPRANGE diprg; diprg.diph.dwSize = sizeof(DIPROPRANGE); diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER); diprg.diph.dwHow = DIPH_BYID; diprg.diph.dwObj = dioi->dwType; diprg.lMin = -1000; diprg.lMax = +1000; if( FAILED(p_joy->SetProperty( DIPROP_RANGE, &diprg.diph ) ) ) return DIENUM_STOP; } return DIENUM_CONTINUE; } }; class mxMouse { LPDIRECTINPUTDEVICE8 mo_dev; public: DIMOUSESTATE mo_st; POINT cur_pos; void Init(HWND hwnd, LPDIRECTINPUT8 pdi) { HRESULT rt = pdi->CreateDevice( GUID_SysMouse,&mo_dev, NULL ); if(FAILED(rt)) { ErrorMsg("Error couldnt create mouse device!\n"); return; } rt = mo_dev->SetDataFormat(&c_dfDIMouse); if(FAILED(rt)) { ErrorMsg("Couldnt set the mouse data format!\n"); SafeFree(mo_dev); return; } rt = mo_dev->SetCooperativeLevel( hwnd, DISCL_NONEXCLUSIVE | DISCL_NOWINKEY | DISCL_FOREGROUND ); if(FAILED(rt)) { ErrorMsg("Couldnt set the coorperative level!\n"); SafeFree(mo_dev); } mo_st.lX = mo_st.lY = mo_st.lZ = 0; mo_st.rgbButtons[0] = 0; mo_st.rgbButtons[1] = 0; mo_st.rgbButtons[2] = 0; //GetCursorPos(&cur_pos); } void Free() { if(mo_dev) { mo_dev->Unacquire(); SafeFree(mo_dev); } } void Update() { DIMOUSESTATE cur_st; HRESULT hr = mo_dev->Poll(); hr = mo_dev->GetDeviceState( sizeof(DIMOUSESTATE),(void*)&cur_st ); if(FAILED(hr)) { hr = mo_dev->Acquire(); if(FAILED(hr)) { OutputDebugString("Error Aquire of Mouse Failed.\n"); return; } hr = mo_dev->Poll(); hr = mo_dev->GetDeviceState( sizeof(DIMOUSESTATE),(void*)&cur_st ); } if(cur_st.lX || cur_st.lY) { mo_st = cur_st; GetCursorPos(&cur_pos); } } }; class mxInput { public: LPDIRECTINPUT8 pdi; mxKeyboard key; mxMouse mouse; void Init(HWND hwnd) { HRESULT rt; rt = DirectInput8Create(GetModuleHandle(0),DIRECTINPUT_VERSION,IID_IDirectInput8,(void**)&pdi,NULL); if(FAILED(rt)) { ErrorMsg("Error DirectInput could not be initialized\n"); return; } key.Init(pdi,hwnd); mouse.Init(hwnd,pdi); } void Free() { key.Free(); mouse.Free(); SafeFree(pdi); } void Update() { key.Update(); mouse.Update(); } }; class mxHwnd { protected: int cur_screen; bool go; public: HWND hwnd; WPARAM active; int w,h; mxScreen screen; mxText text; mxPaint paint; mxInput input; mxHwnd( const char *title, int x, int y, int w , int h, bool fullscreen , WNDPROC WndProc, HICON hIcon); mxHwnd(); bool Init(const char *title,bool full, int x, int y, int w , int h , WNDPROC WndProc, HICON hIcon); bool InitDX(bool,int); int InitLoop(void (*render)(int screen)); LPDIRECT3DSURFACE9 GetBackSurf() { return screen.pback; } void Kill() { go = false; } void SetScreen(int scr) { this->cur_screen = scr; } int GetScreen() { return this->cur_screen; } }; class mxApp : public mxHwnd { public: virtual void init() = 0; virtual void render(int screen) = 0; int InitLoop(); }; extern LPDIRECTSOUND8 m_pDS; extern LPDIRECTSOUND3DLISTENER g_pDSListener; // from Microsoft SDK examples class mxSound { private: DS3DLISTENER g_dsListenerParams; public: mxSound(HWND hwnd) { Init(hwnd); } mxSound() { } ~mxSound() { if(g_pDSListener!=NULL) { g_pDSListener->Release(); g_pDSListener=NULL; } if(m_pDS!=NULL) { m_pDS->Release(); m_pDS=NULL; } } void Init(HWND hWnd) { DirectSoundCreate8( NULL, &m_pDS, NULL ); m_pDS->SetCooperativeLevel( hWnd, DSSCL_PRIORITY ); DSBUFFERDESC dsbd; ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); dsbd.dwSize = sizeof(DSBUFFERDESC); dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRL3D; dsbd.dwBufferBytes = 0; dsbd.lpwfxFormat = NULL; LPDIRECTSOUNDBUFFER pDSBPrimary = NULL; m_pDS->CreateSoundBuffer( &dsbd, &pDSBPrimary, NULL ) ; WAVEFORMATEX wfx; ZeroMemory( &wfx, sizeof(WAVEFORMATEX) ); wfx.wFormatTag = (WORD) WAVE_FORMAT_PCM; wfx.nChannels = 2; wfx.nSamplesPerSec = 22050; wfx.wBitsPerSample = (WORD) 16; wfx.nBlockAlign = (WORD) (wfx.wBitsPerSample / 8 * wfx.nChannels); wfx.nAvgBytesPerSec = (DWORD) (wfx.nSamplesPerSec * wfx.nBlockAlign); pDSBPrimary->SetFormat(&wfx); if(pDSBPrimary) { (pDSBPrimary)->Release(); (pDSBPrimary)=NULL; } DSBUFFERDESC dsbdesc; ZeroMemory( &dsbdesc, sizeof(DSBUFFERDESC) ); dsbdesc.dwSize = sizeof(DSBUFFERDESC); dsbdesc.dwFlags = DSBCAPS_CTRL3D | DSBCAPS_PRIMARYBUFFER; LPDIRECTSOUNDBUFFER pDSBPrimary2 = NULL; m_pDS->CreateSoundBuffer( &dsbdesc, &pDSBPrimary2, NULL ); pDSBPrimary2->QueryInterface( IID_IDirectSound3DListener, (VOID**) &g_pDSListener ); if(pDSBPrimary2) { (pDSBPrimary2)->Release(); (pDSBPrimary2)=NULL; } g_dsListenerParams.dwSize = sizeof(DS3DLISTENER); g_pDSListener->GetAllParameters( &g_dsListenerParams ); } }; class mxWave { private: WAVEFORMATEX* m_pwfx; HMMIO m_hmmio; MMCKINFO m_ck; MMCKINFO m_ckRiff; MMIOINFO m_mmioinfoOut; DWORD m_dwFlags; BYTE* m_pbData; BYTE* m_pbDataCur; ULONG m_ulDataSize; CHAR* m_pResourceBuffer; void ResetFile() { if( m_dwFlags == 1 ) { mmioSeek( m_hmmio, m_ckRiff.dwDataOffset + sizeof(FOURCC),SEEK_SET ); m_ck.ckid = mmioFOURCC('d', 'a', 't', 'a'); mmioDescend( m_hmmio, &m_ck, &m_ckRiff, MMIO_FINDCHUNK ) ; } else { m_ck.ckid = mmioFOURCC('d', 'a', 't', 'a'); m_ck.cksize = 0; mmioCreateChunk( m_hmmio, &m_ck, 0 ) ; mmioGetInfo( m_hmmio, &m_mmioinfoOut, 0 ); } } void Read( BYTE* pBuffer, DWORD dwSizeToRead, DWORD* pdwSizeRead ) { MMIOINFO mmioinfoIn; if( pdwSizeRead != NULL ) *pdwSizeRead = 0; mmioGetInfo( m_hmmio, &mmioinfoIn, 0 ); UINT cbDataIn = dwSizeToRead; if( cbDataIn > m_ck.cksize ) cbDataIn = m_ck.cksize; m_ck.cksize -= cbDataIn; for( DWORD cT = 0; cT < cbDataIn; cT++ ) { if( mmioinfoIn.pchNext == mmioinfoIn.pchEndRead ) mmioAdvance( m_hmmio, &mmioinfoIn, MMIO_READ ); *((BYTE*)pBuffer+cT) = *((BYTE*)mmioinfoIn.pchNext); mmioinfoIn.pchNext++; } mmioSetInfo( m_hmmio, &mmioinfoIn, 0 ); if( pdwSizeRead != NULL ) *pdwSizeRead = cbDataIn; } void Close() { if( m_dwFlags == 1 ) { mmioClose( m_hmmio, 0 ); m_hmmio = NULL; if(m_pResourceBuffer) { delete[] m_pResourceBuffer; m_pResourceBuffer=NULL; } } else { m_mmioinfoOut.dwFlags |= MMIO_DIRTY; mmioSetInfo( m_hmmio, &m_mmioinfoOut, 0 ); mmioAscend( m_hmmio, &m_ck, 0 ); mmioAscend( m_hmmio, &m_ckRiff, 0 ) ; mmioSeek( m_hmmio, 0, SEEK_SET ); (INT)mmioDescend( m_hmmio, &m_ckRiff, NULL, 0 ); m_ck.ckid = mmioFOURCC('f', 'a', 'c', 't'); if( 0 == mmioDescend( m_hmmio, &m_ck, &m_ckRiff, MMIO_FINDCHUNK ) ) { DWORD dwSamples = 0; mmioWrite( m_hmmio, (HPSTR)&dwSamples, sizeof(DWORD) ); mmioAscend( m_hmmio, &m_ck, 0 ); } mmioAscend( m_hmmio, &m_ckRiff, 0 ); mmioClose( m_hmmio, 0 ); m_hmmio = NULL; } } void Open( LPTSTR strFileName, WAVEFORMATEX* pwfx, DWORD dwFlags ) { m_dwFlags = dwFlags; if( m_dwFlags == 1 ) { if(m_pwfx) { delete[] m_pwfx; m_pwfx=NULL; } m_hmmio = mmioOpen( strFileName, NULL, MMIO_ALLOCBUF | MMIO_READ ); if( NULL == m_hmmio ) { DWORD dwSize=0; VOID* pvRes=NULL; m_pResourceBuffer = new CHAR[ dwSize ]; memcpy( m_pResourceBuffer, pvRes, dwSize ); MMIOINFO mmioInfo; ZeroMemory( &mmioInfo, sizeof(mmioInfo) ); mmioInfo.fccIOProc = FOURCC_MEM; mmioInfo.cchBuffer = dwSize; mmioInfo.pchBuffer = (CHAR*) m_pResourceBuffer; m_hmmio = mmioOpen( NULL, &mmioInfo, MMIO_ALLOCBUF | MMIO_READ ); } ReadMMIO(); ResetFile(); m_ck.cksize = m_ck.cksize; } else { m_hmmio = mmioOpen( strFileName, NULL, MMIO_ALLOCBUF | MMIO_READWRITE | MMIO_CREATE ); WriteMMIO( pwfx ); ResetFile(); } } void ReadMMIO() { MMCKINFO ckIn; PCMWAVEFORMAT pcmWaveFormat; m_pwfx = NULL; mmioDescend( m_hmmio, &m_ckRiff, NULL, 0 ); ckIn.ckid = mmioFOURCC('f', 'm', 't', ' '); mmioDescend( m_hmmio, &ckIn, &m_ckRiff, MMIO_FINDCHUNK ) ; mmioRead( m_hmmio, (HPSTR) &pcmWaveFormat, sizeof(pcmWaveFormat)); if( pcmWaveFormat.wf.wFormatTag == WAVE_FORMAT_PCM ) { m_pwfx = (WAVEFORMATEX*)new CHAR[ sizeof(WAVEFORMATEX) ]; memcpy( m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat) ); m_pwfx->cbSize = 0; } else { WORD cbExtraBytes = 0L; mmioRead( m_hmmio, (CHAR*)&cbExtraBytes, sizeof(WORD)) ; m_pwfx = (WAVEFORMATEX*)new CHAR[ sizeof(WAVEFORMATEX) + cbExtraBytes ]; memcpy( m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat) ); m_pwfx->cbSize = cbExtraBytes; if( mmioRead( m_hmmio, (CHAR*)(((BYTE*)&(m_pwfx->cbSize))+sizeof(WORD)), cbExtraBytes ) != cbExtraBytes ) { if(m_pwfx) { delete m_pwfx; m_pwfx=NULL; } } } if( 0 != mmioAscend( m_hmmio, &ckIn, 0 ) ) { if(m_pwfx) { delete m_pwfx; m_pwfx=NULL; } } } void WriteMMIO( WAVEFORMATEX *pwfxDest ) { DWORD dwFactChunk; MMCKINFO ckOut1; dwFactChunk = (DWORD)-1; m_ckRiff.fccType = mmioFOURCC('W', 'A', 'V', 'E'); m_ckRiff.cksize = 0; mmioCreateChunk( m_hmmio, &m_ckRiff, MMIO_CREATERIFF ) ; m_ck.ckid = mmioFOURCC('f', 'm', 't', ' '); m_ck.cksize = sizeof(PCMWAVEFORMAT); mmioCreateChunk( m_hmmio, &m_ck, 0 ); if( pwfxDest->wFormatTag == WAVE_FORMAT_PCM ) mmioWrite( m_hmmio, (HPSTR) pwfxDest, sizeof(PCMWAVEFORMAT)); else (UINT)mmioWrite( m_hmmio, (HPSTR) pwfxDest, sizeof(*pwfxDest) + pwfxDest->cbSize ); mmioAscend( m_hmmio, &m_ck, 0 ) ; ckOut1.ckid = mmioFOURCC('f', 'a', 'c', 't'); ckOut1.cksize = 0; mmioCreateChunk( m_hmmio, &ckOut1, 0 ); mmioWrite( m_hmmio, (HPSTR)&dwFactChunk, sizeof(dwFactChunk)); mmioAscend( m_hmmio, &ckOut1, 0 ); } LPDIRECTSOUNDBUFFER m_apDSBuffer; DWORD m_dwDSBufferSize; DWORD m_dwCreationFlags; void CSoundA(char filename[] , GUID guid3DAlgorithm ,DWORD dwFlags = 0) { m_pwfx = NULL; m_hmmio = NULL; m_pResourceBuffer = NULL; Open( filename, NULL, 1 ); DSBUFFERDESC dsbd; ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) ); dsbd.dwSize = sizeof(DSBUFFERDESC); dsbd.dwFlags = dwFlags; dsbd.dwBufferBytes = m_ck.cksize; dsbd.guid3DAlgorithm = guid3DAlgorithm; dsbd.lpwfxFormat = m_pwfx; m_pDS->CreateSoundBuffer( &dsbd, &m_apDSBuffer, NULL ); m_dwDSBufferSize = m_ck.cksize; m_dwCreationFlags = dwFlags; FillBufferWithSound( m_apDSBuffer, FALSE ); Close(); } void FillBufferWithSound( LPDIRECTSOUNDBUFFER pDSB, BOOL bRepeatWavIfBufferLarger ) { VOID* pDSLockedBuffer = NULL; DWORD dwDSLockedBufferSize = 0; DWORD dwWavDataRead = 0; RestoreBuffer( pDSB, NULL ); pDSB->Lock( 0, m_dwDSBufferSize, &pDSLockedBuffer, &dwDSLockedBufferSize, NULL, NULL, 0L ); ResetFile(); Read( (BYTE*) pDSLockedBuffer, dwDSLockedBufferSize, &dwWavDataRead ) ; if( dwWavDataRead == 0 ) FillMemory( (BYTE*) pDSLockedBuffer, dwDSLockedBufferSize, (BYTE)(m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); else if( dwWavDataRead < dwDSLockedBufferSize ) { if( bRepeatWavIfBufferLarger ) { DWORD dwReadSoFar = dwWavDataRead; while( dwReadSoFar < dwDSLockedBufferSize ) { ResetFile(); Read( (BYTE*)pDSLockedBuffer + dwReadSoFar, dwDSLockedBufferSize - dwReadSoFar, &dwWavDataRead ); dwReadSoFar += dwWavDataRead; } } else FillMemory( (BYTE*) pDSLockedBuffer + dwWavDataRead, dwDSLockedBufferSize - dwWavDataRead, (BYTE)(m_pwfx->wBitsPerSample == 8 ? 128 : 0 ) ); } pDSB->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0 ); } void RestoreBuffer( LPDIRECTSOUNDBUFFER pDSB, BOOL* pbWasRestored ) { HRESULT hr; if( pbWasRestored ) *pbWasRestored = FALSE; DWORD dwStatus; pDSB->GetStatus( &dwStatus ); if( dwStatus & DSBSTATUS_BUFFERLOST ) { do { hr = pDSB->Restore(); if( hr == DSERR_BUFFERLOST ) Sleep( 10 ); } while( ( pDSB->Restore() ) == DSERR_BUFFERLOST ); if( pbWasRestored != NULL ) *pbWasRestored = TRUE; } } HRESULT Get3DBufferInterface( DWORD dwIndex, LPDIRECTSOUND3DBUFFER* ppDS3DBuffer ) { *ppDS3DBuffer = NULL; return m_apDSBuffer->QueryInterface( IID_IDirectSound3DBuffer, (VOID**)ppDS3DBuffer ); } LPDIRECTSOUND3DBUFFER g_pDS3DBuffer; DS3DBUFFER g_dsBufferParams; bool threeDFlag; public: mxWave() { m_apDSBuffer = 0; g_pDS3DBuffer = 0; } ~mxWave() { if(m_pDS) { if(m_apDSBuffer) { m_apDSBuffer->Release(); m_apDSBuffer=NULL; } if(g_pDS3DBuffer) { g_pDS3DBuffer->Release(); g_pDS3DBuffer=NULL; } } } void load(char filename[], int threeDimensionLevel=0) { g_pDS3DBuffer = 0; switch (threeDimensionLevel) { case 0: CSoundA(filename,GUID_NULL,DSBCAPS_CTRLVOLUME); threeDFlag=false; break; case 1: CSoundA(filename,GUID_NULL,DSBCAPS_CTRL3D|DSBCAPS_CTRLVOLUME); break; case 2: CSoundA(filename,DS3DALG_NO_VIRTUALIZATION,DSBCAPS_CTRL3D|DSBCAPS_CTRLVOLUME); break; case 3: CSoundA(filename,DS3DALG_HRTF_LIGHT,DSBCAPS_CTRL3D|DSBCAPS_CTRLVOLUME); break; case 4: CSoundA(filename,DS3DALG_HRTF_FULL,DSBCAPS_CTRL3D|DSBCAPS_CTRLVOLUME); break; } if (threeDimensionLevel!=0) { Get3DBufferInterface( 0, &g_pDS3DBuffer ); g_dsBufferParams.dwSize = sizeof(DS3DBUFFER); g_pDS3DBuffer->GetAllParameters( &g_dsBufferParams ); g_dsBufferParams.dwMode = DS3DMODE_HEADRELATIVE; g_pDS3DBuffer->SetAllParameters( &g_dsBufferParams, DS3D_IMMEDIATE ); DSBCAPS dsbcaps; ZeroMemory( &dsbcaps, sizeof(DSBCAPS) ); dsbcaps.dwSize = sizeof(DSBCAPS); m_apDSBuffer->GetCaps( &dsbcaps ); threeDFlag=true; } } void Play(long volume = 0, float x = 0, float y = 0, float z = 0, float minDist = 1, float maxDist = 1, float rolloff = 1) { if (threeDFlag) g_pDS3DBuffer->SetPosition(x,y,z,DS3D_IMMEDIATE); m_apDSBuffer ->SetVolume(volume); m_apDSBuffer ->Stop(); m_apDSBuffer ->SetCurrentPosition(0); m_apDSBuffer->Play(0,0,0 ); } void stop() { m_apDSBuffer ->Stop(); m_apDSBuffer ->SetCurrentPosition(0); } bool is_playing() { bool answer=false; DWORD dwStatus = 0; m_apDSBuffer->GetStatus( &dwStatus ); answer |= ( ( dwStatus & DSBSTATUS_PLAYING ) != 0 ); return answer; } };