From 22f8cc597093913c937abf1520b1c83fb067aee5 Mon Sep 17 00:00:00 2001 From: PixelyIon Date: Sat, 4 Feb 2023 22:40:00 +0530 Subject: [PATCH] Stub indirect layer VI service functions Indirect layers are used by the game to render layer on its own, the game allocates a buffer with the size from `GetIndirectLayerImageRequiredMemoryInfo` and uses `GetIndirectLayerImageMap` to draw the applet contents into the buffer. As we don't LLE applet implementations nor do our HLE implementations draw equivalent applets, we cannot submit this to the guest. As a result, these functions are stubbed with the framebuffer being cleared to red. Stubbing these functions allows titles such as Dark Souls to not crash while initializing indirect layers. --- .../visrv/IApplicationDisplayService.cpp | 34 +++++++++++++++++++ .../visrv/IApplicationDisplayService.h | 14 ++++++++ .../main/cpp/skyline/services/visrv/results.h | 1 + 3 files changed, 49 insertions(+) diff --git a/app/src/main/cpp/skyline/services/visrv/IApplicationDisplayService.cpp b/app/src/main/cpp/skyline/services/visrv/IApplicationDisplayService.cpp index 8e1c68b8..206bfed7 100644 --- a/app/src/main/cpp/skyline/services/visrv/IApplicationDisplayService.cpp +++ b/app/src/main/cpp/skyline/services/visrv/IApplicationDisplayService.cpp @@ -124,4 +124,38 @@ namespace skyline::service::visrv { return {}; } + + Result IApplicationDisplayService::GetIndirectLayerImageMap(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { + auto width{request.Pop()}; + auto height{request.Pop()}; + + if (!request.outputBuf.empty()) { + // As we don't support indirect layers, we just fill the output buffer with red + auto imageBuffer{request.outputBuf.at(0)}; + std::fill(imageBuffer.begin(), imageBuffer.end(), 0xFF0000FF); + } + + response.Push(width); + response.Push(height); + + return {}; + } + + Result IApplicationDisplayService::GetIndirectLayerImageRequiredMemoryInfo(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { + i64 width{request.Pop()}, height{request.Pop()}; + + if (width <= 0 || height <= 0) + return result::InvalidDimensions; + + constexpr ssize_t A8B8G8R8Size{4}; //!< The size of a pixel in the A8B8G8R8 format, this format is used by indirect layers + i64 layerSize{width * height * A8B8G8R8Size}; + + constexpr ssize_t BlockSize{0x20000}; //!< The size of an arbitrarily defined block, the layer size must be aligned to a block + response.Push(util::AlignUpNpot(layerSize, BlockSize)); + + constexpr size_t DefaultAlignment{0x1000}; //!< The default alignment of the buffer + response.Push(DefaultAlignment); + + return Result{}; + } } diff --git a/app/src/main/cpp/skyline/services/visrv/IApplicationDisplayService.h b/app/src/main/cpp/skyline/services/visrv/IApplicationDisplayService.h index ab2a1a66..02e67ff1 100644 --- a/app/src/main/cpp/skyline/services/visrv/IApplicationDisplayService.h +++ b/app/src/main/cpp/skyline/services/visrv/IApplicationDisplayService.h @@ -88,6 +88,18 @@ namespace skyline::service::visrv { */ Result SetLayerScalingMode(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); + /** + * @brief Draws an indirect layer into the supplied buffer + * @url https://switchbrew.org/wiki/Display_services#GetIndirectLayerImageMap + */ + Result GetIndirectLayerImageMap(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); + + /** + * @brief Gets the amount of memory required for an indirect layer + * @url https://switchbrew.org/wiki/Display_services#GetIndirectLayerImageRequiredMemoryInfo + */ + Result GetIndirectLayerImageRequiredMemoryInfo(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); + /** * @brief Converts an arbitrary scaling mode to a VI scaling mode */ @@ -113,6 +125,8 @@ namespace skyline::service::visrv { SFUNC_BASE(0x7EF, IApplicationDisplayService, IDisplayService, DestroyStrayLayer), SFUNC(0x835, IApplicationDisplayService, SetLayerScalingMode), SFUNC(0x836, IApplicationDisplayService, ConvertScalingMode), + SFUNC(0x992, IApplicationDisplayService, GetIndirectLayerImageMap), + SFUNC(0x99C, IApplicationDisplayService, GetIndirectLayerImageRequiredMemoryInfo), SFUNC(0x1452, IApplicationDisplayService, GetDisplayVsyncEvent) ) }; diff --git a/app/src/main/cpp/skyline/services/visrv/results.h b/app/src/main/cpp/skyline/services/visrv/results.h index 17f051c5..bf637ec5 100644 --- a/app/src/main/cpp/skyline/services/visrv/results.h +++ b/app/src/main/cpp/skyline/services/visrv/results.h @@ -7,5 +7,6 @@ namespace skyline::service::visrv::result { constexpr Result InvalidArgument(114, 1); + constexpr Result InvalidDimensions(114, 4); constexpr Result IllegalOperation(114, 6); }