1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-07-04 23:36:00 +02:00

Working on installer, fixing more Win32 issues

Throwing error on member references with ".." cascade token outside invocations (ie: "ts..mA = 123")
Fixed 'Thread.ModuleTLSIndex' error - which caused us TLS lookup failures in Beef DLLs
Fixed some hotswap errors
Made BeefPerf shut down properly
Fixed an 'int literal' FixIntUnknown issue where rhs was System.Object which caused an illegal boxing
Fixed COFF::LocateSymbol issues with Win32 and also with linking to static libraries - showed up with hot-linking in fmod when hot-adding a floating point mod
Fixed a couple memory leaks
Fixed alignment issue in COFF::ParseCompileUnit
This commit is contained in:
Brian Fiete 2019-09-02 17:39:47 -07:00
parent aad0a640c5
commit b63a243fd7
73 changed files with 2474 additions and 293 deletions

View file

@ -30,6 +30,7 @@ BFApp::BFApp()
mCursor = CURSOR_POINTER;
mInProcess = false;
mUpdateCnt = 0;
mNumPhysUpdates = 0;
mVSynched = true;
mMaxUpdatesPerDraw = 60; // 8?
@ -49,7 +50,7 @@ BFApp::~BFApp()
gBFApp = NULL;
delete gPerfManager;
for (auto window : mPendingWindowDeleteList)
delete window;
delete window;
}
void BFApp::Init()
@ -170,7 +171,10 @@ void BFApp::Process()
mFrameTimeAcc = 0;
}
updates = std::min(updates, mMaxUpdatesPerDraw);
// Compensate for "slow start" by limiting the number of catchup-updates we can do when starting the app
int maxUpdates = BF_MIN(mNumPhysUpdates + 1, mMaxUpdatesPerDraw);
updates = BF_MIN(updates, maxUpdates);
/*if (updates > 2)
OutputDebugStrF("Updates: %d TickDelta: %d\n", updates, tickNow - mLastProcessTick);*/
@ -198,8 +202,15 @@ void BFApp::Process()
}
#endif
if (updates > 0)
mNumPhysUpdates++;
for (int updateNum = 0; updateNum < updates; updateNum++)
{
if (!mRunning)
break;
Update(updateNum == 0);
}
if ((mRunning) && (updates > 0))
Draw();

View file

@ -9,6 +9,7 @@ typedef void (*BFApp_UpdateFunc)(bool batchStart);
typedef void (*BFApp_DrawFunc)();
class BFApp;
class BFSoundManager;
class RenderDevice;
class BFWindow;
class FileStream;
@ -46,7 +47,7 @@ public:
String mInstallDir;
String mDataDir;
bool mDrawEnabled;
float mRefreshRate;
float mRefreshRate;
int mMaxUpdatesPerDraw;
bool mInProcess;
@ -54,6 +55,7 @@ public:
RenderDevice* mRenderDevice;
int mSysDialogCnt;
int mUpdateCnt;
int mNumPhysUpdates;
bool mVSynched;
bool mVSyncFailed;
@ -99,6 +101,8 @@ public:
virtual BFSysBitmap* LoadSysBitmap(const wchar_t* fileName) = 0;
virtual FileStream* OpenBinaryFile(const StringImpl& fileName);
virtual BFSoundManager* GetSoundManager() { return NULL; }
};
extern BFApp* gBFApp;

72
BeefySysLib/BFSound.cpp Normal file
View file

@ -0,0 +1,72 @@
#include "BFSound.h"
using namespace Beefy;
//////////////////////////////////////////////////////////////////////////
BF_EXPORT int32 BF_CALLTYPE BFSoundManager_LoadSound(BFSoundManager* manager, const char* fileName)
{
return manager->LoadSound(fileName);
}
BF_EXPORT BFSoundInstance* BF_CALLTYPE BFSoundManager_GetSoundInstance(BFSoundManager* manager, int32 sfxId)
{
return manager->GetSoundInstance(sfxId);
}
//////////////////////////////////////////////////////////////////////////
BF_EXPORT void BF_CALLTYPE BFSoundInstance_Release(BFSoundInstance* instance)
{
instance->Release();
}
BF_EXPORT void BF_CALLTYPE BFSoundInstance_SetBaseVolume(BFSoundInstance* instance, float theBaseVolume)
{
instance->SetBaseVolume(theBaseVolume);
}
BF_EXPORT void BF_CALLTYPE BFSoundInstance_SetBasePan(BFSoundInstance* instance, int theBasePan)
{
instance->SetBasePan(theBasePan);
}
BF_EXPORT void BF_CALLTYPE BFSoundInstance_SetVolume(BFSoundInstance* instance, float theVolume)
{
instance->SetVolume(theVolume);
}
BF_EXPORT void BF_CALLTYPE BFSoundInstance_SetPan(BFSoundInstance* instance, int thePosition)
{
instance->SetPan(thePosition);
}
BF_EXPORT void BF_CALLTYPE BFSoundInstance_AdjustPitch(BFSoundInstance* instance, float theNumSteps)
{
instance->AdjustPitch(theNumSteps);
}
BF_EXPORT bool BF_CALLTYPE BFSoundInstance_Play(BFSoundInstance* instance, bool looping, bool autoRelease)
{
return instance->Play(looping, autoRelease);
}
BF_EXPORT void BF_CALLTYPE BFSoundInstance_Stop(BFSoundInstance* instance)
{
instance->Stop();
}
BF_EXPORT bool BF_CALLTYPE BFSoundInstance_IsPlaying(BFSoundInstance* instance)
{
return instance->IsPlaying();
}
BF_EXPORT bool BF_CALLTYPE BFSoundInstance_IsReleased(BFSoundInstance* instance)
{
return instance->IsReleased();
}
BF_EXPORT float BF_CALLTYPE BFSoundInstance_GetVolume(BFSoundInstance* instance)
{
return (float)instance->GetVolume();
}

