Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Correct some scePsmf info retrieval funcs and error handling #8793

Merged
merged 8 commits into from
May 31, 2016
208 changes: 125 additions & 83 deletions Core/HLE/scePsmf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,11 +161,12 @@ class Psmf {
void DoState(PointerWrap &p);

bool isValidCurrentStreamNumber() const {
return currentStreamNum >= 0 && currentStreamNum < (int)streamMap.size(); // urgh, checking size isn't really right here.
return currentStreamNum >= 0 && streamMap.find(currentStreamNum) != streamMap.end();
}

void setStreamNum(int num);
bool setStreamNum(int num);
bool setStreamWithType(int type, int channel);
bool setStreamWithTypeNumber(int type, int n);

int FindEPWithTimestamp(int pts) const;

Expand All @@ -186,6 +187,8 @@ class Psmf {

int numStreams;
int currentStreamNum;
int currentStreamType;
int currentStreamChannel;
int currentAudioStreamNum;
int currentVideoStreamNum;

Expand Down Expand Up @@ -312,6 +315,13 @@ class PsmfStream {
INFO_LOG(ME, "PSMF private audio found: id=%02x, privid=%02x, channels=%i, freq=%i", streamId, privateStreamId, psmf->audioChannels, psmf->audioFrequency);
}

bool matchesType(int ty) {
if (ty == PSMF_AUDIO_STREAM) {
return type == PSMF_ATRAC_STREAM || type == PSMF_PCM_STREAM;
}
return type == ty;
}

void DoState(PointerWrap &p) {
auto s = p.Section("PsmfStream", 1);
if (!s)
Expand Down Expand Up @@ -343,6 +353,8 @@ Psmf::Psmf(const u8 *ptr, u32 data) {
headerSize = 0x800;

currentStreamNum = -1;
currentStreamType = -1;
currentStreamChannel = -1;
currentAudioStreamNum = -1;
currentVideoStreamNum = -1;

Expand All @@ -351,17 +363,26 @@ Psmf::Psmf(const u8 *ptr, u32 data) {
const u8 *const currentStreamAddr = ptr + 0x82 + i * 16;
int streamId = currentStreamAddr[0];
if ((streamId & PSMF_VIDEO_STREAM_ID) == PSMF_VIDEO_STREAM_ID) {
stream = new PsmfStream(PSMF_AVC_STREAM, ++currentVideoStreamNum);
stream = new PsmfStream(PSMF_AVC_STREAM, streamId & 0x0F);
stream->readMPEGVideoStreamParams(currentStreamAddr, ptr, this);
} else if ((streamId & PSMF_AUDIO_STREAM_ID) == PSMF_AUDIO_STREAM_ID) {
stream = new PsmfStream(PSMF_ATRAC_STREAM, ++currentAudioStreamNum);
int type = PSMF_ATRAC_STREAM;
int privateStreamId = currentStreamAddr[1];
if ((privateStreamId & 0xF0) != 0) {
WARN_LOG_REPORT(ME, "Unknown private stream type, assuming PCM: %02x", privateStreamId);
type = PSMF_PCM_STREAM;
}
stream = new PsmfStream(type, privateStreamId & 0x0F);
stream->readPrivateAudioStreamParams(currentStreamAddr, this);
}
if (stream) {
currentStreamNum++;
streamMap[currentStreamNum] = stream;
}
}

// Default to the first stream.
currentStreamNum = 0;
}

Psmf::~Psmf() {
Expand Down Expand Up @@ -401,7 +422,7 @@ PsmfPlayer::PsmfPlayer(const PsmfPlayerCreateData *data) {
}

void Psmf::DoState(PointerWrap &p) {
auto s = p.Section("Psmf", 1, 2);
auto s = p.Section("Psmf", 1, 3);
if (!s)
return;

Expand Down Expand Up @@ -433,6 +454,18 @@ void Psmf::DoState(PointerWrap &p) {
}

p.Do(streamMap);
if (s >= 3) {
p.Do(currentStreamType);
p.Do(currentStreamChannel);
} else {
currentStreamType = -1;
currentStreamChannel = -1;
auto streamInfo = streamMap.find(currentStreamNum);
if (streamInfo != streamMap.end()) {
currentStreamType = streamInfo->second->type;
currentStreamChannel = streamInfo->second->channel;
}
}
}

void PsmfPlayer::DoState(PointerWrap &p) {
Expand Down Expand Up @@ -507,39 +540,55 @@ void PsmfPlayer::DoState(PointerWrap &p) {
}
}

void Psmf::setStreamNum(int num) {
bool Psmf::setStreamNum(int num) {
currentStreamNum = num;
currentStreamType = -1;
currentStreamChannel = -1;
if (!isValidCurrentStreamNumber())
return;
return false;
PsmfStreamMap::iterator iter = streamMap.find(currentStreamNum);
if (iter == streamMap.end())
return;
return false;

// TODO: This information is *probably* only for the scePsmf lookups?
// Not sure if we need to communicate with the media engine.
int type = iter->second->type;
int channel = iter->second->channel;
switch (type) {
case PSMF_AVC_STREAM:
if (currentVideoStreamNum != num) {
// TODO: Tell video mediaengine or something about channel.
currentVideoStreamNum = num;
}
currentVideoStreamNum = num;
break;

case PSMF_ATRAC_STREAM:
case PSMF_PCM_STREAM:
if (currentAudioStreamNum != num) {
// TODO: Tell audio mediaengine or something about channel.
currentAudioStreamNum = num;
}
currentAudioStreamNum = num;
break;
}

currentStreamType = type;
currentStreamChannel = iter->second->channel;
return true;
}

bool Psmf::setStreamWithType(int type, int channel) {
for (PsmfStreamMap::iterator iter = streamMap.begin(); iter != streamMap.end(); ++iter) {
if (iter->second->type == type && iter->second->channel == channel) {
setStreamNum(iter->first);
return true;
for (auto iter : streamMap) {
// Note: this does NOT support PSMF_AUDIO_STREAM.
if (iter.second->type == type && iter.second->channel == channel) {
return setStreamNum(iter.first);
}
}
return false;
}

bool Psmf::setStreamWithTypeNumber(int type, int n) {
for (auto iter : streamMap) {
if (iter.second->matchesType(type)) {
if (n != 0) {
// Keep counting...
n--;
continue;
}
// Okay, this is the one.
return setStreamNum(iter.first);
}
}
return false;
Expand Down Expand Up @@ -652,72 +701,67 @@ static u32 scePsmfSetPsmf(u32 psmfStruct, u32 psmfData)
return 0;
}

static u32 scePsmfGetNumberOfStreams(u32 psmfStruct)
{
static u32 scePsmfGetNumberOfStreams(u32 psmfStruct) {
Psmf *psmf = getPsmf(psmfStruct);
if (!psmf) {
ERROR_LOG(ME, "scePsmfGetNumberOfStreams(%08x): invalid psmf", psmfStruct);
return ERROR_PSMF_NOT_FOUND;
return hleLogError(ME, ERROR_PSMF_NOT_INITIALIZED, "invalid psmf");
}
DEBUG_LOG(ME, "scePsmfGetNumberOfStreams(%08x)", psmfStruct);
return psmf->numStreams;
return hleLogSuccessI(ME, psmf->numStreams);
}

static u32 scePsmfGetNumberOfSpecificStreams(u32 psmfStruct, int streamType)
{
static u32 scePsmfGetNumberOfSpecificStreams(u32 psmfStruct, int streamType) {
Psmf *psmf = getPsmf(psmfStruct);
if (!psmf) {
ERROR_LOG(ME, "scePsmfGetNumberOfSpecificStreams(%08x, %08x): invalid psmf", psmfStruct, streamType);
return ERROR_PSMF_NOT_FOUND;
return hleLogError(ME, ERROR_PSMF_NOT_INITIALIZED, "invalid psmf");
}
WARN_LOG(ME, "scePsmfGetNumberOfSpecificStreams(%08x, %08x)", psmfStruct, streamType);

int streamNum = 0;
int type = (streamType == PSMF_AUDIO_STREAM ? PSMF_ATRAC_STREAM : streamType);
for (int i = (int)psmf->streamMap.size() - 1; i >= 0; i--) {
if (psmf->streamMap[i]->type == type)
for (auto it : psmf->streamMap) {
bool match = false;
if (it.second->matchesType(streamType)) {
streamNum++;
}
}
return streamNum;

return hleLogSuccessI(ME, streamNum);
}

static u32 scePsmfSpecifyStreamWithStreamType(u32 psmfStruct, u32 streamType, u32 channel)
{
static u32 scePsmfSpecifyStreamWithStreamType(u32 psmfStruct, u32 streamType, u32 channel) {
Psmf *psmf = getPsmf(psmfStruct);
if (!psmf) {
ERROR_LOG(ME, "scePsmfSpecifyStreamWithStreamType(%08x, %08x, %i): invalid psmf", psmfStruct, streamType, channel);
return ERROR_PSMF_NOT_FOUND;
return hleLogError(ME, ERROR_PSMF_NOT_INITIALIZED, "invalid psmf");
}
INFO_LOG(ME, "scePsmfSpecifyStreamWithStreamType(%08x, %08x, %i)", psmfStruct, streamType, channel);
if (!psmf->setStreamWithType(streamType, channel)) {
psmf->setStreamNum(-1);
// An invalid type seems to make the stream number invalid, but retain the old type/channel.
psmf->currentStreamNum = ERROR_PSMF_INVALID_ID;
// Also, returns 0 even when no stream found.
return hleLogWarning(ME, 0, "no stream found");
}
return 0;
return hleLogSuccessI(ME, 0);
}

static u32 scePsmfSpecifyStreamWithStreamTypeNumber(u32 psmfStruct, u32 streamType, u32 typeNum)
{
static u32 scePsmfSpecifyStreamWithStreamTypeNumber(u32 psmfStruct, u32 streamType, u32 typeNum) {
Psmf *psmf = getPsmf(psmfStruct);
if (!psmf) {
ERROR_LOG(ME, "scePsmfSpecifyStreamWithStreamTypeNumber(%08x, %08x, %08x): invalid psmf", psmfStruct, streamType, typeNum);
return ERROR_PSMF_NOT_FOUND;
return hleLogError(ME, ERROR_PSMF_NOT_INITIALIZED, "invalid psmf");
}
INFO_LOG_REPORT(ME, "scePsmfSpecifyStreamWithStreamTypeNumber(%08x, %08x, %08x)", psmfStruct, streamType, typeNum);
// right now typeNum and channel are the same...
if (!psmf->setStreamWithType(streamType, typeNum)) {
psmf->setStreamNum(-1);
if (!psmf->setStreamWithTypeNumber(streamType, typeNum)) {
// Don't update stream, just bail out.
return hleLogWarning(ME, ERROR_PSMF_INVALID_ID, "no stream found");
}
return 0;
return hleLogSuccessI(ME, 0);
}

static u32 scePsmfSpecifyStream(u32 psmfStruct, int streamNum) {
Psmf *psmf = getPsmf(psmfStruct);
if (!psmf) {
ERROR_LOG(ME, "scePsmfSpecifyStream(%08x, %i): invalid psmf", psmfStruct, streamNum);
return ERROR_PSMF_NOT_FOUND;
return hleLogError(ME, ERROR_PSMF_NOT_INITIALIZED, "invalid psmf");
}
INFO_LOG(ME, "scePsmfSpecifyStream(%08x, %i)", psmfStruct, streamNum);
psmf->setStreamNum(streamNum);
return 0;
if (!psmf->setStreamNum(streamNum)) {
psmf->setStreamNum(ERROR_PSMF_NOT_INITIALIZED);
return hleLogWarning(ME, ERROR_PSMF_INVALID_ID, "bad stream id");
}
return hleLogSuccessI(ME, 0);
}

static u32 scePsmfGetVideoInfo(u32 psmfStruct, u32 videoInfoAddr) {
Expand Down Expand Up @@ -751,20 +795,19 @@ static u32 scePsmfGetAudioInfo(u32 psmfStruct, u32 audioInfoAddr) {
static u32 scePsmfGetCurrentStreamType(u32 psmfStruct, u32 typeAddr, u32 channelAddr) {
Psmf *psmf = getPsmf(psmfStruct);
if (!psmf) {
ERROR_LOG(ME, "scePsmfGetCurrentStreamType(%08x, %08x, %08x): invalid psmf", psmfStruct, typeAddr, channelAddr);
return ERROR_PSMF_NOT_FOUND;
return hleLogError(ME, ERROR_PSMF_NOT_INITIALIZED, "invalid psmf");
}
INFO_LOG(ME, "scePsmfGetCurrentStreamType(%08x, %08x, %08x)", psmfStruct, typeAddr, channelAddr);
if (Memory::IsValidAddress(typeAddr)) {
u32 type = 0, channel = 0;
if (psmf->streamMap.find(psmf->currentStreamNum) != psmf->streamMap.end())
type = psmf->streamMap[psmf->currentStreamNum]->type;
if (psmf->streamMap.find(psmf->currentStreamNum) != psmf->streamMap.end())
channel = psmf->streamMap[psmf->currentStreamNum]->channel;
Memory::Write_U32(type, typeAddr);
Memory::Write_U32(channel, channelAddr);
if (psmf->currentStreamNum == ERROR_PSMF_NOT_INITIALIZED) {
return hleLogError(ME, ERROR_PSMF_NOT_INITIALIZED, "no stream set");
}
return 0;
if (!Memory::IsValidAddress(typeAddr) || !Memory::IsValidAddress(channelAddr)) {
return hleLogError(ME, SCE_KERNEL_ERROR_ILLEGAL_ADDRESS, "bad pointers");
}
if (psmf->currentStreamType != -1) {
Memory::Write_U32(psmf->currentStreamType, typeAddr);
Memory::Write_U32(psmf->currentStreamChannel, channelAddr);
}
return hleLogSuccessI(ME, 0);
}

static u32 scePsmfGetStreamSize(u32 psmfStruct, u32 sizeAddr)
Expand Down Expand Up @@ -882,16 +925,15 @@ static u32 scePsmfGetPresentationEndTime(u32 psmfStruct, u32 endTimeAddr)
return 0;
}

static u32 scePsmfGetCurrentStreamNumber(u32 psmfStruct)
{
static u32 scePsmfGetCurrentStreamNumber(u32 psmfStruct) {
Psmf *psmf = getPsmf(psmfStruct);
if (!psmf) {
ERROR_LOG(ME, "scePsmfGetCurrentStreamNumber(%08x): invalid psmf", psmfStruct);
return ERROR_PSMF_NOT_FOUND;
return hleLogError(ME, ERROR_PSMF_NOT_INITIALIZED, "invalid psmf");
}

DEBUG_LOG(ME, "scePsmfGetCurrentStreamNumber(%08x)", psmfStruct);
return psmf->currentStreamNum;
if (psmf->currentStreamNum < 0) {
return hleLogError(ME, psmf->currentStreamNum, "invalid stream");
}
return hleLogSuccessI(ME, psmf->currentStreamNum);
}

static u32 scePsmfCheckEPMap(u32 psmfStruct)
Expand Down Expand Up @@ -1987,19 +2029,19 @@ static int __PsmfPlayerFinish(u32 psmfPlayer) {

const HLEFunction scePsmf[] = {
{0XC22C8327, &WrapU_UU<scePsmfSetPsmf>, "scePsmfSetPsmf", 'x', "xx" },
{0XC7DB3A5B, &WrapU_UUU<scePsmfGetCurrentStreamType>, "scePsmfGetCurrentStreamType", 'x', "xxx"},
{0X28240568, &WrapU_U<scePsmfGetCurrentStreamNumber>, "scePsmfGetCurrentStreamNumber", 'x', "x" },
{0X1E6D9013, &WrapU_UUU<scePsmfSpecifyStreamWithStreamType>, "scePsmfSpecifyStreamWithStreamType", 'x', "xxx"},
{0X0C120E1D, &WrapU_UUU<scePsmfSpecifyStreamWithStreamTypeNumber>, "scePsmfSpecifyStreamWithStreamTypeNumber", 'x', "xxx"},
{0X4BC9BDE0, &WrapU_UI<scePsmfSpecifyStream>, "scePsmfSpecifyStream", 'x', "xi" },
{0XC7DB3A5B, &WrapU_UUU<scePsmfGetCurrentStreamType>, "scePsmfGetCurrentStreamType", 'i', "xpp"},
{0X28240568, &WrapU_U<scePsmfGetCurrentStreamNumber>, "scePsmfGetCurrentStreamNumber", 'i', "x" },
{0X1E6D9013, &WrapU_UUU<scePsmfSpecifyStreamWithStreamType>, "scePsmfSpecifyStreamWithStreamType", 'i', "xii"},
{0X0C120E1D, &WrapU_UUU<scePsmfSpecifyStreamWithStreamTypeNumber>, "scePsmfSpecifyStreamWithStreamTypeNumber", 'i', "xii"},
{0X4BC9BDE0, &WrapU_UI<scePsmfSpecifyStream>, "scePsmfSpecifyStream", 'i', "xi" },
{0X76D3AEBA, &WrapU_UU<scePsmfGetPresentationStartTime>, "scePsmfGetPresentationStartTime", 'x', "xx" },
{0XBD8AE0D8, &WrapU_UU<scePsmfGetPresentationEndTime>, "scePsmfGetPresentationEndTime", 'x', "xx" },
{0XEAED89CD, &WrapU_U<scePsmfGetNumberOfStreams>, "scePsmfGetNumberOfStreams", 'x', "x" },
{0XEAED89CD, &WrapU_U<scePsmfGetNumberOfStreams>, "scePsmfGetNumberOfStreams", 'i', "x" },
{0X7491C438, &WrapU_U<scePsmfGetNumberOfEPentries>, "scePsmfGetNumberOfEPentries", 'x', "x" },
{0X0BA514E5, &WrapU_UU<scePsmfGetVideoInfo>, "scePsmfGetVideoInfo", 'x', "xx" },
{0XA83F7113, &WrapU_UU<scePsmfGetAudioInfo>, "scePsmfGetAudioInfo", 'x', "xx" },
{0X971A3A90, &WrapU_U<scePsmfCheckEPMap>, "scePsmfCheckEPmap", 'x', "x" },
{0X68D42328, &WrapU_UI<scePsmfGetNumberOfSpecificStreams>, "scePsmfGetNumberOfSpecificStreams", 'x', "xi" },
{0X68D42328, &WrapU_UI<scePsmfGetNumberOfSpecificStreams>, "scePsmfGetNumberOfSpecificStreams", 'i', "xi" },
{0X5B70FCC1, &WrapU_UU<scePsmfQueryStreamOffset>, "scePsmfQueryStreamOffset", 'x', "xx" },
{0X9553CC91, &WrapU_UU<scePsmfQueryStreamSize>, "scePsmfQueryStreamSize", 'x', "xx" },
{0XB78EB9E9, &WrapU_UU<scePsmfGetHeaderSize>, "scePsmfGetHeaderSize", 'x', "xx" },
Expand Down