Add y2r:u commands
This commit is contained in:
parent
e2f8011f69
commit
8a76010988
@ -36,6 +36,7 @@ extern "C" {
|
||||
#include <3ds/services/mvd.h>
|
||||
#include <3ds/services/news.h>
|
||||
#include <3ds/services/qtm.h>
|
||||
#include <3ds/services/y2r.h>
|
||||
#include <3ds/services/hb.h>
|
||||
|
||||
#include <3ds/gpu/gx.h>
|
||||
|
117
libctru/include/3ds/services/y2r.h
Normal file
117
libctru/include/3ds/services/y2r.h
Normal file
@ -0,0 +1,117 @@
|
||||
#pragma once
|
||||
#include <3ds/types.h>
|
||||
|
||||
typedef enum
|
||||
{
|
||||
INPUT_YUV422_INDIV_8 = 0x0,
|
||||
INPUT_YUV420_INDIV_8 = 0x1,
|
||||
INPUT_YUV422_INDIV_16 = 0x2,
|
||||
INPUT_YUV420_INDIV_16 = 0x3,
|
||||
INPUT_YUV422_BATCH = 0x4,
|
||||
} Y2R_InputFormat;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
OUTPUT_RGB_32 = 0x0,
|
||||
OUTPUT_RGB_24 = 0x1,
|
||||
OUTPUT_RGB_16_555 = 0x2,
|
||||
OUTPUT_RGB_16_565 = 0x3,
|
||||
} Y2R_OutputFormat;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ROTATION_NONE = 0x0,
|
||||
ROTATION_CLOCKWISE_90 = 0x1,
|
||||
ROTATION_CLOCKWISE_180 = 0x2,
|
||||
ROTATION_CLOCKWISE_270 = 0x3,
|
||||
} Y2R_Rotation;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
BLOCK_LINE = 0x0,
|
||||
BLOCK_8_BY_8 = 0x1,
|
||||
} Y2R_BlockAlignment;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
COEFFICIENT_ITU_R_BT_601 = 0x0,
|
||||
COEFFICIENT_ITU_R_BT_709 = 0x1,
|
||||
COEFFICIENT_ITU_R_BT_601_SCALING = 0x2,
|
||||
COEFFICIENT_ITU_R_BT_709_SCALING = 0x3,
|
||||
} Y2R_StandardCoefficient;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Y2R_InputFormat input_format : 8;
|
||||
Y2R_OutputFormat output_format : 8;
|
||||
Y2R_Rotation rotation : 8;
|
||||
Y2R_BlockAlignment block_alignment : 8;
|
||||
u16 input_line_width;
|
||||
u16 input_lines;
|
||||
Y2R_StandardCoefficient standard_coefficient : 8;
|
||||
u8 unused;
|
||||
u16 alpha;
|
||||
} Y2R_ConversionParams;
|
||||
|
||||
/**
|
||||
* 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:
|
||||
* ```
|
||||
* 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)
|
||||
* ```
|
||||
*/
|
||||
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;
|
||||
|
||||
Result y2rInit();
|
||||
Result y2rExit();
|
||||
|
||||
Result Y2RU_SetInputFormat(Y2R_InputFormat format);
|
||||
Result Y2RU_SetOutputFormat(Y2R_OutputFormat format);
|
||||
Result Y2RU_SetRotation(Y2R_Rotation rotation);
|
||||
Result Y2RU_SetBlockAlignment(Y2R_BlockAlignment alignment);
|
||||
|
||||
Result Y2RU_SetTransferEndInterrupt(bool should_interrupt);
|
||||
Result Y2RU_GetTransferEndEvent(Handle* end_event);
|
||||
Result Y2RU_SetSendingY(const void* src_buf, u32 image_size, u16 transfer_unit, u16 transfer_gap);
|
||||
Result Y2RU_SetSendingU(const void* src_buf, u32 image_size, u16 transfer_unit, u16 transfer_gap);
|
||||
Result Y2RU_SetSendingV(const void* src_buf, u32 image_size, u16 transfer_unit, u16 transfer_gap);
|
||||
Result Y2RU_SetSendingYUYV(const void* src_buf, u32 image_size, u16 transfer_unit, u16 transfer_gap);
|
||||
Result Y2RU_IsDoneSendingYUYV(bool* is_done);
|
||||
Result Y2RU_IsDoneSendingY(bool* is_done);
|
||||
Result Y2RU_IsDoneSendingU(bool* is_done);
|
||||
Result Y2RU_IsDoneSendingV(bool* is_done);
|
||||
Result Y2RU_SetReceiving(void* dst_buf, u32 image_size, u16 transfer_unit, u16 transfer_gap);
|
||||
Result Y2RU_IsDoneReceiving(bool* is_done);
|
||||
Result Y2RU_SetInputLineWidth(u16 line_width);
|
||||
Result Y2RU_SetInputLines(u16 num_lines);
|
||||
Result Y2RU_SetCoefficient(const Y2R_ColorCoefficients* coefficient);
|
||||
Result Y2RU_SetStandardCoefficient(Y2R_StandardCoefficient coefficient);
|
||||
|
||||
Result Y2RU_SetAlpha(u16 alpha);
|
||||
Result Y2RU_SetUnknownParams(const u16 params[16]);
|
||||
Result Y2RU_StartConversion(void);
|
||||
Result Y2RU_StopConversion(void);
|
||||
Result Y2RU_IsBusyConversion(bool* is_busy);
|
||||
Result Y2RU_SetConversionParams(const Y2R_ConversionParams* params);
|
||||
|
||||
/* Seems to check whether y2r is ready to be used */
|
||||
Result Y2RU_PingProcess(u8* ping);
|
||||
|
||||
Result Y2RU_DriverInitialize(void);
|
||||
Result Y2RU_DriverFinalize(void);
|
||||
|
395
libctru/source/services/y2r.c
Normal file
395
libctru/source/services/y2r.c
Normal 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_SetCoefficient(const Y2R_ColorCoefficients* coefficient)
|
||||
{
|
||||
Result ret = 0;
|
||||
u32* cmdbuf = getThreadCommandBuffer();
|
||||
cmdbuf[0] = 0x001E0100;
|
||||
memcpy(&cmdbuf[1], coefficient, 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];
|
||||
}
|
Loading…
Reference in New Issue
Block a user