Compare commits

..

201 Commits

Author SHA1 Message Date
ReinUsesLisp
e6c60b419c yuzu/bootmanager: Explicitly enable deprecated OpenGL features on compat
Nvidia's proprietary driver creates a real OpenGL compatibility profile
without this option, meanwhile Intel (and probably AMD, I haven't tested
it) require that QSurfaceFormat::FormatOption::DeprecatedFunctions is
explicitly enabled.
2019-05-17 04:09:17 -03:00
Mat M
c4d549919f Merge pull request #2462 from lioncash/video-mm
video_core/memory_manager: Minor tidying
2019-05-14 06:40:33 -04:00
Mat M
dadcf317dc Merge pull request #2461 from lioncash/unused-var
video_core: Remove a few unused variables and functions
2019-05-14 06:36:26 -04:00
Mat M
8b933e77cd Merge pull request #2460 from lioncash/volatile
CMakeLists: Specify /volatile:iso for MSVC
2019-05-14 06:34:53 -04:00
Mat M
3e8e335a5c Merge pull request #2450 from lioncash/warn-level
CMakeLists: Explicitly specify -Wall for the non-MSVC case
2019-05-14 06:34:05 -04:00
Rodrigo Locatti
940a71089d Merge pull request #2413 from FernandoS27/opt-gpu
Rasterizer Cache: refactor flushing & optimize memory usage of surfaces
2019-05-13 23:01:59 -03:00
Lioncash
716fbaef74 video_core/memory_manager: Mark IsBlockContinuous() as a const member function
Corrects the typo in its name and marks the function as a const member
function, given it doesn't actually modify memory manager state.
2019-05-09 19:14:36 -04:00
Lioncash
d4bcd006b2 video_core/memory_manager: Mark the constructor as explicit
Prevents implicit converting constructions of the memory manager.
2019-05-09 19:10:26 -04:00
Lioncash
fd12788967 video_core/memory_manager: Default the destructor within the cpp file
Makes the class less surprising when it comes to forward declaring the
type, and also prevents inlining the destruction code of the class,
given it contains non-trivial types.
2019-05-09 19:10:13 -04:00
Lioncash
53afe47cec video_core/memory_manager: Amend doxygen comments
Corrects references to non-existent parameters and corrects typos.
2019-05-09 19:09:19 -04:00
Lioncash
5235b053b4 video_core/memory_manager: Remove superfluous const from function declarations
These are able to be omitted from the declaration of functions, since
they don't do anything at the type system level. The definitions of the
functions can retain the use of const though, since they make the
variables immutable in the implementation of the function where they're
used.
2019-05-09 18:59:49 -04:00
Lioncash
b6408e9671 video_core/renderer_opengl/gl_shader_cache: Correct member initialization order
Silences a -Wreorder warning.
2019-05-09 18:55:47 -04:00
Lioncash
e43ba3acd4 video_core/shader/decode/texture: Remove unused variable from GetTld4Code() 2019-05-09 18:49:56 -04:00
Lioncash
e3c45b4338 renderer_vulkan/vk_shader_decompiler: Remove unused variable from DeclareInternalFlags() 2019-05-09 18:47:48 -04:00
Lioncash
175fe8aaeb video_core/renderer_opengl/gl_shader_decompiler: Remove unused Composite() function
This isn't used at all, so it can be removed.
2019-05-09 18:45:26 -04:00
Lioncash
6d28d288a3 video_core/renderer_opengl/gl_rasterizer_cache: Remove unused variable in UploadGLMipmapTexture()
This variable is unused entirely, so it can be removed.
2019-05-09 18:42:48 -04:00
Lioncash
ba165b1092 video_core/gpu_thread: Remove unused local variable
Instead of retrieving the data from the std::variant instance, we can
just check if the variant contains that type of data.

This is essentially the same behavior, only it returns a bool indicating
whether or not the type in the variant is currently active, instead of
actually retrieving the data.
2019-05-09 18:39:21 -04:00
Lioncash
c56d893e77 video_core/textures/astc: Remove unused variables
Silences a few compilation warnings.
2019-05-09 18:33:36 -04:00
Lioncash
c4d03f0154 CMakeLists: Specify /volatile:iso for MSVC
By default, MSVC doesn't use standards-compliant volatile semantics.
This makes it behave in a standards-compliant manner, making
expectations more uniform across compilers.
2019-05-09 15:49:30 -04:00
bunnei
7cb17834c7 Merge pull request #2437 from lioncash/audctl
service/audctl: Update documentation comments to be relative to 8.0.0
2019-05-09 13:24:13 -04:00
bunnei
f3317cf2db Merge pull request #2454 from lioncash/cflag
src/CMakeLists: Add /Zc:externConstexpr to the MSVC build flags
2019-05-09 13:23:49 -04:00
bunnei
daca045fcd Merge pull request #2442 from FernandoS27/astc-fix
Fix Layered ASTC Textures
2019-05-09 13:23:14 -04:00
bunnei
f69d3a6351 Merge pull request #2443 from ReinUsesLisp/skip-repeated-variants
gl_shader_disk_cache: Skip stored shader variants instead of asserting
2019-05-09 13:22:42 -04:00
bunnei
5907619a04 Merge pull request #2445 from FearlessTobi/port-4749
Port citra-emu/citra#4749: "web_service: Misc fixes"
2019-05-09 13:22:00 -04:00
bunnei
9567b3a293 Merge pull request #2458 from lioncash/hotkey
yuzu/hotkeys: Remove unnecessary constructor
2019-05-09 13:21:36 -04:00
bunnei
c6f3831320 Merge pull request #2456 from lioncash/qualifier
yuzu/compatdb: Remove unnecessary qualifiers
2019-05-09 13:21:04 -04:00
bunnei
8abf0add04 Merge pull request #2459 from lioncash/what
configure_dialog: Remove the Whats This? button from the dialog
2019-05-09 13:20:12 -04:00
bunnei
5b6571c170 Merge pull request #2453 from lioncash/enum
core/memory: Remove unused FlushMode enum
2019-05-09 13:19:49 -04:00
bunnei
c27b81cb85 Merge pull request #2429 from FernandoS27/compute
Corrections and Implementation on GPU Engines
2019-05-09 13:19:22 -04:00
bunnei
0e9a17b029 Merge pull request #2440 from lioncash/dynarmic
externals: Update dynarmic to master
2019-05-09 13:18:49 -04:00
Lioncash
f3c18d622e configure_dialog: Remove the Whats This? button from the dialog 2019-05-09 03:20:13 -04:00
Lioncash
8bdef4f951 yuzu/hotkeys: Remove unnecessary constructor
The behavior of the Hotkey constructor is already accomplished via in-class member
initializers, so the constructor is superfluous here.
2019-05-09 02:17:22 -04:00
Lioncash
a97120efc1 yuzu/compatdb: Remove unnecessary qualifiers
Keeps the code consistent in regards to how the buttons are referred to.
2019-05-09 01:08:06 -04:00
Lioncash
70c6506a7e src/CMakeLists: Add /Zc:externConstexpr to the MSVC build flags
The C++ standard allows constexpr variables declared with the extern
keyword to have external linkage. Previously MSVC wasn't abiding by
this. This just makes the compiler more standards compliant during
builds.

Given we currently don't make use of anything that would break by this,
this is safe to enable.
2019-05-07 14:06:22 -04:00
Lioncash
6ca7241bd9 src/CMakeLists: Vertically order compilation flags
Makes it much nicer to visually scan the options. This also starts the
flag descriptions from the same column for the same reason.
2019-05-07 14:05:48 -04:00
Lioncash
495a8d8d95 core/memory: Remove unused FlushMode enum
Recent changes to memory-related code resulted in this being unused, so
we can remove it.
2019-05-07 13:55:17 -04:00
Lioncash
0964444529 externals: Update dynarmic to master
Better instruction support has been added since the last update.
2019-05-07 10:39:25 -04:00
Merry
c63e68c480 Merge pull request #2451 from lioncash/travis
travis: Update to using Xcode 10.2
2019-05-07 15:36:13 +01:00
Lioncash
4aefd45193 travis: Update to using Xcode 10.2
Keeps the CI toolchain updated. This is also necessary for updating
dynarmic.
2019-05-07 06:40:30 -04:00
Rodrigo Locatti
6743982d28 Merge pull request #2447 from lioncash/dtor
core/frontend/emu_window: Make GraphicsContext's destructor virtual
2019-05-07 05:54:04 -03:00
Rodrigo Locatti
57db3f6763 Merge pull request #2448 from lioncash/pragma
common/zstd_compression: Remove #pragma once directive from source file
2019-05-07 05:51:37 -03:00
Rodrigo Locatti
a206418846 Merge pull request #2449 from lioncash/unused-var
gl_rasterizer: Silence unused variable warnings
2019-05-07 05:50:59 -03:00
zhupengfei
10c4f23953 core/telemetry_session: Only create the backend when we really need it
The backend is not used until we decide to submit the testcase/telemetry, and creating it early prevents users from updating the credentials properly while the games are running.
2019-05-04 19:45:48 +02:00
Lioncash
9e15193ef8 shader/decode/texture: Remove unused variable
This isn't used anywhere, so we can get rid of it.
2019-05-04 02:10:38 -04:00
Lioncash
5d0dca73c6 CMakeLists: Explicitly specify -Wall for the non-MSVC case
Ensures that -Wall is always active as a compilation flag.
2019-05-04 02:06:56 -04:00
Lioncash
08b270676b gl_rasterizer: Silence unused variable warning
Makes use of src, so it's not considered unused.
2019-05-04 02:00:17 -04:00
Lioncash
a6f7a44aab common/zstd_compression: Remove #pragma once directive from source file
Introduced in 72477731ed. This is only
necessary within header files.
2019-05-04 01:54:29 -04:00
Lioncash
1230a0e7ce core/frontend/emu_window: Make GraphicsContext's destructor virtual
This class is used in a polymorphic context, so destruction of the
context will lead to undefined behavior if the destructor isn't virtual.
2019-05-04 01:47:38 -04:00
bunnei
1f72bb733f Merge pull request #2408 from FearlessTobi/port-4215
Port citra-emu/citra#4215: "travis: Use Ninja for Travis builds"
2019-05-02 20:59:09 -04:00
Fernando Sahmkow
e64c41efe8 Refactors and name corrections. 2019-05-01 15:31:39 -04:00
ReinUsesLisp
4aa081b4e7 gl_shader_disk_cache: Skip stored shader variants instead of asserting
Instead of asserting on already stored shader variants, silently skip them.
This shouldn't be happening but when a shader is invalidated and it is
not stored in the shader cache, this assert would hit and save that
shader anyways when the asserts are disabled.
2019-05-01 00:36:11 -03:00
Fernando Sahmkow
95261639fb Fix Layered ASTC Textures
By adding the missing layer offset in ASTC compression.
2019-04-30 23:02:31 -04:00
Lioncash
75a8b304d4 loader/nso: Remove left-in debug pragma
Unintentionally introduced in 552d5071fa
2019-04-30 22:55:53 -04:00
bunnei
fb420358a9 Merge pull request #2406 from FearlessTobi/port-3839
Port citra-emu/citra#3839: "travis: use prebuilt image"
2019-04-30 19:25:53 -04:00
bunnei
79e54abe19 Merge pull request #2100 from FreddyFunk/disk-cache-precompiled-file
gl_shader_disk_cache: Improve precompiled shader cache generation speed and size
2019-04-30 19:24:01 -04:00
bunnei
91e239d66f Merge pull request #2435 from ReinUsesLisp/misc-vc
shader_ir: Miscellaneous fixes
2019-04-28 22:29:43 -04:00
bunnei
2be32eb3d2 Merge pull request #2412 from lioncash/system
kernel/vm_manager: Remove usages of global system accessors
2019-04-28 22:27:14 -04:00
bunnei
c52233ec8b Merge pull request #2322 from ReinUsesLisp/wswitch
video_core: Silent -Wswitch warnings
2019-04-28 22:24:58 -04:00
bunnei
9a3737120d Merge pull request #2423 from FernandoS27/half-correct
Corrections on Half Float operations: HADD2 HMUL2 and HFMA2
2019-04-28 22:24:22 -04:00
Lioncash
565fce71b1 service/audctl: Update documentation comments to be relative to 8.0.0
The state of these service calls are still the same in version 8.0.0.
2019-04-27 23:17:58 -04:00
ReinUsesLisp
2156e52014 shader_ir: Move Sampler index entry in operand< to sort declarations 2019-04-26 01:13:05 -03:00
ReinUsesLisp
b77b4b76bb shader_ir: Add missing entry to Sampler operand< comparison 2019-04-26 01:11:24 -03:00
ReinUsesLisp
0b91087a1e shader_ir/texture: Fix sampler const buffer key shift 2019-04-26 01:09:29 -03:00
bunnei
78574e7a47 Merge pull request #2416 from lioncash/wait
kernel/svc: Clean up wait synchronization related functionality
2019-04-24 22:56:08 -04:00
bunnei
94db649205 Merge pull request #2424 from FernandoS27/compat
Allow picking a Compatibility Profile for OpenGL.
2019-04-24 22:54:27 -04:00
bunnei
ee2252b6e1 Merge pull request #2426 from FearlessTobi/port-4748
Port citra-emu/citra#4748: "Launch directly in Mac without terminal"
2019-04-24 22:53:48 -04:00
bunnei
53f746fa9a Merge pull request #2228 from DarkLordZach/applet-manager-p1
applets: Add AppletManager and implement PhotoViewer and Error applets
2019-04-24 22:53:21 -04:00
bunnei
0592869076 Merge pull request #2404 from lioncash/unicode
CMakeLists: Ensure we specify Unicode as the codepage on Windows
2019-04-24 22:51:17 -04:00
FreddyFunk
1a3ff252a4 Re added new lines at the end of files 2019-04-23 23:19:28 +02:00
unknown
3091b40691 gl_shader_disk_cache: Compress precompiled shader cache file with Zstandard 2019-04-23 22:24:31 +02:00
unknown
9db2c734c9 gl_shader_disk_cache: Use VectorVfsFile for the virtual precompiled shader cache file 2019-04-23 22:24:23 +02:00
unknown
3fe542cf60 gl_shader_disk_cache: Remove per shader compression 2019-04-23 21:40:01 +02:00
Fernando Sahmkow
b3118ee316 Fixes and Corrections to DMA Engine 2019-04-23 15:28:18 -04:00
Hexagon12
8df9449bb8 Merge pull request #2422 from ReinUsesLisp/fixup-samplers
gl_state: Fix samplers memory corruption
2019-04-23 18:30:35 +03:00
Hexagon12
b2fbcaae30 Merge pull request #2425 from FernandoS27/y-direction
Fix flipping on some games by applying Y direction register
2019-04-23 18:29:29 +03:00
Fernando Sahmkow
f1e5314f1a Add Swizzle Parameters to the DMA engine 2019-04-23 11:21:00 -04:00
Fernando Sahmkow
e140e2ebc6 Add Documentation Headers to all the GPU Engines 2019-04-23 08:44:52 -04:00
Fernando Sahmkow
021d28c9b8 Corrections and styling 2019-04-23 08:02:24 -04:00
bunnei
4fad91ca45 Merge pull request #2383 from ReinUsesLisp/aoffi-test
gl_shader_decompiler: Disable variable AOFFI on unsupported devices
2019-04-22 22:14:02 -04:00
bunnei
9cab042674 Merge pull request #2420 from lioncash/audctl
service/audctl: Implement GetTargetVolumeMin() and GetTargetVolumeMax()
2019-04-22 22:12:48 -04:00
Fernando Sahmkow
701ce1c9d0 Implement Maxwell3D Data Upload 2019-04-22 19:27:36 -04:00
Fernando Sahmkow
e4ff140b99 Introduce skeleton of the GPU Compute Engine. 2019-04-22 19:05:43 -04:00
Fernando Sahmkow
a91d3fc639 Revamp Kepler Memory to use a subegine to manage uploads 2019-04-22 18:50:56 -04:00
bunnei
b5889cbd6f Merge pull request #2403 from FernandoS27/compressed-linear
Support compressed formats on linear textures.
2019-04-22 17:09:42 -04:00
bunnei
68b707711a Merge pull request #2411 from FernandoS27/unsafe-gpu
GPU Manager: Implement ReadBlockUnsafe and WriteBlockUnsafe
2019-04-22 17:09:00 -04:00
bunnei
01100f8afd Merge pull request #2400 from FernandoS27/corret-kepler-mem
Implement Kepler Memory on both Linear and BlockLinear.
2019-04-22 16:47:05 -04:00
Fernando Sahmkow
4c36b78567 Rasterizer Cache: Use a temporal storage for Surfaces loading/flushing.
This PR should heavily reduce memory usage since temporal buffers are no
longer stored per Surface but instead managed by the Rasterizer Cache.
2019-04-21 11:42:07 -04:00
Fernando Sahmkow
623b2e4b8f Corrections Half Float operations on const buffers and implement saturation. 2019-04-20 21:11:33 -04:00
tkeph616
92c274d4bb Launch directly in Mac without terminal 2019-04-20 20:31:34 +02:00
bunnei
da0c3bc658 Merge pull request #2407 from FernandoS27/f2f
Do some corrections in conversion shader instructions.
2019-04-20 00:42:34 -04:00
Fernando Sahmkow
788497fd9d Allow picking a Compatibility Profile for OpenGL.
This option allows picking the compatibility profile since a lot of bugs
are fixed in it. We devs will use this option to easierly debug current
problems in our Core implementation.:wq
2019-04-20 00:05:24 -04:00
bunnei
650d9b1044 Merge pull request #2409 from ReinUsesLisp/half-floats
shader_ir/decode: Miscellaneous fixes to half-float decompilation
2019-04-19 21:31:52 -04:00
Fernando Sahmkow
08cdcc2871 Apply Position Y Direction 2019-04-19 20:49:00 -04:00
Fernando Sahmkow
a3eb91ed8c RasterizerCache Redesign: Flush
flushing is now responsability of children caches instead of the cache 
object. This change will allow the specific cache to pass extra 
parameters on flushing and will allow more flexibility.
2019-04-19 20:44:56 -04:00
Fernando Sahmkow
db4b2bc798 make ReadBlockunsafe and WriteBlockunsafe, ignore invalid pages. 2019-04-19 20:35:54 -04:00
bunnei
62c2404d3c Merge pull request #2415 from lioncash/const
kernel/wait_object: Make GetHighestPriorityReadyThread() a const member function
2019-04-19 19:12:02 -04:00
bunnei
cd38eadcc1 Merge pull request #2414 from lioncash/reorder
yuzu/bootmanager: Resolve constructor initializer list warnings
2019-04-19 19:11:47 -04:00
bunnei
b6faea0dd2 Merge pull request #2421 from lioncash/svc-call
kernel/svc: Name supervisor call 0x36
2019-04-19 19:10:20 -04:00
bunnei
40dc893c37 Merge pull request #2374 from lioncash/pagetable
core: Reorganize boot order
2019-04-19 19:09:20 -04:00
ReinUsesLisp
d74cb16535 gl_state: Fix samplers memory corruption
It was possible for "samplers" to be read without being written. This
addresses that.
2019-04-19 17:07:56 -03:00
Lioncash
f8be3f55da kernel/svc: Name supervisor call 0x36
This call was added to the SVC handlers in the 8.0.0 kernel, so we can
finally give it a name.
2019-04-19 14:34:56 -04:00
Lioncash
19f8f86bdb service/audctl: Implement GetTargetVolumeMin() and GetTargetVolumeMax()
These two service functions are literally hardcoded to always return
these values without any other error checking.
2019-04-18 16:39:54 -04:00
bunnei
83b830eb2f Merge pull request #2397 from lioncash/thread-unused
kernel/thread: Remove unused guest_handle member variable
2019-04-17 21:46:46 -04:00
bunnei
4294062516 Merge pull request #2318 from ReinUsesLisp/sampler-cache
gl_sampler_cache: Port sampler cache to OpenGL
2019-04-17 21:45:56 -04:00
bunnei
5bd5140bde Merge pull request #2348 from FernandoS27/guest-bindless
Implement Bindless Textures on Shader Decompiler and GL backend
2019-04-17 20:59:49 -04:00
Zach Hilman
2adb226b26 web_browser: Make OpenPage non-const 2019-04-17 11:35:24 -04:00
Zach Hilman
8f8049e846 main: Add GMainWindow hooks for Error display 2019-04-17 11:35:24 -04:00
Zach Hilman
a04d36c5a4 main: Switch to AppletManager for frontend 2019-04-17 11:35:24 -04:00
Zach Hilman
76452cd5b3 qt: Add dialog implementation of Error applet 2019-04-17 11:35:24 -04:00
Zach Hilman
f6e2295055 general_backend: Move StubApplet and add backend PhotoViewer 2019-04-17 11:35:24 -04:00
Zach Hilman
80c9e4d3ab general_frontend: Add frontend scaffold for PhotoViewer applet 2019-04-17 11:35:24 -04:00
Zach Hilman
d9f6715d45 frontend: Add frontend receiver for Error applet 2019-04-17 11:35:24 -04:00
Zach Hilman
de3cfb1d37 applets: Add Error applet
Responsible for displaying error codes and messages
2019-04-17 11:35:24 -04:00
Zach Hilman
d273bec68f applets: Port current applets to take frontend in constructor
As opposed to using Core::System::GetInstance()
2019-04-17 11:35:24 -04:00
Zach Hilman
f7540157e4 web_browser: Make OpenPage const 2019-04-17 11:35:24 -04:00
Zach Hilman
ec0bc3061e core: Remove specific applets in favor of AppletManager 2019-04-17 11:35:24 -04:00
Zach Hilman
6cea62b756 am: Delegate applet creation to AppletManager 2019-04-17 11:35:24 -04:00
Zach Hilman
e51d33f0ce applets: Add AppletManager class to control lifetime 2019-04-17 11:35:24 -04:00
Lioncash
c268ffd831 kernel/thread: Unify wait synchronization types
This is a holdover from Citra, where the 3DS has both
WaitSynchronization1 and WaitSynchronizationN. The switch only has one
form of wait synchronizing (literally WaitSynchonization). This allows
us to throw out code that doesn't apply at all to the Switch kernel.

Because of this unnecessary dichotomy within the wait synchronization
utilities, we were also neglecting to properly handle waiting on
multiple objects.

While we're at it, we can also scrub out any lingering references to
WaitSynchronization1/WaitSynchronizationN in comments, and change them
to WaitSynchronization (or remove them if the mention no longer
applies).
2019-04-17 09:30:56 -04:00
Lioncash
433b59c112 kernel/svc: Migrate svcCancelSynchronization behavior to a thread function
The actual behavior of this function is slightly more complex than what
we're currently doing within the supervisor call. To avoid dumping most
of this behavior in the supervisor call itself, we can migrate this to
another function.
2019-04-17 09:30:56 -04:00
Lioncash
6b2bece81f kernel/wait_object: Make GetHighestPriorityReadyThread() a const member function
This doesn't actually modify internal state of a wait object, so it can
be const qualified.
2019-04-17 06:44:34 -04:00
Lioncash
54e9f9b6ed yuzu/bootmanager: Replace unnnecessary constructor initializer list member of GGLContext
The default constructor will always run, even when not specified, so
this is redundant.

