Compare commits

..

69 Commits

Author SHA1 Message Date
Lioncash
524eb15513 video_core/texture_cache: Amend Doxygen references
Amends the doxygen comments so that they properly resolve. While we're
at it, we can correct some typos and fix up some of the comments'
formatting in order to make them slightly nicer to read.
2019-10-15 15:40:00 -04:00
bunnei
cab2619aeb Merge pull request #2965 from FernandoS27/fair-core-timing
Core Timing: Rework Core Timing to run all cores evenly.
2019-10-15 11:48:30 -04:00
bunnei
0378babd15 Merge pull request #2897 from DarkLordZach/oss-ext-fonts-1
pl_u: Move open source font archives and fix NAND error
2019-10-14 15:13:41 -04:00
bunnei
c274fd588d Merge pull request #2968 from FreddyFunk/fix-zl-zr-analog-triggers
yuzu/configure_input_player: Fix input handling for ZL and ZR from controllers with analog triggers
2019-10-14 13:04:49 -04:00
bunnei
cd2efed922 Merge pull request #2930 from DarkLordZach/gamecard-partitions
file_sys: Add code to access raw gamecard partitions and lazily load them
2019-10-14 10:29:10 -04:00
Zach Hilman
e0b9ee9b94 card_image: Implement system update commands in XCI 2019-10-13 14:18:45 -04:00
Zach Hilman
1911f85391 pl_u: Fix mismatched rebase size error in font encryption 2019-10-13 13:46:27 -04:00
Zach Hilman
36d829c27b pl_u: Use kernel physical memory 2019-10-13 13:46:27 -04:00
Zach Hilman
b3a8a094a5 pl_u: Remove excess static qualifier 2019-10-13 13:46:27 -04:00
Zach Hilman
40284c6868 pl_u: Use OSS system archives if real archives don't exist 2019-10-13 13:46:27 -04:00
Zach Hilman
920742d418 system_archive: Synthesize shared fonts system archives 2019-10-13 13:46:10 -04:00
Zach Hilman
d6d6a87bde externals: Move OSS font data to file_sys in core 2019-10-13 13:46:10 -04:00
Fernando Sahmkow
a4ae11d63e Core_Timing: Address Remaining feedback. 2019-10-12 07:26:38 -04:00
Fernando Sahmkow
91f6333e23 Core_Timing: Fix tests. 2019-10-12 07:23:08 -04:00
Fernando Sahmkow
e0650a2034 Core_Timing: Address Feedback and suppress warnings. 2019-10-11 14:44:14 -04:00
FreddyFunk
be5dc68ca3 fixed clang format & addressed feedback 2019-10-10 23:27:00 +02:00
FreddyFunk
a31c6b2c4e yuzu/configure_input_player: Fix input handling for ZL and ZR from controllers with analog triggers 2019-10-10 23:12:06 +02:00
bunnei
b41692b69b Merge pull request #2910 from FearlessTobi/port-4930
Port citra-emu/citra#4930: "Pause when in background"
2019-10-09 21:36:51 -04:00
bunnei
d46e523fda Merge pull request #2915 from vitor-k/patch-1
Link to Yuzu's wiki instead of Citra's
2019-10-09 21:35:48 -04:00
bunnei
2ba273e49e Merge pull request #2928 from ReinUsesLisp/dirty-depth-bounds
maxwell_3d: Add dirty flags for depth bounds values
2019-10-09 15:44:30 -04:00
bunnei
6b5e50d20e Merge pull request #2927 from ReinUsesLisp/polygon-offset-units
gl_rasterizer: Fix polygon offset units
2019-10-09 15:38:52 -04:00
Fernando Sahmkow
96f2b16356 Core Timing: Correct Idle and remove lefting pragma 2019-10-09 12:30:33 -04:00
Fernando Sahmkow
65aff6930b Core Timing: General corrections and added tests. 2019-10-09 12:30:33 -04:00
Fernando Sahmkow
c9a1129c95 Tests: Eliminate old Core Timing Tests 2019-10-09 12:30:32 -04:00
Fernando Sahmkow
555866f8dc Core Timing: Rework Core Timing to run all cores evenly. 2019-10-09 12:30:31 -04:00
bunnei
e664c24355 Merge pull request #2921 from FreddyFunk/compiler-warnings-core
Services::ES fix casting warnings
2019-10-09 10:34:48 -04:00
bunnei
f1990f57f4 Merge pull request #2964 from Schplee/update-icon
Updated yuzu icon to thicker version
2019-10-09 10:33:28 -04:00
Schplee
3969591a13 Updated yuzu icon to thicker version 2019-10-08 23:33:51 -07:00
bunnei
b9c831de62 Merge pull request #2654 from DarkLordZach/lm-log-rewrite
lm: Rewrite logger to use core reporting services
2019-10-08 20:23:13 -04:00
bunnei
464353bc57 Merge pull request #2961 from DarkLordZach/azure-tag-names
ci: Correct azure tag and release names
2019-10-08 20:16:28 -04:00
bunnei
e17067642d Merge pull request #2956 from DarkLordZach/azure-win-tarxz
ci: Add TAR-XZ compression to MSVC builds
2019-10-08 20:09:48 -04:00
Zach Hilman
1817191d55 ci: Isolate upload merge step into stage 2 2019-10-08 19:52:02 -04:00
Zach Hilman
1ec23a0353 ci: Update build suffix for mock builds 2019-10-08 19:51:24 -04:00
Fernando Sahmkow
971870b89d Merge pull request #2959 from ReinUsesLisp/cbuf-hsetp2
shader/half_set_predicate: Fix HSETP2 for constant buffers
2019-10-08 12:00:44 -04:00
ReinUsesLisp
3d0f357307 shader/half_set_predicate: Fix HSETP2 for constant buffers
HSETP2 when used with a constant buffer parses the second operand type
as F32. This is not configurable.
2019-10-07 14:49:47 -03:00
ReinUsesLisp
632c9e4ee3 shader/half_set_predicate: Reduce DEBUG_ASSERT to LOG_DEBUG 2019-10-07 14:48:58 -03:00
bunnei
e53e6b43f5 Merge pull request #2890 from Morph1984/hid_deactivatenpad
hid: Implement DeactivateNpad
2019-10-07 12:26:32 -04:00
Morph
29e15601f3 hid: Implement DeactivateNpad
Makes use of the already existing DeactivateController function.
2019-10-07 04:44:09 -07:00
Zach Hilman
5326d3cb3a Merge pull request #2951 from lioncash/global
core: Remove Core::CurrentProcess()
2019-10-06 20:47:48 -04:00
Zach Hilman
df80e89b8f ci: Add TAR-XZ compression to MSVC builds 2019-10-06 20:44:30 -04:00
Rodrigo Locatti
dcdd887df3 Merge pull request #2952 from lioncash/warning
bcat: Silence various warnings
2019-10-06 23:35:12 +00:00
Rodrigo Locatti
3cb4c9f08a Merge pull request #2955 from lioncash/allocator
alignment: Resolve allocator construction issues on debug
2019-10-06 23:30:54 +00:00
Lioncash
57ffada746 alignment: Resolve allocator construction issues on debug
This was related to the source allocator being passed into the
constructor potentially having a different type than allocator being
constructed.

We simply need to provide a constructor to handle this case.

This resolves issues related to the allocator causing debug builds on
MSVC to fail.
2019-10-06 18:49:49 -04:00
Lioncash
9aafb2a277 alignment: Specify trait definitions within the allocator
Allows containers and other data structures to consider optimizations
based off of them. We satisfy all of these requirements anyways.
2019-10-06 18:48:05 -04:00
Fernando Sahmkow
8f407adeeb Merge pull request #2954 from ReinUsesLisp/fix-invalidation
gl_shader_disk_cache: Properly ignore existing cache
2019-10-06 17:48:14 -04:00
ReinUsesLisp
58b597c5ec gl_shader_disk_cache: Properly ignore existing cache
Previously old entries where appended to the file even if the shader
cache was ignored at boot. Address that issue.
2019-10-06 18:00:20 -03:00
Lioncash
0705ce0ed1 bcat/module: Silence truncation warnings
We need to perform explicit casts here, otherwise we're implicitly
truncating a 64-bit type to a 32-bit one.
2019-10-06 15:38:12 -04:00
Lioncash
7e77d1593f bcat: Take std::function instance by value in NullBackend's constructor
Without this, the std::move within the constructor initializer list
won't be able to actually perform a move.
2019-10-06 15:38:12 -04:00
Lioncash
81adf46d1d bcat: In-class initialize ProgressServiceBackend's impl member
Allows us to remove a constructor initializer list.
2019-10-06 15:38:12 -04:00
Lioncash
3fcd2180e4 bcat: Make ProgressServiceBackend's constructor take a std::string_view
Given the string is appended to another, we can make it a view so a
redundant full copy of the string isn't made.
2019-10-06 15:38:09 -04:00
bunnei
123c0580b4 Merge pull request #2953 from DarkLordZach/azure-titlebars-gamename
qt: Fix game name format error
2019-10-06 15:13:57 -04:00
Lioncash
f2fa16b609 bcat: Make ProgressServiceBackend's GetEvent() const
This member function doesn't modify internal member state, so it can be
marked const.
2019-10-06 14:03:18 -04:00
Lioncash
329081fcb7 boxcat: Silence an unused variable warning
On parse errors, we can log out the explanatory string indicating what
the parsing error was, rather than just ignoring the variable and
returning an overly broad error code.
2019-10-06 14:00:32 -04:00
Lioncash
839b38c404 core/core: Remove unused header
This isn't used anywhere in either the cpp or header file.
2019-10-06 13:54:27 -04:00
Lioncash
f1382cf0e7 core: Remove Core::CurrentProcess()
This only encourages the use of the global system instance (which will
be phased out long-term). Instead, we use the direct system function
call directly to remove the appealing but discouraged short-hand.
2019-10-06 13:53:12 -04:00
Lioncash
69f16ba50e hle/service: Replace global system instance calls with instance-based ones
Migrates the HLE service code off the use of directly accessing the
global system instance where trivially able to do so.

This removes all usages of Core::CurrentProcess from the service code,
only 8 occurrences of this function exist elsewhere. There's still quite
a bit of "System::GetInstance()" being used, however this was able to
replace a few instances.
2019-10-06 13:42:23 -04:00
ReinUsesLisp
fe7f20e659 maxwell_3d: Add dirty flags for depth bounds values
This is useful in Vulkan where we want to update depth bounds without
caring if it's enabled or disabled through vkCmdSetDepthBounds.
2019-10-05 04:07:47 +00:00
ReinUsesLisp
69c806feb6 gl_rasterizer: Fix polygon offset units
For some reason hardware divides polygon offset units by two. This is
visible since drivers multiply the application requested polygon offset
by two.
2019-10-01 02:00:23 -03:00
FreddyFunk
7b93c4646a Services::ES fix casting warnings 2019-09-29 22:45:09 +02:00
Vitor K
d901983085 Link to Yuzu's wiki instead of Citra's
The original Contributing.md had differences, such as some links, so I created a page on yuzu's wiki based on the original file.
2019-09-27 21:49:08 -03:00
FearlessTobi
b89fb6e1be yuzu: Pause when in background
Co-Authored-By: Vitor K <vitor-k@users.noreply.github.com>
2019-09-26 14:54:31 +02:00
Zach Hilman
c4f3400bea card_image: Add accessors for raw partitions in XCI 2019-09-22 21:51:46 -04:00
Zach Hilman
3952c73aee card_image: Lazily load partitions in XCI 2019-09-22 21:50:29 -04:00
Zach Hilman
3895f7e456 pfs: Provide accessors for file sizes and offsets 2019-09-22 21:44:36 -04:00
Zach Hilman
6212df3beb lm: Flush manager output on core shutdown 2019-09-22 12:34:55 -04:00
Zach Hilman
fa6531ab0f lm: Rename Initialize to Log and implement with manager/reporter
Allows saving and clearer output of data.
2019-09-22 12:34:55 -04:00
Zach Hilman
ef9a7fa1f5 lm: Implement manager class to output to reporter 2019-09-22 12:34:55 -04:00
Zach Hilman
4153bd8d17 core: Add LM::Manager to system
Allows centralized control over logging mechanisms.
2019-09-22 12:34:55 -04:00
Zach Hilman
82bf055eca reporter: Add log output for packaged lm log data
Takes the vector from head to tail of log data and saves it.
2019-09-22 12:34:33 -04:00
102 changed files with 74457 additions and 112449 deletions

View File

@@ -5,6 +5,8 @@ $RELEASE_DIST = "yuzu-windows-msvc"
$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 " ", ""
$MSVC_TAR = "yuzu-windows-msvc-$GITDATE-$GITREV.tar" -replace " ", ""
$MSVC_TARXZ = "yuzu-windows-msvc-$GITDATE-$GITREV.tar.xz" -replace " ", ""
$env:BUILD_ZIP = $MSVC_BUILD_ZIP
$env:BUILD_SYMBOLS = $MSVC_BUILD_PDB
@@ -28,5 +30,9 @@ Copy-Item .\README.md -Destination $RELEASE_DIST
7z a -tzip $MSVC_BUILD_ZIP $RELEASE_DIST\*
7z a $MSVC_SEVENZIP $RELEASE_DIST
7z a -r -ttar $MSVC_TAR $RELEASE_DIST
7z a -r -txz $MSVC_TARXZ $MSVC_TAR
Get-ChildItem . -Filter "*.zip" | Copy-Item -destination "artifacts"
Get-ChildItem . -Filter "*.7z" | Copy-Item -destination "artifacts"
Get-ChildItem . -Filter "*.7z" | Copy-Item -destination "artifacts"
Get-ChildItem . -Filter "*.tar.xz" | Copy-Item -destination "artifacts"

View File

@@ -1,5 +1,5 @@
steps:
- script: mkdir artifacts || echo 'X' > artifacts/T1.txt
- publish: artifacts
artifact: 'yuzu-$(BuildName)-$(BuildSuffix)'
artifact: 'yuzu-$(BuildName)-mock'
displayName: 'Upload Artifacts'

View File

@@ -31,17 +31,7 @@ jobs:
needSubmodules: 'true'
- script: chmod a+x $(System.DefaultWorkingDirectory)/.ci/scripts/merge/yuzubot-git-config.sh && $(System.DefaultWorkingDirectory)/.ci/scripts/merge/yuzubot-git-config.sh
displayName: 'Apply Git Configuration'
- script: git tag -a $(BuildName)-$(Build.BuildId) -m "yuzu $(BuildName) $(Build.BuildNumber) $(Build.DefinitionName)"
displayName: 'Tag Source'
- script: git remote add other $(GitRepoPushChangesURL)
displayName: 'Register Repository'
- script: git push --follow-tags --force other HEAD:$(GitPushBranch)
- script: git push --force other HEAD:$(GitPushBranch)
displayName: 'Update Code'
- script: git rev-list -n 1 $(BuildName)-$(Build.BuildId) > $(Build.ArtifactStagingDirectory)/tag-commit.sha
displayName: 'Calculate Release Point'
- task: PublishPipelineArtifact@1
displayName: 'Upload Release Point'
inputs:
targetPath: '$(Build.ArtifactStagingDirectory)/tag-commit.sha'
artifact: 'yuzu-$(BuildName)-release-point'
replaceExistingArchive: true

View File

@@ -30,17 +30,7 @@ jobs:
needSubmodules: 'true'
- script: chmod a+x $(System.DefaultWorkingDirectory)/.ci/scripts/merge/yuzubot-git-config.sh && $(System.DefaultWorkingDirectory)/.ci/scripts/merge/yuzubot-git-config.sh
displayName: 'Apply Git Configuration'
- script: git tag -a $(BuildName)-$(Build.BuildId) -m "yuzu $(BuildName) $(Build.BuildNumber) $(Build.DefinitionName)"
displayName: 'Tag Source'
- script: git remote add other $(GitRepoPushChangesURL)
displayName: 'Register Repository'
- script: git push --follow-tags --force other HEAD:$(GitPushBranch)
- script: git push --force other HEAD:$(GitPushBranch)
displayName: 'Update Code'
- script: git rev-list -n 1 $(BuildName)-$(Build.BuildId) > $(Build.ArtifactStagingDirectory)/tag-commit.sha
displayName: 'Calculate Release Point'
- task: PublishPipelineArtifact@1
displayName: 'Upload Release Point'
inputs:
targetPath: '$(Build.ArtifactStagingDirectory)/tag-commit.sha'
artifact: 'yuzu-$(BuildName)-release-point'
replaceExistingArchive: true

View File

@@ -1,11 +1,13 @@
steps:
- template: ./release-download.yml
- task: GitHubRelease@0
displayName: 'GitHub Release'
inputs:
action: 'create'
title: 'yuzu $(BuildName) #$(Build.BuildId)'
title: '$(ReleasePrefix) $(DisplayVersion)'
assets: '$(Build.ArtifactStagingDirectory)/*'
gitHubConnection: $(GitHubReleaseConnectionName)
repositoryName: '$(Build.Repository.Name)'
target: '$(Build.SourceVersion)'
tagSource: 'auto'
tagSource: manual
tag: $(BuildName)-$(DisplayPrefix)-$(DisplayVersion)

View File

@@ -0,0 +1,9 @@
steps:
- script: chmod a+x $(System.DefaultWorkingDirectory)/.ci/scripts/merge/yuzubot-git-config.sh && $(System.DefaultWorkingDirectory)/.ci/scripts/merge/yuzubot-git-config.sh
displayName: 'Apply Git Configuration'
- script: git tag -a $(BuildName)-$(DisplayPrefix)-$(DisplayVersion) -m "yuzu $(BuildName) $(Build.BuildNumber) $(Build.DefinitionName) $(DisplayPrefix)-$(DisplayVersion)"
displayName: 'Tag Source'
- script: git remote add other $(GitRepoPushChangesURL)
displayName: 'Register Repository'
- script: git push other $(BuildName)-$(DisplayPrefix)-$(DisplayVersion)
displayName: 'Update Code'

View File

@@ -57,12 +57,12 @@ stages:
cache: 'true'
version: $(DisplayVersion)
- stage: release
displayName: 'Release'
displayName: 'release'
dependsOn:
- build
- build_win
jobs:
- job: github
displayName: 'GitHub Release'
displayName: 'github'
steps:
- template: ./templates/release-github.yml

View File

@@ -32,3 +32,11 @@ stages:
artifactSource: 'false'
cache: $(parameters.cache)
version: $(DisplayVersion)
- stage: release
displayName: 'release'
dependsOn: build
jobs:
- job: release
displayName: 'source'
steps:
- template: ./templates/release-private-tag.yml

View File

@@ -1 +1 @@
**The Contributor's Guide has moved to [the Citra wiki](https://github.com/citra-emu/citra/wiki/Contributing).**
**The Contributor's Guide has moved to [the Yuzu wiki](https://github.com/yuzu-emu/yuzu/wiki/Contributing).**

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.0 KiB

After

Width:  |  Height:  |  Size: 10 KiB

BIN
dist/yuzu.icns vendored

Binary file not shown.

BIN
dist/yuzu.ico vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 361 KiB

After

Width:  |  Height:  |  Size: 23 KiB

87
dist/yuzu.svg vendored
View File

@@ -1,86 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="svg815"
xml:space="preserve"
width="72"
height="80"
viewBox="0 0 72 80"
sodipodi:docname="center-logo-v3.svg"
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"><metadata
id="metadata821"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs819"><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath831"><path
d="M 0,60 H 54 V 0 H 0 Z"
id="path829"
inkscape:connector-curvature="0" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath843"><path
d="M 0,60 H 54 V 0 H 0 Z"
id="path841"
inkscape:connector-curvature="0" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath855"><path
d="M 0,60 H 54 V 0 H 0 Z"
id="path853"
inkscape:connector-curvature="0" /></clipPath><clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath867"><path
d="M 0,60 H 54 V 0 H 0 Z"
id="path865"
inkscape:connector-curvature="0" /></clipPath></defs><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1017"
id="namedview817"
showgrid="false"
inkscape:zoom="7.4953319"
inkscape:cx="28.177201"
inkscape:cy="44.348084"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="g823" /><g
id="g823"
inkscape:groupmode="layer"
inkscape:label="center-logo-v3"
transform="matrix(1.3333333,0,0,-1.3333333,0,80)"><g
id="right"
inkscape:label="#g825"><g
id="g827"
clip-path="url(#clipPath831)"><g
id="g833"
transform="translate(30,48)"><path
d="m 0,0 v -48 c 13.255,0 24,10.745 24,24 C 24,-10.745 13.255,0 0,0 M 3,-3.214 C 13.163,-4.674 21,-13.439 21,-24 21,-34.561 13.163,-43.326 3,-44.786 v 41.572"
style="fill:#ff3c28;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path835"
inkscape:connector-curvature="0" /></g></g></g><g
id="left"
inkscape:label="#g837"><g
id="g839"
clip-path="url(#clipPath843)"><g
id="g845"
transform="translate(24,60)"><path
d="m 0,0 c -13.255,0 -24,-10.745 -24,-24 0,-13.255 10.745,-24 24,-24 z m -3,-3.214 v -41.572 c -10.163,1.46 -18,10.225 -18,20.786 0,10.561 7.837,19.326 18,20.786"
style="fill:#0ab9e6;fill-opacity:1;fill-rule:nonzero;stroke:none"
id="path847"
inkscape:connector-curvature="0" /></g></g></g></g></svg>
<svg id="svg815" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 614.4 682.67"><defs><style>.cls-1{fill:none;}.cls-2{clip-path:url(#clip-path);}.cls-3{fill:#ff3c28;}.cls-4{fill:#0ab9e6;}</style><clipPath id="clip-path"><rect class="cls-1" x="-43" y="-46.67" width="699.6" height="777.33"/></clipPath></defs><title>Artboard 1</title><g id="g823"><g id="right"><g class="cls-2"><g id="g827"><g id="g833"><path id="path835" class="cls-3" d="M340.81,138V682.08c150.26,0,272.06-121.81,272.06-272.06S491.07,138,340.81,138M394,197.55a219.06,219.06,0,0,1,0,424.94V197.55"/></g></g></g></g><g id="left"><g class="cls-2"><g id="g839"><g id="g845"><path id="path847" class="cls-4" d="M272.79,1.92C122.53,1.92.73,123.73.73,274s121.8,272.07,272.06,272.07ZM219.65,61.51v425A219,219,0,0,1,118,119.18,217.51,217.51,0,0,1,219.65,61.51"/></g></g></g></g></g></svg>

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 889 B

