Migrate sound to SDL (#70)

This commit is contained in:
Alexander Batalov 2022-07-12 12:09:53 +03:00 committed by GitHub
parent bbfd7785b5
commit 07d1f9fd81
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 639 additions and 687 deletions

View File

@ -233,7 +233,8 @@ add_executable(${EXECUTABLE_NAME} WIN32 MACOSX_BUNDLE
)
target_sources(${EXECUTABLE_NAME} PUBLIC
"src/dsound_compat.h"
"src/audio_engine.cc"
"src/audio_engine.h"
"src/fps_limiter.cc"
"src/fps_limiter.h"
"src/platform_compat.cc"

432
src/audio_engine.cc Normal file
View File

@ -0,0 +1,432 @@
#include "audio_engine.h"
#include <string.h>
#include <mutex>
#include <SDL.h>
#define AUDIO_ENGINE_SOUND_BUFFERS 8
struct AudioEngineSoundBuffer {
bool active;
unsigned int size;
int bitsPerSample;
int channels;
int rate;
void* data;
int volume;
bool playing;
bool looping;
unsigned int pos;
SDL_AudioStream* stream;
std::recursive_mutex mutex;
};
extern bool gProgramIsActive;
static bool soundBufferIsValid(int soundBufferIndex);
static void audioEngineMixin(void* userData, Uint8* stream, int length);
static SDL_AudioSpec gAudioEngineSpec;
static SDL_AudioDeviceID gAudioEngineDeviceId = -1;
static AudioEngineSoundBuffer gAudioEngineSoundBuffers[AUDIO_ENGINE_SOUND_BUFFERS];
static bool soundBufferIsValid(int soundBufferIndex)
{
return soundBufferIndex >= 0 && soundBufferIndex < AUDIO_ENGINE_SOUND_BUFFERS;
}
static void audioEngineMixin(void* userData, Uint8* stream, int length)
{
memset(stream, gAudioEngineSpec.silence, length);
if (!gProgramIsActive) {
return;
}
for (int index = 0; index < AUDIO_ENGINE_SOUND_BUFFERS; index++) {
AudioEngineSoundBuffer* soundBuffer = &(gAudioEngineSoundBuffers[index]);
std::lock_guard<std::recursive_mutex> lock(soundBuffer->mutex);
if (soundBuffer->active && soundBuffer->playing) {
int srcFrameSize = soundBuffer->bitsPerSample / 8 * soundBuffer->channels;
unsigned char buffer[1024];
int pos = 0;
while (pos < length) {
int remaining = length - pos;
if (remaining > sizeof(buffer)) {
remaining = sizeof(buffer);
}
// TODO: Make something better than frame-by-frame convertion.
SDL_AudioStreamPut(soundBuffer->stream, (unsigned char*)soundBuffer->data + soundBuffer->pos, srcFrameSize);
soundBuffer->pos += srcFrameSize;
int bytesRead = SDL_AudioStreamGet(soundBuffer->stream, buffer, remaining);
if (bytesRead == -1) {
break;
}
SDL_MixAudioFormat(stream + pos, buffer, gAudioEngineSpec.format, bytesRead, soundBuffer->volume);
if (soundBuffer->pos >= soundBuffer->size) {
if (soundBuffer->looping) {
soundBuffer->pos %= soundBuffer->size;
} else {
soundBuffer->playing = false;
break;
}
}
pos += bytesRead;
}
}
}
}
bool audioEngineInit()
{
if (SDL_InitSubSystem(SDL_INIT_AUDIO) == -1) {
return false;
}
SDL_AudioSpec desiredSpec;
desiredSpec.freq = 22050;
desiredSpec.format = AUDIO_S16;
desiredSpec.channels = 2;
desiredSpec.samples = 1024;
desiredSpec.callback = audioEngineMixin;
gAudioEngineDeviceId = SDL_OpenAudioDevice(NULL, 0, &desiredSpec, &gAudioEngineSpec, SDL_AUDIO_ALLOW_ANY_CHANGE);
if (gAudioEngineDeviceId == -1) {
return false;
}
SDL_PauseAudioDevice(gAudioEngineDeviceId, 0);
return true;
}
void audioEngineExit()
{
if (gAudioEngineDeviceId != -1) {
SDL_CloseAudioDevice(gAudioEngineDeviceId);
gAudioEngineDeviceId = -1;
}
SDL_QuitSubSystem(SDL_INIT_AUDIO);
}
void audioEnginePause()
{
if (gAudioEngineDeviceId != -1) {
SDL_PauseAudioDevice(gAudioEngineDeviceId, 1);
}
}
void audioEngineResume()
{
if (gAudioEngineDeviceId != -1) {
SDL_PauseAudioDevice(gAudioEngineDeviceId, 0);
}
}
int audioEngineCreateSoundBuffer(unsigned int size, int bitsPerSample, int channels, int rate)
{
for (int index = 0; index < AUDIO_ENGINE_SOUND_BUFFERS; index++) {
AudioEngineSoundBuffer* soundBuffer = &(gAudioEngineSoundBuffers[index]);
std::lock_guard<std::recursive_mutex> lock(soundBuffer->mutex);
if (!soundBuffer->active) {
soundBuffer->active = true;
soundBuffer->size = size;
soundBuffer->bitsPerSample = bitsPerSample;
soundBuffer->channels = channels;
soundBuffer->rate = rate;
soundBuffer->volume = SDL_MIX_MAXVOLUME;
soundBuffer->playing = false;
soundBuffer->looping = false;
soundBuffer->pos = 0;
soundBuffer->data = malloc(size);
soundBuffer->stream = SDL_NewAudioStream(bitsPerSample == 16 ? AUDIO_S16 : AUDIO_S8, channels, rate, gAudioEngineSpec.format, gAudioEngineSpec.channels, gAudioEngineSpec.freq);
return index;
}
}
return -1;
}
bool audioEngineSoundBufferRelease(int soundBufferIndex)
{
if (!soundBufferIsValid(soundBufferIndex)) {
return false;
}
AudioEngineSoundBuffer* soundBuffer = &(gAudioEngineSoundBuffers[soundBufferIndex]);
std::lock_guard<std::recursive_mutex> lock(soundBuffer->mutex);
if (!soundBuffer->active) {
return false;
}
soundBuffer->active = false;
free(soundBuffer->data);
soundBuffer->data = NULL;
SDL_FreeAudioStream(soundBuffer->stream);
soundBuffer->stream = NULL;
return true;
}
bool audioEngineSoundBufferSetVolume(int soundBufferIndex, int volume)
{
if (!soundBufferIsValid(soundBufferIndex)) {
return false;
}
AudioEngineSoundBuffer* soundBuffer = &(gAudioEngineSoundBuffers[soundBufferIndex]);
std::lock_guard<std::recursive_mutex> lock(soundBuffer->mutex);
if (!soundBuffer->active) {
return false;
}
soundBuffer->volume = volume;
return true;
}
bool audioEngineSoundBufferGetVolume(int soundBufferIndex, int* volumePtr)
{
if (!soundBufferIsValid(soundBufferIndex)) {
return false;
}
AudioEngineSoundBuffer* soundBuffer = &(gAudioEngineSoundBuffers[soundBufferIndex]);
std::lock_guard<std::recursive_mutex> lock(soundBuffer->mutex);
if (!soundBuffer->active) {
return false;
}
*volumePtr = soundBuffer->volume;
return true;
}
bool audioEngineSoundBufferSetPan(int soundBufferIndex, int pan)
{
if (!soundBufferIsValid(soundBufferIndex)) {
return false;
}
AudioEngineSoundBuffer* soundBuffer = &(gAudioEngineSoundBuffers[soundBufferIndex]);
std::lock_guard<std::recursive_mutex> lock(soundBuffer->mutex);
if (!soundBuffer->active) {
return false;
}
// NOTE: Audio engine does not support sound panning. I'm not sure it's
// even needed. For now this value is silently ignored.
return true;
}
bool audioEngineSoundBufferPlay(int soundBufferIndex, unsigned int flags)
{
if (!soundBufferIsValid(soundBufferIndex)) {
return false;
}
AudioEngineSoundBuffer* soundBuffer = &(gAudioEngineSoundBuffers[soundBufferIndex]);
std::lock_guard<std::recursive_mutex> lock(soundBuffer->mutex);
if (!soundBuffer->active) {
return false;
}
soundBuffer->playing = true;
if ((flags & AUDIO_ENGINE_SOUND_BUFFER_PLAY_LOOPING) != 0) {
soundBuffer->looping = true;
}
return true;
}
bool audioEngineSoundBufferStop(int soundBufferIndex)
{
if (!soundBufferIsValid(soundBufferIndex)) {
return false;
}
AudioEngineSoundBuffer* soundBuffer = &(gAudioEngineSoundBuffers[soundBufferIndex]);
std::lock_guard<std::recursive_mutex> lock(soundBuffer->mutex);
if (!soundBuffer->active) {
return false;
}
soundBuffer->playing = false;
return true;
}
bool audioEngineSoundBufferGetCurrentPosition(int soundBufferIndex, unsigned int* readPosPtr, unsigned int* writePosPtr)
{
if (!soundBufferIsValid(soundBufferIndex)) {
return false;
}
AudioEngineSoundBuffer* soundBuffer = &(gAudioEngineSoundBuffers[soundBufferIndex]);
std::lock_guard<std::recursive_mutex> lock(soundBuffer->mutex);
if (!soundBuffer->active) {
return false;
}
if (readPosPtr != NULL) {
*readPosPtr = soundBuffer->pos;
}
if (writePosPtr != NULL) {
*writePosPtr = soundBuffer->pos;
if (soundBuffer->playing) {
// 15 ms lead
// See: https://docs.microsoft.com/en-us/previous-versions/windows/desktop/mt708925(v=vs.85)#remarks
*writePosPtr += soundBuffer->rate / 150;
*writePosPtr %= soundBuffer->size;
}
}
return true;
}
bool audioEngineSoundBufferSetCurrentPosition(int soundBufferIndex, unsigned int pos)
{
if (!soundBufferIsValid(soundBufferIndex)) {
return false;
}
AudioEngineSoundBuffer* soundBuffer = &(gAudioEngineSoundBuffers[soundBufferIndex]);
std::lock_guard<std::recursive_mutex> lock(soundBuffer->mutex);
if (!soundBuffer->active) {
return false;
}
soundBuffer->pos = pos % soundBuffer->size;
return true;
}
bool audioEngineSoundBufferLock(int soundBufferIndex, unsigned int writePos, unsigned int writeBytes, void** audioPtr1, unsigned int* audioBytes1, void** audioPtr2, unsigned int* audioBytes2, unsigned int flags)
{
if (!soundBufferIsValid(soundBufferIndex)) {
return false;
}
AudioEngineSoundBuffer* soundBuffer = &(gAudioEngineSoundBuffers[soundBufferIndex]);
std::lock_guard<std::recursive_mutex> lock(soundBuffer->mutex);
if (!soundBuffer->active) {
return false;
}
if (audioBytes1 == NULL) {
return false;
}
if ((flags & AUDIO_ENGINE_SOUND_BUFFER_LOCK_FROM_WRITE_POS) != 0) {
if (!audioEngineSoundBufferGetCurrentPosition(soundBufferIndex, NULL, &writePos)) {
return false;
}
}
if ((flags & AUDIO_ENGINE_SOUND_BUFFER_LOCK_ENTIRE_BUFFER) != 0) {
writeBytes = soundBuffer->size;
}
if (writePos + writeBytes <= soundBuffer->size) {
*(unsigned char**)audioPtr1 = (unsigned char*)soundBuffer->data + writePos;
*audioBytes1 = writeBytes;
if (audioPtr2 != NULL) {
*audioPtr2 = NULL;
}
if (audioBytes2 != NULL) {
*audioBytes2 = 0;
}
} else {
unsigned int remainder = writePos + writeBytes - soundBuffer->size;
*(unsigned char**)audioPtr1 = (unsigned char*)soundBuffer->data + writePos;
*audioBytes1 = soundBuffer->size - writePos;
if (audioPtr2 != NULL) {
*(unsigned char**)audioPtr2 = (unsigned char*)soundBuffer->data;
}
if (audioBytes2 != NULL) {
*audioBytes2 = writeBytes - (soundBuffer->size - writePos);
}
}
// TODO: Mark range as locked.
return true;
}
bool audioEngineSoundBufferUnlock(int soundBufferIndex, void* audioPtr1, unsigned int audioBytes1, void* audioPtr2, unsigned int audioBytes2)
{
if (!soundBufferIsValid(soundBufferIndex)) {
return false;
}
AudioEngineSoundBuffer* soundBuffer = &(gAudioEngineSoundBuffers[soundBufferIndex]);
std::lock_guard<std::recursive_mutex> lock(soundBuffer->mutex);
if (!soundBuffer->active) {
return false;
}
// TODO: Mark range as unlocked.
return true;
}
bool audioEngineSoundBufferGetStatus(int soundBufferIndex, unsigned int* statusPtr)
{
if (!soundBufferIsValid(soundBufferIndex)) {
return false;
}
AudioEngineSoundBuffer* soundBuffer = &(gAudioEngineSoundBuffers[soundBufferIndex]);
std::lock_guard<std::recursive_mutex> lock(soundBuffer->mutex);
if (!soundBuffer->active) {
return false;
}
if (statusPtr == NULL) {
return false;
}
*statusPtr = 0;
if (soundBuffer->playing) {
*statusPtr |= AUDIO_ENGINE_SOUND_BUFFER_STATUS_PLAYING;
if (soundBuffer->looping) {
*statusPtr |= AUDIO_ENGINE_SOUND_BUFFER_STATUS_LOOPING;
}
}
return true;
}

29
src/audio_engine.h Normal file
View File

@ -0,0 +1,29 @@
#ifndef AUDIO_ENGINE_H
#define AUDIO_ENGINE_H
#define AUDIO_ENGINE_SOUND_BUFFER_LOCK_FROM_WRITE_POS 0x00000001
#define AUDIO_ENGINE_SOUND_BUFFER_LOCK_ENTIRE_BUFFER 0x00000002
#define AUDIO_ENGINE_SOUND_BUFFER_PLAY_LOOPING 0x00000001
#define AUDIO_ENGINE_SOUND_BUFFER_STATUS_PLAYING 0x00000001
#define AUDIO_ENGINE_SOUND_BUFFER_STATUS_LOOPING 0x00000004
bool audioEngineInit();
void audioEngineExit();
void audioEnginePause();
void audioEngineResume();
int audioEngineCreateSoundBuffer(unsigned int size, int bitsPerSample, int channels, int rate);
bool audioEngineSoundBufferRelease(int soundBufferIndex);
bool audioEngineSoundBufferSetVolume(int soundBufferIndex, int volume);
bool audioEngineSoundBufferGetVolume(int soundBufferIndex, int* volumePtr);
bool audioEngineSoundBufferSetPan(int soundBufferIndex, int pan);
bool audioEngineSoundBufferPlay(int soundBufferIndex, unsigned int flags);
bool audioEngineSoundBufferStop(int soundBufferIndex);
bool audioEngineSoundBufferGetCurrentPosition(int soundBufferIndex, unsigned int* readPosPtr, unsigned int* writePosPtr);
bool audioEngineSoundBufferSetCurrentPosition(int soundBufferIndex, unsigned int pos);
bool audioEngineSoundBufferLock(int soundBufferIndex, unsigned int writePos, unsigned int writeBytes, void** audioPtr1, unsigned int* audioBytes1, void** audioPtr2, unsigned int* audioBytes2, unsigned int flags);
bool audioEngineSoundBufferUnlock(int soundBufferIndex, void* audioPtr1, unsigned int audioBytes1, void* audioPtr2, unsigned int audioBytes2);
bool audioEngineSoundBufferGetStatus(int soundBufferIndex, unsigned int* status);
#endif /* AUDIO_ENGINE_H */

View File

@ -1,5 +1,6 @@
#include "core.h"
#include "audio_engine.h"
#include "config.h"
#include "color.h"
#include "dinput.h"
@ -15,9 +16,6 @@
#include <limits.h>
#include <string.h>
#include <SDL.h>
#if _WIN32
#include <SDL_syswm.h>
#endif
// NOT USED.
void (*_idle_func)() = NULL;
@ -1276,9 +1274,11 @@ void _GNW95_process_message()
case SDL_WINDOWEVENT_FOCUS_GAINED:
gProgramIsActive = true;
windowRefreshAll(&_scr_size);
audioEngineResume();
break;
case SDL_WINDOWEVENT_FOCUS_LOST:
gProgramIsActive = false;
audioEnginePause();
break;
}
break;
@ -2055,18 +2055,6 @@ int _GNW95_init_window(int width, int height, bool fullscreen)
if (gSdlTextureSurface == NULL) {
goto err;
}
#if _WIN32
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
if (!SDL_GetWindowWMInfo(gSdlWindow, &info)) {
goto err;
}
// Needed for DirectSound.
gProgramWindow = info.info.win.window;
#endif
}
return 0;

