From 08ab2cdfe87b1dc8e182b9c137aa9163129cbf0c Mon Sep 17 00:00:00 2001 From: zsilencer Date: Tue, 26 Aug 2014 16:34:34 -0600 Subject: [PATCH 1/3] some directsound decompilation --- projects/openrct2.vcxproj | 4 +- src/addresses.h | 3 + src/audio.c | 282 +++++++++++++++++++++++++++++++++++--- src/audio.h | 17 ++- src/rct2.c | 2 +- src/title.c | 3 +- 6 files changed, 283 insertions(+), 28 deletions(-) diff --git a/projects/openrct2.vcxproj b/projects/openrct2.vcxproj index 9c079203b5..3077811de3 100644 --- a/projects/openrct2.vcxproj +++ b/projects/openrct2.vcxproj @@ -201,7 +201,7 @@ true - winmm.lib;sdl2.lib;%(AdditionalDependencies) + winmm.lib;sdl2.lib;Dsound.lib;%(AdditionalDependencies) @@ -224,7 +224,7 @@ true true true - winmm.lib;sdl2.lib;%(AdditionalDependencies) + winmm.lib;sdl2.lib;Dsound.lib;%(AdditionalDependencies) xcopy /Y "$(ProjectDir)\..\Data\Language\*.*" "$(TargetDir)\Data\Language\" diff --git a/src/addresses.h b/src/addresses.h index 700ad084be..d6b95d7426 100644 --- a/src/addresses.h +++ b/src/addresses.h @@ -165,6 +165,7 @@ #define RCT2_ADDRESS_SOUNDLIST_BEGIN 0x009E2B98 #define RCT2_ADDRESS_SOUNDLIST_END 0x009E2B9C #define RCT2_ADDRESS_DIRECTSOUND 0x009E2BA0 +#define RCT2_ADDRESS_DSOUND_DEVICES_COUNTER 0x009E2BAC #define RCT2_ADDRESS_CMDLINE 0x009E2D98 @@ -316,6 +317,8 @@ #define RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER 0x0141ED68 +#define RCT2_ADDRESS_AUDIO_INFO 0x01425B40 + #define RCT2_ADDRESS_SOUND_CHANNEL_LIST 0x014262E0 #define RCT2_ADDRESS_WATER_RAISE_COST 0x0141F738 diff --git a/src/audio.c b/src/audio.c index 4bfbf81863..ecc2ddb50d 100644 --- a/src/audio.c +++ b/src/audio.c @@ -66,16 +66,79 @@ void audio_get_devices() } } +/** +* +* rct2: 0x00404BD2 +*/ +int sound_release() +{ + sound_stop_all(); + if (RCT2_GLOBAL(0x009E2BA4, LPDIRECTSOUND3DBUFFER)) { + RCT2_GLOBAL(0x009E2BA4, LPDIRECTSOUND3DBUFFER)->lpVtbl->Release(RCT2_GLOBAL(0x009E2BA4, LPDIRECTSOUND3DBUFFER)); + RCT2_GLOBAL(0x009E2BA4, LPDIRECTSOUND3DBUFFER) = 0; + } + if (RCT2_GLOBAL(0x009E2BA8, LPDIRECTSOUNDBUFFER)) { + RCT2_GLOBAL(0x009E2BA8, LPDIRECTSOUNDBUFFER)->lpVtbl->Release(RCT2_GLOBAL(0x009E2BA8, LPDIRECTSOUNDBUFFER)); + RCT2_GLOBAL(0x009E2BA8, LPDIRECTSOUNDBUFFER) = 0; + } + int result = 0; + if (RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND)) { + result = RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND)->lpVtbl->Release(RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND)); + RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND) = 0; + } + return result; +} + +/** +* +* rct2: 0x00404C45 +*/ +int sound_unmap_info() +{ + if (RCT2_GLOBAL(RCT2_ADDRESS_SOUND_INFO_LIST_OFFSET, int)) { + sound_stop_all(); + sound_unmap_file(RCT2_GLOBAL(RCT2_ADDRESS_SOUND_INFO_LIST_OFFSET, LPCVOID)); + RCT2_GLOBAL(RCT2_ADDRESS_SOUND_INFO_LIST_OFFSET, int) = 0; + return 1; + } + return 0; +} + +/** +* +* rct2: 0x00404DF5 +*/ +int sound_stop_all() +{ + int result = 0; + while (RCT2_GLOBAL(RCT2_ADDRESS_SOUNDLIST_BEGIN, rct_sound*)) { + result = sound_stop(RCT2_GLOBAL(RCT2_ADDRESS_SOUNDLIST_BEGIN, rct_sound*)); + } + return result; +} + +/** +* +* rct2: 0x004068A0 +*/ +int sound_unmap_file(LPCVOID base) +{ + if (base) { + return UnmapViewOfFile(base); + } + return 0; +} + /** * * rct2: 0x006BAB21 */ -void sub_6BAB21(void) +void sub_6BAB21() { if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SOUND_DEVICE, uint32) != -1) { stop_other_sounds(); stop_peep_sounds(); - RCT2_CALLPROC_EBPSAFE(0x006BD0BD); + stop_title_music(); if (RCT2_GLOBAL(0x009AF284, uint32) & (1 << 0)) { stop_ride_music(); RCT2_GLOBAL(0x014241BC, uint32) = 1; @@ -83,13 +146,125 @@ void sub_6BAB21(void) RCT2_GLOBAL(0x014241BC, uint32) = 0; } RCT2_GLOBAL(0x014241BC, uint32) = 1; - RCT2_CALLPROC(0x00404C45); - RCT2_CALLPROC(0x00404BD2); + sound_unmap_info(); + sound_release(); RCT2_GLOBAL(0x014241BC, uint32) = 0; RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SOUND_DEVICE, uint32) = -1; } } +/** +* +* rct2: 0x000404F28 +*/ +int sound_load3dparameters() +{ + if (SUCCEEDED(RCT2_GLOBAL(0x009E2BA4, LPDIRECTSOUND3DBUFFER)->lpVtbl->GetAllParameters(RCT2_GLOBAL(0x009E2BA4, LPDIRECTSOUND3DBUFFER), &RCT2_GLOBAL(0x009A6084, DS3DBUFFER)))) { + return 1; + } + return 0; +} + +/** +* +* rct2: 0x00404932 +*/ +int dsound_create_primary_buffer(int a, int device, int channels, int samples, int bits) +{ + rct_dsdevice* dsdevice = 0; + if (device) { + if (device > RCT2_GLOBAL(RCT2_ADDRESS_NUM_DSOUND_DEVICES, int)) { + return 0; + } + dsdevice = &RCT2_GLOBAL(RCT2_ADDRESS_DSOUND_DEVICES, rct_dsdevice*)[device]; + } + memset(&RCT2_GLOBAL(RCT2_ADDRESS_AUDIO_INFO, rct_audio_info), 0, sizeof(rct_audio_info)); + RCT2_GLOBAL(RCT2_ADDRESS_AUDIO_INFO, rct_audio_info).var_0 = 1; + RCT2_GLOBAL(RCT2_ADDRESS_AUDIO_INFO, rct_audio_info).channels = channels; + RCT2_GLOBAL(RCT2_ADDRESS_AUDIO_INFO, rct_audio_info).samples = samples; + RCT2_GLOBAL(RCT2_ADDRESS_AUDIO_INFO, rct_audio_info).var_8 = samples * RCT2_GLOBAL(0x01425B4C, uint16); + RCT2_GLOBAL(RCT2_ADDRESS_AUDIO_INFO, rct_audio_info).bytes = bits * channels / 8; + RCT2_GLOBAL(RCT2_ADDRESS_AUDIO_INFO, rct_audio_info).bits = bits; + RCT2_GLOBAL(RCT2_ADDRESS_AUDIO_INFO, rct_audio_info).var_E = 0; + DSBUFFERDESC bufferdesc; + memset(&bufferdesc, 0, sizeof(bufferdesc)); + bufferdesc.dwSize = sizeof(bufferdesc); + if (a) { + if (a != 1) { + return 0; + } + bufferdesc.dwFlags = DSBCAPS_CTRL3D | DSBCAPS_PRIMARYBUFFER; + if (RCT2_GLOBAL(0x009E2B90, uint32)) { + bufferdesc.dwFlags = DSBCAPS_STICKYFOCUS | DSBCAPS_CTRL3D | DSBCAPS_PRIMARYBUFFER; + } + if (FAILED(DirectSoundCreate(&dsdevice->guid, &RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND), 0))) { + return 0; + } + if (FAILED(RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND)->lpVtbl->SetCooperativeLevel(RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND), RCT2_GLOBAL(0x009E2D70, HWND), DSSCL_NORMAL)) || + FAILED(RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND)->lpVtbl->CreateSoundBuffer(RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND), &bufferdesc, &RCT2_GLOBAL(0x009E2BA8, LPDIRECTSOUNDBUFFER), 0))) { + RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND)->lpVtbl->Release(RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND)); + RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND) = 0; + return 0; + } + if (SUCCEEDED(RCT2_GLOBAL(0x009E2BA8, LPDIRECTSOUNDBUFFER)->lpVtbl->QueryInterface(RCT2_GLOBAL(0x009E2BA8, LPDIRECTSOUNDBUFFER), &RCT2_GLOBAL(0x009A4444, IID) /* IID_IDirectSound3DBuffer */, &RCT2_GLOBAL(0x009E2BA4, LPDIRECTSOUND3DBUFFER)))) { + // doesn't seem to ever make it here, below doesn't make sense and is probably remnants of unused 3d sound tests + memset(&RCT2_GLOBAL(0x009A6084, DS3DBUFFER), 0, sizeof(RCT2_GLOBAL(0x009A6084, DS3DBUFFER))); + RCT2_GLOBAL(0x009A6084, DS3DBUFFER).dwSize = sizeof(RCT2_GLOBAL(0x009A6084, DS3DBUFFER)); + + if (sound_load3dparameters()) { + RCT2_GLOBAL(0x009A6084, DS3DBUFFER).vPosition.x = 0.0f; + } + RCT2_GLOBAL(0x009A6084, DS3DBUFFER).vPosition.y = 0.0f; + RCT2_GLOBAL(0x009A6084, DS3DBUFFER).vPosition.x = -1.0f; + RCT2_GLOBAL(0x009A6084, DS3DBUFFER).flMaxDistance = 9.8999996f; + RCT2_GLOBAL(0x009A6084, DS3DBUFFER).flMinDistance = 0.25f; + if (RCT2_CALLFUNC(0x00404F3F, int)) { + if (SUCCEEDED(RCT2_GLOBAL(0x009E2BA4, LPDIRECTSOUND3DBUFFER)->lpVtbl->SetMinDistance(RCT2_GLOBAL(0x009E2BA4, LPDIRECTSOUND3DBUFFER), RCT2_GLOBAL(0x009A6084, DS3DBUFFER).flMinDistance, 1))) { + if (sound_load3dparameters()) { + return 1; + } + } + } + RCT2_GLOBAL(0x009E2BA4, LPDIRECTSOUND3DBUFFER)->lpVtbl->Release(RCT2_GLOBAL(0x009E2BA4, LPDIRECTSOUND3DBUFFER)); + RCT2_GLOBAL(0x009E2BA4, LPDIRECTSOUND3DBUFFER) = 0; + RCT2_GLOBAL(0x009E2BA8, LPDIRECTSOUNDBUFFER)->lpVtbl->Release(RCT2_GLOBAL(0x009E2BA8, LPDIRECTSOUNDBUFFER)); + RCT2_GLOBAL(0x009E2BA8, LPDIRECTSOUNDBUFFER) = 0; + RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND)->lpVtbl->Release(RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND)); + RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND) = 0; + } else { + RCT2_GLOBAL(0x009E2BA8, LPDIRECTSOUNDBUFFER)->lpVtbl->Release(RCT2_GLOBAL(0x009E2BA8, LPDIRECTSOUNDBUFFER)); + RCT2_GLOBAL(0x009E2BA8, LPDIRECTSOUNDBUFFER) = 0; + RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND)->lpVtbl->Release(RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND)); + RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND) = 0; + } + } + bufferdesc.dwFlags = DSBCAPS_PRIMARYBUFFER; + if (RCT2_GLOBAL(0x009E2B90, uint32)) { + bufferdesc.dwFlags = DSBCAPS_STICKYFOCUS | DSBCAPS_PRIMARYBUFFER; + } + if (FAILED(DirectSoundCreate(&dsdevice->guid, &RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND), 0))) { + return 0; + } + if (FAILED(RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND)->lpVtbl->SetCooperativeLevel(RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND), RCT2_GLOBAL(0x009E2D70, HWND), DSSCL_PRIORITY))) { + RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND)->lpVtbl->Release(RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND)); + RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND) = 0; + return 0; + } + RCT2_GLOBAL(0x01425B60, DSCAPS).dwSize = sizeof(DSCAPS); + RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND)->lpVtbl->GetCaps(RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND), &RCT2_GLOBAL(0x01425B60, DSCAPS)); + if (FAILED(RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND)->lpVtbl->CreateSoundBuffer(RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND), &bufferdesc, &RCT2_GLOBAL(0x009E2BA8, LPDIRECTSOUNDBUFFER), 0))) { + RCT2_GLOBAL(0x009E2BA8, LPDIRECTSOUNDBUFFER)->lpVtbl->Release(RCT2_GLOBAL(0x009E2BA8, LPDIRECTSOUNDBUFFER)); + RCT2_GLOBAL(0x009E2BA8, LPDIRECTSOUNDBUFFER) = 0; + RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND)->lpVtbl->Release(RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND)); + RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND) = 0; + } + WAVEFORMATEX waveformat1, waveformat2; + RCT2_GLOBAL(0x009E2BA8, LPDIRECTSOUNDBUFFER)->lpVtbl->GetFormat(RCT2_GLOBAL(0x009E2BA8, LPDIRECTSOUNDBUFFER), &waveformat1, sizeof(WAVEFORMATEX), 0); + RCT2_GLOBAL(0x009E2BA8, LPDIRECTSOUNDBUFFER)->lpVtbl->SetFormat(RCT2_GLOBAL(0x009E2BA8, LPDIRECTSOUNDBUFFER), &RCT2_GLOBAL(0x01425B40, WAVEFORMATEX)); + RCT2_GLOBAL(0x009E2BA8, LPDIRECTSOUNDBUFFER)->lpVtbl->GetFormat(RCT2_GLOBAL(0x009E2BA8, LPDIRECTSOUNDBUFFER), &waveformat2, sizeof(WAVEFORMATEX), 0); + return 1; +} + /** * * rct2: 0x006BA9B5 @@ -106,7 +281,8 @@ void audio_init2(int device) other_sound->id = 0xFFFF; } RCT2_GLOBAL(0x014241BC, uint32) = 1; - int v5 = RCT2_CALLFUNC_5(0x00404932, int, int, int, int, int, int, 0, device, 2, 22050, 16); + int v5 = dsound_create_primary_buffer(0, device, 2, 22050, 16); + //int v5 = RCT2_CALLFUNC_5(0x00404932, int, int, int, int, int, int, 0, device, 2, 22050, 16); RCT2_GLOBAL(0x014241BC, uint32) = 0; if (!v5) { return; @@ -117,16 +293,16 @@ void audio_init2(int device) RCT2_GLOBAL(0x014241BC, uint32) = 0; if (!v8) { RCT2_GLOBAL(0x014241BC, uint32) = 1; - RCT2_CALLPROC(0x00404BD2); + sound_release(); RCT2_GLOBAL(0x014241BC, uint32) = 0; return; } RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SOUND_DEVICE, uint32) = device; - int* data = RCT2_ADDRESS(RCT2_ADDRESS_DSOUND_DEVICES + (0x210 * device), int); - RCT2_GLOBAL(0x009AAC5D, uint32) = data[0]; - RCT2_GLOBAL(0x009AAC61, uint32) = data[1]; - RCT2_GLOBAL(0x009AAC65, uint32) = data[2]; - RCT2_GLOBAL(0x009AAC69, uint32) = data[3]; + rct_dsdevice dsdevice = RCT2_GLOBAL(RCT2_ADDRESS_DSOUND_DEVICES, rct_dsdevice*)[device]; + RCT2_GLOBAL(0x009AAC5D, uint32) = dsdevice.guid.Data1; + RCT2_GLOBAL(0x009AAC61, uint32) = dsdevice.guid.Data2; + RCT2_GLOBAL(0x009AAC65, uint32) = dsdevice.guid.Data3; + RCT2_GLOBAL(0x009AAC69, uint32) = (uint32)dsdevice.guid.Data4; RCT2_GLOBAL(0x009AAC5C, uint8) = 1; config_save(); RCT2_GLOBAL(0x014241BC, uint32) = 1; @@ -146,13 +322,60 @@ void audio_init2(int device) } } +/** +* +* rct2: 0x00404F85 +*/ +BOOL CALLBACK dsound_enum_callback_count(LPGUID lpGuid, LPCSTR lpcstrDescription, LPCSTR lpcstrModule, LPVOID lpContext) +{ + RCT2_GLOBAL(RCT2_ADDRESS_DSOUND_DEVICES_COUNTER, int)++; + return 1; +} + +/** +* +* rct2: 0x00404F91 +*/ +int dsound_count_devices() +{ + RCT2_GLOBAL(RCT2_ADDRESS_DSOUND_DEVICES_COUNTER, int) = 0; + if (SUCCEEDED(DirectSoundEnumerate(dsound_enum_callback_count, 0))) { + return RCT2_GLOBAL(RCT2_ADDRESS_DSOUND_DEVICES_COUNTER, int); + } + return 0; +} + +/** +* +* rct2: 0x00404FB1 +*/ +BOOL CALLBACK dsound_enum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription, LPCSTR lpcstrModule, LPVOID lpContext) +{ + if (lpGuid) { + memcpy(&RCT2_GLOBAL(RCT2_ADDRESS_DSOUND_DEVICES, rct_dsdevice*)[RCT2_GLOBAL(0x01425B54, int)].guid, lpGuid, sizeof(GUID)); + } else { + memset(&RCT2_GLOBAL(RCT2_ADDRESS_DSOUND_DEVICES, rct_dsdevice*)[RCT2_GLOBAL(0x01425B54, int)].guid, 0, sizeof(GUID)); + } + strcpy(RCT2_GLOBAL(RCT2_ADDRESS_DSOUND_DEVICES, rct_dsdevice*)[RCT2_GLOBAL(0x01425B54, int)].desc, lpcstrDescription); + strcpy(RCT2_GLOBAL(RCT2_ADDRESS_DSOUND_DEVICES, rct_dsdevice*)[RCT2_GLOBAL(0x01425B54, int)].drvname, lpcstrModule); + RCT2_GLOBAL(0x01425B54, int)++; + return 1; +} + /** * * rct2: 0x0040502E */ -void get_dsound_devices() +int get_dsound_devices() { - RCT2_CALLPROC(0x0040502E); + RCT2_GLOBAL(RCT2_ADDRESS_NUM_DSOUND_DEVICES, uint32) = dsound_count_devices(); + RCT2_GLOBAL(RCT2_ADDRESS_DSOUND_DEVICES, rct_dsdevice*) = malloc(RCT2_GLOBAL(RCT2_ADDRESS_NUM_DSOUND_DEVICES, uint32) * sizeof(rct_dsdevice)); + if (RCT2_GLOBAL(RCT2_ADDRESS_DSOUND_DEVICES, rct_dsdevice*)) { + RCT2_GLOBAL(0x01425B54, int) = 0; + DirectSoundEnumerate(dsound_enum_callback, 0); + return RCT2_GLOBAL(0x01425B54, int); + } + return 0; } /** @@ -200,7 +423,7 @@ rct_sound* sound_next(rct_sound* sound) */ rct_sound_info* sound_get_info(uint16 sound_id) { - if (RCT2_GLOBAL(RCT2_ADDRESS_SOUND_INFO_LIST_OFFSET, int) && sound_id < RCT2_GLOBAL(RCT2_ADDRESS_SOUND_INFO_LIST_OFFSET, int)) { + if (RCT2_GLOBAL(RCT2_ADDRESS_SOUND_INFO_LIST_OFFSET, int) && sound_id < RCT2_GLOBAL(RCT2_ADDRESS_SOUND_INFO_LIST_OFFSET, int*)[0]) { return (rct_sound_info*)(RCT2_GLOBAL(RCT2_ADDRESS_SOUND_INFO_LIST_OFFSET, int) + RCT2_GLOBAL(RCT2_ADDRESS_SOUND_INFO_LIST_OFFSET, int*)[sound_id + 1]); } return 0; @@ -419,7 +642,7 @@ int sound_channel_set_volume(int channel, int volume) */ int sound_play(rct_sound* sound, int looping, int volume, int pan, int frequency) { - if (sound) { + if (sound->dsbuffer) { sound_set_frequency(sound, frequency); sound_set_pan(sound, pan); sound_set_volume(sound, volume); @@ -444,7 +667,7 @@ int sound_play(rct_sound* sound, int looping, int volume, int pan, int frequency * rct2: 0x00404E53 */ int sound_is_playing(rct_sound* sound){ - if (sound) { + if (sound->dsbuffer) { DWORD status; if (SUCCEEDED(sound->dsbuffer->lpVtbl->GetStatus(sound->dsbuffer, &status))) { if (status & DSBSTATUS_PLAYING || status & DSBSTATUS_LOOPING) @@ -461,7 +684,7 @@ int sound_is_playing(rct_sound* sound){ */ int sound_set_frequency(rct_sound* sound, int frequency) { - if (sound) { + if (sound->dsbuffer) { if (SUCCEEDED(sound->dsbuffer->lpVtbl->SetFrequency(sound->dsbuffer, frequency))) return 1; @@ -475,7 +698,7 @@ int sound_set_frequency(rct_sound* sound, int frequency) */ int sound_set_pan(rct_sound* sound, int pan) { - if (sound) { + if (sound->dsbuffer) { if (SUCCEEDED(sound->dsbuffer->lpVtbl->SetPan(sound->dsbuffer, pan))) return 1; @@ -489,7 +712,7 @@ int sound_set_pan(rct_sound* sound, int pan) */ int sound_set_volume(rct_sound* sound, int volume) { - if (sound) { + if (sound->dsbuffer) { if (SUCCEEDED(sound->dsbuffer->lpVtbl->SetVolume(sound->dsbuffer, volume))) return 1; @@ -501,14 +724,14 @@ int sound_set_volume(rct_sound* sound, int volume) * * rct2: 0x00404DD8 */ -rct_sound* sound_stop(rct_sound* sound) +int sound_stop(rct_sound* sound) { if (sound->dsbuffer) { sound->dsbuffer->lpVtbl->Release(sound->dsbuffer); sound->dsbuffer = 0; - return sound_remove(sound); + return sound_remove(sound) ? 1 : 0; } - return sound; + return 0; } /** @@ -678,6 +901,21 @@ void stop_peep_sounds() } } +/** +* +* rct2: 0x006BD0BD +*/ +void stop_title_music() +{ + if (RCT2_GLOBAL(0x009AF284, uint32) & (1 << 0)) { + if (RCT2_GLOBAL(0x009AF600, uint8) != 0) { + RCT2_GLOBAL(0x014241BC, uint32) = 1; + sound_channel_stop(3); + RCT2_GLOBAL(0x014241BC, uint32) = 0; + } + } +} + /** * * rct2: 0x00401A05 diff --git a/src/audio.h b/src/audio.h index 6009cd40cf..1ce9960cb4 100644 --- a/src/audio.h +++ b/src/audio.h @@ -57,6 +57,16 @@ typedef struct rct_sound { struct rct_sound* next; } rct_sound; +typedef struct { + uint16 var_0; + uint16 channels; + uint32 samples; + uint32 var_8; + uint16 bytes; + uint16 bits; + uint16 var_E; +} rct_audio_info; + typedef struct { uint32 var_0; uint8 pad_4[0x118]; @@ -90,7 +100,7 @@ typedef struct { rct_sound sound; } rct_other_sound; -void get_dsound_devices(); +int get_dsound_devices(); int sound_prepare(int sound_id, rct_sound *sound, int channels, int software); int sound_play_panned(int sound_id, int x); int sound_play(rct_sound* sound, int looping, int volume, int pan, int frequency); @@ -102,7 +112,9 @@ int sound_channel_play(int channel, int a2, int volume, int pan, int frequency); int sound_channel_set_frequency(int channel, int frequency); int sound_channel_set_pan(int channel, int pan); int sound_channel_set_volume(int channel, int volume); -rct_sound* sound_stop(rct_sound *sound); +int sound_stop(rct_sound *sound); +int sound_stop_all(); +int sound_unmap_file(LPCVOID base); int sound_channel_stop(int channel); rct_sound* sound_add(rct_sound* sound); rct_sound* sound_remove(rct_sound* sound); @@ -113,6 +125,7 @@ void stop_other_sounds(); void stop_vehicle_sounds(); void stop_ride_music(); void stop_peep_sounds(); +void stop_title_music(); void unpause_sounds(); // 0x009AF59C probably does the same job diff --git a/src/rct2.c b/src/rct2.c index b413820fd9..29572477a3 100644 --- a/src/rct2.c +++ b/src/rct2.c @@ -84,7 +84,7 @@ __declspec(dllexport) int StartOpenRCT(HINSTANCE hInstance, HINSTANCE hPrevInsta audio_init(); audio_get_devices(); - RCT2_CALLPROC(0x0040502E); // get_dsound_devices() + get_dsound_devices(); config_init(); language_open(gGeneral_config.language); rct2_init(); diff --git a/src/title.c b/src/title.c index 79a6aae429..adfb25e080 100644 --- a/src/title.c +++ b/src/title.c @@ -22,6 +22,7 @@ #include #include #include "addresses.h" +#include "audio.h" #include "config.h" #include "climate.h" #include "date.h" @@ -309,7 +310,7 @@ static void title_play_music() if (!(RCT2_GLOBAL(0x009AF284, uint32) & 1) || !(RCT2_GLOBAL(0x009AF59D, uint8) & 1)) { if (RCT2_GLOBAL(0x009AF600, uint8) != 0) - RCT2_CALLPROC_EBPSAFE(0x006BD0BD); // stop music + stop_title_music(); return; } From fba1a81e07e21555fda03d37f0612ea507702afd Mon Sep 17 00:00:00 2001 From: zsilencer Date: Tue, 26 Aug 2014 20:23:32 -0600 Subject: [PATCH 2/3] audio_remove_timer, audio_create_timer, map_file, audio_timer_callback --- src/addresses.h | 3 +- src/audio.c | 163 +++++++++++++++++++++++++++++++++++++++++------- src/audio.h | 2 +- 3 files changed, 144 insertions(+), 24 deletions(-) diff --git a/src/addresses.h b/src/addresses.h index d6b95d7426..80ef4cbe20 100644 --- a/src/addresses.h +++ b/src/addresses.h @@ -33,6 +33,7 @@ #define RCT2_CALLFUNC_3(address, returnType, a1, a2, a3, v1, v2, v3) (((returnType(*)(a1, a2, a3))(address))(v1, v2, v3)) #define RCT2_CALLFUNC_4(address, returnType, a1, a2, a3, a4, v1, v2, v3, v4) (((returnType(*)(a1, a2, a3, a4))(address))(v1, v2, v3, v4)) #define RCT2_CALLFUNC_5(address, returnType, a1, a2, a3, a4, a5, v1, v2, v3, v4, v5) (((returnType(*)(a1, a2, a3, a4, a5))(address))(v1, v2, v3, v4, v5)) +#define RCT2_CALLFUNC_6(address, returnType, a1, a2, a3, a4, a5, a6, v1, v2, v3, v4, v5, v6) (((returnType(*)(a1, a2, a3, a4, a5, a6))(address))(v1, v2, v3, v4, v5, v6)) #define RCT2_CALLPROC_1(address, a1, v1) RCT2_CALLFUNC_1(address, void, a1, v1) #define RCT2_CALLPROC_2(address, a1, a2, v1, v2) RCT2_CALLFUNC_2(address, void, a1, a2, v1, v2) @@ -161,7 +162,7 @@ #define RCT2_ADDRESS_DSOUND_BUFFERS 0x009E1AB0 #define RCT2_ADDRESS_NUM_DSOUND_DEVICES 0x009E2B88 #define RCT2_ADDRESS_DSOUND_DEVICES 0x009E2B8C -#define RCT2_ADDRESS_SOUND_INFO_LIST_OFFSET 0x009E2B94 +#define RCT2_ADDRESS_SOUND_INFO_LIST_MAPPING 0x009E2B94 #define RCT2_ADDRESS_SOUNDLIST_BEGIN 0x009E2B98 #define RCT2_ADDRESS_SOUNDLIST_END 0x009E2B9C #define RCT2_ADDRESS_DIRECTSOUND 0x009E2BA0 diff --git a/src/audio.c b/src/audio.c index ecc2ddb50d..f970f11256 100644 --- a/src/audio.c +++ b/src/audio.c @@ -70,7 +70,7 @@ void audio_get_devices() * * rct2: 0x00404BD2 */ -int sound_release() +int audio_release() { sound_stop_all(); if (RCT2_GLOBAL(0x009E2BA4, LPDIRECTSOUND3DBUFFER)) { @@ -93,12 +93,12 @@ int sound_release() * * rct2: 0x00404C45 */ -int sound_unmap_info() +int unmap_sound_info() { - if (RCT2_GLOBAL(RCT2_ADDRESS_SOUND_INFO_LIST_OFFSET, int)) { + if (RCT2_GLOBAL(RCT2_ADDRESS_SOUND_INFO_LIST_MAPPING, LPVOID)) { sound_stop_all(); - sound_unmap_file(RCT2_GLOBAL(RCT2_ADDRESS_SOUND_INFO_LIST_OFFSET, LPCVOID)); - RCT2_GLOBAL(RCT2_ADDRESS_SOUND_INFO_LIST_OFFSET, int) = 0; + unmap_file(RCT2_GLOBAL(RCT2_ADDRESS_SOUND_INFO_LIST_MAPPING, LPVOID)); + RCT2_GLOBAL(RCT2_ADDRESS_SOUND_INFO_LIST_MAPPING, LPVOID) = 0; return 1; } return 0; @@ -121,7 +121,7 @@ int sound_stop_all() * * rct2: 0x004068A0 */ -int sound_unmap_file(LPCVOID base) +int unmap_file(LPCVOID base) { if (base) { return UnmapViewOfFile(base); @@ -129,11 +129,33 @@ int sound_unmap_file(LPCVOID base) return 0; } +/** +* +* rct2: 0x004018F0 +*/ +int audio_remove_timer() +{ + for (int i = 0; i < 4; i++) { + sound_channel_stop(i); + } + if (RCT2_GLOBAL(0x009E1AA4, int)) { + timeKillEvent(RCT2_GLOBAL(0x009E1AA0, MMRESULT)); + timeEndPeriod(50); + while (_InterlockedExchange(&RCT2_GLOBAL(0x009E1AAC, LONG), 1) != 1) { + Sleep(100); + } + int result = _InterlockedExchange(&RCT2_GLOBAL(0x009E1AAC, LONG), 0); + RCT2_GLOBAL(0x009E1AA4, int) = 0; + return result; + } + return 0; +} + /** * * rct2: 0x006BAB21 */ -void sub_6BAB21() +void audio_close() { if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SOUND_DEVICE, uint32) != -1) { stop_other_sounds(); @@ -142,12 +164,12 @@ void sub_6BAB21() if (RCT2_GLOBAL(0x009AF284, uint32) & (1 << 0)) { stop_ride_music(); RCT2_GLOBAL(0x014241BC, uint32) = 1; - RCT2_CALLPROC(0x004018F0); // remove multimedia timer + audio_remove_timer(); RCT2_GLOBAL(0x014241BC, uint32) = 0; } RCT2_GLOBAL(0x014241BC, uint32) = 1; - sound_unmap_info(); - sound_release(); + unmap_sound_info(); + audio_release(); RCT2_GLOBAL(0x014241BC, uint32) = 0; RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SOUND_DEVICE, uint32) = -1; } @@ -265,13 +287,112 @@ int dsound_create_primary_buffer(int a, int device, int channels, int samples, i return 1; } +/** +* +* rct2: 0x004067F9 +*/ +LPVOID map_file(LPCSTR lpFileName, DWORD dwCreationDisposition, DWORD dwNumberOfBytesToMap) +{ + DWORD dwDesiredAccess; + DWORD dwDesiredAccessmap; + DWORD flProtect; + HANDLE filehandle; + HANDLE filemaphandle; + LPVOID address = 0; + if (dwCreationDisposition) { + if (dwCreationDisposition == CREATE_NEW) { + dwDesiredAccess = GENERIC_READ | GENERIC_WRITE; + dwDesiredAccessmap = FILE_MAP_WRITE; + flProtect = PAGE_READWRITE; + dwCreationDisposition = OPEN_ALWAYS; + } + } else { + dwDesiredAccess = GENERIC_READ; + flProtect = PAGE_READONLY; + dwDesiredAccessmap = FILE_MAP_READ; + dwCreationDisposition = OPEN_EXISTING; + } + filehandle = CreateFileA(lpFileName, dwDesiredAccess, 0, 0, dwCreationDisposition, FILE_ATTRIBUTE_NORMAL, 0); + if (filehandle != INVALID_HANDLE_VALUE) { + filemaphandle = CreateFileMappingA(filehandle, 0, flProtect, 0, dwNumberOfBytesToMap, 0); + CloseHandle(filehandle); + if (filemaphandle) { + address = MapViewOfFile(filemaphandle, dwDesiredAccessmap, 0, 0, dwNumberOfBytesToMap); + CloseHandle(filemaphandle); + } + } + return address; +} + +/** +* +* rct2: 0x00404C1A +*/ +int map_sound_info(const char* filename) +{ + if (RCT2_GLOBAL(RCT2_ADDRESS_SOUND_INFO_LIST_MAPPING, LPVOID)) { + return 0; + } else { + RCT2_GLOBAL(RCT2_ADDRESS_SOUND_INFO_LIST_MAPPING, LPVOID) = map_file(filename, 0, 0); + return RCT2_GLOBAL(RCT2_ADDRESS_SOUND_INFO_LIST_MAPPING, LPVOID) != 0; + } +} + +/** +* +* rct2: 0x00401000 +*/ +void sub_401000(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2, int channel) +{ + RCT2_CALLFUNC_6(0x00401000, void, UINT, UINT, DWORD_PTR, DWORD_PTR, DWORD_PTR, int, uTimerID, uMsg, dwUser, dw1, dw2, channel); +} + +/** +* +* rct2: 0x004014DF +*/ +int CALLBACK audio_timer_callback(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2) +{ + if (_InterlockedExchange(&RCT2_GLOBAL(0x009E1AAC, LONG), 1) == 0) { + for (int i = 0; i < 4; i++) { + rct_sound_channel* sound_channel = &RCT2_ADDRESS(RCT2_ADDRESS_SOUND_CHANNEL_LIST, rct_sound_channel)[i]; + if(sound_channel->var_0){ + sub_401000(uTimerID, uMsg, dwUser, dw1, dw2, i); + } + } + return _InterlockedExchange(&RCT2_GLOBAL(0x009E1AAC, LONG), 0); + } + return 0; +} + +/** +* +* rct2: 0x004018A6 +*/ +int audio_create_timer() +{ + if (RCT2_GLOBAL(0x009E1AA4, int)) { + return 0; + } + for (int i = 0; i < 4; i++) { + rct_sound_channel* sound_channel = &RCT2_ADDRESS(RCT2_ADDRESS_SOUND_CHANNEL_LIST, rct_sound_channel)[i]; + sound_channel->var_0 = 0; + } + RCT2_GLOBAL(0x009E1AA0, MMRESULT) = timeSetEvent(50, 10, audio_timer_callback, 0, TIME_PERIODIC); + if (!RCT2_GLOBAL(0x009E1AA0, MMRESULT)) { + return 0; + } + RCT2_GLOBAL(0x009E1AA4, int) = 1; + return 1; +} + /** * * rct2: 0x006BA9B5 */ void audio_init2(int device) { - sub_6BAB21(); + audio_close(); for (int i = 0; i < 7; i++) { rct_vehicle_sound* vehicle_sound = &RCT2_ADDRESS(RCT2_ADDRESS_VEHICLE_SOUND_LIST, rct_vehicle_sound)[i]; vehicle_sound->id = 0xFFFF; @@ -281,19 +402,18 @@ void audio_init2(int device) other_sound->id = 0xFFFF; } RCT2_GLOBAL(0x014241BC, uint32) = 1; - int v5 = dsound_create_primary_buffer(0, device, 2, 22050, 16); - //int v5 = RCT2_CALLFUNC_5(0x00404932, int, int, int, int, int, int, 0, device, 2, 22050, 16); + int successdsound = dsound_create_primary_buffer(0, device, 2, 22050, 16); RCT2_GLOBAL(0x014241BC, uint32) = 0; - if (!v5) { + if (!successdsound) { return; } const char * filepath = get_file_path(2); RCT2_GLOBAL(0x014241BC, uint32) = 1; - int v8 = RCT2_CALLFUNC_1(0x00404C1A, int, const char *, filepath); + int successmap = map_sound_info(filepath); RCT2_GLOBAL(0x014241BC, uint32) = 0; - if (!v8) { + if (!successmap) { RCT2_GLOBAL(0x014241BC, uint32) = 1; - sound_release(); + audio_release(); RCT2_GLOBAL(0x014241BC, uint32) = 0; return; } @@ -306,9 +426,9 @@ void audio_init2(int device) RCT2_GLOBAL(0x009AAC5C, uint8) = 1; config_save(); RCT2_GLOBAL(0x014241BC, uint32) = 1; - int result = RCT2_CALLFUNC(0x004018A6, int); // create multimedia timer + int successtimer = audio_create_timer(); RCT2_GLOBAL(0x014241BC, uint32) = 0; - if (result) { + if (successtimer) { if ((RCT2_GLOBAL(0x009AF284, uint32) & (1 << 0))) { for (int i = 0; i < 2; i++) { RCT2_GLOBAL(0x009AF46C + (i * 8), uint8) = -1; @@ -423,8 +543,8 @@ rct_sound* sound_next(rct_sound* sound) */ rct_sound_info* sound_get_info(uint16 sound_id) { - if (RCT2_GLOBAL(RCT2_ADDRESS_SOUND_INFO_LIST_OFFSET, int) && sound_id < RCT2_GLOBAL(RCT2_ADDRESS_SOUND_INFO_LIST_OFFSET, int*)[0]) { - return (rct_sound_info*)(RCT2_GLOBAL(RCT2_ADDRESS_SOUND_INFO_LIST_OFFSET, int) + RCT2_GLOBAL(RCT2_ADDRESS_SOUND_INFO_LIST_OFFSET, int*)[sound_id + 1]); + if (RCT2_GLOBAL(RCT2_ADDRESS_SOUND_INFO_LIST_MAPPING, LPVOID) && sound_id < RCT2_GLOBAL(RCT2_ADDRESS_SOUND_INFO_LIST_MAPPING, uint32*)[0]) { + return (rct_sound_info*)(RCT2_GLOBAL(RCT2_ADDRESS_SOUND_INFO_LIST_MAPPING, int) + RCT2_GLOBAL(RCT2_ADDRESS_SOUND_INFO_LIST_MAPPING, uint32*)[sound_id + 1]); } return 0; } @@ -468,7 +588,6 @@ int sound_fill_buffer(LPDIRECTSOUNDBUFFER dsbuffer, char* src, int size) */ int sound_prepare(int sound_id, rct_sound *sound, int channels, int software) { - //return RCT2_CALLFUNC_4(0x00404C6D, int, int, rct_sound*, int, int, sound_id, sound, channels, software); DSBUFFERDESC bufferdesc; char* buffer = 0; memset(&bufferdesc, 0, sizeof(bufferdesc)); diff --git a/src/audio.h b/src/audio.h index 1ce9960cb4..85aba58db8 100644 --- a/src/audio.h +++ b/src/audio.h @@ -114,7 +114,7 @@ int sound_channel_set_pan(int channel, int pan); int sound_channel_set_volume(int channel, int volume); int sound_stop(rct_sound *sound); int sound_stop_all(); -int sound_unmap_file(LPCVOID base); +int unmap_file(LPCVOID base); int sound_channel_stop(int channel); rct_sound* sound_add(rct_sound* sound); rct_sound* sound_remove(rct_sound* sound); From 6250331bd07eca503567609f36ff778ca2bfced7 Mon Sep 17 00:00:00 2001 From: zsilencer Date: Tue, 26 Aug 2014 21:48:47 -0600 Subject: [PATCH 3/3] compile test --- CMakeLists.txt | 2 +- src/audio.c | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5c911bb9fe..74762470ce 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,6 +55,6 @@ set_target_properties(${PROJECT} PROPERTIES PREFIX "") TARGET_LINK_LIBRARIES(${PROJECT} ${SDL2_LIBRARIES}) if (WIN32) - target_link_libraries(${PROJECT} winmm.lib -limm32 -lversion) + target_link_libraries(${PROJECT} winmm.lib -limm32 -lversion -ldsound) endif (WIN32) diff --git a/src/audio.c b/src/audio.c index f970f11256..6fe7726f63 100644 --- a/src/audio.c +++ b/src/audio.c @@ -228,7 +228,7 @@ int dsound_create_primary_buffer(int a, int device, int channels, int samples, i RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND) = 0; return 0; } - if (SUCCEEDED(RCT2_GLOBAL(0x009E2BA8, LPDIRECTSOUNDBUFFER)->lpVtbl->QueryInterface(RCT2_GLOBAL(0x009E2BA8, LPDIRECTSOUNDBUFFER), &RCT2_GLOBAL(0x009A4444, IID) /* IID_IDirectSound3DBuffer */, &RCT2_GLOBAL(0x009E2BA4, LPDIRECTSOUND3DBUFFER)))) { + if (SUCCEEDED(RCT2_GLOBAL(0x009E2BA8, LPDIRECTSOUNDBUFFER)->lpVtbl->QueryInterface(RCT2_GLOBAL(0x009E2BA8, LPDIRECTSOUNDBUFFER), &RCT2_GLOBAL(0x009A4444, IID) /* IID_IDirectSound3DBuffer */, (void**)&RCT2_GLOBAL(0x009E2BA4, LPDIRECTSOUND3DBUFFER)))) { // doesn't seem to ever make it here, below doesn't make sense and is probably remnants of unused 3d sound tests memset(&RCT2_GLOBAL(0x009A6084, DS3DBUFFER), 0, sizeof(RCT2_GLOBAL(0x009A6084, DS3DBUFFER))); RCT2_GLOBAL(0x009A6084, DS3DBUFFER).dwSize = sizeof(RCT2_GLOBAL(0x009A6084, DS3DBUFFER)); @@ -378,7 +378,7 @@ int audio_create_timer() rct_sound_channel* sound_channel = &RCT2_ADDRESS(RCT2_ADDRESS_SOUND_CHANNEL_LIST, rct_sound_channel)[i]; sound_channel->var_0 = 0; } - RCT2_GLOBAL(0x009E1AA0, MMRESULT) = timeSetEvent(50, 10, audio_timer_callback, 0, TIME_PERIODIC); + RCT2_GLOBAL(0x009E1AA0, MMRESULT) = timeSetEvent(50, 10, (LPTIMECALLBACK)audio_timer_callback, 0, TIME_PERIODIC); if (!RCT2_GLOBAL(0x009E1AA0, MMRESULT)) { return 0; } @@ -565,11 +565,11 @@ int sound_info_loadvars(rct_sound_info* sound_info, LPWAVEFORMATEX* waveformat, * * rct2: 0x00405076 */ -int sound_fill_buffer(LPDIRECTSOUNDBUFFER dsbuffer, char* src, int size) +int sound_fill_buffer(LPDIRECTSOUNDBUFFER dsbuffer, char* src, DWORD size) { - char* buf; - char* buf2; - int buf2size; + LPVOID buf; + LPVOID buf2; + DWORD buf2size; if (SUCCEEDED(dsbuffer->lpVtbl->Lock(dsbuffer, 0, size, &buf, &size, &buf2, &buf2size, 0))) { memset(buf, 0, size); memcpy(buf, src, size);