Merge branch 'yuzu-emu:master' into new-shortcut

This commit is contained in:
Franco M
2023-10-26 19:11:15 -03:00
committed by GitHub
40 changed files with 11687 additions and 9925 deletions

View File

@ -120,6 +120,8 @@ add_library(common STATIC
socket_types.h
spin_lock.cpp
spin_lock.h
stb.cpp
stb.h
steady_clock.cpp
steady_clock.h
stream.cpp
@ -208,6 +210,8 @@ if (MSVC)
/we4254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data
/we4800 # Implicit conversion from 'type' to bool. Possible information loss
)
else()
set_source_files_properties(stb.cpp PROPERTIES COMPILE_OPTIONS "-Wno-implicit-fallthrough;-Wno-missing-declarations;-Wno-missing-field-initializers")
endif()
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
@ -223,7 +227,7 @@ endif()
create_target_directory_groups(common)
target_link_libraries(common PUBLIC Boost::context Boost::headers fmt::fmt microprofile Threads::Threads)
target_link_libraries(common PUBLIC Boost::context Boost::headers fmt::fmt microprofile stb::headers Threads::Threads)
target_link_libraries(common PRIVATE lz4::lz4 zstd::zstd LLVM::Demangle)
if (ANDROID)

8
src/common/stb.cpp Normal file
View File

@ -0,0 +1,8 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#define STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_RESIZE_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "common/stb.h"

8
src/common/stb.h Normal file
View File

@ -0,0 +1,8 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <stb_image.h>
#include <stb_image_resize.h>
#include <stb_image_write.h>

View File

@ -11,6 +11,7 @@
#include <mach/mach.h>
#elif defined(_WIN32)
#include <windows.h>
#include "common/string_util.h"
#else
#if defined(__Bitrig__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__)
#include <pthread_np.h>
@ -82,29 +83,8 @@ void SetCurrentThreadPriority(ThreadPriority new_priority) {
#ifdef _MSC_VER
// Sets the debugger-visible name of the current thread.
// Uses trick documented in:
// https://docs.microsoft.com/en-us/visualstudio/debugger/how-to-set-a-thread-name-in-native-code
void SetCurrentThreadName(const char* name) {
static const DWORD MS_VC_EXCEPTION = 0x406D1388;
#pragma pack(push, 8)
struct THREADNAME_INFO {
DWORD dwType; // must be 0x1000
LPCSTR szName; // pointer to name (in user addr space)
DWORD dwThreadID; // thread ID (-1=caller thread)
DWORD dwFlags; // reserved for future use, must be zero
} info;
#pragma pack(pop)
info.dwType = 0x1000;
info.szName = name;
info.dwThreadID = std::numeric_limits<DWORD>::max();
info.dwFlags = 0;
__try {
RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info);
} __except (EXCEPTION_CONTINUE_EXECUTION) {
}
SetThreadDescription(GetCurrentThread(), UTF8ToUTF16W(name).data());
}
#else // !MSVC_VER, so must be POSIX threads

View File

