Merge pull request #126 from yuriks/y2r

Add y2r:u commands
This commit is contained in:
fincs 2015-06-22 00:22:41 +02:00
commit 66b2e4548e
3 changed files with 766 additions and 0 deletions

View File

@ -36,6 +36,7 @@ extern "C" {
#include <3ds/services/mvd.h> #include <3ds/services/mvd.h>
#include <3ds/services/news.h> #include <3ds/services/news.h>
#include <3ds/services/qtm.h> #include <3ds/services/qtm.h>
#include <3ds/services/y2r.h>
#include <3ds/services/hb.h> #include <3ds/services/hb.h>
#include <3ds/gpu/gx.h> #include <3ds/gpu/gx.h>

View File

@ -0,0 +1,370 @@
/**
* @file y2r.h
*/
#pragma once
#include <3ds/types.h>
/**
* @brief Input color formats
*
* For the 16-bit per component formats, bits 15-8 are padding and 7-0 contains the value.
*/
typedef enum
{
INPUT_YUV422_INDIV_8 = 0x0, ///< 8-bit per component, planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples).\n Usually named YUV422P.
INPUT_YUV420_INDIV_8 = 0x1, ///< 8-bit per component, planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples).\n Usually named YUV420P.
INPUT_YUV422_INDIV_16 = 0x2, ///< 16-bit per component, planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples).\n Usually named YUV422P16.
INPUT_YUV420_INDIV_16 = 0x3, ///< 16-bit per component, planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples).\n Usually named YUV420P16.
INPUT_YUV422_BATCH = 0x4, ///< 8-bit per component, packed YUV 4:2:2, 16bpp, (Y0 Cb Y1 Cr).\n Usually named YUYV422.
} Y2R_InputFormat;
/**
* @brief Output color formats
*
* Those are the same as the framebuffer and GPU texture formats.
*/
typedef enum
{
OUTPUT_RGB_32 = 0x0, ///< The alpha component is the 8-bit value set by @ref Y2RU_SetAlpha
OUTPUT_RGB_24 = 0x1,
OUTPUT_RGB_16_555 = 0x2, ///< The alpha bit is the 7th bit of the alpha value set by @ref Y2RU_SetAlpha
OUTPUT_RGB_16_565 = 0x3,
} Y2R_OutputFormat;
/**
* @brief Rotation to be applied to the output
*/
typedef enum
{
ROTATION_NONE = 0x0,
ROTATION_CLOCKWISE_90 = 0x1,
ROTATION_CLOCKWISE_180 = 0x2,
ROTATION_CLOCKWISE_270 = 0x3,
} Y2R_Rotation;
/**
* @brief Block alignment of output
*
* Defines the way the output will be laid out in memory.
*/
typedef enum
{
BLOCK_LINE = 0x0, ///< The result buffer will be laid out in linear format, the usual way.
BLOCK_8_BY_8 = 0x1, ///< The result will be stored as 8x8 blocks in Z-order.\n Useful for textures since it is the format used by the PICA200.
} Y2R_BlockAlignment;
/**
* @brief Coefficients of the YUV->RGB conversion formula.
*
* A set of coefficients configuring the RGB to YUV conversion. Coefficients 0-4 are unsigned 2.8
* fixed pointer numbers representing entries on the conversion matrix, while coefficient 5-7 are
* signed 11.5 fixed point numbers added as offsets to the RGB result.
*
* The overall conversion process formula is:
* @code
* R = trunc((rgb_Y * Y + r_V * V) + 0.75 + r_offset)
* G = trunc((rgb_Y * Y - g_U * U - g_V * V) + 0.75 + g_offset)
* B = trunc((rgb_Y * Y + b_U * U ) + 0.75 + b_offset)
* @endcode
*/
typedef struct
{
u16 rgb_Y;
u16 r_V;
u16 g_V;
u16 g_U;
u16 b_U;
u16 r_offset;
u16 g_offset;
u16 b_offset;
} Y2R_ColorCoefficients;
/**
* @brief Preset conversion coefficients based on ITU standards for the YUV->RGB formula.
*
* For more details refer to @ref Y2R_ColorCoefficients
*/
typedef enum
{
COEFFICIENT_ITU_R_BT_601 = 0x0, ///< Coefficients from the ITU-R BT.601 standard with PC ranges.
COEFFICIENT_ITU_R_BT_709 = 0x1, ///< Coefficients from the ITU-R BT.709 standard with PC ranges.
COEFFICIENT_ITU_R_BT_601_SCALING = 0x2, ///< Coefficients from the ITU-R BT.601 standard with TV ranges.
COEFFICIENT_ITU_R_BT_709_SCALING = 0x3, ///< Coefficients from the ITU-R BT.709 standard with TV ranges.
} Y2R_StandardCoefficient;
/**
* @brief Structure used to configure all parameters at once.
*
* You can send a batch of configuration parameters using this structure and @ref Y2RU_SetConversionParams.
*
*/
typedef struct
{
Y2R_InputFormat input_format : 8; ///< Value passed to @ref Y2RU_SetInputFormat
Y2R_OutputFormat output_format : 8; ///< Value passed to @ref Y2RU_SetOutputFormat
Y2R_Rotation rotation : 8; ///< Value passed to @ref Y2RU_SetRotation
Y2R_BlockAlignment block_alignment : 8; ///< Value passed to @ref Y2RU_SetBlockAlignment
u16 input_line_width; ///< Value passed to @ref Y2RU_SetInputLineWidth
u16 input_lines; ///< Value passed to @ref Y2RU_SetInputLines
Y2R_StandardCoefficient standard_coefficient : 8; ///< Value passed to @ref Y2RU_SetStandardCoefficient
u8 unused;
u16 alpha; ///< Value passed to @ref Y2RU_SetAlpha
} Y2R_ConversionParams;
/**
* @brief Initializes the y2r service.
*
* This will internally get the handle of the service, and on success call Y2RU_DriverInitialize.
*/
Result y2rInit();
/**
* @brief Closes the y2r service.
*
* This will internally call Y2RU_DriverFinalize and close the handle of the service.
*/
Result y2rExit();
/**
* @brief Used to configure the input format.
*
* @note Prefer using @ref Y2RU_SetConversionParams if you have to set multiple parameters.
*/
Result Y2RU_SetInputFormat(Y2R_InputFormat format);
/**
* @brief Used to configure the output format.
*
* @note Prefer using @ref Y2RU_SetConversionParams if you have to set multiple parameters.
*/
Result Y2RU_SetOutputFormat(Y2R_OutputFormat format);
/**
* @brief Used to configure the rotation of the output.
*
* It seems to apply the rotation per batch of 8 lines, so the output will be (height/8) images of size 8 x width.
*
* @note Prefer using @ref Y2RU_SetConversionParams if you have to set multiple parameters.
*/
Result Y2RU_SetRotation(Y2R_Rotation rotation);
/**
* @brief Used to configure the alignment of the output buffer.
*
* @note Prefer using @ref Y2RU_SetConversionParams if you have to set multiple parameters.
*/
Result Y2RU_SetBlockAlignment(Y2R_BlockAlignment alignment);
/**
* @brief Used to configure the width of the image.
* @param line_width Width of the image in pixels. Must be a multiple of 8, up to 1024.
*
* @note Prefer using @ref Y2RU_SetConversionParams if you have to set multiple parameters.
*/
Result Y2RU_SetInputLineWidth(u16 line_width);
/**
* @brief Used to configure the height of the image.
* @param num_lines Number of lines to be converted.
*
* A multiple of 8 seems to be preferred.
* If using the @ref BLOCK_8_BY_8 mode, it must be a multiple of 8.
*
* @note Prefer using @ref Y2RU_SetConversionParams if you have to set multiple parameters.
*/
Result Y2RU_SetInputLines(u16 num_lines);
/**
* @brief Used to configure the color conversion formula.
*
* See @ref Y2R_ColorCoefficients for more information about the coefficients.
*
* @note Prefer using @ref Y2RU_SetConversionParams if you have to set multiple parameters.
*/
Result Y2RU_SetCoefficients(const Y2R_ColorCoefficients* coefficients);
/**
* @brief Used to configure the color conversion formula with ITU stantards coefficients.
*
* See @ref Y2R_ColorCoefficients for more information about the coefficients.
*
* @note Prefer using @ref Y2RU_SetConversionParams if you have to set multiple parameters.
*/
Result Y2RU_SetStandardCoefficient(Y2R_StandardCoefficient coefficient);
/**
* @brief Used to configure the alpha value of the output.
* @param alpha 8-bit value to be used for the output when the format requires it.
*
* @note Prefer using @ref Y2RU_SetConversionParams if you have to set multiple parameters.
*/
Result Y2RU_SetAlpha(u16 alpha);
/**
* @brief Used to enable the end of conversion interrupt.
* @param should_interrupt Enables the interrupt if true, disable it if false.
*
* It is possible to fire an interrupt when the conversion is finished, and that the DMA is done copying the data.
* This interrupt will then be used to fire an event. See @ref Y2RU_GetTransferEndEvent.
* By default the interrupt is enabled.
*
* @note It seems that the event can be fired too soon in some cases, depending the transfer_unit size.\n Please see the note at @ref Y2RU_SetReceiving
*/
Result Y2RU_SetTransferEndInterrupt(bool should_interrupt);
/**
* @brief Gets an handle to the end of conversion event.
* @param end_event Pointer to the event handle to be set to the end of conversion event. It isn't necessary to create or close this handle.
*
* To enable this event you have to use @code{C} Y2RU_SetTransferEndInterrupt(true);@endcode
* The event will be triggered when the corresponding interrupt is fired.
*
* @note It is recommended to use a timeout when waiting on this event, as it sometimes (but rarely) isn't triggered.
*/
Result Y2RU_GetTransferEndEvent(Handle* end_event);
/**
* @brief Configures the Y plane buffer.
* @param src_buf A pointer to the beginning of your Y data buffer.
* @param image_size The total size of the data buffer.
* @param transfer_unit Specifies the size of 1 DMA transfer. Usually set to 1 line. This has to be a divisor of image_size.
* @param transfer_unit Specifies the gap (offset) to be added after each transfer. Can be used to convert images with stride or only a part of it.
*
* This specifies the Y data buffer for the planar input formats (INPUT_YUV42*_INDIV_*).
* The actual transfer will only happen after calling @ref Y2RU_StartConversion.
*/
Result Y2RU_SetSendingY(const void* src_buf, u32 image_size, u16 transfer_unit, u16 transfer_gap);
/**
* @brief Configures the U plane buffer.
* @param src_buf A pointer to the beginning of your Y data buffer.
* @param image_size The total size of the data buffer.
* @param transfer_unit Specifies the size of 1 DMA transfer. Usually set to 1 line. This has to be a divisor of image_size.
* @param transfer_unit Specifies the gap (offset) to be added after each transfer. Can be used to convert images with stride or only a part of it.
*
* This specifies the U data buffer for the planar input formats (INPUT_YUV42*_INDIV_*).
* The actual transfer will only happen after calling @ref Y2RU_StartConversion.
*/
Result Y2RU_SetSendingU(const void* src_buf, u32 image_size, u16 transfer_unit, u16 transfer_gap);
/**
* @brief Configures the V plane buffer.
* @param src_buf A pointer to the beginning of your Y data buffer.
* @param image_size The total size of the data buffer.
* @param transfer_unit Specifies the size of 1 DMA transfer. Usually set to 1 line. This has to be a divisor of image_size.
* @param transfer_unit Specifies the gap (offset) to be added after each transfer. Can be used to convert images with stride or only a part of it.
*
* This specifies the V data buffer for the planar input formats (INPUT_YUV42*_INDIV_*).
* The actual transfer will only happen after calling @ref Y2RU_StartConversion.
*/
Result Y2RU_SetSendingV(const void* src_buf, u32 image_size, u16 transfer_unit, u16 transfer_gap);
/**
* @brief Configures the YUYV source buffer.
* @param src_buf A pointer to the beginning of your Y data buffer.
* @param image_size The total size of the data buffer.
* @param transfer_unit Specifies the size of 1 DMA transfer. Usually set to 1 line. This has to be a divisor of image_size.
* @param transfer_unit Specifies the gap (offset) to be added after each transfer. Can be used to convert images with stride or only a part of it.
*
* This specifies the YUYV data buffer for the packed input format @ref INPUT_YUV422_BATCH.
* The actual transfer will only happen after calling @ref Y2RU_StartConversion.
*/
Result Y2RU_SetSendingYUYV(const void* src_buf, u32 image_size, u16 transfer_unit, u16 transfer_gap);
/**
* @brief Configures the destination buffer.
* @param src_buf A pointer to the beginning of your destination buffer in FCRAM
* @param image_size The total size of the data buffer.
* @param transfer_unit Specifies the size of 1 DMA transfer. Usually set to 1 line. This has to be a divisor of image_size.
* @param transfer_unit Specifies the gap (offset) to be added after each transfer. Can be used to convert images with stride or only a part of it.
*
* This specifies the destination buffer of the conversion.
* The actual transfer will only happen after calling @ref Y2RU_StartConversion.
* The buffer does NOT need to be allocated in the linear heap.
*
* @note
* It seems that depending on the size of the image and of the transfer unit,\n
* it is possible for the end of conversion interrupt to be triggered right after the conversion began.\n
* One line as transfer_unit seems to trigger this issue for 400x240, setting to 2/4/8 lines fixes it.
*
* @note Setting a transfer_unit of 4 or 8 lines seems to bring the best results in terms of speed for a 400x240 image.
*/
Result Y2RU_SetReceiving(void* dst_buf, u32 image_size, u16 transfer_unit, u16 transfer_gap);
/**
* @brief Checks if the DMA has finished sending the Y buffer.
* @param is_done pointer to the boolean that will hold the result
*
* True if the DMA has finished transferring the Y plane, false otherwise. To be used with @ref Y2RU_SetSendingY.
*/
Result Y2RU_IsDoneSendingY(bool* is_done);
/**
* @brief Checks if the DMA has finished sending the U buffer.
* @param is_done pointer to the boolean that will hold the result
*
* True if the DMA has finished transferring the U plane, false otherwise. To be used with @ref Y2RU_SetSendingU.
*/
Result Y2RU_IsDoneSendingU(bool* is_done);
/**
* @brief Checks if the DMA has finished sending the V buffer.
* @param is_done pointer to the boolean that will hold the result
*
* True if the DMA has finished transferring the V plane, false otherwise. To be used with @ref Y2RU_SetSendingV.
*/
Result Y2RU_IsDoneSendingV(bool* is_done);
/**
* @brief Checks if the DMA has finished sending the YUYV buffer.
* @param is_done pointer to the boolean that will hold the result
*
* True if the DMA has finished transferring the YUYV buffer, false otherwise. To be used with @ref Y2RU_SetSendingYUYV.
*/
Result Y2RU_IsDoneSendingYUYV(bool* is_done);
/**
* @brief Checks if the DMA has finished sending the converted result.
* @param is_done pointer to the boolean that will hold the result
*
* True if the DMA has finished transferring data to your destination buffer, false otherwise.
*/
Result Y2RU_IsDoneReceiving(bool* is_done);
Result Y2RU_SetUnknownParams(const u16 params[16]);
/**
* @brief Sets all the parameters of Y2R_ConversionParams at once.
*
* Faster than calling the individual value through Y2R_Set* because only one system call is made.
*/
Result Y2RU_SetConversionParams(const Y2R_ConversionParams* params);
/**
* @brief Starts the conversion process
*/
Result Y2RU_StartConversion(void);
/**
* @brief Cancels the conversion
*/
Result Y2RU_StopConversion(void);
/**
* @brief Check if the conversion and DMA transfer are finished
*
* This can have the same problems as the event and interrupt. See @ref Y2RU_SetTransferEndInterrupt.
*/
Result Y2RU_IsBusyConversion(bool* is_busy);
/* Seems to check whether y2r is ready to be used */
Result Y2RU_PingProcess(u8* ping);
Result Y2RU_DriverInitialize(void);
Result Y2RU_DriverFinalize(void);

View File

@ -0,0 +1,395 @@
#include <stdlib.h>
#include <string.h>
#include <3ds/services/y2r.h>
#include <3ds/srv.h>
#include <3ds/svc.h>
#include <3ds/types.h>
Handle y2rHandle = 0;
static bool initialized = false;
Result y2rInit(void)
{
Result ret = 0;
if (initialized) return 0;
if (y2rHandle == 0)
{
ret = srvGetServiceHandle(&y2rHandle, "y2r:u");
if (ret < 0) return ret;
}
ret = Y2RU_DriverInitialize();
if (ret < 0) return ret;
initialized = true;
return 0;
}
Result y2rExit(void)
{
Result ret = 0;
if (initialized)
{
ret = Y2RU_DriverFinalize();
if (ret < 0) return ret;
}
if (y2rHandle != 0)
{
ret = svcCloseHandle(y2rHandle);
if (ret < 0) return ret;
y2rHandle = 0;
}
return 0;
}
Result Y2RU_SetInputFormat(Y2R_InputFormat format)
{
Result ret = 0;
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00010040;
cmdbuf[1] = format;
if ((ret = svcSendSyncRequest(y2rHandle)) != 0) return ret;
return cmdbuf[1];
}
Result Y2RU_SetOutputFormat(Y2R_OutputFormat format)
{
Result ret = 0;
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00030040;
cmdbuf[1] = format;
if ((ret = svcSendSyncRequest(y2rHandle)) != 0) return ret;
return cmdbuf[1];
}
Result Y2RU_SetRotation(Y2R_Rotation rotation)
{
Result ret = 0;
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00050040;
cmdbuf[1] = rotation;
if ((ret = svcSendSyncRequest(y2rHandle)) != 0) return ret;
return cmdbuf[1];
}
Result Y2RU_SetBlockAlignment(Y2R_BlockAlignment alignment)
{
Result ret = 0;
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00070040;
cmdbuf[1] = alignment;
if ((ret = svcSendSyncRequest(y2rHandle)) != 0) return ret;
return cmdbuf[1];
}
Result Y2RU_SetTransferEndInterrupt(bool should_interrupt)
{
Result ret = 0;
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x000D0040;
cmdbuf[1] = should_interrupt;
if ((ret = svcSendSyncRequest(y2rHandle)) != 0) return ret;
return cmdbuf[1];
}
Result Y2RU_GetTransferEndEvent(Handle* end_event)
{
if (*end_event != 0)
{
svcCloseHandle(*end_event);
*end_event = 0;
}
Result ret = 0;
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x000F0000;
if ((ret = svcSendSyncRequest(y2rHandle)) != 0) return ret;
*end_event = cmdbuf[3];
return cmdbuf[1];
}
Result Y2RU_SetSendingY(const void* src_buf, u32 image_size, u16 transfer_unit, u16 transfer_gap)
{
Result ret = 0;
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00100102;
cmdbuf[1] = (u32)src_buf;
cmdbuf[2] = image_size;
cmdbuf[3] = transfer_unit;
cmdbuf[4] = transfer_gap;
cmdbuf[5] = 0;
cmdbuf[6] = 0xFFFF8001;
if ((ret = svcSendSyncRequest(y2rHandle)) != 0) return ret;
return cmdbuf[1];
}
Result Y2RU_SetSendingU(const void* src_buf, u32 image_size, u16 transfer_unit, u16 transfer_gap)
{
Result ret = 0;
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00110102;
cmdbuf[1] = (u32)src_buf;
cmdbuf[2] = image_size;
cmdbuf[3] = transfer_unit;
cmdbuf[4] = transfer_gap;
cmdbuf[5] = 0;
cmdbuf[6] = 0xFFFF8001;
if ((ret = svcSendSyncRequest(y2rHandle)) != 0) return ret;
return cmdbuf[1];
}
Result Y2RU_SetSendingV(const void* src_buf, u32 image_size, u16 transfer_unit, u16 transfer_gap)
{
Result ret = 0;
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00120102;
cmdbuf[1] = (u32)src_buf;
cmdbuf[2] = image_size;
cmdbuf[3] = transfer_unit;
cmdbuf[4] = transfer_gap;
cmdbuf[5] = 0;
cmdbuf[6] = 0xFFFF8001;
if ((ret = svcSendSyncRequest(y2rHandle)) != 0) return ret;
return cmdbuf[1];
}
Result Y2RU_SetSendingYUYV(const void* src_buf, u32 image_size, u16 transfer_unit, u16 transfer_gap)
{
Result ret = 0;
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00130102;
cmdbuf[1] = (u32)src_buf;
cmdbuf[2] = image_size;
cmdbuf[3] = transfer_unit;
cmdbuf[4] = transfer_gap;
cmdbuf[5] = 0;
cmdbuf[6] = 0xFFFF8001;
if ((ret = svcSendSyncRequest(y2rHandle)) != 0) return ret;
return cmdbuf[1];
}
Result Y2RU_IsDoneSendingYUYV(bool* is_done)
{
Result ret = 0;
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00140000;
if ((ret = svcSendSyncRequest(y2rHandle)) != 0) return ret;
*is_done = cmdbuf[2] & 0xFF;
return cmdbuf[1];
}
Result Y2RU_IsDoneSendingY(bool* is_done)
{
Result ret = 0;
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00150000;
if ((ret = svcSendSyncRequest(y2rHandle)) != 0) return ret;
*is_done = cmdbuf[2] & 0xFF;
return cmdbuf[1];
}
Result Y2RU_IsDoneSendingU(bool* is_done)
{
Result ret = 0;
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00160000;
if ((ret = svcSendSyncRequest(y2rHandle)) != 0) return ret;
*is_done = cmdbuf[2] & 0xFF;
return cmdbuf[1];
}
Result Y2RU_IsDoneSendingV(bool* is_done)
{
Result ret = 0;
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00170000;
if ((ret = svcSendSyncRequest(y2rHandle)) != 0) return ret;
*is_done = cmdbuf[2] & 0xFF;
return cmdbuf[1];
}
Result Y2RU_SetReceiving(void* dst_buf, u32 image_size, u16 transfer_unit, u16 transfer_gap)
{
Result ret = 0;
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00180102;
cmdbuf[1] = (u32)dst_buf;
cmdbuf[2] = image_size;
cmdbuf[3] = transfer_unit;
cmdbuf[4] = transfer_gap;
cmdbuf[5] = 0;
cmdbuf[6] = 0xFFFF8001;
if ((ret = svcSendSyncRequest(y2rHandle)) != 0) return ret;
return cmdbuf[1];
}
Result Y2RU_IsDoneReceiving(bool* is_done)
{
Result ret = 0;
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00190000;
if ((ret = svcSendSyncRequest(y2rHandle)) != 0) return ret;
*is_done = cmdbuf[2] & 0xFF;
return cmdbuf[1];
}
Result Y2RU_SetInputLineWidth(u16 line_width)
{
Result ret = 0;
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x001A0040;
cmdbuf[1] = line_width;
if ((ret = svcSendSyncRequest(y2rHandle)) != 0) return ret;
return cmdbuf[1];
}
Result Y2RU_SetInputLines(u16 num_lines)
{
Result ret = 0;
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x001C0040;
cmdbuf[1] = num_lines;
if ((ret = svcSendSyncRequest(y2rHandle)) != 0) return ret;
return cmdbuf[1];
}
Result Y2RU_SetCoefficients(const Y2R_ColorCoefficients* coefficients)
{
Result ret = 0;
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x001E0100;
memcpy(&cmdbuf[1], coefficients, sizeof(Y2R_ColorCoefficients));
if ((ret = svcSendSyncRequest(y2rHandle)) != 0) return ret;
return cmdbuf[1];
}
Result Y2RU_SetStandardCoefficient(Y2R_StandardCoefficient coefficient)
{
Result ret = 0;
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00200040;
cmdbuf[1] = coefficient;
if ((ret = svcSendSyncRequest(y2rHandle)) != 0) return ret;
return cmdbuf[1];
}
Result Y2RU_SetAlpha(u16 alpha)
{
Result ret = 0;
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00220040;
cmdbuf[1] = alpha;
if ((ret = svcSendSyncRequest(y2rHandle)) != 0) return ret;
return cmdbuf[1];
}
Result Y2RU_SetUnknownParams(const u16 params[16])
{
Result ret = 0;
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00240200;
memcpy(&cmdbuf[1], params, sizeof(u16) * 16);
if ((ret = svcSendSyncRequest(y2rHandle)) != 0) return ret;
return cmdbuf[1];
}
Result Y2RU_StartConversion(void)
{
Result ret = 0;
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00260000;
if ((ret = svcSendSyncRequest(y2rHandle)) != 0) return ret;
return cmdbuf[1];
}
Result Y2RU_StopConversion(void)
{
Result ret = 0;
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00270000;
if ((ret = svcSendSyncRequest(y2rHandle)) != 0) return ret;
return cmdbuf[1];
}
Result Y2RU_IsBusyConversion(bool* is_busy)
{
Result ret = 0;
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x00280000;
if ((ret = svcSendSyncRequest(y2rHandle)) != 0) return ret;
*is_busy = cmdbuf[2] & 0xFF;
return cmdbuf[1];
}
Result Y2RU_SetConversionParams(const Y2R_ConversionParams* params)
{
Result ret = 0;
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x002900C0;
memcpy(&cmdbuf[1], params, sizeof(Y2R_ConversionParams));
if ((ret = svcSendSyncRequest(y2rHandle)) != 0) return ret;
return cmdbuf[1];
}
Result Y2RU_PingProcess(u8* ping)
{
Result ret = 0;
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x002A0000;
if ((ret = svcSendSyncRequest(y2rHandle)) != 0) return ret;
*ping = (u8)cmdbuf[2];
return cmdbuf[1];
}
Result Y2RU_DriverInitialize(void)
{
Result ret = 0;
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x002B0000;
if ((ret = svcSendSyncRequest(y2rHandle)) != 0) return ret;
return cmdbuf[1];
}
Result Y2RU_DriverFinalize(void)
{
Result ret = 0;
u32* cmdbuf = getThreadCommandBuffer();
cmdbuf[0] = 0x002C0000;
if ((ret = svcSendSyncRequest(y2rHandle)) != 0) return ret;
return cmdbuf[1];
}