diff --git a/rpcs3/Emu/FS/vfsDir.cpp b/rpcs3/Emu/FS/vfsDir.cpp index 0d165c6ca5..8fcb8d4bde 100644 --- a/rpcs3/Emu/FS/vfsDir.cpp +++ b/rpcs3/Emu/FS/vfsDir.cpp @@ -30,7 +30,7 @@ bool vfsDir::Create(const wxString& path) bool vfsDir::IsExists(const wxString& path) const { - return m_stream->IsExists(path); + return m_stream->IsExists(path); // Crash (Access violation reading location 0x0000000000000000) } const Array& vfsDir::GetEntries() const diff --git a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp index d11dfa1c52..99346a4252 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp @@ -85,9 +85,15 @@ u32 dmuxOpen(Demuxer* data) break; case PADDING_STREAM: + { + stream.skip(4); + stream.get(len); + stream.skip(len); + } + break; + case PRIVATE_STREAM_2: { - // unknown stream.skip(4); stream.get(len); stream.skip(len); @@ -127,19 +133,19 @@ u32 dmuxOpen(Demuxer* data) stream.get(len); PesHeader pes(stream); - if (!pes.size && !es.hasdata()) // fatal error + if (!pes.new_au && !es.hasdata()) // fatal error { ConLog.Error("PES not found"); return; } - if (pes.size && es.hasdata()) // new AU detected + if (pes.new_au && es.hasdata()) // new AU detected { - /*if (es.hasunseen()) + if (es.hasunseen()) // hack, probably useless { stream = backup; continue; - }*/ + } es.finish(stream); // callback mem_ptr_t esMsg(a128(dmux.memAddr) + (cb_add ^= 16)); @@ -151,7 +157,7 @@ u32 dmuxOpen(Demuxer* data) cb.Branch(false); } - if (pes.size) + if (pes.new_au) { ConLog.Write("*** AVC AU detected (pts=0x%llx, dts=0x%llx)", pes.pts, pes.dts); } @@ -161,7 +167,6 @@ u32 dmuxOpen(Demuxer* data) stream = backup; continue; } - es.push(stream, len - pes.size - 3, pes); } else @@ -217,6 +222,19 @@ task: { case dmuxSetStream: { + bool do_wait = false; + for (u32 i = 0; i < 192; i++) + { + if (esALL[i]) + { + if (esALL[i]->hasunseen()) // hack, probably useless + { + do_wait = true; + break; + } + } + } + if (do_wait) continue; stream = task.stream; ConLog.Write("*** stream updated(addr=0x%x, size=0x%x, discont=%d, userdata=0x%llx)", stream.addr, stream.size, stream.discontinuity, stream.userdata); @@ -832,7 +850,9 @@ int cellDmuxPeekAuEx(u32 esHandle, mem32_t auInfoEx_ptr, mem32_t auSpecificInfo_ int cellDmuxReleaseAu(u32 esHandle) { - cellDmux.Log("cellDmuxReleaseAu(esHandle=0x%x)", esHandle); + cellDmux.Warning("(disabled) cellDmuxReleaseAu(esHandle=0x%x)", esHandle); + + return CELL_OK; ElementaryStream* es; if (!Emu.GetIdManager().GetIDData(esHandle, es)) @@ -842,7 +862,9 @@ int cellDmuxReleaseAu(u32 esHandle) if (!es->canrelease()) { + cellDmux.Error("cellDmuxReleaseAu: no AU"); return CELL_DMUX_ERROR_SEQ; + //return CELL_OK; } DemuxerTask task(dmuxReleaseAu); diff --git a/rpcs3/Emu/SysCalls/Modules/cellDmux.h b/rpcs3/Emu/SysCalls/Modules/cellDmux.h index a61918b01b..fad19dd63a 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellDmux.h +++ b/rpcs3/Emu/SysCalls/Modules/cellDmux.h @@ -366,23 +366,28 @@ struct PesHeader u64 dts; u8 ch; u8 size; + bool new_au; PesHeader(DemuxerStream& stream) - : pts(0) - , dts(0) + : pts(0xffffffffffffffff) + , dts(0xffffffffffffffff) , ch(0) , size(0) + , new_au(false) { u16 header; stream.get(header); stream.get(size); + new_au = true; if (size) { + //ConLog.Write(">>>>> Pes Header (size=%d)", size); if (size < 10) { - ConLog.Error("Unknown PesHeader size"); - Emu.Pause(); + stream.skip(size); + return; } + new_au = true; u8 v; stream.get(v); if ((v & 0xF0) != 0x30) @@ -454,8 +459,8 @@ public: const u32 cbFunc; const u32 cbArg; u32 id; - bool is_finished; - bool is_running; + volatile bool is_finished; + volatile bool is_running; Demuxer(u32 addr, u32 size, u32 func, u32 arg) diff --git a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp index 45cdf7f38a..2ded407750 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp @@ -6,6 +6,7 @@ extern "C" { #include "libavcodec\avcodec.h" +#include "libavutil\imgutils.h" } #include "cellVdec.h" @@ -26,8 +27,8 @@ u32 vdecQueryAttr(CellVdecCodecType type, u32 profile, u32 spec_addr /* may be 0 // TODO: check values attr->decoderVerLower = 0x280000; // from dmux attr->decoderVerUpper = 0x260000; - attr->memSize = 64 * 1024 * 1024; - attr->cmdDepth = 15; + attr->memSize = 4 * 1024 * 1024; + attr->cmdDepth = 16; return CELL_OK; } @@ -59,6 +60,12 @@ u32 vdecOpen(VideoDecoder* data) continue; } + if (vdec.has_picture) // hack + { + Sleep(1); + continue; + } + if (!vdec.job.Pop(task)) { break; @@ -76,7 +83,10 @@ u32 vdecOpen(VideoDecoder* data) case vdecEndSeq: { - // TODO: send callback + Callback cb; + cb.SetAddr(vdec.cbFunc); + cb.Handle(vdec.id, CELL_VDEC_MSG_TYPE_SEQDONE, 0, vdec.cbArg); + cb.Branch(false); ConLog.Warning("vdecEndSeq()"); vdec.is_running = false; } @@ -90,6 +100,7 @@ u32 vdecOpen(VideoDecoder* data) { av_new_packet(this, size + FF_INPUT_BUFFER_PADDING_SIZE); memset(data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE); + this->size -= FF_INPUT_BUFFER_PADDING_SIZE; // ???????????????????? } ~vdecPacket() @@ -99,8 +110,13 @@ u32 vdecOpen(VideoDecoder* data) } au(task.size); - au.pts = task.pts; - au.dts = task.dts; + if (task.pts || task.dts) + { + vdec.pts = task.pts; + vdec.dts = task.dts; + } + au.pts = vdec.pts; + au.dts = vdec.dts; if (task.mode != CELL_VDEC_DEC_MODE_NORMAL) { @@ -116,6 +132,9 @@ u32 vdecOpen(VideoDecoder* data) int got_picture = 0; + //vdec.ctx->flags |= CODEC_FLAG_TRUNCATED; + //vdec.ctx->flags2 |= CODEC_FLAG2_CHUNKS; + int decode = avcodec_decode_video2(vdec.ctx, vdec.frame, &got_picture, &au); if (decode < 0) { @@ -123,7 +142,48 @@ u32 vdecOpen(VideoDecoder* data) break; } - ConLog.Write("Frame decoded (%d)", decode); + ConLog.Write("Frame decoded (pts=0x%llx, dts=0x%llx, addr=0x%x, result=0x%x)", + au.pts, au.dts, task.addr, decode); + + + Callback cb; + cb.SetAddr(vdec.cbFunc); + cb.Handle(vdec.id, CELL_VDEC_MSG_TYPE_AUDONE, 0, vdec.cbArg); + cb.Branch(false); + + if (got_picture) + { + ConLog.Write("got_picture (%d, vdec: pts=0x%llx, dts=0x%llx)", got_picture, vdec.pts, vdec.dts); + + vdec.pts += 3003; + vdec.dts += 3003; + + /*if (vdec.out_data[0]) av_freep(vdec.out_data[0]); + + int err = av_image_alloc(vdec.out_data, vdec.linesize, vdec.ctx->width, vdec.ctx->height, vdec.ctx->pix_fmt, 1); + if (err < 0) + { + ConLog.Error("vdecDecodeAu: av_image_alloc failed(%d)", err); + Emu.Pause(); + return; + } + + vdec.buf_size = err; + + av_image_copy(vdec.out_data, vdec.linesize, (const u8**)(vdec.frame->data), vdec.frame->linesize, + vdec.ctx->pix_fmt, vdec.ctx->width, vdec.ctx->height);*/ + vdec.buf_size = a128(av_image_get_buffer_size(vdec.ctx->pix_fmt, vdec.ctx->width, vdec.ctx->height, 1)); + + vdec.dts = task.dts; + vdec.pts = task.pts; + vdec.userdata = task.userData; + vdec.has_picture = true; + + Callback cb; + cb.SetAddr(vdec.cbFunc); + cb.Handle(vdec.id, CELL_VDEC_MSG_TYPE_PICOUT, 0, vdec.cbArg); + cb.Branch(false); + } } break; @@ -137,6 +197,7 @@ u32 vdecOpen(VideoDecoder* data) case vdecSetFrameRate: { ConLog.Error("TODO: vdecSetFrameRate(%d)", task.frc); + return; } default: @@ -297,13 +358,162 @@ int cellVdecDecodeAu(u32 handle, CellVdecDecodeMode mode, const mem_ptr_t format, u32 out_addr) { - cellVdec.Error("cellVdecGetPicture(handle=%d, format_addr=0x%x, out_addr=0x%x)", handle, format.GetAddr(), out_addr); + cellVdec.Warning("cellVdecGetPicture(handle=%d, format_addr=0x%x, out_addr=0x%x)", handle, format.GetAddr(), out_addr); + + VideoDecoder* vdec; + if (!Emu.GetIdManager().GetIDData(handle, vdec)) + { + return CELL_VDEC_ERROR_ARG; + } + + if (!format.IsGood()) + { + return CELL_VDEC_ERROR_FATAL; + } + + if (!vdec->has_picture) + { + return CELL_VDEC_ERROR_EMPTY; + } + + if (out_addr) + { + if (!Memory.IsGoodAddr(out_addr, vdec->buf_size)) + { + return CELL_VDEC_ERROR_FATAL; + } + + if (format->formatType != CELL_VDEC_PICFMT_YUV420_PLANAR) + { + cellVdec.Error("cellVdecGetPicture: TODO: unknown formatType(%d)", (u32)format->formatType); + return CELL_OK; + } + if (format->colorMatrixType != CELL_VDEC_COLOR_MATRIX_TYPE_BT709) + { + cellVdec.Error("cellVdecGetPicture: TODO: unknown colorMatrixType(%d)", (u32)format->colorMatrixType); + return CELL_OK; + } + + AVFrame& frame = *vdec->frame; + + u8* buf = (u8*)malloc(vdec->buf_size); + if (!buf) + { + cellVdec.Error("cellVdecGetPicture: malloc failed (out of memory)"); + Emu.Pause(); + return CELL_OK; + } + + // TODO: zero padding bytes + + int err = av_image_copy_to_buffer(buf, vdec->buf_size, frame.data, frame.linesize, vdec->ctx->pix_fmt, frame.width, frame.height, 1); + if (err < 0) + { + cellVdec.Error("cellVdecGetPicture: av_image_copy_to_buffer failed(%d)", err); + Emu.Pause(); + } + + if (!Memory.CopyFromReal(out_addr, buf, vdec->buf_size)) + { + cellVdec.Error("cellVdecGetPicture: data copying failed"); + Emu.Pause(); + } + + /* + u32 size0 = frame.linesize[0] * frame.height; + u32 size1 = frame.linesize[1] * frame.height / 2; + u32 size2 = frame.linesize[2] * frame.height / 2; + ConLog.Write("*** size0=0x%x, size1=0x%x, size2=0x%x, buf_size=0x%x (res=0x%x)", size0, size1, size2, vdec->buf_size, err); + */ + + free(buf); + } + + vdec->has_picture = false; return CELL_OK; } -int cellVdecGetPicItem(u32 handle, const u32 picItem_ptr_addr) +int cellVdecGetPicItem(u32 handle, mem32_t picItem_ptr) { - cellVdec.Error("cellVdecGetPicItem(handle=%d, picItem_ptr_addr=0x%x)", handle, picItem_ptr_addr); + cellVdec.Warning("cellVdecGetPicItem(handle=%d, picItem_ptr_addr=0x%x)", handle, picItem_ptr.GetAddr()); + + VideoDecoder* vdec; + if (!Emu.GetIdManager().GetIDData(handle, vdec)) + { + return CELL_VDEC_ERROR_ARG; + } + + if (!picItem_ptr.IsGood()) + { + return CELL_VDEC_ERROR_FATAL; + } + + if (!vdec->has_picture) + { + return CELL_VDEC_ERROR_EMPTY; + } + + mem_ptr_t info(vdec->memAddr); + + info->codecType = vdec->type; + info->startAddr = 0x00000123; // invalid value (no address for picture) + info->size = vdec->buf_size; + info->auNum = 1; + info->auPts[0].lower = vdec->pts; + info->auPts[0].upper = vdec->pts >> 32; + info->auPts[1].lower = 0xffffffff; + info->auPts[1].upper = 0xffffffff; + info->auDts[0].lower = vdec->dts; + info->auDts[0].upper = vdec->dts >> 32; + info->auDts[1].lower = 0xffffffff; + info->auDts[1].upper = 0xffffffff; + info->auUserData[0] = vdec->userdata; + info->auUserData[1] = 0; + info->status = CELL_OK; + info->attr = CELL_VDEC_PICITEM_ATTR_NORMAL; + info->picInfo_addr = vdec->memAddr + sizeof(CellVdecPicItem); + + mem_ptr_t avc(vdec->memAddr + sizeof(CellVdecPicItem)); + + avc->horizontalSize = vdec->frame->width; // ??? + avc->verticalSize = vdec->frame->height; + switch (vdec->frame->pict_type) + { + case AV_PICTURE_TYPE_I: avc->pictureType[0] = CELL_VDEC_AVC_PCT_I; break; + case AV_PICTURE_TYPE_P: avc->pictureType[0] = CELL_VDEC_AVC_PCT_P; break; + case AV_PICTURE_TYPE_B: avc->pictureType[0] = CELL_VDEC_AVC_PCT_B; break; + default: avc->pictureType[0] = CELL_VDEC_AVC_PCT_UNKNOWN; break; // ??? + } + avc->pictureType[1] = CELL_VDEC_AVC_PCT_UNKNOWN; // ??? + avc->idrPictureFlag = false; // ??? + avc->aspect_ratio_idc = CELL_VDEC_AVC_ARI_SAR_UNSPECIFIED; // ??? + avc->sar_height = 0; + avc->sar_width = 0; + avc->pic_struct = CELL_VDEC_AVC_PSTR_FRAME; // ??? + avc->picOrderCount[0] = 0; // ??? + avc->picOrderCount[1] = 0; + avc->vui_parameters_present_flag = true; // ??? + avc->frame_mbs_only_flag = true; // ??? progressive + avc->video_signal_type_present_flag = true; // ??? + avc->video_format = CELL_VDEC_AVC_VF_COMPONENT; // ??? + avc->video_full_range_flag = false; // ??? + avc->colour_description_present_flag = true; + avc->colour_primaries = CELL_VDEC_AVC_CP_ITU_R_BT_709_5; // ??? + avc->transfer_characteristics = CELL_VDEC_AVC_TC_ITU_R_BT_709_5; + avc->matrix_coefficients = CELL_VDEC_AVC_MXC_ITU_R_BT_709_5; // important + avc->timing_info_present_flag = true; + avc->frameRateCode = CELL_VDEC_AVC_FRC_30000DIV1001; // important (!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!) + avc->fixed_frame_rate_flag = true; + avc->low_delay_hrd_flag = true; // ??? + avc->entropy_coding_mode_flag = true; // ??? + avc->nalUnitPresentFlags = 0; // ??? + avc->ccDataLength[0] = 0; + avc->ccDataLength[1] = 0; + avc->reserved[0] = 0; + avc->reserved[1] = 0; + + picItem_ptr = info.GetAddr(); + return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellVdec.h b/rpcs3/Emu/SysCalls/Modules/cellVdec.h index 69de466bca..e1c37aa250 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVdec.h +++ b/rpcs3/Emu/SysCalls/Modules/cellVdec.h @@ -2,6 +2,8 @@ #include "Utilities/SQueue.h" +#define a128(x) ((x + 127) & (~127)) + // Error Codes enum { @@ -341,16 +343,18 @@ struct CellVdecAvcInfo AVC_transfer_characteristics transfer_characteristics; AVC_matrix_coefficients matrix_coefficients; bool timing_info_present_flag; - CellVdecFrameRate frameRateCode; + AVC_FrameRateCode frameRateCode; // ??? bool fixed_frame_rate_flag; bool low_delay_hrd_flag; bool entropy_coding_mode_flag; - be_t nalUnitPresentFlags; + be_t nalUnitPresentFlags; u8 ccDataLength[2]; u8 ccData[2][CELL_VDEC_AVC_CCD_MAX]; be_t reserved[2]; }; +const int sz = sizeof(CellVdecAvcInfo); + // DIVX Profile enum DIVX_level : u8 { @@ -686,15 +690,21 @@ public: AVCodec* codec; AVCodecContext* ctx; AVFrame* frame; + AVDictionary* opts; + u32 buf_size; + u64 pts; + u64 dts; + u64 userdata; + volatile bool has_picture; - const u32 type; + const CellVdecCodecType type; const u32 profile; const u32 memAddr; const u32 memSize; const u32 cbFunc; const u32 cbArg; - VideoDecoder(u32 type, u32 profile, u32 addr, u32 size, u32 func, u32 arg) + VideoDecoder(CellVdecCodecType type, u32 profile, u32 addr, u32 size, u32 func, u32 arg) : type(type) , profile(profile) , memAddr(addr) @@ -703,6 +713,7 @@ public: , cbArg(arg) , is_finished(false) , is_running(false) + , has_picture(false) { codec = avcodec_find_decoder(AV_CODEC_ID_H264); if (!codec) @@ -718,7 +729,9 @@ public: Emu.Pause(); return; } - if (int err = avcodec_open2(ctx, codec, NULL)) // TODO: not multithread safe + opts = nullptr; + int err = avcodec_open2(ctx, codec, &opts); + if (err) // TODO: not multithread safe { ConLog.Error("VideoDecoder(): avcodec_open2 failed(%d)", err); Emu.Pause(); @@ -731,6 +744,8 @@ public: Emu.Pause(); return; } + //memset(&out_data, 0, sizeof(out_data)); + //memset(&linesize, 0, sizeof(linesize)); } ~VideoDecoder() @@ -741,5 +756,6 @@ public: avcodec_close(ctx); av_free(ctx); } + //if (out_data[0]) av_freep(out_data[0]); } }; \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/Modules/cellVpost.cpp b/rpcs3/Emu/SysCalls/Modules/cellVpost.cpp index 0154af54c1..8073080424 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVpost.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellVpost.cpp @@ -8,35 +8,186 @@ Module cellVpost(0x0008, cellVpost_init); int cellVpostQueryAttr(const mem_ptr_t cfgParam, mem_ptr_t attr) { - cellVpost.Error("cellVpostQueryAttr(cfgParam_addr=0x%x, attr_addr=0x%x)", cfgParam.GetAddr(), attr.GetAddr()); + 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.Error("cellVpostOpen(cfgParam_addr=0x%x, resource_addr=0x%x, handle_addr=0x%x)", + 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.Error("cellVpostOpenEx(cfgParam_addr=0x%x, resource_addr=0x%x, handle_addr=0x%x)", + 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.Error("cellVpostClose(handle=0x%x)", 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.Error("cellVpostExec(handle=0x%x, inPicBuff_addr=0x%x, ctrlParam_addr=0x%x, outPicBuff_addr=0x%x, picInfo_addr=0x%x)", + 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; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellVpost.h b/rpcs3/Emu/SysCalls/Modules/cellVpost.h index 3e54a55050..ab54a695fa 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVpost.h +++ b/rpcs3/Emu/SysCalls/Modules/cellVpost.h @@ -315,3 +315,14 @@ struct CellVpostPictureInfo be_t reserved1; be_t reserved2; }; + +class VpostInstance +{ +public: + const bool to_rgba; + + VpostInstance(bool rgba) + : to_rgba(rgba) + { + } +}; \ No newline at end of file diff --git a/rpcs3/Gui/MemoryViewer.cpp b/rpcs3/Gui/MemoryViewer.cpp index 41d2fc85fb..90e36a0175 100644 --- a/rpcs3/Gui/MemoryViewer.cpp +++ b/rpcs3/Gui/MemoryViewer.cpp @@ -29,10 +29,10 @@ MemoryViewerPanel::MemoryViewerPanel(wxWindow* parent) s_tools_mem_bytes.Add(sc_bytes); wxStaticBoxSizer& s_tools_mem_buttons = *new wxStaticBoxSizer(wxHORIZONTAL, this, "Control"); - wxButton* b_fprev = new wxButton(this, wxID_ANY, "\u00AB", wxDefaultPosition, wxSize(21, 21)); + wxButton* b_fprev = new wxButton(this, wxID_ANY, "<<", wxDefaultPosition, wxSize(21, 21)); wxButton* b_prev = new wxButton(this, wxID_ANY, "<", wxDefaultPosition, wxSize(21, 21)); wxButton* b_next = new wxButton(this, wxID_ANY, ">", wxDefaultPosition, wxSize(21, 21)); - wxButton* b_fnext = new wxButton(this, wxID_ANY, "\u00BB", wxDefaultPosition, wxSize(21, 21)); + wxButton* b_fnext = new wxButton(this, wxID_ANY, ">>", wxDefaultPosition, wxSize(21, 21)); s_tools_mem_buttons.Add(b_fprev); s_tools_mem_buttons.Add(b_prev); s_tools_mem_buttons.Add(b_next);