Compare commits
28 Commits
__refs_pul
...
__refs_pul
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b3eb08254b | ||
|
|
f09c9b5fcc | ||
|
|
3b5673daca | ||
|
|
5ac018d1df | ||
|
|
df91c9f5e6 | ||
|
|
28eb8c83d4 | ||
|
|
9db569b2d9 | ||
|
|
ada4242c01 | ||
|
|
93f93cb8bc | ||
|
|
afd0e2eb0b | ||
|
|
384cbe3829 | ||
|
|
6119836795 | ||
|
|
31dac5d95f | ||
|
|
1bccbc424c | ||
|
|
71a3c60d95 | ||
|
|
2e1c58b905 | ||
|
|
25b73e135f | ||
|
|
fefc76e5da | ||
|
|
07f6646f7f | ||
|
|
27ce97fd42 | ||
|
|
9ff8504452 | ||
|
|
c8b3d92836 | ||
|
|
166f5d1612 | ||
|
|
c17e1bd7a8 | ||
|
|
4a3d57e469 | ||
|
|
8aeb425669 | ||
|
|
859ba21f6d | ||
|
|
ac48e059bc |
2
externals/dynarmic
vendored
2
externals/dynarmic
vendored
Submodule externals/dynarmic updated: 36c3b289a0...828959caed
@@ -30,9 +30,16 @@
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
SessionRequestHandler::SessionRequestHandler() = default;
|
||||
SessionRequestHandler::SessionRequestHandler(KernelCore& kernel_, const char* service_name_)
|
||||
: kernel{kernel_}, service_thread{kernel.CreateServiceThread(service_name_)} {}
|
||||
|
||||
SessionRequestHandler::~SessionRequestHandler() = default;
|
||||
SessionRequestHandler::~SessionRequestHandler() {
|
||||
kernel.ReleaseServiceThread(service_thread);
|
||||
}
|
||||
|
||||
SessionRequestManager::SessionRequestManager(KernelCore& kernel_) : kernel{kernel_} {}
|
||||
|
||||
SessionRequestManager::~SessionRequestManager() = default;
|
||||
|
||||
void SessionRequestHandler::ClientConnected(KServerSession* session) {
|
||||
session->SetSessionHandler(shared_from_this());
|
||||
|
||||
@@ -46,6 +46,7 @@ class KThread;
|
||||
class KReadableEvent;
|
||||
class KSession;
|
||||
class KWritableEvent;
|
||||
class ServiceThread;
|
||||
|
||||
enum class ThreadWakeupReason;
|
||||
|
||||
@@ -56,7 +57,7 @@ enum class ThreadWakeupReason;
|
||||
*/
|
||||
class SessionRequestHandler : public std::enable_shared_from_this<SessionRequestHandler> {
|
||||
public:
|
||||
SessionRequestHandler();
|
||||
SessionRequestHandler(KernelCore& kernel, const char* service_name_);
|
||||
virtual ~SessionRequestHandler();
|
||||
|
||||
/**
|
||||
@@ -83,6 +84,14 @@ public:
|
||||
* @param server_session ServerSession associated with the connection.
|
||||
*/
|
||||
void ClientDisconnected(KServerSession* session);
|
||||
|
||||
std::shared_ptr<ServiceThread> GetServiceThread() const {
|
||||
return service_thread.lock();
|
||||
}
|
||||
|
||||
protected:
|
||||
KernelCore& kernel;
|
||||
std::weak_ptr<ServiceThread> service_thread;
|
||||
};
|
||||
|
||||
using SessionRequestHandlerPtr = std::shared_ptr<SessionRequestHandler>;
|
||||
@@ -94,7 +103,8 @@ using SessionRequestHandlerPtr = std::shared_ptr<SessionRequestHandler>;
|
||||
*/
|
||||
class SessionRequestManager final {
|
||||
public:
|
||||
SessionRequestManager() = default;
|
||||
explicit SessionRequestManager(KernelCore& kernel);
|
||||
~SessionRequestManager();
|
||||
|
||||
bool IsDomain() const {
|
||||
return is_domain;
|
||||
@@ -142,10 +152,18 @@ public:
|
||||
session_handler = std::move(handler);
|
||||
}
|
||||
|
||||
std::shared_ptr<ServiceThread> GetServiceThread() const {
|
||||
return session_handler->GetServiceThread();
|
||||
}
|
||||
|
||||
private:
|
||||
bool is_domain{};
|
||||
SessionRequestHandlerPtr session_handler;
|
||||
std::vector<SessionRequestHandlerPtr> domain_handlers;
|
||||
|
||||
private:
|
||||
KernelCore& kernel;
|
||||
std::weak_ptr<ServiceThread> service_thread;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,10 +7,11 @@
|
||||
#include <atomic>
|
||||
#include <string>
|
||||
|
||||
#include <boost/intrusive/rbtree.hpp>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/common_funcs.h"
|
||||
#include "common/common_types.h"
|
||||
#include "common/intrusive_red_black_tree.h"
|
||||
#include "core/hle/kernel/k_class_token.h"
|
||||
|
||||
namespace Kernel {
|
||||
@@ -175,7 +176,7 @@ private:
|
||||
|
||||
class KAutoObjectWithListContainer;
|
||||
|
||||
class KAutoObjectWithList : public KAutoObject {
|
||||
class KAutoObjectWithList : public KAutoObject, public boost::intrusive::set_base_hook<> {
|
||||
public:
|
||||
explicit KAutoObjectWithList(KernelCore& kernel_) : KAutoObject(kernel_) {}
|
||||
|
||||
@@ -192,6 +193,10 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
friend bool operator<(const KAutoObjectWithList& left, const KAutoObjectWithList& right) {
|
||||
return &left < &right;
|
||||
}
|
||||
|
||||
public:
|
||||
virtual u64 GetId() const {
|
||||
return reinterpret_cast<u64>(this);
|
||||
@@ -203,8 +208,6 @@ public:
|
||||
|
||||
private:
|
||||
friend class KAutoObjectWithListContainer;
|
||||
|
||||
Common::IntrusiveRedBlackTreeNode list_node;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
|
||||
@@ -9,13 +9,13 @@ namespace Kernel {
|
||||
void KAutoObjectWithListContainer::Register(KAutoObjectWithList* obj) {
|
||||
KScopedLightLock lk(m_lock);
|
||||
|
||||
m_object_list.insert(*obj);
|
||||
m_object_list.insert_unique(*obj);
|
||||
}
|
||||
|
||||
void KAutoObjectWithListContainer::Unregister(KAutoObjectWithList* obj) {
|
||||
KScopedLightLock lk(m_lock);
|
||||
|
||||
m_object_list.erase(m_object_list.iterator_to(*obj));
|
||||
m_object_list.erase(*obj);
|
||||
}
|
||||
|
||||
size_t KAutoObjectWithListContainer::GetOwnedCount(KProcess* owner) {
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
|
||||
#include <atomic>
|
||||
|
||||
#include <boost/intrusive/rbtree.hpp>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/common_funcs.h"
|
||||
#include "common/common_types.h"
|
||||
@@ -23,8 +25,7 @@ class KAutoObjectWithListContainer {
|
||||
YUZU_NON_MOVEABLE(KAutoObjectWithListContainer);
|
||||
|
||||
public:
|
||||
using ListType = Common::IntrusiveRedBlackTreeMemberTraits<
|
||||
&KAutoObjectWithList::list_node>::TreeType<KAutoObjectWithList>;
|
||||
using ListType = boost::intrusive::rbtree<KAutoObjectWithList>;
|
||||
|
||||
public:
|
||||
class ListAccessor : public KScopedLightLock {
|
||||
|
||||
@@ -16,11 +16,11 @@ namespace Kernel {
|
||||
KClientPort::KClientPort(KernelCore& kernel_) : KSynchronizationObject{kernel_} {}
|
||||
KClientPort::~KClientPort() = default;
|
||||
|
||||
void KClientPort::Initialize(KPort* parent_, s32 max_sessions_, std::string&& name_) {
|
||||
void KClientPort::Initialize(KPort* parent_port_, s32 max_sessions_, std::string&& name_) {
|
||||
// Set member variables.
|
||||
num_sessions = 0;
|
||||
peak_sessions = 0;
|
||||
parent = parent_;
|
||||
parent = parent_port_;
|
||||
max_sessions = max_sessions_;
|
||||
name = std::move(name_);
|
||||
}
|
||||
@@ -56,7 +56,8 @@ bool KClientPort::IsSignaled() const {
|
||||
return num_sessions < max_sessions;
|
||||
}
|
||||
|
||||
ResultCode KClientPort::CreateSession(KClientSession** out) {
|
||||
ResultCode KClientPort::CreateSession(KClientSession** out,
|
||||
std::shared_ptr<SessionRequestManager> session_manager) {
|
||||
// Reserve a new session from the resource limit.
|
||||
KScopedResourceReservation session_reservation(kernel.CurrentProcess()->GetResourceLimit(),
|
||||
LimitableResource::Sessions);
|
||||
@@ -101,7 +102,7 @@ ResultCode KClientPort::CreateSession(KClientSession** out) {
|
||||
}
|
||||
|
||||
// Initialize the session.
|
||||
session->Initialize(this, parent->GetName());
|
||||
session->Initialize(this, parent->GetName(), session_manager);
|
||||
|
||||
// Commit the session reservation.
|
||||
session_reservation.Commit();
|
||||
|
||||
@@ -16,6 +16,7 @@ namespace Kernel {
|
||||
class KClientSession;
|
||||
class KernelCore;
|
||||
class KPort;
|
||||
class SessionRequestManager;
|
||||
|
||||
class KClientPort final : public KSynchronizationObject {
|
||||
KERNEL_AUTOOBJECT_TRAITS(KClientPort, KSynchronizationObject);
|
||||
@@ -52,7 +53,8 @@ public:
|
||||
void Destroy() override;
|
||||
bool IsSignaled() const override;
|
||||
|
||||
ResultCode CreateSession(KClientSession** out);
|
||||
ResultCode CreateSession(KClientSession** out,
|
||||
std::shared_ptr<SessionRequestManager> session_manager = nullptr);
|
||||
|
||||
private:
|
||||
std::atomic<s32> num_sessions{};
|
||||
|
||||
@@ -36,9 +36,9 @@ public:
|
||||
explicit KClientSession(KernelCore& kernel_);
|
||||
~KClientSession() override;
|
||||
|
||||
void Initialize(KSession* parent_, std::string&& name_) {
|
||||
void Initialize(KSession* parent_session_, std::string&& name_) {
|
||||
// Set member variables.
|
||||
parent = parent_;
|
||||
parent = parent_session_;
|
||||
name = std::move(name_);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,9 +21,9 @@ public:
|
||||
explicit KReadableEvent(KernelCore& kernel_);
|
||||
~KReadableEvent() override;
|
||||
|
||||
void Initialize(KEvent* parent_, std::string&& name_) {
|
||||
void Initialize(KEvent* parent_event_, std::string&& name_) {
|
||||
is_signaled = false;
|
||||
parent = parent_;
|
||||
parent = parent_event_;
|
||||
name = std::move(name_);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,9 +17,9 @@ namespace Kernel {
|
||||
KServerPort::KServerPort(KernelCore& kernel_) : KSynchronizationObject{kernel_} {}
|
||||
KServerPort::~KServerPort() = default;
|
||||
|
||||
void KServerPort::Initialize(KPort* parent_, std::string&& name_) {
|
||||
void KServerPort::Initialize(KPort* parent_port_, std::string&& name_) {
|
||||
// Set member variables.
|
||||
parent = parent_;
|
||||
parent = parent_port_;
|
||||
name = std::move(name_);
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ public:
|
||||
explicit KServerPort(KernelCore& kernel_);
|
||||
~KServerPort() override;
|
||||
|
||||
void Initialize(KPort* parent_, std::string&& name_);
|
||||
void Initialize(KPort* parent_port_, std::string&& name_);
|
||||
|
||||
/// Whether or not this server port has an HLE handler available.
|
||||
bool HasSessionRequestHandler() const {
|
||||
|
||||
@@ -13,8 +13,10 @@
|
||||
#include "core/hle/kernel/hle_ipc.h"
|
||||
#include "core/hle/kernel/k_client_port.h"
|
||||
#include "core/hle/kernel/k_handle_table.h"
|
||||
#include "core/hle/kernel/k_port.h"
|
||||
#include "core/hle/kernel/k_process.h"
|
||||
#include "core/hle/kernel/k_scheduler.h"
|
||||
#include "core/hle/kernel/k_server_port.h"
|
||||
#include "core/hle/kernel/k_server_session.h"
|
||||
#include "core/hle/kernel/k_session.h"
|
||||
#include "core/hle/kernel/k_thread.h"
|
||||
@@ -23,18 +25,21 @@
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
KServerSession::KServerSession(KernelCore& kernel_)
|
||||
: KSynchronizationObject{kernel_}, manager{std::make_shared<SessionRequestManager>()} {}
|
||||
KServerSession::KServerSession(KernelCore& kernel_) : KSynchronizationObject{kernel_} {}
|
||||
|
||||
KServerSession::~KServerSession() {
|
||||
kernel.ReleaseServiceThread(service_thread);
|
||||
}
|
||||
KServerSession::~KServerSession() {}
|
||||
|
||||
void KServerSession::Initialize(KSession* parent_, std::string&& name_) {
|
||||
void KServerSession::Initialize(KSession* parent_session_, std::string&& name_,
|
||||
std::shared_ptr<SessionRequestManager> manager_) {
|
||||
// Set member variables.
|
||||
parent = parent_;
|
||||
parent = parent_session_;
|
||||
name = std::move(name_);
|
||||
service_thread = kernel.CreateServiceThread(name);
|
||||
|
||||
if (manager_) {
|
||||
manager = manager_;
|
||||
} else {
|
||||
manager = std::make_shared<SessionRequestManager>(kernel);
|
||||
}
|
||||
}
|
||||
|
||||
void KServerSession::Destroy() {
|
||||
@@ -114,9 +119,11 @@ ResultCode KServerSession::QueueSyncRequest(KThread* thread, Core::Memory::Memor
|
||||
|
||||
context->PopulateFromIncomingCommandBuffer(kernel.CurrentProcess()->GetHandleTable(), cmd_buf);
|
||||
|
||||
if (auto strong_ptr = service_thread.lock()) {
|
||||
if (auto strong_ptr = manager->GetServiceThread(); strong_ptr) {
|
||||
strong_ptr->QueueSyncRequest(*parent, std::move(context));
|
||||
return ResultSuccess;
|
||||
} else {
|
||||
ASSERT_MSG(false, "strong_ptr was nullptr!");
|
||||
}
|
||||
|
||||
return ResultSuccess;
|
||||
|
||||
@@ -32,6 +32,7 @@ class HLERequestContext;
|
||||
class KernelCore;
|
||||
class KSession;
|
||||
class SessionRequestHandler;
|
||||
class SessionRequestManager;
|
||||
class KThread;
|
||||
|
||||
class KServerSession final : public KSynchronizationObject,
|
||||
@@ -46,7 +47,8 @@ public:
|
||||
|
||||
void Destroy() override;
|
||||
|
||||
void Initialize(KSession* parent_, std::string&& name_);
|
||||
void Initialize(KSession* parent_session_, std::string&& name_,
|
||||
std::shared_ptr<SessionRequestManager> manager_);
|
||||
|
||||
KSession* GetParent() {
|
||||
return parent;
|
||||
@@ -104,16 +106,6 @@ public:
|
||||
return manager;
|
||||
}
|
||||
|
||||
/// Gets the session request manager, which forwards requests to the underlying service
|
||||
const std::shared_ptr<SessionRequestManager>& GetSessionRequestManager() const {
|
||||
return manager;
|
||||
}
|
||||
|
||||
/// Sets the session request manager, which forwards requests to the underlying service
|
||||
void SetSessionRequestManager(std::shared_ptr<SessionRequestManager> manager_) {
|
||||
manager = std::move(manager_);
|
||||
}
|
||||
|
||||
private:
|
||||
/// Queues a sync request from the emulated application.
|
||||
ResultCode QueueSyncRequest(KThread* thread, Core::Memory::Memory& memory);
|
||||
@@ -131,9 +123,6 @@ private:
|
||||
/// When set to True, converts the session to a domain at the end of the command
|
||||
bool convert_to_domain{};
|
||||
|
||||
/// Thread to dispatch service requests
|
||||
std::weak_ptr<ServiceThread> service_thread;
|
||||
|
||||
/// KSession that owns this KServerSession
|
||||
KSession* parent{};
|
||||
};
|
||||
|
||||
@@ -15,7 +15,8 @@ KSession::KSession(KernelCore& kernel_)
|
||||
: KAutoObjectWithSlabHeapAndContainer{kernel_}, server{kernel_}, client{kernel_} {}
|
||||
KSession::~KSession() = default;
|
||||
|
||||
void KSession::Initialize(KClientPort* port_, const std::string& name_) {
|
||||
void KSession::Initialize(KClientPort* port_, const std::string& name_,
|
||||
std::shared_ptr<SessionRequestManager> manager_) {
|
||||
// Increment reference count.
|
||||
// Because reference count is one on creation, this will result
|
||||
// in a reference count of two. Thus, when both server and client are closed
|
||||
@@ -27,7 +28,7 @@ void KSession::Initialize(KClientPort* port_, const std::string& name_) {
|
||||
KAutoObject::Create(std::addressof(client));
|
||||
|
||||
// Initialize our sub sessions.
|
||||
server.Initialize(this, name_ + ":Server");
|
||||
server.Initialize(this, name_ + ":Server", manager_);
|
||||
client.Initialize(this, name_ + ":Client");
|
||||
|
||||
// Set state and name.
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
class SessionRequestManager;
|
||||
|
||||
class KSession final : public KAutoObjectWithSlabHeapAndContainer<KSession, KAutoObjectWithList> {
|
||||
KERNEL_AUTOOBJECT_TRAITS(KSession, KAutoObject);
|
||||
|
||||
@@ -20,7 +22,8 @@ public:
|
||||
explicit KSession(KernelCore& kernel_);
|
||||
~KSession() override;
|
||||
|
||||
void Initialize(KClientPort* port_, const std::string& name_);
|
||||
void Initialize(KClientPort* port_, const std::string& name_,
|
||||
std::shared_ptr<SessionRequestManager> manager_ = nullptr);
|
||||
|
||||
void Finalize() override;
|
||||
|
||||
|
||||
@@ -13,8 +13,8 @@ KWritableEvent::KWritableEvent(KernelCore& kernel_)
|
||||
|
||||
KWritableEvent::~KWritableEvent() = default;
|
||||
|
||||
void KWritableEvent::Initialize(KEvent* parent_, std::string&& name_) {
|
||||
parent = parent_;
|
||||
void KWritableEvent::Initialize(KEvent* parent_event_, std::string&& name_) {
|
||||
parent = parent_event_;
|
||||
name = std::move(name_);
|
||||
parent->GetReadableEvent().Open();
|
||||
}
|
||||
|
||||
@@ -124,21 +124,21 @@ union ResultCode {
|
||||
constexpr ResultCode(ErrorModule module_, u32 description_)
|
||||
: raw(module.FormatValue(module_) | description.FormatValue(description_)) {}
|
||||
|
||||
constexpr bool IsSuccess() const {
|
||||
[[nodiscard]] constexpr bool IsSuccess() const {
|
||||
return raw == 0;
|
||||
}
|
||||
|
||||
constexpr bool IsError() const {
|
||||
return raw != 0;
|
||||
[[nodiscard]] constexpr bool IsError() const {
|
||||
return !IsSuccess();
|
||||
}
|
||||
};
|
||||
|
||||
constexpr bool operator==(const ResultCode& a, const ResultCode& b) {
|
||||
[[nodiscard]] constexpr bool operator==(const ResultCode& a, const ResultCode& b) {
|
||||
return a.raw == b.raw;
|
||||
}
|
||||
|
||||
constexpr bool operator!=(const ResultCode& a, const ResultCode& b) {
|
||||
return a.raw != b.raw;
|
||||
[[nodiscard]] constexpr bool operator!=(const ResultCode& a, const ResultCode& b) {
|
||||
return !operator==(a, b);
|
||||
}
|
||||
|
||||
// Convenience functions for creating some common kinds of errors:
|
||||
@@ -200,7 +200,7 @@ public:
|
||||
* specify the success code. `success_code` must not be an error code.
|
||||
*/
|
||||
template <typename... Args>
|
||||
static ResultVal WithCode(ResultCode success_code, Args&&... args) {
|
||||
[[nodiscard]] static ResultVal WithCode(ResultCode success_code, Args&&... args) {
|
||||
ResultVal<T> result;
|
||||
result.emplace(success_code, std::forward<Args>(args)...);
|
||||
return result;
|
||||
@@ -259,49 +259,49 @@ public:
|
||||
}
|
||||
|
||||
/// Returns true if the `ResultVal` contains an error code and no value.
|
||||
bool empty() const {
|
||||
[[nodiscard]] bool empty() const {
|
||||
return result_code.IsError();
|
||||
}
|
||||
|
||||
/// Returns true if the `ResultVal` contains a return value.
|
||||
bool Succeeded() const {
|
||||
[[nodiscard]] bool Succeeded() const {
|
||||
return result_code.IsSuccess();
|
||||
}
|
||||
/// Returns true if the `ResultVal` contains an error code and no value.
|
||||
bool Failed() const {
|
||||
[[nodiscard]] bool Failed() const {
|
||||
return empty();
|
||||
}
|
||||
|
||||
ResultCode Code() const {
|
||||
[[nodiscard]] ResultCode Code() const {
|
||||
return result_code;
|
||||
}
|
||||
|
||||
const T& operator*() const {
|
||||
[[nodiscard]] const T& operator*() const {
|
||||
return object;
|
||||
}
|
||||
T& operator*() {
|
||||
[[nodiscard]] T& operator*() {
|
||||
return object;
|
||||
}
|
||||
const T* operator->() const {
|
||||
[[nodiscard]] const T* operator->() const {
|
||||
return &object;
|
||||
}
|
||||
T* operator->() {
|
||||
[[nodiscard]] T* operator->() {
|
||||
return &object;
|
||||
}
|
||||
|
||||
/// Returns the value contained in this `ResultVal`, or the supplied default if it is missing.
|
||||
template <typename U>
|
||||
T ValueOr(U&& value) const {
|
||||
[[nodiscard]] T ValueOr(U&& value) const {
|
||||
return !empty() ? object : std::move(value);
|
||||
}
|
||||
|
||||
/// Asserts that the result succeeded and returns a reference to it.
|
||||
T& Unwrap() & {
|
||||
[[nodiscard]] T& Unwrap() & {
|
||||
ASSERT_MSG(Succeeded(), "Tried to Unwrap empty ResultVal");
|
||||
return **this;
|
||||
}
|
||||
|
||||
T&& Unwrap() && {
|
||||
[[nodiscard]] T&& Unwrap() && {
|
||||
ASSERT_MSG(Succeeded(), "Tried to Unwrap empty ResultVal");
|
||||
return std::move(**this);
|
||||
}
|
||||
@@ -320,7 +320,7 @@ private:
|
||||
* `T` with and creates a success `ResultVal` contained the constructed value.
|
||||
*/
|
||||
template <typename T, typename... Args>
|
||||
ResultVal<T> MakeResult(Args&&... args) {
|
||||
[[nodiscard]] ResultVal<T> MakeResult(Args&&... args) {
|
||||
return ResultVal<T>::WithCode(ResultSuccess, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
@@ -329,7 +329,7 @@ ResultVal<T> MakeResult(Args&&... args) {
|
||||
* copy or move constructing.
|
||||
*/
|
||||
template <typename Arg>
|
||||
ResultVal<std::remove_reference_t<Arg>> MakeResult(Arg&& arg) {
|
||||
[[nodiscard]] ResultVal<std::remove_reference_t<Arg>> MakeResult(Arg&& arg) {
|
||||
return ResultVal<std::remove_reference_t<Arg>>::WithCode(ResultSuccess, std::forward<Arg>(arg));
|
||||
}
|
||||
|
||||
|
||||
@@ -254,8 +254,6 @@ void PL_U::GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_NS, "called");
|
||||
|
||||
// Create shared font memory object
|
||||
auto& kernel = system.Kernel();
|
||||
|
||||
std::memcpy(kernel.GetFontSharedMem().GetPointer(), impl->shared_font->data(),
|
||||
impl->shared_font->size());
|
||||
|
||||
|
||||
@@ -93,8 +93,8 @@ namespace Service {
|
||||
|
||||
ServiceFrameworkBase::ServiceFrameworkBase(Core::System& system_, const char* service_name_,
|
||||
u32 max_sessions_, InvokerFn* handler_invoker_)
|
||||
: system{system_}, service_name{service_name_}, max_sessions{max_sessions_},
|
||||
handler_invoker{handler_invoker_} {}
|
||||
: SessionRequestHandler(system_.Kernel(), service_name_), system{system_},
|
||||
service_name{service_name_}, max_sessions{max_sessions_}, handler_invoker{handler_invoker_} {}
|
||||
|
||||
ServiceFrameworkBase::~ServiceFrameworkBase() {
|
||||
// Wait for other threads to release access before destroying
|
||||
@@ -111,7 +111,7 @@ void ServiceFrameworkBase::InstallAsService(SM::ServiceManager& service_manager)
|
||||
port_installed = true;
|
||||
}
|
||||
|
||||
Kernel::KClientPort& ServiceFrameworkBase::CreatePort(Kernel::KernelCore& kernel) {
|
||||
Kernel::KClientPort& ServiceFrameworkBase::CreatePort() {
|
||||
const auto guard = LockService();
|
||||
|
||||
ASSERT(!port_installed);
|
||||
|
||||
@@ -23,6 +23,7 @@ namespace Kernel {
|
||||
class HLERequestContext;
|
||||
class KClientPort;
|
||||
class KServerSession;
|
||||
class ServiceThread;
|
||||
} // namespace Kernel
|
||||
|
||||
namespace Service {
|
||||
@@ -41,7 +42,7 @@ class ServiceManager;
|
||||
|
||||
static const int kMaxPortSize = 8; ///< Maximum size of a port name (8 characters)
|
||||
/// Arbitrary default number of maximum connections to an HLE service.
|
||||
static const u32 DefaultMaxSessions = 10;
|
||||
static const u32 DefaultMaxSessions = 64;
|
||||
|
||||
/**
|
||||
* This is an non-templated base of ServiceFramework to reduce code bloat and compilation times, it
|
||||
@@ -74,7 +75,7 @@ public:
|
||||
void InvokeRequestTipc(Kernel::HLERequestContext& ctx);
|
||||
|
||||
/// Creates a port pair and registers it on the kernel's global port registry.
|
||||
Kernel::KClientPort& CreatePort(Kernel::KernelCore& kernel);
|
||||
Kernel::KClientPort& CreatePort();
|
||||
|
||||
/// Handles a synchronization request for the service.
|
||||
ResultCode HandleSyncRequest(Kernel::KServerSession& session,
|
||||
|
||||
@@ -28,42 +28,25 @@ void Controller::ConvertCurrentObjectToDomain(Kernel::HLERequestContext& ctx) {
|
||||
}
|
||||
|
||||
void Controller::CloneCurrentObject(Kernel::HLERequestContext& ctx) {
|
||||
// TODO(bunnei): This is just creating a new handle to the same Session. I assume this is wrong
|
||||
// and that we probably want to actually make an entirely new Session, but we still need to
|
||||
// verify this on hardware.
|
||||
|
||||
LOG_DEBUG(Service, "called");
|
||||
|
||||
auto& kernel = system.Kernel();
|
||||
auto* session = ctx.Session()->GetParent();
|
||||
auto* port = session->GetParent()->GetParent();
|
||||
auto& parent_session = *ctx.Session()->GetParent();
|
||||
auto& parent_port = parent_session.GetParent()->GetParent()->GetClientPort();
|
||||
auto& session_manager = parent_session.GetServerSession().GetSessionRequestManager();
|
||||
|
||||
// Reserve a new session from the process resource limit.
|
||||
Kernel::KScopedResourceReservation session_reservation(
|
||||
kernel.CurrentProcess()->GetResourceLimit(), Kernel::LimitableResource::Sessions);
|
||||
if (!session_reservation.Succeeded()) {
|
||||
// Create a session.
|
||||
Kernel::KClientSession* session{};
|
||||
const ResultCode result = parent_port.CreateSession(std::addressof(session), session_manager);
|
||||
if (result.IsError()) {
|
||||
LOG_CRITICAL(Service, "CreateSession failed with error 0x{:08X}", result.raw);
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(Kernel::ResultLimitReached);
|
||||
rb.Push(result);
|
||||
}
|
||||
|
||||
// Create a new session.
|
||||
auto* clone = Kernel::KSession::Create(kernel);
|
||||
clone->Initialize(&port->GetClientPort(), session->GetName());
|
||||
|
||||
// Commit the session reservation.
|
||||
session_reservation.Commit();
|
||||
|
||||
// Enqueue the session with the named port.
|
||||
port->EnqueueSession(&clone->GetServerSession());
|
||||
|
||||
// Set the session request manager.
|
||||
clone->GetServerSession().SetSessionRequestManager(
|
||||
session->GetServerSession().GetSessionRequestManager());
|
||||
|
||||
// We succeeded.
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushMoveObjects(clone->GetClientSession());
|
||||
rb.PushMoveObjects(session);
|
||||
}
|
||||
|
||||
void Controller::CloneCurrentObjectEx(Kernel::HLERequestContext& ctx) {
|
||||
|
||||
@@ -46,7 +46,7 @@ Kernel::KClientPort& ServiceManager::InterfaceFactory(ServiceManager& self, Core
|
||||
self.sm_interface = sm;
|
||||
self.controller_interface = std::make_unique<Controller>(system);
|
||||
|
||||
return sm->CreatePort(system.Kernel());
|
||||
return sm->CreatePort();
|
||||
}
|
||||
|
||||
ResultVal<Kernel::KServerPort*> ServiceManager::RegisterService(std::string name,
|
||||
|
||||
@@ -110,6 +110,8 @@ public:
|
||||
|
||||
void BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr gpu_addr, u32 size);
|
||||
|
||||
void DisableGraphicsUniformBuffer(size_t stage, u32 index);
|
||||
|
||||
void UpdateGraphicsBuffers(bool is_indexed);
|
||||
|
||||
void UpdateComputeBuffers();
|
||||
@@ -419,10 +421,6 @@ template <class P>
|
||||
void BufferCache<P>::BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr gpu_addr,
|
||||
u32 size) {
|
||||
const std::optional<VAddr> cpu_addr = gpu_memory.GpuToCpuAddress(gpu_addr);
|
||||
if (!cpu_addr) {
|
||||
uniform_buffers[stage][index] = NULL_BINDING;
|
||||
return;
|
||||
}
|
||||
const Binding binding{
|
||||
.cpu_addr = *cpu_addr,
|
||||
.size = size,
|
||||
@@ -431,6 +429,11 @@ void BufferCache<P>::BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr
|
||||
uniform_buffers[stage][index] = binding;
|
||||
}
|
||||
|
||||
template <class P>
|
||||
void BufferCache<P>::DisableGraphicsUniformBuffer(size_t stage, u32 index) {
|
||||
uniform_buffers[stage][index] = NULL_BINDING;
|
||||
}
|
||||
|
||||
template <class P>
|
||||
void BufferCache<P>::UpdateGraphicsBuffers(bool is_indexed) {
|
||||
MICROPROFILE_SCOPE(GPU_PrepareBuffers);
|
||||
|
||||
@@ -578,8 +578,12 @@ void Maxwell3D::ProcessCBBind(size_t stage_index) {
|
||||
buffer.size = regs.const_buffer.cb_size;
|
||||
|
||||
const bool is_enabled = bind_data.valid.Value() != 0;
|
||||
const GPUVAddr gpu_addr = is_enabled ? regs.const_buffer.BufferAddress() : 0;
|
||||
const u32 size = is_enabled ? regs.const_buffer.cb_size : 0;
|
||||
if (!is_enabled) {
|
||||
rasterizer->DisableGraphicsUniformBuffer(stage_index, bind_data.index);
|
||||
return;
|
||||
}
|
||||
const GPUVAddr gpu_addr = regs.const_buffer.BufferAddress();
|
||||
const u32 size = regs.const_buffer.cb_size;
|
||||
rasterizer->BindGraphicsUniformBuffer(stage_index, bind_data.index, gpu_addr, size);
|
||||
}
|
||||
|
||||
|
||||
@@ -163,6 +163,9 @@ std::optional<GPUVAddr> MemoryManager::FindFreeRange(std::size_t size, std::size
|
||||
}
|
||||
|
||||
std::optional<VAddr> MemoryManager::GpuToCpuAddress(GPUVAddr gpu_addr) const {
|
||||
if (gpu_addr == 0) {
|
||||
return std::nullopt;
|
||||
}
|
||||
const auto page_entry{GetPageEntry(gpu_addr)};
|
||||
if (!page_entry.IsValid()) {
|
||||
return std::nullopt;
|
||||
|
||||
@@ -54,6 +54,9 @@ public:
|
||||
virtual void BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr gpu_addr,
|
||||
u32 size) = 0;
|
||||
|
||||
/// Signal disabling of a uniform buffer
|
||||
virtual void DisableGraphicsUniformBuffer(size_t stage, u32 index) = 0;
|
||||
|
||||
/// Signal a GPU based semaphore as a fence
|
||||
virtual void SignalSemaphore(GPUVAddr addr, u32 value) = 0;
|
||||
|
||||
|
||||
@@ -526,6 +526,10 @@ void RasterizerOpenGL::BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAd
|
||||
buffer_cache.BindGraphicsUniformBuffer(stage, index, gpu_addr, size);
|
||||
}
|
||||
|
||||
void RasterizerOpenGL::DisableGraphicsUniformBuffer(size_t stage, u32 index) {
|
||||
buffer_cache.DisableGraphicsUniformBuffer(stage, index);
|
||||
}
|
||||
|
||||
void RasterizerOpenGL::FlushAll() {}
|
||||
|
||||
void RasterizerOpenGL::FlushRegion(VAddr addr, u64 size) {
|
||||
|
||||
@@ -72,6 +72,7 @@ public:
|
||||
void ResetCounter(VideoCore::QueryType type) override;
|
||||
void Query(GPUVAddr gpu_addr, VideoCore::QueryType type, std::optional<u64> timestamp) override;
|
||||
void BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr gpu_addr, u32 size) override;
|
||||
void DisableGraphicsUniformBuffer(size_t stage, u32 index) override;
|
||||
void FlushAll() override;
|
||||
void FlushRegion(VAddr addr, u64 size) override;
|
||||
bool MustFlushRegion(VAddr addr, u64 size) override;
|
||||
|
||||
@@ -476,6 +476,10 @@ void RasterizerVulkan::BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAd
|
||||
buffer_cache.BindGraphicsUniformBuffer(stage, index, gpu_addr, size);
|
||||
}
|
||||
|
||||
void Vulkan::RasterizerVulkan::DisableGraphicsUniformBuffer(size_t stage, u32 index) {
|
||||
buffer_cache.DisableGraphicsUniformBuffer(stage, index);
|
||||
}
|
||||
|
||||
void RasterizerVulkan::FlushAll() {}
|
||||
|
||||
void RasterizerVulkan::FlushRegion(VAddr addr, u64 size) {
|
||||
|
||||
@@ -64,6 +64,7 @@ public:
|
||||
void ResetCounter(VideoCore::QueryType type) override;
|
||||
void Query(GPUVAddr gpu_addr, VideoCore::QueryType type, std::optional<u64> timestamp) override;
|
||||
void BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr gpu_addr, u32 size) override;
|
||||
void DisableGraphicsUniformBuffer(size_t stage, u32 index) override;
|
||||
void FlushAll() override;
|
||||
void FlushRegion(VAddr addr, u64 size) override;
|
||||
bool MustFlushRegion(VAddr addr, u64 size) override;
|
||||
|
||||
@@ -27,6 +27,8 @@ ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry,
|
||||
|
||||
ui->inputTab->Initialize(input_subsystem);
|
||||
|
||||
ui->generalTab->SetResetCallback([&] { this->close(); });
|
||||
|
||||
SetConfiguration();
|
||||
PopulateSelectionList();
|
||||
|
||||
|
||||
@@ -2,11 +2,15 @@
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
#include <QCheckBox>
|
||||
#include <QMessageBox>
|
||||
#include <QSpinBox>
|
||||
#include "common/settings.h"
|
||||
#include "core/core.h"
|
||||
#include "ui_configure_general.h"
|
||||
#include "yuzu/configuration/config.h"
|
||||
#include "yuzu/configuration/configuration_shared.h"
|
||||
#include "yuzu/configuration/configure_general.h"
|
||||
#include "yuzu/uisettings.h"
|
||||
@@ -23,6 +27,9 @@ ConfigureGeneral::ConfigureGeneral(QWidget* parent)
|
||||
connect(ui->toggle_frame_limit, &QCheckBox::clicked, ui->frame_limit,
|
||||
[this]() { ui->frame_limit->setEnabled(ui->toggle_frame_limit->isChecked()); });
|
||||
}
|
||||
|
||||
connect(ui->button_reset_defaults, &QPushButton::clicked, this,
|
||||
&ConfigureGeneral::ResetDefaults);
|
||||
}
|
||||
|
||||
ConfigureGeneral::~ConfigureGeneral() = default;
|
||||
@@ -41,6 +48,8 @@ void ConfigureGeneral::SetConfiguration() {
|
||||
ui->toggle_frame_limit->setChecked(Settings::values.use_frame_limit.GetValue());
|
||||
ui->frame_limit->setValue(Settings::values.frame_limit.GetValue());
|
||||
|
||||
ui->button_reset_defaults->setEnabled(runtime_lock);
|
||||
|
||||
if (Settings::IsConfiguringGlobal()) {
|
||||
ui->frame_limit->setEnabled(Settings::values.use_frame_limit.GetValue());
|
||||
} else {
|
||||
@@ -49,6 +58,25 @@ void ConfigureGeneral::SetConfiguration() {
|
||||
}
|
||||
}
|
||||
|
||||
// Called to set the callback when resetting settings to defaults
|
||||
void ConfigureGeneral::SetResetCallback(std::function<void()> callback) {
|
||||
reset_callback = std::move(callback);
|
||||
}
|
||||
|
||||
void ConfigureGeneral::ResetDefaults() {
|
||||
QMessageBox::StandardButton answer = QMessageBox::question(
|
||||
this, tr("yuzu"),
|
||||
tr("This reset all settings and remove all per-game configurations. This will not delete "
|
||||
"game directories, profiles, or input profiles. Proceed?"),
|
||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
|
||||
if (answer == QMessageBox::No) {
|
||||
return;
|
||||
}
|
||||
UISettings::values.reset_to_defaults = true;
|
||||
UISettings::values.is_game_list_reload_pending.exchange(true);
|
||||
reset_callback();
|
||||
}
|
||||
|
||||
void ConfigureGeneral::ApplyConfiguration() {
|
||||
ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_multi_core, ui->use_multi_core,
|
||||
use_multi_core);
|
||||
@@ -105,6 +133,8 @@ void ConfigureGeneral::SetupPerGameUI() {
|
||||
ui->toggle_background_pause->setVisible(false);
|
||||
ui->toggle_hide_mouse->setVisible(false);
|
||||
|
||||
ui->button_reset_defaults->setVisible(false);
|
||||
|
||||
ConfigurationShared::SetColoredTristate(ui->toggle_frame_limit,
|
||||
Settings::values.use_frame_limit, use_frame_limit);
|
||||
ConfigurationShared::SetColoredTristate(ui->use_multi_core, Settings::values.use_multi_core,
|
||||
|
||||
@@ -4,9 +4,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <QWidget>
|
||||
|
||||
class ConfigureDialog;
|
||||
|
||||
namespace ConfigurationShared {
|
||||
enum class CheckState;
|
||||
}
|
||||
@@ -24,6 +27,8 @@ public:
|
||||
explicit ConfigureGeneral(QWidget* parent = nullptr);
|
||||
~ConfigureGeneral() override;
|
||||
|
||||
void SetResetCallback(std::function<void()> callback);
|
||||
void ResetDefaults();
|
||||
void ApplyConfiguration();
|
||||
|
||||
private:
|
||||
@@ -34,6 +39,8 @@ private:
|
||||
|
||||
void SetupPerGameUI();
|
||||
|
||||
std::function<void()> reset_callback;
|
||||
|
||||
std::unique_ptr<Ui::ConfigureGeneral> ui;
|
||||
|
||||
ConfigurationShared::CheckState use_frame_limit;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>300</width>
|
||||
<width>329</width>
|
||||
<height>407</height>
|
||||
</rect>
|
||||
</property>
|
||||
@@ -104,6 +104,45 @@
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="layout_reset">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="button_reset_defaults">
|
||||
<property name="text">
|
||||
<string>Reset All Settings</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="spacer_reset">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
|
||||
@@ -85,6 +85,8 @@ void PlayerControlPreview::SetConnectedStatus(bool checked) {
|
||||
led_color[1] = led_pattern.position2 ? colors.led_on : colors.led_off;
|
||||
led_color[2] = led_pattern.position3 ? colors.led_on : colors.led_off;
|
||||
led_color[3] = led_pattern.position4 ? colors.led_on : colors.led_off;
|
||||
is_enabled = checked;
|
||||
ResetInputs();
|
||||
}
|
||||
|
||||
void PlayerControlPreview::SetControllerType(const Settings::ControllerType type) {
|
||||
@@ -108,6 +110,7 @@ void PlayerControlPreview::EndMapping() {
|
||||
analog_mapping_index = Settings::NativeAnalog::NumAnalogs;
|
||||
mapping_active = false;
|
||||
blink_counter = 0;
|
||||
ResetInputs();
|
||||
}
|
||||
|
||||
void PlayerControlPreview::UpdateColors() {
|
||||
@@ -156,7 +159,23 @@ void PlayerControlPreview::UpdateColors() {
|
||||
// colors.right = QColor(Settings::values.players.GetValue()[player_index].body_color_right);
|
||||
}
|
||||
|
||||
void PlayerControlPreview::ResetInputs() {
|
||||
for (std::size_t index = 0; index < button_values.size(); ++index) {
|
||||
button_values[index] = false;
|
||||
}
|
||||
|
||||
for (std::size_t index = 0; index < axis_values.size(); ++index) {
|
||||
axis_values[index].properties = {0, 1, 0};
|
||||
axis_values[index].value = {0, 0};
|
||||
axis_values[index].raw_value = {0, 0};
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
void PlayerControlPreview::UpdateInput() {
|
||||
if (!is_enabled && !mapping_active) {
|
||||
return;
|
||||
}
|
||||
bool input_changed = false;
|
||||
const auto& button_state = buttons;
|
||||
for (std::size_t index = 0; index < button_values.size(); ++index) {
|
||||
|
||||
@@ -100,6 +100,7 @@ private:
|
||||
|
||||
static LedPattern GetColorPattern(std::size_t index, bool player_on);
|
||||
void UpdateColors();
|
||||
void ResetInputs();
|
||||
|
||||
// Draw controller functions
|
||||
void DrawHandheldController(QPainter& p, QPointF center);
|
||||
@@ -176,6 +177,7 @@ private:
|
||||
using StickArray =
|
||||
std::array<std::unique_ptr<Input::AnalogDevice>, Settings::NativeAnalog::NUM_STICKS_HID>;
|
||||
|
||||
bool is_enabled{};
|
||||
bool mapping_active{};
|
||||
int blink_counter{};
|
||||
QColor button_color{};
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ ControllerDialog::ControllerDialog(QWidget* parent) : QWidget(parent, Qt::Dialog
|
||||
// Configure focus so that widget is focusable and the dialog automatically forwards focus to
|
||||
// it.
|
||||
setFocusProxy(widget);
|
||||
widget->SetConnectedStatus(false);
|
||||
widget->setFocusPolicy(Qt::StrongFocus);
|
||||
widget->setFocus();
|
||||
}
|
||||
@@ -36,9 +37,8 @@ void ControllerDialog::refreshConfiguration() {
|
||||
const auto& players = Settings::values.players.GetValue();
|
||||
constexpr std::size_t player = 0;
|
||||
widget->SetPlayerInputRaw(player, players[player].buttons, players[player].analogs);
|
||||
widget->SetConnectedStatus(players[player].connected);
|
||||
widget->SetControllerType(players[player].controller_type);
|
||||
widget->repaint();
|
||||
widget->SetConnectedStatus(players[player].connected);
|
||||
}
|
||||
|
||||
QAction* ControllerDialog::toggleViewAction() {
|
||||
@@ -56,6 +56,7 @@ void ControllerDialog::showEvent(QShowEvent* ev) {
|
||||
if (toggle_view_action) {
|
||||
toggle_view_action->setChecked(isVisible());
|
||||
}
|
||||
refreshConfiguration();
|
||||
QWidget::showEvent(ev);
|
||||
}
|
||||
|
||||
@@ -63,5 +64,6 @@ void ControllerDialog::hideEvent(QHideEvent* ev) {
|
||||
if (toggle_view_action) {
|
||||
toggle_view_action->setChecked(isVisible());
|
||||
}
|
||||
widget->SetConnectedStatus(false);
|
||||
QWidget::hideEvent(ev);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
@@ -2596,13 +2598,53 @@ void GMainWindow::OnConfigure() {
|
||||
&GMainWindow::OnLanguageChanged);
|
||||
|
||||
const auto result = configure_dialog.exec();
|
||||
if (result != QDialog::Accepted && !UISettings::values.configuration_applied) {
|
||||
if (result != QDialog::Accepted && !UISettings::values.configuration_applied &&
|
||||
!UISettings::values.reset_to_defaults) {
|
||||
// Runs if the user hit Cancel or closed the window, and did not ever press the Apply button
|
||||
// or `Reset to Defaults` button
|
||||
return;
|
||||
} else if (result == QDialog::Accepted) {
|
||||
// Only apply new changes if user hit Okay
|
||||
// This is here to avoid applying changes if the user hit Apply, made some changes, then hit
|
||||
// Cancel
|
||||
configure_dialog.ApplyConfiguration();
|
||||
controller_dialog->refreshConfiguration();
|
||||
} else if (UISettings::values.reset_to_defaults) {
|
||||
LOG_INFO(Frontend, "Resetting all settings to defaults");
|
||||
if (!Common::FS::RemoveFile(config->GetConfigFilePath())) {
|
||||
LOG_WARNING(Frontend, "Failed to remove configuration file");
|
||||
}
|
||||
if (!Common::FS::RemoveDirContentsRecursively(
|
||||
Common::FS::GetYuzuPath(Common::FS::YuzuPath::ConfigDir) / "custom")) {
|
||||
LOG_WARNING(Frontend, "Failed to remove custom configuration files");
|
||||
}
|
||||
if (!Common::FS::RemoveDirRecursively(
|
||||
Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir) / "game_list")) {
|
||||
LOG_WARNING(Frontend, "Failed to remove game metadata cache files");
|
||||
}
|
||||
|
||||
// Explicitly save the game directories, since reinitializing config does not explicitly do
|
||||
// so.
|
||||
QVector<UISettings::GameDir> old_game_dirs = std::move(UISettings::values.game_dirs);
|
||||
QVector<u64> old_favorited_ids = std::move(UISettings::values.favorited_ids);
|
||||
|
||||
Settings::values.disabled_addons.clear();
|
||||
|
||||
config = std::make_unique<Config>();
|
||||
UISettings::values.reset_to_defaults = false;
|
||||
|
||||
UISettings::values.game_dirs = std::move(old_game_dirs);
|
||||
UISettings::values.favorited_ids = std::move(old_favorited_ids);
|
||||
|
||||
InitializeRecentFileMenuActions();
|
||||
|
||||
SetDefaultUIGeometry();
|
||||
RestoreUIState();
|
||||
|
||||
ShowTelemetryCallout();
|
||||
}
|
||||
controller_dialog->refreshConfiguration();
|
||||
InitializeHotkeys();
|
||||
|
||||
if (UISettings::values.theme != old_theme) {
|
||||
UpdateUITheme();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -97,6 +97,7 @@ struct Values {
|
||||
bool cache_game_list;
|
||||
|
||||
bool configuration_applied;
|
||||
bool reset_to_defaults;
|
||||
};
|
||||
|
||||
extern Values values;
|
||||
|
||||
@@ -317,6 +317,43 @@ void Config::ReadValues() {
|
||||
sdl2_config->GetInteger("ControlsGeneral", "touch_diameter_x", 15);
|
||||
Settings::values.touchscreen.diameter_y =
|
||||
sdl2_config->GetInteger("ControlsGeneral", "touch_diameter_y", 15);
|
||||
|
||||
int num_touch_from_button_maps =
|
||||
sdl2_config->GetInteger("ControlsGeneral", "touch_from_button_map", 0);
|
||||
if (num_touch_from_button_maps > 0) {
|
||||
for (int i = 0; i < num_touch_from_button_maps; ++i) {
|
||||
Settings::TouchFromButtonMap map;
|
||||
map.name = sdl2_config->Get("ControlsGeneral",
|
||||
std::string("touch_from_button_maps_") + std::to_string(i) +
|
||||
std::string("_name"),
|
||||
"default");
|
||||
const int num_touch_maps = sdl2_config->GetInteger(
|
||||
"ControlsGeneral",
|
||||
std::string("touch_from_button_maps_") + std::to_string(i) + std::string("_count"),
|
||||
0);
|
||||
map.buttons.reserve(num_touch_maps);
|
||||
|
||||
for (int j = 0; j < num_touch_maps; ++j) {
|
||||
std::string touch_mapping =
|
||||
sdl2_config->Get("ControlsGeneral",
|
||||
std::string("touch_from_button_maps_") + std::to_string(i) +
|
||||
std::string("_bind_") + std::to_string(j),
|
||||
"");
|
||||
map.buttons.emplace_back(std::move(touch_mapping));
|
||||
}
|
||||
|
||||
Settings::values.touch_from_button_maps.emplace_back(std::move(map));
|
||||
}
|
||||
} else {
|
||||
Settings::values.touch_from_button_maps.emplace_back(
|
||||
Settings::TouchFromButtonMap{"default", {}});
|
||||
num_touch_from_button_maps = 1;
|
||||
}
|
||||
Settings::values.use_touch_from_button =
|
||||
sdl2_config->GetBoolean("ControlsGeneral", "use_touch_from_button", false);
|
||||
Settings::values.touch_from_button_map_index =
|
||||
std::clamp(Settings::values.touch_from_button_map_index, 0, num_touch_from_button_maps - 1);
|
||||
|
||||
Settings::values.udp_input_servers =
|
||||
sdl2_config->Get("Controls", "udp_input_address", InputCommon::CemuhookUDP::DEFAULT_SRV);
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
namespace DefaultINI {
|
||||
|
||||
const char* sdl2_config_file = R"(
|
||||
[Controls]
|
||||
[ControlsGeneral]
|
||||
# The input devices and parameters for each Switch native input
|
||||
# It should be in the format of "engine:[engine_name],[param1]:[value1],[param2]:[value2]..."
|
||||
# Escape characters $0 (for ':'), $1 (for ',') and $2 (for '$') can be used in values
|
||||
@@ -86,6 +86,18 @@ motion_device=
|
||||
# - "min_x", "min_y", "max_x", "max_y": defines the udp device's touch screen coordinate system
|
||||
touch_device=
|
||||
|
||||
# Whether to enable or disable touch input from button
|
||||
# 0 (default): Disabled, 1: Enabled
|
||||
use_touch_from_button=
|
||||
|
||||
# for mapping buttons to touch inputs.
|
||||
#touch_from_button_map=1
|
||||
#touch_from_button_maps_0_name=default
|
||||
#touch_from_button_maps_0_count=2
|
||||
#touch_from_button_maps_0_bind_0=foo
|
||||
#touch_from_button_maps_0_bind_1=bar
|
||||
# etc.
|
||||
|
||||
# Most desktop operating systems do not expose a way to poll the motion state of the controllers
|
||||
# so as a way around it, cemuhook created a udp client/server protocol to broadcast the data directly
|
||||
# from a controller device to the client program. Citra has a client that can connect and read
|
||||
|
||||
@@ -32,17 +32,17 @@
|
||||
|
||||
class SDLGLContext : public Core::Frontend::GraphicsContext {
|
||||
public:
|
||||
explicit SDLGLContext() {
|
||||
// create a hidden window to make the shared context against
|
||||
window = SDL_CreateWindow(NULL, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 0, 0,
|
||||
SDL_WINDOW_HIDDEN | SDL_WINDOW_OPENGL);
|
||||
explicit SDLGLContext(SDL_Window* window_) : window{window_} {
|
||||
context = SDL_GL_CreateContext(window);
|
||||
}
|
||||
|
||||
~SDLGLContext() {
|
||||
DoneCurrent();
|
||||
SDL_GL_DeleteContext(context);
|
||||
SDL_DestroyWindow(window);
|
||||
}
|
||||
|
||||
void SwapBuffers() override {
|
||||
SDL_GL_SwapWindow(window);
|
||||
}
|
||||
|
||||
void MakeCurrent() override {
|
||||
@@ -114,9 +114,6 @@ EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(InputCommon::InputSubsystem* input_subsyste
|
||||
exit(1);
|
||||
}
|
||||
|
||||
dummy_window = SDL_CreateWindow(NULL, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 0, 0,
|
||||
SDL_WINDOW_HIDDEN | SDL_WINDOW_OPENGL);
|
||||
|
||||
SetWindowIcon();
|
||||
|
||||
if (fullscreen) {
|
||||
@@ -159,5 +156,5 @@ EmuWindow_SDL2_GL::~EmuWindow_SDL2_GL() {
|
||||
}
|
||||
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext> EmuWindow_SDL2_GL::CreateSharedContext() const {
|
||||
return std::make_unique<SDLGLContext>();
|
||||
return std::make_unique<SDLGLContext>(render_window);
|
||||
}
|
||||
|
||||
@@ -20,9 +20,6 @@ public:
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext> CreateSharedContext() const override;
|
||||
|
||||
private:
|
||||
/// Fake hidden window for the core context
|
||||
SDL_Window* dummy_window{};
|
||||
|
||||
/// Whether the GPU and driver supports the OpenGL extension required
|
||||
bool SupportsRequiredGLExtensions();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user