diff --git a/CMakeLists.txt b/CMakeLists.txt index 774e910be..2b6aca744 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -289,6 +289,7 @@ set(devilutionx_SRCS SourceX/thread.cpp SourceX/sound.cpp SourceX/soundsample.cpp + SourceX/storm_sdl_rw.cpp SourceX/storm/storm.cpp SourceX/storm/storm_net.cpp SourceX/dvlnet/abstract_net.cpp diff --git a/SourceS/miniwin/misc.h b/SourceS/miniwin/misc.h index 53ccb97ec..831b358a7 100644 --- a/SourceS/miniwin/misc.h +++ b/SourceS/miniwin/misc.h @@ -62,6 +62,7 @@ bool PostMessage(UINT Msg, WPARAM wParam, LPARAM lParam); // MSCVRT emulation // +#define DVL_FILE_BEGIN 0 #define DVL_FILE_CURRENT 1 #define DVL_FILE_END 2 diff --git a/SourceX/sound.cpp b/SourceX/sound.cpp index 1ac306beb..c1e3e9654 100644 --- a/SourceX/sound.cpp +++ b/SourceX/sound.cpp @@ -6,6 +6,7 @@ #include "all.h" #include "../3rdParty/Storm/Source/storm.h" #include "stubs.h" +#include "storm_sdl_rw.h" #include #include @@ -15,9 +16,11 @@ BOOLEAN gbSndInited; /** Specifies whether background music is enabled. */ HANDLE sghMusic; +namespace { + Mix_Music *music; -SDL_RWops *musicRw; -char *musicBuffer; + +} // namespace /* data */ @@ -157,12 +160,10 @@ void music_stop() { if (sghMusic) { Mix_HaltMusic(); - SFileCloseFile(sghMusic); - sghMusic = NULL; Mix_FreeMusic(music); music = NULL; - musicRw = NULL; - mem_free_dbg(musicBuffer); + SFileCloseFile(sghMusic); + sghMusic = NULL; sgnMusicTrack = NUM_MUSIC; } } @@ -183,17 +184,25 @@ void music_start(int nTrack) if (!success) { sghMusic = NULL; } else { - int bytestoread = SFileGetFileSize(sghMusic, 0); - musicBuffer = (char *)DiabloAllocPtr(bytestoread); - SFileReadFile(sghMusic, musicBuffer, bytestoread, NULL, 0); - - musicRw = SDL_RWFromConstMem(musicBuffer, bytestoread); - if (musicRw == NULL) { - ErrSdl(); + music = Mix_LoadMUSType_RW(SFileRw_FromStormHandle(sghMusic), MUS_NONE, /*freesrc=*/1); + if (music == NULL) { + SDL_Log("Mix_LoadMUSType_RW: %s", Mix_GetError()); + SFileCloseFile(sghMusic); + sghMusic = NULL; + sgnMusicTrack = NUM_MUSIC; + return; } - music = Mix_LoadMUSType_RW(musicRw, MUS_NONE, 1); + Mix_VolumeMusic(MIX_MAX_VOLUME - MIX_MAX_VOLUME * sgOptions.Audio.nMusicVolume / VOLUME_MIN); - Mix_PlayMusic(music, -1); + if (Mix_PlayMusic(music, -1) < 0) { + SDL_Log("Mix_PlayMusic: %s", Mix_GetError()); + Mix_FreeMusic(music); + SFileCloseFile(sghMusic); + sghMusic = NULL; + music = NULL; + sgnMusicTrack = NUM_MUSIC; + return; + } sgnMusicTrack = nTrack; } diff --git a/SourceX/storm_sdl_rw.cpp b/SourceX/storm_sdl_rw.cpp new file mode 100644 index 000000000..686745a22 --- /dev/null +++ b/SourceX/storm_sdl_rw.cpp @@ -0,0 +1,88 @@ +#include "storm_sdl_rw.h" + +#include "all.h" +#include "../3rdParty/Storm/Source/storm.h" +#include "../Source/engine.h" + +namespace dvl { + +static HANDLE SFileRw_GetHandle(struct SDL_RWops *context) +{ + return (HANDLE)context->hidden.unknown.data1; +} + +static void SFileRw_SetHandle(struct SDL_RWops *context, HANDLE handle) +{ + context->hidden.unknown.data1 = handle; +} + +#ifndef USE_SDL1 +static Sint64 SFileRw_size(struct SDL_RWops *context) +{ + DWORD result; + if (!SFileGetFileSize(SFileRw_GetHandle(context), &result)) + return -1; + return result; +} +#endif + +#ifndef USE_SDL1 +static Sint64 SFileRw_seek(struct SDL_RWops *context, Sint64 offset, int whence) +#else +static int SFileRw_seek(struct SDL_RWops *context, int offset, int whence) +#endif +{ + DWORD swhence; + switch (whence) { + case RW_SEEK_SET: + swhence = DVL_FILE_BEGIN; + break; + case RW_SEEK_CUR: + swhence = DVL_FILE_CURRENT; + break; + case RW_SEEK_END: + swhence = DVL_FILE_END; + break; + default: + return -1; + } + return SFileSetFilePointer(SFileRw_GetHandle(context), offset, NULL, swhence); +} + +#ifndef USE_SDL1 +static size_t SFileRw_read(struct SDL_RWops *context, void *ptr, size_t size, size_t maxnum) +#else +static int SFileRw_read(struct SDL_RWops *context, void *ptr, int size, int maxnum) +#endif +{ + DWORD num_read = 0; + SFileReadFile(SFileRw_GetHandle(context), ptr, maxnum * size, &num_read, NULL); + return num_read; +} + +static int SFileRw_close(struct SDL_RWops *context) +{ + mem_free_dbg(context); + return 0; +} + +SDL_RWops *SFileRw_FromStormHandle(HANDLE handle) +{ + SDL_RWops *result = (SDL_RWops *)DiabloAllocPtr(sizeof(SDL_RWops)); + +#ifndef USE_SDL1 + result->size = &SFileRw_size; + result->type = SDL_RWOPS_UNKNOWN; +#else + result->type = 0; +#endif + + result->seek = &SFileRw_seek; + result->read = &SFileRw_read; + result->write = NULL; + result->close = &SFileRw_close; + SFileRw_SetHandle(result, handle); + return result; +} + +} // namespace dvl diff --git a/SourceX/storm_sdl_rw.h b/SourceX/storm_sdl_rw.h new file mode 100644 index 000000000..22e8857f1 --- /dev/null +++ b/SourceX/storm_sdl_rw.h @@ -0,0 +1,16 @@ +#pragma once + +#include + +#include "../SourceS/miniwin/misc.h" + +namespace dvl { + +/** + * @brief Creates a read-only SDL_RWops from a Storm file handle. + * + * Does not close the handle when it gets closed. + */ +SDL_RWops *SFileRw_FromStormHandle(HANDLE handle); + +} // namespace dvl