diff --git a/src/addresses.h b/src/addresses.h index 4f620d00bd..700ad084be 100644 --- a/src/addresses.h +++ b/src/addresses.h @@ -161,8 +161,10 @@ #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_SOUNDLIST_BEGIN 0x009E2B98 #define RCT2_ADDRESS_SOUNDLIST_END 0x009E2B9C +#define RCT2_ADDRESS_DIRECTSOUND 0x009E2BA0 #define RCT2_ADDRESS_CMDLINE 0x009E2D98 diff --git a/src/audio.c b/src/audio.c index fb6b639d47..4bfbf81863 100644 --- a/src/audio.c +++ b/src/audio.c @@ -70,7 +70,7 @@ void audio_get_devices() * * rct2: 0x006BAB21 */ -void audio_6BAB21(void) +void sub_6BAB21(void) { if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SOUND_DEVICE, uint32) != -1) { stop_other_sounds(); @@ -96,7 +96,7 @@ void audio_6BAB21(void) */ void audio_init2(int device) { - audio_6BAB21(); + sub_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; @@ -155,13 +155,149 @@ void get_dsound_devices() RCT2_CALLPROC(0x0040502E); } +/** +* +* rct2: 0x00404D99 +*/ +int sound_duplicate(rct_sound* newsound, rct_sound* sound) +{ + if (FAILED(RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND)->lpVtbl->DuplicateSoundBuffer(RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND), sound->dsbuffer, &newsound->dsbuffer))) { + return 0; + } else { + newsound->id = sound->id; + newsound->has_caps = sound->has_caps; + newsound->var_0C = sound->var_0C; + sound_add(newsound); + return 1; + } +} + +/** +* +* rct2: 0x00405103 +*/ +rct_sound* sound_begin() +{ + return RCT2_GLOBAL(RCT2_ADDRESS_SOUNDLIST_BEGIN, rct_sound*); +} + +/** +* +* rct2: 0x00405109 +*/ +rct_sound* sound_next(rct_sound* sound) +{ + if (RCT2_GLOBAL(RCT2_ADDRESS_SOUNDLIST_END, rct_sound*) == sound) { + return 0; + } else { + return sound->next; + } +} + +/** +* +* rct2: 0x00405206 +*/ +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)) { + 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; +} + +/** +* +* rct2: 0x00405054 +*/ +int sound_info_loadvars(rct_sound_info* sound_info, LPWAVEFORMATEX* waveformat, char** data, DWORD* buffersize) +{ + *buffersize = sound_info->size; + *waveformat = &sound_info->format; + *data = (char*)&sound_info->data; + return 1; +} + +/** +* +* rct2: 0x00405076 +*/ +int sound_fill_buffer(LPDIRECTSOUNDBUFFER dsbuffer, char* src, int size) +{ + char* buf; + char* buf2; + int buf2size; + if (SUCCEEDED(dsbuffer->lpVtbl->Lock(dsbuffer, 0, size, &buf, &size, &buf2, &buf2size, 0))) { + memset(buf, 0, size); + memcpy(buf, src, size); + if (buf2size) { + memcpy(buf2, &src[size], buf2size); + } + dsbuffer->lpVtbl->Unlock(dsbuffer, buf, size, buf2, buf2size); + return 1; + } + return 0; +} + /** * * rct2: 0x00404C6D */ -int sound_prepare(int sound_id, rct_sound *sound, int var_8, int var_c) +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, var_8, var_c); + //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)); + bufferdesc.dwSize = sizeof(bufferdesc); + rct_sound* tempsound = sound_begin(); + if (tempsound) { + int wasduplicated = 0; + while (!tempsound->dsbuffer || tempsound->id != sound_id || !sound_duplicate(sound, tempsound)) { + tempsound = sound_next(tempsound); + if (!tempsound) { + wasduplicated = 1; + break; + } + } + if (!wasduplicated) { + return 1; + } + } + rct_sound_info* sound_info = sound_get_info(sound_id); + if (sound_info) { + if (sound_info_loadvars(sound_info, &bufferdesc.lpwfxFormat, &buffer, &bufferdesc.dwBufferBytes)) { + bufferdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_STATIC; + if (channels) { + if (channels == 2) { + bufferdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLPAN | DSBCAPS_CTRLFREQUENCY | DSBCAPS_STATIC; + } else { + bufferdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRL3D | DSBCAPS_STATIC; + } + if (RCT2_GLOBAL(0x009E2B90, uint32)) { + bufferdesc.dwFlags |= DSBCAPS_CTRLPAN; + } + if (software) { + bufferdesc.dwFlags |= DSBCAPS_LOCSOFTWARE; + } + if (SUCCEEDED(RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND)->lpVtbl->CreateSoundBuffer(RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND), &bufferdesc, &sound->dsbuffer, 0))) { + if (sound_fill_buffer(sound->dsbuffer, buffer, bufferdesc.dwBufferBytes)) { + sound->id = sound_id; + DSBCAPS caps; + caps.dwSize = sizeof(caps); + sound->dsbuffer->lpVtbl->GetCaps(sound->dsbuffer, &caps); + sound->has_caps = caps.dwFlags; + sound_add(sound); + return 1; + } + sound->dsbuffer->lpVtbl->Release(sound->dsbuffer); + sound->dsbuffer = 0; + } + } + sound->dsbuffer = 0; + } + } + return 0; } /** @@ -171,7 +307,7 @@ int sound_prepare(int sound_id, rct_sound *sound, int var_8, int var_c) int sound_play_panned(int sound_id, int x) { //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 + // this function is not complete, need to add in volume adjust int result = 0; if (RCT2_GLOBAL(0x009AF59D, uint8) & 1) { RCT2_GLOBAL(0x00F438AD, uint8) = 0; @@ -193,7 +329,12 @@ int sound_play_panned(int sound_id, int x) if (x == 0x8000) { pan = 0; } else { - // stuff to adjust pan + int x2 = x << 16; + uint16 screenwidth = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, uint16); + if (screenwidth < 64) { + screenwidth = 64; + } + pan = ((x2 / screenwidth) - 0x8000) >> 4; } if (!RCT2_GLOBAL(0x009AAC6D, uint8)) { pan = 0; @@ -360,13 +501,30 @@ int sound_set_volume(rct_sound* sound, int volume) * * rct2: 0x00404DD8 */ -void sound_stop(rct_sound* sound) +rct_sound* sound_stop(rct_sound* sound) { if (sound->dsbuffer) { sound->dsbuffer->lpVtbl->Release(sound->dsbuffer); sound->dsbuffer = 0; - sound_remove(sound); + return sound_remove(sound); } + return sound; +} + +/** +* +* rct2: 0x0040511C +*/ +rct_sound* sound_add(rct_sound* sound) +{ + if (RCT2_GLOBAL(RCT2_ADDRESS_SOUNDLIST_BEGIN, rct_sound*)) { + RCT2_GLOBAL(RCT2_ADDRESS_SOUNDLIST_END, rct_sound*)->next = sound; + } else { + RCT2_GLOBAL(RCT2_ADDRESS_SOUNDLIST_BEGIN, rct_sound*) = sound; + } + RCT2_GLOBAL(RCT2_ADDRESS_SOUNDLIST_END, rct_sound*) = sound; + sound->next = 0; + return sound; } /** @@ -398,6 +556,24 @@ rct_sound* sound_remove(rct_sound* sound) return result; } +/** +* +* rct2: 0x00405436 +*/ +void sound_channel_free(HMMIO* hmmio, HGLOBAL* hmem) +{ + if(*hmem) + { + GlobalFree(*hmem); + *hmem = 0; + } + if(*hmmio) + { + mmioClose(*hmmio, 0); + *hmmio = 0; + } +} + /** * * rct2: 0x006BABB4 @@ -514,8 +690,9 @@ int sound_channel_stop(int channel) 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? + if (sound_channel->hmem) { + sound_channel_free(&sound_channel->hmmio, &sound_channel->hmem); + } LPDIRECTSOUNDBUFFER dsbuffer = RCT2_ADDRESS(RCT2_ADDRESS_DSOUND_BUFFERS, LPDIRECTSOUNDBUFFER)[channel]; if (dsbuffer) { diff --git a/src/audio.h b/src/audio.h index e7430cec61..6009cd40cf 100644 --- a/src/audio.h +++ b/src/audio.h @@ -35,7 +35,6 @@ void audio_quit(); void audio_get_devices(); void audio_init2(int device); - #include /** @@ -61,14 +60,20 @@ typedef struct rct_sound { typedef struct { uint32 var_0; uint8 pad_4[0x118]; - uint32 var_11C; - uint32 var_120; + HMMIO hmmio; + HGLOBAL hmem; uint8 pad_124[0x3C]; uint32 var_160; uint32 var_164; uint32 var_168; } rct_sound_channel; +typedef struct { + uint32 size; + WAVEFORMATEX format; + char* data; +} rct_sound_info; + typedef struct { uint16 id; uint16 var_2; @@ -86,7 +91,7 @@ typedef struct { } rct_other_sound; void get_dsound_devices(); -int sound_prepare(int sound_id, rct_sound *sound, int var_8, int var_c); +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); int sound_is_playing(rct_sound* sound); @@ -97,9 +102,12 @@ 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); -void sound_stop(rct_sound *sound); +rct_sound* sound_stop(rct_sound *sound); int sound_channel_stop(int channel); +rct_sound* sound_add(rct_sound* sound); rct_sound* sound_remove(rct_sound* sound); +rct_sound* sound_begin(); +rct_sound* sound_next(rct_sound* sound); void pause_sounds(); void stop_other_sounds(); void stop_vehicle_sounds(); diff --git a/src/osinterface.c b/src/osinterface.c index c86a3f792c..9213603e7d 100644 --- a/src/osinterface.c +++ b/src/osinterface.c @@ -452,6 +452,7 @@ int osinterface_open_common_file_dialog(int type, char *title, char *filename, c OPENFILENAME openFileName; BOOL result; int tmp; + DWORD commonFlags; // Get directory path from given filename strcpy(initialDirectory, filename); @@ -488,7 +489,7 @@ int osinterface_open_common_file_dialog(int type, char *title, char *filename, c RCT2_GLOBAL(0x009E2C74, uint32) = 1; // Open dialog - DWORD commonFlags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_NOCHANGEDIR; + commonFlags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_NOCHANGEDIR; if (type == 0) { openFileName.Flags = commonFlags | OFN_CREATEPROMPT | OFN_OVERWRITEPROMPT; result = GetSaveFileName(&openFileName); diff --git a/src/window_ride.c b/src/window_ride.c index fb0384abeb..66b9e2a23b 100644 --- a/src/window_ride.c +++ b/src/window_ride.c @@ -113,6 +113,7 @@ rct_window *window_ride_open(int rideIndex) ebx++; } RCT2_GLOBAL((int)w + 496, uint16) = ebx; + return w; } /**