View File

@ -1,17 +0,0 @@
#ifndef DSOUND_COMPAT_H
#define DSOUND_COMPAT_H
#ifdef _WIN32
#define HAVE_DSOUND 1
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <windows.h>
#include <mmreg.h>
#define DIRECTSOUND_VERSION 0x0300
#include <dsound.h>
#endif
#endif /* DSOUND_COMPAT_H */

View File

@ -163,9 +163,6 @@ static int _movieX;
// 0x638EB4
static int _movieY;
// 0x638EB8
static bool gMovieDirectSoundInitialized;
// 0x638EBC
static File* _alphaHandle;
@ -364,12 +361,6 @@ static int _noop()
void movieInit()
{
movieLibSetMemoryProcs(movieMallocImpl, movieFreeImpl);
#ifdef HAVE_DSOUND
movieLibSetDirectSound(gDirectSound);
gMovieDirectSoundInitialized = (gDirectSound != NULL);
#else
gMovieDirectSoundInitialized = false;
#endif
movieLibSetPaletteEntriesProc(movieSetPaletteEntriesImpl);
_MVE_sfSVGA(640, 480, 480, 0, 0, 0, 0, 0, 0);
movieLibSetReadProc(movieReadImpl);
@ -835,10 +826,8 @@ void movieSetBuildSubtitleFilePathProc(MovieBuildSubtitleFilePathProc* proc)
// 0x487BD0
void movieSetVolume(int volume)
{
if (gMovieDirectSoundInitialized) {
int normalizedVolume = _soundVolumeHMItoDirectSound(volume);
movieLibSetVolume(normalizedVolume);
}
int normalizedVolume = _soundVolumeHMItoDirectSound(volume);
movieLibSetVolume(normalizedVolume);
}
// 0x487BEC

View File

@ -4,6 +4,7 @@
#include "movie_lib.h"
#include "audio_engine.h"
#include "platform_compat.h"
#include <assert.h>
@ -146,16 +147,6 @@ static int _sync_late = 0;
// 0x51EDEC
static int _sync_FrameDropped = 0;
#ifdef HAVE_DSOUND
// 0x51EDF0
static LPDIRECTSOUND gMovieLibDirectSound = NULL;
#endif
#ifdef HAVE_DSOUND
// 0x51EDF4
static LPDIRECTSOUNDBUFFER gMovieLibDirectSoundBuffer = NULL;
#endif
// 0x51EDF8
static int gMovieLibVolume = 0;
@ -348,11 +339,6 @@ static unsigned int _$$R0063[256] = {
// 0x6B3660
static int dword_6B3660;
#ifdef HAVE_DSOUND
// 0x6B3668
static DSBCAPS stru_6B3668;
#endif
// 0x6B367C
static int _sf_ScreenWidth;
@ -520,6 +506,8 @@ static int dword_6B403F;
static SDL_Surface* gMovieSdlSurface1;
static SDL_Surface* gMovieSdlSurface2;
static int gMveSoundBuffer = -1;
static unsigned int gMveBufferBytes;
// 0x4F4800
void movieLibSetMemoryProcs(MallocProc* mallocProc, FreeProc* freeProc)
@ -558,24 +546,14 @@ static void _MVE_MemFree(STRUCT_6B3690* a1)
a1->field_4 = 0;
}
#ifdef HAVE_DSOUND
// 0x4F48F0
void movieLibSetDirectSound(LPDIRECTSOUND ds)
{
gMovieLibDirectSound = ds;
}
#endif
// 0x4F4900
void movieLibSetVolume(int volume)
{
gMovieLibVolume = volume;
#ifdef HAVE_DSOUND
if (gMovieLibDirectSoundBuffer != NULL) {
IDirectSoundBuffer_SetVolume(gMovieLibDirectSoundBuffer, volume);
if (gMveSoundBuffer != -1) {
audioEngineSoundBufferSetVolume(gMveSoundBuffer, volume);
}
#endif
}
// 0x4F4920
@ -583,11 +561,9 @@ void movieLibSetPan(int pan)
{
gMovieLibPan = pan;
#ifdef HAVE_DSOUND
if (gMovieLibDirectSoundBuffer != NULL) {
IDirectSoundBuffer_SetPan(gMovieLibDirectSoundBuffer, pan);
if (gMveSoundBuffer != -1) {
audioEngineSoundBufferSetPan(gMveSoundBuffer, pan);
}
#endif
}
// 0x4F4940
@ -832,11 +808,9 @@ static int _syncWait()
// 0x4F4EA0
static void _MVE_sndPause()
{
#ifdef HAVE_DSOUND
if (gMovieLibDirectSoundBuffer != NULL) {
IDirectSoundBuffer_Stop(gMovieLibDirectSoundBuffer);
if (gMveSoundBuffer != -1) {
audioEngineSoundBufferStop(gMveSoundBuffer);
}
#endif
}
// 0x4F4EC0
@ -1151,55 +1125,28 @@ static void _syncReset(int a1)
// 0x4F5570
static int _MVE_sndConfigure(int a1, int a2, int a3, int a4, int a5, int a6)
{
#ifdef HAVE_DSOUND
DSBUFFERDESC dsbd;
WAVEFORMATEX wfxFormat;
if (gMovieLibDirectSound == NULL) {
return 1;
}
_MVE_sndReset();
_snd_comp = a3;
dword_6B36A0 = a5;
_snd_buf = a6;
dsbd.dwSize = sizeof(DSBUFFERDESC);
dsbd.dwFlags = DSBCAPS_CTRLFREQUENCY | DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME;
dsbd.dwBufferBytes = (a2 + (a2 >> 1)) & 0xFFFFFFFC;
dsbd.dwReserved = 0;
dsbd.lpwfxFormat = &wfxFormat;
wfxFormat.wFormatTag = 1;
wfxFormat.nSamplesPerSec = a4;
wfxFormat.nChannels = 2 - (a3 < 1);
wfxFormat.nBlockAlign = wfxFormat.nChannels * (2 - (a5 < 1));
wfxFormat.cbSize = 0;
wfxFormat.nAvgBytesPerSec = wfxFormat.nSamplesPerSec * wfxFormat.nBlockAlign;
wfxFormat.wBitsPerSample = a5 < 1 ? 8 : 16;
gMveBufferBytes = (a2 + (a2 >> 1)) & 0xFFFFFFFC;
dword_6B3AE4 = 0;
dword_6B3660 = 0;
if (IDirectSound_CreateSoundBuffer(gMovieLibDirectSound, &dsbd, &gMovieLibDirectSoundBuffer, NULL) != DS_OK) {
gMveSoundBuffer = audioEngineCreateSoundBuffer(gMveBufferBytes, a5 < 1 ? 8 : 16, 2 - (a3 < 1), a4);
if (gMveSoundBuffer == -1) {
return 0;
}
IDirectSoundBuffer_SetVolume(gMovieLibDirectSoundBuffer, gMovieLibVolume);
IDirectSoundBuffer_SetPan(gMovieLibDirectSoundBuffer, gMovieLibPan);
audioEngineSoundBufferSetVolume(gMveSoundBuffer, gMovieLibVolume);
audioEngineSoundBufferSetPan(gMveSoundBuffer, gMovieLibPan);
dword_6B36A4 = 0;
stru_6B3668.dwSize = sizeof(DSBCAPS);
if (IDirectSoundBuffer_GetCaps(gMovieLibDirectSoundBuffer, &stru_6B3668) != DS_OK) {
return 0;
}
return 1;
#else
return 0;
#endif
}
// 0x4F56C0
@ -1214,23 +1161,20 @@ static void _MVE_syncSync()
// 0x4F56F0
static void _MVE_sndReset()
{
#ifdef HAVE_DSOUND
if (gMovieLibDirectSoundBuffer != NULL) {
IDirectSoundBuffer_Stop(gMovieLibDirectSoundBuffer);
IDirectSoundBuffer_Release(gMovieLibDirectSoundBuffer);
gMovieLibDirectSoundBuffer = NULL;
if (gMveSoundBuffer != -1) {
audioEngineSoundBufferStop(gMveSoundBuffer);
audioEngineSoundBufferRelease(gMveSoundBuffer);
gMveSoundBuffer = -1;
}
#endif
}
// 0x4F5720
static void _MVE_sndSync()
{
#ifdef HAVE_DSOUND
DWORD dwCurrentPlayCursor;
DWORD dwCurrentWriteCursor;
unsigned int dwCurrentPlayCursor;
unsigned int dwCurrentWriteCursor;
bool v10;
DWORD dwStatus;
unsigned int dwStatus;
unsigned int v1;
bool v2;
int v3;
@ -1247,27 +1191,23 @@ static void _MVE_sndSync()
_sync_late = _syncWaitLevel(_sync_wait_quanta >> 2) > -_sync_wait_quanta >> 1 && !_sync_FrameDropped;
_sync_FrameDropped = 0;
if (gMovieLibDirectSound == NULL) {
return;
}
if (gMovieLibDirectSoundBuffer == NULL) {
if (gMveSoundBuffer == -1) {
return;
}
while (1) {
if (IDirectSoundBuffer_GetStatus(gMovieLibDirectSoundBuffer, &dwStatus) != DS_OK) {
if (!audioEngineSoundBufferGetStatus(gMveSoundBuffer, &dwStatus)) {
return;
}
if (IDirectSoundBuffer_GetCurrentPosition(gMovieLibDirectSoundBuffer, &dwCurrentPlayCursor, &dwCurrentWriteCursor) != DS_OK) {
if (!audioEngineSoundBufferGetCurrentPosition(gMveSoundBuffer, &dwCurrentPlayCursor, &dwCurrentWriteCursor)) {
return;
}
dwCurrentWriteCursor = dword_6B36A4;
v1 = (stru_6B3668.dwBufferBytes + dword_6B39E0[dword_6B3660] - _gSoundTimeBase)
% stru_6B3668.dwBufferBytes;
v1 = (gMveBufferBytes + dword_6B39E0[dword_6B3660] - _gSoundTimeBase)
% gMveBufferBytes;
if (dwCurrentPlayCursor <= dword_6B36A4) {
if (v1 < dwCurrentPlayCursor || v1 >= dword_6B36A4) {
@ -1283,15 +1223,15 @@ static void _MVE_sndSync()
}
}
if (!v2 || !(dwStatus & DSBSTATUS_PLAYING)) {
if (!v2 || !(dwStatus & AUDIO_ENGINE_SOUND_BUFFER_STATUS_PLAYING)) {
if (v0) {
_syncReset(_sync_wait_quanta + (_sync_wait_quanta >> 2));
}
v3 = dword_6B39E0[dword_6B3660];
if (!(dwStatus & DSBSTATUS_PLAYING)) {
v4 = (stru_6B3668.dwBufferBytes + v3) % stru_6B3668.dwBufferBytes;
if (!(dwStatus & AUDIO_ENGINE_SOUND_BUFFER_STATUS_PLAYING)) {
v4 = (gMveBufferBytes + v3) % gMveBufferBytes;
if (dwCurrentWriteCursor >= dwCurrentPlayCursor) {
if (v4 >= dwCurrentPlayCursor && v4 < dwCurrentWriteCursor) {
@ -1306,11 +1246,11 @@ static void _MVE_sndSync()
}
if (v5) {
if (IDirectSoundBuffer_SetCurrentPosition(gMovieLibDirectSoundBuffer, v4) != DS_OK) {
if (!audioEngineSoundBufferSetCurrentPosition(gMveSoundBuffer, v4)) {
return;
}
if (IDirectSoundBuffer_Play(gMovieLibDirectSoundBuffer, 0, 0, 1) != DS_OK) {
if (!audioEngineSoundBufferPlay(gMveSoundBuffer, 1)) {
return;
}
}
@ -1318,20 +1258,20 @@ static void _MVE_sndSync()
break;
}
v6 = (stru_6B3668.dwBufferBytes + _gSoundTimeBase + v3) % stru_6B3668.dwBufferBytes;
v6 = (gMveBufferBytes + _gSoundTimeBase + v3) % gMveBufferBytes;
v7 = dwCurrentWriteCursor - dwCurrentPlayCursor;
if (((dwCurrentWriteCursor - dwCurrentPlayCursor) & 0x80000000) != 0) {
v7 += stru_6B3668.dwBufferBytes;
v7 += gMveBufferBytes;
}
v8 = stru_6B3668.dwBufferBytes - v7 - 1;
v8 = gMveBufferBytes - v7 - 1;
// NOTE: Original code uses signed comparison.
if ((int)stru_6B3668.dwBufferBytes / 2 < v8) {
v8 = stru_6B3668.dwBufferBytes >> 1;
if ((int)gMveBufferBytes / 2 < v8) {
v8 = gMveBufferBytes >> 1;
}
v9 = (stru_6B3668.dwBufferBytes + dwCurrentPlayCursor - v8) % stru_6B3668.dwBufferBytes;
v9 = (gMveBufferBytes + dwCurrentPlayCursor - v8) % gMveBufferBytes;
dwCurrentPlayCursor = v9;
@ -1350,7 +1290,7 @@ static void _MVE_sndSync()
}
if (!v10) {
IDirectSoundBuffer_Stop(gMovieLibDirectSoundBuffer);
audioEngineSoundBufferStop(gMveSoundBuffer);
}
break;
@ -1365,10 +1305,6 @@ static void _MVE_sndSync()
++dword_6B3660;
}
}
#else
_sync_late = _syncWaitLevel(_sync_wait_quanta >> 2) > -_sync_wait_quanta >> 1 && !_sync_FrameDropped;
_sync_FrameDropped = 0;
#endif
}
// 0x4F59B0
@ -1394,20 +1330,19 @@ static int _syncWaitLevel(int a1)
// 0x4F5A00
static void _CallsSndBuff_Loc(unsigned char* a1, int a2)
{
#ifdef HAVE_DSOUND
int v2;
int v3;
int v5;
DWORD dwCurrentPlayCursor;
DWORD dwCurrentWriteCursor;
LPVOID lpvAudioPtr1;
DWORD dwAudioBytes1;
LPVOID lpvAudioPtr2;
DWORD dwAudioBytes2;
unsigned int dwCurrentPlayCursor;
unsigned int dwCurrentWriteCursor;
void* lpvAudioPtr1;
unsigned int dwAudioBytes1;
void* lpvAudioPtr2;
unsigned int dwAudioBytes2;
_gSoundTimeBase = a2;
if (gMovieLibDirectSoundBuffer == NULL) {
if (gMveSoundBuffer == -1) {
return;
}
@ -1420,13 +1355,13 @@ static void _CallsSndBuff_Loc(unsigned char* a1, int a2)
return;
}
if (IDirectSoundBuffer_GetCurrentPosition(gMovieLibDirectSoundBuffer, &dwCurrentPlayCursor, &dwCurrentWriteCursor) != DS_OK) {
if (!audioEngineSoundBufferGetCurrentPosition(gMveSoundBuffer, &dwCurrentPlayCursor, &dwCurrentWriteCursor)) {
return;
}
dwCurrentWriteCursor = dword_6B36A4;
if (IDirectSoundBuffer_Lock(gMovieLibDirectSoundBuffer, dword_6B36A4, a2, &lpvAudioPtr1, &dwAudioBytes1, &lpvAudioPtr2, &dwAudioBytes2, 0) != DS_OK) {
if (!audioEngineSoundBufferLock(gMveSoundBuffer, dword_6B36A4, a2, &lpvAudioPtr1, &dwAudioBytes1, &lpvAudioPtr2, &dwAudioBytes2, 0)) {
return;
}
@ -1443,11 +1378,11 @@ static void _CallsSndBuff_Loc(unsigned char* a1, int a2)
dword_6B36A4 = dwAudioBytes2;
}
if (dword_6B36A4 == stru_6B3668.dwBufferBytes) {
if (dword_6B36A4 == gMveBufferBytes) {
dword_6B36A4 = 0;
}
IDirectSoundBuffer_Unlock(gMovieLibDirectSoundBuffer, lpvAudioPtr1, dwAudioBytes1, lpvAudioPtr2, dwAudioBytes2);
audioEngineSoundBufferUnlock(gMveSoundBuffer, lpvAudioPtr1, dwAudioBytes1, lpvAudioPtr2, dwAudioBytes2);
dword_6B39E0[dword_6B3AE4] = dwCurrentWriteCursor;
@ -1456,7 +1391,6 @@ static void _CallsSndBuff_Loc(unsigned char* a1, int a2)
} else {
++dword_6B3AE4;
}
#endif
}
// 0x4F5B70

View File

@ -1,7 +1,6 @@
#ifndef MOVIE_LIB_H
#define MOVIE_LIB_H
#include "dsound_compat.h"
#include "memory_defs.h"
#include <SDL.h>
@ -11,9 +10,6 @@ typedef void(MovieShowFrameProc)(SDL_Surface*, int, int, int, int, int, int, int
void movieLibSetMemoryProcs(MallocProc* mallocProc, FreeProc* freeProc);
void movieLibSetReadProc(MovieReadProc* readProc);
#ifdef HAVE_DSOUND
void movieLibSetDirectSound(LPDIRECTSOUND ds);
#endif
void movieLibSetVolume(int volume);
void movieLibSetPan(int pan);
void _MVE_sfSVGA(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9);

File diff suppressed because it is too large Load Diff

View File

@ -41,8 +41,6 @@ typedef enum SoundError {
SOUND_INVALID_HANDLE = 30,
SOUND_NO_MEMORY_AVAILABLE = 31,
SOUND_UNKNOWN_ERROR = 32,
// TODO: Remove once DirectX -> SDL transition is completed.
SOUND_NOT_IMPLEMENTED = 33,
SOUND_ERR_COUNT,
} SoundError;
@ -70,10 +68,10 @@ typedef void SoundCallback(void* userData, int a2);
typedef struct Sound {
SoundFileIO io;
unsigned char* field_20;
#ifdef HAVE_DSOUND
LPDIRECTSOUNDBUFFER directSoundBuffer;
DSBUFFERDESC directSoundBufferDescription;
#endif
int soundBuffer;
int bitsPerSample;
int channels;
int rate;
int field_3C;
// flags
int field_40;
@ -91,9 +89,7 @@ typedef struct Sound {
int field_68;
int readLimit;
int field_70;
#ifdef HAVE_DSOUND
DWORD field_74;
#endif
unsigned int field_74;
int field_78;
int field_7C;
int field_80;
@ -106,10 +102,6 @@ typedef struct Sound {
struct Sound* prev;
} Sound;
#ifdef HAVE_DSOUND
extern LPDIRECTSOUND gDirectSound;
#endif
void soundSetMemoryProcs(MallocProc* mallocProc, ReallocProc* reallocProc, FreeProc* freeProc);
const char* soundGetErrorDescription(int err);
int soundInit(int a1, int a2, int a3, int a4, int rate);

View File

@ -8,77 +8,26 @@
#include <stdlib.h>
#ifdef _WIN32
#ifdef HAVE_DSOUND
// 0x51E430
DirectSoundCreateProc* gDirectSoundCreateProc = NULL;
#endif
// 0x51E434
HWND gProgramWindow = NULL;
// 0x51E444
bool gProgramIsActive = false;
// GNW95MUTEX
HANDLE _GNW95_mutex = NULL;
#ifdef HAVE_DSOUND
// 0x51E454
HMODULE gDSoundDLL = NULL;
#endif
// 0x4DE700
int main(int argc, char* argv[])
{
_GNW95_mutex = CreateMutexA(0, TRUE, "GNW95MUTEX");
if (GetLastError() == ERROR_SUCCESS) {
SDL_ShowCursor(SDL_DISABLE);
if (_LoadDirectX()) {
gProgramIsActive = true;
falloutMain(argc, argv);
}
gProgramIsActive = true;
falloutMain(argc, argv);
CloseHandle(_GNW95_mutex);
}
return 0;
}
// 0x4DE8D0
bool _LoadDirectX()
{
#ifdef HAVE_DSOUND
gDSoundDLL = LoadLibraryA("DSOUND.DLL");
if (gDSoundDLL == NULL) {
goto err;
}
gDirectSoundCreateProc = (DirectSoundCreateProc*)GetProcAddress(gDSoundDLL, "DirectSoundCreate");
if (gDirectSoundCreateProc == NULL) {
goto err;
}
#endif
atexit(_UnloadDirectX);
return true;
err:
_UnloadDirectX();
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Could not load DirectX", "This program requires DirectX 3.0a or later.", NULL);
return false;
}
// 0x4DE988
void _UnloadDirectX(void)
{
#ifdef HAVE_DSOUND
if (gDSoundDLL != NULL) {
FreeLibrary(gDSoundDLL);
gDSoundDLL = NULL;
}
#endif
}
#else
bool gProgramIsActive = false;

View File

@ -1,28 +1,13 @@
#ifndef WIN32_H
#define WIN32_H
#include "dsound_compat.h"
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <windows.h>
#ifdef HAVE_DSOUND
typedef HRESULT(__stdcall DirectSoundCreateProc)(GUID*, LPDIRECTSOUND*, IUnknown*);
#endif
#ifdef HAVE_DSOUND
extern DirectSoundCreateProc* gDirectSoundCreateProc;
#endif
extern HWND gProgramWindow;
extern bool gProgramIsActive;
extern HANDLE _GNW95_mutex;
#ifdef HAVE_DSOUND
extern HMODULE gDSoundDLL;
#endif
bool _LoadDirectX();
void _UnloadDirectX(void);
#else
extern bool gProgramIsActive;
#endif