diff --git a/src/addresses.h b/src/addresses.h index 8b28dad719..4f620d00bd 100644 --- a/src/addresses.h +++ b/src/addresses.h @@ -106,6 +106,10 @@ #define RCT2_ADDRESS_INSTALLED_OBJECT_LIST 0x009ADAE8 +#define RCT2_ADDRESS_CURRENT_SOUND_DEVICE 0x009AF280 + +#define RCT2_ADDRESS_VEHICLE_SOUND_LIST 0x009AF288 + #define RCT2_ADDRESS_CURENT_CURSOR 0x009DE51C #define RCT2_ADDRESS_INPUT_STATE 0x009DE51D #define RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS 0x009DE51F @@ -310,7 +314,7 @@ #define RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER 0x0141ED68 - +#define RCT2_ADDRESS_SOUND_CHANNEL_LIST 0x014262E0 #define RCT2_ADDRESS_WATER_RAISE_COST 0x0141F738 #define RCT2_ADDRESS_WATER_LOWER_COST 0x0141F73C diff --git a/src/audio.c b/src/audio.c index 8f2d0cce27..fb6b639d47 100644 --- a/src/audio.c +++ b/src/audio.c @@ -21,6 +21,7 @@ #include #include "audio.h" #include "addresses.h" +#include "config.h" #include "rct2.h" int gAudioDeviceCount; @@ -65,6 +66,86 @@ void audio_get_devices() } } +/** +* +* rct2: 0x006BAB21 +*/ +void audio_6BAB21(void) +{ + if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SOUND_DEVICE, uint32) != -1) { + stop_other_sounds(); + stop_peep_sounds(); + RCT2_CALLPROC_EBPSAFE(0x006BD0BD); + if (RCT2_GLOBAL(0x009AF284, uint32) & (1 << 0)) { + stop_ride_music(); + RCT2_GLOBAL(0x014241BC, uint32) = 1; + RCT2_CALLPROC(0x004018F0); // remove multimedia timer + RCT2_GLOBAL(0x014241BC, uint32) = 0; + } + RCT2_GLOBAL(0x014241BC, uint32) = 1; + RCT2_CALLPROC(0x00404C45); + RCT2_CALLPROC(0x00404BD2); + RCT2_GLOBAL(0x014241BC, uint32) = 0; + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SOUND_DEVICE, uint32) = -1; + } +} + +/** +* +* rct2: 0x006BA9B5 +*/ +void audio_init2(int device) +{ + audio_6BAB21(); + 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; + } + for (int i = 0; i < 7; i++) { + rct_other_sound* other_sound = &RCT2_ADDRESS(0x009AF484, rct_other_sound)[i]; + 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); + RCT2_GLOBAL(0x014241BC, uint32) = 0; + if (!v5) { + return; + } + const char * filepath = get_file_path(2); + RCT2_GLOBAL(0x014241BC, uint32) = 1; + int v8 = RCT2_CALLFUNC_1(0x00404C1A, int, const char *, filepath); + RCT2_GLOBAL(0x014241BC, uint32) = 0; + if (!v8) { + RCT2_GLOBAL(0x014241BC, uint32) = 1; + RCT2_CALLPROC(0x00404BD2); + 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]; + RCT2_GLOBAL(0x009AAC5C, uint8) = 1; + config_save(); + RCT2_GLOBAL(0x014241BC, uint32) = 1; + int result = RCT2_CALLFUNC(0x004018A6, int); // create multimedia timer + RCT2_GLOBAL(0x014241BC, uint32) = 0; + if (result) { + if ((RCT2_GLOBAL(0x009AF284, uint32) & (1 << 0))) { + for (int i = 0; i < 2; i++) { + RCT2_GLOBAL(0x009AF46C + (i * 8), uint8) = -1; + } + } + } + if (!RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) & 1 << 4) { + RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_SOUND_SW_BUFFER, uint32) = RCT2_GLOBAL(0x001425B74, uint32) != RCT2_GLOBAL(0x001425B78, uint32) || RCT2_GLOBAL(0x001425B74, uint32) != RCT2_GLOBAL(0x001425B7C, uint32); + RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) |= 1 << 4; + config_save(); + } +} + /** * * rct2: 0x0040502E @@ -74,14 +155,58 @@ void get_dsound_devices() RCT2_CALLPROC(0x0040502E); } +/** +* +* rct2: 0x00404C6D +*/ int sound_prepare(int sound_id, rct_sound *sound, int var_8, int var_c) { return RCT2_CALLFUNC_4(0x00404C6D, int, int, rct_sound*, int, int, sound_id, sound, var_8, var_c); } -void sound_play_panned(int sound_id, int x) +/** +* +* rct2: 0x006BB76E +*/ +int sound_play_panned(int sound_id, int x) { - RCT2_CALLPROC_X(0x006BB76E, sound_id, x, 0, 0, 0, 0, 0); + //RCT2_CALLPROC_X(0x006BB76E, sound_id, x, 0, 0, 0, 0, 0); + // this function is not complete, need to add in volume and pan adjust + int result = 0; + if (RCT2_GLOBAL(0x009AF59D, uint8) & 1) { + RCT2_GLOBAL(0x00F438AD, uint8) = 0; + int volume = 0; + if (x == 0x8001) { + // stuff to adjust volume + } + int i = 0; + rct_other_sound* other_sound = &RCT2_ADDRESS(0x009AF484, rct_other_sound)[i]; + while (other_sound->id != 0xFFFF) { + i++; + other_sound = &RCT2_ADDRESS(0x009AF484, rct_other_sound)[i]; + if (i > RCT2_GLOBAL(0x009AAC76, uint8)) { // too many sounds playing + return sound_id; + } + } + other_sound->id = sound_id; + int pan; + if (x == 0x8000) { + pan = 0; + } else { + // stuff to adjust pan + } + if (!RCT2_GLOBAL(0x009AAC6D, uint8)) { + pan = 0; + } + + RCT2_GLOBAL(0x014241BC, uint32) = 1; + sound_prepare(sound_id, &other_sound->sound, 1, RCT2_GLOBAL(0x009AAC6E, uint32)); + RCT2_GLOBAL(0x014241BC, uint32) = 0; + RCT2_GLOBAL(0x014241BC, uint32) = 1; + result = sound_play(&other_sound->sound, 0, volume, pan, 0); + RCT2_GLOBAL(0x014241BC, uint32) = 0; + } + return result; } /** @@ -90,14 +215,15 @@ void sound_play_panned(int sound_id, int x) */ int sound_channel_play(int channel, int a2, int volume, int pan, int frequency) { - RCT2_GLOBAL(0x1426444 + (91 * channel * 4), uint32) = a2; + rct_sound_channel* sound_channel = &RCT2_ADDRESS(RCT2_ADDRESS_SOUND_CHANNEL_LIST, rct_sound_channel)[channel]; + sound_channel->var_164 = a2; sound_channel_set_frequency(channel, frequency); sound_channel_set_pan(channel, pan); sound_channel_set_volume(channel, volume); LPDIRECTSOUNDBUFFER dsbuffer = RCT2_ADDRESS(RCT2_ADDRESS_DSOUND_BUFFERS, LPDIRECTSOUNDBUFFER)[channel]; dsbuffer->lpVtbl->SetCurrentPosition(dsbuffer, 0); dsbuffer->lpVtbl->Play(dsbuffer, 0, 0, DSBPLAY_LOOPING); - RCT2_GLOBAL(0x14262E0 + (91 * channel * 4), uint32) = 1; + sound_channel->var_0 = 1; return 1; } @@ -172,6 +298,22 @@ int sound_play(rct_sound* sound, int looping, int volume, int pan, int frequency return 0; } +/** +* +* rct2: 0x00404E53 +*/ +int sound_is_playing(rct_sound* sound){ + if (sound) { + DWORD status; + if (SUCCEEDED(sound->dsbuffer->lpVtbl->GetStatus(sound->dsbuffer, &status))) { + if (status & DSBSTATUS_PLAYING || status & DSBSTATUS_LOOPING) + return 1; + + } + } + return 0; +} + /** * * rct2: 0x00404ED7 @@ -260,21 +402,137 @@ rct_sound* sound_remove(rct_sound* sound) * * rct2: 0x006BABB4 */ -void pause_sounds() { +void pause_sounds() +{ if (++RCT2_GLOBAL(0x009AF59C, uint8) == 1) { - RCT2_CALLPROC_EBPSAFE(0x006BCAE5); - RCT2_CALLPROC_EBPSAFE(0x006BABDF); - RCT2_CALLPROC_EBPSAFE(0x006BCA9F); - RCT2_CALLPROC_EBPSAFE(0x006BD07F); + stop_other_sounds(); + stop_vehicle_sounds(); + stop_ride_music(); + stop_peep_sounds(); } g_sounds_disabled = 1; } +/** +* +* rct2: 0x006BCAE5 +*/ +void stop_other_sounds() +{ + if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SOUND_DEVICE, uint32) != -1) { + if (RCT2_GLOBAL(0x009AF5A8, uint32) != 1) { + RCT2_GLOBAL(0x014241BC, uint32) = 1; + sound_stop(RCT2_GLOBAL(0x009AF5AC, rct_sound*)); + RCT2_GLOBAL(0x014241BC, uint32) = 0; + RCT2_GLOBAL(0x009AF5A8, uint32) = 1; + } + if (RCT2_GLOBAL(0x009AF5C0, uint32) != 8) { + RCT2_GLOBAL(0x014241BC, uint32) = 1; + sound_stop(RCT2_GLOBAL(0x009AF5C4, rct_sound*)); + RCT2_GLOBAL(0x014241BC, uint32) = 0; + RCT2_GLOBAL(0x009AF5C0, uint32) = 8; + } + if (RCT2_GLOBAL(0x009AF5D8, uint32) != 8) { + RCT2_GLOBAL(0x014241BC, uint32) = 1; + sound_stop(RCT2_GLOBAL(0x009AF5DC, rct_sound*)); + RCT2_GLOBAL(0x014241BC, uint32) = 0; + RCT2_GLOBAL(0x009AF5D8, uint32) = 8; + } + } +} + +/** +* +* rct2: 0x006BABDF +*/ +void stop_vehicle_sounds() +{ + if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SOUND_DEVICE, sint32) != -1) { + for (int i = 0; i < 7; i++) { + rct_vehicle_sound* vehicle_sound = &RCT2_ADDRESS(RCT2_ADDRESS_VEHICLE_SOUND_LIST, rct_vehicle_sound)[i]; + if (vehicle_sound->id != 0xFFFF) { + if (vehicle_sound->var_18 != 0xFFFF) { + RCT2_GLOBAL(0x014241BC, uint32) = 1; + sound_stop(&vehicle_sound->sound1); + RCT2_GLOBAL(0x014241BC, uint32) = 0; + } + if (vehicle_sound->var_34 != 0xFFFF) { + RCT2_GLOBAL(0x014241BC, uint32) = 1; + sound_stop(&vehicle_sound->sound2); + RCT2_GLOBAL(0x014241BC, uint32) = 0; + } + } + vehicle_sound->id = 0xFFFF; + } + } +} + +/** +* +* rct2: 0x006BCA9F +*/ +void stop_ride_music() +{ + if ((RCT2_GLOBAL(0x009AF284, uint32) & (1 << 0))) { + for (int i = 0; i < 2; i++) { + uint8 * data = RCT2_ADDRESS(0x009AF46C + (i * 8), uint8); + if (data[0] != 0xFF) { + RCT2_GLOBAL(0x014241BC, uint32) = 1; + sound_channel_stop(i); + RCT2_GLOBAL(0x014241BC, uint32) = 0; + data[0] = 0xFF; + } + } + } +} + +/** +* +* rct2: 0x006BD07F +*/ +void stop_peep_sounds() +{ + if ((RCT2_GLOBAL(0x009AF284, uint32) & (1 << 0))) { + if (RCT2_GLOBAL(0x009AF5FC, uint32) != 1) { + RCT2_GLOBAL(0x014241BC, uint32) = 1; + sound_channel_stop(2); + RCT2_GLOBAL(0x014241BC, uint32) = 0; + RCT2_GLOBAL(0x009AF5FC, uint32) = 1; + } + } +} + +/** +* +* rct2: 0x00401A05 +*/ +int sound_channel_stop(int channel) +{ + rct_sound_channel* sound_channel = &RCT2_ADDRESS(RCT2_ADDRESS_SOUND_CHANNEL_LIST, rct_sound_channel)[channel]; + sound_channel->var_0 = 0; + sound_channel->var_160 = 1; + while (_InterlockedExchange(&RCT2_GLOBAL(0x009E1AAC, LONG), 1) != 1) { + Sleep(10); + } + if (sound_channel->var_120) + RCT2_CALLPROC_2(0x00405436, uint32, uint32, sound_channel->var_11C, sound_channel->var_120); // free_sound? + + LPDIRECTSOUNDBUFFER dsbuffer = RCT2_ADDRESS(RCT2_ADDRESS_DSOUND_BUFFERS, LPDIRECTSOUNDBUFFER)[channel]; + if (dsbuffer) { + dsbuffer->lpVtbl->Stop(dsbuffer); + dsbuffer->lpVtbl->Release(dsbuffer); + RCT2_ADDRESS(RCT2_ADDRESS_DSOUND_BUFFERS, LPDIRECTSOUNDBUFFER)[channel] = 0; + } + _InterlockedExchange(&RCT2_GLOBAL(0x009E1AAC, LONG), 0); + return 1; +} + /** * * rct2: 0x006BABD8 */ -void unpause_sounds() { +void unpause_sounds() +{ RCT2_GLOBAL(0x009AF59C, uint8)--; g_sounds_disabled = 0; } \ No newline at end of file diff --git a/src/audio.h b/src/audio.h index e40b1416f3..e7430cec61 100644 --- a/src/audio.h +++ b/src/audio.h @@ -21,6 +21,8 @@ #ifndef _AUDIO_H_ #define _AUDIO_H_ +#include "rct2.h" + typedef struct { char name[256]; } audio_device; @@ -31,6 +33,7 @@ extern audio_device *gAudioDevices; void audio_init(); void audio_quit(); void audio_get_devices(); +void audio_init2(int device); #include @@ -55,10 +58,38 @@ typedef struct rct_sound { struct rct_sound* next; } rct_sound; +typedef struct { + uint32 var_0; + uint8 pad_4[0x118]; + uint32 var_11C; + uint32 var_120; + uint8 pad_124[0x3C]; + uint32 var_160; + uint32 var_164; + uint32 var_168; +} rct_sound_channel; + +typedef struct { + uint16 id; + uint16 var_2; + rct_sound sound1; // 0x04 + uint16 var_18; + uint8 pad_1A[0x06]; + rct_sound sound2; // 0x20 + uint16 var_34; + uint8 pad_36[0x06]; +} rct_vehicle_sound; + +typedef struct { + uint16 id; + rct_sound sound; +} rct_other_sound; + void get_dsound_devices(); int sound_prepare(int sound_id, rct_sound *sound, int var_8, int var_c); -void sound_play_panned(int sound_id, int x); +int sound_play_panned(int sound_id, int x); int sound_play(rct_sound* sound, int looping, int volume, int pan, int frequency); +int sound_is_playing(rct_sound* sound); int sound_set_frequency(rct_sound* sound, int frequency); int sound_set_pan(rct_sound* sound, int pan); int sound_set_volume(rct_sound* sound, int volume); @@ -67,8 +98,13 @@ 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); void sound_stop(rct_sound *sound); +int sound_channel_stop(int channel); rct_sound* sound_remove(rct_sound* sound); void pause_sounds(); +void stop_other_sounds(); +void stop_vehicle_sounds(); +void stop_ride_music(); +void stop_peep_sounds(); void unpause_sounds(); // 0x009AF59C probably does the same job diff --git a/src/climate.c b/src/climate.c index 5f1bf8902b..af633917fa 100644 --- a/src/climate.c +++ b/src/climate.c @@ -186,7 +186,7 @@ static void climate_determine_future_weather() */ void climate_update_sound() { - if (RCT2_GLOBAL(0x009AF280, uint32) == 0xFFFFFFFF) + if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SOUND_DEVICE, uint32) == 0xFFFFFFFF) return; if (RCT2_GLOBAL(0x009AF59C, uint8) != 0) return; @@ -210,13 +210,13 @@ static void climate_update_rain_sound() } else { // Increase rain sound _rainVolume = min(-1400, _rainVolume + 80); - RCT2_CALLPROC_2(0x00404F0D, rct_sound*, int, &_rainSoundInstance, _rainVolume); + sound_set_volume(&_rainSoundInstance, _rainVolume); } } else if (_rainVolume != 1) { // Decrease rain sound _rainVolume -= 80; if (_rainVolume > -4000) { - RCT2_CALLPROC_2(0x00404F0D, rct_sound*, int, &_rainSoundInstance, _rainVolume); + sound_set_volume(&_rainSoundInstance, _rainVolume); } else { sound_stop(&_rainSoundInstance); _rainVolume = 1; @@ -248,7 +248,7 @@ static void climate_update_thunder_sound() if (_thunderStatus[i] == THUNDER_STATUS_NULL) continue; - if (!RCT2_CALLFUNC_1(0x00404E53, int, rct_sound*, &_thunderSoundInstance[i])) { + if (!sound_is_playing(&_thunderSoundInstance[i])) { sound_stop(&_thunderSoundInstance[i]); _thunderStatus[i] = THUNDER_STATUS_NULL; } diff --git a/src/game.c b/src/game.c index 1bafb3d29e..f67b6f9279 100644 --- a/src/game.c +++ b/src/game.c @@ -388,6 +388,8 @@ void game_logic_update() news_item_update_current(); RCT2_CALLPROC_EBPSAFE(0x0067009A); // scenario editor opening of windows for a phase + RCT2_CALLPROC_EBPSAFE(0x006BB991); // removes other sounds that are no longer playing, this is normally called somewhere in rct2_init + // Update windows window_dispatch_update_all(); diff --git a/src/intro.c b/src/intro.c index 75f3c853cb..8b2ee2fdba 100644 --- a/src/intro.c +++ b/src/intro.c @@ -80,7 +80,7 @@ void intro_update() // Chain lift sound _sound_playing_flag = 0; - if (RCT2_GLOBAL(0x009AF280, sint32) != -1) { + if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SOUND_DEVICE, sint32) != -1) { // Prepare and play the sound if (sound_prepare(SOUND_LIFT_7, &_prepared_sound, 0, 1)) if (sound_play(&_prepared_sound, 1, 0, 0, 0)) @@ -157,7 +157,7 @@ void intro_update() } // Play the track friction sound - if (RCT2_GLOBAL(0x009AF280, sint32) != -1) { + if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SOUND_DEVICE, sint32) != -1) { // Prepare and play the sound if (sound_prepare(SOUND_TRACK_FRICTION_3, &_prepared_sound, 1, 1)) if (sound_play(&_prepared_sound, 1, -800, 0, 0x3A98)) @@ -188,7 +188,7 @@ void intro_update() } // Play long peep scream sound - if (RCT2_GLOBAL(0x009AF280, sint32) != -1) + if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SOUND_DEVICE, sint32) != -1) if (sound_prepare(SOUND_SCREAM_1, &_prepared_sound, 0, 1)) if (sound_play(&_prepared_sound, 0, 0, 0, 0)) _sound_playing_flag = 1; diff --git a/src/window_options.c b/src/window_options.c index 738fe92bdf..8190d761ed 100644 --- a/src/window_options.c +++ b/src/window_options.c @@ -379,7 +379,7 @@ static void window_options_mousedown(int widgetIndex, rct_window*w, rct_widget* window_options_show_dropdown(w, widget, gAudioDeviceCount); - gDropdownItemsChecked |= (1 << RCT2_GLOBAL(0x9AF280, uint32)); + gDropdownItemsChecked |= (1 << RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SOUND_DEVICE, uint32)); break; case WIDX_HEIGHT_LABELS_DROPDOWN: gDropdownItemsFormat[0] = 1142; @@ -500,13 +500,15 @@ static void window_options_dropdown() switch (widgetIndex) { case WIDX_SOUND_DROPDOWN: - #ifdef _MSC_VER + audio_init2(dropdownIndex); + /*#ifdef _MSC_VER __asm movzx ax, dropdownIndex #else __asm__ ( "movzx ax, %[dropdownIndex] " : : [dropdownIndex] "g" ((char)dropdownIndex) ); #endif // the switch replaces ax value - RCT2_CALLPROC_EBPSAFE(0x006BA9B5); // part of init audio + RCT2_CALLPROC_EBPSAFE(0x006BA9B5); // part of init audio*/ + window_invalidate(w); break; case WIDX_HEIGHT_LABELS_DROPDOWN: @@ -670,7 +672,7 @@ static void window_options_invalidate() window_options_widgets[WIDX_HEIGHT_LABELS_DROPDOWN].type = WWT_DROPDOWN_BUTTON; break; case WINDOW_OPTIONS_PAGE_AUDIO: - currentSoundDevice = RCT2_GLOBAL(0x009AF280, sint32); + currentSoundDevice = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SOUND_DEVICE, sint32); // sound devices if (currentSoundDevice == -1 || gAudioDeviceCount == 0) {