2022-08-22 22:21:23 +02:00
# include "gui/wxgui.h"
# include "gui/GeneralSettings2.h"
# include "gui/CemuApp.h"
# include "gui/helpers/wxControlObject.h"
# include "util/helpers/helpers.h"
# include "Cafe/OS/libs/snd_core/ax.h"
# include <wx/collpane.h>
# include <wx/clrpicker.h>
# include <wx/cshelp.h>
# include <wx/textdlg.h>
# include <wx/hyperlink.h>
# include "config/CemuConfig.h"
# include "audio/IAudioAPI.h"
2022-08-26 04:03:26 +02:00
# if BOOST_OS_WINDOWS
2022-08-22 22:21:23 +02:00
# include "audio/DirectSoundAPI.h"
# include "audio/XAudio27API.h"
# endif
# include "audio/CubebAPI.h"
# include "Cafe/HW/Latte/Renderer/Vulkan/VulkanAPI.h"
# include "Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h"
# include "Cafe/Account/Account.h"
# include <boost/tokenizer.hpp>
# include "util/helpers/SystemException.h"
# include "gui/dialogs/CreateAccount/wxCreateAccountDialog.h"
# include "config/PermanentStorage.h"
2022-08-26 04:03:26 +02:00
# if BOOST_OS_WINDOWS
2022-08-22 22:21:23 +02:00
# include <VersionHelpers.h>
# endif
# include "config/LaunchSettings.h"
# include "config/ActiveSettings.h"
# include "gui/helpers/wxHelpers.h"
2022-08-26 04:03:26 +02:00
# if BOOST_OS_LINUX || BOOST_OS_MACOS
# include "resource/embedded/resources.h"
2022-08-22 22:21:23 +02:00
# endif
# include "Cafe/CafeSystem.h"
# include "Cemu/ncrypto/ncrypto.h"
# include "Cafe/TitleList/TitleList.h"
# include "wxHelper.h"
const wxString kDirectSound ( wxT ( " DirectSound " ) ) ;
const wxString kXAudio27 ( wxT ( " XAudio2.7 " ) ) ;
const wxString kXAudio2 ( wxT ( " XAudio2 " ) ) ;
const wxString kCubeb ( wxT ( " Cubeb " ) ) ;
const wxString kPropertyPersistentId ( wxT ( " PersistentId " ) ) ;
const wxString kPropertyMiiName ( wxT ( " MiiName " ) ) ;
const wxString kPropertyBirthday ( wxT ( " Birthday " ) ) ;
const wxString kPropertyGender ( wxT ( " Gender " ) ) ;
const wxString kPropertyEmail ( wxT ( " Email " ) ) ;
const wxString kPropertyCountry ( wxT ( " Country " ) ) ;
wxDEFINE_EVENT ( wxEVT_ACCOUNTLIST_REFRESH , wxCommandEvent ) ;
class wxDeviceDescription : public wxClientData
{
public :
wxDeviceDescription ( const IAudioAPI : : DeviceDescriptionPtr & description ) : m_description ( description ) { }
const IAudioAPI : : DeviceDescriptionPtr & GetDescription ( ) const { return m_description ; }
private :
IAudioAPI : : DeviceDescriptionPtr m_description ;
} ;
class wxVulkanUUID : public wxClientData
{
public :
wxVulkanUUID ( const VulkanRenderer : : DeviceInfo & info )
: m_device_info ( info ) { }
const VulkanRenderer : : DeviceInfo & GetDeviceInfo ( ) const { return m_device_info ; }
private :
VulkanRenderer : : DeviceInfo m_device_info ;
} ;
class wxAccountData : public wxClientData
{
public :
wxAccountData ( const Account & account )
: m_account ( account ) { }
Account & GetAccount ( ) { return m_account ; }
const Account & GetAccount ( ) const { return m_account ; }
private :
Account m_account ;
} ;
wxPanel * GeneralSettings2 : : AddGeneralPage ( wxNotebook * notebook )
{
auto * panel = new wxPanel ( notebook ) ;
auto * general_panel_sizer = new wxBoxSizer ( wxVERTICAL ) ;
{
auto * box = new wxStaticBox ( panel , wxID_ANY , _ ( " Interface " ) ) ;
auto * box_sizer = new wxStaticBoxSizer ( box , wxVERTICAL ) ;
{
auto * first_row = new wxFlexGridSizer ( 0 , 2 , 0 , 0 ) ;
first_row - > SetFlexibleDirection ( wxBOTH ) ;
first_row - > SetNonFlexibleGrowMode ( wxFLEX_GROWMODE_SPECIFIED ) ;
first_row - > Add ( new wxStaticText ( box , wxID_ANY , _ ( " Language " ) , wxDefaultPosition , wxDefaultSize , 0 ) , 0 , wxALIGN_CENTER_VERTICAL | wxALL , 5 ) ;
wxString language_choices [ ] = { _ ( " Default " ) , _ ( " English " ) } ;
m_language = new wxChoice ( box , wxID_ANY , wxDefaultPosition , wxDefaultSize , std : : size ( language_choices ) , language_choices ) ;
m_language - > SetSelection ( 0 ) ;
m_language - > SetToolTip ( _ ( " Changes the interface language of Cemu \n Available languages are stored in the translation directory \n A restart will be required after changing the language " ) ) ;
for ( const auto & language : wxGetApp ( ) . GetLanguages ( ) )
{
m_language - > Append ( language - > Description ) ;
}
first_row - > Add ( m_language , 0 , wxALL | wxEXPAND , 5 ) ;
box_sizer - > Add ( first_row , 1 , wxEXPAND , 5 ) ;
}
{
auto * second_row = new wxFlexGridSizer ( 0 , 3 , 0 , 0 ) ;
second_row - > SetFlexibleDirection ( wxBOTH ) ;
second_row - > SetNonFlexibleGrowMode ( wxFLEX_GROWMODE_SPECIFIED ) ;
const int topflag = wxALIGN_CENTER_VERTICAL | wxALL ;
m_save_window_position_size = new wxCheckBox ( box , wxID_ANY , _ ( " Remember main window position " ) ) ;
m_save_window_position_size - > SetToolTip ( _ ( " Restores the last known window position and size when starting Cemu " ) ) ;
second_row - > Add ( m_save_window_position_size , 0 , topflag , 5 ) ;
second_row - > AddSpacer ( 10 ) ;
m_save_padwindow_position_size = new wxCheckBox ( box , wxID_ANY , _ ( " Remember pad window position " ) ) ;
m_save_padwindow_position_size - > SetToolTip ( _ ( " Restores the last known pad window position and size when opening it " ) ) ;
second_row - > Add ( m_save_padwindow_position_size , 0 , topflag , 5 ) ;
const int botflag = wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT | wxBOTTOM ;
m_discord_presence = new wxCheckBox ( box , wxID_ANY , _ ( " Discord Presence " ) ) ;
m_discord_presence - > SetToolTip ( _ ( " Enables the Discord Rich Presence feature \n You will also need to enable it in the Discord settings itself! " ) ) ;
second_row - > Add ( m_discord_presence , 0 , botflag , 5 ) ;
second_row - > AddSpacer ( 10 ) ;
m_fullscreen_menubar = new wxCheckBox ( box , wxID_ANY , _ ( " Fullscreen menu bar " ) ) ;
m_fullscreen_menubar - > SetToolTip ( _ ( " Displays the menu bar when Cemu is running in fullscreen mode and the mouse cursor is moved to the top " ) ) ;
second_row - > Add ( m_fullscreen_menubar , 0 , botflag , 5 ) ;
m_auto_update = new wxCheckBox ( box , wxID_ANY , _ ( " Automatically check for updates " ) ) ;
m_auto_update - > SetToolTip ( _ ( " Automatically checks for new cemu versions on startup " ) ) ;
second_row - > Add ( m_auto_update , 0 , botflag , 5 ) ;
second_row - > AddSpacer ( 10 ) ;
m_save_screenshot = new wxCheckBox ( box , wxID_ANY , _ ( " Save screenshot " ) ) ;
m_save_screenshot - > SetToolTip ( _ ( " Pressing the screenshot key (F12) will save a screenshot directly to the screenshots folder " ) ) ;
second_row - > Add ( m_save_screenshot , 0 , botflag , 5 ) ;
m_permanent_storage = new wxCheckBox ( box , wxID_ANY , _ ( " Use permanent storage " ) ) ;
m_permanent_storage - > SetToolTip ( _ ( " Cemu will remember your custom mlc path in %LOCALAPPDATA%/Cemu for new installations. " ) ) ;
second_row - > Add ( m_permanent_storage , 0 , botflag , 5 ) ;
box_sizer - > Add ( second_row , 0 , wxEXPAND , 5 ) ;
}
general_panel_sizer - > Add ( box_sizer , 0 , wxEXPAND | wxALL , 5 ) ;
}
{
auto * box = new wxStaticBox ( panel , wxID_ANY , _ ( " MLC Path " ) ) ;
auto * box_sizer = new wxStaticBoxSizer ( box , wxHORIZONTAL ) ;
m_mlc_path = new wxTextCtrl ( box , wxID_ANY , wxEmptyString , wxDefaultPosition , wxDefaultSize , wxTE_READONLY ) ;
m_mlc_path - > SetMinSize ( wxSize ( 150 , - 1 ) ) ;
m_mlc_path - > Bind ( wxEVT_CHAR , & GeneralSettings2 : : OnMLCPathChar , this ) ;
m_mlc_path - > SetToolTip ( _ ( " The mlc directory contains your save games and installed game update/dlc data " ) ) ;
box_sizer - > Add ( m_mlc_path , 1 , wxALL | wxEXPAND , 5 ) ;
auto * change_path = new wxButton ( box , wxID_ANY , wxT ( " ... " ) ) ;
change_path - > Bind ( wxEVT_BUTTON , & GeneralSettings2 : : OnMLCPathSelect , this ) ;
change_path - > SetToolTip ( _ ( " Select a custom mlc path \n The mlc path is used to store Wii U related files like save games, game updates and dlc data " ) ) ;
box_sizer - > Add ( change_path , 0 , wxALL , 5 ) ;
if ( LaunchSettings : : GetMLCPath ( ) . has_value ( ) )
change_path - > Disable ( ) ;
general_panel_sizer - > Add ( box_sizer , 0 , wxEXPAND | wxALL , 5 ) ;
}
{
auto * general_gamepath_box = new wxStaticBox ( panel , wxID_ANY , _ ( " Game Paths " ) ) ;
auto * general_gamepath_sizer = new wxStaticBoxSizer ( general_gamepath_box , wxVERTICAL ) ;
m_game_paths = new wxListBox ( general_gamepath_box , wxID_ANY ) ;
m_game_paths - > SetMinSize ( wxSize ( 150 , 100 ) ) ;
m_game_paths - > SetToolTip ( _ ( " Add the root directory of your game(s). It will scan all directories in it for games " ) ) ;
general_gamepath_sizer - > Add ( m_game_paths , 1 , wxALL | wxEXPAND , 5 ) ;
auto * general_gamepath_buttons = new wxFlexGridSizer ( 0 , 2 , 0 , 0 ) ;
general_gamepath_buttons - > SetFlexibleDirection ( wxBOTH ) ;
general_gamepath_buttons - > SetNonFlexibleGrowMode ( wxFLEX_GROWMODE_SPECIFIED ) ;
auto * general_gamepath_add_button = new wxButton ( general_gamepath_box , wxID_ANY , _ ( " Add " ) ) ;
general_gamepath_add_button - > Bind ( wxEVT_BUTTON , & GeneralSettings2 : : OnAddPathClicked , this ) ;
general_gamepath_add_button - > SetToolTip ( _ ( " Adds a game path to scan for games displayed in the game list \n If you have unpacked games, make sure to select the root folder of a game " ) ) ;
general_gamepath_buttons - > Add ( general_gamepath_add_button , 0 , wxALL , 5 ) ;
auto * general_gamepath_remove_button = new wxButton ( general_gamepath_box , wxID_ANY , _ ( " Remove " ) ) ;
general_gamepath_remove_button - > Bind ( wxEVT_BUTTON , & GeneralSettings2 : : OnRemovePathClicked , this ) ;
general_gamepath_remove_button - > SetToolTip ( _ ( " Removes the currently selected game path from the game list " ) ) ;
general_gamepath_buttons - > Add ( general_gamepath_remove_button , 0 , wxALL , 5 ) ;
general_gamepath_sizer - > Add ( general_gamepath_buttons , 0 , wxEXPAND , 5 ) ;
general_panel_sizer - > Add ( general_gamepath_sizer , 1 , wxEXPAND | wxALL , 5 ) ;
}
panel - > SetSizerAndFit ( general_panel_sizer ) ;
return panel ;
}
wxPanel * GeneralSettings2 : : AddGraphicsPage ( wxNotebook * notebook )
{
// Graphics page
auto graphics_panel = new wxPanel ( notebook ) ;
auto graphics_panel_sizer = new wxBoxSizer ( wxVERTICAL ) ;
{
auto box = new wxStaticBox ( graphics_panel , wxID_ANY , _ ( " General " ) ) ;
auto box_sizer = new wxStaticBoxSizer ( box , wxVERTICAL ) ;
auto row = new wxFlexGridSizer ( 0 , 2 , 0 , 0 ) ;
row - > SetFlexibleDirection ( wxBOTH ) ;
row - > SetNonFlexibleGrowMode ( wxFLEX_GROWMODE_SPECIFIED ) ;
row - > Add ( new wxStaticText ( box , wxID_ANY , _ ( " Graphics API " ) ) , 0 , wxALIGN_CENTER_VERTICAL | wxALL , 5 ) ;
sint32 api_size = 1 ;
wxString choices [ 2 ] = { " OpenGL " } ;
if ( g_vulkan_available )
{
choices [ 1 ] = " Vulkan " ;
api_size = 2 ;
}
m_graphic_api = new wxChoice ( box , wxID_ANY , wxDefaultPosition , wxDefaultSize , api_size , choices ) ;
m_graphic_api - > SetSelection ( 0 ) ;
if ( api_size > 1 )
m_graphic_api - > SetToolTip ( _ ( " Select one of the available graphic back ends " ) ) ;
row - > Add ( m_graphic_api , 0 , wxALL , 5 ) ;
m_graphic_api - > Bind ( wxEVT_CHOICE , & GeneralSettings2 : : OnGraphicAPISelected , this ) ;
row - > Add ( new wxStaticText ( box , wxID_ANY , _ ( " Graphics Device " ) ) , 0 , wxALIGN_CENTER_VERTICAL | wxALL , 5 ) ;
m_graphic_device = new wxChoice ( box , wxID_ANY , wxDefaultPosition , { 230 , - 1 } , api_size , choices ) ;
m_graphic_device - > SetSelection ( 0 ) ;
m_graphic_device - > SetToolTip ( _ ( " Select the used graphic device " ) ) ;
row - > Add ( m_graphic_device , 0 , wxALL , 5 ) ;
row - > Add ( new wxStaticText ( box , wxID_ANY , _ ( " VSync " ) ) , 0 , wxALIGN_CENTER_VERTICAL | wxALL , 5 ) ;
m_vsync = new wxChoice ( box , wxID_ANY , wxDefaultPosition , { 230 , - 1 } ) ;
m_vsync - > SetToolTip ( _ ( " Controls the vsync state " ) ) ;
row - > Add ( m_vsync , 0 , wxALL , 5 ) ;
box_sizer - > Add ( row , 0 , wxEXPAND , 5 ) ;
auto * graphic_misc_row = new wxFlexGridSizer ( 0 , 2 , 0 , 0 ) ;
m_async_compile = new wxCheckBox ( box , wxID_ANY , _ ( " Async shader compile " ) ) ;
m_async_compile - > SetToolTip ( _ ( " Enables async shader and pipeline compilation. Reduces stutter at the cost of objects not rendering for a short time. \n Vulkan only " ) ) ;
graphic_misc_row - > Add ( m_async_compile , 0 , wxALL , 5 ) ;
m_gx2drawdone_sync = new wxCheckBox ( box , wxID_ANY , _ ( " Full sync at GX2DrawDone() " ) ) ;
m_gx2drawdone_sync - > SetToolTip ( _ ( " If synchronization is requested by the game, the emulated CPU will wait for the GPU to finish all operations. \n This is more accurate behavior, but may cause lower performance " ) ) ;
graphic_misc_row - > Add ( m_gx2drawdone_sync , 0 , wxALL , 5 ) ;
box_sizer - > Add ( graphic_misc_row , 1 , wxEXPAND , 5 ) ;
graphics_panel_sizer - > Add ( box_sizer , 0 , wxEXPAND | wxALL , 5 ) ;
}
{
wxString choices [ ] = { _ ( " Bilinear " ) , _ ( " Bicubic " ) , _ ( " Hermite " ) , _ ( " Nearest Neighbor " ) } ;
m_upscale_filter = new wxRadioBox ( graphics_panel , wxID_ANY , _ ( " Upscale filter " ) , wxDefaultPosition , wxDefaultSize , std : : size ( choices ) , choices , 5 , wxRA_SPECIFY_COLS ) ;
m_upscale_filter - > SetToolTip ( _ ( " Upscaling filters are used when the game resolution is smaller than the window size " ) ) ;
graphics_panel_sizer - > Add ( m_upscale_filter , 0 , wxALL | wxEXPAND , 5 ) ;
m_downscale_filter = new wxRadioBox ( graphics_panel , wxID_ANY , _ ( " Downscale filter " ) , wxDefaultPosition , wxDefaultSize , std : : size ( choices ) , choices , 5 , wxRA_SPECIFY_COLS ) ;
m_downscale_filter - > SetToolTip ( _ ( " Downscaling filters are used when the game resolution is bigger than the window size " ) ) ;
graphics_panel_sizer - > Add ( m_downscale_filter , 0 , wxALL | wxEXPAND , 5 ) ;
}
{
wxString choices [ ] = { _ ( " Keep aspect ratio " ) , _ ( " Stretch " ) } ;
m_fullscreen_scaling = new wxRadioBox ( graphics_panel , wxID_ANY , _ ( " Fullscreen scaling " ) , wxDefaultPosition , wxDefaultSize , std : : size ( choices ) , choices , 5 , wxRA_SPECIFY_COLS ) ;
m_fullscreen_scaling - > SetToolTip ( _ ( " Controls the output aspect ratio when it doesn't match the ratio of the game " ) ) ;
graphics_panel_sizer - > Add ( m_fullscreen_scaling , 0 , wxALL | wxEXPAND , 5 ) ;
}
graphics_panel - > SetSizerAndFit ( graphics_panel_sizer ) ;
return graphics_panel ;
}
wxPanel * GeneralSettings2 : : AddAudioPage ( wxNotebook * notebook )
{
auto audio_panel = new wxPanel ( notebook , wxID_ANY , wxDefaultPosition , wxDefaultSize , wxTAB_TRAVERSAL ) ;
auto audio_panel_sizer = new wxBoxSizer ( wxVERTICAL ) ;
{
auto box = new wxStaticBox ( audio_panel , wxID_ANY , _ ( " General " ) ) ;
auto box_sizer = new wxStaticBoxSizer ( box , wxVERTICAL ) ;
auto audio_general_row = new wxFlexGridSizer ( 0 , 3 , 0 , 0 ) ;
audio_general_row - > SetFlexibleDirection ( wxBOTH ) ;
audio_general_row - > SetNonFlexibleGrowMode ( wxFLEX_GROWMODE_SPECIFIED ) ;
audio_general_row - > Add ( new wxStaticText ( box , wxID_ANY , _ ( " API " ) ) , 0 , wxALIGN_CENTER_VERTICAL | wxALL , 5 ) ;
m_audio_api = new wxChoice ( box , wxID_ANY , wxDefaultPosition , wxDefaultSize , 0 , nullptr ) ;
if ( IAudioAPI : : IsAudioAPIAvailable ( IAudioAPI : : DirectSound ) )
m_audio_api - > Append ( kDirectSound ) ;
if ( IAudioAPI : : IsAudioAPIAvailable ( IAudioAPI : : XAudio27 ) )
m_audio_api - > Append ( kXAudio27 ) ;
if ( IAudioAPI : : IsAudioAPIAvailable ( IAudioAPI : : XAudio2 ) )
m_audio_api - > Append ( kXAudio2 ) ;
if ( IAudioAPI : : IsAudioAPIAvailable ( IAudioAPI : : Cubeb ) )
m_audio_api - > Append ( kCubeb ) ;
m_audio_api - > SetSelection ( 0 ) ;
m_audio_api - > SetToolTip ( _ ( " Select one of the available audio back ends " ) ) ;
audio_general_row - > Add ( m_audio_api , 0 , wxALL , 5 ) ;
m_audio_api - > Bind ( wxEVT_CHOICE , & GeneralSettings2 : : OnAudioAPISelected , this ) ;
audio_general_row - > AddSpacer ( 0 ) ;
audio_general_row - > Add ( new wxStaticText ( box , wxID_ANY , _ ( " Latency " ) ) , 0 , wxALIGN_CENTER_VERTICAL | wxALL , 5 ) ;
m_audio_latency = new wxSlider ( box , wxID_ANY , 2 , 0 , IAudioAPI : : kBlockCount - 1 , wxDefaultPosition , wxDefaultSize , wxSL_HORIZONTAL ) ;
m_audio_latency - > SetToolTip ( _ ( " Controls the amount of buffered audio data \n Higher values will create a delay in audio playback, but may avoid audio problems when emulation is too slow " ) ) ;
audio_general_row - > Add ( m_audio_latency , 0 , wxEXPAND | wxALL , 5 ) ;
auto latency_text = new wxStaticText ( box , wxID_ANY , wxT ( " 24ms " ) ) ;
audio_general_row - > Add ( latency_text , 0 , wxALIGN_CENTER_VERTICAL | wxALL | wxALIGN_RIGHT , 5 ) ;
m_audio_latency - > Bind ( wxEVT_SLIDER , & GeneralSettings2 : : OnLatencySliderChanged , this , wxID_ANY , wxID_ANY , new wxControlObject ( latency_text ) ) ;
m_audio_latency - > Bind ( wxEVT_SLIDER , & GeneralSettings2 : : OnAudioLatencyChanged , this ) ;
box_sizer - > Add ( audio_general_row , 1 , wxEXPAND , 5 ) ;
audio_panel_sizer - > Add ( box_sizer , 0 , wxEXPAND | wxALL , 5 ) ;
}
const wxString audio_channel_choices [ ] = { _ ( " Mono " ) , _ ( " Stereo " ) , _ ( " Surround " ) } ;
{
auto box = new wxStaticBox ( audio_panel , wxID_ANY , _ ( " TV " ) ) ;
auto box_sizer = new wxStaticBoxSizer ( box , wxVERTICAL ) ;
auto audio_tv_row = new wxFlexGridSizer ( 0 , 3 , 0 , 0 ) ;
audio_tv_row - > SetFlexibleDirection ( wxBOTH ) ;
audio_tv_row - > SetNonFlexibleGrowMode ( wxFLEX_GROWMODE_SPECIFIED ) ;
audio_tv_row - > Add ( new wxStaticText ( box , wxID_ANY , _ ( " Device " ) ) , 0 , wxALIGN_CENTER_VERTICAL | wxALL , 5 ) ;
m_tv_device = new wxChoice ( box , wxID_ANY ) ;
m_tv_device - > SetMinSize ( wxSize ( 300 , - 1 ) ) ;
m_tv_device - > SetToolTip ( _ ( " Select the active audio output device for Wii U TV " ) ) ;
audio_tv_row - > Add ( m_tv_device , 0 , wxEXPAND | wxALL , 5 ) ;
audio_tv_row - > AddSpacer ( 0 ) ;
m_tv_device - > Bind ( wxEVT_CHOICE , & GeneralSettings2 : : OnAudioDeviceSelected , this ) ;
audio_tv_row - > Add ( new wxStaticText ( box , wxID_ANY , _ ( " Channels " ) ) , 0 , wxALIGN_CENTER_VERTICAL | wxALL , 5 ) ;
m_tv_channels = new wxChoice ( box , wxID_ANY , wxDefaultPosition , wxDefaultSize , std : : size ( audio_channel_choices ) , audio_channel_choices ) ;
m_tv_channels - > SetSelection ( 1 ) ; // set default to stereo
m_tv_channels - > Bind ( wxEVT_CHOICE , & GeneralSettings2 : : OnAudioChannelsSelected , this ) ;
audio_tv_row - > Add ( m_tv_channels , 0 , wxEXPAND | wxALL , 5 ) ;
audio_tv_row - > AddSpacer ( 0 ) ;
audio_tv_row - > Add ( new wxStaticText ( box , wxID_ANY , _ ( " Volume " ) ) , 0 , wxALIGN_CENTER_VERTICAL | wxALL , 5 ) ;
m_tv_volume = new wxSlider ( box , wxID_ANY , 100 , 0 , 100 , wxDefaultPosition , wxDefaultSize , wxSL_HORIZONTAL ) ;
audio_tv_row - > Add ( m_tv_volume , 0 , wxEXPAND | wxALL , 5 ) ;
auto audio_tv_volume_text = new wxStaticText ( box , wxID_ANY , wxT ( " 100% " ) ) ;
audio_tv_row - > Add ( audio_tv_volume_text , 0 , wxALIGN_CENTER_VERTICAL | wxALL | wxALIGN_RIGHT , 5 ) ;
m_tv_volume - > Bind ( wxEVT_SLIDER , & GeneralSettings2 : : OnSliderChangedPercent , this , wxID_ANY , wxID_ANY , new wxControlObject ( audio_tv_volume_text ) ) ;
m_tv_volume - > Bind ( wxEVT_SLIDER , & GeneralSettings2 : : OnVolumeChanged , this ) ;
box_sizer - > Add ( audio_tv_row , 1 , wxEXPAND , 5 ) ;
audio_panel_sizer - > Add ( box_sizer , 0 , wxEXPAND | wxALL , 5 ) ;
}
{
auto box = new wxStaticBox ( audio_panel , wxID_ANY , _ ( " Gamepad " ) ) ;
auto box_sizer = new wxStaticBoxSizer ( box , wxVERTICAL ) ;
auto audio_pad_row = new wxFlexGridSizer ( 0 , 3 , 0 , 0 ) ;
audio_pad_row - > SetFlexibleDirection ( wxBOTH ) ;
audio_pad_row - > SetNonFlexibleGrowMode ( wxFLEX_GROWMODE_SPECIFIED ) ;
audio_pad_row - > Add ( new wxStaticText ( box , wxID_ANY , _ ( " Device " ) ) , 0 , wxALIGN_CENTER_VERTICAL | wxALL , 5 ) ;
m_pad_device = new wxChoice ( box , wxID_ANY , wxDefaultPosition ) ;
m_pad_device - > SetMinSize ( wxSize ( 300 , - 1 ) ) ;
m_pad_device - > SetToolTip ( _ ( " Select the active audio output device for Wii U GamePad " ) ) ;
audio_pad_row - > Add ( m_pad_device , 0 , wxEXPAND | wxALL , 5 ) ;
audio_pad_row - > AddSpacer ( 0 ) ;
m_pad_device - > Bind ( wxEVT_CHOICE , & GeneralSettings2 : : OnAudioDeviceSelected , this ) ;
const wxString audio_channel_drc_choices [ ] = { _ ( " Stereo " ) } ; // stereo for now only
audio_pad_row - > Add ( new wxStaticText ( box , wxID_ANY , _ ( " Channels " ) ) , 0 , wxALIGN_CENTER_VERTICAL | wxALL , 5 ) ;
m_pad_channels = new wxChoice ( box , wxID_ANY , wxDefaultPosition , wxDefaultSize , std : : size ( audio_channel_drc_choices ) , audio_channel_drc_choices ) ;
m_pad_channels - > SetSelection ( 0 ) ; // set default to stereo
m_pad_channels - > Bind ( wxEVT_CHOICE , & GeneralSettings2 : : OnAudioChannelsSelected , this ) ;
audio_pad_row - > Add ( m_pad_channels , 0 , wxEXPAND | wxALL , 5 ) ;
audio_pad_row - > AddSpacer ( 0 ) ;
audio_pad_row - > Add ( new wxStaticText ( box , wxID_ANY , _ ( " Volume " ) ) , 0 , wxALIGN_CENTER_VERTICAL | wxALL , 5 ) ;
m_pad_volume = new wxSlider ( box , wxID_ANY , 100 , 0 , 100 ) ;
audio_pad_row - > Add ( m_pad_volume , 0 , wxEXPAND | wxALL , 5 ) ;
auto audio_pad_volume_text = new wxStaticText ( box , wxID_ANY , wxT ( " 100% " ) ) ;
audio_pad_row - > Add ( audio_pad_volume_text , 0 , wxALIGN_CENTER_VERTICAL | wxALL | wxALIGN_RIGHT , 5 ) ;
m_pad_volume - > Bind ( wxEVT_SLIDER , & GeneralSettings2 : : OnSliderChangedPercent , this , wxID_ANY , wxID_ANY , new wxControlObject ( audio_pad_volume_text ) ) ;
m_pad_volume - > Bind ( wxEVT_SLIDER , & GeneralSettings2 : : OnVolumeChanged , this ) ;
box_sizer - > Add ( audio_pad_row , 1 , wxEXPAND , 5 ) ;
audio_panel_sizer - > Add ( box_sizer , 0 , wxEXPAND | wxALL , 5 ) ;
}
audio_panel - > SetSizerAndFit ( audio_panel_sizer ) ;
return audio_panel ;
}
wxPanel * GeneralSettings2 : : AddOverlayPage ( wxNotebook * notebook )
{
auto * panel = new wxPanel ( notebook , wxID_ANY , wxDefaultPosition , wxDefaultSize , wxTAB_TRAVERSAL ) ;
auto * panel_sizer = new wxBoxSizer ( wxVERTICAL ) ;
const wxString positions [ ] { _ ( " Disabled " ) , _ ( " Top left " ) , _ ( " Top center " ) , _ ( " Top right " ) , _ ( " Bottom left " ) , _ ( " Bottom center " ) , _ ( " Bottom right " ) } ;
const wxString text_scale [ ] { " 50% " , " 75% " , " 100% " , " 125% " , " 150% " , " 175% " , " 200% " , " 225% " , " 250% " , " 275% " , " 300% " } ;
{
auto box = new wxStaticBox ( panel , wxID_ANY , _ ( " Overlay " ) ) ;
auto box_sizer = new wxStaticBoxSizer ( box , wxVERTICAL ) ;
auto position_row = new wxFlexGridSizer ( 1 , 0 , 0 , 0 ) ;
position_row - > SetFlexibleDirection ( wxBOTH ) ;
position_row - > SetNonFlexibleGrowMode ( wxFLEX_GROWMODE_SPECIFIED ) ;
{
position_row - > Add ( new wxStaticText ( box , wxID_ANY , _ ( " Position " ) ) , 0 , wxALL | wxALIGN_CENTER_VERTICAL , 5 ) ;
m_overlay_position = new wxChoice ( box , wxID_ANY , wxDefaultPosition , wxDefaultSize , std : : size ( positions ) , positions ) ;
m_overlay_position - > SetSelection ( 0 ) ;
m_overlay_position - > SetToolTip ( _ ( " Controls the overlay which displays technical information while playing " ) ) ;
position_row - > Add ( m_overlay_position , 0 , wxALL , 5 ) ;
position_row - > AddSpacer ( 25 ) ;
position_row - > Add ( new wxStaticText ( box , wxID_ANY , _ ( " Text Color " ) ) , 0 , wxALL | wxALIGN_CENTRE_VERTICAL , 5 ) ;
m_overlay_font_color = new wxColourPickerCtrl ( box , wxID_ANY , * wxWHITE , wxDefaultPosition , wxDefaultSize , wxCLRP_SHOW_ALPHA ) ;
m_overlay_font_color - > SetToolTip ( _ ( " Sets the text color of the overlay " ) ) ;
position_row - > Add ( m_overlay_font_color , 0 , wxEXPAND | wxALL , 5 ) ;
position_row - > AddSpacer ( 25 ) ;
position_row - > Add ( new wxStaticText ( box , wxID_ANY , _ ( " Scale " ) ) , 0 , wxALL | wxALIGN_CENTRE_VERTICAL , 5 ) ;
m_overlay_scale = new wxChoice ( box , wxID_ANY , wxDefaultPosition , wxDefaultSize , std : : size ( text_scale ) , text_scale ) ;
m_overlay_scale - > SetToolTip ( _ ( " Sets the scale of the overlay text " ) ) ;
position_row - > Add ( m_overlay_scale , 0 , wxEXPAND | wxALL , 5 ) ;
}
box_sizer - > Add ( position_row , 0 , wxEXPAND , 5 ) ;
auto settings2_row = new wxFlexGridSizer ( 0 , 4 , 2 , 0 ) ;
{
m_overlay_fps = new wxCheckBox ( box , wxID_ANY , _ ( " FPS " ) ) ;
m_overlay_fps - > SetToolTip ( _ ( " The number of frames per second. Average over last 5 seconds " ) ) ;
settings2_row - > Add ( m_overlay_fps , 0 , wxALL , 5 ) ;
m_overlay_drawcalls = new wxCheckBox ( box , wxID_ANY , _ ( " Draw calls per frame " ) ) ;
m_overlay_drawcalls - > SetToolTip ( _ ( " The number of draw calls per frame. Average over last 5 seconds " ) ) ;
settings2_row - > Add ( m_overlay_drawcalls , 0 , wxALL , 5 ) ;
m_overlay_cpu = new wxCheckBox ( box , wxID_ANY , _ ( " CPU usage " ) ) ;
m_overlay_cpu - > SetToolTip ( _ ( " CPU usage of Cemu in percent " ) ) ;
settings2_row - > Add ( m_overlay_cpu , 0 , wxALL , 5 ) ;
m_overlay_cpu_per_core = new wxCheckBox ( box , wxID_ANY , _ ( " CPU per core usage " ) ) ;
m_overlay_cpu_per_core - > SetToolTip ( _ ( " Total cpu usage in percent for each core " ) ) ;
settings2_row - > Add ( m_overlay_cpu_per_core , 0 , wxALL , 5 ) ;
m_overlay_ram = new wxCheckBox ( box , wxID_ANY , _ ( " RAM usage " ) ) ;
m_overlay_ram - > SetToolTip ( _ ( " Cemu RAM usage in MB " ) ) ;
settings2_row - > Add ( m_overlay_ram , 0 , wxALL , 5 ) ;
m_overlay_vram = new wxCheckBox ( box , wxID_ANY , _ ( " VRAM usage " ) ) ;
# if BOOST_OS_WINDOWS
using RtlGetVersion_t = LONG ( WINAPI * ) ( PRTL_OSVERSIONINFOW lpVersionInformation ) ;
const auto pRtlGetVersion = ( RtlGetVersion_t ) GetProcAddress ( GetModuleHandleA ( " ntdll.dll " ) , " RtlGetVersion " ) ;
//if(IsWindows8Point1OrGreater()) requires manifest
RTL_OSVERSIONINFOW info { } ;
// Windows 8.1 6.3*
if ( pRtlGetVersion & & pRtlGetVersion ( & info ) = = 0 & & ( ( info . dwMajorVersion = = 6 & & info . dwMinorVersion > = 3 ) | | info . dwMajorVersion > 6 ) )
m_overlay_vram - > SetToolTip ( _ ( " The VRAM usage of Cemu in MB " ) ) ;
else
{
m_overlay_vram - > SetToolTip ( _ ( " This option requires Win8.1+ " ) ) ;
m_overlay_vram - > Disable ( ) ;
}
# else
m_overlay_vram - > SetToolTip ( _ ( " The VRAM usage of Cemu in MB " ) ) ;
# endif
settings2_row - > Add ( m_overlay_vram , 0 , wxALL , 5 ) ;
m_overlay_debug = new wxCheckBox ( box , wxID_ANY , _ ( " Debug " ) ) ;
m_overlay_debug - > SetToolTip ( _ ( " Displays internal debug information (Vulkan only) " ) ) ;
settings2_row - > Add ( m_overlay_debug , 0 , wxALL , 5 ) ;
}
box_sizer - > Add ( settings2_row , 0 , wxEXPAND , 5 ) ;
panel_sizer - > Add ( box_sizer , 0 , wxEXPAND | wxALL , 5 ) ;
}
{
auto box = new wxStaticBox ( panel , wxID_ANY , _ ( " Notifications " ) ) ;
auto box_sizer = new wxStaticBoxSizer ( box , wxVERTICAL ) ;
auto position_row = new wxFlexGridSizer ( 1 , 0 , 0 , 0 ) ;
position_row - > SetFlexibleDirection ( wxBOTH ) ;
position_row - > SetNonFlexibleGrowMode ( wxFLEX_GROWMODE_SPECIFIED ) ;
{
position_row - > Add ( new wxStaticText ( box , wxID_ANY , _ ( " Position " ) ) , 0 , wxALL | wxALIGN_CENTER_VERTICAL , 5 ) ;
m_notification_position = new wxChoice ( box , wxID_ANY , wxDefaultPosition , wxDefaultSize , std : : size ( positions ) , positions ) ;
m_notification_position - > SetSelection ( 0 ) ;
m_notification_position - > SetToolTip ( _ ( " Controls the notification position while playing " ) ) ;
position_row - > Add ( m_notification_position , 0 , wxALL , 5 ) ;
position_row - > AddSpacer ( 25 ) ;
position_row - > Add ( new wxStaticText ( box , wxID_ANY , _ ( " Text Color " ) ) , 0 , wxALL | wxALIGN_CENTRE_VERTICAL , 5 ) ;
m_notification_font_color = new wxColourPickerCtrl ( box , wxID_ANY , * wxWHITE , wxDefaultPosition , wxDefaultSize , wxCLRP_SHOW_ALPHA ) ;
m_notification_font_color - > SetToolTip ( _ ( " Sets the text color of notifications " ) ) ;
position_row - > Add ( m_notification_font_color , 0 , wxEXPAND | wxALL , 5 ) ;
position_row - > Add ( new wxStaticText ( box , wxID_ANY , _ ( " Scale " ) ) , 0 , wxALL | wxALIGN_CENTRE_VERTICAL , 5 ) ;
m_notification_scale = new wxChoice ( box , wxID_ANY , wxDefaultPosition , wxDefaultSize , std : : size ( text_scale ) , text_scale ) ;
m_notification_scale - > SetToolTip ( _ ( " Sets the scale of the notification text " ) ) ;
position_row - > Add ( m_notification_scale , 0 , wxEXPAND | wxALL , 5 ) ;
}
box_sizer - > Add ( position_row , 0 , wxEXPAND , 5 ) ;
auto settings1_row = new wxFlexGridSizer ( 1 , 0 , 2 , 0 ) ;
{
m_controller_profile_name = new wxCheckBox ( box , wxID_ANY , _ ( " Controller profiles " ) ) ;
m_controller_profile_name - > SetToolTip ( _ ( " Displays the active controller profile when starting a game " ) ) ;
settings1_row - > Add ( m_controller_profile_name , 0 , wxALL , 5 ) ;
m_controller_low_battery = new wxCheckBox ( box , wxID_ANY , _ ( " Low battery " ) ) ;
m_controller_low_battery - > SetToolTip ( _ ( " Shows a notification when a low controller battery has been detected " ) ) ;
settings1_row - > Add ( m_controller_low_battery , 0 , wxALL , 5 ) ;
m_shader_compiling = new wxCheckBox ( box , wxID_ANY , _ ( " Shader compiler " ) ) ;
m_shader_compiling - > SetToolTip ( _ ( " Shows a notification after shaders have been compiled " ) ) ;
settings1_row - > Add ( m_shader_compiling , 0 , wxALL , 5 ) ;
m_friends_data = new wxCheckBox ( box , wxID_ANY , _ ( " Friend list " ) ) ;
m_friends_data - > SetToolTip ( _ ( " Shows friend list related data if online " ) ) ;
settings1_row - > Add ( m_friends_data , 0 , wxALL , 5 ) ;
}
box_sizer - > Add ( settings1_row , 0 , wxEXPAND , 5 ) ;
panel_sizer - > Add ( box_sizer , 0 , wxEXPAND | wxALL , 5 ) ;
}
panel - > SetSizerAndFit ( panel_sizer ) ;
return panel ;
}
wxPanel * GeneralSettings2 : : AddAccountPage ( wxNotebook * notebook )
{
auto * online_panel = new wxPanel ( notebook ) ;
auto * online_panel_sizer = new wxBoxSizer ( wxVERTICAL ) ;
{
auto * box = new wxStaticBox ( online_panel , wxID_ANY , _ ( " Account settings " ) ) ;
auto * box_sizer = new wxStaticBoxSizer ( box , wxVERTICAL ) ;
auto * content = new wxFlexGridSizer ( 0 , 4 , 0 , 0 ) ;
content - > SetFlexibleDirection ( wxBOTH ) ;
content - > SetNonFlexibleGrowMode ( wxFLEX_GROWMODE_SPECIFIED ) ;
content - > AddGrowableCol ( 1 , 1 ) ;
content - > AddGrowableCol ( 2 , 0 ) ;
content - > AddGrowableCol ( 3 , 0 ) ;
content - > Add ( new wxStaticText ( box , wxID_ANY , _ ( " Active account " ) ) , 1 , wxALIGN_CENTER_VERTICAL | wxALL , 5 ) ;
m_active_account = new wxChoice ( box , wxID_ANY ) ;
m_active_account - > SetMinSize ( { 250 , - 1 } ) ;
content - > Add ( m_active_account , 0 , wxEXPAND | wxALL , 5 ) ;
m_active_account - > Bind ( wxEVT_CHOICE , & GeneralSettings2 : : OnActiveAccountChanged , this ) ;
m_create_account = new wxButton ( box , wxID_ANY , _ ( " Create " ) ) ;
content - > Add ( m_create_account , 0 , wxEXPAND | wxALL | wxALIGN_RIGHT , 5 ) ;
m_create_account - > Bind ( wxEVT_BUTTON , & GeneralSettings2 : : OnAccountCreate , this ) ;
m_delete_account = new wxButton ( box , wxID_ANY , _ ( " Delete " ) ) ;
content - > Add ( m_delete_account , 0 , wxEXPAND | wxALL | wxALIGN_RIGHT , 5 ) ;
m_delete_account - > Bind ( wxEVT_BUTTON , & GeneralSettings2 : : OnAccountDelete , this ) ;
box_sizer - > Add ( content , 1 , wxEXPAND , 5 ) ;
online_panel_sizer - > Add ( box_sizer , 0 , wxEXPAND | wxALL , 5 ) ;
if ( CafeSystem : : IsTitleRunning ( ) )
{
m_active_account - > Enable ( false ) ;
m_create_account - > Enable ( false ) ;
m_delete_account - > Enable ( false ) ;
}
}
{
auto * box = new wxStaticBox ( online_panel , wxID_ANY , _ ( " Online settings " ) ) ;
auto * box_sizer = new wxStaticBoxSizer ( box , wxVERTICAL ) ;
m_online_enabled = new wxCheckBox ( box , wxID_ANY , _ ( " Enable online mode " ) ) ;
m_online_enabled - > Bind ( wxEVT_CHECKBOX , & GeneralSettings2 : : OnOnlineEnable , this ) ;
box_sizer - > Add ( m_online_enabled , 0 , wxEXPAND | wxALL , 5 ) ;
auto * row = new wxFlexGridSizer ( 0 , 2 , 0 , 0 ) ;
row - > SetFlexibleDirection ( wxBOTH ) ;
row - > SetNonFlexibleGrowMode ( wxFLEX_GROWMODE_SPECIFIED ) ;
const wxImage tmp = wxBITMAP_PNG ( PNG_ERROR ) . ConvertToImage ( ) ;
m_validate_online = new wxBitmapButton ( box , wxID_ANY , tmp . Scale ( 16 , 16 ) ) ;
m_validate_online - > Bind ( wxEVT_BUTTON , & GeneralSettings2 : : OnShowOnlineValidator , this ) ;
row - > Add ( m_validate_online , 0 , wxEXPAND | wxALL , 5 ) ;
m_online_status = new wxStaticText ( box , wxID_ANY , _ ( " No account selected " ) ) ;
row - > Add ( m_online_status , 1 , wxALL | wxALIGN_CENTRE_VERTICAL , 5 ) ;
box_sizer - > Add ( row , 1 , wxEXPAND , 5 ) ;
auto * tutorial_link = new wxHyperlinkCtrl ( box , wxID_ANY , _ ( " Online play tutorial " ) , " https://cemu.info/online-guide " ) ;
box_sizer - > Add ( tutorial_link , 0 , wxALL , 5 ) ;
online_panel_sizer - > Add ( box_sizer , 0 , wxEXPAND | wxALL , 5 ) ;
}
{
m_account_information = new wxCollapsiblePane ( online_panel , wxID_ANY , _ ( " Account information " ) ) ;
2022-08-26 04:03:26 +02:00
# if BOOST_OS_WINDOWS
2022-08-22 22:21:23 +02:00
m_account_information - > GetControlWidget ( ) - > SetBackgroundColour ( * wxWHITE ) ;
# endif
auto win = m_account_information - > GetPane ( ) ;
auto content = new wxBoxSizer ( wxVERTICAL ) ;
m_account_grid = new wxPropertyGrid ( win , wxID_ANY , wxDefaultPosition , wxDefaultSize , wxPG_HIDE_MARGIN | wxPG_STATIC_SPLITTER ) ;
m_account_grid - > SetExtraStyle ( wxPG_EX_HELP_AS_TOOLTIPS ) ;
m_account_grid - > SetMinSize ( { 300 , - 1 } ) ;
//m_account_grid->Append(new wxPropertyCategory("Main"));
auto * persistent_id_gprop = m_account_grid - > Append ( new wxStringProperty ( wxT ( " PersistentId " ) , kPropertyPersistentId ) ) ;
persistent_id_gprop - > SetHelpString ( _ ( " The persistent id is the internal folder name used for your saves " ) ) ;
m_account_grid - > SetPropertyReadOnly ( persistent_id_gprop ) ;
m_account_grid - > Append ( new wxStringProperty ( _ ( " Mii name " ) , kPropertyMiiName ) ) - > SetHelpString ( _ ( " The mii name is the profile name " ) ) ;
m_account_grid - > Append ( new wxStringProperty ( _ ( " Birthday " ) , kPropertyBirthday ) ) ;
wxPGChoices gender ;
gender . Add ( _ ( " Female " ) , 0 ) ;
gender . Add ( _ ( " Male " ) , 1 ) ;
m_account_grid - > Append ( new wxEnumProperty ( " Gender " , kPropertyGender , gender ) ) ;
m_account_grid - > Append ( new wxStringProperty ( _ ( " Email " ) , kPropertyEmail ) ) ;
wxPGChoices countries ;
for ( int i = 0 ; i < 195 ; + + i )
{
const auto country = NCrypto : : GetCountryAsString ( i ) ;
if ( country & & ( i = = 0 | | ! boost : : equals ( country , " NN " ) ) )
{
countries . Add ( country , i ) ;
}
}
m_account_grid - > Append ( new wxEnumProperty ( _ ( " Country " ) , kPropertyCountry , countries ) ) ;
m_account_grid - > Bind ( wxEVT_PG_CHANGED , & GeneralSettings2 : : OnAccountSettingsChanged , this ) ;
content - > Add ( m_account_grid , 1 , wxEXPAND | wxALL , 5 ) ;
win - > SetSizer ( content ) ;
content - > SetSizeHints ( win ) ;
online_panel_sizer - > Add ( m_account_information , 0 , wxEXPAND | wxALL , 5 ) ;
}
online_panel - > SetSizerAndFit ( online_panel_sizer ) ;
return online_panel ;
}
wxPanel * GeneralSettings2 : : AddDebugPage ( wxNotebook * notebook )
{
auto * panel = new wxPanel ( notebook , wxID_ANY , wxDefaultPosition , wxDefaultSize , wxTAB_TRAVERSAL ) ;
auto * debug_panel_sizer = new wxBoxSizer ( wxVERTICAL ) ;
auto * debug_row = new wxFlexGridSizer ( 0 , 2 , 0 , 0 ) ;
debug_row - > SetFlexibleDirection ( wxBOTH ) ;
debug_row - > SetNonFlexibleGrowMode ( wxFLEX_GROWMODE_SPECIFIED ) ;
debug_row - > Add ( new wxStaticText ( panel , wxID_ANY , _ ( " Crash dump " ) , wxDefaultPosition , wxDefaultSize , 0 ) , 0 , wxALIGN_CENTER_VERTICAL | wxALL , 5 ) ;
wxString dump_choices [ ] = { _ ( " Disabled " ) , _ ( " Lite " ) , _ ( " Full " ) } ;
m_crash_dump = new wxChoice ( panel , wxID_ANY , wxDefaultPosition , wxDefaultSize , std : : size ( dump_choices ) , dump_choices ) ;
m_crash_dump - > SetSelection ( 0 ) ;
m_crash_dump - > SetToolTip ( _ ( " Creates a dump when Cemu crashes \n Only enable when requested by a developer! \n The Full option will create a very large dump file (includes a full RAM dump of the Cemu process) " ) ) ;
debug_row - > Add ( m_crash_dump , 0 , wxALL | wxEXPAND , 5 ) ;
debug_panel_sizer - > Add ( debug_row , 0 , wxALL | wxEXPAND , 5 ) ;
panel - > SetSizerAndFit ( debug_panel_sizer ) ;
return panel ;
}
GeneralSettings2 : : GeneralSettings2 ( wxWindow * parent , bool game_launched )
: wxDialog ( parent , wxID_ANY , _ ( " General settings " ) , wxDefaultPosition , wxDefaultSize , wxCLOSE_BOX | wxCLIP_CHILDREN | wxCAPTION | wxRESIZE_BORDER ) , m_game_launched ( game_launched )
{
SetIcon ( wxICON ( X_SETTINGS ) ) ;
auto * sizer = new wxBoxSizer ( wxVERTICAL ) ;
auto * notebook = new wxNotebook ( this , wxID_ANY ) ;
notebook - > AddPage ( AddGeneralPage ( notebook ) , _ ( " General " ) ) ;
notebook - > AddPage ( AddGraphicsPage ( notebook ) , _ ( " Graphics " ) ) ;
notebook - > AddPage ( AddAudioPage ( notebook ) , _ ( " Audio " ) ) ;
notebook - > AddPage ( AddOverlayPage ( notebook ) , _ ( " Overlay " ) ) ;
notebook - > AddPage ( AddAccountPage ( notebook ) , _ ( " Account " ) ) ;
notebook - > AddPage ( AddDebugPage ( notebook ) , _ ( " Debug " ) ) ;
Bind ( wxEVT_CLOSE_WINDOW , & GeneralSettings2 : : OnClose , this ) ;
//
sizer - > Add ( notebook , 1 , wxEXPAND | wxALL , 5 ) ;
SetSizerAndFit ( sizer ) ;
Layout ( ) ;
Centre ( wxBOTH ) ;
//
UpdateOnlineAccounts ( ) ;
UpdateAudioDeviceList ( ) ;
ApplyConfig ( ) ;
HandleGraphicsApiSelection ( ) ;
DisableSettings ( game_launched ) ;
}
void GeneralSettings2 : : StoreConfig ( )
{
auto * app = ( CemuApp * ) wxTheApp ;
auto & config = GetConfig ( ) ;
config . use_discord_presence = m_discord_presence - > IsChecked ( ) ;
config . fullscreen_menubar = m_fullscreen_menubar - > IsChecked ( ) ;
config . check_update = m_auto_update - > IsChecked ( ) ;
config . save_screenshot = m_save_screenshot - > IsChecked ( ) ;
const bool use_ps = m_permanent_storage - > IsChecked ( ) ;
if ( use_ps )
{
config . permanent_storage = use_ps ;
try
{
PermanentStorage storage ;
storage . RemoveStorage ( ) ;
}
catch ( . . . ) { }
}
else
{
try
{
// delete permanent storage
PermanentStorage storage ;
storage . RemoveStorage ( ) ;
}
catch ( . . . ) { }
config . permanent_storage = use_ps ;
}
if ( ! LaunchSettings : : GetMLCPath ( ) . has_value ( ) )
config . SetMLCPath ( m_mlc_path - > GetValue ( ) . ToStdWstring ( ) , false ) ;
// -1 is default wx widget value -> set to dummy 0 so mainwindow and padwindow will update it
config . window_position = m_save_window_position_size - > IsChecked ( ) ? Vector2i { 0 , 0 } : Vector2i { - 1 , - 1 } ;
config . window_size = m_save_window_position_size - > IsChecked ( ) ? Vector2i { 0 , 0 } : Vector2i { - 1 , - 1 } ;
config . pad_position = m_save_padwindow_position_size - > IsChecked ( ) ? Vector2i { 0 , 0 } : Vector2i { - 1 , - 1 } ;
config . pad_size = m_save_padwindow_position_size - > IsChecked ( ) ? Vector2i { 0 , 0 } : Vector2i { - 1 , - 1 } ;
config . game_paths . clear ( ) ;
for ( auto & path : m_game_paths - > GetStrings ( ) )
config . game_paths . emplace_back ( path ) ;
auto selection = m_language - > GetSelection ( ) ;
if ( selection = = 0 )
GetConfig ( ) . language = wxLANGUAGE_DEFAULT ;
else if ( selection = = 1 )
GetConfig ( ) . language = wxLANGUAGE_ENGLISH ;
else
{
const auto language = m_language - > GetStringSelection ( ) ;
for ( const auto & lang : app - > GetLanguages ( ) )
{
if ( lang - > Description = = language )
{
GetConfig ( ) . language = lang - > Language ;
break ;
}
}
}
// audio
if ( m_audio_api - > GetStringSelection ( ) = = kDirectSound )
config . audio_api = IAudioAPI : : DirectSound ;
else if ( m_audio_api - > GetStringSelection ( ) = = kXAudio27 )
config . audio_api = IAudioAPI : : XAudio27 ;
else if ( m_audio_api - > GetStringSelection ( ) = = kXAudio2 )
config . audio_api = IAudioAPI : : XAudio2 ;
else if ( m_audio_api - > GetStringSelection ( ) = = kCubeb )
config . audio_api = IAudioAPI : : Cubeb ;
config . audio_delay = m_audio_latency - > GetValue ( ) ;
config . tv_channels = ( AudioChannels ) m_tv_channels - > GetSelection ( ) ;
//config.pad_channels = (AudioChannels)m_pad_channels->GetSelection();
config . pad_channels = kStereo ; // (AudioChannels)m_pad_channels->GetSelection();
config . tv_volume = m_tv_volume - > GetValue ( ) ;
config . pad_volume = m_pad_volume - > GetValue ( ) ;
2022-09-17 03:45:18 +02:00
config . tv_device . clear ( ) ;
2022-08-22 22:21:23 +02:00
const auto tv_device = m_tv_device - > GetSelection ( ) ;
if ( tv_device ! = wxNOT_FOUND & & tv_device ! = 0 & & m_tv_device - > HasClientObjectData ( ) )
{
const auto * device_description = ( wxDeviceDescription * ) m_tv_device - > GetClientObject ( tv_device ) ;
if ( device_description )
config . tv_device = device_description - > GetDescription ( ) - > GetIdentifier ( ) ;
}
2022-09-17 03:45:18 +02:00
config . pad_device . clear ( ) ;
2022-08-22 22:21:23 +02:00
const auto pad_device = m_pad_device - > GetSelection ( ) ;
if ( pad_device ! = wxNOT_FOUND & & pad_device ! = 0 & & m_pad_device - > HasClientObjectData ( ) )
{
const auto * device_description = ( wxDeviceDescription * ) m_pad_device - > GetClientObject ( pad_device ) ;
if ( device_description )
config . pad_device = device_description - > GetDescription ( ) - > GetIdentifier ( ) ;
}
// graphics
config . graphic_api = ( GraphicAPI ) m_graphic_api - > GetSelection ( ) ;
selection = m_graphic_device - > GetSelection ( ) ;
if ( selection ! = wxNOT_FOUND )
{
const auto * info = ( wxVulkanUUID * ) m_graphic_device - > GetClientObject ( selection ) ;
if ( info )
config . graphic_device_uuid = info - > GetDeviceInfo ( ) . uuid ;
else
config . graphic_device_uuid = { } ;
}
else
config . graphic_device_uuid = { } ;
config . vsync = m_vsync - > GetSelection ( ) ;
config . gx2drawdone_sync = m_gx2drawdone_sync - > IsChecked ( ) ;
config . async_compile = m_async_compile - > IsChecked ( ) ;
config . upscale_filter = m_upscale_filter - > GetSelection ( ) ;
config . downscale_filter = m_downscale_filter - > GetSelection ( ) ;
config . fullscreen_scaling = m_fullscreen_scaling - > GetSelection ( ) ;
config . overlay . position = ( ScreenPosition ) m_overlay_position - > GetSelection ( ) ; wxASSERT ( ( int ) config . overlay . position < = ( int ) ScreenPosition : : kBottomRight ) ;
config . overlay . text_color = m_overlay_font_color - > GetColour ( ) . GetRGBA ( ) ;
config . overlay . text_scale = m_overlay_scale - > GetSelection ( ) * 25 + 50 ;
config . overlay . fps = m_overlay_fps - > GetValue ( ) ;
config . overlay . drawcalls = m_overlay_drawcalls - > GetValue ( ) ;
config . overlay . cpu_usage = m_overlay_cpu - > GetValue ( ) ;
config . overlay . cpu_per_core_usage = m_overlay_cpu_per_core - > GetValue ( ) ;
config . overlay . ram_usage = m_overlay_ram - > GetValue ( ) ;
config . overlay . vram_usage = m_overlay_vram - > GetValue ( ) ;
config . overlay . debug = m_overlay_debug - > GetValue ( ) ;
config . notification . position = ( ScreenPosition ) m_notification_position - > GetSelection ( ) ; wxASSERT ( ( int ) config . notification . position < = ( int ) ScreenPosition : : kBottomRight ) ;
config . notification . text_color = m_notification_font_color - > GetColour ( ) . GetRGBA ( ) ;
config . notification . text_scale = m_notification_scale - > GetSelection ( ) * 25 + 50 ;
config . notification . controller_profiles = m_controller_profile_name - > GetValue ( ) ;
config . notification . controller_battery = m_controller_low_battery - > GetValue ( ) ;
config . notification . shader_compiling = m_shader_compiling - > GetValue ( ) ;
config . notification . friends = m_friends_data - > GetValue ( ) ;
// account
const auto active_account = m_active_account - > GetSelection ( ) ;
if ( active_account = = wxNOT_FOUND )
config . account . m_persistent_id = config . account . m_persistent_id . GetInitValue ( ) ;
else
config . account . m_persistent_id = dynamic_cast < wxAccountData * > ( m_active_account - > GetClientObject ( active_account ) ) - > GetAccount ( ) . GetPersistentId ( ) ;
config . account . online_enabled = m_online_enabled - > GetValue ( ) ;
// debug
config . crash_dump = ( CrashDump ) m_crash_dump - > GetSelection ( ) ;
g_config . Save ( ) ;
}
GeneralSettings2 : : ~ GeneralSettings2 ( )
{
Unbind ( wxEVT_CLOSE_WINDOW , & GeneralSettings2 : : OnClose , this ) ;
}
void GeneralSettings2 : : OnClose ( wxCloseEvent & event )
{
StoreConfig ( ) ;
if ( m_has_account_change )
{
wxCommandEvent refresh_event ( wxEVT_ACCOUNTLIST_REFRESH ) ;
GetParent ( ) - > ProcessWindowEvent ( refresh_event ) ;
}
event . Skip ( ) ;
}
void GeneralSettings2 : : ValidateConfig ( )
{
g_config . Load ( ) ;
auto & data = g_config . data ( ) ;
// todo
//data.fullscreen_scaling = min(max(data.fullscreen_scaling,))
}
void GeneralSettings2 : : DisableSettings ( bool game_launched )
{
}
void GeneralSettings2 : : OnAudioLatencyChanged ( wxCommandEvent & event )
{
IAudioAPI : : s_audioDelay = event . GetInt ( ) ;
event . Skip ( ) ;
}
void GeneralSettings2 : : OnVolumeChanged ( wxCommandEvent & event )
{
std : : shared_lock lock ( g_audioMutex ) ;
if ( event . GetEventObject ( ) = = m_pad_volume )
{
if ( g_padAudio )
{
g_padAudio - > SetVolume ( event . GetInt ( ) ) ;
g_padVolume = event . GetInt ( ) ;
}
}
else
{
if ( g_tvAudio )
g_tvAudio - > SetVolume ( event . GetInt ( ) ) ;
}
event . Skip ( ) ;
}
void GeneralSettings2 : : OnInputVolumeChanged ( wxCommandEvent & event )
{
std : : shared_lock lock ( g_audioMutex ) ;
if ( g_padAudio )
{
g_padAudio - > SetInputVolume ( event . GetInt ( ) ) ;
g_padVolume = event . GetInt ( ) ;
}
event . Skip ( ) ;
}
void GeneralSettings2 : : OnSliderChangedPercent ( wxCommandEvent & event )
{
const auto slider = dynamic_cast < wxSlider * > ( event . GetEventObject ( ) ) ;
wxASSERT ( slider ) ;
const auto control = dynamic_cast < wxControlObject * > ( event . GetEventUserData ( ) ) ;
wxASSERT ( control ) ;
auto slider_text = control - > GetControl < wxStaticText > ( ) ;
wxASSERT ( slider_text ) ;
const auto value = event . GetInt ( ) ;
slider - > SetValue ( value ) ;
slider_text - > SetLabel ( wxString : : Format ( " %d%% " , value ) ) ;
event . Skip ( ) ;
}
void GeneralSettings2 : : OnLatencySliderChanged ( wxCommandEvent & event )
{
const auto slider = dynamic_cast < wxSlider * > ( event . GetEventObject ( ) ) ;
wxASSERT ( slider ) ;
const auto control = dynamic_cast < wxControlObject * > ( event . GetEventUserData ( ) ) ;
wxASSERT ( control ) ;
auto slider_text = control - > GetControl < wxStaticText > ( ) ;
wxASSERT ( slider_text ) ;
const auto value = event . GetInt ( ) ;
slider - > SetValue ( value ) ;
slider_text - > SetLabel ( wxString : : Format ( " %dms " , value * 12 ) ) ;
event . Skip ( ) ;
}
void GeneralSettings2 : : UpdateAudioDeviceList ( )
{
m_tv_device - > Clear ( ) ;
m_pad_device - > Clear ( ) ;
m_tv_device - > Append ( _ ( " Disabled " ) ) ;
m_pad_device - > Append ( _ ( " Disabled " ) ) ;
const auto audio_api = ( IAudioAPI : : AudioAPI ) GetConfig ( ) . audio_api ;
const auto devices = IAudioAPI : : GetDevices ( audio_api ) ;
for ( auto & device : devices )
{
m_tv_device - > Append ( device - > GetName ( ) , new wxDeviceDescription ( device ) ) ;
m_pad_device - > Append ( device - > GetName ( ) , new wxDeviceDescription ( device ) ) ;
}
if ( m_tv_device - > GetCount ( ) > 1 )
m_tv_device - > SetSelection ( 1 ) ;
else
m_tv_device - > SetSelection ( 0 ) ;
m_pad_device - > SetSelection ( 0 ) ;
// todo reset global instance of audio device
}
void GeneralSettings2 : : ResetAccountInformation ( )
{
m_account_grid - > SetSplitterPosition ( 100 ) ;
m_active_account - > SetSelection ( 0 ) ;
for ( auto it = m_account_grid - > GetIterator ( ) ; ! it . AtEnd ( ) ; + + it )
{
( * it ) - > SetValueToUnspecified ( ) ;
}
// refresh pane size
m_account_information - > InvalidateBestSize ( ) ;
2022-08-26 04:03:26 +02:00
# if BOOST_OS_WINDOWS
2022-08-22 22:21:23 +02:00
m_account_information - > OnStateChange ( GetBestSize ( ) ) ;
# endif
}
void GeneralSettings2 : : OnAccountCreate ( wxCommandEvent & event )
{
wxASSERT ( Account : : HasFreeAccountSlots ( ) ) ;
wxCreateAccountDialog dialog ( this ) ;
if ( dialog . ShowModal ( ) = = wxID_CANCEL )
return ;
Account account ( dialog . GetPersistentId ( ) , dialog . GetMiiName ( ) . ToStdWstring ( ) ) ;
account . Save ( ) ;
Account : : RefreshAccounts ( ) ;
const int index = m_active_account - > Append ( account . ToString ( ) , new wxAccountData ( account ) ) ;
// update ui
m_active_account - > SetSelection ( index ) ;
UpdateAccountInformation ( ) ;
m_create_account - > Enable ( m_active_account - > GetCount ( ) < 0xC ) ;
m_delete_account - > Enable ( m_active_account - > GetCount ( ) > 1 ) ;
// send main window event
wxASSERT ( GetParent ( ) ) ;
wxCommandEvent refresh_event ( wxEVT_ACCOUNTLIST_REFRESH ) ;
GetParent ( ) - > ProcessWindowEvent ( refresh_event ) ;
}
void GeneralSettings2 : : OnAccountDelete ( wxCommandEvent & event )
{
if ( m_active_account - > GetCount ( ) = = 1 )
{
wxMessageBox ( _ ( " Can't delete the only account! " ) , _ ( " Error " ) , wxOK | wxCENTRE | wxICON_ERROR , this ) ;
return ;
}
const auto selection = m_active_account - > GetSelection ( ) ;
wxASSERT ( selection ! = wxNOT_FOUND ) ;
auto * obj = dynamic_cast < wxAccountData * > ( m_active_account - > GetClientObject ( selection ) ) ;
wxASSERT ( obj ) ;
auto & account = obj - > GetAccount ( ) ;
const std : : wstring format_str = _ ( " Are you sure you want to delete the account {} with id {:x}? " ) . ToStdWstring ( ) ;
2022-09-05 14:48:44 +02:00
const std : : wstring msg = fmt : : format ( fmt : : runtime ( format_str ) ,
2022-08-22 22:21:23 +02:00
std : : wstring { account . GetMiiName ( ) } , account . GetPersistentId ( ) ) ;
const int answer = wxMessageBox ( msg , _ ( " Confirmation " ) , wxYES_NO | wxCENTRE | wxICON_QUESTION , this ) ;
if ( answer = = wxNO )
return ;
// todo: ask if saves should be deleted too?
const fs : : path path = account . GetFileName ( ) ;
try
{
fs : : remove_all ( path . parent_path ( ) ) ;
m_active_account - > Delete ( selection ) ;
m_active_account - > SetSelection ( 0 ) ;
Account : : RefreshAccounts ( ) ;
UpdateAccountInformation ( ) ;
m_create_account - > Enable ( m_active_account - > GetCount ( ) < 0xC ) ;
m_delete_account - > Enable ( m_active_account - > GetCount ( ) > 1 ) ;
}
catch ( const std : : exception & ex )
{
SystemException sys ( ex ) ;
forceLog_printf ( ( char * ) sys . what ( ) ) ;
}
}
void GeneralSettings2 : : OnAccountSettingsChanged ( wxPropertyGridEvent & event )
{
wxPGProperty * property = event . GetProperty ( ) ;
if ( ! property )
return ;
const wxAny value = property - > GetValue ( ) ;
if ( value . IsNull ( ) )
return ;
const auto selection = m_active_account - > GetSelection ( ) ;
wxASSERT ( selection ! = wxNOT_FOUND ) ;
auto * obj = dynamic_cast < wxAccountData * > ( m_active_account - > GetClientObject ( selection ) ) ;
wxASSERT ( obj ) ;
auto & account = obj - > GetAccount ( ) ;
// TODO make id changeable to free ids + current it?
bool refresh_accounts = false ;
if ( property - > GetName ( ) = = kPropertyMiiName )
{
std : : wstring new_name = value . As < wxString > ( ) . ToStdWstring ( ) ;
if ( new_name . empty ( ) )
new_name = L " default " ;
account . SetMiiName ( new_name ) ;
refresh_accounts = true ;
}
else if ( property - > GetName ( ) = = kPropertyBirthday )
{
const std : : string birthday = value . As < wxString > ( ) . ToStdString ( ) ;
const boost : : char_separator < char > sep { " - " } ;
std : : vector < std : : string > tokens ;
for ( const auto & token : boost : : tokenizer ( birthday , sep ) )
{
tokens . emplace_back ( token ) ;
}
if ( tokens . size ( ) = = 3 )
{
account . SetBirthYear ( ConvertString < uint16 > ( tokens [ 0 ] ) ) ;
account . SetBirthMonth ( ConvertString < uint8 > ( tokens [ 1 ] ) ) ;
account . SetBirthDay ( ConvertString < uint8 > ( tokens [ 2 ] ) ) ;
}
}
else if ( property - > GetName ( ) = = kPropertyGender )
{
account . SetGender ( value . As < int > ( ) ) ;
}
else if ( property - > GetName ( ) = = kPropertyEmail )
{
account . SetEmail ( value . As < wxString > ( ) . ToStdString ( ) ) ;
}
else if ( property - > GetName ( ) = = kPropertyCountry )
{
account . SetCountry ( value . As < int > ( ) ) ;
}
else
cemu_assert_debug ( false ) ;
account . Save ( ) ;
Account : : RefreshAccounts ( ) ; // refresh internal account list
UpdateAccountInformation ( ) ; // refresh on invalid values
if ( refresh_accounts )
{
wxCommandEvent refresh_event ( wxEVT_ACCOUNTLIST_REFRESH ) ;
GetParent ( ) - > ProcessWindowEvent ( refresh_event ) ;
}
}
void GeneralSettings2 : : UpdateAccountInformation ( )
{
m_account_grid - > SetSplitterPosition ( 100 ) ;
m_online_status - > SetLabel ( _ ( " At least one issue has been found " ) ) ;
const auto selection = m_active_account - > GetSelection ( ) ;
if ( selection = = wxNOT_FOUND )
{
m_validate_online - > SetBitmap ( wxBITMAP_PNG ( PNG_ERROR ) . ConvertToImage ( ) . Scale ( 16 , 16 ) ) ;
m_validate_online - > SetWindowStyleFlag ( m_validate_online - > GetWindowStyleFlag ( ) & ~ wxBORDER_NONE ) ;
ResetAccountInformation ( ) ;
return ;
}
const auto * obj = dynamic_cast < wxAccountData * > ( m_active_account - > GetClientObject ( selection ) ) ;
wxASSERT ( obj ) ;
const auto & account = obj - > GetAccount ( ) ;
m_active_account - > SetString ( selection , account . ToString ( ) ) ;
m_account_grid - > GetProperty ( kPropertyPersistentId ) - > SetValueFromString ( fmt : : format ( " {:x} " , account . GetPersistentId ( ) ) ) ;
m_account_grid - > GetProperty ( kPropertyMiiName ) - > SetValueFromString ( std : : wstring { account . GetMiiName ( ) } ) ;
m_account_grid - > GetProperty ( kPropertyBirthday ) - > SetValueFromString ( fmt : : format ( " {:04d}-{:02d}-{:02d} " , account . GetBirthYear ( ) , account . GetBirthMonth ( ) , account . GetBirthDay ( ) ) ) ;
const auto gender_property = m_account_grid - > GetProperty ( kPropertyGender ) ; // gender 2 can be also female?
gender_property - > SetChoiceSelection ( std : : min ( gender_property - > GetChoices ( ) . GetCount ( ) - 1 , ( uint32 ) account . GetGender ( ) ) ) ;
m_account_grid - > GetProperty ( kPropertyEmail ) - > SetValueFromString ( std : : string { account . GetEmail ( ) } ) ;
auto * country_property = dynamic_cast < wxEnumProperty * > ( m_account_grid - > GetProperty ( kPropertyCountry ) ) ;
wxASSERT ( country_property ) ;
int index = ( country_property ) - > GetIndexForValue ( account . GetCountry ( ) ) ;
if ( index = = wxNOT_FOUND )
index = 0 ;
country_property - > SetChoiceSelection ( index ) ;
const bool online_valid = account . IsValidOnlineAccount ( ) & & ActiveSettings : : HasRequiredOnlineFiles ( ) ;
if ( online_valid )
{
m_online_status - > SetLabel ( _ ( " Your account is a valid online account " ) ) ;
m_validate_online - > SetBitmap ( wxBITMAP_PNG ( PNG_CHECK_YES ) . ConvertToImage ( ) . Scale ( 16 , 16 ) ) ;
m_validate_online - > SetWindowStyleFlag ( m_validate_online - > GetWindowStyleFlag ( ) | wxBORDER_NONE ) ;
}
else
{
m_validate_online - > SetBitmap ( wxBITMAP_PNG ( PNG_ERROR ) . ConvertToImage ( ) . Scale ( 16 , 16 ) ) ;
m_validate_online - > SetWindowStyleFlag ( m_validate_online - > GetWindowStyleFlag ( ) & ~ wxBORDER_NONE ) ;
}
// refresh pane size
m_account_grid - > InvalidateBestSize ( ) ;
//m_account_grid->GetParent()->FitInside();
//m_account_information->OnStateChange(GetBestSize()); idk..
}
void GeneralSettings2 : : UpdateOnlineAccounts ( )
{
m_active_account - > Clear ( ) ;
for ( const auto & account : Account : : GetAccounts ( ) )
{
m_active_account - > Append ( fmt : : format ( L " {} ({:x}) " , std : : wstring { account . GetMiiName ( ) } , account . GetPersistentId ( ) ) ,
new wxAccountData ( account ) ) ;
}
m_active_account - > SetSelection ( 0 ) ;
m_create_account - > Enable ( m_active_account - > GetCount ( ) < 0xC ) ;
m_delete_account - > Enable ( m_active_account - > GetCount ( ) > 1 ) ;
UpdateAccountInformation ( ) ;
}
void GeneralSettings2 : : HandleGraphicsApiSelection ( )
{
int selection = m_vsync - > GetSelection ( ) ;
if ( selection = = wxNOT_FOUND )
selection = GetConfig ( ) . vsync ;
m_vsync - > Clear ( ) ;
if ( m_graphic_api - > GetSelection ( ) = = 0 )
{
// OpenGL
m_vsync - > AppendString ( _ ( " Off " ) ) ;
m_vsync - > AppendString ( _ ( " On " ) ) ;
if ( selection = = 0 )
m_vsync - > Select ( 0 ) ;
else
m_vsync - > Select ( 1 ) ;
m_graphic_device - > Clear ( ) ;
m_graphic_device - > Disable ( ) ;
m_gx2drawdone_sync - > Enable ( ) ;
m_async_compile - > Disable ( ) ;
}
else
{
// Vulkan
m_gx2drawdone_sync - > Disable ( ) ;
m_async_compile - > Enable ( ) ;
m_vsync - > AppendString ( _ ( " Off " ) ) ;
m_vsync - > AppendString ( _ ( " Double buffering " ) ) ;
m_vsync - > AppendString ( _ ( " Triple buffering " ) ) ;
m_vsync - > AppendString ( _ ( " Match emulated display (Experimental) " ) ) ;
m_vsync - > Select ( selection ) ;
m_graphic_device - > Enable ( ) ;
auto devices = VulkanRenderer : : GetDevices ( ) ;
m_graphic_device - > Clear ( ) ;
if ( ! devices . empty ( ) )
{
for ( const auto & device : devices )
{
m_graphic_device - > Append ( device . name , new wxVulkanUUID ( device ) ) ;
}
m_graphic_device - > SetSelection ( 0 ) ;
const auto & config = GetConfig ( ) ;
for ( size_t i = 0 ; i < devices . size ( ) ; + + i )
{
if ( config . graphic_device_uuid = = devices [ i ] . uuid )
{
m_graphic_device - > SetSelection ( i ) ;
break ;
}
}
}
}
}
void GeneralSettings2 : : ApplyConfig ( )
{
ValidateConfig ( ) ;
auto & config = GetConfig ( ) ;
if ( LaunchSettings : : GetMLCPath ( ) . has_value ( ) )
m_mlc_path - > SetValue ( wxString { LaunchSettings : : GetMLCPath ( ) . value ( ) . generic_wstring ( ) } ) ;
else
m_mlc_path - > SetValue ( config . mlc_path . GetValue ( ) ) ;
m_save_window_position_size - > SetValue ( config . window_position ! = Vector2i { - 1 , - 1 } ) ;
m_save_padwindow_position_size - > SetValue ( config . pad_position ! = Vector2i { - 1 , - 1 } ) ;
m_discord_presence - > SetValue ( config . use_discord_presence ) ;
m_fullscreen_menubar - > SetValue ( config . fullscreen_menubar ) ;
m_auto_update - > SetValue ( config . check_update ) ;
m_save_screenshot - > SetValue ( config . save_screenshot ) ;
m_permanent_storage - > SetValue ( config . permanent_storage ) ;
for ( auto & path : config . game_paths )
{
m_game_paths - > Append ( path ) ;
}
const auto app = ( CemuApp * ) wxTheApp ;
for ( const auto & language : app - > GetLanguages ( ) )
{
if ( config . language = = language - > Language )
{
m_language - > SetStringSelection ( language - > Description ) ;
break ;
}
}
// graphics
m_graphic_api - > SetSelection ( config . graphic_api ) ;
m_vsync - > SetSelection ( config . vsync ) ;
m_async_compile - > SetValue ( config . async_compile ) ;
m_gx2drawdone_sync - > SetValue ( config . gx2drawdone_sync ) ;
m_upscale_filter - > SetSelection ( config . upscale_filter ) ;
m_downscale_filter - > SetSelection ( config . downscale_filter ) ;
m_fullscreen_scaling - > SetSelection ( config . fullscreen_scaling ) ;
wxASSERT ( ( uint32 ) config . overlay . position < m_overlay_position - > GetCount ( ) ) ;
m_overlay_position - > SetSelection ( ( int ) config . overlay . position ) ;
m_overlay_font_color - > SetColour ( wxColour ( ( unsigned long ) config . overlay . text_color ) ) ;
uint32 selection = ( config . overlay . text_scale - 50 ) / 25 ;
wxASSERT ( selection < m_overlay_scale - > GetCount ( ) ) ;
m_overlay_scale - > SetSelection ( selection ) ;
m_overlay_fps - > SetValue ( config . overlay . fps ) ;
m_overlay_drawcalls - > SetValue ( config . overlay . drawcalls ) ;
m_overlay_cpu - > SetValue ( config . overlay . cpu_usage ) ;
m_overlay_cpu_per_core - > SetValue ( config . overlay . cpu_per_core_usage ) ;
m_overlay_ram - > SetValue ( config . overlay . ram_usage ) ;
m_overlay_vram - > SetValue ( config . overlay . vram_usage ) ;
m_overlay_debug - > SetValue ( config . overlay . debug ) ;
wxASSERT ( ( uint32 ) config . notification . position < m_notification_position - > GetCount ( ) ) ;
m_notification_position - > SetSelection ( ( int ) config . notification . position ) ;
m_notification_font_color - > SetColour ( wxColour ( ( unsigned long ) config . notification . text_color ) ) ;
selection = ( config . notification . text_scale - 50 ) / 25 ;
wxASSERT ( selection < m_notification_scale - > GetCount ( ) ) ;
m_notification_scale - > SetSelection ( selection ) ;
m_controller_profile_name - > SetValue ( config . notification . controller_profiles ) ;
m_controller_low_battery - > SetValue ( config . notification . controller_battery ) ;
m_shader_compiling - > SetValue ( config . notification . shader_compiling ) ;
m_friends_data - > SetValue ( config . notification . friends ) ;
// audio
if ( config . audio_api = = IAudioAPI : : DirectSound )
m_audio_api - > SetStringSelection ( kDirectSound ) ;
else if ( config . audio_api = = IAudioAPI : : XAudio27 )
m_audio_api - > SetStringSelection ( kXAudio27 ) ;
else if ( config . audio_api = = IAudioAPI : : XAudio2 )
m_audio_api - > SetStringSelection ( kXAudio2 ) ;
else if ( config . audio_api = = IAudioAPI : : Cubeb )
m_audio_api - > SetStringSelection ( kCubeb ) ;
SendSliderEvent ( m_audio_latency , config . audio_delay ) ;
m_tv_channels - > SetSelection ( config . tv_channels ) ;
//m_pad_channels->SetSelection(config.pad_channels);
m_pad_channels - > SetSelection ( 0 ) ;
SendSliderEvent ( m_tv_volume , config . tv_volume ) ;
if ( ! config . tv_device . empty ( ) & & m_tv_device - > HasClientObjectData ( ) )
{
for ( uint32 i = 0 ; i < m_tv_device - > GetCount ( ) ; + + i )
{
const auto device_description = ( wxDeviceDescription * ) m_tv_device - > GetClientObject ( i ) ;
if ( device_description & & config . tv_device = = device_description - > GetDescription ( ) - > GetIdentifier ( ) )
{
m_tv_device - > SetSelection ( i ) ;
break ;
}
}
}
else
m_tv_device - > SetSelection ( 0 ) ;
SendSliderEvent ( m_pad_volume , config . pad_volume ) ;
if ( ! config . pad_device . empty ( ) & & m_pad_device - > HasClientObjectData ( ) )
{
for ( uint32 i = 0 ; i < m_pad_device - > GetCount ( ) ; + + i )
{
const auto device_description = ( wxDeviceDescription * ) m_pad_device - > GetClientObject ( i ) ;
if ( device_description & & config . pad_device = = device_description - > GetDescription ( ) - > GetIdentifier ( ) )
{
m_pad_device - > SetSelection ( i ) ;
break ;
}
}
}
else
m_pad_device - > SetSelection ( 0 ) ;
// account
UpdateOnlineAccounts ( ) ;
m_active_account - > SetSelection ( 0 ) ;
for ( uint32 i = 0 ; i < m_active_account - > GetCount ( ) ; + + i )
{
const auto * obj = dynamic_cast < wxAccountData * > ( m_active_account - > GetClientObject ( i ) ) ;
wxASSERT ( obj ) ;
if ( obj - > GetAccount ( ) . GetPersistentId ( ) = = ActiveSettings : : GetPersistentId ( ) )
{
m_active_account - > SetSelection ( i ) ;
break ;
}
}
m_online_enabled - > SetValue ( config . account . online_enabled ) ;
UpdateAccountInformation ( ) ;
// debug
m_crash_dump - > SetSelection ( ( int ) config . crash_dump . GetValue ( ) ) ;
}
void GeneralSettings2 : : OnOnlineEnable ( wxCommandEvent & event )
{
event . Skip ( ) ;
if ( ! m_online_enabled - > GetValue ( ) )
return ;
// show warning if player enables online mode
const auto result = wxMessageBox ( _ ( " Please be aware that online mode lets you connect to OFFICIAL servers and therefore there is a risk of getting banned. \n Only proceed if you are willing to risk losing online access with your Wii U and/or NNID. " ) ,
_ ( " Warning " ) , wxYES_NO | wxCENTRE | wxICON_EXCLAMATION , this ) ;
if ( result = = wxNO )
m_online_enabled - > SetValue ( false ) ;
}
void GeneralSettings2 : : OnAudioAPISelected ( wxCommandEvent & event )
{
IAudioAPI : : AudioAPI api ;
if ( m_audio_api - > GetStringSelection ( ) = = kDirectSound )
api = IAudioAPI : : DirectSound ;
else if ( m_audio_api - > GetStringSelection ( ) = = kXAudio27 )
api = IAudioAPI : : XAudio27 ;
else if ( m_audio_api - > GetStringSelection ( ) = = kXAudio2 )
api = IAudioAPI : : XAudio2 ;
else if ( m_audio_api - > GetStringSelection ( ) = = kCubeb )
api = IAudioAPI : : Cubeb ;
else
{
wxFAIL_MSG ( " invalid audio api selected! " ) ;
return ;
}
GetConfig ( ) . audio_api = api ;
UpdateAudioDeviceList ( ) ;
OnAudioDeviceSelected ( event ) ;
}
# define AX_FRAMES_PER_GROUP 4
void GeneralSettings2 : : UpdateAudioDevice ( )
{
auto & config = GetConfig ( ) ;
// tv audio device
{
const auto selection = m_tv_device - > GetSelection ( ) ;
if ( selection = = wxNOT_FOUND )
{
cemu_assert_debug ( false ) ;
return ;
}
if ( m_tv_device - > HasClientObjectData ( ) )
{
const auto description = ( wxDeviceDescription * ) m_tv_device - > GetClientObject ( selection ) ;
if ( description )
{
std : : unique_lock lock ( g_audioMutex ) ;
sint32 channels ;
if ( m_game_launched & & g_tvAudio )
channels = g_tvAudio - > GetChannels ( ) ;
else
{
switch ( config . tv_channels )
{
case 0 :
channels = 1 ;
break ;
case 2 :
channels = 6 ;
break ;
default : // stereo
channels = 2 ;
break ;
}
}
try
{
g_tvAudio . reset ( ) ;
g_tvAudio = IAudioAPI : : CreateDevice ( ( IAudioAPI : : AudioAPI ) config . audio_api , description - > GetDescription ( ) , 48000 , channels , snd_core : : AX_SAMPLES_PER_3MS_48KHZ * AX_FRAMES_PER_GROUP , 16 ) ;
g_tvAudio - > SetVolume ( m_tv_volume - > GetValue ( ) ) ;
}
catch ( std : : runtime_error & ex )
{
forceLog_printf ( " can't initialize tv audio: %s " , ex . what ( ) ) ;
}
}
}
}
// pad audio device
{
const auto selection = m_pad_device - > GetSelection ( ) ;
if ( selection = = wxNOT_FOUND )
{
cemu_assert_debug ( false ) ;
return ;
}
if ( m_pad_device - > HasClientObjectData ( ) )
{
const auto description = ( wxDeviceDescription * ) m_pad_device - > GetClientObject ( selection ) ;
if ( description )
{
std : : unique_lock lock ( g_audioMutex ) ;
sint32 channels ;
if ( m_game_launched & & g_padAudio )
channels = g_padAudio - > GetChannels ( ) ;
else
{
switch ( config . pad_channels )
{
case 0 :
channels = 1 ;
break ;
case 2 :
channels = 6 ;
break ;
default : // stereo
channels = 2 ;
break ;
}
}
try
{
g_padAudio . reset ( ) ;
g_padAudio = IAudioAPI : : CreateDevice ( ( IAudioAPI : : AudioAPI ) config . audio_api , description - > GetDescription ( ) , 48000 , channels , snd_core : : AX_SAMPLES_PER_3MS_48KHZ * AX_FRAMES_PER_GROUP , 16 ) ;
g_padAudio - > SetVolume ( m_pad_volume - > GetValue ( ) ) ;
g_padVolume = m_pad_volume - > GetValue ( ) ;
}
catch ( std : : runtime_error & ex )
{
forceLog_printf ( " can't initialize pad audio: %s " , ex . what ( ) ) ;
}
}
}
}
}
void GeneralSettings2 : : OnAudioDeviceSelected ( wxCommandEvent & event )
{
UpdateAudioDevice ( ) ;
}
void GeneralSettings2 : : OnAudioChannelsSelected ( wxCommandEvent & event )
{
const auto obj = wxDynamicCast ( event . GetEventObject ( ) , wxChoice ) ;
wxASSERT ( obj ) ;
if ( obj - > GetSelection ( ) = = wxNOT_FOUND )
return ;
auto & config = GetConfig ( ) ;
if ( obj = = m_tv_channels )
{
if ( config . tv_channels = = ( AudioChannels ) obj - > GetSelection ( ) )
return ;
config . tv_channels = ( AudioChannels ) obj - > GetSelection ( ) ;
}
else if ( obj = = m_pad_channels )
{
if ( config . pad_channels = = ( AudioChannels ) obj - > GetSelection ( ) )
return ;
config . pad_channels = ( AudioChannels ) obj - > GetSelection ( ) ;
}
else
cemu_assert_debug ( false ) ;
if ( m_game_launched )
wxMessageBox ( _ ( " You have to restart the game in order to apply the new settings. " ) , _ ( " Information " ) , wxOK | wxCENTRE , this ) ;
else
UpdateAudioDevice ( ) ;
}
void GeneralSettings2 : : OnGraphicAPISelected ( wxCommandEvent & event )
{
HandleGraphicsApiSelection ( ) ;
}
void GeneralSettings2 : : OnAddPathClicked ( wxCommandEvent & event )
{
wxDirDialog path_dialog ( this , _ ( " Select a directory containing games. " ) , wxEmptyString , wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST ) ;
if ( path_dialog . ShowModal ( ) ! = wxID_OK | | path_dialog . GetPath ( ) . empty ( ) )
return ;
const auto path = path_dialog . GetPath ( ) ;
// test if already included
for ( auto & s : m_game_paths - > GetStrings ( ) )
{
if ( s = = path )
return ;
}
m_game_paths - > Append ( path ) ;
m_reload_gamelist = true ;
// trigger title list rescan with new path configuration
CafeTitleList : : ClearScanPaths ( ) ;
for ( auto & it : m_game_paths - > GetStrings ( ) )
CafeTitleList : : AddScanPath ( wxHelper : : MakeFSPath ( it ) ) ;
CafeTitleList : : Refresh ( ) ;
}
void GeneralSettings2 : : OnRemovePathClicked ( wxCommandEvent & event )
{
const auto selection = m_game_paths - > GetSelection ( ) ;
if ( selection = = wxNOT_FOUND )
return ;
m_game_paths - > Delete ( selection ) ;
m_reload_gamelist = true ;
// trigger title list rescan with new path configuration
CafeTitleList : : ClearScanPaths ( ) ;
for ( auto & it : m_game_paths - > GetStrings ( ) )
CafeTitleList : : AddScanPath ( wxHelper : : MakeFSPath ( it ) ) ;
CafeTitleList : : Refresh ( ) ;
}
void GeneralSettings2 : : OnActiveAccountChanged ( wxCommandEvent & event )
{
UpdateAccountInformation ( ) ;
m_has_account_change = true ;
}
void GeneralSettings2 : : OnMLCPathSelect ( wxCommandEvent & event )
{
if ( ! CemuApp : : SelectMLCPath ( this ) )
return ;
m_mlc_path - > SetValue ( ActiveSettings : : GetMlcPath ( ) . generic_string ( ) ) ;
m_reload_gamelist = true ;
m_mlc_modified = true ;
CemuApp : : CreateDefaultFiles ( ) ;
}
void GeneralSettings2 : : OnMLCPathChar ( wxKeyEvent & event )
{
if ( LaunchSettings : : GetMLCPath ( ) . has_value ( ) )
return ;
if ( event . GetKeyCode ( ) = = WXK_DELETE | | event . GetKeyCode ( ) = = WXK_BACK )
{
m_mlc_path - > SetValue ( wxEmptyString ) ;
m_reload_gamelist = true ;
GetConfig ( ) . mlc_path = L " " ;
g_config . Save ( ) ;
m_mlc_modified = true ;
CemuApp : : CreateDefaultFiles ( ) ;
}
}
void GeneralSettings2 : : OnShowOnlineValidator ( wxCommandEvent & event )
{
const auto selection = m_active_account - > GetSelection ( ) ;
if ( selection = = wxNOT_FOUND )
return ;
const auto * obj = dynamic_cast < wxAccountData * > ( m_active_account - > GetClientObject ( selection ) ) ;
wxASSERT ( obj ) ;
const auto & account = obj - > GetAccount ( ) ;
const auto validator = account . ValidateOnlineFiles ( ) ;
if ( validator ) // everything valid? shouldn't happen
return ;
std : : wstringstream err ;
err < < L " The following error(s) have been found: " < < std : : endl ;
if ( validator . otp = = OnlineValidator : : FileState : : Missing )
err < < L " otp.bin missing in cemu root directory " < < std : : endl ;
else if ( validator . otp = = OnlineValidator : : FileState : : Corrupted )
err < < L " otp.bin is invalid " < < std : : endl ;
if ( validator . seeprom = = OnlineValidator : : FileState : : Missing )
err < < L " seeprom.bin missing in cemu root directory " < < std : : endl ;
else if ( validator . seeprom = = OnlineValidator : : FileState : : Corrupted )
err < < L " seeprom.bin is invalid " < < std : : endl ;
if ( ! validator . missing_files . empty ( ) )
{
err < < L " Missing certificate and key files: " < < std : : endl ;
int counter = 0 ;
for ( const auto & f : validator . missing_files )
{
err < < f < < std : : endl ;
+ + counter ;
if ( counter > 10 )
{
err < < L " ... " < < std : : endl ;
break ;
}
}
err < < std : : endl ;
}
if ( ! validator . valid_account )
{
err < < L " The currently selected account is not a valid or dumped online account: \n " < < boost : : nowide : : widen ( fmt : : format ( " {} " , validator . account_error ) ) ;
}
wxMessageBox ( err . str ( ) , _ ( " Online Status " ) , wxOK | wxCENTRE | wxICON_INFORMATION ) ;
}