61
BeefySysLib/BFSound.h Normal file
View file

@ -0,0 +1,61 @@
#pragma once
#include "Common.h"
NS_BF_BEGIN;
#define MAX_SOURCE_SOUNDS 1024
#define MAX_CHANNELS 32
class BFSoundInstance
{
public:
virtual ~BFSoundInstance() {}
virtual void Release() = 0;
virtual void SetBaseVolume(float theBaseVolume) = 0;
virtual void SetBasePan(int theBasePan) = 0;
virtual void SetVolume(float theVolume) = 0;
virtual void SetPan(int thePosition) = 0; //-hundredth db to +hundredth db = left to right
virtual void AdjustPitch(float theNumSteps) = 0;
virtual bool Play(bool looping, bool autoRelease) = 0;
virtual void Stop() = 0;
virtual bool IsPlaying() = 0;
virtual bool IsReleased() = 0;
virtual float GetVolume() = 0;
};
class BFSoundManager
{
public:
virtual ~BFSoundManager() {}
virtual bool Initialized() = 0;
virtual bool LoadSound(unsigned int theSfxID, const StringImpl& theFilename) = 0;
virtual int LoadSound(const StringImpl& theFilename) = 0;
virtual void ReleaseSound(unsigned int theSfxID) = 0;
virtual void SetVolume(float theVolume) = 0;
virtual bool SetBaseVolume(unsigned int theSfxID, float theBaseVolume) = 0;
virtual bool SetBasePan(unsigned int theSfxID, int theBasePan) = 0;
virtual BFSoundInstance* GetSoundInstance(unsigned int theSfxID) = 0;
virtual void ReleaseSounds() = 0;
virtual void ReleaseChannels() = 0;
virtual float GetMasterVolume() = 0;
virtual void SetMasterVolume(float theVolume) = 0;
virtual void Flush() = 0;
virtual void StopAllSounds() = 0;
virtual int GetFreeSoundId() = 0;
virtual int GetNumSounds() = 0;
};
NS_BF_END;

View file

@ -255,6 +255,11 @@ BF_EXPORT void BF_CALLTYPE BFApp_RehupMouse()
}
BF_EXPORT BFSoundManager* BF_CALLTYPE BFApp_GetSoundManager()
{
return gBFApp->GetSoundManager();
}
///
BF_EXPORT void BF_CALLTYPE BFWindow_SetCallbacks(BFWindow* window, BFWindow_MovedFunc movedFunc, BFWindow_CloseQueryFunc closeQueryFunc, BFWindow_ClosedFunc closedFunc,

View file

@ -433,6 +433,7 @@ copy /y $(OutDir)$(TargetName).lib $(SolutionDir)\BeefLibs\Beefy2D\dist\</Comman
<ItemGroup>
<ClCompile Include="BFApp.cpp" />
<ClCompile Include="BeefySysLib.cpp" />
<ClCompile Include="BFSound.cpp" />
<ClCompile Include="BFWindow.cpp" />
<ClCompile Include="CachedDataStream.cpp" />
<ClCompile Include="Common.cpp" />
@ -485,6 +486,8 @@ copy /y $(OutDir)$(TargetName).lib $(SolutionDir)\BeefLibs\Beefy2D\dist\</Comman
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="platform\win\CrashCatcher.cpp" />
<ClCompile Include="platform\win\DSoundInstance.cpp" />
<ClCompile Include="platform\win\DSoundManager.cpp" />
<ClCompile Include="platform\win\WinBFApp.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</ExcludedFromBuild>
</ClCompile>
@ -1940,6 +1943,7 @@ copy /y $(OutDir)$(TargetName).lib $(SolutionDir)\BeefLibs\Beefy2D\dist\</Comman
</ItemGroup>
<ItemGroup>
<ClInclude Include="BFApp.h" />
<ClInclude Include="BFSound.h" />
<ClInclude Include="BFWindow.h" />
<ClInclude Include="CachedDataStream.h" />
<ClInclude Include="Common.h" />
@ -1989,6 +1993,8 @@ copy /y $(OutDir)$(TargetName).lib $(SolutionDir)\BeefLibs\Beefy2D\dist\</Comman
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClInclude>
<ClInclude Include="platform\win\CrashCatcher.h" />
<ClInclude Include="platform\win\DSoundInstance.h" />
<ClInclude Include="platform\win\DSoundManager.h" />
<ClInclude Include="platform\win\PlatformApp.h" />
<ClInclude Include="platform\win\WinBFApp.h">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</ExcludedFromBuild>

View file

@ -688,6 +688,15 @@
<ClCompile Include="util\ThreadPool.cpp">
<Filter>src\util</Filter>
</ClCompile>
<ClCompile Include="platform\win\DSoundInstance.cpp">
<Filter>src\platform\win</Filter>
</ClCompile>
<ClCompile Include="platform\win\DSoundManager.cpp">
<Filter>src\platform\win</Filter>
</ClCompile>
<ClCompile Include="BFSound.cpp">
<Filter>src\platform</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Common.h">
@ -1038,6 +1047,15 @@
<ClInclude Include="util\MultiHashSet.h">
<Filter>src\util</Filter>
</ClInclude>
<ClInclude Include="platform\win\DSoundInstance.h">
<Filter>src\platform\win</Filter>
</ClInclude>
<ClInclude Include="platform\win\DSoundManager.h">
<Filter>src\platform\win</Filter>
</ClInclude>
<ClInclude Include="BFSound.h">
<Filter>src</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="third_party\libffi\i686-pc-cygwin\src\x86\win32.asm">

View file

@ -29,6 +29,7 @@ bool FileStream::Open(const StringImpl& filePath, const char* fopenOptions)
#else
mFP = fopen(filePath.c_str(), fopenOptions);
#endif
mReadPastEnd = false;
return mFP != NULL;
}