@ -1,6 +1,7 @@
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/logging/log.h"
#include "core/file_sys/system_archive/system_version.h"
#include "core/file_sys/vfs_vector.h"
#include "core/hle/api_version.h"
@ -12,6 +13,9 @@ std::string GetLongDisplayVersion() {
}
VirtualDir SystemVersion() {
LOG_WARNING(Common_Filesystem, "called - Using hardcoded firmware version '{}'",
GetLongDisplayVersion());
VirtualFile file = std::make_shared<VectorVfsFile>(std::vector<u8>(0x100), "file");
file->WriteObject(HLE::ApiVersion::HOS_VERSION_MAJOR, 0);
file->WriteObject(HLE::ApiVersion::HOS_VERSION_MINOR, 1);

View File

@ -25,11 +25,12 @@ void LoopProcess(Core::System& system) {
server_manager->RegisterNamedService(
"caps:u", std::make_shared<IAlbumApplicationService>(system, album_manager));
server_manager->RegisterNamedService("caps:ss", std::make_shared<IScreenShotService>(system));
server_manager->RegisterNamedService(
"caps:ss", std::make_shared<IScreenShotService>(system, album_manager));
server_manager->RegisterNamedService("caps:sc",
std::make_shared<IScreenShotControlService>(system));
server_manager->RegisterNamedService("caps:su",
std::make_shared<IScreenShotApplicationService>(system));
server_manager->RegisterNamedService(
"caps:su", std::make_shared<IScreenShotApplicationService>(system, album_manager));
ServerManager::RunServer(std::move(server_manager));
}

View File

@ -2,12 +2,11 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include <sstream>
#include <stb_image.h>
#include <stb_image_resize.h>
#include "common/fs/file.h"
#include "common/fs/path_util.h"
#include "common/logging/log.h"
#include "common/stb.h"
#include "core/core.h"
#include "core/hle/service/caps/caps_manager.h"
#include "core/hle/service/caps/caps_result.h"
@ -227,6 +226,49 @@ Result AlbumManager::LoadAlbumScreenShotThumbnail(
+static_cast<int>(out_image_output.height), decoder_options.flags);
}
Result AlbumManager::SaveScreenShot(ApplicationAlbumEntry& out_entry,
const ScreenShotAttribute& attribute,
std::span<const u8> image_data, u64 aruid) {
return SaveScreenShot(out_entry, attribute, {}, image_data, aruid);
}
Result AlbumManager::SaveScreenShot(ApplicationAlbumEntry& out_entry,
const ScreenShotAttribute& attribute,
const ApplicationData& app_data, std::span<const u8> image_data,
u64 aruid) {
const u64 title_id = system.GetApplicationProcessProgramID();
const auto& user_clock = system.GetTimeManager().GetStandardUserSystemClockCore();
s64 posix_time{};
Result result = user_clock.GetCurrentTime(system, posix_time);
if (result.IsError()) {
return result;
}
const auto date = ConvertToAlbumDateTime(posix_time);
return SaveImage(out_entry, image_data, title_id, date);
}
Result AlbumManager::SaveEditedScreenShot(ApplicationAlbumEntry& out_entry,
const ScreenShotAttribute& attribute,
const AlbumFileId& file_id,
std::span<const u8> image_data) {
const auto& user_clock = system.GetTimeManager().GetStandardUserSystemClockCore();
s64 posix_time{};
Result result = user_clock.GetCurrentTime(system, posix_time);
if (result.IsError()) {
return result;
}
const auto date = ConvertToAlbumDateTime(posix_time);
return SaveImage(out_entry, image_data, file_id.application_id, date);
}
Result AlbumManager::GetFile(std::filesystem::path& out_path, const AlbumFileId& file_id) const {
const auto file = album_files.find(file_id);
@ -365,6 +407,47 @@ Result AlbumManager::LoadImage(std::span<u8> out_image, const std::filesystem::p
return ResultSuccess;
}
static void PNGToMemory(void* context, void* png, int len) {
std::vector<u8>* png_image = static_cast<std::vector<u8>*>(context);
png_image->reserve(len);
std::memcpy(png_image->data(), png, len);
}
Result AlbumManager::SaveImage(ApplicationAlbumEntry& out_entry, std::span<const u8> image,
u64 title_id, const AlbumFileDateTime& date) const {
const auto screenshot_path =
Common::FS::GetYuzuPathString(Common::FS::YuzuPath::ScreenshotsDir);
const std::string formatted_date =
fmt::format("{:04}-{:02}-{:02}_{:02}-{:02}-{:02}-{:03}", date.year, date.month, date.day,
date.hour, date.minute, date.second, 0);
const std::string file_path =
fmt::format("{}/{:016x}_{}.png", screenshot_path, title_id, formatted_date);
const Common::FS::IOFile db_file{file_path, Common::FS::FileAccessMode::Write,
Common::FS::FileType::BinaryFile};
std::vector<u8> png_image;
if (!stbi_write_png_to_func(PNGToMemory, &png_image, 1280, 720, STBI_rgb_alpha, image.data(),
0)) {
return ResultFileCountLimit;
}
if (db_file.Write(png_image) != png_image.size()) {
return ResultFileCountLimit;
}
out_entry = {
.size = png_image.size(),
.hash = {},
.datetime = date,
.storage = AlbumStorage::Sd,
.content = ContentType::Screenshot,
.unknown = 1,
};
return ResultSuccess;
}
AlbumFileDateTime AlbumManager::ConvertToAlbumDateTime(u64 posix_time) const {
Time::TimeZone::CalendarInfo calendar_date{};
const auto& time_zone_manager =

View File

@ -58,6 +58,15 @@ public:
std::vector<u8>& out_image, const AlbumFileId& file_id,
const ScreenShotDecodeOption& decoder_options) const;
Result SaveScreenShot(ApplicationAlbumEntry& out_entry, const ScreenShotAttribute& attribute,
std::span<const u8> image_data, u64 aruid);
Result SaveScreenShot(ApplicationAlbumEntry& out_entry, const ScreenShotAttribute& attribute,
const ApplicationData& app_data, std::span<const u8> image_data,
u64 aruid);
Result SaveEditedScreenShot(ApplicationAlbumEntry& out_entry,
const ScreenShotAttribute& attribute, const AlbumFileId& file_id,
std::span<const u8> image_data);
private:
static constexpr std::size_t NandAlbumFileLimit = 1000;
static constexpr std::size_t SdAlbumFileLimit = 10000;
@ -67,6 +76,8 @@ private:
Result GetAlbumEntry(AlbumEntry& out_entry, const std::filesystem::path& path) const;
Result LoadImage(std::span<u8> out_image, const std::filesystem::path& path, int width,
int height, ScreenShotDecoderFlag flag) const;
Result SaveImage(ApplicationAlbumEntry& out_entry, std::span<const u8> image, u64 title_id,
const AlbumFileDateTime& date) const;
AlbumFileDateTime ConvertToAlbumDateTime(u64 posix_time) const;

View File

@ -1,19 +1,25 @@
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/logging/log.h"
#include "core/hle/service/caps/caps_manager.h"
#include "core/hle/service/caps/caps_types.h"
#include "core/hle/service/ipc_helpers.h"
#include "core/hle/service/caps/caps_ss.h"
namespace Service::Capture {
IScreenShotService::IScreenShotService(Core::System& system_)
: ServiceFramework{system_, "caps:ss"} {
IScreenShotService::IScreenShotService(Core::System& system_,
std::shared_ptr<AlbumManager> album_manager)
: ServiceFramework{system_, "caps:ss"}, manager{album_manager} {
// clang-format off
static const FunctionInfo functions[] = {
{201, nullptr, "SaveScreenShot"},
{202, nullptr, "SaveEditedScreenShot"},
{203, nullptr, "SaveScreenShotEx0"},
{203, &IScreenShotService::SaveScreenShotEx0, "SaveScreenShotEx0"},
{204, nullptr, "SaveEditedScreenShotEx0"},
{206, nullptr, "Unknown206"},
{206, &IScreenShotService::SaveEditedScreenShotEx1, "SaveEditedScreenShotEx1"},
{208, nullptr, "SaveScreenShotOfMovieEx1"},
{1000, nullptr, "Unknown1000"},
};
@ -24,4 +30,65 @@ IScreenShotService::IScreenShotService(Core::System& system_)
IScreenShotService::~IScreenShotService() = default;
void IScreenShotService::SaveScreenShotEx0(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
struct Parameters {
ScreenShotAttribute attribute{};
u32 report_option{};
INSERT_PADDING_BYTES(0x4);
u64 applet_resource_user_id{};
};
static_assert(sizeof(Parameters) == 0x50, "Parameters has incorrect size.");
const auto parameters{rp.PopRaw<Parameters>()};
const auto image_data_buffer = ctx.ReadBuffer();
LOG_INFO(Service_Capture,
"called, report_option={}, image_data_buffer_size={}, applet_resource_user_id={}",
parameters.report_option, image_data_buffer.size(),
parameters.applet_resource_user_id);
ApplicationAlbumEntry entry{};
const auto result = manager->SaveScreenShot(entry, parameters.attribute, image_data_buffer,
parameters.applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 10};
rb.Push(result);
rb.PushRaw(entry);
}
void IScreenShotService::SaveEditedScreenShotEx1(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
struct Parameters {
ScreenShotAttribute attribute;
u64 width;
u64 height;
u64 thumbnail_width;
u64 thumbnail_height;
AlbumFileId file_id;
};
static_assert(sizeof(Parameters) == 0x78, "Parameters has incorrect size.");
const auto parameters{rp.PopRaw<Parameters>()};
const auto application_data_buffer = ctx.ReadBuffer(0);
const auto image_data_buffer = ctx.ReadBuffer(1);
const auto thumbnail_image_data_buffer = ctx.ReadBuffer(2);
LOG_INFO(Service_Capture,
"called, width={}, height={}, thumbnail_width={}, thumbnail_height={}, "
"application_id={:016x}, storage={}, type={}, app_data_buffer_size={}, "
"image_data_buffer_size={}, thumbnail_image_buffer_size={}",
parameters.width, parameters.height, parameters.thumbnail_width,
parameters.thumbnail_height, parameters.file_id.application_id,
parameters.file_id.storage, parameters.file_id.type, application_data_buffer.size(),
image_data_buffer.size(), thumbnail_image_data_buffer.size());
ApplicationAlbumEntry entry{};
const auto result = manager->SaveEditedScreenShot(entry, parameters.attribute,
parameters.file_id, image_data_buffer);
IPC::ResponseBuilder rb{ctx, 10};
rb.Push(result);
rb.PushRaw(entry);
}
} // namespace Service::Capture

View File

@ -13,8 +13,14 @@ namespace Service::Capture {
class IScreenShotService final : public ServiceFramework<IScreenShotService> {
public:
explicit IScreenShotService(Core::System& system_);
explicit IScreenShotService(Core::System& system_, std::shared_ptr<AlbumManager> album_manager);
~IScreenShotService() override;
private:
void SaveScreenShotEx0(HLERequestContext& ctx);
void SaveEditedScreenShotEx1(HLERequestContext& ctx);
std::shared_ptr<AlbumManager> manager;
};
} // namespace Service::Capture

View File

@ -2,19 +2,22 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/logging/log.h"
#include "core/hle/service/caps/caps_manager.h"
#include "core/hle/service/caps/caps_su.h"
#include "core/hle/service/caps/caps_types.h"
#include "core/hle/service/ipc_helpers.h"
namespace Service::Capture {
IScreenShotApplicationService::IScreenShotApplicationService(Core::System& system_)
: ServiceFramework{system_, "caps:su"} {
IScreenShotApplicationService::IScreenShotApplicationService(
Core::System& system_, std::shared_ptr<AlbumManager> album_manager)
: ServiceFramework{system_, "caps:su"}, manager{album_manager} {
// clang-format off
static const FunctionInfo functions[] = {
{32, &IScreenShotApplicationService::SetShimLibraryVersion, "SetShimLibraryVersion"},
{201, nullptr, "SaveScreenShot"},
{203, nullptr, "SaveScreenShotEx0"},
{205, nullptr, "SaveScreenShotEx1"},
{203, &IScreenShotApplicationService::SaveScreenShotEx0, "SaveScreenShotEx0"},
{205, &IScreenShotApplicationService::SaveScreenShotEx1, "SaveScreenShotEx1"},
{210, nullptr, "SaveScreenShotEx2"},
};
// clang-format on
@ -36,4 +39,62 @@ void IScreenShotApplicationService::SetShimLibraryVersion(HLERequestContext& ctx
rb.Push(ResultSuccess);
}
void IScreenShotApplicationService::SaveScreenShotEx0(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
struct Parameters {
ScreenShotAttribute attribute{};
AlbumReportOption report_option{};
INSERT_PADDING_BYTES(0x4);
u64 applet_resource_user_id{};
};
static_assert(sizeof(Parameters) == 0x50, "Parameters has incorrect size.");
const auto parameters{rp.PopRaw<Parameters>()};
const auto image_data_buffer = ctx.ReadBuffer();
LOG_INFO(Service_Capture,
"called, report_option={}, image_data_buffer_size={}, applet_resource_user_id={}",
parameters.report_option, image_data_buffer.size(),
parameters.applet_resource_user_id);
ApplicationAlbumEntry entry{};
const auto result = manager->SaveScreenShot(entry, parameters.attribute, image_data_buffer,
parameters.applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 10};
rb.Push(result);
rb.PushRaw(entry);
}
void IScreenShotApplicationService::SaveScreenShotEx1(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
struct Parameters {
ScreenShotAttribute attribute{};
AlbumReportOption report_option{};
INSERT_PADDING_BYTES(0x4);
u64 applet_resource_user_id{};
};
static_assert(sizeof(Parameters) == 0x50, "Parameters has incorrect size.");
const auto parameters{rp.PopRaw<Parameters>()};
const auto app_data_buffer = ctx.ReadBuffer(0);
const auto image_data_buffer = ctx.ReadBuffer(1);
LOG_INFO(Service_Capture,
"called, report_option={}, image_data_buffer_size={}, applet_resource_user_id={}",
parameters.report_option, image_data_buffer.size(),
parameters.applet_resource_user_id);
ApplicationAlbumEntry entry{};
ApplicationData app_data{};
std::memcpy(&app_data, app_data_buffer.data(), sizeof(ApplicationData));
const auto result =
manager->SaveScreenShot(entry, parameters.attribute, app_data, image_data_buffer,
parameters.applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 10};
rb.Push(result);
rb.PushRaw(entry);
}
} // namespace Service::Capture

View File

@ -10,14 +10,20 @@ class System;
}
namespace Service::Capture {
class AlbumManager;
class IScreenShotApplicationService final : public ServiceFramework<IScreenShotApplicationService> {
public:
explicit IScreenShotApplicationService(Core::System& system_);
explicit IScreenShotApplicationService(Core::System& system_,
std::shared_ptr<AlbumManager> album_manager);
~IScreenShotApplicationService() override;
private:
void SetShimLibraryVersion(HLERequestContext& ctx);
void SaveScreenShotEx0(HLERequestContext& ctx);
void SaveScreenShotEx1(HLERequestContext& ctx);
std::shared_ptr<AlbumManager> manager;
};
} // namespace Service::Capture

View File

@ -20,6 +20,8 @@ enum class AlbumImageOrientation {
enum class AlbumReportOption : s32 {
Disable,
Enable,
Unknown2,
Unknown3,
};
enum class ContentType : u8 {

View File

@ -27,10 +27,12 @@ namespace {
static thread_local std::array read_buffer_data_a{
Common::ScratchBuffer<u8>(),
Common::ScratchBuffer<u8>(),
Common::ScratchBuffer<u8>(),
};
static thread_local std::array read_buffer_data_x{
Common::ScratchBuffer<u8>(),
Common::ScratchBuffer<u8>(),
Common::ScratchBuffer<u8>(),
};
} // Anonymous namespace
@ -343,6 +345,7 @@ std::span<const u8> HLERequestContext::ReadBufferA(std::size_t buffer_index) con
static thread_local std::array read_buffer_a{
Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead>(memory, 0, 0),
Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead>(memory, 0, 0),
Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead>(memory, 0, 0),
};
ASSERT_OR_EXECUTE_MSG(
@ -358,6 +361,7 @@ std::span<const u8> HLERequestContext::ReadBufferX(std::size_t buffer_index) con
static thread_local std::array read_buffer_x{
Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead>(memory, 0, 0),
Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead>(memory, 0, 0),
Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead>(memory, 0, 0),
};
ASSERT_OR_EXECUTE_MSG(
@ -373,10 +377,12 @@ std::span<const u8> HLERequestContext::ReadBuffer(std::size_t buffer_index) cons
static thread_local std::array read_buffer_a{
Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead>(memory, 0, 0),
Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead>(memory, 0, 0),
Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead>(memory, 0, 0),
};
static thread_local std::array read_buffer_x{
Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead>(memory, 0, 0),
Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead>(memory, 0, 0),
Core::Memory::CpuGuestMemory<u8, Core::Memory::GuestMemoryFlags::SafeRead>(memory, 0, 0),
};
const bool is_buffer_a{BufferDescriptorA().size() > buffer_index &&

View File

@ -9,6 +9,35 @@
namespace Service::PTM {
enum class Location : u8 {
Internal,
External,
};
class ISession : public ServiceFramework<ISession> {
public:
explicit ISession(Core::System& system_) : ServiceFramework{system_, "ISession"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "GetTemperatureRange"},
{2, nullptr, "SetMeasurementMode"},
{4, &ISession::GetTemperature, "GetTemperature"},
};
// clang-format on
RegisterHandlers(functions);
}
private:
void GetTemperature(HLERequestContext& ctx) {
constexpr f32 temperature = 35;
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(temperature);
}
};
TS::TS(Core::System& system_) : ServiceFramework{system_, "ts"} {
// clang-format off
static const FunctionInfo functions[] = {
@ -16,7 +45,7 @@ TS::TS(Core::System& system_) : ServiceFramework{system_, "ts"} {
{1, &TS::GetTemperature, "GetTemperature"},
{2, nullptr, "SetMeasurementMode"},
{3, &TS::GetTemperatureMilliC, "GetTemperatureMilliC"},
{4, nullptr, "OpenSession"},
{4, &TS::OpenSession, "OpenSession"},
};
// clang-format on
@ -47,4 +76,13 @@ void TS::GetTemperatureMilliC(HLERequestContext& ctx) {
rb.Push(temperature);
}
void TS::OpenSession(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
[[maybe_unused]] const u32 device_code = rp.Pop<u32>();
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<ISession>(system);
}
} // namespace Service::PTM

View File

@ -14,13 +14,9 @@ public:
~TS() override;
private:
enum class Location : u8 {
Internal,
External,
};
void GetTemperature(HLERequestContext& ctx);
void GetTemperatureMilliC(HLERequestContext& ctx);
void OpenSession(HLERequestContext& ctx);
};
} // namespace Service::PTM

View File

@ -5,8 +5,13 @@
#include "common/logging/log.h"
#include "common/settings.h"
#include "common/string_util.h"
#include "core/core.h"
#include "core/file_sys/content_archive.h"
#include "core/file_sys/errors.h"
#include "core/file_sys/system_archive/system_version.h"
#include "core/file_sys/nca_metadata.h"
#include "core/file_sys/registered_cache.h"
#include "core/file_sys/romfs.h"
#include "core/file_sys/system_archive/system_archive.h"
#include "core/hle/service/filesystem/filesystem.h"
#include "core/hle/service/ipc_helpers.h"
#include "core/hle/service/set/set.h"
@ -22,18 +27,30 @@ enum class GetFirmwareVersionType {
Version2,
};
void GetFirmwareVersionImpl(HLERequestContext& ctx, GetFirmwareVersionType type) {
LOG_WARNING(Service_SET, "called - Using hardcoded firmware version '{}'",
FileSys::SystemArchive::GetLongDisplayVersion());
void GetFirmwareVersionImpl(Core::System& system, HLERequestContext& ctx,
GetFirmwareVersionType type) {
ASSERT_MSG(ctx.GetWriteBufferSize() == 0x100,
"FirmwareVersion output buffer must be 0x100 bytes in size!");
// Instead of using the normal procedure of checking for the real system archive and if it
// doesn't exist, synthesizing one, I feel that that would lead to strange bugs because a
// used is using a really old or really new SystemVersion title. The synthesized one ensures
// consistence (currently reports as 5.1.0-0.0)
const auto archive = FileSys::SystemArchive::SystemVersion();
constexpr u64 FirmwareVersionSystemDataId = 0x0100000000000809;
auto& fsc = system.GetFileSystemController();
// Attempt to load version data from disk
const FileSys::RegisteredCache* bis_system{};
std::unique_ptr<FileSys::NCA> nca{};
FileSys::VirtualDir romfs{};
bis_system = fsc.GetSystemNANDContents();
if (bis_system) {
nca = bis_system->GetEntry(FirmwareVersionSystemDataId, FileSys::ContentRecordType::Data);
}
if (nca) {
romfs = FileSys::ExtractRomFS(nca->GetRomFS());
}
if (!romfs) {
romfs = FileSys::ExtractRomFS(
FileSys::SystemArchive::SynthesizeSystemArchive(FirmwareVersionSystemDataId));
}
const auto early_exit_failure = [&ctx](std::string_view desc, Result code) {
LOG_ERROR(Service_SET, "General failure while attempting to resolve firmware version ({}).",
@ -42,13 +59,7 @@ void GetFirmwareVersionImpl(HLERequestContext& ctx, GetFirmwareVersionType type)
rb.Push(code);
};
if (archive == nullptr) {
early_exit_failure("The system version archive couldn't be synthesized.",
FileSys::ERROR_FAILED_MOUNT_ARCHIVE);
return;
}
const auto ver_file = archive->GetFile("file");
const auto ver_file = romfs->GetFile("file");
if (ver_file == nullptr) {
early_exit_failure("The system version archive didn't contain the file 'file'.",
FileSys::ERROR_INVALID_ARGUMENT);
@ -87,12 +98,12 @@ void SET_SYS::SetLanguageCode(HLERequestContext& ctx) {
void SET_SYS::GetFirmwareVersion(HLERequestContext& ctx) {
LOG_DEBUG(Service_SET, "called");
GetFirmwareVersionImpl(ctx, GetFirmwareVersionType::Version1);
GetFirmwareVersionImpl(system, ctx, GetFirmwareVersionType::Version1);
}
void SET_SYS::GetFirmwareVersion2(HLERequestContext& ctx) {
LOG_DEBUG(Service_SET, "called");
GetFirmwareVersionImpl(ctx, GetFirmwareVersionType::Version2);
GetFirmwareVersionImpl(system, ctx, GetFirmwareVersionType::Version2);
}
void SET_SYS::GetAccountSettings(HLERequestContext& ctx) {

View File

@ -19,16 +19,23 @@ namespace Core::Memory {
namespace {
constexpr auto CHEAT_ENGINE_NS = std::chrono::nanoseconds{1000000000 / 12};
std::string_view ExtractName(std::string_view data, std::size_t start_index, char match) {
std::string_view ExtractName(std::size_t& out_name_size, std::string_view data,
std::size_t start_index, char match) {
auto end_index = start_index;
while (data[end_index] != match) {
++end_index;
if (end_index > data.size() ||
(end_index - start_index - 1) > sizeof(CheatDefinition::readable_name)) {
if (end_index > data.size()) {
return {};
}
}
out_name_size = end_index - start_index;
// Clamp name if it's too big
if (out_name_size > sizeof(CheatDefinition::readable_name)) {
end_index = start_index + sizeof(CheatDefinition::readable_name);
}
return data.substr(start_index, end_index - start_index);
}
} // Anonymous namespace
@ -113,7 +120,8 @@ std::vector<CheatEntry> TextCheatParser::Parse(std::string_view data) const {
return {};
}
const auto name = ExtractName(data, i + 1, '}');
std::size_t name_size{};
const auto name = ExtractName(name_size, data, i + 1, '}');
if (name.empty()) {
return {};
}
@ -125,12 +133,13 @@ std::vector<CheatEntry> TextCheatParser::Parse(std::string_view data) const {
.definition.readable_name[out[*current_entry].definition.readable_name.size() - 1] =
'\0';
i += name.length() + 1;
i += name_size + 1;
} else if (data[i] == '[') {
current_entry = out.size();
out.emplace_back();
const auto name = ExtractName(data, i + 1, ']');
std::size_t name_size{};
const auto name = ExtractName(name_size, data, i + 1, ']');
if (name.empty()) {
return {};
}
@ -142,7 +151,7 @@ std::vector<CheatEntry> TextCheatParser::Parse(std::string_view data) const {
.definition.readable_name[out[*current_entry].definition.readable_name.size() - 1] =
'\0';
i += name.length() + 1;
i += name_size + 1;
} else if (::isxdigit(data[i])) {
if (!current_entry || out[*current_entry].definition.num_opcodes >=
out[*current_entry].definition.opcodes.size()) {

View File

@ -242,6 +242,7 @@ std::string EmitGLSL(const Profile& profile, const RuntimeInfo& runtime_info, IR
}
if (program.info.uses_subgroup_shuffles) {
ctx.header += "bool shfl_in_bounds;";
ctx.header += "uint shfl_result;";
}
ctx.code.insert(0, ctx.header);
ctx.code += '}';

View File

@ -141,7 +141,8 @@ void EmitShuffleIndex(EmitContext& ctx, IR::Inst& inst, std::string_view value,
const auto src_thread_id{fmt::format("({})|({})", lhs, min_thread_id)};
ctx.Add("shfl_in_bounds=int({})<=int({});", src_thread_id, max_thread_id);
SetInBoundsFlag(ctx, inst);
ctx.AddU32("{}=shfl_in_bounds?readInvocationARB({},{}):{};", inst, value, src_thread_id, value);
ctx.Add("shfl_result=readInvocationARB({},{});", value, src_thread_id);
ctx.AddU32("{}=shfl_in_bounds?shfl_result:{};", inst, value);
}
void EmitShuffleUp(EmitContext& ctx, IR::Inst& inst, std::string_view value, std::string_view index,
@ -158,7 +159,8 @@ void EmitShuffleUp(EmitContext& ctx, IR::Inst& inst, std::string_view value, std
const auto src_thread_id{fmt::format("({}-{})", THREAD_ID, index)};
ctx.Add("shfl_in_bounds=int({})>=int({});", src_thread_id, max_thread_id);
SetInBoundsFlag(ctx, inst);
ctx.AddU32("{}=shfl_in_bounds?readInvocationARB({},{}):{};", inst, value, src_thread_id, value);
ctx.Add("shfl_result=readInvocationARB({},{});", value, src_thread_id);
ctx.AddU32("{}=shfl_in_bounds?shfl_result:{};", inst, value);
}
void EmitShuffleDown(EmitContext& ctx, IR::Inst& inst, std::string_view value,
@ -175,7 +177,8 @@ void EmitShuffleDown(EmitContext& ctx, IR::Inst& inst, std::string_view value,
const auto src_thread_id{fmt::format("({}+{})", THREAD_ID, index)};
ctx.Add("shfl_in_bounds=int({})<=int({});", src_thread_id, max_thread_id);
SetInBoundsFlag(ctx, inst);
ctx.AddU32("{}=shfl_in_bounds?readInvocationARB({},{}):{};", inst, value, src_thread_id, value);
ctx.Add("shfl_result=readInvocationARB({},{});", value, src_thread_id);
ctx.AddU32("{}=shfl_in_bounds?shfl_result:{};", inst, value);
}
void EmitShuffleButterfly(EmitContext& ctx, IR::Inst& inst, std::string_view value,
@ -193,7 +196,8 @@ void EmitShuffleButterfly(EmitContext& ctx, IR::Inst& inst, std::string_view val
const auto src_thread_id{fmt::format("({}^{})", THREAD_ID, index)};
ctx.Add("shfl_in_bounds=int({})<=int({});", src_thread_id, max_thread_id);
SetInBoundsFlag(ctx, inst);
ctx.AddU32("{}=shfl_in_bounds?readInvocationARB({},{}):{};", inst, value, src_thread_id, value);
ctx.Add("shfl_result=readInvocationARB({},{});", value, src_thread_id);
ctx.AddU32("{}=shfl_in_bounds?shfl_result:{};", inst, value);
}
void EmitFSwizzleAdd(EmitContext& ctx, IR::Inst& inst, std::string_view op_a, std::string_view op_b,

View File

@ -111,16 +111,33 @@ Id GetCbuf(EmitContext& ctx, Id result_type, Id UniformDefinitions::*member_ptr,
} else if (element_size > 1) {
const u32 log2_element_size{static_cast<u32>(std::countr_zero(element_size))};
const Id shift{ctx.Const(log2_element_size)};
buffer_offset = ctx.OpShiftRightArithmetic(ctx.U32[1], ctx.Def(offset), shift);
buffer_offset = ctx.OpShiftRightLogical(ctx.U32[1], ctx.Def(offset), shift);
} else {
buffer_offset = ctx.Def(offset);
}
if (!binding.IsImmediate()) {
return ctx.OpFunctionCall(result_type, indirect_func, ctx.Def(binding), buffer_offset);
}
const Id cbuf{ctx.cbufs[binding.U32()].*member_ptr};
const Id access_chain{ctx.OpAccessChain(uniform_type, cbuf, ctx.u32_zero_value, buffer_offset)};
return ctx.OpLoad(result_type, access_chain);
const Id val = ctx.OpLoad(result_type, access_chain);
if (offset.IsImmediate() || !ctx.profile.has_broken_robust) {
return val;
}
const auto is_float = UniformDefinitions::IsFloat(member_ptr);
const auto num_elements = UniformDefinitions::NumElements(member_ptr);
const std::array zero_vec{
is_float ? ctx.Const(0.0f) : ctx.Const(0u),
is_float ? ctx.Const(0.0f) : ctx.Const(0u),
is_float ? ctx.Const(0.0f) : ctx.Const(0u),
is_float ? ctx.Const(0.0f) : ctx.Const(0u),
};
const Id cond = ctx.OpULessThanEqual(ctx.TypeBool(), buffer_offset, ctx.Const(0xFFFFu));
const Id zero = ctx.OpCompositeConstruct(result_type, std::span(zero_vec.data(), num_elements));
return ctx.OpSelect(result_type, cond, val, zero);
}
Id GetCbufU32(EmitContext& ctx, const IR::Value& binding, const IR::Value& offset) {
@ -138,7 +155,7 @@ Id GetCbufElement(EmitContext& ctx, Id vector, const IR::Value& offset, u32 inde
const u32 element{(offset.U32() / 4) % 4 + index_offset};
return ctx.OpCompositeExtract(ctx.U32[1], vector, element);
}
const Id shift{ctx.OpShiftRightArithmetic(ctx.U32[1], ctx.Def(offset), ctx.Const(2u))};
const Id shift{ctx.OpShiftRightLogical(ctx.U32[1], ctx.Def(offset), ctx.Const(2u))};
Id element{ctx.OpBitwiseAnd(ctx.U32[1], shift, ctx.Const(3u))};
if (index_offset > 0) {
element = ctx.OpIAdd(ctx.U32[1], element, ctx.Const(index_offset));

View File

@ -64,6 +64,42 @@ struct UniformDefinitions {
Id F32{};
Id U32x2{};
Id U32x4{};
constexpr static size_t NumElements(Id UniformDefinitions::*member_ptr) {
if (member_ptr == &UniformDefinitions::U8) {
return 1;
}
if (member_ptr == &UniformDefinitions::S8) {
return 1;
}
if (member_ptr == &UniformDefinitions::U16) {
return 1;
}
if (member_ptr == &UniformDefinitions::S16) {
return 1;
}
if (member_ptr == &UniformDefinitions::U32) {
return 1;
}
if (member_ptr == &UniformDefinitions::F32) {
return 1;
}
if (member_ptr == &UniformDefinitions::U32x2) {
return 2;
}
if (member_ptr == &UniformDefinitions::U32x4) {
return 4;
}
ASSERT(false);
return 1;
}
constexpr static bool IsFloat(Id UniformDefinitions::*member_ptr) {
if (member_ptr == &UniformDefinitions::F32) {
return true;
}
return false;
}
};
struct StorageTypeDefinition {

View File

@ -9,7 +9,6 @@ namespace Shader {
struct Profile {
u32 supported_spirv{0x00010000};
bool unified_descriptor_binding{};
bool support_descriptor_aliasing{};
bool support_int8{};
@ -82,6 +81,9 @@ struct Profile {
bool has_broken_spirv_subgroup_mask_vector_extract_dynamic{};
u32 gl_max_compute_smem_size{};
/// Maxwell and earlier nVidia architectures have broken robust support
bool has_broken_robust{};
};
} // namespace Shader

View File

@ -356,7 +356,11 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, const Device& device
.has_broken_fp16_float_controls = driver_id == VK_DRIVER_ID_NVIDIA_PROPRIETARY,
.ignore_nan_fp_comparisons = false,
.has_broken_spirv_subgroup_mask_vector_extract_dynamic =
driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY};
driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY,
.has_broken_robust =
device.IsNvidia() && device.GetNvidiaArch() <= NvidiaArchitecture::Arch_Maxwell,
};
host_info = Shader::HostTranslateInfo{
.support_float64 = device.IsFloat64Supported(),
.support_float16 = device.IsFloat16Supported(),

View File

@ -83,15 +83,6 @@ constexpr std::array VK_FORMAT_A4B4G4R4_UNORM_PACK16{
} // namespace Alternatives
enum class NvidiaArchitecture {
KeplerOrOlder,
Maxwell,
Pascal,
Volta,
Turing,
AmpereOrNewer,
};
template <typename T>
void SetNext(void**& next, T& data) {
*next = &data;
@ -326,9 +317,9 @@ NvidiaArchitecture GetNvidiaArchitecture(vk::PhysicalDevice physical,
if (shading_rate_props.primitiveFragmentShadingRateWithMultipleViewports) {
// Only Ampere and newer support this feature
// TODO: Find a way to differentiate Ampere and Ada
return NvidiaArchitecture::AmpereOrNewer;
return NvidiaArchitecture::Arch_AmpereOrNewer;
}
return NvidiaArchitecture::Turing;
return NvidiaArchitecture::Arch_Turing;
}
if (exts.contains(VK_EXT_BLEND_OPERATION_ADVANCED_EXTENSION_NAME)) {
@ -340,7 +331,7 @@ NvidiaArchitecture GetNvidiaArchitecture(vk::PhysicalDevice physical,
physical_properties.pNext = &advanced_blending_props;
physical.GetProperties2(physical_properties);
if (advanced_blending_props.advancedBlendMaxColorAttachments == 1) {
return NvidiaArchitecture::Maxwell;
return NvidiaArchitecture::Arch_Maxwell;
}
if (exts.contains(VK_EXT_CONSERVATIVE_RASTERIZATION_EXTENSION_NAME)) {
@ -350,13 +341,13 @@ NvidiaArchitecture GetNvidiaArchitecture(vk::PhysicalDevice physical,
physical_properties.pNext = &conservative_raster_props;
physical.GetProperties2(physical_properties);
if (conservative_raster_props.degenerateLinesRasterized) {
return NvidiaArchitecture::Volta;
return NvidiaArchitecture::Arch_Volta;
}
return NvidiaArchitecture::Pascal;
return NvidiaArchitecture::Arch_Pascal;
}
}
return NvidiaArchitecture::KeplerOrOlder;
return NvidiaArchitecture::Arch_KeplerOrOlder;
}
std::vector<const char*> ExtensionListForVulkan(
@ -436,6 +427,10 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
throw vk::Exception(VK_ERROR_INCOMPATIBLE_DRIVER);
}
if (is_nvidia) {
nvidia_arch = GetNvidiaArchitecture(physical, supported_extensions);
}
SetupFamilies(surface);
const auto queue_cis = GetDeviceQueueCreateInfos();
@ -532,11 +527,11 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
if (is_nvidia) {
const u32 nv_major_version = (properties.properties.driverVersion >> 22) & 0x3ff;
const auto arch = GetNvidiaArchitecture(physical, supported_extensions);
if (arch >= NvidiaArchitecture::AmpereOrNewer) {
const auto arch = GetNvidiaArch();
if (arch >= NvidiaArchitecture::Arch_AmpereOrNewer) {
LOG_WARNING(Render_Vulkan, "Ampere and newer have broken float16 math");
features.shader_float16_int8.shaderFloat16 = false;
} else if (arch <= NvidiaArchitecture::Volta) {
} else if (arch <= NvidiaArchitecture::Arch_Volta) {
if (nv_major_version < 527) {
LOG_WARNING(Render_Vulkan, "Volta and older have broken VK_KHR_push_descriptor");
RemoveExtension(extensions.push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
@ -686,8 +681,8 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
RemoveExtension(extensions.push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
}
} else if (extensions.push_descriptor && is_nvidia) {
const auto arch = GetNvidiaArchitecture(physical, supported_extensions);
if (arch <= NvidiaArchitecture::Pascal) {
const auto arch = GetNvidiaArch();
if (arch <= NvidiaArchitecture::Arch_Pascal) {
LOG_WARNING(Render_Vulkan,
"Pascal and older architectures have broken VK_KHR_push_descriptor");
RemoveExtension(extensions.push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);

View File

@ -177,6 +177,15 @@ enum class FormatType { Linear, Optimal, Buffer };
/// Subgroup size of the guest emulated hardware (Nvidia has 32 threads per subgroup).
const u32 GuestWarpSize = 32;
enum class NvidiaArchitecture {
Arch_KeplerOrOlder,
Arch_Maxwell,
Arch_Pascal,
Arch_Volta,
Arch_Turing,
Arch_AmpereOrNewer,
};
/// Handles data specific to a physical device.
class Device {
public:
@ -670,6 +679,14 @@ public:
return false;
}
bool IsNvidia() const noexcept {
return properties.driver.driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY;
}
NvidiaArchitecture GetNvidiaArch() const noexcept {
return nvidia_arch;
}
private:
/// Checks if the physical device is suitable and configures the object state
/// with all necessary info about its properties.
@ -788,6 +805,7 @@ private:
bool supports_conditional_barriers{}; ///< Allows barriers in conditional control flow.
u64 device_access_memory{}; ///< Total size of device local memory in bytes.
u32 sets_per_pool{}; ///< Sets per Description Pool
NvidiaArchitecture nvidia_arch{NvidiaArchitecture::Arch_AmpereOrNewer};
// Telemetry parameters
std::set<std::string, std::less<>> supported_extensions; ///< Reported Vulkan extensions.

View File

@ -522,7 +522,7 @@ Instance Instance::Create(u32 version, Span<const char*> layers, Span<const char
.applicationVersion = VK_MAKE_VERSION(0, 1, 0),
.pEngineName = "yuzu Emulator",
.engineVersion = VK_MAKE_VERSION(0, 1, 0),
.apiVersion = version,
.apiVersion = VK_API_VERSION_1_3,
};
const VkInstanceCreateInfo ci{
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,

View File

@ -114,7 +114,7 @@ const std::map<Settings::ShaderBackend, QString> Config::shader_backend_texts_ma
// This must be in alphabetical order according to action name as it must have the same order as
// UISetting::values.shortcuts, which is alphabetically ordered.
// clang-format off
const std::array<UISettings::Shortcut, 22> Config::default_hotkeys{{
const std::array<UISettings::Shortcut, 23> Config::default_hotkeys{{
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Mute/Unmute")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+M"), QStringLiteral("Home+Dpad_Right"), Qt::WindowShortcut, false}},
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Volume Down")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("-"), QStringLiteral("Home+Dpad_Down"), Qt::ApplicationShortcut, true}},
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Volume Up")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("="), QStringLiteral("Home+Dpad_Up"), Qt::ApplicationShortcut, true}},
@ -136,6 +136,7 @@ const std::array<UISettings::Shortcut, 22> Config::default_hotkeys{{
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Filter Bar")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+F"), QStringLiteral(""), Qt::WindowShortcut, false}},
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Framerate Limit")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+U"), QStringLiteral("Home+Y"), Qt::ApplicationShortcut, false}},
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Mouse Panning")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+F9"), QStringLiteral(""), Qt::ApplicationShortcut, false}},
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Renderdoc Capture")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral(""), QStringLiteral(""), Qt::ApplicationShortcut, false}},
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Toggle Status Bar")), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")), {QStringLiteral("Ctrl+S"), QStringLiteral(""), Qt::WindowShortcut, false}},
}};
// clang-format on

View File

@ -48,7 +48,7 @@ public:
default_mouse_buttons;
static const std::array<int, Settings::NativeKeyboard::NumKeyboardKeys> default_keyboard_keys;
static const std::array<int, Settings::NativeKeyboard::NumKeyboardMods> default_keyboard_mods;
static const std::array<UISettings::Shortcut, 22> default_hotkeys;
static const std::array<UISettings::Shortcut, 23> default_hotkeys;
static const std::map<Settings::AntiAliasing, QString> anti_aliasing_texts_map;
static const std::map<Settings::ScalingFilter, QString> scaling_filter_texts_map;

View File

@ -319,6 +319,13 @@ void ConfigureHotkeys::ApplyConfiguration(HotkeyRegistry& registry) {
void ConfigureHotkeys::RestoreDefaults() {
for (int r = 0; r < model->rowCount(); ++r) {
const QStandardItem* parent = model->item(r, 0);
const int hotkey_size = static_cast<int>(Config::default_hotkeys.size());
if (hotkey_size != parent->rowCount()) {
QMessageBox::warning(this, tr("Invalid hotkey settings"),
tr("An error occurred. Please report this issue on github."));
return;
}
for (int r2 = 0; r2 < parent->rowCount(); ++r2) {
model->item(r, 0)

View File

@ -89,7 +89,7 @@ void ConfigureVibration::VibrateController(Core::HID::ControllerTriggerType type
auto& player = Settings::values.players.GetValue()[player_index];
auto controller = hid_core.GetEmulatedControllerByIndex(player_index);
const int vibration_strenght = vibration_spinboxes[player_index]->value();
const int vibration_strength = vibration_spinboxes[player_index]->value();
const auto& buttons = controller->GetButtonsValues();
bool button_is_pressed = false;
@ -105,10 +105,10 @@ void ConfigureVibration::VibrateController(Core::HID::ControllerTriggerType type
return;
}
const int old_vibration_enabled = player.vibration_enabled;
const bool old_vibration_strenght = player.vibration_strength;
const bool old_vibration_enabled = player.vibration_enabled;
const int old_vibration_strength = player.vibration_strength;
player.vibration_enabled = true;
player.vibration_strength = vibration_strenght;
player.vibration_strength = vibration_strength;
const Core::HID::VibrationValue vibration{
.low_amplitude = 1.0f,
@ -121,7 +121,7 @@ void ConfigureVibration::VibrateController(Core::HID::ControllerTriggerType type
// Restore previous values
player.vibration_enabled = old_vibration_enabled;
player.vibration_strength = old_vibration_strenght;
player.vibration_strength = old_vibration_strength;
}
void ConfigureVibration::StopVibrations() {