From 09dde13b197b0fa82e3a8c1400960004ddc78cde Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 18 May 2014 19:18:49 -0700 Subject: [PATCH 1/9] Fix minor typo in comment. --- Globals.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Globals.h b/Globals.h index 29dd89363f..f5a3c869c5 100644 --- a/Globals.h +++ b/Globals.h @@ -32,7 +32,7 @@ inline u8 Convert4To8(u8 v) { - // Swizzle bits: 00012345 -> 12345123 + // Swizzle bits: 00001234 -> 12341234 return (v << 4) | (v); } From 55fd30b52022d6caef36513d2df54275b2696677 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 18 May 2014 19:20:34 -0700 Subject: [PATCH 2/9] Skip a bit of work when syncing video/audio. --- Core/HLE/scePsmf.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/HLE/scePsmf.cpp b/Core/HLE/scePsmf.cpp index 7ab27c2bb0..1f045bdc0d 100644 --- a/Core/HLE/scePsmf.cpp +++ b/Core/HLE/scePsmf.cpp @@ -1464,7 +1464,7 @@ int scePsmfPlayerGetVideoData(u32 psmfPlayer, u32 videoDataAddr) } else { // This is an approximation, it should allow a certain amount ahead before skipping frames. while (deltapts <= -(VIDEO_FRAME_DURATION_TS * 5)) { - psmfplayer->mediaengine->stepVideo(videoPixelMode); + psmfplayer->mediaengine->stepVideo(videoPixelMode, true); deltapts = psmfplayer->mediaengine->getVideoTimeStamp() - psmfplayer->mediaengine->getAudioTimeStamp(); } } From 242fe2f3a9b26b11bf085e39c8aa2f03593ad6ff Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 18 May 2014 19:26:05 -0700 Subject: [PATCH 3/9] scePsmfPlayerGetVideoData() writes every frame. Thought it didn't due to dcache not being invalidated. Fixes #6085. --- Core/HLE/scePsmf.cpp | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/Core/HLE/scePsmf.cpp b/Core/HLE/scePsmf.cpp index 1f045bdc0d..2ce04c8f25 100644 --- a/Core/HLE/scePsmf.cpp +++ b/Core/HLE/scePsmf.cpp @@ -1451,16 +1451,13 @@ int scePsmfPlayerGetVideoData(u32 psmfPlayer, u32 videoDataAddr) auto videoData = PSPPointer::Create(videoDataAddr); if (videoData.IsValid()) { + bool doVideoStep = true; if (!psmfplayer->mediaengine->IsNoAudioData()) { s64 deltapts = psmfplayer->mediaengine->getVideoTimeStamp() - psmfplayer->mediaengine->getAudioTimeStamp(); if (deltapts > 0) { // Don't advance, just return the same frame again. // TODO: This also seems somewhat based on Update() calls, but audio is involved too... - int displaybufSize = psmfplayer->mediaengine->writeVideoImage(videoData->displaybuf, videoData->frameWidth, videoPixelMode); - // Need to invalidate, even if it didn't change, to trigger upload to framebuffer. - gpu->InvalidateCache(videoData->displaybuf, displaybufSize, GPU_INVALIDATE_SAFE); - __PsmfUpdatePts(psmfplayer, videoData); - return hleDelayResult(0, "psmfPlayer behind audio", 3000); + doVideoStep = false; } else { // This is an approximation, it should allow a certain amount ahead before skipping frames. while (deltapts <= -(VIDEO_FRAME_DURATION_TS * 5)) { @@ -1471,14 +1468,13 @@ int scePsmfPlayerGetVideoData(u32 psmfPlayer, u32 videoDataAddr) } else { // No audio, based on Update() calls. playSpeed doesn't seem to matter? if (psmfplayer->videoStep <= 1) { - // In this case, don't advance but also don't write the video frame. - videoData->displaypts = (u32)psmfplayer->psmfPlayerAvcAu.pts; - return hleDelayResult(0, "psmfPlayer behind", 3000); + doVideoStep = false; + } else { + psmfplayer->videoStep = 0; } - psmfplayer->videoStep = 0; } - if (psmfplayer->mediaengine->stepVideo(videoPixelMode)) { + if (!doVideoStep || psmfplayer->mediaengine->stepVideo(videoPixelMode)) { int displaybufSize = psmfplayer->mediaengine->writeVideoImage(videoData->displaybuf, videoData->frameWidth, videoPixelMode); gpu->InvalidateCache(videoData->displaybuf, displaybufSize, GPU_INVALIDATE_SAFE); } From 923189ab47477f51fcab5f2c7eb0943d5372a8b2 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 18 May 2014 20:30:58 -0700 Subject: [PATCH 4/9] Prevent a crash on bogus data in psmfplayer. --- Core/HLE/scePsmf.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Core/HLE/scePsmf.cpp b/Core/HLE/scePsmf.cpp index 2ce04c8f25..f14be11e57 100644 --- a/Core/HLE/scePsmf.cpp +++ b/Core/HLE/scePsmf.cpp @@ -1101,6 +1101,11 @@ int _PsmfPlayerSetPsmfOffset(u32 psmfPlayer, const char *filename, int offset, b // TODO: Merge better with Psmf. u16 numStreams = *(u16_be *)(buf + 0x80); + if (numStreams > 128) { + ERROR_LOG_REPORT(ME, "scePsmfPlayerSetPsmf*: too many streams in PSMF video, bogus data"); + return SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT; + } + psmfplayer->totalVideoStreams = 0; psmfplayer->totalAudioStreams = 0; psmfplayer->playerVersion = PSMF_PLAYER_VERSION_FULL; From cd9d85caff10a18e25130f031f2a48a5a5205223 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 18 May 2014 20:43:10 -0700 Subject: [PATCH 5/9] Add a delay when setting the psmfplayer file. This roughly matches the delay that occurs on a real PSP, during which other threads can run. --- Core/HLE/scePsmf.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Core/HLE/scePsmf.cpp b/Core/HLE/scePsmf.cpp index f14be11e57..3bf40498da 100644 --- a/Core/HLE/scePsmf.cpp +++ b/Core/HLE/scePsmf.cpp @@ -1081,9 +1081,12 @@ int _PsmfPlayerSetPsmfOffset(u32 psmfPlayer, const char *filename, int offset, b if (!filename) { return ERROR_PSMFPLAYER_INVALID_PARAM; } + + int delayUs = 1100; + psmfplayer->filehandle = pspFileSystem.OpenFile(filename, (FileAccess) FILEACCESS_READ); if (!psmfplayer->filehandle) { - return SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT; + return hleDelayResult(SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT, "psmfplayer set", delayUs); } if (psmfplayer->filehandle && psmfplayer->tempbuf) { @@ -1092,6 +1095,8 @@ int _PsmfPlayerSetPsmfOffset(u32 psmfPlayer, const char *filename, int offset, b u8 *buf = psmfplayer->tempbuf; int tempbufSize = (int)sizeof(psmfplayer->tempbuf); int size = (int)pspFileSystem.ReadFile(psmfplayer->filehandle, buf, 2048); + delayUs += 2000; + const u32 magic = *(u32_le *)buf; if (magic != PSMF_MAGIC) { // TODO: Let's keep trying as we were before. @@ -1103,7 +1108,7 @@ int _PsmfPlayerSetPsmfOffset(u32 psmfPlayer, const char *filename, int offset, b u16 numStreams = *(u16_be *)(buf + 0x80); if (numStreams > 128) { ERROR_LOG_REPORT(ME, "scePsmfPlayerSetPsmf*: too many streams in PSMF video, bogus data"); - return SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT; + return hleDelayResult(SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT, "psmfplayer set", delayUs); } psmfplayer->totalVideoStreams = 0; @@ -1140,7 +1145,7 @@ int _PsmfPlayerSetPsmfOffset(u32 psmfPlayer, const char *filename, int offset, b psmfplayer->status = PSMF_PLAYER_STATUS_STANDBY; - return 0; + return hleDelayResult(0, "psmfplayer set", delayUs); } int scePsmfPlayerSetPsmf(u32 psmfPlayer, const char *filename) From ceebdca2fb1175d4d6d24250267d410ba1d435df Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 18 May 2014 20:48:02 -0700 Subject: [PATCH 6/9] Check scePsmfPlayerStart() params like the PSP. It doesn't care if there's actually audio data here. --- Core/HLE/scePsmf.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/HLE/scePsmf.cpp b/Core/HLE/scePsmf.cpp index 3bf40498da..c18a78c0f2 100644 --- a/Core/HLE/scePsmf.cpp +++ b/Core/HLE/scePsmf.cpp @@ -1287,7 +1287,7 @@ int scePsmfPlayerStart(u32 psmfPlayer, u32 psmfPlayerData, int initPts) psmfplayer->mediaengine->setVideoStream(playerData->videoStreamNum); psmfplayer->videoCodec = playerData->videoCodec; psmfplayer->videoStreamNum = playerData->videoStreamNum; - if (!psmfplayer->mediaengine->IsNoAudioData()) { + if (psmfplayer->totalAudioStreams > 0) { psmfplayer->mediaengine->setAudioStream(playerData->audioStreamNum); psmfplayer->audioCodec = playerData->audioCodec; psmfplayer->audioStreamNum = playerData->audioStreamNum; From 0c77d3c2ea2e7e24b671bf206c026cbbe2e222a8 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 18 May 2014 20:59:18 -0700 Subject: [PATCH 7/9] Delay scePsmfPlayerStart() when seeking. It seems to only delay when it was already playing. --- Core/HLE/scePsmf.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Core/HLE/scePsmf.cpp b/Core/HLE/scePsmf.cpp index c18a78c0f2..2b13f3b72e 100644 --- a/Core/HLE/scePsmf.cpp +++ b/Core/HLE/scePsmf.cpp @@ -1297,6 +1297,7 @@ int scePsmfPlayerStart(u32 psmfPlayer, u32 psmfPlayerData, int initPts) // Does not alter current pts, it just catches up when Update()/etc. get there. + int delayUs = psmfplayer->status == PSMF_PLAYER_STATUS_PLAYING ? 3000 : 0; psmfplayer->status = PSMF_PLAYER_STATUS_PLAYING; psmfplayer->warmUp = 0; @@ -1333,7 +1334,7 @@ int scePsmfPlayerStart(u32 psmfPlayer, u32 psmfPlayerData, int initPts) psmfplayer->seekDestTimeStamp = initPts; __PsmfPlayerContinueSeek(psmfplayer); - return 0; + return delayUs == 0 ? 0 : hleDelayResult(0, "psmfplayer start", delayUs); } int scePsmfPlayerDelete(u32 psmfPlayer) From aafc8f1ceca74548efee557120f9ebbe20c22f8e Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 18 May 2014 21:41:15 -0700 Subject: [PATCH 8/9] Validate and report initial psmfplayer playMode. We only support play and pause, but they're the only ones I've seen. --- Core/HLE/scePsmf.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/Core/HLE/scePsmf.cpp b/Core/HLE/scePsmf.cpp index 2b13f3b72e..ff6f2aef46 100644 --- a/Core/HLE/scePsmf.cpp +++ b/Core/HLE/scePsmf.cpp @@ -1282,6 +1282,25 @@ int scePsmfPlayerStart(u32 psmfPlayer, u32 psmfPlayerData, int initPts) return ERROR_PSMFPLAYER_INVALID_CONFIG; } + switch ((PsmfPlayerMode)(s32)playerData->playMode) { + case PSMF_PLAYER_MODE_FORWARD: + case PSMF_PLAYER_MODE_REWIND: + if (psmfplayer->playerVersion == PSMF_PLAYER_VERSION_BASIC) { + WARN_LOG_REPORT(ME, "scePsmfPlayerStart(%08x, %08x, %d): no EP data for FORWARD/REWIND", psmfPlayer, psmfPlayerData, initPts); + return ERROR_PSMFPLAYER_INVALID_PARAM; + } + WARN_LOG_REPORT(ME, "scePsmfPlayerStart(%08x, %08x, %d): unsupported playMode", psmfPlayer, psmfPlayerData, initPts); + break; + + case PSMF_PLAYER_MODE_PLAY: + case PSMF_PLAYER_MODE_PAUSE: + break; + + default: + WARN_LOG_REPORT(ME, "scePsmfPlayerStart(%08x, %08x, %d): unsupported playMode", psmfPlayer, psmfPlayerData, initPts); + break; + } + WARN_LOG(ME, "scePsmfPlayerStart(%08x, %08x, %d)", psmfPlayer, psmfPlayerData, initPts); psmfplayer->mediaengine->setVideoStream(playerData->videoStreamNum); From 346f725334460cd3b2062a151b69796c206b5fe3 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 18 May 2014 21:58:43 -0700 Subject: [PATCH 9/9] Don't allow seeking without an EPmap. --- Core/HLE/scePsmf.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Core/HLE/scePsmf.cpp b/Core/HLE/scePsmf.cpp index ff6f2aef46..9715e33716 100644 --- a/Core/HLE/scePsmf.cpp +++ b/Core/HLE/scePsmf.cpp @@ -1301,6 +1301,11 @@ int scePsmfPlayerStart(u32 psmfPlayer, u32 psmfPlayerData, int initPts) break; } + if (psmfplayer->playerVersion == PSMF_PLAYER_VERSION_BASIC && initPts != 0) { + ERROR_LOG_REPORT(ME, "scePsmfPlayerStart(%08x, %08x, %d): unable to seek without EPmap", psmfPlayer, psmfPlayerData, initPts); + return ERROR_PSMFPLAYER_INVALID_PARAM; + } + WARN_LOG(ME, "scePsmfPlayerStart(%08x, %08x, %d)", psmfPlayer, psmfPlayerData, initPts); psmfplayer->mediaengine->setVideoStream(playerData->videoStreamNum);