View file

@ -101,10 +101,22 @@ VertexDefinition* Beefy::RenderDevice::CreateVertexDefinition(VertexDefData* ele
Texture* RenderDevice::LoadTexture(const StringImpl& fileName, int flags)
{
int dotPos = (int)fileName.LastIndexOf('.');
String ext = fileName.Substring(dotPos);
String ext;
if (dotPos != -1)
ext = fileName.Substring(dotPos);
ImageData* imageData = NULL;
if (ext == ".tga")
bool handled = false;
bool failed = false;
if (fileName == "!white")
{
imageData = new ImageData();
imageData->CreateNew(1, 1, true);
imageData->mBits[0] = 0xFFFFFFFF;
handled = true;
}
else if (ext == ".tga")
imageData = new TGAData();
else if (ext == ".png")
imageData = new PNGData();
@ -117,22 +129,20 @@ Texture* RenderDevice::LoadTexture(const StringImpl& fileName, int flags)
BF_FATAL("Unknown texture format");
return NULL; // Unknown format
}
imageData->mWantsAlphaPremultiplied = (flags & TextureFlag_NoPremult) == 0;
if (!handled)
{
imageData->mWantsAlphaPremultiplied = (flags & TextureFlag_NoPremult) == 0;
if (!imageData->LoadFromFile(fileName))
{
failed = true;
BF_FATAL("Failed to load image");
}
}
Texture* aTexture = NULL;
if (imageData->LoadFromFile(fileName))
{
// if ((int)fileName.IndexOf("fft") != -1)
// {
// BFIData bFIData;
// bFIData.Compress(imageData);
// }
if (!failed)
aTexture = LoadTexture(imageData, flags);
}
else
BF_FATAL("Failed to load image");
delete imageData;
return aTexture;

View file

@ -0,0 +1,177 @@
#include "DSoundInstance.h"
#include "DSoundManager.h"
using namespace Beefy;
DSoundInstance::DSoundInstance(DSoundManager* theSoundManager, LPDIRECTSOUNDBUFFER theSourceSound)
{
mSoundManagerP = theSoundManager;
mReleased = false;
mAutoRelease = false;
mHasPlayed = false;
mSourceSoundBuffer = theSourceSound;
mSoundBuffer = NULL;
mBaseVolume = 1.0;
mBasePan = 0;
mVolume = 1.0;
mPan = 0;
mDefaultFrequency = 44100;
HRESULT hr;
if (mSourceSoundBuffer != NULL)
{
hr=mSoundManagerP->mDirectSound->DuplicateSoundBuffer(mSourceSoundBuffer, &mSoundBuffer);
if (hr!=DS_OK)
{
switch (hr)
{
case DSERR_ALLOCATED: MessageBoxA(0,"DSERR_ALLOCATED","Hey",MB_OK);break;
case DSERR_INVALIDCALL: MessageBoxA(0,"DSERR_INVALIDCALL","Hey",MB_OK);break;
case DSERR_INVALIDPARAM: MessageBoxA(0,"DSERR_INVALIDPARAM","Hey",MB_OK);break;
case DSERR_OUTOFMEMORY: MessageBoxA(0,"DSERR_OUTOFMEMORY","Hey",MB_OK);break;
case DSERR_UNINITIALIZED: MessageBoxA(0,"DSERR_UNINITIALIZED","Hey",MB_OK);break;
}
exit(0);
}
mSoundBuffer->GetFrequency(&mDefaultFrequency);
}
RehupVolume();
}
DSoundInstance::~DSoundInstance()
{
if (mSoundBuffer != NULL)
mSoundBuffer->Release();
}
void DSoundInstance::RehupVolume()
{
if (mSoundBuffer != NULL)
mSoundBuffer->SetVolume(mSoundManagerP->VolumeToDB(mBaseVolume * mVolume * mSoundManagerP->mMasterVolume));
}
void DSoundInstance::RehupPan()
{
if (mSoundBuffer != NULL)
mSoundBuffer->SetPan(mBasePan + mPan);
}
void DSoundInstance::Release()
{
Stop();
mReleased = true;
}
void DSoundInstance::SetVolume(float theVolume) // 0 = max
{
mVolume = theVolume;
RehupVolume();
}
void DSoundInstance::SetPan(int thePosition) //-db to =db = left to right
{
mPan = thePosition;
RehupPan();
}
void DSoundInstance::SetBaseVolume(float theBaseVolume)
{
mBaseVolume = theBaseVolume;
RehupVolume();
}
void DSoundInstance::SetBasePan(int theBasePan)
{
mBasePan = theBasePan;
RehupPan();
}
bool DSoundInstance::Play(bool looping, bool autoRelease)
{
Stop();
mHasPlayed = true;
mAutoRelease = autoRelease;
if (mSoundBuffer == NULL)
{
return false;
}
if (looping)
{
if (mSoundBuffer->Play(0, 0, DSBPLAY_LOOPING) != DS_OK)
return false;
}
else
{
if (mSoundBuffer->Play(0, 0, 0) != DS_OK)
{
return false;
}
}
return true;
}
void DSoundInstance::Stop()
{
if (mSoundBuffer != NULL)
{
mSoundBuffer->Stop();
mSoundBuffer->SetCurrentPosition(0);
mAutoRelease = false;
}
}
//#include "DirectXErrorString.h"
void DSoundInstance::AdjustPitch(float theNumSteps)
{
if (mSoundBuffer != NULL)
{
float aFrequencyMult = powf(1.0594630943592952645618252949463f, theNumSteps);
float aNewFrequency = mDefaultFrequency*aFrequencyMult;
if (aNewFrequency < DSBFREQUENCY_MIN)
aNewFrequency = DSBFREQUENCY_MIN;
if (aNewFrequency > DSBFREQUENCY_MAX)
aNewFrequency = DSBFREQUENCY_MAX;
mSoundBuffer->SetFrequency((DWORD)aNewFrequency);
}
}
bool DSoundInstance::IsPlaying()
{
if (!mHasPlayed)
return false;
if (mSoundBuffer == NULL)
return false;
DWORD aStatus;
if (mSoundBuffer->GetStatus(&aStatus) == DS_OK)
// Has the sound stopped?
return ((aStatus & DSBSTATUS_PLAYING) != 0);
else
return false;
}
bool DSoundInstance::IsReleased()
{
if ((!mReleased) && (mAutoRelease) && (mHasPlayed) && (!IsPlaying()))
Release();
return mReleased;
}
float DSoundInstance::GetVolume()
{
return mVolume;
}

View file

@ -0,0 +1,60 @@
#ifndef __DSOUNDINSTANCE_H__
#define __DSOUNDINSTANCE_H__
#include <dsound.h>
#include "BFSound.h"
//#define _LPCWAVEFORMATEX_DEFINED
namespace Beefy
{
class DSoundManager;
class DSoundInstance : public BFSoundInstance
{
friend class DSoundManager;
protected:
DSoundManager* mSoundManagerP;
LPDIRECTSOUNDBUFFER mSourceSoundBuffer;
LPDIRECTSOUNDBUFFER mSoundBuffer;
bool mAutoRelease;
bool mHasPlayed;
bool mReleased;
int mBasePan;
float mBaseVolume;
int mPan;
float mVolume;
DWORD mDefaultFrequency;
protected:
void RehupVolume();
void RehupPan();
public:
DSoundInstance(DSoundManager* theSoundManager, LPDIRECTSOUNDBUFFER theSourceSound);
virtual ~DSoundInstance();
virtual void Release() override;
virtual void SetBaseVolume(float theBaseVolume) override;
virtual void SetBasePan(int theBasePan) override;
virtual void SetVolume(float theVolume) override;
virtual void SetPan(int thePosition) override; //-hundredth db to +hundredth db = left to right
virtual void AdjustPitch(float theNumSteps) override;
virtual bool Play(bool looping, bool autoRelease) override;
virtual void Stop() override;
virtual bool IsPlaying() override;
virtual bool IsReleased() override;
virtual float GetVolume() override;
};
}
#endif //__DSOUNDINSTANCE_H__

View file

@ -0,0 +1,535 @@
#pragma warning(disable:4996)
#include "DSoundManager.h"
#include <io.h>
#include <fcntl.h>
#include "DSoundInstance.h"
#include <math.h>
using namespace Beefy;
static HMODULE gDSoundDLL;
#pragma comment(lib, "dsound.lib")
#define SOUND_FLAGS (DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_STATIC | DSBCAPS_LOCSOFTWARE | DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRLFREQUENCY)
DSoundManager::DSoundManager(HWND theHWnd)
{
mLastReleaseTick = 0;
mPrimaryBuffer = NULL;
int i;
for (i = 0; i < MAX_SOURCE_SOUNDS; i++)
{
mSourceSounds[i] = NULL;
mBaseVolumes[i] = 1;
mBasePans[i] = 0;
}
for (i = 0; i < MAX_CHANNELS; i++)
mPlayingSounds[i] = NULL;
mDirectSound = NULL;
mMasterVolume = 1.0;
//typedef HRESULT (WINAPI *DirectSoundCreateFunc)(LPCGUID lpcGuid, LPDIRECTSOUND * ppDS, LPUNKNOWN pUnkOuter);
//DirectSoundCreateFunc aDirectSoundCreateFunc = (DirectSoundCreateFunc)GetProcAddress(gDSoundDLL,"DirectSoundCreate");
// Seems crazy but this was even suggested in MSDN docs for windowless applications
if (theHWnd == NULL)
theHWnd = ::GetDesktopWindow();
//if (aDirectSoundCreateFunc != NULL && aDirectSoundCreateFunc(NULL, &mDirectSound, NULL) == DS_OK)
if (DirectSoundCreate(NULL, &mDirectSound, NULL) == DS_OK)
{
bool handled = false;
if (theHWnd != NULL)
{
HRESULT aResult = mDirectSound->SetCooperativeLevel(theHWnd, DSSCL_PRIORITY);
if (SUCCEEDED(aResult))
{
// Set primary buffer to 16-bit 44.1Khz
WAVEFORMATEX aWaveFormat;
DSBUFFERDESC aBufferDesc;
// Set up wave format structure.
int aBitCount = 16;
int aChannelCount = 2;
int aSampleRate = 44100;
// Set up wave format structure.
memset(&aWaveFormat, 0, sizeof(WAVEFORMATEX));
aWaveFormat.cbSize = sizeof(WAVEFORMATEX);
aWaveFormat.wFormatTag = WAVE_FORMAT_PCM;
aWaveFormat.nChannels = aChannelCount;
aWaveFormat.nSamplesPerSec = aSampleRate;
aWaveFormat.nBlockAlign = aChannelCount * aBitCount / 8;
aWaveFormat.nAvgBytesPerSec =
aWaveFormat.nSamplesPerSec * aWaveFormat.nBlockAlign;
aWaveFormat.wBitsPerSample = aBitCount;
// Set up DSBUFFERDESC structure.
memset(&aBufferDesc, 0, sizeof(DSBUFFERDESC)); // Zero it out.
aBufferDesc.dwSize = sizeof(DSBUFFERDESC1);
aBufferDesc.dwFlags = DSBCAPS_PRIMARYBUFFER;//| DSBCAPS_CTRL3D; // Need default controls (pan, volume, frequency).
aBufferDesc.dwBufferBytes = 0;
aBufferDesc.lpwfxFormat = NULL;//(LPWAVEFORMATEX)&aWaveFormat;
HRESULT aResult = mDirectSound->CreateSoundBuffer(&aBufferDesc, &mPrimaryBuffer, NULL);
if (aResult == DS_OK)
{
aResult = mPrimaryBuffer->SetFormat(&aWaveFormat);
}
handled = true;
}
}
if (!handled)
{
HRESULT aResult = mDirectSound->SetCooperativeLevel(theHWnd,DSSCL_NORMAL);
}
}
}
DSoundManager::~DSoundManager()
{
ReleaseChannels();
ReleaseSounds();
if (mPrimaryBuffer)
mPrimaryBuffer->Release();
if (mDirectSound != NULL)
{
mDirectSound->Release();
}
}
int DSoundManager::FindFreeChannel()
{
DWORD aTick = GetTickCount();
if (aTick-mLastReleaseTick > 1000)
{
ReleaseFreeChannels();
mLastReleaseTick = aTick;
}
for (int i = 0; i < MAX_CHANNELS; i++)
{
if (mPlayingSounds[i] == NULL)
return i;
if (mPlayingSounds[i]->IsReleased())
{
delete mPlayingSounds[i];
mPlayingSounds[i] = NULL;
return i;
}
}
return -1;
}
bool DSoundManager::Initialized()
{
/*
if (mDirectSound!=NULL)
{
mDirectSound->SetCooperativeLevel(theHWnd,DSSCL_NORMAL);
}
*/
return (mDirectSound != NULL);
}
int DSoundManager::VolumeToDB(float theVolume)
{
int aVol = (int) ((log10(1 + theVolume*9) - 1.0) * 2333);
if (aVol < -2000)
aVol = -10000;
return aVol;
}
void DSoundManager::SetVolume(float theVolume)
{
mMasterVolume = theVolume;
for (int i = 0; i < MAX_CHANNELS; i++)
if (mPlayingSounds[i] != NULL)
mPlayingSounds[i]->RehupVolume();
}
bool DSoundManager::LoadWAVSound(unsigned int theSfxID, const StringImpl& theFilename)
{
int aDataSize;
FILE* fp;
fp = fopen(theFilename.c_str(), "rb");
if (fp <= 0)
return false;
char aChunkType[5];
aChunkType[4] = '\0';
uint32 aChunkSize;
fread(aChunkType, 1, 4, fp);
if (!strcmp(aChunkType, "RIFF") == 0)
return false;
fread(&aChunkSize, 4, 1, fp);
fread(aChunkType, 1, 4, fp);
if (!strcmp(aChunkType, "WAVE") == 0)
return false;
uint16 aBitCount = 16;
uint16 aChannelCount = 1;
uint32 aSampleRate = 22050;
uint8 anXor = 0;
while (!feof(fp))
{
fread(aChunkType, 1, 4, fp);
if (fread(&aChunkSize, 4, 1, fp) == 0)
return false;
int aCurPos = ftell(fp);
if (strcmp(aChunkType, "fmt ") == 0)
{
uint16 aFormatTag;
uint32 aBytesPerSec;
uint16 aBlockAlign;
fread(&aFormatTag, 2, 1, fp);
fread(&aChannelCount, 2, 1, fp);
fread(&aSampleRate, 4, 1, fp);
fread(&aBytesPerSec, 4, 1, fp);
fread(&aBlockAlign, 2, 1, fp);
fread(&aBitCount, 2, 1, fp);
if (aFormatTag != 1)
return false;
}
else if (strcmp(aChunkType, "data") == 0)
{
aDataSize = aChunkSize;
mSourceDataSizes[theSfxID] = aChunkSize;
PCMWAVEFORMAT aWaveFormat;
DSBUFFERDESC aBufferDesc;
// Set up wave format structure.
memset(&aWaveFormat, 0, sizeof(PCMWAVEFORMAT));
aWaveFormat.wf.wFormatTag = WAVE_FORMAT_PCM;
aWaveFormat.wf.nChannels = aChannelCount;
aWaveFormat.wf.nSamplesPerSec = aSampleRate;
aWaveFormat.wf.nBlockAlign = aChannelCount*aBitCount/8;
aWaveFormat.wf.nAvgBytesPerSec =
aWaveFormat.wf.nSamplesPerSec * aWaveFormat.wf.nBlockAlign;
aWaveFormat.wBitsPerSample = aBitCount;
// Set up DSBUFFERDESC structure.
memset(&aBufferDesc, 0, sizeof(DSBUFFERDESC)); // Zero it out.
aBufferDesc.dwSize = sizeof(DSBUFFERDESC);
//aBufferDesc.dwFlags = DSBCAPS_CTRL3D;
aBufferDesc.dwFlags = SOUND_FLAGS; //DSBCAPS_CTRLDEFAULT;
//aBufferDesc.dwFlags = 0;
aBufferDesc.dwBufferBytes = aDataSize;
aBufferDesc.lpwfxFormat = (LPWAVEFORMATEX)&aWaveFormat;
if (mDirectSound->CreateSoundBuffer(&aBufferDesc, &mSourceSounds[theSfxID], NULL) != DS_OK)
{
fclose(fp);
return false;
}
void* lpvPtr;
DWORD dwBytes;
if (mSourceSounds[theSfxID]->Lock(0, aDataSize, &lpvPtr, &dwBytes, NULL, NULL, 0) != DS_OK)
{
fclose(fp);
return false;
}
int aReadSize = (int)fread(lpvPtr, 1, aDataSize, fp);
fclose(fp);
for (int i = 0; i < aDataSize; i++)
((uint8*) lpvPtr)[i] ^= anXor;
if (mSourceSounds[theSfxID]->Unlock(lpvPtr, dwBytes, NULL, NULL) != DS_OK)
return false;
if (aReadSize != aDataSize)
return false;
return true;
}
fseek(fp, aCurPos+aChunkSize, SEEK_SET);
}
return false;
}
bool DSoundManager::LoadSound(unsigned int theSfxID, const StringImpl& theFilename)
{
if ((theSfxID < 0) || (theSfxID >= MAX_SOURCE_SOUNDS))
return false;
ReleaseSound(theSfxID);
if (!mDirectSound)
return true; // sounds just won't play, but this is not treated as a failure condition
mSourceFileNames[theSfxID] = theFilename;
StringImpl aFilename = theFilename;
if (aFilename.EndsWith(".wav", StringImpl::CompareKind_OrdinalIgnoreCase))
{
if (LoadWAVSound(theSfxID, aFilename))
return true;
}
return false;
}
int DSoundManager::LoadSound(const StringImpl& theFilename)
{
int i;
for (i = 0; i < MAX_SOURCE_SOUNDS; i++)
if (mSourceFileNames[i] == theFilename)
return i;
for (i = MAX_SOURCE_SOUNDS-1; i >= 0; i--)
{
if (mSourceSounds[i] == NULL)
{
if (!LoadSound(i, theFilename))
return -1;
else
return i;
}
}
return -1;
}
void DSoundManager::ReleaseSound(unsigned int theSfxID)
{
if (mSourceSounds[theSfxID] != NULL)
{
mSourceSounds[theSfxID]->Release();
mSourceSounds[theSfxID] = NULL;
mSourceFileNames[theSfxID] = "";
}
}
int DSoundManager::GetFreeSoundId()
{
for (int i=0; i<MAX_SOURCE_SOUNDS; i++)
{
if (mSourceSounds[i]==NULL)
return i;
}
return -1;
}
int DSoundManager::GetNumSounds()
{
int aCount = 0;
for (int i=0; i<MAX_SOURCE_SOUNDS; i++)
{
if (mSourceSounds[i]!=NULL)
aCount++;
}
return aCount;
}
bool DSoundManager::SetBaseVolume(unsigned int theSfxID, float theBaseVolume)
{
if ((theSfxID < 0) || (theSfxID >= MAX_SOURCE_SOUNDS))
return false;
mBaseVolumes[theSfxID] = theBaseVolume;
return true;
}
bool DSoundManager::SetBasePan(unsigned int theSfxID, int theBasePan)
{
if ((theSfxID < 0) || (theSfxID >= MAX_SOURCE_SOUNDS))
return false;
mBasePans[theSfxID] = theBasePan;
return true;
}
BFSoundInstance* DSoundManager::GetSoundInstance(unsigned int theSfxID)
{
if (theSfxID > MAX_SOURCE_SOUNDS)
return NULL;
int aFreeChannel = FindFreeChannel();
if (aFreeChannel < 0)
return NULL;
if (mDirectSound==NULL)
{
mPlayingSounds[aFreeChannel] = new DSoundInstance(this, NULL);
}
else
{
if (mSourceSounds[theSfxID] == NULL)
return NULL;
mPlayingSounds[aFreeChannel] = new DSoundInstance(this, mSourceSounds[theSfxID]);
}
mPlayingSounds[aFreeChannel]->SetBasePan(mBasePans[theSfxID]);
mPlayingSounds[aFreeChannel]->SetBaseVolume(mBaseVolumes[theSfxID]);
return mPlayingSounds[aFreeChannel];
}
void DSoundManager::ReleaseSounds()
{
for (int i = 0; i < MAX_SOURCE_SOUNDS; i++)
if (mSourceSounds[i] != NULL)
{
mSourceSounds[i]->Release();
mSourceSounds[i] = NULL;
}
}
void DSoundManager::ReleaseChannels()
{
for (int i = 0; i < MAX_CHANNELS; i++)
if (mPlayingSounds[i] != NULL)
{
delete mPlayingSounds[i];
mPlayingSounds[i] = NULL;
}
}
void DSoundManager::ReleaseFreeChannels()
{
for (int i = 0; i < MAX_CHANNELS; i++)
if (mPlayingSounds[i] != NULL && mPlayingSounds[i]->IsReleased())
{
delete mPlayingSounds[i];
mPlayingSounds[i] = NULL;
}
}
void DSoundManager::StopAllSounds()
{
for (int i = 0; i < MAX_CHANNELS; i++)
if (mPlayingSounds[i] != NULL)
{
bool isAutoRelease = mPlayingSounds[i]->mAutoRelease;
mPlayingSounds[i]->Stop();
mPlayingSounds[i]->mAutoRelease = isAutoRelease;
}
}
float DSoundManager::GetMasterVolume()
{
MIXERCONTROLDETAILS mcd;
MIXERCONTROLDETAILS_UNSIGNED mxcd_u;
MIXERLINECONTROLS mxlc;
MIXERCONTROL mlct;
MIXERLINE mixerLine;
HMIXER hmx;
MIXERCAPS pmxcaps;
mixerOpen((HMIXER*) &hmx, 0, 0, 0, MIXER_OBJECTF_MIXER);
mixerGetDevCaps(0, &pmxcaps, sizeof(pmxcaps));
mxlc.cbStruct = sizeof(mxlc);
mxlc.cbmxctrl = sizeof(mlct);
mxlc.pamxctrl = &mlct;
mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
mixerLine.cbStruct = sizeof(mixerLine);
mixerLine.dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT;
mixerGetLineInfo((HMIXEROBJ) hmx, &mixerLine, MIXER_GETLINEINFOF_COMPONENTTYPE);
mxlc.dwLineID = mixerLine.dwLineID;
mixerGetLineControls((HMIXEROBJ) hmx, &mxlc, MIXER_GETLINECONTROLSF_ONEBYTYPE);
mcd.cbStruct = sizeof(mcd);
mcd.dwControlID = mlct.dwControlID;
mcd.cChannels = 1;
mcd.cMultipleItems = 0;
mcd.cbDetails = sizeof(mxcd_u);
mcd.paDetails = &mxcd_u;
mixerGetControlDetails((HMIXEROBJ) hmx, &mcd, 0L);
mixerClose(hmx);
return mxcd_u.dwValue / (float) 0xFFFF;
}
void DSoundManager::SetMasterVolume(float theVolume)
{
MIXERCONTROLDETAILS mcd;
MIXERCONTROLDETAILS_UNSIGNED mxcd_u;
MIXERLINECONTROLS mxlc;
MIXERCONTROL mlct;
MIXERLINE mixerLine;
HMIXER hmx;
MIXERCAPS pmxcaps;
mixerOpen((HMIXER*) &hmx, 0, 0, 0, MIXER_OBJECTF_MIXER);
mixerGetDevCaps(0, &pmxcaps, sizeof(pmxcaps));
mxlc.cbStruct = sizeof(mxlc);
mxlc.cbmxctrl = sizeof(mlct);
mxlc.pamxctrl = &mlct;
mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
mixerLine.cbStruct = sizeof(mixerLine);
mixerLine.dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT;
mixerGetLineInfo((HMIXEROBJ) hmx, &mixerLine, MIXER_GETLINEINFOF_COMPONENTTYPE);
mxlc.dwLineID = mixerLine.dwLineID;
mixerGetLineControls((HMIXEROBJ) hmx, &mxlc, MIXER_GETLINECONTROLSF_ONEBYTYPE);
mcd.cbStruct = sizeof(mcd);
mcd.dwControlID = mlct.dwControlID;
mcd.cChannels = 1;
mcd.cMultipleItems = 0;
mcd.cbDetails = sizeof(mxcd_u);
mcd.paDetails = &mxcd_u;
mxcd_u.dwValue = (int) (0xFFFF * theVolume);
mixerSetControlDetails((HMIXEROBJ) hmx, &mcd, 0L);
mixerClose(hmx);
}
void DSoundManager::Flush()
{
}
void DSoundManager::SetCooperativeWindow(HWND theHWnd, bool isWindowed)
{
if (mDirectSound != NULL)
mDirectSound->SetCooperativeLevel(theHWnd,DSSCL_NORMAL);
/*
if (isWindowed==true) mDirectSound->SetCooperativeLevel(theHWnd,DSSCL_NORMAL);
else mDirectSound->SetCooperativeLevel(theHWnd,DSSCL_EXCLUSIVE);
*/
}
#undef SOUND_FLAGS

View file

@ -0,0 +1,68 @@
#ifndef __DSOUNDMANAGER_H__
#define __DSOUNDMANAGER_H__
#include <dsound.h>
#include "BFSound.h"
namespace Beefy
{
class DSoundInstance;
class DSoundManager : public BFSoundManager
{
friend class DSoundInstance;
friend class DSoundMusicInterface;
protected:
LPDIRECTSOUNDBUFFER mSourceSounds[MAX_SOURCE_SOUNDS];
String mSourceFileNames[MAX_SOURCE_SOUNDS];
LPDIRECTSOUNDBUFFER mPrimaryBuffer;
int32 mSourceDataSizes[MAX_SOURCE_SOUNDS];
float mBaseVolumes[MAX_SOURCE_SOUNDS];
int mBasePans[MAX_SOURCE_SOUNDS];
DSoundInstance* mPlayingSounds[MAX_CHANNELS];
float mMasterVolume;
DWORD mLastReleaseTick;
protected:
int FindFreeChannel();
int VolumeToDB(float theVolume);
bool LoadWAVSound(unsigned int theSfxID, const StringImpl& theFilename);
void ReleaseFreeChannels();
public:
LPDIRECTSOUND mDirectSound;
DSoundManager(HWND theHWnd);
virtual ~DSoundManager();
virtual bool Initialized() override;
virtual bool LoadSound(unsigned int theSfxID, const StringImpl& theFilename) override;
virtual int LoadSound(const StringImpl& theFilename) override;
virtual void ReleaseSound(unsigned int theSfxID) override;
virtual void SetVolume(float theVolume) override;
virtual bool SetBaseVolume(unsigned int theSfxID, float theBaseVolume) override;
virtual bool SetBasePan(unsigned int theSfxID, int theBasePan) override;
virtual BFSoundInstance* GetSoundInstance(unsigned int theSfxID);
virtual void ReleaseSounds() override;
virtual void ReleaseChannels() override;
virtual float GetMasterVolume() override;
virtual void SetMasterVolume(float theVolume) override;
virtual void Flush() override;
virtual void SetCooperativeWindow(HWND theHWnd, bool isWindowed);
virtual void StopAllSounds() override;
virtual int GetFreeSoundId() override;
virtual int GetNumSounds() override;
};
}
#endif //__DSOUNDMANAGER_H__

View file

@ -1,7 +1,9 @@
#include <dsound.h>
#include "WinBFApp.h"
#include "DXRenderDevice.h"
#include <signal.h>
#include "../../util/BeefPerf.h"
#include "DSoundManager.h"
#include <dwmapi.h>
#pragma comment(lib, "dwmapi.lib")
@ -130,9 +132,9 @@ WinBFWindow::WinBFWindow(BFWindow* parent, const StringImpl& title, int x, int y
::SystemParametersInfo(SPI_GETWORKAREA, NULL, &desktopRect, NULL);
if (x + width >= desktopRect.right)
x = std::max((int)desktopRect.left, requestedX - width);
x = BF_MAX((int)desktopRect.left, requestedX - width);
if (y + height >= desktopRect.bottom)
y = std::max((int)desktopRect.top, requestedY - height);
y = BF_MAX((int)desktopRect.top, requestedY - height);
}
mFlags = windowFlags;
@ -1037,11 +1039,13 @@ WinBFApp::WinBFApp()
mDataDir = mInstallDir;
mInMsgProc = false;
mDSoundManager = NULL;
}
WinBFApp::~WinBFApp()
{
delete mRenderDevice;
delete mDSoundManager;
}
void WinBFApp::Init()
@ -1670,6 +1674,13 @@ BFSysBitmap* WinBFApp::LoadSysBitmap(const WCHAR* fileName)
return NULL;
}
BFSoundManager* WinBFApp::GetSoundManager()
{
if (mDSoundManager == NULL)
mDSoundManager = new DSoundManager(NULL);
return mDSoundManager;
}
void WinBFWindow::ModalsRemoved()
{
::EnableWindow(mHWnd, TRUE);

View file

@ -9,6 +9,7 @@
NS_BF_BEGIN;
class RenderDevice;
class DSoundManager;
typedef Dictionary<void*, HGLOBAL> PtrToHGlobalMap;
typedef Dictionary<String, uint32> StringToUIntMap;
@ -87,6 +88,7 @@ public:
bool mInMsgProc;
PtrToHGlobalMap mLockedHGlobalMap;
StringToUIntMap mClipboardFormatMap;
DSoundManager* mDSoundManager;
protected:
virtual void Draw() override;
@ -112,6 +114,8 @@ public:
virtual void RehupMouse() override;
virtual BFSysBitmap* LoadSysBitmap(const WCHAR* fileName) override;
virtual BFSoundManager* GetSoundManager() override;
};
NS_BF_END;