However, the context member can indeed be initialized in the constructor
initializer list.
2019-04-17 00:04:10 -04:00
Lioncash
52e43734c4 yuzu/bootmanager: Remove unnecessary includes
This include isn't used anymore so it can be removed.
2019-04-16 23:52:57 -04:00
Lioncash
fbfc347351 yuzu/bootmanager: Resolve constructor initializer list warnings
Resolves -Wreorder warnings. These will automatically be initialized to
nullptr anyways, so these were redundant.
2019-04-16 23:49:26 -04:00
bunnei
0cfbd3325b Merge pull request #2315 from ReinUsesLisp/severity-decompiler
shader_ir/decode: Reduce the severity of common assertions
2019-04-16 22:21:19 -04:00
bunnei
21d498bc06 Merge pull request #2384 from ReinUsesLisp/gl-state-clear
gl_rasterizer: Apply just the needed state on Clear
2019-04-16 22:19:03 -04:00
bunnei
be6b9e2d2b Merge pull request #2405 from lioncash/qt
CMakeLists: Define QT_USE_QSTRINGBUILDER for the Qt target
2019-04-16 22:17:09 -04:00
bunnei
1b83f255c2 Merge pull request #2092 from ReinUsesLisp/stg
shader/memory: Implement STG and global memory flushing
2019-04-16 22:15:17 -04:00
bunnei
2654eb659e Merge pull request #2376 from lioncash/const
yuzu/configure_hotkey: Minor changes
2019-04-16 22:13:12 -04:00
bunnei
382fbbb198 Merge pull request #2401 from lioncash/guard
common/{lz4_compression, zstd_compression}: Add missing header guards
2019-04-16 22:11:04 -04:00
Lioncash
819c21d99e CMakeLists: Ensure we specify Unicode as the codepage on Windows
Previously we were building with MBCS, which is pretty undesirable. We
want the application to be Unicode-aware in general.

Currently, we make the command line variant of yuzu use ANSI variants of
the non-standard getopt functions that we link in for Windows, given we
only have an ANSI option-set.

We should really replace getopt with a library that we make all build
types of yuzu link in, but this will have to do for the time being.
2019-04-16 21:23:34 -04:00
Lioncash
b6a87b422e kernel/vm_manager: Remove usages of global system accessors
Makes the dependency on the system instance explicit within VMManager's
interface.
2019-04-16 20:02:50 -04:00
Fernando Sahmkow
d0082de82a Implement IsBlockContinous
This detects when a GPU Memory Block is not continous within host cpu
memory.
2019-04-16 18:49:35 -04:00
Fernando Sahmkow
da91e6e4b6 Apply Const correctness to SwizzleKepler and replace u32 for size_t on iterators. 2019-04-16 12:00:46 -04:00
Fernando Sahmkow
13d626fc21 Use ReadBlockUnsafe for fetyching DMA CommandLists 2019-04-16 11:22:34 -04:00
Fernando Sahmkow
06d1c5a991 Document unsafe versions and add BlockCopyUnsafe 2019-04-16 10:11:35 -04:00
Fernando Sahmkow
6fc562a9aa Use ReadBlockUnsafe for Shader Cache 2019-04-15 23:34:03 -04:00
Fernando Sahmkow
ef381e6924 Use ReadBlockUnsafe on TIC and TSC reading
Use ReadBlockUnsafe on TIC and TSC reading as memory is never flushed
from host GPU there.
2019-04-15 23:10:24 -04:00
Fernando Sahmkow
367704aa82 GPU MemoryManager: Implement ReadBlockUnsafe and WriteBlockUnsafe 2019-04-15 23:01:35 -04:00
Fernando Sahmkow
3e96c367bd Use WriteBlock and ReadBlock. 2019-04-15 22:42:34 -04:00
bunnei
9186f76b07 Merge pull request #2382 from lioncash/table
service: Update service function tables
2019-04-15 21:46:15 -04:00
bunnei
fc64156533 Merge pull request #2393 from lioncash/svc
kernel/svc: Implement svcMapProcessCodeMemory/svcUnmapProcessCodeMemory
2019-04-15 21:43:56 -04:00
bunnei
a7c3275b8b Merge pull request #2398 from lioncash/boost
kernel/thread: Remove BoostPriority()
2019-04-15 21:42:16 -04:00
bunnei
c1e35d117c Merge pull request #2399 from FernandoS27/fermi-fix
Correct Pitch in Fermi2D
2019-04-15 21:41:52 -04:00
Fernando Sahmkow
bec28d692d Implement Block Linear copies in Kepler Memory. 2019-04-15 21:22:16 -04:00
ReinUsesLisp
ef8245bed2 vk_shader_decompiler: Add missing operations 2019-04-15 21:32:57 -03:00
ReinUsesLisp
f43995ec53 shader_ir/decode: Fix half float pre-operations and remove MetaHalfArithmetic
Operations done before the main half float operation (like HAdd) were
managing a packed value instead of the unpacked one. Adding an unpacked
operation allows us to drop the per-operand MetaHalfArithmetic entry,
simplifying the code overall.
2019-04-15 21:16:10 -03:00
ReinUsesLisp
abcbcb1b2a gl_shader_decompiler: Fix MrgH0 decompilation
GLSL decompilation for HMergeH0 was wrong. This addresses that issue.
2019-04-15 21:16:10 -03:00
ReinUsesLisp
64613db605 shader_ir/decode: Implement half float saturation 2019-04-15 21:16:10 -03:00
ReinUsesLisp
90cbf89303 shader_ir/decode: Reduce severity of unimplemented half-float FTZ 2019-04-15 21:16:09 -03:00
ReinUsesLisp
acf618afbc renderer_opengl: Implement half float NaN comparisons 2019-04-15 21:13:26 -03:00
ReinUsesLisp
ae46ad48ed shader_ir: Avoid using static on heap-allocated objects
Using static here might be faster at runtime, but it adds a heap
allocation called before main.
2019-04-15 21:12:43 -03:00
Fernando Sahmkow
aa471274d9 Do some corrections in conversion shader instructions.
Corrects encodings for I2F, F2F, I2I and F2I
Implements Immediate variants of all four conversion types.
Add assertions to unimplemented stuffs.
2019-04-15 19:16:27 -04:00
Cameron Cawley
1f3cc036da travis: Use Ninja for Travis builds 2019-04-16 01:06:34 +02:00
fearlessTobi
b67be7154d GenerateSCMRev: fix Travis compilation on repo forks 2019-04-16 00:34:22 +02:00
Lioncash
d28bb56c91 CMakeLists: Define QT_USE_QSTRINGBUILDER for the Qt target
This is a compile definition introduced in Qt 4.8 for reducing the total
potential number of strings created when performing string
concatenation. This allows for less memory churn.

This can be read about here:
https://blog.qt.io/blog/2011/06/13/string-concatenation-with-qstringbuilder/

For a change that isn't source-compatible, we only had one occurrence
that actually need to have its type clarified, which is pretty good, as
far as transitioning goes.
2019-04-15 17:59:41 -04:00
liushuyu
a9f58593d4 travis: use prebuilt image (#3839)
* travis: use prebuilt image

* travis: use prebuilt image (MinGW)
2019-04-15 22:22:09 +02:00
Lioncash
3283aa1e20 svc: Specify handle value in thread's name
Allows the handle to be seen alongside the entry point.
2019-04-15 15:56:18 -04:00
Fernando Sahmkow
8a099ac99f Correct Kepler Memory on Linear Pushes. 2019-04-15 14:51:36 -04:00
Fernando Sahmkow
773d955dfa Support compressed formats on linear textures. 2019-04-15 13:56:09 -04:00
Lioncash
4620ed47a3 common/{lz4_compression, zstd_compression}: Add missing header guards
These two files were missing the #pragma once directive.
2019-04-15 13:00:08 -04:00
Fernando Sahmkow
bf561e4340 Correct Pitch in Fermi2D 2019-04-15 12:24:29 -04:00
Lioncash
e3566e6c1d kernel/thread: Remove BoostPriority()
This is a holdover from Citra that currently remains unused, so it can
be removed from the Thread interface.
2019-04-15 06:59:19 -04:00
Lioncash
09caf8a756 kernel/thread: Remove unused guest_handle member variable
This member variable is entirely unused. It was only set but never
actually utilized. Given that, we can remove it to get rid of noise in
the thread interface.
2019-04-14 06:06:06 -04:00
ReinUsesLisp
f15c59a164 gl_shader_decompiler: Use variable AOFFI on supported hardware 2019-04-14 05:13:19 -03:00
ReinUsesLisp
5c280e6ff0 shader_ir: Implement STG, keep track of global memory usage and flush 2019-04-14 00:25:32 -03:00
Lioncash
4d293bb5cb kernel/svc: Implement svcUnmapProcessCodeMemory
Essentially performs the inverse of svcMapProcessCodeMemory. This unmaps
the aliasing region first, then restores the general traits of the
aliased memory.

What this entails, is:

- Restoring Read/Write permissions to the VMA.
- Restoring its memory state to reflect it as a general heap memory region.
- Clearing the memory attributes on the region.
2019-04-12 21:56:03 -04:00
Lioncash
76a2465655 kernel/svc: Implement svcMapProcessCodeMemory
This is utilized for mapping code modules into memory. Notably, the
ldr service would call this in order to map objects into memory.
2019-04-12 21:55:50 -04:00
Lioncash
612e1388df core/core: Move process execution start to System's Load()
This gives us significantly more control over where in the
initialization process we start execution of the main process.

Previously we were running the main process before the CPU or GPU
threads were initialized (not good). This amends execution to start
after all of our threads are properly set up.
2019-04-11 22:11:41 -04:00
Lioncash
32a6ceb4e5 core/process: Remove unideal page table setting from LoadFromMetadata()
Initially required due to the split codepath with how the initial main
process instance was initialized. We used to initialize the process
like:

Init() {
    main_process = Process::Create(...);
    kernel.MakeCurrentProcess(main_process.get());
}

Load() {
    const auto load_result = loader.Load(*kernel.GetCurrentProcess());
    if (load_result != Loader::ResultStatus::Success) {
        // Handle error here.
    }
    ...
}

which presented a problem.

Setting a created process as the main process would set the page table
for that process as the main page table. This is fine... until we get to
the part that the page table can have its size changed in the Load()
function via NPDM metadata, which can dictate either a 32-bit, 36-bit,
or 39-bit usable address space.

Now that we have full control over the process' creation in load, we can
simply set the initial process as the main process after all the loading
is done, reflecting the potential page table changes without any
special-casing behavior.

We can also remove the cache flushing within LoadModule(), as execution
wouldn't have even begun yet during all usages of this function, now
that we have the initialization order cleaned up.
2019-04-11 22:11:41 -04:00
Lioncash
a4b0a8559c core/core: Move main process creation into Load()
Now that we have dependencies on the initialization order, we can move
the creation of the main process to a more sensible area: where we
actually load in the executable data.

This allows localizing the creation and loading of the process in one
location, making the initialization of the process much nicer to trace.
2019-04-11 22:11:40 -04:00
Lioncash
6d0551196d video_core/gpu: Create threads separately from initialization
Like with CPU emulation, we generally don't want to fire off the threads
immediately after the relevant classes are initialized, we want to do
this after all necessary data is done loading first.

This splits the thread creation into its own interface member function
to allow controlling when these threads in particular get created.
2019-04-11 22:11:40 -04:00
Lioncash
f2331a804a core/cpu_core_manager: Create threads separately from initialization.
Our initialization process is a little wonky than one would expect when
it comes to code flow. We initialize the CPU last, as opposed to
hardware, where the CPU obviously needs to be first, otherwise nothing
else would work, and we have code that adds checks to get around this.

For example, in the page table setting code, we check to see if the
system is turned on before we even notify the CPU instances of a page
table switch. This results in dead code (at the moment), because the
only time a page table switch will occur is when the system is *not*
running, preventing the emulated CPU instances from being notified of a
page table switch in a convenient manner (technically the code path
could be taken, but we don't emulate the process creation svc handlers
yet).

This moves the threads creation into its own member function of the core
manager and restores a little order (and predictability) to our
initialization process.

Previously, in the multi-threaded cases, we'd kick off several threads
before even the main kernel process was created and ready to execute (gross!).
Now the initialization process is like so:

Initialization:
  1. Timers

  2. CPU

  3. Kernel

  4. Filesystem stuff (kind of gross, but can be amended trivially)

  5. Applet stuff (ditto in terms of being kind of gross)

  6. Main process (will be moved into the loading step in a following
                   change)

  7. Telemetry (this should be initialized last in the future).

  8. Services (4 and 5 should ideally be alongside this).

  9. GDB (gross. Uses namespace scope state. Needs to be refactored into a
          class or booted altogether).

  10. Renderer

  11. GPU (will also have its threads created in a separate step in a
           following change).

Which... isn't *ideal* per-se, however getting rid of the wonky
intertwining of CPU state initialization out of this mix gets rid of
most of the footguns when it comes to our initialization process.
2019-04-11 22:11:40 -04:00
Lioncash
ca96dc4676 service: Update service function tables
Updates function tables based off information from SwitchBrew.
2019-04-11 02:47:00 -04:00
ReinUsesLisp
6df25e9c7b gl_rasterizer: Apply just the needed state on Clear 2019-04-10 18:13:15 -03:00
ReinUsesLisp
0032821864 gl_device: Implement interface and add uniform offset alignment 2019-04-10 15:56:12 -03:00
Lioncash
e1101d3e20 configure_hotkeys: Pass the dialog as a parent to SequenceDialog()
Without passing in a parent, this can result in focus being stolen from
the dialog in certain cases.

Example:

On Windows, if the logging window is left open, the logging Window will
potentially get focus over the hotkey dialog itself, since it brings all
open windows for the application into view. By specifying a parent, we
only bring windows for the parent into view (of which there are none,
aside from the hotkey dialog).
2019-04-09 20:06:49 -04:00
Lioncash
b47c0c8a80 configure_hotkeys: Avoid dialog memory leak within Configure()
Without a parent, this dialog won't have its memory freed when it
happens to get destroyed.
2019-04-09 20:05:57 -04:00
Lioncash
dbf13f8169 configure_hotkeys: Mark member variables as const where applicable in Configure() 2019-04-09 19:50:14 -04:00
Lioncash
cf6cdd20f8 configure_hotkeys: Make comparison check a little more self-documenting
This is checking if an index is valid or not and returning early if it
isn't.
2019-04-09 19:47:20 -04:00
Lioncash
c4ba717491 configure_dialog: Amend constructor initializer list order
Avoids a -Wreorder compiler warning.
2019-04-09 19:39:43 -04:00
Lioncash
8c05dfaa61 configure_hotkey: Remove unnecessary include
Avoids dumping all of the core settings machinery into whatever files
include this header. Nothing inside the header itself actually made use
of anything in settings.h anyways.
2019-04-09 19:37:08 -04:00
Lioncash
e28a5b0d18 configure_hotkey: Make IsUsedKey() a const member function
This doesn't actually modify instance state of the dialog, so this can
be made const.
2019-04-09 19:35:54 -04:00
Fernando Sahmkow
ef8be408d3 Adapt Bindless to work with AOFFI 2019-04-08 12:07:56 -04:00
Fernando Sahmkow
492040bd9c Move ConstBufferAccessor to Maxwell3d, correct mistakes and clang format. 2019-04-08 11:36:11 -04:00
Fernando Sahmkow
797e351bf8 Fix bad rebase 2019-04-08 11:35:22 -04:00
Fernando Sahmkow
c60b0b8432 Fix TMML 2019-04-08 11:35:22 -04:00
Fernando Sahmkow
a77e9a27b0 Simplify ConstBufferAccessor 2019-04-08 11:35:19 -04:00
Fernando Sahmkow
fd4e994de3 Refactor GetTextureCode and GetTexCode to use an optional instead of optional parameters 2019-04-08 11:35:18 -04:00
Fernando Sahmkow
4841440382 Implement TXQ_B 2019-04-08 11:29:52 -04:00
Fernando Sahmkow
189bd1980c Implement TMML_B 2019-04-08 11:29:49 -04:00
Fernando Sahmkow
ac3ba9a33e Corrections to TEX_B 2019-04-08 11:28:44 -04:00
Fernando Sahmkow
90d06acfed Fixes to Const Buffer Accessor and Formatting 2019-04-08 11:23:47 -04:00
Fernando Sahmkow
7af82ca022 Implement Bindless Handling on SetupTexture 2019-04-08 11:23:46 -04:00
Fernando Sahmkow
fe392fff24 Unify both sampler types. 2019-04-08 11:23:45 -04:00
Fernando Sahmkow
e28fd3d0a5 Implement Bindless Samplers and TEX_B in the IR. 2019-04-08 11:23:42 -04:00
Fernando Sahmkow
c4ac05c82c Implement Const Buffer Accessor 2019-04-08 11:19:34 -04:00
ReinUsesLisp
04979560fb shader_ir/memory: Reduce severity of LD_L cache management and log it 2019-04-03 17:12:44 -03:00
ReinUsesLisp
24abeb9a67 shader_ir/memory: Reduce severity of ST_L cache management and log it 2019-04-03 17:12:44 -03:00
ReinUsesLisp
576ad9a012 gl_sampler_cache: Port sampler cache to OpenGL 2019-04-02 16:58:08 -03:00
ReinUsesLisp
c5047540c9 video_core: Abstract vk_sampler_cache into a templated class 2019-04-02 15:54:11 -03:00
192 changed files with 3686 additions and 1426 deletions

View File

@@ -24,7 +24,7 @@ matrix:
- os: osx
env: NAME="macos build"
sudo: false
osx_image: xcode10.1
osx_image: xcode10.2
install: "./.travis/macos/deps.sh"
script: "./.travis/macos/build.sh"
after_success: "./.travis/macos/upload.sh"

View File

@@ -1,3 +1,3 @@
#!/bin/bash -ex
mkdir "$HOME/.ccache" || true
docker run --env-file .travis/common/travis-ci.env -v $(pwd):/yuzu -v "$HOME/.ccache":/root/.ccache ubuntu:18.04 /bin/bash -ex /yuzu/.travis/linux-mingw/docker.sh
docker run --env-file .travis/common/travis-ci.env -v $(pwd):/yuzu -v "$HOME/.ccache":/root/.ccache yuzuemu/build-environments:linux-mingw /bin/bash -ex /yuzu/.travis/linux-mingw/docker.sh

View File

@@ -1,3 +1,3 @@
#!/bin/sh -ex
docker pull ubuntu:18.04
docker pull yuzuemu/build-environments:linux-mingw

View File

@@ -1,16 +1,6 @@
#!/bin/bash -ex
cd /yuzu
MINGW_PACKAGES="sdl2-mingw-w64 qt5base-mingw-w64 qt5tools-mingw-w64 libsamplerate-mingw-w64 qt5multimedia-mingw-w64"
apt-get update
apt-get install -y gpg wget git python3-pip python ccache g++-mingw-w64-x86-64 gcc-mingw-w64-x86-64 mingw-w64-tools cmake
echo 'deb http://ppa.launchpad.net/tobydox/mingw-w64/ubuntu bionic main ' > /etc/apt/sources.list.d/extras.list
apt-key adv --keyserver keyserver.ubuntu.com --recv '72931B477E22FEFD47F8DECE02FE5F12ADDE29B2'
apt-get update
apt-get install -y ${MINGW_PACKAGES}
# fix a problem in current MinGW headers
wget -q https://raw.githubusercontent.com/Alexpux/mingw-w64/d0d7f784833bbb0b2d279310ddc6afb52fe47a46/mingw-w64-headers/crt/errno.h -O /usr/x86_64-w64-mingw32/include/errno.h
# override Travis CI unreasonable ccache size
echo 'max_size = 3.0G' > "$HOME/.ccache/ccache.conf"
@@ -23,8 +13,8 @@ echo '' >> /bin/cmd
chmod +x /bin/cmd
mkdir build && cd build
cmake .. -DCMAKE_TOOLCHAIN_FILE="$(pwd)/../CMakeModules/MinGWCross.cmake" -DUSE_CCACHE=ON -DYUZU_USE_BUNDLED_UNICORN=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DCMAKE_BUILD_TYPE=Release
make -j4
cmake .. -G Ninja -DCMAKE_TOOLCHAIN_FILE="$(pwd)/../CMakeModules/MinGWCross.cmake" -DUSE_CCACHE=ON -DYUZU_USE_BUNDLED_UNICORN=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DCMAKE_BUILD_TYPE=Release
ninja
# Clean up the dirty hacks
rm /bin/uname && mv /bin/uname1 /bin/uname

View File

@@ -1,4 +1,4 @@
#!/bin/bash -ex
mkdir -p "$HOME/.ccache"
docker run -e ENABLE_COMPATIBILITY_REPORTING --env-file .travis/common/travis-ci.env -v $(pwd):/yuzu -v "$HOME/.ccache":/root/.ccache ubuntu:18.04 /bin/bash /yuzu/.travis/linux/docker.sh
docker run -e ENABLE_COMPATIBILITY_REPORTING --env-file .travis/common/travis-ci.env -v $(pwd):/yuzu -v "$HOME/.ccache":/root/.ccache yuzuemu/build-environments:linux-fresh /bin/bash /yuzu/.travis/linux/docker.sh

View File

@@ -1,3 +1,3 @@
#!/bin/sh -ex
docker pull ubuntu:18.04
docker pull yuzuemu/build-environments:linux-fresh

View File

@@ -1,12 +1,9 @@
#!/bin/bash -ex
apt-get update
apt-get install --no-install-recommends -y build-essential git libqt5opengl5-dev libsdl2-dev libssl-dev python qtbase5-dev qtwebengine5-dev wget cmake ninja-build ccache
cd /yuzu
mkdir build && cd build
cmake .. -DYUZU_USE_BUNDLED_UNICORN=ON -DYUZU_USE_QT_WEB_ENGINE=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=/usr/lib/ccache/gcc -DCMAKE_CXX_COMPILER=/usr/lib/ccache/g++ -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DUSE_DISCORD_PRESENCE=ON -G Ninja
cmake .. -G Ninja -DYUZU_USE_BUNDLED_UNICORN=ON -DYUZU_USE_QT_WEB_ENGINE=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=/usr/lib/ccache/gcc -DCMAKE_CXX_COMPILER=/usr/lib/ccache/g++ -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DUSE_DISCORD_PRESENCE=ON
ninja
ccache -s

View File

@@ -7,6 +7,7 @@ export Qt5_DIR=$(brew --prefix)/opt/qt5
export UNICORNDIR=$(pwd)/externals/unicorn
export PATH="/usr/local/opt/ccache/libexec:$PATH"
# TODO: Build using ninja instead of make
mkdir build && cd build
cmake --version
cmake .. -DYUZU_USE_BUNDLED_UNICORN=ON -DYUZU_USE_QT_WEB_ENGINE=ON -DCMAKE_BUILD_TYPE=Release -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} -DUSE_DISCORD_PRESENCE=ON

View File

@@ -19,18 +19,6 @@ $(brew --prefix)/opt/qt5/bin/macdeployqt "${REV_NAME}/yuzu.app" -executable="${R
# move libs into folder for deployment
macpack "${REV_NAME}/yuzu-cmd" -d "libs"
# Make the yuzu.app application launch a debugging terminal.
# Store away the actual binary
mv ${REV_NAME}/yuzu.app/Contents/MacOS/yuzu ${REV_NAME}/yuzu.app/Contents/MacOS/yuzu-bin
cat > ${REV_NAME}/yuzu.app/Contents/MacOS/yuzu <<EOL
#!/usr/bin/env bash
cd "\`dirname "\$0"\`"
chmod +x yuzu-bin
open yuzu-bin --args "\$@"
EOL
# Content that will serve as the launching script for yuzu (within the .app folder)
# Make the launching script executable
chmod +x ${REV_NAME}/yuzu.app/Contents/MacOS/yuzu

View File

@@ -19,7 +19,7 @@ set(BUILD_VERSION "0")
if (BUILD_REPOSITORY)
# regex capture the string nightly or canary into CMAKE_MATCH_1
string(REGEX MATCH "yuzu-emu/yuzu-?(.*)" OUTVAR ${BUILD_REPOSITORY})
if (${CMAKE_MATCH_COUNT} GREATER 0)
if ("${CMAKE_MATCH_COUNT}" GREATER 0)
# capitalize the first letter of each word in the repo name.
string(REPLACE "-" ";" REPO_NAME_LIST ${CMAKE_MATCH_1})
foreach(WORD ${REPO_NAME_LIST})

