From 171733870d6884d279ba7070b5b303a89d10bfcd Mon Sep 17 00:00:00 2001 From: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> Date: Wed, 1 Nov 2023 22:49:50 +0200 Subject: [PATCH 1/4] Add Y2R::GetStandardCoefficientParams --- include/services/y2r.hpp | 11 +++++++++++ src/core/services/y2r.cpp | 23 ++++++++++++++++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) 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"); From cc130d52e92bba095fafd726f99d3b46e2c2123b Mon Sep 17 00:00:00 2001 From: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> Date: Wed, 1 Nov 2023 23:01:38 +0200 Subject: [PATCH 2/4] Add Y2R::GetCoefficientParams --- include/services/y2r.hpp | 3 +++ src/core/services/y2r.cpp | 22 ++++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/include/services/y2r.hpp b/include/services/y2r.hpp index 3fe56f36..8b30525c 100644 --- a/include/services/y2r.hpp +++ b/include/services/y2r.hpp @@ -60,6 +60,8 @@ class Y2RService { {{0x12A, 0x1CA, 0x88, 0x36, 0x21C, -0x1F04, 0x99C, -0x2421}}, // ITU_Rec709_Scaling }}; + CoefficientSet conversionCoefficients; // Current conversion coefficients + InputFormat inputFmt; OutputFormat outputFmt; Rotation rotation; @@ -98,6 +100,7 @@ class Y2RService { void setSpacialDithering(u32 messagePointer); void setStandardCoeff(u32 messagePointer); void setTemporalDithering(u32 messagePointer); + void getCoefficientParams(u32 messagePointer); void getStandardCoefficientParams(u32 messagePointer); void startConversion(u32 messagePointer); diff --git a/src/core/services/y2r.cpp b/src/core/services/y2r.cpp index 9539f02a..44a04958 100644 --- a/src/core/services/y2r.cpp +++ b/src/core/services/y2r.cpp @@ -23,6 +23,7 @@ namespace Y2RCommands { GetInputLineWidth = 0x001B0000, SetInputLines = 0x001C0040, GetInputLines = 0x001D0000, + GetCoefficientParams = 0x001F0000, SetStandardCoeff = 0x00200040, GetStandardCoefficientParams = 0x00210040, SetAlpha = 0x00220040, @@ -51,6 +52,8 @@ void Y2RService::reset() { alpha = 0xFFFF; inputLines = 69; inputLineWidth = 420; + + conversionCoefficients.fill(0); } void Y2RService::handleSyncRequest(u32 messagePointer) { @@ -84,6 +87,9 @@ void Y2RService::handleSyncRequest(u32 messagePointer) { case Y2RCommands::SetTransferEndInterrupt: setTransferEndInterrupt(messagePointer); break; case Y2RCommands::StartConversion: [[likely]] startConversion(messagePointer); break; case Y2RCommands::StopConversion: stopConversion(messagePointer); break; + + // Intentionally break ordering a bit for less-used Y2R functions + case Y2RCommands::GetCoefficientParams: getCoefficientParams(messagePointer); break; default: Helpers::panic("Y2R service requested. Command: %08X\n", command); } } @@ -99,6 +105,8 @@ void Y2RService::driverInitialize(u32 messagePointer) { log("Y2R::DriverInitialize\n"); mem.write32(messagePointer, IPC::responseHeader(0x2B, 1, 0)); mem.write32(messagePointer + 4, Result::Success); + + conversionCoefficients.fill(0); } void Y2RService::driverFinalize(u32 messagePointer) { @@ -337,6 +345,20 @@ void Y2RService::getStandardCoefficientParams(u32 messagePointer) { } } +void Y2RService::getCoefficientParams(u32 messagePointer) { + log("Y2R::GetCoefficientParams\n"); + mem.write32(messagePointer, IPC::responseHeader(0x1F, 5, 0)); + mem.write32(messagePointer + 4, Result::Success); + const auto& coeff = conversionCoefficients; + + // Write 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"); From 0b56427019e82ca7705680f4e7b1da46cccdc28d Mon Sep 17 00:00:00 2001 From: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> Date: Wed, 1 Nov 2023 23:09:07 +0200 Subject: [PATCH 3/4] Add Y2R::SetCoefficientParams --- include/services/y2r.hpp | 1 + src/core/services/y2r.cpp | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/include/services/y2r.hpp b/include/services/y2r.hpp index 8b30525c..0a1cae2f 100644 --- a/include/services/y2r.hpp +++ b/include/services/y2r.hpp @@ -87,6 +87,7 @@ class Y2RService { void setAlpha(u32 messagePointer); void setBlockAlignment(u32 messagePointer); + void setCoefficientParams(u32 messagePointer); void setInputFormat(u32 messagePointer); void setInputLineWidth(u32 messagePointer); void setInputLines(u32 messagePointer); diff --git a/src/core/services/y2r.cpp b/src/core/services/y2r.cpp index 44a04958..62f933f6 100644 --- a/src/core/services/y2r.cpp +++ b/src/core/services/y2r.cpp @@ -23,6 +23,7 @@ namespace Y2RCommands { GetInputLineWidth = 0x001B0000, SetInputLines = 0x001C0040, GetInputLines = 0x001D0000, + SetCoefficientParams = 0x001E0100, GetCoefficientParams = 0x001F0000, SetStandardCoeff = 0x00200040, GetStandardCoefficientParams = 0x00210040, @@ -89,6 +90,7 @@ void Y2RService::handleSyncRequest(u32 messagePointer) { case Y2RCommands::StopConversion: stopConversion(messagePointer); break; // Intentionally break ordering a bit for less-used Y2R functions + case Y2RCommands::SetCoefficientParams: setCoefficientParams(messagePointer); break; case Y2RCommands::GetCoefficientParams: getCoefficientParams(messagePointer); break; default: Helpers::panic("Y2R service requested. Command: %08X\n", command); } @@ -345,6 +347,19 @@ void Y2RService::getStandardCoefficientParams(u32 messagePointer) { } } +void Y2RService::setCoefficientParams(u32 messagePointer) { + log("Y2R::SetCoefficientParams\n"); + mem.write32(messagePointer, IPC::responseHeader(0x1E, 1, 0)); + mem.write32(messagePointer + 4, Result::Success); + auto& coeff = conversionCoefficients; + + // Write 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 + coeff[i] = mem.read16(pointer); + } +} + void Y2RService::getCoefficientParams(u32 messagePointer) { log("Y2R::GetCoefficientParams\n"); mem.write32(messagePointer, IPC::responseHeader(0x1F, 5, 0)); @@ -358,7 +373,6 @@ void Y2RService::getCoefficientParams(u32 messagePointer) { } } - void Y2RService::setSendingY(u32 messagePointer) { log("Y2R::SetSendingY\n"); Helpers::warn("Unimplemented Y2R::SetSendingY"); From 42252e6442a791b8ebf4a50b9681308e4a30fa1b Mon Sep 17 00:00:00 2001 From: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> Date: Wed, 1 Nov 2023 23:29:09 +0200 Subject: [PATCH 4/4] Fix Y2R::SetCoefficientParams --- src/core/services/y2r.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/core/services/y2r.cpp b/src/core/services/y2r.cpp index 62f933f6..b5daf6bb 100644 --- a/src/core/services/y2r.cpp +++ b/src/core/services/y2r.cpp @@ -288,6 +288,7 @@ void Y2RService::getInputLineWidth(u32 messagePointer) { mem.write32(messagePointer + 4, Result::Success); mem.write32(messagePointer + 8, inputLineWidth); } + void Y2RService::setInputLines(u32 messagePointer) { const u16 lines = mem.read16(messagePointer + 4); log("Y2R::SetInputLines (lines = %d)\n", lines); @@ -349,15 +350,16 @@ void Y2RService::getStandardCoefficientParams(u32 messagePointer) { void Y2RService::setCoefficientParams(u32 messagePointer) { log("Y2R::SetCoefficientParams\n"); - mem.write32(messagePointer, IPC::responseHeader(0x1E, 1, 0)); - mem.write32(messagePointer + 4, Result::Success); auto& coeff = conversionCoefficients; // Write 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 + const u32 pointer = messagePointer + 4 + i * sizeof(u16); // Pointer to write parameter to coeff[i] = mem.read16(pointer); } + + mem.write32(messagePointer, IPC::responseHeader(0x1E, 1, 0)); + mem.write32(messagePointer + 4, Result::Success); } void Y2RService::getCoefficientParams(u32 messagePointer) {