Merge pull request #348 from unknownbrackets/mpeg-fix

Fix games broken by the mpeg merge
This commit is contained in:
Henrik Rydgård 2013-01-06 22:32:38 -08:00
commit 8e91de7501
16 changed files with 81 additions and 65 deletions

View File

@ -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

View File

@ -1 +0,0 @@
#include "Action.h"

View File

@ -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;
};

View File

@ -1,5 +1,4 @@
set(SRCS
Action.cpp
ColorUtil.cpp
ConsoleListener.cpp
ExtendedTrace.cpp

View File

@ -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>

View File

@ -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>

View File

@ -22,7 +22,6 @@
#include "HLE.h"
#include "../MIPS/MIPS.h"
#include "Action.h"
#include "sceKernel.h"
#include "sceKernelThread.h"
#include "sceKernelInterrupt.h"

View File

@ -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]);
}

View File

@ -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);

View File

@ -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

View File

@ -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)

View File

@ -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;

View File

@ -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 \

View File

@ -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))

View File

@ -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;

View File

@ -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;