mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-15 10:40:01 +01:00
Run the real mpeg.prx in place of our sceMpeg HLE
Add flash0:/kd/mpeg.prx to the sceUtility module swap, hung off av_mpegbase, so it loads when DisableHLEFlags::sceMpeg is set. Games that ship their own sceMpeg_library on the disc never get here and just use theirs. The piece that was missing to make it work: the access unit address mpeg.prx passes to sceVideocodecDecode is in Media Engine space, which we can't read. On hardware sceMpegBasePESpacketCopy DMA'd the payload there first. That copy is ours, so it now gathers the blocks and sceVideocodec decodes from those, falling back to main memory for any caller that points at it directly. The gather is keyed by destination, because that call carries the audio payload too - video to an ME address, audio to main memory - and handing an ATRAC packet to the H.264 decoder gets you nothing. With that, video/mpeg/basic gets a 144x80 frame out of real Sony code driving our sceVideocodec through ffmpeg. The test still fails overall, as it did before this branch - it is in tests_next. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
ba975d2908
commit
00770764a7
5 files changed
+94
-8
No files matched your search
@@ -20,6 +20,7 @@
|
||||
// mpeg.prx drives these directly, so they have to be real for the firmware module to run in place
|
||||
// of our sceMpeg HLE.
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "Common/Swap.h"
|
||||
@@ -31,12 +32,18 @@
|
||||
#include "Core/MemMapHelpers.h"
|
||||
#include "GPU/ge_constants.h"
|
||||
|
||||
// The PES payloads gathered by sceMpegBasePESpacketCopy, keyed by the destination each was
|
||||
// copied to. It carries audio as well as video - the destination is what tells them apart - so
|
||||
// sceVideocodec has to ask for the one matching the address it was handed.
|
||||
static std::map<u32, std::vector<u8>> g_pesPackets;
|
||||
|
||||
// Set by sceMpegBaseCscInit / sceMpegBaseCscSetPixelMode, and used when the caller passes 0.
|
||||
static int g_mpegBaseBufferWidth = 512;
|
||||
static int g_mpegBasePixelMode = GE_CMODE_32BIT_ABGR8888;
|
||||
|
||||
void __MpegBaseInit() {
|
||||
// None of this survives a boot on hardware.
|
||||
g_pesPackets.clear();
|
||||
g_mpegBaseBufferWidth = 512;
|
||||
g_mpegBasePixelMode = GE_CMODE_32BIT_ABGR8888;
|
||||
}
|
||||
@@ -56,10 +63,41 @@ static u32 sceMpegBasePESpacketCopy(u32 p)
|
||||
}
|
||||
MpegSetPmpVideoSource(p, nBlocks);
|
||||
|
||||
DEBUG_LOG(Log::Mpeg, "sceMpegBasePESpacketCopy(%08x), received %d block(s)", p, nBlocks);
|
||||
// On hardware this is the DMA that moves the PES payload into the Media Engine's own memory,
|
||||
// after which mpeg.prx hands sceVideocodecDecode an ME-side address we have no way to read.
|
||||
// Since the copy is ours, gather the blocks here instead and let sceVideocodec decode from
|
||||
// this - see MpegBaseGetPESPacket.
|
||||
lli = PSPPointer<SceMpegLLI>::Create(p);
|
||||
u32 dest = 0;
|
||||
std::vector<u8> gathered;
|
||||
for (int i = 0; i < nBlocks && lli.IsValid(); i++) {
|
||||
if (i == 0) {
|
||||
dest = lli->pDst;
|
||||
}
|
||||
// The list is game-supplied, so check the span before taking a pointer to it: the range
|
||||
// accessors raise a memory exception rather than returning null, and a malformed block
|
||||
// shouldn't fault the game when the intent here is to skip it.
|
||||
const u8 *src = (lli->iSize > 0 && Memory::IsValidRange(lli->pSrc, lli->iSize))
|
||||
? Memory::GetTypedPointerRange<u8>(lli->pSrc, lli->iSize) : nullptr;
|
||||
if (src) {
|
||||
gathered.insert(gathered.end(), src, src + lli->iSize);
|
||||
}
|
||||
++lli;
|
||||
}
|
||||
if (dest != 0) {
|
||||
g_pesPackets[dest] = std::move(gathered);
|
||||
}
|
||||
|
||||
DEBUG_LOG(Log::Mpeg, "sceMpegBasePESpacketCopy(%08x), %d block(s) -> %08x, %d bytes",
|
||||
p, nBlocks, dest, dest ? (int)g_pesPackets[dest].size() : 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const std::vector<u8> *MpegBaseGetPESPacket(u32 dest) {
|
||||
auto it = g_pesPackets.find(dest);
|
||||
return it == g_pesPackets.end() ? nullptr : &it->second;
|
||||
}
|
||||
|
||||
|
||||
// --- sceMpegbase colour conversion ---------------------------------------------------------
|
||||
//
|
||||
|
||||
Reference in new issue
Block a user