Compare commits

..

132 Commits

Author SHA1 Message Date
Morph
248a146ab7 CMakeLists: Disable all warnings for external headers
This lets us avoid needing to wrap external headers with #pragma warning directives for warnings we treat as errors and avoids generating warnings for external code.

Thanks to MerryMage for pointing this out.
2021-06-28 14:24:28 -04:00
Morph
22d7b89c15 video_core: Remove #pragma warning directives for external headers 2021-06-28 14:21:40 -04:00
Morph
954259312e input_common: Remove #pragma warning directives for external headers 2021-06-28 14:20:25 -04:00
Morph
0eae00e263 CMakeLists: Enforce C4018, C4267, C4305, C4389 2021-06-28 14:20:25 -04:00
Morph
e828c5a559 core: Enforce C4242 2021-06-28 14:20:25 -04:00
Morph
58550cfcdc input_common: Enforce C4242 2021-06-28 14:20:25 -04:00
Morph
a47704f4dd video_core: Enforce C4242 2021-06-28 14:20:25 -04:00
Morph
d3d6613d33 video_core: Silence signed/unsigned mismatch warnings 2021-06-28 09:21:42 -04:00
Morph
c5e25cffb9 Merge pull request #6535 from ameerj/insert-fancy-name
main: Display the instruction set of the running title in the window name
2021-06-28 04:25:03 -04:00
ameerj
4cee25281f main: Display the instruction set of the running title in the window name
Displays whether the currently running title uses 64-bit instructions or only 32-bit instructions.
2021-06-28 00:37:24 -04:00
Morph
4df04ad48a Merge pull request #6529 from ReinUsesLisp/reaper-fixups
buffer_cache,texture_cache: Misc fixups from the memory reaper
2021-06-27 09:33:58 -04:00
Morph
3bc7b0a587 Merge pull request #6532 from MerryMage/libusb-apple
libusb: Apple is a POSIX system
2021-06-27 00:30:47 -04:00
MerryMage
f54f29198f libusb: Apple is a POSIX system 2021-06-26 20:24:18 +01:00
bunnei
432fab7c4f Merge pull request #6526 from bunnei/doom-update
services: Misc. minor changes for latest SDK update.
2021-06-26 01:21:55 -07:00
bunnei
36d581ec73 hle: service: hwopus: OpenHardwareOpusDecoderEx: Remove unused buffer size. 2021-06-26 00:38:08 -07:00
ReinUsesLisp
9476309d53 buffer_cache: Only flush downloaded size
Fixes a regression unintentionally introduced by the garbage collector.
This makes regular memory downloads only flush the requested sizes.

This negatively affected Koei Tecmo games.
2021-06-26 03:29:34 -03:00
ReinUsesLisp
03abe8bf85 video_core: Enforce C4244
Enforce implicit integer casts to a smaller type as errors.
2021-06-26 03:29:34 -03:00
ReinUsesLisp
05bd50a1cf codec,vic: Disable warnings in ffmpeg headers 2021-06-26 03:29:31 -03:00
ReinUsesLisp
3ab5bf6454 vk_buffer_cache: Silence implicit cast warnings 2021-06-26 02:17:36 -03:00
ReinUsesLisp
b4894faeae buffer_cache/texture_cache: Make GC functions private 2021-06-26 02:17:36 -03:00
ReinUsesLisp
e79d02bf38 buffer_cache: Silence implicit cast warning 2021-06-26 02:17:36 -03:00
Ameer J
d9fb6dbd37 Merge pull request #6528 from ReinUsesLisp/device-memory
vulkan_device: Make device memory match the rest of the file
2021-06-25 17:07:24 -04:00
ReinUsesLisp
99b859db55 vulkan_device: Make device memory match the rest of the file
Match the style in the file.
2021-06-25 02:38:58 -03:00
bunnei
c805c0b395 Merge pull request #6496 from ameerj/astc-fixes
astc: Various robustness enhancements for the gpu decoder
2021-06-24 21:47:05 -07:00
bunnei
b9c2732121 Merge pull request #6519 from Wunkolo/mem-size-literal
common: Replace common_sizes into user-literals
2021-06-24 19:09:12 -07:00
bunnei
982be246ab hle: hle_helpers: Skip data payload offset checks on TIPC requests.
- TIPC does not use this.
2021-06-24 18:39:43 -07:00
bunnei
3565e32f4d hle: service: hwopus: Implement GetWorkBufferSizeEx and OpenHardwareOpusDecoderEx.
- This is used by the latest update of Doom Eternal.
2021-06-24 18:25:37 -07:00
bunnei
d1ba4a2db2 hle: service: aoc: Stub GetAddOnContentListChangedEventWithProcessId.
- This is used by the latest update of Doom Eternal.
2021-06-24 18:22:53 -07:00
bunnei
50d0cc2716 audio_core: common: Bump audio revision to 9.
- This is used in fw 12.x.x games.
2021-06-24 18:22:10 -07:00
Wunkolo
4569f39c7c common: Replace common_sizes into user-literals
Removes common_sizes.h in favor of having `_KiB`, `_MiB`, `_GiB`, etc
user-literals within literals.h.

To keep the global namespace clean, users will have to use:

```
using namespace Common::Literals;
```

