From e283a643b3f80bc8c2c7dd0fb51e117fc84f31a1 Mon Sep 17 00:00:00 2001 From: Muzychenko Andrey <33288308+k4zmu2a@users.noreply.github.com> Date: Fri, 20 May 2022 19:32:09 +0300 Subject: [PATCH] Added support for multiple music tracks in FT mode. Note that taba3 is not currently played as it needs multiball support. Issue #129. --- SpaceCadetPinball/TPinballTable.cpp | 3 ++ SpaceCadetPinball/control.cpp | 13 ++++++++ SpaceCadetPinball/midi.cpp | 46 ++++++++++++++++++----------- SpaceCadetPinball/midi.h | 19 ++++++++---- SpaceCadetPinball/options.cpp | 2 +- SpaceCadetPinball/pb.cpp | 4 +-- SpaceCadetPinball/winmain.cpp | 2 +- 7 files changed, 63 insertions(+), 26 deletions(-) diff --git a/SpaceCadetPinball/TPinballTable.cpp b/SpaceCadetPinball/TPinballTable.cpp index 86e55ea..11fdafe 100644 --- a/SpaceCadetPinball/TPinballTable.cpp +++ b/SpaceCadetPinball/TPinballTable.cpp @@ -4,6 +4,7 @@ #include "control.h" #include "loader.h" +#include "midi.h" #include "pb.h" #include "pinball.h" #include "render.h" @@ -448,6 +449,8 @@ int TPinballTable::Message(int code, float value) auto time = loader::play_sound(SoundIndex1); LightShowTimer = timer::set(time, this, LightShow_timeout); } + + midi::play_track(midi::track1); break; case 1018: if (ReplayTimer) diff --git a/SpaceCadetPinball/control.cpp b/SpaceCadetPinball/control.cpp index 8747dd9..5d4dfe8 100644 --- a/SpaceCadetPinball/control.cpp +++ b/SpaceCadetPinball/control.cpp @@ -1,6 +1,7 @@ #include "pch.h" #include "control.h" +#include "midi.h" #include "pb.h" #include "pinball.h" #include "TBlocker.h" @@ -967,6 +968,8 @@ void control::table_set_flag_lights() void control::table_set_multiball() { info_text_box->Display(pinball::get_rc_string(16, 0), 2.0); + if (midi::get_active_track() != midi::track3) + midi::play_track(midi::track3); } void control::table_bump_ball_sink_lock() @@ -2572,6 +2575,8 @@ void control::BallDrainControl(int code, TPinballComponent* caller) { lite200->Message(20, 0.0); lite199->Message(20, 0.0); + if (midi::get_active_track() != midi::track1) + midi::play_track(midi::track1); } if (light_on(&control_lite200_tag)) { @@ -3102,6 +3107,8 @@ void control::GameoverController(int code, TPinballComponent* caller) flip1->Message(1022, 0.0); flip2->Message(1022, 0.0); mission_text_box->MessageField = 0; + if (midi::get_active_track() != midi::track1) + midi::play_track(midi::track1); return; } if (code != 67) @@ -4008,6 +4015,8 @@ void control::SelectMissionController(int code, TPinballComponent* caller) int addedScore = SpecialAddScore(mission_select_scores[scoreId]); snprintf(Buffer, sizeof Buffer, pinball::get_rc_string(77, 0), addedScore); mission_text_box->Display(Buffer, 4.0); + if (midi::get_active_track() != midi::track2) + midi::play_track(midi::track2); } return; } @@ -4121,6 +4130,8 @@ void control::SelectMissionController(int code, TPinballComponent* caller) return; } case 66: + if (midi::get_active_track() != midi::track1) + midi::play_track(midi::track1); lite198->Message(20, 0.0); outer_circle->Message(34, 0.0); ramp_tgt_lights->Message(20, 0.0); @@ -4408,6 +4419,8 @@ void control::WaitingDeploymentController(int code, TPinballComponent* caller) case 66: mission_text_box->Clear(); waiting_deployment_flag = 0; + if (midi::get_active_track() != midi::track1) + midi::play_track(midi::track1); break; case 67: mission_text_box->Display(pinball::get_rc_string(50, 0), -1.0); diff --git a/SpaceCadetPinball/midi.cpp b/SpaceCadetPinball/midi.cpp index f17c6d2..ad0b705 100644 --- a/SpaceCadetPinball/midi.cpp +++ b/SpaceCadetPinball/midi.cpp @@ -8,8 +8,8 @@ std::vector midi::LoadedTracks{}; Mix_Music *midi::track1, *midi::track2, *midi::track3, *midi::active_track, *midi::NextTrack; -bool midi::SetNextTrackFlag; int midi::Volume = MIX_MAX_VOLUME; +bool midi::IsPlaying = false; constexpr uint32_t FOURCC(uint8_t a, uint8_t b, uint8_t c, uint8_t d) { @@ -31,27 +31,41 @@ int ToVariableLen(uint32_t value, uint32_t& dst) return count; } -int midi::play_pb_theme() +void midi::music_play() { - // Todo: add support for tracks 2 and 3 - return play_track(track1); + if (!IsPlaying) + { + IsPlaying = true; + play_track(NextTrack); + NextTrack = nullptr; + } } -int midi::music_stop() +void midi::music_stop() { - if (active_track) + if (IsPlaying) { - active_track = nullptr; - Mix_HaltMusic(); + IsPlaying = false; + NextTrack = active_track; + StopPlayback(); } +} - return true; +void midi::StopPlayback() +{ + if (active_track != nullptr) + { + Mix_HaltMusic(); + active_track = nullptr; + } } int midi::music_init(int volume) { SetVolume(volume); active_track = nullptr; + NextTrack = nullptr; + IsPlaying = false; if (pb::FullTiltMode) { @@ -78,8 +92,7 @@ int midi::music_init(int volume) void midi::music_shutdown() { - if (active_track) - Mix_HaltMusic(); + music_stop(); for (auto midi : LoadedTracks) { @@ -105,7 +118,7 @@ Mix_Music* midi::load_track(std::string fileName) fileName.insert(0, "SOUND"); } - // FT has music in two formats, depending on version: MIDI in 16bit, MIDS in 32bit. + // FT has music in two formats, depending on game version: MIDI in 16bit, MIDS in 32bit. // 3DPB music is MIDI only. auto basePath = pinball::make_path_name(fileName); for (int i = 0; i <= 1 && !audio; i++) @@ -148,15 +161,14 @@ Mix_Music* midi::load_track(std::string fileName) bool midi::play_track(Mix_Music* midi) { - music_stop(); + StopPlayback(); if (!midi) return false; - if (SetNextTrackFlag) + if (!IsPlaying) { NextTrack = midi; - SetNextTrackFlag = false; - return true; + return false; } if (Mix_PlayMusic(midi, -1)) @@ -331,7 +343,7 @@ std::vector* midi::MdsToMidi(std::string file) while (false); delete[] fileBuf; - if (returnCode && midiOut) + if (returnCode && midiOut) { delete midiOut; midiOut = nullptr; diff --git a/SpaceCadetPinball/midi.h b/SpaceCadetPinball/midi.h index 864cbdc..d12686a 100644 --- a/SpaceCadetPinball/midi.h +++ b/SpaceCadetPinball/midi.h @@ -86,18 +86,27 @@ static_assert(sizeof(midi_track) == 8, "Wrong size of midi_track"); class midi { public: - static int play_pb_theme(); - static int music_stop(); + static Mix_Music * track1, * track2, * track3; + static void music_play(); + static void music_stop(); static int music_init(int volume); static void music_shutdown(); static void SetVolume(int volume); + static bool play_track(Mix_Music* midi); + static Mix_Music* get_active_track() + { + if (active_track == nullptr) + return NextTrack; + else + return active_track; + } private: static std::vector LoadedTracks; - static Mix_Music *track1, *track2, *track3, *active_track, *NextTrack; - static bool SetNextTrackFlag; + static Mix_Music *active_track, *NextTrack; static int Volume; + static bool IsPlaying; + static void StopPlayback(); static Mix_Music* load_track(std::string fileName); - static bool play_track(Mix_Music* midi); static std::vector* MdsToMidi(std::string file); }; diff --git a/SpaceCadetPinball/options.cpp b/SpaceCadetPinball/options.cpp index f0ebb5c..a14a19b 100644 --- a/SpaceCadetPinball/options.cpp +++ b/SpaceCadetPinball/options.cpp @@ -226,7 +226,7 @@ void options::toggle(Menu1 uIDCheckItem) if (!Options.Music) midi::music_stop(); else - midi::play_pb_theme(); + midi::music_play(); return; case Menu1::Show_Menu: Options.ShowMenu = Options.ShowMenu == 0; diff --git a/SpaceCadetPinball/pb.cpp b/SpaceCadetPinball/pb.cpp index 65c2fbc..1197a3e 100644 --- a/SpaceCadetPinball/pb.cpp +++ b/SpaceCadetPinball/pb.cpp @@ -232,7 +232,7 @@ void pb::replay_level(bool demoMode) demo_mode = demoMode; mode_change(GameModes::InGame); if (options::Options.Music) - midi::play_pb_theme(); + midi::music_play(); MainTable->Message(1014, static_cast(options::Options.Players)); } @@ -379,7 +379,7 @@ void pb::pause_continue() pinball::InfoTextBox->Display(text, textTime); } if (options::Options.Music && !winmain::single_step) - midi::play_pb_theme(); + midi::music_play(); Sound::Activate(); } } diff --git a/SpaceCadetPinball/winmain.cpp b/SpaceCadetPinball/winmain.cpp index 89e233a..1d733c5 100644 --- a/SpaceCadetPinball/winmain.cpp +++ b/SpaceCadetPinball/winmain.cpp @@ -813,7 +813,7 @@ int winmain::event_handler(const SDL_Event* event) activated = true; Sound::Activate(); if (Options.Music && !single_step) - midi::play_pb_theme(); + midi::music_play(); no_time_loss = true; has_focus = true; break;