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 "Core/HLE/HLE.h"
2014-03-15 11:22:19 -07:00
# include "Core/HLE/FunctionWrappers.h"
2013-05-19 17:54:14 -07:00
# include "Common/ChunkFile.h"
# include "Core/Reporting.h"
2012-11-01 16:19:01 +01:00
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"
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 psmfMaxAheadTimestamp = 40000 ;
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
} ;
2013-02-10 23:01:18 +10:00
int getMaxAheadTimestamp ( int packets ) { return std : : max ( 40000 , packets * 700 ) ; }
2013-01-18 18:05:51 +08:00
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
bool isValidCurrentStreamNumber ( ) {
2013-07-07 18:10:55 -07:00
return currentStreamNum > = 0 & & currentStreamNum < ( int ) streamMap . size ( ) ; // urgh, checking size isn't really right here.
2013-06-05 21:24:14 +02:00
}
void setStreamNum ( int num ) ;
bool setStreamWithType ( int type , int channel ) ;
2012-12-29 03:19:13 -08:00
2014-01-01 13:23:19 -08:00
int FindEPWithTimestamp ( int pts ) ;
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 ;
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.
2013-06-16 03:27:14 +08:00
PsmfPlayer ( ) { mediaengine = new MediaEngine ; filehandle = 0 ; }
2014-04-20 00:01:16 -07:00
PsmfPlayer ( const PsmfPlayerCreateData * data ) ;
2013-06-16 03:27:14 +08: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
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 ;
int psmfMaxAheadTimestamp ;
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
MediaEngine * mediaengine ;
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-05-15 00:10:01 -07:00
psmf - > EPMapOffset = * ( u32_be * ) & addr [ 4 ] ;
psmf - > EPMapEntriesNum = * ( u32_be * ) & addr [ 8 ] ;
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 ] ;
entry . EPPts = * ( u32_be * ) & entryAddr [ 2 ] ;
entry . EPOffset = * ( u32_be * ) & 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
}
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 ] ;
streamOffset = * ( u32_be * ) & ptr [ 8 ] ;
streamSize = * ( u32_be * ) & ptr [ 12 ] ;
streamDataTotalSize = * ( u32_be * ) & ptr [ 0x50 ] ;
presentationStartTime = getMpegTimeStamp ( ptr + PSMF_FIRST_TIMESTAMP_OFFSET ) ;
presentationEndTime = getMpegTimeStamp ( ptr + PSMF_LAST_TIMESTAMP_OFFSET ) ;
streamDataNextBlockSize = * ( u32_be * ) & ptr [ 0x6A ] ;
streamDataNextInnerBlockSize = * ( u32_be * ) & ptr [ 0x7C ] ;
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 ;
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 ) {
2013-06-16 01:35:47 +08:00
stream = new PsmfStream ( PSMF_AVC_STREAM , + + currentVideoStreamNum ) ;
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 ) {
2013-06-16 01:35:47 +08:00
stream = new PsmfStream ( PSMF_ATRAC_STREAM , + + currentAudioStreamNum ) ;
2012-11-13 18:05:26 +01:00
stream - > readPrivateAudioStreamParams ( currentStreamAddr , this ) ;
}
if ( stream ) {
currentStreamNum + + ;
streamMap [ currentStreamNum ] = stream ;
}
}
}
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 ;
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 ) {
2014-01-01 13:23:19 -08:00
auto s = p . Section ( " Psmf " , 1 , 2 ) ;
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 ) ;
2012-12-28 23:29:24 -08:00
}
2013-01-19 21:05:05 +08:00
void PsmfPlayer : : DoState ( PointerWrap & p ) {
2014-05-15 00:14:27 -07:00
auto s = p . Section ( " PsmfPlayer " , 1 , 5 ) ;
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 ) ;
p . Do ( psmfMaxAheadTimestamp ) ;
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 ) ;
2013-01-19 21:05:05 +08:00
}
2013-06-05 21:24:14 +02:00
void Psmf : : setStreamNum ( int num ) {
currentStreamNum = num ;
if ( ! isValidCurrentStreamNumber ( ) )
return ;
PsmfStreamMap : : iterator iter = streamMap . find ( currentStreamNum ) ;
if ( iter = = streamMap . end ( ) )
return ;
int type = iter - > second - > type ;
int channel = iter - > second - > channel ;
switch ( type ) {
case PSMF_AVC_STREAM :
if ( currentVideoStreamNum ! = num ) {
2014-01-14 19:31:09 +01:00
// TODO: Tell video mediaengine or something about channel.
2013-06-05 21:24:14 +02:00
currentVideoStreamNum = num ;
}
break ;
case PSMF_ATRAC_STREAM :
case PSMF_PCM_STREAM :
if ( currentAudioStreamNum ! = num ) {
2014-01-14 19:31:09 +01:00
// TODO: Tell audio mediaengine or something about channel.
2013-06-05 21:24:14 +02:00
currentAudioStreamNum = num ;
}
break ;
}
}
bool Psmf : : setStreamWithType ( int type , int channel ) {
for ( PsmfStreamMap : : iterator iter = streamMap . begin ( ) ; iter ! = streamMap . end ( ) ; + + iter ) {
2013-07-01 14:02:12 +08:00
if ( iter - > second - > type = = type & & iter - > second - > channel = = channel ) {
2013-06-05 21:24:14 +02:00
setStreamNum ( iter - > first ) ;
return true ;
}
}
return false ;
}
2014-01-01 13:23:19 -08:00
int Psmf : : FindEPWithTimestamp ( int pts ) {
int best = - 1 ;
int bestPts = 0 ;
for ( int i = 0 ; i < ( int ) EPMap . size ( ) ; + + i ) {
const int matchPts = EPMap [ i ] . EPPts ;
if ( matchPts = = pts ) {
// Exact match, take it.
return i ;
}
// TODO: Does it actually do fuzzy matching?
if ( matchPts < pts & & matchPts > = bestPts ) {
best = i ;
bestPts = matchPts ;
}
}
return best ;
}
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
2012-12-24 10:44:40 -08:00
Psmf * getPsmf ( u32 psmf )
{
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 ;
}
2013-01-18 18:05:51 +08:00
PsmfPlayer * getPsmfPlayer ( u32 psmfplayer )
{
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-02-14 10:19:38 +08:00
bool isPlayingStatus ( u32 status ) {
if ( status ! = PSMF_PLAYER_STATUS_PLAYING & & status ! = PSMF_PLAYER_STATUS_PLAYING_FINISHED ) {
return false ;
}
return true ;
}
bool isInitializedStatus ( u32 status ) {
if ( status = = PSMF_PLAYER_STATUS_NONE ) {
return false ;
}
return true ;
}
2012-11-01 16:19:01 +01:00
u32 scePsmfSetPsmf ( u32 psmfStruct , u32 psmfData )
{
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
}
u32 scePsmfGetNumberOfStreams ( u32 psmfStruct )
{
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 , " scePsmfGetNumberOfStreams(%08x): invalid psmf " , psmfStruct ) ;
2012-11-13 18:05:26 +01:00
return ERROR_PSMF_NOT_FOUND ;
}
2013-09-07 22:02:55 +02:00
DEBUG_LOG ( ME , " scePsmfGetNumberOfStreams(%08x) " , psmfStruct ) ;
2013-01-18 18:05:51 +08:00
return psmf - > numStreams ;
2012-11-01 16:19:01 +01:00
}
2013-07-07 18:10:55 -07:00
u32 scePsmfGetNumberOfSpecificStreams ( u32 psmfStruct , int streamType )
2012-11-01 16:19:01 +01:00
{
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 , " scePsmfGetNumberOfSpecificStreams(%08x, %08x): invalid psmf " , psmfStruct , streamType ) ;
2012-11-13 18:05:26 +01:00
return ERROR_PSMF_NOT_FOUND ;
}
2013-09-07 22:02:55 +02:00
WARN_LOG ( ME , " scePsmfGetNumberOfSpecificStreams(%08x, %08x) " , psmfStruct , streamType ) ;
2013-06-15 01:39:56 +08:00
int streamNum = 0 ;
2013-06-16 01:35:47 +08:00
int type = ( streamType = = PSMF_AUDIO_STREAM ? PSMF_ATRAC_STREAM : streamType ) ;
2013-07-22 19:22:21 +02:00
for ( int i = ( int ) psmf - > streamMap . size ( ) - 1 ; i > = 0 ; i - - ) {
2013-06-16 01:35:47 +08:00
if ( psmf - > streamMap [ i ] - > type = = type )
2013-06-15 01:39:56 +08:00
streamNum + + ;
}
return streamNum ;
2012-11-01 16:19:01 +01:00
}
2012-12-17 18:48:32 +01:00
u32 scePsmfSpecifyStreamWithStreamType ( u32 psmfStruct , u32 streamType , u32 channel )
2012-11-01 16:19:01 +01:00
{
2013-06-05 21:24:14 +02:00
Psmf * psmf = getPsmf ( psmfStruct ) ;
if ( ! psmf ) {
2013-09-07 22:02:55 +02:00
ERROR_LOG ( ME , " scePsmfSpecifyStreamWithStreamType(%08x, %08x, %i): invalid psmf " , psmfStruct , streamType , channel ) ;
2013-06-05 21:24:14 +02:00
return ERROR_PSMF_NOT_FOUND ;
}
2013-09-07 22:02:55 +02:00
INFO_LOG ( ME , " scePsmfSpecifyStreamWithStreamType(%08x, %08x, %i) " , psmfStruct , streamType , channel ) ;
2013-06-05 21:24:14 +02:00
if ( ! psmf - > setStreamWithType ( streamType , channel ) ) {
psmf - > setStreamNum ( - 1 ) ;
}
2012-12-24 10:44:40 -08:00
return 0 ;
2012-11-01 16:19:01 +01:00
}
2012-12-17 18:48:32 +01:00
u32 scePsmfSpecifyStreamWithStreamTypeNumber ( u32 psmfStruct , u32 streamType , u32 typeNum )
{
2013-06-05 21:24:14 +02:00
Psmf * psmf = getPsmf ( psmfStruct ) ;
if ( ! psmf ) {
2013-09-07 22:02:55 +02:00
ERROR_LOG ( ME , " scePsmfSpecifyStreamWithStreamTypeNumber(%08x, %08x, %08x): invalid psmf " , psmfStruct , streamType , typeNum ) ;
2013-06-05 21:24:14 +02:00
return ERROR_PSMF_NOT_FOUND ;
}
2013-09-07 22:02:55 +02:00
INFO_LOG_REPORT ( ME , " scePsmfSpecifyStreamWithStreamTypeNumber(%08x, %08x, %08x) " , psmfStruct , streamType , typeNum ) ;
2013-07-01 14:02:12 +08:00
// right now typeNum and channel are the same...
if ( ! psmf - > setStreamWithType ( streamType , typeNum ) ) {
psmf - > setStreamNum ( - 1 ) ;
}
2012-12-17 18:48:32 +01:00
return 0 ;
}
2013-06-05 21:24:14 +02:00
u32 scePsmfSpecifyStream ( u32 psmfStruct , int streamNum ) {
Psmf * psmf = getPsmf ( psmfStruct ) ;
if ( ! psmf ) {
2013-09-07 22:02:55 +02:00
ERROR_LOG ( ME , " scePsmfSpecifyStream(%08x, %i): invalid psmf " , psmfStruct , streamNum ) ;
2013-06-05 21:24:14 +02:00
return ERROR_PSMF_NOT_FOUND ;
}
2013-09-07 22:02:55 +02:00
INFO_LOG ( ME , " scePsmfSpecifyStream(%08x, %i) " , psmfStruct , streamNum ) ;
2013-06-05 21:24:14 +02:00
psmf - > setStreamNum ( streamNum ) ;
2013-06-05 19:56:36 +02:00
return 0 ;
}
2013-01-05 18:10:13 +01:00
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
}
2013-01-05 18:10:13 +01:00
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
}
2013-01-05 18:10:13 +01:00
u32 scePsmfGetCurrentStreamType ( u32 psmfStruct , u32 typeAddr , u32 channelAddr ) {
Psmf * psmf = getPsmf ( psmfStruct ) ;
if ( ! psmf ) {
2013-09-07 22:02:55 +02:00
ERROR_LOG ( ME , " scePsmfGetCurrentStreamType(%08x, %08x, %08x): invalid psmf " , psmfStruct , typeAddr , channelAddr ) ;
2013-01-05 18:10:13 +01:00
return ERROR_PSMF_NOT_FOUND ;
}
2013-09-07 22:02:55 +02:00
INFO_LOG ( ME , " scePsmfGetCurrentStreamType(%08x, %08x, %08x) " , psmfStruct , typeAddr , channelAddr ) ;
2013-01-05 18:10:13 +01:00
if ( Memory : : IsValidAddress ( typeAddr ) ) {
u32 type = 0 , channel = 0 ;
if ( psmf - > streamMap . find ( psmf - > currentStreamNum ) ! = psmf - > streamMap . end ( ) )
type = psmf - > streamMap [ psmf - > currentStreamNum ] - > type ;
if ( psmf - > streamMap . find ( psmf - > currentStreamNum ) ! = psmf - > streamMap . end ( ) )
channel = psmf - > streamMap [ psmf - > currentStreamNum ] - > channel ;
Memory : : Write_U32 ( type , typeAddr ) ;
Memory : : Write_U32 ( channel , channelAddr ) ;
}
return 0 ;
}
2012-11-13 18:05:26 +01:00
2013-01-18 18:05:51 +08:00
u32 scePsmfGetStreamSize ( u32 psmfStruct , u32 sizeAddr )
{
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 ;
}
2013-03-29 01:05:11 -07:00
u32 scePsmfQueryStreamOffset ( u32 bufferAddr , u32 offsetAddr )
{
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
}
u32 scePsmfQueryStreamSize ( u32 bufferAddr , u32 sizeAddr )
{
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 ;
}
2013-01-18 18:05:51 +08:00
u32 scePsmfGetHeaderSize ( u32 psmfStruct , u32 sizeAddr )
{
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 ;
}
u32 scePsmfGetPsmfVersion ( u32 psmfStruct )
{
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 ;
}
2013-01-29 01:28:51 +01:00
u32 scePsmfVerifyPsmf ( u32 psmfAddr )
{
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 ;
}
2013-01-18 18:05:51 +08:00
u32 scePsmfGetNumberOfEPentries ( u32 psmfStruct )
{
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 ;
}
u32 scePsmfGetPresentationStartTime ( u32 psmfStruct , u32 startTimeAddr )
{
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 ;
}
u32 scePsmfGetPresentationEndTime ( u32 psmfStruct , u32 endTimeAddr )
{
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 ;
}
u32 scePsmfGetCurrentStreamNumber ( u32 psmfStruct )
{
Psmf * psmf = getPsmf ( psmfStruct ) ;
if ( ! psmf ) {
2013-09-07 22:02:55 +02:00
ERROR_LOG ( ME , " scePsmfGetCurrentStreamNumber(%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 , " scePsmfGetCurrentStreamNumber(%08x) " , psmfStruct ) ;
2013-01-18 18:05:51 +08:00
return psmf - > currentStreamNum ;
}
2014-01-10 19:15:35 +08:00
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-01-01 13:23:19 -08:00
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 ;
}
2013-01-22 23:44:23 -08:00
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 ;
}
2013-01-22 23:44:23 -08:00
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-04-20 00:01:16 -07:00
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-01-24 19:40:26 +08:00
psmfplayer - > psmfMaxAheadTimestamp = getMaxAheadTimestamp ( 581 ) ;
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-01-08 14:20:20 +01:00
int scePsmfPlayerStop ( 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 , " scePsmfPlayerStop(%08x): invalid psmf player " , psmfPlayer ) ;
return ERROR_PSMF_NOT_FOUND ;
}
2014-02-14 10:19:38 +08:00
bool isInitialized = isInitializedStatus ( psmfplayer - > status ) ;
if ( ! isInitialized ) {
2014-02-13 20:22:56 +08:00
ERROR_LOG ( ME , " scePsmfPlayerStop(%08x): not initialized " , psmfPlayer ) ;
2014-04-20 08:17:56 -07:00
return ERROR_PSMFPLAYER_INVALID_STATUS ;
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 ;
2013-01-06 22:15:47 -08:00
return 0 ;
2012-11-07 19:10:52 +01:00
}
2014-01-08 14:20:20 +01:00
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 ) ;
return ERROR_PSMF_NOT_FOUND ;
}
2014-02-14 10:19:38 +08:00
bool isInitialized = isInitializedStatus ( psmfplayer - > status ) ;
if ( ! isInitialized ) {
ERROR_LOG ( ME , " scePsmfPlayerBreak(%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
}
2014-02-05 22:33:44 +08:00
// Fix everybody stress buster
psmfplayer - > status = PSMF_PLAYER_STATUS_INIT ;
2013-01-06 22:15:47 -08:00
return 0 ;
2012-11-07 19:10:52 +01:00
}
2013-06-27 23:46:26 +08:00
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 ) ;
if ( psmfplayer - > readSize > = psmfplayer - > streamSize & & videoLoopStatus = = PSMF_PLAYER_CONFIG_LOOP ) {
// start looping
psmfplayer - > readSize = 0 ;
pspFileSystem . SeekFile ( psmfplayer - > filehandle , psmfplayer - > fileoffset , FILEMOVE_BEGIN ) ;
}
return 0 ;
}
2014-04-20 08:45:40 -07:00
int _PsmfPlayerSetPsmfOffset ( u32 psmfPlayer , const char * filename , int offset , bool docallback ) {
PsmfPlayer * psmfplayer = getPsmfPlayer ( psmfPlayer ) ;
if ( ! psmfplayer | | psmfplayer - > status ! = PSMF_PLAYER_STATUS_INIT ) {
return ERROR_PSMFPLAYER_INVALID_STATUS ;
}
if ( ! filename ) {
return ERROR_PSMFPLAYER_INVALID_PARAM ;
}
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 ) {
return SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT ;
}
2013-06-18 16:05:15 +08:00
if ( psmfplayer - > filehandle & & psmfplayer - > tempbuf ) {
2014-04-20 08:45:40 -07:00
if ( offset ! = 0 )
2013-06-27 23:46:26 +08:00
pspFileSystem . SeekFile ( psmfplayer - > filehandle , offset , FILEMOVE_BEGIN ) ;
2014-04-20 08:45:40 -07:00
u8 * buf = psmfplayer - > tempbuf ;
2014-01-04 01:25:42 -08:00
int tempbufSize = ( int ) sizeof ( psmfplayer - > tempbuf ) ;
2013-07-22 19:22:21 +02:00
int size = ( int ) pspFileSystem . ReadFile ( psmfplayer - > filehandle , buf , 2048 ) ;
2014-04-20 08:55:30 -07: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-04-20 11:53:59 -07:00
// TODO: Merge better with Psmf.
u16 numStreams = * ( u16_be * ) ( buf + 0x80 ) ;
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 = * ( const u32_be * ) ( currentStreamAddr + 4 ) ;
const u32 epEntries = * ( const u32_be * ) ( 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 ;
}
} else if ( ( streamId & PSMF_AUDIO_STREAM_ID ) = = PSMF_AUDIO_STREAM_ID ) {
+ + psmfplayer - > totalAudioStreams ;
} else {
WARN_LOG_REPORT ( ME , " scePsmfPlayerSetPsmf*: unexpected streamID %x " , streamId ) ;
}
}
// TODO: It seems like it's invalid if there's not at least 1 video stream.
2014-05-11 11:14:59 -07:00
int mpegoffset = * ( s32_be * ) ( buf + PSMF_STREAM_OFFSET_OFFSET ) ;
2013-06-27 23:46:26 +08:00
psmfplayer - > readSize = size - mpegoffset ;
2014-05-11 11:14:59 -07:00
psmfplayer - > streamSize = * ( s32_be * ) ( buf + PSMF_STREAM_SIZE_OFFSET ) ;
2013-06-27 23:46:26 +08:00
psmfplayer - > fileoffset = offset + mpegoffset ;
2014-01-04 01:25:42 -08:00
psmfplayer - > mediaengine - > loadStream ( buf , 2048 , std : : max ( 2048 * 500 , tempbufSize ) ) ;
2013-06-27 23:46:26 +08:00
_PsmfPlayerFillRingbuffer ( psmfplayer ) ;
2014-05-11 21:51:28 -07:00
psmfplayer - > totalDurationTimestamp = psmfplayer - > mediaengine - > getLastTimeStamp ( ) ;
2013-06-18 16:05:15 +08:00
}
2014-04-20 08:55:30 -07:00
psmfplayer - > status = PSMF_PLAYER_STATUS_STANDBY ;
2013-06-18 16:05:15 +08:00
return 0 ;
}
2013-01-18 18:05:51 +08:00
int scePsmfPlayerSetPsmf ( u32 psmfPlayer , const char * filename )
{
2014-04-20 08:45:40 -07:00
int result = _PsmfPlayerSetPsmfOffset ( psmfPlayer , filename , 0 , false ) ;
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
}
2013-01-18 18:05:51 +08:00
int scePsmfPlayerSetPsmfCB ( u32 psmfPlayer , const char * filename )
{
2013-06-13 22:33:59 -07:00
// TODO: hleCheckCurrentCallbacks?
2014-04-20 08:45:40 -07:00
int result = _PsmfPlayerSetPsmfOffset ( psmfPlayer , filename , 0 , true ) ;
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
}
2013-06-18 16:05:15 +08:00
int scePsmfPlayerSetPsmfOffset ( u32 psmfPlayer , const char * filename , int offset )
{
2014-04-20 08:45:40 -07:00
int result = _PsmfPlayerSetPsmfOffset ( psmfPlayer , filename , offset , false ) ;
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
}
int scePsmfPlayerSetPsmfOffsetCB ( u32 psmfPlayer , const char * filename , int offset )
{
// TODO: hleCheckCurrentCallbacks?
2014-04-20 08:45:40 -07:00
int result = _PsmfPlayerSetPsmfOffset ( psmfPlayer , filename , offset , true ) ;
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
}
2013-01-18 18:05:51 +08:00
int scePsmfPlayerGetAudioOutSize ( u32 psmfPlayer )
{
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-05-15 00:14:27 -07:00
bool __PsmfPlayerContinueSeek ( PsmfPlayer * psmfplayer , int tries = 50 ) {
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-05-04 23:52:12 -07:00
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-04 23:52:12 -07:00
WARN_LOG ( ME , " scePsmfPlayerStart(%08x, %08x, %d) " , psmfPlayer , psmfPlayerData , initPts ) ;
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 ;
if ( ! psmfplayer - > mediaengine - > IsNoAudioData ( ) ) {
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
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 ) {
if ( initPts < = it - > EPPts ) {
break ;
}
lastOffset = it - > EPOffset ;
2014-05-05 01:24:31 -07:00
}
2014-05-15 00:14:27 -07:00
psmfplayer - > readSize + = lastOffset * 2048 ;
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 ) ;
2013-01-06 22:15:47 -08:00
return 0 ;
}
2013-01-18 18:05:51 +08:00
int scePsmfPlayerDelete ( u32 psmfPlayer )
{
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-02-05 22:33:44 +08:00
return ERROR_PSMF_NOT_FOUND ;
2013-03-29 00:54:04 -07:00
}
2014-02-05 22:33:44 +08:00
2014-02-14 10:19:38 +08:00
bool isInitialized = isInitializedStatus ( psmfplayer - > status ) ;
if ( ! isInitialized ) {
ERROR_LOG ( ME , " scePsmfPlayerDelete(%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
}
2014-02-05 22:33:44 +08:00
INFO_LOG ( ME , " scePsmfPlayerDelete(%08x) " , psmfPlayer ) ;
delete psmfplayer ;
psmfPlayerMap . erase ( psmfPlayer ) ;
2013-01-06 22:15:47 -08:00
return 0 ;
}
2013-01-18 18:05:51 +08:00
int scePsmfPlayerUpdate ( u32 psmfPlayer )
{
PsmfPlayer * psmfplayer = getPsmfPlayer ( psmfPlayer ) ;
if ( ! psmfplayer ) {
2013-09-07 22:02:55 +02:00
ERROR_LOG ( ME , " scePsmfPlayerUpdate(%08x): invalid psmf player " , psmfPlayer ) ;
2013-01-18 18:05:51 +08:00
return ERROR_PSMF_NOT_FOUND ;
}
2014-02-14 10:19:38 +08:00
bool isInitialized = isInitializedStatus ( psmfplayer - > status ) ;
if ( ! isInitialized ) {
ERROR_LOG ( ME , " scePsmfPlayerUpdate(%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
}
2014-02-05 22:55:46 +08:00
bool psmfplayerstatus = isPlayingStatus ( psmfplayer - > status ) ;
if ( ! psmfplayerstatus ) {
ERROR_LOG ( ME , " scePsmfPlayerUpdate(%08x): psmf not playing " , psmfPlayer ) ;
return ERROR_PSMF_NOT_INITIALIZED ;
}
2013-09-07 22:02:55 +02:00
DEBUG_LOG ( ME , " scePsmfPlayerUpdate(%08x) " , psmfPlayer ) ;
2013-01-24 19:40:26 +08:00
if ( psmfplayer - > psmfPlayerAvcAu . pts > 0 ) {
2013-06-27 23:46:26 +08:00
if ( psmfplayer - > mediaengine - > IsVideoEnd ( ) ) {
2013-09-07 22:02:55 +02:00
INFO_LOG ( ME , " video end reached " ) ;
2013-03-06 01:00:26 -08:00
psmfplayer - > status = PSMF_PLAYER_STATUS_PLAYING_FINISHED ;
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
}
2013-01-18 18:05:51 +08:00
int scePsmfPlayerReleasePsmf ( 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 , " scePsmfPlayerReleasePsmf(%08x): invalid psmf player " , psmfPlayer ) ;
return ERROR_PSMF_NOT_FOUND ;
}
2014-02-14 10:19:38 +08:00
bool isInitialized = isInitializedStatus ( psmfplayer - > status ) ;
2014-02-15 18:38:38 +08:00
if ( ! isInitialized ) {
2014-02-14 10:19:38 +08:00
ERROR_LOG ( ME , " scePsmfPlayerReleasePsmf(%08x): not initialized " , 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-05-11 21:51:28 -07:00
void __PsmfUpdatePts ( PsmfPlayer * psmfplayer , PsmfVideoData * videoData ) {
// 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 ;
}
}
2013-03-29 00:54:04 -07:00
int scePsmfPlayerGetVideoData ( u32 psmfPlayer , u32 videoDataAddr )
{
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 ) ;
2013-03-29 00:54:04 -07:00
return ERROR_PSMF_NOT_FOUND ;
}
2014-02-14 10:19:38 +08:00
bool isInitialized = isInitializedStatus ( psmfplayer - > status ) ;
if ( ! isInitialized ) {
ERROR_LOG ( ME , " scePsmfPlayerGetVideoData(%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
}
2014-02-05 22:55:46 +08:00
bool psmfplayerstatus = isPlayingStatus ( psmfplayer - > status ) ;
if ( ! psmfplayerstatus ) {
ERROR_LOG ( ME , " scePsmfPlayerGetVideoData(%08x): psmf not playing " , psmfPlayer ) ;
return ERROR_PSMF_NOT_INITIALIZED ;
}
2014-02-14 10:43:53 +08:00
if ( psmfplayer - > playMode = = PSMF_PLAYER_MODE_PAUSE ) {
INFO_LOG ( HLE , " scePsmfPlayerGetVideoData(%08x): paused mode " , psmfPlayer ) ;
return 0 ;
}
2014-02-15 18:07:19 +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-04-25 23:40:22 -07:00
auto videoData = PSPPointer < PsmfVideoData > : : Create ( videoDataAddr ) ;
if ( videoData . IsValid ( ) ) {
if ( ! psmfplayer - > mediaengine - > IsNoAudioData ( ) ) {
2014-05-11 21:51:28 -07:00
s64 deltapts = psmfplayer - > mediaengine - > getVideoTimeStamp ( ) - psmfplayer - > mediaengine - > getAudioTimeStamp ( ) ;
2014-04-25 23:40:22 -07:00
if ( deltapts > 0 ) {
// Don't advance, just return the same frame again.
// TODO: This also seems somewhat based on Update() calls, but audio is involved too...
2014-04-27 08:23:42 -07:00
int displaybufSize = psmfplayer - > mediaengine - > writeVideoImage ( videoData - > displaybuf , videoData - > frameWidth , videoPixelMode ) ;
// Need to invalidate, even if it didn't change, to trigger upload to framebuffer.
gpu - > InvalidateCache ( videoData - > displaybuf , displaybufSize , GPU_INVALIDATE_SAFE ) ;
2014-05-11 21:51:28 -07:00
__PsmfUpdatePts ( psmfplayer , videoData ) ;
2014-04-25 23:40:22 -07:00
return hleDelayResult ( 0 , " psmfPlayer behind audio " , 3000 ) ;
2014-05-11 21:51:28 -07:00
} else {
// 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 ) ;
deltapts = psmfplayer - > mediaengine - > getVideoTimeStamp ( ) - psmfplayer - > mediaengine - > getAudioTimeStamp ( ) ;
}
2014-04-25 23:40:22 -07:00
}
} else {
// No audio, based on Update() calls. playSpeed doesn't seem to matter?
if ( psmfplayer - > videoStep < = 1 ) {
// In this case, don't advance but also don't write the video frame.
videoData - > displaypts = ( u32 ) psmfplayer - > psmfPlayerAvcAu . pts ;
return hleDelayResult ( 0 , " psmfPlayer behind " , 3000 ) ;
}
psmfplayer - > videoStep = 0 ;
}
2013-06-08 04:50:36 -07:00
if ( psmfplayer - > mediaengine - > stepVideo ( videoPixelMode ) ) {
2014-04-25 23:40:22 -07:00
int displaybufSize = psmfplayer - > mediaengine - > writeVideoImage ( videoData - > displaybuf , videoData - > frameWidth , videoPixelMode ) ;
gpu - > InvalidateCache ( videoData - > displaybuf , displaybufSize , GPU_INVALIDATE_SAFE ) ;
2013-06-08 04:50:36 -07:00
}
2014-05-11 21:51:28 -07:00
__PsmfUpdatePts ( psmfplayer , videoData ) ;
2013-06-02 01:30:51 +08:00
}
2013-06-10 01:07:43 +08:00
2013-06-27 23:46:26 +08:00
_PsmfPlayerFillRingbuffer ( psmfplayer ) ;
2013-10-19 14:02:47 -07:00
int ret = psmfplayer - > mediaengine - > IsVideoEnd ( ) ? ( int ) ERROR_PSMFPLAYER_NO_MORE_DATA : 0 ;
2013-06-10 01:07:43 +08:00
2014-02-12 23:32:05 +08:00
DEBUG_LOG ( ME , " %08x=scePsmfPlayerGetVideoData(%08x, %08x) " , ret , psmfPlayer , videoDataAddr ) ;
2014-04-25 23:40:22 -07:00
if ( ret ! = 0 ) {
return ret ;
}
return hleDelayResult ( ret , " psmfPlayer video decode " , 3000 ) ;
2013-03-29 00:54:04 -07:00
}
int scePsmfPlayerGetAudioData ( u32 psmfPlayer , u32 audioDataAddr )
{
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 ) ;
2013-03-29 00:54:04 -07:00
return ERROR_PSMF_NOT_FOUND ;
}
2014-02-14 10:19:38 +08:00
bool isInitialized = isInitializedStatus ( psmfplayer - > status ) ;
if ( ! isInitialized ) {
ERROR_LOG ( ME , " scePsmfPlayerGetAudioData(%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
}
2014-02-05 22:55:46 +08:00
bool psmfplayerstatus = isPlayingStatus ( psmfplayer - > status ) ;
if ( ! psmfplayerstatus ) {
ERROR_LOG ( ME , " scePsmfPlayerGetAudioData(%08x): psmf not playing " , psmfPlayer ) ;
return ERROR_PSMF_NOT_INITIALIZED ;
}
2014-02-14 10:43:53 +08:00
if ( psmfplayer - > playMode = = PSMF_PLAYER_MODE_PAUSE ) {
INFO_LOG ( HLE , " scePsmfPlayerGetAudioData(%08x): paused mode " , psmfPlayer ) ;
2014-02-15 17:49:35 +08:00
// Clear the audio when paused.
2014-02-15 18:37:34 +08:00
if ( Memory : : IsValidAddress ( audioDataAddr ) ) {
Memory : : Memset ( audioDataAddr , 0 , audioSamplesBytes ) ;
}
2014-02-14 10:43:53 +08:00
return 0 ;
}
2014-02-15 18:07:19 +08:00
2014-04-27 12:57:39 -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-15 18:37:34 +08:00
if ( Memory : : IsValidAddress ( audioDataAddr ) ) {
psmfplayer - > mediaengine - > getAudioSamples ( audioDataAddr ) ;
}
2014-02-15 18:15:44 +08:00
2013-10-19 14:02:47 -07:00
int ret = psmfplayer - > mediaengine - > IsNoAudioData ( ) ? ( int ) ERROR_PSMFPLAYER_NO_MORE_DATA : 0 ;
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
}
2013-01-18 18:05:51 +08:00
int scePsmfPlayerGetCurrentStatus ( u32 psmfPlayer )
{
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-02-14 10:19:38 +08:00
bool isInitialized = isInitializedStatus ( psmfplayer - > status ) ;
if ( ! isInitialized ) {
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
2013-01-18 18:05:51 +08:00
u32 scePsmfPlayerGetCurrentPts ( u32 psmfPlayer , u32 currentPtsAddr )
{
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 ;
}
u32 scePsmfPlayerGetPsmfInfo ( u32 psmfPlayer , u32 psmfInfoAddr )
{
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 ;
}
u32 scePsmfPlayerGetCurrentPlayMode ( u32 psmfPlayer , u32 playModeAddr , u32 playSpeedAddr )
{
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 ;
}
u32 scePsmfPlayerGetCurrentVideoStream ( u32 psmfPlayer , u32 videoCodecAddr , u32 videoStreamNumAddr )
{
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 ;
}
u32 scePsmfPlayerGetCurrentAudioStream ( u32 psmfPlayer , u32 audioCodecAddr , u32 audioStreamNumAddr )
{
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 ;
}
2013-03-12 11:54:52 +08:00
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 ;
}
u32 scePsmfPlayerChangePlayMode ( u32 psmfPlayer , int playMode , int playSpeed )
{
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 ;
}
u32 scePsmfPlayerSelectAudio ( u32 psmfPlayer )
{
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 ;
}
u32 scePsmfPlayerSelectVideo ( u32 psmfPlayer )
{
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 ;
}
u32 scePsmfPlayerSelectSpecificVideo ( u32 psmfPlayer , int videoCodec , int videoStreamNum )
{
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.
2013-01-18 18:05:51 +08:00
u32 scePsmfPlayerSelectSpecificAudio ( u32 psmfPlayer , int audioCodec , int audioStreamNum )
{
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 ;
}
u32 scePsmfPlayerConfigPlayer ( u32 psmfPlayer , int configMode , int configAttr )
{
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 ;
}
2013-01-24 19:40:26 +08:00
const HLEFunction scePsmf [ ] = {
{ 0xc22c8327 , WrapU_UU < scePsmfSetPsmf > , " scePsmfSetPsmf " } ,
{ 0xC7DB3A5B , WrapU_UUU < scePsmfGetCurrentStreamType > , " scePsmfGetCurrentStreamType " } ,
{ 0x28240568 , WrapU_U < scePsmfGetCurrentStreamNumber > , " scePsmfGetCurrentStreamNumber " } ,
{ 0x1E6D9013 , WrapU_UUU < scePsmfSpecifyStreamWithStreamType > , " scePsmfSpecifyStreamWithStreamType " } ,
{ 0x0C120E1D , WrapU_UUU < scePsmfSpecifyStreamWithStreamTypeNumber > , " scePsmfSpecifyStreamWithStreamTypeNumber " } ,
2013-03-12 00:17:24 +01:00
{ 0x4BC9BDE0 , WrapU_UI < scePsmfSpecifyStream > , " scePsmfSpecifyStream " } ,
2013-01-24 19:40:26 +08:00
{ 0x76D3AEBA , WrapU_UU < scePsmfGetPresentationStartTime > , " scePsmfGetPresentationStartTime " } ,
{ 0xBD8AE0D8 , WrapU_UU < scePsmfGetPresentationEndTime > , " scePsmfGetPresentationEndTime " } ,
{ 0xEAED89CD , WrapU_U < scePsmfGetNumberOfStreams > , " scePsmfGetNumberOfStreams " } ,
{ 0x7491C438 , WrapU_U < scePsmfGetNumberOfEPentries > , " scePsmfGetNumberOfEPentries " } ,
{ 0x0BA514E5 , WrapU_UU < scePsmfGetVideoInfo > , " scePsmfGetVideoInfo " } ,
{ 0xA83F7113 , WrapU_UU < scePsmfGetAudioInfo > , " scePsmfGetAudioInfo " } ,
2013-06-24 18:58:36 +02:00
{ 0x971A3A90 , WrapU_U < scePsmfCheckEPMap > , " scePsmfCheckEPmap " } ,
2013-07-07 18:10:55 -07:00
{ 0x68d42328 , WrapU_UI < scePsmfGetNumberOfSpecificStreams > , " scePsmfGetNumberOfSpecificStreams " } ,
2013-03-29 01:05:11 -07:00
{ 0x5b70fcc1 , WrapU_UU < scePsmfQueryStreamOffset > , " scePsmfQueryStreamOffset " } ,
{ 0x9553cc91 , WrapU_UU < scePsmfQueryStreamSize > , " scePsmfQueryStreamSize " } ,
2013-01-24 19:40:26 +08:00
{ 0xB78EB9E9 , WrapU_UU < scePsmfGetHeaderSize > , " scePsmfGetHeaderSize " } ,
{ 0xA5EBFE81 , WrapU_UU < scePsmfGetStreamSize > , " scePsmfGetStreamSize " } ,
{ 0xE1283895 , WrapU_U < scePsmfGetPsmfVersion > , " scePsmfGetPsmfVersion " } ,
2013-01-29 01:28:51 +01:00
{ 0x2673646B , WrapU_U < scePsmfVerifyPsmf > , " scePsmfVerifyPsmf " } ,
2013-01-24 19:40:26 +08:00
{ 0x4E624A34 , WrapU_UIU < scePsmfGetEPWithId > , " scePsmfGetEPWithId " } ,
{ 0x7C0E7AC3 , WrapU_UUU < scePsmfGetEPWithTimestamp > , " scePsmfGetEPWithTimestamp " } ,
{ 0x5F457515 , WrapU_UU < scePsmfGetEPidWithTimestamp > , " scePsmfGetEPidWithTimestamp " } ,
2013-12-02 23:36:55 -08:00
{ 0x43ac7dbb , 0 , " scePsmfGetPsmfMark " } ,
{ 0xde78e9fc , 0 , " scePsmfGetNumberOfPsmfMarks " } ,
2013-01-24 19:40:26 +08:00
} ;
2012-11-01 16:19:01 +01:00
const HLEFunction scePsmfPlayer [ ] =
{
2013-01-06 22:15:47 -08:00
{ 0x235d8787 , WrapI_UU < scePsmfPlayerCreate > , " scePsmfPlayerCreate " } ,
{ 0x1078c008 , WrapI_U < scePsmfPlayerStop > , " scePsmfPlayerStop " } ,
2013-01-18 18:05:51 +08:00
{ 0x1e57a8e7 , WrapU_UII < scePsmfPlayerConfigPlayer > , " scePsmfPlayerConfigPlayer " } ,
2013-01-06 22:15:47 -08:00
{ 0x2beb1569 , WrapI_U < scePsmfPlayerBreak > , " scePsmfPlayerBreak " } ,
{ 0x3d6d25a9 , WrapI_UC < scePsmfPlayerSetPsmf > , " scePsmfPlayerSetPsmf " } ,
{ 0x58B83577 , WrapI_UC < scePsmfPlayerSetPsmfCB > , " scePsmfPlayerSetPsmfCB " } ,
{ 0x3ea82a4b , WrapI_U < scePsmfPlayerGetAudioOutSize > , " scePsmfPlayerGetAudioOutSize " } ,
2013-01-18 18:05:51 +08:00
{ 0x3ed62233 , WrapU_UU < scePsmfPlayerGetCurrentPts > , " scePsmfPlayerGetCurrentPts " } ,
2013-03-29 00:54:04 -07:00
{ 0x46f61f8b , WrapI_UU < scePsmfPlayerGetVideoData > , " scePsmfPlayerGetVideoData " } ,
2013-01-18 18:05:51 +08:00
{ 0x68f07175 , WrapU_UUU < scePsmfPlayerGetCurrentAudioStream > , " scePsmfPlayerGetCurrentAudioStream " } ,
{ 0x75f03fa2 , WrapU_UII < scePsmfPlayerSelectSpecificVideo > , " scePsmfPlayerSelectSpecificVideo " } ,
{ 0x85461eff , WrapU_UII < scePsmfPlayerSelectSpecificAudio > , " scePsmfPlayerSelectSpecificAudio " } ,
{ 0x8a9ebdcd , WrapU_U < scePsmfPlayerSelectVideo > , " scePsmfPlayerSelectVideo " } ,
{ 0x95a84ee5 , WrapI_UUI < scePsmfPlayerStart > , " scePsmfPlayerStart " } ,
2013-01-06 22:15:47 -08:00
{ 0x9b71a274 , WrapI_U < scePsmfPlayerDelete > , " scePsmfPlayerDelete " } ,
2013-01-18 18:05:51 +08:00
{ 0x9ff2b2e7 , WrapU_UUU < scePsmfPlayerGetCurrentVideoStream > , " scePsmfPlayerGetCurrentVideoStream " } ,
2013-01-06 22:15:47 -08:00
{ 0xa0b8ca55 , WrapI_U < scePsmfPlayerUpdate > , " scePsmfPlayerUpdate " } ,
2013-01-18 18:05:51 +08:00
{ 0xa3d81169 , WrapU_UII < scePsmfPlayerChangePlayMode > , " scePsmfPlayerChangePlayMode " } ,
{ 0xb8d10c56 , WrapU_U < scePsmfPlayerSelectAudio > , " scePsmfPlayerSelectAudio " } ,
2013-03-29 00:54:04 -07:00
{ 0xb9848a74 , WrapI_UU < scePsmfPlayerGetAudioData > , " scePsmfPlayerGetAudioData " } ,
2013-01-18 18:05:51 +08:00
{ 0xdf089680 , WrapU_UU < scePsmfPlayerGetPsmfInfo > , " scePsmfPlayerGetPsmfInfo " } ,
2013-01-06 22:15:47 -08:00
{ 0xe792cd94 , WrapI_U < scePsmfPlayerReleasePsmf > , " scePsmfPlayerReleasePsmf " } ,
2013-01-18 18:05:51 +08:00
{ 0xf3efaa91 , WrapU_UUU < scePsmfPlayerGetCurrentPlayMode > , " scePsmfPlayerGetCurrentPlayMode " } ,
2013-01-06 22:15:47 -08:00
{ 0xf8ef08a6 , WrapI_U < scePsmfPlayerGetCurrentStatus > , " scePsmfPlayerGetCurrentStatus " } ,
2013-03-12 09:51:50 +01:00
{ 0x2D0E4E0A , WrapI_UUU < scePsmfPlayerSetTempBuf > , " scePsmfPlayerSetTempBuf " } ,
2013-06-18 16:05:15 +08:00
{ 0x76C0F4AE , WrapI_UCI < scePsmfPlayerSetPsmfOffset > , " scePsmfPlayerSetPsmfOffset " } ,
{ 0xA72DB4F9 , WrapI_UCI < scePsmfPlayerSetPsmfOffsetCB > , " scePsmfPlayerSetPsmfOffsetCB " } ,
2013-06-30 11:40:52 -07:00
{ 0x340c12cb , 0 , " scePsmfPlayer_340C12CB " } ,
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
}