mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-01 14:58:14 +00:00
sceMpegBasePESpacketCopy used to gather each DMA into a buffer filed under the address of its first block, and sceVideocodecDecode looked one up by the address it was handed. That works only while an access unit arrives in a single call. It doesn't: mpeg.prx routinely DMAs one in several pieces at consecutive addresses, and the table then kept whichever piece happened to start where the decode later asked, and dropped the rest. So the DMA now writes each block at the address it names. The Media Engine's own memory moves to its real addresses - low ones, which mpeg.prx bounds-checks against 0x3FFFFF - and pieces written at consecutive addresses end up consecutive, which is all this ever needed. Our own allocations move to the top half, away from the addresses mpeg.prx picks for itself. That memory is the ME's, not the Allegrex's, and the two are separate address spaces: on hardware only the ME reaches it, so here it is a buffer of our own that nothing emulated can address. It gets its own MEIsValidRange and MEGetPointerRange rather than borrowing Memory::, which answers for the Allegrex's memory and has nothing to say about this one. An address only means something together with the space it came from, and mpeg.prx hands over bare integers. The three places that have to work it out from the value now ask the ME first, where they used to ask Memory:: first and so read every address as the CPU's. It separates the addresses these callers actually pass (ME memory well down in the first megabyte, PSP RAM at 0x08000000 and up), but that's those callers rather than a rule. Savestates from before this carry the old packet table; it's read and dropped, since the Media Engine's memory is saved and that's where the payloads live now. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
71 lines
3.1 KiB
C++
71 lines
3.1 KiB
C++
// Copyright (c) 2026- PPSSPP Project.
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, version 2.0 or later versions.
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License 2.0 for more details.
|
|
|
|
// A copy of the GPL 2.0 should have been included with the program.
|
|
// If not, see http://www.gnu.org/licenses/
|
|
|
|
// Official git repository and contact information can be found at
|
|
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
|
|
|
#pragma once
|
|
|
|
#include <vector>
|
|
|
|
#include "Common/CommonTypes.h"
|
|
|
|
class PointerWrap;
|
|
|
|
void Register_sceMpegbase();
|
|
|
|
// Called per boot, from __KernelInit and __KernelShutdown, around sceMpeg's own pair.
|
|
void __MpegBaseInit();
|
|
void __MpegBaseShutdown();
|
|
|
|
void __MpegBaseDoState(PointerWrap &p);
|
|
|
|
|
|
// Un-tiles a decoded frame from the eight buffers the Media Engine lays it out in into three
|
|
// planes. The buffers are in sceVideocodec's order: four luma, then four chroma. cb and cr come
|
|
// out at half width and half height, as YUV420 does.
|
|
//
|
|
// The planes point into scratch that is reused by the next call, so read them before calling again.
|
|
bool ReadTiledYCbCr(const u32 *buffers, int width, int height,
|
|
const u8 **luma, const u8 **cb, const u8 **cr);
|
|
|
|
// The de-tiling on its own, taking the eight buffers already resolved to host pointers, so it can
|
|
// be measured and checked without a game - see TestMpegCsc. A null entry in src leaves that
|
|
// buffer's share of the output alone.
|
|
void UntileYCbCr(u8 *luma, u8 *cb, u8 *cr, const u8 *const src[8], const int sizes[8],
|
|
int width, int height);
|
|
|
|
// Converts a rectangle of a planar YCbCr420 frame to RGB, the way the DMACPLUS does on the way to
|
|
// the screen. Pure, so it can be measured and checked on its own - see TestMpegCsc.
|
|
//
|
|
// luma is width by height; cb and cr are half that in both directions. dest is destStride pixels
|
|
// wide in the format pixelMode names (a GEBufferFormat), and the range lands at its origin.
|
|
void MpegCscRange(u8 *dest, int destStride, int pixelMode,
|
|
const u8 *luma, const u8 *cb, const u8 *cr, int width,
|
|
int rangeX, int rangeY, int rangeWidth, int rangeHeight);
|
|
|
|
// The two implementations behind it, exposed so TestMpegCsc can measure and compare them.
|
|
// The scalar one handles anything; the swscale one refuses what it cannot express and is then
|
|
// not used. They do not agree to the bit - swscale rounds its own way - so the scalar one is
|
|
// what the reference in the test is checked against.
|
|
void MpegCscRangeScalar(u8 *dest, int destStride, int pixelMode,
|
|
const u8 *luma, const u8 *cb, const u8 *cr, int width,
|
|
int rangeX, int rangeY, int rangeWidth, int rangeHeight);
|
|
bool MpegCscRangeSws(u8 *dest, int destStride, int pixelMode,
|
|
const u8 *luma, const u8 *cb, const u8 *cr, int width,
|
|
int rangeX, int rangeY, int rangeWidth, int rangeHeight);
|
|
|
|
// Frees the cached swscale context.
|
|
void MpegCscShutdown();
|