summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/common_funcs.h2
-rw-r--r--src/common/hash.h35
-rw-r--r--src/core/file_sys/xts_archive.cpp3
-rw-r--r--src/video_core/CMakeLists.txt6
-rw-r--r--src/video_core/engines/maxwell_3d.cpp3
-rw-r--r--src/video_core/engines/shader_bytecode.h12
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp2
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.cpp6
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp2
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp6
-rw-r--r--src/video_core/shader/decode.cpp4
-rw-r--r--src/video_core/shader/shader_ir.h6
-rw-r--r--src/video_core/textures/astc.cpp73
-rw-r--r--src/video_core/textures/texture.h7
-rw-r--r--src/video_core/video_core.cpp2
-rw-r--r--src/web_service/web_backend.cpp52
-rw-r--r--src/web_service/web_backend.h23
-rw-r--r--src/yuzu/configuration/configure_web.cpp73
-rw-r--r--src/yuzu/configuration/configure_web.ui12
19 files changed, 185 insertions, 144 deletions
diff --git a/src/common/common_funcs.h b/src/common/common_funcs.h
index c029dc7b3..6dc3e108f 100644
--- a/src/common/common_funcs.h
+++ b/src/common/common_funcs.h
@@ -56,7 +56,7 @@ std::string GetLastErrorMsg();
namespace Common {
constexpr u32 MakeMagic(char a, char b, char c, char d) {
- return a | b << 8 | c << 16 | d << 24;
+ return u32(a) | u32(b) << 8 | u32(c) << 16 | u32(d) << 24;
}
} // namespace Common
diff --git a/src/common/hash.h b/src/common/hash.h
index ebd4125e2..b2538f3ea 100644
--- a/src/common/hash.h
+++ b/src/common/hash.h
@@ -35,41 +35,6 @@ static inline u64 ComputeStructHash64(const T& data) {
return ComputeHash64(&data, sizeof(data));
}
-/// A helper template that ensures the padding in a struct is initialized by memsetting to 0.
-template <typename T>
-struct HashableStruct {
- // In addition to being trivially copyable, T must also have a trivial default constructor,
- // because any member initialization would be overridden by memset
- static_assert(std::is_trivial_v<T>, "Type passed to HashableStruct must be trivial");
- /*
- * We use a union because "implicitly-defined copy/move constructor for a union X copies the
- * object representation of X." and "implicitly-defined copy assignment operator for a union X
- * copies the object representation (3.9) of X." = Bytewise copy instead of memberwise copy.
- * This is important because the padding bytes are included in the hash and comparison between
- * objects.
- */
- union {
- T state;
- };
-
- HashableStruct() {
- // Memset structure to zero padding bits, so that they will be deterministic when hashing
- std::memset(&state, 0, sizeof(T));
- }
-
- bool operator==(const HashableStruct<T>& o) const {
- return std::memcmp(&state, &o.state, sizeof(T)) == 0;
- };
-
- bool operator!=(const HashableStruct<T>& o) const {
- return !(*this == o);
- };
-
- std::size_t Hash() const {
- return Common::ComputeStructHash64(state);
- }
-};
-
struct PairHash {
template <class T1, class T2>
std::size_t operator()(const std::pair<T1, T2>& pair) const noexcept {
diff --git a/src/core/file_sys/xts_archive.cpp b/src/core/file_sys/xts_archive.cpp
index 4bc5cb2ee..f5f8b91c9 100644
--- a/src/core/file_sys/xts_archive.cpp
+++ b/src/core/file_sys/xts_archive.cpp
@@ -93,8 +93,7 @@ Loader::ResultStatus NAX::Parse(std::string_view path) {
std::size_t i = 0;
for (; i < sd_keys.size(); ++i) {
std::array<Core::Crypto::Key128, 2> nax_keys{};
- if (!CalculateHMAC256(nax_keys.data(), sd_keys[i].data(), 0x10, std::string(path).c_str(),
- path.size())) {
+ if (!CalculateHMAC256(nax_keys.data(), sd_keys[i].data(), 0x10, path.data(), path.size())) {
return Loader::ResultStatus::ErrorNAXKeyHMACFailed;
}
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt
index c911c6ec4..45d8eaf23 100644
--- a/src/video_core/CMakeLists.txt
+++ b/src/video_core/CMakeLists.txt
@@ -180,3 +180,9 @@ target_link_libraries(video_core PRIVATE glad)
if (ENABLE_VULKAN)
target_link_libraries(video_core PRIVATE sirit)
endif()
+
+if (MSVC)
+ target_compile_options(video_core PRIVATE /we4267)
+else()
+ target_compile_options(video_core PRIVATE -Werror=conversion -Wno-error=sign-conversion)
+endif()
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index 2bed6cb38..42ce49a4d 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -261,7 +261,8 @@ void Maxwell3D::CallMacroMethod(u32 method, std::size_t num_parameters, const u3
executing_macro = 0;
// Lookup the macro offset
- const u32 entry = ((method - MacroRegistersStart) >> 1) % macro_positions.size();
+ const u32 entry =
+ ((method - MacroRegistersStart) >> 1) % static_cast<u32>(macro_positions.size());
// Execute the current macro.
macro_interpreter.Execute(macro_positions[entry], num_parameters, parameters);
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index 312617f71..9fafed4a2 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -1486,7 +1486,8 @@ union Instruction {
u32 value = static_cast<u32>(target);
// The branch offset is relative to the next instruction and is stored in bytes, so
// divide it by the size of an instruction and add 1 to it.
- return static_cast<s32>((value ^ mask) - mask) / sizeof(Instruction) + 1;
+ return static_cast<s32>((value ^ mask) - mask) / static_cast<s32>(sizeof(Instruction)) +
+ 1;
}
} bra;
@@ -1500,7 +1501,8 @@ union Instruction {
u32 value = static_cast<u32>(target);
// The branch offset is relative to the next instruction and is stored in bytes, so
// divide it by the size of an instruction and add 1 to it.
- return static_cast<s32>((value ^ mask) - mask) / sizeof(Instruction) + 1;
+ return static_cast<s32>((value ^ mask) - mask) / static_cast<s32>(sizeof(Instruction)) +
+ 1;
}
} brx;
@@ -1860,11 +1862,11 @@ private:
const std::size_t bit_position = opcode_bitsize - i - 1;
switch (bitstring[i]) {
case '0':
- mask |= 1 << bit_position;
+ mask |= static_cast<u16>(1U << bit_position);
break;
case '1':
- expect |= 1 << bit_position;
- mask |= 1 << bit_position;
+ expect |= static_cast<u16>(1U << bit_position);
+ mask |= static_cast<u16>(1U << bit_position);
break;
default:
// Ignore
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index e560d70d5..e43ba9d6b 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -375,7 +375,7 @@ void RasterizerOpenGL::ConfigureFramebuffers() {
fbkey.color_attachments[index] = GL_COLOR_ATTACHMENT0 + regs.rt_control.GetMap(index);
fbkey.colors[index] = std::move(color_surface);
}
- fbkey.colors_count = regs.rt_control.count;
+ fbkey.colors_count = static_cast<u16>(regs.rt_control.count);
if (depth_surface) {
// Assume that a surface will be written to if it is used as a framebuffer, even if
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp
index 21bac11ec..04a239a39 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp
@@ -403,7 +403,8 @@ Shader CachedShader::CreateStageFromMemory(const ShaderParameters& params,
params.disk_cache.SaveRaw(ShaderDiskCacheRaw(
params.unique_identifier, GetProgramType(program_type), program_code, program_code_b));
- ConstBufferLocker locker(GetEnginesShaderType(GetProgramType(program_type)));
+ ConstBufferLocker locker(GetEnginesShaderType(GetProgramType(program_type)),
+ params.system.GPU().Maxwell3D());
const ShaderIR ir(program_code, STAGE_MAIN_OFFSET, COMPILER_SETTINGS, locker);
// TODO(Rodrigo): Handle VertexA shaders
// std::optional<ShaderIR> ir_b;
@@ -419,7 +420,8 @@ Shader CachedShader::CreateKernelFromMemory(const ShaderParameters& params, Prog
params.disk_cache.SaveRaw(
ShaderDiskCacheRaw(params.unique_identifier, ProgramType::Compute, code));
- ConstBufferLocker locker(Tegra::Engines::ShaderType::Compute);
+ ConstBufferLocker locker(Tegra::Engines::ShaderType::Compute,
+ params.system.GPU().KeplerCompute());
const ShaderIR ir(code, KERNEL_MAIN_OFFSET, COMPILER_SETTINGS, locker);
return std::shared_ptr<CachedShader>(new CachedShader(
params, ProgramType::Compute, GLShader::GetEntries(ir), std::move(code), {}));
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 5d2c38a5e..e56ed51de 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -1690,7 +1690,7 @@ private:
const auto type = meta->sampler.IsShadow() ? Type::Float : Type::Int;
return {GenerateTexture(operation, "Gather",
- {TextureArgument{type, meta->component}, TextureAoffi{}}) +
+ {TextureAoffi{}, TextureArgument{type, meta->component}}) +
GetSwizzle(meta->element),
Type::Float};
}
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index 4bbd17b12..7646cbb0e 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -323,10 +323,12 @@ void RendererOpenGL::DrawScreenTriangles(const ScreenInfo& screen_info, float x,
// (e.g. handheld mode) on a 1920x1080 framebuffer.
f32 scale_u = 1.f, scale_v = 1.f;
if (framebuffer_crop_rect.GetWidth() > 0) {
- scale_u = static_cast<f32>(framebuffer_crop_rect.GetWidth()) / screen_info.texture.width;
+ scale_u = static_cast<f32>(framebuffer_crop_rect.GetWidth()) /
+ static_cast<f32>(screen_info.texture.width);
}
if (framebuffer_crop_rect.GetHeight() > 0) {
- scale_v = static_cast<f32>(framebuffer_crop_rect.GetHeight()) / screen_info.texture.height;
+ scale_v = static_cast<f32>(framebuffer_crop_rect.GetHeight()) /
+ static_cast<f32>(screen_info.texture.height);
}
std::array<ScreenRectVertex, 4> vertices = {{
diff --git a/src/video_core/shader/decode.cpp b/src/video_core/shader/decode.cpp
index 21fb9cb83..22c3e5120 100644
--- a/src/video_core/shader/decode.cpp
+++ b/src/video_core/shader/decode.cpp
@@ -154,10 +154,10 @@ void ShaderIR::Decode() {
LOG_CRITICAL(HW_GPU, "Unknown decompilation mode!");
[[fallthrough]];
case CompileDepth::BruteForce: {
+ const auto shader_end = static_cast<u32>(program_code.size());
coverage_begin = main_offset;
- const std::size_t shader_end = program_code.size();
coverage_end = shader_end;
- for (u32 label = main_offset; label < shader_end; label++) {
+ for (u32 label = main_offset; label < shader_end; ++label) {
basic_blocks.insert({label, DecodeRange(label, label + 1)});
}
break;
diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h
index 26c8fde22..76a849818 100644
--- a/src/video_core/shader/shader_ir.h
+++ b/src/video_core/shader/shader_ir.h
@@ -49,7 +49,7 @@ public:
}
u32 GetSize() const {
- return max_offset + sizeof(float);
+ return max_offset + static_cast<u32>(sizeof(float));
}
u32 GetMaxOffset() const {
@@ -165,8 +165,8 @@ public:
return program_manager.GetVariables();
}
- u32 ConvertAddressToNvidiaSpace(const u32 address) const {
- return (address - main_offset) * sizeof(Tegra::Shader::Instruction);
+ u32 ConvertAddressToNvidiaSpace(u32 address) const {
+ return (address - main_offset) * static_cast<u32>(sizeof(Tegra::Shader::Instruction));
}
/// Returns a condition code evaluated from internal flags
diff --git a/src/video_core/textures/astc.cpp b/src/video_core/textures/astc.cpp
index 58b608a36..33bd31865 100644
--- a/src/video_core/textures/astc.cpp
+++ b/src/video_core/textures/astc.cpp
@@ -92,11 +92,11 @@ private:
const unsigned int mask = 1 << m_NextBit++;
// clear the bit
- *m_CurByte &= ~mask;
+ *m_CurByte &= static_cast<unsigned char>(~mask);
// Write the bit, if necessary
if (b)
- *m_CurByte |= mask;
+ *m_CurByte |= static_cast<unsigned char>(mask);
// Next byte?
if (m_NextBit >= 8) {
@@ -137,7 +137,7 @@ public:
}
uint64_t mask = (1 << (end - start + 1)) - 1;
- return (m_Bits >> start) & mask;
+ return (m_Bits >> start) & static_cast<IntType>(mask);
}
private:
@@ -656,7 +656,7 @@ static IntType Replicate(const IntType& val, uint32_t numBits, uint32_t toBit) {
return 0;
if (toBit == 0)
return 0;
- IntType v = val & ((1 << numBits) - 1);
+ IntType v = val & static_cast<IntType>((1 << numBits) - 1);
IntType res = v;
uint32_t reslen = numBits;
while (reslen < toBit) {
@@ -666,8 +666,8 @@ static IntType Replicate(const IntType& val, uint32_t numBits, uint32_t toBit) {
comp = numBits - newshift;
numBits = newshift;
}
- res <<= numBits;
- res |= v >> comp;
+ res = static_cast<IntType>(res << numBits);
+ res = static_cast<IntType>(res | (v >> comp));
reslen += numBits;
}
return res;
@@ -714,7 +714,7 @@ public:
// Do nothing
return val;
} else if (oldDepth == 0 && newDepth != 0) {
- return (1 << newDepth) - 1;
+ return static_cast<ChannelType>((1 << newDepth) - 1);
} else if (newDepth > oldDepth) {
return Replicate(val, oldDepth, newDepth);
} else {
@@ -722,10 +722,11 @@ public:
if (newDepth == 0) {
return 0xFF;
} else {
- uint8_t bitsWasted = oldDepth - newDepth;
+ uint8_t bitsWasted = static_cast<uint8_t>(oldDepth - newDepth);
uint16_t v = static_cast<uint16_t>(val);
- v = (v + (1 << (bitsWasted - 1))) >> bitsWasted;
- v = ::std::min<uint16_t>(::std::max<uint16_t>(0, v), (1 << newDepth) - 1);
+ v = static_cast<uint16_t>((v + (1 << (bitsWasted - 1))) >> bitsWasted);
+ v = ::std::min<uint16_t>(::std::max<uint16_t>(0, v),
+ static_cast<uint16_t>((1 << newDepth) - 1));
return static_cast<uint8_t>(v);
}
}
@@ -1191,18 +1192,18 @@ static uint32_t SelectPartition(int32_t seed, int32_t x, int32_t y, int32_t z,
uint8_t seed11 = static_cast<uint8_t>((rnum >> 26) & 0xF);
uint8_t seed12 = static_cast<uint8_t>(((rnum >> 30) | (rnum << 2)) & 0xF);
- seed1 *= seed1;
- seed2 *= seed2;
- seed3 *= seed3;
- seed4 *= seed4;
- seed5 *= seed5;
- seed6 *= seed6;
- seed7 *= seed7;
- seed8 *= seed8;
- seed9 *= seed9;
- seed10 *= seed10;
- seed11 *= seed11;
- seed12 *= seed12;
+ seed1 = static_cast<uint8_t>(seed1 * seed1);
+ seed2 = static_cast<uint8_t>(seed2 * seed2);
+ seed3 = static_cast<uint8_t>(seed3 * seed3);
+ seed4 = static_cast<uint8_t>(seed4 * seed4);
+ seed5 = static_cast<uint8_t>(seed5 * seed5);
+ seed6 = static_cast<uint8_t>(seed6 * seed6);
+ seed7 = static_cast<uint8_t>(seed7 * seed7);
+ seed8 = static_cast<uint8_t>(seed8 * seed8);
+ seed9 = static_cast<uint8_t>(seed9 * seed9);
+ seed10 = static_cast<uint8_t>(seed10 * seed10);
+ seed11 = static_cast<uint8_t>(seed11 * seed11);
+ seed12 = static_cast<uint8_t>(seed12 * seed12);
int32_t sh1, sh2, sh3;
if (seed & 1) {
@@ -1214,18 +1215,18 @@ static uint32_t SelectPartition(int32_t seed, int32_t x, int32_t y, int32_t z,
}
sh3 = (seed & 0x10) ? sh1 : sh2;
- seed1 >>= sh1;
- seed2 >>= sh2;
- seed3 >>= sh1;
- seed4 >>= sh2;
- seed5 >>= sh1;
- seed6 >>= sh2;
- seed7 >>= sh1;
- seed8 >>= sh2;
- seed9 >>= sh3;
- seed10 >>= sh3;
- seed11 >>= sh3;
- seed12 >>= sh3;
+ seed1 = static_cast<uint8_t>(seed1 >> sh1);
+ seed2 = static_cast<uint8_t>(seed2 >> sh2);
+ seed3 = static_cast<uint8_t>(seed3 >> sh1);
+ seed4 = static_cast<uint8_t>(seed4 >> sh2);
+ seed5 = static_cast<uint8_t>(seed5 >> sh1);
+ seed6 = static_cast<uint8_t>(seed6 >> sh2);
+ seed7 = static_cast<uint8_t>(seed7 >> sh1);
+ seed8 = static_cast<uint8_t>(seed8 >> sh2);
+ seed9 = static_cast<uint8_t>(seed9 >> sh3);
+ seed10 = static_cast<uint8_t>(seed10 >> sh3);
+ seed11 = static_cast<uint8_t>(seed11 >> sh3);
+ seed12 = static_cast<uint8_t>(seed12 >> sh3);
int32_t a = seed1 * x + seed2 * y + seed11 * z + (rnum >> 14);
int32_t b = seed3 * x + seed4 * y + seed12 * z + (rnum >> 10);
@@ -1558,7 +1559,9 @@ static void DecompressBlock(const uint8_t inBuf[16], const uint32_t blockWidth,
// Make sure that higher non-texel bits are set to zero
const uint32_t clearByteStart = (weightParams.GetPackedBitSize() >> 3) + 1;
- texelWeightData[clearByteStart - 1] &= (1 << (weightParams.GetPackedBitSize() % 8)) - 1;
+ texelWeightData[clearByteStart - 1] =
+ texelWeightData[clearByteStart - 1] &
+ static_cast<uint8_t>((1 << (weightParams.GetPackedBitSize() % 8)) - 1);
memset(texelWeightData + clearByteStart, 0, 16 - clearByteStart);
std::vector<IntegerEncodedValue> texelWeightValues;
diff --git a/src/video_core/textures/texture.h b/src/video_core/textures/texture.h
index 27c8ce975..8e82c6748 100644
--- a/src/video_core/textures/texture.h
+++ b/src/video_core/textures/texture.h
@@ -342,13 +342,14 @@ struct TSCEntry {
float GetLodBias() const {
// Sign extend the 13-bit value.
constexpr u32 mask = 1U << (13 - 1);
- return static_cast<s32>((mip_lod_bias ^ mask) - mask) / 256.0f;
+ return static_cast<float>(static_cast<s32>((mip_lod_bias ^ mask) - mask)) / 256.0f;
}
std::array<float, 4> GetBorderColor() const {
if (srgb_conversion) {
- return {srgb_border_color_r / 255.0f, srgb_border_color_g / 255.0f,
- srgb_border_color_b / 255.0f, border_color[3]};
+ return {static_cast<float>(srgb_border_color_r) / 255.0f,
+ static_cast<float>(srgb_border_color_g) / 255.0f,
+ static_cast<float>(srgb_border_color_b) / 255.0f, border_color[3]};
}
return border_color;
}
diff --git a/src/video_core/video_core.cpp b/src/video_core/video_core.cpp
index 60cda0ca3..8e947394c 100644
--- a/src/video_core/video_core.cpp
+++ b/src/video_core/video_core.cpp
@@ -28,7 +28,7 @@ std::unique_ptr<Tegra::GPU> CreateGPU(Core::System& system) {
u16 GetResolutionScaleFactor(const RendererBase& renderer) {
return static_cast<u16>(
- Settings::values.resolution_factor
+ Settings::values.resolution_factor != 0
? Settings::values.resolution_factor
: renderer.GetRenderWindow().GetFramebufferLayout().GetScalingRatio());
}
diff --git a/src/web_service/web_backend.cpp b/src/web_service/web_backend.cpp
index dc149d2ed..6683f459f 100644
--- a/src/web_service/web_backend.cpp
+++ b/src/web_service/web_backend.cpp
@@ -2,10 +2,12 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include <array>
#include <cstdlib>
#include <mutex>
#include <string>
#include <LUrlParser.h>
+#include <fmt/format.h>
#include <httplib.h>
#include "common/common_types.h"
#include "common/logging/log.h"
@@ -16,10 +18,10 @@ namespace WebService {
constexpr std::array<const char, 1> API_VERSION{'1'};
-constexpr u32 HTTP_PORT = 80;
-constexpr u32 HTTPS_PORT = 443;
+constexpr int HTTP_PORT = 80;
+constexpr int HTTPS_PORT = 443;
-constexpr u32 TIMEOUT_SECONDS = 30;
+constexpr std::size_t TIMEOUT_SECONDS = 30;
struct Client::Impl {
Impl(std::string host, std::string username, std::string token)
@@ -31,8 +33,9 @@ struct Client::Impl {
}
/// A generic function handles POST, GET and DELETE request together
- Common::WebResult GenericJson(const std::string& method, const std::string& path,
- const std::string& data, bool allow_anonymous) {
+ Common::WebResult GenericRequest(const std::string& method, const std::string& path,
+ const std::string& data, bool allow_anonymous,
+ const std::string& accept) {
if (jwt.empty()) {
UpdateJWT();
}
@@ -43,11 +46,11 @@ struct Client::Impl {
"Credentials needed"};
}
- auto result = GenericJson(method, path, data, jwt);
+ auto result = GenericRequest(method, path, data, accept, jwt);
if (result.result_string == "401") {
// Try again with new JWT
UpdateJWT();
- result = GenericJson(method, path, data, jwt);
+ result = GenericRequest(method, path, data, accept, jwt);
}
return result;
@@ -56,12 +59,13 @@ struct Client::Impl {
/**
* A generic function with explicit authentication method specified
* JWT is used if the jwt parameter is not empty
- * username + token is used if jwt is empty but username and token are not empty
- * anonymous if all of jwt, username and token are empty
+ * username + token is used if jwt is empty but username and token are
+ * not empty anonymous if all of jwt, username and token are empty
*/
- Common::WebResult GenericJson(const std::string& method, const std::string& path,
- const std::string& data, const std::string& jwt = "",
- const std::string& username = "", const std::string& token = "") {
+ Common::WebResult GenericRequest(const std::string& method, const std::string& path,
+ const std::string& data, const std::string& accept,
+ const std::string& jwt = "", const std::string& username = "",
+ const std::string& token = "") {
if (cli == nullptr) {
auto parsedUrl = LUrlParser::clParseURL::ParseURL(host);
int port;
@@ -132,8 +136,7 @@ struct Client::Impl {
return Common::WebResult{Common::WebResult::Code::WrongContent, ""};
}
- if (content_type->second.find("application/json") == std::string::npos &&
- content_type->second.find("text/html; charset=utf-8") == std::string::npos) {
+ if (content_type->second.find(accept) == std::string::npos) {
LOG_ERROR(WebService, "{} to {} returned wrong content: {}", method, host + path,
content_type->second);
return Common::WebResult{Common::WebResult::Code::WrongContent, "Wrong content"};
@@ -147,7 +150,7 @@ struct Client::Impl {
return;
}
- auto result = GenericJson("POST", "/jwt/internal", "", "", username, token);
+ auto result = GenericRequest("POST", "/jwt/internal", "", "text/html", "", username, token);
if (result.result_code != Common::WebResult::Code::Success) {
LOG_ERROR(WebService, "UpdateJWT failed");
} else {
@@ -180,16 +183,29 @@ Client::~Client() = default;
Common::WebResult Client::PostJson(const std::string& path, const std::string& data,
bool allow_anonymous) {
- return impl->GenericJson("POST", path, data, allow_anonymous);
+ return impl->GenericRequest("POST", path, data, allow_anonymous, "application/json");
}
Common::WebResult Client::GetJson(const std::string& path, bool allow_anonymous) {
- return impl->GenericJson("GET", path, "", allow_anonymous);
+ return impl->GenericRequest("GET", path, "", allow_anonymous, "application/json");
}
Common::WebResult Client::DeleteJson(const std::string& path, const std::string& data,
bool allow_anonymous) {
- return impl->GenericJson("DELETE", path, data, allow_anonymous);
+ return impl->GenericRequest("DELETE", path, data, allow_anonymous, "application/json");
+}
+
+Common::WebResult Client::GetPlain(const std::string& path, bool allow_anonymous) {
+ return impl->GenericRequest("GET", path, "", allow_anonymous, "text/plain");
+}
+
+Common::WebResult Client::GetImage(const std::string& path, bool allow_anonymous) {
+ return impl->GenericRequest("GET", path, "", allow_anonymous, "image/png");
+}
+
+Common::WebResult Client::GetExternalJWT(const std::string& audience) {
+ return impl->GenericRequest("POST", fmt::format("/jwt/external/{}", audience), "", false,
+ "text/html");
}
} // namespace WebService
diff --git a/src/web_service/web_backend.h b/src/web_service/web_backend.h
index c637e09df..04121f17e 100644
--- a/src/web_service/web_backend.h
+++ b/src/web_service/web_backend.h
@@ -46,6 +46,29 @@ public:
Common::WebResult DeleteJson(const std::string& path, const std::string& data,
bool allow_anonymous);
+ /**
+ * Gets a plain string from the specified path.
+ * @param path the URL segment after the host address.
+ * @param allow_anonymous If true, allow anonymous unauthenticated requests.
+ * @return the result of the request.
+ */
+ Common::WebResult GetPlain(const std::string& path, bool allow_anonymous);
+
+ /**
+ * Gets an PNG image from the specified path.
+ * @param path the URL segment after the host address.
+ * @param allow_anonymous If true, allow anonymous unauthenticated requests.
+ * @return the result of the request.
+ */
+ Common::WebResult GetImage(const std::string& path, bool allow_anonymous);
+
+ /**
+ * Requests an external JWT for the specific audience provided.
+ * @param audience the audience of the JWT requested.
+ * @return the result of the request.
+ */
+ Common::WebResult GetExternalJWT(const std::string& audience);
+
private:
struct Impl;
std::unique_ptr<Impl> impl;
diff --git a/src/yuzu/configuration/configure_web.cpp b/src/yuzu/configuration/configure_web.cpp
index 336b062b3..8637f5b3c 100644
--- a/src/yuzu/configuration/configure_web.cpp
+++ b/src/yuzu/configuration/configure_web.cpp
@@ -11,6 +11,31 @@
#include "yuzu/configuration/configure_web.h"
#include "yuzu/uisettings.h"
+static constexpr char token_delimiter{':'};
+
+static std::string GenerateDisplayToken(const std::string& username, const std::string& token) {
+ if (username.empty() || token.empty()) {
+ return {};
+ }
+
+ const std::string unencoded_display_token{username + token_delimiter + token};
+ QByteArray b{unencoded_display_token.c_str()};
+ QByteArray b64 = b.toBase64();
+ return b64.toStdString();
+}
+
+static std::string UsernameFromDisplayToken(const std::string& display_token) {
+ const std::string unencoded_display_token{
+ QByteArray::fromBase64(display_token.c_str()).toStdString()};
+ return unencoded_display_token.substr(0, unencoded_display_token.find(token_delimiter));
+}
+
+static std::string TokenFromDisplayToken(const std::string& display_token) {
+ const std::string unencoded_display_token{
+ QByteArray::fromBase64(display_token.c_str()).toStdString()};
+ return unencoded_display_token.substr(unencoded_display_token.find(token_delimiter) + 1);
+}
+
ConfigureWeb::ConfigureWeb(QWidget* parent)
: QWidget(parent), ui(std::make_unique<Ui::ConfigureWeb>()) {
ui->setupUi(this);
@@ -63,13 +88,18 @@ void ConfigureWeb::SetConfiguration() {
ui->web_signup_link->setOpenExternalLinks(true);
ui->web_token_info_link->setOpenExternalLinks(true);
+ if (Settings::values.yuzu_username.empty()) {
+ ui->username->setText(tr("Unspecified"));
+ } else {
+ ui->username->setText(QString::fromStdString(Settings::values.yuzu_username));
+ }
+
ui->toggle_telemetry->setChecked(Settings::values.enable_telemetry);
- ui->edit_username->setText(QString::fromStdString(Settings::values.yuzu_username));
- ui->edit_token->setText(QString::fromStdString(Settings::values.yuzu_token));
+ ui->edit_token->setText(QString::fromStdString(
+ GenerateDisplayToken(Settings::values.yuzu_username, Settings::values.yuzu_token)));
// Connect after setting the values, to avoid calling OnLoginChanged now
connect(ui->edit_token, &QLineEdit::textChanged, this, &ConfigureWeb::OnLoginChanged);
- connect(ui->edit_username, &QLineEdit::textChanged, this, &ConfigureWeb::OnLoginChanged);
user_verified = true;
@@ -80,12 +110,13 @@ void ConfigureWeb::ApplyConfiguration() {
Settings::values.enable_telemetry = ui->toggle_telemetry->isChecked();
UISettings::values.enable_discord_presence = ui->toggle_discordrpc->isChecked();
if (user_verified) {
- Settings::values.yuzu_username = ui->edit_username->text().toStdString();
- Settings::values.yuzu_token = ui->edit_token->text().toStdString();
+ Settings::values.yuzu_username =
+ UsernameFromDisplayToken(ui->edit_token->text().toStdString());
+ Settings::values.yuzu_token = TokenFromDisplayToken(ui->edit_token->text().toStdString());
} else {
- QMessageBox::warning(this, tr("Username and token not verified"),
- tr("Username and token were not verified. The changes to your "
- "username and/or token have not been saved."));
+ QMessageBox::warning(
+ this, tr("Token not verified"),
+ tr("Token was not verified. The change to your token has not been saved."));
}
}
@@ -96,17 +127,15 @@ void ConfigureWeb::RefreshTelemetryID() {
}
void ConfigureWeb::OnLoginChanged() {
- if (ui->edit_username->text().isEmpty() && ui->edit_token->text().isEmpty()) {
+ if (ui->edit_token->text().isEmpty()) {
user_verified = true;
const QPixmap pixmap = QIcon::fromTheme(QStringLiteral("checked")).pixmap(16);
- ui->label_username_verified->setPixmap(pixmap);
ui->label_token_verified->setPixmap(pixmap);
} else {
user_verified = false;
const QPixmap pixmap = QIcon::fromTheme(QStringLiteral("failed")).pixmap(16);
- ui->label_username_verified->setPixmap(pixmap);
ui->label_token_verified->setPixmap(pixmap);
}
}
@@ -114,10 +143,11 @@ void ConfigureWeb::OnLoginChanged() {
void ConfigureWeb::VerifyLogin() {
ui->button_verify_login->setDisabled(true);
ui->button_verify_login->setText(tr("Verifying..."));
- verify_watcher.setFuture(QtConcurrent::run([username = ui->edit_username->text().toStdString(),
- token = ui->edit_token->text().toStdString()] {
- return Core::VerifyLogin(username, token);
- }));
+ verify_watcher.setFuture(QtConcurrent::run(
+ [username = UsernameFromDisplayToken(ui->edit_token->text().toStdString()),
+ token = TokenFromDisplayToken(ui->edit_token->text().toStdString())] {
+ return Core::VerifyLogin(username, token);
+ }));
}
void ConfigureWeb::OnLoginVerified() {
@@ -127,16 +157,15 @@ void ConfigureWeb::OnLoginVerified() {
user_verified = true;
const QPixmap pixmap = QIcon::fromTheme(QStringLiteral("checked")).pixmap(16);
- ui->label_username_verified->setPixmap(pixmap);
ui->label_token_verified->setPixmap(pixmap);
+ ui->username->setText(
+ QString::fromStdString(UsernameFromDisplayToken(ui->edit_token->text().toStdString())));
} else {
const QPixmap pixmap = QIcon::fromTheme(QStringLiteral("failed")).pixmap(16);
- ui->label_username_verified->setPixmap(pixmap);
ui->label_token_verified->setPixmap(pixmap);
-
- QMessageBox::critical(
- this, tr("Verification failed"),
- tr("Verification failed. Check that you have entered your username and token "
- "correctly, and that your internet connection is working."));
+ ui->username->setText(tr("Unspecified"));
+ QMessageBox::critical(this, tr("Verification failed"),
+ tr("Verification failed. Check that you have entered your token "
+ "correctly, and that your internet connection is working."));
}
}
diff --git a/src/yuzu/configuration/configure_web.ui b/src/yuzu/configuration/configure_web.ui
index 2f4b9dd73..8c07d1165 100644
--- a/src/yuzu/configuration/configure_web.ui
+++ b/src/yuzu/configuration/configure_web.ui
@@ -55,11 +55,7 @@
</widget>
</item>
<item row="0" column="1" colspan="3">
- <widget class="QLineEdit" name="edit_username">
- <property name="maxLength">
- <number>36</number>
- </property>
- </widget>
+ <widget class="QLabel" name="username" />
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_token">
@@ -79,14 +75,10 @@
</property>
</widget>
</item>
- <item row="0" column="4">
- <widget class="QLabel" name="label_username_verified">
- </widget>
- </item>
<item row="1" column="1" colspan="3">
<widget class="QLineEdit" name="edit_token">
<property name="maxLength">
- <number>36</number>
+ <number>80</number>
</property>
<property name="echoMode">
<enum>QLineEdit::Password</enum>