View File

@@ -42,9 +42,6 @@ target_include_directories(mbedtls PUBLIC ./mbedtls/include)
add_library(microprofile INTERFACE)
target_include_directories(microprofile INTERFACE ./microprofile)
# Open Source Archives
add_subdirectory(open_source_archives EXCLUDE_FROM_ALL)
# Unicorn
add_library(unicorn-headers INTERFACE)
target_include_directories(unicorn-headers INTERFACE ./unicorn/include)

View File

@@ -1,16 +0,0 @@
add_library(open_source_archives
src/FontChineseSimplified.cpp
src/FontChineseTraditional.cpp
src/FontExtendedChineseSimplified.cpp
src/FontKorean.cpp
src/FontNintendoExtended.cpp
src/FontStandard.cpp
include/FontChineseSimplified.h
include/FontChineseTraditional.h
include/FontExtendedChineseSimplified.h
include/FontKorean.h
include/FontNintendoExtended.h
include/FontStandard.h
)
target_include_directories(open_source_archives PUBLIC include)

View File

@@ -1,4 +0,0 @@
These files were generated by https://github.com/FearlessTobi/yuzu_system_archives at git commit 0a24b0c9f38d71fb2c4bba5645a39029e539a5ec. To generate the files use the run.sh inside that repository.
The follwing system archives are currently included:
- JPN/EUR/USA System Font

View File

@@ -1,6 +0,0 @@
#pragma once
#include <array>
extern const std::array<unsigned char, 217276> FontChineseSimplified;

View File

@@ -1,6 +0,0 @@
#pragma once
#include <array>
extern const std::array<unsigned char, 222236> FontChineseTraditional;

View File

@@ -1,6 +0,0 @@
#pragma once
#include <array>
extern const std::array<unsigned char, 293516> FontExtendedChineseSimplified;

View File

@@ -1,6 +0,0 @@
#pragma once
#include <array>
extern const std::array<unsigned char, 217276> FontKorean;

View File

@@ -1,6 +0,0 @@
#pragma once
#include <array>
extern const std::array<unsigned char, 172064> FontNintendoExtended;

View File

@@ -1,6 +0,0 @@
#pragma once
#include <array>
extern const std::array<unsigned char, 217276> FontStandard;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -51,7 +51,17 @@ public:
using reference = T&;
using const_reference = const T&;
using propagate_on_container_copy_assignment = std::true_type;
using propagate_on_container_move_assignment = std::true_type;
using propagate_on_container_swap = std::true_type;
using is_always_equal = std::true_type;
public:
constexpr AlignmentAllocator() noexcept = default;
template <typename T2>
constexpr AlignmentAllocator(const AlignmentAllocator<T2, Align>&) noexcept {}
pointer address(reference r) noexcept {
return std::addressof(r);
}

View File

