Compare commits
186 Commits
__refs_pul
...
__refs_pul
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5d686986e7 | ||
|
|
720970c4c1 | ||
|
|
30442d8a89 | ||
|
|
7f256392a1 | ||
|
|
0eacc362dd | ||
|
|
c50f170597 | ||
|
|
1994edfeb6 | ||
|
|
d35391b9f4 | ||
|
|
b39b33b1fe | ||
|
|
852858c2cb | ||
|
|
50acc0da20 | ||
|
|
bdabd17c76 | ||
|
|
3af2117c88 | ||
|
|
84934693cf | ||
|
|
1af499c15b | ||
|
|
ced1302975 | ||
|
|
70d51f72ec | ||
|
|
3a71ff44f8 | ||
|
|
2ceb514a39 | ||
|
|
0cf78a34ba | ||
|
|
3ceefc64f1 | ||
|
|
a6e6a5ac38 | ||
|
|
64275dfbf4 | ||
|
|
f178a8ef0c | ||
|
|
21c1316503 | ||
|
|
ef427e4cb0 | ||
|
|
b92c4abc96 | ||
|
|
bee6b71553 | ||
|
|
35aa153d6c | ||
|
|
f2988ecabc | ||
|
|
b275f2e475 | ||
|
|
7c4b6aab2e | ||
|
|
f2a4204245 | ||
|
|
863e2e2b4f | ||
|
|
b871388a31 | ||
|
|
7ce29ea74e | ||
|
|
43ba9db890 | ||
|
|
3d1f2bb3aa | ||
|
|
cb09ea0f01 | ||
|
|
98b351758c | ||
|
|
52e52924bb | ||
|
|
a41e9e93dd | ||
|
|
b118fa8698 | ||
|
|
d6b5f64484 | ||
|
|
2d4bbd83e6 | ||
|
|
194579bc4f | ||
|
|
d607ceacf4 | ||
|
|
f808a30f94 | ||
|
|
02178137c9 | ||
|
|
c50ad56bf5 | ||
|
|
49f9a44235 | ||
|
|
99ba26460d | ||
|
|
7aa0d97eed | ||
|
|
a3a353edf2 | ||
|
|
7c2c72a6d6 | ||
|
|
604b6d1210 | ||
|
|
92159b210e | ||
|
|
f503dbf071 | ||
|
|
c1b199bd21 | ||
|
|
60e79d50f8 | ||
|
|
06d097a18e | ||
|
|
3f8d74dec1 | ||
|
|
cd49907248 | ||
|
|
baf599c1d3 | ||
|
|
e4052a1dab | ||
|
|
fac2e073a1 | ||
|
|
61121d1b22 | ||
|
|
1b5c37fa29 | ||
|
|
189927c237 | ||
|
|
1ff9ad4e7c | ||
|
|
40c8a8c627 | ||
|
|
dd29285e35 | ||
|
|
052017e189 | ||
|
|
a8b0104923 | ||
|
|
36c21ff6cb | ||
|
|
92bebecf46 | ||
|
|
b04c7b6343 | ||
|
|
1665e2d2a6 | ||
|
|
63ed7d9af7 | ||
|
|
3c8c17be4d | ||
|
|
aed5878dd3 | ||
|
|
e5291e2031 | ||
|
|
3be87bed8d | ||
|
|
31b9797296 | ||
|
|
5299554bb0 | ||
|
|
2dbef58eeb | ||
|
|
494e34af6a | ||
|
|
ad8afaf1ef | ||
|
|
2686bf6734 | ||
|
|
33e92c15eb | ||
|
|
7461196839 | ||
|
|
b769bea61b | ||
|
|
b65314dc21 | ||
|
|
1841f63a40 | ||
|
|
b01aa721ff | ||
|
|
f190547bbb | ||
|
|
c82318c9cb | ||
|
|
c871320760 | ||
|
|
06894b0711 | ||
|
|
4e81b799f1 | ||
|
|
ef811c6425 | ||
|
|
abe6d39b1a | ||
|
|
3791c7ca82 | ||
|
|
3f4444b552 | ||
|
|
5b735a4c9d | ||
|
|
28d343d288 | ||
|
|
da6673e79a | ||
|
|
992f325662 | ||
|
|
622bc478e6 | ||
|
|
67189d747c | ||
|
|
8b996015a8 | ||
|
|
d4c79a0404 | ||
|
|
aef3ae1cb9 | ||
|
|
f40b425cd7 | ||
|
|
20b20a1086 | ||
|
|
41b4047536 | ||
|
|
de81571289 | ||
|
|
2b622411fd | ||
|
|
53cf91d151 | ||
|
|
198c6ad0d7 | ||
|
|
7dca0bc11d | ||
|
|
dc385b7392 | ||
|
|
427ce8dcef | ||
|
|
5c6ca597c5 | ||
|
|
f0dc07dbac | ||
|
|
17763a44d5 | ||
|
|
218ebc1fe8 | ||
|
|
b6719094e6 | ||
|
|
2a5014b193 | ||
|
|
764369f4c7 | ||
|
|
d5c4af2d5b | ||
|
|
5b7b7276d5 | ||
|
|
ecef109162 | ||
|
|
bad122b195 | ||
|
|
86908d569e | ||
|
|
ab441fb009 | ||
|
|
851fe91b69 | ||
|
|
07b82427ab | ||
|
|
c68ce25a14 | ||
|
|
b02d662980 | ||
|
|
0d6057b2fa | ||
|
|
3ffff78a27 | ||
|
|
894b483a0d | ||
|
|
2643752f93 | ||
|
|
9f0f827db4 | ||
|
|
50384e2619 | ||
|
|
44c73cfca0 | ||
|
|
a39760b947 | ||
|
|
74a6222b3e | ||
|
|
018cf3853e | ||
|
|
b97f340f01 | ||
|
|
bd509cedb8 | ||
|
|
0b8a7ca213 | ||
|
|
2a77c29c6d | ||
|
|
39b3c9022d | ||
|
|
818651909f | ||
|
|
c709fbba23 | ||
|
|
1ea303e2af | ||
|
|
97452b9558 | ||
|
|
8212a864ca | ||
|
|
5c829c7e4e | ||
|
|
0ee2185c59 | ||
|
|
f346b04d12 | ||
|
|
ba8be75037 | ||
|
|
4fbec776d6 | ||
|
|
0394e4bb8e | ||
|
|
39cd6306e6 | ||
|
|
54ae8d1649 | ||
|
|
403fc86c11 | ||
|
|
c317504b5f | ||
|
|
5aae61775f | ||
|
|
b6894bfc5b | ||
|
|
4ce53ffe6a | ||
|
|
493905665c | ||
|
|
fb66a455c4 | ||
|
|
bea7824bd1 | ||
|
|
7bb2dd75cd | ||
|
|
899fdb9c44 | ||
|
|
0498669b4b | ||
|
|
bb8bf740e9 | ||
|
|
7f4de3466a | ||
|
|
d702b393a4 | ||
|
|
8fdb51ab46 | ||
|
|
60a3980561 | ||
|
|
13471ddf86 | ||
|
|
d4cab35533 |
@@ -1,7 +1,7 @@
|
||||
# Download all pull requests as patches that match a specific label
|
||||
# Usage: python download-patches-by-label.py <Label to Match> <Root Path Folder to DL to>
|
||||
|
||||
import requests, sys, json, urllib3.request, shutil, subprocess, os
|
||||
import requests, sys, json, urllib3.request, shutil, subprocess, os, traceback
|
||||
|
||||
tagline = sys.argv[2]
|
||||
|
||||
@@ -33,4 +33,5 @@ try:
|
||||
for i in range(1,30):
|
||||
do_page(i)
|
||||
except:
|
||||
traceback.print_exc(file=sys.stdout)
|
||||
sys.exit(-1)
|
||||
|
||||
25
.ci/scripts/transifex/docker.sh
Executable file
25
.ci/scripts/transifex/docker.sh
Executable file
@@ -0,0 +1,25 @@
|
||||
#!/bin/bash -e
|
||||
|
||||
# Setup RC file for tx
|
||||
cat << EOF > ~/.transifexrc
|
||||
[https://www.transifex.com]
|
||||
hostname = https://www.transifex.com
|
||||
username = api
|
||||
password = $TRANSIFEX_API_TOKEN
|
||||
EOF
|
||||
|
||||
|
||||
set -x
|
||||
|
||||
echo -e "\e[1m\e[33mBuild tools information:\e[0m"
|
||||
cmake --version
|
||||
gcc -v
|
||||
tx --version
|
||||
|
||||
mkdir build && cd build
|
||||
cmake .. -DENABLE_QT_TRANSLATION=ON -DGENERATE_QT_TRANSLATION=ON -DCMAKE_BUILD_TYPE=Release -DENABLE_SDL2=OFF
|
||||
make translation
|
||||
cd ..
|
||||
|
||||
cd dist/languages
|
||||
tx push -s
|
||||
@@ -1,6 +1,8 @@
|
||||
jobs:
|
||||
- job: merge
|
||||
displayName: 'pull requests'
|
||||
pool:
|
||||
vmImage: 'ubuntu-latest'
|
||||
steps:
|
||||
- checkout: self
|
||||
submodules: recursive
|
||||
@@ -24,6 +26,8 @@ jobs:
|
||||
- job: upload_source
|
||||
displayName: 'upload'
|
||||
dependsOn: merge
|
||||
pool:
|
||||
vmImage: 'ubuntu-latest'
|
||||
steps:
|
||||
- template: ./sync-source.yml
|
||||
parameters:
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
jobs:
|
||||
- job: merge
|
||||
displayName: 'pull requests'
|
||||
pool:
|
||||
vmImage: 'ubuntu-latest'
|
||||
steps:
|
||||
- checkout: self
|
||||
submodules: recursive
|
||||
@@ -23,6 +25,8 @@ jobs:
|
||||
- job: upload_source
|
||||
displayName: 'upload'
|
||||
dependsOn: merge
|
||||
pool:
|
||||
vmImage: 'ubuntu-latest'
|
||||
steps:
|
||||
- template: ./sync-source.yml
|
||||
parameters:
|
||||
|
||||
@@ -66,5 +66,7 @@ stages:
|
||||
jobs:
|
||||
- job: github
|
||||
displayName: 'github'
|
||||
pool:
|
||||
vmImage: ubuntu-latest
|
||||
steps:
|
||||
- template: ./templates/release-github.yml
|
||||
|
||||
@@ -29,5 +29,7 @@ stages:
|
||||
jobs:
|
||||
- job: release
|
||||
displayName: 'source'
|
||||
pool:
|
||||
vmImage: 'ubuntu-latest'
|
||||
steps:
|
||||
- template: ./templates/release-private-tag.yml
|
||||
|
||||
23
.github/workflows/ci.yml
vendored
Normal file
23
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
name: yuzu-ci
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
tags: [ "*" ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
transifex:
|
||||
runs-on: ubuntu-latest
|
||||
container: yuzuemu/build-environments:linux-transifex
|
||||
if: ${{ github.repository == 'yuzu-emu/yuzu' && !github.head_ref }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: recursive
|
||||
fetch-depth: 0
|
||||
- name: Update Translation
|
||||
run: ./.ci/scripts/transifex/docker.sh
|
||||
env:
|
||||
TRANSIFEX_API_TOKEN: ${{ secrets.TRANSIFEX_API_TOKEN }}
|
||||
59
.travis.yml
59
.travis.yml
@@ -1,59 +0,0 @@
|
||||
language: cpp
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
env: NAME="clang-format"
|
||||
sudo: required
|
||||
dist: trusty
|
||||
services: docker
|
||||
install: "./.travis/clang-format/deps.sh"
|
||||
script: "./.travis/clang-format/build.sh"
|
||||
- os: linux
|
||||
env: NAME="linux build"
|
||||
sudo: required
|
||||
dist: trusty
|
||||
services: docker
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- p7zip-full
|
||||
install: "./.travis/linux/deps.sh"
|
||||
script: "./.travis/linux/build.sh"
|
||||
after_success: "./.travis/linux/upload.sh"
|
||||
cache: ccache
|
||||
- os: osx
|
||||
env: NAME="macos build"
|
||||
sudo: false
|
||||
osx_image: xcode10.2
|
||||
install: "./.travis/macos/deps.sh"
|
||||
script: "./.travis/macos/build.sh"
|
||||
after_success: "./.travis/macos/upload.sh"
|
||||
cache: ccache
|
||||
- os: linux
|
||||
env: NAME="MinGW build"
|
||||
sudo: required
|
||||
dist: trusty
|
||||
services: docker
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- p7zip-full
|
||||
install: "./.travis/linux-mingw/deps.sh"
|
||||
script: "./.travis/linux-mingw/build.sh"
|
||||
after_success: "./.travis/linux-mingw/upload.sh"
|
||||
cache: ccache
|
||||
|
||||
deploy:
|
||||
provider: releases
|
||||
api_key:
|
||||
secure: ElsIAlbvVXBNKsP31nVPysh+mf0GQA4DiL/y5iJeQxKQYR6iRoNo+RfzOBmdswdo0bE/PGeBAlfzCkp15gjhWf6Je0N6dRpczmcmLq6SSQFn1Mpq00xMJB2AgQIlaHs6KFgoUA173EBKbPwgU/NubTFpJFm/Wa+NcSWAHQXKL9KT2M3qKpxNkPl3mKEVsbch4REP+T/46vsa+ikw0VE0kIs6V93LqUQZpI2F0Dhihx8Cxr5iedkE1QsNK+QSX9iItMHbfek9OH980gP7L3lkZltyAA1Pk0c37OAgz2PwczwNKwCT8jg9PMzdcKmWouvLyAkZFuA806ElzwHY3oEd91Zm6+Bk5n24yBKZ9027AZzw38NK2Z2m9Akb8+ar8PdsKU6N5pDutX9qSLayr0oMgJ0s7/xnGBGdL3gfkPCFc50xO/2DxlsOR+zAhPNM9Y76hhGy6A7/40+9uzrJvd4nAuDvIXRzi2Yl2L7mKBE4suMKbFLtk2LlgM0qY5JMVTQ8NliaEtqopfPur2KWFVJUpWDNLtNX8xGqhfwg7cLjIiGmnxSaJBTDuZI6dpEjkWkU0n1xYhGqEqit8DbehYzazozMJ+Vsr8hku7jGlUtlw+U6HG1e19O2y4aGeSwYPROcCNz+BLwmVM8oZE3Roy3qoaa2yiFf+sy6rUHznrhsfEM=
|
||||
file_glob: true
|
||||
file: "artifacts/*"
|
||||
skip_cleanup: true
|
||||
on:
|
||||
tags: true
|
||||
|
||||
notifications:
|
||||
webhooks:
|
||||
urls:
|
||||
- https://api.yuzu-emu.org/code/travis/notify
|
||||
@@ -1,3 +0,0 @@
|
||||
#!/bin/bash -ex
|
||||
|
||||
docker run --env-file .travis/common/travis-ci.env -v $(pwd):/yuzu -v "$HOME/.ccache":/root/.ccache citraemu/build-environments:linux-clang-format /bin/bash -ex /yuzu/.travis/clang-format/docker.sh
|
||||
@@ -1,3 +0,0 @@
|
||||
#!/bin/sh -ex
|
||||
|
||||
docker pull citraemu/build-environments:linux-clang-format
|
||||
@@ -1,5 +0,0 @@
|
||||
#!/bin/bash -ex
|
||||
|
||||
# Run clang-format
|
||||
cd /yuzu
|
||||
./.travis/clang-format/script.sh
|
||||
@@ -1,37 +0,0 @@
|
||||
#!/bin/bash -ex
|
||||
|
||||
if grep -nrI '\s$' src *.yml *.txt *.md Doxyfile .gitignore .gitmodules .travis* dist/*.desktop \
|
||||
dist/*.svg dist/*.xml; then
|
||||
echo Trailing whitespace found, aborting
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Default clang-format points to default 3.5 version one
|
||||
CLANG_FORMAT=clang-format-10.0
|
||||
$CLANG_FORMAT --version
|
||||
|
||||
if [ "$TRAVIS_EVENT_TYPE" = "pull_request" ]; then
|
||||
# Get list of every file modified in this pull request
|
||||
files_to_lint="$(git diff --name-only --diff-filter=ACMRTUXB $TRAVIS_COMMIT_RANGE | grep '^src/[^.]*[.]\(cpp\|h\)$' || true)"
|
||||
else
|
||||
# Check everything for branch pushes
|
||||
files_to_lint="$(find src/ -name '*.cpp' -or -name '*.h')"
|
||||
fi
|
||||
|
||||
# Turn off tracing for this because it's too verbose
|
||||
set +x
|
||||
|
||||
for f in $files_to_lint; do
|
||||
d=$(diff -u "$f" <($CLANG_FORMAT "$f") || true)
|
||||
if ! [ -z "$d" ]; then
|
||||
echo "!!! $f not compliant to coding style, here is the fix:"
|
||||
echo "$d"
|
||||
fail=1
|
||||
fi
|
||||
done
|
||||
|
||||
set -x
|
||||
|
||||
if [ "$fail" = 1 ]; then
|
||||
exit 1
|
||||
fi
|
||||
@@ -1,25 +0,0 @@
|
||||
#!/bin/bash -ex
|
||||
|
||||
# Copy documentation
|
||||
cp license.txt "$REV_NAME"
|
||||
cp README.md "$REV_NAME"
|
||||
|
||||
tar $COMPRESSION_FLAGS "$ARCHIVE_NAME" "$REV_NAME"
|
||||
|
||||
# Find out what release we are building
|
||||
if [ -z $TRAVIS_TAG ]; then
|
||||
RELEASE_NAME=head
|
||||
else
|
||||
RELEASE_NAME=$(echo $TRAVIS_TAG | cut -d- -f1)
|
||||
if [ "$NAME" = "MinGW build" ]; then
|
||||
RELEASE_NAME="${RELEASE_NAME}-mingw"
|
||||
fi
|
||||
fi
|
||||
|
||||
mv "$REV_NAME" $RELEASE_NAME
|
||||
|
||||
7z a "$REV_NAME.7z" $RELEASE_NAME
|
||||
|
||||
# move the compiled archive into the artifacts directory to be uploaded by travis releases
|
||||
mv "$ARCHIVE_NAME" artifacts/
|
||||
mv "$REV_NAME.7z" artifacts/
|
||||
@@ -1,6 +0,0 @@
|
||||
#!/bin/bash -ex
|
||||
|
||||
GITDATE="`git show -s --date=short --format='%ad' | sed 's/-//g'`"
|
||||
GITREV="`git show -s --format='%h'`"
|
||||
|
||||
mkdir -p artifacts
|
||||
@@ -1,18 +0,0 @@
|
||||
# List of environment variables to be shared with Docker containers
|
||||
CI
|
||||
TRAVIS
|
||||
CONTINUOUS_INTEGRATION
|
||||
TRAVIS_BRANCH
|
||||
TRAVIS_BUILD_ID
|
||||
TRAVIS_BUILD_NUMBER
|
||||
TRAVIS_COMMIT
|
||||
TRAVIS_COMMIT_RANGE
|
||||
TRAVIS_EVENT_TYPE
|
||||
TRAVIS_JOB_ID
|
||||
TRAVIS_JOB_NUMBER
|
||||
TRAVIS_REPO_SLUG
|
||||
TRAVIS_TAG
|
||||
|
||||
# yuzu specific flags
|
||||
ENABLE_COMPATIBILITY_REPORTING
|
||||
USE_DISCORD_PRESENCE
|
||||
@@ -1,3 +0,0 @@
|
||||
#!/bin/bash -ex
|
||||
mkdir "$HOME/.ccache" || true
|
||||
docker run --env-file .travis/common/travis-ci.env -v $(pwd):/yuzu -v "$HOME/.ccache":/root/.ccache yuzuemu/build-environments:linux-mingw /bin/bash -ex /yuzu/.travis/linux-mingw/docker.sh
|
||||
@@ -1,3 +0,0 @@
|
||||
#!/bin/sh -ex
|
||||
|
||||
docker pull yuzuemu/build-environments:linux-mingw
|
||||
@@ -1,42 +0,0 @@
|
||||
#!/bin/bash -ex
|
||||
|
||||
cd /yuzu
|
||||
# override Travis CI unreasonable ccache size
|
||||
echo 'max_size = 3.0G' > "$HOME/.ccache/ccache.conf"
|
||||
|
||||
mkdir build && cd build
|
||||
cmake .. -G Ninja -DCMAKE_TOOLCHAIN_FILE="$(pwd)/../CMakeModules/MinGWCross.cmake" -DUSE_CCACHE=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DCMAKE_BUILD_TYPE=Release
|
||||
ninja
|
||||
|
||||
# Clean up the dirty hacks
|
||||
rm /bin/uname && mv /bin/uname1 /bin/uname
|
||||
rm /bin/cmd
|
||||
|
||||
ccache -s
|
||||
|
||||
echo "Tests skipped"
|
||||
#ctest -VV -C Release
|
||||
|
||||
echo 'Prepare binaries...'
|
||||
cd ..
|
||||
mkdir package
|
||||
|
||||
QT_PLATFORM_DLL_PATH='/usr/x86_64-w64-mingw32/lib/qt5/plugins/platforms/'
|
||||
find build/ -name "yuzu*.exe" -exec cp {} 'package' \;
|
||||
|
||||
# copy Qt plugins
|
||||
mkdir package/platforms
|
||||
cp "${QT_PLATFORM_DLL_PATH}/qwindows.dll" package/platforms/
|
||||
cp -rv "${QT_PLATFORM_DLL_PATH}/../mediaservice/" package/
|
||||
cp -rv "${QT_PLATFORM_DLL_PATH}/../imageformats/" package/
|
||||
rm -f package/mediaservice/*d.dll
|
||||
|
||||
for i in package/*.exe; do
|
||||
# we need to process pdb here, however, cv2pdb
|
||||
# does not work here, so we just simply strip all the debug symbols
|
||||
x86_64-w64-mingw32-strip "${i}"
|
||||
done
|
||||
|
||||
pip3 install pefile
|
||||
python3 .travis/linux-mingw/scan_dll.py package/*.exe "package/"
|
||||
python3 .travis/linux-mingw/scan_dll.py package/imageformats/*.dll "package/"
|
||||
@@ -1,106 +0,0 @@
|
||||
import pefile
|
||||
import sys
|
||||
import re
|
||||
import os
|
||||
import queue
|
||||
import shutil
|
||||
|
||||
# constant definitions
|
||||
KNOWN_SYS_DLLS = ['WINMM.DLL', 'MSVCRT.DLL', 'VERSION.DLL', 'MPR.DLL',
|
||||
'DWMAPI.DLL', 'UXTHEME.DLL', 'DNSAPI.DLL', 'IPHLPAPI.DLL']
|
||||
# below is for Ubuntu 18.04 with specified PPA enabled, if you are using
|
||||
# other distro or different repositories, change the following accordingly
|
||||
DLL_PATH = [
|
||||
'/usr/x86_64-w64-mingw32/bin/',
|
||||
'/usr/x86_64-w64-mingw32/lib/',
|
||||
'/usr/lib/gcc/x86_64-w64-mingw32/7.3-posix/'
|
||||
]
|
||||
|
||||
missing = []
|
||||
|
||||
|
||||
def parse_imports(file_name):
|
||||
results = []
|
||||
pe = pefile.PE(file_name, fast_load=True)
|
||||
pe.parse_data_directories()
|
||||
|
||||
for entry in pe.DIRECTORY_ENTRY_IMPORT:
|
||||
current = entry.dll.decode()
|
||||
current_u = current.upper() # b/c Windows is often case insensitive
|
||||
# here we filter out system dlls
|
||||
# dll w/ names like *32.dll are likely to be system dlls
|
||||
if current_u.upper() not in KNOWN_SYS_DLLS and not re.match(string=current_u, pattern=r'.*32\.DLL'):
|
||||
results.append(current)
|
||||
|
||||
return results
|
||||
|
||||
|
||||
def parse_imports_recursive(file_name, path_list=[]):
|
||||
q = queue.Queue() # create a FIFO queue
|
||||
# file_name can be a string or a list for the convience
|
||||
if isinstance(file_name, str):
|
||||
q.put(file_name)
|
||||
elif isinstance(file_name, list):
|
||||
for i in file_name:
|
||||
q.put(i)
|
||||
full_list = []
|
||||
while q.qsize():
|
||||
current = q.get_nowait()
|
||||
print('> %s' % current)
|
||||
deps = parse_imports(current)
|
||||
# if this dll does not have any import, ignore it
|
||||
if not deps:
|
||||
continue
|
||||
for dep in deps:
|
||||
# the dependency already included in the list, skip
|
||||
if dep in full_list:
|
||||
continue
|
||||
# find the requested dll in the provided paths
|
||||
full_path = find_dll(dep)
|
||||
if not full_path:
|
||||
missing.append(dep)
|
||||
continue
|
||||
full_list.append(dep)
|
||||
q.put(full_path)
|
||||
path_list.append(full_path)
|
||||
return full_list
|
||||
|
||||
|
||||
def find_dll(name):
|
||||
for path in DLL_PATH:
|
||||
for root, _, files in os.walk(path):
|
||||
for f in files:
|
||||
if name.lower() == f.lower():
|
||||
return os.path.join(root, f)
|
||||
|
||||
|
||||
def deploy(name, dst, dry_run=False):
|
||||
dlls_path = []
|
||||
parse_imports_recursive(name, dlls_path)
|
||||
for dll_entry in dlls_path:
|
||||
if not dry_run:
|
||||
shutil.copy(dll_entry, dst)
|
||||
else:
|
||||
print('[Dry-Run] Copy %s to %s' % (dll_entry, dst))
|
||||
print('Deploy completed.')
|
||||
return dlls_path
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) < 3:
|
||||
print('Usage: %s [files to examine ...] [target deploy directory]')
|
||||
return 1
|
||||
to_deploy = sys.argv[1:-1]
|
||||
tgt_dir = sys.argv[-1]
|
||||
if not os.path.isdir(tgt_dir):
|
||||
print('%s is not a directory.' % tgt_dir)
|
||||
return 1
|
||||
print('Scanning dependencies...')
|
||||
deploy(to_deploy, tgt_dir)
|
||||
if missing:
|
||||
print('Following DLLs are not found: %s' % ('\n'.join(missing)))
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1,13 +0,0 @@
|
||||
#!/bin/bash -ex
|
||||
|
||||
. .travis/common/pre-upload.sh
|
||||
|
||||
REV_NAME="yuzu-windows-mingw-${GITDATE}-${GITREV}"
|
||||
ARCHIVE_NAME="${REV_NAME}.tar.gz"
|
||||
COMPRESSION_FLAGS="-czvf"
|
||||
|
||||
mkdir "$REV_NAME"
|
||||
# get around the permission issues
|
||||
cp -r package/* "$REV_NAME"
|
||||
|
||||
. .travis/common/post-upload.sh
|
||||
@@ -1,4 +0,0 @@
|
||||
#!/bin/bash -ex
|
||||
|
||||
mkdir -p "$HOME/.ccache"
|
||||
docker run -e ENABLE_COMPATIBILITY_REPORTING --env-file .travis/common/travis-ci.env -v $(pwd):/yuzu -v "$HOME/.ccache":/home/yuzu/.ccache yuzuemu/build-environments:linux-fresh /bin/bash /yuzu/.travis/linux/docker.sh
|
||||
@@ -1,3 +0,0 @@
|
||||
#!/bin/sh -ex
|
||||
|
||||
docker pull yuzuemu/build-environments:linux-fresh
|
||||
@@ -1,11 +0,0 @@
|
||||
#!/bin/bash -ex
|
||||
|
||||
cd /yuzu
|
||||
|
||||
mkdir build && cd build
|
||||
cmake .. -G Ninja -DYUZU_USE_QT_WEB_ENGINE=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=/usr/lib/ccache/gcc -DCMAKE_CXX_COMPILER=/usr/lib/ccache/g++ -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DUSE_DISCORD_PRESENCE=ON
|
||||
ninja
|
||||
|
||||
ccache -s
|
||||
|
||||
ctest -VV -C Release
|
||||
@@ -1,14 +0,0 @@
|
||||
#!/bin/bash -ex
|
||||
|
||||
. .travis/common/pre-upload.sh
|
||||
|
||||
REV_NAME="yuzu-linux-${GITDATE}-${GITREV}"
|
||||
ARCHIVE_NAME="${REV_NAME}.tar.xz"
|
||||
COMPRESSION_FLAGS="-cJvf"
|
||||
|
||||
mkdir "$REV_NAME"
|
||||
|
||||
cp build/bin/yuzu-cmd "$REV_NAME"
|
||||
cp build/bin/yuzu "$REV_NAME"
|
||||
|
||||
. .travis/common/post-upload.sh
|
||||
@@ -1,17 +0,0 @@
|
||||
#!/bin/bash -ex
|
||||
|
||||
set -o pipefail
|
||||
|
||||
export MACOSX_DEPLOYMENT_TARGET=10.14
|
||||
export Qt5_DIR=$(brew --prefix)/opt/qt5
|
||||
export PATH="/usr/local/opt/ccache/libexec:$PATH"
|
||||
|
||||
# TODO: Build using ninja instead of make
|
||||
mkdir build && cd build
|
||||
cmake --version
|
||||
cmake .. -DYUZU_USE_QT_WEB_ENGINE=ON -DCMAKE_BUILD_TYPE=Release -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} -DUSE_DISCORD_PRESENCE=ON
|
||||
make -j4
|
||||
|
||||
ccache -s
|
||||
|
||||
ctest -VV -C Release
|
||||
@@ -1,6 +0,0 @@
|
||||
#!/bin/sh -ex
|
||||
|
||||
brew update
|
||||
brew install p7zip qt5 sdl2 ccache
|
||||
brew outdated cmake || brew upgrade cmake
|
||||
pip3 install macpack
|
||||
@@ -1,28 +0,0 @@
|
||||
#!/bin/bash -ex
|
||||
|
||||
. .travis/common/pre-upload.sh
|
||||
|
||||
REV_NAME="yuzu-osx-${GITDATE}-${GITREV}"
|
||||
ARCHIVE_NAME="${REV_NAME}.tar.gz"
|
||||
COMPRESSION_FLAGS="-czvf"
|
||||
|
||||
mkdir "$REV_NAME"
|
||||
|
||||
cp build/bin/yuzu-cmd "$REV_NAME"
|
||||
cp -r build/bin/yuzu.app "$REV_NAME"
|
||||
|
||||
# move libs into folder for deployment
|
||||
macpack "${REV_NAME}/yuzu.app/Contents/MacOS/yuzu" -d "../Frameworks"
|
||||
# move qt frameworks into app bundle for deployment
|
||||
$(brew --prefix)/opt/qt5/bin/macdeployqt "${REV_NAME}/yuzu.app" -executable="${REV_NAME}/yuzu.app/Contents/MacOS/yuzu"
|
||||
|
||||
# move libs into folder for deployment
|
||||
macpack "${REV_NAME}/yuzu-cmd" -d "libs"
|
||||
|
||||
# Make the launching script executable
|
||||
chmod +x ${REV_NAME}/yuzu.app/Contents/MacOS/yuzu
|
||||
|
||||
# Verify loader instructions
|
||||
find "$REV_NAME" -exec otool -L {} \;
|
||||
|
||||
. .travis/common/post-upload.sh
|
||||
@@ -411,12 +411,13 @@ if (CONAN_REQUIRED_LIBS)
|
||||
# Download conan.cmake automatically, you can also just copy the conan.cmake file
|
||||
if(NOT EXISTS "${CMAKE_BINARY_DIR}/conan.cmake")
|
||||
message(STATUS "Downloading conan.cmake from https://github.com/conan-io/cmake-conan")
|
||||
file(DOWNLOAD "https://github.com/conan-io/cmake-conan/raw/v0.15/conan.cmake"
|
||||
# TODO: Use a tagged release. The latest tagged release does not support VS2022 as of this writing.
|
||||
file(DOWNLOAD "https://raw.githubusercontent.com/conan-io/cmake-conan/43e385830ee35377dbd2dcbe8d5a9e750301ea00/conan.cmake"
|
||||
"${CMAKE_BINARY_DIR}/conan.cmake")
|
||||
endif()
|
||||
include(${CMAKE_BINARY_DIR}/conan.cmake)
|
||||
|
||||
conan_check(VERSION 1.24.0 REQUIRED)
|
||||
conan_check(VERSION 1.41.0 REQUIRED)
|
||||
|
||||
# Manually add iconv to fix a dep conflict between qt and sdl2
|
||||
# We don't need to add it through find_package or anything since the other two can find it just fine
|
||||
@@ -599,6 +600,7 @@ if (YUZU_USE_BUNDLED_FFMPEG)
|
||||
${LIBVA_LIBRARIES})
|
||||
set(FFmpeg_HWACCEL_FLAGS
|
||||
--enable-hwaccel=h264_vaapi
|
||||
--enable-hwaccel=vp8_vaapi
|
||||
--enable-hwaccel=vp9_vaapi
|
||||
--enable-libdrm)
|
||||
list(APPEND FFmpeg_HWACCEL_INCLUDE_DIRS
|
||||
@@ -619,6 +621,7 @@ if (YUZU_USE_BUNDLED_FFMPEG)
|
||||
--enable-ffnvcodec
|
||||
--enable-nvdec
|
||||
--enable-hwaccel=h264_nvdec
|
||||
--enable-hwaccel=vp8_nvdec
|
||||
--enable-hwaccel=vp9_nvdec
|
||||
--extra-cflags=-I${CUDA_INCLUDE_DIRS}
|
||||
)
|
||||
@@ -669,6 +672,7 @@ if (YUZU_USE_BUNDLED_FFMPEG)
|
||||
--disable-postproc
|
||||
--disable-swresample
|
||||
--enable-decoder=h264
|
||||
--enable-decoder=vp8
|
||||
--enable-decoder=vp9
|
||||
--cc="${CMAKE_C_COMPILER}"
|
||||
--cxx="${CMAKE_CXX_COMPILER}"
|
||||
|
||||
5826
dist/languages/ca.ts
vendored
Normal file
5826
dist/languages/ca.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
5840
dist/languages/cs.ts
vendored
Normal file
5840
dist/languages/cs.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
5821
dist/languages/da.ts
vendored
Normal file
5821
dist/languages/da.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
3698
dist/languages/de.ts
vendored
3698
dist/languages/de.ts
vendored
File diff suppressed because it is too large
Load Diff
3811
dist/languages/es.ts
vendored
3811
dist/languages/es.ts
vendored
File diff suppressed because it is too large
Load Diff
4555
dist/languages/fr.ts
vendored
4555
dist/languages/fr.ts
vendored
File diff suppressed because it is too large
Load Diff
4221
dist/languages/it.ts
vendored
4221
dist/languages/it.ts
vendored
File diff suppressed because it is too large
Load Diff
4077
dist/languages/ja_JP.ts
vendored
4077
dist/languages/ja_JP.ts
vendored
File diff suppressed because it is too large
Load Diff
5848
dist/languages/ko_KR.ts
vendored
Normal file
5848
dist/languages/ko_KR.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
5795
dist/languages/nb.ts
vendored
Normal file
5795
dist/languages/nb.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
4327
dist/languages/nl.ts
vendored
4327
dist/languages/nl.ts
vendored
File diff suppressed because it is too large
Load Diff
4117
dist/languages/pl.ts
vendored
4117
dist/languages/pl.ts
vendored
File diff suppressed because it is too large
Load Diff
3790
dist/languages/pt_BR.ts
vendored
3790
dist/languages/pt_BR.ts
vendored
File diff suppressed because it is too large
Load Diff
4541
dist/languages/pt_PT.ts
vendored
4541
dist/languages/pt_PT.ts
vendored
File diff suppressed because it is too large
Load Diff
4683
dist/languages/ru_RU.ts
vendored
4683
dist/languages/ru_RU.ts
vendored
File diff suppressed because it is too large
Load Diff
5822
dist/languages/sv.ts
vendored
Normal file
5822
dist/languages/sv.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
5852
dist/languages/tr_TR.ts
vendored
Normal file
5852
dist/languages/tr_TR.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
3806
dist/languages/zh_CN.ts
vendored
3806
dist/languages/zh_CN.ts
vendored
File diff suppressed because it is too large
Load Diff
5839
dist/languages/zh_TW.ts
vendored
Normal file
5839
dist/languages/zh_TW.ts
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2
externals/dynarmic
vendored
2
externals/dynarmic
vendored
Submodule externals/dynarmic updated: 517e35f845...cce7e4ee5d
@@ -32,6 +32,7 @@ if (MSVC)
|
||||
# /Zc:externConstexpr - Allow extern constexpr variables to have external linkage, like the standard mandates
|
||||
# /Zc:inline - Let codegen omit inline functions in object files
|
||||
# /Zc:throwingNew - Let codegen assume `operator new` (without std::nothrow) will never return null
|
||||
# /GT - Supports fiber safety for data allocated using static thread-local storage
|
||||
add_compile_options(
|
||||
/MP
|
||||
/Zi
|
||||
@@ -44,6 +45,7 @@ if (MSVC)
|
||||
/Zc:externConstexpr
|
||||
/Zc:inline
|
||||
/Zc:throwingNew
|
||||
/GT
|
||||
|
||||
# External headers diagnostics
|
||||
/experimental:external # Enables the external headers options. This option isn't required in Visual Studio 2019 version 16.10 and later
|
||||
@@ -69,6 +71,10 @@ if (MSVC)
|
||||
/we5038 # data member 'member1' will be initialized after data member 'member2'
|
||||
)
|
||||
|
||||
if (ARCHITECTURE_x86_64)
|
||||
add_compile_options(/QIntel-jcc-erratum)
|
||||
endif()
|
||||
|
||||
# /GS- - No stack buffer overflow checks
|
||||
add_compile_options("$<$<CONFIG:Release>:/GS->")
|
||||
|
||||
|
||||
@@ -55,6 +55,7 @@ add_library(common STATIC
|
||||
dynamic_library.h
|
||||
error.cpp
|
||||
error.h
|
||||
expected.h
|
||||
fiber.cpp
|
||||
fiber.h
|
||||
fs/file.cpp
|
||||
|
||||
@@ -64,7 +64,7 @@ public:
|
||||
using propagate_on_container_copy_assignment = std::true_type;
|
||||
using propagate_on_container_move_assignment = std::true_type;
|
||||
using propagate_on_container_swap = std::true_type;
|
||||
using is_always_equal = std::true_type;
|
||||
using is_always_equal = std::false_type;
|
||||
|
||||
constexpr AlignmentAllocator() noexcept = default;
|
||||
|
||||
@@ -83,6 +83,11 @@ public:
|
||||
struct rebind {
|
||||
using other = AlignmentAllocator<T2, Align>;
|
||||
};
|
||||
|
||||
template <typename T2, size_t Align2>
|
||||
constexpr bool operator==(const AlignmentAllocator<T2, Align2>&) const noexcept {
|
||||
return std::is_same_v<T, T2> && Align == Align2;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Common
|
||||
|
||||
987
src/common/expected.h
Normal file
987
src/common/expected.h
Normal file
@@ -0,0 +1,987 @@
|
||||
// Copyright 2021 yuzu Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
// This is based on the proposed implementation of std::expected (P0323)
|
||||
// https://github.com/TartanLlama/expected/blob/master/include/tl/expected.hpp
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace Common {
|
||||
|
||||
template <typename T, typename E>
|
||||
class Expected;
|
||||
|
||||
template <typename E>
|
||||
class Unexpected {
|
||||
public:
|
||||
Unexpected() = delete;
|
||||
|
||||
constexpr explicit Unexpected(const E& e) : m_val{e} {}
|
||||
|
||||
constexpr explicit Unexpected(E&& e) : m_val{std::move(e)} {}
|
||||
|
||||
constexpr E& value() & {
|
||||
return m_val;
|
||||
}
|
||||
|
||||
constexpr const E& value() const& {
|
||||
return m_val;
|
||||
}
|
||||
|
||||
constexpr E&& value() && {
|
||||
return std::move(m_val);
|
||||
}
|
||||
|
||||
constexpr const E&& value() const&& {
|
||||
return std::move(m_val);
|
||||
}
|
||||
|
||||
private:
|
||||
E m_val;
|
||||
};
|
||||
|
||||
template <typename E>
|
||||
constexpr auto operator<=>(const Unexpected<E>& lhs, const Unexpected<E>& rhs) {
|
||||
return lhs.value() <=> rhs.value();
|
||||
}
|
||||
|
||||
struct unexpect_t {
|
||||
constexpr explicit unexpect_t() = default;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
struct no_init_t {
|
||||
constexpr explicit no_init_t() = default;
|
||||
};
|
||||
|
||||
/**
|
||||
* This specialization is for when T is not trivially destructible,
|
||||
* so the destructor must be called on destruction of `expected'
|
||||
* Additionally, this requires E to be trivially destructible
|
||||
*/
|
||||
template <typename T, typename E, bool = std::is_trivially_destructible_v<T>>
|
||||
requires std::is_trivially_destructible_v<E>
|
||||
struct expected_storage_base {
|
||||
constexpr expected_storage_base() : m_val{T{}}, m_has_val{true} {}
|
||||
|
||||
constexpr expected_storage_base(no_init_t) : m_has_val{false} {}
|
||||
|
||||
template <typename... Args, std::enable_if_t<std::is_constructible_v<T, Args&&...>>* = nullptr>
|
||||
constexpr expected_storage_base(std::in_place_t, Args&&... args)
|
||||
: m_val{std::forward<Args>(args)...}, m_has_val{true} {}
|
||||
|
||||
template <typename U, typename... Args,
|
||||
std::enable_if_t<std::is_constructible_v<T, std::initializer_list<U>&, Args&&...>>* =
|
||||
nullptr>
|
||||
constexpr expected_storage_base(std::in_place_t, std::initializer_list<U> il, Args&&... args)
|
||||
: m_val{il, std::forward<Args>(args)...}, m_has_val{true} {}
|
||||
|
||||
template <typename... Args, std::enable_if_t<std::is_constructible_v<E, Args&&...>>* = nullptr>
|
||||
constexpr explicit expected_storage_base(unexpect_t, Args&&... args)
|
||||
: m_unexpect{std::forward<Args>(args)...}, m_has_val{false} {}
|
||||
|
||||
template <typename U, typename... Args,
|
||||
std::enable_if_t<std::is_constructible_v<E, std::initializer_list<U>&, Args&&...>>* =
|
||||
nullptr>
|
||||
constexpr explicit expected_storage_base(unexpect_t, std::initializer_list<U> il,
|
||||
Args&&... args)
|
||||
: m_unexpect{il, std::forward<Args>(args)...}, m_has_val{false} {}
|
||||
|
||||
~expected_storage_base() {
|
||||
if (m_has_val) {
|
||||
m_val.~T();
|
||||
}
|
||||
}
|
||||
|
||||
union {
|
||||
T m_val;
|
||||
Unexpected<E> m_unexpect;
|
||||
};
|
||||
|
||||
bool m_has_val;
|
||||
};
|
||||
|
||||
/**
|
||||
* This specialization is for when T is trivially destructible,
|
||||
* so the destructor of `expected` can be trivial
|
||||
* Additionally, this requires E to be trivially destructible
|
||||
*/
|
||||
template <typename T, typename E>
|
||||
requires std::is_trivially_destructible_v<E>
|
||||
struct expected_storage_base<T, E, true> {
|
||||
constexpr expected_storage_base() : m_val{T{}}, m_has_val{true} {}
|
||||
|
||||
constexpr expected_storage_base(no_init_t) : m_has_val{false} {}
|
||||
|
||||
template <typename... Args, std::enable_if_t<std::is_constructible_v<T, Args&&...>>* = nullptr>
|
||||
constexpr expected_storage_base(std::in_place_t, Args&&... args)
|
||||
: m_val{std::forward<Args>(args)...}, m_has_val{true} {}
|
||||
|
||||
template <typename U, typename... Args,
|
||||
std::enable_if_t<std::is_constructible_v<T, std::initializer_list<U>&, Args&&...>>* =
|
||||
nullptr>
|
||||
constexpr expected_storage_base(std::in_place_t, std::initializer_list<U> il, Args&&... args)
|
||||
: m_val{il, std::forward<Args>(args)...}, m_has_val{true} {}
|
||||
|
||||
template <typename... Args, std::enable_if_t<std::is_constructible_v<E, Args&&...>>* = nullptr>
|
||||
constexpr explicit expected_storage_base(unexpect_t, Args&&... args)
|
||||
: m_unexpect{std::forward<Args>(args)...}, m_has_val{false} {}
|
||||
|
||||
template <typename U, typename... Args,
|
||||
std::enable_if_t<std::is_constructible_v<E, std::initializer_list<U>&, Args&&...>>* =
|
||||
nullptr>
|
||||
constexpr explicit expected_storage_base(unexpect_t, std::initializer_list<U> il,
|
||||
Args&&... args)
|
||||
: m_unexpect{il, std::forward<Args>(args)...}, m_has_val{false} {}
|
||||
|
||||
~expected_storage_base() = default;
|
||||
|
||||
union {
|
||||
T m_val;
|
||||
Unexpected<E> m_unexpect;
|
||||
};
|
||||
|
||||
bool m_has_val;
|
||||
};
|
||||
|
||||
template <typename T, typename E>
|
||||
struct expected_operations_base : expected_storage_base<T, E> {
|
||||
using expected_storage_base<T, E>::expected_storage_base;
|
||||
|
||||
template <typename... Args>
|
||||
void construct(Args&&... args) noexcept {
|
||||
new (std::addressof(this->m_val)) T{std::forward<Args>(args)...};
|
||||
this->m_has_val = true;
|
||||
}
|
||||
|
||||
template <typename Rhs>
|
||||
void construct_with(Rhs&& rhs) noexcept {
|
||||
new (std::addressof(this->m_val)) T{std::forward<Rhs>(rhs).get()};
|
||||
this->m_has_val = true;
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void construct_error(Args&&... args) noexcept {
|
||||
new (std::addressof(this->m_unexpect)) Unexpected<E>{std::forward<Args>(args)...};
|
||||
this->m_has_val = false;
|
||||
}
|
||||
|
||||
void assign(const expected_operations_base& rhs) noexcept {
|
||||
if (!this->m_has_val && rhs.m_has_val) {
|
||||
geterr().~Unexpected<E>();
|
||||
construct(rhs.get());
|
||||
} else {
|
||||
assign_common(rhs);
|
||||
}
|
||||
}
|
||||
|
||||
void assign(expected_operations_base&& rhs) noexcept {
|
||||
if (!this->m_has_val && rhs.m_has_val) {
|
||||
geterr().~Unexpected<E>();
|
||||
construct(std::move(rhs).get());
|
||||
} else {
|
||||
assign_common(rhs);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Rhs>
|
||||
void assign_common(Rhs&& rhs) {
|
||||
if (this->m_has_val) {
|
||||
if (rhs.m_has_val) {
|
||||
get() = std::forward<Rhs>(rhs).get();
|
||||
} else {
|
||||
destroy_val();
|
||||
construct_error(std::forward<Rhs>(rhs).geterr());
|
||||
}
|
||||
} else {
|
||||
if (!rhs.m_has_val) {
|
||||
geterr() = std::forward<Rhs>(rhs).geterr();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool has_value() const {
|
||||
return this->m_has_val;
|
||||
}
|
||||
|
||||
constexpr T& get() & {
|
||||
return this->m_val;
|
||||
}
|
||||
|
||||
constexpr const T& get() const& {
|
||||
return this->m_val;
|
||||
}
|
||||
|
||||
constexpr T&& get() && {
|
||||
return std::move(this->m_val);
|
||||
}
|
||||
|
||||
constexpr const T&& get() const&& {
|
||||
return std::move(this->m_val);
|
||||
}
|
||||
|
||||
constexpr Unexpected<E>& geterr() & {
|
||||
return this->m_unexpect;
|
||||
}
|
||||
|
||||
constexpr const Unexpected<E>& geterr() const& {
|
||||
return this->m_unexpect;
|
||||
}
|
||||
|
||||
constexpr Unexpected<E>&& geterr() && {
|
||||
return std::move(this->m_unexpect);
|
||||
}
|
||||
|
||||
constexpr const Unexpected<E>&& geterr() const&& {
|
||||
return std::move(this->m_unexpect);
|
||||
}
|
||||
|
||||
constexpr void destroy_val() {
|
||||
get().~T();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* This manages conditionally having a trivial copy constructor
|
||||
* This specialization is for when T is trivially copy constructible
|
||||
* Additionally, this requires E to be trivially copy constructible
|
||||
*/
|
||||
template <typename T, typename E, bool = std::is_trivially_copy_constructible_v<T>>
|
||||
requires std::is_trivially_copy_constructible_v<E>
|
||||
struct expected_copy_base : expected_operations_base<T, E> {
|
||||
using expected_operations_base<T, E>::expected_operations_base;
|
||||
};
|
||||
|
||||
/**
|
||||
* This specialization is for when T is not trivially copy constructible
|
||||
* Additionally, this requires E to be trivially copy constructible
|
||||
*/
|
||||
template <typename T, typename E>
|
||||
requires std::is_trivially_copy_constructible_v<E>
|
||||
struct expected_copy_base<T, E, false> : expected_operations_base<T, E> {
|
||||
using expected_operations_base<T, E>::expected_operations_base;
|
||||
|
||||
expected_copy_base() = default;
|
||||
|
||||
expected_copy_base(const expected_copy_base& rhs)
|
||||
: expected_operations_base<T, E>{no_init_t{}} {
|
||||
if (rhs.has_value()) {
|
||||
this->construct_with(rhs);
|
||||
} else {
|
||||
this->construct_error(rhs.geterr());
|
||||
}
|
||||
}
|
||||
|
||||
expected_copy_base(expected_copy_base&&) = default;
|
||||
|
||||
expected_copy_base& operator=(const expected_copy_base&) = default;
|
||||
|
||||
expected_copy_base& operator=(expected_copy_base&&) = default;
|
||||
};
|
||||
|
||||
/**
|
||||
* This manages conditionally having a trivial move constructor
|
||||
* This specialization is for when T is trivially move constructible
|
||||
* Additionally, this requires E to be trivially move constructible
|
||||
*/
|
||||
template <typename T, typename E, bool = std::is_trivially_move_constructible_v<T>>
|
||||
requires std::is_trivially_move_constructible_v<E>
|
||||
struct expected_move_base : expected_copy_base<T, E> {
|
||||
using expected_copy_base<T, E>::expected_copy_base;
|
||||
};
|
||||
|
||||
/**
|
||||
* This specialization is for when T is not trivially move constructible
|
||||
* Additionally, this requires E to be trivially move constructible
|
||||
*/
|
||||
template <typename T, typename E>
|
||||
requires std::is_trivially_move_constructible_v<E>
|
||||
struct expected_move_base<T, E, false> : expected_copy_base<T, E> {
|
||||
using expected_copy_base<T, E>::expected_copy_base;
|
||||
|
||||
expected_move_base() = default;
|
||||
|
||||
expected_move_base(const expected_move_base&) = default;
|
||||
|
||||
expected_move_base(expected_move_base&& rhs) noexcept(std::is_nothrow_move_constructible_v<T>)
|
||||
: expected_copy_base<T, E>{no_init_t{}} {
|
||||
if (rhs.has_value()) {
|
||||
this->construct_with(std::move(rhs));
|
||||
} else {
|
||||
this->construct_error(std::move(rhs.geterr()));
|
||||
}
|
||||
}
|
||||
|
||||
expected_move_base& operator=(const expected_move_base&) = default;
|
||||
|
||||
expected_move_base& operator=(expected_move_base&&) = default;
|
||||
};
|
||||
|
||||
/**
|
||||
* This manages conditionally having a trivial copy assignment operator
|
||||
* This specialization is for when T is trivially copy assignable
|
||||
* Additionally, this requires E to be trivially copy assignable
|
||||
*/
|
||||
template <typename T, typename E,
|
||||
bool = std::conjunction_v<std::is_trivially_copy_assignable<T>,
|
||||
std::is_trivially_copy_constructible<T>,
|
||||
std::is_trivially_destructible<T>>>
|
||||
requires std::conjunction_v<std::is_trivially_copy_assignable<E>,
|
||||
std::is_trivially_copy_constructible<E>,
|
||||
std::is_trivially_destructible<E>>
|
||||
struct expected_copy_assign_base : expected_move_base<T, E> {
|
||||
using expected_move_base<T, E>::expected_move_base;
|
||||
};
|
||||
|
||||
/**
|
||||
* This specialization is for when T is not trivially copy assignable
|
||||
* Additionally, this requires E to be trivially copy assignable
|
||||
*/
|
||||
template <typename T, typename E>
|
||||
requires std::conjunction_v<std::is_trivially_copy_assignable<E>,
|
||||
std::is_trivially_copy_constructible<E>,
|
||||
std::is_trivially_destructible<E>>
|
||||
struct expected_copy_assign_base<T, E, false> : expected_move_base<T, E> {
|
||||
using expected_move_base<T, E>::expected_move_base;
|
||||
|
||||
expected_copy_assign_base() = default;
|
||||
|
||||
expected_copy_assign_base(const expected_copy_assign_base&) = default;
|
||||
|
||||
expected_copy_assign_base(expected_copy_assign_base&&) = default;
|
||||
|
||||
expected_copy_assign_base& operator=(const expected_copy_assign_base& rhs) {
|
||||
this->assign(rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
expected_copy_assign_base& operator=(expected_copy_assign_base&&) = default;
|
||||
};
|
||||
|
||||
/**
|
||||
* This manages conditionally having a trivial move assignment operator
|
||||
* This specialization is for when T is trivially move assignable
|
||||
* Additionally, this requires E to be trivially move assignable
|
||||
*/
|
||||
template <typename T, typename E,
|
||||
bool = std::conjunction_v<std::is_trivially_move_assignable<T>,
|
||||
std::is_trivially_move_constructible<T>,
|
||||
std::is_trivially_destructible<T>>>
|
||||
requires std::conjunction_v<std::is_trivially_move_assignable<E>,
|
||||
std::is_trivially_move_constructible<E>,
|
||||
std::is_trivially_destructible<E>>
|
||||
struct expected_move_assign_base : expected_copy_assign_base<T, E> {
|
||||
using expected_copy_assign_base<T, E>::expected_copy_assign_base;
|
||||
};
|
||||
|
||||
/**
|
||||
* This specialization is for when T is not trivially move assignable
|
||||
* Additionally, this requires E to be trivially move assignable
|
||||
*/
|
||||
template <typename T, typename E>
|
||||
requires std::conjunction_v<std::is_trivially_move_assignable<E>,
|
||||
std::is_trivially_move_constructible<E>,
|
||||
std::is_trivially_destructible<E>>
|
||||
struct expected_move_assign_base<T, E, false> : expected_copy_assign_base<T, E> {
|
||||
using expected_copy_assign_base<T, E>::expected_copy_assign_base;
|
||||
|
||||
expected_move_assign_base() = default;
|
||||
|
||||
expected_move_assign_base(const expected_move_assign_base&) = default;
|
||||
|
||||
expected_move_assign_base(expected_move_assign_base&&) = default;
|
||||
|
||||
expected_move_assign_base& operator=(const expected_move_assign_base&) = default;
|
||||
|
||||
expected_move_assign_base& operator=(expected_move_assign_base&& rhs) noexcept(
|
||||
std::conjunction_v<std::is_nothrow_move_constructible<T>,
|
||||
std::is_nothrow_move_assignable<T>>) {
|
||||
this->assign(std::move(rhs));
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* expected_delete_ctor_base will conditionally delete copy and move constructors
|
||||
* depending on whether T is copy/move constructible
|
||||
* Additionally, this requires E to be copy/move constructible
|
||||
*/
|
||||
template <typename T, typename E, bool EnableCopy = std::is_copy_constructible_v<T>,
|
||||
bool EnableMove = std::is_move_constructible_v<T>>
|
||||
requires std::conjunction_v<std::is_copy_constructible<E>, std::is_move_constructible<E>>
|
||||
struct expected_delete_ctor_base {
|
||||
expected_delete_ctor_base() = default;
|
||||
expected_delete_ctor_base(const expected_delete_ctor_base&) = default;
|
||||
expected_delete_ctor_base(expected_delete_ctor_base&&) noexcept = default;
|
||||
expected_delete_ctor_base& operator=(const expected_delete_ctor_base&) = default;
|
||||
expected_delete_ctor_base& operator=(expected_delete_ctor_base&&) noexcept = default;
|
||||
};
|
||||
|
||||
template <typename T, typename E>
|
||||
requires std::conjunction_v<std::is_copy_constructible<E>, std::is_move_constructible<E>>
|
||||
struct expected_delete_ctor_base<T, E, true, false> {
|
||||
expected_delete_ctor_base() = default;
|
||||
expected_delete_ctor_base(const expected_delete_ctor_base&) = default;
|
||||
expected_delete_ctor_base(expected_delete_ctor_base&&) noexcept = delete;
|
||||
expected_delete_ctor_base& operator=(const expected_delete_ctor_base&) = default;
|
||||
expected_delete_ctor_base& operator=(expected_delete_ctor_base&&) noexcept = default;
|
||||
};
|
||||
|
||||
template <typename T, typename E>
|
||||
requires std::conjunction_v<std::is_copy_constructible<E>, std::is_move_constructible<E>>
|
||||
struct expected_delete_ctor_base<T, E, false, true> {
|
||||
expected_delete_ctor_base() = default;
|
||||
expected_delete_ctor_base(const expected_delete_ctor_base&) = delete;
|
||||
expected_delete_ctor_base(expected_delete_ctor_base&&) noexcept = default;
|
||||
expected_delete_ctor_base& operator=(const expected_delete_ctor_base&) = default;
|
||||
expected_delete_ctor_base& operator=(expected_delete_ctor_base&&) noexcept = default;
|
||||
};
|
||||
|
||||
template <typename T, typename E>
|
||||
requires std::conjunction_v<std::is_copy_constructible<E>, std::is_move_constructible<E>>
|
||||
struct expected_delete_ctor_base<T, E, false, false> {
|
||||
expected_delete_ctor_base() = default;
|
||||
expected_delete_ctor_base(const expected_delete_ctor_base&) = delete;
|
||||
expected_delete_ctor_base(expected_delete_ctor_base&&) noexcept = delete;
|
||||
expected_delete_ctor_base& operator=(const expected_delete_ctor_base&) = default;
|
||||
expected_delete_ctor_base& operator=(expected_delete_ctor_base&&) noexcept = default;
|
||||
};
|
||||
|
||||
/**
|
||||
* expected_delete_assign_base will conditionally delete copy and move assignment operators
|
||||
* depending on whether T is copy/move constructible + assignable
|
||||
* Additionally, this requires E to be copy/move constructible + assignable
|
||||
*/
|
||||
template <
|
||||
typename T, typename E,
|
||||
bool EnableCopy = std::conjunction_v<std::is_copy_constructible<T>, std::is_copy_assignable<T>>,
|
||||
bool EnableMove = std::conjunction_v<std::is_move_constructible<T>, std::is_move_assignable<T>>>
|
||||
requires std::conjunction_v<std::is_copy_constructible<E>, std::is_move_constructible<E>,
|
||||
std::is_copy_assignable<E>, std::is_move_assignable<E>>
|
||||
struct expected_delete_assign_base {
|
||||
expected_delete_assign_base() = default;
|
||||
expected_delete_assign_base(const expected_delete_assign_base&) = default;
|
||||
expected_delete_assign_base(expected_delete_assign_base&&) noexcept = default;
|
||||
expected_delete_assign_base& operator=(const expected_delete_assign_base&) = default;
|
||||
expected_delete_assign_base& operator=(expected_delete_assign_base&&) noexcept = default;
|
||||
};
|
||||
|
||||
template <typename T, typename E>
|
||||
requires std::conjunction_v<std::is_copy_constructible<E>, std::is_move_constructible<E>,
|
||||
std::is_copy_assignable<E>, std::is_move_assignable<E>>
|
||||
struct expected_delete_assign_base<T, E, true, false> {
|
||||
expected_delete_assign_base() = default;
|
||||
expected_delete_assign_base(const expected_delete_assign_base&) = default;
|
||||
expected_delete_assign_base(expected_delete_assign_base&&) noexcept = default;
|
||||
expected_delete_assign_base& operator=(const expected_delete_assign_base&) = default;
|
||||
expected_delete_assign_base& operator=(expected_delete_assign_base&&) noexcept = delete;
|
||||
};
|
||||
|
||||
template <typename T, typename E>
|
||||
requires std::conjunction_v<std::is_copy_constructible<E>, std::is_move_constructible<E>,
|
||||
std::is_copy_assignable<E>, std::is_move_assignable<E>>
|
||||
struct expected_delete_assign_base<T, E, false, true> {
|
||||
expected_delete_assign_base() = default;
|
||||
expected_delete_assign_base(const expected_delete_assign_base&) = default;
|
||||
expected_delete_assign_base(expected_delete_assign_base&&) noexcept = default;
|
||||
expected_delete_assign_base& operator=(const expected_delete_assign_base&) = delete;
|
||||
expected_delete_assign_base& operator=(expected_delete_assign_base&&) noexcept = default;
|
||||
};
|
||||
|
||||
template <typename T, typename E>
|
||||
requires std::conjunction_v<std::is_copy_constructible<E>, std::is_move_constructible<E>,
|
||||
std::is_copy_assignable<E>, std::is_move_assignable<E>>
|
||||
struct expected_delete_assign_base<T, E, false, false> {
|
||||
expected_delete_assign_base() = default;
|
||||
expected_delete_assign_base(const expected_delete_assign_base&) = default;
|
||||
expected_delete_assign_base(expected_delete_assign_base&&) noexcept = default;
|
||||
expected_delete_assign_base& operator=(const expected_delete_assign_base&) = delete;
|
||||
expected_delete_assign_base& operator=(expected_delete_assign_base&&) noexcept = delete;
|
||||
};
|
||||
|
||||
/**
|
||||
* This is needed to be able to construct the expected_default_ctor_base which follows,
|
||||
* while still conditionally deleting the default constructor.
|
||||
*/
|
||||
struct default_constructor_tag {
|
||||
constexpr explicit default_constructor_tag() = default;
|
||||
};
|
||||
|
||||
/**
|
||||
* expected_default_ctor_base will ensure that expected
|
||||
* has a deleted default constructor if T is not default constructible
|
||||
* This specialization is for when T is default constructible
|
||||
*/
|
||||
template <typename T, typename E, bool Enable = std::is_default_constructible_v<T>>
|
||||
struct expected_default_ctor_base {
|
||||
constexpr expected_default_ctor_base() noexcept = default;
|
||||
constexpr expected_default_ctor_base(expected_default_ctor_base const&) noexcept = default;
|
||||
constexpr expected_default_ctor_base(expected_default_ctor_base&&) noexcept = default;
|
||||
expected_default_ctor_base& operator=(expected_default_ctor_base const&) noexcept = default;
|
||||
expected_default_ctor_base& operator=(expected_default_ctor_base&&) noexcept = default;
|
||||
|
||||
constexpr explicit expected_default_ctor_base(default_constructor_tag) {}
|
||||
};
|
||||
|
||||
template <typename T, typename E>
|
||||
struct expected_default_ctor_base<T, E, false> {
|
||||
constexpr expected_default_ctor_base() noexcept = delete;
|
||||
constexpr expected_default_ctor_base(expected_default_ctor_base const&) noexcept = default;
|
||||
constexpr expected_default_ctor_base(expected_default_ctor_base&&) noexcept = default;
|
||||
expected_default_ctor_base& operator=(expected_default_ctor_base const&) noexcept = default;
|
||||
expected_default_ctor_base& operator=(expected_default_ctor_base&&) noexcept = default;
|
||||
|
||||
constexpr explicit expected_default_ctor_base(default_constructor_tag) {}
|
||||
};
|
||||
|
||||
template <typename T, typename E, typename U>
|
||||
using expected_enable_forward_value =
|
||||
std::enable_if_t<std::is_constructible_v<T, U&&> &&
|
||||
!std::is_same_v<std::remove_cvref_t<U>, std::in_place_t> &&
|
||||
!std::is_same_v<Expected<T, E>, std::remove_cvref_t<U>> &&
|
||||
!std::is_same_v<Unexpected<E>, std::remove_cvref_t<U>>>;
|
||||
|
||||
template <typename T, typename E, typename U, typename G, typename UR, typename GR>
|
||||
using expected_enable_from_other = std::enable_if_t<
|
||||
std::is_constructible_v<T, UR> && std::is_constructible_v<E, GR> &&
|
||||
!std::is_constructible_v<T, Expected<U, G>&> && !std::is_constructible_v<T, Expected<U, G>&&> &&
|
||||
!std::is_constructible_v<T, const Expected<U, G>&> &&
|
||||
!std::is_constructible_v<T, const Expected<U, G>&&> &&
|
||||
!std::is_convertible_v<Expected<U, G>&, T> && !std::is_convertible_v<Expected<U, G>&&, T> &&
|
||||
!std::is_convertible_v<const Expected<U, G>&, T> &&
|
||||
!std::is_convertible_v<const Expected<U, G>&&, T>>;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename T, typename E>
|
||||
class Expected : private detail::expected_move_assign_base<T, E>,
|
||||
private detail::expected_delete_ctor_base<T, E>,
|
||||
private detail::expected_delete_assign_base<T, E>,
|
||||
private detail::expected_default_ctor_base<T, E> {
|
||||
public:
|
||||
using value_type = T;
|
||||
using error_type = E;
|
||||
using unexpected_type = Unexpected<E>;
|
||||
|
||||
constexpr Expected() = default;
|
||||
constexpr Expected(const Expected&) = default;
|
||||
constexpr Expected(Expected&&) = default;
|
||||
Expected& operator=(const Expected&) = default;
|
||||
Expected& operator=(Expected&&) = default;
|
||||
|
||||
template <typename... Args, std::enable_if_t<std::is_constructible_v<T, Args&&...>>* = nullptr>
|
||||
constexpr Expected(std::in_place_t, Args&&... args)
|
||||
: impl_base{std::in_place, std::forward<Args>(args)...},
|
||||
ctor_base{detail::default_constructor_tag{}} {}
|
||||
|
||||
template <typename U, typename... Args,
|
||||
std::enable_if_t<std::is_constructible_v<T, std::initializer_list<U>&, Args&&...>>* =
|
||||
nullptr>
|
||||
constexpr Expected(std::in_place_t, std::initializer_list<U> il, Args&&... args)
|
||||
: impl_base{std::in_place, il, std::forward<Args>(args)...},
|
||||
ctor_base{detail::default_constructor_tag{}} {}
|
||||
|
||||
template <typename G = E, std::enable_if_t<std::is_constructible_v<E, const G&>>* = nullptr,
|
||||
std::enable_if_t<!std::is_convertible_v<const G&, E>>* = nullptr>
|
||||
constexpr explicit Expected(const Unexpected<G>& e)
|
||||
: impl_base{unexpect_t{}, e.value()}, ctor_base{detail::default_constructor_tag{}} {}
|
||||
|
||||
template <typename G = E, std::enable_if_t<std::is_constructible_v<E, const G&>>* = nullptr,
|
||||
std::enable_if_t<std::is_convertible_v<const G&, E>>* = nullptr>
|
||||
constexpr Expected(Unexpected<G> const& e)
|
||||
: impl_base{unexpect_t{}, e.value()}, ctor_base{detail::default_constructor_tag{}} {}
|
||||
|
||||
template <typename G = E, std::enable_if_t<std::is_constructible_v<E, G&&>>* = nullptr,
|
||||
std::enable_if_t<!std::is_convertible_v<G&&, E>>* = nullptr>
|
||||
constexpr explicit Expected(Unexpected<G>&& e) noexcept(std::is_nothrow_constructible_v<E, G&&>)
|
||||
: impl_base{unexpect_t{}, std::move(e.value())}, ctor_base{
|
||||
detail::default_constructor_tag{}} {}
|
||||
|
||||
template <typename G = E, std::enable_if_t<std::is_constructible_v<E, G&&>>* = nullptr,
|
||||
std::enable_if_t<std::is_convertible_v<G&&, E>>* = nullptr>
|
||||
constexpr Expected(Unexpected<G>&& e) noexcept(std::is_nothrow_constructible_v<E, G&&>)
|
||||
: impl_base{unexpect_t{}, std::move(e.value())}, ctor_base{
|
||||
detail::default_constructor_tag{}} {}
|
||||
|
||||
template <typename... Args, std::enable_if_t<std::is_constructible_v<E, Args&&...>>* = nullptr>
|
||||
constexpr explicit Expected(unexpect_t, Args&&... args)
|
||||
: impl_base{unexpect_t{}, std::forward<Args>(args)...},
|
||||
ctor_base{detail::default_constructor_tag{}} {}
|
||||
|
||||
template <typename U, typename... Args,
|
||||
std::enable_if_t<std::is_constructible_v<E, std::initializer_list<U>&, Args&&...>>* =
|
||||
nullptr>
|
||||
constexpr explicit Expected(unexpect_t, std::initializer_list<U> il, Args&&... args)
|
||||
: impl_base{unexpect_t{}, il, std::forward<Args>(args)...},
|
||||
ctor_base{detail::default_constructor_tag{}} {}
|
||||
|
||||
template <typename U, typename G,
|
||||
std::enable_if_t<!(std::is_convertible_v<U const&, T> &&
|
||||
std::is_convertible_v<G const&, E>)>* = nullptr,
|
||||
detail::expected_enable_from_other<T, E, U, G, const U&, const G&>* = nullptr>
|
||||
constexpr explicit Expected(const Expected<U, G>& rhs)
|
||||
: ctor_base{detail::default_constructor_tag{}} {
|
||||
if (rhs.has_value()) {
|
||||
this->construct(*rhs);
|
||||
} else {
|
||||
this->construct_error(rhs.error());
|
||||
}
|
||||
}
|
||||
|
||||
template <typename U, typename G,
|
||||
std::enable_if_t<(std::is_convertible_v<U const&, T> &&
|
||||
std::is_convertible_v<G const&, E>)>* = nullptr,
|
||||
detail::expected_enable_from_other<T, E, U, G, const U&, const G&>* = nullptr>
|
||||
constexpr Expected(const Expected<U, G>& rhs) : ctor_base{detail::default_constructor_tag{}} {
|
||||
if (rhs.has_value()) {
|
||||
this->construct(*rhs);
|
||||
} else {
|
||||
this->construct_error(rhs.error());
|
||||
}
|
||||
}
|
||||
|
||||
template <typename U, typename G,
|
||||
std::enable_if_t<!(std::is_convertible_v<U&&, T> && std::is_convertible_v<G&&, E>)>* =
|
||||
nullptr,
|
||||
detail::expected_enable_from_other<T, E, U, G, U&&, G&&>* = nullptr>
|
||||
constexpr explicit Expected(Expected<U, G>&& rhs)
|
||||
: ctor_base{detail::default_constructor_tag{}} {
|
||||
if (rhs.has_value()) {
|
||||
this->construct(std::move(*rhs));
|
||||
} else {
|
||||
this->construct_error(std::move(rhs.error()));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename U, typename G,
|
||||
std::enable_if_t<(std::is_convertible_v<U&&, T> && std::is_convertible_v<G&&, E>)>* =
|
||||
nullptr,
|
||||
detail::expected_enable_from_other<T, E, U, G, U&&, G&&>* = nullptr>
|
||||
constexpr Expected(Expected<U, G>&& rhs) : ctor_base{detail::default_constructor_tag{}} {
|
||||
if (rhs.has_value()) {
|
||||
this->construct(std::move(*rhs));
|
||||
} else {
|
||||
this->construct_error(std::move(rhs.error()));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename U = T, std::enable_if_t<!std::is_convertible_v<U&&, T>>* = nullptr,
|
||||
detail::expected_enable_forward_value<T, E, U>* = nullptr>
|
||||
constexpr explicit Expected(U&& v) : Expected{std::in_place, std::forward<U>(v)} {}
|
||||
|
||||
template <typename U = T, std::enable_if_t<std::is_convertible_v<U&&, T>>* = nullptr,
|
||||
detail::expected_enable_forward_value<T, E, U>* = nullptr>
|
||||
constexpr Expected(U&& v) : Expected{std::in_place, std::forward<U>(v)} {}
|
||||
|
||||
template <typename U = T, typename G = T,
|
||||
std::enable_if_t<std::is_nothrow_constructible_v<T, U&&>>* = nullptr,
|
||||
std::enable_if_t<(
|
||||
!std::is_same_v<Expected<T, E>, std::remove_cvref_t<U>> &&
|
||||
!std::conjunction_v<std::is_scalar<T>, std::is_same<T, std::remove_cvref_t<U>>> &&
|
||||
std::is_constructible_v<T, U> && std::is_assignable_v<G&, U> &&
|
||||
std::is_nothrow_move_constructible_v<E>)>* = nullptr>
|
||||
Expected& operator=(U&& v) {
|
||||
if (has_value()) {
|
||||
val() = std::forward<U>(v);
|
||||
} else {
|
||||
err().~Unexpected<E>();
|
||||
new (valptr()) T{std::forward<U>(v)};
|
||||
this->m_has_val = true;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename U = T, typename G = T,
|
||||
std::enable_if_t<!std::is_nothrow_constructible_v<T, U&&>>* = nullptr,
|
||||
std::enable_if_t<(
|
||||
!std::is_same_v<Expected<T, E>, std::remove_cvref_t<U>> &&
|
||||
!std::conjunction_v<std::is_scalar<T>, std::is_same<T, std::remove_cvref_t<U>>> &&
|
||||
std::is_constructible_v<T, U> && std::is_assignable_v<G&, U> &&
|
||||
std::is_nothrow_move_constructible_v<E>)>* = nullptr>
|
||||
Expected& operator=(U&& v) {
|
||||
if (has_value()) {
|
||||
val() = std::forward<U>(v);
|
||||
} else {
|
||||
auto tmp = std::move(err());
|
||||
err().~Unexpected<E>();
|
||||
new (valptr()) T{std::forward<U>(v)};
|
||||
this->m_has_val = true;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename G = E, std::enable_if_t<std::is_nothrow_copy_constructible_v<G> &&
|
||||
std::is_assignable_v<G&, G>>* = nullptr>
|
||||
Expected& operator=(const Unexpected<G>& rhs) {
|
||||
if (!has_value()) {
|
||||
err() = rhs;
|
||||
} else {
|
||||
this->destroy_val();
|
||||
new (errptr()) Unexpected<E>{rhs};
|
||||
this->m_has_val = false;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename G = E, std::enable_if_t<std::is_nothrow_move_constructible_v<G> &&
|
||||
std::is_move_assignable_v<G>>* = nullptr>
|
||||
Expected& operator=(Unexpected<G>&& rhs) noexcept {
|
||||
if (!has_value()) {
|
||||
err() = std::move(rhs);
|
||||
} else {
|
||||
this->destroy_val();
|
||||
new (errptr()) Unexpected<E>{std::move(rhs)};
|
||||
this->m_has_val = false;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename... Args,
|
||||
std::enable_if_t<std::is_nothrow_constructible_v<T, Args&&...>>* = nullptr>
|
||||
void emplace(Args&&... args) {
|
||||
if (has_value()) {
|
||||
val() = T{std::forward<Args>(args)...};
|
||||
} else {
|
||||
err().~Unexpected<E>();
|
||||
new (valptr()) T{std::forward<Args>(args)...};
|
||||
this->m_has_val = true;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename... Args,
|
||||
std::enable_if_t<!std::is_nothrow_constructible_v<T, Args&&...>>* = nullptr>
|
||||
void emplace(Args&&... args) {
|
||||
if (has_value()) {
|
||||
val() = T{std::forward<Args>(args)...};
|
||||
} else {
|
||||
auto tmp = std::move(err());
|
||||
err().~Unexpected<E>();
|
||||
new (valptr()) T{std::forward<Args>(args)...};
|
||||
this->m_has_val = true;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename U, typename... Args,
|
||||
std::enable_if_t<std::is_nothrow_constructible_v<T, std::initializer_list<U>&,
|
||||
Args&&...>>* = nullptr>
|
||||
void emplace(std::initializer_list<U> il, Args&&... args) {
|
||||
if (has_value()) {
|
||||
T t{il, std::forward<Args>(args)...};
|
||||
val() = std::move(t);
|
||||
} else {
|
||||
err().~Unexpected<E>();
|
||||
new (valptr()) T{il, std::forward<Args>(args)...};
|
||||
this->m_has_val = true;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename U, typename... Args,
|
||||
std::enable_if_t<!std::is_nothrow_constructible_v<T, std::initializer_list<U>&,
|
||||
Args&&...>>* = nullptr>
|
||||
void emplace(std::initializer_list<U> il, Args&&... args) {
|
||||
if (has_value()) {
|
||||
T t{il, std::forward<Args>(args)...};
|
||||
val() = std::move(t);
|
||||
} else {
|
||||
auto tmp = std::move(err());
|
||||
err().~Unexpected<E>();
|
||||
new (valptr()) T{il, std::forward<Args>(args)...};
|
||||
this->m_has_val = true;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr T* operator->() {
|
||||
return valptr();
|
||||
}
|
||||
|
||||
constexpr const T* operator->() const {
|
||||
return valptr();
|
||||
}
|
||||
|
||||
template <typename U = T>
|
||||
constexpr U& operator*() & {
|
||||
return val();
|
||||
}
|
||||
|
||||
template <typename U = T>
|
||||
constexpr const U& operator*() const& {
|
||||
return val();
|
||||
}
|
||||
|
||||
template <typename U = T>
|
||||
constexpr U&& operator*() && {
|
||||
return std::move(val());
|
||||
}
|
||||
|
||||
template <typename U = T>
|
||||
constexpr const U&& operator*() const&& {
|
||||
return std::move(val());
|
||||
}
|
||||
|
||||
constexpr bool has_value() const noexcept {
|
||||
return this->m_has_val;
|
||||
}
|
||||
|
||||
constexpr explicit operator bool() const noexcept {
|
||||
return this->m_has_val;
|
||||
}
|
||||
|
||||
template <typename U = T>
|
||||
constexpr U& value() & {
|
||||
return val();
|
||||
}
|
||||
|
||||
template <typename U = T>
|
||||
constexpr const U& value() const& {
|
||||
return val();
|
||||
}
|
||||
|
||||
template <typename U = T>
|
||||
constexpr U&& value() && {
|
||||
return std::move(val());
|
||||
}
|
||||
|
||||
template <typename U = T>
|
||||
constexpr const U&& value() const&& {
|
||||
return std::move(val());
|
||||
}
|
||||
|
||||
constexpr E& error() & {
|
||||
return err().value();
|
||||
}
|
||||
|
||||
constexpr const E& error() const& {
|
||||
return err().value();
|
||||
}
|
||||
|
||||
constexpr E&& error() && {
|
||||
return std::move(err().value());
|
||||
}
|
||||
|
||||
constexpr const E&& error() const&& {
|
||||
return std::move(err().value());
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
constexpr T value_or(U&& v) const& {
|
||||
static_assert(std::is_copy_constructible_v<T> && std::is_convertible_v<U&&, T>,
|
||||
"T must be copy-constructible and convertible from U&&");
|
||||
return bool(*this) ? **this : static_cast<T>(std::forward<U>(v));
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
constexpr T value_or(U&& v) && {
|
||||
static_assert(std::is_move_constructible_v<T> && std::is_convertible_v<U&&, T>,
|
||||
"T must be move-constructible and convertible from U&&");
|
||||
return bool(*this) ? std::move(**this) : static_cast<T>(std::forward<U>(v));
|
||||
}
|
||||
|
||||
private:
|
||||
static_assert(!std::is_reference_v<T>, "T must not be a reference");
|
||||
static_assert(!std::is_same_v<T, std::remove_cv_t<std::in_place_t>>,
|
||||
"T must not be std::in_place_t");
|
||||
static_assert(!std::is_same_v<T, std::remove_cv_t<unexpect_t>>, "T must not be unexpect_t");
|
||||
static_assert(!std::is_same_v<T, std::remove_cv_t<Unexpected<E>>>,
|
||||
"T must not be Unexpected<E>");
|
||||
static_assert(!std::is_reference_v<E>, "E must not be a reference");
|
||||
|
||||
T* valptr() {
|
||||
return std::addressof(this->m_val);
|
||||
}
|
||||
|
||||
const T* valptr() const {
|
||||
return std::addressof(this->m_val);
|
||||
}
|
||||
|
||||
Unexpected<E>* errptr() {
|
||||
return std::addressof(this->m_unexpect);
|
||||
}
|
||||
|
||||
const Unexpected<E>* errptr() const {
|
||||
return std::addressof(this->m_unexpect);
|
||||
}
|
||||
|
||||
template <typename U = T>
|
||||
constexpr U& val() {
|
||||
return this->m_val;
|
||||
}
|
||||
|
||||
template <typename U = T>
|
||||
constexpr const U& val() const {
|
||||
return this->m_val;
|
||||
}
|
||||
|
||||
constexpr Unexpected<E>& err() {
|
||||
return this->m_unexpect;
|
||||
}
|
||||
|
||||
constexpr const Unexpected<E>& err() const {
|
||||
return this->m_unexpect;
|
||||
}
|
||||
|
||||
using impl_base = detail::expected_move_assign_base<T, E>;
|
||||
using ctor_base = detail::expected_default_ctor_base<T, E>;
|
||||
};
|
||||
|
||||
template <typename T, typename E, typename U, typename F>
|
||||
constexpr bool operator==(const Expected<T, E>& lhs, const Expected<U, F>& rhs) {
|
||||
return (lhs.has_value() != rhs.has_value())
|
||||
? false
|
||||
: (!lhs.has_value() ? lhs.error() == rhs.error() : *lhs == *rhs);
|
||||
}
|
||||
|
||||
template <typename T, typename E, typename U, typename F>
|
||||
constexpr bool operator!=(const Expected<T, E>& lhs, const Expected<U, F>& rhs) {
|
||||
return !operator==(lhs, rhs);
|
||||
}
|
||||
|
||||
template <typename T, typename E, typename U>
|
||||
constexpr bool operator==(const Expected<T, E>& x, const U& v) {
|
||||
return x.has_value() ? *x == v : false;
|
||||
}
|
||||
|
||||
template <typename T, typename E, typename U>
|
||||
constexpr bool operator==(const U& v, const Expected<T, E>& x) {
|
||||
return x.has_value() ? *x == v : false;
|
||||
}
|
||||
|
||||
template <typename T, typename E, typename U>
|
||||
constexpr bool operator!=(const Expected<T, E>& x, const U& v) {
|
||||
return !operator==(x, v);
|
||||
}
|
||||
|
||||
template <typename T, typename E, typename U>
|
||||
constexpr bool operator!=(const U& v, const Expected<T, E>& x) {
|
||||
return !operator==(v, x);
|
||||
}
|
||||
|
||||
template <typename T, typename E>
|
||||
constexpr bool operator==(const Expected<T, E>& x, const Unexpected<E>& e) {
|
||||
return x.has_value() ? false : x.error() == e.value();
|
||||
}
|
||||
|
||||
template <typename T, typename E>
|
||||
constexpr bool operator==(const Unexpected<E>& e, const Expected<T, E>& x) {
|
||||
return x.has_value() ? false : x.error() == e.value();
|
||||
}
|
||||
|
||||
template <typename T, typename E>
|
||||
constexpr bool operator!=(const Expected<T, E>& x, const Unexpected<E>& e) {
|
||||
return !operator==(x, e);
|
||||
}
|
||||
|
||||
template <typename T, typename E>
|
||||
constexpr bool operator!=(const Unexpected<E>& e, const Expected<T, E>& x) {
|
||||
return !operator==(e, x);
|
||||
}
|
||||
|
||||
} // namespace Common
|
||||
@@ -82,32 +82,35 @@ public:
|
||||
|
||||
private:
|
||||
PathManagerImpl() {
|
||||
fs::path yuzu_path;
|
||||
fs::path yuzu_path_cache;
|
||||
fs::path yuzu_path_config;
|
||||
|
||||
#ifdef _WIN32
|
||||
auto yuzu_path = GetExeDirectory() / PORTABLE_DIR;
|
||||
yuzu_path = GetExeDirectory() / PORTABLE_DIR;
|
||||
|
||||
if (!IsDir(yuzu_path)) {
|
||||
yuzu_path = GetAppDataRoamingDirectory() / YUZU_DIR;
|
||||
}
|
||||
|
||||
GenerateYuzuPath(YuzuPath::YuzuDir, yuzu_path);
|
||||
GenerateYuzuPath(YuzuPath::CacheDir, yuzu_path / CACHE_DIR);
|
||||
GenerateYuzuPath(YuzuPath::ConfigDir, yuzu_path / CONFIG_DIR);
|
||||
yuzu_path_cache = yuzu_path / CACHE_DIR;
|
||||
yuzu_path_config = yuzu_path / CONFIG_DIR;
|
||||
#else
|
||||
auto yuzu_path = GetCurrentDir() / PORTABLE_DIR;
|
||||
yuzu_path = GetCurrentDir() / PORTABLE_DIR;
|
||||
|
||||
if (Exists(yuzu_path) && IsDir(yuzu_path)) {
|
||||
GenerateYuzuPath(YuzuPath::YuzuDir, yuzu_path);
|
||||
GenerateYuzuPath(YuzuPath::CacheDir, yuzu_path / CACHE_DIR);
|
||||
GenerateYuzuPath(YuzuPath::ConfigDir, yuzu_path / CONFIG_DIR);
|
||||
yuzu_path_cache = yuzu_path / CACHE_DIR;
|
||||
yuzu_path_config = yuzu_path / CONFIG_DIR;
|
||||
} else {
|
||||
yuzu_path = GetDataDirectory("XDG_DATA_HOME") / YUZU_DIR;
|
||||
|
||||
GenerateYuzuPath(YuzuPath::YuzuDir, yuzu_path);
|
||||
GenerateYuzuPath(YuzuPath::CacheDir, GetDataDirectory("XDG_CACHE_HOME") / YUZU_DIR);
|
||||
GenerateYuzuPath(YuzuPath::ConfigDir, GetDataDirectory("XDG_CONFIG_HOME") / YUZU_DIR);
|
||||
yuzu_path_cache = GetDataDirectory("XDG_CACHE_HOME") / YUZU_DIR;
|
||||
yuzu_path_config = GetDataDirectory("XDG_CONFIG_HOME") / YUZU_DIR;
|
||||
}
|
||||
#endif
|
||||
|
||||
GenerateYuzuPath(YuzuPath::YuzuDir, yuzu_path);
|
||||
GenerateYuzuPath(YuzuPath::CacheDir, yuzu_path_cache);
|
||||
GenerateYuzuPath(YuzuPath::ConfigDir, yuzu_path_config);
|
||||
GenerateYuzuPath(YuzuPath::DumpDir, yuzu_path / DUMP_DIR);
|
||||
GenerateYuzuPath(YuzuPath::KeysDir, yuzu_path / KEYS_DIR);
|
||||
GenerateYuzuPath(YuzuPath::LoadDir, yuzu_path / LOAD_DIR);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <chrono>
|
||||
#include <climits>
|
||||
#include <exception>
|
||||
#include <stop_token>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
@@ -186,6 +187,10 @@ public:
|
||||
initialization_in_progress_suppress_logging = false;
|
||||
}
|
||||
|
||||
static void Start() {
|
||||
instance->StartBackendThread();
|
||||
}
|
||||
|
||||
Impl(const Impl&) = delete;
|
||||
Impl& operator=(const Impl&) = delete;
|
||||
|
||||
@@ -201,7 +206,7 @@ public:
|
||||
}
|
||||
|
||||
void PushEntry(Class log_class, Level log_level, const char* filename, unsigned int line_num,
|
||||
const char* function, std::string message) {
|
||||
const char* function, std::string&& message) {
|
||||
if (!filter.CheckMessage(log_class, log_level))
|
||||
return;
|
||||
const Entry& entry =
|
||||
@@ -211,40 +216,41 @@ public:
|
||||
|
||||
private:
|
||||
Impl(const std::filesystem::path& file_backend_filename, const Filter& filter_)
|
||||
: filter{filter_}, file_backend{file_backend_filename}, backend_thread{std::thread([this] {
|
||||
Common::SetCurrentThreadName("yuzu:Log");
|
||||
Entry entry;
|
||||
const auto write_logs = [this, &entry]() {
|
||||
ForEachBackend([&entry](Backend& backend) { backend.Write(entry); });
|
||||
};
|
||||
while (true) {
|
||||
entry = message_queue.PopWait();
|
||||
if (entry.final_entry) {
|
||||
break;
|
||||
}
|
||||
write_logs();
|
||||
}
|
||||
// Drain the logging queue. Only writes out up to MAX_LOGS_TO_WRITE to prevent a
|
||||
// case where a system is repeatedly spamming logs even on close.
|
||||
int max_logs_to_write = filter.IsDebug() ? INT_MAX : 100;
|
||||
while (max_logs_to_write-- && message_queue.Pop(entry)) {
|
||||
write_logs();
|
||||
}
|
||||
})} {}
|
||||
: filter{filter_}, file_backend{file_backend_filename} {}
|
||||
|
||||
~Impl() {
|
||||
StopBackendThread();
|
||||
}
|
||||
|
||||
void StartBackendThread() {
|
||||
backend_thread = std::thread([this] {
|
||||
Common::SetCurrentThreadName("yuzu:Log");
|
||||
Entry entry;
|
||||
const auto write_logs = [this, &entry]() {
|
||||
ForEachBackend([&entry](Backend& backend) { backend.Write(entry); });
|
||||
};
|
||||
while (!stop.stop_requested()) {
|
||||
entry = message_queue.PopWait(stop.get_token());
|
||||
if (entry.filename != nullptr) {
|
||||
write_logs();
|
||||
}
|
||||
}
|
||||
// Drain the logging queue. Only writes out up to MAX_LOGS_TO_WRITE to prevent a
|
||||
// case where a system is repeatedly spamming logs even on close.
|
||||
int max_logs_to_write = filter.IsDebug() ? INT_MAX : 100;
|
||||
while (max_logs_to_write-- && message_queue.Pop(entry)) {
|
||||
write_logs();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void StopBackendThread() {
|
||||
Entry stop_entry{};
|
||||
stop_entry.final_entry = true;
|
||||
message_queue.Push(stop_entry);
|
||||
stop.request_stop();
|
||||
backend_thread.join();
|
||||
}
|
||||
|
||||
Entry CreateEntry(Class log_class, Level log_level, const char* filename, unsigned int line_nr,
|
||||
const char* function, std::string message) const {
|
||||
const char* function, std::string&& message) const {
|
||||
using std::chrono::duration_cast;
|
||||
using std::chrono::microseconds;
|
||||
using std::chrono::steady_clock;
|
||||
@@ -257,7 +263,6 @@ private:
|
||||
.line_num = line_nr,
|
||||
.function = function,
|
||||
.message = std::move(message),
|
||||
.final_entry = false,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -278,8 +283,9 @@ private:
|
||||
ColorConsoleBackend color_console_backend{};
|
||||
FileBackend file_backend;
|
||||
|
||||
std::stop_source stop;
|
||||
std::thread backend_thread;
|
||||
MPSCQueue<Entry> message_queue{};
|
||||
MPSCQueue<Entry, true> message_queue{};
|
||||
std::chrono::steady_clock::time_point time_origin{std::chrono::steady_clock::now()};
|
||||
};
|
||||
} // namespace
|
||||
@@ -288,6 +294,10 @@ void Initialize() {
|
||||
Impl::Initialize();
|
||||
}
|
||||
|
||||
void Start() {
|
||||
Impl::Start();
|
||||
}
|
||||
|
||||
void DisableLoggingInTests() {
|
||||
initialization_in_progress_suppress_logging = true;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@ class Filter;
|
||||
/// Initializes the logging system. This should be the first thing called in main.
|
||||
void Initialize();
|
||||
|
||||
void Start();
|
||||
|
||||
void DisableLoggingInTests();
|
||||
|
||||
/**
|
||||
|
||||
@@ -22,7 +22,6 @@ struct Entry {
|
||||
unsigned int line_num = 0;
|
||||
std::string function;
|
||||
std::string message;
|
||||
bool final_entry = false;
|
||||
};
|
||||
|
||||
} // namespace Common::Log
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
@@ -487,9 +486,9 @@ struct Values {
|
||||
// System
|
||||
Setting<std::optional<u32>> rng_seed{std::optional<u32>(), "rng_seed"};
|
||||
// Measured in seconds since epoch
|
||||
std::optional<std::chrono::seconds> custom_rtc;
|
||||
std::optional<s64> custom_rtc;
|
||||
// Set on game boot, reset on stop. Seconds difference between current time and `custom_rtc`
|
||||
std::chrono::seconds custom_rtc_differential;
|
||||
s64 custom_rtc_differential;
|
||||
|
||||
BasicSetting<s32> current_user{0, "current_user"};
|
||||
RangedSetting<s32> language_index{1, 0, 17, "language_index"};
|
||||
|
||||
@@ -180,20 +180,20 @@ std::wstring UTF8ToUTF16W(const std::string& input) {
|
||||
|
||||
#endif
|
||||
|
||||
std::string StringFromFixedZeroTerminatedBuffer(const char* buffer, std::size_t max_len) {
|
||||
std::string StringFromFixedZeroTerminatedBuffer(std::string_view buffer, std::size_t max_len) {
|
||||
std::size_t len = 0;
|
||||
while (len < max_len && buffer[len] != '\0')
|
||||
while (len < buffer.length() && len < max_len && buffer[len] != '\0') {
|
||||
++len;
|
||||
|
||||
return std::string(buffer, len);
|
||||
}
|
||||
return std::string(buffer.begin(), buffer.begin() + len);
|
||||
}
|
||||
|
||||
std::u16string UTF16StringFromFixedZeroTerminatedBuffer(std::u16string_view buffer,
|
||||
std::size_t max_len) {
|
||||
std::size_t len = 0;
|
||||
while (len < max_len && buffer[len] != '\0')
|
||||
while (len < buffer.length() && len < max_len && buffer[len] != '\0') {
|
||||
++len;
|
||||
|
||||
}
|
||||
return std::u16string(buffer.begin(), buffer.begin() + len);
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ template <typename InIt>
|
||||
* Creates a std::string from a fixed-size NUL-terminated char buffer. If the buffer isn't
|
||||
* NUL-terminated then the string ends at max_len characters.
|
||||
*/
|
||||
[[nodiscard]] std::string StringFromFixedZeroTerminatedBuffer(const char* buffer,
|
||||
[[nodiscard]] std::string StringFromFixedZeroTerminatedBuffer(std::string_view buffer,
|
||||
std::size_t max_len);
|
||||
|
||||
/**
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
|
||||
#include <dynarmic/interface/A32/a32.h>
|
||||
#include <dynarmic/interface/A64/a64.h>
|
||||
#include <dynarmic/interface/exclusive_monitor.h>
|
||||
#include "common/common_types.h"
|
||||
#include "common/hash.h"
|
||||
#include "core/arm/arm_interface.h"
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#include "core/core_timing.h"
|
||||
#include "core/hardware_properties.h"
|
||||
#include "core/hle/kernel/k_process.h"
|
||||
#include "core/hle/kernel/k_scheduler.h"
|
||||
#include "core/hle/kernel/svc.h"
|
||||
#include "core/memory.h"
|
||||
|
||||
@@ -263,7 +262,7 @@ void ARM_Dynarmic_64::Run() {
|
||||
}
|
||||
|
||||
void ARM_Dynarmic_64::Step() {
|
||||
cb->InterpreterFallback(jit->GetPC(), 1);
|
||||
jit->Step();
|
||||
}
|
||||
|
||||
ARM_Dynarmic_64::ARM_Dynarmic_64(System& system_, CPUInterrupts& interrupt_handlers_,
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include "core/arm/dynarmic/arm_dynarmic_cp15.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/core_timing_util.h"
|
||||
|
||||
using Callback = Dynarmic::A32::Coprocessor::Callback;
|
||||
using CallbackOrAccessOneWord = Dynarmic::A32::Coprocessor::CallbackOrAccessOneWord;
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
#include <dynarmic/interface/A32/coprocessor.h>
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <cinttypes>
|
||||
#include <memory>
|
||||
#include "core/arm/dynarmic/arm_exclusive_monitor.h"
|
||||
#include "core/memory.h"
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <dynarmic/interface/exclusive_monitor.h>
|
||||
|
||||
@@ -19,20 +19,16 @@
|
||||
#include "core/cpu_manager.h"
|
||||
#include "core/device_memory.h"
|
||||
#include "core/file_sys/bis_factory.h"
|
||||
#include "core/file_sys/card_image.h"
|
||||
#include "core/file_sys/mode.h"
|
||||
#include "core/file_sys/patch_manager.h"
|
||||
#include "core/file_sys/registered_cache.h"
|
||||
#include "core/file_sys/romfs_factory.h"
|
||||
#include "core/file_sys/savedata_factory.h"
|
||||
#include "core/file_sys/sdmc_factory.h"
|
||||
#include "core/file_sys/vfs_concat.h"
|
||||
#include "core/file_sys/vfs_real.h"
|
||||
#include "core/hardware_interrupt_manager.h"
|
||||
#include "core/hle/kernel/k_client_port.h"
|
||||
#include "core/hle/kernel/k_process.h"
|
||||
#include "core/hle/kernel/k_scheduler.h"
|
||||
#include "core/hle/kernel/k_thread.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
#include "core/hle/kernel/physical_core.h"
|
||||
#include "core/hle/service/am/applets/applets.h"
|
||||
@@ -83,12 +79,6 @@ FileSys::StorageId GetStorageIdForFrontendSlot(
|
||||
}
|
||||
}
|
||||
|
||||
void KProcessDeleter(Kernel::KProcess* process) {
|
||||
process->Destroy();
|
||||
}
|
||||
|
||||
using KProcessPtr = std::unique_ptr<Kernel::KProcess, decltype(&KProcessDeleter)>;
|
||||
|
||||
} // Anonymous namespace
|
||||
|
||||
FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
|
||||
@@ -139,27 +129,47 @@ struct System::Impl {
|
||||
: kernel{system}, fs_controller{system}, memory{system},
|
||||
cpu_manager{system}, reporter{system}, applet_manager{system}, time_manager{system} {}
|
||||
|
||||
ResultStatus Run() {
|
||||
status = ResultStatus::Success;
|
||||
SystemResultStatus Run() {
|
||||
std::unique_lock<std::mutex> lk(suspend_guard);
|
||||
status = SystemResultStatus::Success;
|
||||
|
||||
kernel.Suspend(false);
|
||||
core_timing.SyncPause(false);
|
||||
cpu_manager.Pause(false);
|
||||
is_paused = false;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
ResultStatus Pause() {
|
||||
status = ResultStatus::Success;
|
||||
SystemResultStatus Pause() {
|
||||
std::unique_lock<std::mutex> lk(suspend_guard);
|
||||
status = SystemResultStatus::Success;
|
||||
|
||||
core_timing.SyncPause(true);
|
||||
kernel.Suspend(true);
|
||||
cpu_manager.Pause(true);
|
||||
is_paused = true;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
ResultStatus Init(System& system, Frontend::EmuWindow& emu_window) {
|
||||
std::unique_lock<std::mutex> StallCPU() {
|
||||
std::unique_lock<std::mutex> lk(suspend_guard);
|
||||
kernel.Suspend(true);
|
||||
core_timing.SyncPause(true);
|
||||
cpu_manager.Pause(true);
|
||||
return lk;
|
||||
}
|
||||
|
||||
void UnstallCPU() {
|
||||
if (!is_paused) {
|
||||
core_timing.SyncPause(false);
|
||||
kernel.Suspend(false);
|
||||
cpu_manager.Pause(false);
|
||||
}
|
||||
}
|
||||
|
||||
SystemResultStatus Init(System& system, Frontend::EmuWindow& emu_window) {
|
||||
LOG_DEBUG(Core, "initialized OK");
|
||||
|
||||
device_memory = std::make_unique<Core::DeviceMemory>();
|
||||
@@ -176,8 +186,9 @@ struct System::Impl {
|
||||
cpu_manager.Initialize();
|
||||
core_timing.Initialize([&system]() { system.RegisterHostThread(); });
|
||||
|
||||
const auto current_time = std::chrono::duration_cast<std::chrono::seconds>(
|
||||
std::chrono::system_clock::now().time_since_epoch());
|
||||
const auto posix_time = std::chrono::system_clock::now().time_since_epoch();
|
||||
const auto current_time =
|
||||
std::chrono::duration_cast<std::chrono::seconds>(posix_time).count();
|
||||
Settings::values.custom_rtc_differential =
|
||||
Settings::values.custom_rtc.value_or(current_time) - current_time;
|
||||
|
||||
@@ -197,7 +208,7 @@ struct System::Impl {
|
||||
|
||||
gpu_core = VideoCore::CreateGPU(emu_window, system);
|
||||
if (!gpu_core) {
|
||||
return ResultStatus::ErrorVideoCore;
|
||||
return SystemResultStatus::ErrorVideoCore;
|
||||
}
|
||||
|
||||
service_manager = std::make_shared<Service::SM::ServiceManager>(kernel);
|
||||
@@ -217,21 +228,22 @@ struct System::Impl {
|
||||
|
||||
LOG_DEBUG(Core, "Initialized OK");
|
||||
|
||||
return ResultStatus::Success;
|
||||
return SystemResultStatus::Success;
|
||||
}
|
||||
|
||||
ResultStatus Load(System& system, Frontend::EmuWindow& emu_window, const std::string& filepath,
|
||||
u64 program_id, std::size_t program_index) {
|
||||
SystemResultStatus Load(System& system, Frontend::EmuWindow& emu_window,
|
||||
const std::string& filepath, u64 program_id,
|
||||
std::size_t program_index) {
|
||||
app_loader = Loader::GetLoader(system, GetGameFileFromPath(virtual_filesystem, filepath),
|
||||
program_id, program_index);
|
||||
|
||||
if (!app_loader) {
|
||||
LOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath);
|
||||
return ResultStatus::ErrorGetLoader;
|
||||
return SystemResultStatus::ErrorGetLoader;
|
||||
}
|
||||
|
||||
ResultStatus init_result{Init(system, emu_window)};
|
||||
if (init_result != ResultStatus::Success) {
|
||||
SystemResultStatus init_result{Init(system, emu_window)};
|
||||
if (init_result != SystemResultStatus::Success) {
|
||||
LOG_CRITICAL(Core, "Failed to initialize system (Error {})!",
|
||||
static_cast<int>(init_result));
|
||||
Shutdown();
|
||||
@@ -239,21 +251,20 @@ struct System::Impl {
|
||||
}
|
||||
|
||||
telemetry_session->AddInitialInfo(*app_loader, fs_controller, *content_provider);
|
||||
main_process = KProcessPtr{Kernel::KProcess::Create(system.Kernel()), KProcessDeleter};
|
||||
ASSERT(Kernel::KProcess::Initialize(main_process.get(), system, "main",
|
||||
auto main_process = Kernel::KProcess::Create(system.Kernel());
|
||||
ASSERT(Kernel::KProcess::Initialize(main_process, system, "main",
|
||||
Kernel::KProcess::ProcessType::Userland)
|
||||
.IsSuccess());
|
||||
main_process->Open();
|
||||
const auto [load_result, load_parameters] = app_loader->Load(*main_process, system);
|
||||
if (load_result != Loader::ResultStatus::Success) {
|
||||
LOG_CRITICAL(Core, "Failed to load ROM (Error {})!", load_result);
|
||||
Shutdown();
|
||||
|
||||
return static_cast<ResultStatus>(static_cast<u32>(ResultStatus::ErrorLoader) +
|
||||
static_cast<u32>(load_result));
|
||||
return static_cast<SystemResultStatus>(
|
||||
static_cast<u32>(SystemResultStatus::ErrorLoader) + static_cast<u32>(load_result));
|
||||
}
|
||||
AddGlueRegistrationForProcess(*app_loader, *main_process);
|
||||
kernel.MakeCurrentProcess(main_process.get());
|
||||
kernel.MakeCurrentProcess(main_process);
|
||||
kernel.InitializeCores();
|
||||
|
||||
// Initialize cheat engine
|
||||
@@ -282,7 +293,7 @@ struct System::Impl {
|
||||
GetAndResetPerfStats();
|
||||
perf_stats->BeginSystemFrame();
|
||||
|
||||
status = ResultStatus::Success;
|
||||
status = SystemResultStatus::Success;
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -313,13 +324,11 @@ struct System::Impl {
|
||||
time_manager.Shutdown();
|
||||
core_timing.Shutdown();
|
||||
app_loader.reset();
|
||||
perf_stats.reset();
|
||||
gpu_core.reset();
|
||||
perf_stats.reset();
|
||||
kernel.Shutdown();
|
||||
memory.Reset();
|
||||
applet_manager.ClearAll();
|
||||
// TODO: The main process should be freed based on KAutoObject ref counting.
|
||||
main_process.reset();
|
||||
|
||||
LOG_DEBUG(Core, "Shutdown OK");
|
||||
}
|
||||
@@ -340,7 +349,7 @@ struct System::Impl {
|
||||
}
|
||||
|
||||
Service::Glue::ApplicationLaunchProperty launch{};
|
||||
launch.title_id = process.GetTitleID();
|
||||
launch.title_id = process.GetProgramID();
|
||||
|
||||
FileSys::PatchManager pm{launch.title_id, fs_controller, *content_provider};
|
||||
launch.version = pm.GetGameVersion().value_or(0);
|
||||
@@ -355,7 +364,7 @@ struct System::Impl {
|
||||
arp_manager.Register(launch.title_id, launch, std::move(nacp_data));
|
||||
}
|
||||
|
||||
void SetStatus(ResultStatus new_status, const char* details = nullptr) {
|
||||
void SetStatus(SystemResultStatus new_status, const char* details = nullptr) {
|
||||
status = new_status;
|
||||
if (details) {
|
||||
status_details = details;
|
||||
@@ -366,6 +375,9 @@ struct System::Impl {
|
||||
return perf_stats->GetAndResetStats(core_timing.GetGlobalTimeUs());
|
||||
}
|
||||
|
||||
std::mutex suspend_guard;
|
||||
bool is_paused{};
|
||||
|
||||
Timing::CoreTiming core_timing;
|
||||
Kernel::KernelCore kernel;
|
||||
/// RealVfsFilesystem instance
|
||||
@@ -378,7 +390,6 @@ struct System::Impl {
|
||||
std::unique_ptr<Tegra::GPU> gpu_core;
|
||||
std::unique_ptr<Hardware::InterruptManager> interrupt_manager;
|
||||
std::unique_ptr<Core::DeviceMemory> device_memory;
|
||||
KProcessPtr main_process{nullptr, KProcessDeleter};
|
||||
Core::Memory::Memory memory;
|
||||
CpuManager cpu_manager;
|
||||
std::atomic_bool is_powered_on{};
|
||||
@@ -411,7 +422,7 @@ struct System::Impl {
|
||||
/// Network instance
|
||||
Network::NetworkInstance network_instance;
|
||||
|
||||
ResultStatus status = ResultStatus::Success;
|
||||
SystemResultStatus status = SystemResultStatus::Success;
|
||||
std::string status_details = "";
|
||||
|
||||
std::unique_ptr<Core::PerfStats> perf_stats;
|
||||
@@ -428,22 +439,9 @@ struct System::Impl {
|
||||
};
|
||||
|
||||
System::System() : impl{std::make_unique<Impl>(*this)} {}
|
||||
|
||||
System::~System() = default;
|
||||
|
||||
System& System::GetInstance() {
|
||||
if (!s_instance) {
|
||||
throw std::runtime_error("Using System instance before its initialization");
|
||||
}
|
||||
return *s_instance;
|
||||
}
|
||||
|
||||
void System::InitializeGlobalInstance() {
|
||||
if (s_instance) {
|
||||
throw std::runtime_error("Reinitializing Global System instance.");
|
||||
}
|
||||
s_instance = std::unique_ptr<System>(new System);
|
||||
}
|
||||
|
||||
CpuManager& System::GetCpuManager() {
|
||||
return impl->cpu_manager;
|
||||
}
|
||||
@@ -452,16 +450,16 @@ const CpuManager& System::GetCpuManager() const {
|
||||
return impl->cpu_manager;
|
||||
}
|
||||
|
||||
System::ResultStatus System::Run() {
|
||||
SystemResultStatus System::Run() {
|
||||
return impl->Run();
|
||||
}
|
||||
|
||||
System::ResultStatus System::Pause() {
|
||||
SystemResultStatus System::Pause() {
|
||||
return impl->Pause();
|
||||
}
|
||||
|
||||
System::ResultStatus System::SingleStep() {
|
||||
return ResultStatus::Success;
|
||||
SystemResultStatus System::SingleStep() {
|
||||
return SystemResultStatus::Success;
|
||||
}
|
||||
|
||||
void System::InvalidateCpuInstructionCaches() {
|
||||
@@ -476,8 +474,16 @@ void System::Shutdown() {
|
||||
impl->Shutdown();
|
||||
}
|
||||
|
||||
System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::string& filepath,
|
||||
u64 program_id, std::size_t program_index) {
|
||||
std::unique_lock<std::mutex> System::StallCPU() {
|
||||
return impl->StallCPU();
|
||||
}
|
||||
|
||||
void System::UnstallCPU() {
|
||||
impl->UnstallCPU();
|
||||
}
|
||||
|
||||
SystemResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::string& filepath,
|
||||
u64 program_id, std::size_t program_index) {
|
||||
return impl->Load(*this, emu_window, filepath, program_id, program_index);
|
||||
}
|
||||
|
||||
@@ -633,11 +639,15 @@ const Core::SpeedLimiter& System::SpeedLimiter() const {
|
||||
return impl->speed_limiter;
|
||||
}
|
||||
|
||||
u64 System::GetCurrentProcessProgramID() const {
|
||||
return impl->kernel.CurrentProcess()->GetProgramID();
|
||||
}
|
||||
|
||||
Loader::ResultStatus System::GetGameName(std::string& out) const {
|
||||
return impl->GetGameName(out);
|
||||
}
|
||||
|
||||
void System::SetStatus(ResultStatus new_status, const char* details) {
|
||||
void System::SetStatus(SystemResultStatus new_status, const char* details) {
|
||||
impl->SetStatus(new_status, details);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -104,55 +105,49 @@ struct PerfStatsResults;
|
||||
FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
|
||||
const std::string& path);
|
||||
|
||||
/// Enumeration representing the return values of the System Initialize and Load process.
|
||||
enum class SystemResultStatus : u32 {
|
||||
Success, ///< Succeeded
|
||||
ErrorNotInitialized, ///< Error trying to use core prior to initialization
|
||||
ErrorGetLoader, ///< Error finding the correct application loader
|
||||
ErrorSystemFiles, ///< Error in finding system files
|
||||
ErrorSharedFont, ///< Error in finding shared font
|
||||
ErrorVideoCore, ///< Error in the video core
|
||||
ErrorUnknown, ///< Any other error
|
||||
ErrorLoader, ///< The base for loader errors (too many to repeat)
|
||||
};
|
||||
|
||||
class System {
|
||||
public:
|
||||
using CurrentBuildProcessID = std::array<u8, 0x20>;
|
||||
|
||||
explicit System();
|
||||
|
||||
~System();
|
||||
|
||||
System(const System&) = delete;
|
||||
System& operator=(const System&) = delete;
|
||||
|
||||
System(System&&) = delete;
|
||||
System& operator=(System&&) = delete;
|
||||
|
||||
~System();
|
||||
|
||||
/**
|
||||
* Gets the instance of the System singleton class.
|
||||
* @returns Reference to the instance of the System singleton class.
|
||||
*/
|
||||
[[deprecated("Use of the global system instance is deprecated")]] static System& GetInstance();
|
||||
|
||||
static void InitializeGlobalInstance();
|
||||
|
||||
/// Enumeration representing the return values of the System Initialize and Load process.
|
||||
enum class ResultStatus : u32 {
|
||||
Success, ///< Succeeded
|
||||
ErrorNotInitialized, ///< Error trying to use core prior to initialization
|
||||
ErrorGetLoader, ///< Error finding the correct application loader
|
||||
ErrorSystemFiles, ///< Error in finding system files
|
||||
ErrorSharedFont, ///< Error in finding shared font
|
||||
ErrorVideoCore, ///< Error in the video core
|
||||
ErrorUnknown, ///< Any other error
|
||||
ErrorLoader, ///< The base for loader errors (too many to repeat)
|
||||
};
|
||||
|
||||
/**
|
||||
* Run the OS and Application
|
||||
* This function will start emulation and run the relevant devices
|
||||
*/
|
||||
[[nodiscard]] ResultStatus Run();
|
||||
[[nodiscard]] SystemResultStatus Run();
|
||||
|
||||
/**
|
||||
* Pause the OS and Application
|
||||
* This function will pause emulation and stop the relevant devices
|
||||
*/
|
||||
[[nodiscard]] ResultStatus Pause();
|
||||
[[nodiscard]] SystemResultStatus Pause();
|
||||
|
||||
/**
|
||||
* Step the CPU one instruction
|
||||
* @return Result status, indicating whether or not the operation succeeded.
|
||||
*/
|
||||
[[nodiscard]] ResultStatus SingleStep();
|
||||
[[nodiscard]] SystemResultStatus SingleStep();
|
||||
|
||||
/**
|
||||
* Invalidate the CPU instruction caches
|
||||
@@ -166,16 +161,20 @@ public:
|
||||
/// Shutdown the emulated system.
|
||||
void Shutdown();
|
||||
|
||||
std::unique_lock<std::mutex> StallCPU();
|
||||
void UnstallCPU();
|
||||
|
||||
/**
|
||||
* Load an executable application.
|
||||
* @param emu_window Reference to the host-system window used for video output and keyboard
|
||||
* input.
|
||||
* @param filepath String path to the executable application to load on the host file system.
|
||||
* @param program_index Specifies the index within the container of the program to launch.
|
||||
* @returns ResultStatus code, indicating if the operation succeeded.
|
||||
* @returns SystemResultStatus code, indicating if the operation succeeded.
|
||||
*/
|
||||
[[nodiscard]] ResultStatus Load(Frontend::EmuWindow& emu_window, const std::string& filepath,
|
||||
u64 program_id = 0, std::size_t program_index = 0);
|
||||
[[nodiscard]] SystemResultStatus Load(Frontend::EmuWindow& emu_window,
|
||||
const std::string& filepath, u64 program_id = 0,
|
||||
std::size_t program_index = 0);
|
||||
|
||||
/**
|
||||
* Indicates if the emulated system is powered on (all subsystems initialized and able to run an
|
||||
@@ -298,10 +297,12 @@ public:
|
||||
/// Provides a constant reference to the speed limiter
|
||||
[[nodiscard]] const Core::SpeedLimiter& SpeedLimiter() const;
|
||||
|
||||
[[nodiscard]] u64 GetCurrentProcessProgramID() const;
|
||||
|
||||
/// Gets the name of the current game
|
||||
[[nodiscard]] Loader::ResultStatus GetGameName(std::string& out) const;
|
||||
|
||||
void SetStatus(ResultStatus new_status, const char* details);
|
||||
void SetStatus(SystemResultStatus new_status, const char* details);
|
||||
|
||||
[[nodiscard]] const std::string& GetStatusDetails() const;
|
||||
|
||||
@@ -403,12 +404,8 @@ public:
|
||||
void ApplySettings();
|
||||
|
||||
private:
|
||||
System();
|
||||
|
||||
struct Impl;
|
||||
std::unique_ptr<Impl> impl;
|
||||
|
||||
inline static std::unique_ptr<System> s_instance{};
|
||||
};
|
||||
|
||||
} // namespace Core
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#include "common/microprofile.h"
|
||||
#include "common/scope_exit.h"
|
||||
#include "common/thread.h"
|
||||
#include "core/arm/exclusive_monitor.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/cpu_manager.h"
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include "common/assert.h"
|
||||
#include "core/crypto/ctr_encryption_layer.h"
|
||||
|
||||
namespace Core::Crypto {
|
||||
|
||||
@@ -10,14 +10,12 @@
|
||||
#include <locale>
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#include <string_view>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
#include <mbedtls/bignum.h>
|
||||
#include <mbedtls/cipher.h>
|
||||
#include <mbedtls/cmac.h>
|
||||
#include <mbedtls/sha256.h>
|
||||
#include "common/common_funcs.h"
|
||||
#include "common/fs/file.h"
|
||||
#include "common/fs/fs.h"
|
||||
#include "common/fs/path_util.h"
|
||||
@@ -30,7 +28,6 @@
|
||||
#include "core/crypto/partition_data_manager.h"
|
||||
#include "core/file_sys/content_archive.h"
|
||||
#include "core/file_sys/nca_metadata.h"
|
||||
#include "core/file_sys/partition_filesystem.h"
|
||||
#include "core/file_sys/registered_cache.h"
|
||||
#include "core/hle/service/filesystem/filesystem.h"
|
||||
#include "core/loader/loader.h"
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#include "common/common_funcs.h"
|
||||
#include "common/common_types.h"
|
||||
#include "core/crypto/partition_data_manager.h"
|
||||
#include "core/file_sys/vfs_types.h"
|
||||
|
||||
namespace Common::FS {
|
||||
class IOFile;
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#include <cctype>
|
||||
#include <cstring>
|
||||
#include <mbedtls/sha256.h>
|
||||
#include "common/assert.h"
|
||||
#include "common/common_funcs.h"
|
||||
#include "common/common_types.h"
|
||||
#include "common/hex_util.h"
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include "common/assert.h"
|
||||
#include "core/crypto/xts_encryption_layer.h"
|
||||
|
||||
namespace Core::Crypto {
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include "core/file_sys/nca_metadata.h"
|
||||
#include "core/file_sys/partition_filesystem.h"
|
||||
#include "core/file_sys/submission_package.h"
|
||||
#include "core/file_sys/vfs_concat.h"
|
||||
#include "core/file_sys/vfs_offset.h"
|
||||
#include "core/file_sys/vfs_vector.h"
|
||||
#include "core/loader/loader.h"
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
namespace FileSys {
|
||||
|
||||
const std::array<const char*, 15> LANGUAGE_NAMES{{
|
||||
const std::array<const char*, 16> LANGUAGE_NAMES{{
|
||||
"AmericanEnglish",
|
||||
"BritishEnglish",
|
||||
"Japanese",
|
||||
@@ -25,6 +25,7 @@ const std::array<const char*, 15> LANGUAGE_NAMES{{
|
||||
"Korean",
|
||||
"Taiwanese",
|
||||
"Chinese",
|
||||
"BrazilianPortuguese",
|
||||
}};
|
||||
|
||||
std::string LanguageEntry::GetApplicationName() const {
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include "common/common_funcs.h"
|
||||
#include "common/common_types.h"
|
||||
@@ -88,11 +87,12 @@ enum class Language : u8 {
|
||||
Korean = 12,
|
||||
Taiwanese = 13,
|
||||
Chinese = 14,
|
||||
BrazilianPortuguese = 15,
|
||||
|
||||
Default = 255,
|
||||
};
|
||||
|
||||
extern const std::array<const char*, 15> LANGUAGE_NAMES;
|
||||
extern const std::array<const char*, 16> LANGUAGE_NAMES;
|
||||
|
||||
// A class representing the format used by NX metadata files, typically named Control.nacp.
|
||||
// These store application name, dev name, title id, and other miscellaneous data.
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
#include <string_view>
|
||||
#include "common/common_funcs.h"
|
||||
#include "common/common_types.h"
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include "common/common_funcs.h"
|
||||
#include "common/common_types.h"
|
||||
|
||||
@@ -53,13 +53,16 @@ Loader::ResultStatus ProgramMetadata::Load(VirtualFile file) {
|
||||
}
|
||||
|
||||
/*static*/ ProgramMetadata ProgramMetadata::GetDefault() {
|
||||
// Allow use of cores 0~3 and thread priorities 1~63.
|
||||
constexpr u32 default_thread_info_capability = 0x30007F7;
|
||||
|
||||
ProgramMetadata result;
|
||||
|
||||
result.LoadManual(
|
||||
true /*is_64_bit*/, FileSys::ProgramAddressSpaceType::Is39Bit /*address_space*/,
|
||||
0x2c /*main_thread_prio*/, 0 /*main_thread_core*/, 0x00100000 /*main_thread_stack_size*/,
|
||||
0 /*title_id*/, 0xFFFFFFFFFFFFFFFF /*filesystem_permissions*/,
|
||||
0x1FE00000 /*system_resource_size*/, {} /*capabilities*/);
|
||||
0x1FE00000 /*system_resource_size*/, {default_thread_info_capability} /*capabilities*/);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#include "common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "core/file_sys/card_image.h"
|
||||
#include "core/file_sys/common_funcs.h"
|
||||
#include "core/file_sys/content_archive.h"
|
||||
#include "core/file_sys/nca_metadata.h"
|
||||
@@ -39,13 +38,12 @@ void RomFSFactory::SetPackedUpdate(VirtualFile update_raw_file) {
|
||||
|
||||
ResultVal<VirtualFile> RomFSFactory::OpenCurrentProcess(u64 current_process_title_id) const {
|
||||
if (!updatable) {
|
||||
return MakeResult<VirtualFile>(file);
|
||||
return file;
|
||||
}
|
||||
|
||||
const PatchManager patch_manager{current_process_title_id, filesystem_controller,
|
||||
content_provider};
|
||||
return MakeResult<VirtualFile>(
|
||||
patch_manager.PatchRomFS(file, ivfc_offset, ContentRecordType::Program, update_raw));
|
||||
return patch_manager.PatchRomFS(file, ivfc_offset, ContentRecordType::Program, update_raw);
|
||||
}
|
||||
|
||||
ResultVal<VirtualFile> RomFSFactory::OpenPatchedRomFS(u64 title_id, ContentRecordType type) const {
|
||||
@@ -58,8 +56,7 @@ ResultVal<VirtualFile> RomFSFactory::OpenPatchedRomFS(u64 title_id, ContentRecor
|
||||
|
||||
const PatchManager patch_manager{title_id, filesystem_controller, content_provider};
|
||||
|
||||
return MakeResult<VirtualFile>(
|
||||
patch_manager.PatchRomFS(nca->GetRomFS(), nca->GetBaseIVFCOffset(), type));
|
||||
return patch_manager.PatchRomFS(nca->GetRomFS(), nca->GetBaseIVFCOffset(), type);
|
||||
}
|
||||
|
||||
ResultVal<VirtualFile> RomFSFactory::OpenPatchedRomFSWithProgramIndex(
|
||||
@@ -83,7 +80,7 @@ ResultVal<VirtualFile> RomFSFactory::Open(u64 title_id, StorageId storage,
|
||||
return ResultUnknown;
|
||||
}
|
||||
|
||||
return MakeResult<VirtualFile>(romfs);
|
||||
return romfs;
|
||||
}
|
||||
|
||||
std::shared_ptr<NCA> RomFSFactory::GetEntry(u64 title_id, StorageId storage,
|
||||
|
||||
@@ -5,8 +5,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "core/file_sys/vfs.h"
|
||||
#include "core/file_sys/vfs_types.h"
|
||||
#include "core/hle/result.h"
|
||||
|
||||
namespace Loader {
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#include "core/core.h"
|
||||
#include "core/file_sys/savedata_factory.h"
|
||||
#include "core/file_sys/vfs.h"
|
||||
#include "core/hle/kernel/k_process.h"
|
||||
|
||||
namespace FileSys {
|
||||
|
||||
@@ -94,7 +93,7 @@ ResultVal<VirtualDir> SaveDataFactory::Create(SaveDataSpaceId space,
|
||||
return ResultUnknown;
|
||||
}
|
||||
|
||||
return MakeResult<VirtualDir>(std::move(out));
|
||||
return out;
|
||||
}
|
||||
|
||||
ResultVal<VirtualDir> SaveDataFactory::Open(SaveDataSpaceId space,
|
||||
@@ -115,7 +114,7 @@ ResultVal<VirtualDir> SaveDataFactory::Open(SaveDataSpaceId space,
|
||||
return ResultUnknown;
|
||||
}
|
||||
|
||||
return MakeResult<VirtualDir>(std::move(out));
|
||||
return out;
|
||||
}
|
||||
|
||||
VirtualDir SaveDataFactory::GetSaveDataSpaceDirectory(SaveDataSpaceId space) const {
|
||||
@@ -143,7 +142,7 @@ std::string SaveDataFactory::GetFullPath(Core::System& system, SaveDataSpaceId s
|
||||
// be interpreted as the title id of the current process.
|
||||
if (type == SaveDataType::SaveData || type == SaveDataType::DeviceSaveData) {
|
||||
if (title_id == 0) {
|
||||
title_id = system.CurrentProcess()->GetTitleID();
|
||||
title_id = system.GetCurrentProcessProgramID();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include <string>
|
||||
#include "common/common_funcs.h"
|
||||
#include "common/common_types.h"
|
||||
#include "common/swap.h"
|
||||
#include "core/file_sys/vfs.h"
|
||||
#include "core/hle/result.h"
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ SDMCFactory::SDMCFactory(VirtualDir sd_dir_, VirtualDir sd_mod_dir_)
|
||||
SDMCFactory::~SDMCFactory() = default;
|
||||
|
||||
ResultVal<VirtualDir> SDMCFactory::Open() const {
|
||||
return MakeResult<VirtualDir>(sd_dir);
|
||||
return sd_dir;
|
||||
}
|
||||
|
||||
VirtualDir SDMCFactory::GetSDMCModificationLoadRoot(u64 title_id) const {
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <string_view>
|
||||
|
||||
#include <fmt/ostream.h>
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include "core/file_sys/vfs_types.h"
|
||||
|
||||
namespace FileSys::SystemArchive {
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string_view>
|
||||
#include "core/file_sys/vfs.h"
|
||||
|
||||
namespace FileSys {
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string_view>
|
||||
|
||||
#include "core/file_sys/vfs.h"
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace Core::Frontend {
|
||||
|
||||
@@ -16,7 +16,8 @@ DefaultSoftwareKeyboardApplet::~DefaultSoftwareKeyboardApplet() = default;
|
||||
|
||||
void DefaultSoftwareKeyboardApplet::InitializeKeyboard(
|
||||
bool is_inline, KeyboardInitializeParameters initialize_parameters,
|
||||
std::function<void(Service::AM::Applets::SwkbdResult, std::u16string)> submit_normal_callback_,
|
||||
std::function<void(Service::AM::Applets::SwkbdResult, std::u16string, bool)>
|
||||
submit_normal_callback_,
|
||||
std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)>
|
||||
submit_inline_callback_) {
|
||||
if (is_inline) {
|
||||
@@ -128,7 +129,7 @@ void DefaultSoftwareKeyboardApplet::ExitKeyboard() const {
|
||||
}
|
||||
|
||||
void DefaultSoftwareKeyboardApplet::SubmitNormalText(std::u16string text) const {
|
||||
submit_normal_callback(Service::AM::Applets::SwkbdResult::Ok, text);
|
||||
submit_normal_callback(Service::AM::Applets::SwkbdResult::Ok, text, true);
|
||||
}
|
||||
|
||||
void DefaultSoftwareKeyboardApplet::SubmitInlineText(std::u16string_view text) const {
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <thread>
|
||||
|
||||
#include "common/common_types.h"
|
||||
|
||||
@@ -58,7 +57,7 @@ public:
|
||||
|
||||
virtual void InitializeKeyboard(
|
||||
bool is_inline, KeyboardInitializeParameters initialize_parameters,
|
||||
std::function<void(Service::AM::Applets::SwkbdResult, std::u16string)>
|
||||
std::function<void(Service::AM::Applets::SwkbdResult, std::u16string, bool)>
|
||||
submit_normal_callback_,
|
||||
std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)>
|
||||
submit_inline_callback_) = 0;
|
||||
@@ -83,7 +82,7 @@ public:
|
||||
|
||||
void InitializeKeyboard(
|
||||
bool is_inline, KeyboardInitializeParameters initialize_parameters,
|
||||
std::function<void(Service::AM::Applets::SwkbdResult, std::u16string)>
|
||||
std::function<void(Service::AM::Applets::SwkbdResult, std::u16string, bool)>
|
||||
submit_normal_callback_,
|
||||
std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)>
|
||||
submit_inline_callback_) override;
|
||||
@@ -107,7 +106,7 @@ private:
|
||||
|
||||
KeyboardInitializeParameters parameters;
|
||||
|
||||
mutable std::function<void(Service::AM::Applets::SwkbdResult, std::u16string)>
|
||||
mutable std::function<void(Service::AM::Applets::SwkbdResult, std::u16string, bool)>
|
||||
submit_normal_callback;
|
||||
mutable std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)>
|
||||
submit_inline_callback;
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <string_view>
|
||||
|
||||
#include "core/hle/service/am/applets/applet_web_browser_types.h"
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <cmath>
|
||||
#include <mutex>
|
||||
#include "common/settings.h"
|
||||
#include "core/frontend/emu_window.h"
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
#include "common/common_types.h"
|
||||
#include "core/frontend/framebuffer_layout.h"
|
||||
|
||||
@@ -4,17 +4,14 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include "common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
#include "core/hle/ipc.h"
|
||||
#include "core/hle/kernel/hle_ipc.h"
|
||||
#include "core/hle/kernel/k_client_port.h"
|
||||
#include "core/hle/kernel/k_process.h"
|
||||
#include "core/hle/kernel/k_resource_limit.h"
|
||||
#include "core/hle/kernel/k_session.h"
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace Kernel::Board::Nintendo::Nx::Smc {
|
||||
|
||||
enum MemorySize {
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "core/hle/kernel/physical_memory.h"
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
|
||||
#include <boost/range/algorithm_ext/erase.hpp>
|
||||
|
||||
@@ -15,17 +14,13 @@
|
||||
#include "common/logging/log.h"
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/kernel/hle_ipc.h"
|
||||
#include "core/hle/kernel/k_auto_object.h"
|
||||
#include "core/hle/kernel/k_handle_table.h"
|
||||
#include "core/hle/kernel/k_process.h"
|
||||
#include "core/hle/kernel/k_readable_event.h"
|
||||
#include "core/hle/kernel/k_scheduler.h"
|
||||
#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
|
||||
#include "core/hle/kernel/k_server_session.h"
|
||||
#include "core/hle/kernel/k_thread.h"
|
||||
#include "core/hle/kernel/k_writable_event.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
#include "core/hle/kernel/svc_results.h"
|
||||
#include "core/hle/kernel/time_manager.h"
|
||||
#include "core/memory.h"
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user