diff --git a/README.md b/README.md index da01833e5..95428dfd0 100644 --- a/README.md +++ b/README.md @@ -102,7 +102,7 @@ PAD DOWN | DOWN | PAD LEFT | LEFT | PAD RIGHT | RIGHT | OPTIONS | RETURN | -TOUCH PAD | SPACE | +BACK BUTTON / TOUCH PAD | SPACE | L1 | Q | R1 | U | L2 | E | diff --git a/src/common/config.cpp b/src/common/config.cpp index 8ac3c694b..a7d01f53b 100644 --- a/src/common/config.cpp +++ b/src/common/config.cpp @@ -41,6 +41,7 @@ static std::string logFilter; static std::string logType = "async"; static std::string userName = "shadPS4"; static std::string updateChannel; +static std::string backButtonBehavior = "left"; static bool useSpecialPad = false; static int specialPadClass = 1; static bool isDebugDump = false; @@ -56,6 +57,8 @@ static bool vkValidationGpu = false; static bool rdocEnable = false; static bool vkMarkers = false; static bool vkCrashDiagnostic = false; +static s16 cursorState = HideCursorState::Idle; +static int cursorHideTimeout = 5; // 5 seconds (default) // Gui std::filesystem::path settings_install_dir = {}; @@ -95,6 +98,14 @@ int getBGMvolume() { return BGMvolume; } +s16 getCursorState() { + return cursorState; +} + +int getCursorHideTimeout() { + return cursorHideTimeout; +} + u32 getScreenWidth() { return screenWidth; } @@ -123,6 +134,10 @@ std::string getUpdateChannel() { return updateChannel; } +std::string getBackButtonBehavior() { + return backButtonBehavior; +} + bool getUseSpecialPad() { return useSpecialPad; } @@ -251,6 +266,14 @@ void setBGMvolume(int volume) { BGMvolume = volume; } +void setCursorState(s16 newCursorState) { + cursorState = newCursorState; +} + +void setCursorHideTimeout(int newcursorHideTimeout) { + cursorHideTimeout = newcursorHideTimeout; +} + void setLanguage(u32 language) { m_language = language; } @@ -275,6 +298,10 @@ void setUpdateChannel(const std::string& type) { updateChannel = type; } +void setBackButtonBehavior(const std::string& type) { + backButtonBehavior = type; +} + void setUseSpecialPad(bool use) { useSpecialPad = use; } @@ -435,11 +462,14 @@ void load(const std::filesystem::path& path) { } isShowSplash = toml::find_or(general, "showSplash", true); isAutoUpdate = toml::find_or(general, "autoUpdate", false); + backButtonBehavior = toml::find_or(general, "backButtonBehavior", "left"); } if (data.contains("Input")) { const toml::value& input = data.at("Input"); + cursorState = toml::find_or(input, "cursorState", HideCursorState::Idle); + cursorHideTimeout = toml::find_or(input, "cursorHideTimeout", 5); useSpecialPad = toml::find_or(input, "useSpecialPad", false); specialPadClass = toml::find_or(input, "specialPadClass", 1); } @@ -533,6 +563,9 @@ void save(const std::filesystem::path& path) { data["General"]["updateChannel"] = updateChannel; data["General"]["showSplash"] = isShowSplash; data["General"]["autoUpdate"] = isAutoUpdate; + data["Input"]["cursorState"] = cursorState; + data["Input"]["cursorHideTimeout"] = cursorHideTimeout; + data["General"]["backButtonBehavior"] = backButtonBehavior; data["Input"]["useSpecialPad"] = useSpecialPad; data["Input"]["specialPadClass"] = specialPadClass; data["GPU"]["screenWidth"] = screenWidth; @@ -581,6 +614,8 @@ void setDefaultValues() { isFullscreen = false; playBGM = false; BGMvolume = 50; + cursorState = HideCursorState::Idle; + cursorHideTimeout = 5; screenWidth = 1280; screenHeight = 720; logFilter = ""; @@ -591,6 +626,7 @@ void setDefaultValues() { } else { updateChannel = "Nightly"; } + backButtonBehavior = "left"; useSpecialPad = false; specialPadClass = 1; isDebugDump = false; diff --git a/src/common/config.h b/src/common/config.h index daee9e078..32cfc605e 100644 --- a/src/common/config.h +++ b/src/common/config.h @@ -8,6 +8,9 @@ #include "types.h" namespace Config { + +enum HideCursorState : s16 { Never, Idle, Always }; + void load(const std::filesystem::path& path); void save(const std::filesystem::path& path); @@ -16,10 +19,14 @@ bool isFullscreenMode(); bool getPlayBGM(); int getBGMvolume(); +s16 getCursorState(); +int getCursorHideTimeout(); + std::string getLogFilter(); std::string getLogType(); std::string getUserName(); std::string getUpdateChannel(); +std::string getBackButtonBehavior(); bool getUseSpecialPad(); int getSpecialPadClass(); @@ -50,10 +57,13 @@ void setScreenHeight(u32 height); void setFullscreenMode(bool enable); void setPlayBGM(bool enable); void setBGMvolume(int volume); +void setCursorState(s16 cursorState); +void setCursorHideTimeout(int newcursorHideTimeout); void setLanguage(u32 language); void setNeoMode(bool enable); void setUserName(const std::string& type); void setUpdateChannel(const std::string& type); +void setBackButtonBehavior(const std::string& type); void setUseSpecialPad(bool use); void setSpecialPadClass(int type); diff --git a/src/core/address_space.cpp b/src/core/address_space.cpp index 48748e4c3..b2cb95a54 100644 --- a/src/core/address_space.cpp +++ b/src/core/address_space.cpp @@ -25,7 +25,7 @@ asm(".zerofill GUEST_SYSTEM,GUEST_SYSTEM,__guest_system,0xFBFC00000"); namespace Core { -static constexpr size_t BackingSize = SCE_KERNEL_MAIN_DMEM_SIZE; +static constexpr size_t BackingSize = SCE_KERNEL_MAIN_DMEM_SIZE_PRO; #ifdef _WIN32 diff --git a/src/core/file_format/psf.cpp b/src/core/file_format/psf.cpp index a5e502f98..0502f29d2 100644 --- a/src/core/file_format/psf.cpp +++ b/src/core/file_format/psf.cpp @@ -227,6 +227,12 @@ void PSF::AddBinary(std::string key, std::vector value, bool update) { map_binaries.emplace(entry_list.size() - 1, std::move(value)); } +void PSF::AddBinary(std::string key, uint64_t value, bool update) { + std::vector data(8); + std::memcpy(data.data(), &value, 8); + return AddBinary(std::move(key), std::move(data), update); +} + void PSF::AddString(std::string key, std::string value, bool update) { auto [it, index] = FindEntry(key); bool exist = it != entry_list.end(); diff --git a/src/core/file_format/psf.h b/src/core/file_format/psf.h index d25b79eec..6f35fa69a 100644 --- a/src/core/file_format/psf.h +++ b/src/core/file_format/psf.h @@ -67,6 +67,7 @@ public: std::optional GetInteger(std::string_view key) const; void AddBinary(std::string key, std::vector value, bool update = false); + void AddBinary(std::string key, uint64_t value, bool update = false); // rsv4 format void AddString(std::string key, std::string value, bool update = false); void AddInteger(std::string key, s32 value, bool update = false); diff --git a/src/core/libraries/kernel/memory_management.h b/src/core/libraries/kernel/memory_management.h index 38898aa57..6e90204cf 100644 --- a/src/core/libraries/kernel/memory_management.h +++ b/src/core/libraries/kernel/memory_management.h @@ -7,6 +7,8 @@ #include "common/types.h" constexpr u64 SCE_KERNEL_MAIN_DMEM_SIZE = 5056_MB; // ~ 5GB +// TODO: Confirm this value on hardware. +constexpr u64 SCE_KERNEL_MAIN_DMEM_SIZE_PRO = 5568_MB; // ~ 5.5GB namespace Libraries::Kernel { diff --git a/src/core/libraries/save_data/save_instance.cpp b/src/core/libraries/save_data/save_instance.cpp index 1127a5452..0d6c5173c 100644 --- a/src/core/libraries/save_data/save_instance.cpp +++ b/src/core/libraries/save_data/save_instance.cpp @@ -12,9 +12,9 @@ #include "core/file_sys/fs.h" #include "save_instance.h" -constexpr u32 OrbisSaveDataBlocksMax = 32768; // 1 GiB +constexpr auto OrbisSaveDataBlocksMin2 = 96; // 3MiB +constexpr auto OrbisSaveDataBlocksMax = 32768; // 1 GiB constexpr std::string_view sce_sys = "sce_sys"; // system folder inside save -constexpr std::string_view max_block_file_name = "max_block.txt"; static Core::FileSys::MntPoints* g_mnt = Common::Singleton::Instance(); @@ -58,18 +58,13 @@ std::filesystem::path SaveInstance::MakeDirSavePath(OrbisUserServiceUserId user_ game_serial / dir_name; } -int SaveInstance::GetMaxBlocks(const std::filesystem::path& save_path) { - Common::FS::IOFile max_blocks_file{save_path / sce_sys / max_block_file_name, - Common::FS::FileAccessMode::Read}; - int max_blocks = 0; - if (max_blocks_file.IsOpen()) { - max_blocks = std::atoi(max_blocks_file.ReadString(16).c_str()); +uint64_t SaveInstance::GetMaxBlockFromSFO(const PSF& psf) { + const auto vec = psf.GetBinary(std::string{SaveParams::SAVEDATA_BLOCKS}); + if (!vec.has_value()) { + return OrbisSaveDataBlocksMax; } - if (max_blocks <= 0) { - max_blocks = OrbisSaveDataBlocksMax; - } - - return max_blocks; + auto value = vec.value(); + return *(uint64_t*)value.data(); } std::filesystem::path SaveInstance::GetParamSFOPath(const std::filesystem::path& dir_path) { @@ -92,13 +87,15 @@ void SaveInstance::SetupDefaultParamSFO(PSF& param_sfo, std::string dir_name, P(String, SaveParams::SAVEDATA_DIRECTORY, std::move(dir_name)); P(Integer, SaveParams::SAVEDATA_LIST_PARAM, 0); P(String, SaveParams::TITLE_ID, std::move(game_serial)); + P(Binary, SaveParams::SAVEDATA_BLOCKS, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); #undef P } SaveInstance::SaveInstance(int slot_num, OrbisUserServiceUserId user_id, std::string _game_serial, std::string_view _dir_name, int max_blocks) : slot_num(slot_num), user_id(user_id), game_serial(std::move(_game_serial)), - dir_name(_dir_name), max_blocks(max_blocks) { + dir_name(_dir_name), + max_blocks(std::clamp(max_blocks, OrbisSaveDataBlocksMin2, OrbisSaveDataBlocksMax)) { ASSERT(slot_num >= 0 && slot_num < 16); save_path = MakeDirSavePath(user_id, game_serial, dir_name); @@ -187,7 +184,7 @@ void SaveInstance::SetupAndMount(bool read_only, bool copy_icon, bool ignore_cor } } - max_blocks = GetMaxBlocks(save_path); + max_blocks = static_cast(GetMaxBlockFromSFO(param_sfo)); g_mnt->Mount(save_path, mount_point, read_only); mounted = true; @@ -217,16 +214,13 @@ void SaveInstance::CreateFiles() { fs::create_directories(sce_sys_dir); SetupDefaultParamSFO(param_sfo, dir_name, game_serial); + param_sfo.AddBinary(std::string{SaveParams::SAVEDATA_BLOCKS}, max_blocks, true); const bool ok = param_sfo.Encode(param_sfo_path); if (!ok) { throw std::filesystem::filesystem_error("Failed to write param.sfo", param_sfo_path, std::make_error_code(std::errc::permission_denied)); } - - Common::FS::IOFile max_block{sce_sys_dir / max_block_file_name, - Common::FS::FileAccessMode::Write}; - max_block.WriteString(std::to_string(max_blocks == 0 ? OrbisSaveDataBlocksMax : max_blocks)); } } // namespace Libraries::SaveData \ No newline at end of file diff --git a/src/core/libraries/save_data/save_instance.h b/src/core/libraries/save_data/save_instance.h index f07011047..3be5c4595 100644 --- a/src/core/libraries/save_data/save_instance.h +++ b/src/core/libraries/save_data/save_instance.h @@ -62,7 +62,7 @@ public: std::string_view game_serial, std::string_view dir_name); - static int GetMaxBlocks(const std::filesystem::path& save_path); + static uint64_t GetMaxBlockFromSFO(const PSF& psf); // Get param.sfo path from a dir_path generated by MakeDirSavePath static std::filesystem::path GetParamSFOPath(const std::filesystem::path& dir_path); diff --git a/src/core/libraries/save_data/savedata.cpp b/src/core/libraries/save_data/savedata.cpp index a2af2f159..93b3c20a9 100644 --- a/src/core/libraries/save_data/savedata.cpp +++ b/src/core/libraries/save_data/savedata.cpp @@ -445,7 +445,7 @@ static Error saveDataMount(const OrbisSaveDataMount2* mount_info, fs::create_directories(root_save); const auto available = fs::space(root_save).available; - auto requested_size = mount_info->blocks * OrbisSaveDataBlockSize; + auto requested_size = save_instance.GetMaxBlocks() * OrbisSaveDataBlockSize; if (requested_size > available) { mount_result->required_blocks = (requested_size - available) / OrbisSaveDataBlockSize; return Error::NO_SPACE_FS; @@ -830,10 +830,11 @@ Error PS4_SYSV_ABI sceSaveDataDirNameSearch(const OrbisSaveDataDirNameSearchCond LOG_ERROR(Lib_SaveData, "Failed to read SFO: {}", fmt::UTF(sfo_path.u8string())); ASSERT_MSG(false, "Failed to read SFO"); } - map_dir_sfo.emplace(dir_name, std::move(sfo)); size_t size = Common::FS::GetDirectorySize(dir_path); - size_t total = SaveInstance::GetMaxBlocks(dir_path); + size_t total = SaveInstance::GetMaxBlockFromSFO(sfo); + + map_dir_sfo.emplace(dir_name, std::move(sfo)); map_free_size.emplace(dir_name, total - size / OrbisSaveDataBlockSize); map_max_blocks.emplace(dir_name, total); } diff --git a/src/core/memory.cpp b/src/core/memory.cpp index d21ebae83..dd63522fc 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -3,6 +3,7 @@ #include "common/alignment.h" #include "common/assert.h" +#include "common/config.h" #include "common/debug.h" #include "core/libraries/error_codes.h" #include "core/libraries/kernel/memory_management.h" @@ -39,8 +40,10 @@ MemoryManager::MemoryManager() { MemoryManager::~MemoryManager() = default; void MemoryManager::SetupMemoryRegions(u64 flexible_size) { + const auto total_size = + Config::isNeoMode() ? SCE_KERNEL_MAIN_DMEM_SIZE_PRO : SCE_KERNEL_MAIN_DMEM_SIZE; total_flexible_size = flexible_size; - total_direct_size = SCE_KERNEL_MAIN_DMEM_SIZE - flexible_size; + total_direct_size = total_size - flexible_size; // Insert an area that covers direct memory physical block. // Note that this should never be called after direct memory allocations have been made. diff --git a/src/imgui/renderer/imgui_impl_sdl3.cpp b/src/imgui/renderer/imgui_impl_sdl3.cpp index cecf504a7..230d396f0 100644 --- a/src/imgui/renderer/imgui_impl_sdl3.cpp +++ b/src/imgui/renderer/imgui_impl_sdl3.cpp @@ -4,6 +4,7 @@ // Based on imgui_impl_sdl3.cpp from Dear ImGui repository #include +#include "common/config.h" #include "imgui_impl_sdl3.h" // SDL @@ -36,6 +37,8 @@ struct SdlData { SDL_Cursor* mouse_cursors[ImGuiMouseCursor_COUNT]{}; SDL_Cursor* mouse_last_cursor{}; int mouse_pending_leave_frame{}; + ImVec2 prev_mouse_pos{0, 0}; + Uint64 lastCursorMoveTime{}; // Gamepad handling ImVector gamepads{}; @@ -371,6 +374,13 @@ bool ProcessEvent(const SDL_Event* event) { ? ImGuiMouseSource_TouchScreen : ImGuiMouseSource_Mouse); io.AddMousePosEvent(mouse_pos.x, mouse_pos.y); + if (mouse_pos.x != bd->prev_mouse_pos.x || mouse_pos.y != bd->prev_mouse_pos.y) { + bd->prev_mouse_pos.x = mouse_pos.x; + bd->prev_mouse_pos.y = mouse_pos.y; + if (Config::getCursorState() == Config::HideCursorState::Idle) { + bd->lastCursorMoveTime = bd->time; + } + } return true; } case SDL_EVENT_MOUSE_WHEEL: { @@ -447,6 +457,7 @@ bool ProcessEvent(const SDL_Event* event) { return false; bd->mouse_window_id = event->window.windowID; bd->mouse_pending_leave_frame = 0; + bd->lastCursorMoveTime = bd->time; return true; } // - In some cases, when detaching a window from main viewport SDL may send @@ -459,6 +470,7 @@ bool ProcessEvent(const SDL_Event* event) { if (GetViewportForWindowId(event->window.windowID) == NULL) return false; bd->mouse_pending_leave_frame = ImGui::GetFrameCount() + 1; + bd->lastCursorMoveTime = bd->time; return true; } case SDL_EVENT_WINDOW_FOCUS_GAINED: @@ -600,7 +612,18 @@ static void UpdateMouseData() { int window_x, window_y; SDL_GetGlobalMouseState(&mouse_x_global, &mouse_y_global); SDL_GetWindowPosition(focused_window, &window_x, &window_y); - io.AddMousePosEvent(mouse_x_global - (float)window_x, mouse_y_global - (float)window_y); + mouse_x_global -= (float)window_x; + mouse_y_global -= (float)window_y; + io.AddMousePosEvent(mouse_x_global, mouse_y_global); + // SDL_EVENT_MOUSE_MOTION isn't triggered before the first frame is rendered + // force update the prev_cursor coords + if (mouse_x_global != bd->prev_mouse_pos.x || mouse_y_global != bd->prev_mouse_pos.y && + bd->prev_mouse_pos.y == 0 && + bd->prev_mouse_pos.x == 0) { + bd->prev_mouse_pos.x = mouse_x_global; + bd->prev_mouse_pos.y = mouse_y_global; + bd->lastCursorMoveTime = bd->time; + } } } } @@ -611,10 +634,25 @@ static void UpdateMouseCursor() { return; SdlData* bd = GetBackendData(); + s16 cursorState = Config::getCursorState(); ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor(); - if (io.MouseDrawCursor || imgui_cursor == ImGuiMouseCursor_None) { + if (io.MouseDrawCursor || imgui_cursor == ImGuiMouseCursor_None || + cursorState == Config::HideCursorState::Always) { // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor SDL_HideCursor(); + + } else if (cursorState == Config::HideCursorState::Idle && + bd->time - bd->lastCursorMoveTime >= + Config::getCursorHideTimeout() * SDL_GetPerformanceFrequency()) { + + bool wasCursorVisible = SDL_CursorVisible(); + SDL_HideCursor(); + + if (wasCursorVisible) { + SDL_WarpMouseInWindow(SDL_GetKeyboardFocus(), bd->prev_mouse_pos.x, + bd->prev_mouse_pos.y); // Force refresh the cursor state + } + } else { // Show OS mouse cursor SDL_Cursor* expected_cursor = bd->mouse_cursors[imgui_cursor] diff --git a/src/qt_gui/check_update.cpp b/src/qt_gui/check_update.cpp index 023c6e7bb..ca6009ca3 100644 --- a/src/qt_gui/check_update.cpp +++ b/src/qt_gui/check_update.cpp @@ -374,11 +374,17 @@ void CheckUpdate::Install() { QString userPath; Common::FS::PathToQString(userPath, Common::FS::GetUserPath(Common::FS::PathType::UserDir)); - QString startingUpdate = tr("Starting Update..."); - QString tempDirPath = userPath + "/temp_download_update"; QString rootPath; Common::FS::PathToQString(rootPath, std::filesystem::current_path()); + QString tempDirPath = userPath + "/temp_download_update"; + QString startingUpdate = tr("Starting Update..."); + + QString binaryStartingUpdate; + for (QChar c : startingUpdate) { + binaryStartingUpdate.append(QString::number(c.unicode(), 2).rightJustified(16, '0')); + } + QString scriptContent; QString scriptFileName; QStringList arguments; @@ -389,7 +395,13 @@ void CheckUpdate::Install() { scriptFileName = tempDirPath + "/update.ps1"; scriptContent = QStringLiteral( "Set-ExecutionPolicy Bypass -Scope Process -Force\n" - "Write-Output '%1'\n" + "$binaryStartingUpdate = '%1'\n" + "$chars = @()\n" + "for ($i = 0; $i -lt $binaryStartingUpdate.Length; $i += 16) {\n" + " $chars += [char]([convert]::ToInt32($binaryStartingUpdate.Substring($i, 16), 2))\n" + "}\n" + "$startingUpdate = -join $chars\n" + "Write-Output $startingUpdate\n" "Expand-Archive -Path '%2\\temp_download_update.zip' -DestinationPath '%2' -Force\n" "Start-Sleep -Seconds 3\n" "Copy-Item -Recurse -Force '%2\\*' '%3\\'\n" @@ -454,6 +466,10 @@ void CheckUpdate::Install() { " sleep 2\n" " extract_file\n" " sleep 2\n" + " if pgrep -f \"Shadps4-qt.AppImage\" > /dev/null; then\n" + " pkill -f \"Shadps4-qt.AppImage\"\n" + " sleep 2\n" + " fi\n" " cp -r \"%2/\"* \"%3/\"\n" " sleep 2\n" " rm \"%3/update.sh\"\n" @@ -508,7 +524,12 @@ void CheckUpdate::Install() { QFile scriptFile(scriptFileName); if (scriptFile.open(QIODevice::WriteOnly | QIODevice::Text)) { QTextStream out(&scriptFile); +#ifdef Q_OS_WIN + out << scriptContent.arg(binaryStartingUpdate).arg(tempDirPath).arg(rootPath); +#endif +#if defined(Q_OS_LINUX) || defined(Q_OS_MAC) out << scriptContent.arg(startingUpdate).arg(tempDirPath).arg(rootPath); +#endif scriptFile.close(); // Make the script executable on Unix-like systems @@ -525,4 +546,4 @@ void CheckUpdate::Install() { this, tr("Error"), QString(tr("Failed to create the update script file") + ":\n" + scriptFileName)); } -} \ No newline at end of file +} diff --git a/src/qt_gui/settings_dialog.cpp b/src/qt_gui/settings_dialog.cpp index 4a42e1961..3845ab0c1 100644 --- a/src/qt_gui/settings_dialog.cpp +++ b/src/qt_gui/settings_dialog.cpp @@ -47,6 +47,8 @@ QStringList languageNames = {"Arabic", const QVector languageIndexes = {21, 23, 14, 6, 18, 1, 12, 22, 2, 4, 25, 24, 29, 5, 0, 9, 15, 16, 17, 7, 26, 8, 11, 20, 3, 13, 27, 10, 19, 28}; +QStringList hideCursorStates = {"Never", "Idle", "Always"}; + SettingsDialog::SettingsDialog(std::span physical_devices, QWidget* parent) : QDialog(parent), ui(new Ui::SettingsDialog) { ui->setupUi(this); @@ -67,6 +69,8 @@ SettingsDialog::SettingsDialog(std::span physical_devices, QWidge completer->setCaseSensitivity(Qt::CaseInsensitive); ui->consoleLanguageComboBox->setCompleter(completer); + ui->hideCursorComboBox->addItems(hideCursorStates); + InitializeEmulatorLanguages(); LoadValuesFromConfig(); @@ -98,6 +102,15 @@ SettingsDialog::SettingsDialog(std::span physical_devices, QWidge ui->buttonBox->button(QDialogButtonBox::RestoreDefaults)->setText(tr("Restore Defaults")); ui->buttonBox->button(QDialogButtonBox::Close)->setText(tr("Close")); + ui->backButtonBehaviorComboBox->addItem(tr("Touchpad Left"), "left"); + ui->backButtonBehaviorComboBox->addItem(tr("Touchpad Center"), "center"); + ui->backButtonBehaviorComboBox->addItem(tr("Touchpad Right"), "right"); + ui->backButtonBehaviorComboBox->addItem(tr("None"), "none"); + + QString currentBackButtonBehavior = QString::fromStdString(Config::getBackButtonBehavior()); + int index = ui->backButtonBehaviorComboBox->findData(currentBackButtonBehavior); + ui->backButtonBehaviorComboBox->setCurrentIndex(index != -1 ? index : 0); + connect(ui->tabWidgetSettings, &QTabWidget::currentChanged, this, [this]() { ui->buttonBox->button(QDialogButtonBox::Close)->setFocus(); }); @@ -151,6 +164,26 @@ SettingsDialog::SettingsDialog(std::span physical_devices, QWidge Config::setBGMvolume(val); BackgroundMusicPlayer::getInstance().setVolume(val); }); + + connect(ui->backButtonBehaviorComboBox, QOverload::of(&QComboBox::currentIndexChanged), + this, [this](int index) { + if (index >= 0 && index < ui->backButtonBehaviorComboBox->count()) { + QString data = ui->backButtonBehaviorComboBox->itemData(index).toString(); + Config::setBackButtonBehavior(data.toStdString()); + } + }); + } + + // Input TAB + { + connect(ui->hideCursorComboBox, QOverload::of(&QComboBox::currentIndexChanged), this, + [this](s16 index) { + Config::setCursorState(index); + OnCursorStateChanged(index); + }); + + connect(ui->idleTimeoutSpinBox, &QSpinBox::valueChanged, this, + [](int index) { Config::setCursorHideTimeout(index); }); } // GPU TAB @@ -204,6 +237,7 @@ SettingsDialog::SettingsDialog(std::span physical_devices, QWidge ui->logFilter->installEventFilter(this); ui->updaterGroupBox->installEventFilter(this); ui->GUIgroupBox->installEventFilter(this); + ui->backButtonBehaviorGroupBox->installEventFilter(this); // Graphics ui->graphicsAdapterGroupBox->installEventFilter(this); @@ -228,6 +262,9 @@ void SettingsDialog::LoadValuesFromConfig() { std::find(languageIndexes.begin(), languageIndexes.end(), Config::GetLanguage())) % languageIndexes.size()); ui->emulatorLanguageComboBox->setCurrentIndex(languages[Config::getEmulatorLanguage()]); + ui->hideCursorComboBox->setCurrentIndex(Config::getCursorState()); + OnCursorStateChanged(Config::getCursorState()); + ui->idleTimeoutSpinBox->setValue(Config::getCursorHideTimeout()); ui->graphicsAdapterBox->setCurrentIndex(Config::getGpuId() + 1); ui->widthSpinBox->setValue(Config::getScreenWidth()); ui->heightSpinBox->setValue(Config::getScreenHeight()); @@ -258,6 +295,10 @@ void SettingsDialog::LoadValuesFromConfig() { } } ui->updateComboBox->setCurrentText(QString::fromStdString(updateChannel)); + + QString backButtonBehavior = QString::fromStdString(Config::getBackButtonBehavior()); + int index = ui->backButtonBehaviorComboBox->findData(backButtonBehavior); + ui->backButtonBehaviorComboBox->setCurrentIndex(index != -1 ? index : 0); } void SettingsDialog::InitializeEmulatorLanguages() { @@ -289,6 +330,18 @@ void SettingsDialog::OnLanguageChanged(int index) { emit LanguageChanged(ui->emulatorLanguageComboBox->itemData(index).toString().toStdString()); } +void SettingsDialog::OnCursorStateChanged(s16 index) { + if (index == -1) + return; + if (index == Config::HideCursorState::Idle) { + ui->idleTimeoutGroupBox->show(); + } else { + if (!ui->idleTimeoutGroupBox->isHidden()) { + ui->idleTimeoutGroupBox->hide(); + } + } +} + int SettingsDialog::exec() { return QDialog::exec(); } @@ -319,6 +372,8 @@ void SettingsDialog::updateNoteTextEdit(const QString& elementName) { text = tr("updaterGroupBox"); } else if (elementName == "GUIgroupBox") { text = tr("GUIgroupBox"); + } else if (elementName == "backButtonBehaviorGroupBox") { + text = tr("backButtonBehaviorGroupBox"); } // Graphics @@ -334,8 +389,6 @@ void SettingsDialog::updateNoteTextEdit(const QString& elementName) { text = tr("dumpShadersCheckBox"); } else if (elementName == "nullGpuCheckBox") { text = tr("nullGpuCheckBox"); - } else if (elementName == "dumpPM4CheckBox") { - text = tr("dumpPM4CheckBox"); } // Debug @@ -352,7 +405,7 @@ void SettingsDialog::updateNoteTextEdit(const QString& elementName) { ui->descriptionText->setText(text.replace("\\n", "\n")); } -bool SettingsDialog::override(QObject* obj, QEvent* event) { +bool SettingsDialog::eventFilter(QObject* obj, QEvent* event) { if (event->type() == QEvent::Enter || event->type() == QEvent::Leave) { if (qobject_cast(obj)) { bool hovered = (event->type() == QEvent::Enter); diff --git a/src/qt_gui/settings_dialog.h b/src/qt_gui/settings_dialog.h index 71307d398..d09617ec3 100644 --- a/src/qt_gui/settings_dialog.h +++ b/src/qt_gui/settings_dialog.h @@ -21,7 +21,7 @@ public: explicit SettingsDialog(std::span physical_devices, QWidget* parent = nullptr); ~SettingsDialog(); - bool override(QObject* obj, QEvent* event); + bool eventFilter(QObject* obj, QEvent* event) override; void updateNoteTextEdit(const QString& groupName); int exec() override; @@ -33,6 +33,7 @@ private: void LoadValuesFromConfig(); void InitializeEmulatorLanguages(); void OnLanguageChanged(int index); + void OnCursorStateChanged(s16 index); std::unique_ptr ui; diff --git a/src/qt_gui/settings_dialog.ui b/src/qt_gui/settings_dialog.ui index 4edec9e1b..b686c3f8b 100644 --- a/src/qt_gui/settings_dialog.ui +++ b/src/qt_gui/settings_dialog.ui @@ -34,9 +34,18 @@ :/images/shadps4.ico:/images/shadps4.ico + + false + + + false + + + true + QFrame::Shape::NoFrame @@ -51,8 +60,8 @@ 0 0 - 836 - 446 + 832 + 431 @@ -62,7 +71,7 @@ - 0 + 1 @@ -369,7 +378,7 @@ 10 30 241 - 71 + 92 @@ -442,17 +451,220 @@ - + + + + + + 0 + 0 + + + + Controller Settings + + + + + 12 + 30 + 241 + 65 + + + + Back Button Behavior + + + + + 12 + 30 + 217 + 28 + + + + + + + + + + + + + + + Input + + + + + + + + + + Cursor + + + + + + Hide Cursor + + + + + + + + + + + + true + + + + 0 + 85 + + + + Hide Cursor Idle Timeout + + + Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop + + + false + + + + 70 + + + 11 + + + + + true + + + + 0 + 0 + + + + + 80 + 30 + + + + + 16777215 + 16777215 + + + + Qt::LayoutDirection::LeftToRight + + + false + + + Qt::AlignmentFlag::AlignCenter + + + QAbstractSpinBox::ButtonSymbols::UpDownArrows + + + + + + 3600 + + + 5 + + + 10 + + + + + + + s + + + + + + + + + + + + + + + + + Qt::Orientation::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Qt::Orientation::Horizontal + + + + 40 + 20 + + + + + + + + + + + + 0 + + + - Qt::Orientation::Horizontal + Qt::Orientation::Vertical - QSizePolicy::Policy::Expanding + QSizePolicy::Policy::MinimumExpanding - 0 - 0 + 20 + 20 diff --git a/src/qt_gui/translations/ar.ts b/src/qt_gui/translations/ar.ts index b385b491b..ca23620bb 100644 --- a/src/qt_gui/translations/ar.ts +++ b/src/qt_gui/translations/ar.ts @@ -474,11 +474,6 @@ Enable NULL GPU تمكين وحدة معالجة الرسومات الفارغة - - - Enable PM4 Dumping - PM4 تمكين تفريغ - Debug @@ -1053,11 +1048,6 @@ nullGpuCheckBox تمكين GPU الافتراضية:\nلأغراض تصحيح الأخطاء التقنية، يقوم بتعطيل عرض اللعبة كما لو لم يكن هناك بطاقة رسومات. - - - dumpPM4CheckBox - تمكين تفريغ PM4:\nلأغراض تصحيح الأخطاء التقنية، يحفظ بيانات تعليمات GPU الأولية في مجلد أثناء معالجتها. - debugDump diff --git a/src/qt_gui/translations/da_DK.ts b/src/qt_gui/translations/da_DK.ts index 73bc37189..0d81e2357 100644 --- a/src/qt_gui/translations/da_DK.ts +++ b/src/qt_gui/translations/da_DK.ts @@ -474,11 +474,6 @@ Enable NULL GPU Enable NULL GPU - - - Enable PM4 Dumping - Enable PM4 Dumping - Debug @@ -1053,11 +1048,6 @@ nullGpuCheckBox Aktiver virtuel GPU:\nTil teknisk fejlfinding deaktiverer det spilvisning, som om der ikke var et grafikkort. - - - dumpPM4CheckBox - Aktiver dumping af PM4:\nTil teknisk fejlfinding gemmer det rå GPU-kommandoer i en mappe under behandling. - debugDump diff --git a/src/qt_gui/translations/de.ts b/src/qt_gui/translations/de.ts index 771d3bf8e..9e31afd6e 100644 --- a/src/qt_gui/translations/de.ts +++ b/src/qt_gui/translations/de.ts @@ -474,11 +474,6 @@ Enable NULL GPU NULL GPU aktivieren - - - Enable PM4 Dumping - PM4-Dumping aktivieren - Debug @@ -1053,11 +1048,6 @@ nullGpuCheckBox Virtuelle GPU aktivieren:\nFür das technische Debugging deaktiviert es die Spielanzeige, als ob keine Grafikkarte vorhanden wäre. - - - dumpPM4CheckBox - PM4-Dumping aktivieren:\nZum technischen Debuggen speichert es rohe GPU-Befehlsdaten in einem Ordner während der Verarbeitung. - debugDump diff --git a/src/qt_gui/translations/el.ts b/src/qt_gui/translations/el.ts index f2265c7d7..de10fc3a8 100644 --- a/src/qt_gui/translations/el.ts +++ b/src/qt_gui/translations/el.ts @@ -474,11 +474,6 @@ Enable NULL GPU Enable NULL GPU - - - Enable PM4 Dumping - Enable PM4 Dumping - Debug @@ -1053,11 +1048,6 @@ nullGpuCheckBox Ενεργοποίηση Εικονικής GPU:\nΓια τεχνικό εντοπισμό σφαλμάτων, απενεργοποιεί την εμφάνιση του παιχνιδιού σαν να μην υπάρχει κάρτα γραφικών. - - - dumpPM4CheckBox - Ενεργοποίηση Καταγραφής PM4:\nΓια τεχνικό εντοπισμό σφαλμάτων, αποθηκεύει τις ακατέργαστες εντολές της GPU σε φάκελο κατά την επεξεργασία. - debugDump diff --git a/src/qt_gui/translations/en.ts b/src/qt_gui/translations/en.ts index e45ac475a..18c54428f 100644 --- a/src/qt_gui/translations/en.ts +++ b/src/qt_gui/translations/en.ts @@ -474,11 +474,6 @@ Enable NULL GPU Enable NULL GPU - - - Enable PM4 Dumping - Enable PM4 Dumping - Debug @@ -539,6 +534,16 @@ Volume Volume + + + Controller Settings + Controller Settings + + + + Back Button Behavior + Back Button Behavior + MainWindow @@ -1028,6 +1033,31 @@ GUIgroupBox Play Title Music:\nIf a game supports it, enable playing special music when selecting the game in the GUI. + + + backButtonBehaviorGroupBox + Back Button Behavior:\nAllows setting which part of the touchpad the back button will emulate a touch on. + + + + Touchpad Left + Touchpad Left + + + + Touchpad Right + Touchpad Right + + + + Touchpad Center + Touchpad Center + + + + None + None + graphicsAdapterGroupBox @@ -1053,11 +1083,6 @@ nullGpuCheckBox Enable Null GPU:\nFor the sake of technical debugging, disables game rendering as if there were no graphics card. - - - dumpPM4CheckBox - Enable PM4 Dumping:\nFor the sake of technical debugging, saves raw GPU instruction data to a folder as the emulator processes it. - debugDump diff --git a/src/qt_gui/translations/es_ES.ts b/src/qt_gui/translations/es_ES.ts index 4242bc91e..86a3e1adc 100644 --- a/src/qt_gui/translations/es_ES.ts +++ b/src/qt_gui/translations/es_ES.ts @@ -474,11 +474,6 @@ Enable NULL GPU Habilitar GPU NULL - - - Enable PM4 Dumping - Habilitar volcado de PM4 - Debug @@ -1053,11 +1048,6 @@ nullGpuCheckBox Habilitar GPU Nula:\nPor el bien de la depuración técnica, desactiva el renderizado del juego como si no hubiera tarjeta gráfica. - - - dumpPM4CheckBox - Habilitar la Volcadura de PM4:\nPor el bien de la depuración técnica, guarda los datos de instrucciones crudas de GPU en una carpeta a medida que el emulador los procesa. - debugDump diff --git a/src/qt_gui/translations/fa_IR.ts b/src/qt_gui/translations/fa_IR.ts index 15e07c886..a613af70b 100644 --- a/src/qt_gui/translations/fa_IR.ts +++ b/src/qt_gui/translations/fa_IR.ts @@ -474,11 +474,6 @@ Enable NULL GPU NULL GPU فعال کردن - - - Enable PM4 Dumping - PM4 Dumping فعال کردن - Debug @@ -1053,11 +1048,6 @@ nullGpuCheckBox Enable Null GPU:\nFor the sake of technical debugging, disables game rendering as if there were no graphics card. - - - dumpPM4CheckBox - Enable PM4 Dumping:\nFor the sake of technical debugging, saves raw GPU instruction data to a folder as the emulator processes it. - debugDump diff --git a/src/qt_gui/translations/fi.ts b/src/qt_gui/translations/fi.ts index a2b319280..e4010b872 100644 --- a/src/qt_gui/translations/fi.ts +++ b/src/qt_gui/translations/fi.ts @@ -474,11 +474,6 @@ Enable NULL GPU Enable NULL GPU - - - Enable PM4 Dumping - Enable PM4 Dumping - Debug @@ -1053,11 +1048,6 @@ nullGpuCheckBox Ota Null GPU käyttöön:\nTeknistä vianetsintää varten pelin renderöinti estetään niin, että ikään kuin grafiikkakorttia ei olisi. - - - dumpPM4CheckBox - Ota PM4 dumpaus käyttöön:\nTeknistä vianetsintää varten raakoja GPU-ohjeita tallennetaan kansioon emulaattorin käsitellessä sitä. - debugDump diff --git a/src/qt_gui/translations/fr.ts b/src/qt_gui/translations/fr.ts index 05c70f195..b11b585c9 100644 --- a/src/qt_gui/translations/fr.ts +++ b/src/qt_gui/translations/fr.ts @@ -474,11 +474,6 @@ Enable NULL GPU NULL GPU - - - Enable PM4 Dumping - Dumper le PM4 - Debug @@ -1053,11 +1048,6 @@ nullGpuCheckBox Activer le GPU nul :\nPour le débogage technique, désactive le rendu du jeu comme s'il n'y avait pas de carte graphique. - - - dumpPM4CheckBox - Activer l'exportation PM4 :\nPour le débogage technique, enregistre les données brutes des instructions GPU dans un dossier pendant que l'émulateur les traite. - debugDump diff --git a/src/qt_gui/translations/hu_HU.ts b/src/qt_gui/translations/hu_HU.ts index fb348ee29..5986193c4 100644 --- a/src/qt_gui/translations/hu_HU.ts +++ b/src/qt_gui/translations/hu_HU.ts @@ -474,11 +474,6 @@ Enable NULL GPU NULL GPU Engedélyezése - - - Enable PM4 Dumping - PM4 Dumpolás Engedélyezése - Debug @@ -1053,11 +1048,6 @@ nullGpuCheckBox Null GPU engedélyezése:\nMűszaki hibaelhárítás céljából letiltja a játék renderelését, mintha nem lenne grafikus kártya. - - - dumpPM4CheckBox - PM4 dumpolás engedélyezése:\nMűszaki hibaelhárítás céljából a nyers GPU utasítási adatokat elmenti egy mappába, ahogy az emulátor feldolgozza őket. - debugDump diff --git a/src/qt_gui/translations/id.ts b/src/qt_gui/translations/id.ts index 86c58c6ce..274029bd0 100644 --- a/src/qt_gui/translations/id.ts +++ b/src/qt_gui/translations/id.ts @@ -474,11 +474,6 @@ Enable NULL GPU Enable NULL GPU - - - Enable PM4 Dumping - Enable PM4 Dumping - Debug @@ -1053,11 +1048,6 @@ nullGpuCheckBox Aktifkan GPU Null:\nUntuk tujuan debugging teknis, menonaktifkan rendering permainan seolah-olah tidak ada kartu grafis. - - - dumpPM4CheckBox - Aktifkan Pembuangan PM4:\nUntuk tujuan debugging teknis, menyimpan data instruksi GPU mentah ke folder saat emulator memprosesnya. - debugDump diff --git a/src/qt_gui/translations/it.ts b/src/qt_gui/translations/it.ts index f5ea9a65c..07976865c 100644 --- a/src/qt_gui/translations/it.ts +++ b/src/qt_gui/translations/it.ts @@ -474,11 +474,6 @@ Enable NULL GPU Abilita NULL GPU - - - Enable PM4 Dumping - Abilita Dump PM4 - Debug @@ -1053,11 +1048,6 @@ nullGpuCheckBox Abilita GPU Null:\nPer scopi di debug tecnico, disabilita il rendering del gioco come se non ci fosse alcuna scheda grafica. - - - dumpPM4CheckBox - Abilita Pompaggio PM4:\nPer scopi di debug tecnico, salva i dati delle istruzioni GPU grezze in una cartella mentre l'emulatore li elabora. - debugDump diff --git a/src/qt_gui/translations/ja_JP.ts b/src/qt_gui/translations/ja_JP.ts index 166100db6..c3444906b 100644 --- a/src/qt_gui/translations/ja_JP.ts +++ b/src/qt_gui/translations/ja_JP.ts @@ -474,11 +474,6 @@ Enable NULL GPU NULL GPUを有効にする - - - Enable PM4 Dumping - PM4ダンプを有効にする - Debug @@ -1053,11 +1048,6 @@ nullGpuCheckBox Null GPUを有効にする:\n技術的なデバッグの目的で、グラフィックスカードがないかのようにゲームのレンダリングを無効にします。 - - - dumpPM4CheckBox - PM4ダンプを有効にする:\n技術的なデバッグの目的で、エミュレーターが処理している間に生のGPU命令データをフォルダーに保存します。 - debugDump diff --git a/src/qt_gui/translations/ko_KR.ts b/src/qt_gui/translations/ko_KR.ts index 93ceb9e35..e816e2f4b 100644 --- a/src/qt_gui/translations/ko_KR.ts +++ b/src/qt_gui/translations/ko_KR.ts @@ -474,11 +474,6 @@ Enable NULL GPU Enable NULL GPU - - - Enable PM4 Dumping - Enable PM4 Dumping - Debug @@ -1053,11 +1048,6 @@ nullGpuCheckBox Enable Null GPU:\nFor the sake of technical debugging, disables game rendering as if there were no graphics card. - - - dumpPM4CheckBox - Enable PM4 Dumping:\nFor the sake of technical debugging, saves raw GPU instruction data to a folder as the emulator processes it. - debugDump diff --git a/src/qt_gui/translations/lt_LT.ts b/src/qt_gui/translations/lt_LT.ts index cac8ebbfc..d5b4ff3ad 100644 --- a/src/qt_gui/translations/lt_LT.ts +++ b/src/qt_gui/translations/lt_LT.ts @@ -474,11 +474,6 @@ Enable NULL GPU Enable NULL GPU - - - Enable PM4 Dumping - Enable PM4 Dumping - Debug @@ -1053,11 +1048,6 @@ nullGpuCheckBox Įjungti tuščią GPU:\nTechninio derinimo tikslais išjungia žaidimo renderiavimą, tarsi nebūtų grafikos plokštės. - - - dumpPM4CheckBox - Įjungti PM4 išmetimą:\nTechninio derinimo tikslais saugo žalius GPU nurodymų duomenis į aplanką, kai emuliatorius juos apdoroja. - debugDump diff --git a/src/qt_gui/translations/nb.ts b/src/qt_gui/translations/nb.ts index e0bc1a550..334600950 100644 --- a/src/qt_gui/translations/nb.ts +++ b/src/qt_gui/translations/nb.ts @@ -474,11 +474,6 @@ Enable NULL GPU Enable NULL GPU - - - Enable PM4 Dumping - Enable PM4 Dumping - Debug @@ -1053,11 +1048,6 @@ nullGpuCheckBox Aktiver Null GPU:\nFor teknisk feilsøking deaktiverer spillrendering som om det ikke var noe grafikkort. - - - dumpPM4CheckBox - Aktiver PM4 dumping:\nFor teknisk feilsøking lagrer rå GPU-instruksjonsdata i en mappe mens emulatoren behandler dem. - debugDump diff --git a/src/qt_gui/translations/nl.ts b/src/qt_gui/translations/nl.ts index 29a60ecc8..6e49d4640 100644 --- a/src/qt_gui/translations/nl.ts +++ b/src/qt_gui/translations/nl.ts @@ -474,11 +474,6 @@ Enable NULL GPU Enable NULL GPU - - - Enable PM4 Dumping - Enable PM4 Dumping - Debug @@ -1053,11 +1048,6 @@ nullGpuCheckBox Null GPU inschakelen:\nVoor technische foutopsporing schakelt de game-rendering uit alsof er geen grafische kaart is. - - - dumpPM4CheckBox - PM4 dumpen inschakelen:\nVoor technische foutopsporing slaat het ruwe GPU-instructiegegevens op in een map terwijl de emulator ze verwerkt. - debugDump diff --git a/src/qt_gui/translations/pl_PL.ts b/src/qt_gui/translations/pl_PL.ts index bd772b0fe..e95b8ba0c 100644 --- a/src/qt_gui/translations/pl_PL.ts +++ b/src/qt_gui/translations/pl_PL.ts @@ -474,11 +474,6 @@ Enable NULL GPU Wyłącz kartę graficzną - - - Enable PM4 Dumping - Włącz zgrywanie PM4 - Debug @@ -1053,11 +1048,6 @@ nullGpuCheckBox Włącz Null GPU:\nDla technicznego debugowania dezaktywuje renderowanie gry tak, jakby nie było karty graficznej. - - - dumpPM4CheckBox - Włącz zrzucanie PM4:\nDla technicznego debugowania zapisuje surowe dane instrukcji GPU w folderze, gdy emulator je przetwarza. - debugDump diff --git a/src/qt_gui/translations/pt_BR.ts b/src/qt_gui/translations/pt_BR.ts index 38836b1d0..e1570b2cd 100644 --- a/src/qt_gui/translations/pt_BR.ts +++ b/src/qt_gui/translations/pt_BR.ts @@ -474,11 +474,6 @@ Enable NULL GPU Ativar GPU NULA - - - Enable PM4 Dumping - Ativar Dumping de PM4 - Debug @@ -1053,11 +1048,6 @@ nullGpuCheckBox Ativar GPU NULA:\nDesativa a renderização do jogo para fins de depuração técnica, como se não houvesse nenhuma placa gráfica. - - - dumpPM4CheckBox - Ativar Dumping de PM4:\nArmazena os dados de instrução bruta da GPU em uma pasta enquanto o emulador os processa, para fins de depuração técnica. Recomendado deixar desativado. - debugDump diff --git a/src/qt_gui/translations/ro_RO.ts b/src/qt_gui/translations/ro_RO.ts index a5c3783bb..e98b7e5c9 100644 --- a/src/qt_gui/translations/ro_RO.ts +++ b/src/qt_gui/translations/ro_RO.ts @@ -474,11 +474,6 @@ Enable NULL GPU Enable NULL GPU - - - Enable PM4 Dumping - Enable PM4 Dumping - Debug @@ -1053,11 +1048,6 @@ nullGpuCheckBox Activează GPU Null:\nÎn scopuri de depanare tehnică, dezactivează redarea jocului ca și cum nu ar exista o placă grafică. - - - dumpPM4CheckBox - Activează salvarea PM4:\nÎn scopuri de depanare tehnică, salvează datele brute ale instrucțiunilor GPU într-un folder pe măsură ce emulatorul le procesează. - debugDump diff --git a/src/qt_gui/translations/ru_RU.ts b/src/qt_gui/translations/ru_RU.ts index 13cc49f20..aaff66ef9 100644 --- a/src/qt_gui/translations/ru_RU.ts +++ b/src/qt_gui/translations/ru_RU.ts @@ -474,11 +474,6 @@ Enable NULL GPU Включить NULL GPU - - - Enable PM4 Dumping - Включить дамп PM4 - Debug @@ -1053,11 +1048,6 @@ nullGpuCheckBox Включить NULL GPU:\nДля технической отладки отключает рендеринг игры так, как будто графической карты нет. - - - dumpPM4CheckBox - Включить дамп PM4:\nДля технической отладки сохраняет необработанные данные инструкций GPU в папку, пока эмулятор их обрабатывает. - debugDump diff --git a/src/qt_gui/translations/sq.ts b/src/qt_gui/translations/sq.ts index c105c5267..dddc694a4 100644 --- a/src/qt_gui/translations/sq.ts +++ b/src/qt_gui/translations/sq.ts @@ -474,11 +474,6 @@ Enable NULL GPU Aktivizo GPU-në NULL - - - Enable PM4 Dumping - Aktivizo Zbrazjen PM4 - Debug @@ -1053,11 +1048,6 @@ nullGpuCheckBox Aktivizo GPU-në Null:\nPër qëllime të korrigjimit teknik, çaktivizon pasqyrimin e lojës sikur nuk ka një kartë grafike. - - - dumpPM4CheckBox - Aktivizo zbrazjen PM4:\nPër qëllime të korrigjimit teknik, ruan të dhënat e instruksioneve të GPU-së në një dosje ndërsa emulatori i përpunon ato. - debugDump diff --git a/src/qt_gui/translations/tr_TR.ts b/src/qt_gui/translations/tr_TR.ts index 32e5c4bd6..5cd71af34 100644 --- a/src/qt_gui/translations/tr_TR.ts +++ b/src/qt_gui/translations/tr_TR.ts @@ -474,11 +474,6 @@ Enable NULL GPU NULL GPU'yu Etkinleştir - - - Enable PM4 Dumping - PM4 Kaydını Etkinleştir - Debug @@ -1053,11 +1048,6 @@ nullGpuCheckBox Null GPU'yu Etkinleştir:\nTeknik hata ayıklama amacıyla, oyunun render edilmesini grafik kartı yokmuş gibi devre dışı bırakır. - - - dumpPM4CheckBox - PM4 Dışa Aktarmayı Etkinleştir:\nTeknik hata ayıklama amacıyla, emülatör bunları işlerken GPU komut verilerini bir klasöre kaydeder. - debugDump diff --git a/src/qt_gui/translations/vi_VN.ts b/src/qt_gui/translations/vi_VN.ts index 8f377f2a7..523683621 100644 --- a/src/qt_gui/translations/vi_VN.ts +++ b/src/qt_gui/translations/vi_VN.ts @@ -474,11 +474,6 @@ Enable NULL GPU Enable NULL GPU - - - Enable PM4 Dumping - Enable PM4 Dumping - Debug @@ -1053,11 +1048,6 @@ nullGpuCheckBox Bật GPU Null:\nĐể mục đích gỡ lỗi kỹ thuật, vô hiệu hóa việc kết xuất trò chơi như thể không có card đồ họa. - - - dumpPM4CheckBox - Bật xuất PM4:\nĐể mục đích gỡ lỗi kỹ thuật, lưu dữ liệu lệnh GPU vào một thư mục khi trình giả lập xử lý chúng. - debugDump diff --git a/src/qt_gui/translations/zh_CN.ts b/src/qt_gui/translations/zh_CN.ts index 0eae5a5bd..f2abc4f4b 100644 --- a/src/qt_gui/translations/zh_CN.ts +++ b/src/qt_gui/translations/zh_CN.ts @@ -474,11 +474,6 @@ Enable NULL GPU 启用 NULL GPU - - - Enable PM4 Dumping - 启用 PM4 转储 - Debug @@ -1053,11 +1048,6 @@ nullGpuCheckBox 启用空 GPU:\n为了技术调试,将游戏渲染禁用,仿佛没有图形卡。 - - - dumpPM4CheckBox - 启用 PM4 转储:\n为了技术调试,在模拟器处理时将原始 GPU 指令数据保存到文件夹中。 - debugDump diff --git a/src/qt_gui/translations/zh_TW.ts b/src/qt_gui/translations/zh_TW.ts index cead22ecf..2d34f8d12 100644 --- a/src/qt_gui/translations/zh_TW.ts +++ b/src/qt_gui/translations/zh_TW.ts @@ -474,11 +474,6 @@ Enable NULL GPU Enable NULL GPU - - - Enable PM4 Dumping - Enable PM4 Dumping - Debug @@ -1053,11 +1048,6 @@ nullGpuCheckBox 啟用空GPU:\n為了技術調試,禁用遊戲渲染,彷彿沒有顯示卡。 - - - dumpPM4CheckBox - 啟用PM4轉儲:\n為了技術調試,將原始GPU指令數據在模擬器處理時保存到文件夾中。 - debugDump diff --git a/src/sdl_window.cpp b/src/sdl_window.cpp index 4a4020a42..bf29b37f6 100644 --- a/src/sdl_window.cpp +++ b/src/sdl_window.cpp @@ -145,6 +145,7 @@ void WindowSDL::onKeyPress(const SDL_Event* event) { Input::Axis axis = Input::Axis::AxisMax; int axisvalue = 0; int ax = 0; + std::string backButtonBehavior = Config::getBackButtonBehavior(); switch (event->key.key) { case SDLK_UP: button = OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_UP; @@ -278,7 +279,15 @@ void WindowSDL::onKeyPress(const SDL_Event* event) { ax = Input::GetAxis(0, 0x80, axisvalue); break; case SDLK_SPACE: - button = OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_TOUCH_PAD; + if (backButtonBehavior != "none") { + float x = backButtonBehavior == "left" ? 0.25f + : (backButtonBehavior == "right" ? 0.75f : 0.5f); + // trigger a touchpad event so that the touchpad emulation for back button works + controller->SetTouchpadState(0, true, x, 0.5f); + button = OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_TOUCH_PAD; + } else { + button = 0; + } break; case SDLK_F11: if (event->type == SDL_EVENT_KEY_DOWN) { @@ -304,9 +313,6 @@ void WindowSDL::onKeyPress(const SDL_Event* event) { if (axis != Input::Axis::AxisMax) { controller->Axis(0, axis, ax); } - if (SDL_GetCursor() != NULL) { - SDL_HideCursor(); - } } void WindowSDL::onGamepadEvent(const SDL_Event* event) { @@ -330,10 +336,20 @@ void WindowSDL::onGamepadEvent(const SDL_Event* event) { case SDL_EVENT_GAMEPAD_BUTTON_UP: button = sdlGamepadToOrbisButton(event->gbutton.button); if (button != 0) { - controller->CheckButton(0, button, event->type == SDL_EVENT_GAMEPAD_BUTTON_DOWN); - } - if (SDL_GetCursor() != NULL) { - SDL_HideCursor(); + if (event->gbutton.button == SDL_GAMEPAD_BUTTON_BACK) { + std::string backButtonBehavior = Config::getBackButtonBehavior(); + if (backButtonBehavior != "none") { + float x = backButtonBehavior == "left" + ? 0.25f + : (backButtonBehavior == "right" ? 0.75f : 0.5f); + // trigger a touchpad event so that the touchpad emulation for back button works + controller->SetTouchpadState(0, true, x, 0.5f); + controller->CheckButton(0, button, + event->type == SDL_EVENT_GAMEPAD_BUTTON_DOWN); + } + } else { + controller->CheckButton(0, button, event->type == SDL_EVENT_GAMEPAD_BUTTON_DOWN); + } } break; case SDL_EVENT_GAMEPAD_AXIS_MOTION: diff --git a/src/shader_recompiler/frontend/format.cpp b/src/shader_recompiler/frontend/format.cpp index 7b3ad00ba..4f0922e2e 100644 --- a/src/shader_recompiler/frontend/format.cpp +++ b/src/shader_recompiler/frontend/format.cpp @@ -3642,8 +3642,8 @@ constexpr std::array InstructionFormatMIMG = {{ {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined, ScalarType::Undefined}, // 95 = IMAGE_GATHER4_C_LZ_O - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined, - ScalarType::Undefined}, + {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, + ScalarType::Float32}, // 96 = IMAGE_GET_LOD {InstClass::VectorMemImgUt, InstCategory::VectorMemory, 4, 1, ScalarType::Float32, ScalarType::Float32}, diff --git a/src/shader_recompiler/frontend/translate/vector_memory.cpp b/src/shader_recompiler/frontend/translate/vector_memory.cpp index 0419f7628..e76ba6d8a 100644 --- a/src/shader_recompiler/frontend/translate/vector_memory.cpp +++ b/src/shader_recompiler/frontend/translate/vector_memory.cpp @@ -147,6 +147,7 @@ void Translator::EmitVectorMemory(const GcnInst& inst) { case Opcode::IMAGE_GATHER4_C_O: case Opcode::IMAGE_GATHER4_C_LZ: case Opcode::IMAGE_GATHER4_LZ_O: + case Opcode::IMAGE_GATHER4_C_LZ_O: return IMAGE_GATHER(inst); // Image misc operations diff --git a/src/video_core/page_manager.cpp b/src/video_core/page_manager.cpp index fb09e70f2..a49fff43a 100644 --- a/src/video_core/page_manager.cpp +++ b/src/video_core/page_manager.cpp @@ -142,6 +142,9 @@ struct PageManager::Impl { } void Protect(VAddr address, size_t size, bool allow_write) { + ASSERT_MSG(owned_ranges.find(address) != owned_ranges.end(), + "Attempted to track non-GPU memory at address {:#x}, size {:#x}.", address, + size); #ifdef _WIN32 DWORD prot = allow_write ? PAGE_READWRITE : PAGE_READONLY; DWORD old_prot{};