diff options
Diffstat (limited to 'src/citra_qt')
| -rw-r--r-- | src/citra_qt/CMakeLists.txt | 3 | ||||
| -rw-r--r-- | src/citra_qt/config.cpp | 6 | ||||
| -rw-r--r-- | src/citra_qt/configure.ui | 11 | ||||
| -rw-r--r-- | src/citra_qt/configure_audio.cpp | 44 | ||||
| -rw-r--r-- | src/citra_qt/configure_audio.h | 27 | ||||
| -rw-r--r-- | src/citra_qt/configure_audio.ui | 48 | ||||
| -rw-r--r-- | src/citra_qt/configure_dialog.cpp | 1 | ||||
| -rw-r--r-- | src/citra_qt/debugger/callstack.cpp | 5 | ||||
| -rw-r--r-- | src/citra_qt/debugger/profiler.cpp | 16 | ||||
| -rw-r--r-- | src/citra_qt/game_list.cpp | 33 | ||||
| -rw-r--r-- | src/citra_qt/game_list_p.h | 55 | ||||
| -rw-r--r-- | src/citra_qt/main.cpp | 10 |
12 files changed, 185 insertions, 74 deletions
diff --git a/src/citra_qt/CMakeLists.txt b/src/citra_qt/CMakeLists.txt index 3f0099200..0a5d4624b 100644 --- a/src/citra_qt/CMakeLists.txt +++ b/src/citra_qt/CMakeLists.txt @@ -20,6 +20,7 @@ set(SRCS util/spinbox.cpp util/util.cpp bootmanager.cpp + configure_audio.cpp configure_debug.cpp configure_dialog.cpp configure_general.cpp @@ -51,6 +52,7 @@ set(HEADERS util/spinbox.h util/util.h bootmanager.h + configure_audio.h configure_debug.h configure_dialog.h configure_general.h @@ -69,6 +71,7 @@ set(UIS debugger/profiler.ui debugger/registers.ui configure.ui + configure_audio.ui configure_debug.ui configure_general.ui hotkeys.ui diff --git a/src/citra_qt/config.cpp b/src/citra_qt/config.cpp index b5bb75537..6e4ba3907 100644 --- a/src/citra_qt/config.cpp +++ b/src/citra_qt/config.cpp @@ -60,7 +60,8 @@ void Config::ReadValues() { Settings::values.use_virtual_sd = qt_config->value("use_virtual_sd", true).toBool(); qt_config->endGroup(); - qt_config->beginGroup("System Region"); + qt_config->beginGroup("System"); + Settings::values.is_new_3ds = qt_config->value("is_new_3ds", false).toBool(); Settings::values.region_value = qt_config->value("region_value", 1).toInt(); qt_config->endGroup(); @@ -150,7 +151,8 @@ void Config::SaveValues() { qt_config->setValue("use_virtual_sd", Settings::values.use_virtual_sd); qt_config->endGroup(); - qt_config->beginGroup("System Region"); + qt_config->beginGroup("System"); + qt_config->setValue("is_new_3ds", Settings::values.is_new_3ds); qt_config->setValue("region_value", Settings::values.region_value); qt_config->endGroup(); diff --git a/src/citra_qt/configure.ui b/src/citra_qt/configure.ui index 6ae056ff9..e1624bbef 100644 --- a/src/citra_qt/configure.ui +++ b/src/citra_qt/configure.ui @@ -29,6 +29,11 @@ <string>Input</string> </attribute> </widget> + <widget class="ConfigureAudio" name="audioTab"> + <attribute name="title"> + <string>Audio</string> + </attribute> + </widget> <widget class="ConfigureDebug" name="debugTab"> <attribute name="title"> <string>Debug</string> @@ -53,6 +58,12 @@ <container>1</container> </customwidget> <customwidget> + <class>ConfigureAudio</class> + <extends>QWidget</extends> + <header>configure_audio.h</header> + <container>1</container> + </customwidget> + <customwidget> <class>ConfigureDebug</class> <extends>QWidget</extends> <header>configure_debug.h</header> diff --git a/src/citra_qt/configure_audio.cpp b/src/citra_qt/configure_audio.cpp new file mode 100644 index 000000000..cedfa2f2a --- /dev/null +++ b/src/citra_qt/configure_audio.cpp @@ -0,0 +1,44 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "audio_core/sink_details.h" + +#include "citra_qt/configure_audio.h" +#include "ui_configure_audio.h" + +#include "core/settings.h" + +ConfigureAudio::ConfigureAudio(QWidget* parent) : + QWidget(parent), + ui(std::make_unique<Ui::ConfigureAudio>()) +{ + ui->setupUi(this); + + ui->output_sink_combo_box->clear(); + ui->output_sink_combo_box->addItem("auto"); + for (const auto& sink_detail : AudioCore::g_sink_details) { + ui->output_sink_combo_box->addItem(sink_detail.id); + } + + this->setConfiguration(); +} + +ConfigureAudio::~ConfigureAudio() { +} + +void ConfigureAudio::setConfiguration() { + int new_sink_index = 0; + for (int index = 0; index < ui->output_sink_combo_box->count(); index++) { + if (ui->output_sink_combo_box->itemText(index).toStdString() == Settings::values.sink_id) { + new_sink_index = index; + break; + } + } + ui->output_sink_combo_box->setCurrentIndex(new_sink_index); +} + +void ConfigureAudio::applyConfiguration() { + Settings::values.sink_id = ui->output_sink_combo_box->itemText(ui->output_sink_combo_box->currentIndex()).toStdString(); + Settings::Apply(); +} diff --git a/src/citra_qt/configure_audio.h b/src/citra_qt/configure_audio.h new file mode 100644 index 000000000..51df2e27b --- /dev/null +++ b/src/citra_qt/configure_audio.h @@ -0,0 +1,27 @@ +// Copyright 2016 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <memory> +#include <QWidget> + +namespace Ui { +class ConfigureAudio; +} + +class ConfigureAudio : public QWidget { + Q_OBJECT + +public: + explicit ConfigureAudio(QWidget* parent = nullptr); + ~ConfigureAudio(); + + void applyConfiguration(); + +private: + void setConfiguration(); + + std::unique_ptr<Ui::ConfigureAudio> ui; +}; diff --git a/src/citra_qt/configure_audio.ui b/src/citra_qt/configure_audio.ui new file mode 100644 index 000000000..d7f6946ca --- /dev/null +++ b/src/citra_qt/configure_audio.ui @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="utf-8"?> + +<ui version="4.0"> + <class>ConfigureAudio</class> + <widget class="QWidget" name="ConfigureAudio"> + <layout class="QVBoxLayout"> + <item> + <widget class="QGroupBox"> + <property name="title"> + <string>Audio</string> + </property> + <layout class="QVBoxLayout"> + <item> + <layout class="QHBoxLayout"> + <item> + <widget class="QLabel"> + <property name="text"> + <string>Output Engine:</string> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="output_sink_combo_box"> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <spacer> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + <resources /> + <connections /> +</ui> diff --git a/src/citra_qt/configure_dialog.cpp b/src/citra_qt/configure_dialog.cpp index 87c26c715..2f0317fe0 100644 --- a/src/citra_qt/configure_dialog.cpp +++ b/src/citra_qt/configure_dialog.cpp @@ -25,5 +25,6 @@ void ConfigureDialog::setConfiguration() { void ConfigureDialog::applyConfiguration() { ui->generalTab->applyConfiguration(); + ui->audioTab->applyConfiguration(); ui->debugTab->applyConfiguration(); } diff --git a/src/citra_qt/debugger/callstack.cpp b/src/citra_qt/debugger/callstack.cpp index 793944639..1a3077495 100644 --- a/src/citra_qt/debugger/callstack.cpp +++ b/src/citra_qt/debugger/callstack.cpp @@ -37,10 +37,13 @@ void CallstackWidget::OnDebugModeEntered() int counter = 0; for (u32 addr = 0x10000000; addr >= sp; addr -= 4) { + if (!Memory::IsValidVirtualAddress(addr)) + break; + const u32 ret_addr = Memory::Read32(addr); const u32 call_addr = ret_addr - 4; //get call address??? - if (Memory::GetPointer(call_addr) == nullptr) + if (!Memory::IsValidVirtualAddress(call_addr)) break; /* TODO (mattvail) clean me, move to debugger interface */ diff --git a/src/citra_qt/debugger/profiler.cpp b/src/citra_qt/debugger/profiler.cpp index 7bb010f77..585ac049a 100644 --- a/src/citra_qt/debugger/profiler.cpp +++ b/src/citra_qt/debugger/profiler.cpp @@ -151,6 +151,8 @@ private: /// This timer is used to redraw the widget's contents continuously. To save resources, it only /// runs while the widget is visible. QTimer update_timer; + /// Scale the coordinate system appropriately when physical DPI != logical DPI. + qreal x_scale, y_scale; }; #endif @@ -220,11 +222,17 @@ MicroProfileWidget::MicroProfileWidget(QWidget* parent) : QWidget(parent) { MicroProfileInitUI(); connect(&update_timer, SIGNAL(timeout()), SLOT(update())); + + QPainter painter(this); + x_scale = qreal(painter.device()->physicalDpiX()) / qreal(painter.device()->logicalDpiX()); + y_scale = qreal(painter.device()->physicalDpiY()) / qreal(painter.device()->logicalDpiY()); } void MicroProfileWidget::paintEvent(QPaintEvent* ev) { QPainter painter(this); + painter.scale(x_scale, y_scale); + painter.setBackground(Qt::black); painter.eraseRect(rect()); @@ -248,24 +256,24 @@ void MicroProfileWidget::hideEvent(QHideEvent* ev) { } void MicroProfileWidget::mouseMoveEvent(QMouseEvent* ev) { - MicroProfileMousePosition(ev->x(), ev->y(), 0); + MicroProfileMousePosition(ev->x() / x_scale, ev->y() / y_scale, 0); ev->accept(); } void MicroProfileWidget::mousePressEvent(QMouseEvent* ev) { - MicroProfileMousePosition(ev->x(), ev->y(), 0); + MicroProfileMousePosition(ev->x() / x_scale, ev->y() / y_scale, 0); MicroProfileMouseButton(ev->buttons() & Qt::LeftButton, ev->buttons() & Qt::RightButton); ev->accept(); } void MicroProfileWidget::mouseReleaseEvent(QMouseEvent* ev) { - MicroProfileMousePosition(ev->x(), ev->y(), 0); + MicroProfileMousePosition(ev->x() / x_scale, ev->y() / y_scale, 0); MicroProfileMouseButton(ev->buttons() & Qt::LeftButton, ev->buttons() & Qt::RightButton); ev->accept(); } void MicroProfileWidget::wheelEvent(QWheelEvent* ev) { - MicroProfileMousePosition(ev->x(), ev->y(), ev->delta() / 120); + MicroProfileMousePosition(ev->x() / x_scale, ev->y() / y_scale, ev->delta() / 120); ev->accept(); } diff --git a/src/citra_qt/game_list.cpp b/src/citra_qt/game_list.cpp index d4ac9c96e..49cb98e70 100644 --- a/src/citra_qt/game_list.cpp +++ b/src/citra_qt/game_list.cpp @@ -118,44 +118,31 @@ void GameList::LoadInterfaceLayout() item_model->sort(header->sortIndicatorSection(), header->sortIndicatorOrder()); } -void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, bool deep_scan) +void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, unsigned int recursion) { const auto callback = [&](unsigned* num_entries_out, const std::string& directory, - const std::string& virtual_name) -> bool { + const std::string& virtual_name, + unsigned int recursion) -> bool { std::string physical_name = directory + DIR_SEP + virtual_name; if (stop_processing) return false; // Breaks the callback loop. - if (deep_scan && FileUtil::IsDirectory(physical_name)) { - AddFstEntriesToGameList(physical_name, true); + if (recursion > 0 && FileUtil::IsDirectory(physical_name)) { + AddFstEntriesToGameList(physical_name, recursion - 1); } else { - std::string filename_filename, filename_extension; - Common::SplitPath(physical_name, nullptr, &filename_filename, &filename_extension); - - Loader::FileType guessed_filetype = Loader::GuessFromExtension(filename_extension); - if (guessed_filetype == Loader::FileType::Unknown) - return true; - Loader::FileType filetype = Loader::IdentifyFile(physical_name); - if (filetype == Loader::FileType::Unknown) { - LOG_WARNING(Frontend, "File %s is of indeterminate type and is possibly corrupted.", physical_name.c_str()); + std::unique_ptr<Loader::AppLoader> loader = Loader::GetLoader(physical_name); + if (!loader) return true; - } - if (guessed_filetype != filetype) { - LOG_WARNING(Frontend, "Filetype and extension of file %s do not match.", physical_name.c_str()); - } std::vector<u8> smdh; - std::unique_ptr<Loader::AppLoader> loader = Loader::GetLoader(FileUtil::IOFile(physical_name, "rb"), filetype, filename_filename, physical_name); - - if (loader) - loader->ReadIcon(smdh); + loader->ReadIcon(smdh); emit EntryReady({ new GameListItemPath(QString::fromStdString(physical_name), smdh), - new GameListItem(QString::fromStdString(Loader::GetFileTypeString(filetype))), + new GameListItem(QString::fromStdString(Loader::GetFileTypeString(loader->GetFileType()))), new GameListItemSize(FileUtil::GetSize(physical_name)), }); } @@ -169,7 +156,7 @@ void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, bool d void GameListWorker::run() { stop_processing = false; - AddFstEntriesToGameList(dir_path.toStdString(), deep_scan); + AddFstEntriesToGameList(dir_path.toStdString(), deep_scan ? 256 : 0); emit Finished(); } diff --git a/src/citra_qt/game_list_p.h b/src/citra_qt/game_list_p.h index 284f5da81..353b2d1e2 100644 --- a/src/citra_qt/game_list_p.h +++ b/src/citra_qt/game_list_p.h @@ -15,52 +15,21 @@ #include "common/string_util.h" #include "common/color.h" -#include "core/loader/loader.h" +#include "core/loader/smdh.h" #include "video_core/utils.h" /** - * Tests if data is a valid SMDH by its length and magic number. - * @param smdh_data data buffer to test - * @return bool test result - */ -static bool IsValidSMDH(const std::vector<u8>& smdh_data) { - if (smdh_data.size() < sizeof(Loader::SMDH)) - return false; - - u32 magic; - memcpy(&magic, smdh_data.data(), 4); - - return Loader::MakeMagic('S', 'M', 'D', 'H') == magic; -} - -/** * Gets game icon from SMDH * @param sdmh SMDH data * @param large If true, returns large icon (48x48), otherwise returns small icon (24x24) * @return QPixmap game icon */ -static QPixmap GetIconFromSMDH(const Loader::SMDH& smdh, bool large) { - u32 size; - const u8* icon_data; - - if (large) { - size = 48; - icon_data = smdh.large_icon.data(); - } else { - size = 24; - icon_data = smdh.small_icon.data(); - } - - QImage icon(size, size, QImage::Format::Format_RGB888); - for (u32 x = 0; x < size; ++x) { - for (u32 y = 0; y < size; ++y) { - u32 coarse_y = y & ~7; - auto v = Color::DecodeRGB565( - icon_data + VideoCore::GetMortonOffset(x, y, 2) + coarse_y * size * 2); - icon.setPixel(x, y, qRgb(v.r(), v.g(), v.b())); - } - } +static QPixmap GetQPixmapFromSMDH(const Loader::SMDH& smdh, bool large) { + std::vector<u16> icon_data = smdh.GetIcon(large); + const uchar* data = reinterpret_cast<const uchar*>(icon_data.data()); + int size = large ? 48 : 24; + QImage icon(data, size, size, QImage::Format::Format_RGB16); return QPixmap::fromImage(icon); } @@ -82,8 +51,8 @@ static QPixmap GetDefaultIcon(bool large) { * @param language title language * @return QString short title */ -static QString GetShortTitleFromSMDH(const Loader::SMDH& smdh, Loader::SMDH::TitleLanguage language) { - return QString::fromUtf16(smdh.titles[static_cast<int>(language)].short_title.data()); +static QString GetQStringShortTitleFromSMDH(const Loader::SMDH& smdh, Loader::SMDH::TitleLanguage language) { + return QString::fromUtf16(smdh.GetShortTitle(language).data()); } class GameListItem : public QStandardItem { @@ -112,7 +81,7 @@ public: { setData(game_path, FullPathRole); - if (!IsValidSMDH(smdh_data)) { + if (!Loader::IsValidSMDH(smdh_data)) { // SMDH is not valid, set a default icon setData(GetDefaultIcon(true), Qt::DecorationRole); return; @@ -122,10 +91,10 @@ public: memcpy(&smdh, smdh_data.data(), sizeof(Loader::SMDH)); // Get icon from SMDH - setData(GetIconFromSMDH(smdh, true), Qt::DecorationRole); + setData(GetQPixmapFromSMDH(smdh, true), Qt::DecorationRole); // Get title form SMDH - setData(GetShortTitleFromSMDH(smdh, Loader::SMDH::TitleLanguage::English), TitleRole); + setData(GetQStringShortTitleFromSMDH(smdh, Loader::SMDH::TitleLanguage::English), TitleRole); } QVariant data(int role) const override { @@ -212,5 +181,5 @@ private: bool deep_scan; std::atomic_bool stop_processing; - void AddFstEntriesToGameList(const std::string& dir_path, bool deep_scan); + void AddFstEntriesToGameList(const std::string& dir_path, unsigned int recursion = 0); }; diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp index a85c94a4b..6239160bc 100644 --- a/src/citra_qt/main.cpp +++ b/src/citra_qt/main.cpp @@ -272,7 +272,15 @@ bool GMainWindow::InitializeSystem() { } bool GMainWindow::LoadROM(const std::string& filename) { - Loader::ResultStatus result = Loader::LoadFile(filename); + std::unique_ptr<Loader::AppLoader> app_loader = Loader::GetLoader(filename); + if (!app_loader) { + LOG_CRITICAL(Frontend, "Failed to obtain loader for %s!", filename.c_str()); + QMessageBox::critical(this, tr("Error while loading ROM!"), + tr("The ROM format is not supported.")); + return false; + } + + Loader::ResultStatus result = app_loader->Load(); if (Loader::ResultStatus::Success != result) { LOG_CRITICAL(Frontend, "Failed to load ROM!"); System::Shutdown(); |