View file

@ -31,6 +31,25 @@ USING_NS_BF;
#define BP_ABI_VERSION 2
BpManager* BpManager::sBpManager = NULL;
static bool gOwnsBpManager = false;
static BpThreadInfo sFakeThreadInfo;
struct BpManagerOwner
{
BpManager* mOwnedManager;
bool mDidShutdown;
BpManagerOwner()
{
mOwnedManager = NULL;
mDidShutdown = false;
}
~BpManagerOwner()
{
mDidShutdown = true;
delete mOwnedManager;
}
};
static BpManagerOwner gBpManagerOwner;
BF_TLS_DECLSPEC BpThreadInfo* Beefy::BpManager::sBpThreadInfo;
@ -314,7 +333,7 @@ const char* BpCmdTarget::ToStrPtr(const char* str)
return str;
}
#define BPCMD_PREPARE if (!BpManager::Get()->mCollectData) return; AutoCrit autoCrit(mCritSect)
#define BPCMD_PREPARE if ((gBpManagerOwner.mDidShutdown) || (!BpManager::Get()->mCollectData)) return; AutoCrit autoCrit(mCritSect)
#define GET_FROM(ptr, T) *((T*)(ptr += sizeof(T)) - 1)
@ -1527,6 +1546,8 @@ BpThreadInfo* BpManager::GetCurThreadInfo()
BpThreadInfo* threadInfo = sBpThreadInfo;
if (threadInfo == NULL)
{
if (gBpManagerOwner.mDidShutdown)
return &sFakeThreadInfo;
threadInfo = Get()->SlowGetCurThreadInfo();
sBpThreadInfo = threadInfo;
}
@ -1581,13 +1602,14 @@ BpManager* BpManager::Get()
BpSharedMemory* sharedMem = (BpSharedMemory*)MapViewOfFile(fileMapping, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(BpSharedMemory));
if (sharedMem != NULL)
{
sBpManager = new BpManager();
sBpManager = new BpManager();
sBpManager->mMutex = mutex;
sBpManager->mSharedMemoryFile = sharedMem;
sBpManager->mSharedMemoryFile = fileMapping;
sharedMem->mBpManager = sBpManager;
sharedMem->mABIVersion = BP_ABI_VERSION;
::UnmapViewOfFile(sharedMem);
::ReleaseMutex(mutex);
gBpManagerOwner.mOwnedManager = sBpManager;
}
else
{
@ -1609,6 +1631,7 @@ BpManager* BpManager::Get()
if (sBpManager == NULL)
{
sBpManager = new BpManager();
gBpManagerOwner.mOwnedManager = sBpManager;
}
return sBpManager;
}