diff options
Diffstat (limited to 'src/citra_qt')
-rw-r--r-- | src/citra_qt/CMakeLists.txt | 3 | ||||
-rw-r--r-- | src/citra_qt/bootmanager.cpp | 2 | ||||
-rw-r--r-- | src/citra_qt/config.cpp | 10 | ||||
-rw-r--r-- | src/citra_qt/configure_general.cpp | 2 | ||||
-rw-r--r-- | src/citra_qt/configure_general.ui | 7 | ||||
-rw-r--r-- | src/citra_qt/debugger/graphics_breakpoints.cpp | 6 | ||||
-rw-r--r-- | src/citra_qt/debugger/graphics_framebuffer.cpp | 6 | ||||
-rw-r--r-- | src/citra_qt/debugger/graphics_tracing.cpp | 4 | ||||
-rw-r--r-- | src/citra_qt/debugger/graphics_vertex_shader.cpp | 6 | ||||
-rw-r--r-- | src/citra_qt/debugger/profiler.cpp | 39 | ||||
-rw-r--r-- | src/citra_qt/debugger/profiler.h | 3 | ||||
-rw-r--r-- | src/citra_qt/game_list.cpp | 16 | ||||
-rw-r--r-- | src/citra_qt/game_list.h | 2 | ||||
-rw-r--r-- | src/citra_qt/game_list_p.h | 106 | ||||
-rw-r--r-- | src/citra_qt/main.cpp | 20 | ||||
-rw-r--r-- | src/citra_qt/util/util.cpp | 2 |
16 files changed, 187 insertions, 47 deletions
diff --git a/src/citra_qt/CMakeLists.txt b/src/citra_qt/CMakeLists.txt index 6660d9879..3f0099200 100644 --- a/src/citra_qt/CMakeLists.txt +++ b/src/citra_qt/CMakeLists.txt @@ -55,6 +55,7 @@ set(HEADERS configure_dialog.h configure_general.h game_list.h + game_list_p.h hotkeys.h main.h ui_settings.h @@ -92,7 +93,7 @@ else() endif() target_link_libraries(citra-qt core video_core audio_core common qhexedit) target_link_libraries(citra-qt ${OPENGL_gl_LIBRARY} ${CITRA_QT_LIBS}) -target_link_libraries(citra-qt ${PLATFORM_LIBRARIES}) +target_link_libraries(citra-qt ${PLATFORM_LIBRARIES} Threads::Threads) if(${CMAKE_SYSTEM_NAME} MATCHES "Linux|FreeBSD|OpenBSD|NetBSD") install(TARGETS citra-qt RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/bin") diff --git a/src/citra_qt/bootmanager.cpp b/src/citra_qt/bootmanager.cpp index 8e60b9cad..01b81c11c 100644 --- a/src/citra_qt/bootmanager.cpp +++ b/src/citra_qt/bootmanager.cpp @@ -71,7 +71,9 @@ void EmuThread::run() { // Shutdown the core emulation System::Shutdown(); +#if MICROPROFILE_ENABLED MicroProfileOnThreadExit(); +#endif render_window->moveContext(); } diff --git a/src/citra_qt/config.cpp b/src/citra_qt/config.cpp index e363be38a..b5bb75537 100644 --- a/src/citra_qt/config.cpp +++ b/src/citra_qt/config.cpp @@ -45,12 +45,17 @@ void Config::ReadValues() { qt_config->beginGroup("Renderer"); Settings::values.use_hw_renderer = qt_config->value("use_hw_renderer", false).toBool(); Settings::values.use_shader_jit = qt_config->value("use_shader_jit", true).toBool(); + Settings::values.use_scaled_resolution = qt_config->value("use_scaled_resolution", false).toBool(); Settings::values.bg_red = qt_config->value("bg_red", 1.0).toFloat(); Settings::values.bg_green = qt_config->value("bg_green", 1.0).toFloat(); Settings::values.bg_blue = qt_config->value("bg_blue", 1.0).toFloat(); qt_config->endGroup(); + qt_config->beginGroup("Audio"); + Settings::values.sink_id = qt_config->value("output_engine", "auto").toString().toStdString(); + qt_config->endGroup(); + qt_config->beginGroup("Data Storage"); Settings::values.use_virtual_sd = qt_config->value("use_virtual_sd", true).toBool(); qt_config->endGroup(); @@ -129,6 +134,7 @@ void Config::SaveValues() { qt_config->beginGroup("Renderer"); qt_config->setValue("use_hw_renderer", Settings::values.use_hw_renderer); qt_config->setValue("use_shader_jit", Settings::values.use_shader_jit); + qt_config->setValue("use_scaled_resolution", Settings::values.use_scaled_resolution); // Cast to double because Qt's written float values are not human-readable qt_config->setValue("bg_red", (double)Settings::values.bg_red); @@ -136,6 +142,10 @@ void Config::SaveValues() { qt_config->setValue("bg_blue", (double)Settings::values.bg_blue); qt_config->endGroup(); + qt_config->beginGroup("Audio"); + qt_config->setValue("output_engine", QString::fromStdString(Settings::values.sink_id)); + qt_config->endGroup(); + qt_config->beginGroup("Data Storage"); qt_config->setValue("use_virtual_sd", Settings::values.use_virtual_sd); qt_config->endGroup(); diff --git a/src/citra_qt/configure_general.cpp b/src/citra_qt/configure_general.cpp index a27d0d26c..62648e665 100644 --- a/src/citra_qt/configure_general.cpp +++ b/src/citra_qt/configure_general.cpp @@ -25,6 +25,7 @@ void ConfigureGeneral::setConfiguration() { ui->region_combobox->setCurrentIndex(Settings::values.region_value); ui->toogle_hw_renderer->setChecked(Settings::values.use_hw_renderer); ui->toogle_shader_jit->setChecked(Settings::values.use_shader_jit); + ui->toogle_scaled_resolution->setChecked(Settings::values.use_scaled_resolution); } void ConfigureGeneral::applyConfiguration() { @@ -33,5 +34,6 @@ void ConfigureGeneral::applyConfiguration() { Settings::values.region_value = ui->region_combobox->currentIndex(); Settings::values.use_hw_renderer = ui->toogle_hw_renderer->isChecked(); Settings::values.use_shader_jit = ui->toogle_shader_jit->isChecked(); + Settings::values.use_scaled_resolution = ui->toogle_scaled_resolution->isChecked(); Settings::Apply(); } diff --git a/src/citra_qt/configure_general.ui b/src/citra_qt/configure_general.ui index 47184c5c6..5eb309793 100644 --- a/src/citra_qt/configure_general.ui +++ b/src/citra_qt/configure_general.ui @@ -128,6 +128,13 @@ </property> </widget> </item> + <item> + <widget class="QCheckBox" name="toogle_scaled_resolution"> + <property name="text"> + <string>Enable scaled resolution</string> + </property> + </widget> + </item> </layout> </item> </layout> diff --git a/src/citra_qt/debugger/graphics_breakpoints.cpp b/src/citra_qt/debugger/graphics_breakpoints.cpp index 819ec7707..fe66918a8 100644 --- a/src/citra_qt/debugger/graphics_breakpoints.cpp +++ b/src/citra_qt/debugger/graphics_breakpoints.cpp @@ -44,7 +44,7 @@ QVariant BreakPointModel::data(const QModelIndex& index, int role) const { Pica::DebugContext::Event::PicaCommandProcessed, tr("Pica command processed") }, { Pica::DebugContext::Event::IncomingPrimitiveBatch, tr("Incoming primitive batch") }, { Pica::DebugContext::Event::FinishedPrimitiveBatch, tr("Finished primitive batch") }, - { Pica::DebugContext::Event::VertexLoaded, tr("Vertex loaded") }, + { Pica::DebugContext::Event::VertexShaderInvocation, tr("Vertex shader invocation") }, { Pica::DebugContext::Event::IncomingDisplayTransfer, tr("Incoming display transfer") }, { Pica::DebugContext::Event::GSPCommandProcessed, tr("GSP command processed") }, { Pica::DebugContext::Event::BufferSwapped, tr("Buffers swapped") } @@ -75,7 +75,7 @@ QVariant BreakPointModel::data(const QModelIndex& index, int role) const case Role_IsEnabled: { auto context = context_weak.lock(); - return context && context->breakpoints[event].enabled; + return context && context->breakpoints[(int)event].enabled; } default: @@ -110,7 +110,7 @@ bool BreakPointModel::setData(const QModelIndex& index, const QVariant& value, i if (!context) return false; - context->breakpoints[event].enabled = value == Qt::Checked; + context->breakpoints[(int)event].enabled = value == Qt::Checked; QModelIndex changed_index = createIndex(index.row(), 0); emit dataChanged(changed_index, changed_index); return true; diff --git a/src/citra_qt/debugger/graphics_framebuffer.cpp b/src/citra_qt/debugger/graphics_framebuffer.cpp index c30e75933..68cff78b2 100644 --- a/src/citra_qt/debugger/graphics_framebuffer.cpp +++ b/src/citra_qt/debugger/graphics_framebuffer.cpp @@ -346,5 +346,11 @@ u32 GraphicsFramebufferWidget::BytesPerPixel(GraphicsFramebufferWidget::Format f case Format::RGBA4: case Format::D16: return 2; + default: + UNREACHABLE_MSG("GraphicsFramebufferWidget::BytesPerPixel: this " + "should not be reached as this function should " + "be given a format which is in " + "GraphicsFramebufferWidget::Format. Instead got %i", + static_cast<int>(format)); } } diff --git a/src/citra_qt/debugger/graphics_tracing.cpp b/src/citra_qt/debugger/graphics_tracing.cpp index e06498744..1402f8e79 100644 --- a/src/citra_qt/debugger/graphics_tracing.cpp +++ b/src/citra_qt/debugger/graphics_tracing.cpp @@ -2,6 +2,9 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include <algorithm> +#include <array> +#include <iterator> #include <memory> #include <boost/range/algorithm/copy.hpp> @@ -18,6 +21,7 @@ #include "core/hw/gpu.h" #include "core/hw/lcd.h" +#include "core/tracer/recorder.h" #include "nihstro/float24.h" diff --git a/src/citra_qt/debugger/graphics_vertex_shader.cpp b/src/citra_qt/debugger/graphics_vertex_shader.cpp index d648d4640..854f6ff16 100644 --- a/src/citra_qt/debugger/graphics_vertex_shader.cpp +++ b/src/citra_qt/debugger/graphics_vertex_shader.cpp @@ -365,7 +365,7 @@ GraphicsVertexShaderWidget::GraphicsVertexShaderWidget(std::shared_ptr< Pica::De input_data[i]->setValidator(new QDoubleValidator(input_data[i])); } - breakpoint_warning = new QLabel(tr("(data only available at VertexLoaded breakpoints)")); + breakpoint_warning = new QLabel(tr("(data only available at vertex shader invocation breakpoints)")); // TODO: Add some button for jumping to the shader entry point @@ -454,7 +454,7 @@ GraphicsVertexShaderWidget::GraphicsVertexShaderWidget(std::shared_ptr< Pica::De void GraphicsVertexShaderWidget::OnBreakPointHit(Pica::DebugContext::Event event, void* data) { auto input = static_cast<Pica::Shader::InputVertex*>(data); - if (event == Pica::DebugContext::Event::VertexLoaded) { + if (event == Pica::DebugContext::Event::VertexShaderInvocation) { Reload(true, data); } else { // No vertex data is retrievable => invalidate currently stored vertex data @@ -515,7 +515,7 @@ void GraphicsVertexShaderWidget::Reload(bool replace_vertex_data, void* vertex_d } // Initialize debug info text for current cycle count - cycle_index->setMaximum(debug_data.records.size() - 1); + cycle_index->setMaximum(static_cast<int>(debug_data.records.size() - 1)); OnCycleIndexChanged(cycle_index->value()); model->endResetModel(); diff --git a/src/citra_qt/debugger/profiler.cpp b/src/citra_qt/debugger/profiler.cpp index 4f6ba0e1f..7bb010f77 100644 --- a/src/citra_qt/debugger/profiler.cpp +++ b/src/citra_qt/debugger/profiler.cpp @@ -9,13 +9,16 @@ #include "citra_qt/debugger/profiler.h" #include "citra_qt/util/util.h" +#include "common/common_types.h" #include "common/microprofile.h" #include "common/profiler_reporting.h" // Include the implementation of the UI in this file. This isn't in microprofile.cpp because the // non-Qt frontends don't need it (and don't implement the UI drawing hooks either). +#if MICROPROFILE_ENABLED #define MICROPROFILEUI_IMPL 1 #include "common/microprofileui.h" +#endif using namespace Common::Profiling; @@ -34,21 +37,9 @@ static QVariant GetDataForColumn(int col, const AggregatedDuration& duration) } } -static const TimingCategoryInfo* GetCategoryInfo(int id) -{ - const auto& categories = GetProfilingManager().GetTimingCategoriesInfo(); - if ((size_t)id >= categories.size()) { - return nullptr; - } else { - return &categories[id]; - } -} - ProfilerModel::ProfilerModel(QObject* parent) : QAbstractItemModel(parent) { updateProfilingInfo(); - const auto& categories = GetProfilingManager().GetTimingCategoriesInfo(); - results.time_per_category.resize(categories.size()); } QVariant ProfilerModel::headerData(int section, Qt::Orientation orientation, int role) const @@ -85,7 +76,7 @@ int ProfilerModel::rowCount(const QModelIndex& parent) const if (parent.isValid()) { return 0; } else { - return static_cast<int>(results.time_per_category.size() + 2); + return 2; } } @@ -104,17 +95,6 @@ QVariant ProfilerModel::data(const QModelIndex& index, int role) const } else { return GetDataForColumn(index.column(), results.interframe_time); } - } else { - if (index.column() == 0) { - const TimingCategoryInfo* info = GetCategoryInfo(index.row() - 2); - return info != nullptr ? QString(info->name) : QVariant(); - } else { - if (index.row() - 2 < (int)results.time_per_category.size()) { - return GetDataForColumn(index.column(), results.time_per_category[index.row() - 2]); - } else { - return QVariant(); - } - } } } @@ -148,6 +128,8 @@ void ProfilerWidget::setProfilingInfoUpdateEnabled(bool enable) } } +#if MICROPROFILE_ENABLED + class MicroProfileWidget : public QWidget { public: MicroProfileWidget(QWidget* parent = nullptr); @@ -171,6 +153,8 @@ private: QTimer update_timer; }; +#endif + MicroProfileDialog::MicroProfileDialog(QWidget* parent) : QWidget(parent, Qt::Dialog) { @@ -180,6 +164,8 @@ MicroProfileDialog::MicroProfileDialog(QWidget* parent) // Remove the "?" button from the titlebar and enable the maximize button setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint | Qt::WindowMaximizeButtonHint); +#if MICROPROFILE_ENABLED + MicroProfileWidget* widget = new MicroProfileWidget(this); QLayout* layout = new QVBoxLayout(this); @@ -191,6 +177,7 @@ MicroProfileDialog::MicroProfileDialog(QWidget* parent) setFocusProxy(widget); widget->setFocusPolicy(Qt::StrongFocus); widget->setFocus(); +#endif } QAction* MicroProfileDialog::toggleViewAction() { @@ -218,6 +205,9 @@ void MicroProfileDialog::hideEvent(QHideEvent* ev) { QWidget::hideEvent(ev); } + +#if MICROPROFILE_ENABLED + /// There's no way to pass a user pointer to MicroProfile, so this variable is used to make the /// QPainter available inside the drawing callbacks. static QPainter* mp_painter = nullptr; @@ -337,3 +327,4 @@ void MicroProfileDrawLine2D(u32 vertices_length, float* vertices, u32 hex_color) mp_painter->drawPolyline(point_buf.data(), vertices_length); point_buf.clear(); } +#endif diff --git a/src/citra_qt/debugger/profiler.h b/src/citra_qt/debugger/profiler.h index 036054740..3b38ed8ec 100644 --- a/src/citra_qt/debugger/profiler.h +++ b/src/citra_qt/debugger/profiler.h @@ -7,8 +7,10 @@ #include <QAbstractItemModel> #include <QDockWidget> #include <QTimer> + #include "ui_profiler.h" +#include "common/microprofile.h" #include "common/profiler_reporting.h" class ProfilerModel : public QAbstractItemModel @@ -49,6 +51,7 @@ private: QTimer update_timer; }; + class MicroProfileDialog : public QWidget { Q_OBJECT diff --git a/src/citra_qt/game_list.cpp b/src/citra_qt/game_list.cpp index d14532102..d4ac9c96e 100644 --- a/src/citra_qt/game_list.cpp +++ b/src/citra_qt/game_list.cpp @@ -34,8 +34,8 @@ GameList::GameList(QWidget* parent) tree_view->setUniformRowHeights(true); item_model->insertColumns(0, COLUMN_COUNT); - item_model->setHeaderData(COLUMN_FILE_TYPE, Qt::Horizontal, "File type"); item_model->setHeaderData(COLUMN_NAME, Qt::Horizontal, "Name"); + item_model->setHeaderData(COLUMN_FILE_TYPE, Qt::Horizontal, "File type"); item_model->setHeaderData(COLUMN_SIZE, Qt::Horizontal, "Size"); connect(tree_view, SIGNAL(activated(const QModelIndex&)), this, SLOT(ValidateEntry(const QModelIndex&))); @@ -109,7 +109,11 @@ void GameList::SaveInterfaceLayout() void GameList::LoadInterfaceLayout() { auto header = tree_view->header(); - header->restoreState(UISettings::values.gamelist_header_state); + if (!header->restoreState(UISettings::values.gamelist_header_state)) { + // We are using the name column to display icons and titles + // so make it as large as possible as default. + header->resizeSection(COLUMN_NAME, header->width()); + } item_model->sort(header->sortIndicatorSection(), header->sortIndicatorOrder()); } @@ -143,9 +147,15 @@ void GameListWorker::AddFstEntriesToGameList(const std::string& dir_path, bool d 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); + emit EntryReady({ + new GameListItemPath(QString::fromStdString(physical_name), smdh), new GameListItem(QString::fromStdString(Loader::GetFileTypeString(filetype))), - new GameListItemPath(QString::fromStdString(physical_name)), new GameListItemSize(FileUtil::GetSize(physical_name)), }); } diff --git a/src/citra_qt/game_list.h b/src/citra_qt/game_list.h index 48febdc60..198674f04 100644 --- a/src/citra_qt/game_list.h +++ b/src/citra_qt/game_list.h @@ -20,8 +20,8 @@ class GameList : public QWidget { public: enum { - COLUMN_FILE_TYPE, COLUMN_NAME, + COLUMN_FILE_TYPE, COLUMN_SIZE, COLUMN_COUNT, // Number of columns }; diff --git a/src/citra_qt/game_list_p.h b/src/citra_qt/game_list_p.h index 820012bce..284f5da81 100644 --- a/src/citra_qt/game_list_p.h +++ b/src/citra_qt/game_list_p.h @@ -6,13 +6,85 @@ #include <atomic> +#include <QImage> #include <QRunnable> #include <QStandardItem> #include <QString> #include "citra_qt/util/util.h" #include "common/string_util.h" +#include "common/color.h" +#include "core/loader/loader.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())); + } + } + return QPixmap::fromImage(icon); +} + +/** + * Gets the default icon (for games without valid SMDH) + * @param large If true, returns large icon (48x48), otherwise returns small icon (24x24) + * @return QPixmap default icon + */ +static QPixmap GetDefaultIcon(bool large) { + int size = large ? 48 : 24; + QPixmap icon(size, size); + icon.fill(Qt::transparent); + return icon; +} + +/** + * Gets the short game title fromn SMDH + * @param sdmh SMDH data + * @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()); +} class GameListItem : public QStandardItem { @@ -27,29 +99,43 @@ public: * A specialization of GameListItem for path values. * This class ensures that for every full path value it holds, a correct string representation * of just the filename (with no extension) will be displayed to the user. + * If this class recieves valid SMDH data, it will also display game icons and titles. */ class GameListItemPath : public GameListItem { public: static const int FullPathRole = Qt::UserRole + 1; + static const int TitleRole = Qt::UserRole + 2; GameListItemPath(): GameListItem() {} - GameListItemPath(const QString& game_path): GameListItem() + GameListItemPath(const QString& game_path, const std::vector<u8>& smdh_data): GameListItem() { setData(game_path, FullPathRole); + + if (!IsValidSMDH(smdh_data)) { + // SMDH is not valid, set a default icon + setData(GetDefaultIcon(true), Qt::DecorationRole); + return; + } + + Loader::SMDH smdh; + memcpy(&smdh, smdh_data.data(), sizeof(Loader::SMDH)); + + // Get icon from SMDH + setData(GetIconFromSMDH(smdh, true), Qt::DecorationRole); + + // Get title form SMDH + setData(GetShortTitleFromSMDH(smdh, Loader::SMDH::TitleLanguage::English), TitleRole); } - void setData(const QVariant& value, int role) override - { - // By specializing setData for FullPathRole, we can ensure that the two string - // representations of the data are always accurate and in the correct format. - if (role == FullPathRole) { + QVariant data(int role) const override { + if (role == Qt::DisplayRole) { std::string filename; - Common::SplitPath(value.toString().toStdString(), nullptr, &filename, nullptr); - GameListItem::setData(QString::fromStdString(filename), Qt::DisplayRole); - GameListItem::setData(value, FullPathRole); + Common::SplitPath(data(FullPathRole).toString().toStdString(), nullptr, &filename, nullptr); + QString title = data(TitleRole).toString(); + return QString::fromStdString(filename) + (title.isEmpty() ? "" : "\n " + title); } else { - GameListItem::setData(value, role); + return GameListItem::data(role); } } }; diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp index 2ca1e51f6..a85c94a4b 100644 --- a/src/citra_qt/main.cpp +++ b/src/citra_qt/main.cpp @@ -6,6 +6,9 @@ #include <memory> #include <thread> +#include <glad/glad.h> + +#define QT_NO_OPENGL #include <QDesktopWidget> #include <QtGui> #include <QFileDialog> @@ -69,8 +72,10 @@ GMainWindow::GMainWindow() : config(new Config()), emu_thread(nullptr) addDockWidget(Qt::BottomDockWidgetArea, profilerWidget); profilerWidget->hide(); +#if MICROPROFILE_ENABLED microProfileDialog = new MicroProfileDialog(this); microProfileDialog->hide(); +#endif disasmWidget = new DisassemblerWidget(this, emu_thread.get()); addDockWidget(Qt::BottomDockWidgetArea, disasmWidget); @@ -110,7 +115,9 @@ GMainWindow::GMainWindow() : config(new Config()), emu_thread(nullptr) QMenu* debug_menu = ui.menu_View->addMenu(tr("Debugging")); debug_menu->addAction(profilerWidget->toggleViewAction()); +#if MICROPROFILE_ENABLED debug_menu->addAction(microProfileDialog->toggleViewAction()); +#endif debug_menu->addAction(disasmWidget->toggleViewAction()); debug_menu->addAction(registersWidget->toggleViewAction()); debug_menu->addAction(callstackWidget->toggleViewAction()); @@ -136,8 +143,10 @@ GMainWindow::GMainWindow() : config(new Config()), emu_thread(nullptr) restoreGeometry(UISettings::values.geometry); restoreState(UISettings::values.state); render_window->restoreGeometry(UISettings::values.renderwindow_geometry); +#if MICROPROFILE_ENABLED microProfileDialog->restoreGeometry(UISettings::values.microprofile_geometry); microProfileDialog->setVisible(UISettings::values.microprofile_visible); +#endif game_list->LoadInterfaceLayout(); @@ -234,6 +243,14 @@ bool GMainWindow::InitializeSystem() { if (emu_thread != nullptr) ShutdownGame(); + render_window->MakeCurrent(); + if (!gladLoadGL()) { + QMessageBox::critical(this, tr("Error while starting Citra!"), + tr("Failed to initialize the video core!\n\n" + "Please ensure that your GPU supports OpenGL 3.3 and that you have the latest graphics driver.")); + return false; + } + // Initialize the core emulation System::Result system_result = System::Init(render_window); if (System::Result::Success != system_result) { @@ -511,9 +528,10 @@ void GMainWindow::closeEvent(QCloseEvent* event) { UISettings::values.geometry = saveGeometry(); UISettings::values.state = saveState(); UISettings::values.renderwindow_geometry = render_window->saveGeometry(); +#if MICROPROFILE_ENABLED UISettings::values.microprofile_geometry = microProfileDialog->saveGeometry(); UISettings::values.microprofile_visible = microProfileDialog->isVisible(); - +#endif UISettings::values.single_window_mode = ui.action_Single_Window_Mode->isChecked(); UISettings::values.display_titlebar = ui.actionDisplay_widget_title_bars->isChecked(); UISettings::values.first_start = false; diff --git a/src/citra_qt/util/util.cpp b/src/citra_qt/util/util.cpp index 8734a8efd..2f9beb5cc 100644 --- a/src/citra_qt/util/util.cpp +++ b/src/citra_qt/util/util.cpp @@ -19,7 +19,7 @@ QString ReadableByteSize(qulonglong size) { static const std::array<const char*, 6> units = { "B", "KiB", "MiB", "GiB", "TiB", "PiB" }; if (size == 0) return "0"; - int digit_groups = std::min<int>((int)(std::log10(size) / std::log10(1024)), units.size()); + int digit_groups = std::min<int>(static_cast<int>(std::log10(size) / std::log10(1024)), static_cast<int>(units.size())); return QString("%L1 %2").arg(size / std::pow(1024, digit_groups), 0, 'f', 1) .arg(units[digit_groups]); } |