View File

@@ -7,6 +7,10 @@ include(DownloadExternals)
add_library(catch-single-include INTERFACE)
target_include_directories(catch-single-include INTERFACE catch/single_include)
# libfmt
add_subdirectory(fmt)
add_library(fmt::fmt ALIAS fmt)
# Dynarmic
if (ARCHITECTURE_x86_64)
set(DYNARMIC_TESTS OFF)
@@ -14,10 +18,6 @@ if (ARCHITECTURE_x86_64)
add_subdirectory(dynarmic)
endif()
# libfmt
add_subdirectory(fmt)
add_library(fmt::fmt ALIAS fmt)
# getopt
if (MSVC)
add_subdirectory(getopt)

View File

@@ -18,15 +18,32 @@ if (MSVC)
# Avoid windows.h from including some usually unused libs like winsocks.h, since this might cause some redefinition errors.
add_definitions(-DWIN32_LEAN_AND_MEAN)
# /W3 - Level 3 warnings
# /MP - Multi-threaded compilation
# /Zi - Output debugging information
# /Zo - enhanced debug info for optimized builds
# /permissive- - enables stricter C++ standards conformance checks
# /EHsc - C++-only exception handling semantics
# /Zc:throwingNew - let codegen assume `operator new` will never return null
# /Zc:inline - let codegen omit inline functions in object files
add_compile_options(/W3 /MP /Zi /Zo /permissive- /EHsc /std:c++latest /Zc:throwingNew,inline)
# Ensure that projects build with Unicode support.
add_definitions(-DUNICODE -D_UNICODE)
# /W3 - Level 3 warnings
# /MP - Multi-threaded compilation
# /Zi - Output debugging information
# /Zo - Enhanced debug info for optimized builds
# /permissive- - Enables stricter C++ standards conformance checks
# /EHsc - C++-only exception handling semantics
# /volatile:iso - Use strict standards-compliant volatile semantics.
# /Zc:externConstexpr - Allow extern constexpr variables to have external linkage, like the standard mandates
# /Zc:inline - Let codegen omit inline functions in object files
# /Zc:throwingNew - Let codegen assume `operator new` (without std::nothrow) will never return null
add_compile_options(
/W3
/MP
/Zi
/Zo
/permissive-
/EHsc
/std:c++latest
/volatile:iso
/Zc:externConstexpr
/Zc:inline
/Zc:throwingNew
)
# /GS- - No stack buffer overflow checks
add_compile_options("$<$<CONFIG:Release>:/GS->")
@@ -34,7 +51,10 @@ if (MSVC)
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "/DEBUG /MANIFEST:NO" CACHE STRING "" FORCE)
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "/DEBUG /MANIFEST:NO /INCREMENTAL:NO /OPT:REF,ICF" CACHE STRING "" FORCE)
else()
add_compile_options("-Wno-attributes")
add_compile_options(
-Wall
-Wno-attributes
)
if (APPLE AND CMAKE_CXX_COMPILER_ID STREQUAL Clang)
add_compile_options("-stdlib=libc++")

View File

@@ -2,6 +2,8 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <vector>
#include "common/common_types.h"

View File

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

View File

@@ -2,6 +2,8 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <vector>
#include "common/common_types.h"

View File

