diff --git a/patches/dmime-load-wave/0001-dmime-Store-WAVE-data-when-Loading.patch b/patches/dmime-load-wave/0001-dmime-Store-WAVE-data-when-Loading.patch new file mode 100644 index 00000000..871f8fe3 --- /dev/null +++ b/patches/dmime-load-wave/0001-dmime-Store-WAVE-data-when-Loading.patch @@ -0,0 +1,100 @@ +From 4b20338821a19304650d1acc1229b0e8615896bc Mon Sep 17 00:00:00 2001 +From: Alistair Leslie-Hughes +Date: Wed, 3 Aug 2022 16:25:11 +1000 +Subject: [PATCH] dmime: Store WAVE data when Loading. + +--- + dlls/dmime/segment.c | 56 ++++++++++++++++++++++++++++++++++++++++---- + 1 file changed, 52 insertions(+), 4 deletions(-) + +diff --git a/dlls/dmime/segment.c b/dlls/dmime/segment.c +index bf44c5e73b3..6bf9f3abf0c 100644 +--- a/dlls/dmime/segment.c ++++ b/dlls/dmime/segment.c +@@ -33,6 +33,10 @@ typedef struct IDirectMusicSegment8Impl { + DMUS_IO_SEGMENT_HEADER header; + IDirectMusicGraph *pGraph; + struct list Tracks; ++ ++ PCMWAVEFORMAT wave_format; ++ void *wave_data; ++ int data_size; + } IDirectMusicSegment8Impl; + + IDirectMusicSegment8Impl *create_segment(void); +@@ -86,6 +90,9 @@ static ULONG WINAPI IDirectMusicSegment8Impl_Release(IDirectMusicSegment8 *iface + TRACE("(%p) ref=%ld\n", This, ref); + + if (!ref) { ++ if (This->wave_data) ++ free(This->wave_data); ++ + HeapFree(GetProcessHeap(), 0, This); + DMIME_UnlockModule(); + } +@@ -818,6 +825,49 @@ static inline IDirectMusicSegment8Impl *impl_from_IPersistStream(IPersistStream + return CONTAINING_RECORD(iface, IDirectMusicSegment8Impl, dmobj.IPersistStream_iface); + } + ++static HRESULT parse_wave_form(IDirectMusicSegment8Impl *This, IStream *stream, const struct chunk_entry *riff) ++{ ++ HRESULT hr; ++ struct chunk_entry chunk = {.parent = riff}; ++ ++ TRACE("Parsing segment wave in %p: %s\n", stream, debugstr_chunk(riff)); ++ ++ while ((hr = stream_next_chunk(stream, &chunk)) == S_OK) { ++ switch (chunk.id) { ++ case mmioFOURCC('f','m','t',' '): { ++ if (FAILED(hr = stream_chunk_get_data(stream, &chunk, &This->wave_format, chunk.size))) ++ return hr; ++ TRACE("Wave Format tag %d\n", This->wave_format.wf.wFormatTag); ++ break; ++ } ++ case mmioFOURCC('d','a','t','a'): { ++ TRACE("Wave Data size %lu\n", chunk.size); ++ This->wave_data = malloc(chunk.size); ++ This->data_size = chunk.size; ++ if (!This->wave_data) ++ return E_OUTOFMEMORY; ++ if (FAILED(hr = stream_chunk_get_data(stream, &chunk, This->wave_data, chunk.size))) ++ return hr; ++ break; ++ } ++ case FOURCC_LIST: { ++ FIXME("Skipping LIST tag\n"); ++ break; ++ } ++ case mmioFOURCC('I','S','F','T'): { ++ FIXME("Skipping ISFT tag\n"); ++ break; ++ } ++ case mmioFOURCC('f','a','c','t'): { ++ FIXME("Skipping fact tag\n"); ++ break; ++ } ++ } ++ } ++ ++ return S_OK; ++} ++ + static HRESULT WINAPI seg_IPersistStream_Load(IPersistStream *iface, IStream *stream) + { + IDirectMusicSegment8Impl *This = impl_from_IPersistStream(iface); +@@ -847,10 +897,8 @@ static HRESULT WINAPI seg_IPersistStream_Load(IPersistStream *iface, IStream *st + + if (riff.type == DMUS_FOURCC_SEGMENT_FORM) + hr = parse_segment_form(This, stream, &riff); +- else { +- FIXME("WAVE form loading not implemented\n"); +- hr = S_OK; +- } ++ else ++ hr = parse_wave_form(This, stream, &riff); + + return hr; + } +-- +2.39.1 + diff --git a/patches/dmime-load-wave/0002-dmime-Implement-IDirectMusicSegment8-Download.patch b/patches/dmime-load-wave/0002-dmime-Implement-IDirectMusicSegment8-Download.patch new file mode 100644 index 00000000..209c1daf --- /dev/null +++ b/patches/dmime-load-wave/0002-dmime-Implement-IDirectMusicSegment8-Download.patch @@ -0,0 +1,157 @@ +From f58dbcdfedf4d5d78d586d54f507c647e58379c8 Mon Sep 17 00:00:00 2001 +From: Alistair Leslie-Hughes +Date: Fri, 2 Dec 2022 14:41:30 +1100 +Subject: [PATCH] dmime: Implement IDirectMusicSegment8 Download + +--- + dlls/dmime/dmime_private.h | 2 + + dlls/dmime/performance.c | 7 +++ + dlls/dmime/segment.c | 87 ++++++++++++++++++++++++++++++++++++-- + 3 files changed, 93 insertions(+), 3 deletions(-) + +diff --git a/dlls/dmime/dmime_private.h b/dlls/dmime/dmime_private.h +index 4159abffa99..030aab50094 100644 +--- a/dlls/dmime/dmime_private.h ++++ b/dlls/dmime/dmime_private.h +@@ -71,6 +71,8 @@ extern void set_audiopath_perf_pointer(IDirectMusicAudioPath*,IDirectMusicPerfor + extern void set_audiopath_dsound_buffer(IDirectMusicAudioPath*,IDirectSoundBuffer*) DECLSPEC_HIDDEN; + extern void set_audiopath_primary_dsound_buffer(IDirectMusicAudioPath*,IDirectSoundBuffer*) DECLSPEC_HIDDEN; + ++extern IDirectSound *get_dsound_interface(IDirectMusicPerformance8*) DECLSPEC_HIDDEN; ++ + /***************************************************************************** + * Auxiliary definitions + */ +diff --git a/dlls/dmime/performance.c b/dlls/dmime/performance.c +index d69a27540d6..5578c3e523b 100644 +--- a/dlls/dmime/performance.c ++++ b/dlls/dmime/performance.c +@@ -252,6 +252,13 @@ static inline IDirectMusicPerformance8Impl *impl_from_IDirectMusicPerformance8(I + return CONTAINING_RECORD(iface, IDirectMusicPerformance8Impl, IDirectMusicPerformance8_iface); + } + ++IDirectSound *get_dsound_interface(IDirectMusicPerformance8* iface) ++{ ++ IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface); ++ return This->dsound; ++} ++ ++ + /* IDirectMusicPerformance8 IUnknown part: */ + static HRESULT WINAPI IDirectMusicPerformance8Impl_QueryInterface(IDirectMusicPerformance8 *iface, + REFIID riid, void **ppv) +diff --git a/dlls/dmime/segment.c b/dlls/dmime/segment.c +index 6bf9f3abf0c..0ea0c15c5e0 100644 +--- a/dlls/dmime/segment.c ++++ b/dlls/dmime/segment.c +@@ -37,6 +37,7 @@ typedef struct IDirectMusicSegment8Impl { + PCMWAVEFORMAT wave_format; + void *wave_data; + int data_size; ++ IDirectSoundBuffer *buffer; + } IDirectMusicSegment8Impl; + + IDirectMusicSegment8Impl *create_segment(void); +@@ -90,6 +91,8 @@ static ULONG WINAPI IDirectMusicSegment8Impl_Release(IDirectMusicSegment8 *iface + TRACE("(%p) ref=%ld\n", This, ref); + + if (!ref) { ++ if (This->buffer) ++ IDirectSoundBuffer_Release(This->buffer); + if (This->wave_data) + free(This->wave_data); + +@@ -559,9 +562,87 @@ static HRESULT WINAPI IDirectMusicSegment8Impl_Compose(IDirectMusicSegment8 *ifa + static HRESULT WINAPI IDirectMusicSegment8Impl_Download(IDirectMusicSegment8 *iface, + IUnknown *pAudioPath) + { +- IDirectMusicSegment8Impl *This = impl_from_IDirectMusicSegment8(iface); +- FIXME("(%p, %p): stub\n", This, pAudioPath); +- return S_OK; ++ IDirectMusicSegment8Impl *This = impl_from_IDirectMusicSegment8(iface); ++ IDirectMusicPerformance8 *perf; ++ IDirectMusicAudioPath *audio; ++ IDirectSound *dsound; ++ HRESULT hr; ++ DSBUFFERDESC dsbd = {.dwSize = sizeof(dsbd)}; ++ void *data; ++ DWORD size; ++ DWORD buffer = 0; ++ ++ TRACE("(%p, %p)\n", This, pAudioPath); ++ ++ if (!pAudioPath) ++ return E_INVALIDARG; ++ ++ if (This->buffer) ++ { ++ TRACE("Using Cached buffer\n"); ++ return S_OK; ++ } ++ ++ /* pAudioPath can either be IDirectMusicAudioPath or IDirectMusicPerformance */ ++ hr = IUnknown_QueryInterface(pAudioPath, &IID_IDirectMusicPerformance8, (void**)&perf); ++ if (FAILED(hr)) ++ { ++ TRACE("Checking for IDirectMusicAudioPath interface\n"); ++ hr = IUnknown_QueryInterface(pAudioPath, &IID_IDirectMusicAudioPath, (void**)&audio); ++ if (FAILED(hr)) ++ { ++ WARN("Cannot query for IDirectMusicAudioPath\n"); ++ return E_INVALIDARG; ++ } ++ ++ IDirectMusicAudioPath_GetObjectInPath(audio, DMUS_PCHANNEL_ALL, DMUS_PATH_PERFORMANCE, buffer, &GUID_NULL, ++ 0, &IID_IDirectMusicPerformance, (void**)&perf); ++ IDirectMusicAudioPath_Release(audio); ++ } ++ ++ if (!perf) ++ { ++ ERR("Failed to get IDirectMusicPerformance interface\n"); ++ return E_INVALIDARG; ++ } ++ ++ dsound = get_dsound_interface(perf); ++ if (!dsound) ++ { ++ ERR("Failed get_dsound_interface\n"); ++ return E_INVALIDARG; ++ } ++ ++ if (This->data_size == 0) ++ { ++ FIXME("No wave data skipping\n"); ++ return S_OK; ++ } ++ ++ dsbd.dwBufferBytes = This->data_size; ++ dsbd.lpwfxFormat = (WAVEFORMATEX*)&This->wave_format; ++ ++ hr = IDirectSound_CreateSoundBuffer(dsound, &dsbd, &This->buffer, NULL); ++ if (FAILED(hr)) ++ { ++ ERR("IDirectSound_CreateSoundBuffer failed 0x%08lx\n", hr); ++ return E_INVALIDARG; ++ } ++ ++ TRACE("CreateSoundBuffer successful\n"); ++ ++ hr = IDirectSoundBuffer_Lock(This->buffer, 0, This->data_size, &data, &size, NULL, 0, 0); ++ TRACE("IDirectSoundBuffer_Lock hr 0x%08lx\n", hr); ++ ++ memcpy(data, This->wave_data, This->data_size); ++ ++ hr = IDirectSoundBuffer_Unlock(This->buffer, data, This->data_size, NULL, 0); ++ TRACE("IDirectSoundBuffer_Unlock hr 0x%08lx\n", hr); ++ ++ /*hr = IDirectSoundBuffer_Play(This->buffer, 0, 0, 0); ++ TRACE("IDirectSoundBuffer_Play hr 0x%08lx\n", hr);*/ ++ ++ return S_OK; + } + + static HRESULT WINAPI IDirectMusicSegment8Impl_Unload(IDirectMusicSegment8 *iface, +-- +2.39.1 + diff --git a/patches/dmime-load-wave/0003-dmime-Play-a-sound-in-IDirectMusicPerformance8-PlayS.patch b/patches/dmime-load-wave/0003-dmime-Play-a-sound-in-IDirectMusicPerformance8-PlayS.patch new file mode 100644 index 00000000..412ca481 --- /dev/null +++ b/patches/dmime-load-wave/0003-dmime-Play-a-sound-in-IDirectMusicPerformance8-PlayS.patch @@ -0,0 +1,81 @@ +From 8ef2197cd4c77bf562ab5b83f2a137ae565bc22d Mon Sep 17 00:00:00 2001 +From: Alistair Leslie-Hughes +Date: Mon, 12 Dec 2022 15:20:10 +1100 +Subject: [PATCH 3/3] dmime: Play a sound in IDirectMusicPerformance8 + PlaySegmentEx + +--- + dlls/dmime/dmime_private.h | 1 + + dlls/dmime/performance.c | 25 +++++++++++++++++++------ + dlls/dmime/segment.c | 6 ++++++ + 3 files changed, 26 insertions(+), 6 deletions(-) + +diff --git a/dlls/dmime/dmime_private.h b/dlls/dmime/dmime_private.h +index 030aab50094..d09aba02a5c 100644 +--- a/dlls/dmime/dmime_private.h ++++ b/dlls/dmime/dmime_private.h +@@ -72,6 +72,7 @@ extern void set_audiopath_dsound_buffer(IDirectMusicAudioPath*,IDirectSoundBuffe + extern void set_audiopath_primary_dsound_buffer(IDirectMusicAudioPath*,IDirectSoundBuffer*) DECLSPEC_HIDDEN; + + extern IDirectSound *get_dsound_interface(IDirectMusicPerformance8*) DECLSPEC_HIDDEN; ++extern IDirectSoundBuffer *get_segment_buffer(IDirectMusicSegment8 *iface) DECLSPEC_HIDDEN; + + /***************************************************************************** + * Auxiliary definitions +diff --git a/dlls/dmime/performance.c b/dlls/dmime/performance.c +index 5578c3e523b..03e59e95af3 100644 +--- a/dlls/dmime/performance.c ++++ b/dlls/dmime/performance.c +@@ -1043,13 +1043,26 @@ static HRESULT WINAPI IDirectMusicPerformance8Impl_PlaySegmentEx(IDirectMusicPer + __int64 i64StartTime, IDirectMusicSegmentState **ppSegmentState, IUnknown *pFrom, + IUnknown *pAudioPath) + { +- IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface); ++ IDirectMusicPerformance8Impl *This = impl_from_IDirectMusicPerformance8(iface); ++ IDirectMusicSegment8 *segment; ++ IDirectSoundBuffer *buffer; ++ HRESULT hr; + +- FIXME("(%p, %p, %p, %p, %ld, 0x%s, %p, %p, %p): stub\n", This, pSource, pwzSegmentName, +- pTransition, dwFlags, wine_dbgstr_longlong(i64StartTime), ppSegmentState, pFrom, pAudioPath); +- if (ppSegmentState) +- return create_dmsegmentstate(&IID_IDirectMusicSegmentState,(void**)ppSegmentState); +- return S_OK; ++ FIXME("(%p, %p, %p, %p, %ld, 0x%s, %p, %p, %p): semi-stub\n", This, pSource, pwzSegmentName, ++ pTransition, dwFlags, wine_dbgstr_longlong(i64StartTime), ppSegmentState, pFrom, pAudioPath); ++ ++ hr = IUnknown_QueryInterface(pSource, &IID_IDirectMusicSegment8, (void**)&segment); ++ if (FAILED(hr)) ++ return hr; ++ ++ buffer = get_segment_buffer(segment); ++ ++ if (segment) ++ hr = IDirectSoundBuffer_Play(buffer, 0, 0, 0); ++ ++ if (ppSegmentState) ++ return create_dmsegmentstate(&IID_IDirectMusicSegmentState,(void**)ppSegmentState); ++ return S_OK; + } + + static HRESULT WINAPI IDirectMusicPerformance8Impl_StopEx(IDirectMusicPerformance8 *iface, +diff --git a/dlls/dmime/segment.c b/dlls/dmime/segment.c +index dbf2f8203d8..9213fbf4a4c 100644 +--- a/dlls/dmime/segment.c ++++ b/dlls/dmime/segment.c +@@ -45,6 +45,12 @@ static inline IDirectMusicSegment8Impl *impl_from_IDirectMusicSegment8(IDirectMu + return CONTAINING_RECORD(iface, IDirectMusicSegment8Impl, IDirectMusicSegment8_iface); + } + ++IDirectSoundBuffer *get_segment_buffer(IDirectMusicSegment8 *iface) ++{ ++ IDirectMusicSegment8Impl *This = impl_from_IDirectMusicSegment8(iface); ++ return This->buffer; ++} ++ + static HRESULT WINAPI IDirectMusicSegment8Impl_QueryInterface(IDirectMusicSegment8 *iface, + REFIID riid, void **ret_iface) + { +-- +2.38.1 + diff --git a/patches/dmime-load-wave/definition b/patches/dmime-load-wave/definition new file mode 100644 index 00000000..385cd41d --- /dev/null +++ b/patches/dmime-load-wave/definition @@ -0,0 +1,13 @@ +Fixes: [48220] dmime: Handle basic loading of Wave files and playing them. +Fixes: [61322] dmine: No Sound in Black Rockman Shooter. +Fixes: [34751] dmime: Aura: Fate of the Ages: sounds aren't played, but music works fine +Fixes: [9027] dmime: No sound for rise of nations - all versions. + +# Also +# - Cloning Clyde demo + +# Doesnt fix +# The following are known not to work, at the moment. +# [31586] : Myst sounds (Voices) +# [30969] : Tron 2.0 Background music +# [32896] : Serious Sam: The Random Encounter diff --git a/patches/patchinstall.sh b/patches/patchinstall.sh index 312313a7..ce5642d3 100755 --- a/patches/patchinstall.sh +++ b/patches/patchinstall.sh @@ -105,6 +105,7 @@ patch_enable_all () enable_ddraw_IDirect3DTexture2_Load="$1" enable_ddraw_Silence_FIXMEs="$1" enable_dinput_joy_mappings="$1" + enable_dmime_load_wave="$1" enable_dsound_EAX="$1" enable_dsound_Fast_Mixer="$1" enable_eventfd_synchronization="$1" @@ -327,6 +328,9 @@ patch_enable () dinput-joy-mappings) enable_dinput_joy_mappings="$2" ;; + dmime-load-wave) + enable_dmime_load_wave="$2" + ;; dsound-EAX) enable_dsound_EAX="$2" ;; @@ -1554,6 +1558,23 @@ if test "$enable_dinput_joy_mappings" -eq 1; then patch_apply dinput-joy-mappings/0004-dinput-Allow-mapping-of-controls-based-of-Genre-type.patch fi +# Patchset dmime-load-wave +# | +# | This patchset fixes the following Wine bugs: +# | * [#48220] dmime: Handle basic loading of Wave files and playing them. +# | * [#61322] dmine: No Sound in Black Rockman Shooter. +# | * [#34751] dmime: Aura: Fate of the Ages: sounds aren't played, but music works fine +# | * [#9027] dmime: No sound for rise of nations - all versions. +# | +# | Modified files: +# | * dlls/dmime/dmime_private.h, dlls/dmime/performance.c, dlls/dmime/segment.c +# | +if test "$enable_dmime_load_wave" -eq 1; then + patch_apply dmime-load-wave/0001-dmime-Store-WAVE-data-when-Loading.patch + patch_apply dmime-load-wave/0002-dmime-Implement-IDirectMusicSegment8-Download.patch + patch_apply dmime-load-wave/0003-dmime-Play-a-sound-in-IDirectMusicPerformance8-PlayS.patch +fi + # Patchset dsound-Fast_Mixer # | # | This patchset fixes the following Wine bugs: @@ -3202,7 +3223,7 @@ fi # Patchset wined3d-atomic_minmax_merge # | # | This patchset fixes the following Wine bugs: -# | * [#52233] wined3d: Handle u/signed integers that same +# | * [#52233] wined3d: Handle u/signed integers the same # | # | Modified files: # | * dlls/wined3d/glsl_shader.c