Skip to content

Commit

Permalink
Load the EP map from the psmf data when available.
Browse files Browse the repository at this point in the history
Rather than just having uninitialized values.

Fixes #2642, World Neverland.
  • Loading branch information
unknownbrackets committed Jan 1, 2014
1 parent bb10ffd commit 36707ce
Showing 1 changed file with 65 additions and 18 deletions.
83 changes: 65 additions & 18 deletions Core/HLE/scePsmf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,10 @@ struct PsmfPlayerData {
};

struct PsmfEntry {
int EPIndex;
int EPPicOffset;
int EPPts;
int EPOffset;
int id;
int EPIndex;
int EPPicOffset;
};

int getMaxAheadTimestamp(int packets) {return std::max(40000, packets * 700);}
Expand Down Expand Up @@ -123,6 +122,8 @@ class Psmf {
void setStreamNum(int num);
bool setStreamWithType(int type, int channel);

int FindEPWithTimestamp(int pts);

u32 magic;
u32 version;
u32 streamOffset;
Expand Down Expand Up @@ -151,7 +152,7 @@ class Psmf {
int videoHeight;
int audioChannels;
int audioFrequency;
PsmfEntry psmfEntry;
std::vector<PsmfEntry> EPMap;

PsmfStreamMap streamMap;
};
Expand Down Expand Up @@ -210,6 +211,18 @@ class PsmfStream {
psmf->videoWidth = Memory::Read_U8(addr + 12) * 16;
psmf->videoHeight = Memory::Read_U8(addr + 13) * 16;

const u32 EP_MAP_STRIDE = 1 + 1 + 4 + 4;
psmf->EPMap.clear();
for (u32 i = 0; i < psmf->EPMapEntriesNum; i++) {
const u32 entryAddr = addr + psmf->EPMapOffset + EP_MAP_STRIDE * i;
PsmfEntry entry;
entry.EPIndex = Memory::Read_U8(entryAddr + 0);
entry.EPPicOffset = Memory::Read_U8(entryAddr + 1);
entry.EPPts = Memory::Read_U32(entryAddr + 2);
entry.EPOffset = Memory::Read_U32(entryAddr + 6);
psmf->EPMap.push_back(entry);
}

INFO_LOG(ME, "PSMF MPEG data found: id=%02x, privid=%02x, epmoff=%08x, epmnum=%08x, width=%i, height=%i", streamId, privateStreamId, psmf->EPMapOffset, psmf->EPMapEntriesNum, psmf->videoWidth, psmf->videoHeight);
}

Expand Down Expand Up @@ -298,7 +311,7 @@ PsmfPlayer::PsmfPlayer(u32 data) {
}

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

Expand All @@ -325,6 +338,10 @@ void Psmf::DoState(PointerWrap &p) {
p.Do(audioChannels);
p.Do(audioFrequency);

if (s >= 2) {
p.Do(EPMap);
}

p.Do(streamMap);
}

Expand Down Expand Up @@ -393,6 +410,26 @@ bool Psmf::setStreamWithType(int type, int channel) {
return false;
}

int Psmf::FindEPWithTimestamp(int pts) {
int best = -1;
int bestPts = 0;

for (int i = 0; i < (int)EPMap.size(); ++i) {
const int matchPts = EPMap[i].EPPts;
if (matchPts == pts) {
// Exact match, take it.
return i;
}
// TODO: Does it actually do fuzzy matching?
if (matchPts < pts && matchPts >= bestPts) {
best = i;
bestPts = matchPts;
}
}

return best;
}


static std::map<u32, Psmf *> psmfMap;
static std::map<u32, PsmfPlayer *> psmfPlayerMap;
Expand Down Expand Up @@ -719,19 +756,20 @@ u32 scePsmfCheckEPMap(u32 psmfPlayer)
return 0; // Should be okay according to JPCSP
}

u32 scePsmfGetEPWithId(u32 psmfStruct, int id, u32 outAddr)
u32 scePsmfGetEPWithId(u32 psmfStruct, int epid, u32 entryAddr)
{
Psmf *psmf = getPsmf(psmfStruct);
if (!psmf) {
ERROR_LOG(ME, "scePsmfGetEPWithId(%08x, %i, %08x): invalid psmf", psmfStruct, id, outAddr);
ERROR_LOG(ME, "scePsmfGetEPWithId(%08x, %i, %08x): invalid psmf", psmfStruct, epid, entryAddr);
return ERROR_PSMF_NOT_FOUND;
}
DEBUG_LOG(ME, "scePsmfGetEPWithId(%08x, %i, %08x)", psmfStruct, id, outAddr);
if (Memory::IsValidAddress(outAddr)) {
Memory::Write_U32(psmf->psmfEntry.EPPts, outAddr);
Memory::Write_U32(psmf->psmfEntry.EPOffset, outAddr + 4);
Memory::Write_U32(psmf->psmfEntry.EPIndex, outAddr + 8);
Memory::Write_U32(psmf->psmfEntry.EPPicOffset, outAddr + 12);
DEBUG_LOG(ME, "scePsmfGetEPWithId(%08x, %i, %08x)", psmfStruct, epid, entryAddr);
if (epid < 0 || epid > (int)psmf->EPMap.size()) {
// TODO: Just a guess.
return ERROR_PSMF_INVALID_TIMESTAMP;
}
if (Memory::IsValidAddress(entryAddr)) {
Memory::WriteStruct(entryAddr, &psmf->EPMap[epid]);
}
return 0;
}
Expand All @@ -747,11 +785,15 @@ u32 scePsmfGetEPWithTimestamp(u32 psmfStruct, u32 ts, u32 entryAddr)
if (ts < psmf->presentationStartTime) {
return ERROR_PSMF_INVALID_TIMESTAMP;
}

int epid = psmf->FindEPWithTimestamp(ts);
if (epid < 0 || epid > (int)psmf->EPMap.size()) {
// TODO: Just a guess.
return ERROR_PSMF_INVALID_TIMESTAMP;
}

if (Memory::IsValidAddress(entryAddr)) {
Memory::Write_U32(psmf->psmfEntry.EPPts, entryAddr);
Memory::Write_U32(psmf->psmfEntry.EPOffset, entryAddr + 4);
Memory::Write_U32(psmf->psmfEntry.EPIndex, entryAddr + 8);
Memory::Write_U32(psmf->psmfEntry.EPPicOffset, entryAddr + 12);
Memory::WriteStruct(entryAddr, &psmf->EPMap[epid]);
}
return 0;
}
Expand All @@ -768,7 +810,12 @@ u32 scePsmfGetEPidWithTimestamp(u32 psmfStruct, u32 ts)
return ERROR_PSMF_INVALID_TIMESTAMP;
}

return psmf->psmfEntry.id;
int epid = psmf->FindEPWithTimestamp(ts);
if (epid < 0 || epid > (int)psmf->EPMap.size()) {
// TODO: Just a guess.
return ERROR_PSMF_INVALID_TIMESTAMP;
}
return epid;
}

int scePsmfPlayerCreate(u32 psmfPlayer, u32 psmfPlayerDataAddr)
Expand Down

0 comments on commit 36707ce

Please sign in to comment.