to access these literals.
2021-06-24 09:27:40 -07:00
bunnei
4dc2f5a341 Merge pull request #6522 from Morph1984/pragma
general: Add missing #pragma once directives
2021-06-24 08:53:27 -07:00
Morph
eed0d1f33b general: Add missing #pragma once directives 2021-06-24 07:20:57 -04:00
Chloe
f216a9432b Add missing includes (#6521)
* Add missing includes

* Add array
2021-06-24 03:24:17 -04:00
Schplee
5ed87152c3 Fix bold tag 2021-06-23 23:37:03 -07:00
Schplee
373bc6512d Fix typo in Readme 2021-06-23 23:35:46 -07:00
Schplee
496327490f Update Readme 2021-06-23 23:32:41 -07:00
bunnei
1b09d6628b Merge pull request #6517 from lioncash/fmtlib
externals: Update fmt to 8.0.0
2021-06-23 15:31:04 -07:00
bunnei
809e5fd523 Merge pull request #6504 from Kelebek1/samples-played
[audout] Implement GetAudioOutPlayedSampleCount
2021-06-23 11:31:12 -07:00
Lioncash
d0b1f2bd05 General: Resolve fmt specifiers to adhere to 8.0.0 API where applicable
Also removes some deprecated API usages.
2021-06-23 13:48:21 -04:00
bunnei
d8d9bb0dfb Merge pull request #6518 from lioncash/func
maxwell3d: Add missing return in default SizeInBytes() case
2021-06-23 09:43:00 -07:00
Lioncash
be6844c1ed maxwell3d: Add missing return in default SizeInBytes() case
We were returning '1' in ComponentCount()'s default case but were
neglecting to do the same with SizeInBytes().
2021-06-23 11:50:40 -04:00
Lioncash
c3fe071723 externals: Update dynarmic to allow fmt compilation to succeed 2021-06-23 09:31:59 -04:00
Mai M
17fff10e06 Merge pull request #6465 from FernandoS27/sex-on-the-beach
GPU: Implement a garbage collector for GPU Caches (project Reaper+)
2021-06-23 08:03:01 -04:00
Lioncash
8593e6f1e6 externals: Update fmt to 8.0.0
Keeps us up to date with the latest major release.

Also allows compilers that support it to perform compile-time format
string checking.
2021-06-23 02:43:36 -04:00
Mai M
20f474b09a Merge pull request #6508 from ReinUsesLisp/bootmanager-stop-token
bootmanager: Use std::stop_source for stopping emulation
2021-06-23 02:35:42 -04:00
Morph
c1a9fa9db7 Merge pull request #6514 from OZtistic/master
Simple resizing of Per-Game configuration window and removal of useless Help question mark button in the title bar
2021-06-22 23:19:13 -04:00
Mai M
d6b51e5e21 Merge pull request #6512 from ReinUsesLisp/wait-detached-stasks
common/detached_tasks: Wait for tasks before shutting down
2021-06-22 22:20:14 -04:00
Mai M
95b4c78b07 Merge pull request #6509 from ReinUsesLisp/mouse-datarace
input_common/mouse_input: Fix data race
2021-06-22 22:19:34 -04:00
Mai M
4ec7d79174 Merge pull request #6510 from ReinUsesLisp/npad-data-race
npad: Fix data race when updating devices
2021-06-22 22:17:57 -04:00
OZtistic
36aacf62ad Simple resizing of the Per-Game configuration window and removal of useless Help question mark button in the title bar 2021-06-23 12:02:10 +10:00
bunnei
0308a2679e Merge pull request #6493 from Morph1984/fs-nodiscard
common: fs: Miscellaneous changes
2021-06-22 17:21:59 -07:00
bunnei
255f8d22d7 Merge pull request #6472 from Morph1984/spl
service: spl: Implement general SPL service
2021-06-22 15:43:10 -07:00
bunnei
791d3d1bea Merge pull request #6483 from Morph1984/get-tz-file
service: time: Use GetFileRelative to get files within subdirectories
2021-06-22 14:25:41 -07:00
Fernando Sahmkow
f9b940a442 Reaper: Set minimum cleaning limit on OGL. 2021-06-22 22:07:17 +02:00
Morph
2fa207058b common: fs: Add a description of a regular file in IsFile
This provides a more concrete example of what a regular file is and isn't.
2021-06-22 15:07:51 -04:00
Morph
0394893354 vfs_real: Fix Mode to FileAccessMode conversion
These enforce requiring the file to exist prior to opening.
2021-06-22 15:07:51 -04:00
Morph
76b2313b25 common: fs: Amend IsFile check in FileOpen / (Write/Append)StringToFile
This check was preventing files with the Write or Append file access modes from being created, as per the documented behavior in FileAccessMode.
This amends the check to test for the existence of a filesystem object prior to checking whether it is a regular file.
Thanks to liushuyu for pointing out that removing the check altogether would not guard against attempting to open non-regular files such as directories, symlinks, FIFO (pipes), sockets, block devices, or character devices.
The documentation has also been updated for these functions to clarify that a file refers to a regular file.
2021-06-22 15:06:58 -04:00
Morph
cf0b9d1de2 common: fs: file: Remove [[nodiscard]] attribute from Flush
Similarly, Flush() is typically called to attempt to flush a file into the disk. In the one case where this is used, we do not care whether the flush has succeeded or not, making [[nodiscard]] unnecessary.
2021-06-22 13:36:24 -04:00
Morph
81b1b71993 common: fs: Remove [[nodiscard]] attribute on Remove* functions
There are a lot of scenarios where we don't particularly care whether or not the removal operation and just simply attempt a removal.

As such, removing the [[nodiscard]] attribute is best for these functions.
2021-06-22 13:36:24 -04:00
bunnei
faf57c183f Merge pull request #6506 from ReinUsesLisp/master-semaphore-jthread
vk_master_semaphore: Use jthread for debug thread
2021-06-22 08:44:25 -07:00
bunnei
0e2c1a5739 Merge pull request #6495 from lat9nq/mingw-vista-style
ci: windows: Copy the Qt styles directory when packaging
2021-06-22 08:39:28 -07:00
Mai M
698add8541 Merge pull request #6511 from ReinUsesLisp/core-is-powered-data-race
core: Make is_powered_on atomic
2021-06-22 04:28:38 -04:00
Rodrigo Locatti
c9c8537643 core: Make is_powered_on atomic
Fixes potential data races when shutting down.
2021-06-22 04:33:07 -03:00
Rodrigo Locatti
1ca9a13e50 common/detached_tasks: Wait for tasks before shutting down
If this is not waited on, the synchronization primitives are destroyed
whe main exits and the detached task ends up signalling garbage and not
properly finishing.
2021-06-22 04:27:44 -03:00
Rodrigo Locatti
15cc561d12 npad: Fix data race when updating devices
Add a lock to avoid data races.
This reduces the number of -fsanitize=thread errors significantly.
2021-06-22 03:16:21 -03:00
Rodrigo Locatti
0a39163a90 input_common/mouse_input: Fix data race
Fix data race using std::jthread and std::stop_token.
2021-06-22 02:31:39 -03:00
bunnei
2a7a65c944 Merge pull request #6481 from Morph1984/missing-peak-set
kernel: Fix missing peak set in KResourceLimit::SetLimitValue
2021-06-21 22:16:48 -07:00
Kelebek1
ba3af04da1 Implement audout GetAudioOutPlayedSampleCount
Used in Ninja Gaiden games.
2021-06-22 04:39:17 +01:00
ReinUsesLisp
4009ae1da2 bootmanager: Use std::stop_source for stopping emulation
Use its std::stop_token to abort shader cache loading.

Using std::stop_token instead of std::atomic_bool allows the usage of
other utilities like std::stop_callback.
2021-06-22 00:04:57 -03:00
ReinUsesLisp
cf116a28a6 vk_master_semaphore: Use jthread for debug thread 2021-06-21 19:56:07 -03:00
bunnei
0485b8e84b Merge pull request #6499 from FernandoS27/we-were-on-a-break
Update dynarmic and add new unsafe CPU option.
2021-06-21 14:56:08 -07:00
bunnei
2a3d3d3895 Merge pull request #6475 from ameerj/unlimit-fps
nvflinger: Add experimental toggle to disable buffer swap interval limits
2021-06-21 11:58:12 -07:00
Mai M
83ac715e76 Merge pull request #6486 from CaptV0rt3x/httplib
externals: httplib: replace custom httplib header with upstream as submodule
2021-06-21 11:56:33 -04:00
Fernando Sahmkow
2298508465 Update dynarmic and add new unsafe CPU option. 2021-06-20 20:40:02 +02:00
Fernando Sahmkow
569a1962c0 Reaper: Guarantee correct deletion. 2021-06-20 19:11:41 +02:00
Fernando Sahmkow
865dd615ca Reaper: Upgrade label from unsafe to experimental as no regressions are known now. 2021-06-20 12:35:19 +02:00
ameerj
851c76233d util_shaders: Specify ASTC decoder memory barrier bits 2021-06-19 11:16:25 -04:00
ameerj
ace20ba4a4 astc_decoder.comp: Remove unnecessary LUT SSBOs
We can move them to instead be compile time constants within the shader.
2021-06-19 10:56:13 -04:00
ameerj
31b125ef57 astc: Various robustness enhancements for the gpu decoder
These changes should help in reducing crashes/drivers panics that may
occur due to synchronization issues between the shader completion and
later access of the decoded texture.
2021-06-19 09:00:33 -04:00
lat9nq
ad8aab915b ci: windows: Copy the styles directory when packaging
Qt can make use of qwindowsvistastyle.dll if present, and our MinGW
container has the library, but it was not being copied during the
packaging process. Thus, yuzu looked like a Windows 98 application when
using the PR-verify artifacts.

This copies over the DLL during packaging, for that sweet-sweet Windows
Vista style.

In addition, set the Qt plugins path instead of the plugins/platforms
path. This way we can use the directory directly, rather than appending
a `..` everytime we need something just outside of it.
2021-06-19 05:24:56 -04:00
Morph
03da34b330 Merge pull request #6494 from lat9nq/mingw-fix-fastmem
host_memory: Correct MEM_RESERVE_PLACEHOLDER
2021-06-19 04:40:58 -04:00
lat9nq
9a06b85b24 host_memory: Correct MEM_RESERVE_PLACEHOLDER
Microsoft defines `MEM_RESERVE_PLACEHOLDER` as `0x00040000`, but our
manually imported version of it drops the last zero.
2021-06-19 04:38:33 -04:00
Vortex
e704da9192 externals: httplib: replace custom httplib header with upstream as submodule.
This also includes a minor change to web_service.cpp - to fix compatibility with upstream changes.
2021-06-19 02:18:58 +05:30
Mai M
3870ba670f Merge pull request #6484 from CaptV0rt3x/discord-rpc
update submodule discord-rpc to latest [now deprecated]
2021-06-18 15:18:15 -04:00
Vortex
8a83e3412a update submodule discord-rpc to latest [now deprecated] 2021-06-18 23:13:17 +05:30
Morph
fd5ef1970c service: time: Use GetFileRelative to get files within subdirectories
The timezone info file can be within subdirectories (such as Asia/Tokyo), use GetFileRelative instead of GetFile to get files within subdirectories.
2021-06-18 11:25:26 -04:00
Rodrigo Locatti
bb18a6533d Merge pull request #6478 from ameerj/vk-layer-settings
vulkan_debug_callback: Skip logging known false-positive validation errors
2021-06-18 10:10:49 -03:00
Morph
1a5eceeb9c kernel: Fix missing peak set in KResourceLimit::SetLimitValue 2021-06-18 07:27:48 -04:00
ameerj
0b172d12c0 vulkan_debug_callback: Skip logging known false-positive validation errors
Avoids overwhelming the log with validation errors that are not applicable
2021-06-17 22:16:32 -04:00
Fernando Sahmkow
719a6dd5a1 Reaper: Correct size calculation on Vulkan. 2021-06-17 08:48:41 +02:00
ameerj
36250a4730 config: Add frame limiter toggle hotkey 2021-06-17 01:41:57 -04:00
ameerj
3522fc019c nvflinger: Add toggle to disable buffer swap interval limits
Enabling this setting will allow some titles to present more frames to
the screen as they become available in the nvflinger buffer queue.
2021-06-17 01:41:56 -04:00
bunnei
abb0124b84 Merge pull request #6418 from clementgallet/sdl-audio-backend
Audio: SDL2 audio backend
2021-06-16 21:38:20 -07:00
Ameer J
c5b517aa5f Merge pull request #6469 from ReinUsesLisp/blit-view-compat
texture_cache/util: Avoid relaxed image views on different bytes per block
2021-06-16 21:08:07 -04:00
Fernando Sahmkow
ca6f47c686 Reaper: Change memory restrictions on TC depending on host memory on VK. 2021-06-17 00:29:48 +02:00
Fernando Sahmkow
0dd98842bf Reaper: Address Feedback. 2021-06-16 21:35:03 +02:00
Fernando Sahmkow
954ad2a61e Reaper: Setup settings and final tuning. 2021-06-16 21:35:03 +02:00
Fernando Sahmkow
d8ad6aa187 Reaper: Tune it up to be an smart GC. 2021-06-16 21:35:02 +02:00
ReinUsesLisp
a11bc4a382 Initial Reaper Setup
WIP
2021-06-16 21:35:02 +02:00
ReinUsesLisp
5b1efe522e vulkan_memory_allocator: Release allocations with no commits 2021-06-16 21:35:01 +02:00
bunnei
973bf306ed Merge pull request #6464 from ameerj/disable-astc
textures: Add a toggle for GPU Accelerated ASTC decoder
2021-06-16 11:29:10 -07:00
Morph
92942fe01b Merge pull request #6460 from Morph1984/fs-access-log-fix
fsp_srv: Fix filesystem access logging
2021-06-16 14:03:01 -04:00
Morph
4a4e304319 spl: Mark the other functions as unimplemented 2021-06-16 01:46:45 -04:00
Morph
8ba83c4c2a spl: Implement spl::GetConfig 2021-06-16 01:46:45 -04:00
Morph
e4318a1914 hle: api_version: Add HLE API version constants 2021-06-16 01:46:45 -04:00
Morph
ded36b8688 spl: Add the general SPL interface 2021-06-16 01:46:45 -04:00
Morph
faf11fe46d spl: Add SPL types 2021-06-16 01:46:45 -04:00
Morph
95f203b7c7 spl: Add SPL result codes 2021-06-16 01:07:58 -04:00
Morph
74790e4f33 common: fs: file: Remove redundant call to WriteStringToFile
The Append open mode will create a new file if said file does not exist at a given path, making this call redundant.
2021-06-16 00:06:02 -04:00
Morph
0f48292de1 fsp_srv: Fix filesystem access logging
This introduces a new setting Enable FS Access Log which saves the filesystem access log to sdmc:/FsAccessLog.txt

If this setting is not enabled, this will indicate to FS to not call OutputAccessLogToSdCard.

Fixes softlocks during loading in Xenoblade Chronicles 2 when certain DLC is enabled.
2021-06-16 00:06:02 -04:00
bunnei
78651b5476 Merge pull request #6462 from Morph1984/proper-flush
common: fs: file: Flush the file to the disk when Flush() is called
2021-06-15 19:03:19 -07:00
ameerj
5fc8393125 astc_decoder: Fix LDR CEM1 endpoint calculation
Per the spec, L1 is clamped to the value 0xff if it is greater than 0xff. An oversight caused us to take the maximum of L1 and 0xff, rather than the minimum.

Huge thanks to wwylele for finding this.

Co-Authored-By: Weiyi Wang <wwylele@gmail.com>
2021-06-15 20:19:01 -04:00
ameerj
f9bfeaa2bc yuzu_cmd/config: Add Accelerate ASTC and missing NVDEC emulation settings 2021-06-15 20:19:00 -04:00
ameerj
b2955479e5 configure_graphics: Add Accelerate ASTC decoding setting 2021-06-15 20:19:00 -04:00
ameerj
c4ff7ecf51 textures: Reintroduce CPU ASTC decoder
Users may want to fall back to the CPU ASTC texture decoder due to hangs
and crashes that may be caused by keeping the GPU under compute heavy
loads for extended periods of time. This is especially the case in games
such as Astral Chain which make extensive use of ASTC textures.
2021-06-15 20:19:00 -04:00
bunnei
f3caf53648 Merge pull request #6470 from ameerj/lm-silence
lm: Demote LM guest logs to LOG_DEBUG
2021-06-14 20:40:25 -07:00
ameerj
422a15ee75 lm: Demote guest logs to LOG_DEBUG
Guest logs are not very useful, as they are intended for use by the game developers during development. As such, they provide little meaning to be logged by yuzu and tend to overwhelm the log output at times.
2021-06-14 22:23:27 -04:00
ReinUsesLisp
3d89398b84 texture_cache/util: Avoid relaxed image views on different bytes per pixel
Avoids API usage errors on UE4 titles leading to crashes.
2021-06-14 21:03:57 -03:00
bunnei
c8f86edee6 Merge pull request #6456 from Morph1984/very-important-changes
configure_cpu_debug: Clarify settings behavior
2021-06-14 15:05:44 -07:00
Fernando Sahmkow
8d4dfc98ec Merge pull request #6448 from Morph1984/recursive-dir-iterator
common: fs: Use the normal directory iterator in *Recursively functions
2021-06-14 15:47:04 +02:00
Mai M
de12dbb01a Merge pull request #6463 from Morph1984/restructure-logging
common: logging: Restructure logging backend
2021-06-13 14:29:39 -04:00
Morph
a4454329c1 general: Remove extraneous includes 2021-06-13 11:32:43 -04:00
Morph
391e823c79 common: logging: Restructure backend code 2021-06-13 11:05:58 -04:00
Morph
8150c65c07 common: logging: backend: Wrap IOFile in a unique_ptr
Allows us to forward declare Common::FS::IOFile.
2021-06-13 11:05:58 -04:00
Morph
a98b6c8f07 common: fs: file: Flush the file to the disk when Flush() is called
std::fflush does not guarantee that file buffers are flushed to the disk.

Use _commit on Windows and fsync on all other OSes to ensure that the file is flushed to the disk.
2021-06-13 07:47:57 -04:00
Morph
56afd4ab4b Merge pull request #6452 from german77/sixaxis_firmware_stub
hid: Stub IsFirmwareUpdateAvailableForSixAxisSensor
2021-06-13 05:28:32 -04:00
Morph
c11b4c45e1 configure_cpu_debug: Clarify settings behavior
This makes it clear that the disabled settings only take effect when CPU Accuracy is set to Debug Mode.
2021-06-13 00:27:33 -04:00
Morph
c978f3144c common: fs: Use the normal directory iterator in *Recursively functions
MSVC's implementation of recursive_directory_iterator throws an exception on an error despite a std::error_code being passed into its constructor. This is most likely a bug in MSVC's implementation since directory_iterator does not throw an exception on an error.

We can replace the usage of recursive_directory_iterator for now until MSVC fixes their implementation of it.
2021-06-12 01:39:07 -04:00
german77
827483409b hid: Stub IsFirmwareUpdateAvailableForSixAxisSensor 2021-06-11 14:44:46 -05:00
Clément Gallet
f611506dca Various suggestions by v1993 and lioncash 2021-06-07 12:51:59 +02:00
Clément Gallet
df8a2e3ad8 Add sdl2 audio description in the yuzu-cmd config file 2021-06-06 11:29:02 +02:00
Clément Gallet
c7c99905f4 Add SDL2 audio backend 2021-06-06 11:28:38 +02:00
161 changed files with 3921 additions and 8105 deletions

View File

@@ -18,19 +18,20 @@ cd ..
mkdir package
if [ -d "/usr/x86_64-w64-mingw32/lib/qt5/plugins/platforms/" ]; then
QT_PLATFORM_DLL_PATH='/usr/x86_64-w64-mingw32/lib/qt5/plugins/platforms/'
QT_PLUGINS_PATH='/usr/x86_64-w64-mingw32/lib/qt5/plugins'
else
#fallback to qt
QT_PLATFORM_DLL_PATH='/usr/x86_64-w64-mingw32/lib/qt/plugins/platforms/'
QT_PLUGINS_PATH='/usr/x86_64-w64-mingw32/lib/qt/plugins'
fi
find build/ -name "yuzu*.exe" -exec cp {} 'package' \;
# copy Qt plugins
mkdir package/platforms
cp "${QT_PLATFORM_DLL_PATH}/qwindows.dll" package/platforms/
cp -rv "${QT_PLATFORM_DLL_PATH}/../mediaservice/" package/
cp -rv "${QT_PLATFORM_DLL_PATH}/../imageformats/" package/
cp -v "${QT_PLUGINS_PATH}/platforms/qwindows.dll" package/platforms/
cp -rv "${QT_PLUGINS_PATH}/mediaservice/" package/
cp -rv "${QT_PLUGINS_PATH}/imageformats/" package/
cp -rv "${QT_PLUGINS_PATH}/styles/" package/
rm -f package/mediaservice/*d.dll
for i in package/*.exe; do

5
.gitmodules vendored
View File

@@ -18,7 +18,7 @@
url = https://github.com/libusb/libusb.git
[submodule "discord-rpc"]
path = externals/discord-rpc
url = https://github.com/discordapp/discord-rpc.git
url = https://github.com/discord/discord-rpc.git
[submodule "Vulkan-Headers"]
path = externals/Vulkan-Headers
url = https://github.com/KhronosGroup/Vulkan-Headers.git
@@ -43,3 +43,6 @@
[submodule "SDL"]
path = externals/SDL
url = https://github.com/libsdl-org/SDL.git
[submodule "externals/cpp-httplib"]
path = externals/cpp-httplib
url = https://github.com/yhirose/cpp-httplib.git

View File

@@ -172,7 +172,7 @@ macro(yuzu_find_packages)
set(REQUIRED_LIBS
# Cmake Pkg Prefix Version Conan Pkg
"Catch2 2.13 catch2/2.13.0"
"fmt 7.1 fmt/7.1.2"
"fmt 8.0 fmt/8.0.0"
"lz4 1.8 lz4/1.9.2"
"nlohmann_json 3.8 nlohmann_json/3.8.0"
"ZLIB 1.2 zlib/1.2.11"

View File

@@ -1,43 +1,80 @@
yuzu emulator
=============
[![Travis CI Build Status](https://travis-ci.com/yuzu-emu/yuzu.svg?branch=master)](https://travis-ci.com/yuzu-emu/yuzu)
[![Azure Mainline CI Build Status](https://dev.azure.com/yuzu-emu/yuzu/_apis/build/status/yuzu%20mainline?branchName=master)](https://dev.azure.com/yuzu-emu/yuzu/)
[![Discord](https://img.shields.io/discord/398318088170242053?color=%237289DA&label=yuzu&logo=discord&logoColor=white)](https://discord.com/invite/u77vRWY)
<h1 align="center">
<br>
<a href="https://yuzu-emu.org/"><img src="https://raw.githubusercontent.com/yuzu-emu/yuzu-assets/master/icons/icon.png" alt="yuzu" width="200"></a>
<br>
<b>yuzu</b>
<br>
</h1>
yuzu is an experimental open-source emulator for the Nintendo Switch from the creators of [Citra](https://citra-emu.org/).
<h4 align="center"><b>yuzu</b> is the world's most popular, open-source, Nintendo Switch emulator — started by the creators of <a href="https://citra-emu.org" target="_blank">Citra</a>.
<br>
It is written in C++ with portability in mind, and we actively maintain builds for Windows and Linux.
</h4>
It is written in C++ with portability in mind, with builds actively maintained for Windows and Linux. The emulator is capable of running several commercial games.
<p align="center">
<a href="https://dev.azure.com/yuzu-emu/yuzu/">
<img src="https://dev.azure.com/yuzu-emu/yuzu/_apis/build/status/yuzu%20mainline?branchName=master"
alt="Azure Mainline CI Build Status">
</a>
<a href="https://discord.com/invite/u77vRWY">
<img src="https://img.shields.io/discord/398318088170242053?color=%237289DA&label=yuzu&logo=discord&logoColor=white"
alt="Discord">
</a>
</p>
yuzu only emulates a subset of Switch hardware and therefore most commercial games **do not** run at full speed or are not fully functional.
<p align="center">
<a href="#compatibility">Compatibility</a> |
<a href="#development">Development</a> |
<a href="#building">Building</a> |
<a href="#download">Download</a> |
<a href="#support">Support</a> |
<a href="#license">License</a>
</p>
Do you want to check which games are compatible and which ones are not? Please visit our [Compatibility page](https://yuzu-emu.org/game/)!
## Compatibility
yuzu is licensed under the GPLv2 (or any later version). Refer to the license.txt file included.
The emulator is capable of running most commercial games at full speed, provided you meet the [necessary hardware requirements](https://yuzu-emu.org/help/quickstart/#hardware-requirements).
Check out our [website](https://yuzu-emu.org/)!
For a full list of games yuzu support, please visit our [Compatibility page](https://yuzu-emu.org/game/)
For development discussion, please join us on [Discord](https://discord.com/invite/u77vRWY).
Check out our [website](https://yuzu-emu.org/) for the latest news on exciting features, monthly progress reports, and more!
### Development
## Development
Most of the development happens on GitHub. It's also where [our central repository](https://github.com/yuzu-emu/yuzu) is hosted.
Most of the development happens on GitHub. It's also where [our central repository](https://github.com/yuzu-emu/yuzu) is hosted. For development discussion, please join us on [Discord](https://discord.com/invite/u77vRWY).
If you want to contribute please take a look at the [Contributor's Guide](https://github.com/yuzu-emu/yuzu/wiki/Contributing) and [Developer Information](https://github.com/yuzu-emu/yuzu/wiki/Developer-Information). You should also contact any of the developers on Discord in order to know about the current state of the emulator.
If you want to contribute, please take a look at the [Contributor's Guide](https://github.com/yuzu-emu/yuzu/wiki/Contributing) and [Developer Information](https://github.com/yuzu-emu/yuzu/wiki/Developer-Information).
You can also contact any of the developers on Discord in order to know about the current state of the emulator.
If you want to contribute to the user interface translation, please check out the [yuzu project on transifex](https://www.transifex.com/yuzu-emulator/yuzu). We centralize translation work there, and periodically upstream translations.
If you want to contribute to the user interface translation project, please check out the [yuzu project on transifex](https://www.transifex.com/yuzu-emulator/yuzu). We centralize translation work there, and periodically upstream translations.
### Building
## Building
* __Windows__: [Windows Build](https://github.com/yuzu-emu/yuzu/wiki/Building-For-Windows)
* __Linux__: [Linux Build](https://github.com/yuzu-emu/yuzu/wiki/Building-For-Linux)
## Download
### Support
We happily accept monetary donations, or donated games and hardware. Please see our [donations page](https://yuzu-emu.org/donate/) for more information on how you can contribute to yuzu. Any donations received will go towards things like:
You can download the latest releases automatically via the installer on our [downloads](https://yuzu-emu.org/downloads/) page.
## Support
If you enjoy the project and want to support us financially, check out our Patreon!
<a href="https://www.patreon.com/yuzuteam">
<img src="https://c5.patreon.com/external/logo/become_a_patron_button@2x.png" width="160">
</a>
Any donations received will go towards things like:
* Switch consoles to explore and reverse-engineer the hardware
* Switch games for testing, reverse-engineering, and implementing new features
* Web hosting and infrastructure setup
* Software licenses (e.g. Visual Studio, IDA Pro, etc.)
* Additional hardware (e.g. GPUs as-needed to improve rendering support, other peripherals to add support for, etc.)
We also more than gladly accept used Switch consoles, preferably ones with firmware 3.0.0 or lower! If you would like to give yours away, don't hesitate to join our [Discord](https://discord.gg/VXqngT3) and talk to bunnei. You may also contact: donations@yuzu-emu.org.
If you wish to support us a different way, please join our [Discord](https://discord.gg/u77vRWY) and talk to bunnei. You may also contact: donations@yuzu-emu.org.
## License
yuzu is licensed under the GPLv2 (or any later version). Refer to the [license.txt](https://github.com/yuzu-emu/yuzu/blob/master/license.txt) file.

View File

@@ -53,10 +53,10 @@ endif()
# SDL2
if (NOT SDL2_FOUND AND ENABLE_SDL2)
if (NOT WIN32)
# Yuzu itself needs: Events Joystick Haptic Sensor Timers
# Yuzu itself needs: Events Joystick Haptic Sensor Timers Audio
# Yuzu-cmd also needs: Video (depends on Loadso/Dlopen)
set(SDL_UNUSED_SUBSYSTEMS
Atomic Audio Render Power Threads
Atomic Render Power Threads
File CPUinfo Filesystem Locale)
foreach(_SUB ${SDL_UNUSED_SUBSYSTEMS})
string(TOUPPER ${_SUB} _OPT)
@@ -115,7 +115,7 @@ if (ENABLE_WEB_SERVICE)
# httplib
add_library(httplib INTERFACE)
target_include_directories(httplib INTERFACE ./httplib)
target_include_directories(httplib INTERFACE ./cpp-httplib)
target_compile_definitions(httplib INTERFACE -DCPPHTTPLIB_OPENSSL_SUPPORT)
target_link_libraries(httplib INTERFACE ${OPENSSL_LIBRARIES})
if (WIN32)

1
externals/cpp-httplib vendored Submodule

Submodule externals/cpp-httplib added at 9648f950f5

View File

@@ -1,15 +0,0 @@
From https://github.com/yhirose/cpp-httplib/tree/ff5677ad197947177c158fe857caff4f0e242045 with https://github.com/yhirose/cpp-httplib/pull/701
MIT License
===
cpp-httplib
A C++11 header-only HTTP library.
It's extremely easy to setup. Just include httplib.h file in your code!
Inspired by Sinatra and express.
© 2017 Yuji Hirose

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
if (MINGW OR (${CMAKE_SYSTEM_NAME} MATCHES "Linux"))
if (MINGW OR (${CMAKE_SYSTEM_NAME} MATCHES "Linux") OR APPLE)
set(LIBUSB_FOUND ON CACHE BOOL "libusb is present" FORCE)
set(LIBUSB_VERSION "1.0.24" CACHE STRING "libusb version string" FORCE)

View File

@@ -45,13 +45,22 @@ if (MSVC)
/Zc:inline
/Zc:throwingNew
# External headers diagnostics
/experimental:external # Enables the external headers options. This option isn't required in Visual Studio 2019 version 16.10 and later
/external:anglebrackets # Treats all headers included by #include <header>, where the header file is enclosed in angle brackets (< >), as external headers
/external:W0 # Sets the default warning level to 0 for external headers, effectively turning off warnings for external headers
# Warnings
/W3
/we4062 # enumerator 'identifier' in a switch of enum 'enumeration' is not handled
/we4018 # 'expression': signed/unsigned mismatch
/we4062 # Enumerator 'identifier' in a switch of enum 'enumeration' is not handled
/we4101 # 'identifier': unreferenced local variable
/we4265 # 'class': class has virtual functions, but destructor is not virtual
/we4388 # signed/unsigned mismatch
/we4547 # 'operator' : operator before comma has no effect; expected operator with side-effect
/we4267 # 'var': conversion from 'size_t' to 'type', possible loss of data
/we4305 # 'context': truncation from 'type1' to 'type2'
/we4388 # 'expression': signed/unsigned mismatch
/we4389 # 'operator': signed/unsigned mismatch
/we4547 # 'operator': operator before comma has no effect; expected operator with side-effect
/we4549 # 'operator1': operator before comma has no effect; did you intend 'operator2'?
/we4555 # Expression has no effect; expected expression with side-effect
/we4715 # 'function': not all control paths return a value

View File

@@ -42,6 +42,7 @@ add_library(audio_core STATIC
voice_context.h
$<$<BOOL:${ENABLE_CUBEB}>:cubeb_sink.cpp cubeb_sink.h>
$<$<BOOL:${ENABLE_SDL2}>:sdl2_sink.cpp sdl2_sink.h>
)
create_target_directory_groups(audio_core)
@@ -71,3 +72,7 @@ if(ENABLE_CUBEB)
target_link_libraries(audio_core PRIVATE cubeb)
target_compile_definitions(audio_core PRIVATE -DHAVE_CUBEB=1)
endif()
if(ENABLE_SDL2)
target_link_libraries(audio_core PRIVATE SDL2)
target_compile_definitions(audio_core PRIVATE HAVE_SDL2)
endif()

View File

@@ -15,7 +15,7 @@ constexpr ResultCode ERR_INVALID_PARAMETERS{ErrorModule::Audio, 41};
constexpr ResultCode ERR_SPLITTER_SORT_FAILED{ErrorModule::Audio, 43};
} // namespace Audren
constexpr u32_le CURRENT_PROCESS_REVISION = Common::MakeMagic('R', 'E', 'V', '8');
constexpr u32_le CURRENT_PROCESS_REVISION = Common::MakeMagic('R', 'E', 'V', '9');
constexpr std::size_t MAX_MIX_BUFFERS = 24;
constexpr std::size_t MAX_BIQUAD_FILTERS = 2;
constexpr std::size_t MAX_CHANNEL_COUNT = 6;

View File

@@ -0,0 +1,163 @@
// Copyright 2018 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <algorithm>
#include <atomic>
#include <cstring>
#include "audio_core/sdl2_sink.h"
#include "audio_core/stream.h"
#include "audio_core/time_stretch.h"
#include "common/assert.h"
#include "common/logging/log.h"
//#include "common/settings.h"
// Ignore -Wimplicit-fallthrough due to https://github.com/libsdl-org/SDL/issues/4307
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wimplicit-fallthrough"
#endif
#include <SDL.h>
#ifdef __clang__
#pragma clang diagnostic pop
#endif
namespace AudioCore {
class SDLSinkStream final : public SinkStream {
public:
SDLSinkStream(u32 sample_rate, u32 num_channels_, const std::string& output_device)
: num_channels{std::min(num_channels_, 6u)}, time_stretch{sample_rate, num_channels} {
SDL_AudioSpec spec;
spec.freq = sample_rate;
spec.channels = static_cast<u8>(num_channels);
spec.format = AUDIO_S16SYS;
spec.samples = 4096;
spec.callback = nullptr;
SDL_AudioSpec obtained;
if (output_device.empty()) {
dev = SDL_OpenAudioDevice(nullptr, 0, &spec, &obtained, 0);
} else {
dev = SDL_OpenAudioDevice(output_device.c_str(), 0, &spec, &obtained, 0);
}
if (dev == 0) {
LOG_CRITICAL(Audio_Sink, "Error opening sdl audio device: {}", SDL_GetError());
return;
}
SDL_PauseAudioDevice(dev, 0);
}
~SDLSinkStream() override {
if (dev == 0) {
return;
}
SDL_CloseAudioDevice(dev);
}
void EnqueueSamples(u32 source_num_channels, const std::vector<s16>& samples) override {
if (source_num_channels > num_channels) {
// Downsample 6 channels to 2
ASSERT_MSG(source_num_channels == 6, "Channel count must be 6");
std::vector<s16> buf;
buf.reserve(samples.size() * num_channels / source_num_channels);
for (std::size_t i = 0; i < samples.size(); i += source_num_channels) {
// Downmixing implementation taken from the ATSC standard
const s16 left{samples[i + 0]};
const s16 right{samples[i + 1]};
const s16 center{samples[i + 2]};
const s16 surround_left{samples[i + 4]};
const s16 surround_right{samples[i + 5]};
// Not used in the ATSC reference implementation
[[maybe_unused]] const s16 low_frequency_effects{samples[i + 3]};
constexpr s32 clev{707}; // center mixing level coefficient
constexpr s32 slev{707}; // surround mixing level coefficient
buf.push_back(static_cast<s16>(left + (clev * center / 1000) +
(slev * surround_left / 1000)));
buf.push_back(static_cast<s16>(right + (clev * center / 1000) +
(slev * surround_right / 1000)));
}
int ret = SDL_QueueAudio(dev, static_cast<const void*>(buf.data()),
static_cast<u32>(buf.size() * sizeof(s16)));
if (ret < 0)
LOG_WARNING(Audio_Sink, "Could not queue audio buffer: {}", SDL_GetError());
return;
}
int ret = SDL_QueueAudio(dev, static_cast<const void*>(samples.data()),
static_cast<u32>(samples.size() * sizeof(s16)));
if (ret < 0)
LOG_WARNING(Audio_Sink, "Could not queue audio buffer: {}", SDL_GetError());
}
std::size_t SamplesInQueue(u32 channel_count) const override {
if (dev == 0)
return 0;
return SDL_GetQueuedAudioSize(dev) / (channel_count * sizeof(s16));
}
void Flush() override {
should_flush = true;
}
u32 GetNumChannels() const {
return num_channels;
}
private:
SDL_AudioDeviceID dev = 0;
u32 num_channels{};
std::atomic<bool> should_flush{};
TimeStretcher time_stretch;
};
SDLSink::SDLSink(std::string_view target_device_name) {
if (!SDL_WasInit(SDL_INIT_AUDIO)) {
if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
LOG_CRITICAL(Audio_Sink, "SDL_InitSubSystem audio failed: {}", SDL_GetError());
return;
}
}
if (target_device_name != auto_device_name && !target_device_name.empty()) {
output_device = target_device_name;
} else {
output_device.clear();
}
}
SDLSink::~SDLSink() = default;
SinkStream& SDLSink::AcquireSinkStream(u32 sample_rate, u32 num_channels, const std::string&) {
sink_streams.push_back(
std::make_unique<SDLSinkStream>(sample_rate, num_channels, output_device));
return *sink_streams.back();
}
std::vector<std::string> ListSDLSinkDevices() {
std::vector<std::string> device_list;
if (!SDL_WasInit(SDL_INIT_AUDIO)) {
if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
LOG_CRITICAL(Audio_Sink, "SDL_InitSubSystem audio failed: {}", SDL_GetError());
return {};
}
}
const int device_count = SDL_GetNumAudioDevices(0);
for (int i = 0; i < device_count; ++i) {
device_list.emplace_back(SDL_GetAudioDeviceName(i, 0));
}
return device_list;
}
} // namespace AudioCore

View File

@@ -0,0 +1,29 @@
// Copyright 2018 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <string>
#include <vector>
#include "audio_core/sink.h"
namespace AudioCore {
class SDLSink final : public Sink {
public:
explicit SDLSink(std::string_view device_id);
~SDLSink() override;
SinkStream& AcquireSinkStream(u32 sample_rate, u32 num_channels,
const std::string& name) override;
private:
std::string output_device;
std::vector<SinkStreamPtr> sink_streams;
};
std::vector<std::string> ListSDLSinkDevices();
} // namespace AudioCore

View File

@@ -4,6 +4,8 @@
#pragma once
#include <array>
#include <vector>
#include "audio_core/common.h"
#include "common/common_funcs.h"
#include "common/common_types.h"

View File

@@ -11,6 +11,9 @@
#ifdef HAVE_CUBEB
#include "audio_core/cubeb_sink.h"
#endif
#ifdef HAVE_SDL2
#include "audio_core/sdl2_sink.h"
#endif
#include "common/logging/log.h"
namespace AudioCore {
@@ -35,6 +38,13 @@ constexpr SinkDetails sink_details[] = {
return std::make_unique<CubebSink>(device_id);
},
&ListCubebSinkDevices},
#endif
#ifdef HAVE_SDL2
SinkDetails{"sdl2",
[](std::string_view device_id) -> std::unique_ptr<Sink> {
return std::make_unique<SDLSink>(device_id);
},
&ListSDLSinkDevices},
#endif
SinkDetails{"null",
[](std::string_view device_id) -> std::unique_ptr<Sink> {

View File

@@ -107,9 +107,12 @@ void Stream::PlayNextBuffer(std::chrono::nanoseconds ns_late) {
active_buffer = queued_buffers.front();
queued_buffers.pop();
VolumeAdjustSamples(active_buffer->GetSamples(), game_volume);
auto& samples = active_buffer->GetSamples();
sink_stream.EnqueueSamples(GetNumChannels(), active_buffer->GetSamples());
VolumeAdjustSamples(samples, game_volume);
sink_stream.EnqueueSamples(GetNumChannels(), samples);
played_samples += samples.size();
const auto buffer_release_ns = GetBufferReleaseNS(*active_buffer);

View File

@@ -89,6 +89,11 @@ public:
return sample_rate;
}
/// Gets the number of samples played so far
[[nodiscard]] u64 GetPlayedSampleCount() const {
return played_samples;
}
/// Gets the number of channels
[[nodiscard]] u32 GetNumChannels() const;
@@ -106,6 +111,7 @@ private:
[[nodiscard]] std::chrono::nanoseconds GetBufferReleaseNS(const Buffer& buffer) const;
u32 sample_rate; ///< Sample rate of the stream
u64 played_samples{}; ///< The current played sample count
Format format; ///< Format of the stream
float game_volume = 1.0f; ///< The volume the game currently has set
ReleaseCallback release_callback; ///< Buffer release callback for the stream

View File

@@ -110,7 +110,6 @@ add_library(common STATIC
cityhash.cpp
cityhash.h
common_funcs.h
common_sizes.h
common_types.h
concepts.h
div_ceil.h
@@ -134,6 +133,7 @@ add_library(common STATIC
host_memory.cpp
host_memory.h
intrusive_red_black_tree.h
literals.h
logging/backend.cpp
logging/backend.h
logging/filter.cpp
@@ -141,6 +141,7 @@ add_library(common STATIC
logging/log.h
logging/text_formatter.cpp
logging/text_formatter.h
logging/types.h
lz4_compression.cpp
lz4_compression.h
math_util.h

View File

@@ -1,43 +0,0 @@
// Copyright 2021 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <limits>
#include "common/common_types.h"
namespace Common {
enum : u64 {
Size_1_KB = 0x400ULL,
Size_64_KB = 64ULL * Size_1_KB,
Size_128_KB = 128ULL * Size_1_KB,
Size_1_MB = 0x100000ULL,
Size_2_MB = 2ULL * Size_1_MB,
Size_4_MB = 4ULL * Size_1_MB,
Size_5_MB = 5ULL * Size_1_MB,
Size_14_MB = 14ULL * Size_1_MB,
Size_32_MB = 32ULL * Size_1_MB,
Size_33_MB = 33ULL * Size_1_MB,
Size_128_MB = 128ULL * Size_1_MB,
Size_448_MB = 448ULL * Size_1_MB,
Size_507_MB = 507ULL * Size_1_MB,
Size_562_MB = 562ULL * Size_1_MB,
Size_1554_MB = 1554ULL * Size_1_MB,
Size_2048_MB = 2048ULL * Size_1_MB,
Size_2193_MB = 2193ULL * Size_1_MB,
Size_3285_MB = 3285ULL * Size_1_MB,
Size_4916_MB = 4916ULL * Size_1_MB,
Size_1_GB = 0x40000000ULL,
Size_2_GB = 2ULL * Size_1_GB,
Size_4_GB = 4ULL * Size_1_GB,
Size_6_GB = 6ULL * Size_1_GB,
Size_8_GB = 8ULL * Size_1_GB,
Size_64_GB = 64ULL * Size_1_GB,
Size_512_GB = 512ULL * Size_1_GB,
Size_Invalid = std::numeric_limits<u64>::max(),
};
} // namespace Common

View File

@@ -21,6 +21,8 @@ void DetachedTasks::WaitForAllTasks() {
}
DetachedTasks::~DetachedTasks() {
WaitForAllTasks();
std::unique_lock lock{mutex};
ASSERT(count == 0);
instance = nullptr;

View File

@@ -172,7 +172,7 @@ std::string ReadStringFromFile(const std::filesystem::path& path, FileType type)
size_t WriteStringToFile(const std::filesystem::path& path, FileType type,
std::string_view string) {
if (!IsFile(path)) {
if (Exists(path) && !IsFile(path)) {
return 0;
}
@@ -183,11 +183,7 @@ size_t WriteStringToFile(const std::filesystem::path& path, FileType type,
size_t AppendStringToFile(const std::filesystem::path& path, FileType type,
std::string_view string) {
if (!Exists(path)) {
return WriteStringToFile(path, type, string);
}
if (!IsFile(path)) {
if (Exists(path) && !IsFile(path)) {
return 0;
}
@@ -309,7 +305,11 @@ bool IOFile::Flush() const {
errno = 0;
const auto flush_result = std::fflush(file) == 0;
#ifdef _WIN32
const auto flush_result = std::fflush(file) == 0 && _commit(fileno(file)) == 0;
#else
const auto flush_result = std::fflush(file) == 0 && fsync(fileno(file)) == 0;
#endif
if (!flush_result) {
const auto ec = std::error_code{errno, std::generic_category()};

View File

@@ -49,7 +49,7 @@ void OpenFileStream(FileStream& file_stream, const Path& path, std::ios_base::op
/**
* Reads an entire file at path and returns a string of the contents read from the file.
* If the filesystem object at path is not a file, this function returns an empty string.
* If the filesystem object at path is not a regular file, this function returns an empty string.
*
* @param path Filesystem path
* @param type File type
@@ -71,8 +71,9 @@ template <typename Path>
/**
* Writes a string to a file at path and returns the number of characters successfully written.
* If an file already exists at path, its contents will be erased.
* If the filesystem object at path is not a file, this function returns 0.
* If a file already exists at path, its contents will be erased.
* If a file does not exist at path, it creates and opens a new empty file for writing.
* If the filesystem object at path exists and is not a regular file, this function returns 0.
*
* @param path Filesystem path
* @param type File type
@@ -95,8 +96,8 @@ template <typename Path>
/**
* Appends a string to a file at path and returns the number of characters successfully written.
* If a file does not exist at path, WriteStringToFile is called instead.
* If the filesystem object at path is not a file, this function returns 0.
* If a file does not exist at path, it creates and opens a new empty file for appending.
* If the filesystem object at path exists and is not a regular file, this function returns 0.
*
* @param path Filesystem path
* @param type File type
@@ -395,11 +396,11 @@ public:
[[nodiscard]] size_t WriteString(std::span<const char> string) const;
/**
* Flushes any unwritten buffered data into the file.
* Attempts to flush any unwritten buffered data into the file and flush the file into the disk.
*
* @returns True if the flush was successful, false otherwise.
*/
[[nodiscard]] bool Flush() const;
bool Flush() const;
/**
* Resizes the file to a given size.

View File

@@ -135,8 +135,9 @@ std::shared_ptr<IOFile> FileOpen(const fs::path& path, FileAccessMode mode, File
return nullptr;
}
if (!IsFile(path)) {
LOG_ERROR(Common_Filesystem, "Filesystem object at path={} is not a file",
if (Exists(path) && !IsFile(path)) {
LOG_ERROR(Common_Filesystem,
"Filesystem object at path={} exists and is not a regular file",
PathToUTF8String(path));
return nullptr;
}
@@ -321,7 +322,8 @@ bool RemoveDirContentsRecursively(const fs::path& path) {
std::error_code ec;
for (const auto& entry : fs::recursive_directory_iterator(path, ec)) {
// TODO (Morph): Replace this with recursive_directory_iterator once it's fixed in MSVC.
for (const auto& entry : fs::directory_iterator(path, ec)) {
if (ec) {
LOG_ERROR(Common_Filesystem,
"Failed to completely enumerate the directory at path={}, ec_message={}",
@@ -337,6 +339,12 @@ bool RemoveDirContentsRecursively(const fs::path& path) {
PathToUTF8String(entry.path()), ec.message());
break;
}
// TODO (Morph): Remove this when MSVC fixes recursive_directory_iterator.
// recursive_directory_iterator throws an exception despite passing in a std::error_code.
if (entry.status().type() == fs::file_type::directory) {
return RemoveDirContentsRecursively(entry.path());
}
}
if (ec) {
@@ -475,7 +483,8 @@ void IterateDirEntriesRecursively(const std::filesystem::path& path,
std::error_code ec;
for (const auto& entry : fs::recursive_directory_iterator(path, ec)) {
// TODO (Morph): Replace this with recursive_directory_iterator once it's fixed in MSVC.
for (const auto& entry : fs::directory_iterator(path, ec)) {
if (ec) {
break;
}
@@ -495,6 +504,12 @@ void IterateDirEntriesRecursively(const std::filesystem::path& path,
break;
}
}
// TODO (Morph): Remove this when MSVC fixes recursive_directory_iterator.
// recursive_directory_iterator throws an exception despite passing in a std::error_code.
if (entry.status().type() == fs::file_type::directory) {
IterateDirEntriesRecursively(entry.path(), callback, filter);
}
}
if (callback_error || ec) {

View File

@@ -48,18 +48,18 @@ template <typename Path>
*
* Failures occur when:
* - Input path is not valid
* - Filesystem object at path is not a file
* - Filesystem object at path is not a regular file
* - Filesystem at path is read only
*
* @param path Filesystem path
*
* @returns True if file removal succeeds or file does not exist, false otherwise.
*/
[[nodiscard]] bool RemoveFile(const std::filesystem::path& path);
bool RemoveFile(const std::filesystem::path& path);
#ifdef _WIN32
template <typename Path>
[[nodiscard]] bool RemoveFile(const Path& path) {
bool RemoveFile(const Path& path) {
if constexpr (IsChar<typename Path::value_type>) {
return RemoveFile(ToU8String(path));
} else {
@@ -74,7 +74,7 @@ template <typename Path>
* Failures occur when:
* - One or both input path(s) is not valid
* - Filesystem object at old_path does not exist
* - Filesystem object at old_path is not a file
* - Filesystem object at old_path is not a regular file
* - Filesystem object at new_path exists
* - Filesystem at either path is read only
*
@@ -110,8 +110,8 @@ template <typename Path1, typename Path2>
*
* Failures occur when:
* - Input path is not valid
* - Filesystem object at path is not a file
* - The file is not opened
* - Filesystem object at path exists and is not a regular file
* - The file is not open
*
* @param path Filesystem path
* @param mode File access mode
@@ -251,11 +251,11 @@ template <typename Path>
*
* @returns True if directory removal succeeds or directory does not exist, false otherwise.
*/
[[nodiscard]] bool RemoveDir(const std::filesystem::path& path);
bool RemoveDir(const std::filesystem::path& path);
#ifdef _WIN32
template <typename Path>
[[nodiscard]] bool RemoveDir(const Path& path) {
bool RemoveDir(const Path& path) {
if constexpr (IsChar<typename Path::value_type>) {
return RemoveDir(ToU8String(path));
} else {
@@ -276,11 +276,11 @@ template <typename Path>
*
* @returns True if the directory and all of its contents are removed successfully, false otherwise.
*/
[[nodiscard]] bool RemoveDirRecursively(const std::filesystem::path& path);
bool RemoveDirRecursively(const std::filesystem::path& path);
#ifdef _WIN32
template <typename Path>
[[nodiscard]] bool RemoveDirRecursively(const Path& path) {
bool RemoveDirRecursively(const Path& path) {
if constexpr (IsChar<typename Path::value_type>) {
return RemoveDirRecursively(ToU8String(path));
} else {
@@ -301,11 +301,11 @@ template <typename Path>
*
* @returns True if all of the directory's contents are removed successfully, false otherwise.
*/
[[nodiscard]] bool RemoveDirContentsRecursively(const std::filesystem::path& path);
bool RemoveDirContentsRecursively(const std::filesystem::path& path);
#ifdef _WIN32
template <typename Path>
[[nodiscard]] bool RemoveDirContentsRecursively(const Path& path) {
bool RemoveDirContentsRecursively(const Path& path) {
if constexpr (IsChar<typename Path::value_type>) {
return RemoveDirContentsRecursively(ToU8String(path));
} else {
@@ -435,11 +435,13 @@ template <typename Path>
#endif
/**
* Returns whether a filesystem object at path is a file.
* Returns whether a filesystem object at path is a regular file.
* A regular file is a file that stores text or binary data.
* It is not a directory, symlink, FIFO, socket, block device, or character device.
*
* @param path Filesystem path
*
* @returns True if a filesystem object at path is a file, false otherwise.
* @returns True if a filesystem object at path is a regular file, false otherwise.
*/
[[nodiscard]] bool IsFile(const std::filesystem::path& path);

View File

@@ -53,8 +53,9 @@ template <typename ContiguousContainer>
std::string out;
out.reserve(std::size(data) * pad_width);
const auto format_str = fmt::runtime(upper ? "{:02X}" : "{:02x}");
for (const u8 c : data) {
out += fmt::format(upper ? "{:02X}" : "{:02x}", c);
out += fmt::format(format_str, c);
}
return out;

View File

@@ -34,7 +34,7 @@ constexpr size_t HugePageSize = 0x200000;
// Manually imported for MinGW compatibility
#ifndef MEM_RESERVE_PLACEHOLDER
#define MEM_RESERVE_PLACEHOLDER 0x0004000
#define MEM_RESERVE_PLACEHOLDER 0x00040000
#endif
#ifndef MEM_REPLACE_PLACEHOLDER
#define MEM_REPLACE_PLACEHOLDER 0x00004000

31
src/common/literals.h Normal file
View File

@@ -0,0 +1,31 @@
// Copyright 2021 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include "common/common_types.h"
namespace Common::Literals {
constexpr u64 operator""_KiB(unsigned long long int x) {
return 1024ULL * x;
}
constexpr u64 operator""_MiB(unsigned long long int x) {
return 1024_KiB * x;
}
constexpr u64 operator""_GiB(unsigned long long int x) {
return 1024_MiB * x;
}
constexpr u64 operator""_TiB(unsigned long long int x) {
return 1024_GiB * x;
}
constexpr u64 operator""_PiB(unsigned long long int x) {
return 1024_TiB * x;
}
} // namespace Common::Literals

View File

@@ -17,7 +17,10 @@
#endif
#include "common/assert.h"
#include "common/fs/file.h"
#include "common/fs/fs.h"
#include "common/literals.h"
#include "common/logging/backend.h"
#include "common/logging/log.h"
#include "common/logging/text_formatter.h"
@@ -97,8 +100,8 @@ private:
write_logs(entry);
}
// Drain the logging queue. Only writes out up to MAX_LOGS_TO_WRITE to prevent a case
// where a system is repeatedly spamming logs even on close.
// Drain the logging queue. Only writes out up to MAX_LOGS_TO_WRITE to prevent a
// case where a system is repeatedly spamming logs even on close.
const int MAX_LOGS_TO_WRITE = filter.IsDebug() ? INT_MAX : 100;
int logs_written = 0;
while (logs_written++ < MAX_LOGS_TO_WRITE && message_queue.Pop(entry)) {
@@ -140,10 +143,14 @@ private:
std::chrono::steady_clock::time_point time_origin{std::chrono::steady_clock::now()};
};
ConsoleBackend::~ConsoleBackend() = default;
void ConsoleBackend::Write(const Entry& entry) {
PrintMessage(entry);
}
ColorConsoleBackend::~ColorConsoleBackend() = default;
void ColorConsoleBackend::Write(const Entry& entry) {
PrintColoredMessage(entry);
}
@@ -154,19 +161,23 @@ FileBackend::FileBackend(const std::filesystem::path& filename) {
// Existence checks are done within the functions themselves.
// We don't particularly care if these succeed or not.
void(FS::RemoveFile(old_filename));
FS::RemoveFile(old_filename);
void(FS::RenameFile(filename, old_filename));
file = FS::IOFile(filename, FS::FileAccessMode::Write, FS::FileType::TextFile);
file =
std::make_unique<FS::IOFile>(filename, FS::FileAccessMode::Write, FS::FileType::TextFile);
}
FileBackend::~FileBackend() = default;
void FileBackend::Write(const Entry& entry) {
using namespace Common::Literals;
// prevent logs from going over the maximum size (in case its spamming and the user doesn't
// know)
constexpr std::size_t MAX_BYTES_WRITTEN = 100 * 1024 * 1024;
constexpr std::size_t MAX_BYTES_WRITTEN_EXTENDED = 1024 * 1024 * 1024;
constexpr std::size_t MAX_BYTES_WRITTEN = 100_MiB;
constexpr std::size_t MAX_BYTES_WRITTEN_EXTENDED = 1_GiB;
if (!file.IsOpen()) {
if (!file->IsOpen()) {
return;
}
@@ -176,147 +187,20 @@ void FileBackend::Write(const Entry& entry) {
return;
}
bytes_written += file.WriteString(FormatLogMessage(entry).append(1, '\n'));
bytes_written += file->WriteString(FormatLogMessage(entry).append(1, '\n'));
if (entry.log_level >= Level::Error) {
void(file.Flush());
file->Flush();
}
}
DebuggerBackend::~DebuggerBackend() = default;
void DebuggerBackend::Write(const Entry& entry) {
#ifdef _WIN32
::OutputDebugStringW(UTF8ToUTF16W(FormatLogMessage(entry).append(1, '\n')).c_str());
#endif
}
/// Macro listing all log classes. Code should define CLS and SUB as desired before invoking this.
#define ALL_LOG_CLASSES() \
CLS(Log) \
CLS(Common) \
SUB(Common, Filesystem) \
SUB(Common, Memory) \
CLS(Core) \
SUB(Core, ARM) \
SUB(Core, Timing) \
CLS(Config) \
CLS(Debug) \
SUB(Debug, Emulated) \
SUB(Debug, GPU) \
SUB(Debug, Breakpoint) \
SUB(Debug, GDBStub) \
CLS(Kernel) \
SUB(Kernel, SVC) \
CLS(Service) \
SUB(Service, ACC) \
SUB(Service, Audio) \
SUB(Service, AM) \
SUB(Service, AOC) \
SUB(Service, APM) \
SUB(Service, ARP) \
SUB(Service, BCAT) \
SUB(Service, BPC) \
SUB(Service, BGTC) \
SUB(Service, BTDRV) \
SUB(Service, BTM) \
SUB(Service, Capture) \
SUB(Service, ERPT) \
SUB(Service, ETicket) \
SUB(Service, EUPLD) \
SUB(Service, Fatal) \
SUB(Service, FGM) \
SUB(Service, Friend) \
SUB(Service, FS) \
SUB(Service, GRC) \
SUB(Service, HID) \
SUB(Service, IRS) \
SUB(Service, LBL) \
SUB(Service, LDN) \
SUB(Service, LDR) \
SUB(Service, LM) \
SUB(Service, Migration) \
SUB(Service, Mii) \
SUB(Service, MM) \
SUB(Service, NCM) \
SUB(Service, NFC) \
SUB(Service, NFP) \
SUB(Service, NIFM) \
SUB(Service, NIM) \
SUB(Service, NPNS) \
SUB(Service, NS) \
SUB(Service, NVDRV) \
SUB(Service, OLSC) \
SUB(Service, PCIE) \
SUB(Service, PCTL) \
SUB(Service, PCV) \
SUB(Service, PM) \
SUB(Service, PREPO) \
SUB(Service, PSC) \
SUB(Service, PSM) \
SUB(Service, SET) \
SUB(Service, SM) \
SUB(Service, SPL) \
SUB(Service, SSL) \
SUB(Service, TCAP) \
SUB(Service, Time) \
SUB(Service, USB) \
SUB(Service, VI) \
SUB(Service, WLAN) \
CLS(HW) \
SUB(HW, Memory) \
SUB(HW, LCD) \
SUB(HW, GPU) \
SUB(HW, AES) \
CLS(IPC) \
CLS(Frontend) \
CLS(Render) \
SUB(Render, Software) \
SUB(Render, OpenGL) \
SUB(Render, Vulkan) \
CLS(Audio) \
SUB(Audio, DSP) \
SUB(Audio, Sink) \
CLS(Input) \
CLS(Network) \
CLS(Loader) \
CLS(CheatEngine) \
CLS(Crypto) \
CLS(WebService)
// GetClassName is a macro defined by Windows.h, grrr...
const char* GetLogClassName(Class log_class) {
switch (log_class) {
#define CLS(x) \
case Class::x: \
return #x;
#define SUB(x, y) \
case Class::x##_##y: \
return #x "." #y;
ALL_LOG_CLASSES()
#undef CLS
#undef SUB
case Class::Count:
break;
}
return "Invalid";
}
const char* GetLevelName(Level log_level) {
#define LVL(x) \
case Level::x: \
return #x
switch (log_level) {
LVL(Trace);
LVL(Debug);
LVL(Info);
LVL(Warning);
LVL(Error);
LVL(Critical);
case Level::Count:
break;
}
#undef LVL
return "Invalid";
}
void SetGlobalFilter(const Filter& filter) {
Impl::Instance().SetGlobalFilter(filter);
}

View File

@@ -1,36 +1,24 @@
// Copyright 2014 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <chrono>
#include <filesystem>
#include <memory>
#include <string>
#include <string_view>
#include "common/fs/file.h"
#include "common/logging/filter.h"
#include "common/logging/log.h"
namespace Common::FS {
class IOFile;
}
namespace Common::Log {
class Filter;
/**
* A log entry. Log entries are store in a structured format to permit more varied output
* formatting on different frontends, as well as facilitating filtering and aggregation.
*/
struct Entry {
std::chrono::microseconds timestamp;
Class log_class{};
Level log_level{};
const char* filename = nullptr;
unsigned int line_num = 0;
std::string function;
std::string message;
bool final_entry = false;
};
/**
* Interface for logging backends. As loggers can be created and removed at runtime, this can be
* used by a frontend for adding a custom logging backend as needed
@@ -38,6 +26,7 @@ struct Entry {
class Backend {
public:
virtual ~Backend() = default;
virtual void SetFilter(const Filter& new_filter) {
filter = new_filter;
}
@@ -53,6 +42,8 @@ private:
*/
class ConsoleBackend : public Backend {
public:
~ConsoleBackend() override;
static const char* Name() {
return "console";
}
@@ -67,6 +58,8 @@ public:
*/
class ColorConsoleBackend : public Backend {
public:
~ColorConsoleBackend() override;
static const char* Name() {
return "color_console";
}
@@ -83,6 +76,7 @@ public:
class FileBackend : public Backend {
public:
explicit FileBackend(const std::filesystem::path& filename);
~FileBackend() override;
static const char* Name() {
return "file";
@@ -95,7 +89,7 @@ public:
void Write(const Entry& entry) override;
private:
FS::IOFile file;
std::unique_ptr<FS::IOFile> file;
std::size_t bytes_written = 0;
};
@@ -104,6 +98,8 @@ private:
*/
class DebuggerBackend : public Backend {
public:
~DebuggerBackend() override;
static const char* Name() {
return "debugger";
}
@@ -119,17 +115,6 @@ void RemoveBackend(std::string_view backend_name);
Backend* GetBackend(std::string_view backend_name);
/**
* Returns the name of the passed log class as a C-string. Subclasses are separated by periods
* instead of underscores as in the enumeration.
*/
const char* GetLogClassName(Class log_class);
/**
* Returns the name of the passed log level as a C-string.
*/
const char* GetLevelName(Level log_level);
/**
* The global filter will prevent any messages from even being processed if they are filtered. Each
* backend can have a filter, but if the level is lower than the global filter, the backend will

View File

@@ -3,7 +3,6 @@
// Refer to the license.txt file included.
#include <algorithm>
#include "common/logging/backend.h"
#include "common/logging/filter.h"
#include "common/string_util.h"
@@ -22,7 +21,7 @@ Level GetLevelByName(const It begin, const It end) {
template <typename It>
Class GetClassByName(const It begin, const It end) {
for (ClassType i = 0; i < static_cast<ClassType>(Class::Count); ++i) {
for (u8 i = 0; i < static_cast<u8>(Class::Count); ++i) {
const char* level_name = GetLogClassName(static_cast<Class>(i));
if (Common::ComparePartialString(begin, end, level_name)) {
return static_cast<Class>(i);
@@ -62,6 +61,135 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) {
}
} // Anonymous namespace
/// Macro listing all log classes. Code should define CLS and SUB as desired before invoking this.
#define ALL_LOG_CLASSES() \
CLS(Log) \
CLS(Common) \
SUB(Common, Filesystem) \
SUB(Common, Memory) \
CLS(Core) \
SUB(Core, ARM) \
SUB(Core, Timing) \
CLS(Config) \
CLS(Debug) \
SUB(Debug, Emulated) \
SUB(Debug, GPU) \
SUB(Debug, Breakpoint) \
SUB(Debug, GDBStub) \
CLS(Kernel) \
SUB(Kernel, SVC) \
CLS(Service) \
SUB(Service, ACC) \
SUB(Service, Audio) \
SUB(Service, AM) \
SUB(Service, AOC) \
SUB(Service, APM) \
SUB(Service, ARP) \
SUB(Service, BCAT) \
SUB(Service, BPC) \
SUB(Service, BGTC) \
SUB(Service, BTDRV) \
SUB(Service, BTM) \
SUB(Service, Capture) \
SUB(Service, ERPT) \
SUB(Service, ETicket) \
SUB(Service, EUPLD) \
SUB(Service, Fatal) \
SUB(Service, FGM) \
SUB(Service, Friend) \
SUB(Service, FS) \
SUB(Service, GRC) \
SUB(Service, HID) \
SUB(Service, IRS) \
SUB(Service, LBL) \
SUB(Service, LDN) \
SUB(Service, LDR) \
SUB(Service, LM) \
SUB(Service, Migration) \
SUB(Service, Mii) \
SUB(Service, MM) \
SUB(Service, NCM) \
SUB(Service, NFC) \
SUB(Service, NFP) \
SUB(Service, NIFM) \
SUB(Service, NIM) \
SUB(Service, NPNS) \
SUB(Service, NS) \
SUB(Service, NVDRV) \
SUB(Service, OLSC) \
SUB(Service, PCIE) \
SUB(Service, PCTL) \
SUB(Service, PCV) \
SUB(Service, PM) \
SUB(Service, PREPO) \
SUB(Service, PSC) \
SUB(Service, PSM) \
SUB(Service, SET) \
SUB(Service, SM) \
SUB(Service, SPL) \
SUB(Service, SSL) \
SUB(Service, TCAP) \
SUB(Service, Time) \
SUB(Service, USB) \
SUB(Service, VI) \
SUB(Service, WLAN) \
CLS(HW) \
SUB(HW, Memory) \
SUB(HW, LCD) \
SUB(HW, GPU) \
SUB(HW, AES) \
CLS(IPC) \
CLS(Frontend) \
CLS(Render) \
SUB(Render, Software) \
SUB(Render, OpenGL) \
SUB(Render, Vulkan) \
CLS(Audio) \
SUB(Audio, DSP) \
SUB(Audio, Sink) \
CLS(Input) \
CLS(Network) \
CLS(Loader) \
CLS(CheatEngine) \
CLS(Crypto) \
CLS(WebService)
// GetClassName is a macro defined by Windows.h, grrr...
const char* GetLogClassName(Class log_class) {
switch (log_class) {
#define CLS(x) \
case Class::x: \
return #x;
#define SUB(x, y) \
case Class::x##_##y: \
return #x "." #y;
ALL_LOG_CLASSES()
#undef CLS
#undef SUB
case Class::Count:
break;
}
return "Invalid";
}
const char* GetLevelName(Level log_level) {
#define LVL(x) \
case Level::x: \
return #x
switch (log_level) {
LVL(Trace);
LVL(Debug);
LVL(Info);
LVL(Warning);
LVL(Error);
LVL(Critical);
case Level::Count:
break;
}
#undef LVL
return "Invalid";
}
Filter::Filter(Level default_level) {
ResetAll(default_level);
}

View File

@@ -5,12 +5,24 @@
#pragma once
#include <array>
#include <chrono>
#include <cstddef>
#include <string_view>
#include "common/logging/log.h"
namespace Common::Log {
/**
* Returns the name of the passed log class as a C-string. Subclasses are separated by periods
* instead of underscores as in the enumeration.
*/
const char* GetLogClassName(Class log_class);
/**
* Returns the name of the passed log level as a C-string.
*/
const char* GetLevelName(Level log_level);
/**
* Implements a log message filter which allows different log classes to have different minimum
* severity levels. The filter can be changed at runtime and can be parsed from a string to allow

View File

@@ -5,7 +5,7 @@
#pragma once
#include <fmt/format.h>
#include "common/common_types.h"
#include "common/logging/types.h"
namespace Common::Log {
@@ -18,124 +18,6 @@ constexpr const char* TrimSourcePath(std::string_view source) {
return source.data() + idx;
}
/// Specifies the severity or level of detail of the log message.
enum class Level : u8 {
Trace, ///< Extremely detailed and repetitive debugging information that is likely to
///< pollute logs.
Debug, ///< Less detailed debugging information.
Info, ///< Status information from important points during execution.
Warning, ///< Minor or potential problems found during execution of a task.
Error, ///< Major problems found during execution of a task that prevent it from being
///< completed.
Critical, ///< Major problems during execution that threaten the stability of the entire
///< application.
Count ///< Total number of logging levels
};
typedef u8 ClassType;
/**
* Specifies the sub-system that generated the log message.
*
* @note If you add a new entry here, also add a corresponding one to `ALL_LOG_CLASSES` in
* backend.cpp.
*/
enum class Class : ClassType {
Log, ///< Messages about the log system itself
Common, ///< Library routines
Common_Filesystem, ///< Filesystem interface library
Common_Memory, ///< Memory mapping and management functions
Core, ///< LLE emulation core
Core_ARM, ///< ARM CPU core
Core_Timing, ///< CoreTiming functions
Config, ///< Emulator configuration (including commandline)
Debug, ///< Debugging tools
Debug_Emulated, ///< Debug messages from the emulated programs
Debug_GPU, ///< GPU debugging tools
Debug_Breakpoint, ///< Logging breakpoints and watchpoints
Debug_GDBStub, ///< GDB Stub
Kernel, ///< The HLE implementation of the CTR kernel
Kernel_SVC, ///< Kernel system calls
Service, ///< HLE implementation of system services. Each major service
///< should have its own subclass.
Service_ACC, ///< The ACC (Accounts) service
Service_AM, ///< The AM (Applet manager) service
Service_AOC, ///< The AOC (AddOn Content) service
Service_APM, ///< The APM (Performance) service
Service_ARP, ///< The ARP service
Service_Audio, ///< The Audio (Audio control) service
Service_BCAT, ///< The BCAT service
Service_BGTC, ///< The BGTC (Background Task Controller) service
Service_BPC, ///< The BPC service
Service_BTDRV, ///< The Bluetooth driver service
Service_BTM, ///< The BTM service
Service_Capture, ///< The capture service
Service_ERPT, ///< The error reporting service
Service_ETicket, ///< The ETicket service
Service_EUPLD, ///< The error upload service
Service_Fatal, ///< The Fatal service
Service_FGM, ///< The FGM service
Service_Friend, ///< The friend service
Service_FS, ///< The FS (Filesystem) service
Service_GRC, ///< The game recording service
Service_HID, ///< The HID (Human interface device) service
Service_IRS, ///< The IRS service
Service_LBL, ///< The LBL (LCD backlight) service
Service_LDN, ///< The LDN (Local domain network) service
Service_LDR, ///< The loader service
Service_LM, ///< The LM (Logger) service
Service_Migration, ///< The migration service
Service_Mii, ///< The Mii service
Service_MM, ///< The MM (Multimedia) service
Service_NCM, ///< The NCM service
Service_NFC, ///< The NFC (Near-field communication) service
Service_NFP, ///< The NFP service
Service_NIFM, ///< The NIFM (Network interface) service
Service_NIM, ///< The NIM service
Service_NPNS, ///< The NPNS service
Service_NS, ///< The NS services
Service_NVDRV, ///< The NVDRV (Nvidia driver) service
Service_OLSC, ///< The OLSC service
Service_PCIE, ///< The PCIe service
Service_PCTL, ///< The PCTL (Parental control) service
Service_PCV, ///< The PCV service
Service_PM, ///< The PM service
Service_PREPO, ///< The PREPO (Play report) service
Service_PSC, ///< The PSC service
Service_PSM, ///< The PSM service
Service_SET, ///< The SET (Settings) service
Service_SM, ///< The SM (Service manager) service
Service_SPL, ///< The SPL service
Service_SSL, ///< The SSL service
Service_TCAP, ///< The TCAP service.
Service_Time, ///< The time service
Service_USB, ///< The USB (Universal Serial Bus) service
Service_VI, ///< The VI (Video interface) service
Service_WLAN, ///< The WLAN (Wireless local area network) service
HW, ///< Low-level hardware emulation
HW_Memory, ///< Memory-map and address translation
HW_LCD, ///< LCD register emulation
HW_GPU, ///< GPU control emulation
HW_AES, ///< AES engine emulation
IPC, ///< IPC interface
Frontend, ///< Emulator UI
Render, ///< Emulator video output and hardware acceleration
Render_Software, ///< Software renderer backend
Render_OpenGL, ///< OpenGL backend
Render_Vulkan, ///< Vulkan backend
Audio, ///< Audio emulation
Audio_DSP, ///< The HLE implementation of the DSP
Audio_Sink, ///< Emulator audio output backend
Loader, ///< ROM loader
CheatEngine, ///< Memory manipulation and engine VM functions
Crypto, ///< Cryptographic engine/functions
Input, ///< Input emulation
Network, ///< Network emulation
WebService, ///< Interface to yuzu Web Services
Count ///< Total number of logging classes
};
/// Logs a message to the global logger, using fmt
void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename,
unsigned int line_num, const char* function, const char* format,

View File

@@ -11,7 +11,7 @@
#include "common/assert.h"
#include "common/common_funcs.h"
#include "common/logging/backend.h"
#include "common/logging/filter.h"
#include "common/logging/log.h"
#include "common/logging/text_formatter.h"
#include "common/string_util.h"

144
src/common/logging/types.h Normal file
View File

@@ -0,0 +1,144 @@
// Copyright 2021 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <chrono>
#include "common/common_types.h"
namespace Common::Log {
/// Specifies the severity or level of detail of the log message.
enum class Level : u8 {
Trace, ///< Extremely detailed and repetitive debugging information that is likely to
///< pollute logs.
Debug, ///< Less detailed debugging information.
Info, ///< Status information from important points during execution.
Warning, ///< Minor or potential problems found during execution of a task.
Error, ///< Major problems found during execution of a task that prevent it from being
///< completed.
Critical, ///< Major problems during execution that threaten the stability of the entire
///< application.
Count ///< Total number of logging levels
};
/**
* Specifies the sub-system that generated the log message.
*
* @note If you add a new entry here, also add a corresponding one to `ALL_LOG_CLASSES` in
* filter.cpp.
*/
enum class Class : u8 {
Log, ///< Messages about the log system itself
Common, ///< Library routines
Common_Filesystem, ///< Filesystem interface library
Common_Memory, ///< Memory mapping and management functions
Core, ///< LLE emulation core
Core_ARM, ///< ARM CPU core
Core_Timing, ///< CoreTiming functions
Config, ///< Emulator configuration (including commandline)
Debug, ///< Debugging tools
Debug_Emulated, ///< Debug messages from the emulated programs
Debug_GPU, ///< GPU debugging tools
Debug_Breakpoint, ///< Logging breakpoints and watchpoints
Debug_GDBStub, ///< GDB Stub
Kernel, ///< The HLE implementation of the CTR kernel
Kernel_SVC, ///< Kernel system calls
Service, ///< HLE implementation of system services. Each major service
///< should have its own subclass.
Service_ACC, ///< The ACC (Accounts) service
Service_AM, ///< The AM (Applet manager) service
Service_AOC, ///< The AOC (AddOn Content) service
Service_APM, ///< The APM (Performance) service
Service_ARP, ///< The ARP service
Service_Audio, ///< The Audio (Audio control) service
Service_BCAT, ///< The BCAT service
Service_BGTC, ///< The BGTC (Background Task Controller) service
Service_BPC, ///< The BPC service
Service_BTDRV, ///< The Bluetooth driver service
Service_BTM, ///< The BTM service
Service_Capture, ///< The capture service
Service_ERPT, ///< The error reporting service
Service_ETicket, ///< The ETicket service
Service_EUPLD, ///< The error upload service
Service_Fatal, ///< The Fatal service
Service_FGM, ///< The FGM service
Service_Friend, ///< The friend service
Service_FS, ///< The FS (Filesystem) service
Service_GRC, ///< The game recording service
Service_HID, ///< The HID (Human interface device) service
Service_IRS, ///< The IRS service
Service_LBL, ///< The LBL (LCD backlight) service
Service_LDN, ///< The LDN (Local domain network) service
Service_LDR, ///< The loader service
Service_LM, ///< The LM (Logger) service
Service_Migration, ///< The migration service
Service_Mii, ///< The Mii service
Service_MM, ///< The MM (Multimedia) service
Service_NCM, ///< The NCM service
Service_NFC, ///< The NFC (Near-field communication) service
Service_NFP, ///< The NFP service
Service_NIFM, ///< The NIFM (Network interface) service
Service_NIM, ///< The NIM service
Service_NPNS, ///< The NPNS service
Service_NS, ///< The NS services
Service_NVDRV, ///< The NVDRV (Nvidia driver) service
Service_OLSC, ///< The OLSC service
Service_PCIE, ///< The PCIe service
Service_PCTL, ///< The PCTL (Parental control) service
Service_PCV, ///< The PCV service
Service_PM, ///< The PM service
Service_PREPO, ///< The PREPO (Play report) service
Service_PSC, ///< The PSC service
Service_PSM, ///< The PSM service
Service_SET, ///< The SET (Settings) service
Service_SM, ///< The SM (Service manager) service
Service_SPL, ///< The SPL service
Service_SSL, ///< The SSL service
Service_TCAP, ///< The TCAP service.
Service_Time, ///< The time service
Service_USB, ///< The USB (Universal Serial Bus) service
Service_VI, ///< The VI (Video interface) service
Service_WLAN, ///< The WLAN (Wireless local area network) service
HW, ///< Low-level hardware emulation
HW_Memory, ///< Memory-map and address translation
HW_LCD, ///< LCD register emulation
HW_GPU, ///< GPU control emulation
HW_AES, ///< AES engine emulation
IPC, ///< IPC interface
Frontend, ///< Emulator UI
Render, ///< Emulator video output and hardware acceleration
Render_Software, ///< Software renderer backend
Render_OpenGL, ///< OpenGL backend
Render_Vulkan, ///< Vulkan backend
Audio, ///< Audio emulation
Audio_DSP, ///< The HLE implementation of the DSP
Audio_Sink, ///< Emulator audio output backend
Loader, ///< ROM loader
CheatEngine, ///< Memory manipulation and engine VM functions
Crypto, ///< Cryptographic engine/functions
Input, ///< Input emulation
Network, ///< Network emulation
WebService, ///< Interface to yuzu Web Services
Count ///< Total number of logging classes
};
/**
* A log entry. Log entries are store in a structured format to permit more varied output
* formatting on different frontends, as well as facilitating filtering and aggregation.
*/
struct Entry {
std::chrono::microseconds timestamp;
Class log_class{};
Level log_level{};
const char* filename = nullptr;
unsigned int line_num = 0;
std::string function;
std::string message;
bool final_entry = false;
};
} // namespace Common::Log

View File

@@ -52,14 +52,14 @@ void LogSettings() {
log_setting("Renderer_FrameLimit", values.frame_limit.GetValue());
log_setting("Renderer_UseDiskShaderCache", values.use_disk_shader_cache.GetValue());
log_setting("Renderer_GPUAccuracyLevel", values.gpu_accuracy.GetValue());
log_setting("Renderer_UseGarbageCollect", values.use_garbage_collect.GetValue());
log_setting("Renderer_GarbageCollectLevel", values.garbage_collect_level.GetValue());
log_setting("Renderer_UseAsynchronousGpuEmulation",
values.use_asynchronous_gpu_emulation.GetValue());
log_setting("Renderer_UseNvdecEmulation", values.use_nvdec_emulation.GetValue());
log_setting("Renderer_AccelerateASTC", values.accelerate_astc.GetValue());
log_setting("Renderer_UseVsync", values.use_vsync.GetValue());
log_setting("Renderer_UseAssemblyShaders", values.use_assembly_shaders.GetValue());
log_setting("Renderer_UseAsynchronousShaders", values.use_asynchronous_shaders.GetValue());
log_setting("Renderer_UseGarbageCollection", values.use_caches_gc.GetValue());
log_setting("Renderer_AnisotropicFilteringLevel", values.max_anisotropy.GetValue());
log_setting("Audio_OutputEngine", values.sink_id);
log_setting("Audio_EnableAudioStretching", values.enable_audio_stretching.GetValue());
@@ -99,25 +99,6 @@ bool IsFastmemEnabled() {
return true;
}
bool UseGarbageCollect() {
return values.use_garbage_collect.GetValue();
}
std::chrono::minutes GarbageCollectTimer() {
switch (values.garbage_collect_level.GetValue()) {
case Settings::GCLevel::Aggressive:
return std::chrono::minutes(1);
case Settings::GCLevel::Normal:
return std::chrono::minutes(4);
case Settings::GCLevel::Relaxed:
return std::chrono::minutes(10);
}
UNREACHABLE_MSG("Garbage collection set to unknown value!",
static_cast<int>(values.garbage_collect_level.GetValue()));
values.use_garbage_collect.SetValue(false);
return {};
}
float Volume() {
if (values.audio_muted) {
return 0.0f;
@@ -142,6 +123,7 @@ void RestoreGlobalState(bool is_powered_on) {
values.cpu_accuracy.SetGlobal(true);
values.cpuopt_unsafe_unfuse_fma.SetGlobal(true);
values.cpuopt_unsafe_reduce_fp_error.SetGlobal(true);
values.cpuopt_unsafe_ignore_standard_fpcr.SetGlobal(true);
values.cpuopt_unsafe_inaccurate_nan.SetGlobal(true);
values.cpuopt_unsafe_fastmem_check.SetGlobal(true);
@@ -154,14 +136,14 @@ void RestoreGlobalState(bool is_powered_on) {
values.frame_limit.SetGlobal(true);
values.use_disk_shader_cache.SetGlobal(true);
values.gpu_accuracy.SetGlobal(true);
values.use_garbage_collect.SetGlobal(true);
values.garbage_collect_level.SetGlobal(true);
values.use_asynchronous_gpu_emulation.SetGlobal(true);
values.use_nvdec_emulation.SetGlobal(true);
values.accelerate_astc.SetGlobal(true);
values.use_vsync.SetGlobal(true);
values.use_assembly_shaders.SetGlobal(true);
values.use_asynchronous_shaders.SetGlobal(true);
values.use_fast_gpu_time.SetGlobal(true);
values.use_caches_gc.SetGlobal(true);
values.bg_red.SetGlobal(true);
values.bg_green.SetGlobal(true);
values.bg_blue.SetGlobal(true);

View File

@@ -34,12 +34,6 @@ enum class CPUAccuracy : u32 {
DebugMode = 2,
};
enum class GCLevel : u32 {
Aggressive = 0,
Normal = 1,
Relaxed = 2,
};
template <typename Type>
class Setting final {
public:
@@ -135,6 +129,7 @@ struct Values {
Setting<bool> cpuopt_unsafe_unfuse_fma;
Setting<bool> cpuopt_unsafe_reduce_fp_error;
Setting<bool> cpuopt_unsafe_ignore_standard_fpcr;
Setting<bool> cpuopt_unsafe_inaccurate_nan;
Setting<bool> cpuopt_unsafe_fastmem_check;
@@ -151,14 +146,15 @@ struct Values {
Setting<u16> frame_limit;
Setting<bool> use_disk_shader_cache;
Setting<GPUAccuracy> gpu_accuracy;
Setting<bool> use_garbage_collect;
Setting<GCLevel> garbage_collect_level;
Setting<bool> use_asynchronous_gpu_emulation;
Setting<bool> use_nvdec_emulation;
Setting<bool> accelerate_astc;
Setting<bool> use_vsync;
Setting<bool> disable_fps_limit;
Setting<bool> use_assembly_shaders;
Setting<bool> use_asynchronous_shaders;
Setting<bool> use_fast_gpu_time;
Setting<bool> use_caches_gc;
Setting<float> bg_red;
Setting<float> bg_green;
@@ -226,6 +222,7 @@ struct Values {
std::string program_args;
bool dump_exefs;
bool dump_nso;
bool enable_fs_access_log;
bool reporting_services;
bool quest_flag;
bool disable_macro_jit;
@@ -261,9 +258,6 @@ bool IsGPULevelHigh();
bool IsFastmemEnabled();
bool UseGarbageCollect();
std::chrono::minutes GarbageCollectTimer();
float Volume();
std::string GetTimeZoneString();

View File

@@ -139,6 +139,7 @@ add_library(core STATIC
frontend/input.h
hardware_interrupt_manager.cpp
hardware_interrupt_manager.h
hle/api_version.h
hle/ipc.h
hle/ipc_helpers.h
hle/kernel/board/nintendo/nx/k_system_control.cpp
@@ -550,6 +551,8 @@ add_library(core STATIC
hle/service/spl/module.h
hle/service/spl/spl.cpp
hle/service/spl/spl.h
hle/service/spl/spl_results.h
hle/service/spl/spl_types.h
hle/service/ssl/ssl.cpp
hle/service/ssl/ssl.h
hle/service/time/clock_types.h
@@ -651,17 +654,14 @@ endif()
if (MSVC)
target_compile_options(core PRIVATE
/we4018 # 'expression' : signed/unsigned mismatch
/we4244 # 'argument' : conversion from 'type1' to 'type2', possible loss of data (floating-point)
/we4245 # 'conversion' : conversion from 'type1' to 'type2', signed/unsigned mismatch
/we4242 # 'identifier': conversion from 'type1' to 'type2', possible loss of data
/we4244 # 'conversion': conversion from 'type1' to 'type2', possible loss of data
/we4245 # 'conversion': conversion from 'type1' to 'type2', signed/unsigned mismatch
/we4254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data
/we4267 # 'var' : conversion from 'size_t' to 'type', possible loss of data
/we4305 # 'context' : truncation from 'type1' to 'type2'
/we4456 # Declaration of 'identifier' hides previous local declaration
/we4457 # Declaration of 'identifier' hides function parameter
/we4458 # Declaration of 'identifier' hides class member
/we4459 # Declaration of 'identifier' hides global declaration
/we4715 # 'function' : not all control paths return a value
)
else()
target_compile_options(core PRIVATE

View File

@@ -8,6 +8,7 @@
#include <dynarmic/interface/A32/config.h>
#include <dynarmic/interface/A32/context.h>
#include "common/assert.h"
#include "common/literals.h"
#include "common/logging/log.h"
#include "common/page_table.h"
#include "common/settings.h"
@@ -22,6 +23,8 @@
namespace Core {
using namespace Common::Literals;
class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks {
public:
explicit DynarmicCallbacks32(ARM_Dynarmic_32& parent_)
@@ -143,8 +146,8 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable*
config.wall_clock_cntpct = uses_wall_clock;
// Code cache size
config.code_cache_size = 512 * 1024 * 1024;
config.far_code_offset = 400 * 1024 * 1024;
config.code_cache_size = 512_MiB;
config.far_code_offset = 400_MiB;
// Safe optimizations
if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::DebugMode) {
@@ -186,6 +189,9 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable*
if (Settings::values.cpuopt_unsafe_reduce_fp_error.GetValue()) {
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_ReducedErrorFP;
}
if (Settings::values.cpuopt_unsafe_ignore_standard_fpcr.GetValue()) {
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_IgnoreStandardFPCRValue;
}
if (Settings::values.cpuopt_unsafe_inaccurate_nan.GetValue()) {
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_InaccurateNaN;
}

View File

@@ -7,6 +7,7 @@
#include <dynarmic/interface/A64/a64.h>
#include <dynarmic/interface/A64/config.h>
#include "common/assert.h"
#include "common/literals.h"
#include "common/logging/log.h"
#include "common/page_table.h"
#include "common/settings.h"
@@ -24,6 +25,7 @@
namespace Core {
using Vector = Dynarmic::A64::Vector;
using namespace Common::Literals;
class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks {
public:
@@ -184,8 +186,8 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable*
config.wall_clock_cntpct = uses_wall_clock;
// Code cache size
config.code_cache_size = 512 * 1024 * 1024;
config.far_code_offset = 400 * 1024 * 1024;
config.code_cache_size = 512_MiB;
config.far_code_offset = 400_MiB;
// Safe optimizations
if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::DebugMode) {

View File

@@ -3,6 +3,7 @@
// Refer to the license.txt file included.
#include <array>
#include <atomic>
#include <memory>
#include <utility>
@@ -377,7 +378,7 @@ struct System::Impl {
std::unique_ptr<Core::DeviceMemory> device_memory;
Core::Memory::Memory memory;
CpuManager cpu_manager;
bool is_powered_on = false;
std::atomic_bool is_powered_on{};
bool exit_lock = false;
Reporter reporter;
@@ -463,7 +464,7 @@ System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::st
}
bool System::IsPoweredOn() const {
return impl->is_powered_on;
return impl->is_powered_on.load(std::memory_order::relaxed);
}
void System::PrepareReschedule() {

View File

@@ -835,7 +835,7 @@ void KeyManager::SetKey(S128KeyType id, Key128 key, u64 field1, u64 field2) {
"key_area_key_ocean_{:02X}",
"key_area_key_system_{:02X}",
};
WriteKeyToFile(category, fmt::format(kak_names.at(field2), field1), key);
WriteKeyToFile(category, fmt::format(fmt::runtime(kak_names.at(field2)), field1), key);
} else if (id == S128KeyType::Master) {
WriteKeyToFile(category, fmt::format("master_key_{:02X}", field1), key);
} else if (id == S128KeyType::Package1) {

View File

@@ -58,14 +58,17 @@ static bool FollowsNcaIdFormat(std::string_view name) {
static std::string GetRelativePathFromNcaID(const std::array<u8, 16>& nca_id, bool second_hex_upper,
bool within_two_digit, bool cnmt_suffix) {
if (!within_two_digit)
return fmt::format(cnmt_suffix ? "{}.cnmt.nca" : "/{}.nca",
Common::HexToString(nca_id, second_hex_upper));
if (!within_two_digit) {
const auto format_str = fmt::runtime(cnmt_suffix ? "{}.cnmt.nca" : "/{}.nca");
return fmt::format(format_str, Common::HexToString(nca_id, second_hex_upper));
}
Core::Crypto::SHA256Hash hash{};
mbedtls_sha256_ret(nca_id.data(), nca_id.size(), hash.data(), 0);
return fmt::format(cnmt_suffix ? "/000000{:02X}/{}.cnmt.nca" : "/000000{:02X}/{}.nca", hash[0],
Common::HexToString(nca_id, second_hex_upper));
const auto format_str =
fmt::runtime(cnmt_suffix ? "/000000{:02X}/{}.cnmt.nca" : "/000000{:02X}/{}.nca");
return fmt::format(format_str, hash[0], Common::HexToString(nca_id, second_hex_upper));
}
static std::string GetCNMTName(TitleType type, u64 title_id) {

View File

@@ -4,47 +4,29 @@
#include "core/file_sys/system_archive/system_version.h"
#include "core/file_sys/vfs_vector.h"
#include "core/hle/api_version.h"
namespace FileSys::SystemArchive {
namespace SystemVersionData {
// This section should reflect the best system version to describe yuzu's HLE api.
// TODO(DarkLordZach): Update when HLE gets better.
constexpr u8 VERSION_MAJOR = 11;
constexpr u8 VERSION_MINOR = 0;
constexpr u8 VERSION_MICRO = 1;
constexpr u8 REVISION_MAJOR = 1;
constexpr u8 REVISION_MINOR = 0;
constexpr char PLATFORM_STRING[] = "NX";
constexpr char VERSION_HASH[] = "69103fcb2004dace877094c2f8c29e6113be5dbf";
constexpr char DISPLAY_VERSION[] = "11.0.1";
constexpr char DISPLAY_TITLE[] = "NintendoSDK Firmware for NX 11.0.1-1.0";
} // namespace SystemVersionData
std::string GetLongDisplayVersion() {
return SystemVersionData::DISPLAY_TITLE;
return HLE::ApiVersion::DISPLAY_TITLE;
}
VirtualDir SystemVersion() {
VirtualFile file = std::make_shared<VectorVfsFile>(std::vector<u8>(0x100), "file");
file->WriteObject(SystemVersionData::VERSION_MAJOR, 0);
file->WriteObject(SystemVersionData::VERSION_MINOR, 1);
file->WriteObject(SystemVersionData::VERSION_MICRO, 2);
file->WriteObject(SystemVersionData::REVISION_MAJOR, 4);
file->WriteObject(SystemVersionData::REVISION_MINOR, 5);
file->WriteArray(SystemVersionData::PLATFORM_STRING,
std::min<u64>(sizeof(SystemVersionData::PLATFORM_STRING), 0x20ULL), 0x8);
file->WriteArray(SystemVersionData::VERSION_HASH,
std::min<u64>(sizeof(SystemVersionData::VERSION_HASH), 0x40ULL), 0x28);
file->WriteArray(SystemVersionData::DISPLAY_VERSION,
std::min<u64>(sizeof(SystemVersionData::DISPLAY_VERSION), 0x18ULL), 0x68);
file->WriteArray(SystemVersionData::DISPLAY_TITLE,
std::min<u64>(sizeof(SystemVersionData::DISPLAY_TITLE), 0x80ULL), 0x80);
file->WriteObject(HLE::ApiVersion::HOS_VERSION_MAJOR, 0);
file->WriteObject(HLE::ApiVersion::HOS_VERSION_MINOR, 1);
file->WriteObject(HLE::ApiVersion::HOS_VERSION_MICRO, 2);
file->WriteObject(HLE::ApiVersion::SDK_REVISION_MAJOR, 4);
file->WriteObject(HLE::ApiVersion::SDK_REVISION_MINOR, 5);
file->WriteArray(HLE::ApiVersion::PLATFORM_STRING,
std::min<u64>(sizeof(HLE::ApiVersion::PLATFORM_STRING), 0x20ULL), 0x8);
file->WriteArray(HLE::ApiVersion::VERSION_HASH,
std::min<u64>(sizeof(HLE::ApiVersion::VERSION_HASH), 0x40ULL), 0x28);
file->WriteArray(HLE::ApiVersion::DISPLAY_VERSION,
std::min<u64>(sizeof(HLE::ApiVersion::DISPLAY_VERSION), 0x18ULL), 0x68);
file->WriteArray(HLE::ApiVersion::DISPLAY_TITLE,
std::min<u64>(sizeof(HLE::ApiVersion::DISPLAY_TITLE), 0x80ULL), 0x80);
return std::make_shared<VectorVfsDirectory>(std::vector<VirtualFile>{file},
std::vector<VirtualDir>{}, "data");
}

View File

@@ -6,7 +6,6 @@
#include <numeric>
#include <string>
#include "common/fs/path_util.h"
#include "common/logging/backend.h"
#include "core/file_sys/mode.h"
#include "core/file_sys/vfs.h"

View File

@@ -14,7 +14,6 @@
#endif
#include "common/fs/path_util.h"
#include "common/logging/backend.h"
#include "core/file_sys/vfs.h"
#include "core/file_sys/vfs_libzip.h"
#include "core/file_sys/vfs_vector.h"

View File

@@ -24,17 +24,12 @@ constexpr FS::FileAccessMode ModeFlagsToFileAccessMode(Mode mode) {
case Mode::Read:
return FS::FileAccessMode::Read;
case Mode::Write:
return FS::FileAccessMode::Write;
case Mode::ReadWrite:
return FS::FileAccessMode::ReadWrite;
case Mode::Append:
return FS::FileAccessMode::Append;
case Mode::ReadAppend:
return FS::FileAccessMode::ReadAppend;
case Mode::WriteAppend:
return FS::FileAccessMode::Append;
case Mode::All:
return FS::FileAccessMode::ReadAppend;
return FS::FileAccessMode::ReadWrite;
default:
return {};
}

View File

@@ -4,6 +4,7 @@
#pragma once
#include <functional>
#include <memory>
#include <string>
#include <tuple>

View File

@@ -0,0 +1,40 @@
// Copyright 2021 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include "common/common_types.h"
// This file contains yuzu's HLE API version constants.
namespace HLE::ApiVersion {
// Horizon OS version constants.
constexpr u8 HOS_VERSION_MAJOR = 11;
constexpr u8 HOS_VERSION_MINOR = 0;
constexpr u8 HOS_VERSION_MICRO = 1;
// NintendoSDK version constants.
constexpr u8 SDK_REVISION_MAJOR = 1;
constexpr u8 SDK_REVISION_MINOR = 0;
constexpr char PLATFORM_STRING[] = "NX";
constexpr char VERSION_HASH[] = "69103fcb2004dace877094c2f8c29e6113be5dbf";
constexpr char DISPLAY_VERSION[] = "11.0.1";
constexpr char DISPLAY_TITLE[] = "NintendoSDK Firmware for NX 11.0.1-1.0";
// Atmosphere version constants.
constexpr u8 ATMOSPHERE_RELEASE_VERSION_MAJOR = 0;
constexpr u8 ATMOSPHERE_RELEASE_VERSION_MINOR = 19;
constexpr u8 ATMOSPHERE_RELEASE_VERSION_MICRO = 4;
constexpr u32 GetTargetFirmware() {
return u32{HOS_VERSION_MAJOR} << 24 | u32{HOS_VERSION_MINOR} << 16 |
u32{HOS_VERSION_MICRO} << 8 | 0U;
}
} // namespace HLE::ApiVersion

View File

@@ -345,8 +345,12 @@ public:
explicit RequestParser(u32* command_buffer) : RequestHelperBase(command_buffer) {}
explicit RequestParser(Kernel::HLERequestContext& ctx) : RequestHelperBase(ctx) {
ASSERT_MSG(ctx.GetDataPayloadOffset(), "context is incomplete");
Skip(ctx.GetDataPayloadOffset(), false);
// TIPC does not have data payload offset
if (!ctx.IsTipc()) {
ASSERT_MSG(ctx.GetDataPayloadOffset(), "context is incomplete");
Skip(ctx.GetDataPayloadOffset(), false);
}
// Skip the u64 command id, it's already stored in the context
static constexpr u32 CommandIdSize = 2;
Skip(CommandIdSize, false);

View File

@@ -4,7 +4,8 @@
#include <random>
#include "common/common_sizes.h"
#include "common/literals.h"
#include "core/hle/kernel/board/nintendo/nx/k_system_control.h"
#include "core/hle/kernel/board/nintendo/nx/secure_monitor.h"
#include "core/hle/kernel/k_trace.h"
@@ -25,6 +26,8 @@ constexpr const std::size_t RequiredNonSecureSystemMemorySize =
namespace {
using namespace Common::Literals;
u32 GetMemoryModeForInit() {
return 0x01;
}
@@ -57,11 +60,11 @@ size_t KSystemControl::Init::GetIntendedMemorySize() {
switch (GetMemorySizeForInit()) {
case Smc::MemorySize_4GB:
default: // All invalid modes should go to 4GB.
return Common::Size_4_GB;
return 4_GiB;
case Smc::MemorySize_6GB:
return Common::Size_6_GB;
return 6_GiB;
case Smc::MemorySize_8GB:
return Common::Size_8_GB;
return 8_GiB;
}
}
@@ -79,17 +82,17 @@ std::size_t KSystemControl::Init::GetApplicationPoolSize() {
switch (GetMemoryArrangeForInit()) {
case Smc::MemoryArrangement_4GB:
default:
return Common::Size_3285_MB;
return 3285_MiB;
case Smc::MemoryArrangement_4GBForAppletDev:
return Common::Size_2048_MB;
return 2048_MiB;
case Smc::MemoryArrangement_4GBForSystemDev:
return Common::Size_3285_MB;
return 3285_MiB;
case Smc::MemoryArrangement_6GB:
return Common::Size_4916_MB;
return 4916_MiB;
case Smc::MemoryArrangement_6GBForAppletDev:
return Common::Size_3285_MB;
return 3285_MiB;
case Smc::MemoryArrangement_8GB:
return Common::Size_4916_MB;
return 4916_MiB;
}
}();
@@ -103,22 +106,22 @@ size_t KSystemControl::Init::GetAppletPoolSize() {
switch (GetMemoryArrangeForInit()) {
case Smc::MemoryArrangement_4GB:
default:
return Common::Size_507_MB;
return 507_MiB;
case Smc::MemoryArrangement_4GBForAppletDev:
return Common::Size_1554_MB;
return 1554_MiB;
case Smc::MemoryArrangement_4GBForSystemDev:
return Common::Size_448_MB;
return 448_MiB;
case Smc::MemoryArrangement_6GB:
return Common::Size_562_MB;
return 562_MiB;
case Smc::MemoryArrangement_6GBForAppletDev:
return Common::Size_2193_MB;
return 2193_MiB;
case Smc::MemoryArrangement_8GB:
return Common::Size_2193_MB;
return 2193_MiB;
}
}();
// Return (possibly) adjusted size.
constexpr size_t ExtraSystemMemoryForAtmosphere = Common::Size_33_MB;
constexpr size_t ExtraSystemMemoryForAtmosphere = 33_MiB;
return base_pool_size - ExtraSystemMemoryForAtmosphere - KTraceBufferSize;
}

View File

@@ -5,34 +5,37 @@
#include <array>
#include "common/assert.h"
#include "common/common_sizes.h"
#include "common/literals.h"
#include "core/hle/kernel/k_address_space_info.h"
namespace Kernel {
namespace {
using namespace Common::Literals;
constexpr u64 Size_Invalid = UINT64_MAX;
// clang-format off
constexpr std::array<KAddressSpaceInfo, 13> AddressSpaceInfos{{
{ .bit_width = 32, .address = Common::Size_2_MB , .size = Common::Size_1_GB - Common::Size_2_MB , .type = KAddressSpaceInfo::Type::MapSmall, },
{ .bit_width = 32, .address = Common::Size_1_GB , .size = Common::Size_4_GB - Common::Size_1_GB , .type = KAddressSpaceInfo::Type::MapLarge, },
{ .bit_width = 32, .address = Common::Size_Invalid, .size = Common::Size_1_GB , .type = KAddressSpaceInfo::Type::Alias, },
{ .bit_width = 32, .address = Common::Size_Invalid, .size = Common::Size_1_GB , .type = KAddressSpaceInfo::Type::Heap, },
{ .bit_width = 36, .address = Common::Size_128_MB , .size = Common::Size_2_GB - Common::Size_128_MB, .type = KAddressSpaceInfo::Type::MapSmall, },
{ .bit_width = 36, .address = Common::Size_2_GB , .size = Common::Size_64_GB - Common::Size_2_GB , .type = KAddressSpaceInfo::Type::MapLarge, },
{ .bit_width = 36, .address = Common::Size_Invalid, .size = Common::Size_6_GB , .type = KAddressSpaceInfo::Type::Heap, },
{ .bit_width = 36, .address = Common::Size_Invalid, .size = Common::Size_6_GB , .type = KAddressSpaceInfo::Type::Alias, },
{ .bit_width = 39, .address = Common::Size_128_MB , .size = Common::Size_512_GB - Common::Size_128_MB, .type = KAddressSpaceInfo::Type::Map39Bit, },
{ .bit_width = 39, .address = Common::Size_Invalid, .size = Common::Size_64_GB , .type = KAddressSpaceInfo::Type::MapSmall },
{ .bit_width = 39, .address = Common::Size_Invalid, .size = Common::Size_6_GB , .type = KAddressSpaceInfo::Type::Heap, },
{ .bit_width = 39, .address = Common::Size_Invalid, .size = Common::Size_64_GB , .type = KAddressSpaceInfo::Type::Alias, },
{ .bit_width = 39, .address = Common::Size_Invalid, .size = Common::Size_2_GB , .type = KAddressSpaceInfo::Type::Stack, },
{ .bit_width = 32, .address = 2_MiB , .size = 1_GiB - 2_MiB , .type = KAddressSpaceInfo::Type::MapSmall, },
{ .bit_width = 32, .address = 1_GiB , .size = 4_GiB - 1_GiB , .type = KAddressSpaceInfo::Type::MapLarge, },
{ .bit_width = 32, .address = Size_Invalid, .size = 1_GiB , .type = KAddressSpaceInfo::Type::Alias, },
{ .bit_width = 32, .address = Size_Invalid, .size = 1_GiB , .type = KAddressSpaceInfo::Type::Heap, },
{ .bit_width = 36, .address = 128_MiB , .size = 2_GiB - 128_MiB, .type = KAddressSpaceInfo::Type::MapSmall, },
{ .bit_width = 36, .address = 2_GiB , .size = 64_GiB - 2_GiB , .type = KAddressSpaceInfo::Type::MapLarge, },
{ .bit_width = 36, .address = Size_Invalid, .size = 6_GiB , .type = KAddressSpaceInfo::Type::Heap, },
{ .bit_width = 36, .address = Size_Invalid, .size = 6_GiB , .type = KAddressSpaceInfo::Type::Alias, },
{ .bit_width = 39, .address = 128_MiB , .size = 512_GiB - 128_MiB, .type = KAddressSpaceInfo::Type::Map39Bit, },
{ .bit_width = 39, .address = Size_Invalid, .size = 64_GiB , .type = KAddressSpaceInfo::Type::MapSmall },
{ .bit_width = 39, .address = Size_Invalid, .size = 6_GiB , .type = KAddressSpaceInfo::Type::Heap, },
{ .bit_width = 39, .address = Size_Invalid, .size = 64_GiB , .type = KAddressSpaceInfo::Type::Alias, },
{ .bit_width = 39, .address = Size_Invalid, .size = 2_GiB , .type = KAddressSpaceInfo::Type::Stack, },
}};
// clang-format on
constexpr bool IsAllowedIndexForAddress(std::size_t index) {
return index < AddressSpaceInfos.size() &&
AddressSpaceInfos[index].address != Common::Size_Invalid;
return index < AddressSpaceInfos.size() && AddressSpaceInfos[index].address != Size_Invalid;
}
using IndexArray =

View File

@@ -3,6 +3,7 @@
// Refer to the license.txt file included.
#include "common/alignment.h"
#include "common/literals.h"
#include "core/hle/kernel/k_memory_layout.h"
#include "core/hle/kernel/k_memory_manager.h"
#include "core/hle/kernel/k_system_control.h"
@@ -12,8 +13,10 @@ namespace Kernel {
namespace {
using namespace Common::Literals;
constexpr size_t CarveoutAlignment = 0x20000;
constexpr size_t CarveoutSizeMax = (512ULL * 1024 * 1024) - CarveoutAlignment;
constexpr size_t CarveoutSizeMax = (512_MiB) - CarveoutAlignment;
bool SetupPowerManagementControllerMemoryRegion(KMemoryLayout& memory_layout) {
// Above firmware 2.0.0, the PMC is not mappable.

View File

@@ -7,8 +7,7 @@
#include <utility>
#include "common/alignment.h"
#include "common/common_sizes.h"
#include "common/common_types.h"
#include "common/literals.h"
#include "core/device_memory.h"
#include "core/hle/kernel/k_memory_region.h"
#include "core/hle/kernel/k_memory_region_type.h"
@@ -16,20 +15,22 @@
namespace Kernel {
constexpr std::size_t L1BlockSize = Common::Size_1_GB;
constexpr std::size_t L2BlockSize = Common::Size_2_MB;
using namespace Common::Literals;
constexpr std::size_t L1BlockSize = 1_GiB;
constexpr std::size_t L2BlockSize = 2_MiB;
constexpr std::size_t GetMaximumOverheadSize(std::size_t size) {
return (Common::DivideUp(size, L1BlockSize) + Common::DivideUp(size, L2BlockSize)) * PageSize;
}
constexpr std::size_t MainMemorySize = Common::Size_4_GB;
constexpr std::size_t MainMemorySizeMax = Common::Size_8_GB;
constexpr std::size_t MainMemorySize = 4_GiB;
constexpr std::size_t MainMemorySizeMax = 8_GiB;
constexpr std::size_t ReservedEarlyDramSize = 0x60000;
constexpr std::size_t ReservedEarlyDramSize = 384_KiB;
constexpr std::size_t DramPhysicalAddress = 0x80000000;
constexpr std::size_t KernelAslrAlignment = Common::Size_2_MB;
constexpr std::size_t KernelAslrAlignment = 2_MiB;
constexpr std::size_t KernelVirtualAddressSpaceWidth = 1ULL << 39;
constexpr std::size_t KernelPhysicalAddressSpaceWidth = 1ULL << 48;
@@ -40,7 +41,7 @@ constexpr std::size_t KernelVirtualAddressSpaceLast = KernelVirtualAddressSpaceE
constexpr std::size_t KernelVirtualAddressSpaceSize =
KernelVirtualAddressSpaceEnd - KernelVirtualAddressSpaceBase;
constexpr std::size_t KernelVirtualAddressCodeBase = KernelVirtualAddressSpaceBase;
constexpr std::size_t KernelVirtualAddressCodeSize = 0x62000;
constexpr std::size_t KernelVirtualAddressCodeSize = 392_KiB;
constexpr std::size_t KernelVirtualAddressCodeEnd =
KernelVirtualAddressCodeBase + KernelVirtualAddressCodeSize;
@@ -53,14 +54,14 @@ constexpr std::size_t KernelPhysicalAddressSpaceSize =
constexpr std::size_t KernelPhysicalAddressCodeBase = DramPhysicalAddress + ReservedEarlyDramSize;
constexpr std::size_t KernelPageTableHeapSize = GetMaximumOverheadSize(MainMemorySizeMax);
constexpr std::size_t KernelInitialPageHeapSize = Common::Size_128_KB;
constexpr std::size_t KernelInitialPageHeapSize = 128_KiB;
constexpr std::size_t KernelSlabHeapDataSize = Common::Size_5_MB;
constexpr std::size_t KernelSlabHeapGapsSize = Common::Size_2_MB - Common::Size_64_KB;
constexpr std::size_t KernelSlabHeapDataSize = 5_MiB;
constexpr std::size_t KernelSlabHeapGapsSize = 2_MiB - 64_KiB;
constexpr std::size_t KernelSlabHeapSize = KernelSlabHeapDataSize + KernelSlabHeapGapsSize;
// NOTE: This is calculated from KThread slab counts, assuming KThread size <= 0x860.
constexpr std::size_t KernelSlabHeapAdditionalSize = 0x68000ULL;
constexpr std::size_t KernelSlabHeapAdditionalSize = 416_KiB;
constexpr std::size_t KernelResourceSize =
KernelPageTableHeapSize + KernelInitialPageHeapSize + KernelSlabHeapSize;

View File

@@ -4,6 +4,7 @@
#include "common/alignment.h"
#include "common/assert.h"
#include "common/literals.h"
#include "common/scope_exit.h"
#include "core/core.h"
#include "core/hle/kernel/k_address_space_info.h"
@@ -23,6 +24,8 @@ namespace Kernel {
namespace {
using namespace Common::Literals;
constexpr std::size_t GetAddressSpaceWidthFromType(FileSys::ProgramAddressSpaceType as_type) {
switch (as_type) {
case FileSys::ProgramAddressSpaceType::Is32Bit:
@@ -89,7 +92,7 @@ ResultCode KPageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_
}
// Set code regions and determine remaining
constexpr std::size_t RegionAlignment{2 * 1024 * 1024};
constexpr std::size_t RegionAlignment{2_MiB};
VAddr process_code_start{};
VAddr process_code_end{};
std::size_t stack_region_size{};

View File

@@ -79,6 +79,7 @@ ResultCode KResourceLimit::SetLimitValue(LimitableResource which, s64 value) {
R_UNLESS(current_values[index] <= value, ResultInvalidState);
limit_values[index] = value;
peak_values[index] = current_values[index];
return ResultSuccess;
}

View File

@@ -4,9 +4,13 @@
#pragma once
#include "common/common_funcs.h"
namespace Kernel {
using namespace Common::Literals;
constexpr bool IsKTraceEnabled = false;
constexpr std::size_t KTraceBufferSize = IsKTraceEnabled ? 16 * 1024 * 1024 : 0;
constexpr std::size_t KTraceBufferSize = IsKTraceEnabled ? 16_MiB : 0;
} // namespace Kernel

View File

@@ -12,7 +12,6 @@
#include <utility>
#include "common/assert.h"
#include "common/common_sizes.h"
#include "common/logging/log.h"
#include "common/microprofile.h"
#include "common/thread.h"
@@ -180,7 +179,7 @@ struct KernelCore::Impl {
system_resource_limit->Reserve(LimitableResource::PhysicalMemory, kernel_size);
// Reserve secure applet memory, introduced in firmware 5.0.0
constexpr u64 secure_applet_memory_size{Common::Size_4_MB};
constexpr u64 secure_applet_memory_size{4_MiB};
ASSERT(system_resource_limit->Reserve(LimitableResource::PhysicalMemory,
secure_applet_memory_size));
@@ -320,8 +319,8 @@ struct KernelCore::Impl {
const VAddr code_end_virt_addr = KernelVirtualAddressCodeEnd;
// Setup the containing kernel region.
constexpr size_t KernelRegionSize = Common::Size_1_GB;
constexpr size_t KernelRegionAlign = Common::Size_1_GB;
constexpr size_t KernelRegionSize = 1_GiB;
constexpr size_t KernelRegionAlign = 1_GiB;
constexpr VAddr kernel_region_start =
Common::AlignDown(code_start_virt_addr, KernelRegionAlign);
size_t kernel_region_size = KernelRegionSize;
@@ -368,7 +367,7 @@ struct KernelCore::Impl {
// Decide on the actual size for the misc region.
constexpr size_t MiscRegionAlign = KernelAslrAlignment;
constexpr size_t MiscRegionMinimumSize = Common::Size_32_MB;
constexpr size_t MiscRegionMinimumSize = 32_MiB;
const size_t misc_region_size = Common::AlignUp(
std::max(misc_region_needed_size, MiscRegionMinimumSize), MiscRegionAlign);
ASSERT(misc_region_size > 0);
@@ -381,7 +380,7 @@ struct KernelCore::Impl {
misc_region_start, misc_region_size, KMemoryRegionType_KernelMisc));
// Setup the stack region.
constexpr size_t StackRegionSize = Common::Size_14_MB;
constexpr size_t StackRegionSize = 14_MiB;
constexpr size_t StackRegionAlign = KernelAslrAlignment;
const VAddr stack_region_start =
memory_layout.GetVirtualMemoryRegionTree().GetRandomAlignedRegion(
@@ -414,7 +413,7 @@ struct KernelCore::Impl {
slab_region_start, slab_region_size, KMemoryRegionType_KernelSlab));
// Setup the temp region.
constexpr size_t TempRegionSize = Common::Size_128_MB;
constexpr size_t TempRegionSize = 128_MiB;
constexpr size_t TempRegionAlign = KernelAslrAlignment;
const VAddr temp_region_start =
memory_layout.GetVirtualMemoryRegionTree().GetRandomAlignedRegion(
@@ -470,7 +469,7 @@ struct KernelCore::Impl {
// Determine size available for kernel page table heaps, requiring > 8 MB.
const PAddr resource_end_phys_addr = slab_start_phys_addr + resource_region_size;
const size_t page_table_heap_size = resource_end_phys_addr - slab_end_phys_addr;
ASSERT(page_table_heap_size / Common::Size_4_MB > 2);
ASSERT(page_table_heap_size / 4_MiB > 2);
// Insert a physical region for the kernel page table heap region
ASSERT(memory_layout.GetPhysicalMemoryRegionTree().Insert(
@@ -495,7 +494,7 @@ struct KernelCore::Impl {
ASSERT(linear_extents.GetEndAddress() != 0);
// Setup the linear mapping region.
constexpr size_t LinearRegionAlign = Common::Size_1_GB;
constexpr size_t LinearRegionAlign = 1_GiB;
const PAddr aligned_linear_phys_start =
Common::AlignDown(linear_extents.GetAddress(), LinearRegionAlign);
const size_t linear_region_size =

View File

@@ -117,7 +117,7 @@ AOC_U::AOC_U(Core::System& system_)
{7, &AOC_U::PrepareAddOnContent, "PrepareAddOnContent"},
{8, &AOC_U::GetAddOnContentListChangedEvent, "GetAddOnContentListChangedEvent"},
{9, nullptr, "GetAddOnContentLostErrorCode"},
{10, nullptr, "GetAddOnContentListChangedEventWithProcessId"},
{10, &AOC_U::GetAddOnContentListChangedEventWithProcessId, "GetAddOnContentListChangedEventWithProcessId"},
{100, &AOC_U::CreateEcPurchasedEventManager, "CreateEcPurchasedEventManager"},
{101, &AOC_U::CreatePermanentEcPurchasedEventManager, "CreatePermanentEcPurchasedEventManager"},
{110, nullptr, "CreateContentsServiceManager"},
@@ -257,6 +257,14 @@ void AOC_U::GetAddOnContentListChangedEvent(Kernel::HLERequestContext& ctx) {
rb.PushCopyObjects(aoc_change_event.GetReadableEvent());
}
void AOC_U::GetAddOnContentListChangedEventWithProcessId(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AOC, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(ResultSuccess);
rb.PushCopyObjects(aoc_change_event.GetReadableEvent());
}
void AOC_U::CreateEcPurchasedEventManager(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_AOC, "(STUBBED) called");

View File

@@ -28,6 +28,7 @@ private:
void GetAddOnContentBaseId(Kernel::HLERequestContext& ctx);
void PrepareAddOnContent(Kernel::HLERequestContext& ctx);
void GetAddOnContentListChangedEvent(Kernel::HLERequestContext& ctx);
void GetAddOnContentListChangedEventWithProcessId(Kernel::HLERequestContext& ctx);
void CreateEcPurchasedEventManager(Kernel::HLERequestContext& ctx);
void CreatePermanentEcPurchasedEventManager(Kernel::HLERequestContext& ctx);

View File

@@ -58,7 +58,7 @@ public:
{7, &IAudioOut::AppendAudioOutBufferImpl, "AppendAudioOutBufferAuto"},
{8, &IAudioOut::GetReleasedAudioOutBufferImpl, "GetReleasedAudioOutBufferAuto"},
{9, &IAudioOut::GetAudioOutBufferCount, "GetAudioOutBufferCount"},
{10, nullptr, "GetAudioOutPlayedSampleCount"},
{10, &IAudioOut::GetAudioOutPlayedSampleCount, "GetAudioOutPlayedSampleCount"},
{11, &IAudioOut::FlushAudioOutBuffers, "FlushAudioOutBuffers"},
{12, &IAudioOut::SetAudioOutVolume, "SetAudioOutVolume"},
{13, &IAudioOut::GetAudioOutVolume, "GetAudioOutVolume"},
@@ -186,6 +186,14 @@ private:
rb.Push(static_cast<u32>(stream->GetQueueSize()));
}
void GetAudioOutPlayedSampleCount(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Audio, "called");
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess);
rb.Push(stream->GetPlayedSampleCount());
}
void FlushAudioOutBuffers(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Audio, "called");

View File

@@ -253,7 +253,11 @@ void HwOpus::GetWorkBufferSize(Kernel::HLERequestContext& ctx) {
rb.Push<u32>(worker_buffer_sz);
}
void HwOpus::OpenOpusDecoder(Kernel::HLERequestContext& ctx) {
void HwOpus::GetWorkBufferSizeEx(Kernel::HLERequestContext& ctx) {
GetWorkBufferSize(ctx);
}
void HwOpus::OpenHardwareOpusDecoder(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto sample_rate = rp.Pop<u32>();
const auto channel_count = rp.Pop<u32>();
@@ -291,14 +295,47 @@ void HwOpus::OpenOpusDecoder(Kernel::HLERequestContext& ctx) {
system, OpusDecoderState{std::move(decoder), sample_rate, channel_count});
}
void HwOpus::OpenHardwareOpusDecoderEx(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto sample_rate = rp.Pop<u32>();
const auto channel_count = rp.Pop<u32>();
LOG_CRITICAL(Audio, "called sample_rate={}, channel_count={}", sample_rate, channel_count);
ASSERT_MSG(sample_rate == 48000 || sample_rate == 24000 || sample_rate == 16000 ||
sample_rate == 12000 || sample_rate == 8000,
"Invalid sample rate");
ASSERT_MSG(channel_count == 1 || channel_count == 2, "Invalid channel count");
const int num_stereo_streams = channel_count == 2 ? 1 : 0;
const auto mapping_table = CreateMappingTable(channel_count);
int error = 0;
OpusDecoderPtr decoder{
opus_multistream_decoder_create(sample_rate, static_cast<int>(channel_count), 1,
num_stereo_streams, mapping_table.data(), &error)};
if (error != OPUS_OK || decoder == nullptr) {
LOG_ERROR(Audio, "Failed to create Opus decoder (error={}).", error);
IPC::ResponseBuilder rb{ctx, 2};
// TODO(ogniK): Use correct error code
rb.Push(ResultUnknown);
return;
}
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<IHardwareOpusDecoderManager>(
system, OpusDecoderState{std::move(decoder), sample_rate, channel_count});
}
HwOpus::HwOpus(Core::System& system_) : ServiceFramework{system_, "hwopus"} {
static const FunctionInfo functions[] = {
{0, &HwOpus::OpenOpusDecoder, "OpenOpusDecoder"},
{0, &HwOpus::OpenHardwareOpusDecoder, "OpenHardwareOpusDecoder"},
{1, &HwOpus::GetWorkBufferSize, "GetWorkBufferSize"},
{2, nullptr, "OpenOpusDecoderForMultiStream"},
{3, nullptr, "GetWorkBufferSizeForMultiStream"},
{4, nullptr, "OpenHardwareOpusDecoderEx"},
{5, nullptr, "GetWorkBufferSizeEx"},
{4, &HwOpus::OpenHardwareOpusDecoderEx, "OpenHardwareOpusDecoderEx"},
{5, &HwOpus::GetWorkBufferSizeEx, "GetWorkBufferSizeEx"},
{6, nullptr, "OpenHardwareOpusDecoderForMultiStreamEx"},
{7, nullptr, "GetWorkBufferSizeForMultiStreamEx"},
};

View File

@@ -18,8 +18,10 @@ public:
~HwOpus() override;
private:
void OpenOpusDecoder(Kernel::HLERequestContext& ctx);
void OpenHardwareOpusDecoder(Kernel::HLERequestContext& ctx);
void OpenHardwareOpusDecoderEx(Kernel::HLERequestContext& ctx);
void GetWorkBufferSize(Kernel::HLERequestContext& ctx);
void GetWorkBufferSizeEx(Kernel::HLERequestContext& ctx);
};
} // namespace Service::Audio

View File

@@ -19,7 +19,6 @@
#include "common/fs/fs.h"
#include "common/fs/path_util.h"
#include "common/hex_util.h"
#include "common/logging/backend.h"
#include "common/logging/log.h"
#include "common/settings.h"
#include "core/core.h"
@@ -314,7 +313,7 @@ void SynchronizeInternal(AM::Applets::AppletManager& applet_manager, DirectoryGe
LOG_ERROR(Service_BCAT, "Boxcat synchronization failed with error '{}'!", res);
if (res == DownloadResult::NoMatchBuildId || res == DownloadResult::NoMatchTitleId) {
void(Common::FS::RemoveFile(zip_path));
Common::FS::RemoveFile(zip_path);
}
HandleDownloadDisplayResult(applet_manager, res);
@@ -446,7 +445,7 @@ std::optional<std::vector<u8>> Boxcat::GetLaunchParameter(TitleIDVersion title)
LOG_ERROR(Service_BCAT, "Boxcat synchronization failed with error '{}'!", res);
if (res == DownloadResult::NoMatchBuildId || res == DownloadResult::NoMatchTitleId) {
void(Common::FS::RemoveFile(bin_file_path));
Common::FS::RemoveFile(bin_file_path);
}
HandleDownloadDisplayResult(applet_manager, res);

View File

@@ -13,6 +13,7 @@
#include "common/common_types.h"
#include "common/hex_util.h"
#include "common/logging/log.h"
#include "common/settings.h"
#include "common/string_util.h"
#include "core/core.h"
#include "core/file_sys/directory.h"
@@ -785,6 +786,10 @@ FSP_SRV::FSP_SRV(Core::System& system_)
};
// clang-format on
RegisterHandlers(functions);
if (Settings::values.enable_fs_access_log) {
access_log_mode = AccessLogMode::SdCard;
}
}
FSP_SRV::~FSP_SRV() = default;
@@ -1041,9 +1046,9 @@ void FSP_SRV::DisableAutoSaveDataCreation(Kernel::HLERequestContext& ctx) {
void FSP_SRV::SetGlobalAccessLogMode(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
log_mode = rp.PopEnum<LogMode>();
access_log_mode = rp.PopEnum<AccessLogMode>();
LOG_DEBUG(Service_FS, "called, log_mode={:08X}", log_mode);
LOG_DEBUG(Service_FS, "called, access_log_mode={}", access_log_mode);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
@@ -1054,7 +1059,7 @@ void FSP_SRV::GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.PushEnum(log_mode);
rb.PushEnum(access_log_mode);
}
void FSP_SRV::OutputAccessLogToSdCard(Kernel::HLERequestContext& ctx) {
@@ -1062,9 +1067,9 @@ void FSP_SRV::OutputAccessLogToSdCard(Kernel::HLERequestContext& ctx) {
auto log = Common::StringFromFixedZeroTerminatedBuffer(
reinterpret_cast<const char*>(raw.data()), raw.size());
LOG_DEBUG(Service_FS, "called, log='{}'", log);
LOG_DEBUG(Service_FS, "called");
reporter.SaveFilesystemAccessReport(log_mode, std::move(log));
reporter.SaveFSAccessLog(log);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);

View File

@@ -24,11 +24,10 @@ enum class AccessLogVersion : u32 {
Latest = V7_0_0,
};
enum class LogMode : u32 {
Off,
enum class AccessLogMode : u32 {
None,
Log,
RedirectToSdCard,
LogToSdCard = Log | RedirectToSdCard,
SdCard,
};
class FSP_SRV final : public ServiceFramework<FSP_SRV> {
@@ -59,13 +58,12 @@ private:
FileSystemController& fsc;
const FileSys::ContentProvider& content_provider;
const Core::Reporter& reporter;
FileSys::VirtualFile romfs;
u64 current_process_id = 0;
u32 access_log_program_index = 0;
LogMode log_mode = LogMode::LogToSdCard;
const Core::Reporter& reporter;
AccessLogMode access_log_mode = AccessLogMode::None;
};
} // namespace Service::FileSystem

View File

@@ -314,6 +314,8 @@ void Controller_NPad::OnInit() {
void Controller_NPad::OnLoadInputDevices() {
const auto& players = Settings::values.players.GetValue();
std::lock_guard lock{mutex};
for (std::size_t i = 0; i < players.size(); ++i) {
std::transform(players[i].buttons.begin() + Settings::NativeButton::BUTTON_HID_BEGIN,
players[i].buttons.begin() + Settings::NativeButton::BUTTON_HID_END,
@@ -348,6 +350,8 @@ void Controller_NPad::OnRelease() {
}
void Controller_NPad::RequestPadStateUpdate(u32 npad_id) {
std::lock_guard lock{mutex};
const auto controller_idx = NPadIdToIndex(npad_id);
const auto controller_type = connected_controllers[controller_idx].type;
if (!connected_controllers[controller_idx].is_connected) {

View File

@@ -6,6 +6,8 @@
#include <array>
#include <atomic>
#include <mutex>
#include "common/bit_field.h"
#include "common/common_types.h"
#include "common/quaternion.h"
@@ -563,6 +565,8 @@ private:
using MotionArray = std::array<
std::array<std::unique_ptr<Input::MotionDevice>, Settings::NativeMotion::NUM_MOTIONS_HID>,
10>;
std::mutex mutex;
ButtonArray buttons;
StickArray sticks;
VibrationArray vibrations;

View File

@@ -236,7 +236,7 @@ Hid::Hid(Core::System& system_) : ServiceFramework{system_, "hid"} {
{80, &Hid::GetGyroscopeZeroDriftMode, "GetGyroscopeZeroDriftMode"},
{81, &Hid::ResetGyroscopeZeroDriftMode, "ResetGyroscopeZeroDriftMode"},
{82, &Hid::IsSixAxisSensorAtRest, "IsSixAxisSensorAtRest"},
{83, nullptr, "IsFirmwareUpdateAvailableForSixAxisSensor"},
{83, &Hid::IsFirmwareUpdateAvailableForSixAxisSensor, "IsFirmwareUpdateAvailableForSixAxisSensor"},
{91, &Hid::ActivateGesture, "ActivateGesture"},
{100, &Hid::SetSupportedNpadStyleSet, "SetSupportedNpadStyleSet"},
{101, &Hid::GetSupportedNpadStyleSet, "GetSupportedNpadStyleSet"},
@@ -710,6 +710,27 @@ void Hid::IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx) {
.IsSixAxisSensorAtRest());
}
void Hid::IsFirmwareUpdateAvailableForSixAxisSensor(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
struct Parameters {
Controller_NPad::DeviceHandle sixaxis_handle;
INSERT_PADDING_WORDS_NOINIT(1);
u64 applet_resource_user_id;
};
const auto parameters{rp.PopRaw<Parameters>()};
LOG_WARNING(
Service_HID,
"(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(false);
}
void Hid::ActivateGesture(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
struct Parameters {

View File

@@ -100,6 +100,7 @@ private:
void GetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx);
void ResetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx);
void IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx);
void IsFirmwareUpdateAvailableForSixAxisSensor(Kernel::HLERequestContext& ctx);
void ActivateGesture(Kernel::HLERequestContext& ctx);
void SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx);
void GetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx);

View File

@@ -51,6 +51,24 @@ struct hash<Service::LM::LogPacketHeaderEntry> {
} // namespace std
namespace Service::LM {
namespace {
std::string_view NameOf(LogSeverity severity) {
switch (severity) {
case LogSeverity::Trace:
return "TRACE";
case LogSeverity::Info:
return "INFO";
case LogSeverity::Warning:
return "WARNING";
case LogSeverity::Error:
return "ERROR";
case LogSeverity::Fatal:
return "FATAL";
default:
return "UNKNOWN";
}
}
} // Anonymous namespace
enum class LogDestination : u32 {
TargetManager = 1 << 0,
@@ -262,33 +280,8 @@ private:
if (text_log) {
output_log += fmt::format("Log Text: {}\n", *text_log);
}
switch (entry.severity) {
case LogSeverity::Trace:
LOG_DEBUG(Service_LM, "LogManager TRACE ({}):\n{}", DestinationToString(destination),
output_log);
break;
case LogSeverity::Info:
LOG_INFO(Service_LM, "LogManager INFO ({}):\n{}", DestinationToString(destination),
output_log);
break;
case LogSeverity::Warning:
LOG_WARNING(Service_LM, "LogManager WARNING ({}):\n{}",
DestinationToString(destination), output_log);
break;
case LogSeverity::Error:
LOG_ERROR(Service_LM, "LogManager ERROR ({}):\n{}", DestinationToString(destination),
output_log);
break;
case LogSeverity::Fatal:
LOG_CRITICAL(Service_LM, "LogManager FATAL ({}):\n{}", DestinationToString(destination),
output_log);
break;
default:
LOG_CRITICAL(Service_LM, "LogManager UNKNOWN ({}):\n{}",
DestinationToString(destination), output_log);
break;
}
LOG_DEBUG(Service_LM, "LogManager {} ({}):\n{}", NameOf(entry.severity),
DestinationToString(destination), output_log);
}
static std::string DestinationToString(LogDestination destination) {

View File

@@ -4,6 +4,8 @@
#pragma once
#include <array>
#include <vector>
#include "common/bit_field.h"
#include "common/common_funcs.h"
#include "common/uuid.h"

View File

@@ -307,6 +307,9 @@ void NVFlinger::Compose() {
}
s64 NVFlinger::GetNextTicks() const {
if (Settings::values.disable_fps_limit.GetValue()) {
return 0;
}
constexpr s64 max_hertz = 120LL;
return (1000000000 * (1LL << swap_interval)) / max_hertz;
}

View File

@@ -149,10 +149,10 @@ void ServiceFrameworkBase::ReportUnimplementedFunction(Kernel::HLERequestContext
std::string function_name = info == nullptr ? fmt::format("{}", ctx.GetCommand()) : info->name;
fmt::memory_buffer buf;
fmt::format_to(buf, "function '{}': port='{}' cmd_buf={{[0]=0x{:X}", function_name,
service_name, cmd_buf[0]);
fmt::format_to(std::back_inserter(buf), "function '{}': port='{}' cmd_buf={{[0]=0x{:X}",
function_name, service_name, cmd_buf[0]);
for (int i = 1; i <= 8; ++i) {
fmt::format_to(buf, ", [{}]=0x{:X}", i, cmd_buf[i]);
fmt::format_to(std::back_inserter(buf), ", [{}]=0x{:X}", i, cmd_buf[i]);
}
buf.push_back('}');

View File

@@ -9,7 +9,7 @@ namespace Service::SPL {
CSRNG::CSRNG(Core::System& system_, std::shared_ptr<Module> module_)
: Interface(system_, std::move(module_), "csrng") {
static const FunctionInfo functions[] = {
{0, &CSRNG::GetRandomBytes, "GetRandomBytes"},
{0, &CSRNG::GenerateRandomBytes, "GenerateRandomBytes"},
};
RegisterHandlers(functions);
}

View File

@@ -10,6 +10,7 @@
#include <vector>
#include "common/logging/log.h"
#include "common/settings.h"
#include "core/hle/api_version.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/service/spl/csrng.h"
#include "core/hle/service/spl/module.h"
@@ -24,7 +25,46 @@ Module::Interface::Interface(Core::System& system_, std::shared_ptr<Module> modu
Module::Interface::~Interface() = default;
void Module::Interface::GetRandomBytes(Kernel::HLERequestContext& ctx) {
void Module::Interface::GetConfig(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto config_item = rp.PopEnum<ConfigItem>();
// This should call svcCallSecureMonitor with the appropriate args.
// Since we do not have it implemented yet, we will use this for now.
const auto smc_result = GetConfigImpl(config_item);
const auto result_code = smc_result.Code();
if (smc_result.Failed()) {
LOG_ERROR(Service_SPL, "called, config_item={}, result_code={}", config_item,
result_code.raw);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(result_code);
}
LOG_DEBUG(Service_SPL, "called, config_item={}, result_code={}, smc_result={}", config_item,
result_code.raw, *smc_result);
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(result_code);
rb.Push(*smc_result);
}
void Module::Interface::ModularExponentiate(Kernel::HLERequestContext& ctx) {
UNIMPLEMENTED_MSG("ModularExponentiate is not implemented!");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSecureMonitorNotImplemented);
}
void Module::Interface::SetConfig(Kernel::HLERequestContext& ctx) {
UNIMPLEMENTED_MSG("SetConfig is not implemented!");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSecureMonitorNotImplemented);
}
void Module::Interface::GenerateRandomBytes(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_SPL, "called");
const std::size_t size = ctx.GetWriteBufferSize();
@@ -39,6 +79,88 @@ void Module::Interface::GetRandomBytes(Kernel::HLERequestContext& ctx) {
rb.Push(ResultSuccess);
}
void Module::Interface::IsDevelopment(Kernel::HLERequestContext& ctx) {
UNIMPLEMENTED_MSG("IsDevelopment is not implemented!");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSecureMonitorNotImplemented);
}
void Module::Interface::SetBootReason(Kernel::HLERequestContext& ctx) {
UNIMPLEMENTED_MSG("SetBootReason is not implemented!");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSecureMonitorNotImplemented);
}
void Module::Interface::GetBootReason(Kernel::HLERequestContext& ctx) {
UNIMPLEMENTED_MSG("GetBootReason is not implemented!");
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSecureMonitorNotImplemented);
}
ResultVal<u64> Module::Interface::GetConfigImpl(ConfigItem config_item) const {
switch (config_item) {
case ConfigItem::DisableProgramVerification:
case ConfigItem::DramId:
case ConfigItem::SecurityEngineInterruptNumber:
case ConfigItem::FuseVersion:
case ConfigItem::HardwareType:
case ConfigItem::HardwareState:
case ConfigItem::IsRecoveryBoot:
case ConfigItem::DeviceId:
case ConfigItem::BootReason:
case ConfigItem::MemoryMode:
case ConfigItem::IsDevelopmentFunctionEnabled:
case ConfigItem::KernelConfiguration:
case ConfigItem::IsChargerHiZModeEnabled:
case ConfigItem::QuestState:
case ConfigItem::RegulatorType:
case ConfigItem::DeviceUniqueKeyGeneration:
case ConfigItem::Package2Hash:
return ResultSecureMonitorNotImplemented;
case ConfigItem::ExosphereApiVersion:
// Get information about the current exosphere version.
return MakeResult((u64{HLE::ApiVersion::ATMOSPHERE_RELEASE_VERSION_MAJOR} << 56) |
(u64{HLE::ApiVersion::ATMOSPHERE_RELEASE_VERSION_MINOR} << 48) |
(u64{HLE::ApiVersion::ATMOSPHERE_RELEASE_VERSION_MICRO} << 40) |
(static_cast<u64>(HLE::ApiVersion::GetTargetFirmware())));
case ConfigItem::ExosphereNeedsReboot:
// We are executing, so we aren't in the process of rebooting.
return MakeResult(u64{0});
case ConfigItem::ExosphereNeedsShutdown:
// We are executing, so we aren't in the process of shutting down.
return MakeResult(u64{0});
case ConfigItem::ExosphereGitCommitHash:
// Get information about the current exosphere git commit hash.
return MakeResult(u64{0});
case ConfigItem::ExosphereHasRcmBugPatch:
// Get information about whether this unit has the RCM bug patched.
return MakeResult(u64{0});
case ConfigItem::ExosphereBlankProdInfo:
// Get whether this unit should simulate a "blanked" PRODINFO.
return MakeResult(u64{0});
case ConfigItem::ExosphereAllowCalWrites:
// Get whether this unit should allow writing to the calibration partition.
return MakeResult(u64{0});
case ConfigItem::ExosphereEmummcType:
// Get what kind of emummc this unit has active.
return MakeResult(u64{0});
case ConfigItem::ExospherePayloadAddress:
// Gets the physical address of the reboot payload buffer, if one exists.
return ResultSecureMonitorNotInitialized;
case ConfigItem::ExosphereLogConfiguration:
// Get the log configuration.
return MakeResult(u64{0});
case ConfigItem::ExosphereForceEnableUsb30:
// Get whether usb 3.0 should be force-enabled.
return MakeResult(u64{0});
default:
return ResultSecureMonitorInvalidArgument;
}
}
void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system) {
auto module = std::make_shared<Module>();
std::make_shared<CSRNG>(system, module)->InstallAsService(service_manager);

View File

@@ -6,6 +6,8 @@
#include <random>
#include "core/hle/service/service.h"
#include "core/hle/service/spl/spl_results.h"
#include "core/hle/service/spl/spl_types.h"
namespace Core {
class System;
@@ -21,12 +23,21 @@ public:
const char* name);
~Interface() override;
void GetRandomBytes(Kernel::HLERequestContext& ctx);
// General
void GetConfig(Kernel::HLERequestContext& ctx);
void ModularExponentiate(Kernel::HLERequestContext& ctx);
void SetConfig(Kernel::HLERequestContext& ctx);
void GenerateRandomBytes(Kernel::HLERequestContext& ctx);
void IsDevelopment(Kernel::HLERequestContext& ctx);
void SetBootReason(Kernel::HLERequestContext& ctx);
void GetBootReason(Kernel::HLERequestContext& ctx);
protected:
std::shared_ptr<Module> module;
private:
ResultVal<u64> GetConfigImpl(ConfigItem config_item) const;
std::mt19937 rng;
};
};

View File

@@ -10,13 +10,13 @@ SPL::SPL(Core::System& system_, std::shared_ptr<Module> module_)
: Interface(system_, std::move(module_), "spl:") {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "GetConfig"},
{1, nullptr, "ModularExponentiate"},
{5, nullptr, "SetConfig"},
{7, &SPL::GetRandomBytes, "GetRandomBytes"},
{11, nullptr, "IsDevelopment"},
{24, nullptr, "SetBootReason"},
{25, nullptr, "GetBootReason"},
{0, &SPL::GetConfig, "GetConfig"},
{1, &SPL::ModularExponentiate, "ModularExponentiate"},
{5, &SPL::SetConfig, "SetConfig"},
{7, &SPL::GenerateRandomBytes, "GenerateRandomBytes"},
{11, &SPL::IsDevelopment, "IsDevelopment"},
{24, &SPL::SetBootReason, "SetBootReason"},
{25, &SPL::GetBootReason, "GetBootReason"},
};
// clang-format on
@@ -27,22 +27,22 @@ SPL_MIG::SPL_MIG(Core::System& system_, std::shared_ptr<Module> module_)
: Interface(system_, std::move(module_), "spl:mig") {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "GetConfig"},
{1, nullptr, "ModularExponentiate"},
{0, &SPL::GetConfig, "GetConfig"},
{1, &SPL::ModularExponentiate, "ModularExponentiate"},
{2, nullptr, "GenerateAesKek"},
{3, nullptr, "LoadAesKey"},
{4, nullptr, "GenerateAesKey"},
{5, nullptr, "SetConfig"},
{7, &SPL::GetRandomBytes, "GenerateRandomBytes"},
{11, nullptr, "IsDevelopment"},
{5, &SPL::SetConfig, "SetConfig"},
{7, &SPL::GenerateRandomBytes, "GenerateRandomBytes"},
{11, &SPL::IsDevelopment, "IsDevelopment"},
{14, nullptr, "DecryptAesKey"},
{15, nullptr, "CryptAesCtr"},
{16, nullptr, "ComputeCmac"},
{21, nullptr, "AllocateAesKeyslot"},
{22, nullptr, "DeallocateAesKeySlot"},
{23, nullptr, "GetAesKeyslotAvailableEvent"},
{24, nullptr, "SetBootReason"},
{25, nullptr, "GetBootReason"},
{24, &SPL::SetBootReason, "SetBootReason"},
{25, &SPL::GetBootReason, "GetBootReason"},
};
// clang-format on
@@ -53,16 +53,16 @@ SPL_FS::SPL_FS(Core::System& system_, std::shared_ptr<Module> module_)
: Interface(system_, std::move(module_), "spl:fs") {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "GetConfig"},
{1, nullptr, "ModularExponentiate"},
{0, &SPL::GetConfig, "GetConfig"},
{1, &SPL::ModularExponentiate, "ModularExponentiate"},
{2, nullptr, "GenerateAesKek"},
{3, nullptr, "LoadAesKey"},
{4, nullptr, "GenerateAesKey"},
{5, nullptr, "SetConfig"},
{7, &SPL::GetRandomBytes, "GenerateRandomBytes"},
{5, &SPL::SetConfig, "SetConfig"},
{7, &SPL::GenerateRandomBytes, "GenerateRandomBytes"},
{9, nullptr, "ImportLotusKey"},
{10, nullptr, "DecryptLotusMessage"},
{11, nullptr, "IsDevelopment"},
{11, &SPL::IsDevelopment, "IsDevelopment"},
{12, nullptr, "GenerateSpecificAesKey"},
{14, nullptr, "DecryptAesKey"},
{15, nullptr, "CryptAesCtr"},
@@ -71,8 +71,8 @@ SPL_FS::SPL_FS(Core::System& system_, std::shared_ptr<Module> module_)
{21, nullptr, "AllocateAesKeyslot"},
{22, nullptr, "DeallocateAesKeySlot"},
{23, nullptr, "GetAesKeyslotAvailableEvent"},
{24, nullptr, "SetBootReason"},
{25, nullptr, "GetBootReason"},
{24, &SPL::SetBootReason, "SetBootReason"},
{25, &SPL::GetBootReason, "GetBootReason"},
{31, nullptr, "GetPackage2Hash"},
};
// clang-format on
@@ -84,14 +84,14 @@ SPL_SSL::SPL_SSL(Core::System& system_, std::shared_ptr<Module> module_)
: Interface(system_, std::move(module_), "spl:ssl") {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "GetConfig"},
{1, nullptr, "ModularExponentiate"},
{0, &SPL::GetConfig, "GetConfig"},
{1, &SPL::ModularExponentiate, "ModularExponentiate"},
{2, nullptr, "GenerateAesKek"},
{3, nullptr, "LoadAesKey"},
{4, nullptr, "GenerateAesKey"},
{5, nullptr, "SetConfig"},
{7, &SPL::GetRandomBytes, "GetRandomBytes"},
{11, nullptr, "IsDevelopment"},
{5, &SPL::SetConfig, "SetConfig"},
{7, &SPL::GenerateRandomBytes, "GenerateRandomBytes"},
{11, &SPL::IsDevelopment, "IsDevelopment"},
{13, nullptr, "DecryptDeviceUniqueData"},
{14, nullptr, "DecryptAesKey"},
{15, nullptr, "CryptAesCtr"},
@@ -99,8 +99,8 @@ SPL_SSL::SPL_SSL(Core::System& system_, std::shared_ptr<Module> module_)
{21, nullptr, "AllocateAesKeyslot"},
{22, nullptr, "DeallocateAesKeySlot"},
{23, nullptr, "GetAesKeyslotAvailableEvent"},
{24, nullptr, "SetBootReason"},
{25, nullptr, "GetBootReason"},
{24, &SPL::SetBootReason, "SetBootReason"},
{25, &SPL::GetBootReason, "GetBootReason"},
{26, nullptr, "DecryptAndStoreSslClientCertKey"},
{27, nullptr, "ModularExponentiateWithSslClientCertKey"},
};
@@ -113,14 +113,14 @@ SPL_ES::SPL_ES(Core::System& system_, std::shared_ptr<Module> module_)
: Interface(system_, std::move(module_), "spl:es") {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "GetConfig"},
{1, nullptr, "ModularExponentiate"},
{0, &SPL::GetConfig, "GetConfig"},
{1, &SPL::ModularExponentiate, "ModularExponentiate"},
{2, nullptr, "GenerateAesKek"},
{3, nullptr, "LoadAesKey"},
{4, nullptr, "GenerateAesKey"},
{5, nullptr, "SetConfig"},
{7, &SPL::GetRandomBytes, "GenerateRandomBytes"},
{11, nullptr, "IsDevelopment"},
{5, &SPL::SetConfig, "SetConfig"},
{7, &SPL::GenerateRandomBytes, "GenerateRandomBytes"},
{11, &SPL::IsDevelopment, "IsDevelopment"},
{13, nullptr, "DecryptDeviceUniqueData"},
{14, nullptr, "DecryptAesKey"},
{15, nullptr, "CryptAesCtr"},
@@ -131,8 +131,8 @@ SPL_ES::SPL_ES(Core::System& system_, std::shared_ptr<Module> module_)
{21, nullptr, "AllocateAesKeyslot"},
{22, nullptr, "DeallocateAesKeySlot"},
{23, nullptr, "GetAesKeyslotAvailableEvent"},
{24, nullptr, "SetBootReason"},
{25, nullptr, "GetBootReason"},
{24, &SPL::SetBootReason, "SetBootReason"},
{25, &SPL::GetBootReason, "GetBootReason"},
{28, nullptr, "DecryptAndStoreDrmDeviceCertKey"},
{29, nullptr, "ModularExponentiateWithDrmDeviceCertKey"},
{31, nullptr, "PrepareEsArchiveKey"},
@@ -147,14 +147,14 @@ SPL_MANU::SPL_MANU(Core::System& system_, std::shared_ptr<Module> module_)
: Interface(system_, std::move(module_), "spl:manu") {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "GetConfig"},
{1, nullptr, "ModularExponentiate"},
{0, &SPL::GetConfig, "GetConfig"},
{1, &SPL::ModularExponentiate, "ModularExponentiate"},
{2, nullptr, "GenerateAesKek"},
{3, nullptr, "LoadAesKey"},
{4, nullptr, "GenerateAesKey"},
{5, nullptr, "SetConfig"},
{7, &SPL::GetRandomBytes, "GetRandomBytes"},
{11, nullptr, "IsDevelopment"},
{5, &SPL::SetConfig, "SetConfig"},
{7, &SPL::GenerateRandomBytes, "GenerateRandomBytes"},
{11, &SPL::IsDevelopment, "IsDevelopment"},
{13, nullptr, "DecryptDeviceUniqueData"},
{14, nullptr, "DecryptAesKey"},
{15, nullptr, "CryptAesCtr"},
@@ -162,8 +162,8 @@ SPL_MANU::SPL_MANU(Core::System& system_, std::shared_ptr<Module> module_)
{21, nullptr, "AllocateAesKeyslot"},
{22, nullptr, "DeallocateAesKeySlot"},
{23, nullptr, "GetAesKeyslotAvailableEvent"},
{24, nullptr, "SetBootReason"},
{25, nullptr, "GetBootReason"},
{24, &SPL::SetBootReason, "SetBootReason"},
{25, &SPL::GetBootReason, "GetBootReason"},
{30, nullptr, "ReencryptDeviceUniqueData"},
};
// clang-format on

View File

@@ -0,0 +1,31 @@
// Copyright 2021 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include "core/hle/result.h"
namespace Service::SPL {
// Description 0 - 99
constexpr ResultCode ResultSecureMonitorError{ErrorModule::SPL, 0};
constexpr ResultCode ResultSecureMonitorNotImplemented{ErrorModule::SPL, 1};
constexpr ResultCode ResultSecureMonitorInvalidArgument{ErrorModule::SPL, 2};
constexpr ResultCode ResultSecureMonitorBusy{ErrorModule::SPL, 3};
constexpr ResultCode ResultSecureMonitorNoAsyncOperation{ErrorModule::SPL, 4};
constexpr ResultCode ResultSecureMonitorInvalidAsyncOperation{ErrorModule::SPL, 5};
constexpr ResultCode ResultSecureMonitorNotPermitted{ErrorModule::SPL, 6};
constexpr ResultCode ResultSecureMonitorNotInitialized{ErrorModule::SPL, 7};
constexpr ResultCode ResultInvalidSize{ErrorModule::SPL, 100};
constexpr ResultCode ResultUnknownSecureMonitorError{ErrorModule::SPL, 101};
constexpr ResultCode ResultDecryptionFailed{ErrorModule::SPL, 102};
constexpr ResultCode ResultOutOfKeySlots{ErrorModule::SPL, 104};
constexpr ResultCode ResultInvalidKeySlot{ErrorModule::SPL, 105};
constexpr ResultCode ResultBootReasonAlreadySet{ErrorModule::SPL, 106};
constexpr ResultCode ResultBootReasonNotSet{ErrorModule::SPL, 107};
constexpr ResultCode ResultInvalidArgument{ErrorModule::SPL, 108};
} // namespace Service::SPL

View File

@@ -0,0 +1,232 @@
// Copyright 2021 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <span>
#include "common/bit_field.h"
#include "common/common_types.h"
namespace Service::SPL {
constexpr size_t AES_128_KEY_SIZE = 0x10;
namespace Smc {
enum class FunctionId : u32 {
SetConfig = 0xC3000401,
GetConfig = 0xC3000002,
GetResult = 0xC3000003,
GetResultData = 0xC3000404,
ModularExponentiate = 0xC3000E05,
GenerateRandomBytes = 0xC3000006,
GenerateAesKek = 0xC3000007,
LoadAesKey = 0xC3000008,
ComputeAes = 0xC3000009,
GenerateSpecificAesKey = 0xC300000A,
ComputeCmac = 0xC300040B,
ReencryptDeviceUniqueData = 0xC300D60C,
DecryptDeviceUniqueData = 0xC300100D,
ModularExponentiateWithStorageKey = 0xC300060F,
PrepareEsDeviceUniqueKey = 0xC3000610,
LoadPreparedAesKey = 0xC3000011,
PrepareCommonEsTitleKey = 0xC3000012,
// Deprecated functions.
LoadEsDeviceKey = 0xC300100C,
DecryptAndStoreGcKey = 0xC300100E,
// Atmosphere functions.
AtmosphereIramCopy = 0xF0000201,
AtmosphereReadWriteRegister = 0xF0000002,
AtmosphereGetEmummcConfig = 0xF0000404,
};
enum class CipherMode {
CbcEncrypt = 0,
CbcDecrypt = 1,
Ctr = 2,
};
enum class DeviceUniqueDataMode {
DecryptDeviceUniqueData = 0,
DecryptAndStoreGcKey = 1,
DecryptAndStoreEsDeviceKey = 2,
DecryptAndStoreSslKey = 3,
DecryptAndStoreDrmDeviceCertKey = 4,
};
enum class ModularExponentiateWithStorageKeyMode {
Gc = 0,
Ssl = 1,
DrmDeviceCert = 2,
};
enum class EsCommonKeyType {
TitleKey = 0,
ArchiveKey = 1,
};
struct AsyncOperationKey {
u64 value;
};
} // namespace Smc
enum class HardwareType {
Icosa = 0,
Copper = 1,
Hoag = 2,
Iowa = 3,
Calcio = 4,
Aula = 5,
};
enum class SocType {
Erista = 0,
Mariko = 1,
};
enum class HardwareState {
Development = 0,
Production = 1,
};
enum class MemoryArrangement {
Standard = 0,
StandardForAppletDev = 1,
StandardForSystemDev = 2,
Expanded = 3,
ExpandedForAppletDev = 4,
// Note: Dynamic is not official.
// Atmosphere uses it to maintain compatibility with firmwares prior to 6.0.0,
// which removed the explicit retrieval of memory arrangement from PM.
Dynamic = 5,
Count,
};
enum class BootReason {
Unknown = 0,
AcOk = 1,
OnKey = 2,
RtcAlarm1 = 3,
RtcAlarm2 = 4,
};
struct BootReasonValue {
union {
u32 value{};
BitField<0, 8, u32> power_intr;
BitField<8, 8, u32> rtc_intr;
BitField<16, 8, u32> nv_erc;
BitField<24, 8, u32> boot_reason;
};
};
static_assert(sizeof(BootReasonValue) == sizeof(u32), "BootReasonValue definition!");
struct AesKey {
std::array<u64, AES_128_KEY_SIZE / sizeof(u64)> data64{};
std::span<u8> AsBytes() {
return std::span{reinterpret_cast<u8*>(data64.data()), AES_128_KEY_SIZE};
}
std::span<const u8> AsBytes() const {
return std::span{reinterpret_cast<const u8*>(data64.data()), AES_128_KEY_SIZE};
}
};
static_assert(sizeof(AesKey) == AES_128_KEY_SIZE, "AesKey definition!");
struct IvCtr {
std::array<u64, AES_128_KEY_SIZE / sizeof(u64)> data64{};
std::span<u8> AsBytes() {
return std::span{reinterpret_cast<u8*>(data64.data()), AES_128_KEY_SIZE};
}
std::span<const u8> AsBytes() const {
return std::span{reinterpret_cast<const u8*>(data64.data()), AES_128_KEY_SIZE};
}
};
static_assert(sizeof(AesKey) == AES_128_KEY_SIZE, "IvCtr definition!");
struct Cmac {
std::array<u64, AES_128_KEY_SIZE / sizeof(u64)> data64{};
std::span<u8> AsBytes() {
return std::span{reinterpret_cast<u8*>(data64.data()), AES_128_KEY_SIZE};
}
std::span<const u8> AsBytes() const {
return std::span{reinterpret_cast<const u8*>(data64.data()), AES_128_KEY_SIZE};
}
};
static_assert(sizeof(AesKey) == AES_128_KEY_SIZE, "Cmac definition!");
struct AccessKey {
std::array<u64, AES_128_KEY_SIZE / sizeof(u64)> data64{};
std::span<u8> AsBytes() {
return std::span{reinterpret_cast<u8*>(data64.data()), AES_128_KEY_SIZE};
}
std::span<const u8> AsBytes() const {
return std::span{reinterpret_cast<const u8*>(data64.data()), AES_128_KEY_SIZE};
}
};
static_assert(sizeof(AesKey) == AES_128_KEY_SIZE, "AccessKey definition!");
struct KeySource {
std::array<u64, AES_128_KEY_SIZE / sizeof(u64)> data64{};
std::span<u8> AsBytes() {
return std::span{reinterpret_cast<u8*>(data64.data()), AES_128_KEY_SIZE};
}
std::span<const u8> AsBytes() const {
return std::span{reinterpret_cast<const u8*>(data64.data()), AES_128_KEY_SIZE};
}
};
static_assert(sizeof(AesKey) == AES_128_KEY_SIZE, "KeySource definition!");
enum class ConfigItem : u32 {
// Standard config items.
DisableProgramVerification = 1,
DramId = 2,
SecurityEngineInterruptNumber = 3,
FuseVersion = 4,
HardwareType = 5,
HardwareState = 6,
IsRecoveryBoot = 7,
DeviceId = 8,
BootReason = 9,
MemoryMode = 10,
IsDevelopmentFunctionEnabled = 11,
KernelConfiguration = 12,
IsChargerHiZModeEnabled = 13,
QuestState = 14,
RegulatorType = 15,
DeviceUniqueKeyGeneration = 16,
Package2Hash = 17,
// Extension config items for exosphere.
ExosphereApiVersion = 65000,
ExosphereNeedsReboot = 65001,
ExosphereNeedsShutdown = 65002,
ExosphereGitCommitHash = 65003,
ExosphereHasRcmBugPatch = 65004,
ExosphereBlankProdInfo = 65005,
ExosphereAllowCalWrites = 65006,
ExosphereEmummcType = 65007,
ExospherePayloadAddress = 65008,
ExosphereLogConfiguration = 65009,
ExosphereForceEnableUsb30 = 65010,
};
} // namespace Service::SPL

View File

@@ -125,7 +125,7 @@ ResultCode TimeZoneContentManager::GetTimeZoneInfoFile(const std::string& locati
return ERROR_TIME_NOT_FOUND;
}
vfs_file = zoneinfo_dir->GetFile(location_name);
vfs_file = zoneinfo_dir->GetFileRelative(location_name);
if (!vfs_file) {
LOG_ERROR(Service_Time, "{:016X} has no file \"{}\"! Using default timezone.",
time_zone_binary_titleid, location_name);

View File

@@ -195,7 +195,9 @@ json GetHLERequestContextData(Kernel::HLERequestContext& ctx, Core::Memory::Memo
namespace Core {
Reporter::Reporter(System& system_) : system(system_) {}
Reporter::Reporter(System& system_) : system(system_) {
ClearFSAccessLog();
}
Reporter::~Reporter() = default;
@@ -362,22 +364,12 @@ void Reporter::SaveErrorReport(u64 title_id, ResultCode result,
SaveToFile(std::move(out), GetPath("error_report", title_id, timestamp));
}
void Reporter::SaveFilesystemAccessReport(Service::FileSystem::LogMode log_mode,
std::string log_message) const {
if (!IsReportingEnabled())
return;
void Reporter::SaveFSAccessLog(std::string_view log_message) const {
const auto access_log_path =
Common::FS::GetYuzuPath(Common::FS::YuzuPath::SDMCDir) / "FsAccessLog.txt";
const auto timestamp = GetTimestamp();
const auto title_id = system.CurrentProcess()->GetTitleID();
json out;
out["yuzu_version"] = GetYuzuVersionData();
out["report_common"] = GetReportCommonData(title_id, ResultSuccess, timestamp);
out["log_mode"] = fmt::format("{:08X}", static_cast<u32>(log_mode));
out["log_message"] = std::move(log_message);
SaveToFile(std::move(out), GetPath("filesystem_access_report", title_id, timestamp));
void(Common::FS::AppendStringToFile(access_log_path, Common::FS::FileType::TextFile,
log_message));
}
void Reporter::SaveUserReport() const {
@@ -392,6 +384,18 @@ void Reporter::SaveUserReport() const {
GetPath("user_report", title_id, timestamp));
}
void Reporter::ClearFSAccessLog() const {
const auto access_log_path =
Common::FS::GetYuzuPath(Common::FS::YuzuPath::SDMCDir) / "FsAccessLog.txt";
Common::FS::IOFile access_log_file{access_log_path, Common::FS::FileAccessMode::Write,
Common::FS::FileType::TextFile};
if (!access_log_file.IsOpen()) {
LOG_ERROR(Common_Filesystem, "Failed to clear the filesystem access log.");
}
}
bool Reporter::IsReportingEnabled() const {
return Settings::values.reporting_services;
}

View File

@@ -16,10 +16,6 @@ namespace Kernel {
class HLERequestContext;
} // namespace Kernel
namespace Service::FileSystem {
enum class LogMode : u32;
}
namespace Service::LM {
struct LogMessage;
} // namespace Service::LM
@@ -69,14 +65,15 @@ public:
std::optional<std::string> custom_text_main = {},
std::optional<std::string> custom_text_detail = {}) const;
void SaveFilesystemAccessReport(Service::FileSystem::LogMode log_mode,
std::string log_message) const;
void SaveFSAccessLog(std::string_view log_message) 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:
void ClearFSAccessLog() const;
bool IsReportingEnabled() const;
System& system;

View File

@@ -72,18 +72,6 @@ static const char* TranslateGPUAccuracyLevel(Settings::GPUAccuracy backend) {
return "Unknown";
}
static const char* TranslateGarbageCollectLevel(Settings::GCLevel backend) {
switch (backend) {
case Settings::GCLevel::Aggressive:
return "Aggressive";
case Settings::GCLevel::Normal:
return "Normal";
case Settings::GCLevel::Relaxed:
return "Relaxed";
}
return "Unknown";
}
u64 GetTelemetryId() {
u64 telemetry_id{};
const auto filename = Common::FS::GetYuzuPath(Common::FS::YuzuPath::ConfigDir) / "telemetry_id";
@@ -238,14 +226,11 @@ void TelemetrySession::AddInitialInfo(Loader::AppLoader& app_loader,
Settings::values.use_disk_shader_cache.GetValue());
AddField(field_type, "Renderer_GPUAccuracyLevel",
TranslateGPUAccuracyLevel(Settings::values.gpu_accuracy.GetValue()));
AddField(field_type, "Renderer_UseGarbageCollect",
Settings::values.use_garbage_collect.GetValue());
AddField(field_type, "Renderer_GarbageCollectLevel",
TranslateGarbageCollectLevel(Settings::values.garbage_collect_level.GetValue()));
AddField(field_type, "Renderer_UseAsynchronousGpuEmulation",
Settings::values.use_asynchronous_gpu_emulation.GetValue());
AddField(field_type, "Renderer_UseNvdecEmulation",
Settings::values.use_nvdec_emulation.GetValue());
AddField(field_type, "Renderer_AccelerateASTC", Settings::values.accelerate_astc.GetValue());
AddField(field_type, "Renderer_UseVsync", Settings::values.use_vsync.GetValue());
AddField(field_type, "Renderer_UseAssemblyShaders",
Settings::values.use_assembly_shaders.GetValue());

View File

@@ -34,18 +34,10 @@ if (MSVC)
/W4
/WX
# 'expression' : signed/unsigned mismatch
/we4018
# 'argument' : conversion from 'type1' to 'type2', possible loss of data (floating-point)
/we4244
# 'conversion' : conversion from 'type1' to 'type2', signed/unsigned mismatch
/we4245
# 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data
/we4254
# 'var' : conversion from 'size_t' to 'type', possible loss of data
/we4267
# 'context' : truncation from 'type1' to 'type2'
/we4305
/we4242 # 'identifier': conversion from 'type1' to 'type2', possible loss of data
/we4244 # 'conversion': conversion from 'type1' to 'type2', possible loss of data
/we4245 # 'conversion': conversion from 'type1' to 'type2', signed/unsigned mismatch
/we4254 # 'operator': conversion from 'type1:field_bits' to 'type2:field_bits', possible loss of data
)
else()
target_compile_options(input_common PRIVATE

View File

@@ -5,14 +5,7 @@
#include <chrono>
#include <thread>
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4200) // nonstandard extension used : zero-sized array in struct/union
#endif
#include <libusb.h>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include "common/logging/log.h"
#include "common/param_package.h"

View File

@@ -2,25 +2,23 @@
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include <stop_token>
#include <thread>
#include "common/settings.h"
#include "input_common/mouse/mouse_input.h"
namespace MouseInput {
Mouse::Mouse() {
update_thread = std::thread(&Mouse::UpdateThread, this);
update_thread = std::jthread([this](std::stop_token stop_token) { UpdateThread(stop_token); });
}
Mouse::~Mouse() {
update_thread_running = false;
if (update_thread.joinable()) {
update_thread.join();
}
}
Mouse::~Mouse() = default;
void Mouse::UpdateThread() {
void Mouse::UpdateThread(std::stop_token stop_token) {
constexpr int update_time = 10;
while (update_thread_running) {
while (!stop_token.stop_requested()) {
for (MouseInfo& info : mouse_info) {
const Common::Vec3f angular_direction{
-info.tilt_direction.y,

View File

@@ -6,6 +6,7 @@
#include <array>
#include <mutex>
#include <stop_token>
#include <thread>
#include "common/common_types.h"
@@ -85,7 +86,7 @@ public:
[[nodiscard]] const MouseData& GetMouseState(std::size_t button) const;
private:
void UpdateThread();
void UpdateThread(std::stop_token stop_token);
void UpdateYuzuSettings();
void StopPanning();
@@ -105,12 +106,11 @@ private:
u16 buttons{};
u16 toggle_buttons{};
u16 lock_buttons{};
std::thread update_thread;
std::jthread update_thread;
MouseButton last_button{MouseButton::Undefined};
std::array<MouseInfo, 7> mouse_info;
Common::SPSCQueue<MouseStatus> mouse_queue;
bool configuring{false};
bool update_thread_running{true};
int mouse_panning_timout{};
};
} // namespace MouseInput

View File

@@ -2,6 +2,8 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <algorithm>
#include <memory>
#include <mutex>
#include <utility>

View File

@@ -2,6 +2,7 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <algorithm>
#include "common/settings.h"
#include "core/frontend/framebuffer_layout.h"
#include "input_common/touch_from_button.h"

View File

@@ -8,14 +8,7 @@
#include <optional>
#include <type_traits>
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4701)
#endif
#include <boost/crc.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include "common/bit_field.h"
#include "common/swap.h"

View File

@@ -5,11 +5,13 @@
#include <catch2/catch.hpp>
#include "common/host_memory.h"
#include "common/literals.h"
using Common::HostMemory;
using namespace Common::Literals;
static constexpr size_t VIRTUAL_SIZE = 1ULL << 39;
static constexpr size_t BACKING_SIZE = 4ULL * 1024 * 1024 * 1024;
static constexpr size_t BACKING_SIZE = 4_GiB;
TEST_CASE("HostMemory: Initialize and deinitialize", "[common]") {
{ HostMemory mem(BACKING_SIZE, VIRTUAL_SIZE); }

View File

@@ -237,6 +237,7 @@ add_library(video_core STATIC
texture_cache/util.cpp
texture_cache/util.h
textures/astc.h
textures/astc.cpp
textures/decoders.cpp
textures/decoders.h
textures/texture.cpp
@@ -291,12 +292,12 @@ endif()
if (MSVC)
target_compile_options(video_core PRIVATE
/we4267 # 'var' : conversion from 'size_t' to 'type', possible loss of data
/we4242 # 'identifier': conversion from 'type1' to 'type2', possible loss of data
/we4244 # 'conversion': conversion from 'type1' to 'type2', possible loss of data
/we4456 # Declaration of 'identifier' hides previous local declaration
/we4457 # Declaration of 'identifier' hides function parameter
/we4458 # Declaration of 'identifier' hides class member
/we4459 # Declaration of 'identifier' hides global declaration
/we4715 # 'function' : not all control paths return a value
)
else()
target_compile_options(video_core PRIVATE

View File

@@ -256,6 +256,16 @@ public:
stream_score += score;
}
/// Sets the new frame tick
void SetFrameTick(u64 new_frame_tick) noexcept {
frame_tick = new_frame_tick;
}
/// Returns the new frame tick
[[nodiscard]] u64 FrameTick() const noexcept {
return frame_tick;
}
/// Returns the likeliness of this being a stream buffer
[[nodiscard]] int StreamScore() const noexcept {
return stream_score;
@@ -586,6 +596,7 @@ private:
RasterizerInterface* rasterizer = nullptr;
VAddr cpu_addr = 0;
Words words;
u64 frame_tick = 0;
BufferFlagBits flags{};
int stream_score = 0;
};

View File

@@ -18,6 +18,7 @@
#include "common/common_types.h"
#include "common/div_ceil.h"
#include "common/literals.h"
#include "common/microprofile.h"
#include "common/scope_exit.h"
#include "common/settings.h"
@@ -47,8 +48,11 @@ constexpr u32 NUM_COMPUTE_UNIFORM_BUFFERS = 8;
constexpr u32 NUM_STORAGE_BUFFERS = 16;
constexpr u32 NUM_STAGES = 5;
using namespace Common::Literals;
template <typename P>
class BufferCache {
// Page size for caching purposes.
// This is unrelated to the CPU page size and it can be changed as it seems optimal.
static constexpr u32 PAGE_BITS = 16;
@@ -65,6 +69,9 @@ class BufferCache {
static constexpr BufferId NULL_BUFFER_ID{0};
static constexpr u64 EXPECTED_MEMORY = 512_MiB;
static constexpr u64 CRITICAL_MEMORY = 1_GiB;
using Maxwell = Tegra::Engines::Maxwell3D::Regs;
using Runtime = typename P::Runtime;
@@ -92,7 +99,7 @@ class BufferCache {
};
public:
static constexpr u32 DEFAULT_SKIP_CACHE_SIZE = 4096;
static constexpr u32 DEFAULT_SKIP_CACHE_SIZE = static_cast<u32>(4_KiB);
explicit BufferCache(VideoCore::RasterizerInterface& rasterizer_,
Tegra::Engines::Maxwell3D& maxwell3d_,
@@ -188,6 +195,8 @@ private:
((cpu_addr + size) & ~Core::Memory::PAGE_MASK);
}
void RunGarbageCollector();
void BindHostIndexBuffer();
void BindHostVertexBuffers();
@@ -243,6 +252,8 @@ private:
template <bool insert>
void ChangeRegister(BufferId buffer_id);
void TouchBuffer(Buffer& buffer) const noexcept;
bool SynchronizeBuffer(Buffer& buffer, VAddr cpu_addr, u32 size);
bool SynchronizeBufferImpl(Buffer& buffer, VAddr cpu_addr, u32 size);
@@ -255,6 +266,10 @@ private:
void MappedUploadMemory(Buffer& buffer, u64 total_size_bytes, std::span<BufferCopy> copies);
void DownloadBufferMemory(Buffer& buffer_id);
void DownloadBufferMemory(Buffer& buffer_id, VAddr cpu_addr, u64 size);
void DeleteBuffer(BufferId buffer_id);
void ReplaceBufferDownloads(BufferId old_buffer_id, BufferId new_buffer_id);
@@ -319,6 +334,10 @@ private:
size_t immediate_buffer_capacity = 0;
std::unique_ptr<u8[]> immediate_buffer_alloc;
typename SlotVector<Buffer>::Iterator deletion_iterator;
u64 frame_tick = 0;
u64 total_used_memory = 0;
std::array<BufferId, ((1ULL << 39) >> PAGE_BITS)> page_table;
};
@@ -332,6 +351,28 @@ BufferCache<P>::BufferCache(VideoCore::RasterizerInterface& rasterizer_,
gpu_memory{gpu_memory_}, cpu_memory{cpu_memory_}, runtime{runtime_} {
// Ensure the first slot is used for the null buffer
void(slot_buffers.insert(runtime, NullBufferParams{}));
deletion_iterator = slot_buffers.end();
}
template <class P>
void BufferCache<P>::RunGarbageCollector() {
const bool aggressive_gc = total_used_memory >= CRITICAL_MEMORY;
const u64 ticks_to_destroy = aggressive_gc ? 60 : 120;
int num_iterations = aggressive_gc ? 64 : 32;
for (; num_iterations > 0; --num_iterations) {
if (deletion_iterator == slot_buffers.end()) {
deletion_iterator = slot_buffers.begin();
}
++deletion_iterator;
if (deletion_iterator == slot_buffers.end()) {
break;
}
const auto [buffer_id, buffer] = *deletion_iterator;
if (buffer->FrameTick() + ticks_to_destroy < frame_tick) {
DownloadBufferMemory(*buffer);
DeleteBuffer(buffer_id);
}
}
}
template <class P>
@@ -349,6 +390,10 @@ void BufferCache<P>::TickFrame() {
const bool skip_preferred = hits * 256 < shots * 251;
uniform_buffer_skip_cache_size = skip_preferred ? DEFAULT_SKIP_CACHE_SIZE : 0;
if (Settings::values.use_caches_gc.GetValue() && total_used_memory >= EXPECTED_MEMORY) {
RunGarbageCollector();
}
++frame_tick;
delayed_destruction_ring.Tick();
}
@@ -372,48 +417,7 @@ void BufferCache<P>::CachedWriteMemory(VAddr cpu_addr, u64 size) {
template <class P>
void BufferCache<P>::DownloadMemory(VAddr cpu_addr, u64 size) {
ForEachBufferInRange(cpu_addr, size, [&](BufferId, Buffer& buffer) {
boost::container::small_vector<BufferCopy, 1> copies;
u64 total_size_bytes = 0;
u64 largest_copy = 0;
buffer.ForEachDownloadRange(cpu_addr, size, [&](u64 range_offset, u64 range_size) {
copies.push_back(BufferCopy{
.src_offset = range_offset,
.dst_offset = total_size_bytes,
.size = range_size,
});
total_size_bytes += range_size;
largest_copy = std::max(largest_copy, range_size);
});
if (total_size_bytes == 0) {
return;
}
MICROPROFILE_SCOPE(GPU_DownloadMemory);
if constexpr (USE_MEMORY_MAPS) {
auto download_staging = runtime.DownloadStagingBuffer(total_size_bytes);
const u8* const mapped_memory = download_staging.mapped_span.data();
const std::span<BufferCopy> copies_span(copies.data(), copies.data() + copies.size());
for (BufferCopy& copy : copies) {
// Modify copies to have the staging offset in mind
copy.dst_offset += download_staging.offset;
}
runtime.CopyBuffer(download_staging.buffer, buffer, copies_span);
runtime.Finish();
for (const BufferCopy& copy : copies) {
const VAddr copy_cpu_addr = buffer.CpuAddr() + copy.src_offset;
// Undo the modified offset
const u64 dst_offset = copy.dst_offset - download_staging.offset;
const u8* copy_mapped_memory = mapped_memory + dst_offset;
cpu_memory.WriteBlockUnsafe(copy_cpu_addr, copy_mapped_memory, copy.size);
}
} else {
const std::span<u8> immediate_buffer = ImmediateBuffer(largest_copy);
for (const BufferCopy& copy : copies) {
buffer.ImmediateDownload(copy.src_offset, immediate_buffer.subspan(0, copy.size));
const VAddr copy_cpu_addr = buffer.CpuAddr() + copy.src_offset;
cpu_memory.WriteBlockUnsafe(copy_cpu_addr, immediate_buffer.data(), copy.size);
}
}
DownloadBufferMemory(buffer, cpu_addr, size);
});
}
@@ -640,6 +644,7 @@ bool BufferCache<P>::IsRegionGpuModified(VAddr addr, size_t size) {
template <class P>
void BufferCache<P>::BindHostIndexBuffer() {
Buffer& buffer = slot_buffers[index_buffer.buffer_id];
TouchBuffer(buffer);
const u32 offset = buffer.Offset(index_buffer.cpu_addr);
const u32 size = index_buffer.size;
SynchronizeBuffer(buffer, index_buffer.cpu_addr, size);
@@ -658,6 +663,7 @@ void BufferCache<P>::BindHostVertexBuffers() {
for (u32 index = 0; index < NUM_VERTEX_BUFFERS; ++index) {
const Binding& binding = vertex_buffers[index];
Buffer& buffer = slot_buffers[binding.buffer_id];
TouchBuffer(buffer);
SynchronizeBuffer(buffer, binding.cpu_addr, binding.size);
if (!flags[Dirty::VertexBuffer0 + index]) {
continue;
@@ -693,6 +699,7 @@ void BufferCache<P>::BindHostGraphicsUniformBuffer(size_t stage, u32 index, u32
const VAddr cpu_addr = binding.cpu_addr;
const u32 size = binding.size;
Buffer& buffer = slot_buffers[binding.buffer_id];
TouchBuffer(buffer);
const bool use_fast_buffer = binding.buffer_id != NULL_BUFFER_ID &&
size <= uniform_buffer_skip_cache_size &&
!buffer.IsRegionGpuModified(cpu_addr, size);
@@ -744,6 +751,7 @@ void BufferCache<P>::BindHostGraphicsStorageBuffers(size_t stage) {
ForEachEnabledBit(enabled_storage_buffers[stage], [&](u32 index) {
const Binding& binding = storage_buffers[stage][index];
Buffer& buffer = slot_buffers[binding.buffer_id];
TouchBuffer(buffer);
const u32 size = binding.size;
SynchronizeBuffer(buffer, binding.cpu_addr, size);
@@ -766,6 +774,7 @@ void BufferCache<P>::BindHostTransformFeedbackBuffers() {
for (u32 index = 0; index < NUM_TRANSFORM_FEEDBACK_BUFFERS; ++index) {
const Binding& binding = transform_feedback_buffers[index];
Buffer& buffer = slot_buffers[binding.buffer_id];
TouchBuffer(buffer);
const u32 size = binding.size;
SynchronizeBuffer(buffer, binding.cpu_addr, size);
@@ -784,6 +793,7 @@ void BufferCache<P>::BindHostComputeUniformBuffers() {
ForEachEnabledBit(enabled_compute_uniform_buffers, [&](u32 index) {
const Binding& binding = compute_uniform_buffers[index];
Buffer& buffer = slot_buffers[binding.buffer_id];
TouchBuffer(buffer);
const u32 size = binding.size;
SynchronizeBuffer(buffer, binding.cpu_addr, size);
@@ -803,6 +813,7 @@ void BufferCache<P>::BindHostComputeStorageBuffers() {
ForEachEnabledBit(enabled_compute_storage_buffers, [&](u32 index) {
const Binding& binding = compute_storage_buffers[index];
Buffer& buffer = slot_buffers[binding.buffer_id];
TouchBuffer(buffer);
const u32 size = binding.size;
SynchronizeBuffer(buffer, binding.cpu_addr, size);
@@ -1101,6 +1112,7 @@ BufferId BufferCache<P>::CreateBuffer(VAddr cpu_addr, u32 wanted_size) {
const OverlapResult overlap = ResolveOverlaps(cpu_addr, wanted_size);
const u32 size = static_cast<u32>(overlap.end - overlap.begin);
const BufferId new_buffer_id = slot_buffers.insert(runtime, rasterizer, overlap.begin, size);
TouchBuffer(slot_buffers[new_buffer_id]);
for (const BufferId overlap_id : overlap.ids) {
JoinOverlap(new_buffer_id, overlap_id, !overlap.has_stream_leap);
}
@@ -1122,8 +1134,14 @@ template <class P>
template <bool insert>
void BufferCache<P>::ChangeRegister(BufferId buffer_id) {
const Buffer& buffer = slot_buffers[buffer_id];
const auto size = buffer.SizeBytes();
if (insert) {
total_used_memory += Common::AlignUp(size, 1024);
} else {
total_used_memory -= Common::AlignUp(size, 1024);
}
const VAddr cpu_addr_begin = buffer.CpuAddr();
const VAddr cpu_addr_end = cpu_addr_begin + buffer.SizeBytes();
const VAddr cpu_addr_end = cpu_addr_begin + size;
const u64 page_begin = cpu_addr_begin / PAGE_SIZE;
const u64 page_end = Common::DivCeil(cpu_addr_end, PAGE_SIZE);
for (u64 page = page_begin; page != page_end; ++page) {
@@ -1135,6 +1153,11 @@ void BufferCache<P>::ChangeRegister(BufferId buffer_id) {
}
}
template <class P>
void BufferCache<P>::TouchBuffer(Buffer& buffer) const noexcept {
buffer.SetFrameTick(frame_tick);
}
template <class P>
bool BufferCache<P>::SynchronizeBuffer(Buffer& buffer, VAddr cpu_addr, u32 size) {
if (buffer.CpuAddr() == 0) {
@@ -1211,6 +1234,57 @@ void BufferCache<P>::MappedUploadMemory(Buffer& buffer, u64 total_size_bytes,
runtime.CopyBuffer(buffer, upload_staging.buffer, copies);
}
template <class P>
void BufferCache<P>::DownloadBufferMemory(Buffer& buffer) {
DownloadBufferMemory(buffer, buffer.CpuAddr(), buffer.SizeBytes());
}
template <class P>
void BufferCache<P>::DownloadBufferMemory(Buffer& buffer, VAddr cpu_addr, u64 size) {
boost::container::small_vector<BufferCopy, 1> copies;
u64 total_size_bytes = 0;
u64 largest_copy = 0;
buffer.ForEachDownloadRange(cpu_addr, size, [&](u64 range_offset, u64 range_size) {
copies.push_back(BufferCopy{
.src_offset = range_offset,
.dst_offset = total_size_bytes,
.size = range_size,
});
total_size_bytes += range_size;
largest_copy = std::max(largest_copy, range_size);
});
if (total_size_bytes == 0) {
return;
}
MICROPROFILE_SCOPE(GPU_DownloadMemory);
if constexpr (USE_MEMORY_MAPS) {
auto download_staging = runtime.DownloadStagingBuffer(total_size_bytes);
const u8* const mapped_memory = download_staging.mapped_span.data();
const std::span<BufferCopy> copies_span(copies.data(), copies.data() + copies.size());
for (BufferCopy& copy : copies) {
// Modify copies to have the staging offset in mind
copy.dst_offset += download_staging.offset;
}
runtime.CopyBuffer(download_staging.buffer, buffer, copies_span);
runtime.Finish();
for (const BufferCopy& copy : copies) {
const VAddr copy_cpu_addr = buffer.CpuAddr() + copy.src_offset;
// Undo the modified offset
const u64 dst_offset = copy.dst_offset - download_staging.offset;
const u8* copy_mapped_memory = mapped_memory + dst_offset;
cpu_memory.WriteBlockUnsafe(copy_cpu_addr, copy_mapped_memory, copy.size);
}
} else {
const std::span<u8> immediate_buffer = ImmediateBuffer(largest_copy);
for (const BufferCopy& copy : copies) {
buffer.ImmediateDownload(copy.src_offset, immediate_buffer.subspan(0, copy.size));
const VAddr copy_cpu_addr = buffer.CpuAddr() + copy.src_offset;
cpu_memory.WriteBlockUnsafe(copy_cpu_addr, immediate_buffer.data(), copy.size);
}
}
}
template <class P>
void BufferCache<P>::DeleteBuffer(BufferId buffer_id) {
const auto scalar_replace = [buffer_id](Binding& binding) {
@@ -1236,6 +1310,7 @@ void BufferCache<P>::DeleteBuffer(BufferId buffer_id) {
Unregister(buffer_id);
delayed_destruction_ring.Push(std::move(slot_buffers[buffer_id]));
slot_buffers.erase(buffer_id);
NotifyBufferDeletion();
}

View File

@@ -3,7 +3,21 @@
// Refer to the license.txt file included.
#include <array>
extern "C" {
#if defined(__GNUC__) || defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
#endif
#include <libswscale/swscale.h>
#if defined(__GNUC__) || defined(__clang__)
#pragma GCC diagnostic pop
#endif
}
#include "common/assert.h"
#include "common/logging/log.h"
#include "video_core/command_classes/nvdec.h"
#include "video_core/command_classes/vic.h"
#include "video_core/engines/maxwell_3d.h"
@@ -11,10 +25,6 @@
#include "video_core/memory_manager.h"
#include "video_core/textures/decoders.h"
extern "C" {
#include <libswscale/swscale.h>
}
namespace Tegra {
Vic::Vic(GPU& gpu_, std::shared_ptr<Nvdec> nvdec_processor_)

View File

@@ -242,6 +242,7 @@ public:
return 4;
default:
UNREACHABLE();
return 1;
}
}

View File

@@ -11,12 +11,8 @@
#define UNIFORM(n)
#define BINDING_INPUT_BUFFER 0
#define BINDING_ENC_BUFFER 1
#define BINDING_6_TO_8_BUFFER 2
#define BINDING_7_TO_8_BUFFER 3
#define BINDING_8_TO_8_BUFFER 4
#define BINDING_BYTE_TO_16_BUFFER 5
#define BINDING_SWIZZLE_BUFFER 6
#define BINDING_OUTPUT_IMAGE 7
#define BINDING_SWIZZLE_BUFFER 2
#define BINDING_OUTPUT_IMAGE 3
#else // ^^^ Vulkan ^^^ // vvv OpenGL vvv
@@ -26,10 +22,6 @@
#define BINDING_SWIZZLE_BUFFER 0
#define BINDING_INPUT_BUFFER 1
#define BINDING_ENC_BUFFER 2
#define BINDING_6_TO_8_BUFFER 3
#define BINDING_7_TO_8_BUFFER 4
#define BINDING_8_TO_8_BUFFER 5
#define BINDING_BYTE_TO_16_BUFFER 6
#define BINDING_OUTPUT_IMAGE 0
#endif
@@ -76,19 +68,6 @@ layout(binding = BINDING_INPUT_BUFFER, std430) readonly buffer InputBufferU32 {
layout(binding = BINDING_ENC_BUFFER, std430) readonly buffer EncodingsValues {
EncodingData encoding_values[];
};
// ASTC Precompiled tables
layout(binding = BINDING_6_TO_8_BUFFER, std430) readonly buffer REPLICATE_6_BIT_TO_8 {
uint REPLICATE_6_BIT_TO_8_TABLE[];
};
layout(binding = BINDING_7_TO_8_BUFFER, std430) readonly buffer REPLICATE_7_BIT_TO_8 {
uint REPLICATE_7_BIT_TO_8_TABLE[];
};
layout(binding = BINDING_8_TO_8_BUFFER, std430) readonly buffer REPLICATE_8_BIT_TO_8 {
uint REPLICATE_8_BIT_TO_8_TABLE[];
};
layout(binding = BINDING_BYTE_TO_16_BUFFER, std430) readonly buffer REPLICATE_BYTE_TO_16 {
uint REPLICATE_BYTE_TO_16_TABLE[];
};
layout(binding = BINDING_OUTPUT_IMAGE, rgba8) uniform writeonly image2DArray dest_image;
@@ -139,6 +118,19 @@ const uint REPLICATE_4_BIT_TO_6_TABLE[16] =
const uint REPLICATE_5_BIT_TO_6_TABLE[32] =
uint[](0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 33, 35, 37, 39, 41, 43, 45,
47, 49, 51, 53, 55, 57, 59, 61, 63);
const uint REPLICATE_6_BIT_TO_8_TABLE[64] =
uint[](0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 65, 69, 73, 77, 81, 85, 89,
93, 97, 101, 105, 109, 113, 117, 121, 125, 130, 134, 138, 142, 146, 150, 154, 158, 162,
166, 170, 174, 178, 182, 186, 190, 195, 199, 203, 207, 211, 215, 219, 223, 227, 231, 235,
239, 243, 247, 251, 255);
const uint REPLICATE_7_BIT_TO_8_TABLE[128] =
uint[](0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44,
46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88,
90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126,
129, 131, 133, 135, 137, 139, 141, 143, 145, 147, 149, 151, 153, 155, 157, 159, 161, 163,
165, 167, 169, 171, 173, 175, 177, 179, 181, 183, 185, 187, 189, 191, 193, 195, 197, 199,
201, 203, 205, 207, 209, 211, 213, 215, 217, 219, 221, 223, 225, 227, 229, 231, 233, 235,
237, 239, 241, 243, 245, 247, 249, 251, 253, 255);
// Input ASTC texture globals
uint current_index = 0;
@@ -207,8 +199,7 @@ uint Replicate(uint val, uint num_bits, uint to_bit) {
}
uvec4 ReplicateByteTo16(uvec4 value) {
return uvec4(REPLICATE_BYTE_TO_16_TABLE[value.x], REPLICATE_BYTE_TO_16_TABLE[value.y],
REPLICATE_BYTE_TO_16_TABLE[value.z], REPLICATE_BYTE_TO_16_TABLE[value.w]);
return value * 0x101;
}
uint ReplicateBitTo7(uint value) {
@@ -236,7 +227,7 @@ uint FastReplicateTo8(uint value, uint num_bits) {
case 7:
return REPLICATE_7_BIT_TO_8_TABLE[value];
case 8:
return REPLICATE_8_BIT_TO_8_TABLE[value];
return value;
}
return Replicate(value, num_bits, 8);
}
@@ -763,7 +754,7 @@ void ComputeEndpoints(out uvec4 ep1, out uvec4 ep2, uint color_endpoint_mode) {
case 1: {
READ_UINT_VALUES(2)
uint L0 = (v[0] >> 2) | (v[1] & 0xC0);
uint L1 = max(L0 + (v[1] & 0x3F), 0xFFU);
uint L1 = min(L0 + (v[1] & 0x3F), 0xFFU);
ep1 = uvec4(0xFF, L0, L0, L0);
ep2 = uvec4(0xFF, L1, L1, L1);
break;
@@ -1327,6 +1318,9 @@ void main() {
offset += swizzle;
const ivec3 coord = ivec3(gl_GlobalInvocationID * uvec3(block_dims, 1));
if (any(greaterThanEqual(coord, imageSize(dest_image)))) {
return;
}
uint block_index =
pos.z * gl_WorkGroupSize.x * gl_WorkGroupSize.y + pos.y * gl_WorkGroupSize.x + pos.x;

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