HostInterface: Fix crash on startup with controller connected

This commit is contained in:
Connor McLaughlin 2020-04-06 12:18:33 +10:00
parent f41475ae8f
commit e91d760175
8 changed files with 49 additions and 35 deletions

View file

@ -1,9 +1,9 @@
#include "android_host_interface.h" #include "android_host_interface.h"
#include "android_gles_host_display.h" #include "android_gles_host_display.h"
#include "common/assert.h" #include "common/assert.h"
#include "common/audio_stream.h"
#include "common/log.h" #include "common/log.h"
#include "common/string.h" #include "common/string.h"
#include "common/audio_stream.h"
#include "core/controller.h" #include "core/controller.h"
#include "core/game_list.h" #include "core/game_list.h"
#include "core/gpu.h" #include "core/gpu.h"
@ -67,11 +67,6 @@ bool AndroidHostInterface::Initialize()
if (!HostInterface::Initialize()) if (!HostInterface::Initialize())
return false; return false;
// check settings version, if invalid set defaults, then load settings
INISettingsInterface settings_interface(GetSettingsFileName());
CheckSettings(settings_interface);
UpdateSettings([this, &settings_interface]() { m_settings.Load(settings_interface); });
return true; return true;
} }
@ -96,14 +91,22 @@ void AndroidHostInterface::SetUserDirectory()
m_user_directory = "/sdcard/duckstation"; m_user_directory = "/sdcard/duckstation";
} }
void AndroidHostInterface::LoadSettings()
{
// check settings version, if invalid set defaults, then load settings
INISettingsInterface settings_interface(GetSettingsFileName());
CheckSettings(settings_interface);
UpdateSettings([this, &settings_interface]() { m_settings.Load(settings_interface); });
}
bool AndroidHostInterface::StartEmulationThread(ANativeWindow* initial_surface, SystemBootParameters boot_params) bool AndroidHostInterface::StartEmulationThread(ANativeWindow* initial_surface, SystemBootParameters boot_params)
{ {
Assert(!IsEmulationThreadRunning()); Assert(!IsEmulationThreadRunning());
Log_DevPrintf("Starting emulation thread..."); Log_DevPrintf("Starting emulation thread...");
m_emulation_thread_stop_request.store(false); m_emulation_thread_stop_request.store(false);
m_emulation_thread = std::thread(&AndroidHostInterface::EmulationThreadEntryPoint, this, initial_surface, m_emulation_thread =
std::move(boot_params)); std::thread(&AndroidHostInterface::EmulationThreadEntryPoint, this, initial_surface, std::move(boot_params));
m_emulation_thread_started.Wait(); m_emulation_thread_started.Wait();
if (!m_emulation_thread_start_result.load()) if (!m_emulation_thread_start_result.load())
{ {
@ -458,7 +461,7 @@ DEFINE_JNI_ARGS_METHOD(jint, AndroidHostInterface_getControllerButtonCode, jobje
DEFINE_JNI_ARGS_METHOD(jarray, GameList_getEntries, jobject unused, jstring j_cache_path, jstring j_redump_dat_path, DEFINE_JNI_ARGS_METHOD(jarray, GameList_getEntries, jobject unused, jstring j_cache_path, jstring j_redump_dat_path,
jarray j_search_directories, jboolean search_recursively) jarray j_search_directories, jboolean search_recursively)
{ {
//const std::string cache_path = JStringToString(env, j_cache_path); // const std::string cache_path = JStringToString(env, j_cache_path);
std::string redump_dat_path = JStringToString(env, j_redump_dat_path); std::string redump_dat_path = JStringToString(env, j_redump_dat_path);
// TODO: This should use the base HostInterface. // TODO: This should use the base HostInterface.

View file

@ -36,6 +36,7 @@ public:
protected: protected:
void SetUserDirectory() override; void SetUserDirectory() override;
void LoadSettings() override;
bool AcquireHostDisplay() override; bool AcquireHostDisplay() override;
void ReleaseHostDisplay() override; void ReleaseHostDisplay() override;
std::unique_ptr<AudioStream> CreateAudioStream(AudioBackend backend) override; std::unique_ptr<AudioStream> CreateAudioStream(AudioBackend backend) override;

View file

@ -61,6 +61,7 @@ bool HostInterface::Initialize()
{ {
SetUserDirectory(); SetUserDirectory();
InitializeUserDirectory(); InitializeUserDirectory();
LoadSettings();
m_game_list = std::make_unique<GameList>(); m_game_list = std::make_unique<GameList>();
m_game_list->SetCacheFilename(GetGameListCacheFileName()); m_game_list->SetCacheFilename(GetGameListCacheFileName());
m_game_list->SetDatabaseFilename(GetGameListDatabaseFileName()); m_game_list->SetDatabaseFilename(GetGameListDatabaseFileName());

View file

@ -158,8 +158,8 @@ protected:
/// Sets the base path for the user directory. Can be overridden by platform/frontend/command line. /// Sets the base path for the user directory. Can be overridden by platform/frontend/command line.
virtual void SetUserDirectory(); virtual void SetUserDirectory();
/// Ensures all subdirectories of the user directory are created. /// Performs the initial load of settings. Should call CheckSettings() and m_settings.Load().
void CreateUserDirectorySubdirectories(); virtual void LoadSettings() = 0;
/// Returns the path of the settings file. /// Returns the path of the settings file.
std::string GetSettingsFileName() const; std::string GetSettingsFileName() const;

View file

@ -59,22 +59,6 @@ bool QtHostInterface::initializeOnThread()
if (m_controller_interface) if (m_controller_interface)
m_controller_interface->PollEvents(); m_controller_interface->PollEvents();
// no need to lock here because the main thread is waiting for us
m_qsettings = std::make_unique<QSettings>(QString::fromStdString(GetSettingsFileName()), QSettings::IniFormat);
QtSettingsInterface si(m_qsettings.get());
// check settings validity
const QSettings::Status settings_status = m_qsettings->status();
if (settings_status != QSettings::NoError)
{
m_qsettings->clear();
SetDefaultSettings(si);
}
// load in settings
CheckSettings(si);
m_settings.Load(si);
// bind buttons/axises // bind buttons/axises
updateInputMap(); updateInputMap();
return true; return true;
@ -417,6 +401,25 @@ void QtHostInterface::OnSystemStateSaved(bool global, s32 slot)
emit stateSaved(QString::fromStdString(m_system->GetRunningCode()), global, slot); emit stateSaved(QString::fromStdString(m_system->GetRunningCode()), global, slot);
} }
void QtHostInterface::LoadSettings()
{
// no need to lock here because the main thread is waiting for us
m_qsettings = std::make_unique<QSettings>(QString::fromStdString(GetSettingsFileName()), QSettings::IniFormat);
QtSettingsInterface si(m_qsettings.get());
// check settings validity
const QSettings::Status settings_status = m_qsettings->status();
if (settings_status != QSettings::NoError)
{
m_qsettings->clear();
SetDefaultSettings(si);
}
// load in settings
CheckSettings(si);
m_settings.Load(si);
}
void QtHostInterface::SetDefaultSettings(SettingsInterface& si) void QtHostInterface::SetDefaultSettings(SettingsInterface& si)
{ {
CommonHostInterface::SetDefaultSettings(si); CommonHostInterface::SetDefaultSettings(si);

View file

@ -133,6 +133,7 @@ protected:
void OnRunningGameChanged() override; void OnRunningGameChanged() override;
void OnSystemStateSaved(bool global, s32 slot) override; void OnSystemStateSaved(bool global, s32 slot) override;
void LoadSettings() override;
void SetDefaultSettings(SettingsInterface& si) override; void SetDefaultSettings(SettingsInterface& si) override;
void UpdateInputMap() override; void UpdateInputMap() override;

View file

@ -295,12 +295,6 @@ bool SDLHostInterface::Initialize()
if (!FileSystem::SetWorkingDirectory(m_user_directory.c_str())) if (!FileSystem::SetWorkingDirectory(m_user_directory.c_str()))
Log_ErrorPrintf("Failed to set working directory to '%s'", m_user_directory.c_str()); Log_ErrorPrintf("Failed to set working directory to '%s'", m_user_directory.c_str());
// Settings need to be loaded prior to creating the window for OpenGL bits.
INISettingsInterface si(GetSettingsFileName());
m_settings_copy.Load(si);
m_settings = m_settings_copy;
m_fullscreen = m_settings_copy.start_fullscreen;
if (!CreateSDLWindow()) if (!CreateSDLWindow())
{ {
Log_ErrorPrintf("Failed to create SDL window"); Log_ErrorPrintf("Failed to create SDL window");
@ -334,6 +328,15 @@ void SDLHostInterface::Shutdown()
HostInterface::Shutdown(); HostInterface::Shutdown();
} }
void SDLHostInterface::LoadSettings()
{
// Settings need to be loaded prior to creating the window for OpenGL bits.
INISettingsInterface si(GetSettingsFileName());
m_settings_copy.Load(si);
m_settings = m_settings_copy;
m_fullscreen = m_settings_copy.start_fullscreen;
}
void SDLHostInterface::ReportError(const char* message) void SDLHostInterface::ReportError(const char* message)
{ {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "DuckStation", message, m_window); SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "DuckStation", message, m_window);

View file

@ -29,19 +29,21 @@ public:
void ReportMessage(const char* message) override; void ReportMessage(const char* message) override;
bool ConfirmMessage(const char* message) override; bool ConfirmMessage(const char* message) override;
bool Initialize(); bool Initialize() override;
void Shutdown() override; void Shutdown() override;
void Run(); void Run();
protected: protected:
void LoadSettings() override;
bool AcquireHostDisplay() override; bool AcquireHostDisplay() override;
void ReleaseHostDisplay() override; void ReleaseHostDisplay() override;
std::unique_ptr<AudioStream> CreateAudioStream(AudioBackend backend) override; std::unique_ptr<AudioStream> CreateAudioStream(AudioBackend backend) override;
void OnSystemCreated() override; void OnSystemCreated() override;
void OnSystemPaused(bool paused) override; void OnSystemPaused(bool paused) override;
void OnSystemDestroyed(); void OnSystemDestroyed() override;
void OnControllerTypeChanged(u32 slot) override; void OnControllerTypeChanged(u32 slot) override;
private: private: