diff --git a/src/audio/audio.c b/src/audio/audio.c index 3703d8beec..f562678469 100644 --- a/src/audio/audio.c +++ b/src/audio/audio.c @@ -1555,7 +1555,7 @@ void start_title_music() && RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TITLE_DEMO) { if (!RCT2_GLOBAL(0x009AF600, uint8)) { #ifdef USE_MIXER - gTitleMusicChannel = Mixer_Play_Music(musicPathId); + gTitleMusicChannel = Mixer_Play_Music(musicPathId, true); #else RCT2_GLOBAL(0x014241BC, uint32) = 1; int result = sound_channel_load_file2(3, (char*)get_file_path(musicPathId), 0); diff --git a/src/audio/mixer.cpp b/src/audio/mixer.cpp index 0888df65b4..247e1aa395 100644 --- a/src/audio/mixer.cpp +++ b/src/audio/mixer.cpp @@ -31,21 +31,64 @@ extern "C" { Mixer gMixer; -Sample::Sample() +Source::~Source() +{ + +} + +unsigned long Source::GetSome(unsigned long offset, const uint8** data, unsigned long length) +{ + if (offset >= Length()) { + return 0; + } + unsigned long size = length; + if (offset + length > Length()) { + size = Length() - offset; + } + return Read(offset, data, size); +} + +unsigned long Source::Length() +{ + return length; +} + +const AudioFormat& Source::Format() +{ + return format; +} + +Source_Null::Source_Null() +{ + length = 0; +} + +unsigned long Source_Null::Read(unsigned long offset, const uint8** data, unsigned long length) +{ + return 0; +} + +Source_Sample::Source_Sample() { data = 0; length = 0; issdlwav = false; } -Sample::~Sample() +Source_Sample::~Source_Sample() { Unload(); } -bool Sample::Load(const char* filename) +unsigned long Source_Sample::Read(unsigned long offset, const uint8** data, unsigned long length) { - log_verbose("Sample::Load(%s)", filename); + *data = &Source_Sample::data[offset]; + return length; +} + +bool Source_Sample::LoadWAV(const char* filename) +{ + log_verbose("Source_Sample::LoadWAV(%s)", filename); utf8 utf8filename[512]; win1252_to_utf8(utf8filename, filename, sizeof(utf8filename)); @@ -75,9 +118,9 @@ bool Sample::Load(const char* filename) return true; } -bool Sample::LoadCSS1(const char* filename, unsigned int offset) +bool Source_Sample::LoadCSS1(const char* filename, unsigned int offset) { - log_verbose("Sample::LoadCSS1(%s, %d)", filename, offset); + log_verbose("Source_Sample::LoadCSS1(%s, %d)", filename, offset); utf8 utf8filename[512]; win1252_to_utf8(utf8filename, filename, sizeof(utf8filename)); @@ -107,13 +150,18 @@ bool Sample::LoadCSS1(const char* filename, unsigned int offset) format.freq = waveformat.nSamplesPerSec; format.format = AUDIO_S16LSB; format.channels = waveformat.nChannels; - data = new uint8[length]; + data = new (std::nothrow) uint8[length]; + if (!data) { + log_verbose("Unable to allocate data"); + SDL_RWclose(rw); + return false; + } SDL_RWread(rw, data, length, 1); SDL_RWclose(rw); return true; } -void Sample::Unload() +void Source_Sample::Unload() { if (data) { if (issdlwav) { @@ -127,16 +175,11 @@ void Sample::Unload() length = 0; } -bool Sample::Loaded() +bool Source_Sample::Convert(AudioFormat format) { - return data != 0; -} - -bool Sample::Convert(AudioFormat format) -{ - if(Sample::format.format != format.format || Sample::format.channels != format.channels || Sample::format.freq != format.freq){ + if(Source_Sample::format.format != format.format || Source_Sample::format.channels != format.channels || Source_Sample::format.freq != format.freq){ SDL_AudioCVT cvt; - if (SDL_BuildAudioCVT(&cvt, Sample::format.format, Sample::format.channels, Sample::format.freq, format.format, format.channels, format.freq) < 0) { + if (SDL_BuildAudioCVT(&cvt, Source_Sample::format.format, Source_Sample::format.channels, Source_Sample::format.freq, format.format, format.channels, format.freq) < 0) { return false; } cvt.len = length; @@ -149,69 +192,147 @@ bool Sample::Convert(AudioFormat format) Unload(); data = cvt.buf; length = cvt.len_cvt; - Sample::format = format; + Source_Sample::format = format; return true; } return false; } -const uint8* Sample::Data() +Source_SampleStream::Source_SampleStream() { - return data; + length = 0; + rw = NULL; + buffer = 0; + buffersize = 0; } -unsigned long Sample::Length() +Source_SampleStream::~Source_SampleStream() { - return length; + Unload(); } -Stream::Stream() +unsigned long Source_SampleStream::Read(unsigned long offset, const uint8** data, unsigned long length) { - sourcetype = SOURCE_NONE; + if (length > buffersize) { + if (buffer) { + delete[] buffer; + } + buffer = new (std::nothrow) uint8[length]; + if (!buffer) { + return 0; + } + buffersize = length; + } + Sint64 currentposition = SDL_RWtell(rw); + if (currentposition == -1) { + return 0; + } + if (currentposition - databegin != offset) { + Sint64 newposition = SDL_RWseek(rw, databegin + offset, SEEK_SET); + if (newposition == -1) { + return 0; + } + currentposition = newposition; + } + *data = buffer; + int read = SDL_RWread(rw, buffer, 1, length); + if (read == -1) { + return 0; + } + return read; } -unsigned long Stream::GetSome(unsigned long offset, const uint8** data, unsigned long length) +bool Source_SampleStream::LoadWAV(SDL_RWops* rw) { - unsigned long size = length; - switch(sourcetype) { - case SOURCE_SAMPLE: - if (offset >= sample->Length()) { - return 0; - } - if (offset + length > sample->Length()) { - size = sample->Length() - offset; - } - *data = &sample->Data()[offset]; - return size; - break; + Unload(); + if (rw == NULL) { + return false; + } + Source_SampleStream::rw = rw; + Uint32 chunk_id = SDL_ReadLE32(rw); + const Uint32 RIFF = 0x46464952; + if (chunk_id != RIFF) { + log_verbose("Not a WAV file"); + return false; + } + Uint32 chunk_size = SDL_ReadLE32(rw); + Uint32 chunk_format = SDL_ReadLE32(rw); + const Uint32 WAVE = 0x45564157; + if (chunk_format != WAVE) { + log_verbose("Not in WAVE format"); + return false; + } + const Uint32 FMT = 0x20746D66; + Uint32 fmtchunk_size = FindChunk(rw, FMT); + if (!fmtchunk_size) { + log_verbose("Could not find FMT chunk"); + return false; + } + PCMWAVEFORMAT waveformat; + SDL_RWread(rw, &waveformat, sizeof(waveformat), 1); + if (waveformat.wf.wFormatTag != WAVE_FORMAT_PCM) { + log_verbose("Not in proper format"); + return false; + } + format.freq = waveformat.wf.nSamplesPerSec; + switch (waveformat.wBitsPerSample) { + case 8: + format.format = AUDIO_U8; + break; + case 16: + format.format = AUDIO_S16LSB; + break; + default: + log_verbose("Invalid bits per sample"); + return false; + break; + } + format.channels = waveformat.wf.nChannels; + const Uint32 DATA = 0x61746164; + Uint32 datachunk_size = FindChunk(rw, DATA); + if (!datachunk_size) { + log_verbose("Could not find DATA chunk"); + return false; + } + length = datachunk_size; + databegin = SDL_RWtell(rw); + return true; +} + +Uint32 Source_SampleStream::FindChunk(SDL_RWops* rw, Uint32 wanted_id) +{ + Uint32 subchunk_id = SDL_ReadLE32(rw); + Uint32 subchunk_size = SDL_ReadLE32(rw); + if (subchunk_id == wanted_id) { + return subchunk_size; + } + const Uint32 FACT = 0x74636166; + const Uint32 LIST = 0x5453494c; + const Uint32 BEXT = 0x74786562; + const Uint32 JUNK = 0x4B4E554A; + while (subchunk_id == FACT || subchunk_id == LIST || subchunk_id == BEXT || subchunk_id == JUNK) { + SDL_RWseek(rw, subchunk_size, RW_SEEK_CUR); + subchunk_id = SDL_ReadLE32(rw); + subchunk_size = SDL_ReadLE32(rw); + if (subchunk_id == wanted_id) { + return subchunk_size; + } } return 0; } -unsigned long Stream::Length() +void Source_SampleStream::Unload() { - switch(sourcetype) { - case SOURCE_SAMPLE: - return sample->Length(); - break; + if (rw) { + SDL_RWclose(rw); + rw = NULL; } - return 0; -} - -void Stream::SetSource_Sample(Sample& sample) -{ - sourcetype = SOURCE_SAMPLE; - Stream::sample = &sample; -} - -const AudioFormat* Stream::Format() -{ - switch(sourcetype) { - case SOURCE_SAMPLE: - return &sample->format; - break; + length = 0; + if (buffer) { + delete[] buffer; + buffer = 0; } - return 0; + buffersize = 0; } Channel::Channel() @@ -223,7 +344,8 @@ Channel::Channel() SetPan(0.5f); done = true; stopping = false; - stream = 0; + source = 0; + deletesourceondone = false; } Channel::~Channel() @@ -232,11 +354,14 @@ Channel::~Channel() speex_resampler_destroy(resampler); resampler = 0; } + if (deletesourceondone) { + delete source; + } } -void Channel::Play(Stream& stream, int loop = MIXER_LOOP_NONE) +void Channel::Play(Source& source, int loop = MIXER_LOOP_NONE) { - Channel::stream = &stream; + Channel::source = &source; Channel::loop = loop; offset = 0; done = false; @@ -286,14 +411,25 @@ unsigned long Channel::GetOffset() bool Channel::SetOffset(unsigned long offset) { - if (stream && offset < stream->Length()) { - int samplesize = stream->Format()->channels * stream->Format()->BytesPerSample(); + if (source && offset < source->Length()) { + int samplesize = source->Format().channels * source->Format().BytesPerSample(); Channel::offset = (offset / samplesize) * samplesize; return true; } return false; } +Mixer::Mixer() +{ + effectbuffer = 0; + for (int i = 0; i < countof(css1sources); i++) { + css1sources[i] = 0; + } + for (int i = 0; i < countof(musicsources); i++) { + musicsources[i] = 0; + } +} + void Mixer::Init(const char* device) { Close(); @@ -310,10 +446,15 @@ void Mixer::Init(const char* device) format.channels = have.channels; format.freq = have.freq; const char* filename = get_file_path(PATH_ID_CSS1); - for (int i = 0; i < SOUND_MAXID; i++) { - css1samples[i].LoadCSS1(filename, i); - css1samples[i].Convert(format); // convert to audio output format, saves some cpu usage but requires a bit more memory, optional - css1streams[i].SetSource_Sample(css1samples[i]); + for (int i = 0; i < countof(css1sources); i++) { + Source_Sample* source_sample = new Source_Sample; + if (source_sample->LoadCSS1(filename, i)) { + source_sample->Convert(format); // convert to audio output format, saves some cpu usage but requires a bit more memory, optional + css1sources[i] = source_sample; + } else { + css1sources[i] = &source_null; + delete source_sample; + } } effectbuffer = new uint8[(have.samples * format.BytesPerSample() * format.channels)]; SDL_PauseAudioDevice(deviceid, 0); @@ -328,7 +469,22 @@ void Mixer::Close() } Unlock(); SDL_CloseAudioDevice(deviceid); - delete[] effectbuffer; + for (int i = 0; i < countof(css1sources); i++) { + if (css1sources[i] && css1sources[i] != &source_null) { + delete css1sources[i]; + css1sources[i] = 0; + } + } + for (int i = 0; i < countof(musicsources); i++) { + if (musicsources[i] && musicsources[i] != &source_null) { + delete musicsources[i]; + musicsources[i] = 0; + } + } + if (effectbuffer) { + delete[] effectbuffer; + effectbuffer = 0; + } } void Mixer::Lock() @@ -341,13 +497,14 @@ void Mixer::Unlock() SDL_UnlockAudioDevice(deviceid); } -Channel* Mixer::Play(Stream& stream, int loop, bool deleteondone) +Channel* Mixer::Play(Source& source, int loop, bool deleteondone, bool deletesourceondone) { Lock(); - Channel* newchannel = new (std::nothrow) Channel(); + Channel* newchannel = new (std::nothrow) Channel; if (newchannel) { - newchannel->Play(stream, loop); + newchannel->Play(source, loop); newchannel->deleteondone = deleteondone; + newchannel->deletesourceondone = deletesourceondone; newchannel->stopping = false; channels.push_back(newchannel); } @@ -364,13 +521,20 @@ void Mixer::Stop(Channel& channel) bool Mixer::LoadMusic(int pathid) { - if (pathid >= PATH_ID_END) { + if (pathid >= countof(musicsources)) { return false; } - if (!musicsamples[pathid].Loaded()) { + if (!musicsources[pathid]) { const char* filename = get_file_path(pathid); - musicstreams[pathid].SetSource_Sample(musicsamples[pathid]); - return musicsamples[pathid].Load(filename); + Source_Sample* source_sample = new Source_Sample; + if (source_sample->LoadWAV(filename)) { + musicsources[pathid] = source_sample; + return true; + } else { + delete source_sample; + musicsources[pathid] = &source_null; + return false; + } } else { return true; } @@ -394,8 +558,8 @@ void SDLCALL Mixer::Callback(void* arg, uint8* stream, int length) void Mixer::MixChannel(Channel& channel, uint8* data, int length) { - if (channel.stream && !channel.done) { - AudioFormat streamformat = *channel.stream->Format(); + if (channel.source && channel.source->Length() > 0 && !channel.done) { + AudioFormat streamformat = channel.source->Format(); int loaded = 0; SDL_AudioCVT cvt; cvt.len_ratio = 1; @@ -409,9 +573,9 @@ void Mixer::MixChannel(Channel& channel, uint8* data, int length) } int samplestoread = (int)((samples - samplesloaded) * rate); int lengthloaded = 0; - if (channel.offset < channel.stream->Length()) { + if (channel.offset < channel.source->Length()) { bool mustconvert = false; - if (MustConvert(*channel.stream)) { + if (MustConvert(*channel.source)) { if (SDL_BuildAudioCVT(&cvt, streamformat.format, streamformat.channels, streamformat.freq, Mixer::format.format, Mixer::format.channels, Mixer::format.freq) == -1) { break; } @@ -420,7 +584,7 @@ void Mixer::MixChannel(Channel& channel, uint8* data, int length) const uint8* datastream = 0; int toread = (int)(samplestoread / cvt.len_ratio) * samplesize; - int readfromstream = (channel.stream->GetSome(channel.offset, &datastream, toread)); + int readfromstream = (channel.source->GetSome(channel.offset, &datastream, toread)); if (readfromstream == 0) { break; } @@ -519,7 +683,7 @@ void Mixer::MixChannel(Channel& channel, uint8* data, int length) loaded += lengthloaded; - if (channel.loop != 0 && channel.offset >= channel.stream->Length()) { + if (channel.loop != 0 && channel.offset >= channel.source->Length()) { if (channel.loop != -1) { channel.loop--; } @@ -528,7 +692,7 @@ void Mixer::MixChannel(Channel& channel, uint8* data, int length) } while(loaded < length && channel.loop != 0 && !channel.stopping); channel.oldvolume = channel.volume; - if (channel.loop == 0 && channel.offset >= channel.stream->Length()) { + if (channel.loop == 0 && channel.offset >= channel.source->Length()) { channel.done = true; } } @@ -574,13 +738,10 @@ void Mixer::EffectFadeU8(uint8* data, int length, int startvolume, int endvolume } } -bool Mixer::MustConvert(Stream& stream) +bool Mixer::MustConvert(Source& source) { - const AudioFormat* streamformat = stream.Format(); - if (!streamformat) { - return false; - } - if (streamformat->format != format.format || streamformat->channels != format.channels || streamformat->freq != format.freq) { + const AudioFormat sourceformat = source.Format(); + if (sourceformat.format != format.format || sourceformat.channels != format.channels || sourceformat.freq != format.freq) { return true; } return false; @@ -609,11 +770,11 @@ void Mixer_Init(const char* device) void* Mixer_Play_Effect(int id, int loop, int volume, float pan, double rate, int deleteondone) { - if (id >= SOUND_MAXID) { + if (id >= countof(gMixer.css1sources)) { return 0; } gMixer.Lock(); - Channel* channel = gMixer.Play(gMixer.css1streams[id], loop, deleteondone != 0); + Channel* channel = gMixer.Play(*gMixer.css1sources[id], loop, deleteondone != 0, false); if (channel) { channel->SetVolume(volume); channel->SetPan(pan); @@ -664,10 +825,33 @@ int Mixer_Channel_SetOffset(void* channel, unsigned long offset) return ((Channel*)channel)->SetOffset(offset); } -void* Mixer_Play_Music(int pathid) +void* Mixer_Play_Music(int pathid, int streaming) { - if (gMixer.LoadMusic(pathid)) { - return gMixer.Play(gMixer.musicstreams[pathid], MIXER_LOOP_INFINITE, false); + if (streaming) { + const char* filename = get_file_path(pathid); + + utf8 utf8filename[512]; + win1252_to_utf8(utf8filename, filename, sizeof(utf8filename)); + + SDL_RWops* rw = SDL_RWFromFile(utf8filename, "rb"); + if (rw == NULL) { + return 0; + } + Source_SampleStream* source_samplestream = new Source_SampleStream; + if (source_samplestream->LoadWAV(rw)) { + Channel* channel = gMixer.Play(*source_samplestream, MIXER_LOOP_INFINITE, false, true); + if (!channel) { + delete source_samplestream; + } + return channel; + } else { + delete source_samplestream; + return 0; + } + } else { + if (gMixer.LoadMusic(pathid)) { + return gMixer.Play(*gMixer.musicsources[pathid], MIXER_LOOP_INFINITE, false, false); + } } return 0; } \ No newline at end of file diff --git a/src/audio/mixer.h b/src/audio/mixer.h index 6920986e92..e62dd3cad0 100644 --- a/src/audio/mixer.h +++ b/src/audio/mixer.h @@ -43,45 +43,73 @@ struct AudioFormat { int channels; }; -class Sample +class Source { public: - Sample(); - ~Sample(); - bool Load(const char* filename); - bool LoadCSS1(const char* filename, unsigned int offset); - void Unload(); - bool Loaded(); - bool Convert(AudioFormat format); - const uint8* Data(); - unsigned long Length(); - - friend class Stream; - -private: - AudioFormat format; - uint8* data; - unsigned long length; - bool issdlwav; -}; - -class Stream -{ -public: - Stream(); + virtual ~Source(); unsigned long GetSome(unsigned long offset, const uint8** data, unsigned long length); unsigned long Length(); - void SetSource_Sample(Sample& sample); - const AudioFormat* Format(); + const AudioFormat& Format(); friend class Mixer; +protected: + virtual unsigned long Read(unsigned long offset, const uint8** data, unsigned long length) = 0; + + AudioFormat format; + unsigned long length; +}; + +class Source_Null : public Source +{ +public: + Source_Null(); + +protected: + unsigned long Read(unsigned long offset, const uint8** data, unsigned long length); +}; + +class Source_Sample : public Source +{ +public: + Source_Sample(); + ~Source_Sample(); + bool LoadWAV(const char* filename); + bool LoadCSS1(const char* filename, unsigned int offset); + + friend class Mixer; + +protected: + bool Convert(AudioFormat format); + private: - enum { - SOURCE_NONE = 0, - SOURCE_SAMPLE - } sourcetype; - Sample* sample; + void Unload(); + + uint8* data; + bool issdlwav; + +protected: + unsigned long Read(unsigned long offset, const uint8** data, unsigned long length); +}; + +class Source_SampleStream : public Source +{ +public: + Source_SampleStream(); + ~Source_SampleStream(); + bool LoadWAV(SDL_RWops* rw); + +private: + Uint32 FindChunk(SDL_RWops* rw, Uint32 wanted_id); + void Unload(); + + SDL_RWops* rw; + Uint64 databegin; + uint8* buffer; + unsigned long buffersize; + +protected: + unsigned long Read(unsigned long offset, const uint8** data, unsigned long length); }; class Channel @@ -89,7 +117,7 @@ class Channel public: Channel(); ~Channel(); - void Play(Stream& stream, int loop); + void Play(Source& source, int loop); void SetRate(double rate); void SetVolume(int volume); void SetPan(float pan); @@ -108,25 +136,27 @@ private: float pan; bool done; bool deleteondone; + bool deletesourceondone; bool stopping; int oldvolume; SpeexResamplerState* resampler; - Stream* stream; + Source* source; }; class Mixer { public: + Mixer(); void Init(const char* device); void Close(); void Lock(); void Unlock(); - Channel* Play(Stream& stream, int loop, bool deleteondone); + Channel* Play(Source& source, int loop, bool deleteondone, bool deletesourceondone); void Stop(Channel& channel); bool LoadMusic(int pathid); - Stream css1streams[SOUND_MAXID]; - Stream musicstreams[PATH_ID_END]; + Source* css1sources[SOUND_MAXID]; + Source* musicsources[PATH_ID_END]; private: static void SDLCALL Callback(void* arg, uint8* data, int length); @@ -135,14 +165,13 @@ private: void EffectPanU8(Channel& channel, uint8* data, int length); void EffectFadeS16(sint16* data, int length, int startvolume, int endvolume); void EffectFadeU8(uint8* data, int length, int startvolume, int endvolume); - bool MustConvert(Stream& stream); + bool MustConvert(Source& source); bool Convert(SDL_AudioCVT& cvt, const uint8* data, unsigned long length, uint8** dataout); SDL_AudioDeviceID deviceid; AudioFormat format; uint8* effectbuffer; - Sample css1samples[SOUND_MAXID]; - Sample musicsamples[PATH_ID_END]; std::list channels; + Source_Null source_null; }; extern "C" @@ -158,7 +187,7 @@ void Mixer_Channel_Rate(void* channel, double rate); int Mixer_Channel_IsPlaying(void* channel); unsigned long Mixer_Channel_GetOffset(void* channel); int Mixer_Channel_SetOffset(void* channel, unsigned long offset); -void* Mixer_Play_Music(int pathid); +void* Mixer_Play_Music(int pathid, int streaming); static int DStoMixerVolume(int volume) { return (int)(SDL_MIX_MAXVOLUME * (SDL_pow(10, (float)volume / 2000))); }; static float DStoMixerPan(int pan) { return (((float)pan + -DSBPAN_LEFT) / DSBPAN_RIGHT) / 2; }; diff --git a/src/localisation/string_ids.h b/src/localisation/string_ids.h index 302e2c8ac2..eca3eac66f 100644 --- a/src/localisation/string_ids.h +++ b/src/localisation/string_ids.h @@ -192,6 +192,8 @@ enum { STR_LOCATE_SUBJECT_TIP = 1027, STR_OFF_EDGE_OF_MAP = 1028, + STR_CAN_ONLY_BUILD_THIS_ON_LAND = 1034, + STR_LOAD_GAME_DIALOG_TITLE = 1036, STR_LOAD_LANDSCAPE_DIALOG_TITLE = 1037, STR_CONVERT_SAVED_GAME_TO_SCENARIO_1038 = 1038, @@ -378,6 +380,7 @@ enum { STR_SHOPS_STALLS_TIP = 1228, STR_ROTATE_OBJECTS_90 = 1327, + STR_LEVEL_LAND_REQUIRED = 1328, STR_LAUNCH_SPEED = 1329, STR_LAUNCH_SPEED_TIP = 1330, diff --git a/src/peep/peep.c b/src/peep/peep.c index 03ff279fba..779273b61a 100644 --- a/src/peep/peep.c +++ b/src/peep/peep.c @@ -4577,7 +4577,7 @@ void peep_update_crowd_noise() // Load and play crowd noise #ifdef USE_MIXER if (!gCrowdSoundChannel) { - gCrowdSoundChannel = Mixer_Play_Music(PATH_ID_CSS2); + gCrowdSoundChannel = Mixer_Play_Music(PATH_ID_CSS2, false); } if (gCrowdSoundChannel) { Mixer_Channel_Volume(gCrowdSoundChannel, DStoMixerVolume(volume)); diff --git a/src/ride/ride.c b/src/ride/ride.c index 9297e89837..a703dbf104 100644 --- a/src/ride/ride.c +++ b/src/ride/ride.c @@ -2662,7 +2662,7 @@ void ride_music_update_final() rct_ride_music_info* ride_music_info = &RCT2_GLOBAL(0x009AF1C8, rct_ride_music_info*)[ride_music_params->tuneid]; #ifdef USE_MIXER rct_ride_music* ride_music = &gRideMusicList[ebx]; - ride_music->sound_channel = Mixer_Play_Music(ride_music_info->pathid); + ride_music->sound_channel = Mixer_Play_Music(ride_music_info->pathid, true); if (ride_music->sound_channel) { ride_music->volume = ride_music_params->volume; ride_music->pan = ride_music_params->pan; @@ -2678,7 +2678,7 @@ void ride_music_update_final() } Mixer_Channel_SetOffset(ride_music->sound_channel, offset); } else { - RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_MUSIC, uint8) = 0; + //RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_MUSIC, uint8) = 0; } #else const char* filename = get_file_path(ride_music_info->pathid); diff --git a/src/windows/top_toolbar.c b/src/windows/top_toolbar.c index 887915cb48..b6c111e634 100644 --- a/src/windows/top_toolbar.c +++ b/src/windows/top_toolbar.c @@ -1416,11 +1416,11 @@ static void window_top_toolbar_scenery_tool_down(short x, short y, rct_window* w int cost; { - int esi = 0, eax = grid_x, ecx = grid_y, edx = grid_z; - game_do_command_p(GAME_COMMAND_PLACE_BANNER, &eax, &ebx, &ecx, &edx, &esi, &banner_id, &ebp); + int esi = 0, eax = grid_x, ecx = grid_y, edx = parameter_2, ebx = (parameter_1 & 0xFF00) | 1; + cost = game_do_command_p(GAME_COMMAND_PLACE_BANNER, &eax, &ebx, &ecx, &edx, &esi, &banner_id, &ebp); } - if (ebx == MONEY32_UNDEFINED)return; + if (cost == MONEY32_UNDEFINED)return; sound_play_panned(SOUND_PLACE_ITEM, 0x8001, RCT2_GLOBAL(0x009DEA5E, uint16), RCT2_GLOBAL(0x009DEA60, uint16), RCT2_GLOBAL(0x009DEA62, uint16)); diff --git a/src/world/footpath.h b/src/world/footpath.h index 86574919b5..3745ae05d2 100644 --- a/src/world/footpath.h +++ b/src/world/footpath.h @@ -48,5 +48,6 @@ void footpath_provisional_remove(); void footpath_provisional_update(); void footpath_get_coordinates_from_pos(int screenX, int screenY, int *x, int *y, int *direction, rct_map_element **mapElement); void footpath_bridge_get_info_from_pos(int screenX, int screenY, int *x, int *y, int *direction, rct_map_element **mapElement); +void sub_673883(int x, int y, int z); #endif diff --git a/src/world/map.c b/src/world/map.c index a98612d2e6..13f898ce79 100644 --- a/src/world/map.c +++ b/src/world/map.c @@ -28,6 +28,7 @@ #include "../scenario.h" #include "banner.h" #include "climate.h" +#include "footpath.h" #include "map.h" #include "map_animation.h" #include "park.h" @@ -905,7 +906,7 @@ void game_command_set_fence_colour(int* eax, int* ebx, int* ecx, int* edx, int* return; } if(*ebx & GAME_COMMAND_FLAG_APPLY){ - rct_scenery_entry* scenery_entry = RCT2_ADDRESS(RCT2_ADDRESS_WALL_SCENERY_ENTRIES, rct_scenery_entry*)[map_element->properties.fence.slope]; + rct_scenery_entry* scenery_entry = RCT2_ADDRESS(RCT2_ADDRESS_WALL_SCENERY_ENTRIES, rct_scenery_entry*)[map_element->properties.fence.type]; map_element->properties.fence.item[1] &= 0xE0; map_element->properties.fence.item[1] |= color1; map_element->flags &= 0x9F; @@ -1655,7 +1656,7 @@ void game_command_remove_fence(int* eax, int* ebx, int* ecx, int* edx, int* esi, return; } } - rct_scenery_entry* scenery_entry = RCT2_ADDRESS(RCT2_ADDRESS_WALL_SCENERY_ENTRIES, rct_scenery_entry*)[map_element->properties.fence.slope]; + rct_scenery_entry* scenery_entry = RCT2_ADDRESS(RCT2_ADDRESS_WALL_SCENERY_ENTRIES, rct_scenery_entry*)[map_element->properties.fence.type]; if(scenery_entry->wall.var_0D != 0xFF){ rct_banner* banner = &gBanners[map_element->properties.fence.item[0]]; if(banner->type != BANNER_NULL){ diff --git a/src/world/scenery.c b/src/world/scenery.c index eeb1cb68c3..3a05927927 100644 --- a/src/world/scenery.c +++ b/src/world/scenery.c @@ -178,7 +178,7 @@ void scenery_remove_ghost_tool_placement(){ 105 | (RCT2_GLOBAL(0x00F64EC0, uint8) << 8), y, z, - GAME_COMMAND_44, + GAME_COMMAND_REMOVE_LARGE_SCENERY, 0, 0); } @@ -191,7 +191,7 @@ void scenery_remove_ghost_tool_placement(){ 105, y, z | (RCT2_GLOBAL(0x00F64EC0, uint8) << 8), - GAME_COMMAND_51, + GAME_COMMAND_REMOVE_BANNER, 0, 0); } diff --git a/src/world/scenery.h b/src/world/scenery.h index 7b4765f1e7..3d2e6a98e9 100644 --- a/src/world/scenery.h +++ b/src/world/scenery.h @@ -56,6 +56,12 @@ typedef enum { SMALL_SCENERY_FLAG18 = (1 << 17), // 0x20000 SMALL_SCENERY_FLAG19 = (1 << 18), // 0x40000 SMALL_SCENERY_FLAG_HAS_SECONDARY_COLOUR = (1 << 19), // 0x80000 + SMALL_SCENERY_FLAG20 = (1 << 20), // 0x100000 + SMALL_SCENERY_FLAG21 = (1 << 21), // 0x200000 + SMALL_SCENERY_FLAG22 = (1 << 22), // 0x400000 + SMALL_SCENERY_FLAG23 = (1 << 23), // 0x800000 + SMALL_SCENERY_FLAG24 = (1 << 24), // 0x1000000 + SMALL_SCENERY_FLAG25 = (1 << 25), // 0x2000000 } SMALL_SCENERY_FLAGS; typedef struct {