2020-12-05 13:08:24 +01:00
# include "main_application.h"
2019-06-18 04:02:06 +02:00
2020-12-22 09:42:57 +01:00
# include "util/types.hpp"
# include "util/logs.hpp"
2021-04-10 11:54:52 +02:00
# include "util/sysinfo.hpp"
2020-12-22 09:42:57 +01:00
2021-09-07 21:56:49 +02:00
# include "Utilities/Thread.h"
2019-12-22 17:39:42 +01:00
# include "Input/pad_thread.h"
2020-02-15 23:36:20 +01:00
# include "Emu/System.h"
2020-07-30 13:23:55 +02:00
# include "Emu/system_config.h"
# include "Emu/IdManager.h"
2019-06-18 04:02:06 +02:00
# include "Emu/Io/Null/NullKeyboardHandler.h"
# include "Emu/Io/Null/NullMouseHandler.h"
# include "Emu/Io/KeyboardHandler.h"
# include "Emu/Io/MouseHandler.h"
2019-12-22 17:39:42 +01:00
# include "Input/basic_keyboard_handler.h"
# include "Input/basic_mouse_handler.h"
2019-06-18 04:02:06 +02:00
# include "Emu/Audio/AudioBackend.h"
# include "Emu/Audio/Null/NullAudioBackend.h"
2022-07-08 17:13:38 +02:00
# include "Emu/Audio/Null/null_enumerator.h"
2021-11-24 19:41:05 +01:00
# include "Emu/Audio/Cubeb/CubebBackend.h"
2022-07-08 17:13:38 +02:00
# include "Emu/Audio/Cubeb/cubeb_enumerator.h"
2019-06-18 04:02:06 +02:00
# ifdef _WIN32
# include "Emu/Audio/XAudio2/XAudio2Backend.h"
2022-07-08 17:13:38 +02:00
# include "Emu/Audio/XAudio2/xaudio2_enumerator.h"
2019-06-18 04:02:06 +02:00
# endif
2019-10-24 21:26:29 +02:00
# ifdef HAVE_FAUDIO
# include "Emu/Audio/FAudio/FAudioBackend.h"
2022-07-08 17:13:38 +02:00
# include "Emu/Audio/FAudio/faudio_enumerator.h"
2019-10-24 21:26:29 +02:00
# endif
2019-06-18 04:02:06 +02:00
2022-01-13 05:24:04 +01:00
# include <QFileInfo> // This shouldn't be outside rpcs3qt...
2022-07-23 21:19:43 +02:00
# include <QImageReader> // This shouldn't be outside rpcs3qt...
2022-07-04 15:02:17 +02:00
# include <thread>
2022-01-13 05:24:04 +01:00
2020-02-18 20:42:55 +01:00
LOG_CHANNEL ( sys_log , " SYS " ) ;
2021-04-02 00:54:32 +02:00
/** Emu.Init() wrapper for user management */
void main_application : : InitializeEmulator ( const std : : string & user , bool show_gui )
2019-06-18 04:02:06 +02:00
{
2019-12-03 08:32:28 +01:00
Emu . SetHasGui ( show_gui ) ;
2021-04-02 00:54:32 +02:00
Emu . SetUsr ( user ) ;
Emu . Init ( ) ;
2021-04-10 11:54:52 +02:00
// Log Firmware Version after Emu was initialized
const std : : string firmware_version = utils : : get_firmware_version ( ) ;
const std : : string firmware_string = firmware_version . empty ( ) ? " Missing Firmware " : ( " Firmware version: " + firmware_version ) ;
2021-05-19 13:30:39 +02:00
sys_log . always ( ) ( " %s " , firmware_string ) ;
2019-06-18 04:02:06 +02:00
}
/** RPCS3 emulator has functions it desires to call from the GUI at times. Initialize them in here. */
EmuCallbacks main_application : : CreateCallbacks ( )
{
EmuCallbacks callbacks ;
2020-06-24 17:01:48 +02:00
callbacks . init_kb_handler = [ this ] ( )
2019-06-18 04:02:06 +02:00
{
2021-04-07 23:05:18 +02:00
switch ( g_cfg . io . keyboard . get ( ) )
2019-06-18 04:02:06 +02:00
{
2019-09-19 00:50:08 +02:00
case keyboard_handler : : null :
{
2022-07-04 15:02:17 +02:00
g_fxo - > init < KeyboardHandlerBase , NullKeyboardHandler > ( Emu . DeserialManager ( ) ) ;
2019-09-19 00:50:08 +02:00
break ;
}
2019-06-18 04:02:06 +02:00
case keyboard_handler : : basic :
{
2022-07-04 15:02:17 +02:00
basic_keyboard_handler * ret = g_fxo - > init < KeyboardHandlerBase , basic_keyboard_handler > ( Emu . DeserialManager ( ) ) ;
2019-06-18 04:02:06 +02:00
ret - > moveToThread ( get_thread ( ) ) ;
ret - > SetTargetWindow ( m_game_window ) ;
2019-09-19 00:50:08 +02:00
break ;
2019-06-18 04:02:06 +02:00
}
}
} ;
2020-06-24 17:01:48 +02:00
callbacks . init_mouse_handler = [ this ] ( )
2019-06-18 04:02:06 +02:00
{
2021-04-07 23:05:18 +02:00
switch ( g_cfg . io . mouse . get ( ) )
2019-06-18 04:02:06 +02:00
{
2019-09-19 00:50:08 +02:00
case mouse_handler : : null :
{
2018-07-23 19:57:40 +02:00
if ( g_cfg . io . move = = move_handler : : mouse )
{
2022-07-04 15:02:17 +02:00
basic_mouse_handler * ret = g_fxo - > init < MouseHandlerBase , basic_mouse_handler > ( Emu . DeserialManager ( ) ) ;
2018-07-23 19:57:40 +02:00
ret - > moveToThread ( get_thread ( ) ) ;
ret - > SetTargetWindow ( m_game_window ) ;
}
else
2022-07-06 14:35:50 +02:00
{
2022-07-04 15:02:17 +02:00
g_fxo - > init < MouseHandlerBase , NullMouseHandler > ( Emu . DeserialManager ( ) ) ;
2022-07-06 14:35:50 +02:00
}
2018-07-23 19:57:40 +02:00
2019-09-19 00:50:08 +02:00
break ;
}
2019-06-18 04:02:06 +02:00
case mouse_handler : : basic :
{
2022-07-04 15:02:17 +02:00
basic_mouse_handler * ret = g_fxo - > init < MouseHandlerBase , basic_mouse_handler > ( Emu . DeserialManager ( ) ) ;
2019-06-18 04:02:06 +02:00
ret - > moveToThread ( get_thread ( ) ) ;
ret - > SetTargetWindow ( m_game_window ) ;
2019-09-19 00:50:08 +02:00
break ;
2019-06-18 04:02:06 +02:00
}
}
} ;
2019-09-18 01:44:06 +02:00
callbacks . init_pad_handler = [ this ] ( std : : string_view title_id )
2019-06-18 04:02:06 +02:00
{
2022-07-04 15:02:17 +02:00
ensure ( g_fxo - > init < named_thread < pad_thread > > ( get_thread ( ) , m_game_window , title_id ) ) ;
while ( pad : : g_reset ) std : : this_thread : : yield ( ) ;
2019-06-18 04:02:06 +02:00
} ;
callbacks . get_audio = [ ] ( ) - > std : : shared_ptr < AudioBackend >
{
2020-02-18 20:42:55 +01:00
std : : shared_ptr < AudioBackend > result ;
2021-04-07 23:05:18 +02:00
switch ( g_cfg . audio . renderer . get ( ) )
2019-06-18 04:02:06 +02:00
{
2020-02-18 20:42:55 +01:00
case audio_renderer : : null : result = std : : make_shared < NullAudioBackend > ( ) ; break ;
2019-06-18 04:02:06 +02:00
# ifdef _WIN32
2020-02-18 20:42:55 +01:00
case audio_renderer : : xaudio : result = std : : make_shared < XAudio2Backend > ( ) ; break ;
2019-06-18 04:02:06 +02:00
# endif
2021-11-24 19:41:05 +01:00
case audio_renderer : : cubeb : result = std : : make_shared < CubebBackend > ( ) ; break ;
2019-10-24 21:26:29 +02:00
# ifdef HAVE_FAUDIO
2020-02-18 20:42:55 +01:00
case audio_renderer : : faudio : result = std : : make_shared < FAudioBackend > ( ) ; break ;
2019-10-24 21:26:29 +02:00
# endif
2019-06-18 04:02:06 +02:00
}
2020-02-18 20:42:55 +01:00
if ( ! result - > Initialized ( ) )
{
// Fall back to a null backend if something went wrong
2021-12-02 00:58:28 +01:00
sys_log . error ( " Audio renderer %s could not be initialized, using a Null renderer instead. Make sure that no other application is running that might block audio access (e.g. Netflix). " , result - > GetName ( ) ) ;
2020-02-18 20:42:55 +01:00
result = std : : make_shared < NullAudioBackend > ( ) ;
}
return result ;
2019-06-18 04:02:06 +02:00
} ;
2022-07-08 17:13:38 +02:00
callbacks . get_audio_enumerator = [ ] ( u64 renderer ) - > std : : shared_ptr < audio_device_enumerator >
{
switch ( static_cast < audio_renderer > ( renderer ) )
{
case audio_renderer : : null : return std : : make_shared < null_enumerator > ( ) ;
# ifdef _WIN32
case audio_renderer : : xaudio : return std : : make_shared < xaudio2_enumerator > ( ) ;
# endif
case audio_renderer : : cubeb : return std : : make_shared < cubeb_enumerator > ( ) ;
# ifdef HAVE_FAUDIO
case audio_renderer : : faudio : return std : : make_shared < faudio_enumerator > ( ) ;
# endif
default : fmt : : throw_exception ( " Invalid renderer index %u " , renderer ) ;
}
} ;
2022-07-23 21:19:43 +02:00
callbacks . get_image_info = [ ] ( const std : : string & filename , std : : string & sub_type , s32 & width , s32 & height , s32 & orientation ) - > bool
{
sub_type . clear ( ) ;
width = 0 ;
height = 0 ;
orientation = 0 ; // CELL_SEARCH_ORIENTATION_UNKNOWN
bool success = false ;
Emu . BlockingCallFromMainThread ( [ & ] ( )
{
const QImageReader reader ( QString : : fromStdString ( filename ) ) ;
if ( reader . canRead ( ) )
{
const QSize size = reader . size ( ) ;
width = size . width ( ) ;
height = size . height ( ) ;
sub_type = reader . subType ( ) . toStdString ( ) ;
switch ( reader . transformation ( ) )
{
case QImageIOHandler : : Transformation : : TransformationNone :
orientation = 1 ; // CELL_SEARCH_ORIENTATION_TOP_LEFT = 0°
break ;
case QImageIOHandler : : Transformation : : TransformationRotate90 :
orientation = 2 ; // CELL_SEARCH_ORIENTATION_TOP_RIGHT = 90°
break ;
case QImageIOHandler : : Transformation : : TransformationRotate180 :
orientation = 3 ; // CELL_SEARCH_ORIENTATION_BOTTOM_RIGHT = 180°
break ;
case QImageIOHandler : : Transformation : : TransformationRotate270 :
orientation = 4 ; // CELL_SEARCH_ORIENTATION_BOTTOM_LEFT = 270°
break ;
default :
// Ignore other transformations for now
break ;
}
success = true ;
sys_log . notice ( " get_image_info found image: filename='%s', sub_type='%s', width=%d, height=%d, orientation=%d " , filename , sub_type , width , height , orientation ) ;
}
} ) ;
return success ;
} ;
2022-01-13 05:24:04 +01:00
callbacks . resolve_path = [ ] ( std : : string_view sv )
{
return QFileInfo ( QString : : fromUtf8 ( sv . data ( ) , static_cast < int > ( sv . size ( ) ) ) ) . canonicalFilePath ( ) . toStdString ( ) ;
} ;
2019-06-18 04:02:06 +02:00
return callbacks ;
}