diff --git a/include/services/y2r.hpp b/include/services/y2r.hpp index 17ceaafa..3fe56f36 100644 --- a/include/services/y2r.hpp +++ b/include/services/y2r.hpp @@ -1,4 +1,5 @@ #pragma once +#include #include #include "helpers.hpp" #include "kernel_types.hpp" @@ -50,6 +51,15 @@ class Y2RService { Block8x8 = 1, // Output buffer's pixels are morton swizzled. Used when outputting to a GPU texture. }; + // https://github.com/citra-emu/citra/blob/ac9d72a95ca9a60de8d39484a14aecf489d6d016/src/core/hle/service/cam/y2r_u.cpp#L33 + using CoefficientSet = std::array; + static constexpr std::array standardCoefficients{{ + {{0x100, 0x166, 0xB6, 0x58, 0x1C5, -0x166F, 0x10EE, -0x1C5B}}, // ITU_Rec601 + {{0x100, 0x193, 0x77, 0x2F, 0x1DB, -0x1933, 0xA7C, -0x1D51}}, // ITU_Rec709 + {{0x12A, 0x198, 0xD0, 0x64, 0x204, -0x1BDE, 0x10F2, -0x229B}}, // ITU_Rec601_Scaling + {{0x12A, 0x1CA, 0x88, 0x36, 0x21C, -0x1F04, 0x99C, -0x2421}}, // ITU_Rec709_Scaling + }}; + InputFormat inputFmt; OutputFormat outputFmt; Rotation rotation; @@ -88,6 +98,7 @@ class Y2RService { void setSpacialDithering(u32 messagePointer); void setStandardCoeff(u32 messagePointer); void setTemporalDithering(u32 messagePointer); + void getStandardCoefficientParams(u32 messagePointer); void startConversion(u32 messagePointer); void stopConversion(u32 messagePointer); diff --git a/src/core/services/y2r.cpp b/src/core/services/y2r.cpp index 40a6a04d..9539f02a 100644 --- a/src/core/services/y2r.cpp +++ b/src/core/services/y2r.cpp @@ -24,6 +24,7 @@ namespace Y2RCommands { SetInputLines = 0x001C0040, GetInputLines = 0x001D0000, SetStandardCoeff = 0x00200040, + GetStandardCoefficientParams = 0x00210040, SetAlpha = 0x00220040, StartConversion = 0x00260000, StopConversion = 0x00270000, @@ -62,6 +63,7 @@ void Y2RService::handleSyncRequest(u32 messagePointer) { case Y2RCommands::GetInputLineWidth: getInputLineWidth(messagePointer); break; case Y2RCommands::GetOutputFormat: getOutputFormat(messagePointer); break; case Y2RCommands::GetTransferEndEvent: getTransferEndEvent(messagePointer); break; + case Y2RCommands::GetStandardCoefficientParams: getStandardCoefficientParams(messagePointer); break; case Y2RCommands::IsBusyConversion: isBusyConversion(messagePointer); break; case Y2RCommands::PingProcess: pingProcess(messagePointer); break; case Y2RCommands::SetAlpha: setAlpha(messagePointer); break; @@ -306,7 +308,7 @@ void Y2RService::setStandardCoeff(u32 messagePointer) { log("Y2R::SetStandardCoeff (coefficient = %d)\n", coeff); mem.write32(messagePointer, IPC::responseHeader(0x20, 1, 0)); - if (coeff > 3) { + if (coeff > 3) { // Invalid coefficient, should have an error code Helpers::panic("Y2R: Invalid standard coefficient (coefficient = %d)\n", coeff); } @@ -316,6 +318,25 @@ void Y2RService::setStandardCoeff(u32 messagePointer) { } } +void Y2RService::getStandardCoefficientParams(u32 messagePointer) { + const u32 coefficientIndex = mem.read32(messagePointer + 4); + log("Y2R::GetStandardCoefficientParams (coefficient = %d)\n", coefficientIndex); + + if (coefficientIndex > 3) { // Invalid coefficient, should have an error code + Helpers::panic("Y2R: Invalid standard coefficient (coefficient = %d)\n", coefficientIndex); + } else { + mem.write32(messagePointer, IPC::responseHeader(0x21, 5, 0)); + mem.write32(messagePointer + 4, Result::Success); + const auto& coeff = standardCoefficients[coefficientIndex]; + + // Write standard coefficient parameters to output buffer + for (int i = 0; i < 8; i++) { + const u32 pointer = messagePointer + 8 + i * sizeof(u16); // Pointer to write parameter to + mem.write16(pointer, coeff[i]); + } + } +} + void Y2RService::setSendingY(u32 messagePointer) { log("Y2R::SetSendingY\n"); Helpers::warn("Unimplemented Y2R::SetSendingY");