early-access version 4110
This commit is contained in:
parent
2391029e47
commit
337d0ed51c
18 changed files with 139 additions and 30 deletions
|
@ -1,7 +1,7 @@
|
|||
yuzu emulator early access
|
||||
=============
|
||||
|
||||
This is the source code for early-access 4109.
|
||||
This is the source code for early-access 4110.
|
||||
|
||||
## Legal Notice
|
||||
|
||||
|
|
|
@ -164,6 +164,7 @@ else()
|
|||
|
||||
if (MINGW)
|
||||
add_definitions(-DMINGW_HAS_SECURE_API)
|
||||
add_compile_options("-msse4.1")
|
||||
|
||||
if (MINGW_STATIC_BUILD)
|
||||
add_definitions(-DQT_STATICPLUGIN)
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
#include <fmt/format.h>
|
||||
#include "common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace Common {
|
||||
|
@ -29,6 +30,8 @@ namespace Common {
|
|||
|
||||
template <std::size_t Size, bool le = false>
|
||||
[[nodiscard]] constexpr std::array<u8, Size> HexStringToArray(std::string_view str) {
|
||||
ASSERT_MSG(Size * 2 <= str.size(), "Invalid string size");
|
||||
|
||||
std::array<u8, Size> out{};
|
||||
if constexpr (le) {
|
||||
for (std::size_t i = 2 * Size - 2; i <= 2 * Size; i -= 2) {
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "core/hle/result.h"
|
||||
#include "core/hle/service/am/am_results.h"
|
||||
#include "core/hle/service/am/frontend/applets.h"
|
||||
#include "core/hle/service/am/self_controller.h"
|
||||
#include "core/hle/service/caps/caps_su.h"
|
||||
#include "core/hle/service/hle_ipc.h"
|
||||
#include "core/hle/service/ipc_helpers.h"
|
||||
#include "core/hle/service/nvnflinger/fb_share_buffer_manager.h"
|
||||
#include "core/hle/service/nvnflinger/nvnflinger.h"
|
||||
|
@ -47,7 +50,7 @@ ISelfController::ISelfController(Core::System& system_, std::shared_ptr<Applet>
|
|||
{50, &ISelfController::SetHandlesRequestToDisplay, "SetHandlesRequestToDisplay"},
|
||||
{51, &ISelfController::ApproveToDisplay, "ApproveToDisplay"},
|
||||
{60, nullptr, "OverrideAutoSleepTimeAndDimmingTime"},
|
||||
{61, nullptr, "SetMediaPlaybackState"},
|
||||
{61, &ISelfController::SetMediaPlaybackState, "SetMediaPlaybackState"},
|
||||
{62, &ISelfController::SetIdleTimeDetectionExtension, "SetIdleTimeDetectionExtension"},
|
||||
{63, &ISelfController::GetIdleTimeDetectionExtension, "GetIdleTimeDetectionExtension"},
|
||||
{64, nullptr, "SetInputDetectionSourceSet"},
|
||||
|
@ -324,6 +327,16 @@ void ISelfController::ApproveToDisplay(HLERequestContext& ctx) {
|
|||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void ISelfController::SetMediaPlaybackState(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const u8 state = rp.Pop<u8>();
|
||||
|
||||
LOG_WARNING(Service_AM, "(STUBBED) called, state={}", state);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void ISelfController::SetIdleTimeDetectionExtension(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/hle_ipc.h"
|
||||
#include "core/hle/service/kernel_helpers.h"
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
|
@ -38,6 +39,7 @@ private:
|
|||
void CreateManagedDisplaySeparableLayer(HLERequestContext& ctx);
|
||||
void SetHandlesRequestToDisplay(HLERequestContext& ctx);
|
||||
void ApproveToDisplay(HLERequestContext& ctx);
|
||||
void SetMediaPlaybackState(HLERequestContext& ctx);
|
||||
void SetIdleTimeDetectionExtension(HLERequestContext& ctx);
|
||||
void GetIdleTimeDetectionExtension(HLERequestContext& ctx);
|
||||
void ReportUserIsActive(HLERequestContext& ctx);
|
||||
|
|
|
@ -115,6 +115,11 @@ struct ArgumentTraits {
|
|||
static constexpr ArgumentType Type = ArgumentType::InData;
|
||||
};
|
||||
|
||||
template <typename... Ts>
|
||||
consteval bool ConstIfReference() {
|
||||
return ((!std::is_reference_v<Ts> || std::is_const_v<std::remove_reference_t<Ts>>) && ... && true);
|
||||
}
|
||||
|
||||
struct RequestLayout {
|
||||
u32 copy_handle_count;
|
||||
u32 move_handle_count;
|
||||
|
@ -435,6 +440,7 @@ void CmifReplyWrapImpl(HLERequestContext& ctx, T& t, Result (T::*f)(A...)) {
|
|||
}
|
||||
const bool is_domain = Domain ? ctx.GetManager()->IsDomain() : false;
|
||||
|
||||
static_assert(ConstIfReference<A...>(), "Arguments taken by reference must be const");
|
||||
using MethodArguments = std::tuple<std::remove_cvref_t<A>...>;
|
||||
|
||||
OutTemporaryBuffers buffers{};
|
||||
|
|
|
@ -4,10 +4,9 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <span>
|
||||
|
||||
#include "common/common_funcs.h"
|
||||
#include "common/common_types.h"
|
||||
#include "core/hle/service/hle_ipc.h"
|
||||
|
||||
namespace Service {
|
||||
|
||||
|
@ -22,8 +21,10 @@ class Out {
|
|||
public:
|
||||
using Type = T;
|
||||
|
||||
/* implicit */ Out(const Out& t) : raw(t.raw) {}
|
||||
/* implicit */ Out(AutoOut<Type>& t) : raw(&t.raw) {}
|
||||
/* implicit */ Out(Type* t) : raw(t) {}
|
||||
Out& operator=(const Out&) = delete;
|
||||
|
||||
Type* Get() const {
|
||||
return raw;
|
||||
|
@ -37,6 +38,10 @@ public:
|
|||
return raw;
|
||||
}
|
||||
|
||||
operator Type*() const {
|
||||
return raw;
|
||||
}
|
||||
|
||||
private:
|
||||
Type* raw;
|
||||
};
|
||||
|
@ -113,8 +118,10 @@ class OutCopyHandle {
|
|||
public:
|
||||
using Type = T*;
|
||||
|
||||
/* implicit */ OutCopyHandle(const OutCopyHandle& t) : raw(t.raw) {}
|
||||
/* implicit */ OutCopyHandle(AutoOut<Type>& t) : raw(&t.raw) {}
|
||||
/* implicit */ OutCopyHandle(Type* t) : raw(t) {}
|
||||
OutCopyHandle& operator=(const OutCopyHandle&) = delete;
|
||||
|
||||
Type* Get() const {
|
||||
return raw;
|
||||
|
@ -128,6 +135,10 @@ public:
|
|||
return raw;
|
||||
}
|
||||
|
||||
operator Type*() const {
|
||||
return raw;
|
||||
}
|
||||
|
||||
private:
|
||||
Type* raw;
|
||||
};
|
||||
|
@ -137,8 +148,10 @@ class OutMoveHandle {
|
|||
public:
|
||||
using Type = T*;
|
||||
|
||||
/* implicit */ OutMoveHandle(const OutMoveHandle& t) : raw(t.raw) {}
|
||||
/* implicit */ OutMoveHandle(AutoOut<Type>& t) : raw(&t.raw) {}
|
||||
/* implicit */ OutMoveHandle(Type* t) : raw(t) {}
|
||||
OutMoveHandle& operator=(const OutMoveHandle&) = delete;
|
||||
|
||||
Type* Get() const {
|
||||
return raw;
|
||||
|
@ -152,6 +165,10 @@ public:
|
|||
return raw;
|
||||
}
|
||||
|
||||
operator Type*() const {
|
||||
return raw;
|
||||
}
|
||||
|
||||
private:
|
||||
Type* raw;
|
||||
};
|
||||
|
@ -248,8 +265,10 @@ public:
|
|||
static constexpr BufferAttr Attr = static_cast<BufferAttr>(A | BufferAttr_In | BufferAttr_FixedSize);
|
||||
using Type = T;
|
||||
|
||||
/* implicit */ OutLargeData(const OutLargeData& t) : raw(t.raw) {}
|
||||
/* implicit */ OutLargeData(Type* t) : raw(t) {}
|
||||
/* implicit */ OutLargeData(AutoOut<T>& t) : raw(&t.raw) {}
|
||||
OutLargeData& operator=(const OutLargeData&) = delete;
|
||||
|
||||
Type* Get() const {
|
||||
return raw;
|
||||
|
@ -263,6 +282,10 @@ public:
|
|||
return raw;
|
||||
}
|
||||
|
||||
operator Type*() const {
|
||||
return raw;
|
||||
}
|
||||
|
||||
private:
|
||||
Type* raw;
|
||||
};
|
||||
|
|
|
@ -115,6 +115,11 @@ private:
|
|||
if (type->GetName() == "save") {
|
||||
for (const auto& save_id : type->GetSubdirectories()) {
|
||||
for (const auto& user_id : save_id->GetSubdirectories()) {
|
||||
// Skip non user id subdirectories
|
||||
if (user_id->GetName().size() != 0x20) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto save_id_numeric = stoull_be(save_id->GetName());
|
||||
auto user_id_numeric = Common::HexStringToArray<0x10>(user_id->GetName());
|
||||
std::reverse(user_id_numeric.begin(), user_id_numeric.end());
|
||||
|
@ -160,6 +165,10 @@ private:
|
|||
} else if (space == FileSys::SaveDataSpaceId::TemporaryStorage) {
|
||||
// Temporary Storage
|
||||
for (const auto& user_id : type->GetSubdirectories()) {
|
||||
// Skip non user id subdirectories
|
||||
if (user_id->GetName().size() != 0x20) {
|
||||
continue;
|
||||
}
|
||||
for (const auto& title_id : user_id->GetSubdirectories()) {
|
||||
if (!title_id->GetFiles().empty() ||
|
||||
!title_id->GetSubdirectories().empty()) {
|
||||
|
|
|
@ -65,6 +65,7 @@ Result MountTimeZoneBinary(Core::System& system) {
|
|||
// Validate that the romfs is readable, using invalid firmware keys can cause this to get
|
||||
// set but the files to be garbage. In that case, we want to hit the next path and
|
||||
// synthesise them instead.
|
||||
g_time_zone_binary_mount_result = ResultSuccess;
|
||||
Service::PSC::Time::LocationName name{"Etc/GMT"};
|
||||
if (!IsTimeZoneBinaryValid(name)) {
|
||||
ResetTimeZoneBinary();
|
||||
|
|
|
@ -123,6 +123,8 @@ NvResult nvhost_as_gpu::AllocAsEx(IoctlAllocAsEx& params) {
|
|||
vm.va_range_end = params.va_range_end;
|
||||
}
|
||||
|
||||
const u64 max_big_page_bits = Common::Log2Ceil64(vm.va_range_end);
|
||||
|
||||
const auto start_pages{static_cast<u32>(vm.va_range_start >> VM::PAGE_SIZE_BITS)};
|
||||
const auto end_pages{static_cast<u32>(vm.va_range_split >> VM::PAGE_SIZE_BITS)};
|
||||
vm.small_page_allocator = std::make_shared<VM::Allocator>(start_pages, end_pages);
|
||||
|
@ -132,8 +134,8 @@ NvResult nvhost_as_gpu::AllocAsEx(IoctlAllocAsEx& params) {
|
|||
static_cast<u32>((vm.va_range_end - vm.va_range_split) >> vm.big_page_size_bits)};
|
||||
vm.big_page_allocator = std::make_unique<VM::Allocator>(start_big_pages, end_big_pages);
|
||||
|
||||
gmmu = std::make_shared<Tegra::MemoryManager>(system, 40, vm.big_page_size_bits,
|
||||
VM::PAGE_SIZE_BITS);
|
||||
gmmu = std::make_shared<Tegra::MemoryManager>(system, max_big_page_bits, vm.va_range_split,
|
||||
vm.big_page_size_bits, VM::PAGE_SIZE_BITS);
|
||||
system.GPU().InitAddressSpace(*gmmu);
|
||||
vm.initialised = true;
|
||||
|
||||
|
|
|
@ -134,7 +134,7 @@ bool HardwareContext::InitializeForDecoder(DecoderContext& decoder_context,
|
|||
const Decoder& decoder) {
|
||||
const auto supported_types = GetSupportedDeviceTypes();
|
||||
for (const auto type : PreferredGpuDecoders) {
|
||||
// AVPixelFormat hw_pix_fmt;
|
||||
AVPixelFormat hw_pix_fmt;
|
||||
|
||||
if (std::ranges::find(supported_types, type) == supported_types.end()) {
|
||||
LOG_DEBUG(HW_GPU, "{} explicitly unsupported", av_hwdevice_get_type_name(type));
|
||||
|
@ -145,11 +145,10 @@ bool HardwareContext::InitializeForDecoder(DecoderContext& decoder_context,
|
|||
continue;
|
||||
}
|
||||
|
||||
// Disable GPU decoding as it cannot return decode frame ordering which breaks everything.
|
||||
// if (decoder.SupportsDecodingOnDevice(&hw_pix_fmt, type)) {
|
||||
// decoder_context.InitializeHardwareDecoder(*this, hw_pix_fmt);
|
||||
// return true;
|
||||
//}
|
||||
if (decoder.SupportsDecodingOnDevice(&hw_pix_fmt, type)) {
|
||||
decoder_context.InitializeHardwareDecoder(*this, hw_pix_fmt);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
LOG_INFO(HW_GPU, "Hardware decoding is disabled due to implementation issues, using CPU.");
|
||||
|
|
|
@ -10,7 +10,7 @@ namespace Tegra::Host1x {
|
|||
|
||||
Host1x::Host1x(Core::System& system_)
|
||||
: system{system_}, syncpoint_manager{},
|
||||
memory_manager(system.DeviceMemory()), gmmu_manager{system, memory_manager, 32, 12},
|
||||
memory_manager(system.DeviceMemory()), gmmu_manager{system, memory_manager, 32, 0, 12},
|
||||
allocator{std::make_unique<Common::FlatAllocator<u32, 0, 32>>(1 << 12)} {}
|
||||
|
||||
Host1x::~Host1x() = default;
|
||||
|
|
|
@ -22,11 +22,12 @@ using Tegra::Memory::GuestMemoryFlags;
|
|||
std::atomic<size_t> MemoryManager::unique_identifier_generator{};
|
||||
|
||||
MemoryManager::MemoryManager(Core::System& system_, MaxwellDeviceMemoryManager& memory_,
|
||||
u64 address_space_bits_, u64 big_page_bits_, u64 page_bits_)
|
||||
u64 address_space_bits_, GPUVAddr split_address_, u64 big_page_bits_,
|
||||
u64 page_bits_)
|
||||
: system{system_}, memory{memory_}, address_space_bits{address_space_bits_},
|
||||
page_bits{page_bits_}, big_page_bits{big_page_bits_}, entries{}, big_entries{},
|
||||
page_table{address_space_bits, address_space_bits + page_bits - 38,
|
||||
page_bits != big_page_bits ? page_bits : 0},
|
||||
split_address{split_address_}, page_bits{page_bits_}, big_page_bits{big_page_bits_},
|
||||
entries{}, big_entries{}, page_table{address_space_bits, address_space_bits + page_bits - 38,
|
||||
page_bits != big_page_bits ? page_bits : 0},
|
||||
kind_map{PTEKind::INVALID}, unique_identifier{unique_identifier_generator.fetch_add(
|
||||
1, std::memory_order_acq_rel)},
|
||||
accumulator{std::make_unique<VideoCommon::InvalidationAccumulator>()} {
|
||||
|
@ -48,10 +49,10 @@ MemoryManager::MemoryManager(Core::System& system_, MaxwellDeviceMemoryManager&
|
|||
entries.resize(page_table_size / 32, 0);
|
||||
}
|
||||
|
||||
MemoryManager::MemoryManager(Core::System& system_, u64 address_space_bits_, u64 big_page_bits_,
|
||||
u64 page_bits_)
|
||||
: MemoryManager(system_, system_.Host1x().MemoryManager(), address_space_bits_, big_page_bits_,
|
||||
page_bits_) {}
|
||||
MemoryManager::MemoryManager(Core::System& system_, u64 address_space_bits_,
|
||||
GPUVAddr split_address_, u64 big_page_bits_, u64 page_bits_)
|
||||
: MemoryManager(system_, system_.Host1x().MemoryManager(), address_space_bits_, split_address_,
|
||||
big_page_bits_, page_bits_) {}
|
||||
|
||||
MemoryManager::~MemoryManager() = default;
|
||||
|
||||
|
|
|
@ -36,10 +36,11 @@ namespace Tegra {
|
|||
class MemoryManager final {
|
||||
public:
|
||||
explicit MemoryManager(Core::System& system_, u64 address_space_bits_ = 40,
|
||||
u64 big_page_bits_ = 16, u64 page_bits_ = 12);
|
||||
explicit MemoryManager(Core::System& system_, MaxwellDeviceMemoryManager& memory_,
|
||||
u64 address_space_bits_ = 40, u64 big_page_bits_ = 16,
|
||||
GPUVAddr split_address = 1ULL << 34, u64 big_page_bits_ = 16,
|
||||
u64 page_bits_ = 12);
|
||||
explicit MemoryManager(Core::System& system_, MaxwellDeviceMemoryManager& memory_,
|
||||
u64 address_space_bits_ = 40, GPUVAddr split_address = 1ULL << 34,
|
||||
u64 big_page_bits_ = 16, u64 page_bits_ = 12);
|
||||
~MemoryManager();
|
||||
|
||||
static constexpr bool HAS_FLUSH_INVALIDATION = true;
|
||||
|
@ -194,6 +195,7 @@ private:
|
|||
MaxwellDeviceMemoryManager& memory;
|
||||
|
||||
const u64 address_space_bits;
|
||||
GPUVAddr split_address;
|
||||
const u64 page_bits;
|
||||
u64 address_space_size;
|
||||
u64 page_size;
|
||||
|
|
|
@ -1353,6 +1353,13 @@ void GMainWindow::InitializeHotkeys() {
|
|||
LinkActionShortcut(ui->action_TAS_Start, QStringLiteral("TAS Start/Stop"), true);
|
||||
LinkActionShortcut(ui->action_TAS_Record, QStringLiteral("TAS Record"), true);
|
||||
LinkActionShortcut(ui->action_TAS_Reset, QStringLiteral("TAS Reset"), true);
|
||||
LinkActionShortcut(ui->action_View_Lobby,
|
||||
QStringLiteral("Multiplayer Browse Public Game Lobby"));
|
||||
LinkActionShortcut(ui->action_Start_Room, QStringLiteral("Multiplayer Create Room"));
|
||||
LinkActionShortcut(ui->action_Connect_To_Room,
|
||||
QStringLiteral("Multiplayer Direct Connect to Room"));
|
||||
LinkActionShortcut(ui->action_Show_Room, QStringLiteral("Multiplayer Show Current Room"));
|
||||
LinkActionShortcut(ui->action_Leave_Room, QStringLiteral("Multiplayer Leave Room"));
|
||||
|
||||
static const QString main_window = QStringLiteral("Main Window");
|
||||
const auto connect_shortcut = [&]<typename Fn>(const QString& action_name, const Fn& function) {
|
||||
|
|
|
@ -77,16 +77,23 @@ Lobby::Lobby(QWidget* parent, QStandardItemModel* list,
|
|||
|
||||
// UI Buttons
|
||||
connect(ui->refresh_list, &QPushButton::clicked, this, &Lobby::RefreshLobby);
|
||||
connect(ui->search, &QLineEdit::textChanged, proxy, &LobbyFilterProxyModel::SetFilterSearch);
|
||||
connect(ui->games_owned, &QCheckBox::toggled, proxy, &LobbyFilterProxyModel::SetFilterOwned);
|
||||
connect(ui->hide_empty, &QCheckBox::toggled, proxy, &LobbyFilterProxyModel::SetFilterEmpty);
|
||||
connect(ui->hide_full, &QCheckBox::toggled, proxy, &LobbyFilterProxyModel::SetFilterFull);
|
||||
connect(ui->search, &QLineEdit::textChanged, proxy, &LobbyFilterProxyModel::SetFilterSearch);
|
||||
connect(ui->room_list, &QTreeView::doubleClicked, this, &Lobby::OnJoinRoom);
|
||||
connect(ui->room_list, &QTreeView::clicked, this, &Lobby::OnExpandRoom);
|
||||
|
||||
// Actions
|
||||
connect(&room_list_watcher, &QFutureWatcher<AnnounceMultiplayerRoom::RoomList>::finished, this,
|
||||
&Lobby::OnRefreshLobby);
|
||||
|
||||
// Load persistent filters after events are connected to make sure they apply
|
||||
ui->search->setText(
|
||||
QString::fromStdString(UISettings::values.multiplayer_filter_text.GetValue()));
|
||||
ui->games_owned->setChecked(UISettings::values.multiplayer_filter_games_owned.GetValue());
|
||||
ui->hide_empty->setChecked(UISettings::values.multiplayer_filter_hide_empty.GetValue());
|
||||
ui->hide_full->setChecked(UISettings::values.multiplayer_filter_hide_full.GetValue());
|
||||
}
|
||||
|
||||
Lobby::~Lobby() = default;
|
||||
|
@ -204,6 +211,10 @@ void Lobby::OnJoinRoom(const QModelIndex& source) {
|
|||
|
||||
// Save settings
|
||||
UISettings::values.multiplayer_nickname = ui->nickname->text().toStdString();
|
||||
UISettings::values.multiplayer_filter_text = ui->search->text().toStdString();
|
||||
UISettings::values.multiplayer_filter_games_owned = ui->games_owned->isChecked();
|
||||
UISettings::values.multiplayer_filter_hide_empty = ui->hide_empty->isChecked();
|
||||
UISettings::values.multiplayer_filter_hide_full = ui->hide_full->isChecked();
|
||||
UISettings::values.multiplayer_ip =
|
||||
proxy->data(connection_index, LobbyItemHost::HostIPRole).value<QString>().toStdString();
|
||||
UISettings::values.multiplayer_port =
|
||||
|
|
|
@ -193,12 +193,29 @@ public:
|
|||
}
|
||||
|
||||
QVariant data(int role) const override {
|
||||
if (role != Qt::DisplayRole) {
|
||||
switch (role) {
|
||||
case Qt::DisplayRole: {
|
||||
auto members = data(MemberListRole).toList();
|
||||
return QStringLiteral("%1 / %2 ")
|
||||
.arg(QString::number(members.size()), data(MaxPlayerRole).toString());
|
||||
}
|
||||
case Qt::ForegroundRole: {
|
||||
auto members = data(MemberListRole).toList();
|
||||
auto max_players = data(MaxPlayerRole).toInt();
|
||||
if (members.size() >= max_players) {
|
||||
return QBrush(QColor(255, 48, 32));
|
||||
} else if (members.size() == (max_players - 1)) {
|
||||
return QBrush(QColor(255, 140, 32));
|
||||
} else if (members.size() == 0) {
|
||||
return QBrush(QColor(128, 128, 128));
|
||||
}
|
||||
// FIXME: How to return a value that tells Qt not to modify the
|
||||
// text color from the default (as if Qt::ForegroundRole wasn't overridden)?
|
||||
return QBrush(nullptr);
|
||||
}
|
||||
default:
|
||||
return LobbyItem::data(role);
|
||||
}
|
||||
auto members = data(MemberListRole).toList();
|
||||
return QStringLiteral("%1 / %2 ")
|
||||
.arg(QString::number(members.size()), data(MaxPlayerRole).toString());
|
||||
}
|
||||
|
||||
bool operator<(const QStandardItem& other) const override {
|
||||
|
|
|
@ -169,6 +169,13 @@ struct Values {
|
|||
|
||||
// multiplayer settings
|
||||
Setting<std::string> multiplayer_nickname{linkage, {}, "nickname", Category::Multiplayer};
|
||||
Setting<std::string> multiplayer_filter_text{linkage, {}, "filter_text", Category::Multiplayer};
|
||||
Setting<bool> multiplayer_filter_games_owned{linkage, false, "filter_games_owned",
|
||||
Category::Multiplayer};
|
||||
Setting<bool> multiplayer_filter_hide_empty{linkage, false, "filter_games_hide_empty",
|
||||
Category::Multiplayer};
|
||||
Setting<bool> multiplayer_filter_hide_full{linkage, false, "filter_games_hide_full",
|
||||
Category::Multiplayer};
|
||||
Setting<std::string> multiplayer_ip{linkage, {}, "ip", Category::Multiplayer};
|
||||
Setting<u16, true> multiplayer_port{linkage, 24872, 0,
|
||||
UINT16_MAX, "port", Category::Multiplayer};
|
||||
|
@ -222,7 +229,7 @@ void RestoreWindowState(std::unique_ptr<QtConfig>& qtConfig);
|
|||
// 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<Shortcut, 23> default_hotkeys{{
|
||||
const std::array<Shortcut, 28> default_hotkeys{{
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Mute/Unmute")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+M"), std::string("Home+Dpad_Right"), Qt::WindowShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Volume Down")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("-"), std::string("Home+Dpad_Down"), Qt::ApplicationShortcut, true}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Audio Volume Up")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("="), std::string("Home+Dpad_Up"), Qt::ApplicationShortcut, true}},
|
||||
|
@ -236,6 +243,11 @@ const std::array<Shortcut, 23> default_hotkeys{{
|
|||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Fullscreen")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F11"), std::string("Home+B"), Qt::WindowShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Load File")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+O"), std::string(""), Qt::WidgetWithChildrenShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Load/Remove Amiibo")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F2"), std::string("Home+A"), Qt::WidgetWithChildrenShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Multiplayer Browse Public Game Lobby")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+B"), std::string(""), Qt::ApplicationShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Multiplayer Create Room")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+N"), std::string(""), Qt::ApplicationShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Multiplayer Direct Connect to Room")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+C"), std::string(""), Qt::ApplicationShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Multiplayer Leave Room")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+L"), std::string(""), Qt::ApplicationShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Multiplayer Show Current Room")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+R"), std::string(""), Qt::ApplicationShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Restart Emulation")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F6"), std::string("R+Plus+Minus"), Qt::WindowShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Stop Emulation")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("F5"), std::string("L+Plus+Minus"), Qt::WindowShortcut, false}},
|
||||
{QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "TAS Record")).toStdString(), QStringLiteral(QT_TRANSLATE_NOOP("Hotkeys", "Main Window")).toStdString(), {std::string("Ctrl+F7"), std::string(""), Qt::ApplicationShortcut, false}},
|
||||
|
|
Loading…
Reference in a new issue