early-access version 3764
This commit is contained in:
parent
30259960bd
commit
bbf6b05a26
@ -289,10 +289,11 @@ find_package(Boost 1.79.0 REQUIRED context)
|
||||
find_package(enet 1.3 MODULE)
|
||||
find_package(fmt 9 REQUIRED)
|
||||
find_package(inih 52 MODULE COMPONENTS INIReader)
|
||||
find_package(LLVM MODULE COMPONENTS Demangle)
|
||||
find_package(LLVM 17 MODULE COMPONENTS Demangle)
|
||||
find_package(lz4 REQUIRED)
|
||||
find_package(nlohmann_json 3.8 REQUIRED)
|
||||
find_package(Opus 1.3 MODULE)
|
||||
find_package(VulkanMemoryAllocator CONFIG)
|
||||
find_package(ZLIB 1.2 REQUIRED)
|
||||
find_package(zstd 1.5 REQUIRED)
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
yuzu emulator early access
|
||||
=============
|
||||
|
||||
This is the source code for early-access 3754.
|
||||
This is the source code for early-access 3764.
|
||||
|
||||
## Legal Notice
|
||||
|
||||
|
6
externals/CMakeLists.txt
vendored
6
externals/CMakeLists.txt
vendored
@ -144,9 +144,9 @@ endif()
|
||||
add_subdirectory(nx_tzdb)
|
||||
|
||||
# VMA
|
||||
add_library(vma vma/vma.cpp)
|
||||
target_include_directories(vma PUBLIC ./vma/VulkanMemoryAllocator/include)
|
||||
target_link_libraries(vma PRIVATE Vulkan::Headers)
|
||||
if (NOT TARGET GPUOpen::VulkanMemoryAllocator)
|
||||
add_subdirectory(VulkanMemoryAllocator)
|
||||
endif()
|
||||
|
||||
if (NOT TARGET LLVM::Demangle)
|
||||
add_library(demangle demangle/ItaniumDemangle.cpp)
|
||||
|
171
externals/demangle/ItaniumDemangle.cpp
vendored
171
externals/demangle/ItaniumDemangle.cpp
vendored
@ -20,9 +20,7 @@
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <numeric>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::itanium_demangle;
|
||||
@ -81,8 +79,8 @@ struct DumpVisitor {
|
||||
}
|
||||
|
||||
void printStr(const char *S) { fprintf(stderr, "%s", S); }
|
||||
void print(StringView SV) {
|
||||
fprintf(stderr, "\"%.*s\"", (int)SV.size(), SV.begin());
|
||||
void print(std::string_view SV) {
|
||||
fprintf(stderr, "\"%.*s\"", (int)SV.size(), SV.data());
|
||||
}
|
||||
void print(const Node *N) {
|
||||
if (N)
|
||||
@ -90,14 +88,6 @@ struct DumpVisitor {
|
||||
else
|
||||
printStr("<null>");
|
||||
}
|
||||
void print(NodeOrString NS) {
|
||||
if (NS.isNode())
|
||||
print(NS.asNode());
|
||||
else if (NS.isString())
|
||||
print(NS.asString());
|
||||
else
|
||||
printStr("NodeOrString()");
|
||||
}
|
||||
void print(NodeArray A) {
|
||||
++Depth;
|
||||
printStr("{");
|
||||
@ -116,13 +106,11 @@ struct DumpVisitor {
|
||||
// Overload used when T is exactly 'bool', not merely convertible to 'bool'.
|
||||
void print(bool B) { printStr(B ? "true" : "false"); }
|
||||
|
||||
template <class T>
|
||||
typename std::enable_if<std::is_unsigned<T>::value>::type print(T N) {
|
||||
template <class T> std::enable_if_t<std::is_unsigned<T>::value> print(T N) {
|
||||
fprintf(stderr, "%llu", (unsigned long long)N);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
typename std::enable_if<std::is_signed<T>::value>::type print(T N) {
|
||||
template <class T> std::enable_if_t<std::is_signed<T>::value> print(T N) {
|
||||
fprintf(stderr, "%lld", (long long)N);
|
||||
}
|
||||
|
||||
@ -185,6 +173,50 @@ struct DumpVisitor {
|
||||
return printStr("TemplateParamKind::Template");
|
||||
}
|
||||
}
|
||||
void print(Node::Prec P) {
|
||||
switch (P) {
|
||||
case Node::Prec::Primary:
|
||||
return printStr("Node::Prec::Primary");
|
||||
case Node::Prec::Postfix:
|
||||
return printStr("Node::Prec::Postfix");
|
||||
case Node::Prec::Unary:
|
||||
return printStr("Node::Prec::Unary");
|
||||
case Node::Prec::Cast:
|
||||
return printStr("Node::Prec::Cast");
|
||||
case Node::Prec::PtrMem:
|
||||
return printStr("Node::Prec::PtrMem");
|
||||
case Node::Prec::Multiplicative:
|
||||
return printStr("Node::Prec::Multiplicative");
|
||||
case Node::Prec::Additive:
|
||||
return printStr("Node::Prec::Additive");
|
||||
case Node::Prec::Shift:
|
||||
return printStr("Node::Prec::Shift");
|
||||
case Node::Prec::Spaceship:
|
||||
return printStr("Node::Prec::Spaceship");
|
||||
case Node::Prec::Relational:
|
||||
return printStr("Node::Prec::Relational");
|
||||
case Node::Prec::Equality:
|
||||
return printStr("Node::Prec::Equality");
|
||||
case Node::Prec::And:
|
||||
return printStr("Node::Prec::And");
|
||||
case Node::Prec::Xor:
|
||||
return printStr("Node::Prec::Xor");
|
||||
case Node::Prec::Ior:
|
||||
return printStr("Node::Prec::Ior");
|
||||
case Node::Prec::AndIf:
|
||||
return printStr("Node::Prec::AndIf");
|
||||
case Node::Prec::OrIf:
|
||||
return printStr("Node::Prec::OrIf");
|
||||
case Node::Prec::Conditional:
|
||||
return printStr("Node::Prec::Conditional");
|
||||
case Node::Prec::Assign:
|
||||
return printStr("Node::Prec::Assign");
|
||||
case Node::Prec::Comma:
|
||||
return printStr("Node::Prec::Comma");
|
||||
case Node::Prec::Default:
|
||||
return printStr("Node::Prec::Default");
|
||||
}
|
||||
}
|
||||
|
||||
void newLine() {
|
||||
printStr("\n");
|
||||
@ -334,36 +366,21 @@ public:
|
||||
|
||||
using Demangler = itanium_demangle::ManglingParser<DefaultAllocator>;
|
||||
|
||||
char *llvm::itaniumDemangle(const char *MangledName, char *Buf,
|
||||
size_t *N, int *Status) {
|
||||
if (MangledName == nullptr || (Buf != nullptr && N == nullptr)) {
|
||||
if (Status)
|
||||
*Status = demangle_invalid_args;
|
||||
char *llvm::itaniumDemangle(std::string_view MangledName) {
|
||||
if (MangledName.empty())
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int InternalStatus = demangle_success;
|
||||
Demangler Parser(MangledName, MangledName + std::strlen(MangledName));
|
||||
OutputStream S;
|
||||
|
||||
Demangler Parser(MangledName.data(),
|
||||
MangledName.data() + MangledName.length());
|
||||
Node *AST = Parser.parse();
|
||||
if (!AST)
|
||||
return nullptr;
|
||||
|
||||
if (AST == nullptr)
|
||||
InternalStatus = demangle_invalid_mangled_name;
|
||||
else if (!initializeOutputStream(Buf, N, S, 1024))
|
||||
InternalStatus = demangle_memory_alloc_failure;
|
||||
else {
|
||||
assert(Parser.ForwardTemplateRefs.empty());
|
||||
AST->print(S);
|
||||
S += '\0';
|
||||
if (N != nullptr)
|
||||
*N = S.getCurrentPosition();
|
||||
Buf = S.getBuffer();
|
||||
}
|
||||
|
||||
if (Status)
|
||||
*Status = InternalStatus;
|
||||
return InternalStatus == demangle_success ? Buf : nullptr;
|
||||
OutputBuffer OB;
|
||||
assert(Parser.ForwardTemplateRefs.empty());
|
||||
AST->print(OB);
|
||||
OB += '\0';
|
||||
return OB.getBuffer();
|
||||
}
|
||||
|
||||
ItaniumPartialDemangler::ItaniumPartialDemangler()
|
||||
@ -396,14 +413,12 @@ bool ItaniumPartialDemangler::partialDemangle(const char *MangledName) {
|
||||
}
|
||||
|
||||
static char *printNode(const Node *RootNode, char *Buf, size_t *N) {
|
||||
OutputStream S;
|
||||
if (!initializeOutputStream(Buf, N, S, 128))
|
||||
return nullptr;
|
||||
RootNode->print(S);
|
||||
S += '\0';
|
||||
OutputBuffer OB(Buf, N);
|
||||
RootNode->print(OB);
|
||||
OB += '\0';
|
||||
if (N != nullptr)
|
||||
*N = S.getCurrentPosition();
|
||||
return S.getBuffer();
|
||||
*N = OB.getCurrentPosition();
|
||||
return OB.getBuffer();
|
||||
}
|
||||
|
||||
char *ItaniumPartialDemangler::getFunctionBaseName(char *Buf, size_t *N) const {
|
||||
@ -417,8 +432,8 @@ char *ItaniumPartialDemangler::getFunctionBaseName(char *Buf, size_t *N) const {
|
||||
case Node::KAbiTagAttr:
|
||||
Name = static_cast<const AbiTagAttr *>(Name)->Base;
|
||||
continue;
|
||||
case Node::KStdQualifiedName:
|
||||
Name = static_cast<const StdQualifiedName *>(Name)->Child;
|
||||
case Node::KModuleEntity:
|
||||
Name = static_cast<const ModuleEntity *>(Name)->Name;
|
||||
continue;
|
||||
case Node::KNestedName:
|
||||
Name = static_cast<const NestedName *>(Name)->Name;
|
||||
@ -441,9 +456,7 @@ char *ItaniumPartialDemangler::getFunctionDeclContextName(char *Buf,
|
||||
return nullptr;
|
||||
const Node *Name = static_cast<const FunctionEncoding *>(RootNode)->getName();
|
||||
|
||||
OutputStream S;
|
||||
if (!initializeOutputStream(Buf, N, S, 128))
|
||||
return nullptr;
|
||||
OutputBuffer OB(Buf, N);
|
||||
|
||||
KeepGoingLocalFunction:
|
||||
while (true) {
|
||||
@ -458,27 +471,27 @@ char *ItaniumPartialDemangler::getFunctionDeclContextName(char *Buf,
|
||||
break;
|
||||
}
|
||||
|
||||
if (Name->getKind() == Node::KModuleEntity)
|
||||
Name = static_cast<const ModuleEntity *>(Name)->Name;
|
||||
|
||||
switch (Name->getKind()) {
|
||||
case Node::KStdQualifiedName:
|
||||
S += "std";
|
||||
break;
|
||||
case Node::KNestedName:
|
||||
static_cast<const NestedName *>(Name)->Qual->print(S);
|
||||
static_cast<const NestedName *>(Name)->Qual->print(OB);
|
||||
break;
|
||||
case Node::KLocalName: {
|
||||
auto *LN = static_cast<const LocalName *>(Name);
|
||||
LN->Encoding->print(S);
|
||||
S += "::";
|
||||
LN->Encoding->print(OB);
|
||||
OB += "::";
|
||||
Name = LN->Entity;
|
||||
goto KeepGoingLocalFunction;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
S += '\0';
|
||||
OB += '\0';
|
||||
if (N != nullptr)
|
||||
*N = S.getCurrentPosition();
|
||||
return S.getBuffer();
|
||||
*N = OB.getCurrentPosition();
|
||||
return OB.getBuffer();
|
||||
}
|
||||
|
||||
char *ItaniumPartialDemangler::getFunctionName(char *Buf, size_t *N) const {
|
||||
@ -494,17 +507,15 @@ char *ItaniumPartialDemangler::getFunctionParameters(char *Buf,
|
||||
return nullptr;
|
||||
NodeArray Params = static_cast<FunctionEncoding *>(RootNode)->getParams();
|
||||
|
||||
OutputStream S;
|
||||
if (!initializeOutputStream(Buf, N, S, 128))
|
||||
return nullptr;
|
||||
OutputBuffer OB(Buf, N);
|
||||
|
||||
S += '(';
|
||||
Params.printWithComma(S);
|
||||
S += ')';
|
||||
S += '\0';
|
||||
OB += '(';
|
||||
Params.printWithComma(OB);
|
||||
OB += ')';
|
||||
OB += '\0';
|
||||
if (N != nullptr)
|
||||
*N = S.getCurrentPosition();
|
||||
return S.getBuffer();
|
||||
*N = OB.getCurrentPosition();
|
||||
return OB.getBuffer();
|
||||
}
|
||||
|
||||
char *ItaniumPartialDemangler::getFunctionReturnType(
|
||||
@ -512,18 +523,16 @@ char *ItaniumPartialDemangler::getFunctionReturnType(
|
||||
if (!isFunction())
|
||||
return nullptr;
|
||||
|
||||
OutputStream S;
|
||||
if (!initializeOutputStream(Buf, N, S, 128))
|
||||
return nullptr;
|
||||
OutputBuffer OB(Buf, N);
|
||||
|
||||
if (const Node *Ret =
|
||||
static_cast<const FunctionEncoding *>(RootNode)->getReturnType())
|
||||
Ret->print(S);
|
||||
Ret->print(OB);
|
||||
|
||||
S += '\0';
|
||||
OB += '\0';
|
||||
if (N != nullptr)
|
||||
*N = S.getCurrentPosition();
|
||||
return S.getBuffer();
|
||||
*N = OB.getCurrentPosition();
|
||||
return OB.getBuffer();
|
||||
}
|
||||
|
||||
char *ItaniumPartialDemangler::finishDemangle(char *Buf, size_t *N) const {
|
||||
@ -563,8 +572,8 @@ bool ItaniumPartialDemangler::isCtorOrDtor() const {
|
||||
case Node::KNestedName:
|
||||
N = static_cast<const NestedName *>(N)->Name;
|
||||
break;
|
||||
case Node::KStdQualifiedName:
|
||||
N = static_cast<const StdQualifiedName *>(N)->Child;
|
||||
case Node::KModuleEntity:
|
||||
N = static_cast<const ModuleEntity *>(N)->Name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
37
externals/demangle/llvm/Demangle/Demangle.h
vendored
37
externals/demangle/llvm/Demangle/Demangle.h
vendored
@ -12,6 +12,7 @@
|
||||
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
namespace llvm {
|
||||
/// This is a llvm local version of __cxa_demangle. Other than the name and
|
||||
@ -29,9 +30,10 @@ enum : int {
|
||||
demangle_success = 0,
|
||||
};
|
||||
|
||||
char *itaniumDemangle(const char *mangled_name, char *buf, size_t *n,
|
||||
int *status);
|
||||
|
||||
/// Returns a non-NULL pointer to a NUL-terminated C style string
|
||||
/// that should be explicitly freed, if successful. Otherwise, may return
|
||||
/// nullptr if mangled_name is not a valid mangling or is nullptr.
|
||||
char *itaniumDemangle(std::string_view mangled_name);
|
||||
|
||||
enum MSDemangleFlags {
|
||||
MSDF_None = 0,
|
||||
@ -40,10 +42,34 @@ enum MSDemangleFlags {
|
||||
MSDF_NoCallingConvention = 1 << 2,
|
||||
MSDF_NoReturnType = 1 << 3,
|
||||
MSDF_NoMemberType = 1 << 4,
|
||||
MSDF_NoVariableType = 1 << 5,
|
||||
};
|
||||
char *microsoftDemangle(const char *mangled_name, char *buf, size_t *n,
|
||||
|
||||
/// Demangles the Microsoft symbol pointed at by mangled_name and returns it.
|
||||
/// Returns a pointer to the start of a null-terminated demangled string on
|
||||
/// success, or nullptr on error.
|
||||
/// If n_read is non-null and demangling was successful, it receives how many
|
||||
/// bytes of the input string were consumed.
|
||||
/// status receives one of the demangle_ enum entries above if it's not nullptr.
|
||||
/// Flags controls various details of the demangled representation.
|
||||
char *microsoftDemangle(std::string_view mangled_name, size_t *n_read,
|
||||
int *status, MSDemangleFlags Flags = MSDF_None);
|
||||
|
||||
// Demangles a Rust v0 mangled symbol.
|
||||
char *rustDemangle(std::string_view MangledName);
|
||||
|
||||
// Demangles a D mangled symbol.
|
||||
char *dlangDemangle(std::string_view MangledName);
|
||||
|
||||
/// Attempt to demangle a string using different demangling schemes.
|
||||
/// The function uses heuristics to determine which demangling scheme to use.
|
||||
/// \param MangledName - reference to string to demangle.
|
||||
/// \returns - the demangled string, or a copy of the input string if no
|
||||
/// demangling occurred.
|
||||
std::string demangle(std::string_view MangledName);
|
||||
|
||||
bool nonMicrosoftDemangle(std::string_view MangledName, std::string &Result);
|
||||
|
||||
/// "Partial" demangler. This supports demangling a string into an AST
|
||||
/// (typically an intermediate stage in itaniumDemangle) and querying certain
|
||||
/// properties or partially printing the demangled name.
|
||||
@ -59,7 +85,7 @@ struct ItaniumPartialDemangler {
|
||||
bool partialDemangle(const char *MangledName);
|
||||
|
||||
/// Just print the entire mangled name into Buf. Buf and N behave like the
|
||||
/// second and third parameters to itaniumDemangle.
|
||||
/// second and third parameters to __cxa_demangle.
|
||||
char *finishDemangle(char *Buf, size_t *N) const;
|
||||
|
||||
/// Get the base name of a function. This doesn't include trailing template
|
||||
@ -95,6 +121,7 @@ struct ItaniumPartialDemangler {
|
||||
bool isSpecialName() const;
|
||||
|
||||
~ItaniumPartialDemangler();
|
||||
|
||||
private:
|
||||
void *RootNode;
|
||||
void *Context;
|
||||
|
@ -13,8 +13,8 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_DEMANGLE_COMPILER_H
|
||||
#define LLVM_DEMANGLE_COMPILER_H
|
||||
#ifndef LLVM_DEMANGLE_DEMANGLECONFIG_H
|
||||
#define LLVM_DEMANGLE_DEMANGLECONFIG_H
|
||||
|
||||
#ifndef __has_feature
|
||||
#define __has_feature(x) 0
|
||||
|
3910
externals/demangle/llvm/Demangle/ItaniumDemangle.h
vendored
3910
externals/demangle/llvm/Demangle/ItaniumDemangle.h
vendored
File diff suppressed because it is too large
Load Diff
96
externals/demangle/llvm/Demangle/ItaniumNodes.def
vendored
Executable file
96
externals/demangle/llvm/Demangle/ItaniumNodes.def
vendored
Executable file
@ -0,0 +1,96 @@
|
||||
//===--- ItaniumNodes.def ------------*- mode:c++;eval:(read-only-mode) -*-===//
|
||||
// Do not edit! See README.txt.
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-FileCopyrightText: Part of the LLVM Project
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Define the demangler's node names
|
||||
|
||||
#ifndef NODE
|
||||
#error Define NODE to handle nodes
|
||||
#endif
|
||||
|
||||
NODE(NodeArrayNode)
|
||||
NODE(DotSuffix)
|
||||
NODE(VendorExtQualType)
|
||||
NODE(QualType)
|
||||
NODE(ConversionOperatorType)
|
||||
NODE(PostfixQualifiedType)
|
||||
NODE(ElaboratedTypeSpefType)
|
||||
NODE(NameType)
|
||||
NODE(AbiTagAttr)
|
||||
NODE(EnableIfAttr)
|
||||
NODE(ObjCProtoName)
|
||||
NODE(PointerType)
|
||||
NODE(ReferenceType)
|
||||
NODE(PointerToMemberType)
|
||||
NODE(ArrayType)
|
||||
NODE(FunctionType)
|
||||
NODE(NoexceptSpec)
|
||||
NODE(DynamicExceptionSpec)
|
||||
NODE(FunctionEncoding)
|
||||
NODE(LiteralOperator)
|
||||
NODE(SpecialName)
|
||||
NODE(CtorVtableSpecialName)
|
||||
NODE(QualifiedName)
|
||||
NODE(NestedName)
|
||||
NODE(LocalName)
|
||||
NODE(ModuleName)
|
||||
NODE(ModuleEntity)
|
||||
NODE(VectorType)
|
||||
NODE(PixelVectorType)
|
||||
NODE(BinaryFPType)
|
||||
NODE(BitIntType)
|
||||
NODE(SyntheticTemplateParamName)
|
||||
NODE(TypeTemplateParamDecl)
|
||||
NODE(NonTypeTemplateParamDecl)
|
||||
NODE(TemplateTemplateParamDecl)
|
||||
NODE(TemplateParamPackDecl)
|
||||
NODE(ParameterPack)
|
||||
NODE(TemplateArgumentPack)
|
||||
NODE(ParameterPackExpansion)
|
||||
NODE(TemplateArgs)
|
||||
NODE(ForwardTemplateReference)
|
||||
NODE(NameWithTemplateArgs)
|
||||
NODE(GlobalQualifiedName)
|
||||
NODE(ExpandedSpecialSubstitution)
|
||||
NODE(SpecialSubstitution)
|
||||
NODE(CtorDtorName)
|
||||
NODE(DtorName)
|
||||
NODE(UnnamedTypeName)
|
||||
NODE(ClosureTypeName)
|
||||
NODE(StructuredBindingName)
|
||||
NODE(BinaryExpr)
|
||||
NODE(ArraySubscriptExpr)
|
||||
NODE(PostfixExpr)
|
||||
NODE(ConditionalExpr)
|
||||
NODE(MemberExpr)
|
||||
NODE(SubobjectExpr)
|
||||
NODE(EnclosingExpr)
|
||||
NODE(CastExpr)
|
||||
NODE(SizeofParamPackExpr)
|
||||
NODE(CallExpr)
|
||||
NODE(NewExpr)
|
||||
NODE(DeleteExpr)
|
||||
NODE(PrefixExpr)
|
||||
NODE(FunctionParam)
|
||||
NODE(ConversionExpr)
|
||||
NODE(PointerToMemberConversionExpr)
|
||||
NODE(InitListExpr)
|
||||
NODE(FoldExpr)
|
||||
NODE(ThrowExpr)
|
||||
NODE(BoolExpr)
|
||||
NODE(StringLiteral)
|
||||
NODE(LambdaExpr)
|
||||
NODE(EnumLiteral)
|
||||
NODE(IntegerLiteral)
|
||||
NODE(FloatLiteral)
|
||||
NODE(DoubleLiteral)
|
||||
NODE(LongDoubleLiteral)
|
||||
NODE(BracedExpr)
|
||||
NODE(BracedRangeExpr)
|
||||
|
||||
#undef NODE
|
32
externals/demangle/llvm/Demangle/StringView.h
vendored
32
externals/demangle/llvm/Demangle/StringView.h
vendored
@ -1,5 +1,5 @@
|
||||
//===--- StringView.h -------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
//===--- StringView.h ----------------*- mode:c++;eval:(read-only-mode) -*-===//
|
||||
// Do not edit! See README.txt.
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-FileCopyrightText: Part of the LLVM Project
|
||||
@ -8,6 +8,9 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// FIXME: Use std::string_view instead when we support C++17.
|
||||
// There are two copies of this file in the source tree. The one under
|
||||
// libcxxabi is the original and the one under llvm is the copy. Use
|
||||
// cp-to-llvm.sh to update the copy. See README.txt for more details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@ -15,7 +18,6 @@
|
||||
#define DEMANGLE_STRINGVIEW_H
|
||||
|
||||
#include "DemangleConfig.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
@ -37,29 +39,23 @@ public:
|
||||
StringView(const char *Str) : First(Str), Last(Str + std::strlen(Str)) {}
|
||||
StringView() : First(nullptr), Last(nullptr) {}
|
||||
|
||||
StringView substr(size_t From) const {
|
||||
return StringView(begin() + From, size() - From);
|
||||
StringView substr(size_t Pos, size_t Len = npos) const {
|
||||
assert(Pos <= size());
|
||||
if (Len > size() - Pos)
|
||||
Len = size() - Pos;
|
||||
return StringView(begin() + Pos, Len);
|
||||
}
|
||||
|
||||
size_t find(char C, size_t From = 0) const {
|
||||
size_t FindBegin = std::min(From, size());
|
||||
// Avoid calling memchr with nullptr.
|
||||
if (FindBegin < size()) {
|
||||
if (From < size()) {
|
||||
// Just forward to memchr, which is faster than a hand-rolled loop.
|
||||
if (const void *P = ::memchr(First + FindBegin, C, size() - FindBegin))
|
||||
if (const void *P = ::memchr(First + From, C, size() - From))
|
||||
return size_t(static_cast<const char *>(P) - First);
|
||||
}
|
||||
return npos;
|
||||
}
|
||||
|
||||
StringView substr(size_t From, size_t To) const {
|
||||
if (To >= size())
|
||||
To = size() - 1;
|
||||
if (From >= size())
|
||||
From = size() - 1;
|
||||
return StringView(First + From, First + To);
|
||||
}
|
||||
|
||||
StringView dropFront(size_t N = 1) const {
|
||||
if (N >= size())
|
||||
N = size();
|
||||
@ -106,7 +102,7 @@ public:
|
||||
bool startsWith(StringView Str) const {
|
||||
if (Str.size() > size())
|
||||
return false;
|
||||
return std::equal(Str.begin(), Str.end(), begin());
|
||||
return std::strncmp(Str.begin(), begin(), Str.size()) == 0;
|
||||
}
|
||||
|
||||
const char &operator[](size_t Idx) const { return *(begin() + Idx); }
|
||||
@ -119,7 +115,7 @@ public:
|
||||
|
||||
inline bool operator==(const StringView &LHS, const StringView &RHS) {
|
||||
return LHS.size() == RHS.size() &&
|
||||
std::equal(LHS.begin(), LHS.end(), RHS.begin());
|
||||
std::strncmp(LHS.begin(), RHS.begin(), LHS.size()) == 0;
|
||||
}
|
||||
|
||||
DEMANGLE_NAMESPACE_END
|
||||
|
39
externals/demangle/llvm/Demangle/StringViewExtras.h
vendored
Executable file
39
externals/demangle/llvm/Demangle/StringViewExtras.h
vendored
Executable file
@ -0,0 +1,39 @@
|
||||
//===--- StringViewExtras.h ----------*- mode:c++;eval:(read-only-mode) -*-===//
|
||||
// Do not edit! See README.txt.
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-FileCopyrightText: Part of the LLVM Project
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// There are two copies of this file in the source tree. The one under
|
||||
// libcxxabi is the original and the one under llvm is the copy. Use
|
||||
// cp-to-llvm.sh to update the copy. See README.txt for more details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef DEMANGLE_STRINGVIEW_H
|
||||
#define DEMANGLE_STRINGVIEW_H
|
||||
|
||||
#include "DemangleConfig.h"
|
||||
|
||||
#include <string_view>
|
||||
|
||||
DEMANGLE_NAMESPACE_BEGIN
|
||||
|
||||
inline bool starts_with(std::string_view self, char C) noexcept {
|
||||
return !self.empty() && *self.begin() == C;
|
||||
}
|
||||
|
||||
inline bool starts_with(std::string_view haystack,
|
||||
std::string_view needle) noexcept {
|
||||
if (needle.size() > haystack.size())
|
||||
return false;
|
||||
haystack.remove_suffix(haystack.size() - needle.size());
|
||||
return haystack == needle;
|
||||
}
|
||||
|
||||
DEMANGLE_NAMESPACE_END
|
||||
|
||||
#endif
|
208
externals/demangle/llvm/Demangle/Utility.h
vendored
208
externals/demangle/llvm/Demangle/Utility.h
vendored
@ -1,5 +1,5 @@
|
||||
//===--- Utility.h ----------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
//===--- Utility.h -------------------*- mode:c++;eval:(read-only-mode) -*-===//
|
||||
// Do not edit! See README.txt.
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-FileCopyrightText: Part of the LLVM Project
|
||||
@ -7,70 +7,83 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Provide some utility classes for use in the demangler(s).
|
||||
// Provide some utility classes for use in the demangler.
|
||||
// There are two copies of this file in the source tree. The one in libcxxabi
|
||||
// is the original and the one in llvm is the copy. Use cp-to-llvm.sh to update
|
||||
// the copy. See README.txt for more details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef DEMANGLE_UTILITY_H
|
||||
#define DEMANGLE_UTILITY_H
|
||||
|
||||
#include "StringView.h"
|
||||
#include "DemangleConfig.h"
|
||||
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <iterator>
|
||||
#include <exception>
|
||||
#include <limits>
|
||||
#include <string_view>
|
||||
|
||||
DEMANGLE_NAMESPACE_BEGIN
|
||||
|
||||
// Stream that AST nodes write their string representation into after the AST
|
||||
// has been parsed.
|
||||
class OutputStream {
|
||||
char *Buffer;
|
||||
size_t CurrentPosition;
|
||||
size_t BufferCapacity;
|
||||
class OutputBuffer {
|
||||
char *Buffer = nullptr;
|
||||
size_t CurrentPosition = 0;
|
||||
size_t BufferCapacity = 0;
|
||||
|
||||
// Ensure there is at least n more positions in buffer.
|
||||
// Ensure there are at least N more positions in the buffer.
|
||||
void grow(size_t N) {
|
||||
if (N + CurrentPosition >= BufferCapacity) {
|
||||
size_t Need = N + CurrentPosition;
|
||||
if (Need > BufferCapacity) {
|
||||
// Reduce the number of reallocations, with a bit of hysteresis. The
|
||||
// number here is chosen so the first allocation will more-than-likely not
|
||||
// allocate more than 1K.
|
||||
Need += 1024 - 32;
|
||||
BufferCapacity *= 2;
|
||||
if (BufferCapacity < N + CurrentPosition)
|
||||
BufferCapacity = N + CurrentPosition;
|
||||
if (BufferCapacity < Need)
|
||||
BufferCapacity = Need;
|
||||
Buffer = static_cast<char *>(std::realloc(Buffer, BufferCapacity));
|
||||
if (Buffer == nullptr)
|
||||
std::terminate();
|
||||
}
|
||||
}
|
||||
|
||||
void writeUnsigned(uint64_t N, bool isNeg = false) {
|
||||
// Handle special case...
|
||||
if (N == 0) {
|
||||
*this << '0';
|
||||
return;
|
||||
}
|
||||
OutputBuffer &writeUnsigned(uint64_t N, bool isNeg = false) {
|
||||
std::array<char, 21> Temp;
|
||||
char *TempPtr = Temp.data() + Temp.size();
|
||||
|
||||
char Temp[21];
|
||||
char *TempPtr = std::end(Temp);
|
||||
|
||||
while (N) {
|
||||
*--TempPtr = '0' + char(N % 10);
|
||||
// Output at least one character.
|
||||
do {
|
||||
*--TempPtr = char('0' + N % 10);
|
||||
N /= 10;
|
||||
}
|
||||
} while (N);
|
||||
|
||||
// Add negative sign...
|
||||
// Add negative sign.
|
||||
if (isNeg)
|
||||
*--TempPtr = '-';
|
||||
this->operator<<(StringView(TempPtr, std::end(Temp)));
|
||||
|
||||
return operator+=(
|
||||
std::string_view(TempPtr, Temp.data() + Temp.size() - TempPtr));
|
||||
}
|
||||
|
||||
public:
|
||||
OutputStream(char *StartBuf, size_t Size)
|
||||
: Buffer(StartBuf), CurrentPosition(0), BufferCapacity(Size) {}
|
||||
OutputStream() = default;
|
||||
void reset(char *Buffer_, size_t BufferCapacity_) {
|
||||
CurrentPosition = 0;
|
||||
Buffer = Buffer_;
|
||||
BufferCapacity = BufferCapacity_;
|
||||
OutputBuffer(char *StartBuf, size_t Size)
|
||||
: Buffer(StartBuf), BufferCapacity(Size) {}
|
||||
OutputBuffer(char *StartBuf, size_t *SizePtr)
|
||||
: OutputBuffer(StartBuf, StartBuf ? *SizePtr : 0) {}
|
||||
OutputBuffer() = default;
|
||||
// Non-copyable
|
||||
OutputBuffer(const OutputBuffer &) = delete;
|
||||
OutputBuffer &operator=(const OutputBuffer &) = delete;
|
||||
|
||||
operator std::string_view() const {
|
||||
return std::string_view(Buffer, CurrentPosition);
|
||||
}
|
||||
|
||||
/// If a ParameterPackExpansion (or similar type) is encountered, the offset
|
||||
@ -78,115 +91,116 @@ public:
|
||||
unsigned CurrentPackIndex = std::numeric_limits<unsigned>::max();
|
||||
unsigned CurrentPackMax = std::numeric_limits<unsigned>::max();
|
||||
|
||||
OutputStream &operator+=(StringView R) {
|
||||
size_t Size = R.size();
|
||||
if (Size == 0)
|
||||
return *this;
|
||||
grow(Size);
|
||||
std::memmove(Buffer + CurrentPosition, R.begin(), Size);
|
||||
CurrentPosition += Size;
|
||||
/// When zero, we're printing template args and '>' needs to be parenthesized.
|
||||
/// Use a counter so we can simply increment inside parentheses.
|
||||
unsigned GtIsGt = 1;
|
||||
|
||||
bool isGtInsideTemplateArgs() const { return GtIsGt == 0; }
|
||||
|
||||
void printOpen(char Open = '(') {
|
||||
GtIsGt++;
|
||||
*this += Open;
|
||||
}
|
||||
void printClose(char Close = ')') {
|
||||
GtIsGt--;
|
||||
*this += Close;
|
||||
}
|
||||
|
||||
OutputBuffer &operator+=(std::string_view R) {
|
||||
if (size_t Size = R.size()) {
|
||||
grow(Size);
|
||||
std::memcpy(Buffer + CurrentPosition, &*R.begin(), Size);
|
||||
CurrentPosition += Size;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
OutputStream &operator+=(char C) {
|
||||
OutputBuffer &operator+=(char C) {
|
||||
grow(1);
|
||||
Buffer[CurrentPosition++] = C;
|
||||
return *this;
|
||||
}
|
||||
|
||||
OutputStream &operator<<(StringView R) { return (*this += R); }
|
||||
OutputBuffer &prepend(std::string_view R) {
|
||||
size_t Size = R.size();
|
||||
|
||||
OutputStream &operator<<(char C) { return (*this += C); }
|
||||
grow(Size);
|
||||
std::memmove(Buffer + Size, Buffer, CurrentPosition);
|
||||
std::memcpy(Buffer, &*R.begin(), Size);
|
||||
CurrentPosition += Size;
|
||||
|
||||
OutputStream &operator<<(long long N) {
|
||||
if (N < 0)
|
||||
writeUnsigned(static_cast<unsigned long long>(-N), true);
|
||||
else
|
||||
writeUnsigned(static_cast<unsigned long long>(N));
|
||||
return *this;
|
||||
}
|
||||
|
||||
OutputStream &operator<<(unsigned long long N) {
|
||||
writeUnsigned(N, false);
|
||||
return *this;
|
||||
OutputBuffer &operator<<(std::string_view R) { return (*this += R); }
|
||||
|
||||
OutputBuffer &operator<<(char C) { return (*this += C); }
|
||||
|
||||
OutputBuffer &operator<<(long long N) {
|
||||
return writeUnsigned(static_cast<unsigned long long>(std::abs(N)), N < 0);
|
||||
}
|
||||
|
||||
OutputStream &operator<<(long N) {
|
||||
OutputBuffer &operator<<(unsigned long long N) {
|
||||
return writeUnsigned(N, false);
|
||||
}
|
||||
|
||||
OutputBuffer &operator<<(long N) {
|
||||
return this->operator<<(static_cast<long long>(N));
|
||||
}
|
||||
|
||||
OutputStream &operator<<(unsigned long N) {
|
||||
OutputBuffer &operator<<(unsigned long N) {
|
||||
return this->operator<<(static_cast<unsigned long long>(N));
|
||||
}
|
||||
|
||||
OutputStream &operator<<(int N) {
|
||||
OutputBuffer &operator<<(int N) {
|
||||
return this->operator<<(static_cast<long long>(N));
|
||||
}
|
||||
|
||||
OutputStream &operator<<(unsigned int N) {
|
||||
OutputBuffer &operator<<(unsigned int N) {
|
||||
return this->operator<<(static_cast<unsigned long long>(N));
|
||||
}
|
||||
|
||||
void insert(size_t Pos, const char *S, size_t N) {
|
||||
assert(Pos <= CurrentPosition);
|
||||
if (N == 0)
|
||||
return;
|
||||
grow(N);
|
||||
std::memmove(Buffer + Pos + N, Buffer + Pos, CurrentPosition - Pos);
|
||||
std::memcpy(Buffer + Pos, S, N);
|
||||
CurrentPosition += N;
|
||||
}
|
||||
|
||||
size_t getCurrentPosition() const { return CurrentPosition; }
|
||||
void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; }
|
||||
|
||||
char back() const {
|
||||
return CurrentPosition ? Buffer[CurrentPosition - 1] : '\0';
|
||||
assert(CurrentPosition);
|
||||
return Buffer[CurrentPosition - 1];
|
||||
}
|
||||
|
||||
bool empty() const { return CurrentPosition == 0; }
|
||||
|
||||
char *getBuffer() { return Buffer; }
|
||||
char *getBufferEnd() { return Buffer + CurrentPosition - 1; }
|
||||
size_t getBufferCapacity() { return BufferCapacity; }
|
||||
size_t getBufferCapacity() const { return BufferCapacity; }
|
||||
};
|
||||
|
||||
template <class T> class SwapAndRestore {
|
||||
T &Restore;
|
||||
T OriginalValue;
|
||||
bool ShouldRestore = true;
|
||||
template <class T> class ScopedOverride {
|
||||
T &Loc;
|
||||
T Original;
|
||||
|
||||
public:
|
||||
SwapAndRestore(T &Restore_) : SwapAndRestore(Restore_, Restore_) {}
|
||||
ScopedOverride(T &Loc_) : ScopedOverride(Loc_, Loc_) {}
|
||||
|
||||
SwapAndRestore(T &Restore_, T NewVal)
|
||||
: Restore(Restore_), OriginalValue(Restore) {
|
||||
Restore = std::move(NewVal);
|
||||
}
|
||||
~SwapAndRestore() {
|
||||
if (ShouldRestore)
|
||||
Restore = std::move(OriginalValue);
|
||||
ScopedOverride(T &Loc_, T NewVal) : Loc(Loc_), Original(Loc_) {
|
||||
Loc_ = std::move(NewVal);
|
||||
}
|
||||
~ScopedOverride() { Loc = std::move(Original); }
|
||||
|
||||
void shouldRestore(bool ShouldRestore_) { ShouldRestore = ShouldRestore_; }
|
||||
|
||||
void restoreNow(bool Force) {
|
||||
if (!Force && !ShouldRestore)
|
||||
return;
|
||||
|
||||
Restore = std::move(OriginalValue);
|
||||
ShouldRestore = false;
|
||||
}
|
||||
|
||||
SwapAndRestore(const SwapAndRestore &) = delete;
|
||||
SwapAndRestore &operator=(const SwapAndRestore &) = delete;
|
||||
ScopedOverride(const ScopedOverride &) = delete;
|
||||
ScopedOverride &operator=(const ScopedOverride &) = delete;
|
||||
};
|
||||
|
||||
inline bool initializeOutputStream(char *Buf, size_t *N, OutputStream &S,
|
||||
size_t InitSize) {
|
||||
size_t BufferSize;
|
||||
if (Buf == nullptr) {
|
||||
Buf = static_cast<char *>(std::malloc(InitSize));
|
||||
if (Buf == nullptr)
|
||||
return false;
|
||||
BufferSize = InitSize;
|
||||
} else
|
||||
BufferSize = *N;
|
||||
|
||||
S.reset(Buf, BufferSize);
|
||||
return true;
|
||||
}
|
||||
|
||||
DEMANGLE_NAMESPACE_END
|
||||
|
||||
#endif
|
||||
|
@ -12,6 +12,7 @@ import androidx.core.content.res.ResourcesCompat
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.yuzu.yuzu_emu.R
|
||||
import org.yuzu.yuzu_emu.databinding.CardHomeOptionBinding
|
||||
import org.yuzu.yuzu_emu.fragments.MessageDialogFragment
|
||||
import org.yuzu.yuzu_emu.model.HomeSetting
|
||||
|
||||
class HomeSettingAdapter(private val activity: AppCompatActivity, var options: List<HomeSetting>) :
|
||||
@ -34,7 +35,14 @@ class HomeSettingAdapter(private val activity: AppCompatActivity, var options: L
|
||||
|
||||
override fun onClick(view: View) {
|
||||
val holder = view.tag as HomeOptionViewHolder
|
||||
holder.option.onClick.invoke()
|
||||
if (holder.option.isEnabled.invoke()) {
|
||||
holder.option.onClick.invoke()
|
||||
} else {
|
||||
MessageDialogFragment.newInstance(
|
||||
holder.option.disabledTitleId,
|
||||
holder.option.disabledMessageId
|
||||
).show(activity.supportFragmentManager, MessageDialogFragment.TAG)
|
||||
}
|
||||
}
|
||||
|
||||
inner class HomeOptionViewHolder(val binding: CardHomeOptionBinding) :
|
||||
@ -65,6 +73,12 @@ class HomeSettingAdapter(private val activity: AppCompatActivity, var options: L
|
||||
R.drawable.premium_background
|
||||
)
|
||||
}
|
||||
|
||||
if (!option.isEnabled.invoke()) {
|
||||
binding.optionTitle.alpha = 0.5f
|
||||
binding.optionDescription.alpha = 0.5f
|
||||
binding.optionIcon.alpha = 0.5f
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -73,102 +73,113 @@ class HomeSettingsFragment : Fragment() {
|
||||
HomeSetting(
|
||||
R.string.advanced_settings,
|
||||
R.string.settings_description,
|
||||
R.drawable.ic_settings
|
||||
) { SettingsActivity.launch(requireContext(), SettingsFile.FILE_NAME_CONFIG, "") }
|
||||
R.drawable.ic_settings,
|
||||
{ SettingsActivity.launch(requireContext(), SettingsFile.FILE_NAME_CONFIG, "") }
|
||||
)
|
||||
)
|
||||
add(
|
||||
HomeSetting(
|
||||
R.string.open_user_folder,
|
||||
R.string.open_user_folder_description,
|
||||
R.drawable.ic_folder_open
|
||||
) { openFileManager() }
|
||||
R.drawable.ic_folder_open,
|
||||
{ openFileManager() }
|
||||
)
|
||||
)
|
||||
add(
|
||||
HomeSetting(
|
||||
R.string.preferences_theme,
|
||||
R.string.theme_and_color_description,
|
||||
R.drawable.ic_palette
|
||||
) { SettingsActivity.launch(requireContext(), Settings.SECTION_THEME, "") }
|
||||
)
|
||||
|
||||
if (GpuDriverHelper.supportsCustomDriverLoading()) {
|
||||
add(
|
||||
HomeSetting(
|
||||
R.string.install_gpu_driver,
|
||||
R.string.install_gpu_driver_description,
|
||||
R.drawable.ic_exit
|
||||
) { driverInstaller() }
|
||||
R.drawable.ic_palette,
|
||||
{ SettingsActivity.launch(requireContext(), Settings.SECTION_THEME, "") }
|
||||
)
|
||||
}
|
||||
|
||||
)
|
||||
add(
|
||||
HomeSetting(
|
||||
R.string.install_gpu_driver,
|
||||
R.string.install_gpu_driver_description,
|
||||
R.drawable.ic_exit,
|
||||
{ driverInstaller() },
|
||||
{ GpuDriverHelper.supportsCustomDriverLoading() },
|
||||
R.string.custom_driver_not_supported,
|
||||
R.string.custom_driver_not_supported_description
|
||||
)
|
||||
)
|
||||
add(
|
||||
HomeSetting(
|
||||
R.string.install_amiibo_keys,
|
||||
R.string.install_amiibo_keys_description,
|
||||
R.drawable.ic_nfc
|
||||
) { mainActivity.getAmiiboKey.launch(arrayOf("*/*")) }
|
||||
R.drawable.ic_nfc,
|
||||
{ mainActivity.getAmiiboKey.launch(arrayOf("*/*")) }
|
||||
)
|
||||
)
|
||||
add(
|
||||
HomeSetting(
|
||||
R.string.install_game_content,
|
||||
R.string.install_game_content_description,
|
||||
R.drawable.ic_system_update_alt
|
||||
) { mainActivity.installGameUpdate.launch(arrayOf("*/*")) }
|
||||
R.drawable.ic_system_update_alt,
|
||||
{ mainActivity.installGameUpdate.launch(arrayOf("*/*")) }
|
||||
)
|
||||
)
|
||||
add(
|
||||
HomeSetting(
|
||||
R.string.select_games_folder,
|
||||
R.string.select_games_folder_description,
|
||||
R.drawable.ic_add
|
||||
) {
|
||||
mainActivity.getGamesDirectory.launch(
|
||||
Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).data
|
||||
)
|
||||
}
|
||||
R.drawable.ic_add,
|
||||
{
|
||||
mainActivity.getGamesDirectory.launch(
|
||||
Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).data
|
||||
)
|
||||
}
|
||||
)
|
||||
)
|
||||
add(
|
||||
HomeSetting(
|
||||
R.string.manage_save_data,
|
||||
R.string.import_export_saves_description,
|
||||
R.drawable.ic_save
|
||||
) {
|
||||
ImportExportSavesFragment().show(
|
||||
parentFragmentManager,
|
||||
ImportExportSavesFragment.TAG
|
||||
)
|
||||
}
|
||||
R.drawable.ic_save,
|
||||
{
|
||||
ImportExportSavesFragment().show(
|
||||
parentFragmentManager,
|
||||
ImportExportSavesFragment.TAG
|
||||
)
|
||||
}
|
||||
)
|
||||
)
|
||||
add(
|
||||
HomeSetting(
|
||||
R.string.install_prod_keys,
|
||||
R.string.install_prod_keys_description,
|
||||
R.drawable.ic_unlock
|
||||
) { mainActivity.getProdKey.launch(arrayOf("*/*")) }
|
||||
R.drawable.ic_unlock,
|
||||
{ mainActivity.getProdKey.launch(arrayOf("*/*")) }
|
||||
)
|
||||
)
|
||||
add(
|
||||
HomeSetting(
|
||||
R.string.install_firmware,
|
||||
R.string.install_firmware_description,
|
||||
R.drawable.ic_firmware
|
||||
) { mainActivity.getFirmware.launch(arrayOf("application/zip")) }
|
||||
R.drawable.ic_firmware,
|
||||
{ mainActivity.getFirmware.launch(arrayOf("application/zip")) }
|
||||
)
|
||||
)
|
||||
add(
|
||||
HomeSetting(
|
||||
R.string.share_log,
|
||||
R.string.share_log_description,
|
||||
R.drawable.ic_log
|
||||
) { shareLog() }
|
||||
R.drawable.ic_log,
|
||||
{ shareLog() }
|
||||
)
|
||||
)
|
||||
add(
|
||||
HomeSetting(
|
||||
R.string.about,
|
||||
R.string.about_description,
|
||||
R.drawable.ic_info_outline
|
||||
) {
|
||||
exitTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
|
||||
parentFragmentManager.primaryNavigationFragment?.findNavController()
|
||||
?.navigate(R.id.action_homeSettingsFragment_to_aboutFragment)
|
||||
}
|
||||
R.drawable.ic_info_outline,
|
||||
{
|
||||
exitTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
|
||||
parentFragmentManager.primaryNavigationFragment?.findNavController()
|
||||
?.navigate(R.id.action_homeSettingsFragment_to_aboutFragment)
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@ -178,12 +189,13 @@ class HomeSettingsFragment : Fragment() {
|
||||
HomeSetting(
|
||||
R.string.get_early_access,
|
||||
R.string.get_early_access_description,
|
||||
R.drawable.ic_diamond
|
||||
) {
|
||||
exitTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
|
||||
parentFragmentManager.primaryNavigationFragment?.findNavController()
|
||||
?.navigate(R.id.action_homeSettingsFragment_to_earlyAccessFragment)
|
||||
}
|
||||
R.drawable.ic_diamond,
|
||||
{
|
||||
exitTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
|
||||
parentFragmentManager.primaryNavigationFragment?.findNavController()
|
||||
?.navigate(R.id.action_homeSettingsFragment_to_earlyAccessFragment)
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -7,5 +7,8 @@ data class HomeSetting(
|
||||
val titleId: Int,
|
||||
val descriptionId: Int,
|
||||
val iconId: Int,
|
||||
val onClick: () -> Unit
|
||||
val onClick: () -> Unit,
|
||||
val isEnabled: () -> Boolean = { true },
|
||||
val disabledTitleId: Int = 0,
|
||||
val disabledMessageId: Int = 0
|
||||
)
|
||||
|
@ -113,6 +113,8 @@
|
||||
<string name="install_game_content_success_install">%1$d installed successfully</string>
|
||||
<string name="install_game_content_success_overwrite">%1$d overwritten successfully</string>
|
||||
<string name="install_game_content_help_link">https://yuzu-emu.org/help/quickstart/#dumping-installed-updates</string>
|
||||
<string name="custom_driver_not_supported">Custom drivers not supported</string>
|
||||
<string name="custom_driver_not_supported_description">Custom driver loading isn\'t currently supported for this device.\nCheck this option again in the future to see if support was added!</string>
|
||||
|
||||
<!-- About screen strings -->
|
||||
<string name="gaia_is_not_real">Gaia isn\'t real</string>
|
||||
@ -230,7 +232,7 @@
|
||||
|
||||
<!-- ROM loading errors -->
|
||||
<string name="loader_error_encrypted">Your ROM is encrypted</string>
|
||||
<string name="loader_error_encrypted_roms_description"><![CDATA[Please follow the guides to redump your <a href="https://yuzu-emu.org/help/quickstart/#dumping-cartridge-games">game cartidges</a> or <a href="https://yuzu-emu.org/help/quickstart/#dumping-installed-titles-eshop">installed titles</a>.]]></string>
|
||||
<string name="loader_error_encrypted_roms_description"><![CDATA[Please follow the guides to redump your <a href="https://yuzu-emu.org/help/quickstart/#dumping-physical-titles-game-cards">game cartidges</a> or <a href="https://yuzu-emu.org/help/quickstart/#dumping-digital-titles-eshop">installed titles</a>.]]></string>
|
||||
<string name="loader_error_encrypted_keys_description"><![CDATA[Please ensure your <a href="https://yuzu-emu.org/help/quickstart/#dumping-prodkeys-and-titlekeys">prod.keys</a> file is installed so that games can be decrypted.]]></string>
|
||||
<string name="loader_error_video_core">An error occurred initializing the video core</string>
|
||||
<string name="loader_error_video_core_description">This is usually caused by an incompatible GPU driver. Installing a custom GPU driver may resolve this problem.</string>
|
||||
|
@ -23,7 +23,7 @@ std::string DemangleSymbol(const std::string& mangled) {
|
||||
SCOPE_EXIT({ std::free(demangled); });
|
||||
|
||||
if (is_itanium(mangled)) {
|
||||
demangled = llvm::itaniumDemangle(mangled.c_str(), nullptr, nullptr, nullptr);
|
||||
demangled = llvm::itaniumDemangle(mangled.c_str());
|
||||
}
|
||||
|
||||
if (!demangled) {
|
||||
|
@ -30,8 +30,8 @@ DetachedTasks::~DetachedTasks() {
|
||||
void DetachedTasks::AddTask(std::function<void()> task) {
|
||||
std::unique_lock lock{instance->mutex};
|
||||
++instance->count;
|
||||
std::thread([task{std::move(task)}]() {
|
||||
task();
|
||||
std::thread([task_{std::move(task)}]() {
|
||||
task_();
|
||||
std::unique_lock thread_lock{instance->mutex};
|
||||
--instance->count;
|
||||
std::notify_all_at_thread_exit(instance->cv, std::move(thread_lock));
|
||||
|
@ -3,9 +3,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/common_types.h"
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace Network {
|
||||
|
||||
|
@ -285,6 +285,7 @@ add_library(core STATIC
|
||||
hle/kernel/kernel.cpp
|
||||
hle/kernel/kernel.h
|
||||
hle/kernel/memory_types.h
|
||||
hle/kernel/message_buffer.h
|
||||
hle/kernel/physical_core.cpp
|
||||
hle/kernel/physical_core.h
|
||||
hle/kernel/physical_memory.h
|
||||
@ -875,7 +876,7 @@ elseif (APPLE)
|
||||
elseif (WIN32)
|
||||
target_sources(core PRIVATE
|
||||
hle/service/ssl/ssl_backend_schannel.cpp)
|
||||
target_link_libraries(core PRIVATE secur32)
|
||||
target_link_libraries(core PRIVATE crypt32 secur32)
|
||||
else()
|
||||
target_sources(core PRIVATE
|
||||
hle/service/ssl/ssl_backend_none.cpp)
|
||||
|
@ -20,12 +20,132 @@
|
||||
#include "core/hle/kernel/k_thread.h"
|
||||
#include "core/hle/kernel/k_thread_queue.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
#include "core/hle/kernel/message_buffer.h"
|
||||
#include "core/hle/service/hle_ipc.h"
|
||||
#include "core/hle/service/ipc_helpers.h"
|
||||
#include "core/memory.h"
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
namespace {
|
||||
|
||||
template <bool MoveHandleAllowed>
|
||||
Result ProcessMessageSpecialData(KProcess& dst_process, KProcess& src_process, KThread& src_thread,
|
||||
MessageBuffer& dst_msg, const MessageBuffer& src_msg,
|
||||
MessageBuffer::SpecialHeader& src_special_header) {
|
||||
// Copy the special header to the destination.
|
||||
s32 offset = dst_msg.Set(src_special_header);
|
||||
|
||||
// Copy the process ID.
|
||||
if (src_special_header.GetHasProcessId()) {
|
||||
offset = dst_msg.SetProcessId(offset, src_process.GetProcessId());
|
||||
}
|
||||
|
||||
// Prepare to process handles.
|
||||
auto& dst_handle_table = dst_process.GetHandleTable();
|
||||
auto& src_handle_table = src_process.GetHandleTable();
|
||||
Result result = ResultSuccess;
|
||||
|
||||
// Process copy handles.
|
||||
for (auto i = 0; i < src_special_header.GetCopyHandleCount(); ++i) {
|
||||
// Get the handles.
|
||||
const Handle src_handle = src_msg.GetHandle(offset);
|
||||
Handle dst_handle = Svc::InvalidHandle;
|
||||
|
||||
// If we're in a success state, try to move the handle to the new table.
|
||||
if (R_SUCCEEDED(result) && src_handle != Svc::InvalidHandle) {
|
||||
KScopedAutoObject obj =
|
||||
src_handle_table.GetObjectForIpc(src_handle, std::addressof(src_thread));
|
||||
if (obj.IsNotNull()) {
|
||||
Result add_result =
|
||||
dst_handle_table.Add(std::addressof(dst_handle), obj.GetPointerUnsafe());
|
||||
if (R_FAILED(add_result)) {
|
||||
result = add_result;
|
||||
dst_handle = Svc::InvalidHandle;
|
||||
}
|
||||
} else {
|
||||
result = ResultInvalidHandle;
|
||||
}
|
||||
}
|
||||
|
||||
// Set the handle.
|
||||
offset = dst_msg.SetHandle(offset, dst_handle);
|
||||
}
|
||||
|
||||
// Process move handles.
|
||||
if constexpr (MoveHandleAllowed) {
|
||||
for (auto i = 0; i < src_special_header.GetMoveHandleCount(); ++i) {
|
||||
// Get the handles.
|
||||
const Handle src_handle = src_msg.GetHandle(offset);
|
||||
Handle dst_handle = Svc::InvalidHandle;
|
||||
|
||||
// Whether or not we've succeeded, we need to remove the handles from the source table.
|
||||
if (src_handle != Svc::InvalidHandle) {
|
||||
if (R_SUCCEEDED(result)) {
|
||||
KScopedAutoObject obj =
|
||||
src_handle_table.GetObjectForIpcWithoutPseudoHandle(src_handle);
|
||||
if (obj.IsNotNull()) {
|
||||
Result add_result = dst_handle_table.Add(std::addressof(dst_handle),
|
||||
obj.GetPointerUnsafe());
|
||||
|
||||
src_handle_table.Remove(src_handle);
|
||||
|
||||
if (R_FAILED(add_result)) {
|
||||
result = add_result;
|
||||
dst_handle = Svc::InvalidHandle;
|
||||
}
|
||||
} else {
|
||||
result = ResultInvalidHandle;
|
||||
}
|
||||
} else {
|
||||
src_handle_table.Remove(src_handle);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the handle.
|
||||
offset = dst_msg.SetHandle(offset, dst_handle);
|
||||
}
|
||||
}
|
||||
|
||||
R_RETURN(result);
|
||||
}
|
||||
|
||||
void CleanupSpecialData(KProcess& dst_process, u32* dst_msg_ptr, size_t dst_buffer_size) {
|
||||
// Parse the message.
|
||||
const MessageBuffer dst_msg(dst_msg_ptr, dst_buffer_size);
|
||||
const MessageBuffer::MessageHeader dst_header(dst_msg);
|
||||
const MessageBuffer::SpecialHeader dst_special_header(dst_msg, dst_header);
|
||||
|
||||
// Check that the size is big enough.
|
||||
if (MessageBuffer::GetMessageBufferSize(dst_header, dst_special_header) > dst_buffer_size) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the special header.
|
||||
int offset = dst_msg.Set(dst_special_header);
|
||||
|
||||
// Clear the process id, if needed.
|
||||
if (dst_special_header.GetHasProcessId()) {
|
||||
offset = dst_msg.SetProcessId(offset, 0);
|
||||
}
|
||||
|
||||
// Clear handles, as relevant.
|
||||
auto& dst_handle_table = dst_process.GetHandleTable();
|
||||
for (auto i = 0;
|
||||
i < (dst_special_header.GetCopyHandleCount() + dst_special_header.GetMoveHandleCount());
|
||||
++i) {
|
||||
const Handle handle = dst_msg.GetHandle(offset);
|
||||
|
||||
if (handle != Svc::InvalidHandle) {
|
||||
dst_handle_table.Remove(handle);
|
||||
}
|
||||
|
||||
offset = dst_msg.SetHandle(offset, Svc::InvalidHandle);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
using ThreadQueueImplForKServerSessionRequest = KThreadQueue;
|
||||
|
||||
KServerSession::KServerSession(KernelCore& kernel)
|
||||
@ -223,12 +343,27 @@ Result KServerSession::SendReply(bool is_hle) {
|
||||
// the reply has already been written in this case.
|
||||
} else {
|
||||
Core::Memory::Memory& memory{client_thread->GetOwnerProcess()->GetMemory()};
|
||||
KThread* server_thread{GetCurrentThreadPointer(m_kernel)};
|
||||
KThread* server_thread = GetCurrentThreadPointer(m_kernel);
|
||||
KProcess& src_process = *client_thread->GetOwnerProcess();
|
||||
KProcess& dst_process = *server_thread->GetOwnerProcess();
|
||||
UNIMPLEMENTED_IF(server_thread->GetOwnerProcess() != client_thread->GetOwnerProcess());
|
||||
|
||||
auto* src_msg_buffer = memory.GetPointer(server_thread->GetTlsAddress());
|
||||
auto* dst_msg_buffer = memory.GetPointer(client_message);
|
||||
auto* src_msg_buffer = memory.GetPointer<u32>(server_thread->GetTlsAddress());
|
||||
auto* dst_msg_buffer = memory.GetPointer<u32>(client_message);
|
||||
std::memcpy(dst_msg_buffer, src_msg_buffer, client_buffer_size);
|
||||
|
||||
// Translate special header ad-hoc.
|
||||
MessageBuffer src_msg(src_msg_buffer, client_buffer_size);
|
||||
MessageBuffer::MessageHeader src_header(src_msg);
|
||||
MessageBuffer::SpecialHeader src_special_header(src_msg, src_header);
|
||||
if (src_header.GetHasSpecialHeader()) {
|
||||
MessageBuffer dst_msg(dst_msg_buffer, client_buffer_size);
|
||||
result = ProcessMessageSpecialData<true>(dst_process, src_process, *server_thread,
|
||||
dst_msg, src_msg, src_special_header);
|
||||
if (R_FAILED(result)) {
|
||||
CleanupSpecialData(dst_process, dst_msg_buffer, client_buffer_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result = ResultSessionClosed;
|
||||
@ -330,12 +465,28 @@ Result KServerSession::ReceiveRequest(std::shared_ptr<Service::HLERequestContext
|
||||
->PopulateFromIncomingCommandBuffer(client_thread->GetOwnerProcess()->GetHandleTable(),
|
||||
cmd_buf);
|
||||
} else {
|
||||
KThread* server_thread{GetCurrentThreadPointer(m_kernel)};
|
||||
UNIMPLEMENTED_IF(server_thread->GetOwnerProcess() != client_thread->GetOwnerProcess());
|
||||
KThread* server_thread = GetCurrentThreadPointer(m_kernel);
|
||||
KProcess& src_process = *client_thread->GetOwnerProcess();
|
||||
KProcess& dst_process = *server_thread->GetOwnerProcess();
|
||||
UNIMPLEMENTED_IF(client_thread->GetOwnerProcess() != server_thread->GetOwnerProcess());
|
||||
|
||||
auto* src_msg_buffer = memory.GetPointer(client_message);
|
||||
auto* dst_msg_buffer = memory.GetPointer(server_thread->GetTlsAddress());
|
||||
auto* src_msg_buffer = memory.GetPointer<u32>(client_message);
|
||||
auto* dst_msg_buffer = memory.GetPointer<u32>(server_thread->GetTlsAddress());
|
||||
std::memcpy(dst_msg_buffer, src_msg_buffer, client_buffer_size);
|
||||
|
||||
// Translate special header ad-hoc.
|
||||
// TODO: fix this mess
|
||||
MessageBuffer src_msg(src_msg_buffer, client_buffer_size);
|
||||
MessageBuffer::MessageHeader src_header(src_msg);
|
||||
MessageBuffer::SpecialHeader src_special_header(src_msg, src_header);
|
||||
if (src_header.GetHasSpecialHeader()) {
|
||||
MessageBuffer dst_msg(dst_msg_buffer, client_buffer_size);
|
||||
Result res = ProcessMessageSpecialData<false>(dst_process, src_process, *client_thread,
|
||||
dst_msg, src_msg, src_special_header);
|
||||
if (R_FAILED(res)) {
|
||||
CleanupSpecialData(dst_process, dst_msg_buffer, client_buffer_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We succeeded.
|
||||
|
@ -302,12 +302,12 @@ Result KThread::InitializeServiceThread(Core::System& system, KThread* thread,
|
||||
std::function<void()>&& func, s32 prio, s32 virt_core,
|
||||
KProcess* owner) {
|
||||
system.Kernel().GlobalSchedulerContext().AddThread(thread);
|
||||
std::function<void()> func2{[&system, func{std::move(func)}] {
|
||||
std::function<void()> func2{[&system, func_{std::move(func)}] {
|
||||
// Similar to UserModeThreadStarter.
|
||||
system.Kernel().CurrentScheduler()->OnThreadStart();
|
||||
|
||||
// Run the guest function.
|
||||
func();
|
||||
func_();
|
||||
|
||||
// Exit.
|
||||
Svc::ExitThread(system);
|
||||
|
@ -1089,15 +1089,15 @@ static std::jthread RunHostThreadFunc(KernelCore& kernel, KProcess* process,
|
||||
KThread::Register(kernel, thread);
|
||||
|
||||
return std::jthread(
|
||||
[&kernel, thread, thread_name{std::move(thread_name)}, func{std::move(func)}] {
|
||||
[&kernel, thread, thread_name_{std::move(thread_name)}, func_{std::move(func)}] {
|
||||
// Set the thread name.
|
||||
Common::SetCurrentThreadName(thread_name.c_str());
|
||||
Common::SetCurrentThreadName(thread_name_.c_str());
|
||||
|
||||
// Set the thread as current.
|
||||
kernel.RegisterHostThread(thread);
|
||||
|
||||
// Run the callback.
|
||||
func();
|
||||
func_();
|
||||
|
||||
// Close the thread.
|
||||
// This will free the process if it is the last reference.
|
||||
|
612
src/core/hle/kernel/message_buffer.h
Executable file
612
src/core/hle/kernel/message_buffer.h
Executable file
@ -0,0 +1,612 @@
|
||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/alignment.h"
|
||||
#include "common/bit_field.h"
|
||||
#include "core/hle/kernel/k_thread.h"
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
constexpr inline size_t MessageBufferSize = 0x100;
|
||||
|
||||
class MessageBuffer {
|
||||
public:
|
||||
class MessageHeader {
|
||||
private:
|
||||
static constexpr inline u64 NullTag = 0;
|
||||
|
||||
public:
|
||||
enum class ReceiveListCountType : u32 {
|
||||
None = 0,
|
||||
ToMessageBuffer = 1,
|
||||
ToSingleBuffer = 2,
|
||||
|
||||
CountOffset = 2,
|
||||
CountMax = 13,
|
||||
};
|
||||
|
||||
private:
|
||||
union {
|
||||
std::array<u32, 2> raw;
|
||||
|
||||
struct {
|
||||
// Define fields for the first header word.
|
||||
union {
|
||||
BitField<0, 16, u16> tag;
|
||||
BitField<16, 4, u32> pointer_count;
|
||||
BitField<20, 4, u32> send_count;
|
||||
BitField<24, 4, u32> receive_count;
|
||||
BitField<28, 4, u32> exchange_count;
|
||||
};
|
||||
|
||||
// Define fields for the second header word.
|
||||
union {
|
||||
BitField<0, 10, u32> raw_count;
|
||||
BitField<10, 4, ReceiveListCountType> receive_list_count;
|
||||
BitField<14, 6, u32> reserved0;
|
||||
BitField<20, 11, u32> receive_list_offset;
|
||||
BitField<31, 1, u32> has_special_header;
|
||||
};
|
||||
};
|
||||
} m_header;
|
||||
|
||||
public:
|
||||
constexpr MessageHeader() : m_header{} {}
|
||||
|
||||
constexpr MessageHeader(u16 tag, bool special, s32 ptr, s32 send, s32 recv, s32 exch,
|
||||
s32 raw, ReceiveListCountType recv_list)
|
||||
: m_header{} {
|
||||
m_header.raw[0] = 0;
|
||||
m_header.raw[1] = 0;
|
||||
|
||||
m_header.tag.Assign(tag);
|
||||
m_header.pointer_count.Assign(ptr);
|
||||
m_header.send_count.Assign(send);
|
||||
m_header.receive_count.Assign(recv);
|
||||
m_header.exchange_count.Assign(exch);
|
||||
|
||||
m_header.raw_count.Assign(raw);
|
||||
m_header.receive_list_count.Assign(recv_list);
|
||||
m_header.has_special_header.Assign(special);
|
||||
}
|
||||
|
||||
explicit MessageHeader(const MessageBuffer& buf) : m_header{} {
|
||||
buf.Get(0, m_header.raw.data(), 2);
|
||||
}
|
||||
|
||||
explicit MessageHeader(const u32* msg) : m_header{{msg[0], msg[1]}} {}
|
||||
|
||||
constexpr u16 GetTag() const {
|
||||
return m_header.tag;
|
||||
}
|
||||
|
||||
constexpr s32 GetPointerCount() const {
|
||||
return m_header.pointer_count;
|
||||
}
|
||||
|
||||
constexpr s32 GetSendCount() const {
|
||||
return m_header.send_count;
|
||||
}
|
||||
|
||||
constexpr s32 GetReceiveCount() const {
|
||||
return m_header.receive_count;
|
||||
}
|
||||
|
||||
constexpr s32 GetExchangeCount() const {
|
||||
return m_header.exchange_count;
|
||||
}
|
||||
|
||||
constexpr s32 GetMapAliasCount() const {
|
||||
return this->GetSendCount() + this->GetReceiveCount() + this->GetExchangeCount();
|
||||
}
|
||||
|
||||
constexpr s32 GetRawCount() const {
|
||||
return m_header.raw_count;
|
||||
}
|
||||
|
||||
constexpr ReceiveListCountType GetReceiveListCount() const {
|
||||
return m_header.receive_list_count;
|
||||
}
|
||||
|
||||
constexpr s32 GetReceiveListOffset() const {
|
||||
return m_header.receive_list_offset;
|
||||
}
|
||||
|
||||
constexpr bool GetHasSpecialHeader() const {
|
||||
return m_header.has_special_header.Value() != 0;
|
||||
}
|
||||
|
||||
constexpr void SetReceiveListCount(ReceiveListCountType recv_list) {
|
||||
m_header.receive_list_count.Assign(recv_list);
|
||||
}
|
||||
|
||||
constexpr const u32* GetData() const {
|
||||
return m_header.raw.data();
|
||||
}
|
||||
|
||||
static constexpr size_t GetDataSize() {
|
||||
return sizeof(m_header);
|
||||
}
|
||||
};
|
||||
|
||||
class SpecialHeader {
|
||||
private:
|
||||
union {
|
||||
std::array<u32, 1> raw;
|
||||
|
||||
// Define fields for the header word.
|
||||
BitField<0, 1, u32> has_process_id;
|
||||
BitField<1, 4, u32> copy_handle_count;
|
||||
BitField<5, 4, u32> move_handle_count;
|
||||
} m_header;
|
||||
bool m_has_header;
|
||||
|
||||
public:
|
||||
constexpr explicit SpecialHeader(bool pid, s32 copy, s32 move)
|
||||
: m_header{}, m_has_header(true) {
|
||||
m_header.has_process_id.Assign(pid);
|
||||
m_header.copy_handle_count.Assign(copy);
|
||||
m_header.move_handle_count.Assign(move);
|
||||
}
|
||||
|
||||
constexpr explicit SpecialHeader(bool pid, s32 copy, s32 move, bool _has_header)
|
||||
: m_header{}, m_has_header(_has_header) {
|
||||
m_header.has_process_id.Assign(pid);
|
||||
m_header.copy_handle_count.Assign(copy);
|
||||
m_header.move_handle_count.Assign(move);
|
||||
}
|
||||
|
||||
explicit SpecialHeader(const MessageBuffer& buf, const MessageHeader& hdr)
|
||||
: m_header{}, m_has_header(hdr.GetHasSpecialHeader()) {
|
||||
if (m_has_header) {
|
||||
buf.Get(static_cast<s32>(MessageHeader::GetDataSize() / sizeof(u32)),
|
||||
m_header.raw.data(), sizeof(m_header) / sizeof(u32));
|
||||
}
|
||||
}
|
||||
|
||||
constexpr bool GetHasProcessId() const {
|
||||
return m_header.has_process_id.Value() != 0;
|
||||
}
|
||||
|
||||
constexpr s32 GetCopyHandleCount() const {
|
||||
return m_header.copy_handle_count;
|
||||
}
|
||||
|
||||
constexpr s32 GetMoveHandleCount() const {
|
||||
return m_header.move_handle_count;
|
||||
}
|
||||
|
||||
constexpr const u32* GetHeader() const {
|
||||
return m_header.raw.data();
|
||||
}
|
||||
|
||||
constexpr size_t GetHeaderSize() const {
|
||||
if (m_has_header) {
|
||||
return sizeof(m_header);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr size_t GetDataSize() const {
|
||||
if (m_has_header) {
|
||||
return (this->GetHasProcessId() ? sizeof(u64) : 0) +
|
||||
(this->GetCopyHandleCount() * sizeof(Handle)) +
|
||||
(this->GetMoveHandleCount() * sizeof(Handle));
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class MapAliasDescriptor {
|
||||
public:
|
||||
enum class Attribute : u32 {
|
||||
Ipc = 0,
|
||||
NonSecureIpc = 1,
|
||||
NonDeviceIpc = 3,
|
||||
};
|
||||
|
||||
private:
|
||||
static constexpr u32 SizeLowCount = 32;
|
||||
static constexpr u32 SizeHighCount = 4;
|
||||
static constexpr u32 AddressLowCount = 32;
|
||||
static constexpr u32 AddressMidCount = 4;
|
||||
|
||||
constexpr u32 GetAddressMid(u64 address) {
|
||||
return static_cast<u32>(address >> AddressLowCount) & ((1U << AddressMidCount) - 1);
|
||||
}
|
||||
|
||||
constexpr u32 GetAddressHigh(u64 address) {
|
||||
return static_cast<u32>(address >> (AddressLowCount + AddressMidCount));
|
||||
}
|
||||
|
||||
private:
|
||||
union {
|
||||
std::array<u32, 3> raw;
|
||||
|
||||
struct {
|
||||
// Define fields for the first two words.
|
||||
u32 size_low;
|
||||
u32 address_low;
|
||||
|
||||
// Define fields for the packed descriptor word.
|
||||
union {
|
||||
BitField<0, 2, Attribute> attributes;
|
||||
BitField<2, 3, u32> address_high;
|
||||
BitField<5, 19, u32> reserved;
|
||||
BitField<24, 4, u32> size_high;
|
||||
BitField<28, 4, u32> address_mid;
|
||||
};
|
||||
};
|
||||
} m_data;
|
||||
|
||||
public:
|
||||
constexpr MapAliasDescriptor() : m_data{} {}
|
||||
|
||||
MapAliasDescriptor(const void* buffer, size_t _size, Attribute attr = Attribute::Ipc)
|
||||
: m_data{} {
|
||||
const u64 address = reinterpret_cast<u64>(buffer);
|
||||
const u64 size = static_cast<u64>(_size);
|
||||
m_data.size_low = static_cast<u32>(size);
|
||||
m_data.address_low = static_cast<u32>(address);
|
||||
m_data.attributes.Assign(attr);
|
||||
m_data.address_mid.Assign(GetAddressMid(address));
|
||||
m_data.size_high.Assign(static_cast<u32>(size >> SizeLowCount));
|
||||
m_data.address_high.Assign(GetAddressHigh(address));
|
||||
}
|
||||
|
||||
MapAliasDescriptor(const MessageBuffer& buf, s32 index) : m_data{} {
|
||||
buf.Get(index, m_data.raw.data(), 3);
|
||||
}
|
||||
|
||||
constexpr uintptr_t GetAddress() const {
|
||||
return (static_cast<u64>((m_data.address_high << AddressMidCount) | m_data.address_mid)
|
||||
<< AddressLowCount) |
|
||||
m_data.address_low;
|
||||
}
|
||||
|
||||
constexpr uintptr_t GetSize() const {
|
||||
return (static_cast<u64>(m_data.size_high) << SizeLowCount) | m_data.size_low;
|
||||
}
|
||||
|
||||
constexpr Attribute GetAttribute() const {
|
||||
return m_data.attributes;
|
||||
}
|
||||
|
||||
constexpr const u32* GetData() const {
|
||||
return m_data.raw.data();
|
||||
}
|
||||
|
||||
static constexpr size_t GetDataSize() {
|
||||
return sizeof(m_data);
|
||||
}
|
||||
};
|
||||
|
||||
class PointerDescriptor {
|
||||
private:
|
||||
static constexpr u32 AddressLowCount = 32;
|
||||
static constexpr u32 AddressMidCount = 4;
|
||||
|
||||
constexpr u32 GetAddressMid(u64 address) {
|
||||
return static_cast<u32>(address >> AddressLowCount) & ((1u << AddressMidCount) - 1);
|
||||
}
|
||||
|
||||
constexpr u32 GetAddressHigh(u64 address) {
|
||||
return static_cast<u32>(address >> (AddressLowCount + AddressMidCount));
|
||||
}
|
||||
|
||||
private:
|
||||
union {
|
||||
std::array<u32, 2> raw;
|
||||
|
||||
struct {
|
||||
// Define fields for the packed descriptor word.
|
||||
union {
|
||||
BitField<0, 4, u32> index;
|
||||
BitField<4, 2, u32> reserved0;
|
||||
BitField<6, 3, u32> address_high;
|
||||
BitField<9, 3, u32> reserved1;
|
||||
BitField<12, 4, u32> address_mid;
|
||||
BitField<16, 16, u32> size;
|
||||
};
|
||||
|
||||
// Define fields for the second word.
|
||||
u32 address_low;
|
||||
};
|
||||
} m_data;
|
||||
|
||||
public:
|
||||
constexpr PointerDescriptor() : m_data{} {}
|
||||
|
||||
PointerDescriptor(const void* buffer, size_t size, s32 index) : m_data{} {
|
||||
const u64 address = reinterpret_cast<u64>(buffer);
|
||||
|
||||
m_data.index.Assign(index);
|
||||
m_data.address_high.Assign(GetAddressHigh(address));
|
||||
m_data.address_mid.Assign(GetAddressMid(address));
|
||||
m_data.size.Assign(static_cast<u32>(size));
|
||||
|
||||
m_data.address_low = static_cast<u32>(address);
|
||||
}
|
||||
|
||||
PointerDescriptor(const MessageBuffer& buf, s32 index) : m_data{} {
|
||||
buf.Get(index, m_data.raw.data(), 2);
|
||||
}
|
||||
|
||||
constexpr s32 GetIndex() const {
|
||||
return m_data.index;
|
||||
}
|
||||
|
||||
constexpr uintptr_t GetAddress() const {
|
||||
return (static_cast<u64>((m_data.address_high << AddressMidCount) | m_data.address_mid)
|
||||
<< AddressLowCount) |
|
||||
m_data.address_low;
|
||||
}
|
||||
|
||||
constexpr size_t GetSize() const {
|
||||
return m_data.size;
|
||||
}
|
||||
|
||||
constexpr const u32* GetData() const {
|
||||
return m_data.raw.data();
|
||||
}
|
||||
|
||||
static constexpr size_t GetDataSize() {
|
||||
return sizeof(m_data);
|
||||
}
|
||||
};
|
||||
|
||||
class ReceiveListEntry {
|
||||
private:
|
||||
static constexpr u32 AddressLowCount = 32;
|
||||
|
||||
constexpr u32 GetAddressHigh(u64 address) {
|
||||
return static_cast<u32>(address >> (AddressLowCount));
|
||||
}
|
||||
|
||||
private:
|
||||
union {
|
||||
std::array<u32, 2> raw;
|
||||
|
||||
struct {
|
||||
// Define fields for the first word.
|
||||
u32 address_low;
|
||||
|
||||
// Define fields for the packed descriptor word.
|
||||
union {
|
||||
BitField<0, 7, u32> address_high;
|
||||
BitField<7, 9, u32> reserved;
|
||||
BitField<16, 16, u32> size;
|
||||
};
|
||||
};
|
||||
} m_data;
|
||||
|
||||
public:
|
||||
constexpr ReceiveListEntry() : m_data{} {}
|
||||
|
||||
ReceiveListEntry(const void* buffer, size_t size) : m_data{} {
|
||||
const u64 address = reinterpret_cast<u64>(buffer);
|
||||
|
||||
m_data.address_low = static_cast<u32>(address);
|
||||
|
||||
m_data.address_high.Assign(GetAddressHigh(address));
|
||||
m_data.size.Assign(static_cast<u32>(size));
|
||||
}
|
||||
|
||||
ReceiveListEntry(u32 a, u32 b) : m_data{{a, b}} {}
|
||||
|
||||
constexpr uintptr_t GetAddress() const {
|
||||
return (static_cast<u64>(m_data.address_high) << AddressLowCount) | m_data.address_low;
|
||||
}
|
||||
|
||||
constexpr size_t GetSize() const {
|
||||
return m_data.size;
|
||||
}
|
||||
|
||||
constexpr const u32* GetData() const {
|
||||
return m_data.raw.data();
|
||||
}
|
||||
|
||||
static constexpr size_t GetDataSize() {
|
||||
return sizeof(m_data);
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
u32* m_buffer;
|
||||
size_t m_size;
|
||||
|
||||
public:
|
||||
constexpr MessageBuffer(u32* b, size_t sz) : m_buffer(b), m_size(sz) {}
|
||||
constexpr explicit MessageBuffer(u32* b) : m_buffer(b), m_size(MessageBufferSize) {}
|
||||
|
||||
constexpr void* GetBufferForDebug() const {
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
constexpr size_t GetBufferSize() const {
|
||||
return m_size;
|
||||
}
|
||||
|
||||
void Get(s32 index, u32* dst, size_t count) const {
|
||||
// Ensure that this doesn't get re-ordered.
|
||||
std::atomic_thread_fence(std::memory_order_seq_cst);
|
||||
|
||||
// Get the words.
|
||||
static_assert(sizeof(*dst) == sizeof(*m_buffer));
|
||||
|
||||
memcpy(dst, m_buffer + index, count * sizeof(*dst));
|
||||
}
|
||||
|
||||
s32 Set(s32 index, u32* src, size_t count) const {
|
||||
// Ensure that this doesn't get re-ordered.
|
||||
std::atomic_thread_fence(std::memory_order_seq_cst);
|
||||
|
||||
// Set the words.
|
||||
memcpy(m_buffer + index, src, count * sizeof(*src));
|
||||
|
||||
// Ensure that this doesn't get re-ordered.
|
||||
std::atomic_thread_fence(std::memory_order_seq_cst);
|
||||
|
||||
return static_cast<s32>(index + count);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
const T& GetRaw(s32 index) const {
|
||||
return *reinterpret_cast<const T*>(m_buffer + index);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
s32 SetRaw(s32 index, const T& val) const {
|
||||
*reinterpret_cast<const T*>(m_buffer + index) = val;
|
||||
return index + (Common::AlignUp(sizeof(val), sizeof(*m_buffer)) / sizeof(*m_buffer));
|
||||
}
|
||||
|
||||
void GetRawArray(s32 index, void* dst, size_t len) const {
|
||||
memcpy(dst, m_buffer + index, len);
|
||||
}
|
||||
|
||||
void SetRawArray(s32 index, const void* src, size_t len) const {
|
||||
memcpy(m_buffer + index, src, len);
|
||||
}
|
||||
|
||||
void SetNull() const {
|
||||
this->Set(MessageHeader());
|
||||
}
|
||||
|
||||
s32 Set(const MessageHeader& hdr) const {
|
||||
memcpy(m_buffer, hdr.GetData(), hdr.GetDataSize());
|
||||
return static_cast<s32>(hdr.GetDataSize() / sizeof(*m_buffer));
|
||||
}
|
||||
|
||||
s32 Set(const SpecialHeader& spc) const {
|
||||
const s32 index = static_cast<s32>(MessageHeader::GetDataSize() / sizeof(*m_buffer));
|
||||
memcpy(m_buffer + index, spc.GetHeader(), spc.GetHeaderSize());
|
||||
return static_cast<s32>(index + (spc.GetHeaderSize() / sizeof(*m_buffer)));
|
||||
}
|
||||
|
||||
s32 SetHandle(s32 index, const Handle& hnd) const {
|
||||
memcpy(m_buffer + index, std::addressof(hnd), sizeof(hnd));
|
||||
return static_cast<s32>(index + (sizeof(hnd) / sizeof(*m_buffer)));
|
||||
}
|
||||
|
||||
s32 SetProcessId(s32 index, const u64 pid) const {
|
||||
memcpy(m_buffer + index, std::addressof(pid), sizeof(pid));
|
||||
return static_cast<s32>(index + (sizeof(pid) / sizeof(*m_buffer)));
|
||||
}
|
||||
|
||||
s32 Set(s32 index, const MapAliasDescriptor& desc) const {
|
||||
memcpy(m_buffer + index, desc.GetData(), desc.GetDataSize());
|
||||
return static_cast<s32>(index + (desc.GetDataSize() / sizeof(*m_buffer)));
|
||||
}
|
||||
|
||||
s32 Set(s32 index, const PointerDescriptor& desc) const {
|
||||
memcpy(m_buffer + index, desc.GetData(), desc.GetDataSize());
|
||||
return static_cast<s32>(index + (desc.GetDataSize() / sizeof(*m_buffer)));
|
||||
}
|
||||
|
||||
s32 Set(s32 index, const ReceiveListEntry& desc) const {
|
||||
memcpy(m_buffer + index, desc.GetData(), desc.GetDataSize());
|
||||
return static_cast<s32>(index + (desc.GetDataSize() / sizeof(*m_buffer)));
|
||||
}
|
||||
|
||||
s32 Set(s32 index, const u32 val) const {
|
||||
memcpy(m_buffer + index, std::addressof(val), sizeof(val));
|
||||
return static_cast<s32>(index + (sizeof(val) / sizeof(*m_buffer)));
|
||||
}
|
||||
|
||||
Result GetAsyncResult() const {
|
||||
MessageHeader hdr(m_buffer);
|
||||
MessageHeader null{};
|
||||
if (memcmp(hdr.GetData(), null.GetData(), MessageHeader::GetDataSize()) != 0) [[unlikely]] {
|
||||
R_SUCCEED();
|
||||
}
|
||||
return Result(m_buffer[MessageHeader::GetDataSize() / sizeof(*m_buffer)]);
|
||||
}
|
||||
|
||||
void SetAsyncResult(Result res) const {
|
||||
const s32 index = this->Set(MessageHeader());
|
||||
const auto value = res.raw;
|
||||
memcpy(m_buffer + index, std::addressof(value), sizeof(value));
|
||||
}
|
||||
|
||||
u32 Get32(s32 index) const {
|
||||
return m_buffer[index];
|
||||
}
|
||||
|
||||
u64 Get64(s32 index) const {
|
||||
u64 value;
|
||||
memcpy(std::addressof(value), m_buffer + index, sizeof(value));
|
||||
return value;
|
||||
}
|
||||
|
||||
u64 GetProcessId(s32 index) const {
|
||||
return this->Get64(index);
|
||||
}
|
||||
|
||||
Handle GetHandle(s32 index) const {
|
||||
static_assert(sizeof(Handle) == sizeof(*m_buffer));
|
||||
return Handle(m_buffer[index]);
|
||||
}
|
||||
|
||||
static constexpr s32 GetSpecialDataIndex(const MessageHeader& hdr, const SpecialHeader& spc) {
|
||||
return static_cast<s32>((MessageHeader::GetDataSize() / sizeof(u32)) +
|
||||
(spc.GetHeaderSize() / sizeof(u32)));
|
||||
}
|
||||
|
||||
static constexpr s32 GetPointerDescriptorIndex(const MessageHeader& hdr,
|
||||
const SpecialHeader& spc) {
|
||||
return static_cast<s32>(GetSpecialDataIndex(hdr, spc) + (spc.GetDataSize() / sizeof(u32)));
|
||||
}
|
||||
|
||||
static constexpr s32 GetMapAliasDescriptorIndex(const MessageHeader& hdr,
|
||||
const SpecialHeader& spc) {
|
||||
return GetPointerDescriptorIndex(hdr, spc) +
|
||||
static_cast<s32>(hdr.GetPointerCount() * PointerDescriptor::GetDataSize() /
|
||||
sizeof(u32));
|
||||
}
|
||||
|
||||
static constexpr s32 GetRawDataIndex(const MessageHeader& hdr, const SpecialHeader& spc) {
|
||||
return GetMapAliasDescriptorIndex(hdr, spc) +
|
||||
static_cast<s32>(hdr.GetMapAliasCount() * MapAliasDescriptor::GetDataSize() /
|
||||
sizeof(u32));
|
||||
}
|
||||
|
||||
static constexpr s32 GetReceiveListIndex(const MessageHeader& hdr, const SpecialHeader& spc) {
|
||||
if (const s32 recv_list_index = hdr.GetReceiveListOffset()) {
|
||||
return recv_list_index;
|
||||
} else {
|
||||
return GetRawDataIndex(hdr, spc) + hdr.GetRawCount();
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr size_t GetMessageBufferSize(const MessageHeader& hdr,
|
||||
const SpecialHeader& spc) {
|
||||
// Get the size of the plain message.
|
||||
size_t msg_size = GetReceiveListIndex(hdr, spc) * sizeof(u32);
|
||||
|
||||
// Add the size of the receive list.
|
||||
const auto count = hdr.GetReceiveListCount();
|
||||
switch (count) {
|
||||
case MessageHeader::ReceiveListCountType::None:
|
||||
break;
|
||||
case MessageHeader::ReceiveListCountType::ToMessageBuffer:
|
||||
break;
|
||||
case MessageHeader::ReceiveListCountType::ToSingleBuffer:
|
||||
msg_size += ReceiveListEntry::GetDataSize();
|
||||
break;
|
||||
default:
|
||||
msg_size += (static_cast<s32>(count) -
|
||||
static_cast<s32>(MessageHeader::ReceiveListCountType::CountOffset)) *
|
||||
ReceiveListEntry::GetDataSize();
|
||||
break;
|
||||
}
|
||||
|
||||
return msg_size;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Kernel
|
@ -506,8 +506,8 @@ void ISelfController::SetHandlesRequestToDisplay(HLERequestContext& ctx) {
|
||||
void ISelfController::SetIdleTimeDetectionExtension(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
idle_time_detection_extension = rp.Pop<u32>();
|
||||
LOG_WARNING(Service_AM, "(STUBBED) called idle_time_detection_extension={}",
|
||||
idle_time_detection_extension);
|
||||
LOG_DEBUG(Service_AM, "(STUBBED) called idle_time_detection_extension={}",
|
||||
idle_time_detection_extension);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "core/hle/service/kernel_helpers.h"
|
||||
#include "core/hle/service/nifm/nifm.h"
|
||||
#include "core/hle/service/server_manager.h"
|
||||
#include "network/network.h"
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -4,14 +4,15 @@
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/service.h"
|
||||
#include "network/network.h"
|
||||
#include "network/room.h"
|
||||
#include "network/room_member.h"
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
}
|
||||
|
||||
namespace Network {
|
||||
class RoomNetwork;
|
||||
}
|
||||
|
||||
namespace Service::NIFM {
|
||||
|
||||
void LoopProcess(Core::System& system);
|
||||
|
@ -3,15 +3,15 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/result.h"
|
||||
|
||||
#include "common/common_types.h"
|
||||
|
||||
#include <memory>
|
||||
#include <span>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "common/common_types.h"
|
||||
|
||||
#include "core/hle/result.h"
|
||||
|
||||
namespace Network {
|
||||
class SocketBase;
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "core/hle/service/ssl/ssl_backend.h"
|
||||
|
||||
#include "common/logging/log.h"
|
||||
|
||||
#include "core/hle/service/ssl/ssl_backend.h"
|
||||
|
||||
namespace Service::SSL {
|
||||
|
||||
ResultVal<std::unique_ptr<SSLConnectionBackend>> CreateSSLConnectionBackend() {
|
||||
|
@ -1,14 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "core/hle/service/ssl/ssl_backend.h"
|
||||
#include "core/internal_network/network.h"
|
||||
#include "core/internal_network/sockets.h"
|
||||
|
||||
#include "common/fs/file.h"
|
||||
#include "common/hex_util.h"
|
||||
#include "common/string_util.h"
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include <openssl/bio.h>
|
||||
@ -16,6 +8,14 @@
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/x509.h>
|
||||
|
||||
#include "common/fs/file.h"
|
||||
#include "common/hex_util.h"
|
||||
#include "common/string_util.h"
|
||||
|
||||
#include "core/hle/service/ssl/ssl_backend.h"
|
||||
#include "core/internal_network/network.h"
|
||||
#include "core/internal_network/sockets.h"
|
||||
|
||||
using namespace Common::FS;
|
||||
|
||||
namespace Service::SSL {
|
||||
|
@ -1,16 +1,16 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "core/hle/service/ssl/ssl_backend.h"
|
||||
#include "core/internal_network/network.h"
|
||||
#include "core/internal_network/sockets.h"
|
||||
#include <mutex>
|
||||
|
||||
#include "common/error.h"
|
||||
#include "common/fs/file.h"
|
||||
#include "common/hex_util.h"
|
||||
#include "common/string_util.h"
|
||||
|
||||
#include <mutex>
|
||||
#include "core/hle/service/ssl/ssl_backend.h"
|
||||
#include "core/internal_network/network.h"
|
||||
#include "core/internal_network/sockets.h"
|
||||
|
||||
namespace {
|
||||
|
||||
@ -20,6 +20,7 @@ namespace {
|
||||
#define SECURITY_WIN32
|
||||
#include <schnlsp.h>
|
||||
#include <security.h>
|
||||
#include <wincrypt.h>
|
||||
|
||||
std::once_flag one_time_init_flag;
|
||||
bool one_time_init_success = false;
|
||||
|
@ -1,18 +1,21 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "core/hle/service/ssl/ssl_backend.h"
|
||||
#include "core/internal_network/network.h"
|
||||
#include "core/internal_network/sockets.h"
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include <Security/SecureTransport.h>
|
||||
|
||||
// SecureTransport has been deprecated in its entirety in favor of
|
||||
// Network.framework, but that does not allow layering TLS on top of an
|
||||
// arbitrary socket.
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#include <Security/SecureTransport.h>
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#include "core/hle/service/ssl/ssl_backend.h"
|
||||
#include "core/internal_network/network.h"
|
||||
#include "core/internal_network/sockets.h"
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "core/internal_network/network.h"
|
||||
#include "core/internal_network/network_interface.h"
|
||||
#include "core/internal_network/socket_proxy.h"
|
||||
#include "network/network.h"
|
||||
|
||||
#if YUZU_UNIX
|
||||
#include <sys/socket.h>
|
||||
|
@ -10,10 +10,12 @@
|
||||
|
||||
#include "common/common_funcs.h"
|
||||
#include "core/internal_network/sockets.h"
|
||||
#include "network/network.h"
|
||||
#include "network/room_member.h"
|
||||
|
||||
namespace Network {
|
||||
|
||||
class RoomNetwork;
|
||||
|
||||
class ProxySocket : public SocketBase {
|
||||
public:
|
||||
explicit ProxySocket(RoomNetwork& room_network_) noexcept;
|
||||
|
@ -15,12 +15,13 @@
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "core/internal_network/network.h"
|
||||
#include "network/network.h"
|
||||
|
||||
// TODO: C++20 Replace std::vector usages with std::span
|
||||
|
||||
namespace Network {
|
||||
|
||||
struct ProxyPacket;
|
||||
|
||||
class SocketBase {
|
||||
public:
|
||||
#ifdef YUZU_UNIX
|
||||
|
@ -274,6 +274,7 @@ add_library(video_core STATIC
|
||||
vulkan_common/vulkan_wrapper.h
|
||||
vulkan_common/nsight_aftermath_tracker.cpp
|
||||
vulkan_common/nsight_aftermath_tracker.h
|
||||
vulkan_common/vma.cpp
|
||||
)
|
||||
|
||||
create_target_directory_groups(video_core)
|
||||
@ -291,7 +292,7 @@ target_link_options(video_core PRIVATE ${FFmpeg_LDFLAGS})
|
||||
|
||||
add_dependencies(video_core host_shaders)
|
||||
target_include_directories(video_core PRIVATE ${HOST_SHADERS_INCLUDE})
|
||||
target_link_libraries(video_core PRIVATE sirit Vulkan::Headers vma)
|
||||
target_link_libraries(video_core PRIVATE sirit Vulkan::Headers GPUOpen::VulkanMemoryAllocator)
|
||||
|
||||
if (ENABLE_NSIGHT_AFTERMATH)
|
||||
if (NOT DEFINED ENV{NSIGHT_AFTERMATH_SDK})
|
||||
@ -324,6 +325,9 @@ else()
|
||||
|
||||
# xbyak
|
||||
set_source_files_properties(macro/macro_jit_x64.cpp PROPERTIES COMPILE_OPTIONS "-Wno-conversion;-Wno-shadow")
|
||||
|
||||
# VMA
|
||||
set_source_files_properties(vulkan_common/vma.cpp PROPERTIES COMPILE_OPTIONS "-Wno-conversion;-Wno-unused-variable;-Wno-unused-parameter;-Wno-missing-field-initializers")
|
||||
endif()
|
||||
|
||||
if (ARCHITECTURE_x86_64)
|
||||
|
@ -442,6 +442,11 @@ void BufferCache<P>::UnbindComputeStorageBuffers() {
|
||||
template <class P>
|
||||
void BufferCache<P>::BindComputeStorageBuffer(size_t ssbo_index, u32 cbuf_index, u32 cbuf_offset,
|
||||
bool is_written) {
|
||||
if (ssbo_index >= channel_state->compute_storage_buffers.size()) [[unlikely]] {
|
||||
LOG_ERROR(HW_GPU, "Storage buffer index {} exceeds maximum storage buffer count",
|
||||
ssbo_index);
|
||||
return;
|
||||
}
|
||||
channel_state->enabled_compute_storage_buffers |= 1U << ssbo_index;
|
||||
channel_state->written_compute_storage_buffers |= (is_written ? 1U : 0U) << ssbo_index;
|
||||
|
||||
@ -464,6 +469,11 @@ void BufferCache<P>::UnbindComputeTextureBuffers() {
|
||||
template <class P>
|
||||
void BufferCache<P>::BindComputeTextureBuffer(size_t tbo_index, GPUVAddr gpu_addr, u32 size,
|
||||
PixelFormat format, bool is_written, bool is_image) {
|
||||
if (tbo_index >= channel_state->compute_texture_buffers.size()) [[unlikely]] {
|
||||
LOG_ERROR(HW_GPU, "Texture buffer index {} exceeds maximum texture buffer count",
|
||||
tbo_index);
|
||||
return;
|
||||
}
|
||||
channel_state->enabled_compute_texture_buffers |= 1U << tbo_index;
|
||||
channel_state->written_compute_texture_buffers |= (is_written ? 1U : 0U) << tbo_index;
|
||||
if constexpr (SEPARATE_IMAGE_BUFFERS_BINDINGS) {
|
||||
|
@ -67,7 +67,7 @@ constexpr u32 NUM_TRANSFORM_FEEDBACK_BUFFERS = 4;
|
||||
constexpr u32 NUM_GRAPHICS_UNIFORM_BUFFERS = 18;
|
||||
constexpr u32 NUM_COMPUTE_UNIFORM_BUFFERS = 8;
|
||||
constexpr u32 NUM_STORAGE_BUFFERS = 16;
|
||||
constexpr u32 NUM_TEXTURE_BUFFERS = 16;
|
||||
constexpr u32 NUM_TEXTURE_BUFFERS = 32;
|
||||
constexpr u32 NUM_STAGES = 5;
|
||||
|
||||
using UniformBufferSizes = std::array<std::array<u32, NUM_GRAPHICS_UNIFORM_BUFFERS>, NUM_STAGES>;
|
||||
|
@ -38,8 +38,8 @@ void RendererBase::RequestScreenshot(void* data, std::function<void(bool)> callb
|
||||
LOG_ERROR(Render, "A screenshot is already requested or in progress, ignoring the request");
|
||||
return;
|
||||
}
|
||||
auto async_callback{[callback = std::move(callback)](bool invert_y) {
|
||||
std::thread t{callback, invert_y};
|
||||
auto async_callback{[callback_ = std::move(callback)](bool invert_y) {
|
||||
std::thread t{callback_, invert_y};
|
||||
t.detach();
|
||||
}};
|
||||
renderer_settings.screenshot_bits = data;
|
||||
|
@ -231,24 +231,25 @@ GraphicsPipeline::GraphicsPipeline(const Device& device, TextureCache& texture_c
|
||||
}
|
||||
const bool in_parallel = thread_worker != nullptr;
|
||||
const auto backend = device.GetShaderBackend();
|
||||
auto func{[this, sources = std::move(sources), sources_spirv = std::move(sources_spirv),
|
||||
auto func{[this, sources_ = std::move(sources), sources_spirv_ = std::move(sources_spirv),
|
||||
shader_notify, backend, in_parallel,
|
||||
force_context_flush](ShaderContext::Context*) mutable {
|
||||
for (size_t stage = 0; stage < 5; ++stage) {
|
||||
switch (backend) {
|
||||
case Settings::ShaderBackend::GLSL:
|
||||
if (!sources[stage].empty()) {
|
||||
source_programs[stage] = CreateProgram(sources[stage], Stage(stage));
|
||||
if (!sources_[stage].empty()) {
|
||||
source_programs[stage] = CreateProgram(sources_[stage], Stage(stage));
|
||||
}
|
||||
break;
|
||||
case Settings::ShaderBackend::GLASM:
|
||||
if (!sources[stage].empty()) {
|
||||
assembly_programs[stage] = CompileProgram(sources[stage], AssemblyStage(stage));
|
||||
if (!sources_[stage].empty()) {
|
||||
assembly_programs[stage] =
|
||||
CompileProgram(sources_[stage], AssemblyStage(stage));
|
||||
}
|
||||
break;
|
||||
case Settings::ShaderBackend::SPIRV:
|
||||
if (!sources_spirv[stage].empty()) {
|
||||
source_programs[stage] = CreateProgram(sources_spirv[stage], Stage(stage));
|
||||
if (!sources_spirv_[stage].empty()) {
|
||||
source_programs[stage] = CreateProgram(sources_spirv_[stage], Stage(stage));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -288,9 +288,9 @@ void ShaderCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading,
|
||||
const auto load_compute{[&](std::ifstream& file, FileEnvironment env) {
|
||||
ComputePipelineKey key;
|
||||
file.read(reinterpret_cast<char*>(&key), sizeof(key));
|
||||
queue_work([this, key, env = std::move(env), &state, &callback](Context* ctx) mutable {
|
||||
queue_work([this, key, env_ = std::move(env), &state, &callback](Context* ctx) mutable {
|
||||
ctx->pools.ReleaseContents();
|
||||
auto pipeline{CreateComputePipeline(ctx->pools, key, env, true)};
|
||||
auto pipeline{CreateComputePipeline(ctx->pools, key, env_, true)};
|
||||
std::scoped_lock lock{state.mutex};
|
||||
if (pipeline) {
|
||||
compute_cache.emplace(key, std::move(pipeline));
|
||||
@ -305,9 +305,9 @@ void ShaderCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading,
|
||||
const auto load_graphics{[&](std::ifstream& file, std::vector<FileEnvironment> envs) {
|
||||
GraphicsPipelineKey key;
|
||||
file.read(reinterpret_cast<char*>(&key), sizeof(key));
|
||||
queue_work([this, key, envs = std::move(envs), &state, &callback](Context* ctx) mutable {
|
||||
queue_work([this, key, envs_ = std::move(envs), &state, &callback](Context* ctx) mutable {
|
||||
boost::container::static_vector<Shader::Environment*, 5> env_ptrs;
|
||||
for (auto& env : envs) {
|
||||
for (auto& env : envs_) {
|
||||
env_ptrs.push_back(&env);
|
||||
}
|
||||
ctx->pools.ReleaseContents();
|
||||
|
@ -206,8 +206,8 @@ public:
|
||||
const size_t sub_first_offset = static_cast<size_t>(first % 4) * GetQuadsNum(num_indices);
|
||||
const size_t offset =
|
||||
(sub_first_offset + GetQuadsNum(first)) * 6ULL * BytesPerIndex(index_type);
|
||||
scheduler.Record([buffer = *buffer, index_type_, offset](vk::CommandBuffer cmdbuf) {
|
||||
cmdbuf.BindIndexBuffer(buffer, offset, index_type_);
|
||||
scheduler.Record([buffer_ = *buffer, index_type_, offset](vk::CommandBuffer cmdbuf) {
|
||||
cmdbuf.BindIndexBuffer(buffer_, offset, index_type_);
|
||||
});
|
||||
}
|
||||
|
||||
@ -528,17 +528,18 @@ void BufferCacheRuntime::BindVertexBuffers(VideoCommon::HostBindings<Buffer>& bi
|
||||
buffer_handles.push_back(handle);
|
||||
}
|
||||
if (device.IsExtExtendedDynamicStateSupported()) {
|
||||
scheduler.Record([bindings = std::move(bindings),
|
||||
buffer_handles = std::move(buffer_handles)](vk::CommandBuffer cmdbuf) {
|
||||
cmdbuf.BindVertexBuffers2EXT(
|
||||
bindings.min_index, bindings.max_index - bindings.min_index, buffer_handles.data(),
|
||||
bindings.offsets.data(), bindings.sizes.data(), bindings.strides.data());
|
||||
scheduler.Record([bindings_ = std::move(bindings),
|
||||
buffer_handles_ = std::move(buffer_handles)](vk::CommandBuffer cmdbuf) {
|
||||
cmdbuf.BindVertexBuffers2EXT(bindings_.min_index,
|
||||
bindings_.max_index - bindings_.min_index,
|
||||
buffer_handles_.data(), bindings_.offsets.data(),
|
||||
bindings_.sizes.data(), bindings_.strides.data());
|
||||
});
|
||||
} else {
|
||||
scheduler.Record([bindings = std::move(bindings),
|
||||
buffer_handles = std::move(buffer_handles)](vk::CommandBuffer cmdbuf) {
|
||||
cmdbuf.BindVertexBuffers(bindings.min_index, bindings.max_index - bindings.min_index,
|
||||
buffer_handles.data(), bindings.offsets.data());
|
||||
scheduler.Record([bindings_ = std::move(bindings),
|
||||
buffer_handles_ = std::move(buffer_handles)](vk::CommandBuffer cmdbuf) {
|
||||
cmdbuf.BindVertexBuffers(bindings_.min_index, bindings_.max_index - bindings_.min_index,
|
||||
buffer_handles_.data(), bindings_.offsets.data());
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -573,11 +574,11 @@ void BufferCacheRuntime::BindTransformFeedbackBuffers(VideoCommon::HostBindings<
|
||||
for (u32 index = 0; index < bindings.buffers.size(); ++index) {
|
||||
buffer_handles.push_back(bindings.buffers[index]->Handle());
|
||||
}
|
||||
scheduler.Record([bindings = std::move(bindings),
|
||||
buffer_handles = std::move(buffer_handles)](vk::CommandBuffer cmdbuf) {
|
||||
cmdbuf.BindTransformFeedbackBuffersEXT(0, static_cast<u32>(buffer_handles.size()),
|
||||
buffer_handles.data(), bindings.offsets.data(),
|
||||
bindings.sizes.data());
|
||||
scheduler.Record([bindings_ = std::move(bindings),
|
||||
buffer_handles_ = std::move(buffer_handles)](vk::CommandBuffer cmdbuf) {
|
||||
cmdbuf.BindTransformFeedbackBuffersEXT(0, static_cast<u32>(buffer_handles_.size()),
|
||||
buffer_handles_.data(), bindings_.offsets.data(),
|
||||
bindings_.sizes.data());
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -469,9 +469,9 @@ void PipelineCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading
|
||||
ComputePipelineCacheKey key;
|
||||
file.read(reinterpret_cast<char*>(&key), sizeof(key));
|
||||
|
||||
workers.QueueWork([this, key, env = std::move(env), &state, &callback]() mutable {
|
||||
workers.QueueWork([this, key, env_ = std::move(env), &state, &callback]() mutable {
|
||||
ShaderPools pools;
|
||||
auto pipeline{CreateComputePipeline(pools, key, env, state.statistics.get(), false)};
|
||||
auto pipeline{CreateComputePipeline(pools, key, env_, state.statistics.get(), false)};
|
||||
std::scoped_lock lock{state.mutex};
|
||||
if (pipeline) {
|
||||
compute_cache.emplace(key, std::move(pipeline));
|
||||
@ -500,10 +500,10 @@ void PipelineCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading
|
||||
(key.state.dynamic_vertex_input != 0) != dynamic_features.has_dynamic_vertex_input) {
|
||||
return;
|
||||
}
|
||||
workers.QueueWork([this, key, envs = std::move(envs), &state, &callback]() mutable {
|
||||
workers.QueueWork([this, key, envs_ = std::move(envs), &state, &callback]() mutable {
|
||||
ShaderPools pools;
|
||||
boost::container::static_vector<Shader::Environment*, 5> env_ptrs;
|
||||
for (auto& env : envs) {
|
||||
for (auto& env : envs_) {
|
||||
env_ptrs.push_back(&env);
|
||||
}
|
||||
auto pipeline{CreateGraphicsPipeline(pools, key, MakeSpan(env_ptrs),
|
||||
@ -702,8 +702,8 @@ std::unique_ptr<ComputePipeline> PipelineCache::CreateComputePipeline(
|
||||
if (!pipeline || pipeline_cache_filename.empty()) {
|
||||
return pipeline;
|
||||
}
|
||||
serialization_thread.QueueWork([this, key, env = std::move(env)] {
|
||||
SerializePipeline(key, std::array<const GenericEnvironment*, 1>{&env},
|
||||
serialization_thread.QueueWork([this, key, env_ = std::move(env)] {
|
||||
SerializePipeline(key, std::array<const GenericEnvironment*, 1>{&env_},
|
||||
pipeline_cache_filename, CACHE_VERSION);
|
||||
});
|
||||
return pipeline;
|
||||
|
@ -98,10 +98,10 @@ HostCounter::HostCounter(QueryCache& cache_, std::shared_ptr<HostCounter> depend
|
||||
: HostCounterBase{std::move(dependency_)}, cache{cache_}, type{type_},
|
||||
query{cache_.AllocateQuery(type_)}, tick{cache_.GetScheduler().CurrentTick()} {
|
||||
const vk::Device* logical = &cache.GetDevice().GetLogical();
|
||||
cache.GetScheduler().Record([logical, query = query](vk::CommandBuffer cmdbuf) {
|
||||
cache.GetScheduler().Record([logical, query_ = query](vk::CommandBuffer cmdbuf) {
|
||||
const bool use_precise = Settings::IsGPULevelHigh();
|
||||
logical->ResetQueryPool(query.first, query.second, 1);
|
||||
cmdbuf.BeginQuery(query.first, query.second,
|
||||
logical->ResetQueryPool(query_.first, query_.second, 1);
|
||||
cmdbuf.BeginQuery(query_.first, query_.second,
|
||||
use_precise ? VK_QUERY_CONTROL_PRECISE_BIT : 0);
|
||||
});
|
||||
}
|
||||
@ -111,8 +111,9 @@ HostCounter::~HostCounter() {
|
||||
}
|
||||
|
||||
void HostCounter::EndQuery() {
|
||||
cache.GetScheduler().Record(
|
||||
[query = query](vk::CommandBuffer cmdbuf) { cmdbuf.EndQuery(query.first, query.second); });
|
||||
cache.GetScheduler().Record([query_ = query](vk::CommandBuffer cmdbuf) {
|
||||
cmdbuf.EndQuery(query_.first, query_.second);
|
||||
});
|
||||
}
|
||||
|
||||
u64 HostCounter::BlockingQuery(bool async) const {
|
||||
|
@ -1412,7 +1412,7 @@ void Image::DownloadMemory(std::span<VkBuffer> buffers_span, std::span<VkDeviceS
|
||||
}
|
||||
scheduler->RequestOutsideRenderPassOperationContext();
|
||||
scheduler->Record([buffers = std::move(buffers_vector), image = *original_image,
|
||||
aspect_mask = aspect_mask, vk_copies](vk::CommandBuffer cmdbuf) {
|
||||
aspect_mask_ = aspect_mask, vk_copies](vk::CommandBuffer cmdbuf) {
|
||||
const VkImageMemoryBarrier read_barrier{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
|
||||
.pNext = nullptr,
|
||||
@ -1424,7 +1424,7 @@ void Image::DownloadMemory(std::span<VkBuffer> buffers_span, std::span<VkDeviceS
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = image,
|
||||
.subresourceRange{
|
||||
.aspectMask = aspect_mask,
|
||||
.aspectMask = aspect_mask_,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = VK_REMAINING_MIP_LEVELS,
|
||||
.baseArrayLayer = 0,
|
||||
@ -1456,7 +1456,7 @@ void Image::DownloadMemory(std::span<VkBuffer> buffers_span, std::span<VkDeviceS
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = image,
|
||||
.subresourceRange{
|
||||
.aspectMask = aspect_mask,
|
||||
.aspectMask = aspect_mask_,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = VK_REMAINING_MIP_LEVELS,
|
||||
.baseArrayLayer = 0,
|
||||
|
8
src/video_core/vulkan_common/vma.cpp
Executable file
8
src/video_core/vulkan_common/vma.cpp
Executable file
@ -0,0 +1,8 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#define VMA_IMPLEMENTATION
|
||||
#define VMA_STATIC_VULKAN_FUNCTIONS 0
|
||||
#define VMA_DYNAMIC_VULKAN_FUNCTIONS 1
|
||||
|
||||
#include <vk_mem_alloc.h>
|
@ -135,11 +135,11 @@ void RoomJson::Delete() {
|
||||
LOG_ERROR(WebService, "Room must be registered to be deleted");
|
||||
return;
|
||||
}
|
||||
Common::DetachedTasks::AddTask(
|
||||
[host{this->host}, username{this->username}, token{this->token}, room_id{this->room_id}]() {
|
||||
// create a new client here because the this->client might be destroyed.
|
||||
Client{host, username, token}.DeleteJson(fmt::format("/lobby/{}", room_id), "", false);
|
||||
});
|
||||
Common::DetachedTasks::AddTask([host_{this->host}, username_{this->username},
|
||||
token_{this->token}, room_id_{this->room_id}]() {
|
||||
// create a new client here because the this->client might be destroyed.
|
||||
Client{host_, username_, token_}.DeleteJson(fmt::format("/lobby/{}", room_id_), "", false);
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace WebService
|
||||
|
Loading…
Reference in New Issue
Block a user