From 4c26ee2c407f111c81b1810072294c30425ef0a2 Mon Sep 17 00:00:00 2001 From: Nikhil Narayana Date: Sat, 19 Aug 2023 11:59:52 -0700 Subject: [PATCH] music controlled by asm and jukebox volume slider --- Data/Sys/GameFiles/GALE01/GameSetup.dat | Bin 27379 -> 27395 bytes Data/Sys/GameSettings/GALE01r2.ini | 67 ++++++++++++++++-- Data/Sys/GameSettings/GALJ01r2.ini | 67 ++++++++++++++++-- Data/Sys/GameSettings/Netplay/GALE01r2.ini | 67 ++++++++++++++++-- Data/Sys/GameSettings/Netplay/GALJ01r2.ini | 67 ++++++++++++++++-- Externals/SlippiRustExtensions | 2 +- Source/Core/AudioCommon/AudioCommon.cpp | 6 -- Source/Core/AudioCommon/AudioCommon.h | 11 --- Source/Core/Core/HW/EXI/EXI_DeviceSlippi.cpp | 43 ++++++++--- Source/Core/Core/HW/EXI/EXI_DeviceSlippi.h | 9 +++ Source/Core/Core/Slippi/SlippiExiTypes.h | 22 ++++++ Source/Core/DolphinQt/Settings/AudioPane.cpp | 18 +++++ .../Core/DolphinQt/Settings/GameCubePane.cpp | 2 + Source/Core/DolphinQt/Settings/SlippiPane.cpp | 22 +++++- 14 files changed, 353 insertions(+), 50 deletions(-) diff --git a/Data/Sys/GameFiles/GALE01/GameSetup.dat b/Data/Sys/GameFiles/GALE01/GameSetup.dat index 2f6672becddf40047a98a5b3db117c1e950778cb..e693e82538f450824747c0ef56d278f37459337a 100644 GIT binary patch delta 5363 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[bufLoc]); + slprs_jukebox_start_song(slprs_exi_device_ptr, args.offset, args.size); + break; + } + case CMD_STOP_MUSIC: + slprs_jukebox_stop_music(slprs_exi_device_ptr); + break; + case CMD_CHANGE_MUSIC_VOLUME: + { + auto args = SlippiExiTypes::Convert(&memPtr[bufLoc]); + slprs_jukebox_set_melee_music_volume(slprs_exi_device_ptr, args.volume); + break; + } default: writeToFileAsync(&memPtr[bufLoc], payloadLen + 1, ""); SlippiSpectateServer::getInstance().write(&memPtr[bufLoc], payloadLen + 1); @@ -3291,14 +3301,27 @@ void CEXISlippi::ConfigureJukebox() } #endif - auto& system = Core::System::GetInstance(); + int dolphin_system_volume = + Config::Get(Config::MAIN_AUDIO_MUTED) ? 0 : Config::Get(Config::MAIN_AUDIO_VOLUME); - slprs_exi_device_configure_jukebox( - slprs_exi_device_ptr, Config::Get(Config::SLIPPI_ENABLE_JUKEBOX), system.GetMemory().GetRAM(), - AudioCommonGetCurrentVolume, GetJukeboxVolume); + int dolphin_music_volume = Config::Get(Config::SLIPPI_JUKEBOX_VOLUME); + + slprs_exi_device_configure_jukebox(slprs_exi_device_ptr, + Config::Get(Config::SLIPPI_ENABLE_JUKEBOX), + dolphin_system_volume, dolphin_music_volume); #endif } +void CEXISlippi::UpdateJukeboxDolphinSystemVolume(int volume) +{ + slprs_jukebox_set_dolphin_system_volume(slprs_exi_device_ptr, volume); +} + +void CEXISlippi::UpdateJukeboxDolphinMusicVolume(int volume) +{ + slprs_jukebox_set_dolphin_music_volume(slprs_exi_device_ptr, volume); +} + bool CEXISlippi::IsPresent() const { return true; diff --git a/Source/Core/Core/HW/EXI/EXI_DeviceSlippi.h b/Source/Core/Core/HW/EXI/EXI_DeviceSlippi.h index 2083eacd39..5d0a0cb96e 100644 --- a/Source/Core/Core/HW/EXI/EXI_DeviceSlippi.h +++ b/Source/Core/Core/HW/EXI/EXI_DeviceSlippi.h @@ -38,6 +38,8 @@ public: void DMARead(u32 addr, u32 size) override; void ConfigureJukebox(); + void UpdateJukeboxDolphinSystemVolume(int volume); + void UpdateJukeboxDolphinMusicVolume(int volume); bool IsPresent() const override; @@ -91,6 +93,9 @@ private: CMD_GCT_LENGTH = 0xD3, CMD_GCT_LOAD = 0xD4, CMD_GET_DELAY = 0xD5, + CMD_PLAY_MUSIC = 0xD6, + CMD_STOP_MUSIC = 0xD7, + CMD_CHANGE_MUSIC_VOLUME = 0xD8, CMD_PREMADE_TEXT_LENGTH = 0xE1, CMD_PREMADE_TEXT_LOAD = 0xE2, }; @@ -149,6 +154,10 @@ private: {CMD_GCT_LENGTH, 0x0}, {CMD_GCT_LOAD, 0x4}, {CMD_GET_DELAY, 0x0}, + {CMD_PLAY_MUSIC, static_cast(sizeof(SlippiExiTypes::PlayMusicQuery) - 1)}, + {CMD_STOP_MUSIC, 0x0}, + {CMD_CHANGE_MUSIC_VOLUME, + static_cast(sizeof(SlippiExiTypes::ChangeMusicVolumeQuery) - 1)}, {CMD_PREMADE_TEXT_LENGTH, 0x2}, {CMD_PREMADE_TEXT_LOAD, 0x2}, }; diff --git a/Source/Core/Core/Slippi/SlippiExiTypes.h b/Source/Core/Core/Slippi/SlippiExiTypes.h index bcae0e6f13..beaaab2a7c 100644 --- a/Source/Core/Core/Slippi/SlippiExiTypes.h +++ b/Source/Core/Core/Slippi/SlippiExiTypes.h @@ -89,6 +89,19 @@ struct GetPlayerSettingsResponse PlayerSettings settings[4]; }; +struct PlayMusicQuery +{ + u8 command; + u32 offset; + u32 size; +}; + +struct ChangeMusicVolumeQuery +{ + u8 command; + u8 volume; +}; + // Not sure if resetting is strictly needed, might be contained to the file #pragma pack() @@ -125,4 +138,13 @@ inline OverwriteSelectionsQuery Convert(u8* payload) q.stage_id = Common::FromBigEndian(q.stage_id); return q; } + +template <> +inline PlayMusicQuery Convert(u8* payload) +{ + auto q = *reinterpret_cast(payload); + q.offset = Common::FromBigEndian(q.offset); + q.size = Common::FromBigEndian(q.size); + return q; +} }; // namespace SlippiExiTypes diff --git a/Source/Core/DolphinQt/Settings/AudioPane.cpp b/Source/Core/DolphinQt/Settings/AudioPane.cpp index 8855c50d40..c49a64deea 100644 --- a/Source/Core/DolphinQt/Settings/AudioPane.cpp +++ b/Source/Core/DolphinQt/Settings/AudioPane.cpp @@ -28,6 +28,11 @@ #include "DolphinQt/Config/SettingsWindow.h" #include "DolphinQt/Settings.h" +#ifndef IS_PLAYBACK +#include "Core/HW/EXI/EXI.h" +#include "Core/HW/EXI/EXI_DeviceSlippi.h" +#endif + AudioPane::AudioPane() { CheckNeedForLatencyControl(); @@ -406,6 +411,19 @@ void AudioPane::OnVolumeChanged(int volume) { m_volume_slider->setValue(volume); m_volume_indicator->setText(tr("%1%").arg(volume)); + +#ifndef IS_PLAYBACK + if (Core::GetState() == Core::State::Running) + { + auto& system = Core::System::GetInstance(); + auto& exi_manager = system.GetExpansionInterface(); + ExpansionInterface::CEXISlippi* slippi_exi = static_cast( + exi_manager.GetDevice(ExpansionInterface::Slot::B)); + + if (slippi_exi != nullptr) + slippi_exi->UpdateJukeboxDolphinSystemVolume(volume); + } +#endif } void AudioPane::CheckNeedForLatencyControl() diff --git a/Source/Core/DolphinQt/Settings/GameCubePane.cpp b/Source/Core/DolphinQt/Settings/GameCubePane.cpp index 34ee3697c5..b0301320f4 100644 --- a/Source/Core/DolphinQt/Settings/GameCubePane.cpp +++ b/Source/Core/DolphinQt/Settings/GameCubePane.cpp @@ -102,6 +102,8 @@ void GameCubePane::CreateWidgets() m_slot_buttons[slot]->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); } + m_slot_combos[ExpansionInterface::Slot::B]->setDisabled(true); + for (ExpansionInterface::Slot slot : ExpansionInterface::MEMCARD_SLOTS) { m_memcard_path_layouts[slot] = new QHBoxLayout(); diff --git a/Source/Core/DolphinQt/Settings/SlippiPane.cpp b/Source/Core/DolphinQt/Settings/SlippiPane.cpp index 357d4e03cc..470d5cc215 100644 --- a/Source/Core/DolphinQt/Settings/SlippiPane.cpp +++ b/Source/Core/DolphinQt/Settings/SlippiPane.cpp @@ -9,12 +9,12 @@ #include "Core/Config/MainSettings.h" #include "Core/ConfigManager.h" #include "Core/Core.h" -#include "Core/HW/EXI/EXI.h" #include "Core/System.h" #include "DolphinQt/QtUtils/NonDefaultQPushButton.h" #ifndef IS_PLAYBACK +#include "Core/HW/EXI/EXI.h" #include "Core/HW/EXI/EXI_DeviceSlippi.h" #include "SlippiPane.h" #endif @@ -161,7 +161,7 @@ void SlippiPane::CreateLayout() m_music_volume_percent->setFixedWidth(40); sfx_music_slider_layout->addWidget(music_volume_label, 1, 0); - sfx_music_slider_layout->addWidget(m_music_volume_slider, 1, 1); + sfx_music_slider_layout->addWidget(m_music_volume_slider, 1, 1, Qt::AlignVCenter); sfx_music_slider_layout->addWidget(m_music_volume_percent, 1, 2); jukebox_settings_layout->addLayout(sfx_music_slider_layout); @@ -190,6 +190,7 @@ void SlippiPane::CreateLayout() void SlippiPane::LoadConfig() { +#ifndef IS_PLAYBACK // Replay Settings auto save_replays = Config::Get(Config::SLIPPI_SAVE_REPLAYS); m_save_replays->setChecked(save_replays); @@ -219,10 +220,14 @@ void SlippiPane::LoadConfig() m_music_volume_percent->setText(tr(" %1%").arg(jukebox_volume)); m_music_volume_slider->setDisabled(!enable_jukebox); +#else + // HOOKUP PLAYBACK STUFF +#endif } void SlippiPane::ConnectLayout() { +#ifndef IS_PLAYBACK // Replay Settings connect(m_save_replays, &QCheckBox::toggled, this, &SlippiPane::SetSaveReplays); connect(m_monthly_replay_folders, &QCheckBox::toggled, this, @@ -244,6 +249,9 @@ void SlippiPane::ConnectLayout() connect(m_enable_jukebox, &QCheckBox::toggled, this, &SlippiPane::ToggleJukebox); connect(m_music_volume_slider, qOverload(&QSlider::valueChanged), this, &SlippiPane::OnMusicVolumeUpdate); +#else + // HOOKUP PLAYBACK STUFF +#endif } void SlippiPane::SetSaveReplays(bool checked) @@ -293,6 +301,16 @@ void SlippiPane::OnMusicVolumeUpdate(int volume) { Config::SetBase(Config::SLIPPI_JUKEBOX_VOLUME, volume); m_music_volume_percent->setText(tr(" %1%").arg(volume)); + if (Core::GetState() == Core::State::Running) + { + auto& system = Core::System::GetInstance(); + auto& exi_manager = system.GetExpansionInterface(); + ExpansionInterface::CEXISlippi* slippi_exi = static_cast( + exi_manager.GetDevice(ExpansionInterface::Slot::B)); + + if (slippi_exi != nullptr) + slippi_exi->UpdateJukeboxDolphinMusicVolume(volume); + } } void SlippiPane::OnSaveConfig()