2014-02-16 02:51:04 +01:00
# include "stdafx.h"
2015-10-26 22:09:31 +01:00
# include "Emu/System.h"
2016-03-21 20:42:14 +01:00
# include "Emu/IdManager.h"
# include "Emu/Cell/PPUModule.h"
2014-03-17 20:34:19 +01:00
2017-01-28 13:32:45 +01:00
# include "restore_new.h"
2014-08-23 22:40:04 +02:00
# include "Utilities/rXml.h"
2017-01-28 13:32:45 +01:00
# include "define_new_memleakdetect.h"
2014-02-16 02:51:04 +01:00
# include "Loader/TRP.h"
2014-03-20 19:23:14 +01:00
# include "Loader/TROPUSR.h"
2016-03-21 20:42:14 +01:00
2014-08-23 22:40:04 +02:00
# include "sceNp.h"
# include "sceNpTrophy.h"
2014-04-01 02:33:55 +02:00
2016-04-27 00:27:24 +02:00
# include "Utilities/StrUtil.h"
2017-05-13 20:30:37 +02:00
logs : : channel sceNpTrophy ( " sceNpTrophy " ) ;
2014-02-16 02:51:04 +01:00
2015-07-02 03:54:36 +02:00
struct trophy_context_t
2014-02-16 02:51:04 +01:00
{
2017-01-25 18:50:30 +01:00
static const u32 id_base = 1 ;
static const u32 id_step = 1 ;
2017-01-29 17:50:18 +01:00
static const u32 id_count = 1023 ;
2017-01-25 18:50:30 +01:00
2014-02-16 02:51:04 +01:00
std : : string trp_name ;
2016-03-21 20:42:14 +01:00
fs : : file trp_stream ;
2014-04-18 13:28:27 +02:00
std : : unique_ptr < TROPUSRLoader > tropusr ;
2015-07-02 03:54:36 +02:00
} ;
2014-04-15 16:12:15 +02:00
2015-07-02 03:54:36 +02:00
struct trophy_handle_t
{
2017-01-25 18:50:30 +01:00
static const u32 id_base = 1 ;
static const u32 id_step = 1 ;
2017-01-29 17:50:18 +01:00
static const u32 id_count = 1023 ;
2015-07-02 03:54:36 +02:00
} ;
2014-04-18 13:28:27 +02:00
2017-05-15 13:30:14 +02:00
template < >
void fmt_class_string < SceNpTrophyError > : : format ( std : : string & out , u64 arg )
{
format_enum ( out , arg , [ ] ( auto error )
{
switch ( error )
{
STR_CASE ( SCE_NP_TROPHY_ERROR_ALREADY_INITIALIZED ) ;
STR_CASE ( SCE_NP_TROPHY_ERROR_NOT_INITIALIZED ) ;
STR_CASE ( SCE_NP_TROPHY_ERROR_NOT_SUPPORTED ) ;
STR_CASE ( SCE_NP_TROPHY_ERROR_CONTEXT_NOT_REGISTERED ) ;
STR_CASE ( SCE_NP_TROPHY_ERROR_OUT_OF_MEMORY ) ;
STR_CASE ( SCE_NP_TROPHY_ERROR_INVALID_ARGUMENT ) ;
STR_CASE ( SCE_NP_TROPHY_ERROR_EXCEEDS_MAX ) ;
STR_CASE ( SCE_NP_TROPHY_ERROR_INSUFFICIENT ) ;
STR_CASE ( SCE_NP_TROPHY_ERROR_UNKNOWN_CONTEXT ) ;
STR_CASE ( SCE_NP_TROPHY_ERROR_INVALID_FORMAT ) ;
STR_CASE ( SCE_NP_TROPHY_ERROR_BAD_RESPONSE ) ;
STR_CASE ( SCE_NP_TROPHY_ERROR_INVALID_GRADE ) ;
STR_CASE ( SCE_NP_TROPHY_ERROR_INVALID_CONTEXT ) ;
STR_CASE ( SCE_NP_TROPHY_ERROR_PROCESSING_ABORTED ) ;
STR_CASE ( SCE_NP_TROPHY_ERROR_ABORT ) ;
STR_CASE ( SCE_NP_TROPHY_ERROR_UNKNOWN_HANDLE ) ;
STR_CASE ( SCE_NP_TROPHY_ERROR_LOCKED ) ;
STR_CASE ( SCE_NP_TROPHY_ERROR_HIDDEN ) ;
STR_CASE ( SCE_NP_TROPHY_ERROR_CANNOT_UNLOCK_PLATINUM ) ;
STR_CASE ( SCE_NP_TROPHY_ERROR_ALREADY_UNLOCKED ) ;
STR_CASE ( SCE_NP_TROPHY_ERROR_INVALID_TYPE ) ;
STR_CASE ( SCE_NP_TROPHY_ERROR_INVALID_HANDLE ) ;
STR_CASE ( SCE_NP_TROPHY_ERROR_INVALID_NP_COMM_ID ) ;
STR_CASE ( SCE_NP_TROPHY_ERROR_UNKNOWN_NP_COMM_ID ) ;
STR_CASE ( SCE_NP_TROPHY_ERROR_DISC_IO ) ;
STR_CASE ( SCE_NP_TROPHY_ERROR_CONF_DOES_NOT_EXIST ) ;
STR_CASE ( SCE_NP_TROPHY_ERROR_UNSUPPORTED_FORMAT ) ;
STR_CASE ( SCE_NP_TROPHY_ERROR_ALREADY_INSTALLED ) ;
STR_CASE ( SCE_NP_TROPHY_ERROR_BROKEN_DATA ) ;
STR_CASE ( SCE_NP_TROPHY_ERROR_VERIFICATION_FAILURE ) ;
STR_CASE ( SCE_NP_TROPHY_ERROR_INVALID_TROPHY_ID ) ;
STR_CASE ( SCE_NP_TROPHY_ERROR_UNKNOWN_TROPHY_ID ) ;
STR_CASE ( SCE_NP_TROPHY_ERROR_UNKNOWN_TITLE ) ;
STR_CASE ( SCE_NP_TROPHY_ERROR_UNKNOWN_FILE ) ;
STR_CASE ( SCE_NP_TROPHY_ERROR_DISC_NOT_MOUNTED ) ;
STR_CASE ( SCE_NP_TROPHY_ERROR_SHUTDOWN ) ;
STR_CASE ( SCE_NP_TROPHY_ERROR_TITLE_ICON_NOT_FOUND ) ;
STR_CASE ( SCE_NP_TROPHY_ERROR_TROPHY_ICON_NOT_FOUND ) ;
STR_CASE ( SCE_NP_TROPHY_ERROR_INSUFFICIENT_DISK_SPACE ) ;
STR_CASE ( SCE_NP_TROPHY_ERROR_ILLEGAL_UPDATE ) ;
STR_CASE ( SCE_NP_TROPHY_ERROR_SAVEDATA_USER_DOES_NOT_MATCH ) ;
STR_CASE ( SCE_NP_TROPHY_ERROR_TROPHY_ID_DOES_NOT_EXIST ) ;
STR_CASE ( SCE_NP_TROPHY_ERROR_SERVICE_UNAVAILABLE ) ;
STR_CASE ( SCE_NP_TROPHY_ERROR_UNKNOWN ) ;
}
return unknown ;
} ) ;
}
2015-07-02 03:54:36 +02:00
// Functions
2017-05-15 13:30:14 +02:00
error_code sceNpTrophyInit ( vm : : ptr < void > pool , u32 poolSize , u32 containerId , u64 options )
2015-07-02 03:54:36 +02:00
{
2016-01-12 22:57:16 +01:00
sceNpTrophy . warning ( " sceNpTrophyInit(pool=*0x%x, poolSize=0x%x, containerId=0x%x, options=0x%llx) " , pool , poolSize , containerId , options ) ;
2014-04-18 13:28:27 +02:00
2015-07-02 03:54:36 +02:00
return CELL_OK ;
}
2017-05-15 13:30:14 +02:00
error_code sceNpTrophyTerm ( )
2015-07-02 03:54:36 +02:00
{
2016-01-12 22:57:16 +01:00
sceNpTrophy . warning ( " sceNpTrophyTerm() " ) ;
2014-02-16 02:51:04 +01:00
2015-07-02 03:54:36 +02:00
return CELL_OK ;
}
2017-05-15 13:30:14 +02:00
error_code sceNpTrophyCreateHandle ( vm : : ptr < u32 > handle )
2014-02-16 02:51:04 +01:00
{
2016-01-12 22:57:16 +01:00
sceNpTrophy . warning ( " sceNpTrophyCreateHandle(handle=*0x%x) " , handle ) ;
2014-02-16 02:51:04 +01:00
2015-07-02 03:54:36 +02:00
if ( ! handle )
2014-02-16 02:51:04 +01:00
{
2015-07-02 03:54:36 +02:00
return SCE_NP_TROPHY_ERROR_INVALID_ARGUMENT ;
2014-02-16 02:51:04 +01:00
}
2015-08-05 17:30:32 +02:00
* handle = idm : : make < trophy_handle_t > ( ) ;
2014-02-16 02:51:04 +01:00
2015-07-02 03:54:36 +02:00
return CELL_OK ;
2015-02-08 12:37:10 +01:00
}
2017-05-15 13:30:14 +02:00
error_code sceNpTrophyDestroyHandle ( u32 handle )
2014-02-16 02:51:04 +01:00
{
2016-01-12 22:57:16 +01:00
sceNpTrophy . warning ( " sceNpTrophyDestroyHandle(handle=0x%x) " , handle ) ;
2014-02-16 02:51:04 +01:00
2015-08-05 17:30:32 +02:00
const auto hndl = idm : : get < trophy_handle_t > ( handle ) ;
2014-02-16 02:51:04 +01:00
2015-07-02 03:54:36 +02:00
if ( ! hndl )
{
return SCE_NP_TROPHY_ERROR_UNKNOWN_HANDLE ;
}
2015-08-05 17:30:32 +02:00
idm : : remove < trophy_handle_t > ( handle ) ;
2014-09-22 21:00:28 +02:00
2014-02-16 02:51:04 +01:00
return CELL_OK ;
}
2017-05-15 13:30:14 +02:00
error_code sceNpTrophyAbortHandle ( u32 handle )
2014-02-16 02:51:04 +01:00
{
2016-01-12 22:57:16 +01:00
sceNpTrophy . todo ( " sceNpTrophyAbortHandle(handle=0x%x) " , handle ) ;
2014-02-16 02:51:04 +01:00
2015-08-05 17:30:32 +02:00
const auto hndl = idm : : get < trophy_handle_t > ( handle ) ;
2015-07-02 03:54:36 +02:00
if ( ! hndl )
2015-04-25 23:26:54 +02:00
{
2015-07-02 03:54:36 +02:00
return SCE_NP_TROPHY_ERROR_UNKNOWN_HANDLE ;
2015-04-25 23:26:54 +02:00
}
2015-07-02 03:54:36 +02:00
return CELL_OK ;
}
2017-04-13 19:29:47 +02:00
void deleteTerminateChar ( char * myStr , char _char ) {
2015-07-02 03:54:36 +02:00
2017-02-14 18:46:56 +01:00
char * del = & myStr [ strlen ( myStr ) ] ;
while ( del > myStr & & * del ! = _char )
del - - ;
if ( * del = = _char )
* del = ' \0 ' ;
return ;
}
2017-05-15 13:30:14 +02:00
error_code sceNpTrophyCreateContext ( vm : : ptr < u32 > context , vm : : cptr < SceNpCommunicationId > commId , vm : : cptr < SceNpCommunicationSignature > commSign , u64 options )
2015-07-02 03:54:36 +02:00
{
2016-01-12 22:57:16 +01:00
sceNpTrophy . warning ( " sceNpTrophyCreateContext(context=*0x%x, commId=*0x%x, commSign=*0x%x, options=0x%llx) " , context , commId , commSign , options ) ;
2015-07-02 03:54:36 +02:00
2017-05-15 13:30:14 +02:00
if ( ! context )
{
return SCE_NP_TROPHY_ERROR_INVALID_ARGUMENT ;
}
2015-07-02 03:54:36 +02:00
// rough checks for further fmt::format call
2017-02-14 18:46:56 +01:00
if ( commId - > num > 99 )
2015-04-25 23:26:54 +02:00
{
2017-02-14 18:46:56 +01:00
sceNpTrophy . error ( " sceNpTrophyCreateContext Invalid NP_COMM_ID " ) ;
2015-07-02 03:54:36 +02:00
return SCE_NP_TROPHY_ERROR_INVALID_NP_COMM_ID ;
2015-04-25 23:26:54 +02:00
}
2015-07-02 03:54:36 +02:00
// generate trophy context name
2017-02-14 18:46:56 +01:00
std : : string name ;
sceNpTrophy . warning ( " sceNpTrophyCreateContext term=%s data=%s num=%d " , commId - > term , commId - > data , commId - > num ) ;
if ( commId - > term )
{
char trimchar [ 9 ] ;
2017-04-13 19:29:47 +02:00
memcpy ( trimchar , commId - > data , sizeof ( trimchar ) ) ;
trimchar [ 8 ] = 0 ;
deleteTerminateChar ( trimchar , commId - > term ) ;
2017-02-14 18:46:56 +01:00
name = fmt : : format ( " %s_%02d " , trimchar , commId - > num ) ;
}
else
{
2017-04-13 19:29:47 +02:00
name = fmt : : format ( " %s_%02d " , commId - > data , commId - > num ) ;
2017-02-14 18:46:56 +01:00
}
2017-04-13 19:29:47 +02:00
2015-07-02 03:54:36 +02:00
// open trophy pack file
2016-03-21 20:42:14 +01:00
fs : : file stream ( vfs : : get ( " /app_home/../TROPDIR/ " + name + " /TROPHY.TRP " ) ) ;
2015-07-02 03:54:36 +02:00
// check if exists and opened
2016-03-21 20:42:14 +01:00
if ( ! stream )
2015-04-25 23:26:54 +02:00
{
2017-02-14 18:46:56 +01:00
sceNpTrophy . error ( " sceNpTrophyCreateContext CONF does not exist " ) ;
2014-02-16 02:51:04 +01:00
return SCE_NP_TROPHY_ERROR_CONF_DOES_NOT_EXIST ;
2015-04-25 23:26:54 +02:00
}
2014-02-16 02:51:04 +01:00
2015-07-02 03:54:36 +02:00
// create trophy context
2015-08-05 17:30:32 +02:00
const auto ctxt = idm : : make_ptr < trophy_context_t > ( ) ;
2014-02-16 16:37:32 +01:00
2015-07-02 03:54:36 +02:00
// set trophy context parameters (could be passed to constructor through make_ptr call)
ctxt - > trp_name = std : : move ( name ) ;
ctxt - > trp_stream = std : : move ( stream ) ;
2017-02-04 16:09:02 +01:00
* context = idm : : last_id ( ) ;
2014-02-16 02:51:04 +01:00
2015-07-02 03:54:36 +02:00
return CELL_OK ;
2014-02-16 02:51:04 +01:00
}
2017-05-15 13:30:14 +02:00
error_code sceNpTrophyDestroyContext ( u32 context )
2014-02-16 02:51:04 +01:00
{
2016-01-12 22:57:16 +01:00
sceNpTrophy . warning ( " sceNpTrophyDestroyContext(context=0x%x) " , context ) ;
2014-02-16 02:51:04 +01:00
2015-08-05 17:30:32 +02:00
const auto ctxt = idm : : get < trophy_context_t > ( context ) ;
2014-02-16 02:51:04 +01:00
2015-07-02 03:54:36 +02:00
if ( ! ctxt )
{
return SCE_NP_TROPHY_ERROR_UNKNOWN_CONTEXT ;
}
2015-08-05 17:30:32 +02:00
idm : : remove < trophy_context_t > ( context ) ;
2014-02-16 02:51:04 +01:00
return CELL_OK ;
}
2017-05-15 13:30:14 +02:00
error_code sceNpTrophyRegisterContext ( ppu_thread & ppu , u32 context , u32 handle , vm : : ptr < SceNpTrophyStatusCallback > statusCb , vm : : ptr < void > arg , u64 options )
2014-02-16 02:51:04 +01:00
{
2016-01-12 22:57:16 +01:00
sceNpTrophy . error ( " sceNpTrophyRegisterContext(context=0x%x, handle=0x%x, statusCb=*0x%x, arg=*0x%x, options=0x%llx) " , context , handle , statusCb , arg , options ) ;
2015-07-02 03:54:36 +02:00
2017-05-15 13:30:14 +02:00
if ( ! statusCb )
{
return SCE_NP_TROPHY_ERROR_INVALID_ARGUMENT ;
}
2015-08-05 17:30:32 +02:00
const auto ctxt = idm : : get < trophy_context_t > ( context ) ;
2015-07-02 03:54:36 +02:00
if ( ! ctxt )
{
2016-01-12 22:57:16 +01:00
sceNpTrophy . error ( " sceNpTrophyRegisterContext(): SCE_NP_TROPHY_ERROR_UNKNOWN_CONTEXT " ) ;
2014-03-06 13:27:58 +01:00
return SCE_NP_TROPHY_ERROR_UNKNOWN_CONTEXT ;
2015-02-08 12:37:10 +01:00
}
2014-02-16 02:51:04 +01:00
2015-08-05 17:30:32 +02:00
const auto hndl = idm : : get < trophy_handle_t > ( handle ) ;
2015-07-02 03:54:36 +02:00
if ( ! hndl )
{
2016-01-12 22:57:16 +01:00
sceNpTrophy . error ( " sceNpTrophyRegisterContext(): SCE_NP_TROPHY_ERROR_UNKNOWN_HANDLE " ) ;
2015-07-02 03:54:36 +02:00
return SCE_NP_TROPHY_ERROR_UNKNOWN_HANDLE ;
}
2014-03-06 13:27:58 +01:00
2016-03-21 20:42:14 +01:00
TRPLoader trp ( ctxt - > trp_stream ) ;
2014-03-17 20:34:19 +01:00
if ( ! trp . LoadHeader ( ) )
2015-07-13 21:06:16 +02:00
{
2016-01-12 22:57:16 +01:00
sceNpTrophy . error ( " sceNpTrophyRegisterContext(): SCE_NP_TROPHY_ERROR_ILLEGAL_UPDATE " ) ;
2014-03-17 20:34:19 +01:00
return SCE_NP_TROPHY_ERROR_ILLEGAL_UPDATE ;
2015-07-13 21:06:16 +02:00
}
2014-03-17 20:34:19 +01:00
// Rename or discard certain entries based on the files found
2014-04-15 16:12:15 +02:00
const size_t kTargetBufferLength = 31 ;
2015-07-13 21:06:16 +02:00
char target [ kTargetBufferLength + 1 ] ;
2014-04-15 16:12:15 +02:00
target [ kTargetBufferLength ] = 0 ;
2016-03-21 20:42:14 +01:00
strcpy_trunc ( target , fmt : : format ( " TROP_%02d.SFM " , /*rpcs3::config.system.language.value()*/ 0 ) ) ;
2014-03-17 20:34:19 +01:00
2015-07-13 21:06:16 +02:00
if ( trp . ContainsEntry ( target ) )
{
2014-03-17 20:34:19 +01:00
trp . RemoveEntry ( " TROPCONF.SFM " ) ;
trp . RemoveEntry ( " TROP.SFM " ) ;
trp . RenameEntry ( target , " TROPCONF.SFM " ) ;
}
2015-07-13 21:06:16 +02:00
else if ( trp . ContainsEntry ( " TROP.SFM " ) )
{
2014-03-17 20:34:19 +01:00
trp . RemoveEntry ( " TROPCONF.SFM " ) ;
trp . RenameEntry ( " TROP.SFM " , " TROPCONF.SFM " ) ;
}
2015-07-13 21:06:16 +02:00
else if ( ! trp . ContainsEntry ( " TROPCONF.SFM " ) )
{
2014-03-17 20:34:19 +01:00
return SCE_NP_TROPHY_ERROR_ILLEGAL_UPDATE ;
}
// Discard unnecessary TROP_XX.SFM files
2015-07-13 21:06:16 +02:00
for ( s32 i = 0 ; i < = 18 ; i + + )
{
2015-08-12 20:38:17 +02:00
strcpy_trunc ( target , fmt : : format ( " TROP_%02d.SFM " , i ) ) ;
2016-03-21 20:42:14 +01:00
if ( i ! = /*rpcs3::config.system.language.value()*/ 0 )
2015-07-13 21:06:16 +02:00
{
2014-03-17 20:34:19 +01:00
trp . RemoveEntry ( target ) ;
2015-07-13 21:06:16 +02:00
}
2014-03-17 20:34:19 +01:00
}
2014-02-16 02:51:04 +01:00
// TODO: Get the path of the current user
2015-07-02 03:54:36 +02:00
std : : string trophyPath = " /dev_hdd0/home/00000001/trophy/ " + ctxt - > trp_name ;
2014-03-20 19:23:14 +01:00
if ( ! trp . Install ( trophyPath ) )
2015-07-13 21:06:16 +02:00
{
2016-01-12 22:57:16 +01:00
sceNpTrophy . error ( " sceNpTrophyRegisterContext(): SCE_NP_TROPHY_ERROR_ILLEGAL_UPDATE " ) ;
2014-03-17 20:34:19 +01:00
return SCE_NP_TROPHY_ERROR_ILLEGAL_UPDATE ;
2015-07-13 21:06:16 +02:00
}
2017-04-13 19:29:47 +02:00
2014-03-20 19:23:14 +01:00
TROPUSRLoader * tropusr = new TROPUSRLoader ( ) ;
2014-03-21 15:07:05 +01:00
std : : string trophyUsrPath = trophyPath + " /TROPUSR.DAT " ;
std : : string trophyConfPath = trophyPath + " /TROPCONF.SFM " ;
tropusr - > Load ( trophyUsrPath , trophyConfPath ) ;
2015-07-02 03:54:36 +02:00
ctxt - > tropusr . reset ( tropusr ) ;
2014-03-20 19:23:14 +01:00
2014-02-16 02:51:04 +01:00
// TODO: Callbacks
2017-05-15 13:30:14 +02:00
if ( statusCb ( ppu , context , SCE_NP_TROPHY_STATUS_INSTALLED , 100 , 100 , arg ) < 0 )
2017-04-14 12:08:17 +02:00
{
return SCE_NP_TROPHY_ERROR_PROCESSING_ABORTED ;
}
2017-05-15 13:30:14 +02:00
if ( statusCb ( ppu , context , SCE_NP_TROPHY_STATUS_PROCESSING_COMPLETE , 100 , 100 , arg ) < 0 )
2017-04-14 12:08:17 +02:00
{
return SCE_NP_TROPHY_ERROR_PROCESSING_ABORTED ;
}
2017-04-13 19:29:47 +02:00
2014-03-17 20:34:19 +01:00
return CELL_OK ;
2014-02-16 02:51:04 +01:00
}
2017-05-15 13:30:14 +02:00
error_code sceNpTrophyGetRequiredDiskSpace ( u32 context , u32 handle , vm : : ptr < u64 > reqspace , u64 options )
2014-02-16 02:51:04 +01:00
{
2016-01-12 22:57:16 +01:00
sceNpTrophy . todo ( " sceNpTrophyGetRequiredDiskSpace(context=0x%x, handle=0x%x, reqspace=*0x%x, options=0x%llx) " , context , handle , reqspace , options ) ;
2014-02-16 02:51:04 +01:00
2017-05-15 13:30:14 +02:00
if ( ! reqspace )
{
return SCE_NP_TROPHY_ERROR_INVALID_ARGUMENT ;
}
2015-08-05 17:30:32 +02:00
const auto ctxt = idm : : get < trophy_context_t > ( context ) ;
2014-02-16 02:51:04 +01:00
2015-07-02 03:54:36 +02:00
if ( ! ctxt )
{
2014-03-06 13:27:58 +01:00
return SCE_NP_TROPHY_ERROR_UNKNOWN_CONTEXT ;
2015-02-08 12:37:10 +01:00
}
2014-02-27 04:21:08 +01:00
2015-08-05 17:30:32 +02:00
const auto hndl = idm : : get < trophy_handle_t > ( handle ) ;
2015-07-02 03:54:36 +02:00
if ( ! hndl )
{
return SCE_NP_TROPHY_ERROR_UNKNOWN_HANDLE ;
}
// TODO: This is not accurate. It's just an approximation of the real value
2017-04-13 19:29:47 +02:00
// The real value can be obtained in TRP.cpp:
// m_headers.trp_file_size - sizeof(m_headers) - (m_headers.trp_files_count * m_headers.trp_element_size);
2017-06-19 04:00:42 +02:00
// TODO: eventually this should be set to 0 when trophys are detected as already installed, setting to 0 now causes some games to not call registerContext, which leads to trophys never getting installed
* reqspace = ctxt - > trp_stream . size ( ) ;
2014-03-06 13:27:58 +01:00
2014-02-16 02:51:04 +01:00
return CELL_OK ;
}
2017-05-15 13:30:14 +02:00
error_code sceNpTrophySetSoundLevel ( u32 context , u32 handle , u32 level , u64 options )
2014-02-16 02:51:04 +01:00
{
2016-01-12 22:57:16 +01:00
sceNpTrophy . todo ( " sceNpTrophySetSoundLevel(context=0x%x, handle=0x%x, level=%d, options=0x%llx) " , context , handle , level , options ) ;
2015-07-02 03:54:36 +02:00
2017-05-15 13:30:14 +02:00
const auto ctxt = idm : : get < trophy_context_t > ( context ) ;
if ( ! ctxt )
{
return SCE_NP_TROPHY_ERROR_UNKNOWN_CONTEXT ;
}
const auto hndl = idm : : get < trophy_handle_t > ( handle ) ;
if ( ! hndl )
{
return SCE_NP_TROPHY_ERROR_UNKNOWN_HANDLE ;
}
2014-02-16 02:51:04 +01:00
return CELL_OK ;
}
2017-05-15 13:30:14 +02:00
error_code sceNpTrophyGetGameInfo ( u32 context , u32 handle , vm : : ptr < SceNpTrophyGameDetails > details , vm : : ptr < SceNpTrophyGameData > data )
2014-02-16 02:51:04 +01:00
{
2016-01-12 22:57:16 +01:00
sceNpTrophy . error ( " sceNpTrophyGetGameInfo(context=0x%x, handle=0x%x, details=*0x%x, data=*0x%x) " , context , handle , details , data ) ;
2014-09-30 20:42:15 +02:00
2017-04-13 19:29:47 +02:00
if ( ! details & & ! data )
{
return SCE_NP_TROPHY_ERROR_INVALID_ARGUMENT ;
}
2015-08-05 17:30:32 +02:00
const auto ctxt = idm : : get < trophy_context_t > ( context ) ;
2014-09-30 20:42:15 +02:00
2015-07-02 03:54:36 +02:00
if ( ! ctxt )
{
return SCE_NP_TROPHY_ERROR_UNKNOWN_CONTEXT ;
}
2014-02-16 02:51:04 +01:00
2015-08-05 17:30:32 +02:00
const auto hndl = idm : : get < trophy_handle_t > ( handle ) ;
2014-03-09 04:57:19 +01:00
2015-07-02 03:54:36 +02:00
if ( ! hndl )
{
return SCE_NP_TROPHY_ERROR_UNKNOWN_HANDLE ;
}
2014-03-09 04:57:19 +01:00
2016-03-21 20:42:14 +01:00
// TODO: Get the path of the current user
const std : : string & path = vfs : : get ( " /dev_hdd0/home/00000001/trophy/ " + ctxt - > trp_name + " /TROPCONF.SFM " ) ;
2017-04-13 19:29:47 +02:00
2016-03-21 20:42:14 +01:00
// TODO: rXmlDocument can open only real file
2017-04-13 19:29:47 +02:00
verify ( HERE ) , ! fs : : get_virtual_device ( path ) ;
2014-05-02 08:30:32 +02:00
rXmlDocument doc ;
doc . Load ( path ) ;
2014-03-20 19:23:14 +01:00
2015-07-26 11:15:15 +02:00
for ( std : : shared_ptr < rXmlNode > n = doc . GetRoot ( ) - > GetChildren ( ) ; n ; n = n - > GetNext ( ) )
{
2017-04-13 19:29:47 +02:00
if ( details )
{
if ( n - > GetName ( ) = = " title-name " )
{
std : : string titleName = n - > GetNodeContent ( ) ;
memcpy ( details - > title , titleName . c_str ( ) , titleName . size ( ) ) ;
}
if ( n - > GetName ( ) = = " title-detail " )
{
std : : string titleDetail = n - > GetNodeContent ( ) ;
memcpy ( details - > description , titleDetail . c_str ( ) , titleDetail . size ( ) ) ;
}
}
2014-03-20 19:23:14 +01:00
if ( n - > GetName ( ) = = " trophy " )
{
2014-05-02 08:30:32 +02:00
u32 trophy_id = atoi ( n - > GetAttribute ( " id " ) . c_str ( ) ) ;
2017-04-13 19:29:47 +02:00
if ( details )
2014-03-20 19:23:14 +01:00
{
2017-04-13 19:29:47 +02:00
details - > numTrophies + + ;
2014-05-02 08:30:32 +02:00
switch ( n - > GetAttribute ( " ttype " ) [ 0 ] ) {
2017-04-13 19:29:47 +02:00
case ' B ' : details - > numBronze + + ; break ;
case ' S ' : details - > numSilver + + ; break ;
case ' G ' : details - > numGold + + ; break ;
case ' P ' : details - > numPlatinum + + ; break ;
}
}
if ( data )
{
if ( ctxt - > tropusr - > GetTrophyUnlockState ( trophy_id ) )
{
data - > unlockedTrophies + + ;
switch ( n - > GetAttribute ( " ttype " ) [ 0 ] ) {
case ' B ' : data - > unlockedBronze + + ; break ;
case ' S ' : data - > unlockedSilver + + ; break ;
case ' G ' : data - > unlockedGold + + ; break ;
case ' P ' : data - > unlockedPlatinum + + ; break ;
}
2014-03-20 19:23:14 +01:00
}
}
}
}
2014-02-16 02:51:04 +01:00
return CELL_OK ;
}
2017-05-15 13:30:14 +02:00
error_code sceNpTrophyUnlockTrophy ( u32 context , u32 handle , s32 trophyId , vm : : ptr < u32 > platinumId )
2014-02-16 02:51:04 +01:00
{
2016-01-12 22:57:16 +01:00
sceNpTrophy . error ( " sceNpTrophyUnlockTrophy(context=0x%x, handle=0x%x, trophyId=%d, platinumId=*0x%x) " , context , handle , trophyId , platinumId ) ;
2014-02-16 02:51:04 +01:00
2015-08-05 17:30:32 +02:00
const auto ctxt = idm : : get < trophy_context_t > ( context ) ;
2015-07-02 03:54:36 +02:00
if ( ! ctxt )
{
return SCE_NP_TROPHY_ERROR_UNKNOWN_CONTEXT ;
}
2014-03-20 19:23:14 +01:00
2015-08-05 17:30:32 +02:00
const auto hndl = idm : : get < trophy_handle_t > ( handle ) ;
2015-07-02 03:54:36 +02:00
if ( ! hndl )
{
return SCE_NP_TROPHY_ERROR_UNKNOWN_HANDLE ;
}
if ( trophyId > = ( s32 ) ctxt - > tropusr - > GetTrophiesCount ( ) )
2014-03-20 19:23:14 +01:00
return SCE_NP_TROPHY_ERROR_INVALID_TROPHY_ID ;
2015-07-02 03:54:36 +02:00
if ( ctxt - > tropusr - > GetTrophyUnlockState ( trophyId ) )
2014-03-20 19:23:14 +01:00
return SCE_NP_TROPHY_ERROR_ALREADY_UNLOCKED ;
2015-07-06 01:21:15 +02:00
ctxt - > tropusr - > UnlockTrophy ( trophyId , 0 , 0 ) ; // TODO
2015-07-02 03:54:36 +02:00
std : : string trophyPath = " /dev_hdd0/home/00000001/trophy/ " + ctxt - > trp_name + " /TROPUSR.DAT " ;
ctxt - > tropusr - > Save ( trophyPath ) ;
2014-03-20 19:23:14 +01:00
2014-09-01 02:51:48 +02:00
* platinumId = SCE_NP_TROPHY_INVALID_TROPHY_ID ; // TODO
2014-02-16 02:51:04 +01:00
return CELL_OK ;
}
2017-05-15 13:30:14 +02:00
error_code sceNpTrophyGetTrophyUnlockState ( u32 context , u32 handle , vm : : ptr < SceNpTrophyFlagArray > flags , vm : : ptr < u32 > count )
2014-02-16 02:51:04 +01:00
{
2016-01-12 22:57:16 +01:00
sceNpTrophy . error ( " sceNpTrophyGetTrophyUnlockState(context=0x%x, handle=0x%x, flags=*0x%x, count=*0x%x) " , context , handle , flags , count ) ;
2014-09-22 21:00:28 +02:00
2017-04-13 19:29:47 +02:00
if ( ! flags | | ! count )
{
return SCE_NP_TROPHY_ERROR_INVALID_ARGUMENT ;
}
2015-08-05 17:30:32 +02:00
const auto ctxt = idm : : get < trophy_context_t > ( context ) ;
2014-09-22 21:00:28 +02:00
2015-07-02 03:54:36 +02:00
if ( ! ctxt )
{
return SCE_NP_TROPHY_ERROR_UNKNOWN_CONTEXT ;
}
2014-02-16 02:51:04 +01:00
2015-08-05 17:30:32 +02:00
const auto hndl = idm : : get < trophy_handle_t > ( handle ) ;
2014-03-20 19:23:14 +01:00
2015-07-02 03:54:36 +02:00
if ( ! hndl )
{
return SCE_NP_TROPHY_ERROR_UNKNOWN_HANDLE ;
2015-02-08 12:37:10 +01:00
}
2014-03-20 19:23:14 +01:00
2015-07-02 03:54:36 +02:00
u32 count_ = ctxt - > tropusr - > GetTrophiesCount ( ) ;
2015-02-08 12:37:10 +01:00
* count = count_ ;
if ( count_ > 128 )
2016-01-12 22:57:16 +01:00
sceNpTrophy . error ( " sceNpTrophyGetTrophyUnlockState: More than 128 trophies detected! " ) ;
2014-03-20 19:23:14 +01:00
// Pack up to 128 bools in u32 flag_bits[4]
2015-02-08 12:37:10 +01:00
for ( u32 id = 0 ; id < count_ ; id + + )
2014-03-20 19:23:14 +01:00
{
2015-07-02 03:54:36 +02:00
if ( ctxt - > tropusr - > GetTrophyUnlockState ( id ) )
2017-04-13 19:29:47 +02:00
flags - > flag_bits [ id / 32 ] | = 1 < < ( id % 32 ) ;
2014-03-20 19:23:14 +01:00
else
2017-04-13 19:29:47 +02:00
flags - > flag_bits [ id / 32 ] & = ~ ( 1 < < ( id % 32 ) ) ;
2014-03-20 19:23:14 +01:00
}
2014-02-16 02:51:04 +01:00
return CELL_OK ;
}
2017-05-15 13:30:14 +02:00
error_code sceNpTrophyGetTrophyInfo ( u32 context , u32 handle , s32 trophyId , vm : : ptr < SceNpTrophyDetails > details , vm : : ptr < SceNpTrophyData > data )
2014-02-16 02:51:04 +01:00
{
2016-01-12 22:57:16 +01:00
sceNpTrophy . warning ( " sceNpTrophyGetTrophyInfo(context=0x%x, handle=0x%x, trophyId=%d, details=*0x%x, data=*0x%x) " , context , handle , trophyId , details , data ) ;
2014-02-16 02:51:04 +01:00
2017-04-13 19:29:47 +02:00
if ( ! details & & ! data )
{
return SCE_NP_TROPHY_ERROR_INVALID_ARGUMENT ;
}
2015-08-05 17:30:32 +02:00
const auto ctxt = idm : : get < trophy_context_t > ( context ) ;
2015-07-02 03:54:36 +02:00
if ( ! ctxt )
{
return SCE_NP_TROPHY_ERROR_UNKNOWN_CONTEXT ;
}
2015-08-05 17:30:32 +02:00
const auto hndl = idm : : get < trophy_handle_t > ( handle ) ;
2014-03-06 01:52:23 +01:00
2015-07-02 03:54:36 +02:00
if ( ! hndl )
{
return SCE_NP_TROPHY_ERROR_UNKNOWN_HANDLE ;
}
2017-04-13 19:29:47 +02:00
2016-03-21 20:42:14 +01:00
// TODO: Get the path of the current user
const std : : string & path = vfs : : get ( " /dev_hdd0/home/00000001/trophy/ " + ctxt - > trp_name + " /TROPCONF.SFM " ) ;
// TODO: rXmlDocument can open only real file
2016-08-15 02:11:49 +02:00
verify ( HERE ) , ! fs : : get_virtual_device ( path ) ;
2017-04-13 19:29:47 +02:00
rXmlDocument doc ;
2014-05-02 08:30:32 +02:00
doc . Load ( path ) ;
2017-09-02 13:43:44 +02:00
auto trophy_base = doc . GetRoot ( ) ;
if ( trophy_base - > GetChildren ( ) - > GetName ( ) = = " trophyconf " )
{
trophy_base = trophy_base - > GetChildren ( ) ;
}
2014-03-20 19:23:14 +01:00
2017-04-13 19:29:47 +02:00
bool found = false ;
2017-09-02 13:43:44 +02:00
for ( std : : shared_ptr < rXmlNode > n = trophy_base - > GetChildren ( ) ; n ; n = n - > GetNext ( ) ) {
2014-05-02 08:30:32 +02:00
if ( n - > GetName ( ) = = " trophy " & & ( trophyId = = atoi ( n - > GetAttribute ( " id " ) . c_str ( ) ) ) )
2014-03-20 19:23:14 +01:00
{
2017-04-13 19:29:47 +02:00
found = true ;
if ( n - > GetAttribute ( " hidden " ) [ 0 ] = = ' y ' & & ! ctxt - > tropusr - > GetTrophyUnlockState ( trophyId ) ) // Trophy is hidden
{
return SCE_NP_TROPHY_ERROR_HIDDEN ;
2014-03-20 19:23:14 +01:00
}
2017-04-13 19:29:47 +02:00
if ( details )
{
details - > trophyId = trophyId ;
switch ( n - > GetAttribute ( " ttype " ) [ 0 ] ) {
case ' B ' : details - > trophyGrade = SCE_NP_TROPHY_GRADE_BRONZE ; break ;
case ' S ' : details - > trophyGrade = SCE_NP_TROPHY_GRADE_SILVER ; break ;
case ' G ' : details - > trophyGrade = SCE_NP_TROPHY_GRADE_GOLD ; break ;
case ' P ' : details - > trophyGrade = SCE_NP_TROPHY_GRADE_PLATINUM ; break ;
}
switch ( n - > GetAttribute ( " hidden " ) [ 0 ] ) {
case ' y ' : details - > hidden = true ; break ;
case ' n ' : details - > hidden = false ; break ;
}
for ( std : : shared_ptr < rXmlNode > n2 = n - > GetChildren ( ) ; n2 ; n2 = n2 - > GetNext ( ) ) {
if ( n2 - > GetName ( ) = = " name " )
{
std : : string name = n2 - > GetNodeContent ( ) ;
memcpy ( details - > name , name . c_str ( ) , std : : min ( ( size_t ) SCE_NP_TROPHY_NAME_MAX_SIZE , name . length ( ) + 1 ) ) ;
}
if ( n2 - > GetName ( ) = = " detail " )
{
std : : string detail = n2 - > GetNodeContent ( ) ;
memcpy ( details - > description , detail . c_str ( ) , std : : min ( ( size_t ) SCE_NP_TROPHY_DESCR_MAX_SIZE , detail . length ( ) + 1 ) ) ;
}
}
2014-03-20 19:23:14 +01:00
}
2017-04-13 19:29:47 +02:00
if ( data )
{
data - > trophyId = trophyId ;
data - > unlocked = ctxt - > tropusr - > GetTrophyUnlockState ( trophyId ) ! = 0 ; // ???
data - > timestamp = ctxt - > tropusr - > GetTrophyTimestamp ( trophyId ) ;
2014-03-20 19:23:14 +01:00
}
2017-04-13 19:29:47 +02:00
break ;
}
}
2014-03-20 19:23:14 +01:00
2017-04-13 19:29:47 +02:00
if ( ! found )
{
2017-05-15 13:30:14 +02:00
return not_an_error ( SCE_NP_TROPHY_INVALID_TROPHY_ID ) ;
2014-03-20 19:23:14 +01:00
}
2014-03-09 04:57:19 +01:00
2014-02-16 02:51:04 +01:00
return CELL_OK ;
}
2017-05-15 13:30:14 +02:00
error_code sceNpTrophyGetGameProgress ( u32 context , u32 handle , vm : : ptr < s32 > percentage )
2014-02-16 02:51:04 +01:00
{
2017-04-13 19:29:47 +02:00
sceNpTrophy . warning ( " sceNpTrophyGetGameProgress(context=0x%x, handle=0x%x, percentage=*0x%x) " , context , handle , percentage ) ;
if ( ! percentage )
{
return SCE_NP_TROPHY_ERROR_INVALID_ARGUMENT ;
}
const auto ctxt = idm : : get < trophy_context_t > ( context ) ;
if ( ! ctxt )
{
return SCE_NP_TROPHY_ERROR_UNKNOWN_CONTEXT ;
}
const auto hndl = idm : : get < trophy_handle_t > ( handle ) ;
if ( ! hndl )
{
return SCE_NP_TROPHY_ERROR_UNKNOWN_HANDLE ;
}
double accuratePercentage = 0 ;
for ( int i = ctxt - > tropusr - > GetTrophiesCount ( ) - 1 ; i > = 0 ; i - - )
{
if ( ctxt - > tropusr - > GetTrophyUnlockState ( i ) )
{
accuratePercentage + + ;
}
}
* percentage = ( s32 ) ( accuratePercentage / ctxt - > tropusr - > GetTrophiesCount ( ) ) ;
2015-07-02 03:54:36 +02:00
2014-02-16 02:51:04 +01:00
return CELL_OK ;
}
2017-05-15 13:30:14 +02:00
error_code sceNpTrophyGetGameIcon ( u32 context , u32 handle , vm : : ptr < void > buffer , vm : : ptr < u32 > size )
2014-02-16 02:51:04 +01:00
{
2017-04-13 19:29:47 +02:00
sceNpTrophy . warning ( " sceNpTrophyGetGameIcon(context=0x%x, handle=0x%x, buffer=*0x%x, size=*0x%x) " , context , handle , buffer , size ) ;
if ( ! size )
{
return SCE_NP_TROPHY_ERROR_INVALID_ARGUMENT ;
}
const auto ctxt = idm : : get < trophy_context_t > ( context ) ;
if ( ! ctxt )
{
return SCE_NP_TROPHY_ERROR_UNKNOWN_CONTEXT ;
}
const auto hndl = idm : : get < trophy_handle_t > ( handle ) ;
if ( ! hndl )
{
return SCE_NP_TROPHY_ERROR_UNKNOWN_HANDLE ;
}
const std : : string & path = vfs : : get ( " /dev_hdd0/home/00000001/trophy/ " + ctxt - > trp_name + " /ICON0.PNG " ) ;
if ( ! fs : : exists ( path ) )
{
return SCE_NP_TROPHY_ERROR_UNKNOWN_FILE ;
}
fs : : file gameIconFile ( path ) ;
if ( buffer & & * size > = gameIconFile . size ( ) )
{
gameIconFile . read ( buffer . get_ptr ( ) , gameIconFile . size ( ) ) ;
}
* size = gameIconFile . size ( ) ;
2014-02-16 02:51:04 +01:00
2015-07-02 03:54:36 +02:00
return CELL_OK ;
}
2017-05-15 13:30:14 +02:00
error_code sceNpTrophyGetTrophyIcon ( u32 context , u32 handle , s32 trophyId , vm : : ptr < void > buffer , vm : : ptr < u32 > size )
2015-07-02 03:54:36 +02:00
{
2017-04-13 19:29:47 +02:00
sceNpTrophy . warning ( " sceNpTrophyGetTrophyIcon(context=0x%x, handle=0x%x, trophyId=%d, buffer=*0x%x, size=*0x%x) " , context , handle , trophyId , buffer , size ) ;
if ( ! size )
{
return SCE_NP_TROPHY_ERROR_INVALID_ARGUMENT ;
}
const auto ctxt = idm : : get < trophy_context_t > ( context ) ;
if ( ! ctxt )
{
return SCE_NP_TROPHY_ERROR_UNKNOWN_CONTEXT ;
}
const auto hndl = idm : : get < trophy_handle_t > ( handle ) ;
if ( ! hndl )
{
return SCE_NP_TROPHY_ERROR_UNKNOWN_HANDLE ;
}
if ( ctxt - > tropusr - > GetTrophiesCount ( ) < = ( u32 ) trophyId )
{
return SCE_NP_TROPHY_ERROR_INVALID_TROPHY_ID ;
}
if ( ! ctxt - > tropusr - > GetTrophyUnlockState ( trophyId ) )
{
bool hidden = false ; // TODO obtain this value
return hidden ? SCE_NP_TROPHY_ERROR_HIDDEN : SCE_NP_TROPHY_ERROR_LOCKED ;
}
const std : : string & path = vfs : : get ( " /dev_hdd0/home/00000001/trophy/ " + ctxt - > trp_name + fmt : : format ( " /TROP%03d.PNG " , trophyId ) ) ;
if ( ! fs : : exists ( path ) )
{
return SCE_NP_TROPHY_ERROR_UNKNOWN_FILE ;
}
fs : : file trophyIconFile ( path ) ;
if ( buffer & & * size > = trophyIconFile . size ( ) )
{
trophyIconFile . read ( buffer . get_ptr ( ) , trophyIconFile . size ( ) ) ;
}
* size = trophyIconFile . size ( ) ;
2015-07-02 03:54:36 +02:00
return CELL_OK ;
}
2016-03-21 20:42:14 +01:00
DECLARE ( ppu_module_manager : : sceNpTrophy ) ( " sceNpTrophy " , [ ] ( )
2015-07-02 03:54:36 +02:00
{
2015-02-20 14:58:40 +01:00
REG_FUNC ( sceNpTrophy , sceNpTrophyGetGameProgress ) ;
REG_FUNC ( sceNpTrophy , sceNpTrophyRegisterContext ) ;
REG_FUNC ( sceNpTrophy , sceNpTrophyCreateHandle ) ;
REG_FUNC ( sceNpTrophy , sceNpTrophySetSoundLevel ) ;
REG_FUNC ( sceNpTrophy , sceNpTrophyGetRequiredDiskSpace ) ;
REG_FUNC ( sceNpTrophy , sceNpTrophyDestroyContext ) ;
REG_FUNC ( sceNpTrophy , sceNpTrophyInit ) ;
REG_FUNC ( sceNpTrophy , sceNpTrophyAbortHandle ) ;
REG_FUNC ( sceNpTrophy , sceNpTrophyGetGameInfo ) ;
REG_FUNC ( sceNpTrophy , sceNpTrophyDestroyHandle ) ;
REG_FUNC ( sceNpTrophy , sceNpTrophyUnlockTrophy ) ;
REG_FUNC ( sceNpTrophy , sceNpTrophyTerm ) ;
REG_FUNC ( sceNpTrophy , sceNpTrophyGetTrophyUnlockState ) ;
REG_FUNC ( sceNpTrophy , sceNpTrophyGetTrophyIcon ) ;
REG_FUNC ( sceNpTrophy , sceNpTrophyCreateContext ) ;
REG_FUNC ( sceNpTrophy , sceNpTrophyGetTrophyInfo ) ;
REG_FUNC ( sceNpTrophy , sceNpTrophyGetGameIcon ) ;
2015-02-18 17:22:06 +01:00
} ) ;