diff options
Diffstat (limited to 'src/yuzu')
| -rw-r--r-- | src/yuzu/CMakeLists.txt | 13 | ||||
| -rw-r--r-- | src/yuzu/bootmanager.cpp | 13 | ||||
| -rw-r--r-- | src/yuzu/configuration/config.cpp | 6 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_debug.cpp | 22 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_debug.ui | 41 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_graphics.cpp | 2 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_graphics.ui | 7 | ||||
| -rw-r--r-- | src/yuzu/debugger/console.cpp | 45 | ||||
| -rw-r--r-- | src/yuzu/debugger/console.h | 14 | ||||
| -rw-r--r-- | src/yuzu/debugger/registers.cpp | 190 | ||||
| -rw-r--r-- | src/yuzu/debugger/registers.h | 42 | ||||
| -rw-r--r-- | src/yuzu/debugger/registers.ui | 40 | ||||
| -rw-r--r-- | src/yuzu/debugger/wait_tree.cpp | 4 | ||||
| -rw-r--r-- | src/yuzu/game_list.cpp | 37 | ||||
| -rw-r--r-- | src/yuzu/main.cpp | 55 | ||||
| -rw-r--r-- | src/yuzu/main.h | 3 | ||||
| -rw-r--r-- | src/yuzu/main.ui | 6 | ||||
| -rw-r--r-- | src/yuzu/ui_settings.h | 3 | 
18 files changed, 227 insertions, 316 deletions
| diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index 5af3154d7..7de919a8e 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt @@ -30,10 +30,10 @@ add_executable(yuzu      debugger/graphics/graphics_breakpoints_p.h      debugger/graphics/graphics_surface.cpp      debugger/graphics/graphics_surface.h +    debugger/console.cpp +    debugger/console.h      debugger/profiler.cpp      debugger/profiler.h -    debugger/registers.cpp -    debugger/registers.h      debugger/wait_tree.cpp      debugger/wait_tree.h      game_list.cpp @@ -60,7 +60,6 @@ set(UIS      configuration/configure_graphics.ui      configuration/configure_input.ui      configuration/configure_system.ui -    debugger/registers.ui      hotkeys.ui      main.ui  ) @@ -84,6 +83,14 @@ if (APPLE)      target_sources(yuzu PRIVATE ${MACOSX_ICON})      set_target_properties(yuzu PROPERTIES MACOSX_BUNDLE TRUE)      set_target_properties(yuzu PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist) +elseif(WIN32) +    # compile as a win32 gui application instead of a console application +    target_link_libraries(yuzu PRIVATE Qt5::WinMain) +    if(MSVC) +        set_target_properties(yuzu PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS") +    elseif(MINGW) +        set_target_properties(yuzu PROPERTIES LINK_FLAGS_RELEASE "-mwindows") +    endif()  endif()  create_target_directory_groups(yuzu) diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index 5c17cd0d9..833085559 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp @@ -127,13 +127,14 @@ void GRenderWindow::moveContext() {  }  void GRenderWindow::SwapBuffers() { -#if !defined(QT_NO_DEBUG) -    // Qt debug runtime prints a bogus warning on the console if you haven't called makeCurrent -    // since the last time you called swapBuffers. This presumably means something if you're using -    // QGLWidget the "regular" way, but in our multi-threaded use case is harmless since we never -    // call doneCurrent in this thread. +    // In our multi-threaded QGLWidget use case we shouldn't need to call `makeCurrent`, +    // since we never call `doneCurrent` in this thread. +    // However: +    // - The Qt debug runtime prints a bogus warning on the console if `makeCurrent` wasn't called +    // since the last time `swapBuffers` was executed; +    // - On macOS, if `makeCurrent` isn't called explicitely, resizing the buffer breaks.      child->makeCurrent(); -#endif +      child->swapBuffers();  } diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 8316db708..a32134fbe 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -84,6 +84,8 @@ void Config::ReadValues() {      qt_config->beginGroup("Renderer");      Settings::values.resolution_factor = qt_config->value("resolution_factor", 1.0).toFloat();      Settings::values.toggle_framelimit = qt_config->value("toggle_framelimit", true).toBool(); +    Settings::values.use_accurate_framebuffers = +        qt_config->value("use_accurate_framebuffers", false).toBool();      Settings::values.bg_red = qt_config->value("bg_red", 0.0).toFloat();      Settings::values.bg_green = qt_config->value("bg_green", 0.0).toFloat(); @@ -158,6 +160,7 @@ void Config::ReadValues() {      UISettings::values.confirm_before_closing = qt_config->value("confirmClose", true).toBool();      UISettings::values.first_start = qt_config->value("firstStart", true).toBool();      UISettings::values.callout_flags = qt_config->value("calloutFlags", 0).toUInt(); +    UISettings::values.show_console = qt_config->value("showConsole", false).toBool();      qt_config->endGroup();  } @@ -184,6 +187,7 @@ void Config::SaveValues() {      qt_config->beginGroup("Renderer");      qt_config->setValue("resolution_factor", (double)Settings::values.resolution_factor);      qt_config->setValue("toggle_framelimit", Settings::values.toggle_framelimit); +    qt_config->setValue("use_accurate_framebuffers", Settings::values.use_accurate_framebuffers);      // Cast to double because Qt's written float values are not human-readable      qt_config->setValue("bg_red", (double)Settings::values.bg_red); @@ -243,7 +247,7 @@ void Config::SaveValues() {      qt_config->setValue("confirmClose", UISettings::values.confirm_before_closing);      qt_config->setValue("firstStart", UISettings::values.first_start);      qt_config->setValue("calloutFlags", UISettings::values.callout_flags); - +    qt_config->setValue("showConsole", UISettings::values.show_console);      qt_config->endGroup();  } diff --git a/src/yuzu/configuration/configure_debug.cpp b/src/yuzu/configuration/configure_debug.cpp index a45edd510..241db4ae3 100644 --- a/src/yuzu/configuration/configure_debug.cpp +++ b/src/yuzu/configuration/configure_debug.cpp @@ -2,13 +2,26 @@  // Licensed under GPLv2 or any later version  // Refer to the license.txt file included. +#include <QDesktopServices> +#include <QUrl> +#include "common/file_util.h" +#include "common/logging/backend.h" +#include "common/logging/filter.h" +#include "common/logging/log.h" +#include "core/core.h"  #include "core/settings.h"  #include "ui_configure_debug.h"  #include "yuzu/configuration/configure_debug.h" +#include "yuzu/debugger/console.h" +#include "yuzu/ui_settings.h"  ConfigureDebug::ConfigureDebug(QWidget* parent) : QWidget(parent), ui(new Ui::ConfigureDebug) {      ui->setupUi(this);      this->setConfiguration(); +    connect(ui->open_log_button, &QPushButton::pressed, []() { +        QString path = QString::fromStdString(FileUtil::GetUserPath(D_LOGS_IDX)); +        QDesktopServices::openUrl(QUrl::fromLocalFile(path)); +    });  }  ConfigureDebug::~ConfigureDebug() {} @@ -17,10 +30,19 @@ void ConfigureDebug::setConfiguration() {      ui->toggle_gdbstub->setChecked(Settings::values.use_gdbstub);      ui->gdbport_spinbox->setEnabled(Settings::values.use_gdbstub);      ui->gdbport_spinbox->setValue(Settings::values.gdbstub_port); +    ui->toggle_console->setEnabled(!Core::System::GetInstance().IsPoweredOn()); +    ui->toggle_console->setChecked(UISettings::values.show_console); +    ui->log_filter_edit->setText(QString::fromStdString(Settings::values.log_filter));  }  void ConfigureDebug::applyConfiguration() {      Settings::values.use_gdbstub = ui->toggle_gdbstub->isChecked();      Settings::values.gdbstub_port = ui->gdbport_spinbox->value(); +    UISettings::values.show_console = ui->toggle_console->isChecked(); +    Settings::values.log_filter = ui->log_filter_edit->text().toStdString(); +    Debugger::ToggleConsole(); +    Log::Filter filter; +    filter.ParseFilterString(Settings::values.log_filter); +    Log::SetGlobalFilter(filter);      Settings::Apply();  } diff --git a/src/yuzu/configuration/configure_debug.ui b/src/yuzu/configuration/configure_debug.ui index a10bea2f4..118e91cf1 100644 --- a/src/yuzu/configuration/configure_debug.ui +++ b/src/yuzu/configuration/configure_debug.ui @@ -73,6 +73,47 @@      </layout>     </item>     <item> +    <widget class="QGroupBox" name="groupBox_2"> +     <property name="title"> +      <string>Logging</string> +     </property> +     <layout class="QVBoxLayout" name="verticalLayout"> +      <item> +       <layout class="QHBoxLayout" name="horizontalLayout"> +        <item> +         <widget class="QLabel" name="label"> +          <property name="text"> +           <string>Global Log Filter</string> +          </property> +         </widget> +        </item> +        <item> +         <widget class="QLineEdit" name="log_filter_edit"/> +        </item> +       </layout> +      </item> +      <item> +       <layout class="QHBoxLayout" name="horizontalLayout_2"> +        <item> +         <widget class="QCheckBox" name="toggle_console"> +          <property name="text"> +           <string>Show Log Console (Windows Only)</string> +          </property> +         </widget> +        </item> +        <item> +         <widget class="QPushButton" name="open_log_button"> +          <property name="text"> +           <string>Open Log Location</string> +          </property> +         </widget> +        </item> +       </layout> +      </item> +     </layout> +    </widget> +   </item> +   <item>      <spacer name="verticalSpacer">       <property name="orientation">        <enum>Qt::Vertical</enum> diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp index 47b9b6e95..7664880d5 100644 --- a/src/yuzu/configuration/configure_graphics.cpp +++ b/src/yuzu/configuration/configure_graphics.cpp @@ -59,11 +59,13 @@ void ConfigureGraphics::setConfiguration() {      ui->resolution_factor_combobox->setCurrentIndex(          static_cast<int>(FromResolutionFactor(Settings::values.resolution_factor)));      ui->toggle_framelimit->setChecked(Settings::values.toggle_framelimit); +    ui->use_accurate_framebuffers->setChecked(Settings::values.use_accurate_framebuffers);  }  void ConfigureGraphics::applyConfiguration() {      Settings::values.resolution_factor =          ToResolutionFactor(static_cast<Resolution>(ui->resolution_factor_combobox->currentIndex()));      Settings::values.toggle_framelimit = ui->toggle_framelimit->isChecked(); +    Settings::values.use_accurate_framebuffers = ui->use_accurate_framebuffers->isChecked();      Settings::Apply();  } diff --git a/src/yuzu/configuration/configure_graphics.ui b/src/yuzu/configuration/configure_graphics.ui index 366931a9a..7d092df03 100644 --- a/src/yuzu/configuration/configure_graphics.ui +++ b/src/yuzu/configuration/configure_graphics.ui @@ -30,6 +30,13 @@           </widget>          </item>          <item> +         <widget class="QCheckBox" name="use_accurate_framebuffers"> +          <property name="text"> +           <string>Use accurate framebuffers (slow)</string> +          </property> +         </widget> +        </item> +        <item>           <layout class="QHBoxLayout" name="horizontalLayout">            <item>             <widget class="QLabel" name="label"> diff --git a/src/yuzu/debugger/console.cpp b/src/yuzu/debugger/console.cpp new file mode 100644 index 000000000..e3d2d975f --- /dev/null +++ b/src/yuzu/debugger/console.cpp @@ -0,0 +1,45 @@ +// Copyright 2018 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#ifdef _WIN32 +#include <windows.h> + +#include <wincon.h> +#endif + +#include "common/logging/backend.h" +#include "yuzu/debugger/console.h" +#include "yuzu/ui_settings.h" + +namespace Debugger { +void ToggleConsole() { +#if defined(_WIN32) && !defined(_DEBUG) +    FILE* temp; +    if (UISettings::values.show_console) { +        if (AllocConsole()) { +            // The first parameter for freopen_s is a out parameter, so we can just ignore it +            freopen_s(&temp, "CONIN$", "r", stdin); +            freopen_s(&temp, "CONOUT$", "w", stdout); +            freopen_s(&temp, "CONOUT$", "w", stderr); +            Log::AddBackend(std::make_unique<Log::ColorConsoleBackend>()); +        } +    } else { +        if (FreeConsole()) { +            // In order to close the console, we have to also detach the streams on it. +            // Just redirect them to NUL if there is no console window +            Log::RemoveBackend(Log::ColorConsoleBackend::Name()); +            freopen_s(&temp, "NUL", "r", stdin); +            freopen_s(&temp, "NUL", "w", stdout); +            freopen_s(&temp, "NUL", "w", stderr); +        } +    } +#else +    if (UISettings::values.show_console) { +        Log::AddBackend(std::make_unique<Log::ColorConsoleBackend>()); +    } else { +        Log::RemoveBackend(Log::ColorConsoleBackend::Name()); +    } +#endif +} +} // namespace Debugger diff --git a/src/yuzu/debugger/console.h b/src/yuzu/debugger/console.h new file mode 100644 index 000000000..d1990c496 --- /dev/null +++ b/src/yuzu/debugger/console.h @@ -0,0 +1,14 @@ +// Copyright 2018 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +namespace Debugger { + +/** + * Uses the WINAPI to hide or show the stderr console. This function is a placeholder until we can + * get a real qt logging window which would work for all platforms. + */ +void ToggleConsole(); +} // namespace Debugger
\ No newline at end of file diff --git a/src/yuzu/debugger/registers.cpp b/src/yuzu/debugger/registers.cpp deleted file mode 100644 index 178cc65a7..000000000 --- a/src/yuzu/debugger/registers.cpp +++ /dev/null @@ -1,190 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include <QTreeWidgetItem> -#include "core/arm/arm_interface.h" -#include "core/core.h" -#include "yuzu/debugger/registers.h" -#include "yuzu/util/util.h" - -RegistersWidget::RegistersWidget(QWidget* parent) : QDockWidget(parent) { -    cpu_regs_ui.setupUi(this); - -    tree = cpu_regs_ui.treeWidget; -    tree->addTopLevelItem(core_registers = new QTreeWidgetItem(QStringList(tr("Registers")))); -    tree->addTopLevelItem(vfp_registers = new QTreeWidgetItem(QStringList(tr("VFP Registers")))); -    tree->addTopLevelItem(vfp_system_registers = -                              new QTreeWidgetItem(QStringList(tr("VFP System Registers")))); -    tree->addTopLevelItem(cpsr = new QTreeWidgetItem(QStringList("CPSR"))); - -    for (int i = 0; i < 16; ++i) { -        QTreeWidgetItem* child = new QTreeWidgetItem(QStringList(QString("R[%1]").arg(i))); -        core_registers->addChild(child); -    } - -    for (int i = 0; i < 32; ++i) { -        QTreeWidgetItem* child = new QTreeWidgetItem(QStringList(QString("S[%1]").arg(i))); -        vfp_registers->addChild(child); -    } - -    QFont font = GetMonospaceFont(); - -    CreateCPSRChildren(); -    CreateVFPSystemRegisterChildren(); - -    // Set Registers to display in monospace font -    for (int i = 0; i < core_registers->childCount(); ++i) -        core_registers->child(i)->setFont(1, font); - -    for (int i = 0; i < vfp_registers->childCount(); ++i) -        vfp_registers->child(i)->setFont(1, font); - -    for (int i = 0; i < vfp_system_registers->childCount(); ++i) { -        vfp_system_registers->child(i)->setFont(1, font); -        for (int x = 0; x < vfp_system_registers->child(i)->childCount(); ++x) { -            vfp_system_registers->child(i)->child(x)->setFont(1, font); -        } -    } -    // Set CSPR to display in monospace font -    cpsr->setFont(1, font); -    for (int i = 0; i < cpsr->childCount(); ++i) { -        cpsr->child(i)->setFont(1, font); -        for (int x = 0; x < cpsr->child(i)->childCount(); ++x) { -            cpsr->child(i)->child(x)->setFont(1, font); -        } -    } -    setEnabled(false); -} - -void RegistersWidget::OnDebugModeEntered() { -    if (!Core::System::GetInstance().IsPoweredOn()) -        return; - -    for (int i = 0; i < core_registers->childCount(); ++i) -        core_registers->child(i)->setText( -            1, QString("0x%1").arg(Core::CurrentArmInterface().GetReg(i), 8, 16, QLatin1Char('0'))); - -    UpdateCPSRValues(); -} - -void RegistersWidget::OnDebugModeLeft() {} - -void RegistersWidget::OnEmulationStarting(EmuThread* emu_thread) { -    setEnabled(true); -} - -void RegistersWidget::OnEmulationStopping() { -    // Reset widget text -    for (int i = 0; i < core_registers->childCount(); ++i) -        core_registers->child(i)->setText(1, QString("")); - -    for (int i = 0; i < vfp_registers->childCount(); ++i) -        vfp_registers->child(i)->setText(1, QString("")); - -    for (int i = 0; i < cpsr->childCount(); ++i) -        cpsr->child(i)->setText(1, QString("")); - -    cpsr->setText(1, QString("")); - -    // FPSCR -    for (int i = 0; i < vfp_system_registers->child(0)->childCount(); ++i) -        vfp_system_registers->child(0)->child(i)->setText(1, QString("")); - -    // FPEXC -    for (int i = 0; i < vfp_system_registers->child(1)->childCount(); ++i) -        vfp_system_registers->child(1)->child(i)->setText(1, QString("")); - -    vfp_system_registers->child(0)->setText(1, QString("")); -    vfp_system_registers->child(1)->setText(1, QString("")); -    vfp_system_registers->child(2)->setText(1, QString("")); -    vfp_system_registers->child(3)->setText(1, QString("")); - -    setEnabled(false); -} - -void RegistersWidget::CreateCPSRChildren() { -    cpsr->addChild(new QTreeWidgetItem(QStringList("M"))); -    cpsr->addChild(new QTreeWidgetItem(QStringList("T"))); -    cpsr->addChild(new QTreeWidgetItem(QStringList("F"))); -    cpsr->addChild(new QTreeWidgetItem(QStringList("I"))); -    cpsr->addChild(new QTreeWidgetItem(QStringList("A"))); -    cpsr->addChild(new QTreeWidgetItem(QStringList("E"))); -    cpsr->addChild(new QTreeWidgetItem(QStringList("IT"))); -    cpsr->addChild(new QTreeWidgetItem(QStringList("GE"))); -    cpsr->addChild(new QTreeWidgetItem(QStringList("DNM"))); -    cpsr->addChild(new QTreeWidgetItem(QStringList("J"))); -    cpsr->addChild(new QTreeWidgetItem(QStringList("Q"))); -    cpsr->addChild(new QTreeWidgetItem(QStringList("V"))); -    cpsr->addChild(new QTreeWidgetItem(QStringList("C"))); -    cpsr->addChild(new QTreeWidgetItem(QStringList("Z"))); -    cpsr->addChild(new QTreeWidgetItem(QStringList("N"))); -} - -void RegistersWidget::UpdateCPSRValues() { -    const u32 cpsr_val = Core::CurrentArmInterface().GetCPSR(); - -    cpsr->setText(1, QString("0x%1").arg(cpsr_val, 8, 16, QLatin1Char('0'))); -    cpsr->child(0)->setText( -        1, QString("b%1").arg(cpsr_val & 0x1F, 5, 2, QLatin1Char('0'))); // M - Mode -    cpsr->child(1)->setText(1, QString::number((cpsr_val >> 5) & 1));    // T - State -    cpsr->child(2)->setText(1, QString::number((cpsr_val >> 6) & 1));    // F - FIQ disable -    cpsr->child(3)->setText(1, QString::number((cpsr_val >> 7) & 1));    // I - IRQ disable -    cpsr->child(4)->setText(1, QString::number((cpsr_val >> 8) & 1));    // A - Imprecise abort -    cpsr->child(5)->setText(1, QString::number((cpsr_val >> 9) & 1));    // E - Data endianness -    cpsr->child(6)->setText(1, -                            QString::number((cpsr_val >> 10) & 0x3F)); // IT - If-Then state (DNM) -    cpsr->child(7)->setText(1, -                            QString::number((cpsr_val >> 16) & 0xF)); // GE - Greater-than-or-Equal -    cpsr->child(8)->setText(1, QString::number((cpsr_val >> 20) & 0xF)); // DNM - Do not modify -    cpsr->child(9)->setText(1, QString::number((cpsr_val >> 24) & 1));   // J - Jazelle -    cpsr->child(10)->setText(1, QString::number((cpsr_val >> 27) & 1));  // Q - Saturation -    cpsr->child(11)->setText(1, QString::number((cpsr_val >> 28) & 1));  // V - Overflow -    cpsr->child(12)->setText(1, QString::number((cpsr_val >> 29) & 1));  // C - Carry/Borrow/Extend -    cpsr->child(13)->setText(1, QString::number((cpsr_val >> 30) & 1));  // Z - Zero -    cpsr->child(14)->setText(1, QString::number((cpsr_val >> 31) & 1));  // N - Negative/Less than -} - -void RegistersWidget::CreateVFPSystemRegisterChildren() { -    QTreeWidgetItem* const fpscr = new QTreeWidgetItem(QStringList("FPSCR")); -    fpscr->addChild(new QTreeWidgetItem(QStringList("IOC"))); -    fpscr->addChild(new QTreeWidgetItem(QStringList("DZC"))); -    fpscr->addChild(new QTreeWidgetItem(QStringList("OFC"))); -    fpscr->addChild(new QTreeWidgetItem(QStringList("UFC"))); -    fpscr->addChild(new QTreeWidgetItem(QStringList("IXC"))); -    fpscr->addChild(new QTreeWidgetItem(QStringList("IDC"))); -    fpscr->addChild(new QTreeWidgetItem(QStringList("IOE"))); -    fpscr->addChild(new QTreeWidgetItem(QStringList("DZE"))); -    fpscr->addChild(new QTreeWidgetItem(QStringList("OFE"))); -    fpscr->addChild(new QTreeWidgetItem(QStringList("UFE"))); -    fpscr->addChild(new QTreeWidgetItem(QStringList("IXE"))); -    fpscr->addChild(new QTreeWidgetItem(QStringList("IDE"))); -    fpscr->addChild(new QTreeWidgetItem(QStringList(tr("Vector Length")))); -    fpscr->addChild(new QTreeWidgetItem(QStringList(tr("Vector Stride")))); -    fpscr->addChild(new QTreeWidgetItem(QStringList(tr("Rounding Mode")))); -    fpscr->addChild(new QTreeWidgetItem(QStringList("FZ"))); -    fpscr->addChild(new QTreeWidgetItem(QStringList("DN"))); -    fpscr->addChild(new QTreeWidgetItem(QStringList("V"))); -    fpscr->addChild(new QTreeWidgetItem(QStringList("C"))); -    fpscr->addChild(new QTreeWidgetItem(QStringList("Z"))); -    fpscr->addChild(new QTreeWidgetItem(QStringList("N"))); - -    QTreeWidgetItem* const fpexc = new QTreeWidgetItem(QStringList("FPEXC")); -    fpexc->addChild(new QTreeWidgetItem(QStringList("IOC"))); -    fpexc->addChild(new QTreeWidgetItem(QStringList("OFC"))); -    fpexc->addChild(new QTreeWidgetItem(QStringList("UFC"))); -    fpexc->addChild(new QTreeWidgetItem(QStringList("INV"))); -    fpexc->addChild(new QTreeWidgetItem(QStringList(tr("Vector Iteration Count")))); -    fpexc->addChild(new QTreeWidgetItem(QStringList("FP2V"))); -    fpexc->addChild(new QTreeWidgetItem(QStringList("EN"))); -    fpexc->addChild(new QTreeWidgetItem(QStringList("EX"))); - -    vfp_system_registers->addChild(fpscr); -    vfp_system_registers->addChild(fpexc); -    vfp_system_registers->addChild(new QTreeWidgetItem(QStringList("FPINST"))); -    vfp_system_registers->addChild(new QTreeWidgetItem(QStringList("FPINST2"))); -} - -void RegistersWidget::UpdateVFPSystemRegisterValues() { -    UNIMPLEMENTED(); -} diff --git a/src/yuzu/debugger/registers.h b/src/yuzu/debugger/registers.h deleted file mode 100644 index 55bda5b59..000000000 --- a/src/yuzu/debugger/registers.h +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include <QDockWidget> -#include "ui_registers.h" - -class QTreeWidget; -class QTreeWidgetItem; -class EmuThread; - -class RegistersWidget : public QDockWidget { -    Q_OBJECT - -public: -    explicit RegistersWidget(QWidget* parent = nullptr); - -public slots: -    void OnDebugModeEntered(); -    void OnDebugModeLeft(); - -    void OnEmulationStarting(EmuThread* emu_thread); -    void OnEmulationStopping(); - -private: -    void CreateCPSRChildren(); -    void UpdateCPSRValues(); - -    void CreateVFPSystemRegisterChildren(); -    void UpdateVFPSystemRegisterValues(); - -    Ui::ARMRegisters cpu_regs_ui; - -    QTreeWidget* tree; - -    QTreeWidgetItem* core_registers; -    QTreeWidgetItem* vfp_registers; -    QTreeWidgetItem* vfp_system_registers; -    QTreeWidgetItem* cpsr; -}; diff --git a/src/yuzu/debugger/registers.ui b/src/yuzu/debugger/registers.ui deleted file mode 100644 index c81ae03f9..000000000 --- a/src/yuzu/debugger/registers.ui +++ /dev/null @@ -1,40 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>ARMRegisters</class> - <widget class="QDockWidget" name="ARMRegisters"> -  <property name="geometry"> -   <rect> -    <x>0</x> -    <y>0</y> -    <width>400</width> -    <height>300</height> -   </rect> -  </property> -  <property name="windowTitle"> -   <string>ARM Registers</string> -  </property> -  <widget class="QWidget" name="dockWidgetContents"> -   <layout class="QVBoxLayout" name="verticalLayout"> -    <item> -     <widget class="QTreeWidget" name="treeWidget"> -      <property name="alternatingRowColors"> -       <bool>true</bool> -      </property> -      <column> -       <property name="text"> -        <string>Register</string> -       </property> -      </column> -      <column> -       <property name="text"> -        <string>Value</string> -       </property> -      </column> -     </widget> -    </item> -   </layout> -  </widget> - </widget> - <resources/> - <connections/> -</ui> diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp index 017bef13c..7101b381e 100644 --- a/src/yuzu/debugger/wait_tree.cpp +++ b/src/yuzu/debugger/wait_tree.cpp @@ -213,6 +213,9 @@ QString WaitTreeThread::GetText() const {      case THREADSTATUS_WAIT_MUTEX:          status = tr("waiting for mutex");          break; +    case THREADSTATUS_WAIT_ARB: +        status = tr("waiting for address arbiter"); +        break;      case THREADSTATUS_DORMANT:          status = tr("dormant");          break; @@ -240,6 +243,7 @@ QColor WaitTreeThread::GetColor() const {      case THREADSTATUS_WAIT_SYNCH_ALL:      case THREADSTATUS_WAIT_SYNCH_ANY:      case THREADSTATUS_WAIT_MUTEX: +    case THREADSTATUS_WAIT_ARB:          return QColor(Qt::GlobalColor::red);      case THREADSTATUS_DORMANT:          return QColor(Qt::GlobalColor::darkCyan); diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp index bbd681eae..5a708dc73 100644 --- a/src/yuzu/game_list.cpp +++ b/src/yuzu/game_list.cpp @@ -3,6 +3,7 @@  // Refer to the license.txt file included.  #include <QApplication> +#include <QDir>  #include <QFileInfo>  #include <QHeaderView>  #include <QKeyEvent> @@ -264,8 +265,17 @@ void GameList::ValidateEntry(const QModelIndex& item) {      if (file_path.isEmpty())          return;      std::string std_file_path(file_path.toStdString()); -    if (!FileUtil::Exists(std_file_path) || FileUtil::IsDirectory(std_file_path)) +    if (!FileUtil::Exists(std_file_path))          return; +    if (FileUtil::IsDirectory(std_file_path)) { +        QDir dir(std_file_path.c_str()); +        QStringList matching_main = dir.entryList(QStringList("main"), QDir::Files); +        if (matching_main.size() == 1) { +            emit GameChosen(dir.path() + DIR_SEP + matching_main[0]); +        } +        return; +    } +      // Users usually want to run a diffrent game after closing one      search_field->clear();      emit GameChosen(file_path); @@ -315,8 +325,7 @@ void GameList::PopupContextMenu(const QPoint& menu_location) {  void GameList::PopulateAsync(const QString& dir_path, bool deep_scan) {      if (!FileUtil::Exists(dir_path.toStdString()) ||          !FileUtil::IsDirectory(dir_path.toStdString())) { -        NGLOG_ERROR(Frontend, "Could not find game list folder at {}", -                    dir_path.toLocal8Bit().data()); +        LOG_ERROR(Frontend, "Could not find game list folder at {}", dir_path.toLocal8Bit().data());          search_field->setFilterResult(0, 0);          return;      } @@ -356,16 +365,29 @@ void GameList::LoadInterfaceLayout() {      item_model->sort(header->sortIndicatorSection(), header->sortIndicatorOrder());  } -const QStringList GameList::supported_file_extensions = {"nso", "nro"}; +const QStringList GameList::supported_file_extensions = {"nso", "nro", "nca"};  static bool HasSupportedFileExtension(const std::string& file_name) {      QFileInfo file = QFileInfo(file_name.c_str());      return GameList::supported_file_extensions.contains(file.suffix(), Qt::CaseInsensitive);  } +static bool IsExtractedNCAMain(const std::string& file_name) { +    return QFileInfo(file_name.c_str()).fileName() == "main"; +} + +static QString FormatGameName(const std::string& physical_name) { +    QFileInfo file_info(physical_name.c_str()); +    if (IsExtractedNCAMain(physical_name)) { +        return file_info.dir().path(); +    } else { +        return QString::fromStdString(physical_name); +    } +} +  void GameList::RefreshGameDirectory() {      if (!UISettings::values.gamedir.isEmpty() && current_worker != nullptr) { -        NGLOG_INFO(Frontend, "Change detected in the games directory. Reloading game list."); +        LOG_INFO(Frontend, "Change detected in the games directory. Reloading game list.");          search_field->clear();          PopulateAsync(UISettings::values.gamedir, UISettings::values.gamedir_deepscan);      } @@ -380,7 +402,8 @@ void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsign              return false; // Breaks the callback loop.          bool is_dir = FileUtil::IsDirectory(physical_name); -        if (!is_dir && HasSupportedFileExtension(physical_name)) { +        if (!is_dir && +            (HasSupportedFileExtension(physical_name) || IsExtractedNCAMain(physical_name))) {              std::unique_ptr<Loader::AppLoader> loader = Loader::GetLoader(physical_name);              if (!loader)                  return true; @@ -392,7 +415,7 @@ void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsign              loader->ReadProgramId(program_id);              emit EntryReady({ -                new GameListItemPath(QString::fromStdString(physical_name), smdh, program_id), +                new GameListItemPath(FormatGameName(physical_name), smdh, program_id),                  new GameListItem(                      QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType()))),                  new GameListItemSize(FileUtil::GetSize(physical_name)), diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 3038bd6da..05a8ae6d2 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -13,6 +13,7 @@  #include <QMessageBox>  #include <QtGui>  #include <QtWidgets> +#include "common/common_paths.h"  #include "common/logging/backend.h"  #include "common/logging/filter.h"  #include "common/logging/log.h" @@ -30,10 +31,10 @@  #include "yuzu/bootmanager.h"  #include "yuzu/configuration/config.h"  #include "yuzu/configuration/configure_dialog.h" +#include "yuzu/debugger/console.h"  #include "yuzu/debugger/graphics/graphics_breakpoints.h"  #include "yuzu/debugger/graphics/graphics_surface.h"  #include "yuzu/debugger/profiler.h" -#include "yuzu/debugger/registers.h"  #include "yuzu/debugger/wait_tree.h"  #include "yuzu/game_list.h"  #include "yuzu/hotkeys.h" @@ -169,15 +170,6 @@ void GMainWindow::InitializeDebugWidgets() {      debug_menu->addAction(microProfileDialog->toggleViewAction());  #endif -    registersWidget = new RegistersWidget(this); -    addDockWidget(Qt::RightDockWidgetArea, registersWidget); -    registersWidget->hide(); -    debug_menu->addAction(registersWidget->toggleViewAction()); -    connect(this, &GMainWindow::EmulationStarting, registersWidget, -            &RegistersWidget::OnEmulationStarting); -    connect(this, &GMainWindow::EmulationStopping, registersWidget, -            &RegistersWidget::OnEmulationStopping); -      graphicsBreakpointsWidget = new GraphicsBreakPointsWidget(debug_context, this);      addDockWidget(Qt::RightDockWidgetArea, graphicsBreakpointsWidget);      graphicsBreakpointsWidget->hide(); @@ -270,6 +262,7 @@ void GMainWindow::RestoreUIState() {      ui.action_Show_Status_Bar->setChecked(UISettings::values.show_status_bar);      statusBar()->setVisible(ui.action_Show_Status_Bar->isChecked()); +    Debugger::ToggleConsole();  }  void GMainWindow::ConnectWidgetEvents() { @@ -288,6 +281,7 @@ void GMainWindow::ConnectWidgetEvents() {  void GMainWindow::ConnectMenuEvents() {      // File      connect(ui.action_Load_File, &QAction::triggered, this, &GMainWindow::OnMenuLoadFile); +    connect(ui.action_Load_Folder, &QAction::triggered, this, &GMainWindow::OnMenuLoadFolder);      connect(ui.action_Select_Game_List_Root, &QAction::triggered, this,              &GMainWindow::OnMenuSelectGameListRoot);      connect(ui.action_Exit, &QAction::triggered, this, &QMainWindow::close); @@ -342,13 +336,11 @@ bool GMainWindow::SupportsRequiredGLExtensions() {          unsupported_ext.append("ARB_program_interface_query");      if (!GLAD_GL_ARB_separate_shader_objects)          unsupported_ext.append("ARB_separate_shader_objects"); -    if (!GLAD_GL_ARB_shader_storage_buffer_object) -        unsupported_ext.append("ARB_shader_storage_buffer_object");      if (!GLAD_GL_ARB_vertex_attrib_binding)          unsupported_ext.append("ARB_vertex_attrib_binding");      for (const QString& ext : unsupported_ext) -        NGLOG_CRITICAL(Frontend, "Unsupported GL extension: {}", ext.toStdString()); +        LOG_CRITICAL(Frontend, "Unsupported GL extension: {}", ext.toStdString());      return unsupported_ext.empty();  } @@ -385,17 +377,17 @@ bool GMainWindow::LoadROM(const QString& filename) {      if (result != Core::System::ResultStatus::Success) {          switch (result) {          case Core::System::ResultStatus::ErrorGetLoader: -            NGLOG_CRITICAL(Frontend, "Failed to obtain loader for {}!", filename.toStdString()); +            LOG_CRITICAL(Frontend, "Failed to obtain loader for {}!", filename.toStdString());              QMessageBox::critical(this, tr("Error while loading ROM!"),                                    tr("The ROM format is not supported."));              break;          case Core::System::ResultStatus::ErrorUnsupportedArch: -            NGLOG_CRITICAL(Frontend, "Unsupported architecture detected!", filename.toStdString()); +            LOG_CRITICAL(Frontend, "Unsupported architecture detected!", filename.toStdString());              QMessageBox::critical(this, tr("Error while loading ROM!"),                                    tr("The ROM uses currently unusable 32-bit architecture"));              break;          case Core::System::ResultStatus::ErrorSystemMode: -            NGLOG_CRITICAL(Frontend, "Failed to load ROM!"); +            LOG_CRITICAL(Frontend, "Failed to load ROM!");              QMessageBox::critical(this, tr("Error while loading ROM!"),                                    tr("Could not determine the system mode."));              break; @@ -445,7 +437,7 @@ bool GMainWindow::LoadROM(const QString& filename) {  }  void GMainWindow::BootGame(const QString& filename) { -    NGLOG_INFO(Frontend, "yuzu starting..."); +    LOG_INFO(Frontend, "yuzu starting...");      StoreRecentFile(filename); // Put the filename on top of the list      if (!LoadROM(filename)) @@ -460,17 +452,12 @@ void GMainWindow::BootGame(const QString& filename) {      connect(render_window, &GRenderWindow::Closed, this, &GMainWindow::OnStopGame);      // BlockingQueuedConnection is important here, it makes sure we've finished refreshing our views      // before the CPU continues -    connect(emu_thread.get(), &EmuThread::DebugModeEntered, registersWidget, -            &RegistersWidget::OnDebugModeEntered, Qt::BlockingQueuedConnection);      connect(emu_thread.get(), &EmuThread::DebugModeEntered, waitTreeWidget,              &WaitTreeWidget::OnDebugModeEntered, Qt::BlockingQueuedConnection); -    connect(emu_thread.get(), &EmuThread::DebugModeLeft, registersWidget, -            &RegistersWidget::OnDebugModeLeft, Qt::BlockingQueuedConnection);      connect(emu_thread.get(), &EmuThread::DebugModeLeft, waitTreeWidget,              &WaitTreeWidget::OnDebugModeLeft, Qt::BlockingQueuedConnection);      // Update the GUI -    registersWidget->OnDebugModeEntered();      if (ui.action_Single_Window_Mode->isChecked()) {          game_list->hide();      } @@ -565,6 +552,8 @@ void GMainWindow::OnMenuLoadFile() {      for (const auto& piece : game_list->supported_file_extensions)          extensions += "*." + piece + " "; +    extensions += "main "; +      QString file_filter = tr("Switch Executable") + " (" + extensions + ")";      file_filter += ";;" + tr("All Files (*.*)"); @@ -577,6 +566,18 @@ void GMainWindow::OnMenuLoadFile() {      }  } +void GMainWindow::OnMenuLoadFolder() { +    QDir dir = QFileDialog::getExistingDirectory(this, tr("Open Extracted ROM Directory")); + +    QStringList matching_main = dir.entryList(QStringList("main"), QDir::Files); +    if (matching_main.size() == 1) { +        BootGame(dir.path() + DIR_SEP + matching_main[0]); +    } else { +        QMessageBox::warning(this, tr("Invalid Directory Selected"), +                             tr("The directory you have selected does not contain a 'main' file.")); +    } +} +  void GMainWindow::OnMenuSelectGameListRoot() {      QString dir_path = QFileDialog::getExistingDirectory(this, tr("Select Directory"));      if (!dir_path.isEmpty()) { @@ -883,7 +884,7 @@ void GMainWindow::UpdateUITheme() {          QString theme_uri(":" + UISettings::values.theme + "/style.qss");          QFile f(theme_uri);          if (!f.exists()) { -            NGLOG_ERROR(Frontend, "Unable to set style, stylesheet file not found"); +            LOG_ERROR(Frontend, "Unable to set style, stylesheet file not found");          } else {              f.open(QFile::ReadOnly | QFile::Text);              QTextStream ts(&f); @@ -907,8 +908,7 @@ void GMainWindow::UpdateUITheme() {  #endif  int main(int argc, char* argv[]) { -    Log::Filter log_filter(Log::Level::Info); -    Log::SetFilter(&log_filter); +    Log::AddBackend(std::make_unique<Log::ColorConsoleBackend>());      MicroProfileOnThreadCreate("Frontend");      SCOPE_EXIT({ MicroProfileShutdown(); }); @@ -926,7 +926,12 @@ int main(int argc, char* argv[]) {      GMainWindow main_window;      // After settings have been loaded by GMainWindow, apply the filter +    Log::Filter log_filter;      log_filter.ParseFilterString(Settings::values.log_filter); +    Log::SetGlobalFilter(log_filter); +    FileUtil::CreateFullPath(FileUtil::GetUserPath(D_LOGS_IDX)); +    Log::AddBackend( +        std::make_unique<Log::FileBackend>(FileUtil::GetUserPath(D_LOGS_IDX) + LOG_FILE));      main_window.show();      return app.exec(); diff --git a/src/yuzu/main.h b/src/yuzu/main.h index ac3024d8a..074bba3f9 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h @@ -19,7 +19,6 @@ class GraphicsSurfaceWidget;  class GRenderWindow;  class MicroProfileDialog;  class ProfilerWidget; -class RegistersWidget;  class WaitTreeWidget;  namespace Tegra { @@ -124,6 +123,7 @@ private slots:      void OnGameListLoadFile(QString game_path);      void OnGameListOpenSaveFolder(u64 program_id);      void OnMenuLoadFile(); +    void OnMenuLoadFolder();      /// Called whenever a user selects the "File->Select Game List Root" menu item      void OnMenuSelectGameListRoot();      void OnMenuRecentFile(); @@ -163,7 +163,6 @@ private:      // Debugger panes      ProfilerWidget* profilerWidget;      MicroProfileDialog* microProfileDialog; -    RegistersWidget* registersWidget;      GraphicsBreakPointsWidget* graphicsBreakpointsWidget;      GraphicsSurfaceWidget* graphicsSurfaceWidget;      WaitTreeWidget* waitTreeWidget; diff --git a/src/yuzu/main.ui b/src/yuzu/main.ui index 0fcd93cc2..22c4cad08 100644 --- a/src/yuzu/main.ui +++ b/src/yuzu/main.ui @@ -58,6 +58,7 @@       </property>      </widget>      <addaction name="action_Load_File"/> +    <addaction name="action_Load_Folder"/>      <addaction name="separator"/>      <addaction name="action_Select_Game_List_Root"/>      <addaction name="menu_recent_files"/> @@ -106,6 +107,11 @@      <string>Load File...</string>     </property>    </action> +  <action name="action_Load_Folder"> +   <property name="text"> +    <string>Load Folder...</string> +   </property> +  </action>    <action name="action_Load_Symbol_Map">     <property name="text">      <string>Load Symbol Map...</string> diff --git a/src/yuzu/ui_settings.h b/src/yuzu/ui_settings.h index 8e215a002..2286c2559 100644 --- a/src/yuzu/ui_settings.h +++ b/src/yuzu/ui_settings.h @@ -51,6 +51,9 @@ struct Values {      std::vector<Shortcut> shortcuts;      uint32_t callout_flags; + +    // logging +    bool show_console;  };  extern Values values; | 
