2020-12-05 13:08:24 +01:00
# include "stdafx.h"
2022-07-12 21:28:55 +02:00
# include "Emu/System.h"
2017-03-25 15:25:24 +01:00
# include "Emu/Cell/PPUModule.h"
2022-07-12 21:28:55 +02:00
# include "Emu/IdManager.h"
# include "Emu/localized_string.h"
2018-02-02 16:47:46 +01:00
# include "cellSysutil.h"
2019-11-17 00:22:56 +01:00
# include "cellCrossController.h"
2022-07-12 21:28:55 +02:00
# include "cellMsgDialog.h"
2018-02-09 15:49:37 +01:00
2017-07-21 17:41:11 +02:00
2018-08-25 14:39:00 +02:00
LOG_CHANNEL ( cellCrossController ) ;
2017-03-25 15:25:24 +01:00
2019-11-17 00:22:56 +01:00
template < >
void fmt_class_string < CellCrossControllerError > : : format ( std : : string & out , u64 arg )
2018-02-02 16:47:46 +01:00
{
2019-11-17 00:22:56 +01:00
format_enum ( out , arg , [ ] ( CellCrossControllerError value )
{
switch ( value )
{
STR_CASE ( CELL_CROSS_CONTROLLER_ERROR_CANCEL ) ;
STR_CASE ( CELL_CROSS_CONTROLLER_ERROR_NETWORK ) ;
STR_CASE ( CELL_CROSS_CONTROLLER_ERROR_OUT_OF_MEMORY ) ;
STR_CASE ( CELL_CROSS_CONTROLLER_ERROR_FATAL ) ;
STR_CASE ( CELL_CROSS_CONTROLLER_ERROR_INVALID_PKG_FILENAME ) ;
STR_CASE ( CELL_CROSS_CONTROLLER_ERROR_INVALID_SIG_FILENAME ) ;
STR_CASE ( CELL_CROSS_CONTROLLER_ERROR_INVALID_ICON_FILENAME ) ;
STR_CASE ( CELL_CROSS_CONTROLLER_ERROR_INVALID_VALUE ) ;
STR_CASE ( CELL_CROSS_CONTROLLER_ERROR_PKG_FILE_OPEN ) ;
STR_CASE ( CELL_CROSS_CONTROLLER_ERROR_SIG_FILE_OPEN ) ;
STR_CASE ( CELL_CROSS_CONTROLLER_ERROR_ICON_FILE_OPEN ) ;
STR_CASE ( CELL_CROSS_CONTROLLER_ERROR_INVALID_STATE ) ;
STR_CASE ( CELL_CROSS_CONTROLLER_ERROR_INVALID_PKG_FILE ) ;
STR_CASE ( CELL_CROSS_CONTROLLER_ERROR_INTERNAL ) ;
}
2018-02-02 16:47:46 +01:00
2019-11-17 00:22:56 +01:00
return unknown ;
} ) ;
}
2017-07-21 17:41:11 +02:00
2022-07-12 21:28:55 +02:00
void finish_callback ( ppu_thread & ppu , s32 button_type , vm : : ptr < void > userdata ) ; // Forward declaration
struct cross_controller
{
atomic_t < s32 > status { 0 } ;
std : : unique_ptr < named_thread < std : : function < void ( ) > > > connection_thread ;
vm : : ptr < CellCrossControllerCallback > callback = vm : : null ;
vm : : ptr < void > userdata = vm : : null ;
void on_connection_established ( s32 status )
{
ensure ( ! ! callback ) ;
close_msg_dialog ( ) ;
2022-09-13 15:08:55 +02:00
sysutil_register_cb ( [ this , status ] ( ppu_thread & ppu ) - > s32
2022-07-12 21:28:55 +02:00
{
callback ( ppu , CELL_CROSS_CONTROLLER_STATUS_FINALIZED , status , vm : : null , userdata ) ;
return CELL_OK ;
} ) ;
}
void run_thread ( vm : : cptr < CellCrossControllerPackageInfo > pPkgInfo )
{
ensure ( ! ! pPkgInfo ) ;
ensure ( ! ! callback ) ;
const std : : string msg = fmt : : format ( " %s \n \n %s " ,
get_localized_string ( localized_string_id : : CELL_CROSS_CONTROLLER_MSG , pPkgInfo - > pTitle . get_ptr ( ) ) ,
get_localized_string ( localized_string_id : : CELL_CROSS_CONTROLLER_FW_MSG ) ) ;
vm : : bptr < CellMsgDialogCallback > msg_dialog_callback = vm : : null ;
msg_dialog_callback . set ( g_fxo - > get < ppu_function_manager > ( ) . func_addr ( FIND_FUNC ( finish_callback ) ) ) ;
// TODO: Show icons from comboplay_plugin.rco in dialog. Maybe use a new dialog or add an optional icon to this one.
error_code res = open_msg_dialog ( false , CELL_MSGDIALOG_TYPE_DISABLE_CANCEL_OFF , vm : : make_str ( msg ) , msg_dialog_callback , userdata ) ;
2022-09-13 15:08:55 +02:00
sysutil_register_cb ( [ this , res ] ( ppu_thread & ppu ) - > s32
2022-07-12 21:28:55 +02:00
{
2022-09-13 15:08:55 +02:00
callback ( ppu , CELL_CROSS_CONTROLLER_STATUS_INITIALIZED , res = = CELL_OK ? + CELL_OK : + CELL_CROSS_CONTROLLER_ERROR_INTERNAL , vm : : null , userdata ) ;
2022-07-12 21:28:55 +02:00
return CELL_OK ;
} ) ;
status = CELL_CROSS_CONTROLLER_STATUS_INITIALIZED ;
connection_thread = std : : make_unique < named_thread < std : : function < void ( ) > > > ( fmt : : format ( " Cross-Controller Thread " ) , [ this ] ( )
{
while ( thread_ctrl : : state ( ) ! = thread_state : : aborting )
{
if ( Emu . IsPaused ( ) )
{
thread_ctrl : : wait_for ( 10'000 ) ;
continue ;
}
// TODO: establish connection to PS Vita
if ( false )
{
on_connection_established ( CELL_OK ) ;
}
thread_ctrl : : wait_for ( 1000 ) ;
}
status = CELL_CROSS_CONTROLLER_STATUS_FINALIZED ;
} ) ;
}
void stop_thread ( )
{
if ( connection_thread )
{
auto & thread = * connection_thread ;
thread = thread_state : : aborting ;
thread ( ) ;
connection_thread . reset ( ) ;
}
} ;
} ;
void finish_callback ( ppu_thread & ppu , s32 button_type , vm : : ptr < void > userdata )
{
cross_controller & cc = g_fxo - > get < cross_controller > ( ) ;
// This function should only be called when the user canceled the dialog
ensure ( cc . callback & & button_type = = CELL_MSGDIALOG_BUTTON_ESCAPE ) ;
cc . callback ( ppu , CELL_CROSS_CONTROLLER_STATUS_FINALIZED , CELL_CROSS_CONTROLLER_ERROR_CANCEL , vm : : null , userdata ) ;
cc . stop_thread ( ) ;
}
2019-11-17 00:22:56 +01:00
error_code cellCrossControllerInitialize ( vm : : cptr < CellCrossControllerParam > pParam , vm : : cptr < CellCrossControllerPackageInfo > pPkgInfo , vm : : ptr < CellCrossControllerCallback > cb , vm : : ptr < void > userdata ) // LittleBigPlanet 2 and 3
2017-07-21 17:41:11 +02:00
{
2019-11-17 00:22:56 +01:00
cellCrossController . todo ( " cellCrossControllerInitialize(pParam=*0x%x, pPkgInfo=*0x%x, cb=*0x%x, userdata=*0x%x) " , pParam , pPkgInfo , cb , userdata ) ;
2017-07-21 17:41:11 +02:00
2022-07-12 21:28:55 +02:00
if ( pParam )
{
cellCrossController . notice ( " cellCrossControllerInitialize: pParam: pPackageFileName=%s, pSignatureFileName=%s, pIconFileName=%s " , pParam - > pPackageFileName , pParam - > pSignatureFileName , pParam - > pIconFileName ) ;
}
if ( pPkgInfo )
{
cellCrossController . notice ( " cellCrossControllerInitialize: pPkgInfo: pTitle=%s, pTitleId=%s, pAppVer=%s " , pPkgInfo - > pTitle , pPkgInfo - > pTitleId , pPkgInfo - > pAppVer ) ;
}
cross_controller & cc = g_fxo - > get < cross_controller > ( ) ;
if ( cc . status = = CELL_CROSS_CONTROLLER_STATUS_INITIALIZED ) // TODO: confirm this logic
{
return CELL_CROSS_CONTROLLER_ERROR_INVALID_STATE ;
}
2017-07-21 17:41:11 +02:00
2019-11-17 00:22:56 +01:00
if ( ! pParam | | ! pPkgInfo )
{
return CELL_CROSS_CONTROLLER_ERROR_INVALID_VALUE ;
}
// Check if the strings exceed the allowed size (not counting null terminators)
if ( ! pParam - > pPackageFileName | | ! memchr ( pParam - > pPackageFileName . get_ptr ( ) , ' \0 ' , CELL_CROSS_CONTROLLER_PARAM_FILE_NAME_LEN + 1 ) )
{
return CELL_CROSS_CONTROLLER_ERROR_INVALID_PKG_FILENAME ;
}
if ( ! pParam - > pSignatureFileName | | ! memchr ( pParam - > pSignatureFileName . get_ptr ( ) , ' \0 ' , CELL_CROSS_CONTROLLER_PARAM_FILE_NAME_LEN + 1 ) )
{
return CELL_CROSS_CONTROLLER_ERROR_INVALID_SIG_FILENAME ;
}
if ( ! pParam - > pIconFileName | | ! memchr ( pParam - > pIconFileName . get_ptr ( ) , ' \0 ' , CELL_CROSS_CONTROLLER_PARAM_FILE_NAME_LEN + 1 ) )
{
return CELL_CROSS_CONTROLLER_ERROR_INVALID_ICON_FILENAME ;
}
if ( ! pPkgInfo - > pAppVer | | ! memchr ( pPkgInfo - > pAppVer . get_ptr ( ) , ' \0 ' , CELL_CROSS_CONTROLLER_PKG_APP_VER_LEN + 1 ) | |
! pPkgInfo - > pTitleId | | ! memchr ( pPkgInfo - > pTitleId . get_ptr ( ) , ' \0 ' , CELL_CROSS_CONTROLLER_PKG_TITLE_ID_LEN + 1 ) | |
! pPkgInfo - > pTitle | | ! memchr ( pPkgInfo - > pTitle . get_ptr ( ) , ' \0 ' , CELL_CROSS_CONTROLLER_PKG_TITLE_LEN + 1 ) | |
! cb )
{
return CELL_CROSS_CONTROLLER_ERROR_INVALID_VALUE ;
}
2018-02-02 16:47:46 +01:00
2022-07-12 21:28:55 +02:00
cc . callback = cb ;
cc . userdata = userdata ;
cc . run_thread ( pPkgInfo ) ;
2018-02-02 16:47:46 +01:00
2017-03-25 15:25:24 +01:00
return CELL_OK ;
}
DECLARE ( ppu_module_manager : : cellCrossController ) ( " cellCrossController " , [ ] ( )
{
2017-07-21 17:41:11 +02:00
REG_FUNC ( cellCrossController , cellCrossControllerInitialize ) ;
2022-07-12 21:28:55 +02:00
// Helper Function
REG_HIDDEN_FUNC ( finish_callback ) ;
2017-03-25 15:25:24 +01:00
} ) ;