diff --git a/README.md b/README.md index 3f5e8c225..84bb03b64 100755 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ yuzu emulator early access ============= -This is the source code for early-access 1761. +This is the source code for early-access 1763. ## Legal Notice diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index 260af87e5..45aced99f 100755 --- 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 100755 --- 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 GetServiceThread() const { - return service_thread.lock(); + std::weak_ptr GetServiceThread() const { + return service_thread; } protected: @@ -152,10 +152,12 @@ public: session_handler = std::move(handler); } - std::shared_ptr GetServiceThread() const { + std::weak_ptr 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 service_thread; }; /** diff --git a/src/core/hle/kernel/k_server_session.cpp b/src/core/hle/kernel/k_server_session.cpp index 528ca8614..dd62706a8 100755 --- a/src/core/hle/kernel/k_server_session.cpp +++ b/src/core/hle/kernel/k_server_session.cpp @@ -119,11 +119,16 @@ 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; + // 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)); + return ResultSuccess; + } else { + ASSERT_MSG(false, "strong_ptr is nullptr!"); + } } else { - ASSERT_MSG(false, "strong_ptr was nullptr!"); + ASSERT_MSG(false, "handler is invalid!"); } return ResultSuccess; diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 0ffb78d51..2ceeaeb5f 100755 --- 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); global_handle_table = std::make_unique(kernel); - service_thread_manager = - std::make_unique(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> 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 service_thread_manager; - std::array suspend_threads; std::array interrupts{}; std::array, Core::Hardware::NUM_CPU_CORES> schedulers{}; @@ -986,17 +979,14 @@ void KernelCore::ExitSVCProfile() { std::weak_ptr KernelCore::CreateServiceThread(const std::string& name) { auto service_thread = std::make_shared(*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 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/game_list.cpp b/src/yuzu/game_list.cpp index 9308cfef8..da956c99b 100755 --- a/src/yuzu/game_list.cpp +++ b/src/yuzu/game_list.cpp @@ -505,6 +505,10 @@ void GameList::PopupContextMenu(const QPoint& menu_location) { void GameList::AddGamePopup(QMenu& context_menu, u64 program_id, const std::string& path) { QAction* favorite = context_menu.addAction(tr("Favorite")); context_menu.addSeparator(); + QAction* start_game = context_menu.addAction(tr("Start Game")); + QAction* start_game_global = + context_menu.addAction(tr("Start Game without Custom Configuration")); + context_menu.addSeparator(); QAction* open_save_location = context_menu.addAction(tr("Open Save Data Location")); QAction* open_mod_location = context_menu.addAction(tr("Open Mod Data Location")); QAction* open_transferable_shader_cache = @@ -540,6 +544,12 @@ void GameList::AddGamePopup(QMenu& context_menu, u64 program_id, const std::stri connect(open_save_location, &QAction::triggered, [this, program_id, path]() { emit OpenFolderRequested(program_id, GameListOpenTarget::SaveData, path); }); + connect(start_game, &QAction::triggered, [this, path]() { + emit BootGame(QString::fromStdString(path), 0, StartGameType::Normal); + }); + connect(start_game_global, &QAction::triggered, [this, path]() { + emit BootGame(QString::fromStdString(path), 0, StartGameType::Global); + }); connect(open_mod_location, &QAction::triggered, [this, program_id, path]() { emit OpenFolderRequested(program_id, GameListOpenTarget::ModData, path); }); diff --git a/src/yuzu/game_list.h b/src/yuzu/game_list.h index ab6866735..b630e34ff 100755 --- a/src/yuzu/game_list.h +++ b/src/yuzu/game_list.h @@ -28,6 +28,7 @@ class GameListWorker; class GameListSearchField; class GameListDir; class GMainWindow; +enum class StartGameType; namespace FileSys { class ManualContentProvider; @@ -82,6 +83,7 @@ public: static const QStringList supported_file_extensions; signals: + void BootGame(const QString& game_path, std::size_t program_index, StartGameType type); void GameChosen(const QString& game_path); void ShouldCancelWorker(); void OpenFolderRequested(u64 program_id, GameListOpenTarget target, diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index e683fb920..19339ff2d 100755 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -1094,6 +1094,7 @@ void GMainWindow::OnAppFocusStateChanged(Qt::ApplicationState state) { } void GMainWindow::ConnectWidgetEvents() { + connect(game_list, &GameList::BootGame, this, &GMainWindow::BootGame); connect(game_list, &GameList::GameChosen, this, &GMainWindow::OnGameListLoadFile); connect(game_list, &GameList::OpenDirectory, this, &GMainWindow::OnGameListOpenDirectory); connect(game_list, &GameList::OpenFolderRequested, this, &GMainWindow::OnGameListOpenFolder); @@ -1320,7 +1321,7 @@ void GMainWindow::SelectAndSetCurrentUser() { Settings::values.current_user = dialog.GetIndex(); } -void GMainWindow::BootGame(const QString& filename, std::size_t program_index) { +void GMainWindow::BootGame(const QString& filename, std::size_t program_index, StartGameType type) { LOG_INFO(Frontend, "yuzu starting..."); StoreRecentFile(filename); // Put the filename on top of the list @@ -1332,7 +1333,8 @@ void GMainWindow::BootGame(const QString& filename, std::size_t program_index) { const auto v_file = Core::GetGameFileFromPath(vfs, filename.toUtf8().constData()); const auto loader = Loader::GetLoader(system, v_file, program_index); - if (!(loader == nullptr || loader->ReadProgramId(title_id) != Loader::ResultStatus::Success)) { + if (loader != nullptr && loader->ReadProgramId(title_id) == Loader::ResultStatus::Success && + type == StartGameType::Normal) { // Load per game settings const auto file_path = std::filesystem::path{filename.toStdU16String()}; const auto config_file_name = title_id == 0 diff --git a/src/yuzu/main.h b/src/yuzu/main.h index 490b6889f..11f152cbe 100755 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h @@ -39,6 +39,11 @@ class GameListPlaceholder; class QtSoftwareKeyboardDialog; +enum class StartGameType { + Normal, // Can use custom configuration + Global, // Only uses global configuration +}; + namespace Core::Frontend { struct ControllerParameters; struct InlineAppearParameters; @@ -181,7 +186,8 @@ private: void AllowOSSleep(); bool LoadROM(const QString& filename, std::size_t program_index); - void BootGame(const QString& filename, std::size_t program_index = 0); + void BootGame(const QString& filename, std::size_t program_index = 0, + StartGameType with_config = StartGameType::Normal); void ShutdownGame(); void ShowTelemetryCallout();