@@ -88,6 +88,10 @@ add_library(core STATIC
file_sys/vfs_vector.h
file_sys/xts_archive.cpp
file_sys/xts_archive.h
frontend/applets/error.cpp
frontend/applets/error.h
frontend/applets/general_frontend.cpp
frontend/applets/general_frontend.h
frontend/applets/profile_select.cpp
frontend/applets/profile_select.h
frontend/applets/software_keyboard.cpp
@@ -177,12 +181,14 @@ add_library(core STATIC
hle/service/am/applet_oe.h
hle/service/am/applets/applets.cpp
hle/service/am/applets/applets.h
hle/service/am/applets/error.cpp
hle/service/am/applets/error.h
hle/service/am/applets/general_backend.cpp
hle/service/am/applets/general_backend.h
hle/service/am/applets/profile_select.cpp
hle/service/am/applets/profile_select.h
hle/service/am/applets/software_keyboard.cpp
hle/service/am/applets/software_keyboard.h
hle/service/am/applets/stub_applet.cpp
hle/service/am/applets/stub_applet.h
hle/service/am/applets/web_browser.cpp
hle/service/am/applets/web_browser.h
hle/service/am/idle.cpp

View File

@@ -7,6 +7,10 @@
#include <array>
#include "common/common_types.h"
namespace Common {
struct PageTable;
}
namespace Kernel {
enum class VMAPermission : u8;
}
@@ -49,8 +53,14 @@ public:
/// Clear all instruction cache
virtual void ClearInstructionCache() = 0;
/// Notify CPU emulation that page tables have changed
virtual void PageTableChanged() = 0;
/// Notifies CPU emulation that the current page table has changed.
///
/// @param new_page_table The new page table.
/// @param new_address_space_size_in_bits The new usable size of the address space in bits.
/// This can be either 32, 36, or 39 on official software.
///
virtual void PageTableChanged(Common::PageTable& new_page_table,
std::size_t new_address_space_size_in_bits) = 0;
/**
* Set the Program Counter to an address

View File

@@ -14,7 +14,6 @@
#include "core/core_timing.h"
#include "core/core_timing_util.h"
#include "core/gdbstub/gdbstub.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/svc.h"
#include "core/hle/kernel/vm_manager.h"
@@ -129,18 +128,16 @@ public:
u64 tpidr_el0 = 0;
};
std::unique_ptr<Dynarmic::A64::Jit> ARM_Dynarmic::MakeJit() const {
auto* current_process = system.Kernel().CurrentProcess();
auto** const page_table = current_process->VMManager().page_table.pointers.data();
std::unique_ptr<Dynarmic::A64::Jit> ARM_Dynarmic::MakeJit(Common::PageTable& page_table,
std::size_t address_space_bits) const {
Dynarmic::A64::UserConfig config;
// Callbacks
config.callbacks = cb.get();
// Memory
config.page_table = reinterpret_cast<void**>(page_table);
config.page_table_address_space_bits = current_process->VMManager().GetAddressSpaceWidth();
config.page_table = reinterpret_cast<void**>(page_table.pointers.data());
config.page_table_address_space_bits = address_space_bits;
config.silently_mirror_page_table = false;
// Multi-process state
@@ -176,12 +173,7 @@ ARM_Dynarmic::ARM_Dynarmic(System& system, ExclusiveMonitor& exclusive_monitor,
std::size_t core_index)
: cb(std::make_unique<ARM_Dynarmic_Callbacks>(*this)), inner_unicorn{system},
core_index{core_index}, system{system},
exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor)} {
ThreadContext ctx{};
inner_unicorn.SaveContext(ctx);
PageTableChanged();
LoadContext(ctx);
}
exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor)} {}
ARM_Dynarmic::~ARM_Dynarmic() = default;
@@ -276,8 +268,9 @@ void ARM_Dynarmic::ClearExclusiveState() {
jit->ClearExclusiveState();
}
void ARM_Dynarmic::PageTableChanged() {
jit = MakeJit();
void ARM_Dynarmic::PageTableChanged(Common::PageTable& page_table,
std::size_t new_address_space_size_in_bits) {
jit = MakeJit(page_table, new_address_space_size_in_bits);
}
DynarmicExclusiveMonitor::DynarmicExclusiveMonitor(std::size_t core_count) : monitor(core_count) {}

View File

@@ -48,10 +48,12 @@ public:
void ClearExclusiveState() override;
void ClearInstructionCache() override;
void PageTableChanged() override;
void PageTableChanged(Common::PageTable& new_page_table,
std::size_t new_address_space_size_in_bits) override;
private:
std::unique_ptr<Dynarmic::A64::Jit> MakeJit() const;
std::unique_ptr<Dynarmic::A64::Jit> MakeJit(Common::PageTable& page_table,
std::size_t address_space_bits) const;
friend class ARM_Dynarmic_Callbacks;
std::unique_ptr<ARM_Dynarmic_Callbacks> cb;

View File

@@ -41,7 +41,7 @@ public:
void Run() override;
void Step() override;
void ClearInstructionCache() override;
void PageTableChanged() override{};
void PageTableChanged(Common::PageTable&, std::size_t) override {}
void RecordBreak(GDBStub::BreakpointAddress bkpt);
private:

View File

@@ -3,9 +3,7 @@
// Refer to the license.txt file included.
#include <array>
#include <map>
#include <memory>
#include <thread>
#include <utility>
#include "common/file_util.h"
@@ -20,13 +18,18 @@
#include "core/file_sys/registered_cache.h"
#include "core/file_sys/vfs_concat.h"
#include "core/file_sys/vfs_real.h"
#include "core/frontend/applets/error.h"
#include "core/frontend/applets/general_frontend.h"
#include "core/frontend/applets/profile_select.h"
#include "core/frontend/applets/software_keyboard.h"
#include "core/frontend/applets/web_browser.h"
#include "core/gdbstub/gdbstub.h"
#include "core/hle/kernel/client_port.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/scheduler.h"
#include "core/hle/kernel/thread.h"
#include "core/hle/service/am/applets/software_keyboard.h"
#include "core/hle/service/am/applets/applets.h"
#include "core/hle/service/service.h"
#include "core/hle/service/sm/sm.h"
#include "core/loader/loader.h"
@@ -38,8 +41,6 @@
#include "frontend/applets/software_keyboard.h"
#include "frontend/applets/web_browser.h"
#include "video_core/debug_utils/debug_utils.h"
#include "video_core/gpu_asynch.h"
#include "video_core/gpu_synch.h"
#include "video_core/renderer_base.h"
#include "video_core/video_core.h"
@@ -81,7 +82,7 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
return vfs->OpenFile(path, FileSys::Mode::Read);
}
struct System::Impl {
explicit Impl(System& system) : kernel{system} {}
explicit Impl(System& system) : kernel{system}, cpu_core_manager{system} {}
Cpu& CurrentCpuCore() {
return cpu_core_manager.GetCurrentCore();
@@ -99,6 +100,7 @@ struct System::Impl {
LOG_DEBUG(HW_Memory, "initialized OK");
core_timing.Initialize();
cpu_core_manager.Initialize();
kernel.Initialize();
const auto current_time = std::chrono::duration_cast<std::chrono::seconds>(
@@ -113,15 +115,7 @@ struct System::Impl {
content_provider = std::make_unique<FileSys::ContentProviderUnion>();
/// Create default implementations of applets if one is not provided.
if (profile_selector == nullptr)
profile_selector = std::make_unique<Core::Frontend::DefaultProfileSelectApplet>();
if (software_keyboard == nullptr)
software_keyboard = std::make_unique<Core::Frontend::DefaultSoftwareKeyboardApplet>();
if (web_browser == nullptr)
web_browser = std::make_unique<Core::Frontend::DefaultWebBrowserApplet>();
auto main_process = Kernel::Process::Create(system, "main");
kernel.MakeCurrentProcess(main_process.get());
applet_manager.SetDefaultAppletsIfMissing();
telemetry_session = std::make_unique<Core::TelemetrySession>();
service_manager = std::make_shared<Service::SM::ServiceManager>();
@@ -134,16 +128,10 @@ struct System::Impl {
return ResultStatus::ErrorVideoCore;
}
gpu_core = VideoCore::CreateGPU(system);
is_powered_on = true;
if (Settings::values.use_asynchronous_gpu_emulation) {
gpu_core = std::make_unique<VideoCommon::GPUAsynch>(system, *renderer);
} else {
gpu_core = std::make_unique<VideoCommon::GPUSynch>(system, *renderer);
}
cpu_core_manager.Initialize(system);
LOG_DEBUG(Core, "Initialized OK");
// Reset counters and set time origin to current frame
@@ -179,7 +167,8 @@ struct System::Impl {
return init_result;
}
const Loader::ResultStatus load_result{app_loader->Load(*kernel.CurrentProcess())};
auto main_process = Kernel::Process::Create(system, "main");
const auto [load_result, load_parameters] = app_loader->Load(*main_process);
if (load_result != Loader::ResultStatus::Success) {
LOG_CRITICAL(Core, "Failed to load ROM (Error {})!", static_cast<int>(load_result));
Shutdown();
@@ -187,6 +176,16 @@ struct System::Impl {
return static_cast<ResultStatus>(static_cast<u32>(ResultStatus::ErrorLoader) +
static_cast<u32>(load_result));
}
kernel.MakeCurrentProcess(main_process.get());
// Main process has been loaded and been made current.
// Begin GPU and CPU execution.
gpu_core->Start();
cpu_core_manager.StartThreads();
// All threads are started, begin main process execution, now that we're in the clear.
main_process->Run(load_parameters->main_thread_priority,
load_parameters->main_thread_stack_size);
status = ResultStatus::Success;
return status;
@@ -224,9 +223,7 @@ struct System::Impl {
app_loader.reset();
// Clear all applets
profile_selector.reset();
software_keyboard.reset();
web_browser.reset();
applet_manager.ClearAll();
LOG_DEBUG(Core, "Shutdown OK");
}
@@ -265,9 +262,7 @@ struct System::Impl {
std::unique_ptr<FileSys::CheatEngine> cheat_engine;
/// Frontend applets
std::unique_ptr<Core::Frontend::ProfileSelectApplet> profile_selector;
std::unique_ptr<Core::Frontend::SoftwareKeyboardApplet> software_keyboard;
std::unique_ptr<Core::Frontend::WebBrowserApplet> web_browser;
Service::AM::Applets::AppletManager applet_manager;
/// Service manager
std::shared_ptr<Service::SM::ServiceManager> service_manager;
@@ -477,20 +472,20 @@ std::shared_ptr<FileSys::VfsFilesystem> System::GetFilesystem() const {
return impl->virtual_filesystem;
}
void System::SetProfileSelector(std::unique_ptr<Frontend::ProfileSelectApplet> applet) {
impl->profile_selector = std::move(applet);
void System::SetAppletFrontendSet(Service::AM::Applets::AppletFrontendSet&& set) {
impl->applet_manager.SetAppletFrontendSet(std::move(set));
}
const Frontend::ProfileSelectApplet& System::GetProfileSelector() const {
return *impl->profile_selector;
void System::SetDefaultAppletFrontendSet() {
impl->applet_manager.SetDefaultAppletFrontendSet();
}
void System::SetSoftwareKeyboard(std::unique_ptr<Frontend::SoftwareKeyboardApplet> applet) {
impl->software_keyboard = std::move(applet);
Service::AM::Applets::AppletManager& System::GetAppletManager() {
return impl->applet_manager;
}
const Frontend::SoftwareKeyboardApplet& System::GetSoftwareKeyboard() const {
return *impl->software_keyboard;
const Service::AM::Applets::AppletManager& System::GetAppletManager() const {
return impl->applet_manager;
}
void System::SetContentProvider(std::unique_ptr<FileSys::ContentProviderUnion> provider) {
@@ -514,18 +509,6 @@ void System::ClearContentProvider(FileSys::ContentProviderUnionSlot slot) {
impl->content_provider->ClearSlot(slot);
}
void System::SetWebBrowser(std::unique_ptr<Frontend::WebBrowserApplet> applet) {
impl->web_browser = std::move(applet);
}
Frontend::WebBrowserApplet& System::GetWebBrowser() {
return *impl->web_browser;
}
const Frontend::WebBrowserApplet& System::GetWebBrowser() const {
return *impl->web_browser;
}
System::ResultStatus System::Init(Frontend::EmuWindow& emu_window) {
return impl->Init(*this, emu_window);
}

View File

@@ -14,9 +14,6 @@
namespace Core::Frontend {
class EmuWindow;
class ProfileSelectApplet;
class SoftwareKeyboardApplet;
class WebBrowserApplet;
} // namespace Core::Frontend
namespace FileSys {
@@ -38,9 +35,18 @@ class AppLoader;
enum class ResultStatus : u16;
} // namespace Loader
namespace Service::SM {
namespace Service {
namespace AM::Applets {
struct AppletFrontendSet;
class AppletManager;
} // namespace AM::Applets
namespace SM {
class ServiceManager;
} // namespace Service::SM
} // namespace SM
} // namespace Service
namespace Tegra {
class DebugContext;
@@ -260,18 +266,13 @@ public:
void RegisterCheatList(const std::vector<FileSys::CheatList>& list, const std::string& build_id,
VAddr code_region_start, VAddr code_region_end);
void SetProfileSelector(std::unique_ptr<Frontend::ProfileSelectApplet> applet);
void SetAppletFrontendSet(Service::AM::Applets::AppletFrontendSet&& set);
const Frontend::ProfileSelectApplet& GetProfileSelector() const;
void SetDefaultAppletFrontendSet();
void SetSoftwareKeyboard(std::unique_ptr<Frontend::SoftwareKeyboardApplet> applet);
Service::AM::Applets::AppletManager& GetAppletManager();
const Frontend::SoftwareKeyboardApplet& GetSoftwareKeyboard() const;
void SetWebBrowser(std::unique_ptr<Frontend::WebBrowserApplet> applet);
Frontend::WebBrowserApplet& GetWebBrowser();
const Frontend::WebBrowserApplet& GetWebBrowser() const;
const Service::AM::Applets::AppletManager& GetAppletManager() const;
void SetContentProvider(std::unique_ptr<FileSys::ContentProviderUnion> provider);

View File

@@ -19,17 +19,19 @@ void RunCpuCore(const System& system, Cpu& cpu_state) {
}
} // Anonymous namespace
CpuCoreManager::CpuCoreManager() = default;
CpuCoreManager::CpuCoreManager(System& system) : system{system} {}
CpuCoreManager::~CpuCoreManager() = default;
void CpuCoreManager::Initialize(System& system) {
void CpuCoreManager::Initialize() {
barrier = std::make_unique<CpuBarrier>();
exclusive_monitor = Cpu::MakeExclusiveMonitor(cores.size());
for (std::size_t index = 0; index < cores.size(); ++index) {
cores[index] = std::make_unique<Cpu>(system, *exclusive_monitor, *barrier, index);
}
}
void CpuCoreManager::StartThreads() {
// Create threads for CPU cores 1-3, and build thread_to_cpu map
// CPU core 0 is run on the main thread
thread_to_cpu[std::this_thread::get_id()] = cores[0].get();

View File

@@ -18,7 +18,7 @@ class System;
class CpuCoreManager {
public:
CpuCoreManager();
explicit CpuCoreManager(System& system);
CpuCoreManager(const CpuCoreManager&) = delete;
CpuCoreManager(CpuCoreManager&&) = delete;
@@ -27,7 +27,8 @@ public:
CpuCoreManager& operator=(const CpuCoreManager&) = delete;
CpuCoreManager& operator=(CpuCoreManager&&) = delete;
void Initialize(System& system);
void Initialize();
void StartThreads();
void Shutdown();
Cpu& GetCore(std::size_t index);
@@ -54,6 +55,8 @@ private:
/// Map of guest threads to CPU cores
std::map<std::thread::id, Cpu*> thread_to_cpu;
System& system;
};
} // namespace Core

View File

@@ -0,0 +1,34 @@
// Copyright 2019 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "core/frontend/applets/error.h"
namespace Core::Frontend {
ErrorApplet::~ErrorApplet() = default;
void DefaultErrorApplet::ShowError(ResultCode error, std::function<void()> finished) const {
LOG_CRITICAL(Service_Fatal, "Application requested error display: {:04}-{:04} (raw={:08X})",
static_cast<u32>(error.module.Value()), error.description.Value(), error.raw);
}
void DefaultErrorApplet::ShowErrorWithTimestamp(ResultCode error, std::chrono::seconds time,
std::function<void()> finished) const {
LOG_CRITICAL(
Service_Fatal,
"Application requested error display: {:04X}-{:04X} (raw={:08X}) with timestamp={:016X}",
static_cast<u32>(error.module.Value()), error.description.Value(), error.raw, time.count());
}
void DefaultErrorApplet::ShowCustomErrorText(ResultCode error, std::string main_text,
std::string detail_text,
std::function<void()> finished) const {
LOG_CRITICAL(Service_Fatal,
"Application requested custom error with error_code={:04X}-{:04X} (raw={:08X})",
static_cast<u32>(error.module.Value()), error.description.Value(), error.raw);
LOG_CRITICAL(Service_Fatal, " Main Text: {}", main_text);
LOG_CRITICAL(Service_Fatal, " Detail Text: {}", detail_text);
}
} // namespace Core::Frontend

View File

@@ -0,0 +1,37 @@
// Copyright 2019 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <chrono>
#include <functional>
#include "core/hle/result.h"
namespace Core::Frontend {
class ErrorApplet {
public:
virtual ~ErrorApplet();
virtual void ShowError(ResultCode error, std::function<void()> finished) const = 0;
virtual void ShowErrorWithTimestamp(ResultCode error, std::chrono::seconds time,
std::function<void()> finished) const = 0;
virtual void ShowCustomErrorText(ResultCode error, std::string dialog_text,
std::string fullscreen_text,
std::function<void()> finished) const = 0;
};
class DefaultErrorApplet final : public ErrorApplet {
public:
void ShowError(ResultCode error, std::function<void()> finished) const override;
void ShowErrorWithTimestamp(ResultCode error, std::chrono::seconds time,
std::function<void()> finished) const override;
void ShowCustomErrorText(ResultCode error, std::string main_text, std::string detail_text,
std::function<void()> finished) const override;
};
} // namespace Core::Frontend

View File

@@ -0,0 +1,27 @@
// Copyright 2019 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "common/logging/log.h"
#include "core/frontend/applets/general_frontend.h"
namespace Core::Frontend {
PhotoViewerApplet::~PhotoViewerApplet() = default;
DefaultPhotoViewerApplet::~DefaultPhotoViewerApplet() {}
void DefaultPhotoViewerApplet::ShowPhotosForApplication(u64 title_id,
std::function<void()> finished) const {
LOG_INFO(Service_AM,
"Application requested frontend to display stored photos for title_id={:016X}",
title_id);
finished();
}
void DefaultPhotoViewerApplet::ShowAllPhotos(std::function<void()> finished) const {
LOG_INFO(Service_AM, "Application requested frontend to display all stored photos.");
finished();
}
} // namespace Core::Frontend

View File

@@ -0,0 +1,28 @@
// Copyright 2019 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <functional>
#include "common/common_types.h"
namespace Core::Frontend {
class PhotoViewerApplet {
public:
virtual ~PhotoViewerApplet();
virtual void ShowPhotosForApplication(u64 title_id, std::function<void()> finished) const = 0;
virtual void ShowAllPhotos(std::function<void()> finished) const = 0;
};
class DefaultPhotoViewerApplet final : public PhotoViewerApplet {
public:
~DefaultPhotoViewerApplet() override;
void ShowPhotosForApplication(u64 title_id, std::function<void()> finished) const override;
void ShowAllPhotos(std::function<void()> finished) const override;
};
} // namespace Core::Frontend

View File

@@ -10,6 +10,8 @@
namespace Core::Frontend {
GraphicsContext::~GraphicsContext() = default;
class EmuWindow::TouchState : public Input::Factory<Input::TouchDevice>,
public std::enable_shared_from_this<TouchState> {
public:

View File

@@ -19,6 +19,8 @@ namespace Core::Frontend {
*/
class GraphicsContext {
public:
virtual ~GraphicsContext();
/// Makes the graphics context current for the caller thread
virtual void MakeCurrent() = 0;

View File

@@ -46,8 +46,7 @@ static void ThreadWakeupCallback(u64 thread_handle, [[maybe_unused]] s64 cycles_
bool resume = true;
if (thread->GetStatus() == ThreadStatus::WaitSynchAny ||
thread->GetStatus() == ThreadStatus::WaitSynchAll ||
if (thread->GetStatus() == ThreadStatus::WaitSynch ||
thread->GetStatus() == ThreadStatus::WaitHLEEvent) {
// Remove the thread from each of its waiting objects' waitlists
for (const auto& object : thread->GetWaitObjects()) {
@@ -182,7 +181,12 @@ void KernelCore::AppendNewProcess(SharedPtr<Process> process) {
void KernelCore::MakeCurrentProcess(Process* process) {
impl->current_process = process;
Memory::SetCurrentPageTable(&process->VMManager().page_table);
if (process == nullptr) {
return;
}
Memory::SetCurrentPageTable(*process);
}
Process* KernelCore::CurrentProcess() {

View File

@@ -28,21 +28,20 @@ namespace {
*
* @param owner_process The parent process for the main thread
* @param kernel The kernel instance to create the main thread under.
* @param entry_point The address at which the thread should start execution
* @param priority The priority to give the main thread
*/
void SetupMainThread(Process& owner_process, KernelCore& kernel, VAddr entry_point, u32 priority) {
// Initialize new "main" thread
const VAddr stack_top = owner_process.VMManager().GetTLSIORegionEndAddress();
void SetupMainThread(Process& owner_process, KernelCore& kernel, u32 priority) {
const auto& vm_manager = owner_process.VMManager();
const VAddr entry_point = vm_manager.GetCodeRegionBaseAddress();
const VAddr stack_top = vm_manager.GetTLSIORegionEndAddress();
auto thread_res = Thread::Create(kernel, "main", entry_point, priority, 0,
owner_process.GetIdealCore(), stack_top, owner_process);
SharedPtr<Thread> thread = std::move(thread_res).Unwrap();
// Register 1 must be a handle to the main thread
const Handle guest_handle = owner_process.GetHandleTable().Create(thread).Unwrap();
thread->SetGuestHandle(guest_handle);
thread->GetContext().cpu_registers[1] = guest_handle;
const Handle thread_handle = owner_process.GetHandleTable().Create(thread).Unwrap();
thread->GetContext().cpu_registers[1] = thread_handle;
// Threads by default are dormant, wake up the main thread so it runs when the scheduler fires
thread->ResumeFromWait();
@@ -106,8 +105,6 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata) {
is_64bit_process = metadata.Is64BitProgram();
vm_manager.Reset(metadata.GetAddressSpaceType());
// Ensure that the potentially resized page table is seen by CPU backends.
Memory::SetCurrentPageTable(&vm_manager.page_table);
const auto& caps = metadata.GetKernelCapabilities();
const auto capability_init_result =
@@ -119,7 +116,7 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata) {
return handle_table.SetSize(capabilities.GetHandleTableSize());
}
void Process::Run(VAddr entry_point, s32 main_thread_priority, u64 stack_size) {
void Process::Run(s32 main_thread_priority, u64 stack_size) {
// The kernel always ensures that the given stack size is page aligned.
main_thread_stack_size = Common::AlignUp(stack_size, Memory::PAGE_SIZE);
@@ -135,7 +132,7 @@ void Process::Run(VAddr entry_point, s32 main_thread_priority, u64 stack_size) {
vm_manager.LogLayout();
ChangeStatus(ProcessStatus::Running);
SetupMainThread(*this, kernel, entry_point, main_thread_priority);
SetupMainThread(*this, kernel, main_thread_priority);
}
void Process::PrepareForTermination() {
@@ -150,8 +147,7 @@ void Process::PrepareForTermination() {
continue;
// TODO(Subv): When are the other running/ready threads terminated?
ASSERT_MSG(thread->GetStatus() == ThreadStatus::WaitSynchAny ||
thread->GetStatus() == ThreadStatus::WaitSynchAll,
ASSERT_MSG(thread->GetStatus() == ThreadStatus::WaitSynch,
"Exiting processes with non-waiting threads is currently unimplemented");
thread->Stop();
@@ -242,13 +238,11 @@ void Process::LoadModule(CodeSet module_, VAddr base_addr) {
MapSegment(module_.DataSegment(), VMAPermission::ReadWrite, MemoryState::CodeData);
code_memory_size += module_.memory.size();
// Clear instruction cache in CPU JIT
system.InvalidateCpuInstructionCaches();
}
Process::Process(Core::System& system)
: WaitObject{system.Kernel()}, address_arbiter{system}, mutex{system}, system{system} {}
: WaitObject{system.Kernel()}, vm_manager{system},
address_arbiter{system}, mutex{system}, system{system} {}
Process::~Process() = default;

View File

@@ -225,9 +225,12 @@ public:
ResultCode LoadFromMetadata(const FileSys::ProgramMetadata& metadata);
/**
* Applies address space changes and launches the process main thread.
* Starts the main application thread for this process.
*
* @param main_thread_priority The priority for the main thread.
* @param stack_size The stack size for the main thread in bytes.
*/
void Run(VAddr entry_point, s32 main_thread_priority, u64 stack_size);
void Run(s32 main_thread_priority, u64 stack_size);
/**
* Prepares a process for termination by stopping all of its threads

View File

@@ -424,7 +424,7 @@ static ResultCode GetProcessId(Core::System& system, u64* process_id, Handle han
/// Default thread wakeup callback for WaitSynchronization
static bool DefaultThreadWakeupCallback(ThreadWakeupReason reason, SharedPtr<Thread> thread,
SharedPtr<WaitObject> object, std::size_t index) {
ASSERT(thread->GetStatus() == ThreadStatus::WaitSynchAny);
ASSERT(thread->GetStatus() == ThreadStatus::WaitSynch);
if (reason == ThreadWakeupReason::Timeout) {
thread->SetWaitSynchronizationResult(RESULT_TIMEOUT);
@@ -502,7 +502,7 @@ static ResultCode WaitSynchronization(Core::System& system, Handle* index, VAddr
}
thread->SetWaitObjects(std::move(objects));
thread->SetStatus(ThreadStatus::WaitSynchAny);
thread->SetStatus(ThreadStatus::WaitSynch);
// Create an event to wake the thread up after the specified nanosecond delay has passed
thread->WakeAfterDelay(nano_seconds);
@@ -518,16 +518,14 @@ static ResultCode CancelSynchronization(Core::System& system, Handle thread_hand
LOG_TRACE(Kernel_SVC, "called thread=0x{:X}", thread_handle);
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
const SharedPtr<Thread> thread = handle_table.Get<Thread>(thread_handle);
SharedPtr<Thread> thread = handle_table.Get<Thread>(thread_handle);
if (!thread) {
LOG_ERROR(Kernel_SVC, "Thread handle does not exist, thread_handle=0x{:08X}",
thread_handle);
return ERR_INVALID_HANDLE;
}
ASSERT(thread->GetStatus() == ThreadStatus::WaitSynchAny);
thread->SetWaitSynchronizationResult(ERR_SYNCHRONIZATION_CANCELED);
thread->ResumeFromWait();
thread->CancelWait();
return RESULT_SUCCESS;
}
@@ -1189,6 +1187,142 @@ static ResultCode QueryMemory(Core::System& system, VAddr memory_info_address,
query_address);
}
static ResultCode MapProcessCodeMemory(Core::System& system, Handle process_handle, u64 dst_address,
u64 src_address, u64 size) {
LOG_DEBUG(Kernel_SVC,
"called. process_handle=0x{:08X}, dst_address=0x{:016X}, "
"src_address=0x{:016X}, size=0x{:016X}",
process_handle, dst_address, src_address, size);
if (!Common::Is4KBAligned(src_address)) {
LOG_ERROR(Kernel_SVC, "src_address is not page-aligned (src_address=0x{:016X}).",
src_address);
return ERR_INVALID_ADDRESS;
}
if (!Common::Is4KBAligned(dst_address)) {
LOG_ERROR(Kernel_SVC, "dst_address is not page-aligned (dst_address=0x{:016X}).",
dst_address);
return ERR_INVALID_ADDRESS;
}
if (size == 0 || !Common::Is4KBAligned(size)) {
LOG_ERROR(Kernel_SVC, "Size is zero or not page-aligned (size=0x{:016X})", size);
return ERR_INVALID_SIZE;
}
if (!IsValidAddressRange(dst_address, size)) {
LOG_ERROR(Kernel_SVC,
"Destination address range overflows the address space (dst_address=0x{:016X}, "
"size=0x{:016X}).",
dst_address, size);
return ERR_INVALID_ADDRESS_STATE;
}
if (!IsValidAddressRange(src_address, size)) {
LOG_ERROR(Kernel_SVC,
"Source address range overflows the address space (src_address=0x{:016X}, "
"size=0x{:016X}).",
src_address, size);
return ERR_INVALID_ADDRESS_STATE;
}
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
auto process = handle_table.Get<Process>(process_handle);
if (!process) {
LOG_ERROR(Kernel_SVC, "Invalid process handle specified (handle=0x{:08X}).",
process_handle);
return ERR_INVALID_HANDLE;
}
auto& vm_manager = process->VMManager();
if (!vm_manager.IsWithinAddressSpace(src_address, size)) {
LOG_ERROR(Kernel_SVC,
"Source address range is not within the address space (src_address=0x{:016X}, "
"size=0x{:016X}).",
src_address, size);
return ERR_INVALID_ADDRESS_STATE;
}
if (!vm_manager.IsWithinASLRRegion(dst_address, size)) {
LOG_ERROR(Kernel_SVC,
"Destination address range is not within the ASLR region (dst_address=0x{:016X}, "
"size=0x{:016X}).",
dst_address, size);
return ERR_INVALID_MEMORY_RANGE;
}
return vm_manager.MapCodeMemory(dst_address, src_address, size);
}
ResultCode UnmapProcessCodeMemory(Core::System& system, Handle process_handle, u64 dst_address,
u64 src_address, u64 size) {
LOG_DEBUG(Kernel_SVC,
"called. process_handle=0x{:08X}, dst_address=0x{:016X}, src_address=0x{:016X}, "
"size=0x{:016X}",
process_handle, dst_address, src_address, size);
if (!Common::Is4KBAligned(dst_address)) {
LOG_ERROR(Kernel_SVC, "dst_address is not page-aligned (dst_address=0x{:016X}).",
dst_address);
return ERR_INVALID_ADDRESS;
}
if (!Common::Is4KBAligned(src_address)) {
LOG_ERROR(Kernel_SVC, "src_address is not page-aligned (src_address=0x{:016X}).",
src_address);
return ERR_INVALID_ADDRESS;
}
if (size == 0 || Common::Is4KBAligned(size)) {
LOG_ERROR(Kernel_SVC, "Size is zero or not page-aligned (size=0x{:016X}).", size);
return ERR_INVALID_SIZE;
}
if (!IsValidAddressRange(dst_address, size)) {
LOG_ERROR(Kernel_SVC,
"Destination address range overflows the address space (dst_address=0x{:016X}, "
"size=0x{:016X}).",
dst_address, size);
return ERR_INVALID_ADDRESS_STATE;
}
if (!IsValidAddressRange(src_address, size)) {
LOG_ERROR(Kernel_SVC,
"Source address range overflows the address space (src_address=0x{:016X}, "
"size=0x{:016X}).",
src_address, size);
return ERR_INVALID_ADDRESS_STATE;
}
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
auto process = handle_table.Get<Process>(process_handle);
if (!process) {
LOG_ERROR(Kernel_SVC, "Invalid process handle specified (handle=0x{:08X}).",
process_handle);
return ERR_INVALID_HANDLE;
}
auto& vm_manager = process->VMManager();
if (!vm_manager.IsWithinAddressSpace(src_address, size)) {
LOG_ERROR(Kernel_SVC,
"Source address range is not within the address space (src_address=0x{:016X}, "
"size=0x{:016X}).",
src_address, size);
return ERR_INVALID_ADDRESS_STATE;
}
if (!vm_manager.IsWithinASLRRegion(dst_address, size)) {
LOG_ERROR(Kernel_SVC,
"Destination address range is not within the ASLR region (dst_address=0x{:016X}, "
"size=0x{:016X}).",
dst_address, size);
return ERR_INVALID_MEMORY_RANGE;
}
return vm_manager.UnmapCodeMemory(dst_address, src_address, size);
}
/// Exits the current process
static void ExitProcess(Core::System& system) {
auto* current_process = system.Kernel().CurrentProcess();
@@ -1244,20 +1378,22 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e
return ERR_INVALID_THREAD_PRIORITY;
}
const std::string name = fmt::format("thread-{:X}", entry_point);
auto& kernel = system.Kernel();
CASCADE_RESULT(SharedPtr<Thread> thread,
Thread::Create(kernel, name, entry_point, priority, arg, processor_id, stack_top,
Thread::Create(kernel, "", entry_point, priority, arg, processor_id, stack_top,
*current_process));
const auto new_guest_handle = current_process->GetHandleTable().Create(thread);
if (new_guest_handle.Failed()) {
const auto new_thread_handle = current_process->GetHandleTable().Create(thread);
if (new_thread_handle.Failed()) {
LOG_ERROR(Kernel_SVC, "Failed to create handle with error=0x{:X}",
new_guest_handle.Code().raw);
return new_guest_handle.Code();
new_thread_handle.Code().raw);
return new_thread_handle.Code();
}
thread->SetGuestHandle(*new_guest_handle);
*out_handle = *new_guest_handle;
*out_handle = *new_thread_handle;
// Set the thread name for debugging purposes.
thread->SetName(
fmt::format("thread[entry_point={:X}, handle={:X}]", entry_point, *new_thread_handle));
system.CpuCore(thread->GetProcessorID()).PrepareReschedule();
@@ -2152,7 +2288,7 @@ static const FunctionDef SVC_Table[] = {
{0x33, SvcWrap<GetThreadContext>, "GetThreadContext"},
{0x34, SvcWrap<WaitForAddress>, "WaitForAddress"},
{0x35, SvcWrap<SignalToAddress>, "SignalToAddress"},
{0x36, nullptr, "Unknown"},
{0x36, nullptr, "SynchronizePreemptionState"},
{0x37, nullptr, "Unknown"},
{0x38, nullptr, "Unknown"},
{0x39, nullptr, "Unknown"},
@@ -2217,8 +2353,8 @@ static const FunctionDef SVC_Table[] = {
{0x74, nullptr, "MapProcessMemory"},
{0x75, nullptr, "UnmapProcessMemory"},
{0x76, SvcWrap<QueryProcessMemory>, "QueryProcessMemory"},
{0x77, nullptr, "MapProcessCodeMemory"},
{0x78, nullptr, "UnmapProcessCodeMemory"},
{0x77, SvcWrap<MapProcessCodeMemory>, "MapProcessCodeMemory"},
{0x78, SvcWrap<UnmapProcessCodeMemory>, "UnmapProcessCodeMemory"},
{0x79, nullptr, "CreateProcess"},
{0x7A, nullptr, "StartProcess"},
{0x7B, nullptr, "TerminateProcess"},

View File

@@ -44,6 +44,13 @@ void SvcWrap(Core::System& system) {
func(system, static_cast<u32>(Param(system, 0)), static_cast<u32>(Param(system, 1))).raw);
}
template <ResultCode func(Core::System&, u32, u64, u64, u64)>
void SvcWrap(Core::System& system) {
FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), Param(system, 1),
Param(system, 2), Param(system, 3))
.raw);
}
template <ResultCode func(Core::System&, u32*)>
void SvcWrap(Core::System& system) {
u32 param = 0;

View File

@@ -101,8 +101,7 @@ void Thread::ResumeFromWait() {
ASSERT_MSG(wait_objects.empty(), "Thread is waking up while waiting for objects");
switch (status) {
case ThreadStatus::WaitSynchAll:
case ThreadStatus::WaitSynchAny:
case ThreadStatus::WaitSynch:
case ThreadStatus::WaitHLEEvent:
case ThreadStatus::WaitSleep:
case ThreadStatus::WaitIPC:
@@ -142,6 +141,12 @@ void Thread::ResumeFromWait() {
ChangeScheduler();
}
void Thread::CancelWait() {
ASSERT(GetStatus() == ThreadStatus::WaitSynch);
SetWaitSynchronizationResult(ERR_SYNCHRONIZATION_CANCELED);
ResumeFromWait();
}
/**
* Resets a thread context, making it ready to be scheduled and run by the CPU
* @param context Thread context to reset
@@ -220,11 +225,6 @@ void Thread::SetPriority(u32 priority) {
UpdatePriority();
}
void Thread::BoostPriority(u32 priority) {
scheduler->SetThreadPriority(this, priority);
current_priority = priority;
}
void Thread::SetWaitSynchronizationResult(ResultCode result) {
context.cpu_registers[0] = result.raw;
}

View File

@@ -49,8 +49,7 @@ enum class ThreadStatus {
WaitHLEEvent, ///< Waiting for hle event to finish
WaitSleep, ///< Waiting due to a SleepThread SVC
WaitIPC, ///< Waiting for the reply from an IPC request
WaitSynchAny, ///< Waiting due to WaitSynch1 or WaitSynchN with wait_all = false
WaitSynchAll, ///< Waiting due to WaitSynchronizationN with wait_all = true
WaitSynch, ///< Waiting due to WaitSynchronization
WaitMutex, ///< Waiting due to an ArbitrateLock svc
WaitCondVar, ///< Waiting due to an WaitProcessWideKey svc
WaitArb, ///< Waiting due to a SignalToAddress/WaitForAddress svc
@@ -102,6 +101,11 @@ public:
std::string GetName() const override {
return name;
}
void SetName(std::string new_name) {
name = std::move(new_name);
}
std::string GetTypeName() const override {
return "Thread";
}
@@ -136,12 +140,6 @@ public:
*/
void SetPriority(u32 priority);
/**
* Temporarily boosts the thread's priority until the next time it is scheduled
* @param priority The new priority
*/
void BoostPriority(u32 priority);
/// Adds a thread to the list of threads that are waiting for a lock held by this thread.
void AddMutexWaiter(SharedPtr<Thread> thread);
@@ -170,11 +168,17 @@ public:
return tls_memory;
}
/**
* Resumes a thread from waiting
*/
/// Resumes a thread from waiting
void ResumeFromWait();
/// Cancels a waiting operation that this thread may or may not be within.
///
/// When the thread is within a waiting state, this will set the thread's
/// waiting result to signal a canceled wait. The function will then resume
/// this thread.
///
void CancelWait();
/**
* Schedules an event to wake up the specified thread after the specified delay
* @param nanoseconds The time this thread will be allowed to sleep for
@@ -185,24 +189,27 @@ public:
void CancelWakeupTimer();
/**
* Sets the result after the thread awakens (from either WaitSynchronization SVC)
* Sets the result after the thread awakens (from svcWaitSynchronization)
* @param result Value to set to the returned result
*/
void SetWaitSynchronizationResult(ResultCode result);
/**
* Sets the output parameter value after the thread awakens (from WaitSynchronizationN SVC only)
* Sets the output parameter value after the thread awakens (from svcWaitSynchronization)
* @param output Value to set to the output parameter
*/
void SetWaitSynchronizationOutput(s32 output);
/**
* Retrieves the index that this particular object occupies in the list of objects
* that the thread passed to WaitSynchronizationN, starting the search from the last element.
* It is used to set the output value of WaitSynchronizationN when the thread is awakened.
* that the thread passed to WaitSynchronization, starting the search from the last element.
*
* It is used to set the output index of WaitSynchronization when the thread is awakened.
*
* When a thread wakes up due to an object signal, the kernel will use the index of the last
* matching object in the wait objects list in case of having multiple instances of the same
* object in the list.
*
* @param object Object to query the index of.
*/
s32 GetWaitObjectIndex(const WaitObject* object) const;
@@ -239,13 +246,9 @@ public:
*/
VAddr GetCommandBufferAddress() const;
/**
* Returns whether this thread is waiting for all the objects in
* its wait list to become ready, as a result of a WaitSynchronizationN call
* with wait_all = true.
*/
bool IsSleepingOnWaitAll() const {
return status == ThreadStatus::WaitSynchAll;
/// Returns whether this thread is waiting on objects from a WaitSynchronization call.
bool IsSleepingOnWait() const {
return status == ThreadStatus::WaitSynch;
}
ThreadContext& GetContext() {
@@ -345,10 +348,6 @@ public:
arb_wait_address = address;
}
void SetGuestHandle(Handle handle) {
guest_handle = handle;
}
bool HasWakeupCallback() const {
return wakeup_callback != nullptr;
}
@@ -423,7 +422,7 @@ private:
Process* owner_process;
/// Objects that the thread is waiting on, in the same order as they were
/// passed to WaitSynchronization1/N.
/// passed to WaitSynchronization.
ThreadWaitObjects wait_objects;
/// List of threads that are waiting for a mutex that is held by this thread.
@@ -442,14 +441,11 @@ private:
/// If waiting for an AddressArbiter, this is the address being waited on.
VAddr arb_wait_address{0};
/// Handle used by guest emulated application to access this thread
Handle guest_handle = 0;
/// Handle used as userdata to reference this object when inserting into the CoreTiming queue.
Handle callback_handle = 0;
/// Callback that will be invoked when the thread is resumed from a waiting state. If the thread
/// was waiting via WaitSynchronizationN then the object will be the last object that became
/// was waiting via WaitSynchronization then the object will be the last object that became
/// available. In case of a timeout, the object will be nullptr.
WakeupCallback wakeup_callback;

View File

@@ -62,7 +62,7 @@ bool VirtualMemoryArea::CanBeMergedWith(const VirtualMemoryArea& next) const {
return true;
}
VMManager::VMManager() {
VMManager::VMManager(Core::System& system) : system{system} {
// Default to assuming a 39-bit address space. This way we have a sane
// starting point with executables that don't provide metadata.
Reset(FileSys::ProgramAddressSpaceType::Is39Bit);
@@ -111,7 +111,6 @@ ResultVal<VMManager::VMAHandle> VMManager::MapMemoryBlock(VAddr target,
VirtualMemoryArea& final_vma = vma_handle->second;
ASSERT(final_vma.size == size);
auto& system = Core::System::GetInstance();
system.ArmInterface(0).MapBackingMemory(target, size, block->data() + offset,
VMAPermission::ReadWriteExecute);
system.ArmInterface(1).MapBackingMemory(target, size, block->data() + offset,
@@ -140,7 +139,6 @@ ResultVal<VMManager::VMAHandle> VMManager::MapBackingMemory(VAddr target, u8* me
VirtualMemoryArea& final_vma = vma_handle->second;
ASSERT(final_vma.size == size);
auto& system = Core::System::GetInstance();
system.ArmInterface(0).MapBackingMemory(target, size, memory, VMAPermission::ReadWriteExecute);
system.ArmInterface(1).MapBackingMemory(target, size, memory, VMAPermission::ReadWriteExecute);
system.ArmInterface(2).MapBackingMemory(target, size, memory, VMAPermission::ReadWriteExecute);
@@ -223,7 +221,6 @@ ResultCode VMManager::UnmapRange(VAddr target, u64 size) {
ASSERT(FindVMA(target)->second.size >= size);
auto& system = Core::System::GetInstance();
system.ArmInterface(0).UnmapMemory(target, size);
system.ArmInterface(1).UnmapMemory(target, size);
system.ArmInterface(2).UnmapMemory(target, size);
@@ -302,6 +299,86 @@ ResultVal<VAddr> VMManager::SetHeapSize(u64 size) {
return MakeResult<VAddr>(heap_region_base);
}
ResultCode VMManager::MapCodeMemory(VAddr dst_address, VAddr src_address, u64 size) {
constexpr auto ignore_attribute = MemoryAttribute::LockedForIPC | MemoryAttribute::DeviceMapped;
const auto src_check_result = CheckRangeState(
src_address, size, MemoryState::All, MemoryState::Heap, VMAPermission::All,
VMAPermission::ReadWrite, MemoryAttribute::Mask, MemoryAttribute::None, ignore_attribute);
if (src_check_result.Failed()) {
return src_check_result.Code();
}
const auto mirror_result =
MirrorMemory(dst_address, src_address, size, MemoryState::ModuleCode);
if (mirror_result.IsError()) {
return mirror_result;
}
// Ensure we lock the source memory region.
const auto src_vma_result = CarveVMARange(src_address, size);
if (src_vma_result.Failed()) {
return src_vma_result.Code();
}
auto src_vma_iter = *src_vma_result;
src_vma_iter->second.attribute = MemoryAttribute::Locked;
Reprotect(src_vma_iter, VMAPermission::Read);
// The destination memory region is fine as is, however we need to make it read-only.
return ReprotectRange(dst_address, size, VMAPermission::Read);
}
ResultCode VMManager::UnmapCodeMemory(VAddr dst_address, VAddr src_address, u64 size) {
constexpr auto ignore_attribute = MemoryAttribute::LockedForIPC | MemoryAttribute::DeviceMapped;
const auto src_check_result = CheckRangeState(
src_address, size, MemoryState::All, MemoryState::Heap, VMAPermission::None,
VMAPermission::None, MemoryAttribute::Mask, MemoryAttribute::Locked, ignore_attribute);
if (src_check_result.Failed()) {
return src_check_result.Code();
}
// Yes, the kernel only checks the first page of the region.
const auto dst_check_result =
CheckRangeState(dst_address, Memory::PAGE_SIZE, MemoryState::FlagModule,
MemoryState::FlagModule, VMAPermission::None, VMAPermission::None,
MemoryAttribute::Mask, MemoryAttribute::None, ignore_attribute);
if (dst_check_result.Failed()) {
return dst_check_result.Code();
}
const auto dst_memory_state = std::get<MemoryState>(*dst_check_result);
const auto dst_contiguous_check_result = CheckRangeState(
dst_address, size, MemoryState::All, dst_memory_state, VMAPermission::None,
VMAPermission::None, MemoryAttribute::Mask, MemoryAttribute::None, ignore_attribute);
if (dst_contiguous_check_result.Failed()) {
return dst_contiguous_check_result.Code();
}
const auto unmap_result = UnmapRange(dst_address, size);
if (unmap_result.IsError()) {
return unmap_result;
}
// With the mirrored portion unmapped, restore the original region's traits.
const auto src_vma_result = CarveVMARange(src_address, size);
if (src_vma_result.Failed()) {
return src_vma_result.Code();
}
auto src_vma_iter = *src_vma_result;
src_vma_iter->second.state = MemoryState::Heap;
src_vma_iter->second.attribute = MemoryAttribute::None;
Reprotect(src_vma_iter, VMAPermission::ReadWrite);
if (dst_memory_state == MemoryState::ModuleCode) {
system.InvalidateCpuInstructionCaches();
}
return unmap_result;
}
MemoryInfo VMManager::QueryMemory(VAddr address) const {
const auto vma = FindVMA(address);
MemoryInfo memory_info{};

View File

@@ -14,6 +14,10 @@
#include "core/hle/result.h"
#include "core/memory.h"
namespace Core {
class System;
}
namespace FileSys {
enum class ProgramAddressSpaceType : u8;
}
@@ -43,6 +47,9 @@ enum class VMAPermission : u8 {
ReadExecute = Read | Execute,
WriteExecute = Write | Execute,
ReadWriteExecute = Read | Write | Execute,
// Used as a wildcard when checking permissions across memory ranges
All = 0xFF,
};
constexpr VMAPermission operator|(VMAPermission lhs, VMAPermission rhs) {
@@ -152,6 +159,9 @@ enum class MemoryState : u32 {
FlagUncached = 1U << 24,
FlagCodeMemory = 1U << 25,
// Wildcard used in range checking to indicate all states.
All = 0xFFFFFFFF,
// Convenience flag sets to reduce repetition
IPCFlags = FlagIPC0 | FlagIPC3 | FlagIPC1,
@@ -315,7 +325,7 @@ class VMManager final {
public:
using VMAHandle = VMAMap::const_iterator;
VMManager();
explicit VMManager(Core::System& system);
~VMManager();
/// Clears the address space map, re-initializing with a single free area.
@@ -415,6 +425,49 @@ public:
///
ResultVal<VAddr> SetHeapSize(u64 size);
/// Maps a region of memory as code memory.
///
/// @param dst_address The base address of the region to create the aliasing memory region.
/// @param src_address The base address of the region to be aliased.
/// @param size The total amount of memory to map in bytes.
///
/// @pre Both memory regions lie within the actual addressable address space.
///
/// @post After this function finishes execution, assuming success, then the address range
/// [dst_address, dst_address+size) will alias the memory region,
/// [src_address, src_address+size).
/// <p>
/// What this also entails is as follows:
/// 1. The aliased region gains the Locked memory attribute.
/// 2. The aliased region becomes read-only.
/// 3. The aliasing region becomes read-only.
/// 4. The aliasing region is created with a memory state of MemoryState::CodeModule.
///
ResultCode MapCodeMemory(VAddr dst_address, VAddr src_address, u64 size);
/// Unmaps a region of memory designated as code module memory.
///
/// @param dst_address The base address of the memory region aliasing the source memory region.
/// @param src_address The base address of the memory region being aliased.
/// @param size The size of the memory region to unmap in bytes.
///
/// @pre Both memory ranges lie within the actual addressable address space.
///
/// @pre The memory region being unmapped has been previously been mapped
/// by a call to MapCodeMemory.
///
/// @post After execution of the function, if successful. the aliasing memory region
/// will be unmapped and the aliased region will have various traits about it
/// restored to what they were prior to the original mapping call preceding
/// this function call.
/// <p>
/// What this also entails is as follows:
/// 1. The state of the memory region will now indicate a general heap region.
/// 2. All memory attributes for the memory region are cleared.
/// 3. Memory permissions for the region are restored to user read/write.
///
ResultCode UnmapCodeMemory(VAddr dst_address, VAddr src_address, u64 size);
/// Queries the memory manager for information about the given address.
///
/// @param address The address to query the memory manager about for information.
@@ -663,5 +716,7 @@ private:
// The end of the currently allocated heap. This is not an inclusive
// end of the range. This is essentially 'base_address + current_size'.
VAddr heap_end = 0;
Core::System& system;
};
} // namespace Kernel

View File

@@ -30,7 +30,7 @@ void WaitObject::RemoveWaitingThread(Thread* thread) {
waiting_threads.erase(itr);
}
SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() {
SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() const {
Thread* candidate = nullptr;
u32 candidate_priority = THREADPRIO_LOWEST + 1;
@@ -38,8 +38,7 @@ SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() {
const ThreadStatus thread_status = thread->GetStatus();
// The list of waiting threads must not contain threads that are not waiting to be awakened.
ASSERT_MSG(thread_status == ThreadStatus::WaitSynchAny ||
thread_status == ThreadStatus::WaitSynchAll ||
ASSERT_MSG(thread_status == ThreadStatus::WaitSynch ||
thread_status == ThreadStatus::WaitHLEEvent,
"Inconsistent thread statuses in waiting_threads");
@@ -49,10 +48,10 @@ SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() {
if (ShouldWait(thread.get()))
continue;
// A thread is ready to run if it's either in ThreadStatus::WaitSynchAny or
// in ThreadStatus::WaitSynchAll and the rest of the objects it is waiting on are ready.
// A thread is ready to run if it's either in ThreadStatus::WaitSynch
// and the rest of the objects it is waiting on are ready.
bool ready_to_run = true;
if (thread_status == ThreadStatus::WaitSynchAll) {
if (thread_status == ThreadStatus::WaitSynch) {
ready_to_run = thread->AllWaitObjectsReady();
}
@@ -68,33 +67,35 @@ SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() {
void WaitObject::WakeupWaitingThread(SharedPtr<Thread> thread) {
ASSERT(!ShouldWait(thread.get()));
if (!thread)
if (!thread) {
return;
}
if (!thread->IsSleepingOnWaitAll()) {
Acquire(thread.get());
} else {
if (thread->IsSleepingOnWait()) {
for (const auto& object : thread->GetWaitObjects()) {
ASSERT(!object->ShouldWait(thread.get()));
object->Acquire(thread.get());
}
} else {
Acquire(thread.get());
}
const std::size_t index = thread->GetWaitObjectIndex(this);
for (const auto& object : thread->GetWaitObjects())
for (const auto& object : thread->GetWaitObjects()) {
object->RemoveWaitingThread(thread.get());
}
thread->ClearWaitObjects();
thread->CancelWakeupTimer();
bool resume = true;
if (thread->HasWakeupCallback())
if (thread->HasWakeupCallback()) {
resume = thread->InvokeWakeupCallback(ThreadWakeupReason::Signal, thread, this, index);
if (resume)
}
if (resume) {
thread->ResumeFromWait();
}
}
void WaitObject::WakeupAllWaitingThreads() {

View File

@@ -54,7 +54,7 @@ public:
void WakeupWaitingThread(SharedPtr<Thread> thread);
/// Obtains the highest priority thread that is ready to run from this object's waiting list.
SharedPtr<Thread> GetHighestPriorityReadyThread();
SharedPtr<Thread> GetHighestPriorityReadyThread() const;
/// Get a const reference to the waiting threads list for debug use
const std::vector<SharedPtr<Thread>>& GetWaitingThreads() const;

View File

@@ -137,6 +137,7 @@ private:
class IManagerForApplication final : public ServiceFramework<IManagerForApplication> {
public:
IManagerForApplication() : ServiceFramework("IManagerForApplication") {
// clang-format off
static const FunctionInfo functions[] = {
{0, &IManagerForApplication::CheckAvailability, "CheckAvailability"},
{1, &IManagerForApplication::GetAccountId, "GetAccountId"},
@@ -145,7 +146,10 @@ public:
{130, nullptr, "GetNintendoAccountUserResourceCacheForApplication"},
{150, nullptr, "CreateAuthorizationRequest"},
{160, nullptr, "StoreOpenContext"},
{170, nullptr, "LoadNetworkServiceLicenseKindAsync"},
};
// clang-format on
RegisterHandlers(functions);
}

View File

@@ -8,6 +8,7 @@ namespace Service::Account {
ACC_SU::ACC_SU(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> profile_manager)
: Module::Interface(std::move(module), std::move(profile_manager), "acc:su") {
// clang-format off
static const FunctionInfo functions[] = {
{0, &ACC_SU::GetUserCount, "GetUserCount"},
{1, &ACC_SU::GetUserExistence, "GetUserExistence"},
@@ -19,6 +20,7 @@ ACC_SU::ACC_SU(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> p
{50, &ACC_SU::IsUserRegistrationRequestPermitted, "IsUserRegistrationRequestPermitted"},
{51, &ACC_SU::TrySelectUserWithoutInteraction, "TrySelectUserWithoutInteraction"},
{60, nullptr, "ListOpenContextStoredUsers"},
{99, nullptr, "DebugActivateOpenContextRetention"},
{100, nullptr, "GetUserRegistrationNotifier"},
{101, nullptr, "GetUserStateChangeNotifier"},
{102, nullptr, "GetBaasAccountManagerForSystemService"},
@@ -29,6 +31,8 @@ ACC_SU::ACC_SU(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> p
{111, nullptr, "ClearSaveDataThumbnail"},
{112, nullptr, "LoadSaveDataThumbnail"},
{113, nullptr, "GetSaveDataThumbnailExistence"},
{130, nullptr, "ActivateOpenContextRetention"},
{140, nullptr, "ListQualifiedUsers"},
{190, nullptr, "GetUserLastOpenedApplication"},
{191, nullptr, "ActivateOpenContextHolder"},
{200, nullptr, "BeginUserRegistration"},
@@ -48,6 +52,8 @@ ACC_SU::ACC_SU(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> p
{998, nullptr, "DebugSetUserStateClose"},
{999, nullptr, "DebugSetUserStateOpen"},
};
// clang-format on
RegisterHandlers(functions);
}

View File

@@ -8,6 +8,7 @@ namespace Service::Account {
ACC_U0::ACC_U0(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> profile_manager)
: Module::Interface(std::move(module), std::move(profile_manager), "acc:u0") {
// clang-format off
static const FunctionInfo functions[] = {
{0, &ACC_U0::GetUserCount, "GetUserCount"},
{1, &ACC_U0::GetUserExistence, "GetUserExistence"},
@@ -19,6 +20,7 @@ ACC_U0::ACC_U0(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> p
{50, &ACC_U0::IsUserRegistrationRequestPermitted, "IsUserRegistrationRequestPermitted"},
{51, &ACC_U0::TrySelectUserWithoutInteraction, "TrySelectUserWithoutInteraction"},
{60, nullptr, "ListOpenContextStoredUsers"},
{99, nullptr, "DebugActivateOpenContextRetention"},
{100, &ACC_U0::InitializeApplicationInfo, "InitializeApplicationInfo"},
{101, &ACC_U0::GetBaasAccountManagerForApplication, "GetBaasAccountManagerForApplication"},
{102, nullptr, "AuthenticateApplicationAsync"},
@@ -27,7 +29,13 @@ ACC_U0::ACC_U0(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> p
{111, nullptr, "ClearSaveDataThumbnail"},
{120, nullptr, "CreateGuestLoginRequest"},
{130, nullptr, "LoadOpenContext"},
{131, nullptr, "ListOpenContextStoredUsers"},
{140, nullptr, "InitializeApplicationInfo"},
{141, nullptr, "ListQualifiedUsers"},
{150, nullptr, "IsUserAccountSwitchLocked"},
};
// clang-format on
RegisterHandlers(functions);
}

View File

@@ -8,6 +8,7 @@ namespace Service::Account {
ACC_U1::ACC_U1(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> profile_manager)
: Module::Interface(std::move(module), std::move(profile_manager), "acc:u1") {
// clang-format off
static const FunctionInfo functions[] = {
{0, &ACC_U1::GetUserCount, "GetUserCount"},
{1, &ACC_U1::GetUserExistence, "GetUserExistence"},
@@ -19,6 +20,7 @@ ACC_U1::ACC_U1(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> p
{50, &ACC_U1::IsUserRegistrationRequestPermitted, "IsUserRegistrationRequestPermitted"},
{51, &ACC_U1::TrySelectUserWithoutInteraction, "TrySelectUserWithoutInteraction"},
{60, nullptr, "ListOpenContextStoredUsers"},
{99, nullptr, "DebugActivateOpenContextRetention"},
{100, nullptr, "GetUserRegistrationNotifier"},
{101, nullptr, "GetUserStateChangeNotifier"},
{102, nullptr, "GetBaasAccountManagerForSystemService"},
@@ -29,12 +31,16 @@ ACC_U1::ACC_U1(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> p
{111, nullptr, "ClearSaveDataThumbnail"},
{112, nullptr, "LoadSaveDataThumbnail"},
{113, nullptr, "GetSaveDataThumbnailExistence"},
{130, nullptr, "ActivateOpenContextRetention"},
{140, nullptr, "ListQualifiedUsers"},
{190, nullptr, "GetUserLastOpenedApplication"},
{191, nullptr, "ActivateOpenContextHolder"},
{997, nullptr, "DebugInvalidateTokenCacheForUser"},
{998, nullptr, "DebugSetUserStateClose"},
{999, nullptr, "DebugSetUserStateOpen"},
};
// clang-format on
RegisterHandlers(functions);
}

View File

@@ -22,7 +22,6 @@
#include "core/hle/service/am/applets/applets.h"
#include "core/hle/service/am/applets/profile_select.h"
#include "core/hle/service/am/applets/software_keyboard.h"
#include "core/hle/service/am/applets/stub_applet.h"
#include "core/hle/service/am/applets/web_browser.h"
#include "core/hle/service/am/idle.h"
#include "core/hle/service/am/omm.h"
@@ -42,12 +41,6 @@ constexpr ResultCode ERR_NO_DATA_IN_CHANNEL{ErrorModule::AM, 0x2};
constexpr ResultCode ERR_NO_MESSAGES{ErrorModule::AM, 0x3};
constexpr ResultCode ERR_SIZE_OUT_OF_BOUNDS{ErrorModule::AM, 0x1F7};
enum class AppletId : u32 {
ProfileSelect = 0x10,
SoftwareKeyboard = 0x11,
LibAppletOff = 0x17,
};
constexpr u32 POP_LAUNCH_PARAMETER_MAGIC = 0xC79497CA;
struct LaunchParameters {
@@ -224,6 +217,7 @@ IDebugFunctions::IDebugFunctions() : ServiceFramework{"IDebugFunctions"} {
{20, nullptr, "InvalidateTransitionLayer"},
{30, nullptr, "RequestLaunchApplicationWithUserAndArgumentForDebug"},
{40, nullptr, "GetAppletResourceUsageInfo"},
{41, nullptr, "SetCpuBoostModeForApplet"},
};
// clang-format on
@@ -256,6 +250,7 @@ ISelfController::ISelfController(std::shared_ptr<NVFlinger::NVFlinger> nvflinger
{40, &ISelfController::CreateManagedDisplayLayer, "CreateManagedDisplayLayer"},
{41, nullptr, "IsSystemBufferSharingEnabled"},
{42, nullptr, "GetSystemSharedLayerHandle"},
{43, nullptr, "GetSystemSharedBufferHandle"},
{50, &ISelfController::SetHandlesRequestToDisplay, "SetHandlesRequestToDisplay"},
{51, nullptr, "ApproveToDisplay"},
{60, nullptr, "OverrideAutoSleepTimeAndDimmingTime"},
@@ -269,9 +264,11 @@ ISelfController::ISelfController(std::shared_ptr<NVFlinger::NVFlinger> nvflinger
{68, nullptr, "SetAutoSleepDisabled"},
{69, nullptr, "IsAutoSleepDisabled"},
{70, nullptr, "ReportMultimediaError"},
{71, nullptr, "GetCurrentIlluminanceEx"},
{80, nullptr, "SetWirelessPriorityMode"},
{90, nullptr, "GetAccumulatedSuspendedTickValue"},
{91, nullptr, "GetAccumulatedSuspendedTickChangedEvent"},
{100, nullptr, "SetAlbumImageTakenNotificationEnabled"},
{1000, nullptr, "GetDebugStorageChannel"},
};
// clang-format on
@@ -516,11 +513,20 @@ ICommonStateGetter::ICommonStateGetter(std::shared_ptr<AppletMessageQueue> msg_q
{50, nullptr, "IsVrModeEnabled"},
{51, nullptr, "SetVrModeEnabled"},
{52, nullptr, "SwitchLcdBacklight"},
{53, nullptr, "BeginVrModeEx"},
{54, nullptr, "EndVrModeEx"},
{55, nullptr, "IsInControllerFirmwareUpdateSection"},
{60, &ICommonStateGetter::GetDefaultDisplayResolution, "GetDefaultDisplayResolution"},
{61, &ICommonStateGetter::GetDefaultDisplayResolutionChangeEvent, "GetDefaultDisplayResolutionChangeEvent"},
{62, nullptr, "GetHdcpAuthenticationState"},
{63, nullptr, "GetHdcpAuthenticationStateChangeEvent"},
{64, nullptr, "SetTvPowerStateMatchingMode"},
{65, nullptr, "GetApplicationIdByContentActionName"},
{66, nullptr, "SetCpuBoostMode"},
{80, nullptr, "PerformSystemButtonPressingIfInFocus"},
{90, nullptr, "SetPerformanceConfigurationChangedNotification"},
{91, nullptr, "GetCurrentPerformanceConfiguration"},
{200, nullptr, "GetOperationModeSystemInfo"},
};
// clang-format on
@@ -873,30 +879,16 @@ ILibraryAppletCreator::ILibraryAppletCreator() : ServiceFramework("ILibraryApple
ILibraryAppletCreator::~ILibraryAppletCreator() = default;
static std::shared_ptr<Applets::Applet> GetAppletFromId(AppletId id) {
switch (id) {
case AppletId::ProfileSelect:
return std::make_shared<Applets::ProfileSelect>();
case AppletId::SoftwareKeyboard:
return std::make_shared<Applets::SoftwareKeyboard>();
case AppletId::LibAppletOff:
return std::make_shared<Applets::WebBrowser>();
default:
LOG_ERROR(Service_AM, "Unimplemented AppletId [{:08X}]! -- Falling back to stub!",
static_cast<u32>(id));
return std::make_shared<Applets::StubApplet>();
}
}
void ILibraryAppletCreator::CreateLibraryApplet(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto applet_id = rp.PopRaw<AppletId>();
const auto applet_id = rp.PopRaw<Applets::AppletId>();
const auto applet_mode = rp.PopRaw<u32>();
LOG_DEBUG(Service_AM, "called with applet_id={:08X}, applet_mode={:08X}",
static_cast<u32>(applet_id), applet_mode);
const auto applet = GetAppletFromId(applet_id);
const auto& applet_manager{Core::System::GetInstance().GetAppletManager()};
const auto applet = applet_manager.GetApplet(applet_id);
if (applet == nullptr) {
LOG_ERROR(Service_AM, "Applet doesn't exist! applet_id={}", static_cast<u32>(applet_id));
@@ -960,6 +952,8 @@ IApplicationFunctions::IApplicationFunctions() : ServiceFramework("IApplicationF
{11, nullptr, "CreateApplicationAndPushAndRequestToStartForQuest"},
{12, nullptr, "CreateApplicationAndRequestToStart"},
{13, &IApplicationFunctions::CreateApplicationAndRequestToStartForQuest, "CreateApplicationAndRequestToStartForQuest"},
{14, nullptr, "CreateApplicationWithAttributeAndPushAndRequestToStartForQuest"},
{15, nullptr, "CreateApplicationWithAttributeAndRequestToStartForQuest"},
{20, &IApplicationFunctions::EnsureSaveData, "EnsureSaveData"},
{21, &IApplicationFunctions::GetDesiredLanguage, "GetDesiredLanguage"},
{22, &IApplicationFunctions::SetTerminateResult, "SetTerminateResult"},
@@ -1233,6 +1227,7 @@ IGlobalStateController::IGlobalStateController() : ServiceFramework("IGlobalStat
{2, nullptr, "StartSleepSequence"},
{3, nullptr, "StartShutdownSequence"},
{4, nullptr, "StartRebootSequence"},
{9, nullptr, "IsAutoPowerDownRequested"},
{10, nullptr, "LoadAndApplyIdlePolicySettings"},
{11, nullptr, "NotifyCecSettingsChanged"},
{12, nullptr, "SetDefaultHomeButtonLongPressTime"},

View File

@@ -16,6 +16,7 @@ public:
std::shared_ptr<AppletMessageQueue> msg_queue)
: ServiceFramework("ILibraryAppletProxy"), nvflinger(std::move(nvflinger)),
msg_queue(std::move(msg_queue)) {
// clang-format off
static const FunctionInfo functions[] = {
{0, &ILibraryAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"},
{1, &ILibraryAppletProxy::GetSelfController, "GetSelfController"},
@@ -25,8 +26,11 @@ public:
{10, &ILibraryAppletProxy::GetProcessWindingController, "GetProcessWindingController"},
{11, &ILibraryAppletProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"},
{20, &ILibraryAppletProxy::GetApplicationFunctions, "GetApplicationFunctions"},
{21, nullptr, "GetAppletCommonFunctions"},
{1000, &ILibraryAppletProxy::GetDebugFunctions, "GetDebugFunctions"},
};
// clang-format on
RegisterHandlers(functions);
}
@@ -113,6 +117,7 @@ public:
std::shared_ptr<AppletMessageQueue> msg_queue)
: ServiceFramework("ISystemAppletProxy"), nvflinger(std::move(nvflinger)),
msg_queue(std::move(msg_queue)) {
// clang-format off
static const FunctionInfo functions[] = {
{0, &ISystemAppletProxy::GetCommonStateGetter, "GetCommonStateGetter"},
{1, &ISystemAppletProxy::GetSelfController, "GetSelfController"},
@@ -124,8 +129,11 @@ public:
{20, &ISystemAppletProxy::GetHomeMenuFunctions, "GetHomeMenuFunctions"},
{21, &ISystemAppletProxy::GetGlobalStateController, "GetGlobalStateController"},
{22, &ISystemAppletProxy::GetApplicationCreator, "GetApplicationCreator"},
{23, nullptr, "GetAppletCommonFunctions"},
{1000, &ISystemAppletProxy::GetDebugFunctions, "GetDebugFunctions"},
};
// clang-format on
RegisterHandlers(functions);
}

View File

@@ -5,11 +5,21 @@
#include <cstring>
#include "common/assert.h"
#include "core/core.h"
#include "core/frontend/applets/error.h"
#include "core/frontend/applets/general_frontend.h"
#include "core/frontend/applets/profile_select.h"
#include "core/frontend/applets/software_keyboard.h"
#include "core/frontend/applets/web_browser.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/server_session.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/am/am.h"
#include "core/hle/service/am/applets/applets.h"
#include "core/hle/service/am/applets/error.h"
#include "core/hle/service/am/applets/general_backend.h"
#include "core/hle/service/am/applets/profile_select.h"
#include "core/hle/service/am/applets/software_keyboard.h"
#include "core/hle/service/am/applets/web_browser.h"
namespace Service::AM::Applets {
@@ -111,4 +121,76 @@ void Applet::Initialize() {
initialized = true;
}
AppletManager::AppletManager() = default;
AppletManager::~AppletManager() = default;
void AppletManager::SetAppletFrontendSet(AppletFrontendSet set) {
if (set.error != nullptr)
frontend.error = std::move(set.error);
if (set.photo_viewer != nullptr)
frontend.photo_viewer = std::move(set.photo_viewer);
if (set.profile_select != nullptr)
frontend.profile_select = std::move(set.profile_select);
if (set.software_keyboard != nullptr)
frontend.software_keyboard = std::move(set.software_keyboard);
if (set.web_browser != nullptr)
frontend.web_browser = std::move(set.web_browser);
}
void AppletManager::SetDefaultAppletFrontendSet() {
frontend.error = std::make_unique<Core::Frontend::DefaultErrorApplet>();
frontend.photo_viewer = std::make_unique<Core::Frontend::DefaultPhotoViewerApplet>();
frontend.profile_select = std::make_unique<Core::Frontend::DefaultProfileSelectApplet>();
frontend.software_keyboard = std::make_unique<Core::Frontend::DefaultSoftwareKeyboardApplet>();
frontend.web_browser = std::make_unique<Core::Frontend::DefaultWebBrowserApplet>();
}
void AppletManager::SetDefaultAppletsIfMissing() {
if (frontend.error == nullptr) {
frontend.error = std::make_unique<Core::Frontend::DefaultErrorApplet>();
}
if (frontend.photo_viewer == nullptr) {
frontend.photo_viewer = std::make_unique<Core::Frontend::DefaultPhotoViewerApplet>();
}
if (frontend.profile_select == nullptr) {
frontend.profile_select = std::make_unique<Core::Frontend::DefaultProfileSelectApplet>();
}
if (frontend.software_keyboard == nullptr) {
frontend.software_keyboard =
std::make_unique<Core::Frontend::DefaultSoftwareKeyboardApplet>();
}
if (frontend.web_browser == nullptr) {
frontend.web_browser = std::make_unique<Core::Frontend::DefaultWebBrowserApplet>();
}
}
void AppletManager::ClearAll() {
frontend = {};
}
std::shared_ptr<Applet> AppletManager::GetApplet(AppletId id) const {
switch (id) {
case AppletId::Error:
return std::make_shared<Error>(*frontend.error);
case AppletId::ProfileSelect:
return std::make_shared<ProfileSelect>(*frontend.profile_select);
case AppletId::SoftwareKeyboard:
return std::make_shared<SoftwareKeyboard>(*frontend.software_keyboard);
case AppletId::PhotoViewer:
return std::make_shared<PhotoViewer>(*frontend.photo_viewer);
case AppletId::LibAppletOff:
return std::make_shared<WebBrowser>(*frontend.web_browser);
default:
UNIMPLEMENTED_MSG(
"No backend implementation exists for applet_id={:02X}! Falling back to stub applet.",
static_cast<u8>(id));
return std::make_shared<StubApplet>();
}
}
} // namespace Service::AM::Applets

View File

@@ -12,12 +12,43 @@
union ResultCode;
namespace Core::Frontend {
class ErrorApplet;
class PhotoViewerApplet;
class ProfileSelectApplet;
class SoftwareKeyboardApplet;
class WebBrowserApplet;
} // namespace Core::Frontend
namespace Service::AM {
class IStorage;
namespace Applets {
enum class AppletId : u32 {
OverlayDisplay = 0x02,
QLaunch = 0x03,
Starter = 0x04,
Auth = 0x0A,
Cabinet = 0x0B,
Controller = 0x0C,
DataErase = 0x0D,
Error = 0x0E,
NetConnect = 0x0F,
ProfileSelect = 0x10,
SoftwareKeyboard = 0x11,
MiiEdit = 0x12,
LibAppletWeb = 0x13,
LibAppletShop = 0x14,
PhotoViewer = 0x15,
Settings = 0x16,
LibAppletOff = 0x17,
LibAppletWhitelisted = 0x18,
LibAppletAuth = 0x19,
MyPage = 0x1A,
};
class AppletDataBroker final {
public:
AppletDataBroker();
@@ -105,5 +136,29 @@ protected:
bool initialized = false;
};
struct AppletFrontendSet {
std::unique_ptr<Core::Frontend::ErrorApplet> error;
std::unique_ptr<Core::Frontend::PhotoViewerApplet> photo_viewer;
std::unique_ptr<Core::Frontend::ProfileSelectApplet> profile_select;
std::unique_ptr<Core::Frontend::SoftwareKeyboardApplet> software_keyboard;
std::unique_ptr<Core::Frontend::WebBrowserApplet> web_browser;
};
class AppletManager {
public:
AppletManager();
~AppletManager();
void SetAppletFrontendSet(AppletFrontendSet set);
void SetDefaultAppletFrontendSet();
void SetDefaultAppletsIfMissing();
void ClearAll();
std::shared_ptr<Applet> GetApplet(AppletId id) const;
private:
AppletFrontendSet frontend;
};
} // namespace Applets
} // namespace Service::AM

View File

@@ -0,0 +1,182 @@
// Copyright 2019 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <array>
#include <cstring>
#include "common/assert.h"
#include "common/logging/log.h"
#include "common/string_util.h"
#include "core/core.h"
#include "core/frontend/applets/error.h"
#include "core/hle/service/am/am.h"
#include "core/hle/service/am/applets/error.h"
namespace Service::AM::Applets {
#pragma pack(push, 4)
struct ShowError {
u8 mode;
bool jump;
INSERT_PADDING_BYTES(4);
bool use_64bit_error_code;
INSERT_PADDING_BYTES(1);
u64 error_code_64;
u32 error_code_32;
};
static_assert(sizeof(ShowError) == 0x14, "ShowError has incorrect size.");
#pragma pack(pop)
struct ShowErrorRecord {
u8 mode;
bool jump;
INSERT_PADDING_BYTES(6);
u64 error_code_64;
u64 posix_time;
};
static_assert(sizeof(ShowErrorRecord) == 0x18, "ShowErrorRecord has incorrect size.");
struct SystemErrorArg {
u8 mode;
bool jump;
INSERT_PADDING_BYTES(6);
u64 error_code_64;
std::array<char, 8> language_code;
std::array<char, 0x800> main_text;
std::array<char, 0x800> detail_text;
};
static_assert(sizeof(SystemErrorArg) == 0x1018, "SystemErrorArg has incorrect size.");
struct ApplicationErrorArg {
u8 mode;
bool jump;
INSERT_PADDING_BYTES(6);
u32 error_code;
std::array<char, 8> language_code;
std::array<char, 0x800> main_text;
std::array<char, 0x800> detail_text;
};
static_assert(sizeof(ApplicationErrorArg) == 0x1014, "ApplicationErrorArg has incorrect size.");
union Error::ErrorArguments {
ShowError error;
ShowErrorRecord error_record;
SystemErrorArg system_error;
ApplicationErrorArg application_error;
};
namespace {
template <typename T>
void CopyArgumentData(const std::vector<u8>& data, T& variable) {
ASSERT(data.size() >= sizeof(T));
std::memcpy(&variable, data.data(), sizeof(T));
}
ResultCode Decode64BitError(u64 error) {
const auto description = (error >> 32) & 0x1FFF;
auto module = error & 0x3FF;
if (module >= 2000)
module -= 2000;
module &= 0x1FF;
return {static_cast<ErrorModule>(module), static_cast<u32>(description)};
}
} // Anonymous namespace
Error::Error(const Core::Frontend::ErrorApplet& frontend) : frontend(frontend) {}
Error::~Error() = default;
void Error::Initialize() {
Applet::Initialize();
args = std::make_unique<ErrorArguments>();
complete = false;
const auto storage = broker.PopNormalDataToApplet();
ASSERT(storage != nullptr);
const auto data = storage->GetData();
ASSERT(!data.empty());
std::memcpy(&mode, data.data(), sizeof(ErrorAppletMode));
switch (mode) {
case ErrorAppletMode::ShowError:
CopyArgumentData(data, args->error);
if (args->error.use_64bit_error_code) {
error_code = Decode64BitError(args->error.error_code_64);
} else {
error_code = ResultCode(args->error.error_code_32);
}
break;
case ErrorAppletMode::ShowSystemError:
CopyArgumentData(data, args->system_error);
error_code = ResultCode(Decode64BitError(args->system_error.error_code_64));
break;
case ErrorAppletMode::ShowApplicationError:
CopyArgumentData(data, args->application_error);
error_code = ResultCode(args->application_error.error_code);
break;
case ErrorAppletMode::ShowErrorRecord:
CopyArgumentData(data, args->error_record);
error_code = Decode64BitError(args->error_record.error_code_64);
break;
default:
UNIMPLEMENTED_MSG("Unimplemented LibAppletError mode={:02X}!", static_cast<u8>(mode));
}
}
bool Error::TransactionComplete() const {
return complete;
}
ResultCode Error::GetStatus() const {
return RESULT_SUCCESS;
}
void Error::ExecuteInteractive() {
UNREACHABLE_MSG("Unexpected interactive applet data!");
}
void Error::Execute() {
if (complete) {
return;
}
const auto callback = [this] { DisplayCompleted(); };
switch (mode) {
case ErrorAppletMode::ShowError:
frontend.ShowError(error_code, callback);
break;
case ErrorAppletMode::ShowSystemError:
case ErrorAppletMode::ShowApplicationError: {
const auto system = mode == ErrorAppletMode::ShowSystemError;
const auto& main_text =
system ? args->system_error.main_text : args->application_error.main_text;
const auto& detail_text =
system ? args->system_error.detail_text : args->application_error.detail_text;
frontend.ShowCustomErrorText(
error_code,
Common::StringFromFixedZeroTerminatedBuffer(main_text.data(), main_text.size()),
Common::StringFromFixedZeroTerminatedBuffer(detail_text.data(), detail_text.size()),
callback);
break;
}
case ErrorAppletMode::ShowErrorRecord:
frontend.ShowErrorWithTimestamp(
error_code, std::chrono::seconds{args->error_record.posix_time}, callback);
break;
default:
UNIMPLEMENTED_MSG("Unimplemented LibAppletError mode={:02X}!", static_cast<u8>(mode));
DisplayCompleted();
}
}
void Error::DisplayCompleted() {
complete = true;
broker.PushNormalDataFromApplet(IStorage{{}});
broker.SignalStateChanged();
}
} // namespace Service::AM::Applets

View File

@@ -0,0 +1,47 @@
// Copyright 2019 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include "core/hle/result.h"
#include "core/hle/service/am/applets/applets.h"
namespace Service::AM::Applets {
enum class ErrorAppletMode : u8 {
ShowError = 0,
ShowSystemError = 1,
ShowApplicationError = 2,
ShowEula = 3,
ShowErrorPctl = 4,
ShowErrorRecord = 5,
ShowUpdateEula = 8,
};
class Error final : public Applet {
public:
explicit Error(const Core::Frontend::ErrorApplet& frontend);
~Error() override;
void Initialize() override;
bool TransactionComplete() const override;
ResultCode GetStatus() const override;
void ExecuteInteractive() override;
void Execute() override;
void DisplayCompleted();
private:
union ErrorArguments;
const Core::Frontend::ErrorApplet& frontend;
ResultCode error_code = RESULT_SUCCESS;
ErrorAppletMode mode = ErrorAppletMode::ShowError;
std::unique_ptr<ErrorArguments> args;
bool complete = false;
};
} // namespace Service::AM::Applets

View File

@@ -4,11 +4,15 @@
#include <string>
#include "common/assert.h"
#include "common/hex_util.h"
#include "common/logging/log.h"
#include "core/core.h"
#include "core/frontend/applets/general_frontend.h"
#include "core/hle/kernel/process.h"
#include "core/hle/result.h"
#include "core/hle/service/am/am.h"
#include "core/hle/service/am/applets/stub_applet.h"
#include "core/hle/service/am/applets/general_backend.h"
namespace Service::AM::Applets {
@@ -30,6 +34,55 @@ static void LogCurrentStorage(AppletDataBroker& broker, std::string prefix) {
}
}
PhotoViewer::PhotoViewer(const Core::Frontend::PhotoViewerApplet& frontend) : frontend(frontend) {}
PhotoViewer::~PhotoViewer() = default;
void PhotoViewer::Initialize() {
Applet::Initialize();
complete = false;
const auto storage = broker.PopNormalDataToApplet();
ASSERT(storage != nullptr);
const auto data = storage->GetData();
ASSERT(!data.empty());
mode = static_cast<PhotoViewerAppletMode>(data[0]);
}
bool PhotoViewer::TransactionComplete() const {
return complete;
}
ResultCode PhotoViewer::GetStatus() const {
return RESULT_SUCCESS;
}
void PhotoViewer::ExecuteInteractive() {
UNREACHABLE_MSG("Unexpected interactive applet data.");
}
void PhotoViewer::Execute() {
if (complete)
return;
const auto callback = [this] { ViewFinished(); };
switch (mode) {
case PhotoViewerAppletMode::CurrentApp:
frontend.ShowPhotosForApplication(Core::CurrentProcess()->GetTitleID(), callback);
break;
case PhotoViewerAppletMode::AllApps:
frontend.ShowAllPhotos(callback);
break;
default:
UNIMPLEMENTED_MSG("Unimplemented PhotoViewer applet mode={:02X}!", static_cast<u8>(mode));
}
}
void PhotoViewer::ViewFinished() {
broker.PushNormalDataFromApplet(IStorage{{}});
broker.SignalStateChanged();
}
StubApplet::StubApplet() = default;
StubApplet::~StubApplet() = default;
@@ -67,4 +120,5 @@ void StubApplet::Execute() {
broker.PushInteractiveDataFromApplet(IStorage{std::vector<u8>(0x1000)});
broker.SignalStateChanged();
}
} // namespace Service::AM::Applets

View File

@@ -0,0 +1,48 @@
// Copyright 2019 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include "core/hle/service/am/applets/applets.h"
namespace Service::AM::Applets {
enum class PhotoViewerAppletMode : u8 {
CurrentApp = 0,
AllApps = 1,
};
class PhotoViewer final : public Applet {
public:
explicit PhotoViewer(const Core::Frontend::PhotoViewerApplet& frontend);
~PhotoViewer() override;
void Initialize() override;
bool TransactionComplete() const override;
ResultCode GetStatus() const override;
void ExecuteInteractive() override;
void Execute() override;
void ViewFinished();
private:
const Core::Frontend::PhotoViewerApplet& frontend;
bool complete = false;
PhotoViewerAppletMode mode = PhotoViewerAppletMode::CurrentApp;
};
class StubApplet final : public Applet {
public:
StubApplet();
~StubApplet() override;
void Initialize() override;
bool TransactionComplete() const override;
ResultCode GetStatus() const override;
void ExecuteInteractive() override;
void Execute() override;
};
} // namespace Service::AM::Applets

View File

@@ -15,7 +15,9 @@ namespace Service::AM::Applets {
constexpr ResultCode ERR_USER_CANCELLED_SELECTION{ErrorModule::Account, 1};
ProfileSelect::ProfileSelect() = default;
ProfileSelect::ProfileSelect(const Core::Frontend::ProfileSelectApplet& frontend)
: frontend(frontend) {}
ProfileSelect::~ProfileSelect() = default;
void ProfileSelect::Initialize() {
@@ -51,8 +53,6 @@ void ProfileSelect::Execute() {
return;
}
const auto& frontend{Core::System::GetInstance().GetProfileSelector()};
frontend.SelectProfile([this](std::optional<Account::UUID> uuid) { SelectionComplete(uuid); });
}

View File

@@ -28,7 +28,7 @@ static_assert(sizeof(UserSelectionOutput) == 0x18, "UserSelectionOutput has inco
class ProfileSelect final : public Applet {
public:
ProfileSelect();
explicit ProfileSelect(const Core::Frontend::ProfileSelectApplet& frontend);
~ProfileSelect() override;
void Initialize() override;
@@ -41,6 +41,8 @@ public:
void SelectionComplete(std::optional<Account::UUID> uuid);
private:
const Core::Frontend::ProfileSelectApplet& frontend;
UserSelectionConfig config;
bool complete = false;
ResultCode status = RESULT_SUCCESS;

View File

@@ -39,7 +39,8 @@ static Core::Frontend::SoftwareKeyboardParameters ConvertToFrontendParameters(
return params;
}
SoftwareKeyboard::SoftwareKeyboard() = default;
SoftwareKeyboard::SoftwareKeyboard(const Core::Frontend::SoftwareKeyboardApplet& frontend)
: frontend(frontend) {}
SoftwareKeyboard::~SoftwareKeyboard() = default;
@@ -90,8 +91,6 @@ void SoftwareKeyboard::ExecuteInteractive() {
if (status == INTERACTIVE_STATUS_OK) {
complete = true;
} else {
const auto& frontend{Core::System::GetInstance().GetSoftwareKeyboard()};
std::array<char16_t, SWKBD_OUTPUT_INTERACTIVE_BUFFER_SIZE / 2 - 2> string;
std::memcpy(string.data(), data.data() + 4, string.size() * 2);
frontend.SendTextCheckDialog(
@@ -106,8 +105,6 @@ void SoftwareKeyboard::Execute() {
return;
}
const auto& frontend{Core::System::GetInstance().GetSoftwareKeyboard()};
const auto parameters = ConvertToFrontendParameters(config, initial_text);
frontend.RequestText([this](std::optional<std::u16string> text) { WriteText(text); },

View File

@@ -55,7 +55,7 @@ static_assert(sizeof(KeyboardConfig) == 0x3E0, "KeyboardConfig has incorrect siz
class SoftwareKeyboard final : public Applet {
public:
SoftwareKeyboard();
explicit SoftwareKeyboard(const Core::Frontend::SoftwareKeyboardApplet& frontend);
~SoftwareKeyboard() override;
void Initialize() override;
@@ -68,6 +68,8 @@ public:
void WriteText(std::optional<std::u16string> text);
private:
const Core::Frontend::SoftwareKeyboardApplet& frontend;
KeyboardConfig config;
std::u16string initial_text;
bool complete = false;

View File

@@ -1,24 +0,0 @@
// Copyright 2018 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include "core/hle/service/am/applets/applets.h"
namespace Service::AM::Applets {
class StubApplet final : public Applet {
public:
StubApplet();
~StubApplet() override;
void Initialize() override;
bool TransactionComplete() const override;
ResultCode GetStatus() const override;
void ExecuteInteractive() override;
void Execute() override;
};
} // namespace Service::AM::Applets

View File

@@ -95,7 +95,7 @@ static FileSys::VirtualFile GetManualRomFS() {
return nullptr;
}
WebBrowser::WebBrowser() = default;
WebBrowser::WebBrowser(Core::Frontend::WebBrowserApplet& frontend) : frontend(frontend) {}
WebBrowser::~WebBrowser() = default;
@@ -152,8 +152,6 @@ void WebBrowser::Execute() {
return;
}
auto& frontend{Core::System::GetInstance().GetWebBrowser()};
frontend.OpenPage(filename, [this] { UnpackRomFS(); }, [this] { Finalize(); });
}

View File

@@ -12,7 +12,7 @@ namespace Service::AM::Applets {
class WebBrowser final : public Applet {
public:
WebBrowser();
WebBrowser(Core::Frontend::WebBrowserApplet& frontend);
~WebBrowser() override;
void Initialize() override;
@@ -32,6 +32,8 @@ public:
void Finalize();
private:
Core::Frontend::WebBrowserApplet& frontend;
bool complete = false;
bool unpacked = false;
ResultCode status = RESULT_SUCCESS;

View File

@@ -50,6 +50,7 @@ static std::vector<u64> AccumulateAOCTitleIDs() {
}
AOC_U::AOC_U() : ServiceFramework("aoc:u"), add_on_content(AccumulateAOCTitleIDs()) {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "CountAddOnContentByApplicationId"},
{1, nullptr, "ListAddOnContentByApplicationId"},
@@ -60,7 +61,10 @@ AOC_U::AOC_U() : ServiceFramework("aoc:u"), add_on_content(AccumulateAOCTitleIDs
{6, nullptr, "PrepareAddOnContentByApplicationId"},
{7, &AOC_U::PrepareAddOnContent, "PrepareAddOnContent"},
{8, &AOC_U::GetAddOnContentListChangedEvent, "GetAddOnContentListChangedEvent"},
{100, nullptr, "CreateEcPurchasedEventManager"},
};
// clang-format on
RegisterHandlers(functions);
auto& kernel = Core::System::GetInstance().Kernel();

View File

@@ -87,6 +87,8 @@ APM_Sys::APM_Sys() : ServiceFramework{"apm:sys"} {
{3, nullptr, "GetLastThrottlingState"},
{4, nullptr, "ClearLastThrottlingState"},
{5, nullptr, "LoadAndApplySettings"},
{6, nullptr, "SetCpuBoostMode"},
{7, nullptr, "GetCurrentPerformanceConfiguration"},
};
// clang-format on

View File

@@ -2,6 +2,8 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "common/logging/log.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/service/audio/audctl.h"
namespace Service::Audio {
@@ -11,8 +13,8 @@ AudCtl::AudCtl() : ServiceFramework{"audctl"} {
static const FunctionInfo functions[] = {
{0, nullptr, "GetTargetVolume"},
{1, nullptr, "SetTargetVolume"},
{2, nullptr, "GetTargetVolumeMin"},
{3, nullptr, "GetTargetVolumeMax"},
{2, &AudCtl::GetTargetVolumeMin, "GetTargetVolumeMin"},
{3, &AudCtl::GetTargetVolumeMax, "GetTargetVolumeMax"},
{4, nullptr, "IsTargetMute"},
{5, nullptr, "SetTargetMute"},
{6, nullptr, "IsTargetConnected"},
@@ -44,4 +46,28 @@ AudCtl::AudCtl() : ServiceFramework{"audctl"} {
AudCtl::~AudCtl() = default;
void AudCtl::GetTargetVolumeMin(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Audio, "called.");
// This service function is currently hardcoded on the
// actual console to this value (as of 8.0.0).
constexpr s32 target_min_volume = 0;
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push(target_min_volume);
}
void AudCtl::GetTargetVolumeMax(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Audio, "called.");
// This service function is currently hardcoded on the
// actual console to this value (as of 8.0.0).
constexpr s32 target_max_volume = 15;
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push(target_max_volume);
}
} // namespace Service::Audio

View File

@@ -12,6 +12,10 @@ class AudCtl final : public ServiceFramework<AudCtl> {
public:
explicit AudCtl();
~AudCtl() override;
private:
void GetTargetVolumeMin(Kernel::HLERequestContext& ctx);
void GetTargetVolumeMax(Kernel::HLERequestContext& ctx);
};
} // namespace Service::Audio

View File

@@ -25,6 +25,7 @@ public:
{11, nullptr, "GetAudioInBufferCount"},
{12, nullptr, "SetAudioInDeviceGain"},
{13, nullptr, "GetAudioInDeviceGain"},
{14, nullptr, "FlushAudioInBuffers"},
};
// clang-format on

View File

@@ -44,7 +44,7 @@ public:
std::string&& unique_name)
: ServiceFramework("IAudioOut"), audio_core(audio_core),
device_name(std::move(device_name)), audio_params(audio_params) {
// clang-format off
static const FunctionInfo functions[] = {
{0, &IAudioOut::GetAudioOutState, "GetAudioOutState"},
{1, &IAudioOut::StartAudioOut, "StartAudioOut"},
@@ -58,7 +58,10 @@ public:
{9, &IAudioOut::GetAudioOutBufferCount, "GetAudioOutBufferCount"},
{10, nullptr, "GetAudioOutPlayedSampleCount"},
{11, nullptr, "FlushAudioOutBuffers"},
{12, nullptr, "SetAudioOutVolume"},
{13, nullptr, "GetAudioOutVolume"},
};
// clang-format on
RegisterHandlers(functions);
// This is the event handle used to check if the audio buffer was released

View File

@@ -154,7 +154,8 @@ public:
{96, nullptr, "GetLeHidEventInfo"},
{97, nullptr, "RegisterBleHidEvent"},
{98, nullptr, "SetLeScanParameter"},
{256, nullptr, "GetIsManufacturingMode"}
{256, nullptr, "GetIsManufacturingMode"},
{257, nullptr, "EmulateBluetoothCrash"},
};
// clang-format on

View File

@@ -15,32 +15,41 @@ public:
explicit CAPS_A() : ServiceFramework{"caps:a"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "Unknown1"},
{1, nullptr, "Unknown2"},
{2, nullptr, "Unknown3"},
{3, nullptr, "Unknown4"},
{4, nullptr, "Unknown5"},
{5, nullptr, "Unknown6"},
{6, nullptr, "Unknown7"},
{7, nullptr, "Unknown8"},
{8, nullptr, "Unknown9"},
{9, nullptr, "Unknown10"},
{10, nullptr, "Unknown11"},
{11, nullptr, "Unknown12"},
{12, nullptr, "Unknown13"},
{13, nullptr, "Unknown14"},
{14, nullptr, "Unknown15"},
{301, nullptr, "Unknown16"},
{401, nullptr, "Unknown17"},
{501, nullptr, "Unknown18"},
{1001, nullptr, "Unknown19"},
{1002, nullptr, "Unknown20"},
{8001, nullptr, "Unknown21"},
{8002, nullptr, "Unknown22"},
{8011, nullptr, "Unknown23"},
{8012, nullptr, "Unknown24"},
{8021, nullptr, "Unknown25"},
{10011, nullptr, "Unknown26"},
{0, nullptr, "GetAlbumFileCount"},
{1, nullptr, "GetAlbumFileList"},
{2, nullptr, "LoadAlbumFile"},
{3, nullptr, "DeleteAlbumFile"},
{4, nullptr, "StorageCopyAlbumFile"},
{5, nullptr, "IsAlbumMounted"},
{6, nullptr, "GetAlbumUsage"},
{7, nullptr, "GetAlbumFileSize"},
{8, nullptr, "LoadAlbumFileThumbnail"},
{9, nullptr, "LoadAlbumScreenShotImage"},
{10, nullptr, "LoadAlbumScreenShotThumbnailImage"},
{11, nullptr, "GetAlbumEntryFromApplicationAlbumEntry"},
{12, nullptr, "Unknown12"},
{13, nullptr, "Unknown13"},
{14, nullptr, "Unknown14"},
{15, nullptr, "Unknown15"},
{16, nullptr, "Unknown16"},
{17, nullptr, "Unknown17"},
{18, nullptr, "Unknown18"},
{202, nullptr, "SaveEditedScreenShot"},
{301, nullptr, "GetLastThumbnail"},
{401, nullptr, "GetAutoSavingStorage"},
{501, nullptr, "GetRequiredStorageSpaceSizeToCopyAll"},
{1001, nullptr, "Unknown1001"},
{1002, nullptr, "Unknown1002"},
{1003, nullptr, "Unknown1003"},
{8001, nullptr, "ForceAlbumUnmounted"},
{8002, nullptr, "ResetAlbumMountStatus"},
{8011, nullptr, "RefreshAlbumCache"},
{8012, nullptr, "GetAlbumCache"},
{8013, nullptr, "Unknown8013"},
{8021, nullptr, "GetAlbumEntryFromApplicationAlbumEntryAruid"},
{10011, nullptr, "SetInternalErrorConversionEnabled"},
{50000, nullptr, "Unknown50000"},
{60002, nullptr, "Unknown60002"},
};
// clang-format on
@@ -53,16 +62,17 @@ public:
explicit CAPS_C() : ServiceFramework{"caps:c"} {
// clang-format off
static const FunctionInfo functions[] = {
{2001, nullptr, "Unknown1"},
{2002, nullptr, "Unknown2"},
{2011, nullptr, "Unknown3"},
{2012, nullptr, "Unknown4"},
{2013, nullptr, "Unknown5"},
{2014, nullptr, "Unknown6"},
{2101, nullptr, "Unknown7"},
{2102, nullptr, "Unknown8"},
{2201, nullptr, "Unknown9"},
{2301, nullptr, "Unknown10"},
{33, nullptr, "Unknown33"},
{2001, nullptr, "Unknown2001"},
{2002, nullptr, "Unknown2002"},
{2011, nullptr, "Unknown2011"},
{2012, nullptr, "Unknown2012"},
{2013, nullptr, "Unknown2013"},
{2014, nullptr, "Unknown2014"},
{2101, nullptr, "Unknown2101"},
{2102, nullptr, "Unknown2102"},
{2201, nullptr, "Unknown2201"},
{2301, nullptr, "Unknown2301"},
};
// clang-format on
@@ -127,11 +137,18 @@ public:
explicit CAPS_U() : ServiceFramework{"caps:u"} {
// clang-format off
static const FunctionInfo functions[] = {
{32, nullptr, "SetShimLibraryVersion"},
{102, nullptr, "GetAlbumFileListByAruid"},
{103, nullptr, "DeleteAlbumFileByAruid"},
{104, nullptr, "GetAlbumFileSizeByAruid"},
{105, nullptr, "DeleteAlbumFileByAruidForDebug"},
{110, nullptr, "LoadAlbumScreenShotImageByAruid"},
{120, nullptr, "LoadAlbumScreenShotThumbnailImageByAruid"},
{130, nullptr, "PrecheckToCreateContentsByAruid"},
{140, nullptr, "GetAlbumFileList1AafeAruidDeprecated"},
{141, nullptr, "GetAlbumFileList2AafeUidAruidDeprecated"},
{142, nullptr, "GetAlbumFileList3AaeAruid"},
{143, nullptr, "GetAlbumFileList4AaeUidAruid"},
{60002, nullptr, "OpenAccessorSessionForApplication"},
};
// clang-format on

View File

@@ -664,10 +664,13 @@ FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") {
{100, nullptr, "OpenImageDirectoryFileSystem"},
{110, nullptr, "OpenContentStorageFileSystem"},
{120, nullptr, "OpenCloudBackupWorkStorageFileSystem"},
{130, nullptr, "OpenCustomStorageFileSystem"},
{200, &FSP_SRV::OpenDataStorageByCurrentProcess, "OpenDataStorageByCurrentProcess"},
{201, nullptr, "OpenDataStorageByProgramId"},
{202, &FSP_SRV::OpenDataStorageByDataId, "OpenDataStorageByDataId"},
{203, &FSP_SRV::OpenPatchDataStorageByCurrentProcess, "OpenPatchDataStorageByCurrentProcess"},
{204, nullptr, "OpenDataFileSystemByProgramIndex"},
{205, nullptr, "OpenDataStorageByProgramIndex"},
{400, nullptr, "OpenDeviceOperator"},
{500, nullptr, "OpenSdCardDetectionEventNotifier"},
{501, nullptr, "OpenGameCardDetectionEventNotifier"},
@@ -691,6 +694,7 @@ FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") {
{614, nullptr, "CorruptSaveDataFileSystemBySaveDataSpaceId"},
{615, nullptr, "QuerySaveDataInternalStorageTotalSize"},
{616, nullptr, "GetSaveDataCommitId"},
{617, nullptr, "UnregisterExternalKey"},
{620, nullptr, "SetSdCardEncryptionSeed"},
{630, nullptr, "SetSdCardAccessibility"},
{631, nullptr, "IsSdCardAccessible"},
@@ -701,6 +705,7 @@ FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") {
{710, nullptr, "ResolveAccessFailure"},
{720, nullptr, "AbandonAccessFailure"},
{800, nullptr, "GetAndClearFileSystemProxyErrorInfo"},
{810, nullptr, "RegisterProgramIndexMapInfo"},
{1000, nullptr, "SetBisRootForHost"},
{1001, nullptr, "SetSaveDataSize"},
{1002, nullptr, "SetSaveDataRootPath"},
@@ -711,6 +716,8 @@ FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") {
{1007, nullptr, "RegisterUpdatePartition"},
{1008, nullptr, "OpenRegisteredUpdatePartition"},
{1009, nullptr, "GetAndClearMemoryReportInfo"},
{1010, nullptr, "SetDataStorageRedirectTarget"},
{1011, nullptr, "OutputAccessLogToSdCard2"},
{1100, nullptr, "OverrideSaveDataTransferTokenSignVerificationKey"},
{1110, nullptr, "CorruptSaveDataFileSystemBySaveDataSpaceId2"},
{1200, nullptr, "OpenMultiCommitManager"},

View File

@@ -12,6 +12,7 @@ namespace Service::Friend {
class IFriendService final : public ServiceFramework<IFriendService> {
public:
IFriendService() : ServiceFramework("IFriendService") {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "GetCompletionEvent"},
{1, nullptr, "Cancel"},
@@ -24,8 +25,7 @@ public:
{10400, nullptr, "GetBlockedUserListIds"},
{10500, nullptr, "GetProfileList"},
{10600, nullptr, "DeclareOpenOnlinePlaySession"},
{10601, &IFriendService::DeclareCloseOnlinePlaySession,
"DeclareCloseOnlinePlaySession"},
{10601, &IFriendService::DeclareCloseOnlinePlaySession, "DeclareCloseOnlinePlaySession"},
{10610, &IFriendService::UpdateUserPresence, "UpdateUserPresence"},
{10700, nullptr, "GetPlayHistoryRegistrationKey"},
{10701, nullptr, "GetPlayHistoryRegistrationKeyWithNetworkServiceAccountId"},
@@ -88,6 +88,7 @@ public:
{30830, nullptr, "ClearPlayLog"},
{49900, nullptr, "DeleteNetworkServiceAccountCache"},
};
// clang-format on
RegisterHandlers(functions);
}

View File

@@ -210,6 +210,7 @@ Hid::Hid() : ServiceFramework("hid") {
{131, nullptr, "IsUnintendedHomeButtonInputProtectionEnabled"},
{132, nullptr, "EnableUnintendedHomeButtonInputProtection"},
{133, nullptr, "SetNpadJoyAssignmentModeSingleWithDestination"},
{134, nullptr, "SetNpadAnalogStickUseCenterClamp"},
{200, &Hid::GetVibrationDeviceInfo, "GetVibrationDeviceInfo"},
{201, &Hid::SendVibrationValue, "SendVibrationValue"},
{202, &Hid::GetActualVibrationValue, "GetActualVibrationValue"},
@@ -221,6 +222,7 @@ Hid::Hid() : ServiceFramework("hid") {
{208, nullptr, "GetActualVibrationGcErmCommand"},
{209, &Hid::BeginPermitVibrationSession, "BeginPermitVibrationSession"},
{210, &Hid::EndPermitVibrationSession, "EndPermitVibrationSession"},
{211, nullptr, "IsVibrationDeviceMounted"},
{300, &Hid::ActivateConsoleSixAxisSensor, "ActivateConsoleSixAxisSensor"},
{301, &Hid::StartConsoleSixAxisSensor, "StartConsoleSixAxisSensor"},
{302, nullptr, "StopConsoleSixAxisSensor"},
@@ -265,6 +267,7 @@ Hid::Hid() : ServiceFramework("hid") {
{523, nullptr, "SetIsPalmaPairedConnectable"},
{524, nullptr, "PairPalma"},
{525, &Hid::SetPalmaBoostMode, "SetPalmaBoostMode"},
{526, nullptr, "CancelWritePalmaWaveEntry"},
{1000, nullptr, "SetNpadCommunicationMode"},
{1001, nullptr, "GetNpadCommunicationMode"},
};
@@ -797,12 +800,22 @@ public:
{232, nullptr, "EnableShipmentMode"},
{233, nullptr, "ClearPairingInfo"},
{234, nullptr, "GetUniquePadDeviceTypeSetInternal"},
{235, nullptr, "EnableAnalogStickPower"},
{301, nullptr, "GetAbstractedPadHandles"},
{302, nullptr, "GetAbstractedPadState"},
{303, nullptr, "GetAbstractedPadsState"},
{321, nullptr, "SetAutoPilotVirtualPadState"},
{322, nullptr, "UnsetAutoPilotVirtualPadState"},
{323, nullptr, "UnsetAllAutoPilotVirtualPadState"},
{324, nullptr, "AttachHdlsWorkBuffer"},
{325, nullptr, "ReleaseHdlsWorkBuffer"},
{326, nullptr, "DumpHdlsNpadAssignmentState"},
{327, nullptr, "DumpHdlsStates"},
{328, nullptr, "ApplyHdlsNpadAssignmentState"},
{329, nullptr, "ApplyHdlsStateList"},
{330, nullptr, "AttachHdlsVirtualDevice"},
{331, nullptr, "DetachHdlsVirtualDevice"},
{332, nullptr, "SetHdlsState"},
{350, nullptr, "AddRegisteredDevice"},
{400, nullptr, "DisableExternalMcuOnNxDevice"},
{401, nullptr, "DisableRailDeviceFiltering"},
@@ -825,6 +838,7 @@ public:
{131, nullptr, "ActivateSleepButton"},
{141, nullptr, "AcquireCaptureButtonEventHandle"},
{151, nullptr, "ActivateCaptureButton"},
{161, nullptr, "GetPlatformConfig"},
{210, nullptr, "AcquireNfcDeviceUpdateEventHandle"},
{211, nullptr, "GetNpadsWithNfc"},
{212, nullptr, "AcquireNfcActivateEventHandle"},
@@ -894,6 +908,7 @@ public:
{827, nullptr, "IsAnalogStickButtonPressed"},
{828, nullptr, "IsAnalogStickInReleasePosition"},
{829, nullptr, "IsAnalogStickInCircumference"},
{830, nullptr, "SetNotificationLedPattern"},
{850, nullptr, "IsUsbFullKeyControllerEnabled"},
{851, nullptr, "EnableUsbFullKeyController"},
{852, nullptr, "IsUsbConnected"},

View File

@@ -52,9 +52,11 @@ public:
}
};
class ILocalCommunicationService final : public ServiceFramework<ILocalCommunicationService> {
class ISystemLocalCommunicationService final
: public ServiceFramework<ISystemLocalCommunicationService> {
public:
explicit ILocalCommunicationService(const char* name) : ServiceFramework{name} {
explicit ISystemLocalCommunicationService()
: ServiceFramework{"ISystemLocalCommunicationService"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "GetState"},
@@ -84,6 +86,50 @@ public:
{304, nullptr, "Disconnect"},
{400, nullptr, "InitializeSystem"},
{401, nullptr, "FinalizeSystem"},
{402, nullptr, "SetOperationMode"},
{403, nullptr, "InitializeSystem2"},
};
// clang-format on
RegisterHandlers(functions);
}
};
class IUserLocalCommunicationService final
: public ServiceFramework<IUserLocalCommunicationService> {
public:
explicit IUserLocalCommunicationService() : ServiceFramework{"IUserLocalCommunicationService"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "GetState"},
{1, nullptr, "GetNetworkInfo"},
{2, nullptr, "GetIpv4Address"},
{3, nullptr, "GetDisconnectReason"},
{4, nullptr, "GetSecurityParameter"},
{5, nullptr, "GetNetworkConfig"},
{100, nullptr, "AttachStateChangeEvent"},
{101, nullptr, "GetNetworkInfoLatestUpdate"},
{102, nullptr, "Scan"},
{103, nullptr, "ScanPrivate"},
{104, nullptr, "SetWirelessControllerRestriction"},
{200, nullptr, "OpenAccessPoint"},
{201, nullptr, "CloseAccessPoint"},
{202, nullptr, "CreateNetwork"},
{203, nullptr, "CreateNetworkPrivate"},
{204, nullptr, "DestroyNetwork"},
{205, nullptr, "Reject"},
{206, nullptr, "SetAdvertiseData"},
{207, nullptr, "SetStationAcceptPolicy"},
{208, nullptr, "AddAcceptFilterEntry"},
{209, nullptr, "ClearAcceptFilter"},
{300, nullptr, "OpenStation"},
{301, nullptr, "CloseStation"},
{302, nullptr, "Connect"},
{303, nullptr, "ConnectPrivate"},
{304, nullptr, "Disconnect"},
{400, nullptr, "Initialize"},
{401, nullptr, "Finalize"},
{402, nullptr, "SetOperationMode"},
};
// clang-format on
@@ -108,7 +154,7 @@ public:
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ILocalCommunicationService>("ISystemLocalCommunicationService");
rb.PushIpcInterface<ISystemLocalCommunicationService>();
}
};
@@ -129,7 +175,7 @@ public:
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ILocalCommunicationService>("IUserLocalCommunicationService");
rb.PushIpcInterface<IUserLocalCommunicationService>();
}
};

View File

@@ -86,6 +86,7 @@ public:
{2, &RelocatableObject::LoadNrr, "LoadNrr"},
{3, &RelocatableObject::UnloadNrr, "UnloadNrr"},
{4, &RelocatableObject::Initialize, "Initialize"},
{10, nullptr, "LoadNrrEx"},
};
// clang-format on

View File

@@ -15,12 +15,16 @@ namespace Service::NIFM {
class IScanRequest final : public ServiceFramework<IScanRequest> {
public:
explicit IScanRequest() : ServiceFramework("IScanRequest") {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "Submit"},
{1, nullptr, "IsProcessing"},
{2, nullptr, "GetResult"},
{3, nullptr, "GetSystemEventReadableHandle"},
{4, nullptr, "SetChannels"},
};
// clang-format on
RegisterHandlers(functions);
}
};

View File

@@ -45,7 +45,7 @@ public:
{114, nullptr, "AttachJid"},
{115, nullptr, "DetachJid"},
{201, nullptr, "RequestChangeStateForceTimed"},
{102, nullptr, "RequestChangeStateForceAsync"},
{202, nullptr, "RequestChangeStateForceAsync"},
};
// clang-format on
@@ -73,6 +73,7 @@ public:
{103, nullptr, "GetState"},
{104, nullptr, "GetStatistics"},
{111, nullptr, "GetJid"},
{120, nullptr, "CreateNotificationReceiver"},
};
// clang-format on

View File

@@ -12,10 +12,10 @@ namespace Service::PCTL {
class IParentalControlService final : public ServiceFramework<IParentalControlService> {
public:
IParentalControlService() : ServiceFramework("IParentalControlService") {
// clang-format off
static const FunctionInfo functions[] = {
{1, &IParentalControlService::Initialize, "Initialize"},
{1001, &IParentalControlService::CheckFreeCommunicationPermission,
"CheckFreeCommunicationPermission"},
{1001, &IParentalControlService::CheckFreeCommunicationPermission, "CheckFreeCommunicationPermission"},
{1002, nullptr, "ConfirmLaunchApplicationPermission"},
{1003, nullptr, "ConfirmResumeApplicationPermission"},
{1004, nullptr, "ConfirmSnsPostPermission"},
@@ -30,6 +30,7 @@ public:
{1013, nullptr, "ConfirmStereoVisionPermission"},
{1014, nullptr, "ConfirmPlayableApplicationVideoOld"},
{1015, nullptr, "ConfirmPlayableApplicationVideo"},
{1016, nullptr, "ConfirmShowNewsPermission"},
{1031, nullptr, "IsRestrictionEnabled"},
{1032, nullptr, "GetSafetyLevel"},
{1033, nullptr, "SetSafetyLevel"},
@@ -45,6 +46,7 @@ public:
{1045, nullptr, "UpdateFreeCommunicationApplicationList"},
{1046, nullptr, "DisableFeaturesForReset"},
{1047, nullptr, "NotifyApplicationDownloadStarted"},
{1048, nullptr, "NotifyNetworkProfileCreated"},
{1061, nullptr, "ConfirmStereoVisionRestrictionConfigurable"},
{1062, nullptr, "GetStereoVisionRestriction"},
{1063, nullptr, "SetStereoVisionRestriction"},
@@ -63,6 +65,7 @@ public:
{1411, nullptr, "GetPairingAccountInfo"},
{1421, nullptr, "GetAccountNickname"},
{1424, nullptr, "GetAccountState"},
{1425, nullptr, "RequestPostEvents"},
{1432, nullptr, "GetSynchronizationEvent"},
{1451, nullptr, "StartPlayTimer"},
{1452, nullptr, "StopPlayTimer"},

View File

@@ -42,15 +42,18 @@ private:
class DebugMonitor final : public ServiceFramework<DebugMonitor> {
public:
explicit DebugMonitor() : ServiceFramework{"pm:dmnt"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "IsDebugMode"},
{1, nullptr, "GetDebugProcesses"},
{2, nullptr, "StartDebugProcess"},
{3, nullptr, "GetTitlePid"},
{4, nullptr, "EnableDebugForTitleId"},
{5, nullptr, "GetApplicationPid"},
{6, nullptr, "EnableDebugForApplication"},
{0, nullptr, "GetDebugProcesses"},
{1, nullptr, "StartDebugProcess"},
{2, nullptr, "GetTitlePid"},
{3, nullptr, "EnableDebugForTitleId"},
{4, nullptr, "GetApplicationPid"},
{5, nullptr, "EnableDebugForApplication"},
{6, nullptr, "DisableDebug"},
};
// clang-format on
RegisterHandlers(functions);
}
};
@@ -68,6 +71,7 @@ public:
class Shell final : public ServiceFramework<Shell> {
public:
explicit Shell() : ServiceFramework{"pm:shell"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "LaunchProcess"},
{1, nullptr, "TerminateProcessByPid"},
@@ -77,7 +81,10 @@ public:
{5, nullptr, "NotifyBootFinished"},
{6, nullptr, "GetApplicationPid"},
{7, nullptr, "BoostSystemMemoryResourceLimit"},
{8, nullptr, "EnableAdditionalSystemThreads"},
};
// clang-format on
RegisterHandlers(functions);
}
};

View File

@@ -116,6 +116,7 @@ void SET::GetLanguageCode(Kernel::HLERequestContext& ctx) {
}
SET::SET() : ServiceFramework("set") {
// clang-format off
static const FunctionInfo functions[] = {
{0, &SET::GetLanguageCode, "GetLanguageCode"},
{1, &SET::GetAvailableLanguageCodes, "GetAvailableLanguageCodes"},
@@ -126,7 +127,10 @@ SET::SET() : ServiceFramework("set") {
{6, &SET::GetAvailableLanguageCodeCount2, "GetAvailableLanguageCodeCount2"},
{7, nullptr, "GetKeyCodeMap"},
{8, nullptr, "GetQuestFlag"},
{9, nullptr, "GetKeyCodeMap2"},
};
// clang-format on
RegisterHandlers(functions);
}

View File

@@ -40,7 +40,7 @@ SET_CAL::SET_CAL() : ServiceFramework("set:cal") {
{30, nullptr, "GetAmiiboEcqvBlsCertificate"},
{31, nullptr, "GetAmiiboEcqvBlsRootCertificate"},
{32, nullptr, "GetUsbTypeCPowerSourceCircuitVersion"},
{33, nullptr, "GetBatteryVersion"},
{41, nullptr, "GetBatteryVersion"},
};
RegisterHandlers(functions);
}

View File

@@ -104,6 +104,7 @@ void SET_SYS::SetColorSetId(Kernel::HLERequestContext& ctx) {
}
SET_SYS::SET_SYS() : ServiceFramework("set:sys") {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "SetLanguageCode"},
{1, nullptr, "SetNetworkSettings"},
@@ -252,7 +253,33 @@ SET_SYS::SET_SYS() : ServiceFramework("set:sys") {
{147, nullptr, "GetConsoleSixAxisSensorAngularAcceleration"},
{148, nullptr, "SetConsoleSixAxisSensorAngularAcceleration"},
{149, nullptr, "GetRebootlessSystemUpdateVersion"},
{150, nullptr, "GetDeviceTimeZoneLocationUpdatedTime"},
{151, nullptr, "SetDeviceTimeZoneLocationUpdatedTime"},
{152, nullptr, "GetUserSystemClockAutomaticCorrectionUpdatedTime"},
{153, nullptr, "SetUserSystemClockAutomaticCorrectionUpdatedTime"},
{154, nullptr, "GetAccountOnlineStorageSettings"},
{155, nullptr, "SetAccountOnlineStorageSettings"},
{156, nullptr, "GetPctlReadyFlag"},
{157, nullptr, "SetPctlReadyFlag"},
{162, nullptr, "GetPtmBatteryVersion"},
{163, nullptr, "SetPtmBatteryVersion"},
{164, nullptr, "GetUsb30HostEnableFlag"},
{165, nullptr, "SetUsb30HostEnableFlag"},
{166, nullptr, "GetUsb30DeviceEnableFlag"},
{167, nullptr, "SetUsb30DeviceEnableFlag"},
{168, nullptr, "GetThemeId"},
{169, nullptr, "SetThemeId"},
{170, nullptr, "GetChineseTraditionalInputMethod"},
{171, nullptr, "SetChineseTraditionalInputMethod"},
{172, nullptr, "GetPtmCycleCountReliability"},
{173, nullptr, "SetPtmCycleCountReliability"},
{175, nullptr, "GetThemeSettings"},
{176, nullptr, "SetThemeSettings"},
{177, nullptr, "GetThemeKey"},
{178, nullptr, "SetThemeKey"},
};
// clang-format on
RegisterHandlers(functions);
}

View File

@@ -73,6 +73,7 @@ void BSD::Close(Kernel::HLERequestContext& ctx) {
}
BSD::BSD(const char* name) : ServiceFramework(name) {
// clang-format off
static const FunctionInfo functions[] = {
{0, &BSD::RegisterClient, "RegisterClient"},
{1, &BSD::StartMonitoring, "StartMonitoring"},
@@ -105,7 +106,11 @@ BSD::BSD(const char* name) : ServiceFramework(name) {
{28, nullptr, "GetResourceStatistics"},
{29, nullptr, "RecvMMsg"},
{30, nullptr, "SendMMsg"},
{31, nullptr, "EventFd"},
{32, nullptr, "RegisterResourceStatisticsName"},
};
// clang-format on
RegisterHandlers(functions);
}

View File

@@ -103,6 +103,8 @@ public:
{4, nullptr, "DebugIoctl"},
{5, &SSL::SetInterfaceVersion, "SetInterfaceVersion"},
{6, nullptr, "FlushSessionCache"},
{7, nullptr, "SetDebugOption"},
{8, nullptr, "GetDebugOption"},
};
// clang-format on

View File

@@ -8,6 +8,7 @@ namespace Service::Time {
Time::Time(std::shared_ptr<Module> time, const char* name)
: Module::Interface(std::move(time), name) {
// clang-format off
static const FunctionInfo functions[] = {
{0, &Time::GetStandardUserSystemClock, "GetStandardUserSystemClock"},
{1, &Time::GetStandardNetworkSystemClock, "GetStandardNetworkSystemClock"},
@@ -15,18 +16,23 @@ Time::Time(std::shared_ptr<Module> time, const char* name)
{3, &Time::GetTimeZoneService, "GetTimeZoneService"},
{4, &Time::GetStandardLocalSystemClock, "GetStandardLocalSystemClock"},
{5, nullptr, "GetEphemeralNetworkSystemClock"},
{20, nullptr, "GetSharedMemoryNativeHandle"},
{30, nullptr, "GetStandardNetworkClockOperationEventReadableHandle"},
{31, nullptr, "GetEphemeralNetworkClockOperationEventReadableHandle"},
{50, nullptr, "SetStandardSteadyClockInternalOffset"},
{100, nullptr, "IsStandardUserSystemClockAutomaticCorrectionEnabled"},
{101, nullptr, "SetStandardUserSystemClockAutomaticCorrectionEnabled"},
{102, nullptr, "GetStandardUserSystemClockInitialYear"},
{200, nullptr, "IsStandardNetworkSystemClockAccuracySufficient"},
{201, nullptr, "GetStandardUserSystemClockAutomaticCorrectionUpdatedTime"},
{300, nullptr, "CalculateMonotonicSystemClockBaseTimePoint"},
{400, &Time::GetClockSnapshot, "GetClockSnapshot"},
{401, nullptr, "GetClockSnapshotFromSystemClockContext"},
{500, &Time::CalculateStandardUserSystemClockDifferenceByUser,
"CalculateStandardUserSystemClockDifferenceByUser"},
{500, &Time::CalculateStandardUserSystemClockDifferenceByUser, "CalculateStandardUserSystemClockDifferenceByUser"},
{501, nullptr, "CalculateSpanBetween"},
};
// clang-format on
RegisterHandlers(functions);
}

View File

@@ -86,25 +86,29 @@ FileType AppLoader_DeconstructedRomDirectory::IdentifyType(const FileSys::Virtua
return FileType::Error;
}
ResultStatus AppLoader_DeconstructedRomDirectory::Load(Kernel::Process& process) {
AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirectory::Load(
Kernel::Process& process) {
if (is_loaded) {
return ResultStatus::ErrorAlreadyLoaded;
return {ResultStatus::ErrorAlreadyLoaded, {}};
}
if (dir == nullptr) {
if (file == nullptr)
return ResultStatus::ErrorNullFile;
if (file == nullptr) {
return {ResultStatus::ErrorNullFile, {}};
}
dir = file->GetContainingDirectory();
}
// Read meta to determine title ID
FileSys::VirtualFile npdm = dir->GetFile("main.npdm");
if (npdm == nullptr)
return ResultStatus::ErrorMissingNPDM;
if (npdm == nullptr) {
return {ResultStatus::ErrorMissingNPDM, {}};
}
ResultStatus result = metadata.Load(npdm);
const ResultStatus result = metadata.Load(npdm);
if (result != ResultStatus::Success) {
return result;
return {result, {}};
}
if (override_update) {
@@ -114,23 +118,24 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(Kernel::Process& process)
// Reread in case PatchExeFS affected the main.npdm
npdm = dir->GetFile("main.npdm");
if (npdm == nullptr)
return ResultStatus::ErrorMissingNPDM;
if (npdm == nullptr) {
return {ResultStatus::ErrorMissingNPDM, {}};
}
ResultStatus result2 = metadata.Load(npdm);
const ResultStatus result2 = metadata.Load(npdm);
if (result2 != ResultStatus::Success) {
return result2;
return {result2, {}};
}
metadata.Print();
const FileSys::ProgramAddressSpaceType arch_bits{metadata.GetAddressSpaceType()};
if (arch_bits == FileSys::ProgramAddressSpaceType::Is32Bit ||
arch_bits == FileSys::ProgramAddressSpaceType::Is32BitNoMap) {
return ResultStatus::Error32BitISA;
return {ResultStatus::Error32BitISA, {}};
}
if (process.LoadFromMetadata(metadata).IsError()) {
return ResultStatus::ErrorUnableToParseKernelMetadata;
return {ResultStatus::ErrorUnableToParseKernelMetadata, {}};
}
const FileSys::PatchManager pm(metadata.GetTitleID());
@@ -150,7 +155,7 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(Kernel::Process& process)
const auto tentative_next_load_addr =
AppLoader_NSO::LoadModule(process, *module_file, load_addr, should_pass_arguments, pm);
if (!tentative_next_load_addr) {
return ResultStatus::ErrorLoadingNSO;
return {ResultStatus::ErrorLoadingNSO, {}};
}
next_load_addr = *tentative_next_load_addr;
@@ -159,8 +164,6 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(Kernel::Process& process)
GDBStub::RegisterModule(module, load_addr, next_load_addr - 1, false);
}
process.Run(base_address, metadata.GetMainThreadPriority(), metadata.GetMainThreadStackSize());
// Find the RomFS by searching for a ".romfs" file in this directory
const auto& files = dir->GetFiles();
const auto romfs_iter =
@@ -175,7 +178,8 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(Kernel::Process& process)
}
is_loaded = true;
return ResultStatus::Success;
return {ResultStatus::Success,
LoadParameters{metadata.GetMainThreadPriority(), metadata.GetMainThreadStackSize()}};
}
ResultStatus AppLoader_DeconstructedRomDirectory::ReadRomFS(FileSys::VirtualFile& dir) {

View File

@@ -37,7 +37,7 @@ public:
return IdentifyType(file);
}
ResultStatus Load(Kernel::Process& process) override;
LoadResult Load(Kernel::Process& process) override;
ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override;
ResultStatus ReadIcon(std::vector<u8>& buffer) override;

View File

@@ -382,13 +382,15 @@ FileType AppLoader_ELF::IdentifyType(const FileSys::VirtualFile& file) {
return FileType::Error;
}
ResultStatus AppLoader_ELF::Load(Kernel::Process& process) {
if (is_loaded)
return ResultStatus::ErrorAlreadyLoaded;
AppLoader_ELF::LoadResult AppLoader_ELF::Load(Kernel::Process& process) {
if (is_loaded) {
return {ResultStatus::ErrorAlreadyLoaded, {}};
}
std::vector<u8> buffer = file->ReadAllBytes();
if (buffer.size() != file->GetSize())
return ResultStatus::ErrorIncorrectELFFileSize;
if (buffer.size() != file->GetSize()) {
return {ResultStatus::ErrorIncorrectELFFileSize, {}};
}
const VAddr base_address = process.VMManager().GetCodeRegionBaseAddress();
ElfReader elf_reader(&buffer[0]);
@@ -396,10 +398,9 @@ ResultStatus AppLoader_ELF::Load(Kernel::Process& process) {
const VAddr entry_point = codeset.entrypoint;
process.LoadModule(std::move(codeset), entry_point);
process.Run(entry_point, 48, Memory::DEFAULT_STACK_SIZE);
is_loaded = true;
return ResultStatus::Success;
return {ResultStatus::Success, LoadParameters{48, Memory::DEFAULT_STACK_SIZE}};
}
} // namespace Loader

View File

@@ -26,7 +26,7 @@ public:
return IdentifyType(file);
}
ResultStatus Load(Kernel::Process& process) override;
LoadResult Load(Kernel::Process& process) override;
};
} // namespace Loader

View File

@@ -131,6 +131,12 @@ std::ostream& operator<<(std::ostream& os, ResultStatus status);
/// Interface for loading an application
class AppLoader : NonCopyable {
public:
struct LoadParameters {
s32 main_thread_priority;
u64 main_thread_stack_size;
};
using LoadResult = std::pair<ResultStatus, std::optional<LoadParameters>>;
explicit AppLoader(FileSys::VirtualFile file);
virtual ~AppLoader();
@@ -145,7 +151,7 @@ public:
* @param process The newly created process.
* @return The status result of the operation.
*/
virtual ResultStatus Load(Kernel::Process& process) = 0;
virtual LoadResult Load(Kernel::Process& process) = 0;
/**
* Loads the system mode that this application needs.

View File

@@ -41,31 +41,37 @@ FileType AppLoader_NAX::GetFileType() const {
return IdentifyTypeImpl(*nax);
}
ResultStatus AppLoader_NAX::Load(Kernel::Process& process) {
AppLoader_NAX::LoadResult AppLoader_NAX::Load(Kernel::Process& process) {
if (is_loaded) {
return ResultStatus::ErrorAlreadyLoaded;
return {ResultStatus::ErrorAlreadyLoaded, {}};
}
if (nax->GetStatus() != ResultStatus::Success)
return nax->GetStatus();
const auto nax_status = nax->GetStatus();
if (nax_status != ResultStatus::Success) {
return {nax_status, {}};
}
const auto nca = nax->AsNCA();
if (nca == nullptr) {
if (!Core::Crypto::KeyManager::KeyFileExists(false))
return ResultStatus::ErrorMissingProductionKeyFile;
return ResultStatus::ErrorNAXInconvertibleToNCA;
if (!Core::Crypto::KeyManager::KeyFileExists(false)) {
return {ResultStatus::ErrorMissingProductionKeyFile, {}};
}
return {ResultStatus::ErrorNAXInconvertibleToNCA, {}};
}
if (nca->GetStatus() != ResultStatus::Success)
return nca->GetStatus();
const auto nca_status = nca->GetStatus();
if (nca_status != ResultStatus::Success) {
return {nca_status, {}};
}
const auto result = nca_loader->Load(process);
if (result != ResultStatus::Success)
if (result.first != ResultStatus::Success) {
return result;
}
is_loaded = true;
return ResultStatus::Success;
return result;
}
ResultStatus AppLoader_NAX::ReadRomFS(FileSys::VirtualFile& dir) {

View File

@@ -33,7 +33,7 @@ public:
FileType GetFileType() const override;
ResultStatus Load(Kernel::Process& process) override;
LoadResult Load(Kernel::Process& process) override;
ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override;
u64 ReadRomFSIVFCOffset() const override;

View File

@@ -30,36 +30,38 @@ FileType AppLoader_NCA::IdentifyType(const FileSys::VirtualFile& file) {
return FileType::Error;
}
ResultStatus AppLoader_NCA::Load(Kernel::Process& process) {
AppLoader_NCA::LoadResult AppLoader_NCA::Load(Kernel::Process& process) {
if (is_loaded) {
return ResultStatus::ErrorAlreadyLoaded;
return {ResultStatus::ErrorAlreadyLoaded, {}};
}
const auto result = nca->GetStatus();
if (result != ResultStatus::Success) {
return result;
return {result, {}};
}
if (nca->GetType() != FileSys::NCAContentType::Program)
return ResultStatus::ErrorNCANotProgram;
if (nca->GetType() != FileSys::NCAContentType::Program) {
return {ResultStatus::ErrorNCANotProgram, {}};
}
const auto exefs = nca->GetExeFS();
if (exefs == nullptr)
return ResultStatus::ErrorNoExeFS;
if (exefs == nullptr) {
return {ResultStatus::ErrorNoExeFS, {}};
}
directory_loader = std::make_unique<AppLoader_DeconstructedRomDirectory>(exefs, true);
const auto load_result = directory_loader->Load(process);
if (load_result != ResultStatus::Success)
if (load_result.first != ResultStatus::Success) {
return load_result;
}
if (nca->GetRomFS() != nullptr && nca->GetRomFS()->GetSize() > 0)
if (nca->GetRomFS() != nullptr && nca->GetRomFS()->GetSize() > 0) {
Service::FileSystem::RegisterRomFS(std::make_unique<FileSys::RomFSFactory>(*this));
}
is_loaded = true;
return ResultStatus::Success;
return load_result;
}
ResultStatus AppLoader_NCA::ReadRomFS(FileSys::VirtualFile& dir) {

View File

@@ -33,7 +33,7 @@ public:
return IdentifyType(file);
}
ResultStatus Load(Kernel::Process& process) override;
LoadResult Load(Kernel::Process& process) override;
ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override;
u64 ReadRomFSIVFCOffset() const override;

View File

@@ -201,25 +201,25 @@ bool AppLoader_NRO::LoadNro(Kernel::Process& process, const FileSys::VfsFile& fi
return LoadNroImpl(process, file.ReadAllBytes(), file.GetName(), load_base);
}
ResultStatus AppLoader_NRO::Load(Kernel::Process& process) {
AppLoader_NRO::LoadResult AppLoader_NRO::Load(Kernel::Process& process) {
if (is_loaded) {
return ResultStatus::ErrorAlreadyLoaded;
return {ResultStatus::ErrorAlreadyLoaded, {}};
}
// Load NRO
const VAddr base_address = process.VMManager().GetCodeRegionBaseAddress();
if (!LoadNro(process, *file, base_address)) {
return ResultStatus::ErrorLoadingNRO;
return {ResultStatus::ErrorLoadingNRO, {}};
}
if (romfs != nullptr)
if (romfs != nullptr) {
Service::FileSystem::RegisterRomFS(std::make_unique<FileSys::RomFSFactory>(*this));
process.Run(base_address, Kernel::THREADPRIO_DEFAULT, Memory::DEFAULT_STACK_SIZE);
}
is_loaded = true;
return ResultStatus::Success;
return {ResultStatus::Success,
LoadParameters{Kernel::THREADPRIO_DEFAULT, Memory::DEFAULT_STACK_SIZE}};
}
ResultStatus AppLoader_NRO::ReadIcon(std::vector<u8>& buffer) {

View File

@@ -37,7 +37,7 @@ public:
return IdentifyType(file);
}
ResultStatus Load(Kernel::Process& process) override;
LoadResult Load(Kernel::Process& process) override;
ResultStatus ReadIcon(std::vector<u8>& buffer) override;
ResultStatus ReadProgramId(u64& out_program_id) override;

View File

@@ -21,8 +21,6 @@
#include "core/memory.h"
#include "core/settings.h"
#pragma optimize("", off)
namespace Loader {
namespace {
struct MODHeader {
@@ -169,22 +167,21 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process,
return load_base + image_size;
}
ResultStatus AppLoader_NSO::Load(Kernel::Process& process) {
AppLoader_NSO::LoadResult AppLoader_NSO::Load(Kernel::Process& process) {
if (is_loaded) {
return ResultStatus::ErrorAlreadyLoaded;
return {ResultStatus::ErrorAlreadyLoaded, {}};
}
// Load module
const VAddr base_address = process.VMManager().GetCodeRegionBaseAddress();
if (!LoadModule(process, *file, base_address, true)) {
return ResultStatus::ErrorLoadingNSO;
return {ResultStatus::ErrorLoadingNSO, {}};
}
LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", file->GetName(), base_address);
process.Run(base_address, Kernel::THREADPRIO_DEFAULT, Memory::DEFAULT_STACK_SIZE);
is_loaded = true;
return ResultStatus::Success;
return {ResultStatus::Success,
LoadParameters{Kernel::THREADPRIO_DEFAULT, Memory::DEFAULT_STACK_SIZE}};
}
} // namespace Loader

View File

@@ -84,7 +84,7 @@ public:
VAddr load_base, bool should_pass_arguments,
std::optional<FileSys::PatchManager> pm = {});
ResultStatus Load(Kernel::Process& process) override;
LoadResult Load(Kernel::Process& process) override;
};
} // namespace Loader

View File

@@ -72,37 +72,45 @@ FileType AppLoader_NSP::IdentifyType(const FileSys::VirtualFile& file) {
return FileType::Error;
}
ResultStatus AppLoader_NSP::Load(Kernel::Process& process) {
AppLoader_NSP::LoadResult AppLoader_NSP::Load(Kernel::Process& process) {
if (is_loaded) {
return ResultStatus::ErrorAlreadyLoaded;
return {ResultStatus::ErrorAlreadyLoaded, {}};
}
if (title_id == 0)
return ResultStatus::ErrorNSPMissingProgramNCA;
if (title_id == 0) {
return {ResultStatus::ErrorNSPMissingProgramNCA, {}};
}
if (nsp->GetStatus() != ResultStatus::Success)
return nsp->GetStatus();
const auto nsp_status = nsp->GetStatus();
if (nsp_status != ResultStatus::Success) {
return {nsp_status, {}};
}
if (nsp->GetProgramStatus(title_id) != ResultStatus::Success)
return nsp->GetProgramStatus(title_id);
const auto nsp_program_status = nsp->GetProgramStatus(title_id);
if (nsp_program_status != ResultStatus::Success) {
return {nsp_program_status, {}};
}
if (nsp->GetNCA(title_id, FileSys::ContentRecordType::Program) == nullptr) {
if (!Core::Crypto::KeyManager::KeyFileExists(false))
return ResultStatus::ErrorMissingProductionKeyFile;
return ResultStatus::ErrorNSPMissingProgramNCA;
if (!Core::Crypto::KeyManager::KeyFileExists(false)) {
return {ResultStatus::ErrorMissingProductionKeyFile, {}};
}
return {ResultStatus::ErrorNSPMissingProgramNCA, {}};
}
const auto result = secondary_loader->Load(process);
if (result != ResultStatus::Success)
if (result.first != ResultStatus::Success) {
return result;
}
FileSys::VirtualFile update_raw;
if (ReadUpdateRaw(update_raw) == ResultStatus::Success && update_raw != nullptr)
if (ReadUpdateRaw(update_raw) == ResultStatus::Success && update_raw != nullptr) {
Service::FileSystem::SetPackedUpdate(std::move(update_raw));
}
is_loaded = true;
return ResultStatus::Success;
return result;
}
ResultStatus AppLoader_NSP::ReadRomFS(FileSys::VirtualFile& file) {

View File

@@ -35,7 +35,7 @@ public:
return IdentifyType(file);
}
ResultStatus Load(Kernel::Process& process) override;
LoadResult Load(Kernel::Process& process) override;
ResultStatus ReadRomFS(FileSys::VirtualFile& file) override;
u64 ReadRomFSIVFCOffset() const override;

View File

@@ -48,31 +48,35 @@ FileType AppLoader_XCI::IdentifyType(const FileSys::VirtualFile& file) {
return FileType::Error;
}
ResultStatus AppLoader_XCI::Load(Kernel::Process& process) {
AppLoader_XCI::LoadResult AppLoader_XCI::Load(Kernel::Process& process) {
if (is_loaded) {
return ResultStatus::ErrorAlreadyLoaded;
return {ResultStatus::ErrorAlreadyLoaded, {}};
}
if (xci->GetStatus() != ResultStatus::Success)
return xci->GetStatus();
if (xci->GetStatus() != ResultStatus::Success) {
return {xci->GetStatus(), {}};
}
if (xci->GetProgramNCAStatus() != ResultStatus::Success)
return xci->GetProgramNCAStatus();
if (xci->GetProgramNCAStatus() != ResultStatus::Success) {
return {xci->GetProgramNCAStatus(), {}};
}
if (!xci->HasProgramNCA() && !Core::Crypto::KeyManager::KeyFileExists(false))
return ResultStatus::ErrorMissingProductionKeyFile;
if (!xci->HasProgramNCA() && !Core::Crypto::KeyManager::KeyFileExists(false)) {
return {ResultStatus::ErrorMissingProductionKeyFile, {}};
}
const auto result = nca_loader->Load(process);
if (result != ResultStatus::Success)
if (result.first != ResultStatus::Success) {
return result;
}
FileSys::VirtualFile update_raw;
if (ReadUpdateRaw(update_raw) == ResultStatus::Success && update_raw != nullptr)
if (ReadUpdateRaw(update_raw) == ResultStatus::Success && update_raw != nullptr) {
Service::FileSystem::SetPackedUpdate(std::move(update_raw));
}
is_loaded = true;
return ResultStatus::Success;
return result;
}
ResultStatus AppLoader_XCI::ReadRomFS(FileSys::VirtualFile& file) {

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