diff options
Diffstat (limited to 'src/yuzu/debugger')
| -rw-r--r-- | src/yuzu/debugger/controller.cpp | 66 | ||||
| -rw-r--r-- | src/yuzu/debugger/controller.h | 31 | ||||
| -rw-r--r-- | src/yuzu/debugger/wait_tree.cpp | 189 | ||||
| -rw-r--r-- | src/yuzu/debugger/wait_tree.h | 31 | 
4 files changed, 205 insertions, 112 deletions
| diff --git a/src/yuzu/debugger/controller.cpp b/src/yuzu/debugger/controller.cpp new file mode 100644 index 000000000..2731d948d --- /dev/null +++ b/src/yuzu/debugger/controller.cpp @@ -0,0 +1,66 @@ +// Copyright 2015 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include <QAction> +#include <QLayout> +#include <QString> +#include "core/settings.h" +#include "yuzu/configuration/configure_input_player_widget.h" +#include "yuzu/debugger/controller.h" + +ControllerDialog::ControllerDialog(QWidget* parent) : QWidget(parent, Qt::Dialog) { +    setObjectName(QStringLiteral("Controller")); +    setWindowTitle(tr("Controller P1")); +    resize(500, 350); +    setMinimumSize(500, 350); +    // Remove the "?" button from the titlebar and enable the maximize button +    setWindowFlags((windowFlags() & ~Qt::WindowContextHelpButtonHint) | +                   Qt::WindowMaximizeButtonHint); + +    widget = new PlayerControlPreview(this); +    refreshConfiguration(); +    QLayout* layout = new QVBoxLayout(this); +    layout->setContentsMargins(0, 0, 0, 0); +    layout->addWidget(widget); +    setLayout(layout); + +    // Configure focus so that widget is focusable and the dialog automatically forwards focus to +    // it. +    setFocusProxy(widget); +    widget->setFocusPolicy(Qt::StrongFocus); +    widget->setFocus(); +} + +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); +} + +QAction* ControllerDialog::toggleViewAction() { +    if (toggle_view_action == nullptr) { +        toggle_view_action = new QAction(tr("&Controller P1"), this); +        toggle_view_action->setCheckable(true); +        toggle_view_action->setChecked(isVisible()); +        connect(toggle_view_action, &QAction::toggled, this, &ControllerDialog::setVisible); +    } + +    return toggle_view_action; +} + +void ControllerDialog::showEvent(QShowEvent* ev) { +    if (toggle_view_action) { +        toggle_view_action->setChecked(isVisible()); +    } +    QWidget::showEvent(ev); +} + +void ControllerDialog::hideEvent(QHideEvent* ev) { +    if (toggle_view_action) { +        toggle_view_action->setChecked(isVisible()); +    } +    QWidget::hideEvent(ev); +} diff --git a/src/yuzu/debugger/controller.h b/src/yuzu/debugger/controller.h new file mode 100644 index 000000000..c54750070 --- /dev/null +++ b/src/yuzu/debugger/controller.h @@ -0,0 +1,31 @@ +// Copyright 2015 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <QWidget> + +class QAction; +class QHideEvent; +class QShowEvent; +class PlayerControlPreview; + +class ControllerDialog : public QWidget { +    Q_OBJECT + +public: +    explicit ControllerDialog(QWidget* parent = nullptr); + +    /// Returns a QAction that can be used to toggle visibility of this dialog. +    QAction* toggleViewAction(); +    void refreshConfiguration(); + +protected: +    void showEvent(QShowEvent* ev) override; +    void hideEvent(QHideEvent* ev) override; + +private: +    QAction* toggle_view_action = nullptr; +    PlayerControlPreview* widget; +}; diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp index 0925c10b4..3bca6277b 100644 --- a/src/yuzu/debugger/wait_tree.cpp +++ b/src/yuzu/debugger/wait_tree.cpp @@ -13,12 +13,13 @@  #include "core/arm/arm_interface.h"  #include "core/core.h"  #include "core/hle/kernel/handle_table.h" +#include "core/hle/kernel/k_readable_event.h"  #include "core/hle/kernel/k_scheduler.h" -#include "core/hle/kernel/mutex.h" +#include "core/hle/kernel/k_synchronization_object.h" +#include "core/hle/kernel/k_thread.h"  #include "core/hle/kernel/process.h" -#include "core/hle/kernel/readable_event.h" -#include "core/hle/kernel/synchronization_object.h" -#include "core/hle/kernel/thread.h" +#include "core/hle/kernel/svc_common.h" +#include "core/hle/kernel/svc_types.h"  #include "core/memory.h"  namespace { @@ -90,9 +91,9 @@ std::size_t WaitTreeItem::Row() const {  std::vector<std::unique_ptr<WaitTreeThread>> WaitTreeItem::MakeThreadItemList() {      std::vector<std::unique_ptr<WaitTreeThread>> item_list;      std::size_t row = 0; -    auto add_threads = [&](const std::vector<std::shared_ptr<Kernel::Thread>>& threads) { +    auto add_threads = [&](const std::vector<std::shared_ptr<Kernel::KThread>>& threads) {          for (std::size_t i = 0; i < threads.size(); ++i) { -            if (!threads[i]->IsHLEThread()) { +            if (threads[i]->GetThreadTypeForDebugging() == Kernel::ThreadType::User) {                  item_list.push_back(std::make_unique<WaitTreeThread>(*threads[i]));                  item_list.back()->row = row;              } @@ -116,8 +117,8 @@ QString WaitTreeText::GetText() const {  WaitTreeMutexInfo::WaitTreeMutexInfo(VAddr mutex_address, const Kernel::HandleTable& handle_table)      : mutex_address(mutex_address) {      mutex_value = Core::System::GetInstance().Memory().Read32(mutex_address); -    owner_handle = static_cast<Kernel::Handle>(mutex_value & Kernel::Mutex::MutexOwnerMask); -    owner = handle_table.Get<Kernel::Thread>(owner_handle); +    owner_handle = static_cast<Kernel::Handle>(mutex_value & Kernel::Svc::HandleWaitMask); +    owner = handle_table.Get<Kernel::KThread>(owner_handle);  }  WaitTreeMutexInfo::~WaitTreeMutexInfo() = default; @@ -127,7 +128,7 @@ QString WaitTreeMutexInfo::GetText() const {  }  std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeMutexInfo::GetChildren() const { -    const bool has_waiters = (mutex_value & Kernel::Mutex::MutexHasWaitersFlag) != 0; +    const bool has_waiters = (mutex_value & Kernel::Svc::HandleWaitMask) != 0;      std::vector<std::unique_ptr<WaitTreeItem>> list;      list.push_back(std::make_unique<WaitTreeText>(tr("has waiters: %1").arg(has_waiters))); @@ -139,7 +140,7 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeMutexInfo::GetChildren() cons      return list;  } -WaitTreeCallstack::WaitTreeCallstack(const Kernel::Thread& thread) : thread(thread) {} +WaitTreeCallstack::WaitTreeCallstack(const Kernel::KThread& thread) : thread(thread) {}  WaitTreeCallstack::~WaitTreeCallstack() = default;  QString WaitTreeCallstack::GetText() const { @@ -149,7 +150,7 @@ QString WaitTreeCallstack::GetText() const {  std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeCallstack::GetChildren() const {      std::vector<std::unique_ptr<WaitTreeItem>> list; -    if (thread.IsHLEThread()) { +    if (thread.GetThreadTypeForDebugging() != Kernel::ThreadType::User) {          return list;      } @@ -169,7 +170,8 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeCallstack::GetChildren() cons      return list;  } -WaitTreeSynchronizationObject::WaitTreeSynchronizationObject(const Kernel::SynchronizationObject& o) +WaitTreeSynchronizationObject::WaitTreeSynchronizationObject( +    const Kernel::KSynchronizationObject& o)      : object(o) {}  WaitTreeSynchronizationObject::~WaitTreeSynchronizationObject() = default; @@ -188,12 +190,12 @@ QString WaitTreeSynchronizationObject::GetText() const {  }  std::unique_ptr<WaitTreeSynchronizationObject> WaitTreeSynchronizationObject::make( -    const Kernel::SynchronizationObject& object) { +    const Kernel::KSynchronizationObject& object) {      switch (object.GetHandleType()) {      case Kernel::HandleType::ReadableEvent: -        return std::make_unique<WaitTreeEvent>(static_cast<const Kernel::ReadableEvent&>(object)); +        return std::make_unique<WaitTreeEvent>(static_cast<const Kernel::KReadableEvent&>(object));      case Kernel::HandleType::Thread: -        return std::make_unique<WaitTreeThread>(static_cast<const Kernel::Thread&>(object)); +        return std::make_unique<WaitTreeThread>(static_cast<const Kernel::KThread&>(object));      default:          return std::make_unique<WaitTreeSynchronizationObject>(object);      } @@ -202,7 +204,7 @@ std::unique_ptr<WaitTreeSynchronizationObject> WaitTreeSynchronizationObject::ma  std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeSynchronizationObject::GetChildren() const {      std::vector<std::unique_ptr<WaitTreeItem>> list; -    const auto& threads = object.GetWaitingThreads(); +    const auto& threads = object.GetWaitingThreadsForDebugging();      if (threads.empty()) {          list.push_back(std::make_unique<WaitTreeText>(tr("waited by no thread")));      } else { @@ -211,8 +213,8 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeSynchronizationObject::GetChi      return list;  } -WaitTreeObjectList::WaitTreeObjectList( -    const std::vector<std::shared_ptr<Kernel::SynchronizationObject>>& list, bool w_all) +WaitTreeObjectList::WaitTreeObjectList(const std::vector<Kernel::KSynchronizationObject*>& list, +                                       bool w_all)      : object_list(list), wait_all(w_all) {}  WaitTreeObjectList::~WaitTreeObjectList() = default; @@ -230,54 +232,54 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeObjectList::GetChildren() con      return list;  } -WaitTreeThread::WaitTreeThread(const Kernel::Thread& thread) +WaitTreeThread::WaitTreeThread(const Kernel::KThread& thread)      : WaitTreeSynchronizationObject(thread) {}  WaitTreeThread::~WaitTreeThread() = default;  QString WaitTreeThread::GetText() const { -    const auto& thread = static_cast<const Kernel::Thread&>(object); +    const auto& thread = static_cast<const Kernel::KThread&>(object);      QString status; -    switch (thread.GetStatus()) { -    case Kernel::ThreadStatus::Ready: -        if (!thread.IsPaused()) { -            if (thread.WasRunning()) { -                status = tr("running"); -            } else { -                status = tr("ready"); -            } +    switch (thread.GetState()) { +    case Kernel::ThreadState::Runnable: +        if (!thread.IsSuspended()) { +            status = tr("runnable");          } else {              status = tr("paused");          }          break; -    case Kernel::ThreadStatus::Paused: -        status = tr("paused"); -        break; -    case Kernel::ThreadStatus::WaitHLEEvent: -        status = tr("waiting for HLE return"); -        break; -    case Kernel::ThreadStatus::WaitSleep: -        status = tr("sleeping"); -        break; -    case Kernel::ThreadStatus::WaitIPC: -        status = tr("waiting for IPC reply"); -        break; -    case Kernel::ThreadStatus::WaitSynch: -        status = tr("waiting for objects"); -        break; -    case Kernel::ThreadStatus::WaitMutex: -        status = tr("waiting for mutex"); -        break; -    case Kernel::ThreadStatus::WaitCondVar: -        status = tr("waiting for condition variable"); +    case Kernel::ThreadState::Waiting: +        switch (thread.GetWaitReasonForDebugging()) { +        case Kernel::ThreadWaitReasonForDebugging::Sleep: +            status = tr("sleeping"); +            break; +        case Kernel::ThreadWaitReasonForDebugging::IPC: +            status = tr("waiting for IPC reply"); +            break; +        case Kernel::ThreadWaitReasonForDebugging::Synchronization: +            status = tr("waiting for objects"); +            break; +        case Kernel::ThreadWaitReasonForDebugging::ConditionVar: +            status = tr("waiting for condition variable"); +            break; +        case Kernel::ThreadWaitReasonForDebugging::Arbitration: +            status = tr("waiting for address arbiter"); +            break; +        case Kernel::ThreadWaitReasonForDebugging::Suspended: +            status = tr("waiting for suspend resume"); +            break; +        default: +            status = tr("waiting"); +            break; +        }          break; -    case Kernel::ThreadStatus::WaitArb: -        status = tr("waiting for address arbiter"); +    case Kernel::ThreadState::Initialized: +        status = tr("initialized");          break; -    case Kernel::ThreadStatus::Dormant: -        status = tr("dormant"); +    case Kernel::ThreadState::Terminated: +        status = tr("terminated");          break; -    case Kernel::ThreadStatus::Dead: -        status = tr("dead"); +    default: +        status = tr("unknown");          break;      } @@ -292,33 +294,32 @@ QString WaitTreeThread::GetText() const {  QColor WaitTreeThread::GetColor() const {      const std::size_t color_index = IsDarkTheme() ? 1 : 0; -    const auto& thread = static_cast<const Kernel::Thread&>(object); -    switch (thread.GetStatus()) { -    case Kernel::ThreadStatus::Ready: -        if (!thread.IsPaused()) { -            if (thread.WasRunning()) { -                return QColor(WaitTreeColors[0][color_index]); -            } else { -                return QColor(WaitTreeColors[1][color_index]); -            } +    const auto& thread = static_cast<const Kernel::KThread&>(object); +    switch (thread.GetState()) { +    case Kernel::ThreadState::Runnable: +        if (!thread.IsSuspended()) { +            return QColor(WaitTreeColors[0][color_index]);          } else {              return QColor(WaitTreeColors[2][color_index]);          } -    case Kernel::ThreadStatus::Paused: -        return QColor(WaitTreeColors[3][color_index]); -    case Kernel::ThreadStatus::WaitHLEEvent: -    case Kernel::ThreadStatus::WaitIPC: -        return QColor(WaitTreeColors[4][color_index]); -    case Kernel::ThreadStatus::WaitSleep: -        return QColor(WaitTreeColors[5][color_index]); -    case Kernel::ThreadStatus::WaitSynch: -    case Kernel::ThreadStatus::WaitMutex: -    case Kernel::ThreadStatus::WaitCondVar: -    case Kernel::ThreadStatus::WaitArb: -        return QColor(WaitTreeColors[6][color_index]); -    case Kernel::ThreadStatus::Dormant: +    case Kernel::ThreadState::Waiting: +        switch (thread.GetWaitReasonForDebugging()) { +        case Kernel::ThreadWaitReasonForDebugging::IPC: +            return QColor(WaitTreeColors[4][color_index]); +        case Kernel::ThreadWaitReasonForDebugging::Sleep: +            return QColor(WaitTreeColors[5][color_index]); +        case Kernel::ThreadWaitReasonForDebugging::Synchronization: +        case Kernel::ThreadWaitReasonForDebugging::ConditionVar: +        case Kernel::ThreadWaitReasonForDebugging::Arbitration: +        case Kernel::ThreadWaitReasonForDebugging::Suspended: +            return QColor(WaitTreeColors[6][color_index]); +            break; +        default: +            return QColor(WaitTreeColors[3][color_index]); +        } +    case Kernel::ThreadState::Initialized:          return QColor(WaitTreeColors[7][color_index]); -    case Kernel::ThreadStatus::Dead: +    case Kernel::ThreadState::Terminated:          return QColor(WaitTreeColors[8][color_index]);      default:          return WaitTreeItem::GetColor(); @@ -328,37 +329,31 @@ QColor WaitTreeThread::GetColor() const {  std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeThread::GetChildren() const {      std::vector<std::unique_ptr<WaitTreeItem>> list(WaitTreeSynchronizationObject::GetChildren()); -    const auto& thread = static_cast<const Kernel::Thread&>(object); +    const auto& thread = static_cast<const Kernel::KThread&>(object);      QString processor; -    switch (thread.GetProcessorID()) { -    case Kernel::ThreadProcessorId::THREADPROCESSORID_IDEAL: +    switch (thread.GetActiveCore()) { +    case Kernel::Svc::IdealCoreUseProcessValue:          processor = tr("ideal");          break; -    case Kernel::ThreadProcessorId::THREADPROCESSORID_0: -    case Kernel::ThreadProcessorId::THREADPROCESSORID_1: -    case Kernel::ThreadProcessorId::THREADPROCESSORID_2: -    case Kernel::ThreadProcessorId::THREADPROCESSORID_3: -        processor = tr("core %1").arg(thread.GetProcessorID()); -        break;      default: -        processor = tr("Unknown processor %1").arg(thread.GetProcessorID()); +        processor = tr("core %1").arg(thread.GetActiveCore());          break;      }      list.push_back(std::make_unique<WaitTreeText>(tr("processor = %1").arg(processor))); -    list.push_back( -        std::make_unique<WaitTreeText>(tr("ideal core = %1").arg(thread.GetIdealCore()))); +    list.push_back(std::make_unique<WaitTreeText>( +        tr("ideal core = %1").arg(thread.GetIdealCoreForDebugging())));      list.push_back(std::make_unique<WaitTreeText>(          tr("affinity mask = %1").arg(thread.GetAffinityMask().GetAffinityMask())));      list.push_back(std::make_unique<WaitTreeText>(tr("thread id = %1").arg(thread.GetThreadID())));      list.push_back(std::make_unique<WaitTreeText>(tr("priority = %1(current) / %2(normal)")                                                        .arg(thread.GetPriority()) -                                                      .arg(thread.GetNominalPriority()))); +                                                      .arg(thread.GetBasePriority())));      list.push_back(std::make_unique<WaitTreeText>(          tr("last running ticks = %1").arg(thread.GetLastScheduledTick()))); -    const VAddr mutex_wait_address = thread.GetMutexWaitAddress(); +    const VAddr mutex_wait_address = thread.GetMutexWaitAddressForDebugging();      if (mutex_wait_address != 0) {          const auto& handle_table = thread.GetOwnerProcess()->GetHandleTable();          list.push_back(std::make_unique<WaitTreeMutexInfo>(mutex_wait_address, handle_table)); @@ -366,9 +361,11 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeThread::GetChildren() const {          list.push_back(std::make_unique<WaitTreeText>(tr("not waiting for mutex")));      } -    if (thread.GetStatus() == Kernel::ThreadStatus::WaitSynch) { -        list.push_back(std::make_unique<WaitTreeObjectList>(thread.GetSynchronizationObjects(), -                                                            thread.IsWaitingSync())); +    if (thread.GetState() == Kernel::ThreadState::Waiting && +        thread.GetWaitReasonForDebugging() == +            Kernel::ThreadWaitReasonForDebugging::Synchronization) { +        list.push_back(std::make_unique<WaitTreeObjectList>(thread.GetWaitObjectsForDebugging(), +                                                            thread.IsCancellable()));      }      list.push_back(std::make_unique<WaitTreeCallstack>(thread)); @@ -376,11 +373,11 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeThread::GetChildren() const {      return list;  } -WaitTreeEvent::WaitTreeEvent(const Kernel::ReadableEvent& object) +WaitTreeEvent::WaitTreeEvent(const Kernel::KReadableEvent& object)      : WaitTreeSynchronizationObject(object) {}  WaitTreeEvent::~WaitTreeEvent() = default; -WaitTreeThreadList::WaitTreeThreadList(const std::vector<std::shared_ptr<Kernel::Thread>>& list) +WaitTreeThreadList::WaitTreeThreadList(const std::vector<Kernel::KThread*>& list)      : thread_list(list) {}  WaitTreeThreadList::~WaitTreeThreadList() = default; diff --git a/src/yuzu/debugger/wait_tree.h b/src/yuzu/debugger/wait_tree.h index 8e3bc4b24..3da2fdfd2 100644 --- a/src/yuzu/debugger/wait_tree.h +++ b/src/yuzu/debugger/wait_tree.h @@ -18,9 +18,9 @@ class EmuThread;  namespace Kernel {  class HandleTable; -class ReadableEvent; -class SynchronizationObject; -class Thread; +class KReadableEvent; +class KSynchronizationObject; +class KThread;  } // namespace Kernel  class WaitTreeThread; @@ -83,56 +83,55 @@ private:      VAddr mutex_address;      u32 mutex_value;      Kernel::Handle owner_handle; -    std::shared_ptr<Kernel::Thread> owner; +    std::shared_ptr<Kernel::KThread> owner;  };  class WaitTreeCallstack : public WaitTreeExpandableItem {      Q_OBJECT  public: -    explicit WaitTreeCallstack(const Kernel::Thread& thread); +    explicit WaitTreeCallstack(const Kernel::KThread& thread);      ~WaitTreeCallstack() override;      QString GetText() const override;      std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;  private: -    const Kernel::Thread& thread; +    const Kernel::KThread& thread;  };  class WaitTreeSynchronizationObject : public WaitTreeExpandableItem {      Q_OBJECT  public: -    explicit WaitTreeSynchronizationObject(const Kernel::SynchronizationObject& object); +    explicit WaitTreeSynchronizationObject(const Kernel::KSynchronizationObject& object);      ~WaitTreeSynchronizationObject() override;      static std::unique_ptr<WaitTreeSynchronizationObject> make( -        const Kernel::SynchronizationObject& object); +        const Kernel::KSynchronizationObject& object);      QString GetText() const override;      std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;  protected: -    const Kernel::SynchronizationObject& object; +    const Kernel::KSynchronizationObject& object;  };  class WaitTreeObjectList : public WaitTreeExpandableItem {      Q_OBJECT  public: -    WaitTreeObjectList(const std::vector<std::shared_ptr<Kernel::SynchronizationObject>>& list, -                       bool wait_all); +    WaitTreeObjectList(const std::vector<Kernel::KSynchronizationObject*>& list, bool wait_all);      ~WaitTreeObjectList() override;      QString GetText() const override;      std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;  private: -    const std::vector<std::shared_ptr<Kernel::SynchronizationObject>>& object_list; +    const std::vector<Kernel::KSynchronizationObject*>& object_list;      bool wait_all;  };  class WaitTreeThread : public WaitTreeSynchronizationObject {      Q_OBJECT  public: -    explicit WaitTreeThread(const Kernel::Thread& thread); +    explicit WaitTreeThread(const Kernel::KThread& thread);      ~WaitTreeThread() override;      QString GetText() const override; @@ -143,21 +142,21 @@ public:  class WaitTreeEvent : public WaitTreeSynchronizationObject {      Q_OBJECT  public: -    explicit WaitTreeEvent(const Kernel::ReadableEvent& object); +    explicit WaitTreeEvent(const Kernel::KReadableEvent& object);      ~WaitTreeEvent() override;  };  class WaitTreeThreadList : public WaitTreeExpandableItem {      Q_OBJECT  public: -    explicit WaitTreeThreadList(const std::vector<std::shared_ptr<Kernel::Thread>>& list); +    explicit WaitTreeThreadList(const std::vector<Kernel::KThread*>& list);      ~WaitTreeThreadList() override;      QString GetText() const override;      std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;  private: -    const std::vector<std::shared_ptr<Kernel::Thread>>& thread_list; +    const std::vector<Kernel::KThread*>& thread_list;  };  class WaitTreeModel : public QAbstractItemModel { | 
