diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index 1bdf19e136..70c9339349 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp @@ -32,6 +32,9 @@ namespace Service::VI { +constexpr ResultCode ERR_OPERATION_FAILED{ErrorModule::VI, 1}; +constexpr ResultCode ERR_UNSUPPORTED{ErrorModule::VI, 6}; + struct DisplayInfo { /// The name of this particular display. char display_name[0x40]{"Default"}; @@ -874,6 +877,22 @@ public: ~IApplicationDisplayService() = default; private: + enum class ConvertedScaleMode : u64 { + Freeze = 0, + ScaleToWindow = 1, + ScaleAndCrop = 2, + None = 3, + PreserveAspectRatio = 4, + }; + + enum class NintendoScaleMode : u32 { + None = 0, + Freeze = 1, + ScaleToWindow = 2, + ScaleAndCrop = 3, + PreserveAspectRatio = 4, + }; + void GetRelayService(Kernel::HLERequestContext& ctx) { LOG_WARNING(Service_VI, "(STUBBED) called"); @@ -974,13 +993,27 @@ private: void SetLayerScalingMode(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const u32 scaling_mode = rp.Pop(); + const auto scaling_mode = rp.PopEnum(); const u64 unknown = rp.Pop(); - LOG_WARNING(Service_VI, "(STUBBED) called. scaling_mode=0x{:08X}, unknown=0x{:016X}", - scaling_mode, unknown); + LOG_DEBUG(Service_VI, "called. scaling_mode=0x{:08X}, unknown=0x{:016X}", + static_cast(scaling_mode), unknown); IPC::ResponseBuilder rb{ctx, 2}; + + if (scaling_mode > NintendoScaleMode::PreserveAspectRatio) { + LOG_ERROR(Service_VI, "Invalid scaling mode provided."); + rb.Push(ERR_OPERATION_FAILED); + return; + } + + if (scaling_mode != NintendoScaleMode::ScaleToWindow && + scaling_mode != NintendoScaleMode::PreserveAspectRatio) { + LOG_ERROR(Service_VI, "Unsupported scaling mode supplied."); + rb.Push(ERR_UNSUPPORTED); + return; + } + rb.Push(RESULT_SUCCESS); } @@ -1061,51 +1094,37 @@ private: rb.PushCopyObjects(vsync_event); } - enum class ConvertedScaleMode : u64 { - None = 0, // VI seems to name this as "Unknown" but lots of games pass it, assume it's no - // scaling/default - Freeze = 1, - ScaleToWindow = 2, - Crop = 3, - NoCrop = 4, - }; - - // This struct is different, currently it's 1:1 but this might change in the future. - enum class NintendoScaleMode : u32 { - None = 0, - Freeze = 1, - ScaleToWindow = 2, - Crop = 3, - NoCrop = 4, - }; - void ConvertScalingMode(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - auto mode = rp.PopEnum(); + const auto mode = rp.PopEnum(); LOG_DEBUG(Service_VI, "called mode={}", static_cast(mode)); - IPC::ResponseBuilder rb{ctx, 4}; - rb.Push(RESULT_SUCCESS); + const auto converted_mode = ConvertScalingModeImpl(mode); + + if (converted_mode.Succeeded()) { + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(RESULT_SUCCESS); + rb.PushEnum(*converted_mode); + } else { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(converted_mode.Code()); + } + } + + static ResultVal ConvertScalingModeImpl(NintendoScaleMode mode) { switch (mode) { case NintendoScaleMode::None: - rb.PushEnum(ConvertedScaleMode::None); - break; + return MakeResult(ConvertedScaleMode::None); case NintendoScaleMode::Freeze: - rb.PushEnum(ConvertedScaleMode::Freeze); - break; + return MakeResult(ConvertedScaleMode::Freeze); case NintendoScaleMode::ScaleToWindow: - rb.PushEnum(ConvertedScaleMode::ScaleToWindow); - break; - case NintendoScaleMode::Crop: - rb.PushEnum(ConvertedScaleMode::Crop); - break; - case NintendoScaleMode::NoCrop: - rb.PushEnum(ConvertedScaleMode::NoCrop); - break; + return MakeResult(ConvertedScaleMode::ScaleToWindow); + case NintendoScaleMode::ScaleAndCrop: + return MakeResult(ConvertedScaleMode::ScaleAndCrop); + case NintendoScaleMode::PreserveAspectRatio: + return MakeResult(ConvertedScaleMode::PreserveAspectRatio); default: - UNIMPLEMENTED_MSG("Unknown scaling mode {}", static_cast(mode)); - rb.PushEnum(ConvertedScaleMode::None); - break; + return ERR_OPERATION_FAILED; } }