mirror of
https://github.com/libretro/ppsspp.git
synced 2024-11-25 09:09:49 +00:00
Merge pull request #348 from unknownbrackets/mpeg-fix
Fix games broken by the mpeg merge
This commit is contained in:
commit
8e91de7501
@ -193,8 +193,6 @@ endif()
|
||||
|
||||
add_library(Common STATIC
|
||||
${CommonExtra}
|
||||
Common/Action.cpp
|
||||
Common/Action.h
|
||||
Common/ColorUtil.cpp
|
||||
Common/ColorUtil.h
|
||||
Common/ConsoleListener.cpp
|
||||
|
@ -1 +0,0 @@
|
||||
#include "Action.h"
|
@ -1,23 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "ChunkFile.h"
|
||||
|
||||
// Sometimes you want to set something to happen later, without that later place really needing
|
||||
// to know about all the things that might happen. That's when you use an Action, and add it
|
||||
// to the appropriate ActionSet.
|
||||
//
|
||||
// Unlike CoreTiming events, these are not timed in any way and do not care about the time.
|
||||
// This code also doesn't depend on anything in PPSSPP so it can live in Common.
|
||||
|
||||
|
||||
|
||||
// Pretty much a Runnable. Similar to Action from JPCSP.
|
||||
class Action
|
||||
{
|
||||
public:
|
||||
virtual ~Action() {}
|
||||
virtual void run() = 0;
|
||||
virtual void DoState(PointerWrap &p) = 0;
|
||||
int actionTypeID;
|
||||
};
|
@ -1,5 +1,4 @@
|
||||
set(SRCS
|
||||
Action.cpp
|
||||
ColorUtil.cpp
|
||||
ConsoleListener.cpp
|
||||
ExtendedTrace.cpp
|
||||
|
@ -140,7 +140,6 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="ABI.h" />
|
||||
<ClInclude Include="Action.h" />
|
||||
<ClInclude Include="ArmABI.h">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
@ -196,7 +195,6 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="ABI.cpp" />
|
||||
<ClCompile Include="Action.cpp" />
|
||||
<ClCompile Include="ArmABI.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
|
@ -43,7 +43,6 @@
|
||||
<ClInclude Include="x64Emitter.h" />
|
||||
<ClInclude Include="ArmEmitter.h" />
|
||||
<ClInclude Include="ArmABI.h" />
|
||||
<ClInclude Include="Action.h" />
|
||||
<ClInclude Include="FixedSizeUnorderedSet.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@ -72,7 +71,6 @@
|
||||
<ClCompile Include="x64Emitter.cpp" />
|
||||
<ClCompile Include="ArmEmitter.cpp" />
|
||||
<ClCompile Include="ArmABI.cpp" />
|
||||
<ClCompile Include="Action.cpp" />
|
||||
<ClCompile Include="ThunkArm.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
@ -22,7 +22,6 @@
|
||||
#include "HLE.h"
|
||||
#include "../MIPS/MIPS.h"
|
||||
|
||||
#include "Action.h"
|
||||
#include "sceKernel.h"
|
||||
#include "sceKernelThread.h"
|
||||
#include "sceKernelInterrupt.h"
|
||||
|
@ -19,7 +19,6 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include "HLE.h"
|
||||
#include "Common/Action.h"
|
||||
#include "Common/FileUtil.h"
|
||||
#include "../Host.h"
|
||||
#include "../MIPS/MIPS.h"
|
||||
@ -161,7 +160,7 @@ public:
|
||||
AfterModuleEntryCall() {}
|
||||
SceUID moduleID_;
|
||||
u32 retValAddr;
|
||||
virtual void run();
|
||||
virtual void run(MipsCall &call);
|
||||
virtual void DoState(PointerWrap &p) {
|
||||
p.Do(moduleID_);
|
||||
p.Do(retValAddr);
|
||||
@ -172,7 +171,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
void AfterModuleEntryCall::run() {
|
||||
void AfterModuleEntryCall::run(MipsCall &call) {
|
||||
Memory::Write_U32(retValAddr, currentMIPS->r[2]);
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,6 @@
|
||||
#include "../MIPS/MIPS.h"
|
||||
#include "../../Core/CoreTiming.h"
|
||||
#include "../../Core/MemMap.h"
|
||||
#include "../../Common/Action.h"
|
||||
|
||||
#include "sceAudio.h"
|
||||
#include "sceKernel.h"
|
||||
@ -251,7 +250,7 @@ private:
|
||||
class ActionAfterMipsCall : public Action
|
||||
{
|
||||
public:
|
||||
virtual void run();
|
||||
virtual void run(MipsCall &call);
|
||||
|
||||
static Action *Create()
|
||||
{
|
||||
@ -298,7 +297,7 @@ class ActionAfterCallback : public Action
|
||||
{
|
||||
public:
|
||||
ActionAfterCallback() {}
|
||||
virtual void run();
|
||||
virtual void run(MipsCall &call);
|
||||
|
||||
static Action *Create()
|
||||
{
|
||||
@ -545,6 +544,11 @@ void MipsCall::DoState(PointerWrap &p)
|
||||
}
|
||||
}
|
||||
|
||||
void MipsCall::setReturnValue(u32 value)
|
||||
{
|
||||
savedV0 = value;
|
||||
}
|
||||
|
||||
// TODO: Should move to this wrapper so we can keep the current thread as a SceUID instead
|
||||
// of a dangerous raw pointer.
|
||||
Thread *__GetCurrentThread() {
|
||||
@ -1968,7 +1972,7 @@ void sceKernelReferCallbackStatus()
|
||||
}
|
||||
}
|
||||
|
||||
void ActionAfterMipsCall::run() {
|
||||
void ActionAfterMipsCall::run(MipsCall &call) {
|
||||
u32 error;
|
||||
Thread *thread = kernelObjects.Get<Thread>(threadID, error);
|
||||
if (thread) {
|
||||
@ -1980,7 +1984,7 @@ void ActionAfterMipsCall::run() {
|
||||
}
|
||||
|
||||
if (chainedAction) {
|
||||
chainedAction->run();
|
||||
chainedAction->run(call);
|
||||
delete chainedAction;
|
||||
}
|
||||
}
|
||||
@ -2013,7 +2017,7 @@ void Thread::setReturnValue(u32 retval)
|
||||
int callId = this->currentCallbackId;
|
||||
MipsCall *call = mipsCalls.get(callId);
|
||||
if (call) {
|
||||
call->savedV0 = retval;
|
||||
call->setReturnValue(retval);
|
||||
} else {
|
||||
ERROR_LOG(HLE, "Failed to inject return value %08x in thread", retval);
|
||||
}
|
||||
@ -2271,7 +2275,7 @@ void __KernelReturnFromMipsCall()
|
||||
// Should also save/restore wait state here.
|
||||
if (call->doAfter)
|
||||
{
|
||||
call->doAfter->run();
|
||||
call->doAfter->run(*call);
|
||||
delete call->doAfter;
|
||||
}
|
||||
|
||||
@ -2350,7 +2354,7 @@ void __KernelRunCallbackOnThread(SceUID cbId, Thread *thread, bool reschedAfter)
|
||||
__KernelCallAddress(thread, cb->nc.entrypoint, action, false, args, reschedAfter);
|
||||
}
|
||||
|
||||
void ActionAfterCallback::run() {
|
||||
void ActionAfterCallback::run(MipsCall &call) {
|
||||
if (cbId != -1) {
|
||||
u32 error;
|
||||
Callback *cb = kernelObjects.Get<Callback>(cbId, error);
|
||||
|
@ -221,6 +221,16 @@ struct MipsCall {
|
||||
bool reschedAfter;
|
||||
|
||||
void DoState(PointerWrap &p);
|
||||
void setReturnValue(u32 value);
|
||||
};
|
||||
|
||||
class Action
|
||||
{
|
||||
public:
|
||||
virtual ~Action() {}
|
||||
virtual void run(MipsCall &call) = 0;
|
||||
virtual void DoState(PointerWrap &p) = 0;
|
||||
int actionTypeID;
|
||||
};
|
||||
|
||||
enum ThreadStatus
|
||||
|
@ -23,7 +23,6 @@
|
||||
#include "sceKernelThread.h"
|
||||
#include "HLE.h"
|
||||
#include "../HW/MediaEngine.h"
|
||||
#include "../../Common/Action.h"
|
||||
|
||||
static bool useMediaEngine;
|
||||
|
||||
@ -68,6 +67,8 @@ static const int MPEG_HEADER_BUFFER_MINIMUM_SIZE = 2048;
|
||||
|
||||
static const int NUM_ES_BUFFERS = 2;
|
||||
|
||||
static const int PSP_ERROR_MPEG_NO_DATA = 0x80618001;
|
||||
|
||||
int getMaxAheadTimestamp(const SceMpegRingBuffer &ringbuf) {
|
||||
return std::max(40000, ringbuf.packets * 700); // empiric value from JPCSP, thanks!
|
||||
}
|
||||
@ -262,7 +263,7 @@ public:
|
||||
void setRingAddr(u32 ringAddr) { ringAddr_ = ringAddr; }
|
||||
static Action *Create() { return new PostPutAction; }
|
||||
void DoState(PointerWrap &p) { p.Do(ringAddr_); p.DoMarker("PostPutAction"); }
|
||||
void run();
|
||||
void run(MipsCall &call);
|
||||
private:
|
||||
u32 ringAddr_;
|
||||
};
|
||||
@ -582,7 +583,7 @@ u32 sceMpegAvcDecode(u32 mpeg, u32 auAddr, u32 frameWidth, u32 bufferAddr, u32 i
|
||||
}
|
||||
|
||||
SceMpegAu avcAu;
|
||||
Memory::ReadStruct(auAddr, &avcAu);
|
||||
avcAu.read(auAddr);
|
||||
|
||||
SceMpegRingBuffer ringbuffer;
|
||||
Memory::ReadStruct(ctx->mpegRingbufferAddr, &ringbuffer);
|
||||
@ -651,7 +652,7 @@ u32 sceMpegAvcDecode(u32 mpeg, u32 auAddr, u32 frameWidth, u32 bufferAddr, u32 i
|
||||
ctx->avc.avcDecodeResult = MPEG_AVC_DECODE_SUCCESS;
|
||||
|
||||
// Flush structs back to memory
|
||||
Memory::WriteStruct(auAddr, &avcAu);
|
||||
avcAu.write(auAddr);
|
||||
Memory::WriteStruct(ctx->mpegRingbufferAddr, &ringbuffer);
|
||||
|
||||
Memory::Write_U32(ctx->avc.avcFrameStatus, initAddr); // 1 = showing, 0 = not showing
|
||||
@ -732,7 +733,7 @@ int sceMpegInitAu(u32 mpeg, u32 bufferAddr, u32 auPointer)
|
||||
DEBUG_LOG(HLE, "sceMpegInitAu(%08x, %i, %08x)", mpeg, bufferAddr, auPointer);
|
||||
|
||||
SceMpegAu sceAu;
|
||||
Memory::ReadStruct(auPointer, &sceAu);
|
||||
sceAu.read(auPointer);
|
||||
|
||||
if (bufferAddr >= 1 && bufferAddr <= NUM_ES_BUFFERS && ctx->esBuffers[bufferAddr - 1]) {
|
||||
// This esbuffer has been allocated for Avc.
|
||||
@ -741,7 +742,7 @@ int sceMpegInitAu(u32 mpeg, u32 bufferAddr, u32 auPointer)
|
||||
sceAu.dts = 0;
|
||||
sceAu.pts = 0;
|
||||
|
||||
Memory::WriteStruct(auPointer, &sceAu);
|
||||
sceAu.write(auPointer);
|
||||
} else {
|
||||
// This esbuffer has been left as Atrac.
|
||||
sceAu.esBuffer = bufferAddr;
|
||||
@ -749,7 +750,7 @@ int sceMpegInitAu(u32 mpeg, u32 bufferAddr, u32 auPointer)
|
||||
sceAu.pts = 0;
|
||||
sceAu.dts = UNKNOWN_TIMESTAMP;
|
||||
|
||||
Memory::WriteStruct(auPointer, &sceAu);
|
||||
sceAu.write(auPointer);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -783,7 +784,7 @@ int sceMpegRingbufferAvailableSize(u32 ringbufferAddr)
|
||||
|
||||
|
||||
|
||||
void PostPutAction::run() {
|
||||
void PostPutAction::run(MipsCall &call) {
|
||||
SceMpegRingBuffer ringbuffer;
|
||||
Memory::ReadStruct(ringAddr_, &ringbuffer);
|
||||
|
||||
@ -803,6 +804,7 @@ void PostPutAction::run() {
|
||||
}
|
||||
|
||||
Memory::WriteStruct(ringAddr_, &ringbuffer);
|
||||
call.setReturnValue(packetsAdded);
|
||||
}
|
||||
|
||||
|
||||
@ -859,11 +861,11 @@ int sceMpegGetAvcAu(u32 mpeg, u32 streamId, u32 auAddr, u32 attrAddr)
|
||||
Memory::ReadStruct(ctx->mpegRingbufferAddr, &mpegRingbuffer);
|
||||
|
||||
SceMpegAu sceAu;
|
||||
Memory::ReadStruct(auAddr, &sceAu);
|
||||
sceAu.read(auAddr);
|
||||
|
||||
if (mpegRingbuffer.packetsRead == 0) {
|
||||
// delayThread(mpegErrorDecodeDelay)
|
||||
return -1; // ERROR_MPEG_NO_DATA
|
||||
return PSP_ERROR_MPEG_NO_DATA;
|
||||
}
|
||||
|
||||
if (ctx->streamMap.find(streamId) == ctx->streamMap.end())
|
||||
@ -876,23 +878,29 @@ int sceMpegGetAvcAu(u32 mpeg, u32 streamId, u32 auAddr, u32 attrAddr)
|
||||
if (ctx->atracRegistered && (sceAu.pts > sceAu.pts + getMaxAheadTimestamp(mpegRingbuffer)))
|
||||
{
|
||||
ERROR_LOG(HLE, "sceMpegGetAvcAu - video too much ahead");
|
||||
return -1; // MPEG_NO_DATA
|
||||
return PSP_ERROR_MPEG_NO_DATA;
|
||||
}
|
||||
|
||||
int result = 0;
|
||||
|
||||
// read the au struct from ram
|
||||
if (!ctx->mediaengine->readVideoAu(&sceAu)) {
|
||||
// TODO: For now, always checking, since readVideoAu() is stubbed.
|
||||
if (!ctx->mediaengine->readVideoAu(&sceAu) || true) {
|
||||
// Only return this after the video already ended.
|
||||
if (ctx->endOfVideoReached) {
|
||||
result = PSP_ERROR_MPEG_NO_DATA;
|
||||
}
|
||||
if (ctx->mpegLastTimestamp < 0 || sceAu.pts >= ctx->mpegLastTimestamp) {
|
||||
DEBUG_LOG(HLE, "End of video reached");
|
||||
NOTICE_LOG(HLE, "End of video reached");
|
||||
ctx->endOfVideoReached = true;
|
||||
} else {
|
||||
ctx->endOfAudioReached = false;
|
||||
}
|
||||
|
||||
// The avcau struct may have been modified by mediaengine, write it back.
|
||||
Memory::WriteStruct(auAddr, &sceAu);
|
||||
}
|
||||
|
||||
// The avcau struct may have been modified by mediaengine, write it back.
|
||||
sceAu.write(auAddr);
|
||||
|
||||
if (Memory::IsValidAddress(attrAddr)) {
|
||||
Memory::Write_U32(1, attrAddr);
|
||||
}
|
||||
@ -926,16 +934,29 @@ int sceMpegGetAtracAu(u32 mpeg, u32 streamId, u32 auAddr, u32 attrAddr)
|
||||
Memory::ReadStruct(ctx->mpegRingbufferAddr, &mpegRingbuffer);
|
||||
|
||||
SceMpegAu sceAu;
|
||||
Memory::ReadStruct(auAddr, &sceAu);
|
||||
sceAu.read(auAddr);
|
||||
|
||||
int result = 0;
|
||||
|
||||
//...
|
||||
// TODO: Just faking it.
|
||||
sceAu.pts += videoTimestampStep;
|
||||
sceAu.write(auAddr);
|
||||
|
||||
// TODO: And also audio end?
|
||||
if (ctx->endOfVideoReached) {
|
||||
if (mpegRingbuffer.packetsFree < mpegRingbuffer.packets) {
|
||||
mpegRingbuffer.packetsFree = mpegRingbuffer.packets;
|
||||
Memory::WriteStruct(ctx->mpegRingbufferAddr, &mpegRingbuffer);
|
||||
}
|
||||
result = PSP_ERROR_MPEG_NO_DATA;
|
||||
}
|
||||
|
||||
if (Memory::IsValidAddress(attrAddr)) {
|
||||
Memory::Write_U32(0, attrAddr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
int sceMpegQueryPcmEsSize(u32 mpeg, u32 esSizeAddr, u32 outSizeAddr)
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include "../../Globals.h"
|
||||
#include "../../Common/ChunkFile.h"
|
||||
#include "../MIPS/MIPS.h"
|
||||
|
||||
enum {
|
||||
ERROR_MPEG_BAD_VERSION = 0x80610002,
|
||||
@ -57,6 +58,18 @@ struct SceMpegAu {
|
||||
s64 dts; // decode time stamp
|
||||
u32 esBuffer;
|
||||
u32 esSize;
|
||||
|
||||
void read(u32 addr) {
|
||||
Memory::ReadStruct(addr, this);
|
||||
pts = (pts & 0xFFFFFFFFULL) << 32 | (pts >> 32);
|
||||
dts = (dts & 0xFFFFFFFFULL) << 32 | (dts >> 32);
|
||||
}
|
||||
|
||||
void write(u32 addr) {
|
||||
pts = (pts & 0xFFFFFFFFULL) << 32 | (pts >> 32);
|
||||
dts = (dts & 0xFFFFFFFFULL) << 32 | (dts >> 32);
|
||||
Memory::WriteStruct(addr, this);
|
||||
}
|
||||
};
|
||||
|
||||
const int videoTimestampStep = 3003;
|
||||
|
@ -32,8 +32,7 @@ win32 {
|
||||
HEADERS += ../Common/stdafx.h
|
||||
}
|
||||
|
||||
SOURCES += ../Common/Action.cpp \
|
||||
../Common/ColorUtil.cpp \
|
||||
SOURCES += ../Common/ColorUtil.cpp \
|
||||
../Common/ConsoleListener.cpp \
|
||||
../Common/Crypto/aes_cbc.cpp \
|
||||
../Common/Crypto/aes_core.cpp \
|
||||
@ -57,8 +56,7 @@ SOURCES += ../Common/Action.cpp \
|
||||
../Common/Thread.cpp \
|
||||
../Common/Timer.cpp \
|
||||
../Common/Version.cpp
|
||||
HEADERS += ../Common/Action.h \
|
||||
../Common/ColorUtil.h \
|
||||
HEADERS += ../Common/ColorUtil.h \
|
||||
../Common/ConsoleListener.h \
|
||||
../Common/Crypto/md5.h \
|
||||
../Common/Crypto/sha1.h \
|
||||
|
@ -79,6 +79,7 @@ DWORD TheThread(LPVOID x)
|
||||
coreParameter.pixelWidth = 480 * g_Config.iWindowZoom;
|
||||
coreParameter.pixelHeight = 272 * g_Config.iWindowZoom;
|
||||
coreParameter.startPaused = !g_Config.bAutoRun;
|
||||
coreParameter.useMediaEngine = false;
|
||||
|
||||
std::string error_string;
|
||||
if (!PSP_Init(coreParameter, &error_string))
|
||||
|
@ -67,6 +67,7 @@ EmuScreen::EmuScreen(const std::string &filename) : invalid_(true)
|
||||
coreParam.outputHeight = dp_yres;
|
||||
coreParam.pixelWidth = pixel_xres;
|
||||
coreParam.pixelHeight = pixel_yres;
|
||||
coreParam.useMediaEngine = false;
|
||||
std::string error_string;
|
||||
if (PSP_Init(coreParam, &error_string)) {
|
||||
invalid_ = false;
|
||||
|
@ -151,6 +151,7 @@ int main(int argc, const char* argv[])
|
||||
coreParameter.enableSound = false;
|
||||
coreParameter.headLess = true;
|
||||
coreParameter.printfEmuLog = true;
|
||||
coreParameter.useMediaEngine = false;
|
||||
|
||||
g_Config.bEnableSound = false;
|
||||
g_Config.bFirstRun = false;
|
||||
|
Loading…
Reference in New Issue
Block a user