2012-11-01 16:19:01 +01:00
// Copyright (c) 2012- PPSSPP Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
2012-11-04 23:01:49 +01:00
// the Free Software Foundation, version 2.0 or later versions.
2012-11-01 16:19:01 +01:00
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
2013-05-19 17:54:14 -07:00
# include "Common/ChunkFile.h"
2015-04-05 18:03:50 -07:00
# include "Core/MemMapHelpers.h"
2013-05-19 17:54:14 -07:00
# include "Core/Reporting.h"
2013-12-30 00:11:29 +01:00
# include "Core/System.h"
2013-12-29 23:28:31 +01:00
# include "Core/FileSystems/MetaFileSystem.h"
2015-04-05 18:03:50 -07:00
# include "Core/HLE/HLE.h"
# include "Core/HLE/HLEHelperThread.h"
# include "Core/HLE/FunctionWrappers.h"
2013-05-19 17:54:14 -07:00
# include "Core/HLE/scePsmf.h"
# include "Core/HLE/sceMpeg.h"
2013-06-02 01:30:51 +08:00
# include "Core/HW/MediaEngine.h"
2013-06-08 04:50:36 -07:00
# include "GPU/GPUInterface.h"
# include "GPU/GPUState.h"
2012-11-13 18:05:26 +01:00
# include <map>
2013-09-17 00:48:14 -04:00
# include <algorithm>
2012-11-01 16:19:01 +01:00
// "Go Sudoku" is a good way to test this code...
2012-11-13 18:05:26 +01:00
const int PSMF_VIDEO_STREAM_ID = 0xE0 ;
const int PSMF_AUDIO_STREAM_ID = 0xBD ;
const int PSMF_AVC_STREAM = 0 ;
const int PSMF_ATRAC_STREAM = 1 ;
const int PSMF_PCM_STREAM = 2 ;
const int PSMF_DATA_STREAM = 3 ;
const int PSMF_AUDIO_STREAM = 15 ;
2013-01-18 18:05:51 +08:00
const int PSMF_PLAYER_VERSION_FULL = 0 ;
const int PSMF_PLAYER_VERSION_BASIC = 1 ;
const int PSMF_PLAYER_VERSION_NET = 2 ;
const int PSMF_PLAYER_CONFIG_LOOP = 0 ;
const int PSMF_PLAYER_CONFIG_NO_LOOP = 1 ;
const int PSMF_PLAYER_CONFIG_MODE_LOOP = 0 ;
const int PSMF_PLAYER_CONFIG_MODE_PIXEL_TYPE = 1 ;
2014-04-27 12:57:39 -07:00
const int PSMF_PLAYER_WARMUP_FRAMES = 3 ;
2014-05-11 21:51:28 -07:00
static const int VIDEO_FRAME_DURATION_TS = 3003 ;
2013-01-18 18:05:51 +08:00
int audioSamples = 2048 ;
int audioSamplesBytes = audioSamples * 4 ;
2014-02-14 18:45:12 +08:00
int videoPixelMode = GE_CMODE_32BIT_ABGR8888 ;
2013-09-22 21:19:59 -07:00
int videoLoopStatus = PSMF_PLAYER_CONFIG_NO_LOOP ;
2012-11-01 16:19:01 +01:00
2014-02-16 23:21:32 +08:00
enum PsmfPlayerError {
2014-03-03 11:16:53 -05:00
ERROR_PSMF_NOT_INITIALIZED = 0x80615001 ,
ERROR_PSMF_BAD_VERSION = 0x80615002 ,
ERROR_PSMF_NOT_FOUND = 0x80615025 ,
ERROR_PSMF_INVALID_ID = 0x80615100 ,
ERROR_PSMF_INVALID_VALUE = 0x806151fe ,
ERROR_PSMF_INVALID_TIMESTAMP = 0x80615500 ,
ERROR_PSMF_INVALID_PSMF = 0x80615501 ,
2014-04-20 00:01:16 -07:00
2014-04-20 08:17:56 -07:00
ERROR_PSMFPLAYER_INVALID_STATUS = 0x80616001 ,
2014-04-20 23:14:45 -07:00
ERROR_PSMFPLAYER_INVALID_STREAM = 0x80616003 ,
2014-04-20 00:01:16 -07:00
ERROR_PSMFPLAYER_BUFFER_SIZE = 0x80616005 ,
2014-04-20 19:19:12 -07:00
ERROR_PSMFPLAYER_INVALID_CONFIG = 0x80616006 ,
2014-04-20 00:01:16 -07:00
ERROR_PSMFPLAYER_INVALID_PARAM = 0x80616008 ,
2014-03-03 11:16:53 -05:00
ERROR_PSMFPLAYER_NO_MORE_DATA = 0x8061600c ,
2014-02-16 23:21:32 +08:00
} ;
2013-01-06 22:15:47 -08:00
enum PsmfPlayerStatus {
2014-03-03 11:16:53 -05:00
PSMF_PLAYER_STATUS_NONE = 0x0 ,
PSMF_PLAYER_STATUS_INIT = 0x1 ,
PSMF_PLAYER_STATUS_STANDBY = 0x2 ,
PSMF_PLAYER_STATUS_PLAYING = 0x4 ,
PSMF_PLAYER_STATUS_ERROR = 0x100 ,
2013-01-06 22:15:47 -08:00
PSMF_PLAYER_STATUS_PLAYING_FINISHED = 0x200 ,
} ;
2014-02-14 10:43:53 +08:00
enum PsmfPlayerMode {
2014-03-03 11:16:53 -05:00
PSMF_PLAYER_MODE_PLAY = 0 ,
2014-02-14 10:43:53 +08:00
PSMF_PLAYER_MODE_SLOWMOTION = 1 ,
2014-03-03 11:16:53 -05:00
PSMF_PLAYER_MODE_STEPFRAME = 2 ,
PSMF_PLAYER_MODE_PAUSE = 3 ,
PSMF_PLAYER_MODE_FORWARD = 4 ,
PSMF_PLAYER_MODE_REWIND = 5 ,
2014-02-14 10:43:53 +08:00
} ;
2012-11-01 16:19:01 +01:00
struct PsmfData {
2013-07-27 15:53:30 -07:00
u32_le version ;
u32_le headerSize ;
u32_le headerOffset ;
u32_le streamSize ;
u32_le streamOffset ;
u32_le streamNum ;
u32_le unk1 ;
u32_le unk2 ;
2013-01-18 18:05:51 +08:00
} ;
2014-04-20 00:01:16 -07:00
struct PsmfPlayerCreateData {
PSPPointer < u8 > buffer ;
u32 bufferSize ;
int threadPriority ;
} ;
2013-01-18 18:05:51 +08:00
struct PsmfPlayerData {
2013-07-27 15:53:30 -07:00
s32_le videoCodec ;
s32_le videoStreamNum ;
s32_le audioCodec ;
s32_le audioStreamNum ;
s32_le playMode ;
s32_le playSpeed ;
2012-11-13 18:05:26 +01:00
} ;
2014-04-20 13:48:45 -07:00
struct PsmfInfo {
2014-05-11 21:51:28 -07:00
u32_le lastFrameTS ;
2014-04-20 13:48:45 -07:00
s32_le numVideoStreams ;
s32_le numAudioStreams ;
s32_le numPCMStreams ;
s32_le playerVersion ;
} ;
2014-04-25 23:40:22 -07:00
struct PsmfVideoData {
s32_le frameWidth ;
u32_le displaybuf ;
u32_le displaypts ;
} ;
2012-11-13 18:05:26 +01:00
struct PsmfEntry {
int EPPts ;
int EPOffset ;
2014-01-01 13:23:19 -08:00
int EPIndex ;
int EPPicOffset ;
2012-11-13 18:05:26 +01:00
} ;
2014-06-05 01:08:57 -07:00
// Some of our platforms don't play too nice with direct unaligned access.
2014-12-08 04:40:08 -05:00
static u32 ReadUnalignedU32BE ( const u8 * p ) {
2014-06-05 01:08:57 -07:00
return ( p [ 0 ] < < 24 ) | ( p [ 1 ] < < 16 ) | ( p [ 2 ] < < 8 ) | ( p [ 3 ] < < 0 ) ;
}
2012-11-13 18:05:26 +01:00
class PsmfStream ;
// This does NOT match the raw structure. Due to endianness etc,
// we read it manually.
// TODO: Change to work directly with the data in RAM instead of this
// JPSCP-esque class.
2012-12-29 03:19:13 -08:00
typedef std : : map < int , PsmfStream * > PsmfStreamMap ;
2013-01-05 18:10:13 +01:00
2012-12-29 03:19:13 -08:00
class Psmf {
public :
2013-02-04 01:31:02 -08:00
// For savestates only.
Psmf ( ) { }
2014-05-15 00:10:01 -07:00
Psmf ( const u8 * ptr , u32 data ) ;
2012-12-29 03:19:13 -08:00
~ Psmf ( ) ;
void DoState ( PointerWrap & p ) ;
2013-06-05 21:24:14 +02:00
2014-12-03 15:16:11 -05:00
bool isValidCurrentStreamNumber ( ) const {
2016-05-30 23:26:55 -07:00
return currentStreamNum > = 0 & & streamMap . find ( currentStreamNum ) ! = streamMap . end ( ) ;
2013-06-05 21:24:14 +02:00
}
2016-05-31 00:53:40 -07:00
bool setStreamNum ( int num ) ;
2013-06-05 21:24:14 +02:00
bool setStreamWithType ( int type , int channel ) ;
2016-05-30 23:54:21 -07:00
bool setStreamWithTypeNumber ( int type , int n ) ;
2012-12-29 03:19:13 -08:00
2014-12-07 17:00:14 -05:00
int FindEPWithTimestamp ( int pts ) const ;
2014-01-01 13:23:19 -08:00
2012-11-13 18:05:26 +01:00
u32 magic ;
u32 version ;
u32 streamOffset ;
u32 streamSize ;
2013-01-18 18:05:51 +08:00
u32 headerSize ;
2012-11-13 18:05:26 +01:00
u32 headerOffset ;
2013-01-18 18:05:51 +08:00
u32 streamType ;
u32 streamChannel ;
2012-11-13 18:05:26 +01:00
// 0x50
u32 streamDataTotalSize ;
u32 presentationStartTime ;
u32 presentationEndTime ;
u32 streamDataNextBlockSize ;
u32 streamDataNextInnerBlockSize ;
2013-01-18 18:05:51 +08:00
int numStreams ;
2012-11-13 18:05:26 +01:00
int currentStreamNum ;
2016-05-31 00:53:40 -07:00
int currentStreamType ;
int currentStreamChannel ;
2012-11-13 18:05:26 +01:00
int currentAudioStreamNum ;
int currentVideoStreamNum ;
// parameters gotten from streams
// I guess this is the seek information?
u32 EPMapOffset ;
u32 EPMapEntriesNum ;
int videoWidth ;
int videoHeight ;
int audioChannels ;
int audioFrequency ;
2014-01-01 13:23:19 -08:00
std : : vector < PsmfEntry > EPMap ;
2012-11-13 18:05:26 +01:00
2012-12-28 23:29:24 -08:00
PsmfStreamMap streamMap ;
2012-11-01 16:19:01 +01:00
} ;
2013-01-18 18:05:51 +08:00
class PsmfPlayer {
public :
2013-02-04 01:31:02 -08:00
// For savestates only.
2014-07-28 00:01:28 +02:00
PsmfPlayer ( ) : filehandle ( 0 ) , finishThread ( nullptr ) {
mediaengine = new MediaEngine ( ) ;
}
2014-04-20 00:01:16 -07:00
PsmfPlayer ( const PsmfPlayerCreateData * data ) ;
2014-07-28 00:01:28 +02:00
~ PsmfPlayer ( ) {
if ( mediaengine )
delete mediaengine ;
pspFileSystem . CloseFile ( filehandle ) ;
}
2013-01-19 21:05:05 +08:00
void DoState ( PointerWrap & p ) ;
2013-01-18 18:05:51 +08:00
2014-05-22 23:40:44 -07:00
void ScheduleFinish ( u32 handle ) {
if ( ! finishThread ) {
finishThread = new HLEHelperThread ( " scePsmfPlayer " , " scePsmfPlayer " , " __PsmfPlayerFinish " , playbackThreadPriority , 0x100 ) ;
finishThread - > Start ( handle , 0 ) ;
}
}
2014-07-28 00:01:28 +02:00
2014-05-22 23:40:44 -07:00
void AbortFinish ( ) {
if ( finishThread ) {
delete finishThread ;
2014-07-28 00:01:28 +02:00
finishThread = nullptr ;
2014-05-22 23:40:44 -07:00
}
}
2014-08-17 15:46:04 -07:00
bool HasReachedEnd ( ) {
bool videoPtsEnd = ( s64 ) psmfPlayerAvcAu . pts > = ( s64 ) totalDurationTimestamp - VIDEO_FRAME_DURATION_TS ;
// If we're out of video data and have no audio, it's over even if the pts isn't there yet.
return videoPtsEnd | | ( mediaengine - > IsVideoEnd ( ) & & mediaengine - > IsNoAudioData ( ) ) ;
}
2013-06-16 03:27:14 +08:00
u32 filehandle ;
2013-06-18 16:05:15 +08:00
u32 fileoffset ;
2013-06-27 23:46:26 +08:00
int readSize ;
int streamSize ;
2013-06-18 16:05:15 +08:00
u8 tempbuf [ 0x10000 ] ;
2013-06-16 03:27:14 +08:00
2013-01-18 18:05:51 +08:00
int videoCodec ;
2013-01-24 19:21:32 +08:00
int videoStreamNum ;
int audioCodec ;
int audioStreamNum ;
int playMode ;
int playSpeed ;
2014-05-11 21:51:28 -07:00
u64 totalDurationTimestamp ;
2013-01-18 18:05:51 +08:00
int displayBuffer ;
int displayBufferSize ;
int playbackThreadPriority ;
2014-04-20 11:53:59 -07:00
int totalVideoStreams ;
int totalAudioStreams ;
int playerVersion ;
2014-04-25 23:40:22 -07:00
int videoStep ;
2014-04-27 12:57:39 -07:00
int warmUp ;
2014-05-15 00:14:27 -07:00
s64 seekDestTimeStamp ;
2013-01-18 18:05:51 +08:00
SceMpegAu psmfPlayerAtracAu ;
SceMpegAu psmfPlayerAvcAu ;
2013-03-06 01:00:26 -08:00
PsmfPlayerStatus status ;
2013-06-02 01:30:51 +08:00
2014-05-22 23:40:44 -07:00
MediaEngine * mediaengine ;
HLEHelperThread * finishThread ;
2013-01-18 18:05:51 +08:00
} ;
2012-11-13 18:05:26 +01:00
class PsmfStream {
public :
2013-02-04 01:31:02 -08:00
// Used for save states.
PsmfStream ( ) {
}
2012-11-13 18:05:26 +01:00
PsmfStream ( int type , int channel ) {
this - > type = type ;
this - > channel = channel ;
}
2014-05-15 00:10:01 -07:00
void readMPEGVideoStreamParams ( const u8 * addr , const u8 * data , Psmf * psmf ) {
int streamId = addr [ 0 ] ;
int privateStreamId = addr [ 1 ] ;
2012-11-13 18:05:26 +01:00
// two unknowns here
2014-06-05 01:08:57 -07:00
psmf - > EPMapOffset = ReadUnalignedU32BE ( & addr [ 4 ] ) ;
psmf - > EPMapEntriesNum = ReadUnalignedU32BE ( & addr [ 8 ] ) ;
2014-05-15 00:10:01 -07:00
psmf - > videoWidth = addr [ 12 ] * 16 ;
psmf - > videoHeight = addr [ 13 ] * 16 ;
2012-11-13 18:05:26 +01:00
2014-01-01 13:23:19 -08:00
const u32 EP_MAP_STRIDE = 1 + 1 + 4 + 4 ;
psmf - > EPMap . clear ( ) ;
for ( u32 i = 0 ; i < psmf - > EPMapEntriesNum ; i + + ) {
2014-05-15 00:10:01 -07:00
const u8 * const entryAddr = data + psmf - > EPMapOffset + EP_MAP_STRIDE * i ;
2014-01-01 13:23:19 -08:00
PsmfEntry entry ;
2014-05-15 00:10:01 -07:00
entry . EPIndex = entryAddr [ 0 ] ;
entry . EPPicOffset = entryAddr [ 1 ] ;
2014-06-05 01:08:57 -07:00
entry . EPPts = ReadUnalignedU32BE ( & entryAddr [ 2 ] ) ;
entry . EPOffset = ReadUnalignedU32BE ( & entryAddr [ 6 ] ) ;
2014-01-01 13:23:19 -08:00
psmf - > EPMap . push_back ( entry ) ;
}
2013-09-07 22:02:55 +02:00
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 ) ;
2012-11-13 18:05:26 +01:00
}
2014-05-15 00:10:01 -07:00
void readPrivateAudioStreamParams ( const u8 * addr , Psmf * psmf ) {
int streamId = addr [ 0 ] ;
int privateStreamId = addr [ 1 ] ;
psmf - > audioChannels = addr [ 14 ] ;
psmf - > audioFrequency = addr [ 15 ] ;
2012-11-13 18:05:26 +01:00
// two unknowns here
2013-09-07 22:02:55 +02:00
INFO_LOG ( ME , " PSMF private audio found: id=%02x, privid=%02x, channels=%i, freq=%i " , streamId , privateStreamId , psmf - > audioChannels , psmf - > audioFrequency ) ;
2012-11-13 18:05:26 +01:00
}
2016-05-30 23:32:42 -07:00
bool matchesType ( int ty ) {
if ( ty = = PSMF_AUDIO_STREAM ) {
return type = = PSMF_ATRAC_STREAM | | type = = PSMF_PCM_STREAM ;
}
return type = = ty ;
}
2012-12-28 23:29:24 -08:00
void DoState ( PointerWrap & p ) {
2013-09-14 20:23:03 -07:00
auto s = p . Section ( " PsmfStream " , 1 ) ;
if ( ! s )
return ;
2012-12-29 03:19:13 -08:00
p . Do ( type ) ;
p . Do ( channel ) ;
2012-12-28 23:29:24 -08:00
}
2013-06-05 21:24:14 +02:00
2012-11-13 18:05:26 +01:00
int type ;
int channel ;
} ;
2014-05-15 00:10:01 -07:00
Psmf : : Psmf ( const u8 * ptr , u32 data ) {
2012-11-13 18:05:26 +01:00
headerOffset = data ;
2014-05-15 00:10:01 -07:00
magic = * ( u32_le * ) & ptr [ 0 ] ;
version = * ( u32_le * ) & ptr [ 4 ] ;
2014-06-05 01:08:57 -07:00
streamOffset = ReadUnalignedU32BE ( & ptr [ 8 ] ) ;
streamSize = ReadUnalignedU32BE ( & ptr [ 12 ] ) ;
streamDataTotalSize = ReadUnalignedU32BE ( & ptr [ 0x50 ] ) ;
2014-05-15 00:10:01 -07:00
presentationStartTime = getMpegTimeStamp ( ptr + PSMF_FIRST_TIMESTAMP_OFFSET ) ;
presentationEndTime = getMpegTimeStamp ( ptr + PSMF_LAST_TIMESTAMP_OFFSET ) ;
2014-06-05 01:08:57 -07:00
streamDataNextBlockSize = ReadUnalignedU32BE ( & ptr [ 0x6A ] ) ;
streamDataNextInnerBlockSize = ReadUnalignedU32BE ( & ptr [ 0x7C ] ) ;
2014-05-15 00:10:01 -07:00
numStreams = * ( u16_be * ) & ptr [ 0x80 ] ;
2014-01-01 13:24:05 -08:00
// TODO: Always?
headerSize = 0x800 ;
2012-11-13 18:05:26 +01:00
currentStreamNum = - 1 ;
2016-05-31 00:53:40 -07:00
currentStreamType = - 1 ;
currentStreamChannel = - 1 ;
2012-11-13 18:05:26 +01:00
currentAudioStreamNum = - 1 ;
currentVideoStreamNum = - 1 ;
for ( int i = 0 ; i < numStreams ; i + + ) {
PsmfStream * stream = 0 ;
2014-05-15 00:10:01 -07:00
const u8 * const currentStreamAddr = ptr + 0x82 + i * 16 ;
int streamId = currentStreamAddr [ 0 ] ;
2012-11-13 18:05:26 +01:00
if ( ( streamId & PSMF_VIDEO_STREAM_ID ) = = PSMF_VIDEO_STREAM_ID ) {
2016-05-30 23:55:13 -07:00
stream = new PsmfStream ( PSMF_AVC_STREAM , streamId & 0x0F ) ;
2014-05-15 00:10:01 -07:00
stream - > readMPEGVideoStreamParams ( currentStreamAddr , ptr , this ) ;
2012-11-13 18:05:26 +01:00
} else if ( ( streamId & PSMF_AUDIO_STREAM_ID ) = = PSMF_AUDIO_STREAM_ID ) {
2016-05-30 23:55:13 -07:00
int type = PSMF_ATRAC_STREAM ;
int privateStreamId = currentStreamAddr [ 1 ] ;
if ( ( privateStreamId & 0xF0 ) ! = 0 ) {
WARN_LOG_REPORT ( ME , " Unknown private stream type, assuming PCM: %02x " , privateStreamId ) ;
type = PSMF_PCM_STREAM ;
}
stream = new PsmfStream ( type , privateStreamId & 0x0F ) ;
2012-11-13 18:05:26 +01:00
stream - > readPrivateAudioStreamParams ( currentStreamAddr , this ) ;
}
if ( stream ) {
currentStreamNum + + ;
streamMap [ currentStreamNum ] = stream ;
}
}
2016-05-31 00:52:28 -07:00
// Default to the first stream.
currentStreamNum = 0 ;
2012-11-13 18:05:26 +01:00
}
2012-12-28 23:29:24 -08:00
Psmf : : ~ Psmf ( ) {
for ( auto it = streamMap . begin ( ) , end = streamMap . end ( ) ; it ! = end ; + + it ) {
delete it - > second ;
}
streamMap . clear ( ) ;
}
2014-04-20 00:01:16 -07:00
PsmfPlayer : : PsmfPlayer ( const PsmfPlayerCreateData * data ) {
2014-04-20 20:21:37 -07:00
videoCodec = - 1 ;
videoStreamNum = - 1 ;
audioCodec = - 1 ;
audioStreamNum = - 1 ;
2014-04-20 00:01:16 -07:00
playMode = 0 ;
2014-04-25 20:30:05 -07:00
playSpeed = 1 ;
2014-05-11 21:51:28 -07:00
totalDurationTimestamp = 0 ;
2013-03-06 01:00:26 -08:00
status = PSMF_PLAYER_STATUS_INIT ;
2013-06-02 01:30:51 +08:00
mediaengine = new MediaEngine ;
2014-07-28 00:01:28 +02:00
finishThread = nullptr ;
2013-06-16 03:27:14 +08:00
filehandle = 0 ;
2013-06-18 16:05:15 +08:00
fileoffset = 0 ;
2013-06-27 23:46:26 +08:00
readSize = 0 ;
streamSize = 0 ;
2014-04-25 23:40:22 -07:00
videoStep = 0 ;
2014-04-27 12:57:39 -07:00
warmUp = 0 ;
2014-05-15 00:14:27 -07:00
seekDestTimeStamp = 0 ;
2014-04-20 00:01:16 -07:00
2014-05-11 21:51:28 -07:00
psmfPlayerAtracAu . dts = - 1 ;
psmfPlayerAtracAu . pts = - 1 ;
psmfPlayerAvcAu . dts = - 1 ;
psmfPlayerAvcAu . pts = - 1 ;
2014-04-20 00:01:16 -07:00
displayBuffer = data - > buffer . ptr ;
displayBufferSize = data - > bufferSize ;
playbackThreadPriority = data - > threadPriority ;
2013-01-18 18:05:51 +08:00
}
2012-12-28 23:29:24 -08:00
void Psmf : : DoState ( PointerWrap & p ) {
2016-05-31 00:53:40 -07:00
auto s = p . Section ( " Psmf " , 1 , 3 ) ;
2013-09-14 20:23:03 -07:00
if ( ! s )
return ;
2012-12-29 03:19:13 -08:00
p . Do ( magic ) ;
p . Do ( version ) ;
p . Do ( streamOffset ) ;
p . Do ( streamSize ) ;
p . Do ( headerOffset ) ;
p . Do ( streamDataTotalSize ) ;
p . Do ( presentationStartTime ) ;
p . Do ( presentationEndTime ) ;
p . Do ( streamDataNextBlockSize ) ;
p . Do ( streamDataNextInnerBlockSize ) ;
p . Do ( numStreams ) ;
p . Do ( currentStreamNum ) ;
p . Do ( currentAudioStreamNum ) ;
p . Do ( currentVideoStreamNum ) ;
p . Do ( EPMapOffset ) ;
p . Do ( EPMapEntriesNum ) ;
p . Do ( videoWidth ) ;
p . Do ( videoHeight ) ;
p . Do ( audioChannels ) ;
p . Do ( audioFrequency ) ;
2012-12-28 23:29:24 -08:00
2014-01-01 13:23:19 -08:00
if ( s > = 2 ) {
p . Do ( EPMap ) ;
}
2013-02-04 01:31:02 -08:00
p . Do ( streamMap ) ;
2016-05-31 00:53:40 -07:00
if ( s > = 3 ) {
p . Do ( currentStreamType ) ;
p . Do ( currentStreamChannel ) ;
} else {
currentStreamType = - 1 ;
currentStreamChannel = - 1 ;
auto streamInfo = streamMap . find ( currentStreamNum ) ;
if ( streamInfo ! = streamMap . end ( ) ) {
currentStreamType = streamInfo - > second - > type ;
currentStreamChannel = streamInfo - > second - > channel ;
}
}
2012-12-28 23:29:24 -08:00
}
2013-01-19 21:05:05 +08:00
void PsmfPlayer : : DoState ( PointerWrap & p ) {
2014-07-25 09:19:07 -07:00
auto s = p . Section ( " PsmfPlayer " , 1 , 7 ) ;
2013-09-14 20:23:03 -07:00
if ( ! s )
return ;
2013-01-19 21:05:05 +08:00
p . Do ( videoCodec ) ;
2013-01-24 19:40:26 +08:00
p . Do ( videoStreamNum ) ;
p . Do ( audioCodec ) ;
p . Do ( audioStreamNum ) ;
p . Do ( playMode ) ;
p . Do ( playSpeed ) ;
2013-01-19 21:05:05 +08:00
p . Do ( displayBuffer ) ;
p . Do ( displayBufferSize ) ;
p . Do ( playbackThreadPriority ) ;
2015-12-23 15:22:28 -08:00
int oldMaxAheadTimestamp = 0 ;
p . Do ( oldMaxAheadTimestamp ) ;
2014-04-27 12:57:39 -07:00
if ( s > = 4 ) {
2014-05-11 21:51:28 -07:00
p . Do ( totalDurationTimestamp ) ;
2014-04-27 12:57:39 -07:00
} else {
long oldTimestamp ;
p . Do ( oldTimestamp ) ;
2014-05-11 21:51:28 -07:00
totalDurationTimestamp = oldTimestamp ;
2014-04-27 12:57:39 -07:00
}
2014-04-20 11:53:59 -07:00
if ( s > = 2 ) {
p . Do ( totalVideoStreams ) ;
p . Do ( totalAudioStreams ) ;
p . Do ( playerVersion ) ;
2014-04-25 23:40:22 -07:00
} else {
totalVideoStreams = 1 ;
totalAudioStreams = 1 ;
playerVersion = PSMF_PLAYER_VERSION_FULL ;
}
if ( s > = 3 ) {
p . Do ( videoStep ) ;
} else {
videoStep = 0 ;
2014-04-20 11:53:59 -07:00
}
2014-04-27 12:57:39 -07:00
if ( s > = 4 ) {
p . Do ( warmUp ) ;
} else {
warmUp = 10000 ;
}
2014-05-15 00:14:27 -07:00
if ( s > = 5 ) {
p . Do ( seekDestTimeStamp ) ;
} else {
seekDestTimeStamp = 0 ;
}
2013-06-02 01:30:51 +08:00
p . DoClass ( mediaengine ) ;
2013-06-16 03:27:14 +08:00
p . Do ( filehandle ) ;
2013-06-18 16:05:15 +08:00
p . Do ( fileoffset ) ;
2013-06-27 23:46:26 +08:00
p . Do ( readSize ) ;
p . Do ( streamSize ) ;
2013-01-19 21:05:05 +08:00
2013-06-18 04:08:48 +08:00
p . Do ( status ) ;
2014-04-27 12:57:39 -07:00
if ( s > = 4 ) {
p . Do ( psmfPlayerAtracAu ) ;
}
2013-06-18 04:08:48 +08:00
p . Do ( psmfPlayerAvcAu ) ;
2014-12-03 12:49:04 -08:00
if ( s > = 7 ) {
2014-07-25 09:19:07 -07:00
bool hasFinishThread = finishThread ! = NULL ;
p . Do ( hasFinishThread ) ;
if ( hasFinishThread ) {
p . Do ( finishThread ) ;
}
} else if ( s > = 6 ) {
2014-05-22 23:40:44 -07:00
p . Do ( finishThread ) ;
} else {
finishThread = NULL ;
}
2013-01-19 21:05:05 +08:00
}
2016-05-31 00:53:40 -07:00
bool Psmf : : setStreamNum ( int num ) {
2013-06-05 21:24:14 +02:00
currentStreamNum = num ;
2016-05-31 00:53:40 -07:00
currentStreamType = - 1 ;
currentStreamChannel = - 1 ;
2013-06-05 21:24:14 +02:00
if ( ! isValidCurrentStreamNumber ( ) )
2016-05-31 00:53:40 -07:00
return false ;
2013-06-05 21:24:14 +02:00
PsmfStreamMap : : iterator iter = streamMap . find ( currentStreamNum ) ;
if ( iter = = streamMap . end ( ) )
2016-05-31 00:53:40 -07:00
return false ;
2013-06-05 21:24:14 +02:00
2016-05-31 00:53:40 -07:00
// TODO: This information is *probably* only for the scePsmf lookups?
// Not sure if we need to communicate with the media engine.
2013-06-05 21:24:14 +02:00
int type = iter - > second - > type ;
switch ( type ) {
case PSMF_AVC_STREAM :
2016-05-31 00:53:40 -07:00
currentVideoStreamNum = num ;
2013-06-05 21:24:14 +02:00
break ;
case PSMF_ATRAC_STREAM :
case PSMF_PCM_STREAM :
2016-05-31 00:53:40 -07:00
currentAudioStreamNum = num ;
2013-06-05 21:24:14 +02:00
break ;
}
2016-05-31 00:53:40 -07:00
currentStreamType = type ;
currentStreamChannel = iter - > second - > channel ;
return true ;
2013-06-05 21:24:14 +02:00
}
bool Psmf : : setStreamWithType ( int type , int channel ) {
2016-05-30 23:54:21 -07:00
for ( auto iter : streamMap ) {
2016-05-31 00:53:40 -07:00
// Note: this does NOT support PSMF_AUDIO_STREAM.
if ( iter . second - > type = = type & & iter . second - > channel = = channel ) {
return setStreamNum ( iter . first ) ;
2016-05-30 23:54:21 -07:00
}
}
return false ;
}
bool Psmf : : setStreamWithTypeNumber ( int type , int n ) {
for ( auto iter : streamMap ) {
if ( iter . second - > matchesType ( type ) ) {
if ( n ! = 0 ) {
// Keep counting...
n - - ;
continue ;
}
// Okay, this is the one.
2016-05-31 00:53:40 -07:00
return setStreamNum ( iter . first ) ;
2013-06-05 21:24:14 +02:00
}
}
return false ;
}
2014-12-07 17:00:14 -05:00
int Psmf : : FindEPWithTimestamp ( int pts ) const {
2014-01-01 13:23:19 -08:00
int best = - 1 ;
int bestPts = 0 ;
for ( int i = 0 ; i < ( int ) EPMap . size ( ) ; + + i ) {
const int matchPts = EPMap [ i ] . EPPts ;
if ( matchPts = = pts ) {
// Exact match, take it.
return i ;
}
// TODO: Does it actually do fuzzy matching?
if ( matchPts < pts & & matchPts > = bestPts ) {
best = i ;
bestPts = matchPts ;
}
}
return best ;
}
2013-06-05 21:24:14 +02:00
2013-01-06 22:15:47 -08:00
static std : : map < u32 , Psmf * > psmfMap ;
2013-01-18 18:05:51 +08:00
static std : : map < u32 , PsmfPlayer * > psmfPlayerMap ;
2012-11-13 18:05:26 +01:00
2014-12-08 04:40:08 -05:00
static Psmf * getPsmf ( u32 psmf )
2012-12-24 10:44:40 -08:00
{
2013-12-16 23:47:34 -08:00
auto psmfstruct = PSPPointer < PsmfData > : : Create ( psmf ) ;
2013-07-01 03:52:35 +08:00
if ( ! psmfstruct . IsValid ( ) )
return 0 ;
auto iter = psmfMap . find ( psmfstruct - > headerOffset ) ;
2012-11-13 18:05:26 +01:00
if ( iter ! = psmfMap . end ( ) )
return iter - > second ;
else
return 0 ;
}
2014-12-08 04:40:08 -05:00
static PsmfPlayer * getPsmfPlayer ( u32 psmfplayer )
2013-01-18 18:05:51 +08:00
{
2014-04-20 08:22:51 -07:00
auto iter = psmfPlayerMap . find ( Memory : : Read_U32 ( psmfplayer ) ) ;
2013-01-18 18:05:51 +08:00
if ( iter ! = psmfPlayerMap . end ( ) )
return iter - > second ;
else
return 0 ;
}
2012-12-24 10:44:40 -08:00
void __PsmfInit ( )
{
2014-02-14 10:43:53 +08:00
videoPixelMode = GE_CMODE_32BIT_ABGR8888 ;
2013-09-22 21:19:59 -07:00
videoLoopStatus = PSMF_PLAYER_CONFIG_NO_LOOP ;
2012-12-24 10:44:40 -08:00
}
2012-12-28 23:29:24 -08:00
void __PsmfDoState ( PointerWrap & p )
{
2013-09-14 20:23:03 -07:00
auto s = p . Section ( " scePsmf " , 1 ) ;
if ( ! s )
return ;
2012-12-28 23:29:24 -08:00
2013-09-14 20:23:03 -07:00
p . Do ( psmfMap ) ;
2012-12-28 23:29:24 -08:00
}
2013-01-20 16:16:57 +08:00
void __PsmfPlayerDoState ( PointerWrap & p )
{
2013-09-14 20:23:03 -07:00
auto s = p . Section ( " scePsmfPlayer " , 1 ) ;
if ( ! s )
return ;
2013-02-04 01:31:02 -08:00
p . Do ( psmfPlayerMap ) ;
2013-06-27 23:46:26 +08:00
p . Do ( videoPixelMode ) ;
p . Do ( videoLoopStatus ) ;
2013-01-20 16:16:57 +08:00
}
2012-12-24 10:44:40 -08:00
void __PsmfShutdown ( )
{
for ( auto it = psmfMap . begin ( ) , end = psmfMap . end ( ) ; it ! = end ; + + it )
delete it - > second ;
2013-03-06 01:00:26 -08:00
for ( auto it = psmfPlayerMap . begin ( ) , end = psmfPlayerMap . end ( ) ; it ! = end ; + + it )
delete it - > second ;
2012-12-24 10:44:40 -08:00
psmfMap . clear ( ) ;
2013-03-06 01:00:26 -08:00
psmfPlayerMap . clear ( ) ;
2012-12-24 10:44:40 -08:00
}
2012-11-01 16:19:01 +01:00
2014-12-08 04:40:08 -05:00
static u32 scePsmfSetPsmf ( u32 psmfStruct , u32 psmfData )
2012-11-01 16:19:01 +01:00
{
2014-05-15 01:11:50 -07:00
if ( ! Memory : : IsValidAddress ( psmfData ) ) {
// TODO: Check error code.
ERROR_LOG_REPORT ( ME , " scePsmfSetPsmf(%08x, %08x): bad address " , psmfStruct , psmfData ) ;
return SCE_KERNEL_ERROR_ILLEGAL_ADDRESS ;
}
2013-09-07 22:02:55 +02:00
INFO_LOG ( ME , " scePsmfSetPsmf(%08x, %08x) " , psmfStruct , psmfData ) ;
2012-11-13 18:05:26 +01:00
2014-05-15 00:10:01 -07:00
Psmf * psmf = new Psmf ( Memory : : GetPointer ( psmfData ) , psmfData ) ;
2012-11-13 18:05:26 +01:00
2012-12-24 10:44:40 -08:00
PsmfData data = { 0 } ;
data . version = psmf - > version ;
data . headerSize = 0x800 ;
2012-11-13 18:05:26 +01:00
data . streamSize = psmf - > streamSize ;
data . streamNum = psmf - > numStreams ;
2013-07-01 04:25:04 +08:00
data . headerOffset = psmf - > headerOffset ;
2013-07-01 04:17:09 +08:00
auto iter = psmfMap . find ( data . headerOffset ) ;
if ( iter ! = psmfMap . end ( ) )
delete iter - > second ;
2013-07-01 03:52:35 +08:00
psmfMap [ data . headerOffset ] = psmf ;
2012-12-24 10:44:40 -08:00
Memory : : WriteStruct ( psmfStruct , & data ) ;
return 0 ;
2012-11-01 16:19:01 +01:00
}
2016-05-30 23:32:42 -07:00
static u32 scePsmfGetNumberOfStreams ( u32 psmfStruct ) {
2012-11-13 18:05:26 +01:00
Psmf * psmf = getPsmf ( psmfStruct ) ;
if ( ! psmf ) {
2016-05-30 23:32:42 -07:00
return hleLogError ( ME , ERROR_PSMF_NOT_INITIALIZED , " invalid psmf " ) ;
2012-11-13 18:05:26 +01:00
}
2016-05-30 23:32:42 -07:00
return hleLogSuccessI ( ME , psmf - > numStreams ) ;
2012-11-01 16:19:01 +01:00
}
2016-05-30 23:32:42 -07:00
static u32 scePsmfGetNumberOfSpecificStreams ( u32 psmfStruct , int streamType ) {
2012-11-13 18:05:26 +01:00
Psmf * psmf = getPsmf ( psmfStruct ) ;
if ( ! psmf ) {
2016-05-30 23:32:42 -07:00
return hleLogError ( ME , ERROR_PSMF_NOT_INITIALIZED , " invalid psmf " ) ;
2012-11-13 18:05:26 +01:00
}
2016-05-30 23:32:42 -07:00
2013-06-15 01:39:56 +08:00
int streamNum = 0 ;
2016-05-30 23:26:55 -07:00
for ( auto it : psmf - > streamMap ) {
2016-05-30 23:32:42 -07:00
bool match = false ;
if ( it . second - > matchesType ( streamType ) ) {
2013-06-15 01:39:56 +08:00
streamNum + + ;
2016-05-30 23:32:42 -07:00
}
2013-06-15 01:39:56 +08:00
}
2016-05-30 23:32:42 -07:00
return hleLogSuccessI ( ME , streamNum ) ;
2012-11-01 16:19:01 +01:00
}
2016-05-31 00:53:40 -07:00
static u32 scePsmfSpecifyStreamWithStreamType ( u32 psmfStruct , u32 streamType , u32 channel ) {
2013-06-05 21:24:14 +02:00
Psmf * psmf = getPsmf ( psmfStruct ) ;
if ( ! psmf ) {
2016-05-31 00:53:40 -07:00
return hleLogError ( ME , ERROR_PSMF_NOT_INITIALIZED , " invalid psmf " ) ;
2013-06-05 21:24:14 +02:00
}
if ( ! psmf - > setStreamWithType ( streamType , channel ) ) {
2016-05-31 00:53:40 -07:00
// An invalid type seems to make the stream number invalid, but retain the old type/channel.
psmf - > currentStreamNum = ERROR_PSMF_INVALID_ID ;
// Also, returns 0 even when no stream found.
return hleLogWarning ( ME , 0 , " no stream found " ) ;
2013-06-05 21:24:14 +02:00
}
2016-05-31 00:53:40 -07:00
return hleLogSuccessI ( ME , 0 ) ;
2012-11-01 16:19:01 +01:00
}
2016-05-31 00:53:40 -07:00
static u32 scePsmfSpecifyStreamWithStreamTypeNumber ( u32 psmfStruct , u32 streamType , u32 typeNum ) {
2013-06-05 21:24:14 +02:00
Psmf * psmf = getPsmf ( psmfStruct ) ;
if ( ! psmf ) {
2016-05-31 00:53:40 -07:00
return hleLogError ( ME , ERROR_PSMF_NOT_INITIALIZED , " invalid psmf " ) ;
2013-06-05 21:24:14 +02:00
}
2016-05-30 23:54:21 -07:00
if ( ! psmf - > setStreamWithTypeNumber ( streamType , typeNum ) ) {
2016-05-31 00:53:40 -07:00
// Don't update stream, just bail out.
return hleLogWarning ( ME , ERROR_PSMF_INVALID_ID , " no stream found " ) ;
2013-07-01 14:02:12 +08:00
}
2016-05-31 00:53:40 -07:00
return hleLogSuccessI ( ME , 0 ) ;
2012-12-17 18:48:32 +01:00
}
2014-12-08 04:40:08 -05:00
static u32 scePsmfSpecifyStream ( u32 psmfStruct , int streamNum ) {
2013-06-05 21:24:14 +02:00
Psmf * psmf = getPsmf ( psmfStruct ) ;
if ( ! psmf ) {
2016-05-31 00:53:40 -07:00
return hleLogError ( ME , ERROR_PSMF_NOT_INITIALIZED , " invalid psmf " ) ;
2013-06-05 21:24:14 +02:00
}
2016-05-31 00:53:40 -07:00
if ( ! psmf - > setStreamNum ( streamNum ) ) {
psmf - > setStreamNum ( ERROR_PSMF_NOT_INITIALIZED ) ;
return hleLogWarning ( ME , ERROR_PSMF_INVALID_ID , " bad stream id " ) ;
}
return hleLogSuccessI ( ME , 0 ) ;
2013-06-05 19:56:36 +02:00
}
2014-12-08 04:40:08 -05:00
static u32 scePsmfGetVideoInfo ( u32 psmfStruct , u32 videoInfoAddr ) {
2012-11-13 18:05:26 +01:00
Psmf * psmf = getPsmf ( psmfStruct ) ;
if ( ! psmf ) {
2013-09-07 22:02:55 +02:00
ERROR_LOG ( ME , " scePsmfGetVideoInfo(%08x, %08x): invalid psmf " , psmfStruct , videoInfoAddr ) ;
2012-11-13 18:05:26 +01:00
return ERROR_PSMF_NOT_FOUND ;
}
2013-09-07 22:02:55 +02:00
INFO_LOG ( ME , " scePsmfGetVideoInfo(%08x, %08x) " , psmfStruct , videoInfoAddr ) ;
2012-11-13 18:05:26 +01:00
if ( Memory : : IsValidAddress ( videoInfoAddr ) ) {
Memory : : Write_U32 ( psmf - > videoWidth , videoInfoAddr ) ;
2013-06-13 22:12:16 -07:00
Memory : : Write_U32 ( psmf - > videoHeight , videoInfoAddr + 4 ) ;
2012-11-13 18:05:26 +01:00
}
2012-12-24 10:44:40 -08:00
return 0 ;
2012-11-13 18:05:26 +01:00
}
2014-12-08 04:40:08 -05:00
static u32 scePsmfGetAudioInfo ( u32 psmfStruct , u32 audioInfoAddr ) {
2012-11-13 18:05:26 +01:00
Psmf * psmf = getPsmf ( psmfStruct ) ;
if ( ! psmf ) {
2013-09-07 22:02:55 +02:00
ERROR_LOG ( ME , " scePsmfGetAudioInfo(%08x, %08x): invalid psmf " , psmfStruct , audioInfoAddr ) ;
2012-11-13 18:05:26 +01:00
return ERROR_PSMF_NOT_FOUND ;
}
2013-09-07 22:02:55 +02:00
INFO_LOG ( ME , " scePsmfGetAudioInfo(%08x, %08x) " , psmfStruct , audioInfoAddr ) ;
2012-11-13 18:05:26 +01:00
if ( Memory : : IsValidAddress ( audioInfoAddr ) ) {
Memory : : Write_U32 ( psmf - > audioChannels , audioInfoAddr ) ;
Memory : : Write_U32 ( psmf - > audioFrequency , audioInfoAddr + 4 ) ;
}
2012-12-24 10:44:40 -08:00
return 0 ;
2012-11-13 18:05:26 +01:00
}
2014-12-08 04:40:08 -05:00
static u32 scePsmfGetCurrentStreamType ( u32 psmfStruct , u32 typeAddr , u32 channelAddr ) {
2013-01-05 18:10:13 +01:00
Psmf * psmf = getPsmf ( psmfStruct ) ;
if ( ! psmf ) {
2016-05-31 00:54:26 -07:00
return hleLogError ( ME , ERROR_PSMF_NOT_INITIALIZED , " invalid psmf " ) ;
2013-01-05 18:10:13 +01:00
}
2016-05-31 00:54:26 -07:00
if ( psmf - > currentStreamNum = = ERROR_PSMF_NOT_INITIALIZED ) {
return hleLogError ( ME , ERROR_PSMF_NOT_INITIALIZED , " no stream set " ) ;
2013-01-05 18:10:13 +01:00
}
2016-05-31 00:54:26 -07:00
if ( ! Memory : : IsValidAddress ( typeAddr ) | | ! Memory : : IsValidAddress ( channelAddr ) ) {
return hleLogError ( ME , SCE_KERNEL_ERROR_ILLEGAL_ADDRESS , " bad pointers " ) ;
}
if ( psmf - > currentStreamType ! = - 1 ) {
Memory : : Write_U32 ( psmf - > currentStreamType , typeAddr ) ;
Memory : : Write_U32 ( psmf - > currentStreamChannel , channelAddr ) ;
}
return hleLogSuccessI ( ME , 0 ) ;
2013-01-05 18:10:13 +01:00
}
2012-11-13 18:05:26 +01:00
2014-12-08 04:40:08 -05:00
static u32 scePsmfGetStreamSize ( u32 psmfStruct , u32 sizeAddr )
2013-01-18 18:05:51 +08:00
{
Psmf * psmf = getPsmf ( psmfStruct ) ;
if ( ! psmf ) {
2013-09-07 22:02:55 +02:00
ERROR_LOG ( ME , " scePsmfGetStreamSize(%08x, %08x): invalid psmf " , psmfStruct , sizeAddr ) ;
2013-01-18 18:05:51 +08:00
return ERROR_PSMF_NOT_FOUND ;
}
2013-09-07 22:02:55 +02:00
DEBUG_LOG ( ME , " scePsmfGetStreamSize(%08x, %08x) " , psmfStruct , sizeAddr ) ;
2013-01-18 18:05:51 +08:00
if ( Memory : : IsValidAddress ( sizeAddr ) ) {
Memory : : Write_U32 ( psmf - > streamSize , sizeAddr ) ;
}
return 0 ;
}
2014-12-08 04:40:08 -05:00
static u32 scePsmfQueryStreamOffset ( u32 bufferAddr , u32 offsetAddr )
2013-03-29 01:05:11 -07:00
{
2013-09-07 22:02:55 +02:00
WARN_LOG ( ME , " scePsmfQueryStreamOffset(%08x, %08x) " , bufferAddr , offsetAddr ) ;
2013-03-29 01:05:11 -07:00
if ( Memory : : IsValidAddress ( offsetAddr ) ) {
2013-10-28 17:23:51 +01:00
Memory : : Write_U32 ( bswap32 ( Memory : : Read_U32 ( bufferAddr + PSMF_STREAM_OFFSET_OFFSET ) ) , offsetAddr ) ;
2013-03-29 01:05:11 -07:00
}
2013-06-07 01:27:15 -07:00
return 0 ;
2013-03-29 01:05:11 -07:00
}
2014-12-08 04:40:08 -05:00
static u32 scePsmfQueryStreamSize ( u32 bufferAddr , u32 sizeAddr )
2013-03-29 01:05:11 -07:00
{
2013-09-07 22:02:55 +02:00
WARN_LOG ( ME , " scePsmfQueryStreamSize(%08x, %08x) " , bufferAddr , sizeAddr ) ;
2013-03-29 01:05:11 -07:00
if ( Memory : : IsValidAddress ( sizeAddr ) ) {
2013-10-28 17:23:51 +01:00
Memory : : Write_U32 ( bswap32 ( Memory : : Read_U32 ( bufferAddr + PSMF_STREAM_SIZE_OFFSET ) ) , sizeAddr ) ;
2013-03-29 01:05:11 -07:00
}
return 0 ;
}
2014-12-08 04:40:08 -05:00
static u32 scePsmfGetHeaderSize ( u32 psmfStruct , u32 sizeAddr )
2013-01-18 18:05:51 +08:00
{
Psmf * psmf = getPsmf ( psmfStruct ) ;
if ( ! psmf ) {
2013-09-07 22:02:55 +02:00
ERROR_LOG ( ME , " scePsmfGetHeaderSize(%08x, %08x): invalid psmf " , psmfStruct , sizeAddr ) ;
2013-01-18 18:05:51 +08:00
return ERROR_PSMF_NOT_FOUND ;
}
2013-09-07 22:02:55 +02:00
DEBUG_LOG ( ME , " scePsmfGetHeaderSize(%08x, %08x) " , psmfStruct , sizeAddr ) ;
2013-01-18 18:05:51 +08:00
if ( Memory : : IsValidAddress ( sizeAddr ) ) {
Memory : : Write_U32 ( psmf - > headerSize , sizeAddr ) ;
}
return 0 ;
}
2014-12-08 04:40:08 -05:00
static u32 scePsmfGetPsmfVersion ( u32 psmfStruct )
2013-01-18 18:05:51 +08:00
{
Psmf * psmf = getPsmf ( psmfStruct ) ;
if ( ! psmf ) {
2014-01-01 13:31:47 -08:00
ERROR_LOG ( ME , " scePsmfGetPsmfVersion(%08x): invalid psmf " , psmfStruct ) ;
2013-01-18 18:05:51 +08:00
return ERROR_PSMF_NOT_FOUND ;
}
2013-09-07 22:02:55 +02:00
DEBUG_LOG ( ME , " scePsmfGetPsmfVersion(%08x) " , psmfStruct ) ;
2013-01-18 18:05:51 +08:00
return psmf - > version ;
}
2014-12-08 04:40:08 -05:00
static u32 scePsmfVerifyPsmf ( u32 psmfAddr )
2013-01-29 01:28:51 +01:00
{
2013-07-07 18:10:55 -07:00
u32 magic = Memory : : Read_U32 ( psmfAddr ) ;
2013-06-14 07:15:57 +08:00
if ( magic ! = PSMF_MAGIC ) {
2013-09-07 22:02:55 +02:00
ERROR_LOG ( ME , " scePsmfVerifyPsmf(%08x): bad magic %08x " , psmfAddr , magic ) ;
2013-06-14 07:15:57 +08:00
return ERROR_PSMF_NOT_FOUND ;
}
int version = Memory : : Read_U32 ( psmfAddr + PSMF_STREAM_VERSION_OFFSET ) ;
if ( version < 0 ) {
2013-09-07 22:02:55 +02:00
ERROR_LOG ( ME , " scePsmfVerifyPsmf(%08x): bad version %08x " , psmfAddr , version ) ;
2013-06-14 07:15:57 +08:00
return ERROR_PSMF_NOT_FOUND ;
}
2014-03-02 01:15:00 -08:00
// Kurohyou 2 (at least the demo) uses an uninitialized value that happens to be zero on the PSP.
// It appears to be written by scePsmfVerifyPsmf(), so we write some bytes into the stack here.
Memory : : Memset ( currentMIPS - > r [ MIPS_REG_SP ] - 0x20 , 0 , 0x20 ) ;
2013-09-07 22:02:55 +02:00
DEBUG_LOG ( ME , " scePsmfVerifyPsmf(%08x) " , psmfAddr ) ;
2013-01-29 01:28:51 +01:00
return 0 ;
}
2014-12-08 04:40:08 -05:00
static u32 scePsmfGetNumberOfEPentries ( u32 psmfStruct )
2013-01-18 18:05:51 +08:00
{
Psmf * psmf = getPsmf ( psmfStruct ) ;
if ( ! psmf ) {
2013-09-07 22:02:55 +02:00
ERROR_LOG ( ME , " scePsmfGetNumberOfEPentries(%08x): invalid psmf " , psmfStruct ) ;
2013-01-18 18:05:51 +08:00
return ERROR_PSMF_NOT_FOUND ;
}
2013-09-07 22:02:55 +02:00
DEBUG_LOG ( ME , " scePsmfGetNumberOfEPentries(%08x) " , psmfStruct ) ;
2013-01-18 18:05:51 +08:00
return psmf - > EPMapEntriesNum ;
}
2014-12-08 04:40:08 -05:00
static u32 scePsmfGetPresentationStartTime ( u32 psmfStruct , u32 startTimeAddr )
2013-01-18 18:05:51 +08:00
{
Psmf * psmf = getPsmf ( psmfStruct ) ;
if ( ! psmf ) {
2013-09-07 22:02:55 +02:00
ERROR_LOG ( ME , " scePsmfGetPresentationStartTime(%08x, %08x): invalid psmf " , psmfStruct , startTimeAddr ) ;
2013-01-18 18:05:51 +08:00
return ERROR_PSMF_NOT_FOUND ;
}
2013-09-07 22:02:55 +02:00
DEBUG_LOG ( ME , " scePsmfGetPresentationStartTime(%08x, %08x) " , psmfStruct , startTimeAddr ) ;
2013-01-18 18:05:51 +08:00
if ( Memory : : IsValidAddress ( startTimeAddr ) ) {
Memory : : Write_U32 ( psmf - > presentationStartTime , startTimeAddr ) ;
}
return 0 ;
}
2014-12-08 04:40:08 -05:00
static u32 scePsmfGetPresentationEndTime ( u32 psmfStruct , u32 endTimeAddr )
2013-01-18 18:05:51 +08:00
{
Psmf * psmf = getPsmf ( psmfStruct ) ;
if ( ! psmf ) {
2013-09-07 22:02:55 +02:00
ERROR_LOG ( ME , " scePsmfGetPresentationEndTime(%08x, %08x): invalid psmf " , psmfStruct , endTimeAddr ) ;
2013-01-18 18:05:51 +08:00
return ERROR_PSMF_NOT_FOUND ;
}
2013-09-07 22:02:55 +02:00
DEBUG_LOG ( ME , " scePsmfGetPresentationEndTime(%08x, %08x) " , psmfStruct , endTimeAddr ) ;
2013-01-18 18:05:51 +08:00
if ( Memory : : IsValidAddress ( endTimeAddr ) ) {
Memory : : Write_U32 ( psmf - > presentationEndTime , endTimeAddr ) ;
}
return 0 ;
}
2016-05-31 00:55:11 -07:00
static u32 scePsmfGetCurrentStreamNumber ( u32 psmfStruct ) {
2013-01-18 18:05:51 +08:00
Psmf * psmf = getPsmf ( psmfStruct ) ;
if ( ! psmf ) {
2016-05-31 00:55:11 -07:00
return hleLogError ( ME , ERROR_PSMF_NOT_INITIALIZED , " invalid psmf " ) ;
2013-01-18 18:05:51 +08:00
}
2016-05-31 00:55:11 -07:00
if ( psmf - > currentStreamNum < 0 ) {
return hleLogError ( ME , psmf - > currentStreamNum , " invalid stream " ) ;
}
return hleLogSuccessI ( ME , psmf - > currentStreamNum ) ;
2013-01-18 18:05:51 +08:00
}
2014-12-08 04:40:08 -05:00
static u32 scePsmfCheckEPMap ( u32 psmfStruct )
2013-06-24 18:58:36 +02:00
{
2014-01-10 19:15:35 +08:00
Psmf * psmf = getPsmf ( psmfStruct ) ;
if ( ! psmf ) {
ERROR_LOG ( ME , " scePsmfCheckEPMap(%08x): invalid psmf " , psmfStruct ) ;
return ERROR_PSMF_NOT_FOUND ;
}
DEBUG_LOG ( ME , " scePsmfCheckEPMap(%08x) " , psmfStruct ) ;
2014-01-10 12:57:40 -08:00
return psmf - > EPMap . empty ( ) ? ERROR_PSMF_NOT_FOUND : 0 ;
2013-06-24 18:58:36 +02:00
}
2014-12-08 04:40:08 -05:00
static u32 scePsmfGetEPWithId ( u32 psmfStruct , int epid , u32 entryAddr )
2013-01-18 18:05:51 +08:00
{
Psmf * psmf = getPsmf ( psmfStruct ) ;
if ( ! psmf ) {
2014-01-01 13:23:19 -08:00
ERROR_LOG ( ME , " scePsmfGetEPWithId(%08x, %i, %08x): invalid psmf " , psmfStruct , epid , entryAddr ) ;
2014-03-02 01:15:00 -08:00
return ERROR_PSMF_NOT_INITIALIZED ;
2013-01-18 18:05:51 +08:00
}
2014-01-01 13:23:19 -08:00
DEBUG_LOG ( ME , " scePsmfGetEPWithId(%08x, %i, %08x) " , psmfStruct , epid , entryAddr ) ;
2014-01-09 21:37:01 +08:00
2014-01-08 14:20:20 +01:00
if ( epid < 0 | | epid > = ( int ) psmf - > EPMap . size ( ) ) {
2014-01-09 22:34:02 +08:00
ERROR_LOG ( ME , " scePsmfGetEPWithId(%08x, %i): invalid id " , psmfStruct , epid ) ;
2014-03-02 01:15:00 -08:00
return ERROR_PSMF_NOT_FOUND ;
2014-01-01 13:23:19 -08:00
}
if ( Memory : : IsValidAddress ( entryAddr ) ) {
Memory : : WriteStruct ( entryAddr , & psmf - > EPMap [ epid ] ) ;
2013-01-18 18:05:51 +08:00
}
return 0 ;
}
2014-12-08 04:40:08 -05:00
static u32 scePsmfGetEPWithTimestamp ( u32 psmfStruct , u32 ts , u32 entryAddr )
2013-01-18 18:05:51 +08:00
{
Psmf * psmf = getPsmf ( psmfStruct ) ;
if ( ! psmf ) {
2013-09-07 22:02:55 +02:00
ERROR_LOG ( ME , " scePsmfGetEPWithTimestamp(%08x, %i, %08x): invalid psmf " , psmfStruct , ts , entryAddr ) ;
2014-03-02 01:15:00 -08:00
return ERROR_PSMF_NOT_INITIALIZED ;
2013-01-18 18:05:51 +08:00
}
2013-09-07 22:02:55 +02:00
DEBUG_LOG ( ME , " scePsmfGetEPWithTimestamp(%08x, %i, %08x) " , psmfStruct , ts , entryAddr ) ;
2014-01-09 21:37:01 +08:00
2013-01-18 18:05:51 +08:00
if ( ts < psmf - > presentationStartTime ) {
2014-01-09 22:34:02 +08:00
ERROR_LOG ( ME , " scePsmfGetEPWithTimestamp(%08x, %i): invalid timestamp " , psmfStruct , ts ) ;
2014-03-02 01:15:00 -08:00
return ERROR_PSMF_NOT_FOUND ;
2013-01-18 18:05:51 +08:00
}
2014-01-01 13:23:19 -08:00
int epid = psmf - > FindEPWithTimestamp ( ts ) ;
2014-01-08 14:20:20 +01:00
if ( epid < 0 | | epid > = ( int ) psmf - > EPMap . size ( ) ) {
2014-03-02 15:12:50 +08:00
ERROR_LOG ( ME , " scePsmfGetEPWithTimestamp(%08x, %i): invalid id " , psmfStruct , epid ) ;
2014-03-02 01:15:00 -08:00
return ERROR_PSMF_NOT_FOUND ;
2014-01-01 13:23:19 -08:00
}
2013-01-18 18:05:51 +08:00
if ( Memory : : IsValidAddress ( entryAddr ) ) {
2014-01-01 13:23:19 -08:00
Memory : : WriteStruct ( entryAddr , & psmf - > EPMap [ epid ] ) ;
2013-01-18 18:05:51 +08:00
}
return 0 ;
}
2014-12-08 04:40:08 -05:00
static u32 scePsmfGetEPidWithTimestamp ( u32 psmfStruct , u32 ts )
2013-01-18 18:05:51 +08:00
{
Psmf * psmf = getPsmf ( psmfStruct ) ;
if ( ! psmf ) {
2013-09-07 22:02:55 +02:00
ERROR_LOG ( ME , " scePsmfGetEPidWithTimestamp(%08x, %i): invalid psmf " , psmfStruct , ts ) ;
2013-01-18 18:05:51 +08:00
return ERROR_PSMF_NOT_FOUND ;
}
2013-09-07 22:02:55 +02:00
DEBUG_LOG ( ME , " scePsmfGetEPidWithTimestamp(%08x, %i) " , psmfStruct , ts ) ;
2014-01-09 21:37:01 +08:00
2014-01-10 19:15:35 +08:00
if ( psmf - > EPMap . empty ( ) ) {
ERROR_LOG ( ME , " scePsmfGetEPidWithTimestamp(%08x): EPMap is empty " , psmfStruct ) ;
return ERROR_PSMF_NOT_FOUND ;
}
2013-01-18 18:05:51 +08:00
if ( ts < psmf - > presentationStartTime ) {
2014-01-09 21:37:01 +08:00
ERROR_LOG ( ME , " scePsmfGetEPidWithTimestamp(%08x, %i): invalid timestamp " , psmfStruct , ts ) ;
2013-01-18 18:05:51 +08:00
return ERROR_PSMF_INVALID_TIMESTAMP ;
}
2014-01-01 13:23:19 -08:00
int epid = psmf - > FindEPWithTimestamp ( ts ) ;
2014-01-08 14:20:20 +01:00
if ( epid < 0 | | epid > = ( int ) psmf - > EPMap . size ( ) ) {
2014-01-09 21:37:01 +08:00
ERROR_LOG ( ME , " scePsmfGetEPidWithTimestamp(%08x, %i): invalid id " , psmfStruct , epid ) ;
2014-01-09 21:30:49 +08:00
return ERROR_PSMF_INVALID_ID ;
2014-01-01 13:23:19 -08:00
}
2014-01-10 19:15:35 +08:00
2014-01-01 13:23:19 -08:00
return epid ;
2013-01-18 18:05:51 +08:00
}
2014-12-08 04:40:08 -05:00
static int scePsmfPlayerCreate ( u32 psmfPlayer , u32 dataPtr )
2013-01-18 18:05:51 +08:00
{
2014-04-20 00:01:16 -07:00
auto player = PSPPointer < u32 > : : Create ( psmfPlayer ) ;
const auto data = PSPPointer < const PsmfPlayerCreateData > : : Create ( dataPtr ) ;
if ( ! player . IsValid ( ) | | ! data . IsValid ( ) ) {
ERROR_LOG_REPORT ( ME , " scePsmfPlayerCreate(%08x, %08x): bad pointers " , psmfPlayer , dataPtr ) ;
// Crashes on a PSP.
return SCE_KERNEL_ERROR_ILLEGAL_ADDRESS ;
}
if ( ! data - > buffer . IsValid ( ) ) {
ERROR_LOG_REPORT ( ME , " scePsmfPlayerCreate(%08x, %08x): invalid buffer address %08x " , psmfPlayer , dataPtr , data - > buffer . ptr ) ;
// Also crashes on a PSP.
* player = 0 ;
return SCE_KERNEL_ERROR_ILLEGAL_ADDRESS ;
}
2014-04-27 10:25:51 -07:00
if ( data - > bufferSize < 0x00285800 ) {
2014-04-20 00:01:16 -07:00
ERROR_LOG_REPORT ( ME , " scePsmfPlayerCreate(%08x, %08x): buffer too small %08x " , psmfPlayer , dataPtr , data - > bufferSize ) ;
* player = 0 ;
return ERROR_PSMFPLAYER_BUFFER_SIZE ;
}
if ( data - > threadPriority < 0x10 | | data - > threadPriority > = 0x6E ) {
ERROR_LOG_REPORT ( ME , " scePsmfPlayerCreate(%08x, %08x): bad thread priority %02x " , psmfPlayer , dataPtr , data - > threadPriority ) ;
* player = 0 ;
return ERROR_PSMFPLAYER_INVALID_PARAM ;
}
if ( ! psmfPlayerMap . empty ( ) ) {
ERROR_LOG_REPORT ( ME , " scePsmfPlayerCreate(%08x, %08x): already have an active player " , psmfPlayer , dataPtr ) ;
// TODO: Tests show this is what we should do. Leaving it off for now to see if safe.
//*player = 0;
//return ERROR_MPEG_ALREADY_INIT;
}
INFO_LOG ( ME , " scePsmfPlayerCreate(%08x, %08x) " , psmfPlayer , dataPtr ) ;
2013-01-18 18:05:51 +08:00
PsmfPlayer * psmfplayer = getPsmfPlayer ( psmfPlayer ) ;
if ( ! psmfplayer ) {
2014-04-20 00:01:16 -07:00
psmfplayer = new PsmfPlayer ( data ) ;
2014-03-30 13:14:17 -07:00
if ( psmfPlayerMap . find ( psmfPlayer ) ! = psmfPlayerMap . end ( ) )
delete psmfPlayerMap [ psmfPlayer ] ;
2013-01-27 19:41:56 -08:00
psmfPlayerMap [ psmfPlayer ] = psmfplayer ;
2014-04-20 08:22:51 -07:00
// Write something there to identify it with.
* player = psmfPlayer ;
2013-01-18 18:05:51 +08:00
}
2013-01-24 19:40:26 +08:00
2014-04-20 19:19:12 -07:00
// These really shouldn't be globals. But, you can only have one psmfplayer anyway.
videoPixelMode = GE_CMODE_32BIT_ABGR8888 ;
videoLoopStatus = PSMF_PLAYER_CONFIG_NO_LOOP ;
2013-03-06 01:00:26 -08:00
psmfplayer - > status = PSMF_PLAYER_STATUS_INIT ;
2014-04-20 00:01:16 -07:00
return hleDelayResult ( 0 , " player create " , 20000 ) ;
2013-01-06 22:15:47 -08:00
}
2014-12-08 04:40:08 -05:00
static int scePsmfPlayerStop ( u32 psmfPlayer ) {
2013-03-06 01:00:26 -08:00
PsmfPlayer * psmfplayer = getPsmfPlayer ( psmfPlayer ) ;
2014-02-05 22:33:44 +08:00
if ( ! psmfplayer ) {
ERROR_LOG ( ME , " scePsmfPlayerStop(%08x): invalid psmf player " , psmfPlayer ) ;
2014-05-22 23:41:38 -07:00
return ERROR_PSMFPLAYER_INVALID_STATUS ;
2014-02-05 22:33:44 +08:00
}
2014-05-24 12:46:34 -07:00
if ( psmfplayer - > status < PSMF_PLAYER_STATUS_PLAYING ) {
ERROR_LOG ( ME , " scePsmfPlayerStop(%08x): not yet playing " , psmfPlayer ) ;
2014-04-20 08:17:56 -07:00
return ERROR_PSMFPLAYER_INVALID_STATUS ;
2014-02-13 20:22:56 +08:00
}
2014-05-22 23:40:44 -07:00
psmfplayer - > AbortFinish ( ) ;
2014-02-13 20:22:56 +08:00
2014-02-05 22:33:44 +08:00
INFO_LOG ( ME , " scePsmfPlayerStop(%08x) " , psmfPlayer ) ;
psmfplayer - > status = PSMF_PLAYER_STATUS_STANDBY ;
2014-05-22 23:41:38 -07:00
return hleDelayResult ( 0 , " psmfplayer stop " , 3000 ) ;
2012-11-07 19:10:52 +01:00
}
2014-12-08 04:40:08 -05:00
static int scePsmfPlayerBreak ( u32 psmfPlayer )
2013-01-18 18:05:51 +08:00
{
2014-02-16 23:21:32 +08:00
WARN_LOG ( ME , " scePsmfPlayerBreak(%08x) " , psmfPlayer ) ;
2013-03-06 01:00:26 -08:00
PsmfPlayer * psmfplayer = getPsmfPlayer ( psmfPlayer ) ;
2014-02-05 22:33:44 +08:00
if ( ! psmfplayer ) {
ERROR_LOG ( ME , " scePsmfPlayerBreak(%08x): invalid psmf player " , psmfPlayer ) ;
2014-04-20 08:17:56 -07:00
return ERROR_PSMFPLAYER_INVALID_STATUS ;
2014-02-14 10:19:38 +08:00
}
2014-05-24 12:41:40 -07:00
2014-05-22 23:40:44 -07:00
psmfplayer - > AbortFinish ( ) ;
2014-02-14 10:19:38 +08:00
2013-01-06 22:15:47 -08:00
return 0 ;
2012-11-07 19:10:52 +01:00
}
2014-12-08 04:40:08 -05:00
static int _PsmfPlayerFillRingbuffer ( PsmfPlayer * psmfplayer ) {
2014-02-25 00:22:52 -05:00
if ( ! psmfplayer - > filehandle )
2013-06-27 23:46:26 +08:00
return - 1 ;
u8 * buf = psmfplayer - > tempbuf ;
2014-01-04 01:23:44 -08:00
int tempbufSize = ( int ) sizeof ( psmfplayer - > tempbuf ) ;
2013-06-27 23:46:26 +08:00
int size ;
2014-01-04 01:23:44 -08:00
// Let's not burn a bunch of time adding data all at once.
int addMax = std : : max ( 2048 * 100 , tempbufSize ) ;
2013-06-27 23:46:26 +08:00
do {
2014-01-04 01:23:44 -08:00
size = std : : min ( psmfplayer - > mediaengine - > getRemainSize ( ) , tempbufSize ) ;
2014-01-04 01:25:42 -08:00
size = std : : min ( psmfplayer - > mediaengine - > getAudioRemainSize ( ) , size ) ;
2013-06-27 23:46:26 +08:00
size = std : : min ( psmfplayer - > streamSize - psmfplayer - > readSize , size ) ;
if ( size < = 0 )
break ;
2013-07-22 19:22:21 +02:00
size = ( int ) pspFileSystem . ReadFile ( psmfplayer - > filehandle , buf , size ) ;
2013-06-28 05:44:57 +08:00
psmfplayer - > readSize + = size ;
2013-06-27 23:46:26 +08:00
psmfplayer - > mediaengine - > addStreamData ( buf , size ) ;
2014-01-04 01:23:44 -08:00
addMax - = size ;
if ( addMax < = 0 )
break ;
2013-06-27 23:46:26 +08:00
} while ( size > 0 ) ;
2014-08-17 22:27:39 +02:00
2013-06-27 23:46:26 +08:00
if ( psmfplayer - > readSize > = psmfplayer - > streamSize & & videoLoopStatus = = PSMF_PLAYER_CONFIG_LOOP ) {
2014-08-17 15:46:04 -07:00
// Start looping, but only if we've finished.
if ( psmfplayer - > HasReachedEnd ( ) ) {
psmfplayer - > readSize = 0 ;
pspFileSystem . SeekFile ( psmfplayer - > filehandle , psmfplayer - > fileoffset , FILEMOVE_BEGIN ) ;
psmfplayer - > mediaengine - > reloadStream ( ) ;
}
2013-06-27 23:46:26 +08:00
}
return 0 ;
}
2014-12-08 04:40:08 -05:00
static int _PsmfPlayerSetPsmfOffset ( u32 psmfPlayer , const char * filename , int offset , bool docallback ) {
2014-04-20 08:45:40 -07:00
PsmfPlayer * psmfplayer = getPsmfPlayer ( psmfPlayer ) ;
if ( ! psmfplayer | | psmfplayer - > status ! = PSMF_PLAYER_STATUS_INIT ) {
return ERROR_PSMFPLAYER_INVALID_STATUS ;
}
if ( ! filename ) {
return ERROR_PSMFPLAYER_INVALID_PARAM ;
}
2014-05-18 20:43:10 -07:00
int delayUs = 1100 ;
2013-06-18 16:05:15 +08:00
psmfplayer - > filehandle = pspFileSystem . OpenFile ( filename , ( FileAccess ) FILEACCESS_READ ) ;
2014-04-20 08:45:40 -07:00
if ( ! psmfplayer - > filehandle ) {
2014-05-18 20:43:10 -07:00
return hleDelayResult ( SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT , " psmfplayer set " , delayUs ) ;
2014-04-20 08:45:40 -07:00
}
2014-12-10 23:30:17 -05:00
if ( offset ! = 0 )
pspFileSystem . SeekFile ( psmfplayer - > filehandle , offset , FILEMOVE_BEGIN ) ;
u8 * buf = psmfplayer - > tempbuf ;
int tempbufSize = ( int ) sizeof ( psmfplayer - > tempbuf ) ;
int size = ( int ) pspFileSystem . ReadFile ( psmfplayer - > filehandle , buf , 2048 ) ;
delayUs + = 2000 ;
2014-04-20 11:53:59 -07:00
2014-12-10 23:30:17 -05:00
const u32 magic = * ( u32_le * ) buf ;
if ( magic ! = PSMF_MAGIC ) {
// TODO: Let's keep trying as we were before.
ERROR_LOG_REPORT ( ME , " scePsmfPlayerSetPsmf*: incorrect PSMF magic, bad data " ) ;
//return SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT;
}
2014-05-18 20:30:58 -07:00
2014-12-10 23:30:17 -05:00
// TODO: Merge better with Psmf.
u16 numStreams = * ( u16_be * ) ( buf + 0x80 ) ;
if ( numStreams > 128 ) {
ERROR_LOG_REPORT ( ME , " scePsmfPlayerSetPsmf*: too many streams in PSMF video, bogus data " ) ;
return hleDelayResult ( SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT , " psmfplayer set " , delayUs ) ;
}
psmfplayer - > totalVideoStreams = 0 ;
psmfplayer - > totalAudioStreams = 0 ;
psmfplayer - > playerVersion = PSMF_PLAYER_VERSION_FULL ;
for ( u16 i = 0 ; i < numStreams ; i + + ) {
const u8 * currentStreamAddr = buf + 0x82 + i * 16 ;
const int streamId = * currentStreamAddr ;
if ( ( streamId & PSMF_VIDEO_STREAM_ID ) = = PSMF_VIDEO_STREAM_ID ) {
+ + psmfplayer - > totalVideoStreams ;
// If we don't have EP info for /any/ video stream, revert to BASIC.
const u32 epOffset = ReadUnalignedU32BE ( currentStreamAddr + 4 ) ;
const u32 epEntries = ReadUnalignedU32BE ( currentStreamAddr + 8 ) ;
// TODO: Actually, if these don't match, it seems to be an invalid PSMF.
if ( epOffset = = 0 | | epEntries = = 0 ) {
psmfplayer - > playerVersion = PSMF_PLAYER_VERSION_BASIC ;
2014-04-20 11:53:59 -07:00
}
2014-12-10 23:30:17 -05:00
} else if ( ( streamId & PSMF_AUDIO_STREAM_ID ) = = PSMF_AUDIO_STREAM_ID ) {
+ + psmfplayer - > totalAudioStreams ;
} else {
WARN_LOG_REPORT ( ME , " scePsmfPlayerSetPsmf*: unexpected streamID %x " , streamId ) ;
2014-04-20 11:53:59 -07:00
}
2013-06-18 16:05:15 +08:00
}
2014-12-10 23:30:17 -05:00
// TODO: It seems like it's invalid if there's not at least 1 video stream.
int mpegoffset = * ( s32_be * ) ( buf + PSMF_STREAM_OFFSET_OFFSET ) ;
psmfplayer - > readSize = size - mpegoffset ;
psmfplayer - > streamSize = * ( s32_be * ) ( buf + PSMF_STREAM_SIZE_OFFSET ) ;
psmfplayer - > fileoffset = offset + mpegoffset ;
psmfplayer - > mediaengine - > loadStream ( buf , 2048 , std : : max ( 2048 * 500 , tempbufSize ) ) ;
_PsmfPlayerFillRingbuffer ( psmfplayer ) ;
psmfplayer - > totalDurationTimestamp = psmfplayer - > mediaengine - > getLastTimeStamp ( ) ;
2014-04-20 08:55:30 -07:00
psmfplayer - > status = PSMF_PLAYER_STATUS_STANDBY ;
2014-05-18 20:43:10 -07:00
return hleDelayResult ( 0 , " psmfplayer set " , delayUs ) ;
2013-06-18 16:05:15 +08:00
}
2014-12-08 04:40:08 -05:00
static int scePsmfPlayerSetPsmf ( u32 psmfPlayer , const char * filename )
2013-01-18 18:05:51 +08:00
{
2014-05-31 21:38:37 -07:00
u32 result = _PsmfPlayerSetPsmfOffset ( psmfPlayer , filename , 0 , false ) ;
2014-04-20 08:45:40 -07:00
if ( result = = ERROR_PSMFPLAYER_INVALID_STATUS ) {
ERROR_LOG_REPORT ( ME , " scePsmfPlayerSetPsmf(%08x, %s): invalid psmf player or status " , psmfPlayer , filename ) ;
} else if ( result = = ERROR_PSMFPLAYER_INVALID_PARAM ) {
ERROR_LOG ( ME , " scePsmfPlayerSetPsmf(%08x, %s): invalid filename " , psmfPlayer , filename ) ;
} else if ( result = = SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT ) {
ERROR_LOG ( ME , " scePsmfPlayerSetPsmf(%08x, %s): invalid file data or does not exist " , psmfPlayer , filename ) ;
} else {
INFO_LOG ( ME , " scePsmfPlayerSetPsmf(%08x, %s) " , psmfPlayer , filename ) ;
}
return result ;
2013-01-06 22:15:47 -08:00
}
2014-12-08 04:40:08 -05:00
static int scePsmfPlayerSetPsmfCB ( u32 psmfPlayer , const char * filename )
2013-01-18 18:05:51 +08:00
{
2013-06-13 22:33:59 -07:00
// TODO: hleCheckCurrentCallbacks?
2014-05-31 21:38:37 -07:00
u32 result = _PsmfPlayerSetPsmfOffset ( psmfPlayer , filename , 0 , true ) ;
2014-04-20 08:45:40 -07:00
if ( result = = ERROR_PSMFPLAYER_INVALID_STATUS ) {
ERROR_LOG_REPORT ( ME , " scePsmfPlayerSetPsmfCB(%08x, %s): invalid psmf player or status " , psmfPlayer , filename ) ;
} else if ( result = = ERROR_PSMFPLAYER_INVALID_PARAM ) {
ERROR_LOG ( ME , " scePsmfPlayerSetPsmfCB(%08x, %s): invalid filename " , psmfPlayer , filename ) ;
} else if ( result = = SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT ) {
ERROR_LOG ( ME , " scePsmfPlayerSetPsmfCB(%08x, %s): invalid file data or does not exist " , psmfPlayer , filename ) ;
} else {
INFO_LOG ( ME , " scePsmfPlayerSetPsmfCB(%08x, %s) " , psmfPlayer , filename ) ;
}
return result ;
2013-01-06 22:15:47 -08:00
}
2014-12-08 04:40:08 -05:00
static int scePsmfPlayerSetPsmfOffset ( u32 psmfPlayer , const char * filename , int offset )
2013-06-18 16:05:15 +08:00
{
2014-05-31 21:38:37 -07:00
u32 result = _PsmfPlayerSetPsmfOffset ( psmfPlayer , filename , offset , false ) ;
2014-04-20 08:45:40 -07:00
if ( result = = ERROR_PSMFPLAYER_INVALID_STATUS ) {
ERROR_LOG_REPORT ( ME , " scePsmfPlayerSetPsmfOffset(%08x, %s): invalid psmf player or status " , psmfPlayer , filename ) ;
} else if ( result = = ERROR_PSMFPLAYER_INVALID_PARAM ) {
ERROR_LOG ( ME , " scePsmfPlayerSetPsmfOffset(%08x, %s): invalid filename " , psmfPlayer , filename ) ;
} else if ( result = = SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT ) {
ERROR_LOG ( ME , " scePsmfPlayerSetPsmfOffset(%08x, %s): invalid file data or does not exist " , psmfPlayer , filename ) ;
} else {
INFO_LOG ( ME , " scePsmfPlayerSetPsmfOffset(%08x, %s) " , psmfPlayer , filename ) ;
}
return result ;
2013-06-18 16:05:15 +08:00
}
2014-12-08 04:40:08 -05:00
static int scePsmfPlayerSetPsmfOffsetCB ( u32 psmfPlayer , const char * filename , int offset )
2013-06-18 16:05:15 +08:00
{
// TODO: hleCheckCurrentCallbacks?
2014-05-31 21:38:37 -07:00
u32 result = _PsmfPlayerSetPsmfOffset ( psmfPlayer , filename , offset , true ) ;
2014-04-20 08:45:40 -07:00
if ( result = = ERROR_PSMFPLAYER_INVALID_STATUS ) {
ERROR_LOG_REPORT ( ME , " scePsmfPlayerSetPsmfOffsetCB(%08x, %s): invalid psmf player or status " , psmfPlayer , filename ) ;
} else if ( result = = ERROR_PSMFPLAYER_INVALID_PARAM ) {
ERROR_LOG ( ME , " scePsmfPlayerSetPsmfOffsetCB(%08x, %s): invalid filename " , psmfPlayer , filename ) ;
} else if ( result = = SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT ) {
ERROR_LOG ( ME , " scePsmfPlayerSetPsmfOffsetCB(%08x, %s): invalid file data or does not exist " , psmfPlayer , filename ) ;
} else {
INFO_LOG ( ME , " scePsmfPlayerSetPsmfOffsetCB(%08x, %s) " , psmfPlayer , filename ) ;
}
return result ;
2013-01-06 22:15:47 -08:00
}
2014-12-08 04:40:08 -05:00
static int scePsmfPlayerGetAudioOutSize ( u32 psmfPlayer )
2013-01-18 18:05:51 +08:00
{
2014-05-24 15:35:51 -07:00
PsmfPlayer * psmfplayer = getPsmfPlayer ( psmfPlayer ) ;
if ( ! psmfplayer ) {
ERROR_LOG ( ME , " scePsmfPlayerGetAudioOutSize(%08x): invalid psmf player " , psmfPlayer ) ;
return ERROR_PSMFPLAYER_INVALID_STATUS ;
}
2014-02-14 10:19:38 +08:00
WARN_LOG ( ME , " %i = scePsmfPlayerGetAudioOutSize(%08x) " , audioSamplesBytes , psmfPlayer ) ;
2013-01-18 18:05:51 +08:00
return audioSamplesBytes ;
2013-01-06 22:15:47 -08:00
}
2014-12-08 04:40:08 -05:00
static bool __PsmfPlayerContinueSeek ( PsmfPlayer * psmfplayer , int tries = 50 ) {
2014-05-15 00:14:27 -07:00
if ( psmfplayer - > seekDestTimeStamp < = 0 ) {
return true ;
}
while ( ! psmfplayer - > mediaengine - > seekTo ( psmfplayer - > seekDestTimeStamp , videoPixelMode ) ) {
if ( - - tries < = 0 ) {
return false ;
}
_PsmfPlayerFillRingbuffer ( psmfplayer ) ;
if ( psmfplayer - > mediaengine - > IsVideoEnd ( ) ) {
break ;
}
}
// Seek is done, so forget about it.
psmfplayer - > seekDestTimeStamp = 0 ;
return true ;
}
2014-12-08 04:40:08 -05:00
static int scePsmfPlayerStart ( u32 psmfPlayer , u32 psmfPlayerData , int initPts )
2013-01-18 18:05:51 +08:00
{
2013-01-22 23:44:23 -08:00
PsmfPlayer * psmfplayer = getPsmfPlayer ( psmfPlayer ) ;
2014-05-04 23:52:12 -07:00
if ( ! psmfplayer ) {
ERROR_LOG ( ME , " scePsmfPlayerStart(%08x, %08x, %d): invalid psmf player " , psmfPlayer , psmfPlayerData , initPts ) ;
return ERROR_PSMFPLAYER_INVALID_STATUS ;
}
if ( psmfplayer - > status = = PSMF_PLAYER_STATUS_INIT ) {
ERROR_LOG ( ME , " scePsmfPlayerStart(%08x, %08x, %d): psmf not yet set " , psmfPlayer , psmfPlayerData , initPts ) ;
2014-04-20 08:17:56 -07:00
return ERROR_PSMFPLAYER_INVALID_STATUS ;
2014-02-14 10:19:38 +08:00
}
2014-05-04 23:52:12 -07:00
auto playerData = PSPPointer < PsmfPlayerData > : : Create ( psmfPlayerData ) ;
if ( ! playerData . IsValid ( ) ) {
// Crashes on a PSP.
ERROR_LOG ( ME , " scePsmfPlayerStart(%08x, %08x, %d): bad data address " , psmfPlayer , psmfPlayerData , initPts ) ;
return SCE_KERNEL_ERROR_ILLEGAL_ADDRESS ;
}
if ( playerData - > playMode < 0 | | playerData - > playMode > ( int ) PSMF_PLAYER_MODE_REWIND ) {
ERROR_LOG ( ME , " scePsmfPlayerStart(%08x, %08x, %d): invalid mode " , psmfPlayer , psmfPlayerData , initPts ) ;
return ERROR_PSMFPLAYER_INVALID_PARAM ;
}
if ( initPts > = psmfplayer - > mediaengine - > getLastTimeStamp ( ) ) {
ERROR_LOG ( ME , " scePsmfPlayerStart(%08x, %08x, %d): pts is outside video " , psmfPlayer , psmfPlayerData , initPts ) ;
return ERROR_PSMFPLAYER_INVALID_PARAM ;
}
2014-05-11 11:32:24 -07:00
if ( psmfplayer - > totalAudioStreams > 0 ) {
if ( playerData - > audioCodec ! = 0x0F & & playerData - > audioCodec ! = 0x01 ) {
ERROR_LOG_REPORT ( ME , " scePsmfPlayerStart(%08x, %08x, %d): invalid audio codec %02x " , psmfPlayer , psmfPlayerData , initPts , playerData - > audioCodec ) ;
return ERROR_PSMFPLAYER_INVALID_STREAM ;
}
if ( playerData - > audioStreamNum > = psmfplayer - > totalAudioStreams ) {
ERROR_LOG_REPORT ( ME , " scePsmfPlayerStart(%08x, %08x, %d): unable to change audio stream to %d " , psmfPlayer , psmfPlayerData , initPts , playerData - > audioStreamNum ) ;
return ERROR_PSMFPLAYER_INVALID_CONFIG ;
}
}
if ( playerData - > videoCodec ! = 0x0E & & playerData - > videoCodec ! = 0x00 ) {
ERROR_LOG_REPORT ( ME , " scePsmfPlayerStart(%08x, %08x, %d): invalid video codec %02x " , psmfPlayer , psmfPlayerData , initPts , playerData - > videoCodec ) ;
return ERROR_PSMFPLAYER_INVALID_STREAM ;
}
if ( playerData - > videoStreamNum < 0 | | playerData - > videoStreamNum > = psmfplayer - > totalVideoStreams ) {
ERROR_LOG_REPORT ( ME , " scePsmfPlayerStart(%08x, %08x, %d): unable to change video stream to %d " , psmfPlayer , psmfPlayerData , initPts , playerData - > videoStreamNum ) ;
return ERROR_PSMFPLAYER_INVALID_CONFIG ;
}
2014-05-18 21:41:15 -07:00
switch ( ( PsmfPlayerMode ) ( s32 ) playerData - > playMode ) {
case PSMF_PLAYER_MODE_FORWARD :
case PSMF_PLAYER_MODE_REWIND :
if ( psmfplayer - > playerVersion = = PSMF_PLAYER_VERSION_BASIC ) {
WARN_LOG_REPORT ( ME , " scePsmfPlayerStart(%08x, %08x, %d): no EP data for FORWARD/REWIND " , psmfPlayer , psmfPlayerData , initPts ) ;
return ERROR_PSMFPLAYER_INVALID_PARAM ;
}
WARN_LOG_REPORT ( ME , " scePsmfPlayerStart(%08x, %08x, %d): unsupported playMode " , psmfPlayer , psmfPlayerData , initPts ) ;
break ;
case PSMF_PLAYER_MODE_PLAY :
case PSMF_PLAYER_MODE_PAUSE :
break ;
default :
WARN_LOG_REPORT ( ME , " scePsmfPlayerStart(%08x, %08x, %d): unsupported playMode " , psmfPlayer , psmfPlayerData , initPts ) ;
break ;
}
2014-05-18 21:58:43 -07:00
if ( psmfplayer - > playerVersion = = PSMF_PLAYER_VERSION_BASIC & & initPts ! = 0 ) {
ERROR_LOG_REPORT ( ME , " scePsmfPlayerStart(%08x, %08x, %d): unable to seek without EPmap " , psmfPlayer , psmfPlayerData , initPts ) ;
return ERROR_PSMFPLAYER_INVALID_PARAM ;
}
2014-05-04 23:52:12 -07:00
WARN_LOG ( ME , " scePsmfPlayerStart(%08x, %08x, %d) " , psmfPlayer , psmfPlayerData , initPts ) ;
2014-05-22 23:40:44 -07:00
psmfplayer - > AbortFinish ( ) ;
2014-05-11 11:32:24 -07:00
psmfplayer - > mediaengine - > setVideoStream ( playerData - > videoStreamNum ) ;
2014-05-04 23:52:12 -07:00
psmfplayer - > videoCodec = playerData - > videoCodec ;
psmfplayer - > videoStreamNum = playerData - > videoStreamNum ;
2014-05-18 20:48:02 -07:00
if ( psmfplayer - > totalAudioStreams > 0 ) {
2014-05-11 11:32:24 -07:00
psmfplayer - > mediaengine - > setAudioStream ( playerData - > audioStreamNum ) ;
2014-05-04 23:52:12 -07:00
psmfplayer - > audioCodec = playerData - > audioCodec ;
psmfplayer - > audioStreamNum = playerData - > audioStreamNum ;
2013-06-02 01:30:51 +08:00
}
2014-05-04 23:52:12 -07:00
psmfplayer - > playMode = playerData - > playMode ;
psmfplayer - > playSpeed = playerData - > playSpeed ;
2013-01-18 18:05:51 +08:00
2014-05-11 21:51:28 -07:00
// Does not alter current pts, it just catches up when Update()/etc. get there.
2013-01-18 18:05:51 +08:00
2014-05-18 20:59:18 -07:00
int delayUs = psmfplayer - > status = = PSMF_PLAYER_STATUS_PLAYING ? 3000 : 0 ;
2013-03-06 01:00:26 -08:00
psmfplayer - > status = PSMF_PLAYER_STATUS_PLAYING ;
2014-05-11 21:51:28 -07:00
psmfplayer - > warmUp = 0 ;
2013-06-11 19:04:14 +08:00
psmfplayer - > mediaengine - > openContext ( ) ;
2014-05-15 00:14:27 -07:00
s64 dist = initPts - psmfplayer - > mediaengine - > getVideoTimeStamp ( ) ;
if ( dist < 0 | | dist > VIDEO_FRAME_DURATION_TS * 60 ) {
2014-05-11 11:14:59 -07:00
// When seeking backwards, we just start populating the stream from the start.
pspFileSystem . SeekFile ( psmfplayer - > filehandle , 0 , FILEMOVE_BEGIN ) ;
u8 * buf = psmfplayer - > tempbuf ;
int tempbufSize = ( int ) sizeof ( psmfplayer - > tempbuf ) ;
2014-05-15 00:14:27 -07:00
int size = ( int ) pspFileSystem . ReadFile ( psmfplayer - > filehandle , buf , tempbufSize ) ;
psmfplayer - > mediaengine - > loadStream ( buf , size , std : : max ( 2048 * 500 , tempbufSize ) ) ;
2014-05-11 11:14:59 -07:00
int mpegoffset = * ( s32_be * ) ( buf + PSMF_STREAM_OFFSET_OFFSET ) ;
psmfplayer - > readSize = size - mpegoffset ;
2014-05-15 00:14:27 -07:00
Psmf psmf ( psmfplayer - > tempbuf , 0 ) ;
int lastOffset = 0 ;
for ( auto it = psmf . EPMap . begin ( ) , end = psmf . EPMap . end ( ) ; it ! = end ; + + it ) {
2014-05-22 00:34:47 -07:00
if ( initPts < = it - > EPPts - ( int ) psmf . presentationStartTime ) {
2014-05-15 00:14:27 -07:00
break ;
}
lastOffset = it - > EPOffset ;
2014-05-05 01:24:31 -07:00
}
2014-05-15 00:14:27 -07:00
2014-05-22 00:34:47 -07:00
psmfplayer - > readSize = lastOffset * 2048 ;
2014-05-15 00:14:27 -07:00
pspFileSystem . SeekFile ( psmfplayer - > filehandle , psmfplayer - > fileoffset + psmfplayer - > readSize , FILEMOVE_BEGIN ) ;
_PsmfPlayerFillRingbuffer ( psmfplayer ) ;
2014-05-05 01:24:31 -07:00
}
2014-05-15 00:14:27 -07:00
psmfplayer - > seekDestTimeStamp = initPts ;
__PsmfPlayerContinueSeek ( psmfplayer ) ;
2014-05-18 20:59:18 -07:00
return delayUs = = 0 ? 0 : hleDelayResult ( 0 , " psmfplayer start " , delayUs ) ;
2013-01-06 22:15:47 -08:00
}
2014-12-08 04:40:08 -05:00
static int scePsmfPlayerDelete ( u32 psmfPlayer )
2013-01-18 18:05:51 +08:00
{
2013-03-06 01:00:26 -08:00
PsmfPlayer * psmfplayer = getPsmfPlayer ( psmfPlayer ) ;
2014-02-05 22:33:44 +08:00
if ( ! psmfplayer ) {
2013-09-07 22:02:55 +02:00
ERROR_LOG ( ME , " scePsmfPlayerDelete(%08x): invalid psmf player " , psmfPlayer ) ;
2014-04-20 08:17:56 -07:00
return ERROR_PSMFPLAYER_INVALID_STATUS ;
2014-02-14 10:19:38 +08:00
}
2014-02-05 22:33:44 +08:00
INFO_LOG ( ME , " scePsmfPlayerDelete(%08x) " , psmfPlayer ) ;
delete psmfplayer ;
2014-05-24 14:13:18 -07:00
psmfPlayerMap . erase ( Memory : : Read_U32 ( psmfPlayer ) ) ;
Memory : : Write_U32 ( 0 , psmfPlayer ) ;
2014-02-05 22:33:44 +08:00
2014-05-24 14:13:18 -07:00
return hleDelayResult ( 0 , " psmfplayer deleted " , 20000 ) ;
2013-01-06 22:15:47 -08:00
}
2014-12-08 04:40:08 -05:00
static int scePsmfPlayerUpdate ( u32 psmfPlayer )
2013-01-18 18:05:51 +08:00
{
PsmfPlayer * psmfplayer = getPsmfPlayer ( psmfPlayer ) ;
if ( ! psmfplayer ) {
2013-09-07 22:02:55 +02:00
ERROR_LOG ( ME , " scePsmfPlayerUpdate(%08x): invalid psmf player " , psmfPlayer ) ;
2014-04-20 08:17:56 -07:00
return ERROR_PSMFPLAYER_INVALID_STATUS ;
2014-02-14 10:19:38 +08:00
}
2014-05-20 22:32:40 -07:00
if ( psmfplayer - > status < PSMF_PLAYER_STATUS_PLAYING ) {
ERROR_LOG ( ME , " scePsmfPlayerUpdate(%08x): not playing yet " , psmfPlayer ) ;
return ERROR_PSMFPLAYER_INVALID_STATUS ;
2014-02-05 22:55:46 +08:00
}
2013-09-07 22:02:55 +02:00
DEBUG_LOG ( ME , " scePsmfPlayerUpdate(%08x) " , psmfPlayer ) ;
2014-08-17 15:46:04 -07:00
if ( psmfplayer - > HasReachedEnd ( ) ) {
2014-05-20 22:32:40 -07:00
if ( videoLoopStatus = = PSMF_PLAYER_CONFIG_NO_LOOP & & psmfplayer - > videoStep > = 1 ) {
2014-05-22 23:40:44 -07:00
if ( psmfplayer - > status ! = PSMF_PLAYER_STATUS_PLAYING_FINISHED ) {
psmfplayer - > ScheduleFinish ( psmfPlayer ) ;
INFO_LOG ( ME , " scePsmfPlayerUpdate(%08x): video end scheduled " , psmfPlayer ) ;
}
2013-01-18 18:05:51 +08:00
}
2013-01-22 23:44:23 -08:00
}
2014-04-25 23:40:22 -07:00
psmfplayer - > videoStep + + ;
2014-02-05 22:55:46 +08:00
2013-06-08 00:27:31 +08:00
return 0 ;
2013-01-06 22:15:47 -08:00
}
2014-12-08 04:40:08 -05:00
static int scePsmfPlayerReleasePsmf ( u32 psmfPlayer )
2013-01-18 18:05:51 +08:00
{
2013-03-06 01:00:26 -08:00
PsmfPlayer * psmfplayer = getPsmfPlayer ( psmfPlayer ) ;
2014-02-05 22:33:44 +08:00
if ( ! psmfplayer ) {
ERROR_LOG ( ME , " scePsmfPlayerReleasePsmf(%08x): invalid psmf player " , psmfPlayer ) ;
2014-05-24 15:35:51 -07:00
return ERROR_PSMFPLAYER_INVALID_STATUS ;
2014-02-05 22:33:44 +08:00
}
2014-05-24 15:35:51 -07:00
if ( psmfplayer - > status < PSMF_PLAYER_STATUS_STANDBY ) {
ERROR_LOG ( ME , " scePsmfPlayerReleasePsmf(%08x): not set yet " , psmfPlayer ) ;
2014-04-20 08:17:56 -07:00
return ERROR_PSMFPLAYER_INVALID_STATUS ;
2014-02-13 20:22:56 +08:00
}
2014-02-16 23:21:32 +08:00
WARN_LOG ( ME , " scePsmfPlayerReleasePsmf(%08x) " , psmfPlayer ) ;
2014-02-05 22:33:44 +08:00
psmfplayer - > status = PSMF_PLAYER_STATUS_INIT ;
2013-01-06 22:15:47 -08:00
return 0 ;
}
2014-12-08 04:40:08 -05:00
static void __PsmfUpdatePts ( PsmfPlayer * psmfplayer , PsmfVideoData * videoData ) {
2014-05-11 21:51:28 -07:00
// getVideoTimestamp() includes the frame duration, remove it for this frame's pts.
psmfplayer - > psmfPlayerAvcAu . pts = psmfplayer - > mediaengine - > getVideoTimeStamp ( ) - VIDEO_FRAME_DURATION_TS ;
if ( videoData ) {
videoData - > displaypts = ( u32 ) psmfplayer - > psmfPlayerAvcAu . pts ;
}
}
2014-12-08 04:40:08 -05:00
static int scePsmfPlayerGetVideoData ( u32 psmfPlayer , u32 videoDataAddr )
2013-03-29 00:54:04 -07:00
{
PsmfPlayer * psmfplayer = getPsmfPlayer ( psmfPlayer ) ;
if ( ! psmfplayer ) {
2013-09-07 22:02:55 +02:00
ERROR_LOG ( ME , " scePsmfPlayerGetVideoData(%08x, %08x): invalid psmf player " , psmfPlayer , videoDataAddr ) ;
2014-04-20 08:17:56 -07:00
return ERROR_PSMFPLAYER_INVALID_STATUS ;
2014-02-14 10:19:38 +08:00
}
2014-05-22 22:17:42 -07:00
if ( psmfplayer - > status < PSMF_PLAYER_STATUS_PLAYING ) {
2014-05-23 23:00:01 -07:00
ERROR_LOG ( ME , " scePsmfPlayerGetVideoData(%08x, %08x): psmf not playing " , psmfPlayer , videoDataAddr ) ;
2014-05-22 22:17:42 -07:00
return ERROR_PSMFPLAYER_INVALID_STATUS ;
2014-02-05 22:55:46 +08:00
}
2014-05-23 23:00:01 -07:00
auto videoData = PSPPointer < PsmfVideoData > : : Create ( videoDataAddr ) ;
2014-08-10 21:56:05 -07:00
if ( ! videoData . IsValid ( ) ) {
2014-05-23 23:00:01 -07:00
ERROR_LOG ( ME , " scePsmfPlayerGetVideoData(%08x, %08x): invalid data pointer " , psmfPlayer , videoDataAddr ) ;
// Technically just crashes if videoData is not valid.
return SCE_KERNEL_ERROR_INVALID_POINTER ;
}
if ( videoData - > frameWidth < 0 ) {
ERROR_LOG ( ME , " scePsmfPlayerGetVideoData(%08x, %08x): illegal bufw %d " , psmfPlayer , videoDataAddr , videoData - > frameWidth ) ;
return SCE_KERNEL_ERROR_PRIV_REQUIRED ;
}
if ( videoData - > frameWidth ! = 0 & & videoData - > frameWidth < psmfplayer - > mediaengine - > VideoWidth ( ) ) {
ERROR_LOG ( ME , " scePsmfPlayerGetVideoData(%08x, %08x): bufw %d smaller than width %d " , psmfPlayer , videoDataAddr , videoData - > frameWidth , psmfplayer - > mediaengine - > VideoWidth ( ) ) ;
return SCE_KERNEL_ERROR_INVALID_VALUE ;
}
2014-02-05 22:55:46 +08:00
2014-04-25 23:40:22 -07:00
hleEatCycles ( 20000 ) ;
2014-05-15 00:14:27 -07:00
if ( ! __PsmfPlayerContinueSeek ( psmfplayer ) ) {
DEBUG_LOG ( HLE , " scePsmfPlayerGetVideoData(%08x, %08x): still seeking " , psmfPlayer , videoDataAddr ) ;
return ERROR_PSMFPLAYER_NO_MORE_DATA ;
}
2014-04-27 12:57:39 -07:00
// On a real PSP, this takes a potentially variable amount of time.
// Normally a minimum of 3 without audio, 5 with. But if you don't delay sufficiently between, hundreds.
// It should be okay if we start videos quicker, but some games expect the first couple to fail.
if ( psmfplayer - > warmUp < PSMF_PLAYER_WARMUP_FRAMES ) {
DEBUG_LOG ( ME , " scePsmfPlayerGetVideoData(%08x, %08x): warming up " , psmfPlayer , videoDataAddr ) ;
+ + psmfplayer - > warmUp ;
return ERROR_PSMFPLAYER_NO_MORE_DATA ;
}
// In case we change warm up later, save a high value in savestates - video started.
psmfplayer - > warmUp = 10000 ;
2014-08-10 21:56:05 -07:00
// It's fine to pass an invalid value here if it's still warming up, but after that it's not okay.
if ( ! Memory : : IsValidAddress ( videoData - > displaybuf ) ) {
ERROR_LOG ( ME , " scePsmfPlayerGetVideoData(%08x, %08x): invalid buffer pointer %08x " , psmfPlayer , videoDataAddr , videoData - > displaybuf ) ;
return SCE_KERNEL_ERROR_INVALID_POINTER ;
}
2014-05-23 23:02:23 -07:00
bool doVideoStep = true ;
if ( psmfplayer - > playMode = = PSMF_PLAYER_MODE_PAUSE ) {
doVideoStep = false ;
} else if ( ! psmfplayer - > mediaengine - > IsNoAudioData ( ) ) {
s64 deltapts = psmfplayer - > mediaengine - > getVideoTimeStamp ( ) - psmfplayer - > mediaengine - > getAudioTimeStamp ( ) ;
2014-06-20 08:57:47 -07:00
// Don't skip the very first frame, sometimes audio starts with an early timestamp.
if ( deltapts > 0 & & psmfplayer - > mediaengine - > getVideoTimeStamp ( ) > 0 ) {
2014-05-23 23:02:23 -07:00
// Don't advance, just return the same frame again.
// TODO: This also seems somewhat based on Update() calls, but audio is involved too...
2014-05-23 23:00:48 -07:00
doVideoStep = false ;
2014-04-25 23:40:22 -07:00
} else {
2014-05-23 23:02:23 -07:00
// This is an approximation, it should allow a certain amount ahead before skipping frames.
while ( deltapts < = - ( VIDEO_FRAME_DURATION_TS * 5 ) ) {
psmfplayer - > mediaengine - > stepVideo ( videoPixelMode , true ) ;
deltapts = psmfplayer - > mediaengine - > getVideoTimeStamp ( ) - psmfplayer - > mediaengine - > getAudioTimeStamp ( ) ;
2014-04-25 23:40:22 -07:00
}
}
2014-05-23 23:02:23 -07:00
} else {
// No audio, based on Update() calls. playSpeed doesn't seem to matter?
2014-06-20 08:57:47 -07:00
if ( psmfplayer - > videoStep < = 1 & & psmfplayer - > mediaengine - > getVideoTimeStamp ( ) > 0 ) {
2014-05-23 23:02:23 -07:00
doVideoStep = false ;
} else {
psmfplayer - > videoStep = 0 ;
2013-06-08 04:50:36 -07:00
}
2014-05-23 23:02:23 -07:00
}
2014-05-22 22:19:10 -07:00
2014-05-23 23:02:23 -07:00
if ( doVideoStep ) {
psmfplayer - > mediaengine - > stepVideo ( videoPixelMode ) ;
2013-06-02 01:30:51 +08:00
}
2013-06-10 01:07:43 +08:00
2014-05-23 23:02:23 -07:00
// It seems the frameWidth is rounded down to even values, and defaults to 512.
int bufw = videoData - > frameWidth = = 0 ? 512 : videoData - > frameWidth & ~ 1 ;
// Always write the video frame, even after the video has ended.
int displaybufSize = psmfplayer - > mediaengine - > writeVideoImage ( videoData - > displaybuf , bufw , videoPixelMode ) ;
2016-01-17 12:43:13 -08:00
gpu - > NotifyVideoUpload ( videoData - > displaybuf , displaybufSize , bufw , videoPixelMode ) ;
2014-05-23 23:02:23 -07:00
__PsmfUpdatePts ( psmfplayer , videoData ) ;
2013-06-27 23:46:26 +08:00
_PsmfPlayerFillRingbuffer ( psmfplayer ) ;
2014-04-25 23:40:22 -07:00
2014-05-22 22:19:10 -07:00
DEBUG_LOG ( ME , " %08x=scePsmfPlayerGetVideoData(%08x, %08x) " , 0 , psmfPlayer , videoDataAddr ) ;
return hleDelayResult ( 0 , " psmfPlayer video decode " , 3000 ) ;
2013-03-29 00:54:04 -07:00
}
2014-12-08 04:40:08 -05:00
static int scePsmfPlayerGetAudioData ( u32 psmfPlayer , u32 audioDataAddr )
2013-03-29 00:54:04 -07:00
{
PsmfPlayer * psmfplayer = getPsmfPlayer ( psmfPlayer ) ;
if ( ! psmfplayer ) {
2013-09-07 22:02:55 +02:00
ERROR_LOG ( ME , " scePsmfPlayerGetAudioData(%08x, %08x): invalid psmf player " , psmfPlayer , audioDataAddr ) ;
2014-05-24 01:10:26 -07:00
return ERROR_PSMFPLAYER_INVALID_STATUS ;
2013-03-29 00:54:04 -07:00
}
2014-05-24 01:10:26 -07:00
if ( psmfplayer - > status < PSMF_PLAYER_STATUS_PLAYING ) {
ERROR_LOG ( ME , " scePsmfPlayerGetAudioData(%08x, %08x): not yet playing " , psmfPlayer , audioDataAddr ) ;
2014-04-20 08:17:56 -07:00
return ERROR_PSMFPLAYER_INVALID_STATUS ;
2014-02-14 10:19:38 +08:00
}
2014-05-24 01:10:26 -07:00
if ( ! Memory : : IsValidAddress ( audioDataAddr ) ) {
ERROR_LOG ( ME , " scePsmfPlayerGetAudioData(%08x, %08x): invalid audio pointer " , psmfPlayer , audioDataAddr ) ;
return SCE_KERNEL_ERROR_INVALID_POINTER ;
}
2014-02-14 10:19:38 +08:00
2014-05-24 01:10:26 -07:00
// Don't return audio frames before we would return video frames.
if ( psmfplayer - > warmUp < PSMF_PLAYER_WARMUP_FRAMES ) {
DEBUG_LOG ( ME , " scePsmfPlayerGetAudioData(%08x, %08x): warming up " , psmfPlayer , audioDataAddr ) ;
return ERROR_PSMFPLAYER_NO_MORE_DATA ;
2014-02-05 22:55:46 +08:00
}
2014-02-14 10:43:53 +08:00
if ( psmfplayer - > playMode = = PSMF_PLAYER_MODE_PAUSE ) {
INFO_LOG ( HLE , " scePsmfPlayerGetAudioData(%08x): paused mode " , psmfPlayer ) ;
2014-05-24 01:31:50 -07:00
return ERROR_PSMFPLAYER_NO_MORE_DATA ;
2014-02-14 10:43:53 +08:00
}
2014-02-15 18:07:19 +08:00
2014-05-24 01:10:26 -07:00
int ret = 0 ;
if ( psmfplayer - > mediaengine - > getAudioSamples ( audioDataAddr ) = = 0 ) {
2014-05-24 12:41:40 -07:00
if ( psmfplayer - > totalAudioStreams > 0 & & ( s64 ) psmfplayer - > psmfPlayerAvcAu . pts < ( s64 ) psmfplayer - > totalDurationTimestamp - VIDEO_FRAME_DURATION_TS ) {
2014-05-24 01:31:50 -07:00
// Write zeros for any missing trailing frames so it syncs with the video.
Memory : : Memset ( audioDataAddr , 0 , audioSamplesBytes ) ;
} else {
ret = ( int ) ERROR_PSMFPLAYER_NO_MORE_DATA ;
}
2014-02-15 18:37:34 +08:00
}
2014-02-15 18:15:44 +08:00
2014-02-12 23:32:05 +08:00
DEBUG_LOG ( ME , " %08x=scePsmfPlayerGetAudioData(%08x, %08x) " , ret , psmfPlayer , audioDataAddr ) ;
2014-04-25 23:40:22 -07:00
if ( ret ! = 0 ) {
hleEatCycles ( 10000 ) ;
} else {
hleEatCycles ( 30000 ) ;
}
hleReSchedule ( " psmfplayer audio decode " ) ;
return ret ;
2013-03-29 00:54:04 -07:00
}
2014-12-08 04:40:08 -05:00
static int scePsmfPlayerGetCurrentStatus ( u32 psmfPlayer )
2013-01-18 18:05:51 +08:00
{
2013-03-06 00:50:42 -08:00
PsmfPlayer * psmfplayer = getPsmfPlayer ( psmfPlayer ) ;
if ( ! psmfplayer ) {
2013-12-19 00:18:29 -08:00
// Mana Khemia and other games call this even when not necessary.
// It's annoying so the logging is verbose'd out.
VERBOSE_LOG ( ME , " scePsmfPlayerGetCurrentStatus(%08x): invalid psmf player " , psmfPlayer ) ;
2014-04-20 08:17:56 -07:00
return ERROR_PSMFPLAYER_INVALID_STATUS ;
2013-03-06 00:50:42 -08:00
}
2014-05-24 15:35:51 -07:00
if ( psmfplayer - > status = = PSMF_PLAYER_STATUS_NONE ) {
2014-02-14 10:19:38 +08:00
ERROR_LOG ( ME , " scePsmfPlayerGetCurrentStatus(%08x): not initialized " , psmfPlayer ) ;
2014-04-20 08:17:56 -07:00
return ERROR_PSMFPLAYER_INVALID_STATUS ;
2014-02-14 10:19:38 +08:00
}
2013-09-07 22:02:55 +02:00
DEBUG_LOG ( ME , " %d=scePsmfPlayerGetCurrentStatus(%08x) " , psmfplayer - > status , psmfPlayer ) ;
2013-03-06 01:00:26 -08:00
return psmfplayer - > status ;
2013-01-06 22:15:47 -08:00
}
2012-11-07 19:10:52 +01:00
2014-12-08 04:40:08 -05:00
static u32 scePsmfPlayerGetCurrentPts ( u32 psmfPlayer , u32 currentPtsAddr )
2013-01-18 18:05:51 +08:00
{
PsmfPlayer * psmfplayer = getPsmfPlayer ( psmfPlayer ) ;
if ( ! psmfplayer ) {
2013-09-07 22:02:55 +02:00
ERROR_LOG ( ME , " scePsmfPlayerGetCurrentPts(%08x, %08x): invalid psmf player " , psmfPlayer , currentPtsAddr ) ;
2014-05-11 21:51:28 -07:00
return ERROR_PSMFPLAYER_INVALID_STATUS ;
2013-01-18 18:05:51 +08:00
}
2014-05-11 21:51:28 -07:00
if ( psmfplayer - > status < PSMF_PLAYER_STATUS_STANDBY ) {
ERROR_LOG ( ME , " scePsmfPlayerGetCurrentPts(%08x, %08x): not initialized " , psmfPlayer , currentPtsAddr ) ;
2014-04-20 08:17:56 -07:00
return ERROR_PSMFPLAYER_INVALID_STATUS ;
2014-02-14 10:19:38 +08:00
}
2014-05-11 21:51:28 -07:00
if ( psmfplayer - > psmfPlayerAvcAu . pts < 0 ) {
2014-05-15 00:30:06 -07:00
WARN_LOG ( ME , " scePsmfPlayerGetCurrentPts(%08x, %08x): no frame yet " , psmfPlayer , currentPtsAddr ) ;
2014-05-11 21:51:28 -07:00
return ERROR_PSMFPLAYER_NO_MORE_DATA ;
}
2014-02-14 10:19:38 +08:00
2013-09-07 22:02:55 +02:00
DEBUG_LOG ( ME , " scePsmfPlayerGetCurrentPts(%08x, %08x) " , psmfPlayer , currentPtsAddr ) ;
2013-01-18 18:05:51 +08:00
if ( Memory : : IsValidAddress ( currentPtsAddr ) ) {
2013-06-10 01:07:43 +08:00
Memory : : Write_U32 ( psmfplayer - > psmfPlayerAvcAu . pts , currentPtsAddr ) ;
2014-05-11 21:51:28 -07:00
}
2013-01-18 18:05:51 +08:00
return 0 ;
}
2014-12-08 04:40:08 -05:00
static u32 scePsmfPlayerGetPsmfInfo ( u32 psmfPlayer , u32 psmfInfoAddr )
2013-01-18 18:05:51 +08:00
{
2014-04-20 13:48:45 -07:00
auto info = PSPPointer < PsmfInfo > : : Create ( psmfInfoAddr ) ;
if ( ! Memory : : IsValidAddress ( psmfPlayer ) | | ! info . IsValid ( ) ) {
ERROR_LOG ( ME , " scePsmfPlayerGetPsmfInfo(%08x, %08x): invalid addresses " , psmfPlayer , psmfInfoAddr ) ;
// PSP would crash.
return SCE_KERNEL_ERROR_ILLEGAL_ADDRESS ;
}
2013-01-18 18:05:51 +08:00
PsmfPlayer * psmfplayer = getPsmfPlayer ( psmfPlayer ) ;
if ( ! psmfplayer ) {
2013-09-07 22:02:55 +02:00
ERROR_LOG ( ME , " scePsmfPlayerGetPsmfInfo(%08x, %08x): invalid psmf player " , psmfPlayer , psmfInfoAddr ) ;
2014-04-20 13:48:45 -07:00
return ERROR_PSMFPLAYER_INVALID_STATUS ;
2013-01-18 18:05:51 +08:00
}
2014-04-20 13:48:45 -07:00
if ( psmfplayer - > status < PSMF_PLAYER_STATUS_STANDBY ) {
ERROR_LOG ( ME , " scePsmfPlayerGetPsmfInfo(%08x): psmf not set yet " , psmfPlayer ) ;
2014-04-20 08:17:56 -07:00
return ERROR_PSMFPLAYER_INVALID_STATUS ;
2014-02-14 10:19:38 +08:00
}
2013-09-07 22:02:55 +02:00
DEBUG_LOG ( ME , " scePsmfPlayerGetPsmfInfo(%08x, %08x) " , psmfPlayer , psmfInfoAddr ) ;
2014-05-11 21:51:28 -07:00
// The first frame is at 0, so subtract one frame's duration to get the last frame's timestamp.
info - > lastFrameTS = psmfplayer - > totalDurationTimestamp - VIDEO_FRAME_DURATION_TS ;
2014-04-20 13:48:45 -07:00
info - > numVideoStreams = psmfplayer - > totalVideoStreams ;
info - > numAudioStreams = psmfplayer - > totalAudioStreams ;
// pcm stream num?
info - > numPCMStreams = 0 ;
info - > playerVersion = psmfplayer - > playerVersion ;
2013-01-18 18:05:51 +08:00
return 0 ;
}
2014-12-08 04:40:08 -05:00
static u32 scePsmfPlayerGetCurrentPlayMode ( u32 psmfPlayer , u32 playModeAddr , u32 playSpeedAddr )
2013-01-18 18:05:51 +08:00
{
PsmfPlayer * psmfplayer = getPsmfPlayer ( psmfPlayer ) ;
if ( ! psmfplayer ) {
2013-09-07 22:02:55 +02:00
ERROR_LOG ( ME , " scePsmfPlayerGetCurrentPlayMode(%08x, %08x, %08x): invalid psmf player " , psmfPlayer , playModeAddr , playSpeedAddr ) ;
2014-04-20 08:17:56 -07:00
return ERROR_PSMFPLAYER_INVALID_STATUS ;
2014-02-14 10:19:38 +08:00
}
2014-04-25 20:30:05 -07:00
DEBUG_LOG ( ME , " scePsmfPlayerGetCurrentPlayMode(%08x, %08x, %08x) " , psmfPlayer , playModeAddr , playSpeedAddr ) ;
2013-01-18 18:05:51 +08:00
if ( Memory : : IsValidAddress ( playModeAddr ) ) {
2014-02-05 22:33:44 +08:00
Memory : : Write_U32 ( psmfplayer - > playMode , playModeAddr ) ;
2013-01-18 18:05:51 +08:00
}
if ( Memory : : IsValidAddress ( playSpeedAddr ) ) {
2014-02-05 22:33:44 +08:00
Memory : : Write_U32 ( psmfplayer - > playSpeed , playSpeedAddr ) ;
2013-01-18 18:05:51 +08:00
}
return 0 ;
}
2014-12-08 04:40:08 -05:00
static u32 scePsmfPlayerGetCurrentVideoStream ( u32 psmfPlayer , u32 videoCodecAddr , u32 videoStreamNumAddr )
2013-01-18 18:05:51 +08:00
{
PsmfPlayer * psmfplayer = getPsmfPlayer ( psmfPlayer ) ;
if ( ! psmfplayer ) {
2013-09-07 22:02:55 +02:00
ERROR_LOG ( ME , " scePsmfPlayerGetCurrentVideoStream(%08x, %08x, %08x): invalid psmf player " , psmfPlayer , videoCodecAddr , videoStreamNumAddr ) ;
2014-04-20 20:21:37 -07:00
return ERROR_PSMFPLAYER_INVALID_STATUS ;
2013-01-18 18:05:51 +08:00
}
2014-04-20 20:21:37 -07:00
if ( psmfplayer - > status = = PSMF_PLAYER_STATUS_INIT ) {
ERROR_LOG ( ME , " scePsmfPlayerGetCurrentVideoStream(%08x): psmf not yet set " , psmfPlayer ) ;
2014-04-20 08:17:56 -07:00
return ERROR_PSMFPLAYER_INVALID_STATUS ;
2014-02-14 10:19:38 +08:00
}
2014-04-20 20:21:37 -07:00
DEBUG_LOG ( ME , " scePsmfPlayerGetCurrentVideoStream(%08x, %08x, %08x) " , psmfPlayer , videoCodecAddr , videoStreamNumAddr ) ;
2013-01-18 18:05:51 +08:00
if ( Memory : : IsValidAddress ( videoCodecAddr ) ) {
2014-04-20 20:21:37 -07:00
Memory : : Write_U32 ( psmfplayer - > videoCodec = = 0x0E ? 0 : psmfplayer - > videoCodec , videoCodecAddr ) ;
2013-01-18 18:05:51 +08:00
}
if ( Memory : : IsValidAddress ( videoStreamNumAddr ) ) {
2014-04-20 20:21:37 -07:00
Memory : : Write_U32 ( psmfplayer - > videoStreamNum , videoStreamNumAddr ) ;
2013-01-18 18:05:51 +08:00
}
return 0 ;
}
2014-12-08 04:40:08 -05:00
static u32 scePsmfPlayerGetCurrentAudioStream ( u32 psmfPlayer , u32 audioCodecAddr , u32 audioStreamNumAddr )
2013-01-18 18:05:51 +08:00
{
PsmfPlayer * psmfplayer = getPsmfPlayer ( psmfPlayer ) ;
if ( ! psmfplayer ) {
2013-09-07 22:02:55 +02:00
ERROR_LOG ( ME , " scePsmfPlayerGetCurrentAudioStream(%08x, %08x, %08x): invalid psmf player " , psmfPlayer , audioCodecAddr , audioStreamNumAddr ) ;
2014-05-05 01:24:31 -07:00
return ERROR_PSMFPLAYER_INVALID_STATUS ;
2013-01-18 18:05:51 +08:00
}
2014-04-20 20:21:37 -07:00
if ( psmfplayer - > status = = PSMF_PLAYER_STATUS_INIT ) {
ERROR_LOG ( ME , " scePsmfPlayerGetCurrentVideoStream(%08x): psmf not yet set " , psmfPlayer ) ;
2014-04-20 08:17:56 -07:00
return ERROR_PSMFPLAYER_INVALID_STATUS ;
2014-02-14 10:19:38 +08:00
}
2014-04-20 20:21:37 -07:00
DEBUG_LOG ( ME , " scePsmfPlayerGetCurrentAudioStream(%08x, %08x, %08x) " , psmfPlayer , audioCodecAddr , audioStreamNumAddr ) ;
2013-01-18 18:05:51 +08:00
if ( Memory : : IsValidAddress ( audioCodecAddr ) ) {
2014-04-20 20:21:37 -07:00
Memory : : Write_U32 ( psmfplayer - > audioCodec = = 0x0F ? 1 : psmfplayer - > audioCodec , audioCodecAddr ) ;
2013-01-18 18:05:51 +08:00
}
if ( Memory : : IsValidAddress ( audioStreamNumAddr ) ) {
2014-04-20 20:21:37 -07:00
Memory : : Write_U32 ( psmfplayer - > audioStreamNum , audioStreamNumAddr ) ;
2013-01-18 18:05:51 +08:00
}
return 0 ;
}
2014-12-08 04:40:08 -05:00
static int scePsmfPlayerSetTempBuf ( u32 psmfPlayer , u32 tempBufAddr , u32 tempBufSize )
2013-01-18 18:05:51 +08:00
{
2013-03-06 01:00:26 -08:00
PsmfPlayer * psmfplayer = getPsmfPlayer ( psmfPlayer ) ;
2014-02-05 22:33:44 +08:00
if ( ! psmfplayer ) {
ERROR_LOG ( ME , " scePsmfPlayerSetTempBuf(%08x, %08x, %08x): invalid psmf player " , psmfPlayer , tempBufAddr , tempBufSize ) ;
2014-04-20 08:17:56 -07:00
return ERROR_PSMFPLAYER_INVALID_STATUS ;
2013-06-16 03:27:14 +08:00
}
2014-04-20 08:17:56 -07:00
if ( psmfplayer - > status ! = PSMF_PLAYER_STATUS_INIT ) {
2014-04-20 08:45:40 -07:00
ERROR_LOG_REPORT ( ME , " scePsmfPlayerSetTempBuf(%08x, %08x, %08x): invalid status %x " , psmfPlayer , tempBufAddr , tempBufSize , psmfplayer - > status ) ;
2014-04-20 08:17:56 -07:00
return ERROR_PSMFPLAYER_INVALID_STATUS ;
}
if ( tempBufSize < 0x00010000 ) {
ERROR_LOG_REPORT ( ME , " scePsmfPlayerSetTempBuf(%08x, %08x, %08x): buffer too small " , psmfPlayer , tempBufAddr , tempBufSize ) ;
return ERROR_PSMFPLAYER_INVALID_PARAM ;
2014-02-14 10:19:38 +08:00
}
2014-02-05 22:33:44 +08:00
INFO_LOG ( ME , " scePsmfPlayerSetTempBuf(%08x, %08x, %08x) " , psmfPlayer , tempBufAddr , tempBufSize ) ;
// fake it right now, use tempbuf from memory directly
//psmfplayer->tempbuf = tempBufAddr;
//psmfplayer->tempbufSize = tempBufSize;
2013-01-18 18:05:51 +08:00
return 0 ;
}
2014-12-08 04:40:08 -05:00
static u32 scePsmfPlayerChangePlayMode ( u32 psmfPlayer , int playMode , int playSpeed )
2013-01-18 18:05:51 +08:00
{
PsmfPlayer * psmfplayer = getPsmfPlayer ( psmfPlayer ) ;
if ( ! psmfplayer ) {
2013-09-07 22:02:55 +02:00
ERROR_LOG ( ME , " scePsmfPlayerChangePlayMode(%08x, %i, %i): invalid psmf player " , psmfPlayer , playMode , playSpeed ) ;
2014-04-25 20:30:05 -07:00
return ERROR_PSMFPLAYER_INVALID_STATUS ;
2013-01-18 18:05:51 +08:00
}
2014-04-25 20:30:05 -07:00
if ( psmfplayer - > status < PSMF_PLAYER_STATUS_PLAYING ) {
ERROR_LOG ( ME , " scePsmfPlayerChangePlayMode(%08x, %i, %i): not playing yet " , psmfPlayer , playMode , playSpeed ) ;
2014-04-20 08:17:56 -07:00
return ERROR_PSMFPLAYER_INVALID_STATUS ;
2014-02-14 10:19:38 +08:00
}
2014-04-25 20:30:05 -07:00
if ( playMode < 0 | | playMode > ( int ) PSMF_PLAYER_MODE_REWIND ) {
ERROR_LOG ( ME , " scePsmfPlayerChangePlayMode(%08x, %i, %i): invalid mode " , psmfPlayer , playMode , playSpeed ) ;
return ERROR_PSMFPLAYER_INVALID_CONFIG ;
}
switch ( playMode ) {
case PSMF_PLAYER_MODE_FORWARD :
case PSMF_PLAYER_MODE_REWIND :
if ( psmfplayer - > playerVersion = = PSMF_PLAYER_VERSION_BASIC ) {
ERROR_LOG_REPORT ( ME , " scePsmfPlayerChangePlayMode(%08x, %i, %i): no EP data for FORWARD/REWIND " , psmfPlayer , playMode , playSpeed ) ;
return ERROR_PSMFPLAYER_INVALID_STREAM ;
}
psmfplayer - > playSpeed = playSpeed ;
WARN_LOG_REPORT ( ME , " scePsmfPlayerChangePlayMode(%08x, %i, %i): unsupported playMode " , psmfPlayer , playMode , playSpeed ) ;
break ;
case PSMF_PLAYER_MODE_PLAY :
case PSMF_PLAYER_MODE_PAUSE :
if ( psmfplayer - > playSpeed ! = playSpeed ) {
WARN_LOG_REPORT ( ME , " scePsmfPlayerChangePlayMode(%08x, %i, %i): play speed not changed " , psmfPlayer , playMode , playSpeed ) ;
} else {
DEBUG_LOG ( ME , " scePsmfPlayerChangePlayMode(%08x, %i, %i) " , psmfPlayer , playMode , playSpeed ) ;
}
break ;
default :
if ( psmfplayer - > playSpeed ! = playSpeed ) {
WARN_LOG_REPORT ( ME , " scePsmfPlayerChangePlayMode(%08x, %i, %i): play speed not changed " , psmfPlayer , playMode , playSpeed ) ;
}
WARN_LOG_REPORT ( ME , " scePsmfPlayerChangePlayMode(%08x, %i, %i): unsupported playMode " , psmfPlayer , playMode , playSpeed ) ;
break ;
}
2014-02-14 10:19:38 +08:00
2013-03-30 00:42:12 -04:00
psmfplayer - > playMode = playMode ;
2013-01-18 18:05:51 +08:00
return 0 ;
}
2014-12-08 04:40:08 -05:00
static u32 scePsmfPlayerSelectAudio ( u32 psmfPlayer )
2013-01-18 18:05:51 +08:00
{
PsmfPlayer * psmfplayer = getPsmfPlayer ( psmfPlayer ) ;
if ( ! psmfplayer ) {
2013-09-07 22:02:55 +02:00
ERROR_LOG ( ME , " scePsmfPlayerSelectAudio(%08x): invalid psmf player " , psmfPlayer ) ;
2014-04-20 23:14:45 -07:00
return ERROR_PSMFPLAYER_INVALID_STATUS ;
2013-01-18 18:05:51 +08:00
}
2014-04-20 23:14:45 -07:00
if ( psmfplayer - > status ! = PSMF_PLAYER_STATUS_PLAYING ) {
ERROR_LOG ( ME , " scePsmfPlayerSelectAudio(%08x): not playing " , psmfPlayer ) ;
2014-04-20 08:17:56 -07:00
return ERROR_PSMFPLAYER_INVALID_STATUS ;
2014-02-14 10:19:38 +08:00
}
2014-04-20 23:14:45 -07:00
int next = psmfplayer - > audioStreamNum + 1 ;
if ( next > = psmfplayer - > totalAudioStreams )
next = 0 ;
if ( next = = psmfplayer - > audioStreamNum | | ! psmfplayer - > mediaengine - > setAudioStream ( next ) ) {
ERROR_LOG_REPORT ( ME , " scePsmfPlayerSelectAudio(%08x): no stream to switch to " , psmfPlayer ) ;
return ERROR_PSMFPLAYER_INVALID_STREAM ;
}
WARN_LOG_REPORT ( ME , " scePsmfPlayerSelectAudio(%08x) " , psmfPlayer ) ;
psmfplayer - > audioStreamNum = next ;
2013-01-18 18:05:51 +08:00
return 0 ;
}
2014-12-08 04:40:08 -05:00
static u32 scePsmfPlayerSelectVideo ( u32 psmfPlayer )
2013-01-18 18:05:51 +08:00
{
PsmfPlayer * psmfplayer = getPsmfPlayer ( psmfPlayer ) ;
if ( ! psmfplayer ) {
2013-09-07 22:02:55 +02:00
ERROR_LOG ( ME , " scePsmfPlayerSelectVideo(%08x): invalid psmf player " , psmfPlayer ) ;
2014-04-20 23:14:45 -07:00
return ERROR_PSMFPLAYER_INVALID_STATUS ;
2013-01-18 18:05:51 +08:00
}
2014-04-20 23:14:45 -07:00
if ( psmfplayer - > status ! = PSMF_PLAYER_STATUS_PLAYING ) {
ERROR_LOG ( ME , " scePsmfPlayerSelectVideo(%08x): not playing " , psmfPlayer ) ;
2014-04-20 08:17:56 -07:00
return ERROR_PSMFPLAYER_INVALID_STATUS ;
2014-02-14 10:19:38 +08:00
}
2014-04-20 23:14:45 -07:00
int next = psmfplayer - > videoStreamNum + 1 ;
if ( next > = psmfplayer - > totalVideoStreams )
next = 0 ;
if ( next = = psmfplayer - > videoStreamNum | | ! psmfplayer - > mediaengine - > setVideoStream ( next ) ) {
ERROR_LOG_REPORT ( ME , " scePsmfPlayerSelectVideo(%08x): no stream to switch to " , psmfPlayer ) ;
return ERROR_PSMFPLAYER_INVALID_STREAM ;
}
WARN_LOG_REPORT ( ME , " scePsmfPlayerSelectVideo(%08x) " , psmfPlayer ) ;
psmfplayer - > videoStreamNum = next ;
2013-01-18 18:05:51 +08:00
return 0 ;
}
2014-12-08 04:40:08 -05:00
static u32 scePsmfPlayerSelectSpecificVideo ( u32 psmfPlayer , int videoCodec , int videoStreamNum )
2013-01-18 18:05:51 +08:00
{
PsmfPlayer * psmfplayer = getPsmfPlayer ( psmfPlayer ) ;
if ( ! psmfplayer ) {
2013-09-07 22:02:55 +02:00
ERROR_LOG ( ME , " scePsmfPlayerSelectSpecificVideo(%08x, %i, %i): invalid psmf player " , psmfPlayer , videoCodec , videoStreamNum ) ;
2014-04-20 23:57:32 -07:00
return ERROR_PSMFPLAYER_INVALID_STATUS ;
2013-01-18 18:05:51 +08:00
}
2014-04-20 23:57:32 -07:00
if ( psmfplayer - > status ! = PSMF_PLAYER_STATUS_PLAYING ) {
ERROR_LOG ( ME , " scePsmfPlayerSelectSpecificVideo(%08x, %i, %i): not playing " , psmfPlayer , videoCodec , videoStreamNum ) ;
2014-04-20 08:17:56 -07:00
return ERROR_PSMFPLAYER_INVALID_STATUS ;
2014-02-14 10:19:38 +08:00
}
2014-04-20 23:57:32 -07:00
if ( psmfplayer - > totalVideoStreams < 2 ) {
ERROR_LOG_REPORT ( ME , " scePsmfPlayerSelectSpecificVideo(%08x, %i, %i): unable to change stream " , psmfPlayer , videoCodec , videoStreamNum ) ;
return ERROR_PSMFPLAYER_INVALID_STREAM ;
}
if ( videoStreamNum < 0 | | videoStreamNum > = psmfplayer - > totalVideoStreams ) {
ERROR_LOG_REPORT ( ME , " scePsmfPlayerSelectSpecificVideo(%08x, %i, %i): bad stream num param " , psmfPlayer , videoCodec , videoStreamNum ) ;
return ERROR_PSMFPLAYER_INVALID_CONFIG ;
}
if ( videoCodec ! = 0x0E & & videoCodec ! = 0x00 ) {
ERROR_LOG_REPORT ( ME , " scePsmfPlayerSelectSpecificVideo(%08x, %i, %i): invalid codec " , psmfPlayer , videoCodec , videoStreamNum ) ;
return ERROR_PSMFPLAYER_INVALID_STREAM ;
}
if ( psmfplayer - > totalVideoStreams < 2 | | ! psmfplayer - > mediaengine - > setVideoStream ( videoStreamNum ) ) {
ERROR_LOG_REPORT ( ME , " scePsmfPlayerSelectSpecificVideo(%08x, %i, %i): unable to change stream " , psmfPlayer , videoCodec , videoStreamNum ) ;
return ERROR_PSMFPLAYER_INVALID_STREAM ;
}
2014-02-14 10:19:38 +08:00
2014-04-20 23:57:32 -07:00
WARN_LOG_REPORT ( ME , " scePsmfPlayerSelectSpecificVideo(%08x, %i, %i) " , psmfPlayer , videoCodec , videoStreamNum ) ;
if ( psmfplayer - > videoStreamNum ! = videoStreamNum ) {
hleDelayResult ( 0 , " psmf select video " , 100 ) ;
}
2013-03-30 00:42:12 -04:00
psmfplayer - > videoCodec = videoCodec ;
psmfplayer - > videoStreamNum = videoStreamNum ;
2013-01-18 18:05:51 +08:00
return 0 ;
}
2014-04-20 23:57:32 -07:00
// WARNING: This function appears to be buggy in most libraries.
2014-12-08 04:40:08 -05:00
static u32 scePsmfPlayerSelectSpecificAudio ( u32 psmfPlayer , int audioCodec , int audioStreamNum )
2013-01-18 18:05:51 +08:00
{
PsmfPlayer * psmfplayer = getPsmfPlayer ( psmfPlayer ) ;
if ( ! psmfplayer ) {
2013-09-07 22:02:55 +02:00
ERROR_LOG ( ME , " scePsmfPlayerSelectSpecificAudio(%08x, %i, %i): invalid psmf player " , psmfPlayer , audioCodec , audioStreamNum ) ;
2014-04-20 23:57:32 -07:00
return ERROR_PSMFPLAYER_INVALID_STATUS ;
2013-01-18 18:05:51 +08:00
}
2014-04-20 23:57:32 -07:00
if ( psmfplayer - > status ! = PSMF_PLAYER_STATUS_PLAYING ) {
ERROR_LOG ( ME , " scePsmfPlayerSelectSpecificAudio(%08x, %i, %i): not playing " , psmfPlayer , audioCodec , audioStreamNum ) ;
2014-04-20 08:17:56 -07:00
return ERROR_PSMFPLAYER_INVALID_STATUS ;
2014-02-14 10:19:38 +08:00
}
2014-04-20 23:57:32 -07:00
if ( psmfplayer - > totalAudioStreams < 2 ) {
ERROR_LOG_REPORT ( ME , " scePsmfPlayerSelectSpecificAudio(%08x, %i, %i): unable to change stream " , psmfPlayer , audioCodec , audioStreamNum ) ;
return ERROR_PSMFPLAYER_INVALID_STREAM ;
}
if ( audioStreamNum < 0 | | audioStreamNum > = psmfplayer - > totalAudioStreams ) {
ERROR_LOG_REPORT ( ME , " scePsmfPlayerSelectSpecificAudio(%08x, %i, %i): bad stream num param " , psmfPlayer , audioCodec , audioStreamNum ) ;
return ERROR_PSMFPLAYER_INVALID_CONFIG ;
}
if ( audioCodec ! = 0x0F & & audioCodec ! = 0x01 ) {
ERROR_LOG_REPORT ( ME , " scePsmfPlayerSelectSpecificAudio(%08x, %i, %i): invalid codec " , psmfPlayer , audioCodec , audioStreamNum ) ;
return ERROR_PSMFPLAYER_INVALID_STREAM ;
}
if ( psmfplayer - > totalAudioStreams < 2 | | ! psmfplayer - > mediaengine - > setAudioStream ( audioStreamNum ) ) {
ERROR_LOG_REPORT ( ME , " scePsmfPlayerSelectSpecificAudio(%08x, %i, %i): unable to change stream " , psmfPlayer , audioCodec , audioStreamNum ) ;
return ERROR_PSMFPLAYER_INVALID_STREAM ;
}
2014-02-14 10:19:38 +08:00
2014-04-20 23:57:32 -07:00
WARN_LOG_REPORT ( ME , " scePsmfPlayerSelectSpecificAudio(%08x, %i, %i) " , psmfPlayer , audioCodec , audioStreamNum ) ;
if ( psmfplayer - > audioStreamNum ! = audioStreamNum ) {
hleDelayResult ( 0 , " psmf select audio " , 100 ) ;
}
2013-03-30 00:42:12 -04:00
psmfplayer - > audioCodec = audioCodec ;
psmfplayer - > audioStreamNum = audioStreamNum ;
2013-01-18 18:05:51 +08:00
return 0 ;
}
2014-12-08 04:40:08 -05:00
static u32 scePsmfPlayerConfigPlayer ( u32 psmfPlayer , int configMode , int configAttr )
2013-01-18 18:05:51 +08:00
{
PsmfPlayer * psmfplayer = getPsmfPlayer ( psmfPlayer ) ;
if ( ! psmfplayer ) {
2013-09-07 22:02:55 +02:00
ERROR_LOG ( ME , " scePsmfPlayerConfigPlayer(%08x, %i, %i): invalid psmf player " , psmfPlayer , configMode , configAttr ) ;
2014-04-20 08:17:56 -07:00
return ERROR_PSMFPLAYER_INVALID_STATUS ;
2014-02-14 10:19:38 +08:00
}
2014-04-20 19:19:12 -07:00
// This one works in any status as long as it's created.
2014-02-14 10:19:38 +08:00
2014-02-05 22:33:44 +08:00
switch ( configMode ) {
case PSMF_PLAYER_CONFIG_MODE_LOOP :
2014-04-20 19:19:12 -07:00
if ( configAttr ! = 0 & & configAttr ! = 1 ) {
ERROR_LOG_REPORT ( ME , " scePsmfPlayerConfigPlayer(%08x, loop, %i): invalid value " , psmfPlayer , configAttr ) ;
return ERROR_PSMFPLAYER_INVALID_PARAM ;
}
2013-09-07 22:02:55 +02:00
INFO_LOG ( ME , " scePsmfPlayerConfigPlayer(%08x, loop, %i) " , psmfPlayer , configAttr ) ;
2013-01-18 18:05:51 +08:00
videoLoopStatus = configAttr ;
2014-02-05 22:33:44 +08:00
break ;
case PSMF_PLAYER_CONFIG_MODE_PIXEL_TYPE :
2014-04-20 19:19:12 -07:00
if ( configAttr < - 1 | | configAttr > 3 ) {
ERROR_LOG_REPORT ( ME , " scePsmfPlayerConfigPlayer(%08x, pixelType, %i): invalid value " , psmfPlayer , configAttr ) ;
return ERROR_PSMFPLAYER_INVALID_PARAM ;
}
2013-09-07 22:02:55 +02:00
INFO_LOG ( ME , " scePsmfPlayerConfigPlayer(%08x, pixelType, %i) " , psmfPlayer , configAttr ) ;
2013-06-02 13:52:11 -07:00
// Does -1 mean default or something?
if ( configAttr ! = - 1 ) {
videoPixelMode = configAttr ;
2014-04-20 19:19:12 -07:00
} else {
// TODO: At least for one video, this was the same as 8888.
videoPixelMode = GE_CMODE_32BIT_ABGR8888 ;
2013-06-02 13:52:11 -07:00
}
2014-02-05 22:33:44 +08:00
break ;
default :
2013-09-07 22:02:55 +02:00
ERROR_LOG_REPORT ( ME , " scePsmfPlayerConfigPlayer(%08x, %i, %i): unknown parameter " , psmfPlayer , configMode , configAttr ) ;
2014-04-20 19:19:12 -07:00
return ERROR_PSMFPLAYER_INVALID_CONFIG ;
2013-01-18 18:05:51 +08:00
}
return 0 ;
}
2014-12-08 04:40:08 -05:00
static int __PsmfPlayerFinish ( u32 psmfPlayer ) {
2014-05-22 23:40:44 -07:00
PsmfPlayer * psmfplayer = getPsmfPlayer ( psmfPlayer ) ;
if ( ! psmfplayer ) {
ERROR_LOG_REPORT ( ME , " __PsmfPlayerFinish(%08x): invalid psmf player " , psmfPlayer ) ;
return ERROR_PSMFPLAYER_INVALID_STATUS ;
}
if ( psmfplayer - > status ! = PSMF_PLAYER_STATUS_PLAYING ) {
ERROR_LOG_REPORT ( ME , " __PsmfPlayerFinish(%08x): unexpected status %d " , psmfPlayer , psmfplayer - > status ) ;
return ERROR_PSMFPLAYER_INVALID_STATUS ;
}
INFO_LOG ( ME , " __PsmfPlayerFinish(%08x): video end reached " , psmfPlayer ) ;
psmfplayer - > status = PSMF_PLAYER_STATUS_PLAYING_FINISHED ;
return 0 ;
}
2013-01-24 19:40:26 +08:00
const HLEFunction scePsmf [ ] = {
2015-03-22 16:57:56 -07:00
{ 0XC22C8327 , & WrapU_UU < scePsmfSetPsmf > , " scePsmfSetPsmf " , ' x ' , " xx " } ,
2016-05-31 00:53:40 -07:00
{ 0XC7DB3A5B , & WrapU_UUU < scePsmfGetCurrentStreamType > , " scePsmfGetCurrentStreamType " , ' i ' , " xpp " } ,
{ 0X28240568 , & WrapU_U < scePsmfGetCurrentStreamNumber > , " scePsmfGetCurrentStreamNumber " , ' i ' , " x " } ,
{ 0X1E6D9013 , & WrapU_UUU < scePsmfSpecifyStreamWithStreamType > , " scePsmfSpecifyStreamWithStreamType " , ' i ' , " xii " } ,
{ 0X0C120E1D , & WrapU_UUU < scePsmfSpecifyStreamWithStreamTypeNumber > , " scePsmfSpecifyStreamWithStreamTypeNumber " , ' i ' , " xii " } ,
{ 0X4BC9BDE0 , & WrapU_UI < scePsmfSpecifyStream > , " scePsmfSpecifyStream " , ' i ' , " xi " } ,
2015-03-22 16:57:56 -07:00
{ 0X76D3AEBA , & WrapU_UU < scePsmfGetPresentationStartTime > , " scePsmfGetPresentationStartTime " , ' x ' , " xx " } ,
{ 0XBD8AE0D8 , & WrapU_UU < scePsmfGetPresentationEndTime > , " scePsmfGetPresentationEndTime " , ' x ' , " xx " } ,
2016-05-30 23:32:42 -07:00
{ 0XEAED89CD , & WrapU_U < scePsmfGetNumberOfStreams > , " scePsmfGetNumberOfStreams " , ' i ' , " x " } ,
2015-03-22 16:57:56 -07:00
{ 0X7491C438 , & WrapU_U < scePsmfGetNumberOfEPentries > , " scePsmfGetNumberOfEPentries " , ' x ' , " x " } ,
{ 0X0BA514E5 , & WrapU_UU < scePsmfGetVideoInfo > , " scePsmfGetVideoInfo " , ' x ' , " xx " } ,
{ 0XA83F7113 , & WrapU_UU < scePsmfGetAudioInfo > , " scePsmfGetAudioInfo " , ' x ' , " xx " } ,
{ 0X971A3A90 , & WrapU_U < scePsmfCheckEPMap > , " scePsmfCheckEPmap " , ' x ' , " x " } ,
2016-05-30 23:32:42 -07:00
{ 0X68D42328 , & WrapU_UI < scePsmfGetNumberOfSpecificStreams > , " scePsmfGetNumberOfSpecificStreams " , ' i ' , " xi " } ,
2015-03-22 16:57:56 -07:00
{ 0X5B70FCC1 , & WrapU_UU < scePsmfQueryStreamOffset > , " scePsmfQueryStreamOffset " , ' x ' , " xx " } ,
{ 0X9553CC91 , & WrapU_UU < scePsmfQueryStreamSize > , " scePsmfQueryStreamSize " , ' x ' , " xx " } ,
{ 0XB78EB9E9 , & WrapU_UU < scePsmfGetHeaderSize > , " scePsmfGetHeaderSize " , ' x ' , " xx " } ,
{ 0XA5EBFE81 , & WrapU_UU < scePsmfGetStreamSize > , " scePsmfGetStreamSize " , ' x ' , " xx " } ,
{ 0XE1283895 , & WrapU_U < scePsmfGetPsmfVersion > , " scePsmfGetPsmfVersion " , ' x ' , " x " } ,
{ 0X2673646B , & WrapU_U < scePsmfVerifyPsmf > , " scePsmfVerifyPsmf " , ' x ' , " x " } ,
{ 0X4E624A34 , & WrapU_UIU < scePsmfGetEPWithId > , " scePsmfGetEPWithId " , ' x ' , " xix " } ,
{ 0X7C0E7AC3 , & WrapU_UUU < scePsmfGetEPWithTimestamp > , " scePsmfGetEPWithTimestamp " , ' x ' , " xxx " } ,
{ 0X5F457515 , & WrapU_UU < scePsmfGetEPidWithTimestamp > , " scePsmfGetEPidWithTimestamp " , ' x ' , " xx " } ,
{ 0X43AC7DBB , nullptr , " scePsmfGetPsmfMark " , ' ? ' , " " } ,
{ 0XDE78E9FC , nullptr , " scePsmfGetNumberOfPsmfMarks " , ' ? ' , " " } ,
2013-01-24 19:40:26 +08:00
} ;
2012-11-01 16:19:01 +01:00
const HLEFunction scePsmfPlayer [ ] =
{
2015-03-22 16:57:56 -07:00
{ 0X235D8787 , & WrapI_UU < scePsmfPlayerCreate > , " scePsmfPlayerCreate " , ' i ' , " xx " } ,
{ 0X1078C008 , & WrapI_U < scePsmfPlayerStop > , " scePsmfPlayerStop " , ' i ' , " x " } ,
{ 0X1E57A8E7 , & WrapU_UII < scePsmfPlayerConfigPlayer > , " scePsmfPlayerConfigPlayer " , ' x ' , " xii " } ,
{ 0X2BEB1569 , & WrapI_U < scePsmfPlayerBreak > , " scePsmfPlayerBreak " , ' i ' , " x " } ,
{ 0X3D6D25A9 , & WrapI_UC < scePsmfPlayerSetPsmf > , " scePsmfPlayerSetPsmf " , ' i ' , " xs " } ,
{ 0X58B83577 , & WrapI_UC < scePsmfPlayerSetPsmfCB > , " scePsmfPlayerSetPsmfCB " , ' i ' , " xs " } ,
{ 0X3EA82A4B , & WrapI_U < scePsmfPlayerGetAudioOutSize > , " scePsmfPlayerGetAudioOutSize " , ' i ' , " x " } ,
{ 0X3ED62233 , & WrapU_UU < scePsmfPlayerGetCurrentPts > , " scePsmfPlayerGetCurrentPts " , ' x ' , " xx " } ,
{ 0X46F61F8B , & WrapI_UU < scePsmfPlayerGetVideoData > , " scePsmfPlayerGetVideoData " , ' i ' , " xx " } ,
{ 0X68F07175 , & WrapU_UUU < scePsmfPlayerGetCurrentAudioStream > , " scePsmfPlayerGetCurrentAudioStream " , ' x ' , " xxx " } ,
{ 0X75F03FA2 , & WrapU_UII < scePsmfPlayerSelectSpecificVideo > , " scePsmfPlayerSelectSpecificVideo " , ' x ' , " xii " } ,
{ 0X85461EFF , & WrapU_UII < scePsmfPlayerSelectSpecificAudio > , " scePsmfPlayerSelectSpecificAudio " , ' x ' , " xii " } ,
{ 0X8A9EBDCD , & WrapU_U < scePsmfPlayerSelectVideo > , " scePsmfPlayerSelectVideo " , ' x ' , " x " } ,
{ 0X95A84EE5 , & WrapI_UUI < scePsmfPlayerStart > , " scePsmfPlayerStart " , ' i ' , " xxi " } ,
{ 0X9B71A274 , & WrapI_U < scePsmfPlayerDelete > , " scePsmfPlayerDelete " , ' i ' , " x " } ,
{ 0X9FF2B2E7 , & WrapU_UUU < scePsmfPlayerGetCurrentVideoStream > , " scePsmfPlayerGetCurrentVideoStream " , ' x ' , " xxx " } ,
{ 0XA0B8CA55 , & WrapI_U < scePsmfPlayerUpdate > , " scePsmfPlayerUpdate " , ' i ' , " x " } ,
{ 0XA3D81169 , & WrapU_UII < scePsmfPlayerChangePlayMode > , " scePsmfPlayerChangePlayMode " , ' x ' , " xii " } ,
{ 0XB8D10C56 , & WrapU_U < scePsmfPlayerSelectAudio > , " scePsmfPlayerSelectAudio " , ' x ' , " x " } ,
{ 0XB9848A74 , & WrapI_UU < scePsmfPlayerGetAudioData > , " scePsmfPlayerGetAudioData " , ' i ' , " xx " } ,
{ 0XDF089680 , & WrapU_UU < scePsmfPlayerGetPsmfInfo > , " scePsmfPlayerGetPsmfInfo " , ' x ' , " xx " } ,
{ 0XE792CD94 , & WrapI_U < scePsmfPlayerReleasePsmf > , " scePsmfPlayerReleasePsmf " , ' i ' , " x " } ,
{ 0XF3EFAA91 , & WrapU_UUU < scePsmfPlayerGetCurrentPlayMode > , " scePsmfPlayerGetCurrentPlayMode " , ' x ' , " xxx " } ,
{ 0XF8EF08A6 , & WrapI_U < scePsmfPlayerGetCurrentStatus > , " scePsmfPlayerGetCurrentStatus " , ' i ' , " x " } ,
{ 0X2D0E4E0A , & WrapI_UUU < scePsmfPlayerSetTempBuf > , " scePsmfPlayerSetTempBuf " , ' i ' , " xxx " } ,
{ 0X76C0F4AE , & WrapI_UCI < scePsmfPlayerSetPsmfOffset > , " scePsmfPlayerSetPsmfOffset " , ' i ' , " xsi " } ,
{ 0XA72DB4F9 , & WrapI_UCI < scePsmfPlayerSetPsmfOffsetCB > , " scePsmfPlayerSetPsmfOffsetCB " , ' i ' , " xsi " } ,
{ 0X340C12CB , nullptr , " scePsmfPlayer_340C12CB " , ' ? ' , " " } ,
2014-05-22 23:40:44 -07:00
// Fake function for PPSSPP's use.
2015-03-22 16:57:56 -07:00
{ 0X05B193B7 , & WrapI_U < __PsmfPlayerFinish > , " __PsmfPlayerFinish " , ' i ' , " x " } ,
2012-11-01 16:19:01 +01:00
} ;
void Register_scePsmf ( ) {
2012-12-24 10:44:40 -08:00
RegisterModule ( " scePsmf " , ARRAY_SIZE ( scePsmf ) , scePsmf ) ;
2012-11-01 16:19:01 +01:00
}
void Register_scePsmfPlayer ( ) {
2012-12-24 10:44:40 -08:00
RegisterModule ( " scePsmfPlayer " , ARRAY_SIZE ( scePsmfPlayer ) , scePsmfPlayer ) ;
2012-11-01 16:19:01 +01:00
}