1 // Copyright (c) 2012- PPSSPP Project.
2 
3 // This program is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, version 2.0 or later versions.
6 
7 // This program is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 // GNU General Public License 2.0 for more details.
11 
12 // A copy of the GPL 2.0 should have been included with the program.
13 // If not, see http://www.gnu.org/licenses/
14 
15 // Official git repository and contact information can be found at
16 // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
17 
18 #include "Common/Serialize/Serializer.h"
19 #include "Common/Serialize/SerializeFuncs.h"
20 #include "Common/Serialize/SerializeMap.h"
21 #include "Core/MemMapHelpers.h"
22 #include "Core/Reporting.h"
23 #include "Core/System.h"
24 #include "Core/FileSystems/MetaFileSystem.h"
25 #include "Core/HLE/HLE.h"
26 #include "Core/HLE/HLEHelperThread.h"
27 #include "Core/HLE/FunctionWrappers.h"
28 #include "Core/HLE/scePsmf.h"
29 #include "Core/HLE/sceMpeg.h"
30 #include "Core/HLE/sceKernelMemory.h"
31 #include "Core/HW/MediaEngine.h"
32 #include "Core/CoreTiming.h"
33 #include "GPU/GPUInterface.h"
34 #include "GPU/GPUState.h"
35 
36 #include <map>
37 #include <algorithm>
38 
39 // "Go Sudoku" is a good way to test this code...
40 const int PSMF_AVC_STREAM = 0;
41 const int PSMF_ATRAC_STREAM = 1;
42 const int PSMF_PCM_STREAM = 2;
43 const int PSMF_DATA_STREAM = 3;
44 const int PSMF_AUDIO_STREAM = 15;
45 const int PSMF_PLAYER_VERSION_FULL = 0;
46 const int PSMF_PLAYER_VERSION_BASIC = 1;
47 const int PSMF_PLAYER_VERSION_NET = 2;
48 const int PSMF_PLAYER_CONFIG_LOOP = 0;
49 const int PSMF_PLAYER_CONFIG_NO_LOOP = 1;
50 const int PSMF_PLAYER_CONFIG_MODE_LOOP = 0;
51 const int PSMF_PLAYER_CONFIG_MODE_PIXEL_TYPE = 1;
52 
53 const int PSMF_PLAYER_WARMUP_FRAMES = 3;
54 
55 static const int VIDEO_FRAME_DURATION_TS = 3003;
56 
57 static const int audioSamples = 2048;
58 static const int audioSamplesBytes = audioSamples * 4;
59 static int videoPixelMode = GE_CMODE_32BIT_ABGR8888;
60 static int videoLoopStatus = PSMF_PLAYER_CONFIG_NO_LOOP;
61 static int psmfPlayerLibVersion = 0;
62 
63 int eventPsmfPlayerStatusChange = -1;
64 
65 enum PsmfPlayerError {
66 	ERROR_PSMF_NOT_INITIALIZED       = 0x80615001,
67 	ERROR_PSMF_BAD_VERSION           = 0x80615002,
68 	ERROR_PSMF_NOT_FOUND             = 0x80615025,
69 	ERROR_PSMF_INVALID_ID            = 0x80615100,
70 	ERROR_PSMF_INVALID_VALUE         = 0x806151fe,
71 	ERROR_PSMF_INVALID_TIMESTAMP     = 0x80615500,
72 	ERROR_PSMF_INVALID_PSMF          = 0x80615501,
73 
74 	ERROR_PSMFPLAYER_INVALID_STATUS  = 0x80616001,
75 	ERROR_PSMFPLAYER_INVALID_STREAM  = 0x80616003,
76 	ERROR_PSMFPLAYER_BUFFER_SIZE     = 0x80616005,
77 	ERROR_PSMFPLAYER_INVALID_CONFIG  = 0x80616006,
78 	ERROR_PSMFPLAYER_INVALID_PARAM   = 0x80616008,
79 	ERROR_PSMFPLAYER_NO_MORE_DATA    = 0x8061600c,
80 };
81 
82 enum PsmfPlayerStatus {
83 	PSMF_PLAYER_STATUS_NONE             = 0x0,
84 	PSMF_PLAYER_STATUS_INIT             = 0x1,
85 	PSMF_PLAYER_STATUS_STANDBY          = 0x2,
86 	PSMF_PLAYER_STATUS_PLAYING          = 0x4,
87 	PSMF_PLAYER_STATUS_ERROR            = 0x100,
88 	PSMF_PLAYER_STATUS_PLAYING_FINISHED = 0x200,
89 };
90 
91 enum PsmfPlayerMode {
92 	PSMF_PLAYER_MODE_PLAY       = 0,
93 	PSMF_PLAYER_MODE_SLOWMOTION = 1,
94 	PSMF_PLAYER_MODE_STEPFRAME  = 2,
95 	PSMF_PLAYER_MODE_PAUSE      = 3,
96 	PSMF_PLAYER_MODE_FORWARD    = 4,
97 	PSMF_PLAYER_MODE_REWIND     = 5,
98 };
99 
100 struct PsmfData {
101 	u32_le version;
102 	u32_le headerSize;
103 	u32_le headerOffset;
104 	u32_le streamSize;
105 	u32_le streamOffset;
106 	u32_le streamNum;
107 	u32_le unk1;
108 	u32_le unk2;
109 };
110 
111 struct PsmfPlayerCreateData {
112 	PSPPointer<u8> buffer;
113 	u32_le bufferSize;
114 	s32_le threadPriority;
115 };
116 
117 struct PsmfPlayerData {
118 	s32_le videoCodec;
119 	s32_le videoStreamNum;
120 	s32_le audioCodec;
121 	s32_le audioStreamNum;
122 	s32_le playMode;
123 	s32_le playSpeed;
124 };
125 
126 struct PsmfInfo {
127 	u32_le lastFrameTS;
128 	s32_le numVideoStreams;
129 	s32_le numAudioStreams;
130 	s32_le numPCMStreams;
131 	s32_le playerVersion;
132 };
133 
134 struct PsmfVideoData {
135 	s32_le frameWidth;
136 	u32_le displaybuf;
137 	u32_le displaypts;
138 };
139 
140 struct PsmfEntry {
141 	int EPPts;
142 	int EPOffset;
143 	int EPIndex;
144 	int EPPicOffset;
145 };
146 
147 // Some of our platforms don't play too nice with direct unaligned access.
ReadUnalignedU32BE(const u8 * p)148 static u32 ReadUnalignedU32BE(const u8 *p) {
149 	return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3] << 0);
150 }
151 
152 class PsmfStream;
153 
154 // This does NOT match the raw structure. Due to endianness etc,
155 // we read it manually.
156 // TODO: Change to work directly with the data in RAM instead of this
157 // JPSCP-esque class.
158 typedef std::map<int, PsmfStream *> PsmfStreamMap;
159 
160 class Psmf {
161 public:
162 	// For savestates only.
Psmf()163 	Psmf() {}
164 	Psmf(const u8 *ptr, u32 data);
165 	~Psmf();
166 	void DoState(PointerWrap &p);
167 
isValidCurrentStreamNumber() const168 	bool isValidCurrentStreamNumber() const {
169 		return currentStreamNum >= 0 && streamMap.find(currentStreamNum) != streamMap.end();
170 	}
171 
172 	bool setStreamNum(u32 psmfStruct, int num, bool updateCached = true);
173 	bool setStreamWithType(u32 psmfStruct, int type, int channel);
174 	bool setStreamWithTypeNumber(u32 psmfStruct, int type, int n);
175 
176 	int FindEPWithTimestamp(int pts) const;
177 
178 	u32 magic;
179 	u32 version;
180 	u32 streamOffset;
181 	u32 streamSize;
182 	u32 headerSize;
183 	u32 headerOffset;
184 	u32 streamType;
185 	u32 streamChannel;
186 	// 0x50
187 	u32 streamDataTotalSize;
188 	u32 presentationStartTime;
189 	u32 presentationEndTime;
190 	u32 streamDataNextBlockSize;
191 	u32 streamDataNextInnerBlockSize;
192 
193 	int numStreams;
194 	int currentStreamNum;
195 	int currentStreamType;
196 	int currentStreamChannel;
197 
198 	// parameters gotten from streams
199 	// I guess this is the seek information?
200 	u32 EPMapOffset;
201 	u32 EPMapEntriesNum;
202 	// These shouldn't be here, just here for convenience with old states.
203 	int videoWidth;
204 	int videoHeight;
205 	int audioChannels;
206 	int audioFrequency;
207 	std::vector<PsmfEntry> EPMap;
208 
209 	PsmfStreamMap streamMap;
210 };
211 
212 class PsmfPlayer {
213 public:
214 	// For savestates only.
PsmfPlayer()215 	PsmfPlayer() : videoWidth(480), videoHeight(272) {
216 		mediaengine = new MediaEngine();
217 	}
218 	PsmfPlayer(const PsmfPlayerCreateData *data);
~PsmfPlayer()219 	~PsmfPlayer() {
220 		AbortFinish();
221 		if (mediaengine)
222 			delete mediaengine;
223 		pspFileSystem.CloseFile(filehandle);
224 	}
225 	void DoState(PointerWrap &p);
226 
ScheduleFinish(u32 handle)227 	void ScheduleFinish(u32 handle) {
228 		if (!finishThread) {
229 			finishThread = new HLEHelperThread("scePsmfPlayer", "scePsmfPlayer", "__PsmfPlayerFinish", playbackThreadPriority, 0x200);
230 			finishThread->Start(handle, 0);
231 		}
232 	}
233 
AbortFinish()234 	void AbortFinish() {
235 		if (finishThread) {
236 			delete finishThread;
237 			finishThread = nullptr;
238 		}
239 	}
240 
HasReachedEnd()241 	bool HasReachedEnd() {
242 		// The pts are ignored - the end is when we're out of data.
243 		return mediaengine->IsVideoEnd() && (mediaengine->IsNoAudioData() || !mediaengine->IsActuallyPlayingAudio());
244 	}
245 
246 	int filehandle = 0;
247 	u32 fileoffset;
248 	int readSize;
249 	int streamSize;
250 	u8 tempbuf[0x10000];
251 
252 	int videoCodec;
253 	int videoStreamNum;
254 	int audioCodec;
255 	int audioStreamNum;
256 	int playMode;
257 	int playSpeed;
258 	u64 totalDurationTimestamp;
259 
260 	int displayBuffer;
261 	int displayBufferSize;
262 	int playbackThreadPriority;
263 	int totalVideoStreams;
264 	int totalAudioStreams;
265 	int playerVersion;
266 	int videoStep;
267 	int warmUp;
268 	s64 seekDestTimeStamp;
269 
270 	int videoWidth;
271 	int videoHeight;
272 
273 	SceMpegAu psmfPlayerAtracAu;
274 	SceMpegAu psmfPlayerAvcAu;
275 	PsmfPlayerStatus status;
276 
277 	MediaEngine *mediaengine;
278 	HLEHelperThread *finishThread = nullptr;
279 };
280 
281 class PsmfStream {
282 public:
283 	enum {
284 		USE_PSMF = -2,
285 		INVALID = -1,
286 	};
287 
288 	// Used for save states.
PsmfStream()289 	PsmfStream() : videoWidth_(USE_PSMF), videoHeight_(USE_PSMF), audioChannels_(USE_PSMF), audioFrequency_(USE_PSMF) {
290 	}
291 
PsmfStream(int type,int channel)292 	PsmfStream(int type, int channel) : videoWidth_(INVALID), videoHeight_(INVALID), audioChannels_(INVALID), audioFrequency_(INVALID) {
293 		type_ = type;
294 		channel_ = channel;
295 	}
296 
readMPEGVideoStreamParams(const u8 * addr,const u8 * data,Psmf * psmf)297 	void readMPEGVideoStreamParams(const u8 *addr, const u8 *data, Psmf *psmf) {
298 		int streamId = addr[0];
299 		int privateStreamId = addr[1];
300 		// two unknowns here
301 		psmf->EPMapOffset = ReadUnalignedU32BE(&addr[4]);
302 		psmf->EPMapEntriesNum = ReadUnalignedU32BE(&addr[8]);
303 		videoWidth_ = addr[12] * 16;
304 		videoHeight_ = addr[13] * 16;
305 
306 		const u32 EP_MAP_STRIDE = 1 + 1 + 4 + 4;
307 		psmf->EPMap.clear();
308 		for (u32 i = 0; i < psmf->EPMapEntriesNum; i++) {
309 			const u8 *const entryAddr = data + psmf->EPMapOffset + EP_MAP_STRIDE * i;
310 			PsmfEntry entry;
311 			entry.EPIndex = entryAddr[0];
312 			entry.EPPicOffset = entryAddr[1];
313 			entry.EPPts = ReadUnalignedU32BE(&entryAddr[2]);
314 			entry.EPOffset = ReadUnalignedU32BE(&entryAddr[6]);
315 			psmf->EPMap.push_back(entry);
316 		}
317 
318 		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);
319 	}
320 
readPrivateAudioStreamParams(const u8 * addr,Psmf * psmf)321 	void readPrivateAudioStreamParams(const u8 *addr, Psmf *psmf) {
322 		int streamId = addr[0];
323 		int privateStreamId = addr[1];
324 		audioChannels_ = addr[14];
325 		// Note: "frequency" is usually 2.  But that's what scePsmfGetAudioInfo() writes too.
326 		audioFrequency_ = addr[15];
327 		// two unknowns here
328 		INFO_LOG(ME, "PSMF private audio found: id=%02x, privid=%02x, channels=%i, freq=%i", streamId, privateStreamId, psmf->audioChannels, psmf->audioFrequency);
329 	}
330 
matchesType(int ty)331 	bool matchesType(int ty) {
332 		if (ty == PSMF_AUDIO_STREAM) {
333 			return type_ == PSMF_ATRAC_STREAM || type_ == PSMF_PCM_STREAM;
334 		}
335 		return type_ == ty;
336 	}
337 
DoState(PointerWrap & p)338 	void DoState(PointerWrap &p) {
339 		auto s = p.Section("PsmfStream", 1, 2);
340 		if (!s)
341 			return;
342 
343 		Do(p, type_);
344 		Do(p, channel_);
345 		if (s >= 2) {
346 			Do(p, videoWidth_);
347 			Do(p, videoHeight_);
348 			Do(p, audioChannels_);
349 			Do(p, audioFrequency_);
350 		}
351 	}
352 
353 	int type_;
354 	int channel_;
355 	int videoWidth_;
356 	int videoHeight_;
357 	int audioChannels_;
358 	int audioFrequency_;
359 };
360 
361 
Psmf(const u8 * ptr,u32 data)362 Psmf::Psmf(const u8 *ptr, u32 data) {
363 	headerOffset = data;
364 	magic = *(u32_le *)&ptr[0];
365 	version = *(u32_le *)&ptr[4];
366 	streamOffset = ReadUnalignedU32BE(&ptr[8]);
367 	streamSize = ReadUnalignedU32BE(&ptr[12]);
368 	streamDataTotalSize = ReadUnalignedU32BE(&ptr[0x50]);
369 	presentationStartTime = getMpegTimeStamp(ptr + PSMF_FIRST_TIMESTAMP_OFFSET);
370 	presentationEndTime = getMpegTimeStamp(ptr + PSMF_LAST_TIMESTAMP_OFFSET);
371 	streamDataNextBlockSize = ReadUnalignedU32BE(&ptr[0x6A]);
372 	streamDataNextInnerBlockSize = ReadUnalignedU32BE(&ptr[0x7C]);
373 	numStreams = *(u16_be *)&ptr[0x80];
374 	// TODO: Always?
375 	headerSize = 0x800;
376 
377 	currentStreamNum = -1;
378 	currentStreamType = -1;
379 	currentStreamChannel = -1;
380 
381 	for (int i = 0; i < numStreams; i++) {
382 		PsmfStream *stream = 0;
383 		const u8 *const currentStreamAddr = ptr + 0x82 + i * 16;
384 		int streamId = currentStreamAddr[0];
385 		if ((streamId & PSMF_VIDEO_STREAM_ID) == PSMF_VIDEO_STREAM_ID) {
386 			stream = new PsmfStream(PSMF_AVC_STREAM, streamId & 0x0F);
387 			stream->readMPEGVideoStreamParams(currentStreamAddr, ptr, this);
388 		} else if ((streamId & PSMF_AUDIO_STREAM_ID) == PSMF_AUDIO_STREAM_ID) {
389 			int type = PSMF_ATRAC_STREAM;
390 			int privateStreamId = currentStreamAddr[1];
391 			if ((privateStreamId & 0xF0) != 0) {
392 				WARN_LOG_REPORT(ME, "Unknown private stream type, assuming PCM: %02x", privateStreamId);
393 				type = PSMF_PCM_STREAM;
394 			}
395 			stream = new PsmfStream(type, privateStreamId & 0x0F);
396 			stream->readPrivateAudioStreamParams(currentStreamAddr, this);
397 		}
398 		if (stream) {
399 			currentStreamNum++;
400 			streamMap[currentStreamNum] = stream;
401 		}
402 	}
403 
404 	// Default to the first stream.
405 	currentStreamNum = 0;
406 }
407 
~Psmf()408 Psmf::~Psmf() {
409 	for (auto it = streamMap.begin(), end = streamMap.end(); it != end; ++it) {
410 		delete it->second;
411 	}
412 	streamMap.clear();
413 }
414 
PsmfPlayer(const PsmfPlayerCreateData * data)415 PsmfPlayer::PsmfPlayer(const PsmfPlayerCreateData *data) {
416 	videoCodec = -1;
417 	videoStreamNum = -1;
418 	audioCodec = -1;
419 	audioStreamNum = -1;
420 	playMode = 0;
421 	playSpeed = 1;
422 	totalDurationTimestamp = 0;
423 	status = PSMF_PLAYER_STATUS_INIT;
424 	mediaengine = new MediaEngine();
425 	finishThread = nullptr;
426 	filehandle = 0;
427 	fileoffset = 0;
428 	readSize = 0;
429 	streamSize = 0;
430 	videoStep = 0;
431 	warmUp = 0;
432 	seekDestTimeStamp = 0;
433 
434 	psmfPlayerAtracAu.dts =-1;
435 	psmfPlayerAtracAu.pts = -1;
436 	psmfPlayerAvcAu.dts = -1;
437 	psmfPlayerAvcAu.pts = -1;
438 
439 	displayBuffer = data->buffer.ptr;
440 	displayBufferSize = data->bufferSize;
441 	playbackThreadPriority = data->threadPriority;
442 }
443 
DoState(PointerWrap & p)444 void Psmf::DoState(PointerWrap &p) {
445 	auto s = p.Section("Psmf", 1, 3);
446 	if (!s)
447 		return;
448 
449 	Do(p, magic);
450 	Do(p, version);
451 	Do(p, streamOffset);
452 	Do(p, streamSize);
453 	Do(p, headerOffset);
454 	Do(p, streamDataTotalSize);
455 	Do(p, presentationStartTime);
456 	Do(p, presentationEndTime);
457 	Do(p, streamDataNextBlockSize);
458 	Do(p, streamDataNextInnerBlockSize);
459 	Do(p, numStreams);
460 
461 	Do(p, currentStreamNum);
462 	int legacyStreamNums = 0;
463 	Do(p, legacyStreamNums);
464 	Do(p, legacyStreamNums);
465 
466 	Do(p, EPMapOffset);
467 	Do(p, EPMapEntriesNum);
468 	Do(p, videoWidth);
469 	Do(p, videoHeight);
470 	Do(p, audioChannels);
471 	Do(p, audioFrequency);
472 
473 	if (s >= 2) {
474 		Do(p, EPMap);
475 	}
476 
477 	Do(p, streamMap);
478 	if (s >= 3) {
479 		Do(p, currentStreamType);
480 		Do(p, currentStreamChannel);
481 	} else {
482 		currentStreamType = -1;
483 		currentStreamChannel = -1;
484 		auto streamInfo = streamMap.find(currentStreamNum);
485 		if (streamInfo != streamMap.end()) {
486 			currentStreamType = streamInfo->second->type_;
487 			currentStreamChannel = streamInfo->second->channel_;
488 		}
489 	}
490 }
491 
DoState(PointerWrap & p)492 void PsmfPlayer::DoState(PointerWrap &p) {
493 	auto s = p.Section("PsmfPlayer", 1, 8);
494 	if (!s)
495 		return;
496 
497 	Do(p, videoCodec);
498 	Do(p, videoStreamNum);
499 	Do(p, audioCodec);
500 	Do(p, audioStreamNum);
501 	Do(p, playMode);
502 	Do(p, playSpeed);
503 
504 	Do(p, displayBuffer);
505 	Do(p, displayBufferSize);
506 	Do(p, playbackThreadPriority);
507 	int oldMaxAheadTimestamp = 0;
508 	Do(p, oldMaxAheadTimestamp);
509 	if (s >= 4) {
510 		Do(p, totalDurationTimestamp);
511 	} else {
512 		long oldTimestamp;
513 		Do(p, oldTimestamp);
514 		totalDurationTimestamp = oldTimestamp;
515 	}
516 	if (s >= 2) {
517 		Do(p, totalVideoStreams);
518 		Do(p, totalAudioStreams);
519 		Do(p, playerVersion);
520 	} else {
521 		totalVideoStreams = 1;
522 		totalAudioStreams = 1;
523 		playerVersion = PSMF_PLAYER_VERSION_FULL;
524 	}
525 	if (s >= 3) {
526 		Do(p, videoStep);
527 	} else {
528 		videoStep = 0;
529 	}
530 	if (s >= 4) {
531 		Do(p, warmUp);
532 	} else {
533 		warmUp = 10000;
534 	}
535 	if (s >= 5) {
536 		Do(p, seekDestTimeStamp);
537 	} else {
538 		seekDestTimeStamp = 0;
539 	}
540 	DoClass(p, mediaengine);
541 	Do(p, filehandle);
542 	Do(p, fileoffset);
543 	Do(p, readSize);
544 	Do(p, streamSize);
545 
546 	Do(p, status);
547 	if (s >= 4) {
548 		Do(p, psmfPlayerAtracAu);
549 	}
550 	Do(p, psmfPlayerAvcAu);
551 	if (s >= 7) {
552 		bool hasFinishThread = finishThread != nullptr;
553 		Do(p, hasFinishThread);
554 		if (hasFinishThread) {
555 			Do(p, finishThread);
556 		} else {
557 			if (finishThread)
558 				finishThread->Forget();
559 			delete finishThread;
560 			finishThread = nullptr;
561 		}
562 	} else if (s >= 6) {
563 		Do(p, finishThread);
564 	} else {
565 		if (finishThread)
566 			finishThread->Forget();
567 		delete finishThread;
568 		finishThread = nullptr;
569 	}
570 
571 	if (s >= 8) {
572 		Do(p, videoWidth);
573 		Do(p, videoHeight);
574 	}
575 }
576 
setStreamNum(u32 psmfStruct,int num,bool updateCached)577 bool Psmf::setStreamNum(u32 psmfStruct, int num, bool updateCached) {
578 	auto data = PSPPointer<PsmfData>::Create(psmfStruct);
579 	currentStreamNum = num;
580 	data->streamNum = num;
581 
582 	// One of the functions can set this to invalid without invalidating these values.
583 	if (updateCached) {
584 		currentStreamType = -1;
585 		currentStreamChannel = -1;
586 	}
587 	if (!isValidCurrentStreamNumber())
588 		return false;
589 	PsmfStreamMap::iterator iter = streamMap.find(currentStreamNum);
590 	if (iter == streamMap.end())
591 		return false;
592 
593 	// This information seems to only be for the scePsmf lookups.
594 	currentStreamType = iter->second->type_;
595 	currentStreamChannel = iter->second->channel_;
596 	return true;
597 }
598 
setStreamWithType(u32 psmfStruct,int type,int channel)599 bool Psmf::setStreamWithType(u32 psmfStruct, int type, int channel) {
600 	for (auto iter : streamMap) {
601 		// Note: this does NOT support PSMF_AUDIO_STREAM.
602 		if (iter.second->type_ == type && iter.second->channel_ == channel) {
603 			return setStreamNum(psmfStruct, iter.first);
604 		}
605 	}
606 	return false;
607 }
608 
setStreamWithTypeNumber(u32 psmfStruct,int type,int n)609 bool Psmf::setStreamWithTypeNumber(u32 psmfStruct, int type, int n) {
610 	for (auto iter : streamMap) {
611 		if (iter.second->matchesType(type)) {
612 			if (n != 0) {
613 				// Keep counting...
614 				n--;
615 				continue;
616 			}
617 			// Okay, this is the one.
618 			return setStreamNum(psmfStruct, iter.first);
619 		}
620 	}
621 	return false;
622 }
623 
FindEPWithTimestamp(int pts) const624 int Psmf::FindEPWithTimestamp(int pts) const {
625 	int best = -1;
626 	int bestPts = 0;
627 
628 	for (int i = 0; i < (int)EPMap.size(); ++i) {
629 		const int matchPts = EPMap[i].EPPts;
630 		if (matchPts == pts) {
631 			// Exact match, take it.
632 			return i;
633 		}
634 		// TODO: Does it actually do fuzzy matching?
635 		if (matchPts < pts && matchPts >= bestPts) {
636 			best = i;
637 			bestPts = matchPts;
638 		}
639 	}
640 
641 	return best;
642 }
643 
644 
645 static std::map<u32, Psmf *> psmfMap;
646 static std::map<u32, PsmfPlayer *> psmfPlayerMap;
647 
getPsmf(u32 psmf)648 static Psmf *getPsmf(u32 psmf) {
649 	auto psmfstruct = PSPPointer<PsmfData>::Create(psmf);
650 	if (!psmfstruct.IsValid())
651 		return nullptr;
652 
653 	auto iter = psmfMap.find(psmfstruct->headerOffset);
654 	if (iter != psmfMap.end()) {
655 		// TODO: Migrate to only using PSP RAM.
656 		// Each instance can have its own selected stream.  This is important.
657 		iter->second->currentStreamNum = psmfstruct->streamNum;
658 		return iter->second;
659 	} else {
660 		return nullptr;
661 	}
662 }
663 
getPsmfPlayer(u32 psmfplayer)664 static PsmfPlayer *getPsmfPlayer(u32 psmfplayer)
665 {
666 	auto iter = psmfPlayerMap.find(Memory::Read_U32(psmfplayer));
667 	if (iter != psmfPlayerMap.end())
668 		return iter->second;
669 	else
670 		return 0;
671 }
672 
__PsmfPlayerStatusChange(u64 userdata,int cyclesLate)673 static void __PsmfPlayerStatusChange(u64 userdata, int cyclesLate) {
674 	PsmfPlayerStatus status = PsmfPlayerStatus(userdata & 0xFFFFFFFF);
675 	u32 psmfPlayer = userdata >> 32;
676 	PsmfPlayer *player = getPsmfPlayer(psmfPlayer);
677 	if (player) {
678 		player->status = status;
679 	}
680 }
681 
__PsmfInit()682 void __PsmfInit() {
683 	videoPixelMode = GE_CMODE_32BIT_ABGR8888;
684 	videoLoopStatus = PSMF_PLAYER_CONFIG_NO_LOOP;
685 	psmfPlayerLibVersion = 0;
686 	eventPsmfPlayerStatusChange = CoreTiming::RegisterEvent("PsmfPlayerStatusChange", &__PsmfPlayerStatusChange);
687 }
688 
__PsmfPlayerLoadModule(int devkitVersion)689 void __PsmfPlayerLoadModule(int devkitVersion) {
690 	psmfPlayerLibVersion = devkitVersion;
691 }
692 
__PsmfDoState(PointerWrap & p)693 void __PsmfDoState(PointerWrap &p) {
694 	auto s = p.Section("scePsmf", 1);
695 	if (!s)
696 		return;
697 
698 	Do(p, psmfMap);
699 }
700 
__PsmfPlayerDoState(PointerWrap & p)701 void __PsmfPlayerDoState(PointerWrap &p) {
702 	auto s = p.Section("scePsmfPlayer", 1, 3);
703 	if (!s)
704 		return;
705 
706 	Do(p, psmfPlayerMap);
707 	Do(p, videoPixelMode);
708 	Do(p, videoLoopStatus);
709 	if (s < 3) {
710 		eventPsmfPlayerStatusChange = -1;
711 	} else {
712 		Do(p, eventPsmfPlayerStatusChange);
713 	}
714 	CoreTiming::RestoreRegisterEvent(eventPsmfPlayerStatusChange, "PsmfPlayerStatusChangeEvent", &__PsmfPlayerStatusChange);
715 	if (s < 2) {
716 		// Assume the latest, which is what we were emulating before.
717 		psmfPlayerLibVersion = 0x06060010;
718 	} else {
719 		Do(p, psmfPlayerLibVersion);
720 	}
721 }
722 
__PsmfShutdown()723 void __PsmfShutdown() {
724 	for (auto it = psmfMap.begin(), end = psmfMap.end(); it != end; ++it)
725 		delete it->second;
726 	for (auto it = psmfPlayerMap.begin(), end = psmfPlayerMap.end(); it != end; ++it)
727 		delete it->second;
728 	psmfMap.clear();
729 	psmfPlayerMap.clear();
730 }
731 
DelayPsmfStateChange(u32 psmfPlayer,u32 newState,s64 delayUs)732 static void DelayPsmfStateChange(u32 psmfPlayer, u32 newState, s64 delayUs) {
733 	CoreTiming::ScheduleEvent(usToCycles(delayUs), eventPsmfPlayerStatusChange, (u64)psmfPlayer << 32 | newState);
734 }
735 
scePsmfSetPsmf(u32 psmfStruct,u32 psmfData)736 static u32 scePsmfSetPsmf(u32 psmfStruct, u32 psmfData) {
737 	if (!Memory::IsValidAddress(psmfData) || !Memory::IsValidAddress(psmfData)) {
738 		// Crashes on a PSP.
739 		return hleReportError(ME, SCE_KERNEL_ERROR_ILLEGAL_ADDRESS, "bad address");
740 	}
741 
742 	Psmf *psmf = new Psmf(Memory::GetPointer(psmfData), psmfData);
743 	if (psmf->magic != PSMF_MAGIC) {
744 		delete psmf;
745 		return hleLogError(ME, ERROR_PSMF_INVALID_PSMF, "invalid psmf data");
746 	}
747 	// Note: devkit 00000000 supports only '0012'(0F), '0013'(1F), and '0014'(2F).  03000310+ supports '0015'(3F.)
748 	if (psmf->version == 0) {
749 		delete psmf;
750 		return hleLogError(ME, ERROR_PSMF_BAD_VERSION, "invalid psmf version");
751 	}
752 	if (psmf->streamOffset == 0) {
753 		delete psmf;
754 		return hleLogError(ME, ERROR_PSMF_INVALID_VALUE, "invalid psmf version");
755 	}
756 
757 	// Note: this structure changes between versions.
758 	// TODO: These values are not right, but games probably don't read them.
759 	PsmfData data = {0};
760 	data.version = psmf->version;
761 	data.headerSize = 0x800;
762 	data.streamSize = psmf->streamSize;
763 	// This should be and needs to be the current stream.
764 	data.streamNum = psmf->currentStreamNum;
765 	data.headerOffset = psmf->headerOffset;
766 	Memory::WriteStruct(psmfStruct, &data);
767 
768 	// Because the Psmf struct is sometimes copied, we use a value inside as an id.
769 	auto iter = psmfMap.find(data.headerOffset);
770 	if (iter != psmfMap.end())
771 		delete iter->second;
772 	psmfMap[data.headerOffset] = psmf;
773 
774 	return hleLogSuccessI(ME, 0);
775 }
776 
scePsmfGetNumberOfStreams(u32 psmfStruct)777 static u32 scePsmfGetNumberOfStreams(u32 psmfStruct) {
778 	Psmf *psmf = getPsmf(psmfStruct);
779 	if (!psmf) {
780 		return hleLogError(ME, ERROR_PSMF_NOT_INITIALIZED, "invalid psmf");
781 	}
782 	return hleLogSuccessI(ME, psmf->numStreams);
783 }
784 
scePsmfGetNumberOfSpecificStreams(u32 psmfStruct,int streamType)785 static u32 scePsmfGetNumberOfSpecificStreams(u32 psmfStruct, int streamType) {
786 	Psmf *psmf = getPsmf(psmfStruct);
787 	if (!psmf) {
788 		return hleLogError(ME, ERROR_PSMF_NOT_INITIALIZED, "invalid psmf");
789 	}
790 
791 	int streamNum = 0;
792 	for (auto it : psmf->streamMap) {
793 		if (it.second->matchesType(streamType)) {
794 			streamNum++;
795 		}
796 	}
797 
798 	return hleLogSuccessI(ME, streamNum);
799 }
800 
scePsmfSpecifyStreamWithStreamType(u32 psmfStruct,u32 streamType,u32 channel)801 static u32 scePsmfSpecifyStreamWithStreamType(u32 psmfStruct, u32 streamType, u32 channel) {
802 	Psmf *psmf = getPsmf(psmfStruct);
803 	if (!psmf) {
804 		return hleLogError(ME, ERROR_PSMF_NOT_INITIALIZED, "invalid psmf");
805 	}
806 	if (!psmf->setStreamWithType(psmfStruct, streamType, channel)) {
807 		// An invalid type seems to make the stream number invalid, but retain the old type/channel.
808 		psmf->setStreamNum(psmfStruct, ERROR_PSMF_INVALID_ID, false);
809 		// Also, returns 0 even when no stream found.
810 		return hleLogWarning(ME, 0, "no stream found");
811 	}
812 	return hleLogSuccessI(ME, 0);
813 }
814 
scePsmfSpecifyStreamWithStreamTypeNumber(u32 psmfStruct,u32 streamType,u32 typeNum)815 static u32 scePsmfSpecifyStreamWithStreamTypeNumber(u32 psmfStruct, u32 streamType, u32 typeNum) {
816 	Psmf *psmf = getPsmf(psmfStruct);
817 	if (!psmf) {
818 		return hleLogError(ME, ERROR_PSMF_NOT_INITIALIZED, "invalid psmf");
819 	}
820 	if (!psmf->setStreamWithTypeNumber(psmfStruct, streamType, typeNum)) {
821 		// Don't update stream, just bail out.
822 		return hleLogWarning(ME, ERROR_PSMF_INVALID_ID, "no stream found");
823 	}
824 	return hleLogSuccessI(ME, 0);
825 }
826 
scePsmfSpecifyStream(u32 psmfStruct,int streamNum)827 static u32 scePsmfSpecifyStream(u32 psmfStruct, int streamNum) {
828 	Psmf *psmf = getPsmf(psmfStruct);
829 	if (!psmf) {
830 		return hleLogError(ME, ERROR_PSMF_NOT_INITIALIZED, "invalid psmf");
831 	}
832 	if (!psmf->setStreamNum(psmfStruct, streamNum)) {
833 		psmf->setStreamNum(psmfStruct, ERROR_PSMF_NOT_INITIALIZED);
834 		return hleLogWarning(ME, ERROR_PSMF_INVALID_ID, "bad stream id");
835 	}
836 	return hleLogSuccessI(ME, 0);
837 }
838 
scePsmfGetVideoInfo(u32 psmfStruct,u32 videoInfoAddr)839 static u32 scePsmfGetVideoInfo(u32 psmfStruct, u32 videoInfoAddr) {
840 	Psmf *psmf = getPsmf(psmfStruct);
841 	if (!psmf) {
842 		return hleLogError(ME, ERROR_PSMF_NOT_INITIALIZED, "invalid psmf");
843 	} else if (!psmf->isValidCurrentStreamNumber()) {
844 		return hleLogError(ME, ERROR_PSMF_NOT_INITIALIZED, "invalid stream selected");
845 	} else if (!Memory::IsValidRange(videoInfoAddr, 8)) {
846 		// Would crash.
847 		return hleLogError(ME, SCE_KERNEL_ERROR_ILLEGAL_ADDRESS, "bad address");
848 	}
849 
850 	auto info = psmf->streamMap[psmf->currentStreamNum];
851 	if (info->videoWidth_ == PsmfStream::INVALID) {
852 		return hleLogError(ME, ERROR_PSMF_INVALID_ID, "not a video stream");
853 	}
854 	Memory::Write_U32(info->videoWidth_ == PsmfStream::USE_PSMF ? psmf->videoWidth : info->videoWidth_, videoInfoAddr);
855 	Memory::Write_U32(info->videoHeight_ == PsmfStream::USE_PSMF ? psmf->videoHeight : info->videoHeight_, videoInfoAddr + 4);
856 	return hleLogSuccessI(ME, 0);
857 }
858 
scePsmfGetAudioInfo(u32 psmfStruct,u32 audioInfoAddr)859 static u32 scePsmfGetAudioInfo(u32 psmfStruct, u32 audioInfoAddr) {
860 	Psmf *psmf = getPsmf(psmfStruct);
861 	if (!psmf) {
862 		return hleLogError(ME, ERROR_PSMF_NOT_INITIALIZED, "invalid psmf");
863 	} else if (!psmf->isValidCurrentStreamNumber()) {
864 		return hleLogError(ME, ERROR_PSMF_NOT_INITIALIZED, "invalid stream selected");
865 	} else if (!Memory::IsValidRange(audioInfoAddr, 8)) {
866 		// Would crash.
867 		return hleLogError(ME, SCE_KERNEL_ERROR_ILLEGAL_ADDRESS, "bad address");
868 	}
869 
870 	auto info = psmf->streamMap[psmf->currentStreamNum];
871 	if (info->audioChannels_ == PsmfStream::INVALID) {
872 		return hleLogError(ME, ERROR_PSMF_INVALID_ID, "not an audio stream");
873 	}
874 	Memory::Write_U32(info->audioChannels_ == PsmfStream::USE_PSMF ? psmf->audioChannels : info->audioChannels_, audioInfoAddr);
875 	Memory::Write_U32(info->audioFrequency_ == PsmfStream::USE_PSMF ? psmf->audioFrequency : info->audioFrequency_, audioInfoAddr + 4);
876 	return hleLogSuccessI(ME, 0);
877 }
878 
scePsmfGetCurrentStreamType(u32 psmfStruct,u32 typeAddr,u32 channelAddr)879 static u32 scePsmfGetCurrentStreamType(u32 psmfStruct, u32 typeAddr, u32 channelAddr) {
880 	Psmf *psmf = getPsmf(psmfStruct);
881 	if (!psmf) {
882 		return hleLogError(ME, ERROR_PSMF_NOT_INITIALIZED, "invalid psmf");
883 	}
884 	if (psmf->currentStreamNum == (int)ERROR_PSMF_NOT_INITIALIZED) {
885 		return hleLogError(ME, ERROR_PSMF_NOT_INITIALIZED, "no stream set");
886 	}
887 	if (!Memory::IsValidAddress(typeAddr) || !Memory::IsValidAddress(channelAddr)) {
888 		return hleLogError(ME, SCE_KERNEL_ERROR_ILLEGAL_ADDRESS, "bad pointers");
889 	}
890 	if (psmf->currentStreamType != -1) {
891 		Memory::Write_U32(psmf->currentStreamType, typeAddr);
892 		Memory::Write_U32(psmf->currentStreamChannel, channelAddr);
893 	}
894 	return hleLogSuccessI(ME, 0);
895 }
896 
scePsmfGetStreamSize(u32 psmfStruct,u32 sizeAddr)897 static u32 scePsmfGetStreamSize(u32 psmfStruct, u32 sizeAddr)
898 {
899 	Psmf *psmf = getPsmf(psmfStruct);
900 	if (!psmf) {
901 		ERROR_LOG(ME, "scePsmfGetStreamSize(%08x, %08x): invalid psmf", psmfStruct, sizeAddr);
902 		return ERROR_PSMF_NOT_FOUND;
903 	}
904 	DEBUG_LOG(ME, "scePsmfGetStreamSize(%08x, %08x)", psmfStruct, sizeAddr);
905 	if (Memory::IsValidAddress(sizeAddr)) {
906 		Memory::Write_U32(psmf->streamSize, sizeAddr);
907 	}
908 	return 0;
909 }
910 
scePsmfQueryStreamOffset(u32 bufferAddr,u32 offsetAddr)911 static u32 scePsmfQueryStreamOffset(u32 bufferAddr, u32 offsetAddr)
912 {
913 	WARN_LOG(ME, "scePsmfQueryStreamOffset(%08x, %08x)", bufferAddr, offsetAddr);
914 	if (Memory::IsValidAddress(offsetAddr)) {
915 		Memory::Write_U32(bswap32(Memory::Read_U32(bufferAddr + PSMF_STREAM_OFFSET_OFFSET)), offsetAddr);
916 	}
917 	return 0;
918 }
919 
scePsmfQueryStreamSize(u32 bufferAddr,u32 sizeAddr)920 static u32 scePsmfQueryStreamSize(u32 bufferAddr, u32 sizeAddr)
921 {
922 	WARN_LOG(ME, "scePsmfQueryStreamSize(%08x, %08x)", bufferAddr, sizeAddr);
923 	if (Memory::IsValidAddress(sizeAddr)) {
924 		Memory::Write_U32(bswap32(Memory::Read_U32(bufferAddr + PSMF_STREAM_SIZE_OFFSET)), sizeAddr);
925 	}
926 	return 0;
927 }
928 
scePsmfGetHeaderSize(u32 psmfStruct,u32 sizeAddr)929 static u32 scePsmfGetHeaderSize(u32 psmfStruct, u32 sizeAddr)
930 {
931 	Psmf *psmf = getPsmf(psmfStruct);
932 	if (!psmf) {
933 		ERROR_LOG(ME, "scePsmfGetHeaderSize(%08x, %08x): invalid psmf", psmfStruct, sizeAddr);
934 		return ERROR_PSMF_NOT_FOUND;
935 	}
936 	DEBUG_LOG(ME, "scePsmfGetHeaderSize(%08x, %08x)", psmfStruct, sizeAddr);
937 	if (Memory::IsValidAddress(sizeAddr)) {
938 		Memory::Write_U32(psmf->headerSize, sizeAddr);
939 	}
940 	return 0;
941 }
942 
scePsmfGetPsmfVersion(u32 psmfStruct)943 static u32 scePsmfGetPsmfVersion(u32 psmfStruct)
944 {
945 	Psmf *psmf = getPsmf(psmfStruct);
946 	if (!psmf) {
947 		ERROR_LOG(ME, "scePsmfGetPsmfVersion(%08x): invalid psmf", psmfStruct);
948 		return ERROR_PSMF_NOT_FOUND;
949 	}
950 	DEBUG_LOG(ME, "scePsmfGetPsmfVersion(%08x)", psmfStruct);
951 	return psmf->version;
952 }
953 
scePsmfVerifyPsmf(u32 psmfAddr)954 static u32 scePsmfVerifyPsmf(u32 psmfAddr)
955 {
956 	u32 magic = Memory::Read_U32(psmfAddr);
957 	if (magic != PSMF_MAGIC) {
958 		ERROR_LOG(ME, "scePsmfVerifyPsmf(%08x): bad magic %08x", psmfAddr, magic);
959 		return ERROR_PSMF_NOT_FOUND;
960 	}
961 	int version = Memory::Read_U32(psmfAddr + PSMF_STREAM_VERSION_OFFSET);
962 	if (version < 0) {
963 		ERROR_LOG(ME, "scePsmfVerifyPsmf(%08x): bad version %08x", psmfAddr, version);
964 		return ERROR_PSMF_NOT_FOUND;
965 	}
966 	// Kurohyou 2 (at least the demo) uses an uninitialized value that happens to be zero on the PSP.
967 	// It appears to be written by scePsmfVerifyPsmf(), so we write some bytes into the stack here.
968 	Memory::Memset(currentMIPS->r[MIPS_REG_SP] - 0x20, 0, 0x20, "PsmfStack");
969 	DEBUG_LOG(ME, "scePsmfVerifyPsmf(%08x)", psmfAddr);
970 	return 0;
971 }
972 
scePsmfGetNumberOfEPentries(u32 psmfStruct)973 static u32 scePsmfGetNumberOfEPentries(u32 psmfStruct)
974 {
975 	Psmf *psmf = getPsmf(psmfStruct);
976 	if (!psmf) {
977 		ERROR_LOG(ME, "scePsmfGetNumberOfEPentries(%08x): invalid psmf", psmfStruct);
978 		return ERROR_PSMF_NOT_FOUND;
979 	}
980 	DEBUG_LOG(ME, "scePsmfGetNumberOfEPentries(%08x)", psmfStruct);
981 	return psmf->EPMapEntriesNum;
982 }
983 
scePsmfGetPresentationStartTime(u32 psmfStruct,u32 startTimeAddr)984 static u32 scePsmfGetPresentationStartTime(u32 psmfStruct, u32 startTimeAddr)
985 {
986 	Psmf *psmf = getPsmf(psmfStruct);
987 	if (!psmf) {
988 		ERROR_LOG(ME, "scePsmfGetPresentationStartTime(%08x, %08x): invalid psmf", psmfStruct, startTimeAddr);
989 		return ERROR_PSMF_NOT_FOUND;
990 	}
991 	DEBUG_LOG(ME, "scePsmfGetPresentationStartTime(%08x, %08x)", psmfStruct, startTimeAddr);
992 	if (Memory::IsValidAddress(startTimeAddr)) {
993 		Memory::Write_U32(psmf->presentationStartTime, startTimeAddr);
994 	}
995 	return 0;
996 }
997 
scePsmfGetPresentationEndTime(u32 psmfStruct,u32 endTimeAddr)998 static u32 scePsmfGetPresentationEndTime(u32 psmfStruct, u32 endTimeAddr)
999 {
1000 	Psmf *psmf = getPsmf(psmfStruct);
1001 	if (!psmf) {
1002 		ERROR_LOG(ME, "scePsmfGetPresentationEndTime(%08x, %08x): invalid psmf", psmfStruct, endTimeAddr);
1003 		return ERROR_PSMF_NOT_FOUND;
1004 	}
1005 	DEBUG_LOG(ME, "scePsmfGetPresentationEndTime(%08x, %08x)", psmfStruct, endTimeAddr);
1006 	if (Memory::IsValidAddress(endTimeAddr)) {
1007 		Memory::Write_U32(psmf->presentationEndTime, endTimeAddr);
1008 	}
1009 	return 0;
1010 }
1011 
scePsmfGetCurrentStreamNumber(u32 psmfStruct)1012 static u32 scePsmfGetCurrentStreamNumber(u32 psmfStruct) {
1013 	Psmf *psmf = getPsmf(psmfStruct);
1014 	if (!psmf) {
1015 		return hleLogError(ME, ERROR_PSMF_NOT_INITIALIZED, "invalid psmf");
1016 	}
1017 	if (psmf->currentStreamNum < 0) {
1018 		return hleLogError(ME, psmf->currentStreamNum, "invalid stream");
1019 	}
1020 	return hleLogSuccessI(ME, psmf->currentStreamNum);
1021 }
1022 
scePsmfCheckEPMap(u32 psmfStruct)1023 static u32 scePsmfCheckEPMap(u32 psmfStruct)
1024 {
1025 	Psmf *psmf = getPsmf(psmfStruct);
1026 	if (!psmf) {
1027 		ERROR_LOG(ME, "scePsmfCheckEPMap(%08x): invalid psmf", psmfStruct);
1028 		return ERROR_PSMF_NOT_FOUND;
1029 	}
1030 
1031 	DEBUG_LOG(ME, "scePsmfCheckEPMap(%08x)", psmfStruct);
1032 	return psmf->EPMap.empty() ? ERROR_PSMF_NOT_FOUND : 0;
1033 }
1034 
scePsmfGetEPWithId(u32 psmfStruct,int epid,u32 entryAddr)1035 static u32 scePsmfGetEPWithId(u32 psmfStruct, int epid, u32 entryAddr)
1036 {
1037 	Psmf *psmf = getPsmf(psmfStruct);
1038 	if (!psmf) {
1039 		ERROR_LOG(ME, "scePsmfGetEPWithId(%08x, %i, %08x): invalid psmf", psmfStruct, epid, entryAddr);
1040 		return ERROR_PSMF_NOT_INITIALIZED;
1041 	}
1042 	DEBUG_LOG(ME, "scePsmfGetEPWithId(%08x, %i, %08x)", psmfStruct, epid, entryAddr);
1043 
1044 	if (epid < 0 || epid >= (int)psmf->EPMap.size()) {
1045 		ERROR_LOG(ME, "scePsmfGetEPWithId(%08x, %i): invalid id", psmfStruct, epid);
1046 		return ERROR_PSMF_NOT_FOUND;
1047 	}
1048 	if (Memory::IsValidAddress(entryAddr)) {
1049 		Memory::WriteStruct(entryAddr, &psmf->EPMap[epid]);
1050 	}
1051 	return 0;
1052 }
1053 
scePsmfGetEPWithTimestamp(u32 psmfStruct,u32 ts,u32 entryAddr)1054 static u32 scePsmfGetEPWithTimestamp(u32 psmfStruct, u32 ts, u32 entryAddr)
1055 {
1056 	Psmf *psmf = getPsmf(psmfStruct);
1057 	if (!psmf) {
1058 		ERROR_LOG(ME, "scePsmfGetEPWithTimestamp(%08x, %i, %08x): invalid psmf", psmfStruct, ts, entryAddr);
1059 		return ERROR_PSMF_NOT_INITIALIZED;
1060 	}
1061 	DEBUG_LOG(ME, "scePsmfGetEPWithTimestamp(%08x, %i, %08x)", psmfStruct, ts, entryAddr);
1062 
1063 	if (ts < psmf->presentationStartTime) {
1064 		ERROR_LOG(ME, "scePsmfGetEPWithTimestamp(%08x, %i): invalid timestamp", psmfStruct, ts);
1065 		return ERROR_PSMF_NOT_FOUND;
1066 	}
1067 
1068 	int epid = psmf->FindEPWithTimestamp(ts);
1069 	if (epid < 0 || epid >= (int)psmf->EPMap.size()) {
1070 		ERROR_LOG(ME, "scePsmfGetEPWithTimestamp(%08x, %i): invalid id", psmfStruct, epid);
1071 		return ERROR_PSMF_NOT_FOUND;
1072 	}
1073 
1074 	if (Memory::IsValidAddress(entryAddr)) {
1075 		Memory::WriteStruct(entryAddr, &psmf->EPMap[epid]);
1076 	}
1077 	return 0;
1078 }
1079 
scePsmfGetEPidWithTimestamp(u32 psmfStruct,u32 ts)1080 static u32 scePsmfGetEPidWithTimestamp(u32 psmfStruct, u32 ts)
1081 {
1082 	Psmf *psmf = getPsmf(psmfStruct);
1083 	if (!psmf) {
1084 		ERROR_LOG(ME, "scePsmfGetEPidWithTimestamp(%08x, %i): invalid psmf", psmfStruct, ts);
1085 		return ERROR_PSMF_NOT_FOUND;
1086 	}
1087 	DEBUG_LOG(ME, "scePsmfGetEPidWithTimestamp(%08x, %i)", psmfStruct, ts);
1088 
1089 	if (psmf->EPMap.empty()) {
1090 		ERROR_LOG(ME, "scePsmfGetEPidWithTimestamp(%08x): EPMap is empty", psmfStruct);
1091 		return ERROR_PSMF_NOT_FOUND;
1092 	}
1093 
1094 	if (ts < psmf->presentationStartTime) {
1095 		ERROR_LOG(ME, "scePsmfGetEPidWithTimestamp(%08x, %i): invalid timestamp", psmfStruct, ts);
1096 		return ERROR_PSMF_INVALID_TIMESTAMP;
1097 	}
1098 
1099 	int epid = psmf->FindEPWithTimestamp(ts);
1100 	if (epid < 0 || epid >= (int)psmf->EPMap.size()) {
1101 		ERROR_LOG(ME, "scePsmfGetEPidWithTimestamp(%08x, %i): invalid id", psmfStruct, epid);
1102 		return ERROR_PSMF_INVALID_ID;
1103 	}
1104 
1105 	return epid;
1106 }
1107 
scePsmfPlayerCreate(u32 psmfPlayer,u32 dataPtr)1108 static int scePsmfPlayerCreate(u32 psmfPlayer, u32 dataPtr) {
1109 	auto player = PSPPointer<u32_le>::Create(psmfPlayer);
1110 	const auto data = PSPPointer<const PsmfPlayerCreateData>::Create(dataPtr);
1111 
1112 	if (!player.IsValid() || !data.IsValid()) {
1113 		// Crashes on a PSP.
1114 		return hleReportError(ME, SCE_KERNEL_ERROR_ILLEGAL_ADDRESS, "bad pointers");
1115 	}
1116 	if (!data->buffer.IsValid()) {
1117 		// Also crashes on a PSP.
1118 		*player = 0;
1119 		return hleReportError(ME, SCE_KERNEL_ERROR_ILLEGAL_ADDRESS, "invalid buffer address %08x", data->buffer.ptr);
1120 	}
1121 	if (data->bufferSize < 0x00285800) {
1122 		*player = 0;
1123 		return hleReportError(ME, ERROR_PSMFPLAYER_BUFFER_SIZE, "buffer too small %08x", data->bufferSize);
1124 	}
1125 	if (data->threadPriority < 0x10 || data->threadPriority >= 0x6E) {
1126 		*player = 0;
1127 		return hleReportError(ME, ERROR_PSMFPLAYER_INVALID_PARAM, "bad thread priority %02x", data->threadPriority);
1128 	}
1129 	if (!psmfPlayerMap.empty()) {
1130 		*player = 0;
1131 		return hleReportError(ME, ERROR_MPEG_ALREADY_INIT, "already have an active player");
1132 	}
1133 
1134 	PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer);
1135 	if (!psmfplayer) {
1136 		psmfplayer = new PsmfPlayer(data);
1137 		if (psmfPlayerMap.find(psmfPlayer) != psmfPlayerMap.end())
1138 			delete psmfPlayerMap[psmfPlayer];
1139 		psmfPlayerMap[psmfPlayer] = psmfplayer;
1140 
1141 		// Write something there to identify it with.
1142 		*player = psmfPlayer;
1143 	}
1144 
1145 	// These really shouldn't be globals.  But, you can only have one psmfplayer anyway.
1146 	videoPixelMode = GE_CMODE_32BIT_ABGR8888;
1147 	videoLoopStatus = PSMF_PLAYER_CONFIG_NO_LOOP;
1148 
1149 	int delayUs = 20000;
1150 	DelayPsmfStateChange(psmfPlayer, PSMF_PLAYER_STATUS_INIT, delayUs);
1151 	return hleLogSuccessInfoI(ME, hleDelayResult(0, "player create", delayUs));
1152 }
1153 
scePsmfPlayerStop(u32 psmfPlayer)1154 static int scePsmfPlayerStop(u32 psmfPlayer) {
1155 	PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer);
1156 	if (!psmfplayer) {
1157 		return hleLogError(ME, ERROR_PSMFPLAYER_INVALID_STATUS, "invalid psmf player");
1158 	}
1159 	if (psmfplayer->status < PSMF_PLAYER_STATUS_PLAYING) {
1160 		return hleLogError(ME, ERROR_PSMFPLAYER_INVALID_STATUS, "not yet playing");
1161 	}
1162 	psmfplayer->AbortFinish();
1163 
1164 	int delayUs = 3000;
1165 	DelayPsmfStateChange(psmfPlayer, PSMF_PLAYER_STATUS_STANDBY, delayUs);
1166 	return hleLogSuccessInfoI(ME, hleDelayResult(0, "psmfplayer stop", delayUs));
1167 }
1168 
scePsmfPlayerBreak(u32 psmfPlayer)1169 static int scePsmfPlayerBreak(u32 psmfPlayer) {
1170 	PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer);
1171 	if (!psmfplayer) {
1172 		return hleLogError(ME, ERROR_PSMFPLAYER_INVALID_STATUS, "invalid psmf player", psmfPlayer);
1173 	}
1174 
1175 	psmfplayer->AbortFinish();
1176 
1177 	return hleLogWarning(ME, 0);
1178 }
1179 
_PsmfPlayerFillRingbuffer(PsmfPlayer * psmfplayer)1180 static int _PsmfPlayerFillRingbuffer(PsmfPlayer *psmfplayer) {
1181 	if (psmfplayer->filehandle <= 0)
1182 		return -1;
1183 	u8* buf = psmfplayer->tempbuf;
1184 	int tempbufSize = (int)sizeof(psmfplayer->tempbuf);
1185 	int size;
1186 	// Let's not burn a bunch of time adding data all at once.
1187 	int addMax = std::max(2048 * 100, tempbufSize);
1188 	do {
1189 		size = std::min(psmfplayer->mediaengine->getRemainSize(), tempbufSize);
1190 		size = std::min(psmfplayer->mediaengine->getAudioRemainSize(), size);
1191 		size = std::min(psmfplayer->streamSize - psmfplayer->readSize, size);
1192 		if (size <= 0)
1193 			break;
1194 		size = (int)pspFileSystem.ReadFile(psmfplayer->filehandle, buf, size);
1195 		psmfplayer->readSize += size;
1196 		psmfplayer->mediaengine->addStreamData(buf, size);
1197 		addMax -= size;
1198 		if (addMax <= 0)
1199 			break;
1200 	} while (size > 0);
1201 
1202 	if (psmfplayer->readSize >= psmfplayer->streamSize && videoLoopStatus == PSMF_PLAYER_CONFIG_LOOP) {
1203 		// Start looping, but only if we've finished.
1204 		if (psmfplayer->HasReachedEnd()) {
1205 			psmfplayer->readSize = 0;
1206 			pspFileSystem.SeekFile(psmfplayer->filehandle, psmfplayer->fileoffset, FILEMOVE_BEGIN);
1207 			psmfplayer->mediaengine->reloadStream();
1208 		}
1209 	}
1210 	return 0;
1211 }
1212 
_PsmfPlayerSetPsmfOffset(u32 psmfPlayer,const char * filename,int offset,bool docallback)1213 static int _PsmfPlayerSetPsmfOffset(u32 psmfPlayer, const char *filename, int offset, bool docallback) {
1214 	PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer);
1215 	if (!psmfplayer || psmfplayer->status != PSMF_PLAYER_STATUS_INIT) {
1216 		return hleReportError(ME, ERROR_PSMFPLAYER_INVALID_STATUS, "invalid psmf player or status");
1217 	}
1218 	if (!filename) {
1219 		return hleLogError(ME, ERROR_PSMFPLAYER_INVALID_PARAM, "invalid filename");
1220 	}
1221 
1222 	int delayUs = 1100;
1223 
1224 	psmfplayer->filehandle = pspFileSystem.OpenFile(filename, (FileAccess) FILEACCESS_READ);
1225 	if (psmfplayer->filehandle < 0) {
1226 		return hleLogError(ME, hleDelayResult(SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT, "psmfplayer set", delayUs), "invalid file data or does not exist");
1227 	}
1228 
1229 	if (offset != 0)
1230 		pspFileSystem.SeekFile(psmfplayer->filehandle, offset, FILEMOVE_BEGIN);
1231 	u8 *buf = psmfplayer->tempbuf;
1232 	int tempbufSize = (int)sizeof(psmfplayer->tempbuf);
1233 	int size = (int)pspFileSystem.ReadFile(psmfplayer->filehandle, buf, 2048);
1234 	delayUs += 2000;
1235 
1236 	const u32 magic = *(u32_le *)buf;
1237 	if (magic != PSMF_MAGIC) {
1238 		// TODO: Let's keep trying as we were before.
1239 		ERROR_LOG_REPORT(ME, "scePsmfPlayerSetPsmf*: incorrect PSMF magic (%08x), bad data", magic);
1240 		//return hleReportError(ME, SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT, "incorrect PSMF magic (%08x), bad data", magic);
1241 	}
1242 
1243 	// TODO: Merge better with Psmf.
1244 	u16 numStreams = *(u16_be *)(buf + 0x80);
1245 	if (numStreams > 128) {
1246 		return hleReportError(ME, hleDelayResult(SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT, "psmfplayer set", delayUs), "too many streams in PSMF video, bogus data");
1247 	}
1248 
1249 	psmfplayer->totalVideoStreams = 0;
1250 	psmfplayer->totalAudioStreams = 0;
1251 	psmfplayer->videoWidth = buf[142] * 16;
1252 	psmfplayer->videoHeight = buf[143] * 16;
1253 
1254 	psmfplayer->playerVersion = PSMF_PLAYER_VERSION_FULL;
1255 	for (u16 i = 0; i < numStreams; i++) {
1256 		const u8 *currentStreamAddr = buf + 0x82 + i * 16;
1257 		const int streamId = *currentStreamAddr;
1258 		if ((streamId & PSMF_VIDEO_STREAM_ID) == PSMF_VIDEO_STREAM_ID) {
1259 			++psmfplayer->totalVideoStreams;
1260 			// If we don't have EP info for /any/ video stream, revert to BASIC.
1261 			const u32 epOffset = ReadUnalignedU32BE(currentStreamAddr + 4);
1262 			const u32 epEntries = ReadUnalignedU32BE(currentStreamAddr + 8);
1263 			// TODO: Actually, if these don't match, it seems to be an invalid PSMF.
1264 			if (epOffset == 0 || epEntries == 0) {
1265 				psmfplayer->playerVersion = PSMF_PLAYER_VERSION_BASIC;
1266 			}
1267 		} else if ((streamId & PSMF_AUDIO_STREAM_ID) == PSMF_AUDIO_STREAM_ID) {
1268 			++psmfplayer->totalAudioStreams;
1269 		} else {
1270 			WARN_LOG_REPORT(ME, "scePsmfPlayerSetPsmf*: unexpected streamID %x", streamId);
1271 		}
1272 	}
1273 	// TODO: It seems like it's invalid if there's not at least 1 video stream.
1274 
1275 	int mpegoffset = *(s32_be *)(buf + PSMF_STREAM_OFFSET_OFFSET);
1276 	psmfplayer->readSize = size - mpegoffset;
1277 	if (psmfPlayerLibVersion >= 0x05050010) {
1278 		psmfplayer->streamSize = *(s32_be *)(buf + PSMF_STREAM_SIZE_OFFSET);
1279 	} else {
1280 		// Older versions just read until the end of the file.
1281 		PSPFileInfo info = pspFileSystem.GetFileInfo(filename);
1282 		psmfplayer->streamSize = info.size - offset - mpegoffset;
1283 	}
1284 	psmfplayer->fileoffset = offset + mpegoffset;
1285 	psmfplayer->mediaengine->loadStream(buf, 2048, std::max(2048 * 500, tempbufSize));
1286 	_PsmfPlayerFillRingbuffer(psmfplayer);
1287 	psmfplayer->totalDurationTimestamp = psmfplayer->mediaengine->getLastTimeStamp();
1288 
1289 	DelayPsmfStateChange(psmfPlayer, PSMF_PLAYER_STATUS_STANDBY, delayUs);
1290 	return hleLogSuccessInfoI(ME, hleDelayResult(0, "psmfplayer set", delayUs));
1291 }
1292 
scePsmfPlayerSetPsmf(u32 psmfPlayer,const char * filename)1293 static int scePsmfPlayerSetPsmf(u32 psmfPlayer, const char *filename) {
1294 	return _PsmfPlayerSetPsmfOffset(psmfPlayer, filename, 0, false);
1295 }
1296 
scePsmfPlayerSetPsmfCB(u32 psmfPlayer,const char * filename)1297 static int scePsmfPlayerSetPsmfCB(u32 psmfPlayer, const char *filename) {
1298 	// TODO: hleCheckCurrentCallbacks?
1299 	return _PsmfPlayerSetPsmfOffset(psmfPlayer, filename, 0, true);
1300 }
1301 
scePsmfPlayerSetPsmfOffset(u32 psmfPlayer,const char * filename,int offset)1302 static int scePsmfPlayerSetPsmfOffset(u32 psmfPlayer, const char *filename, int offset) {
1303 	return _PsmfPlayerSetPsmfOffset(psmfPlayer, filename, offset, false);
1304 }
1305 
scePsmfPlayerSetPsmfOffsetCB(u32 psmfPlayer,const char * filename,int offset)1306 static int scePsmfPlayerSetPsmfOffsetCB(u32 psmfPlayer, const char *filename, int offset) {
1307 	// TODO: hleCheckCurrentCallbacks?
1308 	return _PsmfPlayerSetPsmfOffset(psmfPlayer, filename, offset, true);
1309 }
1310 
scePsmfPlayerGetAudioOutSize(u32 psmfPlayer)1311 static int scePsmfPlayerGetAudioOutSize(u32 psmfPlayer) {
1312 	PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer);
1313 	if (!psmfplayer) {
1314 		return hleLogError(ME, ERROR_PSMFPLAYER_INVALID_STATUS, "invalid psmf player");
1315 	}
1316 	return hleLogWarning(ME, audioSamplesBytes);
1317 }
1318 
__PsmfPlayerContinueSeek(PsmfPlayer * psmfplayer,int tries=50)1319 static bool __PsmfPlayerContinueSeek(PsmfPlayer *psmfplayer, int tries = 50) {
1320 	if (psmfplayer->seekDestTimeStamp <= 0) {
1321 		return true;
1322 	}
1323 
1324 	while (!psmfplayer->mediaengine->seekTo(psmfplayer->seekDestTimeStamp, videoPixelMode)) {
1325 		if (--tries <= 0) {
1326 			return false;
1327 		}
1328 		_PsmfPlayerFillRingbuffer(psmfplayer);
1329 		if (psmfplayer->mediaengine->IsVideoEnd()) {
1330 			break;
1331 		}
1332 	}
1333 
1334 	// Seek is done, so forget about it.
1335 	psmfplayer->seekDestTimeStamp = 0;
1336 	return true;
1337 }
1338 
scePsmfPlayerStart(u32 psmfPlayer,u32 psmfPlayerData,int initPts)1339 static int scePsmfPlayerStart(u32 psmfPlayer, u32 psmfPlayerData, int initPts)
1340 {
1341 	PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer);
1342 	if (!psmfplayer) {
1343 		ERROR_LOG(ME, "scePsmfPlayerStart(%08x, %08x, %d): invalid psmf player", psmfPlayer, psmfPlayerData, initPts);
1344 		return ERROR_PSMFPLAYER_INVALID_STATUS;
1345 	}
1346 	if (psmfplayer->status == PSMF_PLAYER_STATUS_INIT) {
1347 		ERROR_LOG(ME, "scePsmfPlayerStart(%08x, %08x, %d): psmf not yet set", psmfPlayer, psmfPlayerData, initPts);
1348 		return ERROR_PSMFPLAYER_INVALID_STATUS;
1349 	}
1350 
1351 	auto playerData = PSPPointer<PsmfPlayerData>::Create(psmfPlayerData);
1352 	if (!playerData.IsValid()) {
1353 		// Crashes on a PSP.
1354 		ERROR_LOG(ME, "scePsmfPlayerStart(%08x, %08x, %d): bad data address", psmfPlayer, psmfPlayerData, initPts);
1355 		return SCE_KERNEL_ERROR_ILLEGAL_ADDRESS;
1356 	}
1357 	if (playerData->playMode < 0 || playerData->playMode > (int)PSMF_PLAYER_MODE_REWIND) {
1358 		ERROR_LOG(ME, "scePsmfPlayerStart(%08x, %08x, %d): invalid mode", psmfPlayer, psmfPlayerData, initPts);
1359 		return ERROR_PSMFPLAYER_INVALID_PARAM;
1360 	}
1361 	if (initPts >= psmfplayer->mediaengine->getLastTimeStamp()) {
1362 		ERROR_LOG(ME, "scePsmfPlayerStart(%08x, %08x, %d): pts is outside video", psmfPlayer, psmfPlayerData, initPts);
1363 		return ERROR_PSMFPLAYER_INVALID_PARAM;
1364 	}
1365 
1366 	if (psmfplayer->totalAudioStreams > 0) {
1367 		if (playerData->audioCodec != 0x0F && playerData->audioCodec != 0x01) {
1368 			ERROR_LOG_REPORT(ME, "scePsmfPlayerStart(%08x, %08x, %d): invalid audio codec %02x", psmfPlayer, psmfPlayerData, initPts, playerData->audioCodec);
1369 			return ERROR_PSMFPLAYER_INVALID_STREAM;
1370 		}
1371 		if (playerData->audioStreamNum >= psmfplayer->totalAudioStreams) {
1372 			ERROR_LOG_REPORT(ME, "scePsmfPlayerStart(%08x, %08x, %d): unable to change audio stream to %d", psmfPlayer, psmfPlayerData, initPts, playerData->audioStreamNum);
1373 			return ERROR_PSMFPLAYER_INVALID_CONFIG;
1374 		}
1375 	}
1376 	if (playerData->videoCodec != 0x0E && playerData->videoCodec != 0x00) {
1377 		ERROR_LOG_REPORT(ME, "scePsmfPlayerStart(%08x, %08x, %d): invalid video codec %02x", psmfPlayer, psmfPlayerData, initPts, playerData->videoCodec);
1378 		return ERROR_PSMFPLAYER_INVALID_STREAM;
1379 	}
1380 	if (playerData->videoStreamNum < 0 || playerData->videoStreamNum >= psmfplayer->totalVideoStreams) {
1381 		ERROR_LOG_REPORT(ME, "scePsmfPlayerStart(%08x, %08x, %d): unable to change video stream to %d", psmfPlayer, psmfPlayerData, initPts, playerData->videoStreamNum);
1382 		return ERROR_PSMFPLAYER_INVALID_CONFIG;
1383 	}
1384 
1385 	switch ((PsmfPlayerMode)(s32)playerData->playMode) {
1386 	case PSMF_PLAYER_MODE_FORWARD:
1387 	case PSMF_PLAYER_MODE_REWIND:
1388 		if (psmfplayer->playerVersion == PSMF_PLAYER_VERSION_BASIC) {
1389 			WARN_LOG_REPORT(ME, "scePsmfPlayerStart(%08x, %08x, %d): no EP data for FORWARD/REWIND", psmfPlayer, psmfPlayerData, initPts);
1390 			return ERROR_PSMFPLAYER_INVALID_PARAM;
1391 		}
1392 		WARN_LOG_REPORT(ME, "scePsmfPlayerStart(%08x, %08x, %d): unsupported playMode", psmfPlayer, psmfPlayerData, initPts);
1393 		break;
1394 
1395 	case PSMF_PLAYER_MODE_PLAY:
1396 	case PSMF_PLAYER_MODE_PAUSE:
1397 		break;
1398 
1399 	default:
1400 		WARN_LOG_REPORT(ME, "scePsmfPlayerStart(%08x, %08x, %d): unsupported playMode", psmfPlayer, psmfPlayerData, initPts);
1401 		break;
1402 	}
1403 
1404 	if (psmfplayer->playerVersion == PSMF_PLAYER_VERSION_BASIC && initPts != 0) {
1405 		ERROR_LOG_REPORT(ME, "scePsmfPlayerStart(%08x, %08x, %d): unable to seek without EPmap", psmfPlayer, psmfPlayerData, initPts);
1406 		return ERROR_PSMFPLAYER_INVALID_PARAM;
1407 	}
1408 
1409 	psmfplayer->AbortFinish();
1410 	psmfplayer->mediaengine->setVideoStream(playerData->videoStreamNum);
1411 	psmfplayer->videoCodec = playerData->videoCodec;
1412 	psmfplayer->videoStreamNum = playerData->videoStreamNum;
1413 	if (psmfplayer->totalAudioStreams > 0) {
1414 		psmfplayer->mediaengine->setAudioStream(playerData->audioStreamNum);
1415 		psmfplayer->audioCodec = playerData->audioCodec;
1416 		psmfplayer->audioStreamNum = playerData->audioStreamNum;
1417 	}
1418 	psmfplayer->playMode = playerData->playMode;
1419 	psmfplayer->playSpeed = playerData->playSpeed;
1420 
1421 	WARN_LOG(ME, "scePsmfPlayerStart(%08x, %08x, %d,(mode %d, speed %d)", psmfPlayer, psmfPlayerData, initPts, playerData->playMode, playerData->playSpeed);
1422 
1423 	// Does not alter current pts, it just catches up when Update()/etc. get there.
1424 
1425 	int delayUs = psmfplayer->status == PSMF_PLAYER_STATUS_PLAYING ? 3000 : 0;
1426 	if (delayUs == 0)
1427 		psmfplayer->status = PSMF_PLAYER_STATUS_PLAYING;
1428 	else
1429 		DelayPsmfStateChange(psmfPlayer, PSMF_PLAYER_STATUS_PLAYING, delayUs);
1430 	psmfplayer->warmUp = 0;
1431 
1432 	psmfplayer->mediaengine->openContext();
1433 
1434 	s64 dist = initPts - psmfplayer->mediaengine->getVideoTimeStamp();
1435 	if (dist < 0 || dist > VIDEO_FRAME_DURATION_TS * 60) {
1436 		// When seeking backwards, we just start populating the stream from the start.
1437 		pspFileSystem.SeekFile(psmfplayer->filehandle, 0, FILEMOVE_BEGIN);
1438 
1439 		u8 *buf = psmfplayer->tempbuf;
1440 		int tempbufSize = (int)sizeof(psmfplayer->tempbuf);
1441 		int size = (int)pspFileSystem.ReadFile(psmfplayer->filehandle, buf, tempbufSize);
1442 		psmfplayer->mediaengine->loadStream(buf, size, std::max(2048 * 500, tempbufSize));
1443 
1444 		int mpegoffset = *(s32_be *)(buf + PSMF_STREAM_OFFSET_OFFSET);
1445 		psmfplayer->readSize = size - mpegoffset;
1446 
1447 		Psmf psmf(psmfplayer->tempbuf, 0);
1448 
1449 		int lastOffset = 0;
1450 		for (auto it = psmf.EPMap.begin(), end = psmf.EPMap.end(); it != end; ++it) {
1451 			if (initPts <= it->EPPts - (int)psmf.presentationStartTime) {
1452 				break;
1453 			}
1454 			lastOffset = it->EPOffset;
1455 		}
1456 
1457 		psmfplayer->readSize = lastOffset * 2048;
1458 		pspFileSystem.SeekFile(psmfplayer->filehandle, psmfplayer->fileoffset + psmfplayer->readSize, FILEMOVE_BEGIN);
1459 
1460 		_PsmfPlayerFillRingbuffer(psmfplayer);
1461 	}
1462 
1463 	psmfplayer->seekDestTimeStamp = initPts;
1464 	__PsmfPlayerContinueSeek(psmfplayer);
1465 	return delayUs == 0 ? 0 : hleDelayResult(0, "psmfplayer start", delayUs);
1466 }
1467 
scePsmfPlayerDelete(u32 psmfPlayer)1468 static int scePsmfPlayerDelete(u32 psmfPlayer)
1469 {
1470 	PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer);
1471 	if (!psmfplayer) {
1472 		ERROR_LOG(ME, "scePsmfPlayerDelete(%08x): invalid psmf player", psmfPlayer);
1473 		return ERROR_PSMFPLAYER_INVALID_STATUS;
1474 	}
1475 
1476 	INFO_LOG(ME, "scePsmfPlayerDelete(%08x)", psmfPlayer);
1477 	delete psmfplayer;
1478 	psmfPlayerMap.erase(Memory::Read_U32(psmfPlayer));
1479 	Memory::Write_U32(0, psmfPlayer);
1480 
1481 	return hleDelayResult(0, "psmfplayer deleted", 20000);
1482 }
1483 
scePsmfPlayerUpdate(u32 psmfPlayer)1484 static int scePsmfPlayerUpdate(u32 psmfPlayer)
1485 {
1486 	PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer);
1487 	if (!psmfplayer) {
1488 		ERROR_LOG(ME, "scePsmfPlayerUpdate(%08x): invalid psmf player", psmfPlayer);
1489 		return ERROR_PSMFPLAYER_INVALID_STATUS;
1490 	}
1491 	if (psmfplayer->status < PSMF_PLAYER_STATUS_PLAYING) {
1492 		ERROR_LOG(ME, "scePsmfPlayerUpdate(%08x): not playing yet", psmfPlayer);
1493 		return ERROR_PSMFPLAYER_INVALID_STATUS;
1494 	}
1495 
1496 	DEBUG_LOG(ME, "scePsmfPlayerUpdate(%08x)", psmfPlayer);
1497 	if (psmfplayer->HasReachedEnd()) {
1498 		if (videoLoopStatus == PSMF_PLAYER_CONFIG_NO_LOOP && psmfplayer->videoStep >= 1) {
1499 			if (psmfplayer->status != PSMF_PLAYER_STATUS_PLAYING_FINISHED) {
1500 				psmfplayer->ScheduleFinish(psmfPlayer);
1501 				INFO_LOG(ME, "scePsmfPlayerUpdate(%08x): video end scheduled", psmfPlayer);
1502 			}
1503 		}
1504 	}
1505 	psmfplayer->videoStep++;
1506 
1507 	return 0;
1508 }
1509 
scePsmfPlayerReleasePsmf(u32 psmfPlayer)1510 static int scePsmfPlayerReleasePsmf(u32 psmfPlayer)
1511 {
1512 	PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer);
1513 	if (!psmfplayer) {
1514 		ERROR_LOG(ME, "scePsmfPlayerReleasePsmf(%08x): invalid psmf player", psmfPlayer);
1515 		return ERROR_PSMFPLAYER_INVALID_STATUS;
1516 	}
1517 	if (psmfplayer->status < PSMF_PLAYER_STATUS_STANDBY) {
1518 		ERROR_LOG(ME, "scePsmfPlayerReleasePsmf(%08x): not set yet", psmfPlayer);
1519 		return ERROR_PSMFPLAYER_INVALID_STATUS;
1520 	}
1521 
1522 	WARN_LOG(ME, "scePsmfPlayerReleasePsmf(%08x)", psmfPlayer);
1523 	psmfplayer->status = PSMF_PLAYER_STATUS_INIT;
1524 	return 0;
1525 }
1526 
__PsmfUpdatePts(PsmfPlayer * psmfplayer,PsmfVideoData * videoData)1527 static void __PsmfUpdatePts(PsmfPlayer *psmfplayer, PsmfVideoData *videoData) {
1528 	// getVideoTimestamp() includes the frame duration, remove it for this frame's pts.
1529 	psmfplayer->psmfPlayerAvcAu.pts = psmfplayer->mediaengine->getVideoTimeStamp() - VIDEO_FRAME_DURATION_TS;
1530 	if (videoData) {
1531 		videoData->displaypts = (u32)psmfplayer->psmfPlayerAvcAu.pts;
1532 	}
1533 }
1534 
scePsmfPlayerGetVideoData(u32 psmfPlayer,u32 videoDataAddr)1535 static int scePsmfPlayerGetVideoData(u32 psmfPlayer, u32 videoDataAddr)
1536 {
1537 	PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer);
1538 	if (!psmfplayer) {
1539 		ERROR_LOG(ME, "scePsmfPlayerGetVideoData(%08x, %08x): invalid psmf player", psmfPlayer, videoDataAddr);
1540 		return ERROR_PSMFPLAYER_INVALID_STATUS;
1541 	}
1542 	if (psmfplayer->status < PSMF_PLAYER_STATUS_PLAYING) {
1543 		ERROR_LOG(ME, "scePsmfPlayerGetVideoData(%08x, %08x): psmf not playing", psmfPlayer, videoDataAddr);
1544 		return ERROR_PSMFPLAYER_INVALID_STATUS;
1545 	}
1546 	auto videoData = PSPPointer<PsmfVideoData>::Create(videoDataAddr);
1547 	if (!videoData.IsValid()) {
1548 		ERROR_LOG(ME, "scePsmfPlayerGetVideoData(%08x, %08x): invalid data pointer", psmfPlayer, videoDataAddr);
1549 		// Technically just crashes if videoData is not valid.
1550 		return SCE_KERNEL_ERROR_INVALID_POINTER;
1551 	}
1552 	if (videoData->frameWidth < 0) {
1553 		ERROR_LOG(ME, "scePsmfPlayerGetVideoData(%08x, %08x): illegal bufw %d", psmfPlayer, videoDataAddr, videoData->frameWidth);
1554 		return SCE_KERNEL_ERROR_PRIV_REQUIRED;
1555 	}
1556 	if (videoData->frameWidth != 0 && videoData->frameWidth < psmfplayer->mediaengine->VideoWidth()) {
1557 		ERROR_LOG(ME, "scePsmfPlayerGetVideoData(%08x, %08x): bufw %d smaller than width %d", psmfPlayer, videoDataAddr, videoData->frameWidth, psmfplayer->mediaengine->VideoWidth());
1558 		return SCE_KERNEL_ERROR_INVALID_VALUE;
1559 	}
1560 
1561 	hleEatCycles(20000);
1562 
1563 	if (!__PsmfPlayerContinueSeek(psmfplayer)) {
1564 		DEBUG_LOG(HLE, "scePsmfPlayerGetVideoData(%08x, %08x): still seeking", psmfPlayer, videoDataAddr);
1565 		return ERROR_PSMFPLAYER_NO_MORE_DATA;
1566 	}
1567 
1568 	// On a real PSP, this takes a potentially variable amount of time.
1569 	// Normally a minimum of 3 without audio, 5 with.  But if you don't delay sufficiently between, hundreds.
1570 	// It should be okay if we start videos quicker, but some games expect the first couple to fail.
1571 	if (psmfplayer->warmUp < PSMF_PLAYER_WARMUP_FRAMES) {
1572 		DEBUG_LOG(ME, "scePsmfPlayerGetVideoData(%08x, %08x): warming up", psmfPlayer, videoDataAddr);
1573 		++psmfplayer->warmUp;
1574 		return ERROR_PSMFPLAYER_NO_MORE_DATA;
1575 	}
1576 	// In case we change warm up later, save a high value in savestates - video started.
1577 	psmfplayer->warmUp = 10000;
1578 
1579 	// It's fine to pass an invalid value here if it's still warming up, but after that it's not okay.
1580 	if (!Memory::IsValidAddress(videoData->displaybuf)) {
1581 		ERROR_LOG(ME, "scePsmfPlayerGetVideoData(%08x, %08x): invalid buffer pointer %08x", psmfPlayer, videoDataAddr, videoData->displaybuf);
1582 		return SCE_KERNEL_ERROR_INVALID_POINTER;
1583 	}
1584 
1585 	bool doVideoStep = true;
1586 	if (psmfplayer->playMode == PSMF_PLAYER_MODE_PAUSE) {
1587 		doVideoStep = false;
1588 	} else if (!psmfplayer->mediaengine->IsNoAudioData() && psmfplayer->mediaengine->IsActuallyPlayingAudio()) {
1589 		s64 deltapts = psmfplayer->mediaengine->getVideoTimeStamp() - psmfplayer->mediaengine->getAudioTimeStamp();
1590 		// Don't skip the very first frame, sometimes audio starts with an early timestamp.
1591 		if (deltapts > 0 && psmfplayer->mediaengine->getVideoTimeStamp() > 0) {
1592 			// Don't advance, just return the same frame again.
1593 			// TODO: This also seems somewhat based on Update() calls, but audio is involved too...
1594 			doVideoStep = false;
1595 		} else {
1596 			// This is an approximation, it should allow a certain amount ahead before skipping frames.
1597 			while (deltapts <= -(VIDEO_FRAME_DURATION_TS * 5)) {
1598 				psmfplayer->mediaengine->stepVideo(videoPixelMode, true);
1599 				deltapts = psmfplayer->mediaengine->getVideoTimeStamp() - psmfplayer->mediaengine->getAudioTimeStamp();
1600 			}
1601 		}
1602 	} else {
1603 		// No audio, based on Update() calls.  playSpeed doesn't seem to matter?
1604 		if (psmfplayer->videoStep <= 1 && psmfplayer->mediaengine->getVideoTimeStamp() > 0) {
1605 			doVideoStep = false;
1606 		} else {
1607 			psmfplayer->videoStep = 0;
1608 		}
1609 	}
1610 
1611 	if (doVideoStep) {
1612 		psmfplayer->mediaengine->stepVideo(videoPixelMode);
1613 	}
1614 
1615 	// It seems the frameWidth is rounded down to even values, and defaults to 512.
1616 	int bufw = videoData->frameWidth == 0 ? 512 : videoData->frameWidth & ~1;
1617 	// Always write the video frame, even after the video has ended.
1618 	int displaybufSize = psmfplayer->mediaengine->writeVideoImage(videoData->displaybuf, bufw, videoPixelMode);
1619 	gpu->NotifyVideoUpload(videoData->displaybuf, displaybufSize, bufw, videoPixelMode);
1620 	__PsmfUpdatePts(psmfplayer, videoData);
1621 
1622 	_PsmfPlayerFillRingbuffer(psmfplayer);
1623 
1624 	DEBUG_LOG(ME, "%08x=scePsmfPlayerGetVideoData(%08x, %08x)", 0, psmfPlayer, videoDataAddr);
1625 	return hleDelayResult(0, "psmfPlayer video decode", 3000);
1626 }
1627 
scePsmfPlayerGetAudioData(u32 psmfPlayer,u32 audioDataAddr)1628 static int scePsmfPlayerGetAudioData(u32 psmfPlayer, u32 audioDataAddr)
1629 {
1630 	PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer);
1631 	if (!psmfplayer) {
1632 		ERROR_LOG(ME, "scePsmfPlayerGetAudioData(%08x, %08x): invalid psmf player", psmfPlayer, audioDataAddr);
1633 		return ERROR_PSMFPLAYER_INVALID_STATUS;
1634 	}
1635 	if (psmfplayer->status < PSMF_PLAYER_STATUS_PLAYING) {
1636 		ERROR_LOG(ME, "scePsmfPlayerGetAudioData(%08x, %08x): not yet playing", psmfPlayer, audioDataAddr);
1637 		return ERROR_PSMFPLAYER_INVALID_STATUS;
1638 	}
1639 	if (!Memory::IsValidAddress(audioDataAddr)) {
1640 		ERROR_LOG(ME, "scePsmfPlayerGetAudioData(%08x, %08x): invalid audio pointer", psmfPlayer, audioDataAddr);
1641 		return SCE_KERNEL_ERROR_INVALID_POINTER;
1642 	}
1643 
1644 	// Don't return audio frames before we would return video frames.
1645 	if (psmfplayer->warmUp < PSMF_PLAYER_WARMUP_FRAMES) {
1646 		DEBUG_LOG(ME, "scePsmfPlayerGetAudioData(%08x, %08x): warming up", psmfPlayer, audioDataAddr);
1647 		return ERROR_PSMFPLAYER_NO_MORE_DATA;
1648 	}
1649 
1650 	if (psmfplayer->playMode == PSMF_PLAYER_MODE_PAUSE) {
1651 		INFO_LOG(HLE, "scePsmfPlayerGetAudioData(%08x): paused mode", psmfPlayer);
1652 		return ERROR_PSMFPLAYER_NO_MORE_DATA;
1653 	}
1654 
1655 	int ret = 0;
1656 	if (psmfplayer->mediaengine->getAudioSamples(audioDataAddr) == 0) {
1657 		if (psmfplayer->totalAudioStreams > 0 && (s64)psmfplayer->psmfPlayerAvcAu.pts < (s64)psmfplayer->totalDurationTimestamp - VIDEO_FRAME_DURATION_TS) {
1658 			// Write zeros for any missing trailing frames so it syncs with the video.
1659 			Memory::Memset(audioDataAddr, 0, audioSamplesBytes, "PsmfAudioClear");
1660 		} else {
1661 			ret = (int)ERROR_PSMFPLAYER_NO_MORE_DATA;
1662 		}
1663 	}
1664 
1665 	DEBUG_LOG(ME, "%08x=scePsmfPlayerGetAudioData(%08x, %08x)", ret, psmfPlayer, audioDataAddr);
1666 	if (ret != 0) {
1667 		hleEatCycles(10000);
1668 	} else {
1669 		hleEatCycles(30000);
1670 	}
1671 	hleReSchedule("psmfplayer audio decode");
1672 	return ret;
1673 }
1674 
scePsmfPlayerGetCurrentStatus(u32 psmfPlayer)1675 static int scePsmfPlayerGetCurrentStatus(u32 psmfPlayer)
1676 {
1677 	PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer);
1678 	if (!psmfplayer) {
1679 		// Mana Khemia and other games call this even when not necessary.
1680 		// It's annoying so the logging is verbose'd out.
1681 		VERBOSE_LOG(ME, "scePsmfPlayerGetCurrentStatus(%08x): invalid psmf player", psmfPlayer);
1682 		return ERROR_PSMFPLAYER_INVALID_STATUS;
1683 	}
1684 	if (psmfplayer->status == PSMF_PLAYER_STATUS_NONE) {
1685 		ERROR_LOG(ME, "scePsmfPlayerGetCurrentStatus(%08x): not initialized", psmfPlayer);
1686 		return ERROR_PSMFPLAYER_INVALID_STATUS;
1687 	}
1688 
1689 	DEBUG_LOG(ME, "%d=scePsmfPlayerGetCurrentStatus(%08x)", psmfplayer->status, psmfPlayer);
1690 	return psmfplayer->status;
1691 }
1692 
scePsmfPlayerGetCurrentPts(u32 psmfPlayer,u32 currentPtsAddr)1693 static u32 scePsmfPlayerGetCurrentPts(u32 psmfPlayer, u32 currentPtsAddr)
1694 {
1695 	PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer);
1696 	if (!psmfplayer) {
1697 		ERROR_LOG(ME, "scePsmfPlayerGetCurrentPts(%08x, %08x): invalid psmf player", psmfPlayer, currentPtsAddr);
1698 		return ERROR_PSMFPLAYER_INVALID_STATUS;
1699 	}
1700 	if (psmfplayer->status < PSMF_PLAYER_STATUS_STANDBY) {
1701 		ERROR_LOG(ME, "scePsmfPlayerGetCurrentPts(%08x, %08x): not initialized", psmfPlayer, currentPtsAddr);
1702 		return ERROR_PSMFPLAYER_INVALID_STATUS;
1703 	}
1704 	if (psmfplayer->psmfPlayerAvcAu.pts < 0) {
1705 		VERBOSE_LOG(ME, "scePsmfPlayerGetCurrentPts(%08x, %08x): no frame yet", psmfPlayer, currentPtsAddr);
1706 		return ERROR_PSMFPLAYER_NO_MORE_DATA;
1707 	}
1708 
1709 	DEBUG_LOG(ME, "scePsmfPlayerGetCurrentPts(%08x, %08x)", psmfPlayer, currentPtsAddr);
1710 	if (Memory::IsValidAddress(currentPtsAddr)) {
1711 		Memory::Write_U32(psmfplayer->psmfPlayerAvcAu.pts, currentPtsAddr);
1712 	}
1713 	return 0;
1714 }
1715 
scePsmfPlayerGetPsmfInfo(u32 psmfPlayer,u32 psmfInfoAddr,u32 widthAddr,u32 heightAddr)1716 static u32 scePsmfPlayerGetPsmfInfo(u32 psmfPlayer, u32 psmfInfoAddr, u32 widthAddr, u32 heightAddr) {
1717 	auto info = PSPPointer<PsmfInfo>::Create(psmfInfoAddr);
1718 	if (!Memory::IsValidAddress(psmfPlayer) || !info.IsValid()) {
1719 		ERROR_LOG(ME, "scePsmfPlayerGetPsmfInfo(%08x, %08x): invalid addresses", psmfPlayer, psmfInfoAddr);
1720 		// PSP would crash.
1721 		return SCE_KERNEL_ERROR_ILLEGAL_ADDRESS;
1722 	}
1723 
1724 	PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer);
1725 	if (!psmfplayer) {
1726 		ERROR_LOG(ME, "scePsmfPlayerGetPsmfInfo(%08x, %08x): invalid psmf player", psmfPlayer, psmfInfoAddr);
1727 		return ERROR_PSMFPLAYER_INVALID_STATUS;
1728 	}
1729 	if (psmfplayer->status < PSMF_PLAYER_STATUS_STANDBY) {
1730 		ERROR_LOG(ME, "scePsmfPlayerGetPsmfInfo(%08x): psmf not set yet", psmfPlayer);
1731 		return ERROR_PSMFPLAYER_INVALID_STATUS;
1732 	}
1733 
1734 	DEBUG_LOG(ME, "scePsmfPlayerGetPsmfInfo(%08x, %08x)", psmfPlayer, psmfInfoAddr);
1735 	// The first frame is at 0, so subtract one frame's duration to get the last frame's timestamp.
1736 	info->lastFrameTS = psmfplayer->totalDurationTimestamp - VIDEO_FRAME_DURATION_TS;
1737 	info->numVideoStreams = psmfplayer->totalVideoStreams;
1738 	info->numAudioStreams = psmfplayer->totalAudioStreams;
1739 	// pcm stream num?
1740 	info->numPCMStreams = 0;
1741 	info->playerVersion = psmfplayer->playerVersion;
1742 
1743 	if (psmfPlayerLibVersion == 0x03090510) {
1744 		// LocoRoco 2 depends on these for sizing its video output. Without this, its height is zero
1745 		// and nothing is drawn.
1746 		// Can't ask mediaengine for width/height here, it's too early, so we grabbed it from the
1747 		// header in scePsmfPlayerSetPsmf.
1748 		if (Memory::IsValidAddress(widthAddr) && psmfplayer->videoWidth) {
1749 			Memory::Write_U32(psmfplayer->videoWidth, widthAddr);
1750 		}
1751 		if (Memory::IsValidAddress(heightAddr) && psmfplayer->videoHeight) {
1752 			Memory::Write_U32(psmfplayer->videoHeight, heightAddr);
1753 		}
1754 	}
1755 	return 0;
1756 }
1757 
scePsmfPlayerGetCurrentPlayMode(u32 psmfPlayer,u32 playModeAddr,u32 playSpeedAddr)1758 static u32 scePsmfPlayerGetCurrentPlayMode(u32 psmfPlayer, u32 playModeAddr, u32 playSpeedAddr)
1759 {
1760 	PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer);
1761 	if (!psmfplayer) {
1762 		ERROR_LOG(ME, "scePsmfPlayerGetCurrentPlayMode(%08x, %08x, %08x): invalid psmf player", psmfPlayer, playModeAddr, playSpeedAddr);
1763 		return ERROR_PSMFPLAYER_INVALID_STATUS;
1764 	}
1765 
1766 	DEBUG_LOG(ME, "scePsmfPlayerGetCurrentPlayMode(%08x, %08x, %08x)", psmfPlayer, playModeAddr, playSpeedAddr);
1767 	if (Memory::IsValidAddress(playModeAddr)) {
1768 		Memory::Write_U32(psmfplayer->playMode, playModeAddr);
1769 	}
1770 	if (Memory::IsValidAddress(playSpeedAddr)) {
1771 		Memory::Write_U32(psmfplayer->playSpeed, playSpeedAddr);
1772 	}
1773 	return 0;
1774 }
1775 
scePsmfPlayerGetCurrentVideoStream(u32 psmfPlayer,u32 videoCodecAddr,u32 videoStreamNumAddr)1776 static u32 scePsmfPlayerGetCurrentVideoStream(u32 psmfPlayer, u32 videoCodecAddr, u32 videoStreamNumAddr)
1777 {
1778 	PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer);
1779 	if (!psmfplayer) {
1780 		ERROR_LOG(ME, "scePsmfPlayerGetCurrentVideoStream(%08x, %08x, %08x): invalid psmf player", psmfPlayer, videoCodecAddr, videoStreamNumAddr);
1781 		return ERROR_PSMFPLAYER_INVALID_STATUS;
1782 	}
1783 	if (psmfplayer->status == PSMF_PLAYER_STATUS_INIT) {
1784 		ERROR_LOG(ME, "scePsmfPlayerGetCurrentVideoStream(%08x): psmf not yet set", psmfPlayer);
1785 		return ERROR_PSMFPLAYER_INVALID_STATUS;
1786 	}
1787 
1788 	DEBUG_LOG(ME, "scePsmfPlayerGetCurrentVideoStream(%08x, %08x, %08x)", psmfPlayer, videoCodecAddr, videoStreamNumAddr);
1789 	if (Memory::IsValidAddress(videoCodecAddr)) {
1790 		Memory::Write_U32(psmfplayer->videoCodec == 0x0E ? 0 : psmfplayer->videoCodec, videoCodecAddr);
1791 	}
1792 	if (Memory::IsValidAddress(videoStreamNumAddr)) {
1793 		Memory::Write_U32(psmfplayer->videoStreamNum, videoStreamNumAddr);
1794 	}
1795 	return 0;
1796 }
1797 
scePsmfPlayerGetCurrentAudioStream(u32 psmfPlayer,u32 audioCodecAddr,u32 audioStreamNumAddr)1798 static u32 scePsmfPlayerGetCurrentAudioStream(u32 psmfPlayer, u32 audioCodecAddr, u32 audioStreamNumAddr)
1799 {
1800 	PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer);
1801 	if (!psmfplayer) {
1802 		ERROR_LOG(ME, "scePsmfPlayerGetCurrentAudioStream(%08x, %08x, %08x): invalid psmf player", psmfPlayer, audioCodecAddr, audioStreamNumAddr);
1803 		return ERROR_PSMFPLAYER_INVALID_STATUS;
1804 	}
1805 	if (psmfplayer->status == PSMF_PLAYER_STATUS_INIT) {
1806 		ERROR_LOG(ME, "scePsmfPlayerGetCurrentVideoStream(%08x): psmf not yet set", psmfPlayer);
1807 		return ERROR_PSMFPLAYER_INVALID_STATUS;
1808 	}
1809 
1810 	DEBUG_LOG(ME, "scePsmfPlayerGetCurrentAudioStream(%08x, %08x, %08x)", psmfPlayer, audioCodecAddr, audioStreamNumAddr);
1811 	if (Memory::IsValidAddress(audioCodecAddr)) {
1812 		Memory::Write_U32(psmfplayer->audioCodec == 0x0F ? 1 : psmfplayer->audioCodec, audioCodecAddr);
1813 	}
1814 	if (Memory::IsValidAddress(audioStreamNumAddr)) {
1815 		Memory::Write_U32(psmfplayer->audioStreamNum, audioStreamNumAddr);
1816 	}
1817 	return 0;
1818 }
1819 
scePsmfPlayerSetTempBuf(u32 psmfPlayer,u32 tempBufAddr,u32 tempBufSize)1820 static int scePsmfPlayerSetTempBuf(u32 psmfPlayer, u32 tempBufAddr, u32 tempBufSize)
1821 {
1822 	PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer);
1823 	if (!psmfplayer) {
1824 		ERROR_LOG(ME, "scePsmfPlayerSetTempBuf(%08x, %08x, %08x): invalid psmf player", psmfPlayer, tempBufAddr, tempBufSize);
1825 		return ERROR_PSMFPLAYER_INVALID_STATUS;
1826 	}
1827 	if (psmfplayer->status != PSMF_PLAYER_STATUS_INIT) {
1828 		ERROR_LOG_REPORT(ME, "scePsmfPlayerSetTempBuf(%08x, %08x, %08x): invalid status %x", psmfPlayer, tempBufAddr, tempBufSize, psmfplayer->status);
1829 		return ERROR_PSMFPLAYER_INVALID_STATUS;
1830 	}
1831 	if (tempBufSize < 0x00010000) {
1832 		ERROR_LOG_REPORT(ME, "scePsmfPlayerSetTempBuf(%08x, %08x, %08x): buffer too small", psmfPlayer, tempBufAddr, tempBufSize);
1833 		return ERROR_PSMFPLAYER_INVALID_PARAM;
1834 	}
1835 
1836 	INFO_LOG(ME, "scePsmfPlayerSetTempBuf(%08x, %08x, %08x)", psmfPlayer, tempBufAddr, tempBufSize);
1837 	// fake it right now, use tempbuf from memory directly
1838 	//psmfplayer->tempbuf = tempBufAddr;
1839 	//psmfplayer->tempbufSize = tempBufSize;
1840 
1841 	return 0;
1842 }
1843 
scePsmfPlayerChangePlayMode(u32 psmfPlayer,int playMode,int playSpeed)1844 static u32 scePsmfPlayerChangePlayMode(u32 psmfPlayer, int playMode, int playSpeed)
1845 {
1846 	PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer);
1847 	if (!psmfplayer) {
1848 		ERROR_LOG(ME, "scePsmfPlayerChangePlayMode(%08x, %i, %i): invalid psmf player", psmfPlayer, playMode, playSpeed);
1849 		return ERROR_PSMFPLAYER_INVALID_STATUS;
1850 	}
1851 	if (psmfplayer->status < PSMF_PLAYER_STATUS_PLAYING) {
1852 		ERROR_LOG(ME, "scePsmfPlayerChangePlayMode(%08x, %i, %i): not playing yet", psmfPlayer, playMode, playSpeed);
1853 		return ERROR_PSMFPLAYER_INVALID_STATUS;
1854 	}
1855 	if (playMode < 0 || playMode > (int)PSMF_PLAYER_MODE_REWIND) {
1856 		ERROR_LOG(ME, "scePsmfPlayerChangePlayMode(%08x, %i, %i): invalid mode", psmfPlayer, playMode, playSpeed);
1857 		return ERROR_PSMFPLAYER_INVALID_CONFIG;
1858 	}
1859 
1860 	switch (playMode) {
1861 	case PSMF_PLAYER_MODE_FORWARD:
1862 	case PSMF_PLAYER_MODE_REWIND:
1863 		if (psmfplayer->playerVersion == PSMF_PLAYER_VERSION_BASIC) {
1864 			ERROR_LOG_REPORT(ME, "scePsmfPlayerChangePlayMode(%08x, %i, %i): no EP data for FORWARD/REWIND", psmfPlayer, playMode, playSpeed);
1865 			return ERROR_PSMFPLAYER_INVALID_STREAM;
1866 		}
1867 		psmfplayer->playSpeed = playSpeed;
1868 		WARN_LOG_REPORT(ME, "scePsmfPlayerChangePlayMode(%08x, %i, %i): unsupported playMode", psmfPlayer, playMode, playSpeed);
1869 		break;
1870 
1871 	case PSMF_PLAYER_MODE_PLAY:
1872 	case PSMF_PLAYER_MODE_PAUSE:
1873 		if (psmfplayer->playSpeed != playSpeed) {
1874 			WARN_LOG_REPORT(ME, "scePsmfPlayerChangePlayMode(%08x, %i, %i): play speed not changed", psmfPlayer, playMode, playSpeed);
1875 		} else {
1876 			DEBUG_LOG(ME, "scePsmfPlayerChangePlayMode(%08x, %i, %i)", psmfPlayer, playMode, playSpeed);
1877 		}
1878 		break;
1879 
1880 	default:
1881 		if (psmfplayer->playSpeed != playSpeed) {
1882 			WARN_LOG_REPORT(ME, "scePsmfPlayerChangePlayMode(%08x, %i, %i): play speed not changed", psmfPlayer, playMode, playSpeed);
1883 		}
1884 		WARN_LOG_REPORT(ME, "scePsmfPlayerChangePlayMode(%08x, %i, %i): unsupported playMode", psmfPlayer, playMode, playSpeed);
1885 		break;
1886 	}
1887 
1888 	psmfplayer->playMode = playMode;
1889 	return 0;
1890 }
1891 
scePsmfPlayerSelectAudio(u32 psmfPlayer)1892 static u32 scePsmfPlayerSelectAudio(u32 psmfPlayer)
1893 {
1894 	PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer);
1895 	if (!psmfplayer) {
1896 		ERROR_LOG(ME, "scePsmfPlayerSelectAudio(%08x): invalid psmf player", psmfPlayer);
1897 		return ERROR_PSMFPLAYER_INVALID_STATUS;
1898 	}
1899 	if (psmfplayer->status != PSMF_PLAYER_STATUS_PLAYING) {
1900 		ERROR_LOG(ME, "scePsmfPlayerSelectAudio(%08x): not playing", psmfPlayer);
1901 		return ERROR_PSMFPLAYER_INVALID_STATUS;
1902 	}
1903 
1904 	int next = psmfplayer->audioStreamNum + 1;
1905 	if (next >= psmfplayer->totalAudioStreams)
1906 		next = 0;
1907 
1908 	if (next == psmfplayer->audioStreamNum || !psmfplayer->mediaengine->setAudioStream(next)) {
1909 		ERROR_LOG_REPORT(ME, "scePsmfPlayerSelectAudio(%08x): no stream to switch to", psmfPlayer);
1910 		return ERROR_PSMFPLAYER_INVALID_STREAM;
1911 	}
1912 
1913 	WARN_LOG_REPORT(ME, "scePsmfPlayerSelectAudio(%08x)", psmfPlayer);
1914 	psmfplayer->audioStreamNum = next;
1915 	return 0;
1916 }
1917 
scePsmfPlayerSelectVideo(u32 psmfPlayer)1918 static u32 scePsmfPlayerSelectVideo(u32 psmfPlayer)
1919 {
1920 	PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer);
1921 	if (!psmfplayer) {
1922 		ERROR_LOG(ME, "scePsmfPlayerSelectVideo(%08x): invalid psmf player", psmfPlayer);
1923 		return ERROR_PSMFPLAYER_INVALID_STATUS;
1924 	}
1925 	if (psmfplayer->status != PSMF_PLAYER_STATUS_PLAYING) {
1926 		ERROR_LOG(ME, "scePsmfPlayerSelectVideo(%08x): not playing", psmfPlayer);
1927 		return ERROR_PSMFPLAYER_INVALID_STATUS;
1928 	}
1929 
1930 	int next = psmfplayer->videoStreamNum + 1;
1931 	if (next >= psmfplayer->totalVideoStreams)
1932 		next = 0;
1933 
1934 	if (next == psmfplayer->videoStreamNum || !psmfplayer->mediaengine->setVideoStream(next)) {
1935 		ERROR_LOG_REPORT(ME, "scePsmfPlayerSelectVideo(%08x): no stream to switch to", psmfPlayer);
1936 		return ERROR_PSMFPLAYER_INVALID_STREAM;
1937 	}
1938 
1939 	WARN_LOG_REPORT(ME, "scePsmfPlayerSelectVideo(%08x)", psmfPlayer);
1940 	psmfplayer->videoStreamNum = next;
1941 	return 0;
1942 }
1943 
scePsmfPlayerSelectSpecificVideo(u32 psmfPlayer,int videoCodec,int videoStreamNum)1944 static u32 scePsmfPlayerSelectSpecificVideo(u32 psmfPlayer, int videoCodec, int videoStreamNum)
1945 {
1946 	PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer);
1947 	if (!psmfplayer) {
1948 		ERROR_LOG(ME, "scePsmfPlayerSelectSpecificVideo(%08x, %i, %i): invalid psmf player", psmfPlayer, videoCodec, videoStreamNum);
1949 		return ERROR_PSMFPLAYER_INVALID_STATUS;
1950 	}
1951 	if (psmfplayer->status != PSMF_PLAYER_STATUS_PLAYING) {
1952 		ERROR_LOG(ME, "scePsmfPlayerSelectSpecificVideo(%08x, %i, %i): not playing", psmfPlayer, videoCodec, videoStreamNum);
1953 		return ERROR_PSMFPLAYER_INVALID_STATUS;
1954 	}
1955 	if (psmfplayer->totalVideoStreams < 2) {
1956 		ERROR_LOG_REPORT(ME, "scePsmfPlayerSelectSpecificVideo(%08x, %i, %i): unable to change stream", psmfPlayer, videoCodec, videoStreamNum);
1957 		return ERROR_PSMFPLAYER_INVALID_STREAM;
1958 	}
1959 	if (videoStreamNum < 0 || videoStreamNum >= psmfplayer->totalVideoStreams) {
1960 		ERROR_LOG_REPORT(ME, "scePsmfPlayerSelectSpecificVideo(%08x, %i, %i): bad stream num param", psmfPlayer, videoCodec, videoStreamNum);
1961 		return ERROR_PSMFPLAYER_INVALID_CONFIG;
1962 	}
1963 	if (videoCodec != 0x0E && videoCodec != 0x00) {
1964 		ERROR_LOG_REPORT(ME, "scePsmfPlayerSelectSpecificVideo(%08x, %i, %i): invalid codec", psmfPlayer, videoCodec, videoStreamNum);
1965 		return ERROR_PSMFPLAYER_INVALID_STREAM;
1966 	}
1967 	if (psmfplayer->totalVideoStreams < 2 || !psmfplayer->mediaengine->setVideoStream(videoStreamNum)) {
1968 		ERROR_LOG_REPORT(ME, "scePsmfPlayerSelectSpecificVideo(%08x, %i, %i): unable to change stream", psmfPlayer, videoCodec, videoStreamNum);
1969 		return ERROR_PSMFPLAYER_INVALID_STREAM;
1970 	}
1971 
1972 	WARN_LOG_REPORT(ME, "scePsmfPlayerSelectSpecificVideo(%08x, %i, %i)", psmfPlayer, videoCodec, videoStreamNum);
1973 	if (psmfplayer->videoStreamNum != videoStreamNum) {
1974 		hleDelayResult(0, "psmf select video", 100);
1975 	}
1976 	psmfplayer->videoCodec = videoCodec;
1977 	psmfplayer->videoStreamNum = videoStreamNum;
1978 	return 0;
1979 }
1980 
1981 // WARNING: This function appears to be buggy in most libraries.
scePsmfPlayerSelectSpecificAudio(u32 psmfPlayer,int audioCodec,int audioStreamNum)1982 static u32 scePsmfPlayerSelectSpecificAudio(u32 psmfPlayer, int audioCodec, int audioStreamNum)
1983 {
1984 	PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer);
1985 	if (!psmfplayer) {
1986 		ERROR_LOG(ME, "scePsmfPlayerSelectSpecificAudio(%08x, %i, %i): invalid psmf player", psmfPlayer, audioCodec, audioStreamNum);
1987 		return ERROR_PSMFPLAYER_INVALID_STATUS;
1988 	}
1989 	if (psmfplayer->status != PSMF_PLAYER_STATUS_PLAYING) {
1990 		ERROR_LOG(ME, "scePsmfPlayerSelectSpecificAudio(%08x, %i, %i): not playing", psmfPlayer, audioCodec, audioStreamNum);
1991 		return ERROR_PSMFPLAYER_INVALID_STATUS;
1992 	}
1993 	if (psmfplayer->totalAudioStreams < 2) {
1994 		ERROR_LOG_REPORT(ME, "scePsmfPlayerSelectSpecificAudio(%08x, %i, %i): unable to change stream", psmfPlayer, audioCodec, audioStreamNum);
1995 		return ERROR_PSMFPLAYER_INVALID_STREAM;
1996 	}
1997 	if (audioStreamNum < 0 || audioStreamNum >= psmfplayer->totalAudioStreams) {
1998 		ERROR_LOG_REPORT(ME, "scePsmfPlayerSelectSpecificAudio(%08x, %i, %i): bad stream num param", psmfPlayer, audioCodec, audioStreamNum);
1999 		return ERROR_PSMFPLAYER_INVALID_CONFIG;
2000 	}
2001 	if (audioCodec != 0x0F && audioCodec != 0x01) {
2002 		ERROR_LOG_REPORT(ME, "scePsmfPlayerSelectSpecificAudio(%08x, %i, %i): invalid codec", psmfPlayer, audioCodec, audioStreamNum);
2003 		return ERROR_PSMFPLAYER_INVALID_STREAM;
2004 	}
2005 	if (psmfplayer->totalAudioStreams < 2 || !psmfplayer->mediaengine->setAudioStream(audioStreamNum)) {
2006 		ERROR_LOG_REPORT(ME, "scePsmfPlayerSelectSpecificAudio(%08x, %i, %i): unable to change stream", psmfPlayer, audioCodec, audioStreamNum);
2007 		return ERROR_PSMFPLAYER_INVALID_STREAM;
2008 	}
2009 
2010 	WARN_LOG_REPORT(ME, "scePsmfPlayerSelectSpecificAudio(%08x, %i, %i)", psmfPlayer, audioCodec, audioStreamNum);
2011 	if (psmfplayer->audioStreamNum != audioStreamNum) {
2012 		hleDelayResult(0, "psmf select audio", 100);
2013 	}
2014 	psmfplayer->audioCodec = audioCodec;
2015 	psmfplayer->audioStreamNum = audioStreamNum;
2016 	return 0;
2017 }
2018 
scePsmfPlayerConfigPlayer(u32 psmfPlayer,int configMode,int configAttr)2019 static u32 scePsmfPlayerConfigPlayer(u32 psmfPlayer, int configMode, int configAttr)
2020 {
2021 	PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer);
2022 	if (!psmfplayer) {
2023 		ERROR_LOG(ME, "scePsmfPlayerConfigPlayer(%08x, %i, %i): invalid psmf player", psmfPlayer, configMode, configAttr);
2024 		return ERROR_PSMFPLAYER_INVALID_STATUS;
2025 	}
2026 	// This one works in any status as long as it's created.
2027 
2028 	switch (configMode) {
2029 	case PSMF_PLAYER_CONFIG_MODE_LOOP:
2030 		if (configAttr != 0 && configAttr != 1) {
2031 			ERROR_LOG_REPORT(ME, "scePsmfPlayerConfigPlayer(%08x, loop, %i): invalid value", psmfPlayer, configAttr);
2032 			return ERROR_PSMFPLAYER_INVALID_PARAM;
2033 		}
2034 		INFO_LOG(ME, "scePsmfPlayerConfigPlayer(%08x, loop, %i)", psmfPlayer, configAttr);
2035 		videoLoopStatus = configAttr;
2036 		break;
2037 	case PSMF_PLAYER_CONFIG_MODE_PIXEL_TYPE:
2038 		if (configAttr < -1 || configAttr > 3) {
2039 			ERROR_LOG_REPORT(ME, "scePsmfPlayerConfigPlayer(%08x, pixelType, %i): invalid value", psmfPlayer, configAttr);
2040 			return ERROR_PSMFPLAYER_INVALID_PARAM;
2041 		}
2042 		INFO_LOG(ME, "scePsmfPlayerConfigPlayer(%08x, pixelType, %i)", psmfPlayer, configAttr);
2043 		// Does -1 mean default or something?
2044 		if (configAttr != -1) {
2045 			videoPixelMode = configAttr;
2046 		} else {
2047 			// TODO: At least for one video, this was the same as 8888.
2048 			videoPixelMode = GE_CMODE_32BIT_ABGR8888;
2049 		}
2050 		break;
2051 	default:
2052 		ERROR_LOG_REPORT(ME, "scePsmfPlayerConfigPlayer(%08x, %i, %i): unknown parameter", psmfPlayer, configMode, configAttr);
2053 		return ERROR_PSMFPLAYER_INVALID_CONFIG;
2054 	}
2055 
2056 	return 0;
2057 }
2058 
__PsmfPlayerFinish(u32 psmfPlayer)2059 static int __PsmfPlayerFinish(u32 psmfPlayer) {
2060 	PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer);
2061 	if (!psmfplayer) {
2062 		ERROR_LOG_REPORT(ME, "__PsmfPlayerFinish(%08x): invalid psmf player", psmfPlayer);
2063 		return ERROR_PSMFPLAYER_INVALID_STATUS;
2064 	}
2065 	if (psmfplayer->status != PSMF_PLAYER_STATUS_PLAYING) {
2066 		ERROR_LOG_REPORT(ME, "__PsmfPlayerFinish(%08x): unexpected status %d", psmfPlayer, psmfplayer->status);
2067 		return ERROR_PSMFPLAYER_INVALID_STATUS;
2068 	}
2069 
2070 	INFO_LOG(ME, "__PsmfPlayerFinish(%08x): video end reached", psmfPlayer);
2071 	psmfplayer->status = PSMF_PLAYER_STATUS_PLAYING_FINISHED;
2072 	return 0;
2073 }
2074 
2075 const HLEFunction scePsmf[] = {
2076 	{0XC22C8327, &WrapU_UU<scePsmfSetPsmf>,                            "scePsmfSetPsmf",                           'x', "xx"  ,HLE_CLEAR_STACK_BYTES, 0x50},
2077 	{0XC7DB3A5B, &WrapU_UUU<scePsmfGetCurrentStreamType>,              "scePsmfGetCurrentStreamType",              'i', "xpp" ,HLE_CLEAR_STACK_BYTES, 0x50},
2078 	{0X28240568, &WrapU_U<scePsmfGetCurrentStreamNumber>,              "scePsmfGetCurrentStreamNumber",            'i', "x"  },
2079 	{0X1E6D9013, &WrapU_UUU<scePsmfSpecifyStreamWithStreamType>,       "scePsmfSpecifyStreamWithStreamType",       'i', "xii" ,HLE_CLEAR_STACK_BYTES, 0x20},
2080 	{0X0C120E1D, &WrapU_UUU<scePsmfSpecifyStreamWithStreamTypeNumber>, "scePsmfSpecifyStreamWithStreamTypeNumber", 'i', "xii"},
2081 	{0X4BC9BDE0, &WrapU_UI<scePsmfSpecifyStream>,                      "scePsmfSpecifyStream",                     'i', "xi"  ,HLE_CLEAR_STACK_BYTES, 0x40},
2082 	{0X76D3AEBA, &WrapU_UU<scePsmfGetPresentationStartTime>,           "scePsmfGetPresentationStartTime",          'x', "xx"  ,HLE_CLEAR_STACK_BYTES, 0x10},
2083 	{0XBD8AE0D8, &WrapU_UU<scePsmfGetPresentationEndTime>,             "scePsmfGetPresentationEndTime",            'x', "xx"  ,HLE_CLEAR_STACK_BYTES, 0x10},
2084 	{0XEAED89CD, &WrapU_U<scePsmfGetNumberOfStreams>,                  "scePsmfGetNumberOfStreams",                'i', "x"   ,HLE_CLEAR_STACK_BYTES, 0x10},
2085 	{0X7491C438, &WrapU_U<scePsmfGetNumberOfEPentries>,                "scePsmfGetNumberOfEPentries",              'x', "x"   ,HLE_CLEAR_STACK_BYTES, 0x10},
2086 	{0X0BA514E5, &WrapU_UU<scePsmfGetVideoInfo>,                       "scePsmfGetVideoInfo",                      'i', "xp"  ,HLE_CLEAR_STACK_BYTES, 0x20},
2087 	{0XA83F7113, &WrapU_UU<scePsmfGetAudioInfo>,                       "scePsmfGetAudioInfo",                      'i', "xp"  ,HLE_CLEAR_STACK_BYTES, 0x20},
2088 	{0X971A3A90, &WrapU_U<scePsmfCheckEPMap>,                          "scePsmfCheckEPmap",                        'x', "x"   ,HLE_CLEAR_STACK_BYTES, 0x10},
2089 	{0X68D42328, &WrapU_UI<scePsmfGetNumberOfSpecificStreams>,         "scePsmfGetNumberOfSpecificStreams",        'i', "xi"  ,HLE_CLEAR_STACK_BYTES, 0x20},
2090 	{0X5B70FCC1, &WrapU_UU<scePsmfQueryStreamOffset>,                  "scePsmfQueryStreamOffset",                 'x', "xx" },
2091 	{0X9553CC91, &WrapU_UU<scePsmfQueryStreamSize>,                    "scePsmfQueryStreamSize",                   'x', "xx" },
2092 	{0XB78EB9E9, &WrapU_UU<scePsmfGetHeaderSize>,                      "scePsmfGetHeaderSize",                     'x', "xx" },
2093 	{0XA5EBFE81, &WrapU_UU<scePsmfGetStreamSize>,                      "scePsmfGetStreamSize",                     'x', "xx" },
2094 	{0XE1283895, &WrapU_U<scePsmfGetPsmfVersion>,                      "scePsmfGetPsmfVersion",                    'x', "x"  },
2095 	{0X2673646B, &WrapU_U<scePsmfVerifyPsmf>,                          "scePsmfVerifyPsmf",                        'x', "x"   ,HLE_CLEAR_STACK_BYTES, 0x100},
2096 	{0X4E624A34, &WrapU_UIU<scePsmfGetEPWithId>,                       "scePsmfGetEPWithId",                       'x', "xix" ,HLE_CLEAR_STACK_BYTES, 0x10},
2097 	{0X7C0E7AC3, &WrapU_UUU<scePsmfGetEPWithTimestamp>,                "scePsmfGetEPWithTimestamp",                'x', "xxx" ,HLE_CLEAR_STACK_BYTES, 0x10},
2098 	{0X5F457515, &WrapU_UU<scePsmfGetEPidWithTimestamp>,               "scePsmfGetEPidWithTimestamp",              'x', "xx"  ,HLE_CLEAR_STACK_BYTES, 0x20},
2099 	{0X43AC7DBB, nullptr,                                              "scePsmfGetPsmfMark",                       '?', ""   },
2100 	{0XDE78E9FC, nullptr,                                              "scePsmfGetNumberOfPsmfMarks",              '?', ""   },
2101 };
2102 
2103 const HLEFunction scePsmfPlayer[] =
2104 {
2105 	{0X235D8787, &WrapI_UU<scePsmfPlayerCreate>,                       "scePsmfPlayerCreate",                      'i', "xx" },
2106 	{0X1078C008, &WrapI_U<scePsmfPlayerStop>,                          "scePsmfPlayerStop",                        'i', "x"  },
2107 	{0X1E57A8E7, &WrapU_UII<scePsmfPlayerConfigPlayer>,                "scePsmfPlayerConfigPlayer",                'x', "xii"},
2108 	{0X2BEB1569, &WrapI_U<scePsmfPlayerBreak>,                         "scePsmfPlayerBreak",                       'i', "x"  },
2109 	{0X3D6D25A9, &WrapI_UC<scePsmfPlayerSetPsmf>,                      "scePsmfPlayerSetPsmf",                     'i', "xs" },
2110 	{0X58B83577, &WrapI_UC<scePsmfPlayerSetPsmfCB>,                    "scePsmfPlayerSetPsmfCB",                   'i', "xs" },
2111 	{0X3EA82A4B, &WrapI_U<scePsmfPlayerGetAudioOutSize>,               "scePsmfPlayerGetAudioOutSize",             'i', "x"  },
2112 	{0X3ED62233, &WrapU_UU<scePsmfPlayerGetCurrentPts>,                "scePsmfPlayerGetCurrentPts",               'x', "xx" },
2113 	{0X46F61F8B, &WrapI_UU<scePsmfPlayerGetVideoData>,                 "scePsmfPlayerGetVideoData",                'i', "xx" },
2114 	{0X68F07175, &WrapU_UUU<scePsmfPlayerGetCurrentAudioStream>,       "scePsmfPlayerGetCurrentAudioStream",       'x', "xxx"},
2115 	{0X75F03FA2, &WrapU_UII<scePsmfPlayerSelectSpecificVideo>,         "scePsmfPlayerSelectSpecificVideo",         'x', "xii"},
2116 	{0X85461EFF, &WrapU_UII<scePsmfPlayerSelectSpecificAudio>,         "scePsmfPlayerSelectSpecificAudio",         'x', "xii"},
2117 	{0X8A9EBDCD, &WrapU_U<scePsmfPlayerSelectVideo>,                   "scePsmfPlayerSelectVideo",                 'x', "x"  },
2118 	{0X95A84EE5, &WrapI_UUI<scePsmfPlayerStart>,                       "scePsmfPlayerStart",                       'i', "xxi"},
2119 	{0X9B71A274, &WrapI_U<scePsmfPlayerDelete>,                        "scePsmfPlayerDelete",                      'i', "x"  },
2120 	{0X9FF2B2E7, &WrapU_UUU<scePsmfPlayerGetCurrentVideoStream>,       "scePsmfPlayerGetCurrentVideoStream",       'x', "xxx"},
2121 	{0XA0B8CA55, &WrapI_U<scePsmfPlayerUpdate>,                        "scePsmfPlayerUpdate",                      'i', "x"  },
2122 	{0XA3D81169, &WrapU_UII<scePsmfPlayerChangePlayMode>,              "scePsmfPlayerChangePlayMode",              'x', "xii"},
2123 	{0XB8D10C56, &WrapU_U<scePsmfPlayerSelectAudio>,                   "scePsmfPlayerSelectAudio",                 'x', "x"  },
2124 	{0XB9848A74, &WrapI_UU<scePsmfPlayerGetAudioData>,                 "scePsmfPlayerGetAudioData",                'i', "xx" },
2125 	{0XDF089680, &WrapU_UUUU<scePsmfPlayerGetPsmfInfo>,                  "scePsmfPlayerGetPsmfInfo",                 'x', "xxxx" },
2126 	{0XE792CD94, &WrapI_U<scePsmfPlayerReleasePsmf>,                   "scePsmfPlayerReleasePsmf",                 'i', "x"  },
2127 	{0XF3EFAA91, &WrapU_UUU<scePsmfPlayerGetCurrentPlayMode>,          "scePsmfPlayerGetCurrentPlayMode",          'x', "xxx"},
2128 	{0XF8EF08A6, &WrapI_U<scePsmfPlayerGetCurrentStatus>,              "scePsmfPlayerGetCurrentStatus",            'i', "x"  },
2129 	{0X2D0E4E0A, &WrapI_UUU<scePsmfPlayerSetTempBuf>,                  "scePsmfPlayerSetTempBuf",                  'i', "xxx"},
2130 	{0X76C0F4AE, &WrapI_UCI<scePsmfPlayerSetPsmfOffset>,               "scePsmfPlayerSetPsmfOffset",               'i', "xsi"},
2131 	{0XA72DB4F9, &WrapI_UCI<scePsmfPlayerSetPsmfOffsetCB>,             "scePsmfPlayerSetPsmfOffsetCB",             'i', "xsi"},
2132 	{0X340C12CB, nullptr,                                              "scePsmfPlayer_340C12CB",                   '?', ""   },
2133 	// Fake function for PPSSPP's use.
2134 	{0X05B193B7, &WrapI_U<__PsmfPlayerFinish>,                         "__PsmfPlayerFinish",                       'i', "x"  },
2135 };
2136 
Register_scePsmf()2137 void Register_scePsmf() {
2138 	RegisterModule("scePsmf",ARRAY_SIZE(scePsmf),scePsmf);
2139 }
2140 
Register_scePsmfPlayer()2141 void Register_scePsmfPlayer() {
2142 	RegisterModule("scePsmfPlayer",ARRAY_SIZE(scePsmfPlayer),scePsmfPlayer);
2143 }
2144