From 309276a3170b876ef7818dc42b7ef81a467fd83e Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 9 Feb 2018 21:42:08 -0500 Subject: [PATCH 1/6] IGBPRequestBufferResponseParcel: Fix response for libnx. --- src/core/hle/service/vi/vi.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index 7508443a87..589a4937ca 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp @@ -301,14 +301,11 @@ public: protected: void SerializeData() override { - // TODO(Subv): Find out what this all means - Write(1); - - Write(sizeof(NVFlinger::IGBPBuffer)); - Write(0); // Unknown - + // TODO(bunnei): Find out what this all means. Writing anything non-zero here breaks libnx. + Write(0); + Write(0); + Write(0); Write(buffer); - Write(0); } From 63de56ee0ff50895f1c318949c027cc96ee40b9c Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 9 Feb 2018 21:42:49 -0500 Subject: [PATCH 2/6] IGBPQueueBufferRequestParcel: Don't enforce buffer length. - Another fix for libnx. --- src/core/hle/service/vi/vi.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index 589a4937ca..a0eee9e4b1 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp @@ -211,7 +211,6 @@ public: void DeserializeData() override { std::u16string token = ReadInterfaceToken(); data = Read(); - ASSERT(data.graphic_buffer_length == sizeof(NVFlinger::IGBPBuffer)); buffer = Read(); } From 725304094eec2985f7e3b48efa0055171b1e7397 Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 9 Feb 2018 22:17:31 -0500 Subject: [PATCH 3/6] nvflinger: (Hack) Use first available buffer if none are found. --- src/core/hle/service/nvflinger/buffer_queue.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/core/hle/service/nvflinger/buffer_queue.cpp b/src/core/hle/service/nvflinger/buffer_queue.cpp index c7206a6831..f90c7ca518 100644 --- a/src/core/hle/service/nvflinger/buffer_queue.cpp +++ b/src/core/hle/service/nvflinger/buffer_queue.cpp @@ -40,7 +40,11 @@ u32 BufferQueue::DequeueBuffer(u32 pixel_format, u32 width, u32 height) { return igbp_buffer.format == pixel_format && igbp_buffer.width == width && igbp_buffer.height == height; }); - ASSERT(itr != queue.end()); + if (itr == queue.end()) { + LOG_CRITICAL(Service_NVDRV, "no free buffers for pixel_format=%d, width=%d, height=%d", + pixel_format, width, height); + itr = queue.begin(); + } itr->status = Buffer::Status::Dequeued; return itr->slot; From c83a1b232028ae4d84eb255e8c04154e9b6e8930 Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 9 Feb 2018 22:50:29 -0500 Subject: [PATCH 4/6] vi: Implement TransactParcelAuto. --- src/core/hle/service/vi/vi.cpp | 78 ++++++++++++++++++++-------------- 1 file changed, 46 insertions(+), 32 deletions(-) diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index a0eee9e4b1..69ac2fe07f 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp @@ -397,7 +397,7 @@ public: {0, &IHOSBinderDriver::TransactParcel, "TransactParcel"}, {1, &IHOSBinderDriver::AdjustRefcount, "AdjustRefcount"}, {2, &IHOSBinderDriver::GetNativeHandle, "GetNativeHandle"}, - {3, nullptr, "TransactParcelAuto"}, + {3, &IHOSBinderDriver::TransactParcelAuto, "TransactParcelAuto"}, }; RegisterHandlers(functions); } @@ -421,35 +421,21 @@ private: SetPreallocatedBuffer = 14 }; - void TransactParcel(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - u32 id = rp.Pop(); - auto transaction = static_cast(rp.Pop()); - u32 flags = rp.Pop(); - - auto& input_buffer = ctx.BufferDescriptorA()[0]; - std::vector input_data(input_buffer.Size()); - Memory::ReadBlock(input_buffer.Address(), input_data.data(), input_buffer.Size()); - - auto& output_buffer = ctx.BufferDescriptorB()[0]; - + void TransactParcel(u32 id, TransactionId transaction, const std::vector& input_data, + VAddr output_addr, u64 output_size) { auto buffer_queue = nv_flinger->GetBufferQueue(id); - LOG_WARNING(Service_VI, "(STUBBED) called, transaction=%x", transaction); + std::vector response_buffer; if (transaction == TransactionId::Connect) { IGBPConnectRequestParcel request{input_data}; IGBPConnectResponseParcel response{1280, 720}; - auto response_buffer = response.Serialize(); - Memory::WriteBlock(output_buffer.Address(), response_buffer.data(), - output_buffer.Size()); + response_buffer = response.Serialize(); } else if (transaction == TransactionId::SetPreallocatedBuffer) { IGBPSetPreallocatedBufferRequestParcel request{input_data}; buffer_queue->SetPreallocatedBuffer(request.data.slot, request.buffer); IGBPSetPreallocatedBufferResponseParcel response{}; - auto response_buffer = response.Serialize(); - Memory::WriteBlock(output_buffer.Address(), response_buffer.data(), - output_buffer.Size()); + response_buffer = response.Serialize(); } else if (transaction == TransactionId::DequeueBuffer) { IGBPDequeueBufferRequestParcel request{input_data}; @@ -457,27 +443,21 @@ private: request.data.height); IGBPDequeueBufferResponseParcel response{slot}; - auto response_buffer = response.Serialize(); - Memory::WriteBlock(output_buffer.Address(), response_buffer.data(), - output_buffer.Size()); + response_buffer = response.Serialize(); } else if (transaction == TransactionId::RequestBuffer) { IGBPRequestBufferRequestParcel request{input_data}; auto& buffer = buffer_queue->RequestBuffer(request.slot); IGBPRequestBufferResponseParcel response{buffer}; - auto response_buffer = response.Serialize(); - Memory::WriteBlock(output_buffer.Address(), response_buffer.data(), - output_buffer.Size()); + response_buffer = response.Serialize(); } else if (transaction == TransactionId::QueueBuffer) { IGBPQueueBufferRequestParcel request{input_data}; buffer_queue->QueueBuffer(request.data.slot); IGBPQueueBufferResponseParcel response{1280, 720}; - auto response_buffer = response.Serialize(); - Memory::WriteBlock(output_buffer.Address(), response_buffer.data(), - output_buffer.Size()); + response_buffer = response.Serialize(); } else if (transaction == TransactionId::Query) { IGBPQueryRequestParcel request{input_data}; @@ -485,13 +465,47 @@ private: buffer_queue->Query(static_cast(request.type)); IGBPQueryResponseParcel response{value}; - auto response_buffer = response.Serialize(); - Memory::WriteBlock(output_buffer.Address(), response_buffer.data(), - output_buffer.Size()); + response_buffer = response.Serialize(); + } else { ASSERT_MSG(false, "Unimplemented"); } + Memory::WriteBlock(output_addr, response_buffer.data(), output_size); + } + + void TransactParcel(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + u32 id = rp.Pop(); + auto transaction = static_cast(rp.Pop()); + u32 flags = rp.Pop(); + LOG_DEBUG(Service_VI, "called, transaction=%x", transaction); + + auto& input_buffer = ctx.BufferDescriptorA()[0]; + auto& output_buffer = ctx.BufferDescriptorB()[0]; + std::vector input_data(input_buffer.Size()); + Memory::ReadBlock(input_buffer.Address(), input_data.data(), input_buffer.Size()); + + TransactParcel(id, transaction, input_data, output_buffer.Address(), output_buffer.Size()); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + } + + void TransactParcelAuto(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + u32 id = rp.Pop(); + auto transaction = static_cast(rp.Pop()); + u32 flags = rp.Pop(); + LOG_DEBUG(Service_VI, "called, transaction=%x", transaction); + + auto& input_buffer = ctx.BufferDescriptorX()[0]; + auto& output_buffer = ctx.BufferDescriptorC()[0]; + std::vector input_data(input_buffer.size); + Memory::ReadBlock(input_buffer.Address(), input_data.data(), input_buffer.size); + + TransactParcel(id, transaction, input_data, output_buffer.Address(), output_buffer.Size()); + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } From 0532de6559b05a5af8177e9771a99f2cbd5985db Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 9 Feb 2018 23:17:37 -0500 Subject: [PATCH 5/6] apm: Refactor service impl. to support multiple ports. --- src/core/CMakeLists.txt | 2 + src/core/hle/service/apm/apm.cpp | 56 ++-------------------- src/core/hle/service/apm/apm.h | 9 ++-- src/core/hle/service/apm/interface.cpp | 66 ++++++++++++++++++++++++++ src/core/hle/service/apm/interface.h | 27 +++++++++++ 5 files changed, 102 insertions(+), 58 deletions(-) create mode 100644 src/core/hle/service/apm/interface.cpp create mode 100644 src/core/hle/service/apm/interface.h diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index eab08207df..a78d6d8881 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -92,6 +92,8 @@ add_library(core STATIC hle/service/aoc/aoc_u.h hle/service/apm/apm.cpp hle/service/apm/apm.h + hle/service/apm/interface.cpp + hle/service/apm/interface.h hle/service/audio/audio.cpp hle/service/audio/audio.h hle/service/audio/audin_u.cpp diff --git a/src/core/hle/service/apm/apm.cpp b/src/core/hle/service/apm/apm.cpp index a7495d0a0b..c4b09b4359 100644 --- a/src/core/hle/service/apm/apm.cpp +++ b/src/core/hle/service/apm/apm.cpp @@ -5,63 +5,15 @@ #include "common/logging/log.h" #include "core/hle/ipc_helpers.h" #include "core/hle/service/apm/apm.h" +#include "core/hle/service/apm/interface.h" namespace Service { namespace APM { void InstallInterfaces(SM::ServiceManager& service_manager) { - std::make_shared()->InstallAsService(service_manager); -} - -class ISession final : public ServiceFramework { -public: - ISession() : ServiceFramework("ISession") { - static const FunctionInfo functions[] = { - {0, &ISession::SetPerformanceConfiguration, "SetPerformanceConfiguration"}, - {1, &ISession::GetPerformanceConfiguration, "GetPerformanceConfiguration"}, - }; - RegisterHandlers(functions); - } - -private: - void SetPerformanceConfiguration(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - - auto mode = static_cast(rp.Pop()); - u32 config = rp.Pop(); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(RESULT_SUCCESS); - - LOG_WARNING(Service_APM, "(STUBBED) called mode=%u config=%u", static_cast(mode), - config); - } - - void GetPerformanceConfiguration(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - - auto mode = static_cast(rp.Pop()); - - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(RESULT_SUCCESS); - rb.Push(0); // Performance configuration - - LOG_WARNING(Service_APM, "(STUBBED) called mode=%u", static_cast(mode)); - } -}; - -APM::APM() : ServiceFramework("apm") { - static const FunctionInfo functions[] = { - {0x00000000, &APM::OpenSession, "OpenSession"}, - {0x00000001, nullptr, "GetPerformanceMode"}, - }; - RegisterHandlers(functions); -} - -void APM::OpenSession(Kernel::HLERequestContext& ctx) { - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; - rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface(); + auto module_ = std::make_shared(); + std::make_shared(module_, "apm")->InstallAsService(service_manager); + std::make_shared(module_, "apm:p")->InstallAsService(service_manager); } } // namespace APM diff --git a/src/core/hle/service/apm/apm.h b/src/core/hle/service/apm/apm.h index 90a1afbbcb..070ab21f87 100644 --- a/src/core/hle/service/apm/apm.h +++ b/src/core/hle/service/apm/apm.h @@ -14,13 +14,10 @@ enum class PerformanceMode : u8 { Docked = 1, }; -class APM final : public ServiceFramework { +class Module final { public: - APM(); - ~APM() = default; - -private: - void OpenSession(Kernel::HLERequestContext& ctx); + Module() = default; + ~Module() = default; }; /// Registers all AM services with the specified service manager. diff --git a/src/core/hle/service/apm/interface.cpp b/src/core/hle/service/apm/interface.cpp new file mode 100644 index 0000000000..0179351ba9 --- /dev/null +++ b/src/core/hle/service/apm/interface.cpp @@ -0,0 +1,66 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/logging/log.h" +#include "core/hle/ipc_helpers.h" +#include "core/hle/service/apm/apm.h" +#include "core/hle/service/apm/interface.h" + +namespace Service { +namespace APM { + +class ISession final : public ServiceFramework { +public: + ISession() : ServiceFramework("ISession") { + static const FunctionInfo functions[] = { + {0, &ISession::SetPerformanceConfiguration, "SetPerformanceConfiguration"}, + {1, &ISession::GetPerformanceConfiguration, "GetPerformanceConfiguration"}, + }; + RegisterHandlers(functions); + } + +private: + void SetPerformanceConfiguration(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + + auto mode = static_cast(rp.Pop()); + u32 config = rp.Pop(); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + + LOG_WARNING(Service_APM, "(STUBBED) called mode=%u config=%u", static_cast(mode), + config); + } + + void GetPerformanceConfiguration(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + + auto mode = static_cast(rp.Pop()); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push(0); // Performance configuration + + LOG_WARNING(Service_APM, "(STUBBED) called mode=%u", static_cast(mode)); + } +}; + +APM::APM(std::shared_ptr apm, const char* name) + : ServiceFramework(name), apm(std::move(apm)) { + static const FunctionInfo functions[] = { + {0, &APM::OpenSession, "OpenSession"}, + {1, nullptr, "GetPerformanceMode"}, + }; + RegisterHandlers(functions); +} + +void APM::OpenSession(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushIpcInterface(); +} + +} // namespace APM +} // namespace Service diff --git a/src/core/hle/service/apm/interface.h b/src/core/hle/service/apm/interface.h new file mode 100644 index 0000000000..7d53721def --- /dev/null +++ b/src/core/hle/service/apm/interface.h @@ -0,0 +1,27 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "core/hle/service/service.h" + +namespace Service { +namespace APM { + +class APM final : public ServiceFramework { +public: + APM(std::shared_ptr apm, const char* name); + ~APM() = default; + +private: + void OpenSession(Kernel::HLERequestContext& ctx); + + std::shared_ptr apm; +}; + +/// Registers all AM services with the specified service manager. +void InstallInterfaces(SM::ServiceManager& service_manager); + +} // namespace APM +} // namespace Service From 8e7da732143b5e4192a4475bd6a4c5d473cf1dff Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 9 Feb 2018 23:30:28 -0500 Subject: [PATCH 6/6] fsp_srv: Stub MountSdCard. --- src/core/hle/service/filesystem/fsp_srv.cpp | 8 ++++++++ src/core/hle/service/filesystem/fsp_srv.h | 1 + 2 files changed, 9 insertions(+) diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp index aa5a3d6311..34d4fd035d 100644 --- a/src/core/hle/service/filesystem/fsp_srv.cpp +++ b/src/core/hle/service/filesystem/fsp_srv.cpp @@ -70,6 +70,7 @@ private: FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") { static const FunctionInfo functions[] = { {1, &FSP_SRV::Initalize, "Initalize"}, + {18, &FSP_SRV::MountSdCard, "MountSdCard"}, {200, &FSP_SRV::OpenDataStorageByCurrentProcess, "OpenDataStorageByCurrentProcess"}, {202, nullptr, "OpenDataStorageByDataId"}, {203, &FSP_SRV::OpenRomStorage, "OpenRomStorage"}, @@ -96,6 +97,13 @@ void FSP_SRV::Initalize(Kernel::HLERequestContext& ctx) { rb.Push(RESULT_SUCCESS); } +void FSP_SRV::MountSdCard(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_FS, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); +} + void FSP_SRV::GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx) { LOG_WARNING(Service_FS, "(STUBBED) called"); diff --git a/src/core/hle/service/filesystem/fsp_srv.h b/src/core/hle/service/filesystem/fsp_srv.h index 15be8edc14..56afc4b90f 100644 --- a/src/core/hle/service/filesystem/fsp_srv.h +++ b/src/core/hle/service/filesystem/fsp_srv.h @@ -23,6 +23,7 @@ private: void TryLoadRomFS(); void Initalize(Kernel::HLERequestContext& ctx); + void MountSdCard(Kernel::HLERequestContext& ctx); void GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx); void OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx); void OpenRomStorage(Kernel::HLERequestContext& ctx);