From 2fd8b52163eb5a55cd4d5a0b13041c712f4f8819 Mon Sep 17 00:00:00 2001 From: BearOso Date: Sat, 5 Aug 2023 16:59:56 -0500 Subject: [PATCH] Qt: More updates. --- common/video/wgl_context.cpp | 3 +- common/video/wgl_context.hpp | 2 +- external/glslang | 2 +- qt/CMakeLists.txt | 10 ++++++- qt/QtStaticBuildVars.txt | 37 ++++++++++++++++++++++++ qt/src/BindingPanel.cpp | 1 + qt/src/BindingPanel.hpp | 8 ++++-- qt/src/ControllerPanel.cpp | 2 ++ qt/src/ControllerPanel.hpp | 3 +- qt/src/DisplayPanel.cpp | 2 ++ qt/src/EmuApplication.cpp | 18 +++++++----- qt/src/EmuApplication.hpp | 11 ++++---- qt/src/EmuCanvas.cpp | 1 + qt/src/EmuCanvas.hpp | 5 ++-- qt/src/EmuCanvasOpenGL.cpp | 1 + qt/src/EmuCanvasQt.cpp | 14 ++++++++-- qt/src/EmuCanvasQt.hpp | 4 +++ qt/src/EmuCanvasVulkan.cpp | 2 ++ qt/src/EmuCanvasVulkan.hpp | 4 +-- qt/src/EmuConfig.hpp | 2 ++ qt/src/EmuMainWindow.cpp | 4 +++ qt/src/EmuSettingsWindow.cpp | 17 +++++++---- qt/src/EmulationPanel.cpp | 3 ++ qt/src/EmulationPanel.hpp | 3 +- qt/src/FoldersPanel.cpp | 2 ++ qt/src/GeneralPanel.cpp | 2 ++ qt/src/ShaderParametersDialog.cpp | 9 +++--- qt/src/SoundPanel.cpp | 2 ++ qt/src/main.cpp | 14 ++++++++++ qt/src/resources/snes9x.ico | Bin 0 -> 12939 bytes qt/src/resources/snes9x_icon.rc | 1 + vulkan/std_chrono_throttle.cpp | 45 +++++++++++++++++++++++------- 32 files changed, 186 insertions(+), 48 deletions(-) create mode 100644 qt/QtStaticBuildVars.txt create mode 100644 qt/src/resources/snes9x.ico create mode 100644 qt/src/resources/snes9x_icon.rc diff --git a/common/video/wgl_context.cpp b/common/video/wgl_context.cpp index 62a11cb0..46717e39 100644 --- a/common/video/wgl_context.cpp +++ b/common/video/wgl_context.cpp @@ -25,8 +25,7 @@ WGLContext::~WGLContext() void WGLContext::deinit() { - if (wglMakeCurrent) - wglMakeCurrent(nullptr, nullptr); + wglMakeCurrent(nullptr, nullptr); if (hglrc) wglDeleteContext(hglrc); if (hdc) diff --git a/common/video/wgl_context.hpp b/common/video/wgl_context.hpp index d139aca5..22fcd527 100644 --- a/common/video/wgl_context.hpp +++ b/common/video/wgl_context.hpp @@ -22,7 +22,7 @@ class WGLContext : public OpenGLContext void swap_buffers() override; void swap_interval(int frames) override; void make_current() override; - bool ready(); + bool ready() override; void deinit(); HWND hwnd; diff --git a/external/glslang b/external/glslang index 9c7fd1a3..3ebb72cc 160000 --- a/external/glslang +++ b/external/glslang @@ -1 +1 @@ -Subproject commit 9c7fd1a33e5cecbe465e1cd70170167d5e40d398 +Subproject commit 3ebb72cc7429f0ab8218104dc3687c659c0f364d diff --git a/qt/CMakeLists.txt b/qt/CMakeLists.txt index c2377ae5..1c453bbd 100644 --- a/qt/CMakeLists.txt +++ b/qt/CMakeLists.txt @@ -76,6 +76,7 @@ add_library(snes9x-core ${SNES9X_CORE_SOURCES}) target_include_directories(snes9x-core PRIVATE ../) target_compile_definitions(snes9x-core PRIVATE ZLIB HAVE_STDINT_H ALLOW_CPU_OVERCLOCK) + find_package(Qt6 REQUIRED COMPONENTS Widgets Gui) find_package(PkgConfig REQUIRED) pkg_check_modules(SDL REQUIRED sdl2) @@ -153,8 +154,10 @@ if(NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Windows") else() list(APPEND PLATFORM_SOURCES ../common/video/wgl_context.cpp - ../external/glad/src/wgl.c) + ../external/glad/src/wgl.c + src/resources/snes9x_icon.rc) list(APPEND LIBS opengl32) + list(APPEND DEFINES SDL_MAIN_HANDLED) endif() set(QT_UI_FILES @@ -170,6 +173,7 @@ set(QT_UI_FILES set(USE_SANITIZERS CACHE BOOL OFF) set(BUILD_TESTS CACHE BOOL OFF) set(BUILD_TOOLS CACHE BOOL OFF) +set(BUNDLE_SPEEX FORCE BOOL ON) add_subdirectory("../external/cubeb" "cubeb" EXCLUDE_FROM_ALL) list(APPEND LIBS cubeb) list(APPEND INCLUDES "../external/cubeb/include") @@ -255,6 +259,10 @@ list(APPEND SOURCES ../external/imgui/imgui.cpp list(APPEND INCLUDES ../external/imgui) add_executable(snes9x-qt ${QT_GUI_SOURCES} ${SOURCES} ${PLATFORM_SOURCES} src/resources/snes9x.qrc) + +if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows") +set_target_properties(snes9x-qt PROPERTIES WIN32_EXECUTABLE True) +endif() target_link_libraries(snes9x-qt snes9x-core ${LIBS}) target_compile_definitions(snes9x-qt PRIVATE ${DEFINES}) target_compile_options(snes9x-qt PRIVATE ${FLAGS}) diff --git a/qt/QtStaticBuildVars.txt b/qt/QtStaticBuildVars.txt new file mode 100644 index 00000000..355b2f25 --- /dev/null +++ b/qt/QtStaticBuildVars.txt @@ -0,0 +1,37 @@ +-DBUILD_SHARED_LIBS=0 +-DCMAKE_BUILD_TYPE=Release +-DCMAKE_INSTALL_PREFIX="C:/Qt" +-DFEATURE_androiddeployqt=0 +-DFEATURE_brotli=0 +-DFEATURE_dbus=0 +-DFEATURE_freetype=0 +-DFEATURE_harfbuzz=0 +-DFEATURE_imageformat_ppm=0 +-DFEATURE_islamiccivilcalendar=0 +-DFEATURE_jalalicalendar=0 +-DFEATURE_lcdnumber=0 +-DFEATURE_movie=0 +-DFEATURE_openssl_linked=0 +-DFEATURE_openssl_runtime=0 +-DFEATURE_optimize_size=1 +-DFEATURE_pdf=0 +-DFEATURE_printsupport=0 +-DFEATURE_shani=0 +-DFEATURE_sql=0 +-DFEATURE_static=1 +-DFEATURE_system_doubleconversion=0 +-DFEATURE_system_freetype=0 +-DFEATURE_system_harfbuzz=0 +-DFEATURE_system_jpeg=0 +-DFEATURE_system_libb2=0 +-DFEATURE_system_png=0 +-DFEATURE_system_proxies=0 +-DFEATURE_system_textmarkdownreader=0 +-DFEATURE_system_zlib=0 +-DFEATURE_testlib=0 +-DFEATURE_textodfwriter=0 +-DFEATURE_vkgen=0 +-DFEATURE_vulkan=0 +-DFEATURE_zstd=0 +-DQT_BUILD_EXAMPLES_BY_DEFAULT=0 +-DQT_BUILD_TESTS_BY_DEFAULT=0 diff --git a/qt/src/BindingPanel.cpp b/qt/src/BindingPanel.cpp index 1a15da41..fd2cc040 100644 --- a/qt/src/BindingPanel.cpp +++ b/qt/src/BindingPanel.cpp @@ -1,4 +1,5 @@ #include "BindingPanel.hpp" +#include "EmuApplication.hpp" #include BindingPanel::BindingPanel(EmuApplication *app) diff --git a/qt/src/BindingPanel.hpp b/qt/src/BindingPanel.hpp index 5718b75f..59ce0b72 100644 --- a/qt/src/BindingPanel.hpp +++ b/qt/src/BindingPanel.hpp @@ -1,8 +1,10 @@ #pragma once -#include -#include + +#include #include -#include "EmuApplication.hpp" +#include "EmuBinding.hpp" + +class EmuApplication; class BindingPanel : public QWidget { diff --git a/qt/src/ControllerPanel.cpp b/qt/src/ControllerPanel.cpp index 98c1c108..301a0a21 100644 --- a/qt/src/ControllerPanel.cpp +++ b/qt/src/ControllerPanel.cpp @@ -1,5 +1,7 @@ #include "ControllerPanel.hpp" #include "SDLInputManager.hpp" +#include "EmuApplication.hpp" +#include "EmuConfig.hpp" #include "SDL_gamecontroller.h" #include #include diff --git a/qt/src/ControllerPanel.hpp b/qt/src/ControllerPanel.hpp index 401e22ff..d2ac3e38 100644 --- a/qt/src/ControllerPanel.hpp +++ b/qt/src/ControllerPanel.hpp @@ -1,9 +1,10 @@ #pragma once #include "ui_ControllerPanel.h" #include "BindingPanel.hpp" -#include "EmuApplication.hpp" #include +class EmuApplication; + class ControllerPanel : public Ui::ControllerPanel, public BindingPanel diff --git a/qt/src/DisplayPanel.cpp b/qt/src/DisplayPanel.cpp index e0449853..f1a203ed 100644 --- a/qt/src/DisplayPanel.cpp +++ b/qt/src/DisplayPanel.cpp @@ -1,4 +1,6 @@ #include "DisplayPanel.hpp" +#include "EmuMainWindow.hpp" +#include "EmuConfig.hpp" #include DisplayPanel::DisplayPanel(EmuApplication *app_) diff --git a/qt/src/EmuApplication.cpp b/qt/src/EmuApplication.cpp index 2f471af0..871ecf10 100644 --- a/qt/src/EmuApplication.cpp +++ b/qt/src/EmuApplication.cpp @@ -1,4 +1,7 @@ #include "EmuApplication.hpp" +#include "EmuMainWindow.hpp" +#include "SDLInputManager.hpp" +#include "Snes9xController.hpp" #include "common/audio/s9x_sound_driver_sdl.hpp" #include "common/audio/s9x_sound_driver_cubeb.hpp" #include @@ -135,13 +138,14 @@ void EmuApplication::startGame() core->screen_output_function = [&](uint16_t *data, int width, int height, int stride_bytes, double frame_rate) { if (window->canvas) { - QMetaObject::invokeMethod(window.get(), "output", Qt::ConnectionType::DirectConnection, - Q_ARG(uint8_t *, (uint8_t *)data), - Q_ARG(int, width), - Q_ARG(int, height), - Q_ARG(QImage::Format, QImage::Format_RGB16), - Q_ARG(int, stride_bytes), - Q_ARG(double, frame_rate)); + window->output((uint8_t *)data, width, height, QImage::Format_RGB16, stride_bytes, frame_rate); + // QMetaObject::invokeMethod(window.get(), "output", Qt::ConnectionType::DirectConnection, + // Q_ARG(uint8_t *, (uint8_t *)data), + // Q_ARG(int, width), + // Q_ARG(int, height), + // Q_ARG(QImage::Format, QImage::Format_RGB16), + // Q_ARG(int, stride_bytes), + // Q_ARG(double, frame_rate)); } }; diff --git a/qt/src/EmuApplication.hpp b/qt/src/EmuApplication.hpp index fe5c990a..4e61c302 100644 --- a/qt/src/EmuApplication.hpp +++ b/qt/src/EmuApplication.hpp @@ -3,11 +3,12 @@ #include #include -#include "EmuMainWindow.hpp" -#include "EmuConfig.hpp" -#include "SDLInputManager.hpp" -#include "Snes9xController.hpp" -#include "common/audio/s9x_sound_driver.hpp" +class EmuMainWindow; +class EmuConfig; +class EmuBinding; +class SDLInputManager; +class Snes9xController; +class S9xSoundDriver; struct EmuThread : public QThread { diff --git a/qt/src/EmuCanvas.cpp b/qt/src/EmuCanvas.cpp index 072f9223..1198ec4b 100644 --- a/qt/src/EmuCanvas.cpp +++ b/qt/src/EmuCanvas.cpp @@ -1,4 +1,5 @@ #include "EmuCanvas.hpp" +#include "EmuConfig.hpp" #include #include diff --git a/qt/src/EmuCanvas.hpp b/qt/src/EmuCanvas.hpp index 62e1e6a6..e609b67e 100644 --- a/qt/src/EmuCanvas.hpp +++ b/qt/src/EmuCanvas.hpp @@ -1,9 +1,10 @@ #pragma once #include #include -#include "EmuConfig.hpp" #include "../../vulkan/std_chrono_throttle.hpp" +class EmuConfig; + class EmuCanvas : public QWidget { public: @@ -33,7 +34,7 @@ class EmuCanvas : public QWidget struct Parameter { - bool operator==(const Parameter &other) + bool operator==(const Parameter &other) const { if (name == other.name && id == other.id && diff --git a/qt/src/EmuCanvasOpenGL.cpp b/qt/src/EmuCanvasOpenGL.cpp index f9e658e7..63e99ff1 100644 --- a/qt/src/EmuCanvasOpenGL.cpp +++ b/qt/src/EmuCanvasOpenGL.cpp @@ -17,6 +17,7 @@ using namespace QNativeInterface; #include "EmuMainWindow.hpp" #include "snes9x_imgui.h" #include "imgui_impl_opengl3.h" +#include static const char *stock_vertex_shader_140 = R"( #version 140 diff --git a/qt/src/EmuCanvasQt.cpp b/qt/src/EmuCanvasQt.cpp index 4f0ef70c..ba51d305 100644 --- a/qt/src/EmuCanvasQt.cpp +++ b/qt/src/EmuCanvasQt.cpp @@ -1,6 +1,10 @@ #include "EmuCanvasQt.hpp" +#include "EmuConfig.hpp" + #include #include +#include +#include EmuCanvasQt::EmuCanvasQt(EmuConfig *config, QWidget *parent, QWidget *main_window) : EmuCanvas(config, parent, main_window) @@ -19,8 +23,11 @@ void EmuCanvasQt::deinit() void EmuCanvasQt::draw() { - QWidget::repaint(0, 0, width(), height()); + qimage_mutex.lock(); + qimage = QImage((const uchar *)output_data.buffer, output_data.width, output_data.height, output_data.bytes_per_line, output_data.format); + qimage_mutex.unlock(); throttle(); + update(); } void EmuCanvasQt::paintEvent(QPaintEvent *event) @@ -34,7 +41,6 @@ void EmuCanvasQt::paintEvent(QPaintEvent *event) } QPainter paint(this); - QImage image((const uchar *)output_data.buffer, output_data.width, output_data.height, output_data.bytes_per_line, output_data.format); paint.setRenderHint(QPainter::SmoothPixmapTransform, config->bilinear_filter); QRect dest = { 0, 0, width(), height() }; if (config->maintain_aspect_ratio) @@ -43,7 +49,9 @@ void EmuCanvasQt::paintEvent(QPaintEvent *event) dest = applyAspect(dest); } - paint.drawImage(dest, image, QRect(0, 0, output_data.width, output_data.height)); + qimage_mutex.lock(); + paint.drawImage(dest, qimage, QRect(0, 0, output_data.width, output_data.height)); + qimage_mutex.unlock(); } void EmuCanvasQt::resizeEvent(QResizeEvent *event) diff --git a/qt/src/EmuCanvasQt.hpp b/qt/src/EmuCanvasQt.hpp index b754daf4..5638d83d 100644 --- a/qt/src/EmuCanvasQt.hpp +++ b/qt/src/EmuCanvasQt.hpp @@ -4,6 +4,7 @@ #include "EmuCanvas.hpp" #include +#include class EmuCanvasQt : public EmuCanvas { @@ -16,6 +17,9 @@ class EmuCanvasQt : public EmuCanvas void paintEvent(QPaintEvent *event) override; void resizeEvent(QResizeEvent *event) override; + + std::mutex qimage_mutex; + QImage qimage; }; #endif \ No newline at end of file diff --git a/qt/src/EmuCanvasVulkan.cpp b/qt/src/EmuCanvasVulkan.cpp index e957a8f9..566d4ac3 100644 --- a/qt/src/EmuCanvasVulkan.cpp +++ b/qt/src/EmuCanvasVulkan.cpp @@ -185,7 +185,9 @@ void EmuCanvasVulkan::draw() throttle(); context->swapchain->swap(); if (config->reduce_input_lag) + { context->wait_idle(); + } } } diff --git a/qt/src/EmuCanvasVulkan.hpp b/qt/src/EmuCanvasVulkan.hpp index 4c3c814e..0a2140b8 100644 --- a/qt/src/EmuCanvasVulkan.hpp +++ b/qt/src/EmuCanvasVulkan.hpp @@ -16,7 +16,7 @@ class EmuCanvasVulkan : public EmuCanvas EmuCanvasVulkan(EmuConfig *config, QWidget *parent, QWidget *main_window); ~EmuCanvasVulkan(); - void createContext(); + void createContext() override; void deinit() override; void paintEvent(QPaintEvent *event) override; void resizeEvent(QResizeEvent *event) override; @@ -30,7 +30,7 @@ class EmuCanvasVulkan : public EmuCanvas void draw() override; bool initImGui(); - void recreateUIAssets(); + void recreateUIAssets() override; vk::UniqueRenderPass imgui_render_pass; vk::UniqueDescriptorPool imgui_descriptor_pool; diff --git a/qt/src/EmuConfig.hpp b/qt/src/EmuConfig.hpp index ccba7633..03570916 100644 --- a/qt/src/EmuConfig.hpp +++ b/qt/src/EmuConfig.hpp @@ -2,6 +2,8 @@ #define __EMU_CONFIG_HPP #include +#include + #include "EmuBinding.hpp" struct EmuConfig diff --git a/qt/src/EmuMainWindow.cpp b/qt/src/EmuMainWindow.cpp index 7a0def5d..4532107c 100644 --- a/qt/src/EmuMainWindow.cpp +++ b/qt/src/EmuMainWindow.cpp @@ -13,6 +13,7 @@ #include "EmuMainWindow.hpp" #include "EmuSettingsWindow.hpp" #include "EmuApplication.hpp" +#include "EmuBinding.hpp" #include "EmuCanvasVulkan.hpp" #include "EmuCanvasOpenGL.hpp" #include "EmuCanvasQt.hpp" @@ -464,10 +465,13 @@ bool EmuMainWindow::event(QEvent *event) switch (event->type()) { case QEvent::Close: + app->suspendThread(); if (isFullScreen()) { toggleFullscreen(); } + QGuiApplication::processEvents(); + QGuiApplication::sync(); app->stopThread(); if (canvas) canvas->deinit(); diff --git a/qt/src/EmuSettingsWindow.cpp b/qt/src/EmuSettingsWindow.cpp index 69c6c969..67fd4bd8 100644 --- a/qt/src/EmuSettingsWindow.cpp +++ b/qt/src/EmuSettingsWindow.cpp @@ -1,10 +1,11 @@ #include "EmuSettingsWindow.hpp" -#include "src/EmuMainWindow.hpp" +#include "EmuMainWindow.hpp" +#include "EmuConfig.hpp" #include -EmuSettingsWindow::EmuSettingsWindow(QWidget *parent, EmuApplication *app) - : QDialog(parent), app(app) +EmuSettingsWindow::EmuSettingsWindow(QWidget *parent, EmuApplication *app_) + : QDialog(parent), app(app_) { setupUi(this); @@ -35,13 +36,19 @@ EmuSettingsWindow::EmuSettingsWindow(QWidget *parent, EmuApplication *app) stackedWidget->setCurrentIndex(0); - closeButton->connect(closeButton, &QPushButton::clicked, [&](bool) { + connect(closeButton, &QPushButton::clicked, [&](bool) { this->close(); }); - panelList->connect(panelList, &QListWidget::currentItemChanged, [&](QListWidgetItem *prev, QListWidgetItem *cur) { + connect(panelList, &QListWidget::currentItemChanged, [&](QListWidgetItem *prev, QListWidgetItem *cur) { stackedWidget->setCurrentIndex(panelList->currentRow()); }); + + connect(defaultsButton, &QPushButton::clicked, [&](bool) { + app->config->setDefaults(stackedWidget->currentIndex()); + stackedWidget->currentWidget()->hide(); + stackedWidget->currentWidget()->show(); + }); } EmuSettingsWindow::~EmuSettingsWindow() diff --git a/qt/src/EmulationPanel.cpp b/qt/src/EmulationPanel.cpp index 1cf4e4b1..91363bb3 100644 --- a/qt/src/EmulationPanel.cpp +++ b/qt/src/EmulationPanel.cpp @@ -1,4 +1,7 @@ #include "EmulationPanel.hpp" +#include "EmuApplication.hpp" +#include "EmuConfig.hpp" + EmulationPanel::EmulationPanel(EmuApplication *app_) : app(app_) { diff --git a/qt/src/EmulationPanel.hpp b/qt/src/EmulationPanel.hpp index 2286e7cd..ad4721dd 100644 --- a/qt/src/EmulationPanel.hpp +++ b/qt/src/EmulationPanel.hpp @@ -1,6 +1,7 @@ #pragma once #include "ui_EmulationPanel.h" -#include "EmuApplication.hpp" + +class EmuApplication; class EmulationPanel : public Ui::EmulationPanel, diff --git a/qt/src/FoldersPanel.cpp b/qt/src/FoldersPanel.cpp index 0ef79023..1bb092ac 100644 --- a/qt/src/FoldersPanel.cpp +++ b/qt/src/FoldersPanel.cpp @@ -1,4 +1,6 @@ #include "FoldersPanel.hpp" +#include "EmuBinding.hpp" +#include "EmuConfig.hpp" #include #include diff --git a/qt/src/GeneralPanel.cpp b/qt/src/GeneralPanel.cpp index 49899b70..384b6700 100644 --- a/qt/src/GeneralPanel.cpp +++ b/qt/src/GeneralPanel.cpp @@ -1,4 +1,6 @@ #include "GeneralPanel.hpp" +#include "EmuApplication.hpp" +#include "EmuConfig.hpp" GeneralPanel::GeneralPanel(EmuApplication *app_) : app(app_) diff --git a/qt/src/ShaderParametersDialog.cpp b/qt/src/ShaderParametersDialog.cpp index de9128f1..830d056b 100644 --- a/qt/src/ShaderParametersDialog.cpp +++ b/qt/src/ShaderParametersDialog.cpp @@ -145,9 +145,10 @@ void ShaderParametersDialog::save() saved_parameters = *parameters; - auto filename = config->findConfigDir() + "/customized_shader" + extension; - canvas->saveParameters(filename); - config->shader = filename; + QDir dir(config->findConfigDir().c_str()); + auto filename = dir.absoluteFilePath(QString::fromStdString("customized_shader" + extension)); + canvas->saveParameters(filename.toStdString()); + config->shader = QDir::toNativeSeparators(filename).toStdString(); } void ShaderParametersDialog::saveAs() @@ -155,7 +156,7 @@ void ShaderParametersDialog::saveAs() auto folder = config->last_shader_folder; auto filename = QFileDialog::getSaveFileName(this, tr("Save Shader Preset As"), folder.c_str()); canvas->saveParameters(filename.toStdString()); - config->shader = filename.toStdString(); + config->shader = QDir::toNativeSeparators(filename).toStdString(); } void ShaderParametersDialog::refreshWidgets() diff --git a/qt/src/SoundPanel.cpp b/qt/src/SoundPanel.cpp index 9c147a71..74955122 100644 --- a/qt/src/SoundPanel.cpp +++ b/qt/src/SoundPanel.cpp @@ -1,4 +1,6 @@ #include "SoundPanel.hpp" +#include "EmuApplication.hpp" +#include "EmuConfig.hpp" static const int playback_rates[] = { 96000, 48000, 44100 }; diff --git a/qt/src/main.cpp b/qt/src/main.cpp index 00fa71a5..7ee6acf6 100644 --- a/qt/src/main.cpp +++ b/qt/src/main.cpp @@ -1,11 +1,25 @@ #include "EmuApplication.hpp" +#include "EmuConfig.hpp" +#include "EmuMainWindow.hpp" +#include "SDLInputManager.hpp" + +#include +#include +#include #ifndef _WIN32 #include #endif +#ifdef _WIN32 +int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, const char *lpCmdLine, int nShowCmd) +{ + char **argv = nullptr; + int argc = 0; +#else int main(int argc, char *argv[]) { +#endif EmuApplication emu; emu.qtapp = std::make_unique(argc, argv); diff --git a/qt/src/resources/snes9x.ico b/qt/src/resources/snes9x.ico new file mode 100644 index 0000000000000000000000000000000000000000..04f78c14a6b1f4e01e3ef9c2d25a1b5acbb6a2cc GIT binary patch literal 12939 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 literal 0 HcmV?d00001 diff --git a/qt/src/resources/snes9x_icon.rc b/qt/src/resources/snes9x_icon.rc new file mode 100644 index 00000000..dce3d274 --- /dev/null +++ b/qt/src/resources/snes9x_icon.rc @@ -0,0 +1 @@ +IDI_ICON1 ICON "snes9x.ico" diff --git a/vulkan/std_chrono_throttle.cpp b/vulkan/std_chrono_throttle.cpp index c83af954..e6eb1ec1 100644 --- a/vulkan/std_chrono_throttle.cpp +++ b/vulkan/std_chrono_throttle.cpp @@ -22,25 +22,50 @@ microseconds Throttle::remaining() #include void Throttle::wait_for_frame() { - static HANDLE timer = nullptr; + static UINT (WINAPI *NtDelayExecution)(BOOL, LARGE_INTEGER *) = nullptr; + static UINT (WINAPI *NtQueryTimerResolution) (ULONG *, ULONG *, ULONG *) = nullptr; + static UINT (WINAPI *NtSetTimerResolution) (ULONG, BOOL, ULONG *) = nullptr; + static int timer_resolution = 12500; - if (timer == nullptr) - timer = CreateWaitableTimer(nullptr, true, nullptr); + if (NtDelayExecution == nullptr) + { + HMODULE ntdll = ::GetModuleHandleW(L"ntdll.dll"); + + if (ntdll) + { + NtDelayExecution = reinterpret_cast(GetProcAddress(ntdll, "NtDelayExecution")); + NtQueryTimerResolution = reinterpret_cast(GetProcAddress(ntdll, "NtQueryTimerResolution")); + NtSetTimerResolution = reinterpret_cast(GetProcAddress(ntdll, "NtSetTimerResolution")); + } + + if (NtQueryTimerResolution) + { + ULONG min, max, current; + NtQueryTimerResolution(&min, &max, ¤t); + + if (NtSetTimerResolution) + NtSetTimerResolution(max, true, ¤t); + + timer_resolution = current * 5 / 4; + } + } auto time_to_wait = remaining(); - if (time_to_wait < -frame_duration_us) + if (time_to_wait < -(frame_duration_us / 8)) { reset(); return; } - if (time_to_wait.count() > 2000) + if (NtDelayExecution) { - LARGE_INTEGER li; - li.QuadPart = -(time_to_wait.count() - 2000) * 10; - SetWaitableTimer(timer, &li, 0, nullptr, nullptr, false); - WaitForSingleObject(timer, INFINITE); + if (time_to_wait.count() * 10 > timer_resolution) + { + LARGE_INTEGER li; + li.QuadPart = -(time_to_wait.count() * 10 - timer_resolution); + NtDelayExecution(false, &li); + } } time_to_wait = remaining(); @@ -64,7 +89,7 @@ void Throttle::wait_for_frame() } if (time_to_wait.count() > 1000) - std::this_thread::sleep_for(time_to_wait - 1ms); + std::this_thread::sleep_for(time_to_wait - 1000us); time_to_wait = remaining(); while (time_to_wait.count() > 0)