@@ -74,10 +74,24 @@ add_library(core STATIC
file_sys/sdmc_factory.h
file_sys/submission_package.cpp
file_sys/submission_package.h
file_sys/system_archive/data/font_chinese_simplified.cpp
file_sys/system_archive/data/font_chinese_simplified.h
file_sys/system_archive/data/font_chinese_traditional.cpp
file_sys/system_archive/data/font_chinese_traditional.h
file_sys/system_archive/data/font_extended_chinese_simplified.cpp
file_sys/system_archive/data/font_extended_chinese_simplified.h
file_sys/system_archive/data/font_korean.cpp
file_sys/system_archive/data/font_korean.h
file_sys/system_archive/data/font_nintendo_extended.cpp
file_sys/system_archive/data/font_nintendo_extended.h
file_sys/system_archive/data/font_standard.cpp
file_sys/system_archive/data/font_standard.h
file_sys/system_archive/mii_model.cpp
file_sys/system_archive/mii_model.h
file_sys/system_archive/ng_word.cpp
file_sys/system_archive/ng_word.h
file_sys/system_archive/shared_font.cpp
file_sys/system_archive/shared_font.h
file_sys/system_archive/system_archive.cpp
file_sys/system_archive/system_archive.h
file_sys/system_archive/system_version.cpp
@@ -335,6 +349,8 @@ add_library(core STATIC
hle/service/ldr/ldr.h
hle/service/lm/lm.cpp
hle/service/lm/lm.h
hle/service/lm/manager.cpp
hle/service/lm/manager.h
hle/service/mig/mig.cpp
hle/service/mig/mig.h
hle/service/mii/mii.cpp
@@ -509,7 +525,7 @@ add_library(core STATIC
create_target_directory_groups(core)
target_link_libraries(core PUBLIC common PRIVATE audio_core video_core)
target_link_libraries(core PUBLIC Boost::boost PRIVATE fmt json-headers mbedtls opus unicorn open_source_archives)
target_link_libraries(core PUBLIC Boost::boost PRIVATE fmt json-headers mbedtls opus unicorn)
if (YUZU_ENABLE_BOXCAT)
get_directory_property(OPENSSL_LIBS

View File

@@ -116,7 +116,7 @@ public:
num_interpreted_instructions = 0;
}
u64 GetTicksRemaining() override {
return std::max(parent.system.CoreTiming().GetDowncount(), 0);
return std::max(parent.system.CoreTiming().GetDowncount(), s64{0});
}
u64 GetCNTPCT() override {
return Timing::CpuCyclesToClockCycles(parent.system.CoreTiming().GetTicks());

View File

@@ -156,7 +156,7 @@ void ARM_Unicorn::Run() {
if (GDBStub::IsServerEnabled()) {
ExecuteInstructions(std::max(4000000, 0));
} else {
ExecuteInstructions(std::max(system.CoreTiming().GetDowncount(), 0));
ExecuteInstructions(std::max(system.CoreTiming().GetDowncount(), s64{0}));
}
}

View File

@@ -35,6 +35,7 @@
#include "core/hle/service/apm/controller.h"
#include "core/hle/service/filesystem/filesystem.h"
#include "core/hle/service/glue/manager.h"
#include "core/hle/service/lm/manager.h"
#include "core/hle/service/service.h"
#include "core/hle/service/sm/sm.h"
#include "core/loader/loader.h"
@@ -111,7 +112,8 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
}
struct System::Impl {
explicit Impl(System& system)
: kernel{system}, cpu_core_manager{system}, applet_manager{system}, reporter{system} {}
: kernel{system}, fs_controller{system}, cpu_core_manager{system},
applet_manager{system}, reporter{system} {}
Cpu& CurrentCpuCore() {
return cpu_core_manager.GetCurrentCore();
@@ -249,6 +251,8 @@ struct System::Impl {
telemetry_session->AddField(Telemetry::FieldType::Performance, "Mean_Frametime_MS",
perf_stats->GetMeanFrametime());
lm_manager.Flush();
is_powered_on = false;
exit_lock = false;
@@ -337,6 +341,7 @@ struct System::Impl {
bool is_powered_on = false;
bool exit_lock = false;
Reporter reporter;
std::unique_ptr<Memory::CheatEngine> cheat_engine;
std::unique_ptr<Tools::Freezer> memory_freezer;
std::array<u8, 0x20> build_id{};
@@ -347,8 +352,9 @@ struct System::Impl {
/// APM (Performance) services
Service::APM::Controller apm_controller{core_timing};
/// Glue services
/// Service State
Service::Glue::ARPManager arp_manager;
Service::LM::Manager lm_manager{reporter};
/// Service manager
std::shared_ptr<Service::SM::ServiceManager> service_manager;
@@ -356,8 +362,6 @@ struct System::Impl {
/// Telemetry session for this emulation session
std::unique_ptr<Core::TelemetrySession> telemetry_session;
Reporter reporter;
ResultStatus status = ResultStatus::Success;
std::string status_details = "";
@@ -633,6 +637,14 @@ const Service::APM::Controller& System::GetAPMController() const {
return impl->apm_controller;
}
Service::LM::Manager& System::GetLogManager() {
return impl->lm_manager;
}
const Service::LM::Manager& System::GetLogManager() const {
return impl->lm_manager;
}
void System::SetExitLock(bool locked) {
impl->exit_lock = locked;
}
@@ -641,11 +653,11 @@ bool System::GetExitLock() const {
return impl->exit_lock;
}
void System::SetCurrentProcessBuildID(std::array<u8, 32> id) {
void System::SetCurrentProcessBuildID(const CurrentBuildProcessID& id) {
impl->build_id = id;
}
const std::array<u8, 32>& System::GetCurrentProcessBuildID() const {
const System::CurrentBuildProcessID& System::GetCurrentProcessBuildID() const {
return impl->build_id;
}

View File

@@ -8,7 +8,6 @@
#include <memory>
#include <string>
#include <map>
#include "common/common_types.h"
#include "core/file_sys/vfs_types.h"
#include "core/hle/kernel/object.h"
@@ -58,6 +57,10 @@ namespace Glue {
class ARPManager;
}
namespace LM {
class Manager;
} // namespace LM
namespace SM {
class ServiceManager;
} // namespace SM
@@ -98,6 +101,8 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
class System {
public:
using CurrentBuildProcessID = std::array<u8, 0x20>;
System(const System&) = delete;
System& operator=(const System&) = delete;
@@ -326,13 +331,17 @@ public:
const Service::APM::Controller& GetAPMController() const;
Service::LM::Manager& GetLogManager();
const Service::LM::Manager& GetLogManager() const;
void SetExitLock(bool locked);
bool GetExitLock() const;
void SetCurrentProcessBuildID(std::array<u8, 0x20> id);
void SetCurrentProcessBuildID(const CurrentBuildProcessID& id);
const std::array<u8, 0x20>& GetCurrentProcessBuildID() const;
const CurrentBuildProcessID& GetCurrentProcessBuildID() const;
private:
System();
@@ -357,8 +366,4 @@ private:
static System s_instance;
};
inline Kernel::Process* CurrentProcess() {
return System::GetInstance().CurrentProcess();
}
} // namespace Core

View File

@@ -85,24 +85,16 @@ void Cpu::RunLoop(bool tight_loop) {
// 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);
if (IsMainCore()) {
// TODO(Subv): Only let CoreTiming idle if all 4 cores are idling.
core_timing.Idle();
core_timing.Advance();
}
core_timing.Idle();
core_timing.Advance();
PrepareReschedule();
} else {
if (IsMainCore()) {
core_timing.Advance();
}
if (tight_loop) {
arm_interface->Run();
} else {
arm_interface->Step();
}
core_timing.Advance();
}
Reschedule();

View File

@@ -15,7 +15,7 @@
namespace Core::Timing {
constexpr int MAX_SLICE_LENGTH = 20000;
constexpr int MAX_SLICE_LENGTH = 10000;
struct CoreTiming::Event {
s64 time;
@@ -38,10 +38,12 @@ CoreTiming::CoreTiming() = default;
CoreTiming::~CoreTiming() = default;
void CoreTiming::Initialize() {
downcount = MAX_SLICE_LENGTH;
downcounts.fill(MAX_SLICE_LENGTH);
time_slice.fill(MAX_SLICE_LENGTH);
slice_length = MAX_SLICE_LENGTH;
global_timer = 0;
idled_cycles = 0;
current_context = 0;
// The time between CoreTiming being initialized and the first call to Advance() is considered
// the slice boundary between slice -1 and slice 0. Dispatcher loops must call Advance() before
@@ -110,7 +112,7 @@ void CoreTiming::UnscheduleEvent(const EventType* event_type, u64 userdata) {
u64 CoreTiming::GetTicks() const {
u64 ticks = static_cast<u64>(global_timer);
if (!is_global_timer_sane) {
ticks += slice_length - downcount;
ticks += accumulated_ticks;
}
return ticks;
}
@@ -120,7 +122,8 @@ u64 CoreTiming::GetIdleTicks() const {
}
void CoreTiming::AddTicks(u64 ticks) {
downcount -= static_cast<int>(ticks);
accumulated_ticks += ticks;
downcounts[current_context] -= static_cast<s64>(ticks);
}
void CoreTiming::ClearPendingEvents() {
@@ -141,22 +144,35 @@ void CoreTiming::RemoveEvent(const EventType* event_type) {
void CoreTiming::ForceExceptionCheck(s64 cycles) {
cycles = std::max<s64>(0, cycles);
if (downcount <= cycles) {
if (downcounts[current_context] <= cycles) {
return;
}
// downcount is always (much) smaller than MAX_INT so we can safely cast cycles to an int
// here. Account for cycles already executed by adjusting the g.slice_length
slice_length -= downcount - static_cast<int>(cycles);
downcount = static_cast<int>(cycles);
downcounts[current_context] = static_cast<int>(cycles);
}
std::optional<u64> CoreTiming::NextAvailableCore(const s64 needed_ticks) const {
const u64 original_context = current_context;
u64 next_context = (original_context + 1) % num_cpu_cores;
while (next_context != original_context) {
if (time_slice[next_context] >= needed_ticks) {
return {next_context};
} else if (time_slice[next_context] >= 0) {
return std::nullopt;
}
next_context = (next_context + 1) % num_cpu_cores;
}
return std::nullopt;
}
void CoreTiming::Advance() {
std::unique_lock<std::mutex> guard(inner_mutex);
const int cycles_executed = slice_length - downcount;
const u64 cycles_executed = accumulated_ticks;
time_slice[current_context] = std::max<s64>(0, time_slice[current_context] - accumulated_ticks);
global_timer += cycles_executed;
slice_length = MAX_SLICE_LENGTH;
is_global_timer_sane = true;
@@ -173,24 +189,46 @@ void CoreTiming::Advance() {
// Still events left (scheduled in the future)
if (!event_queue.empty()) {
slice_length = static_cast<int>(
std::min<s64>(event_queue.front().time - global_timer, MAX_SLICE_LENGTH));
const s64 needed_ticks =
std::min<s64>(event_queue.front().time - global_timer, MAX_SLICE_LENGTH);
const auto next_core = NextAvailableCore(needed_ticks);
if (next_core) {
downcounts[*next_core] = needed_ticks;
}
}
downcount = slice_length;
accumulated_ticks = 0;
downcounts[current_context] = time_slice[current_context];
}
void CoreTiming::ResetRun() {
downcounts.fill(MAX_SLICE_LENGTH);
time_slice.fill(MAX_SLICE_LENGTH);
current_context = 0;
// Still events left (scheduled in the future)
if (!event_queue.empty()) {
const s64 needed_ticks =
std::min<s64>(event_queue.front().time - global_timer, MAX_SLICE_LENGTH);
downcounts[current_context] = needed_ticks;
}
is_global_timer_sane = false;
accumulated_ticks = 0;
}
void CoreTiming::Idle() {
idled_cycles += downcount;
downcount = 0;
accumulated_ticks += downcounts[current_context];
idled_cycles += downcounts[current_context];
downcounts[current_context] = 0;
}
std::chrono::microseconds CoreTiming::GetGlobalTimeUs() const {
return std::chrono::microseconds{GetTicks() * 1000000 / BASE_CLOCK_RATE};
}
int CoreTiming::GetDowncount() const {
return downcount;
s64 CoreTiming::GetDowncount() const {
return downcounts[current_context];
}
} // namespace Core::Timing

View File

@@ -7,6 +7,7 @@
#include <chrono>
#include <functional>
#include <mutex>
#include <optional>
#include <string>
#include <unordered_map>
#include <vector>
@@ -104,7 +105,19 @@ public:
std::chrono::microseconds GetGlobalTimeUs() const;
int GetDowncount() const;
void ResetRun();
s64 GetDowncount() const;
void SwitchContext(u64 new_context) {
current_context = new_context;
}
bool CanCurrentContextRun() const {
return time_slice[current_context] > 0;
}
std::optional<u64> NextAvailableCore(const s64 needed_ticks) const;
private:
struct Event;
@@ -112,10 +125,16 @@ private:
/// Clear all pending events. This should ONLY be done on exit.
void ClearPendingEvents();
static constexpr u64 num_cpu_cores = 4;
s64 global_timer = 0;
s64 idled_cycles = 0;
int slice_length = 0;
int downcount = 0;
s64 slice_length = 0;
u64 accumulated_ticks = 0;
std::array<s64, num_cpu_cores> downcounts{};
// Slice of time assigned to each core per run.
std::array<s64, num_cpu_cores> time_slice{};
u64 current_context = 0;
// Are we in a function that has been called from Advance()
// If events are scheduled from a function that gets called from Advance(),

View File

@@ -6,6 +6,7 @@
#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"
@@ -122,13 +123,19 @@ void CpuCoreManager::RunLoop(bool tight_loop) {
}
}
for (active_core = 0; active_core < NUM_CPU_CORES; ++active_core) {
cores[active_core]->RunLoop(tight_loop);
if (Settings::values.use_multi_core) {
// Cores 1-3 are run on other threads in this mode
break;
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);

View File

@@ -31,7 +31,7 @@ constexpr std::array partition_names{
XCI::XCI(VirtualFile file_)
: file(std::move(file_)), program_nca_status{Loader::ResultStatus::ErrorXCIMissingProgramNCA},
partitions(partition_names.size()) {
partitions(partition_names.size()), partitions_raw(partition_names.size()) {
if (file->ReadObject(&header) != sizeof(GamecardHeader)) {
status = Loader::ResultStatus::ErrorBadXCIHeader;
return;
@@ -42,8 +42,10 @@ XCI::XCI(VirtualFile file_)
return;
}
PartitionFilesystem main_hfs(
std::make_shared<OffsetVfsFile>(file, header.hfs_size, header.hfs_offset));
PartitionFilesystem main_hfs(std::make_shared<OffsetVfsFile>(
file, file->GetSize() - header.hfs_offset, header.hfs_offset));
update_normal_partition_end = main_hfs.GetFileOffsets()["secure"];
if (main_hfs.GetStatus() != Loader::ResultStatus::Success) {
status = main_hfs.GetStatus();
@@ -55,9 +57,7 @@ XCI::XCI(VirtualFile file_)
const auto partition_idx = static_cast<std::size_t>(partition);
auto raw = main_hfs.GetFile(partition_names[partition_idx]);
if (raw != nullptr) {
partitions[partition_idx] = std::make_shared<PartitionFilesystem>(std::move(raw));
}
partitions_raw[static_cast<std::size_t>(partition)] = std::move(raw);
}
secure_partition = std::make_shared<NSP>(
@@ -71,13 +71,7 @@ XCI::XCI(VirtualFile file_)
program_nca_status = Loader::ResultStatus::ErrorXCIMissingProgramNCA;
}
auto result = AddNCAFromPartition(XCIPartition::Update);
if (result != Loader::ResultStatus::Success) {
status = result;
return;
}
result = AddNCAFromPartition(XCIPartition::Normal);
auto result = AddNCAFromPartition(XCIPartition::Normal);
if (result != Loader::ResultStatus::Success) {
status = result;
return;
@@ -104,34 +98,114 @@ Loader::ResultStatus XCI::GetProgramNCAStatus() const {
return program_nca_status;
}
VirtualDir XCI::GetPartition(XCIPartition partition) const {
VirtualDir XCI::GetPartition(XCIPartition partition) {
const auto id = static_cast<std::size_t>(partition);
if (partitions[id] == nullptr && partitions_raw[id] != nullptr) {
partitions[id] = std::make_shared<PartitionFilesystem>(partitions_raw[id]);
}
return partitions[static_cast<std::size_t>(partition)];
}
std::vector<VirtualDir> XCI::GetPartitions() {
std::vector<VirtualDir> out;
for (const auto& id :
{XCIPartition::Update, XCIPartition::Normal, XCIPartition::Secure, XCIPartition::Logo}) {
const auto part = GetPartition(id);
if (part != nullptr) {
out.push_back(part);
}
}
return out;
}
std::shared_ptr<NSP> XCI::GetSecurePartitionNSP() const {
return secure_partition;
}
VirtualDir XCI::GetSecurePartition() const {
VirtualDir XCI::GetSecurePartition() {
return GetPartition(XCIPartition::Secure);
}
VirtualDir XCI::GetNormalPartition() const {
VirtualDir XCI::GetNormalPartition() {
return GetPartition(XCIPartition::Normal);
}
VirtualDir XCI::GetUpdatePartition() const {
VirtualDir XCI::GetUpdatePartition() {
return GetPartition(XCIPartition::Update);
}
VirtualDir XCI::GetLogoPartition() const {
VirtualDir XCI::GetLogoPartition() {
return GetPartition(XCIPartition::Logo);
}
VirtualFile XCI::GetPartitionRaw(XCIPartition partition) const {
return partitions_raw[static_cast<std::size_t>(partition)];
}
VirtualFile XCI::GetSecurePartitionRaw() const {
return GetPartitionRaw(XCIPartition::Secure);
}
VirtualFile XCI::GetStoragePartition0() const {
return std::make_shared<OffsetVfsFile>(file, update_normal_partition_end, 0, "partition0");
}
VirtualFile XCI::GetStoragePartition1() const {
return std::make_shared<OffsetVfsFile>(file, file->GetSize() - update_normal_partition_end,
update_normal_partition_end, "partition1");
}
VirtualFile XCI::GetNormalPartitionRaw() const {
return GetPartitionRaw(XCIPartition::Normal);
}
VirtualFile XCI::GetUpdatePartitionRaw() const {
return GetPartitionRaw(XCIPartition::Update);
}
VirtualFile XCI::GetLogoPartitionRaw() const {
return GetPartitionRaw(XCIPartition::Logo);
}
u64 XCI::GetProgramTitleID() const {
return secure_partition->GetProgramTitleID();
}
u32 XCI::GetSystemUpdateVersion() {
const auto update = GetPartition(XCIPartition::Update);
if (update == nullptr)
return 0;
for (const auto& file : update->GetFiles()) {
NCA nca{file, nullptr, 0, keys};
if (nca.GetStatus() != Loader::ResultStatus::Success)
continue;
if (nca.GetType() == NCAContentType::Meta && nca.GetTitleId() == 0x0100000000000816) {
const auto dir = nca.GetSubdirectories()[0];
const auto cnmt = dir->GetFile("SystemUpdate_0100000000000816.cnmt");
if (cnmt == nullptr)
continue;
CNMT cnmt_data{cnmt};
const auto metas = cnmt_data.GetMetaRecords();
if (metas.empty())
continue;
return metas[0].title_version;
}
}
return 0;
}
u64 XCI::GetSystemUpdateTitleID() const {
return 0x0100000000000816;
}
bool XCI::HasProgramNCA() const {
return program != nullptr;
}
@@ -201,7 +275,7 @@ std::array<u8, 0x200> XCI::GetCertificate() const {
Loader::ResultStatus XCI::AddNCAFromPartition(XCIPartition part) {
const auto partition_index = static_cast<std::size_t>(part);
const auto& partition = partitions[partition_index];
const auto partition = GetPartition(part);
if (partition == nullptr) {
return Loader::ResultStatus::ErrorXCIMissingPartition;
@@ -232,7 +306,7 @@ Loader::ResultStatus XCI::AddNCAFromPartition(XCIPartition part) {
return Loader::ResultStatus::Success;
}
u8 XCI::GetFormatVersion() const {
u8 XCI::GetFormatVersion() {
return GetLogoPartition() == nullptr ? 0x1 : 0x2;
}
} // namespace FileSys

View File

@@ -81,14 +81,24 @@ public:
Loader::ResultStatus GetStatus() const;
Loader::ResultStatus GetProgramNCAStatus() const;
u8 GetFormatVersion() const;
u8 GetFormatVersion();
VirtualDir GetPartition(XCIPartition partition);
std::vector<VirtualDir> GetPartitions();
VirtualDir GetPartition(XCIPartition partition) const;
std::shared_ptr<NSP> GetSecurePartitionNSP() const;
VirtualDir GetSecurePartition() const;
VirtualDir GetNormalPartition() const;
VirtualDir GetUpdatePartition() const;
VirtualDir GetLogoPartition() const;
VirtualDir GetSecurePartition();
VirtualDir GetNormalPartition();
VirtualDir GetUpdatePartition();
VirtualDir GetLogoPartition();
VirtualFile GetPartitionRaw(XCIPartition partition) const;
VirtualFile GetSecurePartitionRaw() const;
VirtualFile GetStoragePartition0() const;
VirtualFile GetStoragePartition1() const;
VirtualFile GetNormalPartitionRaw() const;
VirtualFile GetUpdatePartitionRaw() const;
VirtualFile GetLogoPartitionRaw() const;
u64 GetProgramTitleID() const;
u32 GetSystemUpdateVersion();
@@ -123,6 +133,7 @@ private:
Loader::ResultStatus program_nca_status;
std::vector<VirtualDir> partitions;
std::vector<VirtualFile> partitions_raw;
std::shared_ptr<NSP> secure_partition;
std::shared_ptr<NCA> program;
std::vector<std::shared_ptr<NCA>> ncas;

View File

@@ -65,6 +65,9 @@ PartitionFilesystem::PartitionFilesystem(std::shared_ptr<VfsFile> file) {
std::string name(
reinterpret_cast<const char*>(&file_data[strtab_offset + entry.strtab_offset]));
offsets.insert_or_assign(name, content_offset + entry.offset);
sizes.insert_or_assign(name, entry.size);
pfs_files.emplace_back(std::make_shared<OffsetVfsFile>(
file, entry.size, content_offset + entry.offset, std::move(name)));
}
@@ -78,6 +81,14 @@ Loader::ResultStatus PartitionFilesystem::GetStatus() const {
return status;
}
std::map<std::string, u64> PartitionFilesystem::GetFileOffsets() const {
return offsets;
}
std::map<std::string, u64> PartitionFilesystem::GetFileSizes() const {
return sizes;
}
std::vector<std::shared_ptr<VfsFile>> PartitionFilesystem::GetFiles() const {
return pfs_files;
}

View File

@@ -29,6 +29,9 @@ public:
Loader::ResultStatus GetStatus() const;
std::map<std::string, u64> GetFileOffsets() const;
std::map<std::string, u64> GetFileSizes() const;
std::vector<std::shared_ptr<VfsFile>> GetFiles() const override;
std::vector<std::shared_ptr<VfsDirectory>> GetSubdirectories() const override;
std::string GetName() const override;
@@ -80,6 +83,9 @@ private:
bool is_hfs = false;
std::size_t content_offset = 0;
std::map<std::string, u64> offsets;
std::map<std::string, u64> sizes;
std::vector<VirtualFile> pfs_files;
};

View File

@@ -35,11 +35,11 @@ void RomFSFactory::SetPackedUpdate(VirtualFile update_raw) {
this->update_raw = std::move(update_raw);
}
ResultVal<VirtualFile> RomFSFactory::OpenCurrentProcess() const {
ResultVal<VirtualFile> RomFSFactory::OpenCurrentProcess(u64 current_process_title_id) const {
if (!updatable)
return MakeResult<VirtualFile>(file);
const PatchManager patch_manager(Core::CurrentProcess()->GetTitleID());
const PatchManager patch_manager(current_process_title_id);
return MakeResult<VirtualFile>(
patch_manager.PatchRomFS(file, ivfc_offset, ContentRecordType::Program, update_raw));
}

View File

@@ -33,7 +33,7 @@ public:
~RomFSFactory();
void SetPackedUpdate(VirtualFile update_raw);
ResultVal<VirtualFile> OpenCurrentProcess() const;
ResultVal<VirtualFile> OpenCurrentProcess(u64 current_process_title_id) const;
ResultVal<VirtualFile> Open(u64 title_id, StorageId storage, ContentRecordType type) const;
private:

View File

@@ -127,8 +127,9 @@ std::string SaveDataFactory::GetFullPath(SaveDataSpaceId space, SaveDataType typ
u128 user_id, u64 save_id) {
// According to switchbrew, if a save is of type SaveData and the title id field is 0, it should
// be interpreted as the title id of the current process.
if (type == SaveDataType::SaveData && title_id == 0)
title_id = Core::CurrentProcess()->GetTitleID();
if (type == SaveDataType::SaveData && title_id == 0) {
title_id = Core::System::GetInstance().CurrentProcess()->GetTitleID();
}
std::string out = GetSaveDataSpaceIdPath(space);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,13 @@
// Copyright 2019 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <array>
namespace FileSys::SystemArchive::SharedFontData {
extern const std::array<unsigned char, 217276> FONT_CHINESE_SIMPLIFIED;
} // namespace FileSys::SystemArchive::SharedFontData

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,13 @@
// Copyright 2019 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <array>
namespace FileSys::SystemArchive::SharedFontData {
extern const std::array<unsigned char, 222236> FONT_CHINESE_TRADITIONAL;
} // namespace FileSys::SystemArchive::SharedFontData

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,13 @@
// Copyright 2019 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <array>
namespace FileSys::SystemArchive::SharedFontData {
extern const std::array<unsigned char, 293516> FONT_EXTENDED_CHINESE_SIMPLIFIED;
} // namespace FileSys::SystemArchive::SharedFontData

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,13 @@
// Copyright 2019 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <array>
namespace FileSys::SystemArchive::SharedFontData {
extern const std::array<unsigned char, 217276> FONT_KOREAN;
} // namespace FileSys::SystemArchive::SharedFontData

View File

@@ -0,0 +1,196 @@
// Copyright 2019 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "core/file_sys/system_archive/data/font_nintendo_extended.h"
namespace FileSys::SystemArchive::SharedFontData {
const std::array<unsigned char, 2932> FONT_NINTENDO_EXTENDED{{
0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x80, 0x00, 0x03, 0x00, 0x70, 0x44, 0x53, 0x49, 0x47,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0b, 0x6c, 0x00, 0x00, 0x00, 0x08, 0x4f, 0x53, 0x2f, 0x32,
0x33, 0x86, 0x1d, 0x9b, 0x00, 0x00, 0x01, 0x78, 0x00, 0x00, 0x00, 0x60, 0x63, 0x6d, 0x61, 0x70,
0xc2, 0x06, 0x20, 0xde, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x63, 0x76, 0x74, 0x20,
0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x04, 0x2c, 0x00, 0x00, 0x00, 0x06, 0x66, 0x70, 0x67, 0x6d,
0x06, 0x59, 0x9c, 0x37, 0x00, 0x00, 0x02, 0xa0, 0x00, 0x00, 0x01, 0x73, 0x67, 0x61, 0x73, 0x70,
0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x0b, 0x64, 0x00, 0x00, 0x00, 0x08, 0x67, 0x6c, 0x79, 0x66,
0x10, 0x31, 0x88, 0x00, 0x00, 0x00, 0x04, 0x34, 0x00, 0x00, 0x04, 0x64, 0x68, 0x65, 0x61, 0x64,
0x15, 0x9d, 0xef, 0x91, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x36, 0x68, 0x68, 0x65, 0x61,
0x09, 0x60, 0x03, 0x71, 0x00, 0x00, 0x01, 0x34, 0x00, 0x00, 0x00, 0x24, 0x68, 0x6d, 0x74, 0x78,
0x0d, 0x2e, 0x03, 0xa7, 0x00, 0x00, 0x01, 0xd8, 0x00, 0x00, 0x00, 0x26, 0x6c, 0x6f, 0x63, 0x61,
0x05, 0xc0, 0x04, 0x6c, 0x00, 0x00, 0x08, 0x98, 0x00, 0x00, 0x00, 0x1e, 0x6d, 0x61, 0x78, 0x70,
0x02, 0x1c, 0x00, 0x5f, 0x00, 0x00, 0x01, 0x58, 0x00, 0x00, 0x00, 0x20, 0x6e, 0x61, 0x6d, 0x65,
0x7c, 0xe0, 0x84, 0x5c, 0x00, 0x00, 0x08, 0xb8, 0x00, 0x00, 0x02, 0x09, 0x70, 0x6f, 0x73, 0x74,
0x47, 0x4e, 0x74, 0x19, 0x00, 0x00, 0x0a, 0xc4, 0x00, 0x00, 0x00, 0x9e, 0x70, 0x72, 0x65, 0x70,
0x1c, 0xfc, 0x7d, 0x9c, 0x00, 0x00, 0x04, 0x14, 0x00, 0x00, 0x00, 0x16, 0x00, 0x01, 0x00, 0x00,
0x00, 0x01, 0x00, 0x00, 0x7c, 0xc7, 0xb1, 0x63, 0x5f, 0x0f, 0x3c, 0xf5, 0x00, 0x1b, 0x03, 0xe8,
0x00, 0x00, 0x00, 0x00, 0xd9, 0x44, 0x2f, 0x5d, 0x00, 0x00, 0x00, 0x00, 0xd9, 0x45, 0x7b, 0x69,
0x00, 0x00, 0x00, 0x00, 0x03, 0xe6, 0x03, 0xe8, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x03, 0x84, 0xff, 0x83, 0x01, 0xf4, 0x03, 0xe8,
0x00, 0x00, 0x00, 0x00, 0x03, 0xe6, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x5e,
0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x74, 0x01, 0x90, 0x00, 0x05,
0x00, 0x04, 0x00, 0xcd, 0x00, 0xcd, 0x00, 0x00, 0x01, 0x1f, 0x00, 0xcd, 0x00, 0xcd, 0x00, 0x00,
0x03, 0xc3, 0x00, 0x66, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x00, 0xc0, 0x00, 0x00, 0xe0, 0xe9, 0x03, 0x84, 0xff, 0x83,
0x01, 0xf4, 0x02, 0xee, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe8,
0x02, 0xbc, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x03, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xfa, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x03, 0xe8, 0x00, 0xeb, 0x01, 0x21, 0x00, 0xff,
0x00, 0xff, 0x01, 0x3d, 0x01, 0x17, 0x00, 0x42, 0x00, 0x1c, 0x00, 0x3e, 0x00, 0x17, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x68, 0x00, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1c, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x68, 0x00, 0x06, 0x00, 0x4c,
0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x04, 0x00, 0x38, 0x00, 0x00, 0x00, 0x0a,
0x00, 0x08, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x20, 0xe0, 0xe9, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x20, 0xe0, 0xe0, 0xff, 0xff, 0x00, 0x01, 0xff, 0xf5,
0xff, 0xe3, 0x1f, 0x24, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xb8, 0x00, 0x00, 0x2c, 0x4b, 0xb8, 0x00, 0x09, 0x50, 0x58, 0xb1, 0x01, 0x01, 0x8e, 0x59, 0xb8,
0x01, 0xff, 0x85, 0xb8, 0x00, 0x44, 0x1d, 0xb9, 0x00, 0x09, 0x00, 0x03, 0x5f, 0x5e, 0x2d, 0xb8,
0x00, 0x01, 0x2c, 0x20, 0x20, 0x45, 0x69, 0x44, 0xb0, 0x01, 0x60, 0x2d, 0xb8, 0x00, 0x02, 0x2c,
0xb8, 0x00, 0x01, 0x2a, 0x21, 0x2d, 0xb8, 0x00, 0x03, 0x2c, 0x20, 0x46, 0xb0, 0x03, 0x25, 0x46,
0x52, 0x58, 0x23, 0x59, 0x20, 0x8a, 0x20, 0x8a, 0x49, 0x64, 0x8a, 0x20, 0x46, 0x20, 0x68, 0x61,
0x64, 0xb0, 0x04, 0x25, 0x46, 0x20, 0x68, 0x61, 0x64, 0x52, 0x58, 0x23, 0x65, 0x8a, 0x59, 0x2f,
0x20, 0xb0, 0x00, 0x53, 0x58, 0x69, 0x20, 0xb0, 0x00, 0x54, 0x58, 0x21, 0xb0, 0x40, 0x59, 0x1b,
0x69, 0x20, 0xb0, 0x00, 0x54, 0x58, 0x21, 0xb0, 0x40, 0x65, 0x59, 0x59, 0x3a, 0x2d, 0xb8, 0x00,
0x04, 0x2c, 0x20, 0x46, 0xb0, 0x04, 0x25, 0x46, 0x52, 0x58, 0x23, 0x8a, 0x59, 0x20, 0x46, 0x20,
0x6a, 0x61, 0x64, 0xb0, 0x04, 0x25, 0x46, 0x20, 0x6a, 0x61, 0x64, 0x52, 0x58, 0x23, 0x8a, 0x59,
0x2f, 0xfd, 0x2d, 0xb8, 0x00, 0x05, 0x2c, 0x4b, 0x20, 0xb0, 0x03, 0x26, 0x50, 0x58, 0x51, 0x58,
0xb0, 0x80, 0x44, 0x1b, 0xb0, 0x40, 0x44, 0x59, 0x1b, 0x21, 0x21, 0x20, 0x45, 0xb0, 0xc0, 0x50,
0x58, 0xb0, 0xc0, 0x44, 0x1b, 0x21, 0x59, 0x59, 0x2d, 0xb8, 0x00, 0x06, 0x2c, 0x20, 0x20, 0x45,
0x69, 0x44, 0xb0, 0x01, 0x60, 0x20, 0x20, 0x45, 0x7d, 0x69, 0x18, 0x44, 0xb0, 0x01, 0x60, 0x2d,
0xb8, 0x00, 0x07, 0x2c, 0xb8, 0x00, 0x06, 0x2a, 0x2d, 0xb8, 0x00, 0x08, 0x2c, 0x4b, 0x20, 0xb0,
0x03, 0x26, 0x53, 0x58, 0xb0, 0x40, 0x1b, 0xb0, 0x00, 0x59, 0x8a, 0x8a, 0x20, 0xb0, 0x03, 0x26,
0x53, 0x58, 0x23, 0x21, 0xb0, 0x80, 0x8a, 0x8a, 0x1b, 0x8a, 0x23, 0x59, 0x20, 0xb0, 0x03, 0x26,
0x53, 0x58, 0x23, 0x21, 0xb8, 0x00, 0xc0, 0x8a, 0x8a, 0x1b, 0x8a, 0x23, 0x59, 0x20, 0xb0, 0x03,
0x26, 0x53, 0x58, 0x23, 0x21, 0xb8, 0x01, 0x00, 0x8a, 0x8a, 0x1b, 0x8a, 0x23, 0x59, 0x20, 0xb0,
0x03, 0x26, 0x53, 0x58, 0x23, 0x21, 0xb8, 0x01, 0x40, 0x8a, 0x8a, 0x1b, 0x8a, 0x23, 0x59, 0x20,
0xb8, 0x00, 0x03, 0x26, 0x53, 0x58, 0xb0, 0x03, 0x25, 0x45, 0xb8, 0x01, 0x80, 0x50, 0x58, 0x23,
0x21, 0xb8, 0x01, 0x80, 0x23, 0x21, 0x1b, 0xb0, 0x03, 0x25, 0x45, 0x23, 0x21, 0x23, 0x21, 0x59,
0x1b, 0x21, 0x59, 0x44, 0x2d, 0xb8, 0x00, 0x09, 0x2c, 0x4b, 0x53, 0x58, 0x45, 0x44, 0x1b, 0x21,
0x21, 0x59, 0x2d, 0x00, 0xb8, 0x00, 0x00, 0x2b, 0x00, 0xba, 0x00, 0x01, 0x00, 0x01, 0x00, 0x07,
0x2b, 0xb8, 0x00, 0x00, 0x20, 0x45, 0x7d, 0x69, 0x18, 0x44, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x03, 0xe6, 0x03, 0xe8, 0x00, 0x06,
0x00, 0x00, 0x35, 0x01, 0x33, 0x15, 0x01, 0x23, 0x35, 0x03, 0x52, 0x94, 0xfc, 0xa6, 0x8c, 0x90,
0x03, 0x58, 0x86, 0xfc, 0xa0, 0x8e, 0x00, 0x00, 0x00, 0x02, 0x00, 0xeb, 0x00, 0xcc, 0x02, 0xfb,
0x03, 0x1e, 0x00, 0x08, 0x00, 0x0f, 0x00, 0x00, 0x01, 0x33, 0x13, 0x23, 0x27, 0x23, 0x07, 0x23,
0x13, 0x17, 0x07, 0x06, 0x15, 0x33, 0x27, 0x07, 0x01, 0xbc, 0x6d, 0xd2, 0x7c, 0x26, 0xcc, 0x26,
0x7c, 0xd1, 0x35, 0x40, 0x02, 0x89, 0x45, 0x02, 0x03, 0x1e, 0xfd, 0xae, 0x77, 0x77, 0x02, 0x52,
0x9b, 0xcc, 0x08, 0x04, 0xda, 0x02, 0x00, 0x00, 0x00, 0x03, 0x01, 0x21, 0x00, 0xcc, 0x02, 0xc5,
0x03, 0x1e, 0x00, 0x15, 0x00, 0x1f, 0x00, 0x2b, 0x00, 0x00, 0x25, 0x11, 0x33, 0x32, 0x1e, 0x02,
0x15, 0x14, 0x0e, 0x02, 0x07, 0x1e, 0x01, 0x15, 0x14, 0x0e, 0x02, 0x2b, 0x01, 0x13, 0x33, 0x32,
0x36, 0x35, 0x34, 0x26, 0x2b, 0x01, 0x1d, 0x01, 0x33, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x2b,
0x01, 0x15, 0x01, 0x21, 0xea, 0x25, 0x3f, 0x2e, 0x1a, 0x0e, 0x15, 0x1b, 0x0e, 0x2d, 0x2d, 0x1a,
0x2e, 0x3f, 0x25, 0xf8, 0x76, 0x62, 0x20, 0x2a, 0x28, 0x22, 0x62, 0x76, 0x10, 0x18, 0x11, 0x09,
0x22, 0x22, 0x74, 0xcc, 0x02, 0x52, 0x18, 0x2b, 0x3c, 0x24, 0x1d, 0x1f, 0x17, 0x17, 0x14, 0x0f,
0x48, 0x2f, 0x24, 0x3f, 0x2e, 0x1a, 0x01, 0x5b, 0x29, 0x20, 0x20, 0x2b, 0x94, 0xf8, 0x0e, 0x16,
0x1c, 0x0e, 0x1f, 0x31, 0x9e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xff, 0x00, 0xcc, 0x02, 0xe7,
0x03, 0x1e, 0x00, 0x0c, 0x00, 0x00, 0x01, 0x33, 0x17, 0x37, 0x33, 0x03, 0x13, 0x23, 0x27, 0x07,
0x23, 0x13, 0x03, 0x01, 0x04, 0x86, 0x69, 0x69, 0x86, 0xa3, 0xa8, 0x88, 0x6c, 0x6c, 0x88, 0xa8,
0xa3, 0x03, 0x1e, 0xcb, 0xcb, 0xfe, 0xda, 0xfe, 0xd4, 0xcf, 0xcf, 0x01, 0x2c, 0x01, 0x26, 0x00,
0x00, 0x01, 0x00, 0xff, 0x00, 0xcc, 0x02, 0xe7, 0x03, 0x1e, 0x00, 0x0f, 0x00, 0x00, 0x01, 0x03,
0x33, 0x17, 0x32, 0x15, 0x1e, 0x01, 0x15, 0x1b, 0x01, 0x33, 0x03, 0x15, 0x23, 0x35, 0x01, 0xb8,
0xb9, 0x7e, 0x01, 0x01, 0x01, 0x03, 0x70, 0x75, 0x7f, 0xb9, 0x76, 0x01, 0xa3, 0x01, 0x7b, 0x01,
0x01, 0x01, 0x05, 0x02, 0xff, 0x00, 0x01, 0x0a, 0xfe, 0x85, 0xd7, 0xd7, 0x00, 0x01, 0x01, 0x3d,
0x00, 0xcc, 0x02, 0xa9, 0x03, 0x1e, 0x00, 0x06, 0x00, 0x00, 0x25, 0x11, 0x33, 0x11, 0x33, 0x15,
0x21, 0x01, 0x3d, 0x75, 0xf7, 0xfe, 0x94, 0xcc, 0x02, 0x52, 0xfe, 0x10, 0x62, 0x00, 0x00, 0x00,
0x00, 0x02, 0x01, 0x17, 0x00, 0xbc, 0x02, 0xcf, 0x03, 0x0e, 0x00, 0x15, 0x00, 0x21, 0x00, 0x00,
0x25, 0x11, 0x33, 0x32, 0x1e, 0x02, 0x1d, 0x01, 0x0e, 0x03, 0x1d, 0x01, 0x17, 0x15, 0x23, 0x27,
0x23, 0x15, 0x23, 0x13, 0x33, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x2b, 0x01, 0x15, 0x01, 0x17,
0xf4, 0x27, 0x40, 0x2e, 0x19, 0x01, 0x1f, 0x24, 0x1e, 0x78, 0x7d, 0x6a, 0x5c, 0x75, 0x76, 0x72,
0x12, 0x19, 0x11, 0x08, 0x26, 0x26, 0x6a, 0xbc, 0x02, 0x52, 0x1d, 0x31, 0x42, 0x25, 0x16, 0x18,
0x32, 0x2a, 0x1b, 0x02, 0x01, 0xef, 0x06, 0xd7, 0xd7, 0x01, 0x3f, 0x10, 0x1a, 0x1e, 0x0f, 0x23,
0x36, 0xb0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x42, 0x00, 0xbc, 0x03, 0xa4, 0x03, 0x0e, 0x00, 0x0a,
0x00, 0x11, 0x00, 0x00, 0x13, 0x35, 0x21, 0x15, 0x01, 0x21, 0x15, 0x21, 0x35, 0x01, 0x21, 0x01,
0x11, 0x33, 0x11, 0x33, 0x15, 0x21, 0x42, 0x01, 0xa7, 0xfe, 0xeb, 0x01, 0x1b, 0xfe, 0x53, 0x01,
0x15, 0xfe, 0xeb, 0x01, 0xf7, 0x75, 0xf6, 0xfe, 0x95, 0x02, 0xac, 0x62, 0x45, 0xfe, 0x55, 0x62,
0x47, 0x01, 0xa9, 0xfe, 0x10, 0x02, 0x52, 0xfe, 0x10, 0x62, 0x00, 0x00, 0x00, 0x03, 0x00, 0x1c,
0x00, 0xbc, 0x03, 0xca, 0x03, 0x0e, 0x00, 0x0a, 0x00, 0x21, 0x00, 0x2f, 0x00, 0x00, 0x13, 0x35,
0x21, 0x15, 0x01, 0x21, 0x15, 0x21, 0x35, 0x01, 0x21, 0x01, 0x11, 0x33, 0x32, 0x1e, 0x02, 0x15,
0x14, 0x06, 0x07, 0x0e, 0x03, 0x15, 0x17, 0x15, 0x23, 0x27, 0x23, 0x15, 0x23, 0x13, 0x33, 0x32,
0x3e, 0x02, 0x35, 0x34, 0x2e, 0x02, 0x2b, 0x01, 0x15, 0x1c, 0x01, 0xa7, 0xfe, 0xeb, 0x01, 0x1b,
0xfe, 0x53, 0x01, 0x15, 0xfe, 0xeb, 0x01, 0xf7, 0xf3, 0x27, 0x41, 0x2d, 0x19, 0x1c, 0x20, 0x01,
0x0d, 0x0e, 0x0a, 0x78, 0x7d, 0x69, 0x5c, 0x75, 0x76, 0x71, 0x11, 0x1a, 0x12, 0x09, 0x0a, 0x14,
0x1d, 0x13, 0x69, 0x02, 0xac, 0x62, 0x45, 0xfe, 0x55, 0x62, 0x47, 0x01, 0xa9, 0xfe, 0x10, 0x02,
0x52, 0x1d, 0x31, 0x42, 0x25, 0x2b, 0x44, 0x1d, 0x01, 0x08, 0x09, 0x07, 0x01, 0xf1, 0x06, 0xd7,
0xd7, 0x01, 0x3f, 0x11, 0x19, 0x1f, 0x0e, 0x11, 0x20, 0x19, 0x0f, 0xb0, 0x00, 0x02, 0x00, 0x3e,
0x00, 0xb3, 0x03, 0xa8, 0x03, 0x17, 0x00, 0x3a, 0x00, 0x41, 0x00, 0x00, 0x13, 0x34, 0x3e, 0x02,
0x33, 0x32, 0x1e, 0x02, 0x15, 0x23, 0x27, 0x34, 0x27, 0x2e, 0x01, 0x23, 0x22, 0x0e, 0x02, 0x15,
0x14, 0x16, 0x15, 0x1e, 0x05, 0x15, 0x14, 0x0e, 0x02, 0x23, 0x22, 0x2e, 0x02, 0x35, 0x33, 0x1e,
0x01, 0x33, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x2e, 0x04, 0x35, 0x01, 0x11, 0x33, 0x11, 0x33, 0x15,
0x21, 0x50, 0x24, 0x3b, 0x4a, 0x27, 0x28, 0x4b, 0x39, 0x22, 0x73, 0x01, 0x01, 0x08, 0x2b, 0x29,
0x10, 0x20, 0x19, 0x0f, 0x01, 0x0b, 0x35, 0x41, 0x46, 0x3b, 0x25, 0x23, 0x3a, 0x4b, 0x27, 0x2b,
0x50, 0x3f, 0x26, 0x74, 0x05, 0x34, 0x33, 0x10, 0x20, 0x1a, 0x11, 0x2c, 0x42, 0x4d, 0x42, 0x2c,
0x01, 0xef, 0x73, 0xf6, 0xfe, 0x97, 0x02, 0x70, 0x2a, 0x3f, 0x2a, 0x14, 0x18, 0x2e, 0x44, 0x2c,
0x02, 0x03, 0x01, 0x27, 0x27, 0x07, 0x10, 0x1a, 0x12, 0x02, 0x0b, 0x02, 0x1f, 0x22, 0x19, 0x17,
0x27, 0x3f, 0x34, 0x2c, 0x3e, 0x28, 0x13, 0x1a, 0x32, 0x48, 0x2e, 0x30, 0x30, 0x06, 0x0f, 0x1a,
0x13, 0x21, 0x27, 0x1e, 0x1b, 0x29, 0x3e, 0x31, 0xfe, 0x4c, 0x02, 0x53, 0xfe, 0x10, 0x63, 0x00,
0x00, 0x03, 0x00, 0x17, 0x00, 0xb3, 0x03, 0xce, 0x03, 0x17, 0x00, 0x38, 0x00, 0x4f, 0x00, 0x5d,
0x00, 0x00, 0x13, 0x34, 0x3e, 0x02, 0x33, 0x32, 0x1e, 0x02, 0x15, 0x23, 0x27, 0x34, 0x23, 0x2e,
0x01, 0x23, 0x22, 0x0e, 0x02, 0x15, 0x14, 0x1e, 0x04, 0x15, 0x14, 0x0e, 0x02, 0x23, 0x22, 0x2e,
0x02, 0x35, 0x33, 0x1e, 0x01, 0x33, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x26, 0x27, 0x2e, 0x03, 0x35,
0x01, 0x11, 0x33, 0x32, 0x1e, 0x02, 0x15, 0x14, 0x06, 0x07, 0x30, 0x0e, 0x02, 0x31, 0x17, 0x15,
0x23, 0x27, 0x23, 0x15, 0x23, 0x13, 0x33, 0x32, 0x3e, 0x02, 0x35, 0x34, 0x2e, 0x02, 0x2b, 0x01,
0x15, 0x2a, 0x24, 0x3a, 0x4a, 0x26, 0x29, 0x4b, 0x39, 0x23, 0x73, 0x01, 0x01, 0x08, 0x2a, 0x2a,
0x10, 0x1f, 0x1a, 0x10, 0x2c, 0x42, 0x4d, 0x42, 0x2c, 0x23, 0x39, 0x4b, 0x27, 0x2b, 0x51, 0x3f,
0x27, 0x75, 0x05, 0x34, 0x33, 0x10, 0x20, 0x1a, 0x10, 0x1f, 0x1c, 0x25, 0x53, 0x47, 0x2e, 0x01,
0xed, 0xf3, 0x27, 0x41, 0x2d, 0x19, 0x1c, 0x20, 0x0c, 0x0e, 0x0c, 0x78, 0x7d, 0x68, 0x5d, 0x75,
0x76, 0x71, 0x11, 0x1a, 0x12, 0x09, 0x0a, 0x14, 0x1d, 0x13, 0x69, 0x02, 0x71, 0x2a, 0x3e, 0x2a,
0x14, 0x18, 0x2e, 0x44, 0x2c, 0x02, 0x02, 0x27, 0x29, 0x07, 0x11, 0x1a, 0x12, 0x1d, 0x24, 0x1c,
0x1d, 0x2b, 0x40, 0x32, 0x2c, 0x3f, 0x29, 0x13, 0x1a, 0x31, 0x49, 0x2e, 0x30, 0x30, 0x06, 0x0f,
0x19, 0x13, 0x1e, 0x22, 0x0b, 0x0e, 0x20, 0x2f, 0x43, 0x30, 0xfe, 0x4b, 0x02, 0x52, 0x1d, 0x32,
0x42, 0x25, 0x2c, 0x42, 0x1d, 0x08, 0x0a, 0x08, 0xf1, 0x06, 0xd7, 0xd7, 0x01, 0x3f, 0x11, 0x19,
0x1f, 0x0e, 0x11, 0x20, 0x19, 0x0f, 0xb0, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x12, 0x00, 0x12,
0x00, 0x12, 0x00, 0x32, 0x00, 0x72, 0x00, 0x8e, 0x00, 0xac, 0x00, 0xbe, 0x00, 0xf0, 0x01, 0x14,
0x01, 0x5c, 0x01, 0xb6, 0x02, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0xa2, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x02, 0x00, 0x07, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x2f,
0x00, 0x17, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x46, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x0d, 0x00, 0x58, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x06, 0x00, 0x12, 0x00, 0x65, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x01, 0x00, 0x20,
0x00, 0x77, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x02, 0x00, 0x0e, 0x00, 0x97, 0x00, 0x03,
0x00, 0x01, 0x04, 0x09, 0x00, 0x03, 0x00, 0x5e, 0x00, 0xa5, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09,
0x00, 0x04, 0x00, 0x24, 0x01, 0x03, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x05, 0x00, 0x1a,
0x01, 0x27, 0x00, 0x03, 0x00, 0x01, 0x04, 0x09, 0x00, 0x06, 0x00, 0x24, 0x01, 0x41, 0x00, 0x03,
0x00, 0x01, 0x04, 0x09, 0x00, 0x11, 0x00, 0x02, 0x01, 0x65, 0x59, 0x75, 0x7a, 0x75, 0x4f, 0x53,
0x53, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x67, 0x75, 0x6c, 0x61,
0x72, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x31, 0x2e, 0x30, 0x30, 0x30, 0x3b, 0x3b,
0x59, 0x75, 0x7a, 0x75, 0x4f, 0x53, 0x53, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e,
0x2d, 0x52, 0x3b, 0x32, 0x30, 0x31, 0x39, 0x3b, 0x46, 0x4c, 0x56, 0x49, 0x2d, 0x36, 0x31, 0x34,
0x59, 0x75, 0x7a, 0x75, 0x4f, 0x53, 0x53, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e,
0x20, 0x52, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x31, 0x2e, 0x30, 0x30, 0x30, 0x59,
0x75, 0x7a, 0x75, 0x4f, 0x53, 0x53, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x2d,
0x52, 0x00, 0x59, 0x00, 0x75, 0x00, 0x7a, 0x00, 0x75, 0x00, 0x4f, 0x00, 0x53, 0x00, 0x53, 0x00,
0x45, 0x00, 0x78, 0x00, 0x74, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00,
0x6e, 0x00, 0x52, 0x00, 0x65, 0x00, 0x67, 0x00, 0x75, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x72, 0x00,
0x56, 0x00, 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00,
0x31, 0x00, 0x2e, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x3b, 0x00, 0x3b, 0x00, 0x59, 0x00,
0x75, 0x00, 0x7a, 0x00, 0x75, 0x00, 0x4f, 0x00, 0x53, 0x00, 0x53, 0x00, 0x45, 0x00, 0x78, 0x00,
0x74, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x2d, 0x00,
0x52, 0x00, 0x3b, 0x00, 0x32, 0x00, 0x30, 0x00, 0x31, 0x00, 0x39, 0x00, 0x3b, 0x00, 0x46, 0x00,
0x4c, 0x00, 0x56, 0x00, 0x49, 0x00, 0x2d, 0x00, 0x36, 0x00, 0x31, 0x00, 0x34, 0x00, 0x59, 0x00,
0x75, 0x00, 0x7a, 0x00, 0x75, 0x00, 0x4f, 0x00, 0x53, 0x00, 0x53, 0x00, 0x45, 0x00, 0x78, 0x00,
0x74, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00,
0x52, 0x00, 0x56, 0x00, 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00,
0x20, 0x00, 0x31, 0x00, 0x2e, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x59, 0x00, 0x75, 0x00,
0x7a, 0x00, 0x75, 0x00, 0x4f, 0x00, 0x53, 0x00, 0x53, 0x00, 0x45, 0x00, 0x78, 0x00, 0x74, 0x00,
0x65, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x2d, 0x00, 0x52, 0x00,
0x52, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x9c, 0x00, 0x32,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x01, 0x02, 0x01, 0x03, 0x00, 0x03, 0x01, 0x04,
0x01, 0x05, 0x01, 0x06, 0x01, 0x07, 0x01, 0x08, 0x01, 0x09, 0x01, 0x0a, 0x01, 0x0b, 0x01, 0x0c,
0x01, 0x0d, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x30, 0x30, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x30, 0x30,
0x30, 0x44, 0x07, 0x75, 0x6e, 0x69, 0x45, 0x30, 0x45, 0x30, 0x07, 0x75, 0x6e, 0x69, 0x45, 0x30,
0x45, 0x31, 0x07, 0x75, 0x6e, 0x69, 0x45, 0x30, 0x45, 0x32, 0x07, 0x75, 0x6e, 0x69, 0x45, 0x30,
0x45, 0x33, 0x07, 0x75, 0x6e, 0x69, 0x45, 0x30, 0x45, 0x34, 0x07, 0x75, 0x6e, 0x69, 0x45, 0x30,
0x45, 0x35, 0x07, 0x75, 0x6e, 0x69, 0x45, 0x30, 0x45, 0x36, 0x07, 0x75, 0x6e, 0x69, 0x45, 0x30,
0x45, 0x37, 0x07, 0x75, 0x6e, 0x69, 0x45, 0x30, 0x45, 0x38, 0x07, 0x75, 0x6e, 0x69, 0x45, 0x30,
0x45, 0x39, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0xff, 0xff, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00,
}};
} // namespace FileSys::SystemArchive::SharedFontData

View File

@@ -0,0 +1,13 @@
// Copyright 2019 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <array>
namespace FileSys::SystemArchive::SharedFontData {
extern const std::array<unsigned char, 2932> FONT_NINTENDO_EXTENDED;
} // namespace FileSys::SystemArchive::SharedFontData

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,13 @@
// Copyright 2019 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <array>
namespace FileSys::SystemArchive::SharedFontData {
extern const std::array<unsigned char, 217276> FONT_STANDARD;
} // namespace FileSys::SystemArchive::SharedFontData

View File

@@ -0,0 +1,78 @@
// Copyright 2019 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "core/file_sys/system_archive/data/font_chinese_simplified.h"
#include "core/file_sys/system_archive/data/font_chinese_traditional.h"
#include "core/file_sys/system_archive/data/font_extended_chinese_simplified.h"
#include "core/file_sys/system_archive/data/font_korean.h"
#include "core/file_sys/system_archive/data/font_nintendo_extended.h"
#include "core/file_sys/system_archive/data/font_standard.h"
#include "core/file_sys/system_archive/shared_font.h"
#include "core/file_sys/vfs_vector.h"
#include "core/hle/service/ns/pl_u.h"
namespace FileSys::SystemArchive {
namespace {
template <std::size_t Size>
VirtualFile PackBFTTF(const std::array<u8, Size>& data, const std::string& name) {
std::vector<u32> vec(Size / sizeof(u32));
std::memcpy(vec.data(), data.data(), vec.size() * sizeof(u32));
std::vector<u8> bfttf(Size + sizeof(u64));
u64 offset = 0;
Service::NS::EncryptSharedFont(vec, bfttf, offset);
return std::make_shared<VectorVfsFile>(std::move(bfttf), name);
}
} // Anonymous namespace
VirtualDir FontNintendoExtension() {
return std::make_shared<VectorVfsDirectory>(
std::vector<VirtualFile>{
PackBFTTF(SharedFontData::FONT_NINTENDO_EXTENDED, "nintendo_ext_003.bfttf"),
PackBFTTF(SharedFontData::FONT_NINTENDO_EXTENDED, "nintendo_ext2_003.bfttf"),
},
std::vector<VirtualDir>{});
}
VirtualDir FontStandard() {
return std::make_shared<VectorVfsDirectory>(
std::vector<VirtualFile>{
PackBFTTF(SharedFontData::FONT_STANDARD, "nintendo_udsg-r_std_003.bfttf"),
},
std::vector<VirtualDir>{});
}
VirtualDir FontKorean() {
return std::make_shared<VectorVfsDirectory>(
std::vector<VirtualFile>{
PackBFTTF(SharedFontData::FONT_KOREAN, "nintendo_udsg-r_ko_003.bfttf"),
},
std::vector<VirtualDir>{});
}
VirtualDir FontChineseTraditional() {
return std::make_shared<VectorVfsDirectory>(
std::vector<VirtualFile>{
PackBFTTF(SharedFontData::FONT_CHINESE_TRADITIONAL,
"nintendo_udjxh-db_zh-tw_003.bfttf"),
},
std::vector<VirtualDir>{});
}
VirtualDir FontChineseSimple() {
return std::make_shared<VectorVfsDirectory>(
std::vector<VirtualFile>{
PackBFTTF(SharedFontData::FONT_CHINESE_SIMPLIFIED,
"nintendo_udsg-r_org_zh-cn_003.bfttf"),
PackBFTTF(SharedFontData::FONT_EXTENDED_CHINESE_SIMPLIFIED,
"nintendo_udsg-r_ext_zh-cn_003.bfttf"),
},
std::vector<VirtualDir>{});
}
} // namespace FileSys::SystemArchive

View 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/file_sys/vfs_types.h"
namespace FileSys::SystemArchive {
VirtualDir FontNintendoExtension();
VirtualDir FontStandard();
VirtualDir FontKorean();
VirtualDir FontChineseTraditional();
VirtualDir FontChineseSimple();
} // namespace FileSys::SystemArchive

View File

@@ -6,6 +6,7 @@
#include "core/file_sys/romfs.h"
#include "core/file_sys/system_archive/mii_model.h"
#include "core/file_sys/system_archive/ng_word.h"
#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"
@@ -39,11 +40,11 @@ constexpr std::array<SystemArchiveDescriptor, SYSTEM_ARCHIVE_COUNT> SYSTEM_ARCHI
{0x010000000000080D, "UrlBlackList", nullptr},
{0x010000000000080E, "TimeZoneBinary", nullptr},
{0x010000000000080F, "CertStoreCruiser", nullptr},
{0x0100000000000810, "FontNintendoExtension", nullptr},
{0x0100000000000811, "FontStandard", nullptr},
{0x0100000000000812, "FontKorean", nullptr},
{0x0100000000000813, "FontChineseTraditional", nullptr},
{0x0100000000000814, "FontChineseSimple", nullptr},
{0x0100000000000810, "FontNintendoExtension", &FontNintendoExtension},
{0x0100000000000811, "FontStandard", &FontStandard},
{0x0100000000000812, "FontKorean", &FontKorean},
{0x0100000000000813, "FontChineseTraditional", &FontChineseTraditional},
{0x0100000000000814, "FontChineseSimple", &FontChineseSimple},
{0x0100000000000815, "FontBfcpx", nullptr},
{0x0100000000000816, "SystemUpdate", nullptr},
{0x0100000000000817, "0100000000000817", nullptr},

View File

@@ -641,7 +641,8 @@ static void HandleQuery() {
strlen("Xfer:features:read:target.xml:")) == 0) {
SendReply(target_xml);
} else if (strncmp(query, "Offsets", strlen("Offsets")) == 0) {
const VAddr base_address = Core::CurrentProcess()->VMManager().GetCodeRegionBaseAddress();
const VAddr base_address =
Core::System::GetInstance().CurrentProcess()->VMManager().GetCodeRegionBaseAddress();
std::string buffer = fmt::format("TextSeg={:0x}", base_address);
SendReply(buffer.c_str());
} else if (strncmp(query, "fThreadInfo", strlen("fThreadInfo")) == 0) {

View File

@@ -103,7 +103,7 @@ SharedPtr<Object> HandleTable::GetGeneric(Handle handle) const {
if (handle == CurrentThread) {
return GetCurrentThread();
} else if (handle == CurrentProcess) {
return Core::CurrentProcess();
return Core::System::GetInstance().CurrentProcess();
}
if (!IsValid(handle)) {

View File

@@ -1142,12 +1142,12 @@ void IApplicationFunctions::PopLaunchParameter(Kernel::HLERequestContext& ctx) {
if (kind == LaunchParameterKind::ApplicationSpecific && !launch_popped_application_specific) {
const auto backend = BCAT::CreateBackendFromSettings(
[this](u64 tid) { return system.GetFileSystemController().GetBCATDirectory(tid); });
const auto build_id_full = Core::System::GetInstance().GetCurrentProcessBuildID();
const auto build_id_full = system.GetCurrentProcessBuildID();
u64 build_id{};
std::memcpy(&build_id, build_id_full.data(), sizeof(u64));
const auto data =
backend->GetLaunchParameter({Core::CurrentProcess()->GetTitleID(), build_id});
backend->GetLaunchParameter({system.CurrentProcess()->GetTitleID(), build_id});
if (data.has_value()) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
@@ -1200,7 +1200,7 @@ void IApplicationFunctions::EnsureSaveData(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called, uid={:016X}{:016X}", user_id[1], user_id[0]);
FileSys::SaveDataDescriptor descriptor{};
descriptor.title_id = Core::CurrentProcess()->GetTitleID();
descriptor.title_id = system.CurrentProcess()->GetTitleID();
descriptor.user_id = user_id;
descriptor.type = FileSys::SaveDataType::SaveData;
const auto res = system.GetFileSystemController().CreateSaveData(

View File

@@ -10,13 +10,14 @@
namespace Service::BCAT {
ProgressServiceBackend::ProgressServiceBackend(std::string event_name) : impl{} {
ProgressServiceBackend::ProgressServiceBackend(std::string_view event_name) {
auto& kernel{Core::System::GetInstance().Kernel()};
event = Kernel::WritableEvent::CreateEventPair(
kernel, Kernel::ResetType::Automatic, "ProgressServiceBackend:UpdateEvent:" + event_name);
kernel, Kernel::ResetType::Automatic,
std::string("ProgressServiceBackend:UpdateEvent:").append(event_name));
}
Kernel::SharedPtr<Kernel::ReadableEvent> ProgressServiceBackend::GetEvent() {
Kernel::SharedPtr<Kernel::ReadableEvent> ProgressServiceBackend::GetEvent() const {
return event.readable;
}
@@ -95,7 +96,7 @@ Backend::Backend(DirectoryGetter getter) : dir_getter(std::move(getter)) {}
Backend::~Backend() = default;
NullBackend::NullBackend(const DirectoryGetter& getter) : Backend(std::move(getter)) {}
NullBackend::NullBackend(DirectoryGetter getter) : Backend(std::move(getter)) {}
NullBackend::~NullBackend() = default;

View File

@@ -6,6 +6,9 @@
#include <functional>
#include <optional>
#include <string>
#include <string_view>
#include "common/common_types.h"
#include "core/file_sys/vfs_types.h"
#include "core/hle/kernel/readable_event.h"
@@ -85,14 +88,14 @@ public:
void FinishDownload(ResultCode result);
private:
explicit ProgressServiceBackend(std::string event_name);
explicit ProgressServiceBackend(std::string_view event_name);
Kernel::SharedPtr<Kernel::ReadableEvent> GetEvent();
Kernel::SharedPtr<Kernel::ReadableEvent> GetEvent() const;
DeliveryCacheProgressImpl& GetImpl();
void SignalUpdate() const;
DeliveryCacheProgressImpl impl;
DeliveryCacheProgressImpl impl{};
Kernel::EventPair event;
bool need_hle_lock = false;
};
@@ -128,7 +131,7 @@ protected:
// A backend of BCAT that provides no operation.
class NullBackend : public Backend {
public:
explicit NullBackend(const DirectoryGetter& getter);
explicit NullBackend(DirectoryGetter getter);
~NullBackend() override;
bool Synchronize(TitleIDVersion title, ProgressServiceBackend& progress) override;

View File

@@ -495,7 +495,8 @@ Boxcat::StatusResult Boxcat::GetStatus(std::optional<std::string>& global,
}
return StatusResult::Success;
} catch (const nlohmann::json::parse_error& e) {
} catch (const nlohmann::json::parse_error& error) {
LOG_ERROR(Service_BCAT, "{}", error.what());
return StatusResult::ParseError;
}
}

View File

@@ -6,8 +6,9 @@
namespace Service::BCAT {
BCAT::BCAT(std::shared_ptr<Module> module, FileSystem::FileSystemController& fsc, const char* name)
: Module::Interface(std::move(module), fsc, name) {
BCAT::BCAT(Core::System& system, std::shared_ptr<Module> module,
FileSystem::FileSystemController& fsc, const char* name)
: Interface(system, std::move(module), fsc, name) {
// clang-format off
static const FunctionInfo functions[] = {
{0, &BCAT::CreateBcatService, "CreateBcatService"},

View File

@@ -6,12 +6,16 @@
#include "core/hle/service/bcat/module.h"
namespace Core {
class System;
}
namespace Service::BCAT {
class BCAT final : public Module::Interface {
public:
explicit BCAT(std::shared_ptr<Module> module, FileSystem::FileSystemController& fsc,
const char* name);
explicit BCAT(Core::System& system, std::shared_ptr<Module> module,
FileSystem::FileSystemController& fsc, const char* name);
~BCAT() override;
};

View File

@@ -35,8 +35,7 @@ using BCATDigest = std::array<u8, 0x10>;
namespace {
u64 GetCurrentBuildID() {
const auto& id = Core::System::GetInstance().GetCurrentProcessBuildID();
u64 GetCurrentBuildID(const Core::System::CurrentBuildProcessID& id) {
u64 out{};
std::memcpy(&out, id.data(), sizeof(u64));
return out;
@@ -125,7 +124,8 @@ private:
class IBcatService final : public ServiceFramework<IBcatService> {
public:
IBcatService(Backend& backend) : ServiceFramework("IBcatService"), backend(backend) {
explicit IBcatService(Core::System& system_, Backend& backend_)
: ServiceFramework("IBcatService"), system{system_}, backend{backend_} {
// clang-format off
static const FunctionInfo functions[] = {
{10100, &IBcatService::RequestSyncDeliveryCache, "RequestSyncDeliveryCache"},
@@ -163,7 +163,8 @@ private:
void RequestSyncDeliveryCache(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_BCAT, "called");
backend.Synchronize({Core::CurrentProcess()->GetTitleID(), GetCurrentBuildID()},
backend.Synchronize({system.CurrentProcess()->GetTitleID(),
GetCurrentBuildID(system.GetCurrentProcessBuildID())},
progress.at(static_cast<std::size_t>(SyncType::Normal)));
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
@@ -179,7 +180,8 @@ private:
LOG_DEBUG(Service_BCAT, "called, name={}", name);
backend.SynchronizeDirectory({Core::CurrentProcess()->GetTitleID(), GetCurrentBuildID()},
backend.SynchronizeDirectory({system.CurrentProcess()->GetTitleID(),
GetCurrentBuildID(system.GetCurrentProcessBuildID())},
name,
progress.at(static_cast<std::size_t>(SyncType::Directory)));
@@ -244,6 +246,7 @@ private:
rb.Push(RESULT_SUCCESS);
}
Core::System& system;
Backend& backend;
std::array<ProgressServiceBackend, static_cast<std::size_t>(SyncType::Count)> progress{
@@ -257,7 +260,7 @@ void Module::Interface::CreateBcatService(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IBcatService>(*backend);
rb.PushIpcInterface<IBcatService>(system, *backend);
}
class IDeliveryCacheFileService final : public ServiceFramework<IDeliveryCacheFileService> {
@@ -451,7 +454,7 @@ private:
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(write_size * sizeof(DeliveryCacheDirectoryEntry));
rb.Push(static_cast<u32>(write_size * sizeof(DeliveryCacheDirectoryEntry)));
}
void GetCount(Kernel::HLERequestContext& ctx) {
@@ -468,7 +471,7 @@ private:
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(files.size());
rb.Push(static_cast<u32>(files.size()));
}
FileSys::VirtualDir root;
@@ -525,7 +528,7 @@ private:
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(size);
rb.Push(static_cast<u32>(size));
}
FileSys::VirtualDir root;
@@ -539,7 +542,7 @@ void Module::Interface::CreateDeliveryCacheStorageService(Kernel::HLERequestCont
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IDeliveryCacheStorageService>(
fsc.GetBCATDirectory(Core::CurrentProcess()->GetTitleID()));
fsc.GetBCATDirectory(system.CurrentProcess()->GetTitleID()));
}
void Module::Interface::CreateDeliveryCacheStorageServiceWithApplicationId(
@@ -565,22 +568,23 @@ std::unique_ptr<Backend> CreateBackendFromSettings(DirectoryGetter getter) {
return std::make_unique<NullBackend>(std::move(getter));
}
Module::Interface::Interface(std::shared_ptr<Module> module, FileSystem::FileSystemController& fsc,
const char* name)
: ServiceFramework(name), fsc(fsc), module(std::move(module)),
backend(CreateBackendFromSettings([&fsc](u64 tid) { return fsc.GetBCATDirectory(tid); })) {}
Module::Interface::Interface(Core::System& system_, std::shared_ptr<Module> module_,
FileSystem::FileSystemController& fsc_, const char* name)
: ServiceFramework(name), fsc{fsc_}, module{std::move(module_)},
backend{CreateBackendFromSettings([&fsc_](u64 tid) { return fsc_.GetBCATDirectory(tid); })},
system{system_} {}
Module::Interface::~Interface() = default;
void InstallInterfaces(Core::System& system) {
auto module = std::make_shared<Module>();
std::make_shared<BCAT>(module, system.GetFileSystemController(), "bcat:a")
std::make_shared<BCAT>(system, module, system.GetFileSystemController(), "bcat:a")
->InstallAsService(system.ServiceManager());
std::make_shared<BCAT>(module, system.GetFileSystemController(), "bcat:m")
std::make_shared<BCAT>(system, module, system.GetFileSystemController(), "bcat:m")
->InstallAsService(system.ServiceManager());
std::make_shared<BCAT>(module, system.GetFileSystemController(), "bcat:u")
std::make_shared<BCAT>(system, module, system.GetFileSystemController(), "bcat:u")
->InstallAsService(system.ServiceManager());
std::make_shared<BCAT>(module, system.GetFileSystemController(), "bcat:s")
std::make_shared<BCAT>(system, module, system.GetFileSystemController(), "bcat:s")
->InstallAsService(system.ServiceManager());
}

View File

@@ -6,6 +6,10 @@
#include "core/hle/service/service.h"
namespace Core {
class System;
}
namespace Service {
namespace FileSystem {
@@ -20,8 +24,8 @@ class Module final {
public:
class Interface : public ServiceFramework<Interface> {
public:
explicit Interface(std::shared_ptr<Module> module, FileSystem::FileSystemController& fsc,
const char* name);
explicit Interface(Core::System& system_, std::shared_ptr<Module> module_,
FileSystem::FileSystemController& fsc_, const char* name);
~Interface() override;
void CreateBcatService(Kernel::HLERequestContext& ctx);
@@ -33,6 +37,9 @@ public:
std::shared_ptr<Module> module;
std::unique_ptr<Backend> backend;
private:
Core::System& system;
};
};

View File

@@ -128,7 +128,7 @@ private:
void CountCommonTicket(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_ETicket, "called");
const auto count = keys.GetCommonTickets().size();
const u32 count = static_cast<u32>(keys.GetCommonTickets().size());
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
@@ -138,7 +138,7 @@ private:
void CountPersonalizedTicket(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_ETicket, "called");
const auto count = keys.GetPersonalizedTickets().size();
const u32 count = static_cast<u32>(keys.GetPersonalizedTickets().size());
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
@@ -150,7 +150,7 @@ private:
if (keys.GetCommonTickets().empty())
out_entries = 0;
else
out_entries = ctx.GetWriteBufferSize() / sizeof(u128);
out_entries = static_cast<u32>(ctx.GetWriteBufferSize() / sizeof(u128));
LOG_DEBUG(Service_ETicket, "called, entries={:016X}", out_entries);
@@ -160,7 +160,7 @@ private:
std::transform(tickets.begin(), tickets.end(), std::back_inserter(ids),
[](const auto& pair) { return pair.first; });
out_entries = std::min<u32>(ids.size(), out_entries);
out_entries = static_cast<u32>(std::min<std::size_t>(ids.size(), out_entries));
ctx.WriteBuffer(ids.data(), out_entries * sizeof(u128));
IPC::ResponseBuilder rb{ctx, 3};
@@ -173,7 +173,7 @@ private:
if (keys.GetPersonalizedTickets().empty())
out_entries = 0;
else
out_entries = ctx.GetWriteBufferSize() / sizeof(u128);
out_entries = static_cast<u32>(ctx.GetWriteBufferSize() / sizeof(u128));
LOG_DEBUG(Service_ETicket, "called, entries={:016X}", out_entries);
@@ -183,7 +183,7 @@ private:
std::transform(tickets.begin(), tickets.end(), std::back_inserter(ids),
[](const auto& pair) { return pair.first; });
out_entries = std::min<u32>(ids.size(), out_entries);
out_entries = static_cast<u32>(std::min<std::size_t>(ids.size(), out_entries));
ctx.WriteBuffer(ids.data(), out_entries * sizeof(u128));
IPC::ResponseBuilder rb{ctx, 3};

View File

@@ -66,7 +66,7 @@ enum class FatalType : u32 {
static void GenerateErrorReport(Core::System& system, ResultCode error_code,
const FatalInfo& info) {
const auto title_id = Core::CurrentProcess()->GetTitleID();
const auto title_id = system.CurrentProcess()->GetTitleID();
std::string crash_report = fmt::format(
"Yuzu {}-{} crash report\n"
"Title ID: {:016x}\n"

View File

@@ -241,7 +241,7 @@ ResultVal<FileSys::EntryType> VfsDirectoryServiceWrapper::GetEntryType(
return FileSys::ERROR_PATH_NOT_FOUND;
}
FileSystemController::FileSystemController() = default;
FileSystemController::FileSystemController(Core::System& system_) : system{system_} {}
FileSystemController::~FileSystemController() = default;
@@ -290,7 +290,7 @@ ResultVal<FileSys::VirtualFile> FileSystemController::OpenRomFSCurrentProcess()
return ResultCode(-1);
}
return romfs_factory->OpenCurrentProcess();
return romfs_factory->OpenCurrentProcess(system.CurrentProcess()->GetTitleID());
}
ResultVal<FileSys::VirtualFile> FileSystemController::OpenRomFS(
@@ -447,10 +447,10 @@ FileSys::SaveDataSize FileSystemController::ReadSaveDataSize(FileSys::SaveDataTy
FileSys::SaveDataSize new_size{SUFFICIENT_SAVE_DATA_SIZE, SUFFICIENT_SAVE_DATA_SIZE};
FileSys::NACP nacp;
const auto res = Core::System::GetInstance().GetAppLoader().ReadControlData(nacp);
const auto res = system.GetAppLoader().ReadControlData(nacp);
if (res != Loader::ResultStatus::Success) {
FileSys::PatchManager pm{Core::CurrentProcess()->GetTitleID()};
FileSys::PatchManager pm{system.CurrentProcess()->GetTitleID()};
auto [nacp_unique, discard] = pm.GetControlMetadata();
if (nacp_unique != nullptr) {
@@ -702,10 +702,10 @@ void FileSystemController::CreateFactories(FileSys::VfsFilesystem& vfs, bool ove
if (bis_factory == nullptr) {
bis_factory =
std::make_unique<FileSys::BISFactory>(nand_directory, load_directory, dump_directory);
Core::System::GetInstance().RegisterContentProvider(
FileSys::ContentProviderUnionSlot::SysNAND, bis_factory->GetSystemNANDContents());
Core::System::GetInstance().RegisterContentProvider(
FileSys::ContentProviderUnionSlot::UserNAND, bis_factory->GetUserNANDContents());
system.RegisterContentProvider(FileSys::ContentProviderUnionSlot::SysNAND,
bis_factory->GetSystemNANDContents());
system.RegisterContentProvider(FileSys::ContentProviderUnionSlot::UserNAND,
bis_factory->GetUserNANDContents());
}
if (save_data_factory == nullptr) {
@@ -714,8 +714,8 @@ void FileSystemController::CreateFactories(FileSys::VfsFilesystem& vfs, bool ove
if (sdmc_factory == nullptr) {
sdmc_factory = std::make_unique<FileSys::SDMCFactory>(std::move(sd_directory));
Core::System::GetInstance().RegisterContentProvider(FileSys::ContentProviderUnionSlot::SDMC,
sdmc_factory->GetSDMCContents());
system.RegisterContentProvider(FileSys::ContentProviderUnionSlot::SDMC,
sdmc_factory->GetSDMCContents());
}
}

View File

@@ -10,6 +10,10 @@
#include "core/file_sys/vfs.h"
#include "core/hle/result.h"
namespace Core {
class System;
}
namespace FileSys {
class BISFactory;
class RegisteredCache;
@@ -52,7 +56,7 @@ enum class ImageDirectoryId : u32 {
class FileSystemController {
public:
FileSystemController();
explicit FileSystemController(Core::System& system_);
~FileSystemController();
ResultCode RegisterRomFS(std::unique_ptr<FileSys::RomFSFactory>&& factory);
@@ -125,6 +129,8 @@ private:
std::unique_ptr<FileSys::XCI> gamecard;
std::unique_ptr<FileSys::RegisteredCache> gamecard_registered;
std::unique_ptr<FileSys::PlaceholderCache> gamecard_placeholder;
Core::System& system;
};
void InstallInterfaces(Core::System& system);

View File

@@ -195,7 +195,7 @@ Hid::Hid(Core::System& system) : ServiceFramework("hid"), system(system) {
{101, &Hid::GetSupportedNpadStyleSet, "GetSupportedNpadStyleSet"},
{102, &Hid::SetSupportedNpadIdType, "SetSupportedNpadIdType"},
{103, &Hid::ActivateNpad, "ActivateNpad"},
{104, nullptr, "DeactivateNpad"},
{104, &Hid::DeactivateNpad, "DeactivateNpad"},
{106, &Hid::AcquireNpadStyleSetUpdateEventHandle, "AcquireNpadStyleSetUpdateEventHandle"},
{107, &Hid::DisconnectNpad, "DisconnectNpad"},
{108, &Hid::GetPlayerLedPattern, "GetPlayerLedPattern"},
@@ -470,6 +470,17 @@ void Hid::ActivateNpad(Kernel::HLERequestContext& ctx) {
applet_resource->ActivateController(HidController::NPad);
}
void Hid::DeactivateNpad(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto applet_resource_user_id{rp.Pop<u64>()};
LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
applet_resource->DeactivateController(HidController::NPad);
}
void Hid::AcquireNpadStyleSetUpdateEventHandle(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto npad_id{rp.Pop<u32>()};

View File

@@ -99,6 +99,7 @@ private:
void GetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx);
void SetSupportedNpadIdType(Kernel::HLERequestContext& ctx);
void ActivateNpad(Kernel::HLERequestContext& ctx);
void DeactivateNpad(Kernel::HLERequestContext& ctx);
void AcquireNpadStyleSetUpdateEventHandle(Kernel::HLERequestContext& ctx);
void DisconnectNpad(Kernel::HLERequestContext& ctx);
void GetPlayerLedPattern(Kernel::HLERequestContext& ctx);

View File

@@ -163,7 +163,7 @@ public:
return;
}
if (Core::CurrentProcess()->GetTitleID() != header.title_id) {
if (system.CurrentProcess()->GetTitleID() != header.title_id) {
LOG_ERROR(Service_LDR,
"Attempting to load NRR with title ID other than current process. (actual "
"{:016X})!",
@@ -327,7 +327,7 @@ public:
}
// Load NRO as new executable module
auto* process = Core::CurrentProcess();
auto* process = system.CurrentProcess();
auto& vm_manager = process->VMManager();
auto map_address = vm_manager.FindFreeRegion(nro_size + bss_size);
@@ -411,7 +411,7 @@ public:
return;
}
auto& vm_manager = Core::CurrentProcess()->VMManager();
auto& vm_manager = system.CurrentProcess()->VMManager();
const auto& nro_info = iter->second;
// Unmap the mirrored memory

View File

@@ -6,8 +6,10 @@
#include <string>
#include "common/logging/log.h"
#include "common/scope_exit.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/service/lm/lm.h"
#include "core/hle/service/lm/manager.h"
#include "core/hle/service/service.h"
#include "core/memory.h"
@@ -15,65 +17,16 @@ namespace Service::LM {
class ILogger final : public ServiceFramework<ILogger> {
public:
ILogger() : ServiceFramework("ILogger") {
ILogger(Manager& manager) : ServiceFramework("ILogger"), manager(manager) {
static const FunctionInfo functions[] = {
{0x00000000, &ILogger::Initialize, "Initialize"},
{0x00000001, &ILogger::SetDestination, "SetDestination"},
{0, &ILogger::Log, "Log"},
{1, &ILogger::SetDestination, "SetDestination"},
};
RegisterHandlers(functions);
}
private:
struct MessageHeader {
enum Flags : u32_le {
IsHead = 1,
IsTail = 2,
};
enum Severity : u32_le {
Trace,
Info,
Warning,
Error,
Critical,
};
u64_le pid;
u64_le threadContext;
union {
BitField<0, 16, Flags> flags;
BitField<16, 8, Severity> severity;
BitField<24, 8, u32> verbosity;
};
u32_le payload_size;
bool IsHeadLog() const {
return flags & Flags::IsHead;
}
bool IsTailLog() const {
return flags & Flags::IsTail;
}
};
static_assert(sizeof(MessageHeader) == 0x18, "MessageHeader is incorrect size");
/// Log field type
enum class Field : u8 {
Skip = 1,
Message = 2,
Line = 3,
Filename = 4,
Function = 5,
Module = 6,
Thread = 7,
};
/**
* ILogger::Initialize service function
* Inputs:
* 0: 0x00000000
* Outputs:
* 0: ResultCode
*/
void Initialize(Kernel::HLERequestContext& ctx) {
void Log(Kernel::HLERequestContext& ctx) {
// This function only succeeds - Get that out of the way
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
@@ -85,140 +38,70 @@ private:
Memory::ReadBlock(addr, &header, sizeof(MessageHeader));
addr += sizeof(MessageHeader);
if (header.IsHeadLog()) {
log_stream.str("");
log_stream.clear();
}
// Parse out log metadata
u32 line{};
std::string module;
std::string message;
std::string filename;
std::string function;
std::string thread;
FieldMap fields;
while (addr < end_addr) {
const Field field{static_cast<Field>(Memory::Read8(addr++))};
const std::size_t length{Memory::Read8(addr++)};
const auto field = static_cast<Field>(Memory::Read8(addr++));
const auto length = Memory::Read8(addr++);
if (static_cast<Field>(Memory::Read8(addr)) == Field::Skip) {
++addr;
}
switch (field) {
case Field::Skip:
break;
case Field::Message:
message = Memory::ReadCString(addr, length);
break;
case Field::Line:
line = Memory::Read32(addr);
break;
case Field::Filename:
filename = Memory::ReadCString(addr, length);
break;
case Field::Function:
function = Memory::ReadCString(addr, length);
break;
case Field::Module:
module = Memory::ReadCString(addr, length);
break;
case Field::Thread:
thread = Memory::ReadCString(addr, length);
break;
SCOPE_EXIT({ addr += length; });
if (field == Field::Skip) {
continue;
}
addr += length;
std::vector<u8> data(length);
Memory::ReadBlock(addr, data.data(), length);
fields.emplace(field, std::move(data));
}
// Empty log - nothing to do here
if (log_stream.str().empty() && message.empty()) {
return;
}
// Format a nicely printable string out of the log metadata
if (!filename.empty()) {
log_stream << filename << ':';
}
if (!module.empty()) {
log_stream << module << ':';
}
if (!function.empty()) {
log_stream << function << ':';
}
if (line) {
log_stream << std::to_string(line) << ':';
}
if (!thread.empty()) {
log_stream << thread << ':';
}
if (log_stream.str().length() > 0 && log_stream.str().back() == ':') {
log_stream << ' ';
}
log_stream << message;
if (header.IsTailLog()) {
switch (header.severity) {
case MessageHeader::Severity::Trace:
LOG_DEBUG(Debug_Emulated, "{}", log_stream.str());
break;
case MessageHeader::Severity::Info:
LOG_INFO(Debug_Emulated, "{}", log_stream.str());
break;
case MessageHeader::Severity::Warning:
LOG_WARNING(Debug_Emulated, "{}", log_stream.str());
break;
case MessageHeader::Severity::Error:
LOG_ERROR(Debug_Emulated, "{}", log_stream.str());
break;
case MessageHeader::Severity::Critical:
LOG_CRITICAL(Debug_Emulated, "{}", log_stream.str());
break;
}
}
manager.Log({header, std::move(fields)});
}
// This service function is intended to be used as a way to
// redirect logging output to different destinations, however,
// given we always want to see the logging output, it's sufficient
// to do nothing and return success here.
void SetDestination(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_LM, "called");
IPC::RequestParser rp{ctx};
const auto destination = rp.PopEnum<DestinationFlag>();
LOG_DEBUG(Service_LM, "called, destination={:08X}", static_cast<u32>(destination));
manager.SetDestination(destination);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
std::ostringstream log_stream;
Manager& manager;
};
class LM final : public ServiceFramework<LM> {
public:
explicit LM() : ServiceFramework{"lm"} {
explicit LM(Manager& manager) : ServiceFramework{"lm"}, manager(manager) {
// clang-format off
static const FunctionInfo functions[] = {
{0x00000000, &LM::OpenLogger, "OpenLogger"},
{0, &LM::OpenLogger, "OpenLogger"},
};
// clang-format on
RegisterHandlers(functions);
}
/**
* LM::OpenLogger service function
* Inputs:
* 0: 0x00000000
* Outputs:
* 0: ResultCode
*/
private:
void OpenLogger(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_LM, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ILogger>();
rb.PushIpcInterface<ILogger>(manager);
}
Manager& manager;
};
void InstallInterfaces(SM::ServiceManager& service_manager) {
std::make_shared<LM>()->InstallAsService(service_manager);
void InstallInterfaces(Core::System& system) {
std::make_shared<LM>(system.GetLogManager())->InstallAsService(system.ServiceManager());
}
} // namespace Service::LM

View File

@@ -4,13 +4,13 @@
#pragma once
namespace Service::SM {
class ServiceManager;
namespace Core {
class System;
}
namespace Service::LM {
/// Registers all LM services with the specified service manager.
void InstallInterfaces(SM::ServiceManager& service_manager);
void InstallInterfaces(Core::System& system);
} // namespace Service::LM

View File

@@ -0,0 +1,133 @@
// Copyright 2019 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "common/assert.h"
#include "common/logging/log.h"
#include "common/string_util.h"
#include "core/hle/service/lm/manager.h"
#include "core/reporter.h"
namespace Service::LM {
std::ostream& operator<<(std::ostream& os, DestinationFlag dest) {
std::vector<std::string> array;
const auto check_single_flag = [dest, &array](DestinationFlag check, std::string name) {
if ((static_cast<u32>(check) & static_cast<u32>(dest)) != 0) {
array.emplace_back(std::move(name));
}
};
check_single_flag(DestinationFlag::Default, "Default");
check_single_flag(DestinationFlag::UART, "UART");
check_single_flag(DestinationFlag::UARTSleeping, "UART (Sleeping)");
os << "[";
for (const auto& entry : array) {
os << entry << ", ";
}
return os << "]";
}
std::ostream& operator<<(std::ostream& os, MessageHeader::Severity severity) {
switch (severity) {
case MessageHeader::Severity::Trace:
return os << "Trace";
case MessageHeader::Severity::Info:
return os << "Info";
case MessageHeader::Severity::Warning:
return os << "Warning";
case MessageHeader::Severity::Error:
return os << "Error";
case MessageHeader::Severity::Critical:
return os << "Critical";
default:
return os << fmt::format("{:08X}", static_cast<u32>(severity));
}
}
std::ostream& operator<<(std::ostream& os, Field field) {
switch (field) {
case Field::Skip:
return os << "Skip";
case Field::Message:
return os << "Message";
case Field::Line:
return os << "Line";
case Field::Filename:
return os << "Filename";
case Field::Function:
return os << "Function";
case Field::Module:
return os << "Module";
case Field::Thread:
return os << "Thread";
default:
return os << fmt::format("{:08X}", static_cast<u32>(field));
}
}
std::string FormatField(Field type, const std::vector<u8>& data) {
switch (type) {
case Field::Skip:
return "";
case Field::Line:
if (data.size() >= sizeof(u32)) {
u32 line;
std::memcpy(&line, data.data(), sizeof(u32));
return fmt::format("{}", line);
}
return "[ERROR DECODING LINE NUMBER]";
case Field::Message:
case Field::Filename:
case Field::Function:
case Field::Module:
case Field::Thread:
return Common::StringFromFixedZeroTerminatedBuffer(
reinterpret_cast<const char*>(data.data()), data.size());
default:
UNIMPLEMENTED();
}
}
Manager::Manager(Core::Reporter& reporter) : reporter(reporter) {}
Manager::~Manager() = default;
void Manager::SetEnabled(bool enabled) {
this->enabled = enabled;
}
void Manager::SetDestination(DestinationFlag destination) {
this->destination = destination;
}
void Manager::Log(LogMessage message) {
if (message.header.IsHeadLog()) {
InitializeLog();
}
current_log.emplace_back(std::move(message));
if (current_log.back().header.IsTailLog()) {
FinalizeLog();
}
}
void Manager::Flush() {
FinalizeLog();
}
void Manager::InitializeLog() {
current_log.clear();
LOG_INFO(Service_LM, "Initialized new log session");
}
void Manager::FinalizeLog() {
reporter.SaveLogReport(static_cast<u32>(destination), std::move(current_log));
LOG_INFO(Service_LM, "Finalized current log session");
}
} // namespace Service::LM

View File

@@ -0,0 +1,106 @@
// Copyright 2019 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <map>
#include <ostream>
#include <vector>
#include "common/bit_field.h"
#include "common/common_types.h"
#include "common/swap.h"
namespace Core {
class Reporter;
}
namespace Service::LM {
enum class DestinationFlag : u32 {
Default = 1,
UART = 2,
UARTSleeping = 4,
All = 0xFFFF,
};
struct MessageHeader {
enum Flags : u32_le {
IsHead = 1,
IsTail = 2,
};
enum Severity : u32_le {
Trace,
Info,
Warning,
Error,
Critical,
};
u64_le pid;
u64_le thread_context;
union {
BitField<0, 16, Flags> flags;
BitField<16, 8, Severity> severity;
BitField<24, 8, u32> verbosity;
};
u32_le payload_size;
bool IsHeadLog() const {
return flags & IsHead;
}
bool IsTailLog() const {
return flags & IsTail;
}
};
static_assert(sizeof(MessageHeader) == 0x18, "MessageHeader is incorrect size");
enum class Field : u8 {
Skip = 1,
Message = 2,
Line = 3,
Filename = 4,
Function = 5,
Module = 6,
Thread = 7,
};
std::ostream& operator<<(std::ostream& os, DestinationFlag dest);
std::ostream& operator<<(std::ostream& os, MessageHeader::Severity severity);
std::ostream& operator<<(std::ostream& os, Field field);
using FieldMap = std::map<Field, std::vector<u8>>;
struct LogMessage {
MessageHeader header;
FieldMap fields;
};
std::string FormatField(Field type, const std::vector<u8>& data);
class Manager {
public:
explicit Manager(Core::Reporter& reporter);
~Manager();
void SetEnabled(bool enabled);
void SetDestination(DestinationFlag destination);
void Log(LogMessage message);
void Flush();
private:
void InitializeLog();
void FinalizeLog();
bool enabled = true;
DestinationFlag destination = DestinationFlag::All;
std::vector<LogMessage> current_log;
Core::Reporter& reporter;
};
} // namespace Service::LM

View File

@@ -6,13 +6,6 @@
#include <cstring>
#include <vector>
#include <FontChineseSimplified.h>
#include <FontChineseTraditional.h>
#include <FontExtendedChineseSimplified.h>
#include <FontKorean.h>
#include <FontNintendoExtended.h>
#include <FontStandard.h>
#include "common/assert.h"
#include "common/common_paths.h"
#include "common/common_types.h"
@@ -24,7 +17,9 @@
#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/ipc_helpers.h"
#include "core/hle/kernel/physical_memory.h"
#include "core/hle/kernel/shared_memory.h"
#include "core/hle/service/filesystem/filesystem.h"
#include "core/hle/service/ns/pl_u.h"
@@ -94,15 +89,20 @@ static void DecryptSharedFont(const std::vector<u32>& input, Kernel::PhysicalMem
offset += transformed_font.size() * sizeof(u32);
}
static void EncryptSharedFont(const std::vector<u8>& input, Kernel::PhysicalMemory& output,
std::size_t& offset) {
ASSERT_MSG(offset + input.size() + 8 < SHARED_FONT_MEM_SIZE, "Shared fonts exceeds 17mb!");
const u32 KEY = EXPECTED_MAGIC ^ EXPECTED_RESULT;
std::memcpy(output.data() + offset, &EXPECTED_RESULT, sizeof(u32)); // Magic header
const u32 ENC_SIZE = static_cast<u32>(input.size()) ^ KEY;
std::memcpy(output.data() + offset + sizeof(u32), &ENC_SIZE, sizeof(u32));
std::memcpy(output.data() + offset + (sizeof(u32) * 2), input.data(), input.size());
offset += input.size() + (sizeof(u32) * 2);
void EncryptSharedFont(const std::vector<u32>& input, std::vector<u8>& output,
std::size_t& offset) {
ASSERT_MSG(offset + (input.size() * sizeof(u32)) < SHARED_FONT_MEM_SIZE,
"Shared fonts exceeds 17mb!");
const auto key = Common::swap32(EXPECTED_RESULT ^ EXPECTED_MAGIC);
std::vector<u32> transformed_font(input.size() + 2);
transformed_font[0] = Common::swap32(EXPECTED_MAGIC);
transformed_font[1] = Common::swap32(input.size() * sizeof(u32)) ^ key;
std::transform(input.begin(), input.end(), transformed_font.begin() + 2,
[key](u32 in) { return in ^ key; });
std::memcpy(output.data() + offset, transformed_font.data(),
transformed_font.size() * sizeof(u32));
offset += transformed_font.size() * sizeof(u32);
}
// Helper function to make BuildSharedFontsRawRegions a bit nicer
@@ -168,114 +168,49 @@ PL_U::PL_U(Core::System& system)
// Attempt to load shared font data from disk
const auto* nand = fsc.GetSystemNANDContents();
std::size_t offset = 0;
// Rebuild shared fonts from data ncas
if (nand->HasEntry(static_cast<u64>(FontArchives::Standard),
FileSys::ContentRecordType::Data)) {
impl->shared_font = std::make_shared<Kernel::PhysicalMemory>(SHARED_FONT_MEM_SIZE);
for (auto font : SHARED_FONTS) {
const auto nca =
nand->GetEntry(static_cast<u64>(font.first), FileSys::ContentRecordType::Data);
if (!nca) {
LOG_ERROR(Service_NS, "Failed to find {:016X}! Skipping",
static_cast<u64>(font.first));
continue;
}
const auto romfs = nca->GetRomFS();
if (!romfs) {
LOG_ERROR(Service_NS, "{:016X} has no RomFS! Skipping",
static_cast<u64>(font.first));
continue;
}
const auto extracted_romfs = FileSys::ExtractRomFS(romfs);
if (!extracted_romfs) {
LOG_ERROR(Service_NS, "Failed to extract RomFS for {:016X}! Skipping",
static_cast<u64>(font.first));
continue;
}
const auto font_fp = extracted_romfs->GetFile(font.second);
if (!font_fp) {
LOG_ERROR(Service_NS, "{:016X} has no file \"{}\"! Skipping",
static_cast<u64>(font.first), font.second);
continue;
}
std::vector<u32> font_data_u32(font_fp->GetSize() / sizeof(u32));
font_fp->ReadBytes<u32>(font_data_u32.data(), font_fp->GetSize());
// We need to be BigEndian as u32s for the xor encryption
std::transform(font_data_u32.begin(), font_data_u32.end(), font_data_u32.begin(),
Common::swap32);
FontRegion region{
static_cast<u32>(offset + 8),
static_cast<u32>((font_data_u32.size() * sizeof(u32)) -
8)}; // Font offset and size do not account for the header
DecryptSharedFont(font_data_u32, *impl->shared_font, offset);
impl->shared_font_regions.push_back(region);
// Rebuild shared fonts from data ncas or synthesize
impl->shared_font = std::make_shared<Kernel::PhysicalMemory>(SHARED_FONT_MEM_SIZE);
for (auto font : SHARED_FONTS) {
FileSys::VirtualFile romfs;
const auto nca =
nand->GetEntry(static_cast<u64>(font.first), FileSys::ContentRecordType::Data);
if (nca) {
romfs = nca->GetRomFS();
}
} else {
impl->shared_font = std::make_shared<Kernel::PhysicalMemory>(
SHARED_FONT_MEM_SIZE); // Shared memory needs to always be allocated and a fixed size
const std::string user_path = FileUtil::GetUserPath(FileUtil::UserPath::SysDataDir);
const std::string filepath{user_path + SHARED_FONT};
// Create path if not already created
if (!FileUtil::CreateFullPath(filepath)) {
LOG_ERROR(Service_NS, "Failed to create sharedfonts path \"{}\"!", filepath);
return;
if (!romfs) {
romfs = FileSys::SystemArchive::SynthesizeSystemArchive(static_cast<u64>(font.first));
}
bool using_ttf = false;
for (const char* font_ttf : SHARED_FONTS_TTF) {
if (FileUtil::Exists(user_path + font_ttf)) {
using_ttf = true;
FileUtil::IOFile file(user_path + font_ttf, "rb");
if (file.IsOpen()) {
std::vector<u8> ttf_bytes(file.GetSize());
file.ReadBytes<u8>(ttf_bytes.data(), ttf_bytes.size());
FontRegion region{
static_cast<u32>(offset + 8),
static_cast<u32>(ttf_bytes.size())}; // Font offset and size do not account
// for the header
EncryptSharedFont(ttf_bytes, *impl->shared_font, offset);
impl->shared_font_regions.push_back(region);
} else {
LOG_WARNING(Service_NS, "Unable to load font: {}", font_ttf);
}
} else if (using_ttf) {
LOG_WARNING(Service_NS, "Unable to find font: {}", font_ttf);
}
if (!romfs) {
LOG_ERROR(Service_NS, "Failed to find or synthesize {:016X}! Skipping",
static_cast<u64>(font.first));
continue;
}
if (using_ttf)
return;
FileUtil::IOFile file(filepath, "rb");
if (file.IsOpen()) {
// Read shared font data
ASSERT(file.GetSize() == SHARED_FONT_MEM_SIZE);
file.ReadBytes(impl->shared_font->data(), impl->shared_font->size());
impl->BuildSharedFontsRawRegions(*impl->shared_font);
} else {
LOG_WARNING(Service_NS,
"Shared Font file missing. Loading open source replacement from memory");
// clang-format off
const std::vector<std::vector<u8>> open_source_shared_fonts_ttf = {
{std::begin(FontChineseSimplified), std::end(FontChineseSimplified)},
{std::begin(FontChineseTraditional), std::end(FontChineseTraditional)},
{std::begin(FontExtendedChineseSimplified), std::end(FontExtendedChineseSimplified)},
{std::begin(FontKorean), std::end(FontKorean)},
{std::begin(FontNintendoExtended), std::end(FontNintendoExtended)},
{std::begin(FontStandard), std::end(FontStandard)},
};
// clang-format on
for (const std::vector<u8>& font_ttf : open_source_shared_fonts_ttf) {
const FontRegion region{static_cast<u32>(offset + 8),
static_cast<u32>(font_ttf.size())};
EncryptSharedFont(font_ttf, *impl->shared_font, offset);
impl->shared_font_regions.push_back(region);
}
const auto extracted_romfs = FileSys::ExtractRomFS(romfs);
if (!extracted_romfs) {
LOG_ERROR(Service_NS, "Failed to extract RomFS for {:016X}! Skipping",
static_cast<u64>(font.first));
continue;
}
const auto font_fp = extracted_romfs->GetFile(font.second);
if (!font_fp) {
LOG_ERROR(Service_NS, "{:016X} has no file \"{}\"! Skipping",
static_cast<u64>(font.first), font.second);
continue;
}
std::vector<u32> font_data_u32(font_fp->GetSize() / sizeof(u32));
font_fp->ReadBytes<u32>(font_data_u32.data(), font_fp->GetSize());
// We need to be BigEndian as u32s for the xor encryption
std::transform(font_data_u32.begin(), font_data_u32.end(), font_data_u32.begin(),
Common::swap32);
// Font offset and size do not account for the header
const FontRegion region{static_cast<u32>(offset + 8),
static_cast<u32>((font_data_u32.size() * sizeof(u32)) - 8)};
DecryptSharedFont(font_data_u32, *impl->shared_font, offset);
impl->shared_font_regions.push_back(region);
}
}
@@ -324,14 +259,14 @@ void PL_U::GetSharedMemoryAddressOffset(Kernel::HLERequestContext& ctx) {
void PL_U::GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx) {
// Map backing memory for the font data
LOG_DEBUG(Service_NS, "called");
Core::CurrentProcess()->VMManager().MapMemoryBlock(SHARED_FONT_MEM_VADDR, impl->shared_font, 0,
SHARED_FONT_MEM_SIZE,
Kernel::MemoryState::Shared);
system.CurrentProcess()->VMManager().MapMemoryBlock(SHARED_FONT_MEM_VADDR, impl->shared_font, 0,
SHARED_FONT_MEM_SIZE,
Kernel::MemoryState::Shared);
// Create shared font memory object
auto& kernel = system.Kernel();
impl->shared_font_mem = Kernel::SharedMemory::Create(
kernel, Core::CurrentProcess(), SHARED_FONT_MEM_SIZE, Kernel::MemoryPermission::ReadWrite,
kernel, system.CurrentProcess(), SHARED_FONT_MEM_SIZE, Kernel::MemoryPermission::ReadWrite,
Kernel::MemoryPermission::Read, SHARED_FONT_MEM_VADDR, Kernel::MemoryRegion::BASE,
"PL_U:shared_font_mem");

View File

@@ -5,6 +5,7 @@
#pragma once
#include <memory>
#include <vector>
#include "core/hle/service/service.h"
namespace Service {
@@ -15,6 +16,8 @@ class FileSystemController;
namespace NS {
void EncryptSharedFont(const std::vector<u32>& input, std::vector<u8>& output, std::size_t& offset);
class PL_U final : public ServiceFramework<PL_U> {
public:
explicit PL_U(Core::System& system);

View File

@@ -226,7 +226,7 @@ void Init(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system) {
LBL::InstallInterfaces(*sm);
LDN::InstallInterfaces(*sm);
LDR::InstallInterfaces(*sm, system);
LM::InstallInterfaces(*sm);
LM::InstallInterfaces(system);
Migration::InstallInterfaces(*sm);
Mii::InstallInterfaces(*sm);
MM::InstallInterfaces(*sm);

View File

@@ -146,7 +146,7 @@ static u8* GetPointerFromVMA(const Kernel::Process& process, VAddr vaddr) {
* using a VMA from the current process.
*/
static u8* GetPointerFromVMA(VAddr vaddr) {
return GetPointerFromVMA(*Core::CurrentProcess(), vaddr);
return GetPointerFromVMA(*Core::System::GetInstance().CurrentProcess(), vaddr);
}
template <typename T>
@@ -226,7 +226,7 @@ bool IsValidVirtualAddress(const Kernel::Process& process, const VAddr vaddr) {
}
bool IsValidVirtualAddress(const VAddr vaddr) {
return IsValidVirtualAddress(*Core::CurrentProcess(), vaddr);
return IsValidVirtualAddress(*Core::System::GetInstance().CurrentProcess(), vaddr);
}
bool IsKernelVirtualAddress(const VAddr vaddr) {
@@ -387,7 +387,7 @@ void ReadBlock(const Kernel::Process& process, const VAddr src_addr, void* dest_
}
void ReadBlock(const VAddr src_addr, void* dest_buffer, const std::size_t size) {
ReadBlock(*Core::CurrentProcess(), src_addr, dest_buffer, size);
ReadBlock(*Core::System::GetInstance().CurrentProcess(), src_addr, dest_buffer, size);
}
void Write8(const VAddr addr, const u8 data) {
@@ -450,7 +450,7 @@ void WriteBlock(const Kernel::Process& process, const VAddr dest_addr, const voi
}
void WriteBlock(const VAddr dest_addr, const void* src_buffer, const std::size_t size) {
WriteBlock(*Core::CurrentProcess(), dest_addr, src_buffer, size);
WriteBlock(*Core::System::GetInstance().CurrentProcess(), dest_addr, src_buffer, size);
}
void ZeroBlock(const Kernel::Process& process, const VAddr dest_addr, const std::size_t size) {
@@ -539,7 +539,7 @@ void CopyBlock(const Kernel::Process& process, VAddr dest_addr, VAddr src_addr,
}
void CopyBlock(VAddr dest_addr, VAddr src_addr, std::size_t size) {
CopyBlock(*Core::CurrentProcess(), dest_addr, src_addr, size);
CopyBlock(*Core::System::GetInstance().CurrentProcess(), dest_addr, src_addr, size);
}
} // namespace Memory

View File

@@ -7,6 +7,7 @@
#include <fmt/chrono.h>
#include <fmt/format.h>
#include <fmt/ostream.h>
#include <json.hpp>
#include "common/file_util.h"
@@ -17,6 +18,7 @@
#include "core/hle/kernel/hle_ipc.h"
#include "core/hle/kernel/process.h"
#include "core/hle/result.h"
#include "core/hle/service/lm/manager.h"
#include "core/reporter.h"
#include "core/settings.h"
@@ -354,6 +356,55 @@ void Reporter::SaveErrorReport(u64 title_id, ResultCode result,
SaveToFile(std::move(out), GetPath("error_report", title_id, timestamp));
}
void Reporter::SaveLogReport(u32 destination, std::vector<Service::LM::LogMessage> messages) const {
if (!IsReportingEnabled()) {
return;
}
const auto timestamp = GetTimestamp();
json out;
out["yuzu_version"] = GetYuzuVersionData();
out["report_common"] =
GetReportCommonData(system.CurrentProcess()->GetTitleID(), RESULT_SUCCESS, timestamp);
out["log_destination"] =
fmt::format("{}", static_cast<Service::LM::DestinationFlag>(destination));
auto json_messages = json::array();
std::transform(messages.begin(), messages.end(), std::back_inserter(json_messages),
[](const Service::LM::LogMessage& message) {
json out;
out["is_head"] = fmt::format("{}", message.header.IsHeadLog());
out["is_tail"] = fmt::format("{}", message.header.IsTailLog());
out["pid"] = fmt::format("{:016X}", message.header.pid);
out["thread_context"] =
fmt::format("{:016X}", message.header.thread_context);
out["payload_size"] = fmt::format("{:016X}", message.header.payload_size);
out["flags"] = fmt::format("{:04X}", message.header.flags.Value());
out["severity"] = fmt::format("{}", message.header.severity.Value());
out["verbosity"] = fmt::format("{:02X}", message.header.verbosity);
auto fields = json::array();
std::transform(message.fields.begin(), message.fields.end(),
std::back_inserter(fields), [](const auto& kv) {
json out;
out["type"] = fmt::format("{}", kv.first);
out["data"] =
Service::LM::FormatField(kv.first, kv.second);
return out;
});
out["fields"] = std::move(fields);
return out;
});
out["log_messages"] = std::move(json_messages);
SaveToFile(std::move(out),
GetPath("log_report", system.CurrentProcess()->GetTitleID(), timestamp));
}
void Reporter::SaveFilesystemAccessReport(Service::FileSystem::LogMode log_mode,
std::string log_message) const {
if (!IsReportingEnabled())

View File

@@ -20,6 +20,10 @@ namespace Service::FileSystem {
enum class LogMode : u32;
}
namespace Service::LM {
struct LogMessage;
} // namespace Service::LM
namespace Core {
class System;
@@ -29,18 +33,22 @@ public:
explicit Reporter(System& system);
~Reporter();
// Used by fatal services
void SaveCrashReport(u64 title_id, ResultCode result, u64 set_flags, u64 entry_point, u64 sp,
u64 pc, u64 pstate, u64 afsr0, u64 afsr1, u64 esr, u64 far,
const std::array<u64, 31>& registers, const std::array<u64, 32>& backtrace,
u32 backtrace_size, const std::string& arch, u32 unk10) const;
// Used by syscall svcBreak
void SaveSvcBreakReport(u32 type, bool signal_debugger, u64 info1, u64 info2,
std::optional<std::vector<u8>> resolved_buffer = {}) const;
// Used by HLE service handler
void SaveUnimplementedFunctionReport(Kernel::HLERequestContext& ctx, u32 command_id,
const std::string& name,
const std::string& service_name) const;
// Used by stub applet implementation
void SaveUnimplementedAppletReport(u32 applet_id, u32 common_args_version, u32 library_version,
u32 theme_color, bool startup_sound, u64 system_tick,
std::vector<std::vector<u8>> normal_channel,
@@ -55,6 +63,7 @@ public:
void SavePlayReport(PlayReportType type, u64 title_id, std::vector<std::vector<u8>> data,
std::optional<u64> process_id = {}, std::optional<u128> user_id = {}) const;
// Used by error applet
void SaveErrorReport(u64 title_id, ResultCode result,
std::optional<std::string> custom_text_main = {},
std::optional<std::string> custom_text_detail = {}) const;
@@ -62,6 +71,11 @@ public:
void SaveFilesystemAccessReport(Service::FileSystem::LogMode log_mode,
std::string log_message) const;
// Used by lm services
void SaveLogReport(u32 destination, std::vector<Service::LM::LogMessage> messages) const;
// Can be used anywhere to generate a backtrace and general info report at any point during
// execution. Not intended to be used for anything other than debugging or testing.
void SaveUserReport() const;
private:

View File

@@ -6,6 +6,7 @@
#include <array>
#include <bitset>
#include <cstdlib>
#include <string>
#include "common/file_util.h"
#include "core/core.h"
@@ -13,7 +14,7 @@
// Numbers are chosen randomly to make sure the correct one is given.
static constexpr std::array<u64, 5> CB_IDS{{42, 144, 93, 1026, UINT64_C(0xFFFF7FFFF7FFFF)}};
static constexpr int MAX_SLICE_LENGTH = 20000; // Copied from CoreTiming internals
static constexpr int MAX_SLICE_LENGTH = 10000; // Copied from CoreTiming internals
static std::bitset<CB_IDS.size()> callbacks_ran_flags;
static u64 expected_callback = 0;
@@ -28,6 +29,12 @@ void CallbackTemplate(u64 userdata, s64 cycles_late) {
REQUIRE(lateness == cycles_late);
}
static u64 callbacks_done = 0;
void EmptyCallback(u64 userdata, s64 cycles_late) {
++callbacks_done;
}
struct ScopeInit final {
ScopeInit() {
core_timing.Initialize();
@@ -39,18 +46,19 @@ struct ScopeInit final {
Core::Timing::CoreTiming core_timing;
};
static void AdvanceAndCheck(Core::Timing::CoreTiming& core_timing, u32 idx, int downcount,
static void AdvanceAndCheck(Core::Timing::CoreTiming& core_timing, u32 idx, u32 context = 0,
int expected_lateness = 0, int cpu_downcount = 0) {
callbacks_ran_flags = 0;
expected_callback = CB_IDS[idx];
lateness = expected_lateness;
// Pretend we executed X cycles of instructions.
core_timing.SwitchContext(context);
core_timing.AddTicks(core_timing.GetDowncount() - cpu_downcount);
core_timing.Advance();
core_timing.SwitchContext((context + 1) % 4);
REQUIRE(decltype(callbacks_ran_flags)().set(idx) == callbacks_ran_flags);
REQUIRE(downcount == core_timing.GetDowncount());
}
TEST_CASE("CoreTiming[BasicOrder]", "[core]") {
@@ -64,9 +72,10 @@ TEST_CASE("CoreTiming[BasicOrder]", "[core]") {
Core::Timing::EventType* cb_e = core_timing.RegisterEvent("callbackE", CallbackTemplate<4>);
// Enter slice 0
core_timing.Advance();
core_timing.ResetRun();
// D -> B -> C -> A -> E
core_timing.SwitchContext(0);
core_timing.ScheduleEvent(1000, cb_a, CB_IDS[0]);
REQUIRE(1000 == core_timing.GetDowncount());
core_timing.ScheduleEvent(500, cb_b, CB_IDS[1]);
@@ -78,98 +87,46 @@ TEST_CASE("CoreTiming[BasicOrder]", "[core]") {
core_timing.ScheduleEvent(1200, cb_e, CB_IDS[4]);
REQUIRE(100 == core_timing.GetDowncount());
AdvanceAndCheck(core_timing, 3, 400);
AdvanceAndCheck(core_timing, 1, 300);
AdvanceAndCheck(core_timing, 2, 200);
AdvanceAndCheck(core_timing, 0, 200);
AdvanceAndCheck(core_timing, 4, MAX_SLICE_LENGTH);
AdvanceAndCheck(core_timing, 3, 0);
AdvanceAndCheck(core_timing, 1, 1);
AdvanceAndCheck(core_timing, 2, 2);
AdvanceAndCheck(core_timing, 0, 3);
AdvanceAndCheck(core_timing, 4, 0);
}
TEST_CASE("CoreTiming[Threadsave]", "[core]") {
ScopeInit guard;
auto& core_timing = guard.core_timing;
Core::Timing::EventType* cb_a = core_timing.RegisterEvent("callbackA", CallbackTemplate<0>);
Core::Timing::EventType* cb_b = core_timing.RegisterEvent("callbackB", CallbackTemplate<1>);
Core::Timing::EventType* cb_c = core_timing.RegisterEvent("callbackC", CallbackTemplate<2>);
Core::Timing::EventType* cb_d = core_timing.RegisterEvent("callbackD", CallbackTemplate<3>);
Core::Timing::EventType* cb_e = core_timing.RegisterEvent("callbackE", CallbackTemplate<4>);
// Enter slice 0
core_timing.Advance();
// D -> B -> C -> A -> E
core_timing.ScheduleEvent(1000, cb_a, CB_IDS[0]);
// Manually force since ScheduleEvent doesn't call it
core_timing.ForceExceptionCheck(1000);
REQUIRE(1000 == core_timing.GetDowncount());
core_timing.ScheduleEvent(500, cb_b, CB_IDS[1]);
// Manually force since ScheduleEvent doesn't call it
core_timing.ForceExceptionCheck(500);
REQUIRE(500 == core_timing.GetDowncount());
core_timing.ScheduleEvent(800, cb_c, CB_IDS[2]);
// Manually force since ScheduleEvent doesn't call it
core_timing.ForceExceptionCheck(800);
REQUIRE(500 == core_timing.GetDowncount());
core_timing.ScheduleEvent(100, cb_d, CB_IDS[3]);
// Manually force since ScheduleEvent doesn't call it
core_timing.ForceExceptionCheck(100);
REQUIRE(100 == core_timing.GetDowncount());
core_timing.ScheduleEvent(1200, cb_e, CB_IDS[4]);
// Manually force since ScheduleEvent doesn't call it
core_timing.ForceExceptionCheck(1200);
REQUIRE(100 == core_timing.GetDowncount());
AdvanceAndCheck(core_timing, 3, 400);
AdvanceAndCheck(core_timing, 1, 300);
AdvanceAndCheck(core_timing, 2, 200);
AdvanceAndCheck(core_timing, 0, 200);
AdvanceAndCheck(core_timing, 4, MAX_SLICE_LENGTH);
}
namespace SharedSlotTest {
static unsigned int counter = 0;
template <unsigned int ID>
void FifoCallback(u64 userdata, s64 cycles_late) {
static_assert(ID < CB_IDS.size(), "ID out of range");
callbacks_ran_flags.set(ID);
REQUIRE(CB_IDS[ID] == userdata);
REQUIRE(ID == counter);
REQUIRE(lateness == cycles_late);
++counter;
}
} // namespace SharedSlotTest
TEST_CASE("CoreTiming[SharedSlot]", "[core]") {
using namespace SharedSlotTest;
TEST_CASE("CoreTiming[FairSharing]", "[core]") {
ScopeInit guard;
auto& core_timing = guard.core_timing;
Core::Timing::EventType* cb_a = core_timing.RegisterEvent("callbackA", FifoCallback<0>);
Core::Timing::EventType* cb_b = core_timing.RegisterEvent("callbackB", FifoCallback<1>);
Core::Timing::EventType* cb_c = core_timing.RegisterEvent("callbackC", FifoCallback<2>);
Core::Timing::EventType* cb_d = core_timing.RegisterEvent("callbackD", FifoCallback<3>);
Core::Timing::EventType* cb_e = core_timing.RegisterEvent("callbackE", FifoCallback<4>);
Core::Timing::EventType* empty_callback =
core_timing.RegisterEvent("empty_callback", EmptyCallback);
core_timing.ScheduleEvent(1000, cb_a, CB_IDS[0]);
core_timing.ScheduleEvent(1000, cb_b, CB_IDS[1]);
core_timing.ScheduleEvent(1000, cb_c, CB_IDS[2]);
core_timing.ScheduleEvent(1000, cb_d, CB_IDS[3]);
core_timing.ScheduleEvent(1000, cb_e, CB_IDS[4]);
callbacks_done = 0;
u64 MAX_CALLBACKS = 10;
for (std::size_t i = 0; i < 10; i++) {
core_timing.ScheduleEvent(i * 3333U, empty_callback, 0);
}
// Enter slice 0
core_timing.Advance();
REQUIRE(1000 == core_timing.GetDowncount());
const s64 advances = MAX_SLICE_LENGTH / 10;
core_timing.ResetRun();
u64 current_time = core_timing.GetTicks();
bool keep_running{};
do {
keep_running = false;
for (u32 active_core = 0; active_core < 4; ++active_core) {
core_timing.SwitchContext(active_core);
if (core_timing.CanCurrentContextRun()) {
core_timing.AddTicks(std::min<s64>(advances, core_timing.GetDowncount()));
core_timing.Advance();
}
keep_running |= core_timing.CanCurrentContextRun();
}
} while (keep_running);
u64 current_time_2 = core_timing.GetTicks();
callbacks_ran_flags = 0;
counter = 0;
lateness = 0;
core_timing.AddTicks(core_timing.GetDowncount());
core_timing.Advance();
REQUIRE(MAX_SLICE_LENGTH == core_timing.GetDowncount());
REQUIRE(0x1FULL == callbacks_ran_flags.to_ullong());
REQUIRE(MAX_CALLBACKS == callbacks_done);
REQUIRE(current_time_2 == current_time + MAX_SLICE_LENGTH * 4);
}
TEST_CASE("Core::Timing[PredictableLateness]", "[core]") {
@@ -180,13 +137,13 @@ TEST_CASE("Core::Timing[PredictableLateness]", "[core]") {
Core::Timing::EventType* cb_b = core_timing.RegisterEvent("callbackB", CallbackTemplate<1>);
// Enter slice 0
core_timing.Advance();
core_timing.ResetRun();
core_timing.ScheduleEvent(100, cb_a, CB_IDS[0]);
core_timing.ScheduleEvent(200, cb_b, CB_IDS[1]);
AdvanceAndCheck(core_timing, 0, 90, 10, -10); // (100 - 10)
AdvanceAndCheck(core_timing, 1, MAX_SLICE_LENGTH, 50, -50);
AdvanceAndCheck(core_timing, 0, 0, 10, -10); // (100 - 10)
AdvanceAndCheck(core_timing, 1, 1, 50, -50);
}
namespace ChainSchedulingTest {
@@ -220,7 +177,7 @@ TEST_CASE("CoreTiming[ChainScheduling]", "[core]") {
});
// Enter slice 0
core_timing.Advance();
core_timing.ResetRun();
core_timing.ScheduleEvent(800, cb_a, CB_IDS[0]);
core_timing.ScheduleEvent(1000, cb_b, CB_IDS[1]);
@@ -229,19 +186,19 @@ TEST_CASE("CoreTiming[ChainScheduling]", "[core]") {
REQUIRE(800 == core_timing.GetDowncount());
reschedules = 3;
AdvanceAndCheck(core_timing, 0, 200); // cb_a
AdvanceAndCheck(core_timing, 1, 1000); // cb_b, cb_rs
AdvanceAndCheck(core_timing, 0, 0); // cb_a
AdvanceAndCheck(core_timing, 1, 1); // cb_b, cb_rs
REQUIRE(2 == reschedules);
core_timing.AddTicks(core_timing.GetDowncount());
core_timing.Advance(); // cb_rs
core_timing.SwitchContext(3);
REQUIRE(1 == reschedules);
REQUIRE(200 == core_timing.GetDowncount());
AdvanceAndCheck(core_timing, 2, 800); // cb_c
AdvanceAndCheck(core_timing, 2, 3); // cb_c
core_timing.AddTicks(core_timing.GetDowncount());
core_timing.Advance(); // cb_rs
REQUIRE(0 == reschedules);
REQUIRE(MAX_SLICE_LENGTH == core_timing.GetDowncount());
}

View File

@@ -249,6 +249,11 @@ void Maxwell3D::InitDirtySettings() {
dirty_pointers[MAXWELL3D_REG_INDEX(polygon_offset_units)] = polygon_offset_dirty_reg;
dirty_pointers[MAXWELL3D_REG_INDEX(polygon_offset_factor)] = polygon_offset_dirty_reg;
dirty_pointers[MAXWELL3D_REG_INDEX(polygon_offset_clamp)] = polygon_offset_dirty_reg;
// Depth bounds
constexpr u32 depth_bounds_values_dirty_reg = DIRTY_REGS_POS(depth_bounds_values);
dirty_pointers[MAXWELL3D_REG_INDEX(depth_bounds[0])] = depth_bounds_values_dirty_reg;
dirty_pointers[MAXWELL3D_REG_INDEX(depth_bounds[1])] = depth_bounds_values_dirty_reg;
}
void Maxwell3D::CallMacroMethod(u32 method, std::size_t num_parameters, const u32* parameters) {

View File

@@ -687,7 +687,9 @@ public:
u32 rt_separate_frag_data;
INSERT_PADDING_WORDS(0xC);
f32 depth_bounds[2];
INSERT_PADDING_WORDS(0xA);
struct {
u32 address_high;
@@ -1201,6 +1203,7 @@ public:
bool transform_feedback;
bool color_mask;
bool polygon_offset;
bool depth_bounds_values;
// Complementary
bool viewport_transform;
@@ -1400,6 +1403,7 @@ ASSERT_REG_POSITION(stencil_back_mask, 0x3D6);
ASSERT_REG_POSITION(stencil_back_func_mask, 0x3D7);
ASSERT_REG_POSITION(color_mask_common, 0x3E4);
ASSERT_REG_POSITION(rt_separate_frag_data, 0x3EB);
ASSERT_REG_POSITION(depth_bounds, 0x3EC);
ASSERT_REG_POSITION(zeta, 0x3F8);
ASSERT_REG_POSITION(clear_flags, 0x43E);
ASSERT_REG_POSITION(vertex_attrib_format, 0x458);

View File

@@ -1340,7 +1340,9 @@ void RasterizerOpenGL::SyncPolygonOffset() {
state.polygon_offset.fill_enable = regs.polygon_offset_fill_enable != 0;
state.polygon_offset.line_enable = regs.polygon_offset_line_enable != 0;
state.polygon_offset.point_enable = regs.polygon_offset_point_enable != 0;
state.polygon_offset.units = regs.polygon_offset_units;
// Hardware divides polygon offset units by two
state.polygon_offset.units = regs.polygon_offset_units / 2.0f;
state.polygon_offset.factor = regs.polygon_offset_factor;
state.polygon_offset.clamp = regs.polygon_offset_clamp;

View File

@@ -112,14 +112,15 @@ std::optional<std::pair<std::vector<ShaderDiskCacheRaw>, std::vector<ShaderDiskC
ShaderDiskCacheOpenGL::LoadTransferable() {
// Skip games without title id
const bool has_title_id = system.CurrentProcess()->GetTitleID() != 0;
if (!Settings::values.use_disk_shader_cache || !has_title_id)
if (!Settings::values.use_disk_shader_cache || !has_title_id) {
return {};
tried_to_load = true;
}
FileUtil::IOFile file(GetTransferablePath(), "rb");
if (!file.IsOpen()) {
LOG_INFO(Render_OpenGL, "No transferable shader cache found for game with title id={}",
GetTitleID());
is_usable = true;
return {};
}
@@ -135,6 +136,7 @@ ShaderDiskCacheOpenGL::LoadTransferable() {
LOG_INFO(Render_OpenGL, "Transferable shader cache is old - removing");
file.Close();
InvalidateTransferable();
is_usable = true;
return {};
}
if (version > NativeVersion) {
@@ -180,13 +182,15 @@ ShaderDiskCacheOpenGL::LoadTransferable() {
}
}
return {{raws, usages}};
is_usable = true;
return {{std::move(raws), std::move(usages)}};
}
std::pair<std::unordered_map<u64, ShaderDiskCacheDecompiled>, ShaderDumpsMap>
ShaderDiskCacheOpenGL::LoadPrecompiled() {
if (!IsUsable())
if (!is_usable) {
return {};
}
FileUtil::IOFile file(GetPrecompiledPath(), "rb");
if (!file.IsOpen()) {
@@ -479,8 +483,9 @@ void ShaderDiskCacheOpenGL::InvalidatePrecompiled() {
}
void ShaderDiskCacheOpenGL::SaveRaw(const ShaderDiskCacheRaw& entry) {
if (!IsUsable())
if (!is_usable) {
return;
}
const u64 id = entry.GetUniqueIdentifier();
if (transferable.find(id) != transferable.end()) {
@@ -501,8 +506,9 @@ void ShaderDiskCacheOpenGL::SaveRaw(const ShaderDiskCacheRaw& entry) {
}
void ShaderDiskCacheOpenGL::SaveUsage(const ShaderDiskCacheUsage& usage) {
if (!IsUsable())
if (!is_usable) {
return;
}
const auto it = transferable.find(usage.unique_identifier);
ASSERT_MSG(it != transferable.end(), "Saving shader usage without storing raw previously");
@@ -528,8 +534,9 @@ void ShaderDiskCacheOpenGL::SaveUsage(const ShaderDiskCacheUsage& usage) {
void ShaderDiskCacheOpenGL::SaveDecompiled(u64 unique_identifier, const std::string& code,
const GLShader::ShaderEntries& entries) {
if (!IsUsable())
if (!is_usable) {
return;
}
if (precompiled_cache_virtual_file.GetSize() == 0) {
SavePrecompiledHeaderToVirtualPrecompiledCache();
@@ -543,8 +550,9 @@ void ShaderDiskCacheOpenGL::SaveDecompiled(u64 unique_identifier, const std::str
}
void ShaderDiskCacheOpenGL::SaveDump(const ShaderDiskCacheUsage& usage, GLuint program) {
if (!IsUsable())
if (!is_usable) {
return;
}
GLint binary_length{};
glGetProgramiv(program, GL_PROGRAM_BINARY_LENGTH, &binary_length);
@@ -565,10 +573,6 @@ void ShaderDiskCacheOpenGL::SaveDump(const ShaderDiskCacheUsage& usage, GLuint p
}
}
bool ShaderDiskCacheOpenGL::IsUsable() const {
return tried_to_load && Settings::values.use_disk_shader_cache;
}
FileUtil::IOFile ShaderDiskCacheOpenGL::AppendTransferableFile() const {
if (!EnsureDirectories())
return {};

View File

@@ -224,9 +224,6 @@ private:
bool SaveDecompiledFile(u64 unique_identifier, const std::string& code,
const GLShader::ShaderEntries& entries);
/// Returns if the cache can be used
bool IsUsable() const;
/// Opens current game's transferable file and write it's header if it doesn't exist
FileUtil::IOFile AppendTransferableFile() const;
@@ -297,7 +294,7 @@ private:
std::unordered_map<u64, std::unordered_set<ShaderDiskCacheUsage>> transferable;
// The cache has been loaded at boot
bool tried_to_load{};
bool is_usable{};
};
} // namespace OpenGL

View File

@@ -4,6 +4,7 @@
#include "common/assert.h"
#include "common/common_types.h"
#include "common/logging/log.h"
#include "video_core/engines/shader_bytecode.h"
#include "video_core/shader/node_helper.h"
#include "video_core/shader/shader_ir.h"
@@ -18,7 +19,7 @@ u32 ShaderIR::DecodeHalfSetPredicate(NodeBlock& bb, u32 pc) {
const Instruction instr = {program_code[pc]};
const auto opcode = OpCode::Decode(instr);
DEBUG_ASSERT(instr.hsetp2.ftz == 0);
LOG_DEBUG(HW_GPU, "ftz={}", static_cast<u32>(instr.hsetp2.ftz));
Node op_a = UnpackHalfFloat(GetRegister(instr.gpr8), instr.hsetp2.type_a);
op_a = GetOperandAbsNegHalf(op_a, instr.hsetp2.abs_a, instr.hsetp2.negate_a);
@@ -32,6 +33,8 @@ u32 ShaderIR::DecodeHalfSetPredicate(NodeBlock& bb, u32 pc) {
h_and = instr.hsetp2.cbuf_and_imm.h_and;
op_b = GetOperandAbsNegHalf(GetConstBuffer(instr.cbuf34.index, instr.cbuf34.GetOffset()),
instr.hsetp2.cbuf.abs_b, instr.hsetp2.cbuf.negate_b);
// F32 is hardcoded in hardware
op_b = UnpackHalfFloat(std::move(op_b), Tegra::Shader::HalfType::F32);
break;
case OpCode::Id::HSETP2_IMM:
cond = instr.hsetp2.cbuf_and_imm.cond;

View File

@@ -62,10 +62,10 @@ public:
}
}
/***
* `Guard` guarantees that rendertargets don't unregister themselves if the
/**
* Guarantees that rendertargets don't unregister themselves if the
* collide. Protection is currently only done on 3D slices.
***/
*/
void GuardRenderTargets(bool new_guard) {
guard_render_targets = new_guard;
}
@@ -287,7 +287,7 @@ protected:
const Tegra::Engines::Fermi2D::Config& copy_config) = 0;
// Depending on the backend, a buffer copy can be slow as it means deoptimizing the texture
// and reading it from a sepparate buffer.
// and reading it from a separate buffer.
virtual void BufferCopy(TSurface& src_surface, TSurface& dst_surface) = 0;
void ManageRenderTargetUnregister(TSurface& surface) {
@@ -386,12 +386,13 @@ private:
};
/**
* `PickStrategy` takes care of selecting a proper strategy to deal with a texture recycle.
* @param overlaps, the overlapping surfaces registered in the cache.
* @param params, the paremeters on the new surface.
* @param gpu_addr, the starting address of the new surface.
* @param untopological, tells the recycler that the texture has no way to match the overlaps
* due to topological reasons.
* Takes care of selecting a proper strategy to deal with a texture recycle.
*
* @param overlaps The overlapping surfaces registered in the cache.
* @param params The parameters on the new surface.
* @param gpu_addr The starting address of the new surface.
* @param untopological Indicates to the recycler that the texture has no way
* to match the overlaps due to topological reasons.
**/
RecycleStrategy PickStrategy(std::vector<TSurface>& overlaps, const SurfaceParams& params,
const GPUVAddr gpu_addr, const MatchTopologyResult untopological) {
@@ -419,16 +420,19 @@ private:
}
/**
* `RecycleSurface` es a method we use to decide what to do with textures we can't resolve in
*the cache It has 2 implemented strategies: Ignore and Flush. Ignore just unregisters all the
*overlaps and loads the new texture. Flush, flushes all the overlaps into memory and loads the
*new surface from that data.
* @param overlaps, the overlapping surfaces registered in the cache.
* @param params, the paremeters on the new surface.
* @param gpu_addr, the starting address of the new surface.
* @param preserve_contents, tells if the new surface should be loaded from meory or left blank
* @param untopological, tells the recycler that the texture has no way to match the overlaps
* due to topological reasons.
* Used to decide what to do with textures we can't resolve in the cache It has 2 implemented
* strategies: Ignore and Flush.
*
* - Ignore: Just unregisters all the overlaps and loads the new texture.
* - Flush: Flushes all the overlaps into memory and loads the new surface from that data.
*
* @param overlaps The overlapping surfaces registered in the cache.
* @param params The parameters for the new surface.
* @param gpu_addr The starting address of the new surface.
* @param preserve_contents Indicates that the new surface should be loaded from memory or left
* blank.
* @param untopological Indicates to the recycler that the texture has no way to match the
* overlaps due to topological reasons.
**/
std::pair<TSurface, TView> RecycleSurface(std::vector<TSurface>& overlaps,
const SurfaceParams& params, const GPUVAddr gpu_addr,
@@ -465,10 +469,12 @@ private:
}
/**
* `RebuildSurface` this method takes a single surface and recreates into another that
* may differ in format, target or width alingment.
* @param current_surface, the registered surface in the cache which we want to convert.
* @param params, the new surface params which we'll use to recreate the surface.
* Takes a single surface and recreates into another that may differ in
* format, target or width alignment.
*
* @param current_surface The registered surface in the cache which we want to convert.
* @param params The new surface params which we'll use to recreate the surface.
* @param is_render Whether or not the surface is a render target.
**/
std::pair<TSurface, TView> RebuildSurface(TSurface current_surface, const SurfaceParams& params,
bool is_render) {
@@ -502,12 +508,14 @@ private:
}
/**
* `ManageStructuralMatch` this method takes a single surface and checks with the new surface's
* params if it's an exact match, we return the main view of the registered surface. If it's
* formats don't match, we rebuild the surface. We call this last method a `Mirage`. If formats
* Takes a single surface and checks with the new surface's params if it's an exact
* match, we return the main view of the registered surface. If its formats don't
* match, we rebuild the surface. We call this last method a `Mirage`. If formats
* match but the targets don't, we create an overview View of the registered surface.
* @param current_surface, the registered surface in the cache which we want to convert.
* @param params, the new surface params which we want to check.
*
* @param current_surface The registered surface in the cache which we want to convert.
* @param params The new surface params which we want to check.
* @param is_render Whether or not the surface is a render target.
**/
std::pair<TSurface, TView> ManageStructuralMatch(TSurface current_surface,
const SurfaceParams& params, bool is_render) {
@@ -529,13 +537,14 @@ private:
}
/**
* `TryReconstructSurface` unlike `RebuildSurface` where we know the registered surface
* matches the candidate in some way, we got no guarantess here. We try to see if the overlaps
* are sublayers/mipmaps of the new surface, if they all match we end up recreating a surface
* for them, else we return nothing.
* @param overlaps, the overlapping surfaces registered in the cache.
* @param params, the paremeters on the new surface.
* @param gpu_addr, the starting address of the new surface.
* Unlike RebuildSurface where we know whether or not registered surfaces match the candidate
* in some way, we have no guarantees here. We try to see if the overlaps are sublayers/mipmaps
* of the new surface, if they all match we end up recreating a surface for them,
* else we return nothing.
*
* @param overlaps The overlapping surfaces registered in the cache.
* @param params The parameters on the new surface.
* @param gpu_addr The starting address of the new surface.
**/
std::optional<std::pair<TSurface, TView>> TryReconstructSurface(std::vector<TSurface>& overlaps,
const SurfaceParams& params,
@@ -584,19 +593,27 @@ private:
}
/**
* `GetSurface` gets the starting address and parameters of a candidate surface and tries
* to find a matching surface within the cache. This is done in 3 big steps. The first is to
* check the 1st Level Cache in order to find an exact match, if we fail, we move to step 2.
* Step 2 is checking if there are any overlaps at all, if none, we just load the texture from
* memory else we move to step 3. Step 3 consists on figuring the relationship between the
* candidate texture and the overlaps. We divide the scenarios depending if there's 1 or many
* overlaps. If there's many, we just try to reconstruct a new surface out of them based on the
* candidate's parameters, if we fail, we recycle. When there's only 1 overlap then we have to
* check if the candidate is a view (layer/mipmap) of the overlap or if the registered surface
* is a mipmap/layer of the candidate. In this last case we reconstruct a new surface.
* @param gpu_addr, the starting address of the candidate surface.
* @param params, the paremeters on the candidate surface.
* @param preserve_contents, tells if the new surface should be loaded from meory or left blank.
* Gets the starting address and parameters of a candidate surface and tries
* to find a matching surface within the cache. This is done in 3 big steps:
*
* 1. Check the 1st Level Cache in order to find an exact match, if we fail, we move to step 2.
*
* 2. Check if there are any overlaps at all, if there are none, we just load the texture from
* memory else we move to step 3.
*
* 3. Consists of figuring out the relationship between the candidate texture and the
* overlaps. We divide the scenarios depending if there's 1 or many overlaps. If
* there's many, we just try to reconstruct a new surface out of them based on the
* candidate's parameters, if we fail, we recycle. When there's only 1 overlap then we
* have to check if the candidate is a view (layer/mipmap) of the overlap or if the
* registered surface is a mipmap/layer of the candidate. In this last case we reconstruct
* a new surface.
*
* @param gpu_addr The starting address of the candidate surface.
* @param params The parameters on the candidate surface.
* @param preserve_contents Indicates that the new surface should be loaded from memory or
* left blank.
* @param is_render Whether or not the surface is a render target.
**/
std::pair<TSurface, TView> GetSurface(const GPUVAddr gpu_addr, const SurfaceParams& params,
bool preserve_contents, bool is_render) {
@@ -651,7 +668,7 @@ private:
// Step 3
// Now we need to figure the relationship between the texture and its overlaps
// we do a topological test to ensure we can find some relationship. If it fails
// inmediatly recycle the texture
// immediately recycle the texture
for (const auto& surface : overlaps) {
const auto topological_result = surface->MatchesTopology(params);
if (topological_result != MatchTopologyResult::FullMatch) {
@@ -720,12 +737,13 @@ private:
}
/**
* `DeduceSurface` gets the starting address and parameters of a candidate surface and tries
* to find a matching surface within the cache that's similar to it. If there are many textures
* Gets the starting address and parameters of a candidate surface and tries to find a
* matching surface within the cache that's similar to it. If there are many textures
* or the texture found if entirely incompatible, it will fail. If no texture is found, the
* blit will be unsuccessful.
* @param gpu_addr, the starting address of the candidate surface.
* @param params, the paremeters on the candidate surface.
*
* @param gpu_addr The starting address of the candidate surface.
* @param params The parameters on the candidate surface.
**/
Deduction DeduceSurface(const GPUVAddr gpu_addr, const SurfaceParams& params) {
const auto host_ptr{system.GPU().MemoryManager().GetPointer(gpu_addr)};
@@ -777,11 +795,14 @@ private:
}
/**
* `DeduceBestBlit` gets the a source and destination starting address and parameters,
* Gets the a source and destination starting address and parameters,
* and tries to deduce if they are supposed to be depth textures. If so, their
* parameters are modified and fixed into so.
* @param gpu_addr, the starting address of the candidate surface.
* @param params, the parameters on the candidate surface.
*
* @param src_params The parameters of the candidate surface.
* @param dst_params The parameters of the destination surface.
* @param src_gpu_addr The starting address of the candidate surface.
* @param dst_gpu_addr The starting address of the destination surface.
**/
void DeduceBestBlit(SurfaceParams& src_params, SurfaceParams& dst_params,
const GPUVAddr src_gpu_addr, const GPUVAddr dst_gpu_addr) {

View File

@@ -716,6 +716,8 @@ void Config::ReadUIValues() {
UISettings::values.callout_flags = ReadSetting(QStringLiteral("calloutFlags"), 0).toUInt();
UISettings::values.show_console = ReadSetting(QStringLiteral("showConsole"), false).toBool();
UISettings::values.profile_index = ReadSetting(QStringLiteral("profileIndex"), 0).toUInt();
UISettings::values.pause_when_in_background =
ReadSetting(QStringLiteral("pauseWhenInBackground"), false).toBool();
ApplyDefaultProfileIfInputInvalid();
@@ -1124,6 +1126,8 @@ void Config::SaveUIValues() {
WriteSetting(QStringLiteral("calloutFlags"), UISettings::values.callout_flags, 0);
WriteSetting(QStringLiteral("showConsole"), UISettings::values.show_console, false);
WriteSetting(QStringLiteral("profileIndex"), UISettings::values.profile_index, 0);
WriteSetting(QStringLiteral("pauseWhenInBackground"),
UISettings::values.pause_when_in_background, false);
qt_config->endGroup();
}

View File

@@ -31,6 +31,7 @@ void ConfigureGeneral::SetConfiguration() {
ui->toggle_check_exit->setChecked(UISettings::values.confirm_before_closing);
ui->toggle_user_on_boot->setChecked(UISettings::values.select_user_on_boot);
ui->theme_combobox->setCurrentIndex(ui->theme_combobox->findData(UISettings::values.theme));
ui->toggle_background_pause->setChecked(UISettings::values.pause_when_in_background);
ui->toggle_frame_limit->setChecked(Settings::values.use_frame_limit);
ui->frame_limit->setEnabled(ui->toggle_frame_limit->isChecked());
@@ -42,6 +43,7 @@ void ConfigureGeneral::ApplyConfiguration() {
UISettings::values.select_user_on_boot = ui->toggle_user_on_boot->isChecked();
UISettings::values.theme =
ui->theme_combobox->itemData(ui->theme_combobox->currentIndex()).toString();
UISettings::values.pause_when_in_background = ui->toggle_background_pause->isChecked();
Settings::values.use_frame_limit = ui->toggle_frame_limit->isChecked();
Settings::values.frame_limit = ui->frame_limit->value();

View File

@@ -65,6 +65,13 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="toggle_background_pause">
<property name="text">
<string>Pause emulation when in background</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>

View File

@@ -245,10 +245,24 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
button->setContextMenuPolicy(Qt::CustomContextMenu);
connect(button, &QPushButton::clicked, [=] {
HandleClick(
button_map[button_id],
[=](const Common::ParamPackage& params) { buttons_param[button_id] = params; },
InputCommon::Polling::DeviceType::Button);
HandleClick(button_map[button_id],
[=](Common::ParamPackage params) {
// Workaround for ZL & ZR for analog triggers like on XBOX controllors.
// Analog triggers (from controllers like the XBOX controller) would not
// work due to a different range of their signals (from 0 to 255 on
// analog triggers instead of -32768 to 32768 on analog joysticks). The
// SDL driver misinterprets analog triggers as analog joysticks.
// TODO: reinterpret the signal range for analog triggers to map the
// values correctly. This is required for the correct emulation of the
// analog triggers of the GameCube controller.
if (button_id == Settings::NativeButton::ZL ||
button_id == Settings::NativeButton::ZR) {
params.Set("direction", "+");
params.Set("threshold", "0.5");
}
buttons_param[button_id] = std::move(params);
},
InputCommon::Polling::DeviceType::Button);
});
connect(button, &QPushButton::customContextMenuRequested, [=](const QPoint& menu_location) {
QMenu context_menu;

View File

@@ -675,6 +675,24 @@ void GMainWindow::RestoreUIState() {
Debugger::ToggleConsole();
}
void GMainWindow::OnAppFocusStateChanged(Qt::ApplicationState state) {
if (!UISettings::values.pause_when_in_background) {
return;
}
if (state != Qt::ApplicationHidden && state != Qt::ApplicationInactive &&
state != Qt::ApplicationActive) {
LOG_DEBUG(Frontend, "ApplicationState unusual flag: {} ", state);
}
if (ui.action_Pause->isEnabled() &&
(state & (Qt::ApplicationHidden | Qt::ApplicationInactive))) {
auto_paused = true;
OnPauseGame();
} else if (ui.action_Start->isEnabled() && auto_paused && state == Qt::ApplicationActive) {
auto_paused = false;
OnStartGame();
}
}
void GMainWindow::ConnectWidgetEvents() {
connect(game_list, &GameList::GameChosen, this, &GMainWindow::OnGameListLoadFile);
connect(game_list, &GameList::OpenDirectory, this, &GMainWindow::OnGameListOpenDirectory);
@@ -2320,6 +2338,9 @@ int main(int argc, char* argv[]) {
// After settings have been loaded by GMainWindow, apply the filter
main_window.show();
QObject::connect(&app, &QGuiApplication::applicationStateChanged, &main_window,
&GMainWindow::OnAppFocusStateChanged);
Settings::LogSettings();
int result = app.exec();

Some files were not shown because too many files have changed in this diff Show More