#include "stdafx.h" #include "Emu/SysCalls/SysCalls.h" #include "Emu/SysCalls/SC_FUNC.h" #include "cellVpost.h" void cellVpost_init(); Module cellVpost(0x0008, cellVpost_init); int cellVpostQueryAttr(const mem_ptr_t cfgParam, mem_ptr_t attr) { cellVpost.Warning("cellVpostQueryAttr(cfgParam_addr=0x%x, attr_addr=0x%x)", cfgParam.GetAddr(), attr.GetAddr()); if (!cfgParam.IsGood()) return CELL_VPOST_ERROR_Q_ARG_CFG_NULL; if (!attr.IsGood()) return CELL_VPOST_ERROR_Q_ARG_ATTR_NULL; // TODO: check cfgParam and output values attr->delay = 0; attr->memSize = 4 * 1024 * 1024; attr->vpostVerLower = 0x280000; // from dmux attr->vpostVerUpper = 0x260000; return CELL_OK; } u32 vpostOpen(VpostInstance* data) { u32 id = cellVpost.GetNewId(data); ConLog.Write("*** Vpost instance created (to_rgba=%d): id = %d", data->to_rgba, id); return id; } int cellVpostOpen(const mem_ptr_t cfgParam, const mem_ptr_t resource, mem32_t handle) { cellVpost.Warning("cellVpostOpen(cfgParam_addr=0x%x, resource_addr=0x%x, handle_addr=0x%x)", cfgParam.GetAddr(), resource.GetAddr(), handle.GetAddr()); if (!cfgParam.IsGood()) return CELL_VPOST_ERROR_O_ARG_CFG_NULL; if (!resource.IsGood()) return CELL_VPOST_ERROR_O_ARG_RSRC_NULL; if (!handle.IsGood()) return CELL_VPOST_ERROR_O_ARG_HDL_NULL; // TODO: check values handle = vpostOpen(new VpostInstance(cfgParam->outPicFmt == CELL_VPOST_PIC_FMT_OUT_RGBA_ILV)); return CELL_OK; } int cellVpostOpenEx(const mem_ptr_t cfgParam, const mem_ptr_t resource, mem32_t handle) { cellVpost.Warning("cellVpostOpenEx(cfgParam_addr=0x%x, resource_addr=0x%x, handle_addr=0x%x)", cfgParam.GetAddr(), resource.GetAddr(), handle.GetAddr()); if (!cfgParam.IsGood()) return CELL_VPOST_ERROR_O_ARG_CFG_NULL; if (!resource.IsGood()) return CELL_VPOST_ERROR_O_ARG_RSRC_NULL; if (!handle.IsGood()) return CELL_VPOST_ERROR_O_ARG_HDL_NULL; // TODO: check values handle = vpostOpen(new VpostInstance(cfgParam->outPicFmt == CELL_VPOST_PIC_FMT_OUT_RGBA_ILV)); return CELL_OK; } int cellVpostClose(u32 handle) { cellVpost.Warning("cellVpostClose(handle=0x%x)", handle); VpostInstance* vpost; if (!Emu.GetIdManager().GetIDData(handle, vpost)) { return CELL_VPOST_ERROR_C_ARG_HDL_INVALID; } Emu.GetIdManager().RemoveID(handle); return CELL_OK; } int cellVpostExec(u32 handle, const u32 inPicBuff_addr, const mem_ptr_t ctrlParam, u32 outPicBuff_addr, mem_ptr_t picInfo) { cellVpost.Warning("cellVpostExec(handle=0x%x, inPicBuff_addr=0x%x, ctrlParam_addr=0x%x, outPicBuff_addr=0x%x, picInfo_addr=0x%x)", handle, inPicBuff_addr, ctrlParam.GetAddr(), outPicBuff_addr, picInfo.GetAddr()); VpostInstance* vpost; if (!Emu.GetIdManager().GetIDData(handle, vpost)) { return CELL_VPOST_ERROR_E_ARG_HDL_INVALID; } if (!ctrlParam.IsGood()) { return CELL_VPOST_ERROR_E_ARG_CTRL_INVALID; } u32 w = ctrlParam->inWidth; u32 h = ctrlParam->inHeight; if (!Memory.IsGoodAddr(inPicBuff_addr, w*h*3/2)) { return CELL_VPOST_ERROR_E_ARG_INPICBUF_INVALID; } if (!Memory.IsGoodAddr(outPicBuff_addr, w*h*4)) { return CELL_VPOST_ERROR_E_ARG_OUTPICBUF_INVALID; } if (!picInfo.IsGood()) { return CELL_VPOST_ERROR_E_ARG_PICINFO_NULL; } ctrlParam->inWindow; // ignored ctrlParam->outWindow; // ignored ctrlParam->execType; // ignored ctrlParam->scalerType; // ignored ctrlParam->ipcType; // ignored picInfo->inWidth = ctrlParam->inWidth; // copy picInfo->inHeight = ctrlParam->inHeight; // copy picInfo->inDepth = CELL_VPOST_PIC_DEPTH_8; // fixed picInfo->inScanType = CELL_VPOST_SCAN_TYPE_P; // TODO picInfo->inPicFmt = CELL_VPOST_PIC_FMT_IN_YUV420_PLANAR; // fixed picInfo->inChromaPosType = ctrlParam->inChromaPosType; // copy picInfo->inPicStruct = CELL_VPOST_PIC_STRUCT_PFRM; // TODO picInfo->inQuantRange = ctrlParam->inQuantRange; // copy picInfo->inColorMatrix = ctrlParam->inColorMatrix; // copy picInfo->outWidth = picInfo->inWidth; // TODO (resampling) picInfo->outHeight = picInfo->inHeight; // TODO picInfo->outDepth = CELL_VPOST_PIC_DEPTH_8; // fixed picInfo->outScanType = CELL_VPOST_SCAN_TYPE_P; // TODO picInfo->outPicFmt = CELL_VPOST_PIC_FMT_OUT_RGBA_ILV; // TODO picInfo->outChromaPosType = ctrlParam->inChromaPosType; // ??? picInfo->outPicStruct = picInfo->inPicStruct; // ??? picInfo->outQuantRange = ctrlParam->inQuantRange; // ??? picInfo->outColorMatrix = ctrlParam->inColorMatrix; // ??? picInfo->userData = ctrlParam->userData; // copy picInfo->reserved1 = 0; picInfo->reserved2 = 0; u8* pY = (u8*)malloc(w*h); u8* pU = (u8*)malloc(w*h/4); u8* pV = (u8*)malloc(w*h/4); u32* res = (u32*)malloc(w*h*4); const u8 alpha = ctrlParam->outAlpha; if (!Memory.CopyToReal(pY, inPicBuff_addr, w*h)) { cellVpost.Error("cellVpostExec: data copying failed(pY)"); } if (!Memory.CopyToReal(pU, inPicBuff_addr + w*h, w*h/4)) { cellVpost.Error("cellVpostExec: data copying failed(pU)"); } if (!Memory.CopyToReal(pV, inPicBuff_addr + w*h + w*h/4, w*h/4)) { cellVpost.Error("cellVpostExec: data copying failed(pV)"); } for (u32 i = 0; i < h; i++) for (u32 j = 0; j < w; j++) { float Cr = pV[(i/2)*(w/2)+j/2]; float Cb = pU[(i/2)*(w/2)+j/2]; float Y = pY[i*w+j]; int R = Y + 1.5701f * Cr; if (R < 0) R = 0; if (R > 255) R = 255; int G = Y - 0.1870f * Cb - 0.4664f * Cr; if (G < 0) G = 0; if (G > 255) G = 255; int B = Y - 1.8556f * Cb; if (B < 0) B = 0; if (B > 255) B = 255; res[i*w+j] = ((u32)alpha << 24) | (B << 16) | (G << 8) | (R); } if (!Memory.CopyFromReal(outPicBuff_addr, res, w*h*4)) { cellVpost.Error("cellVpostExec: data copying failed(result)"); Emu.Pause(); } free(pY); free(pU); free(pV); free(res); return CELL_OK; } void cellVpost_init() { cellVpost.AddFunc(0x95e788c3, cellVpostQueryAttr); cellVpost.AddFunc(0xcd33f3e2, cellVpostOpen); cellVpost.AddFunc(0x40524325, cellVpostOpenEx); cellVpost.AddFunc(0x10ef39f6, cellVpostClose); cellVpost.AddFunc(0xabb8cc3d, cellVpostExec); }