xaudio2: Use assembly wrapper to call OnVoiceProcessingPassStart callback.

During a callback function, some games use the wrong function
signature for an xaudio2 function, which changed between xaudio2
versions.  As a result, the EDI and ESI registers are overwritten by
the game.  Apparently Windows's implementation happens not to use
these registers in a way that causes the crash.

This patch pushes EDI and ESI onto the stack before calling the
callback, then pops them back after the callback exits.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=42520
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=43358
Signed-off-by: Andrew Eikum <aeikum@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Sebastian Lackner 2018-11-01 10:32:38 -05:00 committed by Alexandre Julliard
parent 82ba4373ae
commit c649ec3a02

View file

@ -17,6 +17,7 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "config.h"
#include <stdarg.h>
#define NONAMELESSUNION
@ -50,6 +51,37 @@ static HINSTANCE instance;
#define COMPAT_E_DEVICE_INVALIDATED XAUDIO2_E_DEVICE_INVALIDATED
#endif
#if XAUDIO2_VER != 0 && defined(__i386__)
/* EVE Online uses an OnVoiceProcessingPassStart callback which corrupts %esi. */
#define IXAudio2VoiceCallback_OnVoiceProcessingPassStart(a, b) call_on_voice_processing_pass_start(a, b)
extern void call_on_voice_processing_pass_start(IXAudio2VoiceCallback *This, UINT32 BytesRequired);
__ASM_GLOBAL_FUNC( call_on_voice_processing_pass_start,
"pushl %ebp\n\t"
__ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
__ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
"movl %esp,%ebp\n\t"
__ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
"pushl %esi\n\t"
__ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
"pushl %edi\n\t"
__ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
"subl $8,%esp\n\t"
"pushl 12(%ebp)\n\t" /* BytesRequired */
"pushl 8(%ebp)\n\t" /* This */
"movl 8(%ebp),%eax\n\t"
"movl 0(%eax),%eax\n\t"
"call *0(%eax)\n\t" /* This->lpVtbl->OnVoiceProcessingPassStart */
"leal -8(%ebp),%esp\n\t"
"popl %edi\n\t"
__ASM_CFI(".cfi_same_value %edi\n\t")
"popl %esi\n\t"
__ASM_CFI(".cfi_same_value %esi\n\t")
"popl %ebp\n\t"
__ASM_CFI(".cfi_def_cfa %esp,4\n\t")
__ASM_CFI(".cfi_same_value %ebp\n\t")
"ret" )
#endif
static void dump_fmt(const WAVEFORMATEX *fmt)
{
TRACE("wFormatTag: 0x%x (", fmt->wFormatTag);