Compare commits
240 Commits
__refs_pul
...
__refs_pul
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2d1984c20c | ||
|
|
de4b01f75d | ||
|
|
a1630ab53e | ||
|
|
e4a1ead897 | ||
|
|
450341b397 | ||
|
|
4d6a86b03f | ||
|
|
ab89ced244 | ||
|
|
deb97f6a8e | ||
|
|
d01eb12f36 | ||
|
|
bbd85a495a | ||
|
|
0fe11746fc | ||
|
|
ac3690f205 | ||
|
|
a167da4278 | ||
|
|
9c6b5cae68 | ||
|
|
ed76c71319 | ||
|
|
89b326e396 | ||
|
|
d8e0d839bd | ||
|
|
c7055f3670 | ||
|
|
9a22b6dced | ||
|
|
3ce28342a2 | ||
|
|
79e0991d9b | ||
|
|
a665581684 | ||
|
|
bc55c05947 | ||
|
|
7113236b30 | ||
|
|
4ea073c286 | ||
|
|
4043ba5222 | ||
|
|
69b44392a7 | ||
|
|
5a077c95ce | ||
|
|
690732bc0d | ||
|
|
8b9f433d95 | ||
|
|
f5dfe68a94 | ||
|
|
41373d212e | ||
|
|
c610a8ac5a | ||
|
|
265fe40451 | ||
|
|
9ac33c2620 | ||
|
|
b2c976ad0e | ||
|
|
f98cd210ab | ||
|
|
51c8aea979 | ||
|
|
94c41ab1d1 | ||
|
|
d110a371bb | ||
|
|
94915d4ea1 | ||
|
|
e972016456 | ||
|
|
278264b9e5 | ||
|
|
56672b8c98 | ||
|
|
55103da066 | ||
|
|
7e94e544f4 | ||
|
|
9bf4850f74 | ||
|
|
15163edaaa | ||
|
|
3cce5056ff | ||
|
|
4512a6bbfc | ||
|
|
09b1d762d7 | ||
|
|
f34e519da3 | ||
|
|
530a761e7a | ||
|
|
dd74fd014b | ||
|
|
48863afb65 | ||
|
|
657b3a366e | ||
|
|
fe5356d223 | ||
|
|
38e789c761 | ||
|
|
e041f33569 | ||
|
|
f09cd52980 | ||
|
|
63ba41a26d | ||
|
|
0caab54b5d | ||
|
|
82e1285c1e | ||
|
|
30faf6a964 | ||
|
|
d23869811d | ||
|
|
a43ac8c79e | ||
|
|
9e874898f5 | ||
|
|
b429095b61 | ||
|
|
c375d735e6 | ||
|
|
7af56dfa76 | ||
|
|
06d30fbcca | ||
|
|
66a1c777c9 | ||
|
|
cdb00546f0 | ||
|
|
2d09467f6f | ||
|
|
02624c35ec | ||
|
|
64cd46579b | ||
|
|
81e9e229fa | ||
|
|
a1eee1749e | ||
|
|
a83e28b237 | ||
|
|
f10ea944e0 | ||
|
|
4cd5ad90f3 | ||
|
|
15a6840e7a | ||
|
|
55f95e7f26 | ||
|
|
15788ffcde | ||
|
|
6985eea519 | ||
|
|
e749f17257 | ||
|
|
09e17fbb0f | ||
|
|
2b2712fa95 | ||
|
|
da3049aa74 | ||
|
|
6726e8b784 | ||
|
|
43fc793439 | ||
|
|
c76ffa5019 | ||
|
|
b1138e5ea1 | ||
|
|
3d46709b7f | ||
|
|
13021b534c | ||
|
|
e2a2a556b9 | ||
|
|
908e085d02 | ||
|
|
82a64da077 | ||
|
|
80436c1330 | ||
|
|
319c4d2108 | ||
|
|
6888d776ff | ||
|
|
2effdeb924 | ||
|
|
dc96a59fa0 | ||
|
|
b392a5986e | ||
|
|
3142f1b597 | ||
|
|
9c548146ca | ||
|
|
5be00cba15 | ||
|
|
ee9b4a7f9a | ||
|
|
5aeff9aff5 | ||
|
|
322d6a0311 | ||
|
|
5b01f80a12 | ||
|
|
ceb851b590 | ||
|
|
85bb6a6f08 | ||
|
|
984563b773 | ||
|
|
8306703a7d | ||
|
|
09908207fb | ||
|
|
89fc75d769 | ||
|
|
56e450a3f7 | ||
|
|
6fe51f398f | ||
|
|
be5c149d37 | ||
|
|
cd0a7dfdbc | ||
|
|
361285add9 | ||
|
|
a4e840181c | ||
|
|
fab2607c6b | ||
|
|
4414640285 | ||
|
|
78f977c980 | ||
|
|
3dd6b55851 | ||
|
|
5135b74179 | ||
|
|
64c5631579 | ||
|
|
6e347d8d1b | ||
|
|
624a0f7f3f | ||
|
|
c332c66eb2 | ||
|
|
0d6d8129c4 | ||
|
|
ae0e481677 | ||
|
|
1fe7df4517 | ||
|
|
0986caa8d8 | ||
|
|
028b2718ed | ||
|
|
b3371ed09e | ||
|
|
7bd447355f | ||
|
|
4cbb363d3f | ||
|
|
287d5921cf | ||
|
|
cb9dd01ffd | ||
|
|
f2c61bbe13 | ||
|
|
f846e3d6d0 | ||
|
|
8a76f816a4 | ||
|
|
5b989f189f | ||
|
|
3813af2f3c | ||
|
|
c83bf7cd1e | ||
|
|
a5bb1ac6e3 | ||
|
|
5619d24377 | ||
|
|
4af569ee47 | ||
|
|
b9e3f5eb36 | ||
|
|
4a3026b16b | ||
|
|
5770418fb3 | ||
|
|
91d35559e5 | ||
|
|
e976d0e924 | ||
|
|
1e76655f83 | ||
|
|
0f3ac9cfeb | ||
|
|
3dc585d011 | ||
|
|
218ee18417 | ||
|
|
a3916588b6 | ||
|
|
51c9e98677 | ||
|
|
aea978e037 | ||
|
|
27efcc15e9 | ||
|
|
16dcfacbfc | ||
|
|
1e16023d60 | ||
|
|
486c6a5316 | ||
|
|
af93909c9c | ||
|
|
38d3a48873 | ||
|
|
cf27b59493 | ||
|
|
7be65c6a68 | ||
|
|
6d55b14cc0 | ||
|
|
e41da22c8d | ||
|
|
ec983a2451 | ||
|
|
6ddffa010a | ||
|
|
54747d60bc | ||
|
|
2a63b3bdb9 | ||
|
|
de918ebeb0 | ||
|
|
485c21eac3 | ||
|
|
1eb4a95d2b | ||
|
|
253aa52351 | ||
|
|
f4a25f854c | ||
|
|
abb33d4aec | ||
|
|
d53cf05513 | ||
|
|
da0aa4da6b | ||
|
|
ae8d4b6c0c | ||
|
|
a7d6bd1ef1 | ||
|
|
c053269017 | ||
|
|
15a753b9a5 | ||
|
|
e438079b50 | ||
|
|
8b26b4228b | ||
|
|
8825b88a45 | ||
|
|
8a23c32cf0 | ||
|
|
67b8ecc73e | ||
|
|
b52297767e | ||
|
|
65b1b05e05 | ||
|
|
e09c1fbc1f | ||
|
|
844e4a297b | ||
|
|
a87c85eba2 | ||
|
|
3d2c44848b | ||
|
|
3d9fff82c0 | ||
|
|
eac075692b | ||
|
|
0471eb6dc7 | ||
|
|
3d51153611 | ||
|
|
ccda77c8c4 | ||
|
|
035ec7d9de | ||
|
|
285705b5f4 | ||
|
|
2b650543c6 | ||
|
|
e3ea583893 | ||
|
|
f27b21077d | ||
|
|
8db8631d81 | ||
|
|
15513f0801 | ||
|
|
f845df8651 | ||
|
|
2df9a2dcaf | ||
|
|
6d0d79109b | ||
|
|
8fc49a83b6 | ||
|
|
c0ee0aa1a8 | ||
|
|
af89723fa3 | ||
|
|
84a158c977 | ||
|
|
271a3264f3 | ||
|
|
900b2e5cae | ||
|
|
1d2ba3cc97 | ||
|
|
1a66cde175 | ||
|
|
e9faa1617c | ||
|
|
22c6b9fab2 | ||
|
|
30e365e4fc | ||
|
|
f564eaebed | ||
|
|
48e16c4c49 | ||
|
|
34f8881d3e | ||
|
|
c8db7d1399 | ||
|
|
7ffb672f61 | ||
|
|
425a254fa2 | ||
|
|
67b8265bd6 | ||
|
|
e6a0a30334 | ||
|
|
dee7844443 | ||
|
|
3a44faff11 | ||
|
|
75cc501d52 | ||
|
|
056f049b26 | ||
|
|
4589582eaf | ||
|
|
3c95e49c42 |
@@ -1,39 +0,0 @@
|
||||
# Set-up Visual Studio Command Prompt environment for PowerShell
|
||||
pushd "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\Tools\"
|
||||
cmd /c "VsDevCmd.bat -arch=x64 & set" | foreach {
|
||||
if ($_ -match "=") {
|
||||
$v = $_.split("="); Set-Item -Force -Path "ENV:\$($v[0])" -Value "$($v[1])"
|
||||
}
|
||||
}
|
||||
popd
|
||||
|
||||
function Which ($search_path, $name) {
|
||||
($search_path).Split(";") | Get-ChildItem -Filter $name | Select -First 1 -Exp FullName
|
||||
}
|
||||
|
||||
function GetDeps ($search_path, $binary) {
|
||||
((dumpbin /dependents $binary).Where({ $_ -match "dependencies:"}, "SkipUntil") | Select-String "[^ ]*\.dll").Matches | foreach {
|
||||
Which $search_path $_.Value
|
||||
}
|
||||
}
|
||||
|
||||
function RecursivelyGetDeps ($search_path, $binary) {
|
||||
$final_deps = @()
|
||||
$deps_to_process = GetDeps $search_path $binary
|
||||
while ($deps_to_process.Count -gt 0) {
|
||||
$current, $deps_to_process = $deps_to_process
|
||||
if ($final_deps -contains $current) { continue }
|
||||
|
||||
# Is this a system dll file?
|
||||
# We use the same algorithm that cmake uses to determine this.
|
||||
if ($current -match "$([regex]::Escape($env:SystemRoot))\\sys") { continue }
|
||||
if ($current -match "$([regex]::Escape($env:WinDir))\\sys") { continue }
|
||||
if ($current -match "\\msvc[^\\]+dll") { continue }
|
||||
if ($current -match "\\api-ms-win-[^\\]+dll") { continue }
|
||||
|
||||
$final_deps += $current
|
||||
$new_deps = GetDeps $search_path $current
|
||||
$deps_to_process += ($new_deps | ?{-not ($final_deps -contains $_)})
|
||||
}
|
||||
return $final_deps
|
||||
}
|
||||
@@ -350,6 +350,13 @@ function(create_target_directory_groups target_name)
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
# Prevent boost from linking against libs when building
|
||||
add_definitions(-DBOOST_ERROR_CODE_HEADER_ONLY
|
||||
-DBOOST_SYSTEM_NO_LIB
|
||||
-DBOOST_DATE_TIME_NO_LIB
|
||||
-DBOOST_REGEX_NO_LIB
|
||||
)
|
||||
|
||||
enable_testing()
|
||||
add_subdirectory(externals)
|
||||
add_subdirectory(src)
|
||||
|
||||
@@ -5,6 +5,10 @@ function(get_timestamp _var)
|
||||
endfunction()
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${SRC_DIR}/externals/cmake-modules")
|
||||
|
||||
# Find the package here with the known path so that the GetGit commands can find it as well
|
||||
find_package(Git QUIET PATHS "${GIT_EXECUTABLE}")
|
||||
|
||||
# generate git/build information
|
||||
include(GetGitRevisionDescription)
|
||||
get_git_head_revision(GIT_REF_SPEC GIT_REV)
|
||||
|
||||
178
appveyor.yml
178
appveyor.yml
@@ -1,178 +0,0 @@
|
||||
# shallow clone
|
||||
clone_depth: 10
|
||||
|
||||
cache:
|
||||
- C:\ProgramData\chocolatey\bin -> appveyor.yml
|
||||
- C:\ProgramData\chocolatey\lib -> appveyor.yml
|
||||
|
||||
os: Visual Studio 2017
|
||||
|
||||
environment:
|
||||
# Tell msys2 to add mingw64 to the path
|
||||
MSYSTEM: MINGW64
|
||||
# Tell msys2 to inherit the current directory when starting the shell
|
||||
CHERE_INVOKING: 1
|
||||
matrix:
|
||||
- BUILD_TYPE: msvc
|
||||
- BUILD_TYPE: mingw
|
||||
|
||||
platform:
|
||||
- x64
|
||||
|
||||
configuration:
|
||||
- Release
|
||||
|
||||
install:
|
||||
- git submodule update --init --recursive
|
||||
- ps: |
|
||||
if ($env:BUILD_TYPE -eq 'mingw') {
|
||||
$dependencies = "mingw64/mingw-w64-x86_64-cmake",
|
||||
"mingw64/mingw-w64-x86_64-qt5",
|
||||
"mingw64/mingw-w64-x86_64-SDL2"
|
||||
# redirect err to null to prevent warnings from becoming errors
|
||||
# workaround to prevent pacman from failing due to cyclical dependencies
|
||||
C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S mingw64/mingw-w64-x86_64-freetype mingw64/mingw-w64-x86_64-fontconfig" 2> $null
|
||||
C:\msys64\usr\bin\bash -lc "pacman --noconfirm -S $dependencies" 2> $null
|
||||
}
|
||||
|
||||
before_build:
|
||||
- mkdir %BUILD_TYPE%_build
|
||||
- cd %BUILD_TYPE%_build
|
||||
- ps: |
|
||||
$COMPAT = if ($env:ENABLE_COMPATIBILITY_REPORTING -eq $null) {0} else {$env:ENABLE_COMPATIBILITY_REPORTING}
|
||||
if ($env:BUILD_TYPE -eq 'msvc') {
|
||||
# redirect stderr and change the exit code to prevent powershell from cancelling the build if cmake prints a warning
|
||||
cmd /C 'cmake -G "Visual Studio 15 2017 Win64" -DYUZU_USE_BUNDLED_QT=1 -DYUZU_USE_BUNDLED_SDL2=1 -DYUZU_USE_BUNDLED_UNICORN=1 -DYUZU_USE_QT_WEB_ENGINE=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${COMPAT} -DUSE_DISCORD_PRESENCE=ON .. 2>&1 && exit 0'
|
||||
} else {
|
||||
C:\msys64\usr\bin\bash.exe -lc "cmake -G 'MSYS Makefiles' -DYUZU_BUILD_UNICORN=1 -DCMAKE_BUILD_TYPE=Release -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${COMPAT} -DUSE_DISCORD_PRESENCE=ON .. 2>&1"
|
||||
}
|
||||
- cd ..
|
||||
|
||||
build_script:
|
||||
- ps: |
|
||||
if ($env:BUILD_TYPE -eq 'msvc') {
|
||||
# https://www.appveyor.com/docs/build-phase
|
||||
msbuild msvc_build/yuzu.sln /maxcpucount /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
|
||||
} else {
|
||||
C:\msys64\usr\bin\bash.exe -lc 'mingw32-make -C mingw_build/ 2>&1'
|
||||
}
|
||||
|
||||
after_build:
|
||||
- ps: |
|
||||
$GITDATE = $(git show -s --date=short --format='%ad') -replace "-",""
|
||||
$GITREV = $(git show -s --format='%h')
|
||||
|
||||
# Find out which kind of release we are producing by tag name
|
||||
if ($env:APPVEYOR_REPO_TAG_NAME) {
|
||||
$RELEASE_DIST, $RELEASE_VERSION = $env:APPVEYOR_REPO_TAG_NAME.split('-')
|
||||
} else {
|
||||
# There is no repo tag - make assumptions
|
||||
$RELEASE_DIST = "head"
|
||||
}
|
||||
|
||||
if ($env:BUILD_TYPE -eq 'msvc') {
|
||||
# Where are these spaces coming from? Regardless, let's remove them
|
||||
$MSVC_BUILD_ZIP = "yuzu-windows-msvc-$GITDATE-$GITREV.zip" -replace " ", ""
|
||||
$MSVC_BUILD_PDB = "yuzu-windows-msvc-$GITDATE-$GITREV-debugsymbols.zip" -replace " ", ""
|
||||
$MSVC_SEVENZIP = "yuzu-windows-msvc-$GITDATE-$GITREV.7z" -replace " ", ""
|
||||
|
||||
# set the build names as env vars so the artifacts can upload them
|
||||
$env:BUILD_ZIP = $MSVC_BUILD_ZIP
|
||||
$env:BUILD_SYMBOLS = $MSVC_BUILD_PDB
|
||||
$env:BUILD_UPDATE = $MSVC_SEVENZIP
|
||||
|
||||
$BUILD_DIR = ".\msvc_build\bin\Release"
|
||||
|
||||
# Make a debug symbol upload
|
||||
mkdir pdb
|
||||
Get-ChildItem "$BUILD_DIR\" -Recurse -Filter "*.pdb" | Copy-Item -destination .\pdb
|
||||
7z a -tzip $MSVC_BUILD_PDB .\pdb\*.pdb
|
||||
rm "$BUILD_DIR\*.pdb"
|
||||
|
||||
mkdir $RELEASE_DIST
|
||||
# get rid of extra exes by copying everything over, then deleting all the exes, then copying just the exes we want
|
||||
Copy-Item "$BUILD_DIR\*" -Destination $RELEASE_DIST -Recurse
|
||||
rm "$RELEASE_DIST\*.exe"
|
||||
Get-ChildItem "$BUILD_DIR" -Recurse -Filter "yuzu*.exe" | Copy-Item -destination $RELEASE_DIST
|
||||
Get-ChildItem "$BUILD_DIR" -Recurse -Filter "QtWebEngineProcess*.exe" | Copy-Item -destination $RELEASE_DIST
|
||||
Copy-Item .\license.txt -Destination $RELEASE_DIST
|
||||
Copy-Item .\README.md -Destination $RELEASE_DIST
|
||||
7z a -tzip $MSVC_BUILD_ZIP $RELEASE_DIST\*
|
||||
7z a $MSVC_SEVENZIP $RELEASE_DIST
|
||||
} else {
|
||||
$MINGW_BUILD_ZIP = "yuzu-windows-mingw-$GITDATE-$GITREV.zip" -replace " ", ""
|
||||
$MINGW_SEVENZIP = "yuzu-windows-mingw-$GITDATE-$GITREV.7z" -replace " ", ""
|
||||
# not going to bother adding separate debug symbols for mingw, so just upload a README for it
|
||||
# if someone wants to add them, change mingw to compile with -g and use objdump and strip to separate the symbols from the binary
|
||||
$MINGW_NO_DEBUG_SYMBOLS = "README_No_Debug_Symbols.txt"
|
||||
Set-Content -Path $MINGW_NO_DEBUG_SYMBOLS -Value "This is a workaround for Appveyor since msvc has debug symbols but mingw doesnt" -Force
|
||||
|
||||
# store the build information in env vars so we can use them as artifacts
|
||||
$env:BUILD_ZIP = $MINGW_BUILD_ZIP
|
||||
$env:BUILD_SYMBOLS = $MINGW_NO_DEBUG_SYMBOLS
|
||||
$env:BUILD_UPDATE = $MINGW_SEVENZIP
|
||||
|
||||
$CMAKE_SOURCE_DIR = "$env:APPVEYOR_BUILD_FOLDER"
|
||||
$CMAKE_BINARY_DIR = "$CMAKE_SOURCE_DIR/mingw_build/bin"
|
||||
$RELEASE_DIST = $RELEASE_DIST + "-mingw"
|
||||
|
||||
mkdir $RELEASE_DIST
|
||||
mkdir $RELEASE_DIST/platforms
|
||||
mkdir $RELEASE_DIST/styles
|
||||
mkdir $RELEASE_DIST/imageformats
|
||||
|
||||
# copy the compiled binaries and other release files to the release folder
|
||||
Get-ChildItem "$CMAKE_BINARY_DIR" -Filter "yuzu*.exe" | Copy-Item -destination $RELEASE_DIST
|
||||
Copy-Item -path "$CMAKE_SOURCE_DIR/license.txt" -destination $RELEASE_DIST
|
||||
Copy-Item -path "$CMAKE_SOURCE_DIR/README.md" -destination $RELEASE_DIST
|
||||
|
||||
# copy the qt windows plugin dll to platforms
|
||||
Copy-Item -path "C:/msys64/mingw64/share/qt5/plugins/platforms/qwindows.dll" -force -destination "$RELEASE_DIST/platforms"
|
||||
|
||||
# copy the qt windows vista style dll to platforms
|
||||
Copy-Item -path "C:/msys64/mingw64/share/qt5/plugins/styles/qwindowsvistastyle.dll" -force -destination "$RELEASE_DIST/styles"
|
||||
|
||||
# copy the qt jpeg imageformat dll to platforms
|
||||
Copy-Item -path "C:/msys64/mingw64/share/qt5/plugins/imageformats/qjpeg.dll" -force -destination "$RELEASE_DIST/imageformats"
|
||||
|
||||
# copy all the dll dependencies to the release folder
|
||||
. "./.appveyor/UtilityFunctions.ps1"
|
||||
$DLLSearchPath = "C:\msys64\mingw64\bin;$env:PATH"
|
||||
$MingwDLLs = RecursivelyGetDeps $DLLSearchPath "$RELEASE_DIST\yuzu.exe"
|
||||
$MingwDLLs += RecursivelyGetDeps $DLLSearchPath "$RELEASE_DIST\yuzu_cmd.exe"
|
||||
$MingwDLLs += RecursivelyGetDeps $DLLSearchPath "$RELEASE_DIST\imageformats\qjpeg.dll"
|
||||
Write-Host "Detected the following dependencies:"
|
||||
Write-Host $MingwDLLs
|
||||
foreach ($file in $MingwDLLs) {
|
||||
Copy-Item -path "$file" -force -destination "$RELEASE_DIST"
|
||||
}
|
||||
|
||||
7z a -tzip $MINGW_BUILD_ZIP $RELEASE_DIST\*
|
||||
7z a $MINGW_SEVENZIP $RELEASE_DIST
|
||||
}
|
||||
|
||||
test_script:
|
||||
- cd %BUILD_TYPE%_build
|
||||
- ps: |
|
||||
if ($env:BUILD_TYPE -eq 'msvc') {
|
||||
ctest -VV -C Release
|
||||
} else {
|
||||
C:\msys64\usr\bin\bash.exe -lc "ctest -VV -C Release"
|
||||
}
|
||||
- cd ..
|
||||
|
||||
artifacts:
|
||||
- path: $(BUILD_ZIP)
|
||||
name: build
|
||||
type: zip
|
||||
|
||||
deploy:
|
||||
provider: GitHub
|
||||
release: $(appveyor_repo_tag_name)
|
||||
auth_token:
|
||||
secure: QqePPnXbkzmXct5c8hZ2X5AbsthbI6cS1Sr+VBzcD8oUOIjfWJJKXVAQGUbQAbb0
|
||||
artifact: update,build
|
||||
draft: false
|
||||
prerelease: false
|
||||
on:
|
||||
appveyor_repo_tag: true
|
||||
33
dist/qt_themes/qdarkstyle/style.qss
vendored
33
dist/qt_themes/qdarkstyle/style.qss
vendored
@@ -181,7 +181,7 @@ QMenu::icon {
|
||||
}
|
||||
|
||||
QMenu::item {
|
||||
padding: 5px 30px 5px 30px;
|
||||
padding: 5px 16px 5px 40px;
|
||||
border: 1px solid transparent;
|
||||
/* reserve space for selection border */
|
||||
}
|
||||
@@ -192,12 +192,13 @@ QMenu::item:selected {
|
||||
|
||||
QMenu::separator {
|
||||
height: 2px;
|
||||
background: lightblue;
|
||||
background: #76797C;
|
||||
margin-left: 10px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
QMenu::indicator {
|
||||
margin: 0 -26px 0 8px;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
@@ -252,7 +253,7 @@ QWidget:disabled {
|
||||
}
|
||||
|
||||
QAbstractItemView {
|
||||
alternate-background-color: #31363b;
|
||||
alternate-background-color: #2c2f32;
|
||||
color: #eff0f1;
|
||||
border: 1px solid #3A3939;
|
||||
border-radius: 2px;
|
||||
@@ -577,8 +578,6 @@ QTreeView:hover {
|
||||
}
|
||||
|
||||
QComboBox:on {
|
||||
padding-top: 3px;
|
||||
padding-left: 4px;
|
||||
selection-background-color: #4a4a4a;
|
||||
}
|
||||
|
||||
@@ -703,10 +702,10 @@ QTabBar::close-button:pressed {
|
||||
QTabBar::tab:top {
|
||||
color: #eff0f1;
|
||||
border: 1px solid #76797C;
|
||||
border-bottom: 1px transparent black;
|
||||
border-bottom: 2px transparent;
|
||||
background-color: #31363b;
|
||||
padding: 5px;
|
||||
min-width: 50px;
|
||||
padding: 4px 16px 2px;
|
||||
min-width: 38px;
|
||||
border-top-left-radius: 2px;
|
||||
border-top-right-radius: 2px;
|
||||
}
|
||||
@@ -1078,7 +1077,7 @@ QListView::item:selected:active {
|
||||
}
|
||||
|
||||
QHeaderView {
|
||||
background-color: #31363b;
|
||||
background-color: #403F3F;
|
||||
border: 1px transparent;
|
||||
border-radius: 0px;
|
||||
margin: 0px;
|
||||
@@ -1086,30 +1085,32 @@ QHeaderView {
|
||||
}
|
||||
|
||||
QHeaderView::section {
|
||||
background-color: #31363b;
|
||||
background-color: #232629;
|
||||
color: #eff0f1;
|
||||
padding: 5px;
|
||||
border: 1px solid #76797C;
|
||||
padding: 0 5px;
|
||||
border: 1px solid #403F3F;
|
||||
border-bottom: 0;
|
||||
border-radius: 0px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
QHeaderView::section::vertical::first,
|
||||
QHeaderView::section::vertical::only-one {
|
||||
border-top: 1px solid #76797C;
|
||||
border-top: 1px solid #31363b;
|
||||
}
|
||||
|
||||
QHeaderView::section::vertical {
|
||||
border-top: transparent;
|
||||
}
|
||||
|
||||
QHeaderView::section::horizontal,
|
||||
QHeaderView::section::horizontal::first,
|
||||
QHeaderView::section::horizontal::only-one {
|
||||
border-left: 1px solid #76797C;
|
||||
border-left: transparent;
|
||||
}
|
||||
|
||||
QHeaderView::section::horizontal {
|
||||
border-left: transparent;
|
||||
QHeaderView::section::horizontal::last {
|
||||
border-right: transparent;
|
||||
}
|
||||
|
||||
QHeaderView::section:checked {
|
||||
|
||||
2
externals/boost
vendored
2
externals/boost
vendored
Submodule externals/boost updated: 0b920df1c9...5e8300b76a
2
externals/dynarmic
vendored
2
externals/dynarmic
vendored
Submodule externals/dynarmic updated: 087a74417a...f6ae9e1c33
2
externals/sirit
vendored
2
externals/sirit
vendored
Submodule externals/sirit updated: e1a6729df7...a712959f1e
@@ -77,6 +77,15 @@ else()
|
||||
add_compile_options("-static")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Linux" OR MINGW)
|
||||
# GNU ar: Create thin archive files.
|
||||
# Requires binutils-2.19 or later.
|
||||
set(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> qcTP <TARGET> <LINK_FLAGS> <OBJECTS>")
|
||||
set(CMAKE_C_ARCHIVE_APPEND "<CMAKE_AR> qTP <TARGET> <LINK_FLAGS> <OBJECTS>")
|
||||
set(CMAKE_CXX_ARCHIVE_CREATE "<CMAKE_AR> qcTP <TARGET> <LINK_FLAGS> <OBJECTS>")
|
||||
set(CMAKE_CXX_ARCHIVE_APPEND "<CMAKE_AR> qTP <TARGET> <LINK_FLAGS> <OBJECTS>")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_subdirectory(common)
|
||||
|
||||
@@ -15,6 +15,10 @@ endif ()
|
||||
if (DEFINED ENV{DISPLAYVERSION})
|
||||
set(DISPLAY_VERSION $ENV{DISPLAYVERSION})
|
||||
endif ()
|
||||
|
||||
# Pass the path to git to the GenerateSCMRev.cmake as well
|
||||
find_package(Git QUIET)
|
||||
|
||||
add_custom_command(OUTPUT scm_rev.cpp
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-DSRC_DIR="${CMAKE_SOURCE_DIR}"
|
||||
@@ -23,6 +27,7 @@ add_custom_command(OUTPUT scm_rev.cpp
|
||||
-DTITLE_BAR_FORMAT_RUNNING="${TITLE_BAR_FORMAT_RUNNING}"
|
||||
-DBUILD_TAG="${BUILD_TAG}"
|
||||
-DBUILD_ID="${DISPLAY_VERSION}"
|
||||
-DGIT_EXECUTABLE="${GIT_EXECUTABLE}"
|
||||
-P "${CMAKE_SOURCE_DIR}/CMakeModules/GenerateSCMRev.cmake"
|
||||
DEPENDS
|
||||
# WARNING! It was too much work to try and make a common location for this list,
|
||||
|
||||
@@ -44,20 +44,6 @@ template class Field<std::string>;
|
||||
template class Field<const char*>;
|
||||
template class Field<std::chrono::microseconds>;
|
||||
|
||||
#ifdef ARCHITECTURE_x86_64
|
||||
static const char* CpuVendorToStr(Common::CPUVendor vendor) {
|
||||
switch (vendor) {
|
||||
case Common::CPUVendor::INTEL:
|
||||
return "Intel";
|
||||
case Common::CPUVendor::AMD:
|
||||
return "Amd";
|
||||
case Common::CPUVendor::OTHER:
|
||||
return "Other";
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
#endif
|
||||
|
||||
void AppendBuildInfo(FieldCollection& fc) {
|
||||
const bool is_git_dirty{std::strstr(Common::g_scm_desc, "dirty") != nullptr};
|
||||
fc.AddField(FieldType::App, "Git_IsDirty", is_git_dirty);
|
||||
@@ -71,7 +57,6 @@ void AppendCPUInfo(FieldCollection& fc) {
|
||||
#ifdef ARCHITECTURE_x86_64
|
||||
fc.AddField(FieldType::UserSystem, "CPU_Model", Common::GetCPUCaps().cpu_string);
|
||||
fc.AddField(FieldType::UserSystem, "CPU_BrandString", Common::GetCPUCaps().brand_string);
|
||||
fc.AddField(FieldType::UserSystem, "CPU_Vendor", CpuVendorToStr(Common::GetCPUCaps().vendor));
|
||||
fc.AddField(FieldType::UserSystem, "CPU_Extension_x64_AES", Common::GetCPUCaps().aes);
|
||||
fc.AddField(FieldType::UserSystem, "CPU_Extension_x64_AVX", Common::GetCPUCaps().avx);
|
||||
fc.AddField(FieldType::UserSystem, "CPU_Extension_x64_AVX2", Common::GetCPUCaps().avx2);
|
||||
|
||||
@@ -28,6 +28,15 @@ public:
|
||||
is_set = false;
|
||||
}
|
||||
|
||||
template <class Duration>
|
||||
bool WaitFor(const std::chrono::duration<Duration>& time) {
|
||||
std::unique_lock lk{mutex};
|
||||
if (!condvar.wait_for(lk, time, [this] { return is_set; }))
|
||||
return false;
|
||||
is_set = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class Clock, class Duration>
|
||||
bool WaitUntil(const std::chrono::time_point<Clock, Duration>& time) {
|
||||
std::unique_lock lk{mutex};
|
||||
|
||||
@@ -46,9 +46,16 @@ public:
|
||||
ElementPtr* new_ptr = new ElementPtr();
|
||||
write_ptr->next.store(new_ptr, std::memory_order_release);
|
||||
write_ptr = new_ptr;
|
||||
cv.notify_one();
|
||||
|
||||
++size;
|
||||
const size_t previous_size{size++};
|
||||
|
||||
// Acquire the mutex and then immediately release it as a fence.
|
||||
// TODO(bunnei): This can be replaced with C++20 waitable atomics when properly supported.
|
||||
// See discussion on https://github.com/yuzu-emu/yuzu/pull/3173 for details.
|
||||
if (previous_size == 0) {
|
||||
std::lock_guard lock{cv_mutex};
|
||||
}
|
||||
cv.notify_one();
|
||||
}
|
||||
|
||||
void Pop() {
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include "common/common_types.h"
|
||||
#include "common/x64/cpu_detect.h"
|
||||
|
||||
@@ -51,8 +49,6 @@ namespace Common {
|
||||
static CPUCaps Detect() {
|
||||
CPUCaps caps = {};
|
||||
|
||||
caps.num_cores = std::thread::hardware_concurrency();
|
||||
|
||||
// Assumes the CPU supports the CPUID instruction. Those that don't would likely not support
|
||||
// yuzu at all anyway
|
||||
|
||||
@@ -70,12 +66,6 @@ static CPUCaps Detect() {
|
||||
__cpuid(cpu_id, 0x80000000);
|
||||
|
||||
u32 max_ex_fn = cpu_id[0];
|
||||
if (!strcmp(caps.brand_string, "GenuineIntel"))
|
||||
caps.vendor = CPUVendor::INTEL;
|
||||
else if (!strcmp(caps.brand_string, "AuthenticAMD"))
|
||||
caps.vendor = CPUVendor::AMD;
|
||||
else
|
||||
caps.vendor = CPUVendor::OTHER;
|
||||
|
||||
// Set reasonable default brand string even if brand string not available
|
||||
strcpy(caps.cpu_string, caps.brand_string);
|
||||
@@ -96,15 +86,9 @@ static CPUCaps Detect() {
|
||||
caps.sse4_1 = true;
|
||||
if ((cpu_id[2] >> 20) & 1)
|
||||
caps.sse4_2 = true;
|
||||
if ((cpu_id[2] >> 22) & 1)
|
||||
caps.movbe = true;
|
||||
if ((cpu_id[2] >> 25) & 1)
|
||||
caps.aes = true;
|
||||
|
||||
if ((cpu_id[3] >> 24) & 1) {
|
||||
caps.fxsave_fxrstor = true;
|
||||
}
|
||||
|
||||
// AVX support requires 3 separate checks:
|
||||
// - Is the AVX bit set in CPUID?
|
||||
// - Is the XSAVE bit set in CPUID?
|
||||
@@ -129,8 +113,6 @@ static CPUCaps Detect() {
|
||||
}
|
||||
}
|
||||
|
||||
caps.flush_to_zero = caps.sse;
|
||||
|
||||
if (max_ex_fn >= 0x80000004) {
|
||||
// Extract CPU model string
|
||||
__cpuid(cpu_id, 0x80000002);
|
||||
@@ -144,14 +126,8 @@ static CPUCaps Detect() {
|
||||
if (max_ex_fn >= 0x80000001) {
|
||||
// Check for more features
|
||||
__cpuid(cpu_id, 0x80000001);
|
||||
if (cpu_id[2] & 1)
|
||||
caps.lahf_sahf_64 = true;
|
||||
if ((cpu_id[2] >> 5) & 1)
|
||||
caps.lzcnt = true;
|
||||
if ((cpu_id[2] >> 16) & 1)
|
||||
caps.fma4 = true;
|
||||
if ((cpu_id[3] >> 29) & 1)
|
||||
caps.long_mode = true;
|
||||
}
|
||||
|
||||
return caps;
|
||||
@@ -162,48 +138,4 @@ const CPUCaps& GetCPUCaps() {
|
||||
return caps;
|
||||
}
|
||||
|
||||
std::string GetCPUCapsString() {
|
||||
auto caps = GetCPUCaps();
|
||||
|
||||
std::string sum(caps.cpu_string);
|
||||
sum += " (";
|
||||
sum += caps.brand_string;
|
||||
sum += ")";
|
||||
|
||||
if (caps.sse)
|
||||
sum += ", SSE";
|
||||
if (caps.sse2) {
|
||||
sum += ", SSE2";
|
||||
if (!caps.flush_to_zero)
|
||||
sum += " (without DAZ)";
|
||||
}
|
||||
|
||||
if (caps.sse3)
|
||||
sum += ", SSE3";
|
||||
if (caps.ssse3)
|
||||
sum += ", SSSE3";
|
||||
if (caps.sse4_1)
|
||||
sum += ", SSE4.1";
|
||||
if (caps.sse4_2)
|
||||
sum += ", SSE4.2";
|
||||
if (caps.avx)
|
||||
sum += ", AVX";
|
||||
if (caps.avx2)
|
||||
sum += ", AVX2";
|
||||
if (caps.bmi1)
|
||||
sum += ", BMI1";
|
||||
if (caps.bmi2)
|
||||
sum += ", BMI2";
|
||||
if (caps.fma)
|
||||
sum += ", FMA";
|
||||
if (caps.aes)
|
||||
sum += ", AES";
|
||||
if (caps.movbe)
|
||||
sum += ", MOVBE";
|
||||
if (caps.long_mode)
|
||||
sum += ", 64-bit support";
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
} // namespace Common
|
||||
|
||||
@@ -4,23 +4,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace Common {
|
||||
|
||||
/// x86/x64 CPU vendors that may be detected by this module
|
||||
enum class CPUVendor {
|
||||
INTEL,
|
||||
AMD,
|
||||
OTHER,
|
||||
};
|
||||
|
||||
/// x86/x64 CPU capabilities that may be detected by this module
|
||||
struct CPUCaps {
|
||||
CPUVendor vendor;
|
||||
char cpu_string[0x21];
|
||||
char brand_string[0x41];
|
||||
int num_cores;
|
||||
bool sse;
|
||||
bool sse2;
|
||||
bool sse3;
|
||||
@@ -35,20 +24,6 @@ struct CPUCaps {
|
||||
bool fma;
|
||||
bool fma4;
|
||||
bool aes;
|
||||
|
||||
// Support for the FXSAVE and FXRSTOR instructions
|
||||
bool fxsave_fxrstor;
|
||||
|
||||
bool movbe;
|
||||
|
||||
// This flag indicates that the hardware supports some mode in which denormal inputs and outputs
|
||||
// are automatically set to (signed) zero.
|
||||
bool flush_to_zero;
|
||||
|
||||
// Support for LAHF and SAHF instructions in 64-bit mode
|
||||
bool lahf_sahf_64;
|
||||
|
||||
bool long_mode;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -57,10 +32,4 @@ struct CPUCaps {
|
||||
*/
|
||||
const CPUCaps& GetCPUCaps();
|
||||
|
||||
/**
|
||||
* Gets a string summary of the name and supported capabilities of the host CPU
|
||||
* @return String summary
|
||||
*/
|
||||
std::string GetCPUCapsString();
|
||||
|
||||
} // namespace Common
|
||||
|
||||
@@ -15,14 +15,14 @@ add_library(core STATIC
|
||||
constants.h
|
||||
core.cpp
|
||||
core.h
|
||||
core_cpu.cpp
|
||||
core_cpu.h
|
||||
core_manager.cpp
|
||||
core_manager.h
|
||||
core_timing.cpp
|
||||
core_timing.h
|
||||
core_timing_util.cpp
|
||||
core_timing_util.h
|
||||
cpu_core_manager.cpp
|
||||
cpu_core_manager.h
|
||||
cpu_manager.cpp
|
||||
cpu_manager.h
|
||||
crypto/aes_util.cpp
|
||||
crypto/aes_util.h
|
||||
crypto/encryption_layer.cpp
|
||||
@@ -96,6 +96,8 @@ add_library(core STATIC
|
||||
file_sys/system_archive/system_archive.h
|
||||
file_sys/system_archive/system_version.cpp
|
||||
file_sys/system_archive/system_version.h
|
||||
file_sys/system_archive/time_zone_binary.cpp
|
||||
file_sys/system_archive/time_zone_binary.h
|
||||
file_sys/vfs.cpp
|
||||
file_sys/vfs.h
|
||||
file_sys/vfs_concat.cpp
|
||||
@@ -156,6 +158,8 @@ add_library(core STATIC
|
||||
hle/kernel/mutex.h
|
||||
hle/kernel/object.cpp
|
||||
hle/kernel/object.h
|
||||
hle/kernel/physical_core.cpp
|
||||
hle/kernel/physical_core.h
|
||||
hle/kernel/process.cpp
|
||||
hle/kernel/process.h
|
||||
hle/kernel/process_capability.cpp
|
||||
@@ -461,12 +465,40 @@ add_library(core STATIC
|
||||
hle/service/spl/spl.h
|
||||
hle/service/ssl/ssl.cpp
|
||||
hle/service/ssl/ssl.h
|
||||
hle/service/time/clock_types.h
|
||||
hle/service/time/ephemeral_network_system_clock_context_writer.h
|
||||
hle/service/time/ephemeral_network_system_clock_core.h
|
||||
hle/service/time/errors.h
|
||||
hle/service/time/interface.cpp
|
||||
hle/service/time/interface.h
|
||||
hle/service/time/local_system_clock_context_writer.h
|
||||
hle/service/time/network_system_clock_context_writer.h
|
||||
hle/service/time/standard_local_system_clock_core.h
|
||||
hle/service/time/standard_network_system_clock_core.h
|
||||
hle/service/time/standard_steady_clock_core.cpp
|
||||
hle/service/time/standard_steady_clock_core.h
|
||||
hle/service/time/standard_user_system_clock_core.cpp
|
||||
hle/service/time/standard_user_system_clock_core.h
|
||||
hle/service/time/steady_clock_core.h
|
||||
hle/service/time/system_clock_context_update_callback.cpp
|
||||
hle/service/time/system_clock_context_update_callback.h
|
||||
hle/service/time/system_clock_core.cpp
|
||||
hle/service/time/system_clock_core.h
|
||||
hle/service/time/tick_based_steady_clock_core.cpp
|
||||
hle/service/time/tick_based_steady_clock_core.h
|
||||
hle/service/time/time.cpp
|
||||
hle/service/time/time.h
|
||||
hle/service/time/time_manager.cpp
|
||||
hle/service/time/time_manager.h
|
||||
hle/service/time/time_sharedmemory.cpp
|
||||
hle/service/time/time_sharedmemory.h
|
||||
hle/service/time/time_zone_content_manager.cpp
|
||||
hle/service/time/time_zone_content_manager.h
|
||||
hle/service/time/time_zone_manager.cpp
|
||||
hle/service/time/time_zone_manager.h
|
||||
hle/service/time/time_zone_service.cpp
|
||||
hle/service/time/time_zone_service.h
|
||||
hle/service/time/time_zone_types.h
|
||||
hle/service/usb/usb.cpp
|
||||
hle/service/usb/usb.h
|
||||
hle/service/vi/display/vi_display.cpp
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include "common/microprofile.h"
|
||||
#include "core/arm/dynarmic/arm_dynarmic.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_cpu.h"
|
||||
#include "core/core_manager.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/core_timing_util.h"
|
||||
#include "core/gdbstub/gdbstub.h"
|
||||
@@ -141,6 +141,7 @@ std::unique_ptr<Dynarmic::A64::Jit> ARM_Dynarmic::MakeJit(Common::PageTable& pag
|
||||
config.page_table = reinterpret_cast<void**>(page_table.pointers.data());
|
||||
config.page_table_address_space_bits = address_space_bits;
|
||||
config.silently_mirror_page_table = false;
|
||||
config.absolute_offset_page_table = true;
|
||||
|
||||
// Multi-process state
|
||||
config.processor_id = core_index;
|
||||
|
||||
@@ -2,10 +2,24 @@
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#ifdef ARCHITECTURE_x86_64
|
||||
#include "core/arm/dynarmic/arm_dynarmic.h"
|
||||
#endif
|
||||
#include "core/arm/exclusive_monitor.h"
|
||||
#include "core/memory.h"
|
||||
|
||||
namespace Core {
|
||||
|
||||
ExclusiveMonitor::~ExclusiveMonitor() = default;
|
||||
|
||||
std::unique_ptr<Core::ExclusiveMonitor> MakeExclusiveMonitor(Memory::Memory& memory,
|
||||
std::size_t num_cores) {
|
||||
#ifdef ARCHITECTURE_x86_64
|
||||
return std::make_unique<Core::DynarmicExclusiveMonitor>(memory, num_cores);
|
||||
#else
|
||||
// TODO(merry): Passthrough exclusive monitor
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace Core
|
||||
|
||||
@@ -4,8 +4,14 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace Memory {
|
||||
class Memory;
|
||||
}
|
||||
|
||||
namespace Core {
|
||||
|
||||
class ExclusiveMonitor {
|
||||
@@ -22,4 +28,7 @@ public:
|
||||
virtual bool ExclusiveWrite128(std::size_t core_index, VAddr vaddr, u128 value) = 0;
|
||||
};
|
||||
|
||||
std::unique_ptr<Core::ExclusiveMonitor> MakeExclusiveMonitor(Memory::Memory& memory,
|
||||
std::size_t num_cores);
|
||||
|
||||
} // namespace Core
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
#include "common/string_util.h"
|
||||
#include "core/arm/exclusive_monitor.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_cpu.h"
|
||||
#include "core/core_manager.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/cpu_core_manager.h"
|
||||
#include "core/cpu_manager.h"
|
||||
#include "core/file_sys/bis_factory.h"
|
||||
#include "core/file_sys/card_image.h"
|
||||
#include "core/file_sys/mode.h"
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "core/hardware_interrupt_manager.h"
|
||||
#include "core/hle/kernel/client_port.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
#include "core/hle/kernel/physical_core.h"
|
||||
#include "core/hle/kernel/process.h"
|
||||
#include "core/hle/kernel/scheduler.h"
|
||||
#include "core/hle/kernel/thread.h"
|
||||
@@ -46,7 +47,6 @@
|
||||
#include "core/settings.h"
|
||||
#include "core/telemetry_session.h"
|
||||
#include "core/tools/freezer.h"
|
||||
#include "video_core/debug_utils/debug_utils.h"
|
||||
#include "video_core/renderer_base.h"
|
||||
#include "video_core/video_core.h"
|
||||
|
||||
@@ -114,16 +114,25 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
|
||||
struct System::Impl {
|
||||
explicit Impl(System& system)
|
||||
: kernel{system}, fs_controller{system}, memory{system},
|
||||
cpu_core_manager{system}, reporter{system}, applet_manager{system} {}
|
||||
cpu_manager{system}, reporter{system}, applet_manager{system} {}
|
||||
|
||||
Cpu& CurrentCpuCore() {
|
||||
return cpu_core_manager.GetCurrentCore();
|
||||
CoreManager& CurrentCoreManager() {
|
||||
return cpu_manager.GetCurrentCoreManager();
|
||||
}
|
||||
|
||||
Kernel::PhysicalCore& CurrentPhysicalCore() {
|
||||
const auto index = cpu_manager.GetActiveCoreIndex();
|
||||
return kernel.PhysicalCore(index);
|
||||
}
|
||||
|
||||
Kernel::PhysicalCore& GetPhysicalCore(std::size_t index) {
|
||||
return kernel.PhysicalCore(index);
|
||||
}
|
||||
|
||||
ResultStatus RunLoop(bool tight_loop) {
|
||||
status = ResultStatus::Success;
|
||||
|
||||
cpu_core_manager.RunLoop(tight_loop);
|
||||
cpu_manager.RunLoop(tight_loop);
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -132,8 +141,8 @@ struct System::Impl {
|
||||
LOG_DEBUG(HW_Memory, "initialized OK");
|
||||
|
||||
core_timing.Initialize();
|
||||
cpu_core_manager.Initialize();
|
||||
kernel.Initialize();
|
||||
cpu_manager.Initialize();
|
||||
|
||||
const auto current_time = std::chrono::duration_cast<std::chrono::seconds>(
|
||||
std::chrono::system_clock::now().time_since_epoch());
|
||||
@@ -206,7 +215,6 @@ struct System::Impl {
|
||||
// Main process has been loaded and been made current.
|
||||
// Begin GPU and CPU execution.
|
||||
gpu_core->Start();
|
||||
cpu_core_manager.StartThreads();
|
||||
|
||||
// Initialize cheat engine
|
||||
if (cheat_engine) {
|
||||
@@ -273,7 +281,7 @@ struct System::Impl {
|
||||
gpu_core.reset();
|
||||
|
||||
// Close all CPU/threading state
|
||||
cpu_core_manager.Shutdown();
|
||||
cpu_manager.Shutdown();
|
||||
|
||||
// Shutdown kernel and core timing
|
||||
kernel.Shutdown();
|
||||
@@ -341,10 +349,9 @@ struct System::Impl {
|
||||
std::unique_ptr<Loader::AppLoader> app_loader;
|
||||
std::unique_ptr<VideoCore::RendererBase> renderer;
|
||||
std::unique_ptr<Tegra::GPU> gpu_core;
|
||||
std::shared_ptr<Tegra::DebugContext> debug_context;
|
||||
std::unique_ptr<Hardware::InterruptManager> interrupt_manager;
|
||||
Memory::Memory memory;
|
||||
CpuCoreManager cpu_core_manager;
|
||||
CpuManager cpu_manager;
|
||||
bool is_powered_on = false;
|
||||
bool exit_lock = false;
|
||||
|
||||
@@ -379,12 +386,12 @@ struct System::Impl {
|
||||
System::System() : impl{std::make_unique<Impl>(*this)} {}
|
||||
System::~System() = default;
|
||||
|
||||
Cpu& System::CurrentCpuCore() {
|
||||
return impl->CurrentCpuCore();
|
||||
CoreManager& System::CurrentCoreManager() {
|
||||
return impl->CurrentCoreManager();
|
||||
}
|
||||
|
||||
const Cpu& System::CurrentCpuCore() const {
|
||||
return impl->CurrentCpuCore();
|
||||
const CoreManager& System::CurrentCoreManager() const {
|
||||
return impl->CurrentCoreManager();
|
||||
}
|
||||
|
||||
System::ResultStatus System::RunLoop(bool tight_loop) {
|
||||
@@ -396,7 +403,7 @@ System::ResultStatus System::SingleStep() {
|
||||
}
|
||||
|
||||
void System::InvalidateCpuInstructionCaches() {
|
||||
impl->cpu_core_manager.InvalidateAllInstructionCaches();
|
||||
impl->kernel.InvalidateAllInstructionCaches();
|
||||
}
|
||||
|
||||
System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::string& filepath) {
|
||||
@@ -408,13 +415,11 @@ bool System::IsPoweredOn() const {
|
||||
}
|
||||
|
||||
void System::PrepareReschedule() {
|
||||
CurrentCpuCore().PrepareReschedule();
|
||||
impl->CurrentPhysicalCore().Stop();
|
||||
}
|
||||
|
||||
void System::PrepareReschedule(const u32 core_index) {
|
||||
if (core_index < GlobalScheduler().CpuCoresCount()) {
|
||||
CpuCore(core_index).PrepareReschedule();
|
||||
}
|
||||
impl->kernel.PrepareReschedule(core_index);
|
||||
}
|
||||
|
||||
PerfStatsResults System::GetAndResetPerfStats() {
|
||||
@@ -430,31 +435,31 @@ const TelemetrySession& System::TelemetrySession() const {
|
||||
}
|
||||
|
||||
ARM_Interface& System::CurrentArmInterface() {
|
||||
return CurrentCpuCore().ArmInterface();
|
||||
return impl->CurrentPhysicalCore().ArmInterface();
|
||||
}
|
||||
|
||||
const ARM_Interface& System::CurrentArmInterface() const {
|
||||
return CurrentCpuCore().ArmInterface();
|
||||
return impl->CurrentPhysicalCore().ArmInterface();
|
||||
}
|
||||
|
||||
std::size_t System::CurrentCoreIndex() const {
|
||||
return CurrentCpuCore().CoreIndex();
|
||||
return impl->cpu_manager.GetActiveCoreIndex();
|
||||
}
|
||||
|
||||
Kernel::Scheduler& System::CurrentScheduler() {
|
||||
return CurrentCpuCore().Scheduler();
|
||||
return impl->CurrentPhysicalCore().Scheduler();
|
||||
}
|
||||
|
||||
const Kernel::Scheduler& System::CurrentScheduler() const {
|
||||
return CurrentCpuCore().Scheduler();
|
||||
return impl->CurrentPhysicalCore().Scheduler();
|
||||
}
|
||||
|
||||
Kernel::Scheduler& System::Scheduler(std::size_t core_index) {
|
||||
return CpuCore(core_index).Scheduler();
|
||||
return impl->GetPhysicalCore(core_index).Scheduler();
|
||||
}
|
||||
|
||||
const Kernel::Scheduler& System::Scheduler(std::size_t core_index) const {
|
||||
return CpuCore(core_index).Scheduler();
|
||||
return impl->GetPhysicalCore(core_index).Scheduler();
|
||||
}
|
||||
|
||||
/// Gets the global scheduler
|
||||
@@ -476,28 +481,28 @@ const Kernel::Process* System::CurrentProcess() const {
|
||||
}
|
||||
|
||||
ARM_Interface& System::ArmInterface(std::size_t core_index) {
|
||||
return CpuCore(core_index).ArmInterface();
|
||||
return impl->GetPhysicalCore(core_index).ArmInterface();
|
||||
}
|
||||
|
||||
const ARM_Interface& System::ArmInterface(std::size_t core_index) const {
|
||||
return CpuCore(core_index).ArmInterface();
|
||||
return impl->GetPhysicalCore(core_index).ArmInterface();
|
||||
}
|
||||
|
||||
Cpu& System::CpuCore(std::size_t core_index) {
|
||||
return impl->cpu_core_manager.GetCore(core_index);
|
||||
CoreManager& System::GetCoreManager(std::size_t core_index) {
|
||||
return impl->cpu_manager.GetCoreManager(core_index);
|
||||
}
|
||||
|
||||
const Cpu& System::CpuCore(std::size_t core_index) const {
|
||||
const CoreManager& System::GetCoreManager(std::size_t core_index) const {
|
||||
ASSERT(core_index < NUM_CPU_CORES);
|
||||
return impl->cpu_core_manager.GetCore(core_index);
|
||||
return impl->cpu_manager.GetCoreManager(core_index);
|
||||
}
|
||||
|
||||
ExclusiveMonitor& System::Monitor() {
|
||||
return impl->cpu_core_manager.GetExclusiveMonitor();
|
||||
return impl->kernel.GetExclusiveMonitor();
|
||||
}
|
||||
|
||||
const ExclusiveMonitor& System::Monitor() const {
|
||||
return impl->cpu_core_manager.GetExclusiveMonitor();
|
||||
return impl->kernel.GetExclusiveMonitor();
|
||||
}
|
||||
|
||||
Memory::Memory& System::Memory() {
|
||||
@@ -580,14 +585,6 @@ Loader::AppLoader& System::GetAppLoader() const {
|
||||
return *impl->app_loader;
|
||||
}
|
||||
|
||||
void System::SetGPUDebugContext(std::shared_ptr<Tegra::DebugContext> context) {
|
||||
impl->debug_context = std::move(context);
|
||||
}
|
||||
|
||||
Tegra::DebugContext* System::GetGPUDebugContext() const {
|
||||
return impl->debug_context.get();
|
||||
}
|
||||
|
||||
void System::SetFilesystem(std::shared_ptr<FileSys::VfsFilesystem> vfs) {
|
||||
impl->virtual_filesystem = std::move(vfs);
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ class Memory;
|
||||
namespace Core {
|
||||
|
||||
class ARM_Interface;
|
||||
class Cpu;
|
||||
class CoreManager;
|
||||
class ExclusiveMonitor;
|
||||
class FrameLimiter;
|
||||
class PerfStats;
|
||||
@@ -218,10 +218,10 @@ public:
|
||||
const ARM_Interface& ArmInterface(std::size_t core_index) const;
|
||||
|
||||
/// Gets a CPU interface to the CPU core with the specified index
|
||||
Cpu& CpuCore(std::size_t core_index);
|
||||
CoreManager& GetCoreManager(std::size_t core_index);
|
||||
|
||||
/// Gets a CPU interface to the CPU core with the specified index
|
||||
const Cpu& CpuCore(std::size_t core_index) const;
|
||||
const CoreManager& GetCoreManager(std::size_t core_index) const;
|
||||
|
||||
/// Gets a reference to the exclusive monitor
|
||||
ExclusiveMonitor& Monitor();
|
||||
@@ -307,10 +307,6 @@ public:
|
||||
Service::SM::ServiceManager& ServiceManager();
|
||||
const Service::SM::ServiceManager& ServiceManager() const;
|
||||
|
||||
void SetGPUDebugContext(std::shared_ptr<Tegra::DebugContext> context);
|
||||
|
||||
Tegra::DebugContext* GetGPUDebugContext() const;
|
||||
|
||||
void SetFilesystem(std::shared_ptr<FileSys::VfsFilesystem> vfs);
|
||||
|
||||
std::shared_ptr<FileSys::VfsFilesystem> GetFilesystem() const;
|
||||
@@ -368,10 +364,10 @@ private:
|
||||
System();
|
||||
|
||||
/// Returns the currently running CPU core
|
||||
Cpu& CurrentCpuCore();
|
||||
CoreManager& CurrentCoreManager();
|
||||
|
||||
/// Returns the currently running CPU core
|
||||
const Cpu& CurrentCpuCore() const;
|
||||
const CoreManager& CurrentCoreManager() const;
|
||||
|
||||
/**
|
||||
* Initialize the emulated system.
|
||||
|
||||
@@ -1,127 +0,0 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#ifdef ARCHITECTURE_x86_64
|
||||
#include "core/arm/dynarmic/arm_dynarmic.h"
|
||||
#endif
|
||||
#include "core/arm/exclusive_monitor.h"
|
||||
#include "core/arm/unicorn/arm_unicorn.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_cpu.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/hle/kernel/scheduler.h"
|
||||
#include "core/hle/kernel/thread.h"
|
||||
#include "core/hle/lock.h"
|
||||
#include "core/settings.h"
|
||||
|
||||
namespace Core {
|
||||
|
||||
void CpuBarrier::NotifyEnd() {
|
||||
std::unique_lock lock{mutex};
|
||||
end = true;
|
||||
condition.notify_all();
|
||||
}
|
||||
|
||||
bool CpuBarrier::Rendezvous() {
|
||||
if (!Settings::values.use_multi_core) {
|
||||
// Meaningless when running in single-core mode
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!end) {
|
||||
std::unique_lock lock{mutex};
|
||||
|
||||
--cores_waiting;
|
||||
if (!cores_waiting) {
|
||||
cores_waiting = NUM_CPU_CORES;
|
||||
condition.notify_all();
|
||||
return true;
|
||||
}
|
||||
|
||||
condition.wait(lock);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Cpu::Cpu(System& system, ExclusiveMonitor& exclusive_monitor, CpuBarrier& cpu_barrier,
|
||||
std::size_t core_index)
|
||||
: cpu_barrier{cpu_barrier}, global_scheduler{system.GlobalScheduler()},
|
||||
core_timing{system.CoreTiming()}, core_index{core_index} {
|
||||
#ifdef ARCHITECTURE_x86_64
|
||||
arm_interface = std::make_unique<ARM_Dynarmic>(system, exclusive_monitor, core_index);
|
||||
#else
|
||||
arm_interface = std::make_unique<ARM_Unicorn>(system);
|
||||
LOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available");
|
||||
#endif
|
||||
|
||||
scheduler = std::make_unique<Kernel::Scheduler>(system, *arm_interface, core_index);
|
||||
}
|
||||
|
||||
Cpu::~Cpu() = default;
|
||||
|
||||
std::unique_ptr<ExclusiveMonitor> Cpu::MakeExclusiveMonitor(
|
||||
[[maybe_unused]] Memory::Memory& memory, [[maybe_unused]] std::size_t num_cores) {
|
||||
#ifdef ARCHITECTURE_x86_64
|
||||
return std::make_unique<DynarmicExclusiveMonitor>(memory, num_cores);
|
||||
#else
|
||||
// TODO(merry): Passthrough exclusive monitor
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Cpu::RunLoop(bool tight_loop) {
|
||||
// Wait for all other CPU cores to complete the previous slice, such that they run in lock-step
|
||||
if (!cpu_barrier.Rendezvous()) {
|
||||
// If rendezvous failed, session has been killed
|
||||
return;
|
||||
}
|
||||
|
||||
Reschedule();
|
||||
|
||||
// If we don't have a currently active thread then don't execute instructions,
|
||||
// instead advance to the next event and try to yield to the next thread
|
||||
if (Kernel::GetCurrentThread() == nullptr) {
|
||||
LOG_TRACE(Core, "Core-{} idling", core_index);
|
||||
core_timing.Idle();
|
||||
} else {
|
||||
if (tight_loop) {
|
||||
arm_interface->Run();
|
||||
} else {
|
||||
arm_interface->Step();
|
||||
}
|
||||
// We are stopping a run, exclusive state must be cleared
|
||||
arm_interface->ClearExclusiveState();
|
||||
}
|
||||
core_timing.Advance();
|
||||
|
||||
Reschedule();
|
||||
}
|
||||
|
||||
void Cpu::SingleStep() {
|
||||
return RunLoop(false);
|
||||
}
|
||||
|
||||
void Cpu::PrepareReschedule() {
|
||||
arm_interface->PrepareReschedule();
|
||||
}
|
||||
|
||||
void Cpu::Reschedule() {
|
||||
// Lock the global kernel mutex when we manipulate the HLE state
|
||||
std::lock_guard lock(HLE::g_hle_lock);
|
||||
|
||||
global_scheduler.SelectThread(core_index);
|
||||
scheduler->TryDoContextSwitch();
|
||||
}
|
||||
|
||||
void Cpu::Shutdown() {
|
||||
scheduler->Shutdown();
|
||||
}
|
||||
|
||||
} // namespace Core
|
||||
@@ -1,120 +0,0 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <condition_variable>
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace Kernel {
|
||||
class GlobalScheduler;
|
||||
class Scheduler;
|
||||
} // namespace Kernel
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
}
|
||||
|
||||
namespace Core::Timing {
|
||||
class CoreTiming;
|
||||
}
|
||||
|
||||
namespace Memory {
|
||||
class Memory;
|
||||
}
|
||||
|
||||
namespace Core {
|
||||
|
||||
class ARM_Interface;
|
||||
class ExclusiveMonitor;
|
||||
|
||||
constexpr unsigned NUM_CPU_CORES{4};
|
||||
|
||||
class CpuBarrier {
|
||||
public:
|
||||
bool IsAlive() const {
|
||||
return !end;
|
||||
}
|
||||
|
||||
void NotifyEnd();
|
||||
|
||||
bool Rendezvous();
|
||||
|
||||
private:
|
||||
unsigned cores_waiting{NUM_CPU_CORES};
|
||||
std::mutex mutex;
|
||||
std::condition_variable condition;
|
||||
std::atomic<bool> end{};
|
||||
};
|
||||
|
||||
class Cpu {
|
||||
public:
|
||||
Cpu(System& system, ExclusiveMonitor& exclusive_monitor, CpuBarrier& cpu_barrier,
|
||||
std::size_t core_index);
|
||||
~Cpu();
|
||||
|
||||
void RunLoop(bool tight_loop = true);
|
||||
|
||||
void SingleStep();
|
||||
|
||||
void PrepareReschedule();
|
||||
|
||||
ARM_Interface& ArmInterface() {
|
||||
return *arm_interface;
|
||||
}
|
||||
|
||||
const ARM_Interface& ArmInterface() const {
|
||||
return *arm_interface;
|
||||
}
|
||||
|
||||
Kernel::Scheduler& Scheduler() {
|
||||
return *scheduler;
|
||||
}
|
||||
|
||||
const Kernel::Scheduler& Scheduler() const {
|
||||
return *scheduler;
|
||||
}
|
||||
|
||||
bool IsMainCore() const {
|
||||
return core_index == 0;
|
||||
}
|
||||
|
||||
std::size_t CoreIndex() const {
|
||||
return core_index;
|
||||
}
|
||||
|
||||
void Shutdown();
|
||||
|
||||
/**
|
||||
* Creates an exclusive monitor to handle exclusive reads/writes.
|
||||
*
|
||||
* @param memory The current memory subsystem that the monitor may wish
|
||||
* to keep track of.
|
||||
*
|
||||
* @param num_cores The number of cores to assume about the CPU.
|
||||
*
|
||||
* @returns The constructed exclusive monitor instance, or nullptr if the current
|
||||
* CPU backend is unable to use an exclusive monitor.
|
||||
*/
|
||||
static std::unique_ptr<ExclusiveMonitor> MakeExclusiveMonitor(Memory::Memory& memory,
|
||||
std::size_t num_cores);
|
||||
|
||||
private:
|
||||
void Reschedule();
|
||||
|
||||
std::unique_ptr<ARM_Interface> arm_interface;
|
||||
CpuBarrier& cpu_barrier;
|
||||
Kernel::GlobalScheduler& global_scheduler;
|
||||
std::unique_ptr<Kernel::Scheduler> scheduler;
|
||||
Timing::CoreTiming& core_timing;
|
||||
|
||||
std::atomic<bool> reschedule_pending = false;
|
||||
std::size_t core_index;
|
||||
};
|
||||
|
||||
} // namespace Core
|
||||
70
src/core/core_manager.cpp
Normal file
70
src/core/core_manager.cpp
Normal file
@@ -0,0 +1,70 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#ifdef ARCHITECTURE_x86_64
|
||||
#include "core/arm/dynarmic/arm_dynarmic.h"
|
||||
#endif
|
||||
#include "core/arm/exclusive_monitor.h"
|
||||
#include "core/arm/unicorn/arm_unicorn.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_manager.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
#include "core/hle/kernel/physical_core.h"
|
||||
#include "core/hle/kernel/scheduler.h"
|
||||
#include "core/hle/kernel/thread.h"
|
||||
#include "core/hle/lock.h"
|
||||
#include "core/settings.h"
|
||||
|
||||
namespace Core {
|
||||
|
||||
CoreManager::CoreManager(System& system, std::size_t core_index)
|
||||
: global_scheduler{system.GlobalScheduler()}, physical_core{system.Kernel().PhysicalCore(
|
||||
core_index)},
|
||||
core_timing{system.CoreTiming()}, core_index{core_index} {}
|
||||
|
||||
CoreManager::~CoreManager() = default;
|
||||
|
||||
void CoreManager::RunLoop(bool tight_loop) {
|
||||
Reschedule();
|
||||
|
||||
// If we don't have a currently active thread then don't execute instructions,
|
||||
// instead advance to the next event and try to yield to the next thread
|
||||
if (Kernel::GetCurrentThread() == nullptr) {
|
||||
LOG_TRACE(Core, "Core-{} idling", core_index);
|
||||
core_timing.Idle();
|
||||
} else {
|
||||
if (tight_loop) {
|
||||
physical_core.Run();
|
||||
} else {
|
||||
physical_core.Step();
|
||||
}
|
||||
}
|
||||
core_timing.Advance();
|
||||
|
||||
Reschedule();
|
||||
}
|
||||
|
||||
void CoreManager::SingleStep() {
|
||||
return RunLoop(false);
|
||||
}
|
||||
|
||||
void CoreManager::PrepareReschedule() {
|
||||
physical_core.Stop();
|
||||
}
|
||||
|
||||
void CoreManager::Reschedule() {
|
||||
// Lock the global kernel mutex when we manipulate the HLE state
|
||||
std::lock_guard lock(HLE::g_hle_lock);
|
||||
|
||||
global_scheduler.SelectThread(core_index);
|
||||
|
||||
physical_core.Scheduler().TryDoContextSwitch();
|
||||
}
|
||||
|
||||
} // namespace Core
|
||||
63
src/core/core_manager.h
Normal file
63
src/core/core_manager.h
Normal file
@@ -0,0 +1,63 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace Kernel {
|
||||
class GlobalScheduler;
|
||||
class PhysicalCore;
|
||||
} // namespace Kernel
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
}
|
||||
|
||||
namespace Core::Timing {
|
||||
class CoreTiming;
|
||||
}
|
||||
|
||||
namespace Memory {
|
||||
class Memory;
|
||||
}
|
||||
|
||||
namespace Core {
|
||||
|
||||
constexpr unsigned NUM_CPU_CORES{4};
|
||||
|
||||
class CoreManager {
|
||||
public:
|
||||
CoreManager(System& system, std::size_t core_index);
|
||||
~CoreManager();
|
||||
|
||||
void RunLoop(bool tight_loop = true);
|
||||
|
||||
void SingleStep();
|
||||
|
||||
void PrepareReschedule();
|
||||
|
||||
bool IsMainCore() const {
|
||||
return core_index == 0;
|
||||
}
|
||||
|
||||
std::size_t CoreIndex() const {
|
||||
return core_index;
|
||||
}
|
||||
|
||||
private:
|
||||
void Reschedule();
|
||||
|
||||
Kernel::GlobalScheduler& global_scheduler;
|
||||
Kernel::PhysicalCore& physical_core;
|
||||
Timing::CoreTiming& core_timing;
|
||||
|
||||
std::atomic<bool> reschedule_pending = false;
|
||||
std::size_t core_index;
|
||||
};
|
||||
|
||||
} // namespace Core
|
||||
@@ -1,152 +0,0 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "core/arm/exclusive_monitor.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_cpu.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/cpu_core_manager.h"
|
||||
#include "core/gdbstub/gdbstub.h"
|
||||
#include "core/settings.h"
|
||||
|
||||
namespace Core {
|
||||
namespace {
|
||||
void RunCpuCore(const System& system, Cpu& cpu_state) {
|
||||
while (system.IsPoweredOn()) {
|
||||
cpu_state.RunLoop(true);
|
||||
}
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
CpuCoreManager::CpuCoreManager(System& system) : system{system} {}
|
||||
CpuCoreManager::~CpuCoreManager() = default;
|
||||
|
||||
void CpuCoreManager::Initialize() {
|
||||
barrier = std::make_unique<CpuBarrier>();
|
||||
exclusive_monitor = Cpu::MakeExclusiveMonitor(system.Memory(), cores.size());
|
||||
|
||||
for (std::size_t index = 0; index < cores.size(); ++index) {
|
||||
cores[index] = std::make_unique<Cpu>(system, *exclusive_monitor, *barrier, index);
|
||||
}
|
||||
}
|
||||
|
||||
void CpuCoreManager::StartThreads() {
|
||||
// Create threads for CPU cores 1-3, and build thread_to_cpu map
|
||||
// CPU core 0 is run on the main thread
|
||||
thread_to_cpu[std::this_thread::get_id()] = cores[0].get();
|
||||
if (!Settings::values.use_multi_core) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (std::size_t index = 0; index < core_threads.size(); ++index) {
|
||||
core_threads[index] = std::make_unique<std::thread>(RunCpuCore, std::cref(system),
|
||||
std::ref(*cores[index + 1]));
|
||||
thread_to_cpu[core_threads[index]->get_id()] = cores[index + 1].get();
|
||||
}
|
||||
}
|
||||
|
||||
void CpuCoreManager::Shutdown() {
|
||||
barrier->NotifyEnd();
|
||||
if (Settings::values.use_multi_core) {
|
||||
for (auto& thread : core_threads) {
|
||||
thread->join();
|
||||
thread.reset();
|
||||
}
|
||||
}
|
||||
|
||||
thread_to_cpu.clear();
|
||||
for (auto& cpu_core : cores) {
|
||||
cpu_core->Shutdown();
|
||||
cpu_core.reset();
|
||||
}
|
||||
|
||||
exclusive_monitor.reset();
|
||||
barrier.reset();
|
||||
}
|
||||
|
||||
Cpu& CpuCoreManager::GetCore(std::size_t index) {
|
||||
return *cores.at(index);
|
||||
}
|
||||
|
||||
const Cpu& CpuCoreManager::GetCore(std::size_t index) const {
|
||||
return *cores.at(index);
|
||||
}
|
||||
|
||||
ExclusiveMonitor& CpuCoreManager::GetExclusiveMonitor() {
|
||||
return *exclusive_monitor;
|
||||
}
|
||||
|
||||
const ExclusiveMonitor& CpuCoreManager::GetExclusiveMonitor() const {
|
||||
return *exclusive_monitor;
|
||||
}
|
||||
|
||||
Cpu& CpuCoreManager::GetCurrentCore() {
|
||||
if (Settings::values.use_multi_core) {
|
||||
const auto& search = thread_to_cpu.find(std::this_thread::get_id());
|
||||
ASSERT(search != thread_to_cpu.end());
|
||||
ASSERT(search->second);
|
||||
return *search->second;
|
||||
}
|
||||
|
||||
// Otherwise, use single-threaded mode active_core variable
|
||||
return *cores[active_core];
|
||||
}
|
||||
|
||||
const Cpu& CpuCoreManager::GetCurrentCore() const {
|
||||
if (Settings::values.use_multi_core) {
|
||||
const auto& search = thread_to_cpu.find(std::this_thread::get_id());
|
||||
ASSERT(search != thread_to_cpu.end());
|
||||
ASSERT(search->second);
|
||||
return *search->second;
|
||||
}
|
||||
|
||||
// Otherwise, use single-threaded mode active_core variable
|
||||
return *cores[active_core];
|
||||
}
|
||||
|
||||
void CpuCoreManager::RunLoop(bool tight_loop) {
|
||||
// Update thread_to_cpu in case Core 0 is run from a different host thread
|
||||
thread_to_cpu[std::this_thread::get_id()] = cores[0].get();
|
||||
|
||||
if (GDBStub::IsServerEnabled()) {
|
||||
GDBStub::HandlePacket();
|
||||
|
||||
// If the loop is halted and we want to step, use a tiny (1) number of instructions to
|
||||
// execute. Otherwise, get out of the loop function.
|
||||
if (GDBStub::GetCpuHaltFlag()) {
|
||||
if (GDBStub::GetCpuStepFlag()) {
|
||||
tight_loop = false;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto& core_timing = system.CoreTiming();
|
||||
core_timing.ResetRun();
|
||||
bool keep_running{};
|
||||
do {
|
||||
keep_running = false;
|
||||
for (active_core = 0; active_core < NUM_CPU_CORES; ++active_core) {
|
||||
core_timing.SwitchContext(active_core);
|
||||
if (core_timing.CanCurrentContextRun()) {
|
||||
cores[active_core]->RunLoop(tight_loop);
|
||||
}
|
||||
keep_running |= core_timing.CanCurrentContextRun();
|
||||
}
|
||||
} while (keep_running);
|
||||
|
||||
if (GDBStub::IsServerEnabled()) {
|
||||
GDBStub::SetCpuStepFlag(false);
|
||||
}
|
||||
}
|
||||
|
||||
void CpuCoreManager::InvalidateAllInstructionCaches() {
|
||||
for (auto& cpu : cores) {
|
||||
cpu->ArmInterface().ClearInstructionCache();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Core
|
||||
@@ -1,62 +0,0 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
|
||||
namespace Core {
|
||||
|
||||
class Cpu;
|
||||
class CpuBarrier;
|
||||
class ExclusiveMonitor;
|
||||
class System;
|
||||
|
||||
class CpuCoreManager {
|
||||
public:
|
||||
explicit CpuCoreManager(System& system);
|
||||
CpuCoreManager(const CpuCoreManager&) = delete;
|
||||
CpuCoreManager(CpuCoreManager&&) = delete;
|
||||
|
||||
~CpuCoreManager();
|
||||
|
||||
CpuCoreManager& operator=(const CpuCoreManager&) = delete;
|
||||
CpuCoreManager& operator=(CpuCoreManager&&) = delete;
|
||||
|
||||
void Initialize();
|
||||
void StartThreads();
|
||||
void Shutdown();
|
||||
|
||||
Cpu& GetCore(std::size_t index);
|
||||
const Cpu& GetCore(std::size_t index) const;
|
||||
|
||||
Cpu& GetCurrentCore();
|
||||
const Cpu& GetCurrentCore() const;
|
||||
|
||||
ExclusiveMonitor& GetExclusiveMonitor();
|
||||
const ExclusiveMonitor& GetExclusiveMonitor() const;
|
||||
|
||||
void RunLoop(bool tight_loop);
|
||||
|
||||
void InvalidateAllInstructionCaches();
|
||||
|
||||
private:
|
||||
static constexpr std::size_t NUM_CPU_CORES = 4;
|
||||
|
||||
std::unique_ptr<ExclusiveMonitor> exclusive_monitor;
|
||||
std::unique_ptr<CpuBarrier> barrier;
|
||||
std::array<std::unique_ptr<Cpu>, NUM_CPU_CORES> cores;
|
||||
std::array<std::unique_ptr<std::thread>, NUM_CPU_CORES - 1> core_threads;
|
||||
std::size_t active_core{}; ///< Active core, only used in single thread mode
|
||||
|
||||
/// Map of guest threads to CPU cores
|
||||
std::map<std::thread::id, Cpu*> thread_to_cpu;
|
||||
|
||||
System& system;
|
||||
};
|
||||
|
||||
} // namespace Core
|
||||
83
src/core/cpu_manager.cpp
Normal file
83
src/core/cpu_manager.cpp
Normal file
@@ -0,0 +1,83 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "core/arm/exclusive_monitor.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_manager.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/cpu_manager.h"
|
||||
#include "core/gdbstub/gdbstub.h"
|
||||
#include "core/settings.h"
|
||||
|
||||
namespace Core {
|
||||
|
||||
CpuManager::CpuManager(System& system) : system{system} {}
|
||||
CpuManager::~CpuManager() = default;
|
||||
|
||||
void CpuManager::Initialize() {
|
||||
for (std::size_t index = 0; index < core_managers.size(); ++index) {
|
||||
core_managers[index] = std::make_unique<CoreManager>(system, index);
|
||||
}
|
||||
}
|
||||
|
||||
void CpuManager::Shutdown() {
|
||||
for (auto& cpu_core : core_managers) {
|
||||
cpu_core.reset();
|
||||
}
|
||||
}
|
||||
|
||||
CoreManager& CpuManager::GetCoreManager(std::size_t index) {
|
||||
return *core_managers.at(index);
|
||||
}
|
||||
|
||||
const CoreManager& CpuManager::GetCoreManager(std::size_t index) const {
|
||||
return *core_managers.at(index);
|
||||
}
|
||||
|
||||
CoreManager& CpuManager::GetCurrentCoreManager() {
|
||||
// Otherwise, use single-threaded mode active_core variable
|
||||
return *core_managers[active_core];
|
||||
}
|
||||
|
||||
const CoreManager& CpuManager::GetCurrentCoreManager() const {
|
||||
// Otherwise, use single-threaded mode active_core variable
|
||||
return *core_managers[active_core];
|
||||
}
|
||||
|
||||
void CpuManager::RunLoop(bool tight_loop) {
|
||||
if (GDBStub::IsServerEnabled()) {
|
||||
GDBStub::HandlePacket();
|
||||
|
||||
// If the loop is halted and we want to step, use a tiny (1) number of instructions to
|
||||
// execute. Otherwise, get out of the loop function.
|
||||
if (GDBStub::GetCpuHaltFlag()) {
|
||||
if (GDBStub::GetCpuStepFlag()) {
|
||||
tight_loop = false;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto& core_timing = system.CoreTiming();
|
||||
core_timing.ResetRun();
|
||||
bool keep_running{};
|
||||
do {
|
||||
keep_running = false;
|
||||
for (active_core = 0; active_core < NUM_CPU_CORES; ++active_core) {
|
||||
core_timing.SwitchContext(active_core);
|
||||
if (core_timing.CanCurrentContextRun()) {
|
||||
core_managers[active_core]->RunLoop(tight_loop);
|
||||
}
|
||||
keep_running |= core_timing.CanCurrentContextRun();
|
||||
}
|
||||
} while (keep_running);
|
||||
|
||||
if (GDBStub::IsServerEnabled()) {
|
||||
GDBStub::SetCpuStepFlag(false);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Core
|
||||
50
src/core/cpu_manager.h
Normal file
50
src/core/cpu_manager.h
Normal file
@@ -0,0 +1,50 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
|
||||
namespace Core {
|
||||
|
||||
class CoreManager;
|
||||
class System;
|
||||
|
||||
class CpuManager {
|
||||
public:
|
||||
explicit CpuManager(System& system);
|
||||
CpuManager(const CpuManager&) = delete;
|
||||
CpuManager(CpuManager&&) = delete;
|
||||
|
||||
~CpuManager();
|
||||
|
||||
CpuManager& operator=(const CpuManager&) = delete;
|
||||
CpuManager& operator=(CpuManager&&) = delete;
|
||||
|
||||
void Initialize();
|
||||
void Shutdown();
|
||||
|
||||
CoreManager& GetCoreManager(std::size_t index);
|
||||
const CoreManager& GetCoreManager(std::size_t index) const;
|
||||
|
||||
CoreManager& GetCurrentCoreManager();
|
||||
const CoreManager& GetCurrentCoreManager() const;
|
||||
|
||||
std::size_t GetActiveCoreIndex() const {
|
||||
return active_core;
|
||||
}
|
||||
|
||||
void RunLoop(bool tight_loop);
|
||||
|
||||
private:
|
||||
static constexpr std::size_t NUM_CPU_CORES = 4;
|
||||
|
||||
std::array<std::unique_ptr<CoreManager>, NUM_CPU_CORES> core_managers;
|
||||
std::size_t active_core{}; ///< Active core, only used in single thread mode
|
||||
|
||||
System& system;
|
||||
};
|
||||
|
||||
} // namespace Core
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "core/file_sys/system_archive/shared_font.h"
|
||||
#include "core/file_sys/system_archive/system_archive.h"
|
||||
#include "core/file_sys/system_archive/system_version.h"
|
||||
#include "core/file_sys/system_archive/time_zone_binary.h"
|
||||
|
||||
namespace FileSys::SystemArchive {
|
||||
|
||||
@@ -38,7 +39,7 @@ constexpr std::array<SystemArchiveDescriptor, SYSTEM_ARCHIVE_COUNT> SYSTEM_ARCHI
|
||||
{0x010000000000080B, "LocalNews", nullptr},
|
||||
{0x010000000000080C, "Eula", nullptr},
|
||||
{0x010000000000080D, "UrlBlackList", nullptr},
|
||||
{0x010000000000080E, "TimeZoneBinary", nullptr},
|
||||
{0x010000000000080E, "TimeZoneBinary", &TimeZoneBinary},
|
||||
{0x010000000000080F, "CertStoreCruiser", nullptr},
|
||||
{0x0100000000000810, "FontNintendoExtension", &FontNintendoExtension},
|
||||
{0x0100000000000811, "FontStandard", &FontStandard},
|
||||
|
||||
657
src/core/file_sys/system_archive/time_zone_binary.cpp
Normal file
657
src/core/file_sys/system_archive/time_zone_binary.cpp
Normal file
@@ -0,0 +1,657 @@
|
||||
// Copyright 2019 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/swap.h"
|
||||
#include "core/file_sys/system_archive/time_zone_binary.h"
|
||||
#include "core/file_sys/vfs_vector.h"
|
||||
#include "core/hle/service/time/time_zone_types.h"
|
||||
|
||||
namespace FileSys::SystemArchive {
|
||||
|
||||
static constexpr std::array<u8, 9633> LOCATION_NAMES{
|
||||
0x43, 0x45, 0x54, 0x0d, 0x0a, 0x43, 0x53, 0x54, 0x36, 0x43, 0x44, 0x54, 0x0d, 0x0a, 0x43, 0x75,
|
||||
0x62, 0x61, 0x0d, 0x0a, 0x45, 0x45, 0x54, 0x0d, 0x0a, 0x45, 0x67, 0x79, 0x70, 0x74, 0x0d, 0x0a,
|
||||
0x45, 0x69, 0x72, 0x65, 0x0d, 0x0a, 0x45, 0x53, 0x54, 0x0d, 0x0a, 0x45, 0x53, 0x54, 0x35, 0x45,
|
||||
0x44, 0x54, 0x0d, 0x0a, 0x47, 0x42, 0x0d, 0x0a, 0x47, 0x42, 0x2d, 0x45, 0x69, 0x72, 0x65, 0x0d,
|
||||
0x0a, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x47, 0x4d, 0x54, 0x2b, 0x30, 0x0d, 0x0a, 0x47, 0x4d, 0x54,
|
||||
0x2d, 0x30, 0x0d, 0x0a, 0x47, 0x4d, 0x54, 0x30, 0x0d, 0x0a, 0x47, 0x72, 0x65, 0x65, 0x6e, 0x77,
|
||||
0x69, 0x63, 0x68, 0x0d, 0x0a, 0x48, 0x6f, 0x6e, 0x67, 0x6b, 0x6f, 0x6e, 0x67, 0x0d, 0x0a, 0x48,
|
||||
0x53, 0x54, 0x0d, 0x0a, 0x49, 0x63, 0x65, 0x6c, 0x61, 0x6e, 0x64, 0x0d, 0x0a, 0x49, 0x72, 0x61,
|
||||
0x6e, 0x0d, 0x0a, 0x49, 0x73, 0x72, 0x61, 0x65, 0x6c, 0x0d, 0x0a, 0x4a, 0x61, 0x6d, 0x61, 0x69,
|
||||
0x63, 0x61, 0x0d, 0x0a, 0x4a, 0x61, 0x70, 0x61, 0x6e, 0x0d, 0x0a, 0x4b, 0x77, 0x61, 0x6a, 0x61,
|
||||
0x6c, 0x65, 0x69, 0x6e, 0x0d, 0x0a, 0x4c, 0x69, 0x62, 0x79, 0x61, 0x0d, 0x0a, 0x4d, 0x45, 0x54,
|
||||
0x0d, 0x0a, 0x4d, 0x53, 0x54, 0x0d, 0x0a, 0x4d, 0x53, 0x54, 0x37, 0x4d, 0x44, 0x54, 0x0d, 0x0a,
|
||||
0x4e, 0x61, 0x76, 0x61, 0x6a, 0x6f, 0x0d, 0x0a, 0x4e, 0x5a, 0x0d, 0x0a, 0x4e, 0x5a, 0x2d, 0x43,
|
||||
0x48, 0x41, 0x54, 0x0d, 0x0a, 0x50, 0x6f, 0x6c, 0x61, 0x6e, 0x64, 0x0d, 0x0a, 0x50, 0x6f, 0x72,
|
||||
0x74, 0x75, 0x67, 0x61, 0x6c, 0x0d, 0x0a, 0x50, 0x52, 0x43, 0x0d, 0x0a, 0x50, 0x53, 0x54, 0x38,
|
||||
0x50, 0x44, 0x54, 0x0d, 0x0a, 0x52, 0x4f, 0x43, 0x0d, 0x0a, 0x52, 0x4f, 0x4b, 0x0d, 0x0a, 0x53,
|
||||
0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72, 0x65, 0x0d, 0x0a, 0x54, 0x75, 0x72, 0x6b, 0x65, 0x79,
|
||||
0x0d, 0x0a, 0x55, 0x43, 0x54, 0x0d, 0x0a, 0x55, 0x6e, 0x69, 0x76, 0x65, 0x72, 0x73, 0x61, 0x6c,
|
||||
0x0d, 0x0a, 0x55, 0x54, 0x43, 0x0d, 0x0a, 0x57, 0x2d, 0x53, 0x55, 0x0d, 0x0a, 0x57, 0x45, 0x54,
|
||||
0x0d, 0x0a, 0x5a, 0x75, 0x6c, 0x75, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41,
|
||||
0x62, 0x69, 0x64, 0x6a, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41,
|
||||
0x63, 0x63, 0x72, 0x61, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x64, 0x64,
|
||||
0x69, 0x73, 0x5f, 0x41, 0x62, 0x61, 0x62, 0x61, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61,
|
||||
0x2f, 0x41, 0x6c, 0x67, 0x69, 0x65, 0x72, 0x73, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61,
|
||||
0x2f, 0x41, 0x73, 0x6d, 0x61, 0x72, 0x61, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f,
|
||||
0x41, 0x73, 0x6d, 0x65, 0x72, 0x61, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42,
|
||||
0x61, 0x6d, 0x61, 0x6b, 0x6f, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61,
|
||||
0x6e, 0x67, 0x75, 0x69, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x6e,
|
||||
0x6a, 0x75, 0x6c, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x69, 0x73, 0x73,
|
||||
0x61, 0x75, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6c, 0x61, 0x6e, 0x74,
|
||||
0x79, 0x72, 0x65, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x72, 0x61, 0x7a,
|
||||
0x7a, 0x61, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f,
|
||||
0x42, 0x75, 0x6a, 0x75, 0x6d, 0x62, 0x75, 0x72, 0x61, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63,
|
||||
0x61, 0x2f, 0x43, 0x61, 0x69, 0x72, 0x6f, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f,
|
||||
0x43, 0x61, 0x73, 0x61, 0x62, 0x6c, 0x61, 0x6e, 0x63, 0x61, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69,
|
||||
0x63, 0x61, 0x2f, 0x43, 0x65, 0x75, 0x74, 0x61, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61,
|
||||
0x2f, 0x43, 0x6f, 0x6e, 0x61, 0x6b, 0x72, 0x79, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61,
|
||||
0x2f, 0x44, 0x61, 0x6b, 0x61, 0x72, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44,
|
||||
0x61, 0x72, 0x5f, 0x65, 0x73, 0x5f, 0x53, 0x61, 0x6c, 0x61, 0x61, 0x6d, 0x0d, 0x0a, 0x41, 0x66,
|
||||
0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x6a, 0x69, 0x62, 0x6f, 0x75, 0x74, 0x69, 0x0d, 0x0a, 0x41,
|
||||
0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x6f, 0x75, 0x61, 0x6c, 0x61, 0x0d, 0x0a, 0x41, 0x66,
|
||||
0x72, 0x69, 0x63, 0x61, 0x2f, 0x45, 0x6c, 0x5f, 0x41, 0x61, 0x69, 0x75, 0x6e, 0x0d, 0x0a, 0x41,
|
||||
0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x46, 0x72, 0x65, 0x65, 0x74, 0x6f, 0x77, 0x6e, 0x0d, 0x0a,
|
||||
0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x61, 0x62, 0x6f, 0x72, 0x6f, 0x6e, 0x65, 0x0d,
|
||||
0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x48, 0x61, 0x72, 0x61, 0x72, 0x65, 0x0d, 0x0a,
|
||||
0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a, 0x6f, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x73, 0x62,
|
||||
0x75, 0x72, 0x67, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a, 0x75, 0x62, 0x61,
|
||||
0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x61, 0x6d, 0x70, 0x61, 0x6c, 0x61,
|
||||
0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x68, 0x61, 0x72, 0x74, 0x6f, 0x75,
|
||||
0x6d, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x69, 0x67, 0x61, 0x6c, 0x69,
|
||||
0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x69, 0x6e, 0x73, 0x68, 0x61, 0x73,
|
||||
0x61, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x61, 0x67, 0x6f, 0x73, 0x0d,
|
||||
0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x69, 0x62, 0x72, 0x65, 0x76, 0x69, 0x6c,
|
||||
0x6c, 0x65, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x6d, 0x65, 0x0d,
|
||||
0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x75, 0x61, 0x6e, 0x64, 0x61, 0x0d, 0x0a,
|
||||
0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x75, 0x62, 0x75, 0x6d, 0x62, 0x61, 0x73, 0x68,
|
||||
0x69, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x75, 0x73, 0x61, 0x6b, 0x61,
|
||||
0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x6c, 0x61, 0x62, 0x6f, 0x0d,
|
||||
0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x70, 0x75, 0x74, 0x6f, 0x0d, 0x0a,
|
||||
0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x73, 0x65, 0x72, 0x75, 0x0d, 0x0a, 0x41,
|
||||
0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x62, 0x61, 0x62, 0x61, 0x6e, 0x65, 0x0d, 0x0a, 0x41,
|
||||
0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x67, 0x61, 0x64, 0x69, 0x73, 0x68, 0x75, 0x0d,
|
||||
0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x72, 0x6f, 0x76, 0x69, 0x61,
|
||||
0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x61, 0x69, 0x72, 0x6f, 0x62, 0x69,
|
||||
0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x64, 0x6a, 0x61, 0x6d, 0x65, 0x6e,
|
||||
0x61, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x69, 0x61, 0x6d, 0x65, 0x79,
|
||||
0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x75, 0x61, 0x6b, 0x63, 0x68,
|
||||
0x6f, 0x74, 0x74, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4f, 0x75, 0x61, 0x67,
|
||||
0x61, 0x64, 0x6f, 0x75, 0x67, 0x6f, 0x75, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x2f,
|
||||
0x50, 0x6f, 0x72, 0x74, 0x6f, 0x2d, 0x4e, 0x6f, 0x76, 0x6f, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69,
|
||||
0x63, 0x61, 0x2f, 0x53, 0x61, 0x6f, 0x5f, 0x54, 0x6f, 0x6d, 0x65, 0x0d, 0x0a, 0x41, 0x66, 0x72,
|
||||
0x69, 0x63, 0x61, 0x2f, 0x54, 0x69, 0x6d, 0x62, 0x75, 0x6b, 0x74, 0x75, 0x0d, 0x0a, 0x41, 0x66,
|
||||
0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x72, 0x69, 0x70, 0x6f, 0x6c, 0x69, 0x0d, 0x0a, 0x41, 0x66,
|
||||
0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x75, 0x6e, 0x69, 0x73, 0x0d, 0x0a, 0x41, 0x66, 0x72, 0x69,
|
||||
0x63, 0x61, 0x2f, 0x57, 0x69, 0x6e, 0x64, 0x68, 0x6f, 0x65, 0x6b, 0x0d, 0x0a, 0x41, 0x6d, 0x65,
|
||||
0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x64, 0x61, 0x6b, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69,
|
||||
0x63, 0x61, 0x2f, 0x41, 0x6e, 0x63, 0x68, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x0d, 0x0a, 0x41, 0x6d,
|
||||
0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x6e, 0x67, 0x75, 0x69, 0x6c, 0x6c, 0x61, 0x0d, 0x0a,
|
||||
0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x6e, 0x74, 0x69, 0x67, 0x75, 0x61, 0x0d,
|
||||
0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x61, 0x67, 0x75, 0x61, 0x69,
|
||||
0x6e, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x75, 0x62,
|
||||
0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x73, 0x75, 0x6e, 0x63,
|
||||
0x69, 0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x74, 0x69,
|
||||
0x6b, 0x6f, 0x6b, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41,
|
||||
0x74, 0x6b, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x68,
|
||||
0x69, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x68, 0x69,
|
||||
0x61, 0x5f, 0x42, 0x61, 0x6e, 0x64, 0x65, 0x72, 0x61, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
|
||||
0x69, 0x63, 0x61, 0x2f, 0x42, 0x61, 0x72, 0x62, 0x61, 0x64, 0x6f, 0x73, 0x0d, 0x0a, 0x41, 0x6d,
|
||||
0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x65, 0x6c, 0x65, 0x6d, 0x0d, 0x0a, 0x41, 0x6d, 0x65,
|
||||
0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x65, 0x6c, 0x69, 0x7a, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65,
|
||||
0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6c, 0x61, 0x6e, 0x63, 0x2d, 0x53, 0x61, 0x62, 0x6c, 0x6f,
|
||||
0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6f, 0x61, 0x5f, 0x56,
|
||||
0x69, 0x73, 0x74, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6f,
|
||||
0x67, 0x6f, 0x74, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x6f,
|
||||
0x69, 0x73, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x42, 0x75, 0x65,
|
||||
0x6e, 0x6f, 0x73, 0x5f, 0x41, 0x69, 0x72, 0x65, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69,
|
||||
0x63, 0x61, 0x2f, 0x43, 0x61, 0x6d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x5f, 0x42, 0x61, 0x79,
|
||||
0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x6d, 0x70, 0x6f, 0x5f,
|
||||
0x47, 0x72, 0x61, 0x6e, 0x64, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
|
||||
0x43, 0x61, 0x6e, 0x63, 0x75, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
|
||||
0x43, 0x61, 0x72, 0x61, 0x63, 0x61, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
|
||||
0x2f, 0x43, 0x61, 0x74, 0x61, 0x6d, 0x61, 0x72, 0x63, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
|
||||
0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x79, 0x65, 0x6e, 0x6e, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65,
|
||||
0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x79, 0x6d, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65,
|
||||
0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x68, 0x69, 0x63, 0x61, 0x67, 0x6f, 0x0d, 0x0a, 0x41, 0x6d,
|
||||
0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x68, 0x69, 0x68, 0x75, 0x61, 0x68, 0x75, 0x61, 0x0d,
|
||||
0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x6f, 0x72, 0x61, 0x6c, 0x5f, 0x48,
|
||||
0x61, 0x72, 0x62, 0x6f, 0x75, 0x72, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
|
||||
0x43, 0x6f, 0x72, 0x64, 0x6f, 0x62, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
|
||||
0x2f, 0x43, 0x6f, 0x73, 0x74, 0x61, 0x5f, 0x52, 0x69, 0x63, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65,
|
||||
0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x72, 0x65, 0x73, 0x74, 0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x6d,
|
||||
0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x75, 0x69, 0x61, 0x62, 0x61, 0x0d, 0x0a, 0x41, 0x6d,
|
||||
0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x43, 0x75, 0x72, 0x61, 0x63, 0x61, 0x6f, 0x0d, 0x0a, 0x41,
|
||||
0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x6e, 0x6d, 0x61, 0x72, 0x6b, 0x73, 0x68,
|
||||
0x61, 0x76, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x77,
|
||||
0x73, 0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x77,
|
||||
0x73, 0x6f, 0x6e, 0x5f, 0x43, 0x72, 0x65, 0x65, 0x6b, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69,
|
||||
0x63, 0x61, 0x2f, 0x44, 0x65, 0x6e, 0x76, 0x65, 0x72, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69,
|
||||
0x63, 0x61, 0x2f, 0x44, 0x65, 0x74, 0x72, 0x6f, 0x69, 0x74, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
|
||||
0x69, 0x63, 0x61, 0x2f, 0x44, 0x6f, 0x6d, 0x69, 0x6e, 0x69, 0x63, 0x61, 0x0d, 0x0a, 0x41, 0x6d,
|
||||
0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x45, 0x64, 0x6d, 0x6f, 0x6e, 0x74, 0x6f, 0x6e, 0x0d, 0x0a,
|
||||
0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x45, 0x69, 0x72, 0x75, 0x6e, 0x65, 0x70, 0x65,
|
||||
0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x45, 0x6c, 0x5f, 0x53, 0x61, 0x6c,
|
||||
0x76, 0x61, 0x64, 0x6f, 0x72, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x45,
|
||||
0x6e, 0x73, 0x65, 0x6e, 0x61, 0x64, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
|
||||
0x2f, 0x46, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x65, 0x7a, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
|
||||
0x69, 0x63, 0x61, 0x2f, 0x46, 0x6f, 0x72, 0x74, 0x5f, 0x4e, 0x65, 0x6c, 0x73, 0x6f, 0x6e, 0x0d,
|
||||
0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x46, 0x6f, 0x72, 0x74, 0x5f, 0x57, 0x61,
|
||||
0x79, 0x6e, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x6c, 0x61,
|
||||
0x63, 0x65, 0x5f, 0x42, 0x61, 0x79, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
|
||||
0x47, 0x6f, 0x64, 0x74, 0x68, 0x61, 0x62, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
|
||||
0x2f, 0x47, 0x6f, 0x6f, 0x73, 0x65, 0x5f, 0x42, 0x61, 0x79, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
|
||||
0x69, 0x63, 0x61, 0x2f, 0x47, 0x72, 0x61, 0x6e, 0x64, 0x5f, 0x54, 0x75, 0x72, 0x6b, 0x0d, 0x0a,
|
||||
0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x72, 0x65, 0x6e, 0x61, 0x64, 0x61, 0x0d,
|
||||
0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x75, 0x61, 0x64, 0x65, 0x6c, 0x6f,
|
||||
0x75, 0x70, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x47, 0x75, 0x61,
|
||||
0x74, 0x65, 0x6d, 0x61, 0x6c, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
|
||||
0x47, 0x75, 0x61, 0x79, 0x61, 0x71, 0x75, 0x69, 0x6c, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69,
|
||||
0x63, 0x61, 0x2f, 0x47, 0x75, 0x79, 0x61, 0x6e, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69,
|
||||
0x63, 0x61, 0x2f, 0x48, 0x61, 0x6c, 0x69, 0x66, 0x61, 0x78, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
|
||||
0x69, 0x63, 0x61, 0x2f, 0x48, 0x61, 0x76, 0x61, 0x6e, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
|
||||
0x69, 0x63, 0x61, 0x2f, 0x48, 0x65, 0x72, 0x6d, 0x6f, 0x73, 0x69, 0x6c, 0x6c, 0x6f, 0x0d, 0x0a,
|
||||
0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x70,
|
||||
0x6f, 0x6c, 0x69, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e,
|
||||
0x75, 0x76, 0x69, 0x6b, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x71,
|
||||
0x61, 0x6c, 0x75, 0x69, 0x74, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a,
|
||||
0x61, 0x6d, 0x61, 0x69, 0x63, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
|
||||
0x4a, 0x75, 0x6a, 0x75, 0x79, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4a,
|
||||
0x75, 0x6e, 0x65, 0x61, 0x75, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b,
|
||||
0x6e, 0x6f, 0x78, 0x5f, 0x49, 0x4e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
|
||||
0x4b, 0x72, 0x61, 0x6c, 0x65, 0x6e, 0x64, 0x69, 0x6a, 0x6b, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
|
||||
0x69, 0x63, 0x61, 0x2f, 0x4c, 0x61, 0x5f, 0x50, 0x61, 0x7a, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
|
||||
0x69, 0x63, 0x61, 0x2f, 0x4c, 0x69, 0x6d, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
|
||||
0x61, 0x2f, 0x4c, 0x6f, 0x73, 0x5f, 0x41, 0x6e, 0x67, 0x65, 0x6c, 0x65, 0x73, 0x0d, 0x0a, 0x41,
|
||||
0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x75, 0x69, 0x73, 0x76, 0x69, 0x6c, 0x6c,
|
||||
0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4c, 0x6f, 0x77, 0x65, 0x72,
|
||||
0x5f, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x65, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
|
||||
0x61, 0x2f, 0x4d, 0x61, 0x63, 0x65, 0x69, 0x6f, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
|
||||
0x61, 0x2f, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x75, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69,
|
||||
0x63, 0x61, 0x2f, 0x4d, 0x61, 0x6e, 0x61, 0x75, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69,
|
||||
0x63, 0x61, 0x2f, 0x4d, 0x61, 0x72, 0x69, 0x67, 0x6f, 0x74, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
|
||||
0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x72, 0x74, 0x69, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x0d, 0x0a,
|
||||
0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x74, 0x61, 0x6d, 0x6f, 0x72, 0x6f,
|
||||
0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x7a, 0x61, 0x74,
|
||||
0x6c, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x6e,
|
||||
0x64, 0x6f, 0x7a, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65,
|
||||
0x6e, 0x6f, 0x6d, 0x69, 0x6e, 0x65, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
|
||||
0x2f, 0x4d, 0x65, 0x72, 0x69, 0x64, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
|
||||
0x2f, 0x4d, 0x65, 0x74, 0x6c, 0x61, 0x6b, 0x61, 0x74, 0x6c, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65,
|
||||
0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x5f, 0x43, 0x69, 0x74, 0x79,
|
||||
0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x69, 0x71, 0x75, 0x65, 0x6c,
|
||||
0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x63,
|
||||
0x74, 0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e,
|
||||
0x74, 0x65, 0x72, 0x72, 0x65, 0x79, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
|
||||
0x4d, 0x6f, 0x6e, 0x74, 0x65, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
|
||||
0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x72, 0x65, 0x61, 0x6c, 0x0d, 0x0a, 0x41, 0x6d,
|
||||
0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x73, 0x65, 0x72, 0x72, 0x61, 0x74,
|
||||
0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x61, 0x73, 0x73, 0x61, 0x75,
|
||||
0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x65, 0x77, 0x5f, 0x59, 0x6f,
|
||||
0x72, 0x6b, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x69, 0x70, 0x69,
|
||||
0x67, 0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x6d,
|
||||
0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x72, 0x6f, 0x6e,
|
||||
0x68, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4f, 0x6a, 0x69, 0x6e,
|
||||
0x61, 0x67, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x61, 0x6e,
|
||||
0x61, 0x6d, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x61, 0x6e,
|
||||
0x67, 0x6e, 0x69, 0x72, 0x74, 0x75, 0x6e, 0x67, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
|
||||
0x61, 0x2f, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x61, 0x72, 0x69, 0x62, 0x6f, 0x0d, 0x0a, 0x41, 0x6d,
|
||||
0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x68, 0x6f, 0x65, 0x6e, 0x69, 0x78, 0x0d, 0x0a, 0x41,
|
||||
0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x2d, 0x61, 0x75, 0x2d, 0x50,
|
||||
0x72, 0x69, 0x6e, 0x63, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50,
|
||||
0x6f, 0x72, 0x74, 0x6f, 0x5f, 0x41, 0x63, 0x72, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69,
|
||||
0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x6f, 0x5f, 0x56, 0x65, 0x6c, 0x68, 0x6f, 0x0d, 0x0a,
|
||||
0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x5f, 0x6f, 0x66, 0x5f,
|
||||
0x53, 0x70, 0x61, 0x69, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x50,
|
||||
0x75, 0x65, 0x72, 0x74, 0x6f, 0x5f, 0x52, 0x69, 0x63, 0x6f, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
|
||||
0x69, 0x63, 0x61, 0x2f, 0x50, 0x75, 0x6e, 0x74, 0x61, 0x5f, 0x41, 0x72, 0x65, 0x6e, 0x61, 0x73,
|
||||
0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x61, 0x69, 0x6e, 0x79, 0x5f,
|
||||
0x52, 0x69, 0x76, 0x65, 0x72, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52,
|
||||
0x61, 0x6e, 0x6b, 0x69, 0x6e, 0x5f, 0x49, 0x6e, 0x6c, 0x65, 0x74, 0x0d, 0x0a, 0x41, 0x6d, 0x65,
|
||||
0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x65, 0x63, 0x69, 0x66, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65,
|
||||
0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x65, 0x67, 0x69, 0x6e, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65,
|
||||
0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x65, 0x0d, 0x0a, 0x41,
|
||||
0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x69, 0x6f, 0x5f, 0x42, 0x72, 0x61, 0x6e, 0x63,
|
||||
0x6f, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x52, 0x6f, 0x73, 0x61, 0x72,
|
||||
0x69, 0x6f, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74,
|
||||
0x61, 0x72, 0x65, 0x6d, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61,
|
||||
0x6e, 0x74, 0x61, 0x5f, 0x49, 0x73, 0x61, 0x62, 0x65, 0x6c, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
|
||||
0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x69, 0x61, 0x67, 0x6f, 0x0d, 0x0a, 0x41, 0x6d,
|
||||
0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x74, 0x6f, 0x5f, 0x44, 0x6f, 0x6d, 0x69,
|
||||
0x6e, 0x67, 0x6f, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x61, 0x6f,
|
||||
0x5f, 0x50, 0x61, 0x75, 0x6c, 0x6f, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
|
||||
0x53, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x62, 0x79, 0x73, 0x75, 0x6e, 0x64, 0x0d, 0x0a, 0x41, 0x6d,
|
||||
0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x68, 0x69, 0x70, 0x72, 0x6f, 0x63, 0x6b, 0x0d, 0x0a,
|
||||
0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x69, 0x74, 0x6b, 0x61, 0x0d, 0x0a, 0x41,
|
||||
0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x42, 0x61, 0x72, 0x74, 0x68, 0x65,
|
||||
0x6c, 0x65, 0x6d, 0x79, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74,
|
||||
0x5f, 0x4a, 0x6f, 0x68, 0x6e, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
|
||||
0x53, 0x74, 0x5f, 0x4b, 0x69, 0x74, 0x74, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
|
||||
0x61, 0x2f, 0x53, 0x74, 0x5f, 0x4c, 0x75, 0x63, 0x69, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
|
||||
0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x54, 0x68, 0x6f, 0x6d, 0x61, 0x73, 0x0d, 0x0a, 0x41,
|
||||
0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x74, 0x5f, 0x56, 0x69, 0x6e, 0x63, 0x65, 0x6e,
|
||||
0x74, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x77, 0x69, 0x66, 0x74,
|
||||
0x5f, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
|
||||
0x61, 0x2f, 0x54, 0x65, 0x67, 0x75, 0x63, 0x69, 0x67, 0x61, 0x6c, 0x70, 0x61, 0x0d, 0x0a, 0x41,
|
||||
0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x68, 0x75, 0x6c, 0x65, 0x0d, 0x0a, 0x41, 0x6d,
|
||||
0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x68, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x5f, 0x42, 0x61,
|
||||
0x79, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x69, 0x6a, 0x75, 0x61,
|
||||
0x6e, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x6f, 0x72, 0x6f,
|
||||
0x6e, 0x74, 0x6f, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x54, 0x6f, 0x72,
|
||||
0x74, 0x6f, 0x6c, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x56, 0x61,
|
||||
0x6e, 0x63, 0x6f, 0x75, 0x76, 0x65, 0x72, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
|
||||
0x2f, 0x56, 0x69, 0x72, 0x67, 0x69, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
|
||||
0x2f, 0x57, 0x68, 0x69, 0x74, 0x65, 0x68, 0x6f, 0x72, 0x73, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65,
|
||||
0x72, 0x69, 0x63, 0x61, 0x2f, 0x57, 0x69, 0x6e, 0x6e, 0x69, 0x70, 0x65, 0x67, 0x0d, 0x0a, 0x41,
|
||||
0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x59, 0x61, 0x6b, 0x75, 0x74, 0x61, 0x74, 0x0d, 0x0a,
|
||||
0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x59, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6b, 0x6e,
|
||||
0x69, 0x66, 0x65, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67,
|
||||
0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x42, 0x75, 0x65, 0x6e, 0x6f, 0x73, 0x5f, 0x41, 0x69,
|
||||
0x72, 0x65, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67,
|
||||
0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x43, 0x61, 0x74, 0x61, 0x6d, 0x61, 0x72, 0x63, 0x61,
|
||||
0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74,
|
||||
0x69, 0x6e, 0x61, 0x2f, 0x43, 0x6f, 0x6d, 0x6f, 0x64, 0x52, 0x69, 0x76, 0x61, 0x64, 0x61, 0x76,
|
||||
0x69, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65,
|
||||
0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x43, 0x6f, 0x72, 0x64, 0x6f, 0x62, 0x61, 0x0d, 0x0a, 0x41,
|
||||
0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61,
|
||||
0x2f, 0x4a, 0x75, 0x6a, 0x75, 0x79, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
|
||||
0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x4c, 0x61, 0x5f, 0x52, 0x69, 0x6f,
|
||||
0x6a, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65,
|
||||
0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x4d, 0x65, 0x6e, 0x64, 0x6f, 0x7a, 0x61, 0x0d, 0x0a, 0x41,
|
||||
0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61,
|
||||
0x2f, 0x52, 0x69, 0x6f, 0x5f, 0x47, 0x61, 0x6c, 0x6c, 0x65, 0x67, 0x6f, 0x73, 0x0d, 0x0a, 0x41,
|
||||
0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61,
|
||||
0x2f, 0x53, 0x61, 0x6c, 0x74, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f,
|
||||
0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x5f, 0x4a, 0x75,
|
||||
0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65,
|
||||
0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x53, 0x61, 0x6e, 0x5f, 0x4c, 0x75, 0x69, 0x73, 0x0d, 0x0a,
|
||||
0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e,
|
||||
0x61, 0x2f, 0x54, 0x75, 0x63, 0x75, 0x6d, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69,
|
||||
0x63, 0x61, 0x2f, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x2f, 0x55, 0x73, 0x68,
|
||||
0x75, 0x61, 0x69, 0x61, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e,
|
||||
0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x70, 0x6f, 0x6c,
|
||||
0x69, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69,
|
||||
0x61, 0x6e, 0x61, 0x2f, 0x4b, 0x6e, 0x6f, 0x78, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
|
||||
0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x4d, 0x61, 0x72, 0x65, 0x6e, 0x67,
|
||||
0x6f, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61,
|
||||
0x6e, 0x61, 0x2f, 0x50, 0x65, 0x74, 0x65, 0x72, 0x73, 0x62, 0x75, 0x72, 0x67, 0x0d, 0x0a, 0x41,
|
||||
0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x54,
|
||||
0x65, 0x6c, 0x6c, 0x5f, 0x43, 0x69, 0x74, 0x79, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
|
||||
0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x56, 0x65, 0x76, 0x61, 0x79, 0x0d,
|
||||
0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61,
|
||||
0x2f, 0x56, 0x69, 0x6e, 0x63, 0x65, 0x6e, 0x6e, 0x65, 0x73, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
|
||||
0x69, 0x63, 0x61, 0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2f, 0x57, 0x69, 0x6e, 0x61,
|
||||
0x6d, 0x61, 0x63, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x65, 0x6e,
|
||||
0x74, 0x75, 0x63, 0x6b, 0x79, 0x2f, 0x4c, 0x6f, 0x75, 0x69, 0x73, 0x76, 0x69, 0x6c, 0x6c, 0x65,
|
||||
0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4b, 0x65, 0x6e, 0x74, 0x75, 0x63,
|
||||
0x6b, 0x79, 0x2f, 0x4d, 0x6f, 0x6e, 0x74, 0x69, 0x63, 0x65, 0x6c, 0x6c, 0x6f, 0x0d, 0x0a, 0x41,
|
||||
0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x5f, 0x44, 0x61, 0x6b,
|
||||
0x6f, 0x74, 0x61, 0x2f, 0x42, 0x65, 0x75, 0x6c, 0x61, 0x68, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72,
|
||||
0x69, 0x63, 0x61, 0x2f, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x5f, 0x44, 0x61, 0x6b, 0x6f, 0x74, 0x61,
|
||||
0x2f, 0x43, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x0d, 0x0a, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
|
||||
0x2f, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x5f, 0x44, 0x61, 0x6b, 0x6f, 0x74, 0x61, 0x2f, 0x4e, 0x65,
|
||||
0x77, 0x5f, 0x53, 0x61, 0x6c, 0x65, 0x6d, 0x0d, 0x0a, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74,
|
||||
0x69, 0x63, 0x61, 0x2f, 0x43, 0x61, 0x73, 0x65, 0x79, 0x0d, 0x0a, 0x41, 0x6e, 0x74, 0x61, 0x72,
|
||||
0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x61, 0x76, 0x69, 0x73, 0x0d, 0x0a, 0x41, 0x6e, 0x74,
|
||||
0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x44, 0x75, 0x6d, 0x6f, 0x6e, 0x74, 0x44, 0x55,
|
||||
0x72, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0d, 0x0a, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69,
|
||||
0x63, 0x61, 0x2f, 0x4d, 0x61, 0x63, 0x71, 0x75, 0x61, 0x72, 0x69, 0x65, 0x0d, 0x0a, 0x41, 0x6e,
|
||||
0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x61, 0x77, 0x73, 0x6f, 0x6e, 0x0d,
|
||||
0x0a, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x4d, 0x63, 0x4d, 0x75,
|
||||
0x72, 0x64, 0x6f, 0x0d, 0x0a, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f,
|
||||
0x50, 0x61, 0x6c, 0x6d, 0x65, 0x72, 0x0d, 0x0a, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69,
|
||||
0x63, 0x61, 0x2f, 0x52, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x61, 0x0d, 0x0a, 0x41, 0x6e, 0x74, 0x61,
|
||||
0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x5f, 0x50, 0x6f, 0x6c,
|
||||
0x65, 0x0d, 0x0a, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f, 0x53, 0x79,
|
||||
0x6f, 0x77, 0x61, 0x0d, 0x0a, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63, 0x61, 0x2f,
|
||||
0x54, 0x72, 0x6f, 0x6c, 0x6c, 0x0d, 0x0a, 0x41, 0x6e, 0x74, 0x61, 0x72, 0x63, 0x74, 0x69, 0x63,
|
||||
0x61, 0x2f, 0x56, 0x6f, 0x73, 0x74, 0x6f, 0x6b, 0x0d, 0x0a, 0x41, 0x72, 0x63, 0x74, 0x69, 0x63,
|
||||
0x2f, 0x4c, 0x6f, 0x6e, 0x67, 0x79, 0x65, 0x61, 0x72, 0x62, 0x79, 0x65, 0x6e, 0x0d, 0x0a, 0x41,
|
||||
0x73, 0x69, 0x61, 0x2f, 0x41, 0x64, 0x65, 0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41,
|
||||
0x6c, 0x6d, 0x61, 0x74, 0x79, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x6d, 0x6d, 0x61,
|
||||
0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x6e, 0x61, 0x64, 0x79, 0x72, 0x0d, 0x0a,
|
||||
0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x71, 0x74, 0x61, 0x75, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
|
||||
0x2f, 0x41, 0x71, 0x74, 0x6f, 0x62, 0x65, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x73,
|
||||
0x68, 0x67, 0x61, 0x62, 0x61, 0x74, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x73, 0x68,
|
||||
0x6b, 0x68, 0x61, 0x62, 0x61, 0x64, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x41, 0x74, 0x79,
|
||||
0x72, 0x61, 0x75, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x67, 0x68, 0x64, 0x61,
|
||||
0x64, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x68, 0x72, 0x61, 0x69, 0x6e, 0x0d,
|
||||
0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x61, 0x6b, 0x75, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
|
||||
0x2f, 0x42, 0x61, 0x6e, 0x67, 0x6b, 0x6f, 0x6b, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42,
|
||||
0x61, 0x72, 0x6e, 0x61, 0x75, 0x6c, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x65, 0x69,
|
||||
0x72, 0x75, 0x74, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x69, 0x73, 0x68, 0x6b, 0x65,
|
||||
0x6b, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x42, 0x72, 0x75, 0x6e, 0x65, 0x69, 0x0d, 0x0a,
|
||||
0x41, 0x73, 0x69, 0x61, 0x2f, 0x43, 0x61, 0x6c, 0x63, 0x75, 0x74, 0x74, 0x61, 0x0d, 0x0a, 0x41,
|
||||
0x73, 0x69, 0x61, 0x2f, 0x43, 0x68, 0x69, 0x74, 0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f,
|
||||
0x43, 0x68, 0x6f, 0x69, 0x62, 0x61, 0x6c, 0x73, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
|
||||
0x2f, 0x43, 0x68, 0x6f, 0x6e, 0x67, 0x71, 0x69, 0x6e, 0x67, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
|
||||
0x2f, 0x43, 0x68, 0x75, 0x6e, 0x67, 0x6b, 0x69, 0x6e, 0x67, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
|
||||
0x2f, 0x43, 0x6f, 0x6c, 0x6f, 0x6d, 0x62, 0x6f, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44,
|
||||
0x61, 0x63, 0x63, 0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x61, 0x6d, 0x61, 0x73,
|
||||
0x63, 0x75, 0x73, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x68, 0x61, 0x6b, 0x61, 0x0d,
|
||||
0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x69, 0x6c, 0x69, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
|
||||
0x2f, 0x44, 0x75, 0x62, 0x61, 0x69, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x44, 0x75, 0x73,
|
||||
0x68, 0x61, 0x6e, 0x62, 0x65, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x46, 0x61, 0x6d, 0x61,
|
||||
0x67, 0x75, 0x73, 0x74, 0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x47, 0x61, 0x7a, 0x61,
|
||||
0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x48, 0x61, 0x72, 0x62, 0x69, 0x6e, 0x0d, 0x0a, 0x41,
|
||||
0x73, 0x69, 0x61, 0x2f, 0x48, 0x65, 0x62, 0x72, 0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
|
||||
0x2f, 0x48, 0x6f, 0x6e, 0x67, 0x5f, 0x4b, 0x6f, 0x6e, 0x67, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
|
||||
0x2f, 0x48, 0x6f, 0x76, 0x64, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x48, 0x6f, 0x5f, 0x43,
|
||||
0x68, 0x69, 0x5f, 0x4d, 0x69, 0x6e, 0x68, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x49, 0x72,
|
||||
0x6b, 0x75, 0x74, 0x73, 0x6b, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x49, 0x73, 0x74, 0x61,
|
||||
0x6e, 0x62, 0x75, 0x6c, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4a, 0x61, 0x6b, 0x61, 0x72,
|
||||
0x74, 0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4a, 0x61, 0x79, 0x61, 0x70, 0x75, 0x72,
|
||||
0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4a, 0x65, 0x72, 0x75, 0x73, 0x61, 0x6c, 0x65,
|
||||
0x6d, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, 0x62, 0x75, 0x6c, 0x0d, 0x0a, 0x41,
|
||||
0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, 0x6d, 0x63, 0x68, 0x61, 0x74, 0x6b, 0x61, 0x0d, 0x0a, 0x41,
|
||||
0x73, 0x69, 0x61, 0x2f, 0x4b, 0x61, 0x72, 0x61, 0x63, 0x68, 0x69, 0x0d, 0x0a, 0x41, 0x73, 0x69,
|
||||
0x61, 0x2f, 0x4b, 0x61, 0x73, 0x68, 0x67, 0x61, 0x72, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f,
|
||||
0x4b, 0x61, 0x74, 0x68, 0x6d, 0x61, 0x6e, 0x64, 0x75, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f,
|
||||
0x4b, 0x61, 0x74, 0x6d, 0x61, 0x6e, 0x64, 0x75, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b,
|
||||
0x68, 0x61, 0x6e, 0x64, 0x79, 0x67, 0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x6f,
|
||||
0x6c, 0x6b, 0x61, 0x74, 0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x72, 0x61, 0x73,
|
||||
0x6e, 0x6f, 0x79, 0x61, 0x72, 0x73, 0x6b, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b, 0x75,
|
||||
0x61, 0x6c, 0x61, 0x5f, 0x4c, 0x75, 0x6d, 0x70, 0x75, 0x72, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
|
||||
0x2f, 0x4b, 0x75, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4b,
|
||||
0x75, 0x77, 0x61, 0x69, 0x74, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x61, 0x63, 0x61,
|
||||
0x6f, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x61, 0x63, 0x61, 0x75, 0x0d, 0x0a, 0x41,
|
||||
0x73, 0x69, 0x61, 0x2f, 0x4d, 0x61, 0x67, 0x61, 0x64, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69,
|
||||
0x61, 0x2f, 0x4d, 0x61, 0x6b, 0x61, 0x73, 0x73, 0x61, 0x72, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
|
||||
0x2f, 0x4d, 0x61, 0x6e, 0x69, 0x6c, 0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4d, 0x75,
|
||||
0x73, 0x63, 0x61, 0x74, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4e, 0x69, 0x63, 0x6f, 0x73,
|
||||
0x69, 0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4e, 0x6f, 0x76, 0x6f, 0x6b, 0x75, 0x7a,
|
||||
0x6e, 0x65, 0x74, 0x73, 0x6b, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4e, 0x6f, 0x76, 0x6f,
|
||||
0x73, 0x69, 0x62, 0x69, 0x72, 0x73, 0x6b, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4f, 0x6d,
|
||||
0x73, 0x6b, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x4f, 0x72, 0x61, 0x6c, 0x0d, 0x0a, 0x41,
|
||||
0x73, 0x69, 0x61, 0x2f, 0x50, 0x68, 0x6e, 0x6f, 0x6d, 0x5f, 0x50, 0x65, 0x6e, 0x68, 0x0d, 0x0a,
|
||||
0x41, 0x73, 0x69, 0x61, 0x2f, 0x50, 0x6f, 0x6e, 0x74, 0x69, 0x61, 0x6e, 0x61, 0x6b, 0x0d, 0x0a,
|
||||
0x41, 0x73, 0x69, 0x61, 0x2f, 0x50, 0x79, 0x6f, 0x6e, 0x67, 0x79, 0x61, 0x6e, 0x67, 0x0d, 0x0a,
|
||||
0x41, 0x73, 0x69, 0x61, 0x2f, 0x51, 0x61, 0x74, 0x61, 0x72, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
|
||||
0x2f, 0x51, 0x79, 0x7a, 0x79, 0x6c, 0x6f, 0x72, 0x64, 0x61, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
|
||||
0x2f, 0x52, 0x61, 0x6e, 0x67, 0x6f, 0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x52,
|
||||
0x69, 0x79, 0x61, 0x64, 0x68, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x61, 0x69, 0x67,
|
||||
0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x61, 0x6b, 0x68, 0x61, 0x6c, 0x69,
|
||||
0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x61, 0x6d, 0x61, 0x72, 0x6b, 0x61, 0x6e,
|
||||
0x64, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x53, 0x65, 0x6f, 0x75, 0x6c, 0x0d, 0x0a, 0x41,
|
||||
0x73, 0x69, 0x61, 0x2f, 0x53, 0x68, 0x61, 0x6e, 0x67, 0x68, 0x61, 0x69, 0x0d, 0x0a, 0x41, 0x73,
|
||||
0x69, 0x61, 0x2f, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72, 0x65, 0x0d, 0x0a, 0x41, 0x73,
|
||||
0x69, 0x61, 0x2f, 0x53, 0x72, 0x65, 0x64, 0x6e, 0x65, 0x6b, 0x6f, 0x6c, 0x79, 0x6d, 0x73, 0x6b,
|
||||
0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x61, 0x69, 0x70, 0x65, 0x69, 0x0d, 0x0a, 0x41,
|
||||
0x73, 0x69, 0x61, 0x2f, 0x54, 0x61, 0x73, 0x68, 0x6b, 0x65, 0x6e, 0x74, 0x0d, 0x0a, 0x41, 0x73,
|
||||
0x69, 0x61, 0x2f, 0x54, 0x62, 0x69, 0x6c, 0x69, 0x73, 0x69, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61,
|
||||
0x2f, 0x54, 0x65, 0x68, 0x72, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x65,
|
||||
0x6c, 0x5f, 0x41, 0x76, 0x69, 0x76, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x68, 0x69,
|
||||
0x6d, 0x62, 0x75, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x68, 0x69, 0x6d, 0x70, 0x68,
|
||||
0x75, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x54, 0x6f, 0x6b, 0x79, 0x6f, 0x0d, 0x0a, 0x41,
|
||||
0x73, 0x69, 0x61, 0x2f, 0x54, 0x6f, 0x6d, 0x73, 0x6b, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f,
|
||||
0x55, 0x6a, 0x75, 0x6e, 0x67, 0x5f, 0x50, 0x61, 0x6e, 0x64, 0x61, 0x6e, 0x67, 0x0d, 0x0a, 0x41,
|
||||
0x73, 0x69, 0x61, 0x2f, 0x55, 0x6c, 0x61, 0x61, 0x6e, 0x62, 0x61, 0x61, 0x74, 0x61, 0x72, 0x0d,
|
||||
0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x6c, 0x61, 0x6e, 0x5f, 0x42, 0x61, 0x74, 0x6f, 0x72,
|
||||
0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f, 0x55, 0x72, 0x75, 0x6d, 0x71, 0x69, 0x0d, 0x0a, 0x41,
|
||||
0x73, 0x69, 0x61, 0x2f, 0x55, 0x73, 0x74, 0x2d, 0x4e, 0x65, 0x72, 0x61, 0x0d, 0x0a, 0x41, 0x73,
|
||||
0x69, 0x61, 0x2f, 0x56, 0x69, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6e, 0x65, 0x0d, 0x0a, 0x41, 0x73,
|
||||
0x69, 0x61, 0x2f, 0x56, 0x6c, 0x61, 0x64, 0x69, 0x76, 0x6f, 0x73, 0x74, 0x6f, 0x6b, 0x0d, 0x0a,
|
||||
0x41, 0x73, 0x69, 0x61, 0x2f, 0x59, 0x61, 0x6b, 0x75, 0x74, 0x73, 0x6b, 0x0d, 0x0a, 0x41, 0x73,
|
||||
0x69, 0x61, 0x2f, 0x59, 0x61, 0x6e, 0x67, 0x6f, 0x6e, 0x0d, 0x0a, 0x41, 0x73, 0x69, 0x61, 0x2f,
|
||||
0x59, 0x65, 0x6b, 0x61, 0x74, 0x65, 0x72, 0x69, 0x6e, 0x62, 0x75, 0x72, 0x67, 0x0d, 0x0a, 0x41,
|
||||
0x73, 0x69, 0x61, 0x2f, 0x59, 0x65, 0x72, 0x65, 0x76, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x74, 0x6c,
|
||||
0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x41, 0x7a, 0x6f, 0x72, 0x65, 0x73, 0x0d, 0x0a, 0x41, 0x74,
|
||||
0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x42, 0x65, 0x72, 0x6d, 0x75, 0x64, 0x61, 0x0d, 0x0a,
|
||||
0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x43, 0x61, 0x6e, 0x61, 0x72, 0x79, 0x0d,
|
||||
0x0a, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x43, 0x61, 0x70, 0x65, 0x5f, 0x56,
|
||||
0x65, 0x72, 0x64, 0x65, 0x0d, 0x0a, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x46,
|
||||
0x61, 0x65, 0x72, 0x6f, 0x65, 0x0d, 0x0a, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f,
|
||||
0x46, 0x61, 0x72, 0x6f, 0x65, 0x0d, 0x0a, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f,
|
||||
0x4a, 0x61, 0x6e, 0x5f, 0x4d, 0x61, 0x79, 0x65, 0x6e, 0x0d, 0x0a, 0x41, 0x74, 0x6c, 0x61, 0x6e,
|
||||
0x74, 0x69, 0x63, 0x2f, 0x4d, 0x61, 0x64, 0x65, 0x69, 0x72, 0x61, 0x0d, 0x0a, 0x41, 0x74, 0x6c,
|
||||
0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x52, 0x65, 0x79, 0x6b, 0x6a, 0x61, 0x76, 0x69, 0x6b, 0x0d,
|
||||
0x0a, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69, 0x63, 0x2f, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x5f,
|
||||
0x47, 0x65, 0x6f, 0x72, 0x67, 0x69, 0x61, 0x0d, 0x0a, 0x41, 0x74, 0x6c, 0x61, 0x6e, 0x74, 0x69,
|
||||
0x63, 0x2f, 0x53, 0x74, 0x61, 0x6e, 0x6c, 0x65, 0x79, 0x0d, 0x0a, 0x41, 0x74, 0x6c, 0x61, 0x6e,
|
||||
0x74, 0x69, 0x63, 0x2f, 0x53, 0x74, 0x5f, 0x48, 0x65, 0x6c, 0x65, 0x6e, 0x61, 0x0d, 0x0a, 0x41,
|
||||
0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x41, 0x43, 0x54, 0x0d, 0x0a, 0x41, 0x75,
|
||||
0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x41, 0x64, 0x65, 0x6c, 0x61, 0x69, 0x64, 0x65,
|
||||
0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x42, 0x72, 0x69, 0x73,
|
||||
0x62, 0x61, 0x6e, 0x65, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f,
|
||||
0x42, 0x72, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x48, 0x69, 0x6c, 0x6c, 0x0d, 0x0a, 0x41, 0x75, 0x73,
|
||||
0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x43, 0x61, 0x6e, 0x62, 0x65, 0x72, 0x72, 0x61, 0x0d,
|
||||
0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x43, 0x75, 0x72, 0x72, 0x69,
|
||||
0x65, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x44, 0x61, 0x72,
|
||||
0x77, 0x69, 0x6e, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x45,
|
||||
0x75, 0x63, 0x6c, 0x61, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f,
|
||||
0x48, 0x6f, 0x62, 0x61, 0x72, 0x74, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69,
|
||||
0x61, 0x2f, 0x4c, 0x48, 0x49, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61,
|
||||
0x2f, 0x4c, 0x69, 0x6e, 0x64, 0x65, 0x6d, 0x61, 0x6e, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72,
|
||||
0x61, 0x6c, 0x69, 0x61, 0x2f, 0x4c, 0x6f, 0x72, 0x64, 0x5f, 0x48, 0x6f, 0x77, 0x65, 0x0d, 0x0a,
|
||||
0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x4d, 0x65, 0x6c, 0x62, 0x6f, 0x75,
|
||||
0x72, 0x6e, 0x65, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x4e,
|
||||
0x6f, 0x72, 0x74, 0x68, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f,
|
||||
0x4e, 0x53, 0x57, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x50,
|
||||
0x65, 0x72, 0x74, 0x68, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f,
|
||||
0x51, 0x75, 0x65, 0x65, 0x6e, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74,
|
||||
0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x0d, 0x0a, 0x41, 0x75, 0x73,
|
||||
0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x53, 0x79, 0x64, 0x6e, 0x65, 0x79, 0x0d, 0x0a, 0x41,
|
||||
0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x54, 0x61, 0x73, 0x6d, 0x61, 0x6e, 0x69,
|
||||
0x61, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x2f, 0x56, 0x69, 0x63,
|
||||
0x74, 0x6f, 0x72, 0x69, 0x61, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61,
|
||||
0x2f, 0x57, 0x65, 0x73, 0x74, 0x0d, 0x0a, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61,
|
||||
0x2f, 0x59, 0x61, 0x6e, 0x63, 0x6f, 0x77, 0x69, 0x6e, 0x6e, 0x61, 0x0d, 0x0a, 0x42, 0x72, 0x61,
|
||||
0x7a, 0x69, 0x6c, 0x2f, 0x41, 0x63, 0x72, 0x65, 0x0d, 0x0a, 0x42, 0x72, 0x61, 0x7a, 0x69, 0x6c,
|
||||
0x2f, 0x44, 0x65, 0x4e, 0x6f, 0x72, 0x6f, 0x6e, 0x68, 0x61, 0x0d, 0x0a, 0x42, 0x72, 0x61, 0x7a,
|
||||
0x69, 0x6c, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x0d, 0x0a, 0x42, 0x72, 0x61, 0x7a, 0x69, 0x6c, 0x2f,
|
||||
0x57, 0x65, 0x73, 0x74, 0x0d, 0x0a, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f, 0x41, 0x74, 0x6c,
|
||||
0x61, 0x6e, 0x74, 0x69, 0x63, 0x0d, 0x0a, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f, 0x43, 0x65,
|
||||
0x6e, 0x74, 0x72, 0x61, 0x6c, 0x0d, 0x0a, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f, 0x45, 0x61,
|
||||
0x73, 0x74, 0x2d, 0x53, 0x61, 0x73, 0x6b, 0x61, 0x74, 0x63, 0x68, 0x65, 0x77, 0x61, 0x6e, 0x0d,
|
||||
0x0a, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x6e, 0x0d,
|
||||
0x0a, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e,
|
||||
0x0d, 0x0a, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f, 0x4e, 0x65, 0x77, 0x66, 0x6f, 0x75, 0x6e,
|
||||
0x64, 0x6c, 0x61, 0x6e, 0x64, 0x0d, 0x0a, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f, 0x50, 0x61,
|
||||
0x63, 0x69, 0x66, 0x69, 0x63, 0x0d, 0x0a, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x2f, 0x53, 0x61,
|
||||
0x73, 0x6b, 0x61, 0x74, 0x63, 0x68, 0x65, 0x77, 0x61, 0x6e, 0x0d, 0x0a, 0x43, 0x61, 0x6e, 0x61,
|
||||
0x64, 0x61, 0x2f, 0x59, 0x75, 0x6b, 0x6f, 0x6e, 0x0d, 0x0a, 0x43, 0x68, 0x69, 0x6c, 0x65, 0x2f,
|
||||
0x43, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x0d, 0x0a, 0x43, 0x68, 0x69,
|
||||
0x6c, 0x65, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x0d,
|
||||
0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d,
|
||||
0x54, 0x2b, 0x30, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x31, 0x0d, 0x0a,
|
||||
0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x31, 0x30, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f,
|
||||
0x47, 0x4d, 0x54, 0x2b, 0x31, 0x31, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b,
|
||||
0x31, 0x32, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x32, 0x0d, 0x0a, 0x45,
|
||||
0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x33, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d,
|
||||
0x54, 0x2b, 0x34, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x35, 0x0d, 0x0a,
|
||||
0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x36, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47,
|
||||
0x4d, 0x54, 0x2b, 0x37, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x38, 0x0d,
|
||||
0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2b, 0x39, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f,
|
||||
0x47, 0x4d, 0x54, 0x2d, 0x30, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31,
|
||||
0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x30, 0x0d, 0x0a, 0x45, 0x74,
|
||||
0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x31, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d,
|
||||
0x54, 0x2d, 0x31, 0x32, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x33,
|
||||
0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x31, 0x34, 0x0d, 0x0a, 0x45, 0x74,
|
||||
0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x32, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54,
|
||||
0x2d, 0x33, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x34, 0x0d, 0x0a, 0x45,
|
||||
0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x35, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d,
|
||||
0x54, 0x2d, 0x36, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x37, 0x0d, 0x0a,
|
||||
0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x2d, 0x38, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47,
|
||||
0x4d, 0x54, 0x2d, 0x39, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x47, 0x4d, 0x54, 0x30, 0x0d, 0x0a,
|
||||
0x45, 0x74, 0x63, 0x2f, 0x47, 0x72, 0x65, 0x65, 0x6e, 0x77, 0x69, 0x63, 0x68, 0x0d, 0x0a, 0x45,
|
||||
0x74, 0x63, 0x2f, 0x55, 0x43, 0x54, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x55, 0x6e, 0x69, 0x76,
|
||||
0x65, 0x72, 0x73, 0x61, 0x6c, 0x0d, 0x0a, 0x45, 0x74, 0x63, 0x2f, 0x55, 0x54, 0x43, 0x0d, 0x0a,
|
||||
0x45, 0x74, 0x63, 0x2f, 0x5a, 0x75, 0x6c, 0x75, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65,
|
||||
0x2f, 0x41, 0x6d, 0x73, 0x74, 0x65, 0x72, 0x64, 0x61, 0x6d, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f,
|
||||
0x70, 0x65, 0x2f, 0x41, 0x6e, 0x64, 0x6f, 0x72, 0x72, 0x61, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f,
|
||||
0x70, 0x65, 0x2f, 0x41, 0x73, 0x74, 0x72, 0x61, 0x6b, 0x68, 0x61, 0x6e, 0x0d, 0x0a, 0x45, 0x75,
|
||||
0x72, 0x6f, 0x70, 0x65, 0x2f, 0x41, 0x74, 0x68, 0x65, 0x6e, 0x73, 0x0d, 0x0a, 0x45, 0x75, 0x72,
|
||||
0x6f, 0x70, 0x65, 0x2f, 0x42, 0x65, 0x6c, 0x66, 0x61, 0x73, 0x74, 0x0d, 0x0a, 0x45, 0x75, 0x72,
|
||||
0x6f, 0x70, 0x65, 0x2f, 0x42, 0x65, 0x6c, 0x67, 0x72, 0x61, 0x64, 0x65, 0x0d, 0x0a, 0x45, 0x75,
|
||||
0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x65, 0x72, 0x6c, 0x69, 0x6e, 0x0d, 0x0a, 0x45, 0x75, 0x72,
|
||||
0x6f, 0x70, 0x65, 0x2f, 0x42, 0x72, 0x61, 0x74, 0x69, 0x73, 0x6c, 0x61, 0x76, 0x61, 0x0d, 0x0a,
|
||||
0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x72, 0x75, 0x73, 0x73, 0x65, 0x6c, 0x73, 0x0d,
|
||||
0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x75, 0x63, 0x68, 0x61, 0x72, 0x65, 0x73,
|
||||
0x74, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x75, 0x64, 0x61, 0x70, 0x65,
|
||||
0x73, 0x74, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x42, 0x75, 0x73, 0x69, 0x6e,
|
||||
0x67, 0x65, 0x6e, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x43, 0x68, 0x69, 0x73,
|
||||
0x69, 0x6e, 0x61, 0x75, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x43, 0x6f, 0x70,
|
||||
0x65, 0x6e, 0x68, 0x61, 0x67, 0x65, 0x6e, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f,
|
||||
0x44, 0x75, 0x62, 0x6c, 0x69, 0x6e, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x47,
|
||||
0x69, 0x62, 0x72, 0x61, 0x6c, 0x74, 0x61, 0x72, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65,
|
||||
0x2f, 0x47, 0x75, 0x65, 0x72, 0x6e, 0x73, 0x65, 0x79, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70,
|
||||
0x65, 0x2f, 0x48, 0x65, 0x6c, 0x73, 0x69, 0x6e, 0x6b, 0x69, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f,
|
||||
0x70, 0x65, 0x2f, 0x49, 0x73, 0x6c, 0x65, 0x5f, 0x6f, 0x66, 0x5f, 0x4d, 0x61, 0x6e, 0x0d, 0x0a,
|
||||
0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x49, 0x73, 0x74, 0x61, 0x6e, 0x62, 0x75, 0x6c, 0x0d,
|
||||
0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4a, 0x65, 0x72, 0x73, 0x65, 0x79, 0x0d, 0x0a,
|
||||
0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4b, 0x61, 0x6c, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x72,
|
||||
0x61, 0x64, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4b, 0x69, 0x65, 0x76, 0x0d,
|
||||
0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4b, 0x69, 0x72, 0x6f, 0x76, 0x0d, 0x0a, 0x45,
|
||||
0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x69, 0x73, 0x62, 0x6f, 0x6e, 0x0d, 0x0a, 0x45, 0x75,
|
||||
0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x6a, 0x75, 0x62, 0x6c, 0x6a, 0x61, 0x6e, 0x61, 0x0d, 0x0a,
|
||||
0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x6f, 0x6e, 0x64, 0x6f, 0x6e, 0x0d, 0x0a, 0x45,
|
||||
0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4c, 0x75, 0x78, 0x65, 0x6d, 0x62, 0x6f, 0x75, 0x72, 0x67,
|
||||
0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x61, 0x64, 0x72, 0x69, 0x64, 0x0d,
|
||||
0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x61, 0x6c, 0x74, 0x61, 0x0d, 0x0a, 0x45,
|
||||
0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x61, 0x72, 0x69, 0x65, 0x68, 0x61, 0x6d, 0x6e, 0x0d,
|
||||
0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x69, 0x6e, 0x73, 0x6b, 0x0d, 0x0a, 0x45,
|
||||
0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x6f, 0x6e, 0x61, 0x63, 0x6f, 0x0d, 0x0a, 0x45, 0x75,
|
||||
0x72, 0x6f, 0x70, 0x65, 0x2f, 0x4d, 0x6f, 0x73, 0x63, 0x6f, 0x77, 0x0d, 0x0a, 0x45, 0x75, 0x72,
|
||||
0x6f, 0x70, 0x65, 0x2f, 0x4e, 0x69, 0x63, 0x6f, 0x73, 0x69, 0x61, 0x0d, 0x0a, 0x45, 0x75, 0x72,
|
||||
0x6f, 0x70, 0x65, 0x2f, 0x4f, 0x73, 0x6c, 0x6f, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65,
|
||||
0x2f, 0x50, 0x61, 0x72, 0x69, 0x73, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x50,
|
||||
0x6f, 0x64, 0x67, 0x6f, 0x72, 0x69, 0x63, 0x61, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65,
|
||||
0x2f, 0x50, 0x72, 0x61, 0x67, 0x75, 0x65, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f,
|
||||
0x52, 0x69, 0x67, 0x61, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x52, 0x6f, 0x6d,
|
||||
0x65, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x61, 0x6d, 0x61, 0x72, 0x61,
|
||||
0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x61, 0x6e, 0x5f, 0x4d, 0x61, 0x72,
|
||||
0x69, 0x6e, 0x6f, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x61, 0x72, 0x61,
|
||||
0x6a, 0x65, 0x76, 0x6f, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x61, 0x72,
|
||||
0x61, 0x74, 0x6f, 0x76, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x69, 0x6d,
|
||||
0x66, 0x65, 0x72, 0x6f, 0x70, 0x6f, 0x6c, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f,
|
||||
0x53, 0x6b, 0x6f, 0x70, 0x6a, 0x65, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53,
|
||||
0x6f, 0x66, 0x69, 0x61, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x53, 0x74, 0x6f,
|
||||
0x63, 0x6b, 0x68, 0x6f, 0x6c, 0x6d, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x54,
|
||||
0x61, 0x6c, 0x6c, 0x69, 0x6e, 0x6e, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x54,
|
||||
0x69, 0x72, 0x61, 0x6e, 0x65, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x54, 0x69,
|
||||
0x72, 0x61, 0x73, 0x70, 0x6f, 0x6c, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x55,
|
||||
0x6c, 0x79, 0x61, 0x6e, 0x6f, 0x76, 0x73, 0x6b, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65,
|
||||
0x2f, 0x55, 0x7a, 0x68, 0x67, 0x6f, 0x72, 0x6f, 0x64, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70,
|
||||
0x65, 0x2f, 0x56, 0x61, 0x64, 0x75, 0x7a, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f,
|
||||
0x56, 0x61, 0x74, 0x69, 0x63, 0x61, 0x6e, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f,
|
||||
0x56, 0x69, 0x65, 0x6e, 0x6e, 0x61, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56,
|
||||
0x69, 0x6c, 0x6e, 0x69, 0x75, 0x73, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x56,
|
||||
0x6f, 0x6c, 0x67, 0x6f, 0x67, 0x72, 0x61, 0x64, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65,
|
||||
0x2f, 0x57, 0x61, 0x72, 0x73, 0x61, 0x77, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f,
|
||||
0x5a, 0x61, 0x67, 0x72, 0x65, 0x62, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x2f, 0x5a,
|
||||
0x61, 0x70, 0x6f, 0x72, 0x6f, 0x7a, 0x68, 0x79, 0x65, 0x0d, 0x0a, 0x45, 0x75, 0x72, 0x6f, 0x70,
|
||||
0x65, 0x2f, 0x5a, 0x75, 0x72, 0x69, 0x63, 0x68, 0x0d, 0x0a, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e,
|
||||
0x2f, 0x41, 0x6e, 0x74, 0x61, 0x6e, 0x61, 0x6e, 0x61, 0x72, 0x69, 0x76, 0x6f, 0x0d, 0x0a, 0x49,
|
||||
0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x43, 0x68, 0x61, 0x67, 0x6f, 0x73, 0x0d, 0x0a, 0x49, 0x6e,
|
||||
0x64, 0x69, 0x61, 0x6e, 0x2f, 0x43, 0x68, 0x72, 0x69, 0x73, 0x74, 0x6d, 0x61, 0x73, 0x0d, 0x0a,
|
||||
0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x43, 0x6f, 0x63, 0x6f, 0x73, 0x0d, 0x0a, 0x49, 0x6e,
|
||||
0x64, 0x69, 0x61, 0x6e, 0x2f, 0x43, 0x6f, 0x6d, 0x6f, 0x72, 0x6f, 0x0d, 0x0a, 0x49, 0x6e, 0x64,
|
||||
0x69, 0x61, 0x6e, 0x2f, 0x4b, 0x65, 0x72, 0x67, 0x75, 0x65, 0x6c, 0x65, 0x6e, 0x0d, 0x0a, 0x49,
|
||||
0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4d, 0x61, 0x68, 0x65, 0x0d, 0x0a, 0x49, 0x6e, 0x64, 0x69,
|
||||
0x61, 0x6e, 0x2f, 0x4d, 0x61, 0x6c, 0x64, 0x69, 0x76, 0x65, 0x73, 0x0d, 0x0a, 0x49, 0x6e, 0x64,
|
||||
0x69, 0x61, 0x6e, 0x2f, 0x4d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x69, 0x75, 0x73, 0x0d, 0x0a, 0x49,
|
||||
0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x4d, 0x61, 0x79, 0x6f, 0x74, 0x74, 0x65, 0x0d, 0x0a, 0x49,
|
||||
0x6e, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x52, 0x65, 0x75, 0x6e, 0x69, 0x6f, 0x6e, 0x0d, 0x0a, 0x4d,
|
||||
0x65, 0x78, 0x69, 0x63, 0x6f, 0x2f, 0x42, 0x61, 0x6a, 0x61, 0x4e, 0x6f, 0x72, 0x74, 0x65, 0x0d,
|
||||
0x0a, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x2f, 0x42, 0x61, 0x6a, 0x61, 0x53, 0x75, 0x72, 0x0d,
|
||||
0x0a, 0x4d, 0x65, 0x78, 0x69, 0x63, 0x6f, 0x2f, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x0d,
|
||||
0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x41, 0x70, 0x69, 0x61, 0x0d, 0x0a, 0x50,
|
||||
0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x41, 0x75, 0x63, 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x0d,
|
||||
0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x42, 0x6f, 0x75, 0x67, 0x61, 0x69, 0x6e,
|
||||
0x76, 0x69, 0x6c, 0x6c, 0x65, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x43,
|
||||
0x68, 0x61, 0x74, 0x68, 0x61, 0x6d, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f,
|
||||
0x43, 0x68, 0x75, 0x75, 0x6b, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x45,
|
||||
0x61, 0x73, 0x74, 0x65, 0x72, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x45,
|
||||
0x66, 0x61, 0x74, 0x65, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x45, 0x6e,
|
||||
0x64, 0x65, 0x72, 0x62, 0x75, 0x72, 0x79, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63,
|
||||
0x2f, 0x46, 0x61, 0x6b, 0x61, 0x6f, 0x66, 0x6f, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69,
|
||||
0x63, 0x2f, 0x46, 0x69, 0x6a, 0x69, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f,
|
||||
0x46, 0x75, 0x6e, 0x61, 0x66, 0x75, 0x74, 0x69, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69,
|
||||
0x63, 0x2f, 0x47, 0x61, 0x6c, 0x61, 0x70, 0x61, 0x67, 0x6f, 0x73, 0x0d, 0x0a, 0x50, 0x61, 0x63,
|
||||
0x69, 0x66, 0x69, 0x63, 0x2f, 0x47, 0x61, 0x6d, 0x62, 0x69, 0x65, 0x72, 0x0d, 0x0a, 0x50, 0x61,
|
||||
0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x47, 0x75, 0x61, 0x64, 0x61, 0x6c, 0x63, 0x61, 0x6e, 0x61,
|
||||
0x6c, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x47, 0x75, 0x61, 0x6d, 0x0d,
|
||||
0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x48, 0x6f, 0x6e, 0x6f, 0x6c, 0x75, 0x6c,
|
||||
0x75, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4a, 0x6f, 0x68, 0x6e, 0x73,
|
||||
0x74, 0x6f, 0x6e, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4b, 0x69, 0x72,
|
||||
0x69, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x69, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63,
|
||||
0x2f, 0x4b, 0x6f, 0x73, 0x72, 0x61, 0x65, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63,
|
||||
0x2f, 0x4b, 0x77, 0x61, 0x6a, 0x61, 0x6c, 0x65, 0x69, 0x6e, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69,
|
||||
0x66, 0x69, 0x63, 0x2f, 0x4d, 0x61, 0x6a, 0x75, 0x72, 0x6f, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69,
|
||||
0x66, 0x69, 0x63, 0x2f, 0x4d, 0x61, 0x72, 0x71, 0x75, 0x65, 0x73, 0x61, 0x73, 0x0d, 0x0a, 0x50,
|
||||
0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4d, 0x69, 0x64, 0x77, 0x61, 0x79, 0x0d, 0x0a, 0x50,
|
||||
0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4e, 0x61, 0x75, 0x72, 0x75, 0x0d, 0x0a, 0x50, 0x61,
|
||||
0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x4e, 0x69, 0x75, 0x65, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69,
|
||||
0x66, 0x69, 0x63, 0x2f, 0x4e, 0x6f, 0x72, 0x66, 0x6f, 0x6c, 0x6b, 0x0d, 0x0a, 0x50, 0x61, 0x63,
|
||||
0x69, 0x66, 0x69, 0x63, 0x2f, 0x4e, 0x6f, 0x75, 0x6d, 0x65, 0x61, 0x0d, 0x0a, 0x50, 0x61, 0x63,
|
||||
0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x61, 0x67, 0x6f, 0x5f, 0x50, 0x61, 0x67, 0x6f, 0x0d, 0x0a,
|
||||
0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x61, 0x6c, 0x61, 0x75, 0x0d, 0x0a, 0x50,
|
||||
0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x69, 0x74, 0x63, 0x61, 0x69, 0x72, 0x6e, 0x0d,
|
||||
0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x6f, 0x68, 0x6e, 0x70, 0x65, 0x69,
|
||||
0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x6f, 0x6e, 0x61, 0x70, 0x65,
|
||||
0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f, 0x50, 0x6f, 0x72, 0x74, 0x5f, 0x4d,
|
||||
0x6f, 0x72, 0x65, 0x73, 0x62, 0x79, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2f,
|
||||
0x52, 0x61, 0x72, 0x6f, 0x74, 0x6f, 0x6e, 0x67, 0x61, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66,
|
||||
0x69, 0x63, 0x2f, 0x53, 0x61, 0x69, 0x70, 0x61, 0x6e, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66,
|
||||
0x69, 0x63, 0x2f, 0x53, 0x61, 0x6d, 0x6f, 0x61, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69,
|
||||
0x63, 0x2f, 0x54, 0x61, 0x68, 0x69, 0x74, 0x69, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69,
|
||||
0x63, 0x2f, 0x54, 0x61, 0x72, 0x61, 0x77, 0x61, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69,
|
||||
0x63, 0x2f, 0x54, 0x6f, 0x6e, 0x67, 0x61, 0x74, 0x61, 0x70, 0x75, 0x0d, 0x0a, 0x50, 0x61, 0x63,
|
||||
0x69, 0x66, 0x69, 0x63, 0x2f, 0x54, 0x72, 0x75, 0x6b, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66,
|
||||
0x69, 0x63, 0x2f, 0x57, 0x61, 0x6b, 0x65, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63,
|
||||
0x2f, 0x57, 0x61, 0x6c, 0x6c, 0x69, 0x73, 0x0d, 0x0a, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63,
|
||||
0x2f, 0x59, 0x61, 0x70, 0x0d, 0x0a, 0x55, 0x53, 0x2f, 0x41, 0x6c, 0x61, 0x73, 0x6b, 0x61, 0x0d,
|
||||
0x0a, 0x55, 0x53, 0x2f, 0x41, 0x6c, 0x65, 0x75, 0x74, 0x69, 0x61, 0x6e, 0x0d, 0x0a, 0x55, 0x53,
|
||||
0x2f, 0x41, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x61, 0x0d, 0x0a, 0x55, 0x53, 0x2f, 0x43, 0x65, 0x6e,
|
||||
0x74, 0x72, 0x61, 0x6c, 0x0d, 0x0a, 0x55, 0x53, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x2d, 0x49, 0x6e,
|
||||
0x64, 0x69, 0x61, 0x6e, 0x61, 0x0d, 0x0a, 0x55, 0x53, 0x2f, 0x45, 0x61, 0x73, 0x74, 0x65, 0x72,
|
||||
0x6e, 0x0d, 0x0a, 0x55, 0x53, 0x2f, 0x48, 0x61, 0x77, 0x61, 0x69, 0x69, 0x0d, 0x0a, 0x55, 0x53,
|
||||
0x2f, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x61, 0x2d, 0x53, 0x74, 0x61, 0x72, 0x6b, 0x65, 0x0d,
|
||||
0x0a, 0x55, 0x53, 0x2f, 0x4d, 0x69, 0x63, 0x68, 0x69, 0x67, 0x61, 0x6e, 0x0d, 0x0a, 0x55, 0x53,
|
||||
0x2f, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x0d, 0x0a, 0x55, 0x53, 0x2f, 0x50, 0x61,
|
||||
0x63, 0x69, 0x66, 0x69, 0x63, 0x0d, 0x0a, 0x55, 0x53, 0x2f, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69,
|
||||
0x63, 0x2d, 0x4e, 0x65, 0x77, 0x0d, 0x0a, 0x55, 0x53, 0x2f, 0x53, 0x61, 0x6d, 0x6f, 0x61, 0x0d,
|
||||
0x0a};
|
||||
|
||||
static VirtualFile GenerateDefaultTimeZoneFile() {
|
||||
struct {
|
||||
s64_be at;
|
||||
INSERT_PADDING_BYTES(7);
|
||||
std::array<char, 4> time_zone_chars;
|
||||
INSERT_PADDING_BYTES(2);
|
||||
std::array<char, 6> time_zone_name;
|
||||
} time_zone_info{};
|
||||
|
||||
const VirtualFile file{std::make_shared<VectorVfsFile>(
|
||||
std::vector<u8>(sizeof(Service::Time::TimeZone::TzifHeader) + sizeof(time_zone_info)),
|
||||
"GMT")};
|
||||
|
||||
Service::Time::TimeZone::TzifHeader header{};
|
||||
header.magic = 0x545a6966;
|
||||
header.version = 0x32;
|
||||
header.ttis_gmt_count = 0x1;
|
||||
header.ttis_std_count = 0x1;
|
||||
header.time_count = 0x1;
|
||||
header.type_count = 0x1;
|
||||
header.char_count = 0x4;
|
||||
file->WriteObject(header, 0);
|
||||
|
||||
time_zone_info.at = 0xf8;
|
||||
time_zone_info.time_zone_chars = {'G', 'M', 'T', '\0'};
|
||||
time_zone_info.time_zone_name = {'\n', 'G', 'M', 'T', '0', '\n'};
|
||||
file->WriteObject(time_zone_info, sizeof(Service::Time::TimeZone::TzifHeader));
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
VirtualDir TimeZoneBinary() {
|
||||
const std::vector<VirtualDir> root_dirs{std::make_shared<VectorVfsDirectory>(
|
||||
std::vector<VirtualFile>{GenerateDefaultTimeZoneFile()}, std::vector<VirtualDir>{},
|
||||
"zoneinfo")};
|
||||
const std::vector<VirtualFile> root_files{
|
||||
std::make_shared<ArrayVfsFile<LOCATION_NAMES.size()>>(LOCATION_NAMES, "binaryList.txt")};
|
||||
return std::make_shared<VectorVfsDirectory>(root_files, root_dirs, "data");
|
||||
}
|
||||
|
||||
} // namespace FileSys::SystemArchive
|
||||
14
src/core/file_sys/system_archive/time_zone_binary.h
Normal file
14
src/core/file_sys/system_archive/time_zone_binary.h
Normal file
@@ -0,0 +1,14 @@
|
||||
// Copyright 2019 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include "core/file_sys/vfs_types.h"
|
||||
|
||||
namespace FileSys::SystemArchive {
|
||||
|
||||
VirtualDir TimeZoneBinary();
|
||||
|
||||
} // namespace FileSys::SystemArchive
|
||||
@@ -35,7 +35,7 @@
|
||||
#include "common/swap.h"
|
||||
#include "core/arm/arm_interface.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_cpu.h"
|
||||
#include "core/core_manager.h"
|
||||
#include "core/gdbstub/gdbstub.h"
|
||||
#include "core/hle/kernel/process.h"
|
||||
#include "core/hle/kernel/scheduler.h"
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include "common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_cpu.h"
|
||||
#include "core/hle/kernel/address_arbiter.h"
|
||||
#include "core/hle/kernel/errors.h"
|
||||
#include "core/hle/kernel/scheduler.h"
|
||||
@@ -17,10 +16,10 @@
|
||||
#include "core/memory.h"
|
||||
|
||||
namespace Kernel {
|
||||
namespace {
|
||||
|
||||
// Wake up num_to_wake (or all) threads in a vector.
|
||||
void WakeThreads(const std::vector<std::shared_ptr<Thread>>& waiting_threads, s32 num_to_wake) {
|
||||
auto& system = Core::System::GetInstance();
|
||||
void AddressArbiter::WakeThreads(const std::vector<std::shared_ptr<Thread>>& waiting_threads,
|
||||
s32 num_to_wake) {
|
||||
// Only process up to 'target' threads, unless 'target' is <= 0, in which case process
|
||||
// them all.
|
||||
std::size_t last = waiting_threads.size();
|
||||
@@ -32,12 +31,12 @@ void WakeThreads(const std::vector<std::shared_ptr<Thread>>& waiting_threads, s3
|
||||
for (std::size_t i = 0; i < last; i++) {
|
||||
ASSERT(waiting_threads[i]->GetStatus() == ThreadStatus::WaitArb);
|
||||
waiting_threads[i]->SetWaitSynchronizationResult(RESULT_SUCCESS);
|
||||
RemoveThread(waiting_threads[i]);
|
||||
waiting_threads[i]->SetArbiterWaitAddress(0);
|
||||
waiting_threads[i]->ResumeFromWait();
|
||||
system.PrepareReschedule(waiting_threads[i]->GetProcessorID());
|
||||
}
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
AddressArbiter::AddressArbiter(Core::System& system) : system{system} {}
|
||||
AddressArbiter::~AddressArbiter() = default;
|
||||
@@ -184,6 +183,7 @@ ResultCode AddressArbiter::WaitForAddressIfEqual(VAddr address, s32 value, s64 t
|
||||
ResultCode AddressArbiter::WaitForAddressImpl(VAddr address, s64 timeout) {
|
||||
Thread* current_thread = system.CurrentScheduler().GetCurrentThread();
|
||||
current_thread->SetArbiterWaitAddress(address);
|
||||
InsertThread(SharedFrom(current_thread));
|
||||
current_thread->SetStatus(ThreadStatus::WaitArb);
|
||||
current_thread->InvalidateWakeupCallback();
|
||||
current_thread->WakeAfterDelay(timeout);
|
||||
@@ -192,26 +192,51 @@ ResultCode AddressArbiter::WaitForAddressImpl(VAddr address, s64 timeout) {
|
||||
return RESULT_TIMEOUT;
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<Thread>> AddressArbiter::GetThreadsWaitingOnAddress(
|
||||
VAddr address) const {
|
||||
void AddressArbiter::HandleWakeupThread(std::shared_ptr<Thread> thread) {
|
||||
ASSERT(thread->GetStatus() == ThreadStatus::WaitArb);
|
||||
RemoveThread(thread);
|
||||
thread->SetArbiterWaitAddress(0);
|
||||
}
|
||||
|
||||
// Retrieve all threads that are waiting for this address.
|
||||
std::vector<std::shared_ptr<Thread>> threads;
|
||||
const auto& scheduler = system.GlobalScheduler();
|
||||
const auto& thread_list = scheduler.GetThreadList();
|
||||
|
||||
for (const auto& thread : thread_list) {
|
||||
if (thread->GetArbiterWaitAddress() == address) {
|
||||
threads.push_back(thread);
|
||||
void AddressArbiter::InsertThread(std::shared_ptr<Thread> thread) {
|
||||
const VAddr arb_addr = thread->GetArbiterWaitAddress();
|
||||
std::list<std::shared_ptr<Thread>>& thread_list = arb_threads[arb_addr];
|
||||
auto it = thread_list.begin();
|
||||
while (it != thread_list.end()) {
|
||||
const std::shared_ptr<Thread>& current_thread = *it;
|
||||
if (current_thread->GetPriority() >= thread->GetPriority()) {
|
||||
thread_list.insert(it, thread);
|
||||
return;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
thread_list.push_back(std::move(thread));
|
||||
}
|
||||
|
||||
// Sort them by priority, such that the highest priority ones come first.
|
||||
std::sort(threads.begin(), threads.end(),
|
||||
[](const std::shared_ptr<Thread>& lhs, const std::shared_ptr<Thread>& rhs) {
|
||||
return lhs->GetPriority() < rhs->GetPriority();
|
||||
});
|
||||
void AddressArbiter::RemoveThread(std::shared_ptr<Thread> thread) {
|
||||
const VAddr arb_addr = thread->GetArbiterWaitAddress();
|
||||
std::list<std::shared_ptr<Thread>>& thread_list = arb_threads[arb_addr];
|
||||
auto it = thread_list.begin();
|
||||
while (it != thread_list.end()) {
|
||||
const std::shared_ptr<Thread>& current_thread = *it;
|
||||
if (current_thread.get() == thread.get()) {
|
||||
thread_list.erase(it);
|
||||
return;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
return threads;
|
||||
std::vector<std::shared_ptr<Thread>> AddressArbiter::GetThreadsWaitingOnAddress(VAddr address) {
|
||||
std::vector<std::shared_ptr<Thread>> result;
|
||||
std::list<std::shared_ptr<Thread>>& thread_list = arb_threads[address];
|
||||
auto it = thread_list.begin();
|
||||
while (it != thread_list.end()) {
|
||||
std::shared_ptr<Thread> current_thread = *it;
|
||||
result.push_back(std::move(current_thread));
|
||||
++it;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
} // namespace Kernel
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "common/common_types.h"
|
||||
@@ -48,6 +50,9 @@ public:
|
||||
/// Waits on an address with a particular arbitration type.
|
||||
ResultCode WaitForAddress(VAddr address, ArbitrationType type, s32 value, s64 timeout_ns);
|
||||
|
||||
/// Removes a thread from the container and resets its address arbiter adress to 0
|
||||
void HandleWakeupThread(std::shared_ptr<Thread> thread);
|
||||
|
||||
private:
|
||||
/// Signals an address being waited on.
|
||||
ResultCode SignalToAddressOnly(VAddr address, s32 num_to_wake);
|
||||
@@ -71,8 +76,20 @@ private:
|
||||
// Waits on the given address with a timeout in nanoseconds
|
||||
ResultCode WaitForAddressImpl(VAddr address, s64 timeout);
|
||||
|
||||
/// Wake up num_to_wake (or all) threads in a vector.
|
||||
void WakeThreads(const std::vector<std::shared_ptr<Thread>>& waiting_threads, s32 num_to_wake);
|
||||
|
||||
/// Insert a thread into the address arbiter container
|
||||
void InsertThread(std::shared_ptr<Thread> thread);
|
||||
|
||||
/// Removes a thread from the address arbiter container
|
||||
void RemoveThread(std::shared_ptr<Thread> thread);
|
||||
|
||||
// Gets the threads waiting on an address.
|
||||
std::vector<std::shared_ptr<Thread>> GetThreadsWaitingOnAddress(VAddr address) const;
|
||||
std::vector<std::shared_ptr<Thread>> GetThreadsWaitingOnAddress(VAddr address);
|
||||
|
||||
/// List of threads waiting for a address arbiter
|
||||
std::unordered_map<VAddr, std::list<std::shared_ptr<Thread>>> arb_threads;
|
||||
|
||||
Core::System& system;
|
||||
};
|
||||
|
||||
@@ -3,13 +3,15 @@
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <utility>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/logging/log.h"
|
||||
|
||||
#include "core/arm/arm_interface.h"
|
||||
#include "core/arm/exclusive_monitor.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/core_timing_util.h"
|
||||
@@ -17,6 +19,7 @@
|
||||
#include "core/hle/kernel/errors.h"
|
||||
#include "core/hle/kernel/handle_table.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
#include "core/hle/kernel/physical_core.h"
|
||||
#include "core/hle/kernel/process.h"
|
||||
#include "core/hle/kernel/resource_limit.h"
|
||||
#include "core/hle/kernel/scheduler.h"
|
||||
@@ -78,9 +81,9 @@ static void ThreadWakeupCallback(u64 thread_handle, [[maybe_unused]] s64 cycles_
|
||||
}
|
||||
}
|
||||
|
||||
if (thread->GetArbiterWaitAddress() != 0) {
|
||||
ASSERT(thread->GetStatus() == ThreadStatus::WaitArb);
|
||||
thread->SetArbiterWaitAddress(0);
|
||||
if (thread->GetStatus() == ThreadStatus::WaitArb) {
|
||||
auto& address_arbiter = thread->GetOwnerProcess()->GetAddressArbiter();
|
||||
address_arbiter.HandleWakeupThread(thread);
|
||||
}
|
||||
|
||||
if (resume) {
|
||||
@@ -98,6 +101,7 @@ struct KernelCore::Impl {
|
||||
void Initialize(KernelCore& kernel) {
|
||||
Shutdown();
|
||||
|
||||
InitializePhysicalCores(kernel);
|
||||
InitializeSystemResourceLimit(kernel);
|
||||
InitializeThreads();
|
||||
InitializePreemption();
|
||||
@@ -121,6 +125,21 @@ struct KernelCore::Impl {
|
||||
global_scheduler.Shutdown();
|
||||
|
||||
named_ports.clear();
|
||||
|
||||
for (auto& core : cores) {
|
||||
core.Shutdown();
|
||||
}
|
||||
cores.clear();
|
||||
|
||||
exclusive_monitor.reset(nullptr);
|
||||
}
|
||||
|
||||
void InitializePhysicalCores(KernelCore& kernel) {
|
||||
exclusive_monitor =
|
||||
Core::MakeExclusiveMonitor(system.Memory(), global_scheduler.CpuCoresCount());
|
||||
for (std::size_t i = 0; i < global_scheduler.CpuCoresCount(); i++) {
|
||||
cores.emplace_back(system, kernel, i, *exclusive_monitor);
|
||||
}
|
||||
}
|
||||
|
||||
// Creates the default system resource limit
|
||||
@@ -186,6 +205,9 @@ struct KernelCore::Impl {
|
||||
/// the ConnectToPort SVC.
|
||||
NamedPortTable named_ports;
|
||||
|
||||
std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor;
|
||||
std::vector<Kernel::PhysicalCore> cores;
|
||||
|
||||
// System context
|
||||
Core::System& system;
|
||||
};
|
||||
@@ -240,6 +262,34 @@ const Kernel::GlobalScheduler& KernelCore::GlobalScheduler() const {
|
||||
return impl->global_scheduler;
|
||||
}
|
||||
|
||||
Kernel::PhysicalCore& KernelCore::PhysicalCore(std::size_t id) {
|
||||
return impl->cores[id];
|
||||
}
|
||||
|
||||
const Kernel::PhysicalCore& KernelCore::PhysicalCore(std::size_t id) const {
|
||||
return impl->cores[id];
|
||||
}
|
||||
|
||||
Core::ExclusiveMonitor& KernelCore::GetExclusiveMonitor() {
|
||||
return *impl->exclusive_monitor;
|
||||
}
|
||||
|
||||
const Core::ExclusiveMonitor& KernelCore::GetExclusiveMonitor() const {
|
||||
return *impl->exclusive_monitor;
|
||||
}
|
||||
|
||||
void KernelCore::InvalidateAllInstructionCaches() {
|
||||
for (std::size_t i = 0; i < impl->global_scheduler.CpuCoresCount(); i++) {
|
||||
PhysicalCore(i).ArmInterface().ClearInstructionCache();
|
||||
}
|
||||
}
|
||||
|
||||
void KernelCore::PrepareReschedule(std::size_t id) {
|
||||
if (id < impl->global_scheduler.CpuCoresCount()) {
|
||||
impl->cores[id].Stop();
|
||||
}
|
||||
}
|
||||
|
||||
void KernelCore::AddNamedPort(std::string name, std::shared_ptr<ClientPort> port) {
|
||||
impl->named_ports.emplace(std::move(name), std::move(port));
|
||||
}
|
||||
|
||||
@@ -11,8 +11,9 @@
|
||||
#include "core/hle/kernel/object.h"
|
||||
|
||||
namespace Core {
|
||||
class ExclusiveMonitor;
|
||||
class System;
|
||||
}
|
||||
} // namespace Core
|
||||
|
||||
namespace Core::Timing {
|
||||
class CoreTiming;
|
||||
@@ -25,6 +26,7 @@ class AddressArbiter;
|
||||
class ClientPort;
|
||||
class GlobalScheduler;
|
||||
class HandleTable;
|
||||
class PhysicalCore;
|
||||
class Process;
|
||||
class ResourceLimit;
|
||||
class Thread;
|
||||
@@ -84,6 +86,21 @@ public:
|
||||
/// Gets the sole instance of the global scheduler
|
||||
const Kernel::GlobalScheduler& GlobalScheduler() const;
|
||||
|
||||
/// Gets the an instance of the respective physical CPU core.
|
||||
Kernel::PhysicalCore& PhysicalCore(std::size_t id);
|
||||
|
||||
/// Gets the an instance of the respective physical CPU core.
|
||||
const Kernel::PhysicalCore& PhysicalCore(std::size_t id) const;
|
||||
|
||||
/// Stops execution of 'id' core, in order to reschedule a new thread.
|
||||
void PrepareReschedule(std::size_t id);
|
||||
|
||||
Core::ExclusiveMonitor& GetExclusiveMonitor();
|
||||
|
||||
const Core::ExclusiveMonitor& GetExclusiveMonitor() const;
|
||||
|
||||
void InvalidateAllInstructionCaches();
|
||||
|
||||
/// Adds a port to the named port table
|
||||
void AddNamedPort(std::string name, std::shared_ptr<ClientPort> port);
|
||||
|
||||
|
||||
52
src/core/hle/kernel/physical_core.cpp
Normal file
52
src/core/hle/kernel/physical_core.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
// Copyright 2020 yuzu Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "core/arm/arm_interface.h"
|
||||
#ifdef ARCHITECTURE_x86_64
|
||||
#include "core/arm/dynarmic/arm_dynarmic.h"
|
||||
#endif
|
||||
#include "core/arm/exclusive_monitor.h"
|
||||
#include "core/arm/unicorn/arm_unicorn.h"
|
||||
#include "core/core.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
#include "core/hle/kernel/physical_core.h"
|
||||
#include "core/hle/kernel/scheduler.h"
|
||||
#include "core/hle/kernel/thread.h"
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
PhysicalCore::PhysicalCore(Core::System& system, KernelCore& kernel, std::size_t id,
|
||||
Core::ExclusiveMonitor& exclusive_monitor)
|
||||
: core_index{id}, kernel{kernel} {
|
||||
#ifdef ARCHITECTURE_x86_64
|
||||
arm_interface = std::make_shared<Core::ARM_Dynarmic>(system, exclusive_monitor, core_index);
|
||||
#else
|
||||
arm_interface = std::make_shared<Core::ARM_Unicorn>(system);
|
||||
LOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available");
|
||||
#endif
|
||||
|
||||
scheduler = std::make_shared<Kernel::Scheduler>(system, *arm_interface, core_index);
|
||||
}
|
||||
|
||||
PhysicalCore::~PhysicalCore() = default;
|
||||
|
||||
void PhysicalCore::Run() {
|
||||
arm_interface->Run();
|
||||
arm_interface->ClearExclusiveState();
|
||||
}
|
||||
|
||||
void PhysicalCore::Step() {
|
||||
arm_interface->Step();
|
||||
}
|
||||
|
||||
void PhysicalCore::Stop() {
|
||||
arm_interface->PrepareReschedule();
|
||||
}
|
||||
|
||||
void PhysicalCore::Shutdown() {
|
||||
scheduler->Shutdown();
|
||||
}
|
||||
|
||||
} // namespace Kernel
|
||||
74
src/core/hle/kernel/physical_core.h
Normal file
74
src/core/hle/kernel/physical_core.h
Normal file
@@ -0,0 +1,74 @@
|
||||
// Copyright 2020 yuzu Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
|
||||
namespace Kernel {
|
||||
class Scheduler;
|
||||
} // namespace Kernel
|
||||
|
||||
namespace Core {
|
||||
class ARM_Interface;
|
||||
class ExclusiveMonitor;
|
||||
class System;
|
||||
} // namespace Core
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
class PhysicalCore {
|
||||
public:
|
||||
PhysicalCore(Core::System& system, KernelCore& kernel, std::size_t id,
|
||||
Core::ExclusiveMonitor& exclusive_monitor);
|
||||
|
||||
~PhysicalCore();
|
||||
|
||||
/// Execute current jit state
|
||||
void Run();
|
||||
/// Execute a single instruction in current jit.
|
||||
void Step();
|
||||
/// Stop JIT execution/exit
|
||||
void Stop();
|
||||
|
||||
// Shutdown this physical core.
|
||||
void Shutdown();
|
||||
|
||||
Core::ARM_Interface& ArmInterface() {
|
||||
return *arm_interface;
|
||||
}
|
||||
|
||||
const Core::ARM_Interface& ArmInterface() const {
|
||||
return *arm_interface;
|
||||
}
|
||||
|
||||
bool IsMainCore() const {
|
||||
return core_index == 0;
|
||||
}
|
||||
|
||||
bool IsSystemCore() const {
|
||||
return core_index == 3;
|
||||
}
|
||||
|
||||
std::size_t CoreIndex() const {
|
||||
return core_index;
|
||||
}
|
||||
|
||||
Kernel::Scheduler& Scheduler() {
|
||||
return *scheduler;
|
||||
}
|
||||
|
||||
const Kernel::Scheduler& Scheduler() const {
|
||||
return *scheduler;
|
||||
}
|
||||
|
||||
private:
|
||||
std::size_t core_index;
|
||||
KernelCore& kernel;
|
||||
std::shared_ptr<Core::ARM_Interface> arm_interface;
|
||||
std::shared_ptr<Kernel::Scheduler> scheduler;
|
||||
};
|
||||
|
||||
} // namespace Kernel
|
||||
@@ -14,6 +14,9 @@ namespace Kernel {
|
||||
// - Second to ensure all host backing memory used is aligned to 256 bytes due
|
||||
// to strict alignment restrictions on GPU memory.
|
||||
|
||||
using PhysicalMemory = std::vector<u8, Common::AlignmentAllocator<u8, 256>>;
|
||||
using PhysicalMemoryVector = std::vector<u8, Common::AlignmentAllocator<u8, 256>>;
|
||||
class PhysicalMemory final : public PhysicalMemoryVector {
|
||||
using PhysicalMemoryVector::PhysicalMemoryVector;
|
||||
};
|
||||
|
||||
} // namespace Kernel
|
||||
|
||||
@@ -317,6 +317,8 @@ void Process::FreeTLSRegion(VAddr tls_address) {
|
||||
}
|
||||
|
||||
void Process::LoadModule(CodeSet module_, VAddr base_addr) {
|
||||
code_memory_size += module_.memory.size();
|
||||
|
||||
const auto memory = std::make_shared<PhysicalMemory>(std::move(module_.memory));
|
||||
|
||||
const auto MapSegment = [&](const CodeSet::Segment& segment, VMAPermission permissions,
|
||||
@@ -332,8 +334,6 @@ void Process::LoadModule(CodeSet module_, VAddr base_addr) {
|
||||
MapSegment(module_.CodeSegment(), VMAPermission::ReadExecute, MemoryState::Code);
|
||||
MapSegment(module_.RODataSegment(), VMAPermission::Read, MemoryState::CodeData);
|
||||
MapSegment(module_.DataSegment(), VMAPermission::ReadWrite, MemoryState::CodeData);
|
||||
|
||||
code_memory_size += module_.memory.size();
|
||||
}
|
||||
|
||||
Process::Process(Core::System& system)
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include "common/logging/log.h"
|
||||
#include "core/arm/arm_interface.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_cpu.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
#include "core/hle/kernel/process.h"
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include "common/string_util.h"
|
||||
#include "core/arm/exclusive_monitor.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_cpu.h"
|
||||
#include "core/core_manager.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/core_timing_util.h"
|
||||
#include "core/hle/kernel/address_arbiter.h"
|
||||
@@ -1650,8 +1650,7 @@ static ResultCode WaitProcessWideKeyAtomic(Core::System& system, VAddr mutex_add
|
||||
}
|
||||
|
||||
/// Signal process wide key
|
||||
static ResultCode SignalProcessWideKey(Core::System& system, VAddr condition_variable_addr,
|
||||
s32 target) {
|
||||
static void SignalProcessWideKey(Core::System& system, VAddr condition_variable_addr, s32 target) {
|
||||
LOG_TRACE(Kernel_SVC, "called, condition_variable_addr=0x{:X}, target=0x{:08X}",
|
||||
condition_variable_addr, target);
|
||||
|
||||
@@ -1726,8 +1725,6 @@ static ResultCode SignalProcessWideKey(Core::System& system, VAddr condition_var
|
||||
system.PrepareReschedule(thread->GetProcessorID());
|
||||
}
|
||||
}
|
||||
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
// Wait for an address (via Address Arbiter)
|
||||
@@ -1781,6 +1778,17 @@ static ResultCode SignalToAddress(Core::System& system, VAddr address, u32 type,
|
||||
return address_arbiter.SignalToAddress(address, signal_type, value, num_to_wake);
|
||||
}
|
||||
|
||||
static void KernelDebug([[maybe_unused]] Core::System& system,
|
||||
[[maybe_unused]] u32 kernel_debug_type, [[maybe_unused]] u64 param1,
|
||||
[[maybe_unused]] u64 param2, [[maybe_unused]] u64 param3) {
|
||||
// Intentionally do nothing, as this does nothing in released kernel binaries.
|
||||
}
|
||||
|
||||
static void ChangeKernelTraceState([[maybe_unused]] Core::System& system,
|
||||
[[maybe_unused]] u32 trace_state) {
|
||||
// Intentionally do nothing, as this does nothing in released kernel binaries.
|
||||
}
|
||||
|
||||
/// This returns the total CPU ticks elapsed since the CPU was powered-on
|
||||
static u64 GetSystemTick(Core::System& system) {
|
||||
LOG_TRACE(Kernel_SVC, "called");
|
||||
@@ -2418,8 +2426,8 @@ static const FunctionDef SVC_Table[] = {
|
||||
{0x39, nullptr, "Unknown"},
|
||||
{0x3A, nullptr, "Unknown"},
|
||||
{0x3B, nullptr, "Unknown"},
|
||||
{0x3C, nullptr, "DumpInfo"},
|
||||
{0x3D, nullptr, "DumpInfoNew"},
|
||||
{0x3C, SvcWrap<KernelDebug>, "KernelDebug"},
|
||||
{0x3D, SvcWrap<ChangeKernelTraceState>, "ChangeKernelTraceState"},
|
||||
{0x3E, nullptr, "Unknown"},
|
||||
{0x3F, nullptr, "Unknown"},
|
||||
{0x40, nullptr, "CreateSession"},
|
||||
|
||||
@@ -112,11 +112,6 @@ void SvcWrap(Core::System& system) {
|
||||
FuncReturn(system, retval);
|
||||
}
|
||||
|
||||
template <ResultCode func(Core::System&, u64, s32)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
FuncReturn(system, func(system, Param(system, 0), static_cast<s32>(Param(system, 1))).raw);
|
||||
}
|
||||
|
||||
template <ResultCode func(Core::System&, u64, u32)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
FuncReturn(system, func(system, Param(system, 0), static_cast<u32>(Param(system, 1))).raw);
|
||||
@@ -311,11 +306,27 @@ void SvcWrap(Core::System& system) {
|
||||
func(system);
|
||||
}
|
||||
|
||||
template <void func(Core::System&, u32)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
func(system, static_cast<u32>(Param(system, 0)));
|
||||
}
|
||||
|
||||
template <void func(Core::System&, u32, u64, u64, u64)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
func(system, static_cast<u32>(Param(system, 0)), Param(system, 1), Param(system, 2),
|
||||
Param(system, 3));
|
||||
}
|
||||
|
||||
template <void func(Core::System&, s64)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
func(system, static_cast<s64>(Param(system, 0)));
|
||||
}
|
||||
|
||||
template <void func(Core::System&, u64, s32)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
func(system, Param(system, 0), static_cast<s32>(Param(system, 1)));
|
||||
}
|
||||
|
||||
template <void func(Core::System&, u64, u64)>
|
||||
void SvcWrap(Core::System& system) {
|
||||
func(system, Param(system, 0), Param(system, 1));
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#include "common/thread_queue_list.h"
|
||||
#include "core/arm/arm_interface.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_cpu.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/core_timing_util.h"
|
||||
#include "core/hle/kernel/errors.h"
|
||||
@@ -356,7 +355,7 @@ void Thread::SetActivity(ThreadActivity value) {
|
||||
// Set status if not waiting
|
||||
if (status == ThreadStatus::Ready || status == ThreadStatus::Running) {
|
||||
SetStatus(ThreadStatus::Paused);
|
||||
Core::System::GetInstance().CpuCore(processor_id).PrepareReschedule();
|
||||
kernel.PrepareReschedule(processor_id);
|
||||
}
|
||||
} else if (status == ThreadStatus::Paused) {
|
||||
// Ready to reschedule
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <iterator>
|
||||
#include <utility>
|
||||
#include "common/alignment.h"
|
||||
@@ -269,18 +270,9 @@ ResultVal<VAddr> VMManager::SetHeapSize(u64 size) {
|
||||
// If necessary, expand backing vector to cover new heap extents in
|
||||
// the case of allocating. Otherwise, shrink the backing memory,
|
||||
// if a smaller heap has been requested.
|
||||
const u64 old_heap_size = GetCurrentHeapSize();
|
||||
if (size > old_heap_size) {
|
||||
const u64 alloc_size = size - old_heap_size;
|
||||
|
||||
heap_memory->insert(heap_memory->end(), alloc_size, 0);
|
||||
RefreshMemoryBlockMappings(heap_memory.get());
|
||||
} else if (size < old_heap_size) {
|
||||
heap_memory->resize(size);
|
||||
heap_memory->shrink_to_fit();
|
||||
|
||||
RefreshMemoryBlockMappings(heap_memory.get());
|
||||
}
|
||||
heap_memory->resize(size);
|
||||
heap_memory->shrink_to_fit();
|
||||
RefreshMemoryBlockMappings(heap_memory.get());
|
||||
|
||||
heap_end = heap_region_base + size;
|
||||
ASSERT(GetCurrentHeapSize() == heap_memory->size());
|
||||
@@ -752,24 +744,20 @@ void VMManager::MergeAdjacentVMA(VirtualMemoryArea& left, const VirtualMemoryAre
|
||||
// Always merge allocated memory blocks, even when they don't share the same backing block.
|
||||
if (left.type == VMAType::AllocatedMemoryBlock &&
|
||||
(left.backing_block != right.backing_block || left.offset + left.size != right.offset)) {
|
||||
const auto right_begin = right.backing_block->begin() + right.offset;
|
||||
const auto right_end = right_begin + right.size;
|
||||
|
||||
// Check if we can save work.
|
||||
if (left.offset == 0 && left.size == left.backing_block->size()) {
|
||||
// Fast case: left is an entire backing block.
|
||||
left.backing_block->insert(left.backing_block->end(), right_begin, right_end);
|
||||
left.backing_block->resize(left.size + right.size);
|
||||
std::memcpy(left.backing_block->data() + left.size,
|
||||
right.backing_block->data() + right.offset, right.size);
|
||||
} else {
|
||||
// Slow case: make a new memory block for left and right.
|
||||
const auto left_begin = left.backing_block->begin() + left.offset;
|
||||
const auto left_end = left_begin + left.size;
|
||||
const auto left_size = static_cast<std::size_t>(std::distance(left_begin, left_end));
|
||||
const auto right_size = static_cast<std::size_t>(std::distance(right_begin, right_end));
|
||||
|
||||
auto new_memory = std::make_shared<PhysicalMemory>();
|
||||
new_memory->reserve(left_size + right_size);
|
||||
new_memory->insert(new_memory->end(), left_begin, left_end);
|
||||
new_memory->insert(new_memory->end(), right_begin, right_end);
|
||||
new_memory->resize(left.size + right.size);
|
||||
std::memcpy(new_memory->data(), left.backing_block->data() + left.offset, left.size);
|
||||
std::memcpy(new_memory->data() + left.size, right.backing_block->data() + right.offset,
|
||||
right.size);
|
||||
|
||||
left.backing_block = std::move(new_memory);
|
||||
left.offset = 0;
|
||||
@@ -792,8 +780,7 @@ void VMManager::UpdatePageTableForVMA(const VirtualMemoryArea& vma) {
|
||||
memory.UnmapRegion(page_table, vma.base, vma.size);
|
||||
break;
|
||||
case VMAType::AllocatedMemoryBlock:
|
||||
memory.MapMemoryRegion(page_table, vma.base, vma.size,
|
||||
vma.backing_block->data() + vma.offset);
|
||||
memory.MapMemoryRegion(page_table, vma.base, vma.size, *vma.backing_block, vma.offset);
|
||||
break;
|
||||
case VMAType::BackingMemory:
|
||||
memory.MapMemoryRegion(page_table, vma.base, vma.size, vma.backing_memory);
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include "common/common_types.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_cpu.h"
|
||||
#include "core/hle/kernel/kernel.h"
|
||||
#include "core/hle/kernel/object.h"
|
||||
#include "core/hle/kernel/process.h"
|
||||
@@ -96,7 +95,7 @@ void WaitObject::WakeupWaitingThread(std::shared_ptr<Thread> thread) {
|
||||
}
|
||||
if (resume) {
|
||||
thread->ResumeFromWait();
|
||||
Core::System::GetInstance().PrepareReschedule(thread->GetProcessorID());
|
||||
kernel.PrepareReschedule(thread->GetProcessorID());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -211,7 +211,7 @@ protected:
|
||||
}
|
||||
|
||||
ProfileManager& profile_manager;
|
||||
Common::UUID user_id; ///< The user id this profile refers to.
|
||||
Common::UUID user_id{Common::INVALID_UUID}; ///< The user id this profile refers to.
|
||||
};
|
||||
|
||||
class IProfile final : public IProfileCommon {
|
||||
|
||||
@@ -16,17 +16,17 @@ namespace Service::Account {
|
||||
using Common::UUID;
|
||||
|
||||
struct UserRaw {
|
||||
UUID uuid;
|
||||
UUID uuid2;
|
||||
u64 timestamp;
|
||||
ProfileUsername username;
|
||||
ProfileData extra_data;
|
||||
UUID uuid{Common::INVALID_UUID};
|
||||
UUID uuid2{Common::INVALID_UUID};
|
||||
u64 timestamp{};
|
||||
ProfileUsername username{};
|
||||
ProfileData extra_data{};
|
||||
};
|
||||
static_assert(sizeof(UserRaw) == 0xC8, "UserRaw has incorrect size.");
|
||||
|
||||
struct ProfileDataRaw {
|
||||
INSERT_PADDING_BYTES(0x10);
|
||||
std::array<UserRaw, MAX_USERS> users;
|
||||
std::array<UserRaw, MAX_USERS> users{};
|
||||
};
|
||||
static_assert(sizeof(ProfileDataRaw) == 0x650, "ProfileDataRaw has incorrect size.");
|
||||
|
||||
@@ -238,7 +238,7 @@ UserIDArray ProfileManager::GetOpenUsers() const {
|
||||
std::transform(profiles.begin(), profiles.end(), output.begin(), [](const ProfileInfo& p) {
|
||||
if (p.is_open)
|
||||
return p.user_uuid;
|
||||
return UUID{};
|
||||
return UUID{Common::INVALID_UUID};
|
||||
});
|
||||
std::stable_partition(output.begin(), output.end(), [](const UUID& uuid) { return uuid; });
|
||||
return output;
|
||||
|
||||
@@ -13,9 +13,10 @@
|
||||
#include "core/hle/result.h"
|
||||
|
||||
namespace Service::Account {
|
||||
constexpr std::size_t MAX_USERS = 8;
|
||||
|
||||
constexpr std::size_t profile_username_size = 32;
|
||||
constexpr std::size_t MAX_USERS{8};
|
||||
constexpr std::size_t profile_username_size{32};
|
||||
|
||||
using ProfileUsername = std::array<u8, profile_username_size>;
|
||||
using UserIDArray = std::array<Common::UUID, MAX_USERS>;
|
||||
|
||||
@@ -23,8 +24,8 @@ using UserIDArray = std::array<Common::UUID, MAX_USERS>;
|
||||
/// TODO: RE this structure
|
||||
struct ProfileData {
|
||||
INSERT_PADDING_WORDS(1);
|
||||
u32 icon_id;
|
||||
u8 bg_color_id;
|
||||
u32 icon_id{};
|
||||
u8 bg_color_id{};
|
||||
INSERT_PADDING_BYTES(0x7);
|
||||
INSERT_PADDING_BYTES(0x10);
|
||||
INSERT_PADDING_BYTES(0x60);
|
||||
@@ -34,17 +35,17 @@ static_assert(sizeof(ProfileData) == 0x80, "ProfileData structure has incorrect
|
||||
/// This holds general information about a users profile. This is where we store all the information
|
||||
/// based on a specific user
|
||||
struct ProfileInfo {
|
||||
Common::UUID user_uuid;
|
||||
ProfileUsername username;
|
||||
u64 creation_time;
|
||||
ProfileData data; // TODO(ognik): Work out what this is
|
||||
bool is_open;
|
||||
Common::UUID user_uuid{Common::INVALID_UUID};
|
||||
ProfileUsername username{};
|
||||
u64 creation_time{};
|
||||
ProfileData data{}; // TODO(ognik): Work out what this is
|
||||
bool is_open{};
|
||||
};
|
||||
|
||||
struct ProfileBase {
|
||||
Common::UUID user_uuid;
|
||||
u64_le timestamp;
|
||||
ProfileUsername username;
|
||||
Common::UUID user_uuid{Common::INVALID_UUID};
|
||||
u64_le timestamp{};
|
||||
ProfileUsername username{};
|
||||
|
||||
// Zero out all the fields to make the profile slot considered "Empty"
|
||||
void Invalidate() {
|
||||
@@ -101,7 +102,7 @@ private:
|
||||
bool RemoveProfileAtIndex(std::size_t index);
|
||||
|
||||
std::array<ProfileInfo, MAX_USERS> profiles{};
|
||||
std::size_t user_count = 0;
|
||||
std::size_t user_count{};
|
||||
Common::UUID last_opened_user{Common::INVALID_UUID};
|
||||
};
|
||||
|
||||
|
||||
@@ -241,7 +241,7 @@ private:
|
||||
bool has_received_friend_request;
|
||||
};
|
||||
|
||||
Common::UUID uuid;
|
||||
Common::UUID uuid{Common::INVALID_UUID};
|
||||
Kernel::EventPair notification_event;
|
||||
std::queue<SizedNotificationInfo> notifications;
|
||||
States states{};
|
||||
|
||||
@@ -10,13 +10,13 @@
|
||||
|
||||
namespace Service::Mii {
|
||||
|
||||
constexpr std::size_t MAX_MIIS = 100;
|
||||
constexpr u32 INVALID_INDEX = 0xFFFFFFFF;
|
||||
constexpr std::size_t MAX_MIIS{100};
|
||||
constexpr u32 INVALID_INDEX{0xFFFFFFFF};
|
||||
|
||||
struct RandomParameters {
|
||||
u32 unknown_1;
|
||||
u32 unknown_2;
|
||||
u32 unknown_3;
|
||||
u32 unknown_1{};
|
||||
u32 unknown_2{};
|
||||
u32 unknown_3{};
|
||||
};
|
||||
static_assert(sizeof(RandomParameters) == 0xC, "RandomParameters has incorrect size.");
|
||||
|
||||
@@ -30,57 +30,57 @@ enum class Source : u32 {
|
||||
std::ostream& operator<<(std::ostream& os, Source source);
|
||||
|
||||
struct MiiInfo {
|
||||
Common::UUID uuid;
|
||||
std::array<char16_t, 11> name;
|
||||
u8 font_region;
|
||||
u8 favorite_color;
|
||||
u8 gender;
|
||||
u8 height;
|
||||
u8 weight;
|
||||
u8 mii_type;
|
||||
u8 mii_region;
|
||||
u8 face_type;
|
||||
u8 face_color;
|
||||
u8 face_wrinkle;
|
||||
u8 face_makeup;
|
||||
u8 hair_type;
|
||||
u8 hair_color;
|
||||
bool hair_flip;
|
||||
u8 eye_type;
|
||||
u8 eye_color;
|
||||
u8 eye_scale;
|
||||
u8 eye_aspect_ratio;
|
||||
u8 eye_rotate;
|
||||
u8 eye_x;
|
||||
u8 eye_y;
|
||||
u8 eyebrow_type;
|
||||
u8 eyebrow_color;
|
||||
u8 eyebrow_scale;
|
||||
u8 eyebrow_aspect_ratio;
|
||||
u8 eyebrow_rotate;
|
||||
u8 eyebrow_x;
|
||||
u8 eyebrow_y;
|
||||
u8 nose_type;
|
||||
u8 nose_scale;
|
||||
u8 nose_y;
|
||||
u8 mouth_type;
|
||||
u8 mouth_color;
|
||||
u8 mouth_scale;
|
||||
u8 mouth_aspect_ratio;
|
||||
u8 mouth_y;
|
||||
u8 facial_hair_color;
|
||||
u8 beard_type;
|
||||
u8 mustache_type;
|
||||
u8 mustache_scale;
|
||||
u8 mustache_y;
|
||||
u8 glasses_type;
|
||||
u8 glasses_color;
|
||||
u8 glasses_scale;
|
||||
u8 glasses_y;
|
||||
u8 mole_type;
|
||||
u8 mole_scale;
|
||||
u8 mole_x;
|
||||
u8 mole_y;
|
||||
Common::UUID uuid{Common::INVALID_UUID};
|
||||
std::array<char16_t, 11> name{};
|
||||
u8 font_region{};
|
||||
u8 favorite_color{};
|
||||
u8 gender{};
|
||||
u8 height{};
|
||||
u8 weight{};
|
||||
u8 mii_type{};
|
||||
u8 mii_region{};
|
||||
u8 face_type{};
|
||||
u8 face_color{};
|
||||
u8 face_wrinkle{};
|
||||
u8 face_makeup{};
|
||||
u8 hair_type{};
|
||||
u8 hair_color{};
|
||||
bool hair_flip{};
|
||||
u8 eye_type{};
|
||||
u8 eye_color{};
|
||||
u8 eye_scale{};
|
||||
u8 eye_aspect_ratio{};
|
||||
u8 eye_rotate{};
|
||||
u8 eye_x{};
|
||||
u8 eye_y{};
|
||||
u8 eyebrow_type{};
|
||||
u8 eyebrow_color{};
|
||||
u8 eyebrow_scale{};
|
||||
u8 eyebrow_aspect_ratio{};
|
||||
u8 eyebrow_rotate{};
|
||||
u8 eyebrow_x{};
|
||||
u8 eyebrow_y{};
|
||||
u8 nose_type{};
|
||||
u8 nose_scale{};
|
||||
u8 nose_y{};
|
||||
u8 mouth_type{};
|
||||
u8 mouth_color{};
|
||||
u8 mouth_scale{};
|
||||
u8 mouth_aspect_ratio{};
|
||||
u8 mouth_y{};
|
||||
u8 facial_hair_color{};
|
||||
u8 beard_type{};
|
||||
u8 mustache_type{};
|
||||
u8 mustache_scale{};
|
||||
u8 mustache_y{};
|
||||
u8 glasses_type{};
|
||||
u8 glasses_color{};
|
||||
u8 glasses_scale{};
|
||||
u8 glasses_y{};
|
||||
u8 mole_type{};
|
||||
u8 mole_scale{};
|
||||
u8 mole_x{};
|
||||
u8 mole_y{};
|
||||
INSERT_PADDING_BYTES(1);
|
||||
|
||||
std::u16string Name() const;
|
||||
@@ -94,14 +94,14 @@ bool operator!=(const MiiInfo& lhs, const MiiInfo& rhs);
|
||||
|
||||
#pragma pack(push, 4)
|
||||
struct MiiInfoElement {
|
||||
MiiInfo info;
|
||||
Source source;
|
||||
MiiInfo info{};
|
||||
Source source{};
|
||||
};
|
||||
static_assert(sizeof(MiiInfoElement) == 0x5C, "MiiInfoElement has incorrect size.");
|
||||
|
||||
struct MiiStoreBitFields {
|
||||
union {
|
||||
u32 word_0;
|
||||
u32 word_0{};
|
||||
|
||||
BitField<24, 8, u32> hair_type;
|
||||
BitField<23, 1, u32> mole_type;
|
||||
@@ -112,7 +112,7 @@ struct MiiStoreBitFields {
|
||||
};
|
||||
|
||||
union {
|
||||
u32 word_1;
|
||||
u32 word_1{};
|
||||
|
||||
BitField<31, 1, u32> gender;
|
||||
BitField<24, 7, u32> eye_color;
|
||||
@@ -122,7 +122,7 @@ struct MiiStoreBitFields {
|
||||
};
|
||||
|
||||
union {
|
||||
u32 word_2;
|
||||
u32 word_2{};
|
||||
|
||||
BitField<31, 1, u32> mii_type;
|
||||
BitField<24, 7, u32> glasses_color;
|
||||
@@ -135,7 +135,7 @@ struct MiiStoreBitFields {
|
||||
};
|
||||
|
||||
union {
|
||||
u32 word_3;
|
||||
u32 word_3{};
|
||||
|
||||
BitField<29, 3, u32> mustache_type;
|
||||
BitField<24, 5, u32> eyebrow_type;
|
||||
@@ -148,7 +148,7 @@ struct MiiStoreBitFields {
|
||||
};
|
||||
|
||||
union {
|
||||
u32 word_4;
|
||||
u32 word_4{};
|
||||
|
||||
BitField<29, 3, u32> eye_rotate;
|
||||
BitField<24, 5, u32> mustache_y;
|
||||
@@ -160,7 +160,7 @@ struct MiiStoreBitFields {
|
||||
};
|
||||
|
||||
union {
|
||||
u32 word_5;
|
||||
u32 word_5{};
|
||||
|
||||
BitField<24, 5, u32> glasses_type;
|
||||
BitField<20, 4, u32> face_type;
|
||||
@@ -172,7 +172,7 @@ struct MiiStoreBitFields {
|
||||
};
|
||||
|
||||
union {
|
||||
u32 word_6;
|
||||
u32 word_6{};
|
||||
|
||||
BitField<28, 4, u32> eyebrow_rotate;
|
||||
BitField<24, 4, u32> eyebrow_scale;
|
||||
@@ -192,30 +192,30 @@ struct MiiStoreData {
|
||||
// This corresponds to the above structure MiiStoreBitFields. I did it like this because the
|
||||
// BitField<> type makes this (and any thing that contains it) not trivially copyable, which is
|
||||
// not suitable for our uses.
|
||||
std::array<u8, 0x1C> data;
|
||||
std::array<u8, 0x1C> data{};
|
||||
static_assert(sizeof(MiiStoreBitFields) == sizeof(data), "data field has incorrect size.");
|
||||
|
||||
std::array<char16_t, 10> name;
|
||||
Common::UUID uuid;
|
||||
u16 crc_1;
|
||||
u16 crc_2;
|
||||
std::array<char16_t, 10> name{};
|
||||
Common::UUID uuid{Common::INVALID_UUID};
|
||||
u16 crc_1{};
|
||||
u16 crc_2{};
|
||||
|
||||
std::u16string Name() const;
|
||||
};
|
||||
static_assert(sizeof(MiiStoreData) == 0x44, "MiiStoreData has incorrect size.");
|
||||
|
||||
struct MiiStoreDataElement {
|
||||
MiiStoreData data;
|
||||
Source source;
|
||||
MiiStoreData data{};
|
||||
Source source{};
|
||||
};
|
||||
static_assert(sizeof(MiiStoreDataElement) == 0x48, "MiiStoreDataElement has incorrect size.");
|
||||
|
||||
struct MiiDatabase {
|
||||
u32 magic; // 'NFDB'
|
||||
std::array<MiiStoreData, MAX_MIIS> miis;
|
||||
u32 magic{}; // 'NFDB'
|
||||
std::array<MiiStoreData, MAX_MIIS> miis{};
|
||||
INSERT_PADDING_BYTES(1);
|
||||
u8 count;
|
||||
u16 crc;
|
||||
u8 count{};
|
||||
u16 crc{};
|
||||
};
|
||||
static_assert(sizeof(MiiDatabase) == 0x1A98, "MiiDatabase has incorrect size.");
|
||||
#pragma pack(pop)
|
||||
@@ -266,8 +266,8 @@ private:
|
||||
void EnsureDatabasePartition();
|
||||
|
||||
MiiDatabase database;
|
||||
bool updated_flag = false;
|
||||
bool is_test_mode_enabled = false;
|
||||
bool updated_flag{};
|
||||
bool is_test_mode_enabled{};
|
||||
};
|
||||
|
||||
}; // namespace Service::Mii
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "core/hle/kernel/writable_event.h"
|
||||
#include "core/hle/service/nifm/nifm.h"
|
||||
#include "core/hle/service/service.h"
|
||||
#include "core/settings.h"
|
||||
|
||||
namespace Service::NIFM {
|
||||
|
||||
@@ -86,7 +87,12 @@ private:
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushEnum(RequestState::Connected);
|
||||
|
||||
if (Settings::values.bcat_backend == "none") {
|
||||
rb.PushEnum(RequestState::NotSubmitted);
|
||||
} else {
|
||||
rb.PushEnum(RequestState::Connected);
|
||||
}
|
||||
}
|
||||
|
||||
void GetResult(Kernel::HLERequestContext& ctx) {
|
||||
@@ -194,14 +200,22 @@ private:
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push<u8>(1);
|
||||
if (Settings::values.bcat_backend == "none") {
|
||||
rb.Push<u8>(0);
|
||||
} else {
|
||||
rb.Push<u8>(1);
|
||||
}
|
||||
}
|
||||
void IsAnyInternetRequestAccepted(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_NIFM, "(STUBBED) called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push<u8>(1);
|
||||
if (Settings::values.bcat_backend == "none") {
|
||||
rb.Push<u8>(0);
|
||||
} else {
|
||||
rb.Push<u8>(1);
|
||||
}
|
||||
}
|
||||
Core::System& system;
|
||||
};
|
||||
|
||||
@@ -104,10 +104,12 @@ u32 nvhost_as_gpu::Remap(const std::vector<u8>& input, std::vector<u8>& output)
|
||||
|
||||
ASSERT(object->status == nvmap::Object::Status::Allocated);
|
||||
|
||||
u64 size = static_cast<u64>(entry.pages) << 0x10;
|
||||
const u64 size = static_cast<u64>(entry.pages) << 0x10;
|
||||
ASSERT(size <= object->size);
|
||||
const u64 map_offset = static_cast<u64>(entry.map_offset) << 0x10;
|
||||
|
||||
GPUVAddr returned = gpu.MemoryManager().MapBufferEx(object->addr, offset, size);
|
||||
const GPUVAddr returned =
|
||||
gpu.MemoryManager().MapBufferEx(object->addr + map_offset, offset, size);
|
||||
ASSERT(returned == offset);
|
||||
}
|
||||
std::memcpy(output.data(), entries.data(), output.size());
|
||||
|
||||
@@ -62,7 +62,7 @@ private:
|
||||
u16_le flags;
|
||||
u16_le kind;
|
||||
u32_le nvmap_handle;
|
||||
INSERT_PADDING_WORDS(1);
|
||||
u32_le map_offset;
|
||||
u32_le offset;
|
||||
u32_le pages;
|
||||
};
|
||||
|
||||
@@ -88,6 +88,12 @@ std::optional<u64> NVFlinger::CreateLayer(u64 display_id) {
|
||||
return layer_id;
|
||||
}
|
||||
|
||||
void NVFlinger::CloseLayer(u64 layer_id) {
|
||||
for (auto& display : displays) {
|
||||
display.CloseLayer(layer_id);
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<u32> NVFlinger::FindBufferQueueId(u64 display_id, u64 layer_id) const {
|
||||
const auto* const layer = FindLayer(display_id, layer_id);
|
||||
|
||||
@@ -192,7 +198,7 @@ void NVFlinger::Compose() {
|
||||
|
||||
const auto& igbp_buffer = buffer->get().igbp_buffer;
|
||||
|
||||
const auto& gpu = system.GPU();
|
||||
auto& gpu = system.GPU();
|
||||
const auto& multi_fence = buffer->get().multi_fence;
|
||||
for (u32 fence_id = 0; fence_id < multi_fence.num_fences; fence_id++) {
|
||||
const auto& fence = multi_fence.fences[fence_id];
|
||||
|
||||
@@ -54,6 +54,9 @@ public:
|
||||
/// If an invalid display ID is specified, then an empty optional is returned.
|
||||
std::optional<u64> CreateLayer(u64 display_id);
|
||||
|
||||
/// Closes a layer on all displays for the given layer ID.
|
||||
void CloseLayer(u64 layer_id);
|
||||
|
||||
/// Finds the buffer queue ID of the specified layer in the specified display.
|
||||
///
|
||||
/// If an invalid display ID or layer ID is provided, then an empty optional is returned.
|
||||
|
||||
103
src/core/hle/service/time/clock_types.h
Normal file
103
src/core/hle/service/time/clock_types.h
Normal file
@@ -0,0 +1,103 @@
|
||||
// Copyright 2019 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/common_funcs.h"
|
||||
#include "common/common_types.h"
|
||||
#include "common/uuid.h"
|
||||
#include "core/hle/service/time/errors.h"
|
||||
#include "core/hle/service/time/time_zone_types.h"
|
||||
|
||||
namespace Service::Time::Clock {
|
||||
|
||||
/// https://switchbrew.org/wiki/Glue_services#SteadyClockTimePoint
|
||||
struct SteadyClockTimePoint {
|
||||
s64 time_point;
|
||||
Common::UUID clock_source_id;
|
||||
|
||||
ResultCode GetSpanBetween(SteadyClockTimePoint other, s64& span) const {
|
||||
span = 0;
|
||||
|
||||
if (clock_source_id != other.clock_source_id) {
|
||||
return ERROR_TIME_MISMATCH;
|
||||
}
|
||||
|
||||
span = other.time_point - time_point;
|
||||
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static SteadyClockTimePoint GetRandom() {
|
||||
return {0, Common::UUID::Generate()};
|
||||
}
|
||||
};
|
||||
static_assert(sizeof(SteadyClockTimePoint) == 0x18, "SteadyClockTimePoint is incorrect size");
|
||||
static_assert(std::is_trivially_copyable_v<SteadyClockTimePoint>,
|
||||
"SteadyClockTimePoint must be trivially copyable");
|
||||
|
||||
struct SteadyClockContext {
|
||||
u64 internal_offset;
|
||||
Common::UUID steady_time_point;
|
||||
};
|
||||
static_assert(sizeof(SteadyClockContext) == 0x18, "SteadyClockContext is incorrect size");
|
||||
static_assert(std::is_trivially_copyable_v<SteadyClockContext>,
|
||||
"SteadyClockContext must be trivially copyable");
|
||||
|
||||
struct SystemClockContext {
|
||||
s64 offset;
|
||||
SteadyClockTimePoint steady_time_point;
|
||||
};
|
||||
static_assert(sizeof(SystemClockContext) == 0x20, "SystemClockContext is incorrect size");
|
||||
static_assert(std::is_trivially_copyable_v<SystemClockContext>,
|
||||
"SystemClockContext must be trivially copyable");
|
||||
|
||||
/// https://switchbrew.org/wiki/Glue_services#TimeSpanType
|
||||
struct TimeSpanType {
|
||||
s64 nanoseconds{};
|
||||
static constexpr s64 ns_per_second{1000000000ULL};
|
||||
|
||||
s64 ToSeconds() const {
|
||||
return nanoseconds / ns_per_second;
|
||||
}
|
||||
|
||||
static TimeSpanType FromSeconds(s64 seconds) {
|
||||
return {seconds * ns_per_second};
|
||||
}
|
||||
|
||||
static TimeSpanType FromTicks(u64 ticks, u64 frequency) {
|
||||
return FromSeconds(static_cast<s64>(ticks) / static_cast<s64>(frequency));
|
||||
}
|
||||
};
|
||||
static_assert(sizeof(TimeSpanType) == 8, "TimeSpanType is incorrect size");
|
||||
|
||||
struct ClockSnapshot {
|
||||
SystemClockContext user_context{};
|
||||
SystemClockContext network_context{};
|
||||
s64 user_time{};
|
||||
s64 network_time{};
|
||||
TimeZone::CalendarTime user_calendar_time{};
|
||||
TimeZone::CalendarTime network_calendar_time{};
|
||||
TimeZone::CalendarAdditionalInfo user_calendar_additional_time{};
|
||||
TimeZone::CalendarAdditionalInfo network_calendar_additional_time{};
|
||||
SteadyClockTimePoint steady_clock_time_point{};
|
||||
TimeZone::LocationName location_name{};
|
||||
u8 is_automatic_correction_enabled{};
|
||||
u8 type{};
|
||||
INSERT_PADDING_BYTES(0x2);
|
||||
|
||||
static ResultCode GetCurrentTime(s64& current_time,
|
||||
const SteadyClockTimePoint& steady_clock_time_point,
|
||||
const SystemClockContext& context) {
|
||||
if (steady_clock_time_point.clock_source_id != context.steady_time_point.clock_source_id) {
|
||||
current_time = 0;
|
||||
return ERROR_TIME_MISMATCH;
|
||||
}
|
||||
current_time = steady_clock_time_point.time_point + context.offset;
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
};
|
||||
static_assert(sizeof(ClockSnapshot) == 0xD0, "ClockSnapshot is incorrect size");
|
||||
|
||||
} // namespace Service::Time::Clock
|
||||
@@ -0,0 +1,16 @@
|
||||
// Copyright 2019 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/time/system_clock_context_update_callback.h"
|
||||
|
||||
namespace Service::Time::Clock {
|
||||
|
||||
class EphemeralNetworkSystemClockContextWriter final : public SystemClockContextUpdateCallback {
|
||||
public:
|
||||
EphemeralNetworkSystemClockContextWriter() : SystemClockContextUpdateCallback{} {}
|
||||
};
|
||||
|
||||
} // namespace Service::Time::Clock
|
||||
@@ -0,0 +1,17 @@
|
||||
// Copyright 2019 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/time/system_clock_core.h"
|
||||
|
||||
namespace Service::Time::Clock {
|
||||
|
||||
class EphemeralNetworkSystemClockCore final : public SystemClockCore {
|
||||
public:
|
||||
explicit EphemeralNetworkSystemClockCore(SteadyClockCore& steady_clock_core)
|
||||
: SystemClockCore{steady_clock_core} {}
|
||||
};
|
||||
|
||||
} // namespace Service::Time::Clock
|
||||
22
src/core/hle/service/time/errors.h
Normal file
22
src/core/hle/service/time/errors.h
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright 2019 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/result.h"
|
||||
|
||||
namespace Service::Time {
|
||||
|
||||
constexpr ResultCode ERROR_PERMISSION_DENIED{ErrorModule::Time, 1};
|
||||
constexpr ResultCode ERROR_TIME_MISMATCH{ErrorModule::Time, 102};
|
||||
constexpr ResultCode ERROR_UNINITIALIZED_CLOCK{ErrorModule::Time, 103};
|
||||
constexpr ResultCode ERROR_TIME_NOT_FOUND{ErrorModule::Time, 200};
|
||||
constexpr ResultCode ERROR_OVERFLOW{ErrorModule::Time, 201};
|
||||
constexpr ResultCode ERROR_LOCATION_NAME_TOO_LONG{ErrorModule::Time, 801};
|
||||
constexpr ResultCode ERROR_OUT_OF_RANGE{ErrorModule::Time, 902};
|
||||
constexpr ResultCode ERROR_TIME_ZONE_CONVERSION_FAILED{ErrorModule::Time, 903};
|
||||
constexpr ResultCode ERROR_TIME_ZONE_NOT_FOUND{ErrorModule::Time, 989};
|
||||
constexpr ResultCode ERROR_NOT_IMPLEMENTED{ErrorModule::Time, 990};
|
||||
|
||||
} // namespace Service::Time
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Copyright 2019 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
@@ -6,9 +6,8 @@
|
||||
|
||||
namespace Service::Time {
|
||||
|
||||
Time::Time(std::shared_ptr<Module> time, std::shared_ptr<SharedMemory> shared_memory,
|
||||
Core::System& system, const char* name)
|
||||
: Module::Interface(std::move(time), std::move(shared_memory), system, name) {
|
||||
Time::Time(std::shared_ptr<Module> module, Core::System& system, const char* name)
|
||||
: Module::Interface(std::move(module), system, name) {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &Time::GetStandardUserSystemClock, "GetStandardUserSystemClock"},
|
||||
@@ -22,15 +21,15 @@ Time::Time(std::shared_ptr<Module> time, std::shared_ptr<SharedMemory> shared_me
|
||||
{31, nullptr, "GetEphemeralNetworkClockOperationEventReadableHandle"},
|
||||
{50, nullptr, "SetStandardSteadyClockInternalOffset"},
|
||||
{51, nullptr, "GetStandardSteadyClockRtcValue"},
|
||||
{100, &Time::IsStandardUserSystemClockAutomaticCorrectionEnabled, "IsStandardUserSystemClockAutomaticCorrectionEnabled"},
|
||||
{101, &Time::SetStandardUserSystemClockAutomaticCorrectionEnabled, "SetStandardUserSystemClockAutomaticCorrectionEnabled"},
|
||||
{100, nullptr, "IsStandardUserSystemClockAutomaticCorrectionEnabled"},
|
||||
{101, nullptr, "SetStandardUserSystemClockAutomaticCorrectionEnabled"},
|
||||
{102, nullptr, "GetStandardUserSystemClockInitialYear"},
|
||||
{200, nullptr, "IsStandardNetworkSystemClockAccuracySufficient"},
|
||||
{200, &Time::IsStandardNetworkSystemClockAccuracySufficient, "IsStandardNetworkSystemClockAccuracySufficient"},
|
||||
{201, nullptr, "GetStandardUserSystemClockAutomaticCorrectionUpdatedTime"},
|
||||
{300, nullptr, "CalculateMonotonicSystemClockBaseTimePoint"},
|
||||
{300, &Time::CalculateMonotonicSystemClockBaseTimePoint, "CalculateMonotonicSystemClockBaseTimePoint"},
|
||||
{400, &Time::GetClockSnapshot, "GetClockSnapshot"},
|
||||
{401, nullptr, "GetClockSnapshotFromSystemClockContext"},
|
||||
{500, &Time::CalculateStandardUserSystemClockDifferenceByUser, "CalculateStandardUserSystemClockDifferenceByUser"},
|
||||
{401, &Time::GetClockSnapshotFromSystemClockContext, "GetClockSnapshotFromSystemClockContext"},
|
||||
{500, nullptr, "CalculateStandardUserSystemClockDifferenceByUser"},
|
||||
{501, nullptr, "CalculateSpanBetween"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Copyright 2019 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
@@ -6,14 +6,15 @@
|
||||
|
||||
#include "core/hle/service/time/time.h"
|
||||
|
||||
namespace Service::Time {
|
||||
namespace Core {
|
||||
class System;
|
||||
}
|
||||
|
||||
class SharedMemory;
|
||||
namespace Service::Time {
|
||||
|
||||
class Time final : public Module::Interface {
|
||||
public:
|
||||
explicit Time(std::shared_ptr<Module> time, std::shared_ptr<SharedMemory> shared_memory,
|
||||
Core::System& system, const char* name);
|
||||
explicit Time(std::shared_ptr<Module> time, Core::System& system, const char* name);
|
||||
~Time() override;
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
// Copyright 2019 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/time/errors.h"
|
||||
#include "core/hle/service/time/system_clock_context_update_callback.h"
|
||||
#include "core/hle/service/time/time_sharedmemory.h"
|
||||
|
||||
namespace Service::Time::Clock {
|
||||
|
||||
class LocalSystemClockContextWriter final : public SystemClockContextUpdateCallback {
|
||||
public:
|
||||
explicit LocalSystemClockContextWriter(SharedMemory& shared_memory)
|
||||
: SystemClockContextUpdateCallback{}, shared_memory{shared_memory} {}
|
||||
|
||||
protected:
|
||||
ResultCode Update() override {
|
||||
shared_memory.UpdateLocalSystemClockContext(context);
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
private:
|
||||
SharedMemory& shared_memory;
|
||||
};
|
||||
|
||||
} // namespace Service::Time::Clock
|
||||
@@ -0,0 +1,28 @@
|
||||
// Copyright 2019 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/time/errors.h"
|
||||
#include "core/hle/service/time/system_clock_context_update_callback.h"
|
||||
#include "core/hle/service/time/time_sharedmemory.h"
|
||||
|
||||
namespace Service::Time::Clock {
|
||||
|
||||
class NetworkSystemClockContextWriter final : public SystemClockContextUpdateCallback {
|
||||
public:
|
||||
explicit NetworkSystemClockContextWriter(SharedMemory& shared_memory)
|
||||
: SystemClockContextUpdateCallback{}, shared_memory{shared_memory} {}
|
||||
|
||||
protected:
|
||||
ResultCode Update() override {
|
||||
shared_memory.UpdateNetworkSystemClockContext(context);
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
private:
|
||||
SharedMemory& shared_memory;
|
||||
};
|
||||
|
||||
} // namespace Service::Time::Clock
|
||||
17
src/core/hle/service/time/standard_local_system_clock_core.h
Normal file
17
src/core/hle/service/time/standard_local_system_clock_core.h
Normal file
@@ -0,0 +1,17 @@
|
||||
// Copyright 2019 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/time/system_clock_core.h"
|
||||
|
||||
namespace Service::Time::Clock {
|
||||
|
||||
class StandardLocalSystemClockCore final : public SystemClockCore {
|
||||
public:
|
||||
explicit StandardLocalSystemClockCore(SteadyClockCore& steady_clock_core)
|
||||
: SystemClockCore{steady_clock_core} {}
|
||||
};
|
||||
|
||||
} // namespace Service::Time::Clock
|
||||
@@ -0,0 +1,46 @@
|
||||
// Copyright 2019 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/time/clock_types.h"
|
||||
#include "core/hle/service/time/steady_clock_core.h"
|
||||
#include "core/hle/service/time/system_clock_core.h"
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
}
|
||||
|
||||
namespace Service::Time::Clock {
|
||||
|
||||
class StandardNetworkSystemClockCore final : public SystemClockCore {
|
||||
public:
|
||||
explicit StandardNetworkSystemClockCore(SteadyClockCore& steady_clock_core)
|
||||
: SystemClockCore{steady_clock_core} {}
|
||||
|
||||
void SetStandardNetworkClockSufficientAccuracy(TimeSpanType value) {
|
||||
standard_network_clock_sufficient_accuracy = value;
|
||||
}
|
||||
|
||||
bool IsStandardNetworkSystemClockAccuracySufficient(Core::System& system) {
|
||||
SystemClockContext context{};
|
||||
if (GetClockContext(system, context) != RESULT_SUCCESS) {
|
||||
return {};
|
||||
}
|
||||
|
||||
s64 span{};
|
||||
if (context.steady_time_point.GetSpanBetween(
|
||||
GetSteadyClockCore().GetCurrentTimePoint(system), span) != RESULT_SUCCESS) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return TimeSpanType{span}.nanoseconds <
|
||||
standard_network_clock_sufficient_accuracy.nanoseconds;
|
||||
}
|
||||
|
||||
private:
|
||||
TimeSpanType standard_network_clock_sufficient_accuracy{};
|
||||
};
|
||||
|
||||
} // namespace Service::Time::Clock
|
||||
26
src/core/hle/service/time/standard_steady_clock_core.cpp
Normal file
26
src/core/hle/service/time/standard_steady_clock_core.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
// Copyright 2019 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/core.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/core_timing_util.h"
|
||||
#include "core/hle/service/time/standard_steady_clock_core.h"
|
||||
|
||||
namespace Service::Time::Clock {
|
||||
|
||||
TimeSpanType StandardSteadyClockCore::GetCurrentRawTimePoint(Core::System& system) {
|
||||
const TimeSpanType ticks_time_span{TimeSpanType::FromTicks(
|
||||
Core::Timing::CpuCyclesToClockCycles(system.CoreTiming().GetTicks()),
|
||||
Core::Timing::CNTFREQ)};
|
||||
TimeSpanType raw_time_point{setup_value.nanoseconds + ticks_time_span.nanoseconds};
|
||||
|
||||
if (raw_time_point.nanoseconds < cached_raw_time_point.nanoseconds) {
|
||||
raw_time_point.nanoseconds = cached_raw_time_point.nanoseconds;
|
||||
}
|
||||
|
||||
cached_raw_time_point = raw_time_point;
|
||||
return raw_time_point;
|
||||
}
|
||||
|
||||
} // namespace Service::Time::Clock
|
||||
42
src/core/hle/service/time/standard_steady_clock_core.h
Normal file
42
src/core/hle/service/time/standard_steady_clock_core.h
Normal file
@@ -0,0 +1,42 @@
|
||||
// Copyright 2019 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/time/clock_types.h"
|
||||
#include "core/hle/service/time/steady_clock_core.h"
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
}
|
||||
|
||||
namespace Service::Time::Clock {
|
||||
|
||||
class StandardSteadyClockCore final : public SteadyClockCore {
|
||||
public:
|
||||
SteadyClockTimePoint GetTimePoint(Core::System& system) override {
|
||||
return {GetCurrentRawTimePoint(system).ToSeconds(), GetClockSourceId()};
|
||||
}
|
||||
|
||||
TimeSpanType GetInternalOffset() const override {
|
||||
return internal_offset;
|
||||
}
|
||||
|
||||
void SetInternalOffset(TimeSpanType value) override {
|
||||
internal_offset = value;
|
||||
}
|
||||
|
||||
TimeSpanType GetCurrentRawTimePoint(Core::System& system) override;
|
||||
|
||||
void SetSetupValue(TimeSpanType value) {
|
||||
setup_value = value;
|
||||
}
|
||||
|
||||
private:
|
||||
TimeSpanType setup_value{};
|
||||
TimeSpanType internal_offset{};
|
||||
TimeSpanType cached_raw_time_point{};
|
||||
};
|
||||
|
||||
} // namespace Service::Time::Clock
|
||||
@@ -0,0 +1,77 @@
|
||||
// Copyright 2019 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "core/core.h"
|
||||
#include "core/hle/kernel/writable_event.h"
|
||||
#include "core/hle/service/time/standard_local_system_clock_core.h"
|
||||
#include "core/hle/service/time/standard_network_system_clock_core.h"
|
||||
#include "core/hle/service/time/standard_user_system_clock_core.h"
|
||||
|
||||
namespace Service::Time::Clock {
|
||||
|
||||
StandardUserSystemClockCore::StandardUserSystemClockCore(
|
||||
StandardLocalSystemClockCore& local_system_clock_core,
|
||||
StandardNetworkSystemClockCore& network_system_clock_core, Core::System& system)
|
||||
: SystemClockCore(local_system_clock_core.GetSteadyClockCore()),
|
||||
local_system_clock_core{local_system_clock_core},
|
||||
network_system_clock_core{network_system_clock_core}, auto_correction_enabled{},
|
||||
auto_correction_time{SteadyClockTimePoint::GetRandom()},
|
||||
auto_correction_event{Kernel::WritableEvent::CreateEventPair(
|
||||
system.Kernel(), "StandardUserSystemClockCore:AutoCorrectionEvent")} {}
|
||||
|
||||
ResultCode StandardUserSystemClockCore::SetAutomaticCorrectionEnabled(Core::System& system,
|
||||
bool value) {
|
||||
if (const ResultCode result{ApplyAutomaticCorrection(system, value)};
|
||||
result != RESULT_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
|
||||
auto_correction_enabled = value;
|
||||
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
ResultCode StandardUserSystemClockCore::GetClockContext(Core::System& system,
|
||||
SystemClockContext& context) const {
|
||||
if (const ResultCode result{ApplyAutomaticCorrection(system, false)};
|
||||
result != RESULT_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return local_system_clock_core.GetClockContext(system, context);
|
||||
}
|
||||
|
||||
ResultCode StandardUserSystemClockCore::Flush(const SystemClockContext& context) {
|
||||
UNREACHABLE();
|
||||
return ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
ResultCode StandardUserSystemClockCore::SetClockContext(const SystemClockContext& context) {
|
||||
UNREACHABLE();
|
||||
return ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
ResultCode StandardUserSystemClockCore::ApplyAutomaticCorrection(Core::System& system,
|
||||
bool value) const {
|
||||
if (auto_correction_enabled == value) {
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
if (!network_system_clock_core.IsClockSetup(system)) {
|
||||
return ERROR_UNINITIALIZED_CLOCK;
|
||||
}
|
||||
|
||||
SystemClockContext context{};
|
||||
if (const ResultCode result{network_system_clock_core.GetClockContext(system, context)};
|
||||
result != RESULT_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
|
||||
local_system_clock_core.SetClockContext(context);
|
||||
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace Service::Time::Clock
|
||||
57
src/core/hle/service/time/standard_user_system_clock_core.h
Normal file
57
src/core/hle/service/time/standard_user_system_clock_core.h
Normal file
@@ -0,0 +1,57 @@
|
||||
// Copyright 2019 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/kernel/writable_event.h"
|
||||
#include "core/hle/service/time/clock_types.h"
|
||||
#include "core/hle/service/time/system_clock_core.h"
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
}
|
||||
|
||||
namespace Service::Time::Clock {
|
||||
|
||||
class StandardLocalSystemClockCore;
|
||||
class StandardNetworkSystemClockCore;
|
||||
|
||||
class StandardUserSystemClockCore final : public SystemClockCore {
|
||||
public:
|
||||
StandardUserSystemClockCore(StandardLocalSystemClockCore& local_system_clock_core,
|
||||
StandardNetworkSystemClockCore& network_system_clock_core,
|
||||
Core::System& system);
|
||||
|
||||
ResultCode SetAutomaticCorrectionEnabled(Core::System& system, bool value);
|
||||
|
||||
ResultCode GetClockContext(Core::System& system, SystemClockContext& context) const override;
|
||||
|
||||
bool IsAutomaticCorrectionEnabled() const {
|
||||
return auto_correction_enabled;
|
||||
}
|
||||
|
||||
void SetAutomaticCorrectionUpdatedTime(SteadyClockTimePoint steady_clock_time_point) {
|
||||
auto_correction_time = steady_clock_time_point;
|
||||
}
|
||||
|
||||
protected:
|
||||
ResultCode Flush(const SystemClockContext& context) override;
|
||||
|
||||
ResultCode SetClockContext(const SystemClockContext&) override;
|
||||
|
||||
ResultCode ApplyAutomaticCorrection(Core::System& system, bool value) const;
|
||||
|
||||
const SteadyClockTimePoint& GetAutomaticCorrectionUpdatedTime() const {
|
||||
return auto_correction_time;
|
||||
}
|
||||
|
||||
private:
|
||||
StandardLocalSystemClockCore& local_system_clock_core;
|
||||
StandardNetworkSystemClockCore& network_system_clock_core;
|
||||
bool auto_correction_enabled{};
|
||||
SteadyClockTimePoint auto_correction_time;
|
||||
Kernel::EventPair auto_correction_event;
|
||||
};
|
||||
|
||||
} // namespace Service::Time::Clock
|
||||
55
src/core/hle/service/time/steady_clock_core.h
Normal file
55
src/core/hle/service/time/steady_clock_core.h
Normal file
@@ -0,0 +1,55 @@
|
||||
// Copyright 2019 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/uuid.h"
|
||||
#include "core/hle/service/time/clock_types.h"
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
}
|
||||
|
||||
namespace Service::Time::Clock {
|
||||
|
||||
class SteadyClockCore {
|
||||
public:
|
||||
SteadyClockCore() = default;
|
||||
|
||||
const Common::UUID& GetClockSourceId() const {
|
||||
return clock_source_id;
|
||||
}
|
||||
|
||||
void SetClockSourceId(const Common::UUID& value) {
|
||||
clock_source_id = value;
|
||||
}
|
||||
|
||||
virtual TimeSpanType GetInternalOffset() const = 0;
|
||||
|
||||
virtual void SetInternalOffset(TimeSpanType internal_offset) = 0;
|
||||
|
||||
virtual SteadyClockTimePoint GetTimePoint(Core::System& system) = 0;
|
||||
|
||||
virtual TimeSpanType GetCurrentRawTimePoint(Core::System& system) = 0;
|
||||
|
||||
SteadyClockTimePoint GetCurrentTimePoint(Core::System& system) {
|
||||
SteadyClockTimePoint result{GetTimePoint(system)};
|
||||
result.time_point += GetInternalOffset().ToSeconds();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool IsInitialized() const {
|
||||
return is_initialized;
|
||||
}
|
||||
|
||||
void MarkAsInitialized() {
|
||||
is_initialized = true;
|
||||
}
|
||||
|
||||
private:
|
||||
Common::UUID clock_source_id{Common::UUID::Generate()};
|
||||
bool is_initialized{};
|
||||
};
|
||||
|
||||
} // namespace Service::Time::Clock
|
||||
@@ -0,0 +1,55 @@
|
||||
// Copyright 2019 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/hle/kernel/writable_event.h"
|
||||
#include "core/hle/service/time/errors.h"
|
||||
#include "core/hle/service/time/system_clock_context_update_callback.h"
|
||||
|
||||
namespace Service::Time::Clock {
|
||||
|
||||
SystemClockContextUpdateCallback::SystemClockContextUpdateCallback() = default;
|
||||
SystemClockContextUpdateCallback::~SystemClockContextUpdateCallback() = default;
|
||||
|
||||
bool SystemClockContextUpdateCallback::NeedUpdate(const SystemClockContext& value) const {
|
||||
if (has_context) {
|
||||
return context.offset != value.offset ||
|
||||
context.steady_time_point.clock_source_id != value.steady_time_point.clock_source_id;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SystemClockContextUpdateCallback::RegisterOperationEvent(
|
||||
std::shared_ptr<Kernel::WritableEvent>&& writable_event) {
|
||||
operation_event_list.emplace_back(std::move(writable_event));
|
||||
}
|
||||
|
||||
void SystemClockContextUpdateCallback::BroadcastOperationEvent() {
|
||||
for (const auto& writable_event : operation_event_list) {
|
||||
writable_event->Signal();
|
||||
}
|
||||
}
|
||||
|
||||
ResultCode SystemClockContextUpdateCallback::Update(const SystemClockContext& value) {
|
||||
ResultCode result{RESULT_SUCCESS};
|
||||
|
||||
if (NeedUpdate(value)) {
|
||||
context = value;
|
||||
has_context = true;
|
||||
|
||||
result = Update();
|
||||
|
||||
if (result == RESULT_SUCCESS) {
|
||||
BroadcastOperationEvent();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ResultCode SystemClockContextUpdateCallback::Update() {
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace Service::Time::Clock
|
||||
@@ -0,0 +1,43 @@
|
||||
// Copyright 2019 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "core/hle/service/time/clock_types.h"
|
||||
|
||||
namespace Kernel {
|
||||
class WritableEvent;
|
||||
}
|
||||
|
||||
namespace Service::Time::Clock {
|
||||
|
||||
// Parts of this implementation were based on Ryujinx (https://github.com/Ryujinx/Ryujinx/pull/783).
|
||||
// This code was released under public domain.
|
||||
|
||||
class SystemClockContextUpdateCallback {
|
||||
public:
|
||||
SystemClockContextUpdateCallback();
|
||||
~SystemClockContextUpdateCallback();
|
||||
|
||||
bool NeedUpdate(const SystemClockContext& value) const;
|
||||
|
||||
void RegisterOperationEvent(std::shared_ptr<Kernel::WritableEvent>&& writable_event);
|
||||
|
||||
void BroadcastOperationEvent();
|
||||
|
||||
ResultCode Update(const SystemClockContext& value);
|
||||
|
||||
protected:
|
||||
virtual ResultCode Update();
|
||||
|
||||
SystemClockContext context{};
|
||||
|
||||
private:
|
||||
bool has_context{};
|
||||
std::vector<std::shared_ptr<Kernel::WritableEvent>> operation_event_list;
|
||||
};
|
||||
|
||||
} // namespace Service::Time::Clock
|
||||
72
src/core/hle/service/time/system_clock_core.cpp
Normal file
72
src/core/hle/service/time/system_clock_core.cpp
Normal file
@@ -0,0 +1,72 @@
|
||||
// Copyright 2019 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/hle/service/time/steady_clock_core.h"
|
||||
#include "core/hle/service/time/system_clock_context_update_callback.h"
|
||||
#include "core/hle/service/time/system_clock_core.h"
|
||||
|
||||
namespace Service::Time::Clock {
|
||||
|
||||
SystemClockCore::SystemClockCore(SteadyClockCore& steady_clock_core)
|
||||
: steady_clock_core{steady_clock_core}, is_initialized{} {
|
||||
context.steady_time_point.clock_source_id = steady_clock_core.GetClockSourceId();
|
||||
}
|
||||
|
||||
SystemClockCore ::~SystemClockCore() = default;
|
||||
|
||||
ResultCode SystemClockCore::GetCurrentTime(Core::System& system, s64& posix_time) const {
|
||||
posix_time = 0;
|
||||
|
||||
const SteadyClockTimePoint current_time_point{steady_clock_core.GetCurrentTimePoint(system)};
|
||||
|
||||
SystemClockContext clock_context{};
|
||||
if (const ResultCode result{GetClockContext(system, clock_context)}; result != RESULT_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (current_time_point.clock_source_id != clock_context.steady_time_point.clock_source_id) {
|
||||
return ERROR_TIME_MISMATCH;
|
||||
}
|
||||
|
||||
posix_time = clock_context.offset + current_time_point.time_point;
|
||||
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
ResultCode SystemClockCore::SetCurrentTime(Core::System& system, s64 posix_time) {
|
||||
const SteadyClockTimePoint current_time_point{steady_clock_core.GetCurrentTimePoint(system)};
|
||||
const SystemClockContext clock_context{posix_time - current_time_point.time_point,
|
||||
current_time_point};
|
||||
|
||||
if (const ResultCode result{SetClockContext(clock_context)}; result != RESULT_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
return Flush(clock_context);
|
||||
}
|
||||
|
||||
ResultCode SystemClockCore::Flush(const SystemClockContext& context) {
|
||||
if (!system_clock_context_update_callback) {
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
return system_clock_context_update_callback->Update(context);
|
||||
}
|
||||
|
||||
ResultCode SystemClockCore::SetSystemClockContext(const SystemClockContext& context) {
|
||||
if (const ResultCode result{SetClockContext(context)}; result != RESULT_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
return Flush(context);
|
||||
}
|
||||
|
||||
bool SystemClockCore::IsClockSetup(Core::System& system) const {
|
||||
SystemClockContext value{};
|
||||
if (GetClockContext(system, value) == RESULT_SUCCESS) {
|
||||
const SteadyClockTimePoint steady_clock_time_point{
|
||||
steady_clock_core.GetCurrentTimePoint(system)};
|
||||
return steady_clock_time_point.clock_source_id == value.steady_time_point.clock_source_id;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
} // namespace Service::Time::Clock
|
||||
71
src/core/hle/service/time/system_clock_core.h
Normal file
71
src/core/hle/service/time/system_clock_core.h
Normal file
@@ -0,0 +1,71 @@
|
||||
// Copyright 2019 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "core/hle/service/time/clock_types.h"
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
}
|
||||
|
||||
namespace Service::Time::Clock {
|
||||
|
||||
class SteadyClockCore;
|
||||
class SystemClockContextUpdateCallback;
|
||||
|
||||
// Parts of this implementation were based on Ryujinx (https://github.com/Ryujinx/Ryujinx/pull/783).
|
||||
// This code was released under public domain.
|
||||
|
||||
class SystemClockCore {
|
||||
public:
|
||||
explicit SystemClockCore(SteadyClockCore& steady_clock_core);
|
||||
~SystemClockCore();
|
||||
|
||||
SteadyClockCore& GetSteadyClockCore() const {
|
||||
return steady_clock_core;
|
||||
}
|
||||
|
||||
ResultCode GetCurrentTime(Core::System& system, s64& posix_time) const;
|
||||
|
||||
ResultCode SetCurrentTime(Core::System& system, s64 posix_time);
|
||||
|
||||
virtual ResultCode GetClockContext([[maybe_unused]] Core::System& system,
|
||||
SystemClockContext& value) const {
|
||||
value = context;
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
virtual ResultCode SetClockContext(const SystemClockContext& value) {
|
||||
context = value;
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
virtual ResultCode Flush(const SystemClockContext& context);
|
||||
|
||||
void SetUpdateCallbackInstance(std::shared_ptr<SystemClockContextUpdateCallback> callback) {
|
||||
system_clock_context_update_callback = std::move(callback);
|
||||
}
|
||||
|
||||
ResultCode SetSystemClockContext(const SystemClockContext& context);
|
||||
|
||||
bool IsInitialized() const {
|
||||
return is_initialized;
|
||||
}
|
||||
|
||||
void MarkAsInitialized() {
|
||||
is_initialized = true;
|
||||
}
|
||||
|
||||
bool IsClockSetup(Core::System& system) const;
|
||||
|
||||
private:
|
||||
SteadyClockCore& steady_clock_core;
|
||||
SystemClockContext context{};
|
||||
bool is_initialized{};
|
||||
std::shared_ptr<SystemClockContextUpdateCallback> system_clock_context_update_callback;
|
||||
};
|
||||
|
||||
} // namespace Service::Time::Clock
|
||||
24
src/core/hle/service/time/tick_based_steady_clock_core.cpp
Normal file
24
src/core/hle/service/time/tick_based_steady_clock_core.cpp
Normal file
@@ -0,0 +1,24 @@
|
||||
// Copyright 2020 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/core.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/core_timing_util.h"
|
||||
#include "core/hle/service/time/tick_based_steady_clock_core.h"
|
||||
|
||||
namespace Service::Time::Clock {
|
||||
|
||||
SteadyClockTimePoint TickBasedSteadyClockCore::GetTimePoint(Core::System& system) {
|
||||
const TimeSpanType ticks_time_span{TimeSpanType::FromTicks(
|
||||
Core::Timing::CpuCyclesToClockCycles(system.CoreTiming().GetTicks()),
|
||||
Core::Timing::CNTFREQ)};
|
||||
|
||||
return {ticks_time_span.ToSeconds(), GetClockSourceId()};
|
||||
}
|
||||
|
||||
TimeSpanType TickBasedSteadyClockCore::GetCurrentRawTimePoint(Core::System& system) {
|
||||
return TimeSpanType::FromSeconds(GetTimePoint(system).time_point);
|
||||
}
|
||||
|
||||
} // namespace Service::Time::Clock
|
||||
29
src/core/hle/service/time/tick_based_steady_clock_core.h
Normal file
29
src/core/hle/service/time/tick_based_steady_clock_core.h
Normal file
@@ -0,0 +1,29 @@
|
||||
// Copyright 2020 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/time/clock_types.h"
|
||||
#include "core/hle/service/time/steady_clock_core.h"
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
}
|
||||
|
||||
namespace Service::Time::Clock {
|
||||
|
||||
class TickBasedSteadyClockCore final : public SteadyClockCore {
|
||||
public:
|
||||
TimeSpanType GetInternalOffset() const override {
|
||||
return {};
|
||||
}
|
||||
|
||||
void SetInternalOffset(TimeSpanType internal_offset) override {}
|
||||
|
||||
SteadyClockTimePoint GetTimePoint(Core::System& system) override;
|
||||
|
||||
TimeSpanType GetCurrentRawTimePoint(Core::System& system) override;
|
||||
};
|
||||
|
||||
} // namespace Service::Time::Clock
|
||||
@@ -1,9 +1,7 @@
|
||||
// Copyright 2018 yuzu emulator team
|
||||
// Copyright 2019 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <chrono>
|
||||
#include <ctime>
|
||||
#include "common/logging/log.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_timing.h"
|
||||
@@ -11,429 +9,321 @@
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/kernel/client_port.h"
|
||||
#include "core/hle/kernel/client_session.h"
|
||||
#include "core/hle/kernel/scheduler.h"
|
||||
#include "core/hle/service/time/interface.h"
|
||||
#include "core/hle/service/time/time.h"
|
||||
#include "core/hle/service/time/time_sharedmemory.h"
|
||||
#include "core/settings.h"
|
||||
#include "core/hle/service/time/time_zone_service.h"
|
||||
|
||||
namespace Service::Time {
|
||||
|
||||
static std::chrono::seconds GetSecondsSinceEpoch() {
|
||||
return std::chrono::duration_cast<std::chrono::seconds>(
|
||||
std::chrono::system_clock::now().time_since_epoch()) +
|
||||
Settings::values.custom_rtc_differential;
|
||||
}
|
||||
|
||||
static void PosixToCalendar(u64 posix_time, CalendarTime& calendar_time,
|
||||
CalendarAdditionalInfo& additional_info,
|
||||
[[maybe_unused]] const TimeZoneRule& /*rule*/) {
|
||||
const std::time_t time(posix_time);
|
||||
const std::tm* tm = std::localtime(&time);
|
||||
if (tm == nullptr) {
|
||||
calendar_time = {};
|
||||
additional_info = {};
|
||||
return;
|
||||
}
|
||||
calendar_time.year = static_cast<u16_le>(tm->tm_year + 1900);
|
||||
calendar_time.month = static_cast<u8>(tm->tm_mon + 1);
|
||||
calendar_time.day = static_cast<u8>(tm->tm_mday);
|
||||
calendar_time.hour = static_cast<u8>(tm->tm_hour);
|
||||
calendar_time.minute = static_cast<u8>(tm->tm_min);
|
||||
calendar_time.second = static_cast<u8>(tm->tm_sec);
|
||||
|
||||
additional_info.day_of_week = tm->tm_wday;
|
||||
additional_info.day_of_year = tm->tm_yday;
|
||||
std::memcpy(additional_info.name.data(), "UTC", sizeof("UTC"));
|
||||
additional_info.utc_offset = 0;
|
||||
}
|
||||
|
||||
static u64 CalendarToPosix(const CalendarTime& calendar_time,
|
||||
[[maybe_unused]] const TimeZoneRule& /*rule*/) {
|
||||
std::tm time{};
|
||||
time.tm_year = calendar_time.year - 1900;
|
||||
time.tm_mon = calendar_time.month - 1;
|
||||
time.tm_mday = calendar_time.day;
|
||||
|
||||
time.tm_hour = calendar_time.hour;
|
||||
time.tm_min = calendar_time.minute;
|
||||
time.tm_sec = calendar_time.second;
|
||||
|
||||
std::time_t epoch_time = std::mktime(&time);
|
||||
return static_cast<u64>(epoch_time);
|
||||
}
|
||||
|
||||
enum class ClockContextType {
|
||||
StandardSteady,
|
||||
StandardUserSystem,
|
||||
StandardNetworkSystem,
|
||||
StandardLocalSystem,
|
||||
};
|
||||
|
||||
class ISystemClock final : public ServiceFramework<ISystemClock> {
|
||||
public:
|
||||
ISystemClock(std::shared_ptr<Service::Time::SharedMemory> shared_memory,
|
||||
ClockContextType clock_type)
|
||||
: ServiceFramework("ISystemClock"), shared_memory(shared_memory), clock_type(clock_type) {
|
||||
ISystemClock(Clock::SystemClockCore& clock_core)
|
||||
: ServiceFramework("ISystemClock"), clock_core{clock_core} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &ISystemClock::GetCurrentTime, "GetCurrentTime"},
|
||||
{1, nullptr, "SetCurrentTime"},
|
||||
{2, &ISystemClock::GetSystemClockContext, "GetSystemClockContext"},
|
||||
{2, &ISystemClock::GetSystemClockContext, "GetSystemClockContext"},
|
||||
{3, nullptr, "SetSystemClockContext"},
|
||||
{4, nullptr, "GetOperationEventReadableHandle"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
UpdateSharedMemoryContext(system_clock_context);
|
||||
}
|
||||
|
||||
private:
|
||||
void GetCurrentTime(Kernel::HLERequestContext& ctx) {
|
||||
const s64 time_since_epoch{GetSecondsSinceEpoch().count()};
|
||||
LOG_DEBUG(Service_Time, "called");
|
||||
|
||||
if (!clock_core.IsInitialized()) {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ERROR_UNINITIALIZED_CLOCK);
|
||||
return;
|
||||
}
|
||||
|
||||
s64 posix_time{};
|
||||
if (const ResultCode result{
|
||||
clock_core.GetCurrentTime(Core::System::GetInstance(), posix_time)};
|
||||
result != RESULT_SUCCESS) {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(result);
|
||||
return;
|
||||
}
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push<u64>(time_since_epoch);
|
||||
rb.Push<s64>(posix_time);
|
||||
}
|
||||
|
||||
void GetSystemClockContext(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_Time, "(STUBBED) called");
|
||||
LOG_DEBUG(Service_Time, "called");
|
||||
|
||||
// TODO(ogniK): This should be updated periodically however since we have it stubbed we'll
|
||||
// only update when we get a new context
|
||||
UpdateSharedMemoryContext(system_clock_context);
|
||||
if (!clock_core.IsInitialized()) {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ERROR_UNINITIALIZED_CLOCK);
|
||||
return;
|
||||
}
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, (sizeof(SystemClockContext) / 4) + 2};
|
||||
Clock::SystemClockContext system_clock_context{};
|
||||
if (const ResultCode result{
|
||||
clock_core.GetClockContext(Core::System::GetInstance(), system_clock_context)};
|
||||
result != RESULT_SUCCESS) {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(result);
|
||||
return;
|
||||
}
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, sizeof(Clock::SystemClockContext) / 4 + 2};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushRaw(system_clock_context);
|
||||
}
|
||||
|
||||
void UpdateSharedMemoryContext(const SystemClockContext& clock_context) {
|
||||
switch (clock_type) {
|
||||
case ClockContextType::StandardLocalSystem:
|
||||
shared_memory->SetStandardLocalSystemClockContext(clock_context);
|
||||
break;
|
||||
case ClockContextType::StandardNetworkSystem:
|
||||
shared_memory->SetStandardNetworkSystemClockContext(clock_context);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SystemClockContext system_clock_context{};
|
||||
std::shared_ptr<Service::Time::SharedMemory> shared_memory;
|
||||
ClockContextType clock_type;
|
||||
Clock::SystemClockCore& clock_core;
|
||||
};
|
||||
|
||||
class ISteadyClock final : public ServiceFramework<ISteadyClock> {
|
||||
public:
|
||||
ISteadyClock(std::shared_ptr<SharedMemory> shared_memory, Core::System& system)
|
||||
: ServiceFramework("ISteadyClock"), shared_memory(shared_memory), system(system) {
|
||||
ISteadyClock(Clock::SteadyClockCore& clock_core)
|
||||
: ServiceFramework("ISteadyClock"), clock_core{clock_core} {
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &ISteadyClock::GetCurrentTimePoint, "GetCurrentTimePoint"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
|
||||
shared_memory->SetStandardSteadyClockTimepoint(GetCurrentTimePoint());
|
||||
}
|
||||
|
||||
private:
|
||||
void GetCurrentTimePoint(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called");
|
||||
|
||||
const auto time_point = GetCurrentTimePoint();
|
||||
// TODO(ogniK): This should be updated periodically
|
||||
shared_memory->SetStandardSteadyClockTimepoint(time_point);
|
||||
if (!clock_core.IsInitialized()) {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ERROR_UNINITIALIZED_CLOCK);
|
||||
return;
|
||||
}
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, (sizeof(SteadyClockTimePoint) / 4) + 2};
|
||||
const Clock::SteadyClockTimePoint time_point{
|
||||
clock_core.GetCurrentTimePoint(Core::System::GetInstance())};
|
||||
IPC::ResponseBuilder rb{ctx, (sizeof(Clock::SteadyClockTimePoint) / 4) + 2};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushRaw(time_point);
|
||||
}
|
||||
|
||||
SteadyClockTimePoint GetCurrentTimePoint() const {
|
||||
const auto& core_timing = system.CoreTiming();
|
||||
const auto ms = Core::Timing::CyclesToMs(core_timing.GetTicks());
|
||||
return {static_cast<u64_le>(ms.count() / 1000), {}};
|
||||
}
|
||||
|
||||
std::shared_ptr<SharedMemory> shared_memory;
|
||||
Core::System& system;
|
||||
Clock::SteadyClockCore& clock_core;
|
||||
};
|
||||
|
||||
class ITimeZoneService final : public ServiceFramework<ITimeZoneService> {
|
||||
public:
|
||||
ITimeZoneService() : ServiceFramework("ITimeZoneService") {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &ITimeZoneService::GetDeviceLocationName, "GetDeviceLocationName"},
|
||||
{1, nullptr, "SetDeviceLocationName"},
|
||||
{2, &ITimeZoneService::GetTotalLocationNameCount, "GetTotalLocationNameCount"},
|
||||
{3, nullptr, "LoadLocationNameList"},
|
||||
{4, &ITimeZoneService::LoadTimeZoneRule, "LoadTimeZoneRule"},
|
||||
{5, nullptr, "GetTimeZoneRuleVersion"},
|
||||
{6, nullptr, "GetDeviceLocationNameAndUpdatedTime"},
|
||||
{7, nullptr, "SetDeviceLocationNameWithTimeZoneRule"},
|
||||
{8, nullptr, "ParseTimeZoneBinary"},
|
||||
{20, nullptr, "GetDeviceLocationNameOperationEventReadableHandle"},
|
||||
{100, &ITimeZoneService::ToCalendarTime, "ToCalendarTime"},
|
||||
{101, &ITimeZoneService::ToCalendarTimeWithMyRule, "ToCalendarTimeWithMyRule"},
|
||||
{201, &ITimeZoneService::ToPosixTime, "ToPosixTime"},
|
||||
{202, &ITimeZoneService::ToPosixTimeWithMyRule, "ToPosixTimeWithMyRule"},
|
||||
};
|
||||
// clang-format on
|
||||
ResultCode Module::Interface::GetClockSnapshotFromSystemClockContextInternal(
|
||||
Kernel::Thread* thread, Clock::SystemClockContext user_context,
|
||||
Clock::SystemClockContext network_context, u8 type, Clock::ClockSnapshot& clock_snapshot) {
|
||||
|
||||
RegisterHandlers(functions);
|
||||
auto& time_manager{module->GetTimeManager()};
|
||||
|
||||
clock_snapshot.is_automatic_correction_enabled =
|
||||
time_manager.GetStandardUserSystemClockCore().IsAutomaticCorrectionEnabled();
|
||||
clock_snapshot.user_context = user_context;
|
||||
clock_snapshot.network_context = network_context;
|
||||
|
||||
if (const ResultCode result{
|
||||
time_manager.GetTimeZoneContentManager().GetTimeZoneManager().GetDeviceLocationName(
|
||||
clock_snapshot.location_name)};
|
||||
result != RESULT_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
LocationName location_name{"UTC"};
|
||||
TimeZoneRule my_time_zone_rule{};
|
||||
|
||||
void GetDeviceLocationName(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, (sizeof(LocationName) / 4) + 2};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushRaw(location_name);
|
||||
const auto current_time_point{
|
||||
time_manager.GetStandardSteadyClockCore().GetCurrentTimePoint(Core::System::GetInstance())};
|
||||
if (const ResultCode result{Clock::ClockSnapshot::GetCurrentTime(
|
||||
clock_snapshot.user_time, current_time_point, clock_snapshot.user_context)};
|
||||
result != RESULT_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
|
||||
void GetTotalLocationNameCount(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_Time, "(STUBBED) called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push<u32>(0);
|
||||
TimeZone::CalendarInfo userCalendarInfo{};
|
||||
if (const ResultCode result{
|
||||
time_manager.GetTimeZoneContentManager().GetTimeZoneManager().ToCalendarTimeWithMyRules(
|
||||
clock_snapshot.user_time, userCalendarInfo)};
|
||||
result != RESULT_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
|
||||
void LoadTimeZoneRule(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_Time, "(STUBBED) called");
|
||||
clock_snapshot.user_calendar_time = userCalendarInfo.time;
|
||||
clock_snapshot.user_calendar_additional_time = userCalendarInfo.additiona_info;
|
||||
|
||||
ctx.WriteBuffer(&my_time_zone_rule, sizeof(TimeZoneRule));
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
if (Clock::ClockSnapshot::GetCurrentTime(clock_snapshot.network_time, current_time_point,
|
||||
clock_snapshot.network_context) != RESULT_SUCCESS) {
|
||||
clock_snapshot.network_time = 0;
|
||||
}
|
||||
|
||||
void ToCalendarTime(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const u64 posix_time = rp.Pop<u64>();
|
||||
LOG_WARNING(Service_Time, "(STUBBED) called, posix_time=0x{:016X}", posix_time);
|
||||
|
||||
TimeZoneRule time_zone_rule{};
|
||||
auto buffer = ctx.ReadBuffer();
|
||||
std::memcpy(&time_zone_rule, buffer.data(), buffer.size());
|
||||
|
||||
CalendarTime calendar_time{2018, 1, 1, 0, 0, 0};
|
||||
CalendarAdditionalInfo additional_info{};
|
||||
|
||||
PosixToCalendar(posix_time, calendar_time, additional_info, time_zone_rule);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 10};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushRaw(calendar_time);
|
||||
rb.PushRaw(additional_info);
|
||||
TimeZone::CalendarInfo networkCalendarInfo{};
|
||||
if (const ResultCode result{
|
||||
time_manager.GetTimeZoneContentManager().GetTimeZoneManager().ToCalendarTimeWithMyRules(
|
||||
clock_snapshot.network_time, networkCalendarInfo)};
|
||||
result != RESULT_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
|
||||
void ToCalendarTimeWithMyRule(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const u64 posix_time = rp.Pop<u64>();
|
||||
LOG_WARNING(Service_Time, "(STUBBED) called, posix_time=0x{:016X}", posix_time);
|
||||
clock_snapshot.network_calendar_time = networkCalendarInfo.time;
|
||||
clock_snapshot.network_calendar_additional_time = networkCalendarInfo.additiona_info;
|
||||
clock_snapshot.type = type;
|
||||
|
||||
CalendarTime calendar_time{2018, 1, 1, 0, 0, 0};
|
||||
CalendarAdditionalInfo additional_info{};
|
||||
|
||||
PosixToCalendar(posix_time, calendar_time, additional_info, my_time_zone_rule);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 10};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushRaw(calendar_time);
|
||||
rb.PushRaw(additional_info);
|
||||
}
|
||||
|
||||
void ToPosixTime(Kernel::HLERequestContext& ctx) {
|
||||
// TODO(ogniK): Figure out how to handle multiple times
|
||||
LOG_WARNING(Service_Time, "(STUBBED) called");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto calendar_time = rp.PopRaw<CalendarTime>();
|
||||
auto posix_time = CalendarToPosix(calendar_time, {});
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushRaw<u32>(1); // Amount of times we're returning
|
||||
ctx.WriteBuffer(&posix_time, sizeof(u64));
|
||||
}
|
||||
|
||||
void ToPosixTimeWithMyRule(Kernel::HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_Time, "(STUBBED) called");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto calendar_time = rp.PopRaw<CalendarTime>();
|
||||
auto posix_time = CalendarToPosix(calendar_time, {});
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushRaw<u32>(1); // Amount of times we're returning
|
||||
ctx.WriteBuffer(&posix_time, sizeof(u64));
|
||||
}
|
||||
};
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
void Module::Interface::GetStandardUserSystemClock(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushIpcInterface<ISystemClock>(shared_memory, ClockContextType::StandardUserSystem);
|
||||
rb.PushIpcInterface<ISystemClock>(module->GetTimeManager().GetStandardUserSystemClockCore());
|
||||
}
|
||||
|
||||
void Module::Interface::GetStandardNetworkSystemClock(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushIpcInterface<ISystemClock>(shared_memory, ClockContextType::StandardNetworkSystem);
|
||||
rb.PushIpcInterface<ISystemClock>(module->GetTimeManager().GetStandardNetworkSystemClockCore());
|
||||
}
|
||||
|
||||
void Module::Interface::GetStandardSteadyClock(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushIpcInterface<ISteadyClock>(shared_memory, system);
|
||||
rb.PushIpcInterface<ISteadyClock>(module->GetTimeManager().GetStandardSteadyClockCore());
|
||||
}
|
||||
|
||||
void Module::Interface::GetTimeZoneService(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushIpcInterface<ITimeZoneService>();
|
||||
rb.PushIpcInterface<ITimeZoneService>(module->GetTimeManager().GetTimeZoneContentManager());
|
||||
}
|
||||
|
||||
void Module::Interface::GetStandardLocalSystemClock(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushIpcInterface<ISystemClock>(shared_memory, ClockContextType::StandardLocalSystem);
|
||||
rb.PushIpcInterface<ISystemClock>(module->GetTimeManager().GetStandardLocalSystemClockCore());
|
||||
}
|
||||
|
||||
void Module::Interface::IsStandardNetworkSystemClockAccuracySufficient(
|
||||
Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called");
|
||||
auto& clock_core{module->GetTimeManager().GetStandardNetworkSystemClockCore()};
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push<u32>(clock_core.IsStandardNetworkSystemClockAccuracySufficient(system));
|
||||
}
|
||||
|
||||
void Module::Interface::CalculateMonotonicSystemClockBaseTimePoint(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called");
|
||||
|
||||
auto& steady_clock_core{module->GetTimeManager().GetStandardSteadyClockCore()};
|
||||
if (!steady_clock_core.IsInitialized()) {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ERROR_UNINITIALIZED_CLOCK);
|
||||
return;
|
||||
}
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto context{rp.PopRaw<Clock::SystemClockContext>()};
|
||||
const auto current_time_point{
|
||||
steady_clock_core.GetCurrentTimePoint(Core::System::GetInstance())};
|
||||
|
||||
if (current_time_point.clock_source_id == context.steady_time_point.clock_source_id) {
|
||||
const auto ticks{Clock::TimeSpanType::FromTicks(
|
||||
Core::Timing::CpuCyclesToClockCycles(system.CoreTiming().GetTicks()),
|
||||
Core::Timing::CNTFREQ)};
|
||||
const s64 base_time_point{context.offset + current_time_point.time_point -
|
||||
ticks.ToSeconds()};
|
||||
IPC::ResponseBuilder rb{ctx, (sizeof(s64) / 4) + 2};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushRaw(base_time_point);
|
||||
return;
|
||||
}
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ERROR_TIME_MISMATCH);
|
||||
}
|
||||
|
||||
void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto initial_type = rp.PopRaw<u8>();
|
||||
const auto type{rp.PopRaw<u8>()};
|
||||
|
||||
const s64 time_since_epoch{GetSecondsSinceEpoch().count()};
|
||||
const std::time_t time(time_since_epoch);
|
||||
const std::tm* tm = std::localtime(&time);
|
||||
if (tm == nullptr) {
|
||||
LOG_ERROR(Service_Time, "tm is a nullptr");
|
||||
Clock::SystemClockContext user_context{};
|
||||
if (const ResultCode result{
|
||||
module->GetTimeManager().GetStandardUserSystemClockCore().GetClockContext(
|
||||
Core::System::GetInstance(), user_context)};
|
||||
result != RESULT_SUCCESS) {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(RESULT_UNKNOWN); // TODO(ogniK): Find appropriate error code
|
||||
rb.Push(result);
|
||||
return;
|
||||
}
|
||||
Clock::SystemClockContext network_context{};
|
||||
if (const ResultCode result{
|
||||
module->GetTimeManager().GetStandardNetworkSystemClockCore().GetClockContext(
|
||||
Core::System::GetInstance(), network_context)};
|
||||
result != RESULT_SUCCESS) {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(result);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& core_timing = system.CoreTiming();
|
||||
const auto ms = Core::Timing::CyclesToMs(core_timing.GetTicks());
|
||||
const SteadyClockTimePoint steady_clock_time_point{static_cast<u64_le>(ms.count() / 1000), {}};
|
||||
|
||||
CalendarTime calendar_time{};
|
||||
calendar_time.year = static_cast<u16_le>(tm->tm_year + 1900);
|
||||
calendar_time.month = static_cast<u8>(tm->tm_mon + 1);
|
||||
calendar_time.day = static_cast<u8>(tm->tm_mday);
|
||||
calendar_time.hour = static_cast<u8>(tm->tm_hour);
|
||||
calendar_time.minute = static_cast<u8>(tm->tm_min);
|
||||
calendar_time.second = static_cast<u8>(tm->tm_sec);
|
||||
|
||||
ClockSnapshot clock_snapshot{};
|
||||
clock_snapshot.system_posix_time = time_since_epoch;
|
||||
clock_snapshot.network_posix_time = time_since_epoch;
|
||||
clock_snapshot.system_calendar_time = calendar_time;
|
||||
clock_snapshot.network_calendar_time = calendar_time;
|
||||
|
||||
CalendarAdditionalInfo additional_info{};
|
||||
PosixToCalendar(time_since_epoch, calendar_time, additional_info, {});
|
||||
|
||||
clock_snapshot.system_calendar_info = additional_info;
|
||||
clock_snapshot.network_calendar_info = additional_info;
|
||||
|
||||
clock_snapshot.steady_clock_timepoint = steady_clock_time_point;
|
||||
clock_snapshot.location_name = LocationName{"UTC"};
|
||||
clock_snapshot.clock_auto_adjustment_enabled = 1;
|
||||
clock_snapshot.type = initial_type;
|
||||
Clock::ClockSnapshot clock_snapshot{};
|
||||
if (const ResultCode result{GetClockSnapshotFromSystemClockContextInternal(
|
||||
&ctx.GetThread(), user_context, network_context, type, clock_snapshot)};
|
||||
result != RESULT_SUCCESS) {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(result);
|
||||
return;
|
||||
}
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
ctx.WriteBuffer(&clock_snapshot, sizeof(ClockSnapshot));
|
||||
ctx.WriteBuffer(&clock_snapshot, sizeof(Clock::ClockSnapshot));
|
||||
}
|
||||
|
||||
void Module::Interface::CalculateStandardUserSystemClockDifferenceByUser(
|
||||
Kernel::HLERequestContext& ctx) {
|
||||
void Module::Interface::GetClockSnapshotFromSystemClockContext(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto snapshot_a = rp.PopRaw<ClockSnapshot>();
|
||||
const auto snapshot_b = rp.PopRaw<ClockSnapshot>();
|
||||
const u64 difference =
|
||||
snapshot_b.user_clock_context.offset - snapshot_a.user_clock_context.offset;
|
||||
const auto type{rp.PopRaw<u8>()};
|
||||
rp.AlignWithPadding();
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
const Clock::SystemClockContext user_context{rp.PopRaw<Clock::SystemClockContext>()};
|
||||
const Clock::SystemClockContext network_context{rp.PopRaw<Clock::SystemClockContext>()};
|
||||
|
||||
Clock::ClockSnapshot clock_snapshot{};
|
||||
if (const ResultCode result{GetClockSnapshotFromSystemClockContextInternal(
|
||||
&ctx.GetThread(), user_context, network_context, type, clock_snapshot)};
|
||||
result != RESULT_SUCCESS) {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(result);
|
||||
return;
|
||||
}
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushRaw<u64>(difference);
|
||||
ctx.WriteBuffer(&clock_snapshot, sizeof(Clock::ClockSnapshot));
|
||||
}
|
||||
|
||||
void Module::Interface::GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called");
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushCopyObjects(shared_memory->GetSharedMemoryHolder());
|
||||
rb.PushCopyObjects(module->GetTimeManager().GetSharedMemory().GetSharedMemoryHolder());
|
||||
}
|
||||
|
||||
void Module::Interface::IsStandardUserSystemClockAutomaticCorrectionEnabled(
|
||||
Kernel::HLERequestContext& ctx) {
|
||||
// ogniK(TODO): When clock contexts are implemented, the value should be read from the context
|
||||
// instead of our shared memory holder
|
||||
LOG_DEBUG(Service_Time, "called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.Push<u8>(shared_memory->GetStandardUserSystemClockAutomaticCorrectionEnabled());
|
||||
}
|
||||
|
||||
void Module::Interface::SetStandardUserSystemClockAutomaticCorrectionEnabled(
|
||||
Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto enabled = rp.Pop<u8>();
|
||||
|
||||
LOG_WARNING(Service_Time, "(PARTIAL IMPLEMENTATION) called");
|
||||
|
||||
// TODO(ogniK): Update clock contexts and correct timespans
|
||||
|
||||
shared_memory->SetStandardUserSystemClockAutomaticCorrectionEnabled(enabled > 0);
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
}
|
||||
|
||||
Module::Interface::Interface(std::shared_ptr<Module> time,
|
||||
std::shared_ptr<SharedMemory> shared_memory, Core::System& system,
|
||||
const char* name)
|
||||
: ServiceFramework(name), time(std::move(time)), shared_memory(std::move(shared_memory)),
|
||||
system(system) {}
|
||||
Module::Interface::Interface(std::shared_ptr<Module> module, Core::System& system, const char* name)
|
||||
: ServiceFramework(name), module{std::move(module)}, system{system} {}
|
||||
|
||||
Module::Interface::~Interface() = default;
|
||||
|
||||
void InstallInterfaces(Core::System& system) {
|
||||
auto time = std::make_shared<Module>();
|
||||
auto shared_mem = std::make_shared<SharedMemory>(system);
|
||||
|
||||
std::make_shared<Time>(time, shared_mem, system, "time:a")
|
||||
->InstallAsService(system.ServiceManager());
|
||||
std::make_shared<Time>(time, shared_mem, system, "time:s")
|
||||
->InstallAsService(system.ServiceManager());
|
||||
std::make_shared<Time>(std::move(time), shared_mem, system, "time:u")
|
||||
->InstallAsService(system.ServiceManager());
|
||||
auto module{std::make_shared<Module>(system)};
|
||||
std::make_shared<Time>(module, system, "time:a")->InstallAsService(system.ServiceManager());
|
||||
std::make_shared<Time>(module, system, "time:s")->InstallAsService(system.ServiceManager());
|
||||
std::make_shared<Time>(module, system, "time:u")->InstallAsService(system.ServiceManager());
|
||||
}
|
||||
|
||||
} // namespace Service::Time
|
||||
|
||||
@@ -4,84 +4,23 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include "common/common_funcs.h"
|
||||
#include "core/hle/service/service.h"
|
||||
#include "core/hle/service/time/clock_types.h"
|
||||
#include "core/hle/service/time/time_manager.h"
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
}
|
||||
|
||||
namespace Service::Time {
|
||||
|
||||
class SharedMemory;
|
||||
|
||||
struct LocationName {
|
||||
std::array<u8, 0x24> name;
|
||||
};
|
||||
static_assert(sizeof(LocationName) == 0x24, "LocationName is incorrect size");
|
||||
|
||||
struct CalendarTime {
|
||||
u16_le year;
|
||||
u8 month; // Starts at 1
|
||||
u8 day; // Starts at 1
|
||||
u8 hour;
|
||||
u8 minute;
|
||||
u8 second;
|
||||
};
|
||||
static_assert(sizeof(CalendarTime) == 0x8, "CalendarTime structure has incorrect size");
|
||||
|
||||
struct CalendarAdditionalInfo {
|
||||
u32_le day_of_week;
|
||||
u32_le day_of_year;
|
||||
std::array<u8, 8> name;
|
||||
u8 is_dst;
|
||||
s32_le utc_offset;
|
||||
};
|
||||
static_assert(sizeof(CalendarAdditionalInfo) == 0x18,
|
||||
"CalendarAdditionalInfo structure has incorrect size");
|
||||
|
||||
// TODO(mailwl) RE this structure
|
||||
struct TimeZoneRule {
|
||||
INSERT_PADDING_BYTES(0x4000);
|
||||
};
|
||||
|
||||
struct SteadyClockTimePoint {
|
||||
using SourceID = std::array<u8, 16>;
|
||||
|
||||
u64_le value;
|
||||
SourceID source_id;
|
||||
};
|
||||
static_assert(sizeof(SteadyClockTimePoint) == 0x18, "SteadyClockTimePoint is incorrect size");
|
||||
|
||||
struct SystemClockContext {
|
||||
u64_le offset;
|
||||
SteadyClockTimePoint time_point;
|
||||
};
|
||||
static_assert(sizeof(SystemClockContext) == 0x20,
|
||||
"SystemClockContext structure has incorrect size");
|
||||
|
||||
struct ClockSnapshot {
|
||||
SystemClockContext user_clock_context;
|
||||
SystemClockContext network_clock_context;
|
||||
s64_le system_posix_time;
|
||||
s64_le network_posix_time;
|
||||
CalendarTime system_calendar_time;
|
||||
CalendarTime network_calendar_time;
|
||||
CalendarAdditionalInfo system_calendar_info;
|
||||
CalendarAdditionalInfo network_calendar_info;
|
||||
SteadyClockTimePoint steady_clock_timepoint;
|
||||
LocationName location_name;
|
||||
u8 clock_auto_adjustment_enabled;
|
||||
u8 type;
|
||||
u8 version;
|
||||
INSERT_PADDING_BYTES(1);
|
||||
};
|
||||
static_assert(sizeof(ClockSnapshot) == 0xd0, "ClockSnapshot is an invalid size");
|
||||
|
||||
class Module final {
|
||||
public:
|
||||
Module(Core::System& system) : time_manager{system} {}
|
||||
|
||||
class Interface : public ServiceFramework<Interface> {
|
||||
public:
|
||||
explicit Interface(std::shared_ptr<Module> time,
|
||||
std::shared_ptr<SharedMemory> shared_memory, Core::System& system,
|
||||
const char* name);
|
||||
explicit Interface(std::shared_ptr<Module> module, Core::System& system, const char* name);
|
||||
~Interface() override;
|
||||
|
||||
void GetStandardUserSystemClock(Kernel::HLERequestContext& ctx);
|
||||
@@ -89,17 +28,29 @@ public:
|
||||
void GetStandardSteadyClock(Kernel::HLERequestContext& ctx);
|
||||
void GetTimeZoneService(Kernel::HLERequestContext& ctx);
|
||||
void GetStandardLocalSystemClock(Kernel::HLERequestContext& ctx);
|
||||
void IsStandardNetworkSystemClockAccuracySufficient(Kernel::HLERequestContext& ctx);
|
||||
void CalculateMonotonicSystemClockBaseTimePoint(Kernel::HLERequestContext& ctx);
|
||||
void GetClockSnapshot(Kernel::HLERequestContext& ctx);
|
||||
void CalculateStandardUserSystemClockDifferenceByUser(Kernel::HLERequestContext& ctx);
|
||||
void GetClockSnapshotFromSystemClockContext(Kernel::HLERequestContext& ctx);
|
||||
void GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx);
|
||||
void IsStandardUserSystemClockAutomaticCorrectionEnabled(Kernel::HLERequestContext& ctx);
|
||||
void SetStandardUserSystemClockAutomaticCorrectionEnabled(Kernel::HLERequestContext& ctx);
|
||||
|
||||
private:
|
||||
ResultCode GetClockSnapshotFromSystemClockContextInternal(
|
||||
Kernel::Thread* thread, Clock::SystemClockContext user_context,
|
||||
Clock::SystemClockContext network_context, u8 type,
|
||||
Clock::ClockSnapshot& cloc_snapshot);
|
||||
|
||||
protected:
|
||||
std::shared_ptr<Module> time;
|
||||
std::shared_ptr<SharedMemory> shared_memory;
|
||||
std::shared_ptr<Module> module;
|
||||
Core::System& system;
|
||||
};
|
||||
|
||||
TimeManager& GetTimeManager() {
|
||||
return time_manager;
|
||||
}
|
||||
|
||||
private:
|
||||
TimeManager time_manager;
|
||||
};
|
||||
|
||||
/// Registers all Time services with the specified service manager.
|
||||
|
||||
137
src/core/hle/service/time/time_manager.cpp
Normal file
137
src/core/hle/service/time/time_manager.cpp
Normal file
@@ -0,0 +1,137 @@
|
||||
// Copyright 2019 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <chrono>
|
||||
#include <ctime>
|
||||
|
||||
#include "core/hle/service/time/ephemeral_network_system_clock_context_writer.h"
|
||||
#include "core/hle/service/time/local_system_clock_context_writer.h"
|
||||
#include "core/hle/service/time/network_system_clock_context_writer.h"
|
||||
#include "core/hle/service/time/time_manager.h"
|
||||
#include "core/settings.h"
|
||||
|
||||
namespace Service::Time {
|
||||
|
||||
constexpr Clock::TimeSpanType standard_network_clock_accuracy{0x0009356907420000ULL};
|
||||
|
||||
static std::chrono::seconds GetSecondsSinceEpoch() {
|
||||
return std::chrono::duration_cast<std::chrono::seconds>(
|
||||
std::chrono::system_clock::now().time_since_epoch()) +
|
||||
Settings::values.custom_rtc_differential;
|
||||
}
|
||||
|
||||
static s64 GetExternalRtcValue() {
|
||||
return GetSecondsSinceEpoch().count();
|
||||
}
|
||||
|
||||
TimeManager::TimeManager(Core::System& system)
|
||||
: shared_memory{system}, standard_local_system_clock_core{standard_steady_clock_core},
|
||||
standard_network_system_clock_core{standard_steady_clock_core},
|
||||
standard_user_system_clock_core{standard_local_system_clock_core,
|
||||
standard_network_system_clock_core, system},
|
||||
ephemeral_network_system_clock_core{tick_based_steady_clock_core},
|
||||
local_system_clock_context_writer{
|
||||
std::make_shared<Clock::LocalSystemClockContextWriter>(shared_memory)},
|
||||
network_system_clock_context_writer{
|
||||
std::make_shared<Clock::NetworkSystemClockContextWriter>(shared_memory)},
|
||||
ephemeral_network_system_clock_context_writer{
|
||||
std::make_shared<Clock::EphemeralNetworkSystemClockContextWriter>()},
|
||||
time_zone_content_manager{*this, system} {
|
||||
|
||||
const auto system_time{Clock::TimeSpanType::FromSeconds(GetExternalRtcValue())};
|
||||
SetupStandardSteadyClock(system, Common::UUID::Generate(), system_time, {}, {});
|
||||
SetupStandardLocalSystemClock(system, {}, system_time.ToSeconds());
|
||||
SetupStandardNetworkSystemClock({}, standard_network_clock_accuracy);
|
||||
SetupStandardUserSystemClock(system, {}, Clock::SteadyClockTimePoint::GetRandom());
|
||||
SetupEphemeralNetworkSystemClock();
|
||||
}
|
||||
|
||||
TimeManager::~TimeManager() = default;
|
||||
|
||||
void TimeManager::SetupTimeZoneManager(std::string location_name,
|
||||
Clock::SteadyClockTimePoint time_zone_updated_time_point,
|
||||
std::size_t total_location_name_count,
|
||||
u128 time_zone_rule_version,
|
||||
FileSys::VirtualFile& vfs_file) {
|
||||
if (time_zone_content_manager.GetTimeZoneManager().SetDeviceLocationNameWithTimeZoneRule(
|
||||
location_name, vfs_file) != RESULT_SUCCESS) {
|
||||
UNREACHABLE();
|
||||
return;
|
||||
}
|
||||
|
||||
time_zone_content_manager.GetTimeZoneManager().SetUpdatedTime(time_zone_updated_time_point);
|
||||
time_zone_content_manager.GetTimeZoneManager().SetTotalLocationNameCount(
|
||||
total_location_name_count);
|
||||
time_zone_content_manager.GetTimeZoneManager().SetTimeZoneRuleVersion(time_zone_rule_version);
|
||||
time_zone_content_manager.GetTimeZoneManager().MarkAsInitialized();
|
||||
}
|
||||
|
||||
void TimeManager::SetupStandardSteadyClock(Core::System& system, Common::UUID clock_source_id,
|
||||
Clock::TimeSpanType setup_value,
|
||||
Clock::TimeSpanType internal_offset,
|
||||
bool is_rtc_reset_detected) {
|
||||
standard_steady_clock_core.SetClockSourceId(clock_source_id);
|
||||
standard_steady_clock_core.SetSetupValue(setup_value);
|
||||
standard_steady_clock_core.SetInternalOffset(internal_offset);
|
||||
standard_steady_clock_core.MarkAsInitialized();
|
||||
|
||||
const auto current_time_point{standard_steady_clock_core.GetCurrentRawTimePoint(system)};
|
||||
shared_memory.SetupStandardSteadyClock(system, clock_source_id, current_time_point);
|
||||
}
|
||||
|
||||
void TimeManager::SetupStandardLocalSystemClock(Core::System& system,
|
||||
Clock::SystemClockContext clock_context,
|
||||
s64 posix_time) {
|
||||
standard_local_system_clock_core.SetUpdateCallbackInstance(local_system_clock_context_writer);
|
||||
|
||||
const auto current_time_point{
|
||||
standard_local_system_clock_core.GetSteadyClockCore().GetCurrentTimePoint(system)};
|
||||
if (current_time_point.clock_source_id == clock_context.steady_time_point.clock_source_id) {
|
||||
standard_local_system_clock_core.SetSystemClockContext(clock_context);
|
||||
} else {
|
||||
if (standard_local_system_clock_core.SetCurrentTime(system, posix_time) != RESULT_SUCCESS) {
|
||||
UNREACHABLE();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
standard_local_system_clock_core.MarkAsInitialized();
|
||||
}
|
||||
|
||||
void TimeManager::SetupStandardNetworkSystemClock(Clock::SystemClockContext clock_context,
|
||||
Clock::TimeSpanType sufficient_accuracy) {
|
||||
standard_network_system_clock_core.SetUpdateCallbackInstance(
|
||||
network_system_clock_context_writer);
|
||||
|
||||
if (standard_network_system_clock_core.SetSystemClockContext(clock_context) != RESULT_SUCCESS) {
|
||||
UNREACHABLE();
|
||||
return;
|
||||
}
|
||||
|
||||
standard_network_system_clock_core.SetStandardNetworkClockSufficientAccuracy(
|
||||
sufficient_accuracy);
|
||||
standard_network_system_clock_core.MarkAsInitialized();
|
||||
}
|
||||
|
||||
void TimeManager::SetupStandardUserSystemClock(
|
||||
Core::System& system, bool is_automatic_correction_enabled,
|
||||
Clock::SteadyClockTimePoint steady_clock_time_point) {
|
||||
if (standard_user_system_clock_core.SetAutomaticCorrectionEnabled(
|
||||
system, is_automatic_correction_enabled) != RESULT_SUCCESS) {
|
||||
UNREACHABLE();
|
||||
return;
|
||||
}
|
||||
|
||||
standard_user_system_clock_core.SetAutomaticCorrectionUpdatedTime(steady_clock_time_point);
|
||||
standard_user_system_clock_core.MarkAsInitialized();
|
||||
shared_memory.SetAutomaticCorrectionEnabled(is_automatic_correction_enabled);
|
||||
}
|
||||
|
||||
void TimeManager::SetupEphemeralNetworkSystemClock() {
|
||||
ephemeral_network_system_clock_core.SetUpdateCallbackInstance(
|
||||
ephemeral_network_system_clock_context_writer);
|
||||
ephemeral_network_system_clock_core.MarkAsInitialized();
|
||||
}
|
||||
|
||||
} // namespace Service::Time
|
||||
117
src/core/hle/service/time/time_manager.h
Normal file
117
src/core/hle/service/time/time_manager.h
Normal file
@@ -0,0 +1,117 @@
|
||||
// Copyright 2019 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "core/file_sys/vfs_types.h"
|
||||
#include "core/hle/service/time/clock_types.h"
|
||||
#include "core/hle/service/time/ephemeral_network_system_clock_core.h"
|
||||
#include "core/hle/service/time/standard_local_system_clock_core.h"
|
||||
#include "core/hle/service/time/standard_network_system_clock_core.h"
|
||||
#include "core/hle/service/time/standard_steady_clock_core.h"
|
||||
#include "core/hle/service/time/standard_user_system_clock_core.h"
|
||||
#include "core/hle/service/time/tick_based_steady_clock_core.h"
|
||||
#include "core/hle/service/time/time_sharedmemory.h"
|
||||
#include "core/hle/service/time/time_zone_content_manager.h"
|
||||
|
||||
namespace Service::Time {
|
||||
|
||||
namespace Clock {
|
||||
class EphemeralNetworkSystemClockContextWriter;
|
||||
class LocalSystemClockContextWriter;
|
||||
class NetworkSystemClockContextWriter;
|
||||
} // namespace Clock
|
||||
|
||||
// Parts of this implementation were based on Ryujinx (https://github.com/Ryujinx/Ryujinx/pull/783).
|
||||
// This code was released under public domain.
|
||||
|
||||
class TimeManager final {
|
||||
public:
|
||||
explicit TimeManager(Core::System& system);
|
||||
~TimeManager();
|
||||
|
||||
Clock::StandardSteadyClockCore& GetStandardSteadyClockCore() {
|
||||
return standard_steady_clock_core;
|
||||
}
|
||||
|
||||
const Clock::StandardSteadyClockCore& GetStandardSteadyClockCore() const {
|
||||
return standard_steady_clock_core;
|
||||
}
|
||||
|
||||
Clock::StandardLocalSystemClockCore& GetStandardLocalSystemClockCore() {
|
||||
return standard_local_system_clock_core;
|
||||
}
|
||||
|
||||
const Clock::StandardLocalSystemClockCore& GetStandardLocalSystemClockCore() const {
|
||||
return standard_local_system_clock_core;
|
||||
}
|
||||
|
||||
Clock::StandardNetworkSystemClockCore& GetStandardNetworkSystemClockCore() {
|
||||
return standard_network_system_clock_core;
|
||||
}
|
||||
|
||||
const Clock::StandardNetworkSystemClockCore& GetStandardNetworkSystemClockCore() const {
|
||||
return standard_network_system_clock_core;
|
||||
}
|
||||
|
||||
Clock::StandardUserSystemClockCore& GetStandardUserSystemClockCore() {
|
||||
return standard_user_system_clock_core;
|
||||
}
|
||||
|
||||
const Clock::StandardUserSystemClockCore& GetStandardUserSystemClockCore() const {
|
||||
return standard_user_system_clock_core;
|
||||
}
|
||||
|
||||
TimeZone::TimeZoneContentManager& GetTimeZoneContentManager() {
|
||||
return time_zone_content_manager;
|
||||
}
|
||||
|
||||
const TimeZone::TimeZoneContentManager& GetTimeZoneContentManager() const {
|
||||
return time_zone_content_manager;
|
||||
}
|
||||
|
||||
SharedMemory& GetSharedMemory() {
|
||||
return shared_memory;
|
||||
}
|
||||
|
||||
const SharedMemory& GetSharedMemory() const {
|
||||
return shared_memory;
|
||||
}
|
||||
|
||||
void SetupTimeZoneManager(std::string location_name,
|
||||
Clock::SteadyClockTimePoint time_zone_updated_time_point,
|
||||
std::size_t total_location_name_count, u128 time_zone_rule_version,
|
||||
FileSys::VirtualFile& vfs_file);
|
||||
|
||||
private:
|
||||
void SetupStandardSteadyClock(Core::System& system, Common::UUID clock_source_id,
|
||||
Clock::TimeSpanType setup_value,
|
||||
Clock::TimeSpanType internal_offset, bool is_rtc_reset_detected);
|
||||
void SetupStandardLocalSystemClock(Core::System& system,
|
||||
Clock::SystemClockContext clock_context, s64 posix_time);
|
||||
void SetupStandardNetworkSystemClock(Clock::SystemClockContext clock_context,
|
||||
Clock::TimeSpanType sufficient_accuracy);
|
||||
void SetupStandardUserSystemClock(Core::System& system, bool is_automatic_correction_enabled,
|
||||
Clock::SteadyClockTimePoint steady_clock_time_point);
|
||||
void SetupEphemeralNetworkSystemClock();
|
||||
|
||||
SharedMemory shared_memory;
|
||||
|
||||
Clock::StandardSteadyClockCore standard_steady_clock_core;
|
||||
Clock::TickBasedSteadyClockCore tick_based_steady_clock_core;
|
||||
Clock::StandardLocalSystemClockCore standard_local_system_clock_core;
|
||||
Clock::StandardNetworkSystemClockCore standard_network_system_clock_core;
|
||||
Clock::StandardUserSystemClockCore standard_user_system_clock_core;
|
||||
Clock::EphemeralNetworkSystemClockCore ephemeral_network_system_clock_core;
|
||||
|
||||
std::shared_ptr<Clock::LocalSystemClockContextWriter> local_system_clock_context_writer;
|
||||
std::shared_ptr<Clock::NetworkSystemClockContextWriter> network_system_clock_context_writer;
|
||||
std::shared_ptr<Clock::EphemeralNetworkSystemClockContextWriter>
|
||||
ephemeral_network_system_clock_context_writer;
|
||||
|
||||
TimeZone::TimeZoneContentManager time_zone_content_manager;
|
||||
};
|
||||
|
||||
} // namespace Service::Time
|
||||
@@ -3,20 +3,21 @@
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "core/core.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/core_timing_util.h"
|
||||
#include "core/hle/service/time/clock_types.h"
|
||||
#include "core/hle/service/time/steady_clock_core.h"
|
||||
#include "core/hle/service/time/time_sharedmemory.h"
|
||||
|
||||
namespace Service::Time {
|
||||
const std::size_t SHARED_MEMORY_SIZE = 0x1000;
|
||||
|
||||
static constexpr std::size_t SHARED_MEMORY_SIZE{0x1000};
|
||||
|
||||
SharedMemory::SharedMemory(Core::System& system) : system(system) {
|
||||
shared_memory_holder = Kernel::SharedMemory::Create(
|
||||
system.Kernel(), nullptr, SHARED_MEMORY_SIZE, Kernel::MemoryPermission::ReadWrite,
|
||||
Kernel::MemoryPermission::Read, 0, Kernel::MemoryRegion::BASE, "Time:SharedMemory");
|
||||
|
||||
// Seems static from 1.0.0 -> 8.1.0. Specific games seem to check this value and crash
|
||||
// if it's set to anything else
|
||||
shared_memory_format.format_version = 14;
|
||||
std::memcpy(shared_memory_holder->GetPointer(), &shared_memory_format, sizeof(Format));
|
||||
std::memset(shared_memory_holder->GetPointer(), 0, SHARED_MEMORY_SIZE);
|
||||
}
|
||||
|
||||
SharedMemory::~SharedMemory() = default;
|
||||
@@ -25,44 +26,32 @@ std::shared_ptr<Kernel::SharedMemory> SharedMemory::GetSharedMemoryHolder() cons
|
||||
return shared_memory_holder;
|
||||
}
|
||||
|
||||
void SharedMemory::SetStandardSteadyClockTimepoint(const SteadyClockTimePoint& timepoint) {
|
||||
void SharedMemory::SetupStandardSteadyClock(Core::System& system,
|
||||
const Common::UUID& clock_source_id,
|
||||
Clock::TimeSpanType current_time_point) {
|
||||
const Clock::TimeSpanType ticks_time_span{Clock::TimeSpanType::FromTicks(
|
||||
Core::Timing::CpuCyclesToClockCycles(system.CoreTiming().GetTicks()),
|
||||
Core::Timing::CNTFREQ)};
|
||||
const Clock::SteadyClockContext context{
|
||||
static_cast<u64>(current_time_point.nanoseconds - ticks_time_span.nanoseconds),
|
||||
clock_source_id};
|
||||
shared_memory_format.standard_steady_clock_timepoint.StoreData(
|
||||
shared_memory_holder->GetPointer(), timepoint);
|
||||
shared_memory_holder->GetPointer(), context);
|
||||
}
|
||||
|
||||
void SharedMemory::SetStandardLocalSystemClockContext(const SystemClockContext& context) {
|
||||
void SharedMemory::UpdateLocalSystemClockContext(const Clock::SystemClockContext& context) {
|
||||
shared_memory_format.standard_local_system_clock_context.StoreData(
|
||||
shared_memory_holder->GetPointer(), context);
|
||||
}
|
||||
|
||||
void SharedMemory::SetStandardNetworkSystemClockContext(const SystemClockContext& context) {
|
||||
void SharedMemory::UpdateNetworkSystemClockContext(const Clock::SystemClockContext& context) {
|
||||
shared_memory_format.standard_network_system_clock_context.StoreData(
|
||||
shared_memory_holder->GetPointer(), context);
|
||||
}
|
||||
|
||||
void SharedMemory::SetStandardUserSystemClockAutomaticCorrectionEnabled(bool enabled) {
|
||||
void SharedMemory::SetAutomaticCorrectionEnabled(bool is_enabled) {
|
||||
shared_memory_format.standard_user_system_clock_automatic_correction.StoreData(
|
||||
shared_memory_holder->GetPointer(), enabled);
|
||||
}
|
||||
|
||||
SteadyClockTimePoint SharedMemory::GetStandardSteadyClockTimepoint() {
|
||||
return shared_memory_format.standard_steady_clock_timepoint.ReadData(
|
||||
shared_memory_holder->GetPointer());
|
||||
}
|
||||
|
||||
SystemClockContext SharedMemory::GetStandardLocalSystemClockContext() {
|
||||
return shared_memory_format.standard_local_system_clock_context.ReadData(
|
||||
shared_memory_holder->GetPointer());
|
||||
}
|
||||
|
||||
SystemClockContext SharedMemory::GetStandardNetworkSystemClockContext() {
|
||||
return shared_memory_format.standard_network_system_clock_context.ReadData(
|
||||
shared_memory_holder->GetPointer());
|
||||
}
|
||||
|
||||
bool SharedMemory::GetStandardUserSystemClockAutomaticCorrectionEnabled() {
|
||||
return shared_memory_format.standard_user_system_clock_automatic_correction.ReadData(
|
||||
shared_memory_holder->GetPointer());
|
||||
shared_memory_holder->GetPointer(), is_enabled);
|
||||
}
|
||||
|
||||
} // namespace Service::Time
|
||||
|
||||
@@ -5,11 +5,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "common/uuid.h"
|
||||
#include "core/hle/kernel/shared_memory.h"
|
||||
#include "core/hle/service/time/time.h"
|
||||
#include "core/hle/kernel/thread.h"
|
||||
#include "core/hle/service/time/clock_types.h"
|
||||
|
||||
namespace Service::Time {
|
||||
class SharedMemory {
|
||||
|
||||
class SharedMemory final {
|
||||
public:
|
||||
explicit SharedMemory(Core::System& system);
|
||||
~SharedMemory();
|
||||
@@ -17,22 +20,10 @@ public:
|
||||
// Return the shared memory handle
|
||||
std::shared_ptr<Kernel::SharedMemory> GetSharedMemoryHolder() const;
|
||||
|
||||
// Set memory barriers in shared memory and update them
|
||||
void SetStandardSteadyClockTimepoint(const SteadyClockTimePoint& timepoint);
|
||||
void SetStandardLocalSystemClockContext(const SystemClockContext& context);
|
||||
void SetStandardNetworkSystemClockContext(const SystemClockContext& context);
|
||||
void SetStandardUserSystemClockAutomaticCorrectionEnabled(bool enabled);
|
||||
|
||||
// Pull from memory barriers in the shared memory
|
||||
SteadyClockTimePoint GetStandardSteadyClockTimepoint();
|
||||
SystemClockContext GetStandardLocalSystemClockContext();
|
||||
SystemClockContext GetStandardNetworkSystemClockContext();
|
||||
bool GetStandardUserSystemClockAutomaticCorrectionEnabled();
|
||||
|
||||
// TODO(ogniK): We have to properly simulate memory barriers, how are we going to do this?
|
||||
template <typename T, std::size_t Offset>
|
||||
struct MemoryBarrier {
|
||||
static_assert(std::is_trivially_constructible_v<T>, "T must be trivially constructable");
|
||||
static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable");
|
||||
u32_le read_attempt{};
|
||||
std::array<T, 2> data{};
|
||||
|
||||
@@ -57,16 +48,22 @@ public:
|
||||
|
||||
// Shared memory format
|
||||
struct Format {
|
||||
MemoryBarrier<SteadyClockTimePoint, 0x0> standard_steady_clock_timepoint;
|
||||
MemoryBarrier<SystemClockContext, 0x38> standard_local_system_clock_context;
|
||||
MemoryBarrier<SystemClockContext, 0x80> standard_network_system_clock_context;
|
||||
MemoryBarrier<Clock::SteadyClockContext, 0x0> standard_steady_clock_timepoint;
|
||||
MemoryBarrier<Clock::SystemClockContext, 0x38> standard_local_system_clock_context;
|
||||
MemoryBarrier<Clock::SystemClockContext, 0x80> standard_network_system_clock_context;
|
||||
MemoryBarrier<bool, 0xc8> standard_user_system_clock_automatic_correction;
|
||||
u32_le format_version;
|
||||
};
|
||||
static_assert(sizeof(Format) == 0xd8, "Format is an invalid size");
|
||||
|
||||
void SetupStandardSteadyClock(Core::System& system, const Common::UUID& clock_source_id,
|
||||
Clock::TimeSpanType currentTimePoint);
|
||||
void UpdateLocalSystemClockContext(const Clock::SystemClockContext& context);
|
||||
void UpdateNetworkSystemClockContext(const Clock::SystemClockContext& context);
|
||||
void SetAutomaticCorrectionEnabled(bool is_enabled);
|
||||
|
||||
private:
|
||||
std::shared_ptr<Kernel::SharedMemory> shared_memory_holder{};
|
||||
std::shared_ptr<Kernel::SharedMemory> shared_memory_holder;
|
||||
Core::System& system;
|
||||
Format shared_memory_format{};
|
||||
};
|
||||
|
||||
125
src/core/hle/service/time/time_zone_content_manager.cpp
Normal file
125
src/core/hle/service/time/time_zone_content_manager.cpp
Normal file
@@ -0,0 +1,125 @@
|
||||
// Copyright 2019 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "core/core.h"
|
||||
#include "core/file_sys/content_archive.h"
|
||||
#include "core/file_sys/nca_metadata.h"
|
||||
#include "core/file_sys/registered_cache.h"
|
||||
#include "core/file_sys/romfs.h"
|
||||
#include "core/file_sys/system_archive/system_archive.h"
|
||||
#include "core/hle/service/filesystem/filesystem.h"
|
||||
#include "core/hle/service/time/time_manager.h"
|
||||
#include "core/hle/service/time/time_zone_content_manager.h"
|
||||
|
||||
namespace Service::Time::TimeZone {
|
||||
|
||||
constexpr u64 time_zone_binary_titleid{0x010000000000080E};
|
||||
|
||||
static FileSys::VirtualDir GetTimeZoneBinary(Core::System& system) {
|
||||
const auto* nand{system.GetFileSystemController().GetSystemNANDContents()};
|
||||
const auto nca{nand->GetEntry(time_zone_binary_titleid, FileSys::ContentRecordType::Data)};
|
||||
|
||||
FileSys::VirtualFile romfs;
|
||||
if (nca) {
|
||||
romfs = nca->GetRomFS();
|
||||
}
|
||||
|
||||
if (!romfs) {
|
||||
romfs = FileSys::SystemArchive::SynthesizeSystemArchive(time_zone_binary_titleid);
|
||||
}
|
||||
|
||||
if (!romfs) {
|
||||
LOG_ERROR(Service_Time, "Failed to find or synthesize {:016X!}", time_zone_binary_titleid);
|
||||
return {};
|
||||
}
|
||||
|
||||
return FileSys::ExtractRomFS(romfs);
|
||||
}
|
||||
|
||||
static std::vector<std::string> BuildLocationNameCache(Core::System& system) {
|
||||
const FileSys::VirtualDir extracted_romfs{GetTimeZoneBinary(system)};
|
||||
if (!extracted_romfs) {
|
||||
LOG_ERROR(Service_Time, "Failed to extract RomFS for {:016X}!", time_zone_binary_titleid);
|
||||
return {};
|
||||
}
|
||||
|
||||
const FileSys::VirtualFile binary_list{extracted_romfs->GetFile("binaryList.txt")};
|
||||
if (!binary_list) {
|
||||
LOG_ERROR(Service_Time, "{:016X} has no file binaryList.txt!", time_zone_binary_titleid);
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<char> raw_data(binary_list->GetSize());
|
||||
binary_list->ReadBytes<char>(raw_data.data(), binary_list->GetSize());
|
||||
|
||||
std::stringstream data_stream{raw_data.data()};
|
||||
std::string name;
|
||||
std::vector<std::string> location_name_cache;
|
||||
while (std::getline(data_stream, name)) {
|
||||
name.pop_back(); // Remove carriage return
|
||||
location_name_cache.emplace_back(std::move(name));
|
||||
}
|
||||
return location_name_cache;
|
||||
}
|
||||
|
||||
TimeZoneContentManager::TimeZoneContentManager(TimeManager& time_manager, Core::System& system)
|
||||
: system{system}, location_name_cache{BuildLocationNameCache(system)} {
|
||||
if (FileSys::VirtualFile vfs_file; GetTimeZoneInfoFile("GMT", vfs_file) == RESULT_SUCCESS) {
|
||||
const auto time_point{
|
||||
time_manager.GetStandardSteadyClockCore().GetCurrentTimePoint(system)};
|
||||
time_manager.SetupTimeZoneManager("GMT", time_point, location_name_cache.size(), {},
|
||||
vfs_file);
|
||||
} else {
|
||||
time_zone_manager.MarkAsInitialized();
|
||||
}
|
||||
}
|
||||
|
||||
ResultCode TimeZoneContentManager::LoadTimeZoneRule(TimeZoneRule& rules,
|
||||
const std::string& location_name) const {
|
||||
FileSys::VirtualFile vfs_file;
|
||||
if (const ResultCode result{GetTimeZoneInfoFile(location_name, vfs_file)};
|
||||
result != RESULT_SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return time_zone_manager.ParseTimeZoneRuleBinary(rules, vfs_file);
|
||||
}
|
||||
|
||||
bool TimeZoneContentManager::IsLocationNameValid(const std::string& location_name) const {
|
||||
return std::find(location_name_cache.begin(), location_name_cache.end(), location_name) !=
|
||||
location_name_cache.end();
|
||||
}
|
||||
|
||||
ResultCode TimeZoneContentManager::GetTimeZoneInfoFile(const std::string& location_name,
|
||||
FileSys::VirtualFile& vfs_file) const {
|
||||
if (!IsLocationNameValid(location_name)) {
|
||||
return ERROR_TIME_NOT_FOUND;
|
||||
}
|
||||
|
||||
const FileSys::VirtualDir extracted_romfs{GetTimeZoneBinary(system)};
|
||||
if (!extracted_romfs) {
|
||||
LOG_ERROR(Service_Time, "Failed to extract RomFS for {:016X}!", time_zone_binary_titleid);
|
||||
return ERROR_TIME_NOT_FOUND;
|
||||
}
|
||||
|
||||
const FileSys::VirtualDir zoneinfo_dir{extracted_romfs->GetSubdirectory("zoneinfo")};
|
||||
if (!zoneinfo_dir) {
|
||||
LOG_ERROR(Service_Time, "{:016X} has no directory zoneinfo!", time_zone_binary_titleid);
|
||||
return ERROR_TIME_NOT_FOUND;
|
||||
}
|
||||
|
||||
vfs_file = zoneinfo_dir->GetFile(location_name);
|
||||
if (!vfs_file) {
|
||||
LOG_ERROR(Service_Time, "{:016X} has no file \"{}\"!", time_zone_binary_titleid,
|
||||
location_name);
|
||||
return ERROR_TIME_NOT_FOUND;
|
||||
}
|
||||
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace Service::Time::TimeZone
|
||||
46
src/core/hle/service/time/time_zone_content_manager.h
Normal file
46
src/core/hle/service/time/time_zone_content_manager.h
Normal file
@@ -0,0 +1,46 @@
|
||||
// Copyright 2019 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "core/hle/service/time/time_zone_manager.h"
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
}
|
||||
|
||||
namespace Service::Time {
|
||||
class TimeManager;
|
||||
}
|
||||
|
||||
namespace Service::Time::TimeZone {
|
||||
|
||||
class TimeZoneContentManager final {
|
||||
public:
|
||||
TimeZoneContentManager(TimeManager& time_manager, Core::System& system);
|
||||
|
||||
TimeZoneManager& GetTimeZoneManager() {
|
||||
return time_zone_manager;
|
||||
}
|
||||
|
||||
const TimeZoneManager& GetTimeZoneManager() const {
|
||||
return time_zone_manager;
|
||||
}
|
||||
|
||||
ResultCode LoadTimeZoneRule(TimeZoneRule& rules, const std::string& location_name) const;
|
||||
|
||||
private:
|
||||
bool IsLocationNameValid(const std::string& location_name) const;
|
||||
ResultCode GetTimeZoneInfoFile(const std::string& location_name,
|
||||
FileSys::VirtualFile& vfs_file) const;
|
||||
|
||||
Core::System& system;
|
||||
TimeZoneManager time_zone_manager;
|
||||
const std::vector<std::string> location_name_cache;
|
||||
};
|
||||
|
||||
} // namespace Service::Time::TimeZone
|
||||
1039
src/core/hle/service/time/time_zone_manager.cpp
Normal file
1039
src/core/hle/service/time/time_zone_manager.cpp
Normal file
File diff suppressed because it is too large
Load Diff
54
src/core/hle/service/time/time_zone_manager.h
Normal file
54
src/core/hle/service/time/time_zone_manager.h
Normal file
@@ -0,0 +1,54 @@
|
||||
// Copyright 2019 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "core/file_sys/vfs_types.h"
|
||||
#include "core/hle/service/time/clock_types.h"
|
||||
#include "core/hle/service/time/time_zone_types.h"
|
||||
|
||||
namespace Service::Time::TimeZone {
|
||||
|
||||
class TimeZoneManager final {
|
||||
public:
|
||||
TimeZoneManager();
|
||||
~TimeZoneManager();
|
||||
|
||||
void SetTotalLocationNameCount(std::size_t value) {
|
||||
total_location_name_count = value;
|
||||
}
|
||||
|
||||
void SetTimeZoneRuleVersion(const u128& value) {
|
||||
time_zone_rule_version = value;
|
||||
}
|
||||
|
||||
void MarkAsInitialized() {
|
||||
is_initialized = true;
|
||||
}
|
||||
|
||||
ResultCode SetDeviceLocationNameWithTimeZoneRule(const std::string& location_name,
|
||||
FileSys::VirtualFile& vfs_file);
|
||||
ResultCode SetUpdatedTime(const Clock::SteadyClockTimePoint& value);
|
||||
ResultCode GetDeviceLocationName(TimeZone::LocationName& value) const;
|
||||
ResultCode ToCalendarTime(const TimeZoneRule& rules, s64 time, CalendarInfo& calendar) const;
|
||||
ResultCode ToCalendarTimeWithMyRules(s64 time, CalendarInfo& calendar) const;
|
||||
ResultCode ParseTimeZoneRuleBinary(TimeZoneRule& rules, FileSys::VirtualFile& vfs_file) const;
|
||||
ResultCode ToPosixTime(const TimeZoneRule& rules, const CalendarTime& calendar_time,
|
||||
s64& posix_time) const;
|
||||
ResultCode ToPosixTimeWithMyRule(const CalendarTime& calendar_time, s64& posix_time) const;
|
||||
|
||||
private:
|
||||
bool is_initialized{};
|
||||
TimeZoneRule time_zone_rule{};
|
||||
std::string device_location_name{"GMT"};
|
||||
u128 time_zone_rule_version{};
|
||||
std::size_t total_location_name_count{};
|
||||
Clock::SteadyClockTimePoint time_zone_update_time_point{
|
||||
Clock::SteadyClockTimePoint::GetRandom()};
|
||||
};
|
||||
|
||||
} // namespace Service::Time::TimeZone
|
||||
170
src/core/hle/service/time/time_zone_service.cpp
Normal file
170
src/core/hle/service/time/time_zone_service.cpp
Normal file
@@ -0,0 +1,170 @@
|
||||
// Copyright 2019 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/service/time/time_zone_content_manager.h"
|
||||
#include "core/hle/service/time/time_zone_service.h"
|
||||
#include "core/hle/service/time/time_zone_types.h"
|
||||
|
||||
namespace Service::Time {
|
||||
|
||||
ITimeZoneService ::ITimeZoneService(TimeZone::TimeZoneContentManager& time_zone_content_manager)
|
||||
: ServiceFramework("ITimeZoneService"), time_zone_content_manager{time_zone_content_manager} {
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &ITimeZoneService::GetDeviceLocationName, "GetDeviceLocationName"},
|
||||
{1, nullptr, "SetDeviceLocationName"},
|
||||
{2, nullptr, "GetTotalLocationNameCount"},
|
||||
{3, nullptr, "LoadLocationNameList"},
|
||||
{4, &ITimeZoneService::LoadTimeZoneRule, "LoadTimeZoneRule"},
|
||||
{5, nullptr, "GetTimeZoneRuleVersion"},
|
||||
{100, &ITimeZoneService::ToCalendarTime, "ToCalendarTime"},
|
||||
{101, &ITimeZoneService::ToCalendarTimeWithMyRule, "ToCalendarTimeWithMyRule"},
|
||||
{201, &ITimeZoneService::ToPosixTime, "ToPosixTime"},
|
||||
{202, &ITimeZoneService::ToPosixTimeWithMyRule, "ToPosixTimeWithMyRule"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
void ITimeZoneService::GetDeviceLocationName(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called");
|
||||
|
||||
TimeZone::LocationName location_name{};
|
||||
if (const ResultCode result{
|
||||
time_zone_content_manager.GetTimeZoneManager().GetDeviceLocationName(location_name)};
|
||||
result != RESULT_SUCCESS) {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(result);
|
||||
return;
|
||||
}
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, (sizeof(location_name) / 4) + 2};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushRaw(location_name);
|
||||
}
|
||||
|
||||
void ITimeZoneService::LoadTimeZoneRule(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto raw_location_name{rp.PopRaw<std::array<u8, 0x24>>()};
|
||||
|
||||
std::string location_name;
|
||||
for (const auto& byte : raw_location_name) {
|
||||
// Strip extra bytes
|
||||
if (byte == '\0') {
|
||||
break;
|
||||
}
|
||||
location_name.push_back(byte);
|
||||
}
|
||||
|
||||
LOG_DEBUG(Service_Time, "called, location_name={}", location_name);
|
||||
|
||||
TimeZone::TimeZoneRule time_zone_rule{};
|
||||
if (const ResultCode result{
|
||||
time_zone_content_manager.LoadTimeZoneRule(time_zone_rule, location_name)};
|
||||
result != RESULT_SUCCESS) {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(result);
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<u8> time_zone_rule_outbuffer(sizeof(TimeZone::TimeZoneRule));
|
||||
std::memcpy(time_zone_rule_outbuffer.data(), &time_zone_rule, sizeof(TimeZone::TimeZoneRule));
|
||||
ctx.WriteBuffer(time_zone_rule_outbuffer);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
}
|
||||
|
||||
void ITimeZoneService::ToCalendarTime(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto posix_time{rp.Pop<s64>()};
|
||||
|
||||
LOG_DEBUG(Service_Time, "called, posix_time=0x{:016X}", posix_time);
|
||||
|
||||
TimeZone::TimeZoneRule time_zone_rule{};
|
||||
const auto buffer{ctx.ReadBuffer()};
|
||||
std::memcpy(&time_zone_rule, buffer.data(), buffer.size());
|
||||
|
||||
TimeZone::CalendarInfo calendar_info{};
|
||||
if (const ResultCode result{time_zone_content_manager.GetTimeZoneManager().ToCalendarTime(
|
||||
time_zone_rule, posix_time, calendar_info)};
|
||||
result != RESULT_SUCCESS) {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(result);
|
||||
return;
|
||||
}
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2 + (sizeof(TimeZone::CalendarInfo) / 4)};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushRaw(calendar_info);
|
||||
}
|
||||
|
||||
void ITimeZoneService::ToCalendarTimeWithMyRule(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto posix_time{rp.Pop<s64>()};
|
||||
|
||||
LOG_DEBUG(Service_Time, "called, posix_time=0x{:016X}", posix_time);
|
||||
|
||||
TimeZone::CalendarInfo calendar_info{};
|
||||
if (const ResultCode result{
|
||||
time_zone_content_manager.GetTimeZoneManager().ToCalendarTimeWithMyRules(
|
||||
posix_time, calendar_info)};
|
||||
result != RESULT_SUCCESS) {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(result);
|
||||
return;
|
||||
}
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2 + (sizeof(TimeZone::CalendarInfo) / 4)};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushRaw(calendar_info);
|
||||
}
|
||||
|
||||
void ITimeZoneService::ToPosixTime(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto calendar_time{rp.PopRaw<TimeZone::CalendarTime>()};
|
||||
TimeZone::TimeZoneRule time_zone_rule{};
|
||||
std::memcpy(&time_zone_rule, ctx.ReadBuffer().data(), sizeof(TimeZone::TimeZoneRule));
|
||||
|
||||
s64 posix_time{};
|
||||
if (const ResultCode result{time_zone_content_manager.GetTimeZoneManager().ToPosixTime(
|
||||
time_zone_rule, calendar_time, posix_time)};
|
||||
result != RESULT_SUCCESS) {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(result);
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO(bunnei): Handle multiple times
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushRaw<u32>(1); // Number of times we're returning
|
||||
ctx.WriteBuffer(&posix_time, sizeof(s64));
|
||||
}
|
||||
|
||||
void ITimeZoneService::ToPosixTimeWithMyRule(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Time, "called");
|
||||
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto calendar_time{rp.PopRaw<TimeZone::CalendarTime>()};
|
||||
|
||||
s64 posix_time{};
|
||||
if (const ResultCode result{
|
||||
time_zone_content_manager.GetTimeZoneManager().ToPosixTimeWithMyRule(calendar_time,
|
||||
posix_time)};
|
||||
result != RESULT_SUCCESS) {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(result);
|
||||
return;
|
||||
}
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
rb.PushRaw<u32>(1); // Number of times we're returning
|
||||
ctx.WriteBuffer(&posix_time, sizeof(s64));
|
||||
}
|
||||
|
||||
} // namespace Service::Time
|
||||
31
src/core/hle/service/time/time_zone_service.h
Normal file
31
src/core/hle/service/time/time_zone_service.h
Normal file
@@ -0,0 +1,31 @@
|
||||
// Copyright 2019 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Service::Time {
|
||||
|
||||
namespace TimeZone {
|
||||
class TimeZoneContentManager;
|
||||
}
|
||||
|
||||
class ITimeZoneService final : public ServiceFramework<ITimeZoneService> {
|
||||
public:
|
||||
explicit ITimeZoneService(TimeZone::TimeZoneContentManager& time_zone_manager);
|
||||
|
||||
private:
|
||||
void GetDeviceLocationName(Kernel::HLERequestContext& ctx);
|
||||
void LoadTimeZoneRule(Kernel::HLERequestContext& ctx);
|
||||
void ToCalendarTime(Kernel::HLERequestContext& ctx);
|
||||
void ToCalendarTimeWithMyRule(Kernel::HLERequestContext& ctx);
|
||||
void ToPosixTime(Kernel::HLERequestContext& ctx);
|
||||
void ToPosixTimeWithMyRule(Kernel::HLERequestContext& ctx);
|
||||
|
||||
private:
|
||||
TimeZone::TimeZoneContentManager& time_zone_content_manager;
|
||||
};
|
||||
|
||||
} // namespace Service::Time
|
||||
87
src/core/hle/service/time/time_zone_types.h
Normal file
87
src/core/hle/service/time/time_zone_types.h
Normal file
@@ -0,0 +1,87 @@
|
||||
// Copyright 2019 yuzu emulator team
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
|
||||
#include "common/common_funcs.h"
|
||||
#include "common/common_types.h"
|
||||
#include "common/swap.h"
|
||||
|
||||
namespace Service::Time::TimeZone {
|
||||
|
||||
using LocationName = std::array<char, 0x24>;
|
||||
|
||||
/// https://switchbrew.org/wiki/Glue_services#ttinfo
|
||||
struct TimeTypeInfo {
|
||||
s32 gmt_offset{};
|
||||
u8 is_dst{};
|
||||
INSERT_PADDING_BYTES(3);
|
||||
s32 abbreviation_list_index{};
|
||||
u8 is_standard_time_daylight{};
|
||||
u8 is_gmt{};
|
||||
INSERT_PADDING_BYTES(2);
|
||||
};
|
||||
static_assert(sizeof(TimeTypeInfo) == 0x10, "TimeTypeInfo is incorrect size");
|
||||
|
||||
/// https://switchbrew.org/wiki/Glue_services#TimeZoneRule
|
||||
struct TimeZoneRule {
|
||||
s32 time_count{};
|
||||
s32 type_count{};
|
||||
s32 char_count{};
|
||||
u8 go_back{};
|
||||
u8 go_ahead{};
|
||||
INSERT_PADDING_BYTES(2);
|
||||
std::array<s64, 1000> ats{};
|
||||
std::array<s8, 1000> types{};
|
||||
std::array<TimeTypeInfo, 128> ttis{};
|
||||
std::array<char, 512> chars{};
|
||||
s32 default_type{};
|
||||
INSERT_PADDING_BYTES(0x12C4);
|
||||
};
|
||||
static_assert(sizeof(TimeZoneRule) == 0x4000, "TimeZoneRule is incorrect size");
|
||||
|
||||
/// https://switchbrew.org/wiki/Glue_services#CalendarAdditionalInfo
|
||||
struct CalendarAdditionalInfo {
|
||||
u32 day_of_week{};
|
||||
u32 day_of_year{};
|
||||
std::array<char, 8> timezone_name;
|
||||
u32 is_dst{};
|
||||
s32 gmt_offset{};
|
||||
};
|
||||
static_assert(sizeof(CalendarAdditionalInfo) == 0x18, "CalendarAdditionalInfo is incorrect size");
|
||||
|
||||
/// https://switchbrew.org/wiki/Glue_services#CalendarTime
|
||||
struct CalendarTime {
|
||||
s16 year{};
|
||||
s8 month{};
|
||||
s8 day{};
|
||||
s8 hour{};
|
||||
s8 minute{};
|
||||
s8 second{};
|
||||
INSERT_PADDING_BYTES(1);
|
||||
};
|
||||
static_assert(sizeof(CalendarTime) == 0x8, "CalendarTime is incorrect size");
|
||||
|
||||
struct CalendarInfo {
|
||||
CalendarTime time{};
|
||||
CalendarAdditionalInfo additiona_info{};
|
||||
};
|
||||
static_assert(sizeof(CalendarInfo) == 0x20, "CalendarInfo is incorrect size");
|
||||
|
||||
struct TzifHeader {
|
||||
u32_be magic{};
|
||||
u8 version{};
|
||||
INSERT_PADDING_BYTES(15);
|
||||
s32_be ttis_gmt_count{};
|
||||
s32_be ttis_std_count{};
|
||||
s32_be leap_count{};
|
||||
s32_be time_count{};
|
||||
s32_be type_count{};
|
||||
s32_be char_count{};
|
||||
};
|
||||
static_assert(sizeof(TzifHeader) == 0x2C, "TzifHeader is incorrect size");
|
||||
|
||||
} // namespace Service::Time::TimeZone
|
||||
@@ -24,11 +24,11 @@ Display::Display(u64 id, std::string name, Core::System& system) : id{id}, name{
|
||||
Display::~Display() = default;
|
||||
|
||||
Layer& Display::GetLayer(std::size_t index) {
|
||||
return layers.at(index);
|
||||
return *layers.at(index);
|
||||
}
|
||||
|
||||
const Layer& Display::GetLayer(std::size_t index) const {
|
||||
return layers.at(index);
|
||||
return *layers.at(index);
|
||||
}
|
||||
|
||||
std::shared_ptr<Kernel::ReadableEvent> Display::GetVSyncEvent() const {
|
||||
@@ -43,29 +43,38 @@ void Display::CreateLayer(u64 id, NVFlinger::BufferQueue& buffer_queue) {
|
||||
// TODO(Subv): Support more than 1 layer.
|
||||
ASSERT_MSG(layers.empty(), "Only one layer is supported per display at the moment");
|
||||
|
||||
layers.emplace_back(id, buffer_queue);
|
||||
layers.emplace_back(std::make_shared<Layer>(id, buffer_queue));
|
||||
}
|
||||
|
||||
void Display::CloseLayer(u64 id) {
|
||||
layers.erase(
|
||||
std::remove_if(layers.begin(), layers.end(),
|
||||
[id](const std::shared_ptr<Layer>& layer) { return layer->GetID() == id; }),
|
||||
layers.end());
|
||||
}
|
||||
|
||||
Layer* Display::FindLayer(u64 id) {
|
||||
const auto itr = std::find_if(layers.begin(), layers.end(),
|
||||
[id](const VI::Layer& layer) { return layer.GetID() == id; });
|
||||
const auto itr =
|
||||
std::find_if(layers.begin(), layers.end(),
|
||||
[id](const std::shared_ptr<Layer>& layer) { return layer->GetID() == id; });
|
||||
|
||||
if (itr == layers.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return &*itr;
|
||||
return itr->get();
|
||||
}
|
||||
|
||||
const Layer* Display::FindLayer(u64 id) const {
|
||||
const auto itr = std::find_if(layers.begin(), layers.end(),
|
||||
[id](const VI::Layer& layer) { return layer.GetID() == id; });
|
||||
const auto itr =
|
||||
std::find_if(layers.begin(), layers.end(),
|
||||
[id](const std::shared_ptr<Layer>& layer) { return layer->GetID() == id; });
|
||||
|
||||
if (itr == layers.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return &*itr;
|
||||
return itr->get();
|
||||
}
|
||||
|
||||
} // namespace Service::VI
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -69,6 +70,12 @@ public:
|
||||
///
|
||||
void CreateLayer(u64 id, NVFlinger::BufferQueue& buffer_queue);
|
||||
|
||||
/// Closes and removes a layer from this display with the given ID.
|
||||
///
|
||||
/// @param id The ID assigned to the layer to close.
|
||||
///
|
||||
void CloseLayer(u64 id);
|
||||
|
||||
/// Attempts to find a layer with the given ID.
|
||||
///
|
||||
/// @param id The layer ID.
|
||||
@@ -91,7 +98,7 @@ private:
|
||||
u64 id;
|
||||
std::string name;
|
||||
|
||||
std::vector<Layer> layers;
|
||||
std::vector<std::shared_ptr<Layer>> layers;
|
||||
Kernel::EventPair vsync_event;
|
||||
};
|
||||
|
||||
|
||||
@@ -1066,6 +1066,18 @@ private:
|
||||
rb.Push<u64>(ctx.WriteBuffer(native_window.Serialize()));
|
||||
}
|
||||
|
||||
void CloseLayer(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto layer_id{rp.Pop<u64>()};
|
||||
|
||||
LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}", layer_id);
|
||||
|
||||
nv_flinger->CloseLayer(layer_id);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(RESULT_SUCCESS);
|
||||
}
|
||||
|
||||
void CreateStrayLayer(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const u32 flags = rp.Pop<u32>();
|
||||
@@ -1178,7 +1190,7 @@ IApplicationDisplayService::IApplicationDisplayService(
|
||||
{1101, &IApplicationDisplayService::SetDisplayEnabled, "SetDisplayEnabled"},
|
||||
{1102, &IApplicationDisplayService::GetDisplayResolution, "GetDisplayResolution"},
|
||||
{2020, &IApplicationDisplayService::OpenLayer, "OpenLayer"},
|
||||
{2021, nullptr, "CloseLayer"},
|
||||
{2021, &IApplicationDisplayService::CloseLayer, "CloseLayer"},
|
||||
{2030, &IApplicationDisplayService::CreateStrayLayer, "CreateStrayLayer"},
|
||||
{2031, &IApplicationDisplayService::DestroyStrayLayer, "DestroyStrayLayer"},
|
||||
{2101, &IApplicationDisplayService::SetLayerScalingMode, "SetLayerScalingMode"},
|
||||
|
||||
@@ -335,7 +335,8 @@ Kernel::CodeSet ElfReader::LoadInto(VAddr vaddr) {
|
||||
codeset_segment->addr = segment_addr;
|
||||
codeset_segment->size = aligned_size;
|
||||
|
||||
memcpy(&program_image[current_image_position], GetSegmentPtr(i), p->p_filesz);
|
||||
std::memcpy(program_image.data() + current_image_position, GetSegmentPtr(i),
|
||||
p->p_filesz);
|
||||
current_image_position += aligned_size;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <cstring>
|
||||
#include "core/file_sys/kernel_executable.h"
|
||||
#include "core/file_sys/program_metadata.h"
|
||||
#include "core/gdbstub/gdbstub.h"
|
||||
@@ -76,8 +77,8 @@ AppLoader::LoadResult AppLoader_KIP::Load(Kernel::Process& process) {
|
||||
segment.addr = offset;
|
||||
segment.offset = offset;
|
||||
segment.size = PageAlignSize(static_cast<u32>(data.size()));
|
||||
program_image.resize(offset);
|
||||
program_image.insert(program_image.end(), data.begin(), data.end());
|
||||
program_image.resize(offset + data.size());
|
||||
std::memcpy(program_image.data() + offset, data.data(), data.size());
|
||||
};
|
||||
|
||||
load_segment(codeset.CodeSegment(), kip->GetTextSection(), kip->GetTextOffset());
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <cinttypes>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
#include "common/common_funcs.h"
|
||||
@@ -96,8 +97,9 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process,
|
||||
if (nso_header.IsSegmentCompressed(i)) {
|
||||
data = DecompressSegment(data, nso_header.segments[i]);
|
||||
}
|
||||
program_image.resize(nso_header.segments[i].location);
|
||||
program_image.insert(program_image.end(), data.begin(), data.end());
|
||||
program_image.resize(nso_header.segments[i].location + data.size());
|
||||
std::memcpy(program_image.data() + nso_header.segments[i].location, data.data(),
|
||||
data.size());
|
||||
codeset.segments[i].addr = nso_header.segments[i].location;
|
||||
codeset.segments[i].offset = nso_header.segments[i].location;
|
||||
codeset.segments[i].size = PageAlignSize(static_cast<u32>(data.size()));
|
||||
@@ -139,12 +141,12 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process,
|
||||
std::vector<u8> pi_header;
|
||||
pi_header.insert(pi_header.begin(), reinterpret_cast<u8*>(&nso_header),
|
||||
reinterpret_cast<u8*>(&nso_header) + sizeof(NSOHeader));
|
||||
pi_header.insert(pi_header.begin() + sizeof(NSOHeader), program_image.begin(),
|
||||
program_image.end());
|
||||
pi_header.insert(pi_header.begin() + sizeof(NSOHeader), program_image.data(),
|
||||
program_image.data() + program_image.size());
|
||||
|
||||
pi_header = pm->PatchNSO(pi_header, file.GetName());
|
||||
|
||||
std::copy(pi_header.begin() + sizeof(NSOHeader), pi_header.end(), program_image.begin());
|
||||
std::copy(pi_header.begin() + sizeof(NSOHeader), pi_header.end(), program_image.data());
|
||||
}
|
||||
|
||||
// Apply cheats if they exist and the program has a valid title ID
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "common/swap.h"
|
||||
#include "core/arm/arm_interface.h"
|
||||
#include "core/core.h"
|
||||
#include "core/hle/kernel/physical_memory.h"
|
||||
#include "core/hle/kernel/process.h"
|
||||
#include "core/hle/kernel/vm_manager.h"
|
||||
#include "core/memory.h"
|
||||
@@ -38,6 +39,11 @@ struct Memory::Impl {
|
||||
system.ArmInterface(3).PageTableChanged(*current_page_table, address_space_width);
|
||||
}
|
||||
|
||||
void MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size,
|
||||
Kernel::PhysicalMemory& memory, VAddr offset) {
|
||||
MapMemoryRegion(page_table, base, size, memory.data() + offset);
|
||||
}
|
||||
|
||||
void MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size, u8* target) {
|
||||
ASSERT_MSG((size & PAGE_MASK) == 0, "non-page aligned size: {:016X}", size);
|
||||
ASSERT_MSG((base & PAGE_MASK) == 0, "non-page aligned base: {:016X}", base);
|
||||
@@ -146,7 +152,7 @@ struct Memory::Impl {
|
||||
u8* GetPointer(const VAddr vaddr) {
|
||||
u8* const page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS];
|
||||
if (page_pointer != nullptr) {
|
||||
return page_pointer + (vaddr & PAGE_MASK);
|
||||
return page_pointer + vaddr;
|
||||
}
|
||||
|
||||
if (current_page_table->attributes[vaddr >> PAGE_BITS] ==
|
||||
@@ -229,7 +235,8 @@ struct Memory::Impl {
|
||||
case Common::PageType::Memory: {
|
||||
DEBUG_ASSERT(page_table.pointers[page_index]);
|
||||
|
||||
const u8* const src_ptr = page_table.pointers[page_index] + page_offset;
|
||||
const u8* const src_ptr =
|
||||
page_table.pointers[page_index] + page_offset + (page_index << PAGE_BITS);
|
||||
std::memcpy(dest_buffer, src_ptr, copy_amount);
|
||||
break;
|
||||
}
|
||||
@@ -276,7 +283,8 @@ struct Memory::Impl {
|
||||
case Common::PageType::Memory: {
|
||||
DEBUG_ASSERT(page_table.pointers[page_index]);
|
||||
|
||||
u8* const dest_ptr = page_table.pointers[page_index] + page_offset;
|
||||
u8* const dest_ptr =
|
||||
page_table.pointers[page_index] + page_offset + (page_index << PAGE_BITS);
|
||||
std::memcpy(dest_ptr, src_buffer, copy_amount);
|
||||
break;
|
||||
}
|
||||
@@ -322,7 +330,8 @@ struct Memory::Impl {
|
||||
case Common::PageType::Memory: {
|
||||
DEBUG_ASSERT(page_table.pointers[page_index]);
|
||||
|
||||
u8* dest_ptr = page_table.pointers[page_index] + page_offset;
|
||||
u8* dest_ptr =
|
||||
page_table.pointers[page_index] + page_offset + (page_index << PAGE_BITS);
|
||||
std::memset(dest_ptr, 0, copy_amount);
|
||||
break;
|
||||
}
|
||||
@@ -368,7 +377,8 @@ struct Memory::Impl {
|
||||
}
|
||||
case Common::PageType::Memory: {
|
||||
DEBUG_ASSERT(page_table.pointers[page_index]);
|
||||
const u8* src_ptr = page_table.pointers[page_index] + page_offset;
|
||||
const u8* src_ptr =
|
||||
page_table.pointers[page_index] + page_offset + (page_index << PAGE_BITS);
|
||||
WriteBlock(process, dest_addr, src_ptr, copy_amount);
|
||||
break;
|
||||
}
|
||||
@@ -446,7 +456,8 @@ struct Memory::Impl {
|
||||
page_type = Common::PageType::Unmapped;
|
||||
} else {
|
||||
page_type = Common::PageType::Memory;
|
||||
current_page_table->pointers[vaddr >> PAGE_BITS] = pointer;
|
||||
current_page_table->pointers[vaddr >> PAGE_BITS] =
|
||||
pointer - (vaddr & ~PAGE_MASK);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -493,7 +504,9 @@ struct Memory::Impl {
|
||||
memory);
|
||||
} else {
|
||||
while (base != end) {
|
||||
page_table.pointers[base] = memory;
|
||||
page_table.pointers[base] = memory - (base << PAGE_BITS);
|
||||
ASSERT_MSG(page_table.pointers[base],
|
||||
"memory mapping base yield a nullptr within the table");
|
||||
|
||||
base += 1;
|
||||
memory += PAGE_SIZE;
|
||||
@@ -518,7 +531,7 @@ struct Memory::Impl {
|
||||
if (page_pointer != nullptr) {
|
||||
// NOTE: Avoid adding any extra logic to this fast-path block
|
||||
T value;
|
||||
std::memcpy(&value, &page_pointer[vaddr & PAGE_MASK], sizeof(T));
|
||||
std::memcpy(&value, &page_pointer[vaddr], sizeof(T));
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -559,7 +572,7 @@ struct Memory::Impl {
|
||||
u8* const page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS];
|
||||
if (page_pointer != nullptr) {
|
||||
// NOTE: Avoid adding any extra logic to this fast-path block
|
||||
std::memcpy(&page_pointer[vaddr & PAGE_MASK], &data, sizeof(T));
|
||||
std::memcpy(&page_pointer[vaddr], &data, sizeof(T));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -594,6 +607,11 @@ void Memory::SetCurrentPageTable(Kernel::Process& process) {
|
||||
impl->SetCurrentPageTable(process);
|
||||
}
|
||||
|
||||
void Memory::MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size,
|
||||
Kernel::PhysicalMemory& memory, VAddr offset) {
|
||||
impl->MapMemoryRegion(page_table, base, size, memory, offset);
|
||||
}
|
||||
|
||||
void Memory::MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size, u8* target) {
|
||||
impl->MapMemoryRegion(page_table, base, size, target);
|
||||
}
|
||||
|
||||
@@ -19,8 +19,9 @@ class System;
|
||||
}
|
||||
|
||||
namespace Kernel {
|
||||
class PhysicalMemory;
|
||||
class Process;
|
||||
}
|
||||
} // namespace Kernel
|
||||
|
||||
namespace Memory {
|
||||
|
||||
@@ -65,6 +66,19 @@ public:
|
||||
*/
|
||||
void SetCurrentPageTable(Kernel::Process& process);
|
||||
|
||||
/**
|
||||
* Maps an physical buffer onto a region of the emulated process address space.
|
||||
*
|
||||
* @param page_table The page table of the emulated process.
|
||||
* @param base The address to start mapping at. Must be page-aligned.
|
||||
* @param size The amount of bytes to map. Must be page-aligned.
|
||||
* @param memory Physical buffer with the memory backing the mapping. Must be of length
|
||||
* at least `size + offset`.
|
||||
* @param offset The offset within the physical memory. Must be page-aligned.
|
||||
*/
|
||||
void MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size,
|
||||
Kernel::PhysicalMemory& memory, VAddr offset);
|
||||
|
||||
/**
|
||||
* Maps an allocated buffer onto a region of the emulated process address space.
|
||||
*
|
||||
|
||||
@@ -401,6 +401,9 @@ struct Values {
|
||||
std::string motion_device;
|
||||
TouchscreenInput touchscreen;
|
||||
std::atomic_bool is_device_reload_pending{true};
|
||||
std::string udp_input_address;
|
||||
u16 udp_input_port;
|
||||
u8 udp_pad_index;
|
||||
|
||||
// Core
|
||||
bool use_multi_core;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user