diff options
m--------- | externals/dynarmic | 0 | ||||
-rw-r--r-- | src/audio_core/stream.cpp | 8 | ||||
-rw-r--r-- | src/audio_core/stream.h | 3 | ||||
-rw-r--r-- | src/core/hle/service/audio/audout_u.cpp | 10 | ||||
-rw-r--r-- | src/core/hle/service/prepo/prepo.cpp | 11 | ||||
-rw-r--r-- | src/video_core/memory_manager.cpp | 23 | ||||
-rw-r--r-- | src/video_core/memory_manager.h | 6 | ||||
-rw-r--r-- | src/yuzu/configuration/configure_input.cpp | 6 | ||||
-rw-r--r-- | src/yuzu/configuration/configure_input_player.cpp | 46 |
9 files changed, 94 insertions, 19 deletions
diff --git a/externals/dynarmic b/externals/dynarmic -Subproject 0f27368fdab3d2d1169e8dab14854e888bc9ce7 +Subproject 8c09da666aa3f0bb1000b0b6c5d5b0a1876f306 diff --git a/src/audio_core/stream.cpp b/src/audio_core/stream.cpp index afe68c9ed..5b0b285cd 100644 --- a/src/audio_core/stream.cpp +++ b/src/audio_core/stream.cpp @@ -51,6 +51,14 @@ void Stream::Stop() { UNIMPLEMENTED(); } +bool Stream::Flush() { + const bool had_buffers = !queued_buffers.empty(); + while (!queued_buffers.empty()) { + queued_buffers.pop(); + } + return had_buffers; +} + void Stream::SetVolume(float volume) { game_volume = volume; } diff --git a/src/audio_core/stream.h b/src/audio_core/stream.h index 506ac536b..559844b9b 100644 --- a/src/audio_core/stream.h +++ b/src/audio_core/stream.h @@ -56,6 +56,9 @@ public: /// Queues a buffer into the audio stream, returns true on success bool QueueBuffer(BufferPtr&& buffer); + /// Flush audio buffers + bool Flush(); + /// Returns true if the audio stream contains a buffer with the specified tag [[nodiscard]] bool ContainsBuffer(Buffer::Tag tag) const; diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp index 02ca711fb..273a46265 100644 --- a/src/core/hle/service/audio/audout_u.cpp +++ b/src/core/hle/service/audio/audout_u.cpp @@ -58,7 +58,7 @@ public: {8, &IAudioOut::GetReleasedAudioOutBufferImpl, "GetReleasedAudioOutBufferAuto"}, {9, &IAudioOut::GetAudioOutBufferCount, "GetAudioOutBufferCount"}, {10, nullptr, "GetAudioOutPlayedSampleCount"}, - {11, nullptr, "FlushAudioOutBuffers"}, + {11, &IAudioOut::FlushAudioOutBuffers, "FlushAudioOutBuffers"}, {12, &IAudioOut::SetAudioOutVolume, "SetAudioOutVolume"}, {13, &IAudioOut::GetAudioOutVolume, "GetAudioOutVolume"}, }; @@ -185,6 +185,14 @@ private: rb.Push(static_cast<u32>(stream->GetQueueSize())); } + void FlushAudioOutBuffers(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_Audio, "called"); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push(stream->Flush()); + } + void SetAudioOutVolume(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const float volume = rp.Pop<float>(); diff --git a/src/core/hle/service/prepo/prepo.cpp b/src/core/hle/service/prepo/prepo.cpp index 6edd45455..86ecc5b97 100644 --- a/src/core/hle/service/prepo/prepo.cpp +++ b/src/core/hle/service/prepo/prepo.cpp @@ -27,7 +27,7 @@ public: {10105, &PlayReport::SaveReportWithUser<Core::Reporter::PlayReportType::New>, "SaveReportWithUser"}, {10200, nullptr, "RequestImmediateTransmission"}, {10300, nullptr, "GetTransmissionStatus"}, - {10400, nullptr, "GetSystemSessionId"}, + {10400, &PlayReport::GetSystemSessionId, "GetSystemSessionId"}, {20100, &PlayReport::SaveSystemReport, "SaveSystemReport"}, {20101, &PlayReport::SaveSystemReportWithUser, "SaveSystemReportWithUser"}, {20200, nullptr, "SetOperationMode"}, @@ -108,6 +108,15 @@ private: rb.Push(RESULT_SUCCESS); } + void GetSystemSessionId(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_PREPO, "(STUBBED) called"); + + constexpr u64 system_session_id = 0; + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(RESULT_SUCCESS); + rb.Push(system_session_id); + } + void SaveSystemReport(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto title_id = rp.PopRaw<u64>(); diff --git a/src/video_core/memory_manager.cpp b/src/video_core/memory_manager.cpp index f5cdf548e..c841f3cd7 100644 --- a/src/video_core/memory_manager.cpp +++ b/src/video_core/memory_manager.cpp @@ -4,6 +4,7 @@ #include "common/alignment.h" #include "common/assert.h" +#include "common/logging/log.h" #include "core/core.h" #include "core/hle/kernel/memory/page_table.h" #include "core/hle/kernel/process.h" @@ -38,6 +39,12 @@ GPUVAddr MemoryManager::UpdateRange(GPUVAddr gpu_addr, PageEntry page_entry, std } GPUVAddr MemoryManager::Map(VAddr cpu_addr, GPUVAddr gpu_addr, std::size_t size) { + const auto it = std::ranges::lower_bound(map_ranges, gpu_addr, {}, &MapRange::first); + if (it != map_ranges.end() && it->first == gpu_addr) { + it->second = size; + } else { + map_ranges.insert(it, MapRange{gpu_addr, size}); + } return UpdateRange(gpu_addr, cpu_addr, size); } @@ -52,10 +59,16 @@ GPUVAddr MemoryManager::MapAllocate32(VAddr cpu_addr, std::size_t size) { } void MemoryManager::Unmap(GPUVAddr gpu_addr, std::size_t size) { - if (!size) { + if (size == 0) { return; } - + const auto it = std::ranges::lower_bound(map_ranges, gpu_addr, {}, &MapRange::first); + if (it != map_ranges.end()) { + ASSERT(it->first == gpu_addr); + map_ranges.erase(it); + } else { + UNREACHABLE_MSG("Unmapping non-existent GPU address=0x{:x}", gpu_addr); + } // Flush and invalidate through the GPU interface, to be asynchronous if possible. const std::optional<VAddr> cpu_addr = GpuToCpuAddress(gpu_addr); ASSERT(cpu_addr); @@ -218,6 +231,12 @@ const u8* MemoryManager::GetPointer(GPUVAddr gpu_addr) const { return system.Memory().GetPointer(*address); } +size_t MemoryManager::BytesToMapEnd(GPUVAddr gpu_addr) const noexcept { + auto it = std::ranges::upper_bound(map_ranges, gpu_addr, {}, &MapRange::first); + --it; + return it->second - (gpu_addr - it->first); +} + void MemoryManager::ReadBlock(GPUVAddr gpu_src_addr, void* dest_buffer, std::size_t size) const { std::size_t remaining_size{size}; std::size_t page_index{gpu_src_addr >> page_bits}; diff --git a/src/video_core/memory_manager.h b/src/video_core/memory_manager.h index a52fbbd8c..b468a67de 100644 --- a/src/video_core/memory_manager.h +++ b/src/video_core/memory_manager.h @@ -85,6 +85,9 @@ public: [[nodiscard]] u8* GetPointer(GPUVAddr addr); [[nodiscard]] const u8* GetPointer(GPUVAddr addr) const; + /// Returns the number of bytes until the end of the memory map containing the given GPU address + [[nodiscard]] size_t BytesToMapEnd(GPUVAddr gpu_addr) const noexcept; + /** * ReadBlock and WriteBlock are full read and write operations over virtual * GPU Memory. It's important to use these when GPU memory may not be continuous @@ -151,6 +154,9 @@ private: VideoCore::RasterizerInterface* rasterizer = nullptr; std::vector<PageEntry> page_table; + + using MapRange = std::pair<GPUVAddr, size_t>; + std::vector<MapRange> map_ranges; }; } // namespace Tegra diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp index 567a36d9b..422022d02 100644 --- a/src/yuzu/configuration/configure_input.cpp +++ b/src/yuzu/configuration/configure_input.cpp @@ -190,12 +190,16 @@ void ConfigureInput::ApplyConfiguration() { // This emulates a delay between disconnecting and reconnecting controllers as some games // do not respond to a change in controller type if it was instantaneous. using namespace std::chrono_literals; - std::this_thread::sleep_for(60ms); + std::this_thread::sleep_for(150ms); for (auto* controller : player_controllers) { controller->TryConnectSelectedController(); } + // This emulates a delay between disconnecting and reconnecting controllers as some games + // do not respond to a change in controller type if it was instantaneous. + std::this_thread::sleep_for(150ms); + advanced->ApplyConfiguration(); const bool pre_docked_mode = Settings::values.use_docked_mode.GetValue(); diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index 13f0351d4..fbe36046b 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp @@ -579,11 +579,11 @@ void ConfigureInputPlayer::ApplyConfiguration() { // Apply configuration for handheld if (player_index == 0) { auto& handheld = Settings::values.players.GetValue()[HANDHELD_INDEX]; + const auto handheld_connected = handheld.connected; if (player.controller_type == Settings::ControllerType::Handheld) { handheld = player; } - handheld.connected = ui->groupConnectedController->isChecked() && - player.controller_type == Settings::ControllerType::Handheld; + handheld.connected = handheld_connected; } } @@ -595,6 +595,18 @@ void ConfigureInputPlayer::TryConnectSelectedController() { const auto player_connected = ui->groupConnectedController->isChecked() && controller_type != Settings::ControllerType::Handheld; + // Connect Handheld depending on Player 1's controller configuration. + if (player_index == 0 && controller_type == Settings::ControllerType::Handheld) { + auto& handheld = Settings::values.players.GetValue()[HANDHELD_INDEX]; + const auto handheld_connected = ui->groupConnectedController->isChecked() && + controller_type == Settings::ControllerType::Handheld; + // Connect only if handheld is going from disconnected to connected + if (!handheld.connected && handheld_connected) { + UpdateController(controller_type, HANDHELD_INDEX, true); + } + handheld.connected = handheld_connected; + } + if (player.controller_type == controller_type && player.connected == player_connected) { // Set vibration devices in the event that the input device has changed. ConfigureVibration::SetVibrationDevices(player_index); @@ -606,22 +618,11 @@ void ConfigureInputPlayer::TryConnectSelectedController() { ConfigureVibration::SetVibrationDevices(player_index); - // Connect/Disconnect Handheld depending on Player 1's controller configuration. - if (player_index == 0) { - auto& handheld = Settings::values.players.GetValue()[HANDHELD_INDEX]; - if (controller_type == Settings::ControllerType::Handheld) { - handheld = player; - } - handheld.connected = ui->groupConnectedController->isChecked() && - controller_type == Settings::ControllerType::Handheld; - UpdateController(Settings::ControllerType::Handheld, HANDHELD_INDEX, handheld.connected); - } - if (!player.connected) { return; } - UpdateController(controller_type, player_index, player_connected); + UpdateController(controller_type, player_index, true); } void ConfigureInputPlayer::TryDisconnectSelectedController() { @@ -632,11 +633,28 @@ void ConfigureInputPlayer::TryDisconnectSelectedController() { const auto player_connected = ui->groupConnectedController->isChecked() && controller_type != Settings::ControllerType::Handheld; + // Disconnect Handheld depending on Player 1's controller configuration. + if (player_index == 0 && player.controller_type == Settings::ControllerType::Handheld) { + const auto& handheld = Settings::values.players.GetValue()[HANDHELD_INDEX]; + const auto handheld_connected = ui->groupConnectedController->isChecked() && + controller_type == Settings::ControllerType::Handheld; + // Disconnect only if handheld is going from connected to disconnected + if (handheld.connected && !handheld_connected) { + UpdateController(controller_type, HANDHELD_INDEX, false); + } + return; + } + // Do not do anything if the controller configuration has not changed. if (player.controller_type == controller_type && player.connected == player_connected) { return; } + // Do not disconnect if the controller is already disconnected + if (!player.connected) { + return; + } + // Disconnect the controller first. UpdateController(controller_type, player_index, false); } |