diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/core/hle/kernel/hle_ipc.cpp | 15 | ||||
-rw-r--r-- | src/core/hle/kernel/hle_ipc.h | 9 | ||||
-rw-r--r-- | src/core/hle/kernel/k_server_session.cpp | 42 | ||||
-rw-r--r-- | src/core/hle/kernel/kernel.cpp | 18 | ||||
-rw-r--r-- | src/yuzu/configuration/configure_ui.cpp | 40 |
5 files changed, 83 insertions, 41 deletions
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index 260af87e5..45aced99f 100644 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp @@ -41,6 +41,21 @@ SessionRequestManager::SessionRequestManager(KernelCore& kernel_) : kernel{kerne SessionRequestManager::~SessionRequestManager() = default; +bool SessionRequestManager::HasSessionRequestHandler(const HLERequestContext& context) const { + if (IsDomain() && context.HasDomainMessageHeader()) { + const auto& message_header = context.GetDomainMessageHeader(); + const auto object_id = message_header.object_id; + + if (object_id > DomainHandlerCount()) { + LOG_CRITICAL(IPC, "object_id {} is too big!", object_id); + return false; + } + return DomainHandler(object_id - 1) != nullptr; + } else { + return session_handler != nullptr; + } +} + void SessionRequestHandler::ClientConnected(KServerSession* session) { session->SetSessionHandler(shared_from_this()); } diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h index 2aaf93fca..a61870f8b 100644 --- a/src/core/hle/kernel/hle_ipc.h +++ b/src/core/hle/kernel/hle_ipc.h @@ -85,8 +85,8 @@ public: */ void ClientDisconnected(KServerSession* session); - std::shared_ptr<ServiceThread> GetServiceThread() const { - return service_thread.lock(); + std::weak_ptr<ServiceThread> GetServiceThread() const { + return service_thread; } protected: @@ -152,10 +152,12 @@ public: session_handler = std::move(handler); } - std::shared_ptr<ServiceThread> GetServiceThread() const { + std::weak_ptr<ServiceThread> GetServiceThread() const { return session_handler->GetServiceThread(); } + bool HasSessionRequestHandler(const HLERequestContext& context) const; + private: bool is_domain{}; SessionRequestHandlerPtr session_handler; @@ -163,7 +165,6 @@ private: private: KernelCore& kernel; - std::weak_ptr<ServiceThread> service_thread; }; /** diff --git a/src/core/hle/kernel/k_server_session.cpp b/src/core/hle/kernel/k_server_session.cpp index 528ca8614..5c3c13ce6 100644 --- a/src/core/hle/kernel/k_server_session.cpp +++ b/src/core/hle/kernel/k_server_session.cpp @@ -8,6 +8,7 @@ #include "common/assert.h" #include "common/common_types.h" #include "common/logging/log.h" +#include "common/scope_exit.h" #include "core/core_timing.h" #include "core/hle/ipc_helpers.h" #include "core/hle/kernel/hle_ipc.h" @@ -119,11 +120,25 @@ ResultCode KServerSession::QueueSyncRequest(KThread* thread, Core::Memory::Memor context->PopulateFromIncomingCommandBuffer(kernel.CurrentProcess()->GetHandleTable(), cmd_buf); - if (auto strong_ptr = manager->GetServiceThread(); strong_ptr) { - strong_ptr->QueueSyncRequest(*parent, std::move(context)); - return ResultSuccess; + // In the event that something fails here, stub a result to prevent the game from crashing. + // This is a work-around in the event that somehow we process a service request after the + // session has been closed by the game. This has been observed to happen rarely in Pokemon + // Sword/Shield and is likely a result of us using host threads/scheduling for services. + // TODO(bunnei): Find a better solution here. + auto error_guard = SCOPE_GUARD({ CompleteSyncRequest(*context); }); + + // Ensure we have a session request handler + if (manager->HasSessionRequestHandler(*context)) { + if (auto strong_ptr = manager->GetServiceThread().lock()) { + strong_ptr->QueueSyncRequest(*parent, std::move(context)); + + // We succeeded. + error_guard.Cancel(); + } else { + ASSERT_MSG(false, "strong_ptr is nullptr!"); + } } else { - ASSERT_MSG(false, "strong_ptr was nullptr!"); + ASSERT_MSG(false, "handler is invalid!"); } return ResultSuccess; @@ -131,13 +146,20 @@ ResultCode KServerSession::QueueSyncRequest(KThread* thread, Core::Memory::Memor ResultCode KServerSession::CompleteSyncRequest(HLERequestContext& context) { ResultCode result = ResultSuccess; + // If the session has been converted to a domain, handle the domain request - if (IsDomain() && context.HasDomainMessageHeader()) { - result = HandleDomainSyncRequest(context); - // If there is no domain header, the regular session handler is used - } else if (manager->HasSessionHandler()) { - // If this ServerSession has an associated HLE handler, forward the request to it. - result = manager->SessionHandler().HandleSyncRequest(*this, context); + if (manager->HasSessionRequestHandler(context)) { + if (IsDomain() && context.HasDomainMessageHeader()) { + result = HandleDomainSyncRequest(context); + // If there is no domain header, the regular session handler is used + } else if (manager->HasSessionHandler()) { + // If this ServerSession has an associated HLE handler, forward the request to it. + result = manager->SessionHandler().HandleSyncRequest(*this, context); + } + } else { + ASSERT_MSG(false, "Session handler is invalid, stubbing response!"); + IPC::ResponseBuilder rb(context, 2); + rb.Push(ResultSuccess); } if (convert_to_domain) { diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 0ffb78d51..2ceeaeb5f 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -63,8 +63,6 @@ struct KernelCore::Impl { global_scheduler_context = std::make_unique<Kernel::GlobalSchedulerContext>(kernel); global_handle_table = std::make_unique<Kernel::KHandleTable>(kernel); - service_thread_manager = - std::make_unique<Common::ThreadWorker>(1, "yuzu:ServiceThreadManager"); is_phantom_mode_for_singlecore = false; InitializePhysicalCores(); @@ -96,7 +94,6 @@ struct KernelCore::Impl { process_list.clear(); // Ensures all service threads gracefully shutdown - service_thread_manager.reset(); service_threads.clear(); next_object_id = 0; @@ -680,10 +677,6 @@ struct KernelCore::Impl { // Threads used for services std::unordered_set<std::shared_ptr<Kernel::ServiceThread>> service_threads; - // Service threads are managed by a worker thread, so that a calling service thread can queue up - // the release of itself - std::unique_ptr<Common::ThreadWorker> service_thread_manager; - std::array<KThread*, Core::Hardware::NUM_CPU_CORES> suspend_threads; std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES> interrupts{}; std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{}; @@ -986,17 +979,14 @@ void KernelCore::ExitSVCProfile() { std::weak_ptr<Kernel::ServiceThread> KernelCore::CreateServiceThread(const std::string& name) { auto service_thread = std::make_shared<Kernel::ServiceThread>(*this, 1, name); - impl->service_thread_manager->QueueWork( - [this, service_thread] { impl->service_threads.emplace(service_thread); }); + impl->service_threads.emplace(service_thread); return service_thread; } void KernelCore::ReleaseServiceThread(std::weak_ptr<Kernel::ServiceThread> service_thread) { - impl->service_thread_manager->QueueWork([this, service_thread] { - if (auto strong_ptr = service_thread.lock()) { - impl->service_threads.erase(strong_ptr); - } - }); + if (auto strong_ptr = service_thread.lock()) { + impl->service_threads.erase(strong_ptr); + } } Init::KSlabResourceCounts& KernelCore::SlabResourceCounts() { diff --git a/src/yuzu/configuration/configure_ui.cpp b/src/yuzu/configuration/configure_ui.cpp index 0a28c87c0..9674119e1 100644 --- a/src/yuzu/configuration/configure_ui.cpp +++ b/src/yuzu/configuration/configure_ui.cpp @@ -17,17 +17,30 @@ namespace { constexpr std::array default_icon_sizes{ - std::make_pair(0, QT_TR_NOOP("None")), - std::make_pair(32, QT_TR_NOOP("Small (32x32)")), - std::make_pair(64, QT_TR_NOOP("Standard (64x64)")), - std::make_pair(128, QT_TR_NOOP("Large (128x128)")), - std::make_pair(256, QT_TR_NOOP("Full Size (256x256)")), + std::make_pair(0, QT_TRANSLATE_NOOP("ConfigureUI", "None")), + std::make_pair(32, QT_TRANSLATE_NOOP("ConfigureUI", "Small (32x32)")), + std::make_pair(64, QT_TRANSLATE_NOOP("ConfigureUI", "Standard (64x64)")), + std::make_pair(128, QT_TRANSLATE_NOOP("ConfigureUI", "Large (128x128)")), + std::make_pair(256, QT_TRANSLATE_NOOP("ConfigureUI", "Full Size (256x256)")), }; +// clang-format off constexpr std::array row_text_names{ - QT_TR_NOOP("Filename"), QT_TR_NOOP("Filetype"), QT_TR_NOOP("Title ID"), - QT_TR_NOOP("Title Name"), QT_TR_NOOP("None"), + QT_TRANSLATE_NOOP("ConfigureUI", "Filename"), + QT_TRANSLATE_NOOP("ConfigureUI", "Filetype"), + QT_TRANSLATE_NOOP("ConfigureUI", "Title ID"), + QT_TRANSLATE_NOOP("ConfigureUI", "Title Name"), + QT_TRANSLATE_NOOP("ConfigureUI", "None"), }; +// clang-format on + +QString GetTranslatedIconSize(size_t index) { + return QCoreApplication::translate("ConfigureUI", default_icon_sizes[index].second); +} + +QString GetTranslatedRowTextName(size_t index) { + return QCoreApplication::translate("ConfigureUI", row_text_names[index]); +} } // Anonymous namespace ConfigureUi::ConfigureUi(QWidget* parent) : QWidget(parent), ui(new Ui::ConfigureUi) { @@ -121,11 +134,11 @@ void ConfigureUi::RetranslateUI() { ui->retranslateUi(this); for (int i = 0; i < ui->icon_size_combobox->count(); i++) { - ui->icon_size_combobox->setItemText(i, tr(default_icon_sizes[i].second)); + ui->icon_size_combobox->setItemText(i, GetTranslatedIconSize(static_cast<size_t>(i))); } for (int i = 0; i < ui->row_1_text_combobox->count(); i++) { - const QString name = tr(row_text_names[i]); + const QString name = GetTranslatedRowTextName(static_cast<size_t>(i)); ui->row_1_text_combobox->setItemText(i, name); ui->row_2_text_combobox->setItemText(i, name); @@ -152,8 +165,9 @@ void ConfigureUi::InitializeLanguageComboBox() { } void ConfigureUi::InitializeIconSizeComboBox() { - for (const auto& size : default_icon_sizes) { - ui->icon_size_combobox->addItem(QString::fromUtf8(size.second), size.first); + for (size_t i = 0; i < default_icon_sizes.size(); i++) { + const auto size = default_icon_sizes[i].first; + ui->icon_size_combobox->addItem(GetTranslatedIconSize(i), size); } } @@ -170,7 +184,7 @@ void ConfigureUi::UpdateFirstRowComboBox(bool init) { ui->row_1_text_combobox->clear(); for (std::size_t i = 0; i < row_text_names.size(); i++) { - const QString row_text_name = QString::fromUtf8(row_text_names[i]); + const QString row_text_name = GetTranslatedRowTextName(i); ui->row_1_text_combobox->addItem(row_text_name, QVariant::fromValue(i)); } @@ -189,7 +203,7 @@ void ConfigureUi::UpdateSecondRowComboBox(bool init) { ui->row_2_text_combobox->clear(); for (std::size_t i = 0; i < row_text_names.size(); ++i) { - const QString row_text_name = QString::fromUtf8(row_text_names[i]); + const QString row_text_name = GetTranslatedRowTextName(i); ui->row_2_text_combobox->addItem(row_text_name, QVariant::fromValue(i)); } |