diff --git a/src/xenia/app/emulator_window.cc b/src/xenia/app/emulator_window.cc index e04073454..6703272d9 100644 --- a/src/xenia/app/emulator_window.cc +++ b/src/xenia/app/emulator_window.cc @@ -490,6 +490,73 @@ void EmulatorWindow::EmulatorWindowListener::OnMouseDoubleClick( emulator_window_.OnMouseDoubleClick(e); } +void EmulatorWindow::XMPConfigDialog::OnDraw(ImGuiIO& io) { + // Center window horizontally, position in lower portion of screen + float window_width = 400.0f; + float window_height = 150.0f; + float x = (io.DisplaySize.x - window_width) * 0.5f; + float y = io.DisplaySize.y * 0.85f - window_height * 0.5f; + + ImGui::SetNextWindowPos(ImVec2(x, y), ImGuiCond_FirstUseEver); + ImGui::SetNextWindowSize(ImVec2(window_width, window_height), + ImGuiCond_FirstUseEver); + + bool dialog_open = true; + if (!ImGui::Begin("Audio Player Menu", &dialog_open, + ImGuiWindowFlags_NoCollapse | + ImGuiWindowFlags_AlwaysAutoResize | + ImGuiWindowFlags_HorizontalScrollbar)) { + Close(); + ImGui::End(); + return; + } + + auto audio_player = emulator_window_.emulator_->audio_media_player(); + using xmp_state = kernel::xam::apps::XmpApp::State; + if (audio_player) { + ImGui::Text("Audio player status:"); + ImGui::SameLine(); + switch (audio_player->GetState()) { + case xmp_state::kIdle: + ImGui::Text("Idle"); + break; + case xmp_state::kPaused: + ImGui::Text("Paused"); + break; + case xmp_state::kPlaying: + ImGui::Text("Playing"); + break; + default: + break; + } + + if (audio_player->IsPlaying()) { + if (ImGui::Button("Pause")) { + audio_player->Pause(); + } + } else if (audio_player->IsPaused()) { + if (ImGui::Button("Resume")) { + audio_player->Continue(); + } + } + + volume_ = + emulator_window_.emulator_->audio_media_player()->GetVolume()->load(); + + if (ImGui::SliderFloat("Audio player volume", &volume_, 0.0f, 1.0f)) { + audio_player->SetVolume(volume_); + } + } + + if (!dialog_open) { + ImGui::End(); + emulator_window_.ToggleXMPConfigDialog(); + return; + } + + ImGui::End(); +} + bool EmulatorWindow::Initialize() { window_->AddListener(&window_listener_); window_->AddInputListener(&window_listener_, kZOrderEmulatorWindowInput); @@ -1050,6 +1117,9 @@ void EmulatorWindow::OnMouseDown(const ui::MouseEvent& e) { context_menu->AddAction("Profiles Menu", [this]() { ToggleProfilesConfigDialog(); }); + context_menu->AddAction("XMP Audio Player", + [this]() { ToggleXMPConfigDialog(); }); + // Show menu at mouse position QPoint global_pos = QCursor::pos(); context_menu->ShowAt(global_pos); @@ -1544,6 +1614,15 @@ void EmulatorWindow::OpenConfigDialog(const std::string& category) { config_dialog_qt_->activateWindow(); } +void EmulatorWindow::ToggleXMPConfigDialog() { + if (!xmp_config_dialog_) { + xmp_config_dialog_ = std::unique_ptr( + new XMPConfigDialog(imgui_drawer_.get(), *this)); + } else { + xmp_config_dialog_.reset(); + } +} + void EmulatorWindow::ToggleControllerVibration() { auto input_sys = emulator()->input_system(); if (input_sys) { diff --git a/src/xenia/app/emulator_window.h b/src/xenia/app/emulator_window.h index 4bea01b28..ec04c69b2 100644 --- a/src/xenia/app/emulator_window.h +++ b/src/xenia/app/emulator_window.h @@ -113,6 +113,7 @@ class EmulatorWindow { const xe::ui::RawImage& image); void ToggleProfilesConfigDialog(); + void ToggleXMPConfigDialog(); void SetHotkeysState(bool enabled) { disable_hotkeys_ = !enabled; } void FileOpen(); const std::vector& GetRecentlyLaunchedTitles() const { @@ -180,6 +181,26 @@ class EmulatorWindow { }; public: + class XMPConfigDialog final : public ui::ImGuiDialog { + public: + XMPConfigDialog(ui::ImGuiDrawer* imgui_drawer, + EmulatorWindow& emulator_window) + : ui::ImGuiDialog(imgui_drawer), emulator_window_(emulator_window) { + if (emulator_window_.emulator_->audio_media_player()) { + volume_ = emulator_window_.emulator_->audio_media_player() + ->GetVolume() + ->load(); + } + } + + protected: + void OnDraw(ImGuiIO& io) override; + + private: + EmulatorWindow& emulator_window_; + float volume_ = 0.0f; + }; + explicit EmulatorWindow(Emulator* emulator, ui::WindowedAppContext& app_context, uint32_t width, uint32_t height, bool is_game_process = false); @@ -283,6 +304,8 @@ class EmulatorWindow { // messages back to guest. std::unique_ptr profile_config_dialog_; + std::unique_ptr xmp_config_dialog_; + std::vector recently_launched_titles_; // Menu items that need to be enabled/disabled based on child process state diff --git a/src/xenia/apu/audio_media_player.cc b/src/xenia/apu/audio_media_player.cc index b88e5aab2..76e460c9e 100644 --- a/src/xenia/apu/audio_media_player.cc +++ b/src/xenia/apu/audio_media_player.cc @@ -448,7 +448,7 @@ void AudioMediaPlayer::RemovePlaylist(uint32_t handle) { } X_STATUS AudioMediaPlayer::SetVolume(float volume) { - volume_ = std::min(volume, 1.0f); + volume_.store(std::min(volume, 1.0f)); std::unique_lock guard(driver_mutex_); if (!driver_) { diff --git a/src/xenia/apu/audio_media_player.h b/src/xenia/apu/audio_media_player.h index 4343a8b9d..6d0745dd5 100644 --- a/src/xenia/apu/audio_media_player.h +++ b/src/xenia/apu/audio_media_player.h @@ -51,7 +51,7 @@ class AudioMediaPlayer { bool IsLastSongInPlaylist() const; X_STATUS SetVolume(float volume); - float GetVolume() const { return volume_; } + const std::atomic* GetVolume() const { return &volume_; } void SetPlaybackMode(XmpApp::PlaybackMode playback_mode) { playback_mode_ = playback_mode; @@ -106,7 +106,7 @@ class AudioMediaPlayer { XmpApp::PlaybackMode playback_mode_ = XmpApp::PlaybackMode::kInOrder; XmpApp::RepeatMode repeat_mode_ = XmpApp::RepeatMode::kPlaylist; XmpApp::PlaybackFlags playback_flags_ = XmpApp::PlaybackFlags::kDefault; - float volume_ = 1.0f; + std::atomic volume_ = 0.0f; uint32_t dash_init_state = 0; std::unordered_map> playlists_; diff --git a/src/xenia/cpu/backend/x64/x64_op.h b/src/xenia/cpu/backend/x64/x64_op.h index 68e67567c..b923bc31b 100644 --- a/src/xenia/cpu/backend/x64/x64_op.h +++ b/src/xenia/cpu/backend/x64/x64_op.h @@ -175,6 +175,10 @@ struct ValueOp : Op, KEY_TYPE> { virtual bool ConstantFitsIn32Reg() const { return true; } const REG_TYPE& reg() const { assert_true(!is_constant); + if (is_constant) { + XELOGE("{} - Invalid handling of constant! Report this to developers!", + __FUNCTION__); + } return reg_; } operator const REG_TYPE&() const { return reg(); } diff --git a/src/xenia/cpu/backend/x64/x64_seq_vector.cc b/src/xenia/cpu/backend/x64/x64_seq_vector.cc index cc4016abd..d4aea1029 100644 --- a/src/xenia/cpu/backend/x64/x64_seq_vector.cc +++ b/src/xenia/cpu/backend/x64/x64_seq_vector.cc @@ -1885,7 +1885,12 @@ struct VECTOR_ROTATE_LEFT_V128 } break; case INT32_TYPE: { if (e.IsFeatureEnabled(kX64EmitAVX512Ortho)) { - e.vprolvd(i.dest, i.src1, i.src2); + if (i.src2.is_constant) { + e.LoadConstantXmm(e.xmm0, i.src2.constant()); + e.vprolvd(i.dest, i.src1, e.xmm0); + } else { + e.vprolvd(i.dest, i.src1, i.src2); + } } else if (e.IsFeatureEnabled(kX64EmitAVX2)) { Xmm temp = i.dest; if (i.dest == i.src1 || i.dest == i.src2) { diff --git a/src/xenia/kernel/xam/apps/xmp_app.cc b/src/xenia/kernel/xam/apps/xmp_app.cc index 95176156e..283e17d34 100644 --- a/src/xenia/kernel/xam/apps/xmp_app.cc +++ b/src/xenia/kernel/xam/apps/xmp_app.cc @@ -262,7 +262,7 @@ X_HRESULT XmpApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr, xe::store_and_swap( memory_->TranslateVirtual(args->volume_ptr), - kernel_state_->emulator()->audio_media_player()->GetVolume()); + kernel_state_->emulator()->audio_media_player()->GetVolume()->load()); return X_E_SUCCESS; } case 0x0007000C: { @@ -401,7 +401,7 @@ X_HRESULT XmpApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr, XMP_CREATE_USER_PLAYLIST_ENUMERATOR* args = reinterpret_cast(buffer); - XELOGD("XMPSetPlaybackController({:08X}, {:08X}, {:08X})", + XELOGD("XMPCreateUserPlaylistEnumerator({:08X}, {:08X}, {:08X})", uint32_t(args->xmp_client), uint32_t(args->flags), uint32_t(args->unk_ptr)); return X_E_SUCCESS; diff --git a/src/xenia/kernel/xam/apps/xmp_app.h b/src/xenia/kernel/xam/apps/xmp_app.h index b0324fd81..92f228102 100644 --- a/src/xenia/kernel/xam/apps/xmp_app.h +++ b/src/xenia/kernel/xam/apps/xmp_app.h @@ -86,7 +86,7 @@ static_assert_size(XMP_GET_VOLUME, 0x8); struct XMP_SET_VOLUME { xe::be xmp_client; - xe::be value; + xe::be value; }; static_assert_size(XMP_SET_VOLUME, 0x8); diff --git a/src/xenia/kernel/xam/xam_net.cc b/src/xenia/kernel/xam/xam_net.cc index 6f634f3e0..d8024d1fc 100644 --- a/src/xenia/kernel/xam/xam_net.cc +++ b/src/xenia/kernel/xam/xam_net.cc @@ -672,7 +672,8 @@ dword_result_t NetDll_socket_entry(dword_t caller, dword_t af, dword_t type, socket->Release(); XThread::SetLastError(socket->GetLastWSAError()); - XELOGI("NetDll_socket: failed with error"); + XELOGE("NetDll_socket: failed with error {:08X}", + socket->GetLastWSAError()); return -1; } @@ -765,7 +766,8 @@ dword_result_t NetDll_ioctlsocket_entry(dword_t caller, dword_t socket_handle, X_STATUS status = socket->IOControl(cmd, arg_ptr); if (XFAILED(status)) { XThread::SetLastError(socket->GetLastWSAError()); - XELOGI("NetDll_ioctlsocket: failed"); + XELOGE("NetDll_ioctlsocket: failed with error {:08X}", + socket->GetLastWSAError()); return -1; } @@ -1072,7 +1074,6 @@ dword_result_t NetDll_sendto_entry(dword_t caller, dword_t socket_handle, N_XSOCKADDR_IN native_to(to_ptr); int ret = socket->SendTo(buf_ptr, buf_len, flags, &native_to, to_len); - XELOGD("NetDll_sendto: returned {}", ret); return ret; } DECLARE_XAM_EXPORT1(NetDll_sendto, kNetworking, kImplemented); diff --git a/src/xenia/kernel/xsocket.cc b/src/xenia/kernel/xsocket.cc index a979d5423..3f9bbaada 100644 --- a/src/xenia/kernel/xsocket.cc +++ b/src/xenia/kernel/xsocket.cc @@ -157,7 +157,7 @@ X_STATUS XSocket::SetOption(uint32_t level, uint32_t optname, void* optval_ptr, } int ret = setsockopt(native_handle_, native_level, native_optname, - (char*)optval_ptr, optlen); + static_cast(optval_ptr), optlen); if (ret < 0) { XELOGE("XSocket::SetOption: setsockopt failed, errno={}", errno); return X_STATUS_UNSUCCESSFUL; @@ -218,7 +218,7 @@ X_STATUS XSocket::Bind(N_XSOCKADDR_IN* name, int name_len) { // privileges. Remap to port + 10000 to avoid privilege issues. // Note: sin_port is xe::be which automatically handles endianness, // so we use it directly without ntohs/htons. - uint16_t original_port = uint16_t(name->sin_port); + const uint16_t original_port = uint16_t(name->sin_port); if (original_port < 1024) { uint16_t new_port = original_port + 10000; name->sin_port = new_port;