summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/logging/filter.cpp1
-rw-r--r--src/common/logging/types.h1
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/core/hle/service/ngct/ngct.cpp46
-rw-r--r--src/core/hle/service/ngct/ngct.h20
-rw-r--r--src/core/hle/service/nifm/nifm.cpp113
-rw-r--r--src/core/hle/service/service.cpp2
-rw-r--r--src/core/network/network_interface.cpp171
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp5
-rw-r--r--src/video_core/command_classes/codecs/vp9.cpp1
-rw-r--r--src/video_core/command_classes/codecs/vp9_types.h85
-rw-r--r--src/video_core/renderer_vulkan/vk_blit_screen.cpp4
-rw-r--r--src/video_core/textures/decoders.cpp8
13 files changed, 255 insertions, 204 deletions
diff --git a/src/common/logging/filter.cpp b/src/common/logging/filter.cpp
index f055f0e11..42744c994 100644
--- a/src/common/logging/filter.cpp
+++ b/src/common/logging/filter.cpp
@@ -111,6 +111,7 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) {
111 SUB(Service, NCM) \ 111 SUB(Service, NCM) \
112 SUB(Service, NFC) \ 112 SUB(Service, NFC) \
113 SUB(Service, NFP) \ 113 SUB(Service, NFP) \
114 SUB(Service, NGCT) \
114 SUB(Service, NIFM) \ 115 SUB(Service, NIFM) \
115 SUB(Service, NIM) \ 116 SUB(Service, NIM) \
116 SUB(Service, NPNS) \ 117 SUB(Service, NPNS) \
diff --git a/src/common/logging/types.h b/src/common/logging/types.h
index 7ad0334fc..ddf9d27ca 100644
--- a/src/common/logging/types.h
+++ b/src/common/logging/types.h
@@ -81,6 +81,7 @@ enum class Class : u8 {
81 Service_NCM, ///< The NCM service 81 Service_NCM, ///< The NCM service
82 Service_NFC, ///< The NFC (Near-field communication) service 82 Service_NFC, ///< The NFC (Near-field communication) service
83 Service_NFP, ///< The NFP service 83 Service_NFP, ///< The NFP service
84 Service_NGCT, ///< The NGCT (No Good Content for Terra) service
84 Service_NIFM, ///< The NIFM (Network interface) service 85 Service_NIFM, ///< The NIFM (Network interface) service
85 Service_NIM, ///< The NIM service 86 Service_NIM, ///< The NIM service
86 Service_NPNS, ///< The NPNS service 87 Service_NPNS, ///< The NPNS service
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index f5cf5c16a..87d47e2e5 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -452,6 +452,8 @@ add_library(core STATIC
452 hle/service/nfp/nfp.h 452 hle/service/nfp/nfp.h
453 hle/service/nfp/nfp_user.cpp 453 hle/service/nfp/nfp_user.cpp
454 hle/service/nfp/nfp_user.h 454 hle/service/nfp/nfp_user.h
455 hle/service/ngct/ngct.cpp
456 hle/service/ngct/ngct.h
455 hle/service/nifm/nifm.cpp 457 hle/service/nifm/nifm.cpp
456 hle/service/nifm/nifm.h 458 hle/service/nifm/nifm.h
457 hle/service/nim/nim.cpp 459 hle/service/nim/nim.cpp
diff --git a/src/core/hle/service/ngct/ngct.cpp b/src/core/hle/service/ngct/ngct.cpp
new file mode 100644
index 000000000..deb3abb28
--- /dev/null
+++ b/src/core/hle/service/ngct/ngct.cpp
@@ -0,0 +1,46 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included
4
5#include "common/string_util.h"
6#include "core/core.h"
7#include "core/hle/ipc_helpers.h"
8#include "core/hle/service/ngct/ngct.h"
9#include "core/hle/service/service.h"
10
11namespace Service::NGCT {
12
13class IService final : public ServiceFramework<IService> {
14public:
15 explicit IService(Core::System& system_) : ServiceFramework{system_, "ngct:u"} {
16 // clang-format off
17 static const FunctionInfo functions[] = {
18 {0, nullptr, "Match"},
19 {1, &IService::Filter, "Filter"},
20 };
21 // clang-format on
22
23 RegisterHandlers(functions);
24 }
25
26private:
27 void Filter(Kernel::HLERequestContext& ctx) {
28 const auto buffer = ctx.ReadBuffer();
29 const auto text = Common::StringFromFixedZeroTerminatedBuffer(
30 reinterpret_cast<const char*>(buffer.data()), buffer.size());
31
32 LOG_WARNING(Service_NGCT, "(STUBBED) called, text={}", text);
33
34 // Return the same string since we don't censor anything
35 ctx.WriteBuffer(buffer);
36
37 IPC::ResponseBuilder rb{ctx, 2};
38 rb.Push(ResultSuccess);
39 }
40};
41
42void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) {
43 std::make_shared<IService>(system)->InstallAsService(system.ServiceManager());
44}
45
46} // namespace Service::NGCT
diff --git a/src/core/hle/service/ngct/ngct.h b/src/core/hle/service/ngct/ngct.h
new file mode 100644
index 000000000..1f2a47b78
--- /dev/null
+++ b/src/core/hle/service/ngct/ngct.h
@@ -0,0 +1,20 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included
4
5#pragma once
6
7namespace Core {
8class System;
9}
10
11namespace Service::SM {
12class ServiceManager;
13}
14
15namespace Service::NGCT {
16
17/// Registers all NGCT services with the specified service manager.
18void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system);
19
20} // namespace Service::NGCT
diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp
index 0a53c0c81..9decb9290 100644
--- a/src/core/hle/service/nifm/nifm.cpp
+++ b/src/core/hle/service/nifm/nifm.cpp
@@ -277,37 +277,45 @@ private:
277 void GetCurrentNetworkProfile(Kernel::HLERequestContext& ctx) { 277 void GetCurrentNetworkProfile(Kernel::HLERequestContext& ctx) {
278 LOG_WARNING(Service_NIFM, "(STUBBED) called"); 278 LOG_WARNING(Service_NIFM, "(STUBBED) called");
279 279
280 const SfNetworkProfileData network_profile_data{ 280 const auto net_iface = Network::GetSelectedNetworkInterface();
281 .ip_setting_data{ 281
282 .ip_address_setting{ 282 const SfNetworkProfileData network_profile_data = [&net_iface] {
283 .is_automatic{true}, 283 if (!net_iface) {
284 .current_address{192, 168, 1, 100}, 284 return SfNetworkProfileData{};
285 .subnet_mask{255, 255, 255, 0}, 285 }
286 .gateway{192, 168, 1, 1}, 286
287 }, 287 return SfNetworkProfileData{
288 .dns_setting{ 288 .ip_setting_data{
289 .is_automatic{true}, 289 .ip_address_setting{
290 .primary_dns{1, 1, 1, 1}, 290 .is_automatic{true},
291 .secondary_dns{1, 0, 0, 1}, 291 .current_address{Network::TranslateIPv4(net_iface->ip_address)},
292 .subnet_mask{Network::TranslateIPv4(net_iface->subnet_mask)},
293 .gateway{Network::TranslateIPv4(net_iface->gateway)},
294 },
295 .dns_setting{
296 .is_automatic{true},
297 .primary_dns{1, 1, 1, 1},
298 .secondary_dns{1, 0, 0, 1},
299 },
300 .proxy_setting{
301 .enabled{false},
302 .port{},
303 .proxy_server{},
304 .automatic_auth_enabled{},
305 .user{},
306 .password{},
307 },
308 .mtu{1500},
292 }, 309 },
293 .proxy_setting{ 310 .uuid{0xdeadbeef, 0xdeadbeef},
294 .enabled{false}, 311 .network_name{"yuzu Network"},
295 .port{}, 312 .wireless_setting_data{
296 .proxy_server{}, 313 .ssid_length{12},
297 .automatic_auth_enabled{}, 314 .ssid{"yuzu Network"},
298 .user{}, 315 .passphrase{"yuzupassword"},
299 .password{},
300 }, 316 },
301 .mtu{1500}, 317 };
302 }, 318 }();
303 .uuid{0xdeadbeef, 0xdeadbeef},
304 .network_name{"yuzu Network"},
305 .wireless_setting_data{
306 .ssid_length{12},
307 .ssid{"yuzu Network"},
308 .passphrase{"yuzupassword"},
309 },
310 };
311 319
312 ctx.WriteBuffer(network_profile_data); 320 ctx.WriteBuffer(network_profile_data);
313 321
@@ -352,38 +360,33 @@ private:
352 LOG_WARNING(Service_NIFM, "(STUBBED) called"); 360 LOG_WARNING(Service_NIFM, "(STUBBED) called");
353 361
354 struct IpConfigInfo { 362 struct IpConfigInfo {
355 IpAddressSetting ip_address_setting; 363 IpAddressSetting ip_address_setting{};
356 DnsSetting dns_setting; 364 DnsSetting dns_setting{};
357 }; 365 };
358 static_assert(sizeof(IpConfigInfo) == sizeof(IpAddressSetting) + sizeof(DnsSetting), 366 static_assert(sizeof(IpConfigInfo) == sizeof(IpAddressSetting) + sizeof(DnsSetting),
359 "IpConfigInfo has incorrect size."); 367 "IpConfigInfo has incorrect size.");
360 368
361 IpConfigInfo ip_config_info{ 369 const auto net_iface = Network::GetSelectedNetworkInterface();
362 .ip_address_setting{
363 .is_automatic{true},
364 .current_address{0, 0, 0, 0},
365 .subnet_mask{255, 255, 255, 0},
366 .gateway{192, 168, 1, 1},
367 },
368 .dns_setting{
369 .is_automatic{true},
370 .primary_dns{1, 1, 1, 1},
371 .secondary_dns{1, 0, 0, 1},
372 },
373 };
374 370
375 const auto iface = Network::GetSelectedNetworkInterface(); 371 const IpConfigInfo ip_config_info = [&net_iface] {
376 if (iface) { 372 if (!net_iface) {
377 ip_config_info.ip_address_setting = 373 return IpConfigInfo{};
378 IpAddressSetting{.is_automatic{true}, 374 }
379 .current_address{Network::TranslateIPv4(iface->ip_address)},
380 .subnet_mask{Network::TranslateIPv4(iface->subnet_mask)},
381 .gateway{Network::TranslateIPv4(iface->gateway)}};
382 375
383 } else { 376 return IpConfigInfo{
384 LOG_ERROR(Service_NIFM, 377 .ip_address_setting{
385 "Couldn't get host network configuration info, using default values"); 378 .is_automatic{true},
386 } 379 .current_address{Network::TranslateIPv4(net_iface->ip_address)},
380 .subnet_mask{Network::TranslateIPv4(net_iface->subnet_mask)},
381 .gateway{Network::TranslateIPv4(net_iface->gateway)},
382 },
383 .dns_setting{
384 .is_automatic{true},
385 .primary_dns{1, 1, 1, 1},
386 .secondary_dns{1, 0, 0, 1},
387 },
388 };
389 }();
387 390
388 IPC::ResponseBuilder rb{ctx, 2 + (sizeof(IpConfigInfo) + 3) / sizeof(u32)}; 391 IPC::ResponseBuilder rb{ctx, 2 + (sizeof(IpConfigInfo) + 3) / sizeof(u32)};
389 rb.Push(ResultSuccess); 392 rb.Push(ResultSuccess);
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index b3e50433b..065133166 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -46,6 +46,7 @@
46#include "core/hle/service/ncm/ncm.h" 46#include "core/hle/service/ncm/ncm.h"
47#include "core/hle/service/nfc/nfc.h" 47#include "core/hle/service/nfc/nfc.h"
48#include "core/hle/service/nfp/nfp.h" 48#include "core/hle/service/nfp/nfp.h"
49#include "core/hle/service/ngct/ngct.h"
49#include "core/hle/service/nifm/nifm.h" 50#include "core/hle/service/nifm/nifm.h"
50#include "core/hle/service/nim/nim.h" 51#include "core/hle/service/nim/nim.h"
51#include "core/hle/service/npns/npns.h" 52#include "core/hle/service/npns/npns.h"
@@ -271,6 +272,7 @@ Services::Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system
271 NCM::InstallInterfaces(*sm, system); 272 NCM::InstallInterfaces(*sm, system);
272 NFC::InstallInterfaces(*sm, system); 273 NFC::InstallInterfaces(*sm, system);
273 NFP::InstallInterfaces(*sm, system); 274 NFP::InstallInterfaces(*sm, system);
275 NGCT::InstallInterfaces(*sm, system);
274 NIFM::InstallInterfaces(*sm, system); 276 NIFM::InstallInterfaces(*sm, system);
275 NIM::InstallInterfaces(*sm, system); 277 NIM::InstallInterfaces(*sm, system);
276 NPNS::InstallInterfaces(*sm, system); 278 NPNS::InstallInterfaces(*sm, system);
diff --git a/src/core/network/network_interface.cpp b/src/core/network/network_interface.cpp
index cecc9aa11..6811f21b1 100644
--- a/src/core/network/network_interface.cpp
+++ b/src/core/network/network_interface.cpp
@@ -37,73 +37,73 @@ std::vector<NetworkInterface> GetAvailableNetworkInterfaces() {
37 AF_INET, GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_INCLUDE_GATEWAYS, 37 AF_INET, GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_INCLUDE_GATEWAYS,
38 nullptr, adapter_addresses.data(), &buf_size); 38 nullptr, adapter_addresses.data(), &buf_size);
39 39
40 if (ret == ERROR_BUFFER_OVERFLOW) { 40 if (ret != ERROR_BUFFER_OVERFLOW) {
41 adapter_addresses.resize((buf_size / sizeof(IP_ADAPTER_ADDRESSES)) + 1);
42 } else {
43 break; 41 break;
44 } 42 }
43
44 adapter_addresses.resize((buf_size / sizeof(IP_ADAPTER_ADDRESSES)) + 1);
45 } 45 }
46 46
47 if (ret == NO_ERROR) { 47 if (ret != NO_ERROR) {
48 std::vector<NetworkInterface> result; 48 LOG_ERROR(Network, "Failed to get network interfaces with GetAdaptersAddresses");
49 return {};
50 }
49 51
50 for (auto current_address = adapter_addresses.data(); current_address != nullptr; 52 std::vector<NetworkInterface> result;
51 current_address = current_address->Next) {
52 if (current_address->FirstUnicastAddress == nullptr ||
53 current_address->FirstUnicastAddress->Address.lpSockaddr == nullptr) {
54 continue;
55 }
56 53
57 if (current_address->OperStatus != IfOperStatusUp) { 54 for (auto current_address = adapter_addresses.data(); current_address != nullptr;
58 continue; 55 current_address = current_address->Next) {
59 } 56 if (current_address->FirstUnicastAddress == nullptr ||
57 current_address->FirstUnicastAddress->Address.lpSockaddr == nullptr) {
58 continue;
59 }
60 60
61 const auto ip_addr = Common::BitCast<struct sockaddr_in>( 61 if (current_address->OperStatus != IfOperStatusUp) {
62 *current_address->FirstUnicastAddress->Address.lpSockaddr) 62 continue;
63 .sin_addr; 63 }
64 64
65 ULONG mask = 0; 65 const auto ip_addr = Common::BitCast<struct sockaddr_in>(
66 if (ConvertLengthToIpv4Mask(current_address->FirstUnicastAddress->OnLinkPrefixLength, 66 *current_address->FirstUnicastAddress->Address.lpSockaddr)
67 &mask) != NO_ERROR) { 67 .sin_addr;
68 LOG_ERROR(Network, "Failed to convert IPv4 prefix length to subnet mask");
69 continue;
70 }
71 68
72 struct in_addr gateway = {.S_un{.S_addr{0}}}; 69 ULONG mask = 0;
73 if (current_address->FirstGatewayAddress != nullptr && 70 if (ConvertLengthToIpv4Mask(current_address->FirstUnicastAddress->OnLinkPrefixLength,
74 current_address->FirstGatewayAddress->Address.lpSockaddr != nullptr) { 71 &mask) != NO_ERROR) {
75 gateway = Common::BitCast<struct sockaddr_in>( 72 LOG_ERROR(Network, "Failed to convert IPv4 prefix length to subnet mask");
76 *current_address->FirstGatewayAddress->Address.lpSockaddr) 73 continue;
77 .sin_addr; 74 }
78 }
79 75
80 result.push_back(NetworkInterface{ 76 struct in_addr gateway = {.S_un{.S_addr{0}}};
81 .name{Common::UTF16ToUTF8(std::wstring{current_address->FriendlyName})}, 77 if (current_address->FirstGatewayAddress != nullptr &&
82 .ip_address{ip_addr}, 78 current_address->FirstGatewayAddress->Address.lpSockaddr != nullptr) {
83 .subnet_mask = in_addr{.S_un{.S_addr{mask}}}, 79 gateway = Common::BitCast<struct sockaddr_in>(
84 .gateway = gateway}); 80 *current_address->FirstGatewayAddress->Address.lpSockaddr)
81 .sin_addr;
85 } 82 }
86 83
87 return result; 84 result.emplace_back(NetworkInterface{
88 } else { 85 .name{Common::UTF16ToUTF8(std::wstring{current_address->FriendlyName})},
89 LOG_ERROR(Network, "Failed to get network interfaces with GetAdaptersAddresses"); 86 .ip_address{ip_addr},
90 return {}; 87 .subnet_mask = in_addr{.S_un{.S_addr{mask}}},
88 .gateway = gateway});
91 } 89 }
90
91 return result;
92} 92}
93 93
94#else 94#else
95 95
96std::vector<NetworkInterface> GetAvailableNetworkInterfaces() { 96std::vector<NetworkInterface> GetAvailableNetworkInterfaces() {
97 std::vector<NetworkInterface> result;
98
99 struct ifaddrs* ifaddr = nullptr; 97 struct ifaddrs* ifaddr = nullptr;
100 98
101 if (getifaddrs(&ifaddr) != 0) { 99 if (getifaddrs(&ifaddr) != 0) {
102 LOG_ERROR(Network, "Failed to get network interfaces with getifaddrs: {}", 100 LOG_ERROR(Network, "Failed to get network interfaces with getifaddrs: {}",
103 std::strerror(errno)); 101 std::strerror(errno));
104 return result; 102 return {};
105 } 103 }
106 104
105 std::vector<NetworkInterface> result;
106
107 for (auto ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) { 107 for (auto ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) {
108 if (ifa->ifa_addr == nullptr || ifa->ifa_netmask == nullptr) { 108 if (ifa->ifa_addr == nullptr || ifa->ifa_netmask == nullptr) {
109 continue; 109 continue;
@@ -117,55 +117,62 @@ std::vector<NetworkInterface> GetAvailableNetworkInterfaces() {
117 continue; 117 continue;
118 } 118 }
119 119
120 std::uint32_t gateway{0}; 120 u32 gateway{};
121
121 std::ifstream file{"/proc/net/route"}; 122 std::ifstream file{"/proc/net/route"};
122 if (file.is_open()) { 123 if (!file.is_open()) {
124 LOG_ERROR(Network, "Failed to open \"/proc/net/route\"");
123 125
124 // ignore header 126 result.emplace_back(NetworkInterface{
125 file.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); 127 .name{ifa->ifa_name},
128 .ip_address{Common::BitCast<struct sockaddr_in>(*ifa->ifa_addr).sin_addr},
129 .subnet_mask{Common::BitCast<struct sockaddr_in>(*ifa->ifa_netmask).sin_addr},
130 .gateway{in_addr{.s_addr = gateway}}});
131 continue;
132 }
126 133
127 bool gateway_found = false; 134 // ignore header
135 file.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
128 136
129 for (std::string line; std::getline(file, line);) { 137 bool gateway_found = false;
130 std::istringstream iss{line};
131 138
132 std::string iface_name{}; 139 for (std::string line; std::getline(file, line);) {
133 iss >> iface_name; 140 std::istringstream iss{line};
134 if (iface_name != ifa->ifa_name) {
135 continue;
136 }
137 141
138 iss >> std::hex; 142 std::string iface_name;
143 iss >> iface_name;
144 if (iface_name != ifa->ifa_name) {
145 continue;
146 }
139 147
140 std::uint32_t dest{0}; 148 iss >> std::hex;
141 iss >> dest;
142 if (dest != 0) {
143 // not the default route
144 continue;
145 }
146 149
147 iss >> gateway; 150 u32 dest{};
151 iss >> dest;
152 if (dest != 0) {
153 // not the default route
154 continue;
155 }
148 156
149 std::uint16_t flags{0}; 157 iss >> gateway;
150 iss >> flags;
151 158
152 // flag RTF_GATEWAY (defined in <linux/route.h>) 159 u16 flags{};
153 if ((flags & 0x2) == 0) { 160 iss >> flags;
154 continue;
155 }
156 161
157 gateway_found = true; 162 // flag RTF_GATEWAY (defined in <linux/route.h>)
158 break; 163 if ((flags & 0x2) == 0) {
164 continue;
159 } 165 }
160 166
161 if (!gateway_found) { 167 gateway_found = true;
162 gateway = 0; 168 break;
163 }
164 } else {
165 LOG_ERROR(Network, "Failed to open \"/proc/net/route\"");
166 } 169 }
167 170
168 result.push_back(NetworkInterface{ 171 if (!gateway_found) {
172 gateway = 0;
173 }
174
175 result.emplace_back(NetworkInterface{
169 .name{ifa->ifa_name}, 176 .name{ifa->ifa_name},
170 .ip_address{Common::BitCast<struct sockaddr_in>(*ifa->ifa_addr).sin_addr}, 177 .ip_address{Common::BitCast<struct sockaddr_in>(*ifa->ifa_addr).sin_addr},
171 .subnet_mask{Common::BitCast<struct sockaddr_in>(*ifa->ifa_netmask).sin_addr}, 178 .subnet_mask{Common::BitCast<struct sockaddr_in>(*ifa->ifa_netmask).sin_addr},
@@ -180,11 +187,11 @@ std::vector<NetworkInterface> GetAvailableNetworkInterfaces() {
180#endif 187#endif
181 188
182std::optional<NetworkInterface> GetSelectedNetworkInterface() { 189std::optional<NetworkInterface> GetSelectedNetworkInterface() {
183 const std::string& selected_network_interface = Settings::values.network_interface.GetValue(); 190 const auto& selected_network_interface = Settings::values.network_interface.GetValue();
184 const auto network_interfaces = Network::GetAvailableNetworkInterfaces(); 191 const auto network_interfaces = Network::GetAvailableNetworkInterfaces();
185 if (network_interfaces.size() == 0) { 192 if (network_interfaces.size() == 0) {
186 LOG_ERROR(Network, "GetAvailableNetworkInterfaces returned no interfaces"); 193 LOG_ERROR(Network, "GetAvailableNetworkInterfaces returned no interfaces");
187 return {}; 194 return std::nullopt;
188 } 195 }
189 196
190 const auto res = 197 const auto res =
@@ -192,12 +199,12 @@ std::optional<NetworkInterface> GetSelectedNetworkInterface() {
192 return iface.name == selected_network_interface; 199 return iface.name == selected_network_interface;
193 }); 200 });
194 201
195 if (res != network_interfaces.end()) { 202 if (res == network_interfaces.end()) {
196 return *res;
197 } else {
198 LOG_ERROR(Network, "Couldn't find selected interface \"{}\"", selected_network_interface); 203 LOG_ERROR(Network, "Couldn't find selected interface \"{}\"", selected_network_interface);
199 return {}; 204 return std::nullopt;
200 } 205 }
206
207 return *res;
201} 208}
202 209
203} // namespace Network 210} // namespace Network
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp
index 14c77f162..9e54a17ee 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp
@@ -333,8 +333,9 @@ Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, Id vertex) {
333 return ctx.OpBitcast(ctx.F32[1], ctx.OpISub(ctx.U32[1], index, base)); 333 return ctx.OpBitcast(ctx.F32[1], ctx.OpISub(ctx.U32[1], index, base));
334 } 334 }
335 case IR::Attribute::FrontFace: 335 case IR::Attribute::FrontFace:
336 return ctx.OpSelect(ctx.U32[1], ctx.OpLoad(ctx.U1, ctx.front_face), 336 return ctx.OpSelect(ctx.F32[1], ctx.OpLoad(ctx.U1, ctx.front_face),
337 ctx.Const(std::numeric_limits<u32>::max()), ctx.u32_zero_value); 337 ctx.OpBitcast(ctx.F32[1], ctx.Const(std::numeric_limits<u32>::max())),
338 ctx.f32_zero_value);
338 case IR::Attribute::PointSpriteS: 339 case IR::Attribute::PointSpriteS:
339 return ctx.OpLoad(ctx.F32[1], 340 return ctx.OpLoad(ctx.F32[1],
340 ctx.OpAccessChain(ctx.input_f32, ctx.point_coord, ctx.u32_zero_value)); 341 ctx.OpAccessChain(ctx.input_f32, ctx.point_coord, ctx.u32_zero_value));
diff --git a/src/video_core/command_classes/codecs/vp9.cpp b/src/video_core/command_classes/codecs/vp9.cpp
index 70030066a..d7e749485 100644
--- a/src/video_core/command_classes/codecs/vp9.cpp
+++ b/src/video_core/command_classes/codecs/vp9.cpp
@@ -742,6 +742,7 @@ VpxBitStreamWriter VP9::ComposeUncompressedHeader() {
742 uncomp_writer.WriteDeltaQ(current_frame_info.uv_dc_delta_q); 742 uncomp_writer.WriteDeltaQ(current_frame_info.uv_dc_delta_q);
743 uncomp_writer.WriteDeltaQ(current_frame_info.uv_ac_delta_q); 743 uncomp_writer.WriteDeltaQ(current_frame_info.uv_ac_delta_q);
744 744
745 ASSERT(!current_frame_info.segment_enabled);
745 uncomp_writer.WriteBit(false); // Segmentation enabled (TODO). 746 uncomp_writer.WriteBit(false); // Segmentation enabled (TODO).
746 747
747 const s32 min_tile_cols_log2 = CalcMinLog2TileCols(current_frame_info.frame_size.width); 748 const s32 min_tile_cols_log2 = CalcMinLog2TileCols(current_frame_info.frame_size.width);
diff --git a/src/video_core/command_classes/codecs/vp9_types.h b/src/video_core/command_classes/codecs/vp9_types.h
index 87eafdb03..3b1ed4b3a 100644
--- a/src/video_core/command_classes/codecs/vp9_types.h
+++ b/src/video_core/command_classes/codecs/vp9_types.h
@@ -22,7 +22,7 @@ struct Vp9FrameDimensions {
22}; 22};
23static_assert(sizeof(Vp9FrameDimensions) == 0x8, "Vp9 Vp9FrameDimensions is an invalid size"); 23static_assert(sizeof(Vp9FrameDimensions) == 0x8, "Vp9 Vp9FrameDimensions is an invalid size");
24 24
25enum FrameFlags : u32 { 25enum class FrameFlags : u32 {
26 IsKeyFrame = 1 << 0, 26 IsKeyFrame = 1 << 0,
27 LastFrameIsKeyFrame = 1 << 1, 27 LastFrameIsKeyFrame = 1 << 1,
28 FrameSizeChanged = 1 << 2, 28 FrameSizeChanged = 1 << 2,
@@ -30,6 +30,7 @@ enum FrameFlags : u32 {
30 LastShowFrame = 1 << 4, 30 LastShowFrame = 1 << 4,
31 IntraOnly = 1 << 5, 31 IntraOnly = 1 << 5,
32}; 32};
33DECLARE_ENUM_FLAG_OPERATORS(FrameFlags)
33 34
34enum class TxSize { 35enum class TxSize {
35 Tx4x4 = 0, // 4x4 transform 36 Tx4x4 = 0, // 4x4 transform
@@ -92,44 +93,34 @@ struct Vp9EntropyProbs {
92static_assert(sizeof(Vp9EntropyProbs) == 0x7B4, "Vp9EntropyProbs is an invalid size"); 93static_assert(sizeof(Vp9EntropyProbs) == 0x7B4, "Vp9EntropyProbs is an invalid size");
93 94
94struct Vp9PictureInfo { 95struct Vp9PictureInfo {
95 bool is_key_frame; 96 u32 bitstream_size;
96 bool intra_only; 97 std::array<u64, 4> frame_offsets;
97 bool last_frame_was_key;
98 bool frame_size_changed;
99 bool error_resilient_mode;
100 bool last_frame_shown;
101 bool show_frame;
102 std::array<s8, 4> ref_frame_sign_bias; 98 std::array<s8, 4> ref_frame_sign_bias;
103 s32 base_q_index; 99 s32 base_q_index;
104 s32 y_dc_delta_q; 100 s32 y_dc_delta_q;
105 s32 uv_dc_delta_q; 101 s32 uv_dc_delta_q;
106 s32 uv_ac_delta_q; 102 s32 uv_ac_delta_q;
107 bool lossless;
108 s32 transform_mode; 103 s32 transform_mode;
109 bool allow_high_precision_mv;
110 s32 interp_filter; 104 s32 interp_filter;
111 s32 reference_mode; 105 s32 reference_mode;
112 s8 comp_fixed_ref;
113 std::array<s8, 2> comp_var_ref;
114 s32 log2_tile_cols; 106 s32 log2_tile_cols;
115 s32 log2_tile_rows; 107 s32 log2_tile_rows;
116 bool segment_enabled;
117 bool segment_map_update;
118 bool segment_map_temporal_update;
119 s32 segment_abs_delta;
120 std::array<u32, 8> segment_feature_enable;
121 std::array<std::array<s16, 4>, 8> segment_feature_data;
122 bool mode_ref_delta_enabled;
123 bool use_prev_in_find_mv_refs;
124 std::array<s8, 4> ref_deltas; 108 std::array<s8, 4> ref_deltas;
125 std::array<s8, 2> mode_deltas; 109 std::array<s8, 2> mode_deltas;
126 Vp9EntropyProbs entropy; 110 Vp9EntropyProbs entropy;
127 Vp9FrameDimensions frame_size; 111 Vp9FrameDimensions frame_size;
128 u8 first_level; 112 u8 first_level;
129 u8 sharpness_level; 113 u8 sharpness_level;
130 u32 bitstream_size; 114 bool is_key_frame;
131 std::array<u64, 4> frame_offsets; 115 bool intra_only;
132 std::array<bool, 4> refresh_frame; 116 bool last_frame_was_key;
117 bool error_resilient_mode;
118 bool last_frame_shown;
119 bool show_frame;
120 bool lossless;
121 bool allow_high_precision_mv;
122 bool segment_enabled;
123 bool mode_ref_delta_enabled;
133}; 124};
134 125
135struct Vp9FrameContainer { 126struct Vp9FrameContainer {
@@ -145,7 +136,7 @@ struct PictureInfo {
145 Vp9FrameDimensions golden_frame_size; ///< 0x50 136 Vp9FrameDimensions golden_frame_size; ///< 0x50
146 Vp9FrameDimensions alt_frame_size; ///< 0x58 137 Vp9FrameDimensions alt_frame_size; ///< 0x58
147 Vp9FrameDimensions current_frame_size; ///< 0x60 138 Vp9FrameDimensions current_frame_size; ///< 0x60
148 u32 vp9_flags; ///< 0x68 139 FrameFlags vp9_flags; ///< 0x68
149 std::array<s8, 4> ref_frame_sign_bias; ///< 0x6C 140 std::array<s8, 4> ref_frame_sign_bias; ///< 0x6C
150 u8 first_level; ///< 0x70 141 u8 first_level; ///< 0x70
151 u8 sharpness_level; ///< 0x71 142 u8 sharpness_level; ///< 0x71
@@ -158,60 +149,43 @@ struct PictureInfo {
158 u8 allow_high_precision_mv; ///< 0x78 149 u8 allow_high_precision_mv; ///< 0x78
159 u8 interp_filter; ///< 0x79 150 u8 interp_filter; ///< 0x79
160 u8 reference_mode; ///< 0x7A 151 u8 reference_mode; ///< 0x7A
161 s8 comp_fixed_ref; ///< 0x7B 152 INSERT_PADDING_BYTES_NOINIT(3); ///< 0x7B
162 std::array<s8, 2> comp_var_ref; ///< 0x7C
163 u8 log2_tile_cols; ///< 0x7E 153 u8 log2_tile_cols; ///< 0x7E
164 u8 log2_tile_rows; ///< 0x7F 154 u8 log2_tile_rows; ///< 0x7F
165 Segmentation segmentation; ///< 0x80 155 Segmentation segmentation; ///< 0x80
166 LoopFilter loop_filter; ///< 0xE4 156 LoopFilter loop_filter; ///< 0xE4
167 INSERT_PADDING_BYTES_NOINIT(5); ///< 0xEB 157 INSERT_PADDING_BYTES_NOINIT(21); ///< 0xEB
168 u32 surface_params; ///< 0xF0
169 INSERT_PADDING_WORDS_NOINIT(3); ///< 0xF4
170 158
171 [[nodiscard]] Vp9PictureInfo Convert() const { 159 [[nodiscard]] Vp9PictureInfo Convert() const {
172 return { 160 return {
173 .is_key_frame = (vp9_flags & FrameFlags::IsKeyFrame) != 0, 161 .bitstream_size = bitstream_size,
174 .intra_only = (vp9_flags & FrameFlags::IntraOnly) != 0, 162 .frame_offsets{},
175 .last_frame_was_key = (vp9_flags & FrameFlags::LastFrameIsKeyFrame) != 0,
176 .frame_size_changed = (vp9_flags & FrameFlags::FrameSizeChanged) != 0,
177 .error_resilient_mode = (vp9_flags & FrameFlags::ErrorResilientMode) != 0,
178 .last_frame_shown = (vp9_flags & FrameFlags::LastShowFrame) != 0,
179 .show_frame = true,
180 .ref_frame_sign_bias = ref_frame_sign_bias, 163 .ref_frame_sign_bias = ref_frame_sign_bias,
181 .base_q_index = base_q_index, 164 .base_q_index = base_q_index,
182 .y_dc_delta_q = y_dc_delta_q, 165 .y_dc_delta_q = y_dc_delta_q,
183 .uv_dc_delta_q = uv_dc_delta_q, 166 .uv_dc_delta_q = uv_dc_delta_q,
184 .uv_ac_delta_q = uv_ac_delta_q, 167 .uv_ac_delta_q = uv_ac_delta_q,
185 .lossless = lossless != 0,
186 .transform_mode = tx_mode, 168 .transform_mode = tx_mode,
187 .allow_high_precision_mv = allow_high_precision_mv != 0,
188 .interp_filter = interp_filter, 169 .interp_filter = interp_filter,
189 .reference_mode = reference_mode, 170 .reference_mode = reference_mode,
190 .comp_fixed_ref = comp_fixed_ref,
191 .comp_var_ref = comp_var_ref,
192 .log2_tile_cols = log2_tile_cols, 171 .log2_tile_cols = log2_tile_cols,
193 .log2_tile_rows = log2_tile_rows, 172 .log2_tile_rows = log2_tile_rows,
194 .segment_enabled = segmentation.enabled != 0,
195 .segment_map_update = segmentation.update_map != 0,
196 .segment_map_temporal_update = segmentation.temporal_update != 0,
197 .segment_abs_delta = segmentation.abs_delta,
198 .segment_feature_enable = segmentation.feature_mask,
199 .segment_feature_data = segmentation.feature_data,
200 .mode_ref_delta_enabled = loop_filter.mode_ref_delta_enabled != 0,
201 .use_prev_in_find_mv_refs = !(vp9_flags == (FrameFlags::ErrorResilientMode)) &&
202 !(vp9_flags == (FrameFlags::FrameSizeChanged)) &&
203 !(vp9_flags == (FrameFlags::IntraOnly)) &&
204 (vp9_flags == (FrameFlags::LastShowFrame)) &&
205 !(vp9_flags == (FrameFlags::LastFrameIsKeyFrame)),
206 .ref_deltas = loop_filter.ref_deltas, 173 .ref_deltas = loop_filter.ref_deltas,
207 .mode_deltas = loop_filter.mode_deltas, 174 .mode_deltas = loop_filter.mode_deltas,
208 .entropy{}, 175 .entropy{},
209 .frame_size = current_frame_size, 176 .frame_size = current_frame_size,
210 .first_level = first_level, 177 .first_level = first_level,
211 .sharpness_level = sharpness_level, 178 .sharpness_level = sharpness_level,
212 .bitstream_size = bitstream_size, 179 .is_key_frame = True(vp9_flags & FrameFlags::IsKeyFrame),
213 .frame_offsets{}, 180 .intra_only = True(vp9_flags & FrameFlags::IntraOnly),
214 .refresh_frame{}, 181 .last_frame_was_key = True(vp9_flags & FrameFlags::LastFrameIsKeyFrame),
182 .error_resilient_mode = True(vp9_flags & FrameFlags::ErrorResilientMode),
183 .last_frame_shown = True(vp9_flags & FrameFlags::LastShowFrame),
184 .show_frame = true,
185 .lossless = lossless != 0,
186 .allow_high_precision_mv = allow_high_precision_mv != 0,
187 .segment_enabled = segmentation.enabled != 0,
188 .mode_ref_delta_enabled = loop_filter.mode_ref_delta_enabled != 0,
215 }; 189 };
216 } 190 }
217}; 191};
@@ -316,7 +290,6 @@ ASSERT_POSITION(last_frame_size, 0x48);
316ASSERT_POSITION(first_level, 0x70); 290ASSERT_POSITION(first_level, 0x70);
317ASSERT_POSITION(segmentation, 0x80); 291ASSERT_POSITION(segmentation, 0x80);
318ASSERT_POSITION(loop_filter, 0xE4); 292ASSERT_POSITION(loop_filter, 0xE4);
319ASSERT_POSITION(surface_params, 0xF0);
320#undef ASSERT_POSITION 293#undef ASSERT_POSITION
321 294
322#define ASSERT_POSITION(field_name, position) \ 295#define ASSERT_POSITION(field_name, position) \
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp
index 5c43b8acf..cb0580182 100644
--- a/src/video_core/renderer_vulkan/vk_blit_screen.cpp
+++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp
@@ -159,11 +159,13 @@ VkSemaphore VKBlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer,
159 159
160 const VAddr framebuffer_addr = framebuffer.address + framebuffer.offset; 160 const VAddr framebuffer_addr = framebuffer.address + framebuffer.offset;
161 const u8* const host_ptr = cpu_memory.GetPointer(framebuffer_addr); 161 const u8* const host_ptr = cpu_memory.GetPointer(framebuffer_addr);
162 const size_t size_bytes = GetSizeInBytes(framebuffer);
163 162
164 // TODO(Rodrigo): Read this from HLE 163 // TODO(Rodrigo): Read this from HLE
165 constexpr u32 block_height_log2 = 4; 164 constexpr u32 block_height_log2 = 4;
166 const u32 bytes_per_pixel = GetBytesPerPixel(framebuffer); 165 const u32 bytes_per_pixel = GetBytesPerPixel(framebuffer);
166 const u64 size_bytes{Tegra::Texture::CalculateSize(true, bytes_per_pixel,
167 framebuffer.stride, framebuffer.height,
168 1, block_height_log2, 0)};
167 Tegra::Texture::UnswizzleTexture( 169 Tegra::Texture::UnswizzleTexture(
168 mapped_span.subspan(image_offset, size_bytes), std::span(host_ptr, size_bytes), 170 mapped_span.subspan(image_offset, size_bytes), std::span(host_ptr, size_bytes),
169 bytes_per_pixel, framebuffer.width, framebuffer.height, 1, block_height_log2, 0); 171 bytes_per_pixel, framebuffer.width, framebuffer.height, 1, block_height_log2, 0);
diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp
index c010b9353..24e943e4c 100644
--- a/src/video_core/textures/decoders.cpp
+++ b/src/video_core/textures/decoders.cpp
@@ -63,14 +63,6 @@ void SwizzleImpl(std::span<u8> output, std::span<const u8> input, u32 width, u32
63 const u32 unswizzled_offset = 63 const u32 unswizzled_offset =
64 slice * pitch * height + line * pitch + column * BYTES_PER_PIXEL; 64 slice * pitch * height + line * pitch + column * BYTES_PER_PIXEL;
65 65
66 if (const auto offset = (TO_LINEAR ? unswizzled_offset : swizzled_offset);
67 offset >= input.size()) {
68 // TODO(Rodrigo): This is an out of bounds access that should never happen. To
69 // avoid crashing the emulator, break.
70 ASSERT_MSG(false, "offset {} exceeds input size {}!", offset, input.size());
71 break;
72 }
73
74 u8* const dst = &output[TO_LINEAR ? swizzled_offset : unswizzled_offset]; 66 u8* const dst = &output[TO_LINEAR ? swizzled_offset : unswizzled_offset];
75 const u8* const src = &input[TO_LINEAR ? unswizzled_offset : swizzled_offset]; 67 const u8* const src = &input[TO_LINEAR ? unswizzled_offset : swizzled_offset];
76 68