2013-09-28 04:36:57 +02:00
# include "stdafx.h"
2014-06-02 19:27:24 +02:00
# include "Emu/System.h"
2015-08-06 17:55:19 +02:00
# include "Emu/IdManager.h"
2016-03-21 20:43:03 +01:00
# include "Emu/Cell/PPUModule.h"
2013-09-28 04:36:57 +02:00
2015-04-13 16:05:44 +02:00
# include "cellSysutil.h"
2015-12-19 12:40:52 +01:00
# include "cellMsgDialog.h"
2014-07-01 00:53:29 +02:00
# include "cellGame.h"
2016-04-25 12:49:12 +02:00
# include "Loader/PSF.h"
2016-04-27 00:27:24 +02:00
# include "Utilities/StrUtil.h"
2016-03-21 20:43:03 +01:00
2016-05-13 15:55:34 +02:00
# include <thread>
2017-05-13 20:30:37 +02:00
logs : : channel cellGame ( " cellGame " ) ;
2013-09-28 04:36:57 +02:00
2016-08-16 17:46:24 +02:00
template < >
void fmt_class_string < CellGameError > : : format ( std : : string & out , u64 arg )
{
format_enum ( out , arg , [ ] ( auto error )
{
switch ( error )
{
STR_CASE ( CELL_GAME_ERROR_NOTFOUND ) ;
STR_CASE ( CELL_GAME_ERROR_BROKEN ) ;
STR_CASE ( CELL_GAME_ERROR_INTERNAL ) ;
STR_CASE ( CELL_GAME_ERROR_PARAM ) ;
STR_CASE ( CELL_GAME_ERROR_NOAPP ) ;
STR_CASE ( CELL_GAME_ERROR_ACCESS_ERROR ) ;
STR_CASE ( CELL_GAME_ERROR_NOSPACE ) ;
STR_CASE ( CELL_GAME_ERROR_NOTSUPPORTED ) ;
STR_CASE ( CELL_GAME_ERROR_FAILURE ) ;
STR_CASE ( CELL_GAME_ERROR_BUSY ) ;
STR_CASE ( CELL_GAME_ERROR_IN_SHUTDOWN ) ;
STR_CASE ( CELL_GAME_ERROR_INVALID_ID ) ;
STR_CASE ( CELL_GAME_ERROR_EXIST ) ;
STR_CASE ( CELL_GAME_ERROR_NOTPATCH ) ;
STR_CASE ( CELL_GAME_ERROR_INVALID_THEME_FILE ) ;
STR_CASE ( CELL_GAME_ERROR_BOOTPATH ) ;
}
return unknown ;
} ) ;
}
template < >
void fmt_class_string < CellGameDataError > : : format ( std : : string & out , u64 arg )
{
format_enum ( out , arg , [ ] ( auto error )
{
switch ( error )
{
STR_CASE ( CELL_GAMEDATA_ERROR_CBRESULT ) ;
STR_CASE ( CELL_GAMEDATA_ERROR_ACCESS_ERROR ) ;
STR_CASE ( CELL_GAMEDATA_ERROR_INTERNAL ) ;
STR_CASE ( CELL_GAMEDATA_ERROR_PARAM ) ;
STR_CASE ( CELL_GAMEDATA_ERROR_NOSPACE ) ;
STR_CASE ( CELL_GAMEDATA_ERROR_BROKEN ) ;
STR_CASE ( CELL_GAMEDATA_ERROR_FAILURE ) ;
}
return unknown ;
} ) ;
}
2016-08-17 20:59:42 +02:00
// If dir is empty:
// contentInfo = "/dev_bdvd/PS3_GAME"
// usrdir = "/dev_bdvd/PS3_GAME/USRDIR"
// Temporary content directory (dir is not empty):
2015-08-06 17:55:19 +02:00
// contentInfo = "/dev_hdd1/game/" + dir
// usrdir = "/dev_hdd1/game/" + dir + "/USRDIR"
2016-08-17 20:59:42 +02:00
// Normal content directory (dir is not empty):
2015-08-06 17:55:19 +02:00
// contentInfo = "/dev_hdd0/game/" + dir
// usrdir = "/dev_hdd0/game/" + dir + "/USRDIR"
2016-04-25 12:49:12 +02:00
struct content_permission final
2015-08-06 17:55:19 +02:00
{
2016-04-25 12:49:12 +02:00
// Content directory name or path
2015-08-06 17:55:19 +02:00
const std : : string dir ;
2016-04-25 12:49:12 +02:00
// SFO file
psf : : registry sfo ;
// True if temporary directory is created and must be moved or deleted
2015-08-06 17:55:19 +02:00
bool is_temporary = false ;
2016-08-17 20:59:42 +02:00
template < typename Dir , typename Sfo >
content_permission ( Dir & & dir , Sfo & & sfo , bool is_temp = false )
: dir ( std : : forward < Dir > ( dir ) )
, sfo ( std : : forward < Sfo > ( sfo ) )
2015-12-19 12:40:52 +01:00
, is_temporary ( is_temp )
2015-08-06 17:55:19 +02:00
{
}
2016-04-25 12:49:12 +02:00
~ content_permission ( )
2015-08-06 17:55:19 +02:00
{
2016-08-18 12:27:20 +02:00
try
2015-08-06 17:55:19 +02:00
{
2016-08-18 12:27:20 +02:00
if ( is_temporary )
{
fs : : remove_all ( vfs : : get ( " /dev_hdd1/game/ " + dir ) ) ;
}
}
catch ( . . . )
{
cellGame . fatal ( " Failed to clean directory '/dev_hdd1/game/%s' " , dir ) ;
catch_all_exceptions ( ) ;
2015-08-06 17:55:19 +02:00
}
}
} ;
2014-06-28 03:19:44 +02:00
2016-07-27 23:43:22 +02:00
s32 cellHddGameCheck ( ppu_thread & ppu , u32 version , vm : : cptr < char > dirName , u32 errDialog , vm : : ptr < CellHddGameStatCallback > funcStat , u32 container )
2013-11-29 05:56:26 +01:00
{
2016-08-11 01:29:59 +02:00
cellGame . error ( " cellHddGameCheck(version=%d, dirName=%s, errDialog=%d, funcStat=*0x%x, container=%d) " , version , dirName , errDialog , funcStat , container ) ;
2015-04-13 16:05:44 +02:00
std : : string dir = dirName . get_ptr ( ) ;
2015-04-16 01:17:42 +02:00
2015-04-13 16:05:44 +02:00
if ( dir . size ( ) ! = 9 )
2015-04-16 01:17:42 +02:00
{
2015-04-13 16:05:44 +02:00
return CELL_HDDGAME_ERROR_PARAM ;
2015-04-16 01:17:42 +02:00
}
2015-04-13 16:05:44 +02:00
2015-09-26 22:46:04 +02:00
vm : : var < CellHddGameCBResult > result ;
vm : : var < CellHddGameStatGet > get ;
vm : : var < CellHddGameStatSet > set ;
2015-04-13 16:05:44 +02:00
get - > hddFreeSizeKB = 40 * 1024 * 1024 ; // 40 GB, TODO: Use the free space of the computer's HDD where RPCS3 is being run.
get - > isNewData = CELL_HDDGAME_ISNEWDATA_EXIST ;
get - > sysSizeKB = 0 ; // TODO
get - > atime = 0 ; // TODO
get - > ctime = 0 ; // TODO
get - > mtime = 0 ; // TODO
get - > sizeKB = CELL_HDDGAME_SIZEKB_NOTCALC ;
2015-04-16 01:17:42 +02:00
strcpy_trunc ( get - > contentInfoPath , " /dev_hdd0/game/ " + dir ) ;
strcpy_trunc ( get - > hddGamePath , " /dev_hdd0/game/ " + dir + " /USRDIR " ) ;
2015-04-13 16:05:44 +02:00
2016-03-21 20:43:03 +01:00
const std : : string & local_dir = vfs : : get ( " /dev_hdd0/game/ " + dir ) ;
if ( ! fs : : is_dir ( local_dir ) )
2015-04-13 16:05:44 +02:00
{
get - > isNewData = CELL_HDDGAME_ISNEWDATA_NODIR ;
2016-03-21 20:43:03 +01:00
get - > getParam = { } ;
2015-04-13 16:05:44 +02:00
}
else
{
// TODO: Is cellHddGameCheck really responsible for writing the information in get->getParam ? (If not, delete this else)
2016-03-21 20:43:03 +01:00
const auto & psf = psf : : load_object ( fs : : file ( local_dir + " /PARAM.SFO " ) ) ;
2015-04-13 16:05:44 +02:00
2016-06-20 00:43:13 +02:00
// Some following fields may be zero in old FW 1.00 version PARAM.SFO
if ( psf . count ( " PARENTAL_LEVEL " ) ! = 0 ) get - > getParam . parentalLevel = psf . at ( " PARENTAL_LEVEL " ) . as_integer ( ) ;
if ( psf . count ( " ATTRIBUTE " ) ! = 0 ) get - > getParam . attribute = psf . at ( " ATTRIBUTE " ) . as_integer ( ) ;
if ( psf . count ( " RESOLUTION " ) ! = 0 ) get - > getParam . resolution = psf . at ( " RESOLUTION " ) . as_integer ( ) ;
if ( psf . count ( " SOUND_FORMAT " ) ! = 0 ) get - > getParam . soundFormat = psf . at ( " SOUND_FORMAT " ) . as_integer ( ) ;
if ( psf . count ( " TITLE " ) ! = 0 ) strcpy_trunc ( get - > getParam . title , psf . at ( " TITLE " ) . as_string ( ) ) ;
if ( psf . count ( " APP_VER " ) ! = 0 ) strcpy_trunc ( get - > getParam . dataVersion , psf . at ( " APP_VER " ) . as_string ( ) ) ;
if ( psf . count ( " TITLE_ID " ) ! = 0 ) strcpy_trunc ( get - > getParam . titleId , psf . at ( " TITLE_ID " ) . as_string ( ) ) ;
2015-04-13 16:05:44 +02:00
2015-04-16 01:17:42 +02:00
for ( u32 i = 0 ; i < CELL_HDDGAME_SYSP_LANGUAGE_NUM ; i + + )
{
2016-01-26 19:13:36 +01:00
strcpy_trunc ( get - > getParam . titleLang [ i ] , psf : : get_string ( psf , fmt : : format ( " TITLE_%02d " , i ) ) ) ;
2015-04-13 16:05:44 +02:00
}
}
// TODO ?
2015-09-10 15:09:31 +02:00
funcStat ( ppu , result , get , set ) ;
2015-04-13 16:05:44 +02:00
2015-09-10 15:09:31 +02:00
if ( result - > result ! = CELL_HDDGAME_CBRESULT_OK & & result - > result ! = CELL_HDDGAME_CBRESULT_OK_CANCEL )
{
return CELL_HDDGAME_ERROR_CBRESULT ;
}
2015-04-13 16:05:44 +02:00
// TODO ?
return CELL_OK ;
}
2015-08-01 18:14:49 +02:00
s32 cellHddGameCheck2 ( )
{
2016-08-08 18:01:06 +02:00
fmt : : throw_exception ( " Unimplemented " HERE ) ;
2015-08-01 18:14:49 +02:00
}
2017-02-05 14:07:26 +01:00
s32 cellHddGameGetSizeKB ( vm : : ptr < u32 > size )
2015-08-01 18:14:49 +02:00
{
2017-03-22 11:09:10 +01:00
cellGame . warning ( " cellHddGameGetSizeKB(size=*0x%x) " , size ) ;
const std : : string & local_dir = vfs : : get ( " /dev_hdd0/game/ " + Emu . GetTitleID ( ) ) ;
if ( ! fs : : is_dir ( local_dir ) )
{
return CELL_HDDGAME_ERROR_FAILURE ;
}
2017-03-26 00:16:47 +01:00
* size = ( u32 ) ( fs : : get_dir_size ( local_dir ) / 1024 ) ;
2017-02-05 14:07:26 +01:00
return CELL_OK ;
2015-08-01 18:14:49 +02:00
}
s32 cellHddGameSetSystemVer ( )
{
2016-08-08 18:01:06 +02:00
fmt : : throw_exception ( " Unimplemented " HERE ) ;
2015-08-01 18:14:49 +02:00
}
s32 cellHddGameExitBroken ( )
{
2016-08-08 18:01:06 +02:00
fmt : : throw_exception ( " Unimplemented " HERE ) ;
2015-08-01 18:14:49 +02:00
}
2016-12-05 18:35:05 +01:00
s32 cellGameDataGetSizeKB ( vm : : ptr < u32 > size )
2015-08-01 18:14:49 +02:00
{
2017-03-22 11:09:10 +01:00
cellGame . warning ( " cellGameDataGetSizeKB(size=*0x%x) " , size ) ;
const std : : string & local_dir = vfs : : get ( " /dev_hdd0/game/ " + Emu . GetTitleID ( ) ) ;
if ( ! fs : : is_dir ( local_dir ) )
{
return CELL_GAMEDATA_ERROR_FAILURE ;
}
2017-03-26 00:16:47 +01:00
* size = ( u32 ) ( fs : : get_dir_size ( local_dir ) / 1024 ) ;
2017-02-05 14:07:26 +01:00
2016-12-05 18:35:05 +01:00
return CELL_OK ;
2017-03-22 11:09:10 +01:00
2015-08-01 18:14:49 +02:00
}
s32 cellGameDataSetSystemVer ( )
{
2016-08-08 18:01:06 +02:00
fmt : : throw_exception ( " Unimplemented " HERE ) ;
2015-08-01 18:14:49 +02:00
}
s32 cellGameDataExitBroken ( )
{
2016-08-08 18:01:06 +02:00
fmt : : throw_exception ( " Unimplemented " HERE ) ;
2015-08-01 18:14:49 +02:00
}
2016-08-16 17:46:24 +02:00
error_code cellGameBootCheck ( vm : : ptr < u32 > type , vm : : ptr < u32 > attributes , vm : : ptr < CellGameContentSize > size , vm : : ptr < char [ CELL_GAME_DIRNAME_SIZE ] > dirName )
2015-04-13 16:05:44 +02:00
{
2016-01-12 22:57:16 +01:00
cellGame . warning ( " cellGameBootCheck(type=*0x%x, attributes=*0x%x, size=*0x%x, dirName=*0x%x) " , type , attributes , size , dirName ) ;
2013-11-29 05:56:26 +01:00
2014-08-12 19:44:28 +02:00
if ( size )
{
// TODO: Use the free space of the computer's HDD where RPCS3 is being run.
size - > hddFreeSizeKB = 40000000 ; // 40 GB
2014-06-28 03:19:44 +02:00
2014-08-12 19:44:28 +02:00
// TODO: Calculate data size for HG and DG games, if necessary.
size - > sizeKB = CELL_GAME_SIZEKB_NOTCALC ;
size - > sysSizeKB = 0 ;
}
2014-03-17 20:34:19 +01:00
2016-03-21 20:43:03 +01:00
// According to testing (in debug mode) cellGameBootCheck doesn't return an error code, when PARAM.SFO doesn't exist.
2016-08-17 20:59:42 +02:00
psf : : registry sfo = psf : : load_object ( fs : : file ( vfs : : get ( " /app_home/../PARAM.SFO " ) ) ) ;
2016-04-25 12:49:12 +02:00
const std : : string & category = psf : : get_string ( sfo , " CATEGORY " ) ;
2014-06-28 03:19:44 +02:00
2016-01-26 19:13:36 +01:00
if ( category = = " DG " )
2014-06-28 03:19:44 +02:00
{
2014-09-01 02:51:48 +02:00
* type = CELL_GAME_GAMETYPE_DISC ;
* attributes = 0 ; // TODO
2014-09-05 01:23:36 +02:00
if ( dirName ) strcpy_trunc ( * dirName , " " ) ; // ???
2015-08-06 17:55:19 +02:00
2016-08-17 20:59:42 +02:00
if ( ! fxm : : make < content_permission > ( " " , std : : move ( sfo ) ) )
2015-08-06 17:55:19 +02:00
{
return CELL_GAME_ERROR_BUSY ;
}
2014-06-28 03:19:44 +02:00
}
2017-02-11 20:11:04 +01:00
else if ( category = = " AP " | | category = = " AV " | | category = = " HG " )
2014-06-28 03:19:44 +02:00
{
2014-09-01 02:51:48 +02:00
* type = CELL_GAME_GAMETYPE_HDD ;
* attributes = 0 ; // TODO
2016-03-21 20:43:03 +01:00
if ( dirName ) strcpy_trunc ( * dirName , Emu . GetTitleID ( ) ) ;
2015-08-06 17:55:19 +02:00
2016-08-17 20:59:42 +02:00
if ( ! fxm : : make < content_permission > ( Emu . GetTitleID ( ) , std : : move ( sfo ) ) )
2015-08-06 17:55:19 +02:00
{
return CELL_GAME_ERROR_BUSY ;
}
2014-06-28 03:19:44 +02:00
}
2016-01-26 19:13:36 +01:00
else if ( category = = " GD " )
2014-06-28 03:19:44 +02:00
{
2014-09-01 02:51:48 +02:00
* type = CELL_GAME_GAMETYPE_DISC ;
* attributes = CELL_GAME_ATTRIBUTE_PATCH ; // TODO
2016-03-21 20:43:03 +01:00
if ( dirName ) strcpy_trunc ( * dirName , Emu . GetTitleID ( ) ) ; // ???
2015-08-06 17:55:19 +02:00
2016-08-17 20:59:42 +02:00
if ( ! fxm : : make < content_permission > ( " " , std : : move ( sfo ) ) )
2015-08-06 17:55:19 +02:00
{
return CELL_GAME_ERROR_BUSY ;
}
2014-06-28 03:19:44 +02:00
}
2016-01-26 19:13:36 +01:00
else
2014-06-28 03:19:44 +02:00
{
2016-07-14 22:12:26 +02:00
// Hack: When there is no (or unknown) CATEGORY returned, instead of throwing an exception
// we assume it's a disk game.
* type = CELL_GAME_GAMETYPE_DISC ;
* attributes = 0 ;
cellGame . error ( " cellGameBootCheck(): Unknown CATEGORY: %s " , category ) ;
2014-06-28 03:19:44 +02:00
}
2013-11-29 05:56:26 +01:00
2016-08-16 17:46:24 +02:00
return CELL_OK ;
2013-09-28 04:36:57 +02:00
}
2016-08-16 17:46:24 +02:00
error_code cellGamePatchCheck ( vm : : ptr < CellGameContentSize > size , vm : : ptr < void > reserved )
2013-09-28 04:36:57 +02:00
{
2016-01-12 22:57:16 +01:00
cellGame . warning ( " cellGamePatchCheck(size=*0x%x, reserved=*0x%x) " , size , reserved ) ;
2014-06-28 03:19:44 +02:00
2014-08-13 09:57:55 +02:00
if ( size )
{
// TODO: Use the free space of the computer's HDD where RPCS3 is being run.
size - > hddFreeSizeKB = 40000000 ; // 40 GB
2014-06-28 03:19:44 +02:00
2014-08-13 09:57:55 +02:00
// TODO: Calculate data size for patch data, if necessary.
size - > sizeKB = CELL_GAME_SIZEKB_NOTCALC ;
size - > sysSizeKB = 0 ;
}
2014-06-28 03:19:44 +02:00
2016-08-17 20:59:42 +02:00
psf : : registry sfo = psf : : load_object ( fs : : file ( vfs : : get ( " /app_home/../PARAM.SFO " ) ) ) ;
2016-04-25 12:49:12 +02:00
if ( psf : : get_string ( sfo , " CATEGORY " ) ! = " GD " )
2014-06-28 03:19:44 +02:00
{
return CELL_GAME_ERROR_NOTPATCH ;
}
2016-08-17 20:59:42 +02:00
if ( ! fxm : : make < content_permission > ( Emu . GetTitleID ( ) , std : : move ( sfo ) ) )
2015-08-06 17:55:19 +02:00
{
return CELL_GAME_ERROR_BUSY ;
}
2014-06-28 03:19:44 +02:00
2015-08-06 17:55:19 +02:00
return CELL_OK ;
2013-09-28 04:36:57 +02:00
}
2016-08-16 17:46:24 +02:00
error_code cellGameDataCheck ( u32 type , vm : : cptr < char > dirName , vm : : ptr < CellGameContentSize > size )
2013-09-28 04:36:57 +02:00
{
2016-08-11 01:29:59 +02:00
cellGame . warning ( " cellGameDataCheck(type=%d, dirName=%s, size=*0x%x) " , type , dirName , size ) ;
2014-06-28 03:19:44 +02:00
2014-08-05 12:18:22 +02:00
if ( ( type - 1 ) > = 3 )
2014-06-28 03:19:44 +02:00
{
return CELL_GAME_ERROR_PARAM ;
}
2014-08-13 09:57:55 +02:00
if ( size )
{
// TODO: Use the free space of the computer's HDD where RPCS3 is being run.
size - > hddFreeSizeKB = 40000000 ; //40 GB
2014-06-28 03:19:44 +02:00
2014-08-13 09:57:55 +02:00
// TODO: Calculate data size for game data, if necessary.
size - > sizeKB = CELL_GAME_SIZEKB_NOTCALC ;
size - > sysSizeKB = 0 ;
}
2014-06-28 03:19:44 +02:00
2016-03-21 20:43:03 +01:00
// TODO: not sure what should be checked there
2016-08-17 20:59:42 +02:00
const auto prm = fxm : : make < content_permission > ( type = = CELL_GAME_GAMETYPE_DISC ? " " : dirName . get_ptr ( ) , psf : : registry { } ) ;
2015-02-12 21:10:25 +01:00
2016-08-17 20:59:42 +02:00
if ( ! prm )
2014-06-28 03:19:44 +02:00
{
2016-08-17 20:59:42 +02:00
return CELL_GAME_ERROR_BUSY ;
2016-03-21 20:43:03 +01:00
}
2015-02-12 21:10:25 +01:00
2016-08-17 20:59:42 +02:00
const std : : string dir = prm - > dir . empty ( ) ? " /dev_bdvd/PS3_GAME " s : " /dev_hdd0/game/ " + prm - > dir ;
if ( ! fs : : is_dir ( vfs : : get ( dir ) ) )
2016-03-21 20:43:03 +01:00
{
2016-08-17 20:59:42 +02:00
cellGame . warning ( " cellGameDataCheck(): directory '%s' not found " , dir ) ;
return not_an_error ( CELL_GAME_RET_NONE ) ;
2014-06-28 03:19:44 +02:00
}
2016-08-17 20:59:42 +02:00
prm - > sfo = psf : : load_object ( fs : : file ( vfs : : get ( dir + " /PARAM.SFO " ) ) ) ;
2016-08-16 17:46:24 +02:00
return CELL_OK ;
2013-09-28 04:36:57 +02:00
}
2016-08-16 17:46:24 +02:00
error_code cellGameContentPermit ( vm : : ptr < char [ CELL_GAME_PATH_MAX ] > contentInfoPath , vm : : ptr < char [ CELL_GAME_PATH_MAX ] > usrdirPath )
2013-09-28 04:36:57 +02:00
{
2016-01-12 22:57:16 +01:00
cellGame . warning ( " cellGameContentPermit(contentInfoPath=*0x%x, usrdirPath=*0x%x) " , contentInfoPath , usrdirPath ) ;
2014-11-19 16:17:29 +01:00
2015-04-20 17:53:31 +02:00
if ( ! contentInfoPath & & ! usrdirPath )
2014-11-19 16:17:29 +01:00
{
return CELL_GAME_ERROR_PARAM ;
}
2015-04-13 16:05:44 +02:00
2016-08-18 12:27:20 +02:00
const auto prm = fxm : : get < content_permission > ( ) ;
2013-12-07 21:56:42 +01:00
2016-04-25 12:49:12 +02:00
if ( ! prm )
2014-06-28 03:19:44 +02:00
{
2014-03-12 23:34:35 +01:00
return CELL_GAME_ERROR_FAILURE ;
2014-06-28 03:19:44 +02:00
}
2014-03-12 23:34:35 +01:00
2016-08-17 20:59:42 +02:00
const std : : string dir = prm - > dir . empty ( ) ? " /dev_bdvd/PS3_GAME " s : " /dev_hdd0/game/ " + prm - > dir ;
2016-04-25 12:49:12 +02:00
if ( prm - > is_temporary )
2015-04-20 17:53:31 +02:00
{
2016-03-21 20:43:03 +01:00
// Make temporary directory persistent
2016-08-17 20:59:42 +02:00
const auto vdir = vfs : : get ( dir ) ;
if ( fs : : exists ( vdir ) )
{
fmt : : throw_exception ( " cellGameContentPermit(): epic fail: directory '%s' already exists " , dir ) ;
}
if ( fs : : rename ( vfs : : get ( " /dev_hdd1/game/ " + prm - > dir ) , vdir ) )
2015-04-20 17:53:31 +02:00
{
2016-08-17 20:59:42 +02:00
cellGame . success ( " cellGameContentPermit(): directory '%s' has been created " , dir ) ;
2015-08-06 17:55:19 +02:00
}
else
{
2016-08-17 20:59:42 +02:00
fmt : : throw_exception ( " cellGameContentPermit(): failed to initialize directory '%s' " , dir ) ;
2015-04-20 17:53:31 +02:00
}
2016-04-25 12:49:12 +02:00
// Create PARAM.SFO
2016-08-17 20:59:42 +02:00
psf : : save_object ( fs : : file ( vdir + " /PARAM.SFO " , fs : : rewrite ) , prm - > sfo ) ;
2016-04-25 12:49:12 +02:00
2016-03-21 20:43:03 +01:00
// Disable deletion
2016-04-25 12:49:12 +02:00
prm - > is_temporary = false ;
2015-08-06 17:55:19 +02:00
}
2016-08-17 20:59:42 +02:00
strcpy_trunc ( * contentInfoPath , dir ) ;
strcpy_trunc ( * usrdirPath , dir + " /USRDIR " ) ;
2016-08-18 12:27:20 +02:00
verify ( HERE ) , fxm : : remove < content_permission > ( ) ;
2014-06-28 03:19:44 +02:00
2015-08-06 17:55:19 +02:00
return CELL_OK ;
2014-06-28 03:19:44 +02:00
}
2016-08-16 17:46:24 +02:00
error_code cellGameDataCheckCreate2 ( ppu_thread & ppu , u32 version , vm : : cptr < char > dirName , u32 errDialog , vm : : ptr < CellGameDataStatCallback > funcStat , u32 container )
2014-06-28 03:19:44 +02:00
{
2016-08-11 01:29:59 +02:00
cellGame . error ( " cellGameDataCheckCreate2(version=0x%x, dirName=%s, errDialog=0x%x, funcStat=*0x%x, container=%d) " , version , dirName , errDialog , funcStat , container ) ;
2014-07-01 00:53:29 +02:00
2017-03-11 09:59:50 +01:00
//older sdk. it might not care about game type.
2014-08-05 12:18:22 +02:00
if ( version ! = CELL_GAMEDATA_VERSION_CURRENT | | errDialog > 1 )
2014-07-01 00:53:29 +02:00
{
return CELL_GAMEDATA_ERROR_PARAM ;
}
// TODO: output errors (errDialog)
2016-03-21 20:43:03 +01:00
const std : : string & dir = " /dev_hdd0/game/ " s + dirName . get_ptr ( ) ;
2014-07-01 00:53:29 +02:00
2015-09-26 22:46:04 +02:00
vm : : var < CellGameDataCBResult > cbResult ;
vm : : var < CellGameDataStatGet > cbGet ;
vm : : var < CellGameDataStatSet > cbSet ;
2017-03-11 09:59:50 +01:00
cbGet - > isNewData = fs : : is_dir ( vfs : : get ( dir ) ) ? CELL_GAMEDATA_ISNEWDATA_NO : CELL_GAMEDATA_ISNEWDATA_YES ;
2014-07-01 00:53:29 +02:00
// TODO: Use the free space of the computer's HDD where RPCS3 is being run.
cbGet - > hddFreeSizeKB = 40000000 ; //40 GB
2017-03-11 09:59:50 +01:00
2014-07-01 17:34:25 +02:00
strcpy_trunc ( cbGet - > contentInfoPath , dir ) ;
strcpy_trunc ( cbGet - > gameDataPath , dir + " /USRDIR " ) ;
2014-07-01 00:53:29 +02:00
// TODO: set correct time
2014-07-01 17:34:25 +02:00
cbGet - > st_atime_ = 0 ;
cbGet - > st_ctime_ = 0 ;
cbGet - > st_mtime_ = 0 ;
2014-07-01 00:53:29 +02:00
// TODO: calculate data size, if necessary
cbGet - > sizeKB = CELL_GAMEDATA_SIZEKB_NOTCALC ;
cbGet - > sysSizeKB = 0 ;
2016-08-17 20:59:42 +02:00
psf : : registry sfo = psf : : load_object ( fs : : file ( vfs : : get ( " /app_home/../PARAM.SFO " ) ) ) ;
2016-04-25 12:49:12 +02:00
2014-07-01 00:53:29 +02:00
cbGet - > getParam . attribute = CELL_GAMEDATA_ATTR_NORMAL ;
2016-04-25 12:49:12 +02:00
cbGet - > getParam . parentalLevel = psf : : get_integer ( sfo , " PARENTAL_LEVEL " , 0 ) ;
strcpy_trunc ( cbGet - > getParam . dataVersion , psf : : get_string ( sfo , " APP_VER " , " " ) ) ;
strcpy_trunc ( cbGet - > getParam . titleId , psf : : get_string ( sfo , " TITLE_ID " , " " ) ) ;
strcpy_trunc ( cbGet - > getParam . title , psf : : get_string ( sfo , " TITLE " , " " ) ) ;
2017-03-11 09:59:50 +01:00
for ( u32 i = 0 ; i < CELL_HDDGAME_SYSP_LANGUAGE_NUM ; i + + )
2014-07-01 00:53:29 +02:00
{
2017-03-11 09:59:50 +01:00
strcpy_trunc ( cbGet - > getParam . titleLang [ i ] , psf : : get_string ( sfo , fmt : : format ( " TITLE_%02d " , i ) ) ) ;
2014-07-01 00:53:29 +02:00
}
2017-03-11 09:59:50 +01:00
funcStat ( ppu , cbResult , cbGet , cbSet ) ;
2014-07-01 20:42:05 +02:00
switch ( ( s32 ) cbResult - > result )
2014-07-01 00:53:29 +02:00
{
2014-07-01 19:50:57 +02:00
case CELL_GAMEDATA_CBRESULT_OK_CANCEL :
2017-03-11 09:59:50 +01:00
// TODO: do not process game data(directory)
2016-01-12 22:57:16 +01:00
cellGame . warning ( " cellGameDataCheckCreate2(): callback returned CELL_GAMEDATA_CBRESULT_OK_CANCEL " ) ;
2017-03-11 09:59:50 +01:00
return CELL_OK ;
2014-07-01 00:53:29 +02:00
2017-03-11 09:59:50 +01:00
case CELL_GAMEDATA_CBRESULT_OK :
//game confirmed that it wants to create directory
if ( ! fs : : is_dir ( vfs : : get ( dir + " /USRDIR " ) ) & & ! fs : : create_path ( vfs : : get ( dir + " /USRDIR " ) ) )
{
cellGame . error ( " cellGameDataCheckCreate2(): folder creation failed " ) ;
return CELL_GAME_ERROR_NOSPACE ; //don't know which error. picked one at random
}
if ( cbSet - > setParam )
{
const auto vdir = vfs : : get ( dir ) ;
//older SDK does not define not settable values, hopefully it doesn't just change some values(overwrite)
psf : : registry sfo_write =
{
{ " TITLE_ID " , psf : : string ( CELL_GAME_SYSP_TITLEID_SIZE , cbSet - > setParam - > titleId ) } ,
{ " TITLE " , psf : : string ( CELL_GAME_SYSP_TITLE_SIZE , cbSet - > setParam - > title ) } ,
{ " VERSION " , psf : : string ( CELL_GAME_SYSP_VERSION_SIZE , cbSet - > setParam - > dataVersion ) } ,
{ " PARENTAL_LEVEL " , cbSet - > setParam - > parentalLevel . value ( ) }
} ;
//sfo_write.emplace("PARENTAL_LEVEL", cbSet->setParam->parentalLevel.value()); // I don't care about age restrictions.
for ( u32 i = 0 ; i < CELL_HDDGAME_SYSP_LANGUAGE_NUM ; i + + )
{
sfo_write . emplace ( fmt : : format ( " TITLE_%02d " , i ) , psf : : string ( CELL_GAME_SYSP_TITLE_SIZE , cbSet - > setParam - > titleLang [ i ] ) ) ;
}
if ( ! fs : : is_dir ( vdir ) )
{
cellGame . fatal ( " directory where param.sfo is to be created does not exist " ) ;
return CELL_GAME_ERROR_INTERNAL ;
}
psf : : save_object ( fs : : file ( vdir + " /PARAM.SFO " , fs : : rewrite ) , sfo_write ) ;
}
2016-08-16 17:46:24 +02:00
return CELL_OK ;
2014-07-01 00:53:29 +02:00
2014-07-01 19:50:57 +02:00
case CELL_GAMEDATA_CBRESULT_ERR_NOSPACE : // TODO: process errors, error message and needSizeKB result
2016-01-12 22:57:16 +01:00
cellGame . error ( " cellGameDataCheckCreate2(): callback returned CELL_GAMEDATA_CBRESULT_ERR_NOSPACE " ) ;
2014-07-01 00:53:29 +02:00
return CELL_GAMEDATA_ERROR_CBRESULT ;
2014-07-01 19:50:57 +02:00
case CELL_GAMEDATA_CBRESULT_ERR_BROKEN :
2016-01-12 22:57:16 +01:00
cellGame . error ( " cellGameDataCheckCreate2(): callback returned CELL_GAMEDATA_CBRESULT_ERR_BROKEN " ) ;
2014-07-01 00:53:29 +02:00
return CELL_GAMEDATA_ERROR_CBRESULT ;
2014-07-01 19:50:57 +02:00
case CELL_GAMEDATA_CBRESULT_ERR_NODATA :
2016-01-12 22:57:16 +01:00
cellGame . error ( " cellGameDataCheckCreate2(): callback returned CELL_GAMEDATA_CBRESULT_ERR_NODATA " ) ;
2014-07-01 00:53:29 +02:00
return CELL_GAMEDATA_ERROR_CBRESULT ;
2014-07-01 19:50:57 +02:00
case CELL_GAMEDATA_CBRESULT_ERR_INVALID :
2016-01-12 22:57:16 +01:00
cellGame . error ( " cellGameDataCheckCreate2(): callback returned CELL_GAMEDATA_CBRESULT_ERR_INVALID " ) ;
2014-07-01 00:53:29 +02:00
return CELL_GAMEDATA_ERROR_CBRESULT ;
default :
2016-01-12 22:57:16 +01:00
cellGame . error ( " cellGameDataCheckCreate2(): callback returned unknown error (code=0x%x) " ) ;
2014-07-01 00:53:29 +02:00
return CELL_GAMEDATA_ERROR_CBRESULT ;
}
2013-09-28 04:36:57 +02:00
}
2016-07-27 23:43:22 +02:00
s32 cellGameDataCheckCreate ( ppu_thread & ppu , u32 version , vm : : cptr < char > dirName , u32 errDialog , vm : : ptr < CellGameDataStatCallback > funcStat , u32 container )
2014-06-28 03:19:44 +02:00
{
2016-08-11 01:29:59 +02:00
cellGame . warning ( " cellGameDataCheckCreate(version=0x%x, dirName=%s, errDialog=0x%x, funcStat=*0x%x, container=%d) " , version , dirName , errDialog , funcStat , container ) ;
2015-04-13 16:05:44 +02:00
2014-07-01 00:53:29 +02:00
// TODO: almost identical, the only difference is that this function will always calculate the size of game data
2015-08-13 15:28:42 +02:00
return cellGameDataCheckCreate2 ( ppu , version , dirName , errDialog , funcStat , container ) ;
2014-06-28 03:19:44 +02:00
}
2016-08-16 17:46:24 +02:00
error_code cellGameCreateGameData ( vm : : ptr < CellGameSetInitParams > init , vm : : ptr < char [ CELL_GAME_PATH_MAX ] > tmp_contentInfoPath , vm : : ptr < char [ CELL_GAME_PATH_MAX ] > tmp_usrdirPath )
2013-09-28 04:36:57 +02:00
{
2016-01-12 22:57:16 +01:00
cellGame . error ( " cellGameCreateGameData(init=*0x%x, tmp_contentInfoPath=*0x%x, tmp_usrdirPath=*0x%x) " , init , tmp_contentInfoPath , tmp_usrdirPath ) ;
2015-04-13 16:05:44 +02:00
2016-08-17 20:59:42 +02:00
const auto prm = fxm : : get < content_permission > ( ) ;
if ( ! prm | | prm - > dir . empty ( ) )
{
return CELL_GAME_ERROR_FAILURE ;
}
2016-04-25 12:49:12 +02:00
2016-08-17 20:59:42 +02:00
std : : string tmp_contentInfo = " /dev_hdd1/game/ " + prm - > dir ;
std : : string tmp_usrdir = " /dev_hdd1/game/ " + prm - > dir + " /USRDIR " ;
2015-04-13 16:05:44 +02:00
2016-03-21 20:43:03 +01:00
if ( ! fs : : create_dir ( vfs : : get ( tmp_contentInfo ) ) )
2015-04-13 16:05:44 +02:00
{
2016-08-17 20:59:42 +02:00
cellGame . error ( " cellGameCreateGameData(): failed to create directory '%s' " , tmp_contentInfo ) ;
2015-04-13 16:05:44 +02:00
return CELL_GAME_ERROR_ACCESS_ERROR ; // ???
}
2016-03-21 20:43:03 +01:00
if ( ! fs : : create_dir ( vfs : : get ( tmp_usrdir ) ) )
2015-04-13 16:05:44 +02:00
{
2016-08-17 20:59:42 +02:00
cellGame . error ( " cellGameCreateGameData(): failed to create directory '%s' " , tmp_usrdir ) ;
2015-04-13 16:05:44 +02:00
return CELL_GAME_ERROR_ACCESS_ERROR ; // ???
}
2014-06-29 05:21:57 +02:00
2016-08-17 20:59:42 +02:00
// cellGameContentPermit should then move files in non-temporary location and return their non-temporary displacement
strcpy_trunc ( * tmp_contentInfoPath , tmp_contentInfo ) ;
strcpy_trunc ( * tmp_usrdirPath , tmp_usrdir ) ;
cellGame . success ( " cellGameCreateGameData(): temporary directory '%s' has been created " , tmp_contentInfo ) ;
prm - > is_temporary = true ;
// Initial PARAM.SFO parameters (overwrite)
prm - > sfo =
2016-04-25 12:49:12 +02:00
{
2016-08-17 20:59:42 +02:00
{ " CATEGORY " , psf : : string ( 3 , " GD " ) } ,
2016-04-25 12:49:12 +02:00
{ " TITLE_ID " , psf : : string ( CELL_GAME_SYSP_TITLEID_SIZE , init - > titleId ) } ,
{ " TITLE " , psf : : string ( CELL_GAME_SYSP_TITLE_SIZE , init - > title ) } ,
{ " VERSION " , psf : : string ( CELL_GAME_SYSP_VERSION_SIZE , init - > version ) } ,
} ;
2013-09-28 04:36:57 +02:00
return CELL_OK ;
}
2015-04-13 16:05:44 +02:00
s32 cellGameDeleteGameData ( )
2013-09-28 04:36:57 +02:00
{
UNIMPLEMENTED_FUNC ( cellGame ) ;
return CELL_OK ;
}
2016-08-16 17:46:24 +02:00
error_code cellGameGetParamInt ( s32 id , vm : : ptr < s32 > value )
2013-09-28 04:36:57 +02:00
{
2016-01-12 22:57:16 +01:00
cellGame . warning ( " cellGameGetParamInt(id=%d, value=*0x%x) " , id , value ) ;
2013-11-23 05:47:19 +01:00
2016-04-25 12:49:12 +02:00
const auto prm = fxm : : get < content_permission > ( ) ;
if ( ! prm )
{
return CELL_GAME_ERROR_FAILURE ;
}
2016-01-07 23:12:33 +01:00
std : : string key ;
2013-11-23 05:47:19 +01:00
switch ( id )
2013-11-24 01:01:57 +01:00
{
2016-01-07 23:12:33 +01:00
case CELL_GAME_PARAMID_PARENTAL_LEVEL : key = " PARENTAL_LEVEL " ; break ;
case CELL_GAME_PARAMID_RESOLUTION : key = " RESOLUTION " ; break ;
case CELL_GAME_PARAMID_SOUND_FORMAT : key = " SOUND_FORMAT " ; break ;
2013-11-23 05:47:19 +01:00
default :
2016-04-25 12:49:12 +02:00
{
2013-11-23 05:47:19 +01:00
return CELL_GAME_ERROR_INVALID_ID ;
}
2016-04-25 12:49:12 +02:00
}
2013-11-23 05:47:19 +01:00
2016-04-25 12:49:12 +02:00
* value = psf : : get_integer ( prm - > sfo , key , 0 ) ;
2013-09-28 04:36:57 +02:00
return CELL_OK ;
}
2016-04-25 12:49:12 +02:00
static const char * get_param_string_key ( s32 id )
{
switch ( id )
{
case CELL_GAME_PARAMID_TITLE : return " TITLE " ; // TODO: Is this value correct?
case CELL_GAME_PARAMID_TITLE_DEFAULT : return " TITLE " ;
case CELL_GAME_PARAMID_TITLE_JAPANESE : return " TITLE_00 " ;
case CELL_GAME_PARAMID_TITLE_ENGLISH : return " TITLE_01 " ;
case CELL_GAME_PARAMID_TITLE_FRENCH : return " TITLE_02 " ;
case CELL_GAME_PARAMID_TITLE_SPANISH : return " TITLE_03 " ;
case CELL_GAME_PARAMID_TITLE_GERMAN : return " TITLE_04 " ;
case CELL_GAME_PARAMID_TITLE_ITALIAN : return " TITLE_05 " ;
case CELL_GAME_PARAMID_TITLE_DUTCH : return " TITLE_06 " ;
case CELL_GAME_PARAMID_TITLE_PORTUGUESE : return " TITLE_07 " ;
case CELL_GAME_PARAMID_TITLE_RUSSIAN : return " TITLE_08 " ;
case CELL_GAME_PARAMID_TITLE_KOREAN : return " TITLE_09 " ;
case CELL_GAME_PARAMID_TITLE_CHINESE_T : return " TITLE_10 " ;
case CELL_GAME_PARAMID_TITLE_CHINESE_S : return " TITLE_11 " ;
case CELL_GAME_PARAMID_TITLE_FINNISH : return " TITLE_12 " ;
case CELL_GAME_PARAMID_TITLE_SWEDISH : return " TITLE_13 " ;
case CELL_GAME_PARAMID_TITLE_DANISH : return " TITLE_14 " ;
case CELL_GAME_PARAMID_TITLE_NORWEGIAN : return " TITLE_15 " ;
case CELL_GAME_PARAMID_TITLE_POLISH : return " TITLE_16 " ;
case CELL_GAME_PARAMID_TITLE_PORTUGUESE_BRAZIL : return " TITLE_17 " ;
case CELL_GAME_PARAMID_TITLE_ENGLISH_UK : return " TITLE_18 " ;
2017-03-07 16:18:45 +01:00
case CELL_GAME_PARAMID_TITLE_TURKISH : return " TITLE_19 " ;
2016-04-25 12:49:12 +02:00
case CELL_GAME_PARAMID_TITLE_ID : return " TITLE_ID " ;
case CELL_GAME_PARAMID_VERSION : return " VERSION " ;
case CELL_GAME_PARAMID_PS3_SYSTEM_VER : return " PS3_SYSTEM_VER " ;
case CELL_GAME_PARAMID_APP_VER : return " APP_VER " ;
}
return nullptr ;
}
2016-08-16 17:46:24 +02:00
error_code cellGameGetParamString ( s32 id , vm : : ptr < char > buf , u32 bufsize )
2013-11-23 05:47:19 +01:00
{
2016-01-12 22:57:16 +01:00
cellGame . warning ( " cellGameGetParamString(id=%d, buf=*0x%x, bufsize=%d) " , id , buf , bufsize ) ;
2013-11-23 05:47:19 +01:00
2016-04-25 12:49:12 +02:00
const auto prm = fxm : : get < content_permission > ( ) ;
2016-03-21 20:43:03 +01:00
2016-04-25 12:49:12 +02:00
if ( ! prm )
2013-11-23 05:47:19 +01:00
{
2016-04-25 12:49:12 +02:00
return CELL_GAME_ERROR_FAILURE ;
}
2013-11-23 05:47:19 +01:00
2016-04-25 12:49:12 +02:00
const auto key = get_param_string_key ( id ) ;
if ( ! key )
{
2013-11-23 05:47:19 +01:00
return CELL_GAME_ERROR_INVALID_ID ;
}
2016-08-17 20:59:42 +02:00
std : : string value = psf : : get_string ( prm - > sfo , key ) ;
2016-04-25 12:49:12 +02:00
value . resize ( bufsize - 1 ) ;
2016-01-07 23:12:33 +01:00
2016-05-13 15:55:34 +02:00
std : : memcpy ( buf . get_ptr ( ) , value . c_str ( ) , bufsize ) ;
2016-01-07 23:12:33 +01:00
2013-09-28 04:36:57 +02:00
return CELL_OK ;
}
2016-08-16 17:46:24 +02:00
error_code cellGameSetParamString ( s32 id , vm : : cptr < char > buf )
2013-09-28 04:36:57 +02:00
{
2016-04-25 12:49:12 +02:00
cellGame . warning ( " cellGameSetParamString(id=%d, buf=*0x%x) " , id , buf ) ;
const auto prm = fxm : : get < content_permission > ( ) ;
if ( ! prm )
{
return CELL_GAME_ERROR_FAILURE ;
}
const auto key = get_param_string_key ( id ) ;
if ( ! key )
{
return CELL_GAME_ERROR_INVALID_ID ;
}
u32 max_size = CELL_GAME_SYSP_TITLE_SIZE ;
switch ( id )
{
case CELL_GAME_PARAMID_TITLE_ID : max_size = CELL_GAME_SYSP_TITLEID_SIZE ; break ;
case CELL_GAME_PARAMID_VERSION : max_size = CELL_GAME_SYSP_VERSION_SIZE ; break ;
case CELL_GAME_PARAMID_PS3_SYSTEM_VER : max_size = CELL_GAME_SYSP_PS3_SYSTEM_VER_SIZE ; break ;
case CELL_GAME_PARAMID_APP_VER : max_size = CELL_GAME_SYSP_APP_VER_SIZE ; break ;
}
prm - > sfo . emplace ( key , psf : : string ( max_size , buf . get_ptr ( ) ) ) ;
2013-09-28 04:36:57 +02:00
return CELL_OK ;
}
2017-02-05 14:07:26 +01:00
s32 cellGameGetSizeKB ( vm : : ptr < s32 > size )
2013-09-28 04:36:57 +02:00
{
2017-03-22 11:09:10 +01:00
cellGame . warning ( " cellGameGetSizeKB(size=*0x%x) " , size ) ;
const auto prm = fxm : : get < content_permission > ( ) ;
if ( ! prm )
{
return CELL_GAME_ERROR_FAILURE ;
}
const std : : string & local_dir = prm - > is_temporary ? vfs : : get ( " /dev_hdd1/game/ " s + prm - > dir ) : vfs : : get ( " /dev_hdd0/game/ " s + prm - > dir ) ; //should we check the temporary folder?
if ( ! fs : : is_dir ( local_dir ) )
{
return CELL_GAME_ERROR_FAILURE ;
}
2017-03-26 00:16:47 +01:00
* size = ( u32 ) ( fs : : get_dir_size ( local_dir ) / 1024 ) ;
2017-02-05 14:07:26 +01:00
2013-09-28 04:36:57 +02:00
return CELL_OK ;
}
2015-04-13 16:05:44 +02:00
s32 cellGameGetDiscContentInfoUpdatePath ( )
2013-09-28 04:36:57 +02:00
{
UNIMPLEMENTED_FUNC ( cellGame ) ;
return CELL_OK ;
}
2015-04-13 16:05:44 +02:00
s32 cellGameGetLocalWebContentPath ( )
2013-09-28 04:36:57 +02:00
{
UNIMPLEMENTED_FUNC ( cellGame ) ;
return CELL_OK ;
}
2016-08-16 17:46:24 +02:00
error_code cellGameContentErrorDialog ( s32 type , s32 errNeedSizeKB , vm : : cptr < char > dirName )
2013-09-28 04:36:57 +02:00
{
2016-08-11 01:29:59 +02:00
cellGame . warning ( " cellGameContentErrorDialog(type=%d, errNeedSizeKB=%d, dirName=%s) " , type , errNeedSizeKB , dirName ) ;
2014-08-12 22:27:13 +02:00
2014-09-05 19:23:00 +02:00
std : : string errorName ;
2014-08-12 22:27:13 +02:00
switch ( type )
{
case CELL_GAME_ERRDIALOG_BROKEN_GAMEDATA : errorName = " Game data is corrupted (can be continued). " ; break ;
case CELL_GAME_ERRDIALOG_BROKEN_HDDGAME : errorName = " HDD boot game is corrupted (can be continued). " ; break ;
case CELL_GAME_ERRDIALOG_NOSPACE : errorName = " Not enough available space (can be continued). " ; break ;
case CELL_GAME_ERRDIALOG_BROKEN_EXIT_GAMEDATA : errorName = " Game data is corrupted (terminate application). " ; break ;
case CELL_GAME_ERRDIALOG_BROKEN_EXIT_HDDGAME : errorName = " HDD boot game is corrupted (terminate application). " ; break ;
case CELL_GAME_ERRDIALOG_NOSPACE_EXIT : errorName = " Not enough available space (terminate application). " ; break ;
default : return CELL_GAME_ERROR_PARAM ;
}
2014-09-05 19:23:00 +02:00
std : : string errorMsg ;
2014-08-13 08:39:45 +02:00
if ( type = = CELL_GAME_ERRDIALOG_NOSPACE | | type = = CELL_GAME_ERRDIALOG_NOSPACE_EXIT )
2014-08-12 22:27:13 +02:00
{
2015-01-18 23:54:56 +01:00
errorMsg = fmt : : format ( " ERROR: %s \n Space needed: %d KB " , errorName , errNeedSizeKB ) ;
2014-08-12 22:27:13 +02:00
}
else
2014-02-11 03:47:25 +01:00
{
2015-01-18 23:54:56 +01:00
errorMsg = fmt : : format ( " ERROR: %s " , errorName ) ;
2014-02-11 03:47:25 +01:00
}
2014-09-05 19:23:00 +02:00
if ( dirName )
{
2016-08-11 01:29:59 +02:00
errorMsg + = fmt : : format ( " \n Directory name: %s " , dirName ) ;
2014-09-05 19:23:00 +02:00
}
2015-12-19 12:40:52 +01:00
const auto dlg = Emu . GetCallbacks ( ) . get_msg_dialog ( ) ;
dlg - > type . bg_invisible = true ;
dlg - > type . button_type = 2 ; // OK
dlg - > type . disable_cancel = true ;
2016-04-25 12:49:12 +02:00
atomic_t < bool > result ( false ) ;
2015-12-19 12:40:52 +01:00
2016-04-25 12:49:12 +02:00
dlg - > on_close = [ & ] ( s32 status )
2015-12-19 12:40:52 +01:00
{
2016-04-25 12:49:12 +02:00
result = true ;
2015-12-19 12:40:52 +01:00
} ;
2017-04-26 05:05:48 +02:00
Emu . CallAfter ( [ & ] ( )
{
dlg - > Create ( errorMsg ) ;
} ) ;
2015-12-19 12:40:52 +01:00
2016-04-25 12:49:12 +02:00
while ( ! result )
{
2017-02-05 15:06:03 +01:00
thread_ctrl : : wait_for ( 1000 ) ;
2016-04-25 12:49:12 +02:00
}
2014-08-12 22:27:13 +02:00
2013-09-28 04:36:57 +02:00
return CELL_OK ;
}
2015-04-13 16:05:44 +02:00
s32 cellGameThemeInstall ( )
2013-09-28 04:36:57 +02:00
{
UNIMPLEMENTED_FUNC ( cellGame ) ;
return CELL_OK ;
}
2015-04-13 16:05:44 +02:00
s32 cellGameThemeInstallFromBuffer ( )
2013-09-28 04:36:57 +02:00
{
UNIMPLEMENTED_FUNC ( cellGame ) ;
return CELL_OK ;
}
2015-08-01 18:14:49 +02:00
2017-02-15 09:49:18 +01:00
s32 cellDiscGameGetBootDiscInfo ( vm : : ptr < CellDiscGameSystemFileParam > getParam )
2015-08-01 18:14:49 +02:00
{
2017-02-15 09:49:18 +01:00
cellGame . warning ( " cellDiscGameGetBootDiscInfo(getParam=*0x%x) " , getParam ) ;
2017-02-28 16:42:45 +01:00
// This is also called by non-disc games, see NPUB90029
2017-02-15 09:49:18 +01:00
const std : : string dir = " /dev_bdvd/PS3_GAME " s ;
if ( ! fs : : is_dir ( vfs : : get ( dir ) ) )
{
2017-02-28 16:42:45 +01:00
// Not a disc game. TODO: Fetch PARAM.SFO from proper game dir
2017-02-15 09:49:18 +01:00
cellGame . warning ( " cellDiscGameGetBootDiscInfo(): directory '%s' not found " , dir ) ;
2017-02-28 16:42:45 +01:00
getParam - > parentalLevel = 0 ;
strcpy_trunc ( getParam - > titleId , " 0 " ) ;
return CELL_OK ;
2017-02-15 09:49:18 +01:00
}
2017-02-28 16:42:45 +01:00
2017-02-15 09:49:18 +01:00
const auto & psf = psf : : load_object ( fs : : file ( vfs : : get ( dir + " /PARAM.SFO " ) ) ) ;
if ( psf . count ( " PARENTAL_LEVEL " ) ! = 0 ) getParam - > parentalLevel = psf . at ( " PARENTAL_LEVEL " ) . as_integer ( ) ;
if ( psf . count ( " TITLE_ID " ) ! = 0 ) strcpy_trunc ( getParam - > titleId , psf . at ( " TITLE_ID " ) . as_string ( ) ) ;
2016-06-25 21:39:41 +02:00
return CELL_OK ;
2015-08-01 18:14:49 +02:00
}
s32 cellDiscGameRegisterDiscChangeCallback ( )
{
2016-06-25 21:39:41 +02:00
UNIMPLEMENTED_FUNC ( cellGame ) ;
return CELL_OK ;
2015-08-01 18:14:49 +02:00
}
s32 cellDiscGameUnregisterDiscChangeCallback ( )
{
2016-06-25 21:39:41 +02:00
UNIMPLEMENTED_FUNC ( cellGame ) ;
return CELL_OK ;
2015-08-01 18:14:49 +02:00
}
s32 cellGameRegisterDiscChangeCallback ( )
{
2016-06-25 21:39:41 +02:00
UNIMPLEMENTED_FUNC ( cellGame ) ;
return CELL_OK ;
2015-08-01 18:14:49 +02:00
}
s32 cellGameUnregisterDiscChangeCallback ( )
{
2016-06-25 21:39:41 +02:00
UNIMPLEMENTED_FUNC ( cellGame ) ;
return CELL_OK ;
2015-08-01 18:14:49 +02:00
}
void cellSysutil_GameData_init ( )
{
REG_FUNC ( cellSysutil , cellHddGameCheck ) ;
REG_FUNC ( cellSysutil , cellHddGameCheck2 ) ;
REG_FUNC ( cellSysutil , cellHddGameGetSizeKB ) ;
REG_FUNC ( cellSysutil , cellHddGameSetSystemVer ) ;
REG_FUNC ( cellSysutil , cellHddGameExitBroken ) ;
REG_FUNC ( cellSysutil , cellGameDataGetSizeKB ) ;
REG_FUNC ( cellSysutil , cellGameDataSetSystemVer ) ;
REG_FUNC ( cellSysutil , cellGameDataExitBroken ) ;
REG_FUNC ( cellSysutil , cellGameDataCheckCreate ) ;
REG_FUNC ( cellSysutil , cellGameDataCheckCreate2 ) ;
REG_FUNC ( cellSysutil , cellDiscGameGetBootDiscInfo ) ;
REG_FUNC ( cellSysutil , cellDiscGameRegisterDiscChangeCallback ) ;
REG_FUNC ( cellSysutil , cellDiscGameUnregisterDiscChangeCallback ) ;
REG_FUNC ( cellSysutil , cellGameRegisterDiscChangeCallback ) ;
REG_FUNC ( cellSysutil , cellGameUnregisterDiscChangeCallback ) ;
}
2016-03-21 20:43:03 +01:00
DECLARE ( ppu_module_manager : : cellGame ) ( " cellGame " , [ ] ( )
2013-09-28 04:36:57 +02:00
{
2015-02-20 14:58:40 +01:00
REG_FUNC ( cellGame , cellGameBootCheck ) ;
REG_FUNC ( cellGame , cellGamePatchCheck ) ;
REG_FUNC ( cellGame , cellGameDataCheck ) ;
REG_FUNC ( cellGame , cellGameContentPermit ) ;
2013-09-28 04:36:57 +02:00
2015-02-20 14:58:40 +01:00
REG_FUNC ( cellGame , cellGameCreateGameData ) ;
REG_FUNC ( cellGame , cellGameDeleteGameData ) ;
2013-09-28 04:36:57 +02:00
2015-02-20 14:58:40 +01:00
REG_FUNC ( cellGame , cellGameGetParamInt ) ;
REG_FUNC ( cellGame , cellGameGetParamString ) ;
REG_FUNC ( cellGame , cellGameSetParamString ) ;
REG_FUNC ( cellGame , cellGameGetSizeKB ) ;
REG_FUNC ( cellGame , cellGameGetDiscContentInfoUpdatePath ) ;
REG_FUNC ( cellGame , cellGameGetLocalWebContentPath ) ;
2013-09-28 04:36:57 +02:00
2015-02-20 14:58:40 +01:00
REG_FUNC ( cellGame , cellGameContentErrorDialog ) ;
2013-09-28 04:36:57 +02:00
2015-02-20 14:58:40 +01:00
REG_FUNC ( cellGame , cellGameThemeInstall ) ;
REG_FUNC ( cellGame , cellGameThemeInstallFromBuffer ) ;
2015-02-18 17:22:06 +01:00
} ) ;