2020-12-05 13:08:24 +01:00
# include "stdafx.h"
2020-10-30 21:26:22 +01:00
# include "Emu/System.h"
2016-03-21 20:43:03 +01:00
# include "Emu/Cell/PPUModule.h"
2019-04-05 09:56:46 +02:00
# include "Emu/Cell/PPUThread.h"
# include "Emu/Cell/lv2/sys_sync.h"
2021-03-23 20:32:50 +01:00
# include "Emu/Cell/timers.hpp"
2020-10-04 22:46:28 +02:00
# include "Emu/Io/interception.h"
2020-02-25 22:42:29 +01:00
# include "Emu/RSX/Overlays/overlay_message_dialog.h"
2014-07-04 00:52:43 +02:00
# include "cellSysutil.h"
# include "cellMsgDialog.h"
2016-05-13 15:55:34 +02:00
# include <thread>
2019-09-26 20:50:55 +02:00
# include "util/init_mutex.hpp"
2020-01-31 10:01:17 +01:00
LOG_CHANNEL ( cellSysutil ) ;
2014-07-04 00:52:43 +02:00
2019-01-04 14:45:32 +01:00
template < >
void fmt_class_string < CellMsgDialogError > : : format ( std : : string & out , u64 arg )
{
format_enum ( out , arg , [ ] ( auto error )
{
switch ( error )
{
STR_CASE ( CELL_MSGDIALOG_ERROR_PARAM ) ;
STR_CASE ( CELL_MSGDIALOG_ERROR_DIALOG_NOT_OPENED ) ;
}
return unknown ;
} ) ;
}
2017-01-25 00:22:19 +01:00
MsgDialogBase : : ~ MsgDialogBase ( )
{
}
2019-09-26 20:50:55 +02:00
struct msg_info
{
std : : shared_ptr < MsgDialogBase > dlg ;
stx : : init_mutex init ;
// Emulate fxm as if it's some sort of museum
std : : shared_ptr < MsgDialogBase > make ( ) noexcept
{
const auto init_lock = init . init ( ) ;
if ( ! init_lock )
{
return nullptr ;
}
dlg = Emu . GetCallbacks ( ) . get_msg_dialog ( ) ;
return dlg ;
}
std : : shared_ptr < MsgDialogBase > get ( ) noexcept
{
const auto init_lock = init . access ( ) ;
if ( ! init_lock )
{
return nullptr ;
}
return dlg ;
}
void remove ( ) noexcept
{
const auto init_lock = init . reset ( ) ;
if ( ! init_lock )
{
return ;
}
dlg . reset ( ) ;
}
} ;
2020-02-22 12:46:49 +01:00
struct msg_dlg_thread_info
{
atomic_t < u64 > wait_until = 0 ;
void operator ( ) ( )
{
while ( thread_ctrl : : state ( ) ! = thread_state : : aborting )
{
const u64 new_value = wait_until . load ( ) ;
if ( new_value = = 0 )
{
2021-02-13 15:50:07 +01:00
thread_ctrl : : wait_on ( wait_until , 0 ) ;
2020-02-22 12:46:49 +01:00
continue ;
}
while ( get_guest_system_time ( ) < new_value )
{
if ( wait_until . load ( ) ! = new_value )
break ;
2021-02-21 14:43:02 +01:00
thread_ctrl : : wait_for ( 10'000 ) ;
2020-02-22 12:46:49 +01:00
}
2021-02-03 19:14:31 +01:00
if ( auto manager = g_fxo - > try_get < rsx : : overlays : : display_manager > ( ) )
2020-02-22 12:46:49 +01:00
{
if ( auto dlg = manager - > get < rsx : : overlays : : message_dialog > ( ) )
{
if ( ! wait_until . compare_and_swap_test ( new_value , 0 ) )
{
continue ;
}
2020-03-09 23:00:26 +01:00
dlg - > close ( true , true ) ;
2020-02-22 12:46:49 +01:00
}
}
2021-03-02 12:59:19 +01:00
else if ( const auto dlg = g_fxo - > get < msg_info > ( ) . get ( ) )
2020-02-22 12:46:49 +01:00
{
if ( ! wait_until . compare_and_swap_test ( new_value , 0 ) )
{
continue ;
}
dlg - > on_close ( CELL_MSGDIALOG_BUTTON_NONE ) ;
}
}
}
static constexpr auto thread_name = " MsgDialog Close Thread " sv ;
} ;
using msg_dlg_thread = named_thread < msg_dlg_thread_info > ;
2019-07-13 21:48:54 +02:00
// variable used to immediately get the response from auxiliary message dialogs (callbacks would be async)
atomic_t < s32 > g_last_user_response = CELL_MSGDIALOG_BUTTON_NONE ;
2018-06-12 21:33:21 +02:00
// forward declaration for open_msg_dialog
2019-01-04 14:45:32 +01:00
error_code cellMsgDialogOpen2 ( u32 type , vm : : cptr < char > msgString , vm : : ptr < CellMsgDialogCallback > callback , vm : : ptr < void > userData , vm : : ptr < void > extParam ) ;
2018-06-12 21:33:21 +02:00
// wrapper to call for other hle dialogs
2019-01-20 23:46:48 +01:00
error_code open_msg_dialog ( bool is_blocking , u32 type , vm : : cptr < char > msgString , vm : : ptr < CellMsgDialogCallback > callback , vm : : ptr < void > userData , vm : : ptr < void > extParam )
2018-06-12 21:33:21 +02:00
{
2019-01-20 23:46:48 +01:00
cellSysutil . warning ( " open_msg_dialog(is_blocking=%d, type=0x%x, msgString=%s, callback=*0x%x, userData=*0x%x, extParam=*0x%x) " , is_blocking , type , msgString , callback , userData , extParam ) ;
2019-12-29 01:01:54 +01:00
const MsgDialogType _type { type } ;
2019-01-20 23:46:48 +01:00
2021-02-03 19:14:31 +01:00
if ( auto manager = g_fxo - > try_get < rsx : : overlays : : display_manager > ( ) )
2019-01-20 23:46:48 +01:00
{
2019-12-29 01:01:54 +01:00
if ( manager - > get < rsx : : overlays : : message_dialog > ( ) )
{
return CELL_SYSUTIL_ERROR_BUSY ;
}
g_last_user_response = CELL_MSGDIALOG_BUTTON_NONE ;
const auto res = manager - > create < rsx : : overlays : : message_dialog > ( ) - > show ( is_blocking , msgString . get_ptr ( ) , _type , [ callback , userData ] ( s32 status )
2019-01-20 23:46:48 +01:00
{
2019-12-29 01:01:54 +01:00
if ( callback )
2019-01-20 23:46:48 +01:00
{
2019-12-29 01:01:54 +01:00
sysutil_register_cb ( [ = ] ( ppu_thread & ppu ) - > s32
2019-01-20 23:46:48 +01:00
{
2019-12-29 01:01:54 +01:00
callback ( ppu , status , userData ) ;
return CELL_OK ;
} ) ;
2019-01-20 23:46:48 +01:00
}
2019-12-29 01:01:54 +01:00
} ) ;
return res ;
}
2021-03-02 12:59:19 +01:00
const auto dlg = g_fxo - > get < msg_info > ( ) . make ( ) ;
2019-12-29 01:01:54 +01:00
if ( ! dlg )
{
return CELL_SYSUTIL_ERROR_BUSY ;
}
dlg - > type = _type ;
dlg - > on_close = [ callback , userData , wptr = std : : weak_ptr < MsgDialogBase > ( dlg ) ] ( s32 status )
{
const auto dlg = wptr . lock ( ) ;
if ( dlg & & dlg - > state . compare_and_swap_test ( MsgDialogState : : Open , MsgDialogState : : Close ) )
2019-01-20 23:46:48 +01:00
{
2019-12-29 01:01:54 +01:00
if ( callback )
2019-01-20 23:46:48 +01:00
{
2019-12-29 01:01:54 +01:00
sysutil_register_cb ( [ = ] ( ppu_thread & ppu ) - > s32
2019-01-20 23:46:48 +01:00
{
2019-12-29 01:01:54 +01:00
callback ( ppu , status , userData ) ;
return CELL_OK ;
} ) ;
2019-01-20 23:46:48 +01:00
}
2019-12-29 01:01:54 +01:00
2021-03-02 12:59:19 +01:00
g_fxo - > get < msg_dlg_thread > ( ) . wait_until = 0 ;
g_fxo - > get < msg_info > ( ) . remove ( ) ;
2019-12-29 01:01:54 +01:00
}
2020-10-04 22:46:28 +02:00
input : : SetIntercepted ( false ) ;
2019-12-29 01:01:54 +01:00
} ;
2020-10-04 22:46:28 +02:00
input : : SetIntercepted ( true ) ;
2019-12-29 01:01:54 +01:00
auto & ppu = * get_current_cpu_thread ( ) ;
lv2_obj : : sleep ( ppu ) ;
// Run asynchronously in GUI thread
Emu . CallAfter ( [ & ] ( )
{
g_last_user_response = CELL_MSGDIALOG_BUTTON_NONE ;
dlg - > Create ( msgString . get_ptr ( ) ) ;
lv2_obj : : awake ( & ppu ) ;
} ) ;
2021-02-13 15:50:07 +01:00
while ( auto state = ppu . state . fetch_sub ( cpu_flag : : signal ) )
2019-12-29 01:01:54 +01:00
{
2021-02-13 15:50:07 +01:00
if ( is_stopped ( state ) )
2019-12-29 01:01:54 +01:00
{
2021-02-13 15:50:07 +01:00
return { } ;
2019-12-29 01:01:54 +01:00
}
2021-02-13 15:50:07 +01:00
if ( state & cpu_flag : : signal )
{
break ;
}
thread_ctrl : : wait_on ( ppu . state , state ) ;
2019-12-29 01:01:54 +01:00
}
if ( is_blocking )
{
2021-03-02 12:59:19 +01:00
while ( auto dlg = g_fxo - > get < msg_info > ( ) . get ( ) )
2019-12-29 01:01:54 +01:00
{
if ( Emu . IsStopped ( ) | | dlg - > state ! = MsgDialogState : : Open )
{
break ;
}
std : : this_thread : : yield ( ) ;
2019-01-20 23:46:48 +01:00
}
}
2019-12-29 01:01:54 +01:00
return CELL_OK ;
2018-06-12 21:33:21 +02:00
}
2019-01-20 22:57:51 +01:00
void exit_game ( s32 /* buttonType*/ , vm : : ptr < void > /* userData*/ )
{
sysutil_send_system_cmd ( CELL_SYSUTIL_REQUEST_EXITGAME , 0 ) ;
}
error_code open_exit_dialog ( const std : : string & message , bool is_exit_requested )
{
cellSysutil . warning ( " open_exit_dialog(message=%s, is_exit_requested=%d) " , message , is_exit_requested ) ;
vm : : bptr < CellMsgDialogCallback > callback = vm : : null ;
if ( is_exit_requested )
{
2020-12-14 12:32:04 +01:00
callback . set ( ppu_function_manager : : func_addr ( FIND_FUNC ( exit_game ) ) ) ;
2019-01-20 22:57:51 +01:00
}
2019-01-20 23:46:48 +01:00
const error_code res = open_msg_dialog
2019-01-20 22:57:51 +01:00
(
2019-01-20 23:46:48 +01:00
true ,
2019-01-20 22:57:51 +01:00
CELL_MSGDIALOG_TYPE_SE_TYPE_ERROR | CELL_MSGDIALOG_TYPE_BUTTON_TYPE_OK | CELL_MSGDIALOG_TYPE_DISABLE_CANCEL_ON ,
2019-01-20 23:46:48 +01:00
vm : : make_str ( message ) ,
callback
2019-01-20 22:57:51 +01:00
) ;
if ( res ! = CELL_OK )
{
// Something went wrong, exit anyway
if ( is_exit_requested )
{
sysutil_send_system_cmd ( CELL_SYSUTIL_REQUEST_EXITGAME , 0 ) ;
}
}
return CELL_OK ;
}
2019-01-04 14:45:32 +01:00
error_code cellMsgDialogOpen2 ( u32 type , vm : : cptr < char > msgString , vm : : ptr < CellMsgDialogCallback > callback , vm : : ptr < void > userData , vm : : ptr < void > extParam )
2014-07-04 00:52:43 +02:00
{
2016-08-11 01:29:59 +02:00
cellSysutil . warning ( " cellMsgDialogOpen2(type=0x%x, msgString=%s, callback=*0x%x, userData=*0x%x, extParam=*0x%x) " , type , msgString , callback , userData , extParam ) ;
2014-12-19 00:18:44 +01:00
2018-06-07 13:20:09 +02:00
if ( ! msgString | | std : : strlen ( msgString . get_ptr ( ) ) > = CELL_MSGDIALOG_STRING_SIZE | | type & - 0x33f8 )
2014-12-19 00:18:44 +01:00
{
return CELL_MSGDIALOG_ERROR_PARAM ;
}
2017-11-14 15:57:56 +01:00
const MsgDialogType _type = { type ^ CELL_MSGDIALOG_TYPE_BG_INVISIBLE } ;
2015-09-26 22:46:04 +02:00
switch ( _type . button_type . unshifted ( ) )
2014-12-19 00:18:44 +01:00
{
case CELL_MSGDIALOG_TYPE_BUTTON_TYPE_NONE :
{
2015-09-26 22:46:04 +02:00
if ( _type . default_cursor | | _type . progress_bar_count > 2 )
2014-12-19 00:18:44 +01:00
{
return CELL_MSGDIALOG_ERROR_PARAM ;
}
2015-09-26 22:46:04 +02:00
2014-12-19 00:18:44 +01:00
break ;
}
case CELL_MSGDIALOG_TYPE_BUTTON_TYPE_YESNO :
{
2015-09-26 22:46:04 +02:00
if ( _type . default_cursor > 1 | | _type . progress_bar_count )
2014-12-19 00:18:44 +01:00
{
return CELL_MSGDIALOG_ERROR_PARAM ;
}
2015-09-26 22:46:04 +02:00
2014-12-19 00:18:44 +01:00
break ;
}
case CELL_MSGDIALOG_TYPE_BUTTON_TYPE_OK :
{
2015-09-26 22:46:04 +02:00
if ( _type . default_cursor | | _type . progress_bar_count )
2014-12-19 00:18:44 +01:00
{
return CELL_MSGDIALOG_ERROR_PARAM ;
}
2015-09-26 22:46:04 +02:00
2014-12-19 00:18:44 +01:00
break ;
}
default : return CELL_MSGDIALOG_ERROR_PARAM ;
}
2014-07-04 00:52:43 +02:00
2015-09-26 22:46:04 +02:00
if ( _type . se_mute_on )
2014-08-29 20:30:21 +02:00
{
2015-09-26 22:46:04 +02:00
// TODO
2015-04-15 20:33:44 +02:00
}
2015-09-26 22:46:04 +02:00
if ( _type . se_normal )
2015-04-15 20:33:44 +02:00
{
2019-10-09 01:14:52 +02:00
cellSysutil . warning ( " %s " , msgString ) ;
2014-08-29 20:30:21 +02:00
}
2015-09-26 22:46:04 +02:00
else
2014-07-04 00:52:43 +02:00
{
2019-10-09 01:14:52 +02:00
cellSysutil . error ( " %s " , msgString ) ;
2015-07-27 03:06:05 +02:00
}
2014-07-04 00:52:43 +02:00
2019-12-29 01:01:54 +01:00
return open_msg_dialog ( false , type , msgString , callback , userData , extParam ) ;
2014-07-04 00:52:43 +02:00
}
2019-01-04 14:45:32 +01:00
error_code cellMsgDialogOpen ( u32 type , vm : : cptr < char > msgString , vm : : ptr < CellMsgDialogCallback > callback , vm : : ptr < void > userData , vm : : ptr < void > extParam )
2017-02-07 11:00:19 +01:00
{
2018-06-07 13:20:09 +02:00
// Note: This function needs proper implementation, solve first argument "type" conflict with MsgDialogOpen2 in cellMsgDialog.h.
2017-02-07 11:00:19 +01:00
cellSysutil . todo ( " cellMsgDialogOpen(type=0x%x, msgString=%s, callback=*0x%x, userData=*0x%x, extParam=*0x%x) " , type , msgString , callback , userData , extParam ) ;
return cellMsgDialogOpen2 ( type , msgString , callback , userData , extParam ) ;
}
2019-01-04 14:45:32 +01:00
error_code cellMsgDialogOpenErrorCode ( u32 errorCode , vm : : ptr < CellMsgDialogCallback > callback , vm : : ptr < void > userData , vm : : ptr < void > extParam )
2014-07-04 00:52:43 +02:00
{
2016-01-12 22:57:16 +01:00
cellSysutil . warning ( " cellMsgDialogOpenErrorCode(errorCode=0x%x, callback=*0x%x, userData=*0x%x, extParam=*0x%x) " , errorCode , callback , userData , extParam ) ;
2015-04-15 20:33:44 +02:00
2020-09-03 20:56:02 +02:00
localized_string_id string_id = localized_string_id : : INVALID ;
2014-07-04 00:52:43 +02:00
switch ( errorCode )
{
2020-09-03 20:56:02 +02:00
case 0x80010001 : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_80010001 ; break ; // The resource is temporarily unavailable.
case 0x80010002 : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_80010002 ; break ; // Invalid argument or flag.
case 0x80010003 : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_80010003 ; break ; // The feature is not yet implemented.
case 0x80010004 : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_80010004 ; break ; // Memory allocation failed.
case 0x80010005 : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_80010005 ; break ; // The resource with the specified identifier does not exist.
case 0x80010006 : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_80010006 ; break ; // The file does not exist.
case 0x80010007 : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_80010007 ; break ; // The file is in unrecognized format / The file is not a valid ELF file.
case 0x80010008 : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_80010008 ; break ; // Resource deadlock is avoided.
case 0x80010009 : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_80010009 ; break ; // Operation not permitted.
case 0x8001000A : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_8001000A ; break ; // The device or resource is busy.
case 0x8001000B : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_8001000B ; break ; // The operation is timed out.
case 0x8001000C : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_8001000C ; break ; // The operation is aborted.
case 0x8001000D : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_8001000D ; break ; // Invalid memory access.
case 0x8001000F : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_8001000F ; break ; // State of the target thread is invalid.
case 0x80010010 : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_80010010 ; break ; // Alignment is invalid.
case 0x80010011 : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_80010011 ; break ; // Shortage of the kernel resources.
case 0x80010012 : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_80010012 ; break ; // The file is a directory.
case 0x80010013 : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_80010013 ; break ; // Operation cancelled.
case 0x80010014 : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_80010014 ; break ; // Entry already exists.
case 0x80010015 : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_80010015 ; break ; // Port is already connected.
case 0x80010016 : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_80010016 ; break ; // Port is not connected.
case 0x80010017 : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_80010017 ; break ; // Failure in authorizing SELF. Program authentication fail.
case 0x80010018 : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_80010018 ; break ; // The file is not MSELF.
case 0x80010019 : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_80010019 ; break ; // System version error.
case 0x8001001A : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_8001001A ; break ; // Fatal system error occurred while authorizing SELF. SELF auth failure.
case 0x8001001B : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_8001001B ; break ; // Math domain violation.
case 0x8001001C : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_8001001C ; break ; // Math range violation.
case 0x8001001D : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_8001001D ; break ; // Illegal multi-byte sequence in input.
case 0x8001001E : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_8001001E ; break ; // File position error.
case 0x8001001F : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_8001001F ; break ; // Syscall was interrupted.
case 0x80010020 : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_80010020 ; break ; // File too large.
case 0x80010021 : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_80010021 ; break ; // Too many links.
case 0x80010022 : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_80010022 ; break ; // File table overflow.
case 0x80010023 : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_80010023 ; break ; // No space left on device.
case 0x80010024 : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_80010024 ; break ; // Not a TTY.
case 0x80010025 : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_80010025 ; break ; // Broken pipe.
case 0x80010026 : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_80010026 ; break ; // Read-only filesystem.
case 0x80010027 : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_80010027 ; break ; // Illegal seek.
case 0x80010028 : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_80010028 ; break ; // Arg list too long.
case 0x80010029 : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_80010029 ; break ; // Access violation.
case 0x8001002A : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_8001002A ; break ; // Invalid file descriptor.
case 0x8001002B : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_8001002B ; break ; // Filesystem mounting failed.
case 0x8001002C : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_8001002C ; break ; // Too many files open.
case 0x8001002D : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_8001002D ; break ; // No device.
case 0x8001002E : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_8001002E ; break ; // Not a directory.
case 0x8001002F : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_8001002F ; break ; // No such device or IO.
case 0x80010030 : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_80010030 ; break ; // Cross-device link error.
case 0x80010031 : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_80010031 ; break ; // Bad Message.
case 0x80010032 : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_80010032 ; break ; // In progress.
case 0x80010033 : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_80010033 ; break ; // Message size error.
case 0x80010034 : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_80010034 ; break ; // Name too long.
case 0x80010035 : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_80010035 ; break ; // No lock.
case 0x80010036 : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_80010036 ; break ; // Not empty.
case 0x80010037 : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_80010037 ; break ; // Not supported.
case 0x80010038 : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_80010038 ; break ; // File-system specific error.
case 0x80010039 : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_80010039 ; break ; // Overflow occured.
case 0x8001003A : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_8001003A ; break ; // Filesystem not mounted.
case 0x8001003B : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_8001003B ; break ; // Not SData.
case 0x8001003C : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_8001003C ; break ; // Incorrect version in sys_load_param.
case 0x8001003D : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_8001003D ; break ; // Pointer is null.
case 0x8001003E : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_8001003E ; break ; // Pointer is null.
default : string_id = localized_string_id : : CELL_MSG_DIALOG_ERROR_DEFAULT ; break ; // An error has occurred.
2014-07-04 00:52:43 +02:00
}
2020-09-03 20:56:02 +02:00
const std : : string error = get_localized_string ( string_id , fmt : : format ( " %08x " , errorCode ) . c_str ( ) ) ;
2014-07-04 00:52:43 +02:00
2015-09-26 22:46:04 +02:00
return cellMsgDialogOpen2 ( CELL_MSGDIALOG_TYPE_SE_TYPE_ERROR | CELL_MSGDIALOG_TYPE_BUTTON_TYPE_OK , vm : : make_str ( error ) , callback , userData , extParam ) ;
2014-07-04 00:52:43 +02:00
}
2019-01-04 14:45:32 +01:00
error_code cellMsgDialogClose ( f32 delay )
2014-07-04 00:52:43 +02:00
{
2016-01-12 22:57:16 +01:00
cellSysutil . warning ( " cellMsgDialogClose(delay=%f) " , delay ) ;
2014-07-04 00:52:43 +02:00
2019-07-14 05:55:11 +02:00
const u64 wait_until = get_guest_system_time ( ) + static_cast < s64 > ( std : : max < float > ( delay , 0.0f ) * 1000 ) ;
2018-01-17 17:14:00 +01:00
2021-02-03 19:14:31 +01:00
if ( auto manager = g_fxo - > try_get < rsx : : overlays : : display_manager > ( ) )
2018-01-17 17:14:00 +01:00
{
2018-05-20 22:05:00 +02:00
if ( auto dlg = manager - > get < rsx : : overlays : : message_dialog > ( ) )
2018-01-17 17:14:00 +01:00
{
2021-03-02 12:59:19 +01:00
auto & thr = g_fxo - > get < msg_dlg_thread > ( ) ;
thr . wait_until = wait_until ;
thr . wait_until . notify_one ( ) ;
2018-01-17 17:14:00 +01:00
return CELL_OK ;
}
2020-02-22 12:46:49 +01:00
return CELL_MSGDIALOG_ERROR_DIALOG_NOT_OPENED ;
2018-01-17 17:14:00 +01:00
}
2021-03-02 12:59:19 +01:00
const auto dlg = g_fxo - > get < msg_info > ( ) . get ( ) ;
2015-04-15 20:33:44 +02:00
2015-09-18 00:41:14 +02:00
if ( ! dlg )
2014-07-04 00:52:43 +02:00
{
2015-09-18 00:41:14 +02:00
return CELL_MSGDIALOG_ERROR_DIALOG_NOT_OPENED ;
}
2021-03-02 12:59:19 +01:00
auto & thr = g_fxo - > get < msg_dlg_thread > ( ) ;
thr . wait_until = wait_until ;
thr . wait_until . notify_one ( ) ;
2014-07-04 00:52:43 +02:00
return CELL_OK ;
}
2019-01-04 14:45:32 +01:00
error_code cellMsgDialogAbort ( )
2014-07-04 00:52:43 +02:00
{
2016-01-12 22:57:16 +01:00
cellSysutil . warning ( " cellMsgDialogAbort() " ) ;
2014-07-04 00:52:43 +02:00
2021-02-03 19:14:31 +01:00
if ( auto manager = g_fxo - > try_get < rsx : : overlays : : display_manager > ( ) )
2018-01-17 17:14:00 +01:00
{
2018-05-20 22:05:00 +02:00
if ( auto dlg = manager - > get < rsx : : overlays : : message_dialog > ( ) )
2018-01-17 17:14:00 +01:00
{
2021-03-02 12:59:19 +01:00
g_fxo - > get < msg_dlg_thread > ( ) . wait_until = 0 ;
2020-03-09 23:00:26 +01:00
dlg - > close ( false , true ) ;
2018-01-17 17:14:00 +01:00
return CELL_OK ;
}
}
2021-03-02 12:59:19 +01:00
const auto dlg = g_fxo - > get < msg_info > ( ) . get ( ) ;
2015-04-15 20:33:44 +02:00
2015-09-18 00:41:14 +02:00
if ( ! dlg )
2014-07-04 00:52:43 +02:00
{
2015-09-18 00:41:14 +02:00
return CELL_MSGDIALOG_ERROR_DIALOG_NOT_OPENED ;
}
if ( ! dlg - > state . compare_and_swap_test ( MsgDialogState : : Open , MsgDialogState : : Abort ) )
{
return CELL_SYSUTIL_ERROR_BUSY ;
}
2021-03-02 12:59:19 +01:00
g_fxo - > get < msg_dlg_thread > ( ) . wait_until = 0 ;
g_fxo - > get < msg_info > ( ) . remove ( ) ; // this shouldn't call on_close
2020-10-04 22:46:28 +02:00
input : : SetIntercepted ( false ) ; // so we need to reenable the pads here
2019-06-01 09:46:45 +02:00
2014-07-04 00:52:43 +02:00
return CELL_OK ;
}
2019-01-04 14:45:32 +01:00
error_code cellMsgDialogOpenSimulViewWarning ( vm : : ptr < CellMsgDialogCallback > callback , vm : : ptr < void > userData , vm : : ptr < void > extParam )
2018-06-07 13:20:09 +02:00
{
cellSysutil . todo ( " cellMsgDialogOpenSimulViewWarning(callback=*0x%x, userData=*0x%x, extParam=*0x%x) " , callback , userData , extParam ) ;
2019-01-18 14:36:25 +01:00
error_code ret = cellMsgDialogOpen2 ( CELL_MSGDIALOG_TYPE_SE_TYPE_NORMAL | CELL_MSGDIALOG_TYPE_BUTTON_TYPE_OK , vm : : make_str ( " SimulView Warning " ) , callback , userData , extParam ) ;
2018-06-07 13:20:09 +02:00
// The dialog should ideally only be closeable by pressing ok after 3 seconds until it closes itself automatically after 5 seconds
if ( ret = = CELL_OK )
cellMsgDialogClose ( 5000.0f ) ;
return ret ;
}
2019-01-04 14:45:32 +01:00
error_code cellMsgDialogProgressBarSetMsg ( u32 progressBarIndex , vm : : cptr < char > msgString )
2014-07-04 00:52:43 +02:00
{
2016-08-11 01:29:59 +02:00
cellSysutil . warning ( " cellMsgDialogProgressBarSetMsg(progressBarIndex=%d, msgString=%s) " , progressBarIndex , msgString ) ;
2014-07-04 00:52:43 +02:00
2018-06-07 13:20:09 +02:00
if ( ! msgString | | std : : strlen ( msgString . get_ptr ( ) ) > = CELL_MSGDIALOG_PROGRESSBAR_STRING_SIZE )
2018-01-27 15:01:33 +01:00
{
return CELL_MSGDIALOG_ERROR_PARAM ;
}
2021-02-03 19:14:31 +01:00
if ( auto manager = g_fxo - > try_get < rsx : : overlays : : display_manager > ( ) )
2018-01-17 17:14:00 +01:00
{
2018-05-20 22:05:00 +02:00
if ( auto dlg = manager - > get < rsx : : overlays : : message_dialog > ( ) )
2018-01-17 17:14:00 +01:00
{
2018-05-20 22:05:00 +02:00
return dlg - > progress_bar_set_message ( progressBarIndex , msgString . get_ptr ( ) ) ;
2018-01-17 17:14:00 +01:00
}
}
2021-03-02 12:59:19 +01:00
const auto dlg = g_fxo - > get < msg_info > ( ) . get ( ) ;
2015-09-18 00:41:14 +02:00
if ( ! dlg )
2014-07-04 00:52:43 +02:00
{
return CELL_MSGDIALOG_ERROR_DIALOG_NOT_OPENED ;
}
2018-01-27 15:01:33 +01:00
if ( progressBarIndex > = dlg - > type . progress_bar_count )
2014-07-04 00:52:43 +02:00
{
return CELL_MSGDIALOG_ERROR_PARAM ;
}
2015-09-18 00:41:14 +02:00
Emu . CallAfter ( [ = , msg = std : : string { msgString . get_ptr ( ) } ]
{
dlg - > ProgressBarSetMsg ( progressBarIndex , msg ) ;
} ) ;
2015-04-15 20:33:44 +02:00
2014-07-04 00:52:43 +02:00
return CELL_OK ;
}
2019-01-04 14:45:32 +01:00
error_code cellMsgDialogProgressBarReset ( u32 progressBarIndex )
2014-07-04 00:52:43 +02:00
{
2016-01-12 22:57:16 +01:00
cellSysutil . warning ( " cellMsgDialogProgressBarReset(progressBarIndex=%d) " , progressBarIndex ) ;
2014-07-04 00:52:43 +02:00
2021-02-03 19:14:31 +01:00
if ( auto manager = g_fxo - > try_get < rsx : : overlays : : display_manager > ( ) )
2018-01-17 17:14:00 +01:00
{
2018-05-20 22:05:00 +02:00
if ( auto dlg = manager - > get < rsx : : overlays : : message_dialog > ( ) )
2018-01-17 17:14:00 +01:00
{
2018-05-20 22:05:00 +02:00
return dlg - > progress_bar_reset ( progressBarIndex ) ;
2018-01-17 17:14:00 +01:00
}
}
2021-03-02 12:59:19 +01:00
const auto dlg = g_fxo - > get < msg_info > ( ) . get ( ) ;
2015-09-18 00:41:14 +02:00
if ( ! dlg )
2014-07-04 00:52:43 +02:00
{
return CELL_MSGDIALOG_ERROR_DIALOG_NOT_OPENED ;
}
2015-09-26 22:46:04 +02:00
if ( progressBarIndex > = dlg - > type . progress_bar_count )
2014-07-04 00:52:43 +02:00
{
return CELL_MSGDIALOG_ERROR_PARAM ;
}
2016-08-14 02:22:19 +02:00
Emu . CallAfter ( [ = ]
{
dlg - > ProgressBarReset ( progressBarIndex ) ;
} ) ;
2015-04-15 20:33:44 +02:00
2014-07-04 00:52:43 +02:00
return CELL_OK ;
}
2019-01-04 14:45:32 +01:00
error_code cellMsgDialogProgressBarInc ( u32 progressBarIndex , u32 delta )
2014-07-04 00:52:43 +02:00
{
2016-01-12 22:57:16 +01:00
cellSysutil . warning ( " cellMsgDialogProgressBarInc(progressBarIndex=%d, delta=%d) " , progressBarIndex , delta ) ;
2014-07-04 00:52:43 +02:00
2021-02-03 19:14:31 +01:00
if ( auto manager = g_fxo - > try_get < rsx : : overlays : : display_manager > ( ) )
2018-01-17 17:14:00 +01:00
{
2018-05-20 22:05:00 +02:00
if ( auto dlg = manager - > get < rsx : : overlays : : message_dialog > ( ) )
2018-01-17 17:14:00 +01:00
{
2019-12-02 22:31:34 +01:00
return dlg - > progress_bar_increment ( progressBarIndex , static_cast < f32 > ( delta ) ) ;
2018-01-17 17:14:00 +01:00
}
}
2021-03-02 12:59:19 +01:00
const auto dlg = g_fxo - > get < msg_info > ( ) . get ( ) ;
2015-09-18 00:41:14 +02:00
if ( ! dlg )
2014-07-04 00:52:43 +02:00
{
return CELL_MSGDIALOG_ERROR_DIALOG_NOT_OPENED ;
}
2015-09-26 22:46:04 +02:00
if ( progressBarIndex > = dlg - > type . progress_bar_count )
2014-07-04 00:52:43 +02:00
{
return CELL_MSGDIALOG_ERROR_PARAM ;
}
2016-08-14 02:22:19 +02:00
Emu . CallAfter ( [ = ]
{
dlg - > ProgressBarInc ( progressBarIndex , delta ) ;
} ) ;
2015-04-15 20:33:44 +02:00
2014-07-04 00:52:43 +02:00
return CELL_OK ;
2014-07-10 22:54:12 +02:00
}
2015-04-15 20:33:44 +02:00
void cellSysutil_MsgDialog_init ( )
{
2015-08-01 18:14:49 +02:00
REG_FUNC ( cellSysutil , cellMsgDialogOpen ) ;
2015-04-15 20:33:44 +02:00
REG_FUNC ( cellSysutil , cellMsgDialogOpen2 ) ;
REG_FUNC ( cellSysutil , cellMsgDialogOpenErrorCode ) ;
2015-08-01 18:14:49 +02:00
REG_FUNC ( cellSysutil , cellMsgDialogOpenSimulViewWarning ) ;
2015-04-15 20:33:44 +02:00
REG_FUNC ( cellSysutil , cellMsgDialogProgressBarSetMsg ) ;
REG_FUNC ( cellSysutil , cellMsgDialogProgressBarReset ) ;
REG_FUNC ( cellSysutil , cellMsgDialogProgressBarInc ) ;
REG_FUNC ( cellSysutil , cellMsgDialogClose ) ;
REG_FUNC ( cellSysutil , cellMsgDialogAbort ) ;
2019-01-20 22:57:51 +01:00
// Helper Function
2019-01-20 23:46:48 +01:00
REG_FUNC ( cellSysutil , exit_game ) . flag ( MFF_HIDDEN ) ;
2015-04-15 20:33:44 +02:00
}